diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..895eac4 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,10 @@ +[build] + +# https://docs.rs/tracing/latest/tracing/field/index.html#using-valuable +rustflags = ["--cfg", "tracing_unstable"] + +[env] +TS_RS_EXPORT_DIR = { value = "app/packages/payy/src/ts-rs-bindings", relative = true } + +[alias] +xtask = "run --bin xtask -q --" diff --git a/.gitattributes b/.gitattributes index 865af6a..73bfcf0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,59 @@ -/fixtures/params/*.srs filter=lfs diff=lfs merge=lfs -text -audits/kalos_2024_02_23.pdf filter=lfs diff=lfs merge=lfs -text +# Smart contract binaries - suppress diffs +eth/contracts/**/*.bin binary -diff + +# Generated Solidity verifiers (90-97 KB each, auto-generated from Noir) +eth/noir/*.sol -diff + +# Hardhat/Solidity artifacts and generated bindings +eth/artifacts/**/*.json linguist-generated=true -diff +eth/artifacts/**/*.d.ts linguist-generated=true -diff +eth/artifacts/contracts/**/*.sol linguist-generated=true -diff + +# Noir compiled programs (large JSON or binary, up to 1.6 MB) +fixtures/programs/* -diff + +# Verification keys and cryptographic data +fixtures/keys/* -diff +fixtures/keys/*_key_fields.json -diff + +# Proof files +fixtures/proofs/*.proof -diff +fixtures/circuits/*.proof -diff +pkg/node/tests/cache/*.proof -diff + +# Cryptographic parameters +fixtures/params/*.dat -diff + +# Insta snapshot files (keep diffs) +**/snapshots/*.snap text +linting/tests/__snapshots__/*.yml text + +# Test fixtures (includes 1.8 MB large_wallet_mateo.json) +pkg/wallet-data-dep/tests/fixtures/*.json -diff +pkg/bungee-client-http/fixtures/*.json -diff + +# Package lock files (auto-generated dependencies) +yarn.lock linguist-generated=true +package-lock.json linguist-generated=true +Cargo.lock linguist-generated=true +bun.lock linguist-generated=true +bun.lockb binary linguist-generated=true +flake.lock linguist-generated=true + +# Generated source code +pkg/database/src/schema.rs linguist-generated=true +**/ts-rs-bindings/*.ts linguist-generated=true +.github/actions/**/dist/*.js linguist-generated=true -diff + +# Large generated/reference data +app/packages/emoji-shortcode-mapping/*.json -diff +app/packages/link/src/app/img/note.svg -diff + +# Contract compiler artifacts +eth/contracts/noir/*.linkrefs.json -diff + +# Binary assets +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary diff --git a/.github/actions/cloud-cache/.gitignore b/.github/actions/cloud-cache/.gitignore new file mode 100644 index 0000000..1515f0e --- /dev/null +++ b/.github/actions/cloud-cache/.gitignore @@ -0,0 +1,3 @@ +node_modules +!dist/index.js +!dist/post/index.js diff --git a/.github/actions/cloud-cache/action.yml b/.github/actions/cloud-cache/action.yml new file mode 100644 index 0000000..200e199 --- /dev/null +++ b/.github/actions/cloud-cache/action.yml @@ -0,0 +1,88 @@ +name: 'Cloud Cache' +description: 'Restores and saves a directory to cloud storage as a cache (tar.zst compressed), using a primary key and fallback keys. Supports GCS and S3.' +inputs: + provider: + description: 'Storage provider: gcs or s3' + required: false + default: 'gcs' + gcs-key: + description: 'Base64 encoded JSON service account key for GCS' + required: false + s3-access-key: + description: 'Access key for S3' + required: false + s3-secret-key: + description: 'Secret key for S3' + required: false + s3-endpoint: + description: 'Endpoint URL for S3 (for non-AWS S3-compatible services)' + required: false + s3-region: + description: 'Region for S3 (default: auto)' + required: false + default: 'auto' + bucket: + description: 'Bucket name (GCS or S3)' + required: true + prefix: + description: 'Prefix path in the bucket (optional)' + required: false + default: '' + primary-key: + description: 'Primary key for the cache (without .tar.zst extension)' + required: false + default: '' + primary-key-generator: + description: 'Shell script (bash) to generate the primary key, appending the key (without .tar.zst extension) to $PRIMARY_KEY' + required: false + default: '' + fallback-keys: + description: 'Comma-separated list of fallback keys to check (in order of priority, without .tar.zst extension)' + required: false + default: '' + fallback-key-generator: + description: 'Shell script (bash) to generate fallback keys dynamically, appending one key (without .tar.zst extension) per line to $FALLBACK_KEYS' + required: false + default: '' + local-path: + description: 'Local directory path to restore the cache to and save from' + required: true + skip-upload: + description: 'Skip the cache upload' + required: false + default: 'false' + skip-download: + description: 'Skip restoring (downloading) the cache' + required: false + default: 'false' + retries: + description: 'Total retry attempts per part (download/upload)' + required: false + default: '3' + retry-delay-ms: + description: 'Base backoff in ms for retries (jittered)' + required: false + default: '100' + download-part-count: + description: 'Target number of download parts when restoring (>=1)' + required: false + default: '128' + download-concurrency: + description: 'Max concurrent download parts' + required: false + default: '32' + upload-concurrency: + description: 'Max concurrent S3 upload parts (multipart)' + required: false + default: '32' +outputs: + path: + description: 'Local directory path for the cache' + cache-hit: + description: 'True if exact cache hit on primary key' + restored: + description: 'True if a cache was restored (any key matched, downloaded and extracted)' +runs: + using: 'node16' + main: 'dist/index.js' + post: 'dist/post/index.js' diff --git a/.github/actions/cloud-cache/build.sh b/.github/actions/cloud-cache/build.sh new file mode 100755 index 0000000..a258a3c --- /dev/null +++ b/.github/actions/cloud-cache/build.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +alias ncc="npx @vercel/ncc" + +ncc build index.js -o dist +ncc build post.js --out dist/post diff --git a/.github/actions/cloud-cache/dist/index.js b/.github/actions/cloud-cache/dist/index.js new file mode 100644 index 0000000..2248e71 --- /dev/null +++ b/.github/actions/cloud-cache/dist/index.js @@ -0,0 +1,108842 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 44914: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.issue = exports.issueCommand = void 0; +const os = __importStar(__nccwpck_require__(70857)); +const utils_1 = __nccwpck_require__(30302); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return (0, utils_1.toCommandValue)(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return (0, utils_1.toCommandValue)(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 37484: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.platform = exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = exports.markdownSummary = exports.summary = exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; +const command_1 = __nccwpck_require__(44914); +const file_command_1 = __nccwpck_require__(24753); +const utils_1 = __nccwpck_require__(30302); +const os = __importStar(__nccwpck_require__(70857)); +const path = __importStar(__nccwpck_require__(16928)); +const oidc_utils_1 = __nccwpck_require__(35306); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode || (exports.ExitCode = ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = (0, utils_1.toCommandValue)(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + return (0, file_command_1.issueFileCommand)('ENV', (0, file_command_1.prepareKeyValueMessage)(name, val)); + } + (0, command_1.issueCommand)('set-env', { name }, convertedVal); +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + (0, command_1.issueCommand)('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + (0, file_command_1.issueFileCommand)('PATH', inputPath); + } + else { + (0, command_1.issueCommand)('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); +} +exports.getMultilineInput = getMultilineInput; +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +exports.getBooleanInput = getBooleanInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return (0, file_command_1.issueFileCommand)('OUTPUT', (0, file_command_1.prepareKeyValueMessage)(name, value)); + } + process.stdout.write(os.EOL); + (0, command_1.issueCommand)('set-output', { name }, (0, utils_1.toCommandValue)(value)); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + (0, command_1.issue)('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + (0, command_1.issueCommand)('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function error(message, properties = {}) { + (0, command_1.issueCommand)('error', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds a warning issue + * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function warning(message, properties = {}) { + (0, command_1.issueCommand)('warning', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + (0, command_1.issueCommand)('notice', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + (0, command_1.issue)('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + (0, command_1.issue)('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return (0, file_command_1.issueFileCommand)('STATE', (0, file_command_1.prepareKeyValueMessage)(name, value)); + } + (0, command_1.issueCommand)('save-state', { name }, (0, utils_1.toCommandValue)(value)); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); +} +exports.getIDToken = getIDToken; +/** + * Summary exports + */ +var summary_1 = __nccwpck_require__(71847); +Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); +/** + * @deprecated use core.summary + */ +var summary_2 = __nccwpck_require__(71847); +Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); +/** + * Path exports + */ +var path_utils_1 = __nccwpck_require__(31976); +Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); +Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); +Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); +/** + * Platform utilities exports + */ +exports.platform = __importStar(__nccwpck_require__(18968)); +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 24753: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// For internal use, subject to change. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +const crypto = __importStar(__nccwpck_require__(76982)); +const fs = __importStar(__nccwpck_require__(79896)); +const os = __importStar(__nccwpck_require__(70857)); +const utils_1 = __nccwpck_require__(30302); +function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os.EOL}`, { + encoding: 'utf8' + }); +} +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${crypto.randomUUID()}`; + const convertedValue = (0, utils_1.toCommandValue)(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; +//# sourceMappingURL=file-command.js.map + +/***/ }), + +/***/ 35306: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OidcClient = void 0; +const http_client_1 = __nccwpck_require__(54844); +const auth_1 = __nccwpck_require__(44552); +const core_1 = __nccwpck_require__(37484); +class OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + (0, core_1.debug)(`ID token url is ${id_token_url}`); + const id_token = yield OidcClient.getCall(id_token_url); + (0, core_1.setSecret)(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +exports.OidcClient = OidcClient; +//# sourceMappingURL=oidc-utils.js.map + +/***/ }), + +/***/ 31976: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; +const path = __importStar(__nccwpck_require__(16928)); +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +exports.toPosixPath = toPosixPath; +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +exports.toWin32Path = toWin32Path; +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +exports.toPlatformPath = toPlatformPath; +//# sourceMappingURL=path-utils.js.map + +/***/ }), + +/***/ 18968: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getDetails = exports.isLinux = exports.isMacOS = exports.isWindows = exports.arch = exports.platform = void 0; +const os_1 = __importDefault(__nccwpck_require__(70857)); +const exec = __importStar(__nccwpck_require__(95236)); +const getWindowsInfo = () => __awaiter(void 0, void 0, void 0, function* () { + const { stdout: version } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', undefined, { + silent: true + }); + const { stdout: name } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', undefined, { + silent: true + }); + return { + name: name.trim(), + version: version.trim() + }; +}); +const getMacOsInfo = () => __awaiter(void 0, void 0, void 0, function* () { + var _a, _b, _c, _d; + const { stdout } = yield exec.getExecOutput('sw_vers', undefined, { + silent: true + }); + const version = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ''; + const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ''; + return { + name, + version + }; +}); +const getLinuxInfo = () => __awaiter(void 0, void 0, void 0, function* () { + const { stdout } = yield exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], { + silent: true + }); + const [name, version] = stdout.trim().split('\n'); + return { + name, + version + }; +}); +exports.platform = os_1.default.platform(); +exports.arch = os_1.default.arch(); +exports.isWindows = exports.platform === 'win32'; +exports.isMacOS = exports.platform === 'darwin'; +exports.isLinux = exports.platform === 'linux'; +function getDetails() { + return __awaiter(this, void 0, void 0, function* () { + return Object.assign(Object.assign({}, (yield (exports.isWindows + ? getWindowsInfo() + : exports.isMacOS + ? getMacOsInfo() + : getLinuxInfo()))), { platform: exports.platform, + arch: exports.arch, + isWindows: exports.isWindows, + isMacOS: exports.isMacOS, + isLinux: exports.isLinux }); + }); +} +exports.getDetails = getDetails; +//# sourceMappingURL=platform.js.map + +/***/ }), + +/***/ 71847: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __nccwpck_require__(70857); +const fs_1 = __nccwpck_require__(79896); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +exports.markdownSummary = _summary; +exports.summary = _summary; +//# sourceMappingURL=summary.js.map + +/***/ }), + +/***/ 30302: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toCommandProperties = exports.toCommandValue = void 0; +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 95236: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getExecOutput = exports.exec = void 0; +const string_decoder_1 = __nccwpck_require__(13193); +const tr = __importStar(__nccwpck_require__(6665)); +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code + */ +function exec(commandLine, args, options) { + return __awaiter(this, void 0, void 0, function* () { + const commandArgs = tr.argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + // Path to tool to execute should be first arg + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new tr.ToolRunner(toolPath, args, options); + return runner.exec(); + }); +} +exports.exec = exec; +/** + * Exec a command and get the output. + * Output will be streamed to the live console. + * Returns promise with the exit code and collected stdout and stderr + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code, stdout, and stderr + */ +function getExecOutput(commandLine, args, options) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + let stdout = ''; + let stderr = ''; + //Using string decoder covers the case where a mult-byte character is split + const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); + const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + //flush any remaining characters + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); +} +exports.getExecOutput = getExecOutput; +//# sourceMappingURL=exec.js.map + +/***/ }), + +/***/ 6665: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.argStringToArray = exports.ToolRunner = void 0; +const os = __importStar(__nccwpck_require__(70857)); +const events = __importStar(__nccwpck_require__(24434)); +const child = __importStar(__nccwpck_require__(35317)); +const path = __importStar(__nccwpck_require__(16928)); +const io = __importStar(__nccwpck_require__(94994)); +const ioUtil = __importStar(__nccwpck_require__(75207)); +const timers_1 = __nccwpck_require__(53557); +/* eslint-disable @typescript-eslint/unbound-method */ +const IS_WINDOWS = process.platform === 'win32'; +/* + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. + */ +class ToolRunner extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; + } + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } + } + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool + if (IS_WINDOWS) { + // Windows + cmd file + if (this._isCmdFile()) { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows + verbatim + else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows (regular) + else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } + } + } + else { + // OSX/Linux - this can likely be improved with some form of quoting. + // creating processes on Unix is fundamentally different than Windows. + // on Unix, execvp() takes an arg array. + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + return cmd; + } + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n = s.indexOf(os.EOL); + while (n > -1) { + const line = s.substring(0, n); + onLine(line); + // the rest of the string ... + s = s.substring(n + os.EOL.length); + n = s.indexOf(os.EOL); + } + return s; + } + catch (err) { + // streaming lines to console is best effort. Don't fail a build. + this._debug(`error processing line. Failed with error ${err}`); + return ''; + } + } + _getSpawnFileName() { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + return process.env['COMSPEC'] || 'cmd.exe'; + } + } + return this.toolPath; + } + _getSpawnArgs(options) { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += ' '; + argline += options.windowsVerbatimArguments + ? a + : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; + } + } + return this.args; + } + _endsWith(str, end) { + return str.endsWith(end); + } + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return (this._endsWith(upperToolPath, '.CMD') || + this._endsWith(upperToolPath, '.BAT')); + } + _windowsQuoteCmdArg(arg) { + // for .exe, apply the normal quoting rules that libuv applies + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + // otherwise apply quoting rules specific to the cmd.exe command line parser. + // the libuv rules are generic and are not designed specifically for cmd.exe + // command line parser. + // + // for a detailed description of the cmd.exe command line parser, refer to + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 + // need quotes for empty arg + if (!arg) { + return '""'; + } + // determine whether the arg needs to be quoted + const cmdSpecialChars = [ + ' ', + '\t', + '&', + '(', + ')', + '[', + ']', + '{', + '}', + '^', + '=', + ';', + '!', + "'", + '+', + ',', + '`', + '~', + '|', + '<', + '>', + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some(x => x === char)) { + needsQuotes = true; + break; + } + } + // short-circuit if quotes not needed + if (!needsQuotes) { + return arg; + } + // the following quoting rules are very similar to the rules that by libuv applies. + // + // 1) wrap the string in quotes + // + // 2) double-up quotes - i.e. " => "" + // + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately + // doesn't work well with a cmd.exe command line. + // + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. + // for example, the command line: + // foo.exe "myarg:""my val""" + // is parsed by a .NET console app into an arg array: + // [ "myarg:\"my val\"" ] + // which is the same end result when applying libuv quoting rules. although the actual + // command line from libuv quoting rules would look like: + // foo.exe "myarg:\"my val\"" + // + // 3) double-up slashes that precede a quote, + // e.g. hello \world => "hello \world" + // hello\"world => "hello\\""world" + // hello\\"world => "hello\\\\""world" + // hello world\ => "hello world\\" + // + // technically this is not required for a cmd.exe command line, or the batch argument parser. + // the reasons for including this as a .cmd quoting rule are: + // + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. + // + // b) it's what we've been doing previously (by deferring to node default behavior) and we + // haven't heard any complaints about that aspect. + // + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be + // escaped when used on the command line directly - even though within a .cmd file % can be escaped + // by using %%. + // + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. + // + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args + // to an external program. + // + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. + // % can be escaped within a .cmd file. + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; // double the slash + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; // double the quote + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _uvQuoteCmdArg(arg) { + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments + // is used. + // + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), + // pasting copyright notice from Node within this function: + // + // Copyright Joyent, Inc. and other Node contributors. All rights reserved. + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to + // deal in the Software without restriction, including without limitation the + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + // sell copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + // IN THE SOFTWARE. + if (!arg) { + // Need double quotation for empty argument + return '""'; + } + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { + // No quotation needed + return arg; + } + if (!arg.includes('"') && !arg.includes('\\')) { + // No embedded double quotes or backslashes, so I can just wrap + // quote marks around the whole thing. + return `"${arg}"`; + } + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" - note the comment in libuv actually reads "hello world\" + // but it appears the comment is wrong, it should be "hello world\\" + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '\\'; + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 10000 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result['windowsVerbatimArguments'] = + options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; + } + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return __awaiter(this, void 0, void 0, function* () { + // root the tool path if it is unrooted and contains relative pathing + if (!ioUtil.isRooted(this.toolPath) && + (this.toolPath.includes('/') || + (IS_WINDOWS && this.toolPath.includes('\\')))) { + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted + this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + // if the tool is only a file name, then resolve it from the PATH + // otherwise verify it exists (add extension on Windows if necessary) + this.toolPath = yield io.which(this.toolPath, true); + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug('arguments:'); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ''; + if (cp.stdout) { + cp.stdout.on('data', (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ''; + if (cp.stderr) { + cp.stderr.on('data', (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && + optionsNonNull.errStream && + optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr + ? optionsNonNull.errStream + : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on('error', (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on('exit', (code) => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on('close', (code) => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on('done', (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit('stdline', stdbuffer); + } + if (errbuffer.length > 0) { + this.emit('errline', errbuffer); + } + cp.removeAllListeners(); + if (error) { + reject(error); + } + else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error('child process missing stdin'); + } + cp.stdin.end(this.options.input); + } + })); + }); + } +} +exports.ToolRunner = ToolRunner; +/** + * Convert an arg string to an array of args. Handles escaping + * + * @param argString string of arguments + * @returns string[] array of arguments + */ +function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ''; + function append(c) { + // we only escape double quotes. + if (escaped && c !== '"') { + arg += '\\'; + } + arg += c; + escaped = false; + } + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } + else { + append(c); + } + continue; + } + if (c === '\\' && escaped) { + append(c); + continue; + } + if (c === '\\' && inQuotes) { + escaped = true; + continue; + } + if (c === ' ' && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ''; + } + continue; + } + append(c); + } + if (arg.length > 0) { + args.push(arg.trim()); + } + return args; +} +exports.argStringToArray = argStringToArray; +class ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; // tracks whether the process has exited and stdio is closed + this.processError = ''; + this.processExitCode = 0; + this.processExited = false; // tracks whether the process has exited + this.processStderr = false; // tracks whether stderr was written to + this.delay = 10000; // 10 seconds + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error('toolPath must not be empty'); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } + else if (this.processExited) { + this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit('debug', message); + } + _setResult() { + // determine whether there is an error + let error; + if (this.processExited) { + if (this.processError) { + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } + else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } + else if (this.processStderr && this.options.failOnStdErr) { + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + // clear the timeout + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit('done', error, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / + 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); + } +} +//# sourceMappingURL=toolrunner.js.map + +/***/ }), + +/***/ 44552: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BasicCredentialHandler = BasicCredentialHandler; +class BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BearerCredentialHandler = BearerCredentialHandler; +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; +//# sourceMappingURL=auth.js.map + +/***/ }), + +/***/ 54844: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; +const http = __importStar(__nccwpck_require__(58611)); +const https = __importStar(__nccwpck_require__(65692)); +const pm = __importStar(__nccwpck_require__(54988)); +const tunnel = __importStar(__nccwpck_require__(20770)); +const undici_1 = __nccwpck_require__(46752); +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes || (exports.HttpCodes = HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers || (exports.Headers = Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes || (exports.MediaTypes = MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } +} +exports.HttpClientError = HttpClientError; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } + readBodyBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + const chunks = []; + this.message.on('data', (chunk) => { + chunks.push(chunk); + }); + this.message.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + })); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + getAgentDispatcher(serverUrl) { + const parsedUrl = new URL(serverUrl); + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (!useProxy) { + return; + } + return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (!useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if tunneling agent isn't assigned create a new agent + if (!agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _getProxyAgentDispatcher(parsedUrl, proxyUrl) { + let proxyAgent; + if (this._keepAlive) { + proxyAgent = this._proxyAgentDispatcher; + } + // if agent is already assigned use that agent. + if (proxyAgent) { + return proxyAgent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + proxyAgent = new undici_1.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, ((proxyUrl.username || proxyUrl.password) && { + token: `Basic ${Buffer.from(`${proxyUrl.username}:${proxyUrl.password}`).toString('base64')}` + }))); + this._proxyAgentDispatcher = proxyAgent; + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + proxyAgent.options = Object.assign(proxyAgent.options.requestTls || {}, { + rejectUnauthorized: false + }); + } + return proxyAgent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +exports.HttpClient = HttpClient; +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 54988: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkBypass = exports.getProxyUrl = void 0; +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + try { + return new DecodedURL(proxyVar); + } + catch (_a) { + if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://')) + return new DecodedURL(`http://${proxyVar}`); + } + } + else { + return undefined; + } +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperNoProxyItem === '*' || + upperReqHosts.some(x => x === upperNoProxyItem || + x.endsWith(`.${upperNoProxyItem}`) || + (upperNoProxyItem.startsWith('.') && + x.endsWith(`${upperNoProxyItem}`)))) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; +function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return (hostLower === 'localhost' || + hostLower.startsWith('127.') || + hostLower.startsWith('[::1]') || + hostLower.startsWith('[0:0:0:0:0:0:0:1]')); +} +class DecodedURL extends URL { + constructor(url, base) { + super(url, base); + this._decodedUsername = decodeURIComponent(super.username); + this._decodedPassword = decodeURIComponent(super.password); + } + get username() { + return this._decodedUsername; + } + get password() { + return this._decodedPassword; + } +} +//# sourceMappingURL=proxy.js.map + +/***/ }), + +/***/ 75207: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; +const fs = __importStar(__nccwpck_require__(79896)); +const path = __importStar(__nccwpck_require__(16928)); +_a = fs.promises +// export const {open} = 'fs' +, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; +// export const {open} = 'fs' +exports.IS_WINDOWS = process.platform === 'win32'; +// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 +exports.UV_FS_O_EXLOCK = 0x10000000; +exports.READONLY = fs.constants.O_RDONLY; +function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exports.stat(fsPath); + } + catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } + return true; + }); +} +exports.exists = exists; +function isDirectory(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); + return stats.isDirectory(); + }); +} +exports.isDirectory = isDirectory; +/** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (exports.IS_WINDOWS) { + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); +} +exports.isRooted = isRooted; +/** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ +function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { + // test file exists + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // on Windows, test for valid extension + const upperExt = path.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = undefined; + try { + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = path.dirname(filePath); + const upperName = path.basename(filePath).toUpperCase(); + for (const actualName of yield exports.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path.join(directory, actualName); + break; + } + } + } + catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ''; + }); +} +exports.tryGetExecutablePath = tryGetExecutablePath; +function normalizeSeparators(p) { + p = p || ''; + if (exports.IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); + } + // remove redundant slashes + return p.replace(/\/\/+/g, '/'); +} +// on Mac/Linux, test the execute bit +// R W X R W X R W X +// 256 128 64 32 16 8 4 2 1 +function isUnixExecutable(stats) { + return ((stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && stats.uid === process.getuid())); +} +// Get the path of cmd.exe in windows +function getCmdPath() { + var _a; + return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; +} +exports.getCmdPath = getCmdPath; +//# sourceMappingURL=io-util.js.map + +/***/ }), + +/***/ 94994: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; +const assert_1 = __nccwpck_require__(42613); +const path = __importStar(__nccwpck_require__(16928)); +const ioUtil = __importStar(__nccwpck_require__(75207)); +/** + * Copies a file or folder. + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +function cp(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + const { force, recursive, copySourceDirectory } = readCopyOptions(options); + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; + // Dest is an existing file, but not forcing + if (destStat && destStat.isFile() && !force) { + return; + } + // If dest is an existing directory, should copy inside. + const newDest = destStat && destStat.isDirectory() && copySourceDirectory + ? path.join(dest, path.basename(source)) + : dest; + if (!(yield ioUtil.exists(source))) { + throw new Error(`no such file or directory: ${source}`); + } + const sourceStat = yield ioUtil.stat(source); + if (sourceStat.isDirectory()) { + if (!recursive) { + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } + else { + yield cpDirRecursive(source, newDest, 0, force); + } + } + else { + if (path.relative(source, newDest) === '') { + // a file cannot be copied to itself + throw new Error(`'${newDest}' and '${source}' are the same file`); + } + yield copyFile(source, newDest, force); + } + }); +} +exports.cp = cp; +/** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See MoveOptions. + */ +function mv(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (yield ioUtil.exists(dest)) { + let destExists = true; + if (yield ioUtil.isDirectory(dest)) { + // If dest is directory copy src into dest + dest = path.join(dest, path.basename(source)); + destExists = yield ioUtil.exists(dest); + } + if (destExists) { + if (options.force == null || options.force) { + yield rmRF(dest); + } + else { + throw new Error('Destination already exists'); + } + } + } + yield mkdirP(path.dirname(dest)); + yield ioUtil.rename(source, dest); + }); +} +exports.mv = mv; +/** + * Remove a path recursively with force + * + * @param inputPath path to remove + */ +function rmRF(inputPath) { + return __awaiter(this, void 0, void 0, function* () { + if (ioUtil.IS_WINDOWS) { + // Check for invalid characters + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + if (/[*"<>|]/.test(inputPath)) { + throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); + } + } + try { + // note if path does not exist, error is silent + yield ioUtil.rm(inputPath, { + force: true, + maxRetries: 3, + recursive: true, + retryDelay: 300 + }); + } + catch (err) { + throw new Error(`File was unable to be removed ${err}`); + } + }); +} +exports.rmRF = rmRF; +/** + * Make a directory. Creates the full path with folders in between + * Will throw if it fails + * + * @param fsPath path to create + * @returns Promise + */ +function mkdirP(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, 'a path argument must be provided'); + yield ioUtil.mkdir(fsPath, { recursive: true }); + }); +} +exports.mkdirP = mkdirP; +/** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * If you check and the tool does not exist, it will throw. + * + * @param tool name of the tool + * @param check whether to check if tool exists + * @returns Promise path to tool + */ +function which(tool, check) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // recursive when check=true + if (check) { + const result = yield which(tool, false); + if (!result) { + if (ioUtil.IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } + else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ''; + }); +} +exports.which = which; +/** + * Returns a list of all occurrences of the given tool on the system path. + * + * @returns Promise the paths of the tool + */ +function findInPath(tool) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // build the list of extensions to try + const extensions = []; + if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { + for (const extension of process.env['PATHEXT'].split(path.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + // if it's rooted, return it if exists. otherwise return empty. + if (ioUtil.isRooted(tool)) { + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + // if any path separators, return empty + if (tool.includes(path.sep)) { + return []; + } + // build the list of directories + // + // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, + // it feels like we should not do this. Checking the current directory seems like more of a use + // case of a shell, and the which() function exposed by the toolkit should strive for consistency + // across platforms. + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(path.delimiter)) { + if (p) { + directories.push(p); + } + } + } + // find all matches + const matches = []; + for (const directory of directories) { + const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); +} +exports.findInPath = findInPath; +function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + const copySourceDirectory = options.copySourceDirectory == null + ? true + : Boolean(options.copySourceDirectory); + return { force, recursive, copySourceDirectory }; +} +function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return __awaiter(this, void 0, void 0, function* () { + // Ensure there is not a run away recursive copy + if (currentDepth >= 255) + return; + currentDepth++; + yield mkdirP(destDir); + const files = yield ioUtil.readdir(sourceDir); + for (const fileName of files) { + const srcFile = `${sourceDir}/${fileName}`; + const destFile = `${destDir}/${fileName}`; + const srcFileStat = yield ioUtil.lstat(srcFile); + if (srcFileStat.isDirectory()) { + // Recurse + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } + else { + yield copyFile(srcFile, destFile, force); + } + } + // Change the mode for the newly created directory + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); + }); +} +// Buffered file copy +function copyFile(srcFile, destFile, force) { + return __awaiter(this, void 0, void 0, function* () { + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { + // unlink/re-link it + try { + yield ioUtil.lstat(destFile); + yield ioUtil.unlink(destFile); + } + catch (e) { + // Try to override file permission + if (e.code === 'EPERM') { + yield ioUtil.chmod(destFile, '0666'); + yield ioUtil.unlink(destFile); + } + // other errors = it doesn't exist, no work to do + } + // Copy over symlink + const symlinkFull = yield ioUtil.readlink(srcFile); + yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); + } + else if (!(yield ioUtil.exists(destFile)) || force) { + yield ioUtil.copyFile(srcFile, destFile); + } + }); +} +//# sourceMappingURL=io.js.map + +/***/ }), + +/***/ 56863: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32 = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +var index_1 = __nccwpck_require__(62110); +var AwsCrc32 = /** @class */ (function () { + function AwsCrc32() { + this.crc32 = new index_1.Crc32(); + } + AwsCrc32.prototype.update = function (toHash) { + if ((0, util_1.isEmptyData)(toHash)) + return; + this.crc32.update((0, util_1.convertToBuffer)(toHash)); + }; + AwsCrc32.prototype.digest = function () { + return tslib_1.__awaiter(this, void 0, void 0, function () { + return tslib_1.__generator(this, function (_a) { + return [2 /*return*/, (0, util_1.numToUint8)(this.crc32.digest())]; + }); + }); + }; + AwsCrc32.prototype.reset = function () { + this.crc32 = new index_1.Crc32(); + }; + return AwsCrc32; +}()); +exports.AwsCrc32 = AwsCrc32; +//# sourceMappingURL=aws_crc32.js.map + +/***/ }), + +/***/ 62110: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32 = exports.Crc32 = exports.crc32 = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +function crc32(data) { + return new Crc32().update(data).digest(); +} +exports.crc32 = crc32; +var Crc32 = /** @class */ (function () { + function Crc32() { + this.checksum = 0xffffffff; + } + Crc32.prototype.update = function (data) { + var e_1, _a; + try { + for (var data_1 = tslib_1.__values(data), data_1_1 = data_1.next(); !data_1_1.done; data_1_1 = data_1.next()) { + var byte = data_1_1.value; + this.checksum = + (this.checksum >>> 8) ^ lookupTable[(this.checksum ^ byte) & 0xff]; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (data_1_1 && !data_1_1.done && (_a = data_1.return)) _a.call(data_1); + } + finally { if (e_1) throw e_1.error; } + } + return this; + }; + Crc32.prototype.digest = function () { + return (this.checksum ^ 0xffffffff) >>> 0; + }; + return Crc32; +}()); +exports.Crc32 = Crc32; +// prettier-ignore +var a_lookUpTable = [ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +]; +var lookupTable = (0, util_1.uint32ArrayFrom)(a_lookUpTable); +var aws_crc32_1 = __nccwpck_require__(56863); +Object.defineProperty(exports, "AwsCrc32", ({ enumerable: true, get: function () { return aws_crc32_1.AwsCrc32; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 95405: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32c = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +var index_1 = __nccwpck_require__(91491); +var AwsCrc32c = /** @class */ (function () { + function AwsCrc32c() { + this.crc32c = new index_1.Crc32c(); + } + AwsCrc32c.prototype.update = function (toHash) { + if ((0, util_1.isEmptyData)(toHash)) + return; + this.crc32c.update((0, util_1.convertToBuffer)(toHash)); + }; + AwsCrc32c.prototype.digest = function () { + return tslib_1.__awaiter(this, void 0, void 0, function () { + return tslib_1.__generator(this, function (_a) { + return [2 /*return*/, (0, util_1.numToUint8)(this.crc32c.digest())]; + }); + }); + }; + AwsCrc32c.prototype.reset = function () { + this.crc32c = new index_1.Crc32c(); + }; + return AwsCrc32c; +}()); +exports.AwsCrc32c = AwsCrc32c; +//# sourceMappingURL=aws_crc32c.js.map + +/***/ }), + +/***/ 91491: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32c = exports.Crc32c = exports.crc32c = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +function crc32c(data) { + return new Crc32c().update(data).digest(); +} +exports.crc32c = crc32c; +var Crc32c = /** @class */ (function () { + function Crc32c() { + this.checksum = 0xffffffff; + } + Crc32c.prototype.update = function (data) { + var e_1, _a; + try { + for (var data_1 = tslib_1.__values(data), data_1_1 = data_1.next(); !data_1_1.done; data_1_1 = data_1.next()) { + var byte = data_1_1.value; + this.checksum = + (this.checksum >>> 8) ^ lookupTable[(this.checksum ^ byte) & 0xff]; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (data_1_1 && !data_1_1.done && (_a = data_1.return)) _a.call(data_1); + } + finally { if (e_1) throw e_1.error; } + } + return this; + }; + Crc32c.prototype.digest = function () { + return (this.checksum ^ 0xffffffff) >>> 0; + }; + return Crc32c; +}()); +exports.Crc32c = Crc32c; +// prettier-ignore +var a_lookupTable = [ + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, +]; +var lookupTable = (0, util_1.uint32ArrayFrom)(a_lookupTable); +var aws_crc32c_1 = __nccwpck_require__(95405); +Object.defineProperty(exports, "AwsCrc32c", ({ enumerable: true, get: function () { return aws_crc32c_1.AwsCrc32c; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 45675: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.convertToBuffer = void 0; +var util_utf8_1 = __nccwpck_require__(47515); +// Quick polyfill +var fromUtf8 = typeof Buffer !== "undefined" && Buffer.from + ? function (input) { return Buffer.from(input, "utf8"); } + : util_utf8_1.fromUtf8; +function convertToBuffer(data) { + // Already a Uint8, do nothing + if (data instanceof Uint8Array) + return data; + if (typeof data === "string") { + return fromUtf8(data); + } + if (ArrayBuffer.isView(data)) { + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT); + } + return new Uint8Array(data); +} +exports.convertToBuffer = convertToBuffer; +//# sourceMappingURL=convertToBuffer.js.map + +/***/ }), + +/***/ 95667: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.uint32ArrayFrom = exports.numToUint8 = exports.isEmptyData = exports.convertToBuffer = void 0; +var convertToBuffer_1 = __nccwpck_require__(45675); +Object.defineProperty(exports, "convertToBuffer", ({ enumerable: true, get: function () { return convertToBuffer_1.convertToBuffer; } })); +var isEmptyData_1 = __nccwpck_require__(14658); +Object.defineProperty(exports, "isEmptyData", ({ enumerable: true, get: function () { return isEmptyData_1.isEmptyData; } })); +var numToUint8_1 = __nccwpck_require__(35436); +Object.defineProperty(exports, "numToUint8", ({ enumerable: true, get: function () { return numToUint8_1.numToUint8; } })); +var uint32ArrayFrom_1 = __nccwpck_require__(50673); +Object.defineProperty(exports, "uint32ArrayFrom", ({ enumerable: true, get: function () { return uint32ArrayFrom_1.uint32ArrayFrom; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 14658: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isEmptyData = void 0; +function isEmptyData(data) { + if (typeof data === "string") { + return data.length === 0; + } + return data.byteLength === 0; +} +exports.isEmptyData = isEmptyData; +//# sourceMappingURL=isEmptyData.js.map + +/***/ }), + +/***/ 35436: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.numToUint8 = void 0; +function numToUint8(num) { + return new Uint8Array([ + (num & 0xff000000) >> 24, + (num & 0x00ff0000) >> 16, + (num & 0x0000ff00) >> 8, + num & 0x000000ff, + ]); +} +exports.numToUint8 = numToUint8; +//# sourceMappingURL=numToUint8.js.map + +/***/ }), + +/***/ 50673: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.uint32ArrayFrom = void 0; +// IE 11 does not support Array.from, so we do it manually +function uint32ArrayFrom(a_lookUpTable) { + if (!Uint32Array.from) { + var return_array = new Uint32Array(a_lookUpTable.length); + var a_index = 0; + while (a_index < a_lookUpTable.length) { + return_array[a_index] = a_lookUpTable[a_index]; + a_index += 1; + } + return return_array; + } + return Uint32Array.from(a_lookUpTable); +} +exports.uint32ArrayFrom = uint32ArrayFrom; +//# sourceMappingURL=uint32ArrayFrom.js.map + +/***/ }), + +/***/ 78756: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + isArrayBuffer: () => isArrayBuffer +}); +module.exports = __toCommonJS(src_exports); +var isArrayBuffer = /* @__PURE__ */ __name((arg) => typeof ArrayBuffer === "function" && arg instanceof ArrayBuffer || Object.prototype.toString.call(arg) === "[object ArrayBuffer]", "isArrayBuffer"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 19077: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromArrayBuffer: () => fromArrayBuffer, + fromString: () => fromString +}); +module.exports = __toCommonJS(src_exports); +var import_is_array_buffer = __nccwpck_require__(78756); +var import_buffer = __nccwpck_require__(20181); +var fromArrayBuffer = /* @__PURE__ */ __name((input, offset = 0, length = input.byteLength - offset) => { + if (!(0, import_is_array_buffer.isArrayBuffer)(input)) { + throw new TypeError(`The "input" argument must be ArrayBuffer. Received type ${typeof input} (${input})`); + } + return import_buffer.Buffer.from(input, offset, length); +}, "fromArrayBuffer"); +var fromString = /* @__PURE__ */ __name((input, encoding) => { + if (typeof input !== "string") { + throw new TypeError(`The "input" argument must be of type string. Received type ${typeof input} (${input})`); + } + return encoding ? import_buffer.Buffer.from(input, encoding) : import_buffer.Buffer.from(input); +}, "fromString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 47515: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromUtf8: () => fromUtf8, + toUint8Array: () => toUint8Array, + toUtf8: () => toUtf8 +}); +module.exports = __toCommonJS(src_exports); + +// src/fromUtf8.ts +var import_util_buffer_from = __nccwpck_require__(19077); +var fromUtf8 = /* @__PURE__ */ __name((input) => { + const buf = (0, import_util_buffer_from.fromString)(input, "utf8"); + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength / Uint8Array.BYTES_PER_ELEMENT); +}, "fromUtf8"); + +// src/toUint8Array.ts +var toUint8Array = /* @__PURE__ */ __name((data) => { + if (typeof data === "string") { + return fromUtf8(data); + } + if (ArrayBuffer.isView(data)) { + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT); + } + return new Uint8Array(data); +}, "toUint8Array"); + +// src/toUtf8.ts + +var toUtf8 = /* @__PURE__ */ __name((input) => { + if (typeof input === "string") { + return input; + } + if (typeof input !== "object" || typeof input.byteOffset !== "number" || typeof input.byteLength !== "number") { + throw new Error("@smithy/util-utf8: toUtf8 encoder function only accepts string | Uint8Array."); + } + return (0, import_util_buffer_from.fromArrayBuffer)(input.buffer, input.byteOffset, input.byteLength).toString("utf8"); +}, "toUtf8"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 7168: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.defaultS3HttpAuthSchemeProvider = exports.defaultS3HttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const signature_v4_multi_region_1 = __nccwpck_require__(5785); +const middleware_endpoint_1 = __nccwpck_require__(40099); +const util_middleware_1 = __nccwpck_require__(76324); +const endpointResolver_1 = __nccwpck_require__(57526); +const createEndpointRuleSetHttpAuthSchemeParametersProvider = (defaultHttpAuthSchemeParametersProvider) => async (config, context, input) => { + if (!input) { + throw new Error(`Could not find \`input\` for \`defaultEndpointRuleSetHttpAuthSchemeParametersProvider\``); + } + const defaultParameters = await defaultHttpAuthSchemeParametersProvider(config, context, input); + const instructionsFn = (0, util_middleware_1.getSmithyContext)(context)?.commandInstance?.constructor + ?.getEndpointParameterInstructions; + if (!instructionsFn) { + throw new Error(`getEndpointParameterInstructions() is not defined on \`${context.commandName}\``); + } + const endpointParameters = await (0, middleware_endpoint_1.resolveParams)(input, { getEndpointParameterInstructions: instructionsFn }, config); + return Object.assign(defaultParameters, endpointParameters); +}; +const _defaultS3HttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultS3HttpAuthSchemeParametersProvider = createEndpointRuleSetHttpAuthSchemeParametersProvider(_defaultS3HttpAuthSchemeParametersProvider); +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "s3", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createAwsAuthSigv4aHttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4a", + signingProperties: { + name: "s3", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +const createEndpointRuleSetHttpAuthSchemeProvider = (defaultEndpointResolver, defaultHttpAuthSchemeResolver, createHttpAuthOptionFunctions) => { + const endpointRuleSetHttpAuthSchemeProvider = (authParameters) => { + const endpoint = defaultEndpointResolver(authParameters); + const authSchemes = endpoint.properties?.authSchemes; + if (!authSchemes) { + return defaultHttpAuthSchemeResolver(authParameters); + } + const options = []; + for (const scheme of authSchemes) { + const { name: resolvedName, properties = {}, ...rest } = scheme; + const name = resolvedName.toLowerCase(); + if (resolvedName !== name) { + console.warn(`HttpAuthScheme has been normalized with lowercasing: \`${resolvedName}\` to \`${name}\``); + } + let schemeId; + if (name === "sigv4a") { + schemeId = "aws.auth#sigv4a"; + const sigv4Present = authSchemes.find((s) => { + const name = s.name.toLowerCase(); + return name !== "sigv4a" && name.startsWith("sigv4"); + }); + if (signature_v4_multi_region_1.SignatureV4MultiRegion.sigv4aDependency() === "none" && sigv4Present) { + continue; + } + } + else if (name.startsWith("sigv4")) { + schemeId = "aws.auth#sigv4"; + } + else { + throw new Error(`Unknown HttpAuthScheme found in \`@smithy.rules#endpointRuleSet\`: \`${name}\``); + } + const createOption = createHttpAuthOptionFunctions[schemeId]; + if (!createOption) { + throw new Error(`Could not find HttpAuthOption create function for \`${schemeId}\``); + } + const option = createOption(authParameters); + option.schemeId = schemeId; + option.signingProperties = { ...(option.signingProperties || {}), ...rest, ...properties }; + options.push(option); + } + return options; + }; + return endpointRuleSetHttpAuthSchemeProvider; +}; +const _defaultS3HttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + options.push(createAwsAuthSigv4aHttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultS3HttpAuthSchemeProvider = createEndpointRuleSetHttpAuthSchemeProvider(endpointResolver_1.defaultEndpointResolver, _defaultS3HttpAuthSchemeProvider, { + "aws.auth#sigv4": createAwsAuthSigv4HttpAuthOption, + "aws.auth#sigv4a": createAwsAuthSigv4aHttpAuthOption, +}); +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config); + const config_1 = (0, core_1.resolveAwsSdkSigV4AConfig)(config_0); + return Object.assign(config_1, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 57526: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(62999); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: [ + "Accelerate", + "Bucket", + "DisableAccessPoints", + "DisableMultiRegionAccessPoints", + "DisableS3ExpressSessionAuth", + "Endpoint", + "ForcePathStyle", + "Region", + "UseArnRegion", + "UseDualStack", + "UseFIPS", + "UseGlobalEndpoint", + "UseObjectLambdaEndpoint", + "UseS3ExpressControlEndpoint", + ], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 62999: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const cp = "required", cq = "type", cr = "rules", cs = "conditions", ct = "fn", cu = "argv", cv = "ref", cw = "assign", cx = "url", cy = "properties", cz = "backend", cA = "authSchemes", cB = "disableDoubleEncoding", cC = "signingName", cD = "signingRegion", cE = "headers", cF = "signingRegionSet"; +const a = 6, b = false, c = true, d = "isSet", e = "booleanEquals", f = "error", g = "aws.partition", h = "stringEquals", i = "getAttr", j = "name", k = "substring", l = "bucketSuffix", m = "parseURL", n = "endpoint", o = "tree", p = "aws.isVirtualHostableS3Bucket", q = "{url#scheme}://{Bucket}.{url#authority}{url#path}", r = "not", s = "accessPointSuffix", t = "{url#scheme}://{url#authority}{url#path}", u = "hardwareType", v = "regionPrefix", w = "bucketAliasSuffix", x = "outpostId", y = "isValidHostLabel", z = "sigv4a", A = "s3-outposts", B = "s3", C = "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", D = "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", E = "https://{Bucket}.s3.{partitionResult#dnsSuffix}", F = "aws.parseArn", G = "bucketArn", H = "arnType", I = "", J = "s3-object-lambda", K = "accesspoint", L = "accessPointName", M = "{url#scheme}://{accessPointName}-{bucketArn#accountId}.{url#authority}{url#path}", N = "mrapPartition", O = "outpostType", P = "arnPrefix", Q = "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", R = "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", S = "https://s3.{partitionResult#dnsSuffix}", T = { [cp]: false, [cq]: "String" }, U = { [cp]: true, "default": false, [cq]: "Boolean" }, V = { [cp]: false, [cq]: "Boolean" }, W = { [ct]: e, [cu]: [{ [cv]: "Accelerate" }, true] }, X = { [ct]: e, [cu]: [{ [cv]: "UseFIPS" }, true] }, Y = { [ct]: e, [cu]: [{ [cv]: "UseDualStack" }, true] }, Z = { [ct]: d, [cu]: [{ [cv]: "Endpoint" }] }, aa = { [ct]: g, [cu]: [{ [cv]: "Region" }], [cw]: "partitionResult" }, ab = { [ct]: h, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "partitionResult" }, j] }, "aws-cn"] }, ac = { [ct]: d, [cu]: [{ [cv]: "Bucket" }] }, ad = { [cv]: "Bucket" }, ae = { [cs]: [Y], [f]: "S3Express does not support Dual-stack.", [cq]: f }, af = { [cs]: [W], [f]: "S3Express does not support S3 Accelerate.", [cq]: f }, ag = { [cs]: [Z, { [ct]: m, [cu]: [{ [cv]: "Endpoint" }], [cw]: "url" }], [cr]: [{ [cs]: [{ [ct]: d, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }] }, { [ct]: e, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }, true] }], [cr]: [{ [cs]: [{ [ct]: e, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "url" }, "isIp"] }, true] }], [cr]: [{ [cs]: [{ [ct]: "uriEncode", [cu]: [ad], [cw]: "uri_encoded_bucket" }], [cr]: [{ [n]: { [cx]: "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: p, [cu]: [ad, false] }], [cr]: [{ [n]: { [cx]: q, [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }, { [f]: "S3Express bucket name is not a valid virtual hostable name.", [cq]: f }], [cq]: o }, { [cs]: [{ [ct]: e, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "url" }, "isIp"] }, true] }], [cr]: [{ [cs]: [{ [ct]: "uriEncode", [cu]: [ad], [cw]: "uri_encoded_bucket" }], [cr]: [{ [n]: { [cx]: "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: p, [cu]: [ad, false] }], [cr]: [{ [n]: { [cx]: q, [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }, { [f]: "S3Express bucket name is not a valid virtual hostable name.", [cq]: f }], [cq]: o }, ah = { [ct]: m, [cu]: [{ [cv]: "Endpoint" }], [cw]: "url" }, ai = { [ct]: e, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "url" }, "isIp"] }, true] }, aj = { [cv]: "url" }, ak = { [ct]: "uriEncode", [cu]: [ad], [cw]: "uri_encoded_bucket" }, al = { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: "s3express", [cD]: "{Region}" }] }, am = {}, an = { [ct]: p, [cu]: [ad, false] }, ao = { [f]: "S3Express bucket name is not a valid virtual hostable name.", [cq]: f }, ap = { [ct]: d, [cu]: [{ [cv]: "UseS3ExpressControlEndpoint" }] }, aq = { [ct]: e, [cu]: [{ [cv]: "UseS3ExpressControlEndpoint" }, true] }, ar = { [ct]: r, [cu]: [Z] }, as = { [f]: "Unrecognized S3Express bucket name format.", [cq]: f }, at = { [ct]: r, [cu]: [ac] }, au = { [cv]: u }, av = { [cs]: [ar], [f]: "Expected a endpoint to be specified but no endpoint was found", [cq]: f }, aw = { [cA]: [{ [cB]: true, [j]: z, [cC]: A, [cF]: ["*"] }, { [cB]: true, [j]: "sigv4", [cC]: A, [cD]: "{Region}" }] }, ax = { [ct]: e, [cu]: [{ [cv]: "ForcePathStyle" }, false] }, ay = { [cv]: "ForcePathStyle" }, az = { [ct]: e, [cu]: [{ [cv]: "Accelerate" }, false] }, aA = { [ct]: h, [cu]: [{ [cv]: "Region" }, "aws-global"] }, aB = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "us-east-1" }] }, aC = { [ct]: r, [cu]: [aA] }, aD = { [ct]: e, [cu]: [{ [cv]: "UseGlobalEndpoint" }, true] }, aE = { [cx]: "https://{Bucket}.s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "{Region}" }] }, [cE]: {} }, aF = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "{Region}" }] }, aG = { [ct]: e, [cu]: [{ [cv]: "UseGlobalEndpoint" }, false] }, aH = { [ct]: e, [cu]: [{ [cv]: "UseDualStack" }, false] }, aI = { [cx]: "https://{Bucket}.s3-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aJ = { [ct]: e, [cu]: [{ [cv]: "UseFIPS" }, false] }, aK = { [cx]: "https://{Bucket}.s3-accelerate.dualstack.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aL = { [cx]: "https://{Bucket}.s3.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aM = { [ct]: e, [cu]: [{ [ct]: i, [cu]: [aj, "isIp"] }, false] }, aN = { [cx]: C, [cy]: aF, [cE]: {} }, aO = { [cx]: q, [cy]: aF, [cE]: {} }, aP = { [n]: aO, [cq]: n }, aQ = { [cx]: D, [cy]: aF, [cE]: {} }, aR = { [cx]: "https://{Bucket}.s3.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aS = { [f]: "Invalid region: region was not a valid DNS name.", [cq]: f }, aT = { [cv]: G }, aU = { [cv]: H }, aV = { [ct]: i, [cu]: [aT, "service"] }, aW = { [cv]: L }, aX = { [cs]: [Y], [f]: "S3 Object Lambda does not support Dual-stack", [cq]: f }, aY = { [cs]: [W], [f]: "S3 Object Lambda does not support S3 Accelerate", [cq]: f }, aZ = { [cs]: [{ [ct]: d, [cu]: [{ [cv]: "DisableAccessPoints" }] }, { [ct]: e, [cu]: [{ [cv]: "DisableAccessPoints" }, true] }], [f]: "Access points are not supported for this operation", [cq]: f }, ba = { [cs]: [{ [ct]: d, [cu]: [{ [cv]: "UseArnRegion" }] }, { [ct]: e, [cu]: [{ [cv]: "UseArnRegion" }, false] }, { [ct]: r, [cu]: [{ [ct]: h, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }, "{Region}"] }] }], [f]: "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", [cq]: f }, bb = { [ct]: i, [cu]: [{ [cv]: "bucketPartition" }, j] }, bc = { [ct]: i, [cu]: [aT, "accountId"] }, bd = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: J, [cD]: "{bucketArn#region}" }] }, be = { [f]: "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName}`", [cq]: f }, bf = { [f]: "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", [cq]: f }, bg = { [f]: "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", [cq]: f }, bh = { [f]: "Client was configured for partition `{partitionResult#name}` but ARN (`{Bucket}`) has `{bucketPartition#name}`", [cq]: f }, bi = { [f]: "Invalid ARN: The ARN may only contain a single resource component after `accesspoint`.", [cq]: f }, bj = { [f]: "Invalid ARN: Expected a resource of the format `accesspoint:` but no name was provided", [cq]: f }, bk = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "{bucketArn#region}" }] }, bl = { [cA]: [{ [cB]: true, [j]: z, [cC]: A, [cF]: ["*"] }, { [cB]: true, [j]: "sigv4", [cC]: A, [cD]: "{bucketArn#region}" }] }, bm = { [ct]: F, [cu]: [ad] }, bn = { [cx]: "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bo = { [cx]: "https://s3-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bp = { [cx]: "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bq = { [cx]: Q, [cy]: aF, [cE]: {} }, br = { [cx]: "https://s3.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bs = { [cv]: "UseObjectLambdaEndpoint" }, bt = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: J, [cD]: "{Region}" }] }, bu = { [cx]: "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bv = { [cx]: "https://s3-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bw = { [cx]: "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bx = { [cx]: t, [cy]: aF, [cE]: {} }, by = { [cx]: "https://s3.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bz = [{ [cv]: "Region" }], bA = [{ [cv]: "Endpoint" }], bB = [ad], bC = [Y], bD = [W], bE = [Z, ah], bF = [{ [ct]: d, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }] }, { [ct]: e, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }, true] }], bG = [ak], bH = [an], bI = [aa], bJ = [X], bK = [{ [ct]: k, [cu]: [ad, 6, 14, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 14, 16, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bL = [{ [cs]: [X], [n]: { [cx]: "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: {} }, [cq]: n }, { [n]: { [cx]: "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: {} }, [cq]: n }], bM = [{ [ct]: k, [cu]: [ad, 6, 15, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 15, 17, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bN = [{ [ct]: k, [cu]: [ad, 6, 19, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 19, 21, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bO = [{ [ct]: k, [cu]: [ad, 6, 20, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 20, 22, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bP = [{ [ct]: k, [cu]: [ad, 6, 26, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 26, 28, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bQ = [{ [cs]: [X], [n]: { [cx]: "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }, { [n]: { [cx]: "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], bR = [ad, 0, 7, true], bS = [{ [ct]: k, [cu]: [ad, 7, 15, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 15, 17, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bT = [{ [ct]: k, [cu]: [ad, 7, 16, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 16, 18, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bU = [{ [ct]: k, [cu]: [ad, 7, 20, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 20, 22, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bV = [{ [ct]: k, [cu]: [ad, 7, 21, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 21, 23, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bW = [{ [ct]: k, [cu]: [ad, 7, 27, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 27, 29, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bX = [ac], bY = [{ [ct]: y, [cu]: [{ [cv]: x }, false] }], bZ = [{ [ct]: h, [cu]: [{ [cv]: v }, "beta"] }], ca = ["*"], cb = [{ [ct]: y, [cu]: [{ [cv]: "Region" }, false] }], cc = [{ [ct]: h, [cu]: [{ [cv]: "Region" }, "us-east-1"] }], cd = [{ [ct]: h, [cu]: [aU, K] }], ce = [{ [ct]: i, [cu]: [aT, "resourceId[1]"], [cw]: L }, { [ct]: r, [cu]: [{ [ct]: h, [cu]: [aW, I] }] }], cf = [aT, "resourceId[1]"], cg = [{ [ct]: r, [cu]: [{ [ct]: h, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }, I] }] }], ch = [{ [ct]: r, [cu]: [{ [ct]: d, [cu]: [{ [ct]: i, [cu]: [aT, "resourceId[2]"] }] }] }], ci = [aT, "resourceId[2]"], cj = [{ [ct]: g, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }], [cw]: "bucketPartition" }], ck = [{ [ct]: h, [cu]: [bb, { [ct]: i, [cu]: [{ [cv]: "partitionResult" }, j] }] }], cl = [{ [ct]: y, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }, true] }], cm = [{ [ct]: y, [cu]: [bc, false] }], cn = [{ [ct]: y, [cu]: [aW, false] }], co = [{ [ct]: y, [cu]: [{ [cv]: "Region" }, true] }]; +const _data = { version: "1.0", parameters: { Bucket: T, Region: T, UseFIPS: U, UseDualStack: U, Endpoint: T, ForcePathStyle: U, Accelerate: U, UseGlobalEndpoint: U, UseObjectLambdaEndpoint: V, Key: T, Prefix: T, CopySource: T, DisableAccessPoints: V, DisableMultiRegionAccessPoints: U, UseArnRegion: V, UseS3ExpressControlEndpoint: V, DisableS3ExpressSessionAuth: V }, [cr]: [{ [cs]: [{ [ct]: d, [cu]: bz }], [cr]: [{ [cs]: [W, X], error: "Accelerate cannot be used with FIPS", [cq]: f }, { [cs]: [Y, Z], error: "Cannot set dual-stack in combination with a custom endpoint.", [cq]: f }, { [cs]: [Z, X], error: "A custom endpoint cannot be combined with FIPS", [cq]: f }, { [cs]: [Z, W], error: "A custom endpoint cannot be combined with S3 Accelerate", [cq]: f }, { [cs]: [X, aa, ab], error: "Partition does not support FIPS", [cq]: f }, { [cs]: [ac, { [ct]: k, [cu]: [ad, 0, a, c], [cw]: l }, { [ct]: h, [cu]: [{ [cv]: l }, "--x-s3"] }], [cr]: [ae, af, ag, { [cs]: [ap, aq], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: [ak, ar], [cr]: [{ [cs]: bJ, endpoint: { [cx]: "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: al, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://s3express-control.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: al, [cE]: am }, [cq]: n }], [cq]: o }], [cq]: o }], [cq]: o }, { [cs]: bH, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: bF, [cr]: [{ [cs]: bK, [cr]: bL, [cq]: o }, { [cs]: bM, [cr]: bL, [cq]: o }, { [cs]: bN, [cr]: bL, [cq]: o }, { [cs]: bO, [cr]: bL, [cq]: o }, { [cs]: bP, [cr]: bL, [cq]: o }, as], [cq]: o }, { [cs]: bK, [cr]: bQ, [cq]: o }, { [cs]: bM, [cr]: bQ, [cq]: o }, { [cs]: bN, [cr]: bQ, [cq]: o }, { [cs]: bO, [cr]: bQ, [cq]: o }, { [cs]: bP, [cr]: bQ, [cq]: o }, as], [cq]: o }], [cq]: o }, ao], [cq]: o }, { [cs]: [ac, { [ct]: k, [cu]: bR, [cw]: s }, { [ct]: h, [cu]: [{ [cv]: s }, "--xa-s3"] }], [cr]: [ae, af, ag, { [cs]: bH, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: bF, [cr]: [{ [cs]: bS, [cr]: bL, [cq]: o }, { [cs]: bT, [cr]: bL, [cq]: o }, { [cs]: bU, [cr]: bL, [cq]: o }, { [cs]: bV, [cr]: bL, [cq]: o }, { [cs]: bW, [cr]: bL, [cq]: o }, as], [cq]: o }, { [cs]: bS, [cr]: bQ, [cq]: o }, { [cs]: bT, [cr]: bQ, [cq]: o }, { [cs]: bU, [cr]: bQ, [cq]: o }, { [cs]: bV, [cr]: bQ, [cq]: o }, { [cs]: bW, [cr]: bQ, [cq]: o }, as], [cq]: o }], [cq]: o }, ao], [cq]: o }, { [cs]: [at, ap, aq], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: bE, endpoint: { [cx]: t, [cy]: al, [cE]: am }, [cq]: n }, { [cs]: bJ, endpoint: { [cx]: "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: am }, [cq]: n }], [cq]: o }], [cq]: o }, { [cs]: [ac, { [ct]: k, [cu]: [ad, 49, 50, c], [cw]: u }, { [ct]: k, [cu]: [ad, 8, 12, c], [cw]: v }, { [ct]: k, [cu]: bR, [cw]: w }, { [ct]: k, [cu]: [ad, 32, 49, c], [cw]: x }, { [ct]: g, [cu]: bz, [cw]: "regionPartition" }, { [ct]: h, [cu]: [{ [cv]: w }, "--op-s3"] }], [cr]: [{ [cs]: bY, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [au, "e"] }], [cr]: [{ [cs]: bZ, [cr]: [av, { [cs]: bE, endpoint: { [cx]: "https://{Bucket}.ec2.{url#authority}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { endpoint: { [cx]: "https://{Bucket}.ec2.s3-outposts.{Region}.{regionPartition#dnsSuffix}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { [cs]: [{ [ct]: h, [cu]: [au, "o"] }], [cr]: [{ [cs]: bZ, [cr]: [av, { [cs]: bE, endpoint: { [cx]: "https://{Bucket}.op-{outpostId}.{url#authority}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { endpoint: { [cx]: "https://{Bucket}.op-{outpostId}.s3-outposts.{Region}.{regionPartition#dnsSuffix}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { error: "Unrecognized hardware type: \"Expected hardware type o or e but got {hardwareType}\"", [cq]: f }], [cq]: o }, { error: "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`.", [cq]: f }], [cq]: o }, { [cs]: bX, [cr]: [{ [cs]: [Z, { [ct]: r, [cu]: [{ [ct]: d, [cu]: [{ [ct]: m, [cu]: bA }] }] }], error: "Custom endpoint `{Endpoint}` was not a valid URI", [cq]: f }, { [cs]: [ax, an], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: cb, [cr]: [{ [cs]: [W, ab], error: "S3 Accelerate cannot be used in this region", [cq]: f }, { [cs]: [Y, X, az, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, X, az, ar, aC, aD], [cr]: [{ endpoint: aE, [cq]: n }], [cq]: o }, { [cs]: [Y, X, az, ar, aC, aG], endpoint: aE, [cq]: n }, { [cs]: [aH, X, az, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3-fips.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, X, az, ar, aC, aD], [cr]: [{ endpoint: aI, [cq]: n }], [cq]: o }, { [cs]: [aH, X, az, ar, aC, aG], endpoint: aI, [cq]: n }, { [cs]: [Y, aJ, W, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3-accelerate.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, aJ, W, ar, aC, aD], [cr]: [{ endpoint: aK, [cq]: n }], [cq]: o }, { [cs]: [Y, aJ, W, ar, aC, aG], endpoint: aK, [cq]: n }, { [cs]: [Y, aJ, az, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, aJ, az, ar, aC, aD], [cr]: [{ endpoint: aL, [cq]: n }], [cq]: o }, { [cs]: [Y, aJ, az, ar, aC, aG], endpoint: aL, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, ai, aA], endpoint: { [cx]: C, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, aM, aA], endpoint: { [cx]: q, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, ai, aC, aD], [cr]: [{ [cs]: cc, endpoint: aN, [cq]: n }, { endpoint: aN, [cq]: n }], [cq]: o }, { [cs]: [aH, aJ, az, Z, ah, aM, aC, aD], [cr]: [{ [cs]: cc, endpoint: aO, [cq]: n }, aP], [cq]: o }, { [cs]: [aH, aJ, az, Z, ah, ai, aC, aG], endpoint: aN, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, aM, aC, aG], endpoint: aO, [cq]: n }, { [cs]: [aH, aJ, W, ar, aA], endpoint: { [cx]: D, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, W, ar, aC, aD], [cr]: [{ [cs]: cc, endpoint: aQ, [cq]: n }, { endpoint: aQ, [cq]: n }], [cq]: o }, { [cs]: [aH, aJ, W, ar, aC, aG], endpoint: aQ, [cq]: n }, { [cs]: [aH, aJ, az, ar, aA], endpoint: { [cx]: E, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, az, ar, aC, aD], [cr]: [{ [cs]: cc, endpoint: { [cx]: E, [cy]: aF, [cE]: am }, [cq]: n }, { endpoint: aR, [cq]: n }], [cq]: o }, { [cs]: [aH, aJ, az, ar, aC, aG], endpoint: aR, [cq]: n }], [cq]: o }, aS], [cq]: o }], [cq]: o }, { [cs]: [Z, ah, { [ct]: h, [cu]: [{ [ct]: i, [cu]: [aj, "scheme"] }, "http"] }, { [ct]: p, [cu]: [ad, c] }, ax, aJ, aH, az], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: cb, [cr]: [aP], [cq]: o }, aS], [cq]: o }], [cq]: o }, { [cs]: [ax, { [ct]: F, [cu]: bB, [cw]: G }], [cr]: [{ [cs]: [{ [ct]: i, [cu]: [aT, "resourceId[0]"], [cw]: H }, { [ct]: r, [cu]: [{ [ct]: h, [cu]: [aU, I] }] }], [cr]: [{ [cs]: [{ [ct]: h, [cu]: [aV, J] }], [cr]: [{ [cs]: cd, [cr]: [{ [cs]: ce, [cr]: [aX, aY, { [cs]: cg, [cr]: [aZ, { [cs]: ch, [cr]: [ba, { [cs]: cj, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: ck, [cr]: [{ [cs]: cl, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [bc, I] }], error: "Invalid ARN: Missing account id", [cq]: f }, { [cs]: cm, [cr]: [{ [cs]: cn, [cr]: [{ [cs]: bE, endpoint: { [cx]: M, [cy]: bd, [cE]: am }, [cq]: n }, { [cs]: bJ, endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-object-lambda-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bd, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-object-lambda.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bd, [cE]: am }, [cq]: n }], [cq]: o }, be], [cq]: o }, bf], [cq]: o }, bg], [cq]: o }, bh], [cq]: o }], [cq]: o }], [cq]: o }, bi], [cq]: o }, { error: "Invalid ARN: bucket ARN is missing a region", [cq]: f }], [cq]: o }, bj], [cq]: o }, { error: "Invalid ARN: Object Lambda ARNs only support `accesspoint` arn types, but found: `{arnType}`", [cq]: f }], [cq]: o }, { [cs]: cd, [cr]: [{ [cs]: ce, [cr]: [{ [cs]: cg, [cr]: [{ [cs]: cd, [cr]: [{ [cs]: cg, [cr]: [aZ, { [cs]: ch, [cr]: [ba, { [cs]: cj, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [bb, "{partitionResult#name}"] }], [cr]: [{ [cs]: cl, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [aV, B] }], [cr]: [{ [cs]: cm, [cr]: [{ [cs]: cn, [cr]: [{ [cs]: bD, error: "Access Points do not support S3 Accelerate", [cq]: f }, { [cs]: [X, Y], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint-fips.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [X, aH], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [aJ, Y], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH, Z, ah], endpoint: { [cx]: M, [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }], [cq]: o }, be], [cq]: o }, bf], [cq]: o }, { error: "Invalid ARN: The ARN was not for the S3 service, found: {bucketArn#service}", [cq]: f }], [cq]: o }, bg], [cq]: o }, bh], [cq]: o }], [cq]: o }], [cq]: o }, bi], [cq]: o }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: y, [cu]: [aW, c] }], [cr]: [{ [cs]: bC, error: "S3 MRAP does not support dual-stack", [cq]: f }, { [cs]: bJ, error: "S3 MRAP does not support FIPS", [cq]: f }, { [cs]: bD, error: "S3 MRAP does not support S3 Accelerate", [cq]: f }, { [cs]: [{ [ct]: e, [cu]: [{ [cv]: "DisableMultiRegionAccessPoints" }, c] }], error: "Invalid configuration: Multi-Region Access Point ARNs are disabled.", [cq]: f }, { [cs]: [{ [ct]: g, [cu]: bz, [cw]: N }], [cr]: [{ [cs]: [{ [ct]: h, [cu]: [{ [ct]: i, [cu]: [{ [cv]: N }, j] }, { [ct]: i, [cu]: [aT, "partition"] }] }], [cr]: [{ endpoint: { [cx]: "https://{accessPointName}.accesspoint.s3-global.{mrapPartition#dnsSuffix}", [cy]: { [cA]: [{ [cB]: c, name: z, [cC]: B, [cF]: ca }] }, [cE]: am }, [cq]: n }], [cq]: o }, { error: "Client was configured for partition `{mrapPartition#name}` but bucket referred to partition `{bucketArn#partition}`", [cq]: f }], [cq]: o }], [cq]: o }, { error: "Invalid Access Point Name", [cq]: f }], [cq]: o }, bj], [cq]: o }, { [cs]: [{ [ct]: h, [cu]: [aV, A] }], [cr]: [{ [cs]: bC, error: "S3 Outposts does not support Dual-stack", [cq]: f }, { [cs]: bJ, error: "S3 Outposts does not support FIPS", [cq]: f }, { [cs]: bD, error: "S3 Outposts does not support S3 Accelerate", [cq]: f }, { [cs]: [{ [ct]: d, [cu]: [{ [ct]: i, [cu]: [aT, "resourceId[4]"] }] }], error: "Invalid Arn: Outpost Access Point ARN contains sub resources", [cq]: f }, { [cs]: [{ [ct]: i, [cu]: cf, [cw]: x }], [cr]: [{ [cs]: bY, [cr]: [ba, { [cs]: cj, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: ck, [cr]: [{ [cs]: cl, [cr]: [{ [cs]: cm, [cr]: [{ [cs]: [{ [ct]: i, [cu]: ci, [cw]: O }], [cr]: [{ [cs]: [{ [ct]: i, [cu]: [aT, "resourceId[3]"], [cw]: L }], [cr]: [{ [cs]: [{ [ct]: h, [cu]: [{ [cv]: O }, K] }], [cr]: [{ [cs]: bE, endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.{outpostId}.{url#authority}", [cy]: bl, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.{outpostId}.s3-outposts.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bl, [cE]: am }, [cq]: n }], [cq]: o }, { error: "Expected an outpost type `accesspoint`, found {outpostType}", [cq]: f }], [cq]: o }, { error: "Invalid ARN: expected an access point name", [cq]: f }], [cq]: o }, { error: "Invalid ARN: Expected a 4-component resource", [cq]: f }], [cq]: o }, bf], [cq]: o }, bg], [cq]: o }, bh], [cq]: o }], [cq]: o }], [cq]: o }, { error: "Invalid ARN: The outpost Id may only contain a-z, A-Z, 0-9 and `-`. Found: `{outpostId}`", [cq]: f }], [cq]: o }, { error: "Invalid ARN: The Outpost Id was not set", [cq]: f }], [cq]: o }, { error: "Invalid ARN: Unrecognized format: {Bucket} (type: {arnType})", [cq]: f }], [cq]: o }, { error: "Invalid ARN: No ARN type specified", [cq]: f }], [cq]: o }, { [cs]: [{ [ct]: k, [cu]: [ad, 0, 4, b], [cw]: P }, { [ct]: h, [cu]: [{ [cv]: P }, "arn:"] }, { [ct]: r, [cu]: [{ [ct]: d, [cu]: [bm] }] }], error: "Invalid ARN: `{Bucket}` was not a valid ARN", [cq]: f }, { [cs]: [{ [ct]: e, [cu]: [ay, c] }, bm], error: "Path-style addressing cannot be used with ARN buckets", [cq]: f }, { [cs]: bG, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: [az], [cr]: [{ [cs]: [Y, ar, X, aA], endpoint: { [cx]: "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, ar, X, aC, aD], [cr]: [{ endpoint: bn, [cq]: n }], [cq]: o }, { [cs]: [Y, ar, X, aC, aG], endpoint: bn, [cq]: n }, { [cs]: [aH, ar, X, aA], endpoint: { [cx]: "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, ar, X, aC, aD], [cr]: [{ endpoint: bo, [cq]: n }], [cq]: o }, { [cs]: [aH, ar, X, aC, aG], endpoint: bo, [cq]: n }, { [cs]: [Y, ar, aJ, aA], endpoint: { [cx]: "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, ar, aJ, aC, aD], [cr]: [{ endpoint: bp, [cq]: n }], [cq]: o }, { [cs]: [Y, ar, aJ, aC, aG], endpoint: bp, [cq]: n }, { [cs]: [aH, Z, ah, aJ, aA], endpoint: { [cx]: Q, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, Z, ah, aJ, aC, aD], [cr]: [{ [cs]: cc, endpoint: bq, [cq]: n }, { endpoint: bq, [cq]: n }], [cq]: o }, { [cs]: [aH, Z, ah, aJ, aC, aG], endpoint: bq, [cq]: n }, { [cs]: [aH, ar, aJ, aA], endpoint: { [cx]: R, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, ar, aJ, aC, aD], [cr]: [{ [cs]: cc, endpoint: { [cx]: R, [cy]: aF, [cE]: am }, [cq]: n }, { endpoint: br, [cq]: n }], [cq]: o }, { [cs]: [aH, ar, aJ, aC, aG], endpoint: br, [cq]: n }], [cq]: o }, { error: "Path-style addressing cannot be used with S3 Accelerate", [cq]: f }], [cq]: o }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: d, [cu]: [bs] }, { [ct]: e, [cu]: [bs, c] }], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: co, [cr]: [aX, aY, { [cs]: bE, endpoint: { [cx]: t, [cy]: bt, [cE]: am }, [cq]: n }, { [cs]: bJ, endpoint: { [cx]: "https://s3-object-lambda-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: bt, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://s3-object-lambda.{Region}.{partitionResult#dnsSuffix}", [cy]: bt, [cE]: am }, [cq]: n }], [cq]: o }, aS], [cq]: o }], [cq]: o }, { [cs]: [at], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: co, [cr]: [{ [cs]: [X, Y, ar, aA], endpoint: { [cx]: "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [X, Y, ar, aC, aD], [cr]: [{ endpoint: bu, [cq]: n }], [cq]: o }, { [cs]: [X, Y, ar, aC, aG], endpoint: bu, [cq]: n }, { [cs]: [X, aH, ar, aA], endpoint: { [cx]: "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [X, aH, ar, aC, aD], [cr]: [{ endpoint: bv, [cq]: n }], [cq]: o }, { [cs]: [X, aH, ar, aC, aG], endpoint: bv, [cq]: n }, { [cs]: [aJ, Y, ar, aA], endpoint: { [cx]: "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aJ, Y, ar, aC, aD], [cr]: [{ endpoint: bw, [cq]: n }], [cq]: o }, { [cs]: [aJ, Y, ar, aC, aG], endpoint: bw, [cq]: n }, { [cs]: [aJ, aH, Z, ah, aA], endpoint: { [cx]: t, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH, Z, ah, aC, aD], [cr]: [{ [cs]: cc, endpoint: bx, [cq]: n }, { endpoint: bx, [cq]: n }], [cq]: o }, { [cs]: [aJ, aH, Z, ah, aC, aG], endpoint: bx, [cq]: n }, { [cs]: [aJ, aH, ar, aA], endpoint: { [cx]: S, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH, ar, aC, aD], [cr]: [{ [cs]: cc, endpoint: { [cx]: S, [cy]: aF, [cE]: am }, [cq]: n }, { endpoint: by, [cq]: n }], [cq]: o }, { [cs]: [aJ, aH, ar, aC, aG], endpoint: by, [cq]: n }], [cq]: o }, aS], [cq]: o }], [cq]: o }], [cq]: o }, { error: "A region must be set when sending requests to S3.", [cq]: f }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 53711: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + AbortMultipartUploadCommand: () => AbortMultipartUploadCommand, + AnalyticsFilter: () => AnalyticsFilter, + AnalyticsS3ExportFileFormat: () => AnalyticsS3ExportFileFormat, + ArchiveStatus: () => ArchiveStatus, + BucketAccelerateStatus: () => BucketAccelerateStatus, + BucketAlreadyExists: () => BucketAlreadyExists, + BucketAlreadyOwnedByYou: () => BucketAlreadyOwnedByYou, + BucketCannedACL: () => BucketCannedACL, + BucketLocationConstraint: () => BucketLocationConstraint, + BucketLogsPermission: () => BucketLogsPermission, + BucketType: () => BucketType, + BucketVersioningStatus: () => BucketVersioningStatus, + ChecksumAlgorithm: () => ChecksumAlgorithm, + ChecksumMode: () => ChecksumMode, + ChecksumType: () => ChecksumType, + CompleteMultipartUploadCommand: () => CompleteMultipartUploadCommand, + CompleteMultipartUploadOutputFilterSensitiveLog: () => CompleteMultipartUploadOutputFilterSensitiveLog, + CompleteMultipartUploadRequestFilterSensitiveLog: () => CompleteMultipartUploadRequestFilterSensitiveLog, + CompressionType: () => CompressionType, + CopyObjectCommand: () => CopyObjectCommand, + CopyObjectOutputFilterSensitiveLog: () => CopyObjectOutputFilterSensitiveLog, + CopyObjectRequestFilterSensitiveLog: () => CopyObjectRequestFilterSensitiveLog, + CreateBucketCommand: () => CreateBucketCommand, + CreateBucketMetadataConfigurationCommand: () => CreateBucketMetadataConfigurationCommand, + CreateBucketMetadataTableConfigurationCommand: () => CreateBucketMetadataTableConfigurationCommand, + CreateMultipartUploadCommand: () => CreateMultipartUploadCommand, + CreateMultipartUploadOutputFilterSensitiveLog: () => CreateMultipartUploadOutputFilterSensitiveLog, + CreateMultipartUploadRequestFilterSensitiveLog: () => CreateMultipartUploadRequestFilterSensitiveLog, + CreateSessionCommand: () => CreateSessionCommand, + CreateSessionOutputFilterSensitiveLog: () => CreateSessionOutputFilterSensitiveLog, + CreateSessionRequestFilterSensitiveLog: () => CreateSessionRequestFilterSensitiveLog, + DataRedundancy: () => DataRedundancy, + DeleteBucketAnalyticsConfigurationCommand: () => DeleteBucketAnalyticsConfigurationCommand, + DeleteBucketCommand: () => DeleteBucketCommand, + DeleteBucketCorsCommand: () => DeleteBucketCorsCommand, + DeleteBucketEncryptionCommand: () => DeleteBucketEncryptionCommand, + DeleteBucketIntelligentTieringConfigurationCommand: () => DeleteBucketIntelligentTieringConfigurationCommand, + DeleteBucketInventoryConfigurationCommand: () => DeleteBucketInventoryConfigurationCommand, + DeleteBucketLifecycleCommand: () => DeleteBucketLifecycleCommand, + DeleteBucketMetadataConfigurationCommand: () => DeleteBucketMetadataConfigurationCommand, + DeleteBucketMetadataTableConfigurationCommand: () => DeleteBucketMetadataTableConfigurationCommand, + DeleteBucketMetricsConfigurationCommand: () => DeleteBucketMetricsConfigurationCommand, + DeleteBucketOwnershipControlsCommand: () => DeleteBucketOwnershipControlsCommand, + DeleteBucketPolicyCommand: () => DeleteBucketPolicyCommand, + DeleteBucketReplicationCommand: () => DeleteBucketReplicationCommand, + DeleteBucketTaggingCommand: () => DeleteBucketTaggingCommand, + DeleteBucketWebsiteCommand: () => DeleteBucketWebsiteCommand, + DeleteMarkerReplicationStatus: () => DeleteMarkerReplicationStatus, + DeleteObjectCommand: () => DeleteObjectCommand, + DeleteObjectTaggingCommand: () => DeleteObjectTaggingCommand, + DeleteObjectsCommand: () => DeleteObjectsCommand, + DeletePublicAccessBlockCommand: () => DeletePublicAccessBlockCommand, + EncodingType: () => EncodingType, + EncryptionFilterSensitiveLog: () => EncryptionFilterSensitiveLog, + EncryptionTypeMismatch: () => EncryptionTypeMismatch, + Event: () => Event, + ExistingObjectReplicationStatus: () => ExistingObjectReplicationStatus, + ExpirationState: () => ExpirationState, + ExpirationStatus: () => ExpirationStatus, + ExpressionType: () => ExpressionType, + FileHeaderInfo: () => FileHeaderInfo, + FilterRuleName: () => FilterRuleName, + GetBucketAccelerateConfigurationCommand: () => GetBucketAccelerateConfigurationCommand, + GetBucketAclCommand: () => GetBucketAclCommand, + GetBucketAnalyticsConfigurationCommand: () => GetBucketAnalyticsConfigurationCommand, + GetBucketCorsCommand: () => GetBucketCorsCommand, + GetBucketEncryptionCommand: () => GetBucketEncryptionCommand, + GetBucketEncryptionOutputFilterSensitiveLog: () => GetBucketEncryptionOutputFilterSensitiveLog, + GetBucketIntelligentTieringConfigurationCommand: () => GetBucketIntelligentTieringConfigurationCommand, + GetBucketInventoryConfigurationCommand: () => GetBucketInventoryConfigurationCommand, + GetBucketInventoryConfigurationOutputFilterSensitiveLog: () => GetBucketInventoryConfigurationOutputFilterSensitiveLog, + GetBucketLifecycleConfigurationCommand: () => GetBucketLifecycleConfigurationCommand, + GetBucketLocationCommand: () => GetBucketLocationCommand, + GetBucketLoggingCommand: () => GetBucketLoggingCommand, + GetBucketMetadataConfigurationCommand: () => GetBucketMetadataConfigurationCommand, + GetBucketMetadataTableConfigurationCommand: () => GetBucketMetadataTableConfigurationCommand, + GetBucketMetricsConfigurationCommand: () => GetBucketMetricsConfigurationCommand, + GetBucketNotificationConfigurationCommand: () => GetBucketNotificationConfigurationCommand, + GetBucketOwnershipControlsCommand: () => GetBucketOwnershipControlsCommand, + GetBucketPolicyCommand: () => GetBucketPolicyCommand, + GetBucketPolicyStatusCommand: () => GetBucketPolicyStatusCommand, + GetBucketReplicationCommand: () => GetBucketReplicationCommand, + GetBucketRequestPaymentCommand: () => GetBucketRequestPaymentCommand, + GetBucketTaggingCommand: () => GetBucketTaggingCommand, + GetBucketVersioningCommand: () => GetBucketVersioningCommand, + GetBucketWebsiteCommand: () => GetBucketWebsiteCommand, + GetObjectAclCommand: () => GetObjectAclCommand, + GetObjectAttributesCommand: () => GetObjectAttributesCommand, + GetObjectAttributesRequestFilterSensitiveLog: () => GetObjectAttributesRequestFilterSensitiveLog, + GetObjectCommand: () => GetObjectCommand, + GetObjectLegalHoldCommand: () => GetObjectLegalHoldCommand, + GetObjectLockConfigurationCommand: () => GetObjectLockConfigurationCommand, + GetObjectOutputFilterSensitiveLog: () => GetObjectOutputFilterSensitiveLog, + GetObjectRequestFilterSensitiveLog: () => GetObjectRequestFilterSensitiveLog, + GetObjectRetentionCommand: () => GetObjectRetentionCommand, + GetObjectTaggingCommand: () => GetObjectTaggingCommand, + GetObjectTorrentCommand: () => GetObjectTorrentCommand, + GetObjectTorrentOutputFilterSensitiveLog: () => GetObjectTorrentOutputFilterSensitiveLog, + GetPublicAccessBlockCommand: () => GetPublicAccessBlockCommand, + HeadBucketCommand: () => HeadBucketCommand, + HeadObjectCommand: () => HeadObjectCommand, + HeadObjectOutputFilterSensitiveLog: () => HeadObjectOutputFilterSensitiveLog, + HeadObjectRequestFilterSensitiveLog: () => HeadObjectRequestFilterSensitiveLog, + IdempotencyParameterMismatch: () => IdempotencyParameterMismatch, + IntelligentTieringAccessTier: () => IntelligentTieringAccessTier, + IntelligentTieringStatus: () => IntelligentTieringStatus, + InvalidObjectState: () => InvalidObjectState, + InvalidRequest: () => InvalidRequest, + InvalidWriteOffset: () => InvalidWriteOffset, + InventoryConfigurationFilterSensitiveLog: () => InventoryConfigurationFilterSensitiveLog, + InventoryConfigurationState: () => InventoryConfigurationState, + InventoryDestinationFilterSensitiveLog: () => InventoryDestinationFilterSensitiveLog, + InventoryEncryptionFilterSensitiveLog: () => InventoryEncryptionFilterSensitiveLog, + InventoryFormat: () => InventoryFormat, + InventoryFrequency: () => InventoryFrequency, + InventoryIncludedObjectVersions: () => InventoryIncludedObjectVersions, + InventoryOptionalField: () => InventoryOptionalField, + InventoryS3BucketDestinationFilterSensitiveLog: () => InventoryS3BucketDestinationFilterSensitiveLog, + JSONType: () => JSONType, + ListBucketAnalyticsConfigurationsCommand: () => ListBucketAnalyticsConfigurationsCommand, + ListBucketIntelligentTieringConfigurationsCommand: () => ListBucketIntelligentTieringConfigurationsCommand, + ListBucketInventoryConfigurationsCommand: () => ListBucketInventoryConfigurationsCommand, + ListBucketInventoryConfigurationsOutputFilterSensitiveLog: () => ListBucketInventoryConfigurationsOutputFilterSensitiveLog, + ListBucketMetricsConfigurationsCommand: () => ListBucketMetricsConfigurationsCommand, + ListBucketsCommand: () => ListBucketsCommand, + ListDirectoryBucketsCommand: () => ListDirectoryBucketsCommand, + ListMultipartUploadsCommand: () => ListMultipartUploadsCommand, + ListObjectVersionsCommand: () => ListObjectVersionsCommand, + ListObjectsCommand: () => ListObjectsCommand, + ListObjectsV2Command: () => ListObjectsV2Command, + ListPartsCommand: () => ListPartsCommand, + ListPartsRequestFilterSensitiveLog: () => ListPartsRequestFilterSensitiveLog, + LocationType: () => LocationType, + MFADelete: () => MFADelete, + MFADeleteStatus: () => MFADeleteStatus, + MetadataDirective: () => MetadataDirective, + MetricsFilter: () => MetricsFilter, + MetricsStatus: () => MetricsStatus, + NoSuchBucket: () => NoSuchBucket, + NoSuchKey: () => NoSuchKey, + NoSuchUpload: () => NoSuchUpload, + NotFound: () => NotFound, + ObjectAlreadyInActiveTierError: () => ObjectAlreadyInActiveTierError, + ObjectAttributes: () => ObjectAttributes, + ObjectCannedACL: () => ObjectCannedACL, + ObjectLockEnabled: () => ObjectLockEnabled, + ObjectLockLegalHoldStatus: () => ObjectLockLegalHoldStatus, + ObjectLockMode: () => ObjectLockMode, + ObjectLockRetentionMode: () => ObjectLockRetentionMode, + ObjectNotInActiveTierError: () => ObjectNotInActiveTierError, + ObjectOwnership: () => ObjectOwnership, + ObjectStorageClass: () => ObjectStorageClass, + ObjectVersionStorageClass: () => ObjectVersionStorageClass, + OptionalObjectAttributes: () => OptionalObjectAttributes, + OutputLocationFilterSensitiveLog: () => OutputLocationFilterSensitiveLog, + OwnerOverride: () => OwnerOverride, + PartitionDateSource: () => PartitionDateSource, + Payer: () => Payer, + Permission: () => Permission, + Protocol: () => Protocol, + PutBucketAccelerateConfigurationCommand: () => PutBucketAccelerateConfigurationCommand, + PutBucketAclCommand: () => PutBucketAclCommand, + PutBucketAnalyticsConfigurationCommand: () => PutBucketAnalyticsConfigurationCommand, + PutBucketCorsCommand: () => PutBucketCorsCommand, + PutBucketEncryptionCommand: () => PutBucketEncryptionCommand, + PutBucketEncryptionRequestFilterSensitiveLog: () => PutBucketEncryptionRequestFilterSensitiveLog, + PutBucketIntelligentTieringConfigurationCommand: () => PutBucketIntelligentTieringConfigurationCommand, + PutBucketInventoryConfigurationCommand: () => PutBucketInventoryConfigurationCommand, + PutBucketInventoryConfigurationRequestFilterSensitiveLog: () => PutBucketInventoryConfigurationRequestFilterSensitiveLog, + PutBucketLifecycleConfigurationCommand: () => PutBucketLifecycleConfigurationCommand, + PutBucketLoggingCommand: () => PutBucketLoggingCommand, + PutBucketMetricsConfigurationCommand: () => PutBucketMetricsConfigurationCommand, + PutBucketNotificationConfigurationCommand: () => PutBucketNotificationConfigurationCommand, + PutBucketOwnershipControlsCommand: () => PutBucketOwnershipControlsCommand, + PutBucketPolicyCommand: () => PutBucketPolicyCommand, + PutBucketReplicationCommand: () => PutBucketReplicationCommand, + PutBucketRequestPaymentCommand: () => PutBucketRequestPaymentCommand, + PutBucketTaggingCommand: () => PutBucketTaggingCommand, + PutBucketVersioningCommand: () => PutBucketVersioningCommand, + PutBucketWebsiteCommand: () => PutBucketWebsiteCommand, + PutObjectAclCommand: () => PutObjectAclCommand, + PutObjectCommand: () => PutObjectCommand, + PutObjectLegalHoldCommand: () => PutObjectLegalHoldCommand, + PutObjectLockConfigurationCommand: () => PutObjectLockConfigurationCommand, + PutObjectOutputFilterSensitiveLog: () => PutObjectOutputFilterSensitiveLog, + PutObjectRequestFilterSensitiveLog: () => PutObjectRequestFilterSensitiveLog, + PutObjectRetentionCommand: () => PutObjectRetentionCommand, + PutObjectTaggingCommand: () => PutObjectTaggingCommand, + PutPublicAccessBlockCommand: () => PutPublicAccessBlockCommand, + QuoteFields: () => QuoteFields, + RenameObjectCommand: () => RenameObjectCommand, + ReplicaModificationsStatus: () => ReplicaModificationsStatus, + ReplicationRuleStatus: () => ReplicationRuleStatus, + ReplicationStatus: () => ReplicationStatus, + ReplicationTimeStatus: () => ReplicationTimeStatus, + RequestCharged: () => RequestCharged, + RequestPayer: () => RequestPayer, + RestoreObjectCommand: () => RestoreObjectCommand, + RestoreObjectRequestFilterSensitiveLog: () => RestoreObjectRequestFilterSensitiveLog, + RestoreRequestFilterSensitiveLog: () => RestoreRequestFilterSensitiveLog, + RestoreRequestType: () => RestoreRequestType, + S3: () => S3, + S3Client: () => S3Client, + S3LocationFilterSensitiveLog: () => S3LocationFilterSensitiveLog, + S3ServiceException: () => S3ServiceException, + S3TablesBucketType: () => S3TablesBucketType, + SSEKMSFilterSensitiveLog: () => SSEKMSFilterSensitiveLog, + SelectObjectContentCommand: () => SelectObjectContentCommand, + SelectObjectContentEventStream: () => SelectObjectContentEventStream, + SelectObjectContentEventStreamFilterSensitiveLog: () => SelectObjectContentEventStreamFilterSensitiveLog, + SelectObjectContentOutputFilterSensitiveLog: () => SelectObjectContentOutputFilterSensitiveLog, + SelectObjectContentRequestFilterSensitiveLog: () => SelectObjectContentRequestFilterSensitiveLog, + ServerSideEncryption: () => ServerSideEncryption, + ServerSideEncryptionByDefaultFilterSensitiveLog: () => ServerSideEncryptionByDefaultFilterSensitiveLog, + ServerSideEncryptionConfigurationFilterSensitiveLog: () => ServerSideEncryptionConfigurationFilterSensitiveLog, + ServerSideEncryptionRuleFilterSensitiveLog: () => ServerSideEncryptionRuleFilterSensitiveLog, + SessionCredentialsFilterSensitiveLog: () => SessionCredentialsFilterSensitiveLog, + SessionMode: () => SessionMode, + SseKmsEncryptedObjectsStatus: () => SseKmsEncryptedObjectsStatus, + StorageClass: () => StorageClass, + StorageClassAnalysisSchemaVersion: () => StorageClassAnalysisSchemaVersion, + TableSseAlgorithm: () => TableSseAlgorithm, + TaggingDirective: () => TaggingDirective, + Tier: () => Tier, + TooManyParts: () => TooManyParts, + TransitionDefaultMinimumObjectSize: () => TransitionDefaultMinimumObjectSize, + TransitionStorageClass: () => TransitionStorageClass, + Type: () => Type, + UpdateBucketMetadataInventoryTableConfigurationCommand: () => UpdateBucketMetadataInventoryTableConfigurationCommand, + UpdateBucketMetadataJournalTableConfigurationCommand: () => UpdateBucketMetadataJournalTableConfigurationCommand, + UploadPartCommand: () => UploadPartCommand, + UploadPartCopyCommand: () => UploadPartCopyCommand, + UploadPartCopyOutputFilterSensitiveLog: () => UploadPartCopyOutputFilterSensitiveLog, + UploadPartCopyRequestFilterSensitiveLog: () => UploadPartCopyRequestFilterSensitiveLog, + UploadPartOutputFilterSensitiveLog: () => UploadPartOutputFilterSensitiveLog, + UploadPartRequestFilterSensitiveLog: () => UploadPartRequestFilterSensitiveLog, + WriteGetObjectResponseCommand: () => WriteGetObjectResponseCommand, + WriteGetObjectResponseRequestFilterSensitiveLog: () => WriteGetObjectResponseRequestFilterSensitiveLog, + __Client: () => import_smithy_client.Client, + paginateListBuckets: () => paginateListBuckets, + paginateListDirectoryBuckets: () => paginateListDirectoryBuckets, + paginateListObjectsV2: () => paginateListObjectsV2, + paginateListParts: () => paginateListParts, + waitForBucketExists: () => waitForBucketExists, + waitForBucketNotExists: () => waitForBucketNotExists, + waitForObjectExists: () => waitForObjectExists, + waitForObjectNotExists: () => waitForObjectNotExists, + waitUntilBucketExists: () => waitUntilBucketExists, + waitUntilBucketNotExists: () => waitUntilBucketNotExists, + waitUntilObjectExists: () => waitUntilObjectExists, + waitUntilObjectNotExists: () => waitUntilObjectNotExists +}); +module.exports = __toCommonJS(index_exports); + +// src/S3Client.ts +var import_middleware_expect_continue = __nccwpck_require__(84745); +var import_middleware_flexible_checksums = __nccwpck_require__(29836); +var import_middleware_host_header = __nccwpck_require__(52590); +var import_middleware_logger = __nccwpck_require__(85242); +var import_middleware_recursion_detection = __nccwpck_require__(81568); +var import_middleware_sdk_s32 = __nccwpck_require__(77445); +var import_middleware_user_agent = __nccwpck_require__(32959); +var import_config_resolver = __nccwpck_require__(39316); +var import_core3 = __nccwpck_require__(90402); +var import_eventstream_serde_config_resolver = __nccwpck_require__(86895); +var import_middleware_content_length = __nccwpck_require__(47212); + +var import_middleware_retry = __nccwpck_require__(19618); + +var import_httpAuthSchemeProvider = __nccwpck_require__(7168); + +// src/commands/CreateSessionCommand.ts +var import_middleware_sdk_s3 = __nccwpck_require__(77445); +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_serde = __nccwpck_require__(83255); + + +// src/endpoint/EndpointParameters.ts +var resolveClientEndpointParameters = /* @__PURE__ */ __name((options) => { + return Object.assign(options, { + useFipsEndpoint: options.useFipsEndpoint ?? false, + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + forcePathStyle: options.forcePathStyle ?? false, + useAccelerateEndpoint: options.useAccelerateEndpoint ?? false, + useGlobalEndpoint: options.useGlobalEndpoint ?? false, + disableMultiregionAccessPoints: options.disableMultiregionAccessPoints ?? false, + defaultSigningName: "s3" + }); +}, "resolveClientEndpointParameters"); +var commonParams = { + ForcePathStyle: { type: "clientContextParams", name: "forcePathStyle" }, + UseArnRegion: { type: "clientContextParams", name: "useArnRegion" }, + DisableMultiRegionAccessPoints: { type: "clientContextParams", name: "disableMultiregionAccessPoints" }, + Accelerate: { type: "clientContextParams", name: "useAccelerateEndpoint" }, + DisableS3ExpressSessionAuth: { type: "clientContextParams", name: "disableS3ExpressSessionAuth" }, + UseGlobalEndpoint: { type: "builtInParams", name: "useGlobalEndpoint" }, + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" } +}; + +// src/models/models_0.ts + + +// src/models/S3ServiceException.ts +var import_smithy_client = __nccwpck_require__(61411); +var S3ServiceException = class _S3ServiceException extends import_smithy_client.ServiceException { + static { + __name(this, "S3ServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _S3ServiceException.prototype); + } +}; + +// src/models/models_0.ts +var RequestCharged = { + requester: "requester" +}; +var RequestPayer = { + requester: "requester" +}; +var NoSuchUpload = class _NoSuchUpload extends S3ServiceException { + static { + __name(this, "NoSuchUpload"); + } + name = "NoSuchUpload"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NoSuchUpload", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NoSuchUpload.prototype); + } +}; +var BucketAccelerateStatus = { + Enabled: "Enabled", + Suspended: "Suspended" +}; +var Type = { + AmazonCustomerByEmail: "AmazonCustomerByEmail", + CanonicalUser: "CanonicalUser", + Group: "Group" +}; +var Permission = { + FULL_CONTROL: "FULL_CONTROL", + READ: "READ", + READ_ACP: "READ_ACP", + WRITE: "WRITE", + WRITE_ACP: "WRITE_ACP" +}; +var OwnerOverride = { + Destination: "Destination" +}; +var ChecksumType = { + COMPOSITE: "COMPOSITE", + FULL_OBJECT: "FULL_OBJECT" +}; +var ServerSideEncryption = { + AES256: "AES256", + aws_fsx: "aws:fsx", + aws_kms: "aws:kms", + aws_kms_dsse: "aws:kms:dsse" +}; +var ObjectCannedACL = { + authenticated_read: "authenticated-read", + aws_exec_read: "aws-exec-read", + bucket_owner_full_control: "bucket-owner-full-control", + bucket_owner_read: "bucket-owner-read", + private: "private", + public_read: "public-read", + public_read_write: "public-read-write" +}; +var ChecksumAlgorithm = { + CRC32: "CRC32", + CRC32C: "CRC32C", + CRC64NVME: "CRC64NVME", + SHA1: "SHA1", + SHA256: "SHA256" +}; +var MetadataDirective = { + COPY: "COPY", + REPLACE: "REPLACE" +}; +var ObjectLockLegalHoldStatus = { + OFF: "OFF", + ON: "ON" +}; +var ObjectLockMode = { + COMPLIANCE: "COMPLIANCE", + GOVERNANCE: "GOVERNANCE" +}; +var StorageClass = { + DEEP_ARCHIVE: "DEEP_ARCHIVE", + EXPRESS_ONEZONE: "EXPRESS_ONEZONE", + FSX_OPENZFS: "FSX_OPENZFS", + GLACIER: "GLACIER", + GLACIER_IR: "GLACIER_IR", + INTELLIGENT_TIERING: "INTELLIGENT_TIERING", + ONEZONE_IA: "ONEZONE_IA", + OUTPOSTS: "OUTPOSTS", + REDUCED_REDUNDANCY: "REDUCED_REDUNDANCY", + SNOW: "SNOW", + STANDARD: "STANDARD", + STANDARD_IA: "STANDARD_IA" +}; +var TaggingDirective = { + COPY: "COPY", + REPLACE: "REPLACE" +}; +var ObjectNotInActiveTierError = class _ObjectNotInActiveTierError extends S3ServiceException { + static { + __name(this, "ObjectNotInActiveTierError"); + } + name = "ObjectNotInActiveTierError"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ObjectNotInActiveTierError", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ObjectNotInActiveTierError.prototype); + } +}; +var BucketAlreadyExists = class _BucketAlreadyExists extends S3ServiceException { + static { + __name(this, "BucketAlreadyExists"); + } + name = "BucketAlreadyExists"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "BucketAlreadyExists", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _BucketAlreadyExists.prototype); + } +}; +var BucketAlreadyOwnedByYou = class _BucketAlreadyOwnedByYou extends S3ServiceException { + static { + __name(this, "BucketAlreadyOwnedByYou"); + } + name = "BucketAlreadyOwnedByYou"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "BucketAlreadyOwnedByYou", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _BucketAlreadyOwnedByYou.prototype); + } +}; +var BucketCannedACL = { + authenticated_read: "authenticated-read", + private: "private", + public_read: "public-read", + public_read_write: "public-read-write" +}; +var DataRedundancy = { + SingleAvailabilityZone: "SingleAvailabilityZone", + SingleLocalZone: "SingleLocalZone" +}; +var BucketType = { + Directory: "Directory" +}; +var LocationType = { + AvailabilityZone: "AvailabilityZone", + LocalZone: "LocalZone" +}; +var BucketLocationConstraint = { + EU: "EU", + af_south_1: "af-south-1", + ap_east_1: "ap-east-1", + ap_northeast_1: "ap-northeast-1", + ap_northeast_2: "ap-northeast-2", + ap_northeast_3: "ap-northeast-3", + ap_south_1: "ap-south-1", + ap_south_2: "ap-south-2", + ap_southeast_1: "ap-southeast-1", + ap_southeast_2: "ap-southeast-2", + ap_southeast_3: "ap-southeast-3", + ap_southeast_4: "ap-southeast-4", + ap_southeast_5: "ap-southeast-5", + ca_central_1: "ca-central-1", + cn_north_1: "cn-north-1", + cn_northwest_1: "cn-northwest-1", + eu_central_1: "eu-central-1", + eu_central_2: "eu-central-2", + eu_north_1: "eu-north-1", + eu_south_1: "eu-south-1", + eu_south_2: "eu-south-2", + eu_west_1: "eu-west-1", + eu_west_2: "eu-west-2", + eu_west_3: "eu-west-3", + il_central_1: "il-central-1", + me_central_1: "me-central-1", + me_south_1: "me-south-1", + sa_east_1: "sa-east-1", + us_east_2: "us-east-2", + us_gov_east_1: "us-gov-east-1", + us_gov_west_1: "us-gov-west-1", + us_west_1: "us-west-1", + us_west_2: "us-west-2" +}; +var ObjectOwnership = { + BucketOwnerEnforced: "BucketOwnerEnforced", + BucketOwnerPreferred: "BucketOwnerPreferred", + ObjectWriter: "ObjectWriter" +}; +var InventoryConfigurationState = { + DISABLED: "DISABLED", + ENABLED: "ENABLED" +}; +var TableSseAlgorithm = { + AES256: "AES256", + aws_kms: "aws:kms" +}; +var ExpirationState = { + DISABLED: "DISABLED", + ENABLED: "ENABLED" +}; +var SessionMode = { + ReadOnly: "ReadOnly", + ReadWrite: "ReadWrite" +}; +var NoSuchBucket = class _NoSuchBucket extends S3ServiceException { + static { + __name(this, "NoSuchBucket"); + } + name = "NoSuchBucket"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NoSuchBucket", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NoSuchBucket.prototype); + } +}; +var AnalyticsFilter; +((AnalyticsFilter2) => { + AnalyticsFilter2.visit = /* @__PURE__ */ __name((value, visitor) => { + if (value.Prefix !== void 0) return visitor.Prefix(value.Prefix); + if (value.Tag !== void 0) return visitor.Tag(value.Tag); + if (value.And !== void 0) return visitor.And(value.And); + return visitor._(value.$unknown[0], value.$unknown[1]); + }, "visit"); +})(AnalyticsFilter || (AnalyticsFilter = {})); +var AnalyticsS3ExportFileFormat = { + CSV: "CSV" +}; +var StorageClassAnalysisSchemaVersion = { + V_1: "V_1" +}; +var IntelligentTieringStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var IntelligentTieringAccessTier = { + ARCHIVE_ACCESS: "ARCHIVE_ACCESS", + DEEP_ARCHIVE_ACCESS: "DEEP_ARCHIVE_ACCESS" +}; +var InventoryFormat = { + CSV: "CSV", + ORC: "ORC", + Parquet: "Parquet" +}; +var InventoryIncludedObjectVersions = { + All: "All", + Current: "Current" +}; +var InventoryOptionalField = { + BucketKeyStatus: "BucketKeyStatus", + ChecksumAlgorithm: "ChecksumAlgorithm", + ETag: "ETag", + EncryptionStatus: "EncryptionStatus", + IntelligentTieringAccessTier: "IntelligentTieringAccessTier", + IsMultipartUploaded: "IsMultipartUploaded", + LastModifiedDate: "LastModifiedDate", + ObjectAccessControlList: "ObjectAccessControlList", + ObjectLockLegalHoldStatus: "ObjectLockLegalHoldStatus", + ObjectLockMode: "ObjectLockMode", + ObjectLockRetainUntilDate: "ObjectLockRetainUntilDate", + ObjectOwner: "ObjectOwner", + ReplicationStatus: "ReplicationStatus", + Size: "Size", + StorageClass: "StorageClass" +}; +var InventoryFrequency = { + Daily: "Daily", + Weekly: "Weekly" +}; +var TransitionStorageClass = { + DEEP_ARCHIVE: "DEEP_ARCHIVE", + GLACIER: "GLACIER", + GLACIER_IR: "GLACIER_IR", + INTELLIGENT_TIERING: "INTELLIGENT_TIERING", + ONEZONE_IA: "ONEZONE_IA", + STANDARD_IA: "STANDARD_IA" +}; +var ExpirationStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var TransitionDefaultMinimumObjectSize = { + all_storage_classes_128K: "all_storage_classes_128K", + varies_by_storage_class: "varies_by_storage_class" +}; +var BucketLogsPermission = { + FULL_CONTROL: "FULL_CONTROL", + READ: "READ", + WRITE: "WRITE" +}; +var PartitionDateSource = { + DeliveryTime: "DeliveryTime", + EventTime: "EventTime" +}; +var S3TablesBucketType = { + aws: "aws", + customer: "customer" +}; +var MetricsFilter; +((MetricsFilter2) => { + MetricsFilter2.visit = /* @__PURE__ */ __name((value, visitor) => { + if (value.Prefix !== void 0) return visitor.Prefix(value.Prefix); + if (value.Tag !== void 0) return visitor.Tag(value.Tag); + if (value.AccessPointArn !== void 0) return visitor.AccessPointArn(value.AccessPointArn); + if (value.And !== void 0) return visitor.And(value.And); + return visitor._(value.$unknown[0], value.$unknown[1]); + }, "visit"); +})(MetricsFilter || (MetricsFilter = {})); +var Event = { + s3_IntelligentTiering: "s3:IntelligentTiering", + s3_LifecycleExpiration_: "s3:LifecycleExpiration:*", + s3_LifecycleExpiration_Delete: "s3:LifecycleExpiration:Delete", + s3_LifecycleExpiration_DeleteMarkerCreated: "s3:LifecycleExpiration:DeleteMarkerCreated", + s3_LifecycleTransition: "s3:LifecycleTransition", + s3_ObjectAcl_Put: "s3:ObjectAcl:Put", + s3_ObjectCreated_: "s3:ObjectCreated:*", + s3_ObjectCreated_CompleteMultipartUpload: "s3:ObjectCreated:CompleteMultipartUpload", + s3_ObjectCreated_Copy: "s3:ObjectCreated:Copy", + s3_ObjectCreated_Post: "s3:ObjectCreated:Post", + s3_ObjectCreated_Put: "s3:ObjectCreated:Put", + s3_ObjectRemoved_: "s3:ObjectRemoved:*", + s3_ObjectRemoved_Delete: "s3:ObjectRemoved:Delete", + s3_ObjectRemoved_DeleteMarkerCreated: "s3:ObjectRemoved:DeleteMarkerCreated", + s3_ObjectRestore_: "s3:ObjectRestore:*", + s3_ObjectRestore_Completed: "s3:ObjectRestore:Completed", + s3_ObjectRestore_Delete: "s3:ObjectRestore:Delete", + s3_ObjectRestore_Post: "s3:ObjectRestore:Post", + s3_ObjectTagging_: "s3:ObjectTagging:*", + s3_ObjectTagging_Delete: "s3:ObjectTagging:Delete", + s3_ObjectTagging_Put: "s3:ObjectTagging:Put", + s3_ReducedRedundancyLostObject: "s3:ReducedRedundancyLostObject", + s3_Replication_: "s3:Replication:*", + s3_Replication_OperationFailedReplication: "s3:Replication:OperationFailedReplication", + s3_Replication_OperationMissedThreshold: "s3:Replication:OperationMissedThreshold", + s3_Replication_OperationNotTracked: "s3:Replication:OperationNotTracked", + s3_Replication_OperationReplicatedAfterThreshold: "s3:Replication:OperationReplicatedAfterThreshold" +}; +var FilterRuleName = { + prefix: "prefix", + suffix: "suffix" +}; +var DeleteMarkerReplicationStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var MetricsStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ReplicationTimeStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ExistingObjectReplicationStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ReplicaModificationsStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var SseKmsEncryptedObjectsStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ReplicationRuleStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var Payer = { + BucketOwner: "BucketOwner", + Requester: "Requester" +}; +var MFADeleteStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var BucketVersioningStatus = { + Enabled: "Enabled", + Suspended: "Suspended" +}; +var Protocol = { + http: "http", + https: "https" +}; +var ReplicationStatus = { + COMPLETE: "COMPLETE", + COMPLETED: "COMPLETED", + FAILED: "FAILED", + PENDING: "PENDING", + REPLICA: "REPLICA" +}; +var ChecksumMode = { + ENABLED: "ENABLED" +}; +var InvalidObjectState = class _InvalidObjectState extends S3ServiceException { + static { + __name(this, "InvalidObjectState"); + } + name = "InvalidObjectState"; + $fault = "client"; + StorageClass; + AccessTier; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidObjectState", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidObjectState.prototype); + this.StorageClass = opts.StorageClass; + this.AccessTier = opts.AccessTier; + } +}; +var NoSuchKey = class _NoSuchKey extends S3ServiceException { + static { + __name(this, "NoSuchKey"); + } + name = "NoSuchKey"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NoSuchKey", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NoSuchKey.prototype); + } +}; +var ObjectAttributes = { + CHECKSUM: "Checksum", + ETAG: "ETag", + OBJECT_PARTS: "ObjectParts", + OBJECT_SIZE: "ObjectSize", + STORAGE_CLASS: "StorageClass" +}; +var ObjectLockEnabled = { + Enabled: "Enabled" +}; +var ObjectLockRetentionMode = { + COMPLIANCE: "COMPLIANCE", + GOVERNANCE: "GOVERNANCE" +}; +var NotFound = class _NotFound extends S3ServiceException { + static { + __name(this, "NotFound"); + } + name = "NotFound"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NotFound", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NotFound.prototype); + } +}; +var ArchiveStatus = { + ARCHIVE_ACCESS: "ARCHIVE_ACCESS", + DEEP_ARCHIVE_ACCESS: "DEEP_ARCHIVE_ACCESS" +}; +var EncodingType = { + url: "url" +}; +var CompleteMultipartUploadOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "CompleteMultipartUploadOutputFilterSensitiveLog"); +var CompleteMultipartUploadRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "CompleteMultipartUploadRequestFilterSensitiveLog"); +var CopyObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CopyObjectOutputFilterSensitiveLog"); +var CopyObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING }, + ...obj.CopySourceSSECustomerKey && { CopySourceSSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "CopyObjectRequestFilterSensitiveLog"); +var CreateMultipartUploadOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CreateMultipartUploadOutputFilterSensitiveLog"); +var CreateMultipartUploadRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CreateMultipartUploadRequestFilterSensitiveLog"); +var SessionCredentialsFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SecretAccessKey && { SecretAccessKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SessionToken && { SessionToken: import_smithy_client.SENSITIVE_STRING } +}), "SessionCredentialsFilterSensitiveLog"); +var CreateSessionOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING }, + ...obj.Credentials && { Credentials: SessionCredentialsFilterSensitiveLog(obj.Credentials) } +}), "CreateSessionOutputFilterSensitiveLog"); +var CreateSessionRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CreateSessionRequestFilterSensitiveLog"); +var ServerSideEncryptionByDefaultFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.KMSMasterKeyID && { KMSMasterKeyID: import_smithy_client.SENSITIVE_STRING } +}), "ServerSideEncryptionByDefaultFilterSensitiveLog"); +var ServerSideEncryptionRuleFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.ApplyServerSideEncryptionByDefault && { + ApplyServerSideEncryptionByDefault: ServerSideEncryptionByDefaultFilterSensitiveLog( + obj.ApplyServerSideEncryptionByDefault + ) + } +}), "ServerSideEncryptionRuleFilterSensitiveLog"); +var ServerSideEncryptionConfigurationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Rules && { Rules: obj.Rules.map((item) => ServerSideEncryptionRuleFilterSensitiveLog(item)) } +}), "ServerSideEncryptionConfigurationFilterSensitiveLog"); +var GetBucketEncryptionOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.ServerSideEncryptionConfiguration && { + ServerSideEncryptionConfiguration: ServerSideEncryptionConfigurationFilterSensitiveLog( + obj.ServerSideEncryptionConfiguration + ) + } +}), "GetBucketEncryptionOutputFilterSensitiveLog"); +var SSEKMSFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.KeyId && { KeyId: import_smithy_client.SENSITIVE_STRING } +}), "SSEKMSFilterSensitiveLog"); +var InventoryEncryptionFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMS && { SSEKMS: SSEKMSFilterSensitiveLog(obj.SSEKMS) } +}), "InventoryEncryptionFilterSensitiveLog"); +var InventoryS3BucketDestinationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Encryption && { Encryption: InventoryEncryptionFilterSensitiveLog(obj.Encryption) } +}), "InventoryS3BucketDestinationFilterSensitiveLog"); +var InventoryDestinationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.S3BucketDestination && { + S3BucketDestination: InventoryS3BucketDestinationFilterSensitiveLog(obj.S3BucketDestination) + } +}), "InventoryDestinationFilterSensitiveLog"); +var InventoryConfigurationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Destination && { Destination: InventoryDestinationFilterSensitiveLog(obj.Destination) } +}), "InventoryConfigurationFilterSensitiveLog"); +var GetBucketInventoryConfigurationOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.InventoryConfiguration && { + InventoryConfiguration: InventoryConfigurationFilterSensitiveLog(obj.InventoryConfiguration) + } +}), "GetBucketInventoryConfigurationOutputFilterSensitiveLog"); +var GetObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "GetObjectOutputFilterSensitiveLog"); +var GetObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "GetObjectRequestFilterSensitiveLog"); +var GetObjectAttributesRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "GetObjectAttributesRequestFilterSensitiveLog"); +var GetObjectTorrentOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj +}), "GetObjectTorrentOutputFilterSensitiveLog"); +var HeadObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "HeadObjectOutputFilterSensitiveLog"); +var HeadObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "HeadObjectRequestFilterSensitiveLog"); +var ListBucketInventoryConfigurationsOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.InventoryConfigurationList && { + InventoryConfigurationList: obj.InventoryConfigurationList.map( + (item) => InventoryConfigurationFilterSensitiveLog(item) + ) + } +}), "ListBucketInventoryConfigurationsOutputFilterSensitiveLog"); + +// src/protocols/Aws_restXml.ts +var import_core = __nccwpck_require__(8704); +var import_xml_builder = __nccwpck_require__(94274); +var import_core2 = __nccwpck_require__(90402); +var import_protocol_http = __nccwpck_require__(72356); + +var import_uuid = __nccwpck_require__(12048); + +// src/models/models_1.ts + +var ObjectStorageClass = { + DEEP_ARCHIVE: "DEEP_ARCHIVE", + EXPRESS_ONEZONE: "EXPRESS_ONEZONE", + FSX_OPENZFS: "FSX_OPENZFS", + GLACIER: "GLACIER", + GLACIER_IR: "GLACIER_IR", + INTELLIGENT_TIERING: "INTELLIGENT_TIERING", + ONEZONE_IA: "ONEZONE_IA", + OUTPOSTS: "OUTPOSTS", + REDUCED_REDUNDANCY: "REDUCED_REDUNDANCY", + SNOW: "SNOW", + STANDARD: "STANDARD", + STANDARD_IA: "STANDARD_IA" +}; +var OptionalObjectAttributes = { + RESTORE_STATUS: "RestoreStatus" +}; +var ObjectVersionStorageClass = { + STANDARD: "STANDARD" +}; +var MFADelete = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var EncryptionTypeMismatch = class _EncryptionTypeMismatch extends S3ServiceException { + static { + __name(this, "EncryptionTypeMismatch"); + } + name = "EncryptionTypeMismatch"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "EncryptionTypeMismatch", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _EncryptionTypeMismatch.prototype); + } +}; +var InvalidRequest = class _InvalidRequest extends S3ServiceException { + static { + __name(this, "InvalidRequest"); + } + name = "InvalidRequest"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidRequest", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidRequest.prototype); + } +}; +var InvalidWriteOffset = class _InvalidWriteOffset extends S3ServiceException { + static { + __name(this, "InvalidWriteOffset"); + } + name = "InvalidWriteOffset"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidWriteOffset", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidWriteOffset.prototype); + } +}; +var TooManyParts = class _TooManyParts extends S3ServiceException { + static { + __name(this, "TooManyParts"); + } + name = "TooManyParts"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "TooManyParts", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _TooManyParts.prototype); + } +}; +var IdempotencyParameterMismatch = class _IdempotencyParameterMismatch extends S3ServiceException { + static { + __name(this, "IdempotencyParameterMismatch"); + } + name = "IdempotencyParameterMismatch"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "IdempotencyParameterMismatch", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _IdempotencyParameterMismatch.prototype); + } +}; +var ObjectAlreadyInActiveTierError = class _ObjectAlreadyInActiveTierError extends S3ServiceException { + static { + __name(this, "ObjectAlreadyInActiveTierError"); + } + name = "ObjectAlreadyInActiveTierError"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ObjectAlreadyInActiveTierError", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ObjectAlreadyInActiveTierError.prototype); + } +}; +var Tier = { + Bulk: "Bulk", + Expedited: "Expedited", + Standard: "Standard" +}; +var ExpressionType = { + SQL: "SQL" +}; +var CompressionType = { + BZIP2: "BZIP2", + GZIP: "GZIP", + NONE: "NONE" +}; +var FileHeaderInfo = { + IGNORE: "IGNORE", + NONE: "NONE", + USE: "USE" +}; +var JSONType = { + DOCUMENT: "DOCUMENT", + LINES: "LINES" +}; +var QuoteFields = { + ALWAYS: "ALWAYS", + ASNEEDED: "ASNEEDED" +}; +var RestoreRequestType = { + SELECT: "SELECT" +}; +var SelectObjectContentEventStream; +((SelectObjectContentEventStream3) => { + SelectObjectContentEventStream3.visit = /* @__PURE__ */ __name((value, visitor) => { + if (value.Records !== void 0) return visitor.Records(value.Records); + if (value.Stats !== void 0) return visitor.Stats(value.Stats); + if (value.Progress !== void 0) return visitor.Progress(value.Progress); + if (value.Cont !== void 0) return visitor.Cont(value.Cont); + if (value.End !== void 0) return visitor.End(value.End); + return visitor._(value.$unknown[0], value.$unknown[1]); + }, "visit"); +})(SelectObjectContentEventStream || (SelectObjectContentEventStream = {})); +var ListPartsRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "ListPartsRequestFilterSensitiveLog"); +var PutBucketEncryptionRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.ServerSideEncryptionConfiguration && { + ServerSideEncryptionConfiguration: ServerSideEncryptionConfigurationFilterSensitiveLog( + obj.ServerSideEncryptionConfiguration + ) + } +}), "PutBucketEncryptionRequestFilterSensitiveLog"); +var PutBucketInventoryConfigurationRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.InventoryConfiguration && { + InventoryConfiguration: InventoryConfigurationFilterSensitiveLog(obj.InventoryConfiguration) + } +}), "PutBucketInventoryConfigurationRequestFilterSensitiveLog"); +var PutObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "PutObjectOutputFilterSensitiveLog"); +var PutObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "PutObjectRequestFilterSensitiveLog"); +var EncryptionFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.KMSKeyId && { KMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "EncryptionFilterSensitiveLog"); +var S3LocationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Encryption && { Encryption: EncryptionFilterSensitiveLog(obj.Encryption) } +}), "S3LocationFilterSensitiveLog"); +var OutputLocationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.S3 && { S3: S3LocationFilterSensitiveLog(obj.S3) } +}), "OutputLocationFilterSensitiveLog"); +var RestoreRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.OutputLocation && { OutputLocation: OutputLocationFilterSensitiveLog(obj.OutputLocation) } +}), "RestoreRequestFilterSensitiveLog"); +var RestoreObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.RestoreRequest && { RestoreRequest: RestoreRequestFilterSensitiveLog(obj.RestoreRequest) } +}), "RestoreObjectRequestFilterSensitiveLog"); +var SelectObjectContentEventStreamFilterSensitiveLog = /* @__PURE__ */ __name((obj) => { + if (obj.Records !== void 0) return { Records: obj.Records }; + if (obj.Stats !== void 0) return { Stats: obj.Stats }; + if (obj.Progress !== void 0) return { Progress: obj.Progress }; + if (obj.Cont !== void 0) return { Cont: obj.Cont }; + if (obj.End !== void 0) return { End: obj.End }; + if (obj.$unknown !== void 0) return { [obj.$unknown[0]]: "UNKNOWN" }; +}, "SelectObjectContentEventStreamFilterSensitiveLog"); +var SelectObjectContentOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Payload && { Payload: "STREAMING_CONTENT" } +}), "SelectObjectContentOutputFilterSensitiveLog"); +var SelectObjectContentRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "SelectObjectContentRequestFilterSensitiveLog"); +var UploadPartOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartOutputFilterSensitiveLog"); +var UploadPartRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartRequestFilterSensitiveLog"); +var UploadPartCopyOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartCopyOutputFilterSensitiveLog"); +var UploadPartCopyRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.CopySourceSSECustomerKey && { CopySourceSSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartCopyRequestFilterSensitiveLog"); +var WriteGetObjectResponseRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "WriteGetObjectResponseRequestFilterSensitiveLog"); + +// src/protocols/Aws_restXml.ts +var se_AbortMultipartUploadCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaimit]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMIT]), () => (0, import_smithy_client.dateToUtcString)(input[_IMIT]).toString()] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "AbortMultipartUpload"], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_AbortMultipartUploadCommand"); +var se_CompleteMultipartUploadCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xacc]: input[_CCRC], + [_xacc_]: input[_CCRCC], + [_xacc__]: input[_CCRCNVME], + [_xacs]: input[_CSHA], + [_xacs_]: input[_CSHAh], + [_xact]: input[_CT], + [_xamos]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_MOS]), () => input[_MOS].toString()], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_im]: input[_IM], + [_inm]: input[_INM], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + let contents; + if (input.MultipartUpload !== void 0) { + contents = se_CompletedMultipartUpload(input.MultipartUpload, context); + contents = contents.n("CompleteMultipartUpload"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CompleteMultipartUploadCommand"); +var se_CopyObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + [_xaa]: input[_ACL], + [_cc]: input[_CC], + [_xaca]: input[_CA], + [_cd]: input[_CD], + [_ce]: input[_CE], + [_cl]: input[_CL], + [_ct]: input[_CTo], + [_xacs__]: input[_CS], + [_xacsim]: input[_CSIM], + [_xacsims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIMS]).toString()], + [_xacsinm]: input[_CSINM], + [_xacsius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIUS]).toString()], + [_e]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagwa]: input[_GWACP], + [_xamd]: input[_MD], + [_xatd]: input[_TD], + [_xasse]: input[_SSE], + [_xasc]: input[_SC], + [_xawrl]: input[_WRL], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()], + [_xacssseca]: input[_CSSSECA], + [_xacssseck]: input[_CSSSECK], + [_xacssseckm]: input[_CSSSECKMD], + [_xarp]: input[_RP], + [_xat]: input[_T], + [_xaolm]: input[_OLM], + [_xaolrud]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString()], + [_xaollh]: input[_OLLHS], + [_xaebo]: input[_EBO], + [_xasebo]: input[_ESBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "CopyObject"] + }); + let body; + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_CopyObjectCommand"); +var se_CreateBucketCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaa]: input[_ACL], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagw]: input[_GW], + [_xagwa]: input[_GWACP], + [_xabole]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLEFB]), () => input[_OLEFB].toString()], + [_xaoo]: input[_OO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + let body; + let contents; + if (input.CreateBucketConfiguration !== void 0) { + contents = se_CreateBucketConfiguration(input.CreateBucketConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).b(body); + return b.build(); +}, "se_CreateBucketCommand"); +var se_CreateBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mC]: [, ""] + }); + let body; + let contents; + if (input.MetadataConfiguration !== void 0) { + contents = se_MetadataConfiguration(input.MetadataConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateBucketMetadataConfigurationCommand"); +var se_CreateBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mT]: [, ""] + }); + let body; + let contents; + if (input.MetadataTableConfiguration !== void 0) { + contents = se_MetadataTableConfiguration(input.MetadataTableConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateBucketMetadataTableConfigurationCommand"); +var se_CreateMultipartUploadCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + [_xaa]: input[_ACL], + [_cc]: input[_CC], + [_cd]: input[_CD], + [_ce]: input[_CE], + [_cl]: input[_CL], + [_ct]: input[_CTo], + [_e]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagwa]: input[_GWACP], + [_xasse]: input[_SSE], + [_xasc]: input[_SC], + [_xawrl]: input[_WRL], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()], + [_xarp]: input[_RP], + [_xat]: input[_T], + [_xaolm]: input[_OLM], + [_xaolrud]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString()], + [_xaollh]: input[_OLLHS], + [_xaebo]: input[_EBO], + [_xaca]: input[_CA], + [_xact]: input[_CT] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_u]: [, ""] + }); + let body; + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateMultipartUploadCommand"); +var se_CreateSessionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xacsm]: input[_SM], + [_xasse]: input[_SSE], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_s]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateSessionCommand"); +var se_DeleteBucketCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + let body; + b.m("DELETE").h(headers).b(body); + return b.build(); +}, "se_DeleteBucketCommand"); +var se_DeleteBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketAnalyticsConfigurationCommand"); +var se_DeleteBucketCorsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_c]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketCorsCommand"); +var se_DeleteBucketEncryptionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_en]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketEncryptionCommand"); +var se_DeleteBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketIntelligentTieringConfigurationCommand"); +var se_DeleteBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketInventoryConfigurationCommand"); +var se_DeleteBucketLifecycleCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_l]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketLifecycleCommand"); +var se_DeleteBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mC]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketMetadataConfigurationCommand"); +var se_DeleteBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mT]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketMetadataTableConfigurationCommand"); +var se_DeleteBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketMetricsConfigurationCommand"); +var se_DeleteBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_oC]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketOwnershipControlsCommand"); +var se_DeleteBucketPolicyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_p]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketPolicyCommand"); +var se_DeleteBucketReplicationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_r]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketReplicationCommand"); +var se_DeleteBucketTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketTaggingCommand"); +var se_DeleteBucketWebsiteCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_w]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketWebsiteCommand"); +var se_DeleteObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xam]: input[_MFA], + [_xarp]: input[_RP], + [_xabgr]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BGR]), () => input[_BGR].toString()], + [_xaebo]: input[_EBO], + [_im]: input[_IM], + [_xaimlmt]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMLMT]), () => (0, import_smithy_client.dateToUtcString)(input[_IMLMT]).toString()], + [_xaims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMS]), () => input[_IMS].toString()] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "DeleteObject"], + [_vI]: [, input[_VI]] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteObjectCommand"); +var se_DeleteObjectsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xam]: input[_MFA], + [_xarp]: input[_RP], + [_xabgr]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BGR]), () => input[_BGR].toString()], + [_xaebo]: input[_EBO], + [_xasca]: input[_CA] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_d]: [, ""] + }); + let body; + let contents; + if (input.Delete !== void 0) { + contents = se_Delete(input.Delete, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteObjectsCommand"); +var se_DeleteObjectTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteObjectTaggingCommand"); +var se_DeletePublicAccessBlockCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pAB]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeletePublicAccessBlockCommand"); +var se_GetBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ac]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketAccelerateConfigurationCommand"); +var se_GetBucketAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketAclCommand"); +var se_GetBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_xi]: [, "GetBucketAnalyticsConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketAnalyticsConfigurationCommand"); +var se_GetBucketCorsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_c]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketCorsCommand"); +var se_GetBucketEncryptionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_en]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketEncryptionCommand"); +var se_GetBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_xi]: [, "GetBucketIntelligentTieringConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketIntelligentTieringConfigurationCommand"); +var se_GetBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_xi]: [, "GetBucketInventoryConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketInventoryConfigurationCommand"); +var se_GetBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_l]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketLifecycleConfigurationCommand"); +var se_GetBucketLocationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_lo]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketLocationCommand"); +var se_GetBucketLoggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_log]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketLoggingCommand"); +var se_GetBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mC]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketMetadataConfigurationCommand"); +var se_GetBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mT]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketMetadataTableConfigurationCommand"); +var se_GetBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_xi]: [, "GetBucketMetricsConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketMetricsConfigurationCommand"); +var se_GetBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_n]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketNotificationConfigurationCommand"); +var se_GetBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_oC]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketOwnershipControlsCommand"); +var se_GetBucketPolicyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_p]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketPolicyCommand"); +var se_GetBucketPolicyStatusCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pS]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketPolicyStatusCommand"); +var se_GetBucketReplicationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_r]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketReplicationCommand"); +var se_GetBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_rP]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketRequestPaymentCommand"); +var se_GetBucketTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketTaggingCommand"); +var se_GetBucketVersioningCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_v]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketVersioningCommand"); +var se_GetBucketWebsiteCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_w]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketWebsiteCommand"); +var se_GetObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_im]: input[_IM], + [_ims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMSf]), () => (0, import_smithy_client.dateToUtcString)(input[_IMSf]).toString()], + [_inm]: input[_INM], + [_ius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IUS]), () => (0, import_smithy_client.dateToUtcString)(input[_IUS]).toString()], + [_ra]: input[_R], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xacm]: input[_CM] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "GetObject"], + [_rcc]: [, input[_RCC]], + [_rcd]: [, input[_RCD]], + [_rce]: [, input[_RCE]], + [_rcl]: [, input[_RCL]], + [_rct]: [, input[_RCT]], + [_re]: [() => input.ResponseExpires !== void 0, () => (0, import_smithy_client.dateToUtcString)(input[_RE]).toString()], + [_vI]: [, input[_VI]], + [_pN]: [() => input.PartNumber !== void 0, () => input[_PN].toString()] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectCommand"); +var se_GetObjectAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectAclCommand"); +var se_GetObjectAttributesCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xamp]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_MP]), () => input[_MP].toString()], + [_xapnm]: input[_PNM], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaoa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OA]), () => (input[_OA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_at]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectAttributesCommand"); +var se_GetObjectLegalHoldCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_lh]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectLegalHoldCommand"); +var se_GetObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ol]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectLockConfigurationCommand"); +var se_GetObjectRetentionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_ret]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectRetentionCommand"); +var se_GetObjectTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectTaggingCommand"); +var se_GetObjectTorrentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_to]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectTorrentCommand"); +var se_GetPublicAccessBlockCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pAB]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetPublicAccessBlockCommand"); +var se_HeadBucketCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + let body; + b.m("HEAD").h(headers).b(body); + return b.build(); +}, "se_HeadBucketCommand"); +var se_HeadObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_im]: input[_IM], + [_ims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMSf]), () => (0, import_smithy_client.dateToUtcString)(input[_IMSf]).toString()], + [_inm]: input[_INM], + [_ius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IUS]), () => (0, import_smithy_client.dateToUtcString)(input[_IUS]).toString()], + [_ra]: input[_R], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xacm]: input[_CM] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_rcc]: [, input[_RCC]], + [_rcd]: [, input[_RCD]], + [_rce]: [, input[_RCE]], + [_rcl]: [, input[_RCL]], + [_rct]: [, input[_RCT]], + [_re]: [() => input.ResponseExpires !== void 0, () => (0, import_smithy_client.dateToUtcString)(input[_RE]).toString()], + [_vI]: [, input[_VI]], + [_pN]: [() => input.PartNumber !== void 0, () => input[_PN].toString()] + }); + let body; + b.m("HEAD").h(headers).q(query).b(body); + return b.build(); +}, "se_HeadObjectCommand"); +var se_ListBucketAnalyticsConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_xi]: [, "ListBucketAnalyticsConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketAnalyticsConfigurationsCommand"); +var se_ListBucketIntelligentTieringConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_xi]: [, "ListBucketIntelligentTieringConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketIntelligentTieringConfigurationsCommand"); +var se_ListBucketInventoryConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_xi]: [, "ListBucketInventoryConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketInventoryConfigurationsCommand"); +var se_ListBucketMetricsConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_xi]: [, "ListBucketMetricsConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketMetricsConfigurationsCommand"); +var se_ListBucketsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = {}; + b.bp("/"); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "ListBuckets"], + [_mb]: [() => input.MaxBuckets !== void 0, () => input[_MB].toString()], + [_ct_]: [, input[_CTon]], + [_pr]: [, input[_P]], + [_br]: [, input[_BR]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketsCommand"); +var se_ListDirectoryBucketsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = {}; + b.bp("/"); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "ListDirectoryBuckets"], + [_ct_]: [, input[_CTon]], + [_mdb]: [() => input.MaxDirectoryBuckets !== void 0, () => input[_MDB].toString()] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListDirectoryBucketsCommand"); +var se_ListMultipartUploadsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_u]: [, ""], + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_km]: [, input[_KM]], + [_mu]: [() => input.MaxUploads !== void 0, () => input[_MU].toString()], + [_pr]: [, input[_P]], + [_uim]: [, input[_UIM]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListMultipartUploadsCommand"); +var se_ListObjectsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaooa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OOA]), () => (input[_OOA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_ma]: [, input[_M]], + [_mk]: [() => input.MaxKeys !== void 0, () => input[_MK].toString()], + [_pr]: [, input[_P]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListObjectsCommand"); +var se_ListObjectsV2Command = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaooa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OOA]), () => (input[_OOA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_lt]: [, "2"], + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_mk]: [() => input.MaxKeys !== void 0, () => input[_MK].toString()], + [_pr]: [, input[_P]], + [_ct_]: [, input[_CTon]], + [_fo]: [() => input.FetchOwner !== void 0, () => input[_FO].toString()], + [_sa]: [, input[_SA]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListObjectsV2Command"); +var se_ListObjectVersionsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP], + [_xaooa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OOA]), () => (input[_OOA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ver]: [, ""], + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_km]: [, input[_KM]], + [_mk]: [() => input.MaxKeys !== void 0, () => input[_MK].toString()], + [_pr]: [, input[_P]], + [_vim]: [, input[_VIM]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListObjectVersionsCommand"); +var se_ListPartsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "ListParts"], + [_mp]: [() => input.MaxParts !== void 0, () => input[_MP].toString()], + [_pnm]: [, input[_PNM]], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListPartsCommand"); +var se_PutBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO], + [_xasca]: input[_CA] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ac]: [, ""] + }); + let body; + let contents; + if (input.AccelerateConfiguration !== void 0) { + contents = se_AccelerateConfiguration(input.AccelerateConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketAccelerateConfigurationCommand"); +var se_PutBucketAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaa]: input[_ACL], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagw]: input[_GW], + [_xagwa]: input[_GWACP], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""] + }); + let body; + let contents; + if (input.AccessControlPolicy !== void 0) { + contents = se_AccessControlPolicy(input.AccessControlPolicy, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketAclCommand"); +var se_PutBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.AnalyticsConfiguration !== void 0) { + contents = se_AnalyticsConfiguration(input.AnalyticsConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketAnalyticsConfigurationCommand"); +var se_PutBucketCorsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_c]: [, ""] + }); + let body; + let contents; + if (input.CORSConfiguration !== void 0) { + contents = se_CORSConfiguration(input.CORSConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketCorsCommand"); +var se_PutBucketEncryptionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_en]: [, ""] + }); + let body; + let contents; + if (input.ServerSideEncryptionConfiguration !== void 0) { + contents = se_ServerSideEncryptionConfiguration(input.ServerSideEncryptionConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketEncryptionCommand"); +var se_PutBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.IntelligentTieringConfiguration !== void 0) { + contents = se_IntelligentTieringConfiguration(input.IntelligentTieringConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketIntelligentTieringConfigurationCommand"); +var se_PutBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.InventoryConfiguration !== void 0) { + contents = se_InventoryConfiguration(input.InventoryConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketInventoryConfigurationCommand"); +var se_PutBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xasca]: input[_CA], + [_xaebo]: input[_EBO], + [_xatdmos]: input[_TDMOS] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_l]: [, ""] + }); + let body; + let contents; + if (input.LifecycleConfiguration !== void 0) { + contents = se_BucketLifecycleConfiguration(input.LifecycleConfiguration, context); + contents = contents.n("LifecycleConfiguration"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketLifecycleConfigurationCommand"); +var se_PutBucketLoggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_log]: [, ""] + }); + let body; + let contents; + if (input.BucketLoggingStatus !== void 0) { + contents = se_BucketLoggingStatus(input.BucketLoggingStatus, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketLoggingCommand"); +var se_PutBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.MetricsConfiguration !== void 0) { + contents = se_MetricsConfiguration(input.MetricsConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketMetricsConfigurationCommand"); +var se_PutBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO], + [_xasdv]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SDV]), () => input[_SDV].toString()] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_n]: [, ""] + }); + let body; + let contents; + if (input.NotificationConfiguration !== void 0) { + contents = se_NotificationConfiguration(input.NotificationConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketNotificationConfigurationCommand"); +var se_PutBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xaebo]: input[_EBO], + [_xasca]: input[_CA] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_oC]: [, ""] + }); + let body; + let contents; + if (input.OwnershipControls !== void 0) { + contents = se_OwnershipControls(input.OwnershipControls, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketOwnershipControlsCommand"); +var se_PutBucketPolicyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "text/plain", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xacrsba]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CRSBA]), () => input[_CRSBA].toString()], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_p]: [, ""] + }); + let body; + let contents; + if (input.Policy !== void 0) { + contents = input.Policy; + body = contents; + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketPolicyCommand"); +var se_PutBucketReplicationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xabolt]: input[_To], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_r]: [, ""] + }); + let body; + let contents; + if (input.ReplicationConfiguration !== void 0) { + contents = se_ReplicationConfiguration(input.ReplicationConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketReplicationCommand"); +var se_PutBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_rP]: [, ""] + }); + let body; + let contents; + if (input.RequestPaymentConfiguration !== void 0) { + contents = se_RequestPaymentConfiguration(input.RequestPaymentConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketRequestPaymentCommand"); +var se_PutBucketTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""] + }); + let body; + let contents; + if (input.Tagging !== void 0) { + contents = se_Tagging(input.Tagging, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketTaggingCommand"); +var se_PutBucketVersioningCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xam]: input[_MFA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_v]: [, ""] + }); + let body; + let contents; + if (input.VersioningConfiguration !== void 0) { + contents = se_VersioningConfiguration(input.VersioningConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketVersioningCommand"); +var se_PutBucketWebsiteCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_w]: [, ""] + }); + let body; + let contents; + if (input.WebsiteConfiguration !== void 0) { + contents = se_WebsiteConfiguration(input.WebsiteConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketWebsiteCommand"); +var se_PutObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + [_ct]: input[_CTo] || "application/octet-stream", + [_xaa]: input[_ACL], + [_cc]: input[_CC], + [_cd]: input[_CD], + [_ce]: input[_CE], + [_cl]: input[_CL], + [_cl_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CLo]), () => input[_CLo].toString()], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xacc]: input[_CCRC], + [_xacc_]: input[_CCRCC], + [_xacc__]: input[_CCRCNVME], + [_xacs]: input[_CSHA], + [_xacs_]: input[_CSHAh], + [_e]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_im]: input[_IM], + [_inm]: input[_INM], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagwa]: input[_GWACP], + [_xawob]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_WOB]), () => input[_WOB].toString()], + [_xasse]: input[_SSE], + [_xasc]: input[_SC], + [_xawrl]: input[_WRL], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()], + [_xarp]: input[_RP], + [_xat]: input[_T], + [_xaolm]: input[_OLM], + [_xaolrud]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString()], + [_xaollh]: input[_OLLHS], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "PutObject"] + }); + let body; + let contents; + if (input.Body !== void 0) { + contents = input.Body; + body = contents; + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectCommand"); +var se_PutObjectAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaa]: input[_ACL], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagw]: input[_GW], + [_xagwa]: input[_GWACP], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.AccessControlPolicy !== void 0) { + contents = se_AccessControlPolicy(input.AccessControlPolicy, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectAclCommand"); +var se_PutObjectLegalHoldCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_lh]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.LegalHold !== void 0) { + contents = se_ObjectLockLegalHold(input.LegalHold, context); + contents = contents.n("LegalHold"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectLegalHoldCommand"); +var se_PutObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_xabolt]: input[_To], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ol]: [, ""] + }); + let body; + let contents; + if (input.ObjectLockConfiguration !== void 0) { + contents = se_ObjectLockConfiguration(input.ObjectLockConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectLockConfigurationCommand"); +var se_PutObjectRetentionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_xabgr]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BGR]), () => input[_BGR].toString()], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_ret]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.Retention !== void 0) { + contents = se_ObjectLockRetention(input.Retention, context); + contents = contents.n("Retention"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectRetentionCommand"); +var se_PutObjectTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.Tagging !== void 0) { + contents = se_Tagging(input.Tagging, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectTaggingCommand"); +var se_PutPublicAccessBlockCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pAB]: [, ""] + }); + let body; + let contents; + if (input.PublicAccessBlockConfiguration !== void 0) { + contents = se_PublicAccessBlockConfiguration(input.PublicAccessBlockConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutPublicAccessBlockCommand"); +var se_RenameObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xars]: input[_RS], + [_im]: input[_DIM], + [_inm]: input[_DINM], + [_ims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_DIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_DIMS]).toString()], + [_ius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_DIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_DIUS]).toString()], + [_xarsim]: input[_SIM], + [_xarsinm]: input[_SINM], + [_xarsims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_SIMS]).toString()], + [_xarsius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_SIUS]).toString()], + [_xact_]: input[_CTl] ?? (0, import_uuid.v4)() + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_rO]: [, ""] + }); + let body; + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_RenameObjectCommand"); +var se_RestoreObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_res]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.RestoreRequest !== void 0) { + contents = se_RestoreRequest(input.RestoreRequest, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_RestoreObjectCommand"); +var se_SelectObjectContentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_se]: [, ""], + [_st]: [, "2"] + }); + let body; + body = _ve; + const bn = new import_xml_builder.XmlNode(_SOCR); + bn.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + bn.cc(input, _Ex); + bn.cc(input, _ETx); + if (input[_IS] != null) { + bn.c(se_InputSerialization(input[_IS], context).n(_IS)); + } + if (input[_OS] != null) { + bn.c(se_OutputSerialization(input[_OS], context).n(_OS)); + } + if (input[_RPe] != null) { + bn.c(se_RequestProgress(input[_RPe], context).n(_RPe)); + } + if (input[_SR] != null) { + bn.c(se_ScanRange(input[_SR], context).n(_SR)); + } + body += bn.toString(); + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_SelectObjectContentCommand"); +var se_UpdateBucketMetadataInventoryTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mIT]: [, ""] + }); + let body; + let contents; + if (input.InventoryTableConfiguration !== void 0) { + contents = se_InventoryTableConfigurationUpdates(input.InventoryTableConfiguration, context); + contents = contents.n("InventoryTableConfiguration"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UpdateBucketMetadataInventoryTableConfigurationCommand"); +var se_UpdateBucketMetadataJournalTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mJT]: [, ""] + }); + let body; + let contents; + if (input.JournalTableConfiguration !== void 0) { + contents = se_JournalTableConfigurationUpdates(input.JournalTableConfiguration, context); + contents = contents.n("JournalTableConfiguration"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UpdateBucketMetadataJournalTableConfigurationCommand"); +var se_UploadPartCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/octet-stream", + [_cl_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CLo]), () => input[_CLo].toString()], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xacc]: input[_CCRC], + [_xacc_]: input[_CCRCC], + [_xacc__]: input[_CCRCNVME], + [_xacs]: input[_CSHA], + [_xacs_]: input[_CSHAh], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "UploadPart"], + [_pN]: [(0, import_smithy_client.expectNonNull)(input.PartNumber, `PartNumber`) != null, () => input[_PN].toString()], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + let contents; + if (input.Body !== void 0) { + contents = input.Body; + body = contents; + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UploadPartCommand"); +var se_UploadPartCopyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xacs__]: input[_CS], + [_xacsim]: input[_CSIM], + [_xacsims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIMS]).toString()], + [_xacsinm]: input[_CSINM], + [_xacsius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIUS]).toString()], + [_xacsr]: input[_CSR], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xacssseca]: input[_CSSSECA], + [_xacssseck]: input[_CSSSECK], + [_xacssseckm]: input[_CSSSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xasebo]: input[_ESBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "UploadPartCopy"], + [_pN]: [(0, import_smithy_client.expectNonNull)(input.PartNumber, `PartNumber`) != null, () => input[_PN].toString()], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UploadPartCopyCommand"); +var se_WriteGetObjectResponseCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "x-amz-content-sha256": "UNSIGNED-PAYLOAD", + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + "content-type": "application/octet-stream", + [_xarr]: input[_RR], + [_xart]: input[_RT], + [_xafs]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SCt]), () => input[_SCt].toString()], + [_xafec]: input[_EC], + [_xafem]: input[_EM], + [_xafhar]: input[_AR], + [_xafhcc]: input[_CC], + [_xafhcd]: input[_CD], + [_xafhce]: input[_CE], + [_xafhcl]: input[_CL], + [_cl_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CLo]), () => input[_CLo].toString()], + [_xafhcr]: input[_CR], + [_xafhct]: input[_CTo], + [_xafhxacc]: input[_CCRC], + [_xafhxacc_]: input[_CCRCC], + [_xafhxacc__]: input[_CCRCNVME], + [_xafhxacs]: input[_CSHA], + [_xafhxacs_]: input[_CSHAh], + [_xafhxadm]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_DM]), () => input[_DM].toString()], + [_xafhe]: input[_ETa], + [_xafhe_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_xafhxae]: input[_Exp], + [_xafhlm]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_LM]), () => (0, import_smithy_client.dateToUtcString)(input[_LM]).toString()], + [_xafhxamm]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_MM]), () => input[_MM].toString()], + [_xafhxaolm]: input[_OLM], + [_xafhxaollh]: input[_OLLHS], + [_xafhxaolrud]: [ + () => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), + () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString() + ], + [_xafhxampc]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_PC]), () => input[_PC].toString()], + [_xafhxars]: input[_RSe], + [_xafhxarc]: input[_RC], + [_xafhxar]: input[_Re], + [_xafhxasse]: input[_SSE], + [_xafhxasseca]: input[_SSECA], + [_xafhxasseakki]: input[_SSEKMSKI], + [_xafhxasseckm]: input[_SSECKMD], + [_xafhxasc]: input[_SC], + [_xafhxatc]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_TC]), () => input[_TC].toString()], + [_xafhxavi]: input[_VI], + [_xafhxassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()] + }); + b.bp("/WriteGetObjectResponse"); + let body; + let contents; + if (input.Body !== void 0) { + contents = input.Body; + body = contents; + } + let { hostname: resolvedHostname } = await context.endpoint(); + if (context.disableHostPrefix !== true) { + resolvedHostname = "{RequestRoute}." + resolvedHostname; + if (input.RequestRoute === void 0) { + throw new Error("Empty value provided for input host prefix: RequestRoute."); + } + resolvedHostname = resolvedHostname.replace("{RequestRoute}", input.RequestRoute); + if (!(0, import_protocol_http.isValidHostname)(resolvedHostname)) { + throw new Error("ValidationError: prefixed hostname must be hostname compatible."); + } + } + b.hn(resolvedHostname); + b.m("POST").h(headers).b(body); + return b.build(); +}, "se_WriteGetObjectResponseCommand"); +var de_AbortMultipartUploadCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_AbortMultipartUploadCommand"); +var de_CompleteMultipartUploadCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_Exp]: [, output.headers[_xae]], + [_SSE]: [, output.headers[_xasse]], + [_VI]: [, output.headers[_xavi]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(data[_CCRC]); + } + if (data[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(data[_CCRCC]); + } + if (data[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(data[_CCRCNVME]); + } + if (data[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(data[_CSHA]); + } + if (data[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(data[_CSHAh]); + } + if (data[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(data[_CT]); + } + if (data[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(data[_ETa]); + } + if (data[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(data[_K]); + } + if (data[_L] != null) { + contents[_L] = (0, import_smithy_client.expectString)(data[_L]); + } + return contents; +}, "de_CompleteMultipartUploadCommand"); +var de_CopyObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_Exp]: [, output.headers[_xae]], + [_CSVI]: [, output.headers[_xacsvi]], + [_VI]: [, output.headers[_xavi]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.CopyObjectResult = de_CopyObjectResult(data, context); + return contents; +}, "de_CopyObjectCommand"); +var de_CreateBucketCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_L]: [, output.headers[_lo]], + [_BA]: [, output.headers[_xaba]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_CreateBucketCommand"); +var de_CreateBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_CreateBucketMetadataConfigurationCommand"); +var de_CreateBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_CreateBucketMetadataTableConfigurationCommand"); +var de_CreateMultipartUploadCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_AD]: [ + () => void 0 !== output.headers[_xaad], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_xaad])) + ], + [_ARI]: [, output.headers[_xaari]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]], + [_CA]: [, output.headers[_xaca]], + [_CT]: [, output.headers[_xact]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(data[_K]); + } + if (data[_UI] != null) { + contents[_UI] = (0, import_smithy_client.expectString)(data[_UI]); + } + return contents; +}, "de_CreateMultipartUploadCommand"); +var de_CreateSessionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_SSE]: [, output.headers[_xasse]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_C] != null) { + contents[_C] = de_SessionCredentials(data[_C], context); + } + return contents; +}, "de_CreateSessionCommand"); +var de_DeleteBucketCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketCommand"); +var de_DeleteBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketAnalyticsConfigurationCommand"); +var de_DeleteBucketCorsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketCorsCommand"); +var de_DeleteBucketEncryptionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketEncryptionCommand"); +var de_DeleteBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketIntelligentTieringConfigurationCommand"); +var de_DeleteBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketInventoryConfigurationCommand"); +var de_DeleteBucketLifecycleCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketLifecycleCommand"); +var de_DeleteBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketMetadataConfigurationCommand"); +var de_DeleteBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketMetadataTableConfigurationCommand"); +var de_DeleteBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketMetricsConfigurationCommand"); +var de_DeleteBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketOwnershipControlsCommand"); +var de_DeleteBucketPolicyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketPolicyCommand"); +var de_DeleteBucketReplicationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketReplicationCommand"); +var de_DeleteBucketTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketTaggingCommand"); +var de_DeleteBucketWebsiteCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketWebsiteCommand"); +var de_DeleteObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_VI]: [, output.headers[_xavi]], + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteObjectCommand"); +var de_DeleteObjectsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Deleted === "") { + contents[_De] = []; + } else if (data[_De] != null) { + contents[_De] = de_DeletedObjects((0, import_smithy_client.getArrayIfSingleItem)(data[_De]), context); + } + if (data.Error === "") { + contents[_Err] = []; + } else if (data[_Er] != null) { + contents[_Err] = de_Errors((0, import_smithy_client.getArrayIfSingleItem)(data[_Er]), context); + } + return contents; +}, "de_DeleteObjectsCommand"); +var de_DeleteObjectTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_VI]: [, output.headers[_xavi]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteObjectTaggingCommand"); +var de_DeletePublicAccessBlockCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeletePublicAccessBlockCommand"); +var de_GetBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(data[_S]); + } + return contents; +}, "de_GetBucketAccelerateConfigurationCommand"); +var de_GetBucketAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.AccessControlList === "") { + contents[_Gr] = []; + } else if (data[_ACLc] != null && data[_ACLc][_G] != null) { + contents[_Gr] = de_Grants((0, import_smithy_client.getArrayIfSingleItem)(data[_ACLc][_G]), context); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + return contents; +}, "de_GetBucketAclCommand"); +var de_GetBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.AnalyticsConfiguration = de_AnalyticsConfiguration(data, context); + return contents; +}, "de_GetBucketAnalyticsConfigurationCommand"); +var de_GetBucketCorsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CORSRule === "") { + contents[_CORSRu] = []; + } else if (data[_CORSR] != null) { + contents[_CORSRu] = de_CORSRules((0, import_smithy_client.getArrayIfSingleItem)(data[_CORSR]), context); + } + return contents; +}, "de_GetBucketCorsCommand"); +var de_GetBucketEncryptionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.ServerSideEncryptionConfiguration = de_ServerSideEncryptionConfiguration(data, context); + return contents; +}, "de_GetBucketEncryptionCommand"); +var de_GetBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.IntelligentTieringConfiguration = de_IntelligentTieringConfiguration(data, context); + return contents; +}, "de_GetBucketIntelligentTieringConfigurationCommand"); +var de_GetBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.InventoryConfiguration = de_InventoryConfiguration(data, context); + return contents; +}, "de_GetBucketInventoryConfigurationCommand"); +var de_GetBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_TDMOS]: [, output.headers[_xatdmos]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Rule === "") { + contents[_Rul] = []; + } else if (data[_Ru] != null) { + contents[_Rul] = de_LifecycleRules((0, import_smithy_client.getArrayIfSingleItem)(data[_Ru]), context); + } + return contents; +}, "de_GetBucketLifecycleConfigurationCommand"); +var de_GetBucketLocationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_LC] != null) { + contents[_LC] = (0, import_smithy_client.expectString)(data[_LC]); + } + return contents; +}, "de_GetBucketLocationCommand"); +var de_GetBucketLoggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_LE] != null) { + contents[_LE] = de_LoggingEnabled(data[_LE], context); + } + return contents; +}, "de_GetBucketLoggingCommand"); +var de_GetBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.GetBucketMetadataConfigurationResult = de_GetBucketMetadataConfigurationResult(data, context); + return contents; +}, "de_GetBucketMetadataConfigurationCommand"); +var de_GetBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.GetBucketMetadataTableConfigurationResult = de_GetBucketMetadataTableConfigurationResult(data, context); + return contents; +}, "de_GetBucketMetadataTableConfigurationCommand"); +var de_GetBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.MetricsConfiguration = de_MetricsConfiguration(data, context); + return contents; +}, "de_GetBucketMetricsConfigurationCommand"); +var de_GetBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_EBC] != null) { + contents[_EBC] = de_EventBridgeConfiguration(data[_EBC], context); + } + if (data.CloudFunctionConfiguration === "") { + contents[_LFC] = []; + } else if (data[_CFC] != null) { + contents[_LFC] = de_LambdaFunctionConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_CFC]), context); + } + if (data.QueueConfiguration === "") { + contents[_QCu] = []; + } else if (data[_QC] != null) { + contents[_QCu] = de_QueueConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_QC]), context); + } + if (data.TopicConfiguration === "") { + contents[_TCop] = []; + } else if (data[_TCo] != null) { + contents[_TCop] = de_TopicConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_TCo]), context); + } + return contents; +}, "de_GetBucketNotificationConfigurationCommand"); +var de_GetBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.OwnershipControls = de_OwnershipControls(data, context); + return contents; +}, "de_GetBucketOwnershipControlsCommand"); +var de_GetBucketPolicyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = await collectBodyString(output.body, context); + contents.Policy = (0, import_smithy_client.expectString)(data); + return contents; +}, "de_GetBucketPolicyCommand"); +var de_GetBucketPolicyStatusCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.PolicyStatus = de_PolicyStatus(data, context); + return contents; +}, "de_GetBucketPolicyStatusCommand"); +var de_GetBucketReplicationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.ReplicationConfiguration = de_ReplicationConfiguration(data, context); + return contents; +}, "de_GetBucketReplicationCommand"); +var de_GetBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_Pa] != null) { + contents[_Pa] = (0, import_smithy_client.expectString)(data[_Pa]); + } + return contents; +}, "de_GetBucketRequestPaymentCommand"); +var de_GetBucketTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.TagSet === "") { + contents[_TS] = []; + } else if (data[_TS] != null && data[_TS][_Ta] != null) { + contents[_TS] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(data[_TS][_Ta]), context); + } + return contents; +}, "de_GetBucketTaggingCommand"); +var de_GetBucketVersioningCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_MDf] != null) { + contents[_MFAD] = (0, import_smithy_client.expectString)(data[_MDf]); + } + if (data[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(data[_S]); + } + return contents; +}, "de_GetBucketVersioningCommand"); +var de_GetBucketWebsiteCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_ED] != null) { + contents[_ED] = de_ErrorDocument(data[_ED], context); + } + if (data[_ID] != null) { + contents[_ID] = de_IndexDocument(data[_ID], context); + } + if (data[_RART] != null) { + contents[_RART] = de_RedirectAllRequestsTo(data[_RART], context); + } + if (data.RoutingRules === "") { + contents[_RRo] = []; + } else if (data[_RRo] != null && data[_RRo][_RRou] != null) { + contents[_RRo] = de_RoutingRules((0, import_smithy_client.getArrayIfSingleItem)(data[_RRo][_RRou]), context); + } + return contents; +}, "de_GetBucketWebsiteCommand"); +var de_GetObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_AR]: [, output.headers[_ar]], + [_Exp]: [, output.headers[_xae]], + [_Re]: [, output.headers[_xar]], + [_LM]: [() => void 0 !== output.headers[_lm], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_lm]))], + [_CLo]: [() => void 0 !== output.headers[_cl_], () => (0, import_smithy_client.strictParseLong)(output.headers[_cl_])], + [_ETa]: [, output.headers[_eta]], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_CT]: [, output.headers[_xact]], + [_MM]: [() => void 0 !== output.headers[_xamm], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xamm])], + [_VI]: [, output.headers[_xavi]], + [_CC]: [, output.headers[_cc]], + [_CD]: [, output.headers[_cd]], + [_CE]: [, output.headers[_ce]], + [_CL]: [, output.headers[_cl]], + [_CR]: [, output.headers[_cr]], + [_CTo]: [, output.headers[_ct]], + [_E]: [() => void 0 !== output.headers[_e], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_e]))], + [_ES]: [, output.headers[_ex]], + [_WRL]: [, output.headers[_xawrl]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_SC]: [, output.headers[_xasc]], + [_RC]: [, output.headers[_xarc]], + [_RSe]: [, output.headers[_xars_]], + [_PC]: [() => void 0 !== output.headers[_xampc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xampc])], + [_TC]: [() => void 0 !== output.headers[_xatc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xatc])], + [_OLM]: [, output.headers[_xaolm]], + [_OLRUD]: [ + () => void 0 !== output.headers[_xaolrud], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output.headers[_xaolrud])) + ], + [_OLLHS]: [, output.headers[_xaollh]], + Metadata: [ + , + Object.keys(output.headers).filter((header) => header.startsWith("x-amz-meta-")).reduce((acc, header) => { + acc[header.substring(11)] = output.headers[header]; + return acc; + }, {}) + ] + }); + const data = output.body; + context.sdkStreamMixin(data); + contents.Body = data; + return contents; +}, "de_GetObjectCommand"); +var de_GetObjectAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.AccessControlList === "") { + contents[_Gr] = []; + } else if (data[_ACLc] != null && data[_ACLc][_G] != null) { + contents[_Gr] = de_Grants((0, import_smithy_client.getArrayIfSingleItem)(data[_ACLc][_G]), context); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + return contents; +}, "de_GetObjectAclCommand"); +var de_GetObjectAttributesCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_LM]: [() => void 0 !== output.headers[_lm], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_lm]))], + [_VI]: [, output.headers[_xavi]], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_Ch] != null) { + contents[_Ch] = de_Checksum(data[_Ch], context); + } + if (data[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(data[_ETa]); + } + if (data[_OP] != null) { + contents[_OP] = de_GetObjectAttributesParts(data[_OP], context); + } + if (data[_OSb] != null) { + contents[_OSb] = (0, import_smithy_client.strictParseLong)(data[_OSb]); + } + if (data[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(data[_SC]); + } + return contents; +}, "de_GetObjectAttributesCommand"); +var de_GetObjectLegalHoldCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.LegalHold = de_ObjectLockLegalHold(data, context); + return contents; +}, "de_GetObjectLegalHoldCommand"); +var de_GetObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.ObjectLockConfiguration = de_ObjectLockConfiguration(data, context); + return contents; +}, "de_GetObjectLockConfigurationCommand"); +var de_GetObjectRetentionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.Retention = de_ObjectLockRetention(data, context); + return contents; +}, "de_GetObjectRetentionCommand"); +var de_GetObjectTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_VI]: [, output.headers[_xavi]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.TagSet === "") { + contents[_TS] = []; + } else if (data[_TS] != null && data[_TS][_Ta] != null) { + contents[_TS] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(data[_TS][_Ta]), context); + } + return contents; +}, "de_GetObjectTaggingCommand"); +var de_GetObjectTorrentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = output.body; + context.sdkStreamMixin(data); + contents.Body = data; + return contents; +}, "de_GetObjectTorrentCommand"); +var de_GetPublicAccessBlockCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.PublicAccessBlockConfiguration = de_PublicAccessBlockConfiguration(data, context); + return contents; +}, "de_GetPublicAccessBlockCommand"); +var de_HeadBucketCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_BA]: [, output.headers[_xaba]], + [_BLT]: [, output.headers[_xablt]], + [_BLN]: [, output.headers[_xabln]], + [_BR]: [, output.headers[_xabr]], + [_APA]: [() => void 0 !== output.headers[_xaapa], () => (0, import_smithy_client.parseBoolean)(output.headers[_xaapa])] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_HeadBucketCommand"); +var de_HeadObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_AR]: [, output.headers[_ar]], + [_Exp]: [, output.headers[_xae]], + [_Re]: [, output.headers[_xar]], + [_AS]: [, output.headers[_xaas]], + [_LM]: [() => void 0 !== output.headers[_lm], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_lm]))], + [_CLo]: [() => void 0 !== output.headers[_cl_], () => (0, import_smithy_client.strictParseLong)(output.headers[_cl_])], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_CT]: [, output.headers[_xact]], + [_ETa]: [, output.headers[_eta]], + [_MM]: [() => void 0 !== output.headers[_xamm], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xamm])], + [_VI]: [, output.headers[_xavi]], + [_CC]: [, output.headers[_cc]], + [_CD]: [, output.headers[_cd]], + [_CE]: [, output.headers[_ce]], + [_CL]: [, output.headers[_cl]], + [_CTo]: [, output.headers[_ct]], + [_CR]: [, output.headers[_cr]], + [_E]: [() => void 0 !== output.headers[_e], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_e]))], + [_ES]: [, output.headers[_ex]], + [_WRL]: [, output.headers[_xawrl]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_SC]: [, output.headers[_xasc]], + [_RC]: [, output.headers[_xarc]], + [_RSe]: [, output.headers[_xars_]], + [_PC]: [() => void 0 !== output.headers[_xampc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xampc])], + [_TC]: [() => void 0 !== output.headers[_xatc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xatc])], + [_OLM]: [, output.headers[_xaolm]], + [_OLRUD]: [ + () => void 0 !== output.headers[_xaolrud], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output.headers[_xaolrud])) + ], + [_OLLHS]: [, output.headers[_xaollh]], + Metadata: [ + , + Object.keys(output.headers).filter((header) => header.startsWith("x-amz-meta-")).reduce((acc, header) => { + acc[header.substring(11)] = output.headers[header]; + return acc; + }, {}) + ] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_HeadObjectCommand"); +var de_ListBucketAnalyticsConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.AnalyticsConfiguration === "") { + contents[_ACLn] = []; + } else if (data[_AC] != null) { + contents[_ACLn] = de_AnalyticsConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_AC]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketAnalyticsConfigurationsCommand"); +var de_ListBucketIntelligentTieringConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data.IntelligentTieringConfiguration === "") { + contents[_ITCL] = []; + } else if (data[_ITC] != null) { + contents[_ITCL] = de_IntelligentTieringConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_ITC]), context); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketIntelligentTieringConfigurationsCommand"); +var de_ListBucketInventoryConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data.InventoryConfiguration === "") { + contents[_ICL] = []; + } else if (data[_IC] != null) { + contents[_ICL] = de_InventoryConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_IC]), context); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketInventoryConfigurationsCommand"); +var de_ListBucketMetricsConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data.MetricsConfiguration === "") { + contents[_MCL] = []; + } else if (data[_MC] != null) { + contents[_MCL] = de_MetricsConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_MC]), context); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketMetricsConfigurationsCommand"); +var de_ListBucketsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Buckets === "") { + contents[_Bu] = []; + } else if (data[_Bu] != null && data[_Bu][_B] != null) { + contents[_Bu] = de_Buckets((0, import_smithy_client.getArrayIfSingleItem)(data[_Bu][_B]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + return contents; +}, "de_ListBucketsCommand"); +var de_ListDirectoryBucketsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Buckets === "") { + contents[_Bu] = []; + } else if (data[_Bu] != null && data[_Bu][_B] != null) { + contents[_Bu] = de_Buckets((0, import_smithy_client.getArrayIfSingleItem)(data[_Bu][_B]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + return contents; +}, "de_ListDirectoryBucketsCommand"); +var de_ListMultipartUploadsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_KM] != null) { + contents[_KM] = (0, import_smithy_client.expectString)(data[_KM]); + } + if (data[_MU] != null) { + contents[_MU] = (0, import_smithy_client.strictParseInt32)(data[_MU]); + } + if (data[_NKM] != null) { + contents[_NKM] = (0, import_smithy_client.expectString)(data[_NKM]); + } + if (data[_NUIM] != null) { + contents[_NUIM] = (0, import_smithy_client.expectString)(data[_NUIM]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + if (data[_UIM] != null) { + contents[_UIM] = (0, import_smithy_client.expectString)(data[_UIM]); + } + if (data.Upload === "") { + contents[_Up] = []; + } else if (data[_U] != null) { + contents[_Up] = de_MultipartUploadList((0, import_smithy_client.getArrayIfSingleItem)(data[_U]), context); + } + return contents; +}, "de_ListMultipartUploadsCommand"); +var de_ListObjectsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data.Contents === "") { + contents[_Co] = []; + } else if (data[_Co] != null) { + contents[_Co] = de_ObjectList((0, import_smithy_client.getArrayIfSingleItem)(data[_Co]), context); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_M] != null) { + contents[_M] = (0, import_smithy_client.expectString)(data[_M]); + } + if (data[_MK] != null) { + contents[_MK] = (0, import_smithy_client.strictParseInt32)(data[_MK]); + } + if (data[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(data[_N]); + } + if (data[_NM] != null) { + contents[_NM] = (0, import_smithy_client.expectString)(data[_NM]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + return contents; +}, "de_ListObjectsCommand"); +var de_ListObjectsV2Command = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data.Contents === "") { + contents[_Co] = []; + } else if (data[_Co] != null) { + contents[_Co] = de_ObjectList((0, import_smithy_client.getArrayIfSingleItem)(data[_Co]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_KC] != null) { + contents[_KC] = (0, import_smithy_client.strictParseInt32)(data[_KC]); + } + if (data[_MK] != null) { + contents[_MK] = (0, import_smithy_client.strictParseInt32)(data[_MK]); + } + if (data[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(data[_N]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + if (data[_SA] != null) { + contents[_SA] = (0, import_smithy_client.expectString)(data[_SA]); + } + return contents; +}, "de_ListObjectsV2Command"); +var de_ListObjectVersionsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data.DeleteMarker === "") { + contents[_DMe] = []; + } else if (data[_DM] != null) { + contents[_DMe] = de_DeleteMarkers((0, import_smithy_client.getArrayIfSingleItem)(data[_DM]), context); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_KM] != null) { + contents[_KM] = (0, import_smithy_client.expectString)(data[_KM]); + } + if (data[_MK] != null) { + contents[_MK] = (0, import_smithy_client.strictParseInt32)(data[_MK]); + } + if (data[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(data[_N]); + } + if (data[_NKM] != null) { + contents[_NKM] = (0, import_smithy_client.expectString)(data[_NKM]); + } + if (data[_NVIM] != null) { + contents[_NVIM] = (0, import_smithy_client.expectString)(data[_NVIM]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + if (data[_VIM] != null) { + contents[_VIM] = (0, import_smithy_client.expectString)(data[_VIM]); + } + if (data.Version === "") { + contents[_Ve] = []; + } else if (data[_V] != null) { + contents[_Ve] = de_ObjectVersionList((0, import_smithy_client.getArrayIfSingleItem)(data[_V]), context); + } + return contents; +}, "de_ListObjectVersionsCommand"); +var de_ListPartsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_AD]: [ + () => void 0 !== output.headers[_xaad], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_xaad])) + ], + [_ARI]: [, output.headers[_xaari]], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data[_CA] != null) { + contents[_CA] = (0, import_smithy_client.expectString)(data[_CA]); + } + if (data[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(data[_CT]); + } + if (data[_In] != null) { + contents[_In] = de_Initiator(data[_In], context); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(data[_K]); + } + if (data[_MP] != null) { + contents[_MP] = (0, import_smithy_client.strictParseInt32)(data[_MP]); + } + if (data[_NPNM] != null) { + contents[_NPNM] = (0, import_smithy_client.expectString)(data[_NPNM]); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + if (data[_PNM] != null) { + contents[_PNM] = (0, import_smithy_client.expectString)(data[_PNM]); + } + if (data.Part === "") { + contents[_Part] = []; + } else if (data[_Par] != null) { + contents[_Part] = de_Parts((0, import_smithy_client.getArrayIfSingleItem)(data[_Par]), context); + } + if (data[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(data[_SC]); + } + if (data[_UI] != null) { + contents[_UI] = (0, import_smithy_client.expectString)(data[_UI]); + } + return contents; +}, "de_ListPartsCommand"); +var de_PutBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketAccelerateConfigurationCommand"); +var de_PutBucketAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketAclCommand"); +var de_PutBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketAnalyticsConfigurationCommand"); +var de_PutBucketCorsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketCorsCommand"); +var de_PutBucketEncryptionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketEncryptionCommand"); +var de_PutBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketIntelligentTieringConfigurationCommand"); +var de_PutBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketInventoryConfigurationCommand"); +var de_PutBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_TDMOS]: [, output.headers[_xatdmos]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketLifecycleConfigurationCommand"); +var de_PutBucketLoggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketLoggingCommand"); +var de_PutBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketMetricsConfigurationCommand"); +var de_PutBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketNotificationConfigurationCommand"); +var de_PutBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketOwnershipControlsCommand"); +var de_PutBucketPolicyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketPolicyCommand"); +var de_PutBucketReplicationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketReplicationCommand"); +var de_PutBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketRequestPaymentCommand"); +var de_PutBucketTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketTaggingCommand"); +var de_PutBucketVersioningCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketVersioningCommand"); +var de_PutBucketWebsiteCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketWebsiteCommand"); +var de_PutObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_Exp]: [, output.headers[_xae]], + [_ETa]: [, output.headers[_eta]], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_CT]: [, output.headers[_xact]], + [_SSE]: [, output.headers[_xasse]], + [_VI]: [, output.headers[_xavi]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_Si]: [() => void 0 !== output.headers[_xaos], () => (0, import_smithy_client.strictParseLong)(output.headers[_xaos])], + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectCommand"); +var de_PutObjectAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectAclCommand"); +var de_PutObjectLegalHoldCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectLegalHoldCommand"); +var de_PutObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectLockConfigurationCommand"); +var de_PutObjectRetentionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectRetentionCommand"); +var de_PutObjectTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_VI]: [, output.headers[_xavi]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectTaggingCommand"); +var de_PutPublicAccessBlockCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutPublicAccessBlockCommand"); +var de_RenameObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_RenameObjectCommand"); +var de_RestoreObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]], + [_ROP]: [, output.headers[_xarop]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_RestoreObjectCommand"); +var de_SelectObjectContentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = output.body; + contents.Payload = de_SelectObjectContentEventStream(data, context); + return contents; +}, "de_SelectObjectContentCommand"); +var de_UpdateBucketMetadataInventoryTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_UpdateBucketMetadataInventoryTableConfigurationCommand"); +var de_UpdateBucketMetadataJournalTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_UpdateBucketMetadataJournalTableConfigurationCommand"); +var de_UploadPartCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_SSE]: [, output.headers[_xasse]], + [_ETa]: [, output.headers[_eta]], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_UploadPartCommand"); +var de_UploadPartCopyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_CSVI]: [, output.headers[_xacsvi]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.CopyPartResult = de_CopyPartResult(data, context); + return contents; +}, "de_UploadPartCopyCommand"); +var de_WriteGetObjectResponseCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_WriteGetObjectResponseCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core.parseXmlErrorBody)(output.body, context) + }; + const errorCode = (0, import_core.loadRestXmlErrorCode)(output, parsedOutput.body); + switch (errorCode) { + case "NoSuchUpload": + case "com.amazonaws.s3#NoSuchUpload": + throw await de_NoSuchUploadRes(parsedOutput, context); + case "ObjectNotInActiveTierError": + case "com.amazonaws.s3#ObjectNotInActiveTierError": + throw await de_ObjectNotInActiveTierErrorRes(parsedOutput, context); + case "BucketAlreadyExists": + case "com.amazonaws.s3#BucketAlreadyExists": + throw await de_BucketAlreadyExistsRes(parsedOutput, context); + case "BucketAlreadyOwnedByYou": + case "com.amazonaws.s3#BucketAlreadyOwnedByYou": + throw await de_BucketAlreadyOwnedByYouRes(parsedOutput, context); + case "NoSuchBucket": + case "com.amazonaws.s3#NoSuchBucket": + throw await de_NoSuchBucketRes(parsedOutput, context); + case "InvalidObjectState": + case "com.amazonaws.s3#InvalidObjectState": + throw await de_InvalidObjectStateRes(parsedOutput, context); + case "NoSuchKey": + case "com.amazonaws.s3#NoSuchKey": + throw await de_NoSuchKeyRes(parsedOutput, context); + case "NotFound": + case "com.amazonaws.s3#NotFound": + throw await de_NotFoundRes(parsedOutput, context); + case "EncryptionTypeMismatch": + case "com.amazonaws.s3#EncryptionTypeMismatch": + throw await de_EncryptionTypeMismatchRes(parsedOutput, context); + case "InvalidRequest": + case "com.amazonaws.s3#InvalidRequest": + throw await de_InvalidRequestRes(parsedOutput, context); + case "InvalidWriteOffset": + case "com.amazonaws.s3#InvalidWriteOffset": + throw await de_InvalidWriteOffsetRes(parsedOutput, context); + case "TooManyParts": + case "com.amazonaws.s3#TooManyParts": + throw await de_TooManyPartsRes(parsedOutput, context); + case "IdempotencyParameterMismatch": + case "com.amazonaws.s3#IdempotencyParameterMismatch": + throw await de_IdempotencyParameterMismatchRes(parsedOutput, context); + case "ObjectAlreadyInActiveTierError": + case "com.amazonaws.s3#ObjectAlreadyInActiveTierError": + throw await de_ObjectAlreadyInActiveTierErrorRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody, + errorCode + }); + } +}, "de_CommandError"); +var throwDefaultError = (0, import_smithy_client.withBaseException)(S3ServiceException); +var de_BucketAlreadyExistsRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new BucketAlreadyExists({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_BucketAlreadyExistsRes"); +var de_BucketAlreadyOwnedByYouRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new BucketAlreadyOwnedByYou({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_BucketAlreadyOwnedByYouRes"); +var de_EncryptionTypeMismatchRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new EncryptionTypeMismatch({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_EncryptionTypeMismatchRes"); +var de_IdempotencyParameterMismatchRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new IdempotencyParameterMismatch({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_IdempotencyParameterMismatchRes"); +var de_InvalidObjectStateRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + if (data[_AT] != null) { + contents[_AT] = (0, import_smithy_client.expectString)(data[_AT]); + } + if (data[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(data[_SC]); + } + const exception = new InvalidObjectState({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidObjectStateRes"); +var de_InvalidRequestRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new InvalidRequest({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidRequestRes"); +var de_InvalidWriteOffsetRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new InvalidWriteOffset({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidWriteOffsetRes"); +var de_NoSuchBucketRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NoSuchBucket({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NoSuchBucketRes"); +var de_NoSuchKeyRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NoSuchKey({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NoSuchKeyRes"); +var de_NoSuchUploadRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NoSuchUpload({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NoSuchUploadRes"); +var de_NotFoundRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NotFound({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NotFoundRes"); +var de_ObjectAlreadyInActiveTierErrorRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new ObjectAlreadyInActiveTierError({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_ObjectAlreadyInActiveTierErrorRes"); +var de_ObjectNotInActiveTierErrorRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new ObjectNotInActiveTierError({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_ObjectNotInActiveTierErrorRes"); +var de_TooManyPartsRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new TooManyParts({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_TooManyPartsRes"); +var de_SelectObjectContentEventStream = /* @__PURE__ */ __name((output, context) => { + return context.eventStreamMarshaller.deserialize(output, async (event) => { + if (event["Records"] != null) { + return { + Records: await de_RecordsEvent_event(event["Records"], context) + }; + } + if (event["Stats"] != null) { + return { + Stats: await de_StatsEvent_event(event["Stats"], context) + }; + } + if (event["Progress"] != null) { + return { + Progress: await de_ProgressEvent_event(event["Progress"], context) + }; + } + if (event["Cont"] != null) { + return { + Cont: await de_ContinuationEvent_event(event["Cont"], context) + }; + } + if (event["End"] != null) { + return { + End: await de_EndEvent_event(event["End"], context) + }; + } + return { $unknown: event }; + }); +}, "de_SelectObjectContentEventStream"); +var de_ContinuationEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + Object.assign(contents, de_ContinuationEvent(data, context)); + return contents; +}, "de_ContinuationEvent_event"); +var de_EndEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + Object.assign(contents, de_EndEvent(data, context)); + return contents; +}, "de_EndEvent_event"); +var de_ProgressEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + contents.Details = de_Progress(data, context); + return contents; +}, "de_ProgressEvent_event"); +var de_RecordsEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + contents.Payload = output.body; + return contents; +}, "de_RecordsEvent_event"); +var de_StatsEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + contents.Details = de_Stats(data, context); + return contents; +}, "de_StatsEvent_event"); +var se_AbortIncompleteMultipartUpload = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AIMU); + if (input[_DAI] != null) { + bn.c(import_xml_builder.XmlNode.of(_DAI, String(input[_DAI])).n(_DAI)); + } + return bn; +}, "se_AbortIncompleteMultipartUpload"); +var se_AccelerateConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ACc); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_BAS, input[_S]).n(_S)); + } + return bn; +}, "se_AccelerateConfiguration"); +var se_AccessControlPolicy = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ACP); + bn.lc(input, "Grants", "AccessControlList", () => se_Grants(input[_Gr], context)); + if (input[_O] != null) { + bn.c(se_Owner(input[_O], context).n(_O)); + } + return bn; +}, "se_AccessControlPolicy"); +var se_AccessControlTranslation = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ACT); + if (input[_O] != null) { + bn.c(import_xml_builder.XmlNode.of(_OOw, input[_O]).n(_O)); + } + return bn; +}, "se_AccessControlTranslation"); +var se_AllowedHeaders = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_AH, entry); + return n.n(_me); + }); +}, "se_AllowedHeaders"); +var se_AllowedMethods = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_AM, entry); + return n.n(_me); + }); +}, "se_AllowedMethods"); +var se_AllowedOrigins = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_AO, entry); + return n.n(_me); + }); +}, "se_AllowedOrigins"); +var se_AnalyticsAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_AnalyticsAndOperator"); +var se_AnalyticsConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_AI, input[_I]).n(_I)); + } + if (input[_F] != null) { + bn.c(se_AnalyticsFilter(input[_F], context).n(_F)); + } + if (input[_SCA] != null) { + bn.c(se_StorageClassAnalysis(input[_SCA], context).n(_SCA)); + } + return bn; +}, "se_AnalyticsConfiguration"); +var se_AnalyticsExportDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AED); + if (input[_SBD] != null) { + bn.c(se_AnalyticsS3BucketDestination(input[_SBD], context).n(_SBD)); + } + return bn; +}, "se_AnalyticsExportDestination"); +var se_AnalyticsFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AF); + AnalyticsFilter.visit(input, { + Prefix: /* @__PURE__ */ __name((value) => { + if (input[_P] != null) { + bn.c(import_xml_builder.XmlNode.of(_P, value).n(_P)); + } + }, "Prefix"), + Tag: /* @__PURE__ */ __name((value) => { + if (input[_Ta] != null) { + bn.c(se_Tag(value, context).n(_Ta)); + } + }, "Tag"), + And: /* @__PURE__ */ __name((value) => { + if (input[_A] != null) { + bn.c(se_AnalyticsAndOperator(value, context).n(_A)); + } + }, "And"), + _: /* @__PURE__ */ __name((name, value) => { + if (!(value instanceof import_xml_builder.XmlNode || value instanceof import_xml_builder.XmlText)) { + throw new Error("Unable to serialize unknown union members in XML."); + } + bn.c(new import_xml_builder.XmlNode(name).c(value)); + }, "_") + }); + return bn; +}, "se_AnalyticsFilter"); +var se_AnalyticsS3BucketDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ASBD); + if (input[_Fo] != null) { + bn.c(import_xml_builder.XmlNode.of(_ASEFF, input[_Fo]).n(_Fo)); + } + if (input[_BAI] != null) { + bn.c(import_xml_builder.XmlNode.of(_AIc, input[_BAI]).n(_BAI)); + } + if (input[_B] != null) { + bn.c(import_xml_builder.XmlNode.of(_BN, input[_B]).n(_B)); + } + bn.cc(input, _P); + return bn; +}, "se_AnalyticsS3BucketDestination"); +var se_BucketInfo = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_BI); + bn.cc(input, _DR); + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_BT, input[_Ty]).n(_Ty)); + } + return bn; +}, "se_BucketInfo"); +var se_BucketLifecycleConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_BLC); + bn.l(input, "Rules", "Rule", () => se_LifecycleRules(input[_Rul], context)); + return bn; +}, "se_BucketLifecycleConfiguration"); +var se_BucketLoggingStatus = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_BLS); + if (input[_LE] != null) { + bn.c(se_LoggingEnabled(input[_LE], context).n(_LE)); + } + return bn; +}, "se_BucketLoggingStatus"); +var se_CompletedMultipartUpload = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CMU); + bn.l(input, "Parts", "Part", () => se_CompletedPartList(input[_Part], context)); + return bn; +}, "se_CompletedMultipartUpload"); +var se_CompletedPart = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CPo); + bn.cc(input, _ETa); + bn.cc(input, _CCRC); + bn.cc(input, _CCRCC); + bn.cc(input, _CCRCNVME); + bn.cc(input, _CSHA); + bn.cc(input, _CSHAh); + if (input[_PN] != null) { + bn.c(import_xml_builder.XmlNode.of(_PN, String(input[_PN])).n(_PN)); + } + return bn; +}, "se_CompletedPart"); +var se_CompletedPartList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_CompletedPart(entry, context); + return n.n(_me); + }); +}, "se_CompletedPartList"); +var se_Condition = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Con); + bn.cc(input, _HECRE); + bn.cc(input, _KPE); + return bn; +}, "se_Condition"); +var se_CORSConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CORSC); + bn.l(input, "CORSRules", "CORSRule", () => se_CORSRules(input[_CORSRu], context)); + return bn; +}, "se_CORSConfiguration"); +var se_CORSRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CORSR); + bn.cc(input, _ID_); + bn.l(input, "AllowedHeaders", "AllowedHeader", () => se_AllowedHeaders(input[_AHl], context)); + bn.l(input, "AllowedMethods", "AllowedMethod", () => se_AllowedMethods(input[_AMl], context)); + bn.l(input, "AllowedOrigins", "AllowedOrigin", () => se_AllowedOrigins(input[_AOl], context)); + bn.l(input, "ExposeHeaders", "ExposeHeader", () => se_ExposeHeaders(input[_EH], context)); + if (input[_MAS] != null) { + bn.c(import_xml_builder.XmlNode.of(_MAS, String(input[_MAS])).n(_MAS)); + } + return bn; +}, "se_CORSRule"); +var se_CORSRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_CORSRule(entry, context); + return n.n(_me); + }); +}, "se_CORSRules"); +var se_CreateBucketConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CBC); + if (input[_LC] != null) { + bn.c(import_xml_builder.XmlNode.of(_BLCu, input[_LC]).n(_LC)); + } + if (input[_L] != null) { + bn.c(se_LocationInfo(input[_L], context).n(_L)); + } + if (input[_B] != null) { + bn.c(se_BucketInfo(input[_B], context).n(_B)); + } + bn.lc(input, "Tags", "Tags", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_CreateBucketConfiguration"); +var se_CSVInput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CSVIn); + bn.cc(input, _FHI); + bn.cc(input, _Com); + bn.cc(input, _QEC); + bn.cc(input, _RD); + bn.cc(input, _FD); + bn.cc(input, _QCuo); + if (input[_AQRD] != null) { + bn.c(import_xml_builder.XmlNode.of(_AQRD, String(input[_AQRD])).n(_AQRD)); + } + return bn; +}, "se_CSVInput"); +var se_CSVOutput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CSVO); + bn.cc(input, _QF); + bn.cc(input, _QEC); + bn.cc(input, _RD); + bn.cc(input, _FD); + bn.cc(input, _QCuo); + return bn; +}, "se_CSVOutput"); +var se_DefaultRetention = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_DRe); + if (input[_Mo] != null) { + bn.c(import_xml_builder.XmlNode.of(_OLRM, input[_Mo]).n(_Mo)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_Y] != null) { + bn.c(import_xml_builder.XmlNode.of(_Y, String(input[_Y])).n(_Y)); + } + return bn; +}, "se_DefaultRetention"); +var se_Delete = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Del); + bn.l(input, "Objects", "Object", () => se_ObjectIdentifierList(input[_Ob], context)); + if (input[_Q] != null) { + bn.c(import_xml_builder.XmlNode.of(_Q, String(input[_Q])).n(_Q)); + } + return bn; +}, "se_Delete"); +var se_DeleteMarkerReplication = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_DMR); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_DMRS, input[_S]).n(_S)); + } + return bn; +}, "se_DeleteMarkerReplication"); +var se_Destination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Des); + if (input[_B] != null) { + bn.c(import_xml_builder.XmlNode.of(_BN, input[_B]).n(_B)); + } + if (input[_Ac] != null) { + bn.c(import_xml_builder.XmlNode.of(_AIc, input[_Ac]).n(_Ac)); + } + bn.cc(input, _SC); + if (input[_ACT] != null) { + bn.c(se_AccessControlTranslation(input[_ACT], context).n(_ACT)); + } + if (input[_ECn] != null) { + bn.c(se_EncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + if (input[_RTe] != null) { + bn.c(se_ReplicationTime(input[_RTe], context).n(_RTe)); + } + if (input[_Me] != null) { + bn.c(se_Metrics(input[_Me], context).n(_Me)); + } + return bn; +}, "se_Destination"); +var se_Encryption = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_En); + if (input[_ETn] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSE, input[_ETn]).n(_ETn)); + } + if (input[_KMSKI] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSEKMSKI, input[_KMSKI]).n(_KMSKI)); + } + bn.cc(input, _KMSC); + return bn; +}, "se_Encryption"); +var se_EncryptionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ECn); + bn.cc(input, _RKKID); + return bn; +}, "se_EncryptionConfiguration"); +var se_ErrorDocument = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ED); + if (input[_K] != null) { + bn.c(import_xml_builder.XmlNode.of(_OK, input[_K]).n(_K)); + } + return bn; +}, "se_ErrorDocument"); +var se_EventBridgeConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_EBC); + return bn; +}, "se_EventBridgeConfiguration"); +var se_EventList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_Ev, entry); + return n.n(_me); + }); +}, "se_EventList"); +var se_ExistingObjectReplication = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_EOR); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_EORS, input[_S]).n(_S)); + } + return bn; +}, "se_ExistingObjectReplication"); +var se_ExposeHeaders = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_EHx, entry); + return n.n(_me); + }); +}, "se_ExposeHeaders"); +var se_FilterRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_FR); + if (input[_N] != null) { + bn.c(import_xml_builder.XmlNode.of(_FRN, input[_N]).n(_N)); + } + if (input[_Va] != null) { + bn.c(import_xml_builder.XmlNode.of(_FRV, input[_Va]).n(_Va)); + } + return bn; +}, "se_FilterRule"); +var se_FilterRuleList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_FilterRule(entry, context); + return n.n(_me); + }); +}, "se_FilterRuleList"); +var se_GlacierJobParameters = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_GJP); + bn.cc(input, _Ti); + return bn; +}, "se_GlacierJobParameters"); +var se_Grant = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_G); + if (input[_Gra] != null) { + const n = se_Grantee(input[_Gra], context).n(_Gra); + n.a("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + bn.c(n); + } + bn.cc(input, _Pe); + return bn; +}, "se_Grant"); +var se_Grantee = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Gra); + bn.cc(input, _DN); + bn.cc(input, _EA); + bn.cc(input, _ID_); + bn.cc(input, _URI); + bn.a("xsi:type", input[_Ty]); + return bn; +}, "se_Grantee"); +var se_Grants = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Grant(entry, context); + return n.n(_G); + }); +}, "se_Grants"); +var se_IndexDocument = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ID); + bn.cc(input, _Su); + return bn; +}, "se_IndexDocument"); +var se_InputSerialization = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IS); + if (input[_CSV] != null) { + bn.c(se_CSVInput(input[_CSV], context).n(_CSV)); + } + bn.cc(input, _CTom); + if (input[_JSON] != null) { + bn.c(se_JSONInput(input[_JSON], context).n(_JSON)); + } + if (input[_Parq] != null) { + bn.c(se_ParquetInput(input[_Parq], context).n(_Parq)); + } + return bn; +}, "se_InputSerialization"); +var se_IntelligentTieringAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_IntelligentTieringAndOperator"); +var se_IntelligentTieringConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITI, input[_I]).n(_I)); + } + if (input[_F] != null) { + bn.c(se_IntelligentTieringFilter(input[_F], context).n(_F)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITS, input[_S]).n(_S)); + } + bn.l(input, "Tierings", "Tiering", () => se_TieringList(input[_Tie], context)); + return bn; +}, "se_IntelligentTieringConfiguration"); +var se_IntelligentTieringFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITF); + bn.cc(input, _P); + if (input[_Ta] != null) { + bn.c(se_Tag(input[_Ta], context).n(_Ta)); + } + if (input[_A] != null) { + bn.c(se_IntelligentTieringAndOperator(input[_A], context).n(_A)); + } + return bn; +}, "se_IntelligentTieringFilter"); +var se_InventoryConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IC); + if (input[_Des] != null) { + bn.c(se_InventoryDestination(input[_Des], context).n(_Des)); + } + if (input[_IE] != null) { + bn.c(import_xml_builder.XmlNode.of(_IE, String(input[_IE])).n(_IE)); + } + if (input[_F] != null) { + bn.c(se_InventoryFilter(input[_F], context).n(_F)); + } + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_II, input[_I]).n(_I)); + } + if (input[_IOV] != null) { + bn.c(import_xml_builder.XmlNode.of(_IIOV, input[_IOV]).n(_IOV)); + } + bn.lc(input, "OptionalFields", "OptionalFields", () => se_InventoryOptionalFields(input[_OF], context)); + if (input[_Sc] != null) { + bn.c(se_InventorySchedule(input[_Sc], context).n(_Sc)); + } + return bn; +}, "se_InventoryConfiguration"); +var se_InventoryDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IDn); + if (input[_SBD] != null) { + bn.c(se_InventoryS3BucketDestination(input[_SBD], context).n(_SBD)); + } + return bn; +}, "se_InventoryDestination"); +var se_InventoryEncryption = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IEn); + if (input[_SSES] != null) { + bn.c(se_SSES3(input[_SSES], context).n(_SS)); + } + if (input[_SSEKMS] != null) { + bn.c(se_SSEKMS(input[_SSEKMS], context).n(_SK)); + } + return bn; +}, "se_InventoryEncryption"); +var se_InventoryFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IF); + bn.cc(input, _P); + return bn; +}, "se_InventoryFilter"); +var se_InventoryOptionalFields = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_IOF, entry); + return n.n(_Fi); + }); +}, "se_InventoryOptionalFields"); +var se_InventoryS3BucketDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ISBD); + bn.cc(input, _AIc); + if (input[_B] != null) { + bn.c(import_xml_builder.XmlNode.of(_BN, input[_B]).n(_B)); + } + if (input[_Fo] != null) { + bn.c(import_xml_builder.XmlNode.of(_IFn, input[_Fo]).n(_Fo)); + } + bn.cc(input, _P); + if (input[_En] != null) { + bn.c(se_InventoryEncryption(input[_En], context).n(_En)); + } + return bn; +}, "se_InventoryS3BucketDestination"); +var se_InventorySchedule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ISn); + if (input[_Fr] != null) { + bn.c(import_xml_builder.XmlNode.of(_IFnv, input[_Fr]).n(_Fr)); + } + return bn; +}, "se_InventorySchedule"); +var se_InventoryTableConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITCn); + if (input[_CSo] != null) { + bn.c(import_xml_builder.XmlNode.of(_ICS, input[_CSo]).n(_CSo)); + } + if (input[_ECn] != null) { + bn.c(se_MetadataTableEncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + return bn; +}, "se_InventoryTableConfiguration"); +var se_InventoryTableConfigurationUpdates = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITCU); + if (input[_CSo] != null) { + bn.c(import_xml_builder.XmlNode.of(_ICS, input[_CSo]).n(_CSo)); + } + if (input[_ECn] != null) { + bn.c(se_MetadataTableEncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + return bn; +}, "se_InventoryTableConfigurationUpdates"); +var se_JournalTableConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JTC); + if (input[_REe] != null) { + bn.c(se_RecordExpiration(input[_REe], context).n(_REe)); + } + if (input[_ECn] != null) { + bn.c(se_MetadataTableEncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + return bn; +}, "se_JournalTableConfiguration"); +var se_JournalTableConfigurationUpdates = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JTCU); + if (input[_REe] != null) { + bn.c(se_RecordExpiration(input[_REe], context).n(_REe)); + } + return bn; +}, "se_JournalTableConfigurationUpdates"); +var se_JSONInput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JSONI); + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_JSONT, input[_Ty]).n(_Ty)); + } + return bn; +}, "se_JSONInput"); +var se_JSONOutput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JSONO); + bn.cc(input, _RD); + return bn; +}, "se_JSONOutput"); +var se_LambdaFunctionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LFCa); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_NI, input[_I]).n(_I)); + } + if (input[_LFA] != null) { + bn.c(import_xml_builder.XmlNode.of(_LFA, input[_LFA]).n(_CF)); + } + bn.l(input, "Events", "Event", () => se_EventList(input[_Eve], context)); + if (input[_F] != null) { + bn.c(se_NotificationConfigurationFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_LambdaFunctionConfiguration"); +var se_LambdaFunctionConfigurationList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_LambdaFunctionConfiguration(entry, context); + return n.n(_me); + }); +}, "se_LambdaFunctionConfigurationList"); +var se_LifecycleExpiration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LEi); + if (input[_Dat] != null) { + bn.c(import_xml_builder.XmlNode.of(_Dat, (0, import_smithy_client.serializeDateTime)(input[_Dat]).toString()).n(_Dat)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_EODM] != null) { + bn.c(import_xml_builder.XmlNode.of(_EODM, String(input[_EODM])).n(_EODM)); + } + return bn; +}, "se_LifecycleExpiration"); +var se_LifecycleRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LR); + if (input[_Exp] != null) { + bn.c(se_LifecycleExpiration(input[_Exp], context).n(_Exp)); + } + bn.cc(input, _ID_); + bn.cc(input, _P); + if (input[_F] != null) { + bn.c(se_LifecycleRuleFilter(input[_F], context).n(_F)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_ESx, input[_S]).n(_S)); + } + bn.l(input, "Transitions", "Transition", () => se_TransitionList(input[_Tr], context)); + bn.l( + input, + "NoncurrentVersionTransitions", + "NoncurrentVersionTransition", + () => se_NoncurrentVersionTransitionList(input[_NVT], context) + ); + if (input[_NVE] != null) { + bn.c(se_NoncurrentVersionExpiration(input[_NVE], context).n(_NVE)); + } + if (input[_AIMU] != null) { + bn.c(se_AbortIncompleteMultipartUpload(input[_AIMU], context).n(_AIMU)); + } + return bn; +}, "se_LifecycleRule"); +var se_LifecycleRuleAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LRAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + if (input[_OSGT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSGTB, String(input[_OSGT])).n(_OSGT)); + } + if (input[_OSLT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSLTB, String(input[_OSLT])).n(_OSLT)); + } + return bn; +}, "se_LifecycleRuleAndOperator"); +var se_LifecycleRuleFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LRF); + bn.cc(input, _P); + if (input[_Ta] != null) { + bn.c(se_Tag(input[_Ta], context).n(_Ta)); + } + if (input[_OSGT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSGTB, String(input[_OSGT])).n(_OSGT)); + } + if (input[_OSLT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSLTB, String(input[_OSLT])).n(_OSLT)); + } + if (input[_A] != null) { + bn.c(se_LifecycleRuleAndOperator(input[_A], context).n(_A)); + } + return bn; +}, "se_LifecycleRuleFilter"); +var se_LifecycleRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_LifecycleRule(entry, context); + return n.n(_me); + }); +}, "se_LifecycleRules"); +var se_LocationInfo = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LI); + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_LT, input[_Ty]).n(_Ty)); + } + if (input[_N] != null) { + bn.c(import_xml_builder.XmlNode.of(_LNAS, input[_N]).n(_N)); + } + return bn; +}, "se_LocationInfo"); +var se_LoggingEnabled = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LE); + bn.cc(input, _TB); + bn.lc(input, "TargetGrants", "TargetGrants", () => se_TargetGrants(input[_TG], context)); + bn.cc(input, _TP); + if (input[_TOKF] != null) { + bn.c(se_TargetObjectKeyFormat(input[_TOKF], context).n(_TOKF)); + } + return bn; +}, "se_LoggingEnabled"); +var se_MetadataConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MCe); + if (input[_JTC] != null) { + bn.c(se_JournalTableConfiguration(input[_JTC], context).n(_JTC)); + } + if (input[_ITCn] != null) { + bn.c(se_InventoryTableConfiguration(input[_ITCn], context).n(_ITCn)); + } + return bn; +}, "se_MetadataConfiguration"); +var se_MetadataEntry = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ME); + if (input[_N] != null) { + bn.c(import_xml_builder.XmlNode.of(_MKe, input[_N]).n(_N)); + } + if (input[_Va] != null) { + bn.c(import_xml_builder.XmlNode.of(_MV, input[_Va]).n(_Va)); + } + return bn; +}, "se_MetadataEntry"); +var se_MetadataTableConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MTC); + if (input[_STD] != null) { + bn.c(se_S3TablesDestination(input[_STD], context).n(_STD)); + } + return bn; +}, "se_MetadataTableConfiguration"); +var se_MetadataTableEncryptionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MTEC); + if (input[_SAs] != null) { + bn.c(import_xml_builder.XmlNode.of(_TSA, input[_SAs]).n(_SAs)); + } + bn.cc(input, _KKA); + return bn; +}, "se_MetadataTableEncryptionConfiguration"); +var se_Metrics = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Me); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_MS, input[_S]).n(_S)); + } + if (input[_ETv] != null) { + bn.c(se_ReplicationTimeValue(input[_ETv], context).n(_ETv)); + } + return bn; +}, "se_Metrics"); +var se_MetricsAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + bn.cc(input, _APAc); + return bn; +}, "se_MetricsAndOperator"); +var se_MetricsConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_MI, input[_I]).n(_I)); + } + if (input[_F] != null) { + bn.c(se_MetricsFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_MetricsConfiguration"); +var se_MetricsFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MF); + MetricsFilter.visit(input, { + Prefix: /* @__PURE__ */ __name((value) => { + if (input[_P] != null) { + bn.c(import_xml_builder.XmlNode.of(_P, value).n(_P)); + } + }, "Prefix"), + Tag: /* @__PURE__ */ __name((value) => { + if (input[_Ta] != null) { + bn.c(se_Tag(value, context).n(_Ta)); + } + }, "Tag"), + AccessPointArn: /* @__PURE__ */ __name((value) => { + if (input[_APAc] != null) { + bn.c(import_xml_builder.XmlNode.of(_APAc, value).n(_APAc)); + } + }, "AccessPointArn"), + And: /* @__PURE__ */ __name((value) => { + if (input[_A] != null) { + bn.c(se_MetricsAndOperator(value, context).n(_A)); + } + }, "And"), + _: /* @__PURE__ */ __name((name, value) => { + if (!(value instanceof import_xml_builder.XmlNode || value instanceof import_xml_builder.XmlText)) { + throw new Error("Unable to serialize unknown union members in XML."); + } + bn.c(new import_xml_builder.XmlNode(name).c(value)); + }, "_") + }); + return bn; +}, "se_MetricsFilter"); +var se_NoncurrentVersionExpiration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NVE); + if (input[_ND] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_ND])).n(_ND)); + } + if (input[_NNV] != null) { + bn.c(import_xml_builder.XmlNode.of(_VC, String(input[_NNV])).n(_NNV)); + } + return bn; +}, "se_NoncurrentVersionExpiration"); +var se_NoncurrentVersionTransition = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NVTo); + if (input[_ND] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_ND])).n(_ND)); + } + if (input[_SC] != null) { + bn.c(import_xml_builder.XmlNode.of(_TSC, input[_SC]).n(_SC)); + } + if (input[_NNV] != null) { + bn.c(import_xml_builder.XmlNode.of(_VC, String(input[_NNV])).n(_NNV)); + } + return bn; +}, "se_NoncurrentVersionTransition"); +var se_NoncurrentVersionTransitionList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_NoncurrentVersionTransition(entry, context); + return n.n(_me); + }); +}, "se_NoncurrentVersionTransitionList"); +var se_NotificationConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NC); + bn.l(input, "TopicConfigurations", "TopicConfiguration", () => se_TopicConfigurationList(input[_TCop], context)); + bn.l(input, "QueueConfigurations", "QueueConfiguration", () => se_QueueConfigurationList(input[_QCu], context)); + bn.l( + input, + "LambdaFunctionConfigurations", + "CloudFunctionConfiguration", + () => se_LambdaFunctionConfigurationList(input[_LFC], context) + ); + if (input[_EBC] != null) { + bn.c(se_EventBridgeConfiguration(input[_EBC], context).n(_EBC)); + } + return bn; +}, "se_NotificationConfiguration"); +var se_NotificationConfigurationFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NCF); + if (input[_K] != null) { + bn.c(se_S3KeyFilter(input[_K], context).n(_SKe)); + } + return bn; +}, "se_NotificationConfigurationFilter"); +var se_ObjectIdentifier = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OI); + if (input[_K] != null) { + bn.c(import_xml_builder.XmlNode.of(_OK, input[_K]).n(_K)); + } + if (input[_VI] != null) { + bn.c(import_xml_builder.XmlNode.of(_OVI, input[_VI]).n(_VI)); + } + bn.cc(input, _ETa); + if (input[_LMT] != null) { + bn.c(import_xml_builder.XmlNode.of(_LMT, (0, import_smithy_client.dateToUtcString)(input[_LMT]).toString()).n(_LMT)); + } + if (input[_Si] != null) { + bn.c(import_xml_builder.XmlNode.of(_Si, String(input[_Si])).n(_Si)); + } + return bn; +}, "se_ObjectIdentifier"); +var se_ObjectIdentifierList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_ObjectIdentifier(entry, context); + return n.n(_me); + }); +}, "se_ObjectIdentifierList"); +var se_ObjectLockConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLC); + bn.cc(input, _OLE); + if (input[_Ru] != null) { + bn.c(se_ObjectLockRule(input[_Ru], context).n(_Ru)); + } + return bn; +}, "se_ObjectLockConfiguration"); +var se_ObjectLockLegalHold = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLLH); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_OLLHS, input[_S]).n(_S)); + } + return bn; +}, "se_ObjectLockLegalHold"); +var se_ObjectLockRetention = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLR); + if (input[_Mo] != null) { + bn.c(import_xml_builder.XmlNode.of(_OLRM, input[_Mo]).n(_Mo)); + } + if (input[_RUD] != null) { + bn.c(import_xml_builder.XmlNode.of(_Dat, (0, import_smithy_client.serializeDateTime)(input[_RUD]).toString()).n(_RUD)); + } + return bn; +}, "se_ObjectLockRetention"); +var se_ObjectLockRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLRb); + if (input[_DRe] != null) { + bn.c(se_DefaultRetention(input[_DRe], context).n(_DRe)); + } + return bn; +}, "se_ObjectLockRule"); +var se_OutputLocation = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OL); + if (input[_S_] != null) { + bn.c(se_S3Location(input[_S_], context).n(_S_)); + } + return bn; +}, "se_OutputLocation"); +var se_OutputSerialization = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OS); + if (input[_CSV] != null) { + bn.c(se_CSVOutput(input[_CSV], context).n(_CSV)); + } + if (input[_JSON] != null) { + bn.c(se_JSONOutput(input[_JSON], context).n(_JSON)); + } + return bn; +}, "se_OutputSerialization"); +var se_Owner = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_O); + bn.cc(input, _DN); + bn.cc(input, _ID_); + return bn; +}, "se_Owner"); +var se_OwnershipControls = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OC); + bn.l(input, "Rules", "Rule", () => se_OwnershipControlsRules(input[_Rul], context)); + return bn; +}, "se_OwnershipControls"); +var se_OwnershipControlsRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OCR); + bn.cc(input, _OO); + return bn; +}, "se_OwnershipControlsRule"); +var se_OwnershipControlsRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_OwnershipControlsRule(entry, context); + return n.n(_me); + }); +}, "se_OwnershipControlsRules"); +var se_ParquetInput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_PI); + return bn; +}, "se_ParquetInput"); +var se_PartitionedPrefix = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_PP); + bn.cc(input, _PDS); + return bn; +}, "se_PartitionedPrefix"); +var se_PublicAccessBlockConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_PABC); + if (input[_BPA] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_BPA])).n(_BPA)); + } + if (input[_IPA] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_IPA])).n(_IPA)); + } + if (input[_BPP] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_BPP])).n(_BPP)); + } + if (input[_RPB] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_RPB])).n(_RPB)); + } + return bn; +}, "se_PublicAccessBlockConfiguration"); +var se_QueueConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_QC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_NI, input[_I]).n(_I)); + } + if (input[_QA] != null) { + bn.c(import_xml_builder.XmlNode.of(_QA, input[_QA]).n(_Qu)); + } + bn.l(input, "Events", "Event", () => se_EventList(input[_Eve], context)); + if (input[_F] != null) { + bn.c(se_NotificationConfigurationFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_QueueConfiguration"); +var se_QueueConfigurationList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_QueueConfiguration(entry, context); + return n.n(_me); + }); +}, "se_QueueConfigurationList"); +var se_RecordExpiration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_REe); + if (input[_Exp] != null) { + bn.c(import_xml_builder.XmlNode.of(_ESxp, input[_Exp]).n(_Exp)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_RED, String(input[_Da])).n(_Da)); + } + return bn; +}, "se_RecordExpiration"); +var se_Redirect = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Red); + bn.cc(input, _HN); + bn.cc(input, _HRC); + bn.cc(input, _Pr); + bn.cc(input, _RKPW); + bn.cc(input, _RKW); + return bn; +}, "se_Redirect"); +var se_RedirectAllRequestsTo = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RART); + bn.cc(input, _HN); + bn.cc(input, _Pr); + return bn; +}, "se_RedirectAllRequestsTo"); +var se_ReplicaModifications = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RM); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_RMS, input[_S]).n(_S)); + } + return bn; +}, "se_ReplicaModifications"); +var se_ReplicationConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RCe); + bn.cc(input, _Ro); + bn.l(input, "Rules", "Rule", () => se_ReplicationRules(input[_Rul], context)); + return bn; +}, "se_ReplicationConfiguration"); +var se_ReplicationRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRe); + bn.cc(input, _ID_); + if (input[_Pri] != null) { + bn.c(import_xml_builder.XmlNode.of(_Pri, String(input[_Pri])).n(_Pri)); + } + bn.cc(input, _P); + if (input[_F] != null) { + bn.c(se_ReplicationRuleFilter(input[_F], context).n(_F)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_RRS, input[_S]).n(_S)); + } + if (input[_SSC] != null) { + bn.c(se_SourceSelectionCriteria(input[_SSC], context).n(_SSC)); + } + if (input[_EOR] != null) { + bn.c(se_ExistingObjectReplication(input[_EOR], context).n(_EOR)); + } + if (input[_Des] != null) { + bn.c(se_Destination(input[_Des], context).n(_Des)); + } + if (input[_DMR] != null) { + bn.c(se_DeleteMarkerReplication(input[_DMR], context).n(_DMR)); + } + return bn; +}, "se_ReplicationRule"); +var se_ReplicationRuleAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_ReplicationRuleAndOperator"); +var se_ReplicationRuleFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRF); + bn.cc(input, _P); + if (input[_Ta] != null) { + bn.c(se_Tag(input[_Ta], context).n(_Ta)); + } + if (input[_A] != null) { + bn.c(se_ReplicationRuleAndOperator(input[_A], context).n(_A)); + } + return bn; +}, "se_ReplicationRuleFilter"); +var se_ReplicationRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_ReplicationRule(entry, context); + return n.n(_me); + }); +}, "se_ReplicationRules"); +var se_ReplicationTime = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RTe); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_RTS, input[_S]).n(_S)); + } + if (input[_Tim] != null) { + bn.c(se_ReplicationTimeValue(input[_Tim], context).n(_Tim)); + } + return bn; +}, "se_ReplicationTime"); +var se_ReplicationTimeValue = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RTV); + if (input[_Mi] != null) { + bn.c(import_xml_builder.XmlNode.of(_Mi, String(input[_Mi])).n(_Mi)); + } + return bn; +}, "se_ReplicationTimeValue"); +var se_RequestPaymentConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RPC); + bn.cc(input, _Pa); + return bn; +}, "se_RequestPaymentConfiguration"); +var se_RequestProgress = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RPe); + if (input[_Ena] != null) { + bn.c(import_xml_builder.XmlNode.of(_ERP, String(input[_Ena])).n(_Ena)); + } + return bn; +}, "se_RequestProgress"); +var se_RestoreRequest = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRes); + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_GJP] != null) { + bn.c(se_GlacierJobParameters(input[_GJP], context).n(_GJP)); + } + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_RRT, input[_Ty]).n(_Ty)); + } + bn.cc(input, _Ti); + bn.cc(input, _Desc); + if (input[_SP] != null) { + bn.c(se_SelectParameters(input[_SP], context).n(_SP)); + } + if (input[_OL] != null) { + bn.c(se_OutputLocation(input[_OL], context).n(_OL)); + } + return bn; +}, "se_RestoreRequest"); +var se_RoutingRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRou); + if (input[_Con] != null) { + bn.c(se_Condition(input[_Con], context).n(_Con)); + } + if (input[_Red] != null) { + bn.c(se_Redirect(input[_Red], context).n(_Red)); + } + return bn; +}, "se_RoutingRule"); +var se_RoutingRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_RoutingRule(entry, context); + return n.n(_RRou); + }); +}, "se_RoutingRules"); +var se_S3KeyFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SKF); + bn.l(input, "FilterRules", "FilterRule", () => se_FilterRuleList(input[_FRi], context)); + return bn; +}, "se_S3KeyFilter"); +var se_S3Location = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SL); + bn.cc(input, _BN); + if (input[_P] != null) { + bn.c(import_xml_builder.XmlNode.of(_LP, input[_P]).n(_P)); + } + if (input[_En] != null) { + bn.c(se_Encryption(input[_En], context).n(_En)); + } + if (input[_CACL] != null) { + bn.c(import_xml_builder.XmlNode.of(_OCACL, input[_CACL]).n(_CACL)); + } + bn.lc(input, "AccessControlList", "AccessControlList", () => se_Grants(input[_ACLc], context)); + if (input[_T] != null) { + bn.c(se_Tagging(input[_T], context).n(_T)); + } + bn.lc(input, "UserMetadata", "UserMetadata", () => se_UserMetadata(input[_UM], context)); + bn.cc(input, _SC); + return bn; +}, "se_S3Location"); +var se_S3TablesDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_STD); + if (input[_TBA] != null) { + bn.c(import_xml_builder.XmlNode.of(_STBA, input[_TBA]).n(_TBA)); + } + if (input[_TN] != null) { + bn.c(import_xml_builder.XmlNode.of(_STN, input[_TN]).n(_TN)); + } + return bn; +}, "se_S3TablesDestination"); +var se_ScanRange = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SR); + if (input[_St] != null) { + bn.c(import_xml_builder.XmlNode.of(_St, String(input[_St])).n(_St)); + } + if (input[_End] != null) { + bn.c(import_xml_builder.XmlNode.of(_End, String(input[_End])).n(_End)); + } + return bn; +}, "se_ScanRange"); +var se_SelectParameters = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SP); + if (input[_IS] != null) { + bn.c(se_InputSerialization(input[_IS], context).n(_IS)); + } + bn.cc(input, _ETx); + bn.cc(input, _Ex); + if (input[_OS] != null) { + bn.c(se_OutputSerialization(input[_OS], context).n(_OS)); + } + return bn; +}, "se_SelectParameters"); +var se_ServerSideEncryptionByDefault = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSEBD); + if (input[_SSEA] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSE, input[_SSEA]).n(_SSEA)); + } + if (input[_KMSMKID] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSEKMSKI, input[_KMSMKID]).n(_KMSMKID)); + } + return bn; +}, "se_ServerSideEncryptionByDefault"); +var se_ServerSideEncryptionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSEC); + bn.l(input, "Rules", "Rule", () => se_ServerSideEncryptionRules(input[_Rul], context)); + return bn; +}, "se_ServerSideEncryptionConfiguration"); +var se_ServerSideEncryptionRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSER); + if (input[_ASSEBD] != null) { + bn.c(se_ServerSideEncryptionByDefault(input[_ASSEBD], context).n(_ASSEBD)); + } + if (input[_BKE] != null) { + bn.c(import_xml_builder.XmlNode.of(_BKE, String(input[_BKE])).n(_BKE)); + } + return bn; +}, "se_ServerSideEncryptionRule"); +var se_ServerSideEncryptionRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_ServerSideEncryptionRule(entry, context); + return n.n(_me); + }); +}, "se_ServerSideEncryptionRules"); +var se_SimplePrefix = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SPi); + return bn; +}, "se_SimplePrefix"); +var se_SourceSelectionCriteria = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSC); + if (input[_SKEO] != null) { + bn.c(se_SseKmsEncryptedObjects(input[_SKEO], context).n(_SKEO)); + } + if (input[_RM] != null) { + bn.c(se_ReplicaModifications(input[_RM], context).n(_RM)); + } + return bn; +}, "se_SourceSelectionCriteria"); +var se_SSEKMS = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SK); + if (input[_KI] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSEKMSKI, input[_KI]).n(_KI)); + } + return bn; +}, "se_SSEKMS"); +var se_SseKmsEncryptedObjects = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SKEO); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_SKEOS, input[_S]).n(_S)); + } + return bn; +}, "se_SseKmsEncryptedObjects"); +var se_SSES3 = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SS); + return bn; +}, "se_SSES3"); +var se_StorageClassAnalysis = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SCA); + if (input[_DE] != null) { + bn.c(se_StorageClassAnalysisDataExport(input[_DE], context).n(_DE)); + } + return bn; +}, "se_StorageClassAnalysis"); +var se_StorageClassAnalysisDataExport = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SCADE); + if (input[_OSV] != null) { + bn.c(import_xml_builder.XmlNode.of(_SCASV, input[_OSV]).n(_OSV)); + } + if (input[_Des] != null) { + bn.c(se_AnalyticsExportDestination(input[_Des], context).n(_Des)); + } + return bn; +}, "se_StorageClassAnalysisDataExport"); +var se_Tag = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Ta); + if (input[_K] != null) { + bn.c(import_xml_builder.XmlNode.of(_OK, input[_K]).n(_K)); + } + bn.cc(input, _Va); + return bn; +}, "se_Tag"); +var se_Tagging = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_T); + bn.lc(input, "TagSet", "TagSet", () => se_TagSet(input[_TS], context)); + return bn; +}, "se_Tagging"); +var se_TagSet = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Tag(entry, context); + return n.n(_Ta); + }); +}, "se_TagSet"); +var se_TargetGrant = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_TGa); + if (input[_Gra] != null) { + const n = se_Grantee(input[_Gra], context).n(_Gra); + n.a("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + bn.c(n); + } + if (input[_Pe] != null) { + bn.c(import_xml_builder.XmlNode.of(_BLP, input[_Pe]).n(_Pe)); + } + return bn; +}, "se_TargetGrant"); +var se_TargetGrants = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_TargetGrant(entry, context); + return n.n(_G); + }); +}, "se_TargetGrants"); +var se_TargetObjectKeyFormat = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_TOKF); + if (input[_SPi] != null) { + bn.c(se_SimplePrefix(input[_SPi], context).n(_SPi)); + } + if (input[_PP] != null) { + bn.c(se_PartitionedPrefix(input[_PP], context).n(_PP)); + } + return bn; +}, "se_TargetObjectKeyFormat"); +var se_Tiering = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Tier); + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITD, String(input[_Da])).n(_Da)); + } + if (input[_AT] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITAT, input[_AT]).n(_AT)); + } + return bn; +}, "se_Tiering"); +var se_TieringList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Tiering(entry, context); + return n.n(_me); + }); +}, "se_TieringList"); +var se_TopicConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_TCo); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_NI, input[_I]).n(_I)); + } + if (input[_TA] != null) { + bn.c(import_xml_builder.XmlNode.of(_TA, input[_TA]).n(_Top)); + } + bn.l(input, "Events", "Event", () => se_EventList(input[_Eve], context)); + if (input[_F] != null) { + bn.c(se_NotificationConfigurationFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_TopicConfiguration"); +var se_TopicConfigurationList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_TopicConfiguration(entry, context); + return n.n(_me); + }); +}, "se_TopicConfigurationList"); +var se_Transition = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Tra); + if (input[_Dat] != null) { + bn.c(import_xml_builder.XmlNode.of(_Dat, (0, import_smithy_client.serializeDateTime)(input[_Dat]).toString()).n(_Dat)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_SC] != null) { + bn.c(import_xml_builder.XmlNode.of(_TSC, input[_SC]).n(_SC)); + } + return bn; +}, "se_Transition"); +var se_TransitionList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Transition(entry, context); + return n.n(_me); + }); +}, "se_TransitionList"); +var se_UserMetadata = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_MetadataEntry(entry, context); + return n.n(_ME); + }); +}, "se_UserMetadata"); +var se_VersioningConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_VCe); + if (input[_MFAD] != null) { + bn.c(import_xml_builder.XmlNode.of(_MFAD, input[_MFAD]).n(_MDf)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_BVS, input[_S]).n(_S)); + } + return bn; +}, "se_VersioningConfiguration"); +var se_WebsiteConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_WC); + if (input[_ED] != null) { + bn.c(se_ErrorDocument(input[_ED], context).n(_ED)); + } + if (input[_ID] != null) { + bn.c(se_IndexDocument(input[_ID], context).n(_ID)); + } + if (input[_RART] != null) { + bn.c(se_RedirectAllRequestsTo(input[_RART], context).n(_RART)); + } + bn.lc(input, "RoutingRules", "RoutingRules", () => se_RoutingRules(input[_RRo], context)); + return bn; +}, "se_WebsiteConfiguration"); +var de_AbortIncompleteMultipartUpload = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DAI] != null) { + contents[_DAI] = (0, import_smithy_client.strictParseInt32)(output[_DAI]); + } + return contents; +}, "de_AbortIncompleteMultipartUpload"); +var de_AccessControlTranslation = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_O] != null) { + contents[_O] = (0, import_smithy_client.expectString)(output[_O]); + } + return contents; +}, "de_AccessControlTranslation"); +var de_AllowedHeaders = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_AllowedHeaders"); +var de_AllowedMethods = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_AllowedMethods"); +var de_AllowedOrigins = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_AllowedOrigins"); +var de_AnalyticsAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + return contents; +}, "de_AnalyticsAndOperator"); +var de_AnalyticsConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output.Filter === "") { + } else if (output[_F] != null) { + contents[_F] = de_AnalyticsFilter((0, import_smithy_client.expectUnion)(output[_F]), context); + } + if (output[_SCA] != null) { + contents[_SCA] = de_StorageClassAnalysis(output[_SCA], context); + } + return contents; +}, "de_AnalyticsConfiguration"); +var de_AnalyticsConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_AnalyticsConfiguration(entry, context); + }); +}, "de_AnalyticsConfigurationList"); +var de_AnalyticsExportDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SBD] != null) { + contents[_SBD] = de_AnalyticsS3BucketDestination(output[_SBD], context); + } + return contents; +}, "de_AnalyticsExportDestination"); +var de_AnalyticsFilter = /* @__PURE__ */ __name((output, context) => { + if (output[_P] != null) { + return { + Prefix: (0, import_smithy_client.expectString)(output[_P]) + }; + } + if (output[_Ta] != null) { + return { + Tag: de_Tag(output[_Ta], context) + }; + } + if (output[_A] != null) { + return { + And: de_AnalyticsAndOperator(output[_A], context) + }; + } + return { $unknown: Object.entries(output)[0] }; +}, "de_AnalyticsFilter"); +var de_AnalyticsS3BucketDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Fo] != null) { + contents[_Fo] = (0, import_smithy_client.expectString)(output[_Fo]); + } + if (output[_BAI] != null) { + contents[_BAI] = (0, import_smithy_client.expectString)(output[_BAI]); + } + if (output[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(output[_B]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + return contents; +}, "de_AnalyticsS3BucketDestination"); +var de_Bucket = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(output[_N]); + } + if (output[_CDr] != null) { + contents[_CDr] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_CDr])); + } + if (output[_BR] != null) { + contents[_BR] = (0, import_smithy_client.expectString)(output[_BR]); + } + if (output[_BA] != null) { + contents[_BA] = (0, import_smithy_client.expectString)(output[_BA]); + } + return contents; +}, "de_Bucket"); +var de_Buckets = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Bucket(entry, context); + }); +}, "de_Buckets"); +var de_Checksum = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + return contents; +}, "de_Checksum"); +var de_ChecksumAlgorithmList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_ChecksumAlgorithmList"); +var de_CommonPrefix = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + return contents; +}, "de_CommonPrefix"); +var de_CommonPrefixList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_CommonPrefix(entry, context); + }); +}, "de_CommonPrefixList"); +var de_Condition = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_HECRE] != null) { + contents[_HECRE] = (0, import_smithy_client.expectString)(output[_HECRE]); + } + if (output[_KPE] != null) { + contents[_KPE] = (0, import_smithy_client.expectString)(output[_KPE]); + } + return contents; +}, "de_Condition"); +var de_ContinuationEvent = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_ContinuationEvent"); +var de_CopyObjectResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_CopyObjectResult"); +var de_CopyPartResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_CopyPartResult"); +var de_CORSRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output.AllowedHeader === "") { + contents[_AHl] = []; + } else if (output[_AH] != null) { + contents[_AHl] = de_AllowedHeaders((0, import_smithy_client.getArrayIfSingleItem)(output[_AH]), context); + } + if (output.AllowedMethod === "") { + contents[_AMl] = []; + } else if (output[_AM] != null) { + contents[_AMl] = de_AllowedMethods((0, import_smithy_client.getArrayIfSingleItem)(output[_AM]), context); + } + if (output.AllowedOrigin === "") { + contents[_AOl] = []; + } else if (output[_AO] != null) { + contents[_AOl] = de_AllowedOrigins((0, import_smithy_client.getArrayIfSingleItem)(output[_AO]), context); + } + if (output.ExposeHeader === "") { + contents[_EH] = []; + } else if (output[_EHx] != null) { + contents[_EH] = de_ExposeHeaders((0, import_smithy_client.getArrayIfSingleItem)(output[_EHx]), context); + } + if (output[_MAS] != null) { + contents[_MAS] = (0, import_smithy_client.strictParseInt32)(output[_MAS]); + } + return contents; +}, "de_CORSRule"); +var de_CORSRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_CORSRule(entry, context); + }); +}, "de_CORSRules"); +var de_DefaultRetention = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Mo] != null) { + contents[_Mo] = (0, import_smithy_client.expectString)(output[_Mo]); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_Y] != null) { + contents[_Y] = (0, import_smithy_client.strictParseInt32)(output[_Y]); + } + return contents; +}, "de_DefaultRetention"); +var de_DeletedObject = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_DM] != null) { + contents[_DM] = (0, import_smithy_client.parseBoolean)(output[_DM]); + } + if (output[_DMVI] != null) { + contents[_DMVI] = (0, import_smithy_client.expectString)(output[_DMVI]); + } + return contents; +}, "de_DeletedObject"); +var de_DeletedObjects = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_DeletedObject(entry, context); + }); +}, "de_DeletedObjects"); +var de_DeleteMarkerEntry = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_IL] != null) { + contents[_IL] = (0, import_smithy_client.parseBoolean)(output[_IL]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + return contents; +}, "de_DeleteMarkerEntry"); +var de_DeleteMarkerReplication = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_DeleteMarkerReplication"); +var de_DeleteMarkers = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_DeleteMarkerEntry(entry, context); + }); +}, "de_DeleteMarkers"); +var de_Destination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(output[_B]); + } + if (output[_Ac] != null) { + contents[_Ac] = (0, import_smithy_client.expectString)(output[_Ac]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_ACT] != null) { + contents[_ACT] = de_AccessControlTranslation(output[_ACT], context); + } + if (output[_ECn] != null) { + contents[_ECn] = de_EncryptionConfiguration(output[_ECn], context); + } + if (output[_RTe] != null) { + contents[_RTe] = de_ReplicationTime(output[_RTe], context); + } + if (output[_Me] != null) { + contents[_Me] = de_Metrics(output[_Me], context); + } + return contents; +}, "de_Destination"); +var de_DestinationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TBT] != null) { + contents[_TBT] = (0, import_smithy_client.expectString)(output[_TBT]); + } + if (output[_TBA] != null) { + contents[_TBA] = (0, import_smithy_client.expectString)(output[_TBA]); + } + if (output[_TNa] != null) { + contents[_TNa] = (0, import_smithy_client.expectString)(output[_TNa]); + } + return contents; +}, "de_DestinationResult"); +var de_EncryptionConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_RKKID] != null) { + contents[_RKKID] = (0, import_smithy_client.expectString)(output[_RKKID]); + } + return contents; +}, "de_EncryptionConfiguration"); +var de_EndEvent = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_EndEvent"); +var de__Error = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_Cod] != null) { + contents[_Cod] = (0, import_smithy_client.expectString)(output[_Cod]); + } + if (output[_Mes] != null) { + contents[_Mes] = (0, import_smithy_client.expectString)(output[_Mes]); + } + return contents; +}, "de__Error"); +var de_ErrorDetails = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_EC] != null) { + contents[_EC] = (0, import_smithy_client.expectString)(output[_EC]); + } + if (output[_EM] != null) { + contents[_EM] = (0, import_smithy_client.expectString)(output[_EM]); + } + return contents; +}, "de_ErrorDetails"); +var de_ErrorDocument = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + return contents; +}, "de_ErrorDocument"); +var de_Errors = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de__Error(entry, context); + }); +}, "de_Errors"); +var de_EventBridgeConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_EventBridgeConfiguration"); +var de_EventList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_EventList"); +var de_ExistingObjectReplication = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_ExistingObjectReplication"); +var de_ExposeHeaders = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_ExposeHeaders"); +var de_FilterRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(output[_N]); + } + if (output[_Va] != null) { + contents[_Va] = (0, import_smithy_client.expectString)(output[_Va]); + } + return contents; +}, "de_FilterRule"); +var de_FilterRuleList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_FilterRule(entry, context); + }); +}, "de_FilterRuleList"); +var de_GetBucketMetadataConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_MCR] != null) { + contents[_MCR] = de_MetadataConfigurationResult(output[_MCR], context); + } + return contents; +}, "de_GetBucketMetadataConfigurationResult"); +var de_GetBucketMetadataTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_MTCR] != null) { + contents[_MTCR] = de_MetadataTableConfigurationResult(output[_MTCR], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_Er] != null) { + contents[_Er] = de_ErrorDetails(output[_Er], context); + } + return contents; +}, "de_GetBucketMetadataTableConfigurationResult"); +var de_GetObjectAttributesParts = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PC] != null) { + contents[_TPC] = (0, import_smithy_client.strictParseInt32)(output[_PC]); + } + if (output[_PNM] != null) { + contents[_PNM] = (0, import_smithy_client.expectString)(output[_PNM]); + } + if (output[_NPNM] != null) { + contents[_NPNM] = (0, import_smithy_client.expectString)(output[_NPNM]); + } + if (output[_MP] != null) { + contents[_MP] = (0, import_smithy_client.strictParseInt32)(output[_MP]); + } + if (output[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(output[_IT]); + } + if (output.Part === "") { + contents[_Part] = []; + } else if (output[_Par] != null) { + contents[_Part] = de_PartsList((0, import_smithy_client.getArrayIfSingleItem)(output[_Par]), context); + } + return contents; +}, "de_GetObjectAttributesParts"); +var de_Grant = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Gra] != null) { + contents[_Gra] = de_Grantee(output[_Gra], context); + } + if (output[_Pe] != null) { + contents[_Pe] = (0, import_smithy_client.expectString)(output[_Pe]); + } + return contents; +}, "de_Grant"); +var de_Grantee = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DN] != null) { + contents[_DN] = (0, import_smithy_client.expectString)(output[_DN]); + } + if (output[_EA] != null) { + contents[_EA] = (0, import_smithy_client.expectString)(output[_EA]); + } + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_URI] != null) { + contents[_URI] = (0, import_smithy_client.expectString)(output[_URI]); + } + if (output[_x] != null) { + contents[_Ty] = (0, import_smithy_client.expectString)(output[_x]); + } + return contents; +}, "de_Grantee"); +var de_Grants = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Grant(entry, context); + }); +}, "de_Grants"); +var de_IndexDocument = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Su] != null) { + contents[_Su] = (0, import_smithy_client.expectString)(output[_Su]); + } + return contents; +}, "de_IndexDocument"); +var de_Initiator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_DN] != null) { + contents[_DN] = (0, import_smithy_client.expectString)(output[_DN]); + } + return contents; +}, "de_Initiator"); +var de_IntelligentTieringAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + return contents; +}, "de_IntelligentTieringAndOperator"); +var de_IntelligentTieringConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_F] != null) { + contents[_F] = de_IntelligentTieringFilter(output[_F], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output.Tiering === "") { + contents[_Tie] = []; + } else if (output[_Tier] != null) { + contents[_Tie] = de_TieringList((0, import_smithy_client.getArrayIfSingleItem)(output[_Tier]), context); + } + return contents; +}, "de_IntelligentTieringConfiguration"); +var de_IntelligentTieringConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_IntelligentTieringConfiguration(entry, context); + }); +}, "de_IntelligentTieringConfigurationList"); +var de_IntelligentTieringFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_Ta] != null) { + contents[_Ta] = de_Tag(output[_Ta], context); + } + if (output[_A] != null) { + contents[_A] = de_IntelligentTieringAndOperator(output[_A], context); + } + return contents; +}, "de_IntelligentTieringFilter"); +var de_InventoryConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Des] != null) { + contents[_Des] = de_InventoryDestination(output[_Des], context); + } + if (output[_IE] != null) { + contents[_IE] = (0, import_smithy_client.parseBoolean)(output[_IE]); + } + if (output[_F] != null) { + contents[_F] = de_InventoryFilter(output[_F], context); + } + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_IOV] != null) { + contents[_IOV] = (0, import_smithy_client.expectString)(output[_IOV]); + } + if (output.OptionalFields === "") { + contents[_OF] = []; + } else if (output[_OF] != null && output[_OF][_Fi] != null) { + contents[_OF] = de_InventoryOptionalFields((0, import_smithy_client.getArrayIfSingleItem)(output[_OF][_Fi]), context); + } + if (output[_Sc] != null) { + contents[_Sc] = de_InventorySchedule(output[_Sc], context); + } + return contents; +}, "de_InventoryConfiguration"); +var de_InventoryConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_InventoryConfiguration(entry, context); + }); +}, "de_InventoryConfigurationList"); +var de_InventoryDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SBD] != null) { + contents[_SBD] = de_InventoryS3BucketDestination(output[_SBD], context); + } + return contents; +}, "de_InventoryDestination"); +var de_InventoryEncryption = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SS] != null) { + contents[_SSES] = de_SSES3(output[_SS], context); + } + if (output[_SK] != null) { + contents[_SSEKMS] = de_SSEKMS(output[_SK], context); + } + return contents; +}, "de_InventoryEncryption"); +var de_InventoryFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + return contents; +}, "de_InventoryFilter"); +var de_InventoryOptionalFields = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_InventoryOptionalFields"); +var de_InventoryS3BucketDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_AIc] != null) { + contents[_AIc] = (0, import_smithy_client.expectString)(output[_AIc]); + } + if (output[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(output[_B]); + } + if (output[_Fo] != null) { + contents[_Fo] = (0, import_smithy_client.expectString)(output[_Fo]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_En] != null) { + contents[_En] = de_InventoryEncryption(output[_En], context); + } + return contents; +}, "de_InventoryS3BucketDestination"); +var de_InventorySchedule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Fr] != null) { + contents[_Fr] = (0, import_smithy_client.expectString)(output[_Fr]); + } + return contents; +}, "de_InventorySchedule"); +var de_InventoryTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_CSo] != null) { + contents[_CSo] = (0, import_smithy_client.expectString)(output[_CSo]); + } + if (output[_TSa] != null) { + contents[_TSa] = (0, import_smithy_client.expectString)(output[_TSa]); + } + if (output[_Er] != null) { + contents[_Er] = de_ErrorDetails(output[_Er], context); + } + if (output[_TN] != null) { + contents[_TN] = (0, import_smithy_client.expectString)(output[_TN]); + } + if (output[_TAa] != null) { + contents[_TAa] = (0, import_smithy_client.expectString)(output[_TAa]); + } + return contents; +}, "de_InventoryTableConfigurationResult"); +var de_JournalTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TSa] != null) { + contents[_TSa] = (0, import_smithy_client.expectString)(output[_TSa]); + } + if (output[_Er] != null) { + contents[_Er] = de_ErrorDetails(output[_Er], context); + } + if (output[_TN] != null) { + contents[_TN] = (0, import_smithy_client.expectString)(output[_TN]); + } + if (output[_TAa] != null) { + contents[_TAa] = (0, import_smithy_client.expectString)(output[_TAa]); + } + if (output[_REe] != null) { + contents[_REe] = de_RecordExpiration(output[_REe], context); + } + return contents; +}, "de_JournalTableConfigurationResult"); +var de_LambdaFunctionConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_CF] != null) { + contents[_LFA] = (0, import_smithy_client.expectString)(output[_CF]); + } + if (output.Event === "") { + contents[_Eve] = []; + } else if (output[_Ev] != null) { + contents[_Eve] = de_EventList((0, import_smithy_client.getArrayIfSingleItem)(output[_Ev]), context); + } + if (output[_F] != null) { + contents[_F] = de_NotificationConfigurationFilter(output[_F], context); + } + return contents; +}, "de_LambdaFunctionConfiguration"); +var de_LambdaFunctionConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_LambdaFunctionConfiguration(entry, context); + }); +}, "de_LambdaFunctionConfigurationList"); +var de_LifecycleExpiration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Dat] != null) { + contents[_Dat] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Dat])); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_EODM] != null) { + contents[_EODM] = (0, import_smithy_client.parseBoolean)(output[_EODM]); + } + return contents; +}, "de_LifecycleExpiration"); +var de_LifecycleRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Exp] != null) { + contents[_Exp] = de_LifecycleExpiration(output[_Exp], context); + } + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_F] != null) { + contents[_F] = de_LifecycleRuleFilter(output[_F], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output.Transition === "") { + contents[_Tr] = []; + } else if (output[_Tra] != null) { + contents[_Tr] = de_TransitionList((0, import_smithy_client.getArrayIfSingleItem)(output[_Tra]), context); + } + if (output.NoncurrentVersionTransition === "") { + contents[_NVT] = []; + } else if (output[_NVTo] != null) { + contents[_NVT] = de_NoncurrentVersionTransitionList((0, import_smithy_client.getArrayIfSingleItem)(output[_NVTo]), context); + } + if (output[_NVE] != null) { + contents[_NVE] = de_NoncurrentVersionExpiration(output[_NVE], context); + } + if (output[_AIMU] != null) { + contents[_AIMU] = de_AbortIncompleteMultipartUpload(output[_AIMU], context); + } + return contents; +}, "de_LifecycleRule"); +var de_LifecycleRuleAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + if (output[_OSGT] != null) { + contents[_OSGT] = (0, import_smithy_client.strictParseLong)(output[_OSGT]); + } + if (output[_OSLT] != null) { + contents[_OSLT] = (0, import_smithy_client.strictParseLong)(output[_OSLT]); + } + return contents; +}, "de_LifecycleRuleAndOperator"); +var de_LifecycleRuleFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_Ta] != null) { + contents[_Ta] = de_Tag(output[_Ta], context); + } + if (output[_OSGT] != null) { + contents[_OSGT] = (0, import_smithy_client.strictParseLong)(output[_OSGT]); + } + if (output[_OSLT] != null) { + contents[_OSLT] = (0, import_smithy_client.strictParseLong)(output[_OSLT]); + } + if (output[_A] != null) { + contents[_A] = de_LifecycleRuleAndOperator(output[_A], context); + } + return contents; +}, "de_LifecycleRuleFilter"); +var de_LifecycleRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_LifecycleRule(entry, context); + }); +}, "de_LifecycleRules"); +var de_LoggingEnabled = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TB] != null) { + contents[_TB] = (0, import_smithy_client.expectString)(output[_TB]); + } + if (output.TargetGrants === "") { + contents[_TG] = []; + } else if (output[_TG] != null && output[_TG][_G] != null) { + contents[_TG] = de_TargetGrants((0, import_smithy_client.getArrayIfSingleItem)(output[_TG][_G]), context); + } + if (output[_TP] != null) { + contents[_TP] = (0, import_smithy_client.expectString)(output[_TP]); + } + if (output[_TOKF] != null) { + contents[_TOKF] = de_TargetObjectKeyFormat(output[_TOKF], context); + } + return contents; +}, "de_LoggingEnabled"); +var de_MetadataConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DRes] != null) { + contents[_DRes] = de_DestinationResult(output[_DRes], context); + } + if (output[_JTCR] != null) { + contents[_JTCR] = de_JournalTableConfigurationResult(output[_JTCR], context); + } + if (output[_ITCR] != null) { + contents[_ITCR] = de_InventoryTableConfigurationResult(output[_ITCR], context); + } + return contents; +}, "de_MetadataConfigurationResult"); +var de_MetadataTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_STDR] != null) { + contents[_STDR] = de_S3TablesDestinationResult(output[_STDR], context); + } + return contents; +}, "de_MetadataTableConfigurationResult"); +var de_Metrics = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_ETv] != null) { + contents[_ETv] = de_ReplicationTimeValue(output[_ETv], context); + } + return contents; +}, "de_Metrics"); +var de_MetricsAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + if (output[_APAc] != null) { + contents[_APAc] = (0, import_smithy_client.expectString)(output[_APAc]); + } + return contents; +}, "de_MetricsAndOperator"); +var de_MetricsConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output.Filter === "") { + } else if (output[_F] != null) { + contents[_F] = de_MetricsFilter((0, import_smithy_client.expectUnion)(output[_F]), context); + } + return contents; +}, "de_MetricsConfiguration"); +var de_MetricsConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_MetricsConfiguration(entry, context); + }); +}, "de_MetricsConfigurationList"); +var de_MetricsFilter = /* @__PURE__ */ __name((output, context) => { + if (output[_P] != null) { + return { + Prefix: (0, import_smithy_client.expectString)(output[_P]) + }; + } + if (output[_Ta] != null) { + return { + Tag: de_Tag(output[_Ta], context) + }; + } + if (output[_APAc] != null) { + return { + AccessPointArn: (0, import_smithy_client.expectString)(output[_APAc]) + }; + } + if (output[_A] != null) { + return { + And: de_MetricsAndOperator(output[_A], context) + }; + } + return { $unknown: Object.entries(output)[0] }; +}, "de_MetricsFilter"); +var de_MultipartUpload = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_UI] != null) { + contents[_UI] = (0, import_smithy_client.expectString)(output[_UI]); + } + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_Ini] != null) { + contents[_Ini] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Ini])); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_In] != null) { + contents[_In] = de_Initiator(output[_In], context); + } + if (output[_CA] != null) { + contents[_CA] = (0, import_smithy_client.expectString)(output[_CA]); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + return contents; +}, "de_MultipartUpload"); +var de_MultipartUploadList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_MultipartUpload(entry, context); + }); +}, "de_MultipartUploadList"); +var de_NoncurrentVersionExpiration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ND] != null) { + contents[_ND] = (0, import_smithy_client.strictParseInt32)(output[_ND]); + } + if (output[_NNV] != null) { + contents[_NNV] = (0, import_smithy_client.strictParseInt32)(output[_NNV]); + } + return contents; +}, "de_NoncurrentVersionExpiration"); +var de_NoncurrentVersionTransition = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ND] != null) { + contents[_ND] = (0, import_smithy_client.strictParseInt32)(output[_ND]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_NNV] != null) { + contents[_NNV] = (0, import_smithy_client.strictParseInt32)(output[_NNV]); + } + return contents; +}, "de_NoncurrentVersionTransition"); +var de_NoncurrentVersionTransitionList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_NoncurrentVersionTransition(entry, context); + }); +}, "de_NoncurrentVersionTransitionList"); +var de_NotificationConfigurationFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SKe] != null) { + contents[_K] = de_S3KeyFilter(output[_SKe], context); + } + return contents; +}, "de_NotificationConfigurationFilter"); +var de__Object = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output.ChecksumAlgorithm === "") { + contents[_CA] = []; + } else if (output[_CA] != null) { + contents[_CA] = de_ChecksumAlgorithmList((0, import_smithy_client.getArrayIfSingleItem)(output[_CA]), context); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_RSes] != null) { + contents[_RSes] = de_RestoreStatus(output[_RSes], context); + } + return contents; +}, "de__Object"); +var de_ObjectList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de__Object(entry, context); + }); +}, "de_ObjectList"); +var de_ObjectLockConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_OLE] != null) { + contents[_OLE] = (0, import_smithy_client.expectString)(output[_OLE]); + } + if (output[_Ru] != null) { + contents[_Ru] = de_ObjectLockRule(output[_Ru], context); + } + return contents; +}, "de_ObjectLockConfiguration"); +var de_ObjectLockLegalHold = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_ObjectLockLegalHold"); +var de_ObjectLockRetention = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Mo] != null) { + contents[_Mo] = (0, import_smithy_client.expectString)(output[_Mo]); + } + if (output[_RUD] != null) { + contents[_RUD] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_RUD])); + } + return contents; +}, "de_ObjectLockRetention"); +var de_ObjectLockRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DRe] != null) { + contents[_DRe] = de_DefaultRetention(output[_DRe], context); + } + return contents; +}, "de_ObjectLockRule"); +var de_ObjectPart = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PN] != null) { + contents[_PN] = (0, import_smithy_client.strictParseInt32)(output[_PN]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_ObjectPart"); +var de_ObjectVersion = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output.ChecksumAlgorithm === "") { + contents[_CA] = []; + } else if (output[_CA] != null) { + contents[_CA] = de_ChecksumAlgorithmList((0, import_smithy_client.getArrayIfSingleItem)(output[_CA]), context); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_IL] != null) { + contents[_IL] = (0, import_smithy_client.parseBoolean)(output[_IL]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_RSes] != null) { + contents[_RSes] = de_RestoreStatus(output[_RSes], context); + } + return contents; +}, "de_ObjectVersion"); +var de_ObjectVersionList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ObjectVersion(entry, context); + }); +}, "de_ObjectVersionList"); +var de_Owner = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DN] != null) { + contents[_DN] = (0, import_smithy_client.expectString)(output[_DN]); + } + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + return contents; +}, "de_Owner"); +var de_OwnershipControls = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output.Rule === "") { + contents[_Rul] = []; + } else if (output[_Ru] != null) { + contents[_Rul] = de_OwnershipControlsRules((0, import_smithy_client.getArrayIfSingleItem)(output[_Ru]), context); + } + return contents; +}, "de_OwnershipControls"); +var de_OwnershipControlsRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_OO] != null) { + contents[_OO] = (0, import_smithy_client.expectString)(output[_OO]); + } + return contents; +}, "de_OwnershipControlsRule"); +var de_OwnershipControlsRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_OwnershipControlsRule(entry, context); + }); +}, "de_OwnershipControlsRules"); +var de_Part = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PN] != null) { + contents[_PN] = (0, import_smithy_client.strictParseInt32)(output[_PN]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_Part"); +var de_PartitionedPrefix = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PDS] != null) { + contents[_PDS] = (0, import_smithy_client.expectString)(output[_PDS]); + } + return contents; +}, "de_PartitionedPrefix"); +var de_Parts = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Part(entry, context); + }); +}, "de_Parts"); +var de_PartsList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ObjectPart(entry, context); + }); +}, "de_PartsList"); +var de_PolicyStatus = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_IP] != null) { + contents[_IP] = (0, import_smithy_client.parseBoolean)(output[_IP]); + } + return contents; +}, "de_PolicyStatus"); +var de_Progress = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_BS] != null) { + contents[_BS] = (0, import_smithy_client.strictParseLong)(output[_BS]); + } + if (output[_BP] != null) { + contents[_BP] = (0, import_smithy_client.strictParseLong)(output[_BP]); + } + if (output[_BRy] != null) { + contents[_BRy] = (0, import_smithy_client.strictParseLong)(output[_BRy]); + } + return contents; +}, "de_Progress"); +var de_PublicAccessBlockConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_BPA] != null) { + contents[_BPA] = (0, import_smithy_client.parseBoolean)(output[_BPA]); + } + if (output[_IPA] != null) { + contents[_IPA] = (0, import_smithy_client.parseBoolean)(output[_IPA]); + } + if (output[_BPP] != null) { + contents[_BPP] = (0, import_smithy_client.parseBoolean)(output[_BPP]); + } + if (output[_RPB] != null) { + contents[_RPB] = (0, import_smithy_client.parseBoolean)(output[_RPB]); + } + return contents; +}, "de_PublicAccessBlockConfiguration"); +var de_QueueConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_Qu] != null) { + contents[_QA] = (0, import_smithy_client.expectString)(output[_Qu]); + } + if (output.Event === "") { + contents[_Eve] = []; + } else if (output[_Ev] != null) { + contents[_Eve] = de_EventList((0, import_smithy_client.getArrayIfSingleItem)(output[_Ev]), context); + } + if (output[_F] != null) { + contents[_F] = de_NotificationConfigurationFilter(output[_F], context); + } + return contents; +}, "de_QueueConfiguration"); +var de_QueueConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_QueueConfiguration(entry, context); + }); +}, "de_QueueConfigurationList"); +var de_RecordExpiration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Exp] != null) { + contents[_Exp] = (0, import_smithy_client.expectString)(output[_Exp]); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + return contents; +}, "de_RecordExpiration"); +var de_Redirect = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_HN] != null) { + contents[_HN] = (0, import_smithy_client.expectString)(output[_HN]); + } + if (output[_HRC] != null) { + contents[_HRC] = (0, import_smithy_client.expectString)(output[_HRC]); + } + if (output[_Pr] != null) { + contents[_Pr] = (0, import_smithy_client.expectString)(output[_Pr]); + } + if (output[_RKPW] != null) { + contents[_RKPW] = (0, import_smithy_client.expectString)(output[_RKPW]); + } + if (output[_RKW] != null) { + contents[_RKW] = (0, import_smithy_client.expectString)(output[_RKW]); + } + return contents; +}, "de_Redirect"); +var de_RedirectAllRequestsTo = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_HN] != null) { + contents[_HN] = (0, import_smithy_client.expectString)(output[_HN]); + } + if (output[_Pr] != null) { + contents[_Pr] = (0, import_smithy_client.expectString)(output[_Pr]); + } + return contents; +}, "de_RedirectAllRequestsTo"); +var de_ReplicaModifications = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_ReplicaModifications"); +var de_ReplicationConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Ro] != null) { + contents[_Ro] = (0, import_smithy_client.expectString)(output[_Ro]); + } + if (output.Rule === "") { + contents[_Rul] = []; + } else if (output[_Ru] != null) { + contents[_Rul] = de_ReplicationRules((0, import_smithy_client.getArrayIfSingleItem)(output[_Ru]), context); + } + return contents; +}, "de_ReplicationConfiguration"); +var de_ReplicationRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_Pri] != null) { + contents[_Pri] = (0, import_smithy_client.strictParseInt32)(output[_Pri]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_F] != null) { + contents[_F] = de_ReplicationRuleFilter(output[_F], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_SSC] != null) { + contents[_SSC] = de_SourceSelectionCriteria(output[_SSC], context); + } + if (output[_EOR] != null) { + contents[_EOR] = de_ExistingObjectReplication(output[_EOR], context); + } + if (output[_Des] != null) { + contents[_Des] = de_Destination(output[_Des], context); + } + if (output[_DMR] != null) { + contents[_DMR] = de_DeleteMarkerReplication(output[_DMR], context); + } + return contents; +}, "de_ReplicationRule"); +var de_ReplicationRuleAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + return contents; +}, "de_ReplicationRuleAndOperator"); +var de_ReplicationRuleFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_Ta] != null) { + contents[_Ta] = de_Tag(output[_Ta], context); + } + if (output[_A] != null) { + contents[_A] = de_ReplicationRuleAndOperator(output[_A], context); + } + return contents; +}, "de_ReplicationRuleFilter"); +var de_ReplicationRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ReplicationRule(entry, context); + }); +}, "de_ReplicationRules"); +var de_ReplicationTime = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_Tim] != null) { + contents[_Tim] = de_ReplicationTimeValue(output[_Tim], context); + } + return contents; +}, "de_ReplicationTime"); +var de_ReplicationTimeValue = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Mi] != null) { + contents[_Mi] = (0, import_smithy_client.strictParseInt32)(output[_Mi]); + } + return contents; +}, "de_ReplicationTimeValue"); +var de_RestoreStatus = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_IRIP] != null) { + contents[_IRIP] = (0, import_smithy_client.parseBoolean)(output[_IRIP]); + } + if (output[_REDe] != null) { + contents[_REDe] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_REDe])); + } + return contents; +}, "de_RestoreStatus"); +var de_RoutingRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Con] != null) { + contents[_Con] = de_Condition(output[_Con], context); + } + if (output[_Red] != null) { + contents[_Red] = de_Redirect(output[_Red], context); + } + return contents; +}, "de_RoutingRule"); +var de_RoutingRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_RoutingRule(entry, context); + }); +}, "de_RoutingRules"); +var de_S3KeyFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output.FilterRule === "") { + contents[_FRi] = []; + } else if (output[_FR] != null) { + contents[_FRi] = de_FilterRuleList((0, import_smithy_client.getArrayIfSingleItem)(output[_FR]), context); + } + return contents; +}, "de_S3KeyFilter"); +var de_S3TablesDestinationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TBA] != null) { + contents[_TBA] = (0, import_smithy_client.expectString)(output[_TBA]); + } + if (output[_TN] != null) { + contents[_TN] = (0, import_smithy_client.expectString)(output[_TN]); + } + if (output[_TAa] != null) { + contents[_TAa] = (0, import_smithy_client.expectString)(output[_TAa]); + } + if (output[_TNa] != null) { + contents[_TNa] = (0, import_smithy_client.expectString)(output[_TNa]); + } + return contents; +}, "de_S3TablesDestinationResult"); +var de_ServerSideEncryptionByDefault = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SSEA] != null) { + contents[_SSEA] = (0, import_smithy_client.expectString)(output[_SSEA]); + } + if (output[_KMSMKID] != null) { + contents[_KMSMKID] = (0, import_smithy_client.expectString)(output[_KMSMKID]); + } + return contents; +}, "de_ServerSideEncryptionByDefault"); +var de_ServerSideEncryptionConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output.Rule === "") { + contents[_Rul] = []; + } else if (output[_Ru] != null) { + contents[_Rul] = de_ServerSideEncryptionRules((0, import_smithy_client.getArrayIfSingleItem)(output[_Ru]), context); + } + return contents; +}, "de_ServerSideEncryptionConfiguration"); +var de_ServerSideEncryptionRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ASSEBD] != null) { + contents[_ASSEBD] = de_ServerSideEncryptionByDefault(output[_ASSEBD], context); + } + if (output[_BKE] != null) { + contents[_BKE] = (0, import_smithy_client.parseBoolean)(output[_BKE]); + } + return contents; +}, "de_ServerSideEncryptionRule"); +var de_ServerSideEncryptionRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ServerSideEncryptionRule(entry, context); + }); +}, "de_ServerSideEncryptionRules"); +var de_SessionCredentials = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_AKI] != null) { + contents[_AKI] = (0, import_smithy_client.expectString)(output[_AKI]); + } + if (output[_SAK] != null) { + contents[_SAK] = (0, import_smithy_client.expectString)(output[_SAK]); + } + if (output[_ST] != null) { + contents[_ST] = (0, import_smithy_client.expectString)(output[_ST]); + } + if (output[_Exp] != null) { + contents[_Exp] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Exp])); + } + return contents; +}, "de_SessionCredentials"); +var de_SimplePrefix = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_SimplePrefix"); +var de_SourceSelectionCriteria = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SKEO] != null) { + contents[_SKEO] = de_SseKmsEncryptedObjects(output[_SKEO], context); + } + if (output[_RM] != null) { + contents[_RM] = de_ReplicaModifications(output[_RM], context); + } + return contents; +}, "de_SourceSelectionCriteria"); +var de_SSEKMS = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_KI] != null) { + contents[_KI] = (0, import_smithy_client.expectString)(output[_KI]); + } + return contents; +}, "de_SSEKMS"); +var de_SseKmsEncryptedObjects = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_SseKmsEncryptedObjects"); +var de_SSES3 = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_SSES3"); +var de_Stats = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_BS] != null) { + contents[_BS] = (0, import_smithy_client.strictParseLong)(output[_BS]); + } + if (output[_BP] != null) { + contents[_BP] = (0, import_smithy_client.strictParseLong)(output[_BP]); + } + if (output[_BRy] != null) { + contents[_BRy] = (0, import_smithy_client.strictParseLong)(output[_BRy]); + } + return contents; +}, "de_Stats"); +var de_StorageClassAnalysis = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DE] != null) { + contents[_DE] = de_StorageClassAnalysisDataExport(output[_DE], context); + } + return contents; +}, "de_StorageClassAnalysis"); +var de_StorageClassAnalysisDataExport = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_OSV] != null) { + contents[_OSV] = (0, import_smithy_client.expectString)(output[_OSV]); + } + if (output[_Des] != null) { + contents[_Des] = de_AnalyticsExportDestination(output[_Des], context); + } + return contents; +}, "de_StorageClassAnalysisDataExport"); +var de_Tag = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_Va] != null) { + contents[_Va] = (0, import_smithy_client.expectString)(output[_Va]); + } + return contents; +}, "de_Tag"); +var de_TagSet = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Tag(entry, context); + }); +}, "de_TagSet"); +var de_TargetGrant = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Gra] != null) { + contents[_Gra] = de_Grantee(output[_Gra], context); + } + if (output[_Pe] != null) { + contents[_Pe] = (0, import_smithy_client.expectString)(output[_Pe]); + } + return contents; +}, "de_TargetGrant"); +var de_TargetGrants = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_TargetGrant(entry, context); + }); +}, "de_TargetGrants"); +var de_TargetObjectKeyFormat = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SPi] != null) { + contents[_SPi] = de_SimplePrefix(output[_SPi], context); + } + if (output[_PP] != null) { + contents[_PP] = de_PartitionedPrefix(output[_PP], context); + } + return contents; +}, "de_TargetObjectKeyFormat"); +var de_Tiering = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_AT] != null) { + contents[_AT] = (0, import_smithy_client.expectString)(output[_AT]); + } + return contents; +}, "de_Tiering"); +var de_TieringList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Tiering(entry, context); + }); +}, "de_TieringList"); +var de_TopicConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_Top] != null) { + contents[_TA] = (0, import_smithy_client.expectString)(output[_Top]); + } + if (output.Event === "") { + contents[_Eve] = []; + } else if (output[_Ev] != null) { + contents[_Eve] = de_EventList((0, import_smithy_client.getArrayIfSingleItem)(output[_Ev]), context); + } + if (output[_F] != null) { + contents[_F] = de_NotificationConfigurationFilter(output[_F], context); + } + return contents; +}, "de_TopicConfiguration"); +var de_TopicConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_TopicConfiguration(entry, context); + }); +}, "de_TopicConfigurationList"); +var de_Transition = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Dat] != null) { + contents[_Dat] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Dat])); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + return contents; +}, "de_Transition"); +var de_TransitionList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Transition(entry, context); + }); +}, "de_TransitionList"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); +var collectBodyString = /* @__PURE__ */ __name((streamBody, context) => (0, import_smithy_client.collectBody)(streamBody, context).then((body) => context.utf8Encoder(body)), "collectBodyString"); +var _A = "And"; +var _AAO = "AnalyticsAndOperator"; +var _AC = "AnalyticsConfiguration"; +var _ACL = "ACL"; +var _ACLc = "AccessControlList"; +var _ACLn = "AnalyticsConfigurationList"; +var _ACP = "AccessControlPolicy"; +var _ACT = "AccessControlTranslation"; +var _ACc = "AccelerateConfiguration"; +var _AD = "AbortDate"; +var _AED = "AnalyticsExportDestination"; +var _AF = "AnalyticsFilter"; +var _AH = "AllowedHeader"; +var _AHl = "AllowedHeaders"; +var _AI = "AnalyticsId"; +var _AIMU = "AbortIncompleteMultipartUpload"; +var _AIc = "AccountId"; +var _AKI = "AccessKeyId"; +var _AM = "AllowedMethod"; +var _AMl = "AllowedMethods"; +var _AO = "AllowedOrigin"; +var _AOl = "AllowedOrigins"; +var _APA = "AccessPointAlias"; +var _APAc = "AccessPointArn"; +var _AQRD = "AllowQuotedRecordDelimiter"; +var _AR = "AcceptRanges"; +var _ARI = "AbortRuleId"; +var _AS = "ArchiveStatus"; +var _ASBD = "AnalyticsS3BucketDestination"; +var _ASEFF = "AnalyticsS3ExportFileFormat"; +var _ASSEBD = "ApplyServerSideEncryptionByDefault"; +var _AT = "AccessTier"; +var _Ac = "Account"; +var _B = "Bucket"; +var _BA = "BucketArn"; +var _BAI = "BucketAccountId"; +var _BAS = "BucketAccelerateStatus"; +var _BGR = "BypassGovernanceRetention"; +var _BI = "BucketInfo"; +var _BKE = "BucketKeyEnabled"; +var _BLC = "BucketLifecycleConfiguration"; +var _BLCu = "BucketLocationConstraint"; +var _BLN = "BucketLocationName"; +var _BLP = "BucketLogsPermission"; +var _BLS = "BucketLoggingStatus"; +var _BLT = "BucketLocationType"; +var _BN = "BucketName"; +var _BP = "BytesProcessed"; +var _BPA = "BlockPublicAcls"; +var _BPP = "BlockPublicPolicy"; +var _BR = "BucketRegion"; +var _BRy = "BytesReturned"; +var _BS = "BytesScanned"; +var _BT = "BucketType"; +var _BVS = "BucketVersioningStatus"; +var _Bu = "Buckets"; +var _C = "Credentials"; +var _CA = "ChecksumAlgorithm"; +var _CACL = "CannedACL"; +var _CBC = "CreateBucketConfiguration"; +var _CC = "CacheControl"; +var _CCRC = "ChecksumCRC32"; +var _CCRCC = "ChecksumCRC32C"; +var _CCRCNVME = "ChecksumCRC64NVME"; +var _CD = "ContentDisposition"; +var _CDr = "CreationDate"; +var _CE = "ContentEncoding"; +var _CF = "CloudFunction"; +var _CFC = "CloudFunctionConfiguration"; +var _CL = "ContentLanguage"; +var _CLo = "ContentLength"; +var _CM = "ChecksumMode"; +var _CMD = "ContentMD5"; +var _CMU = "CompletedMultipartUpload"; +var _CORSC = "CORSConfiguration"; +var _CORSR = "CORSRule"; +var _CORSRu = "CORSRules"; +var _CP = "CommonPrefixes"; +var _CPo = "CompletedPart"; +var _CR = "ContentRange"; +var _CRSBA = "ConfirmRemoveSelfBucketAccess"; +var _CS = "CopySource"; +var _CSHA = "ChecksumSHA1"; +var _CSHAh = "ChecksumSHA256"; +var _CSIM = "CopySourceIfMatch"; +var _CSIMS = "CopySourceIfModifiedSince"; +var _CSINM = "CopySourceIfNoneMatch"; +var _CSIUS = "CopySourceIfUnmodifiedSince"; +var _CSR = "CopySourceRange"; +var _CSSSECA = "CopySourceSSECustomerAlgorithm"; +var _CSSSECK = "CopySourceSSECustomerKey"; +var _CSSSECKMD = "CopySourceSSECustomerKeyMD5"; +var _CSV = "CSV"; +var _CSVI = "CopySourceVersionId"; +var _CSVIn = "CSVInput"; +var _CSVO = "CSVOutput"; +var _CSo = "ConfigurationState"; +var _CT = "ChecksumType"; +var _CTl = "ClientToken"; +var _CTo = "ContentType"; +var _CTom = "CompressionType"; +var _CTon = "ContinuationToken"; +var _Ch = "Checksum"; +var _Co = "Contents"; +var _Cod = "Code"; +var _Com = "Comments"; +var _Con = "Condition"; +var _D = "Delimiter"; +var _DAI = "DaysAfterInitiation"; +var _DE = "DataExport"; +var _DIM = "DestinationIfMatch"; +var _DIMS = "DestinationIfModifiedSince"; +var _DINM = "DestinationIfNoneMatch"; +var _DIUS = "DestinationIfUnmodifiedSince"; +var _DM = "DeleteMarker"; +var _DMR = "DeleteMarkerReplication"; +var _DMRS = "DeleteMarkerReplicationStatus"; +var _DMVI = "DeleteMarkerVersionId"; +var _DMe = "DeleteMarkers"; +var _DN = "DisplayName"; +var _DR = "DataRedundancy"; +var _DRe = "DefaultRetention"; +var _DRes = "DestinationResult"; +var _Da = "Days"; +var _Dat = "Date"; +var _De = "Deleted"; +var _Del = "Delete"; +var _Des = "Destination"; +var _Desc = "Description"; +var _E = "Expires"; +var _EA = "EmailAddress"; +var _EBC = "EventBridgeConfiguration"; +var _EBO = "ExpectedBucketOwner"; +var _EC = "ErrorCode"; +var _ECn = "EncryptionConfiguration"; +var _ED = "ErrorDocument"; +var _EH = "ExposeHeaders"; +var _EHx = "ExposeHeader"; +var _EM = "ErrorMessage"; +var _EODM = "ExpiredObjectDeleteMarker"; +var _EOR = "ExistingObjectReplication"; +var _EORS = "ExistingObjectReplicationStatus"; +var _ERP = "EnableRequestProgress"; +var _ES = "ExpiresString"; +var _ESBO = "ExpectedSourceBucketOwner"; +var _ESx = "ExpirationStatus"; +var _ESxp = "ExpirationState"; +var _ET = "EncodingType"; +var _ETa = "ETag"; +var _ETn = "EncryptionType"; +var _ETv = "EventThreshold"; +var _ETx = "ExpressionType"; +var _En = "Encryption"; +var _Ena = "Enabled"; +var _End = "End"; +var _Er = "Error"; +var _Err = "Errors"; +var _Ev = "Event"; +var _Eve = "Events"; +var _Ex = "Expression"; +var _Exp = "Expiration"; +var _F = "Filter"; +var _FD = "FieldDelimiter"; +var _FHI = "FileHeaderInfo"; +var _FO = "FetchOwner"; +var _FR = "FilterRule"; +var _FRN = "FilterRuleName"; +var _FRV = "FilterRuleValue"; +var _FRi = "FilterRules"; +var _Fi = "Field"; +var _Fo = "Format"; +var _Fr = "Frequency"; +var _G = "Grant"; +var _GFC = "GrantFullControl"; +var _GJP = "GlacierJobParameters"; +var _GR = "GrantRead"; +var _GRACP = "GrantReadACP"; +var _GW = "GrantWrite"; +var _GWACP = "GrantWriteACP"; +var _Gr = "Grants"; +var _Gra = "Grantee"; +var _HECRE = "HttpErrorCodeReturnedEquals"; +var _HN = "HostName"; +var _HRC = "HttpRedirectCode"; +var _I = "Id"; +var _IC = "InventoryConfiguration"; +var _ICL = "InventoryConfigurationList"; +var _ICS = "InventoryConfigurationState"; +var _ID = "IndexDocument"; +var _ID_ = "ID"; +var _IDn = "InventoryDestination"; +var _IE = "IsEnabled"; +var _IEn = "InventoryEncryption"; +var _IF = "InventoryFilter"; +var _IFn = "InventoryFormat"; +var _IFnv = "InventoryFrequency"; +var _II = "InventoryId"; +var _IIOV = "InventoryIncludedObjectVersions"; +var _IL = "IsLatest"; +var _IM = "IfMatch"; +var _IMIT = "IfMatchInitiatedTime"; +var _IMLMT = "IfMatchLastModifiedTime"; +var _IMS = "IfMatchSize"; +var _IMSf = "IfModifiedSince"; +var _INM = "IfNoneMatch"; +var _IOF = "InventoryOptionalField"; +var _IOV = "IncludedObjectVersions"; +var _IP = "IsPublic"; +var _IPA = "IgnorePublicAcls"; +var _IRIP = "IsRestoreInProgress"; +var _IS = "InputSerialization"; +var _ISBD = "InventoryS3BucketDestination"; +var _ISn = "InventorySchedule"; +var _IT = "IsTruncated"; +var _ITAO = "IntelligentTieringAndOperator"; +var _ITAT = "IntelligentTieringAccessTier"; +var _ITC = "IntelligentTieringConfiguration"; +var _ITCL = "IntelligentTieringConfigurationList"; +var _ITCR = "InventoryTableConfigurationResult"; +var _ITCU = "InventoryTableConfigurationUpdates"; +var _ITCn = "InventoryTableConfiguration"; +var _ITD = "IntelligentTieringDays"; +var _ITF = "IntelligentTieringFilter"; +var _ITI = "IntelligentTieringId"; +var _ITS = "IntelligentTieringStatus"; +var _IUS = "IfUnmodifiedSince"; +var _In = "Initiator"; +var _Ini = "Initiated"; +var _JSON = "JSON"; +var _JSONI = "JSONInput"; +var _JSONO = "JSONOutput"; +var _JSONT = "JSONType"; +var _JTC = "JournalTableConfiguration"; +var _JTCR = "JournalTableConfigurationResult"; +var _JTCU = "JournalTableConfigurationUpdates"; +var _K = "Key"; +var _KC = "KeyCount"; +var _KI = "KeyId"; +var _KKA = "KmsKeyArn"; +var _KM = "KeyMarker"; +var _KMSC = "KMSContext"; +var _KMSKI = "KMSKeyId"; +var _KMSMKID = "KMSMasterKeyID"; +var _KPE = "KeyPrefixEquals"; +var _L = "Location"; +var _LC = "LocationConstraint"; +var _LE = "LoggingEnabled"; +var _LEi = "LifecycleExpiration"; +var _LFA = "LambdaFunctionArn"; +var _LFC = "LambdaFunctionConfigurations"; +var _LFCa = "LambdaFunctionConfiguration"; +var _LI = "LocationInfo"; +var _LM = "LastModified"; +var _LMT = "LastModifiedTime"; +var _LNAS = "LocationNameAsString"; +var _LP = "LocationPrefix"; +var _LR = "LifecycleRule"; +var _LRAO = "LifecycleRuleAndOperator"; +var _LRF = "LifecycleRuleFilter"; +var _LT = "LocationType"; +var _M = "Marker"; +var _MAO = "MetricsAndOperator"; +var _MAS = "MaxAgeSeconds"; +var _MB = "MaxBuckets"; +var _MC = "MetricsConfiguration"; +var _MCL = "MetricsConfigurationList"; +var _MCR = "MetadataConfigurationResult"; +var _MCe = "MetadataConfiguration"; +var _MD = "MetadataDirective"; +var _MDB = "MaxDirectoryBuckets"; +var _MDf = "MfaDelete"; +var _ME = "MetadataEntry"; +var _MF = "MetricsFilter"; +var _MFA = "MFA"; +var _MFAD = "MFADelete"; +var _MI = "MetricsId"; +var _MK = "MaxKeys"; +var _MKe = "MetadataKey"; +var _MM = "MissingMeta"; +var _MOS = "MpuObjectSize"; +var _MP = "MaxParts"; +var _MS = "MetricsStatus"; +var _MTC = "MetadataTableConfiguration"; +var _MTCR = "MetadataTableConfigurationResult"; +var _MTEC = "MetadataTableEncryptionConfiguration"; +var _MU = "MaxUploads"; +var _MV = "MetadataValue"; +var _Me = "Metrics"; +var _Mes = "Message"; +var _Mi = "Minutes"; +var _Mo = "Mode"; +var _N = "Name"; +var _NC = "NotificationConfiguration"; +var _NCF = "NotificationConfigurationFilter"; +var _NCT = "NextContinuationToken"; +var _ND = "NoncurrentDays"; +var _NI = "NotificationId"; +var _NKM = "NextKeyMarker"; +var _NM = "NextMarker"; +var _NNV = "NewerNoncurrentVersions"; +var _NPNM = "NextPartNumberMarker"; +var _NUIM = "NextUploadIdMarker"; +var _NVE = "NoncurrentVersionExpiration"; +var _NVIM = "NextVersionIdMarker"; +var _NVT = "NoncurrentVersionTransitions"; +var _NVTo = "NoncurrentVersionTransition"; +var _O = "Owner"; +var _OA = "ObjectAttributes"; +var _OC = "OwnershipControls"; +var _OCACL = "ObjectCannedACL"; +var _OCR = "OwnershipControlsRule"; +var _OF = "OptionalFields"; +var _OI = "ObjectIdentifier"; +var _OK = "ObjectKey"; +var _OL = "OutputLocation"; +var _OLC = "ObjectLockConfiguration"; +var _OLE = "ObjectLockEnabled"; +var _OLEFB = "ObjectLockEnabledForBucket"; +var _OLLH = "ObjectLockLegalHold"; +var _OLLHS = "ObjectLockLegalHoldStatus"; +var _OLM = "ObjectLockMode"; +var _OLR = "ObjectLockRetention"; +var _OLRM = "ObjectLockRetentionMode"; +var _OLRUD = "ObjectLockRetainUntilDate"; +var _OLRb = "ObjectLockRule"; +var _OO = "ObjectOwnership"; +var _OOA = "OptionalObjectAttributes"; +var _OOw = "OwnerOverride"; +var _OP = "ObjectParts"; +var _OS = "OutputSerialization"; +var _OSGT = "ObjectSizeGreaterThan"; +var _OSGTB = "ObjectSizeGreaterThanBytes"; +var _OSLT = "ObjectSizeLessThan"; +var _OSLTB = "ObjectSizeLessThanBytes"; +var _OSV = "OutputSchemaVersion"; +var _OSb = "ObjectSize"; +var _OVI = "ObjectVersionId"; +var _Ob = "Objects"; +var _P = "Prefix"; +var _PABC = "PublicAccessBlockConfiguration"; +var _PC = "PartsCount"; +var _PDS = "PartitionDateSource"; +var _PI = "ParquetInput"; +var _PN = "PartNumber"; +var _PNM = "PartNumberMarker"; +var _PP = "PartitionedPrefix"; +var _Pa = "Payer"; +var _Par = "Part"; +var _Parq = "Parquet"; +var _Part = "Parts"; +var _Pe = "Permission"; +var _Pr = "Protocol"; +var _Pri = "Priority"; +var _Q = "Quiet"; +var _QA = "QueueArn"; +var _QC = "QueueConfiguration"; +var _QCu = "QueueConfigurations"; +var _QCuo = "QuoteCharacter"; +var _QEC = "QuoteEscapeCharacter"; +var _QF = "QuoteFields"; +var _Qu = "Queue"; +var _R = "Range"; +var _RART = "RedirectAllRequestsTo"; +var _RC = "RequestCharged"; +var _RCC = "ResponseCacheControl"; +var _RCD = "ResponseContentDisposition"; +var _RCE = "ResponseContentEncoding"; +var _RCL = "ResponseContentLanguage"; +var _RCT = "ResponseContentType"; +var _RCe = "ReplicationConfiguration"; +var _RD = "RecordDelimiter"; +var _RE = "ResponseExpires"; +var _RED = "RecordExpirationDays"; +var _REDe = "RestoreExpiryDate"; +var _REe = "RecordExpiration"; +var _RKKID = "ReplicaKmsKeyID"; +var _RKPW = "ReplaceKeyPrefixWith"; +var _RKW = "ReplaceKeyWith"; +var _RM = "ReplicaModifications"; +var _RMS = "ReplicaModificationsStatus"; +var _ROP = "RestoreOutputPath"; +var _RP = "RequestPayer"; +var _RPB = "RestrictPublicBuckets"; +var _RPC = "RequestPaymentConfiguration"; +var _RPe = "RequestProgress"; +var _RR = "RequestRoute"; +var _RRAO = "ReplicationRuleAndOperator"; +var _RRF = "ReplicationRuleFilter"; +var _RRS = "ReplicationRuleStatus"; +var _RRT = "RestoreRequestType"; +var _RRe = "ReplicationRule"; +var _RRes = "RestoreRequest"; +var _RRo = "RoutingRules"; +var _RRou = "RoutingRule"; +var _RS = "RenameSource"; +var _RSe = "ReplicationStatus"; +var _RSes = "RestoreStatus"; +var _RT = "RequestToken"; +var _RTS = "ReplicationTimeStatus"; +var _RTV = "ReplicationTimeValue"; +var _RTe = "ReplicationTime"; +var _RUD = "RetainUntilDate"; +var _Re = "Restore"; +var _Red = "Redirect"; +var _Ro = "Role"; +var _Ru = "Rule"; +var _Rul = "Rules"; +var _S = "Status"; +var _SA = "StartAfter"; +var _SAK = "SecretAccessKey"; +var _SAs = "SseAlgorithm"; +var _SBD = "S3BucketDestination"; +var _SC = "StorageClass"; +var _SCA = "StorageClassAnalysis"; +var _SCADE = "StorageClassAnalysisDataExport"; +var _SCASV = "StorageClassAnalysisSchemaVersion"; +var _SCt = "StatusCode"; +var _SDV = "SkipDestinationValidation"; +var _SIM = "SourceIfMatch"; +var _SIMS = "SourceIfModifiedSince"; +var _SINM = "SourceIfNoneMatch"; +var _SIUS = "SourceIfUnmodifiedSince"; +var _SK = "SSE-KMS"; +var _SKEO = "SseKmsEncryptedObjects"; +var _SKEOS = "SseKmsEncryptedObjectsStatus"; +var _SKF = "S3KeyFilter"; +var _SKe = "S3Key"; +var _SL = "S3Location"; +var _SM = "SessionMode"; +var _SOCR = "SelectObjectContentRequest"; +var _SP = "SelectParameters"; +var _SPi = "SimplePrefix"; +var _SR = "ScanRange"; +var _SS = "SSE-S3"; +var _SSC = "SourceSelectionCriteria"; +var _SSE = "ServerSideEncryption"; +var _SSEA = "SSEAlgorithm"; +var _SSEBD = "ServerSideEncryptionByDefault"; +var _SSEC = "ServerSideEncryptionConfiguration"; +var _SSECA = "SSECustomerAlgorithm"; +var _SSECK = "SSECustomerKey"; +var _SSECKMD = "SSECustomerKeyMD5"; +var _SSEKMS = "SSEKMS"; +var _SSEKMSEC = "SSEKMSEncryptionContext"; +var _SSEKMSKI = "SSEKMSKeyId"; +var _SSER = "ServerSideEncryptionRule"; +var _SSES = "SSES3"; +var _ST = "SessionToken"; +var _STBA = "S3TablesBucketArn"; +var _STD = "S3TablesDestination"; +var _STDR = "S3TablesDestinationResult"; +var _STN = "S3TablesName"; +var _S_ = "S3"; +var _Sc = "Schedule"; +var _Se = "Setting"; +var _Si = "Size"; +var _St = "Start"; +var _Su = "Suffix"; +var _T = "Tagging"; +var _TA = "TopicArn"; +var _TAa = "TableArn"; +var _TB = "TargetBucket"; +var _TBA = "TableBucketArn"; +var _TBT = "TableBucketType"; +var _TC = "TagCount"; +var _TCo = "TopicConfiguration"; +var _TCop = "TopicConfigurations"; +var _TD = "TaggingDirective"; +var _TDMOS = "TransitionDefaultMinimumObjectSize"; +var _TG = "TargetGrants"; +var _TGa = "TargetGrant"; +var _TN = "TableName"; +var _TNa = "TableNamespace"; +var _TOKF = "TargetObjectKeyFormat"; +var _TP = "TargetPrefix"; +var _TPC = "TotalPartsCount"; +var _TS = "TagSet"; +var _TSA = "TableSseAlgorithm"; +var _TSC = "TransitionStorageClass"; +var _TSa = "TableStatus"; +var _Ta = "Tag"; +var _Tag = "Tags"; +var _Ti = "Tier"; +var _Tie = "Tierings"; +var _Tier = "Tiering"; +var _Tim = "Time"; +var _To = "Token"; +var _Top = "Topic"; +var _Tr = "Transitions"; +var _Tra = "Transition"; +var _Ty = "Type"; +var _U = "Upload"; +var _UI = "UploadId"; +var _UIM = "UploadIdMarker"; +var _UM = "UserMetadata"; +var _URI = "URI"; +var _Up = "Uploads"; +var _V = "Version"; +var _VC = "VersionCount"; +var _VCe = "VersioningConfiguration"; +var _VI = "VersionId"; +var _VIM = "VersionIdMarker"; +var _Va = "Value"; +var _Ve = "Versions"; +var _WC = "WebsiteConfiguration"; +var _WOB = "WriteOffsetBytes"; +var _WRL = "WebsiteRedirectLocation"; +var _Y = "Years"; +var _a = "analytics"; +var _ac = "accelerate"; +var _acl = "acl"; +var _ar = "accept-ranges"; +var _at = "attributes"; +var _br = "bucket-region"; +var _c = "cors"; +var _cc = "cache-control"; +var _cd = "content-disposition"; +var _ce = "content-encoding"; +var _cl = "content-language"; +var _cl_ = "content-length"; +var _cm = "content-md5"; +var _cr = "content-range"; +var _ct = "content-type"; +var _ct_ = "continuation-token"; +var _d = "delete"; +var _de = "delimiter"; +var _e = "expires"; +var _en = "encryption"; +var _et = "encoding-type"; +var _eta = "etag"; +var _ex = "expiresstring"; +var _fo = "fetch-owner"; +var _i = "id"; +var _im = "if-match"; +var _ims = "if-modified-since"; +var _in = "inventory"; +var _inm = "if-none-match"; +var _it = "intelligent-tiering"; +var _ius = "if-unmodified-since"; +var _km = "key-marker"; +var _l = "lifecycle"; +var _lh = "legal-hold"; +var _lm = "last-modified"; +var _lo = "location"; +var _log = "logging"; +var _lt = "list-type"; +var _m = "metrics"; +var _mC = "metadataConfiguration"; +var _mIT = "metadataInventoryTable"; +var _mJT = "metadataJournalTable"; +var _mT = "metadataTable"; +var _ma = "marker"; +var _mb = "max-buckets"; +var _mdb = "max-directory-buckets"; +var _me = "member"; +var _mk = "max-keys"; +var _mp = "max-parts"; +var _mu = "max-uploads"; +var _n = "notification"; +var _oC = "ownershipControls"; +var _ol = "object-lock"; +var _p = "policy"; +var _pAB = "publicAccessBlock"; +var _pN = "partNumber"; +var _pS = "policyStatus"; +var _pnm = "part-number-marker"; +var _pr = "prefix"; +var _r = "replication"; +var _rO = "renameObject"; +var _rP = "requestPayment"; +var _ra = "range"; +var _rcc = "response-cache-control"; +var _rcd = "response-content-disposition"; +var _rce = "response-content-encoding"; +var _rcl = "response-content-language"; +var _rct = "response-content-type"; +var _re = "response-expires"; +var _res = "restore"; +var _ret = "retention"; +var _s = "session"; +var _sa = "start-after"; +var _se = "select"; +var _st = "select-type"; +var _t = "tagging"; +var _to = "torrent"; +var _u = "uploads"; +var _uI = "uploadId"; +var _uim = "upload-id-marker"; +var _v = "versioning"; +var _vI = "versionId"; +var _ve = ''; +var _ver = "versions"; +var _vim = "version-id-marker"; +var _w = "website"; +var _x = "xsi:type"; +var _xaa = "x-amz-acl"; +var _xaad = "x-amz-abort-date"; +var _xaapa = "x-amz-access-point-alias"; +var _xaari = "x-amz-abort-rule-id"; +var _xaas = "x-amz-archive-status"; +var _xaba = "x-amz-bucket-arn"; +var _xabgr = "x-amz-bypass-governance-retention"; +var _xabln = "x-amz-bucket-location-name"; +var _xablt = "x-amz-bucket-location-type"; +var _xabole = "x-amz-bucket-object-lock-enabled"; +var _xabolt = "x-amz-bucket-object-lock-token"; +var _xabr = "x-amz-bucket-region"; +var _xaca = "x-amz-checksum-algorithm"; +var _xacc = "x-amz-checksum-crc32"; +var _xacc_ = "x-amz-checksum-crc32c"; +var _xacc__ = "x-amz-checksum-crc64nvme"; +var _xacm = "x-amz-checksum-mode"; +var _xacrsba = "x-amz-confirm-remove-self-bucket-access"; +var _xacs = "x-amz-checksum-sha1"; +var _xacs_ = "x-amz-checksum-sha256"; +var _xacs__ = "x-amz-copy-source"; +var _xacsim = "x-amz-copy-source-if-match"; +var _xacsims = "x-amz-copy-source-if-modified-since"; +var _xacsinm = "x-amz-copy-source-if-none-match"; +var _xacsius = "x-amz-copy-source-if-unmodified-since"; +var _xacsm = "x-amz-create-session-mode"; +var _xacsr = "x-amz-copy-source-range"; +var _xacssseca = "x-amz-copy-source-server-side-encryption-customer-algorithm"; +var _xacssseck = "x-amz-copy-source-server-side-encryption-customer-key"; +var _xacssseckm = "x-amz-copy-source-server-side-encryption-customer-key-md5"; +var _xacsvi = "x-amz-copy-source-version-id"; +var _xact = "x-amz-checksum-type"; +var _xact_ = "x-amz-client-token"; +var _xadm = "x-amz-delete-marker"; +var _xae = "x-amz-expiration"; +var _xaebo = "x-amz-expected-bucket-owner"; +var _xafec = "x-amz-fwd-error-code"; +var _xafem = "x-amz-fwd-error-message"; +var _xafhar = "x-amz-fwd-header-accept-ranges"; +var _xafhcc = "x-amz-fwd-header-cache-control"; +var _xafhcd = "x-amz-fwd-header-content-disposition"; +var _xafhce = "x-amz-fwd-header-content-encoding"; +var _xafhcl = "x-amz-fwd-header-content-language"; +var _xafhcr = "x-amz-fwd-header-content-range"; +var _xafhct = "x-amz-fwd-header-content-type"; +var _xafhe = "x-amz-fwd-header-etag"; +var _xafhe_ = "x-amz-fwd-header-expires"; +var _xafhlm = "x-amz-fwd-header-last-modified"; +var _xafhxacc = "x-amz-fwd-header-x-amz-checksum-crc32"; +var _xafhxacc_ = "x-amz-fwd-header-x-amz-checksum-crc32c"; +var _xafhxacc__ = "x-amz-fwd-header-x-amz-checksum-crc64nvme"; +var _xafhxacs = "x-amz-fwd-header-x-amz-checksum-sha1"; +var _xafhxacs_ = "x-amz-fwd-header-x-amz-checksum-sha256"; +var _xafhxadm = "x-amz-fwd-header-x-amz-delete-marker"; +var _xafhxae = "x-amz-fwd-header-x-amz-expiration"; +var _xafhxamm = "x-amz-fwd-header-x-amz-missing-meta"; +var _xafhxampc = "x-amz-fwd-header-x-amz-mp-parts-count"; +var _xafhxaollh = "x-amz-fwd-header-x-amz-object-lock-legal-hold"; +var _xafhxaolm = "x-amz-fwd-header-x-amz-object-lock-mode"; +var _xafhxaolrud = "x-amz-fwd-header-x-amz-object-lock-retain-until-date"; +var _xafhxar = "x-amz-fwd-header-x-amz-restore"; +var _xafhxarc = "x-amz-fwd-header-x-amz-request-charged"; +var _xafhxars = "x-amz-fwd-header-x-amz-replication-status"; +var _xafhxasc = "x-amz-fwd-header-x-amz-storage-class"; +var _xafhxasse = "x-amz-fwd-header-x-amz-server-side-encryption"; +var _xafhxasseakki = "x-amz-fwd-header-x-amz-server-side-encryption-aws-kms-key-id"; +var _xafhxassebke = "x-amz-fwd-header-x-amz-server-side-encryption-bucket-key-enabled"; +var _xafhxasseca = "x-amz-fwd-header-x-amz-server-side-encryption-customer-algorithm"; +var _xafhxasseckm = "x-amz-fwd-header-x-amz-server-side-encryption-customer-key-md5"; +var _xafhxatc = "x-amz-fwd-header-x-amz-tagging-count"; +var _xafhxavi = "x-amz-fwd-header-x-amz-version-id"; +var _xafs = "x-amz-fwd-status"; +var _xagfc = "x-amz-grant-full-control"; +var _xagr = "x-amz-grant-read"; +var _xagra = "x-amz-grant-read-acp"; +var _xagw = "x-amz-grant-write"; +var _xagwa = "x-amz-grant-write-acp"; +var _xaimit = "x-amz-if-match-initiated-time"; +var _xaimlmt = "x-amz-if-match-last-modified-time"; +var _xaims = "x-amz-if-match-size"; +var _xam = "x-amz-mfa"; +var _xamd = "x-amz-metadata-directive"; +var _xamm = "x-amz-missing-meta"; +var _xamos = "x-amz-mp-object-size"; +var _xamp = "x-amz-max-parts"; +var _xampc = "x-amz-mp-parts-count"; +var _xaoa = "x-amz-object-attributes"; +var _xaollh = "x-amz-object-lock-legal-hold"; +var _xaolm = "x-amz-object-lock-mode"; +var _xaolrud = "x-amz-object-lock-retain-until-date"; +var _xaoo = "x-amz-object-ownership"; +var _xaooa = "x-amz-optional-object-attributes"; +var _xaos = "x-amz-object-size"; +var _xapnm = "x-amz-part-number-marker"; +var _xar = "x-amz-restore"; +var _xarc = "x-amz-request-charged"; +var _xarop = "x-amz-restore-output-path"; +var _xarp = "x-amz-request-payer"; +var _xarr = "x-amz-request-route"; +var _xars = "x-amz-rename-source"; +var _xars_ = "x-amz-replication-status"; +var _xarsim = "x-amz-rename-source-if-match"; +var _xarsims = "x-amz-rename-source-if-modified-since"; +var _xarsinm = "x-amz-rename-source-if-none-match"; +var _xarsius = "x-amz-rename-source-if-unmodified-since"; +var _xart = "x-amz-request-token"; +var _xasc = "x-amz-storage-class"; +var _xasca = "x-amz-sdk-checksum-algorithm"; +var _xasdv = "x-amz-skip-destination-validation"; +var _xasebo = "x-amz-source-expected-bucket-owner"; +var _xasse = "x-amz-server-side-encryption"; +var _xasseakki = "x-amz-server-side-encryption-aws-kms-key-id"; +var _xassebke = "x-amz-server-side-encryption-bucket-key-enabled"; +var _xassec = "x-amz-server-side-encryption-context"; +var _xasseca = "x-amz-server-side-encryption-customer-algorithm"; +var _xasseck = "x-amz-server-side-encryption-customer-key"; +var _xasseckm = "x-amz-server-side-encryption-customer-key-md5"; +var _xat = "x-amz-tagging"; +var _xatc = "x-amz-tagging-count"; +var _xatd = "x-amz-tagging-directive"; +var _xatdmos = "x-amz-transition-default-minimum-object-size"; +var _xavi = "x-amz-version-id"; +var _xawob = "x-amz-write-offset-bytes"; +var _xawrl = "x-amz-website-redirect-location"; +var _xi = "x-id"; + +// src/commands/CreateSessionCommand.ts +var CreateSessionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s3.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "CreateSession", {}).n("S3Client", "CreateSessionCommand").f(CreateSessionRequestFilterSensitiveLog, CreateSessionOutputFilterSensitiveLog).ser(se_CreateSessionCommand).de(de_CreateSessionCommand).build() { + static { + __name(this, "CreateSessionCommand"); + } +}; + +// src/S3Client.ts +var import_runtimeConfig = __nccwpck_require__(35745); + +// src/runtimeExtensions.ts +var import_region_config_resolver = __nccwpck_require__(36463); + + + +// src/auth/httpAuthExtensionConfiguration.ts +var getHttpAuthExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + } + }; +}, "getHttpAuthExtensionConfiguration"); +var resolveHttpAuthRuntimeConfig = /* @__PURE__ */ __name((config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials() + }; +}, "resolveHttpAuthRuntimeConfig"); + +// src/runtimeExtensions.ts +var resolveRuntimeExtensions = /* @__PURE__ */ __name((runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign( + (0, import_region_config_resolver.getAwsRegionExtensionConfiguration)(runtimeConfig), + (0, import_smithy_client.getDefaultExtensionConfiguration)(runtimeConfig), + (0, import_protocol_http.getHttpHandlerExtensionConfiguration)(runtimeConfig), + getHttpAuthExtensionConfiguration(runtimeConfig) + ); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign( + runtimeConfig, + (0, import_region_config_resolver.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), + (0, import_smithy_client.resolveDefaultRuntimeConfig)(extensionConfiguration), + (0, import_protocol_http.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), + resolveHttpAuthRuntimeConfig(extensionConfiguration) + ); +}, "resolveRuntimeExtensions"); + +// src/S3Client.ts +var S3Client = class extends import_smithy_client.Client { + static { + __name(this, "S3Client"); + } + /** + * The resolved configuration of S3Client class. This is resolved and normalized from the {@link S3ClientConfig | constructor configuration interface}. + */ + config; + constructor(...[configuration]) { + const _config_0 = (0, import_runtimeConfig.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = resolveClientEndpointParameters(_config_0); + const _config_2 = (0, import_middleware_user_agent.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, import_middleware_flexible_checksums.resolveFlexibleChecksumsConfig)(_config_2); + const _config_4 = (0, import_middleware_retry.resolveRetryConfig)(_config_3); + const _config_5 = (0, import_config_resolver.resolveRegionConfig)(_config_4); + const _config_6 = (0, import_middleware_host_header.resolveHostHeaderConfig)(_config_5); + const _config_7 = (0, import_middleware_endpoint.resolveEndpointConfig)(_config_6); + const _config_8 = (0, import_eventstream_serde_config_resolver.resolveEventStreamSerdeConfig)(_config_7); + const _config_9 = (0, import_httpAuthSchemeProvider.resolveHttpAuthSchemeConfig)(_config_8); + const _config_10 = (0, import_middleware_sdk_s32.resolveS3Config)(_config_9, { session: [() => this, CreateSessionCommand] }); + const _config_11 = resolveRuntimeExtensions(_config_10, configuration?.extensions || []); + this.config = _config_11; + this.middlewareStack.use((0, import_middleware_user_agent.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_retry.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_content_length.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_host_header.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_logger.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_recursion_detection.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use( + (0, import_core3.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: import_httpAuthSchemeProvider.defaultS3HttpAuthSchemeParametersProvider, + identityProviderConfigProvider: /* @__PURE__ */ __name(async (config) => new import_core3.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials, + "aws.auth#sigv4a": config.credentials + }), "identityProviderConfigProvider") + }) + ); + this.middlewareStack.use((0, import_core3.getHttpSigningPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getValidateBucketNamePlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_expect_continue.getAddExpectContinuePlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getRegionRedirectMiddlewarePlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getS3ExpressPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getS3ExpressHttpSigningPlugin)(this.config)); + } + /** + * Destroy underlying resources, like sockets. It's usually not necessary to do this. + * However in Node.js, it's best to explicitly shut down the client's agent when it is no longer needed. + * Otherwise, sockets might stay open for quite a long time before the server terminates them. + */ + destroy() { + super.destroy(); + } +}; + +// src/S3.ts + + +// src/commands/AbortMultipartUploadCommand.ts +var import_middleware_sdk_s33 = __nccwpck_require__(77445); + + + +var AbortMultipartUploadCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s33.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "AbortMultipartUpload", {}).n("S3Client", "AbortMultipartUploadCommand").f(void 0, void 0).ser(se_AbortMultipartUploadCommand).de(de_AbortMultipartUploadCommand).build() { + static { + __name(this, "AbortMultipartUploadCommand"); + } +}; + +// src/commands/CompleteMultipartUploadCommand.ts +var import_middleware_sdk_s34 = __nccwpck_require__(77445); +var import_middleware_ssec = __nccwpck_require__(35568); + + + +var CompleteMultipartUploadCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s34.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "CompleteMultipartUpload", {}).n("S3Client", "CompleteMultipartUploadCommand").f(CompleteMultipartUploadRequestFilterSensitiveLog, CompleteMultipartUploadOutputFilterSensitiveLog).ser(se_CompleteMultipartUploadCommand).de(de_CompleteMultipartUploadCommand).build() { + static { + __name(this, "CompleteMultipartUploadCommand"); + } +}; + +// src/commands/CopyObjectCommand.ts +var import_middleware_sdk_s35 = __nccwpck_require__(77445); + + + + +var CopyObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" }, + CopySource: { type: "contextParams", name: "CopySource" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s35.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "CopyObject", {}).n("S3Client", "CopyObjectCommand").f(CopyObjectRequestFilterSensitiveLog, CopyObjectOutputFilterSensitiveLog).ser(se_CopyObjectCommand).de(de_CopyObjectCommand).build() { + static { + __name(this, "CopyObjectCommand"); + } +}; + +// src/commands/CreateBucketCommand.ts +var import_middleware_location_constraint = __nccwpck_require__(23209); +var import_middleware_sdk_s36 = __nccwpck_require__(77445); + + + +var CreateBucketCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + DisableAccessPoints: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s36.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_location_constraint.getLocationConstraintPlugin)(config) + ]; +}).s("AmazonS3", "CreateBucket", {}).n("S3Client", "CreateBucketCommand").f(void 0, void 0).ser(se_CreateBucketCommand).de(de_CreateBucketCommand).build() { + static { + __name(this, "CreateBucketCommand"); + } +}; + +// src/commands/CreateBucketMetadataConfigurationCommand.ts + + + + +var CreateBucketMetadataConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "CreateBucketMetadataConfiguration", {}).n("S3Client", "CreateBucketMetadataConfigurationCommand").f(void 0, void 0).ser(se_CreateBucketMetadataConfigurationCommand).de(de_CreateBucketMetadataConfigurationCommand).build() { + static { + __name(this, "CreateBucketMetadataConfigurationCommand"); + } +}; + +// src/commands/CreateBucketMetadataTableConfigurationCommand.ts + + + + +var CreateBucketMetadataTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "CreateBucketMetadataTableConfiguration", {}).n("S3Client", "CreateBucketMetadataTableConfigurationCommand").f(void 0, void 0).ser(se_CreateBucketMetadataTableConfigurationCommand).de(de_CreateBucketMetadataTableConfigurationCommand).build() { + static { + __name(this, "CreateBucketMetadataTableConfigurationCommand"); + } +}; + +// src/commands/CreateMultipartUploadCommand.ts +var import_middleware_sdk_s37 = __nccwpck_require__(77445); + + + + +var CreateMultipartUploadCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s37.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "CreateMultipartUpload", {}).n("S3Client", "CreateMultipartUploadCommand").f(CreateMultipartUploadRequestFilterSensitiveLog, CreateMultipartUploadOutputFilterSensitiveLog).ser(se_CreateMultipartUploadCommand).de(de_CreateMultipartUploadCommand).build() { + static { + __name(this, "CreateMultipartUploadCommand"); + } +}; + +// src/commands/DeleteBucketAnalyticsConfigurationCommand.ts + + + +var DeleteBucketAnalyticsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketAnalyticsConfiguration", {}).n("S3Client", "DeleteBucketAnalyticsConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketAnalyticsConfigurationCommand).de(de_DeleteBucketAnalyticsConfigurationCommand).build() { + static { + __name(this, "DeleteBucketAnalyticsConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketCommand.ts + + + +var DeleteBucketCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucket", {}).n("S3Client", "DeleteBucketCommand").f(void 0, void 0).ser(se_DeleteBucketCommand).de(de_DeleteBucketCommand).build() { + static { + __name(this, "DeleteBucketCommand"); + } +}; + +// src/commands/DeleteBucketCorsCommand.ts + + + +var DeleteBucketCorsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketCors", {}).n("S3Client", "DeleteBucketCorsCommand").f(void 0, void 0).ser(se_DeleteBucketCorsCommand).de(de_DeleteBucketCorsCommand).build() { + static { + __name(this, "DeleteBucketCorsCommand"); + } +}; + +// src/commands/DeleteBucketEncryptionCommand.ts + + + +var DeleteBucketEncryptionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketEncryption", {}).n("S3Client", "DeleteBucketEncryptionCommand").f(void 0, void 0).ser(se_DeleteBucketEncryptionCommand).de(de_DeleteBucketEncryptionCommand).build() { + static { + __name(this, "DeleteBucketEncryptionCommand"); + } +}; + +// src/commands/DeleteBucketIntelligentTieringConfigurationCommand.ts + + + +var DeleteBucketIntelligentTieringConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketIntelligentTieringConfiguration", {}).n("S3Client", "DeleteBucketIntelligentTieringConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketIntelligentTieringConfigurationCommand).de(de_DeleteBucketIntelligentTieringConfigurationCommand).build() { + static { + __name(this, "DeleteBucketIntelligentTieringConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketInventoryConfigurationCommand.ts + + + +var DeleteBucketInventoryConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketInventoryConfiguration", {}).n("S3Client", "DeleteBucketInventoryConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketInventoryConfigurationCommand).de(de_DeleteBucketInventoryConfigurationCommand).build() { + static { + __name(this, "DeleteBucketInventoryConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketLifecycleCommand.ts + + + +var DeleteBucketLifecycleCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketLifecycle", {}).n("S3Client", "DeleteBucketLifecycleCommand").f(void 0, void 0).ser(se_DeleteBucketLifecycleCommand).de(de_DeleteBucketLifecycleCommand).build() { + static { + __name(this, "DeleteBucketLifecycleCommand"); + } +}; + +// src/commands/DeleteBucketMetadataConfigurationCommand.ts + + + +var DeleteBucketMetadataConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketMetadataConfiguration", {}).n("S3Client", "DeleteBucketMetadataConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketMetadataConfigurationCommand).de(de_DeleteBucketMetadataConfigurationCommand).build() { + static { + __name(this, "DeleteBucketMetadataConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketMetadataTableConfigurationCommand.ts + + + +var DeleteBucketMetadataTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketMetadataTableConfiguration", {}).n("S3Client", "DeleteBucketMetadataTableConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketMetadataTableConfigurationCommand).de(de_DeleteBucketMetadataTableConfigurationCommand).build() { + static { + __name(this, "DeleteBucketMetadataTableConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketMetricsConfigurationCommand.ts + + + +var DeleteBucketMetricsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketMetricsConfiguration", {}).n("S3Client", "DeleteBucketMetricsConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketMetricsConfigurationCommand).de(de_DeleteBucketMetricsConfigurationCommand).build() { + static { + __name(this, "DeleteBucketMetricsConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketOwnershipControlsCommand.ts + + + +var DeleteBucketOwnershipControlsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketOwnershipControls", {}).n("S3Client", "DeleteBucketOwnershipControlsCommand").f(void 0, void 0).ser(se_DeleteBucketOwnershipControlsCommand).de(de_DeleteBucketOwnershipControlsCommand).build() { + static { + __name(this, "DeleteBucketOwnershipControlsCommand"); + } +}; + +// src/commands/DeleteBucketPolicyCommand.ts + + + +var DeleteBucketPolicyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketPolicy", {}).n("S3Client", "DeleteBucketPolicyCommand").f(void 0, void 0).ser(se_DeleteBucketPolicyCommand).de(de_DeleteBucketPolicyCommand).build() { + static { + __name(this, "DeleteBucketPolicyCommand"); + } +}; + +// src/commands/DeleteBucketReplicationCommand.ts + + + +var DeleteBucketReplicationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketReplication", {}).n("S3Client", "DeleteBucketReplicationCommand").f(void 0, void 0).ser(se_DeleteBucketReplicationCommand).de(de_DeleteBucketReplicationCommand).build() { + static { + __name(this, "DeleteBucketReplicationCommand"); + } +}; + +// src/commands/DeleteBucketTaggingCommand.ts + + + +var DeleteBucketTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketTagging", {}).n("S3Client", "DeleteBucketTaggingCommand").f(void 0, void 0).ser(se_DeleteBucketTaggingCommand).de(de_DeleteBucketTaggingCommand).build() { + static { + __name(this, "DeleteBucketTaggingCommand"); + } +}; + +// src/commands/DeleteBucketWebsiteCommand.ts + + + +var DeleteBucketWebsiteCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketWebsite", {}).n("S3Client", "DeleteBucketWebsiteCommand").f(void 0, void 0).ser(se_DeleteBucketWebsiteCommand).de(de_DeleteBucketWebsiteCommand).build() { + static { + __name(this, "DeleteBucketWebsiteCommand"); + } +}; + +// src/commands/DeleteObjectCommand.ts +var import_middleware_sdk_s38 = __nccwpck_require__(77445); + + + +var DeleteObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s38.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "DeleteObject", {}).n("S3Client", "DeleteObjectCommand").f(void 0, void 0).ser(se_DeleteObjectCommand).de(de_DeleteObjectCommand).build() { + static { + __name(this, "DeleteObjectCommand"); + } +}; + +// src/commands/DeleteObjectsCommand.ts + +var import_middleware_sdk_s39 = __nccwpck_require__(77445); + + + +var DeleteObjectsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s39.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "DeleteObjects", {}).n("S3Client", "DeleteObjectsCommand").f(void 0, void 0).ser(se_DeleteObjectsCommand).de(de_DeleteObjectsCommand).build() { + static { + __name(this, "DeleteObjectsCommand"); + } +}; + +// src/commands/DeleteObjectTaggingCommand.ts +var import_middleware_sdk_s310 = __nccwpck_require__(77445); + + + +var DeleteObjectTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s310.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "DeleteObjectTagging", {}).n("S3Client", "DeleteObjectTaggingCommand").f(void 0, void 0).ser(se_DeleteObjectTaggingCommand).de(de_DeleteObjectTaggingCommand).build() { + static { + __name(this, "DeleteObjectTaggingCommand"); + } +}; + +// src/commands/DeletePublicAccessBlockCommand.ts + + + +var DeletePublicAccessBlockCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeletePublicAccessBlock", {}).n("S3Client", "DeletePublicAccessBlockCommand").f(void 0, void 0).ser(se_DeletePublicAccessBlockCommand).de(de_DeletePublicAccessBlockCommand).build() { + static { + __name(this, "DeletePublicAccessBlockCommand"); + } +}; + +// src/commands/GetBucketAccelerateConfigurationCommand.ts +var import_middleware_sdk_s311 = __nccwpck_require__(77445); + + + +var GetBucketAccelerateConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s311.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketAccelerateConfiguration", {}).n("S3Client", "GetBucketAccelerateConfigurationCommand").f(void 0, void 0).ser(se_GetBucketAccelerateConfigurationCommand).de(de_GetBucketAccelerateConfigurationCommand).build() { + static { + __name(this, "GetBucketAccelerateConfigurationCommand"); + } +}; + +// src/commands/GetBucketAclCommand.ts +var import_middleware_sdk_s312 = __nccwpck_require__(77445); + + + +var GetBucketAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s312.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketAcl", {}).n("S3Client", "GetBucketAclCommand").f(void 0, void 0).ser(se_GetBucketAclCommand).de(de_GetBucketAclCommand).build() { + static { + __name(this, "GetBucketAclCommand"); + } +}; + +// src/commands/GetBucketAnalyticsConfigurationCommand.ts +var import_middleware_sdk_s313 = __nccwpck_require__(77445); + + + +var GetBucketAnalyticsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s313.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketAnalyticsConfiguration", {}).n("S3Client", "GetBucketAnalyticsConfigurationCommand").f(void 0, void 0).ser(se_GetBucketAnalyticsConfigurationCommand).de(de_GetBucketAnalyticsConfigurationCommand).build() { + static { + __name(this, "GetBucketAnalyticsConfigurationCommand"); + } +}; + +// src/commands/GetBucketCorsCommand.ts +var import_middleware_sdk_s314 = __nccwpck_require__(77445); + + + +var GetBucketCorsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s314.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketCors", {}).n("S3Client", "GetBucketCorsCommand").f(void 0, void 0).ser(se_GetBucketCorsCommand).de(de_GetBucketCorsCommand).build() { + static { + __name(this, "GetBucketCorsCommand"); + } +}; + +// src/commands/GetBucketEncryptionCommand.ts +var import_middleware_sdk_s315 = __nccwpck_require__(77445); + + + +var GetBucketEncryptionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s315.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketEncryption", {}).n("S3Client", "GetBucketEncryptionCommand").f(void 0, GetBucketEncryptionOutputFilterSensitiveLog).ser(se_GetBucketEncryptionCommand).de(de_GetBucketEncryptionCommand).build() { + static { + __name(this, "GetBucketEncryptionCommand"); + } +}; + +// src/commands/GetBucketIntelligentTieringConfigurationCommand.ts +var import_middleware_sdk_s316 = __nccwpck_require__(77445); + + + +var GetBucketIntelligentTieringConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s316.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketIntelligentTieringConfiguration", {}).n("S3Client", "GetBucketIntelligentTieringConfigurationCommand").f(void 0, void 0).ser(se_GetBucketIntelligentTieringConfigurationCommand).de(de_GetBucketIntelligentTieringConfigurationCommand).build() { + static { + __name(this, "GetBucketIntelligentTieringConfigurationCommand"); + } +}; + +// src/commands/GetBucketInventoryConfigurationCommand.ts +var import_middleware_sdk_s317 = __nccwpck_require__(77445); + + + +var GetBucketInventoryConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s317.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketInventoryConfiguration", {}).n("S3Client", "GetBucketInventoryConfigurationCommand").f(void 0, GetBucketInventoryConfigurationOutputFilterSensitiveLog).ser(se_GetBucketInventoryConfigurationCommand).de(de_GetBucketInventoryConfigurationCommand).build() { + static { + __name(this, "GetBucketInventoryConfigurationCommand"); + } +}; + +// src/commands/GetBucketLifecycleConfigurationCommand.ts +var import_middleware_sdk_s318 = __nccwpck_require__(77445); + + + +var GetBucketLifecycleConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s318.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketLifecycleConfiguration", {}).n("S3Client", "GetBucketLifecycleConfigurationCommand").f(void 0, void 0).ser(se_GetBucketLifecycleConfigurationCommand).de(de_GetBucketLifecycleConfigurationCommand).build() { + static { + __name(this, "GetBucketLifecycleConfigurationCommand"); + } +}; + +// src/commands/GetBucketLocationCommand.ts +var import_middleware_sdk_s319 = __nccwpck_require__(77445); + + + +var GetBucketLocationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s319.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketLocation", {}).n("S3Client", "GetBucketLocationCommand").f(void 0, void 0).ser(se_GetBucketLocationCommand).de(de_GetBucketLocationCommand).build() { + static { + __name(this, "GetBucketLocationCommand"); + } +}; + +// src/commands/GetBucketLoggingCommand.ts +var import_middleware_sdk_s320 = __nccwpck_require__(77445); + + + +var GetBucketLoggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s320.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketLogging", {}).n("S3Client", "GetBucketLoggingCommand").f(void 0, void 0).ser(se_GetBucketLoggingCommand).de(de_GetBucketLoggingCommand).build() { + static { + __name(this, "GetBucketLoggingCommand"); + } +}; + +// src/commands/GetBucketMetadataConfigurationCommand.ts +var import_middleware_sdk_s321 = __nccwpck_require__(77445); + + + +var GetBucketMetadataConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s321.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketMetadataConfiguration", {}).n("S3Client", "GetBucketMetadataConfigurationCommand").f(void 0, void 0).ser(se_GetBucketMetadataConfigurationCommand).de(de_GetBucketMetadataConfigurationCommand).build() { + static { + __name(this, "GetBucketMetadataConfigurationCommand"); + } +}; + +// src/commands/GetBucketMetadataTableConfigurationCommand.ts +var import_middleware_sdk_s322 = __nccwpck_require__(77445); + + + +var GetBucketMetadataTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s322.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketMetadataTableConfiguration", {}).n("S3Client", "GetBucketMetadataTableConfigurationCommand").f(void 0, void 0).ser(se_GetBucketMetadataTableConfigurationCommand).de(de_GetBucketMetadataTableConfigurationCommand).build() { + static { + __name(this, "GetBucketMetadataTableConfigurationCommand"); + } +}; + +// src/commands/GetBucketMetricsConfigurationCommand.ts +var import_middleware_sdk_s323 = __nccwpck_require__(77445); + + + +var GetBucketMetricsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s323.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketMetricsConfiguration", {}).n("S3Client", "GetBucketMetricsConfigurationCommand").f(void 0, void 0).ser(se_GetBucketMetricsConfigurationCommand).de(de_GetBucketMetricsConfigurationCommand).build() { + static { + __name(this, "GetBucketMetricsConfigurationCommand"); + } +}; + +// src/commands/GetBucketNotificationConfigurationCommand.ts +var import_middleware_sdk_s324 = __nccwpck_require__(77445); + + + +var GetBucketNotificationConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s324.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketNotificationConfiguration", {}).n("S3Client", "GetBucketNotificationConfigurationCommand").f(void 0, void 0).ser(se_GetBucketNotificationConfigurationCommand).de(de_GetBucketNotificationConfigurationCommand).build() { + static { + __name(this, "GetBucketNotificationConfigurationCommand"); + } +}; + +// src/commands/GetBucketOwnershipControlsCommand.ts +var import_middleware_sdk_s325 = __nccwpck_require__(77445); + + + +var GetBucketOwnershipControlsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s325.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketOwnershipControls", {}).n("S3Client", "GetBucketOwnershipControlsCommand").f(void 0, void 0).ser(se_GetBucketOwnershipControlsCommand).de(de_GetBucketOwnershipControlsCommand).build() { + static { + __name(this, "GetBucketOwnershipControlsCommand"); + } +}; + +// src/commands/GetBucketPolicyCommand.ts +var import_middleware_sdk_s326 = __nccwpck_require__(77445); + + + +var GetBucketPolicyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s326.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketPolicy", {}).n("S3Client", "GetBucketPolicyCommand").f(void 0, void 0).ser(se_GetBucketPolicyCommand).de(de_GetBucketPolicyCommand).build() { + static { + __name(this, "GetBucketPolicyCommand"); + } +}; + +// src/commands/GetBucketPolicyStatusCommand.ts +var import_middleware_sdk_s327 = __nccwpck_require__(77445); + + + +var GetBucketPolicyStatusCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s327.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketPolicyStatus", {}).n("S3Client", "GetBucketPolicyStatusCommand").f(void 0, void 0).ser(se_GetBucketPolicyStatusCommand).de(de_GetBucketPolicyStatusCommand).build() { + static { + __name(this, "GetBucketPolicyStatusCommand"); + } +}; + +// src/commands/GetBucketReplicationCommand.ts +var import_middleware_sdk_s328 = __nccwpck_require__(77445); + + + +var GetBucketReplicationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s328.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketReplication", {}).n("S3Client", "GetBucketReplicationCommand").f(void 0, void 0).ser(se_GetBucketReplicationCommand).de(de_GetBucketReplicationCommand).build() { + static { + __name(this, "GetBucketReplicationCommand"); + } +}; + +// src/commands/GetBucketRequestPaymentCommand.ts +var import_middleware_sdk_s329 = __nccwpck_require__(77445); + + + +var GetBucketRequestPaymentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s329.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketRequestPayment", {}).n("S3Client", "GetBucketRequestPaymentCommand").f(void 0, void 0).ser(se_GetBucketRequestPaymentCommand).de(de_GetBucketRequestPaymentCommand).build() { + static { + __name(this, "GetBucketRequestPaymentCommand"); + } +}; + +// src/commands/GetBucketTaggingCommand.ts +var import_middleware_sdk_s330 = __nccwpck_require__(77445); + + + +var GetBucketTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s330.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketTagging", {}).n("S3Client", "GetBucketTaggingCommand").f(void 0, void 0).ser(se_GetBucketTaggingCommand).de(de_GetBucketTaggingCommand).build() { + static { + __name(this, "GetBucketTaggingCommand"); + } +}; + +// src/commands/GetBucketVersioningCommand.ts +var import_middleware_sdk_s331 = __nccwpck_require__(77445); + + + +var GetBucketVersioningCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s331.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketVersioning", {}).n("S3Client", "GetBucketVersioningCommand").f(void 0, void 0).ser(se_GetBucketVersioningCommand).de(de_GetBucketVersioningCommand).build() { + static { + __name(this, "GetBucketVersioningCommand"); + } +}; + +// src/commands/GetBucketWebsiteCommand.ts +var import_middleware_sdk_s332 = __nccwpck_require__(77445); + + + +var GetBucketWebsiteCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s332.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketWebsite", {}).n("S3Client", "GetBucketWebsiteCommand").f(void 0, void 0).ser(se_GetBucketWebsiteCommand).de(de_GetBucketWebsiteCommand).build() { + static { + __name(this, "GetBucketWebsiteCommand"); + } +}; + +// src/commands/GetObjectAclCommand.ts +var import_middleware_sdk_s333 = __nccwpck_require__(77445); + + + +var GetObjectAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s333.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectAcl", {}).n("S3Client", "GetObjectAclCommand").f(void 0, void 0).ser(se_GetObjectAclCommand).de(de_GetObjectAclCommand).build() { + static { + __name(this, "GetObjectAclCommand"); + } +}; + +// src/commands/GetObjectAttributesCommand.ts +var import_middleware_sdk_s334 = __nccwpck_require__(77445); + + + + +var GetObjectAttributesCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s334.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectAttributes", {}).n("S3Client", "GetObjectAttributesCommand").f(GetObjectAttributesRequestFilterSensitiveLog, void 0).ser(se_GetObjectAttributesCommand).de(de_GetObjectAttributesCommand).build() { + static { + __name(this, "GetObjectAttributesCommand"); + } +}; + +// src/commands/GetObjectCommand.ts + +var import_middleware_sdk_s335 = __nccwpck_require__(77445); + + + + +var GetObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestChecksumRequired: false, + requestValidationModeMember: "ChecksumMode", + responseAlgorithms: ["CRC64NVME", "CRC32", "CRC32C", "SHA256", "SHA1"] + }), + (0, import_middleware_ssec.getSsecPlugin)(config), + (0, import_middleware_sdk_s335.getS3ExpiresMiddlewarePlugin)(config) + ]; +}).s("AmazonS3", "GetObject", {}).n("S3Client", "GetObjectCommand").f(GetObjectRequestFilterSensitiveLog, GetObjectOutputFilterSensitiveLog).ser(se_GetObjectCommand).de(de_GetObjectCommand).build() { + static { + __name(this, "GetObjectCommand"); + } +}; + +// src/commands/GetObjectLegalHoldCommand.ts +var import_middleware_sdk_s336 = __nccwpck_require__(77445); + + + +var GetObjectLegalHoldCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s336.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectLegalHold", {}).n("S3Client", "GetObjectLegalHoldCommand").f(void 0, void 0).ser(se_GetObjectLegalHoldCommand).de(de_GetObjectLegalHoldCommand).build() { + static { + __name(this, "GetObjectLegalHoldCommand"); + } +}; + +// src/commands/GetObjectLockConfigurationCommand.ts +var import_middleware_sdk_s337 = __nccwpck_require__(77445); + + + +var GetObjectLockConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s337.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectLockConfiguration", {}).n("S3Client", "GetObjectLockConfigurationCommand").f(void 0, void 0).ser(se_GetObjectLockConfigurationCommand).de(de_GetObjectLockConfigurationCommand).build() { + static { + __name(this, "GetObjectLockConfigurationCommand"); + } +}; + +// src/commands/GetObjectRetentionCommand.ts +var import_middleware_sdk_s338 = __nccwpck_require__(77445); + + + +var GetObjectRetentionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s338.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectRetention", {}).n("S3Client", "GetObjectRetentionCommand").f(void 0, void 0).ser(se_GetObjectRetentionCommand).de(de_GetObjectRetentionCommand).build() { + static { + __name(this, "GetObjectRetentionCommand"); + } +}; + +// src/commands/GetObjectTaggingCommand.ts +var import_middleware_sdk_s339 = __nccwpck_require__(77445); + + + +var GetObjectTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s339.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectTagging", {}).n("S3Client", "GetObjectTaggingCommand").f(void 0, void 0).ser(se_GetObjectTaggingCommand).de(de_GetObjectTaggingCommand).build() { + static { + __name(this, "GetObjectTaggingCommand"); + } +}; + +// src/commands/GetObjectTorrentCommand.ts + + + +var GetObjectTorrentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "GetObjectTorrent", {}).n("S3Client", "GetObjectTorrentCommand").f(void 0, GetObjectTorrentOutputFilterSensitiveLog).ser(se_GetObjectTorrentCommand).de(de_GetObjectTorrentCommand).build() { + static { + __name(this, "GetObjectTorrentCommand"); + } +}; + +// src/commands/GetPublicAccessBlockCommand.ts +var import_middleware_sdk_s340 = __nccwpck_require__(77445); + + + +var GetPublicAccessBlockCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s340.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetPublicAccessBlock", {}).n("S3Client", "GetPublicAccessBlockCommand").f(void 0, void 0).ser(se_GetPublicAccessBlockCommand).de(de_GetPublicAccessBlockCommand).build() { + static { + __name(this, "GetPublicAccessBlockCommand"); + } +}; + +// src/commands/HeadBucketCommand.ts +var import_middleware_sdk_s341 = __nccwpck_require__(77445); + + + +var HeadBucketCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s341.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "HeadBucket", {}).n("S3Client", "HeadBucketCommand").f(void 0, void 0).ser(se_HeadBucketCommand).de(de_HeadBucketCommand).build() { + static { + __name(this, "HeadBucketCommand"); + } +}; + +// src/commands/HeadObjectCommand.ts +var import_middleware_sdk_s342 = __nccwpck_require__(77445); + + + + +var HeadObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s342.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config), + (0, import_middleware_sdk_s342.getS3ExpiresMiddlewarePlugin)(config) + ]; +}).s("AmazonS3", "HeadObject", {}).n("S3Client", "HeadObjectCommand").f(HeadObjectRequestFilterSensitiveLog, HeadObjectOutputFilterSensitiveLog).ser(se_HeadObjectCommand).de(de_HeadObjectCommand).build() { + static { + __name(this, "HeadObjectCommand"); + } +}; + +// src/commands/ListBucketAnalyticsConfigurationsCommand.ts +var import_middleware_sdk_s343 = __nccwpck_require__(77445); + + + +var ListBucketAnalyticsConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s343.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketAnalyticsConfigurations", {}).n("S3Client", "ListBucketAnalyticsConfigurationsCommand").f(void 0, void 0).ser(se_ListBucketAnalyticsConfigurationsCommand).de(de_ListBucketAnalyticsConfigurationsCommand).build() { + static { + __name(this, "ListBucketAnalyticsConfigurationsCommand"); + } +}; + +// src/commands/ListBucketIntelligentTieringConfigurationsCommand.ts +var import_middleware_sdk_s344 = __nccwpck_require__(77445); + + + +var ListBucketIntelligentTieringConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s344.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketIntelligentTieringConfigurations", {}).n("S3Client", "ListBucketIntelligentTieringConfigurationsCommand").f(void 0, void 0).ser(se_ListBucketIntelligentTieringConfigurationsCommand).de(de_ListBucketIntelligentTieringConfigurationsCommand).build() { + static { + __name(this, "ListBucketIntelligentTieringConfigurationsCommand"); + } +}; + +// src/commands/ListBucketInventoryConfigurationsCommand.ts +var import_middleware_sdk_s345 = __nccwpck_require__(77445); + + + +var ListBucketInventoryConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s345.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketInventoryConfigurations", {}).n("S3Client", "ListBucketInventoryConfigurationsCommand").f(void 0, ListBucketInventoryConfigurationsOutputFilterSensitiveLog).ser(se_ListBucketInventoryConfigurationsCommand).de(de_ListBucketInventoryConfigurationsCommand).build() { + static { + __name(this, "ListBucketInventoryConfigurationsCommand"); + } +}; + +// src/commands/ListBucketMetricsConfigurationsCommand.ts +var import_middleware_sdk_s346 = __nccwpck_require__(77445); + + + +var ListBucketMetricsConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s346.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketMetricsConfigurations", {}).n("S3Client", "ListBucketMetricsConfigurationsCommand").f(void 0, void 0).ser(se_ListBucketMetricsConfigurationsCommand).de(de_ListBucketMetricsConfigurationsCommand).build() { + static { + __name(this, "ListBucketMetricsConfigurationsCommand"); + } +}; + +// src/commands/ListBucketsCommand.ts +var import_middleware_sdk_s347 = __nccwpck_require__(77445); + + + +var ListBucketsCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s347.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBuckets", {}).n("S3Client", "ListBucketsCommand").f(void 0, void 0).ser(se_ListBucketsCommand).de(de_ListBucketsCommand).build() { + static { + __name(this, "ListBucketsCommand"); + } +}; + +// src/commands/ListDirectoryBucketsCommand.ts +var import_middleware_sdk_s348 = __nccwpck_require__(77445); + + + +var ListDirectoryBucketsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s348.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListDirectoryBuckets", {}).n("S3Client", "ListDirectoryBucketsCommand").f(void 0, void 0).ser(se_ListDirectoryBucketsCommand).de(de_ListDirectoryBucketsCommand).build() { + static { + __name(this, "ListDirectoryBucketsCommand"); + } +}; + +// src/commands/ListMultipartUploadsCommand.ts +var import_middleware_sdk_s349 = __nccwpck_require__(77445); + + + +var ListMultipartUploadsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s349.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListMultipartUploads", {}).n("S3Client", "ListMultipartUploadsCommand").f(void 0, void 0).ser(se_ListMultipartUploadsCommand).de(de_ListMultipartUploadsCommand).build() { + static { + __name(this, "ListMultipartUploadsCommand"); + } +}; + +// src/commands/ListObjectsCommand.ts +var import_middleware_sdk_s350 = __nccwpck_require__(77445); + + + +var ListObjectsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s350.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListObjects", {}).n("S3Client", "ListObjectsCommand").f(void 0, void 0).ser(se_ListObjectsCommand).de(de_ListObjectsCommand).build() { + static { + __name(this, "ListObjectsCommand"); + } +}; + +// src/commands/ListObjectsV2Command.ts +var import_middleware_sdk_s351 = __nccwpck_require__(77445); + + + +var ListObjectsV2Command = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s351.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListObjectsV2", {}).n("S3Client", "ListObjectsV2Command").f(void 0, void 0).ser(se_ListObjectsV2Command).de(de_ListObjectsV2Command).build() { + static { + __name(this, "ListObjectsV2Command"); + } +}; + +// src/commands/ListObjectVersionsCommand.ts +var import_middleware_sdk_s352 = __nccwpck_require__(77445); + + + +var ListObjectVersionsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s352.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListObjectVersions", {}).n("S3Client", "ListObjectVersionsCommand").f(void 0, void 0).ser(se_ListObjectVersionsCommand).de(de_ListObjectVersionsCommand).build() { + static { + __name(this, "ListObjectVersionsCommand"); + } +}; + +// src/commands/ListPartsCommand.ts +var import_middleware_sdk_s353 = __nccwpck_require__(77445); + + + + +var ListPartsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s353.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "ListParts", {}).n("S3Client", "ListPartsCommand").f(ListPartsRequestFilterSensitiveLog, void 0).ser(se_ListPartsCommand).de(de_ListPartsCommand).build() { + static { + __name(this, "ListPartsCommand"); + } +}; + +// src/commands/PutBucketAccelerateConfigurationCommand.ts + + + + +var PutBucketAccelerateConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }) + ]; +}).s("AmazonS3", "PutBucketAccelerateConfiguration", {}).n("S3Client", "PutBucketAccelerateConfigurationCommand").f(void 0, void 0).ser(se_PutBucketAccelerateConfigurationCommand).de(de_PutBucketAccelerateConfigurationCommand).build() { + static { + __name(this, "PutBucketAccelerateConfigurationCommand"); + } +}; + +// src/commands/PutBucketAclCommand.ts + + + + +var PutBucketAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketAcl", {}).n("S3Client", "PutBucketAclCommand").f(void 0, void 0).ser(se_PutBucketAclCommand).de(de_PutBucketAclCommand).build() { + static { + __name(this, "PutBucketAclCommand"); + } +}; + +// src/commands/PutBucketAnalyticsConfigurationCommand.ts + + + +var PutBucketAnalyticsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketAnalyticsConfiguration", {}).n("S3Client", "PutBucketAnalyticsConfigurationCommand").f(void 0, void 0).ser(se_PutBucketAnalyticsConfigurationCommand).de(de_PutBucketAnalyticsConfigurationCommand).build() { + static { + __name(this, "PutBucketAnalyticsConfigurationCommand"); + } +}; + +// src/commands/PutBucketCorsCommand.ts + + + + +var PutBucketCorsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketCors", {}).n("S3Client", "PutBucketCorsCommand").f(void 0, void 0).ser(se_PutBucketCorsCommand).de(de_PutBucketCorsCommand).build() { + static { + __name(this, "PutBucketCorsCommand"); + } +}; + +// src/commands/PutBucketEncryptionCommand.ts + + + + +var PutBucketEncryptionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketEncryption", {}).n("S3Client", "PutBucketEncryptionCommand").f(PutBucketEncryptionRequestFilterSensitiveLog, void 0).ser(se_PutBucketEncryptionCommand).de(de_PutBucketEncryptionCommand).build() { + static { + __name(this, "PutBucketEncryptionCommand"); + } +}; + +// src/commands/PutBucketIntelligentTieringConfigurationCommand.ts + + + +var PutBucketIntelligentTieringConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketIntelligentTieringConfiguration", {}).n("S3Client", "PutBucketIntelligentTieringConfigurationCommand").f(void 0, void 0).ser(se_PutBucketIntelligentTieringConfigurationCommand).de(de_PutBucketIntelligentTieringConfigurationCommand).build() { + static { + __name(this, "PutBucketIntelligentTieringConfigurationCommand"); + } +}; + +// src/commands/PutBucketInventoryConfigurationCommand.ts + + + +var PutBucketInventoryConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketInventoryConfiguration", {}).n("S3Client", "PutBucketInventoryConfigurationCommand").f(PutBucketInventoryConfigurationRequestFilterSensitiveLog, void 0).ser(se_PutBucketInventoryConfigurationCommand).de(de_PutBucketInventoryConfigurationCommand).build() { + static { + __name(this, "PutBucketInventoryConfigurationCommand"); + } +}; + +// src/commands/PutBucketLifecycleConfigurationCommand.ts + +var import_middleware_sdk_s354 = __nccwpck_require__(77445); + + + +var PutBucketLifecycleConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s354.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutBucketLifecycleConfiguration", {}).n("S3Client", "PutBucketLifecycleConfigurationCommand").f(void 0, void 0).ser(se_PutBucketLifecycleConfigurationCommand).de(de_PutBucketLifecycleConfigurationCommand).build() { + static { + __name(this, "PutBucketLifecycleConfigurationCommand"); + } +}; + +// src/commands/PutBucketLoggingCommand.ts + + + + +var PutBucketLoggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketLogging", {}).n("S3Client", "PutBucketLoggingCommand").f(void 0, void 0).ser(se_PutBucketLoggingCommand).de(de_PutBucketLoggingCommand).build() { + static { + __name(this, "PutBucketLoggingCommand"); + } +}; + +// src/commands/PutBucketMetricsConfigurationCommand.ts + + + +var PutBucketMetricsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketMetricsConfiguration", {}).n("S3Client", "PutBucketMetricsConfigurationCommand").f(void 0, void 0).ser(se_PutBucketMetricsConfigurationCommand).de(de_PutBucketMetricsConfigurationCommand).build() { + static { + __name(this, "PutBucketMetricsConfigurationCommand"); + } +}; + +// src/commands/PutBucketNotificationConfigurationCommand.ts + + + +var PutBucketNotificationConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketNotificationConfiguration", {}).n("S3Client", "PutBucketNotificationConfigurationCommand").f(void 0, void 0).ser(se_PutBucketNotificationConfigurationCommand).de(de_PutBucketNotificationConfigurationCommand).build() { + static { + __name(this, "PutBucketNotificationConfigurationCommand"); + } +}; + +// src/commands/PutBucketOwnershipControlsCommand.ts + + + + +var PutBucketOwnershipControlsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketOwnershipControls", {}).n("S3Client", "PutBucketOwnershipControlsCommand").f(void 0, void 0).ser(se_PutBucketOwnershipControlsCommand).de(de_PutBucketOwnershipControlsCommand).build() { + static { + __name(this, "PutBucketOwnershipControlsCommand"); + } +}; + +// src/commands/PutBucketPolicyCommand.ts + + + + +var PutBucketPolicyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketPolicy", {}).n("S3Client", "PutBucketPolicyCommand").f(void 0, void 0).ser(se_PutBucketPolicyCommand).de(de_PutBucketPolicyCommand).build() { + static { + __name(this, "PutBucketPolicyCommand"); + } +}; + +// src/commands/PutBucketReplicationCommand.ts + + + + +var PutBucketReplicationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketReplication", {}).n("S3Client", "PutBucketReplicationCommand").f(void 0, void 0).ser(se_PutBucketReplicationCommand).de(de_PutBucketReplicationCommand).build() { + static { + __name(this, "PutBucketReplicationCommand"); + } +}; + +// src/commands/PutBucketRequestPaymentCommand.ts + + + + +var PutBucketRequestPaymentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketRequestPayment", {}).n("S3Client", "PutBucketRequestPaymentCommand").f(void 0, void 0).ser(se_PutBucketRequestPaymentCommand).de(de_PutBucketRequestPaymentCommand).build() { + static { + __name(this, "PutBucketRequestPaymentCommand"); + } +}; + +// src/commands/PutBucketTaggingCommand.ts + + + + +var PutBucketTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketTagging", {}).n("S3Client", "PutBucketTaggingCommand").f(void 0, void 0).ser(se_PutBucketTaggingCommand).de(de_PutBucketTaggingCommand).build() { + static { + __name(this, "PutBucketTaggingCommand"); + } +}; + +// src/commands/PutBucketVersioningCommand.ts + + + + +var PutBucketVersioningCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketVersioning", {}).n("S3Client", "PutBucketVersioningCommand").f(void 0, void 0).ser(se_PutBucketVersioningCommand).de(de_PutBucketVersioningCommand).build() { + static { + __name(this, "PutBucketVersioningCommand"); + } +}; + +// src/commands/PutBucketWebsiteCommand.ts + + + + +var PutBucketWebsiteCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketWebsite", {}).n("S3Client", "PutBucketWebsiteCommand").f(void 0, void 0).ser(se_PutBucketWebsiteCommand).de(de_PutBucketWebsiteCommand).build() { + static { + __name(this, "PutBucketWebsiteCommand"); + } +}; + +// src/commands/PutObjectAclCommand.ts + +var import_middleware_sdk_s355 = __nccwpck_require__(77445); + + + +var PutObjectAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s355.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectAcl", {}).n("S3Client", "PutObjectAclCommand").f(void 0, void 0).ser(se_PutObjectAclCommand).de(de_PutObjectAclCommand).build() { + static { + __name(this, "PutObjectAclCommand"); + } +}; + +// src/commands/PutObjectCommand.ts + +var import_middleware_sdk_s356 = __nccwpck_require__(77445); + + + + +var PutObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }), + (0, import_middleware_sdk_s356.getCheckContentLengthHeaderPlugin)(config), + (0, import_middleware_sdk_s356.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "PutObject", {}).n("S3Client", "PutObjectCommand").f(PutObjectRequestFilterSensitiveLog, PutObjectOutputFilterSensitiveLog).ser(se_PutObjectCommand).de(de_PutObjectCommand).build() { + static { + __name(this, "PutObjectCommand"); + } +}; + +// src/commands/PutObjectLegalHoldCommand.ts + +var import_middleware_sdk_s357 = __nccwpck_require__(77445); + + + +var PutObjectLegalHoldCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s357.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectLegalHold", {}).n("S3Client", "PutObjectLegalHoldCommand").f(void 0, void 0).ser(se_PutObjectLegalHoldCommand).de(de_PutObjectLegalHoldCommand).build() { + static { + __name(this, "PutObjectLegalHoldCommand"); + } +}; + +// src/commands/PutObjectLockConfigurationCommand.ts + +var import_middleware_sdk_s358 = __nccwpck_require__(77445); + + + +var PutObjectLockConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s358.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectLockConfiguration", {}).n("S3Client", "PutObjectLockConfigurationCommand").f(void 0, void 0).ser(se_PutObjectLockConfigurationCommand).de(de_PutObjectLockConfigurationCommand).build() { + static { + __name(this, "PutObjectLockConfigurationCommand"); + } +}; + +// src/commands/PutObjectRetentionCommand.ts + +var import_middleware_sdk_s359 = __nccwpck_require__(77445); + + + +var PutObjectRetentionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s359.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectRetention", {}).n("S3Client", "PutObjectRetentionCommand").f(void 0, void 0).ser(se_PutObjectRetentionCommand).de(de_PutObjectRetentionCommand).build() { + static { + __name(this, "PutObjectRetentionCommand"); + } +}; + +// src/commands/PutObjectTaggingCommand.ts + +var import_middleware_sdk_s360 = __nccwpck_require__(77445); + + + +var PutObjectTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s360.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectTagging", {}).n("S3Client", "PutObjectTaggingCommand").f(void 0, void 0).ser(se_PutObjectTaggingCommand).de(de_PutObjectTaggingCommand).build() { + static { + __name(this, "PutObjectTaggingCommand"); + } +}; + +// src/commands/PutPublicAccessBlockCommand.ts + + + + +var PutPublicAccessBlockCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutPublicAccessBlock", {}).n("S3Client", "PutPublicAccessBlockCommand").f(void 0, void 0).ser(se_PutPublicAccessBlockCommand).de(de_PutPublicAccessBlockCommand).build() { + static { + __name(this, "PutPublicAccessBlockCommand"); + } +}; + +// src/commands/RenameObjectCommand.ts +var import_middleware_sdk_s361 = __nccwpck_require__(77445); + + + +var RenameObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s361.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "RenameObject", {}).n("S3Client", "RenameObjectCommand").f(void 0, void 0).ser(se_RenameObjectCommand).de(de_RenameObjectCommand).build() { + static { + __name(this, "RenameObjectCommand"); + } +}; + +// src/commands/RestoreObjectCommand.ts + +var import_middleware_sdk_s362 = __nccwpck_require__(77445); + + + +var RestoreObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }), + (0, import_middleware_sdk_s362.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "RestoreObject", {}).n("S3Client", "RestoreObjectCommand").f(RestoreObjectRequestFilterSensitiveLog, void 0).ser(se_RestoreObjectCommand).de(de_RestoreObjectCommand).build() { + static { + __name(this, "RestoreObjectCommand"); + } +}; + +// src/commands/SelectObjectContentCommand.ts +var import_middleware_sdk_s363 = __nccwpck_require__(77445); + + + + +var SelectObjectContentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s363.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "SelectObjectContent", { + /** + * @internal + */ + eventStream: { + output: true + } +}).n("S3Client", "SelectObjectContentCommand").f(SelectObjectContentRequestFilterSensitiveLog, SelectObjectContentOutputFilterSensitiveLog).ser(se_SelectObjectContentCommand).de(de_SelectObjectContentCommand).build() { + static { + __name(this, "SelectObjectContentCommand"); + } +}; + +// src/commands/UpdateBucketMetadataInventoryTableConfigurationCommand.ts + + + + +var UpdateBucketMetadataInventoryTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "UpdateBucketMetadataInventoryTableConfiguration", {}).n("S3Client", "UpdateBucketMetadataInventoryTableConfigurationCommand").f(void 0, void 0).ser(se_UpdateBucketMetadataInventoryTableConfigurationCommand).de(de_UpdateBucketMetadataInventoryTableConfigurationCommand).build() { + static { + __name(this, "UpdateBucketMetadataInventoryTableConfigurationCommand"); + } +}; + +// src/commands/UpdateBucketMetadataJournalTableConfigurationCommand.ts + + + + +var UpdateBucketMetadataJournalTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "UpdateBucketMetadataJournalTableConfiguration", {}).n("S3Client", "UpdateBucketMetadataJournalTableConfigurationCommand").f(void 0, void 0).ser(se_UpdateBucketMetadataJournalTableConfigurationCommand).de(de_UpdateBucketMetadataJournalTableConfigurationCommand).build() { + static { + __name(this, "UpdateBucketMetadataJournalTableConfigurationCommand"); + } +}; + +// src/commands/UploadPartCommand.ts + +var import_middleware_sdk_s364 = __nccwpck_require__(77445); + + + + +var UploadPartCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }), + (0, import_middleware_sdk_s364.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "UploadPart", {}).n("S3Client", "UploadPartCommand").f(UploadPartRequestFilterSensitiveLog, UploadPartOutputFilterSensitiveLog).ser(se_UploadPartCommand).de(de_UploadPartCommand).build() { + static { + __name(this, "UploadPartCommand"); + } +}; + +// src/commands/UploadPartCopyCommand.ts +var import_middleware_sdk_s365 = __nccwpck_require__(77445); + + + + +var UploadPartCopyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s365.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "UploadPartCopy", {}).n("S3Client", "UploadPartCopyCommand").f(UploadPartCopyRequestFilterSensitiveLog, UploadPartCopyOutputFilterSensitiveLog).ser(se_UploadPartCopyCommand).de(de_UploadPartCopyCommand).build() { + static { + __name(this, "UploadPartCopyCommand"); + } +}; + +// src/commands/WriteGetObjectResponseCommand.ts + + + +var WriteGetObjectResponseCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseObjectLambdaEndpoint: { type: "staticContextParams", value: true } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "WriteGetObjectResponse", {}).n("S3Client", "WriteGetObjectResponseCommand").f(WriteGetObjectResponseRequestFilterSensitiveLog, void 0).ser(se_WriteGetObjectResponseCommand).de(de_WriteGetObjectResponseCommand).build() { + static { + __name(this, "WriteGetObjectResponseCommand"); + } +}; + +// src/S3.ts +var commands = { + AbortMultipartUploadCommand, + CompleteMultipartUploadCommand, + CopyObjectCommand, + CreateBucketCommand, + CreateBucketMetadataConfigurationCommand, + CreateBucketMetadataTableConfigurationCommand, + CreateMultipartUploadCommand, + CreateSessionCommand, + DeleteBucketCommand, + DeleteBucketAnalyticsConfigurationCommand, + DeleteBucketCorsCommand, + DeleteBucketEncryptionCommand, + DeleteBucketIntelligentTieringConfigurationCommand, + DeleteBucketInventoryConfigurationCommand, + DeleteBucketLifecycleCommand, + DeleteBucketMetadataConfigurationCommand, + DeleteBucketMetadataTableConfigurationCommand, + DeleteBucketMetricsConfigurationCommand, + DeleteBucketOwnershipControlsCommand, + DeleteBucketPolicyCommand, + DeleteBucketReplicationCommand, + DeleteBucketTaggingCommand, + DeleteBucketWebsiteCommand, + DeleteObjectCommand, + DeleteObjectsCommand, + DeleteObjectTaggingCommand, + DeletePublicAccessBlockCommand, + GetBucketAccelerateConfigurationCommand, + GetBucketAclCommand, + GetBucketAnalyticsConfigurationCommand, + GetBucketCorsCommand, + GetBucketEncryptionCommand, + GetBucketIntelligentTieringConfigurationCommand, + GetBucketInventoryConfigurationCommand, + GetBucketLifecycleConfigurationCommand, + GetBucketLocationCommand, + GetBucketLoggingCommand, + GetBucketMetadataConfigurationCommand, + GetBucketMetadataTableConfigurationCommand, + GetBucketMetricsConfigurationCommand, + GetBucketNotificationConfigurationCommand, + GetBucketOwnershipControlsCommand, + GetBucketPolicyCommand, + GetBucketPolicyStatusCommand, + GetBucketReplicationCommand, + GetBucketRequestPaymentCommand, + GetBucketTaggingCommand, + GetBucketVersioningCommand, + GetBucketWebsiteCommand, + GetObjectCommand, + GetObjectAclCommand, + GetObjectAttributesCommand, + GetObjectLegalHoldCommand, + GetObjectLockConfigurationCommand, + GetObjectRetentionCommand, + GetObjectTaggingCommand, + GetObjectTorrentCommand, + GetPublicAccessBlockCommand, + HeadBucketCommand, + HeadObjectCommand, + ListBucketAnalyticsConfigurationsCommand, + ListBucketIntelligentTieringConfigurationsCommand, + ListBucketInventoryConfigurationsCommand, + ListBucketMetricsConfigurationsCommand, + ListBucketsCommand, + ListDirectoryBucketsCommand, + ListMultipartUploadsCommand, + ListObjectsCommand, + ListObjectsV2Command, + ListObjectVersionsCommand, + ListPartsCommand, + PutBucketAccelerateConfigurationCommand, + PutBucketAclCommand, + PutBucketAnalyticsConfigurationCommand, + PutBucketCorsCommand, + PutBucketEncryptionCommand, + PutBucketIntelligentTieringConfigurationCommand, + PutBucketInventoryConfigurationCommand, + PutBucketLifecycleConfigurationCommand, + PutBucketLoggingCommand, + PutBucketMetricsConfigurationCommand, + PutBucketNotificationConfigurationCommand, + PutBucketOwnershipControlsCommand, + PutBucketPolicyCommand, + PutBucketReplicationCommand, + PutBucketRequestPaymentCommand, + PutBucketTaggingCommand, + PutBucketVersioningCommand, + PutBucketWebsiteCommand, + PutObjectCommand, + PutObjectAclCommand, + PutObjectLegalHoldCommand, + PutObjectLockConfigurationCommand, + PutObjectRetentionCommand, + PutObjectTaggingCommand, + PutPublicAccessBlockCommand, + RenameObjectCommand, + RestoreObjectCommand, + SelectObjectContentCommand, + UpdateBucketMetadataInventoryTableConfigurationCommand, + UpdateBucketMetadataJournalTableConfigurationCommand, + UploadPartCommand, + UploadPartCopyCommand, + WriteGetObjectResponseCommand +}; +var S3 = class extends S3Client { + static { + __name(this, "S3"); + } +}; +(0, import_smithy_client.createAggregatedClient)(commands, S3); + +// src/pagination/ListBucketsPaginator.ts +var import_core4 = __nccwpck_require__(90402); +var paginateListBuckets = (0, import_core4.createPaginator)(S3Client, ListBucketsCommand, "ContinuationToken", "ContinuationToken", "MaxBuckets"); + +// src/pagination/ListDirectoryBucketsPaginator.ts +var import_core5 = __nccwpck_require__(90402); +var paginateListDirectoryBuckets = (0, import_core5.createPaginator)(S3Client, ListDirectoryBucketsCommand, "ContinuationToken", "ContinuationToken", "MaxDirectoryBuckets"); + +// src/pagination/ListObjectsV2Paginator.ts +var import_core6 = __nccwpck_require__(90402); +var paginateListObjectsV2 = (0, import_core6.createPaginator)(S3Client, ListObjectsV2Command, "ContinuationToken", "NextContinuationToken", "MaxKeys"); + +// src/pagination/ListPartsPaginator.ts +var import_core7 = __nccwpck_require__(90402); +var paginateListParts = (0, import_core7.createPaginator)(S3Client, ListPartsCommand, "PartNumberMarker", "NextPartNumberMarker", "MaxParts"); + +// src/waiters/waitForBucketExists.ts +var import_util_waiter = __nccwpck_require__(95290); +var checkState = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadBucketCommand(input)); + reason = result; + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.RETRY, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForBucketExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState); +}, "waitForBucketExists"); +var waitUntilBucketExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilBucketExists"); + +// src/waiters/waitForBucketNotExists.ts + +var checkState2 = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadBucketCommand(input)); + reason = result; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForBucketNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState2); +}, "waitForBucketNotExists"); +var waitUntilBucketNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState2); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilBucketNotExists"); + +// src/waiters/waitForObjectExists.ts + +var checkState3 = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadObjectCommand(input)); + reason = result; + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.RETRY, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForObjectExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState3); +}, "waitForObjectExists"); +var waitUntilObjectExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState3); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilObjectExists"); + +// src/waiters/waitForObjectNotExists.ts + +var checkState4 = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadObjectCommand(input)); + reason = result; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForObjectNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState4); +}, "waitForObjectNotExists"); +var waitUntilObjectNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState4); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilObjectNotExists"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 35745: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(27413)); +const core_1 = __nccwpck_require__(8704); +const credential_provider_node_1 = __nccwpck_require__(5861); +const middleware_bucket_endpoint_1 = __nccwpck_require__(26518); +const middleware_flexible_checksums_1 = __nccwpck_require__(29836); +const middleware_sdk_s3_1 = __nccwpck_require__(77445); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const eventstream_serde_node_1 = __nccwpck_require__(69770); +const hash_node_1 = __nccwpck_require__(5092); +const hash_stream_node_1 = __nccwpck_require__(45317); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(74070); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + credentialDefaultProvider: config?.credentialDefaultProvider ?? credential_provider_node_1.defaultProvider, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + disableS3ExpressSessionAuth: config?.disableS3ExpressSessionAuth ?? (0, node_config_provider_1.loadConfig)(middleware_sdk_s3_1.NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, loaderConfig), + eventStreamSerdeProvider: config?.eventStreamSerdeProvider ?? eventstream_serde_node_1.eventStreamSerdeProvider, + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + md5: config?.md5 ?? hash_node_1.Hash.bind(null, "md5"), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestChecksumCalculation: config?.requestChecksumCalculation ?? + (0, node_config_provider_1.loadConfig)(middleware_flexible_checksums_1.NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS, loaderConfig), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + responseChecksumValidation: config?.responseChecksumValidation ?? + (0, node_config_provider_1.loadConfig)(middleware_flexible_checksums_1.NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS, loaderConfig), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha1: config?.sha1 ?? hash_node_1.Hash.bind(null, "sha1"), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + sigv4aSigningRegionSet: config?.sigv4aSigningRegionSet ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_SIGV4A_CONFIG_OPTIONS, loaderConfig), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + streamHasher: config?.streamHasher ?? hash_stream_node_1.readableStreamHasher, + useArnRegion: config?.useArnRegion ?? (0, node_config_provider_1.loadConfig)(middleware_bucket_endpoint_1.NODE_USE_ARN_REGION_CONFIG_OPTIONS, loaderConfig), + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 74070: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const signature_v4_multi_region_1 = __nccwpck_require__(5785); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_stream_1 = __nccwpck_require__(4252); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(7168); +const endpointResolver_1 = __nccwpck_require__(57526); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2006-03-01", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + getAwsChunkedEncodingStream: config?.getAwsChunkedEncodingStream ?? util_stream_1.getAwsChunkedEncodingStream, + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultS3HttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "aws.auth#sigv4a", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4a"), + signer: new core_1.AwsSdkSigV4ASigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + sdkStreamMixin: config?.sdkStreamMixin ?? util_stream_1.sdkStreamMixin, + serviceId: config?.serviceId ?? "S3", + signerConstructor: config?.signerConstructor ?? signature_v4_multi_region_1.SignatureV4MultiRegion, + signingEscapePath: config?.signingEscapePath ?? false, + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + useArnRegion: config?.useArnRegion ?? undefined, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 62041: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.defaultSSOHttpAuthSchemeProvider = exports.defaultSSOHttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const util_middleware_1 = __nccwpck_require__(76324); +const defaultSSOHttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultSSOHttpAuthSchemeParametersProvider = defaultSSOHttpAuthSchemeParametersProvider; +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "awsssoportal", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createSmithyApiNoAuthHttpAuthOption(authParameters) { + return { + schemeId: "smithy.api#noAuth", + }; +} +const defaultSSOHttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + case "GetRoleCredentials": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + case "ListAccountRoles": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + case "ListAccounts": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + case "Logout": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultSSOHttpAuthSchemeProvider = defaultSSOHttpAuthSchemeProvider; +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config); + return Object.assign(config_0, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 13903: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(41308); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: ["Endpoint", "Region", "UseDualStack", "UseFIPS"], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 41308: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const u = "required", v = "fn", w = "argv", x = "ref"; +const a = true, b = "isSet", c = "booleanEquals", d = "error", e = "endpoint", f = "tree", g = "PartitionResult", h = "getAttr", i = { [u]: false, "type": "String" }, j = { [u]: true, "default": false, "type": "Boolean" }, k = { [x]: "Endpoint" }, l = { [v]: c, [w]: [{ [x]: "UseFIPS" }, true] }, m = { [v]: c, [w]: [{ [x]: "UseDualStack" }, true] }, n = {}, o = { [v]: h, [w]: [{ [x]: g }, "supportsFIPS"] }, p = { [x]: g }, q = { [v]: c, [w]: [true, { [v]: h, [w]: [p, "supportsDualStack"] }] }, r = [l], s = [m], t = [{ [x]: "Region" }]; +const _data = { version: "1.0", parameters: { Region: i, UseDualStack: j, UseFIPS: j, Endpoint: i }, rules: [{ conditions: [{ [v]: b, [w]: [k] }], rules: [{ conditions: r, error: "Invalid Configuration: FIPS and custom endpoint are not supported", type: d }, { conditions: s, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", type: d }, { endpoint: { url: k, properties: n, headers: n }, type: e }], type: f }, { conditions: [{ [v]: b, [w]: t }], rules: [{ conditions: [{ [v]: "aws.partition", [w]: t, assign: g }], rules: [{ conditions: [l, m], rules: [{ conditions: [{ [v]: c, [w]: [a, o] }, q], rules: [{ endpoint: { url: "https://portal.sso-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", type: d }], type: f }, { conditions: r, rules: [{ conditions: [{ [v]: c, [w]: [o, a] }], rules: [{ conditions: [{ [v]: "stringEquals", [w]: [{ [v]: h, [w]: [p, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://portal.sso.{Region}.amazonaws.com", properties: n, headers: n }, type: e }, { endpoint: { url: "https://portal.sso-fips.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS is enabled but this partition does not support FIPS", type: d }], type: f }, { conditions: s, rules: [{ conditions: [q], rules: [{ endpoint: { url: "https://portal.sso.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "DualStack is enabled but this partition does not support DualStack", type: d }], type: f }, { endpoint: { url: "https://portal.sso.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }], type: f }, { error: "Invalid Configuration: Missing Region", type: d }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 62054: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + GetRoleCredentialsCommand: () => GetRoleCredentialsCommand, + GetRoleCredentialsRequestFilterSensitiveLog: () => GetRoleCredentialsRequestFilterSensitiveLog, + GetRoleCredentialsResponseFilterSensitiveLog: () => GetRoleCredentialsResponseFilterSensitiveLog, + InvalidRequestException: () => InvalidRequestException, + ListAccountRolesCommand: () => ListAccountRolesCommand, + ListAccountRolesRequestFilterSensitiveLog: () => ListAccountRolesRequestFilterSensitiveLog, + ListAccountsCommand: () => ListAccountsCommand, + ListAccountsRequestFilterSensitiveLog: () => ListAccountsRequestFilterSensitiveLog, + LogoutCommand: () => LogoutCommand, + LogoutRequestFilterSensitiveLog: () => LogoutRequestFilterSensitiveLog, + ResourceNotFoundException: () => ResourceNotFoundException, + RoleCredentialsFilterSensitiveLog: () => RoleCredentialsFilterSensitiveLog, + SSO: () => SSO, + SSOClient: () => SSOClient, + SSOServiceException: () => SSOServiceException, + TooManyRequestsException: () => TooManyRequestsException, + UnauthorizedException: () => UnauthorizedException, + __Client: () => import_smithy_client.Client, + paginateListAccountRoles: () => paginateListAccountRoles, + paginateListAccounts: () => paginateListAccounts +}); +module.exports = __toCommonJS(index_exports); + +// src/SSOClient.ts +var import_middleware_host_header = __nccwpck_require__(52590); +var import_middleware_logger = __nccwpck_require__(85242); +var import_middleware_recursion_detection = __nccwpck_require__(81568); +var import_middleware_user_agent = __nccwpck_require__(32959); +var import_config_resolver = __nccwpck_require__(39316); +var import_core = __nccwpck_require__(90402); +var import_middleware_content_length = __nccwpck_require__(47212); +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_retry = __nccwpck_require__(19618); + +var import_httpAuthSchemeProvider = __nccwpck_require__(62041); + +// src/endpoint/EndpointParameters.ts +var resolveClientEndpointParameters = /* @__PURE__ */ __name((options) => { + return Object.assign(options, { + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + useFipsEndpoint: options.useFipsEndpoint ?? false, + defaultSigningName: "awsssoportal" + }); +}, "resolveClientEndpointParameters"); +var commonParams = { + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" } +}; + +// src/SSOClient.ts +var import_runtimeConfig = __nccwpck_require__(82696); + +// src/runtimeExtensions.ts +var import_region_config_resolver = __nccwpck_require__(36463); +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client = __nccwpck_require__(61411); + +// src/auth/httpAuthExtensionConfiguration.ts +var getHttpAuthExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + } + }; +}, "getHttpAuthExtensionConfiguration"); +var resolveHttpAuthRuntimeConfig = /* @__PURE__ */ __name((config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials() + }; +}, "resolveHttpAuthRuntimeConfig"); + +// src/runtimeExtensions.ts +var resolveRuntimeExtensions = /* @__PURE__ */ __name((runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign( + (0, import_region_config_resolver.getAwsRegionExtensionConfiguration)(runtimeConfig), + (0, import_smithy_client.getDefaultExtensionConfiguration)(runtimeConfig), + (0, import_protocol_http.getHttpHandlerExtensionConfiguration)(runtimeConfig), + getHttpAuthExtensionConfiguration(runtimeConfig) + ); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign( + runtimeConfig, + (0, import_region_config_resolver.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), + (0, import_smithy_client.resolveDefaultRuntimeConfig)(extensionConfiguration), + (0, import_protocol_http.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), + resolveHttpAuthRuntimeConfig(extensionConfiguration) + ); +}, "resolveRuntimeExtensions"); + +// src/SSOClient.ts +var SSOClient = class extends import_smithy_client.Client { + static { + __name(this, "SSOClient"); + } + /** + * The resolved configuration of SSOClient class. This is resolved and normalized from the {@link SSOClientConfig | constructor configuration interface}. + */ + config; + constructor(...[configuration]) { + const _config_0 = (0, import_runtimeConfig.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = resolveClientEndpointParameters(_config_0); + const _config_2 = (0, import_middleware_user_agent.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, import_middleware_retry.resolveRetryConfig)(_config_2); + const _config_4 = (0, import_config_resolver.resolveRegionConfig)(_config_3); + const _config_5 = (0, import_middleware_host_header.resolveHostHeaderConfig)(_config_4); + const _config_6 = (0, import_middleware_endpoint.resolveEndpointConfig)(_config_5); + const _config_7 = (0, import_httpAuthSchemeProvider.resolveHttpAuthSchemeConfig)(_config_6); + const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []); + this.config = _config_8; + this.middlewareStack.use((0, import_middleware_user_agent.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_retry.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_content_length.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_host_header.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_logger.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_recursion_detection.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use( + (0, import_core.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: import_httpAuthSchemeProvider.defaultSSOHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: /* @__PURE__ */ __name(async (config) => new import_core.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials + }), "identityProviderConfigProvider") + }) + ); + this.middlewareStack.use((0, import_core.getHttpSigningPlugin)(this.config)); + } + /** + * Destroy underlying resources, like sockets. It's usually not necessary to do this. + * However in Node.js, it's best to explicitly shut down the client's agent when it is no longer needed. + * Otherwise, sockets might stay open for quite a long time before the server terminates them. + */ + destroy() { + super.destroy(); + } +}; + +// src/SSO.ts + + +// src/commands/GetRoleCredentialsCommand.ts + +var import_middleware_serde = __nccwpck_require__(83255); + + +// src/models/models_0.ts + + +// src/models/SSOServiceException.ts + +var SSOServiceException = class _SSOServiceException extends import_smithy_client.ServiceException { + static { + __name(this, "SSOServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _SSOServiceException.prototype); + } +}; + +// src/models/models_0.ts +var InvalidRequestException = class _InvalidRequestException extends SSOServiceException { + static { + __name(this, "InvalidRequestException"); + } + name = "InvalidRequestException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidRequestException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidRequestException.prototype); + } +}; +var ResourceNotFoundException = class _ResourceNotFoundException extends SSOServiceException { + static { + __name(this, "ResourceNotFoundException"); + } + name = "ResourceNotFoundException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ResourceNotFoundException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ResourceNotFoundException.prototype); + } +}; +var TooManyRequestsException = class _TooManyRequestsException extends SSOServiceException { + static { + __name(this, "TooManyRequestsException"); + } + name = "TooManyRequestsException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "TooManyRequestsException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _TooManyRequestsException.prototype); + } +}; +var UnauthorizedException = class _UnauthorizedException extends SSOServiceException { + static { + __name(this, "UnauthorizedException"); + } + name = "UnauthorizedException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "UnauthorizedException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _UnauthorizedException.prototype); + } +}; +var GetRoleCredentialsRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "GetRoleCredentialsRequestFilterSensitiveLog"); +var RoleCredentialsFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.secretAccessKey && { secretAccessKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.sessionToken && { sessionToken: import_smithy_client.SENSITIVE_STRING } +}), "RoleCredentialsFilterSensitiveLog"); +var GetRoleCredentialsResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.roleCredentials && { roleCredentials: RoleCredentialsFilterSensitiveLog(obj.roleCredentials) } +}), "GetRoleCredentialsResponseFilterSensitiveLog"); +var ListAccountRolesRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "ListAccountRolesRequestFilterSensitiveLog"); +var ListAccountsRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "ListAccountsRequestFilterSensitiveLog"); +var LogoutRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "LogoutRequestFilterSensitiveLog"); + +// src/protocols/Aws_restJson1.ts +var import_core2 = __nccwpck_require__(8704); + + +var se_GetRoleCredentialsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/federation/credentials"); + const query = (0, import_smithy_client.map)({ + [_rn]: [, (0, import_smithy_client.expectNonNull)(input[_rN], `roleName`)], + [_ai]: [, (0, import_smithy_client.expectNonNull)(input[_aI], `accountId`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetRoleCredentialsCommand"); +var se_ListAccountRolesCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/assignment/roles"); + const query = (0, import_smithy_client.map)({ + [_nt]: [, input[_nT]], + [_mr]: [() => input.maxResults !== void 0, () => input[_mR].toString()], + [_ai]: [, (0, import_smithy_client.expectNonNull)(input[_aI], `accountId`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListAccountRolesCommand"); +var se_ListAccountsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/assignment/accounts"); + const query = (0, import_smithy_client.map)({ + [_nt]: [, input[_nT]], + [_mr]: [() => input.maxResults !== void 0, () => input[_mR].toString()] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListAccountsCommand"); +var se_LogoutCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/logout"); + let body; + b.m("POST").h(headers).b(body); + return b.build(); +}, "se_LogoutCommand"); +var de_GetRoleCredentialsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client.take)(data, { + roleCredentials: import_smithy_client._json + }); + Object.assign(contents, doc); + return contents; +}, "de_GetRoleCredentialsCommand"); +var de_ListAccountRolesCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client.take)(data, { + nextToken: import_smithy_client.expectString, + roleList: import_smithy_client._json + }); + Object.assign(contents, doc); + return contents; +}, "de_ListAccountRolesCommand"); +var de_ListAccountsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client.take)(data, { + accountList: import_smithy_client._json, + nextToken: import_smithy_client.expectString + }); + Object.assign(contents, doc); + return contents; +}, "de_ListAccountsCommand"); +var de_LogoutCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_LogoutCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core2.parseJsonErrorBody)(output.body, context) + }; + const errorCode = (0, import_core2.loadRestJsonErrorCode)(output, parsedOutput.body); + switch (errorCode) { + case "InvalidRequestException": + case "com.amazonaws.sso#InvalidRequestException": + throw await de_InvalidRequestExceptionRes(parsedOutput, context); + case "ResourceNotFoundException": + case "com.amazonaws.sso#ResourceNotFoundException": + throw await de_ResourceNotFoundExceptionRes(parsedOutput, context); + case "TooManyRequestsException": + case "com.amazonaws.sso#TooManyRequestsException": + throw await de_TooManyRequestsExceptionRes(parsedOutput, context); + case "UnauthorizedException": + case "com.amazonaws.sso#UnauthorizedException": + throw await de_UnauthorizedExceptionRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody, + errorCode + }); + } +}, "de_CommandError"); +var throwDefaultError = (0, import_smithy_client.withBaseException)(SSOServiceException); +var de_InvalidRequestExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidRequestException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidRequestExceptionRes"); +var de_ResourceNotFoundExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new ResourceNotFoundException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_ResourceNotFoundExceptionRes"); +var de_TooManyRequestsExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new TooManyRequestsException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_TooManyRequestsExceptionRes"); +var de_UnauthorizedExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new UnauthorizedException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_UnauthorizedExceptionRes"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); +var _aI = "accountId"; +var _aT = "accessToken"; +var _ai = "account_id"; +var _mR = "maxResults"; +var _mr = "max_result"; +var _nT = "nextToken"; +var _nt = "next_token"; +var _rN = "roleName"; +var _rn = "role_name"; +var _xasbt = "x-amz-sso_bearer_token"; + +// src/commands/GetRoleCredentialsCommand.ts +var GetRoleCredentialsCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "GetRoleCredentials", {}).n("SSOClient", "GetRoleCredentialsCommand").f(GetRoleCredentialsRequestFilterSensitiveLog, GetRoleCredentialsResponseFilterSensitiveLog).ser(se_GetRoleCredentialsCommand).de(de_GetRoleCredentialsCommand).build() { + static { + __name(this, "GetRoleCredentialsCommand"); + } +}; + +// src/commands/ListAccountRolesCommand.ts + + + +var ListAccountRolesCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "ListAccountRoles", {}).n("SSOClient", "ListAccountRolesCommand").f(ListAccountRolesRequestFilterSensitiveLog, void 0).ser(se_ListAccountRolesCommand).de(de_ListAccountRolesCommand).build() { + static { + __name(this, "ListAccountRolesCommand"); + } +}; + +// src/commands/ListAccountsCommand.ts + + + +var ListAccountsCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "ListAccounts", {}).n("SSOClient", "ListAccountsCommand").f(ListAccountsRequestFilterSensitiveLog, void 0).ser(se_ListAccountsCommand).de(de_ListAccountsCommand).build() { + static { + __name(this, "ListAccountsCommand"); + } +}; + +// src/commands/LogoutCommand.ts + + + +var LogoutCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "Logout", {}).n("SSOClient", "LogoutCommand").f(LogoutRequestFilterSensitiveLog, void 0).ser(se_LogoutCommand).de(de_LogoutCommand).build() { + static { + __name(this, "LogoutCommand"); + } +}; + +// src/SSO.ts +var commands = { + GetRoleCredentialsCommand, + ListAccountRolesCommand, + ListAccountsCommand, + LogoutCommand +}; +var SSO = class extends SSOClient { + static { + __name(this, "SSO"); + } +}; +(0, import_smithy_client.createAggregatedClient)(commands, SSO); + +// src/pagination/ListAccountRolesPaginator.ts + +var paginateListAccountRoles = (0, import_core.createPaginator)(SSOClient, ListAccountRolesCommand, "nextToken", "nextToken", "maxResults"); + +// src/pagination/ListAccountsPaginator.ts + +var paginateListAccounts = (0, import_core.createPaginator)(SSOClient, ListAccountsCommand, "nextToken", "nextToken", "maxResults"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 82696: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(45188)); +const core_1 = __nccwpck_require__(8704); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const hash_node_1 = __nccwpck_require__(5092); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(8073); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 8073: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const core_2 = __nccwpck_require__(90402); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(62041); +const endpointResolver_1 = __nccwpck_require__(13903); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2019-06-10", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSSOHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + serviceId: config?.serviceId ?? "SSO", + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 8704: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const tslib_1 = __nccwpck_require__(61860); +tslib_1.__exportStar(__nccwpck_require__(5152), exports); +tslib_1.__exportStar(__nccwpck_require__(97523), exports); +tslib_1.__exportStar(__nccwpck_require__(37288), exports); + + +/***/ }), + +/***/ 5152: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/client/index.ts +var index_exports = {}; +__export(index_exports, { + emitWarningIfUnsupportedVersion: () => emitWarningIfUnsupportedVersion, + setCredentialFeature: () => setCredentialFeature, + setFeature: () => setFeature, + setTokenFeature: () => setTokenFeature, + state: () => state +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/client/emitWarningIfUnsupportedVersion.ts +var state = { + warningEmitted: false +}; +var emitWarningIfUnsupportedVersion = /* @__PURE__ */ __name((version) => { + if (version && !state.warningEmitted && parseInt(version.substring(1, version.indexOf("."))) < 18) { + state.warningEmitted = true; + process.emitWarning( + `NodeDeprecationWarning: The AWS SDK for JavaScript (v3) will +no longer support Node.js 16.x on January 6, 2025. + +To continue receiving updates to AWS services, bug fixes, and security +updates please upgrade to a supported Node.js LTS version. + +More information can be found at: https://a.co/74kJMmI` + ); + } +}, "emitWarningIfUnsupportedVersion"); + +// src/submodules/client/setCredentialFeature.ts +function setCredentialFeature(credentials, feature, value) { + if (!credentials.$source) { + credentials.$source = {}; + } + credentials.$source[feature] = value; + return credentials; +} +__name(setCredentialFeature, "setCredentialFeature"); + +// src/submodules/client/setFeature.ts +function setFeature(context, feature, value) { + if (!context.__aws_sdk_context) { + context.__aws_sdk_context = { + features: {} + }; + } else if (!context.__aws_sdk_context.features) { + context.__aws_sdk_context.features = {}; + } + context.__aws_sdk_context.features[feature] = value; +} +__name(setFeature, "setFeature"); + +// src/submodules/client/setTokenFeature.ts +function setTokenFeature(token, feature, value) { + if (!token.$source) { + token.$source = {}; + } + token.$source[feature] = value; + return token; +} +__name(setTokenFeature, "setTokenFeature"); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 97523: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/httpAuthSchemes/index.ts +var index_exports = {}; +__export(index_exports, { + AWSSDKSigV4Signer: () => AWSSDKSigV4Signer, + AwsSdkSigV4ASigner: () => AwsSdkSigV4ASigner, + AwsSdkSigV4Signer: () => AwsSdkSigV4Signer, + NODE_AUTH_SCHEME_PREFERENCE_OPTIONS: () => NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, + NODE_SIGV4A_CONFIG_OPTIONS: () => NODE_SIGV4A_CONFIG_OPTIONS, + getBearerTokenEnvKey: () => getBearerTokenEnvKey, + resolveAWSSDKSigV4Config: () => resolveAWSSDKSigV4Config, + resolveAwsSdkSigV4AConfig: () => resolveAwsSdkSigV4AConfig, + resolveAwsSdkSigV4Config: () => resolveAwsSdkSigV4Config, + validateSigningProperties: () => validateSigningProperties +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts +var import_protocol_http2 = __nccwpck_require__(72356); + +// src/submodules/httpAuthSchemes/utils/getDateHeader.ts +var import_protocol_http = __nccwpck_require__(72356); +var getDateHeader = /* @__PURE__ */ __name((response) => import_protocol_http.HttpResponse.isInstance(response) ? response.headers?.date ?? response.headers?.Date : void 0, "getDateHeader"); + +// src/submodules/httpAuthSchemes/utils/getSkewCorrectedDate.ts +var getSkewCorrectedDate = /* @__PURE__ */ __name((systemClockOffset) => new Date(Date.now() + systemClockOffset), "getSkewCorrectedDate"); + +// src/submodules/httpAuthSchemes/utils/isClockSkewed.ts +var isClockSkewed = /* @__PURE__ */ __name((clockTime, systemClockOffset) => Math.abs(getSkewCorrectedDate(systemClockOffset).getTime() - clockTime) >= 3e5, "isClockSkewed"); + +// src/submodules/httpAuthSchemes/utils/getUpdatedSystemClockOffset.ts +var getUpdatedSystemClockOffset = /* @__PURE__ */ __name((clockTime, currentSystemClockOffset) => { + const clockTimeInMs = Date.parse(clockTime); + if (isClockSkewed(clockTimeInMs, currentSystemClockOffset)) { + return clockTimeInMs - Date.now(); + } + return currentSystemClockOffset; +}, "getUpdatedSystemClockOffset"); + +// src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts +var throwSigningPropertyError = /* @__PURE__ */ __name((name, property) => { + if (!property) { + throw new Error(`Property \`${name}\` is not resolved for AWS SDK SigV4Auth`); + } + return property; +}, "throwSigningPropertyError"); +var validateSigningProperties = /* @__PURE__ */ __name(async (signingProperties) => { + const context = throwSigningPropertyError( + "context", + signingProperties.context + ); + const config = throwSigningPropertyError("config", signingProperties.config); + const authScheme = context.endpointV2?.properties?.authSchemes?.[0]; + const signerFunction = throwSigningPropertyError( + "signer", + config.signer + ); + const signer = await signerFunction(authScheme); + const signingRegion = signingProperties?.signingRegion; + const signingRegionSet = signingProperties?.signingRegionSet; + const signingName = signingProperties?.signingName; + return { + config, + signer, + signingRegion, + signingRegionSet, + signingName + }; +}, "validateSigningProperties"); +var AwsSdkSigV4Signer = class { + static { + __name(this, "AwsSdkSigV4Signer"); + } + async sign(httpRequest, identity, signingProperties) { + if (!import_protocol_http2.HttpRequest.isInstance(httpRequest)) { + throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); + } + const validatedProps = await validateSigningProperties(signingProperties); + const { config, signer } = validatedProps; + let { signingRegion, signingName } = validatedProps; + const handlerExecutionContext = signingProperties.context; + if (handlerExecutionContext?.authSchemes?.length ?? 0 > 1) { + const [first, second] = handlerExecutionContext.authSchemes; + if (first?.name === "sigv4a" && second?.name === "sigv4") { + signingRegion = second?.signingRegion ?? signingRegion; + signingName = second?.signingName ?? signingName; + } + } + const signedRequest = await signer.sign(httpRequest, { + signingDate: getSkewCorrectedDate(config.systemClockOffset), + signingRegion, + signingService: signingName + }); + return signedRequest; + } + errorHandler(signingProperties) { + return (error) => { + const serverTime = error.ServerTime ?? getDateHeader(error.$response); + if (serverTime) { + const config = throwSigningPropertyError("config", signingProperties.config); + const initialSystemClockOffset = config.systemClockOffset; + config.systemClockOffset = getUpdatedSystemClockOffset(serverTime, config.systemClockOffset); + const clockSkewCorrected = config.systemClockOffset !== initialSystemClockOffset; + if (clockSkewCorrected && error.$metadata) { + error.$metadata.clockSkewCorrected = true; + } + } + throw error; + }; + } + successHandler(httpResponse, signingProperties) { + const dateHeader = getDateHeader(httpResponse); + if (dateHeader) { + const config = throwSigningPropertyError("config", signingProperties.config); + config.systemClockOffset = getUpdatedSystemClockOffset(dateHeader, config.systemClockOffset); + } + } +}; +var AWSSDKSigV4Signer = AwsSdkSigV4Signer; + +// src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.ts +var import_protocol_http3 = __nccwpck_require__(72356); +var AwsSdkSigV4ASigner = class extends AwsSdkSigV4Signer { + static { + __name(this, "AwsSdkSigV4ASigner"); + } + async sign(httpRequest, identity, signingProperties) { + if (!import_protocol_http3.HttpRequest.isInstance(httpRequest)) { + throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); + } + const { config, signer, signingRegion, signingRegionSet, signingName } = await validateSigningProperties( + signingProperties + ); + const configResolvedSigningRegionSet = await config.sigv4aSigningRegionSet?.(); + const multiRegionOverride = (configResolvedSigningRegionSet ?? signingRegionSet ?? [signingRegion]).join(","); + const signedRequest = await signer.sign(httpRequest, { + signingDate: getSkewCorrectedDate(config.systemClockOffset), + signingRegion: multiRegionOverride, + signingService: signingName + }); + return signedRequest; + } +}; + +// src/submodules/httpAuthSchemes/utils/getArrayForCommaSeparatedString.ts +var getArrayForCommaSeparatedString = /* @__PURE__ */ __name((str) => typeof str === "string" && str.length > 0 ? str.split(",").map((item) => item.trim()) : [], "getArrayForCommaSeparatedString"); + +// src/submodules/httpAuthSchemes/utils/getBearerTokenEnvKey.ts +var getBearerTokenEnvKey = /* @__PURE__ */ __name((signingName) => `AWS_BEARER_TOKEN_${signingName.replace(/[\s-]/g, "_").toUpperCase()}`, "getBearerTokenEnvKey"); + +// src/submodules/httpAuthSchemes/aws_sdk/NODE_AUTH_SCHEME_PREFERENCE_OPTIONS.ts +var NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY = "AWS_AUTH_SCHEME_PREFERENCE"; +var NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY = "auth_scheme_preference"; +var NODE_AUTH_SCHEME_PREFERENCE_OPTIONS = { + /** + * Retrieves auth scheme preference from environment variables + * @param env - Node process environment object + * @returns Array of auth scheme strings if preference is set, undefined otherwise + */ + environmentVariableSelector: /* @__PURE__ */ __name((env, options) => { + if (options?.signingName) { + const bearerTokenKey = getBearerTokenEnvKey(options.signingName); + if (bearerTokenKey in env) return ["httpBearerAuth"]; + } + if (!(NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY in env)) return void 0; + return getArrayForCommaSeparatedString(env[NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY]); + }, "environmentVariableSelector"), + /** + * Retrieves auth scheme preference from config file + * @param profile - Config profile object + * @returns Array of auth scheme strings if preference is set, undefined otherwise + */ + configFileSelector: /* @__PURE__ */ __name((profile) => { + if (!(NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY in profile)) return void 0; + return getArrayForCommaSeparatedString(profile[NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY]); + }, "configFileSelector"), + /** + * Default auth scheme preference if not specified in environment or config + */ + default: [] +}; + +// src/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4AConfig.ts +var import_core = __nccwpck_require__(90402); +var import_property_provider = __nccwpck_require__(71238); +var resolveAwsSdkSigV4AConfig = /* @__PURE__ */ __name((config) => { + config.sigv4aSigningRegionSet = (0, import_core.normalizeProvider)(config.sigv4aSigningRegionSet); + return config; +}, "resolveAwsSdkSigV4AConfig"); +var NODE_SIGV4A_CONFIG_OPTIONS = { + environmentVariableSelector(env) { + if (env.AWS_SIGV4A_SIGNING_REGION_SET) { + return env.AWS_SIGV4A_SIGNING_REGION_SET.split(",").map((_) => _.trim()); + } + throw new import_property_provider.ProviderError("AWS_SIGV4A_SIGNING_REGION_SET not set in env.", { + tryNextLink: true + }); + }, + configFileSelector(profile) { + if (profile.sigv4a_signing_region_set) { + return (profile.sigv4a_signing_region_set ?? "").split(",").map((_) => _.trim()); + } + throw new import_property_provider.ProviderError("sigv4a_signing_region_set not set in profile.", { + tryNextLink: true + }); + }, + default: void 0 +}; + +// src/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4Config.ts +var import_client = __nccwpck_require__(5152); +var import_core2 = __nccwpck_require__(90402); +var import_signature_v4 = __nccwpck_require__(75118); +var resolveAwsSdkSigV4Config = /* @__PURE__ */ __name((config) => { + let inputCredentials = config.credentials; + let isUserSupplied = !!config.credentials; + let resolvedCredentials = void 0; + Object.defineProperty(config, "credentials", { + set(credentials) { + if (credentials && credentials !== inputCredentials && credentials !== resolvedCredentials) { + isUserSupplied = true; + } + inputCredentials = credentials; + const memoizedProvider = normalizeCredentialProvider(config, { + credentials: inputCredentials, + credentialDefaultProvider: config.credentialDefaultProvider + }); + const boundProvider = bindCallerConfig(config, memoizedProvider); + if (isUserSupplied && !boundProvider.attributed) { + resolvedCredentials = /* @__PURE__ */ __name(async (options) => boundProvider(options).then( + (creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_CODE", "e") + ), "resolvedCredentials"); + resolvedCredentials.memoized = boundProvider.memoized; + resolvedCredentials.configBound = boundProvider.configBound; + resolvedCredentials.attributed = true; + } else { + resolvedCredentials = boundProvider; + } + }, + get() { + return resolvedCredentials; + }, + enumerable: true, + configurable: true + }); + config.credentials = inputCredentials; + const { + // Default for signingEscapePath + signingEscapePath = true, + // Default for systemClockOffset + systemClockOffset = config.systemClockOffset || 0, + // No default for sha256 since it is platform dependent + sha256 + } = config; + let signer; + if (config.signer) { + signer = (0, import_core2.normalizeProvider)(config.signer); + } else if (config.regionInfoProvider) { + signer = /* @__PURE__ */ __name(() => (0, import_core2.normalizeProvider)(config.region)().then( + async (region) => [ + await config.regionInfoProvider(region, { + useFipsEndpoint: await config.useFipsEndpoint(), + useDualstackEndpoint: await config.useDualstackEndpoint() + }) || {}, + region + ] + ).then(([regionInfo, region]) => { + const { signingRegion, signingService } = regionInfo; + config.signingRegion = config.signingRegion || signingRegion || region; + config.signingName = config.signingName || signingService || config.serviceId; + const params = { + ...config, + credentials: config.credentials, + region: config.signingRegion, + service: config.signingName, + sha256, + uriEscapePath: signingEscapePath + }; + const SignerCtor = config.signerConstructor || import_signature_v4.SignatureV4; + return new SignerCtor(params); + }), "signer"); + } else { + signer = /* @__PURE__ */ __name(async (authScheme) => { + authScheme = Object.assign( + {}, + { + name: "sigv4", + signingName: config.signingName || config.defaultSigningName, + signingRegion: await (0, import_core2.normalizeProvider)(config.region)(), + properties: {} + }, + authScheme + ); + const signingRegion = authScheme.signingRegion; + const signingService = authScheme.signingName; + config.signingRegion = config.signingRegion || signingRegion; + config.signingName = config.signingName || signingService || config.serviceId; + const params = { + ...config, + credentials: config.credentials, + region: config.signingRegion, + service: config.signingName, + sha256, + uriEscapePath: signingEscapePath + }; + const SignerCtor = config.signerConstructor || import_signature_v4.SignatureV4; + return new SignerCtor(params); + }, "signer"); + } + const resolvedConfig = Object.assign(config, { + systemClockOffset, + signingEscapePath, + signer + }); + return resolvedConfig; +}, "resolveAwsSdkSigV4Config"); +var resolveAWSSDKSigV4Config = resolveAwsSdkSigV4Config; +function normalizeCredentialProvider(config, { + credentials, + credentialDefaultProvider +}) { + let credentialsProvider; + if (credentials) { + if (!credentials?.memoized) { + credentialsProvider = (0, import_core2.memoizeIdentityProvider)(credentials, import_core2.isIdentityExpired, import_core2.doesIdentityRequireRefresh); + } else { + credentialsProvider = credentials; + } + } else { + if (credentialDefaultProvider) { + credentialsProvider = (0, import_core2.normalizeProvider)( + credentialDefaultProvider( + Object.assign({}, config, { + parentClientConfig: config + }) + ) + ); + } else { + credentialsProvider = /* @__PURE__ */ __name(async () => { + throw new Error( + "@aws-sdk/core::resolveAwsSdkSigV4Config - `credentials` not provided and no credentialDefaultProvider was configured." + ); + }, "credentialsProvider"); + } + } + credentialsProvider.memoized = true; + return credentialsProvider; +} +__name(normalizeCredentialProvider, "normalizeCredentialProvider"); +function bindCallerConfig(config, credentialsProvider) { + if (credentialsProvider.configBound) { + return credentialsProvider; + } + const fn = /* @__PURE__ */ __name(async (options) => credentialsProvider({ ...options, callerClientConfig: config }), "fn"); + fn.memoized = credentialsProvider.memoized; + fn.configBound = true; + return fn; +} +__name(bindCallerConfig, "bindCallerConfig"); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 37288: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/protocols/index.ts +var index_exports = {}; +__export(index_exports, { + AwsEc2QueryProtocol: () => AwsEc2QueryProtocol, + AwsJson1_0Protocol: () => AwsJson1_0Protocol, + AwsJson1_1Protocol: () => AwsJson1_1Protocol, + AwsJsonRpcProtocol: () => AwsJsonRpcProtocol, + AwsQueryProtocol: () => AwsQueryProtocol, + AwsRestJsonProtocol: () => AwsRestJsonProtocol, + AwsRestXmlProtocol: () => AwsRestXmlProtocol, + JsonCodec: () => JsonCodec, + JsonShapeDeserializer: () => JsonShapeDeserializer, + JsonShapeSerializer: () => JsonShapeSerializer, + XmlCodec: () => XmlCodec, + XmlShapeDeserializer: () => XmlShapeDeserializer, + XmlShapeSerializer: () => XmlShapeSerializer, + _toBool: () => _toBool, + _toNum: () => _toNum, + _toStr: () => _toStr, + awsExpectUnion: () => awsExpectUnion, + loadRestJsonErrorCode: () => loadRestJsonErrorCode, + loadRestXmlErrorCode: () => loadRestXmlErrorCode, + parseJsonBody: () => parseJsonBody, + parseJsonErrorBody: () => parseJsonErrorBody, + parseXmlBody: () => parseXmlBody, + parseXmlErrorBody: () => parseXmlErrorBody +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/protocols/coercing-serializers.ts +var _toStr = /* @__PURE__ */ __name((val) => { + if (val == null) { + return val; + } + if (typeof val === "number" || typeof val === "bigint") { + const warning = new Error(`Received number ${val} where a string was expected.`); + warning.name = "Warning"; + console.warn(warning); + return String(val); + } + if (typeof val === "boolean") { + const warning = new Error(`Received boolean ${val} where a string was expected.`); + warning.name = "Warning"; + console.warn(warning); + return String(val); + } + return val; +}, "_toStr"); +var _toBool = /* @__PURE__ */ __name((val) => { + if (val == null) { + return val; + } + if (typeof val === "number") { + } + if (typeof val === "string") { + const lowercase = val.toLowerCase(); + if (val !== "" && lowercase !== "false" && lowercase !== "true") { + const warning = new Error(`Received string "${val}" where a boolean was expected.`); + warning.name = "Warning"; + console.warn(warning); + } + return val !== "" && lowercase !== "false"; + } + return val; +}, "_toBool"); +var _toNum = /* @__PURE__ */ __name((val) => { + if (val == null) { + return val; + } + if (typeof val === "boolean") { + } + if (typeof val === "string") { + const num = Number(val); + if (num.toString() !== val) { + const warning = new Error(`Received string "${val}" where a number was expected.`); + warning.name = "Warning"; + console.warn(warning); + return val; + } + return num; + } + return val; +}, "_toNum"); + +// src/submodules/protocols/json/AwsJsonRpcProtocol.ts +var import_protocols = __nccwpck_require__(93422); +var import_schema3 = __nccwpck_require__(26890); +var import_util_body_length_browser = __nccwpck_require__(12098); + +// src/submodules/protocols/ConfigurableSerdeContext.ts +var SerdeContextConfig = class { + static { + __name(this, "SerdeContextConfig"); + } + serdeContext; + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + } +}; + +// src/submodules/protocols/json/JsonShapeDeserializer.ts +var import_schema = __nccwpck_require__(26890); +var import_serde2 = __nccwpck_require__(92430); +var import_util_base64 = __nccwpck_require__(68385); + +// src/submodules/protocols/json/jsonReviver.ts +var import_serde = __nccwpck_require__(92430); +function jsonReviver(key, value, context) { + if (context?.source) { + const numericString = context.source; + if (typeof value === "number") { + if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER || numericString !== String(value)) { + const isFractional = numericString.includes("."); + if (isFractional) { + return new import_serde.NumericValue(numericString, "bigDecimal"); + } else { + return BigInt(numericString); + } + } + } + } + return value; +} +__name(jsonReviver, "jsonReviver"); + +// src/submodules/protocols/common.ts +var import_smithy_client = __nccwpck_require__(61411); +var collectBodyString = /* @__PURE__ */ __name((streamBody, context) => (0, import_smithy_client.collectBody)(streamBody, context).then((body) => context.utf8Encoder(body)), "collectBodyString"); + +// src/submodules/protocols/json/parseJsonBody.ts +var parseJsonBody = /* @__PURE__ */ __name((streamBody, context) => collectBodyString(streamBody, context).then((encoded) => { + if (encoded.length) { + try { + return JSON.parse(encoded); + } catch (e) { + if (e?.name === "SyntaxError") { + Object.defineProperty(e, "$responseBodyText", { + value: encoded + }); + } + throw e; + } + } + return {}; +}), "parseJsonBody"); +var parseJsonErrorBody = /* @__PURE__ */ __name(async (errorBody, context) => { + const value = await parseJsonBody(errorBody, context); + value.message = value.message ?? value.Message; + return value; +}, "parseJsonErrorBody"); +var loadRestJsonErrorCode = /* @__PURE__ */ __name((output, data) => { + const findKey = /* @__PURE__ */ __name((object, key) => Object.keys(object).find((k) => k.toLowerCase() === key.toLowerCase()), "findKey"); + const sanitizeErrorCode = /* @__PURE__ */ __name((rawValue) => { + let cleanValue = rawValue; + if (typeof cleanValue === "number") { + cleanValue = cleanValue.toString(); + } + if (cleanValue.indexOf(",") >= 0) { + cleanValue = cleanValue.split(",")[0]; + } + if (cleanValue.indexOf(":") >= 0) { + cleanValue = cleanValue.split(":")[0]; + } + if (cleanValue.indexOf("#") >= 0) { + cleanValue = cleanValue.split("#")[1]; + } + return cleanValue; + }, "sanitizeErrorCode"); + const headerKey = findKey(output.headers, "x-amzn-errortype"); + if (headerKey !== void 0) { + return sanitizeErrorCode(output.headers[headerKey]); + } + if (data && typeof data === "object") { + const codeKey = findKey(data, "code"); + if (codeKey && data[codeKey] !== void 0) { + return sanitizeErrorCode(data[codeKey]); + } + if (data["__type"] !== void 0) { + return sanitizeErrorCode(data["__type"]); + } + } +}, "loadRestJsonErrorCode"); + +// src/submodules/protocols/json/JsonShapeDeserializer.ts +var JsonShapeDeserializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "JsonShapeDeserializer"); + } + async read(schema, data) { + return this._read( + schema, + typeof data === "string" ? JSON.parse(data, jsonReviver) : await parseJsonBody(data, this.serdeContext) + ); + } + readObject(schema, data) { + return this._read(schema, data); + } + _read(schema, value) { + const isObject = value !== null && typeof value === "object"; + const ns = import_schema.NormalizedSchema.of(schema); + if (ns.isListSchema() && Array.isArray(value)) { + const listMember = ns.getValueSchema(); + const out = []; + const sparse = !!ns.getMergedTraits().sparse; + for (const item of value) { + if (sparse || item != null) { + out.push(this._read(listMember, item)); + } + } + return out; + } else if (ns.isMapSchema() && isObject) { + const mapMember = ns.getValueSchema(); + const out = {}; + const sparse = !!ns.getMergedTraits().sparse; + for (const [_k, _v] of Object.entries(value)) { + if (sparse || _v != null) { + out[_k] = this._read(mapMember, _v); + } + } + return out; + } else if (ns.isStructSchema() && isObject) { + const out = {}; + for (const [memberName, memberSchema] of ns.structIterator()) { + const fromKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName; + const deserializedValue = this._read(memberSchema, value[fromKey]); + if (deserializedValue != null) { + out[memberName] = deserializedValue; + } + } + return out; + } + if (ns.isBlobSchema() && typeof value === "string") { + return (0, import_util_base64.fromBase64)(value); + } + const mediaType = ns.getMergedTraits().mediaType; + if (ns.isStringSchema() && typeof value === "string" && mediaType) { + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + return import_serde2.LazyJsonString.from(value); + } + } + if (ns.isTimestampSchema()) { + const options = this.settings.timestampFormat; + const format = options.useTrait ? ns.getSchema() === import_schema.SCHEMA.TIMESTAMP_DEFAULT ? options.default : ns.getSchema() ?? options.default : options.default; + switch (format) { + case import_schema.SCHEMA.TIMESTAMP_DATE_TIME: + return (0, import_serde2.parseRfc3339DateTimeWithOffset)(value); + case import_schema.SCHEMA.TIMESTAMP_HTTP_DATE: + return (0, import_serde2.parseRfc7231DateTime)(value); + case import_schema.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + return (0, import_serde2.parseEpochTimestamp)(value); + default: + console.warn("Missing timestamp format, parsing value with Date constructor:", value); + return new Date(value); + } + } + if (ns.isBigIntegerSchema() && (typeof value === "number" || typeof value === "string")) { + return BigInt(value); + } + if (ns.isBigDecimalSchema() && value != void 0) { + if (value instanceof import_serde2.NumericValue) { + return value; + } + return new import_serde2.NumericValue(String(value), "bigDecimal"); + } + if (ns.isNumericSchema() && typeof value === "string") { + switch (value) { + case "Infinity": + return Infinity; + case "-Infinity": + return -Infinity; + case "NaN": + return NaN; + } + } + return value; + } +}; + +// src/submodules/protocols/json/JsonShapeSerializer.ts +var import_schema2 = __nccwpck_require__(26890); +var import_serde4 = __nccwpck_require__(92430); +var import_serde5 = __nccwpck_require__(92430); + +// src/submodules/protocols/json/jsonReplacer.ts +var import_serde3 = __nccwpck_require__(92430); +var NUMERIC_CONTROL_CHAR = String.fromCharCode(925); +var JsonReplacer = class { + static { + __name(this, "JsonReplacer"); + } + /** + * Stores placeholder key to true serialized value lookup. + */ + values = /* @__PURE__ */ new Map(); + counter = 0; + stage = 0; + /** + * Creates a jsonReplacer function that reserves big integer and big decimal values + * for later replacement. + */ + createReplacer() { + if (this.stage === 1) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer already created."); + } + if (this.stage === 2) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer exhausted."); + } + this.stage = 1; + return (key, value) => { + if (value instanceof import_serde3.NumericValue) { + const v = `${NUMERIC_CONTROL_CHAR + +"nv" + this.counter++}_` + value.string; + this.values.set(`"${v}"`, value.string); + return v; + } + if (typeof value === "bigint") { + const s = value.toString(); + const v = `${NUMERIC_CONTROL_CHAR + "b" + this.counter++}_` + s; + this.values.set(`"${v}"`, s); + return v; + } + return value; + }; + } + /** + * Replaces placeholder keys with their true values. + */ + replaceInJson(json) { + if (this.stage === 0) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer not created yet."); + } + if (this.stage === 2) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer exhausted."); + } + this.stage = 2; + if (this.counter === 0) { + return json; + } + for (const [key, value] of this.values) { + json = json.replace(key, value); + } + return json; + } +}; + +// src/submodules/protocols/json/JsonShapeSerializer.ts +var JsonShapeSerializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "JsonShapeSerializer"); + } + buffer; + rootSchema; + write(schema, value) { + this.rootSchema = import_schema2.NormalizedSchema.of(schema); + this.buffer = this._write(this.rootSchema, value); + } + flush() { + if (this.rootSchema?.isStructSchema() || this.rootSchema?.isDocumentSchema()) { + const replacer = new JsonReplacer(); + return replacer.replaceInJson(JSON.stringify(this.buffer, replacer.createReplacer(), 0)); + } + return this.buffer; + } + _write(schema, value, container) { + const isObject = value !== null && typeof value === "object"; + const ns = import_schema2.NormalizedSchema.of(schema); + if (ns.isListSchema() && Array.isArray(value)) { + const listMember = ns.getValueSchema(); + const out = []; + const sparse = !!ns.getMergedTraits().sparse; + for (const item of value) { + if (sparse || item != null) { + out.push(this._write(listMember, item)); + } + } + return out; + } else if (ns.isMapSchema() && isObject) { + const mapMember = ns.getValueSchema(); + const out = {}; + const sparse = !!ns.getMergedTraits().sparse; + for (const [_k, _v] of Object.entries(value)) { + if (sparse || _v != null) { + out[_k] = this._write(mapMember, _v); + } + } + return out; + } else if (ns.isStructSchema() && isObject) { + const out = {}; + for (const [memberName, memberSchema] of ns.structIterator()) { + const targetKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName; + const serializableValue = this._write(memberSchema, value[memberName], ns); + if (serializableValue !== void 0) { + out[targetKey] = serializableValue; + } + } + return out; + } + if (value === null && container?.isStructSchema()) { + return void 0; + } + if (ns.isBlobSchema() && (value instanceof Uint8Array || typeof value === "string")) { + if (ns === this.rootSchema) { + return value; + } + if (!this.serdeContext?.base64Encoder) { + throw new Error("Missing base64Encoder in serdeContext"); + } + return this.serdeContext?.base64Encoder(value); + } + if (ns.isTimestampSchema() && value instanceof Date) { + const options = this.settings.timestampFormat; + const format = options.useTrait ? ns.getSchema() === import_schema2.SCHEMA.TIMESTAMP_DEFAULT ? options.default : ns.getSchema() ?? options.default : options.default; + switch (format) { + case import_schema2.SCHEMA.TIMESTAMP_DATE_TIME: + return value.toISOString().replace(".000Z", "Z"); + case import_schema2.SCHEMA.TIMESTAMP_HTTP_DATE: + return (0, import_serde4.dateToUtcString)(value); + case import_schema2.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + return value.getTime() / 1e3; + default: + console.warn("Missing timestamp format, using epoch seconds", value); + return value.getTime() / 1e3; + } + } + if (ns.isNumericSchema() && typeof value === "number") { + if (Math.abs(value) === Infinity || isNaN(value)) { + return String(value); + } + } + const mediaType = ns.getMergedTraits().mediaType; + if (ns.isStringSchema() && typeof value === "string" && mediaType) { + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + return import_serde5.LazyJsonString.from(value); + } + } + return value; + } +}; + +// src/submodules/protocols/json/JsonCodec.ts +var JsonCodec = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "JsonCodec"); + } + createSerializer() { + const serializer = new JsonShapeSerializer(this.settings); + serializer.setSerdeContext(this.serdeContext); + return serializer; + } + createDeserializer() { + const deserializer = new JsonShapeDeserializer(this.settings); + deserializer.setSerdeContext(this.serdeContext); + return deserializer; + } +}; + +// src/submodules/protocols/json/AwsJsonRpcProtocol.ts +var AwsJsonRpcProtocol = class extends import_protocols.RpcProtocol { + static { + __name(this, "AwsJsonRpcProtocol"); + } + serializer; + deserializer; + codec; + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + this.codec = new JsonCodec({ + timestampFormat: { + useTrait: true, + default: import_schema3.SCHEMA.TIMESTAMP_EPOCH_SECONDS + }, + jsonName: false + }); + this.serializer = this.codec.createSerializer(); + this.deserializer = this.codec.createDeserializer(); + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + if (!request.path.endsWith("/")) { + request.path += "/"; + } + Object.assign(request.headers, { + "content-type": `application/x-amz-json-${this.getJsonRpcVersion()}`, + "x-amz-target": (this.getJsonRpcVersion() === "1.0" ? `JsonRpc10.` : `JsonProtocol.`) + import_schema3.NormalizedSchema.of(operationSchema).getName() + }); + if ((0, import_schema3.deref)(operationSchema.input) === "unit" || !request.body) { + request.body = "{}"; + } + try { + request.headers["content-length"] = String((0, import_util_body_length_browser.calculateBodyLength)(request.body)); + } catch (e) { + } + return request; + } + getPayloadCodec() { + return this.codec; + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = loadRestJsonErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const registry = import_schema3.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.getSchema(errorIdentifier); + } catch (e) { + const baseExceptionSchema = import_schema3.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), dataObject); + } + throw new Error(errorName); + } + const ns = import_schema3.NormalizedSchema.of(errorSchema); + const message = dataObject.message ?? dataObject.Message ?? "Unknown"; + const exception = new errorSchema.ctor(message); + await this.deserializeHttpMessage(errorSchema, context, response, dataObject); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().jsonName ?? name; + output[name] = this.codec.createDeserializer().readObject(member, dataObject[target]); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } +}; + +// src/submodules/protocols/json/AwsJson1_0Protocol.ts +var AwsJson1_0Protocol = class extends AwsJsonRpcProtocol { + static { + __name(this, "AwsJson1_0Protocol"); + } + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + } + getShapeId() { + return "aws.protocols#awsJson1_0"; + } + getJsonRpcVersion() { + return "1.0"; + } +}; + +// src/submodules/protocols/json/AwsJson1_1Protocol.ts +var AwsJson1_1Protocol = class extends AwsJsonRpcProtocol { + static { + __name(this, "AwsJson1_1Protocol"); + } + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + } + getShapeId() { + return "aws.protocols#awsJson1_1"; + } + getJsonRpcVersion() { + return "1.1"; + } +}; + +// src/submodules/protocols/json/AwsRestJsonProtocol.ts +var import_protocols2 = __nccwpck_require__(93422); +var import_schema4 = __nccwpck_require__(26890); +var import_util_body_length_browser2 = __nccwpck_require__(12098); +var AwsRestJsonProtocol = class extends import_protocols2.HttpBindingProtocol { + static { + __name(this, "AwsRestJsonProtocol"); + } + serializer; + deserializer; + codec; + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + const settings = { + timestampFormat: { + useTrait: true, + default: import_schema4.SCHEMA.TIMESTAMP_EPOCH_SECONDS + }, + httpBindings: true, + jsonName: true + }; + this.codec = new JsonCodec(settings); + this.serializer = new import_protocols2.HttpInterceptingShapeSerializer(this.codec.createSerializer(), settings); + this.deserializer = new import_protocols2.HttpInterceptingShapeDeserializer(this.codec.createDeserializer(), settings); + } + getShapeId() { + return "aws.protocols#restJson1"; + } + getPayloadCodec() { + return this.codec; + } + setSerdeContext(serdeContext) { + this.codec.setSerdeContext(serdeContext); + super.setSerdeContext(serdeContext); + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + const inputSchema = import_schema4.NormalizedSchema.of(operationSchema.input); + const members = inputSchema.getMemberSchemas(); + if (!request.headers["content-type"]) { + const httpPayloadMember = Object.values(members).find((m) => { + return !!m.getMergedTraits().httpPayload; + }); + if (httpPayloadMember) { + const mediaType = httpPayloadMember.getMergedTraits().mediaType; + if (mediaType) { + request.headers["content-type"] = mediaType; + } else if (httpPayloadMember.isStringSchema()) { + request.headers["content-type"] = "text/plain"; + } else if (httpPayloadMember.isBlobSchema()) { + request.headers["content-type"] = "application/octet-stream"; + } else { + request.headers["content-type"] = "application/json"; + } + } else if (!inputSchema.isUnitSchema()) { + const hasBody = Object.values(members).find((m) => { + const { httpQuery, httpQueryParams, httpHeader, httpLabel, httpPrefixHeaders } = m.getMergedTraits(); + return !httpQuery && !httpQueryParams && !httpHeader && !httpLabel && httpPrefixHeaders === void 0; + }); + if (hasBody) { + request.headers["content-type"] = "application/json"; + } + } + } + if (request.headers["content-type"] && !request.body) { + request.body = "{}"; + } + if (request.body) { + try { + request.headers["content-length"] = String((0, import_util_body_length_browser2.calculateBodyLength)(request.body)); + } catch (e) { + } + } + return request; + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = loadRestJsonErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const registry = import_schema4.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.getSchema(errorIdentifier); + } catch (e) { + const baseExceptionSchema = import_schema4.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), dataObject); + } + throw new Error(errorName); + } + const ns = import_schema4.NormalizedSchema.of(errorSchema); + const message = dataObject.message ?? dataObject.Message ?? "Unknown"; + const exception = new errorSchema.ctor(message); + await this.deserializeHttpMessage(errorSchema, context, response, dataObject); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().jsonName ?? name; + output[name] = this.codec.createDeserializer().readObject(member, dataObject[target]); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } +}; + +// src/submodules/protocols/json/awsExpectUnion.ts +var import_smithy_client2 = __nccwpck_require__(61411); +var awsExpectUnion = /* @__PURE__ */ __name((value) => { + if (value == null) { + return void 0; + } + if (typeof value === "object" && "__type" in value) { + delete value.__type; + } + return (0, import_smithy_client2.expectUnion)(value); +}, "awsExpectUnion"); + +// src/submodules/protocols/query/AwsQueryProtocol.ts +var import_protocols5 = __nccwpck_require__(93422); +var import_schema7 = __nccwpck_require__(26890); +var import_util_body_length_browser3 = __nccwpck_require__(12098); + +// src/submodules/protocols/xml/XmlShapeDeserializer.ts +var import_protocols3 = __nccwpck_require__(93422); +var import_schema5 = __nccwpck_require__(26890); +var import_smithy_client3 = __nccwpck_require__(61411); +var import_util_utf8 = __nccwpck_require__(71577); +var import_fast_xml_parser = __nccwpck_require__(50591); +var XmlShapeDeserializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + this.stringDeserializer = new import_protocols3.FromStringShapeDeserializer(settings); + } + static { + __name(this, "XmlShapeDeserializer"); + } + stringDeserializer; + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + this.stringDeserializer.setSerdeContext(serdeContext); + } + /** + * @param schema - describing the data. + * @param bytes - serialized data. + * @param key - used by AwsQuery to step one additional depth into the object before reading it. + */ + read(schema, bytes, key) { + const ns = import_schema5.NormalizedSchema.of(schema); + const memberSchemas = ns.getMemberSchemas(); + const isEventPayload = ns.isStructSchema() && ns.isMemberSchema() && !!Object.values(memberSchemas).find((memberNs) => { + return !!memberNs.getMemberTraits().eventPayload; + }); + if (isEventPayload) { + const output = {}; + const memberName = Object.keys(memberSchemas)[0]; + const eventMemberSchema = memberSchemas[memberName]; + if (eventMemberSchema.isBlobSchema()) { + output[memberName] = bytes; + } else { + output[memberName] = this.read(memberSchemas[memberName], bytes); + } + return output; + } + const xmlString = (this.serdeContext?.utf8Encoder ?? import_util_utf8.toUtf8)(bytes); + const parsedObject = this.parseXml(xmlString); + return this.readSchema(schema, key ? parsedObject[key] : parsedObject); + } + readSchema(_schema, value) { + const ns = import_schema5.NormalizedSchema.of(_schema); + const traits = ns.getMergedTraits(); + if (ns.isListSchema() && !Array.isArray(value)) { + return this.readSchema(ns, [value]); + } + if (value == null) { + return value; + } + if (typeof value === "object") { + const sparse = !!traits.sparse; + const flat = !!traits.xmlFlattened; + if (ns.isListSchema()) { + const listValue = ns.getValueSchema(); + const buffer2 = []; + const sourceKey = listValue.getMergedTraits().xmlName ?? "member"; + const source = flat ? value : (value[0] ?? value)[sourceKey]; + const sourceArray = Array.isArray(source) ? source : [source]; + for (const v of sourceArray) { + if (v != null || sparse) { + buffer2.push(this.readSchema(listValue, v)); + } + } + return buffer2; + } + const buffer = {}; + if (ns.isMapSchema()) { + const keyNs = ns.getKeySchema(); + const memberNs = ns.getValueSchema(); + let entries; + if (flat) { + entries = Array.isArray(value) ? value : [value]; + } else { + entries = Array.isArray(value.entry) ? value.entry : [value.entry]; + } + const keyProperty = keyNs.getMergedTraits().xmlName ?? "key"; + const valueProperty = memberNs.getMergedTraits().xmlName ?? "value"; + for (const entry of entries) { + const key = entry[keyProperty]; + const value2 = entry[valueProperty]; + if (value2 != null || sparse) { + buffer[key] = this.readSchema(memberNs, value2); + } + } + return buffer; + } + if (ns.isStructSchema()) { + for (const [memberName, memberSchema] of ns.structIterator()) { + const memberTraits = memberSchema.getMergedTraits(); + const xmlObjectKey = !memberTraits.httpPayload ? memberSchema.getMemberTraits().xmlName ?? memberName : memberTraits.xmlName ?? memberSchema.getName(); + if (value[xmlObjectKey] != null) { + buffer[memberName] = this.readSchema(memberSchema, value[xmlObjectKey]); + } + } + return buffer; + } + if (ns.isDocumentSchema()) { + return value; + } + throw new Error(`@aws-sdk/core/protocols - xml deserializer unhandled schema type for ${ns.getName(true)}`); + } + if (ns.isListSchema()) { + return []; + } + if (ns.isMapSchema() || ns.isStructSchema()) { + return {}; + } + return this.stringDeserializer.read(ns, value); + } + parseXml(xml) { + if (xml.length) { + const parser = new import_fast_xml_parser.XMLParser({ + attributeNamePrefix: "", + htmlEntities: true, + ignoreAttributes: false, + ignoreDeclaration: true, + parseTagValue: false, + trimValues: false, + tagValueProcessor: /* @__PURE__ */ __name((_, val) => val.trim() === "" && val.includes("\n") ? "" : void 0, "tagValueProcessor") + }); + parser.addEntity("#xD", "\r"); + parser.addEntity("#10", "\n"); + let parsedObj; + try { + parsedObj = parser.parse(xml, true); + } catch (e) { + if (e && typeof e === "object") { + Object.defineProperty(e, "$responseBodyText", { + value: xml + }); + } + throw e; + } + const textNodeName = "#text"; + const key = Object.keys(parsedObj)[0]; + const parsedObjToReturn = parsedObj[key]; + if (parsedObjToReturn[textNodeName]) { + parsedObjToReturn[key] = parsedObjToReturn[textNodeName]; + delete parsedObjToReturn[textNodeName]; + } + return (0, import_smithy_client3.getValueFromTextNode)(parsedObjToReturn); + } + return {}; + } +}; + +// src/submodules/protocols/query/QueryShapeSerializer.ts +var import_protocols4 = __nccwpck_require__(93422); +var import_schema6 = __nccwpck_require__(26890); +var import_serde6 = __nccwpck_require__(92430); +var import_smithy_client4 = __nccwpck_require__(61411); +var import_util_base642 = __nccwpck_require__(68385); +var QueryShapeSerializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "QueryShapeSerializer"); + } + buffer; + write(schema, value, prefix = "") { + if (this.buffer === void 0) { + this.buffer = ""; + } + const ns = import_schema6.NormalizedSchema.of(schema); + if (prefix && !prefix.endsWith(".")) { + prefix += "."; + } + if (ns.isBlobSchema()) { + if (typeof value === "string" || value instanceof Uint8Array) { + this.writeKey(prefix); + this.writeValue((this.serdeContext?.base64Encoder ?? import_util_base642.toBase64)(value)); + } + } else if (ns.isBooleanSchema() || ns.isNumericSchema() || ns.isStringSchema()) { + if (value != null) { + this.writeKey(prefix); + this.writeValue(String(value)); + } + } else if (ns.isBigIntegerSchema()) { + if (value != null) { + this.writeKey(prefix); + this.writeValue(String(value)); + } + } else if (ns.isBigDecimalSchema()) { + if (value != null) { + this.writeKey(prefix); + this.writeValue(value instanceof import_serde6.NumericValue ? value.string : String(value)); + } + } else if (ns.isTimestampSchema()) { + if (value instanceof Date) { + this.writeKey(prefix); + const format = (0, import_protocols4.determineTimestampFormat)(ns, this.settings); + switch (format) { + case import_schema6.SCHEMA.TIMESTAMP_DATE_TIME: + this.writeValue(value.toISOString().replace(".000Z", "Z")); + break; + case import_schema6.SCHEMA.TIMESTAMP_HTTP_DATE: + this.writeValue((0, import_smithy_client4.dateToUtcString)(value)); + break; + case import_schema6.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + this.writeValue(String(value.getTime() / 1e3)); + break; + } + } + } else if (ns.isDocumentSchema()) { + throw new Error(`@aws-sdk/core/protocols - QuerySerializer unsupported document type ${ns.getName(true)}`); + } else if (ns.isListSchema()) { + if (Array.isArray(value)) { + if (value.length === 0) { + if (this.settings.serializeEmptyLists) { + this.writeKey(prefix); + this.writeValue(""); + } + } else { + const member = ns.getValueSchema(); + const flat = this.settings.flattenLists || ns.getMergedTraits().xmlFlattened; + let i = 1; + for (const item of value) { + if (item == null) { + continue; + } + const suffix = this.getKey("member", member.getMergedTraits().xmlName); + const key = flat ? `${prefix}${i}` : `${prefix}${suffix}.${i}`; + this.write(member, item, key); + ++i; + } + } + } + } else if (ns.isMapSchema()) { + if (value && typeof value === "object") { + const keySchema = ns.getKeySchema(); + const memberSchema = ns.getValueSchema(); + const flat = ns.getMergedTraits().xmlFlattened; + let i = 1; + for (const [k, v] of Object.entries(value)) { + if (v == null) { + continue; + } + const keySuffix = this.getKey("key", keySchema.getMergedTraits().xmlName); + const key = flat ? `${prefix}${i}.${keySuffix}` : `${prefix}entry.${i}.${keySuffix}`; + const valueSuffix = this.getKey("value", memberSchema.getMergedTraits().xmlName); + const valueKey = flat ? `${prefix}${i}.${valueSuffix}` : `${prefix}entry.${i}.${valueSuffix}`; + this.write(keySchema, k, key); + this.write(memberSchema, v, valueKey); + ++i; + } + } + } else if (ns.isStructSchema()) { + if (value && typeof value === "object") { + for (const [memberName, member] of ns.structIterator()) { + if (value[memberName] == null) { + continue; + } + const suffix = this.getKey(memberName, member.getMergedTraits().xmlName); + const key = `${prefix}${suffix}`; + this.write(member, value[memberName], key); + } + } + } else if (ns.isUnitSchema()) { + } else { + throw new Error(`@aws-sdk/core/protocols - QuerySerializer unrecognized schema type ${ns.getName(true)}`); + } + } + flush() { + if (this.buffer === void 0) { + throw new Error("@aws-sdk/core/protocols - QuerySerializer cannot flush with nothing written to buffer."); + } + const str = this.buffer; + delete this.buffer; + return str; + } + getKey(memberName, xmlName) { + const key = xmlName ?? memberName; + if (this.settings.capitalizeKeys) { + return key[0].toUpperCase() + key.slice(1); + } + return key; + } + writeKey(key) { + if (key.endsWith(".")) { + key = key.slice(0, key.length - 1); + } + this.buffer += `&${(0, import_protocols4.extendedEncodeURIComponent)(key)}=`; + } + writeValue(value) { + this.buffer += (0, import_protocols4.extendedEncodeURIComponent)(value); + } +}; + +// src/submodules/protocols/query/AwsQueryProtocol.ts +var AwsQueryProtocol = class extends import_protocols5.RpcProtocol { + constructor(options) { + super({ + defaultNamespace: options.defaultNamespace + }); + this.options = options; + const settings = { + timestampFormat: { + useTrait: true, + default: import_schema7.SCHEMA.TIMESTAMP_DATE_TIME + }, + httpBindings: false, + xmlNamespace: options.xmlNamespace, + serviceNamespace: options.defaultNamespace, + serializeEmptyLists: true + }; + this.serializer = new QueryShapeSerializer(settings); + this.deserializer = new XmlShapeDeserializer(settings); + } + static { + __name(this, "AwsQueryProtocol"); + } + serializer; + deserializer; + getShapeId() { + return "aws.protocols#awsQuery"; + } + setSerdeContext(serdeContext) { + this.serializer.setSerdeContext(serdeContext); + this.deserializer.setSerdeContext(serdeContext); + } + getPayloadCodec() { + throw new Error("AWSQuery protocol has no payload codec."); + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + if (!request.path.endsWith("/")) { + request.path += "/"; + } + Object.assign(request.headers, { + "content-type": `application/x-www-form-urlencoded` + }); + if ((0, import_schema7.deref)(operationSchema.input) === "unit" || !request.body) { + request.body = ""; + } + request.body = `Action=${operationSchema.name.split("#")[1]}&Version=${this.options.version}` + request.body; + if (request.body.endsWith("&")) { + request.body = request.body.slice(-1); + } + try { + request.headers["content-length"] = String((0, import_util_body_length_browser3.calculateBodyLength)(request.body)); + } catch (e) { + } + return request; + } + async deserializeResponse(operationSchema, context, response) { + const deserializer = this.deserializer; + const ns = import_schema7.NormalizedSchema.of(operationSchema.output); + const dataObject = {}; + if (response.statusCode >= 300) { + const bytes2 = await (0, import_protocols5.collectBody)(response.body, context); + if (bytes2.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(import_schema7.SCHEMA.DOCUMENT, bytes2)); + } + await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response)); + } + for (const header in response.headers) { + const value = response.headers[header]; + delete response.headers[header]; + response.headers[header.toLowerCase()] = value; + } + const awsQueryResultKey = ns.isStructSchema() && this.useNestedResult() ? operationSchema.name.split("#")[1] + "Result" : void 0; + const bytes = await (0, import_protocols5.collectBody)(response.body, context); + if (bytes.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(ns, bytes, awsQueryResultKey)); + } + const output = { + $metadata: this.deserializeMetadata(response), + ...dataObject + }; + return output; + } + /** + * EC2 Query overrides this. + */ + useNestedResult() { + return true; + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = this.loadQueryErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const errorDataSource = this.loadQueryError(dataObject); + const registry = import_schema7.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.find( + (schema) => import_schema7.NormalizedSchema.of(schema).getMergedTraits().awsQueryError?.[0] === errorName + ); + if (!errorSchema) { + errorSchema = registry.getSchema(errorIdentifier); + } + } catch (e) { + const baseExceptionSchema = import_schema7.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), errorDataSource); + } + throw new Error(errorName); + } + const ns = import_schema7.NormalizedSchema.of(errorSchema); + const message = this.loadQueryErrorMessage(dataObject); + const exception = new errorSchema.ctor(message); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().xmlName ?? name; + const value = errorDataSource[target] ?? dataObject[target]; + output[name] = this.deserializer.readSchema(member, value); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } + /** + * The variations in the error and error message locations are attributed to + * divergence between AWS Query and EC2 Query behavior. + */ + loadQueryErrorCode(output, data) { + const code = (data.Errors?.[0]?.Error ?? data.Errors?.Error ?? data.Error)?.Code; + if (code !== void 0) { + return code; + } + if (output.statusCode == 404) { + return "NotFound"; + } + } + loadQueryError(data) { + return data.Errors?.[0]?.Error ?? data.Errors?.Error ?? data.Error; + } + loadQueryErrorMessage(data) { + const errorData = this.loadQueryError(data); + return errorData?.message ?? errorData?.Message ?? data.message ?? data.Message ?? "Unknown"; + } +}; + +// src/submodules/protocols/query/AwsEc2QueryProtocol.ts +var AwsEc2QueryProtocol = class extends AwsQueryProtocol { + constructor(options) { + super(options); + this.options = options; + const ec2Settings = { + capitalizeKeys: true, + flattenLists: true, + serializeEmptyLists: false + }; + Object.assign(this.serializer.settings, ec2Settings); + } + static { + __name(this, "AwsEc2QueryProtocol"); + } + /** + * EC2 Query reads XResponse.XResult instead of XResponse directly. + */ + useNestedResult() { + return false; + } +}; + +// src/submodules/protocols/xml/AwsRestXmlProtocol.ts +var import_protocols6 = __nccwpck_require__(93422); +var import_schema9 = __nccwpck_require__(26890); +var import_util_body_length_browser4 = __nccwpck_require__(12098); + +// src/submodules/protocols/xml/parseXmlBody.ts +var import_smithy_client5 = __nccwpck_require__(61411); +var import_fast_xml_parser2 = __nccwpck_require__(50591); +var parseXmlBody = /* @__PURE__ */ __name((streamBody, context) => collectBodyString(streamBody, context).then((encoded) => { + if (encoded.length) { + const parser = new import_fast_xml_parser2.XMLParser({ + attributeNamePrefix: "", + htmlEntities: true, + ignoreAttributes: false, + ignoreDeclaration: true, + parseTagValue: false, + trimValues: false, + tagValueProcessor: /* @__PURE__ */ __name((_, val) => val.trim() === "" && val.includes("\n") ? "" : void 0, "tagValueProcessor") + }); + parser.addEntity("#xD", "\r"); + parser.addEntity("#10", "\n"); + let parsedObj; + try { + parsedObj = parser.parse(encoded, true); + } catch (e) { + if (e && typeof e === "object") { + Object.defineProperty(e, "$responseBodyText", { + value: encoded + }); + } + throw e; + } + const textNodeName = "#text"; + const key = Object.keys(parsedObj)[0]; + const parsedObjToReturn = parsedObj[key]; + if (parsedObjToReturn[textNodeName]) { + parsedObjToReturn[key] = parsedObjToReturn[textNodeName]; + delete parsedObjToReturn[textNodeName]; + } + return (0, import_smithy_client5.getValueFromTextNode)(parsedObjToReturn); + } + return {}; +}), "parseXmlBody"); +var parseXmlErrorBody = /* @__PURE__ */ __name(async (errorBody, context) => { + const value = await parseXmlBody(errorBody, context); + if (value.Error) { + value.Error.message = value.Error.message ?? value.Error.Message; + } + return value; +}, "parseXmlErrorBody"); +var loadRestXmlErrorCode = /* @__PURE__ */ __name((output, data) => { + if (data?.Error?.Code !== void 0) { + return data.Error.Code; + } + if (data?.Code !== void 0) { + return data.Code; + } + if (output.statusCode == 404) { + return "NotFound"; + } +}, "loadRestXmlErrorCode"); + +// src/submodules/protocols/xml/XmlShapeSerializer.ts +var import_xml_builder = __nccwpck_require__(94274); +var import_schema8 = __nccwpck_require__(26890); +var import_serde7 = __nccwpck_require__(92430); +var import_smithy_client6 = __nccwpck_require__(61411); +var import_util_base643 = __nccwpck_require__(68385); +var XmlShapeSerializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "XmlShapeSerializer"); + } + stringBuffer; + byteBuffer; + buffer; + write(schema, value) { + const ns = import_schema8.NormalizedSchema.of(schema); + if (ns.isStringSchema() && typeof value === "string") { + this.stringBuffer = value; + } else if (ns.isBlobSchema()) { + this.byteBuffer = "byteLength" in value ? value : (this.serdeContext?.base64Decoder ?? import_util_base643.fromBase64)(value); + } else { + this.buffer = this.writeStruct(ns, value, void 0); + const traits = ns.getMergedTraits(); + if (traits.httpPayload && !traits.xmlName) { + this.buffer.withName(ns.getName()); + } + } + } + flush() { + if (this.byteBuffer !== void 0) { + const bytes = this.byteBuffer; + delete this.byteBuffer; + return bytes; + } + if (this.stringBuffer !== void 0) { + const str = this.stringBuffer; + delete this.stringBuffer; + return str; + } + const buffer = this.buffer; + if (this.settings.xmlNamespace) { + if (!buffer?.attributes?.["xmlns"]) { + buffer.addAttribute("xmlns", this.settings.xmlNamespace); + } + } + delete this.buffer; + return buffer.toString(); + } + writeStruct(ns, value, parentXmlns) { + const traits = ns.getMergedTraits(); + const name = ns.isMemberSchema() && !traits.httpPayload ? ns.getMemberTraits().xmlName ?? ns.getMemberName() : traits.xmlName ?? ns.getName(); + if (!name || !ns.isStructSchema()) { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, cannot write struct with empty name or non-struct, schema=${ns.getName( + true + )}.` + ); + } + const structXmlNode = import_xml_builder.XmlNode.of(name); + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(ns, parentXmlns); + if (xmlns) { + structXmlNode.addAttribute(xmlnsAttr, xmlns); + } + for (const [memberName, memberSchema] of ns.structIterator()) { + const val = value[memberName]; + if (val != null) { + if (memberSchema.getMergedTraits().xmlAttribute) { + structXmlNode.addAttribute( + memberSchema.getMergedTraits().xmlName ?? memberName, + this.writeSimple(memberSchema, val) + ); + continue; + } + if (memberSchema.isListSchema()) { + this.writeList(memberSchema, val, structXmlNode, xmlns); + } else if (memberSchema.isMapSchema()) { + this.writeMap(memberSchema, val, structXmlNode, xmlns); + } else if (memberSchema.isStructSchema()) { + structXmlNode.addChildNode(this.writeStruct(memberSchema, val, xmlns)); + } else { + const memberNode = import_xml_builder.XmlNode.of(memberSchema.getMergedTraits().xmlName ?? memberSchema.getMemberName()); + this.writeSimpleInto(memberSchema, val, memberNode, xmlns); + structXmlNode.addChildNode(memberNode); + } + } + } + return structXmlNode; + } + writeList(listMember, array, container, parentXmlns) { + if (!listMember.isMemberSchema()) { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, cannot write non-member list: ${listMember.getName(true)}` + ); + } + const listTraits = listMember.getMergedTraits(); + const listValueSchema = listMember.getValueSchema(); + const listValueTraits = listValueSchema.getMergedTraits(); + const sparse = !!listValueTraits.sparse; + const flat = !!listTraits.xmlFlattened; + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(listMember, parentXmlns); + const writeItem = /* @__PURE__ */ __name((container2, value) => { + if (listValueSchema.isListSchema()) { + this.writeList(listValueSchema, Array.isArray(value) ? value : [value], container2, xmlns); + } else if (listValueSchema.isMapSchema()) { + this.writeMap(listValueSchema, value, container2, xmlns); + } else if (listValueSchema.isStructSchema()) { + const struct = this.writeStruct(listValueSchema, value, xmlns); + container2.addChildNode( + struct.withName(flat ? listTraits.xmlName ?? listMember.getMemberName() : listValueTraits.xmlName ?? "member") + ); + } else { + const listItemNode = import_xml_builder.XmlNode.of( + flat ? listTraits.xmlName ?? listMember.getMemberName() : listValueTraits.xmlName ?? "member" + ); + this.writeSimpleInto(listValueSchema, value, listItemNode, xmlns); + container2.addChildNode(listItemNode); + } + }, "writeItem"); + if (flat) { + for (const value of array) { + if (sparse || value != null) { + writeItem(container, value); + } + } + } else { + const listNode = import_xml_builder.XmlNode.of(listTraits.xmlName ?? listMember.getMemberName()); + if (xmlns) { + listNode.addAttribute(xmlnsAttr, xmlns); + } + for (const value of array) { + if (sparse || value != null) { + writeItem(listNode, value); + } + } + container.addChildNode(listNode); + } + } + writeMap(mapMember, map, container, parentXmlns, containerIsMap = false) { + if (!mapMember.isMemberSchema()) { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, cannot write non-member map: ${mapMember.getName(true)}` + ); + } + const mapTraits = mapMember.getMergedTraits(); + const mapKeySchema = mapMember.getKeySchema(); + const mapKeyTraits = mapKeySchema.getMergedTraits(); + const keyTag = mapKeyTraits.xmlName ?? "key"; + const mapValueSchema = mapMember.getValueSchema(); + const mapValueTraits = mapValueSchema.getMergedTraits(); + const valueTag = mapValueTraits.xmlName ?? "value"; + const sparse = !!mapValueTraits.sparse; + const flat = !!mapTraits.xmlFlattened; + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(mapMember, parentXmlns); + const addKeyValue = /* @__PURE__ */ __name((entry, key, val) => { + const keyNode = import_xml_builder.XmlNode.of(keyTag, key); + const [keyXmlnsAttr, keyXmlns] = this.getXmlnsAttribute(mapKeySchema, xmlns); + if (keyXmlns) { + keyNode.addAttribute(keyXmlnsAttr, keyXmlns); + } + entry.addChildNode(keyNode); + let valueNode = import_xml_builder.XmlNode.of(valueTag); + if (mapValueSchema.isListSchema()) { + this.writeList(mapValueSchema, val, valueNode, xmlns); + } else if (mapValueSchema.isMapSchema()) { + this.writeMap(mapValueSchema, val, valueNode, xmlns, true); + } else if (mapValueSchema.isStructSchema()) { + valueNode = this.writeStruct(mapValueSchema, val, xmlns); + } else { + this.writeSimpleInto(mapValueSchema, val, valueNode, xmlns); + } + entry.addChildNode(valueNode); + }, "addKeyValue"); + if (flat) { + for (const [key, val] of Object.entries(map)) { + if (sparse || val != null) { + const entry = import_xml_builder.XmlNode.of(mapTraits.xmlName ?? mapMember.getMemberName()); + addKeyValue(entry, key, val); + container.addChildNode(entry); + } + } + } else { + let mapNode; + if (!containerIsMap) { + mapNode = import_xml_builder.XmlNode.of(mapTraits.xmlName ?? mapMember.getMemberName()); + if (xmlns) { + mapNode.addAttribute(xmlnsAttr, xmlns); + } + container.addChildNode(mapNode); + } + for (const [key, val] of Object.entries(map)) { + if (sparse || val != null) { + const entry = import_xml_builder.XmlNode.of("entry"); + addKeyValue(entry, key, val); + (containerIsMap ? container : mapNode).addChildNode(entry); + } + } + } + } + writeSimple(_schema, value) { + if (null === value) { + throw new Error("@aws-sdk/core/protocols - (XML serializer) cannot write null value."); + } + const ns = import_schema8.NormalizedSchema.of(_schema); + let nodeContents = null; + if (value && typeof value === "object") { + if (ns.isBlobSchema()) { + nodeContents = (this.serdeContext?.base64Encoder ?? import_util_base643.toBase64)(value); + } else if (ns.isTimestampSchema() && value instanceof Date) { + const options = this.settings.timestampFormat; + const format = options.useTrait ? ns.getSchema() === import_schema8.SCHEMA.TIMESTAMP_DEFAULT ? options.default : ns.getSchema() ?? options.default : options.default; + switch (format) { + case import_schema8.SCHEMA.TIMESTAMP_DATE_TIME: + nodeContents = value.toISOString().replace(".000Z", "Z"); + break; + case import_schema8.SCHEMA.TIMESTAMP_HTTP_DATE: + nodeContents = (0, import_smithy_client6.dateToUtcString)(value); + break; + case import_schema8.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + nodeContents = String(value.getTime() / 1e3); + break; + default: + console.warn("Missing timestamp format, using http date", value); + nodeContents = (0, import_smithy_client6.dateToUtcString)(value); + break; + } + } else if (ns.isBigDecimalSchema() && value) { + if (value instanceof import_serde7.NumericValue) { + return value.string; + } + return String(value); + } else if (ns.isMapSchema() || ns.isListSchema()) { + throw new Error( + "@aws-sdk/core/protocols - xml serializer, cannot call _write() on List/Map schema, call writeList or writeMap() instead." + ); + } else { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, unhandled schema type for object value and schema: ${ns.getName( + true + )}` + ); + } + } + if (ns.isStringSchema() || ns.isBooleanSchema() || ns.isNumericSchema() || ns.isBigIntegerSchema() || ns.isBigDecimalSchema()) { + nodeContents = String(value); + } + if (nodeContents === null) { + throw new Error(`Unhandled schema-value pair ${ns.getName(true)}=${value}`); + } + return nodeContents; + } + writeSimpleInto(_schema, value, into, parentXmlns) { + const nodeContents = this.writeSimple(_schema, value); + const ns = import_schema8.NormalizedSchema.of(_schema); + const content = new import_xml_builder.XmlText(nodeContents); + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(ns, parentXmlns); + if (xmlns) { + into.addAttribute(xmlnsAttr, xmlns); + } + into.addChildNode(content); + } + getXmlnsAttribute(ns, parentXmlns) { + const traits = ns.getMergedTraits(); + const [prefix, xmlns] = traits.xmlNamespace ?? []; + if (xmlns && xmlns !== parentXmlns) { + return [prefix ? `xmlns:${prefix}` : "xmlns", xmlns]; + } + return [void 0, void 0]; + } +}; + +// src/submodules/protocols/xml/XmlCodec.ts +var XmlCodec = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "XmlCodec"); + } + createSerializer() { + const serializer = new XmlShapeSerializer(this.settings); + serializer.setSerdeContext(this.serdeContext); + return serializer; + } + createDeserializer() { + const deserializer = new XmlShapeDeserializer(this.settings); + deserializer.setSerdeContext(this.serdeContext); + return deserializer; + } +}; + +// src/submodules/protocols/xml/AwsRestXmlProtocol.ts +var AwsRestXmlProtocol = class extends import_protocols6.HttpBindingProtocol { + static { + __name(this, "AwsRestXmlProtocol"); + } + codec; + serializer; + deserializer; + constructor(options) { + super(options); + const settings = { + timestampFormat: { + useTrait: true, + default: import_schema9.SCHEMA.TIMESTAMP_DATE_TIME + }, + httpBindings: true, + xmlNamespace: options.xmlNamespace, + serviceNamespace: options.defaultNamespace + }; + this.codec = new XmlCodec(settings); + this.serializer = new import_protocols6.HttpInterceptingShapeSerializer(this.codec.createSerializer(), settings); + this.deserializer = new import_protocols6.HttpInterceptingShapeDeserializer(this.codec.createDeserializer(), settings); + } + getPayloadCodec() { + return this.codec; + } + getShapeId() { + return "aws.protocols#restXml"; + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + const ns = import_schema9.NormalizedSchema.of(operationSchema.input); + const members = ns.getMemberSchemas(); + request.path = String(request.path).split("/").filter((segment) => { + return segment !== "{Bucket}"; + }).join("/") || "/"; + if (!request.headers["content-type"]) { + const httpPayloadMember = Object.values(members).find((m) => { + return !!m.getMergedTraits().httpPayload; + }); + if (httpPayloadMember) { + const mediaType = httpPayloadMember.getMergedTraits().mediaType; + if (mediaType) { + request.headers["content-type"] = mediaType; + } else if (httpPayloadMember.isStringSchema()) { + request.headers["content-type"] = "text/plain"; + } else if (httpPayloadMember.isBlobSchema()) { + request.headers["content-type"] = "application/octet-stream"; + } else { + request.headers["content-type"] = "application/xml"; + } + } else if (!ns.isUnitSchema()) { + const hasBody = Object.values(members).find((m) => { + const { httpQuery, httpQueryParams, httpHeader, httpLabel, httpPrefixHeaders } = m.getMergedTraits(); + return !httpQuery && !httpQueryParams && !httpHeader && !httpLabel && httpPrefixHeaders === void 0; + }); + if (hasBody) { + request.headers["content-type"] = "application/xml"; + } + } + } + if (request.headers["content-type"] === "application/xml") { + if (typeof request.body === "string") { + request.body = '' + request.body; + } + } + if (request.body) { + try { + request.headers["content-length"] = String((0, import_util_body_length_browser4.calculateBodyLength)(request.body)); + } catch (e) { + } + } + return request; + } + async deserializeResponse(operationSchema, context, response) { + return super.deserializeResponse(operationSchema, context, response); + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = loadRestXmlErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const registry = import_schema9.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.getSchema(errorIdentifier); + } catch (e) { + const baseExceptionSchema = import_schema9.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), dataObject); + } + throw new Error(errorName); + } + const ns = import_schema9.NormalizedSchema.of(errorSchema); + const message = dataObject.Error?.message ?? dataObject.Error?.Message ?? dataObject.message ?? dataObject.Message ?? "Unknown"; + const exception = new errorSchema.ctor(message); + await this.deserializeHttpMessage(errorSchema, context, response, dataObject); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().xmlName ?? name; + const value = dataObject.Error?.[target] ?? dataObject[target]; + output[name] = this.codec.createDeserializer().readSchema(member, value); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 55606: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + ENV_ACCOUNT_ID: () => ENV_ACCOUNT_ID, + ENV_CREDENTIAL_SCOPE: () => ENV_CREDENTIAL_SCOPE, + ENV_EXPIRATION: () => ENV_EXPIRATION, + ENV_KEY: () => ENV_KEY, + ENV_SECRET: () => ENV_SECRET, + ENV_SESSION: () => ENV_SESSION, + fromEnv: () => fromEnv +}); +module.exports = __toCommonJS(index_exports); + +// src/fromEnv.ts +var import_client = __nccwpck_require__(5152); +var import_property_provider = __nccwpck_require__(71238); +var ENV_KEY = "AWS_ACCESS_KEY_ID"; +var ENV_SECRET = "AWS_SECRET_ACCESS_KEY"; +var ENV_SESSION = "AWS_SESSION_TOKEN"; +var ENV_EXPIRATION = "AWS_CREDENTIAL_EXPIRATION"; +var ENV_CREDENTIAL_SCOPE = "AWS_CREDENTIAL_SCOPE"; +var ENV_ACCOUNT_ID = "AWS_ACCOUNT_ID"; +var fromEnv = /* @__PURE__ */ __name((init) => async () => { + init?.logger?.debug("@aws-sdk/credential-provider-env - fromEnv"); + const accessKeyId = process.env[ENV_KEY]; + const secretAccessKey = process.env[ENV_SECRET]; + const sessionToken = process.env[ENV_SESSION]; + const expiry = process.env[ENV_EXPIRATION]; + const credentialScope = process.env[ENV_CREDENTIAL_SCOPE]; + const accountId = process.env[ENV_ACCOUNT_ID]; + if (accessKeyId && secretAccessKey) { + const credentials = { + accessKeyId, + secretAccessKey, + ...sessionToken && { sessionToken }, + ...expiry && { expiration: new Date(expiry) }, + ...credentialScope && { credentialScope }, + ...accountId && { accountId } + }; + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_ENV_VARS", "g"); + return credentials; + } + throw new import_property_provider.CredentialsProviderError("Unable to find environment variable credentials.", { logger: init?.logger }); +}, "fromEnv"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 1509: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkUrl = void 0; +const property_provider_1 = __nccwpck_require__(71238); +const LOOPBACK_CIDR_IPv4 = "127.0.0.0/8"; +const LOOPBACK_CIDR_IPv6 = "::1/128"; +const ECS_CONTAINER_HOST = "169.254.170.2"; +const EKS_CONTAINER_HOST_IPv4 = "169.254.170.23"; +const EKS_CONTAINER_HOST_IPv6 = "[fd00:ec2::23]"; +const checkUrl = (url, logger) => { + if (url.protocol === "https:") { + return; + } + if (url.hostname === ECS_CONTAINER_HOST || + url.hostname === EKS_CONTAINER_HOST_IPv4 || + url.hostname === EKS_CONTAINER_HOST_IPv6) { + return; + } + if (url.hostname.includes("[")) { + if (url.hostname === "[::1]" || url.hostname === "[0000:0000:0000:0000:0000:0000:0000:0001]") { + return; + } + } + else { + if (url.hostname === "localhost") { + return; + } + const ipComponents = url.hostname.split("."); + const inRange = (component) => { + const num = parseInt(component, 10); + return 0 <= num && num <= 255; + }; + if (ipComponents[0] === "127" && + inRange(ipComponents[1]) && + inRange(ipComponents[2]) && + inRange(ipComponents[3]) && + ipComponents.length === 4) { + return; + } + } + throw new property_provider_1.CredentialsProviderError(`URL not accepted. It must either be HTTPS or match one of the following: + - loopback CIDR 127.0.0.0/8 or [::1/128] + - ECS container host 169.254.170.2 + - EKS container host 169.254.170.23 or [fd00:ec2::23]`, { logger }); +}; +exports.checkUrl = checkUrl; + + +/***/ }), + +/***/ 68712: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromHttp = void 0; +const tslib_1 = __nccwpck_require__(61860); +const client_1 = __nccwpck_require__(5152); +const node_http_handler_1 = __nccwpck_require__(61279); +const property_provider_1 = __nccwpck_require__(71238); +const promises_1 = tslib_1.__importDefault(__nccwpck_require__(91943)); +const checkUrl_1 = __nccwpck_require__(1509); +const requestHelpers_1 = __nccwpck_require__(78914); +const retry_wrapper_1 = __nccwpck_require__(51122); +const AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"; +const DEFAULT_LINK_LOCAL_HOST = "http://169.254.170.2"; +const AWS_CONTAINER_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI"; +const AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE = "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE"; +const AWS_CONTAINER_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN"; +const fromHttp = (options = {}) => { + options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp"); + let host; + const relative = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI]; + const full = options.awsContainerCredentialsFullUri ?? process.env[AWS_CONTAINER_CREDENTIALS_FULL_URI]; + const token = options.awsContainerAuthorizationToken ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN]; + const tokenFile = options.awsContainerAuthorizationTokenFile ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE]; + const warn = options.logger?.constructor?.name === "NoOpLogger" || !options.logger ? console.warn : options.logger.warn; + if (relative && full) { + warn("@aws-sdk/credential-provider-http: " + + "you have set both awsContainerCredentialsRelativeUri and awsContainerCredentialsFullUri."); + warn("awsContainerCredentialsFullUri will take precedence."); + } + if (token && tokenFile) { + warn("@aws-sdk/credential-provider-http: " + + "you have set both awsContainerAuthorizationToken and awsContainerAuthorizationTokenFile."); + warn("awsContainerAuthorizationToken will take precedence."); + } + if (full) { + host = full; + } + else if (relative) { + host = `${DEFAULT_LINK_LOCAL_HOST}${relative}`; + } + else { + throw new property_provider_1.CredentialsProviderError(`No HTTP credential provider host provided. +Set AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.`, { logger: options.logger }); + } + const url = new URL(host); + (0, checkUrl_1.checkUrl)(url, options.logger); + const requestHandler = new node_http_handler_1.NodeHttpHandler({ + requestTimeout: options.timeout ?? 1000, + connectionTimeout: options.timeout ?? 1000, + }); + return (0, retry_wrapper_1.retryWrapper)(async () => { + const request = (0, requestHelpers_1.createGetRequest)(url); + if (token) { + request.headers.Authorization = token; + } + else if (tokenFile) { + request.headers.Authorization = (await promises_1.default.readFile(tokenFile)).toString(); + } + try { + const result = await requestHandler.handle(request); + return (0, requestHelpers_1.getCredentials)(result.response).then((creds) => (0, client_1.setCredentialFeature)(creds, "CREDENTIALS_HTTP", "z")); + } + catch (e) { + throw new property_provider_1.CredentialsProviderError(String(e), { logger: options.logger }); + } + }, options.maxRetries ?? 3, options.timeout ?? 1000); +}; +exports.fromHttp = fromHttp; + + +/***/ }), + +/***/ 78914: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createGetRequest = createGetRequest; +exports.getCredentials = getCredentials; +const property_provider_1 = __nccwpck_require__(71238); +const protocol_http_1 = __nccwpck_require__(72356); +const smithy_client_1 = __nccwpck_require__(61411); +const util_stream_1 = __nccwpck_require__(4252); +function createGetRequest(url) { + return new protocol_http_1.HttpRequest({ + protocol: url.protocol, + hostname: url.hostname, + port: Number(url.port), + path: url.pathname, + query: Array.from(url.searchParams.entries()).reduce((acc, [k, v]) => { + acc[k] = v; + return acc; + }, {}), + fragment: url.hash, + }); +} +async function getCredentials(response, logger) { + const stream = (0, util_stream_1.sdkStreamMixin)(response.body); + const str = await stream.transformToString(); + if (response.statusCode === 200) { + const parsed = JSON.parse(str); + if (typeof parsed.AccessKeyId !== "string" || + typeof parsed.SecretAccessKey !== "string" || + typeof parsed.Token !== "string" || + typeof parsed.Expiration !== "string") { + throw new property_provider_1.CredentialsProviderError("HTTP credential provider response not of the required format, an object matching: " + + "{ AccessKeyId: string, SecretAccessKey: string, Token: string, Expiration: string(rfc3339) }", { logger }); + } + return { + accessKeyId: parsed.AccessKeyId, + secretAccessKey: parsed.SecretAccessKey, + sessionToken: parsed.Token, + expiration: (0, smithy_client_1.parseRfc3339DateTime)(parsed.Expiration), + }; + } + if (response.statusCode >= 400 && response.statusCode < 500) { + let parsedBody = {}; + try { + parsedBody = JSON.parse(str); + } + catch (e) { } + throw Object.assign(new property_provider_1.CredentialsProviderError(`Server responded with status: ${response.statusCode}`, { logger }), { + Code: parsedBody.Code, + Message: parsedBody.Message, + }); + } + throw new property_provider_1.CredentialsProviderError(`Server responded with status: ${response.statusCode}`, { logger }); +} + + +/***/ }), + +/***/ 51122: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.retryWrapper = void 0; +const retryWrapper = (toRetry, maxRetries, delayMs) => { + return async () => { + for (let i = 0; i < maxRetries; ++i) { + try { + return await toRetry(); + } + catch (e) { + await new Promise((resolve) => setTimeout(resolve, delayMs)); + } + } + return await toRetry(); + }; +}; +exports.retryWrapper = retryWrapper; + + +/***/ }), + +/***/ 98605: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromHttp = void 0; +var fromHttp_1 = __nccwpck_require__(68712); +Object.defineProperty(exports, "fromHttp", ({ enumerable: true, get: function () { return fromHttp_1.fromHttp; } })); + + +/***/ }), + +/***/ 98250: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromIni: () => fromIni +}); +module.exports = __toCommonJS(index_exports); + +// src/fromIni.ts + + +// src/resolveProfileData.ts + + +// src/resolveAssumeRoleCredentials.ts + + +var import_shared_ini_file_loader = __nccwpck_require__(94964); + +// src/resolveCredentialSource.ts +var import_client = __nccwpck_require__(5152); +var import_property_provider = __nccwpck_require__(71238); +var resolveCredentialSource = /* @__PURE__ */ __name((credentialSource, profileName, logger) => { + const sourceProvidersMap = { + EcsContainer: /* @__PURE__ */ __name(async (options) => { + const { fromHttp } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(98605))); + const { fromContainerMetadata } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + logger?.debug("@aws-sdk/credential-provider-ini - credential_source is EcsContainer"); + return async () => (0, import_property_provider.chain)(fromHttp(options ?? {}), fromContainerMetadata(options))().then(setNamedProvider); + }, "EcsContainer"), + Ec2InstanceMetadata: /* @__PURE__ */ __name(async (options) => { + logger?.debug("@aws-sdk/credential-provider-ini - credential_source is Ec2InstanceMetadata"); + const { fromInstanceMetadata } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + return async () => fromInstanceMetadata(options)().then(setNamedProvider); + }, "Ec2InstanceMetadata"), + Environment: /* @__PURE__ */ __name(async (options) => { + logger?.debug("@aws-sdk/credential-provider-ini - credential_source is Environment"); + const { fromEnv } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(55606))); + return async () => fromEnv(options)().then(setNamedProvider); + }, "Environment") + }; + if (credentialSource in sourceProvidersMap) { + return sourceProvidersMap[credentialSource]; + } else { + throw new import_property_provider.CredentialsProviderError( + `Unsupported credential source in profile ${profileName}. Got ${credentialSource}, expected EcsContainer or Ec2InstanceMetadata or Environment.`, + { logger } + ); + } +}, "resolveCredentialSource"); +var setNamedProvider = /* @__PURE__ */ __name((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_NAMED_PROVIDER", "p"), "setNamedProvider"); + +// src/resolveAssumeRoleCredentials.ts +var isAssumeRoleProfile = /* @__PURE__ */ __name((arg, { profile = "default", logger } = {}) => { + return Boolean(arg) && typeof arg === "object" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1 && ["undefined", "string"].indexOf(typeof arg.external_id) > -1 && ["undefined", "string"].indexOf(typeof arg.mfa_serial) > -1 && (isAssumeRoleWithSourceProfile(arg, { profile, logger }) || isCredentialSourceProfile(arg, { profile, logger })); +}, "isAssumeRoleProfile"); +var isAssumeRoleWithSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger }) => { + const withSourceProfile = typeof arg.source_profile === "string" && typeof arg.credential_source === "undefined"; + if (withSourceProfile) { + logger?.debug?.(` ${profile} isAssumeRoleWithSourceProfile source_profile=${arg.source_profile}`); + } + return withSourceProfile; +}, "isAssumeRoleWithSourceProfile"); +var isCredentialSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger }) => { + const withProviderProfile = typeof arg.credential_source === "string" && typeof arg.source_profile === "undefined"; + if (withProviderProfile) { + logger?.debug?.(` ${profile} isCredentialSourceProfile credential_source=${arg.credential_source}`); + } + return withProviderProfile; +}, "isCredentialSourceProfile"); +var resolveAssumeRoleCredentials = /* @__PURE__ */ __name(async (profileName, profiles, options, visitedProfiles = {}) => { + options.logger?.debug("@aws-sdk/credential-provider-ini - resolveAssumeRoleCredentials (STS)"); + const profileData = profiles[profileName]; + const { source_profile, region } = profileData; + if (!options.roleAssumer) { + const { getDefaultRoleAssumer } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(1136))); + options.roleAssumer = getDefaultRoleAssumer( + { + ...options.clientConfig, + credentialProviderLogger: options.logger, + parentClientConfig: { + ...options?.parentClientConfig, + region: region ?? options?.parentClientConfig?.region + } + }, + options.clientPlugins + ); + } + if (source_profile && source_profile in visitedProfiles) { + throw new import_property_provider.CredentialsProviderError( + `Detected a cycle attempting to resolve credentials for profile ${(0, import_shared_ini_file_loader.getProfileName)(options)}. Profiles visited: ` + Object.keys(visitedProfiles).join(", "), + { logger: options.logger } + ); + } + options.logger?.debug( + `@aws-sdk/credential-provider-ini - finding credential resolver using ${source_profile ? `source_profile=[${source_profile}]` : `profile=[${profileName}]`}` + ); + const sourceCredsProvider = source_profile ? resolveProfileData( + source_profile, + profiles, + options, + { + ...visitedProfiles, + [source_profile]: true + }, + isCredentialSourceWithoutRoleArn(profiles[source_profile] ?? {}) + ) : (await resolveCredentialSource(profileData.credential_source, profileName, options.logger)(options))(); + if (isCredentialSourceWithoutRoleArn(profileData)) { + return sourceCredsProvider.then((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o")); + } else { + const params = { + RoleArn: profileData.role_arn, + RoleSessionName: profileData.role_session_name || `aws-sdk-js-${Date.now()}`, + ExternalId: profileData.external_id, + DurationSeconds: parseInt(profileData.duration_seconds || "3600", 10) + }; + const { mfa_serial } = profileData; + if (mfa_serial) { + if (!options.mfaCodeProvider) { + throw new import_property_provider.CredentialsProviderError( + `Profile ${profileName} requires multi-factor authentication, but no MFA code callback was provided.`, + { logger: options.logger, tryNextLink: false } + ); + } + params.SerialNumber = mfa_serial; + params.TokenCode = await options.mfaCodeProvider(mfa_serial); + } + const sourceCreds = await sourceCredsProvider; + return options.roleAssumer(sourceCreds, params).then( + (creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o") + ); + } +}, "resolveAssumeRoleCredentials"); +var isCredentialSourceWithoutRoleArn = /* @__PURE__ */ __name((section) => { + return !section.role_arn && !!section.credential_source; +}, "isCredentialSourceWithoutRoleArn"); + +// src/resolveProcessCredentials.ts + +var isProcessProfile = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.credential_process === "string", "isProcessProfile"); +var resolveProcessCredentials = /* @__PURE__ */ __name(async (options, profile) => Promise.resolve().then(() => __toESM(__nccwpck_require__(75360))).then( + ({ fromProcess }) => fromProcess({ + ...options, + profile + })().then((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_PROCESS", "v")) +), "resolveProcessCredentials"); + +// src/resolveSsoCredentials.ts + +var resolveSsoCredentials = /* @__PURE__ */ __name(async (profile, profileData, options = {}) => { + const { fromSSO } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(60998))); + return fromSSO({ + profile, + logger: options.logger, + parentClientConfig: options.parentClientConfig, + clientConfig: options.clientConfig + })().then((creds) => { + if (profileData.sso_session) { + return (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO", "r"); + } else { + return (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO_LEGACY", "t"); + } + }); +}, "resolveSsoCredentials"); +var isSsoProfile = /* @__PURE__ */ __name((arg) => arg && (typeof arg.sso_start_url === "string" || typeof arg.sso_account_id === "string" || typeof arg.sso_session === "string" || typeof arg.sso_region === "string" || typeof arg.sso_role_name === "string"), "isSsoProfile"); + +// src/resolveStaticCredentials.ts + +var isStaticCredsProfile = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.aws_access_key_id === "string" && typeof arg.aws_secret_access_key === "string" && ["undefined", "string"].indexOf(typeof arg.aws_session_token) > -1 && ["undefined", "string"].indexOf(typeof arg.aws_account_id) > -1, "isStaticCredsProfile"); +var resolveStaticCredentials = /* @__PURE__ */ __name(async (profile, options) => { + options?.logger?.debug("@aws-sdk/credential-provider-ini - resolveStaticCredentials"); + const credentials = { + accessKeyId: profile.aws_access_key_id, + secretAccessKey: profile.aws_secret_access_key, + sessionToken: profile.aws_session_token, + ...profile.aws_credential_scope && { credentialScope: profile.aws_credential_scope }, + ...profile.aws_account_id && { accountId: profile.aws_account_id } + }; + return (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_PROFILE", "n"); +}, "resolveStaticCredentials"); + +// src/resolveWebIdentityCredentials.ts + +var isWebIdentityProfile = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.web_identity_token_file === "string" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1, "isWebIdentityProfile"); +var resolveWebIdentityCredentials = /* @__PURE__ */ __name(async (profile, options) => Promise.resolve().then(() => __toESM(__nccwpck_require__(29956))).then( + ({ fromTokenFile }) => fromTokenFile({ + webIdentityTokenFile: profile.web_identity_token_file, + roleArn: profile.role_arn, + roleSessionName: profile.role_session_name, + roleAssumerWithWebIdentity: options.roleAssumerWithWebIdentity, + logger: options.logger, + parentClientConfig: options.parentClientConfig + })().then((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN", "q")) +), "resolveWebIdentityCredentials"); + +// src/resolveProfileData.ts +var resolveProfileData = /* @__PURE__ */ __name(async (profileName, profiles, options, visitedProfiles = {}, isAssumeRoleRecursiveCall = false) => { + const data = profiles[profileName]; + if (Object.keys(visitedProfiles).length > 0 && isStaticCredsProfile(data)) { + return resolveStaticCredentials(data, options); + } + if (isAssumeRoleRecursiveCall || isAssumeRoleProfile(data, { profile: profileName, logger: options.logger })) { + return resolveAssumeRoleCredentials(profileName, profiles, options, visitedProfiles); + } + if (isStaticCredsProfile(data)) { + return resolveStaticCredentials(data, options); + } + if (isWebIdentityProfile(data)) { + return resolveWebIdentityCredentials(data, options); + } + if (isProcessProfile(data)) { + return resolveProcessCredentials(options, profileName); + } + if (isSsoProfile(data)) { + return await resolveSsoCredentials(profileName, data, options); + } + throw new import_property_provider.CredentialsProviderError( + `Could not resolve credentials using profile: [${profileName}] in configuration/credentials file(s).`, + { logger: options.logger } + ); +}, "resolveProfileData"); + +// src/fromIni.ts +var fromIni = /* @__PURE__ */ __name((_init = {}) => async ({ callerClientConfig } = {}) => { + const init = { + ..._init, + parentClientConfig: { + ...callerClientConfig, + ..._init.parentClientConfig + } + }; + init.logger?.debug("@aws-sdk/credential-provider-ini - fromIni"); + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + return resolveProfileData( + (0, import_shared_ini_file_loader.getProfileName)({ + profile: _init.profile ?? callerClientConfig?.profile + }), + profiles, + init + ); +}, "fromIni"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 5861: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + credentialsTreatedAsExpired: () => credentialsTreatedAsExpired, + credentialsWillNeedRefresh: () => credentialsWillNeedRefresh, + defaultProvider: () => defaultProvider +}); +module.exports = __toCommonJS(index_exports); + +// src/defaultProvider.ts +var import_credential_provider_env = __nccwpck_require__(55606); + +var import_shared_ini_file_loader = __nccwpck_require__(94964); + +// src/remoteProvider.ts +var import_property_provider = __nccwpck_require__(71238); +var ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED"; +var remoteProvider = /* @__PURE__ */ __name(async (init) => { + const { ENV_CMDS_FULL_URI, ENV_CMDS_RELATIVE_URI, fromContainerMetadata, fromInstanceMetadata } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + if (process.env[ENV_CMDS_RELATIVE_URI] || process.env[ENV_CMDS_FULL_URI]) { + init.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromHttp/fromContainerMetadata"); + const { fromHttp } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(98605))); + return (0, import_property_provider.chain)(fromHttp(init), fromContainerMetadata(init)); + } + if (process.env[ENV_IMDS_DISABLED] && process.env[ENV_IMDS_DISABLED] !== "false") { + return async () => { + throw new import_property_provider.CredentialsProviderError("EC2 Instance Metadata Service access disabled", { logger: init.logger }); + }; + } + init.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromInstanceMetadata"); + return fromInstanceMetadata(init); +}, "remoteProvider"); + +// src/defaultProvider.ts +var multipleCredentialSourceWarningEmitted = false; +var defaultProvider = /* @__PURE__ */ __name((init = {}) => (0, import_property_provider.memoize)( + (0, import_property_provider.chain)( + async () => { + const profile = init.profile ?? process.env[import_shared_ini_file_loader.ENV_PROFILE]; + if (profile) { + const envStaticCredentialsAreSet = process.env[import_credential_provider_env.ENV_KEY] && process.env[import_credential_provider_env.ENV_SECRET]; + if (envStaticCredentialsAreSet) { + if (!multipleCredentialSourceWarningEmitted) { + const warnFn = init.logger?.warn && init.logger?.constructor?.name !== "NoOpLogger" ? init.logger.warn : console.warn; + warnFn( + `@aws-sdk/credential-provider-node - defaultProvider::fromEnv WARNING: + Multiple credential sources detected: + Both AWS_PROFILE and the pair AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY static credentials are set. + This SDK will proceed with the AWS_PROFILE value. + + However, a future version may change this behavior to prefer the ENV static credentials. + Please ensure that your environment only sets either the AWS_PROFILE or the + AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY pair. +` + ); + multipleCredentialSourceWarningEmitted = true; + } + } + throw new import_property_provider.CredentialsProviderError("AWS_PROFILE is set, skipping fromEnv provider.", { + logger: init.logger, + tryNextLink: true + }); + } + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromEnv"); + return (0, import_credential_provider_env.fromEnv)(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromSSO"); + const { ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoSession } = init; + if (!ssoStartUrl && !ssoAccountId && !ssoRegion && !ssoRoleName && !ssoSession) { + throw new import_property_provider.CredentialsProviderError( + "Skipping SSO provider in default chain (inputs do not include SSO fields).", + { logger: init.logger } + ); + } + const { fromSSO } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(60998))); + return fromSSO(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromIni"); + const { fromIni } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(98250))); + return fromIni(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromProcess"); + const { fromProcess } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(75360))); + return fromProcess(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromTokenFile"); + const { fromTokenFile } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(29956))); + return fromTokenFile(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::remoteProvider"); + return (await remoteProvider(init))(); + }, + async () => { + throw new import_property_provider.CredentialsProviderError("Could not load credentials from any providers", { + tryNextLink: false, + logger: init.logger + }); + } + ), + credentialsTreatedAsExpired, + credentialsWillNeedRefresh +), "defaultProvider"); +var credentialsWillNeedRefresh = /* @__PURE__ */ __name((credentials) => credentials?.expiration !== void 0, "credentialsWillNeedRefresh"); +var credentialsTreatedAsExpired = /* @__PURE__ */ __name((credentials) => credentials?.expiration !== void 0 && credentials.expiration.getTime() - Date.now() < 3e5, "credentialsTreatedAsExpired"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 75360: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromProcess: () => fromProcess +}); +module.exports = __toCommonJS(index_exports); + +// src/fromProcess.ts +var import_shared_ini_file_loader = __nccwpck_require__(94964); + +// src/resolveProcessCredentials.ts +var import_property_provider = __nccwpck_require__(71238); +var import_child_process = __nccwpck_require__(35317); +var import_util = __nccwpck_require__(39023); + +// src/getValidatedProcessCredentials.ts +var import_client = __nccwpck_require__(5152); +var getValidatedProcessCredentials = /* @__PURE__ */ __name((profileName, data, profiles) => { + if (data.Version !== 1) { + throw Error(`Profile ${profileName} credential_process did not return Version 1.`); + } + if (data.AccessKeyId === void 0 || data.SecretAccessKey === void 0) { + throw Error(`Profile ${profileName} credential_process returned invalid credentials.`); + } + if (data.Expiration) { + const currentTime = /* @__PURE__ */ new Date(); + const expireTime = new Date(data.Expiration); + if (expireTime < currentTime) { + throw Error(`Profile ${profileName} credential_process returned expired credentials.`); + } + } + let accountId = data.AccountId; + if (!accountId && profiles?.[profileName]?.aws_account_id) { + accountId = profiles[profileName].aws_account_id; + } + const credentials = { + accessKeyId: data.AccessKeyId, + secretAccessKey: data.SecretAccessKey, + ...data.SessionToken && { sessionToken: data.SessionToken }, + ...data.Expiration && { expiration: new Date(data.Expiration) }, + ...data.CredentialScope && { credentialScope: data.CredentialScope }, + ...accountId && { accountId } + }; + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_PROCESS", "w"); + return credentials; +}, "getValidatedProcessCredentials"); + +// src/resolveProcessCredentials.ts +var resolveProcessCredentials = /* @__PURE__ */ __name(async (profileName, profiles, logger) => { + const profile = profiles[profileName]; + if (profiles[profileName]) { + const credentialProcess = profile["credential_process"]; + if (credentialProcess !== void 0) { + const execPromise = (0, import_util.promisify)(import_child_process.exec); + try { + const { stdout } = await execPromise(credentialProcess); + let data; + try { + data = JSON.parse(stdout.trim()); + } catch { + throw Error(`Profile ${profileName} credential_process returned invalid JSON.`); + } + return getValidatedProcessCredentials(profileName, data, profiles); + } catch (error) { + throw new import_property_provider.CredentialsProviderError(error.message, { logger }); + } + } else { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} did not contain credential_process.`, { logger }); + } + } else { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} could not be found in shared credentials file.`, { + logger + }); + } +}, "resolveProcessCredentials"); + +// src/fromProcess.ts +var fromProcess = /* @__PURE__ */ __name((init = {}) => async ({ callerClientConfig } = {}) => { + init.logger?.debug("@aws-sdk/credential-provider-process - fromProcess"); + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + return resolveProcessCredentials( + (0, import_shared_ini_file_loader.getProfileName)({ + profile: init.profile ?? callerClientConfig?.profile + }), + profiles, + init.logger + ); +}, "fromProcess"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 60998: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __esm = (fn, res) => function __init() { + return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/loadSso.ts +var loadSso_exports = {}; +__export(loadSso_exports, { + GetRoleCredentialsCommand: () => import_client_sso.GetRoleCredentialsCommand, + SSOClient: () => import_client_sso.SSOClient +}); +var import_client_sso; +var init_loadSso = __esm({ + "src/loadSso.ts"() { + "use strict"; + import_client_sso = __nccwpck_require__(62054); + } +}); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromSSO: () => fromSSO, + isSsoProfile: () => isSsoProfile, + validateSsoProfile: () => validateSsoProfile +}); +module.exports = __toCommonJS(index_exports); + +// src/fromSSO.ts + + + +// src/isSsoProfile.ts +var isSsoProfile = /* @__PURE__ */ __name((arg) => arg && (typeof arg.sso_start_url === "string" || typeof arg.sso_account_id === "string" || typeof arg.sso_session === "string" || typeof arg.sso_region === "string" || typeof arg.sso_role_name === "string"), "isSsoProfile"); + +// src/resolveSSOCredentials.ts +var import_client = __nccwpck_require__(5152); +var import_token_providers = __nccwpck_require__(75433); +var import_property_provider = __nccwpck_require__(71238); +var import_shared_ini_file_loader = __nccwpck_require__(94964); +var SHOULD_FAIL_CREDENTIAL_CHAIN = false; +var resolveSSOCredentials = /* @__PURE__ */ __name(async ({ + ssoStartUrl, + ssoSession, + ssoAccountId, + ssoRegion, + ssoRoleName, + ssoClient, + clientConfig, + parentClientConfig, + profile, + logger +}) => { + let token; + const refreshMessage = `To refresh this SSO session run aws sso login with the corresponding profile.`; + if (ssoSession) { + try { + const _token = await (0, import_token_providers.fromSso)({ profile })(); + token = { + accessToken: _token.token, + expiresAt: new Date(_token.expiration).toISOString() + }; + } catch (e) { + throw new import_property_provider.CredentialsProviderError(e.message, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + } else { + try { + token = await (0, import_shared_ini_file_loader.getSSOTokenFromFile)(ssoStartUrl); + } catch (e) { + throw new import_property_provider.CredentialsProviderError(`The SSO session associated with this profile is invalid. ${refreshMessage}`, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + } + if (new Date(token.expiresAt).getTime() - Date.now() <= 0) { + throw new import_property_provider.CredentialsProviderError(`The SSO session associated with this profile has expired. ${refreshMessage}`, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + const { accessToken } = token; + const { SSOClient: SSOClient2, GetRoleCredentialsCommand: GetRoleCredentialsCommand2 } = await Promise.resolve().then(() => (init_loadSso(), loadSso_exports)); + const sso = ssoClient || new SSOClient2( + Object.assign({}, clientConfig ?? {}, { + logger: clientConfig?.logger ?? parentClientConfig?.logger, + region: clientConfig?.region ?? ssoRegion + }) + ); + let ssoResp; + try { + ssoResp = await sso.send( + new GetRoleCredentialsCommand2({ + accountId: ssoAccountId, + roleName: ssoRoleName, + accessToken + }) + ); + } catch (e) { + throw new import_property_provider.CredentialsProviderError(e, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + const { + roleCredentials: { accessKeyId, secretAccessKey, sessionToken, expiration, credentialScope, accountId } = {} + } = ssoResp; + if (!accessKeyId || !secretAccessKey || !sessionToken || !expiration) { + throw new import_property_provider.CredentialsProviderError("SSO returns an invalid temporary credential.", { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + const credentials = { + accessKeyId, + secretAccessKey, + sessionToken, + expiration: new Date(expiration), + ...credentialScope && { credentialScope }, + ...accountId && { accountId } + }; + if (ssoSession) { + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_SSO", "s"); + } else { + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_SSO_LEGACY", "u"); + } + return credentials; +}, "resolveSSOCredentials"); + +// src/validateSsoProfile.ts + +var validateSsoProfile = /* @__PURE__ */ __name((profile, logger) => { + const { sso_start_url, sso_account_id, sso_region, sso_role_name } = profile; + if (!sso_start_url || !sso_account_id || !sso_region || !sso_role_name) { + throw new import_property_provider.CredentialsProviderError( + `Profile is configured with invalid SSO credentials. Required parameters "sso_account_id", "sso_region", "sso_role_name", "sso_start_url". Got ${Object.keys(profile).join( + ", " + )} +Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html`, + { tryNextLink: false, logger } + ); + } + return profile; +}, "validateSsoProfile"); + +// src/fromSSO.ts +var fromSSO = /* @__PURE__ */ __name((init = {}) => async ({ callerClientConfig } = {}) => { + init.logger?.debug("@aws-sdk/credential-provider-sso - fromSSO"); + const { ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoSession } = init; + const { ssoClient } = init; + const profileName = (0, import_shared_ini_file_loader.getProfileName)({ + profile: init.profile ?? callerClientConfig?.profile + }); + if (!ssoStartUrl && !ssoAccountId && !ssoRegion && !ssoRoleName && !ssoSession) { + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + const profile = profiles[profileName]; + if (!profile) { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} was not found.`, { logger: init.logger }); + } + if (!isSsoProfile(profile)) { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} is not configured with SSO credentials.`, { + logger: init.logger + }); + } + if (profile?.sso_session) { + const ssoSessions = await (0, import_shared_ini_file_loader.loadSsoSessionData)(init); + const session = ssoSessions[profile.sso_session]; + const conflictMsg = ` configurations in profile ${profileName} and sso-session ${profile.sso_session}`; + if (ssoRegion && ssoRegion !== session.sso_region) { + throw new import_property_provider.CredentialsProviderError(`Conflicting SSO region` + conflictMsg, { + tryNextLink: false, + logger: init.logger + }); + } + if (ssoStartUrl && ssoStartUrl !== session.sso_start_url) { + throw new import_property_provider.CredentialsProviderError(`Conflicting SSO start_url` + conflictMsg, { + tryNextLink: false, + logger: init.logger + }); + } + profile.sso_region = session.sso_region; + profile.sso_start_url = session.sso_start_url; + } + const { sso_start_url, sso_account_id, sso_region, sso_role_name, sso_session } = validateSsoProfile( + profile, + init.logger + ); + return resolveSSOCredentials({ + ssoStartUrl: sso_start_url, + ssoSession: sso_session, + ssoAccountId: sso_account_id, + ssoRegion: sso_region, + ssoRoleName: sso_role_name, + ssoClient, + clientConfig: init.clientConfig, + parentClientConfig: init.parentClientConfig, + profile: profileName + }); + } else if (!ssoStartUrl || !ssoAccountId || !ssoRegion || !ssoRoleName) { + throw new import_property_provider.CredentialsProviderError( + 'Incomplete configuration. The fromSSO() argument hash must include "ssoStartUrl", "ssoAccountId", "ssoRegion", "ssoRoleName"', + { tryNextLink: false, logger: init.logger } + ); + } else { + return resolveSSOCredentials({ + ssoStartUrl, + ssoSession, + ssoAccountId, + ssoRegion, + ssoRoleName, + ssoClient, + clientConfig: init.clientConfig, + parentClientConfig: init.parentClientConfig, + profile: profileName + }); + } +}, "fromSSO"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 88079: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromTokenFile = void 0; +const client_1 = __nccwpck_require__(5152); +const property_provider_1 = __nccwpck_require__(71238); +const fs_1 = __nccwpck_require__(79896); +const fromWebToken_1 = __nccwpck_require__(34453); +const ENV_TOKEN_FILE = "AWS_WEB_IDENTITY_TOKEN_FILE"; +const ENV_ROLE_ARN = "AWS_ROLE_ARN"; +const ENV_ROLE_SESSION_NAME = "AWS_ROLE_SESSION_NAME"; +const fromTokenFile = (init = {}) => async () => { + init.logger?.debug("@aws-sdk/credential-provider-web-identity - fromTokenFile"); + const webIdentityTokenFile = init?.webIdentityTokenFile ?? process.env[ENV_TOKEN_FILE]; + const roleArn = init?.roleArn ?? process.env[ENV_ROLE_ARN]; + const roleSessionName = init?.roleSessionName ?? process.env[ENV_ROLE_SESSION_NAME]; + if (!webIdentityTokenFile || !roleArn) { + throw new property_provider_1.CredentialsProviderError("Web identity configuration not specified", { + logger: init.logger, + }); + } + const credentials = await (0, fromWebToken_1.fromWebToken)({ + ...init, + webIdentityToken: (0, fs_1.readFileSync)(webIdentityTokenFile, { encoding: "ascii" }), + roleArn, + roleSessionName, + })(); + if (webIdentityTokenFile === process.env[ENV_TOKEN_FILE]) { + (0, client_1.setCredentialFeature)(credentials, "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN", "h"); + } + return credentials; +}; +exports.fromTokenFile = fromTokenFile; + + +/***/ }), + +/***/ 34453: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromWebToken = void 0; +const fromWebToken = (init) => async (awsIdentityProperties) => { + init.logger?.debug("@aws-sdk/credential-provider-web-identity - fromWebToken"); + const { roleArn, roleSessionName, webIdentityToken, providerId, policyArns, policy, durationSeconds } = init; + let { roleAssumerWithWebIdentity } = init; + if (!roleAssumerWithWebIdentity) { + const { getDefaultRoleAssumerWithWebIdentity } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(1136))); + roleAssumerWithWebIdentity = getDefaultRoleAssumerWithWebIdentity({ + ...init.clientConfig, + credentialProviderLogger: init.logger, + parentClientConfig: { + ...awsIdentityProperties?.callerClientConfig, + ...init.parentClientConfig, + }, + }, init.clientPlugins); + } + return roleAssumerWithWebIdentity({ + RoleArn: roleArn, + RoleSessionName: roleSessionName ?? `aws-sdk-js-session-${Date.now()}`, + WebIdentityToken: webIdentityToken, + ProviderId: providerId, + PolicyArns: policyArns, + Policy: policy, + DurationSeconds: durationSeconds, + }); +}; +exports.fromWebToken = fromWebToken; + + +/***/ }), + +/***/ 29956: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +module.exports = __toCommonJS(index_exports); +__reExport(index_exports, __nccwpck_require__(88079), module.exports); +__reExport(index_exports, __nccwpck_require__(34453), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 26518: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_DISABLE_MULTIREGION_ACCESS_POINT_CONFIG_OPTIONS: () => NODE_DISABLE_MULTIREGION_ACCESS_POINT_CONFIG_OPTIONS, + NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME: () => NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME, + NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME: () => NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME, + NODE_USE_ARN_REGION_CONFIG_OPTIONS: () => NODE_USE_ARN_REGION_CONFIG_OPTIONS, + NODE_USE_ARN_REGION_ENV_NAME: () => NODE_USE_ARN_REGION_ENV_NAME, + NODE_USE_ARN_REGION_INI_NAME: () => NODE_USE_ARN_REGION_INI_NAME, + bucketEndpointMiddleware: () => bucketEndpointMiddleware, + bucketEndpointMiddlewareOptions: () => bucketEndpointMiddlewareOptions, + bucketHostname: () => bucketHostname, + getArnResources: () => getArnResources, + getBucketEndpointPlugin: () => getBucketEndpointPlugin, + getSuffixForArnEndpoint: () => getSuffixForArnEndpoint, + resolveBucketEndpointConfig: () => resolveBucketEndpointConfig, + validateAccountId: () => validateAccountId, + validateDNSHostLabel: () => validateDNSHostLabel, + validateNoDualstack: () => validateNoDualstack, + validateNoFIPS: () => validateNoFIPS, + validateOutpostService: () => validateOutpostService, + validatePartition: () => validatePartition, + validateRegion: () => validateRegion +}); +module.exports = __toCommonJS(index_exports); + +// src/NodeDisableMultiregionAccessPointConfigOptions.ts +var import_util_config_provider = __nccwpck_require__(56716); +var NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME = "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS"; +var NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME = "s3_disable_multiregion_access_points"; +var NODE_DISABLE_MULTIREGION_ACCESS_POINT_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => (0, import_util_config_provider.booleanSelector)(env, NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME, import_util_config_provider.SelectorType.ENV), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => (0, import_util_config_provider.booleanSelector)(profile, NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME, import_util_config_provider.SelectorType.CONFIG), "configFileSelector"), + default: false +}; + +// src/NodeUseArnRegionConfigOptions.ts + +var NODE_USE_ARN_REGION_ENV_NAME = "AWS_S3_USE_ARN_REGION"; +var NODE_USE_ARN_REGION_INI_NAME = "s3_use_arn_region"; +var NODE_USE_ARN_REGION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => (0, import_util_config_provider.booleanSelector)(env, NODE_USE_ARN_REGION_ENV_NAME, import_util_config_provider.SelectorType.ENV), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => (0, import_util_config_provider.booleanSelector)(profile, NODE_USE_ARN_REGION_INI_NAME, import_util_config_provider.SelectorType.CONFIG), "configFileSelector"), + /** + * useArnRegion has specific behavior when undefined instead of false. + * We therefore use undefined as the default value instead of false. + */ + default: void 0 +}; + +// src/bucketEndpointMiddleware.ts +var import_util_arn_parser = __nccwpck_require__(56369); +var import_protocol_http = __nccwpck_require__(72356); + +// src/bucketHostnameUtils.ts +var DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/; +var IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/; +var DOTS_PATTERN = /\.\./; +var DOT_PATTERN = /\./; +var S3_HOSTNAME_PATTERN = /^(.+\.)?s3(-fips)?(\.dualstack)?[.-]([a-z0-9-]+)\./; +var S3_US_EAST_1_ALTNAME_PATTERN = /^s3(-external-1)?\.amazonaws\.com$/; +var AWS_PARTITION_SUFFIX = "amazonaws.com"; +var isBucketNameOptions = /* @__PURE__ */ __name((options) => typeof options.bucketName === "string", "isBucketNameOptions"); +var isDnsCompatibleBucketName = /* @__PURE__ */ __name((bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName), "isDnsCompatibleBucketName"); +var getRegionalSuffix = /* @__PURE__ */ __name((hostname) => { + const parts = hostname.match(S3_HOSTNAME_PATTERN); + return [parts[4], hostname.replace(new RegExp(`^${parts[0]}`), "")]; +}, "getRegionalSuffix"); +var getSuffix = /* @__PURE__ */ __name((hostname) => S3_US_EAST_1_ALTNAME_PATTERN.test(hostname) ? ["us-east-1", AWS_PARTITION_SUFFIX] : getRegionalSuffix(hostname), "getSuffix"); +var getSuffixForArnEndpoint = /* @__PURE__ */ __name((hostname) => S3_US_EAST_1_ALTNAME_PATTERN.test(hostname) ? [hostname.replace(`.${AWS_PARTITION_SUFFIX}`, ""), AWS_PARTITION_SUFFIX] : getRegionalSuffix(hostname), "getSuffixForArnEndpoint"); +var validateArnEndpointOptions = /* @__PURE__ */ __name((options) => { + if (options.pathStyleEndpoint) { + throw new Error("Path-style S3 endpoint is not supported when bucket is an ARN"); + } + if (options.accelerateEndpoint) { + throw new Error("Accelerate endpoint is not supported when bucket is an ARN"); + } + if (!options.tlsCompatible) { + throw new Error("HTTPS is required when bucket is an ARN"); + } +}, "validateArnEndpointOptions"); +var validateService = /* @__PURE__ */ __name((service) => { + if (service !== "s3" && service !== "s3-outposts" && service !== "s3-object-lambda") { + throw new Error("Expect 's3' or 's3-outposts' or 's3-object-lambda' in ARN service component"); + } +}, "validateService"); +var validateS3Service = /* @__PURE__ */ __name((service) => { + if (service !== "s3") { + throw new Error("Expect 's3' in Accesspoint ARN service component"); + } +}, "validateS3Service"); +var validateOutpostService = /* @__PURE__ */ __name((service) => { + if (service !== "s3-outposts") { + throw new Error("Expect 's3-posts' in Outpost ARN service component"); + } +}, "validateOutpostService"); +var validatePartition = /* @__PURE__ */ __name((partition, options) => { + if (partition !== options.clientPartition) { + throw new Error(`Partition in ARN is incompatible, got "${partition}" but expected "${options.clientPartition}"`); + } +}, "validatePartition"); +var validateRegion = /* @__PURE__ */ __name((region, options) => { +}, "validateRegion"); +var validateRegionalClient = /* @__PURE__ */ __name((region) => { + if (["s3-external-1", "aws-global"].includes(region)) { + throw new Error(`Client region ${region} is not regional`); + } +}, "validateRegionalClient"); +var validateAccountId = /* @__PURE__ */ __name((accountId) => { + if (!/[0-9]{12}/.exec(accountId)) { + throw new Error("Access point ARN accountID does not match regex '[0-9]{12}'"); + } +}, "validateAccountId"); +var validateDNSHostLabel = /* @__PURE__ */ __name((label, options = { tlsCompatible: true }) => { + if (label.length >= 64 || !/^[a-z0-9][a-z0-9.-]*[a-z0-9]$/.test(label) || /(\d+\.){3}\d+/.test(label) || /[.-]{2}/.test(label) || options?.tlsCompatible && DOT_PATTERN.test(label)) { + throw new Error(`Invalid DNS label ${label}`); + } +}, "validateDNSHostLabel"); +var validateCustomEndpoint = /* @__PURE__ */ __name((options) => { + if (options.isCustomEndpoint) { + if (options.dualstackEndpoint) throw new Error("Dualstack endpoint is not supported with custom endpoint"); + if (options.accelerateEndpoint) throw new Error("Accelerate endpoint is not supported with custom endpoint"); + } +}, "validateCustomEndpoint"); +var getArnResources = /* @__PURE__ */ __name((resource) => { + const delimiter = resource.includes(":") ? ":" : "/"; + const [resourceType, ...rest] = resource.split(delimiter); + if (resourceType === "accesspoint") { + if (rest.length !== 1 || rest[0] === "") { + throw new Error(`Access Point ARN should have one resource accesspoint${delimiter}{accesspointname}`); + } + return { accesspointName: rest[0] }; + } else if (resourceType === "outpost") { + if (!rest[0] || rest[1] !== "accesspoint" || !rest[2] || rest.length !== 3) { + throw new Error( + `Outpost ARN should have resource outpost${delimiter}{outpostId}${delimiter}accesspoint${delimiter}{accesspointName}` + ); + } + const [outpostId, _, accesspointName] = rest; + return { outpostId, accesspointName }; + } else { + throw new Error(`ARN resource should begin with 'accesspoint${delimiter}' or 'outpost${delimiter}'`); + } +}, "getArnResources"); +var validateNoDualstack = /* @__PURE__ */ __name((dualstackEndpoint) => { +}, "validateNoDualstack"); +var validateNoFIPS = /* @__PURE__ */ __name((useFipsEndpoint) => { + if (useFipsEndpoint) throw new Error(`FIPS region is not supported with Outpost.`); +}, "validateNoFIPS"); +var validateMrapAlias = /* @__PURE__ */ __name((name) => { + try { + name.split(".").forEach((label) => { + validateDNSHostLabel(label); + }); + } catch (e) { + throw new Error(`"${name}" is not a DNS compatible name.`); + } +}, "validateMrapAlias"); + +// src/bucketHostname.ts +var bucketHostname = /* @__PURE__ */ __name((options) => { + validateCustomEndpoint(options); + return isBucketNameOptions(options) ? ( + // Construct endpoint when bucketName is a string referring to a bucket name + getEndpointFromBucketName(options) + ) : ( + // Construct endpoint when bucketName is an ARN referring to an S3 resource like Access Point + getEndpointFromArn(options) + ); +}, "bucketHostname"); +var getEndpointFromBucketName = /* @__PURE__ */ __name(({ + accelerateEndpoint = false, + clientRegion: region, + baseHostname, + bucketName, + dualstackEndpoint = false, + fipsEndpoint = false, + pathStyleEndpoint = false, + tlsCompatible = true, + isCustomEndpoint = false +}) => { + const [clientRegion, hostnameSuffix] = isCustomEndpoint ? [region, baseHostname] : getSuffix(baseHostname); + if (pathStyleEndpoint || !isDnsCompatibleBucketName(bucketName) || tlsCompatible && DOT_PATTERN.test(bucketName)) { + return { + bucketEndpoint: false, + hostname: dualstackEndpoint ? `s3.dualstack.${clientRegion}.${hostnameSuffix}` : baseHostname + }; + } + if (accelerateEndpoint) { + baseHostname = `s3-accelerate${dualstackEndpoint ? ".dualstack" : ""}.${hostnameSuffix}`; + } else if (dualstackEndpoint) { + baseHostname = `s3.dualstack.${clientRegion}.${hostnameSuffix}`; + } + return { + bucketEndpoint: true, + hostname: `${bucketName}.${baseHostname}` + }; +}, "getEndpointFromBucketName"); +var getEndpointFromArn = /* @__PURE__ */ __name((options) => { + const { isCustomEndpoint, baseHostname, clientRegion } = options; + const hostnameSuffix = isCustomEndpoint ? baseHostname : getSuffixForArnEndpoint(baseHostname)[1]; + const { + pathStyleEndpoint, + accelerateEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + bucketName, + clientPartition = "aws" + } = options; + validateArnEndpointOptions({ pathStyleEndpoint, accelerateEndpoint, tlsCompatible }); + const { service, partition, accountId, region, resource } = bucketName; + validateService(service); + validatePartition(partition, { clientPartition }); + validateAccountId(accountId); + const { accesspointName, outpostId } = getArnResources(resource); + if (service === "s3-object-lambda") { + return getEndpointFromObjectLambdaArn({ ...options, tlsCompatible, bucketName, accesspointName, hostnameSuffix }); + } + if (region === "") { + return getEndpointFromMRAPArn({ ...options, clientRegion, mrapAlias: accesspointName, hostnameSuffix }); + } + if (outpostId) { + return getEndpointFromOutpostArn({ ...options, clientRegion, outpostId, accesspointName, hostnameSuffix }); + } + return getEndpointFromAccessPointArn({ ...options, clientRegion, accesspointName, hostnameSuffix }); +}, "getEndpointFromArn"); +var getEndpointFromObjectLambdaArn = /* @__PURE__ */ __name(({ + dualstackEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + accesspointName, + bucketName, + hostnameSuffix +}) => { + const { accountId, region, service } = bucketName; + validateRegionalClient(clientRegion); + const DNSHostLabel = `${accesspointName}-${accountId}`; + validateDNSHostLabel(DNSHostLabel, { tlsCompatible }); + const endpointRegion = useArnRegion ? region : clientRegion; + const signingRegion = useArnRegion ? region : clientSigningRegion; + return { + bucketEndpoint: true, + hostname: `${DNSHostLabel}.${service}${fipsEndpoint ? "-fips" : ""}.${endpointRegion}.${hostnameSuffix}`, + signingRegion, + signingService: service + }; +}, "getEndpointFromObjectLambdaArn"); +var getEndpointFromMRAPArn = /* @__PURE__ */ __name(({ + disableMultiregionAccessPoints, + dualstackEndpoint = false, + isCustomEndpoint, + mrapAlias, + hostnameSuffix +}) => { + if (disableMultiregionAccessPoints === true) { + throw new Error("SDK is attempting to use a MRAP ARN. Please enable to feature."); + } + validateMrapAlias(mrapAlias); + return { + bucketEndpoint: true, + hostname: `${mrapAlias}${isCustomEndpoint ? "" : `.accesspoint.s3-global`}.${hostnameSuffix}`, + signingRegion: "*" + }; +}, "getEndpointFromMRAPArn"); +var getEndpointFromOutpostArn = /* @__PURE__ */ __name(({ + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + bucketName, + outpostId, + dualstackEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + accesspointName, + isCustomEndpoint, + hostnameSuffix +}) => { + validateRegionalClient(clientRegion); + const DNSHostLabel = `${accesspointName}-${bucketName.accountId}`; + validateDNSHostLabel(DNSHostLabel, { tlsCompatible }); + const endpointRegion = useArnRegion ? bucketName.region : clientRegion; + const signingRegion = useArnRegion ? bucketName.region : clientSigningRegion; + validateOutpostService(bucketName.service); + validateDNSHostLabel(outpostId, { tlsCompatible }); + validateNoFIPS(fipsEndpoint); + const hostnamePrefix = `${DNSHostLabel}.${outpostId}`; + return { + bucketEndpoint: true, + hostname: `${hostnamePrefix}${isCustomEndpoint ? "" : `.s3-outposts.${endpointRegion}`}.${hostnameSuffix}`, + signingRegion, + signingService: "s3-outposts" + }; +}, "getEndpointFromOutpostArn"); +var getEndpointFromAccessPointArn = /* @__PURE__ */ __name(({ + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + bucketName, + dualstackEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + accesspointName, + isCustomEndpoint, + hostnameSuffix +}) => { + validateRegionalClient(clientRegion); + const hostnamePrefix = `${accesspointName}-${bucketName.accountId}`; + validateDNSHostLabel(hostnamePrefix, { tlsCompatible }); + const endpointRegion = useArnRegion ? bucketName.region : clientRegion; + const signingRegion = useArnRegion ? bucketName.region : clientSigningRegion; + validateS3Service(bucketName.service); + return { + bucketEndpoint: true, + hostname: `${hostnamePrefix}${isCustomEndpoint ? "" : `.s3-accesspoint${fipsEndpoint ? "-fips" : ""}${dualstackEndpoint ? ".dualstack" : ""}.${endpointRegion}`}.${hostnameSuffix}`, + signingRegion + }; +}, "getEndpointFromAccessPointArn"); + +// src/bucketEndpointMiddleware.ts +var bucketEndpointMiddleware = /* @__PURE__ */ __name((options) => (next, context) => async (args) => { + const { Bucket: bucketName } = args.input; + let replaceBucketInPath = options.bucketEndpoint; + const request = args.request; + if (import_protocol_http.HttpRequest.isInstance(request)) { + if (options.bucketEndpoint) { + request.hostname = bucketName; + } else if ((0, import_util_arn_parser.validate)(bucketName)) { + const bucketArn = (0, import_util_arn_parser.parse)(bucketName); + const clientRegion = await options.region(); + const useDualstackEndpoint = await options.useDualstackEndpoint(); + const useFipsEndpoint = await options.useFipsEndpoint(); + const { partition, signingRegion = clientRegion } = await options.regionInfoProvider(clientRegion, { useDualstackEndpoint, useFipsEndpoint }) || {}; + const useArnRegion = await options.useArnRegion(); + const { + hostname, + bucketEndpoint, + signingRegion: modifiedSigningRegion, + signingService + } = bucketHostname({ + bucketName: bucketArn, + baseHostname: request.hostname, + accelerateEndpoint: options.useAccelerateEndpoint, + dualstackEndpoint: useDualstackEndpoint, + fipsEndpoint: useFipsEndpoint, + pathStyleEndpoint: options.forcePathStyle, + tlsCompatible: request.protocol === "https:", + useArnRegion, + clientPartition: partition, + clientSigningRegion: signingRegion, + clientRegion, + isCustomEndpoint: options.isCustomEndpoint, + disableMultiregionAccessPoints: await options.disableMultiregionAccessPoints() + }); + if (modifiedSigningRegion && modifiedSigningRegion !== signingRegion) { + context["signing_region"] = modifiedSigningRegion; + } + if (signingService && signingService !== "s3") { + context["signing_service"] = signingService; + } + request.hostname = hostname; + replaceBucketInPath = bucketEndpoint; + } else { + const clientRegion = await options.region(); + const dualstackEndpoint = await options.useDualstackEndpoint(); + const fipsEndpoint = await options.useFipsEndpoint(); + const { hostname, bucketEndpoint } = bucketHostname({ + bucketName, + clientRegion, + baseHostname: request.hostname, + accelerateEndpoint: options.useAccelerateEndpoint, + dualstackEndpoint, + fipsEndpoint, + pathStyleEndpoint: options.forcePathStyle, + tlsCompatible: request.protocol === "https:", + isCustomEndpoint: options.isCustomEndpoint + }); + request.hostname = hostname; + replaceBucketInPath = bucketEndpoint; + } + if (replaceBucketInPath) { + request.path = request.path.replace(/^(\/)?[^\/]+/, ""); + if (request.path === "") { + request.path = "/"; + } + } + } + return next({ ...args, request }); +}, "bucketEndpointMiddleware"); +var bucketEndpointMiddlewareOptions = { + tags: ["BUCKET_ENDPOINT"], + name: "bucketEndpointMiddleware", + relation: "before", + toMiddleware: "hostHeaderMiddleware", + override: true +}; +var getBucketEndpointPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo(bucketEndpointMiddleware(options), bucketEndpointMiddlewareOptions); + }, "applyToStack") +}), "getBucketEndpointPlugin"); + +// src/configurations.ts +function resolveBucketEndpointConfig(input) { + const { + bucketEndpoint = false, + forcePathStyle = false, + useAccelerateEndpoint = false, + // useArnRegion has specific behavior when undefined instead of false. + useArnRegion, + disableMultiregionAccessPoints = false + } = input; + return Object.assign(input, { + bucketEndpoint, + forcePathStyle, + useAccelerateEndpoint, + useArnRegion: typeof useArnRegion === "function" ? useArnRegion : () => Promise.resolve(useArnRegion), + disableMultiregionAccessPoints: typeof disableMultiregionAccessPoints === "function" ? disableMultiregionAccessPoints : () => Promise.resolve(disableMultiregionAccessPoints) + }); +} +__name(resolveBucketEndpointConfig, "resolveBucketEndpointConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 84745: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + addExpectContinueMiddleware: () => addExpectContinueMiddleware, + addExpectContinueMiddlewareOptions: () => addExpectContinueMiddlewareOptions, + getAddExpectContinuePlugin: () => getAddExpectContinuePlugin +}); +module.exports = __toCommonJS(index_exports); +var import_protocol_http = __nccwpck_require__(72356); +function addExpectContinueMiddleware(options) { + return (next) => async (args) => { + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request) && request.body && options.runtime === "node") { + if (options.requestHandler?.constructor?.name !== "FetchHttpHandler") { + request.headers = { + ...request.headers, + Expect: "100-continue" + }; + } + } + return next({ + ...args, + request + }); + }; +} +__name(addExpectContinueMiddleware, "addExpectContinueMiddleware"); +var addExpectContinueMiddlewareOptions = { + step: "build", + tags: ["SET_EXPECT_HEADER", "EXPECT_HEADER"], + name: "addExpectContinueMiddleware", + override: true +}; +var getAddExpectContinuePlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(addExpectContinueMiddleware(options), addExpectContinueMiddlewareOptions); + }, "applyToStack") +}), "getAddExpectContinuePlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 23321: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getCrc32ChecksumAlgorithmFunction = void 0; +const tslib_1 = __nccwpck_require__(61860); +const crc32_1 = __nccwpck_require__(62110); +const util_1 = __nccwpck_require__(95667); +const zlib = tslib_1.__importStar(__nccwpck_require__(43106)); +class NodeCrc32 { + checksum = 0; + update(data) { + this.checksum = zlib.crc32(data, this.checksum); + } + async digest() { + return (0, util_1.numToUint8)(this.checksum); + } + reset() { + this.checksum = 0; + } +} +const getCrc32ChecksumAlgorithmFunction = () => { + if (typeof zlib.crc32 === "undefined") { + return crc32_1.AwsCrc32; + } + return NodeCrc32; +}; +exports.getCrc32ChecksumAlgorithmFunction = getCrc32ChecksumAlgorithmFunction; + + +/***/ }), + +/***/ 29836: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + CONFIG_REQUEST_CHECKSUM_CALCULATION: () => CONFIG_REQUEST_CHECKSUM_CALCULATION, + CONFIG_RESPONSE_CHECKSUM_VALIDATION: () => CONFIG_RESPONSE_CHECKSUM_VALIDATION, + ChecksumAlgorithm: () => ChecksumAlgorithm, + ChecksumLocation: () => ChecksumLocation, + DEFAULT_CHECKSUM_ALGORITHM: () => DEFAULT_CHECKSUM_ALGORITHM, + DEFAULT_REQUEST_CHECKSUM_CALCULATION: () => DEFAULT_REQUEST_CHECKSUM_CALCULATION, + DEFAULT_RESPONSE_CHECKSUM_VALIDATION: () => DEFAULT_RESPONSE_CHECKSUM_VALIDATION, + ENV_REQUEST_CHECKSUM_CALCULATION: () => ENV_REQUEST_CHECKSUM_CALCULATION, + ENV_RESPONSE_CHECKSUM_VALIDATION: () => ENV_RESPONSE_CHECKSUM_VALIDATION, + NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS: () => NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS, + NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS: () => NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS, + RequestChecksumCalculation: () => RequestChecksumCalculation, + ResponseChecksumValidation: () => ResponseChecksumValidation, + crc64NvmeCrtContainer: () => crc64NvmeCrtContainer, + flexibleChecksumsMiddleware: () => flexibleChecksumsMiddleware, + flexibleChecksumsMiddlewareOptions: () => flexibleChecksumsMiddlewareOptions, + getFlexibleChecksumsPlugin: () => getFlexibleChecksumsPlugin, + resolveFlexibleChecksumsConfig: () => resolveFlexibleChecksumsConfig +}); +module.exports = __toCommonJS(index_exports); + +// src/constants.ts +var RequestChecksumCalculation = { + /** + * When set, a checksum will be calculated for all request payloads of operations + * modeled with the {@link httpChecksum} trait where `requestChecksumRequired` is `true` + * AND/OR a `requestAlgorithmMember` is modeled. + * {@link https://smithy.io/2.0/aws/aws-core.html#aws-protocols-httpchecksum-trait httpChecksum} + */ + WHEN_SUPPORTED: "WHEN_SUPPORTED", + /** + * When set, a checksum will only be calculated for request payloads of operations + * modeled with the {@link httpChecksum} trait where `requestChecksumRequired` is `true` + * OR where a `requestAlgorithmMember` is modeled and the user sets it. + * {@link https://smithy.io/2.0/aws/aws-core.html#aws-protocols-httpchecksum-trait httpChecksum} + */ + WHEN_REQUIRED: "WHEN_REQUIRED" +}; +var DEFAULT_REQUEST_CHECKSUM_CALCULATION = RequestChecksumCalculation.WHEN_SUPPORTED; +var ResponseChecksumValidation = { + /** + * When set, checksum validation MUST be performed on all response payloads of operations + * modeled with the {@link httpChecksum} trait where `responseAlgorithms` is modeled, + * except when no modeled checksum algorithms are supported by an SDK. + * {@link https://smithy.io/2.0/aws/aws-core.html#aws-protocols-httpchecksum-trait httpChecksum} + */ + WHEN_SUPPORTED: "WHEN_SUPPORTED", + /** + * When set, checksum validation MUST NOT be performed on response payloads of operations UNLESS + * the SDK supports the modeled checksum algorithms AND the user has set the `requestValidationModeMember` to `ENABLED`. + * It is currently impossible to model an operation as requiring a response checksum, + * but this setting leaves the door open for future updates. + */ + WHEN_REQUIRED: "WHEN_REQUIRED" +}; +var DEFAULT_RESPONSE_CHECKSUM_VALIDATION = RequestChecksumCalculation.WHEN_SUPPORTED; +var ChecksumAlgorithm = /* @__PURE__ */ ((ChecksumAlgorithm3) => { + ChecksumAlgorithm3["MD5"] = "MD5"; + ChecksumAlgorithm3["CRC32"] = "CRC32"; + ChecksumAlgorithm3["CRC32C"] = "CRC32C"; + ChecksumAlgorithm3["CRC64NVME"] = "CRC64NVME"; + ChecksumAlgorithm3["SHA1"] = "SHA1"; + ChecksumAlgorithm3["SHA256"] = "SHA256"; + return ChecksumAlgorithm3; +})(ChecksumAlgorithm || {}); +var ChecksumLocation = /* @__PURE__ */ ((ChecksumLocation2) => { + ChecksumLocation2["HEADER"] = "header"; + ChecksumLocation2["TRAILER"] = "trailer"; + return ChecksumLocation2; +})(ChecksumLocation || {}); +var DEFAULT_CHECKSUM_ALGORITHM = "CRC32" /* CRC32 */; + +// src/stringUnionSelector.ts +var stringUnionSelector = /* @__PURE__ */ __name((obj, key, union, type) => { + if (!(key in obj)) return void 0; + const value = obj[key].toUpperCase(); + if (!Object.values(union).includes(value)) { + throw new TypeError(`Cannot load ${type} '${key}'. Expected one of ${Object.values(union)}, got '${obj[key]}'.`); + } + return value; +}, "stringUnionSelector"); + +// src/NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS.ts +var ENV_REQUEST_CHECKSUM_CALCULATION = "AWS_REQUEST_CHECKSUM_CALCULATION"; +var CONFIG_REQUEST_CHECKSUM_CALCULATION = "request_checksum_calculation"; +var NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => stringUnionSelector(env, ENV_REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation, "env" /* ENV */), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => stringUnionSelector(profile, CONFIG_REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation, "shared config entry" /* CONFIG */), "configFileSelector"), + default: DEFAULT_REQUEST_CHECKSUM_CALCULATION +}; + +// src/NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS.ts +var ENV_RESPONSE_CHECKSUM_VALIDATION = "AWS_RESPONSE_CHECKSUM_VALIDATION"; +var CONFIG_RESPONSE_CHECKSUM_VALIDATION = "response_checksum_validation"; +var NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => stringUnionSelector(env, ENV_RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation, "env" /* ENV */), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => stringUnionSelector(profile, CONFIG_RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation, "shared config entry" /* CONFIG */), "configFileSelector"), + default: DEFAULT_RESPONSE_CHECKSUM_VALIDATION +}; + +// src/crc64-nvme-crt-container.ts +var crc64NvmeCrtContainer = { + CrtCrc64Nvme: null +}; + +// src/flexibleChecksumsMiddleware.ts +var import_core = __nccwpck_require__(8704); +var import_protocol_http = __nccwpck_require__(72356); +var import_util_stream = __nccwpck_require__(4252); + +// src/types.ts +var CLIENT_SUPPORTED_ALGORITHMS = [ + "CRC32" /* CRC32 */, + "CRC32C" /* CRC32C */, + "CRC64NVME" /* CRC64NVME */, + "SHA1" /* SHA1 */, + "SHA256" /* SHA256 */ +]; +var PRIORITY_ORDER_ALGORITHMS = [ + "SHA256" /* SHA256 */, + "SHA1" /* SHA1 */, + "CRC32" /* CRC32 */, + "CRC32C" /* CRC32C */, + "CRC64NVME" /* CRC64NVME */ +]; + +// src/getChecksumAlgorithmForRequest.ts +var getChecksumAlgorithmForRequest = /* @__PURE__ */ __name((input, { requestChecksumRequired, requestAlgorithmMember, requestChecksumCalculation }) => { + if (!requestAlgorithmMember) { + return requestChecksumCalculation === RequestChecksumCalculation.WHEN_SUPPORTED || requestChecksumRequired ? DEFAULT_CHECKSUM_ALGORITHM : void 0; + } + if (!input[requestAlgorithmMember]) { + return void 0; + } + const checksumAlgorithm = input[requestAlgorithmMember]; + if (!CLIENT_SUPPORTED_ALGORITHMS.includes(checksumAlgorithm)) { + throw new Error( + `The checksum algorithm "${checksumAlgorithm}" is not supported by the client. Select one of ${CLIENT_SUPPORTED_ALGORITHMS}.` + ); + } + return checksumAlgorithm; +}, "getChecksumAlgorithmForRequest"); + +// src/getChecksumLocationName.ts +var getChecksumLocationName = /* @__PURE__ */ __name((algorithm) => algorithm === "MD5" /* MD5 */ ? "content-md5" : `x-amz-checksum-${algorithm.toLowerCase()}`, "getChecksumLocationName"); + +// src/hasHeader.ts +var hasHeader = /* @__PURE__ */ __name((header, headers) => { + const soughtHeader = header.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return true; + } + } + return false; +}, "hasHeader"); + +// src/hasHeaderWithPrefix.ts +var hasHeaderWithPrefix = /* @__PURE__ */ __name((headerPrefix, headers) => { + const soughtHeaderPrefix = headerPrefix.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (headerName.toLowerCase().startsWith(soughtHeaderPrefix)) { + return true; + } + } + return false; +}, "hasHeaderWithPrefix"); + +// src/isStreaming.ts +var import_is_array_buffer = __nccwpck_require__(86130); +var isStreaming = /* @__PURE__ */ __name((body) => body !== void 0 && typeof body !== "string" && !ArrayBuffer.isView(body) && !(0, import_is_array_buffer.isArrayBuffer)(body), "isStreaming"); + +// src/selectChecksumAlgorithmFunction.ts +var import_crc32c = __nccwpck_require__(91491); +var import_getCrc32ChecksumAlgorithmFunction = __nccwpck_require__(23321); +var selectChecksumAlgorithmFunction = /* @__PURE__ */ __name((checksumAlgorithm, config) => { + switch (checksumAlgorithm) { + case "MD5" /* MD5 */: + return config.md5; + case "CRC32" /* CRC32 */: + return (0, import_getCrc32ChecksumAlgorithmFunction.getCrc32ChecksumAlgorithmFunction)(); + case "CRC32C" /* CRC32C */: + return import_crc32c.AwsCrc32c; + case "CRC64NVME" /* CRC64NVME */: + if (typeof crc64NvmeCrtContainer.CrtCrc64Nvme !== "function") { + throw new Error( + `Please check whether you have installed the "@aws-sdk/crc64-nvme-crt" package explicitly. +You must also register the package by calling [require("@aws-sdk/crc64-nvme-crt");] or an ESM equivalent such as [import "@aws-sdk/crc64-nvme-crt";]. +For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt` + ); + } + return crc64NvmeCrtContainer.CrtCrc64Nvme; + case "SHA1" /* SHA1 */: + return config.sha1; + case "SHA256" /* SHA256 */: + return config.sha256; + default: + throw new Error(`Unsupported checksum algorithm: ${checksumAlgorithm}`); + } +}, "selectChecksumAlgorithmFunction"); + +// src/stringHasher.ts +var import_util_utf8 = __nccwpck_require__(71577); +var stringHasher = /* @__PURE__ */ __name((checksumAlgorithmFn, body) => { + const hash = new checksumAlgorithmFn(); + hash.update((0, import_util_utf8.toUint8Array)(body || "")); + return hash.digest(); +}, "stringHasher"); + +// src/flexibleChecksumsMiddleware.ts +var flexibleChecksumsMiddlewareOptions = { + name: "flexibleChecksumsMiddleware", + step: "build", + tags: ["BODY_CHECKSUM"], + override: true +}; +var flexibleChecksumsMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + if (hasHeaderWithPrefix("x-amz-checksum-", args.request.headers)) { + return next(args); + } + const { request, input } = args; + const { body: requestBody, headers } = request; + const { base64Encoder, streamHasher } = config; + const { requestChecksumRequired, requestAlgorithmMember } = middlewareConfig; + const requestChecksumCalculation = await config.requestChecksumCalculation(); + const requestAlgorithmMemberName = requestAlgorithmMember?.name; + const requestAlgorithmMemberHttpHeader = requestAlgorithmMember?.httpHeader; + if (requestAlgorithmMemberName && !input[requestAlgorithmMemberName]) { + if (requestChecksumCalculation === RequestChecksumCalculation.WHEN_SUPPORTED || requestChecksumRequired) { + input[requestAlgorithmMemberName] = DEFAULT_CHECKSUM_ALGORITHM; + if (requestAlgorithmMemberHttpHeader) { + headers[requestAlgorithmMemberHttpHeader] = DEFAULT_CHECKSUM_ALGORITHM; + } + } + } + const checksumAlgorithm = getChecksumAlgorithmForRequest(input, { + requestChecksumRequired, + requestAlgorithmMember: requestAlgorithmMember?.name, + requestChecksumCalculation + }); + let updatedBody = requestBody; + let updatedHeaders = headers; + if (checksumAlgorithm) { + switch (checksumAlgorithm) { + case "CRC32" /* CRC32 */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_CRC32", "U"); + break; + case "CRC32C" /* CRC32C */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_CRC32C", "V"); + break; + case "CRC64NVME" /* CRC64NVME */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_CRC64", "W"); + break; + case "SHA1" /* SHA1 */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_SHA1", "X"); + break; + case "SHA256" /* SHA256 */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_SHA256", "Y"); + break; + } + const checksumLocationName = getChecksumLocationName(checksumAlgorithm); + const checksumAlgorithmFn = selectChecksumAlgorithmFunction(checksumAlgorithm, config); + if (isStreaming(requestBody)) { + const { getAwsChunkedEncodingStream, bodyLengthChecker } = config; + updatedBody = getAwsChunkedEncodingStream( + typeof config.requestStreamBufferSize === "number" && config.requestStreamBufferSize >= 8 * 1024 ? (0, import_util_stream.createBufferedReadable)(requestBody, config.requestStreamBufferSize, context.logger) : requestBody, + { + base64Encoder, + bodyLengthChecker, + checksumLocationName, + checksumAlgorithmFn, + streamHasher + } + ); + updatedHeaders = { + ...headers, + "content-encoding": headers["content-encoding"] ? `${headers["content-encoding"]},aws-chunked` : "aws-chunked", + "transfer-encoding": "chunked", + "x-amz-decoded-content-length": headers["content-length"], + "x-amz-content-sha256": "STREAMING-UNSIGNED-PAYLOAD-TRAILER", + "x-amz-trailer": checksumLocationName + }; + delete updatedHeaders["content-length"]; + } else if (!hasHeader(checksumLocationName, headers)) { + const rawChecksum = await stringHasher(checksumAlgorithmFn, requestBody); + updatedHeaders = { + ...headers, + [checksumLocationName]: base64Encoder(rawChecksum) + }; + } + } + const result = await next({ + ...args, + request: { + ...request, + headers: updatedHeaders, + body: updatedBody + } + }); + return result; +}, "flexibleChecksumsMiddleware"); + +// src/flexibleChecksumsInputMiddleware.ts + +var flexibleChecksumsInputMiddlewareOptions = { + name: "flexibleChecksumsInputMiddleware", + toMiddleware: "serializerMiddleware", + relation: "before", + tags: ["BODY_CHECKSUM"], + override: true +}; +var flexibleChecksumsInputMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => { + const input = args.input; + const { requestValidationModeMember } = middlewareConfig; + const requestChecksumCalculation = await config.requestChecksumCalculation(); + const responseChecksumValidation = await config.responseChecksumValidation(); + switch (requestChecksumCalculation) { + case RequestChecksumCalculation.WHEN_REQUIRED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED", "a"); + break; + case RequestChecksumCalculation.WHEN_SUPPORTED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED", "Z"); + break; + } + switch (responseChecksumValidation) { + case ResponseChecksumValidation.WHEN_REQUIRED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED", "c"); + break; + case ResponseChecksumValidation.WHEN_SUPPORTED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED", "b"); + break; + } + if (requestValidationModeMember && !input[requestValidationModeMember]) { + if (responseChecksumValidation === ResponseChecksumValidation.WHEN_SUPPORTED) { + input[requestValidationModeMember] = "ENABLED"; + } + } + return next(args); +}, "flexibleChecksumsInputMiddleware"); + +// src/flexibleChecksumsResponseMiddleware.ts + + +// src/getChecksumAlgorithmListForResponse.ts +var getChecksumAlgorithmListForResponse = /* @__PURE__ */ __name((responseAlgorithms = []) => { + const validChecksumAlgorithms = []; + for (const algorithm of PRIORITY_ORDER_ALGORITHMS) { + if (!responseAlgorithms.includes(algorithm) || !CLIENT_SUPPORTED_ALGORITHMS.includes(algorithm)) { + continue; + } + validChecksumAlgorithms.push(algorithm); + } + return validChecksumAlgorithms; +}, "getChecksumAlgorithmListForResponse"); + +// src/isChecksumWithPartNumber.ts +var isChecksumWithPartNumber = /* @__PURE__ */ __name((checksum) => { + const lastHyphenIndex = checksum.lastIndexOf("-"); + if (lastHyphenIndex !== -1) { + const numberPart = checksum.slice(lastHyphenIndex + 1); + if (!numberPart.startsWith("0")) { + const number = parseInt(numberPart, 10); + if (!isNaN(number) && number >= 1 && number <= 1e4) { + return true; + } + } + } + return false; +}, "isChecksumWithPartNumber"); + +// src/validateChecksumFromResponse.ts + + +// src/getChecksum.ts +var getChecksum = /* @__PURE__ */ __name(async (body, { checksumAlgorithmFn, base64Encoder }) => base64Encoder(await stringHasher(checksumAlgorithmFn, body)), "getChecksum"); + +// src/validateChecksumFromResponse.ts +var validateChecksumFromResponse = /* @__PURE__ */ __name(async (response, { config, responseAlgorithms, logger }) => { + const checksumAlgorithms = getChecksumAlgorithmListForResponse(responseAlgorithms); + const { body: responseBody, headers: responseHeaders } = response; + for (const algorithm of checksumAlgorithms) { + const responseHeader = getChecksumLocationName(algorithm); + const checksumFromResponse = responseHeaders[responseHeader]; + if (checksumFromResponse) { + let checksumAlgorithmFn; + try { + checksumAlgorithmFn = selectChecksumAlgorithmFunction(algorithm, config); + } catch (error) { + if (algorithm === "CRC64NVME" /* CRC64NVME */) { + logger?.warn(`Skipping ${"CRC64NVME" /* CRC64NVME */} checksum validation: ${error.message}`); + continue; + } + throw error; + } + const { base64Encoder } = config; + if (isStreaming(responseBody)) { + response.body = (0, import_util_stream.createChecksumStream)({ + expectedChecksum: checksumFromResponse, + checksumSourceLocation: responseHeader, + checksum: new checksumAlgorithmFn(), + source: responseBody, + base64Encoder + }); + return; + } + const checksum = await getChecksum(responseBody, { checksumAlgorithmFn, base64Encoder }); + if (checksum === checksumFromResponse) { + break; + } + throw new Error( + `Checksum mismatch: expected "${checksum}" but received "${checksumFromResponse}" in response header "${responseHeader}".` + ); + } + } +}, "validateChecksumFromResponse"); + +// src/flexibleChecksumsResponseMiddleware.ts +var flexibleChecksumsResponseMiddlewareOptions = { + name: "flexibleChecksumsResponseMiddleware", + toMiddleware: "deserializerMiddleware", + relation: "after", + tags: ["BODY_CHECKSUM"], + override: true +}; +var flexibleChecksumsResponseMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + const input = args.input; + const result = await next(args); + const response = result.response; + const { requestValidationModeMember, responseAlgorithms } = middlewareConfig; + if (requestValidationModeMember && input[requestValidationModeMember] === "ENABLED") { + const { clientName, commandName } = context; + const isS3WholeObjectMultipartGetResponseChecksum = clientName === "S3Client" && commandName === "GetObjectCommand" && getChecksumAlgorithmListForResponse(responseAlgorithms).every((algorithm) => { + const responseHeader = getChecksumLocationName(algorithm); + const checksumFromResponse = response.headers[responseHeader]; + return !checksumFromResponse || isChecksumWithPartNumber(checksumFromResponse); + }); + if (isS3WholeObjectMultipartGetResponseChecksum) { + return result; + } + await validateChecksumFromResponse(response, { + config, + responseAlgorithms, + logger: context.logger + }); + } + return result; +}, "flexibleChecksumsResponseMiddleware"); + +// src/getFlexibleChecksumsPlugin.ts +var getFlexibleChecksumsPlugin = /* @__PURE__ */ __name((config, middlewareConfig) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(flexibleChecksumsMiddleware(config, middlewareConfig), flexibleChecksumsMiddlewareOptions); + clientStack.addRelativeTo( + flexibleChecksumsInputMiddleware(config, middlewareConfig), + flexibleChecksumsInputMiddlewareOptions + ); + clientStack.addRelativeTo( + flexibleChecksumsResponseMiddleware(config, middlewareConfig), + flexibleChecksumsResponseMiddlewareOptions + ); + }, "applyToStack") +}), "getFlexibleChecksumsPlugin"); + +// src/resolveFlexibleChecksumsConfig.ts +var import_util_middleware = __nccwpck_require__(76324); +var resolveFlexibleChecksumsConfig = /* @__PURE__ */ __name((input) => { + const { requestChecksumCalculation, responseChecksumValidation, requestStreamBufferSize } = input; + return Object.assign(input, { + requestChecksumCalculation: (0, import_util_middleware.normalizeProvider)(requestChecksumCalculation ?? DEFAULT_REQUEST_CHECKSUM_CALCULATION), + responseChecksumValidation: (0, import_util_middleware.normalizeProvider)(responseChecksumValidation ?? DEFAULT_RESPONSE_CHECKSUM_VALIDATION), + requestStreamBufferSize: Number(requestStreamBufferSize ?? 0) + }); +}, "resolveFlexibleChecksumsConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 52590: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getHostHeaderPlugin: () => getHostHeaderPlugin, + hostHeaderMiddleware: () => hostHeaderMiddleware, + hostHeaderMiddlewareOptions: () => hostHeaderMiddlewareOptions, + resolveHostHeaderConfig: () => resolveHostHeaderConfig +}); +module.exports = __toCommonJS(index_exports); +var import_protocol_http = __nccwpck_require__(72356); +function resolveHostHeaderConfig(input) { + return input; +} +__name(resolveHostHeaderConfig, "resolveHostHeaderConfig"); +var hostHeaderMiddleware = /* @__PURE__ */ __name((options) => (next) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) return next(args); + const { request } = args; + const { handlerProtocol = "" } = options.requestHandler.metadata || {}; + if (handlerProtocol.indexOf("h2") >= 0 && !request.headers[":authority"]) { + delete request.headers["host"]; + request.headers[":authority"] = request.hostname + (request.port ? ":" + request.port : ""); + } else if (!request.headers["host"]) { + let host = request.hostname; + if (request.port != null) host += `:${request.port}`; + request.headers["host"] = host; + } + return next(args); +}, "hostHeaderMiddleware"); +var hostHeaderMiddlewareOptions = { + name: "hostHeaderMiddleware", + step: "build", + priority: "low", + tags: ["HOST"], + override: true +}; +var getHostHeaderPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(hostHeaderMiddleware(options), hostHeaderMiddlewareOptions); + }, "applyToStack") +}), "getHostHeaderPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 23209: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getLocationConstraintPlugin: () => getLocationConstraintPlugin, + locationConstraintMiddleware: () => locationConstraintMiddleware, + locationConstraintMiddlewareOptions: () => locationConstraintMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); +function locationConstraintMiddleware(options) { + return (next) => async (args) => { + const { CreateBucketConfiguration } = args.input; + const region = await options.region(); + if (!CreateBucketConfiguration?.LocationConstraint && !CreateBucketConfiguration?.Location) { + args = { + ...args, + input: { + ...args.input, + CreateBucketConfiguration: region === "us-east-1" ? void 0 : { LocationConstraint: region } + } + }; + } + return next(args); + }; +} +__name(locationConstraintMiddleware, "locationConstraintMiddleware"); +var locationConstraintMiddlewareOptions = { + step: "initialize", + tags: ["LOCATION_CONSTRAINT", "CREATE_BUCKET_CONFIGURATION"], + name: "locationConstraintMiddleware", + override: true +}; +var getLocationConstraintPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(locationConstraintMiddleware(config), locationConstraintMiddlewareOptions); + }, "applyToStack") +}), "getLocationConstraintPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 85242: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getLoggerPlugin: () => getLoggerPlugin, + loggerMiddleware: () => loggerMiddleware, + loggerMiddlewareOptions: () => loggerMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); + +// src/loggerMiddleware.ts +var loggerMiddleware = /* @__PURE__ */ __name(() => (next, context) => async (args) => { + try { + const response = await next(args); + const { clientName, commandName, logger, dynamoDbDocumentClientOptions = {} } = context; + const { overrideInputFilterSensitiveLog, overrideOutputFilterSensitiveLog } = dynamoDbDocumentClientOptions; + const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog; + const outputFilterSensitiveLog = overrideOutputFilterSensitiveLog ?? context.outputFilterSensitiveLog; + const { $metadata, ...outputWithoutMetadata } = response.output; + logger?.info?.({ + clientName, + commandName, + input: inputFilterSensitiveLog(args.input), + output: outputFilterSensitiveLog(outputWithoutMetadata), + metadata: $metadata + }); + return response; + } catch (error) { + const { clientName, commandName, logger, dynamoDbDocumentClientOptions = {} } = context; + const { overrideInputFilterSensitiveLog } = dynamoDbDocumentClientOptions; + const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog; + logger?.error?.({ + clientName, + commandName, + input: inputFilterSensitiveLog(args.input), + error, + metadata: error.$metadata + }); + throw error; + } +}, "loggerMiddleware"); +var loggerMiddlewareOptions = { + name: "loggerMiddleware", + tags: ["LOGGER"], + step: "initialize", + override: true +}; +var getLoggerPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(loggerMiddleware(), loggerMiddlewareOptions); + }, "applyToStack") +}), "getLoggerPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 81568: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + addRecursionDetectionMiddlewareOptions: () => addRecursionDetectionMiddlewareOptions, + getRecursionDetectionPlugin: () => getRecursionDetectionPlugin, + recursionDetectionMiddleware: () => recursionDetectionMiddleware +}); +module.exports = __toCommonJS(index_exports); +var import_protocol_http = __nccwpck_require__(72356); +var TRACE_ID_HEADER_NAME = "X-Amzn-Trace-Id"; +var ENV_LAMBDA_FUNCTION_NAME = "AWS_LAMBDA_FUNCTION_NAME"; +var ENV_TRACE_ID = "_X_AMZN_TRACE_ID"; +var recursionDetectionMiddleware = /* @__PURE__ */ __name((options) => (next) => async (args) => { + const { request } = args; + if (!import_protocol_http.HttpRequest.isInstance(request) || options.runtime !== "node") { + return next(args); + } + const traceIdHeader = Object.keys(request.headers ?? {}).find((h) => h.toLowerCase() === TRACE_ID_HEADER_NAME.toLowerCase()) ?? TRACE_ID_HEADER_NAME; + if (request.headers.hasOwnProperty(traceIdHeader)) { + return next(args); + } + const functionName = process.env[ENV_LAMBDA_FUNCTION_NAME]; + const traceId = process.env[ENV_TRACE_ID]; + const nonEmptyString = /* @__PURE__ */ __name((str) => typeof str === "string" && str.length > 0, "nonEmptyString"); + if (nonEmptyString(functionName) && nonEmptyString(traceId)) { + request.headers[TRACE_ID_HEADER_NAME] = traceId; + } + return next({ + ...args, + request + }); +}, "recursionDetectionMiddleware"); +var addRecursionDetectionMiddlewareOptions = { + step: "build", + tags: ["RECURSION_DETECTION"], + name: "recursionDetectionMiddleware", + override: true, + priority: "low" +}; +var getRecursionDetectionPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(recursionDetectionMiddleware(options), addRecursionDetectionMiddlewareOptions); + }, "applyToStack") +}), "getRecursionDetectionPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 77445: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS: () => NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, + S3ExpressIdentityCache: () => S3ExpressIdentityCache, + S3ExpressIdentityCacheEntry: () => S3ExpressIdentityCacheEntry, + S3ExpressIdentityProviderImpl: () => S3ExpressIdentityProviderImpl, + SignatureV4S3Express: () => SignatureV4S3Express, + checkContentLengthHeader: () => checkContentLengthHeader, + checkContentLengthHeaderMiddlewareOptions: () => checkContentLengthHeaderMiddlewareOptions, + getCheckContentLengthHeaderPlugin: () => getCheckContentLengthHeaderPlugin, + getRegionRedirectMiddlewarePlugin: () => getRegionRedirectMiddlewarePlugin, + getS3ExpiresMiddlewarePlugin: () => getS3ExpiresMiddlewarePlugin, + getS3ExpressHttpSigningPlugin: () => getS3ExpressHttpSigningPlugin, + getS3ExpressPlugin: () => getS3ExpressPlugin, + getThrow200ExceptionsPlugin: () => getThrow200ExceptionsPlugin, + getValidateBucketNamePlugin: () => getValidateBucketNamePlugin, + regionRedirectEndpointMiddleware: () => regionRedirectEndpointMiddleware, + regionRedirectEndpointMiddlewareOptions: () => regionRedirectEndpointMiddlewareOptions, + regionRedirectMiddleware: () => regionRedirectMiddleware, + regionRedirectMiddlewareOptions: () => regionRedirectMiddlewareOptions, + resolveS3Config: () => resolveS3Config, + s3ExpiresMiddleware: () => s3ExpiresMiddleware, + s3ExpiresMiddlewareOptions: () => s3ExpiresMiddlewareOptions, + s3ExpressHttpSigningMiddleware: () => s3ExpressHttpSigningMiddleware, + s3ExpressHttpSigningMiddlewareOptions: () => s3ExpressHttpSigningMiddlewareOptions, + s3ExpressMiddleware: () => s3ExpressMiddleware, + s3ExpressMiddlewareOptions: () => s3ExpressMiddlewareOptions, + throw200ExceptionsMiddleware: () => throw200ExceptionsMiddleware, + throw200ExceptionsMiddlewareOptions: () => throw200ExceptionsMiddlewareOptions, + validateBucketNameMiddleware: () => validateBucketNameMiddleware, + validateBucketNameMiddlewareOptions: () => validateBucketNameMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); + +// src/check-content-length-header.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client = __nccwpck_require__(61411); +var CONTENT_LENGTH_HEADER = "content-length"; +var DECODED_CONTENT_LENGTH_HEADER = "x-amz-decoded-content-length"; +function checkContentLengthHeader() { + return (next, context) => async (args) => { + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request)) { + if (!(CONTENT_LENGTH_HEADER in request.headers) && !(DECODED_CONTENT_LENGTH_HEADER in request.headers)) { + const message = `Are you using a Stream of unknown length as the Body of a PutObject request? Consider using Upload instead from @aws-sdk/lib-storage.`; + if (typeof context?.logger?.warn === "function" && !(context.logger instanceof import_smithy_client.NoOpLogger)) { + context.logger.warn(message); + } else { + console.warn(message); + } + } + } + return next({ ...args }); + }; +} +__name(checkContentLengthHeader, "checkContentLengthHeader"); +var checkContentLengthHeaderMiddlewareOptions = { + step: "finalizeRequest", + tags: ["CHECK_CONTENT_LENGTH_HEADER"], + name: "getCheckContentLengthHeaderPlugin", + override: true +}; +var getCheckContentLengthHeaderPlugin = /* @__PURE__ */ __name((unused) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(checkContentLengthHeader(), checkContentLengthHeaderMiddlewareOptions); + }, "applyToStack") +}), "getCheckContentLengthHeaderPlugin"); + +// src/region-redirect-endpoint-middleware.ts +var regionRedirectEndpointMiddleware = /* @__PURE__ */ __name((config) => { + return (next, context) => async (args) => { + const originalRegion = await config.region(); + const regionProviderRef = config.region; + let unlock = /* @__PURE__ */ __name(() => { + }, "unlock"); + if (context.__s3RegionRedirect) { + Object.defineProperty(config, "region", { + writable: false, + value: /* @__PURE__ */ __name(async () => { + return context.__s3RegionRedirect; + }, "value") + }); + unlock = /* @__PURE__ */ __name(() => Object.defineProperty(config, "region", { + writable: true, + value: regionProviderRef + }), "unlock"); + } + try { + const result = await next(args); + if (context.__s3RegionRedirect) { + unlock(); + const region = await config.region(); + if (originalRegion !== region) { + throw new Error("Region was not restored following S3 region redirect."); + } + } + return result; + } catch (e) { + unlock(); + throw e; + } + }; +}, "regionRedirectEndpointMiddleware"); +var regionRedirectEndpointMiddlewareOptions = { + tags: ["REGION_REDIRECT", "S3"], + name: "regionRedirectEndpointMiddleware", + override: true, + relation: "before", + toMiddleware: "endpointV2Middleware" +}; + +// src/region-redirect-middleware.ts +function regionRedirectMiddleware(clientConfig) { + return (next, context) => async (args) => { + try { + return await next(args); + } catch (err) { + if (clientConfig.followRegionRedirects) { + if (err?.$metadata?.httpStatusCode === 301 || // err.name === "PermanentRedirect" && --> removing the error name check, as that allows for HEAD operations (which have the 301 status code, but not the same error name) to be covered for region redirection as well + err?.$metadata?.httpStatusCode === 400 && err?.name === "IllegalLocationConstraintException") { + try { + const actualRegion = err.$response.headers["x-amz-bucket-region"]; + context.logger?.debug(`Redirecting from ${await clientConfig.region()} to ${actualRegion}`); + context.__s3RegionRedirect = actualRegion; + } catch (e) { + throw new Error("Region redirect failed: " + e); + } + return next(args); + } + } + throw err; + } + }; +} +__name(regionRedirectMiddleware, "regionRedirectMiddleware"); +var regionRedirectMiddlewareOptions = { + step: "initialize", + tags: ["REGION_REDIRECT", "S3"], + name: "regionRedirectMiddleware", + override: true +}; +var getRegionRedirectMiddlewarePlugin = /* @__PURE__ */ __name((clientConfig) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(regionRedirectMiddleware(clientConfig), regionRedirectMiddlewareOptions); + clientStack.addRelativeTo(regionRedirectEndpointMiddleware(clientConfig), regionRedirectEndpointMiddlewareOptions); + }, "applyToStack") +}), "getRegionRedirectMiddlewarePlugin"); + +// src/s3-expires-middleware.ts + + +var s3ExpiresMiddleware = /* @__PURE__ */ __name((config) => { + return (next, context) => async (args) => { + const result = await next(args); + const { response } = result; + if (import_protocol_http.HttpResponse.isInstance(response)) { + if (response.headers.expires) { + response.headers.expiresstring = response.headers.expires; + try { + (0, import_smithy_client.parseRfc7231DateTime)(response.headers.expires); + } catch (e) { + context.logger?.warn( + `AWS SDK Warning for ${context.clientName}::${context.commandName} response parsing (${response.headers.expires}): ${e}` + ); + delete response.headers.expires; + } + } + } + return result; + }; +}, "s3ExpiresMiddleware"); +var s3ExpiresMiddlewareOptions = { + tags: ["S3"], + name: "s3ExpiresMiddleware", + override: true, + relation: "after", + toMiddleware: "deserializerMiddleware" +}; +var getS3ExpiresMiddlewarePlugin = /* @__PURE__ */ __name((clientConfig) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo(s3ExpiresMiddleware(clientConfig), s3ExpiresMiddlewareOptions); + }, "applyToStack") +}), "getS3ExpiresMiddlewarePlugin"); + +// src/s3-express/classes/S3ExpressIdentityCache.ts +var S3ExpressIdentityCache = class _S3ExpressIdentityCache { + constructor(data = {}) { + this.data = data; + } + static { + __name(this, "S3ExpressIdentityCache"); + } + lastPurgeTime = Date.now(); + static EXPIRED_CREDENTIAL_PURGE_INTERVAL_MS = 3e4; + get(key) { + const entry = this.data[key]; + if (!entry) { + return; + } + return entry; + } + set(key, entry) { + this.data[key] = entry; + return entry; + } + delete(key) { + delete this.data[key]; + } + async purgeExpired() { + const now = Date.now(); + if (this.lastPurgeTime + _S3ExpressIdentityCache.EXPIRED_CREDENTIAL_PURGE_INTERVAL_MS > now) { + return; + } + for (const key in this.data) { + const entry = this.data[key]; + if (!entry.isRefreshing) { + const credential = await entry.identity; + if (credential.expiration) { + if (credential.expiration.getTime() < now) { + delete this.data[key]; + } + } + } + } + } +}; + +// src/s3-express/classes/S3ExpressIdentityCacheEntry.ts +var S3ExpressIdentityCacheEntry = class { + /** + * @param identity - stored identity. + * @param accessed - timestamp of last access in epoch ms. + * @param isRefreshing - this key is currently in the process of being refreshed (background). + */ + constructor(_identity, isRefreshing = false, accessed = Date.now()) { + this._identity = _identity; + this.isRefreshing = isRefreshing; + this.accessed = accessed; + } + static { + __name(this, "S3ExpressIdentityCacheEntry"); + } + get identity() { + this.accessed = Date.now(); + return this._identity; + } +}; + +// src/s3-express/classes/S3ExpressIdentityProviderImpl.ts +var S3ExpressIdentityProviderImpl = class _S3ExpressIdentityProviderImpl { + constructor(createSessionFn, cache = new S3ExpressIdentityCache()) { + this.createSessionFn = createSessionFn; + this.cache = cache; + } + static { + __name(this, "S3ExpressIdentityProviderImpl"); + } + static REFRESH_WINDOW_MS = 6e4; + async getS3ExpressIdentity(awsIdentity, identityProperties) { + const key = identityProperties.Bucket; + const { cache } = this; + const entry = cache.get(key); + if (entry) { + return entry.identity.then((identity) => { + const isExpired = (identity.expiration?.getTime() ?? 0) < Date.now(); + if (isExpired) { + return cache.set(key, new S3ExpressIdentityCacheEntry(this.getIdentity(key))).identity; + } + const isExpiringSoon = (identity.expiration?.getTime() ?? 0) < Date.now() + _S3ExpressIdentityProviderImpl.REFRESH_WINDOW_MS; + if (isExpiringSoon && !entry.isRefreshing) { + entry.isRefreshing = true; + this.getIdentity(key).then((id) => { + cache.set(key, new S3ExpressIdentityCacheEntry(Promise.resolve(id))); + }); + } + return identity; + }); + } + return cache.set(key, new S3ExpressIdentityCacheEntry(this.getIdentity(key))).identity; + } + async getIdentity(key) { + await this.cache.purgeExpired().catch((error) => { + console.warn("Error while clearing expired entries in S3ExpressIdentityCache: \n" + error); + }); + const session = await this.createSessionFn(key); + if (!session.Credentials?.AccessKeyId || !session.Credentials?.SecretAccessKey) { + throw new Error("s3#createSession response credential missing AccessKeyId or SecretAccessKey."); + } + const identity = { + accessKeyId: session.Credentials.AccessKeyId, + secretAccessKey: session.Credentials.SecretAccessKey, + sessionToken: session.Credentials.SessionToken, + expiration: session.Credentials.Expiration ? new Date(session.Credentials.Expiration) : void 0 + }; + return identity; + } +}; + +// src/s3-express/classes/SignatureV4S3Express.ts +var import_signature_v4 = __nccwpck_require__(75118); + +// src/s3-express/constants.ts +var import_util_config_provider = __nccwpck_require__(56716); +var S3_EXPRESS_BUCKET_TYPE = "Directory"; +var S3_EXPRESS_BACKEND = "S3Express"; +var S3_EXPRESS_AUTH_SCHEME = "sigv4-s3express"; +var SESSION_TOKEN_QUERY_PARAM = "X-Amz-S3session-Token"; +var SESSION_TOKEN_HEADER = SESSION_TOKEN_QUERY_PARAM.toLowerCase(); +var NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_ENV_NAME = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH"; +var NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_INI_NAME = "s3_disable_express_session_auth"; +var NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => (0, import_util_config_provider.booleanSelector)(env, NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_ENV_NAME, import_util_config_provider.SelectorType.ENV), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => (0, import_util_config_provider.booleanSelector)(profile, NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_INI_NAME, import_util_config_provider.SelectorType.CONFIG), "configFileSelector"), + default: false +}; + +// src/s3-express/classes/SignatureV4S3Express.ts +var SignatureV4S3Express = class extends import_signature_v4.SignatureV4 { + static { + __name(this, "SignatureV4S3Express"); + } + /** + * Signs with alternate provided credentials instead of those provided in the + * constructor. + * + * Additionally omits the credential sessionToken and assigns it to the + * alternate header field for S3 Express. + */ + async signWithCredentials(requestToSign, credentials, options) { + const credentialsWithoutSessionToken = getCredentialsWithoutSessionToken(credentials); + requestToSign.headers[SESSION_TOKEN_HEADER] = credentials.sessionToken; + const privateAccess = this; + setSingleOverride(privateAccess, credentialsWithoutSessionToken); + return privateAccess.signRequest(requestToSign, options ?? {}); + } + /** + * Similar to {@link SignatureV4S3Express#signWithCredentials} but for presigning. + */ + async presignWithCredentials(requestToSign, credentials, options) { + const credentialsWithoutSessionToken = getCredentialsWithoutSessionToken(credentials); + delete requestToSign.headers[SESSION_TOKEN_HEADER]; + requestToSign.headers[SESSION_TOKEN_QUERY_PARAM] = credentials.sessionToken; + requestToSign.query = requestToSign.query ?? {}; + requestToSign.query[SESSION_TOKEN_QUERY_PARAM] = credentials.sessionToken; + const privateAccess = this; + setSingleOverride(privateAccess, credentialsWithoutSessionToken); + return this.presign(requestToSign, options); + } +}; +function getCredentialsWithoutSessionToken(credentials) { + const credentialsWithoutSessionToken = { + accessKeyId: credentials.accessKeyId, + secretAccessKey: credentials.secretAccessKey, + expiration: credentials.expiration + }; + return credentialsWithoutSessionToken; +} +__name(getCredentialsWithoutSessionToken, "getCredentialsWithoutSessionToken"); +function setSingleOverride(privateAccess, credentialsWithoutSessionToken) { + const id = setTimeout(() => { + throw new Error("SignatureV4S3Express credential override was created but not called."); + }, 10); + const currentCredentialProvider = privateAccess.credentialProvider; + const overrideCredentialsProviderOnce = /* @__PURE__ */ __name(() => { + clearTimeout(id); + privateAccess.credentialProvider = currentCredentialProvider; + return Promise.resolve(credentialsWithoutSessionToken); + }, "overrideCredentialsProviderOnce"); + privateAccess.credentialProvider = overrideCredentialsProviderOnce; +} +__name(setSingleOverride, "setSingleOverride"); + +// src/s3-express/functions/s3ExpressMiddleware.ts +var import_core = __nccwpck_require__(8704); + +var s3ExpressMiddleware = /* @__PURE__ */ __name((options) => { + return (next, context) => async (args) => { + if (context.endpointV2) { + const endpoint = context.endpointV2; + const isS3ExpressAuth = endpoint.properties?.authSchemes?.[0]?.name === S3_EXPRESS_AUTH_SCHEME; + const isS3ExpressBucket = endpoint.properties?.backend === S3_EXPRESS_BACKEND || endpoint.properties?.bucketType === S3_EXPRESS_BUCKET_TYPE; + if (isS3ExpressBucket) { + (0, import_core.setFeature)(context, "S3_EXPRESS_BUCKET", "J"); + context.isS3ExpressBucket = true; + } + if (isS3ExpressAuth) { + const requestBucket = args.input.Bucket; + if (requestBucket) { + const s3ExpressIdentity = await options.s3ExpressIdentityProvider.getS3ExpressIdentity( + await options.credentials(), + { + Bucket: requestBucket + } + ); + context.s3ExpressIdentity = s3ExpressIdentity; + if (import_protocol_http.HttpRequest.isInstance(args.request) && s3ExpressIdentity.sessionToken) { + args.request.headers[SESSION_TOKEN_HEADER] = s3ExpressIdentity.sessionToken; + } + } + } + } + return next(args); + }; +}, "s3ExpressMiddleware"); +var s3ExpressMiddlewareOptions = { + name: "s3ExpressMiddleware", + step: "build", + tags: ["S3", "S3_EXPRESS"], + override: true +}; +var getS3ExpressPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(s3ExpressMiddleware(options), s3ExpressMiddlewareOptions); + }, "applyToStack") +}), "getS3ExpressPlugin"); + +// src/s3-express/functions/s3ExpressHttpSigningMiddleware.ts +var import_core2 = __nccwpck_require__(90402); + +var import_util_middleware = __nccwpck_require__(76324); + +// src/s3-express/functions/signS3Express.ts +var signS3Express = /* @__PURE__ */ __name(async (s3ExpressIdentity, signingOptions, request, sigV4MultiRegionSigner) => { + const signedRequest = await sigV4MultiRegionSigner.signWithCredentials(request, s3ExpressIdentity, {}); + if (signedRequest.headers["X-Amz-Security-Token"] || signedRequest.headers["x-amz-security-token"]) { + throw new Error("X-Amz-Security-Token must not be set for s3-express requests."); + } + return signedRequest; +}, "signS3Express"); + +// src/s3-express/functions/s3ExpressHttpSigningMiddleware.ts +var defaultErrorHandler = /* @__PURE__ */ __name((signingProperties) => (error) => { + throw error; +}, "defaultErrorHandler"); +var defaultSuccessHandler = /* @__PURE__ */ __name((httpResponse, signingProperties) => { +}, "defaultSuccessHandler"); +var s3ExpressHttpSigningMiddlewareOptions = import_core2.httpSigningMiddlewareOptions; +var s3ExpressHttpSigningMiddleware = /* @__PURE__ */ __name((config) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const scheme = smithyContext.selectedHttpAuthScheme; + if (!scheme) { + throw new Error(`No HttpAuthScheme was selected: unable to sign request`); + } + const { + httpAuthOption: { signingProperties = {} }, + identity, + signer + } = scheme; + let request; + if (context.s3ExpressIdentity) { + request = await signS3Express( + context.s3ExpressIdentity, + signingProperties, + args.request, + await config.signer() + ); + } else { + request = await signer.sign(args.request, identity, signingProperties); + } + const output = await next({ + ...args, + request + }).catch((signer.errorHandler || defaultErrorHandler)(signingProperties)); + (signer.successHandler || defaultSuccessHandler)(output.response, signingProperties); + return output; +}, "s3ExpressHttpSigningMiddleware"); +var getS3ExpressHttpSigningPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo( + s3ExpressHttpSigningMiddleware(config), + import_core2.httpSigningMiddlewareOptions + ); + }, "applyToStack") +}), "getS3ExpressHttpSigningPlugin"); + +// src/s3Configuration.ts +var resolveS3Config = /* @__PURE__ */ __name((input, { + session +}) => { + const [s3ClientProvider, CreateSessionCommandCtor] = session; + const { + forcePathStyle, + useAccelerateEndpoint, + disableMultiregionAccessPoints, + followRegionRedirects, + s3ExpressIdentityProvider, + bucketEndpoint + } = input; + return Object.assign(input, { + forcePathStyle: forcePathStyle ?? false, + useAccelerateEndpoint: useAccelerateEndpoint ?? false, + disableMultiregionAccessPoints: disableMultiregionAccessPoints ?? false, + followRegionRedirects: followRegionRedirects ?? false, + s3ExpressIdentityProvider: s3ExpressIdentityProvider ?? new S3ExpressIdentityProviderImpl( + async (key) => s3ClientProvider().send( + new CreateSessionCommandCtor({ + Bucket: key + }) + ) + ), + bucketEndpoint: bucketEndpoint ?? false + }); +}, "resolveS3Config"); + +// src/throw-200-exceptions.ts + +var import_util_stream = __nccwpck_require__(4252); +var THROW_IF_EMPTY_BODY = { + CopyObjectCommand: true, + UploadPartCopyCommand: true, + CompleteMultipartUploadCommand: true +}; +var MAX_BYTES_TO_INSPECT = 3e3; +var throw200ExceptionsMiddleware = /* @__PURE__ */ __name((config) => (next, context) => async (args) => { + const result = await next(args); + const { response } = result; + if (!import_protocol_http.HttpResponse.isInstance(response)) { + return result; + } + const { statusCode, body: sourceBody } = response; + if (statusCode < 200 || statusCode >= 300) { + return result; + } + const isSplittableStream = typeof sourceBody?.stream === "function" || typeof sourceBody?.pipe === "function" || typeof sourceBody?.tee === "function"; + if (!isSplittableStream) { + return result; + } + let bodyCopy = sourceBody; + let body = sourceBody; + if (sourceBody && typeof sourceBody === "object" && !(sourceBody instanceof Uint8Array)) { + [bodyCopy, body] = await (0, import_util_stream.splitStream)(sourceBody); + } + response.body = body; + const bodyBytes = await collectBody(bodyCopy, { + streamCollector: /* @__PURE__ */ __name(async (stream) => { + return (0, import_util_stream.headStream)(stream, MAX_BYTES_TO_INSPECT); + }, "streamCollector") + }); + if (typeof bodyCopy?.destroy === "function") { + bodyCopy.destroy(); + } + const bodyStringTail = config.utf8Encoder(bodyBytes.subarray(bodyBytes.length - 16)); + if (bodyBytes.length === 0 && THROW_IF_EMPTY_BODY[context.commandName]) { + const err = new Error("S3 aborted request"); + err.name = "InternalError"; + throw err; + } + if (bodyStringTail && bodyStringTail.endsWith("")) { + response.statusCode = 400; + } + return result; +}, "throw200ExceptionsMiddleware"); +var collectBody = /* @__PURE__ */ __name((streamBody = new Uint8Array(), context) => { + if (streamBody instanceof Uint8Array) { + return Promise.resolve(streamBody); + } + return context.streamCollector(streamBody) || Promise.resolve(new Uint8Array()); +}, "collectBody"); +var throw200ExceptionsMiddlewareOptions = { + relation: "after", + toMiddleware: "deserializerMiddleware", + tags: ["THROW_200_EXCEPTIONS", "S3"], + name: "throw200ExceptionsMiddleware", + override: true +}; +var getThrow200ExceptionsPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo(throw200ExceptionsMiddleware(config), throw200ExceptionsMiddlewareOptions); + }, "applyToStack") +}), "getThrow200ExceptionsPlugin"); + +// src/validate-bucket-name.ts +var import_util_arn_parser = __nccwpck_require__(56369); + +// src/bucket-endpoint-middleware.ts +function bucketEndpointMiddleware(options) { + return (next, context) => async (args) => { + if (options.bucketEndpoint) { + const endpoint = context.endpointV2; + if (endpoint) { + const bucket = args.input.Bucket; + if (typeof bucket === "string") { + try { + const bucketEndpointUrl = new URL(bucket); + context.endpointV2 = { + ...endpoint, + url: bucketEndpointUrl + }; + } catch (e) { + const warning = `@aws-sdk/middleware-sdk-s3: bucketEndpoint=true was set but Bucket=${bucket} could not be parsed as URL.`; + if (context.logger?.constructor?.name === "NoOpLogger") { + console.warn(warning); + } else { + context.logger?.warn?.(warning); + } + throw e; + } + } + } + } + return next(args); + }; +} +__name(bucketEndpointMiddleware, "bucketEndpointMiddleware"); +var bucketEndpointMiddlewareOptions = { + name: "bucketEndpointMiddleware", + override: true, + relation: "after", + toMiddleware: "endpointV2Middleware" +}; + +// src/validate-bucket-name.ts +function validateBucketNameMiddleware({ bucketEndpoint }) { + return (next) => async (args) => { + const { + input: { Bucket } + } = args; + if (!bucketEndpoint && typeof Bucket === "string" && !(0, import_util_arn_parser.validate)(Bucket) && Bucket.indexOf("/") >= 0) { + const err = new Error(`Bucket name shouldn't contain '/', received '${Bucket}'`); + err.name = "InvalidBucketName"; + throw err; + } + return next({ ...args }); + }; +} +__name(validateBucketNameMiddleware, "validateBucketNameMiddleware"); +var validateBucketNameMiddlewareOptions = { + step: "initialize", + tags: ["VALIDATE_BUCKET_NAME"], + name: "validateBucketNameMiddleware", + override: true +}; +var getValidateBucketNamePlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(validateBucketNameMiddleware(options), validateBucketNameMiddlewareOptions); + clientStack.addRelativeTo(bucketEndpointMiddleware(options), bucketEndpointMiddlewareOptions); + }, "applyToStack") +}), "getValidateBucketNamePlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 35568: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getSsecPlugin: () => getSsecPlugin, + isValidBase64EncodedSSECustomerKey: () => isValidBase64EncodedSSECustomerKey, + ssecMiddleware: () => ssecMiddleware, + ssecMiddlewareOptions: () => ssecMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); +function ssecMiddleware(options) { + return (next) => async (args) => { + const input = { ...args.input }; + const properties = [ + { + target: "SSECustomerKey", + hash: "SSECustomerKeyMD5" + }, + { + target: "CopySourceSSECustomerKey", + hash: "CopySourceSSECustomerKeyMD5" + } + ]; + for (const prop of properties) { + const value = input[prop.target]; + if (value) { + let valueForHash; + if (typeof value === "string") { + if (isValidBase64EncodedSSECustomerKey(value, options)) { + valueForHash = options.base64Decoder(value); + } else { + valueForHash = options.utf8Decoder(value); + input[prop.target] = options.base64Encoder(valueForHash); + } + } else { + valueForHash = ArrayBuffer.isView(value) ? new Uint8Array(value.buffer, value.byteOffset, value.byteLength) : new Uint8Array(value); + input[prop.target] = options.base64Encoder(valueForHash); + } + const hash = new options.md5(); + hash.update(valueForHash); + input[prop.hash] = options.base64Encoder(await hash.digest()); + } + } + return next({ + ...args, + input + }); + }; +} +__name(ssecMiddleware, "ssecMiddleware"); +var ssecMiddlewareOptions = { + name: "ssecMiddleware", + step: "initialize", + tags: ["SSE"], + override: true +}; +var getSsecPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(ssecMiddleware(config), ssecMiddlewareOptions); + }, "applyToStack") +}), "getSsecPlugin"); +function isValidBase64EncodedSSECustomerKey(str, options) { + const base64Regex = /^(?:[A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/; + if (!base64Regex.test(str)) return false; + try { + const decodedBytes = options.base64Decoder(str); + return decodedBytes.length === 32; + } catch { + return false; + } +} +__name(isValidBase64EncodedSSECustomerKey, "isValidBase64EncodedSSECustomerKey"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 32959: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + DEFAULT_UA_APP_ID: () => DEFAULT_UA_APP_ID, + getUserAgentMiddlewareOptions: () => getUserAgentMiddlewareOptions, + getUserAgentPlugin: () => getUserAgentPlugin, + resolveUserAgentConfig: () => resolveUserAgentConfig, + userAgentMiddleware: () => userAgentMiddleware +}); +module.exports = __toCommonJS(index_exports); + +// src/configurations.ts +var import_core = __nccwpck_require__(90402); +var DEFAULT_UA_APP_ID = void 0; +function isValidUserAgentAppId(appId) { + if (appId === void 0) { + return true; + } + return typeof appId === "string" && appId.length <= 50; +} +__name(isValidUserAgentAppId, "isValidUserAgentAppId"); +function resolveUserAgentConfig(input) { + const normalizedAppIdProvider = (0, import_core.normalizeProvider)(input.userAgentAppId ?? DEFAULT_UA_APP_ID); + const { customUserAgent } = input; + return Object.assign(input, { + customUserAgent: typeof customUserAgent === "string" ? [[customUserAgent]] : customUserAgent, + userAgentAppId: /* @__PURE__ */ __name(async () => { + const appId = await normalizedAppIdProvider(); + if (!isValidUserAgentAppId(appId)) { + const logger = input.logger?.constructor?.name === "NoOpLogger" || !input.logger ? console : input.logger; + if (typeof appId !== "string") { + logger?.warn("userAgentAppId must be a string or undefined."); + } else if (appId.length > 50) { + logger?.warn("The provided userAgentAppId exceeds the maximum length of 50 characters."); + } + } + return appId; + }, "userAgentAppId") + }); +} +__name(resolveUserAgentConfig, "resolveUserAgentConfig"); + +// src/user-agent-middleware.ts +var import_util_endpoints = __nccwpck_require__(83068); +var import_protocol_http = __nccwpck_require__(72356); + +// src/check-features.ts +var import_core2 = __nccwpck_require__(8704); +var ACCOUNT_ID_ENDPOINT_REGEX = /\d{12}\.ddb/; +async function checkFeatures(context, config, args) { + const request = args.request; + if (request?.headers?.["smithy-protocol"] === "rpc-v2-cbor") { + (0, import_core2.setFeature)(context, "PROTOCOL_RPC_V2_CBOR", "M"); + } + if (typeof config.retryStrategy === "function") { + const retryStrategy = await config.retryStrategy(); + if (typeof retryStrategy.acquireInitialRetryToken === "function") { + if (retryStrategy.constructor?.name?.includes("Adaptive")) { + (0, import_core2.setFeature)(context, "RETRY_MODE_ADAPTIVE", "F"); + } else { + (0, import_core2.setFeature)(context, "RETRY_MODE_STANDARD", "E"); + } + } else { + (0, import_core2.setFeature)(context, "RETRY_MODE_LEGACY", "D"); + } + } + if (typeof config.accountIdEndpointMode === "function") { + const endpointV2 = context.endpointV2; + if (String(endpointV2?.url?.hostname).match(ACCOUNT_ID_ENDPOINT_REGEX)) { + (0, import_core2.setFeature)(context, "ACCOUNT_ID_ENDPOINT", "O"); + } + switch (await config.accountIdEndpointMode?.()) { + case "disabled": + (0, import_core2.setFeature)(context, "ACCOUNT_ID_MODE_DISABLED", "Q"); + break; + case "preferred": + (0, import_core2.setFeature)(context, "ACCOUNT_ID_MODE_PREFERRED", "P"); + break; + case "required": + (0, import_core2.setFeature)(context, "ACCOUNT_ID_MODE_REQUIRED", "R"); + break; + } + } + const identity = context.__smithy_context?.selectedHttpAuthScheme?.identity; + if (identity?.$source) { + const credentials = identity; + if (credentials.accountId) { + (0, import_core2.setFeature)(context, "RESOLVED_ACCOUNT_ID", "T"); + } + for (const [key, value] of Object.entries(credentials.$source ?? {})) { + (0, import_core2.setFeature)(context, key, value); + } + } +} +__name(checkFeatures, "checkFeatures"); + +// src/constants.ts +var USER_AGENT = "user-agent"; +var X_AMZ_USER_AGENT = "x-amz-user-agent"; +var SPACE = " "; +var UA_NAME_SEPARATOR = "/"; +var UA_NAME_ESCAPE_REGEX = /[^\!\$\%\&\'\*\+\-\.\^\_\`\|\~\d\w]/g; +var UA_VALUE_ESCAPE_REGEX = /[^\!\$\%\&\'\*\+\-\.\^\_\`\|\~\d\w\#]/g; +var UA_ESCAPE_CHAR = "-"; + +// src/encode-features.ts +var BYTE_LIMIT = 1024; +function encodeFeatures(features) { + let buffer = ""; + for (const key in features) { + const val = features[key]; + if (buffer.length + val.length + 1 <= BYTE_LIMIT) { + if (buffer.length) { + buffer += "," + val; + } else { + buffer += val; + } + continue; + } + break; + } + return buffer; +} +__name(encodeFeatures, "encodeFeatures"); + +// src/user-agent-middleware.ts +var userAgentMiddleware = /* @__PURE__ */ __name((options) => (next, context) => async (args) => { + const { request } = args; + if (!import_protocol_http.HttpRequest.isInstance(request)) { + return next(args); + } + const { headers } = request; + const userAgent = context?.userAgent?.map(escapeUserAgent) || []; + const defaultUserAgent = (await options.defaultUserAgentProvider()).map(escapeUserAgent); + await checkFeatures(context, options, args); + const awsContext = context; + defaultUserAgent.push( + `m/${encodeFeatures( + Object.assign({}, context.__smithy_context?.features, awsContext.__aws_sdk_context?.features) + )}` + ); + const customUserAgent = options?.customUserAgent?.map(escapeUserAgent) || []; + const appId = await options.userAgentAppId(); + if (appId) { + defaultUserAgent.push(escapeUserAgent([`app/${appId}`])); + } + const prefix = (0, import_util_endpoints.getUserAgentPrefix)(); + const sdkUserAgentValue = (prefix ? [prefix] : []).concat([...defaultUserAgent, ...userAgent, ...customUserAgent]).join(SPACE); + const normalUAValue = [ + ...defaultUserAgent.filter((section) => section.startsWith("aws-sdk-")), + ...customUserAgent + ].join(SPACE); + if (options.runtime !== "browser") { + if (normalUAValue) { + headers[X_AMZ_USER_AGENT] = headers[X_AMZ_USER_AGENT] ? `${headers[USER_AGENT]} ${normalUAValue}` : normalUAValue; + } + headers[USER_AGENT] = sdkUserAgentValue; + } else { + headers[X_AMZ_USER_AGENT] = sdkUserAgentValue; + } + return next({ + ...args, + request + }); +}, "userAgentMiddleware"); +var escapeUserAgent = /* @__PURE__ */ __name((userAgentPair) => { + const name = userAgentPair[0].split(UA_NAME_SEPARATOR).map((part) => part.replace(UA_NAME_ESCAPE_REGEX, UA_ESCAPE_CHAR)).join(UA_NAME_SEPARATOR); + const version = userAgentPair[1]?.replace(UA_VALUE_ESCAPE_REGEX, UA_ESCAPE_CHAR); + const prefixSeparatorIndex = name.indexOf(UA_NAME_SEPARATOR); + const prefix = name.substring(0, prefixSeparatorIndex); + let uaName = name.substring(prefixSeparatorIndex + 1); + if (prefix === "api") { + uaName = uaName.toLowerCase(); + } + return [prefix, uaName, version].filter((item) => item && item.length > 0).reduce((acc, item, index) => { + switch (index) { + case 0: + return item; + case 1: + return `${acc}/${item}`; + default: + return `${acc}#${item}`; + } + }, ""); +}, "escapeUserAgent"); +var getUserAgentMiddlewareOptions = { + name: "getUserAgentMiddleware", + step: "build", + priority: "low", + tags: ["SET_USER_AGENT", "USER_AGENT"], + override: true +}; +var getUserAgentPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(userAgentMiddleware(config), getUserAgentMiddlewareOptions); + }, "applyToStack") +}), "getUserAgentPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 8396: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.defaultSSOOIDCHttpAuthSchemeProvider = exports.defaultSSOOIDCHttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const util_middleware_1 = __nccwpck_require__(76324); +const defaultSSOOIDCHttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultSSOOIDCHttpAuthSchemeParametersProvider = defaultSSOOIDCHttpAuthSchemeParametersProvider; +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "sso-oauth", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createSmithyApiNoAuthHttpAuthOption(authParameters) { + return { + schemeId: "smithy.api#noAuth", + }; +} +const defaultSSOOIDCHttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + case "CreateToken": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultSSOOIDCHttpAuthSchemeProvider = defaultSSOOIDCHttpAuthSchemeProvider; +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config); + return Object.assign(config_0, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 90546: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(69947); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: ["Endpoint", "Region", "UseDualStack", "UseFIPS"], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 69947: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const u = "required", v = "fn", w = "argv", x = "ref"; +const a = true, b = "isSet", c = "booleanEquals", d = "error", e = "endpoint", f = "tree", g = "PartitionResult", h = "getAttr", i = { [u]: false, "type": "String" }, j = { [u]: true, "default": false, "type": "Boolean" }, k = { [x]: "Endpoint" }, l = { [v]: c, [w]: [{ [x]: "UseFIPS" }, true] }, m = { [v]: c, [w]: [{ [x]: "UseDualStack" }, true] }, n = {}, o = { [v]: h, [w]: [{ [x]: g }, "supportsFIPS"] }, p = { [x]: g }, q = { [v]: c, [w]: [true, { [v]: h, [w]: [p, "supportsDualStack"] }] }, r = [l], s = [m], t = [{ [x]: "Region" }]; +const _data = { version: "1.0", parameters: { Region: i, UseDualStack: j, UseFIPS: j, Endpoint: i }, rules: [{ conditions: [{ [v]: b, [w]: [k] }], rules: [{ conditions: r, error: "Invalid Configuration: FIPS and custom endpoint are not supported", type: d }, { conditions: s, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", type: d }, { endpoint: { url: k, properties: n, headers: n }, type: e }], type: f }, { conditions: [{ [v]: b, [w]: t }], rules: [{ conditions: [{ [v]: "aws.partition", [w]: t, assign: g }], rules: [{ conditions: [l, m], rules: [{ conditions: [{ [v]: c, [w]: [a, o] }, q], rules: [{ endpoint: { url: "https://oidc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", type: d }], type: f }, { conditions: r, rules: [{ conditions: [{ [v]: c, [w]: [o, a] }], rules: [{ conditions: [{ [v]: "stringEquals", [w]: [{ [v]: h, [w]: [p, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://oidc.{Region}.amazonaws.com", properties: n, headers: n }, type: e }, { endpoint: { url: "https://oidc-fips.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS is enabled but this partition does not support FIPS", type: d }], type: f }, { conditions: s, rules: [{ conditions: [q], rules: [{ endpoint: { url: "https://oidc.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "DualStack is enabled but this partition does not support DualStack", type: d }], type: f }, { endpoint: { url: "https://oidc.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }], type: f }, { error: "Invalid Configuration: Missing Region", type: d }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 89443: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/sso-oidc/index.ts +var index_exports = {}; +__export(index_exports, { + $Command: () => import_smithy_client6.Command, + AccessDeniedException: () => AccessDeniedException, + AuthorizationPendingException: () => AuthorizationPendingException, + CreateTokenCommand: () => CreateTokenCommand, + CreateTokenRequestFilterSensitiveLog: () => CreateTokenRequestFilterSensitiveLog, + CreateTokenResponseFilterSensitiveLog: () => CreateTokenResponseFilterSensitiveLog, + ExpiredTokenException: () => ExpiredTokenException, + InternalServerException: () => InternalServerException, + InvalidClientException: () => InvalidClientException, + InvalidGrantException: () => InvalidGrantException, + InvalidRequestException: () => InvalidRequestException, + InvalidScopeException: () => InvalidScopeException, + SSOOIDC: () => SSOOIDC, + SSOOIDCClient: () => SSOOIDCClient, + SSOOIDCServiceException: () => SSOOIDCServiceException, + SlowDownException: () => SlowDownException, + UnauthorizedClientException: () => UnauthorizedClientException, + UnsupportedGrantTypeException: () => UnsupportedGrantTypeException, + __Client: () => import_smithy_client2.Client +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/sso-oidc/SSOOIDCClient.ts +var import_middleware_host_header = __nccwpck_require__(52590); +var import_middleware_logger = __nccwpck_require__(85242); +var import_middleware_recursion_detection = __nccwpck_require__(81568); +var import_middleware_user_agent = __nccwpck_require__(32959); +var import_config_resolver = __nccwpck_require__(39316); +var import_core = __nccwpck_require__(90402); +var import_middleware_content_length = __nccwpck_require__(47212); +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_retry = __nccwpck_require__(19618); +var import_smithy_client2 = __nccwpck_require__(61411); +var import_httpAuthSchemeProvider = __nccwpck_require__(8396); + +// src/submodules/sso-oidc/endpoint/EndpointParameters.ts +var resolveClientEndpointParameters = /* @__PURE__ */ __name((options) => { + return Object.assign(options, { + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + useFipsEndpoint: options.useFipsEndpoint ?? false, + defaultSigningName: "sso-oauth" + }); +}, "resolveClientEndpointParameters"); +var commonParams = { + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" } +}; + +// src/submodules/sso-oidc/SSOOIDCClient.ts +var import_runtimeConfig = __nccwpck_require__(16901); + +// src/submodules/sso-oidc/runtimeExtensions.ts +var import_region_config_resolver = __nccwpck_require__(36463); +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/auth/httpAuthExtensionConfiguration.ts +var getHttpAuthExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + } + }; +}, "getHttpAuthExtensionConfiguration"); +var resolveHttpAuthRuntimeConfig = /* @__PURE__ */ __name((config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials() + }; +}, "resolveHttpAuthRuntimeConfig"); + +// src/submodules/sso-oidc/runtimeExtensions.ts +var resolveRuntimeExtensions = /* @__PURE__ */ __name((runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign( + (0, import_region_config_resolver.getAwsRegionExtensionConfiguration)(runtimeConfig), + (0, import_smithy_client.getDefaultExtensionConfiguration)(runtimeConfig), + (0, import_protocol_http.getHttpHandlerExtensionConfiguration)(runtimeConfig), + getHttpAuthExtensionConfiguration(runtimeConfig) + ); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign( + runtimeConfig, + (0, import_region_config_resolver.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), + (0, import_smithy_client.resolveDefaultRuntimeConfig)(extensionConfiguration), + (0, import_protocol_http.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), + resolveHttpAuthRuntimeConfig(extensionConfiguration) + ); +}, "resolveRuntimeExtensions"); + +// src/submodules/sso-oidc/SSOOIDCClient.ts +var SSOOIDCClient = class extends import_smithy_client2.Client { + static { + __name(this, "SSOOIDCClient"); + } + /** + * The resolved configuration of SSOOIDCClient class. This is resolved and normalized from the {@link SSOOIDCClientConfig | constructor configuration interface}. + */ + config; + constructor(...[configuration]) { + const _config_0 = (0, import_runtimeConfig.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = resolveClientEndpointParameters(_config_0); + const _config_2 = (0, import_middleware_user_agent.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, import_middleware_retry.resolveRetryConfig)(_config_2); + const _config_4 = (0, import_config_resolver.resolveRegionConfig)(_config_3); + const _config_5 = (0, import_middleware_host_header.resolveHostHeaderConfig)(_config_4); + const _config_6 = (0, import_middleware_endpoint.resolveEndpointConfig)(_config_5); + const _config_7 = (0, import_httpAuthSchemeProvider.resolveHttpAuthSchemeConfig)(_config_6); + const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []); + this.config = _config_8; + this.middlewareStack.use((0, import_middleware_user_agent.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_retry.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_content_length.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_host_header.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_logger.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_recursion_detection.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use( + (0, import_core.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: import_httpAuthSchemeProvider.defaultSSOOIDCHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: /* @__PURE__ */ __name(async (config) => new import_core.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials + }), "identityProviderConfigProvider") + }) + ); + this.middlewareStack.use((0, import_core.getHttpSigningPlugin)(this.config)); + } + /** + * Destroy underlying resources, like sockets. It's usually not necessary to do this. + * However in Node.js, it's best to explicitly shut down the client's agent when it is no longer needed. + * Otherwise, sockets might stay open for quite a long time before the server terminates them. + */ + destroy() { + super.destroy(); + } +}; + +// src/submodules/sso-oidc/SSOOIDC.ts +var import_smithy_client7 = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/commands/CreateTokenCommand.ts +var import_middleware_endpoint2 = __nccwpck_require__(40099); +var import_middleware_serde = __nccwpck_require__(83255); +var import_smithy_client6 = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/models/models_0.ts +var import_smithy_client4 = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/models/SSOOIDCServiceException.ts +var import_smithy_client3 = __nccwpck_require__(61411); +var SSOOIDCServiceException = class _SSOOIDCServiceException extends import_smithy_client3.ServiceException { + static { + __name(this, "SSOOIDCServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _SSOOIDCServiceException.prototype); + } +}; + +// src/submodules/sso-oidc/models/models_0.ts +var AccessDeniedException = class _AccessDeniedException extends SSOOIDCServiceException { + static { + __name(this, "AccessDeniedException"); + } + name = "AccessDeniedException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be access_denied.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "AccessDeniedException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _AccessDeniedException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var AuthorizationPendingException = class _AuthorizationPendingException extends SSOOIDCServiceException { + static { + __name(this, "AuthorizationPendingException"); + } + name = "AuthorizationPendingException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * authorization_pending.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "AuthorizationPendingException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _AuthorizationPendingException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var CreateTokenRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.clientSecret && { clientSecret: import_smithy_client4.SENSITIVE_STRING }, + ...obj.refreshToken && { refreshToken: import_smithy_client4.SENSITIVE_STRING }, + ...obj.codeVerifier && { codeVerifier: import_smithy_client4.SENSITIVE_STRING } +}), "CreateTokenRequestFilterSensitiveLog"); +var CreateTokenResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client4.SENSITIVE_STRING }, + ...obj.refreshToken && { refreshToken: import_smithy_client4.SENSITIVE_STRING }, + ...obj.idToken && { idToken: import_smithy_client4.SENSITIVE_STRING } +}), "CreateTokenResponseFilterSensitiveLog"); +var ExpiredTokenException = class _ExpiredTokenException extends SSOOIDCServiceException { + static { + __name(this, "ExpiredTokenException"); + } + name = "ExpiredTokenException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be expired_token.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ExpiredTokenException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ExpiredTokenException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InternalServerException = class _InternalServerException extends SSOOIDCServiceException { + static { + __name(this, "InternalServerException"); + } + name = "InternalServerException"; + $fault = "server"; + /** + *

Single error code. For this exception the value will be server_error.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InternalServerException", + $fault: "server", + ...opts + }); + Object.setPrototypeOf(this, _InternalServerException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidClientException = class _InvalidClientException extends SSOOIDCServiceException { + static { + __name(this, "InvalidClientException"); + } + name = "InvalidClientException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * invalid_client.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidClientException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidClientException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidGrantException = class _InvalidGrantException extends SSOOIDCServiceException { + static { + __name(this, "InvalidGrantException"); + } + name = "InvalidGrantException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be invalid_grant.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidGrantException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidGrantException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidRequestException = class _InvalidRequestException extends SSOOIDCServiceException { + static { + __name(this, "InvalidRequestException"); + } + name = "InvalidRequestException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * invalid_request.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidRequestException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidRequestException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidScopeException = class _InvalidScopeException extends SSOOIDCServiceException { + static { + __name(this, "InvalidScopeException"); + } + name = "InvalidScopeException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be invalid_scope.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidScopeException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidScopeException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var SlowDownException = class _SlowDownException extends SSOOIDCServiceException { + static { + __name(this, "SlowDownException"); + } + name = "SlowDownException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be slow_down.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "SlowDownException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _SlowDownException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var UnauthorizedClientException = class _UnauthorizedClientException extends SSOOIDCServiceException { + static { + __name(this, "UnauthorizedClientException"); + } + name = "UnauthorizedClientException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * unauthorized_client.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "UnauthorizedClientException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _UnauthorizedClientException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var UnsupportedGrantTypeException = class _UnsupportedGrantTypeException extends SSOOIDCServiceException { + static { + __name(this, "UnsupportedGrantTypeException"); + } + name = "UnsupportedGrantTypeException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * unsupported_grant_type.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "UnsupportedGrantTypeException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _UnsupportedGrantTypeException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; + +// src/submodules/sso-oidc/protocols/Aws_restJson1.ts +var import_core2 = __nccwpck_require__(8704); +var import_core3 = __nccwpck_require__(90402); +var import_smithy_client5 = __nccwpck_require__(61411); +var se_CreateTokenCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core3.requestBuilder)(input, context); + const headers = { + "content-type": "application/json" + }; + b.bp("/token"); + let body; + body = JSON.stringify( + (0, import_smithy_client5.take)(input, { + clientId: [], + clientSecret: [], + code: [], + codeVerifier: [], + deviceCode: [], + grantType: [], + redirectUri: [], + refreshToken: [], + scope: /* @__PURE__ */ __name((_) => (0, import_smithy_client5._json)(_), "scope") + }) + ); + b.m("POST").h(headers).b(body); + return b.build(); +}, "se_CreateTokenCommand"); +var de_CreateTokenCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client5.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client5.expectNonNull)((0, import_smithy_client5.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client5.take)(data, { + accessToken: import_smithy_client5.expectString, + expiresIn: import_smithy_client5.expectInt32, + idToken: import_smithy_client5.expectString, + refreshToken: import_smithy_client5.expectString, + tokenType: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + return contents; +}, "de_CreateTokenCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core2.parseJsonErrorBody)(output.body, context) + }; + const errorCode = (0, import_core2.loadRestJsonErrorCode)(output, parsedOutput.body); + switch (errorCode) { + case "AccessDeniedException": + case "com.amazonaws.ssooidc#AccessDeniedException": + throw await de_AccessDeniedExceptionRes(parsedOutput, context); + case "AuthorizationPendingException": + case "com.amazonaws.ssooidc#AuthorizationPendingException": + throw await de_AuthorizationPendingExceptionRes(parsedOutput, context); + case "ExpiredTokenException": + case "com.amazonaws.ssooidc#ExpiredTokenException": + throw await de_ExpiredTokenExceptionRes(parsedOutput, context); + case "InternalServerException": + case "com.amazonaws.ssooidc#InternalServerException": + throw await de_InternalServerExceptionRes(parsedOutput, context); + case "InvalidClientException": + case "com.amazonaws.ssooidc#InvalidClientException": + throw await de_InvalidClientExceptionRes(parsedOutput, context); + case "InvalidGrantException": + case "com.amazonaws.ssooidc#InvalidGrantException": + throw await de_InvalidGrantExceptionRes(parsedOutput, context); + case "InvalidRequestException": + case "com.amazonaws.ssooidc#InvalidRequestException": + throw await de_InvalidRequestExceptionRes(parsedOutput, context); + case "InvalidScopeException": + case "com.amazonaws.ssooidc#InvalidScopeException": + throw await de_InvalidScopeExceptionRes(parsedOutput, context); + case "SlowDownException": + case "com.amazonaws.ssooidc#SlowDownException": + throw await de_SlowDownExceptionRes(parsedOutput, context); + case "UnauthorizedClientException": + case "com.amazonaws.ssooidc#UnauthorizedClientException": + throw await de_UnauthorizedClientExceptionRes(parsedOutput, context); + case "UnsupportedGrantTypeException": + case "com.amazonaws.ssooidc#UnsupportedGrantTypeException": + throw await de_UnsupportedGrantTypeExceptionRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody, + errorCode + }); + } +}, "de_CommandError"); +var throwDefaultError = (0, import_smithy_client5.withBaseException)(SSOOIDCServiceException); +var de_AccessDeniedExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new AccessDeniedException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_AccessDeniedExceptionRes"); +var de_AuthorizationPendingExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new AuthorizationPendingException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_AuthorizationPendingExceptionRes"); +var de_ExpiredTokenExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new ExpiredTokenException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_ExpiredTokenExceptionRes"); +var de_InternalServerExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InternalServerException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InternalServerExceptionRes"); +var de_InvalidClientExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidClientException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidClientExceptionRes"); +var de_InvalidGrantExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidGrantException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidGrantExceptionRes"); +var de_InvalidRequestExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidRequestException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidRequestExceptionRes"); +var de_InvalidScopeExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidScopeException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidScopeExceptionRes"); +var de_SlowDownExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new SlowDownException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_SlowDownExceptionRes"); +var de_UnauthorizedClientExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new UnauthorizedClientException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_UnauthorizedClientExceptionRes"); +var de_UnsupportedGrantTypeExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new UnsupportedGrantTypeException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_UnsupportedGrantTypeExceptionRes"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); + +// src/submodules/sso-oidc/commands/CreateTokenCommand.ts +var CreateTokenCommand = class extends import_smithy_client6.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint2.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AWSSSOOIDCService", "CreateToken", {}).n("SSOOIDCClient", "CreateTokenCommand").f(CreateTokenRequestFilterSensitiveLog, CreateTokenResponseFilterSensitiveLog).ser(se_CreateTokenCommand).de(de_CreateTokenCommand).build() { + static { + __name(this, "CreateTokenCommand"); + } +}; + +// src/submodules/sso-oidc/SSOOIDC.ts +var commands = { + CreateTokenCommand +}; +var SSOOIDC = class extends SSOOIDCClient { + static { + __name(this, "SSOOIDC"); + } +}; +(0, import_smithy_client7.createAggregatedClient)(commands, SSOOIDC); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 16901: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(39955)); +const core_1 = __nccwpck_require__(8704); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const hash_node_1 = __nccwpck_require__(5092); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(1546); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 1546: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const core_2 = __nccwpck_require__(90402); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(8396); +const endpointResolver_1 = __nccwpck_require__(90546); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2019-06-10", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSSOOIDCHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + serviceId: config?.serviceId ?? "SSO OIDC", + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 63723: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.STSClient = exports.__Client = void 0; +const middleware_host_header_1 = __nccwpck_require__(52590); +const middleware_logger_1 = __nccwpck_require__(85242); +const middleware_recursion_detection_1 = __nccwpck_require__(81568); +const middleware_user_agent_1 = __nccwpck_require__(32959); +const config_resolver_1 = __nccwpck_require__(39316); +const core_1 = __nccwpck_require__(90402); +const middleware_content_length_1 = __nccwpck_require__(47212); +const middleware_endpoint_1 = __nccwpck_require__(40099); +const middleware_retry_1 = __nccwpck_require__(19618); +const smithy_client_1 = __nccwpck_require__(61411); +Object.defineProperty(exports, "__Client", ({ enumerable: true, get: function () { return smithy_client_1.Client; } })); +const httpAuthSchemeProvider_1 = __nccwpck_require__(27851); +const EndpointParameters_1 = __nccwpck_require__(76811); +const runtimeConfig_1 = __nccwpck_require__(36578); +const runtimeExtensions_1 = __nccwpck_require__(37742); +class STSClient extends smithy_client_1.Client { + config; + constructor(...[configuration]) { + const _config_0 = (0, runtimeConfig_1.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = (0, EndpointParameters_1.resolveClientEndpointParameters)(_config_0); + const _config_2 = (0, middleware_user_agent_1.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, middleware_retry_1.resolveRetryConfig)(_config_2); + const _config_4 = (0, config_resolver_1.resolveRegionConfig)(_config_3); + const _config_5 = (0, middleware_host_header_1.resolveHostHeaderConfig)(_config_4); + const _config_6 = (0, middleware_endpoint_1.resolveEndpointConfig)(_config_5); + const _config_7 = (0, httpAuthSchemeProvider_1.resolveHttpAuthSchemeConfig)(_config_6); + const _config_8 = (0, runtimeExtensions_1.resolveRuntimeExtensions)(_config_7, configuration?.extensions || []); + this.config = _config_8; + this.middlewareStack.use((0, middleware_user_agent_1.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, middleware_retry_1.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, middleware_content_length_1.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, middleware_host_header_1.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, middleware_logger_1.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, middleware_recursion_detection_1.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use((0, core_1.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: httpAuthSchemeProvider_1.defaultSTSHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: async (config) => new core_1.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials, + }), + })); + this.middlewareStack.use((0, core_1.getHttpSigningPlugin)(this.config)); + } + destroy() { + super.destroy(); + } +} +exports.STSClient = STSClient; + + +/***/ }), + +/***/ 34532: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthRuntimeConfig = exports.getHttpAuthExtensionConfiguration = void 0; +const getHttpAuthExtensionConfiguration = (runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } + else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + }, + }; +}; +exports.getHttpAuthExtensionConfiguration = getHttpAuthExtensionConfiguration; +const resolveHttpAuthRuntimeConfig = (config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials(), + }; +}; +exports.resolveHttpAuthRuntimeConfig = resolveHttpAuthRuntimeConfig; + + +/***/ }), + +/***/ 27851: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.resolveStsAuthConfig = exports.defaultSTSHttpAuthSchemeProvider = exports.defaultSTSHttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const util_middleware_1 = __nccwpck_require__(76324); +const STSClient_1 = __nccwpck_require__(63723); +const defaultSTSHttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultSTSHttpAuthSchemeParametersProvider = defaultSTSHttpAuthSchemeParametersProvider; +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "sts", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createSmithyApiNoAuthHttpAuthOption(authParameters) { + return { + schemeId: "smithy.api#noAuth", + }; +} +const defaultSTSHttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + case "AssumeRoleWithWebIdentity": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultSTSHttpAuthSchemeProvider = defaultSTSHttpAuthSchemeProvider; +const resolveStsAuthConfig = (input) => Object.assign(input, { + stsClientCtor: STSClient_1.STSClient, +}); +exports.resolveStsAuthConfig = resolveStsAuthConfig; +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, exports.resolveStsAuthConfig)(config); + const config_1 = (0, core_1.resolveAwsSdkSigV4Config)(config_0); + return Object.assign(config_1, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 76811: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.commonParams = exports.resolveClientEndpointParameters = void 0; +const resolveClientEndpointParameters = (options) => { + return Object.assign(options, { + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + useFipsEndpoint: options.useFipsEndpoint ?? false, + useGlobalEndpoint: options.useGlobalEndpoint ?? false, + defaultSigningName: "sts", + }); +}; +exports.resolveClientEndpointParameters = resolveClientEndpointParameters; +exports.commonParams = { + UseGlobalEndpoint: { type: "builtInParams", name: "useGlobalEndpoint" }, + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" }, +}; + + +/***/ }), + +/***/ 59765: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(31670); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: ["Endpoint", "Region", "UseDualStack", "UseFIPS", "UseGlobalEndpoint"], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 31670: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const F = "required", G = "type", H = "fn", I = "argv", J = "ref"; +const a = false, b = true, c = "booleanEquals", d = "stringEquals", e = "sigv4", f = "sts", g = "us-east-1", h = "endpoint", i = "https://sts.{Region}.{PartitionResult#dnsSuffix}", j = "tree", k = "error", l = "getAttr", m = { [F]: false, [G]: "String" }, n = { [F]: true, "default": false, [G]: "Boolean" }, o = { [J]: "Endpoint" }, p = { [H]: "isSet", [I]: [{ [J]: "Region" }] }, q = { [J]: "Region" }, r = { [H]: "aws.partition", [I]: [q], "assign": "PartitionResult" }, s = { [J]: "UseFIPS" }, t = { [J]: "UseDualStack" }, u = { "url": "https://sts.amazonaws.com", "properties": { "authSchemes": [{ "name": e, "signingName": f, "signingRegion": g }] }, "headers": {} }, v = {}, w = { "conditions": [{ [H]: d, [I]: [q, "aws-global"] }], [h]: u, [G]: h }, x = { [H]: c, [I]: [s, true] }, y = { [H]: c, [I]: [t, true] }, z = { [H]: l, [I]: [{ [J]: "PartitionResult" }, "supportsFIPS"] }, A = { [J]: "PartitionResult" }, B = { [H]: c, [I]: [true, { [H]: l, [I]: [A, "supportsDualStack"] }] }, C = [{ [H]: "isSet", [I]: [o] }], D = [x], E = [y]; +const _data = { version: "1.0", parameters: { Region: m, UseDualStack: n, UseFIPS: n, Endpoint: m, UseGlobalEndpoint: n }, rules: [{ conditions: [{ [H]: c, [I]: [{ [J]: "UseGlobalEndpoint" }, b] }, { [H]: "not", [I]: C }, p, r, { [H]: c, [I]: [s, a] }, { [H]: c, [I]: [t, a] }], rules: [{ conditions: [{ [H]: d, [I]: [q, "ap-northeast-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-south-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-southeast-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-southeast-2"] }], endpoint: u, [G]: h }, w, { conditions: [{ [H]: d, [I]: [q, "ca-central-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-central-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-north-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-2"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-3"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "sa-east-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, g] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-east-2"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-west-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-west-2"] }], endpoint: u, [G]: h }, { endpoint: { url: i, properties: { authSchemes: [{ name: e, signingName: f, signingRegion: "{Region}" }] }, headers: v }, [G]: h }], [G]: j }, { conditions: C, rules: [{ conditions: D, error: "Invalid Configuration: FIPS and custom endpoint are not supported", [G]: k }, { conditions: E, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", [G]: k }, { endpoint: { url: o, properties: v, headers: v }, [G]: h }], [G]: j }, { conditions: [p], rules: [{ conditions: [r], rules: [{ conditions: [x, y], rules: [{ conditions: [{ [H]: c, [I]: [b, z] }, B], rules: [{ endpoint: { url: "https://sts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", [G]: k }], [G]: j }, { conditions: D, rules: [{ conditions: [{ [H]: c, [I]: [z, b] }], rules: [{ conditions: [{ [H]: d, [I]: [{ [H]: l, [I]: [A, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://sts.{Region}.amazonaws.com", properties: v, headers: v }, [G]: h }, { endpoint: { url: "https://sts-fips.{Region}.{PartitionResult#dnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "FIPS is enabled but this partition does not support FIPS", [G]: k }], [G]: j }, { conditions: E, rules: [{ conditions: [B], rules: [{ endpoint: { url: "https://sts.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "DualStack is enabled but this partition does not support DualStack", [G]: k }], [G]: j }, w, { endpoint: { url: i, properties: v, headers: v }, [G]: h }], [G]: j }], [G]: j }, { error: "Invalid Configuration: Missing Region", [G]: k }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 1136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/sts/index.ts +var index_exports = {}; +__export(index_exports, { + AssumeRoleCommand: () => AssumeRoleCommand, + AssumeRoleResponseFilterSensitiveLog: () => AssumeRoleResponseFilterSensitiveLog, + AssumeRoleWithWebIdentityCommand: () => AssumeRoleWithWebIdentityCommand, + AssumeRoleWithWebIdentityRequestFilterSensitiveLog: () => AssumeRoleWithWebIdentityRequestFilterSensitiveLog, + AssumeRoleWithWebIdentityResponseFilterSensitiveLog: () => AssumeRoleWithWebIdentityResponseFilterSensitiveLog, + ClientInputEndpointParameters: () => import_EndpointParameters3.ClientInputEndpointParameters, + CredentialsFilterSensitiveLog: () => CredentialsFilterSensitiveLog, + ExpiredTokenException: () => ExpiredTokenException, + IDPCommunicationErrorException: () => IDPCommunicationErrorException, + IDPRejectedClaimException: () => IDPRejectedClaimException, + InvalidIdentityTokenException: () => InvalidIdentityTokenException, + MalformedPolicyDocumentException: () => MalformedPolicyDocumentException, + PackedPolicyTooLargeException: () => PackedPolicyTooLargeException, + RegionDisabledException: () => RegionDisabledException, + STS: () => STS, + STSServiceException: () => STSServiceException, + decorateDefaultCredentialProvider: () => decorateDefaultCredentialProvider, + getDefaultRoleAssumer: () => getDefaultRoleAssumer2, + getDefaultRoleAssumerWithWebIdentity: () => getDefaultRoleAssumerWithWebIdentity2 +}); +module.exports = __toCommonJS(index_exports); +__reExport(index_exports, __nccwpck_require__(63723), module.exports); + +// src/submodules/sts/STS.ts +var import_smithy_client6 = __nccwpck_require__(61411); + +// src/submodules/sts/commands/AssumeRoleCommand.ts +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_serde = __nccwpck_require__(83255); +var import_smithy_client4 = __nccwpck_require__(61411); +var import_EndpointParameters = __nccwpck_require__(76811); + +// src/submodules/sts/models/models_0.ts +var import_smithy_client2 = __nccwpck_require__(61411); + +// src/submodules/sts/models/STSServiceException.ts +var import_smithy_client = __nccwpck_require__(61411); +var STSServiceException = class _STSServiceException extends import_smithy_client.ServiceException { + static { + __name(this, "STSServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _STSServiceException.prototype); + } +}; + +// src/submodules/sts/models/models_0.ts +var CredentialsFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SecretAccessKey && { SecretAccessKey: import_smithy_client2.SENSITIVE_STRING } +}), "CredentialsFilterSensitiveLog"); +var AssumeRoleResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Credentials && { Credentials: CredentialsFilterSensitiveLog(obj.Credentials) } +}), "AssumeRoleResponseFilterSensitiveLog"); +var ExpiredTokenException = class _ExpiredTokenException extends STSServiceException { + static { + __name(this, "ExpiredTokenException"); + } + name = "ExpiredTokenException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ExpiredTokenException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ExpiredTokenException.prototype); + } +}; +var MalformedPolicyDocumentException = class _MalformedPolicyDocumentException extends STSServiceException { + static { + __name(this, "MalformedPolicyDocumentException"); + } + name = "MalformedPolicyDocumentException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "MalformedPolicyDocumentException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _MalformedPolicyDocumentException.prototype); + } +}; +var PackedPolicyTooLargeException = class _PackedPolicyTooLargeException extends STSServiceException { + static { + __name(this, "PackedPolicyTooLargeException"); + } + name = "PackedPolicyTooLargeException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "PackedPolicyTooLargeException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _PackedPolicyTooLargeException.prototype); + } +}; +var RegionDisabledException = class _RegionDisabledException extends STSServiceException { + static { + __name(this, "RegionDisabledException"); + } + name = "RegionDisabledException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "RegionDisabledException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _RegionDisabledException.prototype); + } +}; +var IDPRejectedClaimException = class _IDPRejectedClaimException extends STSServiceException { + static { + __name(this, "IDPRejectedClaimException"); + } + name = "IDPRejectedClaimException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "IDPRejectedClaimException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _IDPRejectedClaimException.prototype); + } +}; +var InvalidIdentityTokenException = class _InvalidIdentityTokenException extends STSServiceException { + static { + __name(this, "InvalidIdentityTokenException"); + } + name = "InvalidIdentityTokenException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidIdentityTokenException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidIdentityTokenException.prototype); + } +}; +var AssumeRoleWithWebIdentityRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.WebIdentityToken && { WebIdentityToken: import_smithy_client2.SENSITIVE_STRING } +}), "AssumeRoleWithWebIdentityRequestFilterSensitiveLog"); +var AssumeRoleWithWebIdentityResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Credentials && { Credentials: CredentialsFilterSensitiveLog(obj.Credentials) } +}), "AssumeRoleWithWebIdentityResponseFilterSensitiveLog"); +var IDPCommunicationErrorException = class _IDPCommunicationErrorException extends STSServiceException { + static { + __name(this, "IDPCommunicationErrorException"); + } + name = "IDPCommunicationErrorException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "IDPCommunicationErrorException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _IDPCommunicationErrorException.prototype); + } +}; + +// src/submodules/sts/protocols/Aws_query.ts +var import_core = __nccwpck_require__(8704); +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client3 = __nccwpck_require__(61411); +var se_AssumeRoleCommand = /* @__PURE__ */ __name(async (input, context) => { + const headers = SHARED_HEADERS; + let body; + body = buildFormUrlencodedString({ + ...se_AssumeRoleRequest(input, context), + [_A]: _AR, + [_V]: _ + }); + return buildHttpRpcRequest(context, headers, "/", void 0, body); +}, "se_AssumeRoleCommand"); +var se_AssumeRoleWithWebIdentityCommand = /* @__PURE__ */ __name(async (input, context) => { + const headers = SHARED_HEADERS; + let body; + body = buildFormUrlencodedString({ + ...se_AssumeRoleWithWebIdentityRequest(input, context), + [_A]: _ARWWI, + [_V]: _ + }); + return buildHttpRpcRequest(context, headers, "/", void 0, body); +}, "se_AssumeRoleWithWebIdentityCommand"); +var de_AssumeRoleCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + const data = await (0, import_core.parseXmlBody)(output.body, context); + let contents = {}; + contents = de_AssumeRoleResponse(data.AssumeRoleResult, context); + const response = { + $metadata: deserializeMetadata(output), + ...contents + }; + return response; +}, "de_AssumeRoleCommand"); +var de_AssumeRoleWithWebIdentityCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + const data = await (0, import_core.parseXmlBody)(output.body, context); + let contents = {}; + contents = de_AssumeRoleWithWebIdentityResponse(data.AssumeRoleWithWebIdentityResult, context); + const response = { + $metadata: deserializeMetadata(output), + ...contents + }; + return response; +}, "de_AssumeRoleWithWebIdentityCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core.parseXmlErrorBody)(output.body, context) + }; + const errorCode = loadQueryErrorCode(output, parsedOutput.body); + switch (errorCode) { + case "ExpiredTokenException": + case "com.amazonaws.sts#ExpiredTokenException": + throw await de_ExpiredTokenExceptionRes(parsedOutput, context); + case "MalformedPolicyDocument": + case "com.amazonaws.sts#MalformedPolicyDocumentException": + throw await de_MalformedPolicyDocumentExceptionRes(parsedOutput, context); + case "PackedPolicyTooLarge": + case "com.amazonaws.sts#PackedPolicyTooLargeException": + throw await de_PackedPolicyTooLargeExceptionRes(parsedOutput, context); + case "RegionDisabledException": + case "com.amazonaws.sts#RegionDisabledException": + throw await de_RegionDisabledExceptionRes(parsedOutput, context); + case "IDPCommunicationError": + case "com.amazonaws.sts#IDPCommunicationErrorException": + throw await de_IDPCommunicationErrorExceptionRes(parsedOutput, context); + case "IDPRejectedClaim": + case "com.amazonaws.sts#IDPRejectedClaimException": + throw await de_IDPRejectedClaimExceptionRes(parsedOutput, context); + case "InvalidIdentityToken": + case "com.amazonaws.sts#InvalidIdentityTokenException": + throw await de_InvalidIdentityTokenExceptionRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody: parsedBody.Error, + errorCode + }); + } +}, "de_CommandError"); +var de_ExpiredTokenExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_ExpiredTokenException(body.Error, context); + const exception = new ExpiredTokenException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_ExpiredTokenExceptionRes"); +var de_IDPCommunicationErrorExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_IDPCommunicationErrorException(body.Error, context); + const exception = new IDPCommunicationErrorException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_IDPCommunicationErrorExceptionRes"); +var de_IDPRejectedClaimExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_IDPRejectedClaimException(body.Error, context); + const exception = new IDPRejectedClaimException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_IDPRejectedClaimExceptionRes"); +var de_InvalidIdentityTokenExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_InvalidIdentityTokenException(body.Error, context); + const exception = new InvalidIdentityTokenException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_InvalidIdentityTokenExceptionRes"); +var de_MalformedPolicyDocumentExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_MalformedPolicyDocumentException(body.Error, context); + const exception = new MalformedPolicyDocumentException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_MalformedPolicyDocumentExceptionRes"); +var de_PackedPolicyTooLargeExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_PackedPolicyTooLargeException(body.Error, context); + const exception = new PackedPolicyTooLargeException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_PackedPolicyTooLargeExceptionRes"); +var de_RegionDisabledExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_RegionDisabledException(body.Error, context); + const exception = new RegionDisabledException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_RegionDisabledExceptionRes"); +var se_AssumeRoleRequest = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_RA] != null) { + entries[_RA] = input[_RA]; + } + if (input[_RSN] != null) { + entries[_RSN] = input[_RSN]; + } + if (input[_PA] != null) { + const memberEntries = se_policyDescriptorListType(input[_PA], context); + if (input[_PA]?.length === 0) { + entries.PolicyArns = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `PolicyArns.${key}`; + entries[loc] = value; + }); + } + if (input[_P] != null) { + entries[_P] = input[_P]; + } + if (input[_DS] != null) { + entries[_DS] = input[_DS]; + } + if (input[_T] != null) { + const memberEntries = se_tagListType(input[_T], context); + if (input[_T]?.length === 0) { + entries.Tags = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `Tags.${key}`; + entries[loc] = value; + }); + } + if (input[_TTK] != null) { + const memberEntries = se_tagKeyListType(input[_TTK], context); + if (input[_TTK]?.length === 0) { + entries.TransitiveTagKeys = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `TransitiveTagKeys.${key}`; + entries[loc] = value; + }); + } + if (input[_EI] != null) { + entries[_EI] = input[_EI]; + } + if (input[_SN] != null) { + entries[_SN] = input[_SN]; + } + if (input[_TC] != null) { + entries[_TC] = input[_TC]; + } + if (input[_SI] != null) { + entries[_SI] = input[_SI]; + } + if (input[_PC] != null) { + const memberEntries = se_ProvidedContextsListType(input[_PC], context); + if (input[_PC]?.length === 0) { + entries.ProvidedContexts = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `ProvidedContexts.${key}`; + entries[loc] = value; + }); + } + return entries; +}, "se_AssumeRoleRequest"); +var se_AssumeRoleWithWebIdentityRequest = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_RA] != null) { + entries[_RA] = input[_RA]; + } + if (input[_RSN] != null) { + entries[_RSN] = input[_RSN]; + } + if (input[_WIT] != null) { + entries[_WIT] = input[_WIT]; + } + if (input[_PI] != null) { + entries[_PI] = input[_PI]; + } + if (input[_PA] != null) { + const memberEntries = se_policyDescriptorListType(input[_PA], context); + if (input[_PA]?.length === 0) { + entries.PolicyArns = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `PolicyArns.${key}`; + entries[loc] = value; + }); + } + if (input[_P] != null) { + entries[_P] = input[_P]; + } + if (input[_DS] != null) { + entries[_DS] = input[_DS]; + } + return entries; +}, "se_AssumeRoleWithWebIdentityRequest"); +var se_policyDescriptorListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + const memberEntries = se_PolicyDescriptorType(entry, context); + Object.entries(memberEntries).forEach(([key, value]) => { + entries[`member.${counter}.${key}`] = value; + }); + counter++; + } + return entries; +}, "se_policyDescriptorListType"); +var se_PolicyDescriptorType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_a] != null) { + entries[_a] = input[_a]; + } + return entries; +}, "se_PolicyDescriptorType"); +var se_ProvidedContext = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_PAr] != null) { + entries[_PAr] = input[_PAr]; + } + if (input[_CA] != null) { + entries[_CA] = input[_CA]; + } + return entries; +}, "se_ProvidedContext"); +var se_ProvidedContextsListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + const memberEntries = se_ProvidedContext(entry, context); + Object.entries(memberEntries).forEach(([key, value]) => { + entries[`member.${counter}.${key}`] = value; + }); + counter++; + } + return entries; +}, "se_ProvidedContextsListType"); +var se_Tag = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_K] != null) { + entries[_K] = input[_K]; + } + if (input[_Va] != null) { + entries[_Va] = input[_Va]; + } + return entries; +}, "se_Tag"); +var se_tagKeyListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + entries[`member.${counter}`] = entry; + counter++; + } + return entries; +}, "se_tagKeyListType"); +var se_tagListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + const memberEntries = se_Tag(entry, context); + Object.entries(memberEntries).forEach(([key, value]) => { + entries[`member.${counter}.${key}`] = value; + }); + counter++; + } + return entries; +}, "se_tagListType"); +var de_AssumedRoleUser = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ARI] != null) { + contents[_ARI] = (0, import_smithy_client3.expectString)(output[_ARI]); + } + if (output[_Ar] != null) { + contents[_Ar] = (0, import_smithy_client3.expectString)(output[_Ar]); + } + return contents; +}, "de_AssumedRoleUser"); +var de_AssumeRoleResponse = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_C] != null) { + contents[_C] = de_Credentials(output[_C], context); + } + if (output[_ARU] != null) { + contents[_ARU] = de_AssumedRoleUser(output[_ARU], context); + } + if (output[_PPS] != null) { + contents[_PPS] = (0, import_smithy_client3.strictParseInt32)(output[_PPS]); + } + if (output[_SI] != null) { + contents[_SI] = (0, import_smithy_client3.expectString)(output[_SI]); + } + return contents; +}, "de_AssumeRoleResponse"); +var de_AssumeRoleWithWebIdentityResponse = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_C] != null) { + contents[_C] = de_Credentials(output[_C], context); + } + if (output[_SFWIT] != null) { + contents[_SFWIT] = (0, import_smithy_client3.expectString)(output[_SFWIT]); + } + if (output[_ARU] != null) { + contents[_ARU] = de_AssumedRoleUser(output[_ARU], context); + } + if (output[_PPS] != null) { + contents[_PPS] = (0, import_smithy_client3.strictParseInt32)(output[_PPS]); + } + if (output[_Pr] != null) { + contents[_Pr] = (0, import_smithy_client3.expectString)(output[_Pr]); + } + if (output[_Au] != null) { + contents[_Au] = (0, import_smithy_client3.expectString)(output[_Au]); + } + if (output[_SI] != null) { + contents[_SI] = (0, import_smithy_client3.expectString)(output[_SI]); + } + return contents; +}, "de_AssumeRoleWithWebIdentityResponse"); +var de_Credentials = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_AKI] != null) { + contents[_AKI] = (0, import_smithy_client3.expectString)(output[_AKI]); + } + if (output[_SAK] != null) { + contents[_SAK] = (0, import_smithy_client3.expectString)(output[_SAK]); + } + if (output[_ST] != null) { + contents[_ST] = (0, import_smithy_client3.expectString)(output[_ST]); + } + if (output[_E] != null) { + contents[_E] = (0, import_smithy_client3.expectNonNull)((0, import_smithy_client3.parseRfc3339DateTimeWithOffset)(output[_E])); + } + return contents; +}, "de_Credentials"); +var de_ExpiredTokenException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_ExpiredTokenException"); +var de_IDPCommunicationErrorException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_IDPCommunicationErrorException"); +var de_IDPRejectedClaimException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_IDPRejectedClaimException"); +var de_InvalidIdentityTokenException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_InvalidIdentityTokenException"); +var de_MalformedPolicyDocumentException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_MalformedPolicyDocumentException"); +var de_PackedPolicyTooLargeException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_PackedPolicyTooLargeException"); +var de_RegionDisabledException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_RegionDisabledException"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); +var throwDefaultError = (0, import_smithy_client3.withBaseException)(STSServiceException); +var buildHttpRpcRequest = /* @__PURE__ */ __name(async (context, headers, path, resolvedHostname, body) => { + const { hostname, protocol = "https", port, path: basePath } = await context.endpoint(); + const contents = { + protocol, + hostname, + port, + method: "POST", + path: basePath.endsWith("/") ? basePath.slice(0, -1) + path : basePath + path, + headers + }; + if (resolvedHostname !== void 0) { + contents.hostname = resolvedHostname; + } + if (body !== void 0) { + contents.body = body; + } + return new import_protocol_http.HttpRequest(contents); +}, "buildHttpRpcRequest"); +var SHARED_HEADERS = { + "content-type": "application/x-www-form-urlencoded" +}; +var _ = "2011-06-15"; +var _A = "Action"; +var _AKI = "AccessKeyId"; +var _AR = "AssumeRole"; +var _ARI = "AssumedRoleId"; +var _ARU = "AssumedRoleUser"; +var _ARWWI = "AssumeRoleWithWebIdentity"; +var _Ar = "Arn"; +var _Au = "Audience"; +var _C = "Credentials"; +var _CA = "ContextAssertion"; +var _DS = "DurationSeconds"; +var _E = "Expiration"; +var _EI = "ExternalId"; +var _K = "Key"; +var _P = "Policy"; +var _PA = "PolicyArns"; +var _PAr = "ProviderArn"; +var _PC = "ProvidedContexts"; +var _PI = "ProviderId"; +var _PPS = "PackedPolicySize"; +var _Pr = "Provider"; +var _RA = "RoleArn"; +var _RSN = "RoleSessionName"; +var _SAK = "SecretAccessKey"; +var _SFWIT = "SubjectFromWebIdentityToken"; +var _SI = "SourceIdentity"; +var _SN = "SerialNumber"; +var _ST = "SessionToken"; +var _T = "Tags"; +var _TC = "TokenCode"; +var _TTK = "TransitiveTagKeys"; +var _V = "Version"; +var _Va = "Value"; +var _WIT = "WebIdentityToken"; +var _a = "arn"; +var _m = "message"; +var buildFormUrlencodedString = /* @__PURE__ */ __name((formEntries) => Object.entries(formEntries).map(([key, value]) => (0, import_smithy_client3.extendedEncodeURIComponent)(key) + "=" + (0, import_smithy_client3.extendedEncodeURIComponent)(value)).join("&"), "buildFormUrlencodedString"); +var loadQueryErrorCode = /* @__PURE__ */ __name((output, data) => { + if (data.Error?.Code !== void 0) { + return data.Error.Code; + } + if (output.statusCode == 404) { + return "NotFound"; + } +}, "loadQueryErrorCode"); + +// src/submodules/sts/commands/AssumeRoleCommand.ts +var AssumeRoleCommand = class extends import_smithy_client4.Command.classBuilder().ep(import_EndpointParameters.commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AWSSecurityTokenServiceV20110615", "AssumeRole", {}).n("STSClient", "AssumeRoleCommand").f(void 0, AssumeRoleResponseFilterSensitiveLog).ser(se_AssumeRoleCommand).de(de_AssumeRoleCommand).build() { + static { + __name(this, "AssumeRoleCommand"); + } +}; + +// src/submodules/sts/commands/AssumeRoleWithWebIdentityCommand.ts +var import_middleware_endpoint2 = __nccwpck_require__(40099); +var import_middleware_serde2 = __nccwpck_require__(83255); +var import_smithy_client5 = __nccwpck_require__(61411); +var import_EndpointParameters2 = __nccwpck_require__(76811); +var AssumeRoleWithWebIdentityCommand = class extends import_smithy_client5.Command.classBuilder().ep(import_EndpointParameters2.commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde2.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint2.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AWSSecurityTokenServiceV20110615", "AssumeRoleWithWebIdentity", {}).n("STSClient", "AssumeRoleWithWebIdentityCommand").f(AssumeRoleWithWebIdentityRequestFilterSensitiveLog, AssumeRoleWithWebIdentityResponseFilterSensitiveLog).ser(se_AssumeRoleWithWebIdentityCommand).de(de_AssumeRoleWithWebIdentityCommand).build() { + static { + __name(this, "AssumeRoleWithWebIdentityCommand"); + } +}; + +// src/submodules/sts/STS.ts +var import_STSClient = __nccwpck_require__(63723); +var commands = { + AssumeRoleCommand, + AssumeRoleWithWebIdentityCommand +}; +var STS = class extends import_STSClient.STSClient { + static { + __name(this, "STS"); + } +}; +(0, import_smithy_client6.createAggregatedClient)(commands, STS); + +// src/submodules/sts/index.ts +var import_EndpointParameters3 = __nccwpck_require__(76811); + +// src/submodules/sts/defaultStsRoleAssumers.ts +var import_client = __nccwpck_require__(5152); +var ASSUME_ROLE_DEFAULT_REGION = "us-east-1"; +var getAccountIdFromAssumedRoleUser = /* @__PURE__ */ __name((assumedRoleUser) => { + if (typeof assumedRoleUser?.Arn === "string") { + const arnComponents = assumedRoleUser.Arn.split(":"); + if (arnComponents.length > 4 && arnComponents[4] !== "") { + return arnComponents[4]; + } + } + return void 0; +}, "getAccountIdFromAssumedRoleUser"); +var resolveRegion = /* @__PURE__ */ __name(async (_region, _parentRegion, credentialProviderLogger) => { + const region = typeof _region === "function" ? await _region() : _region; + const parentRegion = typeof _parentRegion === "function" ? await _parentRegion() : _parentRegion; + credentialProviderLogger?.debug?.( + "@aws-sdk/client-sts::resolveRegion", + "accepting first of:", + `${region} (provider)`, + `${parentRegion} (parent client)`, + `${ASSUME_ROLE_DEFAULT_REGION} (STS default)` + ); + return region ?? parentRegion ?? ASSUME_ROLE_DEFAULT_REGION; +}, "resolveRegion"); +var getDefaultRoleAssumer = /* @__PURE__ */ __name((stsOptions, STSClient3) => { + let stsClient; + let closureSourceCreds; + return async (sourceCreds, params) => { + closureSourceCreds = sourceCreds; + if (!stsClient) { + const { + logger = stsOptions?.parentClientConfig?.logger, + region, + requestHandler = stsOptions?.parentClientConfig?.requestHandler, + credentialProviderLogger + } = stsOptions; + const resolvedRegion = await resolveRegion( + region, + stsOptions?.parentClientConfig?.region, + credentialProviderLogger + ); + const isCompatibleRequestHandler = !isH2(requestHandler); + stsClient = new STSClient3({ + profile: stsOptions?.parentClientConfig?.profile, + // A hack to make sts client uses the credential in current closure. + credentialDefaultProvider: /* @__PURE__ */ __name(() => async () => closureSourceCreds, "credentialDefaultProvider"), + region: resolvedRegion, + requestHandler: isCompatibleRequestHandler ? requestHandler : void 0, + logger + }); + } + const { Credentials: Credentials2, AssumedRoleUser: AssumedRoleUser2 } = await stsClient.send(new AssumeRoleCommand(params)); + if (!Credentials2 || !Credentials2.AccessKeyId || !Credentials2.SecretAccessKey) { + throw new Error(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`); + } + const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser2); + const credentials = { + accessKeyId: Credentials2.AccessKeyId, + secretAccessKey: Credentials2.SecretAccessKey, + sessionToken: Credentials2.SessionToken, + expiration: Credentials2.Expiration, + // TODO(credentialScope): access normally when shape is updated. + ...Credentials2.CredentialScope && { credentialScope: Credentials2.CredentialScope }, + ...accountId && { accountId } + }; + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_STS_ASSUME_ROLE", "i"); + return credentials; + }; +}, "getDefaultRoleAssumer"); +var getDefaultRoleAssumerWithWebIdentity = /* @__PURE__ */ __name((stsOptions, STSClient3) => { + let stsClient; + return async (params) => { + if (!stsClient) { + const { + logger = stsOptions?.parentClientConfig?.logger, + region, + requestHandler = stsOptions?.parentClientConfig?.requestHandler, + credentialProviderLogger + } = stsOptions; + const resolvedRegion = await resolveRegion( + region, + stsOptions?.parentClientConfig?.region, + credentialProviderLogger + ); + const isCompatibleRequestHandler = !isH2(requestHandler); + stsClient = new STSClient3({ + profile: stsOptions?.parentClientConfig?.profile, + region: resolvedRegion, + requestHandler: isCompatibleRequestHandler ? requestHandler : void 0, + logger + }); + } + const { Credentials: Credentials2, AssumedRoleUser: AssumedRoleUser2 } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params)); + if (!Credentials2 || !Credentials2.AccessKeyId || !Credentials2.SecretAccessKey) { + throw new Error(`Invalid response from STS.assumeRoleWithWebIdentity call with role ${params.RoleArn}`); + } + const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser2); + const credentials = { + accessKeyId: Credentials2.AccessKeyId, + secretAccessKey: Credentials2.SecretAccessKey, + sessionToken: Credentials2.SessionToken, + expiration: Credentials2.Expiration, + // TODO(credentialScope): access normally when shape is updated. + ...Credentials2.CredentialScope && { credentialScope: Credentials2.CredentialScope }, + ...accountId && { accountId } + }; + if (accountId) { + (0, import_client.setCredentialFeature)(credentials, "RESOLVED_ACCOUNT_ID", "T"); + } + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID", "k"); + return credentials; + }; +}, "getDefaultRoleAssumerWithWebIdentity"); +var isH2 = /* @__PURE__ */ __name((requestHandler) => { + return requestHandler?.metadata?.handlerProtocol === "h2"; +}, "isH2"); + +// src/submodules/sts/defaultRoleAssumers.ts +var import_STSClient2 = __nccwpck_require__(63723); +var getCustomizableStsClientCtor = /* @__PURE__ */ __name((baseCtor, customizations) => { + if (!customizations) return baseCtor; + else + return class CustomizableSTSClient extends baseCtor { + static { + __name(this, "CustomizableSTSClient"); + } + constructor(config) { + super(config); + for (const customization of customizations) { + this.middlewareStack.use(customization); + } + } + }; +}, "getCustomizableStsClientCtor"); +var getDefaultRoleAssumer2 = /* @__PURE__ */ __name((stsOptions = {}, stsPlugins) => getDefaultRoleAssumer(stsOptions, getCustomizableStsClientCtor(import_STSClient2.STSClient, stsPlugins)), "getDefaultRoleAssumer"); +var getDefaultRoleAssumerWithWebIdentity2 = /* @__PURE__ */ __name((stsOptions = {}, stsPlugins) => getDefaultRoleAssumerWithWebIdentity(stsOptions, getCustomizableStsClientCtor(import_STSClient2.STSClient, stsPlugins)), "getDefaultRoleAssumerWithWebIdentity"); +var decorateDefaultCredentialProvider = /* @__PURE__ */ __name((provider) => (input) => provider({ + roleAssumer: getDefaultRoleAssumer2(input), + roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity2(input), + ...input +}), "decorateDefaultCredentialProvider"); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 36578: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(39955)); +const core_1 = __nccwpck_require__(8704); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const core_2 = __nccwpck_require__(90402); +const hash_node_1 = __nccwpck_require__(5092); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(24443); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4") || + (async (idProps) => await config.credentialDefaultProvider(idProps?.__config || {})()), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 24443: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const core_2 = __nccwpck_require__(90402); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(27851); +const endpointResolver_1 = __nccwpck_require__(59765); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2011-06-15", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSTSHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + serviceId: config?.serviceId ?? "STS", + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 37742: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveRuntimeExtensions = void 0; +const region_config_resolver_1 = __nccwpck_require__(36463); +const protocol_http_1 = __nccwpck_require__(72356); +const smithy_client_1 = __nccwpck_require__(61411); +const httpAuthExtensionConfiguration_1 = __nccwpck_require__(34532); +const resolveRuntimeExtensions = (runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign((0, region_config_resolver_1.getAwsRegionExtensionConfiguration)(runtimeConfig), (0, smithy_client_1.getDefaultExtensionConfiguration)(runtimeConfig), (0, protocol_http_1.getHttpHandlerExtensionConfiguration)(runtimeConfig), (0, httpAuthExtensionConfiguration_1.getHttpAuthExtensionConfiguration)(runtimeConfig)); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign(runtimeConfig, (0, region_config_resolver_1.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), (0, smithy_client_1.resolveDefaultRuntimeConfig)(extensionConfiguration), (0, protocol_http_1.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), (0, httpAuthExtensionConfiguration_1.resolveHttpAuthRuntimeConfig)(extensionConfiguration)); +}; +exports.resolveRuntimeExtensions = resolveRuntimeExtensions; + + +/***/ }), + +/***/ 36463: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_REGION_CONFIG_FILE_OPTIONS: () => NODE_REGION_CONFIG_FILE_OPTIONS, + NODE_REGION_CONFIG_OPTIONS: () => NODE_REGION_CONFIG_OPTIONS, + REGION_ENV_NAME: () => REGION_ENV_NAME, + REGION_INI_NAME: () => REGION_INI_NAME, + getAwsRegionExtensionConfiguration: () => getAwsRegionExtensionConfiguration, + resolveAwsRegionExtensionConfiguration: () => resolveAwsRegionExtensionConfiguration, + resolveRegionConfig: () => resolveRegionConfig +}); +module.exports = __toCommonJS(index_exports); + +// src/extensions/index.ts +var getAwsRegionExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return { + setRegion(region) { + runtimeConfig.region = region; + }, + region() { + return runtimeConfig.region; + } + }; +}, "getAwsRegionExtensionConfiguration"); +var resolveAwsRegionExtensionConfiguration = /* @__PURE__ */ __name((awsRegionExtensionConfiguration) => { + return { + region: awsRegionExtensionConfiguration.region() + }; +}, "resolveAwsRegionExtensionConfiguration"); + +// src/regionConfig/config.ts +var REGION_ENV_NAME = "AWS_REGION"; +var REGION_INI_NAME = "region"; +var NODE_REGION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => env[REGION_ENV_NAME], "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => profile[REGION_INI_NAME], "configFileSelector"), + default: /* @__PURE__ */ __name(() => { + throw new Error("Region is missing"); + }, "default") +}; +var NODE_REGION_CONFIG_FILE_OPTIONS = { + preferredFile: "credentials" +}; + +// src/regionConfig/isFipsRegion.ts +var isFipsRegion = /* @__PURE__ */ __name((region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips")), "isFipsRegion"); + +// src/regionConfig/getRealRegion.ts +var getRealRegion = /* @__PURE__ */ __name((region) => isFipsRegion(region) ? ["fips-aws-global", "aws-fips"].includes(region) ? "us-east-1" : region.replace(/fips-(dkr-|prod-)?|-fips/, "") : region, "getRealRegion"); + +// src/regionConfig/resolveRegionConfig.ts +var resolveRegionConfig = /* @__PURE__ */ __name((input) => { + const { region, useFipsEndpoint } = input; + if (!region) { + throw new Error("Region is missing"); + } + return Object.assign(input, { + region: /* @__PURE__ */ __name(async () => { + if (typeof region === "string") { + return getRealRegion(region); + } + const providedRegion = await region(); + return getRealRegion(providedRegion); + }, "region"), + useFipsEndpoint: /* @__PURE__ */ __name(async () => { + const providedRegion = typeof region === "string" ? region : await region(); + if (isFipsRegion(providedRegion)) { + return true; + } + return typeof useFipsEndpoint !== "function" ? Promise.resolve(!!useFipsEndpoint) : useFipsEndpoint(); + }, "useFipsEndpoint") + }); +}, "resolveRegionConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 5785: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + SignatureV4MultiRegion: () => SignatureV4MultiRegion, + signatureV4CrtContainer: () => signatureV4CrtContainer +}); +module.exports = __toCommonJS(index_exports); + +// src/SignatureV4MultiRegion.ts +var import_middleware_sdk_s3 = __nccwpck_require__(77445); +var import_signature_v4 = __nccwpck_require__(75118); + +// src/signature-v4-crt-container.ts +var signatureV4CrtContainer = { + CrtSignerV4: null +}; + +// src/SignatureV4MultiRegion.ts +var SignatureV4MultiRegion = class { + static { + __name(this, "SignatureV4MultiRegion"); + } + sigv4aSigner; + sigv4Signer; + signerOptions; + static sigv4aDependency() { + if (typeof signatureV4CrtContainer.CrtSignerV4 === "function") { + return "crt"; + } else if (typeof import_signature_v4.signatureV4aContainer.SignatureV4a === "function") { + return "js"; + } + return "none"; + } + constructor(options) { + this.sigv4Signer = new import_middleware_sdk_s3.SignatureV4S3Express(options); + this.signerOptions = options; + } + async sign(requestToSign, options = {}) { + if (options.signingRegion === "*") { + return this.getSigv4aSigner().sign(requestToSign, options); + } + return this.sigv4Signer.sign(requestToSign, options); + } + /** + * Sign with alternate credentials to the ones provided in the constructor. + * Note: This is only supported for SigV4a when using the CRT implementation. + */ + async signWithCredentials(requestToSign, credentials, options = {}) { + if (options.signingRegion === "*") { + const signer = this.getSigv4aSigner(); + const CrtSignerV4 = signatureV4CrtContainer.CrtSignerV4; + if (CrtSignerV4 && signer instanceof CrtSignerV4) { + return signer.signWithCredentials(requestToSign, credentials, options); + } else { + throw new Error( + `signWithCredentials with signingRegion '*' is only supported when using the CRT dependency @aws-sdk/signature-v4-crt. Please check whether you have installed the "@aws-sdk/signature-v4-crt" package explicitly. You must also register the package by calling [require("@aws-sdk/signature-v4-crt");] or an ESM equivalent such as [import "@aws-sdk/signature-v4-crt";]. For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt` + ); + } + } + return this.sigv4Signer.signWithCredentials(requestToSign, credentials, options); + } + /** + * Presign a request. + * Note: This is only supported for SigV4a when using the CRT implementation. + */ + async presign(originalRequest, options = {}) { + if (options.signingRegion === "*") { + const signer = this.getSigv4aSigner(); + const CrtSignerV4 = signatureV4CrtContainer.CrtSignerV4; + if (CrtSignerV4 && signer instanceof CrtSignerV4) { + return signer.presign(originalRequest, options); + } else { + throw new Error( + `presign with signingRegion '*' is only supported when using the CRT dependency @aws-sdk/signature-v4-crt. Please check whether you have installed the "@aws-sdk/signature-v4-crt" package explicitly. You must also register the package by calling [require("@aws-sdk/signature-v4-crt");] or an ESM equivalent such as [import "@aws-sdk/signature-v4-crt";]. For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt` + ); + } + } + return this.sigv4Signer.presign(originalRequest, options); + } + async presignWithCredentials(originalRequest, credentials, options = {}) { + if (options.signingRegion === "*") { + throw new Error("Method presignWithCredentials is not supported for [signingRegion=*]."); + } + return this.sigv4Signer.presignWithCredentials(originalRequest, credentials, options); + } + getSigv4aSigner() { + if (!this.sigv4aSigner) { + const CrtSignerV4 = signatureV4CrtContainer.CrtSignerV4; + const JsSigV4aSigner = import_signature_v4.signatureV4aContainer.SignatureV4a; + if (this.signerOptions.runtime === "node") { + if (!CrtSignerV4 && !JsSigV4aSigner) { + throw new Error( + "Neither CRT nor JS SigV4a implementation is available. Please load either @aws-sdk/signature-v4-crt or @aws-sdk/signature-v4a. For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt" + ); + } + if (CrtSignerV4 && typeof CrtSignerV4 === "function") { + this.sigv4aSigner = new CrtSignerV4({ + ...this.signerOptions, + signingAlgorithm: 1 + }); + } else if (JsSigV4aSigner && typeof JsSigV4aSigner === "function") { + this.sigv4aSigner = new JsSigV4aSigner({ + ...this.signerOptions + }); + } else { + throw new Error( + "Available SigV4a implementation is not a valid constructor. Please ensure you've properly imported @aws-sdk/signature-v4-crt or @aws-sdk/signature-v4a.For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt" + ); + } + } else { + if (!JsSigV4aSigner || typeof JsSigV4aSigner !== "function") { + throw new Error( + "JS SigV4a implementation is not available or not a valid constructor. Please check whether you have installed the @aws-sdk/signature-v4a package explicitly. The CRT implementation is not available for browsers. You must also register the package by calling [require('@aws-sdk/signature-v4a');] or an ESM equivalent such as [import '@aws-sdk/signature-v4a';]. For more information please go to https://github.com/aws/aws-sdk-js-v3#using-javascript-non-crt-implementation-of-sigv4a" + ); + } + this.sigv4aSigner = new JsSigV4aSigner({ + ...this.signerOptions + }); + } + } + return this.sigv4aSigner; + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 75433: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromEnvSigningName: () => fromEnvSigningName, + fromSso: () => fromSso, + fromStatic: () => fromStatic, + nodeProvider: () => nodeProvider +}); +module.exports = __toCommonJS(index_exports); + +// src/fromEnvSigningName.ts +var import_client = __nccwpck_require__(5152); +var import_httpAuthSchemes = __nccwpck_require__(97523); +var import_property_provider = __nccwpck_require__(71238); +var fromEnvSigningName = /* @__PURE__ */ __name(({ logger, signingName } = {}) => async () => { + logger?.debug?.("@aws-sdk/token-providers - fromEnvSigningName"); + if (!signingName) { + throw new import_property_provider.TokenProviderError("Please pass 'signingName' to compute environment variable key", { logger }); + } + const bearerTokenKey = (0, import_httpAuthSchemes.getBearerTokenEnvKey)(signingName); + if (!(bearerTokenKey in process.env)) { + throw new import_property_provider.TokenProviderError(`Token not present in '${bearerTokenKey}' environment variable`, { logger }); + } + const token = { token: process.env[bearerTokenKey] }; + (0, import_client.setTokenFeature)(token, "BEARER_SERVICE_ENV_VARS", "3"); + return token; +}, "fromEnvSigningName"); + +// src/fromSso.ts + + + +// src/constants.ts +var EXPIRE_WINDOW_MS = 5 * 60 * 1e3; +var REFRESH_MESSAGE = `To refresh this SSO session run 'aws sso login' with the corresponding profile.`; + +// src/getSsoOidcClient.ts +var getSsoOidcClient = /* @__PURE__ */ __name(async (ssoRegion, init = {}) => { + const { SSOOIDCClient } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(89443))); + const ssoOidcClient = new SSOOIDCClient( + Object.assign({}, init.clientConfig ?? {}, { + region: ssoRegion ?? init.clientConfig?.region, + logger: init.clientConfig?.logger ?? init.parentClientConfig?.logger + }) + ); + return ssoOidcClient; +}, "getSsoOidcClient"); + +// src/getNewSsoOidcToken.ts +var getNewSsoOidcToken = /* @__PURE__ */ __name(async (ssoToken, ssoRegion, init = {}) => { + const { CreateTokenCommand } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(89443))); + const ssoOidcClient = await getSsoOidcClient(ssoRegion, init); + return ssoOidcClient.send( + new CreateTokenCommand({ + clientId: ssoToken.clientId, + clientSecret: ssoToken.clientSecret, + refreshToken: ssoToken.refreshToken, + grantType: "refresh_token" + }) + ); +}, "getNewSsoOidcToken"); + +// src/validateTokenExpiry.ts + +var validateTokenExpiry = /* @__PURE__ */ __name((token) => { + if (token.expiration && token.expiration.getTime() < Date.now()) { + throw new import_property_provider.TokenProviderError(`Token is expired. ${REFRESH_MESSAGE}`, false); + } +}, "validateTokenExpiry"); + +// src/validateTokenKey.ts + +var validateTokenKey = /* @__PURE__ */ __name((key, value, forRefresh = false) => { + if (typeof value === "undefined") { + throw new import_property_provider.TokenProviderError( + `Value not present for '${key}' in SSO Token${forRefresh ? ". Cannot refresh" : ""}. ${REFRESH_MESSAGE}`, + false + ); + } +}, "validateTokenKey"); + +// src/writeSSOTokenToFile.ts +var import_shared_ini_file_loader = __nccwpck_require__(94964); +var import_fs = __nccwpck_require__(79896); +var { writeFile } = import_fs.promises; +var writeSSOTokenToFile = /* @__PURE__ */ __name((id, ssoToken) => { + const tokenFilepath = (0, import_shared_ini_file_loader.getSSOTokenFilepath)(id); + const tokenString = JSON.stringify(ssoToken, null, 2); + return writeFile(tokenFilepath, tokenString); +}, "writeSSOTokenToFile"); + +// src/fromSso.ts +var lastRefreshAttemptTime = /* @__PURE__ */ new Date(0); +var fromSso = /* @__PURE__ */ __name((_init = {}) => async ({ callerClientConfig } = {}) => { + const init = { + ..._init, + parentClientConfig: { + ...callerClientConfig, + ..._init.parentClientConfig + } + }; + init.logger?.debug("@aws-sdk/token-providers - fromSso"); + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + const profileName = (0, import_shared_ini_file_loader.getProfileName)({ + profile: init.profile ?? callerClientConfig?.profile + }); + const profile = profiles[profileName]; + if (!profile) { + throw new import_property_provider.TokenProviderError(`Profile '${profileName}' could not be found in shared credentials file.`, false); + } else if (!profile["sso_session"]) { + throw new import_property_provider.TokenProviderError(`Profile '${profileName}' is missing required property 'sso_session'.`); + } + const ssoSessionName = profile["sso_session"]; + const ssoSessions = await (0, import_shared_ini_file_loader.loadSsoSessionData)(init); + const ssoSession = ssoSessions[ssoSessionName]; + if (!ssoSession) { + throw new import_property_provider.TokenProviderError( + `Sso session '${ssoSessionName}' could not be found in shared credentials file.`, + false + ); + } + for (const ssoSessionRequiredKey of ["sso_start_url", "sso_region"]) { + if (!ssoSession[ssoSessionRequiredKey]) { + throw new import_property_provider.TokenProviderError( + `Sso session '${ssoSessionName}' is missing required property '${ssoSessionRequiredKey}'.`, + false + ); + } + } + const ssoStartUrl = ssoSession["sso_start_url"]; + const ssoRegion = ssoSession["sso_region"]; + let ssoToken; + try { + ssoToken = await (0, import_shared_ini_file_loader.getSSOTokenFromFile)(ssoSessionName); + } catch (e) { + throw new import_property_provider.TokenProviderError( + `The SSO session token associated with profile=${profileName} was not found or is invalid. ${REFRESH_MESSAGE}`, + false + ); + } + validateTokenKey("accessToken", ssoToken.accessToken); + validateTokenKey("expiresAt", ssoToken.expiresAt); + const { accessToken, expiresAt } = ssoToken; + const existingToken = { token: accessToken, expiration: new Date(expiresAt) }; + if (existingToken.expiration.getTime() - Date.now() > EXPIRE_WINDOW_MS) { + return existingToken; + } + if (Date.now() - lastRefreshAttemptTime.getTime() < 30 * 1e3) { + validateTokenExpiry(existingToken); + return existingToken; + } + validateTokenKey("clientId", ssoToken.clientId, true); + validateTokenKey("clientSecret", ssoToken.clientSecret, true); + validateTokenKey("refreshToken", ssoToken.refreshToken, true); + try { + lastRefreshAttemptTime.setTime(Date.now()); + const newSsoOidcToken = await getNewSsoOidcToken(ssoToken, ssoRegion, init); + validateTokenKey("accessToken", newSsoOidcToken.accessToken); + validateTokenKey("expiresIn", newSsoOidcToken.expiresIn); + const newTokenExpiration = new Date(Date.now() + newSsoOidcToken.expiresIn * 1e3); + try { + await writeSSOTokenToFile(ssoSessionName, { + ...ssoToken, + accessToken: newSsoOidcToken.accessToken, + expiresAt: newTokenExpiration.toISOString(), + refreshToken: newSsoOidcToken.refreshToken + }); + } catch (error) { + } + return { + token: newSsoOidcToken.accessToken, + expiration: newTokenExpiration + }; + } catch (error) { + validateTokenExpiry(existingToken); + return existingToken; + } +}, "fromSso"); + +// src/fromStatic.ts + +var fromStatic = /* @__PURE__ */ __name(({ token, logger }) => async () => { + logger?.debug("@aws-sdk/token-providers - fromStatic"); + if (!token || !token.token) { + throw new import_property_provider.TokenProviderError(`Please pass a valid token to fromStatic`, false); + } + return token; +}, "fromStatic"); + +// src/nodeProvider.ts + +var nodeProvider = /* @__PURE__ */ __name((init = {}) => (0, import_property_provider.memoize)( + (0, import_property_provider.chain)(fromSso(init), async () => { + throw new import_property_provider.TokenProviderError("Could not load token from any providers", false); + }), + (token) => token.expiration !== void 0 && token.expiration.getTime() - Date.now() < 3e5, + (token) => token.expiration !== void 0 +), "nodeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 56369: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + build: () => build, + parse: () => parse, + validate: () => validate +}); +module.exports = __toCommonJS(index_exports); +var validate = /* @__PURE__ */ __name((str) => typeof str === "string" && str.indexOf("arn:") === 0 && str.split(":").length >= 6, "validate"); +var parse = /* @__PURE__ */ __name((arn) => { + const segments = arn.split(":"); + if (segments.length < 6 || segments[0] !== "arn") throw new Error("Malformed ARN"); + const [ + , + //Skip "arn" literal + partition, + service, + region, + accountId, + ...resource + ] = segments; + return { + partition, + service, + region, + accountId, + resource: resource.join(":") + }; +}, "parse"); +var build = /* @__PURE__ */ __name((arnObject) => { + const { partition = "aws", service, region, accountId, resource } = arnObject; + if ([service, region, accountId, resource].some((segment) => typeof segment !== "string")) { + throw new Error("Input ARN object is invalid"); + } + return `arn:${partition}:${service}:${region}:${accountId}:${resource}`; +}, "build"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 83068: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + ConditionObject: () => import_util_endpoints.ConditionObject, + DeprecatedObject: () => import_util_endpoints.DeprecatedObject, + EndpointError: () => import_util_endpoints.EndpointError, + EndpointObject: () => import_util_endpoints.EndpointObject, + EndpointObjectHeaders: () => import_util_endpoints.EndpointObjectHeaders, + EndpointObjectProperties: () => import_util_endpoints.EndpointObjectProperties, + EndpointParams: () => import_util_endpoints.EndpointParams, + EndpointResolverOptions: () => import_util_endpoints.EndpointResolverOptions, + EndpointRuleObject: () => import_util_endpoints.EndpointRuleObject, + ErrorRuleObject: () => import_util_endpoints.ErrorRuleObject, + EvaluateOptions: () => import_util_endpoints.EvaluateOptions, + Expression: () => import_util_endpoints.Expression, + FunctionArgv: () => import_util_endpoints.FunctionArgv, + FunctionObject: () => import_util_endpoints.FunctionObject, + FunctionReturn: () => import_util_endpoints.FunctionReturn, + ParameterObject: () => import_util_endpoints.ParameterObject, + ReferenceObject: () => import_util_endpoints.ReferenceObject, + ReferenceRecord: () => import_util_endpoints.ReferenceRecord, + RuleSetObject: () => import_util_endpoints.RuleSetObject, + RuleSetRules: () => import_util_endpoints.RuleSetRules, + TreeRuleObject: () => import_util_endpoints.TreeRuleObject, + awsEndpointFunctions: () => awsEndpointFunctions, + getUserAgentPrefix: () => getUserAgentPrefix, + isIpAddress: () => import_util_endpoints.isIpAddress, + partition: () => partition, + resolveDefaultAwsRegionalEndpointsConfig: () => resolveDefaultAwsRegionalEndpointsConfig, + resolveEndpoint: () => import_util_endpoints.resolveEndpoint, + setPartitionInfo: () => setPartitionInfo, + toEndpointV1: () => toEndpointV1, + useDefaultPartitionInfo: () => useDefaultPartitionInfo +}); +module.exports = __toCommonJS(index_exports); + +// src/aws.ts + + +// src/lib/aws/isVirtualHostableS3Bucket.ts + + +// src/lib/isIpAddress.ts +var import_util_endpoints = __nccwpck_require__(79674); + +// src/lib/aws/isVirtualHostableS3Bucket.ts +var isVirtualHostableS3Bucket = /* @__PURE__ */ __name((value, allowSubDomains = false) => { + if (allowSubDomains) { + for (const label of value.split(".")) { + if (!isVirtualHostableS3Bucket(label)) { + return false; + } + } + return true; + } + if (!(0, import_util_endpoints.isValidHostLabel)(value)) { + return false; + } + if (value.length < 3 || value.length > 63) { + return false; + } + if (value !== value.toLowerCase()) { + return false; + } + if ((0, import_util_endpoints.isIpAddress)(value)) { + return false; + } + return true; +}, "isVirtualHostableS3Bucket"); + +// src/lib/aws/parseArn.ts +var ARN_DELIMITER = ":"; +var RESOURCE_DELIMITER = "/"; +var parseArn = /* @__PURE__ */ __name((value) => { + const segments = value.split(ARN_DELIMITER); + if (segments.length < 6) return null; + const [arn, partition2, service, region, accountId, ...resourcePath] = segments; + if (arn !== "arn" || partition2 === "" || service === "" || resourcePath.join(ARN_DELIMITER) === "") return null; + const resourceId = resourcePath.map((resource) => resource.split(RESOURCE_DELIMITER)).flat(); + return { + partition: partition2, + service, + region, + accountId, + resourceId + }; +}, "parseArn"); + +// src/lib/aws/partitions.json +var partitions_default = { + partitions: [{ + id: "aws", + outputs: { + dnsSuffix: "amazonaws.com", + dualStackDnsSuffix: "api.aws", + implicitGlobalRegion: "us-east-1", + name: "aws", + supportsDualStack: true, + supportsFIPS: true + }, + regionRegex: "^(us|eu|ap|sa|ca|me|af|il|mx)\\-\\w+\\-\\d+$", + regions: { + "af-south-1": { + description: "Africa (Cape Town)" + }, + "ap-east-1": { + description: "Asia Pacific (Hong Kong)" + }, + "ap-east-2": { + description: "Asia Pacific (Taipei)" + }, + "ap-northeast-1": { + description: "Asia Pacific (Tokyo)" + }, + "ap-northeast-2": { + description: "Asia Pacific (Seoul)" + }, + "ap-northeast-3": { + description: "Asia Pacific (Osaka)" + }, + "ap-south-1": { + description: "Asia Pacific (Mumbai)" + }, + "ap-south-2": { + description: "Asia Pacific (Hyderabad)" + }, + "ap-southeast-1": { + description: "Asia Pacific (Singapore)" + }, + "ap-southeast-2": { + description: "Asia Pacific (Sydney)" + }, + "ap-southeast-3": { + description: "Asia Pacific (Jakarta)" + }, + "ap-southeast-4": { + description: "Asia Pacific (Melbourne)" + }, + "ap-southeast-5": { + description: "Asia Pacific (Malaysia)" + }, + "ap-southeast-7": { + description: "Asia Pacific (Thailand)" + }, + "aws-global": { + description: "AWS Standard global region" + }, + "ca-central-1": { + description: "Canada (Central)" + }, + "ca-west-1": { + description: "Canada West (Calgary)" + }, + "eu-central-1": { + description: "Europe (Frankfurt)" + }, + "eu-central-2": { + description: "Europe (Zurich)" + }, + "eu-north-1": { + description: "Europe (Stockholm)" + }, + "eu-south-1": { + description: "Europe (Milan)" + }, + "eu-south-2": { + description: "Europe (Spain)" + }, + "eu-west-1": { + description: "Europe (Ireland)" + }, + "eu-west-2": { + description: "Europe (London)" + }, + "eu-west-3": { + description: "Europe (Paris)" + }, + "il-central-1": { + description: "Israel (Tel Aviv)" + }, + "me-central-1": { + description: "Middle East (UAE)" + }, + "me-south-1": { + description: "Middle East (Bahrain)" + }, + "mx-central-1": { + description: "Mexico (Central)" + }, + "sa-east-1": { + description: "South America (Sao Paulo)" + }, + "us-east-1": { + description: "US East (N. Virginia)" + }, + "us-east-2": { + description: "US East (Ohio)" + }, + "us-west-1": { + description: "US West (N. California)" + }, + "us-west-2": { + description: "US West (Oregon)" + } + } + }, { + id: "aws-cn", + outputs: { + dnsSuffix: "amazonaws.com.cn", + dualStackDnsSuffix: "api.amazonwebservices.com.cn", + implicitGlobalRegion: "cn-northwest-1", + name: "aws-cn", + supportsDualStack: true, + supportsFIPS: true + }, + regionRegex: "^cn\\-\\w+\\-\\d+$", + regions: { + "aws-cn-global": { + description: "AWS China global region" + }, + "cn-north-1": { + description: "China (Beijing)" + }, + "cn-northwest-1": { + description: "China (Ningxia)" + } + } + }, { + id: "aws-us-gov", + outputs: { + dnsSuffix: "amazonaws.com", + dualStackDnsSuffix: "api.aws", + implicitGlobalRegion: "us-gov-west-1", + name: "aws-us-gov", + supportsDualStack: true, + supportsFIPS: true + }, + regionRegex: "^us\\-gov\\-\\w+\\-\\d+$", + regions: { + "aws-us-gov-global": { + description: "AWS GovCloud (US) global region" + }, + "us-gov-east-1": { + description: "AWS GovCloud (US-East)" + }, + "us-gov-west-1": { + description: "AWS GovCloud (US-West)" + } + } + }, { + id: "aws-iso", + outputs: { + dnsSuffix: "c2s.ic.gov", + dualStackDnsSuffix: "c2s.ic.gov", + implicitGlobalRegion: "us-iso-east-1", + name: "aws-iso", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^us\\-iso\\-\\w+\\-\\d+$", + regions: { + "aws-iso-global": { + description: "AWS ISO (US) global region" + }, + "us-iso-east-1": { + description: "US ISO East" + }, + "us-iso-west-1": { + description: "US ISO WEST" + } + } + }, { + id: "aws-iso-b", + outputs: { + dnsSuffix: "sc2s.sgov.gov", + dualStackDnsSuffix: "sc2s.sgov.gov", + implicitGlobalRegion: "us-isob-east-1", + name: "aws-iso-b", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^us\\-isob\\-\\w+\\-\\d+$", + regions: { + "aws-iso-b-global": { + description: "AWS ISOB (US) global region" + }, + "us-isob-east-1": { + description: "US ISOB East (Ohio)" + } + } + }, { + id: "aws-iso-e", + outputs: { + dnsSuffix: "cloud.adc-e.uk", + dualStackDnsSuffix: "cloud.adc-e.uk", + implicitGlobalRegion: "eu-isoe-west-1", + name: "aws-iso-e", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^eu\\-isoe\\-\\w+\\-\\d+$", + regions: { + "aws-iso-e-global": { + description: "AWS ISOE (Europe) global region" + }, + "eu-isoe-west-1": { + description: "EU ISOE West" + } + } + }, { + id: "aws-iso-f", + outputs: { + dnsSuffix: "csp.hci.ic.gov", + dualStackDnsSuffix: "csp.hci.ic.gov", + implicitGlobalRegion: "us-isof-south-1", + name: "aws-iso-f", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^us\\-isof\\-\\w+\\-\\d+$", + regions: { + "aws-iso-f-global": { + description: "AWS ISOF global region" + }, + "us-isof-east-1": { + description: "US ISOF EAST" + }, + "us-isof-south-1": { + description: "US ISOF SOUTH" + } + } + }, { + id: "aws-eusc", + outputs: { + dnsSuffix: "amazonaws.eu", + dualStackDnsSuffix: "amazonaws.eu", + implicitGlobalRegion: "eusc-de-east-1", + name: "aws-eusc", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^eusc\\-(de)\\-\\w+\\-\\d+$", + regions: { + "eusc-de-east-1": { + description: "EU (Germany)" + } + } + }], + version: "1.1" +}; + +// src/lib/aws/partition.ts +var selectedPartitionsInfo = partitions_default; +var selectedUserAgentPrefix = ""; +var partition = /* @__PURE__ */ __name((value) => { + const { partitions } = selectedPartitionsInfo; + for (const partition2 of partitions) { + const { regions, outputs } = partition2; + for (const [region, regionData] of Object.entries(regions)) { + if (region === value) { + return { + ...outputs, + ...regionData + }; + } + } + } + for (const partition2 of partitions) { + const { regionRegex, outputs } = partition2; + if (new RegExp(regionRegex).test(value)) { + return { + ...outputs + }; + } + } + const DEFAULT_PARTITION = partitions.find((partition2) => partition2.id === "aws"); + if (!DEFAULT_PARTITION) { + throw new Error( + "Provided region was not found in the partition array or regex, and default partition with id 'aws' doesn't exist." + ); + } + return { + ...DEFAULT_PARTITION.outputs + }; +}, "partition"); +var setPartitionInfo = /* @__PURE__ */ __name((partitionsInfo, userAgentPrefix = "") => { + selectedPartitionsInfo = partitionsInfo; + selectedUserAgentPrefix = userAgentPrefix; +}, "setPartitionInfo"); +var useDefaultPartitionInfo = /* @__PURE__ */ __name(() => { + setPartitionInfo(partitions_default, ""); +}, "useDefaultPartitionInfo"); +var getUserAgentPrefix = /* @__PURE__ */ __name(() => selectedUserAgentPrefix, "getUserAgentPrefix"); + +// src/aws.ts +var awsEndpointFunctions = { + isVirtualHostableS3Bucket, + parseArn, + partition +}; +import_util_endpoints.customEndpointFunctions.aws = awsEndpointFunctions; + +// src/resolveDefaultAwsRegionalEndpointsConfig.ts +var import_url_parser = __nccwpck_require__(14494); +var resolveDefaultAwsRegionalEndpointsConfig = /* @__PURE__ */ __name((input) => { + if (typeof input.endpointProvider !== "function") { + throw new Error("@aws-sdk/util-endpoint - endpointProvider and endpoint missing in config for this client."); + } + const { endpoint } = input; + if (endpoint === void 0) { + input.endpoint = async () => { + return toEndpointV1( + input.endpointProvider( + { + Region: typeof input.region === "function" ? await input.region() : input.region, + UseDualStack: typeof input.useDualstackEndpoint === "function" ? await input.useDualstackEndpoint() : input.useDualstackEndpoint, + UseFIPS: typeof input.useFipsEndpoint === "function" ? await input.useFipsEndpoint() : input.useFipsEndpoint, + Endpoint: void 0 + }, + { logger: input.logger } + ) + ); + }; + } + return input; +}, "resolveDefaultAwsRegionalEndpointsConfig"); +var toEndpointV1 = /* @__PURE__ */ __name((endpoint) => (0, import_url_parser.parseUrl)(endpoint.url), "toEndpointV1"); + +// src/resolveEndpoint.ts + + +// src/types/EndpointError.ts + + +// src/types/EndpointRuleObject.ts + + +// src/types/ErrorRuleObject.ts + + +// src/types/RuleSetObject.ts + + +// src/types/TreeRuleObject.ts + + +// src/types/shared.ts + +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 51656: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_APP_ID_CONFIG_OPTIONS: () => NODE_APP_ID_CONFIG_OPTIONS, + UA_APP_ID_ENV_NAME: () => UA_APP_ID_ENV_NAME, + UA_APP_ID_INI_NAME: () => UA_APP_ID_INI_NAME, + createDefaultUserAgentProvider: () => createDefaultUserAgentProvider, + crtAvailability: () => crtAvailability, + defaultUserAgent: () => defaultUserAgent +}); +module.exports = __toCommonJS(index_exports); + +// src/defaultUserAgent.ts +var import_os = __nccwpck_require__(70857); +var import_process = __nccwpck_require__(932); + +// src/crt-availability.ts +var crtAvailability = { + isCrtAvailable: false +}; + +// src/is-crt-available.ts +var isCrtAvailable = /* @__PURE__ */ __name(() => { + if (crtAvailability.isCrtAvailable) { + return ["md/crt-avail"]; + } + return null; +}, "isCrtAvailable"); + +// src/defaultUserAgent.ts +var createDefaultUserAgentProvider = /* @__PURE__ */ __name(({ serviceId, clientVersion }) => { + return async (config) => { + const sections = [ + // sdk-metadata + ["aws-sdk-js", clientVersion], + // ua-metadata + ["ua", "2.1"], + // os-metadata + [`os/${(0, import_os.platform)()}`, (0, import_os.release)()], + // language-metadata + // ECMAScript edition doesn't matter in JS, so no version needed. + ["lang/js"], + ["md/nodejs", `${import_process.versions.node}`] + ]; + const crtAvailable = isCrtAvailable(); + if (crtAvailable) { + sections.push(crtAvailable); + } + if (serviceId) { + sections.push([`api/${serviceId}`, clientVersion]); + } + if (import_process.env.AWS_EXECUTION_ENV) { + sections.push([`exec-env/${import_process.env.AWS_EXECUTION_ENV}`]); + } + const appId = await config?.userAgentAppId?.(); + const resolvedUserAgent = appId ? [...sections, [`app/${appId}`]] : [...sections]; + return resolvedUserAgent; + }; +}, "createDefaultUserAgentProvider"); +var defaultUserAgent = createDefaultUserAgentProvider; + +// src/nodeAppIdConfigOptions.ts +var import_middleware_user_agent = __nccwpck_require__(32959); +var UA_APP_ID_ENV_NAME = "AWS_SDK_UA_APP_ID"; +var UA_APP_ID_INI_NAME = "sdk_ua_app_id"; +var UA_APP_ID_INI_NAME_DEPRECATED = "sdk-ua-app-id"; +var NODE_APP_ID_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env2) => env2[UA_APP_ID_ENV_NAME], "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => profile[UA_APP_ID_INI_NAME] ?? profile[UA_APP_ID_INI_NAME_DEPRECATED], "configFileSelector"), + default: import_middleware_user_agent.DEFAULT_UA_APP_ID +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 94274: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + XmlNode: () => XmlNode, + XmlText: () => XmlText +}); +module.exports = __toCommonJS(index_exports); + +// src/escape-attribute.ts +function escapeAttribute(value) { + return value.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); +} +__name(escapeAttribute, "escapeAttribute"); + +// src/escape-element.ts +function escapeElement(value) { + return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(//g, ">").replace(/\r/g, " ").replace(/\n/g, " ").replace(/\u0085/g, "…").replace(/\u2028/, "
"); +} +__name(escapeElement, "escapeElement"); + +// src/XmlText.ts +var XmlText = class { + constructor(value) { + this.value = value; + } + static { + __name(this, "XmlText"); + } + toString() { + return escapeElement("" + this.value); + } +}; + +// src/XmlNode.ts +var XmlNode = class _XmlNode { + constructor(name, children = []) { + this.name = name; + this.children = children; + } + static { + __name(this, "XmlNode"); + } + attributes = {}; + static of(name, childText, withName) { + const node = new _XmlNode(name); + if (childText !== void 0) { + node.addChildNode(new XmlText(childText)); + } + if (withName !== void 0) { + node.withName(withName); + } + return node; + } + withName(name) { + this.name = name; + return this; + } + addAttribute(name, value) { + this.attributes[name] = value; + return this; + } + addChildNode(child) { + this.children.push(child); + return this; + } + removeAttribute(name) { + delete this.attributes[name]; + return this; + } + /** + * @internal + * Alias of {@link XmlNode#withName(string)} for codegen brevity. + */ + n(name) { + this.name = name; + return this; + } + /** + * @internal + * Alias of {@link XmlNode#addChildNode(string)} for codegen brevity. + */ + c(child) { + this.children.push(child); + return this; + } + /** + * @internal + * Checked version of {@link XmlNode#addAttribute(string)} for codegen brevity. + */ + a(name, value) { + if (value != null) { + this.attributes[name] = value; + } + return this; + } + /** + * Create a child node. + * Used in serialization of string fields. + * @internal + */ + cc(input, field, withName = field) { + if (input[field] != null) { + const node = _XmlNode.of(field, input[field]).withName(withName); + this.c(node); + } + } + /** + * Creates list child nodes. + * @internal + */ + l(input, listName, memberName, valueProvider) { + if (input[listName] != null) { + const nodes = valueProvider(); + nodes.map((node) => { + node.withName(memberName); + this.c(node); + }); + } + } + /** + * Creates list child nodes with container. + * @internal + */ + lc(input, listName, memberName, valueProvider) { + if (input[listName] != null) { + const nodes = valueProvider(); + const containerNode = new _XmlNode(memberName); + nodes.map((node) => { + containerNode.c(node); + }); + this.c(containerNode); + } + } + toString() { + const hasChildren = Boolean(this.children.length); + let xmlText = `<${this.name}`; + const attributes = this.attributes; + for (const attributeName of Object.keys(attributes)) { + const attribute = attributes[attributeName]; + if (attribute != null) { + xmlText += ` ${attributeName}="${escapeAttribute("" + attribute)}"`; + } + } + return xmlText += !hasChildren ? "/>" : `>${this.children.map((c) => c.toString()).join("")}`; + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 99469: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/*! + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ResourceStream = exports.paginator = exports.Paginator = void 0; +/*! + * @module common/paginator + */ +const arrify = __nccwpck_require__(26251); +const extend = __nccwpck_require__(23860); +const resource_stream_1 = __nccwpck_require__(97618); +Object.defineProperty(exports, "ResourceStream", ({ enumerable: true, get: function () { return resource_stream_1.ResourceStream; } })); +/*! Developer Documentation + * + * paginator is used to auto-paginate `nextQuery` methods as well as + * streamifying them. + * + * Before: + * + * search.query('done=true', function(err, results, nextQuery) { + * search.query(nextQuery, function(err, results, nextQuery) {}); + * }); + * + * After: + * + * search.query('done=true', function(err, results) {}); + * + * Methods to extend should be written to accept callbacks and return a + * `nextQuery`. + */ +class Paginator { + /** + * Cache the original method, then overwrite it on the Class's prototype. + * + * @param {function} Class - The parent class of the methods to extend. + * @param {string|string[]} methodNames - Name(s) of the methods to extend. + */ + // tslint:disable-next-line:variable-name + extend(Class, methodNames) { + methodNames = arrify(methodNames); + methodNames.forEach(methodName => { + const originalMethod = Class.prototype[methodName]; + // map the original method to a private member + Class.prototype[methodName + '_'] = originalMethod; + // overwrite the original to auto-paginate + /* eslint-disable @typescript-eslint/no-explicit-any */ + Class.prototype[methodName] = function (...args) { + const parsedArguments = paginator.parseArguments_(args); + return paginator.run_(parsedArguments, originalMethod.bind(this)); + }; + }); + } + /** + * Wraps paginated API calls in a readable object stream. + * + * This method simply calls the nextQuery recursively, emitting results to a + * stream. The stream ends when `nextQuery` is null. + * + * `maxResults` will act as a cap for how many results are fetched and emitted + * to the stream. + * + * @param {string} methodName - Name of the method to streamify. + * @return {function} - Wrapped function. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + streamify(methodName) { + return function ( + /* eslint-disable @typescript-eslint/no-explicit-any */ + ...args) { + const parsedArguments = paginator.parseArguments_(args); + const originalMethod = this[methodName + '_'] || this[methodName]; + return paginator.runAsStream_(parsedArguments, originalMethod.bind(this)); + }; + } + /** + * Parse a pseudo-array `arguments` for a query and callback. + * + * @param {array} args - The original `arguments` pseduo-array that the original + * method received. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + parseArguments_(args) { + let query; + let autoPaginate = true; + let maxApiCalls = -1; + let maxResults = -1; + let callback; + const firstArgument = args[0]; + const lastArgument = args[args.length - 1]; + if (typeof firstArgument === 'function') { + callback = firstArgument; + } + else { + query = firstArgument; + } + if (typeof lastArgument === 'function') { + callback = lastArgument; + } + if (typeof query === 'object') { + query = extend(true, {}, query); + // Check if the user only asked for a certain amount of results. + if (query.maxResults && typeof query.maxResults === 'number') { + // `maxResults` is used API-wide. + maxResults = query.maxResults; + } + else if (typeof query.pageSize === 'number') { + // `pageSize` is Pub/Sub's `maxResults`. + maxResults = query.pageSize; + } + if (query.maxApiCalls && typeof query.maxApiCalls === 'number') { + maxApiCalls = query.maxApiCalls; + delete query.maxApiCalls; + } + // maxResults is the user specified limit. + if (maxResults !== -1 || query.autoPaginate === false) { + autoPaginate = false; + } + } + const parsedArguments = { + query: query || {}, + autoPaginate, + maxApiCalls, + maxResults, + callback, + }; + parsedArguments.streamOptions = extend(true, {}, parsedArguments.query); + delete parsedArguments.streamOptions.autoPaginate; + delete parsedArguments.streamOptions.maxResults; + delete parsedArguments.streamOptions.pageSize; + return parsedArguments; + } + /** + * This simply checks to see if `autoPaginate` is set or not, if it's true + * then we buffer all results, otherwise simply call the original method. + * + * @param {array} parsedArguments - Parsed arguments from the original method + * call. + * @param {object=|string=} parsedArguments.query - Query object. This is most + * commonly an object, but to make the API more simple, it can also be a + * string in some places. + * @param {function=} parsedArguments.callback - Callback function. + * @param {boolean} parsedArguments.autoPaginate - Auto-pagination enabled. + * @param {boolean} parsedArguments.maxApiCalls - Maximum API calls to make. + * @param {number} parsedArguments.maxResults - Maximum results to return. + * @param {function} originalMethod - The cached method that accepts a callback + * and returns `nextQuery` to receive more results. + */ + run_(parsedArguments, originalMethod) { + const query = parsedArguments.query; + const callback = parsedArguments.callback; + if (!parsedArguments.autoPaginate) { + return originalMethod(query, callback); + } + const results = new Array(); + let otherArgs = []; + const promise = new Promise((resolve, reject) => { + const stream = paginator.runAsStream_(parsedArguments, originalMethod); + stream + .on('error', reject) + .on('data', (data) => results.push(data)) + .on('end', () => { + otherArgs = stream._otherArgs || []; + resolve(results); + }); + }); + if (!callback) { + return promise.then(results => [results, query, ...otherArgs]); + } + promise.then(results => callback(null, results, query, ...otherArgs), (err) => callback(err)); + } + /** + * This method simply calls the nextQuery recursively, emitting results to a + * stream. The stream ends when `nextQuery` is null. + * + * `maxResults` will act as a cap for how many results are fetched and emitted + * to the stream. + * + * @param {object=|string=} parsedArguments.query - Query object. This is most + * commonly an object, but to make the API more simple, it can also be a + * string in some places. + * @param {function=} parsedArguments.callback - Callback function. + * @param {boolean} parsedArguments.autoPaginate - Auto-pagination enabled. + * @param {boolean} parsedArguments.maxApiCalls - Maximum API calls to make. + * @param {number} parsedArguments.maxResults - Maximum results to return. + * @param {function} originalMethod - The cached method that accepts a callback + * and returns `nextQuery` to receive more results. + * @return {stream} - Readable object stream. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + runAsStream_(parsedArguments, originalMethod) { + return new resource_stream_1.ResourceStream(parsedArguments, originalMethod); + } +} +exports.Paginator = Paginator; +const paginator = new Paginator(); +exports.paginator = paginator; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 97618: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/*! + * Copyright 2019 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ResourceStream = void 0; +const stream_1 = __nccwpck_require__(2203); +class ResourceStream extends stream_1.Transform { + constructor(args, requestFn) { + const options = Object.assign({ objectMode: true }, args.streamOptions); + super(options); + this._ended = false; + this._maxApiCalls = args.maxApiCalls === -1 ? Infinity : args.maxApiCalls; + this._nextQuery = args.query; + this._reading = false; + this._requestFn = requestFn; + this._requestsMade = 0; + this._resultsToSend = args.maxResults === -1 ? Infinity : args.maxResults; + this._otherArgs = []; + } + /* eslint-disable @typescript-eslint/no-explicit-any */ + end(...args) { + this._ended = true; + return super.end(...args); + } + _read() { + if (this._reading) { + return; + } + this._reading = true; + // Wrap in a try/catch to catch input linting errors, e.g. + // an invalid BigQuery query. These errors are thrown in an + // async fashion, which makes them un-catchable by the user. + try { + this._requestFn(this._nextQuery, (err, results, nextQuery, ...otherArgs) => { + if (err) { + this.destroy(err); + return; + } + this._otherArgs = otherArgs; + this._nextQuery = nextQuery; + if (this._resultsToSend !== Infinity) { + results = results.splice(0, this._resultsToSend); + this._resultsToSend -= results.length; + } + let more = true; + for (const result of results) { + if (this._ended) { + break; + } + more = this.push(result); + } + const isFinished = !this._nextQuery || this._resultsToSend < 1; + const madeMaxCalls = ++this._requestsMade >= this._maxApiCalls; + if (isFinished || madeMaxCalls) { + this.end(); + } + if (more && !this._ended) { + setImmediate(() => this._read()); + } + this._reading = false; + }); + } + catch (e) { + this.destroy(e); + } + } +} +exports.ResourceStream = ResourceStream; +//# sourceMappingURL=resource-stream.js.map + +/***/ }), + +/***/ 87635: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.MissingProjectIdError = exports.replaceProjectIdToken = void 0; +const stream_1 = __nccwpck_require__(2203); +// Copyright 2014 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/** + * Populate the `{{projectId}}` placeholder. + * + * @throws {Error} If a projectId is required, but one is not provided. + * + * @param {*} - Any input value that may contain a placeholder. Arrays and objects will be looped. + * @param {string} projectId - A projectId. If not provided + * @return {*} - The original argument with all placeholders populated. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function replaceProjectIdToken(value, projectId) { + if (Array.isArray(value)) { + value = value.map(v => replaceProjectIdToken(v, projectId)); + } + if (value !== null && + typeof value === 'object' && + !(value instanceof Buffer) && + !(value instanceof stream_1.Stream) && + typeof value.hasOwnProperty === 'function') { + for (const opt in value) { + // eslint-disable-next-line no-prototype-builtins + if (value.hasOwnProperty(opt)) { + value[opt] = replaceProjectIdToken(value[opt], projectId); + } + } + } + if (typeof value === 'string' && + value.indexOf('{{projectId}}') > -1) { + if (!projectId || projectId === '{{projectId}}') { + throw new MissingProjectIdError(); + } + value = value.replace(/{{projectId}}/g, projectId); + } + return value; +} +exports.replaceProjectIdToken = replaceProjectIdToken; +/** + * Custom error type for missing project ID errors. + */ +class MissingProjectIdError extends Error { + constructor() { + super(...arguments); + this.message = `Sorry, we cannot connect to Cloud Services without a project + ID. You may specify one with an environment variable named + "GOOGLE_CLOUD_PROJECT".`.replace(/ +/g, ' '); + } +} +exports.MissingProjectIdError = MissingProjectIdError; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 60206: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/* eslint-disable prefer-rest-params */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.callbackifyAll = exports.callbackify = exports.promisifyAll = exports.promisify = void 0; +/** + * Wraps a callback style function to conditionally return a promise. + * + * @param {function} originalMethod - The method to promisify. + * @param {object=} options - Promise options. + * @param {boolean} options.singular - Resolve the promise with single arg instead of an array. + * @return {function} wrapped + */ +function promisify(originalMethod, options) { + if (originalMethod.promisified_) { + return originalMethod; + } + options = options || {}; + const slice = Array.prototype.slice; + // tslint:disable-next-line:no-any + const wrapper = function () { + let last; + for (last = arguments.length - 1; last >= 0; last--) { + const arg = arguments[last]; + if (typeof arg === 'undefined') { + continue; // skip trailing undefined. + } + if (typeof arg !== 'function') { + break; // non-callback last argument found. + } + return originalMethod.apply(this, arguments); + } + // peel trailing undefined. + const args = slice.call(arguments, 0, last + 1); + // tslint:disable-next-line:variable-name + let PromiseCtor = Promise; + // Because dedupe will likely create a single install of + // @google-cloud/common to be shared amongst all modules, we need to + // localize it at the Service level. + if (this && this.Promise) { + PromiseCtor = this.Promise; + } + return new PromiseCtor((resolve, reject) => { + // tslint:disable-next-line:no-any + args.push((...args) => { + const callbackArgs = slice.call(args); + const err = callbackArgs.shift(); + if (err) { + return reject(err); + } + if (options.singular && callbackArgs.length === 1) { + resolve(callbackArgs[0]); + } + else { + resolve(callbackArgs); + } + }); + originalMethod.apply(this, args); + }); + }; + wrapper.promisified_ = true; + return wrapper; +} +exports.promisify = promisify; +/** + * Promisifies certain Class methods. This will not promisify private or + * streaming methods. + * + * @param {module:common/service} Class - Service class. + * @param {object=} options - Configuration object. + */ +// tslint:disable-next-line:variable-name +function promisifyAll(Class, options) { + const exclude = (options && options.exclude) || []; + const ownPropertyNames = Object.getOwnPropertyNames(Class.prototype); + const methods = ownPropertyNames.filter(methodName => { + // clang-format off + return (!exclude.includes(methodName) && + typeof Class.prototype[methodName] === 'function' && // is it a function? + !/(^_|(Stream|_)|promise$)|^constructor$/.test(methodName) // is it promisable? + ); + // clang-format on + }); + methods.forEach(methodName => { + const originalMethod = Class.prototype[methodName]; + if (!originalMethod.promisified_) { + Class.prototype[methodName] = exports.promisify(originalMethod, options); + } + }); +} +exports.promisifyAll = promisifyAll; +/** + * Wraps a promisy type function to conditionally call a callback function. + * + * @param {function} originalMethod - The method to callbackify. + * @param {object=} options - Callback options. + * @param {boolean} options.singular - Pass to the callback a single arg instead of an array. + * @return {function} wrapped + */ +function callbackify(originalMethod) { + if (originalMethod.callbackified_) { + return originalMethod; + } + // tslint:disable-next-line:no-any + const wrapper = function () { + if (typeof arguments[arguments.length - 1] !== 'function') { + return originalMethod.apply(this, arguments); + } + const cb = Array.prototype.pop.call(arguments); + originalMethod.apply(this, arguments).then( + // tslint:disable-next-line:no-any + (res) => { + res = Array.isArray(res) ? res : [res]; + cb(null, ...res); + }, (err) => cb(err)); + }; + wrapper.callbackified_ = true; + return wrapper; +} +exports.callbackify = callbackify; +/** + * Callbackifies certain Class methods. This will not callbackify private or + * streaming methods. + * + * @param {module:common/service} Class - Service class. + * @param {object=} options - Configuration object. + */ +function callbackifyAll( +// tslint:disable-next-line:variable-name +Class, options) { + const exclude = (options && options.exclude) || []; + const ownPropertyNames = Object.getOwnPropertyNames(Class.prototype); + const methods = ownPropertyNames.filter(methodName => { + // clang-format off + return (!exclude.includes(methodName) && + typeof Class.prototype[methodName] === 'function' && // is it a function? + !/^_|(Stream|_)|^constructor$/.test(methodName) // is it callbackifyable? + ); + // clang-format on + }); + methods.forEach(methodName => { + const originalMethod = Class.prototype[methodName]; + if (!originalMethod.callbackified_) { + Class.prototype[methodName] = exports.callbackify(originalMethod); + } + }); +} +exports.callbackifyAll = callbackifyAll; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 1290: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const validator = __nccwpck_require__(67266); +const XMLParser = __nccwpck_require__(44079); +const XMLBuilder = __nccwpck_require__(79708); + +module.exports = { + XMLParser: XMLParser, + XMLValidator: validator, + XMLBuilder: XMLBuilder +} + +/***/ }), + +/***/ 9209: +/***/ ((module) => { + +function getIgnoreAttributesFn(ignoreAttributes) { + if (typeof ignoreAttributes === 'function') { + return ignoreAttributes + } + if (Array.isArray(ignoreAttributes)) { + return (attrName) => { + for (const pattern of ignoreAttributes) { + if (typeof pattern === 'string' && attrName === pattern) { + return true + } + if (pattern instanceof RegExp && pattern.test(attrName)) { + return true + } + } + } + } + return () => false +} + +module.exports = getIgnoreAttributesFn + +/***/ }), + +/***/ 55506: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +const nameStartChar = ':A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD'; +const nameChar = nameStartChar + '\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040'; +const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*' +const regexName = new RegExp('^' + nameRegexp + '$'); + +const getAllMatches = function(string, regex) { + const matches = []; + let match = regex.exec(string); + while (match) { + const allmatches = []; + allmatches.startIndex = regex.lastIndex - match[0].length; + const len = match.length; + for (let index = 0; index < len; index++) { + allmatches.push(match[index]); + } + matches.push(allmatches); + match = regex.exec(string); + } + return matches; +}; + +const isName = function(string) { + const match = regexName.exec(string); + return !(match === null || typeof match === 'undefined'); +}; + +exports.isExist = function(v) { + return typeof v !== 'undefined'; +}; + +exports.isEmptyObject = function(obj) { + return Object.keys(obj).length === 0; +}; + +/** + * Copy all the properties of a into b. + * @param {*} target + * @param {*} a + */ +exports.merge = function(target, a, arrayMode) { + if (a) { + const keys = Object.keys(a); // will return an array of own properties + const len = keys.length; //don't make it inline + for (let i = 0; i < len; i++) { + if (arrayMode === 'strict') { + target[keys[i]] = [ a[keys[i]] ]; + } else { + target[keys[i]] = a[keys[i]]; + } + } + } +}; +/* exports.merge =function (b,a){ + return Object.assign(b,a); +} */ + +exports.getValue = function(v) { + if (exports.isExist(v)) { + return v; + } else { + return ''; + } +}; + +// const fakeCall = function(a) {return a;}; +// const fakeCallNoReturn = function() {}; + +exports.isName = isName; +exports.getAllMatches = getAllMatches; +exports.nameRegexp = nameRegexp; + + +/***/ }), + +/***/ 67266: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +const util = __nccwpck_require__(55506); + +const defaultOptions = { + allowBooleanAttributes: false, //A tag can have attributes without any value + unpairedTags: [] +}; + +//const tagsPattern = new RegExp("<\\/?([\\w:\\-_\.]+)\\s*\/?>","g"); +exports.validate = function (xmlData, options) { + options = Object.assign({}, defaultOptions, options); + + //xmlData = xmlData.replace(/(\r\n|\n|\r)/gm,"");//make it single line + //xmlData = xmlData.replace(/(^\s*<\?xml.*?\?>)/g,"");//Remove XML starting tag + //xmlData = xmlData.replace(/()/g,"");//Remove DOCTYPE + const tags = []; + let tagFound = false; + + //indicates that the root tag has been closed (aka. depth 0 has been reached) + let reachedRoot = false; + + if (xmlData[0] === '\ufeff') { + // check for byte order mark (BOM) + xmlData = xmlData.substr(1); + } + + for (let i = 0; i < xmlData.length; i++) { + + if (xmlData[i] === '<' && xmlData[i+1] === '?') { + i+=2; + i = readPI(xmlData,i); + if (i.err) return i; + }else if (xmlData[i] === '<') { + //starting of tag + //read until you reach to '>' avoiding any '>' in attribute value + let tagStartPos = i; + i++; + + if (xmlData[i] === '!') { + i = readCommentAndCDATA(xmlData, i); + continue; + } else { + let closingTag = false; + if (xmlData[i] === '/') { + //closing tag + closingTag = true; + i++; + } + //read tagname + let tagName = ''; + for (; i < xmlData.length && + xmlData[i] !== '>' && + xmlData[i] !== ' ' && + xmlData[i] !== '\t' && + xmlData[i] !== '\n' && + xmlData[i] !== '\r'; i++ + ) { + tagName += xmlData[i]; + } + tagName = tagName.trim(); + //console.log(tagName); + + if (tagName[tagName.length - 1] === '/') { + //self closing tag without attributes + tagName = tagName.substring(0, tagName.length - 1); + //continue; + i--; + } + if (!validateTagName(tagName)) { + let msg; + if (tagName.trim().length === 0) { + msg = "Invalid space after '<'."; + } else { + msg = "Tag '"+tagName+"' is an invalid name."; + } + return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i)); + } + + const result = readAttributeStr(xmlData, i); + if (result === false) { + return getErrorObject('InvalidAttr', "Attributes for '"+tagName+"' have open quote.", getLineNumberForPosition(xmlData, i)); + } + let attrStr = result.value; + i = result.index; + + if (attrStr[attrStr.length - 1] === '/') { + //self closing tag + const attrStrStart = i - attrStr.length; + attrStr = attrStr.substring(0, attrStr.length - 1); + const isValid = validateAttributeString(attrStr, options); + if (isValid === true) { + tagFound = true; + //continue; //text may presents after self closing tag + } else { + //the result from the nested function returns the position of the error within the attribute + //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute + //this gives us the absolute index in the entire xml, which we can use to find the line at last + return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line)); + } + } else if (closingTag) { + if (!result.tagClosed) { + return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' doesn't have proper closing.", getLineNumberForPosition(xmlData, i)); + } else if (attrStr.trim().length > 0) { + return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos)); + } else if (tags.length === 0) { + return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' has not been opened.", getLineNumberForPosition(xmlData, tagStartPos)); + } else { + const otg = tags.pop(); + if (tagName !== otg.tagName) { + let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos); + return getErrorObject('InvalidTag', + "Expected closing tag '"+otg.tagName+"' (opened in line "+openPos.line+", col "+openPos.col+") instead of closing tag '"+tagName+"'.", + getLineNumberForPosition(xmlData, tagStartPos)); + } + + //when there are no more tags, we reached the root level. + if (tags.length == 0) { + reachedRoot = true; + } + } + } else { + const isValid = validateAttributeString(attrStr, options); + if (isValid !== true) { + //the result from the nested function returns the position of the error within the attribute + //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute + //this gives us the absolute index in the entire xml, which we can use to find the line at last + return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line)); + } + + //if the root level has been reached before ... + if (reachedRoot === true) { + return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i)); + } else if(options.unpairedTags.indexOf(tagName) !== -1){ + //don't push into stack + } else { + tags.push({tagName, tagStartPos}); + } + tagFound = true; + } + + //skip tag text value + //It may include comments and CDATA value + for (i++; i < xmlData.length; i++) { + if (xmlData[i] === '<') { + if (xmlData[i + 1] === '!') { + //comment or CADATA + i++; + i = readCommentAndCDATA(xmlData, i); + continue; + } else if (xmlData[i+1] === '?') { + i = readPI(xmlData, ++i); + if (i.err) return i; + } else{ + break; + } + } else if (xmlData[i] === '&') { + const afterAmp = validateAmpersand(xmlData, i); + if (afterAmp == -1) + return getErrorObject('InvalidChar', "char '&' is not expected.", getLineNumberForPosition(xmlData, i)); + i = afterAmp; + }else{ + if (reachedRoot === true && !isWhiteSpace(xmlData[i])) { + return getErrorObject('InvalidXml', "Extra text at the end", getLineNumberForPosition(xmlData, i)); + } + } + } //end of reading tag text value + if (xmlData[i] === '<') { + i--; + } + } + } else { + if ( isWhiteSpace(xmlData[i])) { + continue; + } + return getErrorObject('InvalidChar', "char '"+xmlData[i]+"' is not expected.", getLineNumberForPosition(xmlData, i)); + } + } + + if (!tagFound) { + return getErrorObject('InvalidXml', 'Start tag expected.', 1); + }else if (tags.length == 1) { + return getErrorObject('InvalidTag', "Unclosed tag '"+tags[0].tagName+"'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos)); + }else if (tags.length > 0) { + return getErrorObject('InvalidXml', "Invalid '"+ + JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\r?\n/g, '')+ + "' found.", {line: 1, col: 1}); + } + + return true; +}; + +function isWhiteSpace(char){ + return char === ' ' || char === '\t' || char === '\n' || char === '\r'; +} +/** + * Read Processing insstructions and skip + * @param {*} xmlData + * @param {*} i + */ +function readPI(xmlData, i) { + const start = i; + for (; i < xmlData.length; i++) { + if (xmlData[i] == '?' || xmlData[i] == ' ') { + //tagname + const tagname = xmlData.substr(start, i - start); + if (i > 5 && tagname === 'xml') { + return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i)); + } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') { + //check if valid attribut string + i++; + break; + } else { + continue; + } + } + } + return i; +} + +function readCommentAndCDATA(xmlData, i) { + if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') { + //comment + for (i += 3; i < xmlData.length; i++) { + if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') { + i += 2; + break; + } + } + } else if ( + xmlData.length > i + 8 && + xmlData[i + 1] === 'D' && + xmlData[i + 2] === 'O' && + xmlData[i + 3] === 'C' && + xmlData[i + 4] === 'T' && + xmlData[i + 5] === 'Y' && + xmlData[i + 6] === 'P' && + xmlData[i + 7] === 'E' + ) { + let angleBracketsCount = 1; + for (i += 8; i < xmlData.length; i++) { + if (xmlData[i] === '<') { + angleBracketsCount++; + } else if (xmlData[i] === '>') { + angleBracketsCount--; + if (angleBracketsCount === 0) { + break; + } + } + } + } else if ( + xmlData.length > i + 9 && + xmlData[i + 1] === '[' && + xmlData[i + 2] === 'C' && + xmlData[i + 3] === 'D' && + xmlData[i + 4] === 'A' && + xmlData[i + 5] === 'T' && + xmlData[i + 6] === 'A' && + xmlData[i + 7] === '[' + ) { + for (i += 8; i < xmlData.length; i++) { + if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') { + i += 2; + break; + } + } + } + + return i; +} + +const doubleQuote = '"'; +const singleQuote = "'"; + +/** + * Keep reading xmlData until '<' is found outside the attribute value. + * @param {string} xmlData + * @param {number} i + */ +function readAttributeStr(xmlData, i) { + let attrStr = ''; + let startChar = ''; + let tagClosed = false; + for (; i < xmlData.length; i++) { + if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) { + if (startChar === '') { + startChar = xmlData[i]; + } else if (startChar !== xmlData[i]) { + //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa + } else { + startChar = ''; + } + } else if (xmlData[i] === '>') { + if (startChar === '') { + tagClosed = true; + break; + } + } + attrStr += xmlData[i]; + } + if (startChar !== '') { + return false; + } + + return { + value: attrStr, + index: i, + tagClosed: tagClosed + }; +} + +/** + * Select all the attributes whether valid or invalid. + */ +const validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s\\S])*?)\\5)?', 'g'); + +//attr, ="sd", a="amit's", a="sd"b="saf", ab cd="" + +function validateAttributeString(attrStr, options) { + //console.log("start:"+attrStr+":end"); + + //if(attrStr.trim().length === 0) return true; //empty string + + const matches = util.getAllMatches(attrStr, validAttrStrRegxp); + const attrNames = {}; + + for (let i = 0; i < matches.length; i++) { + if (matches[i][1].length === 0) { + //nospace before attribute name: a="sd"b="saf" + return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(matches[i])) + } else if (matches[i][3] !== undefined && matches[i][4] === undefined) { + return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' is without value.", getPositionFromMatch(matches[i])); + } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) { + //independent attribute: ab + return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(matches[i])); + } + /* else if(matches[i][6] === undefined){//attribute without value: ab= + return { err: { code:"InvalidAttr",msg:"attribute " + matches[i][2] + " has no value assigned."}}; + } */ + const attrName = matches[i][2]; + if (!validateAttrName(attrName)) { + return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(matches[i])); + } + if (!attrNames.hasOwnProperty(attrName)) { + //check for duplicate attribute. + attrNames[attrName] = 1; + } else { + return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(matches[i])); + } + } + + return true; +} + +function validateNumberAmpersand(xmlData, i) { + let re = /\d/; + if (xmlData[i] === 'x') { + i++; + re = /[\da-fA-F]/; + } + for (; i < xmlData.length; i++) { + if (xmlData[i] === ';') + return i; + if (!xmlData[i].match(re)) + break; + } + return -1; +} + +function validateAmpersand(xmlData, i) { + // https://www.w3.org/TR/xml/#dt-charref + i++; + if (xmlData[i] === ';') + return -1; + if (xmlData[i] === '#') { + i++; + return validateNumberAmpersand(xmlData, i); + } + let count = 0; + for (; i < xmlData.length; i++, count++) { + if (xmlData[i].match(/\w/) && count < 20) + continue; + if (xmlData[i] === ';') + break; + return -1; + } + return i; +} + +function getErrorObject(code, message, lineNumber) { + return { + err: { + code: code, + msg: message, + line: lineNumber.line || lineNumber, + col: lineNumber.col, + }, + }; +} + +function validateAttrName(attrName) { + return util.isName(attrName); +} + +// const startsWithXML = /^xml/i; + +function validateTagName(tagname) { + return util.isName(tagname) /* && !tagname.match(startsWithXML) */; +} + +//this function returns the line number for the character at the given index +function getLineNumberForPosition(xmlData, index) { + const lines = xmlData.substring(0, index).split(/\r?\n/); + return { + line: lines.length, + + // column number is last line's length + 1, because column numbering starts at 1: + col: lines[lines.length - 1].length + 1 + }; +} + +//this function returns the position of the first character of match within attrStr +function getPositionFromMatch(match) { + return match.startIndex + match[1].length; +} + + +/***/ }), + +/***/ 79708: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +//parse Empty Node as self closing node +const buildFromOrderedJs = __nccwpck_require__(80984); +const getIgnoreAttributesFn = __nccwpck_require__(9209) + +const defaultOptions = { + attributeNamePrefix: '@_', + attributesGroupName: false, + textNodeName: '#text', + ignoreAttributes: true, + cdataPropName: false, + format: false, + indentBy: ' ', + suppressEmptyNode: false, + suppressUnpairedNode: true, + suppressBooleanAttributes: true, + tagValueProcessor: function(key, a) { + return a; + }, + attributeValueProcessor: function(attrName, a) { + return a; + }, + preserveOrder: false, + commentPropName: false, + unpairedTags: [], + entities: [ + { regex: new RegExp("&", "g"), val: "&" },//it must be on top + { regex: new RegExp(">", "g"), val: ">" }, + { regex: new RegExp("<", "g"), val: "<" }, + { regex: new RegExp("\'", "g"), val: "'" }, + { regex: new RegExp("\"", "g"), val: """ } + ], + processEntities: true, + stopNodes: [], + // transformTagName: false, + // transformAttributeName: false, + oneListGroup: false +}; + +function Builder(options) { + this.options = Object.assign({}, defaultOptions, options); + if (this.options.ignoreAttributes === true || this.options.attributesGroupName) { + this.isAttribute = function(/*a*/) { + return false; + }; + } else { + this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes) + this.attrPrefixLen = this.options.attributeNamePrefix.length; + this.isAttribute = isAttribute; + } + + this.processTextOrObjNode = processTextOrObjNode + + if (this.options.format) { + this.indentate = indentate; + this.tagEndChar = '>\n'; + this.newLine = '\n'; + } else { + this.indentate = function() { + return ''; + }; + this.tagEndChar = '>'; + this.newLine = ''; + } +} + +Builder.prototype.build = function(jObj) { + if(this.options.preserveOrder){ + return buildFromOrderedJs(jObj, this.options); + }else { + if(Array.isArray(jObj) && this.options.arrayNodeName && this.options.arrayNodeName.length > 1){ + jObj = { + [this.options.arrayNodeName] : jObj + } + } + return this.j2x(jObj, 0, []).val; + } +}; + +Builder.prototype.j2x = function(jObj, level, ajPath) { + let attrStr = ''; + let val = ''; + const jPath = ajPath.join('.') + for (let key in jObj) { + if(!Object.prototype.hasOwnProperty.call(jObj, key)) continue; + if (typeof jObj[key] === 'undefined') { + // supress undefined node only if it is not an attribute + if (this.isAttribute(key)) { + val += ''; + } + } else if (jObj[key] === null) { + // null attribute should be ignored by the attribute list, but should not cause the tag closing + if (this.isAttribute(key)) { + val += ''; + } else if (key === this.options.cdataPropName) { + val += ''; + } else if (key[0] === '?') { + val += this.indentate(level) + '<' + key + '?' + this.tagEndChar; + } else { + val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + } + // val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + } else if (jObj[key] instanceof Date) { + val += this.buildTextValNode(jObj[key], key, '', level); + } else if (typeof jObj[key] !== 'object') { + //premitive type + const attr = this.isAttribute(key); + if (attr && !this.ignoreAttributesFn(attr, jPath)) { + attrStr += this.buildAttrPairStr(attr, '' + jObj[key]); + } else if (!attr) { + //tag value + if (key === this.options.textNodeName) { + let newval = this.options.tagValueProcessor(key, '' + jObj[key]); + val += this.replaceEntitiesValue(newval); + } else { + val += this.buildTextValNode(jObj[key], key, '', level); + } + } + } else if (Array.isArray(jObj[key])) { + //repeated nodes + const arrLen = jObj[key].length; + let listTagVal = ""; + let listTagAttr = ""; + for (let j = 0; j < arrLen; j++) { + const item = jObj[key][j]; + if (typeof item === 'undefined') { + // supress undefined node + } else if (item === null) { + if(key[0] === "?") val += this.indentate(level) + '<' + key + '?' + this.tagEndChar; + else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + // val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + } else if (typeof item === 'object') { + if(this.options.oneListGroup){ + const result = this.j2x(item, level + 1, ajPath.concat(key)); + listTagVal += result.val; + if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) { + listTagAttr += result.attrStr + } + }else{ + listTagVal += this.processTextOrObjNode(item, key, level, ajPath) + } + } else { + if (this.options.oneListGroup) { + let textValue = this.options.tagValueProcessor(key, item); + textValue = this.replaceEntitiesValue(textValue); + listTagVal += textValue; + } else { + listTagVal += this.buildTextValNode(item, key, '', level); + } + } + } + if(this.options.oneListGroup){ + listTagVal = this.buildObjectNode(listTagVal, key, listTagAttr, level); + } + val += listTagVal; + } else { + //nested node + if (this.options.attributesGroupName && key === this.options.attributesGroupName) { + const Ks = Object.keys(jObj[key]); + const L = Ks.length; + for (let j = 0; j < L; j++) { + attrStr += this.buildAttrPairStr(Ks[j], '' + jObj[key][Ks[j]]); + } + } else { + val += this.processTextOrObjNode(jObj[key], key, level, ajPath) + } + } + } + return {attrStr: attrStr, val: val}; +}; + +Builder.prototype.buildAttrPairStr = function(attrName, val){ + val = this.options.attributeValueProcessor(attrName, '' + val); + val = this.replaceEntitiesValue(val); + if (this.options.suppressBooleanAttributes && val === "true") { + return ' ' + attrName; + } else return ' ' + attrName + '="' + val + '"'; +} + +function processTextOrObjNode (object, key, level, ajPath) { + const result = this.j2x(object, level + 1, ajPath.concat(key)); + if (object[this.options.textNodeName] !== undefined && Object.keys(object).length === 1) { + return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level); + } else { + return this.buildObjectNode(result.val, key, result.attrStr, level); + } +} + +Builder.prototype.buildObjectNode = function(val, key, attrStr, level) { + if(val === ""){ + if(key[0] === "?") return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar; + else { + return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar; + } + }else{ + + let tagEndExp = '' + val + tagEndExp ); + } else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) { + return this.indentate(level) + `` + this.newLine; + }else { + return ( + this.indentate(level) + '<' + key + attrStr + piClosingChar + this.tagEndChar + + val + + this.indentate(level) + tagEndExp ); + } + } +} + +Builder.prototype.closeTag = function(key){ + let closeTag = ""; + if(this.options.unpairedTags.indexOf(key) !== -1){ //unpaired + if(!this.options.suppressUnpairedNode) closeTag = "/" + }else if(this.options.suppressEmptyNode){ //empty + closeTag = "/"; + }else{ + closeTag = `>` + this.newLine; + }else if (this.options.commentPropName !== false && key === this.options.commentPropName) { + return this.indentate(level) + `` + this.newLine; + }else if(key[0] === "?") {//PI tag + return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar; + }else{ + let textValue = this.options.tagValueProcessor(key, val); + textValue = this.replaceEntitiesValue(textValue); + + if( textValue === ''){ + return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar; + }else{ + return this.indentate(level) + '<' + key + attrStr + '>' + + textValue + + ' 0 && this.options.processEntities){ + for (let i=0; i { + +const EOL = "\n"; + +/** + * + * @param {array} jArray + * @param {any} options + * @returns + */ +function toXml(jArray, options) { + let indentation = ""; + if (options.format && options.indentBy.length > 0) { + indentation = EOL; + } + return arrToStr(jArray, options, "", indentation); +} + +function arrToStr(arr, options, jPath, indentation) { + let xmlStr = ""; + let isPreviousElementTag = false; + + for (let i = 0; i < arr.length; i++) { + const tagObj = arr[i]; + const tagName = propName(tagObj); + if(tagName === undefined) continue; + + let newJPath = ""; + if (jPath.length === 0) newJPath = tagName + else newJPath = `${jPath}.${tagName}`; + + if (tagName === options.textNodeName) { + let tagText = tagObj[tagName]; + if (!isStopNode(newJPath, options)) { + tagText = options.tagValueProcessor(tagName, tagText); + tagText = replaceEntitiesValue(tagText, options); + } + if (isPreviousElementTag) { + xmlStr += indentation; + } + xmlStr += tagText; + isPreviousElementTag = false; + continue; + } else if (tagName === options.cdataPropName) { + if (isPreviousElementTag) { + xmlStr += indentation; + } + xmlStr += ``; + isPreviousElementTag = false; + continue; + } else if (tagName === options.commentPropName) { + xmlStr += indentation + ``; + isPreviousElementTag = true; + continue; + } else if (tagName[0] === "?") { + const attStr = attr_to_str(tagObj[":@"], options); + const tempInd = tagName === "?xml" ? "" : indentation; + let piTextNodeName = tagObj[tagName][0][options.textNodeName]; + piTextNodeName = piTextNodeName.length !== 0 ? " " + piTextNodeName : ""; //remove extra spacing + xmlStr += tempInd + `<${tagName}${piTextNodeName}${attStr}?>`; + isPreviousElementTag = true; + continue; + } + let newIdentation = indentation; + if (newIdentation !== "") { + newIdentation += options.indentBy; + } + const attStr = attr_to_str(tagObj[":@"], options); + const tagStart = indentation + `<${tagName}${attStr}`; + const tagValue = arrToStr(tagObj[tagName], options, newJPath, newIdentation); + if (options.unpairedTags.indexOf(tagName) !== -1) { + if (options.suppressUnpairedNode) xmlStr += tagStart + ">"; + else xmlStr += tagStart + "/>"; + } else if ((!tagValue || tagValue.length === 0) && options.suppressEmptyNode) { + xmlStr += tagStart + "/>"; + } else if (tagValue && tagValue.endsWith(">")) { + xmlStr += tagStart + `>${tagValue}${indentation}`; + } else { + xmlStr += tagStart + ">"; + if (tagValue && indentation !== "" && (tagValue.includes("/>") || tagValue.includes("`; + } + isPreviousElementTag = true; + } + + return xmlStr; +} + +function propName(obj) { + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if(!obj.hasOwnProperty(key)) continue; + if (key !== ":@") return key; + } +} + +function attr_to_str(attrMap, options) { + let attrStr = ""; + if (attrMap && !options.ignoreAttributes) { + for (let attr in attrMap) { + if(!attrMap.hasOwnProperty(attr)) continue; + let attrVal = options.attributeValueProcessor(attr, attrMap[attr]); + attrVal = replaceEntitiesValue(attrVal, options); + if (attrVal === true && options.suppressBooleanAttributes) { + attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}`; + } else { + attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${attrVal}"`; + } + } + } + return attrStr; +} + +function isStopNode(jPath, options) { + jPath = jPath.substr(0, jPath.length - options.textNodeName.length - 1); + let tagName = jPath.substr(jPath.lastIndexOf(".") + 1); + for (let index in options.stopNodes) { + if (options.stopNodes[index] === jPath || options.stopNodes[index] === "*." + tagName) return true; + } + return false; +} + +function replaceEntitiesValue(textValue, options) { + if (textValue && textValue.length > 0 && options.processEntities) { + for (let i = 0; i < options.entities.length; i++) { + const entity = options.entities[i]; + textValue = textValue.replace(entity.regex, entity.val); + } + } + return textValue; +} +module.exports = toXml; + + +/***/ }), + +/***/ 56988: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const util = __nccwpck_require__(55506); + +//TODO: handle comments +function readDocType(xmlData, i){ + + const entities = {}; + if( xmlData[i + 3] === 'O' && + xmlData[i + 4] === 'C' && + xmlData[i + 5] === 'T' && + xmlData[i + 6] === 'Y' && + xmlData[i + 7] === 'P' && + xmlData[i + 8] === 'E') + { + i = i+9; + let angleBracketsCount = 1; + let hasBody = false, comment = false; + let exp = ""; + for(;i') { //Read tag content + if(comment){ + if( xmlData[i - 1] === "-" && xmlData[i - 2] === "-"){ + comment = false; + angleBracketsCount--; + } + }else{ + angleBracketsCount--; + } + if (angleBracketsCount === 0) { + break; + } + }else if( xmlData[i] === '['){ + hasBody = true; + }else{ + exp += xmlData[i]; + } + } + if(angleBracketsCount !== 0){ + throw new Error(`Unclosed DOCTYPE`); + } + }else{ + throw new Error(`Invalid Tag instead of DOCTYPE`); + } + return {entities, i}; +} + +function readEntityExp(xmlData,i){ + //External entities are not supported + // + + //Parameter entities are not supported + // + + //Internal entities are supported + // + + //read EntityName + let entityName = ""; + for (; i < xmlData.length && (xmlData[i] !== "'" && xmlData[i] !== '"' ); i++) { + // if(xmlData[i] === " ") continue; + // else + entityName += xmlData[i]; + } + entityName = entityName.trim(); + if(entityName.indexOf(" ") !== -1) throw new Error("External entites are not supported"); + + //read Entity Value + const startChar = xmlData[i++]; + let val = "" + for (; i < xmlData.length && xmlData[i] !== startChar ; i++) { + val += xmlData[i]; + } + return [entityName, val, i]; +} + +function isComment(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === '-' && + xmlData[i+3] === '-') return true + return false +} +function isEntity(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'E' && + xmlData[i+3] === 'N' && + xmlData[i+4] === 'T' && + xmlData[i+5] === 'I' && + xmlData[i+6] === 'T' && + xmlData[i+7] === 'Y') return true + return false +} +function isElement(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'E' && + xmlData[i+3] === 'L' && + xmlData[i+4] === 'E' && + xmlData[i+5] === 'M' && + xmlData[i+6] === 'E' && + xmlData[i+7] === 'N' && + xmlData[i+8] === 'T') return true + return false +} + +function isAttlist(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'A' && + xmlData[i+3] === 'T' && + xmlData[i+4] === 'T' && + xmlData[i+5] === 'L' && + xmlData[i+6] === 'I' && + xmlData[i+7] === 'S' && + xmlData[i+8] === 'T') return true + return false +} +function isNotation(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'N' && + xmlData[i+3] === 'O' && + xmlData[i+4] === 'T' && + xmlData[i+5] === 'A' && + xmlData[i+6] === 'T' && + xmlData[i+7] === 'I' && + xmlData[i+8] === 'O' && + xmlData[i+9] === 'N') return true + return false +} + +function validateEntityName(name){ + if (util.isName(name)) + return name; + else + throw new Error(`Invalid entity name ${name}`); +} + +module.exports = readDocType; + + +/***/ }), + +/***/ 81392: +/***/ ((__unused_webpack_module, exports) => { + + +const defaultOptions = { + preserveOrder: false, + attributeNamePrefix: '@_', + attributesGroupName: false, + textNodeName: '#text', + ignoreAttributes: true, + removeNSPrefix: false, // remove NS from tag name or attribute name if true + allowBooleanAttributes: false, //a tag can have attributes without any value + //ignoreRootElement : false, + parseTagValue: true, + parseAttributeValue: false, + trimValues: true, //Trim string values of tag and attributes + cdataPropName: false, + numberParseOptions: { + hex: true, + leadingZeros: true, + eNotation: true + }, + tagValueProcessor: function(tagName, val) { + return val; + }, + attributeValueProcessor: function(attrName, val) { + return val; + }, + stopNodes: [], //nested tags will not be parsed even for errors + alwaysCreateTextNode: false, + isArray: () => false, + commentPropName: false, + unpairedTags: [], + processEntities: true, + htmlEntities: false, + ignoreDeclaration: false, + ignorePiTags: false, + transformTagName: false, + transformAttributeName: false, + updateTag: function(tagName, jPath, attrs){ + return tagName + }, + // skipEmptyListItem: false +}; + +const buildOptions = function(options) { + return Object.assign({}, defaultOptions, options); +}; + +exports.buildOptions = buildOptions; +exports.defaultOptions = defaultOptions; + +/***/ }), + +/***/ 19036: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +///@ts-check + +const util = __nccwpck_require__(55506); +const xmlNode = __nccwpck_require__(72964); +const readDocType = __nccwpck_require__(56988); +const toNumber = __nccwpck_require__(82203); +const getIgnoreAttributesFn = __nccwpck_require__(9209) + +// const regx = +// '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)' +// .replace(/NAME/g, util.nameRegexp); + +//const tagsRegx = new RegExp("<(\\/?[\\w:\\-\._]+)([^>]*)>(\\s*"+cdataRegx+")*([^<]+)?","g"); +//const tagsRegx = new RegExp("<(\\/?)((\\w*:)?([\\w:\\-\._]+))([^>]*)>([^<]*)("+cdataRegx+"([^<]*))*([^<]+)?","g"); + +class OrderedObjParser{ + constructor(options){ + this.options = options; + this.currentNode = null; + this.tagsNodeStack = []; + this.docTypeEntities = {}; + this.lastEntities = { + "apos" : { regex: /&(apos|#39|#x27);/g, val : "'"}, + "gt" : { regex: /&(gt|#62|#x3E);/g, val : ">"}, + "lt" : { regex: /&(lt|#60|#x3C);/g, val : "<"}, + "quot" : { regex: /&(quot|#34|#x22);/g, val : "\""}, + }; + this.ampEntity = { regex: /&(amp|#38|#x26);/g, val : "&"}; + this.htmlEntities = { + "space": { regex: /&(nbsp|#160);/g, val: " " }, + // "lt" : { regex: /&(lt|#60);/g, val: "<" }, + // "gt" : { regex: /&(gt|#62);/g, val: ">" }, + // "amp" : { regex: /&(amp|#38);/g, val: "&" }, + // "quot" : { regex: /&(quot|#34);/g, val: "\"" }, + // "apos" : { regex: /&(apos|#39);/g, val: "'" }, + "cent" : { regex: /&(cent|#162);/g, val: "¢" }, + "pound" : { regex: /&(pound|#163);/g, val: "£" }, + "yen" : { regex: /&(yen|#165);/g, val: "¥" }, + "euro" : { regex: /&(euro|#8364);/g, val: "€" }, + "copyright" : { regex: /&(copy|#169);/g, val: "©" }, + "reg" : { regex: /&(reg|#174);/g, val: "®" }, + "inr" : { regex: /&(inr|#8377);/g, val: "₹" }, + "num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 10)) }, + "num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 16)) }, + }; + this.addExternalEntities = addExternalEntities; + this.parseXml = parseXml; + this.parseTextData = parseTextData; + this.resolveNameSpace = resolveNameSpace; + this.buildAttributesMap = buildAttributesMap; + this.isItStopNode = isItStopNode; + this.replaceEntitiesValue = replaceEntitiesValue; + this.readStopNodeData = readStopNodeData; + this.saveTextToParentTag = saveTextToParentTag; + this.addChild = addChild; + this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes) + } + +} + +function addExternalEntities(externalEntities){ + const entKeys = Object.keys(externalEntities); + for (let i = 0; i < entKeys.length; i++) { + const ent = entKeys[i]; + this.lastEntities[ent] = { + regex: new RegExp("&"+ent+";","g"), + val : externalEntities[ent] + } + } +} + +/** + * @param {string} val + * @param {string} tagName + * @param {string} jPath + * @param {boolean} dontTrim + * @param {boolean} hasAttributes + * @param {boolean} isLeafNode + * @param {boolean} escapeEntities + */ +function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) { + if (val !== undefined) { + if (this.options.trimValues && !dontTrim) { + val = val.trim(); + } + if(val.length > 0){ + if(!escapeEntities) val = this.replaceEntitiesValue(val); + + const newval = this.options.tagValueProcessor(tagName, val, jPath, hasAttributes, isLeafNode); + if(newval === null || newval === undefined){ + //don't parse + return val; + }else if(typeof newval !== typeof val || newval !== val){ + //overwrite + return newval; + }else if(this.options.trimValues){ + return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions); + }else{ + const trimmedVal = val.trim(); + if(trimmedVal === val){ + return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions); + }else{ + return val; + } + } + } + } +} + +function resolveNameSpace(tagname) { + if (this.options.removeNSPrefix) { + const tags = tagname.split(':'); + const prefix = tagname.charAt(0) === '/' ? '/' : ''; + if (tags[0] === 'xmlns') { + return ''; + } + if (tags.length === 2) { + tagname = prefix + tags[1]; + } + } + return tagname; +} + +//TODO: change regex to capture NS +//const attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm"); +const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm'); + +function buildAttributesMap(attrStr, jPath, tagName) { + if (this.options.ignoreAttributes !== true && typeof attrStr === 'string') { + // attrStr = attrStr.replace(/\r?\n/g, ' '); + //attrStr = attrStr || attrStr.trim(); + + const matches = util.getAllMatches(attrStr, attrsRegx); + const len = matches.length; //don't make it inline + const attrs = {}; + for (let i = 0; i < len; i++) { + const attrName = this.resolveNameSpace(matches[i][1]); + if (this.ignoreAttributesFn(attrName, jPath)) { + continue + } + let oldVal = matches[i][4]; + let aName = this.options.attributeNamePrefix + attrName; + if (attrName.length) { + if (this.options.transformAttributeName) { + aName = this.options.transformAttributeName(aName); + } + if(aName === "__proto__") aName = "#__proto__"; + if (oldVal !== undefined) { + if (this.options.trimValues) { + oldVal = oldVal.trim(); + } + oldVal = this.replaceEntitiesValue(oldVal); + const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPath); + if(newVal === null || newVal === undefined){ + //don't parse + attrs[aName] = oldVal; + }else if(typeof newVal !== typeof oldVal || newVal !== oldVal){ + //overwrite + attrs[aName] = newVal; + }else{ + //parse + attrs[aName] = parseValue( + oldVal, + this.options.parseAttributeValue, + this.options.numberParseOptions + ); + } + } else if (this.options.allowBooleanAttributes) { + attrs[aName] = true; + } + } + } + if (!Object.keys(attrs).length) { + return; + } + if (this.options.attributesGroupName) { + const attrCollection = {}; + attrCollection[this.options.attributesGroupName] = attrs; + return attrCollection; + } + return attrs + } +} + +const parseXml = function(xmlData) { + xmlData = xmlData.replace(/\r\n?/g, "\n"); //TODO: remove this line + const xmlObj = new xmlNode('!xml'); + let currentNode = xmlObj; + let textData = ""; + let jPath = ""; + for(let i=0; i< xmlData.length; i++){//for each char in XML data + const ch = xmlData[i]; + if(ch === '<'){ + // const nextIndex = i+1; + // const _2ndChar = xmlData[nextIndex]; + if( xmlData[i+1] === '/') {//Closing Tag + const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.") + let tagName = xmlData.substring(i+2,closeIndex).trim(); + + if(this.options.removeNSPrefix){ + const colonIndex = tagName.indexOf(":"); + if(colonIndex !== -1){ + tagName = tagName.substr(colonIndex+1); + } + } + + if(this.options.transformTagName) { + tagName = this.options.transformTagName(tagName); + } + + if(currentNode){ + textData = this.saveTextToParentTag(textData, currentNode, jPath); + } + + //check if last tag of nested tag was unpaired tag + const lastTagName = jPath.substring(jPath.lastIndexOf(".")+1); + if(tagName && this.options.unpairedTags.indexOf(tagName) !== -1 ){ + throw new Error(`Unpaired tag can not be used as closing tag: `); + } + let propIndex = 0 + if(lastTagName && this.options.unpairedTags.indexOf(lastTagName) !== -1 ){ + propIndex = jPath.lastIndexOf('.', jPath.lastIndexOf('.')-1) + this.tagsNodeStack.pop(); + }else{ + propIndex = jPath.lastIndexOf("."); + } + jPath = jPath.substring(0, propIndex); + + currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope + textData = ""; + i = closeIndex; + } else if( xmlData[i+1] === '?') { + + let tagData = readTagExp(xmlData,i, false, "?>"); + if(!tagData) throw new Error("Pi Tag is not closed."); + + textData = this.saveTextToParentTag(textData, currentNode, jPath); + if( (this.options.ignoreDeclaration && tagData.tagName === "?xml") || this.options.ignorePiTags){ + + }else{ + + const childNode = new xmlNode(tagData.tagName); + childNode.add(this.options.textNodeName, ""); + + if(tagData.tagName !== tagData.tagExp && tagData.attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath, tagData.tagName); + } + this.addChild(currentNode, childNode, jPath) + + } + + + i = tagData.closeIndex + 1; + } else if(xmlData.substr(i + 1, 3) === '!--') { + const endIndex = findClosingIndex(xmlData, "-->", i+4, "Comment is not closed.") + if(this.options.commentPropName){ + const comment = xmlData.substring(i + 4, endIndex - 2); + + textData = this.saveTextToParentTag(textData, currentNode, jPath); + + currentNode.add(this.options.commentPropName, [ { [this.options.textNodeName] : comment } ]); + } + i = endIndex; + } else if( xmlData.substr(i + 1, 2) === '!D') { + const result = readDocType(xmlData, i); + this.docTypeEntities = result.entities; + i = result.i; + }else if(xmlData.substr(i + 1, 2) === '![') { + const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2; + const tagExp = xmlData.substring(i + 9,closeIndex); + + textData = this.saveTextToParentTag(textData, currentNode, jPath); + + let val = this.parseTextData(tagExp, currentNode.tagname, jPath, true, false, true, true); + if(val == undefined) val = ""; + + //cdata should be set even if it is 0 length string + if(this.options.cdataPropName){ + currentNode.add(this.options.cdataPropName, [ { [this.options.textNodeName] : tagExp } ]); + }else{ + currentNode.add(this.options.textNodeName, val); + } + + i = closeIndex + 2; + }else {//Opening tag + let result = readTagExp(xmlData,i, this.options.removeNSPrefix); + let tagName= result.tagName; + const rawTagName = result.rawTagName; + let tagExp = result.tagExp; + let attrExpPresent = result.attrExpPresent; + let closeIndex = result.closeIndex; + + if (this.options.transformTagName) { + tagName = this.options.transformTagName(tagName); + } + + //save text as child node + if (currentNode && textData) { + if(currentNode.tagname !== '!xml'){ + //when nested tag is found + textData = this.saveTextToParentTag(textData, currentNode, jPath, false); + } + } + + //check if last tag was unpaired tag + const lastTag = currentNode; + if(lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1 ){ + currentNode = this.tagsNodeStack.pop(); + jPath = jPath.substring(0, jPath.lastIndexOf(".")); + } + if(tagName !== xmlObj.tagname){ + jPath += jPath ? "." + tagName : tagName; + } + if (this.isItStopNode(this.options.stopNodes, jPath, tagName)) { + let tagContent = ""; + //self-closing tag + if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){ + if(tagName[tagName.length - 1] === "/"){ //remove trailing '/' + tagName = tagName.substr(0, tagName.length - 1); + jPath = jPath.substr(0, jPath.length - 1); + tagExp = tagName; + }else{ + tagExp = tagExp.substr(0, tagExp.length - 1); + } + i = result.closeIndex; + } + //unpaired tag + else if(this.options.unpairedTags.indexOf(tagName) !== -1){ + + i = result.closeIndex; + } + //normal tag + else{ + //read until closing tag is found + const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1); + if(!result) throw new Error(`Unexpected end of ${rawTagName}`); + i = result.i; + tagContent = result.tagContent; + } + + const childNode = new xmlNode(tagName); + if(tagName !== tagExp && attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName); + } + if(tagContent) { + tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true); + } + + jPath = jPath.substr(0, jPath.lastIndexOf(".")); + childNode.add(this.options.textNodeName, tagContent); + + this.addChild(currentNode, childNode, jPath) + }else{ + //selfClosing tag + if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){ + if(tagName[tagName.length - 1] === "/"){ //remove trailing '/' + tagName = tagName.substr(0, tagName.length - 1); + jPath = jPath.substr(0, jPath.length - 1); + tagExp = tagName; + }else{ + tagExp = tagExp.substr(0, tagExp.length - 1); + } + + if(this.options.transformTagName) { + tagName = this.options.transformTagName(tagName); + } + + const childNode = new xmlNode(tagName); + if(tagName !== tagExp && attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName); + } + this.addChild(currentNode, childNode, jPath) + jPath = jPath.substr(0, jPath.lastIndexOf(".")); + } + //opening tag + else{ + const childNode = new xmlNode( tagName); + this.tagsNodeStack.push(currentNode); + + if(tagName !== tagExp && attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName); + } + this.addChild(currentNode, childNode, jPath) + currentNode = childNode; + } + textData = ""; + i = closeIndex; + } + } + }else{ + textData += xmlData[i]; + } + } + return xmlObj.child; +} + +function addChild(currentNode, childNode, jPath){ + const result = this.options.updateTag(childNode.tagname, jPath, childNode[":@"]) + if(result === false){ + }else if(typeof result === "string"){ + childNode.tagname = result + currentNode.addChild(childNode); + }else{ + currentNode.addChild(childNode); + } +} + +const replaceEntitiesValue = function(val){ + + if(this.options.processEntities){ + for(let entityName in this.docTypeEntities){ + const entity = this.docTypeEntities[entityName]; + val = val.replace( entity.regx, entity.val); + } + for(let entityName in this.lastEntities){ + const entity = this.lastEntities[entityName]; + val = val.replace( entity.regex, entity.val); + } + if(this.options.htmlEntities){ + for(let entityName in this.htmlEntities){ + const entity = this.htmlEntities[entityName]; + val = val.replace( entity.regex, entity.val); + } + } + val = val.replace( this.ampEntity.regex, this.ampEntity.val); + } + return val; +} +function saveTextToParentTag(textData, currentNode, jPath, isLeafNode) { + if (textData) { //store previously collected data as textNode + if(isLeafNode === undefined) isLeafNode = currentNode.child.length === 0 + + textData = this.parseTextData(textData, + currentNode.tagname, + jPath, + false, + currentNode[":@"] ? Object.keys(currentNode[":@"]).length !== 0 : false, + isLeafNode); + + if (textData !== undefined && textData !== "") + currentNode.add(this.options.textNodeName, textData); + textData = ""; + } + return textData; +} + +//TODO: use jPath to simplify the logic +/** + * + * @param {string[]} stopNodes + * @param {string} jPath + * @param {string} currentTagName + */ +function isItStopNode(stopNodes, jPath, currentTagName){ + const allNodesExp = "*." + currentTagName; + for (const stopNodePath in stopNodes) { + const stopNodeExp = stopNodes[stopNodePath]; + if( allNodesExp === stopNodeExp || jPath === stopNodeExp ) return true; + } + return false; +} + +/** + * Returns the tag Expression and where it is ending handling single-double quotes situation + * @param {string} xmlData + * @param {number} i starting index + * @returns + */ +function tagExpWithClosingIndex(xmlData, i, closingChar = ">"){ + let attrBoundary; + let tagExp = ""; + for (let index = i; index < xmlData.length; index++) { + let ch = xmlData[index]; + if (attrBoundary) { + if (ch === attrBoundary) attrBoundary = "";//reset + } else if (ch === '"' || ch === "'") { + attrBoundary = ch; + } else if (ch === closingChar[0]) { + if(closingChar[1]){ + if(xmlData[index + 1] === closingChar[1]){ + return { + data: tagExp, + index: index + } + } + }else{ + return { + data: tagExp, + index: index + } + } + } else if (ch === '\t') { + ch = " " + } + tagExp += ch; + } +} + +function findClosingIndex(xmlData, str, i, errMsg){ + const closingIndex = xmlData.indexOf(str, i); + if(closingIndex === -1){ + throw new Error(errMsg) + }else{ + return closingIndex + str.length - 1; + } +} + +function readTagExp(xmlData,i, removeNSPrefix, closingChar = ">"){ + const result = tagExpWithClosingIndex(xmlData, i+1, closingChar); + if(!result) return; + let tagExp = result.data; + const closeIndex = result.index; + const separatorIndex = tagExp.search(/\s/); + let tagName = tagExp; + let attrExpPresent = true; + if(separatorIndex !== -1){//separate tag name and attributes expression + tagName = tagExp.substring(0, separatorIndex); + tagExp = tagExp.substring(separatorIndex + 1).trimStart(); + } + + const rawTagName = tagName; + if(removeNSPrefix){ + const colonIndex = tagName.indexOf(":"); + if(colonIndex !== -1){ + tagName = tagName.substr(colonIndex+1); + attrExpPresent = tagName !== result.data.substr(colonIndex + 1); + } + } + + return { + tagName: tagName, + tagExp: tagExp, + closeIndex: closeIndex, + attrExpPresent: attrExpPresent, + rawTagName: rawTagName, + } +} +/** + * find paired tag for a stop node + * @param {string} xmlData + * @param {string} tagName + * @param {number} i + */ +function readStopNodeData(xmlData, tagName, i){ + const startIndex = i; + // Starting at 1 since we already have an open tag + let openTagCount = 1; + + for (; i < xmlData.length; i++) { + if( xmlData[i] === "<"){ + if (xmlData[i+1] === "/") {//close tag + const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`); + let closeTagName = xmlData.substring(i+2,closeIndex).trim(); + if(closeTagName === tagName){ + openTagCount--; + if (openTagCount === 0) { + return { + tagContent: xmlData.substring(startIndex, i), + i : closeIndex + } + } + } + i=closeIndex; + } else if(xmlData[i+1] === '?') { + const closeIndex = findClosingIndex(xmlData, "?>", i+1, "StopNode is not closed.") + i=closeIndex; + } else if(xmlData.substr(i + 1, 3) === '!--') { + const closeIndex = findClosingIndex(xmlData, "-->", i+3, "StopNode is not closed.") + i=closeIndex; + } else if(xmlData.substr(i + 1, 2) === '![') { + const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2; + i=closeIndex; + } else { + const tagData = readTagExp(xmlData, i, '>') + + if (tagData) { + const openTagName = tagData && tagData.tagName; + if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length-1] !== "/") { + openTagCount++; + } + i=tagData.closeIndex; + } + } + } + }//end for loop +} + +function parseValue(val, shouldParse, options) { + if (shouldParse && typeof val === 'string') { + //console.log(options) + const newval = val.trim(); + if(newval === 'true' ) return true; + else if(newval === 'false' ) return false; + else return toNumber(val, options); + } else { + if (util.isExist(val)) { + return val; + } else { + return ''; + } + } +} + + +module.exports = OrderedObjParser; + + +/***/ }), + +/***/ 44079: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { buildOptions} = __nccwpck_require__(81392); +const OrderedObjParser = __nccwpck_require__(19036); +const { prettify} = __nccwpck_require__(40185); +const validator = __nccwpck_require__(67266); + +class XMLParser{ + + constructor(options){ + this.externalEntities = {}; + this.options = buildOptions(options); + + } + /** + * Parse XML dats to JS object + * @param {string|Buffer} xmlData + * @param {boolean|Object} validationOption + */ + parse(xmlData,validationOption){ + if(typeof xmlData === "string"){ + }else if( xmlData.toString){ + xmlData = xmlData.toString(); + }else{ + throw new Error("XML data is accepted in String or Bytes[] form.") + } + if( validationOption){ + if(validationOption === true) validationOption = {}; //validate with default options + + const result = validator.validate(xmlData, validationOption); + if (result !== true) { + throw Error( `${result.err.msg}:${result.err.line}:${result.err.col}` ) + } + } + const orderedObjParser = new OrderedObjParser(this.options); + orderedObjParser.addExternalEntities(this.externalEntities); + const orderedResult = orderedObjParser.parseXml(xmlData); + if(this.options.preserveOrder || orderedResult === undefined) return orderedResult; + else return prettify(orderedResult, this.options); + } + + /** + * Add Entity which is not by default supported by this library + * @param {string} key + * @param {string} value + */ + addEntity(key, value){ + if(value.indexOf("&") !== -1){ + throw new Error("Entity value can't have '&'") + }else if(key.indexOf("&") !== -1 || key.indexOf(";") !== -1){ + throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for ' '") + }else if(value === "&"){ + throw new Error("An entity with value '&' is not permitted"); + }else{ + this.externalEntities[key] = value; + } + } +} + +module.exports = XMLParser; + +/***/ }), + +/***/ 40185: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +/** + * + * @param {array} node + * @param {any} options + * @returns + */ +function prettify(node, options){ + return compress( node, options); +} + +/** + * + * @param {array} arr + * @param {object} options + * @param {string} jPath + * @returns object + */ +function compress(arr, options, jPath){ + let text; + const compressedObj = {}; + for (let i = 0; i < arr.length; i++) { + const tagObj = arr[i]; + const property = propName(tagObj); + let newJpath = ""; + if(jPath === undefined) newJpath = property; + else newJpath = jPath + "." + property; + + if(property === options.textNodeName){ + if(text === undefined) text = tagObj[property]; + else text += "" + tagObj[property]; + }else if(property === undefined){ + continue; + }else if(tagObj[property]){ + + let val = compress(tagObj[property], options, newJpath); + const isLeaf = isLeafTag(val, options); + + if(tagObj[":@"]){ + assignAttributes( val, tagObj[":@"], newJpath, options); + }else if(Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode){ + val = val[options.textNodeName]; + }else if(Object.keys(val).length === 0){ + if(options.alwaysCreateTextNode) val[options.textNodeName] = ""; + else val = ""; + } + + if(compressedObj[property] !== undefined && compressedObj.hasOwnProperty(property)) { + if(!Array.isArray(compressedObj[property])) { + compressedObj[property] = [ compressedObj[property] ]; + } + compressedObj[property].push(val); + }else{ + //TODO: if a node is not an array, then check if it should be an array + //also determine if it is a leaf node + if (options.isArray(property, newJpath, isLeaf )) { + compressedObj[property] = [val]; + }else{ + compressedObj[property] = val; + } + } + } + + } + // if(text && text.length > 0) compressedObj[options.textNodeName] = text; + if(typeof text === "string"){ + if(text.length > 0) compressedObj[options.textNodeName] = text; + }else if(text !== undefined) compressedObj[options.textNodeName] = text; + return compressedObj; +} + +function propName(obj){ + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if(key !== ":@") return key; + } +} + +function assignAttributes(obj, attrMap, jpath, options){ + if (attrMap) { + const keys = Object.keys(attrMap); + const len = keys.length; //don't make it inline + for (let i = 0; i < len; i++) { + const atrrName = keys[i]; + if (options.isArray(atrrName, jpath + "." + atrrName, true, true)) { + obj[atrrName] = [ attrMap[atrrName] ]; + } else { + obj[atrrName] = attrMap[atrrName]; + } + } + } +} + +function isLeafTag(obj, options){ + const { textNodeName } = options; + const propCount = Object.keys(obj).length; + + if (propCount === 0) { + return true; + } + + if ( + propCount === 1 && + (obj[textNodeName] || typeof obj[textNodeName] === "boolean" || obj[textNodeName] === 0) + ) { + return true; + } + + return false; +} +exports.prettify = prettify; + + +/***/ }), + +/***/ 72964: +/***/ ((module) => { + +"use strict"; + + +class XmlNode{ + constructor(tagname) { + this.tagname = tagname; + this.child = []; //nested tags, text, cdata, comments in order + this[":@"] = {}; //attributes map + } + add(key,val){ + // this.child.push( {name : key, val: val, isCdata: isCdata }); + if(key === "__proto__") key = "#__proto__"; + this.child.push( {[key]: val }); + } + addChild(node) { + if(node.tagname === "__proto__") node.tagname = "#__proto__"; + if(node[":@"] && Object.keys(node[":@"]).length > 0){ + this.child.push( { [node.tagname]: node.child, [":@"]: node[":@"] }); + }else{ + this.child.push( { [node.tagname]: node.child }); + } + }; +}; + + +module.exports = XmlNode; + +/***/ }), + +/***/ 82203: +/***/ ((module) => { + +const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/; +const numRegex = /^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/; +// const octRegex = /^0x[a-z0-9]+/; +// const binRegex = /0x[a-z0-9]+/; + + +const consider = { + hex : true, + // oct: false, + leadingZeros: true, + decimalPoint: "\.", + eNotation: true, + //skipLike: /regex/ +}; + +function toNumber(str, options = {}){ + options = Object.assign({}, consider, options ); + if(!str || typeof str !== "string" ) return str; + + let trimmedStr = str.trim(); + + if(options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str; + else if(str==="0") return 0; + else if (options.hex && hexRegex.test(trimmedStr)) { + return parse_int(trimmedStr, 16); + // }else if (options.oct && octRegex.test(str)) { + // return Number.parseInt(val, 8); + }else if (trimmedStr.search(/[eE]/)!== -1) { //eNotation + const notation = trimmedStr.match(/^([-\+])?(0*)([0-9]*(\.[0-9]*)?[eE][-\+]?[0-9]+)$/); + // +00.123 => [ , '+', '00', '.123', .. + if(notation){ + // console.log(notation) + if(options.leadingZeros){ //accept with leading zeros + trimmedStr = (notation[1] || "") + notation[3]; + }else{ + if(notation[2] === "0" && notation[3][0]=== "."){ //valid number + }else{ + return str; + } + } + return options.eNotation ? Number(trimmedStr) : str; + }else{ + return str; + } + // }else if (options.parseBin && binRegex.test(str)) { + // return Number.parseInt(val, 2); + }else{ + //separate negative sign, leading zeros, and rest number + const match = numRegex.exec(trimmedStr); + // +00.123 => [ , '+', '00', '.123', .. + if(match){ + const sign = match[1]; + const leadingZeros = match[2]; + let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros + //trim ending zeros for floating number + + if(!options.leadingZeros && leadingZeros.length > 0 && sign && trimmedStr[2] !== ".") return str; //-0123 + else if(!options.leadingZeros && leadingZeros.length > 0 && !sign && trimmedStr[1] !== ".") return str; //0123 + else if(options.leadingZeros && leadingZeros===str) return 0; //00 + + else{//no leading zeros or leading zeros are allowed + const num = Number(trimmedStr); + const numStr = "" + num; + + if(numStr.search(/[eE]/) !== -1){ //given number is long and parsed to eNotation + if(options.eNotation) return num; + else return str; + }else if(trimmedStr.indexOf(".") !== -1){ //floating number + if(numStr === "0" && (numTrimmedByZeros === "") ) return num; //0.0 + else if(numStr === numTrimmedByZeros) return num; //0.456. 0.79000 + else if( sign && numStr === "-"+numTrimmedByZeros) return num; + else return str; + } + + if(leadingZeros){ + return (numTrimmedByZeros === numStr) || (sign+numTrimmedByZeros === numStr) ? num : str + }else { + return (trimmedStr === numStr) || (trimmedStr === sign+numStr) ? num : str + } + } + }else{ //non-numeric string + return str; + } + } +} + +/** + * + * @param {string} numStr without leading zeros + * @returns + */ +function trimZeros(numStr){ + if(numStr && numStr.indexOf(".") !== -1){//float + numStr = numStr.replace(/0+$/, ""); //remove ending zeros + if(numStr === ".") numStr = "0"; + else if(numStr[0] === ".") numStr = "0"+numStr; + else if(numStr[numStr.length-1] === ".") numStr = numStr.substr(0,numStr.length-1); + return numStr; + } + return numStr; +} + +function parse_int(numStr, base){ + //polyfill + if(parseInt) return parseInt(numStr, base); + else if(Number.parseInt) return Number.parseInt(numStr, base); + else if(window && window.parseInt) return window.parseInt(numStr, base); + else throw new Error("parseInt, Number.parseInt, window.parseInt are not supported") +} + +module.exports = toNumber; + +/***/ }), + +/***/ 20607: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(21150)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(19220)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(4289)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(36658)); + +var _nil = _interopRequireDefault(__nccwpck_require__(97608)); + +var _version = _interopRequireDefault(__nccwpck_require__(25807)); + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +var _parse = _interopRequireDefault(__nccwpck_require__(36712)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 90039: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 97608: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 36712: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 42456: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 18874: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 39490: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 77318: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function stringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 21150: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(18874)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.default)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 19220: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(38465)); + +var _md = _interopRequireDefault(__nccwpck_require__(90039)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 38465: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = _default; +exports.URL = exports.DNS = void 0; + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +var _parse = _interopRequireDefault(__nccwpck_require__(36712)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (namespace.length !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 4289: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(18874)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.default)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 36658: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(38465)); + +var _sha = _interopRequireDefault(__nccwpck_require__(39490)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 75869: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(42456)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 25807: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.substr(14, 1), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 39316: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + CONFIG_USE_DUALSTACK_ENDPOINT: () => CONFIG_USE_DUALSTACK_ENDPOINT, + CONFIG_USE_FIPS_ENDPOINT: () => CONFIG_USE_FIPS_ENDPOINT, + DEFAULT_USE_DUALSTACK_ENDPOINT: () => DEFAULT_USE_DUALSTACK_ENDPOINT, + DEFAULT_USE_FIPS_ENDPOINT: () => DEFAULT_USE_FIPS_ENDPOINT, + ENV_USE_DUALSTACK_ENDPOINT: () => ENV_USE_DUALSTACK_ENDPOINT, + ENV_USE_FIPS_ENDPOINT: () => ENV_USE_FIPS_ENDPOINT, + NODE_REGION_CONFIG_FILE_OPTIONS: () => NODE_REGION_CONFIG_FILE_OPTIONS, + NODE_REGION_CONFIG_OPTIONS: () => NODE_REGION_CONFIG_OPTIONS, + NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS: () => NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, + NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS: () => NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, + REGION_ENV_NAME: () => REGION_ENV_NAME, + REGION_INI_NAME: () => REGION_INI_NAME, + getRegionInfo: () => getRegionInfo, + resolveCustomEndpointsConfig: () => resolveCustomEndpointsConfig, + resolveEndpointsConfig: () => resolveEndpointsConfig, + resolveRegionConfig: () => resolveRegionConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/endpointsConfig/NodeUseDualstackEndpointConfigOptions.ts +var import_util_config_provider = __nccwpck_require__(56716); +var ENV_USE_DUALSTACK_ENDPOINT = "AWS_USE_DUALSTACK_ENDPOINT"; +var CONFIG_USE_DUALSTACK_ENDPOINT = "use_dualstack_endpoint"; +var DEFAULT_USE_DUALSTACK_ENDPOINT = false; +var NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => (0, import_util_config_provider.booleanSelector)(env, ENV_USE_DUALSTACK_ENDPOINT, import_util_config_provider.SelectorType.ENV), + configFileSelector: (profile) => (0, import_util_config_provider.booleanSelector)(profile, CONFIG_USE_DUALSTACK_ENDPOINT, import_util_config_provider.SelectorType.CONFIG), + default: false +}; + +// src/endpointsConfig/NodeUseFipsEndpointConfigOptions.ts + +var ENV_USE_FIPS_ENDPOINT = "AWS_USE_FIPS_ENDPOINT"; +var CONFIG_USE_FIPS_ENDPOINT = "use_fips_endpoint"; +var DEFAULT_USE_FIPS_ENDPOINT = false; +var NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => (0, import_util_config_provider.booleanSelector)(env, ENV_USE_FIPS_ENDPOINT, import_util_config_provider.SelectorType.ENV), + configFileSelector: (profile) => (0, import_util_config_provider.booleanSelector)(profile, CONFIG_USE_FIPS_ENDPOINT, import_util_config_provider.SelectorType.CONFIG), + default: false +}; + +// src/endpointsConfig/resolveCustomEndpointsConfig.ts +var import_util_middleware = __nccwpck_require__(76324); +var resolveCustomEndpointsConfig = /* @__PURE__ */ __name((input) => { + const { tls, endpoint, urlParser, useDualstackEndpoint } = input; + return Object.assign(input, { + tls: tls ?? true, + endpoint: (0, import_util_middleware.normalizeProvider)(typeof endpoint === "string" ? urlParser(endpoint) : endpoint), + isCustomEndpoint: true, + useDualstackEndpoint: (0, import_util_middleware.normalizeProvider)(useDualstackEndpoint ?? false) + }); +}, "resolveCustomEndpointsConfig"); + +// src/endpointsConfig/resolveEndpointsConfig.ts + + +// src/endpointsConfig/utils/getEndpointFromRegion.ts +var getEndpointFromRegion = /* @__PURE__ */ __name(async (input) => { + const { tls = true } = input; + const region = await input.region(); + const dnsHostRegex = new RegExp(/^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$/); + if (!dnsHostRegex.test(region)) { + throw new Error("Invalid region in client config"); + } + const useDualstackEndpoint = await input.useDualstackEndpoint(); + const useFipsEndpoint = await input.useFipsEndpoint(); + const { hostname } = await input.regionInfoProvider(region, { useDualstackEndpoint, useFipsEndpoint }) ?? {}; + if (!hostname) { + throw new Error("Cannot resolve hostname from client config"); + } + return input.urlParser(`${tls ? "https:" : "http:"}//${hostname}`); +}, "getEndpointFromRegion"); + +// src/endpointsConfig/resolveEndpointsConfig.ts +var resolveEndpointsConfig = /* @__PURE__ */ __name((input) => { + const useDualstackEndpoint = (0, import_util_middleware.normalizeProvider)(input.useDualstackEndpoint ?? false); + const { endpoint, useFipsEndpoint, urlParser, tls } = input; + return Object.assign(input, { + tls: tls ?? true, + endpoint: endpoint ? (0, import_util_middleware.normalizeProvider)(typeof endpoint === "string" ? urlParser(endpoint) : endpoint) : () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }), + isCustomEndpoint: !!endpoint, + useDualstackEndpoint + }); +}, "resolveEndpointsConfig"); + +// src/regionConfig/config.ts +var REGION_ENV_NAME = "AWS_REGION"; +var REGION_INI_NAME = "region"; +var NODE_REGION_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[REGION_ENV_NAME], + configFileSelector: (profile) => profile[REGION_INI_NAME], + default: () => { + throw new Error("Region is missing"); + } +}; +var NODE_REGION_CONFIG_FILE_OPTIONS = { + preferredFile: "credentials" +}; + +// src/regionConfig/isFipsRegion.ts +var isFipsRegion = /* @__PURE__ */ __name((region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips")), "isFipsRegion"); + +// src/regionConfig/getRealRegion.ts +var getRealRegion = /* @__PURE__ */ __name((region) => isFipsRegion(region) ? ["fips-aws-global", "aws-fips"].includes(region) ? "us-east-1" : region.replace(/fips-(dkr-|prod-)?|-fips/, "") : region, "getRealRegion"); + +// src/regionConfig/resolveRegionConfig.ts +var resolveRegionConfig = /* @__PURE__ */ __name((input) => { + const { region, useFipsEndpoint } = input; + if (!region) { + throw new Error("Region is missing"); + } + return Object.assign(input, { + region: async () => { + if (typeof region === "string") { + return getRealRegion(region); + } + const providedRegion = await region(); + return getRealRegion(providedRegion); + }, + useFipsEndpoint: async () => { + const providedRegion = typeof region === "string" ? region : await region(); + if (isFipsRegion(providedRegion)) { + return true; + } + return typeof useFipsEndpoint !== "function" ? Promise.resolve(!!useFipsEndpoint) : useFipsEndpoint(); + } + }); +}, "resolveRegionConfig"); + +// src/regionInfo/getHostnameFromVariants.ts +var getHostnameFromVariants = /* @__PURE__ */ __name((variants = [], { useFipsEndpoint, useDualstackEndpoint }) => variants.find( + ({ tags }) => useFipsEndpoint === tags.includes("fips") && useDualstackEndpoint === tags.includes("dualstack") +)?.hostname, "getHostnameFromVariants"); + +// src/regionInfo/getResolvedHostname.ts +var getResolvedHostname = /* @__PURE__ */ __name((resolvedRegion, { regionHostname, partitionHostname }) => regionHostname ? regionHostname : partitionHostname ? partitionHostname.replace("{region}", resolvedRegion) : void 0, "getResolvedHostname"); + +// src/regionInfo/getResolvedPartition.ts +var getResolvedPartition = /* @__PURE__ */ __name((region, { partitionHash }) => Object.keys(partitionHash || {}).find((key) => partitionHash[key].regions.includes(region)) ?? "aws", "getResolvedPartition"); + +// src/regionInfo/getResolvedSigningRegion.ts +var getResolvedSigningRegion = /* @__PURE__ */ __name((hostname, { signingRegion, regionRegex, useFipsEndpoint }) => { + if (signingRegion) { + return signingRegion; + } else if (useFipsEndpoint) { + const regionRegexJs = regionRegex.replace("\\\\", "\\").replace(/^\^/g, "\\.").replace(/\$$/g, "\\."); + const regionRegexmatchArray = hostname.match(regionRegexJs); + if (regionRegexmatchArray) { + return regionRegexmatchArray[0].slice(1, -1); + } + } +}, "getResolvedSigningRegion"); + +// src/regionInfo/getRegionInfo.ts +var getRegionInfo = /* @__PURE__ */ __name((region, { + useFipsEndpoint = false, + useDualstackEndpoint = false, + signingService, + regionHash, + partitionHash +}) => { + const partition = getResolvedPartition(region, { partitionHash }); + const resolvedRegion = region in regionHash ? region : partitionHash[partition]?.endpoint ?? region; + const hostnameOptions = { useFipsEndpoint, useDualstackEndpoint }; + const regionHostname = getHostnameFromVariants(regionHash[resolvedRegion]?.variants, hostnameOptions); + const partitionHostname = getHostnameFromVariants(partitionHash[partition]?.variants, hostnameOptions); + const hostname = getResolvedHostname(resolvedRegion, { regionHostname, partitionHostname }); + if (hostname === void 0) { + throw new Error(`Endpoint resolution failed for: ${{ resolvedRegion, useFipsEndpoint, useDualstackEndpoint }}`); + } + const signingRegion = getResolvedSigningRegion(hostname, { + signingRegion: regionHash[resolvedRegion]?.signingRegion, + regionRegex: partitionHash[partition].regionRegex, + useFipsEndpoint + }); + return { + partition, + signingService, + hostname, + ...signingRegion && { signingRegion }, + ...regionHash[resolvedRegion]?.signingService && { + signingService: regionHash[resolvedRegion].signingService + } + }; +}, "getRegionInfo"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 90402: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + DefaultIdentityProviderConfig: () => DefaultIdentityProviderConfig, + EXPIRATION_MS: () => EXPIRATION_MS, + HttpApiKeyAuthSigner: () => HttpApiKeyAuthSigner, + HttpBearerAuthSigner: () => HttpBearerAuthSigner, + NoAuthSigner: () => NoAuthSigner, + createIsIdentityExpiredFunction: () => createIsIdentityExpiredFunction, + createPaginator: () => createPaginator, + doesIdentityRequireRefresh: () => doesIdentityRequireRefresh, + getHttpAuthSchemeEndpointRuleSetPlugin: () => getHttpAuthSchemeEndpointRuleSetPlugin, + getHttpAuthSchemePlugin: () => getHttpAuthSchemePlugin, + getHttpSigningPlugin: () => getHttpSigningPlugin, + getSmithyContext: () => getSmithyContext, + httpAuthSchemeEndpointRuleSetMiddlewareOptions: () => httpAuthSchemeEndpointRuleSetMiddlewareOptions, + httpAuthSchemeMiddleware: () => httpAuthSchemeMiddleware, + httpAuthSchemeMiddlewareOptions: () => httpAuthSchemeMiddlewareOptions, + httpSigningMiddleware: () => httpSigningMiddleware, + httpSigningMiddlewareOptions: () => httpSigningMiddlewareOptions, + isIdentityExpired: () => isIdentityExpired, + memoizeIdentityProvider: () => memoizeIdentityProvider, + normalizeProvider: () => normalizeProvider, + requestBuilder: () => import_protocols.requestBuilder, + setFeature: () => setFeature +}); +module.exports = __toCommonJS(src_exports); + +// src/getSmithyContext.ts +var import_types = __nccwpck_require__(90690); +var getSmithyContext = /* @__PURE__ */ __name((context) => context[import_types.SMITHY_CONTEXT_KEY] || (context[import_types.SMITHY_CONTEXT_KEY] = {}), "getSmithyContext"); + +// src/middleware-http-auth-scheme/httpAuthSchemeMiddleware.ts +var import_util_middleware = __nccwpck_require__(76324); + +// src/middleware-http-auth-scheme/resolveAuthOptions.ts +var resolveAuthOptions = /* @__PURE__ */ __name((candidateAuthOptions, authSchemePreference) => { + if (!authSchemePreference || authSchemePreference.length === 0) { + return candidateAuthOptions; + } + const preferredAuthOptions = []; + for (const preferredSchemeName of authSchemePreference) { + for (const candidateAuthOption of candidateAuthOptions) { + const candidateAuthSchemeName = candidateAuthOption.schemeId.split("#")[1]; + if (candidateAuthSchemeName === preferredSchemeName) { + preferredAuthOptions.push(candidateAuthOption); + } + } + } + for (const candidateAuthOption of candidateAuthOptions) { + if (!preferredAuthOptions.find(({ schemeId }) => schemeId === candidateAuthOption.schemeId)) { + preferredAuthOptions.push(candidateAuthOption); + } + } + return preferredAuthOptions; +}, "resolveAuthOptions"); + +// src/middleware-http-auth-scheme/httpAuthSchemeMiddleware.ts +function convertHttpAuthSchemesToMap(httpAuthSchemes) { + const map = /* @__PURE__ */ new Map(); + for (const scheme of httpAuthSchemes) { + map.set(scheme.schemeId, scheme); + } + return map; +} +__name(convertHttpAuthSchemesToMap, "convertHttpAuthSchemesToMap"); +var httpAuthSchemeMiddleware = /* @__PURE__ */ __name((config, mwOptions) => (next, context) => async (args) => { + const options = config.httpAuthSchemeProvider( + await mwOptions.httpAuthSchemeParametersProvider(config, context, args.input) + ); + const authSchemePreference = config.authSchemePreference ? await config.authSchemePreference() : []; + const resolvedOptions = resolveAuthOptions(options, authSchemePreference); + const authSchemes = convertHttpAuthSchemesToMap(config.httpAuthSchemes); + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const failureReasons = []; + for (const option of resolvedOptions) { + const scheme = authSchemes.get(option.schemeId); + if (!scheme) { + failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` was not enabled for this service.`); + continue; + } + const identityProvider = scheme.identityProvider(await mwOptions.identityProviderConfigProvider(config)); + if (!identityProvider) { + failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` did not have an IdentityProvider configured.`); + continue; + } + const { identityProperties = {}, signingProperties = {} } = option.propertiesExtractor?.(config, context) || {}; + option.identityProperties = Object.assign(option.identityProperties || {}, identityProperties); + option.signingProperties = Object.assign(option.signingProperties || {}, signingProperties); + smithyContext.selectedHttpAuthScheme = { + httpAuthOption: option, + identity: await identityProvider(option.identityProperties), + signer: scheme.signer + }; + break; + } + if (!smithyContext.selectedHttpAuthScheme) { + throw new Error(failureReasons.join("\n")); + } + return next(args); +}, "httpAuthSchemeMiddleware"); + +// src/middleware-http-auth-scheme/getHttpAuthSchemeEndpointRuleSetPlugin.ts +var httpAuthSchemeEndpointRuleSetMiddlewareOptions = { + step: "serialize", + tags: ["HTTP_AUTH_SCHEME"], + name: "httpAuthSchemeMiddleware", + override: true, + relation: "before", + toMiddleware: "endpointV2Middleware" +}; +var getHttpAuthSchemeEndpointRuleSetPlugin = /* @__PURE__ */ __name((config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider +}) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo( + httpAuthSchemeMiddleware(config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider + }), + httpAuthSchemeEndpointRuleSetMiddlewareOptions + ); + } +}), "getHttpAuthSchemeEndpointRuleSetPlugin"); + +// src/middleware-http-auth-scheme/getHttpAuthSchemePlugin.ts +var import_middleware_serde = __nccwpck_require__(83255); +var httpAuthSchemeMiddlewareOptions = { + step: "serialize", + tags: ["HTTP_AUTH_SCHEME"], + name: "httpAuthSchemeMiddleware", + override: true, + relation: "before", + toMiddleware: import_middleware_serde.serializerMiddlewareOption.name +}; +var getHttpAuthSchemePlugin = /* @__PURE__ */ __name((config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider +}) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo( + httpAuthSchemeMiddleware(config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider + }), + httpAuthSchemeMiddlewareOptions + ); + } +}), "getHttpAuthSchemePlugin"); + +// src/middleware-http-signing/httpSigningMiddleware.ts +var import_protocol_http = __nccwpck_require__(72356); + +var defaultErrorHandler = /* @__PURE__ */ __name((signingProperties) => (error) => { + throw error; +}, "defaultErrorHandler"); +var defaultSuccessHandler = /* @__PURE__ */ __name((httpResponse, signingProperties) => { +}, "defaultSuccessHandler"); +var httpSigningMiddleware = /* @__PURE__ */ __name((config) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const scheme = smithyContext.selectedHttpAuthScheme; + if (!scheme) { + throw new Error(`No HttpAuthScheme was selected: unable to sign request`); + } + const { + httpAuthOption: { signingProperties = {} }, + identity, + signer + } = scheme; + const output = await next({ + ...args, + request: await signer.sign(args.request, identity, signingProperties) + }).catch((signer.errorHandler || defaultErrorHandler)(signingProperties)); + (signer.successHandler || defaultSuccessHandler)(output.response, signingProperties); + return output; +}, "httpSigningMiddleware"); + +// src/middleware-http-signing/getHttpSigningMiddleware.ts +var httpSigningMiddlewareOptions = { + step: "finalizeRequest", + tags: ["HTTP_SIGNING"], + name: "httpSigningMiddleware", + aliases: ["apiKeyMiddleware", "tokenMiddleware", "awsAuthMiddleware"], + override: true, + relation: "after", + toMiddleware: "retryMiddleware" +}; +var getHttpSigningPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo(httpSigningMiddleware(config), httpSigningMiddlewareOptions); + } +}), "getHttpSigningPlugin"); + +// src/normalizeProvider.ts +var normalizeProvider = /* @__PURE__ */ __name((input) => { + if (typeof input === "function") + return input; + const promisified = Promise.resolve(input); + return () => promisified; +}, "normalizeProvider"); + +// src/pagination/createPaginator.ts +var makePagedClientRequest = /* @__PURE__ */ __name(async (CommandCtor, client, input, withCommand = (_) => _, ...args) => { + let command = new CommandCtor(input); + command = withCommand(command) ?? command; + return await client.send(command, ...args); +}, "makePagedClientRequest"); +function createPaginator(ClientCtor, CommandCtor, inputTokenName, outputTokenName, pageSizeTokenName) { + return /* @__PURE__ */ __name(async function* paginateOperation(config, input, ...additionalArguments) { + const _input = input; + let token = config.startingToken ?? _input[inputTokenName]; + let hasNext = true; + let page; + while (hasNext) { + _input[inputTokenName] = token; + if (pageSizeTokenName) { + _input[pageSizeTokenName] = _input[pageSizeTokenName] ?? config.pageSize; + } + if (config.client instanceof ClientCtor) { + page = await makePagedClientRequest( + CommandCtor, + config.client, + input, + config.withCommand, + ...additionalArguments + ); + } else { + throw new Error(`Invalid client, expected instance of ${ClientCtor.name}`); + } + yield page; + const prevToken = token; + token = get(page, outputTokenName); + hasNext = !!(token && (!config.stopOnSameToken || token !== prevToken)); + } + return void 0; + }, "paginateOperation"); +} +__name(createPaginator, "createPaginator"); +var get = /* @__PURE__ */ __name((fromObject, path) => { + let cursor = fromObject; + const pathComponents = path.split("."); + for (const step of pathComponents) { + if (!cursor || typeof cursor !== "object") { + return void 0; + } + cursor = cursor[step]; + } + return cursor; +}, "get"); + +// src/protocols/requestBuilder.ts +var import_protocols = __nccwpck_require__(93422); + +// src/setFeature.ts +function setFeature(context, feature, value) { + if (!context.__smithy_context) { + context.__smithy_context = { + features: {} + }; + } else if (!context.__smithy_context.features) { + context.__smithy_context.features = {}; + } + context.__smithy_context.features[feature] = value; +} +__name(setFeature, "setFeature"); + +// src/util-identity-and-auth/DefaultIdentityProviderConfig.ts +var DefaultIdentityProviderConfig = class { + /** + * Creates an IdentityProviderConfig with a record of scheme IDs to identity providers. + * + * @param config scheme IDs and identity providers to configure + */ + constructor(config) { + this.authSchemes = /* @__PURE__ */ new Map(); + for (const [key, value] of Object.entries(config)) { + if (value !== void 0) { + this.authSchemes.set(key, value); + } + } + } + static { + __name(this, "DefaultIdentityProviderConfig"); + } + getIdentityProvider(schemeId) { + return this.authSchemes.get(schemeId); + } +}; + +// src/util-identity-and-auth/httpAuthSchemes/httpApiKeyAuth.ts + + +var HttpApiKeyAuthSigner = class { + static { + __name(this, "HttpApiKeyAuthSigner"); + } + async sign(httpRequest, identity, signingProperties) { + if (!signingProperties) { + throw new Error( + "request could not be signed with `apiKey` since the `name` and `in` signer properties are missing" + ); + } + if (!signingProperties.name) { + throw new Error("request could not be signed with `apiKey` since the `name` signer property is missing"); + } + if (!signingProperties.in) { + throw new Error("request could not be signed with `apiKey` since the `in` signer property is missing"); + } + if (!identity.apiKey) { + throw new Error("request could not be signed with `apiKey` since the `apiKey` is not defined"); + } + const clonedRequest = import_protocol_http.HttpRequest.clone(httpRequest); + if (signingProperties.in === import_types.HttpApiKeyAuthLocation.QUERY) { + clonedRequest.query[signingProperties.name] = identity.apiKey; + } else if (signingProperties.in === import_types.HttpApiKeyAuthLocation.HEADER) { + clonedRequest.headers[signingProperties.name] = signingProperties.scheme ? `${signingProperties.scheme} ${identity.apiKey}` : identity.apiKey; + } else { + throw new Error( + "request can only be signed with `apiKey` locations `query` or `header`, but found: `" + signingProperties.in + "`" + ); + } + return clonedRequest; + } +}; + +// src/util-identity-and-auth/httpAuthSchemes/httpBearerAuth.ts + +var HttpBearerAuthSigner = class { + static { + __name(this, "HttpBearerAuthSigner"); + } + async sign(httpRequest, identity, signingProperties) { + const clonedRequest = import_protocol_http.HttpRequest.clone(httpRequest); + if (!identity.token) { + throw new Error("request could not be signed with `token` since the `token` is not defined"); + } + clonedRequest.headers["Authorization"] = `Bearer ${identity.token}`; + return clonedRequest; + } +}; + +// src/util-identity-and-auth/httpAuthSchemes/noAuth.ts +var NoAuthSigner = class { + static { + __name(this, "NoAuthSigner"); + } + async sign(httpRequest, identity, signingProperties) { + return httpRequest; + } +}; + +// src/util-identity-and-auth/memoizeIdentityProvider.ts +var createIsIdentityExpiredFunction = /* @__PURE__ */ __name((expirationMs) => (identity) => doesIdentityRequireRefresh(identity) && identity.expiration.getTime() - Date.now() < expirationMs, "createIsIdentityExpiredFunction"); +var EXPIRATION_MS = 3e5; +var isIdentityExpired = createIsIdentityExpiredFunction(EXPIRATION_MS); +var doesIdentityRequireRefresh = /* @__PURE__ */ __name((identity) => identity.expiration !== void 0, "doesIdentityRequireRefresh"); +var memoizeIdentityProvider = /* @__PURE__ */ __name((provider, isExpired, requiresRefresh) => { + if (provider === void 0) { + return void 0; + } + const normalizedProvider = typeof provider !== "function" ? async () => Promise.resolve(provider) : provider; + let resolved; + let pending; + let hasResult; + let isConstant = false; + const coalesceProvider = /* @__PURE__ */ __name(async (options) => { + if (!pending) { + pending = normalizedProvider(options); + } + try { + resolved = await pending; + hasResult = true; + isConstant = false; + } finally { + pending = void 0; + } + return resolved; + }, "coalesceProvider"); + if (isExpired === void 0) { + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(options); + } + return resolved; + }; + } + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(options); + } + if (isConstant) { + return resolved; + } + if (!requiresRefresh(resolved)) { + isConstant = true; + return resolved; + } + if (isExpired(resolved)) { + await coalesceProvider(options); + return resolved; + } + return resolved; + }; +}, "memoizeIdentityProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 93422: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/protocols/index.ts +var protocols_exports = {}; +__export(protocols_exports, { + FromStringShapeDeserializer: () => FromStringShapeDeserializer, + HttpBindingProtocol: () => HttpBindingProtocol, + HttpInterceptingShapeDeserializer: () => HttpInterceptingShapeDeserializer, + HttpInterceptingShapeSerializer: () => HttpInterceptingShapeSerializer, + RequestBuilder: () => RequestBuilder, + RpcProtocol: () => RpcProtocol, + ToStringShapeSerializer: () => ToStringShapeSerializer, + collectBody: () => collectBody, + determineTimestampFormat: () => determineTimestampFormat, + extendedEncodeURIComponent: () => extendedEncodeURIComponent, + requestBuilder: () => requestBuilder, + resolvedPath: () => resolvedPath +}); +module.exports = __toCommonJS(protocols_exports); + +// src/submodules/protocols/collect-stream-body.ts +var import_util_stream = __nccwpck_require__(4252); +var collectBody = async (streamBody = new Uint8Array(), context) => { + if (streamBody instanceof Uint8Array) { + return import_util_stream.Uint8ArrayBlobAdapter.mutate(streamBody); + } + if (!streamBody) { + return import_util_stream.Uint8ArrayBlobAdapter.mutate(new Uint8Array()); + } + const fromContext = context.streamCollector(streamBody); + return import_util_stream.Uint8ArrayBlobAdapter.mutate(await fromContext); +}; + +// src/submodules/protocols/extended-encode-uri-component.ts +function extendedEncodeURIComponent(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { + return "%" + c.charCodeAt(0).toString(16).toUpperCase(); + }); +} + +// src/submodules/protocols/HttpBindingProtocol.ts +var import_schema2 = __nccwpck_require__(26890); +var import_protocol_http2 = __nccwpck_require__(72356); + +// src/submodules/protocols/HttpProtocol.ts +var import_schema = __nccwpck_require__(26890); +var import_serde = __nccwpck_require__(92430); +var import_protocol_http = __nccwpck_require__(72356); +var import_util_stream2 = __nccwpck_require__(4252); +var HttpProtocol = class { + constructor(options) { + this.options = options; + } + getRequestType() { + return import_protocol_http.HttpRequest; + } + getResponseType() { + return import_protocol_http.HttpResponse; + } + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + this.serializer.setSerdeContext(serdeContext); + this.deserializer.setSerdeContext(serdeContext); + if (this.getPayloadCodec()) { + this.getPayloadCodec().setSerdeContext(serdeContext); + } + } + updateServiceEndpoint(request, endpoint) { + if ("url" in endpoint) { + request.protocol = endpoint.url.protocol; + request.hostname = endpoint.url.hostname; + request.port = endpoint.url.port ? Number(endpoint.url.port) : void 0; + request.path = endpoint.url.pathname; + request.fragment = endpoint.url.hash || void 0; + request.username = endpoint.url.username || void 0; + request.password = endpoint.url.password || void 0; + for (const [k, v] of endpoint.url.searchParams.entries()) { + if (!request.query) { + request.query = {}; + } + request.query[k] = v; + } + return request; + } else { + request.protocol = endpoint.protocol; + request.hostname = endpoint.hostname; + request.port = endpoint.port ? Number(endpoint.port) : void 0; + request.path = endpoint.path; + request.query = { + ...endpoint.query + }; + return request; + } + } + setHostPrefix(request, operationSchema, input) { + const operationNs = import_schema.NormalizedSchema.of(operationSchema); + const inputNs = import_schema.NormalizedSchema.of(operationSchema.input); + if (operationNs.getMergedTraits().endpoint) { + let hostPrefix = operationNs.getMergedTraits().endpoint?.[0]; + if (typeof hostPrefix === "string") { + const hostLabelInputs = [...inputNs.structIterator()].filter( + ([, member]) => member.getMergedTraits().hostLabel + ); + for (const [name] of hostLabelInputs) { + const replacement = input[name]; + if (typeof replacement !== "string") { + throw new Error(`@smithy/core/schema - ${name} in input must be a string as hostLabel.`); + } + hostPrefix = hostPrefix.replace(`{${name}}`, replacement); + } + request.hostname = hostPrefix + request.hostname; + } + } + } + deserializeMetadata(output) { + return { + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] + }; + } + async deserializeHttpMessage(schema, context, response, arg4, arg5) { + let dataObject; + if (arg4 instanceof Set) { + dataObject = arg5; + } else { + dataObject = arg4; + } + const deserializer = this.deserializer; + const ns = import_schema.NormalizedSchema.of(schema); + const nonHttpBindingMembers = []; + for (const [memberName, memberSchema] of ns.structIterator()) { + const memberTraits = memberSchema.getMemberTraits(); + if (memberTraits.httpPayload) { + const isStreaming = memberSchema.isStreaming(); + if (isStreaming) { + const isEventStream = memberSchema.isStructSchema(); + if (isEventStream) { + const context2 = this.serdeContext; + if (!context2.eventStreamMarshaller) { + throw new Error("@smithy/core - HttpProtocol: eventStreamMarshaller missing in serdeContext."); + } + const memberSchemas = memberSchema.getMemberSchemas(); + dataObject[memberName] = context2.eventStreamMarshaller.deserialize(response.body, async (event) => { + const unionMember = Object.keys(event).find((key) => { + return key !== "__type"; + }) ?? ""; + if (unionMember in memberSchemas) { + const eventStreamSchema = memberSchemas[unionMember]; + return { + [unionMember]: await deserializer.read(eventStreamSchema, event[unionMember].body) + }; + } else { + return { + $unknown: event + }; + } + }); + } else { + dataObject[memberName] = (0, import_util_stream2.sdkStreamMixin)(response.body); + } + } else if (response.body) { + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + dataObject[memberName] = await deserializer.read(memberSchema, bytes); + } + } + } else if (memberTraits.httpHeader) { + const key = String(memberTraits.httpHeader).toLowerCase(); + const value = response.headers[key]; + if (null != value) { + if (memberSchema.isListSchema()) { + const headerListValueSchema = memberSchema.getValueSchema(); + let sections; + if (headerListValueSchema.isTimestampSchema() && headerListValueSchema.getSchema() === import_schema.SCHEMA.TIMESTAMP_DEFAULT) { + sections = (0, import_serde.splitEvery)(value, ",", 2); + } else { + sections = (0, import_serde.splitHeader)(value); + } + const list = []; + for (const section of sections) { + list.push(await deserializer.read([headerListValueSchema, { httpHeader: key }], section.trim())); + } + dataObject[memberName] = list; + } else { + dataObject[memberName] = await deserializer.read(memberSchema, value); + } + } + } else if (memberTraits.httpPrefixHeaders !== void 0) { + dataObject[memberName] = {}; + for (const [header, value] of Object.entries(response.headers)) { + if (header.startsWith(memberTraits.httpPrefixHeaders)) { + dataObject[memberName][header.slice(memberTraits.httpPrefixHeaders.length)] = await deserializer.read( + [memberSchema.getValueSchema(), { httpHeader: header }], + value + ); + } + } + } else if (memberTraits.httpResponseCode) { + dataObject[memberName] = response.statusCode; + } else { + nonHttpBindingMembers.push(memberName); + } + } + return nonHttpBindingMembers; + } +}; + +// src/submodules/protocols/HttpBindingProtocol.ts +var HttpBindingProtocol = class extends HttpProtocol { + async serializeRequest(operationSchema, _input, context) { + const input = { + ..._input ?? {} + }; + const serializer = this.serializer; + const query = {}; + const headers = {}; + const endpoint = await context.endpoint(); + const ns = import_schema2.NormalizedSchema.of(operationSchema?.input); + const schema = ns.getSchema(); + let hasNonHttpBindingMember = false; + let payload; + const request = new import_protocol_http2.HttpRequest({ + protocol: "", + hostname: "", + port: void 0, + path: "", + fragment: void 0, + query, + headers, + body: void 0 + }); + if (endpoint) { + this.updateServiceEndpoint(request, endpoint); + this.setHostPrefix(request, operationSchema, input); + const opTraits = import_schema2.NormalizedSchema.translateTraits(operationSchema.traits); + if (opTraits.http) { + request.method = opTraits.http[0]; + const [path, search] = opTraits.http[1].split("?"); + if (request.path == "/") { + request.path = path; + } else { + request.path += path; + } + const traitSearchParams = new URLSearchParams(search ?? ""); + Object.assign(query, Object.fromEntries(traitSearchParams)); + } + } + for (const [memberName, memberNs] of ns.structIterator()) { + const memberTraits = memberNs.getMergedTraits() ?? {}; + const inputMemberValue = input[memberName]; + if (inputMemberValue == null) { + continue; + } + if (memberTraits.httpPayload) { + const isStreaming = memberNs.isStreaming(); + if (isStreaming) { + const isEventStream = memberNs.isStructSchema(); + if (isEventStream) { + throw new Error("serialization of event streams is not yet implemented"); + } else { + payload = inputMemberValue; + } + } else { + serializer.write(memberNs, inputMemberValue); + payload = serializer.flush(); + } + delete input[memberName]; + } else if (memberTraits.httpLabel) { + serializer.write(memberNs, inputMemberValue); + const replacement = serializer.flush(); + if (request.path.includes(`{${memberName}+}`)) { + request.path = request.path.replace( + `{${memberName}+}`, + replacement.split("/").map(extendedEncodeURIComponent).join("/") + ); + } else if (request.path.includes(`{${memberName}}`)) { + request.path = request.path.replace(`{${memberName}}`, extendedEncodeURIComponent(replacement)); + } + delete input[memberName]; + } else if (memberTraits.httpHeader) { + serializer.write(memberNs, inputMemberValue); + headers[memberTraits.httpHeader.toLowerCase()] = String(serializer.flush()); + delete input[memberName]; + } else if (typeof memberTraits.httpPrefixHeaders === "string") { + for (const [key, val] of Object.entries(inputMemberValue)) { + const amalgam = memberTraits.httpPrefixHeaders + key; + serializer.write([memberNs.getValueSchema(), { httpHeader: amalgam }], val); + headers[amalgam.toLowerCase()] = serializer.flush(); + } + delete input[memberName]; + } else if (memberTraits.httpQuery || memberTraits.httpQueryParams) { + this.serializeQuery(memberNs, inputMemberValue, query); + delete input[memberName]; + } else { + hasNonHttpBindingMember = true; + } + } + if (hasNonHttpBindingMember && input) { + serializer.write(schema, input); + payload = serializer.flush(); + } + request.headers = headers; + request.query = query; + request.body = payload; + return request; + } + serializeQuery(ns, data, query) { + const serializer = this.serializer; + const traits = ns.getMergedTraits(); + if (traits.httpQueryParams) { + for (const [key, val] of Object.entries(data)) { + if (!(key in query)) { + this.serializeQuery( + import_schema2.NormalizedSchema.of([ + ns.getValueSchema(), + { + // We pass on the traits to the sub-schema + // because we are still in the process of serializing the map itself. + ...traits, + httpQuery: key, + httpQueryParams: void 0 + } + ]), + val, + query + ); + } + } + return; + } + if (ns.isListSchema()) { + const sparse = !!ns.getMergedTraits().sparse; + const buffer = []; + for (const item of data) { + serializer.write([ns.getValueSchema(), traits], item); + const serializable = serializer.flush(); + if (sparse || serializable !== void 0) { + buffer.push(serializable); + } + } + query[traits.httpQuery] = buffer; + } else { + serializer.write([ns, traits], data); + query[traits.httpQuery] = serializer.flush(); + } + } + async deserializeResponse(operationSchema, context, response) { + const deserializer = this.deserializer; + const ns = import_schema2.NormalizedSchema.of(operationSchema.output); + const dataObject = {}; + if (response.statusCode >= 300) { + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(import_schema2.SCHEMA.DOCUMENT, bytes)); + } + await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response)); + throw new Error("@smithy/core/protocols - HTTP Protocol error handler failed to throw."); + } + for (const header in response.headers) { + const value = response.headers[header]; + delete response.headers[header]; + response.headers[header.toLowerCase()] = value; + } + const nonHttpBindingMembers = await this.deserializeHttpMessage(ns, context, response, dataObject); + if (nonHttpBindingMembers.length) { + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + const dataFromBody = await deserializer.read(ns, bytes); + for (const member of nonHttpBindingMembers) { + dataObject[member] = dataFromBody[member]; + } + } + } + const output = { + $metadata: this.deserializeMetadata(response), + ...dataObject + }; + return output; + } +}; + +// src/submodules/protocols/RpcProtocol.ts +var import_schema3 = __nccwpck_require__(26890); +var import_protocol_http3 = __nccwpck_require__(72356); +var RpcProtocol = class extends HttpProtocol { + async serializeRequest(operationSchema, input, context) { + const serializer = this.serializer; + const query = {}; + const headers = {}; + const endpoint = await context.endpoint(); + const ns = import_schema3.NormalizedSchema.of(operationSchema?.input); + const schema = ns.getSchema(); + let payload; + const request = new import_protocol_http3.HttpRequest({ + protocol: "", + hostname: "", + port: void 0, + path: "/", + fragment: void 0, + query, + headers, + body: void 0 + }); + if (endpoint) { + this.updateServiceEndpoint(request, endpoint); + this.setHostPrefix(request, operationSchema, input); + } + const _input = { + ...input + }; + if (input) { + serializer.write(schema, _input); + payload = serializer.flush(); + } + request.headers = headers; + request.query = query; + request.body = payload; + request.method = "POST"; + return request; + } + async deserializeResponse(operationSchema, context, response) { + const deserializer = this.deserializer; + const ns = import_schema3.NormalizedSchema.of(operationSchema.output); + const dataObject = {}; + if (response.statusCode >= 300) { + const bytes2 = await collectBody(response.body, context); + if (bytes2.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(import_schema3.SCHEMA.DOCUMENT, bytes2)); + } + await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response)); + throw new Error("@smithy/core/protocols - RPC Protocol error handler failed to throw."); + } + for (const header in response.headers) { + const value = response.headers[header]; + delete response.headers[header]; + response.headers[header.toLowerCase()] = value; + } + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(ns, bytes)); + } + const output = { + $metadata: this.deserializeMetadata(response), + ...dataObject + }; + return output; + } +}; + +// src/submodules/protocols/requestBuilder.ts +var import_protocol_http4 = __nccwpck_require__(72356); + +// src/submodules/protocols/resolve-path.ts +var resolvedPath = (resolvedPath2, input, memberName, labelValueProvider, uriLabel, isGreedyLabel) => { + if (input != null && input[memberName] !== void 0) { + const labelValue = labelValueProvider(); + if (labelValue.length <= 0) { + throw new Error("Empty value provided for input HTTP label: " + memberName + "."); + } + resolvedPath2 = resolvedPath2.replace( + uriLabel, + isGreedyLabel ? labelValue.split("/").map((segment) => extendedEncodeURIComponent(segment)).join("/") : extendedEncodeURIComponent(labelValue) + ); + } else { + throw new Error("No value provided for input HTTP label: " + memberName + "."); + } + return resolvedPath2; +}; + +// src/submodules/protocols/requestBuilder.ts +function requestBuilder(input, context) { + return new RequestBuilder(input, context); +} +var RequestBuilder = class { + constructor(input, context) { + this.input = input; + this.context = context; + this.query = {}; + this.method = ""; + this.headers = {}; + this.path = ""; + this.body = null; + this.hostname = ""; + this.resolvePathStack = []; + } + async build() { + const { hostname, protocol = "https", port, path: basePath } = await this.context.endpoint(); + this.path = basePath; + for (const resolvePath of this.resolvePathStack) { + resolvePath(this.path); + } + return new import_protocol_http4.HttpRequest({ + protocol, + hostname: this.hostname || hostname, + port, + method: this.method, + path: this.path, + query: this.query, + body: this.body, + headers: this.headers + }); + } + /** + * Brevity setter for "hostname". + */ + hn(hostname) { + this.hostname = hostname; + return this; + } + /** + * Brevity initial builder for "basepath". + */ + bp(uriLabel) { + this.resolvePathStack.push((basePath) => { + this.path = `${basePath?.endsWith("/") ? basePath.slice(0, -1) : basePath || ""}` + uriLabel; + }); + return this; + } + /** + * Brevity incremental builder for "path". + */ + p(memberName, labelValueProvider, uriLabel, isGreedyLabel) { + this.resolvePathStack.push((path) => { + this.path = resolvedPath(path, this.input, memberName, labelValueProvider, uriLabel, isGreedyLabel); + }); + return this; + } + /** + * Brevity setter for "headers". + */ + h(headers) { + this.headers = headers; + return this; + } + /** + * Brevity setter for "query". + */ + q(query) { + this.query = query; + return this; + } + /** + * Brevity setter for "body". + */ + b(body) { + this.body = body; + return this; + } + /** + * Brevity setter for "method". + */ + m(method) { + this.method = method; + return this; + } +}; + +// src/submodules/protocols/serde/FromStringShapeDeserializer.ts +var import_schema5 = __nccwpck_require__(26890); +var import_serde2 = __nccwpck_require__(92430); +var import_util_base64 = __nccwpck_require__(68385); +var import_util_utf8 = __nccwpck_require__(71577); + +// src/submodules/protocols/serde/determineTimestampFormat.ts +var import_schema4 = __nccwpck_require__(26890); +function determineTimestampFormat(ns, settings) { + if (settings.timestampFormat.useTrait) { + if (ns.isTimestampSchema() && (ns.getSchema() === import_schema4.SCHEMA.TIMESTAMP_DATE_TIME || ns.getSchema() === import_schema4.SCHEMA.TIMESTAMP_HTTP_DATE || ns.getSchema() === import_schema4.SCHEMA.TIMESTAMP_EPOCH_SECONDS)) { + return ns.getSchema(); + } + } + const { httpLabel, httpPrefixHeaders, httpHeader, httpQuery } = ns.getMergedTraits(); + const bindingFormat = settings.httpBindings ? typeof httpPrefixHeaders === "string" || Boolean(httpHeader) ? import_schema4.SCHEMA.TIMESTAMP_HTTP_DATE : Boolean(httpQuery) || Boolean(httpLabel) ? import_schema4.SCHEMA.TIMESTAMP_DATE_TIME : void 0 : void 0; + return bindingFormat ?? settings.timestampFormat.default; +} + +// src/submodules/protocols/serde/FromStringShapeDeserializer.ts +var FromStringShapeDeserializer = class { + constructor(settings) { + this.settings = settings; + } + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + } + read(_schema, data) { + const ns = import_schema5.NormalizedSchema.of(_schema); + if (ns.isListSchema()) { + return (0, import_serde2.splitHeader)(data).map((item) => this.read(ns.getValueSchema(), item)); + } + if (ns.isBlobSchema()) { + return (this.serdeContext?.base64Decoder ?? import_util_base64.fromBase64)(data); + } + if (ns.isTimestampSchema()) { + const format = determineTimestampFormat(ns, this.settings); + switch (format) { + case import_schema5.SCHEMA.TIMESTAMP_DATE_TIME: + return (0, import_serde2.parseRfc3339DateTimeWithOffset)(data); + case import_schema5.SCHEMA.TIMESTAMP_HTTP_DATE: + return (0, import_serde2.parseRfc7231DateTime)(data); + case import_schema5.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + return (0, import_serde2.parseEpochTimestamp)(data); + default: + console.warn("Missing timestamp format, parsing value with Date constructor:", data); + return new Date(data); + } + } + if (ns.isStringSchema()) { + const mediaType = ns.getMergedTraits().mediaType; + let intermediateValue = data; + if (mediaType) { + if (ns.getMergedTraits().httpHeader) { + intermediateValue = this.base64ToUtf8(intermediateValue); + } + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + intermediateValue = import_serde2.LazyJsonString.from(intermediateValue); + } + return intermediateValue; + } + } + switch (true) { + case ns.isNumericSchema(): + return Number(data); + case ns.isBigIntegerSchema(): + return BigInt(data); + case ns.isBigDecimalSchema(): + return new import_serde2.NumericValue(data, "bigDecimal"); + case ns.isBooleanSchema(): + return String(data).toLowerCase() === "true"; + } + return data; + } + base64ToUtf8(base64String) { + return (this.serdeContext?.utf8Encoder ?? import_util_utf8.toUtf8)((this.serdeContext?.base64Decoder ?? import_util_base64.fromBase64)(base64String)); + } +}; + +// src/submodules/protocols/serde/HttpInterceptingShapeDeserializer.ts +var import_schema6 = __nccwpck_require__(26890); +var import_util_utf82 = __nccwpck_require__(71577); +var HttpInterceptingShapeDeserializer = class { + constructor(codecDeserializer, codecSettings) { + this.codecDeserializer = codecDeserializer; + this.stringDeserializer = new FromStringShapeDeserializer(codecSettings); + } + setSerdeContext(serdeContext) { + this.stringDeserializer.setSerdeContext(serdeContext); + this.codecDeserializer.setSerdeContext(serdeContext); + this.serdeContext = serdeContext; + } + read(schema, data) { + const ns = import_schema6.NormalizedSchema.of(schema); + const traits = ns.getMergedTraits(); + const toString = this.serdeContext?.utf8Encoder ?? import_util_utf82.toUtf8; + if (traits.httpHeader || traits.httpResponseCode) { + return this.stringDeserializer.read(ns, toString(data)); + } + if (traits.httpPayload) { + if (ns.isBlobSchema()) { + const toBytes = this.serdeContext?.utf8Decoder ?? import_util_utf82.fromUtf8; + if (typeof data === "string") { + return toBytes(data); + } + return data; + } else if (ns.isStringSchema()) { + if ("byteLength" in data) { + return toString(data); + } + return data; + } + } + return this.codecDeserializer.read(ns, data); + } +}; + +// src/submodules/protocols/serde/HttpInterceptingShapeSerializer.ts +var import_schema8 = __nccwpck_require__(26890); + +// src/submodules/protocols/serde/ToStringShapeSerializer.ts +var import_schema7 = __nccwpck_require__(26890); +var import_serde3 = __nccwpck_require__(92430); +var import_util_base642 = __nccwpck_require__(68385); +var ToStringShapeSerializer = class { + constructor(settings) { + this.settings = settings; + this.stringBuffer = ""; + this.serdeContext = void 0; + } + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + } + write(schema, value) { + const ns = import_schema7.NormalizedSchema.of(schema); + switch (typeof value) { + case "object": + if (value === null) { + this.stringBuffer = "null"; + return; + } + if (ns.isTimestampSchema()) { + if (!(value instanceof Date)) { + throw new Error( + `@smithy/core/protocols - received non-Date value ${value} when schema expected Date in ${ns.getName(true)}` + ); + } + const format = determineTimestampFormat(ns, this.settings); + switch (format) { + case import_schema7.SCHEMA.TIMESTAMP_DATE_TIME: + this.stringBuffer = value.toISOString().replace(".000Z", "Z"); + break; + case import_schema7.SCHEMA.TIMESTAMP_HTTP_DATE: + this.stringBuffer = (0, import_serde3.dateToUtcString)(value); + break; + case import_schema7.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + this.stringBuffer = String(value.getTime() / 1e3); + break; + default: + console.warn("Missing timestamp format, using epoch seconds", value); + this.stringBuffer = String(value.getTime() / 1e3); + } + return; + } + if (ns.isBlobSchema() && "byteLength" in value) { + this.stringBuffer = (this.serdeContext?.base64Encoder ?? import_util_base642.toBase64)(value); + return; + } + if (ns.isListSchema() && Array.isArray(value)) { + let buffer = ""; + for (const item of value) { + this.write([ns.getValueSchema(), ns.getMergedTraits()], item); + const headerItem = this.flush(); + const serialized = ns.getValueSchema().isTimestampSchema() ? headerItem : (0, import_serde3.quoteHeader)(headerItem); + if (buffer !== "") { + buffer += ", "; + } + buffer += serialized; + } + this.stringBuffer = buffer; + return; + } + this.stringBuffer = JSON.stringify(value, null, 2); + break; + case "string": + const mediaType = ns.getMergedTraits().mediaType; + let intermediateValue = value; + if (mediaType) { + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + intermediateValue = import_serde3.LazyJsonString.from(intermediateValue); + } + if (ns.getMergedTraits().httpHeader) { + this.stringBuffer = (this.serdeContext?.base64Encoder ?? import_util_base642.toBase64)(intermediateValue.toString()); + return; + } + } + this.stringBuffer = value; + break; + default: + this.stringBuffer = String(value); + } + } + flush() { + const buffer = this.stringBuffer; + this.stringBuffer = ""; + return buffer; + } +}; + +// src/submodules/protocols/serde/HttpInterceptingShapeSerializer.ts +var HttpInterceptingShapeSerializer = class { + constructor(codecSerializer, codecSettings, stringSerializer = new ToStringShapeSerializer(codecSettings)) { + this.codecSerializer = codecSerializer; + this.stringSerializer = stringSerializer; + } + setSerdeContext(serdeContext) { + this.codecSerializer.setSerdeContext(serdeContext); + this.stringSerializer.setSerdeContext(serdeContext); + } + write(schema, value) { + const ns = import_schema8.NormalizedSchema.of(schema); + const traits = ns.getMergedTraits(); + if (traits.httpHeader || traits.httpLabel || traits.httpQuery) { + this.stringSerializer.write(ns, value); + this.buffer = this.stringSerializer.flush(); + return; + } + return this.codecSerializer.write(ns, value); + } + flush() { + if (this.buffer !== void 0) { + const buffer = this.buffer; + this.buffer = void 0; + return buffer; + } + return this.codecSerializer.flush(); + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 26890: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/schema/index.ts +var schema_exports = {}; +__export(schema_exports, { + ErrorSchema: () => ErrorSchema, + ListSchema: () => ListSchema, + MapSchema: () => MapSchema, + NormalizedSchema: () => NormalizedSchema, + OperationSchema: () => OperationSchema, + SCHEMA: () => SCHEMA, + Schema: () => Schema, + SimpleSchema: () => SimpleSchema, + StructureSchema: () => StructureSchema, + TypeRegistry: () => TypeRegistry, + deref: () => deref, + deserializerMiddlewareOption: () => deserializerMiddlewareOption, + error: () => error, + getSchemaSerdePlugin: () => getSchemaSerdePlugin, + list: () => list, + map: () => map, + op: () => op, + serializerMiddlewareOption: () => serializerMiddlewareOption, + sim: () => sim, + struct: () => struct +}); +module.exports = __toCommonJS(schema_exports); + +// src/submodules/schema/deref.ts +var deref = (schemaRef) => { + if (typeof schemaRef === "function") { + return schemaRef(); + } + return schemaRef; +}; + +// src/submodules/schema/middleware/schemaDeserializationMiddleware.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_util_middleware = __nccwpck_require__(76324); +var schemaDeserializationMiddleware = (config) => (next, context) => async (args) => { + const { response } = await next(args); + const { operationSchema } = (0, import_util_middleware.getSmithyContext)(context); + try { + const parsed = await config.protocol.deserializeResponse( + operationSchema, + { + ...config, + ...context + }, + response + ); + return { + response, + output: parsed + }; + } catch (error2) { + Object.defineProperty(error2, "$response", { + value: response + }); + if (!("$metadata" in error2)) { + const hint = `Deserialization error: to see the raw response, inspect the hidden field {error}.$response on this object.`; + try { + error2.message += "\n " + hint; + } catch (e) { + if (!context.logger || context.logger?.constructor?.name === "NoOpLogger") { + console.warn(hint); + } else { + context.logger?.warn?.(hint); + } + } + if (typeof error2.$responseBodyText !== "undefined") { + if (error2.$response) { + error2.$response.body = error2.$responseBodyText; + } + } + try { + if (import_protocol_http.HttpResponse.isInstance(response)) { + const { headers = {} } = response; + const headerEntries = Object.entries(headers); + error2.$metadata = { + httpStatusCode: response.statusCode, + requestId: findHeader(/^x-[\w-]+-request-?id$/, headerEntries), + extendedRequestId: findHeader(/^x-[\w-]+-id-2$/, headerEntries), + cfId: findHeader(/^x-[\w-]+-cf-id$/, headerEntries) + }; + } + } catch (e) { + } + } + throw error2; + } +}; +var findHeader = (pattern, headers) => { + return (headers.find(([k]) => { + return k.match(pattern); + }) || [void 0, void 0])[1]; +}; + +// src/submodules/schema/middleware/schemaSerializationMiddleware.ts +var import_util_middleware2 = __nccwpck_require__(76324); +var schemaSerializationMiddleware = (config) => (next, context) => async (args) => { + const { operationSchema } = (0, import_util_middleware2.getSmithyContext)(context); + const endpoint = context.endpointV2?.url && config.urlParser ? async () => config.urlParser(context.endpointV2.url) : config.endpoint; + const request = await config.protocol.serializeRequest(operationSchema, args.input, { + ...config, + ...context, + endpoint + }); + return next({ + ...args, + request + }); +}; + +// src/submodules/schema/middleware/getSchemaSerdePlugin.ts +var deserializerMiddlewareOption = { + name: "deserializerMiddleware", + step: "deserialize", + tags: ["DESERIALIZER"], + override: true +}; +var serializerMiddlewareOption = { + name: "serializerMiddleware", + step: "serialize", + tags: ["SERIALIZER"], + override: true +}; +function getSchemaSerdePlugin(config) { + return { + applyToStack: (commandStack) => { + commandStack.add(schemaSerializationMiddleware(config), serializerMiddlewareOption); + commandStack.add(schemaDeserializationMiddleware(config), deserializerMiddlewareOption); + config.protocol.setSerdeContext(config); + } + }; +} + +// src/submodules/schema/TypeRegistry.ts +var TypeRegistry = class _TypeRegistry { + constructor(namespace, schemas = /* @__PURE__ */ new Map()) { + this.namespace = namespace; + this.schemas = schemas; + } + static { + this.registries = /* @__PURE__ */ new Map(); + } + /** + * @param namespace - specifier. + * @returns the schema for that namespace, creating it if necessary. + */ + static for(namespace) { + if (!_TypeRegistry.registries.has(namespace)) { + _TypeRegistry.registries.set(namespace, new _TypeRegistry(namespace)); + } + return _TypeRegistry.registries.get(namespace); + } + /** + * Adds the given schema to a type registry with the same namespace. + * + * @param shapeId - to be registered. + * @param schema - to be registered. + */ + register(shapeId, schema) { + const qualifiedName = this.normalizeShapeId(shapeId); + const registry = _TypeRegistry.for(this.getNamespace(shapeId)); + registry.schemas.set(qualifiedName, schema); + } + /** + * @param shapeId - query. + * @returns the schema. + */ + getSchema(shapeId) { + const id = this.normalizeShapeId(shapeId); + if (!this.schemas.has(id)) { + throw new Error(`@smithy/core/schema - schema not found for ${id}`); + } + return this.schemas.get(id); + } + /** + * The smithy-typescript code generator generates a synthetic (i.e. unmodeled) base exception, + * because generated SDKs before the introduction of schemas have the notion of a ServiceBaseException, which + * is unique per service/model. + * + * This is generated under a unique prefix that is combined with the service namespace, and this + * method is used to retrieve it. + * + * The base exception synthetic schema is used when an error is returned by a service, but we cannot + * determine what existing schema to use to deserialize it. + * + * @returns the synthetic base exception of the service namespace associated with this registry instance. + */ + getBaseException() { + for (const [id, schema] of this.schemas.entries()) { + if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) { + return schema; + } + } + return void 0; + } + /** + * @param predicate - criterion. + * @returns a schema in this registry matching the predicate. + */ + find(predicate) { + return [...this.schemas.values()].find(predicate); + } + /** + * Unloads the current TypeRegistry. + */ + destroy() { + _TypeRegistry.registries.delete(this.namespace); + this.schemas.clear(); + } + normalizeShapeId(shapeId) { + if (shapeId.includes("#")) { + return shapeId; + } + return this.namespace + "#" + shapeId; + } + getNamespace(shapeId) { + return this.normalizeShapeId(shapeId).split("#")[0]; + } +}; + +// src/submodules/schema/schemas/Schema.ts +var Schema = class { + constructor(name, traits) { + this.name = name; + this.traits = traits; + } +}; + +// src/submodules/schema/schemas/ListSchema.ts +var ListSchema = class _ListSchema extends Schema { + constructor(name, traits, valueSchema) { + super(name, traits); + this.name = name; + this.traits = traits; + this.valueSchema = valueSchema; + this.symbol = _ListSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::ListSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _ListSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const list2 = lhs; + return list2.symbol === _ListSchema.symbol; + } + return isPrototype; + } +}; +function list(namespace, name, traits = {}, valueSchema) { + const schema = new ListSchema( + namespace + "#" + name, + traits, + typeof valueSchema === "function" ? valueSchema() : valueSchema + ); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/MapSchema.ts +var MapSchema = class _MapSchema extends Schema { + constructor(name, traits, keySchema, valueSchema) { + super(name, traits); + this.name = name; + this.traits = traits; + this.keySchema = keySchema; + this.valueSchema = valueSchema; + this.symbol = _MapSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::MapSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _MapSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const map2 = lhs; + return map2.symbol === _MapSchema.symbol; + } + return isPrototype; + } +}; +function map(namespace, name, traits = {}, keySchema, valueSchema) { + const schema = new MapSchema( + namespace + "#" + name, + traits, + keySchema, + typeof valueSchema === "function" ? valueSchema() : valueSchema + ); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/OperationSchema.ts +var OperationSchema = class extends Schema { + constructor(name, traits, input, output) { + super(name, traits); + this.name = name; + this.traits = traits; + this.input = input; + this.output = output; + } +}; +function op(namespace, name, traits = {}, input, output) { + const schema = new OperationSchema(namespace + "#" + name, traits, input, output); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/StructureSchema.ts +var StructureSchema = class _StructureSchema extends Schema { + constructor(name, traits, memberNames, memberList) { + super(name, traits); + this.name = name; + this.traits = traits; + this.memberNames = memberNames; + this.memberList = memberList; + this.symbol = _StructureSchema.symbol; + this.members = {}; + for (let i = 0; i < memberNames.length; ++i) { + this.members[memberNames[i]] = Array.isArray(memberList[i]) ? memberList[i] : [memberList[i], 0]; + } + } + static { + this.symbol = Symbol.for("@smithy/core/schema::StructureSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _StructureSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const struct2 = lhs; + return struct2.symbol === _StructureSchema.symbol; + } + return isPrototype; + } +}; +function struct(namespace, name, traits, memberNames, memberList) { + const schema = new StructureSchema(namespace + "#" + name, traits, memberNames, memberList); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/ErrorSchema.ts +var ErrorSchema = class _ErrorSchema extends StructureSchema { + constructor(name, traits, memberNames, memberList, ctor) { + super(name, traits, memberNames, memberList); + this.name = name; + this.traits = traits; + this.memberNames = memberNames; + this.memberList = memberList; + this.ctor = ctor; + this.symbol = _ErrorSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::ErrorSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _ErrorSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const err = lhs; + return err.symbol === _ErrorSchema.symbol; + } + return isPrototype; + } +}; +function error(namespace, name, traits = {}, memberNames, memberList, ctor) { + const schema = new ErrorSchema(namespace + "#" + name, traits, memberNames, memberList, ctor); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/sentinels.ts +var SCHEMA = { + BLOB: 21, + // 21 + STREAMING_BLOB: 42, + // 42 + BOOLEAN: 2, + // 2 + STRING: 0, + // 0 + NUMERIC: 1, + // 1 + BIG_INTEGER: 17, + // 17 + BIG_DECIMAL: 19, + // 19 + DOCUMENT: 15, + // 15 + TIMESTAMP_DEFAULT: 4, + // 4 + TIMESTAMP_DATE_TIME: 5, + // 5 + TIMESTAMP_HTTP_DATE: 6, + // 6 + TIMESTAMP_EPOCH_SECONDS: 7, + // 7 + LIST_MODIFIER: 64, + // 64 + MAP_MODIFIER: 128 + // 128 +}; + +// src/submodules/schema/schemas/SimpleSchema.ts +var SimpleSchema = class _SimpleSchema extends Schema { + constructor(name, schemaRef, traits) { + super(name, traits); + this.name = name; + this.schemaRef = schemaRef; + this.traits = traits; + this.symbol = _SimpleSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::SimpleSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _SimpleSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const sim2 = lhs; + return sim2.symbol === _SimpleSchema.symbol; + } + return isPrototype; + } +}; +function sim(namespace, name, schemaRef, traits) { + const schema = new SimpleSchema(namespace + "#" + name, schemaRef, traits); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/NormalizedSchema.ts +var NormalizedSchema = class _NormalizedSchema { + /** + * @param ref - a polymorphic SchemaRef to be dereferenced/normalized. + * @param memberName - optional memberName if this NormalizedSchema should be considered a member schema. + */ + constructor(ref, memberName) { + this.ref = ref; + this.memberName = memberName; + this.symbol = _NormalizedSchema.symbol; + const traitStack = []; + let _ref = ref; + let schema = ref; + this._isMemberSchema = false; + while (Array.isArray(_ref)) { + traitStack.push(_ref[1]); + _ref = _ref[0]; + schema = deref(_ref); + this._isMemberSchema = true; + } + if (traitStack.length > 0) { + this.memberTraits = {}; + for (let i = traitStack.length - 1; i >= 0; --i) { + const traitSet = traitStack[i]; + Object.assign(this.memberTraits, _NormalizedSchema.translateTraits(traitSet)); + } + } else { + this.memberTraits = 0; + } + if (schema instanceof _NormalizedSchema) { + this.name = schema.name; + this.traits = schema.traits; + this._isMemberSchema = schema._isMemberSchema; + this.schema = schema.schema; + this.memberTraits = Object.assign({}, schema.getMemberTraits(), this.getMemberTraits()); + this.normalizedTraits = void 0; + this.ref = schema.ref; + this.memberName = memberName ?? schema.memberName; + return; + } + this.schema = deref(schema); + if (this.schema && typeof this.schema === "object") { + this.traits = this.schema?.traits ?? {}; + } else { + this.traits = 0; + } + this.name = (typeof this.schema === "object" ? this.schema?.name : void 0) ?? this.memberName ?? this.getSchemaName(); + if (this._isMemberSchema && !memberName) { + throw new Error( + `@smithy/core/schema - NormalizedSchema member schema ${this.getName( + true + )} must initialize with memberName argument.` + ); + } + } + static { + this.symbol = Symbol.for("@smithy/core/schema::NormalizedSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _NormalizedSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const ns = lhs; + return ns.symbol === _NormalizedSchema.symbol; + } + return isPrototype; + } + /** + * Static constructor that attempts to avoid wrapping a NormalizedSchema within another. + */ + static of(ref, memberName) { + if (ref instanceof _NormalizedSchema) { + return ref; + } + return new _NormalizedSchema(ref, memberName); + } + /** + * @param indicator - numeric indicator for preset trait combination. + * @returns equivalent trait object. + */ + static translateTraits(indicator) { + if (typeof indicator === "object") { + return indicator; + } + indicator = indicator | 0; + const traits = {}; + if ((indicator & 1) === 1) { + traits.httpLabel = 1; + } + if ((indicator >> 1 & 1) === 1) { + traits.idempotent = 1; + } + if ((indicator >> 2 & 1) === 1) { + traits.idempotencyToken = 1; + } + if ((indicator >> 3 & 1) === 1) { + traits.sensitive = 1; + } + if ((indicator >> 4 & 1) === 1) { + traits.httpPayload = 1; + } + if ((indicator >> 5 & 1) === 1) { + traits.httpResponseCode = 1; + } + if ((indicator >> 6 & 1) === 1) { + traits.httpQueryParams = 1; + } + return traits; + } + /** + * Creates a normalized member schema from the given schema and member name. + */ + static memberFrom(memberSchema, memberName) { + if (memberSchema instanceof _NormalizedSchema) { + memberSchema.memberName = memberName; + memberSchema._isMemberSchema = true; + return memberSchema; + } + return new _NormalizedSchema(memberSchema, memberName); + } + /** + * @returns the underlying non-normalized schema. + */ + getSchema() { + if (this.schema instanceof _NormalizedSchema) { + return this.schema = this.schema.getSchema(); + } + if (this.schema instanceof SimpleSchema) { + return deref(this.schema.schemaRef); + } + return deref(this.schema); + } + /** + * @param withNamespace - qualifies the name. + * @returns e.g. `MyShape` or `com.namespace#MyShape`. + */ + getName(withNamespace = false) { + if (!withNamespace) { + if (this.name && this.name.includes("#")) { + return this.name.split("#")[1]; + } + } + return this.name || void 0; + } + /** + * @returns the member name if the schema is a member schema. + * @throws Error when the schema isn't a member schema. + */ + getMemberName() { + if (!this.isMemberSchema()) { + throw new Error(`@smithy/core/schema - cannot get member name on non-member schema: ${this.getName(true)}`); + } + return this.memberName; + } + isMemberSchema() { + return this._isMemberSchema; + } + isUnitSchema() { + return this.getSchema() === "unit"; + } + /** + * boolean methods on this class help control flow in shape serialization and deserialization. + */ + isListSchema() { + const inner = this.getSchema(); + if (typeof inner === "number") { + return inner >= SCHEMA.LIST_MODIFIER && inner < SCHEMA.MAP_MODIFIER; + } + return inner instanceof ListSchema; + } + isMapSchema() { + const inner = this.getSchema(); + if (typeof inner === "number") { + return inner >= SCHEMA.MAP_MODIFIER && inner <= 255; + } + return inner instanceof MapSchema; + } + isDocumentSchema() { + return this.getSchema() === SCHEMA.DOCUMENT; + } + isStructSchema() { + const inner = this.getSchema(); + return inner !== null && typeof inner === "object" && "members" in inner || inner instanceof StructureSchema; + } + isBlobSchema() { + return this.getSchema() === SCHEMA.BLOB || this.getSchema() === SCHEMA.STREAMING_BLOB; + } + isTimestampSchema() { + const schema = this.getSchema(); + return typeof schema === "number" && schema >= SCHEMA.TIMESTAMP_DEFAULT && schema <= SCHEMA.TIMESTAMP_EPOCH_SECONDS; + } + isStringSchema() { + return this.getSchema() === SCHEMA.STRING; + } + isBooleanSchema() { + return this.getSchema() === SCHEMA.BOOLEAN; + } + isNumericSchema() { + return this.getSchema() === SCHEMA.NUMERIC; + } + isBigIntegerSchema() { + return this.getSchema() === SCHEMA.BIG_INTEGER; + } + isBigDecimalSchema() { + return this.getSchema() === SCHEMA.BIG_DECIMAL; + } + isStreaming() { + const streaming = !!this.getMergedTraits().streaming; + if (streaming) { + return true; + } + return this.getSchema() === SCHEMA.STREAMING_BLOB; + } + /** + * @returns own traits merged with member traits, where member traits of the same trait key take priority. + * This method is cached. + */ + getMergedTraits() { + if (this.normalizedTraits) { + return this.normalizedTraits; + } + this.normalizedTraits = { + ...this.getOwnTraits(), + ...this.getMemberTraits() + }; + return this.normalizedTraits; + } + /** + * @returns only the member traits. If the schema is not a member, this returns empty. + */ + getMemberTraits() { + return _NormalizedSchema.translateTraits(this.memberTraits); + } + /** + * @returns only the traits inherent to the shape or member target shape if this schema is a member. + * If there are any member traits they are excluded. + */ + getOwnTraits() { + return _NormalizedSchema.translateTraits(this.traits); + } + /** + * @returns the map's key's schema. Returns a dummy Document schema if this schema is a Document. + * + * @throws Error if the schema is not a Map or Document. + */ + getKeySchema() { + if (this.isDocumentSchema()) { + return _NormalizedSchema.memberFrom([SCHEMA.DOCUMENT, 0], "key"); + } + if (!this.isMapSchema()) { + throw new Error(`@smithy/core/schema - cannot get key schema for non-map schema: ${this.getName(true)}`); + } + const schema = this.getSchema(); + if (typeof schema === "number") { + return _NormalizedSchema.memberFrom([63 & schema, 0], "key"); + } + return _NormalizedSchema.memberFrom([schema.keySchema, 0], "key"); + } + /** + * @returns the schema of the map's value or list's member. + * Returns a dummy Document schema if this schema is a Document. + * + * @throws Error if the schema is not a Map, List, nor Document. + */ + getValueSchema() { + const schema = this.getSchema(); + if (typeof schema === "number") { + if (this.isMapSchema()) { + return _NormalizedSchema.memberFrom([63 & schema, 0], "value"); + } else if (this.isListSchema()) { + return _NormalizedSchema.memberFrom([63 & schema, 0], "member"); + } + } + if (schema && typeof schema === "object") { + if (this.isStructSchema()) { + throw new Error(`cannot call getValueSchema() with StructureSchema ${this.getName(true)}`); + } + const collection = schema; + if ("valueSchema" in collection) { + if (this.isMapSchema()) { + return _NormalizedSchema.memberFrom([collection.valueSchema, 0], "value"); + } else if (this.isListSchema()) { + return _NormalizedSchema.memberFrom([collection.valueSchema, 0], "member"); + } + } + } + if (this.isDocumentSchema()) { + return _NormalizedSchema.memberFrom([SCHEMA.DOCUMENT, 0], "value"); + } + throw new Error(`@smithy/core/schema - the schema ${this.getName(true)} does not have a value member.`); + } + /** + * @returns the NormalizedSchema for the given member name. The returned instance will return true for `isMemberSchema()` + * and will have the member name given. + * @param member - which member to retrieve and wrap. + * + * @throws Error if member does not exist or the schema is neither a document nor structure. + * Note that errors are assumed to be structures and unions are considered structures for these purposes. + */ + getMemberSchema(member) { + if (this.isStructSchema()) { + const struct2 = this.getSchema(); + if (!(member in struct2.members)) { + throw new Error( + `@smithy/core/schema - the schema ${this.getName(true)} does not have a member with name=${member}.` + ); + } + return _NormalizedSchema.memberFrom(struct2.members[member], member); + } + if (this.isDocumentSchema()) { + return _NormalizedSchema.memberFrom([SCHEMA.DOCUMENT, 0], member); + } + throw new Error(`@smithy/core/schema - the schema ${this.getName(true)} does not have members.`); + } + /** + * This can be used for checking the members as a hashmap. + * Prefer the structIterator method for iteration. + * + * This does NOT return list and map members, it is only for structures. + * + * @returns a map of member names to member schemas (normalized). + */ + getMemberSchemas() { + const { schema } = this; + const struct2 = schema; + if (!struct2 || typeof struct2 !== "object") { + return {}; + } + if ("members" in struct2) { + const buffer = {}; + for (const member of struct2.memberNames) { + buffer[member] = this.getMemberSchema(member); + } + return buffer; + } + return {}; + } + /** + * Allows iteration over members of a structure schema. + * Each yield is a pair of the member name and member schema. + * + * This avoids the overhead of calling Object.entries(ns.getMemberSchemas()). + */ + *structIterator() { + if (this.isUnitSchema()) { + return; + } + if (!this.isStructSchema()) { + throw new Error("@smithy/core/schema - cannot acquire structIterator on non-struct schema."); + } + const struct2 = this.getSchema(); + for (let i = 0; i < struct2.memberNames.length; ++i) { + yield [struct2.memberNames[i], _NormalizedSchema.memberFrom([struct2.memberList[i], 0], struct2.memberNames[i])]; + } + } + /** + * @returns a last-resort human-readable name for the schema if it has no other identifiers. + */ + getSchemaName() { + const schema = this.getSchema(); + if (typeof schema === "number") { + const _schema = 63 & schema; + const container = 192 & schema; + const type = Object.entries(SCHEMA).find(([, value]) => { + return value === _schema; + })?.[0] ?? "Unknown"; + switch (container) { + case SCHEMA.MAP_MODIFIER: + return `${type}Map`; + case SCHEMA.LIST_MODIFIER: + return `${type}List`; + case 0: + return type; + } + } + return "Unknown"; + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 92430: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/serde/index.ts +var serde_exports = {}; +__export(serde_exports, { + LazyJsonString: () => LazyJsonString, + NumericValue: () => NumericValue, + copyDocumentWithTransform: () => copyDocumentWithTransform, + dateToUtcString: () => dateToUtcString, + expectBoolean: () => expectBoolean, + expectByte: () => expectByte, + expectFloat32: () => expectFloat32, + expectInt: () => expectInt, + expectInt32: () => expectInt32, + expectLong: () => expectLong, + expectNonNull: () => expectNonNull, + expectNumber: () => expectNumber, + expectObject: () => expectObject, + expectShort: () => expectShort, + expectString: () => expectString, + expectUnion: () => expectUnion, + handleFloat: () => handleFloat, + limitedParseDouble: () => limitedParseDouble, + limitedParseFloat: () => limitedParseFloat, + limitedParseFloat32: () => limitedParseFloat32, + logger: () => logger, + nv: () => nv, + parseBoolean: () => parseBoolean, + parseEpochTimestamp: () => parseEpochTimestamp, + parseRfc3339DateTime: () => parseRfc3339DateTime, + parseRfc3339DateTimeWithOffset: () => parseRfc3339DateTimeWithOffset, + parseRfc7231DateTime: () => parseRfc7231DateTime, + quoteHeader: () => quoteHeader, + splitEvery: () => splitEvery, + splitHeader: () => splitHeader, + strictParseByte: () => strictParseByte, + strictParseDouble: () => strictParseDouble, + strictParseFloat: () => strictParseFloat, + strictParseFloat32: () => strictParseFloat32, + strictParseInt: () => strictParseInt, + strictParseInt32: () => strictParseInt32, + strictParseLong: () => strictParseLong, + strictParseShort: () => strictParseShort +}); +module.exports = __toCommonJS(serde_exports); + +// src/submodules/serde/copyDocumentWithTransform.ts +var import_schema = __nccwpck_require__(26890); +var copyDocumentWithTransform = (source, schemaRef, transform = (_) => _) => { + const ns = import_schema.NormalizedSchema.of(schemaRef); + switch (typeof source) { + case "undefined": + case "boolean": + case "number": + case "string": + case "bigint": + case "symbol": + return transform(source, ns); + case "function": + case "object": + if (source === null) { + return transform(null, ns); + } + if (Array.isArray(source)) { + const newArray = new Array(source.length); + let i = 0; + for (const item of source) { + newArray[i++] = copyDocumentWithTransform(item, ns.getValueSchema(), transform); + } + return transform(newArray, ns); + } + if ("byteLength" in source) { + const newBytes = new Uint8Array(source.byteLength); + newBytes.set(source, 0); + return transform(newBytes, ns); + } + if (source instanceof Date) { + return transform(source, ns); + } + const newObject = {}; + if (ns.isMapSchema()) { + for (const key of Object.keys(source)) { + newObject[key] = copyDocumentWithTransform(source[key], ns.getValueSchema(), transform); + } + } else if (ns.isStructSchema()) { + for (const [key, memberSchema] of ns.structIterator()) { + newObject[key] = copyDocumentWithTransform(source[key], memberSchema, transform); + } + } else if (ns.isDocumentSchema()) { + for (const key of Object.keys(source)) { + newObject[key] = copyDocumentWithTransform(source[key], ns.getValueSchema(), transform); + } + } + return transform(newObject, ns); + default: + return transform(source, ns); + } +}; + +// src/submodules/serde/parse-utils.ts +var parseBoolean = (value) => { + switch (value) { + case "true": + return true; + case "false": + return false; + default: + throw new Error(`Unable to parse boolean value "${value}"`); + } +}; +var expectBoolean = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "number") { + if (value === 0 || value === 1) { + logger.warn(stackTraceWarning(`Expected boolean, got ${typeof value}: ${value}`)); + } + if (value === 0) { + return false; + } + if (value === 1) { + return true; + } + } + if (typeof value === "string") { + const lower = value.toLowerCase(); + if (lower === "false" || lower === "true") { + logger.warn(stackTraceWarning(`Expected boolean, got ${typeof value}: ${value}`)); + } + if (lower === "false") { + return false; + } + if (lower === "true") { + return true; + } + } + if (typeof value === "boolean") { + return value; + } + throw new TypeError(`Expected boolean, got ${typeof value}: ${value}`); +}; +var expectNumber = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "string") { + const parsed = parseFloat(value); + if (!Number.isNaN(parsed)) { + if (String(parsed) !== String(value)) { + logger.warn(stackTraceWarning(`Expected number but observed string: ${value}`)); + } + return parsed; + } + } + if (typeof value === "number") { + return value; + } + throw new TypeError(`Expected number, got ${typeof value}: ${value}`); +}; +var MAX_FLOAT = Math.ceil(2 ** 127 * (2 - 2 ** -23)); +var expectFloat32 = (value) => { + const expected = expectNumber(value); + if (expected !== void 0 && !Number.isNaN(expected) && expected !== Infinity && expected !== -Infinity) { + if (Math.abs(expected) > MAX_FLOAT) { + throw new TypeError(`Expected 32-bit float, got ${value}`); + } + } + return expected; +}; +var expectLong = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (Number.isInteger(value) && !Number.isNaN(value)) { + return value; + } + throw new TypeError(`Expected integer, got ${typeof value}: ${value}`); +}; +var expectInt = expectLong; +var expectInt32 = (value) => expectSizedInt(value, 32); +var expectShort = (value) => expectSizedInt(value, 16); +var expectByte = (value) => expectSizedInt(value, 8); +var expectSizedInt = (value, size) => { + const expected = expectLong(value); + if (expected !== void 0 && castInt(expected, size) !== expected) { + throw new TypeError(`Expected ${size}-bit integer, got ${value}`); + } + return expected; +}; +var castInt = (value, size) => { + switch (size) { + case 32: + return Int32Array.of(value)[0]; + case 16: + return Int16Array.of(value)[0]; + case 8: + return Int8Array.of(value)[0]; + } +}; +var expectNonNull = (value, location) => { + if (value === null || value === void 0) { + if (location) { + throw new TypeError(`Expected a non-null value for ${location}`); + } + throw new TypeError("Expected a non-null value"); + } + return value; +}; +var expectObject = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "object" && !Array.isArray(value)) { + return value; + } + const receivedType = Array.isArray(value) ? "array" : typeof value; + throw new TypeError(`Expected object, got ${receivedType}: ${value}`); +}; +var expectString = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "string") { + return value; + } + if (["boolean", "number", "bigint"].includes(typeof value)) { + logger.warn(stackTraceWarning(`Expected string, got ${typeof value}: ${value}`)); + return String(value); + } + throw new TypeError(`Expected string, got ${typeof value}: ${value}`); +}; +var expectUnion = (value) => { + if (value === null || value === void 0) { + return void 0; + } + const asObject = expectObject(value); + const setKeys = Object.entries(asObject).filter(([, v]) => v != null).map(([k]) => k); + if (setKeys.length === 0) { + throw new TypeError(`Unions must have exactly one non-null member. None were found.`); + } + if (setKeys.length > 1) { + throw new TypeError(`Unions must have exactly one non-null member. Keys ${setKeys} were not null.`); + } + return asObject; +}; +var strictParseDouble = (value) => { + if (typeof value == "string") { + return expectNumber(parseNumber(value)); + } + return expectNumber(value); +}; +var strictParseFloat = strictParseDouble; +var strictParseFloat32 = (value) => { + if (typeof value == "string") { + return expectFloat32(parseNumber(value)); + } + return expectFloat32(value); +}; +var NUMBER_REGEX = /(-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)|(-?Infinity)|(NaN)/g; +var parseNumber = (value) => { + const matches = value.match(NUMBER_REGEX); + if (matches === null || matches[0].length !== value.length) { + throw new TypeError(`Expected real number, got implicit NaN`); + } + return parseFloat(value); +}; +var limitedParseDouble = (value) => { + if (typeof value == "string") { + return parseFloatString(value); + } + return expectNumber(value); +}; +var handleFloat = limitedParseDouble; +var limitedParseFloat = limitedParseDouble; +var limitedParseFloat32 = (value) => { + if (typeof value == "string") { + return parseFloatString(value); + } + return expectFloat32(value); +}; +var parseFloatString = (value) => { + switch (value) { + case "NaN": + return NaN; + case "Infinity": + return Infinity; + case "-Infinity": + return -Infinity; + default: + throw new Error(`Unable to parse float value: ${value}`); + } +}; +var strictParseLong = (value) => { + if (typeof value === "string") { + return expectLong(parseNumber(value)); + } + return expectLong(value); +}; +var strictParseInt = strictParseLong; +var strictParseInt32 = (value) => { + if (typeof value === "string") { + return expectInt32(parseNumber(value)); + } + return expectInt32(value); +}; +var strictParseShort = (value) => { + if (typeof value === "string") { + return expectShort(parseNumber(value)); + } + return expectShort(value); +}; +var strictParseByte = (value) => { + if (typeof value === "string") { + return expectByte(parseNumber(value)); + } + return expectByte(value); +}; +var stackTraceWarning = (message) => { + return String(new TypeError(message).stack || message).split("\n").slice(0, 5).filter((s) => !s.includes("stackTraceWarning")).join("\n"); +}; +var logger = { + warn: console.warn +}; + +// src/submodules/serde/date-utils.ts +var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; +var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; +function dateToUtcString(date) { + const year = date.getUTCFullYear(); + const month = date.getUTCMonth(); + const dayOfWeek = date.getUTCDay(); + const dayOfMonthInt = date.getUTCDate(); + const hoursInt = date.getUTCHours(); + const minutesInt = date.getUTCMinutes(); + const secondsInt = date.getUTCSeconds(); + const dayOfMonthString = dayOfMonthInt < 10 ? `0${dayOfMonthInt}` : `${dayOfMonthInt}`; + const hoursString = hoursInt < 10 ? `0${hoursInt}` : `${hoursInt}`; + const minutesString = minutesInt < 10 ? `0${minutesInt}` : `${minutesInt}`; + const secondsString = secondsInt < 10 ? `0${secondsInt}` : `${secondsInt}`; + return `${DAYS[dayOfWeek]}, ${dayOfMonthString} ${MONTHS[month]} ${year} ${hoursString}:${minutesString}:${secondsString} GMT`; +} +var RFC3339 = new RegExp(/^(\d{4})-(\d{2})-(\d{2})[tT](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?[zZ]$/); +var parseRfc3339DateTime = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value !== "string") { + throw new TypeError("RFC-3339 date-times must be expressed as strings"); + } + const match = RFC3339.exec(value); + if (!match) { + throw new TypeError("Invalid RFC-3339 date-time value"); + } + const [_, yearStr, monthStr, dayStr, hours, minutes, seconds, fractionalMilliseconds] = match; + const year = strictParseShort(stripLeadingZeroes(yearStr)); + const month = parseDateValue(monthStr, "month", 1, 12); + const day = parseDateValue(dayStr, "day", 1, 31); + return buildDate(year, month, day, { hours, minutes, seconds, fractionalMilliseconds }); +}; +var RFC3339_WITH_OFFSET = new RegExp( + /^(\d{4})-(\d{2})-(\d{2})[tT](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(([-+]\d{2}\:\d{2})|[zZ])$/ +); +var parseRfc3339DateTimeWithOffset = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value !== "string") { + throw new TypeError("RFC-3339 date-times must be expressed as strings"); + } + const match = RFC3339_WITH_OFFSET.exec(value); + if (!match) { + throw new TypeError("Invalid RFC-3339 date-time value"); + } + const [_, yearStr, monthStr, dayStr, hours, minutes, seconds, fractionalMilliseconds, offsetStr] = match; + const year = strictParseShort(stripLeadingZeroes(yearStr)); + const month = parseDateValue(monthStr, "month", 1, 12); + const day = parseDateValue(dayStr, "day", 1, 31); + const date = buildDate(year, month, day, { hours, minutes, seconds, fractionalMilliseconds }); + if (offsetStr.toUpperCase() != "Z") { + date.setTime(date.getTime() - parseOffsetToMilliseconds(offsetStr)); + } + return date; +}; +var IMF_FIXDATE = new RegExp( + /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? GMT$/ +); +var RFC_850_DATE = new RegExp( + /^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? GMT$/ +); +var ASC_TIME = new RegExp( + /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( [1-9]|\d{2}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? (\d{4})$/ +); +var parseRfc7231DateTime = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value !== "string") { + throw new TypeError("RFC-7231 date-times must be expressed as strings"); + } + let match = IMF_FIXDATE.exec(value); + if (match) { + const [_, dayStr, monthStr, yearStr, hours, minutes, seconds, fractionalMilliseconds] = match; + return buildDate( + strictParseShort(stripLeadingZeroes(yearStr)), + parseMonthByShortName(monthStr), + parseDateValue(dayStr, "day", 1, 31), + { hours, minutes, seconds, fractionalMilliseconds } + ); + } + match = RFC_850_DATE.exec(value); + if (match) { + const [_, dayStr, monthStr, yearStr, hours, minutes, seconds, fractionalMilliseconds] = match; + return adjustRfc850Year( + buildDate(parseTwoDigitYear(yearStr), parseMonthByShortName(monthStr), parseDateValue(dayStr, "day", 1, 31), { + hours, + minutes, + seconds, + fractionalMilliseconds + }) + ); + } + match = ASC_TIME.exec(value); + if (match) { + const [_, monthStr, dayStr, hours, minutes, seconds, fractionalMilliseconds, yearStr] = match; + return buildDate( + strictParseShort(stripLeadingZeroes(yearStr)), + parseMonthByShortName(monthStr), + parseDateValue(dayStr.trimLeft(), "day", 1, 31), + { hours, minutes, seconds, fractionalMilliseconds } + ); + } + throw new TypeError("Invalid RFC-7231 date-time value"); +}; +var parseEpochTimestamp = (value) => { + if (value === null || value === void 0) { + return void 0; + } + let valueAsDouble; + if (typeof value === "number") { + valueAsDouble = value; + } else if (typeof value === "string") { + valueAsDouble = strictParseDouble(value); + } else if (typeof value === "object" && value.tag === 1) { + valueAsDouble = value.value; + } else { + throw new TypeError("Epoch timestamps must be expressed as floating point numbers or their string representation"); + } + if (Number.isNaN(valueAsDouble) || valueAsDouble === Infinity || valueAsDouble === -Infinity) { + throw new TypeError("Epoch timestamps must be valid, non-Infinite, non-NaN numerics"); + } + return new Date(Math.round(valueAsDouble * 1e3)); +}; +var buildDate = (year, month, day, time) => { + const adjustedMonth = month - 1; + validateDayOfMonth(year, adjustedMonth, day); + return new Date( + Date.UTC( + year, + adjustedMonth, + day, + parseDateValue(time.hours, "hour", 0, 23), + parseDateValue(time.minutes, "minute", 0, 59), + // seconds can go up to 60 for leap seconds + parseDateValue(time.seconds, "seconds", 0, 60), + parseMilliseconds(time.fractionalMilliseconds) + ) + ); +}; +var parseTwoDigitYear = (value) => { + const thisYear = (/* @__PURE__ */ new Date()).getUTCFullYear(); + const valueInThisCentury = Math.floor(thisYear / 100) * 100 + strictParseShort(stripLeadingZeroes(value)); + if (valueInThisCentury < thisYear) { + return valueInThisCentury + 100; + } + return valueInThisCentury; +}; +var FIFTY_YEARS_IN_MILLIS = 50 * 365 * 24 * 60 * 60 * 1e3; +var adjustRfc850Year = (input) => { + if (input.getTime() - (/* @__PURE__ */ new Date()).getTime() > FIFTY_YEARS_IN_MILLIS) { + return new Date( + Date.UTC( + input.getUTCFullYear() - 100, + input.getUTCMonth(), + input.getUTCDate(), + input.getUTCHours(), + input.getUTCMinutes(), + input.getUTCSeconds(), + input.getUTCMilliseconds() + ) + ); + } + return input; +}; +var parseMonthByShortName = (value) => { + const monthIdx = MONTHS.indexOf(value); + if (monthIdx < 0) { + throw new TypeError(`Invalid month: ${value}`); + } + return monthIdx + 1; +}; +var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; +var validateDayOfMonth = (year, month, day) => { + let maxDays = DAYS_IN_MONTH[month]; + if (month === 1 && isLeapYear(year)) { + maxDays = 29; + } + if (day > maxDays) { + throw new TypeError(`Invalid day for ${MONTHS[month]} in ${year}: ${day}`); + } +}; +var isLeapYear = (year) => { + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); +}; +var parseDateValue = (value, type, lower, upper) => { + const dateVal = strictParseByte(stripLeadingZeroes(value)); + if (dateVal < lower || dateVal > upper) { + throw new TypeError(`${type} must be between ${lower} and ${upper}, inclusive`); + } + return dateVal; +}; +var parseMilliseconds = (value) => { + if (value === null || value === void 0) { + return 0; + } + return strictParseFloat32("0." + value) * 1e3; +}; +var parseOffsetToMilliseconds = (value) => { + const directionStr = value[0]; + let direction = 1; + if (directionStr == "+") { + direction = 1; + } else if (directionStr == "-") { + direction = -1; + } else { + throw new TypeError(`Offset direction, ${directionStr}, must be "+" or "-"`); + } + const hour = Number(value.substring(1, 3)); + const minute = Number(value.substring(4, 6)); + return direction * (hour * 60 + minute) * 60 * 1e3; +}; +var stripLeadingZeroes = (value) => { + let idx = 0; + while (idx < value.length - 1 && value.charAt(idx) === "0") { + idx++; + } + if (idx === 0) { + return value; + } + return value.slice(idx); +}; + +// src/submodules/serde/lazy-json.ts +var LazyJsonString = function LazyJsonString2(val) { + const str = Object.assign(new String(val), { + deserializeJSON() { + return JSON.parse(String(val)); + }, + toString() { + return String(val); + }, + toJSON() { + return String(val); + } + }); + return str; +}; +LazyJsonString.from = (object) => { + if (object && typeof object === "object" && (object instanceof LazyJsonString || "deserializeJSON" in object)) { + return object; + } else if (typeof object === "string" || Object.getPrototypeOf(object) === String.prototype) { + return LazyJsonString(String(object)); + } + return LazyJsonString(JSON.stringify(object)); +}; +LazyJsonString.fromObject = LazyJsonString.from; + +// src/submodules/serde/quote-header.ts +function quoteHeader(part) { + if (part.includes(",") || part.includes('"')) { + part = `"${part.replace(/"/g, '\\"')}"`; + } + return part; +} + +// src/submodules/serde/split-every.ts +function splitEvery(value, delimiter, numDelimiters) { + if (numDelimiters <= 0 || !Number.isInteger(numDelimiters)) { + throw new Error("Invalid number of delimiters (" + numDelimiters + ") for splitEvery."); + } + const segments = value.split(delimiter); + if (numDelimiters === 1) { + return segments; + } + const compoundSegments = []; + let currentSegment = ""; + for (let i = 0; i < segments.length; i++) { + if (currentSegment === "") { + currentSegment = segments[i]; + } else { + currentSegment += delimiter + segments[i]; + } + if ((i + 1) % numDelimiters === 0) { + compoundSegments.push(currentSegment); + currentSegment = ""; + } + } + if (currentSegment !== "") { + compoundSegments.push(currentSegment); + } + return compoundSegments; +} + +// src/submodules/serde/split-header.ts +var splitHeader = (value) => { + const z = value.length; + const values = []; + let withinQuotes = false; + let prevChar = void 0; + let anchor = 0; + for (let i = 0; i < z; ++i) { + const char = value[i]; + switch (char) { + case `"`: + if (prevChar !== "\\") { + withinQuotes = !withinQuotes; + } + break; + case ",": + if (!withinQuotes) { + values.push(value.slice(anchor, i)); + anchor = i + 1; + } + break; + default: + } + prevChar = char; + } + values.push(value.slice(anchor)); + return values.map((v) => { + v = v.trim(); + const z2 = v.length; + if (z2 < 2) { + return v; + } + if (v[0] === `"` && v[z2 - 1] === `"`) { + v = v.slice(1, z2 - 1); + } + return v.replace(/\\"/g, '"'); + }); +}; + +// src/submodules/serde/value/NumericValue.ts +var NumericValue = class _NumericValue { + constructor(string, type) { + this.string = string; + this.type = type; + let dot = 0; + for (let i = 0; i < string.length; ++i) { + const char = string.charCodeAt(i); + if (i === 0 && char === 45) { + continue; + } + if (char === 46) { + if (dot) { + throw new Error("@smithy/core/serde - NumericValue must contain at most one decimal point."); + } + dot = 1; + continue; + } + if (char < 48 || char > 57) { + throw new Error( + `@smithy/core/serde - NumericValue must only contain [0-9], at most one decimal point ".", and an optional negation prefix "-".` + ); + } + } + } + toString() { + return this.string; + } + static [Symbol.hasInstance](object) { + if (!object || typeof object !== "object") { + return false; + } + const _nv = object; + const prototypeMatch = _NumericValue.prototype.isPrototypeOf(object.constructor?.prototype); + if (prototypeMatch) { + return prototypeMatch; + } + if (typeof _nv.string === "string" && typeof _nv.type === "string" && _nv.constructor?.name === "NumericValue") { + return true; + } + return prototypeMatch; + } +}; +function nv(input) { + return new NumericValue(String(input), "bigDecimal"); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 40566: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + DEFAULT_MAX_RETRIES: () => DEFAULT_MAX_RETRIES, + DEFAULT_TIMEOUT: () => DEFAULT_TIMEOUT, + ENV_CMDS_AUTH_TOKEN: () => ENV_CMDS_AUTH_TOKEN, + ENV_CMDS_FULL_URI: () => ENV_CMDS_FULL_URI, + ENV_CMDS_RELATIVE_URI: () => ENV_CMDS_RELATIVE_URI, + Endpoint: () => Endpoint, + fromContainerMetadata: () => fromContainerMetadata, + fromInstanceMetadata: () => fromInstanceMetadata, + getInstanceMetadataEndpoint: () => getInstanceMetadataEndpoint, + httpRequest: () => httpRequest, + providerConfigFromInit: () => providerConfigFromInit +}); +module.exports = __toCommonJS(src_exports); + +// src/fromContainerMetadata.ts + +var import_url = __nccwpck_require__(87016); + +// src/remoteProvider/httpRequest.ts +var import_property_provider = __nccwpck_require__(71238); +var import_buffer = __nccwpck_require__(20181); +var import_http = __nccwpck_require__(58611); +function httpRequest(options) { + return new Promise((resolve, reject) => { + const req = (0, import_http.request)({ + method: "GET", + ...options, + // Node.js http module doesn't accept hostname with square brackets + // Refs: https://github.com/nodejs/node/issues/39738 + hostname: options.hostname?.replace(/^\[(.+)\]$/, "$1") + }); + req.on("error", (err) => { + reject(Object.assign(new import_property_provider.ProviderError("Unable to connect to instance metadata service"), err)); + req.destroy(); + }); + req.on("timeout", () => { + reject(new import_property_provider.ProviderError("TimeoutError from instance metadata service")); + req.destroy(); + }); + req.on("response", (res) => { + const { statusCode = 400 } = res; + if (statusCode < 200 || 300 <= statusCode) { + reject( + Object.assign(new import_property_provider.ProviderError("Error response received from instance metadata service"), { statusCode }) + ); + req.destroy(); + } + const chunks = []; + res.on("data", (chunk) => { + chunks.push(chunk); + }); + res.on("end", () => { + resolve(import_buffer.Buffer.concat(chunks)); + req.destroy(); + }); + }); + req.end(); + }); +} +__name(httpRequest, "httpRequest"); + +// src/remoteProvider/ImdsCredentials.ts +var isImdsCredentials = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.AccessKeyId === "string" && typeof arg.SecretAccessKey === "string" && typeof arg.Token === "string" && typeof arg.Expiration === "string", "isImdsCredentials"); +var fromImdsCredentials = /* @__PURE__ */ __name((creds) => ({ + accessKeyId: creds.AccessKeyId, + secretAccessKey: creds.SecretAccessKey, + sessionToken: creds.Token, + expiration: new Date(creds.Expiration), + ...creds.AccountId && { accountId: creds.AccountId } +}), "fromImdsCredentials"); + +// src/remoteProvider/RemoteProviderInit.ts +var DEFAULT_TIMEOUT = 1e3; +var DEFAULT_MAX_RETRIES = 0; +var providerConfigFromInit = /* @__PURE__ */ __name(({ + maxRetries = DEFAULT_MAX_RETRIES, + timeout = DEFAULT_TIMEOUT +}) => ({ maxRetries, timeout }), "providerConfigFromInit"); + +// src/remoteProvider/retry.ts +var retry = /* @__PURE__ */ __name((toRetry, maxRetries) => { + let promise = toRetry(); + for (let i = 0; i < maxRetries; i++) { + promise = promise.catch(toRetry); + } + return promise; +}, "retry"); + +// src/fromContainerMetadata.ts +var ENV_CMDS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI"; +var ENV_CMDS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"; +var ENV_CMDS_AUTH_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN"; +var fromContainerMetadata = /* @__PURE__ */ __name((init = {}) => { + const { timeout, maxRetries } = providerConfigFromInit(init); + return () => retry(async () => { + const requestOptions = await getCmdsUri({ logger: init.logger }); + const credsResponse = JSON.parse(await requestFromEcsImds(timeout, requestOptions)); + if (!isImdsCredentials(credsResponse)) { + throw new import_property_provider.CredentialsProviderError("Invalid response received from instance metadata service.", { + logger: init.logger + }); + } + return fromImdsCredentials(credsResponse); + }, maxRetries); +}, "fromContainerMetadata"); +var requestFromEcsImds = /* @__PURE__ */ __name(async (timeout, options) => { + if (process.env[ENV_CMDS_AUTH_TOKEN]) { + options.headers = { + ...options.headers, + Authorization: process.env[ENV_CMDS_AUTH_TOKEN] + }; + } + const buffer = await httpRequest({ + ...options, + timeout + }); + return buffer.toString(); +}, "requestFromEcsImds"); +var CMDS_IP = "169.254.170.2"; +var GREENGRASS_HOSTS = { + localhost: true, + "127.0.0.1": true +}; +var GREENGRASS_PROTOCOLS = { + "http:": true, + "https:": true +}; +var getCmdsUri = /* @__PURE__ */ __name(async ({ logger }) => { + if (process.env[ENV_CMDS_RELATIVE_URI]) { + return { + hostname: CMDS_IP, + path: process.env[ENV_CMDS_RELATIVE_URI] + }; + } + if (process.env[ENV_CMDS_FULL_URI]) { + const parsed = (0, import_url.parse)(process.env[ENV_CMDS_FULL_URI]); + if (!parsed.hostname || !(parsed.hostname in GREENGRASS_HOSTS)) { + throw new import_property_provider.CredentialsProviderError(`${parsed.hostname} is not a valid container metadata service hostname`, { + tryNextLink: false, + logger + }); + } + if (!parsed.protocol || !(parsed.protocol in GREENGRASS_PROTOCOLS)) { + throw new import_property_provider.CredentialsProviderError(`${parsed.protocol} is not a valid container metadata service protocol`, { + tryNextLink: false, + logger + }); + } + return { + ...parsed, + port: parsed.port ? parseInt(parsed.port, 10) : void 0 + }; + } + throw new import_property_provider.CredentialsProviderError( + `The container metadata credential provider cannot be used unless the ${ENV_CMDS_RELATIVE_URI} or ${ENV_CMDS_FULL_URI} environment variable is set`, + { + tryNextLink: false, + logger + } + ); +}, "getCmdsUri"); + +// src/fromInstanceMetadata.ts + + + +// src/error/InstanceMetadataV1FallbackError.ts + +var InstanceMetadataV1FallbackError = class _InstanceMetadataV1FallbackError extends import_property_provider.CredentialsProviderError { + constructor(message, tryNextLink = true) { + super(message, tryNextLink); + this.tryNextLink = tryNextLink; + this.name = "InstanceMetadataV1FallbackError"; + Object.setPrototypeOf(this, _InstanceMetadataV1FallbackError.prototype); + } + static { + __name(this, "InstanceMetadataV1FallbackError"); + } +}; + +// src/utils/getInstanceMetadataEndpoint.ts +var import_node_config_provider = __nccwpck_require__(55704); +var import_url_parser = __nccwpck_require__(14494); + +// src/config/Endpoint.ts +var Endpoint = /* @__PURE__ */ ((Endpoint2) => { + Endpoint2["IPv4"] = "http://169.254.169.254"; + Endpoint2["IPv6"] = "http://[fd00:ec2::254]"; + return Endpoint2; +})(Endpoint || {}); + +// src/config/EndpointConfigOptions.ts +var ENV_ENDPOINT_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT"; +var CONFIG_ENDPOINT_NAME = "ec2_metadata_service_endpoint"; +var ENDPOINT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[ENV_ENDPOINT_NAME], + configFileSelector: (profile) => profile[CONFIG_ENDPOINT_NAME], + default: void 0 +}; + +// src/config/EndpointMode.ts +var EndpointMode = /* @__PURE__ */ ((EndpointMode2) => { + EndpointMode2["IPv4"] = "IPv4"; + EndpointMode2["IPv6"] = "IPv6"; + return EndpointMode2; +})(EndpointMode || {}); + +// src/config/EndpointModeConfigOptions.ts +var ENV_ENDPOINT_MODE_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE"; +var CONFIG_ENDPOINT_MODE_NAME = "ec2_metadata_service_endpoint_mode"; +var ENDPOINT_MODE_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[ENV_ENDPOINT_MODE_NAME], + configFileSelector: (profile) => profile[CONFIG_ENDPOINT_MODE_NAME], + default: "IPv4" /* IPv4 */ +}; + +// src/utils/getInstanceMetadataEndpoint.ts +var getInstanceMetadataEndpoint = /* @__PURE__ */ __name(async () => (0, import_url_parser.parseUrl)(await getFromEndpointConfig() || await getFromEndpointModeConfig()), "getInstanceMetadataEndpoint"); +var getFromEndpointConfig = /* @__PURE__ */ __name(async () => (0, import_node_config_provider.loadConfig)(ENDPOINT_CONFIG_OPTIONS)(), "getFromEndpointConfig"); +var getFromEndpointModeConfig = /* @__PURE__ */ __name(async () => { + const endpointMode = await (0, import_node_config_provider.loadConfig)(ENDPOINT_MODE_CONFIG_OPTIONS)(); + switch (endpointMode) { + case "IPv4" /* IPv4 */: + return "http://169.254.169.254" /* IPv4 */; + case "IPv6" /* IPv6 */: + return "http://[fd00:ec2::254]" /* IPv6 */; + default: + throw new Error(`Unsupported endpoint mode: ${endpointMode}. Select from ${Object.values(EndpointMode)}`); + } +}, "getFromEndpointModeConfig"); + +// src/utils/getExtendedInstanceMetadataCredentials.ts +var STATIC_STABILITY_REFRESH_INTERVAL_SECONDS = 5 * 60; +var STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS = 5 * 60; +var STATIC_STABILITY_DOC_URL = "https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html"; +var getExtendedInstanceMetadataCredentials = /* @__PURE__ */ __name((credentials, logger) => { + const refreshInterval = STATIC_STABILITY_REFRESH_INTERVAL_SECONDS + Math.floor(Math.random() * STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS); + const newExpiration = new Date(Date.now() + refreshInterval * 1e3); + logger.warn( + `Attempting credential expiration extension due to a credential service availability issue. A refresh of these credentials will be attempted after ${new Date(newExpiration)}. +For more information, please visit: ` + STATIC_STABILITY_DOC_URL + ); + const originalExpiration = credentials.originalExpiration ?? credentials.expiration; + return { + ...credentials, + ...originalExpiration ? { originalExpiration } : {}, + expiration: newExpiration + }; +}, "getExtendedInstanceMetadataCredentials"); + +// src/utils/staticStabilityProvider.ts +var staticStabilityProvider = /* @__PURE__ */ __name((provider, options = {}) => { + const logger = options?.logger || console; + let pastCredentials; + return async () => { + let credentials; + try { + credentials = await provider(); + if (credentials.expiration && credentials.expiration.getTime() < Date.now()) { + credentials = getExtendedInstanceMetadataCredentials(credentials, logger); + } + } catch (e) { + if (pastCredentials) { + logger.warn("Credential renew failed: ", e); + credentials = getExtendedInstanceMetadataCredentials(pastCredentials, logger); + } else { + throw e; + } + } + pastCredentials = credentials; + return credentials; + }; +}, "staticStabilityProvider"); + +// src/fromInstanceMetadata.ts +var IMDS_PATH = "/latest/meta-data/iam/security-credentials/"; +var IMDS_TOKEN_PATH = "/latest/api/token"; +var AWS_EC2_METADATA_V1_DISABLED = "AWS_EC2_METADATA_V1_DISABLED"; +var PROFILE_AWS_EC2_METADATA_V1_DISABLED = "ec2_metadata_v1_disabled"; +var X_AWS_EC2_METADATA_TOKEN = "x-aws-ec2-metadata-token"; +var fromInstanceMetadata = /* @__PURE__ */ __name((init = {}) => staticStabilityProvider(getInstanceMetadataProvider(init), { logger: init.logger }), "fromInstanceMetadata"); +var getInstanceMetadataProvider = /* @__PURE__ */ __name((init = {}) => { + let disableFetchToken = false; + const { logger, profile } = init; + const { timeout, maxRetries } = providerConfigFromInit(init); + const getCredentials = /* @__PURE__ */ __name(async (maxRetries2, options) => { + const isImdsV1Fallback = disableFetchToken || options.headers?.[X_AWS_EC2_METADATA_TOKEN] == null; + if (isImdsV1Fallback) { + let fallbackBlockedFromProfile = false; + let fallbackBlockedFromProcessEnv = false; + const configValue = await (0, import_node_config_provider.loadConfig)( + { + environmentVariableSelector: (env) => { + const envValue = env[AWS_EC2_METADATA_V1_DISABLED]; + fallbackBlockedFromProcessEnv = !!envValue && envValue !== "false"; + if (envValue === void 0) { + throw new import_property_provider.CredentialsProviderError( + `${AWS_EC2_METADATA_V1_DISABLED} not set in env, checking config file next.`, + { logger: init.logger } + ); + } + return fallbackBlockedFromProcessEnv; + }, + configFileSelector: (profile2) => { + const profileValue = profile2[PROFILE_AWS_EC2_METADATA_V1_DISABLED]; + fallbackBlockedFromProfile = !!profileValue && profileValue !== "false"; + return fallbackBlockedFromProfile; + }, + default: false + }, + { + profile + } + )(); + if (init.ec2MetadataV1Disabled || configValue) { + const causes = []; + if (init.ec2MetadataV1Disabled) + causes.push("credential provider initialization (runtime option ec2MetadataV1Disabled)"); + if (fallbackBlockedFromProfile) + causes.push(`config file profile (${PROFILE_AWS_EC2_METADATA_V1_DISABLED})`); + if (fallbackBlockedFromProcessEnv) + causes.push(`process environment variable (${AWS_EC2_METADATA_V1_DISABLED})`); + throw new InstanceMetadataV1FallbackError( + `AWS EC2 Metadata v1 fallback has been blocked by AWS SDK configuration in the following: [${causes.join( + ", " + )}].` + ); + } + } + const imdsProfile = (await retry(async () => { + let profile2; + try { + profile2 = await getProfile(options); + } catch (err) { + if (err.statusCode === 401) { + disableFetchToken = false; + } + throw err; + } + return profile2; + }, maxRetries2)).trim(); + return retry(async () => { + let creds; + try { + creds = await getCredentialsFromProfile(imdsProfile, options, init); + } catch (err) { + if (err.statusCode === 401) { + disableFetchToken = false; + } + throw err; + } + return creds; + }, maxRetries2); + }, "getCredentials"); + return async () => { + const endpoint = await getInstanceMetadataEndpoint(); + if (disableFetchToken) { + logger?.debug("AWS SDK Instance Metadata", "using v1 fallback (no token fetch)"); + return getCredentials(maxRetries, { ...endpoint, timeout }); + } else { + let token; + try { + token = (await getMetadataToken({ ...endpoint, timeout })).toString(); + } catch (error) { + if (error?.statusCode === 400) { + throw Object.assign(error, { + message: "EC2 Metadata token request returned error" + }); + } else if (error.message === "TimeoutError" || [403, 404, 405].includes(error.statusCode)) { + disableFetchToken = true; + } + logger?.debug("AWS SDK Instance Metadata", "using v1 fallback (initial)"); + return getCredentials(maxRetries, { ...endpoint, timeout }); + } + return getCredentials(maxRetries, { + ...endpoint, + headers: { + [X_AWS_EC2_METADATA_TOKEN]: token + }, + timeout + }); + } + }; +}, "getInstanceMetadataProvider"); +var getMetadataToken = /* @__PURE__ */ __name(async (options) => httpRequest({ + ...options, + path: IMDS_TOKEN_PATH, + method: "PUT", + headers: { + "x-aws-ec2-metadata-token-ttl-seconds": "21600" + } +}), "getMetadataToken"); +var getProfile = /* @__PURE__ */ __name(async (options) => (await httpRequest({ ...options, path: IMDS_PATH })).toString(), "getProfile"); +var getCredentialsFromProfile = /* @__PURE__ */ __name(async (profile, options, init) => { + const credentialsResponse = JSON.parse( + (await httpRequest({ + ...options, + path: IMDS_PATH + profile + })).toString() + ); + if (!isImdsCredentials(credentialsResponse)) { + throw new import_property_provider.CredentialsProviderError("Invalid response received from instance metadata service.", { + logger: init.logger + }); + } + return fromImdsCredentials(credentialsResponse); +}, "getCredentialsFromProfile"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 37788: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EventStreamCodec: () => EventStreamCodec, + HeaderMarshaller: () => HeaderMarshaller, + Int64: () => Int64, + MessageDecoderStream: () => MessageDecoderStream, + MessageEncoderStream: () => MessageEncoderStream, + SmithyMessageDecoderStream: () => SmithyMessageDecoderStream, + SmithyMessageEncoderStream: () => SmithyMessageEncoderStream +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamCodec.ts +var import_crc322 = __nccwpck_require__(62110); + +// src/HeaderMarshaller.ts + + +// src/Int64.ts +var import_util_hex_encoding = __nccwpck_require__(96435); +var Int64 = class _Int64 { + constructor(bytes) { + this.bytes = bytes; + if (bytes.byteLength !== 8) { + throw new Error("Int64 buffers must be exactly 8 bytes"); + } + } + static { + __name(this, "Int64"); + } + static fromNumber(number) { + if (number > 9223372036854776e3 || number < -9223372036854776e3) { + throw new Error(`${number} is too large (or, if negative, too small) to represent as an Int64`); + } + const bytes = new Uint8Array(8); + for (let i = 7, remaining = Math.abs(Math.round(number)); i > -1 && remaining > 0; i--, remaining /= 256) { + bytes[i] = remaining; + } + if (number < 0) { + negate(bytes); + } + return new _Int64(bytes); + } + /** + * Called implicitly by infix arithmetic operators. + */ + valueOf() { + const bytes = this.bytes.slice(0); + const negative = bytes[0] & 128; + if (negative) { + negate(bytes); + } + return parseInt((0, import_util_hex_encoding.toHex)(bytes), 16) * (negative ? -1 : 1); + } + toString() { + return String(this.valueOf()); + } +}; +function negate(bytes) { + for (let i = 0; i < 8; i++) { + bytes[i] ^= 255; + } + for (let i = 7; i > -1; i--) { + bytes[i]++; + if (bytes[i] !== 0) + break; + } +} +__name(negate, "negate"); + +// src/HeaderMarshaller.ts +var HeaderMarshaller = class { + constructor(toUtf8, fromUtf8) { + this.toUtf8 = toUtf8; + this.fromUtf8 = fromUtf8; + } + static { + __name(this, "HeaderMarshaller"); + } + format(headers) { + const chunks = []; + for (const headerName of Object.keys(headers)) { + const bytes = this.fromUtf8(headerName); + chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName])); + } + const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0)); + let position = 0; + for (const chunk of chunks) { + out.set(chunk, position); + position += chunk.byteLength; + } + return out; + } + formatHeaderValue(header) { + switch (header.type) { + case "boolean": + return Uint8Array.from([header.value ? 0 /* boolTrue */ : 1 /* boolFalse */]); + case "byte": + return Uint8Array.from([2 /* byte */, header.value]); + case "short": + const shortView = new DataView(new ArrayBuffer(3)); + shortView.setUint8(0, 3 /* short */); + shortView.setInt16(1, header.value, false); + return new Uint8Array(shortView.buffer); + case "integer": + const intView = new DataView(new ArrayBuffer(5)); + intView.setUint8(0, 4 /* integer */); + intView.setInt32(1, header.value, false); + return new Uint8Array(intView.buffer); + case "long": + const longBytes = new Uint8Array(9); + longBytes[0] = 5 /* long */; + longBytes.set(header.value.bytes, 1); + return longBytes; + case "binary": + const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength)); + binView.setUint8(0, 6 /* byteArray */); + binView.setUint16(1, header.value.byteLength, false); + const binBytes = new Uint8Array(binView.buffer); + binBytes.set(header.value, 3); + return binBytes; + case "string": + const utf8Bytes = this.fromUtf8(header.value); + const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength)); + strView.setUint8(0, 7 /* string */); + strView.setUint16(1, utf8Bytes.byteLength, false); + const strBytes = new Uint8Array(strView.buffer); + strBytes.set(utf8Bytes, 3); + return strBytes; + case "timestamp": + const tsBytes = new Uint8Array(9); + tsBytes[0] = 8 /* timestamp */; + tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1); + return tsBytes; + case "uuid": + if (!UUID_PATTERN.test(header.value)) { + throw new Error(`Invalid UUID received: ${header.value}`); + } + const uuidBytes = new Uint8Array(17); + uuidBytes[0] = 9 /* uuid */; + uuidBytes.set((0, import_util_hex_encoding.fromHex)(header.value.replace(/\-/g, "")), 1); + return uuidBytes; + } + } + parse(headers) { + const out = {}; + let position = 0; + while (position < headers.byteLength) { + const nameLength = headers.getUint8(position++); + const name = this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, nameLength)); + position += nameLength; + switch (headers.getUint8(position++)) { + case 0 /* boolTrue */: + out[name] = { + type: BOOLEAN_TAG, + value: true + }; + break; + case 1 /* boolFalse */: + out[name] = { + type: BOOLEAN_TAG, + value: false + }; + break; + case 2 /* byte */: + out[name] = { + type: BYTE_TAG, + value: headers.getInt8(position++) + }; + break; + case 3 /* short */: + out[name] = { + type: SHORT_TAG, + value: headers.getInt16(position, false) + }; + position += 2; + break; + case 4 /* integer */: + out[name] = { + type: INT_TAG, + value: headers.getInt32(position, false) + }; + position += 4; + break; + case 5 /* long */: + out[name] = { + type: LONG_TAG, + value: new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)) + }; + position += 8; + break; + case 6 /* byteArray */: + const binaryLength = headers.getUint16(position, false); + position += 2; + out[name] = { + type: BINARY_TAG, + value: new Uint8Array(headers.buffer, headers.byteOffset + position, binaryLength) + }; + position += binaryLength; + break; + case 7 /* string */: + const stringLength = headers.getUint16(position, false); + position += 2; + out[name] = { + type: STRING_TAG, + value: this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, stringLength)) + }; + position += stringLength; + break; + case 8 /* timestamp */: + out[name] = { + type: TIMESTAMP_TAG, + value: new Date(new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)).valueOf()) + }; + position += 8; + break; + case 9 /* uuid */: + const uuidBytes = new Uint8Array(headers.buffer, headers.byteOffset + position, 16); + position += 16; + out[name] = { + type: UUID_TAG, + value: `${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(0, 4))}-${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(4, 6))}-${(0, import_util_hex_encoding.toHex)( + uuidBytes.subarray(6, 8) + )}-${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(8, 10))}-${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(10))}` + }; + break; + default: + throw new Error(`Unrecognized header type tag`); + } + } + return out; + } +}; +var BOOLEAN_TAG = "boolean"; +var BYTE_TAG = "byte"; +var SHORT_TAG = "short"; +var INT_TAG = "integer"; +var LONG_TAG = "long"; +var BINARY_TAG = "binary"; +var STRING_TAG = "string"; +var TIMESTAMP_TAG = "timestamp"; +var UUID_TAG = "uuid"; +var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/; + +// src/splitMessage.ts +var import_crc32 = __nccwpck_require__(62110); +var PRELUDE_MEMBER_LENGTH = 4; +var PRELUDE_LENGTH = PRELUDE_MEMBER_LENGTH * 2; +var CHECKSUM_LENGTH = 4; +var MINIMUM_MESSAGE_LENGTH = PRELUDE_LENGTH + CHECKSUM_LENGTH * 2; +function splitMessage({ byteLength, byteOffset, buffer }) { + if (byteLength < MINIMUM_MESSAGE_LENGTH) { + throw new Error("Provided message too short to accommodate event stream message overhead"); + } + const view = new DataView(buffer, byteOffset, byteLength); + const messageLength = view.getUint32(0, false); + if (byteLength !== messageLength) { + throw new Error("Reported message length does not match received message length"); + } + const headerLength = view.getUint32(PRELUDE_MEMBER_LENGTH, false); + const expectedPreludeChecksum = view.getUint32(PRELUDE_LENGTH, false); + const expectedMessageChecksum = view.getUint32(byteLength - CHECKSUM_LENGTH, false); + const checksummer = new import_crc32.Crc32().update(new Uint8Array(buffer, byteOffset, PRELUDE_LENGTH)); + if (expectedPreludeChecksum !== checksummer.digest()) { + throw new Error( + `The prelude checksum specified in the message (${expectedPreludeChecksum}) does not match the calculated CRC32 checksum (${checksummer.digest()})` + ); + } + checksummer.update( + new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH, byteLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH)) + ); + if (expectedMessageChecksum !== checksummer.digest()) { + throw new Error( + `The message checksum (${checksummer.digest()}) did not match the expected value of ${expectedMessageChecksum}` + ); + } + return { + headers: new DataView(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH, headerLength), + body: new Uint8Array( + buffer, + byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH + headerLength, + messageLength - headerLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH + CHECKSUM_LENGTH) + ) + }; +} +__name(splitMessage, "splitMessage"); + +// src/EventStreamCodec.ts +var EventStreamCodec = class { + static { + __name(this, "EventStreamCodec"); + } + constructor(toUtf8, fromUtf8) { + this.headerMarshaller = new HeaderMarshaller(toUtf8, fromUtf8); + this.messageBuffer = []; + this.isEndOfStream = false; + } + feed(message) { + this.messageBuffer.push(this.decode(message)); + } + endOfStream() { + this.isEndOfStream = true; + } + getMessage() { + const message = this.messageBuffer.pop(); + const isEndOfStream = this.isEndOfStream; + return { + getMessage() { + return message; + }, + isEndOfStream() { + return isEndOfStream; + } + }; + } + getAvailableMessages() { + const messages = this.messageBuffer; + this.messageBuffer = []; + const isEndOfStream = this.isEndOfStream; + return { + getMessages() { + return messages; + }, + isEndOfStream() { + return isEndOfStream; + } + }; + } + /** + * Convert a structured JavaScript object with tagged headers into a binary + * event stream message. + */ + encode({ headers: rawHeaders, body }) { + const headers = this.headerMarshaller.format(rawHeaders); + const length = headers.byteLength + body.byteLength + 16; + const out = new Uint8Array(length); + const view = new DataView(out.buffer, out.byteOffset, out.byteLength); + const checksum = new import_crc322.Crc32(); + view.setUint32(0, length, false); + view.setUint32(4, headers.byteLength, false); + view.setUint32(8, checksum.update(out.subarray(0, 8)).digest(), false); + out.set(headers, 12); + out.set(body, headers.byteLength + 12); + view.setUint32(length - 4, checksum.update(out.subarray(8, length - 4)).digest(), false); + return out; + } + /** + * Convert a binary event stream message into a JavaScript object with an + * opaque, binary body and tagged, parsed headers. + */ + decode(message) { + const { headers, body } = splitMessage(message); + return { headers: this.headerMarshaller.parse(headers), body }; + } + /** + * Convert a structured JavaScript object with tagged headers into a binary + * event stream message header. + */ + formatHeaders(rawHeaders) { + return this.headerMarshaller.format(rawHeaders); + } +}; + +// src/MessageDecoderStream.ts +var MessageDecoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "MessageDecoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const bytes of this.options.inputStream) { + const decoded = this.options.decoder.decode(bytes); + yield decoded; + } + } +}; + +// src/MessageEncoderStream.ts +var MessageEncoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "MessageEncoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const msg of this.options.messageStream) { + const encoded = this.options.encoder.encode(msg); + yield encoded; + } + if (this.options.includeEndFrame) { + yield new Uint8Array(0); + } + } +}; + +// src/SmithyMessageDecoderStream.ts +var SmithyMessageDecoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "SmithyMessageDecoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const message of this.options.messageStream) { + const deserialized = await this.options.deserializer(message); + if (deserialized === void 0) + continue; + yield deserialized; + } + } +}; + +// src/SmithyMessageEncoderStream.ts +var SmithyMessageEncoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "SmithyMessageEncoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const chunk of this.options.inputStream) { + const payloadBuf = this.options.serializer(chunk); + yield payloadBuf; + } + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 86895: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + resolveEventStreamSerdeConfig: () => resolveEventStreamSerdeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamSerdeConfig.ts +var resolveEventStreamSerdeConfig = /* @__PURE__ */ __name((input) => Object.assign(input, { + eventStreamMarshaller: input.eventStreamSerdeProvider(input) +}), "resolveEventStreamSerdeConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 69770: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EventStreamMarshaller: () => EventStreamMarshaller, + eventStreamSerdeProvider: () => eventStreamSerdeProvider +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamMarshaller.ts +var import_eventstream_serde_universal = __nccwpck_require__(14221); +var import_stream = __nccwpck_require__(2203); + +// src/utils.ts +async function* readabletoIterable(readStream) { + let streamEnded = false; + let generationEnded = false; + const records = new Array(); + readStream.on("error", (err) => { + if (!streamEnded) { + streamEnded = true; + } + if (err) { + throw err; + } + }); + readStream.on("data", (data) => { + records.push(data); + }); + readStream.on("end", () => { + streamEnded = true; + }); + while (!generationEnded) { + const value = await new Promise((resolve) => setTimeout(() => resolve(records.shift()), 0)); + if (value) { + yield value; + } + generationEnded = streamEnded && records.length === 0; + } +} +__name(readabletoIterable, "readabletoIterable"); + +// src/EventStreamMarshaller.ts +var EventStreamMarshaller = class { + static { + __name(this, "EventStreamMarshaller"); + } + constructor({ utf8Encoder, utf8Decoder }) { + this.universalMarshaller = new import_eventstream_serde_universal.EventStreamMarshaller({ + utf8Decoder, + utf8Encoder + }); + } + deserialize(body, deserializer) { + const bodyIterable = typeof body[Symbol.asyncIterator] === "function" ? body : readabletoIterable(body); + return this.universalMarshaller.deserialize(bodyIterable, deserializer); + } + serialize(input, serializer) { + return import_stream.Readable.from(this.universalMarshaller.serialize(input, serializer)); + } +}; + +// src/provider.ts +var eventStreamSerdeProvider = /* @__PURE__ */ __name((options) => new EventStreamMarshaller(options), "eventStreamSerdeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 14221: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EventStreamMarshaller: () => EventStreamMarshaller, + eventStreamSerdeProvider: () => eventStreamSerdeProvider +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamMarshaller.ts +var import_eventstream_codec = __nccwpck_require__(37788); + +// src/getChunkedStream.ts +function getChunkedStream(source) { + let currentMessageTotalLength = 0; + let currentMessagePendingLength = 0; + let currentMessage = null; + let messageLengthBuffer = null; + const allocateMessage = /* @__PURE__ */ __name((size) => { + if (typeof size !== "number") { + throw new Error("Attempted to allocate an event message where size was not a number: " + size); + } + currentMessageTotalLength = size; + currentMessagePendingLength = 4; + currentMessage = new Uint8Array(size); + const currentMessageView = new DataView(currentMessage.buffer); + currentMessageView.setUint32(0, size, false); + }, "allocateMessage"); + const iterator = /* @__PURE__ */ __name(async function* () { + const sourceIterator = source[Symbol.asyncIterator](); + while (true) { + const { value, done } = await sourceIterator.next(); + if (done) { + if (!currentMessageTotalLength) { + return; + } else if (currentMessageTotalLength === currentMessagePendingLength) { + yield currentMessage; + } else { + throw new Error("Truncated event message received."); + } + return; + } + const chunkLength = value.length; + let currentOffset = 0; + while (currentOffset < chunkLength) { + if (!currentMessage) { + const bytesRemaining = chunkLength - currentOffset; + if (!messageLengthBuffer) { + messageLengthBuffer = new Uint8Array(4); + } + const numBytesForTotal = Math.min( + 4 - currentMessagePendingLength, + // remaining bytes to fill the messageLengthBuffer + bytesRemaining + // bytes left in chunk + ); + messageLengthBuffer.set( + // @ts-ignore error TS2532: Object is possibly 'undefined' for value + value.slice(currentOffset, currentOffset + numBytesForTotal), + currentMessagePendingLength + ); + currentMessagePendingLength += numBytesForTotal; + currentOffset += numBytesForTotal; + if (currentMessagePendingLength < 4) { + break; + } + allocateMessage(new DataView(messageLengthBuffer.buffer).getUint32(0, false)); + messageLengthBuffer = null; + } + const numBytesToWrite = Math.min( + currentMessageTotalLength - currentMessagePendingLength, + // number of bytes left to complete message + chunkLength - currentOffset + // number of bytes left in the original chunk + ); + currentMessage.set( + // @ts-ignore error TS2532: Object is possibly 'undefined' for value + value.slice(currentOffset, currentOffset + numBytesToWrite), + currentMessagePendingLength + ); + currentMessagePendingLength += numBytesToWrite; + currentOffset += numBytesToWrite; + if (currentMessageTotalLength && currentMessageTotalLength === currentMessagePendingLength) { + yield currentMessage; + currentMessage = null; + currentMessageTotalLength = 0; + currentMessagePendingLength = 0; + } + } + } + }, "iterator"); + return { + [Symbol.asyncIterator]: iterator + }; +} +__name(getChunkedStream, "getChunkedStream"); + +// src/getUnmarshalledStream.ts +function getMessageUnmarshaller(deserializer, toUtf8) { + return async function(message) { + const { value: messageType } = message.headers[":message-type"]; + if (messageType === "error") { + const unmodeledError = new Error(message.headers[":error-message"].value || "UnknownError"); + unmodeledError.name = message.headers[":error-code"].value; + throw unmodeledError; + } else if (messageType === "exception") { + const code = message.headers[":exception-type"].value; + const exception = { [code]: message }; + const deserializedException = await deserializer(exception); + if (deserializedException.$unknown) { + const error = new Error(toUtf8(message.body)); + error.name = code; + throw error; + } + throw deserializedException[code]; + } else if (messageType === "event") { + const event = { + [message.headers[":event-type"].value]: message + }; + const deserialized = await deserializer(event); + if (deserialized.$unknown) + return; + return deserialized; + } else { + throw Error(`Unrecognizable event type: ${message.headers[":event-type"].value}`); + } + }; +} +__name(getMessageUnmarshaller, "getMessageUnmarshaller"); + +// src/EventStreamMarshaller.ts +var EventStreamMarshaller = class { + static { + __name(this, "EventStreamMarshaller"); + } + constructor({ utf8Encoder, utf8Decoder }) { + this.eventStreamCodec = new import_eventstream_codec.EventStreamCodec(utf8Encoder, utf8Decoder); + this.utfEncoder = utf8Encoder; + } + deserialize(body, deserializer) { + const inputStream = getChunkedStream(body); + return new import_eventstream_codec.SmithyMessageDecoderStream({ + messageStream: new import_eventstream_codec.MessageDecoderStream({ inputStream, decoder: this.eventStreamCodec }), + // @ts-expect-error Type 'T' is not assignable to type 'Record' + deserializer: getMessageUnmarshaller(deserializer, this.utfEncoder) + }); + } + serialize(inputStream, serializer) { + return new import_eventstream_codec.MessageEncoderStream({ + messageStream: new import_eventstream_codec.SmithyMessageEncoderStream({ inputStream, serializer }), + encoder: this.eventStreamCodec, + includeEndFrame: true + }); + } +}; + +// src/provider.ts +var eventStreamSerdeProvider = /* @__PURE__ */ __name((options) => new EventStreamMarshaller(options), "eventStreamSerdeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 47809: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + FetchHttpHandler: () => FetchHttpHandler, + keepAliveSupport: () => keepAliveSupport, + streamCollector: () => streamCollector +}); +module.exports = __toCommonJS(src_exports); + +// src/fetch-http-handler.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_querystring_builder = __nccwpck_require__(18256); + +// src/create-request.ts +function createRequest(url, requestOptions) { + return new Request(url, requestOptions); +} +__name(createRequest, "createRequest"); + +// src/request-timeout.ts +function requestTimeout(timeoutInMs = 0) { + return new Promise((resolve, reject) => { + if (timeoutInMs) { + setTimeout(() => { + const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`); + timeoutError.name = "TimeoutError"; + reject(timeoutError); + }, timeoutInMs); + } + }); +} +__name(requestTimeout, "requestTimeout"); + +// src/fetch-http-handler.ts +var keepAliveSupport = { + supported: void 0 +}; +var FetchHttpHandler = class _FetchHttpHandler { + static { + __name(this, "FetchHttpHandler"); + } + /** + * @returns the input if it is an HttpHandler of any class, + * or instantiates a new instance of this handler. + */ + static create(instanceOrOptions) { + if (typeof instanceOrOptions?.handle === "function") { + return instanceOrOptions; + } + return new _FetchHttpHandler(instanceOrOptions); + } + constructor(options) { + if (typeof options === "function") { + this.configProvider = options().then((opts) => opts || {}); + } else { + this.config = options ?? {}; + this.configProvider = Promise.resolve(this.config); + } + if (keepAliveSupport.supported === void 0) { + keepAliveSupport.supported = Boolean( + typeof Request !== "undefined" && "keepalive" in createRequest("https://[::1]") + ); + } + } + destroy() { + } + async handle(request, { abortSignal, requestTimeout: requestTimeout2 } = {}) { + if (!this.config) { + this.config = await this.configProvider; + } + const requestTimeoutInMs = requestTimeout2 ?? this.config.requestTimeout; + const keepAlive = this.config.keepAlive === true; + const credentials = this.config.credentials; + if (abortSignal?.aborted) { + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + return Promise.reject(abortError); + } + let path = request.path; + const queryString = (0, import_querystring_builder.buildQueryString)(request.query || {}); + if (queryString) { + path += `?${queryString}`; + } + if (request.fragment) { + path += `#${request.fragment}`; + } + let auth = ""; + if (request.username != null || request.password != null) { + const username = request.username ?? ""; + const password = request.password ?? ""; + auth = `${username}:${password}@`; + } + const { port, method } = request; + const url = `${request.protocol}//${auth}${request.hostname}${port ? `:${port}` : ""}${path}`; + const body = method === "GET" || method === "HEAD" ? void 0 : request.body; + const requestOptions = { + body, + headers: new Headers(request.headers), + method, + credentials + }; + if (this.config?.cache) { + requestOptions.cache = this.config.cache; + } + if (body) { + requestOptions.duplex = "half"; + } + if (typeof AbortController !== "undefined") { + requestOptions.signal = abortSignal; + } + if (keepAliveSupport.supported) { + requestOptions.keepalive = keepAlive; + } + if (typeof this.config.requestInit === "function") { + Object.assign(requestOptions, this.config.requestInit(request)); + } + let removeSignalEventListener = /* @__PURE__ */ __name(() => { + }, "removeSignalEventListener"); + const fetchRequest = createRequest(url, requestOptions); + const raceOfPromises = [ + fetch(fetchRequest).then((response) => { + const fetchHeaders = response.headers; + const transformedHeaders = {}; + for (const pair of fetchHeaders.entries()) { + transformedHeaders[pair[0]] = pair[1]; + } + const hasReadableStream = response.body != void 0; + if (!hasReadableStream) { + return response.blob().then((body2) => ({ + response: new import_protocol_http.HttpResponse({ + headers: transformedHeaders, + reason: response.statusText, + statusCode: response.status, + body: body2 + }) + })); + } + return { + response: new import_protocol_http.HttpResponse({ + headers: transformedHeaders, + reason: response.statusText, + statusCode: response.status, + body: response.body + }) + }; + }), + requestTimeout(requestTimeoutInMs) + ]; + if (abortSignal) { + raceOfPromises.push( + new Promise((resolve, reject) => { + const onAbort = /* @__PURE__ */ __name(() => { + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + }, "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + const signal = abortSignal; + signal.addEventListener("abort", onAbort, { once: true }); + removeSignalEventListener = /* @__PURE__ */ __name(() => signal.removeEventListener("abort", onAbort), "removeSignalEventListener"); + } else { + abortSignal.onabort = onAbort; + } + }) + ); + } + return Promise.race(raceOfPromises).finally(removeSignalEventListener); + } + updateHttpClientConfig(key, value) { + this.config = void 0; + this.configProvider = this.configProvider.then((config) => { + config[key] = value; + return config; + }); + } + httpHandlerConfigs() { + return this.config ?? {}; + } +}; + +// src/stream-collector.ts +var import_util_base64 = __nccwpck_require__(68385); +var streamCollector = /* @__PURE__ */ __name(async (stream) => { + if (typeof Blob === "function" && stream instanceof Blob || stream.constructor?.name === "Blob") { + if (Blob.prototype.arrayBuffer !== void 0) { + return new Uint8Array(await stream.arrayBuffer()); + } + return collectBlob(stream); + } + return collectStream(stream); +}, "streamCollector"); +async function collectBlob(blob) { + const base64 = await readToBase64(blob); + const arrayBuffer = (0, import_util_base64.fromBase64)(base64); + return new Uint8Array(arrayBuffer); +} +__name(collectBlob, "collectBlob"); +async function collectStream(stream) { + const chunks = []; + const reader = stream.getReader(); + let isDone = false; + let length = 0; + while (!isDone) { + const { done, value } = await reader.read(); + if (value) { + chunks.push(value); + length += value.length; + } + isDone = done; + } + const collected = new Uint8Array(length); + let offset = 0; + for (const chunk of chunks) { + collected.set(chunk, offset); + offset += chunk.length; + } + return collected; +} +__name(collectStream, "collectStream"); +function readToBase64(blob) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => { + if (reader.readyState !== 2) { + return reject(new Error("Reader aborted too early")); + } + const result = reader.result ?? ""; + const commaIndex = result.indexOf(","); + const dataOffset = commaIndex > -1 ? commaIndex + 1 : result.length; + resolve(result.substring(dataOffset)); + }; + reader.onabort = () => reject(new Error("Read aborted")); + reader.onerror = () => reject(reader.error); + reader.readAsDataURL(blob); + }); +} +__name(readToBase64, "readToBase64"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 5092: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Hash: () => Hash +}); +module.exports = __toCommonJS(src_exports); +var import_util_buffer_from = __nccwpck_require__(44151); +var import_util_utf8 = __nccwpck_require__(71577); +var import_buffer = __nccwpck_require__(20181); +var import_crypto = __nccwpck_require__(76982); +var Hash = class { + static { + __name(this, "Hash"); + } + constructor(algorithmIdentifier, secret) { + this.algorithmIdentifier = algorithmIdentifier; + this.secret = secret; + this.reset(); + } + update(toHash, encoding) { + this.hash.update((0, import_util_utf8.toUint8Array)(castSourceData(toHash, encoding))); + } + digest() { + return Promise.resolve(this.hash.digest()); + } + reset() { + this.hash = this.secret ? (0, import_crypto.createHmac)(this.algorithmIdentifier, castSourceData(this.secret)) : (0, import_crypto.createHash)(this.algorithmIdentifier); + } +}; +function castSourceData(toCast, encoding) { + if (import_buffer.Buffer.isBuffer(toCast)) { + return toCast; + } + if (typeof toCast === "string") { + return (0, import_util_buffer_from.fromString)(toCast, encoding); + } + if (ArrayBuffer.isView(toCast)) { + return (0, import_util_buffer_from.fromArrayBuffer)(toCast.buffer, toCast.byteOffset, toCast.byteLength); + } + return (0, import_util_buffer_from.fromArrayBuffer)(toCast); +} +__name(castSourceData, "castSourceData"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 45317: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fileStreamHasher: () => fileStreamHasher, + readableStreamHasher: () => readableStreamHasher +}); +module.exports = __toCommonJS(src_exports); + +// src/fileStreamHasher.ts +var import_fs = __nccwpck_require__(79896); + +// src/HashCalculator.ts +var import_util_utf8 = __nccwpck_require__(71577); +var import_stream = __nccwpck_require__(2203); +var HashCalculator = class extends import_stream.Writable { + constructor(hash, options) { + super(options); + this.hash = hash; + } + static { + __name(this, "HashCalculator"); + } + _write(chunk, encoding, callback) { + try { + this.hash.update((0, import_util_utf8.toUint8Array)(chunk)); + } catch (err) { + return callback(err); + } + callback(); + } +}; + +// src/fileStreamHasher.ts +var fileStreamHasher = /* @__PURE__ */ __name((hashCtor, fileStream) => new Promise((resolve, reject) => { + if (!isReadStream(fileStream)) { + reject(new Error("Unable to calculate hash for non-file streams.")); + return; + } + const fileStreamTee = (0, import_fs.createReadStream)(fileStream.path, { + start: fileStream.start, + end: fileStream.end + }); + const hash = new hashCtor(); + const hashCalculator = new HashCalculator(hash); + fileStreamTee.pipe(hashCalculator); + fileStreamTee.on("error", (err) => { + hashCalculator.end(); + reject(err); + }); + hashCalculator.on("error", reject); + hashCalculator.on("finish", function() { + hash.digest().then(resolve).catch(reject); + }); +}), "fileStreamHasher"); +var isReadStream = /* @__PURE__ */ __name((stream) => typeof stream.path === "string", "isReadStream"); + +// src/readableStreamHasher.ts +var readableStreamHasher = /* @__PURE__ */ __name((hashCtor, readableStream) => { + if (readableStream.readableFlowing !== null) { + throw new Error("Unable to calculate hash for flowing readable stream"); + } + const hash = new hashCtor(); + const hashCalculator = new HashCalculator(hash); + readableStream.pipe(hashCalculator); + return new Promise((resolve, reject) => { + readableStream.on("error", (err) => { + hashCalculator.end(); + reject(err); + }); + hashCalculator.on("error", reject); + hashCalculator.on("finish", () => { + hash.digest().then(resolve).catch(reject); + }); + }); +}, "readableStreamHasher"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 86130: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + isArrayBuffer: () => isArrayBuffer +}); +module.exports = __toCommonJS(src_exports); +var isArrayBuffer = /* @__PURE__ */ __name((arg) => typeof ArrayBuffer === "function" && arg instanceof ArrayBuffer || Object.prototype.toString.call(arg) === "[object ArrayBuffer]", "isArrayBuffer"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 47212: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + contentLengthMiddleware: () => contentLengthMiddleware, + contentLengthMiddlewareOptions: () => contentLengthMiddlewareOptions, + getContentLengthPlugin: () => getContentLengthPlugin +}); +module.exports = __toCommonJS(src_exports); +var import_protocol_http = __nccwpck_require__(72356); +var CONTENT_LENGTH_HEADER = "content-length"; +function contentLengthMiddleware(bodyLengthChecker) { + return (next) => async (args) => { + const request = args.request; + if (import_protocol_http.HttpRequest.isInstance(request)) { + const { body, headers } = request; + if (body && Object.keys(headers).map((str) => str.toLowerCase()).indexOf(CONTENT_LENGTH_HEADER) === -1) { + try { + const length = bodyLengthChecker(body); + request.headers = { + ...request.headers, + [CONTENT_LENGTH_HEADER]: String(length) + }; + } catch (error) { + } + } + } + return next({ + ...args, + request + }); + }; +} +__name(contentLengthMiddleware, "contentLengthMiddleware"); +var contentLengthMiddlewareOptions = { + step: "build", + tags: ["SET_CONTENT_LENGTH", "CONTENT_LENGTH"], + name: "contentLengthMiddleware", + override: true +}; +var getContentLengthPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: (clientStack) => { + clientStack.add(contentLengthMiddleware(options.bodyLengthChecker), contentLengthMiddlewareOptions); + } +}), "getContentLengthPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 76041: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getEndpointFromConfig = void 0; +const node_config_provider_1 = __nccwpck_require__(55704); +const getEndpointUrlConfig_1 = __nccwpck_require__(18008); +const getEndpointFromConfig = async (serviceId) => (0, node_config_provider_1.loadConfig)((0, getEndpointUrlConfig_1.getEndpointUrlConfig)(serviceId !== null && serviceId !== void 0 ? serviceId : ""))(); +exports.getEndpointFromConfig = getEndpointFromConfig; + + +/***/ }), + +/***/ 18008: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getEndpointUrlConfig = void 0; +const shared_ini_file_loader_1 = __nccwpck_require__(94964); +const ENV_ENDPOINT_URL = "AWS_ENDPOINT_URL"; +const CONFIG_ENDPOINT_URL = "endpoint_url"; +const getEndpointUrlConfig = (serviceId) => ({ + environmentVariableSelector: (env) => { + const serviceSuffixParts = serviceId.split(" ").map((w) => w.toUpperCase()); + const serviceEndpointUrl = env[[ENV_ENDPOINT_URL, ...serviceSuffixParts].join("_")]; + if (serviceEndpointUrl) + return serviceEndpointUrl; + const endpointUrl = env[ENV_ENDPOINT_URL]; + if (endpointUrl) + return endpointUrl; + return undefined; + }, + configFileSelector: (profile, config) => { + if (config && profile.services) { + const servicesSection = config[["services", profile.services].join(shared_ini_file_loader_1.CONFIG_PREFIX_SEPARATOR)]; + if (servicesSection) { + const servicePrefixParts = serviceId.split(" ").map((w) => w.toLowerCase()); + const endpointUrl = servicesSection[[servicePrefixParts.join("_"), CONFIG_ENDPOINT_URL].join(shared_ini_file_loader_1.CONFIG_PREFIX_SEPARATOR)]; + if (endpointUrl) + return endpointUrl; + } + } + const endpointUrl = profile[CONFIG_ENDPOINT_URL]; + if (endpointUrl) + return endpointUrl; + return undefined; + }, + default: undefined, +}); +exports.getEndpointUrlConfig = getEndpointUrlConfig; + + +/***/ }), + +/***/ 40099: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + endpointMiddleware: () => endpointMiddleware, + endpointMiddlewareOptions: () => endpointMiddlewareOptions, + getEndpointFromInstructions: () => getEndpointFromInstructions, + getEndpointPlugin: () => getEndpointPlugin, + resolveEndpointConfig: () => resolveEndpointConfig, + resolveEndpointRequiredConfig: () => resolveEndpointRequiredConfig, + resolveParams: () => resolveParams, + toEndpointV1: () => toEndpointV1 +}); +module.exports = __toCommonJS(src_exports); + +// src/service-customizations/s3.ts +var resolveParamsForS3 = /* @__PURE__ */ __name(async (endpointParams) => { + const bucket = endpointParams?.Bucket || ""; + if (typeof endpointParams.Bucket === "string") { + endpointParams.Bucket = bucket.replace(/#/g, encodeURIComponent("#")).replace(/\?/g, encodeURIComponent("?")); + } + if (isArnBucketName(bucket)) { + if (endpointParams.ForcePathStyle === true) { + throw new Error("Path-style addressing cannot be used with ARN buckets"); + } + } else if (!isDnsCompatibleBucketName(bucket) || bucket.indexOf(".") !== -1 && !String(endpointParams.Endpoint).startsWith("http:") || bucket.toLowerCase() !== bucket || bucket.length < 3) { + endpointParams.ForcePathStyle = true; + } + if (endpointParams.DisableMultiRegionAccessPoints) { + endpointParams.disableMultiRegionAccessPoints = true; + endpointParams.DisableMRAP = true; + } + return endpointParams; +}, "resolveParamsForS3"); +var DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/; +var IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/; +var DOTS_PATTERN = /\.\./; +var isDnsCompatibleBucketName = /* @__PURE__ */ __name((bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName), "isDnsCompatibleBucketName"); +var isArnBucketName = /* @__PURE__ */ __name((bucketName) => { + const [arn, partition, service, , , bucket] = bucketName.split(":"); + const isArn = arn === "arn" && bucketName.split(":").length >= 6; + const isValidArn = Boolean(isArn && partition && service && bucket); + if (isArn && !isValidArn) { + throw new Error(`Invalid ARN: ${bucketName} was an invalid ARN.`); + } + return isValidArn; +}, "isArnBucketName"); + +// src/adaptors/createConfigValueProvider.ts +var createConfigValueProvider = /* @__PURE__ */ __name((configKey, canonicalEndpointParamKey, config) => { + const configProvider = /* @__PURE__ */ __name(async () => { + const configValue = config[configKey] ?? config[canonicalEndpointParamKey]; + if (typeof configValue === "function") { + return configValue(); + } + return configValue; + }, "configProvider"); + if (configKey === "credentialScope" || canonicalEndpointParamKey === "CredentialScope") { + return async () => { + const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials; + const configValue = credentials?.credentialScope ?? credentials?.CredentialScope; + return configValue; + }; + } + if (configKey === "accountId" || canonicalEndpointParamKey === "AccountId") { + return async () => { + const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials; + const configValue = credentials?.accountId ?? credentials?.AccountId; + return configValue; + }; + } + if (configKey === "endpoint" || canonicalEndpointParamKey === "endpoint") { + return async () => { + if (config.isCustomEndpoint === false) { + return void 0; + } + const endpoint = await configProvider(); + if (endpoint && typeof endpoint === "object") { + if ("url" in endpoint) { + return endpoint.url.href; + } + if ("hostname" in endpoint) { + const { protocol, hostname, port, path } = endpoint; + return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`; + } + } + return endpoint; + }; + } + return configProvider; +}, "createConfigValueProvider"); + +// src/adaptors/getEndpointFromInstructions.ts +var import_getEndpointFromConfig = __nccwpck_require__(76041); + +// src/adaptors/toEndpointV1.ts +var import_url_parser = __nccwpck_require__(14494); +var toEndpointV1 = /* @__PURE__ */ __name((endpoint) => { + if (typeof endpoint === "object") { + if ("url" in endpoint) { + return (0, import_url_parser.parseUrl)(endpoint.url); + } + return endpoint; + } + return (0, import_url_parser.parseUrl)(endpoint); +}, "toEndpointV1"); + +// src/adaptors/getEndpointFromInstructions.ts +var getEndpointFromInstructions = /* @__PURE__ */ __name(async (commandInput, instructionsSupplier, clientConfig, context) => { + if (!clientConfig.isCustomEndpoint) { + let endpointFromConfig; + if (clientConfig.serviceConfiguredEndpoint) { + endpointFromConfig = await clientConfig.serviceConfiguredEndpoint(); + } else { + endpointFromConfig = await (0, import_getEndpointFromConfig.getEndpointFromConfig)(clientConfig.serviceId); + } + if (endpointFromConfig) { + clientConfig.endpoint = () => Promise.resolve(toEndpointV1(endpointFromConfig)); + clientConfig.isCustomEndpoint = true; + } + } + const endpointParams = await resolveParams(commandInput, instructionsSupplier, clientConfig); + if (typeof clientConfig.endpointProvider !== "function") { + throw new Error("config.endpointProvider is not set."); + } + const endpoint = clientConfig.endpointProvider(endpointParams, context); + return endpoint; +}, "getEndpointFromInstructions"); +var resolveParams = /* @__PURE__ */ __name(async (commandInput, instructionsSupplier, clientConfig) => { + const endpointParams = {}; + const instructions = instructionsSupplier?.getEndpointParameterInstructions?.() || {}; + for (const [name, instruction] of Object.entries(instructions)) { + switch (instruction.type) { + case "staticContextParams": + endpointParams[name] = instruction.value; + break; + case "contextParams": + endpointParams[name] = commandInput[instruction.name]; + break; + case "clientContextParams": + case "builtInParams": + endpointParams[name] = await createConfigValueProvider(instruction.name, name, clientConfig)(); + break; + case "operationContextParams": + endpointParams[name] = instruction.get(commandInput); + break; + default: + throw new Error("Unrecognized endpoint parameter instruction: " + JSON.stringify(instruction)); + } + } + if (Object.keys(instructions).length === 0) { + Object.assign(endpointParams, clientConfig); + } + if (String(clientConfig.serviceId).toLowerCase() === "s3") { + await resolveParamsForS3(endpointParams); + } + return endpointParams; +}, "resolveParams"); + +// src/endpointMiddleware.ts +var import_core = __nccwpck_require__(90402); +var import_util_middleware = __nccwpck_require__(76324); +var endpointMiddleware = /* @__PURE__ */ __name(({ + config, + instructions +}) => { + return (next, context) => async (args) => { + if (config.isCustomEndpoint) { + (0, import_core.setFeature)(context, "ENDPOINT_OVERRIDE", "N"); + } + const endpoint = await getEndpointFromInstructions( + args.input, + { + getEndpointParameterInstructions() { + return instructions; + } + }, + { ...config }, + context + ); + context.endpointV2 = endpoint; + context.authSchemes = endpoint.properties?.authSchemes; + const authScheme = context.authSchemes?.[0]; + if (authScheme) { + context["signing_region"] = authScheme.signingRegion; + context["signing_service"] = authScheme.signingName; + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const httpAuthOption = smithyContext?.selectedHttpAuthScheme?.httpAuthOption; + if (httpAuthOption) { + httpAuthOption.signingProperties = Object.assign( + httpAuthOption.signingProperties || {}, + { + signing_region: authScheme.signingRegion, + signingRegion: authScheme.signingRegion, + signing_service: authScheme.signingName, + signingName: authScheme.signingName, + signingRegionSet: authScheme.signingRegionSet + }, + authScheme.properties + ); + } + } + return next({ + ...args + }); + }; +}, "endpointMiddleware"); + +// src/getEndpointPlugin.ts +var import_middleware_serde = __nccwpck_require__(83255); +var endpointMiddlewareOptions = { + step: "serialize", + tags: ["ENDPOINT_PARAMETERS", "ENDPOINT_V2", "ENDPOINT"], + name: "endpointV2Middleware", + override: true, + relation: "before", + toMiddleware: import_middleware_serde.serializerMiddlewareOption.name +}; +var getEndpointPlugin = /* @__PURE__ */ __name((config, instructions) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo( + endpointMiddleware({ + config, + instructions + }), + endpointMiddlewareOptions + ); + } +}), "getEndpointPlugin"); + +// src/resolveEndpointConfig.ts + +var import_getEndpointFromConfig2 = __nccwpck_require__(76041); +var resolveEndpointConfig = /* @__PURE__ */ __name((input) => { + const tls = input.tls ?? true; + const { endpoint, useDualstackEndpoint, useFipsEndpoint } = input; + const customEndpointProvider = endpoint != null ? async () => toEndpointV1(await (0, import_util_middleware.normalizeProvider)(endpoint)()) : void 0; + const isCustomEndpoint = !!endpoint; + const resolvedConfig = Object.assign(input, { + endpoint: customEndpointProvider, + tls, + isCustomEndpoint, + useDualstackEndpoint: (0, import_util_middleware.normalizeProvider)(useDualstackEndpoint ?? false), + useFipsEndpoint: (0, import_util_middleware.normalizeProvider)(useFipsEndpoint ?? false) + }); + let configuredEndpointPromise = void 0; + resolvedConfig.serviceConfiguredEndpoint = async () => { + if (input.serviceId && !configuredEndpointPromise) { + configuredEndpointPromise = (0, import_getEndpointFromConfig2.getEndpointFromConfig)(input.serviceId); + } + return configuredEndpointPromise; + }; + return resolvedConfig; +}, "resolveEndpointConfig"); + +// src/resolveEndpointRequiredConfig.ts +var resolveEndpointRequiredConfig = /* @__PURE__ */ __name((input) => { + const { endpoint } = input; + if (endpoint === void 0) { + input.endpoint = async () => { + throw new Error( + "@smithy/middleware-endpoint: (default endpointRuleSet) endpoint is not set - you must configure an endpoint." + ); + }; + } + return input; +}, "resolveEndpointRequiredConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 19618: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + AdaptiveRetryStrategy: () => AdaptiveRetryStrategy, + CONFIG_MAX_ATTEMPTS: () => CONFIG_MAX_ATTEMPTS, + CONFIG_RETRY_MODE: () => CONFIG_RETRY_MODE, + ENV_MAX_ATTEMPTS: () => ENV_MAX_ATTEMPTS, + ENV_RETRY_MODE: () => ENV_RETRY_MODE, + NODE_MAX_ATTEMPT_CONFIG_OPTIONS: () => NODE_MAX_ATTEMPT_CONFIG_OPTIONS, + NODE_RETRY_MODE_CONFIG_OPTIONS: () => NODE_RETRY_MODE_CONFIG_OPTIONS, + StandardRetryStrategy: () => StandardRetryStrategy, + defaultDelayDecider: () => defaultDelayDecider, + defaultRetryDecider: () => defaultRetryDecider, + getOmitRetryHeadersPlugin: () => getOmitRetryHeadersPlugin, + getRetryAfterHint: () => getRetryAfterHint, + getRetryPlugin: () => getRetryPlugin, + omitRetryHeadersMiddleware: () => omitRetryHeadersMiddleware, + omitRetryHeadersMiddlewareOptions: () => omitRetryHeadersMiddlewareOptions, + resolveRetryConfig: () => resolveRetryConfig, + retryMiddleware: () => retryMiddleware, + retryMiddlewareOptions: () => retryMiddlewareOptions +}); +module.exports = __toCommonJS(src_exports); + +// src/AdaptiveRetryStrategy.ts + + +// src/StandardRetryStrategy.ts +var import_protocol_http = __nccwpck_require__(72356); + + +var import_uuid = __nccwpck_require__(12048); + +// src/defaultRetryQuota.ts +var import_util_retry = __nccwpck_require__(15518); +var getDefaultRetryQuota = /* @__PURE__ */ __name((initialRetryTokens, options) => { + const MAX_CAPACITY = initialRetryTokens; + const noRetryIncrement = options?.noRetryIncrement ?? import_util_retry.NO_RETRY_INCREMENT; + const retryCost = options?.retryCost ?? import_util_retry.RETRY_COST; + const timeoutRetryCost = options?.timeoutRetryCost ?? import_util_retry.TIMEOUT_RETRY_COST; + let availableCapacity = initialRetryTokens; + const getCapacityAmount = /* @__PURE__ */ __name((error) => error.name === "TimeoutError" ? timeoutRetryCost : retryCost, "getCapacityAmount"); + const hasRetryTokens = /* @__PURE__ */ __name((error) => getCapacityAmount(error) <= availableCapacity, "hasRetryTokens"); + const retrieveRetryTokens = /* @__PURE__ */ __name((error) => { + if (!hasRetryTokens(error)) { + throw new Error("No retry token available"); + } + const capacityAmount = getCapacityAmount(error); + availableCapacity -= capacityAmount; + return capacityAmount; + }, "retrieveRetryTokens"); + const releaseRetryTokens = /* @__PURE__ */ __name((capacityReleaseAmount) => { + availableCapacity += capacityReleaseAmount ?? noRetryIncrement; + availableCapacity = Math.min(availableCapacity, MAX_CAPACITY); + }, "releaseRetryTokens"); + return Object.freeze({ + hasRetryTokens, + retrieveRetryTokens, + releaseRetryTokens + }); +}, "getDefaultRetryQuota"); + +// src/delayDecider.ts + +var defaultDelayDecider = /* @__PURE__ */ __name((delayBase, attempts) => Math.floor(Math.min(import_util_retry.MAXIMUM_RETRY_DELAY, Math.random() * 2 ** attempts * delayBase)), "defaultDelayDecider"); + +// src/retryDecider.ts +var import_service_error_classification = __nccwpck_require__(42058); +var defaultRetryDecider = /* @__PURE__ */ __name((error) => { + if (!error) { + return false; + } + return (0, import_service_error_classification.isRetryableByTrait)(error) || (0, import_service_error_classification.isClockSkewError)(error) || (0, import_service_error_classification.isThrottlingError)(error) || (0, import_service_error_classification.isTransientError)(error); +}, "defaultRetryDecider"); + +// src/util.ts +var asSdkError = /* @__PURE__ */ __name((error) => { + if (error instanceof Error) + return error; + if (error instanceof Object) + return Object.assign(new Error(), error); + if (typeof error === "string") + return new Error(error); + return new Error(`AWS SDK error wrapper for ${error}`); +}, "asSdkError"); + +// src/StandardRetryStrategy.ts +var StandardRetryStrategy = class { + constructor(maxAttemptsProvider, options) { + this.maxAttemptsProvider = maxAttemptsProvider; + this.mode = import_util_retry.RETRY_MODES.STANDARD; + this.retryDecider = options?.retryDecider ?? defaultRetryDecider; + this.delayDecider = options?.delayDecider ?? defaultDelayDecider; + this.retryQuota = options?.retryQuota ?? getDefaultRetryQuota(import_util_retry.INITIAL_RETRY_TOKENS); + } + static { + __name(this, "StandardRetryStrategy"); + } + shouldRetry(error, attempts, maxAttempts) { + return attempts < maxAttempts && this.retryDecider(error) && this.retryQuota.hasRetryTokens(error); + } + async getMaxAttempts() { + let maxAttempts; + try { + maxAttempts = await this.maxAttemptsProvider(); + } catch (error) { + maxAttempts = import_util_retry.DEFAULT_MAX_ATTEMPTS; + } + return maxAttempts; + } + async retry(next, args, options) { + let retryTokenAmount; + let attempts = 0; + let totalDelay = 0; + const maxAttempts = await this.getMaxAttempts(); + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request)) { + request.headers[import_util_retry.INVOCATION_ID_HEADER] = (0, import_uuid.v4)(); + } + while (true) { + try { + if (import_protocol_http.HttpRequest.isInstance(request)) { + request.headers[import_util_retry.REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`; + } + if (options?.beforeRequest) { + await options.beforeRequest(); + } + const { response, output } = await next(args); + if (options?.afterRequest) { + options.afterRequest(response); + } + this.retryQuota.releaseRetryTokens(retryTokenAmount); + output.$metadata.attempts = attempts + 1; + output.$metadata.totalRetryDelay = totalDelay; + return { response, output }; + } catch (e) { + const err = asSdkError(e); + attempts++; + if (this.shouldRetry(err, attempts, maxAttempts)) { + retryTokenAmount = this.retryQuota.retrieveRetryTokens(err); + const delayFromDecider = this.delayDecider( + (0, import_service_error_classification.isThrottlingError)(err) ? import_util_retry.THROTTLING_RETRY_DELAY_BASE : import_util_retry.DEFAULT_RETRY_DELAY_BASE, + attempts + ); + const delayFromResponse = getDelayFromRetryAfterHeader(err.$response); + const delay = Math.max(delayFromResponse || 0, delayFromDecider); + totalDelay += delay; + await new Promise((resolve) => setTimeout(resolve, delay)); + continue; + } + if (!err.$metadata) { + err.$metadata = {}; + } + err.$metadata.attempts = attempts; + err.$metadata.totalRetryDelay = totalDelay; + throw err; + } + } + } +}; +var getDelayFromRetryAfterHeader = /* @__PURE__ */ __name((response) => { + if (!import_protocol_http.HttpResponse.isInstance(response)) + return; + const retryAfterHeaderName = Object.keys(response.headers).find((key) => key.toLowerCase() === "retry-after"); + if (!retryAfterHeaderName) + return; + const retryAfter = response.headers[retryAfterHeaderName]; + const retryAfterSeconds = Number(retryAfter); + if (!Number.isNaN(retryAfterSeconds)) + return retryAfterSeconds * 1e3; + const retryAfterDate = new Date(retryAfter); + return retryAfterDate.getTime() - Date.now(); +}, "getDelayFromRetryAfterHeader"); + +// src/AdaptiveRetryStrategy.ts +var AdaptiveRetryStrategy = class extends StandardRetryStrategy { + static { + __name(this, "AdaptiveRetryStrategy"); + } + constructor(maxAttemptsProvider, options) { + const { rateLimiter, ...superOptions } = options ?? {}; + super(maxAttemptsProvider, superOptions); + this.rateLimiter = rateLimiter ?? new import_util_retry.DefaultRateLimiter(); + this.mode = import_util_retry.RETRY_MODES.ADAPTIVE; + } + async retry(next, args) { + return super.retry(next, args, { + beforeRequest: async () => { + return this.rateLimiter.getSendToken(); + }, + afterRequest: (response) => { + this.rateLimiter.updateClientSendingRate(response); + } + }); + } +}; + +// src/configurations.ts +var import_util_middleware = __nccwpck_require__(76324); + +var ENV_MAX_ATTEMPTS = "AWS_MAX_ATTEMPTS"; +var CONFIG_MAX_ATTEMPTS = "max_attempts"; +var NODE_MAX_ATTEMPT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => { + const value = env[ENV_MAX_ATTEMPTS]; + if (!value) + return void 0; + const maxAttempt = parseInt(value); + if (Number.isNaN(maxAttempt)) { + throw new Error(`Environment variable ${ENV_MAX_ATTEMPTS} mast be a number, got "${value}"`); + } + return maxAttempt; + }, + configFileSelector: (profile) => { + const value = profile[CONFIG_MAX_ATTEMPTS]; + if (!value) + return void 0; + const maxAttempt = parseInt(value); + if (Number.isNaN(maxAttempt)) { + throw new Error(`Shared config file entry ${CONFIG_MAX_ATTEMPTS} mast be a number, got "${value}"`); + } + return maxAttempt; + }, + default: import_util_retry.DEFAULT_MAX_ATTEMPTS +}; +var resolveRetryConfig = /* @__PURE__ */ __name((input) => { + const { retryStrategy, retryMode: _retryMode, maxAttempts: _maxAttempts } = input; + const maxAttempts = (0, import_util_middleware.normalizeProvider)(_maxAttempts ?? import_util_retry.DEFAULT_MAX_ATTEMPTS); + return Object.assign(input, { + maxAttempts, + retryStrategy: async () => { + if (retryStrategy) { + return retryStrategy; + } + const retryMode = await (0, import_util_middleware.normalizeProvider)(_retryMode)(); + if (retryMode === import_util_retry.RETRY_MODES.ADAPTIVE) { + return new import_util_retry.AdaptiveRetryStrategy(maxAttempts); + } + return new import_util_retry.StandardRetryStrategy(maxAttempts); + } + }); +}, "resolveRetryConfig"); +var ENV_RETRY_MODE = "AWS_RETRY_MODE"; +var CONFIG_RETRY_MODE = "retry_mode"; +var NODE_RETRY_MODE_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[ENV_RETRY_MODE], + configFileSelector: (profile) => profile[CONFIG_RETRY_MODE], + default: import_util_retry.DEFAULT_RETRY_MODE +}; + +// src/omitRetryHeadersMiddleware.ts + + +var omitRetryHeadersMiddleware = /* @__PURE__ */ __name(() => (next) => async (args) => { + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request)) { + delete request.headers[import_util_retry.INVOCATION_ID_HEADER]; + delete request.headers[import_util_retry.REQUEST_HEADER]; + } + return next(args); +}, "omitRetryHeadersMiddleware"); +var omitRetryHeadersMiddlewareOptions = { + name: "omitRetryHeadersMiddleware", + tags: ["RETRY", "HEADERS", "OMIT_RETRY_HEADERS"], + relation: "before", + toMiddleware: "awsAuthMiddleware", + override: true +}; +var getOmitRetryHeadersPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo(omitRetryHeadersMiddleware(), omitRetryHeadersMiddlewareOptions); + } +}), "getOmitRetryHeadersPlugin"); + +// src/retryMiddleware.ts + + +var import_smithy_client = __nccwpck_require__(61411); + + +var import_isStreamingPayload = __nccwpck_require__(49831); +var retryMiddleware = /* @__PURE__ */ __name((options) => (next, context) => async (args) => { + let retryStrategy = await options.retryStrategy(); + const maxAttempts = await options.maxAttempts(); + if (isRetryStrategyV2(retryStrategy)) { + retryStrategy = retryStrategy; + let retryToken = await retryStrategy.acquireInitialRetryToken(context["partition_id"]); + let lastError = new Error(); + let attempts = 0; + let totalRetryDelay = 0; + const { request } = args; + const isRequest = import_protocol_http.HttpRequest.isInstance(request); + if (isRequest) { + request.headers[import_util_retry.INVOCATION_ID_HEADER] = (0, import_uuid.v4)(); + } + while (true) { + try { + if (isRequest) { + request.headers[import_util_retry.REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`; + } + const { response, output } = await next(args); + retryStrategy.recordSuccess(retryToken); + output.$metadata.attempts = attempts + 1; + output.$metadata.totalRetryDelay = totalRetryDelay; + return { response, output }; + } catch (e) { + const retryErrorInfo = getRetryErrorInfo(e); + lastError = asSdkError(e); + if (isRequest && (0, import_isStreamingPayload.isStreamingPayload)(request)) { + (context.logger instanceof import_smithy_client.NoOpLogger ? console : context.logger)?.warn( + "An error was encountered in a non-retryable streaming request." + ); + throw lastError; + } + try { + retryToken = await retryStrategy.refreshRetryTokenForRetry(retryToken, retryErrorInfo); + } catch (refreshError) { + if (!lastError.$metadata) { + lastError.$metadata = {}; + } + lastError.$metadata.attempts = attempts + 1; + lastError.$metadata.totalRetryDelay = totalRetryDelay; + throw lastError; + } + attempts = retryToken.getRetryCount(); + const delay = retryToken.getRetryDelay(); + totalRetryDelay += delay; + await new Promise((resolve) => setTimeout(resolve, delay)); + } + } + } else { + retryStrategy = retryStrategy; + if (retryStrategy?.mode) + context.userAgent = [...context.userAgent || [], ["cfg/retry-mode", retryStrategy.mode]]; + return retryStrategy.retry(next, args); + } +}, "retryMiddleware"); +var isRetryStrategyV2 = /* @__PURE__ */ __name((retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" && typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" && typeof retryStrategy.recordSuccess !== "undefined", "isRetryStrategyV2"); +var getRetryErrorInfo = /* @__PURE__ */ __name((error) => { + const errorInfo = { + error, + errorType: getRetryErrorType(error) + }; + const retryAfterHint = getRetryAfterHint(error.$response); + if (retryAfterHint) { + errorInfo.retryAfterHint = retryAfterHint; + } + return errorInfo; +}, "getRetryErrorInfo"); +var getRetryErrorType = /* @__PURE__ */ __name((error) => { + if ((0, import_service_error_classification.isThrottlingError)(error)) + return "THROTTLING"; + if ((0, import_service_error_classification.isTransientError)(error)) + return "TRANSIENT"; + if ((0, import_service_error_classification.isServerError)(error)) + return "SERVER_ERROR"; + return "CLIENT_ERROR"; +}, "getRetryErrorType"); +var retryMiddlewareOptions = { + name: "retryMiddleware", + tags: ["RETRY"], + step: "finalizeRequest", + priority: "high", + override: true +}; +var getRetryPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: (clientStack) => { + clientStack.add(retryMiddleware(options), retryMiddlewareOptions); + } +}), "getRetryPlugin"); +var getRetryAfterHint = /* @__PURE__ */ __name((response) => { + if (!import_protocol_http.HttpResponse.isInstance(response)) + return; + const retryAfterHeaderName = Object.keys(response.headers).find((key) => key.toLowerCase() === "retry-after"); + if (!retryAfterHeaderName) + return; + const retryAfter = response.headers[retryAfterHeaderName]; + const retryAfterSeconds = Number(retryAfter); + if (!Number.isNaN(retryAfterSeconds)) + return new Date(retryAfterSeconds * 1e3); + const retryAfterDate = new Date(retryAfter); + return retryAfterDate; +}, "getRetryAfterHint"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 49831: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isStreamingPayload = void 0; +const stream_1 = __nccwpck_require__(2203); +const isStreamingPayload = (request) => (request === null || request === void 0 ? void 0 : request.body) instanceof stream_1.Readable || + (typeof ReadableStream !== "undefined" && (request === null || request === void 0 ? void 0 : request.body) instanceof ReadableStream); +exports.isStreamingPayload = isStreamingPayload; + + +/***/ }), + +/***/ 83255: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + deserializerMiddleware: () => deserializerMiddleware, + deserializerMiddlewareOption: () => deserializerMiddlewareOption, + getSerdePlugin: () => getSerdePlugin, + serializerMiddleware: () => serializerMiddleware, + serializerMiddlewareOption: () => serializerMiddlewareOption +}); +module.exports = __toCommonJS(src_exports); + +// src/deserializerMiddleware.ts +var import_protocol_http = __nccwpck_require__(72356); +var deserializerMiddleware = /* @__PURE__ */ __name((options, deserializer) => (next, context) => async (args) => { + const { response } = await next(args); + try { + const parsed = await deserializer(response, options); + return { + response, + output: parsed + }; + } catch (error) { + Object.defineProperty(error, "$response", { + value: response + }); + if (!("$metadata" in error)) { + const hint = `Deserialization error: to see the raw response, inspect the hidden field {error}.$response on this object.`; + try { + error.message += "\n " + hint; + } catch (e) { + if (!context.logger || context.logger?.constructor?.name === "NoOpLogger") { + console.warn(hint); + } else { + context.logger?.warn?.(hint); + } + } + if (typeof error.$responseBodyText !== "undefined") { + if (error.$response) { + error.$response.body = error.$responseBodyText; + } + } + try { + if (import_protocol_http.HttpResponse.isInstance(response)) { + const { headers = {} } = response; + const headerEntries = Object.entries(headers); + error.$metadata = { + httpStatusCode: response.statusCode, + requestId: findHeader(/^x-[\w-]+-request-?id$/, headerEntries), + extendedRequestId: findHeader(/^x-[\w-]+-id-2$/, headerEntries), + cfId: findHeader(/^x-[\w-]+-cf-id$/, headerEntries) + }; + } + } catch (e) { + } + } + throw error; + } +}, "deserializerMiddleware"); +var findHeader = /* @__PURE__ */ __name((pattern, headers) => { + return (headers.find(([k]) => { + return k.match(pattern); + }) || [void 0, void 0])[1]; +}, "findHeader"); + +// src/serializerMiddleware.ts +var serializerMiddleware = /* @__PURE__ */ __name((options, serializer) => (next, context) => async (args) => { + const endpointConfig = options; + const endpoint = context.endpointV2?.url && endpointConfig.urlParser ? async () => endpointConfig.urlParser(context.endpointV2.url) : endpointConfig.endpoint; + if (!endpoint) { + throw new Error("No valid endpoint provider available."); + } + const request = await serializer(args.input, { ...options, endpoint }); + return next({ + ...args, + request + }); +}, "serializerMiddleware"); + +// src/serdePlugin.ts +var deserializerMiddlewareOption = { + name: "deserializerMiddleware", + step: "deserialize", + tags: ["DESERIALIZER"], + override: true +}; +var serializerMiddlewareOption = { + name: "serializerMiddleware", + step: "serialize", + tags: ["SERIALIZER"], + override: true +}; +function getSerdePlugin(config, serializer, deserializer) { + return { + applyToStack: (commandStack) => { + commandStack.add(deserializerMiddleware(config, deserializer), deserializerMiddlewareOption); + commandStack.add(serializerMiddleware(config, serializer), serializerMiddlewareOption); + } + }; +} +__name(getSerdePlugin, "getSerdePlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 9208: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + constructStack: () => constructStack +}); +module.exports = __toCommonJS(src_exports); + +// src/MiddlewareStack.ts +var getAllAliases = /* @__PURE__ */ __name((name, aliases) => { + const _aliases = []; + if (name) { + _aliases.push(name); + } + if (aliases) { + for (const alias of aliases) { + _aliases.push(alias); + } + } + return _aliases; +}, "getAllAliases"); +var getMiddlewareNameWithAliases = /* @__PURE__ */ __name((name, aliases) => { + return `${name || "anonymous"}${aliases && aliases.length > 0 ? ` (a.k.a. ${aliases.join(",")})` : ""}`; +}, "getMiddlewareNameWithAliases"); +var constructStack = /* @__PURE__ */ __name(() => { + let absoluteEntries = []; + let relativeEntries = []; + let identifyOnResolve = false; + const entriesNameSet = /* @__PURE__ */ new Set(); + const sort = /* @__PURE__ */ __name((entries) => entries.sort( + (a, b) => stepWeights[b.step] - stepWeights[a.step] || priorityWeights[b.priority || "normal"] - priorityWeights[a.priority || "normal"] + ), "sort"); + const removeByName = /* @__PURE__ */ __name((toRemove) => { + let isRemoved = false; + const filterCb = /* @__PURE__ */ __name((entry) => { + const aliases = getAllAliases(entry.name, entry.aliases); + if (aliases.includes(toRemove)) { + isRemoved = true; + for (const alias of aliases) { + entriesNameSet.delete(alias); + } + return false; + } + return true; + }, "filterCb"); + absoluteEntries = absoluteEntries.filter(filterCb); + relativeEntries = relativeEntries.filter(filterCb); + return isRemoved; + }, "removeByName"); + const removeByReference = /* @__PURE__ */ __name((toRemove) => { + let isRemoved = false; + const filterCb = /* @__PURE__ */ __name((entry) => { + if (entry.middleware === toRemove) { + isRemoved = true; + for (const alias of getAllAliases(entry.name, entry.aliases)) { + entriesNameSet.delete(alias); + } + return false; + } + return true; + }, "filterCb"); + absoluteEntries = absoluteEntries.filter(filterCb); + relativeEntries = relativeEntries.filter(filterCb); + return isRemoved; + }, "removeByReference"); + const cloneTo = /* @__PURE__ */ __name((toStack) => { + absoluteEntries.forEach((entry) => { + toStack.add(entry.middleware, { ...entry }); + }); + relativeEntries.forEach((entry) => { + toStack.addRelativeTo(entry.middleware, { ...entry }); + }); + toStack.identifyOnResolve?.(stack.identifyOnResolve()); + return toStack; + }, "cloneTo"); + const expandRelativeMiddlewareList = /* @__PURE__ */ __name((from) => { + const expandedMiddlewareList = []; + from.before.forEach((entry) => { + if (entry.before.length === 0 && entry.after.length === 0) { + expandedMiddlewareList.push(entry); + } else { + expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); + } + }); + expandedMiddlewareList.push(from); + from.after.reverse().forEach((entry) => { + if (entry.before.length === 0 && entry.after.length === 0) { + expandedMiddlewareList.push(entry); + } else { + expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); + } + }); + return expandedMiddlewareList; + }, "expandRelativeMiddlewareList"); + const getMiddlewareList = /* @__PURE__ */ __name((debug = false) => { + const normalizedAbsoluteEntries = []; + const normalizedRelativeEntries = []; + const normalizedEntriesNameMap = {}; + absoluteEntries.forEach((entry) => { + const normalizedEntry = { + ...entry, + before: [], + after: [] + }; + for (const alias of getAllAliases(normalizedEntry.name, normalizedEntry.aliases)) { + normalizedEntriesNameMap[alias] = normalizedEntry; + } + normalizedAbsoluteEntries.push(normalizedEntry); + }); + relativeEntries.forEach((entry) => { + const normalizedEntry = { + ...entry, + before: [], + after: [] + }; + for (const alias of getAllAliases(normalizedEntry.name, normalizedEntry.aliases)) { + normalizedEntriesNameMap[alias] = normalizedEntry; + } + normalizedRelativeEntries.push(normalizedEntry); + }); + normalizedRelativeEntries.forEach((entry) => { + if (entry.toMiddleware) { + const toMiddleware = normalizedEntriesNameMap[entry.toMiddleware]; + if (toMiddleware === void 0) { + if (debug) { + return; + } + throw new Error( + `${entry.toMiddleware} is not found when adding ${getMiddlewareNameWithAliases(entry.name, entry.aliases)} middleware ${entry.relation} ${entry.toMiddleware}` + ); + } + if (entry.relation === "after") { + toMiddleware.after.push(entry); + } + if (entry.relation === "before") { + toMiddleware.before.push(entry); + } + } + }); + const mainChain = sort(normalizedAbsoluteEntries).map(expandRelativeMiddlewareList).reduce( + (wholeList, expandedMiddlewareList) => { + wholeList.push(...expandedMiddlewareList); + return wholeList; + }, + [] + ); + return mainChain; + }, "getMiddlewareList"); + const stack = { + add: (middleware, options = {}) => { + const { name, override, aliases: _aliases } = options; + const entry = { + step: "initialize", + priority: "normal", + middleware, + ...options + }; + const aliases = getAllAliases(name, _aliases); + if (aliases.length > 0) { + if (aliases.some((alias) => entriesNameSet.has(alias))) { + if (!override) + throw new Error(`Duplicate middleware name '${getMiddlewareNameWithAliases(name, _aliases)}'`); + for (const alias of aliases) { + const toOverrideIndex = absoluteEntries.findIndex( + (entry2) => entry2.name === alias || entry2.aliases?.some((a) => a === alias) + ); + if (toOverrideIndex === -1) { + continue; + } + const toOverride = absoluteEntries[toOverrideIndex]; + if (toOverride.step !== entry.step || entry.priority !== toOverride.priority) { + throw new Error( + `"${getMiddlewareNameWithAliases(toOverride.name, toOverride.aliases)}" middleware with ${toOverride.priority} priority in ${toOverride.step} step cannot be overridden by "${getMiddlewareNameWithAliases(name, _aliases)}" middleware with ${entry.priority} priority in ${entry.step} step.` + ); + } + absoluteEntries.splice(toOverrideIndex, 1); + } + } + for (const alias of aliases) { + entriesNameSet.add(alias); + } + } + absoluteEntries.push(entry); + }, + addRelativeTo: (middleware, options) => { + const { name, override, aliases: _aliases } = options; + const entry = { + middleware, + ...options + }; + const aliases = getAllAliases(name, _aliases); + if (aliases.length > 0) { + if (aliases.some((alias) => entriesNameSet.has(alias))) { + if (!override) + throw new Error(`Duplicate middleware name '${getMiddlewareNameWithAliases(name, _aliases)}'`); + for (const alias of aliases) { + const toOverrideIndex = relativeEntries.findIndex( + (entry2) => entry2.name === alias || entry2.aliases?.some((a) => a === alias) + ); + if (toOverrideIndex === -1) { + continue; + } + const toOverride = relativeEntries[toOverrideIndex]; + if (toOverride.toMiddleware !== entry.toMiddleware || toOverride.relation !== entry.relation) { + throw new Error( + `"${getMiddlewareNameWithAliases(toOverride.name, toOverride.aliases)}" middleware ${toOverride.relation} "${toOverride.toMiddleware}" middleware cannot be overridden by "${getMiddlewareNameWithAliases(name, _aliases)}" middleware ${entry.relation} "${entry.toMiddleware}" middleware.` + ); + } + relativeEntries.splice(toOverrideIndex, 1); + } + } + for (const alias of aliases) { + entriesNameSet.add(alias); + } + } + relativeEntries.push(entry); + }, + clone: () => cloneTo(constructStack()), + use: (plugin) => { + plugin.applyToStack(stack); + }, + remove: (toRemove) => { + if (typeof toRemove === "string") + return removeByName(toRemove); + else + return removeByReference(toRemove); + }, + removeByTag: (toRemove) => { + let isRemoved = false; + const filterCb = /* @__PURE__ */ __name((entry) => { + const { tags, name, aliases: _aliases } = entry; + if (tags && tags.includes(toRemove)) { + const aliases = getAllAliases(name, _aliases); + for (const alias of aliases) { + entriesNameSet.delete(alias); + } + isRemoved = true; + return false; + } + return true; + }, "filterCb"); + absoluteEntries = absoluteEntries.filter(filterCb); + relativeEntries = relativeEntries.filter(filterCb); + return isRemoved; + }, + concat: (from) => { + const cloned = cloneTo(constructStack()); + cloned.use(from); + cloned.identifyOnResolve( + identifyOnResolve || cloned.identifyOnResolve() || (from.identifyOnResolve?.() ?? false) + ); + return cloned; + }, + applyToStack: cloneTo, + identify: () => { + return getMiddlewareList(true).map((mw) => { + const step = mw.step ?? mw.relation + " " + mw.toMiddleware; + return getMiddlewareNameWithAliases(mw.name, mw.aliases) + " - " + step; + }); + }, + identifyOnResolve(toggle) { + if (typeof toggle === "boolean") + identifyOnResolve = toggle; + return identifyOnResolve; + }, + resolve: (handler, context) => { + for (const middleware of getMiddlewareList().map((entry) => entry.middleware).reverse()) { + handler = middleware(handler, context); + } + if (identifyOnResolve) { + console.log(stack.identify()); + } + return handler; + } + }; + return stack; +}, "constructStack"); +var stepWeights = { + initialize: 5, + serialize: 4, + build: 3, + finalizeRequest: 2, + deserialize: 1 +}; +var priorityWeights = { + high: 3, + normal: 2, + low: 1 +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 55704: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + loadConfig: () => loadConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/configLoader.ts + + +// src/fromEnv.ts +var import_property_provider = __nccwpck_require__(71238); + +// src/getSelectorName.ts +function getSelectorName(functionString) { + try { + const constants = new Set(Array.from(functionString.match(/([A-Z_]){3,}/g) ?? [])); + constants.delete("CONFIG"); + constants.delete("CONFIG_PREFIX_SEPARATOR"); + constants.delete("ENV"); + return [...constants].join(", "); + } catch (e) { + return functionString; + } +} +__name(getSelectorName, "getSelectorName"); + +// src/fromEnv.ts +var fromEnv = /* @__PURE__ */ __name((envVarSelector, options) => async () => { + try { + const config = envVarSelector(process.env, options); + if (config === void 0) { + throw new Error(); + } + return config; + } catch (e) { + throw new import_property_provider.CredentialsProviderError( + e.message || `Not found in ENV: ${getSelectorName(envVarSelector.toString())}`, + { logger: options?.logger } + ); + } +}, "fromEnv"); + +// src/fromSharedConfigFiles.ts + +var import_shared_ini_file_loader = __nccwpck_require__(94964); +var fromSharedConfigFiles = /* @__PURE__ */ __name((configSelector, { preferredFile = "config", ...init } = {}) => async () => { + const profile = (0, import_shared_ini_file_loader.getProfileName)(init); + const { configFile, credentialsFile } = await (0, import_shared_ini_file_loader.loadSharedConfigFiles)(init); + const profileFromCredentials = credentialsFile[profile] || {}; + const profileFromConfig = configFile[profile] || {}; + const mergedProfile = preferredFile === "config" ? { ...profileFromCredentials, ...profileFromConfig } : { ...profileFromConfig, ...profileFromCredentials }; + try { + const cfgFile = preferredFile === "config" ? configFile : credentialsFile; + const configValue = configSelector(mergedProfile, cfgFile); + if (configValue === void 0) { + throw new Error(); + } + return configValue; + } catch (e) { + throw new import_property_provider.CredentialsProviderError( + e.message || `Not found in config files w/ profile [${profile}]: ${getSelectorName(configSelector.toString())}`, + { logger: init.logger } + ); + } +}, "fromSharedConfigFiles"); + +// src/fromStatic.ts + +var isFunction = /* @__PURE__ */ __name((func) => typeof func === "function", "isFunction"); +var fromStatic = /* @__PURE__ */ __name((defaultValue) => isFunction(defaultValue) ? async () => await defaultValue() : (0, import_property_provider.fromStatic)(defaultValue), "fromStatic"); + +// src/configLoader.ts +var loadConfig = /* @__PURE__ */ __name(({ environmentVariableSelector, configFileSelector, default: defaultValue }, configuration = {}) => { + const { signingName, logger } = configuration; + const envOptions = { signingName, logger }; + return (0, import_property_provider.memoize)( + (0, import_property_provider.chain)( + fromEnv(environmentVariableSelector, envOptions), + fromSharedConfigFiles(configFileSelector, configuration), + fromStatic(defaultValue) + ) + ); +}, "loadConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 61279: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + DEFAULT_REQUEST_TIMEOUT: () => DEFAULT_REQUEST_TIMEOUT, + NodeHttp2Handler: () => NodeHttp2Handler, + NodeHttpHandler: () => NodeHttpHandler, + streamCollector: () => streamCollector +}); +module.exports = __toCommonJS(src_exports); + +// src/node-http-handler.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_querystring_builder = __nccwpck_require__(18256); +var import_http = __nccwpck_require__(58611); +var import_https = __nccwpck_require__(65692); + +// src/constants.ts +var NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "EPIPE", "ETIMEDOUT"]; + +// src/get-transformed-headers.ts +var getTransformedHeaders = /* @__PURE__ */ __name((headers) => { + const transformedHeaders = {}; + for (const name of Object.keys(headers)) { + const headerValues = headers[name]; + transformedHeaders[name] = Array.isArray(headerValues) ? headerValues.join(",") : headerValues; + } + return transformedHeaders; +}, "getTransformedHeaders"); + +// src/timing.ts +var timing = { + setTimeout: (cb, ms) => setTimeout(cb, ms), + clearTimeout: (timeoutId) => clearTimeout(timeoutId) +}; + +// src/set-connection-timeout.ts +var DEFER_EVENT_LISTENER_TIME = 1e3; +var setConnectionTimeout = /* @__PURE__ */ __name((request, reject, timeoutInMs = 0) => { + if (!timeoutInMs) { + return -1; + } + const registerTimeout = /* @__PURE__ */ __name((offset) => { + const timeoutId = timing.setTimeout(() => { + request.destroy(); + reject( + Object.assign(new Error(`Socket timed out without establishing a connection within ${timeoutInMs} ms`), { + name: "TimeoutError" + }) + ); + }, timeoutInMs - offset); + const doWithSocket = /* @__PURE__ */ __name((socket) => { + if (socket?.connecting) { + socket.on("connect", () => { + timing.clearTimeout(timeoutId); + }); + } else { + timing.clearTimeout(timeoutId); + } + }, "doWithSocket"); + if (request.socket) { + doWithSocket(request.socket); + } else { + request.on("socket", doWithSocket); + } + }, "registerTimeout"); + if (timeoutInMs < 2e3) { + registerTimeout(0); + return 0; + } + return timing.setTimeout(registerTimeout.bind(null, DEFER_EVENT_LISTENER_TIME), DEFER_EVENT_LISTENER_TIME); +}, "setConnectionTimeout"); + +// src/set-socket-keep-alive.ts +var DEFER_EVENT_LISTENER_TIME2 = 3e3; +var setSocketKeepAlive = /* @__PURE__ */ __name((request, { keepAlive, keepAliveMsecs }, deferTimeMs = DEFER_EVENT_LISTENER_TIME2) => { + if (keepAlive !== true) { + return -1; + } + const registerListener = /* @__PURE__ */ __name(() => { + if (request.socket) { + request.socket.setKeepAlive(keepAlive, keepAliveMsecs || 0); + } else { + request.on("socket", (socket) => { + socket.setKeepAlive(keepAlive, keepAliveMsecs || 0); + }); + } + }, "registerListener"); + if (deferTimeMs === 0) { + registerListener(); + return 0; + } + return timing.setTimeout(registerListener, deferTimeMs); +}, "setSocketKeepAlive"); + +// src/set-socket-timeout.ts +var DEFER_EVENT_LISTENER_TIME3 = 3e3; +var setSocketTimeout = /* @__PURE__ */ __name((request, reject, timeoutInMs = DEFAULT_REQUEST_TIMEOUT) => { + const registerTimeout = /* @__PURE__ */ __name((offset) => { + const timeout = timeoutInMs - offset; + const onTimeout = /* @__PURE__ */ __name(() => { + request.destroy(); + reject(Object.assign(new Error(`Connection timed out after ${timeoutInMs} ms`), { name: "TimeoutError" })); + }, "onTimeout"); + if (request.socket) { + request.socket.setTimeout(timeout, onTimeout); + request.on("close", () => request.socket?.removeListener("timeout", onTimeout)); + } else { + request.setTimeout(timeout, onTimeout); + } + }, "registerTimeout"); + if (0 < timeoutInMs && timeoutInMs < 6e3) { + registerTimeout(0); + return 0; + } + return timing.setTimeout( + registerTimeout.bind(null, timeoutInMs === 0 ? 0 : DEFER_EVENT_LISTENER_TIME3), + DEFER_EVENT_LISTENER_TIME3 + ); +}, "setSocketTimeout"); + +// src/write-request-body.ts +var import_stream = __nccwpck_require__(2203); +var MIN_WAIT_TIME = 6e3; +async function writeRequestBody(httpRequest, request, maxContinueTimeoutMs = MIN_WAIT_TIME) { + const headers = request.headers ?? {}; + const expect = headers["Expect"] || headers["expect"]; + let timeoutId = -1; + let sendBody = true; + if (expect === "100-continue") { + sendBody = await Promise.race([ + new Promise((resolve) => { + timeoutId = Number(timing.setTimeout(() => resolve(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs))); + }), + new Promise((resolve) => { + httpRequest.on("continue", () => { + timing.clearTimeout(timeoutId); + resolve(true); + }); + httpRequest.on("response", () => { + timing.clearTimeout(timeoutId); + resolve(false); + }); + httpRequest.on("error", () => { + timing.clearTimeout(timeoutId); + resolve(false); + }); + }) + ]); + } + if (sendBody) { + writeBody(httpRequest, request.body); + } +} +__name(writeRequestBody, "writeRequestBody"); +function writeBody(httpRequest, body) { + if (body instanceof import_stream.Readable) { + body.pipe(httpRequest); + return; + } + if (body) { + if (Buffer.isBuffer(body) || typeof body === "string") { + httpRequest.end(body); + return; + } + const uint8 = body; + if (typeof uint8 === "object" && uint8.buffer && typeof uint8.byteOffset === "number" && typeof uint8.byteLength === "number") { + httpRequest.end(Buffer.from(uint8.buffer, uint8.byteOffset, uint8.byteLength)); + return; + } + httpRequest.end(Buffer.from(body)); + return; + } + httpRequest.end(); +} +__name(writeBody, "writeBody"); + +// src/node-http-handler.ts +var DEFAULT_REQUEST_TIMEOUT = 0; +var NodeHttpHandler = class _NodeHttpHandler { + constructor(options) { + this.socketWarningTimestamp = 0; + // Node http handler is hard-coded to http/1.1: https://github.com/nodejs/node/blob/ff5664b83b89c55e4ab5d5f60068fb457f1f5872/lib/_http_server.js#L286 + this.metadata = { handlerProtocol: "http/1.1" }; + this.configProvider = new Promise((resolve, reject) => { + if (typeof options === "function") { + options().then((_options) => { + resolve(this.resolveDefaultConfig(_options)); + }).catch(reject); + } else { + resolve(this.resolveDefaultConfig(options)); + } + }); + } + static { + __name(this, "NodeHttpHandler"); + } + /** + * @returns the input if it is an HttpHandler of any class, + * or instantiates a new instance of this handler. + */ + static create(instanceOrOptions) { + if (typeof instanceOrOptions?.handle === "function") { + return instanceOrOptions; + } + return new _NodeHttpHandler(instanceOrOptions); + } + /** + * @internal + * + * @param agent - http(s) agent in use by the NodeHttpHandler instance. + * @param socketWarningTimestamp - last socket usage check timestamp. + * @param logger - channel for the warning. + * @returns timestamp of last emitted warning. + */ + static checkSocketUsage(agent, socketWarningTimestamp, logger = console) { + const { sockets, requests, maxSockets } = agent; + if (typeof maxSockets !== "number" || maxSockets === Infinity) { + return socketWarningTimestamp; + } + const interval = 15e3; + if (Date.now() - interval < socketWarningTimestamp) { + return socketWarningTimestamp; + } + if (sockets && requests) { + for (const origin in sockets) { + const socketsInUse = sockets[origin]?.length ?? 0; + const requestsEnqueued = requests[origin]?.length ?? 0; + if (socketsInUse >= maxSockets && requestsEnqueued >= 2 * maxSockets) { + logger?.warn?.( + `@smithy/node-http-handler:WARN - socket usage at capacity=${socketsInUse} and ${requestsEnqueued} additional requests are enqueued. +See https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html +or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler config.` + ); + return Date.now(); + } + } + } + return socketWarningTimestamp; + } + resolveDefaultConfig(options) { + const { requestTimeout, connectionTimeout, socketTimeout, socketAcquisitionWarningTimeout, httpAgent, httpsAgent } = options || {}; + const keepAlive = true; + const maxSockets = 50; + return { + connectionTimeout, + requestTimeout: requestTimeout ?? socketTimeout, + socketAcquisitionWarningTimeout, + httpAgent: (() => { + if (httpAgent instanceof import_http.Agent || typeof httpAgent?.destroy === "function") { + return httpAgent; + } + return new import_http.Agent({ keepAlive, maxSockets, ...httpAgent }); + })(), + httpsAgent: (() => { + if (httpsAgent instanceof import_https.Agent || typeof httpsAgent?.destroy === "function") { + return httpsAgent; + } + return new import_https.Agent({ keepAlive, maxSockets, ...httpsAgent }); + })(), + logger: console + }; + } + destroy() { + this.config?.httpAgent?.destroy(); + this.config?.httpsAgent?.destroy(); + } + async handle(request, { abortSignal, requestTimeout } = {}) { + if (!this.config) { + this.config = await this.configProvider; + } + return new Promise((_resolve, _reject) => { + let writeRequestBodyPromise = void 0; + const timeouts = []; + const resolve = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + timeouts.forEach(timing.clearTimeout); + _resolve(arg); + }, "resolve"); + const reject = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + timeouts.forEach(timing.clearTimeout); + _reject(arg); + }, "reject"); + if (!this.config) { + throw new Error("Node HTTP request handler config is not resolved"); + } + if (abortSignal?.aborted) { + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + return; + } + const isSSL = request.protocol === "https:"; + const agent = isSSL ? this.config.httpsAgent : this.config.httpAgent; + timeouts.push( + timing.setTimeout( + () => { + this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage( + agent, + this.socketWarningTimestamp, + this.config.logger + ); + }, + this.config.socketAcquisitionWarningTimeout ?? (this.config.requestTimeout ?? 2e3) + (this.config.connectionTimeout ?? 1e3) + ) + ); + const queryString = (0, import_querystring_builder.buildQueryString)(request.query || {}); + let auth = void 0; + if (request.username != null || request.password != null) { + const username = request.username ?? ""; + const password = request.password ?? ""; + auth = `${username}:${password}`; + } + let path = request.path; + if (queryString) { + path += `?${queryString}`; + } + if (request.fragment) { + path += `#${request.fragment}`; + } + let hostname = request.hostname ?? ""; + if (hostname[0] === "[" && hostname.endsWith("]")) { + hostname = request.hostname.slice(1, -1); + } else { + hostname = request.hostname; + } + const nodeHttpsOptions = { + headers: request.headers, + host: hostname, + method: request.method, + path, + port: request.port, + agent, + auth + }; + const requestFunc = isSSL ? import_https.request : import_http.request; + const req = requestFunc(nodeHttpsOptions, (res) => { + const httpResponse = new import_protocol_http.HttpResponse({ + statusCode: res.statusCode || -1, + reason: res.statusMessage, + headers: getTransformedHeaders(res.headers), + body: res + }); + resolve({ response: httpResponse }); + }); + req.on("error", (err) => { + if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) { + reject(Object.assign(err, { name: "TimeoutError" })); + } else { + reject(err); + } + }); + if (abortSignal) { + const onAbort = /* @__PURE__ */ __name(() => { + req.destroy(); + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + }, "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + const signal = abortSignal; + signal.addEventListener("abort", onAbort, { once: true }); + req.once("close", () => signal.removeEventListener("abort", onAbort)); + } else { + abortSignal.onabort = onAbort; + } + } + const effectiveRequestTimeout = requestTimeout ?? this.config.requestTimeout; + timeouts.push(setConnectionTimeout(req, reject, this.config.connectionTimeout)); + timeouts.push(setSocketTimeout(req, reject, effectiveRequestTimeout)); + const httpAgent = nodeHttpsOptions.agent; + if (typeof httpAgent === "object" && "keepAlive" in httpAgent) { + timeouts.push( + setSocketKeepAlive(req, { + // @ts-expect-error keepAlive is not public on httpAgent. + keepAlive: httpAgent.keepAlive, + // @ts-expect-error keepAliveMsecs is not public on httpAgent. + keepAliveMsecs: httpAgent.keepAliveMsecs + }) + ); + } + writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout).catch((e) => { + timeouts.forEach(timing.clearTimeout); + return _reject(e); + }); + }); + } + updateHttpClientConfig(key, value) { + this.config = void 0; + this.configProvider = this.configProvider.then((config) => { + return { + ...config, + [key]: value + }; + }); + } + httpHandlerConfigs() { + return this.config ?? {}; + } +}; + +// src/node-http2-handler.ts + + +var import_http22 = __nccwpck_require__(85675); + +// src/node-http2-connection-manager.ts +var import_http2 = __toESM(__nccwpck_require__(85675)); + +// src/node-http2-connection-pool.ts +var NodeHttp2ConnectionPool = class { + constructor(sessions) { + this.sessions = []; + this.sessions = sessions ?? []; + } + static { + __name(this, "NodeHttp2ConnectionPool"); + } + poll() { + if (this.sessions.length > 0) { + return this.sessions.shift(); + } + } + offerLast(session) { + this.sessions.push(session); + } + contains(session) { + return this.sessions.includes(session); + } + remove(session) { + this.sessions = this.sessions.filter((s) => s !== session); + } + [Symbol.iterator]() { + return this.sessions[Symbol.iterator](); + } + destroy(connection) { + for (const session of this.sessions) { + if (session === connection) { + if (!session.destroyed) { + session.destroy(); + } + } + } + } +}; + +// src/node-http2-connection-manager.ts +var NodeHttp2ConnectionManager = class { + constructor(config) { + this.sessionCache = /* @__PURE__ */ new Map(); + this.config = config; + if (this.config.maxConcurrency && this.config.maxConcurrency <= 0) { + throw new RangeError("maxConcurrency must be greater than zero."); + } + } + static { + __name(this, "NodeHttp2ConnectionManager"); + } + lease(requestContext, connectionConfiguration) { + const url = this.getUrlString(requestContext); + const existingPool = this.sessionCache.get(url); + if (existingPool) { + const existingSession = existingPool.poll(); + if (existingSession && !this.config.disableConcurrency) { + return existingSession; + } + } + const session = import_http2.default.connect(url); + if (this.config.maxConcurrency) { + session.settings({ maxConcurrentStreams: this.config.maxConcurrency }, (err) => { + if (err) { + throw new Error( + "Fail to set maxConcurrentStreams to " + this.config.maxConcurrency + "when creating new session for " + requestContext.destination.toString() + ); + } + }); + } + session.unref(); + const destroySessionCb = /* @__PURE__ */ __name(() => { + session.destroy(); + this.deleteSession(url, session); + }, "destroySessionCb"); + session.on("goaway", destroySessionCb); + session.on("error", destroySessionCb); + session.on("frameError", destroySessionCb); + session.on("close", () => this.deleteSession(url, session)); + if (connectionConfiguration.requestTimeout) { + session.setTimeout(connectionConfiguration.requestTimeout, destroySessionCb); + } + const connectionPool = this.sessionCache.get(url) || new NodeHttp2ConnectionPool(); + connectionPool.offerLast(session); + this.sessionCache.set(url, connectionPool); + return session; + } + /** + * Delete a session from the connection pool. + * @param authority The authority of the session to delete. + * @param session The session to delete. + */ + deleteSession(authority, session) { + const existingConnectionPool = this.sessionCache.get(authority); + if (!existingConnectionPool) { + return; + } + if (!existingConnectionPool.contains(session)) { + return; + } + existingConnectionPool.remove(session); + this.sessionCache.set(authority, existingConnectionPool); + } + release(requestContext, session) { + const cacheKey = this.getUrlString(requestContext); + this.sessionCache.get(cacheKey)?.offerLast(session); + } + destroy() { + for (const [key, connectionPool] of this.sessionCache) { + for (const session of connectionPool) { + if (!session.destroyed) { + session.destroy(); + } + connectionPool.remove(session); + } + this.sessionCache.delete(key); + } + } + setMaxConcurrentStreams(maxConcurrentStreams) { + if (maxConcurrentStreams && maxConcurrentStreams <= 0) { + throw new RangeError("maxConcurrentStreams must be greater than zero."); + } + this.config.maxConcurrency = maxConcurrentStreams; + } + setDisableConcurrentStreams(disableConcurrentStreams) { + this.config.disableConcurrency = disableConcurrentStreams; + } + getUrlString(request) { + return request.destination.toString(); + } +}; + +// src/node-http2-handler.ts +var NodeHttp2Handler = class _NodeHttp2Handler { + constructor(options) { + this.metadata = { handlerProtocol: "h2" }; + this.connectionManager = new NodeHttp2ConnectionManager({}); + this.configProvider = new Promise((resolve, reject) => { + if (typeof options === "function") { + options().then((opts) => { + resolve(opts || {}); + }).catch(reject); + } else { + resolve(options || {}); + } + }); + } + static { + __name(this, "NodeHttp2Handler"); + } + /** + * @returns the input if it is an HttpHandler of any class, + * or instantiates a new instance of this handler. + */ + static create(instanceOrOptions) { + if (typeof instanceOrOptions?.handle === "function") { + return instanceOrOptions; + } + return new _NodeHttp2Handler(instanceOrOptions); + } + destroy() { + this.connectionManager.destroy(); + } + async handle(request, { abortSignal, requestTimeout } = {}) { + if (!this.config) { + this.config = await this.configProvider; + this.connectionManager.setDisableConcurrentStreams(this.config.disableConcurrentStreams || false); + if (this.config.maxConcurrentStreams) { + this.connectionManager.setMaxConcurrentStreams(this.config.maxConcurrentStreams); + } + } + const { requestTimeout: configRequestTimeout, disableConcurrentStreams } = this.config; + const effectiveRequestTimeout = requestTimeout ?? configRequestTimeout; + return new Promise((_resolve, _reject) => { + let fulfilled = false; + let writeRequestBodyPromise = void 0; + const resolve = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + _resolve(arg); + }, "resolve"); + const reject = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + _reject(arg); + }, "reject"); + if (abortSignal?.aborted) { + fulfilled = true; + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + return; + } + const { hostname, method, port, protocol, query } = request; + let auth = ""; + if (request.username != null || request.password != null) { + const username = request.username ?? ""; + const password = request.password ?? ""; + auth = `${username}:${password}@`; + } + const authority = `${protocol}//${auth}${hostname}${port ? `:${port}` : ""}`; + const requestContext = { destination: new URL(authority) }; + const session = this.connectionManager.lease(requestContext, { + requestTimeout: this.config?.sessionTimeout, + disableConcurrentStreams: disableConcurrentStreams || false + }); + const rejectWithDestroy = /* @__PURE__ */ __name((err) => { + if (disableConcurrentStreams) { + this.destroySession(session); + } + fulfilled = true; + reject(err); + }, "rejectWithDestroy"); + const queryString = (0, import_querystring_builder.buildQueryString)(query || {}); + let path = request.path; + if (queryString) { + path += `?${queryString}`; + } + if (request.fragment) { + path += `#${request.fragment}`; + } + const req = session.request({ + ...request.headers, + [import_http22.constants.HTTP2_HEADER_PATH]: path, + [import_http22.constants.HTTP2_HEADER_METHOD]: method + }); + session.ref(); + req.on("response", (headers) => { + const httpResponse = new import_protocol_http.HttpResponse({ + statusCode: headers[":status"] || -1, + headers: getTransformedHeaders(headers), + body: req + }); + fulfilled = true; + resolve({ response: httpResponse }); + if (disableConcurrentStreams) { + session.close(); + this.connectionManager.deleteSession(authority, session); + } + }); + if (effectiveRequestTimeout) { + req.setTimeout(effectiveRequestTimeout, () => { + req.close(); + const timeoutError = new Error(`Stream timed out because of no activity for ${effectiveRequestTimeout} ms`); + timeoutError.name = "TimeoutError"; + rejectWithDestroy(timeoutError); + }); + } + if (abortSignal) { + const onAbort = /* @__PURE__ */ __name(() => { + req.close(); + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + rejectWithDestroy(abortError); + }, "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + const signal = abortSignal; + signal.addEventListener("abort", onAbort, { once: true }); + req.once("close", () => signal.removeEventListener("abort", onAbort)); + } else { + abortSignal.onabort = onAbort; + } + } + req.on("frameError", (type, code, id) => { + rejectWithDestroy(new Error(`Frame type id ${type} in stream id ${id} has failed with code ${code}.`)); + }); + req.on("error", rejectWithDestroy); + req.on("aborted", () => { + rejectWithDestroy( + new Error(`HTTP/2 stream is abnormally aborted in mid-communication with result code ${req.rstCode}.`) + ); + }); + req.on("close", () => { + session.unref(); + if (disableConcurrentStreams) { + session.destroy(); + } + if (!fulfilled) { + rejectWithDestroy(new Error("Unexpected error: http2 request did not get a response")); + } + }); + writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout); + }); + } + updateHttpClientConfig(key, value) { + this.config = void 0; + this.configProvider = this.configProvider.then((config) => { + return { + ...config, + [key]: value + }; + }); + } + httpHandlerConfigs() { + return this.config ?? {}; + } + /** + * Destroys a session. + * @param session - the session to destroy. + */ + destroySession(session) { + if (!session.destroyed) { + session.destroy(); + } + } +}; + +// src/stream-collector/collector.ts + +var Collector = class extends import_stream.Writable { + constructor() { + super(...arguments); + this.bufferedBytes = []; + } + static { + __name(this, "Collector"); + } + _write(chunk, encoding, callback) { + this.bufferedBytes.push(chunk); + callback(); + } +}; + +// src/stream-collector/index.ts +var streamCollector = /* @__PURE__ */ __name((stream) => { + if (isReadableStreamInstance(stream)) { + return collectReadableStream(stream); + } + return new Promise((resolve, reject) => { + const collector = new Collector(); + stream.pipe(collector); + stream.on("error", (err) => { + collector.end(); + reject(err); + }); + collector.on("error", reject); + collector.on("finish", function() { + const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes)); + resolve(bytes); + }); + }); +}, "streamCollector"); +var isReadableStreamInstance = /* @__PURE__ */ __name((stream) => typeof ReadableStream === "function" && stream instanceof ReadableStream, "isReadableStreamInstance"); +async function collectReadableStream(stream) { + const chunks = []; + const reader = stream.getReader(); + let isDone = false; + let length = 0; + while (!isDone) { + const { done, value } = await reader.read(); + if (value) { + chunks.push(value); + length += value.length; + } + isDone = done; + } + const collected = new Uint8Array(length); + let offset = 0; + for (const chunk of chunks) { + collected.set(chunk, offset); + offset += chunk.length; + } + return collected; +} +__name(collectReadableStream, "collectReadableStream"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 71238: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + CredentialsProviderError: () => CredentialsProviderError, + ProviderError: () => ProviderError, + TokenProviderError: () => TokenProviderError, + chain: () => chain, + fromStatic: () => fromStatic, + memoize: () => memoize +}); +module.exports = __toCommonJS(src_exports); + +// src/ProviderError.ts +var ProviderError = class _ProviderError extends Error { + constructor(message, options = true) { + let logger; + let tryNextLink = true; + if (typeof options === "boolean") { + logger = void 0; + tryNextLink = options; + } else if (options != null && typeof options === "object") { + logger = options.logger; + tryNextLink = options.tryNextLink ?? true; + } + super(message); + this.name = "ProviderError"; + this.tryNextLink = tryNextLink; + Object.setPrototypeOf(this, _ProviderError.prototype); + logger?.debug?.(`@smithy/property-provider ${tryNextLink ? "->" : "(!)"} ${message}`); + } + static { + __name(this, "ProviderError"); + } + /** + * @deprecated use new operator. + */ + static from(error, options = true) { + return Object.assign(new this(error.message, options), error); + } +}; + +// src/CredentialsProviderError.ts +var CredentialsProviderError = class _CredentialsProviderError extends ProviderError { + /** + * @override + */ + constructor(message, options = true) { + super(message, options); + this.name = "CredentialsProviderError"; + Object.setPrototypeOf(this, _CredentialsProviderError.prototype); + } + static { + __name(this, "CredentialsProviderError"); + } +}; + +// src/TokenProviderError.ts +var TokenProviderError = class _TokenProviderError extends ProviderError { + /** + * @override + */ + constructor(message, options = true) { + super(message, options); + this.name = "TokenProviderError"; + Object.setPrototypeOf(this, _TokenProviderError.prototype); + } + static { + __name(this, "TokenProviderError"); + } +}; + +// src/chain.ts +var chain = /* @__PURE__ */ __name((...providers) => async () => { + if (providers.length === 0) { + throw new ProviderError("No providers in chain"); + } + let lastProviderError; + for (const provider of providers) { + try { + const credentials = await provider(); + return credentials; + } catch (err) { + lastProviderError = err; + if (err?.tryNextLink) { + continue; + } + throw err; + } + } + throw lastProviderError; +}, "chain"); + +// src/fromStatic.ts +var fromStatic = /* @__PURE__ */ __name((staticValue) => () => Promise.resolve(staticValue), "fromStatic"); + +// src/memoize.ts +var memoize = /* @__PURE__ */ __name((provider, isExpired, requiresRefresh) => { + let resolved; + let pending; + let hasResult; + let isConstant = false; + const coalesceProvider = /* @__PURE__ */ __name(async () => { + if (!pending) { + pending = provider(); + } + try { + resolved = await pending; + hasResult = true; + isConstant = false; + } finally { + pending = void 0; + } + return resolved; + }, "coalesceProvider"); + if (isExpired === void 0) { + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(); + } + return resolved; + }; + } + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(); + } + if (isConstant) { + return resolved; + } + if (requiresRefresh && !requiresRefresh(resolved)) { + isConstant = true; + return resolved; + } + if (isExpired(resolved)) { + await coalesceProvider(); + return resolved; + } + return resolved; + }; +}, "memoize"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 72356: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Field: () => Field, + Fields: () => Fields, + HttpRequest: () => HttpRequest, + HttpResponse: () => HttpResponse, + IHttpRequest: () => import_types.HttpRequest, + getHttpHandlerExtensionConfiguration: () => getHttpHandlerExtensionConfiguration, + isValidHostname: () => isValidHostname, + resolveHttpHandlerRuntimeConfig: () => resolveHttpHandlerRuntimeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/extensions/httpExtensionConfiguration.ts +var getHttpHandlerExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return { + setHttpHandler(handler) { + runtimeConfig.httpHandler = handler; + }, + httpHandler() { + return runtimeConfig.httpHandler; + }, + updateHttpClientConfig(key, value) { + runtimeConfig.httpHandler?.updateHttpClientConfig(key, value); + }, + httpHandlerConfigs() { + return runtimeConfig.httpHandler.httpHandlerConfigs(); + } + }; +}, "getHttpHandlerExtensionConfiguration"); +var resolveHttpHandlerRuntimeConfig = /* @__PURE__ */ __name((httpHandlerExtensionConfiguration) => { + return { + httpHandler: httpHandlerExtensionConfiguration.httpHandler() + }; +}, "resolveHttpHandlerRuntimeConfig"); + +// src/Field.ts +var import_types = __nccwpck_require__(90690); +var Field = class { + static { + __name(this, "Field"); + } + constructor({ name, kind = import_types.FieldPosition.HEADER, values = [] }) { + this.name = name; + this.kind = kind; + this.values = values; + } + /** + * Appends a value to the field. + * + * @param value The value to append. + */ + add(value) { + this.values.push(value); + } + /** + * Overwrite existing field values. + * + * @param values The new field values. + */ + set(values) { + this.values = values; + } + /** + * Remove all matching entries from list. + * + * @param value Value to remove. + */ + remove(value) { + this.values = this.values.filter((v) => v !== value); + } + /** + * Get comma-delimited string. + * + * @returns String representation of {@link Field}. + */ + toString() { + return this.values.map((v) => v.includes(",") || v.includes(" ") ? `"${v}"` : v).join(", "); + } + /** + * Get string values as a list + * + * @returns Values in {@link Field} as a list. + */ + get() { + return this.values; + } +}; + +// src/Fields.ts +var Fields = class { + constructor({ fields = [], encoding = "utf-8" }) { + this.entries = {}; + fields.forEach(this.setField.bind(this)); + this.encoding = encoding; + } + static { + __name(this, "Fields"); + } + /** + * Set entry for a {@link Field} name. The `name` + * attribute will be used to key the collection. + * + * @param field The {@link Field} to set. + */ + setField(field) { + this.entries[field.name.toLowerCase()] = field; + } + /** + * Retrieve {@link Field} entry by name. + * + * @param name The name of the {@link Field} entry + * to retrieve + * @returns The {@link Field} if it exists. + */ + getField(name) { + return this.entries[name.toLowerCase()]; + } + /** + * Delete entry from collection. + * + * @param name Name of the entry to delete. + */ + removeField(name) { + delete this.entries[name.toLowerCase()]; + } + /** + * Helper function for retrieving specific types of fields. + * Used to grab all headers or all trailers. + * + * @param kind {@link FieldPosition} of entries to retrieve. + * @returns The {@link Field} entries with the specified + * {@link FieldPosition}. + */ + getByType(kind) { + return Object.values(this.entries).filter((field) => field.kind === kind); + } +}; + +// src/httpRequest.ts + +var HttpRequest = class _HttpRequest { + static { + __name(this, "HttpRequest"); + } + constructor(options) { + this.method = options.method || "GET"; + this.hostname = options.hostname || "localhost"; + this.port = options.port; + this.query = options.query || {}; + this.headers = options.headers || {}; + this.body = options.body; + this.protocol = options.protocol ? options.protocol.slice(-1) !== ":" ? `${options.protocol}:` : options.protocol : "https:"; + this.path = options.path ? options.path.charAt(0) !== "/" ? `/${options.path}` : options.path : "/"; + this.username = options.username; + this.password = options.password; + this.fragment = options.fragment; + } + /** + * Note: this does not deep-clone the body. + */ + static clone(request) { + const cloned = new _HttpRequest({ + ...request, + headers: { ...request.headers } + }); + if (cloned.query) { + cloned.query = cloneQuery(cloned.query); + } + return cloned; + } + /** + * This method only actually asserts that request is the interface {@link IHttpRequest}, + * and not necessarily this concrete class. Left in place for API stability. + * + * Do not call instance methods on the input of this function, and + * do not assume it has the HttpRequest prototype. + */ + static isInstance(request) { + if (!request) { + return false; + } + const req = request; + return "method" in req && "protocol" in req && "hostname" in req && "path" in req && typeof req["query"] === "object" && typeof req["headers"] === "object"; + } + /** + * @deprecated use static HttpRequest.clone(request) instead. It's not safe to call + * this method because {@link HttpRequest.isInstance} incorrectly + * asserts that IHttpRequest (interface) objects are of type HttpRequest (class). + */ + clone() { + return _HttpRequest.clone(this); + } +}; +function cloneQuery(query) { + return Object.keys(query).reduce((carry, paramName) => { + const param = query[paramName]; + return { + ...carry, + [paramName]: Array.isArray(param) ? [...param] : param + }; + }, {}); +} +__name(cloneQuery, "cloneQuery"); + +// src/httpResponse.ts +var HttpResponse = class { + static { + __name(this, "HttpResponse"); + } + constructor(options) { + this.statusCode = options.statusCode; + this.reason = options.reason; + this.headers = options.headers || {}; + this.body = options.body; + } + static isInstance(response) { + if (!response) + return false; + const resp = response; + return typeof resp.statusCode === "number" && typeof resp.headers === "object"; + } +}; + +// src/isValidHostname.ts +function isValidHostname(hostname) { + const hostPattern = /^[a-z0-9][a-z0-9\.\-]*[a-z0-9]$/; + return hostPattern.test(hostname); +} +__name(isValidHostname, "isValidHostname"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 18256: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + buildQueryString: () => buildQueryString +}); +module.exports = __toCommonJS(src_exports); +var import_util_uri_escape = __nccwpck_require__(80146); +function buildQueryString(query) { + const parts = []; + for (let key of Object.keys(query).sort()) { + const value = query[key]; + key = (0, import_util_uri_escape.escapeUri)(key); + if (Array.isArray(value)) { + for (let i = 0, iLen = value.length; i < iLen; i++) { + parts.push(`${key}=${(0, import_util_uri_escape.escapeUri)(value[i])}`); + } + } else { + let qsEntry = key; + if (value || typeof value === "string") { + qsEntry += `=${(0, import_util_uri_escape.escapeUri)(value)}`; + } + parts.push(qsEntry); + } + } + return parts.join("&"); +} +__name(buildQueryString, "buildQueryString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 18822: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + parseQueryString: () => parseQueryString +}); +module.exports = __toCommonJS(src_exports); +function parseQueryString(querystring) { + const query = {}; + querystring = querystring.replace(/^\?/, ""); + if (querystring) { + for (const pair of querystring.split("&")) { + let [key, value = null] = pair.split("="); + key = decodeURIComponent(key); + if (value) { + value = decodeURIComponent(value); + } + if (!(key in query)) { + query[key] = value; + } else if (Array.isArray(query[key])) { + query[key].push(value); + } else { + query[key] = [query[key], value]; + } + } + } + return query; +} +__name(parseQueryString, "parseQueryString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 42058: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + isBrowserNetworkError: () => isBrowserNetworkError, + isClockSkewCorrectedError: () => isClockSkewCorrectedError, + isClockSkewError: () => isClockSkewError, + isRetryableByTrait: () => isRetryableByTrait, + isServerError: () => isServerError, + isThrottlingError: () => isThrottlingError, + isTransientError: () => isTransientError +}); +module.exports = __toCommonJS(src_exports); + +// src/constants.ts +var CLOCK_SKEW_ERROR_CODES = [ + "AuthFailure", + "InvalidSignatureException", + "RequestExpired", + "RequestInTheFuture", + "RequestTimeTooSkewed", + "SignatureDoesNotMatch" +]; +var THROTTLING_ERROR_CODES = [ + "BandwidthLimitExceeded", + "EC2ThrottledException", + "LimitExceededException", + "PriorRequestNotComplete", + "ProvisionedThroughputExceededException", + "RequestLimitExceeded", + "RequestThrottled", + "RequestThrottledException", + "SlowDown", + "ThrottledException", + "Throttling", + "ThrottlingException", + "TooManyRequestsException", + "TransactionInProgressException" + // DynamoDB +]; +var TRANSIENT_ERROR_CODES = ["TimeoutError", "RequestTimeout", "RequestTimeoutException"]; +var TRANSIENT_ERROR_STATUS_CODES = [500, 502, 503, 504]; +var NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "ECONNREFUSED", "EPIPE", "ETIMEDOUT"]; +var NODEJS_NETWORK_ERROR_CODES = ["EHOSTUNREACH", "ENETUNREACH", "ENOTFOUND"]; + +// src/index.ts +var isRetryableByTrait = /* @__PURE__ */ __name((error) => error.$retryable !== void 0, "isRetryableByTrait"); +var isClockSkewError = /* @__PURE__ */ __name((error) => CLOCK_SKEW_ERROR_CODES.includes(error.name), "isClockSkewError"); +var isClockSkewCorrectedError = /* @__PURE__ */ __name((error) => error.$metadata?.clockSkewCorrected, "isClockSkewCorrectedError"); +var isBrowserNetworkError = /* @__PURE__ */ __name((error) => { + const errorMessages = /* @__PURE__ */ new Set([ + "Failed to fetch", + // Chrome + "NetworkError when attempting to fetch resource", + // Firefox + "The Internet connection appears to be offline", + // Safari 16 + "Load failed", + // Safari 17+ + "Network request failed" + // `cross-fetch` + ]); + const isValid = error && error instanceof TypeError; + if (!isValid) { + return false; + } + return errorMessages.has(error.message); +}, "isBrowserNetworkError"); +var isThrottlingError = /* @__PURE__ */ __name((error) => error.$metadata?.httpStatusCode === 429 || THROTTLING_ERROR_CODES.includes(error.name) || error.$retryable?.throttling == true, "isThrottlingError"); +var isTransientError = /* @__PURE__ */ __name((error, depth = 0) => isClockSkewCorrectedError(error) || TRANSIENT_ERROR_CODES.includes(error.name) || NODEJS_TIMEOUT_ERROR_CODES.includes(error?.code || "") || NODEJS_NETWORK_ERROR_CODES.includes(error?.code || "") || TRANSIENT_ERROR_STATUS_CODES.includes(error.$metadata?.httpStatusCode || 0) || isBrowserNetworkError(error) || error.cause !== void 0 && depth <= 10 && isTransientError(error.cause, depth + 1), "isTransientError"); +var isServerError = /* @__PURE__ */ __name((error) => { + if (error.$metadata?.httpStatusCode !== void 0) { + const statusCode = error.$metadata.httpStatusCode; + if (500 <= statusCode && statusCode <= 599 && !isTransientError(error)) { + return true; + } + return false; + } + return false; +}, "isServerError"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 54172: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getHomeDir = void 0; +const os_1 = __nccwpck_require__(70857); +const path_1 = __nccwpck_require__(16928); +const homeDirCache = {}; +const getHomeDirCacheKey = () => { + if (process && process.geteuid) { + return `${process.geteuid()}`; + } + return "DEFAULT"; +}; +const getHomeDir = () => { + const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${path_1.sep}` } = process.env; + if (HOME) + return HOME; + if (USERPROFILE) + return USERPROFILE; + if (HOMEPATH) + return `${HOMEDRIVE}${HOMEPATH}`; + const homeDirCacheKey = getHomeDirCacheKey(); + if (!homeDirCache[homeDirCacheKey]) + homeDirCache[homeDirCacheKey] = (0, os_1.homedir)(); + return homeDirCache[homeDirCacheKey]; +}; +exports.getHomeDir = getHomeDir; + + +/***/ }), + +/***/ 20269: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getSSOTokenFilepath = void 0; +const crypto_1 = __nccwpck_require__(76982); +const path_1 = __nccwpck_require__(16928); +const getHomeDir_1 = __nccwpck_require__(54172); +const getSSOTokenFilepath = (id) => { + const hasher = (0, crypto_1.createHash)("sha1"); + const cacheName = hasher.update(id).digest("hex"); + return (0, path_1.join)((0, getHomeDir_1.getHomeDir)(), ".aws", "sso", "cache", `${cacheName}.json`); +}; +exports.getSSOTokenFilepath = getSSOTokenFilepath; + + +/***/ }), + +/***/ 11326: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getSSOTokenFromFile = void 0; +const fs_1 = __nccwpck_require__(79896); +const getSSOTokenFilepath_1 = __nccwpck_require__(20269); +const { readFile } = fs_1.promises; +const getSSOTokenFromFile = async (id) => { + const ssoTokenFilepath = (0, getSSOTokenFilepath_1.getSSOTokenFilepath)(id); + const ssoTokenText = await readFile(ssoTokenFilepath, "utf8"); + return JSON.parse(ssoTokenText); +}; +exports.getSSOTokenFromFile = getSSOTokenFromFile; + + +/***/ }), + +/***/ 94964: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + CONFIG_PREFIX_SEPARATOR: () => CONFIG_PREFIX_SEPARATOR, + DEFAULT_PROFILE: () => DEFAULT_PROFILE, + ENV_PROFILE: () => ENV_PROFILE, + getProfileName: () => getProfileName, + loadSharedConfigFiles: () => loadSharedConfigFiles, + loadSsoSessionData: () => loadSsoSessionData, + parseKnownFiles: () => parseKnownFiles +}); +module.exports = __toCommonJS(src_exports); +__reExport(src_exports, __nccwpck_require__(54172), module.exports); + +// src/getProfileName.ts +var ENV_PROFILE = "AWS_PROFILE"; +var DEFAULT_PROFILE = "default"; +var getProfileName = /* @__PURE__ */ __name((init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE, "getProfileName"); + +// src/index.ts +__reExport(src_exports, __nccwpck_require__(20269), module.exports); +__reExport(src_exports, __nccwpck_require__(11326), module.exports); + +// src/loadSharedConfigFiles.ts + + +// src/getConfigData.ts +var import_types = __nccwpck_require__(90690); +var getConfigData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => { + const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR); + if (indexOfSeparator === -1) { + return false; + } + return Object.values(import_types.IniSectionType).includes(key.substring(0, indexOfSeparator)); +}).reduce( + (acc, [key, value]) => { + const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR); + const updatedKey = key.substring(0, indexOfSeparator) === import_types.IniSectionType.PROFILE ? key.substring(indexOfSeparator + 1) : key; + acc[updatedKey] = value; + return acc; + }, + { + // Populate default profile, if present. + ...data.default && { default: data.default } + } +), "getConfigData"); + +// src/getConfigFilepath.ts +var import_path = __nccwpck_require__(16928); +var import_getHomeDir = __nccwpck_require__(54172); +var ENV_CONFIG_PATH = "AWS_CONFIG_FILE"; +var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath"); + +// src/getCredentialsFilepath.ts + +var import_getHomeDir2 = __nccwpck_require__(54172); +var ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE"; +var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath"); + +// src/loadSharedConfigFiles.ts +var import_getHomeDir3 = __nccwpck_require__(54172); + +// src/parseIni.ts + +var prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/; +var profileNameBlockList = ["__proto__", "profile __proto__"]; +var parseIni = /* @__PURE__ */ __name((iniData) => { + const map = {}; + let currentSection; + let currentSubSection; + for (const iniLine of iniData.split(/\r?\n/)) { + const trimmedLine = iniLine.split(/(^|\s)[;#]/)[0].trim(); + const isSection = trimmedLine[0] === "[" && trimmedLine[trimmedLine.length - 1] === "]"; + if (isSection) { + currentSection = void 0; + currentSubSection = void 0; + const sectionName = trimmedLine.substring(1, trimmedLine.length - 1); + const matches = prefixKeyRegex.exec(sectionName); + if (matches) { + const [, prefix, , name] = matches; + if (Object.values(import_types.IniSectionType).includes(prefix)) { + currentSection = [prefix, name].join(CONFIG_PREFIX_SEPARATOR); + } + } else { + currentSection = sectionName; + } + if (profileNameBlockList.includes(sectionName)) { + throw new Error(`Found invalid profile name "${sectionName}"`); + } + } else if (currentSection) { + const indexOfEqualsSign = trimmedLine.indexOf("="); + if (![0, -1].includes(indexOfEqualsSign)) { + const [name, value] = [ + trimmedLine.substring(0, indexOfEqualsSign).trim(), + trimmedLine.substring(indexOfEqualsSign + 1).trim() + ]; + if (value === "") { + currentSubSection = name; + } else { + if (currentSubSection && iniLine.trimStart() === iniLine) { + currentSubSection = void 0; + } + map[currentSection] = map[currentSection] || {}; + const key = currentSubSection ? [currentSubSection, name].join(CONFIG_PREFIX_SEPARATOR) : name; + map[currentSection][key] = value; + } + } + } + } + return map; +}, "parseIni"); + +// src/loadSharedConfigFiles.ts +var import_slurpFile = __nccwpck_require__(54246); +var swallowError = /* @__PURE__ */ __name(() => ({}), "swallowError"); +var CONFIG_PREFIX_SEPARATOR = "."; +var loadSharedConfigFiles = /* @__PURE__ */ __name(async (init = {}) => { + const { filepath = getCredentialsFilepath(), configFilepath = getConfigFilepath() } = init; + const homeDir = (0, import_getHomeDir3.getHomeDir)(); + const relativeHomeDirPrefix = "~/"; + let resolvedFilepath = filepath; + if (filepath.startsWith(relativeHomeDirPrefix)) { + resolvedFilepath = (0, import_path.join)(homeDir, filepath.slice(2)); + } + let resolvedConfigFilepath = configFilepath; + if (configFilepath.startsWith(relativeHomeDirPrefix)) { + resolvedConfigFilepath = (0, import_path.join)(homeDir, configFilepath.slice(2)); + } + const parsedFiles = await Promise.all([ + (0, import_slurpFile.slurpFile)(resolvedConfigFilepath, { + ignoreCache: init.ignoreCache + }).then(parseIni).then(getConfigData).catch(swallowError), + (0, import_slurpFile.slurpFile)(resolvedFilepath, { + ignoreCache: init.ignoreCache + }).then(parseIni).catch(swallowError) + ]); + return { + configFile: parsedFiles[0], + credentialsFile: parsedFiles[1] + }; +}, "loadSharedConfigFiles"); + +// src/getSsoSessionData.ts + +var getSsoSessionData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => key.startsWith(import_types.IniSectionType.SSO_SESSION + CONFIG_PREFIX_SEPARATOR)).reduce((acc, [key, value]) => ({ ...acc, [key.substring(key.indexOf(CONFIG_PREFIX_SEPARATOR) + 1)]: value }), {}), "getSsoSessionData"); + +// src/loadSsoSessionData.ts +var import_slurpFile2 = __nccwpck_require__(54246); +var swallowError2 = /* @__PURE__ */ __name(() => ({}), "swallowError"); +var loadSsoSessionData = /* @__PURE__ */ __name(async (init = {}) => (0, import_slurpFile2.slurpFile)(init.configFilepath ?? getConfigFilepath()).then(parseIni).then(getSsoSessionData).catch(swallowError2), "loadSsoSessionData"); + +// src/mergeConfigFiles.ts +var mergeConfigFiles = /* @__PURE__ */ __name((...files) => { + const merged = {}; + for (const file of files) { + for (const [key, values] of Object.entries(file)) { + if (merged[key] !== void 0) { + Object.assign(merged[key], values); + } else { + merged[key] = values; + } + } + } + return merged; +}, "mergeConfigFiles"); + +// src/parseKnownFiles.ts +var parseKnownFiles = /* @__PURE__ */ __name(async (init) => { + const parsedFiles = await loadSharedConfigFiles(init); + return mergeConfigFiles(parsedFiles.configFile, parsedFiles.credentialsFile); +}, "parseKnownFiles"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 54246: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.slurpFile = void 0; +const fs_1 = __nccwpck_require__(79896); +const { readFile } = fs_1.promises; +const filePromisesHash = {}; +const slurpFile = (path, options) => { + if (!filePromisesHash[path] || (options === null || options === void 0 ? void 0 : options.ignoreCache)) { + filePromisesHash[path] = readFile(path, "utf8"); + } + return filePromisesHash[path]; +}; +exports.slurpFile = slurpFile; + + +/***/ }), + +/***/ 75118: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + ALGORITHM_IDENTIFIER: () => ALGORITHM_IDENTIFIER, + ALGORITHM_IDENTIFIER_V4A: () => ALGORITHM_IDENTIFIER_V4A, + ALGORITHM_QUERY_PARAM: () => ALGORITHM_QUERY_PARAM, + ALWAYS_UNSIGNABLE_HEADERS: () => ALWAYS_UNSIGNABLE_HEADERS, + AMZ_DATE_HEADER: () => AMZ_DATE_HEADER, + AMZ_DATE_QUERY_PARAM: () => AMZ_DATE_QUERY_PARAM, + AUTH_HEADER: () => AUTH_HEADER, + CREDENTIAL_QUERY_PARAM: () => CREDENTIAL_QUERY_PARAM, + DATE_HEADER: () => DATE_HEADER, + EVENT_ALGORITHM_IDENTIFIER: () => EVENT_ALGORITHM_IDENTIFIER, + EXPIRES_QUERY_PARAM: () => EXPIRES_QUERY_PARAM, + GENERATED_HEADERS: () => GENERATED_HEADERS, + HOST_HEADER: () => HOST_HEADER, + KEY_TYPE_IDENTIFIER: () => KEY_TYPE_IDENTIFIER, + MAX_CACHE_SIZE: () => MAX_CACHE_SIZE, + MAX_PRESIGNED_TTL: () => MAX_PRESIGNED_TTL, + PROXY_HEADER_PATTERN: () => PROXY_HEADER_PATTERN, + REGION_SET_PARAM: () => REGION_SET_PARAM, + SEC_HEADER_PATTERN: () => SEC_HEADER_PATTERN, + SHA256_HEADER: () => SHA256_HEADER, + SIGNATURE_HEADER: () => SIGNATURE_HEADER, + SIGNATURE_QUERY_PARAM: () => SIGNATURE_QUERY_PARAM, + SIGNED_HEADERS_QUERY_PARAM: () => SIGNED_HEADERS_QUERY_PARAM, + SignatureV4: () => SignatureV4, + SignatureV4Base: () => SignatureV4Base, + TOKEN_HEADER: () => TOKEN_HEADER, + TOKEN_QUERY_PARAM: () => TOKEN_QUERY_PARAM, + UNSIGNABLE_PATTERNS: () => UNSIGNABLE_PATTERNS, + UNSIGNED_PAYLOAD: () => UNSIGNED_PAYLOAD, + clearCredentialCache: () => clearCredentialCache, + createScope: () => createScope, + getCanonicalHeaders: () => getCanonicalHeaders, + getCanonicalQuery: () => getCanonicalQuery, + getPayloadHash: () => getPayloadHash, + getSigningKey: () => getSigningKey, + hasHeader: () => hasHeader, + moveHeadersToQuery: () => moveHeadersToQuery, + prepareRequest: () => prepareRequest, + signatureV4aContainer: () => signatureV4aContainer +}); +module.exports = __toCommonJS(src_exports); + +// src/SignatureV4.ts + +var import_util_utf85 = __nccwpck_require__(71577); + +// src/constants.ts +var ALGORITHM_QUERY_PARAM = "X-Amz-Algorithm"; +var CREDENTIAL_QUERY_PARAM = "X-Amz-Credential"; +var AMZ_DATE_QUERY_PARAM = "X-Amz-Date"; +var SIGNED_HEADERS_QUERY_PARAM = "X-Amz-SignedHeaders"; +var EXPIRES_QUERY_PARAM = "X-Amz-Expires"; +var SIGNATURE_QUERY_PARAM = "X-Amz-Signature"; +var TOKEN_QUERY_PARAM = "X-Amz-Security-Token"; +var REGION_SET_PARAM = "X-Amz-Region-Set"; +var AUTH_HEADER = "authorization"; +var AMZ_DATE_HEADER = AMZ_DATE_QUERY_PARAM.toLowerCase(); +var DATE_HEADER = "date"; +var GENERATED_HEADERS = [AUTH_HEADER, AMZ_DATE_HEADER, DATE_HEADER]; +var SIGNATURE_HEADER = SIGNATURE_QUERY_PARAM.toLowerCase(); +var SHA256_HEADER = "x-amz-content-sha256"; +var TOKEN_HEADER = TOKEN_QUERY_PARAM.toLowerCase(); +var HOST_HEADER = "host"; +var ALWAYS_UNSIGNABLE_HEADERS = { + authorization: true, + "cache-control": true, + connection: true, + expect: true, + from: true, + "keep-alive": true, + "max-forwards": true, + pragma: true, + referer: true, + te: true, + trailer: true, + "transfer-encoding": true, + upgrade: true, + "user-agent": true, + "x-amzn-trace-id": true +}; +var PROXY_HEADER_PATTERN = /^proxy-/; +var SEC_HEADER_PATTERN = /^sec-/; +var UNSIGNABLE_PATTERNS = [/^proxy-/i, /^sec-/i]; +var ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256"; +var ALGORITHM_IDENTIFIER_V4A = "AWS4-ECDSA-P256-SHA256"; +var EVENT_ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256-PAYLOAD"; +var UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; +var MAX_CACHE_SIZE = 50; +var KEY_TYPE_IDENTIFIER = "aws4_request"; +var MAX_PRESIGNED_TTL = 60 * 60 * 24 * 7; + +// src/credentialDerivation.ts +var import_util_hex_encoding = __nccwpck_require__(96435); +var import_util_utf8 = __nccwpck_require__(71577); +var signingKeyCache = {}; +var cacheQueue = []; +var createScope = /* @__PURE__ */ __name((shortDate, region, service) => `${shortDate}/${region}/${service}/${KEY_TYPE_IDENTIFIER}`, "createScope"); +var getSigningKey = /* @__PURE__ */ __name(async (sha256Constructor, credentials, shortDate, region, service) => { + const credsHash = await hmac(sha256Constructor, credentials.secretAccessKey, credentials.accessKeyId); + const cacheKey = `${shortDate}:${region}:${service}:${(0, import_util_hex_encoding.toHex)(credsHash)}:${credentials.sessionToken}`; + if (cacheKey in signingKeyCache) { + return signingKeyCache[cacheKey]; + } + cacheQueue.push(cacheKey); + while (cacheQueue.length > MAX_CACHE_SIZE) { + delete signingKeyCache[cacheQueue.shift()]; + } + let key = `AWS4${credentials.secretAccessKey}`; + for (const signable of [shortDate, region, service, KEY_TYPE_IDENTIFIER]) { + key = await hmac(sha256Constructor, key, signable); + } + return signingKeyCache[cacheKey] = key; +}, "getSigningKey"); +var clearCredentialCache = /* @__PURE__ */ __name(() => { + cacheQueue.length = 0; + Object.keys(signingKeyCache).forEach((cacheKey) => { + delete signingKeyCache[cacheKey]; + }); +}, "clearCredentialCache"); +var hmac = /* @__PURE__ */ __name((ctor, secret, data) => { + const hash = new ctor(secret); + hash.update((0, import_util_utf8.toUint8Array)(data)); + return hash.digest(); +}, "hmac"); + +// src/getCanonicalHeaders.ts +var getCanonicalHeaders = /* @__PURE__ */ __name(({ headers }, unsignableHeaders, signableHeaders) => { + const canonical = {}; + for (const headerName of Object.keys(headers).sort()) { + if (headers[headerName] == void 0) { + continue; + } + const canonicalHeaderName = headerName.toLowerCase(); + if (canonicalHeaderName in ALWAYS_UNSIGNABLE_HEADERS || unsignableHeaders?.has(canonicalHeaderName) || PROXY_HEADER_PATTERN.test(canonicalHeaderName) || SEC_HEADER_PATTERN.test(canonicalHeaderName)) { + if (!signableHeaders || signableHeaders && !signableHeaders.has(canonicalHeaderName)) { + continue; + } + } + canonical[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " "); + } + return canonical; +}, "getCanonicalHeaders"); + +// src/getPayloadHash.ts +var import_is_array_buffer = __nccwpck_require__(86130); + +var import_util_utf82 = __nccwpck_require__(71577); +var getPayloadHash = /* @__PURE__ */ __name(async ({ headers, body }, hashConstructor) => { + for (const headerName of Object.keys(headers)) { + if (headerName.toLowerCase() === SHA256_HEADER) { + return headers[headerName]; + } + } + if (body == void 0) { + return "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + } else if (typeof body === "string" || ArrayBuffer.isView(body) || (0, import_is_array_buffer.isArrayBuffer)(body)) { + const hashCtor = new hashConstructor(); + hashCtor.update((0, import_util_utf82.toUint8Array)(body)); + return (0, import_util_hex_encoding.toHex)(await hashCtor.digest()); + } + return UNSIGNED_PAYLOAD; +}, "getPayloadHash"); + +// src/HeaderFormatter.ts + +var import_util_utf83 = __nccwpck_require__(71577); +var HeaderFormatter = class { + static { + __name(this, "HeaderFormatter"); + } + format(headers) { + const chunks = []; + for (const headerName of Object.keys(headers)) { + const bytes = (0, import_util_utf83.fromUtf8)(headerName); + chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName])); + } + const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0)); + let position = 0; + for (const chunk of chunks) { + out.set(chunk, position); + position += chunk.byteLength; + } + return out; + } + formatHeaderValue(header) { + switch (header.type) { + case "boolean": + return Uint8Array.from([header.value ? 0 /* boolTrue */ : 1 /* boolFalse */]); + case "byte": + return Uint8Array.from([2 /* byte */, header.value]); + case "short": + const shortView = new DataView(new ArrayBuffer(3)); + shortView.setUint8(0, 3 /* short */); + shortView.setInt16(1, header.value, false); + return new Uint8Array(shortView.buffer); + case "integer": + const intView = new DataView(new ArrayBuffer(5)); + intView.setUint8(0, 4 /* integer */); + intView.setInt32(1, header.value, false); + return new Uint8Array(intView.buffer); + case "long": + const longBytes = new Uint8Array(9); + longBytes[0] = 5 /* long */; + longBytes.set(header.value.bytes, 1); + return longBytes; + case "binary": + const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength)); + binView.setUint8(0, 6 /* byteArray */); + binView.setUint16(1, header.value.byteLength, false); + const binBytes = new Uint8Array(binView.buffer); + binBytes.set(header.value, 3); + return binBytes; + case "string": + const utf8Bytes = (0, import_util_utf83.fromUtf8)(header.value); + const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength)); + strView.setUint8(0, 7 /* string */); + strView.setUint16(1, utf8Bytes.byteLength, false); + const strBytes = new Uint8Array(strView.buffer); + strBytes.set(utf8Bytes, 3); + return strBytes; + case "timestamp": + const tsBytes = new Uint8Array(9); + tsBytes[0] = 8 /* timestamp */; + tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1); + return tsBytes; + case "uuid": + if (!UUID_PATTERN.test(header.value)) { + throw new Error(`Invalid UUID received: ${header.value}`); + } + const uuidBytes = new Uint8Array(17); + uuidBytes[0] = 9 /* uuid */; + uuidBytes.set((0, import_util_hex_encoding.fromHex)(header.value.replace(/\-/g, "")), 1); + return uuidBytes; + } + } +}; +var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/; +var Int64 = class _Int64 { + constructor(bytes) { + this.bytes = bytes; + if (bytes.byteLength !== 8) { + throw new Error("Int64 buffers must be exactly 8 bytes"); + } + } + static { + __name(this, "Int64"); + } + static fromNumber(number) { + if (number > 9223372036854776e3 || number < -9223372036854776e3) { + throw new Error(`${number} is too large (or, if negative, too small) to represent as an Int64`); + } + const bytes = new Uint8Array(8); + for (let i = 7, remaining = Math.abs(Math.round(number)); i > -1 && remaining > 0; i--, remaining /= 256) { + bytes[i] = remaining; + } + if (number < 0) { + negate(bytes); + } + return new _Int64(bytes); + } + /** + * Called implicitly by infix arithmetic operators. + */ + valueOf() { + const bytes = this.bytes.slice(0); + const negative = bytes[0] & 128; + if (negative) { + negate(bytes); + } + return parseInt((0, import_util_hex_encoding.toHex)(bytes), 16) * (negative ? -1 : 1); + } + toString() { + return String(this.valueOf()); + } +}; +function negate(bytes) { + for (let i = 0; i < 8; i++) { + bytes[i] ^= 255; + } + for (let i = 7; i > -1; i--) { + bytes[i]++; + if (bytes[i] !== 0) + break; + } +} +__name(negate, "negate"); + +// src/headerUtil.ts +var hasHeader = /* @__PURE__ */ __name((soughtHeader, headers) => { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return true; + } + } + return false; +}, "hasHeader"); + +// src/moveHeadersToQuery.ts +var import_protocol_http = __nccwpck_require__(72356); +var moveHeadersToQuery = /* @__PURE__ */ __name((request, options = {}) => { + const { headers, query = {} } = import_protocol_http.HttpRequest.clone(request); + for (const name of Object.keys(headers)) { + const lname = name.toLowerCase(); + if (lname.slice(0, 6) === "x-amz-" && !options.unhoistableHeaders?.has(lname) || options.hoistableHeaders?.has(lname)) { + query[name] = headers[name]; + delete headers[name]; + } + } + return { + ...request, + headers, + query + }; +}, "moveHeadersToQuery"); + +// src/prepareRequest.ts + +var prepareRequest = /* @__PURE__ */ __name((request) => { + request = import_protocol_http.HttpRequest.clone(request); + for (const headerName of Object.keys(request.headers)) { + if (GENERATED_HEADERS.indexOf(headerName.toLowerCase()) > -1) { + delete request.headers[headerName]; + } + } + return request; +}, "prepareRequest"); + +// src/SignatureV4Base.ts + +var import_util_middleware = __nccwpck_require__(76324); + +var import_util_utf84 = __nccwpck_require__(71577); + +// src/getCanonicalQuery.ts +var import_util_uri_escape = __nccwpck_require__(80146); +var getCanonicalQuery = /* @__PURE__ */ __name(({ query = {} }) => { + const keys = []; + const serialized = {}; + for (const key of Object.keys(query)) { + if (key.toLowerCase() === SIGNATURE_HEADER) { + continue; + } + const encodedKey = (0, import_util_uri_escape.escapeUri)(key); + keys.push(encodedKey); + const value = query[key]; + if (typeof value === "string") { + serialized[encodedKey] = `${encodedKey}=${(0, import_util_uri_escape.escapeUri)(value)}`; + } else if (Array.isArray(value)) { + serialized[encodedKey] = value.slice(0).reduce((encoded, value2) => encoded.concat([`${encodedKey}=${(0, import_util_uri_escape.escapeUri)(value2)}`]), []).sort().join("&"); + } + } + return keys.sort().map((key) => serialized[key]).filter((serialized2) => serialized2).join("&"); +}, "getCanonicalQuery"); + +// src/utilDate.ts +var iso8601 = /* @__PURE__ */ __name((time) => toDate(time).toISOString().replace(/\.\d{3}Z$/, "Z"), "iso8601"); +var toDate = /* @__PURE__ */ __name((time) => { + if (typeof time === "number") { + return new Date(time * 1e3); + } + if (typeof time === "string") { + if (Number(time)) { + return new Date(Number(time) * 1e3); + } + return new Date(time); + } + return time; +}, "toDate"); + +// src/SignatureV4Base.ts +var SignatureV4Base = class { + static { + __name(this, "SignatureV4Base"); + } + constructor({ + applyChecksum, + credentials, + region, + service, + sha256, + uriEscapePath = true + }) { + this.service = service; + this.sha256 = sha256; + this.uriEscapePath = uriEscapePath; + this.applyChecksum = typeof applyChecksum === "boolean" ? applyChecksum : true; + this.regionProvider = (0, import_util_middleware.normalizeProvider)(region); + this.credentialProvider = (0, import_util_middleware.normalizeProvider)(credentials); + } + createCanonicalRequest(request, canonicalHeaders, payloadHash) { + const sortedHeaders = Object.keys(canonicalHeaders).sort(); + return `${request.method} +${this.getCanonicalPath(request)} +${getCanonicalQuery(request)} +${sortedHeaders.map((name) => `${name}:${canonicalHeaders[name]}`).join("\n")} + +${sortedHeaders.join(";")} +${payloadHash}`; + } + async createStringToSign(longDate, credentialScope, canonicalRequest, algorithmIdentifier) { + const hash = new this.sha256(); + hash.update((0, import_util_utf84.toUint8Array)(canonicalRequest)); + const hashedRequest = await hash.digest(); + return `${algorithmIdentifier} +${longDate} +${credentialScope} +${(0, import_util_hex_encoding.toHex)(hashedRequest)}`; + } + getCanonicalPath({ path }) { + if (this.uriEscapePath) { + const normalizedPathSegments = []; + for (const pathSegment of path.split("/")) { + if (pathSegment?.length === 0) + continue; + if (pathSegment === ".") + continue; + if (pathSegment === "..") { + normalizedPathSegments.pop(); + } else { + normalizedPathSegments.push(pathSegment); + } + } + const normalizedPath = `${path?.startsWith("/") ? "/" : ""}${normalizedPathSegments.join("/")}${normalizedPathSegments.length > 0 && path?.endsWith("/") ? "/" : ""}`; + const doubleEncoded = (0, import_util_uri_escape.escapeUri)(normalizedPath); + return doubleEncoded.replace(/%2F/g, "/"); + } + return path; + } + validateResolvedCredentials(credentials) { + if (typeof credentials !== "object" || // @ts-expect-error: Property 'accessKeyId' does not exist on type 'object'.ts(2339) + typeof credentials.accessKeyId !== "string" || // @ts-expect-error: Property 'secretAccessKey' does not exist on type 'object'.ts(2339) + typeof credentials.secretAccessKey !== "string") { + throw new Error("Resolved credential object is not valid"); + } + } + formatDate(now) { + const longDate = iso8601(now).replace(/[\-:]/g, ""); + return { + longDate, + shortDate: longDate.slice(0, 8) + }; + } + getCanonicalHeaderList(headers) { + return Object.keys(headers).sort().join(";"); + } +}; + +// src/SignatureV4.ts +var SignatureV4 = class extends SignatureV4Base { + constructor({ + applyChecksum, + credentials, + region, + service, + sha256, + uriEscapePath = true + }) { + super({ + applyChecksum, + credentials, + region, + service, + sha256, + uriEscapePath + }); + this.headerFormatter = new HeaderFormatter(); + } + static { + __name(this, "SignatureV4"); + } + async presign(originalRequest, options = {}) { + const { + signingDate = /* @__PURE__ */ new Date(), + expiresIn = 3600, + unsignableHeaders, + unhoistableHeaders, + signableHeaders, + hoistableHeaders, + signingRegion, + signingService + } = options; + const credentials = await this.credentialProvider(); + this.validateResolvedCredentials(credentials); + const region = signingRegion ?? await this.regionProvider(); + const { longDate, shortDate } = this.formatDate(signingDate); + if (expiresIn > MAX_PRESIGNED_TTL) { + return Promise.reject( + "Signature version 4 presigned URLs must have an expiration date less than one week in the future" + ); + } + const scope = createScope(shortDate, region, signingService ?? this.service); + const request = moveHeadersToQuery(prepareRequest(originalRequest), { unhoistableHeaders, hoistableHeaders }); + if (credentials.sessionToken) { + request.query[TOKEN_QUERY_PARAM] = credentials.sessionToken; + } + request.query[ALGORITHM_QUERY_PARAM] = ALGORITHM_IDENTIFIER; + request.query[CREDENTIAL_QUERY_PARAM] = `${credentials.accessKeyId}/${scope}`; + request.query[AMZ_DATE_QUERY_PARAM] = longDate; + request.query[EXPIRES_QUERY_PARAM] = expiresIn.toString(10); + const canonicalHeaders = getCanonicalHeaders(request, unsignableHeaders, signableHeaders); + request.query[SIGNED_HEADERS_QUERY_PARAM] = this.getCanonicalHeaderList(canonicalHeaders); + request.query[SIGNATURE_QUERY_PARAM] = await this.getSignature( + longDate, + scope, + this.getSigningKey(credentials, region, shortDate, signingService), + this.createCanonicalRequest(request, canonicalHeaders, await getPayloadHash(originalRequest, this.sha256)) + ); + return request; + } + async sign(toSign, options) { + if (typeof toSign === "string") { + return this.signString(toSign, options); + } else if (toSign.headers && toSign.payload) { + return this.signEvent(toSign, options); + } else if (toSign.message) { + return this.signMessage(toSign, options); + } else { + return this.signRequest(toSign, options); + } + } + async signEvent({ headers, payload }, { signingDate = /* @__PURE__ */ new Date(), priorSignature, signingRegion, signingService }) { + const region = signingRegion ?? await this.regionProvider(); + const { shortDate, longDate } = this.formatDate(signingDate); + const scope = createScope(shortDate, region, signingService ?? this.service); + const hashedPayload = await getPayloadHash({ headers: {}, body: payload }, this.sha256); + const hash = new this.sha256(); + hash.update(headers); + const hashedHeaders = (0, import_util_hex_encoding.toHex)(await hash.digest()); + const stringToSign = [ + EVENT_ALGORITHM_IDENTIFIER, + longDate, + scope, + priorSignature, + hashedHeaders, + hashedPayload + ].join("\n"); + return this.signString(stringToSign, { signingDate, signingRegion: region, signingService }); + } + async signMessage(signableMessage, { signingDate = /* @__PURE__ */ new Date(), signingRegion, signingService }) { + const promise = this.signEvent( + { + headers: this.headerFormatter.format(signableMessage.message.headers), + payload: signableMessage.message.body + }, + { + signingDate, + signingRegion, + signingService, + priorSignature: signableMessage.priorSignature + } + ); + return promise.then((signature) => { + return { message: signableMessage.message, signature }; + }); + } + async signString(stringToSign, { signingDate = /* @__PURE__ */ new Date(), signingRegion, signingService } = {}) { + const credentials = await this.credentialProvider(); + this.validateResolvedCredentials(credentials); + const region = signingRegion ?? await this.regionProvider(); + const { shortDate } = this.formatDate(signingDate); + const hash = new this.sha256(await this.getSigningKey(credentials, region, shortDate, signingService)); + hash.update((0, import_util_utf85.toUint8Array)(stringToSign)); + return (0, import_util_hex_encoding.toHex)(await hash.digest()); + } + async signRequest(requestToSign, { + signingDate = /* @__PURE__ */ new Date(), + signableHeaders, + unsignableHeaders, + signingRegion, + signingService + } = {}) { + const credentials = await this.credentialProvider(); + this.validateResolvedCredentials(credentials); + const region = signingRegion ?? await this.regionProvider(); + const request = prepareRequest(requestToSign); + const { longDate, shortDate } = this.formatDate(signingDate); + const scope = createScope(shortDate, region, signingService ?? this.service); + request.headers[AMZ_DATE_HEADER] = longDate; + if (credentials.sessionToken) { + request.headers[TOKEN_HEADER] = credentials.sessionToken; + } + const payloadHash = await getPayloadHash(request, this.sha256); + if (!hasHeader(SHA256_HEADER, request.headers) && this.applyChecksum) { + request.headers[SHA256_HEADER] = payloadHash; + } + const canonicalHeaders = getCanonicalHeaders(request, unsignableHeaders, signableHeaders); + const signature = await this.getSignature( + longDate, + scope, + this.getSigningKey(credentials, region, shortDate, signingService), + this.createCanonicalRequest(request, canonicalHeaders, payloadHash) + ); + request.headers[AUTH_HEADER] = `${ALGORITHM_IDENTIFIER} Credential=${credentials.accessKeyId}/${scope}, SignedHeaders=${this.getCanonicalHeaderList(canonicalHeaders)}, Signature=${signature}`; + return request; + } + async getSignature(longDate, credentialScope, keyPromise, canonicalRequest) { + const stringToSign = await this.createStringToSign( + longDate, + credentialScope, + canonicalRequest, + ALGORITHM_IDENTIFIER + ); + const hash = new this.sha256(await keyPromise); + hash.update((0, import_util_utf85.toUint8Array)(stringToSign)); + return (0, import_util_hex_encoding.toHex)(await hash.digest()); + } + getSigningKey(credentials, region, shortDate, service) { + return getSigningKey(this.sha256, credentials, shortDate, region, service || this.service); + } +}; + +// src/signature-v4a-container.ts +var signatureV4aContainer = { + SignatureV4a: null +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 61411: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Client: () => Client, + Command: () => Command, + NoOpLogger: () => NoOpLogger, + SENSITIVE_STRING: () => SENSITIVE_STRING, + ServiceException: () => ServiceException, + _json: () => _json, + collectBody: () => import_protocols.collectBody, + convertMap: () => convertMap, + createAggregatedClient: () => createAggregatedClient, + decorateServiceException: () => decorateServiceException, + emitWarningIfUnsupportedVersion: () => emitWarningIfUnsupportedVersion, + extendedEncodeURIComponent: () => import_protocols.extendedEncodeURIComponent, + getArrayIfSingleItem: () => getArrayIfSingleItem, + getDefaultClientConfiguration: () => getDefaultClientConfiguration, + getDefaultExtensionConfiguration: () => getDefaultExtensionConfiguration, + getValueFromTextNode: () => getValueFromTextNode, + isSerializableHeaderValue: () => isSerializableHeaderValue, + loadConfigsForDefaultMode: () => loadConfigsForDefaultMode, + map: () => map, + resolveDefaultRuntimeConfig: () => resolveDefaultRuntimeConfig, + resolvedPath: () => import_protocols.resolvedPath, + serializeDateTime: () => serializeDateTime, + serializeFloat: () => serializeFloat, + take: () => take, + throwDefaultError: () => throwDefaultError, + withBaseException: () => withBaseException +}); +module.exports = __toCommonJS(src_exports); + +// src/client.ts +var import_middleware_stack = __nccwpck_require__(9208); +var Client = class { + constructor(config) { + this.config = config; + this.middlewareStack = (0, import_middleware_stack.constructStack)(); + } + static { + __name(this, "Client"); + } + send(command, optionsOrCb, cb) { + const options = typeof optionsOrCb !== "function" ? optionsOrCb : void 0; + const callback = typeof optionsOrCb === "function" ? optionsOrCb : cb; + const useHandlerCache = options === void 0 && this.config.cacheMiddleware === true; + let handler; + if (useHandlerCache) { + if (!this.handlers) { + this.handlers = /* @__PURE__ */ new WeakMap(); + } + const handlers = this.handlers; + if (handlers.has(command.constructor)) { + handler = handlers.get(command.constructor); + } else { + handler = command.resolveMiddleware(this.middlewareStack, this.config, options); + handlers.set(command.constructor, handler); + } + } else { + delete this.handlers; + handler = command.resolveMiddleware(this.middlewareStack, this.config, options); + } + if (callback) { + handler(command).then( + (result) => callback(null, result.output), + (err) => callback(err) + ).catch( + // prevent any errors thrown in the callback from triggering an + // unhandled promise rejection + () => { + } + ); + } else { + return handler(command).then((result) => result.output); + } + } + destroy() { + this.config?.requestHandler?.destroy?.(); + delete this.handlers; + } +}; + +// src/collect-stream-body.ts +var import_protocols = __nccwpck_require__(93422); + +// src/command.ts + +var import_types = __nccwpck_require__(90690); +var Command = class { + constructor() { + this.middlewareStack = (0, import_middleware_stack.constructStack)(); + } + static { + __name(this, "Command"); + } + /** + * Factory for Command ClassBuilder. + * @internal + */ + static classBuilder() { + return new ClassBuilder(); + } + /** + * @internal + */ + resolveMiddlewareWithContext(clientStack, configuration, options, { + middlewareFn, + clientName, + commandName, + inputFilterSensitiveLog, + outputFilterSensitiveLog, + smithyContext, + additionalContext, + CommandCtor + }) { + for (const mw of middlewareFn.bind(this)(CommandCtor, clientStack, configuration, options)) { + this.middlewareStack.use(mw); + } + const stack = clientStack.concat(this.middlewareStack); + const { logger } = configuration; + const handlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog, + outputFilterSensitiveLog, + [import_types.SMITHY_CONTEXT_KEY]: { + commandInstance: this, + ...smithyContext + }, + ...additionalContext + }; + const { requestHandler } = configuration; + return stack.resolve( + (request) => requestHandler.handle(request.request, options || {}), + handlerExecutionContext + ); + } +}; +var ClassBuilder = class { + constructor() { + this._init = () => { + }; + this._ep = {}; + this._middlewareFn = () => []; + this._commandName = ""; + this._clientName = ""; + this._additionalContext = {}; + this._smithyContext = {}; + this._inputFilterSensitiveLog = (_) => _; + this._outputFilterSensitiveLog = (_) => _; + this._serializer = null; + this._deserializer = null; + } + static { + __name(this, "ClassBuilder"); + } + /** + * Optional init callback. + */ + init(cb) { + this._init = cb; + } + /** + * Set the endpoint parameter instructions. + */ + ep(endpointParameterInstructions) { + this._ep = endpointParameterInstructions; + return this; + } + /** + * Add any number of middleware. + */ + m(middlewareSupplier) { + this._middlewareFn = middlewareSupplier; + return this; + } + /** + * Set the initial handler execution context Smithy field. + */ + s(service, operation, smithyContext = {}) { + this._smithyContext = { + service, + operation, + ...smithyContext + }; + return this; + } + /** + * Set the initial handler execution context. + */ + c(additionalContext = {}) { + this._additionalContext = additionalContext; + return this; + } + /** + * Set constant string identifiers for the operation. + */ + n(clientName, commandName) { + this._clientName = clientName; + this._commandName = commandName; + return this; + } + /** + * Set the input and output sensistive log filters. + */ + f(inputFilter = (_) => _, outputFilter = (_) => _) { + this._inputFilterSensitiveLog = inputFilter; + this._outputFilterSensitiveLog = outputFilter; + return this; + } + /** + * Sets the serializer. + */ + ser(serializer) { + this._serializer = serializer; + return this; + } + /** + * Sets the deserializer. + */ + de(deserializer) { + this._deserializer = deserializer; + return this; + } + /** + * Sets input/output schema for the operation. + */ + sc(operation) { + this._operationSchema = operation; + this._smithyContext.operationSchema = operation; + return this; + } + /** + * @returns a Command class with the classBuilder properties. + */ + build() { + const closure = this; + let CommandRef; + return CommandRef = class extends Command { + /** + * @public + */ + constructor(...[input]) { + super(); + /** + * @internal + */ + // @ts-ignore used in middlewareFn closure. + this.serialize = closure._serializer; + /** + * @internal + */ + // @ts-ignore used in middlewareFn closure. + this.deserialize = closure._deserializer; + this.input = input ?? {}; + closure._init(this); + this.schema = closure._operationSchema; + } + static { + __name(this, "CommandRef"); + } + /** + * @public + */ + static getEndpointParameterInstructions() { + return closure._ep; + } + /** + * @internal + */ + resolveMiddleware(stack, configuration, options) { + return this.resolveMiddlewareWithContext(stack, configuration, options, { + CommandCtor: CommandRef, + middlewareFn: closure._middlewareFn, + clientName: closure._clientName, + commandName: closure._commandName, + inputFilterSensitiveLog: closure._inputFilterSensitiveLog, + outputFilterSensitiveLog: closure._outputFilterSensitiveLog, + smithyContext: closure._smithyContext, + additionalContext: closure._additionalContext + }); + } + }; + } +}; + +// src/constants.ts +var SENSITIVE_STRING = "***SensitiveInformation***"; + +// src/create-aggregated-client.ts +var createAggregatedClient = /* @__PURE__ */ __name((commands, Client2) => { + for (const command of Object.keys(commands)) { + const CommandCtor = commands[command]; + const methodImpl = /* @__PURE__ */ __name(async function(args, optionsOrCb, cb) { + const command2 = new CommandCtor(args); + if (typeof optionsOrCb === "function") { + this.send(command2, optionsOrCb); + } else if (typeof cb === "function") { + if (typeof optionsOrCb !== "object") + throw new Error(`Expected http options but got ${typeof optionsOrCb}`); + this.send(command2, optionsOrCb || {}, cb); + } else { + return this.send(command2, optionsOrCb); + } + }, "methodImpl"); + const methodName = (command[0].toLowerCase() + command.slice(1)).replace(/Command$/, ""); + Client2.prototype[methodName] = methodImpl; + } +}, "createAggregatedClient"); + +// src/exceptions.ts +var ServiceException = class _ServiceException extends Error { + static { + __name(this, "ServiceException"); + } + constructor(options) { + super(options.message); + Object.setPrototypeOf(this, Object.getPrototypeOf(this).constructor.prototype); + this.name = options.name; + this.$fault = options.$fault; + this.$metadata = options.$metadata; + } + /** + * Checks if a value is an instance of ServiceException (duck typed) + */ + static isInstance(value) { + if (!value) + return false; + const candidate = value; + return _ServiceException.prototype.isPrototypeOf(candidate) || Boolean(candidate.$fault) && Boolean(candidate.$metadata) && (candidate.$fault === "client" || candidate.$fault === "server"); + } + /** + * Custom instanceof check to support the operator for ServiceException base class + */ + static [Symbol.hasInstance](instance) { + if (!instance) + return false; + const candidate = instance; + if (this === _ServiceException) { + return _ServiceException.isInstance(instance); + } + if (_ServiceException.isInstance(instance)) { + if (candidate.name && this.name) { + return this.prototype.isPrototypeOf(instance) || candidate.name === this.name; + } + return this.prototype.isPrototypeOf(instance); + } + return false; + } +}; +var decorateServiceException = /* @__PURE__ */ __name((exception, additions = {}) => { + Object.entries(additions).filter(([, v]) => v !== void 0).forEach(([k, v]) => { + if (exception[k] == void 0 || exception[k] === "") { + exception[k] = v; + } + }); + const message = exception.message || exception.Message || "UnknownError"; + exception.message = message; + delete exception.Message; + return exception; +}, "decorateServiceException"); + +// src/default-error-handler.ts +var throwDefaultError = /* @__PURE__ */ __name(({ output, parsedBody, exceptionCtor, errorCode }) => { + const $metadata = deserializeMetadata(output); + const statusCode = $metadata.httpStatusCode ? $metadata.httpStatusCode + "" : void 0; + const response = new exceptionCtor({ + name: parsedBody?.code || parsedBody?.Code || errorCode || statusCode || "UnknownError", + $fault: "client", + $metadata + }); + throw decorateServiceException(response, parsedBody); +}, "throwDefaultError"); +var withBaseException = /* @__PURE__ */ __name((ExceptionCtor) => { + return ({ output, parsedBody, errorCode }) => { + throwDefaultError({ output, parsedBody, exceptionCtor: ExceptionCtor, errorCode }); + }; +}, "withBaseException"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); + +// src/defaults-mode.ts +var loadConfigsForDefaultMode = /* @__PURE__ */ __name((mode) => { + switch (mode) { + case "standard": + return { + retryMode: "standard", + connectionTimeout: 3100 + }; + case "in-region": + return { + retryMode: "standard", + connectionTimeout: 1100 + }; + case "cross-region": + return { + retryMode: "standard", + connectionTimeout: 3100 + }; + case "mobile": + return { + retryMode: "standard", + connectionTimeout: 3e4 + }; + default: + return {}; + } +}, "loadConfigsForDefaultMode"); + +// src/emitWarningIfUnsupportedVersion.ts +var warningEmitted = false; +var emitWarningIfUnsupportedVersion = /* @__PURE__ */ __name((version) => { + if (version && !warningEmitted && parseInt(version.substring(1, version.indexOf("."))) < 16) { + warningEmitted = true; + } +}, "emitWarningIfUnsupportedVersion"); + +// src/extended-encode-uri-component.ts + + +// src/extensions/checksum.ts + +var getChecksumConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const checksumAlgorithms = []; + for (const id in import_types.AlgorithmId) { + const algorithmId = import_types.AlgorithmId[id]; + if (runtimeConfig[algorithmId] === void 0) { + continue; + } + checksumAlgorithms.push({ + algorithmId: () => algorithmId, + checksumConstructor: () => runtimeConfig[algorithmId] + }); + } + return { + addChecksumAlgorithm(algo) { + checksumAlgorithms.push(algo); + }, + checksumAlgorithms() { + return checksumAlgorithms; + } + }; +}, "getChecksumConfiguration"); +var resolveChecksumRuntimeConfig = /* @__PURE__ */ __name((clientConfig) => { + const runtimeConfig = {}; + clientConfig.checksumAlgorithms().forEach((checksumAlgorithm) => { + runtimeConfig[checksumAlgorithm.algorithmId()] = checksumAlgorithm.checksumConstructor(); + }); + return runtimeConfig; +}, "resolveChecksumRuntimeConfig"); + +// src/extensions/retry.ts +var getRetryConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return { + setRetryStrategy(retryStrategy) { + runtimeConfig.retryStrategy = retryStrategy; + }, + retryStrategy() { + return runtimeConfig.retryStrategy; + } + }; +}, "getRetryConfiguration"); +var resolveRetryRuntimeConfig = /* @__PURE__ */ __name((retryStrategyConfiguration) => { + const runtimeConfig = {}; + runtimeConfig.retryStrategy = retryStrategyConfiguration.retryStrategy(); + return runtimeConfig; +}, "resolveRetryRuntimeConfig"); + +// src/extensions/defaultExtensionConfiguration.ts +var getDefaultExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return Object.assign(getChecksumConfiguration(runtimeConfig), getRetryConfiguration(runtimeConfig)); +}, "getDefaultExtensionConfiguration"); +var getDefaultClientConfiguration = getDefaultExtensionConfiguration; +var resolveDefaultRuntimeConfig = /* @__PURE__ */ __name((config) => { + return Object.assign(resolveChecksumRuntimeConfig(config), resolveRetryRuntimeConfig(config)); +}, "resolveDefaultRuntimeConfig"); + +// src/get-array-if-single-item.ts +var getArrayIfSingleItem = /* @__PURE__ */ __name((mayBeArray) => Array.isArray(mayBeArray) ? mayBeArray : [mayBeArray], "getArrayIfSingleItem"); + +// src/get-value-from-text-node.ts +var getValueFromTextNode = /* @__PURE__ */ __name((obj) => { + const textNodeName = "#text"; + for (const key in obj) { + if (obj.hasOwnProperty(key) && obj[key][textNodeName] !== void 0) { + obj[key] = obj[key][textNodeName]; + } else if (typeof obj[key] === "object" && obj[key] !== null) { + obj[key] = getValueFromTextNode(obj[key]); + } + } + return obj; +}, "getValueFromTextNode"); + +// src/is-serializable-header-value.ts +var isSerializableHeaderValue = /* @__PURE__ */ __name((value) => { + return value != null; +}, "isSerializableHeaderValue"); + +// src/NoOpLogger.ts +var NoOpLogger = class { + static { + __name(this, "NoOpLogger"); + } + trace() { + } + debug() { + } + info() { + } + warn() { + } + error() { + } +}; + +// src/object-mapping.ts +function map(arg0, arg1, arg2) { + let target; + let filter; + let instructions; + if (typeof arg1 === "undefined" && typeof arg2 === "undefined") { + target = {}; + instructions = arg0; + } else { + target = arg0; + if (typeof arg1 === "function") { + filter = arg1; + instructions = arg2; + return mapWithFilter(target, filter, instructions); + } else { + instructions = arg1; + } + } + for (const key of Object.keys(instructions)) { + if (!Array.isArray(instructions[key])) { + target[key] = instructions[key]; + continue; + } + applyInstruction(target, null, instructions, key); + } + return target; +} +__name(map, "map"); +var convertMap = /* @__PURE__ */ __name((target) => { + const output = {}; + for (const [k, v] of Object.entries(target || {})) { + output[k] = [, v]; + } + return output; +}, "convertMap"); +var take = /* @__PURE__ */ __name((source, instructions) => { + const out = {}; + for (const key in instructions) { + applyInstruction(out, source, instructions, key); + } + return out; +}, "take"); +var mapWithFilter = /* @__PURE__ */ __name((target, filter, instructions) => { + return map( + target, + Object.entries(instructions).reduce( + (_instructions, [key, value]) => { + if (Array.isArray(value)) { + _instructions[key] = value; + } else { + if (typeof value === "function") { + _instructions[key] = [filter, value()]; + } else { + _instructions[key] = [filter, value]; + } + } + return _instructions; + }, + {} + ) + ); +}, "mapWithFilter"); +var applyInstruction = /* @__PURE__ */ __name((target, source, instructions, targetKey) => { + if (source !== null) { + let instruction = instructions[targetKey]; + if (typeof instruction === "function") { + instruction = [, instruction]; + } + const [filter2 = nonNullish, valueFn = pass, sourceKey = targetKey] = instruction; + if (typeof filter2 === "function" && filter2(source[sourceKey]) || typeof filter2 !== "function" && !!filter2) { + target[targetKey] = valueFn(source[sourceKey]); + } + return; + } + let [filter, value] = instructions[targetKey]; + if (typeof value === "function") { + let _value; + const defaultFilterPassed = filter === void 0 && (_value = value()) != null; + const customFilterPassed = typeof filter === "function" && !!filter(void 0) || typeof filter !== "function" && !!filter; + if (defaultFilterPassed) { + target[targetKey] = _value; + } else if (customFilterPassed) { + target[targetKey] = value(); + } + } else { + const defaultFilterPassed = filter === void 0 && value != null; + const customFilterPassed = typeof filter === "function" && !!filter(value) || typeof filter !== "function" && !!filter; + if (defaultFilterPassed || customFilterPassed) { + target[targetKey] = value; + } + } +}, "applyInstruction"); +var nonNullish = /* @__PURE__ */ __name((_) => _ != null, "nonNullish"); +var pass = /* @__PURE__ */ __name((_) => _, "pass"); + +// src/resolve-path.ts + + +// src/ser-utils.ts +var serializeFloat = /* @__PURE__ */ __name((value) => { + if (value !== value) { + return "NaN"; + } + switch (value) { + case Infinity: + return "Infinity"; + case -Infinity: + return "-Infinity"; + default: + return value; + } +}, "serializeFloat"); +var serializeDateTime = /* @__PURE__ */ __name((date) => date.toISOString().replace(".000Z", "Z"), "serializeDateTime"); + +// src/serde-json.ts +var _json = /* @__PURE__ */ __name((obj) => { + if (obj == null) { + return {}; + } + if (Array.isArray(obj)) { + return obj.filter((_) => _ != null).map(_json); + } + if (typeof obj === "object") { + const target = {}; + for (const key of Object.keys(obj)) { + if (obj[key] == null) { + continue; + } + target[key] = _json(obj[key]); + } + return target; + } + return obj; +}, "_json"); + +// src/index.ts +__reExport(src_exports, __nccwpck_require__(92430), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 90690: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + AlgorithmId: () => AlgorithmId, + EndpointURLScheme: () => EndpointURLScheme, + FieldPosition: () => FieldPosition, + HttpApiKeyAuthLocation: () => HttpApiKeyAuthLocation, + HttpAuthLocation: () => HttpAuthLocation, + IniSectionType: () => IniSectionType, + RequestHandlerProtocol: () => RequestHandlerProtocol, + SMITHY_CONTEXT_KEY: () => SMITHY_CONTEXT_KEY, + getDefaultClientConfiguration: () => getDefaultClientConfiguration, + resolveDefaultRuntimeConfig: () => resolveDefaultRuntimeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/auth/auth.ts +var HttpAuthLocation = /* @__PURE__ */ ((HttpAuthLocation2) => { + HttpAuthLocation2["HEADER"] = "header"; + HttpAuthLocation2["QUERY"] = "query"; + return HttpAuthLocation2; +})(HttpAuthLocation || {}); + +// src/auth/HttpApiKeyAuth.ts +var HttpApiKeyAuthLocation = /* @__PURE__ */ ((HttpApiKeyAuthLocation2) => { + HttpApiKeyAuthLocation2["HEADER"] = "header"; + HttpApiKeyAuthLocation2["QUERY"] = "query"; + return HttpApiKeyAuthLocation2; +})(HttpApiKeyAuthLocation || {}); + +// src/endpoint.ts +var EndpointURLScheme = /* @__PURE__ */ ((EndpointURLScheme2) => { + EndpointURLScheme2["HTTP"] = "http"; + EndpointURLScheme2["HTTPS"] = "https"; + return EndpointURLScheme2; +})(EndpointURLScheme || {}); + +// src/extensions/checksum.ts +var AlgorithmId = /* @__PURE__ */ ((AlgorithmId2) => { + AlgorithmId2["MD5"] = "md5"; + AlgorithmId2["CRC32"] = "crc32"; + AlgorithmId2["CRC32C"] = "crc32c"; + AlgorithmId2["SHA1"] = "sha1"; + AlgorithmId2["SHA256"] = "sha256"; + return AlgorithmId2; +})(AlgorithmId || {}); +var getChecksumConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const checksumAlgorithms = []; + if (runtimeConfig.sha256 !== void 0) { + checksumAlgorithms.push({ + algorithmId: () => "sha256" /* SHA256 */, + checksumConstructor: () => runtimeConfig.sha256 + }); + } + if (runtimeConfig.md5 != void 0) { + checksumAlgorithms.push({ + algorithmId: () => "md5" /* MD5 */, + checksumConstructor: () => runtimeConfig.md5 + }); + } + return { + addChecksumAlgorithm(algo) { + checksumAlgorithms.push(algo); + }, + checksumAlgorithms() { + return checksumAlgorithms; + } + }; +}, "getChecksumConfiguration"); +var resolveChecksumRuntimeConfig = /* @__PURE__ */ __name((clientConfig) => { + const runtimeConfig = {}; + clientConfig.checksumAlgorithms().forEach((checksumAlgorithm) => { + runtimeConfig[checksumAlgorithm.algorithmId()] = checksumAlgorithm.checksumConstructor(); + }); + return runtimeConfig; +}, "resolveChecksumRuntimeConfig"); + +// src/extensions/defaultClientConfiguration.ts +var getDefaultClientConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return getChecksumConfiguration(runtimeConfig); +}, "getDefaultClientConfiguration"); +var resolveDefaultRuntimeConfig = /* @__PURE__ */ __name((config) => { + return resolveChecksumRuntimeConfig(config); +}, "resolveDefaultRuntimeConfig"); + +// src/http.ts +var FieldPosition = /* @__PURE__ */ ((FieldPosition2) => { + FieldPosition2[FieldPosition2["HEADER"] = 0] = "HEADER"; + FieldPosition2[FieldPosition2["TRAILER"] = 1] = "TRAILER"; + return FieldPosition2; +})(FieldPosition || {}); + +// src/middleware.ts +var SMITHY_CONTEXT_KEY = "__smithy_context"; + +// src/profile.ts +var IniSectionType = /* @__PURE__ */ ((IniSectionType2) => { + IniSectionType2["PROFILE"] = "profile"; + IniSectionType2["SSO_SESSION"] = "sso-session"; + IniSectionType2["SERVICES"] = "services"; + return IniSectionType2; +})(IniSectionType || {}); + +// src/transfer.ts +var RequestHandlerProtocol = /* @__PURE__ */ ((RequestHandlerProtocol2) => { + RequestHandlerProtocol2["HTTP_0_9"] = "http/0.9"; + RequestHandlerProtocol2["HTTP_1_0"] = "http/1.0"; + RequestHandlerProtocol2["TDS_8_0"] = "tds/8.0"; + return RequestHandlerProtocol2; +})(RequestHandlerProtocol || {}); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 14494: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + parseUrl: () => parseUrl +}); +module.exports = __toCommonJS(src_exports); +var import_querystring_parser = __nccwpck_require__(18822); +var parseUrl = /* @__PURE__ */ __name((url) => { + if (typeof url === "string") { + return parseUrl(new URL(url)); + } + const { hostname, pathname, port, protocol, search } = url; + let query; + if (search) { + query = (0, import_querystring_parser.parseQueryString)(search); + } + return { + hostname, + port: port ? parseInt(port) : void 0, + protocol, + path: pathname, + query + }; +}, "parseUrl"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 72674: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromBase64 = void 0; +const util_buffer_from_1 = __nccwpck_require__(44151); +const BASE64_REGEX = /^[A-Za-z0-9+/]*={0,2}$/; +const fromBase64 = (input) => { + if ((input.length * 3) % 4 !== 0) { + throw new TypeError(`Incorrect padding on base64 string.`); + } + if (!BASE64_REGEX.exec(input)) { + throw new TypeError(`Invalid base64 string.`); + } + const buffer = (0, util_buffer_from_1.fromString)(input, "base64"); + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); +}; +exports.fromBase64 = fromBase64; + + +/***/ }), + +/***/ 68385: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +module.exports = __toCommonJS(src_exports); +__reExport(src_exports, __nccwpck_require__(72674), module.exports); +__reExport(src_exports, __nccwpck_require__(14871), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 14871: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toBase64 = void 0; +const util_buffer_from_1 = __nccwpck_require__(44151); +const util_utf8_1 = __nccwpck_require__(71577); +const toBase64 = (_input) => { + let input; + if (typeof _input === "string") { + input = (0, util_utf8_1.fromUtf8)(_input); + } + else { + input = _input; + } + if (typeof input !== "object" || typeof input.byteOffset !== "number" || typeof input.byteLength !== "number") { + throw new Error("@smithy/util-base64: toBase64 encoder function only accepts string | Uint8Array."); + } + return (0, util_buffer_from_1.fromArrayBuffer)(input.buffer, input.byteOffset, input.byteLength).toString("base64"); +}; +exports.toBase64 = toBase64; + + +/***/ }), + +/***/ 12098: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + calculateBodyLength: () => calculateBodyLength +}); +module.exports = __toCommonJS(src_exports); + +// src/calculateBodyLength.ts +var TEXT_ENCODER = typeof TextEncoder == "function" ? new TextEncoder() : null; +var calculateBodyLength = /* @__PURE__ */ __name((body) => { + if (typeof body === "string") { + if (TEXT_ENCODER) { + return TEXT_ENCODER.encode(body).byteLength; + } + let len = body.length; + for (let i = len - 1; i >= 0; i--) { + const code = body.charCodeAt(i); + if (code > 127 && code <= 2047) + len++; + else if (code > 2047 && code <= 65535) + len += 2; + if (code >= 56320 && code <= 57343) + i--; + } + return len; + } else if (typeof body.byteLength === "number") { + return body.byteLength; + } else if (typeof body.size === "number") { + return body.size; + } + throw new Error(`Body Length computation failed for ${body}`); +}, "calculateBodyLength"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 13638: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + calculateBodyLength: () => calculateBodyLength +}); +module.exports = __toCommonJS(src_exports); + +// src/calculateBodyLength.ts +var import_fs = __nccwpck_require__(79896); +var calculateBodyLength = /* @__PURE__ */ __name((body) => { + if (!body) { + return 0; + } + if (typeof body === "string") { + return Buffer.byteLength(body); + } else if (typeof body.byteLength === "number") { + return body.byteLength; + } else if (typeof body.size === "number") { + return body.size; + } else if (typeof body.start === "number" && typeof body.end === "number") { + return body.end + 1 - body.start; + } else if (typeof body.path === "string" || Buffer.isBuffer(body.path)) { + return (0, import_fs.lstatSync)(body.path).size; + } else if (typeof body.fd === "number") { + return (0, import_fs.fstatSync)(body.fd).size; + } + throw new Error(`Body Length computation failed for ${body}`); +}, "calculateBodyLength"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 44151: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromArrayBuffer: () => fromArrayBuffer, + fromString: () => fromString +}); +module.exports = __toCommonJS(src_exports); +var import_is_array_buffer = __nccwpck_require__(86130); +var import_buffer = __nccwpck_require__(20181); +var fromArrayBuffer = /* @__PURE__ */ __name((input, offset = 0, length = input.byteLength - offset) => { + if (!(0, import_is_array_buffer.isArrayBuffer)(input)) { + throw new TypeError(`The "input" argument must be ArrayBuffer. Received type ${typeof input} (${input})`); + } + return import_buffer.Buffer.from(input, offset, length); +}, "fromArrayBuffer"); +var fromString = /* @__PURE__ */ __name((input, encoding) => { + if (typeof input !== "string") { + throw new TypeError(`The "input" argument must be of type string. Received type ${typeof input} (${input})`); + } + return encoding ? import_buffer.Buffer.from(input, encoding) : import_buffer.Buffer.from(input); +}, "fromString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 56716: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + SelectorType: () => SelectorType, + booleanSelector: () => booleanSelector, + numberSelector: () => numberSelector +}); +module.exports = __toCommonJS(src_exports); + +// src/booleanSelector.ts +var booleanSelector = /* @__PURE__ */ __name((obj, key, type) => { + if (!(key in obj)) + return void 0; + if (obj[key] === "true") + return true; + if (obj[key] === "false") + return false; + throw new Error(`Cannot load ${type} "${key}". Expected "true" or "false", got ${obj[key]}.`); +}, "booleanSelector"); + +// src/numberSelector.ts +var numberSelector = /* @__PURE__ */ __name((obj, key, type) => { + if (!(key in obj)) + return void 0; + const numberValue = parseInt(obj[key], 10); + if (Number.isNaN(numberValue)) { + throw new TypeError(`Cannot load ${type} '${key}'. Expected number, got '${obj[key]}'.`); + } + return numberValue; +}, "numberSelector"); + +// src/types.ts +var SelectorType = /* @__PURE__ */ ((SelectorType2) => { + SelectorType2["ENV"] = "env"; + SelectorType2["CONFIG"] = "shared config entry"; + return SelectorType2; +})(SelectorType || {}); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 15435: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + resolveDefaultsModeConfig: () => resolveDefaultsModeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/resolveDefaultsModeConfig.ts +var import_config_resolver = __nccwpck_require__(39316); +var import_node_config_provider = __nccwpck_require__(55704); +var import_property_provider = __nccwpck_require__(71238); + +// src/constants.ts +var AWS_EXECUTION_ENV = "AWS_EXECUTION_ENV"; +var AWS_REGION_ENV = "AWS_REGION"; +var AWS_DEFAULT_REGION_ENV = "AWS_DEFAULT_REGION"; +var ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED"; +var DEFAULTS_MODE_OPTIONS = ["in-region", "cross-region", "mobile", "standard", "legacy"]; +var IMDS_REGION_PATH = "/latest/meta-data/placement/region"; + +// src/defaultsModeConfig.ts +var AWS_DEFAULTS_MODE_ENV = "AWS_DEFAULTS_MODE"; +var AWS_DEFAULTS_MODE_CONFIG = "defaults_mode"; +var NODE_DEFAULTS_MODE_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => { + return env[AWS_DEFAULTS_MODE_ENV]; + }, + configFileSelector: (profile) => { + return profile[AWS_DEFAULTS_MODE_CONFIG]; + }, + default: "legacy" +}; + +// src/resolveDefaultsModeConfig.ts +var resolveDefaultsModeConfig = /* @__PURE__ */ __name(({ + region = (0, import_node_config_provider.loadConfig)(import_config_resolver.NODE_REGION_CONFIG_OPTIONS), + defaultsMode = (0, import_node_config_provider.loadConfig)(NODE_DEFAULTS_MODE_CONFIG_OPTIONS) +} = {}) => (0, import_property_provider.memoize)(async () => { + const mode = typeof defaultsMode === "function" ? await defaultsMode() : defaultsMode; + switch (mode?.toLowerCase()) { + case "auto": + return resolveNodeDefaultsModeAuto(region); + case "in-region": + case "cross-region": + case "mobile": + case "standard": + case "legacy": + return Promise.resolve(mode?.toLocaleLowerCase()); + case void 0: + return Promise.resolve("legacy"); + default: + throw new Error( + `Invalid parameter for "defaultsMode", expect ${DEFAULTS_MODE_OPTIONS.join(", ")}, got ${mode}` + ); + } +}), "resolveDefaultsModeConfig"); +var resolveNodeDefaultsModeAuto = /* @__PURE__ */ __name(async (clientRegion) => { + if (clientRegion) { + const resolvedRegion = typeof clientRegion === "function" ? await clientRegion() : clientRegion; + const inferredRegion = await inferPhysicalRegion(); + if (!inferredRegion) { + return "standard"; + } + if (resolvedRegion === inferredRegion) { + return "in-region"; + } else { + return "cross-region"; + } + } + return "standard"; +}, "resolveNodeDefaultsModeAuto"); +var inferPhysicalRegion = /* @__PURE__ */ __name(async () => { + if (process.env[AWS_EXECUTION_ENV] && (process.env[AWS_REGION_ENV] || process.env[AWS_DEFAULT_REGION_ENV])) { + return process.env[AWS_REGION_ENV] ?? process.env[AWS_DEFAULT_REGION_ENV]; + } + if (!process.env[ENV_IMDS_DISABLED]) { + try { + const { getInstanceMetadataEndpoint, httpRequest } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + const endpoint = await getInstanceMetadataEndpoint(); + return (await httpRequest({ ...endpoint, path: IMDS_REGION_PATH })).toString(); + } catch (e) { + } + } +}, "inferPhysicalRegion"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 79674: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EndpointCache: () => EndpointCache, + EndpointError: () => EndpointError, + customEndpointFunctions: () => customEndpointFunctions, + isIpAddress: () => isIpAddress, + isValidHostLabel: () => isValidHostLabel, + resolveEndpoint: () => resolveEndpoint +}); +module.exports = __toCommonJS(src_exports); + +// src/cache/EndpointCache.ts +var EndpointCache = class { + /** + * @param [size] - desired average maximum capacity. A buffer of 10 additional keys will be allowed + * before keys are dropped. + * @param [params] - list of params to consider as part of the cache key. + * + * If the params list is not populated, no caching will happen. + * This may be out of order depending on how the object is created and arrives to this class. + */ + constructor({ size, params }) { + this.data = /* @__PURE__ */ new Map(); + this.parameters = []; + this.capacity = size ?? 50; + if (params) { + this.parameters = params; + } + } + static { + __name(this, "EndpointCache"); + } + /** + * @param endpointParams - query for endpoint. + * @param resolver - provider of the value if not present. + * @returns endpoint corresponding to the query. + */ + get(endpointParams, resolver) { + const key = this.hash(endpointParams); + if (key === false) { + return resolver(); + } + if (!this.data.has(key)) { + if (this.data.size > this.capacity + 10) { + const keys = this.data.keys(); + let i = 0; + while (true) { + const { value, done } = keys.next(); + this.data.delete(value); + if (done || ++i > 10) { + break; + } + } + } + this.data.set(key, resolver()); + } + return this.data.get(key); + } + size() { + return this.data.size; + } + /** + * @returns cache key or false if not cachable. + */ + hash(endpointParams) { + let buffer = ""; + const { parameters } = this; + if (parameters.length === 0) { + return false; + } + for (const param of parameters) { + const val = String(endpointParams[param] ?? ""); + if (val.includes("|;")) { + return false; + } + buffer += val + "|;"; + } + return buffer; + } +}; + +// src/lib/isIpAddress.ts +var IP_V4_REGEX = new RegExp( + `^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$` +); +var isIpAddress = /* @__PURE__ */ __name((value) => IP_V4_REGEX.test(value) || value.startsWith("[") && value.endsWith("]"), "isIpAddress"); + +// src/lib/isValidHostLabel.ts +var VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`); +var isValidHostLabel = /* @__PURE__ */ __name((value, allowSubDomains = false) => { + if (!allowSubDomains) { + return VALID_HOST_LABEL_REGEX.test(value); + } + const labels = value.split("."); + for (const label of labels) { + if (!isValidHostLabel(label)) { + return false; + } + } + return true; +}, "isValidHostLabel"); + +// src/utils/customEndpointFunctions.ts +var customEndpointFunctions = {}; + +// src/debug/debugId.ts +var debugId = "endpoints"; + +// src/debug/toDebugString.ts +function toDebugString(input) { + if (typeof input !== "object" || input == null) { + return input; + } + if ("ref" in input) { + return `$${toDebugString(input.ref)}`; + } + if ("fn" in input) { + return `${input.fn}(${(input.argv || []).map(toDebugString).join(", ")})`; + } + return JSON.stringify(input, null, 2); +} +__name(toDebugString, "toDebugString"); + +// src/types/EndpointError.ts +var EndpointError = class extends Error { + static { + __name(this, "EndpointError"); + } + constructor(message) { + super(message); + this.name = "EndpointError"; + } +}; + +// src/lib/booleanEquals.ts +var booleanEquals = /* @__PURE__ */ __name((value1, value2) => value1 === value2, "booleanEquals"); + +// src/lib/getAttrPathList.ts +var getAttrPathList = /* @__PURE__ */ __name((path) => { + const parts = path.split("."); + const pathList = []; + for (const part of parts) { + const squareBracketIndex = part.indexOf("["); + if (squareBracketIndex !== -1) { + if (part.indexOf("]") !== part.length - 1) { + throw new EndpointError(`Path: '${path}' does not end with ']'`); + } + const arrayIndex = part.slice(squareBracketIndex + 1, -1); + if (Number.isNaN(parseInt(arrayIndex))) { + throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path}'`); + } + if (squareBracketIndex !== 0) { + pathList.push(part.slice(0, squareBracketIndex)); + } + pathList.push(arrayIndex); + } else { + pathList.push(part); + } + } + return pathList; +}, "getAttrPathList"); + +// src/lib/getAttr.ts +var getAttr = /* @__PURE__ */ __name((value, path) => getAttrPathList(path).reduce((acc, index) => { + if (typeof acc !== "object") { + throw new EndpointError(`Index '${index}' in '${path}' not found in '${JSON.stringify(value)}'`); + } else if (Array.isArray(acc)) { + return acc[parseInt(index)]; + } + return acc[index]; +}, value), "getAttr"); + +// src/lib/isSet.ts +var isSet = /* @__PURE__ */ __name((value) => value != null, "isSet"); + +// src/lib/not.ts +var not = /* @__PURE__ */ __name((value) => !value, "not"); + +// src/lib/parseURL.ts +var import_types3 = __nccwpck_require__(90690); +var DEFAULT_PORTS = { + [import_types3.EndpointURLScheme.HTTP]: 80, + [import_types3.EndpointURLScheme.HTTPS]: 443 +}; +var parseURL = /* @__PURE__ */ __name((value) => { + const whatwgURL = (() => { + try { + if (value instanceof URL) { + return value; + } + if (typeof value === "object" && "hostname" in value) { + const { hostname: hostname2, port, protocol: protocol2 = "", path = "", query = {} } = value; + const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${path}`); + url.search = Object.entries(query).map(([k, v]) => `${k}=${v}`).join("&"); + return url; + } + return new URL(value); + } catch (error) { + return null; + } + })(); + if (!whatwgURL) { + console.error(`Unable to parse ${JSON.stringify(value)} as a whatwg URL.`); + return null; + } + const urlString = whatwgURL.href; + const { host, hostname, pathname, protocol, search } = whatwgURL; + if (search) { + return null; + } + const scheme = protocol.slice(0, -1); + if (!Object.values(import_types3.EndpointURLScheme).includes(scheme)) { + return null; + } + const isIp = isIpAddress(hostname); + const inputContainsDefaultPort = urlString.includes(`${host}:${DEFAULT_PORTS[scheme]}`) || typeof value === "string" && value.includes(`${host}:${DEFAULT_PORTS[scheme]}`); + const authority = `${host}${inputContainsDefaultPort ? `:${DEFAULT_PORTS[scheme]}` : ``}`; + return { + scheme, + authority, + path: pathname, + normalizedPath: pathname.endsWith("/") ? pathname : `${pathname}/`, + isIp + }; +}, "parseURL"); + +// src/lib/stringEquals.ts +var stringEquals = /* @__PURE__ */ __name((value1, value2) => value1 === value2, "stringEquals"); + +// src/lib/substring.ts +var substring = /* @__PURE__ */ __name((input, start, stop, reverse) => { + if (start >= stop || input.length < stop) { + return null; + } + if (!reverse) { + return input.substring(start, stop); + } + return input.substring(input.length - stop, input.length - start); +}, "substring"); + +// src/lib/uriEncode.ts +var uriEncode = /* @__PURE__ */ __name((value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`), "uriEncode"); + +// src/utils/endpointFunctions.ts +var endpointFunctions = { + booleanEquals, + getAttr, + isSet, + isValidHostLabel, + not, + parseURL, + stringEquals, + substring, + uriEncode +}; + +// src/utils/evaluateTemplate.ts +var evaluateTemplate = /* @__PURE__ */ __name((template, options) => { + const evaluatedTemplateArr = []; + const templateContext = { + ...options.endpointParams, + ...options.referenceRecord + }; + let currentIndex = 0; + while (currentIndex < template.length) { + const openingBraceIndex = template.indexOf("{", currentIndex); + if (openingBraceIndex === -1) { + evaluatedTemplateArr.push(template.slice(currentIndex)); + break; + } + evaluatedTemplateArr.push(template.slice(currentIndex, openingBraceIndex)); + const closingBraceIndex = template.indexOf("}", openingBraceIndex); + if (closingBraceIndex === -1) { + evaluatedTemplateArr.push(template.slice(openingBraceIndex)); + break; + } + if (template[openingBraceIndex + 1] === "{" && template[closingBraceIndex + 1] === "}") { + evaluatedTemplateArr.push(template.slice(openingBraceIndex + 1, closingBraceIndex)); + currentIndex = closingBraceIndex + 2; + } + const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex); + if (parameterName.includes("#")) { + const [refName, attrName] = parameterName.split("#"); + evaluatedTemplateArr.push(getAttr(templateContext[refName], attrName)); + } else { + evaluatedTemplateArr.push(templateContext[parameterName]); + } + currentIndex = closingBraceIndex + 1; + } + return evaluatedTemplateArr.join(""); +}, "evaluateTemplate"); + +// src/utils/getReferenceValue.ts +var getReferenceValue = /* @__PURE__ */ __name(({ ref }, options) => { + const referenceRecord = { + ...options.endpointParams, + ...options.referenceRecord + }; + return referenceRecord[ref]; +}, "getReferenceValue"); + +// src/utils/evaluateExpression.ts +var evaluateExpression = /* @__PURE__ */ __name((obj, keyName, options) => { + if (typeof obj === "string") { + return evaluateTemplate(obj, options); + } else if (obj["fn"]) { + return callFunction(obj, options); + } else if (obj["ref"]) { + return getReferenceValue(obj, options); + } + throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`); +}, "evaluateExpression"); + +// src/utils/callFunction.ts +var callFunction = /* @__PURE__ */ __name(({ fn, argv }, options) => { + const evaluatedArgs = argv.map( + (arg) => ["boolean", "number"].includes(typeof arg) ? arg : evaluateExpression(arg, "arg", options) + ); + const fnSegments = fn.split("."); + if (fnSegments[0] in customEndpointFunctions && fnSegments[1] != null) { + return customEndpointFunctions[fnSegments[0]][fnSegments[1]](...evaluatedArgs); + } + return endpointFunctions[fn](...evaluatedArgs); +}, "callFunction"); + +// src/utils/evaluateCondition.ts +var evaluateCondition = /* @__PURE__ */ __name(({ assign, ...fnArgs }, options) => { + if (assign && assign in options.referenceRecord) { + throw new EndpointError(`'${assign}' is already defined in Reference Record.`); + } + const value = callFunction(fnArgs, options); + options.logger?.debug?.(`${debugId} evaluateCondition: ${toDebugString(fnArgs)} = ${toDebugString(value)}`); + return { + result: value === "" ? true : !!value, + ...assign != null && { toAssign: { name: assign, value } } + }; +}, "evaluateCondition"); + +// src/utils/evaluateConditions.ts +var evaluateConditions = /* @__PURE__ */ __name((conditions = [], options) => { + const conditionsReferenceRecord = {}; + for (const condition of conditions) { + const { result, toAssign } = evaluateCondition(condition, { + ...options, + referenceRecord: { + ...options.referenceRecord, + ...conditionsReferenceRecord + } + }); + if (!result) { + return { result }; + } + if (toAssign) { + conditionsReferenceRecord[toAssign.name] = toAssign.value; + options.logger?.debug?.(`${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`); + } + } + return { result: true, referenceRecord: conditionsReferenceRecord }; +}, "evaluateConditions"); + +// src/utils/getEndpointHeaders.ts +var getEndpointHeaders = /* @__PURE__ */ __name((headers, options) => Object.entries(headers).reduce( + (acc, [headerKey, headerVal]) => ({ + ...acc, + [headerKey]: headerVal.map((headerValEntry) => { + const processedExpr = evaluateExpression(headerValEntry, "Header value entry", options); + if (typeof processedExpr !== "string") { + throw new EndpointError(`Header '${headerKey}' value '${processedExpr}' is not a string`); + } + return processedExpr; + }) + }), + {} +), "getEndpointHeaders"); + +// src/utils/getEndpointProperty.ts +var getEndpointProperty = /* @__PURE__ */ __name((property, options) => { + if (Array.isArray(property)) { + return property.map((propertyEntry) => getEndpointProperty(propertyEntry, options)); + } + switch (typeof property) { + case "string": + return evaluateTemplate(property, options); + case "object": + if (property === null) { + throw new EndpointError(`Unexpected endpoint property: ${property}`); + } + return getEndpointProperties(property, options); + case "boolean": + return property; + default: + throw new EndpointError(`Unexpected endpoint property type: ${typeof property}`); + } +}, "getEndpointProperty"); + +// src/utils/getEndpointProperties.ts +var getEndpointProperties = /* @__PURE__ */ __name((properties, options) => Object.entries(properties).reduce( + (acc, [propertyKey, propertyVal]) => ({ + ...acc, + [propertyKey]: getEndpointProperty(propertyVal, options) + }), + {} +), "getEndpointProperties"); + +// src/utils/getEndpointUrl.ts +var getEndpointUrl = /* @__PURE__ */ __name((endpointUrl, options) => { + const expression = evaluateExpression(endpointUrl, "Endpoint URL", options); + if (typeof expression === "string") { + try { + return new URL(expression); + } catch (error) { + console.error(`Failed to construct URL with ${expression}`, error); + throw error; + } + } + throw new EndpointError(`Endpoint URL must be a string, got ${typeof expression}`); +}, "getEndpointUrl"); + +// src/utils/evaluateEndpointRule.ts +var evaluateEndpointRule = /* @__PURE__ */ __name((endpointRule, options) => { + const { conditions, endpoint } = endpointRule; + const { result, referenceRecord } = evaluateConditions(conditions, options); + if (!result) { + return; + } + const endpointRuleOptions = { + ...options, + referenceRecord: { ...options.referenceRecord, ...referenceRecord } + }; + const { url, properties, headers } = endpoint; + options.logger?.debug?.(`${debugId} Resolving endpoint from template: ${toDebugString(endpoint)}`); + return { + ...headers != void 0 && { + headers: getEndpointHeaders(headers, endpointRuleOptions) + }, + ...properties != void 0 && { + properties: getEndpointProperties(properties, endpointRuleOptions) + }, + url: getEndpointUrl(url, endpointRuleOptions) + }; +}, "evaluateEndpointRule"); + +// src/utils/evaluateErrorRule.ts +var evaluateErrorRule = /* @__PURE__ */ __name((errorRule, options) => { + const { conditions, error } = errorRule; + const { result, referenceRecord } = evaluateConditions(conditions, options); + if (!result) { + return; + } + throw new EndpointError( + evaluateExpression(error, "Error", { + ...options, + referenceRecord: { ...options.referenceRecord, ...referenceRecord } + }) + ); +}, "evaluateErrorRule"); + +// src/utils/evaluateTreeRule.ts +var evaluateTreeRule = /* @__PURE__ */ __name((treeRule, options) => { + const { conditions, rules } = treeRule; + const { result, referenceRecord } = evaluateConditions(conditions, options); + if (!result) { + return; + } + return evaluateRules(rules, { + ...options, + referenceRecord: { ...options.referenceRecord, ...referenceRecord } + }); +}, "evaluateTreeRule"); + +// src/utils/evaluateRules.ts +var evaluateRules = /* @__PURE__ */ __name((rules, options) => { + for (const rule of rules) { + if (rule.type === "endpoint") { + const endpointOrUndefined = evaluateEndpointRule(rule, options); + if (endpointOrUndefined) { + return endpointOrUndefined; + } + } else if (rule.type === "error") { + evaluateErrorRule(rule, options); + } else if (rule.type === "tree") { + const endpointOrUndefined = evaluateTreeRule(rule, options); + if (endpointOrUndefined) { + return endpointOrUndefined; + } + } else { + throw new EndpointError(`Unknown endpoint rule: ${rule}`); + } + } + throw new EndpointError(`Rules evaluation failed`); +}, "evaluateRules"); + +// src/resolveEndpoint.ts +var resolveEndpoint = /* @__PURE__ */ __name((ruleSetObject, options) => { + const { endpointParams, logger } = options; + const { parameters, rules } = ruleSetObject; + options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`); + const paramsWithDefault = Object.entries(parameters).filter(([, v]) => v.default != null).map(([k, v]) => [k, v.default]); + if (paramsWithDefault.length > 0) { + for (const [paramKey, paramDefaultValue] of paramsWithDefault) { + endpointParams[paramKey] = endpointParams[paramKey] ?? paramDefaultValue; + } + } + const requiredParams = Object.entries(parameters).filter(([, v]) => v.required).map(([k]) => k); + for (const requiredParam of requiredParams) { + if (endpointParams[requiredParam] == null) { + throw new EndpointError(`Missing required parameter: '${requiredParam}'`); + } + } + const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} }); + options.logger?.debug?.(`${debugId} Resolved endpoint: ${toDebugString(endpoint)}`); + return endpoint; +}, "resolveEndpoint"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 96435: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromHex: () => fromHex, + toHex: () => toHex +}); +module.exports = __toCommonJS(src_exports); +var SHORT_TO_HEX = {}; +var HEX_TO_SHORT = {}; +for (let i = 0; i < 256; i++) { + let encodedByte = i.toString(16).toLowerCase(); + if (encodedByte.length === 1) { + encodedByte = `0${encodedByte}`; + } + SHORT_TO_HEX[i] = encodedByte; + HEX_TO_SHORT[encodedByte] = i; +} +function fromHex(encoded) { + if (encoded.length % 2 !== 0) { + throw new Error("Hex encoded strings must have an even number length"); + } + const out = new Uint8Array(encoded.length / 2); + for (let i = 0; i < encoded.length; i += 2) { + const encodedByte = encoded.slice(i, i + 2).toLowerCase(); + if (encodedByte in HEX_TO_SHORT) { + out[i / 2] = HEX_TO_SHORT[encodedByte]; + } else { + throw new Error(`Cannot decode unrecognized sequence ${encodedByte} as hexadecimal`); + } + } + return out; +} +__name(fromHex, "fromHex"); +function toHex(bytes) { + let out = ""; + for (let i = 0; i < bytes.byteLength; i++) { + out += SHORT_TO_HEX[bytes[i]]; + } + return out; +} +__name(toHex, "toHex"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 76324: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + getSmithyContext: () => getSmithyContext, + normalizeProvider: () => normalizeProvider +}); +module.exports = __toCommonJS(src_exports); + +// src/getSmithyContext.ts +var import_types = __nccwpck_require__(90690); +var getSmithyContext = /* @__PURE__ */ __name((context) => context[import_types.SMITHY_CONTEXT_KEY] || (context[import_types.SMITHY_CONTEXT_KEY] = {}), "getSmithyContext"); + +// src/normalizeProvider.ts +var normalizeProvider = /* @__PURE__ */ __name((input) => { + if (typeof input === "function") + return input; + const promisified = Promise.resolve(input); + return () => promisified; +}, "normalizeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 15518: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + AdaptiveRetryStrategy: () => AdaptiveRetryStrategy, + ConfiguredRetryStrategy: () => ConfiguredRetryStrategy, + DEFAULT_MAX_ATTEMPTS: () => DEFAULT_MAX_ATTEMPTS, + DEFAULT_RETRY_DELAY_BASE: () => DEFAULT_RETRY_DELAY_BASE, + DEFAULT_RETRY_MODE: () => DEFAULT_RETRY_MODE, + DefaultRateLimiter: () => DefaultRateLimiter, + INITIAL_RETRY_TOKENS: () => INITIAL_RETRY_TOKENS, + INVOCATION_ID_HEADER: () => INVOCATION_ID_HEADER, + MAXIMUM_RETRY_DELAY: () => MAXIMUM_RETRY_DELAY, + NO_RETRY_INCREMENT: () => NO_RETRY_INCREMENT, + REQUEST_HEADER: () => REQUEST_HEADER, + RETRY_COST: () => RETRY_COST, + RETRY_MODES: () => RETRY_MODES, + StandardRetryStrategy: () => StandardRetryStrategy, + THROTTLING_RETRY_DELAY_BASE: () => THROTTLING_RETRY_DELAY_BASE, + TIMEOUT_RETRY_COST: () => TIMEOUT_RETRY_COST +}); +module.exports = __toCommonJS(src_exports); + +// src/config.ts +var RETRY_MODES = /* @__PURE__ */ ((RETRY_MODES2) => { + RETRY_MODES2["STANDARD"] = "standard"; + RETRY_MODES2["ADAPTIVE"] = "adaptive"; + return RETRY_MODES2; +})(RETRY_MODES || {}); +var DEFAULT_MAX_ATTEMPTS = 3; +var DEFAULT_RETRY_MODE = "standard" /* STANDARD */; + +// src/DefaultRateLimiter.ts +var import_service_error_classification = __nccwpck_require__(42058); +var DefaultRateLimiter = class _DefaultRateLimiter { + constructor(options) { + // Pre-set state variables + this.currentCapacity = 0; + this.enabled = false; + this.lastMaxRate = 0; + this.measuredTxRate = 0; + this.requestCount = 0; + this.lastTimestamp = 0; + this.timeWindow = 0; + this.beta = options?.beta ?? 0.7; + this.minCapacity = options?.minCapacity ?? 1; + this.minFillRate = options?.minFillRate ?? 0.5; + this.scaleConstant = options?.scaleConstant ?? 0.4; + this.smooth = options?.smooth ?? 0.8; + const currentTimeInSeconds = this.getCurrentTimeInSeconds(); + this.lastThrottleTime = currentTimeInSeconds; + this.lastTxRateBucket = Math.floor(this.getCurrentTimeInSeconds()); + this.fillRate = this.minFillRate; + this.maxCapacity = this.minCapacity; + } + static { + __name(this, "DefaultRateLimiter"); + } + static { + /** + * Only used in testing. + */ + this.setTimeoutFn = setTimeout; + } + getCurrentTimeInSeconds() { + return Date.now() / 1e3; + } + async getSendToken() { + return this.acquireTokenBucket(1); + } + async acquireTokenBucket(amount) { + if (!this.enabled) { + return; + } + this.refillTokenBucket(); + if (amount > this.currentCapacity) { + const delay = (amount - this.currentCapacity) / this.fillRate * 1e3; + await new Promise((resolve) => _DefaultRateLimiter.setTimeoutFn(resolve, delay)); + } + this.currentCapacity = this.currentCapacity - amount; + } + refillTokenBucket() { + const timestamp = this.getCurrentTimeInSeconds(); + if (!this.lastTimestamp) { + this.lastTimestamp = timestamp; + return; + } + const fillAmount = (timestamp - this.lastTimestamp) * this.fillRate; + this.currentCapacity = Math.min(this.maxCapacity, this.currentCapacity + fillAmount); + this.lastTimestamp = timestamp; + } + updateClientSendingRate(response) { + let calculatedRate; + this.updateMeasuredRate(); + if ((0, import_service_error_classification.isThrottlingError)(response)) { + const rateToUse = !this.enabled ? this.measuredTxRate : Math.min(this.measuredTxRate, this.fillRate); + this.lastMaxRate = rateToUse; + this.calculateTimeWindow(); + this.lastThrottleTime = this.getCurrentTimeInSeconds(); + calculatedRate = this.cubicThrottle(rateToUse); + this.enableTokenBucket(); + } else { + this.calculateTimeWindow(); + calculatedRate = this.cubicSuccess(this.getCurrentTimeInSeconds()); + } + const newRate = Math.min(calculatedRate, 2 * this.measuredTxRate); + this.updateTokenBucketRate(newRate); + } + calculateTimeWindow() { + this.timeWindow = this.getPrecise(Math.pow(this.lastMaxRate * (1 - this.beta) / this.scaleConstant, 1 / 3)); + } + cubicThrottle(rateToUse) { + return this.getPrecise(rateToUse * this.beta); + } + cubicSuccess(timestamp) { + return this.getPrecise( + this.scaleConstant * Math.pow(timestamp - this.lastThrottleTime - this.timeWindow, 3) + this.lastMaxRate + ); + } + enableTokenBucket() { + this.enabled = true; + } + updateTokenBucketRate(newRate) { + this.refillTokenBucket(); + this.fillRate = Math.max(newRate, this.minFillRate); + this.maxCapacity = Math.max(newRate, this.minCapacity); + this.currentCapacity = Math.min(this.currentCapacity, this.maxCapacity); + } + updateMeasuredRate() { + const t = this.getCurrentTimeInSeconds(); + const timeBucket = Math.floor(t * 2) / 2; + this.requestCount++; + if (timeBucket > this.lastTxRateBucket) { + const currentRate = this.requestCount / (timeBucket - this.lastTxRateBucket); + this.measuredTxRate = this.getPrecise(currentRate * this.smooth + this.measuredTxRate * (1 - this.smooth)); + this.requestCount = 0; + this.lastTxRateBucket = timeBucket; + } + } + getPrecise(num) { + return parseFloat(num.toFixed(8)); + } +}; + +// src/constants.ts +var DEFAULT_RETRY_DELAY_BASE = 100; +var MAXIMUM_RETRY_DELAY = 20 * 1e3; +var THROTTLING_RETRY_DELAY_BASE = 500; +var INITIAL_RETRY_TOKENS = 500; +var RETRY_COST = 5; +var TIMEOUT_RETRY_COST = 10; +var NO_RETRY_INCREMENT = 1; +var INVOCATION_ID_HEADER = "amz-sdk-invocation-id"; +var REQUEST_HEADER = "amz-sdk-request"; + +// src/defaultRetryBackoffStrategy.ts +var getDefaultRetryBackoffStrategy = /* @__PURE__ */ __name(() => { + let delayBase = DEFAULT_RETRY_DELAY_BASE; + const computeNextBackoffDelay = /* @__PURE__ */ __name((attempts) => { + return Math.floor(Math.min(MAXIMUM_RETRY_DELAY, Math.random() * 2 ** attempts * delayBase)); + }, "computeNextBackoffDelay"); + const setDelayBase = /* @__PURE__ */ __name((delay) => { + delayBase = delay; + }, "setDelayBase"); + return { + computeNextBackoffDelay, + setDelayBase + }; +}, "getDefaultRetryBackoffStrategy"); + +// src/defaultRetryToken.ts +var createDefaultRetryToken = /* @__PURE__ */ __name(({ + retryDelay, + retryCount, + retryCost +}) => { + const getRetryCount = /* @__PURE__ */ __name(() => retryCount, "getRetryCount"); + const getRetryDelay = /* @__PURE__ */ __name(() => Math.min(MAXIMUM_RETRY_DELAY, retryDelay), "getRetryDelay"); + const getRetryCost = /* @__PURE__ */ __name(() => retryCost, "getRetryCost"); + return { + getRetryCount, + getRetryDelay, + getRetryCost + }; +}, "createDefaultRetryToken"); + +// src/StandardRetryStrategy.ts +var StandardRetryStrategy = class { + constructor(maxAttempts) { + this.maxAttempts = maxAttempts; + this.mode = "standard" /* STANDARD */; + this.capacity = INITIAL_RETRY_TOKENS; + this.retryBackoffStrategy = getDefaultRetryBackoffStrategy(); + this.maxAttemptsProvider = typeof maxAttempts === "function" ? maxAttempts : async () => maxAttempts; + } + static { + __name(this, "StandardRetryStrategy"); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async acquireInitialRetryToken(retryTokenScope) { + return createDefaultRetryToken({ + retryDelay: DEFAULT_RETRY_DELAY_BASE, + retryCount: 0 + }); + } + async refreshRetryTokenForRetry(token, errorInfo) { + const maxAttempts = await this.getMaxAttempts(); + if (this.shouldRetry(token, errorInfo, maxAttempts)) { + const errorType = errorInfo.errorType; + this.retryBackoffStrategy.setDelayBase( + errorType === "THROTTLING" ? THROTTLING_RETRY_DELAY_BASE : DEFAULT_RETRY_DELAY_BASE + ); + const delayFromErrorType = this.retryBackoffStrategy.computeNextBackoffDelay(token.getRetryCount()); + const retryDelay = errorInfo.retryAfterHint ? Math.max(errorInfo.retryAfterHint.getTime() - Date.now() || 0, delayFromErrorType) : delayFromErrorType; + const capacityCost = this.getCapacityCost(errorType); + this.capacity -= capacityCost; + return createDefaultRetryToken({ + retryDelay, + retryCount: token.getRetryCount() + 1, + retryCost: capacityCost + }); + } + throw new Error("No retry token available"); + } + recordSuccess(token) { + this.capacity = Math.max(INITIAL_RETRY_TOKENS, this.capacity + (token.getRetryCost() ?? NO_RETRY_INCREMENT)); + } + /** + * @returns the current available retry capacity. + * + * This number decreases when retries are executed and refills when requests or retries succeed. + */ + getCapacity() { + return this.capacity; + } + async getMaxAttempts() { + try { + return await this.maxAttemptsProvider(); + } catch (error) { + console.warn(`Max attempts provider could not resolve. Using default of ${DEFAULT_MAX_ATTEMPTS}`); + return DEFAULT_MAX_ATTEMPTS; + } + } + shouldRetry(tokenToRenew, errorInfo, maxAttempts) { + const attempts = tokenToRenew.getRetryCount() + 1; + return attempts < maxAttempts && this.capacity >= this.getCapacityCost(errorInfo.errorType) && this.isRetryableError(errorInfo.errorType); + } + getCapacityCost(errorType) { + return errorType === "TRANSIENT" ? TIMEOUT_RETRY_COST : RETRY_COST; + } + isRetryableError(errorType) { + return errorType === "THROTTLING" || errorType === "TRANSIENT"; + } +}; + +// src/AdaptiveRetryStrategy.ts +var AdaptiveRetryStrategy = class { + constructor(maxAttemptsProvider, options) { + this.maxAttemptsProvider = maxAttemptsProvider; + this.mode = "adaptive" /* ADAPTIVE */; + const { rateLimiter } = options ?? {}; + this.rateLimiter = rateLimiter ?? new DefaultRateLimiter(); + this.standardRetryStrategy = new StandardRetryStrategy(maxAttemptsProvider); + } + static { + __name(this, "AdaptiveRetryStrategy"); + } + async acquireInitialRetryToken(retryTokenScope) { + await this.rateLimiter.getSendToken(); + return this.standardRetryStrategy.acquireInitialRetryToken(retryTokenScope); + } + async refreshRetryTokenForRetry(tokenToRenew, errorInfo) { + this.rateLimiter.updateClientSendingRate(errorInfo); + return this.standardRetryStrategy.refreshRetryTokenForRetry(tokenToRenew, errorInfo); + } + recordSuccess(token) { + this.rateLimiter.updateClientSendingRate({}); + this.standardRetryStrategy.recordSuccess(token); + } +}; + +// src/ConfiguredRetryStrategy.ts +var ConfiguredRetryStrategy = class extends StandardRetryStrategy { + static { + __name(this, "ConfiguredRetryStrategy"); + } + /** + * @param maxAttempts - the maximum number of retry attempts allowed. + * e.g., if set to 3, then 4 total requests are possible. + * @param computeNextBackoffDelay - a millisecond delay for each retry or a function that takes the retry attempt + * and returns the delay. + * + * @example exponential backoff. + * ```js + * new Client({ + * retryStrategy: new ConfiguredRetryStrategy(3, (attempt) => attempt ** 2) + * }); + * ``` + * @example constant delay. + * ```js + * new Client({ + * retryStrategy: new ConfiguredRetryStrategy(3, 2000) + * }); + * ``` + */ + constructor(maxAttempts, computeNextBackoffDelay = DEFAULT_RETRY_DELAY_BASE) { + super(typeof maxAttempts === "function" ? maxAttempts : async () => maxAttempts); + if (typeof computeNextBackoffDelay === "number") { + this.computeNextBackoffDelay = () => computeNextBackoffDelay; + } else { + this.computeNextBackoffDelay = computeNextBackoffDelay; + } + } + async refreshRetryTokenForRetry(tokenToRenew, errorInfo) { + const token = await super.refreshRetryTokenForRetry(tokenToRenew, errorInfo); + token.getRetryDelay = () => this.computeNextBackoffDelay(token.getRetryCount()); + return token; + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 31732: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ByteArrayCollector = void 0; +class ByteArrayCollector { + constructor(allocByteArray) { + this.allocByteArray = allocByteArray; + this.byteLength = 0; + this.byteArrays = []; + } + push(byteArray) { + this.byteArrays.push(byteArray); + this.byteLength += byteArray.byteLength; + } + flush() { + if (this.byteArrays.length === 1) { + const bytes = this.byteArrays[0]; + this.reset(); + return bytes; + } + const aggregation = this.allocByteArray(this.byteLength); + let cursor = 0; + for (let i = 0; i < this.byteArrays.length; ++i) { + const bytes = this.byteArrays[i]; + aggregation.set(bytes, cursor); + cursor += bytes.byteLength; + } + this.reset(); + return aggregation; + } + reset() { + this.byteArrays = []; + this.byteLength = 0; + } +} +exports.ByteArrayCollector = ByteArrayCollector; + + +/***/ }), + +/***/ 87753: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ChecksumStream = void 0; +const ReadableStreamRef = typeof ReadableStream === "function" ? ReadableStream : function () { }; +class ChecksumStream extends ReadableStreamRef { +} +exports.ChecksumStream = ChecksumStream; + + +/***/ }), + +/***/ 71775: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ChecksumStream = void 0; +const util_base64_1 = __nccwpck_require__(68385); +const stream_1 = __nccwpck_require__(2203); +class ChecksumStream extends stream_1.Duplex { + constructor({ expectedChecksum, checksum, source, checksumSourceLocation, base64Encoder, }) { + var _a, _b; + super(); + if (typeof source.pipe === "function") { + this.source = source; + } + else { + throw new Error(`@smithy/util-stream: unsupported source type ${(_b = (_a = source === null || source === void 0 ? void 0 : source.constructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : source} in ChecksumStream.`); + } + this.base64Encoder = base64Encoder !== null && base64Encoder !== void 0 ? base64Encoder : util_base64_1.toBase64; + this.expectedChecksum = expectedChecksum; + this.checksum = checksum; + this.checksumSourceLocation = checksumSourceLocation; + this.source.pipe(this); + } + _read(size) { } + _write(chunk, encoding, callback) { + try { + this.checksum.update(chunk); + this.push(chunk); + } + catch (e) { + return callback(e); + } + return callback(); + } + async _final(callback) { + try { + const digest = await this.checksum.digest(); + const received = this.base64Encoder(digest); + if (this.expectedChecksum !== received) { + return callback(new Error(`Checksum mismatch: expected "${this.expectedChecksum}" but received "${received}"` + + ` in response header "${this.checksumSourceLocation}".`)); + } + } + catch (e) { + return callback(e); + } + this.push(null); + return callback(); + } +} +exports.ChecksumStream = ChecksumStream; + + +/***/ }), + +/***/ 94129: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createChecksumStream = void 0; +const util_base64_1 = __nccwpck_require__(68385); +const stream_type_check_1 = __nccwpck_require__(4414); +const ChecksumStream_browser_1 = __nccwpck_require__(87753); +const createChecksumStream = ({ expectedChecksum, checksum, source, checksumSourceLocation, base64Encoder, }) => { + var _a, _b; + if (!(0, stream_type_check_1.isReadableStream)(source)) { + throw new Error(`@smithy/util-stream: unsupported source type ${(_b = (_a = source === null || source === void 0 ? void 0 : source.constructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : source} in ChecksumStream.`); + } + const encoder = base64Encoder !== null && base64Encoder !== void 0 ? base64Encoder : util_base64_1.toBase64; + if (typeof TransformStream !== "function") { + throw new Error("@smithy/util-stream: unable to instantiate ChecksumStream because API unavailable: ReadableStream/TransformStream."); + } + const transform = new TransformStream({ + start() { }, + async transform(chunk, controller) { + checksum.update(chunk); + controller.enqueue(chunk); + }, + async flush(controller) { + const digest = await checksum.digest(); + const received = encoder(digest); + if (expectedChecksum !== received) { + const error = new Error(`Checksum mismatch: expected "${expectedChecksum}" but received "${received}"` + + ` in response header "${checksumSourceLocation}".`); + controller.error(error); + } + else { + controller.terminate(); + } + }, + }); + source.pipeThrough(transform); + const readable = transform.readable; + Object.setPrototypeOf(readable, ChecksumStream_browser_1.ChecksumStream.prototype); + return readable; +}; +exports.createChecksumStream = createChecksumStream; + + +/***/ }), + +/***/ 5639: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createChecksumStream = createChecksumStream; +const stream_type_check_1 = __nccwpck_require__(4414); +const ChecksumStream_1 = __nccwpck_require__(71775); +const createChecksumStream_browser_1 = __nccwpck_require__(94129); +function createChecksumStream(init) { + if (typeof ReadableStream === "function" && (0, stream_type_check_1.isReadableStream)(init.source)) { + return (0, createChecksumStream_browser_1.createChecksumStream)(init); + } + return new ChecksumStream_1.ChecksumStream(init); +} + + +/***/ }), + +/***/ 72005: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createBufferedReadable = createBufferedReadable; +const node_stream_1 = __nccwpck_require__(57075); +const ByteArrayCollector_1 = __nccwpck_require__(31732); +const createBufferedReadableStream_1 = __nccwpck_require__(78213); +const stream_type_check_1 = __nccwpck_require__(4414); +function createBufferedReadable(upstream, size, logger) { + if ((0, stream_type_check_1.isReadableStream)(upstream)) { + return (0, createBufferedReadableStream_1.createBufferedReadableStream)(upstream, size, logger); + } + const downstream = new node_stream_1.Readable({ read() { } }); + let streamBufferingLoggedWarning = false; + let bytesSeen = 0; + const buffers = [ + "", + new ByteArrayCollector_1.ByteArrayCollector((size) => new Uint8Array(size)), + new ByteArrayCollector_1.ByteArrayCollector((size) => Buffer.from(new Uint8Array(size))), + ]; + let mode = -1; + upstream.on("data", (chunk) => { + const chunkMode = (0, createBufferedReadableStream_1.modeOf)(chunk, true); + if (mode !== chunkMode) { + if (mode >= 0) { + downstream.push((0, createBufferedReadableStream_1.flush)(buffers, mode)); + } + mode = chunkMode; + } + if (mode === -1) { + downstream.push(chunk); + return; + } + const chunkSize = (0, createBufferedReadableStream_1.sizeOf)(chunk); + bytesSeen += chunkSize; + const bufferSize = (0, createBufferedReadableStream_1.sizeOf)(buffers[mode]); + if (chunkSize >= size && bufferSize === 0) { + downstream.push(chunk); + } + else { + const newSize = (0, createBufferedReadableStream_1.merge)(buffers, mode, chunk); + if (!streamBufferingLoggedWarning && bytesSeen > size * 2) { + streamBufferingLoggedWarning = true; + logger === null || logger === void 0 ? void 0 : logger.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`); + } + if (newSize >= size) { + downstream.push((0, createBufferedReadableStream_1.flush)(buffers, mode)); + } + } + }); + upstream.on("end", () => { + if (mode !== -1) { + const remainder = (0, createBufferedReadableStream_1.flush)(buffers, mode); + if ((0, createBufferedReadableStream_1.sizeOf)(remainder) > 0) { + downstream.push(remainder); + } + } + downstream.push(null); + }); + return downstream; +} + + +/***/ }), + +/***/ 78213: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createBufferedReadable = void 0; +exports.createBufferedReadableStream = createBufferedReadableStream; +exports.merge = merge; +exports.flush = flush; +exports.sizeOf = sizeOf; +exports.modeOf = modeOf; +const ByteArrayCollector_1 = __nccwpck_require__(31732); +function createBufferedReadableStream(upstream, size, logger) { + const reader = upstream.getReader(); + let streamBufferingLoggedWarning = false; + let bytesSeen = 0; + const buffers = ["", new ByteArrayCollector_1.ByteArrayCollector((size) => new Uint8Array(size))]; + let mode = -1; + const pull = async (controller) => { + const { value, done } = await reader.read(); + const chunk = value; + if (done) { + if (mode !== -1) { + const remainder = flush(buffers, mode); + if (sizeOf(remainder) > 0) { + controller.enqueue(remainder); + } + } + controller.close(); + } + else { + const chunkMode = modeOf(chunk, false); + if (mode !== chunkMode) { + if (mode >= 0) { + controller.enqueue(flush(buffers, mode)); + } + mode = chunkMode; + } + if (mode === -1) { + controller.enqueue(chunk); + return; + } + const chunkSize = sizeOf(chunk); + bytesSeen += chunkSize; + const bufferSize = sizeOf(buffers[mode]); + if (chunkSize >= size && bufferSize === 0) { + controller.enqueue(chunk); + } + else { + const newSize = merge(buffers, mode, chunk); + if (!streamBufferingLoggedWarning && bytesSeen > size * 2) { + streamBufferingLoggedWarning = true; + logger === null || logger === void 0 ? void 0 : logger.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`); + } + if (newSize >= size) { + controller.enqueue(flush(buffers, mode)); + } + else { + await pull(controller); + } + } + } + }; + return new ReadableStream({ + pull, + }); +} +exports.createBufferedReadable = createBufferedReadableStream; +function merge(buffers, mode, chunk) { + switch (mode) { + case 0: + buffers[0] += chunk; + return sizeOf(buffers[0]); + case 1: + case 2: + buffers[mode].push(chunk); + return sizeOf(buffers[mode]); + } +} +function flush(buffers, mode) { + switch (mode) { + case 0: + const s = buffers[0]; + buffers[0] = ""; + return s; + case 1: + case 2: + return buffers[mode].flush(); + } + throw new Error(`@smithy/util-stream - invalid index ${mode} given to flush()`); +} +function sizeOf(chunk) { + var _a, _b; + return (_b = (_a = chunk === null || chunk === void 0 ? void 0 : chunk.byteLength) !== null && _a !== void 0 ? _a : chunk === null || chunk === void 0 ? void 0 : chunk.length) !== null && _b !== void 0 ? _b : 0; +} +function modeOf(chunk, allowBuffer = true) { + if (allowBuffer && typeof Buffer !== "undefined" && chunk instanceof Buffer) { + return 2; + } + if (chunk instanceof Uint8Array) { + return 1; + } + if (typeof chunk === "string") { + return 0; + } + return -1; +} + + +/***/ }), + +/***/ 6522: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getAwsChunkedEncodingStream = void 0; +const stream_1 = __nccwpck_require__(2203); +const getAwsChunkedEncodingStream = (readableStream, options) => { + const { base64Encoder, bodyLengthChecker, checksumAlgorithmFn, checksumLocationName, streamHasher } = options; + const checksumRequired = base64Encoder !== undefined && + checksumAlgorithmFn !== undefined && + checksumLocationName !== undefined && + streamHasher !== undefined; + const digest = checksumRequired ? streamHasher(checksumAlgorithmFn, readableStream) : undefined; + const awsChunkedEncodingStream = new stream_1.Readable({ read: () => { } }); + readableStream.on("data", (data) => { + const length = bodyLengthChecker(data) || 0; + awsChunkedEncodingStream.push(`${length.toString(16)}\r\n`); + awsChunkedEncodingStream.push(data); + awsChunkedEncodingStream.push("\r\n"); + }); + readableStream.on("end", async () => { + awsChunkedEncodingStream.push(`0\r\n`); + if (checksumRequired) { + const checksum = base64Encoder(await digest); + awsChunkedEncodingStream.push(`${checksumLocationName}:${checksum}\r\n`); + awsChunkedEncodingStream.push(`\r\n`); + } + awsChunkedEncodingStream.push(null); + }); + return awsChunkedEncodingStream; +}; +exports.getAwsChunkedEncodingStream = getAwsChunkedEncodingStream; + + +/***/ }), + +/***/ 80066: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.headStream = headStream; +async function headStream(stream, bytes) { + var _a; + let byteLengthCounter = 0; + const chunks = []; + const reader = stream.getReader(); + let isDone = false; + while (!isDone) { + const { done, value } = await reader.read(); + if (value) { + chunks.push(value); + byteLengthCounter += (_a = value === null || value === void 0 ? void 0 : value.byteLength) !== null && _a !== void 0 ? _a : 0; + } + if (byteLengthCounter >= bytes) { + break; + } + isDone = done; + } + reader.releaseLock(); + const collected = new Uint8Array(Math.min(bytes, byteLengthCounter)); + let offset = 0; + for (const chunk of chunks) { + if (chunk.byteLength > collected.byteLength - offset) { + collected.set(chunk.subarray(0, collected.byteLength - offset), offset); + break; + } + else { + collected.set(chunk, offset); + } + offset += chunk.length; + } + return collected; +} + + +/***/ }), + +/***/ 88412: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.headStream = void 0; +const stream_1 = __nccwpck_require__(2203); +const headStream_browser_1 = __nccwpck_require__(80066); +const stream_type_check_1 = __nccwpck_require__(4414); +const headStream = (stream, bytes) => { + if ((0, stream_type_check_1.isReadableStream)(stream)) { + return (0, headStream_browser_1.headStream)(stream, bytes); + } + return new Promise((resolve, reject) => { + const collector = new Collector(); + collector.limit = bytes; + stream.pipe(collector); + stream.on("error", (err) => { + collector.end(); + reject(err); + }); + collector.on("error", reject); + collector.on("finish", function () { + const bytes = new Uint8Array(Buffer.concat(this.buffers)); + resolve(bytes); + }); + }); +}; +exports.headStream = headStream; +class Collector extends stream_1.Writable { + constructor() { + super(...arguments); + this.buffers = []; + this.limit = Infinity; + this.bytesBuffered = 0; + } + _write(chunk, encoding, callback) { + var _a; + this.buffers.push(chunk); + this.bytesBuffered += (_a = chunk.byteLength) !== null && _a !== void 0 ? _a : 0; + if (this.bytesBuffered >= this.limit) { + const excess = this.bytesBuffered - this.limit; + const tailBuffer = this.buffers[this.buffers.length - 1]; + this.buffers[this.buffers.length - 1] = tailBuffer.subarray(0, tailBuffer.byteLength - excess); + this.emit("finish"); + } + callback(); + } +} + + +/***/ }), + +/***/ 4252: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Uint8ArrayBlobAdapter: () => Uint8ArrayBlobAdapter +}); +module.exports = __toCommonJS(src_exports); + +// src/blob/transforms.ts +var import_util_base64 = __nccwpck_require__(68385); +var import_util_utf8 = __nccwpck_require__(71577); +function transformToString(payload, encoding = "utf-8") { + if (encoding === "base64") { + return (0, import_util_base64.toBase64)(payload); + } + return (0, import_util_utf8.toUtf8)(payload); +} +__name(transformToString, "transformToString"); +function transformFromString(str, encoding) { + if (encoding === "base64") { + return Uint8ArrayBlobAdapter.mutate((0, import_util_base64.fromBase64)(str)); + } + return Uint8ArrayBlobAdapter.mutate((0, import_util_utf8.fromUtf8)(str)); +} +__name(transformFromString, "transformFromString"); + +// src/blob/Uint8ArrayBlobAdapter.ts +var Uint8ArrayBlobAdapter = class _Uint8ArrayBlobAdapter extends Uint8Array { + static { + __name(this, "Uint8ArrayBlobAdapter"); + } + /** + * @param source - such as a string or Stream. + * @returns a new Uint8ArrayBlobAdapter extending Uint8Array. + */ + static fromString(source, encoding = "utf-8") { + switch (typeof source) { + case "string": + return transformFromString(source, encoding); + default: + throw new Error(`Unsupported conversion from ${typeof source} to Uint8ArrayBlobAdapter.`); + } + } + /** + * @param source - Uint8Array to be mutated. + * @returns the same Uint8Array but with prototype switched to Uint8ArrayBlobAdapter. + */ + static mutate(source) { + Object.setPrototypeOf(source, _Uint8ArrayBlobAdapter.prototype); + return source; + } + /** + * @param encoding - default 'utf-8'. + * @returns the blob as string. + */ + transformToString(encoding = "utf-8") { + return transformToString(this, encoding); + } +}; + +// src/index.ts +__reExport(src_exports, __nccwpck_require__(71775), module.exports); +__reExport(src_exports, __nccwpck_require__(5639), module.exports); +__reExport(src_exports, __nccwpck_require__(72005), module.exports); +__reExport(src_exports, __nccwpck_require__(6522), module.exports); +__reExport(src_exports, __nccwpck_require__(88412), module.exports); +__reExport(src_exports, __nccwpck_require__(77201), module.exports); +__reExport(src_exports, __nccwpck_require__(82108), module.exports); +__reExport(src_exports, __nccwpck_require__(4414), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 82207: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sdkStreamMixin = void 0; +const fetch_http_handler_1 = __nccwpck_require__(47809); +const util_base64_1 = __nccwpck_require__(68385); +const util_hex_encoding_1 = __nccwpck_require__(96435); +const util_utf8_1 = __nccwpck_require__(71577); +const stream_type_check_1 = __nccwpck_require__(4414); +const ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED = "The stream has already been transformed."; +const sdkStreamMixin = (stream) => { + var _a, _b; + if (!isBlobInstance(stream) && !(0, stream_type_check_1.isReadableStream)(stream)) { + const name = ((_b = (_a = stream === null || stream === void 0 ? void 0 : stream.__proto__) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) || stream; + throw new Error(`Unexpected stream implementation, expect Blob or ReadableStream, got ${name}`); + } + let transformed = false; + const transformToByteArray = async () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + transformed = true; + return await (0, fetch_http_handler_1.streamCollector)(stream); + }; + const blobToWebStream = (blob) => { + if (typeof blob.stream !== "function") { + throw new Error("Cannot transform payload Blob to web stream. Please make sure the Blob.stream() is polyfilled.\n" + + "If you are using React Native, this API is not yet supported, see: https://react-native.canny.io/feature-requests/p/fetch-streaming-body"); + } + return blob.stream(); + }; + return Object.assign(stream, { + transformToByteArray: transformToByteArray, + transformToString: async (encoding) => { + const buf = await transformToByteArray(); + if (encoding === "base64") { + return (0, util_base64_1.toBase64)(buf); + } + else if (encoding === "hex") { + return (0, util_hex_encoding_1.toHex)(buf); + } + else if (encoding === undefined || encoding === "utf8" || encoding === "utf-8") { + return (0, util_utf8_1.toUtf8)(buf); + } + else if (typeof TextDecoder === "function") { + return new TextDecoder(encoding).decode(buf); + } + else { + throw new Error("TextDecoder is not available, please make sure polyfill is provided."); + } + }, + transformToWebStream: () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + transformed = true; + if (isBlobInstance(stream)) { + return blobToWebStream(stream); + } + else if ((0, stream_type_check_1.isReadableStream)(stream)) { + return stream; + } + else { + throw new Error(`Cannot transform payload to web stream, got ${stream}`); + } + }, + }); +}; +exports.sdkStreamMixin = sdkStreamMixin; +const isBlobInstance = (stream) => typeof Blob === "function" && stream instanceof Blob; + + +/***/ }), + +/***/ 77201: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sdkStreamMixin = void 0; +const node_http_handler_1 = __nccwpck_require__(61279); +const util_buffer_from_1 = __nccwpck_require__(44151); +const stream_1 = __nccwpck_require__(2203); +const sdk_stream_mixin_browser_1 = __nccwpck_require__(82207); +const ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED = "The stream has already been transformed."; +const sdkStreamMixin = (stream) => { + var _a, _b; + if (!(stream instanceof stream_1.Readable)) { + try { + return (0, sdk_stream_mixin_browser_1.sdkStreamMixin)(stream); + } + catch (e) { + const name = ((_b = (_a = stream === null || stream === void 0 ? void 0 : stream.__proto__) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) || stream; + throw new Error(`Unexpected stream implementation, expect Stream.Readable instance, got ${name}`); + } + } + let transformed = false; + const transformToByteArray = async () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + transformed = true; + return await (0, node_http_handler_1.streamCollector)(stream); + }; + return Object.assign(stream, { + transformToByteArray, + transformToString: async (encoding) => { + const buf = await transformToByteArray(); + if (encoding === undefined || Buffer.isEncoding(encoding)) { + return (0, util_buffer_from_1.fromArrayBuffer)(buf.buffer, buf.byteOffset, buf.byteLength).toString(encoding); + } + else { + const decoder = new TextDecoder(encoding); + return decoder.decode(buf); + } + }, + transformToWebStream: () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + if (stream.readableFlowing !== null) { + throw new Error("The stream has been consumed by other callbacks."); + } + if (typeof stream_1.Readable.toWeb !== "function") { + throw new Error("Readable.toWeb() is not supported. Please ensure a polyfill is available."); + } + transformed = true; + return stream_1.Readable.toWeb(stream); + }, + }); +}; +exports.sdkStreamMixin = sdkStreamMixin; + + +/***/ }), + +/***/ 17570: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.splitStream = splitStream; +async function splitStream(stream) { + if (typeof stream.stream === "function") { + stream = stream.stream(); + } + const readableStream = stream; + return readableStream.tee(); +} + + +/***/ }), + +/***/ 82108: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.splitStream = splitStream; +const stream_1 = __nccwpck_require__(2203); +const splitStream_browser_1 = __nccwpck_require__(17570); +const stream_type_check_1 = __nccwpck_require__(4414); +async function splitStream(stream) { + if ((0, stream_type_check_1.isReadableStream)(stream) || (0, stream_type_check_1.isBlob)(stream)) { + return (0, splitStream_browser_1.splitStream)(stream); + } + const stream1 = new stream_1.PassThrough(); + const stream2 = new stream_1.PassThrough(); + stream.pipe(stream1); + stream.pipe(stream2); + return [stream1, stream2]; +} + + +/***/ }), + +/***/ 4414: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isBlob = exports.isReadableStream = void 0; +const isReadableStream = (stream) => { + var _a; + return typeof ReadableStream === "function" && + (((_a = stream === null || stream === void 0 ? void 0 : stream.constructor) === null || _a === void 0 ? void 0 : _a.name) === ReadableStream.name || stream instanceof ReadableStream); +}; +exports.isReadableStream = isReadableStream; +const isBlob = (blob) => { + var _a; + return typeof Blob === "function" && (((_a = blob === null || blob === void 0 ? void 0 : blob.constructor) === null || _a === void 0 ? void 0 : _a.name) === Blob.name || blob instanceof Blob); +}; +exports.isBlob = isBlob; + + +/***/ }), + +/***/ 80146: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + escapeUri: () => escapeUri, + escapeUriPath: () => escapeUriPath +}); +module.exports = __toCommonJS(src_exports); + +// src/escape-uri.ts +var escapeUri = /* @__PURE__ */ __name((uri) => ( + // AWS percent-encodes some extra non-standard characters in a URI + encodeURIComponent(uri).replace(/[!'()*]/g, hexEncode) +), "escapeUri"); +var hexEncode = /* @__PURE__ */ __name((c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`, "hexEncode"); + +// src/escape-uri-path.ts +var escapeUriPath = /* @__PURE__ */ __name((uri) => uri.split("/").map(escapeUri).join("/"), "escapeUriPath"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 71577: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromUtf8: () => fromUtf8, + toUint8Array: () => toUint8Array, + toUtf8: () => toUtf8 +}); +module.exports = __toCommonJS(src_exports); + +// src/fromUtf8.ts +var import_util_buffer_from = __nccwpck_require__(44151); +var fromUtf8 = /* @__PURE__ */ __name((input) => { + const buf = (0, import_util_buffer_from.fromString)(input, "utf8"); + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength / Uint8Array.BYTES_PER_ELEMENT); +}, "fromUtf8"); + +// src/toUint8Array.ts +var toUint8Array = /* @__PURE__ */ __name((data) => { + if (typeof data === "string") { + return fromUtf8(data); + } + if (ArrayBuffer.isView(data)) { + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT); + } + return new Uint8Array(data); +}, "toUint8Array"); + +// src/toUtf8.ts + +var toUtf8 = /* @__PURE__ */ __name((input) => { + if (typeof input === "string") { + return input; + } + if (typeof input !== "object" || typeof input.byteOffset !== "number" || typeof input.byteLength !== "number") { + throw new Error("@smithy/util-utf8: toUtf8 encoder function only accepts string | Uint8Array."); + } + return (0, import_util_buffer_from.fromArrayBuffer)(input.buffer, input.byteOffset, input.byteLength).toString("utf8"); +}, "toUtf8"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 95290: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + WaiterState: () => WaiterState, + checkExceptions: () => checkExceptions, + createWaiter: () => createWaiter, + waiterServiceDefaults: () => waiterServiceDefaults +}); +module.exports = __toCommonJS(src_exports); + +// src/utils/sleep.ts +var sleep = /* @__PURE__ */ __name((seconds) => { + return new Promise((resolve) => setTimeout(resolve, seconds * 1e3)); +}, "sleep"); + +// src/waiter.ts +var waiterServiceDefaults = { + minDelay: 2, + maxDelay: 120 +}; +var WaiterState = /* @__PURE__ */ ((WaiterState2) => { + WaiterState2["ABORTED"] = "ABORTED"; + WaiterState2["FAILURE"] = "FAILURE"; + WaiterState2["SUCCESS"] = "SUCCESS"; + WaiterState2["RETRY"] = "RETRY"; + WaiterState2["TIMEOUT"] = "TIMEOUT"; + return WaiterState2; +})(WaiterState || {}); +var checkExceptions = /* @__PURE__ */ __name((result) => { + if (result.state === "ABORTED" /* ABORTED */) { + const abortError = new Error( + `${JSON.stringify({ + ...result, + reason: "Request was aborted" + })}` + ); + abortError.name = "AbortError"; + throw abortError; + } else if (result.state === "TIMEOUT" /* TIMEOUT */) { + const timeoutError = new Error( + `${JSON.stringify({ + ...result, + reason: "Waiter has timed out" + })}` + ); + timeoutError.name = "TimeoutError"; + throw timeoutError; + } else if (result.state !== "SUCCESS" /* SUCCESS */) { + throw new Error(`${JSON.stringify(result)}`); + } + return result; +}, "checkExceptions"); + +// src/poller.ts +var exponentialBackoffWithJitter = /* @__PURE__ */ __name((minDelay, maxDelay, attemptCeiling, attempt) => { + if (attempt > attemptCeiling) + return maxDelay; + const delay = minDelay * 2 ** (attempt - 1); + return randomInRange(minDelay, delay); +}, "exponentialBackoffWithJitter"); +var randomInRange = /* @__PURE__ */ __name((min, max) => min + Math.random() * (max - min), "randomInRange"); +var runPolling = /* @__PURE__ */ __name(async ({ minDelay, maxDelay, maxWaitTime, abortController, client, abortSignal }, input, acceptorChecks) => { + const observedResponses = {}; + const { state, reason } = await acceptorChecks(client, input); + if (reason) { + const message = createMessageFromResponse(reason); + observedResponses[message] |= 0; + observedResponses[message] += 1; + } + if (state !== "RETRY" /* RETRY */) { + return { state, reason, observedResponses }; + } + let currentAttempt = 1; + const waitUntil = Date.now() + maxWaitTime * 1e3; + const attemptCeiling = Math.log(maxDelay / minDelay) / Math.log(2) + 1; + while (true) { + if (abortController?.signal?.aborted || abortSignal?.aborted) { + const message = "AbortController signal aborted."; + observedResponses[message] |= 0; + observedResponses[message] += 1; + return { state: "ABORTED" /* ABORTED */, observedResponses }; + } + const delay = exponentialBackoffWithJitter(minDelay, maxDelay, attemptCeiling, currentAttempt); + if (Date.now() + delay * 1e3 > waitUntil) { + return { state: "TIMEOUT" /* TIMEOUT */, observedResponses }; + } + await sleep(delay); + const { state: state2, reason: reason2 } = await acceptorChecks(client, input); + if (reason2) { + const message = createMessageFromResponse(reason2); + observedResponses[message] |= 0; + observedResponses[message] += 1; + } + if (state2 !== "RETRY" /* RETRY */) { + return { state: state2, reason: reason2, observedResponses }; + } + currentAttempt += 1; + } +}, "runPolling"); +var createMessageFromResponse = /* @__PURE__ */ __name((reason) => { + if (reason?.$responseBodyText) { + return `Deserialization error for body: ${reason.$responseBodyText}`; + } + if (reason?.$metadata?.httpStatusCode) { + if (reason.$response || reason.message) { + return `${reason.$response.statusCode ?? reason.$metadata.httpStatusCode ?? "Unknown"}: ${reason.message}`; + } + return `${reason.$metadata.httpStatusCode}: OK`; + } + return String(reason?.message ?? JSON.stringify(reason) ?? "Unknown"); +}, "createMessageFromResponse"); + +// src/utils/validate.ts +var validateWaiterOptions = /* @__PURE__ */ __name((options) => { + if (options.maxWaitTime <= 0) { + throw new Error(`WaiterConfiguration.maxWaitTime must be greater than 0`); + } else if (options.minDelay <= 0) { + throw new Error(`WaiterConfiguration.minDelay must be greater than 0`); + } else if (options.maxDelay <= 0) { + throw new Error(`WaiterConfiguration.maxDelay must be greater than 0`); + } else if (options.maxWaitTime <= options.minDelay) { + throw new Error( + `WaiterConfiguration.maxWaitTime [${options.maxWaitTime}] must be greater than WaiterConfiguration.minDelay [${options.minDelay}] for this waiter` + ); + } else if (options.maxDelay < options.minDelay) { + throw new Error( + `WaiterConfiguration.maxDelay [${options.maxDelay}] must be greater than WaiterConfiguration.minDelay [${options.minDelay}] for this waiter` + ); + } +}, "validateWaiterOptions"); + +// src/createWaiter.ts +var abortTimeout = /* @__PURE__ */ __name((abortSignal) => { + let onAbort; + const promise = new Promise((resolve) => { + onAbort = /* @__PURE__ */ __name(() => resolve({ state: "ABORTED" /* ABORTED */ }), "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + abortSignal.addEventListener("abort", onAbort); + } else { + abortSignal.onabort = onAbort; + } + }); + return { + clearListener() { + if (typeof abortSignal.removeEventListener === "function") { + abortSignal.removeEventListener("abort", onAbort); + } + }, + aborted: promise + }; +}, "abortTimeout"); +var createWaiter = /* @__PURE__ */ __name(async (options, input, acceptorChecks) => { + const params = { + ...waiterServiceDefaults, + ...options + }; + validateWaiterOptions(params); + const exitConditions = [runPolling(params, input, acceptorChecks)]; + const finalize = []; + if (options.abortSignal) { + const { aborted, clearListener } = abortTimeout(options.abortSignal); + finalize.push(clearListener); + exitConditions.push(aborted); + } + if (options.abortController?.signal) { + const { aborted, clearListener } = abortTimeout(options.abortController.signal); + finalize.push(clearListener); + exitConditions.push(aborted); + } + return Promise.race(exitConditions).then((result) => { + for (const fn of finalize) { + fn(); + } + return result; + }); +}, "createWaiter"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 48662: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function once(emitter, name, { signal } = {}) { + return new Promise((resolve, reject) => { + function cleanup() { + signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', cleanup); + emitter.removeListener(name, onEvent); + emitter.removeListener('error', onError); + } + function onEvent(...args) { + cleanup(); + resolve(args); + } + function onError(err) { + cleanup(); + reject(err); + } + signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', cleanup); + emitter.on(name, onEvent); + emitter.on('error', onError); + }); +} +exports["default"] = once; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 17413: +/***/ ((module, exports, __nccwpck_require__) => { + +"use strict"; +/** + * @author Toru Nagashima + * See LICENSE file in root directory for full license. + */ + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var eventTargetShim = __nccwpck_require__(16577); + +/** + * The signal class. + * @see https://dom.spec.whatwg.org/#abortsignal + */ +class AbortSignal extends eventTargetShim.EventTarget { + /** + * AbortSignal cannot be constructed directly. + */ + constructor() { + super(); + throw new TypeError("AbortSignal cannot be constructed directly"); + } + /** + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise. + */ + get aborted() { + const aborted = abortedFlags.get(this); + if (typeof aborted !== "boolean") { + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`); + } + return aborted; + } +} +eventTargetShim.defineEventAttribute(AbortSignal.prototype, "abort"); +/** + * Create an AbortSignal object. + */ +function createAbortSignal() { + const signal = Object.create(AbortSignal.prototype); + eventTargetShim.EventTarget.call(signal); + abortedFlags.set(signal, false); + return signal; +} +/** + * Abort a given signal. + */ +function abortSignal(signal) { + if (abortedFlags.get(signal) !== false) { + return; + } + abortedFlags.set(signal, true); + signal.dispatchEvent({ type: "abort" }); +} +/** + * Aborted flag for each instances. + */ +const abortedFlags = new WeakMap(); +// Properties should be enumerable. +Object.defineProperties(AbortSignal.prototype, { + aborted: { enumerable: true }, +}); +// `toString()` should return `"[object AbortSignal]"` +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortSignal", + }); +} + +/** + * The AbortController. + * @see https://dom.spec.whatwg.org/#abortcontroller + */ +class AbortController { + /** + * Initialize this controller. + */ + constructor() { + signals.set(this, createAbortSignal()); + } + /** + * Returns the `AbortSignal` object associated with this object. + */ + get signal() { + return getSignal(this); + } + /** + * Abort and signal to any observers that the associated activity is to be aborted. + */ + abort() { + abortSignal(getSignal(this)); + } +} +/** + * Associated signals. + */ +const signals = new WeakMap(); +/** + * Get the associated signal of a given controller. + */ +function getSignal(controller) { + const signal = signals.get(controller); + if (signal == null) { + throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`); + } + return signal; +} +// Properties should be enumerable. +Object.defineProperties(AbortController.prototype, { + signal: { enumerable: true }, + abort: { enumerable: true }, +}); +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortController.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortController", + }); +} + +exports.AbortController = AbortController; +exports.AbortSignal = AbortSignal; +exports["default"] = AbortController; + +module.exports = AbortController +module.exports.AbortController = module.exports["default"] = AbortController +module.exports.AbortSignal = AbortSignal +//# sourceMappingURL=abort-controller.js.map + + +/***/ }), + +/***/ 15183: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.req = exports.json = exports.toBuffer = void 0; +const http = __importStar(__nccwpck_require__(58611)); +const https = __importStar(__nccwpck_require__(65692)); +async function toBuffer(stream) { + let length = 0; + const chunks = []; + for await (const chunk of stream) { + length += chunk.length; + chunks.push(chunk); + } + return Buffer.concat(chunks, length); +} +exports.toBuffer = toBuffer; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function json(stream) { + const buf = await toBuffer(stream); + const str = buf.toString('utf8'); + try { + return JSON.parse(str); + } + catch (_err) { + const err = _err; + err.message += ` (input: ${str})`; + throw err; + } +} +exports.json = json; +function req(url, opts = {}) { + const href = typeof url === 'string' ? url : url.href; + const req = (href.startsWith('https:') ? https : http).request(url, opts); + const promise = new Promise((resolve, reject) => { + req + .once('response', resolve) + .once('error', reject) + .end(); + }); + req.then = promise.then.bind(promise); + return req; +} +exports.req = req; +//# sourceMappingURL=helpers.js.map + +/***/ }), + +/***/ 98894: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Agent = void 0; +const net = __importStar(__nccwpck_require__(69278)); +const http = __importStar(__nccwpck_require__(58611)); +const https_1 = __nccwpck_require__(65692); +__exportStar(__nccwpck_require__(15183), exports); +const INTERNAL = Symbol('AgentBaseInternalState'); +class Agent extends http.Agent { + constructor(opts) { + super(opts); + this[INTERNAL] = {}; + } + /** + * Determine whether this is an `http` or `https` request. + */ + isSecureEndpoint(options) { + if (options) { + // First check the `secureEndpoint` property explicitly, since this + // means that a parent `Agent` is "passing through" to this instance. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof options.secureEndpoint === 'boolean') { + return options.secureEndpoint; + } + // If no explicit `secure` endpoint, check if `protocol` property is + // set. This will usually be the case since using a full string URL + // or `URL` instance should be the most common usage. + if (typeof options.protocol === 'string') { + return options.protocol === 'https:'; + } + } + // Finally, if no `protocol` property was set, then fall back to + // checking the stack trace of the current call stack, and try to + // detect the "https" module. + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack + .split('\n') + .some((l) => l.indexOf('(https.js:') !== -1 || + l.indexOf('node:https:') !== -1); + } + // In order to support async signatures in `connect()` and Node's native + // connection pooling in `http.Agent`, the array of sockets for each origin + // has to be updated synchronously. This is so the length of the array is + // accurate when `addRequest()` is next called. We achieve this by creating a + // fake socket and adding it to `sockets[origin]` and incrementing + // `totalSocketCount`. + incrementSockets(name) { + // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no + // need to create a fake socket because Node.js native connection pooling + // will never be invoked. + if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) { + return null; + } + // All instances of `sockets` are expected TypeScript errors. The + // alternative is to add it as a private property of this class but that + // will break TypeScript subclassing. + if (!this.sockets[name]) { + // @ts-expect-error `sockets` is readonly in `@types/node` + this.sockets[name] = []; + } + const fakeSocket = new net.Socket({ writable: false }); + this.sockets[name].push(fakeSocket); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount++; + return fakeSocket; + } + decrementSockets(name, socket) { + if (!this.sockets[name] || socket === null) { + return; + } + const sockets = this.sockets[name]; + const index = sockets.indexOf(socket); + if (index !== -1) { + sockets.splice(index, 1); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount--; + if (sockets.length === 0) { + // @ts-expect-error `sockets` is readonly in `@types/node` + delete this.sockets[name]; + } + } + } + // In order to properly update the socket pool, we need to call `getName()` on + // the core `https.Agent` if it is a secureEndpoint. + getName(options) { + const secureEndpoint = this.isSecureEndpoint(options); + if (secureEndpoint) { + // @ts-expect-error `getName()` isn't defined in `@types/node` + return https_1.Agent.prototype.getName.call(this, options); + } + // @ts-expect-error `getName()` isn't defined in `@types/node` + return super.getName(options); + } + createSocket(req, options, cb) { + const connectOpts = { + ...options, + secureEndpoint: this.isSecureEndpoint(options), + }; + const name = this.getName(connectOpts); + const fakeSocket = this.incrementSockets(name); + Promise.resolve() + .then(() => this.connect(req, connectOpts)) + .then((socket) => { + this.decrementSockets(name, fakeSocket); + if (socket instanceof http.Agent) { + try { + // @ts-expect-error `addRequest()` isn't defined in `@types/node` + return socket.addRequest(req, connectOpts); + } + catch (err) { + return cb(err); + } + } + this[INTERNAL].currentSocket = socket; + // @ts-expect-error `createSocket()` isn't defined in `@types/node` + super.createSocket(req, options, cb); + }, (err) => { + this.decrementSockets(name, fakeSocket); + cb(err); + }); + } + createConnection() { + const socket = this[INTERNAL].currentSocket; + this[INTERNAL].currentSocket = undefined; + if (!socket) { + throw new Error('No socket was returned in the `connect()` function'); + } + return socket; + } + get defaultPort() { + return (this[INTERNAL].defaultPort ?? + (this.protocol === 'https:' ? 443 : 80)); + } + set defaultPort(v) { + if (this[INTERNAL]) { + this[INTERNAL].defaultPort = v; + } + } + get protocol() { + return (this[INTERNAL].protocol ?? + (this.isSecureEndpoint() ? 'https:' : 'http:')); + } + set protocol(v) { + if (this[INTERNAL]) { + this[INTERNAL].protocol = v; + } + } +} +exports.Agent = Agent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 26251: +/***/ ((module) => { + +"use strict"; + + +const arrify = value => { + if (value === null || value === undefined) { + return []; + } + + if (Array.isArray(value)) { + return value; + } + + if (typeof value === 'string') { + return [value]; + } + + if (typeof value[Symbol.iterator] === 'function') { + return [...value]; + } + + return [value]; +}; + +module.exports = arrify; + + +/***/ }), + +/***/ 45195: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +// Packages +var retrier = __nccwpck_require__(5546); + +function retry(fn, opts) { + function run(resolve, reject) { + var options = opts || {}; + var op; + + // Default `randomize` to true + if (!('randomize' in options)) { + options.randomize = true; + } + + op = retrier.operation(options); + + // We allow the user to abort retrying + // this makes sense in the cases where + // knowledge is obtained that retrying + // would be futile (e.g.: auth errors) + + function bail(err) { + reject(err || new Error('Aborted')); + } + + function onError(err, num) { + if (err.bail) { + bail(err); + return; + } + + if (!op.retry(err)) { + reject(op.mainError()); + } else if (options.onRetry) { + options.onRetry(err, num); + } + } + + function runAttempt(num) { + var val; + + try { + val = fn(bail, num); + } catch (err) { + onError(err, num); + return; + } + + Promise.resolve(val) + .then(resolve) + .catch(function catchIt(err) { + onError(err, num); + }); + } + + op.attempt(runAttempt); + } + + return new Promise(run); +} + +module.exports = retry; + + +/***/ }), + +/***/ 38793: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + + +/***/ }), + +/***/ 51259: +/***/ (function(module) { + +;(function (globalObject) { + 'use strict'; + +/* + * bignumber.js v9.3.1 + * A JavaScript library for arbitrary-precision arithmetic. + * https://github.com/MikeMcl/bignumber.js + * Copyright (c) 2025 Michael Mclaughlin + * MIT Licensed. + * + * BigNumber.prototype methods | BigNumber methods + * | + * absoluteValue abs | clone + * comparedTo | config set + * decimalPlaces dp | DECIMAL_PLACES + * dividedBy div | ROUNDING_MODE + * dividedToIntegerBy idiv | EXPONENTIAL_AT + * exponentiatedBy pow | RANGE + * integerValue | CRYPTO + * isEqualTo eq | MODULO_MODE + * isFinite | POW_PRECISION + * isGreaterThan gt | FORMAT + * isGreaterThanOrEqualTo gte | ALPHABET + * isInteger | isBigNumber + * isLessThan lt | maximum max + * isLessThanOrEqualTo lte | minimum min + * isNaN | random + * isNegative | sum + * isPositive | + * isZero | + * minus | + * modulo mod | + * multipliedBy times | + * negated | + * plus | + * precision sd | + * shiftedBy | + * squareRoot sqrt | + * toExponential | + * toFixed | + * toFormat | + * toFraction | + * toJSON | + * toNumber | + * toPrecision | + * toString | + * valueOf | + * + */ + + + var BigNumber, + isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, + mathceil = Math.ceil, + mathfloor = Math.floor, + + bignumberError = '[BigNumber Error] ', + tooManyDigits = bignumberError + 'Number primitive has more than 15 significant digits: ', + + BASE = 1e14, + LOG_BASE = 14, + MAX_SAFE_INTEGER = 0x1fffffffffffff, // 2^53 - 1 + // MAX_INT32 = 0x7fffffff, // 2^31 - 1 + POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], + SQRT_BASE = 1e7, + + // EDITABLE + // The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and + // the arguments to toExponential, toFixed, toFormat, and toPrecision. + MAX = 1E9; // 0 to MAX_INT32 + + + /* + * Create and return a BigNumber constructor. + */ + function clone(configObject) { + var div, convertBase, parseNumeric, + P = BigNumber.prototype = { constructor: BigNumber, toString: null, valueOf: null }, + ONE = new BigNumber(1), + + + //----------------------------- EDITABLE CONFIG DEFAULTS ------------------------------- + + + // The default values below must be integers within the inclusive ranges stated. + // The values can also be changed at run-time using BigNumber.set. + + // The maximum number of decimal places for operations involving division. + DECIMAL_PLACES = 20, // 0 to MAX + + // The rounding mode used when rounding to the above decimal places, and when using + // toExponential, toFixed, toFormat and toPrecision, and round (default value). + // UP 0 Away from zero. + // DOWN 1 Towards zero. + // CEIL 2 Towards +Infinity. + // FLOOR 3 Towards -Infinity. + // HALF_UP 4 Towards nearest neighbour. If equidistant, up. + // HALF_DOWN 5 Towards nearest neighbour. If equidistant, down. + // HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour. + // HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity. + // HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity. + ROUNDING_MODE = 4, // 0 to 8 + + // EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS] + + // The exponent value at and beneath which toString returns exponential notation. + // Number type: -7 + TO_EXP_NEG = -7, // 0 to -MAX + + // The exponent value at and above which toString returns exponential notation. + // Number type: 21 + TO_EXP_POS = 21, // 0 to MAX + + // RANGE : [MIN_EXP, MAX_EXP] + + // The minimum exponent value, beneath which underflow to zero occurs. + // Number type: -324 (5e-324) + MIN_EXP = -1e7, // -1 to -MAX + + // The maximum exponent value, above which overflow to Infinity occurs. + // Number type: 308 (1.7976931348623157e+308) + // For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow. + MAX_EXP = 1e7, // 1 to MAX + + // Whether to use cryptographically-secure random number generation, if available. + CRYPTO = false, // true or false + + // The modulo mode used when calculating the modulus: a mod n. + // The quotient (q = a / n) is calculated according to the corresponding rounding mode. + // The remainder (r) is calculated as: r = a - n * q. + // + // UP 0 The remainder is positive if the dividend is negative, else is negative. + // DOWN 1 The remainder has the same sign as the dividend. + // This modulo mode is commonly known as 'truncated division' and is + // equivalent to (a % n) in JavaScript. + // FLOOR 3 The remainder has the same sign as the divisor (Python %). + // HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function. + // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). + // The remainder is always positive. + // + // The truncated division, floored division, Euclidian division and IEEE 754 remainder + // modes are commonly used for the modulus operation. + // Although the other rounding modes can also be used, they may not give useful results. + MODULO_MODE = 1, // 0 to 9 + + // The maximum number of significant digits of the result of the exponentiatedBy operation. + // If POW_PRECISION is 0, there will be unlimited significant digits. + POW_PRECISION = 0, // 0 to MAX + + // The format specification used by the BigNumber.prototype.toFormat method. + FORMAT = { + prefix: '', + groupSize: 3, + secondaryGroupSize: 0, + groupSeparator: ',', + decimalSeparator: '.', + fractionGroupSize: 0, + fractionGroupSeparator: '\xA0', // non-breaking space + suffix: '' + }, + + // The alphabet used for base conversion. It must be at least 2 characters long, with no '+', + // '-', '.', whitespace, or repeated character. + // '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_' + ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz', + alphabetHasNormalDecimalDigits = true; + + + //------------------------------------------------------------------------------------------ + + + // CONSTRUCTOR + + + /* + * The BigNumber constructor and exported function. + * Create and return a new instance of a BigNumber object. + * + * v {number|string|BigNumber} A numeric value. + * [b] {number} The base of v. Integer, 2 to ALPHABET.length inclusive. + */ + function BigNumber(v, b) { + var alphabet, c, caseChanged, e, i, isNum, len, str, + x = this; + + // Enable constructor call without `new`. + if (!(x instanceof BigNumber)) return new BigNumber(v, b); + + if (b == null) { + + if (v && v._isBigNumber === true) { + x.s = v.s; + + if (!v.c || v.e > MAX_EXP) { + x.c = x.e = null; + } else if (v.e < MIN_EXP) { + x.c = [x.e = 0]; + } else { + x.e = v.e; + x.c = v.c.slice(); + } + + return; + } + + if ((isNum = typeof v == 'number') && v * 0 == 0) { + + // Use `1 / n` to handle minus zero also. + x.s = 1 / v < 0 ? (v = -v, -1) : 1; + + // Fast path for integers, where n < 2147483648 (2**31). + if (v === ~~v) { + for (e = 0, i = v; i >= 10; i /= 10, e++); + + if (e > MAX_EXP) { + x.c = x.e = null; + } else { + x.e = e; + x.c = [v]; + } + + return; + } + + str = String(v); + } else { + + if (!isNumeric.test(str = String(v))) return parseNumeric(x, str, isNum); + + x.s = str.charCodeAt(0) == 45 ? (str = str.slice(1), -1) : 1; + } + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + + // Exponential form? + if ((i = str.search(/e/i)) > 0) { + + // Determine exponent. + if (e < 0) e = i; + e += +str.slice(i + 1); + str = str.substring(0, i); + } else if (e < 0) { + + // Integer. + e = str.length; + } + + } else { + + // '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + intCheck(b, 2, ALPHABET.length, 'Base'); + + // Allow exponential notation to be used with base 10 argument, while + // also rounding to DECIMAL_PLACES as with other bases. + if (b == 10 && alphabetHasNormalDecimalDigits) { + x = new BigNumber(v); + return round(x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE); + } + + str = String(v); + + if (isNum = typeof v == 'number') { + + // Avoid potential interpretation of Infinity and NaN as base 44+ values. + if (v * 0 != 0) return parseNumeric(x, str, isNum, b); + + x.s = 1 / v < 0 ? (str = str.slice(1), -1) : 1; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (BigNumber.DEBUG && str.replace(/^0\.0*|\./, '').length > 15) { + throw Error + (tooManyDigits + v); + } + } else { + x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1; + } + + alphabet = ALPHABET.slice(0, b); + e = i = 0; + + // Check that str is a valid base b number. + // Don't use RegExp, so alphabet can contain special characters. + for (len = str.length; i < len; i++) { + if (alphabet.indexOf(c = str.charAt(i)) < 0) { + if (c == '.') { + + // If '.' is not the first character and it has not be found before. + if (i > e) { + e = len; + continue; + } + } else if (!caseChanged) { + + // Allow e.g. hexadecimal 'FF' as well as 'ff'. + if (str == str.toUpperCase() && (str = str.toLowerCase()) || + str == str.toLowerCase() && (str = str.toUpperCase())) { + caseChanged = true; + i = -1; + e = 0; + continue; + } + } + + return parseNumeric(x, String(v), isNum, b); + } + } + + // Prevent later check for length on converted number. + isNum = false; + str = convertBase(str, b, 10, x.s); + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + else e = str.length; + } + + // Determine leading zeros. + for (i = 0; str.charCodeAt(i) === 48; i++); + + // Determine trailing zeros. + for (len = str.length; str.charCodeAt(--len) === 48;); + + if (str = str.slice(i, ++len)) { + len -= i; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (isNum && BigNumber.DEBUG && + len > 15 && (v > MAX_SAFE_INTEGER || v !== mathfloor(v))) { + throw Error + (tooManyDigits + (x.s * v)); + } + + // Overflow? + if ((e = e - i - 1) > MAX_EXP) { + + // Infinity. + x.c = x.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + x.c = [x.e = 0]; + } else { + x.e = e; + x.c = []; + + // Transform base + + // e is the base 10 exponent. + // i is where to slice str to get the first element of the coefficient array. + i = (e + 1) % LOG_BASE; + if (e < 0) i += LOG_BASE; // i < 1 + + if (i < len) { + if (i) x.c.push(+str.slice(0, i)); + + for (len -= LOG_BASE; i < len;) { + x.c.push(+str.slice(i, i += LOG_BASE)); + } + + i = LOG_BASE - (str = str.slice(i)).length; + } else { + i -= len; + } + + for (; i--; str += '0'); + x.c.push(+str); + } + } else { + + // Zero. + x.c = [x.e = 0]; + } + } + + + // CONSTRUCTOR PROPERTIES + + + BigNumber.clone = clone; + + BigNumber.ROUND_UP = 0; + BigNumber.ROUND_DOWN = 1; + BigNumber.ROUND_CEIL = 2; + BigNumber.ROUND_FLOOR = 3; + BigNumber.ROUND_HALF_UP = 4; + BigNumber.ROUND_HALF_DOWN = 5; + BigNumber.ROUND_HALF_EVEN = 6; + BigNumber.ROUND_HALF_CEIL = 7; + BigNumber.ROUND_HALF_FLOOR = 8; + BigNumber.EUCLID = 9; + + + /* + * Configure infrequently-changing library-wide settings. + * + * Accept an object with the following optional properties (if the value of a property is + * a number, it must be an integer within the inclusive range stated): + * + * DECIMAL_PLACES {number} 0 to MAX + * ROUNDING_MODE {number} 0 to 8 + * EXPONENTIAL_AT {number|number[]} -MAX to MAX or [-MAX to 0, 0 to MAX] + * RANGE {number|number[]} -MAX to MAX (not zero) or [-MAX to -1, 1 to MAX] + * CRYPTO {boolean} true or false + * MODULO_MODE {number} 0 to 9 + * POW_PRECISION {number} 0 to MAX + * ALPHABET {string} A string of two or more unique characters which does + * not contain '.'. + * FORMAT {object} An object with some of the following properties: + * prefix {string} + * groupSize {number} + * secondaryGroupSize {number} + * groupSeparator {string} + * decimalSeparator {string} + * fractionGroupSize {number} + * fractionGroupSeparator {string} + * suffix {string} + * + * (The values assigned to the above FORMAT object properties are not checked for validity.) + * + * E.g. + * BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 }) + * + * Ignore properties/parameters set to null or undefined, except for ALPHABET. + * + * Return an object with the properties current values. + */ + BigNumber.config = BigNumber.set = function (obj) { + var p, v; + + if (obj != null) { + + if (typeof obj == 'object') { + + // DECIMAL_PLACES {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] DECIMAL_PLACES {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'DECIMAL_PLACES')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + DECIMAL_PLACES = v; + } + + // ROUNDING_MODE {number} Integer, 0 to 8 inclusive. + // '[BigNumber Error] ROUNDING_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'ROUNDING_MODE')) { + v = obj[p]; + intCheck(v, 0, 8, p); + ROUNDING_MODE = v; + } + + // EXPONENTIAL_AT {number|number[]} + // Integer, -MAX to MAX inclusive or + // [integer -MAX to 0 inclusive, 0 to MAX inclusive]. + // '[BigNumber Error] EXPONENTIAL_AT {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'EXPONENTIAL_AT')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, 0, p); + intCheck(v[1], 0, MAX, p); + TO_EXP_NEG = v[0]; + TO_EXP_POS = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + TO_EXP_NEG = -(TO_EXP_POS = v < 0 ? -v : v); + } + } + + // RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or + // [integer -MAX to -1 inclusive, integer 1 to MAX inclusive]. + // '[BigNumber Error] RANGE {not a primitive number|not an integer|out of range|cannot be zero}: {v}' + if (obj.hasOwnProperty(p = 'RANGE')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, -1, p); + intCheck(v[1], 1, MAX, p); + MIN_EXP = v[0]; + MAX_EXP = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + if (v) { + MIN_EXP = -(MAX_EXP = v < 0 ? -v : v); + } else { + throw Error + (bignumberError + p + ' cannot be zero: ' + v); + } + } + } + + // CRYPTO {boolean} true or false. + // '[BigNumber Error] CRYPTO not true or false: {v}' + // '[BigNumber Error] crypto unavailable' + if (obj.hasOwnProperty(p = 'CRYPTO')) { + v = obj[p]; + if (v === !!v) { + if (v) { + if (typeof crypto != 'undefined' && crypto && + (crypto.getRandomValues || crypto.randomBytes)) { + CRYPTO = v; + } else { + CRYPTO = !v; + throw Error + (bignumberError + 'crypto unavailable'); + } + } else { + CRYPTO = v; + } + } else { + throw Error + (bignumberError + p + ' not true or false: ' + v); + } + } + + // MODULO_MODE {number} Integer, 0 to 9 inclusive. + // '[BigNumber Error] MODULO_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'MODULO_MODE')) { + v = obj[p]; + intCheck(v, 0, 9, p); + MODULO_MODE = v; + } + + // POW_PRECISION {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] POW_PRECISION {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'POW_PRECISION')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + POW_PRECISION = v; + } + + // FORMAT {object} + // '[BigNumber Error] FORMAT not an object: {v}' + if (obj.hasOwnProperty(p = 'FORMAT')) { + v = obj[p]; + if (typeof v == 'object') FORMAT = v; + else throw Error + (bignumberError + p + ' not an object: ' + v); + } + + // ALPHABET {string} + // '[BigNumber Error] ALPHABET invalid: {v}' + if (obj.hasOwnProperty(p = 'ALPHABET')) { + v = obj[p]; + + // Disallow if less than two characters, + // or if it contains '+', '-', '.', whitespace, or a repeated character. + if (typeof v == 'string' && !/^.?$|[+\-.\s]|(.).*\1/.test(v)) { + alphabetHasNormalDecimalDigits = v.slice(0, 10) == '0123456789'; + ALPHABET = v; + } else { + throw Error + (bignumberError + p + ' invalid: ' + v); + } + } + + } else { + + // '[BigNumber Error] Object expected: {v}' + throw Error + (bignumberError + 'Object expected: ' + obj); + } + } + + return { + DECIMAL_PLACES: DECIMAL_PLACES, + ROUNDING_MODE: ROUNDING_MODE, + EXPONENTIAL_AT: [TO_EXP_NEG, TO_EXP_POS], + RANGE: [MIN_EXP, MAX_EXP], + CRYPTO: CRYPTO, + MODULO_MODE: MODULO_MODE, + POW_PRECISION: POW_PRECISION, + FORMAT: FORMAT, + ALPHABET: ALPHABET + }; + }; + + + /* + * Return true if v is a BigNumber instance, otherwise return false. + * + * If BigNumber.DEBUG is true, throw if a BigNumber instance is not well-formed. + * + * v {any} + * + * '[BigNumber Error] Invalid BigNumber: {v}' + */ + BigNumber.isBigNumber = function (v) { + if (!v || v._isBigNumber !== true) return false; + if (!BigNumber.DEBUG) return true; + + var i, n, + c = v.c, + e = v.e, + s = v.s; + + out: if ({}.toString.call(c) == '[object Array]') { + + if ((s === 1 || s === -1) && e >= -MAX && e <= MAX && e === mathfloor(e)) { + + // If the first element is zero, the BigNumber value must be zero. + if (c[0] === 0) { + if (e === 0 && c.length === 1) return true; + break out; + } + + // Calculate number of digits that c[0] should have, based on the exponent. + i = (e + 1) % LOG_BASE; + if (i < 1) i += LOG_BASE; + + // Calculate number of digits of c[0]. + //if (Math.ceil(Math.log(c[0] + 1) / Math.LN10) == i) { + if (String(c[0]).length == i) { + + for (i = 0; i < c.length; i++) { + n = c[i]; + if (n < 0 || n >= BASE || n !== mathfloor(n)) break out; + } + + // Last element cannot be zero, unless it is the only element. + if (n !== 0) return true; + } + } + + // Infinity/NaN + } else if (c === null && e === null && (s === null || s === 1 || s === -1)) { + return true; + } + + throw Error + (bignumberError + 'Invalid BigNumber: ' + v); + }; + + + /* + * Return a new BigNumber whose value is the maximum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.maximum = BigNumber.max = function () { + return maxOrMin(arguments, -1); + }; + + + /* + * Return a new BigNumber whose value is the minimum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.minimum = BigNumber.min = function () { + return maxOrMin(arguments, 1); + }; + + + /* + * Return a new BigNumber with a random value equal to or greater than 0 and less than 1, + * and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing + * zeros are produced). + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp}' + * '[BigNumber Error] crypto unavailable' + */ + BigNumber.random = (function () { + var pow2_53 = 0x20000000000000; + + // Return a 53 bit integer n, where 0 <= n < 9007199254740992. + // Check if Math.random() produces more than 32 bits of randomness. + // If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits. + // 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1. + var random53bitInt = (Math.random() * pow2_53) & 0x1fffff + ? function () { return mathfloor(Math.random() * pow2_53); } + : function () { return ((Math.random() * 0x40000000 | 0) * 0x800000) + + (Math.random() * 0x800000 | 0); }; + + return function (dp) { + var a, b, e, k, v, + i = 0, + c = [], + rand = new BigNumber(ONE); + + if (dp == null) dp = DECIMAL_PLACES; + else intCheck(dp, 0, MAX); + + k = mathceil(dp / LOG_BASE); + + if (CRYPTO) { + + // Browsers supporting crypto.getRandomValues. + if (crypto.getRandomValues) { + + a = crypto.getRandomValues(new Uint32Array(k *= 2)); + + for (; i < k;) { + + // 53 bits: + // ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2) + // 11111 11111111 11111111 11111111 11100000 00000000 00000000 + // ((Math.pow(2, 32) - 1) >>> 11).toString(2) + // 11111 11111111 11111111 + // 0x20000 is 2^21. + v = a[i] * 0x20000 + (a[i + 1] >>> 11); + + // Rejection sampling: + // 0 <= v < 9007199254740992 + // Probability that v >= 9e15, is + // 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251 + if (v >= 9e15) { + b = crypto.getRandomValues(new Uint32Array(2)); + a[i] = b[0]; + a[i + 1] = b[1]; + } else { + + // 0 <= v <= 8999999999999999 + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 2; + } + } + i = k / 2; + + // Node.js supporting crypto.randomBytes. + } else if (crypto.randomBytes) { + + // buffer + a = crypto.randomBytes(k *= 7); + + for (; i < k;) { + + // 0x1000000000000 is 2^48, 0x10000000000 is 2^40 + // 0x100000000 is 2^32, 0x1000000 is 2^24 + // 11111 11111111 11111111 11111111 11111111 11111111 11111111 + // 0 <= v < 9007199254740992 + v = ((a[i] & 31) * 0x1000000000000) + (a[i + 1] * 0x10000000000) + + (a[i + 2] * 0x100000000) + (a[i + 3] * 0x1000000) + + (a[i + 4] << 16) + (a[i + 5] << 8) + a[i + 6]; + + if (v >= 9e15) { + crypto.randomBytes(7).copy(a, i); + } else { + + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 7; + } + } + i = k / 7; + } else { + CRYPTO = false; + throw Error + (bignumberError + 'crypto unavailable'); + } + } + + // Use Math.random. + if (!CRYPTO) { + + for (; i < k;) { + v = random53bitInt(); + if (v < 9e15) c[i++] = v % 1e14; + } + } + + k = c[--i]; + dp %= LOG_BASE; + + // Convert trailing digits to zeros according to dp. + if (k && dp) { + v = POWS_TEN[LOG_BASE - dp]; + c[i] = mathfloor(k / v) * v; + } + + // Remove trailing elements which are zero. + for (; c[i] === 0; c.pop(), i--); + + // Zero? + if (i < 0) { + c = [e = 0]; + } else { + + // Remove leading elements which are zero and adjust exponent accordingly. + for (e = -1 ; c[0] === 0; c.splice(0, 1), e -= LOG_BASE); + + // Count the digits of the first element of c to determine leading zeros, and... + for (i = 1, v = c[0]; v >= 10; v /= 10, i++); + + // adjust the exponent accordingly. + if (i < LOG_BASE) e -= LOG_BASE - i; + } + + rand.e = e; + rand.c = c; + return rand; + }; + })(); + + + /* + * Return a BigNumber whose value is the sum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.sum = function () { + var i = 1, + args = arguments, + sum = new BigNumber(args[0]); + for (; i < args.length;) sum = sum.plus(args[i++]); + return sum; + }; + + + // PRIVATE FUNCTIONS + + + // Called by BigNumber and BigNumber.prototype.toString. + convertBase = (function () { + var decimal = '0123456789'; + + /* + * Convert string of baseIn to an array of numbers of baseOut. + * Eg. toBaseOut('255', 10, 16) returns [15, 15]. + * Eg. toBaseOut('ff', 16, 10) returns [2, 5, 5]. + */ + function toBaseOut(str, baseIn, baseOut, alphabet) { + var j, + arr = [0], + arrL, + i = 0, + len = str.length; + + for (; i < len;) { + for (arrL = arr.length; arrL--; arr[arrL] *= baseIn); + + arr[0] += alphabet.indexOf(str.charAt(i++)); + + for (j = 0; j < arr.length; j++) { + + if (arr[j] > baseOut - 1) { + if (arr[j + 1] == null) arr[j + 1] = 0; + arr[j + 1] += arr[j] / baseOut | 0; + arr[j] %= baseOut; + } + } + } + + return arr.reverse(); + } + + // Convert a numeric string of baseIn to a numeric string of baseOut. + // If the caller is toString, we are converting from base 10 to baseOut. + // If the caller is BigNumber, we are converting from baseIn to base 10. + return function (str, baseIn, baseOut, sign, callerIsToString) { + var alphabet, d, e, k, r, x, xc, y, + i = str.indexOf('.'), + dp = DECIMAL_PLACES, + rm = ROUNDING_MODE; + + // Non-integer. + if (i >= 0) { + k = POW_PRECISION; + + // Unlimited precision. + POW_PRECISION = 0; + str = str.replace('.', ''); + y = new BigNumber(baseIn); + x = y.pow(str.length - i); + POW_PRECISION = k; + + // Convert str as if an integer, then restore the fraction part by dividing the + // result by its base raised to a power. + + y.c = toBaseOut(toFixedPoint(coeffToString(x.c), x.e, '0'), + 10, baseOut, decimal); + y.e = y.c.length; + } + + // Convert the number as integer. + + xc = toBaseOut(str, baseIn, baseOut, callerIsToString + ? (alphabet = ALPHABET, decimal) + : (alphabet = decimal, ALPHABET)); + + // xc now represents str as an integer and converted to baseOut. e is the exponent. + e = k = xc.length; + + // Remove trailing zeros. + for (; xc[--k] == 0; xc.pop()); + + // Zero? + if (!xc[0]) return alphabet.charAt(0); + + // Does str represent an integer? If so, no need for the division. + if (i < 0) { + --e; + } else { + x.c = xc; + x.e = e; + + // The sign is needed for correct rounding. + x.s = sign; + x = div(x, y, dp, rm, baseOut); + xc = x.c; + r = x.r; + e = x.e; + } + + // xc now represents str converted to baseOut. + + // The index of the rounding digit. + d = e + dp + 1; + + // The rounding digit: the digit to the right of the digit that may be rounded up. + i = xc[d]; + + // Look at the rounding digits and mode to determine whether to round up. + + k = baseOut / 2; + r = r || d < 0 || xc[d + 1] != null; + + r = rm < 4 ? (i != null || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : i > k || i == k &&(rm == 4 || r || rm == 6 && xc[d - 1] & 1 || + rm == (x.s < 0 ? 8 : 7)); + + // If the index of the rounding digit is not greater than zero, or xc represents + // zero, then the result of the base conversion is zero or, if rounding up, a value + // such as 0.00001. + if (d < 1 || !xc[0]) { + + // 1^-dp or 0 + str = r ? toFixedPoint(alphabet.charAt(1), -dp, alphabet.charAt(0)) : alphabet.charAt(0); + } else { + + // Truncate xc to the required number of decimal places. + xc.length = d; + + // Round up? + if (r) { + + // Rounding up may mean the previous digit has to be rounded up and so on. + for (--baseOut; ++xc[--d] > baseOut;) { + xc[d] = 0; + + if (!d) { + ++e; + xc = [1].concat(xc); + } + } + } + + // Determine trailing zeros. + for (k = xc.length; !xc[--k];); + + // E.g. [4, 11, 15] becomes 4bf. + for (i = 0, str = ''; i <= k; str += alphabet.charAt(xc[i++])); + + // Add leading zeros, decimal point and trailing zeros as required. + str = toFixedPoint(str, e, alphabet.charAt(0)); + } + + // The caller will add the sign. + return str; + }; + })(); + + + // Perform division in the specified base. Called by div and convertBase. + div = (function () { + + // Assume non-zero x and k. + function multiply(x, k, base) { + var m, temp, xlo, xhi, + carry = 0, + i = x.length, + klo = k % SQRT_BASE, + khi = k / SQRT_BASE | 0; + + for (x = x.slice(); i--;) { + xlo = x[i] % SQRT_BASE; + xhi = x[i] / SQRT_BASE | 0; + m = khi * xlo + xhi * klo; + temp = klo * xlo + ((m % SQRT_BASE) * SQRT_BASE) + carry; + carry = (temp / base | 0) + (m / SQRT_BASE | 0) + khi * xhi; + x[i] = temp % base; + } + + if (carry) x = [carry].concat(x); + + return x; + } + + function compare(a, b, aL, bL) { + var i, cmp; + + if (aL != bL) { + cmp = aL > bL ? 1 : -1; + } else { + + for (i = cmp = 0; i < aL; i++) { + + if (a[i] != b[i]) { + cmp = a[i] > b[i] ? 1 : -1; + break; + } + } + } + + return cmp; + } + + function subtract(a, b, aL, base) { + var i = 0; + + // Subtract b from a. + for (; aL--;) { + a[aL] -= i; + i = a[aL] < b[aL] ? 1 : 0; + a[aL] = i * base + a[aL] - b[aL]; + } + + // Remove leading zeros. + for (; !a[0] && a.length > 1; a.splice(0, 1)); + } + + // x: dividend, y: divisor. + return function (x, y, dp, rm, base) { + var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0, + yL, yz, + s = x.s == y.s ? 1 : -1, + xc = x.c, + yc = y.c; + + // Either NaN, Infinity or 0? + if (!xc || !xc[0] || !yc || !yc[0]) { + + return new BigNumber( + + // Return NaN if either NaN, or both Infinity or 0. + !x.s || !y.s || (xc ? yc && xc[0] == yc[0] : !yc) ? NaN : + + // Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0. + xc && xc[0] == 0 || !yc ? s * 0 : s / 0 + ); + } + + q = new BigNumber(s); + qc = q.c = []; + e = x.e - y.e; + s = dp + e + 1; + + if (!base) { + base = BASE; + e = bitFloor(x.e / LOG_BASE) - bitFloor(y.e / LOG_BASE); + s = s / LOG_BASE | 0; + } + + // Result exponent may be one less then the current value of e. + // The coefficients of the BigNumbers from convertBase may have trailing zeros. + for (i = 0; yc[i] == (xc[i] || 0); i++); + + if (yc[i] > (xc[i] || 0)) e--; + + if (s < 0) { + qc.push(1); + more = true; + } else { + xL = xc.length; + yL = yc.length; + i = 0; + s += 2; + + // Normalise xc and yc so highest order digit of yc is >= base / 2. + + n = mathfloor(base / (yc[0] + 1)); + + // Not necessary, but to handle odd bases where yc[0] == (base / 2) - 1. + // if (n > 1 || n++ == 1 && yc[0] < base / 2) { + if (n > 1) { + yc = multiply(yc, n, base); + xc = multiply(xc, n, base); + yL = yc.length; + xL = xc.length; + } + + xi = yL; + rem = xc.slice(0, yL); + remL = rem.length; + + // Add zeros to make remainder as long as divisor. + for (; remL < yL; rem[remL++] = 0); + yz = yc.slice(); + yz = [0].concat(yz); + yc0 = yc[0]; + if (yc[1] >= base / 2) yc0++; + // Not necessary, but to prevent trial digit n > base, when using base 3. + // else if (base == 3 && yc0 == 1) yc0 = 1 + 1e-15; + + do { + n = 0; + + // Compare divisor and remainder. + cmp = compare(yc, rem, yL, remL); + + // If divisor < remainder. + if (cmp < 0) { + + // Calculate trial digit, n. + + rem0 = rem[0]; + if (yL != remL) rem0 = rem0 * base + (rem[1] || 0); + + // n is how many times the divisor goes into the current remainder. + n = mathfloor(rem0 / yc0); + + // Algorithm: + // product = divisor multiplied by trial digit (n). + // Compare product and remainder. + // If product is greater than remainder: + // Subtract divisor from product, decrement trial digit. + // Subtract product from remainder. + // If product was less than remainder at the last compare: + // Compare new remainder and divisor. + // If remainder is greater than divisor: + // Subtract divisor from remainder, increment trial digit. + + if (n > 1) { + + // n may be > base only when base is 3. + if (n >= base) n = base - 1; + + // product = divisor * trial digit. + prod = multiply(yc, n, base); + prodL = prod.length; + remL = rem.length; + + // Compare product and remainder. + // If product > remainder then trial digit n too high. + // n is 1 too high about 5% of the time, and is not known to have + // ever been more than 1 too high. + while (compare(prod, rem, prodL, remL) == 1) { + n--; + + // Subtract divisor from product. + subtract(prod, yL < prodL ? yz : yc, prodL, base); + prodL = prod.length; + cmp = 1; + } + } else { + + // n is 0 or 1, cmp is -1. + // If n is 0, there is no need to compare yc and rem again below, + // so change cmp to 1 to avoid it. + // If n is 1, leave cmp as -1, so yc and rem are compared again. + if (n == 0) { + + // divisor < remainder, so n must be at least 1. + cmp = n = 1; + } + + // product = divisor + prod = yc.slice(); + prodL = prod.length; + } + + if (prodL < remL) prod = [0].concat(prod); + + // Subtract product from remainder. + subtract(rem, prod, remL, base); + remL = rem.length; + + // If product was < remainder. + if (cmp == -1) { + + // Compare divisor and new remainder. + // If divisor < new remainder, subtract divisor from remainder. + // Trial digit n too low. + // n is 1 too low about 5% of the time, and very rarely 2 too low. + while (compare(yc, rem, yL, remL) < 1) { + n++; + + // Subtract divisor from remainder. + subtract(rem, yL < remL ? yz : yc, remL, base); + remL = rem.length; + } + } + } else if (cmp === 0) { + n++; + rem = [0]; + } // else cmp === 1 and n will be 0 + + // Add the next digit, n, to the result array. + qc[i++] = n; + + // Update the remainder. + if (rem[0]) { + rem[remL++] = xc[xi] || 0; + } else { + rem = [xc[xi]]; + remL = 1; + } + } while ((xi++ < xL || rem[0] != null) && s--); + + more = rem[0] != null; + + // Leading zero? + if (!qc[0]) qc.splice(0, 1); + } + + if (base == BASE) { + + // To calculate q.e, first get the number of digits of qc[0]. + for (i = 1, s = qc[0]; s >= 10; s /= 10, i++); + + round(q, dp + (q.e = i + e * LOG_BASE - 1) + 1, rm, more); + + // Caller is convertBase. + } else { + q.e = e; + q.r = +more; + } + + return q; + }; + })(); + + + /* + * Return a string representing the value of BigNumber n in fixed-point or exponential + * notation rounded to the specified decimal places or significant digits. + * + * n: a BigNumber. + * i: the index of the last digit required (i.e. the digit that may be rounded up). + * rm: the rounding mode. + * id: 1 (toExponential) or 2 (toPrecision). + */ + function format(n, i, rm, id) { + var c0, e, ne, len, str; + + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + if (!n.c) return n.toString(); + + c0 = n.c[0]; + ne = n.e; + + if (i == null) { + str = coeffToString(n.c); + str = id == 1 || id == 2 && (ne <= TO_EXP_NEG || ne >= TO_EXP_POS) + ? toExponential(str, ne) + : toFixedPoint(str, ne, '0'); + } else { + n = round(new BigNumber(n), i, rm); + + // n.e may have changed if the value was rounded up. + e = n.e; + + str = coeffToString(n.c); + len = str.length; + + // toPrecision returns exponential notation if the number of significant digits + // specified is less than the number of digits necessary to represent the integer + // part of the value in fixed-point notation. + + // Exponential notation. + if (id == 1 || id == 2 && (i <= e || e <= TO_EXP_NEG)) { + + // Append zeros? + for (; len < i; str += '0', len++); + str = toExponential(str, e); + + // Fixed-point notation. + } else { + i -= ne + (id === 2 && e > ne); + str = toFixedPoint(str, e, '0'); + + // Append zeros? + if (e + 1 > len) { + if (--i > 0) for (str += '.'; i--; str += '0'); + } else { + i += e - len; + if (i > 0) { + if (e + 1 == len) str += '.'; + for (; i--; str += '0'); + } + } + } + } + + return n.s < 0 && c0 ? '-' + str : str; + } + + + // Handle BigNumber.max and BigNumber.min. + // If any number is NaN, return NaN. + function maxOrMin(args, n) { + var k, y, + i = 1, + x = new BigNumber(args[0]); + + for (; i < args.length; i++) { + y = new BigNumber(args[i]); + if (!y.s || (k = compare(x, y)) === n || k === 0 && x.s === n) { + x = y; + } + } + + return x; + } + + + /* + * Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP. + * Called by minus, plus and times. + */ + function normalise(n, c, e) { + var i = 1, + j = c.length; + + // Remove trailing zeros. + for (; !c[--j]; c.pop()); + + // Calculate the base 10 exponent. First get the number of digits of c[0]. + for (j = c[0]; j >= 10; j /= 10, i++); + + // Overflow? + if ((e = i + e * LOG_BASE - 1) > MAX_EXP) { + + // Infinity. + n.c = n.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + n.c = [n.e = 0]; + } else { + n.e = e; + n.c = c; + } + + return n; + } + + + // Handle values that fail the validity test in BigNumber. + parseNumeric = (function () { + var basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i, + dotAfter = /^([^.]+)\.$/, + dotBefore = /^\.([^.]+)$/, + isInfinityOrNaN = /^-?(Infinity|NaN)$/, + whitespaceOrPlus = /^\s*\+(?=[\w.])|^\s+|\s+$/g; + + return function (x, str, isNum, b) { + var base, + s = isNum ? str : str.replace(whitespaceOrPlus, ''); + + // No exception on ±Infinity or NaN. + if (isInfinityOrNaN.test(s)) { + x.s = isNaN(s) ? null : s < 0 ? -1 : 1; + } else { + if (!isNum) { + + // basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i + s = s.replace(basePrefix, function (m, p1, p2) { + base = (p2 = p2.toLowerCase()) == 'x' ? 16 : p2 == 'b' ? 2 : 8; + return !b || b == base ? p1 : m; + }); + + if (b) { + base = b; + + // E.g. '1.' to '1', '.1' to '0.1' + s = s.replace(dotAfter, '$1').replace(dotBefore, '0.$1'); + } + + if (str != s) return new BigNumber(s, base); + } + + // '[BigNumber Error] Not a number: {n}' + // '[BigNumber Error] Not a base {b} number: {n}' + if (BigNumber.DEBUG) { + throw Error + (bignumberError + 'Not a' + (b ? ' base ' + b : '') + ' number: ' + str); + } + + // NaN + x.s = null; + } + + x.c = x.e = null; + } + })(); + + + /* + * Round x to sd significant digits using rounding mode rm. Check for over/under-flow. + * If r is truthy, it is known that there are more digits after the rounding digit. + */ + function round(x, sd, rm, r) { + var d, i, j, k, n, ni, rd, + xc = x.c, + pows10 = POWS_TEN; + + // if x is not Infinity or NaN... + if (xc) { + + // rd is the rounding digit, i.e. the digit after the digit that may be rounded up. + // n is a base 1e14 number, the value of the element of array x.c containing rd. + // ni is the index of n within x.c. + // d is the number of digits of n. + // i is the index of rd within n including leading zeros. + // j is the actual index of rd within n (if < 0, rd is a leading zero). + out: { + + // Get the number of digits of the first element of xc. + for (d = 1, k = xc[0]; k >= 10; k /= 10, d++); + i = sd - d; + + // If the rounding digit is in the first element of xc... + if (i < 0) { + i += LOG_BASE; + j = sd; + n = xc[ni = 0]; + + // Get the rounding digit at index j of n. + rd = mathfloor(n / pows10[d - j - 1] % 10); + } else { + ni = mathceil((i + 1) / LOG_BASE); + + if (ni >= xc.length) { + + if (r) { + + // Needed by sqrt. + for (; xc.length <= ni; xc.push(0)); + n = rd = 0; + d = 1; + i %= LOG_BASE; + j = i - LOG_BASE + 1; + } else { + break out; + } + } else { + n = k = xc[ni]; + + // Get the number of digits of n. + for (d = 1; k >= 10; k /= 10, d++); + + // Get the index of rd within n. + i %= LOG_BASE; + + // Get the index of rd within n, adjusted for leading zeros. + // The number of leading zeros of n is given by LOG_BASE - d. + j = i - LOG_BASE + d; + + // Get the rounding digit at index j of n. + rd = j < 0 ? 0 : mathfloor(n / pows10[d - j - 1] % 10); + } + } + + r = r || sd < 0 || + + // Are there any non-zero digits after the rounding digit? + // The expression n % pows10[d - j - 1] returns all digits of n to the right + // of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714. + xc[ni + 1] != null || (j < 0 ? n : n % pows10[d - j - 1]); + + r = rm < 4 + ? (rd || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : rd > 5 || rd == 5 && (rm == 4 || r || rm == 6 && + + // Check whether the digit to the left of the rounding digit is odd. + ((i > 0 ? j > 0 ? n / pows10[d - j] : 0 : xc[ni - 1]) % 10) & 1 || + rm == (x.s < 0 ? 8 : 7)); + + if (sd < 1 || !xc[0]) { + xc.length = 0; + + if (r) { + + // Convert sd to decimal places. + sd -= x.e + 1; + + // 1, 0.1, 0.01, 0.001, 0.0001 etc. + xc[0] = pows10[(LOG_BASE - sd % LOG_BASE) % LOG_BASE]; + x.e = -sd || 0; + } else { + + // Zero. + xc[0] = x.e = 0; + } + + return x; + } + + // Remove excess digits. + if (i == 0) { + xc.length = ni; + k = 1; + ni--; + } else { + xc.length = ni + 1; + k = pows10[LOG_BASE - i]; + + // E.g. 56700 becomes 56000 if 7 is the rounding digit. + // j > 0 means i > number of leading zeros of n. + xc[ni] = j > 0 ? mathfloor(n / pows10[d - j] % pows10[j]) * k : 0; + } + + // Round up? + if (r) { + + for (; ;) { + + // If the digit to be rounded up is in the first element of xc... + if (ni == 0) { + + // i will be the length of xc[0] before k is added. + for (i = 1, j = xc[0]; j >= 10; j /= 10, i++); + j = xc[0] += k; + for (k = 1; j >= 10; j /= 10, k++); + + // if i != k the length has increased. + if (i != k) { + x.e++; + if (xc[0] == BASE) xc[0] = 1; + } + + break; + } else { + xc[ni] += k; + if (xc[ni] != BASE) break; + xc[ni--] = 0; + k = 1; + } + } + } + + // Remove trailing zeros. + for (i = xc.length; xc[--i] === 0; xc.pop()); + } + + // Overflow? Infinity. + if (x.e > MAX_EXP) { + x.c = x.e = null; + + // Underflow? Zero. + } else if (x.e < MIN_EXP) { + x.c = [x.e = 0]; + } + } + + return x; + } + + + function valueOf(n) { + var str, + e = n.e; + + if (e === null) return n.toString(); + + str = coeffToString(n.c); + + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(str, e) + : toFixedPoint(str, e, '0'); + + return n.s < 0 ? '-' + str : str; + } + + + // PROTOTYPE/INSTANCE METHODS + + + /* + * Return a new BigNumber whose value is the absolute value of this BigNumber. + */ + P.absoluteValue = P.abs = function () { + var x = new BigNumber(this); + if (x.s < 0) x.s = 1; + return x; + }; + + + /* + * Return + * 1 if the value of this BigNumber is greater than the value of BigNumber(y, b), + * -1 if the value of this BigNumber is less than the value of BigNumber(y, b), + * 0 if they have the same value, + * or null if the value of either is NaN. + */ + P.comparedTo = function (y, b) { + return compare(this, new BigNumber(y, b)); + }; + + + /* + * If dp is undefined or null or true or false, return the number of decimal places of the + * value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * + * Otherwise, if dp is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of dp decimal places using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * [dp] {number} Decimal places: integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.decimalPlaces = P.dp = function (dp, rm) { + var c, n, v, + x = this; + + if (dp != null) { + intCheck(dp, 0, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), dp + x.e + 1, rm); + } + + if (!(c = x.c)) return null; + n = ((v = c.length - 1) - bitFloor(this.e / LOG_BASE)) * LOG_BASE; + + // Subtract the number of trailing zeros of the last number. + if (v = c[v]) for (; v % 10 == 0; v /= 10, n--); + if (n < 0) n = 0; + + return n; + }; + + + /* + * n / 0 = I + * n / N = N + * n / I = 0 + * 0 / n = 0 + * 0 / 0 = N + * 0 / N = N + * 0 / I = 0 + * N / n = N + * N / 0 = N + * N / N = N + * N / I = N + * I / n = I + * I / 0 = I + * I / N = N + * I / I = N + * + * Return a new BigNumber whose value is the value of this BigNumber divided by the value of + * BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.dividedBy = P.div = function (y, b) { + return div(this, new BigNumber(y, b), DECIMAL_PLACES, ROUNDING_MODE); + }; + + + /* + * Return a new BigNumber whose value is the integer part of dividing the value of this + * BigNumber by the value of BigNumber(y, b). + */ + P.dividedToIntegerBy = P.idiv = function (y, b) { + return div(this, new BigNumber(y, b), 0, 1); + }; + + + /* + * Return a BigNumber whose value is the value of this BigNumber exponentiated by n. + * + * If m is present, return the result modulo m. + * If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE. + * If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using ROUNDING_MODE. + * + * The modular power operation works efficiently when x, n, and m are integers, otherwise it + * is equivalent to calculating x.exponentiatedBy(n).modulo(m) with a POW_PRECISION of 0. + * + * n {number|string|BigNumber} The exponent. An integer. + * [m] {number|string|BigNumber} The modulus. + * + * '[BigNumber Error] Exponent not an integer: {n}' + */ + P.exponentiatedBy = P.pow = function (n, m) { + var half, isModExp, i, k, more, nIsBig, nIsNeg, nIsOdd, y, + x = this; + + n = new BigNumber(n); + + // Allow NaN and ±Infinity, but not other non-integers. + if (n.c && !n.isInteger()) { + throw Error + (bignumberError + 'Exponent not an integer: ' + valueOf(n)); + } + + if (m != null) m = new BigNumber(m); + + // Exponent of MAX_SAFE_INTEGER is 15. + nIsBig = n.e > 14; + + // If x is NaN, ±Infinity, ±0 or ±1, or n is ±Infinity, NaN or ±0. + if (!x.c || !x.c[0] || x.c[0] == 1 && !x.e && x.c.length == 1 || !n.c || !n.c[0]) { + + // The sign of the result of pow when x is negative depends on the evenness of n. + // If +n overflows to ±Infinity, the evenness of n would be not be known. + y = new BigNumber(Math.pow(+valueOf(x), nIsBig ? n.s * (2 - isOdd(n)) : +valueOf(n))); + return m ? y.mod(m) : y; + } + + nIsNeg = n.s < 0; + + if (m) { + + // x % m returns NaN if abs(m) is zero, or m is NaN. + if (m.c ? !m.c[0] : !m.s) return new BigNumber(NaN); + + isModExp = !nIsNeg && x.isInteger() && m.isInteger(); + + if (isModExp) x = x.mod(m); + + // Overflow to ±Infinity: >=2**1e10 or >=1.0000024**1e15. + // Underflow to ±0: <=0.79**1e10 or <=0.9999975**1e15. + } else if (n.e > 9 && (x.e > 0 || x.e < -1 || (x.e == 0 + // [1, 240000000] + ? x.c[0] > 1 || nIsBig && x.c[1] >= 24e7 + // [80000000000000] [99999750000000] + : x.c[0] < 8e13 || nIsBig && x.c[0] <= 9999975e7))) { + + // If x is negative and n is odd, k = -0, else k = 0. + k = x.s < 0 && isOdd(n) ? -0 : 0; + + // If x >= 1, k = ±Infinity. + if (x.e > -1) k = 1 / k; + + // If n is negative return ±0, else return ±Infinity. + return new BigNumber(nIsNeg ? 1 / k : k); + + } else if (POW_PRECISION) { + + // Truncating each coefficient array to a length of k after each multiplication + // equates to truncating significant digits to POW_PRECISION + [28, 41], + // i.e. there will be a minimum of 28 guard digits retained. + k = mathceil(POW_PRECISION / LOG_BASE + 2); + } + + if (nIsBig) { + half = new BigNumber(0.5); + if (nIsNeg) n.s = 1; + nIsOdd = isOdd(n); + } else { + i = Math.abs(+valueOf(n)); + nIsOdd = i % 2; + } + + y = new BigNumber(ONE); + + // Performs 54 loop iterations for n of 9007199254740991. + for (; ;) { + + if (nIsOdd) { + y = y.times(x); + if (!y.c) break; + + if (k) { + if (y.c.length > k) y.c.length = k; + } else if (isModExp) { + y = y.mod(m); //y = y.minus(div(y, m, 0, MODULO_MODE).times(m)); + } + } + + if (i) { + i = mathfloor(i / 2); + if (i === 0) break; + nIsOdd = i % 2; + } else { + n = n.times(half); + round(n, n.e + 1, 1); + + if (n.e > 14) { + nIsOdd = isOdd(n); + } else { + i = +valueOf(n); + if (i === 0) break; + nIsOdd = i % 2; + } + } + + x = x.times(x); + + if (k) { + if (x.c && x.c.length > k) x.c.length = k; + } else if (isModExp) { + x = x.mod(m); //x = x.minus(div(x, m, 0, MODULO_MODE).times(m)); + } + } + + if (isModExp) return y; + if (nIsNeg) y = ONE.div(y); + + return m ? y.mod(m) : k ? round(y, POW_PRECISION, ROUNDING_MODE, more) : y; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber rounded to an integer + * using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {rm}' + */ + P.integerValue = function (rm) { + var n = new BigNumber(this); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + return round(n, n.e + 1, rm); + }; + + + /* + * Return true if the value of this BigNumber is equal to the value of BigNumber(y, b), + * otherwise return false. + */ + P.isEqualTo = P.eq = function (y, b) { + return compare(this, new BigNumber(y, b)) === 0; + }; + + + /* + * Return true if the value of this BigNumber is a finite number, otherwise return false. + */ + P.isFinite = function () { + return !!this.c; + }; + + + /* + * Return true if the value of this BigNumber is greater than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isGreaterThan = P.gt = function (y, b) { + return compare(this, new BigNumber(y, b)) > 0; + }; + + + /* + * Return true if the value of this BigNumber is greater than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isGreaterThanOrEqualTo = P.gte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === 1 || b === 0; + + }; + + + /* + * Return true if the value of this BigNumber is an integer, otherwise return false. + */ + P.isInteger = function () { + return !!this.c && bitFloor(this.e / LOG_BASE) > this.c.length - 2; + }; + + + /* + * Return true if the value of this BigNumber is less than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isLessThan = P.lt = function (y, b) { + return compare(this, new BigNumber(y, b)) < 0; + }; + + + /* + * Return true if the value of this BigNumber is less than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isLessThanOrEqualTo = P.lte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === -1 || b === 0; + }; + + + /* + * Return true if the value of this BigNumber is NaN, otherwise return false. + */ + P.isNaN = function () { + return !this.s; + }; + + + /* + * Return true if the value of this BigNumber is negative, otherwise return false. + */ + P.isNegative = function () { + return this.s < 0; + }; + + + /* + * Return true if the value of this BigNumber is positive, otherwise return false. + */ + P.isPositive = function () { + return this.s > 0; + }; + + + /* + * Return true if the value of this BigNumber is 0 or -0, otherwise return false. + */ + P.isZero = function () { + return !!this.c && this.c[0] == 0; + }; + + + /* + * n - 0 = n + * n - N = N + * n - I = -I + * 0 - n = -n + * 0 - 0 = 0 + * 0 - N = N + * 0 - I = -I + * N - n = N + * N - 0 = N + * N - N = N + * N - I = N + * I - n = I + * I - 0 = I + * I - N = N + * I - I = N + * + * Return a new BigNumber whose value is the value of this BigNumber minus the value of + * BigNumber(y, b). + */ + P.minus = function (y, b) { + var i, j, t, xLTy, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.plus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Either Infinity? + if (!xc || !yc) return xc ? (y.s = -b, y) : new BigNumber(yc ? x : NaN); + + // Either zero? + if (!xc[0] || !yc[0]) { + + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + return yc[0] ? (y.s = -b, y) : new BigNumber(xc[0] ? x : + + // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity + ROUNDING_MODE == 3 ? -0 : 0); + } + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Determine which is the bigger number. + if (a = xe - ye) { + + if (xLTy = a < 0) { + a = -a; + t = xc; + } else { + ye = xe; + t = yc; + } + + t.reverse(); + + // Prepend zeros to equalise exponents. + for (b = a; b--; t.push(0)); + t.reverse(); + } else { + + // Exponents equal. Check digit by digit. + j = (xLTy = (a = xc.length) < (b = yc.length)) ? a : b; + + for (a = b = 0; b < j; b++) { + + if (xc[b] != yc[b]) { + xLTy = xc[b] < yc[b]; + break; + } + } + } + + // x < y? Point xc to the array of the bigger number. + if (xLTy) { + t = xc; + xc = yc; + yc = t; + y.s = -y.s; + } + + b = (j = yc.length) - (i = xc.length); + + // Append zeros to xc if shorter. + // No need to add zeros to yc if shorter as subtract only needs to start at yc.length. + if (b > 0) for (; b--; xc[i++] = 0); + b = BASE - 1; + + // Subtract yc from xc. + for (; j > a;) { + + if (xc[--j] < yc[j]) { + for (i = j; i && !xc[--i]; xc[i] = b); + --xc[i]; + xc[j] += BASE; + } + + xc[j] -= yc[j]; + } + + // Remove leading zeros and adjust exponent accordingly. + for (; xc[0] == 0; xc.splice(0, 1), --ye); + + // Zero? + if (!xc[0]) { + + // Following IEEE 754 (2008) 6.3, + // n - n = +0 but n - n = -0 when rounding towards -Infinity. + y.s = ROUNDING_MODE == 3 ? -1 : 1; + y.c = [y.e = 0]; + return y; + } + + // No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity + // for finite x and y. + return normalise(y, xc, ye); + }; + + + /* + * n % 0 = N + * n % N = N + * n % I = n + * 0 % n = 0 + * -0 % n = -0 + * 0 % 0 = N + * 0 % N = N + * 0 % I = 0 + * N % n = N + * N % 0 = N + * N % N = N + * N % I = N + * I % n = N + * I % 0 = N + * I % N = N + * I % I = N + * + * Return a new BigNumber whose value is the value of this BigNumber modulo the value of + * BigNumber(y, b). The result depends on the value of MODULO_MODE. + */ + P.modulo = P.mod = function (y, b) { + var q, s, + x = this; + + y = new BigNumber(y, b); + + // Return NaN if x is Infinity or NaN, or y is NaN or zero. + if (!x.c || !y.s || y.c && !y.c[0]) { + return new BigNumber(NaN); + + // Return x if y is Infinity or x is zero. + } else if (!y.c || x.c && !x.c[0]) { + return new BigNumber(x); + } + + if (MODULO_MODE == 9) { + + // Euclidian division: q = sign(y) * floor(x / abs(y)) + // r = x - qy where 0 <= r < abs(y) + s = y.s; + y.s = 1; + q = div(x, y, 0, 3); + y.s = s; + q.s *= s; + } else { + q = div(x, y, 0, MODULO_MODE); + } + + y = x.minus(q.times(y)); + + // To match JavaScript %, ensure sign of zero is sign of dividend. + if (!y.c[0] && MODULO_MODE == 1) y.s = x.s; + + return y; + }; + + + /* + * n * 0 = 0 + * n * N = N + * n * I = I + * 0 * n = 0 + * 0 * 0 = 0 + * 0 * N = N + * 0 * I = N + * N * n = N + * N * 0 = N + * N * N = N + * N * I = N + * I * n = I + * I * 0 = N + * I * N = N + * I * I = I + * + * Return a new BigNumber whose value is the value of this BigNumber multiplied by the value + * of BigNumber(y, b). + */ + P.multipliedBy = P.times = function (y, b) { + var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc, + base, sqrtBase, + x = this, + xc = x.c, + yc = (y = new BigNumber(y, b)).c; + + // Either NaN, ±Infinity or ±0? + if (!xc || !yc || !xc[0] || !yc[0]) { + + // Return NaN if either is NaN, or one is 0 and the other is Infinity. + if (!x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc) { + y.c = y.e = y.s = null; + } else { + y.s *= x.s; + + // Return ±Infinity if either is ±Infinity. + if (!xc || !yc) { + y.c = y.e = null; + + // Return ±0 if either is ±0. + } else { + y.c = [0]; + y.e = 0; + } + } + + return y; + } + + e = bitFloor(x.e / LOG_BASE) + bitFloor(y.e / LOG_BASE); + y.s *= x.s; + xcL = xc.length; + ycL = yc.length; + + // Ensure xc points to longer array and xcL to its length. + if (xcL < ycL) { + zc = xc; + xc = yc; + yc = zc; + i = xcL; + xcL = ycL; + ycL = i; + } + + // Initialise the result array with zeros. + for (i = xcL + ycL, zc = []; i--; zc.push(0)); + + base = BASE; + sqrtBase = SQRT_BASE; + + for (i = ycL; --i >= 0;) { + c = 0; + ylo = yc[i] % sqrtBase; + yhi = yc[i] / sqrtBase | 0; + + for (k = xcL, j = i + k; j > i;) { + xlo = xc[--k] % sqrtBase; + xhi = xc[k] / sqrtBase | 0; + m = yhi * xlo + xhi * ylo; + xlo = ylo * xlo + ((m % sqrtBase) * sqrtBase) + zc[j] + c; + c = (xlo / base | 0) + (m / sqrtBase | 0) + yhi * xhi; + zc[j--] = xlo % base; + } + + zc[j] = c; + } + + if (c) { + ++e; + } else { + zc.splice(0, 1); + } + + return normalise(y, zc, e); + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber negated, + * i.e. multiplied by -1. + */ + P.negated = function () { + var x = new BigNumber(this); + x.s = -x.s || null; + return x; + }; + + + /* + * n + 0 = n + * n + N = N + * n + I = I + * 0 + n = n + * 0 + 0 = 0 + * 0 + N = N + * 0 + I = I + * N + n = N + * N + 0 = N + * N + N = N + * N + I = N + * I + n = I + * I + 0 = I + * I + N = N + * I + I = I + * + * Return a new BigNumber whose value is the value of this BigNumber plus the value of + * BigNumber(y, b). + */ + P.plus = function (y, b) { + var t, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.minus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Return ±Infinity if either ±Infinity. + if (!xc || !yc) return new BigNumber(a / 0); + + // Either zero? + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + if (!xc[0] || !yc[0]) return yc[0] ? y : new BigNumber(xc[0] ? x : a * 0); + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Prepend zeros to equalise exponents. Faster to use reverse then do unshifts. + if (a = xe - ye) { + if (a > 0) { + ye = xe; + t = yc; + } else { + a = -a; + t = xc; + } + + t.reverse(); + for (; a--; t.push(0)); + t.reverse(); + } + + a = xc.length; + b = yc.length; + + // Point xc to the longer array, and b to the shorter length. + if (a - b < 0) { + t = yc; + yc = xc; + xc = t; + b = a; + } + + // Only start adding at yc.length - 1 as the further digits of xc can be ignored. + for (a = 0; b;) { + a = (xc[--b] = xc[b] + yc[b] + a) / BASE | 0; + xc[b] = BASE === xc[b] ? 0 : xc[b] % BASE; + } + + if (a) { + xc = [a].concat(xc); + ++ye; + } + + // No need to check for zero, as +x + +y != 0 && -x + -y != 0 + // ye = MAX_EXP + 1 possible + return normalise(y, xc, ye); + }; + + + /* + * If sd is undefined or null or true or false, return the number of significant digits of + * the value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * If sd is true include integer-part trailing zeros in the count. + * + * Otherwise, if sd is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of sd significant digits using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * sd {number|boolean} number: significant digits: integer, 1 to MAX inclusive. + * boolean: whether to count integer-part trailing zeros: true or false. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.precision = P.sd = function (sd, rm) { + var c, n, v, + x = this; + + if (sd != null && sd !== !!sd) { + intCheck(sd, 1, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), sd, rm); + } + + if (!(c = x.c)) return null; + v = c.length - 1; + n = v * LOG_BASE + 1; + + if (v = c[v]) { + + // Subtract the number of trailing zeros of the last element. + for (; v % 10 == 0; v /= 10, n--); + + // Add the number of digits of the first element. + for (v = c[0]; v >= 10; v /= 10, n++); + } + + if (sd && x.e + 1 > n) n = x.e + 1; + + return n; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber shifted by k places + * (powers of 10). Shift to the right if n > 0, and to the left if n < 0. + * + * k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {k}' + */ + P.shiftedBy = function (k) { + intCheck(k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); + return this.times('1e' + k); + }; + + + /* + * sqrt(-n) = N + * sqrt(N) = N + * sqrt(-I) = N + * sqrt(I) = I + * sqrt(0) = 0 + * sqrt(-0) = -0 + * + * Return a new BigNumber whose value is the square root of the value of this BigNumber, + * rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.squareRoot = P.sqrt = function () { + var m, n, r, rep, t, + x = this, + c = x.c, + s = x.s, + e = x.e, + dp = DECIMAL_PLACES + 4, + half = new BigNumber('0.5'); + + // Negative/NaN/Infinity/zero? + if (s !== 1 || !c || !c[0]) { + return new BigNumber(!s || s < 0 && (!c || c[0]) ? NaN : c ? x : 1 / 0); + } + + // Initial estimate. + s = Math.sqrt(+valueOf(x)); + + // Math.sqrt underflow/overflow? + // Pass x to Math.sqrt as integer, then adjust the exponent of the result. + if (s == 0 || s == 1 / 0) { + n = coeffToString(c); + if ((n.length + e) % 2 == 0) n += '0'; + s = Math.sqrt(+n); + e = bitFloor((e + 1) / 2) - (e < 0 || e % 2); + + if (s == 1 / 0) { + n = '5e' + e; + } else { + n = s.toExponential(); + n = n.slice(0, n.indexOf('e') + 1) + e; + } + + r = new BigNumber(n); + } else { + r = new BigNumber(s + ''); + } + + // Check for zero. + // r could be zero if MIN_EXP is changed after the this value was created. + // This would cause a division by zero (x/t) and hence Infinity below, which would cause + // coeffToString to throw. + if (r.c[0]) { + e = r.e; + s = e + dp; + if (s < 3) s = 0; + + // Newton-Raphson iteration. + for (; ;) { + t = r; + r = half.times(t.plus(div(x, t, dp, 1))); + + if (coeffToString(t.c).slice(0, s) === (n = coeffToString(r.c)).slice(0, s)) { + + // The exponent of r may here be one less than the final result exponent, + // e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits + // are indexed correctly. + if (r.e < e) --s; + n = n.slice(s - 3, s + 1); + + // The 4th rounding digit may be in error by -1 so if the 4 rounding digits + // are 9999 or 4999 (i.e. approaching a rounding boundary) continue the + // iteration. + if (n == '9999' || !rep && n == '4999') { + + // On the first iteration only, check to see if rounding up gives the + // exact result as the nines may infinitely repeat. + if (!rep) { + round(t, t.e + DECIMAL_PLACES + 2, 0); + + if (t.times(t).eq(x)) { + r = t; + break; + } + } + + dp += 4; + s += 4; + rep = 1; + } else { + + // If rounding digits are null, 0{0,4} or 50{0,3}, check for exact + // result. If not, then there are further digits and m will be truthy. + if (!+n || !+n.slice(1) && n.charAt(0) == '5') { + + // Truncate to the first rounding digit. + round(r, r.e + DECIMAL_PLACES + 2, 1); + m = !r.times(r).eq(x); + } + + break; + } + } + } + } + + return round(r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m); + }; + + + /* + * Return a string representing the value of this BigNumber in exponential notation and + * rounded using ROUNDING_MODE to dp fixed decimal places. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toExponential = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp++; + } + return format(this, dp, rm, 1); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounding + * to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * Note: as with JavaScript's number type, (-0).toFixed(0) is '0', + * but e.g. (-0.00001).toFixed(0) is '-0'. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toFixed = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp = dp + this.e + 1; + } + return format(this, dp, rm); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounded + * using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties + * of the format or FORMAT object (see BigNumber.set). + * + * The formatting object may contain some or all of the properties shown below. + * + * FORMAT = { + * prefix: '', + * groupSize: 3, + * secondaryGroupSize: 0, + * groupSeparator: ',', + * decimalSeparator: '.', + * fractionGroupSize: 0, + * fractionGroupSeparator: '\xA0', // non-breaking space + * suffix: '' + * }; + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * [format] {object} Formatting options. See FORMAT pbject above. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + * '[BigNumber Error] Argument not an object: {format}' + */ + P.toFormat = function (dp, rm, format) { + var str, + x = this; + + if (format == null) { + if (dp != null && rm && typeof rm == 'object') { + format = rm; + rm = null; + } else if (dp && typeof dp == 'object') { + format = dp; + dp = rm = null; + } else { + format = FORMAT; + } + } else if (typeof format != 'object') { + throw Error + (bignumberError + 'Argument not an object: ' + format); + } + + str = x.toFixed(dp, rm); + + if (x.c) { + var i, + arr = str.split('.'), + g1 = +format.groupSize, + g2 = +format.secondaryGroupSize, + groupSeparator = format.groupSeparator || '', + intPart = arr[0], + fractionPart = arr[1], + isNeg = x.s < 0, + intDigits = isNeg ? intPart.slice(1) : intPart, + len = intDigits.length; + + if (g2) { + i = g1; + g1 = g2; + g2 = i; + len -= i; + } + + if (g1 > 0 && len > 0) { + i = len % g1 || g1; + intPart = intDigits.substr(0, i); + for (; i < len; i += g1) intPart += groupSeparator + intDigits.substr(i, g1); + if (g2 > 0) intPart += groupSeparator + intDigits.slice(i); + if (isNeg) intPart = '-' + intPart; + } + + str = fractionPart + ? intPart + (format.decimalSeparator || '') + ((g2 = +format.fractionGroupSize) + ? fractionPart.replace(new RegExp('\\d{' + g2 + '}\\B', 'g'), + '$&' + (format.fractionGroupSeparator || '')) + : fractionPart) + : intPart; + } + + return (format.prefix || '') + str + (format.suffix || ''); + }; + + + /* + * Return an array of two BigNumbers representing the value of this BigNumber as a simple + * fraction with an integer numerator and an integer denominator. + * The denominator will be a positive non-zero value less than or equal to the specified + * maximum denominator. If a maximum denominator is not specified, the denominator will be + * the lowest value necessary to represent the number exactly. + * + * [md] {number|string|BigNumber} Integer >= 1, or Infinity. The maximum denominator. + * + * '[BigNumber Error] Argument {not an integer|out of range} : {md}' + */ + P.toFraction = function (md) { + var d, d0, d1, d2, e, exp, n, n0, n1, q, r, s, + x = this, + xc = x.c; + + if (md != null) { + n = new BigNumber(md); + + // Throw if md is less than one or is not an integer, unless it is Infinity. + if (!n.isInteger() && (n.c || n.s !== 1) || n.lt(ONE)) { + throw Error + (bignumberError + 'Argument ' + + (n.isInteger() ? 'out of range: ' : 'not an integer: ') + valueOf(n)); + } + } + + if (!xc) return new BigNumber(x); + + d = new BigNumber(ONE); + n1 = d0 = new BigNumber(ONE); + d1 = n0 = new BigNumber(ONE); + s = coeffToString(xc); + + // Determine initial denominator. + // d is a power of 10 and the minimum max denominator that specifies the value exactly. + e = d.e = s.length - x.e - 1; + d.c[0] = POWS_TEN[(exp = e % LOG_BASE) < 0 ? LOG_BASE + exp : exp]; + md = !md || n.comparedTo(d) > 0 ? (e > 0 ? d : n1) : n; + + exp = MAX_EXP; + MAX_EXP = 1 / 0; + n = new BigNumber(s); + + // n0 = d1 = 0 + n0.c[0] = 0; + + for (; ;) { + q = div(n, d, 0, 1); + d2 = d0.plus(q.times(d1)); + if (d2.comparedTo(md) == 1) break; + d0 = d1; + d1 = d2; + n1 = n0.plus(q.times(d2 = n1)); + n0 = d2; + d = n.minus(q.times(d2 = d)); + n = d2; + } + + d2 = div(md.minus(d0), d1, 0, 1); + n0 = n0.plus(d2.times(n1)); + d0 = d0.plus(d2.times(d1)); + n0.s = n1.s = x.s; + e = e * 2; + + // Determine which fraction is closer to x, n0/d0 or n1/d1 + r = div(n1, d1, e, ROUNDING_MODE).minus(x).abs().comparedTo( + div(n0, d0, e, ROUNDING_MODE).minus(x).abs()) < 1 ? [n1, d1] : [n0, d0]; + + MAX_EXP = exp; + + return r; + }; + + + /* + * Return the value of this BigNumber converted to a number primitive. + */ + P.toNumber = function () { + return +valueOf(this); + }; + + + /* + * Return a string representing the value of this BigNumber rounded to sd significant digits + * using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits + * necessary to represent the integer part of the value in fixed-point notation, then use + * exponential notation. + * + * [sd] {number} Significant digits. Integer, 1 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.toPrecision = function (sd, rm) { + if (sd != null) intCheck(sd, 1, MAX); + return format(this, sd, rm, 2); + }; + + + /* + * Return a string representing the value of this BigNumber in base b, or base 10 if b is + * omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and + * ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent + * that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than + * TO_EXP_NEG, return exponential notation. + * + * [b] {number} Integer, 2 to ALPHABET.length inclusive. + * + * '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + */ + P.toString = function (b) { + var str, + n = this, + s = n.s, + e = n.e; + + // Infinity or NaN? + if (e === null) { + if (s) { + str = 'Infinity'; + if (s < 0) str = '-' + str; + } else { + str = 'NaN'; + } + } else { + if (b == null) { + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(coeffToString(n.c), e) + : toFixedPoint(coeffToString(n.c), e, '0'); + } else if (b === 10 && alphabetHasNormalDecimalDigits) { + n = round(new BigNumber(n), DECIMAL_PLACES + e + 1, ROUNDING_MODE); + str = toFixedPoint(coeffToString(n.c), n.e, '0'); + } else { + intCheck(b, 2, ALPHABET.length, 'Base'); + str = convertBase(toFixedPoint(coeffToString(n.c), e, '0'), 10, b, s, true); + } + + if (s < 0 && n.c[0]) str = '-' + str; + } + + return str; + }; + + + /* + * Return as toString, but do not accept a base argument, and include the minus sign for + * negative zero. + */ + P.valueOf = P.toJSON = function () { + return valueOf(this); + }; + + + P._isBigNumber = true; + + if (configObject != null) BigNumber.set(configObject); + + return BigNumber; + } + + + // PRIVATE HELPER FUNCTIONS + + // These functions don't need access to variables, + // e.g. DECIMAL_PLACES, in the scope of the `clone` function above. + + + function bitFloor(n) { + var i = n | 0; + return n > 0 || n === i ? i : i - 1; + } + + + // Return a coefficient array as a string of base 10 digits. + function coeffToString(a) { + var s, z, + i = 1, + j = a.length, + r = a[0] + ''; + + for (; i < j;) { + s = a[i++] + ''; + z = LOG_BASE - s.length; + for (; z--; s = '0' + s); + r += s; + } + + // Determine trailing zeros. + for (j = r.length; r.charCodeAt(--j) === 48;); + + return r.slice(0, j + 1 || 1); + } + + + // Compare the value of BigNumbers x and y. + function compare(x, y) { + var a, b, + xc = x.c, + yc = y.c, + i = x.s, + j = y.s, + k = x.e, + l = y.e; + + // Either NaN? + if (!i || !j) return null; + + a = xc && !xc[0]; + b = yc && !yc[0]; + + // Either zero? + if (a || b) return a ? b ? 0 : -j : i; + + // Signs differ? + if (i != j) return i; + + a = i < 0; + b = k == l; + + // Either Infinity? + if (!xc || !yc) return b ? 0 : !xc ^ a ? 1 : -1; + + // Compare exponents. + if (!b) return k > l ^ a ? 1 : -1; + + j = (k = xc.length) < (l = yc.length) ? k : l; + + // Compare digit by digit. + for (i = 0; i < j; i++) if (xc[i] != yc[i]) return xc[i] > yc[i] ^ a ? 1 : -1; + + // Compare lengths. + return k == l ? 0 : k > l ^ a ? 1 : -1; + } + + + /* + * Check that n is a primitive number, an integer, and in range, otherwise throw. + */ + function intCheck(n, min, max, name) { + if (n < min || n > max || n !== mathfloor(n)) { + throw Error + (bignumberError + (name || 'Argument') + (typeof n == 'number' + ? n < min || n > max ? ' out of range: ' : ' not an integer: ' + : ' not a primitive number: ') + String(n)); + } + } + + + // Assumes finite n. + function isOdd(n) { + var k = n.c.length - 1; + return bitFloor(n.e / LOG_BASE) == k && n.c[k] % 2 != 0; + } + + + function toExponential(str, e) { + return (str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str) + + (e < 0 ? 'e' : 'e+') + e; + } + + + function toFixedPoint(str, e, z) { + var len, zs; + + // Negative exponent? + if (e < 0) { + + // Prepend zeros. + for (zs = z + '.'; ++e; zs += z); + str = zs + str; + + // Positive exponent + } else { + len = str.length; + + // Append zeros. + if (++e > len) { + for (zs = z, e -= len; --e; zs += z); + str += zs; + } else if (e < len) { + str = str.slice(0, e) + '.' + str.slice(e); + } + } + + return str; + } + + + // EXPORT + + + BigNumber = clone(); + BigNumber['default'] = BigNumber.BigNumber = BigNumber; + + // AMD. + if (typeof define == 'function' && define.amd) { + define(function () { return BigNumber; }); + + // Node.js and other environments that support module.exports. + } else if ( true && module.exports) { + module.exports = BigNumber; + + // Browser. + } else { + if (!globalObject) { + globalObject = typeof self != 'undefined' && self ? self : window; + } + + globalObject.BigNumber = BigNumber; + } +})(this); + + +/***/ }), + +/***/ 39732: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/*jshint node:true */ + +var Buffer = (__nccwpck_require__(20181).Buffer); // browserify +var SlowBuffer = (__nccwpck_require__(20181).SlowBuffer); + +module.exports = bufferEq; + +function bufferEq(a, b) { + + // shortcutting on type is necessary for correctness + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + return false; + } + + // buffer sizes should be well-known information, so despite this + // shortcutting, it doesn't leak any information about the *contents* of the + // buffers. + if (a.length !== b.length) { + return false; + } + + var c = 0; + for (var i = 0; i < a.length; i++) { + /*jshint bitwise:false */ + c |= a[i] ^ b[i]; // XOR + } + return c === 0; +} + +bufferEq.install = function() { + Buffer.prototype.equal = SlowBuffer.prototype.equal = function equal(that) { + return bufferEq(this, that); + }; +}; + +var origBufEqual = Buffer.prototype.equal; +var origSlowBufEqual = SlowBuffer.prototype.equal; +bufferEq.restore = function() { + Buffer.prototype.equal = origBufEqual; + SlowBuffer.prototype.equal = origSlowBufEqual; +}; + + +/***/ }), + +/***/ 6110: +/***/ ((module, exports, __nccwpck_require__) => { + +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + let m; + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + // eslint-disable-next-line no-return-assign + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = __nccwpck_require__(40897)(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; + + +/***/ }), + +/***/ 40897: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = __nccwpck_require__(70744); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + + createDebug.names = []; + createDebug.skips = []; + + const split = (typeof namespaces === 'string' ? namespaces : '') + .trim() + .replace(/\s+/g, ',') + .split(',') + .filter(Boolean); + + for (const ns of split) { + if (ns[0] === '-') { + createDebug.skips.push(ns.slice(1)); + } else { + createDebug.names.push(ns); + } + } + } + + /** + * Checks if the given string matches a namespace template, honoring + * asterisks as wildcards. + * + * @param {String} search + * @param {String} template + * @return {Boolean} + */ + function matchesTemplate(search, template) { + let searchIndex = 0; + let templateIndex = 0; + let starIndex = -1; + let matchIndex = 0; + + while (searchIndex < search.length) { + if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) { + // Match character or proceed with wildcard + if (template[templateIndex] === '*') { + starIndex = templateIndex; + matchIndex = searchIndex; + templateIndex++; // Skip the '*' + } else { + searchIndex++; + templateIndex++; + } + } else if (starIndex !== -1) { // eslint-disable-line no-negated-condition + // Backtrack to the last '*' and try to match more characters + templateIndex = starIndex + 1; + matchIndex++; + searchIndex = matchIndex; + } else { + return false; // No match + } + } + + // Handle trailing '*' in template + while (templateIndex < template.length && template[templateIndex] === '*') { + templateIndex++; + } + + return templateIndex === template.length; + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names, + ...createDebug.skips.map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + for (const skip of createDebug.skips) { + if (matchesTemplate(name, skip)) { + return false; + } + } + + for (const ns of createDebug.names) { + if (matchesTemplate(name, ns)) { + return true; + } + } + + return false; + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; + + +/***/ }), + +/***/ 2830: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = __nccwpck_require__(6110); +} else { + module.exports = __nccwpck_require__(95108); +} + + +/***/ }), + +/***/ 95108: +/***/ ((module, exports, __nccwpck_require__) => { + +/** + * Module dependencies. + */ + +const tty = __nccwpck_require__(52018); +const util = __nccwpck_require__(39023); + +/** + * This is the Node.js implementation of `debug()`. + */ + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.destroy = util.deprecate( + () => {}, + 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' +); + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = __nccwpck_require__(60075); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; +} + +/** + * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr. + */ + +function log(...args) { + return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +module.exports = __nccwpck_require__(40897)(exports); + +const {formatters} = module.exports; + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); +}; + +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + + +/***/ }), + +/***/ 29112: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var stream = __nccwpck_require__(86131) +var eos = __nccwpck_require__(31424) +var inherits = __nccwpck_require__(39598) +var shift = __nccwpck_require__(34633) + +var SIGNAL_FLUSH = (Buffer.from && Buffer.from !== Uint8Array.from) + ? Buffer.from([0]) + : new Buffer([0]) + +var onuncork = function(self, fn) { + if (self._corked) self.once('uncork', fn) + else fn() +} + +var autoDestroy = function (self, err) { + if (self._autoDestroy) self.destroy(err) +} + +var destroyer = function(self, end) { + return function(err) { + if (err) autoDestroy(self, err.message === 'premature close' ? null : err) + else if (end && !self._ended) self.end() + } +} + +var end = function(ws, fn) { + if (!ws) return fn() + if (ws._writableState && ws._writableState.finished) return fn() + if (ws._writableState) return ws.end(fn) + ws.end() + fn() +} + +var noop = function() {} + +var toStreams2 = function(rs) { + return new (stream.Readable)({objectMode:true, highWaterMark:16}).wrap(rs) +} + +var Duplexify = function(writable, readable, opts) { + if (!(this instanceof Duplexify)) return new Duplexify(writable, readable, opts) + stream.Duplex.call(this, opts) + + this._writable = null + this._readable = null + this._readable2 = null + + this._autoDestroy = !opts || opts.autoDestroy !== false + this._forwardDestroy = !opts || opts.destroy !== false + this._forwardEnd = !opts || opts.end !== false + this._corked = 1 // start corked + this._ondrain = null + this._drained = false + this._forwarding = false + this._unwrite = null + this._unread = null + this._ended = false + + this.destroyed = false + + if (writable) this.setWritable(writable) + if (readable) this.setReadable(readable) +} + +inherits(Duplexify, stream.Duplex) + +Duplexify.obj = function(writable, readable, opts) { + if (!opts) opts = {} + opts.objectMode = true + opts.highWaterMark = 16 + return new Duplexify(writable, readable, opts) +} + +Duplexify.prototype.cork = function() { + if (++this._corked === 1) this.emit('cork') +} + +Duplexify.prototype.uncork = function() { + if (this._corked && --this._corked === 0) this.emit('uncork') +} + +Duplexify.prototype.setWritable = function(writable) { + if (this._unwrite) this._unwrite() + + if (this.destroyed) { + if (writable && writable.destroy) writable.destroy() + return + } + + if (writable === null || writable === false) { + this.end() + return + } + + var self = this + var unend = eos(writable, {writable:true, readable:false}, destroyer(this, this._forwardEnd)) + + var ondrain = function() { + var ondrain = self._ondrain + self._ondrain = null + if (ondrain) ondrain() + } + + var clear = function() { + self._writable.removeListener('drain', ondrain) + unend() + } + + if (this._unwrite) process.nextTick(ondrain) // force a drain on stream reset to avoid livelocks + + this._writable = writable + this._writable.on('drain', ondrain) + this._unwrite = clear + + this.uncork() // always uncork setWritable +} + +Duplexify.prototype.setReadable = function(readable) { + if (this._unread) this._unread() + + if (this.destroyed) { + if (readable && readable.destroy) readable.destroy() + return + } + + if (readable === null || readable === false) { + this.push(null) + this.resume() + return + } + + var self = this + var unend = eos(readable, {writable:false, readable:true}, destroyer(this)) + + var onreadable = function() { + self._forward() + } + + var onend = function() { + self.push(null) + } + + var clear = function() { + self._readable2.removeListener('readable', onreadable) + self._readable2.removeListener('end', onend) + unend() + } + + this._drained = true + this._readable = readable + this._readable2 = readable._readableState ? readable : toStreams2(readable) + this._readable2.on('readable', onreadable) + this._readable2.on('end', onend) + this._unread = clear + + this._forward() +} + +Duplexify.prototype._read = function() { + this._drained = true + this._forward() +} + +Duplexify.prototype._forward = function() { + if (this._forwarding || !this._readable2 || !this._drained) return + this._forwarding = true + + var data + + while (this._drained && (data = shift(this._readable2)) !== null) { + if (this.destroyed) continue + this._drained = this.push(data) + } + + this._forwarding = false +} + +Duplexify.prototype.destroy = function(err, cb) { + if (!cb) cb = noop + if (this.destroyed) return cb(null) + this.destroyed = true + + var self = this + process.nextTick(function() { + self._destroy(err) + cb(null) + }) +} + +Duplexify.prototype._destroy = function(err) { + if (err) { + var ondrain = this._ondrain + this._ondrain = null + if (ondrain) ondrain(err) + else this.emit('error', err) + } + + if (this._forwardDestroy) { + if (this._readable && this._readable.destroy) this._readable.destroy() + if (this._writable && this._writable.destroy) this._writable.destroy() + } + + this.emit('close') +} + +Duplexify.prototype._write = function(data, enc, cb) { + if (this.destroyed) return + if (this._corked) return onuncork(this, this._write.bind(this, data, enc, cb)) + if (data === SIGNAL_FLUSH) return this._finish(cb) + if (!this._writable) return cb() + + if (this._writable.write(data) === false) this._ondrain = cb + else if (!this.destroyed) cb() +} + +Duplexify.prototype._finish = function(cb) { + var self = this + this.emit('preend') + onuncork(this, function() { + end(self._forwardEnd && self._writable, function() { + // haxx to not emit prefinish twice + if (self._writableState.prefinished === false) self._writableState.prefinished = true + self.emit('prefinish') + onuncork(self, cb) + }) + }) +} + +Duplexify.prototype.end = function(data, enc, cb) { + if (typeof data === 'function') return this.end(null, null, data) + if (typeof enc === 'function') return this.end(data, null, enc) + this._ended = true + if (data) this.write(data) + if (!this._writableState.ending && !this._writableState.destroyed) this.write(SIGNAL_FLUSH) + return stream.Writable.prototype.end.call(this, cb) +} + +module.exports = Duplexify + + +/***/ }), + +/***/ 325: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var Buffer = (__nccwpck_require__(93058).Buffer); + +var getParamBytesForAlg = __nccwpck_require__(5028); + +var MAX_OCTET = 0x80, + CLASS_UNIVERSAL = 0, + PRIMITIVE_BIT = 0x20, + TAG_SEQ = 0x10, + TAG_INT = 0x02, + ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6), + ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6); + +function base64Url(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function signatureAsBuffer(signature) { + if (Buffer.isBuffer(signature)) { + return signature; + } else if ('string' === typeof signature) { + return Buffer.from(signature, 'base64'); + } + + throw new TypeError('ECDSA signature must be a Base64 string or a Buffer'); +} + +function derToJose(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + // the DER encoded param should at most be the param size, plus a padding + // zero, since due to being a signed integer + var maxEncodedParamLength = paramBytes + 1; + + var inputLength = signature.length; + + var offset = 0; + if (signature[offset++] !== ENCODED_TAG_SEQ) { + throw new Error('Could not find expected "seq"'); + } + + var seqLength = signature[offset++]; + if (seqLength === (MAX_OCTET | 1)) { + seqLength = signature[offset++]; + } + + if (inputLength - offset < seqLength) { + throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining'); + } + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "r"'); + } + + var rLength = signature[offset++]; + + if (inputLength - offset - 2 < rLength) { + throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available'); + } + + if (maxEncodedParamLength < rLength) { + throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var rOffset = offset; + offset += rLength; + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "s"'); + } + + var sLength = signature[offset++]; + + if (inputLength - offset !== sLength) { + throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"'); + } + + if (maxEncodedParamLength < sLength) { + throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var sOffset = offset; + offset += sLength; + + if (offset !== inputLength) { + throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain'); + } + + var rPadding = paramBytes - rLength, + sPadding = paramBytes - sLength; + + var dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength); + + for (offset = 0; offset < rPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength); + + offset = paramBytes; + + for (var o = offset; offset < o + sPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength); + + dst = dst.toString('base64'); + dst = base64Url(dst); + + return dst; +} + +function countPadding(buf, start, stop) { + var padding = 0; + while (start + padding < stop && buf[start + padding] === 0) { + ++padding; + } + + var needsSign = buf[start + padding] >= MAX_OCTET; + if (needsSign) { + --padding; + } + + return padding; +} + +function joseToDer(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + var signatureBytes = signature.length; + if (signatureBytes !== paramBytes * 2) { + throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"'); + } + + var rPadding = countPadding(signature, 0, paramBytes); + var sPadding = countPadding(signature, paramBytes, signature.length); + var rLength = paramBytes - rPadding; + var sLength = paramBytes - sPadding; + + var rsBytes = 1 + 1 + rLength + 1 + 1 + sLength; + + var shortLength = rsBytes < MAX_OCTET; + + var dst = Buffer.allocUnsafe((shortLength ? 2 : 3) + rsBytes); + + var offset = 0; + dst[offset++] = ENCODED_TAG_SEQ; + if (shortLength) { + // Bit 8 has value "0" + // bits 7-1 give the length. + dst[offset++] = rsBytes; + } else { + // Bit 8 of first octet has value "1" + // bits 7-1 give the number of additional length octets. + dst[offset++] = MAX_OCTET | 1; + // length, base 256 + dst[offset++] = rsBytes & 0xff; + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = rLength; + if (rPadding < 0) { + dst[offset++] = 0; + offset += signature.copy(dst, offset, 0, paramBytes); + } else { + offset += signature.copy(dst, offset, rPadding, paramBytes); + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = sLength; + if (sPadding < 0) { + dst[offset++] = 0; + signature.copy(dst, offset, paramBytes); + } else { + signature.copy(dst, offset, paramBytes + sPadding); + } + + return dst; +} + +module.exports = { + derToJose: derToJose, + joseToDer: joseToDer +}; + + +/***/ }), + +/***/ 5028: +/***/ ((module) => { + +"use strict"; + + +function getParamSize(keySize) { + var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1); + return result; +} + +var paramBytesForAlg = { + ES256: getParamSize(256), + ES384: getParamSize(384), + ES512: getParamSize(521) +}; + +function getParamBytesForAlg(alg) { + var paramBytes = paramBytesForAlg[alg]; + if (paramBytes) { + return paramBytes; + } + + throw new Error('Unknown algorithm "' + alg + '"'); +} + +module.exports = getParamBytesForAlg; + + +/***/ }), + +/***/ 31424: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var once = __nccwpck_require__(55560); + +var noop = function() {}; + +var qnt = global.Bare ? queueMicrotask : process.nextTick.bind(process); + +var isRequest = function(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +}; + +var isChildProcess = function(stream) { + return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 +}; + +var eos = function(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + + callback = once(callback || noop); + + var ws = stream._writableState; + var rs = stream._readableState; + var readable = opts.readable || (opts.readable !== false && stream.readable); + var writable = opts.writable || (opts.writable !== false && stream.writable); + var cancelled = false; + + var onlegacyfinish = function() { + if (!stream.writable) onfinish(); + }; + + var onfinish = function() { + writable = false; + if (!readable) callback.call(stream); + }; + + var onend = function() { + readable = false; + if (!writable) callback.call(stream); + }; + + var onexit = function(exitCode) { + callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); + }; + + var onerror = function(err) { + callback.call(stream, err); + }; + + var onclose = function() { + qnt(onclosenexttick); + }; + + var onclosenexttick = function() { + if (cancelled) return; + if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close')); + }; + + var onrequest = function() { + stream.req.on('finish', onfinish); + }; + + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest(); + else stream.on('request', onrequest); + } else if (writable && !ws) { // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + + if (isChildProcess(stream)) stream.on('exit', onexit); + + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + + return function() { + cancelled = true; + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('exit', onexit); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +}; + +module.exports = eos; + + +/***/ }), + +/***/ 16577: +/***/ ((module, exports) => { + +"use strict"; +/** + * @author Toru Nagashima + * @copyright 2015 Toru Nagashima. All rights reserved. + * See LICENSE file in root directory for full license. + */ + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +/** + * @typedef {object} PrivateData + * @property {EventTarget} eventTarget The event target. + * @property {{type:string}} event The original event object. + * @property {number} eventPhase The current event phase. + * @property {EventTarget|null} currentTarget The current event target. + * @property {boolean} canceled The flag to prevent default. + * @property {boolean} stopped The flag to stop propagation. + * @property {boolean} immediateStopped The flag to stop propagation immediately. + * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null. + * @property {number} timeStamp The unix time. + * @private + */ + +/** + * Private data for event wrappers. + * @type {WeakMap} + * @private + */ +const privateData = new WeakMap(); + +/** + * Cache for wrapper classes. + * @type {WeakMap} + * @private + */ +const wrappers = new WeakMap(); + +/** + * Get private data. + * @param {Event} event The event object to get private data. + * @returns {PrivateData} The private data of the event. + * @private + */ +function pd(event) { + const retv = privateData.get(event); + console.assert( + retv != null, + "'this' is expected an Event object, but got", + event + ); + return retv +} + +/** + * https://dom.spec.whatwg.org/#set-the-canceled-flag + * @param data {PrivateData} private data. + */ +function setCancelFlag(data) { + if (data.passiveListener != null) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error( + "Unable to preventDefault inside passive event listener invocation.", + data.passiveListener + ); + } + return + } + if (!data.event.cancelable) { + return + } + + data.canceled = true; + if (typeof data.event.preventDefault === "function") { + data.event.preventDefault(); + } +} + +/** + * @see https://dom.spec.whatwg.org/#interface-event + * @private + */ +/** + * The event wrapper. + * @constructor + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Event|{type:string}} event The original event to wrap. + */ +function Event(eventTarget, event) { + privateData.set(this, { + eventTarget, + event, + eventPhase: 2, + currentTarget: eventTarget, + canceled: false, + stopped: false, + immediateStopped: false, + passiveListener: null, + timeStamp: event.timeStamp || Date.now(), + }); + + // https://heycam.github.io/webidl/#Unforgeable + Object.defineProperty(this, "isTrusted", { value: false, enumerable: true }); + + // Define accessors + const keys = Object.keys(event); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in this)) { + Object.defineProperty(this, key, defineRedirectDescriptor(key)); + } + } +} + +// Should be enumerable, but class methods are not enumerable. +Event.prototype = { + /** + * The type of this event. + * @type {string} + */ + get type() { + return pd(this).event.type + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get target() { + return pd(this).eventTarget + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get currentTarget() { + return pd(this).currentTarget + }, + + /** + * @returns {EventTarget[]} The composed path of this event. + */ + composedPath() { + const currentTarget = pd(this).currentTarget; + if (currentTarget == null) { + return [] + } + return [currentTarget] + }, + + /** + * Constant of NONE. + * @type {number} + */ + get NONE() { + return 0 + }, + + /** + * Constant of CAPTURING_PHASE. + * @type {number} + */ + get CAPTURING_PHASE() { + return 1 + }, + + /** + * Constant of AT_TARGET. + * @type {number} + */ + get AT_TARGET() { + return 2 + }, + + /** + * Constant of BUBBLING_PHASE. + * @type {number} + */ + get BUBBLING_PHASE() { + return 3 + }, + + /** + * The target of this event. + * @type {number} + */ + get eventPhase() { + return pd(this).eventPhase + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopPropagation() { + const data = pd(this); + + data.stopped = true; + if (typeof data.event.stopPropagation === "function") { + data.event.stopPropagation(); + } + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopImmediatePropagation() { + const data = pd(this); + + data.stopped = true; + data.immediateStopped = true; + if (typeof data.event.stopImmediatePropagation === "function") { + data.event.stopImmediatePropagation(); + } + }, + + /** + * The flag to be bubbling. + * @type {boolean} + */ + get bubbles() { + return Boolean(pd(this).event.bubbles) + }, + + /** + * The flag to be cancelable. + * @type {boolean} + */ + get cancelable() { + return Boolean(pd(this).event.cancelable) + }, + + /** + * Cancel this event. + * @returns {void} + */ + preventDefault() { + setCancelFlag(pd(this)); + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + */ + get defaultPrevented() { + return pd(this).canceled + }, + + /** + * The flag to be composed. + * @type {boolean} + */ + get composed() { + return Boolean(pd(this).event.composed) + }, + + /** + * The unix time of this event. + * @type {number} + */ + get timeStamp() { + return pd(this).timeStamp + }, + + /** + * The target of this event. + * @type {EventTarget} + * @deprecated + */ + get srcElement() { + return pd(this).eventTarget + }, + + /** + * The flag to stop event bubbling. + * @type {boolean} + * @deprecated + */ + get cancelBubble() { + return pd(this).stopped + }, + set cancelBubble(value) { + if (!value) { + return + } + const data = pd(this); + + data.stopped = true; + if (typeof data.event.cancelBubble === "boolean") { + data.event.cancelBubble = true; + } + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + * @deprecated + */ + get returnValue() { + return !pd(this).canceled + }, + set returnValue(value) { + if (!value) { + setCancelFlag(pd(this)); + } + }, + + /** + * Initialize this event object. But do nothing under event dispatching. + * @param {string} type The event type. + * @param {boolean} [bubbles=false] The flag to be possible to bubble up. + * @param {boolean} [cancelable=false] The flag to be possible to cancel. + * @deprecated + */ + initEvent() { + // Do nothing. + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(Event.prototype, "constructor", { + value: Event, + configurable: true, + writable: true, +}); + +// Ensure `event instanceof window.Event` is `true`. +if (typeof window !== "undefined" && typeof window.Event !== "undefined") { + Object.setPrototypeOf(Event.prototype, window.Event.prototype); + + // Make association for wrappers. + wrappers.set(window.Event.prototype, Event); +} + +/** + * Get the property descriptor to redirect a given property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to redirect the property. + * @private + */ +function defineRedirectDescriptor(key) { + return { + get() { + return pd(this).event[key] + }, + set(value) { + pd(this).event[key] = value; + }, + configurable: true, + enumerable: true, + } +} + +/** + * Get the property descriptor to call a given method property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to call the method property. + * @private + */ +function defineCallDescriptor(key) { + return { + value() { + const event = pd(this).event; + return event[key].apply(event, arguments) + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define new wrapper class. + * @param {Function} BaseEvent The base wrapper class. + * @param {Object} proto The prototype of the original event. + * @returns {Function} The defined wrapper class. + * @private + */ +function defineWrapper(BaseEvent, proto) { + const keys = Object.keys(proto); + if (keys.length === 0) { + return BaseEvent + } + + /** CustomEvent */ + function CustomEvent(eventTarget, event) { + BaseEvent.call(this, eventTarget, event); + } + + CustomEvent.prototype = Object.create(BaseEvent.prototype, { + constructor: { value: CustomEvent, configurable: true, writable: true }, + }); + + // Define accessors. + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in BaseEvent.prototype)) { + const descriptor = Object.getOwnPropertyDescriptor(proto, key); + const isFunc = typeof descriptor.value === "function"; + Object.defineProperty( + CustomEvent.prototype, + key, + isFunc + ? defineCallDescriptor(key) + : defineRedirectDescriptor(key) + ); + } + } + + return CustomEvent +} + +/** + * Get the wrapper class of a given prototype. + * @param {Object} proto The prototype of the original event to get its wrapper. + * @returns {Function} The wrapper class. + * @private + */ +function getWrapper(proto) { + if (proto == null || proto === Object.prototype) { + return Event + } + + let wrapper = wrappers.get(proto); + if (wrapper == null) { + wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto); + wrappers.set(proto, wrapper); + } + return wrapper +} + +/** + * Wrap a given event to management a dispatching. + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Object} event The event to wrap. + * @returns {Event} The wrapper instance. + * @private + */ +function wrapEvent(eventTarget, event) { + const Wrapper = getWrapper(Object.getPrototypeOf(event)); + return new Wrapper(eventTarget, event) +} + +/** + * Get the immediateStopped flag of a given event. + * @param {Event} event The event to get. + * @returns {boolean} The flag to stop propagation immediately. + * @private + */ +function isStopped(event) { + return pd(event).immediateStopped +} + +/** + * Set the current event phase of a given event. + * @param {Event} event The event to set current target. + * @param {number} eventPhase New event phase. + * @returns {void} + * @private + */ +function setEventPhase(event, eventPhase) { + pd(event).eventPhase = eventPhase; +} + +/** + * Set the current target of a given event. + * @param {Event} event The event to set current target. + * @param {EventTarget|null} currentTarget New current target. + * @returns {void} + * @private + */ +function setCurrentTarget(event, currentTarget) { + pd(event).currentTarget = currentTarget; +} + +/** + * Set a passive listener of a given event. + * @param {Event} event The event to set current target. + * @param {Function|null} passiveListener New passive listener. + * @returns {void} + * @private + */ +function setPassiveListener(event, passiveListener) { + pd(event).passiveListener = passiveListener; +} + +/** + * @typedef {object} ListenerNode + * @property {Function} listener + * @property {1|2|3} listenerType + * @property {boolean} passive + * @property {boolean} once + * @property {ListenerNode|null} next + * @private + */ + +/** + * @type {WeakMap>} + * @private + */ +const listenersMap = new WeakMap(); + +// Listener types +const CAPTURE = 1; +const BUBBLE = 2; +const ATTRIBUTE = 3; + +/** + * Check whether a given value is an object or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if the value is an object. + */ +function isObject(x) { + return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax +} + +/** + * Get listeners. + * @param {EventTarget} eventTarget The event target to get. + * @returns {Map} The listeners. + * @private + */ +function getListeners(eventTarget) { + const listeners = listenersMap.get(eventTarget); + if (listeners == null) { + throw new TypeError( + "'this' is expected an EventTarget object, but got another value." + ) + } + return listeners +} + +/** + * Get the property descriptor for the event attribute of a given event. + * @param {string} eventName The event name to get property descriptor. + * @returns {PropertyDescriptor} The property descriptor. + * @private + */ +function defineEventAttributeDescriptor(eventName) { + return { + get() { + const listeners = getListeners(this); + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + return node.listener + } + node = node.next; + } + return null + }, + + set(listener) { + if (typeof listener !== "function" && !isObject(listener)) { + listener = null; // eslint-disable-line no-param-reassign + } + const listeners = getListeners(this); + + // Traverse to the tail while removing old value. + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + // Remove old value. + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + node = node.next; + } + + // Add new value. + if (listener !== null) { + const newNode = { + listener, + listenerType: ATTRIBUTE, + passive: false, + once: false, + next: null, + }; + if (prev === null) { + listeners.set(eventName, newNode); + } else { + prev.next = newNode; + } + } + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define an event attribute (e.g. `eventTarget.onclick`). + * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite. + * @param {string} eventName The event name to define. + * @returns {void} + */ +function defineEventAttribute(eventTargetPrototype, eventName) { + Object.defineProperty( + eventTargetPrototype, + `on${eventName}`, + defineEventAttributeDescriptor(eventName) + ); +} + +/** + * Define a custom EventTarget with event attributes. + * @param {string[]} eventNames Event names for event attributes. + * @returns {EventTarget} The custom EventTarget. + * @private + */ +function defineCustomEventTarget(eventNames) { + /** CustomEventTarget */ + function CustomEventTarget() { + EventTarget.call(this); + } + + CustomEventTarget.prototype = Object.create(EventTarget.prototype, { + constructor: { + value: CustomEventTarget, + configurable: true, + writable: true, + }, + }); + + for (let i = 0; i < eventNames.length; ++i) { + defineEventAttribute(CustomEventTarget.prototype, eventNames[i]); + } + + return CustomEventTarget +} + +/** + * EventTarget. + * + * - This is constructor if no arguments. + * - This is a function which returns a CustomEventTarget constructor if there are arguments. + * + * For example: + * + * class A extends EventTarget {} + * class B extends EventTarget("message") {} + * class C extends EventTarget("message", "error") {} + * class D extends EventTarget(["message", "error"]) {} + */ +function EventTarget() { + /*eslint-disable consistent-return */ + if (this instanceof EventTarget) { + listenersMap.set(this, new Map()); + return + } + if (arguments.length === 1 && Array.isArray(arguments[0])) { + return defineCustomEventTarget(arguments[0]) + } + if (arguments.length > 0) { + const types = new Array(arguments.length); + for (let i = 0; i < arguments.length; ++i) { + types[i] = arguments[i]; + } + return defineCustomEventTarget(types) + } + throw new TypeError("Cannot call a class as a function") + /*eslint-enable consistent-return */ +} + +// Should be enumerable, but class methods are not enumerable. +EventTarget.prototype = { + /** + * Add a given listener to this event target. + * @param {string} eventName The event name to add. + * @param {Function} listener The listener to add. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + addEventListener(eventName, listener, options) { + if (listener == null) { + return + } + if (typeof listener !== "function" && !isObject(listener)) { + throw new TypeError("'listener' should be a function or an object.") + } + + const listeners = getListeners(this); + const optionsIsObj = isObject(options); + const capture = optionsIsObj + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + const newNode = { + listener, + listenerType, + passive: optionsIsObj && Boolean(options.passive), + once: optionsIsObj && Boolean(options.once), + next: null, + }; + + // Set it as the first node if the first node is null. + let node = listeners.get(eventName); + if (node === undefined) { + listeners.set(eventName, newNode); + return + } + + // Traverse to the tail while checking duplication.. + let prev = null; + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + // Should ignore duplication. + return + } + prev = node; + node = node.next; + } + + // Add it. + prev.next = newNode; + }, + + /** + * Remove a given listener from this event target. + * @param {string} eventName The event name to remove. + * @param {Function} listener The listener to remove. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + removeEventListener(eventName, listener, options) { + if (listener == null) { + return + } + + const listeners = getListeners(this); + const capture = isObject(options) + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + return + } + + prev = node; + node = node.next; + } + }, + + /** + * Dispatch a given event. + * @param {Event|{type:string}} event The event to dispatch. + * @returns {boolean} `false` if canceled. + */ + dispatchEvent(event) { + if (event == null || typeof event.type !== "string") { + throw new TypeError('"event.type" should be a string.') + } + + // If listeners aren't registered, terminate. + const listeners = getListeners(this); + const eventName = event.type; + let node = listeners.get(eventName); + if (node == null) { + return true + } + + // Since we cannot rewrite several properties, so wrap object. + const wrappedEvent = wrapEvent(this, event); + + // This doesn't process capturing phase and bubbling phase. + // This isn't participating in a tree. + let prev = null; + while (node != null) { + // Remove this listener if it's once + if (node.once) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + // Call this listener + setPassiveListener( + wrappedEvent, + node.passive ? node.listener : null + ); + if (typeof node.listener === "function") { + try { + node.listener.call(this, wrappedEvent); + } catch (err) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error(err); + } + } + } else if ( + node.listenerType !== ATTRIBUTE && + typeof node.listener.handleEvent === "function" + ) { + node.listener.handleEvent(wrappedEvent); + } + + // Break if `event.stopImmediatePropagation` was called. + if (isStopped(wrappedEvent)) { + break + } + + node = node.next; + } + setPassiveListener(wrappedEvent, null); + setEventPhase(wrappedEvent, 0); + setCurrentTarget(wrappedEvent, null); + + return !wrappedEvent.defaultPrevented + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(EventTarget.prototype, "constructor", { + value: EventTarget, + configurable: true, + writable: true, +}); + +// Ensure `eventTarget instanceof window.EventTarget` is `true`. +if ( + typeof window !== "undefined" && + typeof window.EventTarget !== "undefined" +) { + Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype); +} + +exports.defineEventAttribute = defineEventAttribute; +exports.EventTarget = EventTarget; +exports["default"] = EventTarget; + +module.exports = EventTarget +module.exports.EventTarget = module.exports["default"] = EventTarget +module.exports.defineEventAttribute = defineEventAttribute +//# sourceMappingURL=event-target-shim.js.map + + +/***/ }), + +/***/ 23860: +/***/ ((module) => { + +"use strict"; + + +var hasOwn = Object.prototype.hasOwnProperty; +var toStr = Object.prototype.toString; +var defineProperty = Object.defineProperty; +var gOPD = Object.getOwnPropertyDescriptor; + +var isArray = function isArray(arr) { + if (typeof Array.isArray === 'function') { + return Array.isArray(arr); + } + + return toStr.call(arr) === '[object Array]'; +}; + +var isPlainObject = function isPlainObject(obj) { + if (!obj || toStr.call(obj) !== '[object Object]') { + return false; + } + + var hasOwnConstructor = hasOwn.call(obj, 'constructor'); + var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); + // Not own constructor property must be Object + if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) { /**/ } + + return typeof key === 'undefined' || hasOwn.call(obj, key); +}; + +// If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target +var setProperty = function setProperty(target, options) { + if (defineProperty && options.name === '__proto__') { + defineProperty(target, options.name, { + enumerable: true, + configurable: true, + value: options.newValue, + writable: true + }); + } else { + target[options.name] = options.newValue; + } +}; + +// Return undefined instead of __proto__ if '__proto__' is not an own property +var getProperty = function getProperty(obj, name) { + if (name === '__proto__') { + if (!hasOwn.call(obj, name)) { + return void 0; + } else if (gOPD) { + // In early versions of node, obj['__proto__'] is buggy when obj has + // __proto__ as an own property. Object.getOwnPropertyDescriptor() works. + return gOPD(obj, name).value; + } + } + + return obj[name]; +}; + +module.exports = function extend() { + var options, name, src, copy, copyIsArray, clone; + var target = arguments[0]; + var i = 1; + var length = arguments.length; + var deep = false; + + // Handle a deep copy situation + if (typeof target === 'boolean') { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + if (target == null || (typeof target !== 'object' && typeof target !== 'function')) { + target = {}; + } + + for (; i < length; ++i) { + options = arguments[i]; + // Only deal with non-null/undefined values + if (options != null) { + // Extend the base object + for (name in options) { + src = getProperty(target, name); + copy = getProperty(options, name); + + // Prevent never-ending loop + if (target !== copy) { + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + setProperty(target, { name: name, newValue: extend(deep, clone, copy) }); + + // Don't bring in undefined values + } else if (typeof copy !== 'undefined') { + setProperty(target, { name: name, newValue: copy }); + } + } + } + } + } + + // Return the modified object + return target; +}; + + +/***/ }), + +/***/ 47506: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GaxiosError = exports.GAXIOS_ERROR_SYMBOL = void 0; +exports.defaultErrorRedactor = defaultErrorRedactor; +const url_1 = __nccwpck_require__(87016); +const util_1 = __nccwpck_require__(63155); +const extend_1 = __importDefault(__nccwpck_require__(23860)); +/** + * Support `instanceof` operator for `GaxiosError`s in different versions of this library. + * + * @see {@link GaxiosError[Symbol.hasInstance]} + */ +exports.GAXIOS_ERROR_SYMBOL = Symbol.for(`${util_1.pkg.name}-gaxios-error`); +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ +class GaxiosError extends Error { + /** + * Support `instanceof` operator for `GaxiosError` across builds/duplicated files. + * + * @see {@link GAXIOS_ERROR_SYMBOL} + * @see {@link GaxiosError[GAXIOS_ERROR_SYMBOL]} + */ + static [(_a = exports.GAXIOS_ERROR_SYMBOL, Symbol.hasInstance)](instance) { + if (instance && + typeof instance === 'object' && + exports.GAXIOS_ERROR_SYMBOL in instance && + instance[exports.GAXIOS_ERROR_SYMBOL] === util_1.pkg.version) { + return true; + } + // fallback to native + return Function.prototype[Symbol.hasInstance].call(GaxiosError, instance); + } + constructor(message, config, response, error) { + var _b; + super(message); + this.config = config; + this.response = response; + this.error = error; + /** + * Support `instanceof` operator for `GaxiosError` across builds/duplicated files. + * + * @see {@link GAXIOS_ERROR_SYMBOL} + * @see {@link GaxiosError[Symbol.hasInstance]} + * @see {@link https://github.com/microsoft/TypeScript/issues/13965#issuecomment-278570200} + * @see {@link https://stackoverflow.com/questions/46618852/require-and-instanceof} + * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/@@hasInstance#reverting_to_default_instanceof_behavior} + */ + this[_a] = util_1.pkg.version; + // deep-copy config as we do not want to mutate + // the existing config for future retries/use + this.config = (0, extend_1.default)(true, {}, config); + if (this.response) { + this.response.config = (0, extend_1.default)(true, {}, this.response.config); + } + if (this.response) { + try { + this.response.data = translateData(this.config.responseType, (_b = this.response) === null || _b === void 0 ? void 0 : _b.data); + } + catch (_c) { + // best effort - don't throw an error within an error + // we could set `this.response.config.responseType = 'unknown'`, but + // that would mutate future calls with this config object. + } + this.status = this.response.status; + } + if (error && 'code' in error && error.code) { + this.code = error.code; + } + if (config.errorRedactor) { + config.errorRedactor({ + config: this.config, + response: this.response, + }); + } + } +} +exports.GaxiosError = GaxiosError; +function translateData(responseType, data) { + switch (responseType) { + case 'stream': + return data; + case 'json': + return JSON.parse(JSON.stringify(data)); + case 'arraybuffer': + return JSON.parse(Buffer.from(data).toString('utf8')); + case 'blob': + return JSON.parse(data.text()); + default: + return data; + } +} +/** + * An experimental error redactor. + * + * @param config Config to potentially redact properties of + * @param response Config to potentially redact properties of + * + * @experimental + */ +function defaultErrorRedactor(data) { + const REDACT = '< - See `errorRedactor` option in `gaxios` for configuration>.'; + function redactHeaders(headers) { + if (!headers) + return; + for (const key of Object.keys(headers)) { + // any casing of `Authentication` + if (/^authentication$/i.test(key)) { + headers[key] = REDACT; + } + // any casing of `Authorization` + if (/^authorization$/i.test(key)) { + headers[key] = REDACT; + } + // anything containing secret, such as 'client secret' + if (/secret/i.test(key)) { + headers[key] = REDACT; + } + } + } + function redactString(obj, key) { + if (typeof obj === 'object' && + obj !== null && + typeof obj[key] === 'string') { + const text = obj[key]; + if (/grant_type=/i.test(text) || + /assertion=/i.test(text) || + /secret/i.test(text)) { + obj[key] = REDACT; + } + } + } + function redactObject(obj) { + if (typeof obj === 'object' && obj !== null) { + if ('grant_type' in obj) { + obj['grant_type'] = REDACT; + } + if ('assertion' in obj) { + obj['assertion'] = REDACT; + } + if ('client_secret' in obj) { + obj['client_secret'] = REDACT; + } + } + } + if (data.config) { + redactHeaders(data.config.headers); + redactString(data.config, 'data'); + redactObject(data.config.data); + redactString(data.config, 'body'); + redactObject(data.config.body); + try { + const url = new url_1.URL('', data.config.url); + if (url.searchParams.has('token')) { + url.searchParams.set('token', REDACT); + } + if (url.searchParams.has('client_secret')) { + url.searchParams.set('client_secret', REDACT); + } + data.config.url = url.toString(); + } + catch (_b) { + // ignore error - no need to parse an invalid URL + } + } + if (data.response) { + defaultErrorRedactor({ config: data.response.config }); + redactHeaders(data.response.headers); + redactString(data.response, 'data'); + redactObject(data.response.data); + } + return data; +} +//# sourceMappingURL=common.js.map + +/***/ }), + +/***/ 6010: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _Gaxios_instances, _a, _Gaxios_urlMayUseProxy, _Gaxios_applyRequestInterceptors, _Gaxios_applyResponseInterceptors, _Gaxios_prepareRequest, _Gaxios_proxyAgent, _Gaxios_getProxyAgent; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Gaxios = void 0; +const extend_1 = __importDefault(__nccwpck_require__(23860)); +const https_1 = __nccwpck_require__(65692); +const node_fetch_1 = __importDefault(__nccwpck_require__(26705)); +const querystring_1 = __importDefault(__nccwpck_require__(83480)); +const is_stream_1 = __importDefault(__nccwpck_require__(96543)); +const url_1 = __nccwpck_require__(87016); +const common_1 = __nccwpck_require__(47506); +const retry_1 = __nccwpck_require__(32789); +const stream_1 = __nccwpck_require__(2203); +const uuid_1 = __nccwpck_require__(12048); +const interceptor_1 = __nccwpck_require__(85608); +/* eslint-disable @typescript-eslint/no-explicit-any */ +const fetch = hasFetch() ? window.fetch : node_fetch_1.default; +function hasWindow() { + return typeof window !== 'undefined' && !!window; +} +function hasFetch() { + return hasWindow() && !!window.fetch; +} +function hasBuffer() { + return typeof Buffer !== 'undefined'; +} +function hasHeader(options, header) { + return !!getHeader(options, header); +} +function getHeader(options, header) { + header = header.toLowerCase(); + for (const key of Object.keys((options === null || options === void 0 ? void 0 : options.headers) || {})) { + if (header === key.toLowerCase()) { + return options.headers[key]; + } + } + return undefined; +} +class Gaxios { + /** + * The Gaxios class is responsible for making HTTP requests. + * @param defaults The default set of options to be used for this instance. + */ + constructor(defaults) { + _Gaxios_instances.add(this); + this.agentCache = new Map(); + this.defaults = defaults || {}; + this.interceptors = { + request: new interceptor_1.GaxiosInterceptorManager(), + response: new interceptor_1.GaxiosInterceptorManager(), + }; + } + /** + * Perform an HTTP request with the given options. + * @param opts Set of HTTP options that will be used for this HTTP request. + */ + async request(opts = {}) { + opts = await __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_prepareRequest).call(this, opts); + opts = await __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_applyRequestInterceptors).call(this, opts); + return __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_applyResponseInterceptors).call(this, this._request(opts)); + } + async _defaultAdapter(opts) { + const fetchImpl = opts.fetchImplementation || fetch; + const res = (await fetchImpl(opts.url, opts)); + const data = await this.getResponseData(opts, res); + return this.translateResponse(opts, res, data); + } + /** + * Internal, retryable version of the `request` method. + * @param opts Set of HTTP options that will be used for this HTTP request. + */ + async _request(opts = {}) { + var _b; + try { + let translatedResponse; + if (opts.adapter) { + translatedResponse = await opts.adapter(opts, this._defaultAdapter.bind(this)); + } + else { + translatedResponse = await this._defaultAdapter(opts); + } + if (!opts.validateStatus(translatedResponse.status)) { + if (opts.responseType === 'stream') { + let response = ''; + await new Promise(resolve => { + (translatedResponse === null || translatedResponse === void 0 ? void 0 : translatedResponse.data).on('data', chunk => { + response += chunk; + }); + (translatedResponse === null || translatedResponse === void 0 ? void 0 : translatedResponse.data).on('end', resolve); + }); + translatedResponse.data = response; + } + throw new common_1.GaxiosError(`Request failed with status code ${translatedResponse.status}`, opts, translatedResponse); + } + return translatedResponse; + } + catch (e) { + const err = e instanceof common_1.GaxiosError + ? e + : new common_1.GaxiosError(e.message, opts, undefined, e); + const { shouldRetry, config } = await (0, retry_1.getRetryConfig)(err); + if (shouldRetry && config) { + err.config.retryConfig.currentRetryAttempt = + config.retryConfig.currentRetryAttempt; + // The error's config could be redacted - therefore we only want to + // copy the retry state over to the existing config + opts.retryConfig = (_b = err.config) === null || _b === void 0 ? void 0 : _b.retryConfig; + return this._request(opts); + } + throw err; + } + } + async getResponseData(opts, res) { + switch (opts.responseType) { + case 'stream': + return res.body; + case 'json': { + let data = await res.text(); + try { + data = JSON.parse(data); + } + catch (_b) { + // continue + } + return data; + } + case 'arraybuffer': + return res.arrayBuffer(); + case 'blob': + return res.blob(); + case 'text': + return res.text(); + default: + return this.getResponseDataFromContentType(res); + } + } + /** + * By default, throw for any non-2xx status code + * @param status status code from the HTTP response + */ + validateStatus(status) { + return status >= 200 && status < 300; + } + /** + * Encode a set of key/value pars into a querystring format (?foo=bar&baz=boo) + * @param params key value pars to encode + */ + paramsSerializer(params) { + return querystring_1.default.stringify(params); + } + translateResponse(opts, res, data) { + // headers need to be converted from a map to an obj + const headers = {}; + res.headers.forEach((value, key) => { + headers[key] = value; + }); + return { + config: opts, + data: data, + headers, + status: res.status, + statusText: res.statusText, + // XMLHttpRequestLike + request: { + responseURL: res.url, + }, + }; + } + /** + * Attempts to parse a response by looking at the Content-Type header. + * @param {FetchResponse} response the HTTP response. + * @returns {Promise} a promise that resolves to the response data. + */ + async getResponseDataFromContentType(response) { + let contentType = response.headers.get('Content-Type'); + if (contentType === null) { + // Maintain existing functionality by calling text() + return response.text(); + } + contentType = contentType.toLowerCase(); + if (contentType.includes('application/json')) { + let data = await response.text(); + try { + data = JSON.parse(data); + } + catch (_b) { + // continue + } + return data; + } + else if (contentType.match(/^text\//)) { + return response.text(); + } + else { + // If the content type is something not easily handled, just return the raw data (blob) + return response.blob(); + } + } + /** + * Creates an async generator that yields the pieces of a multipart/related request body. + * This implementation follows the spec: https://www.ietf.org/rfc/rfc2387.txt. However, recursive + * multipart/related requests are not currently supported. + * + * @param {GaxioMultipartOptions[]} multipartOptions the pieces to turn into a multipart/related body. + * @param {string} boundary the boundary string to be placed between each part. + */ + async *getMultipartRequest(multipartOptions, boundary) { + const finale = `--${boundary}--`; + for (const currentPart of multipartOptions) { + const partContentType = currentPart.headers['Content-Type'] || 'application/octet-stream'; + const preamble = `--${boundary}\r\nContent-Type: ${partContentType}\r\n\r\n`; + yield preamble; + if (typeof currentPart.content === 'string') { + yield currentPart.content; + } + else { + yield* currentPart.content; + } + yield '\r\n'; + } + yield finale; + } +} +exports.Gaxios = Gaxios; +_a = Gaxios, _Gaxios_instances = new WeakSet(), _Gaxios_urlMayUseProxy = function _Gaxios_urlMayUseProxy(url, noProxy = []) { + var _b, _c; + const candidate = new url_1.URL(url); + const noProxyList = [...noProxy]; + const noProxyEnvList = ((_c = ((_b = process.env.NO_PROXY) !== null && _b !== void 0 ? _b : process.env.no_proxy)) === null || _c === void 0 ? void 0 : _c.split(',')) || []; + for (const rule of noProxyEnvList) { + noProxyList.push(rule.trim()); + } + for (const rule of noProxyList) { + // Match regex + if (rule instanceof RegExp) { + if (rule.test(candidate.toString())) { + return false; + } + } + // Match URL + else if (rule instanceof url_1.URL) { + if (rule.origin === candidate.origin) { + return false; + } + } + // Match string regex + else if (rule.startsWith('*.') || rule.startsWith('.')) { + const cleanedRule = rule.replace(/^\*\./, '.'); + if (candidate.hostname.endsWith(cleanedRule)) { + return false; + } + } + // Basic string match + else if (rule === candidate.origin || + rule === candidate.hostname || + rule === candidate.href) { + return false; + } + } + return true; +}, _Gaxios_applyRequestInterceptors = +/** + * Applies the request interceptors. The request interceptors are applied after the + * call to prepareRequest is completed. + * + * @param {GaxiosOptions} options The current set of options. + * + * @returns {Promise} Promise that resolves to the set of options or response after interceptors are applied. + */ +async function _Gaxios_applyRequestInterceptors(options) { + let promiseChain = Promise.resolve(options); + for (const interceptor of this.interceptors.request.values()) { + if (interceptor) { + promiseChain = promiseChain.then(interceptor.resolved, interceptor.rejected); + } + } + return promiseChain; +}, _Gaxios_applyResponseInterceptors = +/** + * Applies the response interceptors. The response interceptors are applied after the + * call to request is made. + * + * @param {GaxiosOptions} options The current set of options. + * + * @returns {Promise} Promise that resolves to the set of options or response after interceptors are applied. + */ +async function _Gaxios_applyResponseInterceptors(response) { + let promiseChain = Promise.resolve(response); + for (const interceptor of this.interceptors.response.values()) { + if (interceptor) { + promiseChain = promiseChain.then(interceptor.resolved, interceptor.rejected); + } + } + return promiseChain; +}, _Gaxios_prepareRequest = +/** + * Validates the options, merges them with defaults, and prepare request. + * + * @param options The original options passed from the client. + * @returns Prepared options, ready to make a request + */ +async function _Gaxios_prepareRequest(options) { + var _b, _c, _d, _e; + const opts = (0, extend_1.default)(true, {}, this.defaults, options); + if (!opts.url) { + throw new Error('URL is required.'); + } + // baseUrl has been deprecated, remove in 2.0 + const baseUrl = opts.baseUrl || opts.baseURL; + if (baseUrl) { + opts.url = baseUrl.toString() + opts.url; + } + opts.paramsSerializer = opts.paramsSerializer || this.paramsSerializer; + if (opts.params && Object.keys(opts.params).length > 0) { + let additionalQueryParams = opts.paramsSerializer(opts.params); + if (additionalQueryParams.startsWith('?')) { + additionalQueryParams = additionalQueryParams.slice(1); + } + const prefix = opts.url.toString().includes('?') ? '&' : '?'; + opts.url = opts.url + prefix + additionalQueryParams; + } + if (typeof options.maxContentLength === 'number') { + opts.size = options.maxContentLength; + } + if (typeof options.maxRedirects === 'number') { + opts.follow = options.maxRedirects; + } + opts.headers = opts.headers || {}; + if (opts.multipart === undefined && opts.data) { + const isFormData = typeof FormData === 'undefined' + ? false + : (opts === null || opts === void 0 ? void 0 : opts.data) instanceof FormData; + if (is_stream_1.default.readable(opts.data)) { + opts.body = opts.data; + } + else if (hasBuffer() && Buffer.isBuffer(opts.data)) { + // Do not attempt to JSON.stringify() a Buffer: + opts.body = opts.data; + if (!hasHeader(opts, 'Content-Type')) { + opts.headers['Content-Type'] = 'application/json'; + } + } + else if (typeof opts.data === 'object') { + // If www-form-urlencoded content type has been set, but data is + // provided as an object, serialize the content using querystring: + if (!isFormData) { + if (getHeader(opts, 'content-type') === + 'application/x-www-form-urlencoded') { + opts.body = opts.paramsSerializer(opts.data); + } + else { + // } else if (!(opts.data instanceof FormData)) { + if (!hasHeader(opts, 'Content-Type')) { + opts.headers['Content-Type'] = 'application/json'; + } + opts.body = JSON.stringify(opts.data); + } + } + } + else { + opts.body = opts.data; + } + } + else if (opts.multipart && opts.multipart.length > 0) { + // note: once the minimum version reaches Node 16, + // this can be replaced with randomUUID() function from crypto + // and the dependency on UUID removed + const boundary = (0, uuid_1.v4)(); + opts.headers['Content-Type'] = `multipart/related; boundary=${boundary}`; + const bodyStream = new stream_1.PassThrough(); + opts.body = bodyStream; + (0, stream_1.pipeline)(this.getMultipartRequest(opts.multipart, boundary), bodyStream, () => { }); + } + opts.validateStatus = opts.validateStatus || this.validateStatus; + opts.responseType = opts.responseType || 'unknown'; + if (!opts.headers['Accept'] && opts.responseType === 'json') { + opts.headers['Accept'] = 'application/json'; + } + opts.method = opts.method || 'GET'; + const proxy = opts.proxy || + ((_b = process === null || process === void 0 ? void 0 : process.env) === null || _b === void 0 ? void 0 : _b.HTTPS_PROXY) || + ((_c = process === null || process === void 0 ? void 0 : process.env) === null || _c === void 0 ? void 0 : _c.https_proxy) || + ((_d = process === null || process === void 0 ? void 0 : process.env) === null || _d === void 0 ? void 0 : _d.HTTP_PROXY) || + ((_e = process === null || process === void 0 ? void 0 : process.env) === null || _e === void 0 ? void 0 : _e.http_proxy); + const urlMayUseProxy = __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_urlMayUseProxy).call(this, opts.url, opts.noProxy); + if (opts.agent) { + // don't do any of the following options - use the user-provided agent. + } + else if (proxy && urlMayUseProxy) { + const HttpsProxyAgent = await __classPrivateFieldGet(_a, _a, "m", _Gaxios_getProxyAgent).call(_a); + if (this.agentCache.has(proxy)) { + opts.agent = this.agentCache.get(proxy); + } + else { + opts.agent = new HttpsProxyAgent(proxy, { + cert: opts.cert, + key: opts.key, + }); + this.agentCache.set(proxy, opts.agent); + } + } + else if (opts.cert && opts.key) { + // Configure client for mTLS + if (this.agentCache.has(opts.key)) { + opts.agent = this.agentCache.get(opts.key); + } + else { + opts.agent = new https_1.Agent({ + cert: opts.cert, + key: opts.key, + }); + this.agentCache.set(opts.key, opts.agent); + } + } + if (typeof opts.errorRedactor !== 'function' && + opts.errorRedactor !== false) { + opts.errorRedactor = common_1.defaultErrorRedactor; + } + return opts; +}, _Gaxios_getProxyAgent = async function _Gaxios_getProxyAgent() { + __classPrivateFieldSet(this, _a, __classPrivateFieldGet(this, _a, "f", _Gaxios_proxyAgent) || (await Promise.resolve().then(() => __importStar(__nccwpck_require__(3669)))).HttpsProxyAgent, "f", _Gaxios_proxyAgent); + return __classPrivateFieldGet(this, _a, "f", _Gaxios_proxyAgent); +}; +/** + * A cache for the lazily-loaded proxy agent. + * + * Should use {@link Gaxios[#getProxyAgent]} to retrieve. + */ +// using `import` to dynamically import the types here +_Gaxios_proxyAgent = { value: void 0 }; +//# sourceMappingURL=gaxios.js.map + +/***/ }), + +/***/ 97003: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.instance = exports.Gaxios = exports.GaxiosError = void 0; +exports.request = request; +const gaxios_1 = __nccwpck_require__(6010); +Object.defineProperty(exports, "Gaxios", ({ enumerable: true, get: function () { return gaxios_1.Gaxios; } })); +var common_1 = __nccwpck_require__(47506); +Object.defineProperty(exports, "GaxiosError", ({ enumerable: true, get: function () { return common_1.GaxiosError; } })); +__exportStar(__nccwpck_require__(85608), exports); +/** + * The default instance used when the `request` method is directly + * invoked. + */ +exports.instance = new gaxios_1.Gaxios(); +/** + * Make an HTTP request using the given options. + * @param opts Options for the request + */ +async function request(opts) { + return exports.instance.request(opts); +} +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 85608: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2024 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GaxiosInterceptorManager = void 0; +/** + * Class to manage collections of GaxiosInterceptors for both requests and responses. + */ +class GaxiosInterceptorManager extends Set { +} +exports.GaxiosInterceptorManager = GaxiosInterceptorManager; +//# sourceMappingURL=interceptor.js.map + +/***/ }), + +/***/ 32789: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRetryConfig = getRetryConfig; +async function getRetryConfig(err) { + let config = getConfig(err); + if (!err || !err.config || (!config && !err.config.retry)) { + return { shouldRetry: false }; + } + config = config || {}; + config.currentRetryAttempt = config.currentRetryAttempt || 0; + config.retry = + config.retry === undefined || config.retry === null ? 3 : config.retry; + config.httpMethodsToRetry = config.httpMethodsToRetry || [ + 'GET', + 'HEAD', + 'PUT', + 'OPTIONS', + 'DELETE', + ]; + config.noResponseRetries = + config.noResponseRetries === undefined || config.noResponseRetries === null + ? 2 + : config.noResponseRetries; + config.retryDelayMultiplier = config.retryDelayMultiplier + ? config.retryDelayMultiplier + : 2; + config.timeOfFirstRequest = config.timeOfFirstRequest + ? config.timeOfFirstRequest + : Date.now(); + config.totalTimeout = config.totalTimeout + ? config.totalTimeout + : Number.MAX_SAFE_INTEGER; + config.maxRetryDelay = config.maxRetryDelay + ? config.maxRetryDelay + : Number.MAX_SAFE_INTEGER; + // If this wasn't in the list of status codes where we want + // to automatically retry, return. + const retryRanges = [ + // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + // 1xx - Retry (Informational, request still processing) + // 2xx - Do not retry (Success) + // 3xx - Do not retry (Redirect) + // 4xx - Do not retry (Client errors) + // 408 - Retry ("Request Timeout") + // 429 - Retry ("Too Many Requests") + // 5xx - Retry (Server errors) + [100, 199], + [408, 408], + [429, 429], + [500, 599], + ]; + config.statusCodesToRetry = config.statusCodesToRetry || retryRanges; + // Put the config back into the err + err.config.retryConfig = config; + // Determine if we should retry the request + const shouldRetryFn = config.shouldRetry || shouldRetryRequest; + if (!(await shouldRetryFn(err))) { + return { shouldRetry: false, config: err.config }; + } + const delay = getNextRetryDelay(config); + // We're going to retry! Incremenent the counter. + err.config.retryConfig.currentRetryAttempt += 1; + // Create a promise that invokes the retry after the backOffDelay + const backoff = config.retryBackoff + ? config.retryBackoff(err, delay) + : new Promise(resolve => { + setTimeout(resolve, delay); + }); + // Notify the user if they added an `onRetryAttempt` handler + if (config.onRetryAttempt) { + config.onRetryAttempt(err); + } + // Return the promise in which recalls Gaxios to retry the request + await backoff; + return { shouldRetry: true, config: err.config }; +} +/** + * Determine based on config if we should retry the request. + * @param err The GaxiosError passed to the interceptor. + */ +function shouldRetryRequest(err) { + var _a; + const config = getConfig(err); + // node-fetch raises an AbortError if signaled: + // https://github.com/bitinn/node-fetch#request-cancellation-with-abortsignal + if (err.name === 'AbortError' || ((_a = err.error) === null || _a === void 0 ? void 0 : _a.name) === 'AbortError') { + return false; + } + // If there's no config, or retries are disabled, return. + if (!config || config.retry === 0) { + return false; + } + // Check if this error has no response (ETIMEDOUT, ENOTFOUND, etc) + if (!err.response && + (config.currentRetryAttempt || 0) >= config.noResponseRetries) { + return false; + } + // Only retry with configured HttpMethods. + if (!err.config.method || + config.httpMethodsToRetry.indexOf(err.config.method.toUpperCase()) < 0) { + return false; + } + // If this wasn't in the list of status codes where we want + // to automatically retry, return. + if (err.response && err.response.status) { + let isInRange = false; + for (const [min, max] of config.statusCodesToRetry) { + const status = err.response.status; + if (status >= min && status <= max) { + isInRange = true; + break; + } + } + if (!isInRange) { + return false; + } + } + // If we are out of retry attempts, return + config.currentRetryAttempt = config.currentRetryAttempt || 0; + if (config.currentRetryAttempt >= config.retry) { + return false; + } + return true; +} +/** + * Acquire the raxConfig object from an GaxiosError if available. + * @param err The Gaxios error with a config object. + */ +function getConfig(err) { + if (err && err.config && err.config.retryConfig) { + return err.config.retryConfig; + } + return; +} +/** + * Gets the delay to wait before the next retry. + * + * @param {RetryConfig} config The current set of retry options + * @returns {number} the amount of ms to wait before the next retry attempt. + */ +function getNextRetryDelay(config) { + var _a; + // Calculate time to wait with exponential backoff. + // If this is the first retry, look for a configured retryDelay. + const retryDelay = config.currentRetryAttempt ? 0 : (_a = config.retryDelay) !== null && _a !== void 0 ? _a : 100; + // Formula: retryDelay + ((retryDelayMultiplier^currentRetryAttempt - 1 / 2) * 1000) + const calculatedDelay = retryDelay + + ((Math.pow(config.retryDelayMultiplier, config.currentRetryAttempt) - 1) / + 2) * + 1000; + const maxAllowableDelay = config.totalTimeout - (Date.now() - config.timeOfFirstRequest); + return Math.min(calculatedDelay, maxAllowableDelay, config.maxRetryDelay); +} +//# sourceMappingURL=retry.js.map + +/***/ }), + +/***/ 63155: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2023 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.pkg = void 0; +exports.pkg = __nccwpck_require__(66495); +//# sourceMappingURL=util.js.map + +/***/ }), + +/***/ 70381: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GCE_LINUX_BIOS_PATHS = void 0; +exports.isGoogleCloudServerless = isGoogleCloudServerless; +exports.isGoogleComputeEngineLinux = isGoogleComputeEngineLinux; +exports.isGoogleComputeEngineMACAddress = isGoogleComputeEngineMACAddress; +exports.isGoogleComputeEngine = isGoogleComputeEngine; +exports.detectGCPResidency = detectGCPResidency; +const fs_1 = __nccwpck_require__(79896); +const os_1 = __nccwpck_require__(70857); +/** + * Known paths unique to Google Compute Engine Linux instances + */ +exports.GCE_LINUX_BIOS_PATHS = { + BIOS_DATE: '/sys/class/dmi/id/bios_date', + BIOS_VENDOR: '/sys/class/dmi/id/bios_vendor', +}; +const GCE_MAC_ADDRESS_REGEX = /^42:01/; +/** + * Determines if the process is running on a Google Cloud Serverless environment (Cloud Run or Cloud Functions instance). + * + * Uses the: + * - {@link https://cloud.google.com/run/docs/container-contract#env-vars Cloud Run environment variables}. + * - {@link https://cloud.google.com/functions/docs/env-var Cloud Functions environment variables}. + * + * @returns {boolean} `true` if the process is running on GCP serverless, `false` otherwise. + */ +function isGoogleCloudServerless() { + /** + * `CLOUD_RUN_JOB` is used for Cloud Run Jobs + * - See {@link https://cloud.google.com/run/docs/container-contract#env-vars Cloud Run environment variables}. + * + * `FUNCTION_NAME` is used in older Cloud Functions environments: + * - See {@link https://cloud.google.com/functions/docs/env-var Python 3.7 and Go 1.11}. + * + * `K_SERVICE` is used in Cloud Run and newer Cloud Functions environments: + * - See {@link https://cloud.google.com/run/docs/container-contract#env-vars Cloud Run environment variables}. + * - See {@link https://cloud.google.com/functions/docs/env-var Cloud Functions newer runtimes}. + */ + const isGFEnvironment = process.env.CLOUD_RUN_JOB || + process.env.FUNCTION_NAME || + process.env.K_SERVICE; + return !!isGFEnvironment; +} +/** + * Determines if the process is running on a Linux Google Compute Engine instance. + * + * @returns {boolean} `true` if the process is running on Linux GCE, `false` otherwise. + */ +function isGoogleComputeEngineLinux() { + if ((0, os_1.platform)() !== 'linux') + return false; + try { + // ensure this file exist + (0, fs_1.statSync)(exports.GCE_LINUX_BIOS_PATHS.BIOS_DATE); + // ensure this file exist and matches + const biosVendor = (0, fs_1.readFileSync)(exports.GCE_LINUX_BIOS_PATHS.BIOS_VENDOR, 'utf8'); + return /Google/.test(biosVendor); + } + catch (_a) { + return false; + } +} +/** + * Determines if the process is running on a Google Compute Engine instance with a known + * MAC address. + * + * @returns {boolean} `true` if the process is running on GCE (as determined by MAC address), `false` otherwise. + */ +function isGoogleComputeEngineMACAddress() { + const interfaces = (0, os_1.networkInterfaces)(); + for (const item of Object.values(interfaces)) { + if (!item) + continue; + for (const { mac } of item) { + if (GCE_MAC_ADDRESS_REGEX.test(mac)) { + return true; + } + } + } + return false; +} +/** + * Determines if the process is running on a Google Compute Engine instance. + * + * @returns {boolean} `true` if the process is running on GCE, `false` otherwise. + */ +function isGoogleComputeEngine() { + return isGoogleComputeEngineLinux() || isGoogleComputeEngineMACAddress(); +} +/** + * Determines if the process is running on Google Cloud Platform. + * + * @returns {boolean} `true` if the process is running on GCP, `false` otherwise. + */ +function detectGCPResidency() { + return isGoogleCloudServerless() || isGoogleComputeEngine(); +} +//# sourceMappingURL=gcp-residency.js.map + +/***/ }), + +/***/ 23046: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/** + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.gcpResidencyCache = exports.METADATA_SERVER_DETECTION = exports.HEADERS = exports.HEADER_VALUE = exports.HEADER_NAME = exports.SECONDARY_HOST_ADDRESS = exports.HOST_ADDRESS = exports.BASE_PATH = void 0; +exports.instance = instance; +exports.project = project; +exports.universe = universe; +exports.bulk = bulk; +exports.isAvailable = isAvailable; +exports.resetIsAvailableCache = resetIsAvailableCache; +exports.getGCPResidency = getGCPResidency; +exports.setGCPResidency = setGCPResidency; +exports.requestTimeout = requestTimeout; +const gaxios_1 = __nccwpck_require__(97003); +const jsonBigint = __nccwpck_require__(14826); +const gcp_residency_1 = __nccwpck_require__(70381); +const logger = __nccwpck_require__(81577); +exports.BASE_PATH = '/computeMetadata/v1'; +exports.HOST_ADDRESS = 'http://169.254.169.254'; +exports.SECONDARY_HOST_ADDRESS = 'http://metadata.google.internal.'; +exports.HEADER_NAME = 'Metadata-Flavor'; +exports.HEADER_VALUE = 'Google'; +exports.HEADERS = Object.freeze({ [exports.HEADER_NAME]: exports.HEADER_VALUE }); +const log = logger.log('gcp metadata'); +/** + * Metadata server detection override options. + * + * Available via `process.env.METADATA_SERVER_DETECTION`. + */ +exports.METADATA_SERVER_DETECTION = Object.freeze({ + 'assume-present': "don't try to ping the metadata server, but assume it's present", + none: "don't try to ping the metadata server, but don't try to use it either", + 'bios-only': "treat the result of a BIOS probe as canonical (don't fall back to pinging)", + 'ping-only': 'skip the BIOS probe, and go straight to pinging', +}); +/** + * Returns the base URL while taking into account the GCE_METADATA_HOST + * environment variable if it exists. + * + * @returns The base URL, e.g., http://169.254.169.254/computeMetadata/v1. + */ +function getBaseUrl(baseUrl) { + if (!baseUrl) { + baseUrl = + process.env.GCE_METADATA_IP || + process.env.GCE_METADATA_HOST || + exports.HOST_ADDRESS; + } + // If no scheme is provided default to HTTP: + if (!/^https?:\/\//.test(baseUrl)) { + baseUrl = `http://${baseUrl}`; + } + return new URL(exports.BASE_PATH, baseUrl).href; +} +// Accepts an options object passed from the user to the API. In previous +// versions of the API, it referred to a `Request` or an `Axios` request +// options object. Now it refers to an object with very limited property +// names. This is here to help ensure users don't pass invalid options when +// they upgrade from 0.4 to 0.5 to 0.8. +function validate(options) { + Object.keys(options).forEach(key => { + switch (key) { + case 'params': + case 'property': + case 'headers': + break; + case 'qs': + throw new Error("'qs' is not a valid configuration option. Please use 'params' instead."); + default: + throw new Error(`'${key}' is not a valid configuration option.`); + } + }); +} +async function metadataAccessor(type, options = {}, noResponseRetries = 3, fastFail = false) { + let metadataKey = ''; + let params = {}; + let headers = {}; + if (typeof type === 'object') { + const metadataAccessor = type; + metadataKey = metadataAccessor.metadataKey; + params = metadataAccessor.params || params; + headers = metadataAccessor.headers || headers; + noResponseRetries = metadataAccessor.noResponseRetries || noResponseRetries; + fastFail = metadataAccessor.fastFail || fastFail; + } + else { + metadataKey = type; + } + if (typeof options === 'string') { + metadataKey += `/${options}`; + } + else { + validate(options); + if (options.property) { + metadataKey += `/${options.property}`; + } + headers = options.headers || headers; + params = options.params || params; + } + const requestMethod = fastFail ? fastFailMetadataRequest : gaxios_1.request; + const req = { + url: `${getBaseUrl()}/${metadataKey}`, + headers: { ...exports.HEADERS, ...headers }, + retryConfig: { noResponseRetries }, + params, + responseType: 'text', + timeout: requestTimeout(), + }; + log.info('instance request %j', req); + const res = await requestMethod(req); + log.info('instance metadata is %s', res.data); + // NOTE: node.js converts all incoming headers to lower case. + if (res.headers[exports.HEADER_NAME.toLowerCase()] !== exports.HEADER_VALUE) { + throw new Error(`Invalid response from metadata service: incorrect ${exports.HEADER_NAME} header. Expected '${exports.HEADER_VALUE}', got ${res.headers[exports.HEADER_NAME.toLowerCase()] ? `'${res.headers[exports.HEADER_NAME.toLowerCase()]}'` : 'no header'}`); + } + if (typeof res.data === 'string') { + try { + return jsonBigint.parse(res.data); + } + catch (_a) { + /* ignore */ + } + } + return res.data; +} +async function fastFailMetadataRequest(options) { + var _a; + const secondaryOptions = { + ...options, + url: (_a = options.url) === null || _a === void 0 ? void 0 : _a.toString().replace(getBaseUrl(), getBaseUrl(exports.SECONDARY_HOST_ADDRESS)), + }; + // We race a connection between DNS/IP to metadata server. There are a couple + // reasons for this: + // + // 1. the DNS is slow in some GCP environments; by checking both, we might + // detect the runtime environment signficantly faster. + // 2. we can't just check the IP, which is tarpitted and slow to respond + // on a user's local machine. + // + // Additional logic has been added to make sure that we don't create an + // unhandled rejection in scenarios where a failure happens sometime + // after a success. + // + // Note, however, if a failure happens prior to a success, a rejection should + // occur, this is for folks running locally. + // + let responded = false; + const r1 = (0, gaxios_1.request)(options) + .then(res => { + responded = true; + return res; + }) + .catch(err => { + if (responded) { + return r2; + } + else { + responded = true; + throw err; + } + }); + const r2 = (0, gaxios_1.request)(secondaryOptions) + .then(res => { + responded = true; + return res; + }) + .catch(err => { + if (responded) { + return r1; + } + else { + responded = true; + throw err; + } + }); + return Promise.race([r1, r2]); +} +/** + * Obtain metadata for the current GCE instance. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const serviceAccount: {} = await instance('service-accounts/'); + * const serviceAccountEmail: string = await instance('service-accounts/default/email'); + * ``` + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function instance(options) { + return metadataAccessor('instance', options); +} +/** + * Obtain metadata for the current GCP project. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const projectId: string = await project('project-id'); + * const numericProjectId: number = await project('numeric-project-id'); + * ``` + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function project(options) { + return metadataAccessor('project', options); +} +/** + * Obtain metadata for the current universe. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const universeDomain: string = await universe('universe-domain'); + * ``` + */ +function universe(options) { + return metadataAccessor('universe', options); +} +/** + * Retrieve metadata items in parallel. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const data = await bulk([ + * { + * metadataKey: 'instance', + * }, + * { + * metadataKey: 'project/project-id', + * }, + * ] as const); + * + * // data.instance; + * // data['project/project-id']; + * ``` + * + * @param properties The metadata properties to retrieve + * @returns The metadata in `metadatakey:value` format + */ +async function bulk(properties) { + const r = {}; + await Promise.all(properties.map(item => { + return (async () => { + const res = await metadataAccessor(item); + const key = item.metadataKey; + r[key] = res; + })(); + })); + return r; +} +/* + * How many times should we retry detecting GCP environment. + */ +function detectGCPAvailableRetries() { + return process.env.DETECT_GCP_RETRIES + ? Number(process.env.DETECT_GCP_RETRIES) + : 0; +} +let cachedIsAvailableResponse; +/** + * Determine if the metadata server is currently available. + */ +async function isAvailable() { + if (process.env.METADATA_SERVER_DETECTION) { + const value = process.env.METADATA_SERVER_DETECTION.trim().toLocaleLowerCase(); + if (!(value in exports.METADATA_SERVER_DETECTION)) { + throw new RangeError(`Unknown \`METADATA_SERVER_DETECTION\` env variable. Got \`${value}\`, but it should be \`${Object.keys(exports.METADATA_SERVER_DETECTION).join('`, `')}\`, or unset`); + } + switch (value) { + case 'assume-present': + return true; + case 'none': + return false; + case 'bios-only': + return getGCPResidency(); + case 'ping-only': + // continue, we want to ping the server + } + } + try { + // If a user is instantiating several GCP libraries at the same time, + // this may result in multiple calls to isAvailable(), to detect the + // runtime environment. We use the same promise for each of these calls + // to reduce the network load. + if (cachedIsAvailableResponse === undefined) { + cachedIsAvailableResponse = metadataAccessor('instance', undefined, detectGCPAvailableRetries(), + // If the default HOST_ADDRESS has been overridden, we should not + // make an effort to try SECONDARY_HOST_ADDRESS (as we are likely in + // a non-GCP environment): + !(process.env.GCE_METADATA_IP || process.env.GCE_METADATA_HOST)); + } + await cachedIsAvailableResponse; + return true; + } + catch (e) { + const err = e; + if (process.env.DEBUG_AUTH) { + console.info(err); + } + if (err.type === 'request-timeout') { + // If running in a GCP environment, metadata endpoint should return + // within ms. + return false; + } + if (err.response && err.response.status === 404) { + return false; + } + else { + if (!(err.response && err.response.status === 404) && + // A warning is emitted if we see an unexpected err.code, or err.code + // is not populated: + (!err.code || + ![ + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'ENETUNREACH', + 'ENOENT', + 'ENOTFOUND', + 'ECONNREFUSED', + ].includes(err.code))) { + let code = 'UNKNOWN'; + if (err.code) + code = err.code; + process.emitWarning(`received unexpected error = ${err.message} code = ${code}`, 'MetadataLookupWarning'); + } + // Failure to resolve the metadata service means that it is not available. + return false; + } + } +} +/** + * reset the memoized isAvailable() lookup. + */ +function resetIsAvailableCache() { + cachedIsAvailableResponse = undefined; +} +/** + * A cache for the detected GCP Residency. + */ +exports.gcpResidencyCache = null; +/** + * Detects GCP Residency. + * Caches results to reduce costs for subsequent calls. + * + * @see setGCPResidency for setting + */ +function getGCPResidency() { + if (exports.gcpResidencyCache === null) { + setGCPResidency(); + } + return exports.gcpResidencyCache; +} +/** + * Sets the detected GCP Residency. + * Useful for forcing metadata server detection behavior. + * + * Set `null` to autodetect the environment (default behavior). + * @see getGCPResidency for getting + */ +function setGCPResidency(value = null) { + exports.gcpResidencyCache = value !== null ? value : (0, gcp_residency_1.detectGCPResidency)(); +} +/** + * Obtain the timeout for requests to the metadata server. + * + * In certain environments and conditions requests can take longer than + * the default timeout to complete. This function will determine the + * appropriate timeout based on the environment. + * + * @returns {number} a request timeout duration in milliseconds. + */ +function requestTimeout() { + return getGCPResidency() ? 0 : 3000; +} +__exportStar(__nccwpck_require__(70381), exports); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 34810: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2012 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AuthClient = exports.DEFAULT_EAGER_REFRESH_THRESHOLD_MILLIS = exports.DEFAULT_UNIVERSE = void 0; +const events_1 = __nccwpck_require__(24434); +const gaxios_1 = __nccwpck_require__(97003); +const transporters_1 = __nccwpck_require__(67633); +const util_1 = __nccwpck_require__(37870); +/** + * The default cloud universe + * + * @see {@link AuthJSONOptions.universe_domain} + */ +exports.DEFAULT_UNIVERSE = 'googleapis.com'; +/** + * The default {@link AuthClientOptions.eagerRefreshThresholdMillis} + */ +exports.DEFAULT_EAGER_REFRESH_THRESHOLD_MILLIS = 5 * 60 * 1000; +class AuthClient extends events_1.EventEmitter { + constructor(opts = {}) { + var _a, _b, _c, _d, _e; + super(); + this.credentials = {}; + this.eagerRefreshThresholdMillis = exports.DEFAULT_EAGER_REFRESH_THRESHOLD_MILLIS; + this.forceRefreshOnFailure = false; + this.universeDomain = exports.DEFAULT_UNIVERSE; + const options = (0, util_1.originalOrCamelOptions)(opts); + // Shared auth options + this.apiKey = opts.apiKey; + this.projectId = (_a = options.get('project_id')) !== null && _a !== void 0 ? _a : null; + this.quotaProjectId = options.get('quota_project_id'); + this.credentials = (_b = options.get('credentials')) !== null && _b !== void 0 ? _b : {}; + this.universeDomain = (_c = options.get('universe_domain')) !== null && _c !== void 0 ? _c : exports.DEFAULT_UNIVERSE; + // Shared client options + this.transporter = (_d = opts.transporter) !== null && _d !== void 0 ? _d : new transporters_1.DefaultTransporter(); + if (opts.transporterOptions) { + this.transporter.defaults = opts.transporterOptions; + } + if (opts.eagerRefreshThresholdMillis) { + this.eagerRefreshThresholdMillis = opts.eagerRefreshThresholdMillis; + } + this.forceRefreshOnFailure = (_e = opts.forceRefreshOnFailure) !== null && _e !== void 0 ? _e : false; + } + /** + * Return the {@link Gaxios `Gaxios`} instance from the {@link AuthClient.transporter}. + * + * @expiremental + */ + get gaxios() { + if (this.transporter instanceof gaxios_1.Gaxios) { + return this.transporter; + } + else if (this.transporter instanceof transporters_1.DefaultTransporter) { + return this.transporter.instance; + } + else if ('instance' in this.transporter && + this.transporter.instance instanceof gaxios_1.Gaxios) { + return this.transporter.instance; + } + return null; + } + /** + * Sets the auth credentials. + */ + setCredentials(credentials) { + this.credentials = credentials; + } + /** + * Append additional headers, e.g., x-goog-user-project, shared across the + * classes inheriting AuthClient. This method should be used by any method + * that overrides getRequestMetadataAsync(), which is a shared helper for + * setting request information in both gRPC and HTTP API calls. + * + * @param headers object to append additional headers to. + */ + addSharedMetadataHeaders(headers) { + // quota_project_id, stored in application_default_credentials.json, is set in + // the x-goog-user-project header, to indicate an alternate account for + // billing and quota: + if (!headers['x-goog-user-project'] && // don't override a value the user sets. + this.quotaProjectId) { + headers['x-goog-user-project'] = this.quotaProjectId; + } + return headers; + } + /** + * Retry config for Auth-related requests. + * + * @remarks + * + * This is not a part of the default {@link AuthClient.transporter transporter/gaxios} + * config as some downstream APIs would prefer if customers explicitly enable retries, + * such as GCS. + */ + static get RETRY_CONFIG() { + return { + retry: true, + retryConfig: { + httpMethodsToRetry: ['GET', 'PUT', 'POST', 'HEAD', 'OPTIONS', 'DELETE'], + }, + }; + } +} +exports.AuthClient = AuthClient; + + +/***/ }), + +/***/ 81261: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _a, _AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsClient = void 0; +const awsrequestsigner_1 = __nccwpck_require__(27647); +const baseexternalclient_1 = __nccwpck_require__(142); +const defaultawssecuritycredentialssupplier_1 = __nccwpck_require__(69157); +const util_1 = __nccwpck_require__(37870); +/** + * AWS external account client. This is used for AWS workloads, where + * AWS STS GetCallerIdentity serialized signed requests are exchanged for + * GCP access token. + */ +class AwsClient extends baseexternalclient_1.BaseExternalAccountClient { + /** + * Instantiates an AwsClient instance using the provided JSON + * object loaded from an external account credentials file. + * An error is thrown if the credential is not a valid AWS credential. + * @param options The external account options object typically loaded + * from the external account JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + super(options, additionalOptions); + const opts = (0, util_1.originalOrCamelOptions)(options); + const credentialSource = opts.get('credential_source'); + const awsSecurityCredentialsSupplier = opts.get('aws_security_credentials_supplier'); + // Validate credential sourcing configuration. + if (!credentialSource && !awsSecurityCredentialsSupplier) { + throw new Error('A credential source or AWS security credentials supplier must be specified.'); + } + if (credentialSource && awsSecurityCredentialsSupplier) { + throw new Error('Only one of credential source or AWS security credentials supplier can be specified.'); + } + if (awsSecurityCredentialsSupplier) { + this.awsSecurityCredentialsSupplier = awsSecurityCredentialsSupplier; + this.regionalCredVerificationUrl = + __classPrivateFieldGet(_a, _a, "f", _AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL); + this.credentialSourceType = 'programmatic'; + } + else { + const credentialSourceOpts = (0, util_1.originalOrCamelOptions)(credentialSource); + this.environmentId = credentialSourceOpts.get('environment_id'); + // This is only required if the AWS region is not available in the + // AWS_REGION or AWS_DEFAULT_REGION environment variables. + const regionUrl = credentialSourceOpts.get('region_url'); + // This is only required if AWS security credentials are not available in + // environment variables. + const securityCredentialsUrl = credentialSourceOpts.get('url'); + const imdsV2SessionTokenUrl = credentialSourceOpts.get('imdsv2_session_token_url'); + this.awsSecurityCredentialsSupplier = + new defaultawssecuritycredentialssupplier_1.DefaultAwsSecurityCredentialsSupplier({ + regionUrl: regionUrl, + securityCredentialsUrl: securityCredentialsUrl, + imdsV2SessionTokenUrl: imdsV2SessionTokenUrl, + }); + this.regionalCredVerificationUrl = credentialSourceOpts.get('regional_cred_verification_url'); + this.credentialSourceType = 'aws'; + // Data validators. + this.validateEnvironmentId(); + } + this.awsRequestSigner = null; + this.region = ''; + } + validateEnvironmentId() { + var _b; + const match = (_b = this.environmentId) === null || _b === void 0 ? void 0 : _b.match(/^(aws)(\d+)$/); + if (!match || !this.regionalCredVerificationUrl) { + throw new Error('No valid AWS "credential_source" provided'); + } + else if (parseInt(match[2], 10) !== 1) { + throw new Error(`aws version "${match[2]}" is not supported in the current build.`); + } + } + /** + * Triggered when an external subject token is needed to be exchanged for a + * GCP access token via GCP STS endpoint. This will call the + * {@link AwsSecurityCredentialsSupplier} to retrieve an AWS region and AWS + * Security Credentials, then use them to create a signed AWS STS request that + * can be exchanged for a GCP access token. + * @return A promise that resolves with the external subject token. + */ + async retrieveSubjectToken() { + // Initialize AWS request signer if not already initialized. + if (!this.awsRequestSigner) { + this.region = await this.awsSecurityCredentialsSupplier.getAwsRegion(this.supplierContext); + this.awsRequestSigner = new awsrequestsigner_1.AwsRequestSigner(async () => { + return this.awsSecurityCredentialsSupplier.getAwsSecurityCredentials(this.supplierContext); + }, this.region); + } + // Generate signed request to AWS STS GetCallerIdentity API. + // Use the required regional endpoint. Otherwise, the request will fail. + const options = await this.awsRequestSigner.getRequestOptions({ + ..._a.RETRY_CONFIG, + url: this.regionalCredVerificationUrl.replace('{region}', this.region), + method: 'POST', + }); + // The GCP STS endpoint expects the headers to be formatted as: + // [ + // {key: 'x-amz-date', value: '...'}, + // {key: 'Authorization', value: '...'}, + // ... + // ] + // And then serialized as: + // encodeURIComponent(JSON.stringify({ + // url: '...', + // method: 'POST', + // headers: [{key: 'x-amz-date', value: '...'}, ...] + // })) + const reformattedHeader = []; + const extendedHeaders = Object.assign({ + // The full, canonical resource name of the workload identity pool + // provider, with or without the HTTPS prefix. + // Including this header as part of the signature is recommended to + // ensure data integrity. + 'x-goog-cloud-target-resource': this.audience, + }, options.headers); + // Reformat header to GCP STS expected format. + for (const key in extendedHeaders) { + reformattedHeader.push({ + key, + value: extendedHeaders[key], + }); + } + // Serialize the reformatted signed request. + return encodeURIComponent(JSON.stringify({ + url: options.url, + method: options.method, + headers: reformattedHeader, + })); + } +} +exports.AwsClient = AwsClient; +_a = AwsClient; +_AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL = { value: 'https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15' }; +/** + * @deprecated AWS client no validates the EC2 metadata address. + **/ +AwsClient.AWS_EC2_METADATA_IPV4_ADDRESS = '169.254.169.254'; +/** + * @deprecated AWS client no validates the EC2 metadata address. + **/ +AwsClient.AWS_EC2_METADATA_IPV6_ADDRESS = 'fd00:ec2::254'; + + +/***/ }), + +/***/ 27647: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsRequestSigner = void 0; +const crypto_1 = __nccwpck_require__(88851); +/** AWS Signature Version 4 signing algorithm identifier. */ +const AWS_ALGORITHM = 'AWS4-HMAC-SHA256'; +/** + * The termination string for the AWS credential scope value as defined in + * https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html + */ +const AWS_REQUEST_TYPE = 'aws4_request'; +/** + * Implements an AWS API request signer based on the AWS Signature Version 4 + * signing process. + * https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html + */ +class AwsRequestSigner { + /** + * Instantiates an AWS API request signer used to send authenticated signed + * requests to AWS APIs based on the AWS Signature Version 4 signing process. + * This also provides a mechanism to generate the signed request without + * sending it. + * @param getCredentials A mechanism to retrieve AWS security credentials + * when needed. + * @param region The AWS region to use. + */ + constructor(getCredentials, region) { + this.getCredentials = getCredentials; + this.region = region; + this.crypto = (0, crypto_1.createCrypto)(); + } + /** + * Generates the signed request for the provided HTTP request for calling + * an AWS API. This follows the steps described at: + * https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html + * @param amzOptions The AWS request options that need to be signed. + * @return A promise that resolves with the GaxiosOptions containing the + * signed HTTP request parameters. + */ + async getRequestOptions(amzOptions) { + if (!amzOptions.url) { + throw new Error('"url" is required in "amzOptions"'); + } + // Stringify JSON requests. This will be set in the request body of the + // generated signed request. + const requestPayloadData = typeof amzOptions.data === 'object' + ? JSON.stringify(amzOptions.data) + : amzOptions.data; + const url = amzOptions.url; + const method = amzOptions.method || 'GET'; + const requestPayload = amzOptions.body || requestPayloadData; + const additionalAmzHeaders = amzOptions.headers; + const awsSecurityCredentials = await this.getCredentials(); + const uri = new URL(url); + const headerMap = await generateAuthenticationHeaderMap({ + crypto: this.crypto, + host: uri.host, + canonicalUri: uri.pathname, + canonicalQuerystring: uri.search.substr(1), + method, + region: this.region, + securityCredentials: awsSecurityCredentials, + requestPayload, + additionalAmzHeaders, + }); + // Append additional optional headers, eg. X-Amz-Target, Content-Type, etc. + const headers = Object.assign( + // Add x-amz-date if available. + headerMap.amzDate ? { 'x-amz-date': headerMap.amzDate } : {}, { + Authorization: headerMap.authorizationHeader, + host: uri.host, + }, additionalAmzHeaders || {}); + if (awsSecurityCredentials.token) { + Object.assign(headers, { + 'x-amz-security-token': awsSecurityCredentials.token, + }); + } + const awsSignedReq = { + url, + method: method, + headers, + }; + if (typeof requestPayload !== 'undefined') { + awsSignedReq.body = requestPayload; + } + return awsSignedReq; + } +} +exports.AwsRequestSigner = AwsRequestSigner; +/** + * Creates the HMAC-SHA256 hash of the provided message using the + * provided key. + * + * @param crypto The crypto instance used to facilitate cryptographic + * operations. + * @param key The HMAC-SHA256 key to use. + * @param msg The message to hash. + * @return The computed hash bytes. + */ +async function sign(crypto, key, msg) { + return await crypto.signWithHmacSha256(key, msg); +} +/** + * Calculates the signing key used to calculate the signature for + * AWS Signature Version 4 based on: + * https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html + * + * @param crypto The crypto instance used to facilitate cryptographic + * operations. + * @param key The AWS secret access key. + * @param dateStamp The '%Y%m%d' date format. + * @param region The AWS region. + * @param serviceName The AWS service name, eg. sts. + * @return The signing key bytes. + */ +async function getSigningKey(crypto, key, dateStamp, region, serviceName) { + const kDate = await sign(crypto, `AWS4${key}`, dateStamp); + const kRegion = await sign(crypto, kDate, region); + const kService = await sign(crypto, kRegion, serviceName); + const kSigning = await sign(crypto, kService, 'aws4_request'); + return kSigning; +} +/** + * Generates the authentication header map needed for generating the AWS + * Signature Version 4 signed request. + * + * @param option The options needed to compute the authentication header map. + * @return The AWS authentication header map which constitutes of the following + * components: amz-date, authorization header and canonical query string. + */ +async function generateAuthenticationHeaderMap(options) { + const additionalAmzHeaders = options.additionalAmzHeaders || {}; + const requestPayload = options.requestPayload || ''; + // iam.amazonaws.com host => iam service. + // sts.us-east-2.amazonaws.com => sts service. + const serviceName = options.host.split('.')[0]; + const now = new Date(); + // Format: '%Y%m%dT%H%M%SZ'. + const amzDate = now + .toISOString() + .replace(/[-:]/g, '') + .replace(/\.[0-9]+/, ''); + // Format: '%Y%m%d'. + const dateStamp = now.toISOString().replace(/[-]/g, '').replace(/T.*/, ''); + // Change all additional headers to be lower case. + const reformattedAdditionalAmzHeaders = {}; + Object.keys(additionalAmzHeaders).forEach(key => { + reformattedAdditionalAmzHeaders[key.toLowerCase()] = + additionalAmzHeaders[key]; + }); + // Add AWS token if available. + if (options.securityCredentials.token) { + reformattedAdditionalAmzHeaders['x-amz-security-token'] = + options.securityCredentials.token; + } + // Header keys need to be sorted alphabetically. + const amzHeaders = Object.assign({ + host: options.host, + }, + // Previously the date was not fixed with x-amz- and could be provided manually. + // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-header-value-trim.req + reformattedAdditionalAmzHeaders.date ? {} : { 'x-amz-date': amzDate }, reformattedAdditionalAmzHeaders); + let canonicalHeaders = ''; + const signedHeadersList = Object.keys(amzHeaders).sort(); + signedHeadersList.forEach(key => { + canonicalHeaders += `${key}:${amzHeaders[key]}\n`; + }); + const signedHeaders = signedHeadersList.join(';'); + const payloadHash = await options.crypto.sha256DigestHex(requestPayload); + // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html + const canonicalRequest = `${options.method}\n` + + `${options.canonicalUri}\n` + + `${options.canonicalQuerystring}\n` + + `${canonicalHeaders}\n` + + `${signedHeaders}\n` + + `${payloadHash}`; + const credentialScope = `${dateStamp}/${options.region}/${serviceName}/${AWS_REQUEST_TYPE}`; + // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html + const stringToSign = `${AWS_ALGORITHM}\n` + + `${amzDate}\n` + + `${credentialScope}\n` + + (await options.crypto.sha256DigestHex(canonicalRequest)); + // https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html + const signingKey = await getSigningKey(options.crypto, options.securityCredentials.secretAccessKey, dateStamp, options.region, serviceName); + const signature = await sign(options.crypto, signingKey, stringToSign); + // https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html + const authorizationHeader = `${AWS_ALGORITHM} Credential=${options.securityCredentials.accessKeyId}/` + + `${credentialScope}, SignedHeaders=${signedHeaders}, ` + + `Signature=${(0, crypto_1.fromArrayBufferToHex)(signature)}`; + return { + // Do not return x-amz-date if date is available. + amzDate: reformattedAdditionalAmzHeaders.date ? undefined : amzDate, + authorizationHeader, + canonicalQuerystring: options.canonicalQuerystring, + }; +} + + +/***/ }), + +/***/ 142: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _BaseExternalAccountClient_instances, _BaseExternalAccountClient_pendingAccessToken, _BaseExternalAccountClient_internalRefreshAccessTokenAsync; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.BaseExternalAccountClient = exports.DEFAULT_UNIVERSE = exports.CLOUD_RESOURCE_MANAGER = exports.EXTERNAL_ACCOUNT_TYPE = exports.EXPIRATION_TIME_OFFSET = void 0; +const stream = __nccwpck_require__(2203); +const authclient_1 = __nccwpck_require__(34810); +const sts = __nccwpck_require__(121); +const util_1 = __nccwpck_require__(37870); +/** + * The required token exchange grant_type: rfc8693#section-2.1 + */ +const STS_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange'; +/** + * The requested token exchange requested_token_type: rfc8693#section-2.1 + */ +const STS_REQUEST_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token'; +/** The default OAuth scope to request when none is provided. */ +const DEFAULT_OAUTH_SCOPE = 'https://www.googleapis.com/auth/cloud-platform'; +/** Default impersonated token lifespan in seconds.*/ +const DEFAULT_TOKEN_LIFESPAN = 3600; +/** + * Offset to take into account network delays and server clock skews. + */ +exports.EXPIRATION_TIME_OFFSET = 5 * 60 * 1000; +/** + * The credentials JSON file type for external account clients. + * There are 3 types of JSON configs: + * 1. authorized_user => Google end user credential + * 2. service_account => Google service account credential + * 3. external_Account => non-GCP service (eg. AWS, Azure, K8s) + */ +exports.EXTERNAL_ACCOUNT_TYPE = 'external_account'; +/** + * Cloud resource manager URL used to retrieve project information. + * + * @deprecated use {@link BaseExternalAccountClient.cloudResourceManagerURL} instead + **/ +exports.CLOUD_RESOURCE_MANAGER = 'https://cloudresourcemanager.googleapis.com/v1/projects/'; +/** The workforce audience pattern. */ +const WORKFORCE_AUDIENCE_PATTERN = '//iam\\.googleapis\\.com/locations/[^/]+/workforcePools/[^/]+/providers/.+'; +const DEFAULT_TOKEN_URL = 'https://sts.{universeDomain}/v1/token'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = __nccwpck_require__(96066); +/** + * For backwards compatibility. + */ +var authclient_2 = __nccwpck_require__(34810); +Object.defineProperty(exports, "DEFAULT_UNIVERSE", ({ enumerable: true, get: function () { return authclient_2.DEFAULT_UNIVERSE; } })); +/** + * Base external account client. This is used to instantiate AuthClients for + * exchanging external account credentials for GCP access token and authorizing + * requests to GCP APIs. + * The base class implements common logic for exchanging various type of + * external credentials for GCP access token. The logic of determining and + * retrieving the external credential based on the environment and + * credential_source will be left for the subclasses. + */ +class BaseExternalAccountClient extends authclient_1.AuthClient { + /** + * Instantiate a BaseExternalAccountClient instance using the provided JSON + * object loaded from an external account credentials file. + * @param options The external account options object typically loaded + * from the external account JSON credential file. The camelCased options + * are aliases for the snake_cased options. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + var _a; + super({ ...options, ...additionalOptions }); + _BaseExternalAccountClient_instances.add(this); + /** + * A pending access token request. Used for concurrent calls. + */ + _BaseExternalAccountClient_pendingAccessToken.set(this, null); + const opts = (0, util_1.originalOrCamelOptions)(options); + const type = opts.get('type'); + if (type && type !== exports.EXTERNAL_ACCOUNT_TYPE) { + throw new Error(`Expected "${exports.EXTERNAL_ACCOUNT_TYPE}" type but ` + + `received "${options.type}"`); + } + const clientId = opts.get('client_id'); + const clientSecret = opts.get('client_secret'); + const tokenUrl = (_a = opts.get('token_url')) !== null && _a !== void 0 ? _a : DEFAULT_TOKEN_URL.replace('{universeDomain}', this.universeDomain); + const subjectTokenType = opts.get('subject_token_type'); + const workforcePoolUserProject = opts.get('workforce_pool_user_project'); + const serviceAccountImpersonationUrl = opts.get('service_account_impersonation_url'); + const serviceAccountImpersonation = opts.get('service_account_impersonation'); + const serviceAccountImpersonationLifetime = (0, util_1.originalOrCamelOptions)(serviceAccountImpersonation).get('token_lifetime_seconds'); + this.cloudResourceManagerURL = new URL(opts.get('cloud_resource_manager_url') || + `https://cloudresourcemanager.${this.universeDomain}/v1/projects/`); + if (clientId) { + this.clientAuth = { + confidentialClientType: 'basic', + clientId, + clientSecret, + }; + } + this.stsCredential = new sts.StsCredentials(tokenUrl, this.clientAuth); + this.scopes = opts.get('scopes') || [DEFAULT_OAUTH_SCOPE]; + this.cachedAccessToken = null; + this.audience = opts.get('audience'); + this.subjectTokenType = subjectTokenType; + this.workforcePoolUserProject = workforcePoolUserProject; + const workforceAudiencePattern = new RegExp(WORKFORCE_AUDIENCE_PATTERN); + if (this.workforcePoolUserProject && + !this.audience.match(workforceAudiencePattern)) { + throw new Error('workforcePoolUserProject should not be set for non-workforce pool ' + + 'credentials.'); + } + this.serviceAccountImpersonationUrl = serviceAccountImpersonationUrl; + this.serviceAccountImpersonationLifetime = + serviceAccountImpersonationLifetime; + if (this.serviceAccountImpersonationLifetime) { + this.configLifetimeRequested = true; + } + else { + this.configLifetimeRequested = false; + this.serviceAccountImpersonationLifetime = DEFAULT_TOKEN_LIFESPAN; + } + this.projectNumber = this.getProjectNumber(this.audience); + this.supplierContext = { + audience: this.audience, + subjectTokenType: this.subjectTokenType, + transporter: this.transporter, + }; + } + /** The service account email to be impersonated, if available. */ + getServiceAccountEmail() { + var _a; + if (this.serviceAccountImpersonationUrl) { + if (this.serviceAccountImpersonationUrl.length > 256) { + /** + * Prevents DOS attacks. + * @see {@link https://github.com/googleapis/google-auth-library-nodejs/security/code-scanning/84} + **/ + throw new RangeError(`URL is too long: ${this.serviceAccountImpersonationUrl}`); + } + // Parse email from URL. The formal looks as follows: + // https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/name@project-id.iam.gserviceaccount.com:generateAccessToken + const re = /serviceAccounts\/(?[^:]+):generateAccessToken$/; + const result = re.exec(this.serviceAccountImpersonationUrl); + return ((_a = result === null || result === void 0 ? void 0 : result.groups) === null || _a === void 0 ? void 0 : _a.email) || null; + } + return null; + } + /** + * Provides a mechanism to inject GCP access tokens directly. + * When the provided credential expires, a new credential, using the + * external account options, is retrieved. + * @param credentials The Credentials object to set on the current client. + */ + setCredentials(credentials) { + super.setCredentials(credentials); + this.cachedAccessToken = credentials; + } + /** + * @return A promise that resolves with the current GCP access token + * response. If the current credential is expired, a new one is retrieved. + */ + async getAccessToken() { + // If cached access token is unavailable or expired, force refresh. + if (!this.cachedAccessToken || this.isExpired(this.cachedAccessToken)) { + await this.refreshAccessTokenAsync(); + } + // Return GCP access token in GetAccessTokenResponse format. + return { + token: this.cachedAccessToken.access_token, + res: this.cachedAccessToken.res, + }; + } + /** + * The main authentication interface. It takes an optional url which when + * present is the endpoint being accessed, and returns a Promise which + * resolves with authorization header fields. + * + * The result has the form: + * { Authorization: 'Bearer ' } + */ + async getRequestHeaders() { + const accessTokenResponse = await this.getAccessToken(); + const headers = { + Authorization: `Bearer ${accessTokenResponse.token}`, + }; + return this.addSharedMetadataHeaders(headers); + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + /** + * @return A promise that resolves with the project ID corresponding to the + * current workload identity pool or current workforce pool if + * determinable. For workforce pool credential, it returns the project ID + * corresponding to the workforcePoolUserProject. + * This is introduced to match the current pattern of using the Auth + * library: + * const projectId = await auth.getProjectId(); + * const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; + * const res = await client.request({ url }); + * The resource may not have permission + * (resourcemanager.projects.get) to call this API or the required + * scopes may not be selected: + * https://cloud.google.com/resource-manager/reference/rest/v1/projects/get#authorization-scopes + */ + async getProjectId() { + const projectNumber = this.projectNumber || this.workforcePoolUserProject; + if (this.projectId) { + // Return previously determined project ID. + return this.projectId; + } + else if (projectNumber) { + // Preferable not to use request() to avoid retrial policies. + const headers = await this.getRequestHeaders(); + const response = await this.transporter.request({ + ...BaseExternalAccountClient.RETRY_CONFIG, + headers, + url: `${this.cloudResourceManagerURL.toString()}${projectNumber}`, + responseType: 'json', + }); + this.projectId = response.data.projectId; + return this.projectId; + } + return null; + } + /** + * Authenticates the provided HTTP request, processes it and resolves with the + * returned response. + * @param opts The HTTP request options. + * @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure. + * @return A promise that resolves with the successful response. + */ + async requestAsync(opts, reAuthRetried = false) { + let response; + try { + const requestHeaders = await this.getRequestHeaders(); + opts.headers = opts.headers || {}; + if (requestHeaders && requestHeaders['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = + requestHeaders['x-goog-user-project']; + } + if (requestHeaders && requestHeaders.Authorization) { + opts.headers.Authorization = requestHeaders.Authorization; + } + response = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - forceRefreshOnFailure is true + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + this.forceRefreshOnFailure) { + await this.refreshAccessTokenAsync(); + return await this.requestAsync(opts, true); + } + } + throw e; + } + return response; + } + /** + * Forces token refresh, even if unexpired tokens are currently cached. + * External credentials are exchanged for GCP access tokens via the token + * exchange endpoint and other settings provided in the client options + * object. + * If the service_account_impersonation_url is provided, an additional + * step to exchange the external account GCP access token for a service + * account impersonated token is performed. + * @return A promise that resolves with the fresh GCP access tokens. + */ + async refreshAccessTokenAsync() { + // Use an existing access token request, or cache a new one + __classPrivateFieldSet(this, _BaseExternalAccountClient_pendingAccessToken, __classPrivateFieldGet(this, _BaseExternalAccountClient_pendingAccessToken, "f") || __classPrivateFieldGet(this, _BaseExternalAccountClient_instances, "m", _BaseExternalAccountClient_internalRefreshAccessTokenAsync).call(this), "f"); + try { + return await __classPrivateFieldGet(this, _BaseExternalAccountClient_pendingAccessToken, "f"); + } + finally { + // clear pending access token for future requests + __classPrivateFieldSet(this, _BaseExternalAccountClient_pendingAccessToken, null, "f"); + } + } + /** + * Returns the workload identity pool project number if it is determinable + * from the audience resource name. + * @param audience The STS audience used to determine the project number. + * @return The project number associated with the workload identity pool, if + * this can be determined from the STS audience field. Otherwise, null is + * returned. + */ + getProjectNumber(audience) { + // STS audience pattern: + // //iam.googleapis.com/projects/$PROJECT_NUMBER/locations/... + const match = audience.match(/\/projects\/([^/]+)/); + if (!match) { + return null; + } + return match[1]; + } + /** + * Exchanges an external account GCP access token for a service + * account impersonated access token using iamcredentials + * GenerateAccessToken API. + * @param token The access token to exchange for a service account access + * token. + * @return A promise that resolves with the service account impersonated + * credentials response. + */ + async getImpersonatedAccessToken(token) { + const opts = { + ...BaseExternalAccountClient.RETRY_CONFIG, + url: this.serviceAccountImpersonationUrl, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + data: { + scope: this.getScopesArray(), + lifetime: this.serviceAccountImpersonationLifetime + 's', + }, + responseType: 'json', + }; + const response = await this.transporter.request(opts); + const successResponse = response.data; + return { + access_token: successResponse.accessToken, + // Convert from ISO format to timestamp. + expiry_date: new Date(successResponse.expireTime).getTime(), + res: response, + }; + } + /** + * Returns whether the provided credentials are expired or not. + * If there is no expiry time, assumes the token is not expired or expiring. + * @param accessToken The credentials to check for expiration. + * @return Whether the credentials are expired or not. + */ + isExpired(accessToken) { + const now = new Date().getTime(); + return accessToken.expiry_date + ? now >= accessToken.expiry_date - this.eagerRefreshThresholdMillis + : false; + } + /** + * @return The list of scopes for the requested GCP access token. + */ + getScopesArray() { + // Since scopes can be provided as string or array, the type should + // be normalized. + if (typeof this.scopes === 'string') { + return [this.scopes]; + } + return this.scopes || [DEFAULT_OAUTH_SCOPE]; + } + getMetricsHeaderValue() { + const nodeVersion = process.version.replace(/^v/, ''); + const saImpersonation = this.serviceAccountImpersonationUrl !== undefined; + const credentialSourceType = this.credentialSourceType + ? this.credentialSourceType + : 'unknown'; + return `gl-node/${nodeVersion} auth/${pkg.version} google-byoid-sdk source/${credentialSourceType} sa-impersonation/${saImpersonation} config-lifetime/${this.configLifetimeRequested}`; + } +} +exports.BaseExternalAccountClient = BaseExternalAccountClient; +_BaseExternalAccountClient_pendingAccessToken = new WeakMap(), _BaseExternalAccountClient_instances = new WeakSet(), _BaseExternalAccountClient_internalRefreshAccessTokenAsync = async function _BaseExternalAccountClient_internalRefreshAccessTokenAsync() { + // Retrieve the external credential. + const subjectToken = await this.retrieveSubjectToken(); + // Construct the STS credentials options. + const stsCredentialsOptions = { + grantType: STS_GRANT_TYPE, + audience: this.audience, + requestedTokenType: STS_REQUEST_TOKEN_TYPE, + subjectToken, + subjectTokenType: this.subjectTokenType, + // generateAccessToken requires the provided access token to have + // scopes: + // https://www.googleapis.com/auth/iam or + // https://www.googleapis.com/auth/cloud-platform + // The new service account access token scopes will match the user + // provided ones. + scope: this.serviceAccountImpersonationUrl + ? [DEFAULT_OAUTH_SCOPE] + : this.getScopesArray(), + }; + // Exchange the external credentials for a GCP access token. + // Client auth is prioritized over passing the workforcePoolUserProject + // parameter for STS token exchange. + const additionalOptions = !this.clientAuth && this.workforcePoolUserProject + ? { userProject: this.workforcePoolUserProject } + : undefined; + const additionalHeaders = { + 'x-goog-api-client': this.getMetricsHeaderValue(), + }; + const stsResponse = await this.stsCredential.exchangeToken(stsCredentialsOptions, additionalHeaders, additionalOptions); + if (this.serviceAccountImpersonationUrl) { + this.cachedAccessToken = await this.getImpersonatedAccessToken(stsResponse.access_token); + } + else if (stsResponse.expires_in) { + // Save response in cached access token. + this.cachedAccessToken = { + access_token: stsResponse.access_token, + expiry_date: new Date().getTime() + stsResponse.expires_in * 1000, + res: stsResponse.res, + }; + } + else { + // Save response in cached access token. + this.cachedAccessToken = { + access_token: stsResponse.access_token, + res: stsResponse.res, + }; + } + // Save credentials. + this.credentials = {}; + Object.assign(this.credentials, this.cachedAccessToken); + delete this.credentials.res; + // Trigger tokens event to notify external listeners. + this.emit('tokens', { + refresh_token: null, + expiry_date: this.cachedAccessToken.expiry_date, + access_token: this.cachedAccessToken.access_token, + token_type: 'Bearer', + id_token: null, + }); + // Return the cached access token. + return this.cachedAccessToken; +}; + + +/***/ }), + +/***/ 20977: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2013 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Compute = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const gcpMetadata = __nccwpck_require__(23046); +const oauth2client_1 = __nccwpck_require__(10091); +class Compute extends oauth2client_1.OAuth2Client { + /** + * Google Compute Engine service account credentials. + * + * Retrieve access token from the metadata server. + * See: https://cloud.google.com/compute/docs/access/authenticate-workloads#applications + */ + constructor(options = {}) { + super(options); + // Start with an expired refresh token, which will automatically be + // refreshed before the first API call is made. + this.credentials = { expiry_date: 1, refresh_token: 'compute-placeholder' }; + this.serviceAccountEmail = options.serviceAccountEmail || 'default'; + this.scopes = Array.isArray(options.scopes) + ? options.scopes + : options.scopes + ? [options.scopes] + : []; + } + /** + * Refreshes the access token. + * @param refreshToken Unused parameter + */ + async refreshTokenNoCache( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + refreshToken) { + const tokenPath = `service-accounts/${this.serviceAccountEmail}/token`; + let data; + try { + const instanceOptions = { + property: tokenPath, + }; + if (this.scopes.length > 0) { + instanceOptions.params = { + scopes: this.scopes.join(','), + }; + } + data = await gcpMetadata.instance(instanceOptions); + } + catch (e) { + if (e instanceof gaxios_1.GaxiosError) { + e.message = `Could not refresh access token: ${e.message}`; + this.wrapError(e); + } + throw e; + } + const tokens = data; + if (data && data.expires_in) { + tokens.expiry_date = new Date().getTime() + data.expires_in * 1000; + delete tokens.expires_in; + } + this.emit('tokens', tokens); + return { tokens, res: null }; + } + /** + * Fetches an ID token. + * @param targetAudience the audience for the fetched ID token. + */ + async fetchIdToken(targetAudience) { + const idTokenPath = `service-accounts/${this.serviceAccountEmail}/identity` + + `?format=full&audience=${targetAudience}`; + let idToken; + try { + const instanceOptions = { + property: idTokenPath, + }; + idToken = await gcpMetadata.instance(instanceOptions); + } + catch (e) { + if (e instanceof Error) { + e.message = `Could not fetch ID token: ${e.message}`; + } + throw e; + } + return idToken; + } + wrapError(e) { + const res = e.response; + if (res && res.status) { + e.status = res.status; + if (res.status === 403) { + e.message = + 'A Forbidden error was returned while attempting to retrieve an access ' + + 'token for the Compute Engine built-in service account. This may be because the Compute ' + + 'Engine instance does not have the correct permission scopes specified: ' + + e.message; + } + else if (res.status === 404) { + e.message = + 'A Not Found error was returned while attempting to retrieve an access' + + 'token for the Compute Engine built-in service account. This may be because the Compute ' + + 'Engine instance does not have any permission scopes specified: ' + + e.message; + } + } + } +} +exports.Compute = Compute; + + +/***/ }), + +/***/ 69157: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _DefaultAwsSecurityCredentialsSupplier_instances, _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken, _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName, _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials, _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get, _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DefaultAwsSecurityCredentialsSupplier = void 0; +/** + * Internal AWS security credentials supplier implementation used by {@link AwsClient} + * when a credential source is provided instead of a user defined supplier. + * The logic is summarized as: + * 1. If imdsv2_session_token_url is provided in the credential source, then + * fetch the aws session token and include it in the headers of the + * metadata requests. This is a requirement for IDMSv2 but optional + * for IDMSv1. + * 2. Retrieve AWS region from availability-zone. + * 3a. Check AWS credentials in environment variables. If not found, get + * from security-credentials endpoint. + * 3b. Get AWS credentials from security-credentials endpoint. In order + * to retrieve this, the AWS role needs to be determined by calling + * security-credentials endpoint without any argument. Then the + * credentials can be retrieved via: security-credentials/role_name + * 4. Generate the signed request to AWS STS GetCallerIdentity action. + * 5. Inject x-goog-cloud-target-resource into header and serialize the + * signed request. This will be the subject-token to pass to GCP STS. + */ +class DefaultAwsSecurityCredentialsSupplier { + /** + * Instantiates a new DefaultAwsSecurityCredentialsSupplier using information + * from the credential_source stored in the ADC file. + * @param opts The default aws security credentials supplier options object to + * build the supplier with. + */ + constructor(opts) { + _DefaultAwsSecurityCredentialsSupplier_instances.add(this); + this.regionUrl = opts.regionUrl; + this.securityCredentialsUrl = opts.securityCredentialsUrl; + this.imdsV2SessionTokenUrl = opts.imdsV2SessionTokenUrl; + this.additionalGaxiosOptions = opts.additionalGaxiosOptions; + } + /** + * Returns the active AWS region. This first checks to see if the region + * is available as an environment variable. If it is not, then the supplier + * will call the region URL. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link AwsClient}, contains the requested audience and subject token type + * for the external account identity. + * @return A promise that resolves with the AWS region string. + */ + async getAwsRegion(context) { + // Priority order for region determination: + // AWS_REGION > AWS_DEFAULT_REGION > metadata server. + if (__classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get)) { + return __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get); + } + const metadataHeaders = {}; + if (!__classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get) && this.imdsV2SessionTokenUrl) { + metadataHeaders['x-aws-ec2-metadata-token'] = + await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken).call(this, context.transporter); + } + if (!this.regionUrl) { + throw new Error('Unable to determine AWS region due to missing ' + + '"options.credential_source.region_url"'); + } + const opts = { + ...this.additionalGaxiosOptions, + url: this.regionUrl, + method: 'GET', + responseType: 'text', + headers: metadataHeaders, + }; + const response = await context.transporter.request(opts); + // Remove last character. For example, if us-east-2b is returned, + // the region would be us-east-2. + return response.data.substr(0, response.data.length - 1); + } + /** + * Returns AWS security credentials. This first checks to see if the credentials + * is available as environment variables. If it is not, then the supplier + * will call the security credentials URL. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link AwsClient}, contains the requested audience and subject token type + * for the external account identity. + * @return A promise that resolves with the AWS security credentials. + */ + async getAwsSecurityCredentials(context) { + // Check environment variables for permanent credentials first. + // https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html + if (__classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get)) { + return __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get); + } + const metadataHeaders = {}; + if (this.imdsV2SessionTokenUrl) { + metadataHeaders['x-aws-ec2-metadata-token'] = + await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken).call(this, context.transporter); + } + // Since the role on a VM can change, we don't need to cache it. + const roleName = await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName).call(this, metadataHeaders, context.transporter); + // Temporary credentials typically last for several hours. + // Expiration is returned in response. + // Consider future optimization of this logic to cache AWS tokens + // until their natural expiration. + const awsCreds = await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials).call(this, roleName, metadataHeaders, context.transporter); + return { + accessKeyId: awsCreds.AccessKeyId, + secretAccessKey: awsCreds.SecretAccessKey, + token: awsCreds.Token, + }; + } +} +exports.DefaultAwsSecurityCredentialsSupplier = DefaultAwsSecurityCredentialsSupplier; +_DefaultAwsSecurityCredentialsSupplier_instances = new WeakSet(), _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken = +/** + * @param transporter The transporter to use for requests. + * @return A promise that resolves with the IMDSv2 Session Token. + */ +async function _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken(transporter) { + const opts = { + ...this.additionalGaxiosOptions, + url: this.imdsV2SessionTokenUrl, + method: 'PUT', + responseType: 'text', + headers: { 'x-aws-ec2-metadata-token-ttl-seconds': '300' }, + }; + const response = await transporter.request(opts); + return response.data; +}, _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName = +/** + * @param headers The headers to be used in the metadata request. + * @param transporter The transporter to use for requests. + * @return A promise that resolves with the assigned role to the current + * AWS VM. This is needed for calling the security-credentials endpoint. + */ +async function _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName(headers, transporter) { + if (!this.securityCredentialsUrl) { + throw new Error('Unable to determine AWS role name due to missing ' + + '"options.credential_source.url"'); + } + const opts = { + ...this.additionalGaxiosOptions, + url: this.securityCredentialsUrl, + method: 'GET', + responseType: 'text', + headers: headers, + }; + const response = await transporter.request(opts); + return response.data; +}, _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials = +/** + * Retrieves the temporary AWS credentials by calling the security-credentials + * endpoint as specified in the `credential_source` object. + * @param roleName The role attached to the current VM. + * @param headers The headers to be used in the metadata request. + * @param transporter The transporter to use for requests. + * @return A promise that resolves with the temporary AWS credentials + * needed for creating the GetCallerIdentity signed request. + */ +async function _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials(roleName, headers, transporter) { + const response = await transporter.request({ + ...this.additionalGaxiosOptions, + url: `${this.securityCredentialsUrl}/${roleName}`, + responseType: 'json', + headers: headers, + }); + return response.data; +}, _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get = function _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get() { + // The AWS region can be provided through AWS_REGION or AWS_DEFAULT_REGION. + // Only one is required. + return (process.env['AWS_REGION'] || process.env['AWS_DEFAULT_REGION'] || null); +}, _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get = function _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get() { + // Both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are required. + if (process.env['AWS_ACCESS_KEY_ID'] && + process.env['AWS_SECRET_ACCESS_KEY']) { + return { + accessKeyId: process.env['AWS_ACCESS_KEY_ID'], + secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'], + token: process.env['AWS_SESSION_TOKEN'], + }; + } + return null; +}; + + +/***/ }), + +/***/ 77556: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DownscopedClient = exports.EXPIRATION_TIME_OFFSET = exports.MAX_ACCESS_BOUNDARY_RULES_COUNT = void 0; +const stream = __nccwpck_require__(2203); +const authclient_1 = __nccwpck_require__(34810); +const sts = __nccwpck_require__(121); +/** + * The required token exchange grant_type: rfc8693#section-2.1 + */ +const STS_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange'; +/** + * The requested token exchange requested_token_type: rfc8693#section-2.1 + */ +const STS_REQUEST_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token'; +/** + * The requested token exchange subject_token_type: rfc8693#section-2.1 + */ +const STS_SUBJECT_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token'; +/** + * The maximum number of access boundary rules a Credential Access Boundary + * can contain. + */ +exports.MAX_ACCESS_BOUNDARY_RULES_COUNT = 10; +/** + * Offset to take into account network delays and server clock skews. + */ +exports.EXPIRATION_TIME_OFFSET = 5 * 60 * 1000; +/** + * Defines a set of Google credentials that are downscoped from an existing set + * of Google OAuth2 credentials. This is useful to restrict the Identity and + * Access Management (IAM) permissions that a short-lived credential can use. + * The common pattern of usage is to have a token broker with elevated access + * generate these downscoped credentials from higher access source credentials + * and pass the downscoped short-lived access tokens to a token consumer via + * some secure authenticated channel for limited access to Google Cloud Storage + * resources. + */ +class DownscopedClient extends authclient_1.AuthClient { + /** + * Instantiates a downscoped client object using the provided source + * AuthClient and credential access boundary rules. + * To downscope permissions of a source AuthClient, a Credential Access + * Boundary that specifies which resources the new credential can access, as + * well as an upper bound on the permissions that are available on each + * resource, has to be defined. A downscoped client can then be instantiated + * using the source AuthClient and the Credential Access Boundary. + * @param authClient The source AuthClient to be downscoped based on the + * provided Credential Access Boundary rules. + * @param credentialAccessBoundary The Credential Access Boundary which + * contains a list of access boundary rules. Each rule contains information + * on the resource that the rule applies to, the upper bound of the + * permissions that are available on that resource and an optional + * condition to further restrict permissions. + * @param additionalOptions **DEPRECATED, set this in the provided `authClient`.** + * Optional additional behavior customization options. + * @param quotaProjectId **DEPRECATED, set this in the provided `authClient`.** + * Optional quota project id for setting up in the x-goog-user-project header. + */ + constructor(authClient, credentialAccessBoundary, additionalOptions, quotaProjectId) { + super({ ...additionalOptions, quotaProjectId }); + this.authClient = authClient; + this.credentialAccessBoundary = credentialAccessBoundary; + // Check 1-10 Access Boundary Rules are defined within Credential Access + // Boundary. + if (credentialAccessBoundary.accessBoundary.accessBoundaryRules.length === 0) { + throw new Error('At least one access boundary rule needs to be defined.'); + } + else if (credentialAccessBoundary.accessBoundary.accessBoundaryRules.length > + exports.MAX_ACCESS_BOUNDARY_RULES_COUNT) { + throw new Error('The provided access boundary has more than ' + + `${exports.MAX_ACCESS_BOUNDARY_RULES_COUNT} access boundary rules.`); + } + // Check at least one permission should be defined in each Access Boundary + // Rule. + for (const rule of credentialAccessBoundary.accessBoundary + .accessBoundaryRules) { + if (rule.availablePermissions.length === 0) { + throw new Error('At least one permission should be defined in access boundary rules.'); + } + } + this.stsCredential = new sts.StsCredentials(`https://sts.${this.universeDomain}/v1/token`); + this.cachedDownscopedAccessToken = null; + } + /** + * Provides a mechanism to inject Downscoped access tokens directly. + * The expiry_date field is required to facilitate determination of the token + * expiration which would make it easier for the token consumer to handle. + * @param credentials The Credentials object to set on the current client. + */ + setCredentials(credentials) { + if (!credentials.expiry_date) { + throw new Error('The access token expiry_date field is missing in the provided ' + + 'credentials.'); + } + super.setCredentials(credentials); + this.cachedDownscopedAccessToken = credentials; + } + async getAccessToken() { + // If the cached access token is unavailable or expired, force refresh. + // The Downscoped access token will be returned in + // DownscopedAccessTokenResponse format. + if (!this.cachedDownscopedAccessToken || + this.isExpired(this.cachedDownscopedAccessToken)) { + await this.refreshAccessTokenAsync(); + } + // Return Downscoped access token in DownscopedAccessTokenResponse format. + return { + token: this.cachedDownscopedAccessToken.access_token, + expirationTime: this.cachedDownscopedAccessToken.expiry_date, + res: this.cachedDownscopedAccessToken.res, + }; + } + /** + * The main authentication interface. It takes an optional url which when + * present is the endpoint being accessed, and returns a Promise which + * resolves with authorization header fields. + * + * The result has the form: + * { Authorization: 'Bearer ' } + */ + async getRequestHeaders() { + const accessTokenResponse = await this.getAccessToken(); + const headers = { + Authorization: `Bearer ${accessTokenResponse.token}`, + }; + return this.addSharedMetadataHeaders(headers); + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + /** + * Authenticates the provided HTTP request, processes it and resolves with the + * returned response. + * @param opts The HTTP request options. + * @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure + * @return A promise that resolves with the successful response. + */ + async requestAsync(opts, reAuthRetried = false) { + let response; + try { + const requestHeaders = await this.getRequestHeaders(); + opts.headers = opts.headers || {}; + if (requestHeaders && requestHeaders['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = + requestHeaders['x-goog-user-project']; + } + if (requestHeaders && requestHeaders.Authorization) { + opts.headers.Authorization = requestHeaders.Authorization; + } + response = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - forceRefreshOnFailure is true + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + this.forceRefreshOnFailure) { + await this.refreshAccessTokenAsync(); + return await this.requestAsync(opts, true); + } + } + throw e; + } + return response; + } + /** + * Forces token refresh, even if unexpired tokens are currently cached. + * GCP access tokens are retrieved from authclient object/source credential. + * Then GCP access tokens are exchanged for downscoped access tokens via the + * token exchange endpoint. + * @return A promise that resolves with the fresh downscoped access token. + */ + async refreshAccessTokenAsync() { + var _a; + // Retrieve GCP access token from source credential. + const subjectToken = (await this.authClient.getAccessToken()).token; + // Construct the STS credentials options. + const stsCredentialsOptions = { + grantType: STS_GRANT_TYPE, + requestedTokenType: STS_REQUEST_TOKEN_TYPE, + subjectToken: subjectToken, + subjectTokenType: STS_SUBJECT_TOKEN_TYPE, + }; + // Exchange the source AuthClient access token for a Downscoped access + // token. + const stsResponse = await this.stsCredential.exchangeToken(stsCredentialsOptions, undefined, this.credentialAccessBoundary); + /** + * The STS endpoint will only return the expiration time for the downscoped + * access token if the original access token represents a service account. + * The downscoped token's expiration time will always match the source + * credential expiration. When no expires_in is returned, we can copy the + * source credential's expiration time. + */ + const sourceCredExpireDate = ((_a = this.authClient.credentials) === null || _a === void 0 ? void 0 : _a.expiry_date) || null; + const expiryDate = stsResponse.expires_in + ? new Date().getTime() + stsResponse.expires_in * 1000 + : sourceCredExpireDate; + // Save response in cached access token. + this.cachedDownscopedAccessToken = { + access_token: stsResponse.access_token, + expiry_date: expiryDate, + res: stsResponse.res, + }; + // Save credentials. + this.credentials = {}; + Object.assign(this.credentials, this.cachedDownscopedAccessToken); + delete this.credentials.res; + // Trigger tokens event to notify external listeners. + this.emit('tokens', { + refresh_token: null, + expiry_date: this.cachedDownscopedAccessToken.expiry_date, + access_token: this.cachedDownscopedAccessToken.access_token, + token_type: 'Bearer', + id_token: null, + }); + // Return the cached access token. + return this.cachedDownscopedAccessToken; + } + /** + * Returns whether the provided credentials are expired or not. + * If there is no expiry time, assumes the token is not expired or expiring. + * @param downscopedAccessToken The credentials to check for expiration. + * @return Whether the credentials are expired or not. + */ + isExpired(downscopedAccessToken) { + const now = new Date().getTime(); + return downscopedAccessToken.expiry_date + ? now >= + downscopedAccessToken.expiry_date - this.eagerRefreshThresholdMillis + : false; + } +} +exports.DownscopedClient = DownscopedClient; + + +/***/ }), + +/***/ 60963: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GCPEnv = void 0; +exports.clear = clear; +exports.getEnv = getEnv; +const gcpMetadata = __nccwpck_require__(23046); +var GCPEnv; +(function (GCPEnv) { + GCPEnv["APP_ENGINE"] = "APP_ENGINE"; + GCPEnv["KUBERNETES_ENGINE"] = "KUBERNETES_ENGINE"; + GCPEnv["CLOUD_FUNCTIONS"] = "CLOUD_FUNCTIONS"; + GCPEnv["COMPUTE_ENGINE"] = "COMPUTE_ENGINE"; + GCPEnv["CLOUD_RUN"] = "CLOUD_RUN"; + GCPEnv["NONE"] = "NONE"; +})(GCPEnv || (exports.GCPEnv = GCPEnv = {})); +let envPromise; +function clear() { + envPromise = undefined; +} +async function getEnv() { + if (envPromise) { + return envPromise; + } + envPromise = getEnvMemoized(); + return envPromise; +} +async function getEnvMemoized() { + let env = GCPEnv.NONE; + if (isAppEngine()) { + env = GCPEnv.APP_ENGINE; + } + else if (isCloudFunction()) { + env = GCPEnv.CLOUD_FUNCTIONS; + } + else if (await isComputeEngine()) { + if (await isKubernetesEngine()) { + env = GCPEnv.KUBERNETES_ENGINE; + } + else if (isCloudRun()) { + env = GCPEnv.CLOUD_RUN; + } + else { + env = GCPEnv.COMPUTE_ENGINE; + } + } + else { + env = GCPEnv.NONE; + } + return env; +} +function isAppEngine() { + return !!(process.env.GAE_SERVICE || process.env.GAE_MODULE_NAME); +} +function isCloudFunction() { + return !!(process.env.FUNCTION_NAME || process.env.FUNCTION_TARGET); +} +/** + * This check only verifies that the environment is running knative. + * This must be run *after* checking for Kubernetes, otherwise it will + * return a false positive. + */ +function isCloudRun() { + return !!process.env.K_CONFIGURATION; +} +async function isKubernetesEngine() { + try { + await gcpMetadata.instance('attributes/cluster-name'); + return true; + } + catch (e) { + return false; + } +} +async function isComputeEngine() { + return gcpMetadata.isAvailable(); +} + + +/***/ }), + +/***/ 43247: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.InvalidSubjectTokenError = exports.InvalidMessageFieldError = exports.InvalidCodeFieldError = exports.InvalidTokenTypeFieldError = exports.InvalidExpirationTimeFieldError = exports.InvalidSuccessFieldError = exports.InvalidVersionFieldError = exports.ExecutableResponseError = exports.ExecutableResponse = void 0; +const SAML_SUBJECT_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:saml2'; +const OIDC_SUBJECT_TOKEN_TYPE1 = 'urn:ietf:params:oauth:token-type:id_token'; +const OIDC_SUBJECT_TOKEN_TYPE2 = 'urn:ietf:params:oauth:token-type:jwt'; +/** + * Defines the response of a 3rd party executable run by the pluggable auth client. + */ +class ExecutableResponse { + /** + * Instantiates an ExecutableResponse instance using the provided JSON object + * from the output of the executable. + * @param responseJson Response from a 3rd party executable, loaded from a + * run of the executable or a cached output file. + */ + constructor(responseJson) { + // Check that the required fields exist in the json response. + if (!responseJson.version) { + throw new InvalidVersionFieldError("Executable response must contain a 'version' field."); + } + if (responseJson.success === undefined) { + throw new InvalidSuccessFieldError("Executable response must contain a 'success' field."); + } + this.version = responseJson.version; + this.success = responseJson.success; + // Validate required fields for a successful response. + if (this.success) { + this.expirationTime = responseJson.expiration_time; + this.tokenType = responseJson.token_type; + // Validate token type field. + if (this.tokenType !== SAML_SUBJECT_TOKEN_TYPE && + this.tokenType !== OIDC_SUBJECT_TOKEN_TYPE1 && + this.tokenType !== OIDC_SUBJECT_TOKEN_TYPE2) { + throw new InvalidTokenTypeFieldError("Executable response must contain a 'token_type' field when successful " + + `and it must be one of ${OIDC_SUBJECT_TOKEN_TYPE1}, ${OIDC_SUBJECT_TOKEN_TYPE2}, or ${SAML_SUBJECT_TOKEN_TYPE}.`); + } + // Validate subject token. + if (this.tokenType === SAML_SUBJECT_TOKEN_TYPE) { + if (!responseJson.saml_response) { + throw new InvalidSubjectTokenError(`Executable response must contain a 'saml_response' field when token_type=${SAML_SUBJECT_TOKEN_TYPE}.`); + } + this.subjectToken = responseJson.saml_response; + } + else { + if (!responseJson.id_token) { + throw new InvalidSubjectTokenError("Executable response must contain a 'id_token' field when " + + `token_type=${OIDC_SUBJECT_TOKEN_TYPE1} or ${OIDC_SUBJECT_TOKEN_TYPE2}.`); + } + this.subjectToken = responseJson.id_token; + } + } + else { + // Both code and message must be provided for unsuccessful responses. + if (!responseJson.code) { + throw new InvalidCodeFieldError("Executable response must contain a 'code' field when unsuccessful."); + } + if (!responseJson.message) { + throw new InvalidMessageFieldError("Executable response must contain a 'message' field when unsuccessful."); + } + this.errorCode = responseJson.code; + this.errorMessage = responseJson.message; + } + } + /** + * @return A boolean representing if the response has a valid token. Returns + * true when the response was successful and the token is not expired. + */ + isValid() { + return !this.isExpired() && this.success; + } + /** + * @return A boolean representing if the response is expired. Returns true if the + * provided timeout has passed. + */ + isExpired() { + return (this.expirationTime !== undefined && + this.expirationTime < Math.round(Date.now() / 1000)); + } +} +exports.ExecutableResponse = ExecutableResponse; +/** + * An error thrown by the ExecutableResponse class. + */ +class ExecutableResponseError extends Error { + constructor(message) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} +exports.ExecutableResponseError = ExecutableResponseError; +/** + * An error thrown when the 'version' field in an executable response is missing or invalid. + */ +class InvalidVersionFieldError extends ExecutableResponseError { +} +exports.InvalidVersionFieldError = InvalidVersionFieldError; +/** + * An error thrown when the 'success' field in an executable response is missing or invalid. + */ +class InvalidSuccessFieldError extends ExecutableResponseError { +} +exports.InvalidSuccessFieldError = InvalidSuccessFieldError; +/** + * An error thrown when the 'expiration_time' field in an executable response is missing or invalid. + */ +class InvalidExpirationTimeFieldError extends ExecutableResponseError { +} +exports.InvalidExpirationTimeFieldError = InvalidExpirationTimeFieldError; +/** + * An error thrown when the 'token_type' field in an executable response is missing or invalid. + */ +class InvalidTokenTypeFieldError extends ExecutableResponseError { +} +exports.InvalidTokenTypeFieldError = InvalidTokenTypeFieldError; +/** + * An error thrown when the 'code' field in an executable response is missing or invalid. + */ +class InvalidCodeFieldError extends ExecutableResponseError { +} +exports.InvalidCodeFieldError = InvalidCodeFieldError; +/** + * An error thrown when the 'message' field in an executable response is missing or invalid. + */ +class InvalidMessageFieldError extends ExecutableResponseError { +} +exports.InvalidMessageFieldError = InvalidMessageFieldError; +/** + * An error thrown when the subject token in an executable response is missing or invalid. + */ +class InvalidSubjectTokenError extends ExecutableResponseError { +} +exports.InvalidSubjectTokenError = InvalidSubjectTokenError; + + +/***/ }), + +/***/ 34240: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ExternalAccountAuthorizedUserClient = exports.EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = void 0; +const authclient_1 = __nccwpck_require__(34810); +const oauth2common_1 = __nccwpck_require__(6653); +const gaxios_1 = __nccwpck_require__(97003); +const stream = __nccwpck_require__(2203); +const baseexternalclient_1 = __nccwpck_require__(142); +/** + * The credentials JSON file type for external account authorized user clients. + */ +exports.EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = 'external_account_authorized_user'; +const DEFAULT_TOKEN_URL = 'https://sts.{universeDomain}/v1/oauthtoken'; +/** + * Handler for token refresh requests sent to the token_url endpoint for external + * authorized user credentials. + */ +class ExternalAccountAuthorizedUserHandler extends oauth2common_1.OAuthClientAuthHandler { + /** + * Initializes an ExternalAccountAuthorizedUserHandler instance. + * @param url The URL of the token refresh endpoint. + * @param transporter The transporter to use for the refresh request. + * @param clientAuthentication The client authentication credentials to use + * for the refresh request. + */ + constructor(url, transporter, clientAuthentication) { + super(clientAuthentication); + this.url = url; + this.transporter = transporter; + } + /** + * Requests a new access token from the token_url endpoint using the provided + * refresh token. + * @param refreshToken The refresh token to use to generate a new access token. + * @param additionalHeaders Optional additional headers to pass along the + * request. + * @return A promise that resolves with the token refresh response containing + * the requested access token and its expiration time. + */ + async refreshToken(refreshToken, additionalHeaders) { + const values = new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: refreshToken, + }); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + ...additionalHeaders, + }; + const opts = { + ...ExternalAccountAuthorizedUserHandler.RETRY_CONFIG, + url: this.url, + method: 'POST', + headers, + data: values.toString(), + responseType: 'json', + }; + // Apply OAuth client authentication. + this.applyClientAuthenticationOptions(opts); + try { + const response = await this.transporter.request(opts); + // Successful response. + const tokenRefreshResponse = response.data; + tokenRefreshResponse.res = response; + return tokenRefreshResponse; + } + catch (error) { + // Translate error to OAuthError. + if (error instanceof gaxios_1.GaxiosError && error.response) { + throw (0, oauth2common_1.getErrorFromOAuthErrorResponse)(error.response.data, + // Preserve other fields from the original error. + error); + } + // Request could fail before the server responds. + throw error; + } + } +} +/** + * External Account Authorized User Client. This is used for OAuth2 credentials + * sourced using external identities through Workforce Identity Federation. + * Obtaining the initial access and refresh token can be done through the + * Google Cloud CLI. + */ +class ExternalAccountAuthorizedUserClient extends authclient_1.AuthClient { + /** + * Instantiates an ExternalAccountAuthorizedUserClient instances using the + * provided JSON object loaded from a credentials files. + * An error is throws if the credential is not valid. + * @param options The external account authorized user option object typically + * from the external accoutn authorized user JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + var _a; + super({ ...options, ...additionalOptions }); + if (options.universe_domain) { + this.universeDomain = options.universe_domain; + } + this.refreshToken = options.refresh_token; + const clientAuth = { + confidentialClientType: 'basic', + clientId: options.client_id, + clientSecret: options.client_secret, + }; + this.externalAccountAuthorizedUserHandler = + new ExternalAccountAuthorizedUserHandler((_a = options.token_url) !== null && _a !== void 0 ? _a : DEFAULT_TOKEN_URL.replace('{universeDomain}', this.universeDomain), this.transporter, clientAuth); + this.cachedAccessToken = null; + this.quotaProjectId = options.quota_project_id; + // As threshold could be zero, + // eagerRefreshThresholdMillis || EXPIRATION_TIME_OFFSET will override the + // zero value. + if (typeof (additionalOptions === null || additionalOptions === void 0 ? void 0 : additionalOptions.eagerRefreshThresholdMillis) !== 'number') { + this.eagerRefreshThresholdMillis = baseexternalclient_1.EXPIRATION_TIME_OFFSET; + } + else { + this.eagerRefreshThresholdMillis = additionalOptions + .eagerRefreshThresholdMillis; + } + this.forceRefreshOnFailure = !!(additionalOptions === null || additionalOptions === void 0 ? void 0 : additionalOptions.forceRefreshOnFailure); + } + async getAccessToken() { + // If cached access token is unavailable or expired, force refresh. + if (!this.cachedAccessToken || this.isExpired(this.cachedAccessToken)) { + await this.refreshAccessTokenAsync(); + } + // Return GCP access token in GetAccessTokenResponse format. + return { + token: this.cachedAccessToken.access_token, + res: this.cachedAccessToken.res, + }; + } + async getRequestHeaders() { + const accessTokenResponse = await this.getAccessToken(); + const headers = { + Authorization: `Bearer ${accessTokenResponse.token}`, + }; + return this.addSharedMetadataHeaders(headers); + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + /** + * Authenticates the provided HTTP request, processes it and resolves with the + * returned response. + * @param opts The HTTP request options. + * @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure. + * @return A promise that resolves with the successful response. + */ + async requestAsync(opts, reAuthRetried = false) { + let response; + try { + const requestHeaders = await this.getRequestHeaders(); + opts.headers = opts.headers || {}; + if (requestHeaders && requestHeaders['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = + requestHeaders['x-goog-user-project']; + } + if (requestHeaders && requestHeaders.Authorization) { + opts.headers.Authorization = requestHeaders.Authorization; + } + response = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - forceRefreshOnFailure is true + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + this.forceRefreshOnFailure) { + await this.refreshAccessTokenAsync(); + return await this.requestAsync(opts, true); + } + } + throw e; + } + return response; + } + /** + * Forces token refresh, even if unexpired tokens are currently cached. + * @return A promise that resolves with the refreshed credential. + */ + async refreshAccessTokenAsync() { + // Refresh the access token using the refresh token. + const refreshResponse = await this.externalAccountAuthorizedUserHandler.refreshToken(this.refreshToken); + this.cachedAccessToken = { + access_token: refreshResponse.access_token, + expiry_date: new Date().getTime() + refreshResponse.expires_in * 1000, + res: refreshResponse.res, + }; + if (refreshResponse.refresh_token !== undefined) { + this.refreshToken = refreshResponse.refresh_token; + } + return this.cachedAccessToken; + } + /** + * Returns whether the provided credentials are expired or not. + * If there is no expiry time, assumes the token is not expired or expiring. + * @param credentials The credentials to check for expiration. + * @return Whether the credentials are expired or not. + */ + isExpired(credentials) { + const now = new Date().getTime(); + return credentials.expiry_date + ? now >= credentials.expiry_date - this.eagerRefreshThresholdMillis + : false; + } +} +exports.ExternalAccountAuthorizedUserClient = ExternalAccountAuthorizedUserClient; + + +/***/ }), + +/***/ 88323: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ExternalAccountClient = void 0; +const baseexternalclient_1 = __nccwpck_require__(142); +const identitypoolclient_1 = __nccwpck_require__(29960); +const awsclient_1 = __nccwpck_require__(81261); +const pluggable_auth_client_1 = __nccwpck_require__(46077); +/** + * Dummy class with no constructor. Developers are expected to use fromJSON. + */ +class ExternalAccountClient { + constructor() { + throw new Error('ExternalAccountClients should be initialized via: ' + + 'ExternalAccountClient.fromJSON(), ' + + 'directly via explicit constructors, eg. ' + + 'new AwsClient(options), new IdentityPoolClient(options), new' + + 'PluggableAuthClientOptions, or via ' + + 'new GoogleAuth(options).getClient()'); + } + /** + * This static method will instantiate the + * corresponding type of external account credential depending on the + * underlying credential source. + * @param options The external account options object typically loaded + * from the external account JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + * @return A BaseExternalAccountClient instance or null if the options + * provided do not correspond to an external account credential. + */ + static fromJSON(options, additionalOptions) { + var _a, _b; + if (options && options.type === baseexternalclient_1.EXTERNAL_ACCOUNT_TYPE) { + if ((_a = options.credential_source) === null || _a === void 0 ? void 0 : _a.environment_id) { + return new awsclient_1.AwsClient(options, additionalOptions); + } + else if ((_b = options.credential_source) === null || _b === void 0 ? void 0 : _b.executable) { + return new pluggable_auth_client_1.PluggableAuthClient(options, additionalOptions); + } + else { + return new identitypoolclient_1.IdentityPoolClient(options, additionalOptions); + } + } + else { + return null; + } + } +} +exports.ExternalAccountClient = ExternalAccountClient; + + +/***/ }), + +/***/ 10932: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FileSubjectTokenSupplier = void 0; +const util_1 = __nccwpck_require__(39023); +const fs = __nccwpck_require__(79896); +// fs.readfile is undefined in browser karma tests causing +// `npm run browser-test` to fail as test.oauth2.ts imports this file via +// src/index.ts. +// Fallback to void function to avoid promisify throwing a TypeError. +const readFile = (0, util_1.promisify)((_a = fs.readFile) !== null && _a !== void 0 ? _a : (() => { })); +const realpath = (0, util_1.promisify)((_b = fs.realpath) !== null && _b !== void 0 ? _b : (() => { })); +const lstat = (0, util_1.promisify)((_c = fs.lstat) !== null && _c !== void 0 ? _c : (() => { })); +/** + * Internal subject token supplier implementation used when a file location + * is configured in the credential configuration used to build an {@link IdentityPoolClient} + */ +class FileSubjectTokenSupplier { + /** + * Instantiates a new file based subject token supplier. + * @param opts The file subject token supplier options to build the supplier + * with. + */ + constructor(opts) { + this.filePath = opts.filePath; + this.formatType = opts.formatType; + this.subjectTokenFieldName = opts.subjectTokenFieldName; + } + /** + * Returns the subject token stored at the file specified in the constructor. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link IdentityPoolClient}, contains the requested audience and subject + * token type for the external account identity. Not used. + */ + async getSubjectToken(context) { + // Make sure there is a file at the path. lstatSync will throw if there is + // nothing there. + let parsedFilePath = this.filePath; + try { + // Resolve path to actual file in case of symlink. Expect a thrown error + // if not resolvable. + parsedFilePath = await realpath(parsedFilePath); + if (!(await lstat(parsedFilePath)).isFile()) { + throw new Error(); + } + } + catch (err) { + if (err instanceof Error) { + err.message = `The file at ${parsedFilePath} does not exist, or it is not a file. ${err.message}`; + } + throw err; + } + let subjectToken; + const rawText = await readFile(parsedFilePath, { encoding: 'utf8' }); + if (this.formatType === 'text') { + subjectToken = rawText; + } + else if (this.formatType === 'json' && this.subjectTokenFieldName) { + const json = JSON.parse(rawText); + subjectToken = json[this.subjectTokenFieldName]; + } + if (!subjectToken) { + throw new Error('Unable to parse the subject_token from the credential_source file'); + } + return subjectToken; + } +} +exports.FileSubjectTokenSupplier = FileSubjectTokenSupplier; + + +/***/ }), + +/***/ 95934: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _GoogleAuth_instances, _GoogleAuth_pendingAuthClient, _GoogleAuth_prepareAndCacheClient, _GoogleAuth_determineClient; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GoogleAuth = exports.GoogleAuthExceptionMessages = exports.CLOUD_SDK_CLIENT_ID = void 0; +const child_process_1 = __nccwpck_require__(35317); +const fs = __nccwpck_require__(79896); +const gcpMetadata = __nccwpck_require__(23046); +const os = __nccwpck_require__(70857); +const path = __nccwpck_require__(16928); +const crypto_1 = __nccwpck_require__(88851); +const transporters_1 = __nccwpck_require__(67633); +const computeclient_1 = __nccwpck_require__(20977); +const idtokenclient_1 = __nccwpck_require__(12718); +const envDetect_1 = __nccwpck_require__(60963); +const jwtclient_1 = __nccwpck_require__(75277); +const refreshclient_1 = __nccwpck_require__(99807); +const impersonated_1 = __nccwpck_require__(39964); +const externalclient_1 = __nccwpck_require__(88323); +const baseexternalclient_1 = __nccwpck_require__(142); +const authclient_1 = __nccwpck_require__(34810); +const externalAccountAuthorizedUserClient_1 = __nccwpck_require__(34240); +const util_1 = __nccwpck_require__(37870); +exports.CLOUD_SDK_CLIENT_ID = '764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com'; +exports.GoogleAuthExceptionMessages = { + API_KEY_WITH_CREDENTIALS: 'API Keys and Credentials are mutually exclusive authentication methods and cannot be used together.', + NO_PROJECT_ID_FOUND: 'Unable to detect a Project Id in the current environment. \n' + + 'To learn more about authentication and Google APIs, visit: \n' + + 'https://cloud.google.com/docs/authentication/getting-started', + NO_CREDENTIALS_FOUND: 'Unable to find credentials in current environment. \n' + + 'To learn more about authentication and Google APIs, visit: \n' + + 'https://cloud.google.com/docs/authentication/getting-started', + NO_ADC_FOUND: 'Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.', + NO_UNIVERSE_DOMAIN_FOUND: 'Unable to detect a Universe Domain in the current environment.\n' + + 'To learn more about Universe Domain retrieval, visit: \n' + + 'https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys', +}; +class GoogleAuth { + // Note: this properly is only public to satisfy unit tests. + // https://github.com/Microsoft/TypeScript/issues/5228 + get isGCE() { + return this.checkIsGCE; + } + /** + * Configuration is resolved in the following order of precedence: + * - {@link GoogleAuthOptions.credentials `credentials`} + * - {@link GoogleAuthOptions.keyFilename `keyFilename`} + * - {@link GoogleAuthOptions.keyFile `keyFile`} + * + * {@link GoogleAuthOptions.clientOptions `clientOptions`} are passed to the + * {@link AuthClient `AuthClient`s}. + * + * @param opts + */ + constructor(opts = {}) { + _GoogleAuth_instances.add(this); + /** + * Caches a value indicating whether the auth layer is running on Google + * Compute Engine. + * @private + */ + this.checkIsGCE = undefined; + // To save the contents of the JSON credential file + this.jsonContent = null; + this.cachedCredential = null; + /** + * A pending {@link AuthClient}. Used for concurrent {@link GoogleAuth.getClient} calls. + */ + _GoogleAuth_pendingAuthClient.set(this, null); + this.clientOptions = {}; + this._cachedProjectId = opts.projectId || null; + this.cachedCredential = opts.authClient || null; + this.keyFilename = opts.keyFilename || opts.keyFile; + this.scopes = opts.scopes; + this.clientOptions = opts.clientOptions || {}; + this.jsonContent = opts.credentials || null; + this.apiKey = opts.apiKey || this.clientOptions.apiKey || null; + // Cannot use both API Key + Credentials + if (this.apiKey && (this.jsonContent || this.clientOptions.credentials)) { + throw new RangeError(exports.GoogleAuthExceptionMessages.API_KEY_WITH_CREDENTIALS); + } + if (opts.universeDomain) { + this.clientOptions.universeDomain = opts.universeDomain; + } + } + // GAPIC client libraries should always use self-signed JWTs. The following + // variables are set on the JWT client in order to indicate the type of library, + // and sign the JWT with the correct audience and scopes (if not supplied). + setGapicJWTValues(client) { + client.defaultServicePath = this.defaultServicePath; + client.useJWTAccessWithScope = this.useJWTAccessWithScope; + client.defaultScopes = this.defaultScopes; + } + getProjectId(callback) { + if (callback) { + this.getProjectIdAsync().then(r => callback(null, r), callback); + } + else { + return this.getProjectIdAsync(); + } + } + /** + * A temporary method for internal `getProjectId` usages where `null` is + * acceptable. In a future major release, `getProjectId` should return `null` + * (as the `Promise` base signature describes) and this private + * method should be removed. + * + * @returns Promise that resolves with project id (or `null`) + */ + async getProjectIdOptional() { + try { + return await this.getProjectId(); + } + catch (e) { + if (e instanceof Error && + e.message === exports.GoogleAuthExceptionMessages.NO_PROJECT_ID_FOUND) { + return null; + } + else { + throw e; + } + } + } + /** + * A private method for finding and caching a projectId. + * + * Supports environments in order of precedence: + * - GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variable + * - GOOGLE_APPLICATION_CREDENTIALS JSON file + * - Cloud SDK: `gcloud config config-helper --format json` + * - GCE project ID from metadata server + * + * @returns projectId + */ + async findAndCacheProjectId() { + let projectId = null; + projectId || (projectId = await this.getProductionProjectId()); + projectId || (projectId = await this.getFileProjectId()); + projectId || (projectId = await this.getDefaultServiceProjectId()); + projectId || (projectId = await this.getGCEProjectId()); + projectId || (projectId = await this.getExternalAccountClientProjectId()); + if (projectId) { + this._cachedProjectId = projectId; + return projectId; + } + else { + throw new Error(exports.GoogleAuthExceptionMessages.NO_PROJECT_ID_FOUND); + } + } + async getProjectIdAsync() { + if (this._cachedProjectId) { + return this._cachedProjectId; + } + if (!this._findProjectIdPromise) { + this._findProjectIdPromise = this.findAndCacheProjectId(); + } + return this._findProjectIdPromise; + } + /** + * Retrieves a universe domain from the metadata server via + * {@link gcpMetadata.universe}. + * + * @returns a universe domain + */ + async getUniverseDomainFromMetadataServer() { + var _a; + let universeDomain; + try { + universeDomain = await gcpMetadata.universe('universe-domain'); + universeDomain || (universeDomain = authclient_1.DEFAULT_UNIVERSE); + } + catch (e) { + if (e && ((_a = e === null || e === void 0 ? void 0 : e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) { + universeDomain = authclient_1.DEFAULT_UNIVERSE; + } + else { + throw e; + } + } + return universeDomain; + } + /** + * Retrieves, caches, and returns the universe domain in the following order + * of precedence: + * - The universe domain in {@link GoogleAuth.clientOptions} + * - An existing or ADC {@link AuthClient}'s universe domain + * - {@link gcpMetadata.universe}, if {@link Compute} client + * + * @returns The universe domain + */ + async getUniverseDomain() { + let universeDomain = (0, util_1.originalOrCamelOptions)(this.clientOptions).get('universe_domain'); + try { + universeDomain !== null && universeDomain !== void 0 ? universeDomain : (universeDomain = (await this.getClient()).universeDomain); + } + catch (_a) { + // client or ADC is not available + universeDomain !== null && universeDomain !== void 0 ? universeDomain : (universeDomain = authclient_1.DEFAULT_UNIVERSE); + } + return universeDomain; + } + /** + * @returns Any scopes (user-specified or default scopes specified by the + * client library) that need to be set on the current Auth client. + */ + getAnyScopes() { + return this.scopes || this.defaultScopes; + } + getApplicationDefault(optionsOrCallback = {}, callback) { + let options; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else { + options = optionsOrCallback; + } + if (callback) { + this.getApplicationDefaultAsync(options).then(r => callback(null, r.credential, r.projectId), callback); + } + else { + return this.getApplicationDefaultAsync(options); + } + } + async getApplicationDefaultAsync(options = {}) { + // If we've already got a cached credential, return it. + // This will also preserve one's configured quota project, in case they + // set one directly on the credential previously. + if (this.cachedCredential) { + // cache, while preserving existing quota project preferences + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, this.cachedCredential, null); + } + let credential; + // Check for the existence of a local environment variable pointing to the + // location of the credential file. This is typically used in local + // developer scenarios. + credential = + await this._tryGetApplicationCredentialsFromEnvironmentVariable(options); + if (credential) { + if (credential instanceof jwtclient_1.JWT) { + credential.scopes = this.scopes; + } + else if (credential instanceof baseexternalclient_1.BaseExternalAccountClient) { + credential.scopes = this.getAnyScopes(); + } + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, credential); + } + // Look in the well-known credential file location. + credential = + await this._tryGetApplicationCredentialsFromWellKnownFile(options); + if (credential) { + if (credential instanceof jwtclient_1.JWT) { + credential.scopes = this.scopes; + } + else if (credential instanceof baseexternalclient_1.BaseExternalAccountClient) { + credential.scopes = this.getAnyScopes(); + } + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, credential); + } + // Determine if we're running on GCE. + if (await this._checkIsGCE()) { + options.scopes = this.getAnyScopes(); + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, new computeclient_1.Compute(options)); + } + throw new Error(exports.GoogleAuthExceptionMessages.NO_ADC_FOUND); + } + /** + * Determines whether the auth layer is running on Google Compute Engine. + * Checks for GCP Residency, then fallback to checking if metadata server + * is available. + * + * @returns A promise that resolves with the boolean. + * @api private + */ + async _checkIsGCE() { + if (this.checkIsGCE === undefined) { + this.checkIsGCE = + gcpMetadata.getGCPResidency() || (await gcpMetadata.isAvailable()); + } + return this.checkIsGCE; + } + /** + * Attempts to load default credentials from the environment variable path.. + * @returns Promise that resolves with the OAuth2Client or null. + * @api private + */ + async _tryGetApplicationCredentialsFromEnvironmentVariable(options) { + const credentialsPath = process.env['GOOGLE_APPLICATION_CREDENTIALS'] || + process.env['google_application_credentials']; + if (!credentialsPath || credentialsPath.length === 0) { + return null; + } + try { + return this._getApplicationCredentialsFromFilePath(credentialsPath, options); + } + catch (e) { + if (e instanceof Error) { + e.message = `Unable to read the credential file specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable: ${e.message}`; + } + throw e; + } + } + /** + * Attempts to load default credentials from a well-known file location + * @return Promise that resolves with the OAuth2Client or null. + * @api private + */ + async _tryGetApplicationCredentialsFromWellKnownFile(options) { + // First, figure out the location of the file, depending upon the OS type. + let location = null; + if (this._isWindows()) { + // Windows + location = process.env['APPDATA']; + } + else { + // Linux or Mac + const home = process.env['HOME']; + if (home) { + location = path.join(home, '.config'); + } + } + // If we found the root path, expand it. + if (location) { + location = path.join(location, 'gcloud', 'application_default_credentials.json'); + if (!fs.existsSync(location)) { + location = null; + } + } + // The file does not exist. + if (!location) { + return null; + } + // The file seems to exist. Try to use it. + const client = await this._getApplicationCredentialsFromFilePath(location, options); + return client; + } + /** + * Attempts to load default credentials from a file at the given path.. + * @param filePath The path to the file to read. + * @returns Promise that resolves with the OAuth2Client + * @api private + */ + async _getApplicationCredentialsFromFilePath(filePath, options = {}) { + // Make sure the path looks like a string. + if (!filePath || filePath.length === 0) { + throw new Error('The file path is invalid.'); + } + // Make sure there is a file at the path. lstatSync will throw if there is + // nothing there. + try { + // Resolve path to actual file in case of symlink. Expect a thrown error + // if not resolvable. + filePath = fs.realpathSync(filePath); + if (!fs.lstatSync(filePath).isFile()) { + throw new Error(); + } + } + catch (err) { + if (err instanceof Error) { + err.message = `The file at ${filePath} does not exist, or it is not a file. ${err.message}`; + } + throw err; + } + // Now open a read stream on the file, and parse it. + const readStream = fs.createReadStream(filePath); + return this.fromStream(readStream, options); + } + /** + * Create a credentials instance using a given impersonated input options. + * @param json The impersonated input object. + * @returns JWT or UserRefresh Client with data + */ + fromImpersonatedJSON(json) { + var _a, _b, _c, _d; + if (!json) { + throw new Error('Must pass in a JSON object containing an impersonated refresh token'); + } + if (json.type !== impersonated_1.IMPERSONATED_ACCOUNT_TYPE) { + throw new Error(`The incoming JSON object does not have the "${impersonated_1.IMPERSONATED_ACCOUNT_TYPE}" type`); + } + if (!json.source_credentials) { + throw new Error('The incoming JSON object does not contain a source_credentials field'); + } + if (!json.service_account_impersonation_url) { + throw new Error('The incoming JSON object does not contain a service_account_impersonation_url field'); + } + const sourceClient = this.fromJSON(json.source_credentials); + if (((_a = json.service_account_impersonation_url) === null || _a === void 0 ? void 0 : _a.length) > 256) { + /** + * Prevents DOS attacks. + * @see {@link https://github.com/googleapis/google-auth-library-nodejs/security/code-scanning/85} + **/ + throw new RangeError(`Target principal is too long: ${json.service_account_impersonation_url}`); + } + // Extract service account from service_account_impersonation_url + const targetPrincipal = (_c = (_b = /(?[^/]+):(generateAccessToken|generateIdToken)$/.exec(json.service_account_impersonation_url)) === null || _b === void 0 ? void 0 : _b.groups) === null || _c === void 0 ? void 0 : _c.target; + if (!targetPrincipal) { + throw new RangeError(`Cannot extract target principal from ${json.service_account_impersonation_url}`); + } + const targetScopes = (_d = this.getAnyScopes()) !== null && _d !== void 0 ? _d : []; + return new impersonated_1.Impersonated({ + ...json, + sourceClient, + targetPrincipal, + targetScopes: Array.isArray(targetScopes) ? targetScopes : [targetScopes], + }); + } + /** + * Create a credentials instance using the given input options. + * This client is not cached. + * + * **Important**: If you accept a credential configuration (credential JSON/File/Stream) from an external source for authentication to Google Cloud, you must validate it before providing it to any Google API or library. Providing an unvalidated credential configuration to Google APIs can compromise the security of your systems and data. For more information, refer to {@link https://cloud.google.com/docs/authentication/external/externally-sourced-credentials Validate credential configurations from external sources}. + * + * @param json The input object. + * @param options The JWT or UserRefresh options for the client + * @returns JWT or UserRefresh Client with data + */ + fromJSON(json, options = {}) { + let client; + // user's preferred universe domain + const preferredUniverseDomain = (0, util_1.originalOrCamelOptions)(options).get('universe_domain'); + if (json.type === refreshclient_1.USER_REFRESH_ACCOUNT_TYPE) { + client = new refreshclient_1.UserRefreshClient(options); + client.fromJSON(json); + } + else if (json.type === impersonated_1.IMPERSONATED_ACCOUNT_TYPE) { + client = this.fromImpersonatedJSON(json); + } + else if (json.type === baseexternalclient_1.EXTERNAL_ACCOUNT_TYPE) { + client = externalclient_1.ExternalAccountClient.fromJSON(json, options); + client.scopes = this.getAnyScopes(); + } + else if (json.type === externalAccountAuthorizedUserClient_1.EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE) { + client = new externalAccountAuthorizedUserClient_1.ExternalAccountAuthorizedUserClient(json, options); + } + else { + options.scopes = this.scopes; + client = new jwtclient_1.JWT(options); + this.setGapicJWTValues(client); + client.fromJSON(json); + } + if (preferredUniverseDomain) { + client.universeDomain = preferredUniverseDomain; + } + return client; + } + /** + * Return a JWT or UserRefreshClient from JavaScript object, caching both the + * object used to instantiate and the client. + * @param json The input object. + * @param options The JWT or UserRefresh options for the client + * @returns JWT or UserRefresh Client with data + */ + _cacheClientFromJSON(json, options) { + const client = this.fromJSON(json, options); + // cache both raw data used to instantiate client and client itself. + this.jsonContent = json; + this.cachedCredential = client; + return client; + } + fromStream(inputStream, optionsOrCallback = {}, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else { + options = optionsOrCallback; + } + if (callback) { + this.fromStreamAsync(inputStream, options).then(r => callback(null, r), callback); + } + else { + return this.fromStreamAsync(inputStream, options); + } + } + fromStreamAsync(inputStream, options) { + return new Promise((resolve, reject) => { + if (!inputStream) { + throw new Error('Must pass in a stream containing the Google auth settings.'); + } + const chunks = []; + inputStream + .setEncoding('utf8') + .on('error', reject) + .on('data', chunk => chunks.push(chunk)) + .on('end', () => { + try { + try { + const data = JSON.parse(chunks.join('')); + const r = this._cacheClientFromJSON(data, options); + return resolve(r); + } + catch (err) { + // If we failed parsing this.keyFileName, assume that it + // is a PEM or p12 certificate: + if (!this.keyFilename) + throw err; + const client = new jwtclient_1.JWT({ + ...this.clientOptions, + keyFile: this.keyFilename, + }); + this.cachedCredential = client; + this.setGapicJWTValues(client); + return resolve(client); + } + } + catch (err) { + return reject(err); + } + }); + }); + } + /** + * Create a credentials instance using the given API key string. + * The created client is not cached. In order to create and cache it use the {@link GoogleAuth.getClient `getClient`} method after first providing an {@link GoogleAuth.apiKey `apiKey`}. + * + * @param apiKey The API key string + * @param options An optional options object. + * @returns A JWT loaded from the key + */ + fromAPIKey(apiKey, options = {}) { + return new jwtclient_1.JWT({ ...options, apiKey }); + } + /** + * Determines whether the current operating system is Windows. + * @api private + */ + _isWindows() { + const sys = os.platform(); + if (sys && sys.length >= 3) { + if (sys.substring(0, 3).toLowerCase() === 'win') { + return true; + } + } + return false; + } + /** + * Run the Google Cloud SDK command that prints the default project ID + */ + async getDefaultServiceProjectId() { + return new Promise(resolve => { + (0, child_process_1.exec)('gcloud config config-helper --format json', (err, stdout) => { + if (!err && stdout) { + try { + const projectId = JSON.parse(stdout).configuration.properties.core.project; + resolve(projectId); + return; + } + catch (e) { + // ignore errors + } + } + resolve(null); + }); + }); + } + /** + * Loads the project id from environment variables. + * @api private + */ + getProductionProjectId() { + return (process.env['GCLOUD_PROJECT'] || + process.env['GOOGLE_CLOUD_PROJECT'] || + process.env['gcloud_project'] || + process.env['google_cloud_project']); + } + /** + * Loads the project id from the GOOGLE_APPLICATION_CREDENTIALS json file. + * @api private + */ + async getFileProjectId() { + if (this.cachedCredential) { + // Try to read the project ID from the cached credentials file + return this.cachedCredential.projectId; + } + // Ensure the projectId is loaded from the keyFile if available. + if (this.keyFilename) { + const creds = await this.getClient(); + if (creds && creds.projectId) { + return creds.projectId; + } + } + // Try to load a credentials file and read its project ID + const r = await this._tryGetApplicationCredentialsFromEnvironmentVariable(); + if (r) { + return r.projectId; + } + else { + return null; + } + } + /** + * Gets the project ID from external account client if available. + */ + async getExternalAccountClientProjectId() { + if (!this.jsonContent || this.jsonContent.type !== baseexternalclient_1.EXTERNAL_ACCOUNT_TYPE) { + return null; + } + const creds = await this.getClient(); + // Do not suppress the underlying error, as the error could contain helpful + // information for debugging and fixing. This is especially true for + // external account creds as in order to get the project ID, the following + // operations have to succeed: + // 1. Valid credentials file should be supplied. + // 2. Ability to retrieve access tokens from STS token exchange API. + // 3. Ability to exchange for service account impersonated credentials (if + // enabled). + // 4. Ability to get project info using the access token from step 2 or 3. + // Without surfacing the error, it is harder for developers to determine + // which step went wrong. + return await creds.getProjectId(); + } + /** + * Gets the Compute Engine project ID if it can be inferred. + */ + async getGCEProjectId() { + try { + const r = await gcpMetadata.project('project-id'); + return r; + } + catch (e) { + // Ignore any errors + return null; + } + } + getCredentials(callback) { + if (callback) { + this.getCredentialsAsync().then(r => callback(null, r), callback); + } + else { + return this.getCredentialsAsync(); + } + } + async getCredentialsAsync() { + const client = await this.getClient(); + if (client instanceof impersonated_1.Impersonated) { + return { client_email: client.getTargetPrincipal() }; + } + if (client instanceof baseexternalclient_1.BaseExternalAccountClient) { + const serviceAccountEmail = client.getServiceAccountEmail(); + if (serviceAccountEmail) { + return { + client_email: serviceAccountEmail, + universe_domain: client.universeDomain, + }; + } + } + if (this.jsonContent) { + return { + client_email: this.jsonContent.client_email, + private_key: this.jsonContent.private_key, + universe_domain: this.jsonContent.universe_domain, + }; + } + if (await this._checkIsGCE()) { + const [client_email, universe_domain] = await Promise.all([ + gcpMetadata.instance('service-accounts/default/email'), + this.getUniverseDomain(), + ]); + return { client_email, universe_domain }; + } + throw new Error(exports.GoogleAuthExceptionMessages.NO_CREDENTIALS_FOUND); + } + /** + * Automatically obtain an {@link AuthClient `AuthClient`} based on the + * provided configuration. If no options were passed, use Application + * Default Credentials. + */ + async getClient() { + if (this.cachedCredential) { + return this.cachedCredential; + } + // Use an existing auth client request, or cache a new one + __classPrivateFieldSet(this, _GoogleAuth_pendingAuthClient, __classPrivateFieldGet(this, _GoogleAuth_pendingAuthClient, "f") || __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_determineClient).call(this), "f"); + try { + return await __classPrivateFieldGet(this, _GoogleAuth_pendingAuthClient, "f"); + } + finally { + // reset the pending auth client in case it is changed later + __classPrivateFieldSet(this, _GoogleAuth_pendingAuthClient, null, "f"); + } + } + /** + * Creates a client which will fetch an ID token for authorization. + * @param targetAudience the audience for the fetched ID token. + * @returns IdTokenClient for making HTTP calls authenticated with ID tokens. + */ + async getIdTokenClient(targetAudience) { + const client = await this.getClient(); + if (!('fetchIdToken' in client)) { + throw new Error('Cannot fetch ID token in this environment, use GCE or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to a service account credentials JSON file.'); + } + return new idtokenclient_1.IdTokenClient({ targetAudience, idTokenProvider: client }); + } + /** + * Automatically obtain application default credentials, and return + * an access token for making requests. + */ + async getAccessToken() { + const client = await this.getClient(); + return (await client.getAccessToken()).token; + } + /** + * Obtain the HTTP headers that will provide authorization for a given + * request. + */ + async getRequestHeaders(url) { + const client = await this.getClient(); + return client.getRequestHeaders(url); + } + /** + * Obtain credentials for a request, then attach the appropriate headers to + * the request options. + * @param opts Axios or Request options on which to attach the headers + */ + async authorizeRequest(opts) { + opts = opts || {}; + const url = opts.url || opts.uri; + const client = await this.getClient(); + const headers = await client.getRequestHeaders(url); + opts.headers = Object.assign(opts.headers || {}, headers); + return opts; + } + /** + * Automatically obtain application default credentials, and make an + * HTTP request using the given options. + * @param opts Axios request options for the HTTP request. + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async request(opts) { + const client = await this.getClient(); + return client.request(opts); + } + /** + * Determine the compute environment in which the code is running. + */ + getEnv() { + return (0, envDetect_1.getEnv)(); + } + /** + * Sign the given data with the current private key, or go out + * to the IAM API to sign it. + * @param data The data to be signed. + * @param endpoint A custom endpoint to use. + * + * @example + * ``` + * sign('data', 'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/'); + * ``` + */ + async sign(data, endpoint) { + const client = await this.getClient(); + const universe = await this.getUniverseDomain(); + endpoint = + endpoint || + `https://iamcredentials.${universe}/v1/projects/-/serviceAccounts/`; + if (client instanceof impersonated_1.Impersonated) { + const signed = await client.sign(data); + return signed.signedBlob; + } + const crypto = (0, crypto_1.createCrypto)(); + if (client instanceof jwtclient_1.JWT && client.key) { + const sign = await crypto.sign(client.key, data); + return sign; + } + const creds = await this.getCredentials(); + if (!creds.client_email) { + throw new Error('Cannot sign data without `client_email`.'); + } + return this.signBlob(crypto, creds.client_email, data, endpoint); + } + async signBlob(crypto, emailOrUniqueId, data, endpoint) { + const url = new URL(endpoint + `${emailOrUniqueId}:signBlob`); + const res = await this.request({ + method: 'POST', + url: url.href, + data: { + payload: crypto.encodeBase64StringUtf8(data), + }, + retry: true, + retryConfig: { + httpMethodsToRetry: ['POST'], + }, + }); + return res.data.signedBlob; + } +} +exports.GoogleAuth = GoogleAuth; +_GoogleAuth_pendingAuthClient = new WeakMap(), _GoogleAuth_instances = new WeakSet(), _GoogleAuth_prepareAndCacheClient = async function _GoogleAuth_prepareAndCacheClient(credential, quotaProjectIdOverride = process.env['GOOGLE_CLOUD_QUOTA_PROJECT'] || null) { + const projectId = await this.getProjectIdOptional(); + if (quotaProjectIdOverride) { + credential.quotaProjectId = quotaProjectIdOverride; + } + this.cachedCredential = credential; + return { credential, projectId }; +}, _GoogleAuth_determineClient = async function _GoogleAuth_determineClient() { + if (this.jsonContent) { + return this._cacheClientFromJSON(this.jsonContent, this.clientOptions); + } + else if (this.keyFilename) { + const filePath = path.resolve(this.keyFilename); + const stream = fs.createReadStream(filePath); + return await this.fromStreamAsync(stream, this.clientOptions); + } + else if (this.apiKey) { + const client = await this.fromAPIKey(this.apiKey, this.clientOptions); + client.scopes = this.scopes; + const { credential } = await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, client); + return credential; + } + else { + const { credential } = await this.getApplicationDefaultAsync(this.clientOptions); + return credential; + } +}; +/** + * Export DefaultTransporter as a static property of the class. + */ +GoogleAuth.DefaultTransporter = transporters_1.DefaultTransporter; + + +/***/ }), + +/***/ 89390: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2014 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IAMAuth = void 0; +class IAMAuth { + /** + * IAM credentials. + * + * @param selector the iam authority selector + * @param token the token + * @constructor + */ + constructor(selector, token) { + this.selector = selector; + this.token = token; + this.selector = selector; + this.token = token; + } + /** + * Acquire the HTTP headers required to make an authenticated request. + */ + getRequestHeaders() { + return { + 'x-goog-iam-authority-selector': this.selector, + 'x-goog-iam-authorization-token': this.token, + }; + } +} +exports.IAMAuth = IAMAuth; + + +/***/ }), + +/***/ 29960: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IdentityPoolClient = void 0; +const baseexternalclient_1 = __nccwpck_require__(142); +const util_1 = __nccwpck_require__(37870); +const filesubjecttokensupplier_1 = __nccwpck_require__(10932); +const urlsubjecttokensupplier_1 = __nccwpck_require__(24627); +/** + * Defines the Url-sourced and file-sourced external account clients mainly + * used for K8s and Azure workloads. + */ +class IdentityPoolClient extends baseexternalclient_1.BaseExternalAccountClient { + /** + * Instantiate an IdentityPoolClient instance using the provided JSON + * object loaded from an external account credentials file. + * An error is thrown if the credential is not a valid file-sourced or + * url-sourced credential or a workforce pool user project is provided + * with a non workforce audience. + * @param options The external account options object typically loaded + * from the external account JSON credential file. The camelCased options + * are aliases for the snake_cased options. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + super(options, additionalOptions); + const opts = (0, util_1.originalOrCamelOptions)(options); + const credentialSource = opts.get('credential_source'); + const subjectTokenSupplier = opts.get('subject_token_supplier'); + // Validate credential sourcing configuration. + if (!credentialSource && !subjectTokenSupplier) { + throw new Error('A credential source or subject token supplier must be specified.'); + } + if (credentialSource && subjectTokenSupplier) { + throw new Error('Only one of credential source or subject token supplier can be specified.'); + } + if (subjectTokenSupplier) { + this.subjectTokenSupplier = subjectTokenSupplier; + this.credentialSourceType = 'programmatic'; + } + else { + const credentialSourceOpts = (0, util_1.originalOrCamelOptions)(credentialSource); + const formatOpts = (0, util_1.originalOrCamelOptions)(credentialSourceOpts.get('format')); + // Text is the default format type. + const formatType = formatOpts.get('type') || 'text'; + const formatSubjectTokenFieldName = formatOpts.get('subject_token_field_name'); + if (formatType !== 'json' && formatType !== 'text') { + throw new Error(`Invalid credential_source format "${formatType}"`); + } + if (formatType === 'json' && !formatSubjectTokenFieldName) { + throw new Error('Missing subject_token_field_name for JSON credential_source format'); + } + const file = credentialSourceOpts.get('file'); + const url = credentialSourceOpts.get('url'); + const headers = credentialSourceOpts.get('headers'); + if (file && url) { + throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.'); + } + else if (file && !url) { + this.credentialSourceType = 'file'; + this.subjectTokenSupplier = new filesubjecttokensupplier_1.FileSubjectTokenSupplier({ + filePath: file, + formatType: formatType, + subjectTokenFieldName: formatSubjectTokenFieldName, + }); + } + else if (!file && url) { + this.credentialSourceType = 'url'; + this.subjectTokenSupplier = new urlsubjecttokensupplier_1.UrlSubjectTokenSupplier({ + url: url, + formatType: formatType, + subjectTokenFieldName: formatSubjectTokenFieldName, + headers: headers, + additionalGaxiosOptions: IdentityPoolClient.RETRY_CONFIG, + }); + } + else { + throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.'); + } + } + } + /** + * Triggered when a external subject token is needed to be exchanged for a GCP + * access token via GCP STS endpoint. Gets a subject token by calling + * the configured {@link SubjectTokenSupplier} + * @return A promise that resolves with the external subject token. + */ + async retrieveSubjectToken() { + return this.subjectTokenSupplier.getSubjectToken(this.supplierContext); + } +} +exports.IdentityPoolClient = IdentityPoolClient; + + +/***/ }), + +/***/ 12718: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IdTokenClient = void 0; +const oauth2client_1 = __nccwpck_require__(10091); +class IdTokenClient extends oauth2client_1.OAuth2Client { + /** + * Google ID Token client + * + * Retrieve ID token from the metadata server. + * See: https://cloud.google.com/docs/authentication/get-id-token#metadata-server + */ + constructor(options) { + super(options); + this.targetAudience = options.targetAudience; + this.idTokenProvider = options.idTokenProvider; + } + async getRequestMetadataAsync( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + url) { + if (!this.credentials.id_token || + !this.credentials.expiry_date || + this.isTokenExpiring()) { + const idToken = await this.idTokenProvider.fetchIdToken(this.targetAudience); + this.credentials = { + id_token: idToken, + expiry_date: this.getIdTokenExpiryDate(idToken), + }; + } + const headers = { + Authorization: 'Bearer ' + this.credentials.id_token, + }; + return { headers }; + } + getIdTokenExpiryDate(idToken) { + const payloadB64 = idToken.split('.')[1]; + if (payloadB64) { + const payload = JSON.parse(Buffer.from(payloadB64, 'base64').toString('ascii')); + return payload.exp * 1000; + } + } +} +exports.IdTokenClient = IdTokenClient; + + +/***/ }), + +/***/ 39964: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Impersonated = exports.IMPERSONATED_ACCOUNT_TYPE = void 0; +const oauth2client_1 = __nccwpck_require__(10091); +const gaxios_1 = __nccwpck_require__(97003); +const util_1 = __nccwpck_require__(37870); +exports.IMPERSONATED_ACCOUNT_TYPE = 'impersonated_service_account'; +class Impersonated extends oauth2client_1.OAuth2Client { + /** + * Impersonated service account credentials. + * + * Create a new access token by impersonating another service account. + * + * Impersonated Credentials allowing credentials issued to a user or + * service account to impersonate another. The source project using + * Impersonated Credentials must enable the "IAMCredentials" API. + * Also, the target service account must grant the orginating principal + * the "Service Account Token Creator" IAM role. + * + * @param {object} options - The configuration object. + * @param {object} [options.sourceClient] the source credential used as to + * acquire the impersonated credentials. + * @param {string} [options.targetPrincipal] the service account to + * impersonate. + * @param {string[]} [options.delegates] the chained list of delegates + * required to grant the final access_token. If set, the sequence of + * identities must have "Service Account Token Creator" capability granted to + * the preceding identity. For example, if set to [serviceAccountB, + * serviceAccountC], the sourceCredential must have the Token Creator role on + * serviceAccountB. serviceAccountB must have the Token Creator on + * serviceAccountC. Finally, C must have Token Creator on target_principal. + * If left unset, sourceCredential must have that role on targetPrincipal. + * @param {string[]} [options.targetScopes] scopes to request during the + * authorization grant. + * @param {number} [options.lifetime] number of seconds the delegated + * credential should be valid for up to 3600 seconds by default, or 43,200 + * seconds by extending the token's lifetime, see: + * https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials#sa-credentials-oauth + * @param {string} [options.endpoint] api endpoint override. + */ + constructor(options = {}) { + var _a, _b, _c, _d, _e, _f; + super(options); + // Start with an expired refresh token, which will automatically be + // refreshed before the first API call is made. + this.credentials = { + expiry_date: 1, + refresh_token: 'impersonated-placeholder', + }; + this.sourceClient = (_a = options.sourceClient) !== null && _a !== void 0 ? _a : new oauth2client_1.OAuth2Client(); + this.targetPrincipal = (_b = options.targetPrincipal) !== null && _b !== void 0 ? _b : ''; + this.delegates = (_c = options.delegates) !== null && _c !== void 0 ? _c : []; + this.targetScopes = (_d = options.targetScopes) !== null && _d !== void 0 ? _d : []; + this.lifetime = (_e = options.lifetime) !== null && _e !== void 0 ? _e : 3600; + const usingExplicitUniverseDomain = !!(0, util_1.originalOrCamelOptions)(options).get('universe_domain'); + if (!usingExplicitUniverseDomain) { + // override the default universe with the source's universe + this.universeDomain = this.sourceClient.universeDomain; + } + else if (this.sourceClient.universeDomain !== this.universeDomain) { + // non-default universe and is not matching the source - this could be a credential leak + throw new RangeError(`Universe domain ${this.sourceClient.universeDomain} in source credentials does not match ${this.universeDomain} universe domain set for impersonated credentials.`); + } + this.endpoint = + (_f = options.endpoint) !== null && _f !== void 0 ? _f : `https://iamcredentials.${this.universeDomain}`; + } + /** + * Signs some bytes. + * + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob Reference Documentation} + * @param blobToSign String to sign. + * + * @returns A {@link SignBlobResponse} denoting the keyID and signedBlob in base64 string + */ + async sign(blobToSign) { + await this.sourceClient.getAccessToken(); + const name = `projects/-/serviceAccounts/${this.targetPrincipal}`; + const u = `${this.endpoint}/v1/${name}:signBlob`; + const body = { + delegates: this.delegates, + payload: Buffer.from(blobToSign).toString('base64'), + }; + const res = await this.sourceClient.request({ + ...Impersonated.RETRY_CONFIG, + url: u, + data: body, + method: 'POST', + }); + return res.data; + } + /** The service account email to be impersonated. */ + getTargetPrincipal() { + return this.targetPrincipal; + } + /** + * Refreshes the access token. + */ + async refreshToken() { + var _a, _b, _c, _d, _e, _f; + try { + await this.sourceClient.getAccessToken(); + const name = 'projects/-/serviceAccounts/' + this.targetPrincipal; + const u = `${this.endpoint}/v1/${name}:generateAccessToken`; + const body = { + delegates: this.delegates, + scope: this.targetScopes, + lifetime: this.lifetime + 's', + }; + const res = await this.sourceClient.request({ + ...Impersonated.RETRY_CONFIG, + url: u, + data: body, + method: 'POST', + }); + const tokenResponse = res.data; + this.credentials.access_token = tokenResponse.accessToken; + this.credentials.expiry_date = Date.parse(tokenResponse.expireTime); + return { + tokens: this.credentials, + res, + }; + } + catch (error) { + if (!(error instanceof Error)) + throw error; + let status = 0; + let message = ''; + if (error instanceof gaxios_1.GaxiosError) { + status = (_c = (_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.status; + message = (_f = (_e = (_d = error === null || error === void 0 ? void 0 : error.response) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.error) === null || _f === void 0 ? void 0 : _f.message; + } + if (status && message) { + error.message = `${status}: unable to impersonate: ${message}`; + throw error; + } + else { + error.message = `unable to impersonate: ${error}`; + throw error; + } + } + } + /** + * Generates an OpenID Connect ID token for a service account. + * + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateIdToken Reference Documentation} + * + * @param targetAudience the audience for the fetched ID token. + * @param options the for the request + * @return an OpenID Connect ID token + */ + async fetchIdToken(targetAudience, options) { + var _a, _b; + await this.sourceClient.getAccessToken(); + const name = `projects/-/serviceAccounts/${this.targetPrincipal}`; + const u = `${this.endpoint}/v1/${name}:generateIdToken`; + const body = { + delegates: this.delegates, + audience: targetAudience, + includeEmail: (_a = options === null || options === void 0 ? void 0 : options.includeEmail) !== null && _a !== void 0 ? _a : true, + useEmailAzp: (_b = options === null || options === void 0 ? void 0 : options.includeEmail) !== null && _b !== void 0 ? _b : true, + }; + const res = await this.sourceClient.request({ + ...Impersonated.RETRY_CONFIG, + url: u, + data: body, + method: 'POST', + }); + return res.data.token; + } +} +exports.Impersonated = Impersonated; + + +/***/ }), + +/***/ 27060: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2015 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.JWTAccess = void 0; +const jws = __nccwpck_require__(33324); +const util_1 = __nccwpck_require__(37870); +const DEFAULT_HEADER = { + alg: 'RS256', + typ: 'JWT', +}; +class JWTAccess { + /** + * JWTAccess service account credentials. + * + * Create a new access token by using the credential to create a new JWT token + * that's recognized as the access token. + * + * @param email the service account email address. + * @param key the private key that will be used to sign the token. + * @param keyId the ID of the private key used to sign the token. + */ + constructor(email, key, keyId, eagerRefreshThresholdMillis) { + this.cache = new util_1.LRUCache({ + capacity: 500, + maxAge: 60 * 60 * 1000, + }); + this.email = email; + this.key = key; + this.keyId = keyId; + this.eagerRefreshThresholdMillis = + eagerRefreshThresholdMillis !== null && eagerRefreshThresholdMillis !== void 0 ? eagerRefreshThresholdMillis : 5 * 60 * 1000; + } + /** + * Ensures that we're caching a key appropriately, giving precedence to scopes vs. url + * + * @param url The URI being authorized. + * @param scopes The scope or scopes being authorized + * @returns A string that returns the cached key. + */ + getCachedKey(url, scopes) { + let cacheKey = url; + if (scopes && Array.isArray(scopes) && scopes.length) { + cacheKey = url ? `${url}_${scopes.join('_')}` : `${scopes.join('_')}`; + } + else if (typeof scopes === 'string') { + cacheKey = url ? `${url}_${scopes}` : scopes; + } + if (!cacheKey) { + throw Error('Scopes or url must be provided'); + } + return cacheKey; + } + /** + * Get a non-expired access token, after refreshing if necessary. + * + * @param url The URI being authorized. + * @param additionalClaims An object with a set of additional claims to + * include in the payload. + * @returns An object that includes the authorization header. + */ + getRequestHeaders(url, additionalClaims, scopes) { + // Return cached authorization headers, unless we are within + // eagerRefreshThresholdMillis ms of them expiring: + const key = this.getCachedKey(url, scopes); + const cachedToken = this.cache.get(key); + const now = Date.now(); + if (cachedToken && + cachedToken.expiration - now > this.eagerRefreshThresholdMillis) { + return cachedToken.headers; + } + const iat = Math.floor(Date.now() / 1000); + const exp = JWTAccess.getExpirationTime(iat); + let defaultClaims; + // Turn scopes into space-separated string + if (Array.isArray(scopes)) { + scopes = scopes.join(' '); + } + // If scopes are specified, sign with scopes + if (scopes) { + defaultClaims = { + iss: this.email, + sub: this.email, + scope: scopes, + exp, + iat, + }; + } + else { + defaultClaims = { + iss: this.email, + sub: this.email, + aud: url, + exp, + iat, + }; + } + // if additionalClaims are provided, ensure they do not collide with + // other required claims. + if (additionalClaims) { + for (const claim in defaultClaims) { + if (additionalClaims[claim]) { + throw new Error(`The '${claim}' property is not allowed when passing additionalClaims. This claim is included in the JWT by default.`); + } + } + } + const header = this.keyId + ? { ...DEFAULT_HEADER, kid: this.keyId } + : DEFAULT_HEADER; + const payload = Object.assign(defaultClaims, additionalClaims); + // Sign the jwt and add it to the cache + const signedJWT = jws.sign({ header, payload, secret: this.key }); + const headers = { Authorization: `Bearer ${signedJWT}` }; + this.cache.set(key, { + expiration: exp * 1000, + headers, + }); + return headers; + } + /** + * Returns an expiration time for the JWT token. + * + * @param iat The issued at time for the JWT. + * @returns An expiration time for the JWT. + */ + static getExpirationTime(iat) { + const exp = iat + 3600; // 3600 seconds = 1 hour + return exp; + } + /** + * Create a JWTAccess credentials instance using the given input options. + * @param json The input object. + */ + fromJSON(json) { + if (!json) { + throw new Error('Must pass in a JSON object containing the service account auth settings.'); + } + if (!json.client_email) { + throw new Error('The incoming JSON object does not contain a client_email field'); + } + if (!json.private_key) { + throw new Error('The incoming JSON object does not contain a private_key field'); + } + // Extract the relevant information from the json key file. + this.email = json.client_email; + this.key = json.private_key; + this.keyId = json.private_key_id; + this.projectId = json.project_id; + } + fromStream(inputStream, callback) { + if (callback) { + this.fromStreamAsync(inputStream).then(() => callback(), callback); + } + else { + return this.fromStreamAsync(inputStream); + } + } + fromStreamAsync(inputStream) { + return new Promise((resolve, reject) => { + if (!inputStream) { + reject(new Error('Must pass in a stream containing the service account auth settings.')); + } + let s = ''; + inputStream + .setEncoding('utf8') + .on('data', chunk => (s += chunk)) + .on('error', reject) + .on('end', () => { + try { + const data = JSON.parse(s); + this.fromJSON(data); + resolve(); + } + catch (err) { + reject(err); + } + }); + }); + } +} +exports.JWTAccess = JWTAccess; + + +/***/ }), + +/***/ 75277: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2013 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.JWT = void 0; +const gtoken_1 = __nccwpck_require__(28568); +const jwtaccess_1 = __nccwpck_require__(27060); +const oauth2client_1 = __nccwpck_require__(10091); +const authclient_1 = __nccwpck_require__(34810); +class JWT extends oauth2client_1.OAuth2Client { + constructor(optionsOrEmail, keyFile, key, scopes, subject, keyId) { + const opts = optionsOrEmail && typeof optionsOrEmail === 'object' + ? optionsOrEmail + : { email: optionsOrEmail, keyFile, key, keyId, scopes, subject }; + super(opts); + this.email = opts.email; + this.keyFile = opts.keyFile; + this.key = opts.key; + this.keyId = opts.keyId; + this.scopes = opts.scopes; + this.subject = opts.subject; + this.additionalClaims = opts.additionalClaims; + // Start with an expired refresh token, which will automatically be + // refreshed before the first API call is made. + this.credentials = { refresh_token: 'jwt-placeholder', expiry_date: 1 }; + } + /** + * Creates a copy of the credential with the specified scopes. + * @param scopes List of requested scopes or a single scope. + * @return The cloned instance. + */ + createScoped(scopes) { + const jwt = new JWT(this); + jwt.scopes = scopes; + return jwt; + } + /** + * Obtains the metadata to be sent with the request. + * + * @param url the URI being authorized. + */ + async getRequestMetadataAsync(url) { + url = this.defaultServicePath ? `https://${this.defaultServicePath}/` : url; + const useSelfSignedJWT = (!this.hasUserScopes() && url) || + (this.useJWTAccessWithScope && this.hasAnyScopes()) || + this.universeDomain !== authclient_1.DEFAULT_UNIVERSE; + if (this.subject && this.universeDomain !== authclient_1.DEFAULT_UNIVERSE) { + throw new RangeError(`Service Account user is configured for the credential. Domain-wide delegation is not supported in universes other than ${authclient_1.DEFAULT_UNIVERSE}`); + } + if (!this.apiKey && useSelfSignedJWT) { + if (this.additionalClaims && + this.additionalClaims.target_audience) { + const { tokens } = await this.refreshToken(); + return { + headers: this.addSharedMetadataHeaders({ + Authorization: `Bearer ${tokens.id_token}`, + }), + }; + } + else { + // no scopes have been set, but a uri has been provided. Use JWTAccess + // credentials. + if (!this.access) { + this.access = new jwtaccess_1.JWTAccess(this.email, this.key, this.keyId, this.eagerRefreshThresholdMillis); + } + let scopes; + if (this.hasUserScopes()) { + scopes = this.scopes; + } + else if (!url) { + scopes = this.defaultScopes; + } + const useScopes = this.useJWTAccessWithScope || + this.universeDomain !== authclient_1.DEFAULT_UNIVERSE; + const headers = await this.access.getRequestHeaders(url !== null && url !== void 0 ? url : undefined, this.additionalClaims, + // Scopes take precedent over audience for signing, + // so we only provide them if `useJWTAccessWithScope` is on or + // if we are in a non-default universe + useScopes ? scopes : undefined); + return { headers: this.addSharedMetadataHeaders(headers) }; + } + } + else if (this.hasAnyScopes() || this.apiKey) { + return super.getRequestMetadataAsync(url); + } + else { + // If no audience, apiKey, or scopes are provided, we should not attempt + // to populate any headers: + return { headers: {} }; + } + } + /** + * Fetches an ID token. + * @param targetAudience the audience for the fetched ID token. + */ + async fetchIdToken(targetAudience) { + // Create a new gToken for fetching an ID token + const gtoken = new gtoken_1.GoogleToken({ + iss: this.email, + sub: this.subject, + scope: this.scopes || this.defaultScopes, + keyFile: this.keyFile, + key: this.key, + additionalClaims: { target_audience: targetAudience }, + transporter: this.transporter, + }); + await gtoken.getToken({ + forceRefresh: true, + }); + if (!gtoken.idToken) { + throw new Error('Unknown error: Failed to fetch ID token'); + } + return gtoken.idToken; + } + /** + * Determine if there are currently scopes available. + */ + hasUserScopes() { + if (!this.scopes) { + return false; + } + return this.scopes.length > 0; + } + /** + * Are there any default or user scopes defined. + */ + hasAnyScopes() { + if (this.scopes && this.scopes.length > 0) + return true; + if (this.defaultScopes && this.defaultScopes.length > 0) + return true; + return false; + } + authorize(callback) { + if (callback) { + this.authorizeAsync().then(r => callback(null, r), callback); + } + else { + return this.authorizeAsync(); + } + } + async authorizeAsync() { + const result = await this.refreshToken(); + if (!result) { + throw new Error('No result returned'); + } + this.credentials = result.tokens; + this.credentials.refresh_token = 'jwt-placeholder'; + this.key = this.gtoken.key; + this.email = this.gtoken.iss; + return result.tokens; + } + /** + * Refreshes the access token. + * @param refreshToken ignored + * @private + */ + async refreshTokenNoCache( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + refreshToken) { + const gtoken = this.createGToken(); + const token = await gtoken.getToken({ + forceRefresh: this.isTokenExpiring(), + }); + const tokens = { + access_token: token.access_token, + token_type: 'Bearer', + expiry_date: gtoken.expiresAt, + id_token: gtoken.idToken, + }; + this.emit('tokens', tokens); + return { res: null, tokens }; + } + /** + * Create a gToken if it doesn't already exist. + */ + createGToken() { + if (!this.gtoken) { + this.gtoken = new gtoken_1.GoogleToken({ + iss: this.email, + sub: this.subject, + scope: this.scopes || this.defaultScopes, + keyFile: this.keyFile, + key: this.key, + additionalClaims: this.additionalClaims, + transporter: this.transporter, + }); + } + return this.gtoken; + } + /** + * Create a JWT credentials instance using the given input options. + * @param json The input object. + * + * @remarks + * + * **Important**: If you accept a credential configuration (credential JSON/File/Stream) from an external source for authentication to Google Cloud, you must validate it before providing it to any Google API or library. Providing an unvalidated credential configuration to Google APIs can compromise the security of your systems and data. For more information, refer to {@link https://cloud.google.com/docs/authentication/external/externally-sourced-credentials Validate credential configurations from external sources}. + */ + fromJSON(json) { + if (!json) { + throw new Error('Must pass in a JSON object containing the service account auth settings.'); + } + if (!json.client_email) { + throw new Error('The incoming JSON object does not contain a client_email field'); + } + if (!json.private_key) { + throw new Error('The incoming JSON object does not contain a private_key field'); + } + // Extract the relevant information from the json key file. + this.email = json.client_email; + this.key = json.private_key; + this.keyId = json.private_key_id; + this.projectId = json.project_id; + this.quotaProjectId = json.quota_project_id; + this.universeDomain = json.universe_domain || this.universeDomain; + } + fromStream(inputStream, callback) { + if (callback) { + this.fromStreamAsync(inputStream).then(() => callback(), callback); + } + else { + return this.fromStreamAsync(inputStream); + } + } + fromStreamAsync(inputStream) { + return new Promise((resolve, reject) => { + if (!inputStream) { + throw new Error('Must pass in a stream containing the service account auth settings.'); + } + let s = ''; + inputStream + .setEncoding('utf8') + .on('error', reject) + .on('data', chunk => (s += chunk)) + .on('end', () => { + try { + const data = JSON.parse(s); + this.fromJSON(data); + resolve(); + } + catch (e) { + reject(e); + } + }); + }); + } + /** + * Creates a JWT credentials instance using an API Key for authentication. + * @param apiKey The API Key in string form. + */ + fromAPIKey(apiKey) { + if (typeof apiKey !== 'string') { + throw new Error('Must provide an API Key string.'); + } + this.apiKey = apiKey; + } + /** + * Using the key or keyFile on the JWT client, obtain an object that contains + * the key and the client email. + */ + async getCredentials() { + if (this.key) { + return { private_key: this.key, client_email: this.email }; + } + else if (this.keyFile) { + const gtoken = this.createGToken(); + const creds = await gtoken.getCredentials(this.keyFile); + return { private_key: creds.privateKey, client_email: creds.clientEmail }; + } + throw new Error('A key or a keyFile must be provided to getCredentials.'); + } +} +exports.JWT = JWT; + + +/***/ }), + +/***/ 53882: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2014 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.LoginTicket = void 0; +class LoginTicket { + /** + * Create a simple class to extract user ID from an ID Token + * + * @param {string} env Envelope of the jwt + * @param {TokenPayload} pay Payload of the jwt + * @constructor + */ + constructor(env, pay) { + this.envelope = env; + this.payload = pay; + } + getEnvelope() { + return this.envelope; + } + getPayload() { + return this.payload; + } + /** + * Create a simple class to extract user ID from an ID Token + * + * @return The user ID + */ + getUserId() { + const payload = this.getPayload(); + if (payload && payload.sub) { + return payload.sub; + } + return null; + } + /** + * Returns attributes from the login ticket. This can contain + * various information about the user session. + * + * @return The envelope and payload + */ + getAttributes() { + return { envelope: this.getEnvelope(), payload: this.getPayload() }; + } +} +exports.LoginTicket = LoginTicket; + + +/***/ }), + +/***/ 10091: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OAuth2Client = exports.ClientAuthentication = exports.CertificateFormat = exports.CodeChallengeMethod = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const querystring = __nccwpck_require__(83480); +const stream = __nccwpck_require__(2203); +const formatEcdsa = __nccwpck_require__(325); +const crypto_1 = __nccwpck_require__(88851); +const authclient_1 = __nccwpck_require__(34810); +const loginticket_1 = __nccwpck_require__(53882); +var CodeChallengeMethod; +(function (CodeChallengeMethod) { + CodeChallengeMethod["Plain"] = "plain"; + CodeChallengeMethod["S256"] = "S256"; +})(CodeChallengeMethod || (exports.CodeChallengeMethod = CodeChallengeMethod = {})); +var CertificateFormat; +(function (CertificateFormat) { + CertificateFormat["PEM"] = "PEM"; + CertificateFormat["JWK"] = "JWK"; +})(CertificateFormat || (exports.CertificateFormat = CertificateFormat = {})); +/** + * The client authentication type. Supported values are basic, post, and none. + * https://datatracker.ietf.org/doc/html/rfc7591#section-2 + */ +var ClientAuthentication; +(function (ClientAuthentication) { + ClientAuthentication["ClientSecretPost"] = "ClientSecretPost"; + ClientAuthentication["ClientSecretBasic"] = "ClientSecretBasic"; + ClientAuthentication["None"] = "None"; +})(ClientAuthentication || (exports.ClientAuthentication = ClientAuthentication = {})); +class OAuth2Client extends authclient_1.AuthClient { + constructor(optionsOrClientId, clientSecret, redirectUri) { + const opts = optionsOrClientId && typeof optionsOrClientId === 'object' + ? optionsOrClientId + : { clientId: optionsOrClientId, clientSecret, redirectUri }; + super(opts); + this.certificateCache = {}; + this.certificateExpiry = null; + this.certificateCacheFormat = CertificateFormat.PEM; + this.refreshTokenPromises = new Map(); + this._clientId = opts.clientId; + this._clientSecret = opts.clientSecret; + this.redirectUri = opts.redirectUri; + this.endpoints = { + tokenInfoUrl: 'https://oauth2.googleapis.com/tokeninfo', + oauth2AuthBaseUrl: 'https://accounts.google.com/o/oauth2/v2/auth', + oauth2TokenUrl: 'https://oauth2.googleapis.com/token', + oauth2RevokeUrl: 'https://oauth2.googleapis.com/revoke', + oauth2FederatedSignonPemCertsUrl: 'https://www.googleapis.com/oauth2/v1/certs', + oauth2FederatedSignonJwkCertsUrl: 'https://www.googleapis.com/oauth2/v3/certs', + oauth2IapPublicKeyUrl: 'https://www.gstatic.com/iap/verify/public_key', + ...opts.endpoints, + }; + this.clientAuthentication = + opts.clientAuthentication || ClientAuthentication.ClientSecretPost; + this.issuers = opts.issuers || [ + 'accounts.google.com', + 'https://accounts.google.com', + this.universeDomain, + ]; + } + /** + * Generates URL for consent page landing. + * @param opts Options. + * @return URL to consent page. + */ + generateAuthUrl(opts = {}) { + if (opts.code_challenge_method && !opts.code_challenge) { + throw new Error('If a code_challenge_method is provided, code_challenge must be included.'); + } + opts.response_type = opts.response_type || 'code'; + opts.client_id = opts.client_id || this._clientId; + opts.redirect_uri = opts.redirect_uri || this.redirectUri; + // Allow scopes to be passed either as array or a string + if (Array.isArray(opts.scope)) { + opts.scope = opts.scope.join(' '); + } + const rootUrl = this.endpoints.oauth2AuthBaseUrl.toString(); + return (rootUrl + + '?' + + querystring.stringify(opts)); + } + generateCodeVerifier() { + // To make the code compatible with browser SubtleCrypto we need to make + // this method async. + throw new Error('generateCodeVerifier is removed, please use generateCodeVerifierAsync instead.'); + } + /** + * Convenience method to automatically generate a code_verifier, and its + * resulting SHA256. If used, this must be paired with a S256 + * code_challenge_method. + * + * For a full example see: + * https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/oauth2-codeVerifier.js + */ + async generateCodeVerifierAsync() { + // base64 encoding uses 6 bits per character, and we want to generate128 + // characters. 6*128/8 = 96. + const crypto = (0, crypto_1.createCrypto)(); + const randomString = crypto.randomBytesBase64(96); + // The valid characters in the code_verifier are [A-Z]/[a-z]/[0-9]/ + // "-"/"."/"_"/"~". Base64 encoded strings are pretty close, so we're just + // swapping out a few chars. + const codeVerifier = randomString + .replace(/\+/g, '~') + .replace(/=/g, '_') + .replace(/\//g, '-'); + // Generate the base64 encoded SHA256 + const unencodedCodeChallenge = await crypto.sha256DigestBase64(codeVerifier); + // We need to use base64UrlEncoding instead of standard base64 + const codeChallenge = unencodedCodeChallenge + .split('=')[0] + .replace(/\+/g, '-') + .replace(/\//g, '_'); + return { codeVerifier, codeChallenge }; + } + getToken(codeOrOptions, callback) { + const options = typeof codeOrOptions === 'string' ? { code: codeOrOptions } : codeOrOptions; + if (callback) { + this.getTokenAsync(options).then(r => callback(null, r.tokens, r.res), e => callback(e, null, e.response)); + } + else { + return this.getTokenAsync(options); + } + } + async getTokenAsync(options) { + const url = this.endpoints.oauth2TokenUrl.toString(); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + }; + const values = { + client_id: options.client_id || this._clientId, + code_verifier: options.codeVerifier, + code: options.code, + grant_type: 'authorization_code', + redirect_uri: options.redirect_uri || this.redirectUri, + }; + if (this.clientAuthentication === ClientAuthentication.ClientSecretBasic) { + const basic = Buffer.from(`${this._clientId}:${this._clientSecret}`); + headers['Authorization'] = `Basic ${basic.toString('base64')}`; + } + if (this.clientAuthentication === ClientAuthentication.ClientSecretPost) { + values.client_secret = this._clientSecret; + } + const res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + method: 'POST', + url, + data: querystring.stringify(values), + headers, + }); + const tokens = res.data; + if (res.data && res.data.expires_in) { + tokens.expiry_date = new Date().getTime() + res.data.expires_in * 1000; + delete tokens.expires_in; + } + this.emit('tokens', tokens); + return { tokens, res }; + } + /** + * Refreshes the access token. + * @param refresh_token Existing refresh token. + * @private + */ + async refreshToken(refreshToken) { + if (!refreshToken) { + return this.refreshTokenNoCache(refreshToken); + } + // If a request to refresh using the same token has started, + // return the same promise. + if (this.refreshTokenPromises.has(refreshToken)) { + return this.refreshTokenPromises.get(refreshToken); + } + const p = this.refreshTokenNoCache(refreshToken).then(r => { + this.refreshTokenPromises.delete(refreshToken); + return r; + }, e => { + this.refreshTokenPromises.delete(refreshToken); + throw e; + }); + this.refreshTokenPromises.set(refreshToken, p); + return p; + } + async refreshTokenNoCache(refreshToken) { + var _a; + if (!refreshToken) { + throw new Error('No refresh token is set.'); + } + const url = this.endpoints.oauth2TokenUrl.toString(); + const data = { + refresh_token: refreshToken, + client_id: this._clientId, + client_secret: this._clientSecret, + grant_type: 'refresh_token', + }; + let res; + try { + // request for new token + res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + method: 'POST', + url, + data: querystring.stringify(data), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + } + catch (e) { + if (e instanceof gaxios_1.GaxiosError && + e.message === 'invalid_grant' && + ((_a = e.response) === null || _a === void 0 ? void 0 : _a.data) && + /ReAuth/i.test(e.response.data.error_description)) { + e.message = JSON.stringify(e.response.data); + } + throw e; + } + const tokens = res.data; + // TODO: de-duplicate this code from a few spots + if (res.data && res.data.expires_in) { + tokens.expiry_date = new Date().getTime() + res.data.expires_in * 1000; + delete tokens.expires_in; + } + this.emit('tokens', tokens); + return { tokens, res }; + } + refreshAccessToken(callback) { + if (callback) { + this.refreshAccessTokenAsync().then(r => callback(null, r.credentials, r.res), callback); + } + else { + return this.refreshAccessTokenAsync(); + } + } + async refreshAccessTokenAsync() { + const r = await this.refreshToken(this.credentials.refresh_token); + const tokens = r.tokens; + tokens.refresh_token = this.credentials.refresh_token; + this.credentials = tokens; + return { credentials: this.credentials, res: r.res }; + } + getAccessToken(callback) { + if (callback) { + this.getAccessTokenAsync().then(r => callback(null, r.token, r.res), callback); + } + else { + return this.getAccessTokenAsync(); + } + } + async getAccessTokenAsync() { + const shouldRefresh = !this.credentials.access_token || this.isTokenExpiring(); + if (shouldRefresh) { + if (!this.credentials.refresh_token) { + if (this.refreshHandler) { + const refreshedAccessToken = await this.processAndValidateRefreshHandler(); + if (refreshedAccessToken === null || refreshedAccessToken === void 0 ? void 0 : refreshedAccessToken.access_token) { + this.setCredentials(refreshedAccessToken); + return { token: this.credentials.access_token }; + } + } + else { + throw new Error('No refresh token or refresh handler callback is set.'); + } + } + const r = await this.refreshAccessTokenAsync(); + if (!r.credentials || (r.credentials && !r.credentials.access_token)) { + throw new Error('Could not refresh access token.'); + } + return { token: r.credentials.access_token, res: r.res }; + } + else { + return { token: this.credentials.access_token }; + } + } + /** + * The main authentication interface. It takes an optional url which when + * present is the endpoint being accessed, and returns a Promise which + * resolves with authorization header fields. + * + * In OAuth2Client, the result has the form: + * { Authorization: 'Bearer ' } + * @param url The optional url being authorized + */ + async getRequestHeaders(url) { + const headers = (await this.getRequestMetadataAsync(url)).headers; + return headers; + } + async getRequestMetadataAsync( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + url) { + const thisCreds = this.credentials; + if (!thisCreds.access_token && + !thisCreds.refresh_token && + !this.apiKey && + !this.refreshHandler) { + throw new Error('No access, refresh token, API key or refresh handler callback is set.'); + } + if (thisCreds.access_token && !this.isTokenExpiring()) { + thisCreds.token_type = thisCreds.token_type || 'Bearer'; + const headers = { + Authorization: thisCreds.token_type + ' ' + thisCreds.access_token, + }; + return { headers: this.addSharedMetadataHeaders(headers) }; + } + // If refreshHandler exists, call processAndValidateRefreshHandler(). + if (this.refreshHandler) { + const refreshedAccessToken = await this.processAndValidateRefreshHandler(); + if (refreshedAccessToken === null || refreshedAccessToken === void 0 ? void 0 : refreshedAccessToken.access_token) { + this.setCredentials(refreshedAccessToken); + const headers = { + Authorization: 'Bearer ' + this.credentials.access_token, + }; + return { headers: this.addSharedMetadataHeaders(headers) }; + } + } + if (this.apiKey) { + return { headers: { 'X-Goog-Api-Key': this.apiKey } }; + } + let r = null; + let tokens = null; + try { + r = await this.refreshToken(thisCreds.refresh_token); + tokens = r.tokens; + } + catch (err) { + const e = err; + if (e.response && + (e.response.status === 403 || e.response.status === 404)) { + e.message = `Could not refresh access token: ${e.message}`; + } + throw e; + } + const credentials = this.credentials; + credentials.token_type = credentials.token_type || 'Bearer'; + tokens.refresh_token = credentials.refresh_token; + this.credentials = tokens; + const headers = { + Authorization: credentials.token_type + ' ' + tokens.access_token, + }; + return { headers: this.addSharedMetadataHeaders(headers), res: r.res }; + } + /** + * Generates an URL to revoke the given token. + * @param token The existing token to be revoked. + * + * @deprecated use instance method {@link OAuth2Client.getRevokeTokenURL} + */ + static getRevokeTokenUrl(token) { + return new OAuth2Client().getRevokeTokenURL(token).toString(); + } + /** + * Generates a URL to revoke the given token. + * + * @param token The existing token to be revoked. + */ + getRevokeTokenURL(token) { + const url = new URL(this.endpoints.oauth2RevokeUrl); + url.searchParams.append('token', token); + return url; + } + revokeToken(token, callback) { + const opts = { + ...OAuth2Client.RETRY_CONFIG, + url: this.getRevokeTokenURL(token).toString(), + method: 'POST', + }; + if (callback) { + this.transporter + .request(opts) + .then(r => callback(null, r), callback); + } + else { + return this.transporter.request(opts); + } + } + revokeCredentials(callback) { + if (callback) { + this.revokeCredentialsAsync().then(res => callback(null, res), callback); + } + else { + return this.revokeCredentialsAsync(); + } + } + async revokeCredentialsAsync() { + const token = this.credentials.access_token; + this.credentials = {}; + if (token) { + return this.revokeToken(token); + } + else { + throw new Error('No access token to revoke.'); + } + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + async requestAsync(opts, reAuthRetried = false) { + let r2; + try { + const r = await this.getRequestMetadataAsync(opts.url); + opts.headers = opts.headers || {}; + if (r.headers && r.headers['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = r.headers['x-goog-user-project']; + } + if (r.headers && r.headers.Authorization) { + opts.headers.Authorization = r.headers.Authorization; + } + if (this.apiKey) { + opts.headers['X-Goog-Api-Key'] = this.apiKey; + } + r2 = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - An access_token and refresh_token were available, but either no + // expiry_date was available or the forceRefreshOnFailure flag is set. + // The absent expiry_date case can happen when developers stash the + // access_token and refresh_token for later use, but the access_token + // fails on the first try because it's expired. Some developers may + // choose to enable forceRefreshOnFailure to mitigate time-related + // errors. + // Or the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - No refresh_token was available + // - An access_token and a refreshHandler callback were available, but + // either no expiry_date was available or the forceRefreshOnFailure + // flag is set. The access_token fails on the first try because it's + // expired. Some developers may choose to enable forceRefreshOnFailure + // to mitigate time-related errors. + const mayRequireRefresh = this.credentials && + this.credentials.access_token && + this.credentials.refresh_token && + (!this.credentials.expiry_date || this.forceRefreshOnFailure); + const mayRequireRefreshWithNoRefreshToken = this.credentials && + this.credentials.access_token && + !this.credentials.refresh_token && + (!this.credentials.expiry_date || this.forceRefreshOnFailure) && + this.refreshHandler; + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + mayRequireRefresh) { + await this.refreshAccessTokenAsync(); + return this.requestAsync(opts, true); + } + else if (!reAuthRetried && + isAuthErr && + !isReadableStream && + mayRequireRefreshWithNoRefreshToken) { + const refreshedAccessToken = await this.processAndValidateRefreshHandler(); + if (refreshedAccessToken === null || refreshedAccessToken === void 0 ? void 0 : refreshedAccessToken.access_token) { + this.setCredentials(refreshedAccessToken); + } + return this.requestAsync(opts, true); + } + } + throw e; + } + return r2; + } + verifyIdToken(options, callback) { + // This function used to accept two arguments instead of an options object. + // Check the types to help users upgrade with less pain. + // This check can be removed after a 2.0 release. + if (callback && typeof callback !== 'function') { + throw new Error('This method accepts an options object as the first parameter, which includes the idToken, audience, and maxExpiry.'); + } + if (callback) { + this.verifyIdTokenAsync(options).then(r => callback(null, r), callback); + } + else { + return this.verifyIdTokenAsync(options); + } + } + async verifyIdTokenAsync(options) { + if (!options.idToken) { + throw new Error('The verifyIdToken method requires an ID Token'); + } + const response = await this.getFederatedSignonCertsAsync(); + const login = await this.verifySignedJwtWithCertsAsync(options.idToken, response.certs, options.audience, this.issuers, options.maxExpiry); + return login; + } + /** + * Obtains information about the provisioned access token. Especially useful + * if you want to check the scopes that were provisioned to a given token. + * + * @param accessToken Required. The Access Token for which you want to get + * user info. + */ + async getTokenInfo(accessToken) { + const { data } = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: `Bearer ${accessToken}`, + }, + url: this.endpoints.tokenInfoUrl.toString(), + }); + const info = Object.assign({ + expiry_date: new Date().getTime() + data.expires_in * 1000, + scopes: data.scope.split(' '), + }, data); + delete info.expires_in; + delete info.scope; + return info; + } + getFederatedSignonCerts(callback) { + if (callback) { + this.getFederatedSignonCertsAsync().then(r => callback(null, r.certs, r.res), callback); + } + else { + return this.getFederatedSignonCertsAsync(); + } + } + async getFederatedSignonCertsAsync() { + const nowTime = new Date().getTime(); + const format = (0, crypto_1.hasBrowserCrypto)() + ? CertificateFormat.JWK + : CertificateFormat.PEM; + if (this.certificateExpiry && + nowTime < this.certificateExpiry.getTime() && + this.certificateCacheFormat === format) { + return { certs: this.certificateCache, format }; + } + let res; + let url; + switch (format) { + case CertificateFormat.PEM: + url = this.endpoints.oauth2FederatedSignonPemCertsUrl.toString(); + break; + case CertificateFormat.JWK: + url = this.endpoints.oauth2FederatedSignonJwkCertsUrl.toString(); + break; + default: + throw new Error(`Unsupported certificate format ${format}`); + } + try { + res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + url, + }); + } + catch (e) { + if (e instanceof Error) { + e.message = `Failed to retrieve verification certificates: ${e.message}`; + } + throw e; + } + const cacheControl = res ? res.headers['cache-control'] : undefined; + let cacheAge = -1; + if (cacheControl) { + const pattern = new RegExp('max-age=([0-9]*)'); + const regexResult = pattern.exec(cacheControl); + if (regexResult && regexResult.length === 2) { + // Cache results with max-age (in seconds) + cacheAge = Number(regexResult[1]) * 1000; // milliseconds + } + } + let certificates = {}; + switch (format) { + case CertificateFormat.PEM: + certificates = res.data; + break; + case CertificateFormat.JWK: + for (const key of res.data.keys) { + certificates[key.kid] = key; + } + break; + default: + throw new Error(`Unsupported certificate format ${format}`); + } + const now = new Date(); + this.certificateExpiry = + cacheAge === -1 ? null : new Date(now.getTime() + cacheAge); + this.certificateCache = certificates; + this.certificateCacheFormat = format; + return { certs: certificates, format, res }; + } + getIapPublicKeys(callback) { + if (callback) { + this.getIapPublicKeysAsync().then(r => callback(null, r.pubkeys, r.res), callback); + } + else { + return this.getIapPublicKeysAsync(); + } + } + async getIapPublicKeysAsync() { + let res; + const url = this.endpoints.oauth2IapPublicKeyUrl.toString(); + try { + res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + url, + }); + } + catch (e) { + if (e instanceof Error) { + e.message = `Failed to retrieve verification certificates: ${e.message}`; + } + throw e; + } + return { pubkeys: res.data, res }; + } + verifySignedJwtWithCerts() { + // To make the code compatible with browser SubtleCrypto we need to make + // this method async. + throw new Error('verifySignedJwtWithCerts is removed, please use verifySignedJwtWithCertsAsync instead.'); + } + /** + * Verify the id token is signed with the correct certificate + * and is from the correct audience. + * @param jwt The jwt to verify (The ID Token in this case). + * @param certs The array of certs to test the jwt against. + * @param requiredAudience The audience to test the jwt against. + * @param issuers The allowed issuers of the jwt (Optional). + * @param maxExpiry The max expiry the certificate can be (Optional). + * @return Returns a promise resolving to LoginTicket on verification. + */ + async verifySignedJwtWithCertsAsync(jwt, certs, requiredAudience, issuers, maxExpiry) { + const crypto = (0, crypto_1.createCrypto)(); + if (!maxExpiry) { + maxExpiry = OAuth2Client.DEFAULT_MAX_TOKEN_LIFETIME_SECS_; + } + const segments = jwt.split('.'); + if (segments.length !== 3) { + throw new Error('Wrong number of segments in token: ' + jwt); + } + const signed = segments[0] + '.' + segments[1]; + let signature = segments[2]; + let envelope; + let payload; + try { + envelope = JSON.parse(crypto.decodeBase64StringUtf8(segments[0])); + } + catch (err) { + if (err instanceof Error) { + err.message = `Can't parse token envelope: ${segments[0]}': ${err.message}`; + } + throw err; + } + if (!envelope) { + throw new Error("Can't parse token envelope: " + segments[0]); + } + try { + payload = JSON.parse(crypto.decodeBase64StringUtf8(segments[1])); + } + catch (err) { + if (err instanceof Error) { + err.message = `Can't parse token payload '${segments[0]}`; + } + throw err; + } + if (!payload) { + throw new Error("Can't parse token payload: " + segments[1]); + } + if (!Object.prototype.hasOwnProperty.call(certs, envelope.kid)) { + // If this is not present, then there's no reason to attempt verification + throw new Error('No pem found for envelope: ' + JSON.stringify(envelope)); + } + const cert = certs[envelope.kid]; + if (envelope.alg === 'ES256') { + signature = formatEcdsa.joseToDer(signature, 'ES256').toString('base64'); + } + const verified = await crypto.verify(cert, signed, signature); + if (!verified) { + throw new Error('Invalid token signature: ' + jwt); + } + if (!payload.iat) { + throw new Error('No issue time in token: ' + JSON.stringify(payload)); + } + if (!payload.exp) { + throw new Error('No expiration time in token: ' + JSON.stringify(payload)); + } + const iat = Number(payload.iat); + if (isNaN(iat)) + throw new Error('iat field using invalid format'); + const exp = Number(payload.exp); + if (isNaN(exp)) + throw new Error('exp field using invalid format'); + const now = new Date().getTime() / 1000; + if (exp >= now + maxExpiry) { + throw new Error('Expiration time too far in future: ' + JSON.stringify(payload)); + } + const earliest = iat - OAuth2Client.CLOCK_SKEW_SECS_; + const latest = exp + OAuth2Client.CLOCK_SKEW_SECS_; + if (now < earliest) { + throw new Error('Token used too early, ' + + now + + ' < ' + + earliest + + ': ' + + JSON.stringify(payload)); + } + if (now > latest) { + throw new Error('Token used too late, ' + + now + + ' > ' + + latest + + ': ' + + JSON.stringify(payload)); + } + if (issuers && issuers.indexOf(payload.iss) < 0) { + throw new Error('Invalid issuer, expected one of [' + + issuers + + '], but got ' + + payload.iss); + } + // Check the audience matches if we have one + if (typeof requiredAudience !== 'undefined' && requiredAudience !== null) { + const aud = payload.aud; + let audVerified = false; + // If the requiredAudience is an array, check if it contains token + // audience + if (requiredAudience.constructor === Array) { + audVerified = requiredAudience.indexOf(aud) > -1; + } + else { + audVerified = aud === requiredAudience; + } + if (!audVerified) { + throw new Error('Wrong recipient, payload audience != requiredAudience'); + } + } + return new loginticket_1.LoginTicket(envelope, payload); + } + /** + * Returns a promise that resolves with AccessTokenResponse type if + * refreshHandler is defined. + * If not, nothing is returned. + */ + async processAndValidateRefreshHandler() { + if (this.refreshHandler) { + const accessTokenResponse = await this.refreshHandler(); + if (!accessTokenResponse.access_token) { + throw new Error('No access token is returned by the refreshHandler callback.'); + } + return accessTokenResponse; + } + return; + } + /** + * Returns true if a token is expired or will expire within + * eagerRefreshThresholdMillismilliseconds. + * If there is no expiry time, assumes the token is not expired or expiring. + */ + isTokenExpiring() { + const expiryDate = this.credentials.expiry_date; + return expiryDate + ? expiryDate <= new Date().getTime() + this.eagerRefreshThresholdMillis + : false; + } +} +exports.OAuth2Client = OAuth2Client; +/** + * @deprecated use instance's {@link OAuth2Client.endpoints} + */ +OAuth2Client.GOOGLE_TOKEN_INFO_URL = 'https://oauth2.googleapis.com/tokeninfo'; +/** + * Clock skew - five minutes in seconds + */ +OAuth2Client.CLOCK_SKEW_SECS_ = 300; +/** + * The default max Token Lifetime is one day in seconds + */ +OAuth2Client.DEFAULT_MAX_TOKEN_LIFETIME_SECS_ = 86400; + + +/***/ }), + +/***/ 6653: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OAuthClientAuthHandler = void 0; +exports.getErrorFromOAuthErrorResponse = getErrorFromOAuthErrorResponse; +const querystring = __nccwpck_require__(83480); +const crypto_1 = __nccwpck_require__(88851); +/** List of HTTP methods that accept request bodies. */ +const METHODS_SUPPORTING_REQUEST_BODY = ['PUT', 'POST', 'PATCH']; +/** + * Abstract class for handling client authentication in OAuth-based + * operations. + * When request-body client authentication is used, only application/json and + * application/x-www-form-urlencoded content types for HTTP methods that support + * request bodies are supported. + */ +class OAuthClientAuthHandler { + /** + * Instantiates an OAuth client authentication handler. + * @param clientAuthentication The client auth credentials. + */ + constructor(clientAuthentication) { + this.clientAuthentication = clientAuthentication; + this.crypto = (0, crypto_1.createCrypto)(); + } + /** + * Applies client authentication on the OAuth request's headers or POST + * body but does not process the request. + * @param opts The GaxiosOptions whose headers or data are to be modified + * depending on the client authentication mechanism to be used. + * @param bearerToken The optional bearer token to use for authentication. + * When this is used, no client authentication credentials are needed. + */ + applyClientAuthenticationOptions(opts, bearerToken) { + // Inject authenticated header. + this.injectAuthenticatedHeaders(opts, bearerToken); + // Inject authenticated request body. + if (!bearerToken) { + this.injectAuthenticatedRequestBody(opts); + } + } + /** + * Applies client authentication on the request's header if either + * basic authentication or bearer token authentication is selected. + * + * @param opts The GaxiosOptions whose headers or data are to be modified + * depending on the client authentication mechanism to be used. + * @param bearerToken The optional bearer token to use for authentication. + * When this is used, no client authentication credentials are needed. + */ + injectAuthenticatedHeaders(opts, bearerToken) { + var _a; + // Bearer token prioritized higher than basic Auth. + if (bearerToken) { + opts.headers = opts.headers || {}; + Object.assign(opts.headers, { + Authorization: `Bearer ${bearerToken}}`, + }); + } + else if (((_a = this.clientAuthentication) === null || _a === void 0 ? void 0 : _a.confidentialClientType) === 'basic') { + opts.headers = opts.headers || {}; + const clientId = this.clientAuthentication.clientId; + const clientSecret = this.clientAuthentication.clientSecret || ''; + const base64EncodedCreds = this.crypto.encodeBase64StringUtf8(`${clientId}:${clientSecret}`); + Object.assign(opts.headers, { + Authorization: `Basic ${base64EncodedCreds}`, + }); + } + } + /** + * Applies client authentication on the request's body if request-body + * client authentication is selected. + * + * @param opts The GaxiosOptions whose headers or data are to be modified + * depending on the client authentication mechanism to be used. + */ + injectAuthenticatedRequestBody(opts) { + var _a; + if (((_a = this.clientAuthentication) === null || _a === void 0 ? void 0 : _a.confidentialClientType) === 'request-body') { + const method = (opts.method || 'GET').toUpperCase(); + // Inject authenticated request body. + if (METHODS_SUPPORTING_REQUEST_BODY.indexOf(method) !== -1) { + // Get content-type. + let contentType; + const headers = opts.headers || {}; + for (const key in headers) { + if (key.toLowerCase() === 'content-type' && headers[key]) { + contentType = headers[key].toLowerCase(); + break; + } + } + if (contentType === 'application/x-www-form-urlencoded') { + opts.data = opts.data || ''; + const data = querystring.parse(opts.data); + Object.assign(data, { + client_id: this.clientAuthentication.clientId, + client_secret: this.clientAuthentication.clientSecret || '', + }); + opts.data = querystring.stringify(data); + } + else if (contentType === 'application/json') { + opts.data = opts.data || {}; + Object.assign(opts.data, { + client_id: this.clientAuthentication.clientId, + client_secret: this.clientAuthentication.clientSecret || '', + }); + } + else { + throw new Error(`${contentType} content-types are not supported with ` + + `${this.clientAuthentication.confidentialClientType} ` + + 'client authentication'); + } + } + else { + throw new Error(`${method} HTTP method does not support ` + + `${this.clientAuthentication.confidentialClientType} ` + + 'client authentication'); + } + } + } + /** + * Retry config for Auth-related requests. + * + * @remarks + * + * This is not a part of the default {@link AuthClient.transporter transporter/gaxios} + * config as some downstream APIs would prefer if customers explicitly enable retries, + * such as GCS. + */ + static get RETRY_CONFIG() { + return { + retry: true, + retryConfig: { + httpMethodsToRetry: ['GET', 'PUT', 'POST', 'HEAD', 'OPTIONS', 'DELETE'], + }, + }; + } +} +exports.OAuthClientAuthHandler = OAuthClientAuthHandler; +/** + * Converts an OAuth error response to a native JavaScript Error. + * @param resp The OAuth error response to convert to a native Error object. + * @param err The optional original error. If provided, the error properties + * will be copied to the new error. + * @return The converted native Error object. + */ +function getErrorFromOAuthErrorResponse(resp, err) { + // Error response. + const errorCode = resp.error; + const errorDescription = resp.error_description; + const errorUri = resp.error_uri; + let message = `Error code ${errorCode}`; + if (typeof errorDescription !== 'undefined') { + message += `: ${errorDescription}`; + } + if (typeof errorUri !== 'undefined') { + message += ` - ${errorUri}`; + } + const newError = new Error(message); + // Copy properties from original error to newly generated error. + if (err) { + const keys = Object.keys(err); + if (err.stack) { + // Copy error.stack if available. + keys.push('stack'); + } + keys.forEach(key => { + // Do not overwrite the message field. + if (key !== 'message') { + Object.defineProperty(newError, key, { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: err[key], + writable: false, + enumerable: true, + }); + } + }); + } + return newError; +} + + +/***/ }), + +/***/ 62045: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PassThroughClient = void 0; +const authclient_1 = __nccwpck_require__(34810); +/** + * An AuthClient without any Authentication information. Useful for: + * - Anonymous access + * - Local Emulators + * - Testing Environments + * + */ +class PassThroughClient extends authclient_1.AuthClient { + /** + * Creates a request without any authentication headers or checks. + * + * @remarks + * + * In testing environments it may be useful to change the provided + * {@link AuthClient.transporter} for any desired request overrides/handling. + * + * @param opts + * @returns The response of the request. + */ + async request(opts) { + return this.transporter.request(opts); + } + /** + * A required method of the base class. + * Always will return an empty object. + * + * @returns {} + */ + async getAccessToken() { + return {}; + } + /** + * A required method of the base class. + * Always will return an empty object. + * + * @returns {} + */ + async getRequestHeaders() { + return {}; + } +} +exports.PassThroughClient = PassThroughClient; +const a = new PassThroughClient(); +a.getAccessToken(); + + +/***/ }), + +/***/ 46077: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PluggableAuthClient = exports.ExecutableError = void 0; +const baseexternalclient_1 = __nccwpck_require__(142); +const executable_response_1 = __nccwpck_require__(43247); +const pluggable_auth_handler_1 = __nccwpck_require__(908); +/** + * Error thrown from the executable run by PluggableAuthClient. + */ +class ExecutableError extends Error { + constructor(message, code) { + super(`The executable failed with exit code: ${code} and error message: ${message}.`); + this.code = code; + Object.setPrototypeOf(this, new.target.prototype); + } +} +exports.ExecutableError = ExecutableError; +/** + * The default executable timeout when none is provided, in milliseconds. + */ +const DEFAULT_EXECUTABLE_TIMEOUT_MILLIS = 30 * 1000; +/** + * The minimum allowed executable timeout in milliseconds. + */ +const MINIMUM_EXECUTABLE_TIMEOUT_MILLIS = 5 * 1000; +/** + * The maximum allowed executable timeout in milliseconds. + */ +const MAXIMUM_EXECUTABLE_TIMEOUT_MILLIS = 120 * 1000; +/** + * The environment variable to check to see if executable can be run. + * Value must be set to '1' for the executable to run. + */ +const GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES = 'GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES'; +/** + * The maximum currently supported executable version. + */ +const MAXIMUM_EXECUTABLE_VERSION = 1; +/** + * PluggableAuthClient enables the exchange of workload identity pool external credentials for + * Google access tokens by retrieving 3rd party tokens through a user supplied executable. These + * scripts/executables are completely independent of the Google Cloud Auth libraries. These + * credentials plug into ADC and will call the specified executable to retrieve the 3rd party token + * to be exchanged for a Google access token. + * + *

To use these credentials, the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable + * must be set to '1'. This is for security reasons. + * + *

Both OIDC and SAML are supported. The executable must adhere to a specific response format + * defined below. + * + *

The executable must print out the 3rd party token to STDOUT in JSON format. When an + * output_file is specified in the credential configuration, the executable must also handle writing the + * JSON response to this file. + * + *

+ * OIDC response sample:
+ * {
+ *   "version": 1,
+ *   "success": true,
+ *   "token_type": "urn:ietf:params:oauth:token-type:id_token",
+ *   "id_token": "HEADER.PAYLOAD.SIGNATURE",
+ *   "expiration_time": 1620433341
+ * }
+ *
+ * SAML2 response sample:
+ * {
+ *   "version": 1,
+ *   "success": true,
+ *   "token_type": "urn:ietf:params:oauth:token-type:saml2",
+ *   "saml_response": "...",
+ *   "expiration_time": 1620433341
+ * }
+ *
+ * Error response sample:
+ * {
+ *   "version": 1,
+ *   "success": false,
+ *   "code": "401",
+ *   "message": "Error message."
+ * }
+ * 
+ * + *

The "expiration_time" field in the JSON response is only required for successful + * responses when an output file was specified in the credential configuration + * + *

The auth libraries will populate certain environment variables that will be accessible by the + * executable, such as: GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE, GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE, + * GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE, GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL, and + * GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE. + * + *

Please see this repositories README for a complete executable request/response specification. + */ +class PluggableAuthClient extends baseexternalclient_1.BaseExternalAccountClient { + /** + * Instantiates a PluggableAuthClient instance using the provided JSON + * object loaded from an external account credentials file. + * An error is thrown if the credential is not a valid pluggable auth credential. + * @param options The external account options object typically loaded from + * the external account JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + super(options, additionalOptions); + if (!options.credential_source.executable) { + throw new Error('No valid Pluggable Auth "credential_source" provided.'); + } + this.command = options.credential_source.executable.command; + if (!this.command) { + throw new Error('No valid Pluggable Auth "credential_source" provided.'); + } + // Check if the provided timeout exists and if it is valid. + if (options.credential_source.executable.timeout_millis === undefined) { + this.timeoutMillis = DEFAULT_EXECUTABLE_TIMEOUT_MILLIS; + } + else { + this.timeoutMillis = options.credential_source.executable.timeout_millis; + if (this.timeoutMillis < MINIMUM_EXECUTABLE_TIMEOUT_MILLIS || + this.timeoutMillis > MAXIMUM_EXECUTABLE_TIMEOUT_MILLIS) { + throw new Error(`Timeout must be between ${MINIMUM_EXECUTABLE_TIMEOUT_MILLIS} and ` + + `${MAXIMUM_EXECUTABLE_TIMEOUT_MILLIS} milliseconds.`); + } + } + this.outputFile = options.credential_source.executable.output_file; + this.handler = new pluggable_auth_handler_1.PluggableAuthHandler({ + command: this.command, + timeoutMillis: this.timeoutMillis, + outputFile: this.outputFile, + }); + this.credentialSourceType = 'executable'; + } + /** + * Triggered when an external subject token is needed to be exchanged for a + * GCP access token via GCP STS endpoint. + * This uses the `options.credential_source` object to figure out how + * to retrieve the token using the current environment. In this case, + * this calls a user provided executable which returns the subject token. + * The logic is summarized as: + * 1. Validated that the executable is allowed to run. The + * GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment must be set to + * 1 for security reasons. + * 2. If an output file is specified by the user, check the file location + * for a response. If the file exists and contains a valid response, + * return the subject token from the file. + * 3. Call the provided executable and return response. + * @return A promise that resolves with the external subject token. + */ + async retrieveSubjectToken() { + // Check if the executable is allowed to run. + if (process.env[GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES] !== '1') { + throw new Error('Pluggable Auth executables need to be explicitly allowed to run by ' + + 'setting the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment ' + + 'Variable to 1.'); + } + let executableResponse = undefined; + // Try to get cached executable response from output file. + if (this.outputFile) { + executableResponse = await this.handler.retrieveCachedResponse(); + } + // If no response from output file, call the executable. + if (!executableResponse) { + // Set up environment map with required values for the executable. + const envMap = new Map(); + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE', this.audience); + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE', this.subjectTokenType); + // Always set to 0 because interactive mode is not supported. + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE', '0'); + if (this.outputFile) { + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE', this.outputFile); + } + const serviceAccountEmail = this.getServiceAccountEmail(); + if (serviceAccountEmail) { + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL', serviceAccountEmail); + } + executableResponse = + await this.handler.retrieveResponseFromExecutable(envMap); + } + if (executableResponse.version > MAXIMUM_EXECUTABLE_VERSION) { + throw new Error(`Version of executable is not currently supported, maximum supported version is ${MAXIMUM_EXECUTABLE_VERSION}.`); + } + // Check that response was successful. + if (!executableResponse.success) { + throw new ExecutableError(executableResponse.errorMessage, executableResponse.errorCode); + } + // Check that response contains expiration time if output file was specified. + if (this.outputFile) { + if (!executableResponse.expirationTime) { + throw new executable_response_1.InvalidExpirationTimeFieldError('The executable response must contain the `expiration_time` field for successful responses when an output_file has been specified in the configuration.'); + } + } + // Check that response is not expired. + if (executableResponse.isExpired()) { + throw new Error('Executable response is expired.'); + } + // Return subject token from response. + return executableResponse.subjectToken; + } +} +exports.PluggableAuthClient = PluggableAuthClient; + + +/***/ }), + +/***/ 908: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PluggableAuthHandler = void 0; +const pluggable_auth_client_1 = __nccwpck_require__(46077); +const executable_response_1 = __nccwpck_require__(43247); +const childProcess = __nccwpck_require__(35317); +const fs = __nccwpck_require__(79896); +/** + * A handler used to retrieve 3rd party token responses from user defined + * executables and cached file output for the PluggableAuthClient class. + */ +class PluggableAuthHandler { + /** + * Instantiates a PluggableAuthHandler instance using the provided + * PluggableAuthHandlerOptions object. + */ + constructor(options) { + if (!options.command) { + throw new Error('No command provided.'); + } + this.commandComponents = PluggableAuthHandler.parseCommand(options.command); + this.timeoutMillis = options.timeoutMillis; + if (!this.timeoutMillis) { + throw new Error('No timeoutMillis provided.'); + } + this.outputFile = options.outputFile; + } + /** + * Calls user provided executable to get a 3rd party subject token and + * returns the response. + * @param envMap a Map of additional Environment Variables required for + * the executable. + * @return A promise that resolves with the executable response. + */ + retrieveResponseFromExecutable(envMap) { + return new Promise((resolve, reject) => { + // Spawn process to run executable using added environment variables. + const child = childProcess.spawn(this.commandComponents[0], this.commandComponents.slice(1), { + env: { ...process.env, ...Object.fromEntries(envMap) }, + }); + let output = ''; + // Append stdout to output as executable runs. + child.stdout.on('data', (data) => { + output += data; + }); + // Append stderr as executable runs. + child.stderr.on('data', (err) => { + output += err; + }); + // Set up a timeout to end the child process and throw an error. + const timeout = setTimeout(() => { + // Kill child process and remove listeners so 'close' event doesn't get + // read after child process is killed. + child.removeAllListeners(); + child.kill(); + return reject(new Error('The executable failed to finish within the timeout specified.')); + }, this.timeoutMillis); + child.on('close', (code) => { + // Cancel timeout if executable closes before timeout is reached. + clearTimeout(timeout); + if (code === 0) { + // If the executable completed successfully, try to return the parsed response. + try { + const responseJson = JSON.parse(output); + const response = new executable_response_1.ExecutableResponse(responseJson); + return resolve(response); + } + catch (error) { + if (error instanceof executable_response_1.ExecutableResponseError) { + return reject(error); + } + return reject(new executable_response_1.ExecutableResponseError(`The executable returned an invalid response: ${output}`)); + } + } + else { + return reject(new pluggable_auth_client_1.ExecutableError(output, code.toString())); + } + }); + }); + } + /** + * Checks user provided output file for response from previous run of + * executable and return the response if it exists, is formatted correctly, and is not expired. + */ + async retrieveCachedResponse() { + if (!this.outputFile || this.outputFile.length === 0) { + return undefined; + } + let filePath; + try { + filePath = await fs.promises.realpath(this.outputFile); + } + catch (_a) { + // If file path cannot be resolved, return undefined. + return undefined; + } + if (!(await fs.promises.lstat(filePath)).isFile()) { + // If path does not lead to file, return undefined. + return undefined; + } + const responseString = await fs.promises.readFile(filePath, { + encoding: 'utf8', + }); + if (responseString === '') { + return undefined; + } + try { + const responseJson = JSON.parse(responseString); + const response = new executable_response_1.ExecutableResponse(responseJson); + // Check if response is successful and unexpired. + if (response.isValid()) { + return new executable_response_1.ExecutableResponse(responseJson); + } + return undefined; + } + catch (error) { + if (error instanceof executable_response_1.ExecutableResponseError) { + throw error; + } + throw new executable_response_1.ExecutableResponseError(`The output file contained an invalid response: ${responseString}`); + } + } + /** + * Parses given command string into component array, splitting on spaces unless + * spaces are between quotation marks. + */ + static parseCommand(command) { + // Split the command into components by splitting on spaces, + // unless spaces are contained in quotation marks. + const components = command.match(/(?:[^\s"]+|"[^"]*")+/g); + if (!components) { + throw new Error(`Provided command: "${command}" could not be parsed.`); + } + // Remove quotation marks from the beginning and end of each component if they are present. + for (let i = 0; i < components.length; i++) { + if (components[i][0] === '"' && components[i].slice(-1) === '"') { + components[i] = components[i].slice(1, -1); + } + } + return components; + } +} +exports.PluggableAuthHandler = PluggableAuthHandler; + + +/***/ }), + +/***/ 99807: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2015 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserRefreshClient = exports.USER_REFRESH_ACCOUNT_TYPE = void 0; +const oauth2client_1 = __nccwpck_require__(10091); +const querystring_1 = __nccwpck_require__(83480); +exports.USER_REFRESH_ACCOUNT_TYPE = 'authorized_user'; +class UserRefreshClient extends oauth2client_1.OAuth2Client { + constructor(optionsOrClientId, clientSecret, refreshToken, eagerRefreshThresholdMillis, forceRefreshOnFailure) { + const opts = optionsOrClientId && typeof optionsOrClientId === 'object' + ? optionsOrClientId + : { + clientId: optionsOrClientId, + clientSecret, + refreshToken, + eagerRefreshThresholdMillis, + forceRefreshOnFailure, + }; + super(opts); + this._refreshToken = opts.refreshToken; + this.credentials.refresh_token = opts.refreshToken; + } + /** + * Refreshes the access token. + * @param refreshToken An ignored refreshToken.. + * @param callback Optional callback. + */ + async refreshTokenNoCache( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + refreshToken) { + return super.refreshTokenNoCache(this._refreshToken); + } + async fetchIdToken(targetAudience) { + const res = await this.transporter.request({ + ...UserRefreshClient.RETRY_CONFIG, + url: this.endpoints.oauth2TokenUrl, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + data: (0, querystring_1.stringify)({ + client_id: this._clientId, + client_secret: this._clientSecret, + grant_type: 'refresh_token', + refresh_token: this._refreshToken, + target_audience: targetAudience, + }), + }); + return res.data.id_token; + } + /** + * Create a UserRefreshClient credentials instance using the given input + * options. + * @param json The input object. + */ + fromJSON(json) { + if (!json) { + throw new Error('Must pass in a JSON object containing the user refresh token'); + } + if (json.type !== 'authorized_user') { + throw new Error('The incoming JSON object does not have the "authorized_user" type'); + } + if (!json.client_id) { + throw new Error('The incoming JSON object does not contain a client_id field'); + } + if (!json.client_secret) { + throw new Error('The incoming JSON object does not contain a client_secret field'); + } + if (!json.refresh_token) { + throw new Error('The incoming JSON object does not contain a refresh_token field'); + } + this._clientId = json.client_id; + this._clientSecret = json.client_secret; + this._refreshToken = json.refresh_token; + this.credentials.refresh_token = json.refresh_token; + this.quotaProjectId = json.quota_project_id; + this.universeDomain = json.universe_domain || this.universeDomain; + } + fromStream(inputStream, callback) { + if (callback) { + this.fromStreamAsync(inputStream).then(() => callback(), callback); + } + else { + return this.fromStreamAsync(inputStream); + } + } + async fromStreamAsync(inputStream) { + return new Promise((resolve, reject) => { + if (!inputStream) { + return reject(new Error('Must pass in a stream containing the user refresh token.')); + } + let s = ''; + inputStream + .setEncoding('utf8') + .on('error', reject) + .on('data', chunk => (s += chunk)) + .on('end', () => { + try { + const data = JSON.parse(s); + this.fromJSON(data); + return resolve(); + } + catch (err) { + return reject(err); + } + }); + }); + } + /** + * Create a UserRefreshClient credentials instance using the given input + * options. + * @param json The input object. + */ + static fromJSON(json) { + const client = new UserRefreshClient(); + client.fromJSON(json); + return client; + } +} +exports.UserRefreshClient = UserRefreshClient; + + +/***/ }), + +/***/ 121: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.StsCredentials = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const querystring = __nccwpck_require__(83480); +const transporters_1 = __nccwpck_require__(67633); +const oauth2common_1 = __nccwpck_require__(6653); +/** + * Implements the OAuth 2.0 token exchange based on + * https://tools.ietf.org/html/rfc8693 + */ +class StsCredentials extends oauth2common_1.OAuthClientAuthHandler { + /** + * Initializes an STS credentials instance. + * @param tokenExchangeEndpoint The token exchange endpoint. + * @param clientAuthentication The client authentication credentials if + * available. + */ + constructor(tokenExchangeEndpoint, clientAuthentication) { + super(clientAuthentication); + this.tokenExchangeEndpoint = tokenExchangeEndpoint; + this.transporter = new transporters_1.DefaultTransporter(); + } + /** + * Exchanges the provided token for another type of token based on the + * rfc8693 spec. + * @param stsCredentialsOptions The token exchange options used to populate + * the token exchange request. + * @param additionalHeaders Optional additional headers to pass along the + * request. + * @param options Optional additional GCP-specific non-spec defined options + * to send with the request. + * Example: `&options=${encodeUriComponent(JSON.stringified(options))}` + * @return A promise that resolves with the token exchange response containing + * the requested token and its expiration time. + */ + async exchangeToken(stsCredentialsOptions, additionalHeaders, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + options) { + var _a, _b, _c; + const values = { + grant_type: stsCredentialsOptions.grantType, + resource: stsCredentialsOptions.resource, + audience: stsCredentialsOptions.audience, + scope: (_a = stsCredentialsOptions.scope) === null || _a === void 0 ? void 0 : _a.join(' '), + requested_token_type: stsCredentialsOptions.requestedTokenType, + subject_token: stsCredentialsOptions.subjectToken, + subject_token_type: stsCredentialsOptions.subjectTokenType, + actor_token: (_b = stsCredentialsOptions.actingParty) === null || _b === void 0 ? void 0 : _b.actorToken, + actor_token_type: (_c = stsCredentialsOptions.actingParty) === null || _c === void 0 ? void 0 : _c.actorTokenType, + // Non-standard GCP-specific options. + options: options && JSON.stringify(options), + }; + // Remove undefined fields. + Object.keys(values).forEach(key => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof values[key] === 'undefined') { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete values[key]; + } + }); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + }; + // Inject additional STS headers if available. + Object.assign(headers, additionalHeaders || {}); + const opts = { + ...StsCredentials.RETRY_CONFIG, + url: this.tokenExchangeEndpoint.toString(), + method: 'POST', + headers, + data: querystring.stringify(values), + responseType: 'json', + }; + // Apply OAuth client authentication. + this.applyClientAuthenticationOptions(opts); + try { + const response = await this.transporter.request(opts); + // Successful response. + const stsSuccessfulResponse = response.data; + stsSuccessfulResponse.res = response; + return stsSuccessfulResponse; + } + catch (error) { + // Translate error to OAuthError. + if (error instanceof gaxios_1.GaxiosError && error.response) { + throw (0, oauth2common_1.getErrorFromOAuthErrorResponse)(error.response.data, + // Preserve other fields from the original error. + error); + } + // Request could fail before the server responds. + throw error; + } + } +} +exports.StsCredentials = StsCredentials; + + +/***/ }), + +/***/ 24627: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UrlSubjectTokenSupplier = void 0; +/** + * Internal subject token supplier implementation used when a URL + * is configured in the credential configuration used to build an {@link IdentityPoolClient} + */ +class UrlSubjectTokenSupplier { + /** + * Instantiates a URL subject token supplier. + * @param opts The URL subject token supplier options to build the supplier with. + */ + constructor(opts) { + this.url = opts.url; + this.formatType = opts.formatType; + this.subjectTokenFieldName = opts.subjectTokenFieldName; + this.headers = opts.headers; + this.additionalGaxiosOptions = opts.additionalGaxiosOptions; + } + /** + * Sends a GET request to the URL provided in the constructor and resolves + * with the returned external subject token. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link IdentityPoolClient}, contains the requested audience and subject + * token type for the external account identity. Not used. + */ + async getSubjectToken(context) { + const opts = { + ...this.additionalGaxiosOptions, + url: this.url, + method: 'GET', + headers: this.headers, + responseType: this.formatType, + }; + let subjectToken; + if (this.formatType === 'text') { + const response = await context.transporter.request(opts); + subjectToken = response.data; + } + else if (this.formatType === 'json' && this.subjectTokenFieldName) { + const response = await context.transporter.request(opts); + subjectToken = response.data[this.subjectTokenFieldName]; + } + if (!subjectToken) { + throw new Error('Unable to parse the subject_token from the credential_source URL'); + } + return subjectToken; + } +} +exports.UrlSubjectTokenSupplier = UrlSubjectTokenSupplier; + + +/***/ }), + +/***/ 93438: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/* global window */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.BrowserCrypto = void 0; +// This file implements crypto functions we need using in-browser +// SubtleCrypto interface `window.crypto.subtle`. +const base64js = __nccwpck_require__(38793); +const crypto_1 = __nccwpck_require__(88851); +class BrowserCrypto { + constructor() { + if (typeof window === 'undefined' || + window.crypto === undefined || + window.crypto.subtle === undefined) { + throw new Error("SubtleCrypto not found. Make sure it's an https:// website."); + } + } + async sha256DigestBase64(str) { + // SubtleCrypto digest() method is async, so we must make + // this method async as well. + // To calculate SHA256 digest using SubtleCrypto, we first + // need to convert an input string to an ArrayBuffer: + const inputBuffer = new TextEncoder().encode(str); + // Result is ArrayBuffer as well. + const outputBuffer = await window.crypto.subtle.digest('SHA-256', inputBuffer); + return base64js.fromByteArray(new Uint8Array(outputBuffer)); + } + randomBytesBase64(count) { + const array = new Uint8Array(count); + window.crypto.getRandomValues(array); + return base64js.fromByteArray(array); + } + static padBase64(base64) { + // base64js requires padding, so let's add some '=' + while (base64.length % 4 !== 0) { + base64 += '='; + } + return base64; + } + async verify(pubkey, data, signature) { + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: 'SHA-256' }, + }; + const dataArray = new TextEncoder().encode(data); + const signatureArray = base64js.toByteArray(BrowserCrypto.padBase64(signature)); + const cryptoKey = await window.crypto.subtle.importKey('jwk', pubkey, algo, true, ['verify']); + // SubtleCrypto's verify method is async so we must make + // this method async as well. + const result = await window.crypto.subtle.verify(algo, cryptoKey, signatureArray, dataArray); + return result; + } + async sign(privateKey, data) { + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: 'SHA-256' }, + }; + const dataArray = new TextEncoder().encode(data); + const cryptoKey = await window.crypto.subtle.importKey('jwk', privateKey, algo, true, ['sign']); + // SubtleCrypto's sign method is async so we must make + // this method async as well. + const result = await window.crypto.subtle.sign(algo, cryptoKey, dataArray); + return base64js.fromByteArray(new Uint8Array(result)); + } + decodeBase64StringUtf8(base64) { + const uint8array = base64js.toByteArray(BrowserCrypto.padBase64(base64)); + const result = new TextDecoder().decode(uint8array); + return result; + } + encodeBase64StringUtf8(text) { + const uint8array = new TextEncoder().encode(text); + const result = base64js.fromByteArray(uint8array); + return result; + } + /** + * Computes the SHA-256 hash of the provided string. + * @param str The plain text string to hash. + * @return A promise that resolves with the SHA-256 hash of the provided + * string in hexadecimal encoding. + */ + async sha256DigestHex(str) { + // SubtleCrypto digest() method is async, so we must make + // this method async as well. + // To calculate SHA256 digest using SubtleCrypto, we first + // need to convert an input string to an ArrayBuffer: + const inputBuffer = new TextEncoder().encode(str); + // Result is ArrayBuffer as well. + const outputBuffer = await window.crypto.subtle.digest('SHA-256', inputBuffer); + return (0, crypto_1.fromArrayBufferToHex)(outputBuffer); + } + /** + * Computes the HMAC hash of a message using the provided crypto key and the + * SHA-256 algorithm. + * @param key The secret crypto key in utf-8 or ArrayBuffer format. + * @param msg The plain text message. + * @return A promise that resolves with the HMAC-SHA256 hash in ArrayBuffer + * format. + */ + async signWithHmacSha256(key, msg) { + // Convert key, if provided in ArrayBuffer format, to string. + const rawKey = typeof key === 'string' + ? key + : String.fromCharCode(...new Uint16Array(key)); + const enc = new TextEncoder(); + const cryptoKey = await window.crypto.subtle.importKey('raw', enc.encode(rawKey), { + name: 'HMAC', + hash: { + name: 'SHA-256', + }, + }, false, ['sign']); + return window.crypto.subtle.sign('HMAC', cryptoKey, enc.encode(msg)); + } +} +exports.BrowserCrypto = BrowserCrypto; + + +/***/ }), + +/***/ 88851: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/* global window */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createCrypto = createCrypto; +exports.hasBrowserCrypto = hasBrowserCrypto; +exports.fromArrayBufferToHex = fromArrayBufferToHex; +const crypto_1 = __nccwpck_require__(93438); +const crypto_2 = __nccwpck_require__(27388); +function createCrypto() { + if (hasBrowserCrypto()) { + return new crypto_1.BrowserCrypto(); + } + return new crypto_2.NodeCrypto(); +} +function hasBrowserCrypto() { + return (typeof window !== 'undefined' && + typeof window.crypto !== 'undefined' && + typeof window.crypto.subtle !== 'undefined'); +} +/** + * Converts an ArrayBuffer to a hexadecimal string. + * @param arrayBuffer The ArrayBuffer to convert to hexadecimal string. + * @return The hexadecimal encoding of the ArrayBuffer. + */ +function fromArrayBufferToHex(arrayBuffer) { + // Convert buffer to byte array. + const byteArray = Array.from(new Uint8Array(arrayBuffer)); + // Convert bytes to hex string. + return byteArray + .map(byte => { + return byte.toString(16).padStart(2, '0'); + }) + .join(''); +} + + +/***/ }), + +/***/ 27388: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NodeCrypto = void 0; +const crypto = __nccwpck_require__(76982); +class NodeCrypto { + async sha256DigestBase64(str) { + return crypto.createHash('sha256').update(str).digest('base64'); + } + randomBytesBase64(count) { + return crypto.randomBytes(count).toString('base64'); + } + async verify(pubkey, data, signature) { + const verifier = crypto.createVerify('RSA-SHA256'); + verifier.update(data); + verifier.end(); + return verifier.verify(pubkey, signature, 'base64'); + } + async sign(privateKey, data) { + const signer = crypto.createSign('RSA-SHA256'); + signer.update(data); + signer.end(); + return signer.sign(privateKey, 'base64'); + } + decodeBase64StringUtf8(base64) { + return Buffer.from(base64, 'base64').toString('utf-8'); + } + encodeBase64StringUtf8(text) { + return Buffer.from(text, 'utf-8').toString('base64'); + } + /** + * Computes the SHA-256 hash of the provided string. + * @param str The plain text string to hash. + * @return A promise that resolves with the SHA-256 hash of the provided + * string in hexadecimal encoding. + */ + async sha256DigestHex(str) { + return crypto.createHash('sha256').update(str).digest('hex'); + } + /** + * Computes the HMAC hash of a message using the provided crypto key and the + * SHA-256 algorithm. + * @param key The secret crypto key in utf-8 or ArrayBuffer format. + * @param msg The plain text message. + * @return A promise that resolves with the HMAC-SHA256 hash in ArrayBuffer + * format. + */ + async signWithHmacSha256(key, msg) { + const cryptoKey = typeof key === 'string' ? key : toBuffer(key); + return toArrayBuffer(crypto.createHmac('sha256', cryptoKey).update(msg).digest()); + } +} +exports.NodeCrypto = NodeCrypto; +/** + * Converts a Node.js Buffer to an ArrayBuffer. + * https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer + * @param buffer The Buffer input to covert. + * @return The ArrayBuffer representation of the input. + */ +function toArrayBuffer(buffer) { + return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); +} +/** + * Converts an ArrayBuffer to a Node.js Buffer. + * @param arrayBuffer The ArrayBuffer input to covert. + * @return The Buffer representation of the input. + */ +function toBuffer(arrayBuffer) { + return Buffer.from(arrayBuffer); +} + + +/***/ }), + +/***/ 492: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GoogleAuth = exports.auth = exports.DefaultTransporter = exports.PassThroughClient = exports.ExecutableError = exports.PluggableAuthClient = exports.DownscopedClient = exports.BaseExternalAccountClient = exports.ExternalAccountClient = exports.IdentityPoolClient = exports.AwsRequestSigner = exports.AwsClient = exports.UserRefreshClient = exports.LoginTicket = exports.ClientAuthentication = exports.OAuth2Client = exports.CodeChallengeMethod = exports.Impersonated = exports.JWT = exports.JWTAccess = exports.IdTokenClient = exports.IAMAuth = exports.GCPEnv = exports.Compute = exports.DEFAULT_UNIVERSE = exports.AuthClient = exports.gaxios = exports.gcpMetadata = void 0; +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +const googleauth_1 = __nccwpck_require__(95934); +Object.defineProperty(exports, "GoogleAuth", ({ enumerable: true, get: function () { return googleauth_1.GoogleAuth; } })); +// Export common deps to ensure types/instances are the exact match. Useful +// for consistently configuring the library across versions. +exports.gcpMetadata = __nccwpck_require__(23046); +exports.gaxios = __nccwpck_require__(97003); +var authclient_1 = __nccwpck_require__(34810); +Object.defineProperty(exports, "AuthClient", ({ enumerable: true, get: function () { return authclient_1.AuthClient; } })); +Object.defineProperty(exports, "DEFAULT_UNIVERSE", ({ enumerable: true, get: function () { return authclient_1.DEFAULT_UNIVERSE; } })); +var computeclient_1 = __nccwpck_require__(20977); +Object.defineProperty(exports, "Compute", ({ enumerable: true, get: function () { return computeclient_1.Compute; } })); +var envDetect_1 = __nccwpck_require__(60963); +Object.defineProperty(exports, "GCPEnv", ({ enumerable: true, get: function () { return envDetect_1.GCPEnv; } })); +var iam_1 = __nccwpck_require__(89390); +Object.defineProperty(exports, "IAMAuth", ({ enumerable: true, get: function () { return iam_1.IAMAuth; } })); +var idtokenclient_1 = __nccwpck_require__(12718); +Object.defineProperty(exports, "IdTokenClient", ({ enumerable: true, get: function () { return idtokenclient_1.IdTokenClient; } })); +var jwtaccess_1 = __nccwpck_require__(27060); +Object.defineProperty(exports, "JWTAccess", ({ enumerable: true, get: function () { return jwtaccess_1.JWTAccess; } })); +var jwtclient_1 = __nccwpck_require__(75277); +Object.defineProperty(exports, "JWT", ({ enumerable: true, get: function () { return jwtclient_1.JWT; } })); +var impersonated_1 = __nccwpck_require__(39964); +Object.defineProperty(exports, "Impersonated", ({ enumerable: true, get: function () { return impersonated_1.Impersonated; } })); +var oauth2client_1 = __nccwpck_require__(10091); +Object.defineProperty(exports, "CodeChallengeMethod", ({ enumerable: true, get: function () { return oauth2client_1.CodeChallengeMethod; } })); +Object.defineProperty(exports, "OAuth2Client", ({ enumerable: true, get: function () { return oauth2client_1.OAuth2Client; } })); +Object.defineProperty(exports, "ClientAuthentication", ({ enumerable: true, get: function () { return oauth2client_1.ClientAuthentication; } })); +var loginticket_1 = __nccwpck_require__(53882); +Object.defineProperty(exports, "LoginTicket", ({ enumerable: true, get: function () { return loginticket_1.LoginTicket; } })); +var refreshclient_1 = __nccwpck_require__(99807); +Object.defineProperty(exports, "UserRefreshClient", ({ enumerable: true, get: function () { return refreshclient_1.UserRefreshClient; } })); +var awsclient_1 = __nccwpck_require__(81261); +Object.defineProperty(exports, "AwsClient", ({ enumerable: true, get: function () { return awsclient_1.AwsClient; } })); +var awsrequestsigner_1 = __nccwpck_require__(27647); +Object.defineProperty(exports, "AwsRequestSigner", ({ enumerable: true, get: function () { return awsrequestsigner_1.AwsRequestSigner; } })); +var identitypoolclient_1 = __nccwpck_require__(29960); +Object.defineProperty(exports, "IdentityPoolClient", ({ enumerable: true, get: function () { return identitypoolclient_1.IdentityPoolClient; } })); +var externalclient_1 = __nccwpck_require__(88323); +Object.defineProperty(exports, "ExternalAccountClient", ({ enumerable: true, get: function () { return externalclient_1.ExternalAccountClient; } })); +var baseexternalclient_1 = __nccwpck_require__(142); +Object.defineProperty(exports, "BaseExternalAccountClient", ({ enumerable: true, get: function () { return baseexternalclient_1.BaseExternalAccountClient; } })); +var downscopedclient_1 = __nccwpck_require__(77556); +Object.defineProperty(exports, "DownscopedClient", ({ enumerable: true, get: function () { return downscopedclient_1.DownscopedClient; } })); +var pluggable_auth_client_1 = __nccwpck_require__(46077); +Object.defineProperty(exports, "PluggableAuthClient", ({ enumerable: true, get: function () { return pluggable_auth_client_1.PluggableAuthClient; } })); +Object.defineProperty(exports, "ExecutableError", ({ enumerable: true, get: function () { return pluggable_auth_client_1.ExecutableError; } })); +var passthrough_1 = __nccwpck_require__(62045); +Object.defineProperty(exports, "PassThroughClient", ({ enumerable: true, get: function () { return passthrough_1.PassThroughClient; } })); +var transporters_1 = __nccwpck_require__(67633); +Object.defineProperty(exports, "DefaultTransporter", ({ enumerable: true, get: function () { return transporters_1.DefaultTransporter; } })); +const auth = new googleauth_1.GoogleAuth(); +exports.auth = auth; + + +/***/ }), + +/***/ 78290: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.validate = validate; +// Accepts an options object passed from the user to the API. In the +// previous version of the API, it referred to a `Request` options object. +// Now it refers to an Axiox Request Config object. This is here to help +// ensure users don't pass invalid options when they upgrade from 0.x to 1.x. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function validate(options) { + const vpairs = [ + { invalid: 'uri', expected: 'url' }, + { invalid: 'json', expected: 'data' }, + { invalid: 'qs', expected: 'params' }, + ]; + for (const pair of vpairs) { + if (options[pair.invalid]) { + const e = `'${pair.invalid}' is not a valid configuration option. Please use '${pair.expected}' instead. This library is using Axios for requests. Please see https://github.com/axios/axios to learn more about the valid request options.`; + throw new Error(e); + } + } +} + + +/***/ }), + +/***/ 67633: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DefaultTransporter = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const options_1 = __nccwpck_require__(78290); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = __nccwpck_require__(96066); +const PRODUCT_NAME = 'google-api-nodejs-client'; +class DefaultTransporter { + constructor() { + /** + * A configurable, replacable `Gaxios` instance. + */ + this.instance = new gaxios_1.Gaxios(); + } + /** + * Configures request options before making a request. + * @param opts GaxiosOptions options. + * @return Configured options. + */ + configure(opts = {}) { + opts.headers = opts.headers || {}; + if (typeof window === 'undefined') { + // set transporter user agent if not in browser + const uaValue = opts.headers['User-Agent']; + if (!uaValue) { + opts.headers['User-Agent'] = DefaultTransporter.USER_AGENT; + } + else if (!uaValue.includes(`${PRODUCT_NAME}/`)) { + opts.headers['User-Agent'] = + `${uaValue} ${DefaultTransporter.USER_AGENT}`; + } + // track google-auth-library-nodejs version: + if (!opts.headers['x-goog-api-client']) { + const nodeVersion = process.version.replace(/^v/, ''); + opts.headers['x-goog-api-client'] = `gl-node/${nodeVersion}`; + } + } + return opts; + } + /** + * Makes a request using Gaxios with given options. + * @param opts GaxiosOptions options. + * @param callback optional callback that contains GaxiosResponse object. + * @return GaxiosPromise, assuming no callback is passed. + */ + request(opts) { + // ensure the user isn't passing in request-style options + opts = this.configure(opts); + (0, options_1.validate)(opts); + return this.instance.request(opts).catch(e => { + throw this.processError(e); + }); + } + get defaults() { + return this.instance.defaults; + } + set defaults(opts) { + this.instance.defaults = opts; + } + /** + * Changes the error to include details from the body. + */ + processError(e) { + const res = e.response; + const err = e; + const body = res ? res.data : null; + if (res && body && body.error && res.status !== 200) { + if (typeof body.error === 'string') { + err.message = body.error; + err.status = res.status; + } + else if (Array.isArray(body.error.errors)) { + err.message = body.error.errors + .map((err2) => err2.message) + .join('\n'); + err.code = body.error.code; + err.errors = body.error.errors; + } + else { + err.message = body.error.message; + err.code = body.error.code; + } + } + else if (res && res.status >= 400) { + // Consider all 4xx and 5xx responses errors. + err.message = body; + err.status = res.status; + } + return err; + } +} +exports.DefaultTransporter = DefaultTransporter; +/** + * Default user agent. + */ +DefaultTransporter.USER_AGENT = `${PRODUCT_NAME}/${pkg.version}`; + + +/***/ }), + +/***/ 37870: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _LRUCache_instances, _LRUCache_cache, _LRUCache_moveToEnd, _LRUCache_evict; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.LRUCache = void 0; +exports.snakeToCamel = snakeToCamel; +exports.originalOrCamelOptions = originalOrCamelOptions; +/** + * Returns the camel case of a provided string. + * + * @remarks + * + * Match any `_` and not `_` pair, then return the uppercase of the not `_` + * character. + * + * @internal + * + * @param str the string to convert + * @returns the camelCase'd string + */ +function snakeToCamel(str) { + return str.replace(/([_][^_])/g, match => match.slice(1).toUpperCase()); +} +/** + * Get the value of `obj[key]` or `obj[camelCaseKey]`, with a preference + * for original, non-camelCase key. + * + * @param obj object to lookup a value in + * @returns a `get` function for getting `obj[key || snakeKey]`, if available + */ +function originalOrCamelOptions(obj) { + /** + * + * @param key an index of object, preferably snake_case + * @returns the value `obj[key || snakeKey]`, if available + */ + function get(key) { + var _a; + const o = (obj || {}); + return (_a = o[key]) !== null && _a !== void 0 ? _a : o[snakeToCamel(key)]; + } + return { get }; +} +/** + * A simple LRU cache utility. + * Not meant for external usage. + * + * @experimental + * @internal + */ +class LRUCache { + constructor(options) { + _LRUCache_instances.add(this); + /** + * Maps are in order. Thus, the older item is the first item. + * + * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map} + */ + _LRUCache_cache.set(this, new Map()); + this.capacity = options.capacity; + this.maxAge = options.maxAge; + } + /** + * Add an item to the cache. + * + * @param key the key to upsert + * @param value the value of the key + */ + set(key, value) { + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_moveToEnd).call(this, key, value); + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_evict).call(this); + } + /** + * Get an item from the cache. + * + * @param key the key to retrieve + */ + get(key) { + const item = __classPrivateFieldGet(this, _LRUCache_cache, "f").get(key); + if (!item) + return; + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_moveToEnd).call(this, key, item.value); + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_evict).call(this); + return item.value; + } +} +exports.LRUCache = LRUCache; +_LRUCache_cache = new WeakMap(), _LRUCache_instances = new WeakSet(), _LRUCache_moveToEnd = function _LRUCache_moveToEnd(key, value) { + __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(key); + __classPrivateFieldGet(this, _LRUCache_cache, "f").set(key, { + value, + lastAccessed: Date.now(), + }); +}, _LRUCache_evict = function _LRUCache_evict() { + const cutoffDate = this.maxAge ? Date.now() - this.maxAge : 0; + /** + * Because we know Maps are in order, this item is both the + * last item in the list (capacity) and oldest (maxAge). + */ + let oldestItem = __classPrivateFieldGet(this, _LRUCache_cache, "f").entries().next(); + while (!oldestItem.done && + (__classPrivateFieldGet(this, _LRUCache_cache, "f").size > this.capacity || // too many + oldestItem.value[1].lastAccessed < cutoffDate) // too old + ) { + __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(oldestItem.value[0]); + oldestItem = __classPrivateFieldGet(this, _LRUCache_cache, "f").entries().next(); + } +}; + + +/***/ }), + +/***/ 71628: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Colours = void 0; +/** + * Handles figuring out if we can use ANSI colours and handing out the escape codes. + * + * This is for package-internal use only, and may change at any time. + * + * @private + * @internal + */ +class Colours { + /** + * @param stream The stream (e.g. process.stderr) + * @returns true if the stream should have colourization enabled + */ + static isEnabled(stream) { + return (stream.isTTY && + (typeof stream.getColorDepth === 'function' + ? stream.getColorDepth() > 2 + : true)); + } + static refresh() { + Colours.enabled = Colours.isEnabled(process.stderr); + if (!this.enabled) { + Colours.reset = ''; + Colours.bright = ''; + Colours.dim = ''; + Colours.red = ''; + Colours.green = ''; + Colours.yellow = ''; + Colours.blue = ''; + Colours.magenta = ''; + Colours.cyan = ''; + Colours.white = ''; + Colours.grey = ''; + } + else { + Colours.reset = '\u001b[0m'; + Colours.bright = '\u001b[1m'; + Colours.dim = '\u001b[2m'; + Colours.red = '\u001b[31m'; + Colours.green = '\u001b[32m'; + Colours.yellow = '\u001b[33m'; + Colours.blue = '\u001b[34m'; + Colours.magenta = '\u001b[35m'; + Colours.cyan = '\u001b[36m'; + Colours.white = '\u001b[37m'; + Colours.grey = '\u001b[90m'; + } + } +} +exports.Colours = Colours; +Colours.enabled = false; +Colours.reset = ''; +Colours.bright = ''; +Colours.dim = ''; +Colours.red = ''; +Colours.green = ''; +Colours.yellow = ''; +Colours.blue = ''; +Colours.magenta = ''; +Colours.cyan = ''; +Colours.white = ''; +Colours.grey = ''; +Colours.refresh(); +//# sourceMappingURL=colours.js.map + +/***/ }), + +/***/ 81577: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__nccwpck_require__(74788), exports); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 74788: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2021-2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.env = exports.DebugLogBackendBase = exports.placeholder = exports.AdhocDebugLogger = exports.LogSeverity = void 0; +exports.getNodeBackend = getNodeBackend; +exports.getDebugBackend = getDebugBackend; +exports.getStructuredBackend = getStructuredBackend; +exports.setBackend = setBackend; +exports.log = log; +const node_events_1 = __nccwpck_require__(78474); +const process = __importStar(__nccwpck_require__(1708)); +const util = __importStar(__nccwpck_require__(57975)); +const colours_1 = __nccwpck_require__(71628); +// Some functions (as noted) are based on the Node standard library, from +// the following file: +// +// https://github.com/nodejs/node/blob/main/lib/internal/util/debuglog.js +/** + * This module defines an ad-hoc debug logger for Google Cloud Platform + * client libraries in Node. An ad-hoc debug logger is a tool which lets + * users use an external, unified interface (in this case, environment + * variables) to determine what logging they want to see at runtime. This + * isn't necessarily fed into the console, but is meant to be under the + * control of the user. The kind of logging that will be produced by this + * is more like "call retry happened", not "event you'd want to record + * in Cloud Logger". + * + * More for Googlers implementing libraries with it: + * go/cloud-client-logging-design + */ +/** + * Possible log levels. These are a subset of Cloud Observability levels. + * https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity + */ +var LogSeverity; +(function (LogSeverity) { + LogSeverity["DEFAULT"] = "DEFAULT"; + LogSeverity["DEBUG"] = "DEBUG"; + LogSeverity["INFO"] = "INFO"; + LogSeverity["WARNING"] = "WARNING"; + LogSeverity["ERROR"] = "ERROR"; +})(LogSeverity || (exports.LogSeverity = LogSeverity = {})); +/** + * Our logger instance. This actually contains the meat of dealing + * with log lines, including EventEmitter. This contains the function + * that will be passed back to users of the package. + */ +class AdhocDebugLogger extends node_events_1.EventEmitter { + /** + * @param upstream The backend will pass a function that will be + * called whenever our logger function is invoked. + */ + constructor(namespace, upstream) { + super(); + this.namespace = namespace; + this.upstream = upstream; + this.func = Object.assign(this.invoke.bind(this), { + // Also add an instance pointer back to us. + instance: this, + // And pull over the EventEmitter functionality. + on: (event, listener) => this.on(event, listener), + }); + // Convenience methods for log levels. + this.func.debug = (...args) => this.invokeSeverity(LogSeverity.DEBUG, ...args); + this.func.info = (...args) => this.invokeSeverity(LogSeverity.INFO, ...args); + this.func.warn = (...args) => this.invokeSeverity(LogSeverity.WARNING, ...args); + this.func.error = (...args) => this.invokeSeverity(LogSeverity.ERROR, ...args); + this.func.sublog = (namespace) => log(namespace, this.func); + } + invoke(fields, ...args) { + // Push out any upstream logger first. + if (this.upstream) { + this.upstream(fields, ...args); + } + // Emit sink events. + this.emit('log', fields, args); + } + invokeSeverity(severity, ...args) { + this.invoke({ severity }, ...args); + } +} +exports.AdhocDebugLogger = AdhocDebugLogger; +/** + * This can be used in place of a real logger while waiting for Promises or disabling logging. + */ +exports.placeholder = new AdhocDebugLogger('', () => { }).func; +/** + * The base class for debug logging backends. It's possible to use this, but the + * same non-guarantees above still apply (unstable interface, etc). + * + * @private + * @internal + */ +class DebugLogBackendBase { + constructor() { + var _a; + this.cached = new Map(); + this.filters = []; + this.filtersSet = false; + // Look for the Node config variable for what systems to enable. We'll store + // these for the log method below, which will call setFilters() once. + let nodeFlag = (_a = process.env[exports.env.nodeEnables]) !== null && _a !== void 0 ? _a : '*'; + if (nodeFlag === 'all') { + nodeFlag = '*'; + } + this.filters = nodeFlag.split(','); + } + log(namespace, fields, ...args) { + try { + if (!this.filtersSet) { + this.setFilters(); + this.filtersSet = true; + } + let logger = this.cached.get(namespace); + if (!logger) { + logger = this.makeLogger(namespace); + this.cached.set(namespace, logger); + } + logger(fields, ...args); + } + catch (e) { + // Silently ignore all errors; we don't want them to interfere with + // the user's running app. + // e; + console.error(e); + } + } +} +exports.DebugLogBackendBase = DebugLogBackendBase; +// The basic backend. This one definitely works, but it's less feature-filled. +// +// Rather than using util.debuglog, this implements the same basic logic directly. +// The reason for this decision is that debuglog checks the value of the +// NODE_DEBUG environment variable before any user code runs; we therefore +// can't pipe our own enables into it (and util.debuglog will never print unless +// the user duplicates it into NODE_DEBUG, which isn't reasonable). +// +class NodeBackend extends DebugLogBackendBase { + constructor() { + super(...arguments); + // Default to allowing all systems, since we gate earlier based on whether the + // variable is empty. + this.enabledRegexp = /.*/g; + } + isEnabled(namespace) { + return this.enabledRegexp.test(namespace); + } + makeLogger(namespace) { + if (!this.enabledRegexp.test(namespace)) { + return () => { }; + } + return (fields, ...args) => { + var _a; + // TODO: `fields` needs to be turned into a string here, one way or another. + const nscolour = `${colours_1.Colours.green}${namespace}${colours_1.Colours.reset}`; + const pid = `${colours_1.Colours.yellow}${process.pid}${colours_1.Colours.reset}`; + let level; + switch (fields.severity) { + case LogSeverity.ERROR: + level = `${colours_1.Colours.red}${fields.severity}${colours_1.Colours.reset}`; + break; + case LogSeverity.INFO: + level = `${colours_1.Colours.magenta}${fields.severity}${colours_1.Colours.reset}`; + break; + case LogSeverity.WARNING: + level = `${colours_1.Colours.yellow}${fields.severity}${colours_1.Colours.reset}`; + break; + default: + level = (_a = fields.severity) !== null && _a !== void 0 ? _a : LogSeverity.DEFAULT; + break; + } + const msg = util.formatWithOptions({ colors: colours_1.Colours.enabled }, ...args); + const filteredFields = Object.assign({}, fields); + delete filteredFields.severity; + const fieldsJson = Object.getOwnPropertyNames(filteredFields).length + ? JSON.stringify(filteredFields) + : ''; + const fieldsColour = fieldsJson + ? `${colours_1.Colours.grey}${fieldsJson}${colours_1.Colours.reset}` + : ''; + console.error('%s [%s|%s] %s%s', pid, nscolour, level, msg, fieldsJson ? ` ${fieldsColour}` : ''); + }; + } + // Regexp patterns below are from here: + // https://github.com/nodejs/node/blob/c0aebed4b3395bd65d54b18d1fd00f071002ac20/lib/internal/util/debuglog.js#L36 + setFilters() { + const totalFilters = this.filters.join(','); + const regexp = totalFilters + .replace(/[|\\{}()[\]^$+?.]/g, '\\$&') + .replace(/\*/g, '.*') + .replace(/,/g, '$|^'); + this.enabledRegexp = new RegExp(`^${regexp}$`, 'i'); + } +} +/** + * @returns A backend based on Node util.debuglog; this is the default. + */ +function getNodeBackend() { + return new NodeBackend(); +} +class DebugBackend extends DebugLogBackendBase { + constructor(pkg) { + super(); + this.debugPkg = pkg; + } + makeLogger(namespace) { + const debugLogger = this.debugPkg(namespace); + return (fields, ...args) => { + // TODO: `fields` needs to be turned into a string here. + debugLogger(args[0], ...args.slice(1)); + }; + } + setFilters() { + var _a; + const existingFilters = (_a = process.env['NODE_DEBUG']) !== null && _a !== void 0 ? _a : ''; + process.env['NODE_DEBUG'] = `${existingFilters}${existingFilters ? ',' : ''}${this.filters.join(',')}`; + } +} +/** + * Creates a "debug" package backend. The user must call require('debug') and pass + * the resulting object to this function. + * + * ``` + * setBackend(getDebugBackend(require('debug'))) + * ``` + * + * https://www.npmjs.com/package/debug + * + * Note: Google does not explicitly endorse or recommend this package; it's just + * being provided as an option. + * + * @returns A backend based on the npm "debug" package. + */ +function getDebugBackend(debugPkg) { + return new DebugBackend(debugPkg); +} +/** + * This pretty much works like the Node logger, but it outputs structured + * logging JSON matching Google Cloud's ingestion specs. Rather than handling + * its own output, it wraps another backend. The passed backend must be a subclass + * of `DebugLogBackendBase` (any of the backends exposed by this package will work). + */ +class StructuredBackend extends DebugLogBackendBase { + constructor(upstream) { + var _a; + super(); + this.upstream = (_a = upstream) !== null && _a !== void 0 ? _a : new NodeBackend(); + } + makeLogger(namespace) { + const debugLogger = this.upstream.makeLogger(namespace); + return (fields, ...args) => { + var _a; + const severity = (_a = fields.severity) !== null && _a !== void 0 ? _a : LogSeverity.INFO; + const json = Object.assign({ + severity, + message: util.format(...args), + }, fields); + const jsonString = JSON.stringify(json); + debugLogger(fields, jsonString); + }; + } + setFilters() { + this.upstream.setFilters(); + } +} +/** + * Creates a "structured logging" backend. This pretty much works like the + * Node logger, but it outputs structured logging JSON matching Google + * Cloud's ingestion specs instead of plain text. + * + * ``` + * setBackend(getStructuredBackend()) + * ``` + * + * @param upstream If you want to use something besides the Node backend to + * write the actual log lines into, pass that here. + * @returns A backend based on Google Cloud structured logging. + */ +function getStructuredBackend(upstream) { + return new StructuredBackend(upstream); +} +/** + * The environment variables that we standardized on, for all ad-hoc logging. + */ +exports.env = { + /** + * Filter wildcards specific to the Node syntax, and similar to the built-in + * utils.debuglog() environment variable. If missing, disables logging. + */ + nodeEnables: 'GOOGLE_SDK_NODE_LOGGING', +}; +// Keep a copy of all namespaced loggers so users can reliably .on() them. +// Note that these cached functions will need to deal with changes in the backend. +const loggerCache = new Map(); +// Our current global backend. This might be: +let cachedBackend = undefined; +/** + * Set the backend to use for our log output. + * - A backend object + * - null to disable logging + * - undefined for "nothing yet", defaults to the Node backend + * + * @param backend Results from one of the get*Backend() functions. + */ +function setBackend(backend) { + cachedBackend = backend; + loggerCache.clear(); +} +/** + * Creates a logging function. Multiple calls to this with the same namespace + * will produce the same logger, with the same event emitter hooks. + * + * Namespaces can be a simple string ("system" name), or a qualified string + * (system:subsystem), which can be used for filtering, or for "system:*". + * + * @param namespace The namespace, a descriptive text string. + * @returns A function you can call that works similar to console.log(). + */ +function log(namespace, parent) { + // If the enable flag isn't set, do nothing. + const enablesFlag = process.env[exports.env.nodeEnables]; + if (!enablesFlag) { + return exports.placeholder; + } + // This might happen mostly if the typings are dropped in a user's code, + // or if they're calling from JavaScript. + if (!namespace) { + return exports.placeholder; + } + // Handle sub-loggers. + if (parent) { + namespace = `${parent.instance.namespace}:${namespace}`; + } + // Reuse loggers so things like event sinks are persistent. + const existing = loggerCache.get(namespace); + if (existing) { + return existing.func; + } + // Do we have a backend yet? + if (cachedBackend === null) { + // Explicitly disabled. + return exports.placeholder; + } + else if (cachedBackend === undefined) { + // One hasn't been made yet, so default to Node. + cachedBackend = getNodeBackend(); + } + // The logger is further wrapped so we can handle the backend changing out. + const logger = (() => { + let previousBackend = undefined; + const newLogger = new AdhocDebugLogger(namespace, (fields, ...args) => { + if (previousBackend !== cachedBackend) { + // Did the user pass a custom backend? + if (cachedBackend === null) { + // Explicitly disabled. + return; + } + else if (cachedBackend === undefined) { + // One hasn't been made yet, so default to Node. + cachedBackend = getNodeBackend(); + } + previousBackend = cachedBackend; + } + cachedBackend === null || cachedBackend === void 0 ? void 0 : cachedBackend.log(namespace, fields, ...args); + }); + return newLogger; + })(); + loggerCache.set(namespace, logger); + return logger.func; +} +//# sourceMappingURL=logging-utils.js.map + +/***/ }), + +/***/ 28568: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/** + * Copyright 2018 Google LLC + * + * Distributed under MIT license. + * See file LICENSE for detail or copy at https://opensource.org/licenses/MIT + */ +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _GoogleToken_instances, _GoogleToken_inFlightRequest, _GoogleToken_getTokenAsync, _GoogleToken_getTokenAsyncInner, _GoogleToken_ensureEmail, _GoogleToken_revokeTokenAsync, _GoogleToken_configure, _GoogleToken_requestToken; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GoogleToken = void 0; +const fs = __nccwpck_require__(79896); +const gaxios_1 = __nccwpck_require__(97003); +const jws = __nccwpck_require__(33324); +const path = __nccwpck_require__(16928); +const util_1 = __nccwpck_require__(39023); +const readFile = fs.readFile + ? (0, util_1.promisify)(fs.readFile) + : async () => { + // if running in the web-browser, fs.readFile may not have been shimmed. + throw new ErrorWithCode('use key rather than keyFile.', 'MISSING_CREDENTIALS'); + }; +const GOOGLE_TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token'; +const GOOGLE_REVOKE_TOKEN_URL = 'https://accounts.google.com/o/oauth2/revoke?token='; +class ErrorWithCode extends Error { + constructor(message, code) { + super(message); + this.code = code; + } +} +class GoogleToken { + get accessToken() { + return this.rawToken ? this.rawToken.access_token : undefined; + } + get idToken() { + return this.rawToken ? this.rawToken.id_token : undefined; + } + get tokenType() { + return this.rawToken ? this.rawToken.token_type : undefined; + } + get refreshToken() { + return this.rawToken ? this.rawToken.refresh_token : undefined; + } + /** + * Create a GoogleToken. + * + * @param options Configuration object. + */ + constructor(options) { + _GoogleToken_instances.add(this); + this.transporter = { + request: opts => (0, gaxios_1.request)(opts), + }; + _GoogleToken_inFlightRequest.set(this, void 0); + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_configure).call(this, options); + } + /** + * Returns whether the token has expired. + * + * @return true if the token has expired, false otherwise. + */ + hasExpired() { + const now = new Date().getTime(); + if (this.rawToken && this.expiresAt) { + return now >= this.expiresAt; + } + else { + return true; + } + } + /** + * Returns whether the token will expire within eagerRefreshThresholdMillis + * + * @return true if the token will be expired within eagerRefreshThresholdMillis, false otherwise. + */ + isTokenExpiring() { + var _a; + const now = new Date().getTime(); + const eagerRefreshThresholdMillis = (_a = this.eagerRefreshThresholdMillis) !== null && _a !== void 0 ? _a : 0; + if (this.rawToken && this.expiresAt) { + return this.expiresAt <= now + eagerRefreshThresholdMillis; + } + else { + return true; + } + } + getToken(callback, opts = {}) { + if (typeof callback === 'object') { + opts = callback; + callback = undefined; + } + opts = Object.assign({ + forceRefresh: false, + }, opts); + if (callback) { + const cb = callback; + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_getTokenAsync).call(this, opts).then(t => cb(null, t), callback); + return; + } + return __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_getTokenAsync).call(this, opts); + } + /** + * Given a keyFile, extract the key and client email if available + * @param keyFile Path to a json, pem, or p12 file that contains the key. + * @returns an object with privateKey and clientEmail properties + */ + async getCredentials(keyFile) { + const ext = path.extname(keyFile); + switch (ext) { + case '.json': { + const key = await readFile(keyFile, 'utf8'); + const body = JSON.parse(key); + const privateKey = body.private_key; + const clientEmail = body.client_email; + if (!privateKey || !clientEmail) { + throw new ErrorWithCode('private_key and client_email are required.', 'MISSING_CREDENTIALS'); + } + return { privateKey, clientEmail }; + } + case '.der': + case '.crt': + case '.pem': { + const privateKey = await readFile(keyFile, 'utf8'); + return { privateKey }; + } + case '.p12': + case '.pfx': { + throw new ErrorWithCode('*.p12 certificates are not supported after v6.1.2. ' + + 'Consider utilizing *.json format or converting *.p12 to *.pem using the OpenSSL CLI.', 'UNKNOWN_CERTIFICATE_TYPE'); + } + default: + throw new ErrorWithCode('Unknown certificate type. Type is determined based on file extension. ' + + 'Current supported extensions are *.json, and *.pem.', 'UNKNOWN_CERTIFICATE_TYPE'); + } + } + revokeToken(callback) { + if (callback) { + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_revokeTokenAsync).call(this).then(() => callback(), callback); + return; + } + return __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_revokeTokenAsync).call(this); + } +} +exports.GoogleToken = GoogleToken; +_GoogleToken_inFlightRequest = new WeakMap(), _GoogleToken_instances = new WeakSet(), _GoogleToken_getTokenAsync = async function _GoogleToken_getTokenAsync(opts) { + if (__classPrivateFieldGet(this, _GoogleToken_inFlightRequest, "f") && !opts.forceRefresh) { + return __classPrivateFieldGet(this, _GoogleToken_inFlightRequest, "f"); + } + try { + return await (__classPrivateFieldSet(this, _GoogleToken_inFlightRequest, __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_getTokenAsyncInner).call(this, opts), "f")); + } + finally { + __classPrivateFieldSet(this, _GoogleToken_inFlightRequest, undefined, "f"); + } +}, _GoogleToken_getTokenAsyncInner = async function _GoogleToken_getTokenAsyncInner(opts) { + if (this.isTokenExpiring() === false && opts.forceRefresh === false) { + return Promise.resolve(this.rawToken); + } + if (!this.key && !this.keyFile) { + throw new Error('No key or keyFile set.'); + } + if (!this.key && this.keyFile) { + const creds = await this.getCredentials(this.keyFile); + this.key = creds.privateKey; + this.iss = creds.clientEmail || this.iss; + if (!creds.clientEmail) { + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_ensureEmail).call(this); + } + } + return __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_requestToken).call(this); +}, _GoogleToken_ensureEmail = function _GoogleToken_ensureEmail() { + if (!this.iss) { + throw new ErrorWithCode('email is required.', 'MISSING_CREDENTIALS'); + } +}, _GoogleToken_revokeTokenAsync = async function _GoogleToken_revokeTokenAsync() { + if (!this.accessToken) { + throw new Error('No token to revoke.'); + } + const url = GOOGLE_REVOKE_TOKEN_URL + this.accessToken; + await this.transporter.request({ + url, + retry: true, + }); + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_configure).call(this, { + email: this.iss, + sub: this.sub, + key: this.key, + keyFile: this.keyFile, + scope: this.scope, + additionalClaims: this.additionalClaims, + }); +}, _GoogleToken_configure = function _GoogleToken_configure(options = {}) { + this.keyFile = options.keyFile; + this.key = options.key; + this.rawToken = undefined; + this.iss = options.email || options.iss; + this.sub = options.sub; + this.additionalClaims = options.additionalClaims; + if (typeof options.scope === 'object') { + this.scope = options.scope.join(' '); + } + else { + this.scope = options.scope; + } + this.eagerRefreshThresholdMillis = options.eagerRefreshThresholdMillis; + if (options.transporter) { + this.transporter = options.transporter; + } +}, _GoogleToken_requestToken = +/** + * Request the token from Google. + */ +async function _GoogleToken_requestToken() { + var _a, _b; + const iat = Math.floor(new Date().getTime() / 1000); + const additionalClaims = this.additionalClaims || {}; + const payload = Object.assign({ + iss: this.iss, + scope: this.scope, + aud: GOOGLE_TOKEN_URL, + exp: iat + 3600, + iat, + sub: this.sub, + }, additionalClaims); + const signedJWT = jws.sign({ + header: { alg: 'RS256' }, + payload, + secret: this.key, + }); + try { + const r = await this.transporter.request({ + method: 'POST', + url: GOOGLE_TOKEN_URL, + data: { + grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', + assertion: signedJWT, + }, + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'json', + retryConfig: { + httpMethodsToRetry: ['POST'], + }, + }); + this.rawToken = r.data; + this.expiresAt = + r.data.expires_in === null || r.data.expires_in === undefined + ? undefined + : (iat + r.data.expires_in) * 1000; + return this.rawToken; + } + catch (e) { + this.rawToken = undefined; + this.tokenExpires = undefined; + const body = e.response && ((_a = e.response) === null || _a === void 0 ? void 0 : _a.data) + ? (_b = e.response) === null || _b === void 0 ? void 0 : _b.data + : {}; + if (body.error) { + const desc = body.error_description + ? `: ${body.error_description}` + : ''; + e.message = `${body.error}${desc}`; + } + throw e; + } +}; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 77847: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const net_1 = __importDefault(__nccwpck_require__(69278)); +const tls_1 = __importDefault(__nccwpck_require__(64756)); +const url_1 = __importDefault(__nccwpck_require__(87016)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const once_1 = __importDefault(__nccwpck_require__(48662)); +const agent_base_1 = __nccwpck_require__(32960); +const debug = (0, debug_1.default)('http-proxy-agent'); +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +/** + * The `HttpProxyAgent` implements an HTTP Agent subclass that connects + * to the specified "HTTP proxy server" in order to proxy HTTP requests. + * + * @api public + */ +class HttpProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('Creating new HttpProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + const parsed = url_1.default.parse(req.path); + if (!parsed.protocol) { + parsed.protocol = 'http:'; + } + if (!parsed.hostname) { + parsed.hostname = opts.hostname || opts.host || null; + } + if (parsed.port == null && typeof opts.port) { + parsed.port = String(opts.port); + } + if (parsed.port === '80') { + // if port is 80, then we can remove the port so that the + // ":80" portion is not on the produced URL + parsed.port = ''; + } + // Change the `http.ClientRequest` instance's "path" field + // to the absolute path of the URL that will be requested. + req.path = url_1.default.format(parsed); + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + req.setHeader('Proxy-Authorization', `Basic ${Buffer.from(proxy.auth).toString('base64')}`); + } + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + // At this point, the http ClientRequest's internal `_header` field + // might have already been set. If this is the case then we'll need + // to re-generate the string since we just changed the `req.path`. + if (req._header) { + let first; + let endOfHeaders; + debug('Regenerating stored HTTP header string for request'); + req._header = null; + req._implicitHeader(); + if (req.output && req.output.length > 0) { + // Node < 12 + debug('Patching connection write() output buffer with updated header'); + first = req.output[0]; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.output[0] = req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.output); + } + else if (req.outputData && req.outputData.length > 0) { + // Node >= 12 + debug('Patching connection write() output buffer with updated header'); + first = req.outputData[0].data; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.outputData[0].data = + req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.outputData[0].data); + } + } + // Wait for the socket's `connect` event, so that this `callback()` + // function throws instead of the `http` request machinery. This is + // important for i.e. `PacProxyAgent` which determines a failed proxy + // connection via the `callback()` function throwing. + yield (0, once_1.default)(socket, 'connect'); + return socket; + }); + } +} +exports["default"] = HttpProxyAgent; +//# sourceMappingURL=agent.js.map + +/***/ }), + +/***/ 81970: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const agent_1 = __importDefault(__nccwpck_require__(77847)); +function createHttpProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpProxyAgent) { + createHttpProxyAgent.HttpProxyAgent = agent_1.default; + createHttpProxyAgent.prototype = agent_1.default.prototype; +})(createHttpProxyAgent || (createHttpProxyAgent = {})); +module.exports = createHttpProxyAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 32960: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = __nccwpck_require__(24434); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const promisify_1 = __importDefault(__nccwpck_require__(62600)); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 62600: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports["default"] = promisify; +//# sourceMappingURL=promisify.js.map + +/***/ }), + +/***/ 3669: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpsProxyAgent = void 0; +const net = __importStar(__nccwpck_require__(69278)); +const tls = __importStar(__nccwpck_require__(64756)); +const assert_1 = __importDefault(__nccwpck_require__(42613)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const agent_base_1 = __nccwpck_require__(98894); +const url_1 = __nccwpck_require__(87016); +const parse_proxy_response_1 = __nccwpck_require__(37943); +const debug = (0, debug_1.default)('https-proxy-agent'); +const setServernameFromNonIpHost = (options) => { + if (options.servername === undefined && + options.host && + !net.isIP(options.host)) { + return { + ...options, + servername: options.host, + }; + } + return options; +}; +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(proxy, opts) { + super(opts); + this.options = { path: undefined }; + this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy; + this.proxyHeaders = opts?.headers ?? {}; + debug('Creating new HttpsProxyAgent instance: %o', this.proxy.href); + // Trim off the brackets from IPv6 addresses + const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ''); + const port = this.proxy.port + ? parseInt(this.proxy.port, 10) + : this.proxy.protocol === 'https:' + ? 443 + : 80; + this.connectOpts = { + // Attempt to negotiate http/1.1 for proxy servers that support http/2 + ALPNProtocols: ['http/1.1'], + ...(opts ? omit(opts, 'headers') : null), + host, + port, + }; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + */ + async connect(req, opts) { + const { proxy } = this; + if (!opts.host) { + throw new TypeError('No "host" provided'); + } + // Create a socket connection to the proxy server. + let socket; + if (proxy.protocol === 'https:') { + debug('Creating `tls.Socket`: %o', this.connectOpts); + socket = tls.connect(setServernameFromNonIpHost(this.connectOpts)); + } + else { + debug('Creating `net.Socket`: %o', this.connectOpts); + socket = net.connect(this.connectOpts); + } + const headers = typeof this.proxyHeaders === 'function' + ? this.proxyHeaders() + : { ...this.proxyHeaders }; + const host = net.isIPv6(opts.host) ? `[${opts.host}]` : opts.host; + let payload = `CONNECT ${host}:${opts.port} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.username || proxy.password) { + const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`; + headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`; + } + headers.Host = `${host}:${opts.port}`; + if (!headers['Proxy-Connection']) { + headers['Proxy-Connection'] = this.keepAlive + ? 'Keep-Alive' + : 'close'; + } + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = (0, parse_proxy_response_1.parseProxyResponse)(socket); + socket.write(`${payload}\r\n`); + const { connect, buffered } = await proxyResponsePromise; + req.emit('proxyConnect', connect); + this.emit('proxyConnect', connect, req); + if (connect.statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + return tls.connect({ + ...omit(setServernameFromNonIpHost(opts), 'host', 'path', 'port'), + socket, + }); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net.Socket({ writable: false }); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('Replaying proxy buffer for failed request'); + (0, assert_1.default)(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + } +} +HttpsProxyAgent.protocols = ['http', 'https']; +exports.HttpsProxyAgent = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 37943: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.parseProxyResponse = void 0; +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const debug = (0, debug_1.default)('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('readable', read); + } + function onend() { + cleanup(); + debug('onend'); + reject(new Error('Proxy connection ended before receiving CONNECT response')); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const headerParts = buffered + .slice(0, endOfHeaders) + .toString('ascii') + .split('\r\n'); + const firstLine = headerParts.shift(); + if (!firstLine) { + socket.destroy(); + return reject(new Error('No header received from proxy CONNECT response')); + } + const firstLineParts = firstLine.split(' '); + const statusCode = +firstLineParts[1]; + const statusText = firstLineParts.slice(2).join(' '); + const headers = {}; + for (const header of headerParts) { + if (!header) + continue; + const firstColon = header.indexOf(':'); + if (firstColon === -1) { + socket.destroy(); + return reject(new Error(`Invalid header from proxy CONNECT response: "${header}"`)); + } + const key = header.slice(0, firstColon).toLowerCase(); + const value = header.slice(firstColon + 1).trimStart(); + const current = headers[key]; + if (typeof current === 'string') { + headers[key] = [current, value]; + } + else if (Array.isArray(current)) { + current.push(value); + } + else { + headers[key] = value; + } + } + debug('got proxy server response: %o %o', firstLine, headers); + cleanup(); + resolve({ + connect: { + statusCode, + statusText, + headers, + }, + buffered, + }); + } + socket.on('error', onerror); + socket.on('end', onend); + read(); + }); +} +exports.parseProxyResponse = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map + +/***/ }), + +/***/ 39598: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +try { + var util = __nccwpck_require__(39023); + /* istanbul ignore next */ + if (typeof util.inherits !== 'function') throw ''; + module.exports = util.inherits; +} catch (e) { + /* istanbul ignore next */ + module.exports = __nccwpck_require__(26589); +} + + +/***/ }), + +/***/ 26589: +/***/ ((module) => { + +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }) + } + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } +} + + +/***/ }), + +/***/ 96543: +/***/ ((module) => { + +"use strict"; + + +const isStream = stream => + stream !== null && + typeof stream === 'object' && + typeof stream.pipe === 'function'; + +isStream.writable = stream => + isStream(stream) && + stream.writable !== false && + typeof stream._write === 'function' && + typeof stream._writableState === 'object'; + +isStream.readable = stream => + isStream(stream) && + stream.readable !== false && + typeof stream._read === 'function' && + typeof stream._readableState === 'object'; + +isStream.duplex = stream => + isStream.writable(stream) && + isStream.readable(stream); + +isStream.transform = stream => + isStream.duplex(stream) && + typeof stream._transform === 'function'; + +module.exports = isStream; + + +/***/ }), + +/***/ 14826: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var json_stringify = (__nccwpck_require__(93651).stringify); +var json_parse = __nccwpck_require__(3197); + +module.exports = function(options) { + return { + parse: json_parse(options), + stringify: json_stringify + } +}; +//create the default method members with no options applied for backwards compatibility +module.exports.parse = json_parse(); +module.exports.stringify = json_stringify; + + +/***/ }), + +/***/ 3197: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var BigNumber = null; + +// regexpxs extracted from +// (c) BSD-3-Clause +// https://github.com/fastify/secure-json-parse/graphs/contributors and https://github.com/hapijs/bourne/graphs/contributors + +const suspectProtoRx = /(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])/; +const suspectConstructorRx = /(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)/; + +/* + json_parse.js + 2012-06-20 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + This file creates a json_parse function. + During create you can (optionally) specify some behavioural switches + + require('json-bigint')(options) + + The optional options parameter holds switches that drive certain + aspects of the parsing process: + * options.strict = true will warn about duplicate-key usage in the json. + The default (strict = false) will silently ignore those and overwrite + values for keys that are in duplicate use. + + The resulting function follows this signature: + json_parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = json_parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + This is a reference implementation. You are free to copy, modify, or + redistribute. + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. +*/ + +/*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode, + hasOwnProperty, message, n, name, prototype, push, r, t, text +*/ + +var json_parse = function (options) { + 'use strict'; + + // This is a function that can parse a JSON text, producing a JavaScript + // data structure. It is a simple, recursive descent parser. It does not use + // eval or regular expressions, so it can be used as a model for implementing + // a JSON parser in other languages. + + // We are defining the function inside of another function to avoid creating + // global variables. + + // Default options one can override by passing options to the parse() + var _options = { + strict: false, // not being strict means do not generate syntax errors for "duplicate key" + storeAsString: false, // toggles whether the values should be stored as BigNumber (default) or a string + alwaysParseAsBig: false, // toggles whether all numbers should be Big + useNativeBigInt: false, // toggles whether to use native BigInt instead of bignumber.js + protoAction: 'error', + constructorAction: 'error', + }; + + // If there are options, then use them to override the default _options + if (options !== undefined && options !== null) { + if (options.strict === true) { + _options.strict = true; + } + if (options.storeAsString === true) { + _options.storeAsString = true; + } + _options.alwaysParseAsBig = + options.alwaysParseAsBig === true ? options.alwaysParseAsBig : false; + _options.useNativeBigInt = + options.useNativeBigInt === true ? options.useNativeBigInt : false; + + if (typeof options.constructorAction !== 'undefined') { + if ( + options.constructorAction === 'error' || + options.constructorAction === 'ignore' || + options.constructorAction === 'preserve' + ) { + _options.constructorAction = options.constructorAction; + } else { + throw new Error( + `Incorrect value for constructorAction option, must be "error", "ignore" or undefined but passed ${options.constructorAction}` + ); + } + } + + if (typeof options.protoAction !== 'undefined') { + if ( + options.protoAction === 'error' || + options.protoAction === 'ignore' || + options.protoAction === 'preserve' + ) { + _options.protoAction = options.protoAction; + } else { + throw new Error( + `Incorrect value for protoAction option, must be "error", "ignore" or undefined but passed ${options.protoAction}` + ); + } + } + } + + var at, // The index of the current character + ch, // The current character + escapee = { + '"': '"', + '\\': '\\', + '/': '/', + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t', + }, + text, + error = function (m) { + // Call error when something is wrong. + + throw { + name: 'SyntaxError', + message: m, + at: at, + text: text, + }; + }, + next = function (c) { + // If a c parameter is provided, verify that it matches the current character. + + if (c && c !== ch) { + error("Expected '" + c + "' instead of '" + ch + "'"); + } + + // Get the next character. When there are no more characters, + // return the empty string. + + ch = text.charAt(at); + at += 1; + return ch; + }, + number = function () { + // Parse a number value. + + var number, + string = ''; + + if (ch === '-') { + string = '-'; + next('-'); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (!isFinite(number)) { + error('Bad number'); + } else { + if (BigNumber == null) BigNumber = __nccwpck_require__(51259); + //if (number > 9007199254740992 || number < -9007199254740992) + // Bignumber has stricter check: everything with length > 15 digits disallowed + if (string.length > 15) + return _options.storeAsString + ? string + : _options.useNativeBigInt + ? BigInt(string) + : new BigNumber(string); + else + return !_options.alwaysParseAsBig + ? number + : _options.useNativeBigInt + ? BigInt(number) + : new BigNumber(number); + } + }, + string = function () { + // Parse a string value. + + var hex, + i, + string = '', + uffff; + + // When parsing for string values, we must look for " and \ characters. + + if (ch === '"') { + var startAt = at; + while (next()) { + if (ch === '"') { + if (at - 1 > startAt) string += text.substring(startAt, at - 1); + next(); + return string; + } + if (ch === '\\') { + if (at - 1 > startAt) string += text.substring(startAt, at - 1); + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + startAt = at; + } + } + } + error('Bad string'); + }, + white = function () { + // Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + word = function () { + // true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + value, // Place holder for the value function. + array = function () { + // Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error('Bad array'); + }, + object = function () { + // Parse an object value. + + var key, + object = Object.create(null); + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if ( + _options.strict === true && + Object.hasOwnProperty.call(object, key) + ) { + error('Duplicate key "' + key + '"'); + } + + if (suspectProtoRx.test(key) === true) { + if (_options.protoAction === 'error') { + error('Object contains forbidden prototype property'); + } else if (_options.protoAction === 'ignore') { + value(); + } else { + object[key] = value(); + } + } else if (suspectConstructorRx.test(key) === true) { + if (_options.constructorAction === 'error') { + error('Object contains forbidden constructor property'); + } else if (_options.constructorAction === 'ignore') { + value(); + } else { + object[key] = value(); + } + } else { + object[key] = value(); + } + + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error('Bad object'); + }; + + value = function () { + // Parse a JSON value. It could be an object, an array, a string, a number, + // or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } + }; + + // Return the json_parse function. It will have access to all of the above + // functions and variables. + + return function (source, reviver) { + var result; + + text = source + ''; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error('Syntax error'); + } + + // If there is a reviver function, we recursively walk the new structure, + // passing each name/value pair to the reviver function for possible + // transformation, starting with a temporary root object that holds the result + // in an empty key. If there is not a reviver function, we simply return the + // result. + + return typeof reviver === 'function' + ? (function walk(holder, key) { + var k, + v, + value = holder[key]; + if (value && typeof value === 'object') { + Object.keys(value).forEach(function (k) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + }); + } + return reviver.call(holder, key, value); + })({ '': result }, '') + : result; + }; +}; + +module.exports = json_parse; + + +/***/ }), + +/***/ 93651: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var BigNumber = __nccwpck_require__(51259); + +/* + json2.js + 2013-05-26 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, regexp: true */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +var JSON = module.exports; + +(function () { + 'use strict'; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' + ? c + : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key], + isBigNumber = value != null && (value instanceof BigNumber || BigNumber.isBigNumber(value)); + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + if (isBigNumber) { + return value; + } else { + return quote(value); + } + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + case 'bigint': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 + ? '[]' + : gap + ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' + : '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === 'string') { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + Object.keys(value).forEach(function(k) { + var v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + }); + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 + ? '{}' + : gap + ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' + : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } +}()); + + +/***/ }), + +/***/ 38622: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var Buffer = (__nccwpck_require__(93058).Buffer); +var crypto = __nccwpck_require__(76982); +var formatEcdsa = __nccwpck_require__(325); +var util = __nccwpck_require__(39023); + +var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".' +var MSG_INVALID_SECRET = 'secret must be a string or buffer'; +var MSG_INVALID_VERIFIER_KEY = 'key must be a string or a buffer'; +var MSG_INVALID_SIGNER_KEY = 'key must be a string, a buffer or an object'; + +var supportsKeyObjects = typeof crypto.createPublicKey === 'function'; +if (supportsKeyObjects) { + MSG_INVALID_VERIFIER_KEY += ' or a KeyObject'; + MSG_INVALID_SECRET += 'or a KeyObject'; +} + +function checkIsPublicKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.type !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.asymmetricKeyType !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } +}; + +function checkIsPrivateKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (typeof key === 'object') { + return; + } + + throw typeError(MSG_INVALID_SIGNER_KEY); +}; + +function checkIsSecretKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return key; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_SECRET); + } + + if (key.type !== 'secret') { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_SECRET); + } +} + +function fromBase64(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function toBase64(base64url) { + base64url = base64url.toString(); + + var padding = 4 - base64url.length % 4; + if (padding !== 4) { + for (var i = 0; i < padding; ++i) { + base64url += '='; + } + } + + return base64url + .replace(/\-/g, '+') + .replace(/_/g, '/'); +} + +function typeError(template) { + var args = [].slice.call(arguments, 1); + var errMsg = util.format.bind(util, template).apply(null, args); + return new TypeError(errMsg); +} + +function bufferOrString(obj) { + return Buffer.isBuffer(obj) || typeof obj === 'string'; +} + +function normalizeInput(thing) { + if (!bufferOrString(thing)) + thing = JSON.stringify(thing); + return thing; +} + +function createHmacSigner(bits) { + return function sign(thing, secret) { + checkIsSecretKey(secret); + thing = normalizeInput(thing); + var hmac = crypto.createHmac('sha' + bits, secret); + var sig = (hmac.update(thing), hmac.digest('base64')) + return fromBase64(sig); + } +} + +var bufferEqual; +var timingSafeEqual = 'timingSafeEqual' in crypto ? function timingSafeEqual(a, b) { + if (a.byteLength !== b.byteLength) { + return false; + } + + return crypto.timingSafeEqual(a, b) +} : function timingSafeEqual(a, b) { + if (!bufferEqual) { + bufferEqual = __nccwpck_require__(39732); + } + + return bufferEqual(a, b) +} + +function createHmacVerifier(bits) { + return function verify(thing, signature, secret) { + var computedSig = createHmacSigner(bits)(thing, secret); + return timingSafeEqual(Buffer.from(signature), Buffer.from(computedSig)); + } +} + +function createKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + // Even though we are specifying "RSA" here, this works with ECDSA + // keys as well. + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign(privateKey, 'base64')); + return fromBase64(sig); + } +} + +function createKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify(publicKey, signature, 'base64'); + } +} + +function createPSSKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign({ + key: privateKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, 'base64')); + return fromBase64(sig); + } +} + +function createPSSKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify({ + key: publicKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, signature, 'base64'); + } +} + +function createECDSASigner(bits) { + var inner = createKeySigner(bits); + return function sign() { + var signature = inner.apply(null, arguments); + signature = formatEcdsa.derToJose(signature, 'ES' + bits); + return signature; + }; +} + +function createECDSAVerifer(bits) { + var inner = createKeyVerifier(bits); + return function verify(thing, signature, publicKey) { + signature = formatEcdsa.joseToDer(signature, 'ES' + bits).toString('base64'); + var result = inner(thing, signature, publicKey); + return result; + }; +} + +function createNoneSigner() { + return function sign() { + return ''; + } +} + +function createNoneVerifier() { + return function verify(thing, signature) { + return signature === ''; + } +} + +module.exports = function jwa(algorithm) { + var signerFactories = { + hs: createHmacSigner, + rs: createKeySigner, + ps: createPSSKeySigner, + es: createECDSASigner, + none: createNoneSigner, + } + var verifierFactories = { + hs: createHmacVerifier, + rs: createKeyVerifier, + ps: createPSSKeyVerifier, + es: createECDSAVerifer, + none: createNoneVerifier, + } + var match = algorithm.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/); + if (!match) + throw typeError(MSG_INVALID_ALGORITHM, algorithm); + var algo = (match[1] || match[3]).toLowerCase(); + var bits = match[2]; + + return { + sign: signerFactories[algo](bits), + verify: verifierFactories[algo](bits), + } +}; + + +/***/ }), + +/***/ 33324: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +/*global exports*/ +var SignStream = __nccwpck_require__(78600); +var VerifyStream = __nccwpck_require__(4368); + +var ALGORITHMS = [ + 'HS256', 'HS384', 'HS512', + 'RS256', 'RS384', 'RS512', + 'PS256', 'PS384', 'PS512', + 'ES256', 'ES384', 'ES512' +]; + +exports.ALGORITHMS = ALGORITHMS; +exports.sign = SignStream.sign; +exports.verify = VerifyStream.verify; +exports.decode = VerifyStream.decode; +exports.isValid = VerifyStream.isValid; +exports.createSign = function createSign(opts) { + return new SignStream(opts); +}; +exports.createVerify = function createVerify(opts) { + return new VerifyStream(opts); +}; + + +/***/ }), + +/***/ 41831: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module, process*/ +var Buffer = (__nccwpck_require__(93058).Buffer); +var Stream = __nccwpck_require__(2203); +var util = __nccwpck_require__(39023); + +function DataStream(data) { + this.buffer = null; + this.writable = true; + this.readable = true; + + // No input + if (!data) { + this.buffer = Buffer.alloc(0); + return this; + } + + // Stream + if (typeof data.pipe === 'function') { + this.buffer = Buffer.alloc(0); + data.pipe(this); + return this; + } + + // Buffer or String + // or Object (assumedly a passworded key) + if (data.length || typeof data === 'object') { + this.buffer = data; + this.writable = false; + process.nextTick(function () { + this.emit('end', data); + this.readable = false; + this.emit('close'); + }.bind(this)); + return this; + } + + throw new TypeError('Unexpected data type ('+ typeof data + ')'); +} +util.inherits(DataStream, Stream); + +DataStream.prototype.write = function write(data) { + this.buffer = Buffer.concat([this.buffer, Buffer.from(data)]); + this.emit('data', data); +}; + +DataStream.prototype.end = function end(data) { + if (data) + this.write(data); + this.emit('end', data); + this.emit('close'); + this.writable = false; + this.readable = false; +}; + +module.exports = DataStream; + + +/***/ }), + +/***/ 78600: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(93058).Buffer); +var DataStream = __nccwpck_require__(41831); +var jwa = __nccwpck_require__(38622); +var Stream = __nccwpck_require__(2203); +var toString = __nccwpck_require__(95126); +var util = __nccwpck_require__(39023); + +function base64url(string, encoding) { + return Buffer + .from(string, encoding) + .toString('base64') + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function jwsSecuredInput(header, payload, encoding) { + encoding = encoding || 'utf8'; + var encodedHeader = base64url(toString(header), 'binary'); + var encodedPayload = base64url(toString(payload), encoding); + return util.format('%s.%s', encodedHeader, encodedPayload); +} + +function jwsSign(opts) { + var header = opts.header; + var payload = opts.payload; + var secretOrKey = opts.secret || opts.privateKey; + var encoding = opts.encoding; + var algo = jwa(header.alg); + var securedInput = jwsSecuredInput(header, payload, encoding); + var signature = algo.sign(securedInput, secretOrKey); + return util.format('%s.%s', securedInput, signature); +} + +function SignStream(opts) { + var secret = opts.secret||opts.privateKey||opts.key; + var secretStream = new DataStream(secret); + this.readable = true; + this.header = opts.header; + this.encoding = opts.encoding; + this.secret = this.privateKey = this.key = secretStream; + this.payload = new DataStream(opts.payload); + this.secret.once('close', function () { + if (!this.payload.writable && this.readable) + this.sign(); + }.bind(this)); + + this.payload.once('close', function () { + if (!this.secret.writable && this.readable) + this.sign(); + }.bind(this)); +} +util.inherits(SignStream, Stream); + +SignStream.prototype.sign = function sign() { + try { + var signature = jwsSign({ + header: this.header, + payload: this.payload.buffer, + secret: this.secret.buffer, + encoding: this.encoding + }); + this.emit('done', signature); + this.emit('data', signature); + this.emit('end'); + this.readable = false; + return signature; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +SignStream.sign = jwsSign; + +module.exports = SignStream; + + +/***/ }), + +/***/ 95126: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(20181).Buffer); + +module.exports = function toString(obj) { + if (typeof obj === 'string') + return obj; + if (typeof obj === 'number' || Buffer.isBuffer(obj)) + return obj.toString(); + return JSON.stringify(obj); +}; + + +/***/ }), + +/***/ 4368: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(93058).Buffer); +var DataStream = __nccwpck_require__(41831); +var jwa = __nccwpck_require__(38622); +var Stream = __nccwpck_require__(2203); +var toString = __nccwpck_require__(95126); +var util = __nccwpck_require__(39023); +var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/; + +function isObject(thing) { + return Object.prototype.toString.call(thing) === '[object Object]'; +} + +function safeJsonParse(thing) { + if (isObject(thing)) + return thing; + try { return JSON.parse(thing); } + catch (e) { return undefined; } +} + +function headerFromJWS(jwsSig) { + var encodedHeader = jwsSig.split('.', 1)[0]; + return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary')); +} + +function securedInputFromJWS(jwsSig) { + return jwsSig.split('.', 2).join('.'); +} + +function signatureFromJWS(jwsSig) { + return jwsSig.split('.')[2]; +} + +function payloadFromJWS(jwsSig, encoding) { + encoding = encoding || 'utf8'; + var payload = jwsSig.split('.')[1]; + return Buffer.from(payload, 'base64').toString(encoding); +} + +function isValidJws(string) { + return JWS_REGEX.test(string) && !!headerFromJWS(string); +} + +function jwsVerify(jwsSig, algorithm, secretOrKey) { + if (!algorithm) { + var err = new Error("Missing algorithm parameter for jws.verify"); + err.code = "MISSING_ALGORITHM"; + throw err; + } + jwsSig = toString(jwsSig); + var signature = signatureFromJWS(jwsSig); + var securedInput = securedInputFromJWS(jwsSig); + var algo = jwa(algorithm); + return algo.verify(securedInput, signature, secretOrKey); +} + +function jwsDecode(jwsSig, opts) { + opts = opts || {}; + jwsSig = toString(jwsSig); + + if (!isValidJws(jwsSig)) + return null; + + var header = headerFromJWS(jwsSig); + + if (!header) + return null; + + var payload = payloadFromJWS(jwsSig); + if (header.typ === 'JWT' || opts.json) + payload = JSON.parse(payload, opts.encoding); + + return { + header: header, + payload: payload, + signature: signatureFromJWS(jwsSig) + }; +} + +function VerifyStream(opts) { + opts = opts || {}; + var secretOrKey = opts.secret||opts.publicKey||opts.key; + var secretStream = new DataStream(secretOrKey); + this.readable = true; + this.algorithm = opts.algorithm; + this.encoding = opts.encoding; + this.secret = this.publicKey = this.key = secretStream; + this.signature = new DataStream(opts.signature); + this.secret.once('close', function () { + if (!this.signature.writable && this.readable) + this.verify(); + }.bind(this)); + + this.signature.once('close', function () { + if (!this.secret.writable && this.readable) + this.verify(); + }.bind(this)); +} +util.inherits(VerifyStream, Stream); +VerifyStream.prototype.verify = function verify() { + try { + var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer); + var obj = jwsDecode(this.signature.buffer, this.encoding); + this.emit('done', valid, obj); + this.emit('data', valid); + this.emit('end'); + this.readable = false; + return valid; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +VerifyStream.decode = jwsDecode; +VerifyStream.isValid = isValidJws; +VerifyStream.verify = jwsVerify; + +module.exports = VerifyStream; + + +/***/ }), + +/***/ 14402: +/***/ ((module) => { + +"use strict"; + + +/** + * @param typeMap [Object] Map of MIME type -> Array[extensions] + * @param ... + */ +function Mime() { + this._types = Object.create(null); + this._extensions = Object.create(null); + + for (let i = 0; i < arguments.length; i++) { + this.define(arguments[i]); + } + + this.define = this.define.bind(this); + this.getType = this.getType.bind(this); + this.getExtension = this.getExtension.bind(this); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * If a type declares an extension that has already been defined, an error will + * be thrown. To suppress this error and force the extension to be associated + * with the new type, pass `force`=true. Alternatively, you may prefix the + * extension with "*" to map the type to extension, without mapping the + * extension to the type. + * + * e.g. mime.define({'audio/wav', ['wav']}, {'audio/x-wav', ['*wav']}); + * + * + * @param map (Object) type definitions + * @param force (Boolean) if true, force overriding of existing definitions + */ +Mime.prototype.define = function(typeMap, force) { + for (let type in typeMap) { + let extensions = typeMap[type].map(function(t) { + return t.toLowerCase(); + }); + type = type.toLowerCase(); + + for (let i = 0; i < extensions.length; i++) { + const ext = extensions[i]; + + // '*' prefix = not the preferred type for this extension. So fixup the + // extension, and skip it. + if (ext[0] === '*') { + continue; + } + + if (!force && (ext in this._types)) { + throw new Error( + 'Attempt to change mapping for "' + ext + + '" extension from "' + this._types[ext] + '" to "' + type + + '". Pass `force=true` to allow this, otherwise remove "' + ext + + '" from the list of extensions for "' + type + '".' + ); + } + + this._types[ext] = type; + } + + // Use first extension as default + if (force || !this._extensions[type]) { + const ext = extensions[0]; + this._extensions[type] = (ext[0] !== '*') ? ext : ext.substr(1); + } + } +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.getType = function(path) { + path = String(path); + let last = path.replace(/^.*[/\\]/, '').toLowerCase(); + let ext = last.replace(/^.*\./, '').toLowerCase(); + + let hasPath = last.length < path.length; + let hasDot = ext.length < last.length - 1; + + return (hasDot || !hasPath) && this._types[ext] || null; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.getExtension = function(type) { + type = /^\s*([^;\s]*)/.test(type) && RegExp.$1; + return type && this._extensions[type.toLowerCase()] || null; +}; + +module.exports = Mime; + + +/***/ }), + +/***/ 94900: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +let Mime = __nccwpck_require__(14402); +module.exports = new Mime(__nccwpck_require__(83725), __nccwpck_require__(68548)); + + +/***/ }), + +/***/ 68548: +/***/ ((module) => { + +module.exports = {"application/prs.cww":["cww"],"application/vnd.1000minds.decision-model+xml":["1km"],"application/vnd.3gpp.pic-bw-large":["plb"],"application/vnd.3gpp.pic-bw-small":["psb"],"application/vnd.3gpp.pic-bw-var":["pvb"],"application/vnd.3gpp2.tcap":["tcap"],"application/vnd.3m.post-it-notes":["pwn"],"application/vnd.accpac.simply.aso":["aso"],"application/vnd.accpac.simply.imp":["imp"],"application/vnd.acucobol":["acu"],"application/vnd.acucorp":["atc","acutc"],"application/vnd.adobe.air-application-installer-package+zip":["air"],"application/vnd.adobe.formscentral.fcdt":["fcdt"],"application/vnd.adobe.fxp":["fxp","fxpl"],"application/vnd.adobe.xdp+xml":["xdp"],"application/vnd.adobe.xfdf":["xfdf"],"application/vnd.ahead.space":["ahead"],"application/vnd.airzip.filesecure.azf":["azf"],"application/vnd.airzip.filesecure.azs":["azs"],"application/vnd.amazon.ebook":["azw"],"application/vnd.americandynamics.acc":["acc"],"application/vnd.amiga.ami":["ami"],"application/vnd.android.package-archive":["apk"],"application/vnd.anser-web-certificate-issue-initiation":["cii"],"application/vnd.anser-web-funds-transfer-initiation":["fti"],"application/vnd.antix.game-component":["atx"],"application/vnd.apple.installer+xml":["mpkg"],"application/vnd.apple.keynote":["key"],"application/vnd.apple.mpegurl":["m3u8"],"application/vnd.apple.numbers":["numbers"],"application/vnd.apple.pages":["pages"],"application/vnd.apple.pkpass":["pkpass"],"application/vnd.aristanetworks.swi":["swi"],"application/vnd.astraea-software.iota":["iota"],"application/vnd.audiograph":["aep"],"application/vnd.balsamiq.bmml+xml":["bmml"],"application/vnd.blueice.multipass":["mpm"],"application/vnd.bmi":["bmi"],"application/vnd.businessobjects":["rep"],"application/vnd.chemdraw+xml":["cdxml"],"application/vnd.chipnuts.karaoke-mmd":["mmd"],"application/vnd.cinderella":["cdy"],"application/vnd.citationstyles.style+xml":["csl"],"application/vnd.claymore":["cla"],"application/vnd.cloanto.rp9":["rp9"],"application/vnd.clonk.c4group":["c4g","c4d","c4f","c4p","c4u"],"application/vnd.cluetrust.cartomobile-config":["c11amc"],"application/vnd.cluetrust.cartomobile-config-pkg":["c11amz"],"application/vnd.commonspace":["csp"],"application/vnd.contact.cmsg":["cdbcmsg"],"application/vnd.cosmocaller":["cmc"],"application/vnd.crick.clicker":["clkx"],"application/vnd.crick.clicker.keyboard":["clkk"],"application/vnd.crick.clicker.palette":["clkp"],"application/vnd.crick.clicker.template":["clkt"],"application/vnd.crick.clicker.wordbank":["clkw"],"application/vnd.criticaltools.wbs+xml":["wbs"],"application/vnd.ctc-posml":["pml"],"application/vnd.cups-ppd":["ppd"],"application/vnd.curl.car":["car"],"application/vnd.curl.pcurl":["pcurl"],"application/vnd.dart":["dart"],"application/vnd.data-vision.rdz":["rdz"],"application/vnd.dbf":["dbf"],"application/vnd.dece.data":["uvf","uvvf","uvd","uvvd"],"application/vnd.dece.ttml+xml":["uvt","uvvt"],"application/vnd.dece.unspecified":["uvx","uvvx"],"application/vnd.dece.zip":["uvz","uvvz"],"application/vnd.denovo.fcselayout-link":["fe_launch"],"application/vnd.dna":["dna"],"application/vnd.dolby.mlp":["mlp"],"application/vnd.dpgraph":["dpg"],"application/vnd.dreamfactory":["dfac"],"application/vnd.ds-keypoint":["kpxx"],"application/vnd.dvb.ait":["ait"],"application/vnd.dvb.service":["svc"],"application/vnd.dynageo":["geo"],"application/vnd.ecowin.chart":["mag"],"application/vnd.enliven":["nml"],"application/vnd.epson.esf":["esf"],"application/vnd.epson.msf":["msf"],"application/vnd.epson.quickanime":["qam"],"application/vnd.epson.salt":["slt"],"application/vnd.epson.ssf":["ssf"],"application/vnd.eszigno3+xml":["es3","et3"],"application/vnd.ezpix-album":["ez2"],"application/vnd.ezpix-package":["ez3"],"application/vnd.fdf":["fdf"],"application/vnd.fdsn.mseed":["mseed"],"application/vnd.fdsn.seed":["seed","dataless"],"application/vnd.flographit":["gph"],"application/vnd.fluxtime.clip":["ftc"],"application/vnd.framemaker":["fm","frame","maker","book"],"application/vnd.frogans.fnc":["fnc"],"application/vnd.frogans.ltf":["ltf"],"application/vnd.fsc.weblaunch":["fsc"],"application/vnd.fujitsu.oasys":["oas"],"application/vnd.fujitsu.oasys2":["oa2"],"application/vnd.fujitsu.oasys3":["oa3"],"application/vnd.fujitsu.oasysgp":["fg5"],"application/vnd.fujitsu.oasysprs":["bh2"],"application/vnd.fujixerox.ddd":["ddd"],"application/vnd.fujixerox.docuworks":["xdw"],"application/vnd.fujixerox.docuworks.binder":["xbd"],"application/vnd.fuzzysheet":["fzs"],"application/vnd.genomatix.tuxedo":["txd"],"application/vnd.geogebra.file":["ggb"],"application/vnd.geogebra.tool":["ggt"],"application/vnd.geometry-explorer":["gex","gre"],"application/vnd.geonext":["gxt"],"application/vnd.geoplan":["g2w"],"application/vnd.geospace":["g3w"],"application/vnd.gmx":["gmx"],"application/vnd.google-apps.document":["gdoc"],"application/vnd.google-apps.presentation":["gslides"],"application/vnd.google-apps.spreadsheet":["gsheet"],"application/vnd.google-earth.kml+xml":["kml"],"application/vnd.google-earth.kmz":["kmz"],"application/vnd.grafeq":["gqf","gqs"],"application/vnd.groove-account":["gac"],"application/vnd.groove-help":["ghf"],"application/vnd.groove-identity-message":["gim"],"application/vnd.groove-injector":["grv"],"application/vnd.groove-tool-message":["gtm"],"application/vnd.groove-tool-template":["tpl"],"application/vnd.groove-vcard":["vcg"],"application/vnd.hal+xml":["hal"],"application/vnd.handheld-entertainment+xml":["zmm"],"application/vnd.hbci":["hbci"],"application/vnd.hhe.lesson-player":["les"],"application/vnd.hp-hpgl":["hpgl"],"application/vnd.hp-hpid":["hpid"],"application/vnd.hp-hps":["hps"],"application/vnd.hp-jlyt":["jlt"],"application/vnd.hp-pcl":["pcl"],"application/vnd.hp-pclxl":["pclxl"],"application/vnd.hydrostatix.sof-data":["sfd-hdstx"],"application/vnd.ibm.minipay":["mpy"],"application/vnd.ibm.modcap":["afp","listafp","list3820"],"application/vnd.ibm.rights-management":["irm"],"application/vnd.ibm.secure-container":["sc"],"application/vnd.iccprofile":["icc","icm"],"application/vnd.igloader":["igl"],"application/vnd.immervision-ivp":["ivp"],"application/vnd.immervision-ivu":["ivu"],"application/vnd.insors.igm":["igm"],"application/vnd.intercon.formnet":["xpw","xpx"],"application/vnd.intergeo":["i2g"],"application/vnd.intu.qbo":["qbo"],"application/vnd.intu.qfx":["qfx"],"application/vnd.ipunplugged.rcprofile":["rcprofile"],"application/vnd.irepository.package+xml":["irp"],"application/vnd.is-xpr":["xpr"],"application/vnd.isac.fcs":["fcs"],"application/vnd.jam":["jam"],"application/vnd.jcp.javame.midlet-rms":["rms"],"application/vnd.jisp":["jisp"],"application/vnd.joost.joda-archive":["joda"],"application/vnd.kahootz":["ktz","ktr"],"application/vnd.kde.karbon":["karbon"],"application/vnd.kde.kchart":["chrt"],"application/vnd.kde.kformula":["kfo"],"application/vnd.kde.kivio":["flw"],"application/vnd.kde.kontour":["kon"],"application/vnd.kde.kpresenter":["kpr","kpt"],"application/vnd.kde.kspread":["ksp"],"application/vnd.kde.kword":["kwd","kwt"],"application/vnd.kenameaapp":["htke"],"application/vnd.kidspiration":["kia"],"application/vnd.kinar":["kne","knp"],"application/vnd.koan":["skp","skd","skt","skm"],"application/vnd.kodak-descriptor":["sse"],"application/vnd.las.las+xml":["lasxml"],"application/vnd.llamagraphics.life-balance.desktop":["lbd"],"application/vnd.llamagraphics.life-balance.exchange+xml":["lbe"],"application/vnd.lotus-1-2-3":["123"],"application/vnd.lotus-approach":["apr"],"application/vnd.lotus-freelance":["pre"],"application/vnd.lotus-notes":["nsf"],"application/vnd.lotus-organizer":["org"],"application/vnd.lotus-screencam":["scm"],"application/vnd.lotus-wordpro":["lwp"],"application/vnd.macports.portpkg":["portpkg"],"application/vnd.mapbox-vector-tile":["mvt"],"application/vnd.mcd":["mcd"],"application/vnd.medcalcdata":["mc1"],"application/vnd.mediastation.cdkey":["cdkey"],"application/vnd.mfer":["mwf"],"application/vnd.mfmp":["mfm"],"application/vnd.micrografx.flo":["flo"],"application/vnd.micrografx.igx":["igx"],"application/vnd.mif":["mif"],"application/vnd.mobius.daf":["daf"],"application/vnd.mobius.dis":["dis"],"application/vnd.mobius.mbk":["mbk"],"application/vnd.mobius.mqy":["mqy"],"application/vnd.mobius.msl":["msl"],"application/vnd.mobius.plc":["plc"],"application/vnd.mobius.txf":["txf"],"application/vnd.mophun.application":["mpn"],"application/vnd.mophun.certificate":["mpc"],"application/vnd.mozilla.xul+xml":["xul"],"application/vnd.ms-artgalry":["cil"],"application/vnd.ms-cab-compressed":["cab"],"application/vnd.ms-excel":["xls","xlm","xla","xlc","xlt","xlw"],"application/vnd.ms-excel.addin.macroenabled.12":["xlam"],"application/vnd.ms-excel.sheet.binary.macroenabled.12":["xlsb"],"application/vnd.ms-excel.sheet.macroenabled.12":["xlsm"],"application/vnd.ms-excel.template.macroenabled.12":["xltm"],"application/vnd.ms-fontobject":["eot"],"application/vnd.ms-htmlhelp":["chm"],"application/vnd.ms-ims":["ims"],"application/vnd.ms-lrm":["lrm"],"application/vnd.ms-officetheme":["thmx"],"application/vnd.ms-outlook":["msg"],"application/vnd.ms-pki.seccat":["cat"],"application/vnd.ms-pki.stl":["*stl"],"application/vnd.ms-powerpoint":["ppt","pps","pot"],"application/vnd.ms-powerpoint.addin.macroenabled.12":["ppam"],"application/vnd.ms-powerpoint.presentation.macroenabled.12":["pptm"],"application/vnd.ms-powerpoint.slide.macroenabled.12":["sldm"],"application/vnd.ms-powerpoint.slideshow.macroenabled.12":["ppsm"],"application/vnd.ms-powerpoint.template.macroenabled.12":["potm"],"application/vnd.ms-project":["mpp","mpt"],"application/vnd.ms-word.document.macroenabled.12":["docm"],"application/vnd.ms-word.template.macroenabled.12":["dotm"],"application/vnd.ms-works":["wps","wks","wcm","wdb"],"application/vnd.ms-wpl":["wpl"],"application/vnd.ms-xpsdocument":["xps"],"application/vnd.mseq":["mseq"],"application/vnd.musician":["mus"],"application/vnd.muvee.style":["msty"],"application/vnd.mynfc":["taglet"],"application/vnd.neurolanguage.nlu":["nlu"],"application/vnd.nitf":["ntf","nitf"],"application/vnd.noblenet-directory":["nnd"],"application/vnd.noblenet-sealer":["nns"],"application/vnd.noblenet-web":["nnw"],"application/vnd.nokia.n-gage.ac+xml":["*ac"],"application/vnd.nokia.n-gage.data":["ngdat"],"application/vnd.nokia.n-gage.symbian.install":["n-gage"],"application/vnd.nokia.radio-preset":["rpst"],"application/vnd.nokia.radio-presets":["rpss"],"application/vnd.novadigm.edm":["edm"],"application/vnd.novadigm.edx":["edx"],"application/vnd.novadigm.ext":["ext"],"application/vnd.oasis.opendocument.chart":["odc"],"application/vnd.oasis.opendocument.chart-template":["otc"],"application/vnd.oasis.opendocument.database":["odb"],"application/vnd.oasis.opendocument.formula":["odf"],"application/vnd.oasis.opendocument.formula-template":["odft"],"application/vnd.oasis.opendocument.graphics":["odg"],"application/vnd.oasis.opendocument.graphics-template":["otg"],"application/vnd.oasis.opendocument.image":["odi"],"application/vnd.oasis.opendocument.image-template":["oti"],"application/vnd.oasis.opendocument.presentation":["odp"],"application/vnd.oasis.opendocument.presentation-template":["otp"],"application/vnd.oasis.opendocument.spreadsheet":["ods"],"application/vnd.oasis.opendocument.spreadsheet-template":["ots"],"application/vnd.oasis.opendocument.text":["odt"],"application/vnd.oasis.opendocument.text-master":["odm"],"application/vnd.oasis.opendocument.text-template":["ott"],"application/vnd.oasis.opendocument.text-web":["oth"],"application/vnd.olpc-sugar":["xo"],"application/vnd.oma.dd2+xml":["dd2"],"application/vnd.openblox.game+xml":["obgx"],"application/vnd.openofficeorg.extension":["oxt"],"application/vnd.openstreetmap.data+xml":["osm"],"application/vnd.openxmlformats-officedocument.presentationml.presentation":["pptx"],"application/vnd.openxmlformats-officedocument.presentationml.slide":["sldx"],"application/vnd.openxmlformats-officedocument.presentationml.slideshow":["ppsx"],"application/vnd.openxmlformats-officedocument.presentationml.template":["potx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":["xlsx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.template":["xltx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.document":["docx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.template":["dotx"],"application/vnd.osgeo.mapguide.package":["mgp"],"application/vnd.osgi.dp":["dp"],"application/vnd.osgi.subsystem":["esa"],"application/vnd.palm":["pdb","pqa","oprc"],"application/vnd.pawaafile":["paw"],"application/vnd.pg.format":["str"],"application/vnd.pg.osasli":["ei6"],"application/vnd.picsel":["efif"],"application/vnd.pmi.widget":["wg"],"application/vnd.pocketlearn":["plf"],"application/vnd.powerbuilder6":["pbd"],"application/vnd.previewsystems.box":["box"],"application/vnd.proteus.magazine":["mgz"],"application/vnd.publishare-delta-tree":["qps"],"application/vnd.pvi.ptid1":["ptid"],"application/vnd.quark.quarkxpress":["qxd","qxt","qwd","qwt","qxl","qxb"],"application/vnd.rar":["rar"],"application/vnd.realvnc.bed":["bed"],"application/vnd.recordare.musicxml":["mxl"],"application/vnd.recordare.musicxml+xml":["musicxml"],"application/vnd.rig.cryptonote":["cryptonote"],"application/vnd.rim.cod":["cod"],"application/vnd.rn-realmedia":["rm"],"application/vnd.rn-realmedia-vbr":["rmvb"],"application/vnd.route66.link66+xml":["link66"],"application/vnd.sailingtracker.track":["st"],"application/vnd.seemail":["see"],"application/vnd.sema":["sema"],"application/vnd.semd":["semd"],"application/vnd.semf":["semf"],"application/vnd.shana.informed.formdata":["ifm"],"application/vnd.shana.informed.formtemplate":["itp"],"application/vnd.shana.informed.interchange":["iif"],"application/vnd.shana.informed.package":["ipk"],"application/vnd.simtech-mindmapper":["twd","twds"],"application/vnd.smaf":["mmf"],"application/vnd.smart.teacher":["teacher"],"application/vnd.software602.filler.form+xml":["fo"],"application/vnd.solent.sdkm+xml":["sdkm","sdkd"],"application/vnd.spotfire.dxp":["dxp"],"application/vnd.spotfire.sfs":["sfs"],"application/vnd.stardivision.calc":["sdc"],"application/vnd.stardivision.draw":["sda"],"application/vnd.stardivision.impress":["sdd"],"application/vnd.stardivision.math":["smf"],"application/vnd.stardivision.writer":["sdw","vor"],"application/vnd.stardivision.writer-global":["sgl"],"application/vnd.stepmania.package":["smzip"],"application/vnd.stepmania.stepchart":["sm"],"application/vnd.sun.wadl+xml":["wadl"],"application/vnd.sun.xml.calc":["sxc"],"application/vnd.sun.xml.calc.template":["stc"],"application/vnd.sun.xml.draw":["sxd"],"application/vnd.sun.xml.draw.template":["std"],"application/vnd.sun.xml.impress":["sxi"],"application/vnd.sun.xml.impress.template":["sti"],"application/vnd.sun.xml.math":["sxm"],"application/vnd.sun.xml.writer":["sxw"],"application/vnd.sun.xml.writer.global":["sxg"],"application/vnd.sun.xml.writer.template":["stw"],"application/vnd.sus-calendar":["sus","susp"],"application/vnd.svd":["svd"],"application/vnd.symbian.install":["sis","sisx"],"application/vnd.syncml+xml":["xsm"],"application/vnd.syncml.dm+wbxml":["bdm"],"application/vnd.syncml.dm+xml":["xdm"],"application/vnd.syncml.dmddf+xml":["ddf"],"application/vnd.tao.intent-module-archive":["tao"],"application/vnd.tcpdump.pcap":["pcap","cap","dmp"],"application/vnd.tmobile-livetv":["tmo"],"application/vnd.trid.tpt":["tpt"],"application/vnd.triscape.mxs":["mxs"],"application/vnd.trueapp":["tra"],"application/vnd.ufdl":["ufd","ufdl"],"application/vnd.uiq.theme":["utz"],"application/vnd.umajin":["umj"],"application/vnd.unity":["unityweb"],"application/vnd.uoml+xml":["uoml"],"application/vnd.vcx":["vcx"],"application/vnd.visio":["vsd","vst","vss","vsw"],"application/vnd.visionary":["vis"],"application/vnd.vsf":["vsf"],"application/vnd.wap.wbxml":["wbxml"],"application/vnd.wap.wmlc":["wmlc"],"application/vnd.wap.wmlscriptc":["wmlsc"],"application/vnd.webturbo":["wtb"],"application/vnd.wolfram.player":["nbp"],"application/vnd.wordperfect":["wpd"],"application/vnd.wqd":["wqd"],"application/vnd.wt.stf":["stf"],"application/vnd.xara":["xar"],"application/vnd.xfdl":["xfdl"],"application/vnd.yamaha.hv-dic":["hvd"],"application/vnd.yamaha.hv-script":["hvs"],"application/vnd.yamaha.hv-voice":["hvp"],"application/vnd.yamaha.openscoreformat":["osf"],"application/vnd.yamaha.openscoreformat.osfpvg+xml":["osfpvg"],"application/vnd.yamaha.smaf-audio":["saf"],"application/vnd.yamaha.smaf-phrase":["spf"],"application/vnd.yellowriver-custom-menu":["cmp"],"application/vnd.zul":["zir","zirz"],"application/vnd.zzazz.deck+xml":["zaz"],"application/x-7z-compressed":["7z"],"application/x-abiword":["abw"],"application/x-ace-compressed":["ace"],"application/x-apple-diskimage":["*dmg"],"application/x-arj":["arj"],"application/x-authorware-bin":["aab","x32","u32","vox"],"application/x-authorware-map":["aam"],"application/x-authorware-seg":["aas"],"application/x-bcpio":["bcpio"],"application/x-bdoc":["*bdoc"],"application/x-bittorrent":["torrent"],"application/x-blorb":["blb","blorb"],"application/x-bzip":["bz"],"application/x-bzip2":["bz2","boz"],"application/x-cbr":["cbr","cba","cbt","cbz","cb7"],"application/x-cdlink":["vcd"],"application/x-cfs-compressed":["cfs"],"application/x-chat":["chat"],"application/x-chess-pgn":["pgn"],"application/x-chrome-extension":["crx"],"application/x-cocoa":["cco"],"application/x-conference":["nsc"],"application/x-cpio":["cpio"],"application/x-csh":["csh"],"application/x-debian-package":["*deb","udeb"],"application/x-dgc-compressed":["dgc"],"application/x-director":["dir","dcr","dxr","cst","cct","cxt","w3d","fgd","swa"],"application/x-doom":["wad"],"application/x-dtbncx+xml":["ncx"],"application/x-dtbook+xml":["dtb"],"application/x-dtbresource+xml":["res"],"application/x-dvi":["dvi"],"application/x-envoy":["evy"],"application/x-eva":["eva"],"application/x-font-bdf":["bdf"],"application/x-font-ghostscript":["gsf"],"application/x-font-linux-psf":["psf"],"application/x-font-pcf":["pcf"],"application/x-font-snf":["snf"],"application/x-font-type1":["pfa","pfb","pfm","afm"],"application/x-freearc":["arc"],"application/x-futuresplash":["spl"],"application/x-gca-compressed":["gca"],"application/x-glulx":["ulx"],"application/x-gnumeric":["gnumeric"],"application/x-gramps-xml":["gramps"],"application/x-gtar":["gtar"],"application/x-hdf":["hdf"],"application/x-httpd-php":["php"],"application/x-install-instructions":["install"],"application/x-iso9660-image":["*iso"],"application/x-iwork-keynote-sffkey":["*key"],"application/x-iwork-numbers-sffnumbers":["*numbers"],"application/x-iwork-pages-sffpages":["*pages"],"application/x-java-archive-diff":["jardiff"],"application/x-java-jnlp-file":["jnlp"],"application/x-keepass2":["kdbx"],"application/x-latex":["latex"],"application/x-lua-bytecode":["luac"],"application/x-lzh-compressed":["lzh","lha"],"application/x-makeself":["run"],"application/x-mie":["mie"],"application/x-mobipocket-ebook":["prc","mobi"],"application/x-ms-application":["application"],"application/x-ms-shortcut":["lnk"],"application/x-ms-wmd":["wmd"],"application/x-ms-wmz":["wmz"],"application/x-ms-xbap":["xbap"],"application/x-msaccess":["mdb"],"application/x-msbinder":["obd"],"application/x-mscardfile":["crd"],"application/x-msclip":["clp"],"application/x-msdos-program":["*exe"],"application/x-msdownload":["*exe","*dll","com","bat","*msi"],"application/x-msmediaview":["mvb","m13","m14"],"application/x-msmetafile":["*wmf","*wmz","*emf","emz"],"application/x-msmoney":["mny"],"application/x-mspublisher":["pub"],"application/x-msschedule":["scd"],"application/x-msterminal":["trm"],"application/x-mswrite":["wri"],"application/x-netcdf":["nc","cdf"],"application/x-ns-proxy-autoconfig":["pac"],"application/x-nzb":["nzb"],"application/x-perl":["pl","pm"],"application/x-pilot":["*prc","*pdb"],"application/x-pkcs12":["p12","pfx"],"application/x-pkcs7-certificates":["p7b","spc"],"application/x-pkcs7-certreqresp":["p7r"],"application/x-rar-compressed":["*rar"],"application/x-redhat-package-manager":["rpm"],"application/x-research-info-systems":["ris"],"application/x-sea":["sea"],"application/x-sh":["sh"],"application/x-shar":["shar"],"application/x-shockwave-flash":["swf"],"application/x-silverlight-app":["xap"],"application/x-sql":["sql"],"application/x-stuffit":["sit"],"application/x-stuffitx":["sitx"],"application/x-subrip":["srt"],"application/x-sv4cpio":["sv4cpio"],"application/x-sv4crc":["sv4crc"],"application/x-t3vm-image":["t3"],"application/x-tads":["gam"],"application/x-tar":["tar"],"application/x-tcl":["tcl","tk"],"application/x-tex":["tex"],"application/x-tex-tfm":["tfm"],"application/x-texinfo":["texinfo","texi"],"application/x-tgif":["*obj"],"application/x-ustar":["ustar"],"application/x-virtualbox-hdd":["hdd"],"application/x-virtualbox-ova":["ova"],"application/x-virtualbox-ovf":["ovf"],"application/x-virtualbox-vbox":["vbox"],"application/x-virtualbox-vbox-extpack":["vbox-extpack"],"application/x-virtualbox-vdi":["vdi"],"application/x-virtualbox-vhd":["vhd"],"application/x-virtualbox-vmdk":["vmdk"],"application/x-wais-source":["src"],"application/x-web-app-manifest+json":["webapp"],"application/x-x509-ca-cert":["der","crt","pem"],"application/x-xfig":["fig"],"application/x-xliff+xml":["*xlf"],"application/x-xpinstall":["xpi"],"application/x-xz":["xz"],"application/x-zmachine":["z1","z2","z3","z4","z5","z6","z7","z8"],"audio/vnd.dece.audio":["uva","uvva"],"audio/vnd.digital-winds":["eol"],"audio/vnd.dra":["dra"],"audio/vnd.dts":["dts"],"audio/vnd.dts.hd":["dtshd"],"audio/vnd.lucent.voice":["lvp"],"audio/vnd.ms-playready.media.pya":["pya"],"audio/vnd.nuera.ecelp4800":["ecelp4800"],"audio/vnd.nuera.ecelp7470":["ecelp7470"],"audio/vnd.nuera.ecelp9600":["ecelp9600"],"audio/vnd.rip":["rip"],"audio/x-aac":["aac"],"audio/x-aiff":["aif","aiff","aifc"],"audio/x-caf":["caf"],"audio/x-flac":["flac"],"audio/x-m4a":["*m4a"],"audio/x-matroska":["mka"],"audio/x-mpegurl":["m3u"],"audio/x-ms-wax":["wax"],"audio/x-ms-wma":["wma"],"audio/x-pn-realaudio":["ram","ra"],"audio/x-pn-realaudio-plugin":["rmp"],"audio/x-realaudio":["*ra"],"audio/x-wav":["*wav"],"chemical/x-cdx":["cdx"],"chemical/x-cif":["cif"],"chemical/x-cmdf":["cmdf"],"chemical/x-cml":["cml"],"chemical/x-csml":["csml"],"chemical/x-xyz":["xyz"],"image/prs.btif":["btif"],"image/prs.pti":["pti"],"image/vnd.adobe.photoshop":["psd"],"image/vnd.airzip.accelerator.azv":["azv"],"image/vnd.dece.graphic":["uvi","uvvi","uvg","uvvg"],"image/vnd.djvu":["djvu","djv"],"image/vnd.dvb.subtitle":["*sub"],"image/vnd.dwg":["dwg"],"image/vnd.dxf":["dxf"],"image/vnd.fastbidsheet":["fbs"],"image/vnd.fpx":["fpx"],"image/vnd.fst":["fst"],"image/vnd.fujixerox.edmics-mmr":["mmr"],"image/vnd.fujixerox.edmics-rlc":["rlc"],"image/vnd.microsoft.icon":["ico"],"image/vnd.ms-dds":["dds"],"image/vnd.ms-modi":["mdi"],"image/vnd.ms-photo":["wdp"],"image/vnd.net-fpx":["npx"],"image/vnd.pco.b16":["b16"],"image/vnd.tencent.tap":["tap"],"image/vnd.valve.source.texture":["vtf"],"image/vnd.wap.wbmp":["wbmp"],"image/vnd.xiff":["xif"],"image/vnd.zbrush.pcx":["pcx"],"image/x-3ds":["3ds"],"image/x-cmu-raster":["ras"],"image/x-cmx":["cmx"],"image/x-freehand":["fh","fhc","fh4","fh5","fh7"],"image/x-icon":["*ico"],"image/x-jng":["jng"],"image/x-mrsid-image":["sid"],"image/x-ms-bmp":["*bmp"],"image/x-pcx":["*pcx"],"image/x-pict":["pic","pct"],"image/x-portable-anymap":["pnm"],"image/x-portable-bitmap":["pbm"],"image/x-portable-graymap":["pgm"],"image/x-portable-pixmap":["ppm"],"image/x-rgb":["rgb"],"image/x-tga":["tga"],"image/x-xbitmap":["xbm"],"image/x-xpixmap":["xpm"],"image/x-xwindowdump":["xwd"],"message/vnd.wfa.wsc":["wsc"],"model/vnd.collada+xml":["dae"],"model/vnd.dwf":["dwf"],"model/vnd.gdl":["gdl"],"model/vnd.gtw":["gtw"],"model/vnd.mts":["mts"],"model/vnd.opengex":["ogex"],"model/vnd.parasolid.transmit.binary":["x_b"],"model/vnd.parasolid.transmit.text":["x_t"],"model/vnd.sap.vds":["vds"],"model/vnd.usdz+zip":["usdz"],"model/vnd.valve.source.compiled-map":["bsp"],"model/vnd.vtu":["vtu"],"text/prs.lines.tag":["dsc"],"text/vnd.curl":["curl"],"text/vnd.curl.dcurl":["dcurl"],"text/vnd.curl.mcurl":["mcurl"],"text/vnd.curl.scurl":["scurl"],"text/vnd.dvb.subtitle":["sub"],"text/vnd.fly":["fly"],"text/vnd.fmi.flexstor":["flx"],"text/vnd.graphviz":["gv"],"text/vnd.in3d.3dml":["3dml"],"text/vnd.in3d.spot":["spot"],"text/vnd.sun.j2me.app-descriptor":["jad"],"text/vnd.wap.wml":["wml"],"text/vnd.wap.wmlscript":["wmls"],"text/x-asm":["s","asm"],"text/x-c":["c","cc","cxx","cpp","h","hh","dic"],"text/x-component":["htc"],"text/x-fortran":["f","for","f77","f90"],"text/x-handlebars-template":["hbs"],"text/x-java-source":["java"],"text/x-lua":["lua"],"text/x-markdown":["mkd"],"text/x-nfo":["nfo"],"text/x-opml":["opml"],"text/x-org":["*org"],"text/x-pascal":["p","pas"],"text/x-processing":["pde"],"text/x-sass":["sass"],"text/x-scss":["scss"],"text/x-setext":["etx"],"text/x-sfv":["sfv"],"text/x-suse-ymp":["ymp"],"text/x-uuencode":["uu"],"text/x-vcalendar":["vcs"],"text/x-vcard":["vcf"],"video/vnd.dece.hd":["uvh","uvvh"],"video/vnd.dece.mobile":["uvm","uvvm"],"video/vnd.dece.pd":["uvp","uvvp"],"video/vnd.dece.sd":["uvs","uvvs"],"video/vnd.dece.video":["uvv","uvvv"],"video/vnd.dvb.file":["dvb"],"video/vnd.fvt":["fvt"],"video/vnd.mpegurl":["mxu","m4u"],"video/vnd.ms-playready.media.pyv":["pyv"],"video/vnd.uvvu.mp4":["uvu","uvvu"],"video/vnd.vivo":["viv"],"video/x-f4v":["f4v"],"video/x-fli":["fli"],"video/x-flv":["flv"],"video/x-m4v":["m4v"],"video/x-matroska":["mkv","mk3d","mks"],"video/x-mng":["mng"],"video/x-ms-asf":["asf","asx"],"video/x-ms-vob":["vob"],"video/x-ms-wm":["wm"],"video/x-ms-wmv":["wmv"],"video/x-ms-wmx":["wmx"],"video/x-ms-wvx":["wvx"],"video/x-msvideo":["avi"],"video/x-sgi-movie":["movie"],"video/x-smv":["smv"],"x-conference/x-cooltalk":["ice"]}; + +/***/ }), + +/***/ 83725: +/***/ ((module) => { + +module.exports = {"application/andrew-inset":["ez"],"application/applixware":["aw"],"application/atom+xml":["atom"],"application/atomcat+xml":["atomcat"],"application/atomdeleted+xml":["atomdeleted"],"application/atomsvc+xml":["atomsvc"],"application/atsc-dwd+xml":["dwd"],"application/atsc-held+xml":["held"],"application/atsc-rsat+xml":["rsat"],"application/bdoc":["bdoc"],"application/calendar+xml":["xcs"],"application/ccxml+xml":["ccxml"],"application/cdfx+xml":["cdfx"],"application/cdmi-capability":["cdmia"],"application/cdmi-container":["cdmic"],"application/cdmi-domain":["cdmid"],"application/cdmi-object":["cdmio"],"application/cdmi-queue":["cdmiq"],"application/cu-seeme":["cu"],"application/dash+xml":["mpd"],"application/davmount+xml":["davmount"],"application/docbook+xml":["dbk"],"application/dssc+der":["dssc"],"application/dssc+xml":["xdssc"],"application/ecmascript":["es","ecma"],"application/emma+xml":["emma"],"application/emotionml+xml":["emotionml"],"application/epub+zip":["epub"],"application/exi":["exi"],"application/express":["exp"],"application/fdt+xml":["fdt"],"application/font-tdpfr":["pfr"],"application/geo+json":["geojson"],"application/gml+xml":["gml"],"application/gpx+xml":["gpx"],"application/gxf":["gxf"],"application/gzip":["gz"],"application/hjson":["hjson"],"application/hyperstudio":["stk"],"application/inkml+xml":["ink","inkml"],"application/ipfix":["ipfix"],"application/its+xml":["its"],"application/java-archive":["jar","war","ear"],"application/java-serialized-object":["ser"],"application/java-vm":["class"],"application/javascript":["js","mjs"],"application/json":["json","map"],"application/json5":["json5"],"application/jsonml+json":["jsonml"],"application/ld+json":["jsonld"],"application/lgr+xml":["lgr"],"application/lost+xml":["lostxml"],"application/mac-binhex40":["hqx"],"application/mac-compactpro":["cpt"],"application/mads+xml":["mads"],"application/manifest+json":["webmanifest"],"application/marc":["mrc"],"application/marcxml+xml":["mrcx"],"application/mathematica":["ma","nb","mb"],"application/mathml+xml":["mathml"],"application/mbox":["mbox"],"application/mediaservercontrol+xml":["mscml"],"application/metalink+xml":["metalink"],"application/metalink4+xml":["meta4"],"application/mets+xml":["mets"],"application/mmt-aei+xml":["maei"],"application/mmt-usd+xml":["musd"],"application/mods+xml":["mods"],"application/mp21":["m21","mp21"],"application/mp4":["mp4s","m4p"],"application/msword":["doc","dot"],"application/mxf":["mxf"],"application/n-quads":["nq"],"application/n-triples":["nt"],"application/node":["cjs"],"application/octet-stream":["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"],"application/oda":["oda"],"application/oebps-package+xml":["opf"],"application/ogg":["ogx"],"application/omdoc+xml":["omdoc"],"application/onenote":["onetoc","onetoc2","onetmp","onepkg"],"application/oxps":["oxps"],"application/p2p-overlay+xml":["relo"],"application/patch-ops-error+xml":["xer"],"application/pdf":["pdf"],"application/pgp-encrypted":["pgp"],"application/pgp-signature":["asc","sig"],"application/pics-rules":["prf"],"application/pkcs10":["p10"],"application/pkcs7-mime":["p7m","p7c"],"application/pkcs7-signature":["p7s"],"application/pkcs8":["p8"],"application/pkix-attr-cert":["ac"],"application/pkix-cert":["cer"],"application/pkix-crl":["crl"],"application/pkix-pkipath":["pkipath"],"application/pkixcmp":["pki"],"application/pls+xml":["pls"],"application/postscript":["ai","eps","ps"],"application/provenance+xml":["provx"],"application/pskc+xml":["pskcxml"],"application/raml+yaml":["raml"],"application/rdf+xml":["rdf","owl"],"application/reginfo+xml":["rif"],"application/relax-ng-compact-syntax":["rnc"],"application/resource-lists+xml":["rl"],"application/resource-lists-diff+xml":["rld"],"application/rls-services+xml":["rs"],"application/route-apd+xml":["rapd"],"application/route-s-tsid+xml":["sls"],"application/route-usd+xml":["rusd"],"application/rpki-ghostbusters":["gbr"],"application/rpki-manifest":["mft"],"application/rpki-roa":["roa"],"application/rsd+xml":["rsd"],"application/rss+xml":["rss"],"application/rtf":["rtf"],"application/sbml+xml":["sbml"],"application/scvp-cv-request":["scq"],"application/scvp-cv-response":["scs"],"application/scvp-vp-request":["spq"],"application/scvp-vp-response":["spp"],"application/sdp":["sdp"],"application/senml+xml":["senmlx"],"application/sensml+xml":["sensmlx"],"application/set-payment-initiation":["setpay"],"application/set-registration-initiation":["setreg"],"application/shf+xml":["shf"],"application/sieve":["siv","sieve"],"application/smil+xml":["smi","smil"],"application/sparql-query":["rq"],"application/sparql-results+xml":["srx"],"application/srgs":["gram"],"application/srgs+xml":["grxml"],"application/sru+xml":["sru"],"application/ssdl+xml":["ssdl"],"application/ssml+xml":["ssml"],"application/swid+xml":["swidtag"],"application/tei+xml":["tei","teicorpus"],"application/thraud+xml":["tfi"],"application/timestamped-data":["tsd"],"application/toml":["toml"],"application/trig":["trig"],"application/ttml+xml":["ttml"],"application/ubjson":["ubj"],"application/urc-ressheet+xml":["rsheet"],"application/urc-targetdesc+xml":["td"],"application/voicexml+xml":["vxml"],"application/wasm":["wasm"],"application/widget":["wgt"],"application/winhlp":["hlp"],"application/wsdl+xml":["wsdl"],"application/wspolicy+xml":["wspolicy"],"application/xaml+xml":["xaml"],"application/xcap-att+xml":["xav"],"application/xcap-caps+xml":["xca"],"application/xcap-diff+xml":["xdf"],"application/xcap-el+xml":["xel"],"application/xcap-ns+xml":["xns"],"application/xenc+xml":["xenc"],"application/xhtml+xml":["xhtml","xht"],"application/xliff+xml":["xlf"],"application/xml":["xml","xsl","xsd","rng"],"application/xml-dtd":["dtd"],"application/xop+xml":["xop"],"application/xproc+xml":["xpl"],"application/xslt+xml":["*xsl","xslt"],"application/xspf+xml":["xspf"],"application/xv+xml":["mxml","xhvml","xvml","xvm"],"application/yang":["yang"],"application/yin+xml":["yin"],"application/zip":["zip"],"audio/3gpp":["*3gpp"],"audio/adpcm":["adp"],"audio/amr":["amr"],"audio/basic":["au","snd"],"audio/midi":["mid","midi","kar","rmi"],"audio/mobile-xmf":["mxmf"],"audio/mp3":["*mp3"],"audio/mp4":["m4a","mp4a"],"audio/mpeg":["mpga","mp2","mp2a","mp3","m2a","m3a"],"audio/ogg":["oga","ogg","spx","opus"],"audio/s3m":["s3m"],"audio/silk":["sil"],"audio/wav":["wav"],"audio/wave":["*wav"],"audio/webm":["weba"],"audio/xm":["xm"],"font/collection":["ttc"],"font/otf":["otf"],"font/ttf":["ttf"],"font/woff":["woff"],"font/woff2":["woff2"],"image/aces":["exr"],"image/apng":["apng"],"image/avif":["avif"],"image/bmp":["bmp"],"image/cgm":["cgm"],"image/dicom-rle":["drle"],"image/emf":["emf"],"image/fits":["fits"],"image/g3fax":["g3"],"image/gif":["gif"],"image/heic":["heic"],"image/heic-sequence":["heics"],"image/heif":["heif"],"image/heif-sequence":["heifs"],"image/hej2k":["hej2"],"image/hsj2":["hsj2"],"image/ief":["ief"],"image/jls":["jls"],"image/jp2":["jp2","jpg2"],"image/jpeg":["jpeg","jpg","jpe"],"image/jph":["jph"],"image/jphc":["jhc"],"image/jpm":["jpm"],"image/jpx":["jpx","jpf"],"image/jxr":["jxr"],"image/jxra":["jxra"],"image/jxrs":["jxrs"],"image/jxs":["jxs"],"image/jxsc":["jxsc"],"image/jxsi":["jxsi"],"image/jxss":["jxss"],"image/ktx":["ktx"],"image/ktx2":["ktx2"],"image/png":["png"],"image/sgi":["sgi"],"image/svg+xml":["svg","svgz"],"image/t38":["t38"],"image/tiff":["tif","tiff"],"image/tiff-fx":["tfx"],"image/webp":["webp"],"image/wmf":["wmf"],"message/disposition-notification":["disposition-notification"],"message/global":["u8msg"],"message/global-delivery-status":["u8dsn"],"message/global-disposition-notification":["u8mdn"],"message/global-headers":["u8hdr"],"message/rfc822":["eml","mime"],"model/3mf":["3mf"],"model/gltf+json":["gltf"],"model/gltf-binary":["glb"],"model/iges":["igs","iges"],"model/mesh":["msh","mesh","silo"],"model/mtl":["mtl"],"model/obj":["obj"],"model/step+xml":["stpx"],"model/step+zip":["stpz"],"model/step-xml+zip":["stpxz"],"model/stl":["stl"],"model/vrml":["wrl","vrml"],"model/x3d+binary":["*x3db","x3dbz"],"model/x3d+fastinfoset":["x3db"],"model/x3d+vrml":["*x3dv","x3dvz"],"model/x3d+xml":["x3d","x3dz"],"model/x3d-vrml":["x3dv"],"text/cache-manifest":["appcache","manifest"],"text/calendar":["ics","ifb"],"text/coffeescript":["coffee","litcoffee"],"text/css":["css"],"text/csv":["csv"],"text/html":["html","htm","shtml"],"text/jade":["jade"],"text/jsx":["jsx"],"text/less":["less"],"text/markdown":["markdown","md"],"text/mathml":["mml"],"text/mdx":["mdx"],"text/n3":["n3"],"text/plain":["txt","text","conf","def","list","log","in","ini"],"text/richtext":["rtx"],"text/rtf":["*rtf"],"text/sgml":["sgml","sgm"],"text/shex":["shex"],"text/slim":["slim","slm"],"text/spdx":["spdx"],"text/stylus":["stylus","styl"],"text/tab-separated-values":["tsv"],"text/troff":["t","tr","roff","man","me","ms"],"text/turtle":["ttl"],"text/uri-list":["uri","uris","urls"],"text/vcard":["vcard"],"text/vtt":["vtt"],"text/xml":["*xml"],"text/yaml":["yaml","yml"],"video/3gpp":["3gp","3gpp"],"video/3gpp2":["3g2"],"video/h261":["h261"],"video/h263":["h263"],"video/h264":["h264"],"video/iso.segment":["m4s"],"video/jpeg":["jpgv"],"video/jpm":["*jpm","jpgm"],"video/mj2":["mj2","mjp2"],"video/mp2t":["ts"],"video/mp4":["mp4","mp4v","mpg4"],"video/mpeg":["mpeg","mpg","mpe","m1v","m2v"],"video/ogg":["ogv"],"video/quicktime":["qt","mov"],"video/webm":["webm"]}; + +/***/ }), + +/***/ 70744: +/***/ ((module) => { + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function (val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} + + +/***/ }), + +/***/ 26705: +/***/ ((module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var Stream = _interopDefault(__nccwpck_require__(2203)); +var http = _interopDefault(__nccwpck_require__(58611)); +var Url = _interopDefault(__nccwpck_require__(87016)); +var whatwgUrl = _interopDefault(__nccwpck_require__(62686)); +var https = _interopDefault(__nccwpck_require__(65692)); +var zlib = _interopDefault(__nccwpck_require__(43106)); + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = (__nccwpck_require__(42078).convert); +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); +const URL = Url.URL || whatwgUrl.URL; + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +/** + * Wrapper around `new URL` to handle arbitrary URLs + * + * @param {string} urlStr + * @return {void} + */ +function parseURL(urlStr) { + /* + Check whether the URL is absolute or not + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 + */ + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { + urlStr = new URL(urlStr).toString(); + } + + // Fallback to old implementation for arbitrary URLs + return parse_url(urlStr); +} + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parseURL(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parseURL(`${input}`); + } + input = {}; + } else { + parsedURL = parseURL(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +const URL$1 = Url.URL || whatwgUrl.URL; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; + +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { + const orig = new URL$1(original).hostname; + const dest = new URL$1(destination).hostname; + + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); +}; + +/** + * isSameProtocol reports whether the two provided URLs use the same protocol. + * + * Both domains must already be in canonical form. + * @param {string|URL} original + * @param {string|URL} destination + */ +const isSameProtocol = function isSameProtocol(destination, original) { + const orig = new URL$1(original).protocol; + const dest = new URL$1(destination).protocol; + + return orig === dest; +}; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + destroyStream(request.body, error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + + if (response && response.body) { + destroyStream(response.body, err); + } + + finalize(); + }); + + fixResponseChunkedTransferBadEnding(req, function (err) { + if (signal && signal.aborted) { + return; + } + + if (response && response.body) { + destroyStream(response.body, err); + } + }); + + /* c8 ignore next 18 */ + if (parseInt(process.version.substring(1)) < 14) { + // Before Node.js 14, pipeline() does not fully support async iterators and does not always + // properly handle when the socket close/end events are out of order. + req.on('socket', function (s) { + s.addListener('close', function (hadError) { + // if a data listener is still present we didn't end cleanly + const hasDataListener = s.listenerCount('data') > 0; + + // if end happened before close but the socket didn't emit an error, do it now + if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + response.body.emit('error', err); + } + }); + }); + } + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + let locationURL = null; + try { + locationURL = location === null ? null : new URL$1(location, request.url).toString(); + } catch (err) { + // error here can only be invalid URL in Location: header + // do not throw when options.redirect == manual + // let the user extract the errorneous redirect URL + if (request.redirect !== 'manual') { + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); + finalize(); + return; + } + } + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { + requestOpts.headers.delete(name); + } + } + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + raw.on('end', function () { + // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. + if (!response) { + response = new Response(body, response_options); + resolve(response); + } + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +function fixResponseChunkedTransferBadEnding(request, errorCallback) { + let socket; + + request.on('socket', function (s) { + socket = s; + }); + + request.on('response', function (response) { + const headers = response.headers; + + if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { + response.once('close', function (hadError) { + // tests for socket presence, as in some situations the + // the 'socket' event is not triggered for the request + // (happens in deno), avoids `TypeError` + // if a data listener is still present we didn't end cleanly + const hasDataListener = socket && socket.listenerCount('data') > 0; + + if (hasDataListener && !hadError) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + errorCallback(err); + } + }); + } + }); +} + +function destroyStream(stream, err) { + if (stream.destroy) { + stream.destroy(err); + } else { + // node < 8 + stream.emit('error', err); + stream.end(); + } +} + +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +module.exports = exports = fetch; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports["default"] = exports; +exports.Headers = Headers; +exports.Request = Request; +exports.Response = Response; +exports.FetchError = FetchError; +exports.AbortError = AbortError; + + +/***/ }), + +/***/ 55560: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var wrappy = __nccwpck_require__(58264) +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + + +/***/ }), + +/***/ 58890: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const Queue = __nccwpck_require__(30538); + +const pLimit = concurrency => { + if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) { + throw new TypeError('Expected `concurrency` to be a number from 1 and up'); + } + + const queue = new Queue(); + let activeCount = 0; + + const next = () => { + activeCount--; + + if (queue.size > 0) { + queue.dequeue()(); + } + }; + + const run = async (fn, resolve, ...args) => { + activeCount++; + + const result = (async () => fn(...args))(); + + resolve(result); + + try { + await result; + } catch {} + + next(); + }; + + const enqueue = (fn, resolve, ...args) => { + queue.enqueue(run.bind(null, fn, resolve, ...args)); + + (async () => { + // This function needs to wait until the next microtask before comparing + // `activeCount` to `concurrency`, because `activeCount` is updated asynchronously + // when the run function is dequeued and called. The comparison in the if-statement + // needs to happen asynchronously as well to get an up-to-date value for `activeCount`. + await Promise.resolve(); + + if (activeCount < concurrency && queue.size > 0) { + queue.dequeue()(); + } + })(); + }; + + const generator = (fn, ...args) => new Promise(resolve => { + enqueue(fn, resolve, ...args); + }); + + Object.defineProperties(generator, { + activeCount: { + get: () => activeCount + }, + pendingCount: { + get: () => queue.size + }, + clearQueue: { + value: () => { + queue.clear(); + } + } + }); + + return generator; +}; + +module.exports = pLimit; + + +/***/ }), + +/***/ 25500: +/***/ ((module) => { + +"use strict"; + + +const codes = {}; + +function createErrorType(code, message, Base) { + if (!Base) { + Base = Error + } + + function getMessage (arg1, arg2, arg3) { + if (typeof message === 'string') { + return message + } else { + return message(arg1, arg2, arg3) + } + } + + class NodeError extends Base { + constructor (arg1, arg2, arg3) { + super(getMessage(arg1, arg2, arg3)); + } + } + + NodeError.prototype.name = Base.name; + NodeError.prototype.code = code; + + codes[code] = NodeError; +} + +// https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js +function oneOf(expected, thing) { + if (Array.isArray(expected)) { + const len = expected.length; + expected = expected.map((i) => String(i)); + if (len > 2) { + return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` + + expected[len - 1]; + } else if (len === 2) { + return `one of ${thing} ${expected[0]} or ${expected[1]}`; + } else { + return `of ${thing} ${expected[0]}`; + } + } else { + return `of ${thing} ${String(expected)}`; + } +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith +function startsWith(str, search, pos) { + return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith +function endsWith(str, search, this_len) { + if (this_len === undefined || this_len > str.length) { + this_len = str.length; + } + return str.substring(this_len - search.length, this_len) === search; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes +function includes(str, search, start) { + if (typeof start !== 'number') { + start = 0; + } + + if (start + search.length > str.length) { + return false; + } else { + return str.indexOf(search, start) !== -1; + } +} + +createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { + return 'The value "' + value + '" is invalid for option "' + name + '"' +}, TypeError); +createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { + // determiner: 'must be' or 'must not be' + let determiner; + if (typeof expected === 'string' && startsWith(expected, 'not ')) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } + + let msg; + if (endsWith(name, ' argument')) { + // For cases like 'first argument' + msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`; + } else { + const type = includes(name, '.') ? 'property' : 'argument'; + msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`; + } + + msg += `. Received type ${typeof actual}`; + return msg; +}, TypeError); +createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); +createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { + return 'The ' + name + ' method is not implemented' +}); +createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); +createErrorType('ERR_STREAM_DESTROYED', function (name) { + return 'Cannot call ' + name + ' after a stream was destroyed'; +}); +createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); +createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); +createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); +createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { + return 'Unknown encoding: ' + arg +}, TypeError); +createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); + +module.exports.F = codes; + + +/***/ }), + +/***/ 82063: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + + + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +}; +/**/ + +module.exports = Duplex; +var Readable = __nccwpck_require__(86893); +var Writable = __nccwpck_require__(38797); +__nccwpck_require__(39598)(Duplex, Readable); +{ + // Allow the keys array to be GC'ed. + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + Readable.call(this, options); + Writable.call(this, options); + this.allowHalfOpen = true; + if (options) { + if (options.readable === false) this.readable = false; + if (options.writable === false) this.writable = false; + if (options.allowHalfOpen === false) { + this.allowHalfOpen = false; + this.once('end', onend); + } + } +} +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); +Object.defineProperty(Duplex.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); +Object.defineProperty(Duplex.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } +}); + +// the no-half-open enforcer +function onend() { + // If the writable side ended, then we're ok. + if (this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(onEndNT, this); +} +function onEndNT(self) { + self.end(); +} +Object.defineProperty(Duplex.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +/***/ }), + +/***/ 35283: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + + + +module.exports = PassThrough; +var Transform = __nccwpck_require__(12337); +__nccwpck_require__(39598)(PassThrough, Transform); +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + Transform.call(this, options); +} +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; + +/***/ }), + +/***/ 86893: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +module.exports = Readable; + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = (__nccwpck_require__(24434).EventEmitter); +var EElistenerCount = function EElistenerCount(emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = __nccwpck_require__(63283); +/**/ + +var Buffer = (__nccwpck_require__(20181).Buffer); +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ +var debugUtil = __nccwpck_require__(39023); +var debug; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function debug() {}; +} +/**/ + +var BufferList = __nccwpck_require__(77336); +var destroyImpl = __nccwpck_require__(65089); +var _require = __nccwpck_require__(54874), + getHighWaterMark = _require.getHighWaterMark; +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; + +// Lazy loaded to improve the startup performance. +var StringDecoder; +var createReadableStreamAsyncIterator; +var from; +__nccwpck_require__(39598)(Readable, Stream); +var errorOrDestroy = destroyImpl.errorOrDestroy; +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} +function ReadableState(options, stream, isDuplex) { + Duplex = Duplex || __nccwpck_require__(82063); + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + this.paused = true; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = options.emitClose !== false; + + // Should .destroy() be called after 'end' (and potentially 'finish') + this.autoDestroy = !!options.autoDestroy; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = (__nccwpck_require__(80634)/* .StringDecoder */ .I); + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} +function Readable(options) { + Duplex = Duplex || __nccwpck_require__(82063); + if (!(this instanceof Readable)) return new Readable(options); + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the ReadableState constructor, at least with V8 6.5 + var isDuplex = this instanceof Duplex; + this._readableState = new ReadableState(options, this, isDuplex); + + // legacy + this.readable = true; + if (options) { + if (typeof options.read === 'function') this._read = options.read; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + Stream.call(this); +} +Object.defineProperty(Readable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + debug('readableAddChunk', chunk); + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + errorOrDestroy(stream, er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (addToFront) { + if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true); + } else if (state.ended) { + errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); + } else if (state.destroyed) { + return false; + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + maybeReadMore(stream, state); + } + } + + // We can push more data if we are below the highWaterMark. + // Also, if we have no data yet, we can stand some more bytes. + // This is to work around cases where hwm=0, such as the repl. + return !state.ended && (state.length < state.highWaterMark || state.length === 0); +} +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + state.awaitDrain = 0; + stream.emit('data', chunk); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); + } + return er; +} +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = (__nccwpck_require__(80634)/* .StringDecoder */ .I); + var decoder = new StringDecoder(enc); + this._readableState.decoder = decoder; + // If setEncoding(null), decoder.encoding equals utf8 + this._readableState.encoding = this._readableState.decoder.encoding; + + // Iterate over current buffer to convert already stored Buffers: + var p = this._readableState.buffer.head; + var content = ''; + while (p !== null) { + content += decoder.write(p.data); + p = p.next; + } + this._readableState.buffer.clear(); + if (content !== '') this._readableState.buffer.push(content); + this._readableState.length = content.length; + return this; +}; + +// Don't raise the hwm > 1GB +var MAX_HWM = 0x40000000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + // TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE. + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + if (ret === null) { + state.needReadable = state.length <= state.highWaterMark; + n = 0; + } else { + state.length -= n; + state.awaitDrain = 0; + } + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + if (ret !== null) this.emit('data', ret); + return ret; +}; +function onEofChunk(stream, state) { + debug('onEofChunk'); + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + if (state.sync) { + // if we are sync, wait until next tick to emit the data. + // Otherwise we risk emitting data in the flow() + // the readable code triggers during a read() call + emitReadable(stream); + } else { + // emit 'readable' now to make sure it gets picked up. + state.needReadable = false; + if (!state.emittedReadable) { + state.emittedReadable = true; + emitReadable_(stream); + } + } +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + debug('emitReadable', state.needReadable, state.emittedReadable); + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + process.nextTick(emitReadable_, stream); + } +} +function emitReadable_(stream) { + var state = stream._readableState; + debug('emitReadable_', state.destroyed, state.length, state.ended); + if (!state.destroyed && (state.length || state.ended)) { + stream.emit('readable'); + state.emittedReadable = false; + } + + // The stream needs another readable event if + // 1. It is not flowing, as the flow mechanism will take + // care of it. + // 2. It is not ended. + // 3. It is below the highWaterMark, so we can schedule + // another readable later. + state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(maybeReadMore_, stream, state); + } +} +function maybeReadMore_(stream, state) { + // Attempt to read more data if we should. + // + // The conditions for reading more data are (one of): + // - Not enough data buffered (state.length < state.highWaterMark). The loop + // is responsible for filling the buffer with enough data if such data + // is available. If highWaterMark is 0 and we are not in the flowing mode + // we should _not_ attempt to buffer any extra data. We'll get more data + // when the stream consumer calls read() instead. + // - No data in the buffer, and the stream is in flowing mode. In this mode + // the loop below is responsible for ensuring read() is called. Failing to + // call read here would abort the flow and there's no other mechanism for + // continuing the flow if the stream consumer has just subscribed to the + // 'data' event. + // + // In addition to the above conditions to keep reading data, the following + // conditions prevent the data from being read: + // - The stream has ended (state.ended). + // - There is already a pending 'read' operation (state.reading). This is a + // case where the the stream has called the implementation defined _read() + // method, but they are processing the call asynchronously and have _not_ + // called push() with new data. In this case we skip performing more + // read()s. The execution ends in this method again after the _read() ends + // up calling push() with more data. + while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) { + var len = state.length; + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()')); +}; +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn); + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + var ret = dest.write(chunk); + debug('dest.write', ret); + if (ret === false) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', state.awaitDrain); + state.awaitDrain++; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + return dest; +}; +function pipeOnDrain(src) { + return function pipeOnDrainFunctionResult() { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { + hasUnpiped: false + }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + for (var i = 0; i < len; i++) dests[i].emit('unpipe', this, { + hasUnpiped: false + }); + return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + dest.emit('unpipe', this, unpipeInfo); + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + var state = this._readableState; + if (ev === 'data') { + // update readableListening so that resume() may be a no-op + // a few lines down. This is needed to support once('readable'). + state.readableListening = this.listenerCount('readable') > 0; + + // Try start flowing on next tick if stream isn't explicitly paused + if (state.flowing !== false) this.resume(); + } else if (ev === 'readable') { + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.flowing = false; + state.emittedReadable = false; + debug('on readable', state.length, state.reading); + if (state.length) { + emitReadable(this); + } else if (!state.reading) { + process.nextTick(nReadingNextTick, this); + } + } + } + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; +Readable.prototype.removeListener = function (ev, fn) { + var res = Stream.prototype.removeListener.call(this, ev, fn); + if (ev === 'readable') { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +}; +Readable.prototype.removeAllListeners = function (ev) { + var res = Stream.prototype.removeAllListeners.apply(this, arguments); + if (ev === 'readable' || ev === undefined) { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +}; +function updateReadableListening(self) { + var state = self._readableState; + state.readableListening = self.listenerCount('readable') > 0; + if (state.resumeScheduled && !state.paused) { + // flowing needs to be set to true now, otherwise + // the upcoming resume will not flow. + state.flowing = true; + + // crude way to check if we should resume + } else if (self.listenerCount('data') > 0) { + self.resume(); + } +} +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + // we flow only if there is no one listening + // for readable, but we still have to call + // resume() + state.flowing = !state.readableListening; + resume(this, state); + } + state.paused = false; + return this; +}; +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(resume_, stream, state); + } +} +function resume_(stream, state) { + debug('resume', state.reading); + if (!state.reading) { + stream.read(0); + } + state.resumeScheduled = false; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (this._readableState.flowing !== false) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + this._readableState.paused = true; + return this; +}; +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + var state = this._readableState; + var paused = false; + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + _this.push(null); + }); + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function methodWrap(method) { + return function methodWrapReturnFunction() { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + return this; +}; +if (typeof Symbol === 'function') { + Readable.prototype[Symbol.asyncIterator] = function () { + if (createReadableStreamAsyncIterator === undefined) { + createReadableStreamAsyncIterator = __nccwpck_require__(14868); + } + return createReadableStreamAsyncIterator(this); + }; +} +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.highWaterMark; + } +}); +Object.defineProperty(Readable.prototype, 'readableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState && this._readableState.buffer; + } +}); +Object.defineProperty(Readable.prototype, 'readableFlowing', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.flowing; + }, + set: function set(state) { + if (this._readableState) { + this._readableState.flowing = state; + } + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; +Object.defineProperty(Readable.prototype, 'readableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.length; + } +}); + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = state.buffer.consume(n, state.decoder); + } + return ret; +} +function endReadable(stream) { + var state = stream._readableState; + debug('endReadable', state.endEmitted); + if (!state.endEmitted) { + state.ended = true; + process.nextTick(endReadableNT, state, stream); + } +} +function endReadableNT(state, stream) { + debug('endReadableNT', state.endEmitted, state.length); + + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the writable side is ready for autoDestroy as well + var wState = stream._writableState; + if (!wState || wState.autoDestroy && wState.finished) { + stream.destroy(); + } + } + } +} +if (typeof Symbol === 'function') { + Readable.from = function (iterable, opts) { + if (from === undefined) { + from = __nccwpck_require__(4659); + } + return from(Readable, iterable, opts); + }; +} +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} + +/***/ }), + +/***/ 12337: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + + + +module.exports = Transform; +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING, + ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0; +var Duplex = __nccwpck_require__(82063); +__nccwpck_require__(39598)(Transform, Duplex); +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + var cb = ts.writecb; + if (cb === null) { + return this.emit('error', new ERR_MULTIPLE_CALLBACK()); + } + ts.writechunk = null; + ts.writecb = null; + if (data != null) + // single equals check for both `null` and `undefined` + this.push(data); + cb(er); + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + Duplex.call(this, options); + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} +function prefinish() { + var _this = this; + if (typeof this._flush === 'function' && !this._readableState.destroyed) { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()')); +}; +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + if (ts.writechunk !== null && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; +Transform.prototype._destroy = function (err, cb) { + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + }); +}; +function done(stream, er, data) { + if (er) return stream.emit('error', er); + if (data != null) + // single equals check for both `null` and `undefined` + stream.push(data); + + // TODO(BridgeAR): Write a test for these two error cases + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0(); + if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); + return stream.push(null); +} + +/***/ }), + +/***/ 38797: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + + + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var internalUtil = { + deprecate: __nccwpck_require__(24488) +}; +/**/ + +/**/ +var Stream = __nccwpck_require__(63283); +/**/ + +var Buffer = (__nccwpck_require__(20181).Buffer); +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} +var destroyImpl = __nccwpck_require__(65089); +var _require = __nccwpck_require__(54874), + getHighWaterMark = _require.getHighWaterMark; +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED, + ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES, + ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END, + ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING; +var errorOrDestroy = destroyImpl.errorOrDestroy; +__nccwpck_require__(39598)(Writable, Stream); +function nop() {} +function WritableState(options, stream, isDuplex) { + Duplex = Duplex || __nccwpck_require__(82063); + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream, + // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = options.emitClose !== false; + + // Should .destroy() be called after 'finish' (and potentially 'end') + this.autoDestroy = !!options.autoDestroy; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function writableStateBufferGetter() { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function value(object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function realHasInstance(object) { + return object instanceof this; + }; +} +function Writable(options) { + Duplex = Duplex || __nccwpck_require__(82063); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the WritableState constructor, at least with V8 6.5 + var isDuplex = this instanceof Duplex; + if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options); + this._writableState = new WritableState(options, this, isDuplex); + + // legacy. + this.writable = true; + if (options) { + if (typeof options.write === 'function') this._write = options.write; + if (typeof options.writev === 'function') this._writev = options.writev; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + if (typeof options.final === 'function') this._final = options.final; + } + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); +}; +function writeAfterEnd(stream, cb) { + var er = new ERR_STREAM_WRITE_AFTER_END(); + // TODO: defer error events consistently everywhere, not just the cb + errorOrDestroy(stream, er); + process.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var er; + if (chunk === null) { + er = new ERR_STREAM_NULL_VALUES(); + } else if (typeof chunk !== 'string' && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk); + } + if (er) { + errorOrDestroy(stream, er); + process.nextTick(cb, er); + return false; + } + return true; +} +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + if (typeof cb !== 'function') cb = nop; + if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + return ret; +}; +Writable.prototype.cork = function () { + this._writableState.corked++; +}; +Writable.prototype.uncork = function () { + var state = this._writableState; + if (state.corked) { + state.corked--; + if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; +Object.defineProperty(Writable.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + state.length += len; + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + return ret; +} +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + process.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + process.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK(); + onwriteStateUpdate(state); + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state) || stream.destroyed; + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + if (sync) { + process.nextTick(afterWrite, stream, state, finished, cb); + } else { + afterWrite(stream, state, finished, cb); + } + } +} +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + if (entry === null) state.lastBufferedRequest = null; + } + state.bufferedRequest = entry; + state.bufferProcessing = false; +} +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()')); +}; +Writable.prototype._writev = null; +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending) endWritable(this, state, cb); + return this; +}; +Object.defineProperty(Writable.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } +}); +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + errorOrDestroy(stream, err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function' && !state.destroyed) { + state.pendingcb++; + state.finalCalled = true; + process.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the readable side is ready for autoDestroy as well + var rState = stream._readableState; + if (!rState || rState.autoDestroy && rState.endEmitted) { + stream.destroy(); + } + } + } + } + return need; +} +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) process.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + + // reuse the free corkReq. + state.corkedRequestsFree.next = corkReq; +} +Object.defineProperty(Writable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + cb(err); +}; + +/***/ }), + +/***/ 14868: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var _Object$setPrototypeO; +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var finished = __nccwpck_require__(36815); +var kLastResolve = Symbol('lastResolve'); +var kLastReject = Symbol('lastReject'); +var kError = Symbol('error'); +var kEnded = Symbol('ended'); +var kLastPromise = Symbol('lastPromise'); +var kHandlePromise = Symbol('handlePromise'); +var kStream = Symbol('stream'); +function createIterResult(value, done) { + return { + value: value, + done: done + }; +} +function readAndResolve(iter) { + var resolve = iter[kLastResolve]; + if (resolve !== null) { + var data = iter[kStream].read(); + // we defer if data is null + // we can be expecting either 'end' or + // 'error' + if (data !== null) { + iter[kLastPromise] = null; + iter[kLastResolve] = null; + iter[kLastReject] = null; + resolve(createIterResult(data, false)); + } + } +} +function onReadable(iter) { + // we wait for the next tick, because it might + // emit an error with process.nextTick + process.nextTick(readAndResolve, iter); +} +function wrapForNext(lastPromise, iter) { + return function (resolve, reject) { + lastPromise.then(function () { + if (iter[kEnded]) { + resolve(createIterResult(undefined, true)); + return; + } + iter[kHandlePromise](resolve, reject); + }, reject); + }; +} +var AsyncIteratorPrototype = Object.getPrototypeOf(function () {}); +var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = { + get stream() { + return this[kStream]; + }, + next: function next() { + var _this = this; + // if we have detected an error in the meanwhile + // reject straight away + var error = this[kError]; + if (error !== null) { + return Promise.reject(error); + } + if (this[kEnded]) { + return Promise.resolve(createIterResult(undefined, true)); + } + if (this[kStream].destroyed) { + // We need to defer via nextTick because if .destroy(err) is + // called, the error will be emitted via nextTick, and + // we cannot guarantee that there is no error lingering around + // waiting to be emitted. + return new Promise(function (resolve, reject) { + process.nextTick(function () { + if (_this[kError]) { + reject(_this[kError]); + } else { + resolve(createIterResult(undefined, true)); + } + }); + }); + } + + // if we have multiple next() calls + // we will wait for the previous Promise to finish + // this logic is optimized to support for await loops, + // where next() is only called once at a time + var lastPromise = this[kLastPromise]; + var promise; + if (lastPromise) { + promise = new Promise(wrapForNext(lastPromise, this)); + } else { + // fast path needed to support multiple this.push() + // without triggering the next() queue + var data = this[kStream].read(); + if (data !== null) { + return Promise.resolve(createIterResult(data, false)); + } + promise = new Promise(this[kHandlePromise]); + } + this[kLastPromise] = promise; + return promise; + } +}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () { + return this; +}), _defineProperty(_Object$setPrototypeO, "return", function _return() { + var _this2 = this; + // destroy(err, cb) is a private API + // we can guarantee we have that here, because we control the + // Readable class this is attached to + return new Promise(function (resolve, reject) { + _this2[kStream].destroy(null, function (err) { + if (err) { + reject(err); + return; + } + resolve(createIterResult(undefined, true)); + }); + }); +}), _Object$setPrototypeO), AsyncIteratorPrototype); +var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) { + var _Object$create; + var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, { + value: stream, + writable: true + }), _defineProperty(_Object$create, kLastResolve, { + value: null, + writable: true + }), _defineProperty(_Object$create, kLastReject, { + value: null, + writable: true + }), _defineProperty(_Object$create, kError, { + value: null, + writable: true + }), _defineProperty(_Object$create, kEnded, { + value: stream._readableState.endEmitted, + writable: true + }), _defineProperty(_Object$create, kHandlePromise, { + value: function value(resolve, reject) { + var data = iterator[kStream].read(); + if (data) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(data, false)); + } else { + iterator[kLastResolve] = resolve; + iterator[kLastReject] = reject; + } + }, + writable: true + }), _Object$create)); + iterator[kLastPromise] = null; + finished(stream, function (err) { + if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') { + var reject = iterator[kLastReject]; + // reject if we are waiting for data in the Promise + // returned by next() and store the error + if (reject !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + reject(err); + } + iterator[kError] = err; + return; + } + var resolve = iterator[kLastResolve]; + if (resolve !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(undefined, true)); + } + iterator[kEnded] = true; + }); + stream.on('readable', onReadable.bind(null, iterator)); + return iterator; +}; +module.exports = createReadableStreamAsyncIterator; + +/***/ }), + +/***/ 77336: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var _require = __nccwpck_require__(20181), + Buffer = _require.Buffer; +var _require2 = __nccwpck_require__(39023), + inspect = _require2.inspect; +var custom = inspect && inspect.custom || 'inspect'; +function copyBuffer(src, target, offset) { + Buffer.prototype.copy.call(src, target, offset); +} +module.exports = /*#__PURE__*/function () { + function BufferList() { + _classCallCheck(this, BufferList); + this.head = null; + this.tail = null; + this.length = 0; + } + _createClass(BufferList, [{ + key: "push", + value: function push(v) { + var entry = { + data: v, + next: null + }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + } + }, { + key: "unshift", + value: function unshift(v) { + var entry = { + data: v, + next: this.head + }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + } + }, { + key: "shift", + value: function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + } + }, { + key: "clear", + value: function clear() { + this.head = this.tail = null; + this.length = 0; + } + }, { + key: "join", + value: function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) ret += s + p.data; + return ret; + } + }, { + key: "concat", + value: function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + } + + // Consumes a specified amount of bytes or characters from the buffered data. + }, { + key: "consume", + value: function consume(n, hasStrings) { + var ret; + if (n < this.head.data.length) { + // `slice` is the same for buffers and strings. + ret = this.head.data.slice(0, n); + this.head.data = this.head.data.slice(n); + } else if (n === this.head.data.length) { + // First chunk is a perfect match. + ret = this.shift(); + } else { + // Result spans more than one buffer. + ret = hasStrings ? this._getString(n) : this._getBuffer(n); + } + return ret; + } + }, { + key: "first", + value: function first() { + return this.head.data; + } + + // Consumes a specified amount of characters from the buffered data. + }, { + key: "_getString", + value: function _getString(n) { + var p = this.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + + // Consumes a specified amount of bytes from the buffered data. + }, { + key: "_getBuffer", + value: function _getBuffer(n) { + var ret = Buffer.allocUnsafe(n); + var p = this.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + + // Make sure the linked list only shows the minimal necessary information. + }, { + key: custom, + value: function value(_, options) { + return inspect(this, _objectSpread(_objectSpread({}, options), {}, { + // Only inspect one level. + depth: 0, + // It should not recurse. + customInspect: false + })); + } + }]); + return BufferList; +}(); + +/***/ }), + +/***/ 65089: +/***/ ((module) => { + +"use strict"; + + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err) { + if (!this._writableState) { + process.nextTick(emitErrorNT, this, err); + } else if (!this._writableState.errorEmitted) { + this._writableState.errorEmitted = true; + process.nextTick(emitErrorNT, this, err); + } + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + this._destroy(err || null, function (err) { + if (!cb && err) { + if (!_this._writableState) { + process.nextTick(emitErrorAndCloseNT, _this, err); + } else if (!_this._writableState.errorEmitted) { + _this._writableState.errorEmitted = true; + process.nextTick(emitErrorAndCloseNT, _this, err); + } else { + process.nextTick(emitCloseNT, _this); + } + } else if (cb) { + process.nextTick(emitCloseNT, _this); + cb(err); + } else { + process.nextTick(emitCloseNT, _this); + } + }); + return this; +} +function emitErrorAndCloseNT(self, err) { + emitErrorNT(self, err); + emitCloseNT(self); +} +function emitCloseNT(self) { + if (self._writableState && !self._writableState.emitClose) return; + if (self._readableState && !self._readableState.emitClose) return; + self.emit('close'); +} +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finalCalled = false; + this._writableState.prefinished = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} +function emitErrorNT(self, err) { + self.emit('error', err); +} +function errorOrDestroy(stream, err) { + // We have tests that rely on errors being emitted + // in the same tick, so changing this is semver major. + // For now when you opt-in to autoDestroy we allow + // the error to be emitted nextTick. In a future + // semver major update we should change the default to this. + + var rState = stream._readableState; + var wState = stream._writableState; + if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err); +} +module.exports = { + destroy: destroy, + undestroy: undestroy, + errorOrDestroy: errorOrDestroy +}; + +/***/ }), + +/***/ 36815: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Ported from https://github.com/mafintosh/end-of-stream with +// permission from the author, Mathias Buus (@mafintosh). + + + +var ERR_STREAM_PREMATURE_CLOSE = (__nccwpck_require__(25500)/* .codes */ .F).ERR_STREAM_PREMATURE_CLOSE; +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + callback.apply(this, args); + }; +} +function noop() {} +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} +function eos(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + callback = once(callback || noop); + var readable = opts.readable || opts.readable !== false && stream.readable; + var writable = opts.writable || opts.writable !== false && stream.writable; + var onlegacyfinish = function onlegacyfinish() { + if (!stream.writable) onfinish(); + }; + var writableEnded = stream._writableState && stream._writableState.finished; + var onfinish = function onfinish() { + writable = false; + writableEnded = true; + if (!readable) callback.call(stream); + }; + var readableEnded = stream._readableState && stream._readableState.endEmitted; + var onend = function onend() { + readable = false; + readableEnded = true; + if (!writable) callback.call(stream); + }; + var onerror = function onerror(err) { + callback.call(stream, err); + }; + var onclose = function onclose() { + var err; + if (readable && !readableEnded) { + if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + if (writable && !writableEnded) { + if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + }; + var onrequest = function onrequest() { + stream.req.on('finish', onfinish); + }; + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest();else stream.on('request', onrequest); + } else if (writable && !stream._writableState) { + // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + return function () { + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +} +module.exports = eos; + +/***/ }), + +/***/ 4659: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } +function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var ERR_INVALID_ARG_TYPE = (__nccwpck_require__(25500)/* .codes */ .F).ERR_INVALID_ARG_TYPE; +function from(Readable, iterable, opts) { + var iterator; + if (iterable && typeof iterable.next === 'function') { + iterator = iterable; + } else if (iterable && iterable[Symbol.asyncIterator]) iterator = iterable[Symbol.asyncIterator]();else if (iterable && iterable[Symbol.iterator]) iterator = iterable[Symbol.iterator]();else throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable); + var readable = new Readable(_objectSpread({ + objectMode: true + }, opts)); + // Reading boolean to protect against _read + // being called before last iteration completion. + var reading = false; + readable._read = function () { + if (!reading) { + reading = true; + next(); + } + }; + function next() { + return _next2.apply(this, arguments); + } + function _next2() { + _next2 = _asyncToGenerator(function* () { + try { + var _yield$iterator$next = yield iterator.next(), + value = _yield$iterator$next.value, + done = _yield$iterator$next.done; + if (done) { + readable.push(null); + } else if (readable.push(yield value)) { + next(); + } else { + reading = false; + } + } catch (err) { + readable.destroy(err); + } + }); + return _next2.apply(this, arguments); + } + return readable; +} +module.exports = from; + + +/***/ }), + +/***/ 16701: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Ported from https://github.com/mafintosh/pump with +// permission from the author, Mathias Buus (@mafintosh). + + + +var eos; +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + callback.apply(void 0, arguments); + }; +} +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; +function noop(err) { + // Rethrow the error if it exists to avoid swallowing it + if (err) throw err; +} +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} +function destroyer(stream, reading, writing, callback) { + callback = once(callback); + var closed = false; + stream.on('close', function () { + closed = true; + }); + if (eos === undefined) eos = __nccwpck_require__(36815); + eos(stream, { + readable: reading, + writable: writing + }, function (err) { + if (err) return callback(err); + closed = true; + callback(); + }); + var destroyed = false; + return function (err) { + if (closed) return; + if (destroyed) return; + destroyed = true; + + // request.destroy just do .end - .abort is what we want + if (isRequest(stream)) return stream.abort(); + if (typeof stream.destroy === 'function') return stream.destroy(); + callback(err || new ERR_STREAM_DESTROYED('pipe')); + }; +} +function call(fn) { + fn(); +} +function pipe(from, to) { + return from.pipe(to); +} +function popCallback(streams) { + if (!streams.length) return noop; + if (typeof streams[streams.length - 1] !== 'function') return noop; + return streams.pop(); +} +function pipeline() { + for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) { + streams[_key] = arguments[_key]; + } + var callback = popCallback(streams); + if (Array.isArray(streams[0])) streams = streams[0]; + if (streams.length < 2) { + throw new ERR_MISSING_ARGS('streams'); + } + var error; + var destroys = streams.map(function (stream, i) { + var reading = i < streams.length - 1; + var writing = i > 0; + return destroyer(stream, reading, writing, function (err) { + if (!error) error = err; + if (err) destroys.forEach(call); + if (reading) return; + destroys.forEach(call); + callback(error); + }); + }); + return streams.reduce(pipe); +} +module.exports = pipeline; + +/***/ }), + +/***/ 54874: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var ERR_INVALID_OPT_VALUE = (__nccwpck_require__(25500)/* .codes */ .F).ERR_INVALID_OPT_VALUE; +function highWaterMarkFrom(options, isDuplex, duplexKey) { + return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null; +} +function getHighWaterMark(state, options, duplexKey, isDuplex) { + var hwm = highWaterMarkFrom(options, isDuplex, duplexKey); + if (hwm != null) { + if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) { + var name = isDuplex ? duplexKey : 'highWaterMark'; + throw new ERR_INVALID_OPT_VALUE(name, hwm); + } + return Math.floor(hwm); + } + + // Default value + return state.objectMode ? 16 : 16 * 1024; +} +module.exports = { + getHighWaterMark: getHighWaterMark +}; + +/***/ }), + +/***/ 63283: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(2203); + + +/***/ }), + +/***/ 86131: +/***/ ((module, exports, __nccwpck_require__) => { + +var Stream = __nccwpck_require__(2203); +if (process.env.READABLE_STREAM === 'disable' && Stream) { + module.exports = Stream.Readable; + Object.assign(module.exports, Stream); + module.exports.Stream = Stream; +} else { + exports = module.exports = __nccwpck_require__(86893); + exports.Stream = Stream || exports; + exports.Readable = exports; + exports.Writable = __nccwpck_require__(38797); + exports.Duplex = __nccwpck_require__(82063); + exports.Transform = __nccwpck_require__(12337); + exports.PassThrough = __nccwpck_require__(35283); + exports.finished = __nccwpck_require__(36815); + exports.pipeline = __nccwpck_require__(16701); +} + + +/***/ }), + +/***/ 67842: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const {PassThrough} = __nccwpck_require__(2203); +const extend = __nccwpck_require__(23860); + +let debug = () => {}; +if ( + typeof process !== 'undefined' && + 'env' in process && + typeof process.env === 'object' && + process.env.DEBUG === 'retry-request' +) { + debug = message => { + console.log('retry-request:', message); + }; +} + +const DEFAULTS = { + objectMode: false, + retries: 2, + + /* + The maximum time to delay in seconds. If retryDelayMultiplier results in a + delay greater than maxRetryDelay, retries should delay by maxRetryDelay + seconds instead. + */ + maxRetryDelay: 64, + + /* + The multiplier by which to increase the delay time between the completion of + failed requests, and the initiation of the subsequent retrying request. + */ + retryDelayMultiplier: 2, + + /* + The length of time to keep retrying in seconds. The last sleep period will + be shortened as necessary, so that the last retry runs at deadline (and not + considerably beyond it). The total time starting from when the initial + request is sent, after which an error will be returned, regardless of the + retrying attempts made meanwhile. + */ + totalTimeout: 600, + + noResponseRetries: 2, + currentRetryAttempt: 0, + shouldRetryFn: function (response) { + const retryRanges = [ + // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + // 1xx - Retry (Informational, request still processing) + // 2xx - Do not retry (Success) + // 3xx - Do not retry (Redirect) + // 4xx - Do not retry (Client errors) + // 429 - Retry ("Too Many Requests") + // 5xx - Retry (Server errors) + [100, 199], + [429, 429], + [500, 599], + ]; + + const statusCode = response.statusCode; + debug(`Response status: ${statusCode}`); + + let range; + while ((range = retryRanges.shift())) { + if (statusCode >= range[0] && statusCode <= range[1]) { + // Not a successful status or redirect. + return true; + } + } + }, +}; + +function retryRequest(requestOpts, opts, callback) { + if (typeof requestOpts === 'string') { + requestOpts = {url: requestOpts}; + } + + const streamMode = typeof arguments[arguments.length - 1] !== 'function'; + + if (typeof opts === 'function') { + callback = opts; + } + + const manualCurrentRetryAttemptWasSet = + opts && typeof opts.currentRetryAttempt === 'number'; + opts = extend({}, DEFAULTS, opts); + + if (typeof opts.request === 'undefined') { + throw new Error('A request library must be provided to retry-request.'); + } + + let currentRetryAttempt = opts.currentRetryAttempt; + + let numNoResponseAttempts = 0; + let streamResponseHandled = false; + + let retryStream; + let requestStream; + let delayStream; + + let activeRequest; + const retryRequest = { + abort: function () { + if (activeRequest && activeRequest.abort) { + activeRequest.abort(); + } + }, + }; + + if (streamMode) { + retryStream = new PassThrough({objectMode: opts.objectMode}); + retryStream.abort = resetStreams; + } + + const timeOfFirstRequest = Date.now(); + if (currentRetryAttempt > 0) { + retryAfterDelay(currentRetryAttempt); + } else { + makeRequest(); + } + + if (streamMode) { + return retryStream; + } else { + return retryRequest; + } + + function resetStreams() { + delayStream = null; + + if (requestStream) { + requestStream.abort && requestStream.abort(); + requestStream.cancel && requestStream.cancel(); + + if (requestStream.destroy) { + requestStream.destroy(); + } else if (requestStream.end) { + requestStream.end(); + } + } + } + + function makeRequest() { + let finishHandled = false; + currentRetryAttempt++; + debug(`Current retry attempt: ${currentRetryAttempt}`); + + function handleFinish(args = []) { + if (!finishHandled) { + finishHandled = true; + retryStream.emit('complete', ...args); + } + } + + if (streamMode) { + streamResponseHandled = false; + + delayStream = new PassThrough({objectMode: opts.objectMode}); + requestStream = opts.request(requestOpts); + + setImmediate(() => { + retryStream.emit('request'); + }); + + requestStream + // gRPC via google-cloud-node can emit an `error` as well as a `response` + // Whichever it emits, we run with-- we can't run with both. That's what + // is up with the `streamResponseHandled` tracking. + .on('error', err => { + if (streamResponseHandled) { + return; + } + + streamResponseHandled = true; + onResponse(err); + }) + .on('response', (resp, body) => { + if (streamResponseHandled) { + return; + } + + streamResponseHandled = true; + onResponse(null, resp, body); + }) + .on('complete', (...params) => handleFinish(params)) + .on('finish', (...params) => handleFinish(params)); + + requestStream.pipe(delayStream); + } else { + activeRequest = opts.request(requestOpts, onResponse); + } + } + + function retryAfterDelay(currentRetryAttempt) { + if (streamMode) { + resetStreams(); + } + + const nextRetryDelay = getNextRetryDelay({ + maxRetryDelay: opts.maxRetryDelay, + retryDelayMultiplier: opts.retryDelayMultiplier, + retryNumber: currentRetryAttempt, + timeOfFirstRequest, + totalTimeout: opts.totalTimeout, + }); + debug(`Next retry delay: ${nextRetryDelay}`); + + if (nextRetryDelay <= 0) { + numNoResponseAttempts = opts.noResponseRetries + 1; + return; + } + + setTimeout(makeRequest, nextRetryDelay); + } + + function onResponse(err, response, body) { + // An error such as DNS resolution. + if (err) { + numNoResponseAttempts++; + + if (numNoResponseAttempts <= opts.noResponseRetries) { + retryAfterDelay(numNoResponseAttempts); + } else { + if (streamMode) { + retryStream.emit('error', err); + retryStream.end(); + } else { + callback(err, response, body); + } + } + + return; + } + + // Send the response to see if we should try again. + // NOTE: "currentRetryAttempt" isn't accurate by default, as it counts + // the very first request sent as the first "retry". It is only accurate + // when a user provides their own "currentRetryAttempt" option at + // instantiation. + const adjustedCurrentRetryAttempt = manualCurrentRetryAttemptWasSet + ? currentRetryAttempt + : currentRetryAttempt - 1; + if ( + adjustedCurrentRetryAttempt < opts.retries && + opts.shouldRetryFn(response) + ) { + retryAfterDelay(currentRetryAttempt); + return; + } + + // No more attempts need to be made, just continue on. + if (streamMode) { + retryStream.emit('response', response); + delayStream.pipe(retryStream); + requestStream.on('error', err => { + retryStream.destroy(err); + }); + } else { + callback(err, response, body); + } + } +} + +module.exports = retryRequest; + +function getNextRetryDelay(config) { + const { + maxRetryDelay, + retryDelayMultiplier, + retryNumber, + timeOfFirstRequest, + totalTimeout, + } = config; + + const maxRetryDelayMs = maxRetryDelay * 1000; + const totalTimeoutMs = totalTimeout * 1000; + + const jitter = Math.floor(Math.random() * 1000); + const calculatedNextRetryDelay = + Math.pow(retryDelayMultiplier, retryNumber) * 1000 + jitter; + + const maxAllowableDelayMs = + totalTimeoutMs - (Date.now() - timeOfFirstRequest); + + return Math.min( + calculatedNextRetryDelay, + maxAllowableDelayMs, + maxRetryDelayMs + ); +} + +module.exports.defaults = DEFAULTS; +module.exports.getNextRetryDelay = getNextRetryDelay; + + +/***/ }), + +/***/ 5546: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(67084); + +/***/ }), + +/***/ 67084: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +var RetryOperation = __nccwpck_require__(39538); + +exports.operation = function(options) { + var timeouts = exports.timeouts(options); + return new RetryOperation(timeouts, { + forever: options && (options.forever || options.retries === Infinity), + unref: options && options.unref, + maxRetryTime: options && options.maxRetryTime + }); +}; + +exports.timeouts = function(options) { + if (options instanceof Array) { + return [].concat(options); + } + + var opts = { + retries: 10, + factor: 2, + minTimeout: 1 * 1000, + maxTimeout: Infinity, + randomize: false + }; + for (var key in options) { + opts[key] = options[key]; + } + + if (opts.minTimeout > opts.maxTimeout) { + throw new Error('minTimeout is greater than maxTimeout'); + } + + var timeouts = []; + for (var i = 0; i < opts.retries; i++) { + timeouts.push(this.createTimeout(i, opts)); + } + + if (options && options.forever && !timeouts.length) { + timeouts.push(this.createTimeout(i, opts)); + } + + // sort the array numerically ascending + timeouts.sort(function(a,b) { + return a - b; + }); + + return timeouts; +}; + +exports.createTimeout = function(attempt, opts) { + var random = (opts.randomize) + ? (Math.random() + 1) + : 1; + + var timeout = Math.round(random * Math.max(opts.minTimeout, 1) * Math.pow(opts.factor, attempt)); + timeout = Math.min(timeout, opts.maxTimeout); + + return timeout; +}; + +exports.wrap = function(obj, options, methods) { + if (options instanceof Array) { + methods = options; + options = null; + } + + if (!methods) { + methods = []; + for (var key in obj) { + if (typeof obj[key] === 'function') { + methods.push(key); + } + } + } + + for (var i = 0; i < methods.length; i++) { + var method = methods[i]; + var original = obj[method]; + + obj[method] = function retryWrapper(original) { + var op = exports.operation(options); + var args = Array.prototype.slice.call(arguments, 1); + var callback = args.pop(); + + args.push(function(err) { + if (op.retry(err)) { + return; + } + if (err) { + arguments[0] = op.mainError(); + } + callback.apply(this, arguments); + }); + + op.attempt(function() { + original.apply(obj, args); + }); + }.bind(obj, original); + obj[method].options = options; + } +}; + + +/***/ }), + +/***/ 39538: +/***/ ((module) => { + +function RetryOperation(timeouts, options) { + // Compatibility for the old (timeouts, retryForever) signature + if (typeof options === 'boolean') { + options = { forever: options }; + } + + this._originalTimeouts = JSON.parse(JSON.stringify(timeouts)); + this._timeouts = timeouts; + this._options = options || {}; + this._maxRetryTime = options && options.maxRetryTime || Infinity; + this._fn = null; + this._errors = []; + this._attempts = 1; + this._operationTimeout = null; + this._operationTimeoutCb = null; + this._timeout = null; + this._operationStart = null; + this._timer = null; + + if (this._options.forever) { + this._cachedTimeouts = this._timeouts.slice(0); + } +} +module.exports = RetryOperation; + +RetryOperation.prototype.reset = function() { + this._attempts = 1; + this._timeouts = this._originalTimeouts.slice(0); +} + +RetryOperation.prototype.stop = function() { + if (this._timeout) { + clearTimeout(this._timeout); + } + if (this._timer) { + clearTimeout(this._timer); + } + + this._timeouts = []; + this._cachedTimeouts = null; +}; + +RetryOperation.prototype.retry = function(err) { + if (this._timeout) { + clearTimeout(this._timeout); + } + + if (!err) { + return false; + } + var currentTime = new Date().getTime(); + if (err && currentTime - this._operationStart >= this._maxRetryTime) { + this._errors.push(err); + this._errors.unshift(new Error('RetryOperation timeout occurred')); + return false; + } + + this._errors.push(err); + + var timeout = this._timeouts.shift(); + if (timeout === undefined) { + if (this._cachedTimeouts) { + // retry forever, only keep last error + this._errors.splice(0, this._errors.length - 1); + timeout = this._cachedTimeouts.slice(-1); + } else { + return false; + } + } + + var self = this; + this._timer = setTimeout(function() { + self._attempts++; + + if (self._operationTimeoutCb) { + self._timeout = setTimeout(function() { + self._operationTimeoutCb(self._attempts); + }, self._operationTimeout); + + if (self._options.unref) { + self._timeout.unref(); + } + } + + self._fn(self._attempts); + }, timeout); + + if (this._options.unref) { + this._timer.unref(); + } + + return true; +}; + +RetryOperation.prototype.attempt = function(fn, timeoutOps) { + this._fn = fn; + + if (timeoutOps) { + if (timeoutOps.timeout) { + this._operationTimeout = timeoutOps.timeout; + } + if (timeoutOps.cb) { + this._operationTimeoutCb = timeoutOps.cb; + } + } + + var self = this; + if (this._operationTimeoutCb) { + this._timeout = setTimeout(function() { + self._operationTimeoutCb(); + }, self._operationTimeout); + } + + this._operationStart = new Date().getTime(); + + this._fn(this._attempts); +}; + +RetryOperation.prototype.try = function(fn) { + console.log('Using RetryOperation.try() is deprecated'); + this.attempt(fn); +}; + +RetryOperation.prototype.start = function(fn) { + console.log('Using RetryOperation.start() is deprecated'); + this.attempt(fn); +}; + +RetryOperation.prototype.start = RetryOperation.prototype.try; + +RetryOperation.prototype.errors = function() { + return this._errors; +}; + +RetryOperation.prototype.attempts = function() { + return this._attempts; +}; + +RetryOperation.prototype.mainError = function() { + if (this._errors.length === 0) { + return null; + } + + var counts = {}; + var mainError = null; + var mainErrorCount = 0; + + for (var i = 0; i < this._errors.length; i++) { + var error = this._errors[i]; + var message = error.message; + var count = (counts[message] || 0) + 1; + + counts[message] = count; + + if (count >= mainErrorCount) { + mainError = error; + mainErrorCount = count; + } + } + + return mainError; +}; + + +/***/ }), + +/***/ 93058: +/***/ ((module, exports, __nccwpck_require__) => { + +/*! safe-buffer. MIT License. Feross Aboukhadijeh */ +/* eslint-disable node/no-deprecated-api */ +var buffer = __nccwpck_require__(20181) +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.prototype = Object.create(Buffer.prototype) + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + + +/***/ }), + +/***/ 71546: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var stubs = __nccwpck_require__(33897) + +/* + * StreamEvents can be used 2 ways: + * + * 1: + * function MyStream() { + * require('stream-events').call(this) + * } + * + * 2: + * require('stream-events')(myStream) + */ +function StreamEvents(stream) { + stream = stream || this + + var cfg = { + callthrough: true, + calls: 1 + } + + stubs(stream, '_read', cfg, stream.emit.bind(stream, 'reading')) + stubs(stream, '_write', cfg, stream.emit.bind(stream, 'writing')) + + return stream +} + +module.exports = StreamEvents + + +/***/ }), + +/***/ 34633: +/***/ ((module) => { + +module.exports = shift + +function shift (stream) { + var rs = stream._readableState + if (!rs) return null + return (rs.objectMode || typeof stream._duplexState === 'number') ? stream.read() : stream.read(getStateLength(rs)) +} + +function getStateLength (state) { + if (state.buffer.length) { + var idx = state.bufferIndex || 0 + // Since node 6.3.0 state.buffer is a BufferList not an array + if (state.buffer.head) { + return state.buffer.head.data.length + } else if (state.buffer.length - idx > 0 && state.buffer[idx]) { + return state.buffer[idx].length + } + } + + return state.length +} + + +/***/ }), + +/***/ 80634: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +/**/ + +var Buffer = (__nccwpck_require__(93058).Buffer); +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.I = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} + +/***/ }), + +/***/ 33897: +/***/ ((module) => { + +"use strict"; + + +module.exports = function stubs(obj, method, cfg, stub) { + if (!obj || !method || !obj[method]) + throw new Error('You must provide an object and a key for an existing method') + + if (!stub) { + stub = cfg + cfg = {} + } + + stub = stub || function() {} + + cfg.callthrough = cfg.callthrough || false + cfg.calls = cfg.calls || 0 + + var norevert = cfg.calls === 0 + + var cached = obj[method].bind(obj) + + obj[method] = function() { + var args = [].slice.call(arguments) + var returnVal + + if (cfg.callthrough) + returnVal = cached.apply(obj, args) + + returnVal = stub.apply(obj, args) || returnVal + + if (!norevert && --cfg.calls === 0) + obj[method] = cached + + return returnVal + } +} + + +/***/ }), + +/***/ 97745: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TeenyStatistics = exports.TeenyStatisticsWarning = void 0; +/** + * @class TeenyStatisticsWarning + * @extends Error + * @description While an error, is used for emitting warnings when + * meeting certain configured thresholds. + * @see process.emitWarning + */ +class TeenyStatisticsWarning extends Error { + /** + * @param {string} message + */ + constructor(message) { + super(message); + this.threshold = 0; + this.type = ''; + this.value = 0; + this.name = this.constructor.name; + Error.captureStackTrace(this, this.constructor); + } +} +exports.TeenyStatisticsWarning = TeenyStatisticsWarning; +TeenyStatisticsWarning.CONCURRENT_REQUESTS = 'ConcurrentRequestsExceededWarning'; +/** + * @class TeenyStatistics + * @description Maintain various statistics internal to teeny-request. Tracking + * is not automatic and must be instrumented within teeny-request. + */ +class TeenyStatistics { + /** + * @param {TeenyStatisticsOptions} [opts] + */ + constructor(opts) { + /** + * @type {number} + * @private + * @default 0 + */ + this._concurrentRequests = 0; + /** + * @type {boolean} + * @private + * @default false + */ + this._didConcurrentRequestWarn = false; + this._options = TeenyStatistics._prepareOptions(opts); + } + /** + * Returns a copy of the current options. + * @return {TeenyStatisticsOptions} + */ + getOptions() { + return Object.assign({}, this._options); + } + /** + * Change configured statistics options. This will not preserve unspecified + * options that were previously specified, i.e. this is a reset of options. + * @param {TeenyStatisticsOptions} [opts] + * @returns {TeenyStatisticsConfig} The previous options. + * @see _prepareOptions + */ + setOptions(opts) { + const oldOpts = this._options; + this._options = TeenyStatistics._prepareOptions(opts); + return oldOpts; + } + /** + * @readonly + * @return {TeenyStatisticsCounters} + */ + get counters() { + return { + concurrentRequests: this._concurrentRequests, + }; + } + /** + * @description Should call this right before making a request. + */ + requestStarting() { + this._concurrentRequests++; + if (this._options.concurrentRequests > 0 && + this._concurrentRequests >= this._options.concurrentRequests && + !this._didConcurrentRequestWarn) { + this._didConcurrentRequestWarn = true; + const warning = new TeenyStatisticsWarning('Possible excessive concurrent requests detected. ' + + this._concurrentRequests + + ' requests in-flight, which exceeds the configured threshold of ' + + this._options.concurrentRequests + + '. Use the TEENY_REQUEST_WARN_CONCURRENT_REQUESTS environment ' + + 'variable or the concurrentRequests option of teeny-request to ' + + 'increase or disable (0) this warning.'); + warning.type = TeenyStatisticsWarning.CONCURRENT_REQUESTS; + warning.value = this._concurrentRequests; + warning.threshold = this._options.concurrentRequests; + process.emitWarning(warning); + } + } + /** + * @description When using `requestStarting`, call this after the request + * has finished. + */ + requestFinished() { + // TODO negative? + this._concurrentRequests--; + } + /** + * Configuration Precedence: + * 1. Dependency inversion via defined option. + * 2. Global numeric environment variable. + * 3. Built-in default. + * This will not preserve unspecified options previously specified. + * @param {TeenyStatisticsOptions} [opts] + * @returns {TeenyStatisticsOptions} + * @private + */ + static _prepareOptions({ concurrentRequests: diConcurrentRequests, } = {}) { + let concurrentRequests = this.DEFAULT_WARN_CONCURRENT_REQUESTS; + const envConcurrentRequests = Number(process.env.TEENY_REQUEST_WARN_CONCURRENT_REQUESTS); + if (diConcurrentRequests !== undefined) { + concurrentRequests = diConcurrentRequests; + } + else if (!Number.isNaN(envConcurrentRequests)) { + concurrentRequests = envConcurrentRequests; + } + return { concurrentRequests }; + } +} +exports.TeenyStatistics = TeenyStatistics; +/** + * @description A default threshold representing when to warn about excessive + * in-flight/concurrent requests. + * @type {number} + * @static + * @readonly + * @default 5000 + */ +TeenyStatistics.DEFAULT_WARN_CONCURRENT_REQUESTS = 5000; +//# sourceMappingURL=TeenyStatistics.js.map + +/***/ }), + +/***/ 34003: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getAgent = exports.pool = void 0; +const http_1 = __nccwpck_require__(58611); +const https_1 = __nccwpck_require__(65692); +// eslint-disable-next-line node/no-deprecated-api +const url_1 = __nccwpck_require__(87016); +exports.pool = new Map(); +/** + * Determines if a proxy should be considered based on the environment. + * + * @param uri The request uri + * @returns {boolean} + */ +function shouldUseProxyForURI(uri) { + const noProxyEnv = process.env.NO_PROXY || process.env.no_proxy; + if (!noProxyEnv) { + return true; + } + const givenURI = new URL(uri); + for (const noProxyRaw of noProxyEnv.split(',')) { + const noProxy = noProxyRaw.trim(); + if (noProxy === givenURI.origin || noProxy === givenURI.hostname) { + return false; + } + else if (noProxy.startsWith('*.') || noProxy.startsWith('.')) { + const noProxyWildcard = noProxy.replace(/^\*\./, '.'); + if (givenURI.hostname.endsWith(noProxyWildcard)) { + return false; + } + } + } + return true; +} +/** + * Returns a custom request Agent if one is found, otherwise returns undefined + * which will result in the global http(s) Agent being used. + * @private + * @param {string} uri The request uri + * @param {Options} reqOpts The request options + * @returns {HttpAnyAgent|undefined} + */ +function getAgent(uri, reqOpts) { + const isHttp = uri.startsWith('http://'); + const proxy = reqOpts.proxy || + process.env.HTTP_PROXY || + process.env.http_proxy || + process.env.HTTPS_PROXY || + process.env.https_proxy; + const poolOptions = Object.assign({}, reqOpts.pool); + const manuallyProvidedProxy = !!reqOpts.proxy; + const shouldUseProxy = manuallyProvidedProxy || shouldUseProxyForURI(uri); + if (proxy && shouldUseProxy) { + // tslint:disable-next-line variable-name + const Agent = isHttp + ? __nccwpck_require__(81970) + : __nccwpck_require__(6518); + const proxyOpts = { ...(0, url_1.parse)(proxy), ...poolOptions }; + return new Agent(proxyOpts); + } + let key = isHttp ? 'http' : 'https'; + if (reqOpts.forever) { + key += ':forever'; + if (!exports.pool.has(key)) { + // tslint:disable-next-line variable-name + const Agent = isHttp ? http_1.Agent : https_1.Agent; + exports.pool.set(key, new Agent({ ...poolOptions, keepAlive: true })); + } + } + return exports.pool.get(key); +} +exports.getAgent = getAgent; +//# sourceMappingURL=agents.js.map + +/***/ }), + +/***/ 80321: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * @license + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.teenyRequest = exports.RequestError = void 0; +const node_fetch_1 = __nccwpck_require__(26705); +const stream_1 = __nccwpck_require__(2203); +const uuid = __nccwpck_require__(12048); +const agents_1 = __nccwpck_require__(34003); +const TeenyStatistics_1 = __nccwpck_require__(97745); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const streamEvents = __nccwpck_require__(71546); +class RequestError extends Error { +} +exports.RequestError = RequestError; +/** + * Convert options from Request to Fetch format + * @private + * @param reqOpts Request options + */ +function requestToFetchOptions(reqOpts) { + const options = { + method: reqOpts.method || 'GET', + ...(reqOpts.timeout && { timeout: reqOpts.timeout }), + ...(typeof reqOpts.gzip === 'boolean' && { compress: reqOpts.gzip }), + }; + if (typeof reqOpts.json === 'object') { + // Add Content-type: application/json header + reqOpts.headers = reqOpts.headers || {}; + reqOpts.headers['Content-Type'] = 'application/json'; + // Set body to JSON representation of value + options.body = JSON.stringify(reqOpts.json); + } + else { + if (Buffer.isBuffer(reqOpts.body)) { + options.body = reqOpts.body; + } + else if (typeof reqOpts.body !== 'string') { + options.body = JSON.stringify(reqOpts.body); + } + else { + options.body = reqOpts.body; + } + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + options.headers = reqOpts.headers; + let uri = (reqOpts.uri || + reqOpts.url); + if (!uri) { + throw new Error('Missing uri or url in reqOpts.'); + } + if (reqOpts.useQuerystring === true || typeof reqOpts.qs === 'object') { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const qs = __nccwpck_require__(83480); + const params = qs.stringify(reqOpts.qs); + uri = uri + '?' + params; + } + options.agent = (0, agents_1.getAgent)(uri, reqOpts); + return { uri, options }; +} +/** + * Convert a response from `fetch` to `request` format. + * @private + * @param opts The `request` options used to create the request. + * @param res The Fetch response + * @returns A `request` response object + */ +function fetchToRequestResponse(opts, res) { + const request = {}; + request.agent = opts.agent || false; + request.headers = (opts.headers || {}); + request.href = res.url; + // headers need to be converted from a map to an obj + const resHeaders = {}; + res.headers.forEach((value, key) => (resHeaders[key] = value)); + const response = Object.assign(res.body, { + statusCode: res.status, + statusMessage: res.statusText, + request, + body: res.body, + headers: resHeaders, + toJSON: () => ({ headers: resHeaders }), + }); + return response; +} +/** + * Create POST body from two parts as multipart/related content-type + * @private + * @param boundary + * @param multipart + */ +function createMultipartStream(boundary, multipart) { + const finale = `--${boundary}--`; + const stream = new stream_1.PassThrough(); + for (const part of multipart) { + const preamble = `--${boundary}\r\nContent-Type: ${part['Content-Type']}\r\n\r\n`; + stream.write(preamble); + if (typeof part.body === 'string') { + stream.write(part.body); + stream.write('\r\n'); + } + else { + part.body.pipe(stream, { end: false }); + part.body.on('end', () => { + stream.write('\r\n'); + stream.write(finale); + stream.end(); + }); + } + } + return stream; +} +function teenyRequest(reqOpts, callback) { + const { uri, options } = requestToFetchOptions(reqOpts); + const multipart = reqOpts.multipart; + if (reqOpts.multipart && multipart.length === 2) { + if (!callback) { + // TODO: add support for multipart uploads through streaming + throw new Error('Multipart without callback is not implemented.'); + } + const boundary = uuid.v4(); + options.headers['Content-Type'] = `multipart/related; boundary=${boundary}`; + options.body = createMultipartStream(boundary, multipart); + // Multipart upload + teenyRequest.stats.requestStarting(); + (0, node_fetch_1.default)(uri, options).then(res => { + teenyRequest.stats.requestFinished(); + const header = res.headers.get('content-type'); + const response = fetchToRequestResponse(options, res); + const body = response.body; + if (header === 'application/json' || + header === 'application/json; charset=utf-8') { + res.json().then(json => { + response.body = json; + callback(null, response, json); + }, (err) => { + callback(err, response, body); + }); + return; + } + res.text().then(text => { + response.body = text; + callback(null, response, text); + }, err => { + callback(err, response, body); + }); + }, err => { + teenyRequest.stats.requestFinished(); + callback(err, null, null); + }); + return; + } + if (callback === undefined) { + // Stream mode + const requestStream = streamEvents(new stream_1.PassThrough()); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let responseStream; + requestStream.once('reading', () => { + if (responseStream) { + (0, stream_1.pipeline)(responseStream, requestStream, () => { }); + } + else { + requestStream.once('response', () => { + (0, stream_1.pipeline)(responseStream, requestStream, () => { }); + }); + } + }); + options.compress = false; + teenyRequest.stats.requestStarting(); + (0, node_fetch_1.default)(uri, options).then(res => { + teenyRequest.stats.requestFinished(); + responseStream = res.body; + responseStream.on('error', (err) => { + requestStream.emit('error', err); + }); + const response = fetchToRequestResponse(options, res); + requestStream.emit('response', response); + }, err => { + teenyRequest.stats.requestFinished(); + requestStream.emit('error', err); + }); + // fetch doesn't supply the raw HTTP stream, instead it + // returns a PassThrough piped from the HTTP response + // stream. + return requestStream; + } + // GET or POST with callback + teenyRequest.stats.requestStarting(); + (0, node_fetch_1.default)(uri, options).then(res => { + teenyRequest.stats.requestFinished(); + const header = res.headers.get('content-type'); + const response = fetchToRequestResponse(options, res); + const body = response.body; + if (header === 'application/json' || + header === 'application/json; charset=utf-8') { + if (response.statusCode === 204) { + // Probably a DELETE + callback(null, response, body); + return; + } + res.json().then(json => { + response.body = json; + callback(null, response, json); + }, err => { + callback(err, response, body); + }); + return; + } + res.text().then(text => { + const response = fetchToRequestResponse(options, res); + response.body = text; + callback(null, response, text); + }, err => { + callback(err, response, body); + }); + }, err => { + teenyRequest.stats.requestFinished(); + callback(err, null, null); + }); + return; +} +exports.teenyRequest = teenyRequest; +teenyRequest.defaults = (defaults) => { + return (reqOpts, callback) => { + const opts = { ...defaults, ...reqOpts }; + if (callback === undefined) { + return teenyRequest(opts); + } + teenyRequest(opts, callback); + }; +}; +/** + * Single instance of an interface for keeping track of things. + */ +teenyRequest.stats = new TeenyStatistics_1.TeenyStatistics(); +teenyRequest.resetStats = () => { + teenyRequest.stats = new TeenyStatistics_1.TeenyStatistics(teenyRequest.stats.getOptions()); +}; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 77954: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = __nccwpck_require__(24434); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const promisify_1 = __importDefault(__nccwpck_require__(44446)); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 44446: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports["default"] = promisify; +//# sourceMappingURL=promisify.js.map + +/***/ }), + +/***/ 15299: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const net_1 = __importDefault(__nccwpck_require__(69278)); +const tls_1 = __importDefault(__nccwpck_require__(64756)); +const url_1 = __importDefault(__nccwpck_require__(87016)); +const assert_1 = __importDefault(__nccwpck_require__(42613)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const agent_base_1 = __nccwpck_require__(77954); +const parse_proxy_response_1 = __importDefault(__nccwpck_require__(27742)); +const debug = debug_1.default('https-proxy-agent:agent'); +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + * + * @api public + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('creating new HttpsProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + // ALPN is supported by Node.js >= v5. + // attempt to negotiate http/1.1 for proxy servers that support http/2 + if (this.secureProxy && !('ALPNProtocols' in proxy)) { + proxy.ALPNProtocols = ['http 1.1']; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + const headers = Object.assign({}, proxy.headers); + const hostname = `${opts.host}:${opts.port}`; + let payload = `CONNECT ${hostname} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + headers['Proxy-Authorization'] = `Basic ${Buffer.from(proxy.auth).toString('base64')}`; + } + // The `Host` header should only include the port + // number when it is not the default port. + let { host, port, secureEndpoint } = opts; + if (!isDefaultPort(port, secureEndpoint)) { + host += `:${port}`; + } + headers.Host = host; + headers.Connection = 'close'; + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = parse_proxy_response_1.default(socket); + socket.write(`${payload}\r\n`); + const { statusCode, buffered } = yield proxyResponsePromise; + if (statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + const servername = opts.servername || opts.host; + return tls_1.default.connect(Object.assign(Object.assign({}, omit(opts, 'host', 'hostname', 'path', 'port')), { socket, + servername })); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net_1.default.Socket({ writable: false }); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('replaying proxy buffer for failed request'); + assert_1.default(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + }); + } +} +exports["default"] = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function isDefaultPort(port, secure) { + return Boolean((!secure && port === 80) || (secure && port === 443)); +} +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=agent.js.map + +/***/ }), + +/***/ 6518: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const agent_1 = __importDefault(__nccwpck_require__(15299)); +function createHttpsProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpsProxyAgent) { + createHttpsProxyAgent.HttpsProxyAgent = agent_1.default; + createHttpsProxyAgent.prototype = agent_1.default.prototype; +})(createHttpsProxyAgent || (createHttpsProxyAgent = {})); +module.exports = createHttpsProxyAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 27742: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const debug = debug_1.default('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('close', onclose); + socket.removeListener('readable', read); + } + function onclose(err) { + debug('onclose had error %o', err); + } + function onend() { + debug('onend'); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const firstLine = buffered.toString('ascii', 0, buffered.indexOf('\r\n')); + const statusCode = +firstLine.split(' ')[1]; + debug('got proxy server response: %o', firstLine); + resolve({ + statusCode, + buffered + }); + } + socket.on('error', onerror); + socket.on('close', onclose); + socket.on('end', onend); + read(); + }); +} +exports["default"] = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map + +/***/ }), + +/***/ 1552: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var punycode = __nccwpck_require__(24876); +var mappingTable = __nccwpck_require__(92472); + +var PROCESSING_OPTIONS = { + TRANSITIONAL: 0, + NONTRANSITIONAL: 1 +}; + +function normalize(str) { // fix bug in v8 + return str.split('\u0000').map(function (s) { return s.normalize('NFC'); }).join('\u0000'); +} + +function findStatus(val) { + var start = 0; + var end = mappingTable.length - 1; + + while (start <= end) { + var mid = Math.floor((start + end) / 2); + + var target = mappingTable[mid]; + if (target[0][0] <= val && target[0][1] >= val) { + return target; + } else if (target[0][0] > val) { + end = mid - 1; + } else { + start = mid + 1; + } + } + + return null; +} + +var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + +function countSymbols(string) { + return string + // replace every surrogate pair with a BMP symbol + .replace(regexAstralSymbols, '_') + // then get the length + .length; +} + +function mapChars(domain_name, useSTD3, processing_option) { + var hasError = false; + var processed = ""; + + var len = countSymbols(domain_name); + for (var i = 0; i < len; ++i) { + var codePoint = domain_name.codePointAt(i); + var status = findStatus(codePoint); + + switch (status[1]) { + case "disallowed": + hasError = true; + processed += String.fromCodePoint(codePoint); + break; + case "ignored": + break; + case "mapped": + processed += String.fromCodePoint.apply(String, status[2]); + break; + case "deviation": + if (processing_option === PROCESSING_OPTIONS.TRANSITIONAL) { + processed += String.fromCodePoint.apply(String, status[2]); + } else { + processed += String.fromCodePoint(codePoint); + } + break; + case "valid": + processed += String.fromCodePoint(codePoint); + break; + case "disallowed_STD3_mapped": + if (useSTD3) { + hasError = true; + processed += String.fromCodePoint(codePoint); + } else { + processed += String.fromCodePoint.apply(String, status[2]); + } + break; + case "disallowed_STD3_valid": + if (useSTD3) { + hasError = true; + } + + processed += String.fromCodePoint(codePoint); + break; + } + } + + return { + string: processed, + error: hasError + }; +} + +var combiningMarksRegex = /[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8\u19C9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDE2C-\uDE37\uDEDF-\uDEEA\uDF01-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDE30-\uDE40\uDEAB-\uDEB7]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD83A[\uDCD0-\uDCD6]|\uDB40[\uDD00-\uDDEF]/; + +function validateLabel(label, processing_option) { + if (label.substr(0, 4) === "xn--") { + label = punycode.toUnicode(label); + processing_option = PROCESSING_OPTIONS.NONTRANSITIONAL; + } + + var error = false; + + if (normalize(label) !== label || + (label[3] === "-" && label[4] === "-") || + label[0] === "-" || label[label.length - 1] === "-" || + label.indexOf(".") !== -1 || + label.search(combiningMarksRegex) === 0) { + error = true; + } + + var len = countSymbols(label); + for (var i = 0; i < len; ++i) { + var status = findStatus(label.codePointAt(i)); + if ((processing === PROCESSING_OPTIONS.TRANSITIONAL && status[1] !== "valid") || + (processing === PROCESSING_OPTIONS.NONTRANSITIONAL && + status[1] !== "valid" && status[1] !== "deviation")) { + error = true; + break; + } + } + + return { + label: label, + error: error + }; +} + +function processing(domain_name, useSTD3, processing_option) { + var result = mapChars(domain_name, useSTD3, processing_option); + result.string = normalize(result.string); + + var labels = result.string.split("."); + for (var i = 0; i < labels.length; ++i) { + try { + var validation = validateLabel(labels[i]); + labels[i] = validation.label; + result.error = result.error || validation.error; + } catch(e) { + result.error = true; + } + } + + return { + string: labels.join("."), + error: result.error + }; +} + +module.exports.toASCII = function(domain_name, useSTD3, processing_option, verifyDnsLength) { + var result = processing(domain_name, useSTD3, processing_option); + var labels = result.string.split("."); + labels = labels.map(function(l) { + try { + return punycode.toASCII(l); + } catch(e) { + result.error = true; + return l; + } + }); + + if (verifyDnsLength) { + var total = labels.slice(0, labels.length - 1).join(".").length; + if (total.length > 253 || total.length === 0) { + result.error = true; + } + + for (var i=0; i < labels.length; ++i) { + if (labels.length > 63 || labels.length === 0) { + result.error = true; + break; + } + } + } + + if (result.error) return null; + return labels.join("."); +}; + +module.exports.toUnicode = function(domain_name, useSTD3) { + var result = processing(domain_name, useSTD3, PROCESSING_OPTIONS.NONTRANSITIONAL); + + return { + domain: result.string, + error: result.error + }; +}; + +module.exports.PROCESSING_OPTIONS = PROCESSING_OPTIONS; + + +/***/ }), + +/***/ 61860: +/***/ ((module) => { + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */ +var __extends; +var __assign; +var __rest; +var __decorate; +var __param; +var __esDecorate; +var __runInitializers; +var __propKey; +var __setFunctionName; +var __metadata; +var __awaiter; +var __generator; +var __exportStar; +var __values; +var __read; +var __spread; +var __spreadArrays; +var __spreadArray; +var __await; +var __asyncGenerator; +var __asyncDelegator; +var __asyncValues; +var __makeTemplateObject; +var __importStar; +var __importDefault; +var __classPrivateFieldGet; +var __classPrivateFieldSet; +var __classPrivateFieldIn; +var __createBinding; +var __addDisposableResource; +var __disposeResources; +var __rewriteRelativeImportExtension; +(function (factory) { + var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; + if (typeof define === "function" && define.amd) { + define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); + } + else if ( true && typeof module.exports === "object") { + factory(createExporter(root, createExporter(module.exports))); + } + else { + factory(createExporter(root)); + } + function createExporter(exports, previous) { + if (exports !== root) { + if (typeof Object.create === "function") { + Object.defineProperty(exports, "__esModule", { value: true }); + } + else { + exports.__esModule = true; + } + } + return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; + } +}) +(function (exporter) { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + + __extends = function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + + __assign = Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + + __rest = function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + }; + + __decorate = function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + }; + + __param = function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } + }; + + __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; + }; + + __runInitializers = function (thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; + }; + + __propKey = function (x) { + return typeof x === "symbol" ? x : "".concat(x); + }; + + __setFunctionName = function (f, name, prefix) { + if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; + return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); + }; + + __metadata = function (metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); + }; + + __awaiter = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + + __generator = function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + + __exportStar = function(m, o) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); + }; + + __createBinding = Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); + + __values = function (o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); + }; + + __read = function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + }; + + /** @deprecated */ + __spread = function () { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + }; + + /** @deprecated */ + __spreadArrays = function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + }; + + __spreadArray = function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); + }; + + __await = function (v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); + }; + + __asyncGenerator = function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } + }; + + __asyncDelegator = function (o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } + }; + + __asyncValues = function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } + }; + + __makeTemplateObject = function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; + }; + + var __setModuleDefault = Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }; + + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + + __importStar = function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + + __importDefault = function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + + __classPrivateFieldGet = function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + + __classPrivateFieldSet = function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + + __classPrivateFieldIn = function (state, receiver) { + if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); + return typeof state === "function" ? receiver === state : state.has(receiver); + }; + + __addDisposableResource = function (env, value, async) { + if (value !== null && value !== void 0) { + if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); + var dispose, inner; + if (async) { + if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); + dispose = value[Symbol.asyncDispose]; + } + if (dispose === void 0) { + if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); + dispose = value[Symbol.dispose]; + if (async) inner = dispose; + } + if (typeof dispose !== "function") throw new TypeError("Object not disposable."); + if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; + env.stack.push({ value: value, dispose: dispose, async: async }); + } + else if (async) { + env.stack.push({ async: true }); + } + return value; + }; + + var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; + + __disposeResources = function (env) { + function fail(e) { + env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; + env.hasError = true; + } + var r, s = 0; + function next() { + while (r = env.stack.pop()) { + try { + if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); + if (r.dispose) { + var result = r.dispose.call(r.value); + if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + else s |= 1; + } + catch (e) { + fail(e); + } + } + if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); + if (env.hasError) throw env.error; + } + return next(); + }; + + __rewriteRelativeImportExtension = function (path, preserveJsx) { + if (typeof path === "string" && /^\.\.?\//.test(path)) { + return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { + return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); + }); + } + return path; + }; + + exporter("__extends", __extends); + exporter("__assign", __assign); + exporter("__rest", __rest); + exporter("__decorate", __decorate); + exporter("__param", __param); + exporter("__esDecorate", __esDecorate); + exporter("__runInitializers", __runInitializers); + exporter("__propKey", __propKey); + exporter("__setFunctionName", __setFunctionName); + exporter("__metadata", __metadata); + exporter("__awaiter", __awaiter); + exporter("__generator", __generator); + exporter("__exportStar", __exportStar); + exporter("__createBinding", __createBinding); + exporter("__values", __values); + exporter("__read", __read); + exporter("__spread", __spread); + exporter("__spreadArrays", __spreadArrays); + exporter("__spreadArray", __spreadArray); + exporter("__await", __await); + exporter("__asyncGenerator", __asyncGenerator); + exporter("__asyncDelegator", __asyncDelegator); + exporter("__asyncValues", __asyncValues); + exporter("__makeTemplateObject", __makeTemplateObject); + exporter("__importStar", __importStar); + exporter("__importDefault", __importDefault); + exporter("__classPrivateFieldGet", __classPrivateFieldGet); + exporter("__classPrivateFieldSet", __classPrivateFieldSet); + exporter("__classPrivateFieldIn", __classPrivateFieldIn); + exporter("__addDisposableResource", __addDisposableResource); + exporter("__disposeResources", __disposeResources); + exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension); +}); + +0 && (0); + + +/***/ }), + +/***/ 20770: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(20218); + + +/***/ }), + +/***/ 20218: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +var net = __nccwpck_require__(69278); +var tls = __nccwpck_require__(64756); +var http = __nccwpck_require__(58611); +var https = __nccwpck_require__(65692); +var events = __nccwpck_require__(24434); +var assert = __nccwpck_require__(42613); +var util = __nccwpck_require__(39023); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + + +/***/ }), + +/***/ 46752: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Client = __nccwpck_require__(86197) +const Dispatcher = __nccwpck_require__(28611) +const errors = __nccwpck_require__(68707) +const Pool = __nccwpck_require__(35076) +const BalancedPool = __nccwpck_require__(81093) +const Agent = __nccwpck_require__(59965) +const util = __nccwpck_require__(3440) +const { InvalidArgumentError } = errors +const api = __nccwpck_require__(56615) +const buildConnector = __nccwpck_require__(59136) +const MockClient = __nccwpck_require__(47365) +const MockAgent = __nccwpck_require__(47501) +const MockPool = __nccwpck_require__(94004) +const mockErrors = __nccwpck_require__(52429) +const ProxyAgent = __nccwpck_require__(22720) +const RetryHandler = __nccwpck_require__(53573) +const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(32581) +const DecoratorHandler = __nccwpck_require__(78840) +const RedirectHandler = __nccwpck_require__(48299) +const createRedirectInterceptor = __nccwpck_require__(64415) + +let hasCrypto +try { + __nccwpck_require__(76982) + hasCrypto = true +} catch { + hasCrypto = false +} + +Object.assign(Dispatcher.prototype, api) + +module.exports.Dispatcher = Dispatcher +module.exports.Client = Client +module.exports.Pool = Pool +module.exports.BalancedPool = BalancedPool +module.exports.Agent = Agent +module.exports.ProxyAgent = ProxyAgent +module.exports.RetryHandler = RetryHandler + +module.exports.DecoratorHandler = DecoratorHandler +module.exports.RedirectHandler = RedirectHandler +module.exports.createRedirectInterceptor = createRedirectInterceptor + +module.exports.buildConnector = buildConnector +module.exports.errors = errors + +function makeDispatcher (fn) { + return (url, opts, handler) => { + if (typeof opts === 'function') { + handler = opts + opts = null + } + + if (!url || (typeof url !== 'string' && typeof url !== 'object' && !(url instanceof URL))) { + throw new InvalidArgumentError('invalid url') + } + + if (opts != null && typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (opts && opts.path != null) { + if (typeof opts.path !== 'string') { + throw new InvalidArgumentError('invalid opts.path') + } + + let path = opts.path + if (!opts.path.startsWith('/')) { + path = `/${path}` + } + + url = new URL(util.parseOrigin(url).origin + path) + } else { + if (!opts) { + opts = typeof url === 'object' ? url : {} + } + + url = util.parseURL(url) + } + + const { agent, dispatcher = getGlobalDispatcher() } = opts + + if (agent) { + throw new InvalidArgumentError('unsupported opts.agent. Did you mean opts.client?') + } + + return fn.call(dispatcher, { + ...opts, + origin: url.origin, + path: url.search ? `${url.pathname}${url.search}` : url.pathname, + method: opts.method || (opts.body ? 'PUT' : 'GET') + }, handler) + } +} + +module.exports.setGlobalDispatcher = setGlobalDispatcher +module.exports.getGlobalDispatcher = getGlobalDispatcher + +if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { + let fetchImpl = null + module.exports.fetch = async function fetch (resource) { + if (!fetchImpl) { + fetchImpl = (__nccwpck_require__(12315).fetch) + } + + try { + return await fetchImpl(...arguments) + } catch (err) { + if (typeof err === 'object') { + Error.captureStackTrace(err, this) + } + + throw err + } + } + module.exports.Headers = __nccwpck_require__(26349).Headers + module.exports.Response = __nccwpck_require__(48676).Response + module.exports.Request = __nccwpck_require__(25194).Request + module.exports.FormData = __nccwpck_require__(43073).FormData + module.exports.File = __nccwpck_require__(63041).File + module.exports.FileReader = __nccwpck_require__(82160).FileReader + + const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(75628) + + module.exports.setGlobalOrigin = setGlobalOrigin + module.exports.getGlobalOrigin = getGlobalOrigin + + const { CacheStorage } = __nccwpck_require__(44738) + const { kConstruct } = __nccwpck_require__(80296) + + // Cache & CacheStorage are tightly coupled with fetch. Even if it may run + // in an older version of Node, it doesn't have any use without fetch. + module.exports.caches = new CacheStorage(kConstruct) +} + +if (util.nodeMajor >= 16) { + const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(53168) + + module.exports.deleteCookie = deleteCookie + module.exports.getCookies = getCookies + module.exports.getSetCookies = getSetCookies + module.exports.setCookie = setCookie + + const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(94322) + + module.exports.parseMIMEType = parseMIMEType + module.exports.serializeAMimeType = serializeAMimeType +} + +if (util.nodeMajor >= 18 && hasCrypto) { + const { WebSocket } = __nccwpck_require__(55171) + + module.exports.WebSocket = WebSocket +} + +module.exports.request = makeDispatcher(api.request) +module.exports.stream = makeDispatcher(api.stream) +module.exports.pipeline = makeDispatcher(api.pipeline) +module.exports.connect = makeDispatcher(api.connect) +module.exports.upgrade = makeDispatcher(api.upgrade) + +module.exports.MockClient = MockClient +module.exports.MockPool = MockPool +module.exports.MockAgent = MockAgent +module.exports.mockErrors = mockErrors + + +/***/ }), + +/***/ 59965: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { InvalidArgumentError } = __nccwpck_require__(68707) +const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(36443) +const DispatcherBase = __nccwpck_require__(50001) +const Pool = __nccwpck_require__(35076) +const Client = __nccwpck_require__(86197) +const util = __nccwpck_require__(3440) +const createRedirectInterceptor = __nccwpck_require__(64415) +const { WeakRef, FinalizationRegistry } = __nccwpck_require__(13194)() + +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kMaxRedirections = Symbol('maxRedirections') +const kOnDrain = Symbol('onDrain') +const kFactory = Symbol('factory') +const kFinalizer = Symbol('finalizer') +const kOptions = Symbol('options') + +function defaultFactory (origin, opts) { + return opts && opts.connections === 1 + ? new Client(origin, opts) + : new Pool(origin, opts) +} + +class Agent extends DispatcherBase { + constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + super() + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (!Number.isInteger(maxRedirections) || maxRedirections < 0) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + if (connect && typeof connect !== 'function') { + connect = { ...connect } + } + + this[kInterceptors] = options.interceptors && options.interceptors.Agent && Array.isArray(options.interceptors.Agent) + ? options.interceptors.Agent + : [createRedirectInterceptor({ maxRedirections })] + + this[kOptions] = { ...util.deepClone(options), connect } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kMaxRedirections] = maxRedirections + this[kFactory] = factory + this[kClients] = new Map() + this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => { + const ref = this[kClients].get(key) + if (ref !== undefined && ref.deref() === undefined) { + this[kClients].delete(key) + } + }) + + const agent = this + + this[kOnDrain] = (origin, targets) => { + agent.emit('drain', origin, [agent, ...targets]) + } + + this[kOnConnect] = (origin, targets) => { + agent.emit('connect', origin, [agent, ...targets]) + } + + this[kOnDisconnect] = (origin, targets, err) => { + agent.emit('disconnect', origin, [agent, ...targets], err) + } + + this[kOnConnectionError] = (origin, targets, err) => { + agent.emit('connectionError', origin, [agent, ...targets], err) + } + } + + get [kRunning] () { + let ret = 0 + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore next: gc is undeterministic */ + if (client) { + ret += client[kRunning] + } + } + return ret + } + + [kDispatch] (opts, handler) { + let key + if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) { + key = String(opts.origin) + } else { + throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') + } + + const ref = this[kClients].get(key) + + let dispatcher = ref ? ref.deref() : null + if (!dispatcher) { + dispatcher = this[kFactory](opts.origin, this[kOptions]) + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) + + this[kClients].set(key, new WeakRef(dispatcher)) + this[kFinalizer].register(dispatcher, key) + } + + return dispatcher.dispatch(opts, handler) + } + + async [kClose] () { + const closePromises = [] + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore else: gc is undeterministic */ + if (client) { + closePromises.push(client.close()) + } + } + + await Promise.all(closePromises) + } + + async [kDestroy] (err) { + const destroyPromises = [] + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore else: gc is undeterministic */ + if (client) { + destroyPromises.push(client.destroy(err)) + } + } + + await Promise.all(destroyPromises) + } +} + +module.exports = Agent + + +/***/ }), + +/***/ 80158: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { addAbortListener } = __nccwpck_require__(3440) +const { RequestAbortedError } = __nccwpck_require__(68707) + +const kListener = Symbol('kListener') +const kSignal = Symbol('kSignal') + +function abort (self) { + if (self.abort) { + self.abort() + } else { + self.onError(new RequestAbortedError()) + } +} + +function addSignal (self, signal) { + self[kSignal] = null + self[kListener] = null + + if (!signal) { + return + } + + if (signal.aborted) { + abort(self) + return + } + + self[kSignal] = signal + self[kListener] = () => { + abort(self) + } + + addAbortListener(self[kSignal], self[kListener]) +} + +function removeSignal (self) { + if (!self[kSignal]) { + return + } + + if ('removeEventListener' in self[kSignal]) { + self[kSignal].removeEventListener('abort', self[kListener]) + } else { + self[kSignal].removeListener('abort', self[kListener]) + } + + self[kSignal] = null + self[kListener] = null +} + +module.exports = { + addSignal, + removeSignal +} + + +/***/ }), + +/***/ 34660: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { AsyncResource } = __nccwpck_require__(90290) +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { addSignal, removeSignal } = __nccwpck_require__(80158) + +class ConnectHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + const { signal, opaque, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + super('UNDICI_CONNECT') + + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.callback = callback + this.abort = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders () { + throw new SocketError('bad connect', null) + } + + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this + + removeSignal(this) + + this.callback = null + + let headers = rawHeaders + // Indicates is an HTTP2Session + if (headers != null) { + headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + } + + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + socket, + opaque, + context + }) + } + + onError (err) { + const { callback, opaque } = this + + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + } +} + +function connect (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + const connectHandler = new ConnectHandler(opts, callback) + this.dispatch({ ...opts, method: 'CONNECT' }, connectHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = connect + + +/***/ }), + +/***/ 76862: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + Readable, + Duplex, + PassThrough +} = __nccwpck_require__(2203) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { AsyncResource } = __nccwpck_require__(90290) +const { addSignal, removeSignal } = __nccwpck_require__(80158) +const assert = __nccwpck_require__(42613) + +const kResume = Symbol('resume') + +class PipelineRequest extends Readable { + constructor () { + super({ autoDestroy: true }) + + this[kResume] = null + } + + _read () { + const { [kResume]: resume } = this + + if (resume) { + this[kResume] = null + resume() + } + } + + _destroy (err, callback) { + this._read() + + callback(err) + } +} + +class PipelineResponse extends Readable { + constructor (resume) { + super({ autoDestroy: true }) + this[kResume] = resume + } + + _read () { + this[kResume]() + } + + _destroy (err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } + + callback(err) + } +} + +class PipelineHandler extends AsyncResource { + constructor (opts, handler) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof handler !== 'function') { + throw new InvalidArgumentError('invalid handler') + } + + const { signal, method, opaque, onInfo, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_PIPELINE') + + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.handler = handler + this.abort = null + this.context = null + this.onInfo = onInfo || null + + this.req = new PipelineRequest().on('error', util.nop) + + this.ret = new Duplex({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body } = this + + if (body && body.resume) { + body.resume() + } + }, + write: (chunk, encoding, callback) => { + const { req } = this + + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback() + } else { + req[kResume] = callback + } + }, + destroy: (err, callback) => { + const { body, req, res, ret, abort } = this + + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError() + } + + if (abort && err) { + abort() + } + + util.destroy(body, err) + util.destroy(req, err) + util.destroy(res, err) + + removeSignal(this) + + callback(err) + } + }).on('prefinish', () => { + const { req } = this + + // Node < 15 does not call _final in same tick. + req.push(null) + }) + + this.res = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + const { ret, res } = this + + assert(!res, 'pipeline cannot be retried') + + if (ret.destroyed) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume) { + const { opaque, handler, context } = this + + if (statusCode < 200) { + if (this.onInfo) { + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.onInfo({ statusCode, headers }) + } + return + } + + this.res = new PipelineResponse(resume) + + let body + try { + this.handler = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + body = this.runInAsyncScope(handler, null, { + statusCode, + headers, + opaque, + body: this.res, + context + }) + } catch (err) { + this.res.on('error', util.nop) + throw err + } + + if (!body || typeof body.on !== 'function') { + throw new InvalidReturnValueError('expected Readable') + } + + body + .on('data', (chunk) => { + const { ret, body } = this + + if (!ret.push(chunk) && body.pause) { + body.pause() + } + }) + .on('error', (err) => { + const { ret } = this + + util.destroy(ret, err) + }) + .on('end', () => { + const { ret } = this + + ret.push(null) + }) + .on('close', () => { + const { ret } = this + + if (!ret._readableState.ended) { + util.destroy(ret, new RequestAbortedError()) + } + }) + + this.body = body + } + + onData (chunk) { + const { res } = this + return res.push(chunk) + } + + onComplete (trailers) { + const { res } = this + res.push(null) + } + + onError (err) { + const { ret } = this + this.handler = null + util.destroy(ret, err) + } +} + +function pipeline (opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler) + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) + return pipelineHandler.ret + } catch (err) { + return new PassThrough().destroy(err) + } +} + +module.exports = pipeline + + +/***/ }), + +/***/ 14043: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Readable = __nccwpck_require__(49927) +const { + InvalidArgumentError, + RequestAbortedError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { getResolveErrorBodyCallback } = __nccwpck_require__(87655) +const { AsyncResource } = __nccwpck_require__(90290) +const { addSignal, removeSignal } = __nccwpck_require__(80158) + +class RequestHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts + + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { + throw new InvalidArgumentError('invalid highWaterMark') + } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_REQUEST') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.res = null + this.abort = null + this.body = body + this.trailers = {} + this.context = null + this.onInfo = onInfo || null + this.throwOnError = throwOnError + this.highWaterMark = highWaterMark + + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) + } + return + } + + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + const body = new Readable({ resume, abort, contentType, highWaterMark }) + + this.callback = null + this.res = body + if (callback !== null) { + if (this.throwOnError && statusCode >= 400) { + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body, contentType, statusCode, statusMessage, headers } + ) + } else { + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + trailers: this.trailers, + opaque, + body, + context + }) + } + } + } + + onData (chunk) { + const { res } = this + return res.push(chunk) + } + + onComplete (trailers) { + const { res } = this + + removeSignal(this) + + util.parseHeaders(trailers, this.trailers) + + res.push(null) + } + + onError (err) { + const { res, callback, body, opaque } = this + + removeSignal(this) + + if (callback) { + // TODO: Does this need queueMicrotask? + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + + if (res) { + this.res = null + // Ensure all queued handlers are invoked before destroying res. + queueMicrotask(() => { + util.destroy(res, err) + }) + } + + if (body) { + this.body = null + util.destroy(body, err) + } + } +} + +function request (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + this.dispatch(opts, new RequestHandler(opts, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = request +module.exports.RequestHandler = RequestHandler + + +/***/ }), + +/***/ 3560: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { finished, PassThrough } = __nccwpck_require__(2203) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { getResolveErrorBodyCallback } = __nccwpck_require__(87655) +const { AsyncResource } = __nccwpck_require__(90290) +const { addSignal, removeSignal } = __nccwpck_require__(80158) + +class StreamHandler extends AsyncResource { + constructor (opts, factory, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts + + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('invalid factory') + } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_STREAM') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.factory = factory + this.callback = callback + this.res = null + this.abort = null + this.context = null + this.trailers = null + this.body = body + this.onInfo = onInfo || null + this.throwOnError = throwOnError || false + + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { factory, opaque, context, callback, responseHeaders } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) + } + return + } + + this.factory = null + + let res + + if (this.throwOnError && statusCode >= 400) { + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + res = new PassThrough() + + this.callback = null + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body: res, contentType, statusCode, statusMessage, headers } + ) + } else { + if (factory === null) { + return + } + + res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context + }) + + if ( + !res || + typeof res.write !== 'function' || + typeof res.end !== 'function' || + typeof res.on !== 'function' + ) { + throw new InvalidReturnValueError('expected Writable') + } + + // TODO: Avoid finished. It registers an unnecessary amount of listeners. + finished(res, { readable: false }, (err) => { + const { callback, res, opaque, trailers, abort } = this + + this.res = null + if (err || !res.readable) { + util.destroy(res, err) + } + + this.callback = null + this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) + + if (err) { + abort() + } + }) + } + + res.on('drain', resume) + + this.res = res + + const needDrain = res.writableNeedDrain !== undefined + ? res.writableNeedDrain + : res._writableState && res._writableState.needDrain + + return needDrain !== true + } + + onData (chunk) { + const { res } = this + + return res ? res.write(chunk) : true + } + + onComplete (trailers) { + const { res } = this + + removeSignal(this) + + if (!res) { + return + } + + this.trailers = util.parseHeaders(trailers) + + res.end() + } + + onError (err) { + const { res, callback, opaque, body } = this + + removeSignal(this) + + this.factory = null + + if (res) { + this.res = null + util.destroy(res, err) + } else if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + + if (body) { + this.body = null + util.destroy(body, err) + } + } +} + +function stream (opts, factory, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + this.dispatch(opts, new StreamHandler(opts, factory, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = stream + + +/***/ }), + +/***/ 61882: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(68707) +const { AsyncResource } = __nccwpck_require__(90290) +const util = __nccwpck_require__(3440) +const { addSignal, removeSignal } = __nccwpck_require__(80158) +const assert = __nccwpck_require__(42613) + +class UpgradeHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + const { signal, opaque, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + super('UNDICI_UPGRADE') + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.abort = null + this.context = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = null + } + + onHeaders () { + throw new SocketError('bad upgrade', null) + } + + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this + + assert.strictEqual(statusCode, 101) + + removeSignal(this) + + this.callback = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.runInAsyncScope(callback, null, null, { + headers, + socket, + opaque, + context + }) + } + + onError (err) { + const { callback, opaque } = this + + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + } +} + +function upgrade (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + const upgradeHandler = new UpgradeHandler(opts, callback) + this.dispatch({ + ...opts, + method: opts.method || 'GET', + upgrade: opts.protocol || 'Websocket' + }, upgradeHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = upgrade + + +/***/ }), + +/***/ 56615: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +module.exports.request = __nccwpck_require__(14043) +module.exports.stream = __nccwpck_require__(3560) +module.exports.pipeline = __nccwpck_require__(76862) +module.exports.upgrade = __nccwpck_require__(61882) +module.exports.connect = __nccwpck_require__(34660) + + +/***/ }), + +/***/ 49927: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Ported from https://github.com/nodejs/undici/pull/907 + + + +const assert = __nccwpck_require__(42613) +const { Readable } = __nccwpck_require__(2203) +const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(3440) + +let Blob + +const kConsume = Symbol('kConsume') +const kReading = Symbol('kReading') +const kBody = Symbol('kBody') +const kAbort = Symbol('abort') +const kContentType = Symbol('kContentType') + +const noop = () => {} + +module.exports = class BodyReadable extends Readable { + constructor ({ + resume, + abort, + contentType = '', + highWaterMark = 64 * 1024 // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }) + + this._readableState.dataEmitted = false + + this[kAbort] = abort + this[kConsume] = null + this[kBody] = null + this[kContentType] = contentType + + // Is stream being consumed through Readable API? + // This is an optimization so that we avoid checking + // for 'data' and 'readable' listeners in the hot path + // inside push(). + this[kReading] = false + } + + destroy (err) { + if (this.destroyed) { + // Node < 16 + return this + } + + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } + + if (err) { + this[kAbort]() + } + + return super.destroy(err) + } + + emit (ev, ...args) { + if (ev === 'data') { + // Node < 16.7 + this._readableState.dataEmitted = true + } else if (ev === 'error') { + // Node < 16 + this._readableState.errorEmitted = true + } + return super.emit(ev, ...args) + } + + on (ev, ...args) { + if (ev === 'data' || ev === 'readable') { + this[kReading] = true + } + return super.on(ev, ...args) + } + + addListener (ev, ...args) { + return this.on(ev, ...args) + } + + off (ev, ...args) { + const ret = super.off(ev, ...args) + if (ev === 'data' || ev === 'readable') { + this[kReading] = ( + this.listenerCount('data') > 0 || + this.listenerCount('readable') > 0 + ) + } + return ret + } + + removeListener (ev, ...args) { + return this.off(ev, ...args) + } + + push (chunk) { + if (this[kConsume] && chunk !== null && this.readableLength === 0) { + consumePush(this[kConsume], chunk) + return this[kReading] ? super.push(chunk) : true + } + return super.push(chunk) + } + + // https://fetch.spec.whatwg.org/#dom-body-text + async text () { + return consume(this, 'text') + } + + // https://fetch.spec.whatwg.org/#dom-body-json + async json () { + return consume(this, 'json') + } + + // https://fetch.spec.whatwg.org/#dom-body-blob + async blob () { + return consume(this, 'blob') + } + + // https://fetch.spec.whatwg.org/#dom-body-arraybuffer + async arrayBuffer () { + return consume(this, 'arrayBuffer') + } + + // https://fetch.spec.whatwg.org/#dom-body-formdata + async formData () { + // TODO: Implement. + throw new NotSupportedError() + } + + // https://fetch.spec.whatwg.org/#dom-body-bodyused + get bodyUsed () { + return util.isDisturbed(this) + } + + // https://fetch.spec.whatwg.org/#dom-body-body + get body () { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this) + if (this[kConsume]) { + // TODO: Is this the best way to force a lock? + this[kBody].getReader() // Ensure stream is locked. + assert(this[kBody].locked) + } + } + return this[kBody] + } + + dump (opts) { + let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144 + const signal = opts && opts.signal + + if (signal) { + try { + if (typeof signal !== 'object' || !('aborted' in signal)) { + throw new InvalidArgumentError('signal must be an AbortSignal') + } + util.throwIfAborted(signal) + } catch (err) { + return Promise.reject(err) + } + } + + if (this.closed) { + return Promise.resolve(null) + } + + return new Promise((resolve, reject) => { + const signalListenerCleanup = signal + ? util.addAbortListener(signal, () => { + this.destroy() + }) + : noop + + this + .on('close', function () { + signalListenerCleanup() + if (signal && signal.aborted) { + reject(signal.reason || Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })) + } else { + resolve(null) + } + }) + .on('error', noop) + .on('data', function (chunk) { + limit -= chunk.length + if (limit <= 0) { + this.destroy() + } + }) + .resume() + }) + } +} + +// https://streams.spec.whatwg.org/#readablestream-locked +function isLocked (self) { + // Consume is an implicit lock. + return (self[kBody] && self[kBody].locked === true) || self[kConsume] +} + +// https://fetch.spec.whatwg.org/#body-unusable +function isUnusable (self) { + return util.isDisturbed(self) || isLocked(self) +} + +async function consume (stream, type) { + if (isUnusable(stream)) { + throw new TypeError('unusable') + } + + assert(!stream[kConsume]) + + return new Promise((resolve, reject) => { + stream[kConsume] = { + type, + stream, + resolve, + reject, + length: 0, + body: [] + } + + stream + .on('error', function (err) { + consumeFinish(this[kConsume], err) + }) + .on('close', function () { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()) + } + }) + + process.nextTick(consumeStart, stream[kConsume]) + }) +} + +function consumeStart (consume) { + if (consume.body === null) { + return + } + + const { _readableState: state } = consume.stream + + for (const chunk of state.buffer) { + consumePush(consume, chunk) + } + + if (state.endEmitted) { + consumeEnd(this[kConsume]) + } else { + consume.stream.on('end', function () { + consumeEnd(this[kConsume]) + }) + } + + consume.stream.resume() + + while (consume.stream.read() != null) { + // Loop + } +} + +function consumeEnd (consume) { + const { type, body, resolve, stream, length } = consume + + try { + if (type === 'text') { + resolve(toUSVString(Buffer.concat(body))) + } else if (type === 'json') { + resolve(JSON.parse(Buffer.concat(body))) + } else if (type === 'arrayBuffer') { + const dst = new Uint8Array(length) + + let pos = 0 + for (const buf of body) { + dst.set(buf, pos) + pos += buf.byteLength + } + + resolve(dst.buffer) + } else if (type === 'blob') { + if (!Blob) { + Blob = (__nccwpck_require__(20181).Blob) + } + resolve(new Blob(body, { type: stream[kContentType] })) + } + + consumeFinish(consume) + } catch (err) { + stream.destroy(err) + } +} + +function consumePush (consume, chunk) { + consume.length += chunk.length + consume.body.push(chunk) +} + +function consumeFinish (consume, err) { + if (consume.body === null) { + return + } + + if (err) { + consume.reject(err) + } else { + consume.resolve() + } + + consume.type = null + consume.stream = null + consume.resolve = null + consume.reject = null + consume.length = 0 + consume.body = null +} + + +/***/ }), + +/***/ 87655: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(42613) +const { + ResponseStatusCodeError +} = __nccwpck_require__(68707) +const { toUSVString } = __nccwpck_require__(3440) + +async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { + assert(body) + + let chunks = [] + let limit = 0 + + for await (const chunk of body) { + chunks.push(chunk) + limit += chunk.length + if (limit > 128 * 1024) { + chunks = null + break + } + } + + if (statusCode === 204 || !contentType || !chunks) { + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) + return + } + + try { + if (contentType.startsWith('application/json')) { + const payload = JSON.parse(toUSVString(Buffer.concat(chunks))) + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) + return + } + + if (contentType.startsWith('text/')) { + const payload = toUSVString(Buffer.concat(chunks)) + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) + return + } + } catch (err) { + // Process in a fallback if error + } + + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) +} + +module.exports = { getResolveErrorBodyCallback } + + +/***/ }), + +/***/ 81093: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + BalancedPoolMissingUpstreamError, + InvalidArgumentError +} = __nccwpck_require__(68707) +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} = __nccwpck_require__(58640) +const Pool = __nccwpck_require__(35076) +const { kUrl, kInterceptors } = __nccwpck_require__(36443) +const { parseOrigin } = __nccwpck_require__(3440) +const kFactory = Symbol('factory') + +const kOptions = Symbol('options') +const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor') +const kCurrentWeight = Symbol('kCurrentWeight') +const kIndex = Symbol('kIndex') +const kWeight = Symbol('kWeight') +const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') +const kErrorPenalty = Symbol('kErrorPenalty') + +function getGreatestCommonDivisor (a, b) { + if (b === 0) return a + return getGreatestCommonDivisor(b, a % b) +} + +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} + +class BalancedPool extends PoolBase { + constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) { + super() + + this[kOptions] = opts + this[kIndex] = -1 + this[kCurrentWeight] = 0 + + this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100 + this[kErrorPenalty] = this[kOptions].errorPenalty || 15 + + if (!Array.isArray(upstreams)) { + upstreams = [upstreams] + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + this[kInterceptors] = opts.interceptors && opts.interceptors.BalancedPool && Array.isArray(opts.interceptors.BalancedPool) + ? opts.interceptors.BalancedPool + : [] + this[kFactory] = factory + + for (const upstream of upstreams) { + this.addUpstream(upstream) + } + this._updateBalancedPoolStats() + } + + addUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin + + if (this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + ))) { + return this + } + const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])) + + this[kAddClient](pool) + pool.on('connect', () => { + pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]) + }) + + pool.on('connectionError', () => { + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + }) + + pool.on('disconnect', (...args) => { + const err = args[2] + if (err && err.code === 'UND_ERR_SOCKET') { + // decrease the weight of the pool. + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + } + }) + + for (const client of this[kClients]) { + client[kWeight] = this[kMaxWeightPerServer] + } + + this._updateBalancedPoolStats() + + return this + } + + _updateBalancedPoolStats () { + this[kGreatestCommonDivisor] = this[kClients].map(p => p[kWeight]).reduce(getGreatestCommonDivisor, 0) + } + + removeUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin + + const pool = this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + )) + + if (pool) { + this[kRemoveClient](pool) + } + + return this + } + + get upstreams () { + return this[kClients] + .filter(dispatcher => dispatcher.closed !== true && dispatcher.destroyed !== true) + .map((p) => p[kUrl].origin) + } + + [kGetDispatcher] () { + // We validate that pools is greater than 0, + // otherwise we would have to wait until an upstream + // is added, which might never happen. + if (this[kClients].length === 0) { + throw new BalancedPoolMissingUpstreamError() + } + + const dispatcher = this[kClients].find(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + + if (!dispatcher) { + return + } + + const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true) + + if (allClientsBusy) { + return + } + + let counter = 0 + + let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain]) + + while (counter++ < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length + const pool = this[kClients][this[kIndex]] + + // find pool index with the largest weight + if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { + maxWeightIndex = this[kIndex] + } + + // decrease the current weight every `this[kClients].length`. + if (this[kIndex] === 0) { + // Set the current weight to the next lower weight. + this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor] + + if (this[kCurrentWeight] <= 0) { + this[kCurrentWeight] = this[kMaxWeightPerServer] + } + } + if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) { + return pool + } + } + + this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight] + this[kIndex] = maxWeightIndex + return this[kClients][maxWeightIndex] + } +} + +module.exports = BalancedPool + + +/***/ }), + +/***/ 50479: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kConstruct } = __nccwpck_require__(80296) +const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(23993) +const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(3440) +const { kHeadersList } = __nccwpck_require__(36443) +const { webidl } = __nccwpck_require__(74222) +const { Response, cloneResponse } = __nccwpck_require__(48676) +const { Request } = __nccwpck_require__(25194) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(89710) +const { fetching } = __nccwpck_require__(12315) +const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(15523) +const assert = __nccwpck_require__(42613) +const { getGlobalDispatcher } = __nccwpck_require__(32581) + +/** + * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation + * @typedef {Object} CacheBatchOperation + * @property {'delete' | 'put'} type + * @property {any} request + * @property {any} response + * @property {import('../../types/cache').CacheQueryOptions} options + */ + +/** + * @see https://w3c.github.io/ServiceWorker/#dfn-request-response-list + * @typedef {[any, any][]} requestResponseList + */ + +class Cache { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list + * @type {requestResponseList} + */ + #relevantRequestResponseList + + constructor () { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor() + } + + this.#relevantRequestResponseList = arguments[1] + } + + async match (request, options = {}) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.match' }) + + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + const p = await this.matchAll(request, options) + + if (p.length === 0) { + return + } + + return p[0] + } + + async matchAll (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) + + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + // 1. + let r = null + + // 2. + if (request !== undefined) { + if (request instanceof Request) { + // 2.1.1 + r = request[kState] + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { + // 2.2.1 + r = new Request(request)[kState] + } + } + + // 5. + // 5.1 + const responses = [] + + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + responses.push(requestResponse[1]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) + + // 5.3.2 + for (const requestResponse of requestResponses) { + responses.push(requestResponse[1]) + } + } + + // 5.4 + // We don't implement CORs so we don't need to loop over the responses, yay! + + // 5.5.1 + const responseList = [] + + // 5.5.2 + for (const response of responses) { + // 5.5.2.1 + const responseObject = new Response(response.body?.source ?? null) + const body = responseObject[kState].body + responseObject[kState] = response + responseObject[kState].body = body + responseObject[kHeaders][kHeadersList] = response.headersList + responseObject[kHeaders][kGuard] = 'immutable' + + responseList.push(responseObject) + } + + // 6. + return Object.freeze(responseList) + } + + async add (request) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.add' }) + + request = webidl.converters.RequestInfo(request) + + // 1. + const requests = [request] + + // 2. + const responseArrayPromise = this.addAll(requests) + + // 3. + return await responseArrayPromise + } + + async addAll (requests) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.addAll' }) + + requests = webidl.converters['sequence'](requests) + + // 1. + const responsePromises = [] + + // 2. + const requestList = [] + + // 3. + for (const request of requests) { + if (typeof request === 'string') { + continue + } + + // 3.1 + const r = request[kState] + + // 3.2 + if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Expected http/s scheme when method is not GET.' + }) + } + } + + // 4. + /** @type {ReturnType[]} */ + const fetchControllers = [] + + // 5. + for (const request of requests) { + // 5.1 + const r = new Request(request)[kState] + + // 5.2 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Expected http/s scheme.' + }) + } + + // 5.4 + r.initiator = 'fetch' + r.destination = 'subresource' + + // 5.5 + requestList.push(r) + + // 5.6 + const responsePromise = createDeferredPromise() + + // 5.7 + fetchControllers.push(fetching({ + request: r, + dispatcher: getGlobalDispatcher(), + processResponse (response) { + // 1. + if (response.type === 'error' || response.status === 206 || response.status < 200 || response.status > 299) { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Received an invalid status code or the request failed.' + })) + } else if (response.headersList.contains('vary')) { // 2. + // 2.1 + const fieldValues = getFieldValues(response.headersList.get('vary')) + + // 2.2 + for (const fieldValue of fieldValues) { + // 2.2.1 + if (fieldValue === '*') { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'invalid vary field value' + })) + + for (const controller of fetchControllers) { + controller.abort() + } + + return + } + } + } + }, + processResponseEndOfBody (response) { + // 1. + if (response.aborted) { + responsePromise.reject(new DOMException('aborted', 'AbortError')) + return + } + + // 2. + responsePromise.resolve(response) + } + })) + + // 5.8 + responsePromises.push(responsePromise.promise) + } + + // 6. + const p = Promise.all(responsePromises) + + // 7. + const responses = await p + + // 7.1 + const operations = [] + + // 7.2 + let index = 0 + + // 7.3 + for (const response of responses) { + // 7.3.1 + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 7.3.2 + request: requestList[index], // 7.3.3 + response // 7.3.4 + } + + operations.push(operation) // 7.3.5 + + index++ // 7.3.6 + } + + // 7.5 + const cacheJobPromise = createDeferredPromise() + + // 7.6.1 + let errorData = null + + // 7.6.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + // 7.6.3 + queueMicrotask(() => { + // 7.6.3.1 + if (errorData === null) { + cacheJobPromise.resolve(undefined) + } else { + // 7.6.3.2 + cacheJobPromise.reject(errorData) + } + }) + + // 7.7 + return cacheJobPromise.promise + } + + async put (request, response) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 2, { header: 'Cache.put' }) + + request = webidl.converters.RequestInfo(request) + response = webidl.converters.Response(response) + + // 1. + let innerRequest = null + + // 2. + if (request instanceof Request) { + innerRequest = request[kState] + } else { // 3. + innerRequest = new Request(request)[kState] + } + + // 4. + if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Expected an http/s scheme when method is not GET' + }) + } + + // 5. + const innerResponse = response[kState] + + // 6. + if (innerResponse.status === 206) { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Got 206 status' + }) + } + + // 7. + if (innerResponse.headersList.contains('vary')) { + // 7.1. + const fieldValues = getFieldValues(innerResponse.headersList.get('vary')) + + // 7.2. + for (const fieldValue of fieldValues) { + // 7.2.1 + if (fieldValue === '*') { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Got * vary field value' + }) + } + } + } + + // 8. + if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Response body is locked or disturbed' + }) + } + + // 9. + const clonedResponse = cloneResponse(innerResponse) + + // 10. + const bodyReadPromise = createDeferredPromise() + + // 11. + if (innerResponse.body != null) { + // 11.1 + const stream = innerResponse.body.stream + + // 11.2 + const reader = stream.getReader() + + // 11.3 + readAllBytes(reader).then(bodyReadPromise.resolve, bodyReadPromise.reject) + } else { + bodyReadPromise.resolve(undefined) + } + + // 12. + /** @type {CacheBatchOperation[]} */ + const operations = [] + + // 13. + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 14. + request: innerRequest, // 15. + response: clonedResponse // 16. + } + + // 17. + operations.push(operation) + + // 19. + const bytes = await bodyReadPromise.promise + + if (clonedResponse.body != null) { + clonedResponse.body.source = bytes + } + + // 19.1 + const cacheJobPromise = createDeferredPromise() + + // 19.2.1 + let errorData = null + + // 19.2.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + // 19.2.3 + queueMicrotask(() => { + // 19.2.3.1 + if (errorData === null) { + cacheJobPromise.resolve() + } else { // 19.2.3.2 + cacheJobPromise.reject(errorData) + } + }) + + return cacheJobPromise.promise + } + + async delete (request, options = {}) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.delete' }) + + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + /** + * @type {Request} + */ + let r = null + + if (request instanceof Request) { + r = request[kState] + + if (r.method !== 'GET' && !options.ignoreMethod) { + return false + } + } else { + assert(typeof request === 'string') + + r = new Request(request)[kState] + } + + /** @type {CacheBatchOperation[]} */ + const operations = [] + + /** @type {CacheBatchOperation} */ + const operation = { + type: 'delete', + request: r, + options + } + + operations.push(operation) + + const cacheJobPromise = createDeferredPromise() + + let errorData = null + let requestResponses + + try { + requestResponses = this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(!!requestResponses?.length) + } else { + cacheJobPromise.reject(errorData) + } + }) + + return cacheJobPromise.promise + } + + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys + * @param {any} request + * @param {import('../../types/cache').CacheQueryOptions} options + * @returns {readonly Request[]} + */ + async keys (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) + + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + // 1. + let r = null + + // 2. + if (request !== undefined) { + // 2.1 + if (request instanceof Request) { + // 2.1.1 + r = request[kState] + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { // 2.2 + r = new Request(request)[kState] + } + } + + // 4. + const promise = createDeferredPromise() + + // 5. + // 5.1 + const requests = [] + + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + // 5.2.1.1 + requests.push(requestResponse[0]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) + + // 5.3.2 + for (const requestResponse of requestResponses) { + // 5.3.2.1 + requests.push(requestResponse[0]) + } + } + + // 5.4 + queueMicrotask(() => { + // 5.4.1 + const requestList = [] + + // 5.4.2 + for (const request of requests) { + const requestObject = new Request('https://a') + requestObject[kState] = request + requestObject[kHeaders][kHeadersList] = request.headersList + requestObject[kHeaders][kGuard] = 'immutable' + requestObject[kRealm] = request.client + + // 5.4.2.1 + requestList.push(requestObject) + } + + // 5.4.3 + promise.resolve(Object.freeze(requestList)) + }) + + return promise.promise + } + + /** + * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm + * @param {CacheBatchOperation[]} operations + * @returns {requestResponseList} + */ + #batchCacheOperations (operations) { + // 1. + const cache = this.#relevantRequestResponseList + + // 2. + const backupCache = [...cache] + + // 3. + const addedItems = [] + + // 4.1 + const resultList = [] + + try { + // 4.2 + for (const operation of operations) { + // 4.2.1 + if (operation.type !== 'delete' && operation.type !== 'put') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'operation type does not match "delete" or "put"' + }) + } + + // 4.2.2 + if (operation.type === 'delete' && operation.response != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'delete operation should not have an associated response' + }) + } + + // 4.2.3 + if (this.#queryCache(operation.request, operation.options, addedItems).length) { + throw new DOMException('???', 'InvalidStateError') + } + + // 4.2.4 + let requestResponses + + // 4.2.5 + if (operation.type === 'delete') { + // 4.2.5.1 + requestResponses = this.#queryCache(operation.request, operation.options) + + // TODO: the spec is wrong, this is needed to pass WPTs + if (requestResponses.length === 0) { + return [] + } + + // 4.2.5.2 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) + + // 4.2.5.2.1 + cache.splice(idx, 1) + } + } else if (operation.type === 'put') { // 4.2.6 + // 4.2.6.1 + if (operation.response == null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'put operation should have an associated response' + }) + } + + // 4.2.6.2 + const r = operation.request + + // 4.2.6.3 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'expected http or https scheme' + }) + } + + // 4.2.6.4 + if (r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'not get method' + }) + } + + // 4.2.6.5 + if (operation.options != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'options must not be defined' + }) + } + + // 4.2.6.6 + requestResponses = this.#queryCache(operation.request) + + // 4.2.6.7 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) + + // 4.2.6.7.1 + cache.splice(idx, 1) + } + + // 4.2.6.8 + cache.push([operation.request, operation.response]) + + // 4.2.6.10 + addedItems.push([operation.request, operation.response]) + } + + // 4.2.7 + resultList.push([operation.request, operation.response]) + } + + // 4.3 + return resultList + } catch (e) { // 5. + // 5.1 + this.#relevantRequestResponseList.length = 0 + + // 5.2 + this.#relevantRequestResponseList = backupCache + + // 5.3 + throw e + } + } + + /** + * @see https://w3c.github.io/ServiceWorker/#query-cache + * @param {any} requestQuery + * @param {import('../../types/cache').CacheQueryOptions} options + * @param {requestResponseList} targetStorage + * @returns {requestResponseList} + */ + #queryCache (requestQuery, options, targetStorage) { + /** @type {requestResponseList} */ + const resultList = [] + + const storage = targetStorage ?? this.#relevantRequestResponseList + + for (const requestResponse of storage) { + const [cachedRequest, cachedResponse] = requestResponse + if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { + resultList.push(requestResponse) + } + } + + return resultList + } + + /** + * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm + * @param {any} requestQuery + * @param {any} request + * @param {any | null} response + * @param {import('../../types/cache').CacheQueryOptions | undefined} options + * @returns {boolean} + */ + #requestMatchesCachedItem (requestQuery, request, response = null, options) { + // if (options?.ignoreMethod === false && request.method === 'GET') { + // return false + // } + + const queryURL = new URL(requestQuery.url) + + const cachedURL = new URL(request.url) + + if (options?.ignoreSearch) { + cachedURL.search = '' + + queryURL.search = '' + } + + if (!urlEquals(queryURL, cachedURL, true)) { + return false + } + + if ( + response == null || + options?.ignoreVary || + !response.headersList.contains('vary') + ) { + return true + } + + const fieldValues = getFieldValues(response.headersList.get('vary')) + + for (const fieldValue of fieldValues) { + if (fieldValue === '*') { + return false + } + + const requestValue = request.headersList.get(fieldValue) + const queryValue = requestQuery.headersList.get(fieldValue) + + // If one has the header and the other doesn't, or one has + // a different value than the other, return false + if (requestValue !== queryValue) { + return false + } + } + + return true + } +} + +Object.defineProperties(Cache.prototype, { + [Symbol.toStringTag]: { + value: 'Cache', + configurable: true + }, + match: kEnumerableProperty, + matchAll: kEnumerableProperty, + add: kEnumerableProperty, + addAll: kEnumerableProperty, + put: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) + +const cacheQueryOptionConverters = [ + { + key: 'ignoreSearch', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'ignoreMethod', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'ignoreVary', + converter: webidl.converters.boolean, + defaultValue: false + } +] + +webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters) + +webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ + ...cacheQueryOptionConverters, + { + key: 'cacheName', + converter: webidl.converters.DOMString + } +]) + +webidl.converters.Response = webidl.interfaceConverter(Response) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.RequestInfo +) + +module.exports = { + Cache +} + + +/***/ }), + +/***/ 44738: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kConstruct } = __nccwpck_require__(80296) +const { Cache } = __nccwpck_require__(50479) +const { webidl } = __nccwpck_require__(74222) +const { kEnumerableProperty } = __nccwpck_require__(3440) + +class CacheStorage { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map + * @type {Map} + */ + async has (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.has' }) + + cacheName = webidl.converters.DOMString(cacheName) + + // 2.1.1 + // 2.2 + return this.#caches.has(cacheName) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open + * @param {string} cacheName + * @returns {Promise} + */ + async open (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.open' }) + + cacheName = webidl.converters.DOMString(cacheName) + + // 2.1 + if (this.#caches.has(cacheName)) { + // await caches.open('v1') !== await caches.open('v1') + + // 2.1.1 + const cache = this.#caches.get(cacheName) + + // 2.1.1.1 + return new Cache(kConstruct, cache) + } + + // 2.2 + const cache = [] + + // 2.3 + this.#caches.set(cacheName, cache) + + // 2.4 + return new Cache(kConstruct, cache) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete + * @param {string} cacheName + * @returns {Promise} + */ + async delete (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.delete' }) + + cacheName = webidl.converters.DOMString(cacheName) + + return this.#caches.delete(cacheName) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys + * @returns {string[]} + */ + async keys () { + webidl.brandCheck(this, CacheStorage) + + // 2.1 + const keys = this.#caches.keys() + + // 2.2 + return [...keys] + } +} + +Object.defineProperties(CacheStorage.prototype, { + [Symbol.toStringTag]: { + value: 'CacheStorage', + configurable: true + }, + match: kEnumerableProperty, + has: kEnumerableProperty, + open: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) + +module.exports = { + CacheStorage +} + + +/***/ }), + +/***/ 80296: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +module.exports = { + kConstruct: (__nccwpck_require__(36443).kConstruct) +} + + +/***/ }), + +/***/ 23993: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const assert = __nccwpck_require__(42613) +const { URLSerializer } = __nccwpck_require__(94322) +const { isValidHeaderName } = __nccwpck_require__(15523) + +/** + * @see https://url.spec.whatwg.org/#concept-url-equals + * @param {URL} A + * @param {URL} B + * @param {boolean | undefined} excludeFragment + * @returns {boolean} + */ +function urlEquals (A, B, excludeFragment = false) { + const serializedA = URLSerializer(A, excludeFragment) + + const serializedB = URLSerializer(B, excludeFragment) + + return serializedA === serializedB +} + +/** + * @see https://github.com/chromium/chromium/blob/694d20d134cb553d8d89e5500b9148012b1ba299/content/browser/cache_storage/cache_storage_cache.cc#L260-L262 + * @param {string} header + */ +function fieldValues (header) { + assert(header !== null) + + const values = [] + + for (let value of header.split(',')) { + value = value.trim() + + if (!value.length) { + continue + } else if (!isValidHeaderName(value)) { + continue + } + + values.push(value) + } + + return values +} + +module.exports = { + urlEquals, + fieldValues +} + + +/***/ }), + +/***/ 86197: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// @ts-check + + + +/* global WebAssembly */ + +const assert = __nccwpck_require__(42613) +const net = __nccwpck_require__(69278) +const http = __nccwpck_require__(58611) +const { pipeline } = __nccwpck_require__(2203) +const util = __nccwpck_require__(3440) +const timers = __nccwpck_require__(28804) +const Request = __nccwpck_require__(44655) +const DispatcherBase = __nccwpck_require__(50001) +const { + RequestContentLengthMismatchError, + ResponseContentLengthMismatchError, + InvalidArgumentError, + RequestAbortedError, + HeadersTimeoutError, + HeadersOverflowError, + SocketError, + InformationalError, + BodyTimeoutError, + HTTPParserError, + ResponseExceededMaxSizeError, + ClientDestroyedError +} = __nccwpck_require__(68707) +const buildConnector = __nccwpck_require__(59136) +const { + kUrl, + kReset, + kServerName, + kClient, + kBusy, + kParser, + kConnect, + kBlocking, + kResuming, + kRunning, + kPending, + kSize, + kWriting, + kQueue, + kConnected, + kConnecting, + kNeedDrain, + kNoRef, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kSocket, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kConnector, + kMaxRedirections, + kMaxRequests, + kCounter, + kClose, + kDestroy, + kDispatch, + kInterceptors, + kLocalAddress, + kMaxResponseSize, + kHTTPConnVersion, + // HTTP2 + kHost, + kHTTP2Session, + kHTTP2SessionState, + kHTTP2BuildRequest, + kHTTP2CopyHeaders, + kHTTP1BuildRequest +} = __nccwpck_require__(36443) + +/** @type {import('http2')} */ +let http2 +try { + http2 = __nccwpck_require__(85675) +} catch { + // @ts-ignore + http2 = { constants: {} } +} + +const { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS + } +} = http2 + +// Experimental +let h2ExperimentalWarned = false + +const FastBuffer = Buffer[Symbol.species] + +const kClosedResolve = Symbol('kClosedResolve') + +const channels = {} + +try { + const diagnosticsChannel = __nccwpck_require__(31637) + channels.sendHeaders = diagnosticsChannel.channel('undici:client:sendHeaders') + channels.beforeConnect = diagnosticsChannel.channel('undici:client:beforeConnect') + channels.connectError = diagnosticsChannel.channel('undici:client:connectError') + channels.connected = diagnosticsChannel.channel('undici:client:connected') +} catch { + channels.sendHeaders = { hasSubscribers: false } + channels.beforeConnect = { hasSubscribers: false } + channels.connectError = { hasSubscribers: false } + channels.connected = { hasSubscribers: false } +} + +/** + * @type {import('../types/client').default} + */ +class Client extends DispatcherBase { + /** + * + * @param {string|URL} url + * @param {import('../types/client').Client.Options} options + */ + constructor (url, { + interceptors, + maxHeaderSize, + headersTimeout, + socketTimeout, + requestTimeout, + connectTimeout, + bodyTimeout, + idleTimeout, + keepAlive, + keepAliveTimeout, + maxKeepAliveTimeout, + keepAliveMaxTimeout, + keepAliveTimeoutThreshold, + socketPath, + pipelining, + tls, + strictContentLength, + maxCachedSessions, + maxRedirections, + connect, + maxRequestsPerClient, + localAddress, + maxResponseSize, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + // h2 + allowH2, + maxConcurrentStreams + } = {}) { + super() + + if (keepAlive !== undefined) { + throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') + } + + if (socketTimeout !== undefined) { + throw new InvalidArgumentError('unsupported socketTimeout, use headersTimeout & bodyTimeout instead') + } + + if (requestTimeout !== undefined) { + throw new InvalidArgumentError('unsupported requestTimeout, use headersTimeout & bodyTimeout instead') + } + + if (idleTimeout !== undefined) { + throw new InvalidArgumentError('unsupported idleTimeout, use keepAliveTimeout instead') + } + + if (maxKeepAliveTimeout !== undefined) { + throw new InvalidArgumentError('unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead') + } + + if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) { + throw new InvalidArgumentError('invalid maxHeaderSize') + } + + if (socketPath != null && typeof socketPath !== 'string') { + throw new InvalidArgumentError('invalid socketPath') + } + + if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { + throw new InvalidArgumentError('invalid connectTimeout') + } + + if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveTimeout') + } + + if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveMaxTimeout') + } + + if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { + throw new InvalidArgumentError('invalid keepAliveTimeoutThreshold') + } + + if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('headersTimeout must be a positive integer or zero') + } + + if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('bodyTimeout must be a positive integer or zero') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { + throw new InvalidArgumentError('maxRequestsPerClient must be a positive number') + } + + if (localAddress != null && (typeof localAddress !== 'string' || net.isIP(localAddress) === 0)) { + throw new InvalidArgumentError('localAddress must be valid string IP address') + } + + if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { + throw new InvalidArgumentError('maxResponseSize must be a positive number') + } + + if ( + autoSelectFamilyAttemptTimeout != null && + (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1) + ) { + throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number') + } + + // h2 + if (allowH2 != null && typeof allowH2 !== 'boolean') { + throw new InvalidArgumentError('allowH2 must be a valid boolean value') + } + + if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) { + throw new InvalidArgumentError('maxConcurrentStreams must be a possitive integer, greater than 0') + } + + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } + + this[kInterceptors] = interceptors && interceptors.Client && Array.isArray(interceptors.Client) + ? interceptors.Client + : [createRedirectInterceptor({ maxRedirections })] + this[kUrl] = util.parseOrigin(url) + this[kConnector] = connect + this[kSocket] = null + this[kPipelining] = pipelining != null ? pipelining : 1 + this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize + this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout + this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold + this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout] + this[kServerName] = null + this[kLocalAddress] = localAddress != null ? localAddress : null + this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n` + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3 + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3 + this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength + this[kMaxRedirections] = maxRedirections + this[kMaxRequests] = maxRequestsPerClient + this[kClosedResolve] = null + this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1 + this[kHTTPConnVersion] = 'h1' + + // HTTP/2 + this[kHTTP2Session] = null + this[kHTTP2SessionState] = !allowH2 + ? null + : { + // streams: null, // Fixed queue of streams - For future support of `push` + openStreams: 0, // Keep track of them to decide wether or not unref the session + maxConcurrentStreams: maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server + } + this[kHost] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}` + + // kQueue is built up of 3 sections separated by + // the kRunningIdx and kPendingIdx indices. + // | complete | running | pending | + // ^ kRunningIdx ^ kPendingIdx ^ kQueue.length + // kRunningIdx points to the first running element. + // kPendingIdx points to the first pending element. + // This implements a fast queue with an amortized + // time of O(1). + + this[kQueue] = [] + this[kRunningIdx] = 0 + this[kPendingIdx] = 0 + } + + get pipelining () { + return this[kPipelining] + } + + set pipelining (value) { + this[kPipelining] = value + resume(this, true) + } + + get [kPending] () { + return this[kQueue].length - this[kPendingIdx] + } + + get [kRunning] () { + return this[kPendingIdx] - this[kRunningIdx] + } + + get [kSize] () { + return this[kQueue].length - this[kRunningIdx] + } + + get [kConnected] () { + return !!this[kSocket] && !this[kConnecting] && !this[kSocket].destroyed + } + + get [kBusy] () { + const socket = this[kSocket] + return ( + (socket && (socket[kReset] || socket[kWriting] || socket[kBlocking])) || + (this[kSize] >= (this[kPipelining] || 1)) || + this[kPending] > 0 + ) + } + + /* istanbul ignore: only used for test */ + [kConnect] (cb) { + connect(this) + this.once('connect', cb) + } + + [kDispatch] (opts, handler) { + const origin = opts.origin || this[kUrl].origin + + const request = this[kHTTPConnVersion] === 'h2' + ? Request[kHTTP2BuildRequest](origin, opts, handler) + : Request[kHTTP1BuildRequest](origin, opts, handler) + + this[kQueue].push(request) + if (this[kResuming]) { + // Do nothing. + } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { + // Wait a tick in case stream/iterator is ended in the same tick. + this[kResuming] = 1 + process.nextTick(resume, this) + } else { + resume(this, true) + } + + if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { + this[kNeedDrain] = 2 + } + + return this[kNeedDrain] < 2 + } + + async [kClose] () { + // TODO: for H2 we need to gracefully flush the remaining enqueued + // request and close each stream. + return new Promise((resolve) => { + if (!this[kSize]) { + resolve(null) + } else { + this[kClosedResolve] = resolve + } + }) + } + + async [kDestroy] (err) { + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(this, request, err) + } + + const callback = () => { + if (this[kClosedResolve]) { + // TODO (fix): Should we error here with ClientDestroyedError? + this[kClosedResolve]() + this[kClosedResolve] = null + } + resolve() + } + + if (this[kHTTP2Session] != null) { + util.destroy(this[kHTTP2Session], err) + this[kHTTP2Session] = null + this[kHTTP2SessionState] = null + } + + if (!this[kSocket]) { + queueMicrotask(callback) + } else { + util.destroy(this[kSocket].on('close', callback), err) + } + + resume(this) + }) + } +} + +function onHttp2SessionError (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') + + this[kSocket][kError] = err + + onError(this[kClient], err) +} + +function onHttp2FrameError (type, code, id) { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + + if (id === 0) { + this[kSocket][kError] = err + onError(this[kClient], err) + } +} + +function onHttp2SessionEnd () { + util.destroy(this, new SocketError('other side closed')) + util.destroy(this[kSocket], new SocketError('other side closed')) +} + +function onHTTP2GoAway (code) { + const client = this[kClient] + const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`) + client[kSocket] = null + client[kHTTP2Session] = null + + if (client.destroyed) { + assert(this[kPending] === 0) + + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(this, request, err) + } + } else if (client[kRunning] > 0) { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + + errorRequest(client, request, err) + } + + client[kPendingIdx] = client[kRunningIdx] + + assert(client[kRunning] === 0) + + client.emit('disconnect', + client[kUrl], + [client], + err + ) + + resume(client) +} + +const constants = __nccwpck_require__(52824) +const createRedirectInterceptor = __nccwpck_require__(64415) +const EMPTY_BUF = Buffer.alloc(0) + +async function lazyllhttp () { + const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(63870) : undefined + + let mod + try { + mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(53434), 'base64')) + } catch (e) { + /* istanbul ignore next */ + + // We could check if the error was caused by the simd option not + // being enabled, but the occurring of this other error + // * https://github.com/emscripten-core/emscripten/issues/11495 + // got me to remove that check to avoid breaking Node 12. + mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(63870), 'base64')) + } + + return await WebAssembly.instantiate(mod, { + env: { + /* eslint-disable camelcase */ + + wasm_on_url: (p, at, len) => { + /* istanbul ignore next */ + return 0 + }, + wasm_on_status: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_begin: (p) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onMessageBegin() || 0 + }, + wasm_on_header_field: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_header_value: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0 + }, + wasm_on_body: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_complete: (p) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onMessageComplete() || 0 + } + + /* eslint-enable camelcase */ + } + }) +} + +let llhttpInstance = null +let llhttpPromise = lazyllhttp() +llhttpPromise.catch() + +let currentParser = null +let currentBufferRef = null +let currentBufferSize = 0 +let currentBufferPtr = null + +const TIMEOUT_HEADERS = 1 +const TIMEOUT_BODY = 2 +const TIMEOUT_IDLE = 3 + +class Parser { + constructor (client, socket, { exports }) { + assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0) + + this.llhttp = exports + this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) + this.client = client + this.socket = socket + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + this.statusCode = null + this.statusText = '' + this.upgrade = false + this.headers = [] + this.headersSize = 0 + this.headersMaxSize = client[kMaxHeadersSize] + this.shouldKeepAlive = false + this.paused = false + this.resume = this.resume.bind(this) + + this.bytesRead = 0 + + this.keepAlive = '' + this.contentLength = '' + this.connection = '' + this.maxResponseSize = client[kMaxResponseSize] + } + + setTimeout (value, type) { + this.timeoutType = type + if (value !== this.timeoutValue) { + timers.clearTimeout(this.timeout) + if (value) { + this.timeout = timers.setTimeout(onParserTimeout, value, this) + // istanbul ignore else: only for jest + if (this.timeout.unref) { + this.timeout.unref() + } + } else { + this.timeout = null + } + this.timeoutValue = value + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + } + + resume () { + if (this.socket.destroyed || !this.paused) { + return + } + + assert(this.ptr != null) + assert(currentParser == null) + + this.llhttp.llhttp_resume(this.ptr) + + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + this.paused = false + this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. + this.readMore() + } + + readMore () { + while (!this.paused && this.ptr) { + const chunk = this.socket.read() + if (chunk === null) { + break + } + this.execute(chunk) + } + } + + execute (data) { + assert(this.ptr != null) + assert(currentParser == null) + assert(!this.paused) + + const { socket, llhttp } = this + + if (data.length > currentBufferSize) { + if (currentBufferPtr) { + llhttp.free(currentBufferPtr) + } + currentBufferSize = Math.ceil(data.length / 4096) * 4096 + currentBufferPtr = llhttp.malloc(currentBufferSize) + } + + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data) + + // Call `execute` on the wasm parser. + // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data, + // and finally the length of bytes to parse. + // The return value is an error code or `constants.ERROR.OK`. + try { + let ret + + try { + currentBufferRef = data + currentParser = this + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length) + /* eslint-disable-next-line no-useless-catch */ + } catch (err) { + /* istanbul ignore next: difficult to make a test case for */ + throw err + } finally { + currentParser = null + currentBufferRef = null + } + + const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr + + if (ret === constants.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(data.slice(offset)) + } else if (ret === constants.ERROR.PAUSED) { + this.paused = true + socket.unshift(data.slice(offset)) + } else if (ret !== constants.ERROR.OK) { + const ptr = llhttp.llhttp_get_error_reason(this.ptr) + let message = '' + /* istanbul ignore else: difficult to make a test case for */ + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) + message = + 'Response does not match the HTTP/1.1 protocol (' + + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + + ')' + } + throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)) + } + } catch (err) { + util.destroy(socket, err) + } + } + + destroy () { + assert(this.ptr != null) + assert(currentParser == null) + + this.llhttp.llhttp_free(this.ptr) + this.ptr = null + + timers.clearTimeout(this.timeout) + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + + this.paused = false + } + + onStatus (buf) { + this.statusText = buf.toString() + } + + onMessageBegin () { + const { socket, client } = this + + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + if (!request) { + return -1 + } + } + + onHeaderField (buf) { + const len = this.headers.length + + if ((len & 1) === 0) { + this.headers.push(buf) + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + } + + this.trackHeader(buf.length) + } + + onHeaderValue (buf) { + let len = this.headers.length + + if ((len & 1) === 1) { + this.headers.push(buf) + len += 1 + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + } + + const key = this.headers[len - 2] + if (key.length === 10 && key.toString().toLowerCase() === 'keep-alive') { + this.keepAlive += buf.toString() + } else if (key.length === 10 && key.toString().toLowerCase() === 'connection') { + this.connection += buf.toString() + } else if (key.length === 14 && key.toString().toLowerCase() === 'content-length') { + this.contentLength += buf.toString() + } + + this.trackHeader(buf.length) + } + + trackHeader (len) { + this.headersSize += len + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + } + } + + onUpgrade (head) { + const { upgrade, client, socket, headers, statusCode } = this + + assert(upgrade) + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert(!socket.destroyed) + assert(socket === client[kSocket]) + assert(!this.paused) + assert(request.upgrade || request.method === 'CONNECT') + + this.statusCode = null + this.statusText = '' + this.shouldKeepAlive = null + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + socket.unshift(head) + + socket[kParser].destroy() + socket[kParser] = null + + socket[kClient] = null + socket[kError] = null + socket + .removeListener('error', onSocketError) + .removeListener('readable', onSocketReadable) + .removeListener('end', onSocketEnd) + .removeListener('close', onSocketClose) + + client[kSocket] = null + client[kQueue][client[kRunningIdx]++] = null + client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) + + try { + request.onUpgrade(statusCode, headers, socket) + } catch (err) { + util.destroy(socket, err) + } + + resume(client) + } + + onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { + const { client, socket, headers, statusText } = this + + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + + /* istanbul ignore next: difficult to make a test case for */ + if (!request) { + return -1 + } + + assert(!this.upgrade) + assert(this.statusCode < 200) + + if (statusCode === 100) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return -1 + } + + /* this can only happen if server is misbehaving */ + if (upgrade && !request.upgrade) { + util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) + return -1 + } + + assert.strictEqual(this.timeoutType, TIMEOUT_HEADERS) + + this.statusCode = statusCode + this.shouldKeepAlive = ( + shouldKeepAlive || + // Override llhttp value which does not allow keepAlive for HEAD. + (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive') + ) + + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null + ? request.bodyTimeout + : client[kBodyTimeout] + this.setTimeout(bodyTimeout, TIMEOUT_BODY) + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + if (request.method === 'CONNECT') { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } + + if (upgrade) { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null + + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ) + if (timeout <= 0) { + socket[kReset] = true + } else { + client[kKeepAliveTimeoutValue] = timeout + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] + } + } else { + // Stop more requests from being dispatched. + socket[kReset] = true + } + + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false + + if (request.aborted) { + return -1 + } + + if (request.method === 'HEAD') { + return 1 + } + + if (statusCode < 200) { + return 1 + } + + if (socket[kBlocking]) { + socket[kBlocking] = false + resume(client) + } + + return pause ? constants.ERROR.PAUSED : 0 + } + + onBody (buf) { + const { client, socket, statusCode, maxResponseSize } = this + + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert.strictEqual(this.timeoutType, TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + assert(statusCode >= 200) + + if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { + util.destroy(socket, new ResponseExceededMaxSizeError()) + return -1 + } + + this.bytesRead += buf.length + + if (request.onData(buf) === false) { + return constants.ERROR.PAUSED + } + } + + onMessageComplete () { + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this + + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return -1 + } + + if (upgrade) { + return + } + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert(statusCode >= 100) + + this.statusCode = null + this.statusText = '' + this.bytesRead = 0 + this.contentLength = '' + this.keepAlive = '' + this.connection = '' + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + if (statusCode < 200) { + return + } + + /* istanbul ignore next: should be handled by llhttp? */ + if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { + util.destroy(socket, new ResponseContentLengthMismatchError()) + return -1 + } + + request.onComplete(headers) + + client[kQueue][client[kRunningIdx]++] = null + + if (socket[kWriting]) { + assert.strictEqual(client[kRunning], 0) + // Response completed before request. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (!shouldKeepAlive) { + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (socket[kReset] && client[kRunning] === 0) { + // Destroy socket once all requests have completed. + // The request at the tail of the pipeline is the one + // that requested reset and no further requests should + // have been queued since then. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (client[kPipelining] === 1) { + // We must wait a full event loop cycle to reuse this socket to make sure + // that non-spec compliant servers are not closing the connection even if they + // said they won't. + setImmediate(resume, client) + } else { + resume(client) + } + } +} + +function onParserTimeout (parser) { + const { socket, timeoutType, client } = parser + + /* istanbul ignore else */ + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert(!parser.paused, 'cannot be paused while waiting for headers') + util.destroy(socket, new HeadersTimeoutError()) + } + } else if (timeoutType === TIMEOUT_BODY) { + if (!parser.paused) { + util.destroy(socket, new BodyTimeoutError()) + } + } else if (timeoutType === TIMEOUT_IDLE) { + assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) + util.destroy(socket, new InformationalError('socket idle timeout')) + } +} + +function onSocketReadable () { + const { [kParser]: parser } = this + if (parser) { + parser.readMore() + } +} + +function onSocketError (err) { + const { [kClient]: client, [kParser]: parser } = this + + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') + + if (client[kHTTPConnVersion] !== 'h2') { + // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded + // to the user. + if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so for as a valid response. + parser.onMessageComplete() + return + } + } + + this[kError] = err + + onError(this[kClient], err) +} + +function onError (client, err) { + if ( + client[kRunning] === 0 && + err.code !== 'UND_ERR_INFO' && + err.code !== 'UND_ERR_SOCKET' + ) { + // Error is not caused by running request and not a recoverable + // socket error. + + assert(client[kPendingIdx] === client[kRunningIdx]) + + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(client, request, err) + } + assert(client[kSize] === 0) + } +} + +function onSocketEnd () { + const { [kParser]: parser, [kClient]: client } = this + + if (client[kHTTPConnVersion] !== 'h2') { + if (parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + return + } + } + + util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) +} + +function onSocketClose () { + const { [kClient]: client, [kParser]: parser } = this + + if (client[kHTTPConnVersion] === 'h1' && parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + } + + this[kParser].destroy() + this[kParser] = null + } + + const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) + + client[kSocket] = null + + if (client.destroyed) { + assert(client[kPending] === 0) + + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(client, request, err) + } + } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + + errorRequest(client, request, err) + } + + client[kPendingIdx] = client[kRunningIdx] + + assert(client[kRunning] === 0) + + client.emit('disconnect', client[kUrl], [client], err) + + resume(client) +} + +async function connect (client) { + assert(!client[kConnecting]) + assert(!client[kSocket]) + + let { host, hostname, protocol, port } = client[kUrl] + + // Resolve ipv6 + if (hostname[0] === '[') { + const idx = hostname.indexOf(']') + + assert(idx !== -1) + const ip = hostname.substring(1, idx) + + assert(net.isIP(ip)) + hostname = ip + } + + client[kConnecting] = true + + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }) + } + + try { + const socket = await new Promise((resolve, reject) => { + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket) => { + if (err) { + reject(err) + } else { + resolve(socket) + } + }) + }) + + if (client.destroyed) { + util.destroy(socket.on('error', () => {}), new ClientDestroyedError()) + return + } + + client[kConnecting] = false + + assert(socket) + + const isH2 = socket.alpnProtocol === 'h2' + if (isH2) { + if (!h2ExperimentalWarned) { + h2ExperimentalWarned = true + process.emitWarning('H2 support is experimental, expect them to change at any time.', { + code: 'UNDICI-H2' + }) + } + + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kHTTP2SessionState].maxConcurrentStreams + }) + + client[kHTTPConnVersion] = 'h2' + session[kClient] = client + session[kSocket] = socket + session.on('error', onHttp2SessionError) + session.on('frameError', onHttp2FrameError) + session.on('end', onHttp2SessionEnd) + session.on('goaway', onHTTP2GoAway) + session.on('close', onSocketClose) + session.unref() + + client[kHTTP2Session] = session + socket[kHTTP2Session] = session + } else { + if (!llhttpInstance) { + llhttpInstance = await llhttpPromise + llhttpPromise = null + } + + socket[kNoRef] = false + socket[kWriting] = false + socket[kReset] = false + socket[kBlocking] = false + socket[kParser] = new Parser(client, socket, llhttpInstance) + } + + socket[kCounter] = 0 + socket[kMaxRequests] = client[kMaxRequests] + socket[kClient] = client + socket[kError] = null + + socket + .on('error', onSocketError) + .on('readable', onSocketReadable) + .on('end', onSocketEnd) + .on('close', onSocketClose) + + client[kSocket] = socket + + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }) + } + client.emit('connect', client[kUrl], [client]) + } catch (err) { + if (client.destroyed) { + return + } + + client[kConnecting] = false + + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }) + } + + if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { + assert(client[kRunning] === 0) + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue][client[kPendingIdx]++] + errorRequest(client, request, err) + } + } else { + onError(client, err) + } + + client.emit('connectionError', client[kUrl], [client], err) + } + + resume(client) +} + +function emitDrain (client) { + client[kNeedDrain] = 0 + client.emit('drain', client[kUrl], [client]) +} + +function resume (client, sync) { + if (client[kResuming] === 2) { + return + } + + client[kResuming] = 2 + + _resume(client, sync) + client[kResuming] = 0 + + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]) + client[kPendingIdx] -= client[kRunningIdx] + client[kRunningIdx] = 0 + } +} + +function _resume (client, sync) { + while (true) { + if (client.destroyed) { + assert(client[kPending] === 0) + return + } + + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve]() + client[kClosedResolve] = null + return + } + + const socket = client[kSocket] + + if (socket && !socket.destroyed && socket.alpnProtocol !== 'h2') { + if (client[kSize] === 0) { + if (!socket[kNoRef] && socket.unref) { + socket.unref() + socket[kNoRef] = true + } + } else if (socket[kNoRef] && socket.ref) { + socket.ref() + socket[kNoRef] = false + } + + if (client[kSize] === 0) { + if (socket[kParser].timeoutType !== TIMEOUT_IDLE) { + socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE) + } + } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { + if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { + const request = client[kQueue][client[kRunningIdx]] + const headersTimeout = request.headersTimeout != null + ? request.headersTimeout + : client[kHeadersTimeout] + socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) + } + } + } + + if (client[kBusy]) { + client[kNeedDrain] = 2 + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1 + process.nextTick(emitDrain, client) + } else { + emitDrain(client) + } + continue + } + + if (client[kPending] === 0) { + return + } + + if (client[kRunning] >= (client[kPipelining] || 1)) { + return + } + + const request = client[kQueue][client[kPendingIdx]] + + if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { + return + } + + client[kServerName] = request.servername + + if (socket && socket.servername !== request.servername) { + util.destroy(socket, new InformationalError('servername changed')) + return + } + } + + if (client[kConnecting]) { + return + } + + if (!socket && !client[kHTTP2Session]) { + connect(client) + return + } + + if (socket.destroyed || socket[kWriting] || socket[kReset] || socket[kBlocking]) { + return + } + + if (client[kRunning] > 0 && !request.idempotent) { + // Non-idempotent request cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return + } + + if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { + // Don't dispatch an upgrade until all preceding requests have completed. + // A misbehaving server might upgrade the connection before all pipelined + // request has completed. + return + } + + if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && + (util.isStream(request.body) || util.isAsyncIterable(request.body))) { + // Request with stream or iterator body can error while other requests + // are inflight and indirectly error those as well. + // Ensure this doesn't happen by waiting for inflight + // to complete before dispatching. + + // Request with stream or iterator body cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return + } + + if (!request.aborted && write(client, request)) { + client[kPendingIdx]++ + } else { + client[kQueue].splice(client[kPendingIdx], 1) + } + } +} + +// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 +function shouldSendContentLength (method) { + return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' +} + +function write (client, request) { + if (client[kHTTPConnVersion] === 'h2') { + writeH2(client, client[kHTTP2Session], request) + return + } + + const { body, method, path, host, upgrade, headers, blocking, reset } = request + + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 + + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. + + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) + + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } + + const bodyLength = util.bodyLength(body) + + let contentLength = bodyLength + + if (contentLength === null) { + contentLength = request.contentLength + } + + if (contentLength === 0 && !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + + contentLength = null + } + + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()) + return false + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + const socket = client[kSocket] + + try { + request.onConnect((err) => { + if (request.aborted || request.completed) { + return + } + + errorRequest(client, request, err || new RequestAbortedError()) + + util.destroy(socket, new InformationalError('aborted')) + }) + } catch (err) { + errorRequest(client, request, err) + } + + if (request.aborted) { + return false + } + + if (method === 'HEAD') { + // https://github.com/mcollina/undici/issues/258 + // Close after a HEAD request to interop with misbehaving servers + // that may send a body in the response. + + socket[kReset] = true + } + + if (upgrade || method === 'CONNECT') { + // On CONNECT or upgrade, block pipeline from dispatching further + // requests on this connection. + + socket[kReset] = true + } + + if (reset != null) { + socket[kReset] = reset + } + + if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { + socket[kReset] = true + } + + if (blocking) { + socket[kBlocking] = true + } + + let header = `${method} ${path} HTTP/1.1\r\n` + + if (typeof host === 'string') { + header += `host: ${host}\r\n` + } else { + header += client[kHostHeader] + } + + if (upgrade) { + header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n` + } else if (client[kPipelining] && !socket[kReset]) { + header += 'connection: keep-alive\r\n' + } else { + header += 'connection: close\r\n' + } + + if (headers) { + header += headers + } + + if (channels.sendHeaders.hasSubscribers) { + channels.sendHeaders.publish({ request, headers: header, socket }) + } + + /* istanbul ignore else: assertion */ + if (!body || bodyLength === 0) { + if (contentLength === 0) { + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + assert(contentLength === null, 'no body must not have content length') + socket.write(`${header}\r\n`, 'latin1') + } + request.onRequestSent() + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(body) + socket.uncork() + request.onBodySent(body) + request.onRequestSent() + if (!expectsPayload) { + socket[kReset] = true + } + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable({ body: body.stream(), client, request, socket, contentLength, header, expectsPayload }) + } else { + writeBlob({ body, client, request, socket, contentLength, header, expectsPayload }) + } + } else if (util.isStream(body)) { + writeStream({ body, client, request, socket, contentLength, header, expectsPayload }) + } else if (util.isIterable(body)) { + writeIterable({ body, client, request, socket, contentLength, header, expectsPayload }) + } else { + assert(false) + } + + return true +} + +function writeH2 (client, session, request) { + const { body, method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request + + let headers + if (typeof reqHeaders === 'string') headers = Request[kHTTP2CopyHeaders](reqHeaders.trim()) + else headers = reqHeaders + + if (upgrade) { + errorRequest(client, request, new Error('Upgrade not supported for H2')) + return false + } + + try { + // TODO(HTTP/2): Should we call onConnect immediately or on stream ready event? + request.onConnect((err) => { + if (request.aborted || request.completed) { + return + } + + errorRequest(client, request, err || new RequestAbortedError()) + }) + } catch (err) { + errorRequest(client, request, err) + } + + if (request.aborted) { + return false + } + + /** @type {import('node:http2').ClientHttp2Stream} */ + let stream + const h2State = client[kHTTP2SessionState] + + headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost] + headers[HTTP2_HEADER_METHOD] = method + + if (method === 'CONNECT') { + session.ref() + // we are already connected, streams are pending, first request + // will create a new stream. We trigger a request to create the stream and wait until + // `ready` event is triggered + // We disabled endStream to allow the user to write to the stream + stream = session.request(headers, { endStream: false, signal }) + + if (stream.id && !stream.pending) { + request.onUpgrade(null, null, stream) + ++h2State.openStreams + } else { + stream.once('ready', () => { + request.onUpgrade(null, null, stream) + ++h2State.openStreams + }) + } + + stream.once('close', () => { + h2State.openStreams -= 1 + // TODO(HTTP/2): unref only if current streams count is 0 + if (h2State.openStreams === 0) session.unref() + }) + + return true + } + + // https://tools.ietf.org/html/rfc7540#section-8.3 + // :path and :scheme headers must be omited when sending CONNECT + + headers[HTTP2_HEADER_PATH] = path + headers[HTTP2_HEADER_SCHEME] = 'https' + + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 + + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. + + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) + + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } + + let contentLength = util.bodyLength(body) + + if (contentLength == null) { + contentLength = request.contentLength + } + + if (contentLength === 0 || !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + + contentLength = null + } + + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()) + return false + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + if (contentLength != null) { + assert(body, 'no body must not have content length') + headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}` + } + + session.ref() + + const shouldEndStream = method === 'GET' || method === 'HEAD' + if (expectContinue) { + headers[HTTP2_HEADER_EXPECT] = '100-continue' + stream = session.request(headers, { endStream: shouldEndStream, signal }) + + stream.once('continue', writeBodyH2) + } else { + stream = session.request(headers, { + endStream: shouldEndStream, + signal + }) + writeBodyH2() + } + + // Increment counter as we have new several streams open + ++h2State.openStreams + + stream.once('response', headers => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers + + if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), '') === false) { + stream.pause() + } + }) + + stream.once('end', () => { + request.onComplete([]) + }) + + stream.on('data', (chunk) => { + if (request.onData(chunk) === false) { + stream.pause() + } + }) + + stream.once('close', () => { + h2State.openStreams -= 1 + // TODO(HTTP/2): unref only if current streams count is 0 + if (h2State.openStreams === 0) { + session.unref() + } + }) + + stream.once('error', function (err) { + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1 + util.destroy(stream, err) + } + }) + + stream.once('frameError', (type, code) => { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + errorRequest(client, request, err) + + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1 + util.destroy(stream, err) + } + }) + + // stream.on('aborted', () => { + // // TODO(HTTP/2): Support aborted + // }) + + // stream.on('timeout', () => { + // // TODO(HTTP/2): Support timeout + // }) + + // stream.on('push', headers => { + // // TODO(HTTP/2): Suppor push + // }) + + // stream.on('trailers', headers => { + // // TODO(HTTP/2): Support trailers + // }) + + return true + + function writeBodyH2 () { + /* istanbul ignore else: assertion */ + if (!body) { + request.onRequestSent() + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + stream.cork() + stream.write(body) + stream.uncork() + stream.end() + request.onBodySent(body) + request.onRequestSent() + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable({ + client, + request, + contentLength, + h2stream: stream, + expectsPayload, + body: body.stream(), + socket: client[kSocket], + header: '' + }) + } else { + writeBlob({ + body, + client, + request, + contentLength, + expectsPayload, + h2stream: stream, + header: '', + socket: client[kSocket] + }) + } + } else if (util.isStream(body)) { + writeStream({ + body, + client, + request, + contentLength, + expectsPayload, + socket: client[kSocket], + h2stream: stream, + header: '' + }) + } else if (util.isIterable(body)) { + writeIterable({ + body, + client, + request, + contentLength, + expectsPayload, + header: '', + h2stream: stream, + socket: client[kSocket] + }) + } else { + assert(false) + } + } +} + +function writeStream ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') + + if (client[kHTTPConnVersion] === 'h2') { + // For HTTP/2, is enough to pipe the stream + const pipe = pipeline( + body, + h2stream, + (err) => { + if (err) { + util.destroy(body, err) + util.destroy(h2stream, err) + } else { + request.onRequestSent() + } + } + ) + + pipe.on('data', onPipeData) + pipe.once('end', () => { + pipe.removeListener('data', onPipeData) + util.destroy(pipe) + }) + + function onPipeData (chunk) { + request.onBodySent(chunk) + } + + return + } + + let finished = false + + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) + + const onData = function (chunk) { + if (finished) { + return + } + + try { + if (!writer.write(chunk) && this.pause) { + this.pause() + } + } catch (err) { + util.destroy(this, err) + } + } + const onDrain = function () { + if (finished) { + return + } + + if (body.resume) { + body.resume() + } + } + const onAbort = function () { + if (finished) { + return + } + const err = new RequestAbortedError() + queueMicrotask(() => onFinished(err)) + } + const onFinished = function (err) { + if (finished) { + return + } + + finished = true + + assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) + + socket + .off('drain', onDrain) + .off('error', onFinished) + + body + .removeListener('data', onData) + .removeListener('end', onFinished) + .removeListener('error', onFinished) + .removeListener('close', onAbort) + + if (!err) { + try { + writer.end() + } catch (er) { + err = er + } + } + + writer.destroy(err) + + if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) { + util.destroy(body, err) + } else { + util.destroy(body) + } + } + + body + .on('data', onData) + .on('end', onFinished) + .on('error', onFinished) + .on('close', onAbort) + + if (body.resume) { + body.resume() + } + + socket + .on('drain', onDrain) + .on('error', onFinished) +} + +async function writeBlob ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength === body.size, 'blob body must have content length') + + const isH2 = client[kHTTPConnVersion] === 'h2' + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError() + } + + const buffer = Buffer.from(await body.arrayBuffer()) + + if (isH2) { + h2stream.cork() + h2stream.write(buffer) + h2stream.uncork() + } else { + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(buffer) + socket.uncork() + } + + request.onBodySent(buffer) + request.onRequestSent() + + if (!expectsPayload) { + socket[kReset] = true + } + + resume(client) + } catch (err) { + util.destroy(isH2 ? h2stream : socket, err) + } +} + +async function writeIterable ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') + + let callback = null + function onDrain () { + if (callback) { + const cb = callback + callback = null + cb() + } + } + + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null) + + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve + } + }) + + if (client[kHTTPConnVersion] === 'h2') { + h2stream + .on('close', onDrain) + .on('drain', onDrain) + + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } + + const res = h2stream.write(chunk) + request.onBodySent(chunk) + if (!res) { + await waitForDrain() + } + } + } catch (err) { + h2stream.destroy(err) + } finally { + request.onRequestSent() + h2stream.end() + h2stream + .off('close', onDrain) + .off('drain', onDrain) + } + + return + } + + socket + .on('close', onDrain) + .on('drain', onDrain) + + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } + + if (!writer.write(chunk)) { + await waitForDrain() + } + } + + writer.end() + } catch (err) { + writer.destroy(err) + } finally { + socket + .off('close', onDrain) + .off('drain', onDrain) + } +} + +class AsyncWriter { + constructor ({ socket, request, contentLength, client, expectsPayload, header }) { + this.socket = socket + this.request = request + this.contentLength = contentLength + this.client = client + this.bytesWritten = 0 + this.expectsPayload = expectsPayload + this.header = header + + socket[kWriting] = true + } + + write (chunk) { + const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this + + if (socket[kError]) { + throw socket[kError] + } + + if (socket.destroyed) { + return false + } + + const len = Buffer.byteLength(chunk) + if (!len) { + return true + } + + // We should defer writing chunks. + if (contentLength !== null && bytesWritten + len > contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + socket.cork() + + if (bytesWritten === 0) { + if (!expectsPayload) { + socket[kReset] = true + } + + if (contentLength === null) { + socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') + } else { + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + } + } + + if (contentLength === null) { + socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') + } + + this.bytesWritten += len + + const ret = socket.write(chunk) + + socket.uncork() + + request.onBodySent(chunk) + + if (!ret) { + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } + } + + return ret + } + + end () { + const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this + request.onRequestSent() + + socket[kWriting] = false + + if (socket[kError]) { + throw socket[kError] + } + + if (socket.destroyed) { + return + } + + if (bytesWritten === 0) { + if (expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. + + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + socket.write(`${header}\r\n`, 'latin1') + } + } else if (contentLength === null) { + socket.write('\r\n0\r\n\r\n', 'latin1') + } + + if (contentLength !== null && bytesWritten !== contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } else { + process.emitWarning(new RequestContentLengthMismatchError()) + } + } + + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } + + resume(client) + } + + destroy (err) { + const { socket, client } = this + + socket[kWriting] = false + + if (err) { + assert(client[kRunning] <= 1, 'pipeline should only contain this request') + util.destroy(socket, err) + } + } +} + +function errorRequest (client, request, err) { + try { + request.onError(err) + assert(request.aborted) + } catch (err) { + client.emit('error', err) + } +} + +module.exports = Client + + +/***/ }), + +/***/ 13194: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +/* istanbul ignore file: only for Node 12 */ + +const { kConnected, kSize } = __nccwpck_require__(36443) + +class CompatWeakRef { + constructor (value) { + this.value = value + } + + deref () { + return this.value[kConnected] === 0 && this.value[kSize] === 0 + ? undefined + : this.value + } +} + +class CompatFinalizer { + constructor (finalizer) { + this.finalizer = finalizer + } + + register (dispatcher, key) { + if (dispatcher.on) { + dispatcher.on('disconnect', () => { + if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) { + this.finalizer(key) + } + }) + } + } +} + +module.exports = function () { + // FIXME: remove workaround when the Node bug is fixed + // https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 + if (process.env.NODE_V8_COVERAGE) { + return { + WeakRef: CompatWeakRef, + FinalizationRegistry: CompatFinalizer + } + } + return { + WeakRef: global.WeakRef || CompatWeakRef, + FinalizationRegistry: global.FinalizationRegistry || CompatFinalizer + } +} + + +/***/ }), + +/***/ 19237: +/***/ ((module) => { + +"use strict"; + + +// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size +const maxAttributeValueSize = 1024 + +// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size +const maxNameValuePairSize = 4096 + +module.exports = { + maxAttributeValueSize, + maxNameValuePairSize +} + + +/***/ }), + +/***/ 53168: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { parseSetCookie } = __nccwpck_require__(8915) +const { stringify } = __nccwpck_require__(3834) +const { webidl } = __nccwpck_require__(74222) +const { Headers } = __nccwpck_require__(26349) + +/** + * @typedef {Object} Cookie + * @property {string} name + * @property {string} value + * @property {Date|number|undefined} expires + * @property {number|undefined} maxAge + * @property {string|undefined} domain + * @property {string|undefined} path + * @property {boolean|undefined} secure + * @property {boolean|undefined} httpOnly + * @property {'Strict'|'Lax'|'None'} sameSite + * @property {string[]} unparsed + */ + +/** + * @param {Headers} headers + * @returns {Record} + */ +function getCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + const cookie = headers.get('cookie') + const out = {} + + if (!cookie) { + return out + } + + for (const piece of cookie.split(';')) { + const [name, ...value] = piece.split('=') + + out[name.trim()] = value.join('=') + } + + return out +} + +/** + * @param {Headers} headers + * @param {string} name + * @param {{ path?: string, domain?: string }|undefined} attributes + * @returns {void} + */ +function deleteCookie (headers, name, attributes) { + webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + name = webidl.converters.DOMString(name) + attributes = webidl.converters.DeleteCookieAttributes(attributes) + + // Matches behavior of + // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278 + setCookie(headers, { + name, + value: '', + expires: new Date(0), + ...attributes + }) +} + +/** + * @param {Headers} headers + * @returns {Cookie[]} + */ +function getSetCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + const cookies = headers.getSetCookie() + + if (!cookies) { + return [] + } + + return cookies.map((pair) => parseSetCookie(pair)) +} + +/** + * @param {Headers} headers + * @param {Cookie} cookie + * @returns {void} + */ +function setCookie (headers, cookie) { + webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + cookie = webidl.converters.Cookie(cookie) + + const str = stringify(cookie) + + if (str) { + headers.append('Set-Cookie', stringify(cookie)) + } +} + +webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: null + } +]) + +webidl.converters.Cookie = webidl.dictionaryConverter([ + { + converter: webidl.converters.DOMString, + key: 'name' + }, + { + converter: webidl.converters.DOMString, + key: 'value' + }, + { + converter: webidl.nullableConverter((value) => { + if (typeof value === 'number') { + return webidl.converters['unsigned long long'](value) + } + + return new Date(value) + }), + key: 'expires', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters['long long']), + key: 'maxAge', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'secure', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'httpOnly', + defaultValue: null + }, + { + converter: webidl.converters.USVString, + key: 'sameSite', + allowedValues: ['Strict', 'Lax', 'None'] + }, + { + converter: webidl.sequenceConverter(webidl.converters.DOMString), + key: 'unparsed', + defaultValue: [] + } +]) + +module.exports = { + getCookies, + deleteCookie, + getSetCookies, + setCookie +} + + +/***/ }), + +/***/ 8915: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(19237) +const { isCTLExcludingHtab } = __nccwpck_require__(3834) +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(94322) +const assert = __nccwpck_require__(42613) + +/** + * @description Parses the field-value attributes of a set-cookie header string. + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} header + * @returns if the header is invalid, null will be returned + */ +function parseSetCookie (header) { + // 1. If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F + // character (CTL characters excluding HTAB): Abort these steps and + // ignore the set-cookie-string entirely. + if (isCTLExcludingHtab(header)) { + return null + } + + let nameValuePair = '' + let unparsedAttributes = '' + let name = '' + let value = '' + + // 2. If the set-cookie-string contains a %x3B (";") character: + if (header.includes(';')) { + // 1. The name-value-pair string consists of the characters up to, + // but not including, the first %x3B (";"), and the unparsed- + // attributes consist of the remainder of the set-cookie-string + // (including the %x3B (";") in question). + const position = { position: 0 } + + nameValuePair = collectASequenceOfCodePointsFast(';', header, position) + unparsedAttributes = header.slice(position.position) + } else { + // Otherwise: + + // 1. The name-value-pair string consists of all the characters + // contained in the set-cookie-string, and the unparsed- + // attributes is the empty string. + nameValuePair = header + } + + // 3. If the name-value-pair string lacks a %x3D ("=") character, then + // the name string is empty, and the value string is the value of + // name-value-pair. + if (!nameValuePair.includes('=')) { + value = nameValuePair + } else { + // Otherwise, the name string consists of the characters up to, but + // not including, the first %x3D ("=") character, and the (possibly + // empty) value string consists of the characters after the first + // %x3D ("=") character. + const position = { position: 0 } + name = collectASequenceOfCodePointsFast( + '=', + nameValuePair, + position + ) + value = nameValuePair.slice(position.position + 1) + } + + // 4. Remove any leading or trailing WSP characters from the name + // string and the value string. + name = name.trim() + value = value.trim() + + // 5. If the sum of the lengths of the name string and the value string + // is more than 4096 octets, abort these steps and ignore the set- + // cookie-string entirely. + if (name.length + value.length > maxNameValuePairSize) { + return null + } + + // 6. The cookie-name is the name string, and the cookie-value is the + // value string. + return { + name, value, ...parseUnparsedAttributes(unparsedAttributes) + } +} + +/** + * Parses the remaining attributes of a set-cookie header + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} unparsedAttributes + * @param {[Object.]={}} cookieAttributeList + */ +function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) { + // 1. If the unparsed-attributes string is empty, skip the rest of + // these steps. + if (unparsedAttributes.length === 0) { + return cookieAttributeList + } + + // 2. Discard the first character of the unparsed-attributes (which + // will be a %x3B (";") character). + assert(unparsedAttributes[0] === ';') + unparsedAttributes = unparsedAttributes.slice(1) + + let cookieAv = '' + + // 3. If the remaining unparsed-attributes contains a %x3B (";") + // character: + if (unparsedAttributes.includes(';')) { + // 1. Consume the characters of the unparsed-attributes up to, but + // not including, the first %x3B (";") character. + cookieAv = collectASequenceOfCodePointsFast( + ';', + unparsedAttributes, + { position: 0 } + ) + unparsedAttributes = unparsedAttributes.slice(cookieAv.length) + } else { + // Otherwise: + + // 1. Consume the remainder of the unparsed-attributes. + cookieAv = unparsedAttributes + unparsedAttributes = '' + } + + // Let the cookie-av string be the characters consumed in this step. + + let attributeName = '' + let attributeValue = '' + + // 4. If the cookie-av string contains a %x3D ("=") character: + if (cookieAv.includes('=')) { + // 1. The (possibly empty) attribute-name string consists of the + // characters up to, but not including, the first %x3D ("=") + // character, and the (possibly empty) attribute-value string + // consists of the characters after the first %x3D ("=") + // character. + const position = { position: 0 } + + attributeName = collectASequenceOfCodePointsFast( + '=', + cookieAv, + position + ) + attributeValue = cookieAv.slice(position.position + 1) + } else { + // Otherwise: + + // 1. The attribute-name string consists of the entire cookie-av + // string, and the attribute-value string is empty. + attributeName = cookieAv + } + + // 5. Remove any leading or trailing WSP characters from the attribute- + // name string and the attribute-value string. + attributeName = attributeName.trim() + attributeValue = attributeValue.trim() + + // 6. If the attribute-value is longer than 1024 octets, ignore the + // cookie-av string and return to Step 1 of this algorithm. + if (attributeValue.length > maxAttributeValueSize) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 7. Process the attribute-name and attribute-value according to the + // requirements in the following subsections. (Notice that + // attributes with unrecognized attribute-names are ignored.) + const attributeNameLowercase = attributeName.toLowerCase() + + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.1 + // If the attribute-name case-insensitively matches the string + // "Expires", the user agent MUST process the cookie-av as follows. + if (attributeNameLowercase === 'expires') { + // 1. Let the expiry-time be the result of parsing the attribute-value + // as cookie-date (see Section 5.1.1). + const expiryTime = new Date(attributeValue) + + // 2. If the attribute-value failed to parse as a cookie date, ignore + // the cookie-av. + + cookieAttributeList.expires = expiryTime + } else if (attributeNameLowercase === 'max-age') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.2 + // If the attribute-name case-insensitively matches the string "Max- + // Age", the user agent MUST process the cookie-av as follows. + + // 1. If the first character of the attribute-value is not a DIGIT or a + // "-" character, ignore the cookie-av. + const charCode = attributeValue.charCodeAt(0) + + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 2. If the remainder of attribute-value contains a non-DIGIT + // character, ignore the cookie-av. + if (!/^\d+$/.test(attributeValue)) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 3. Let delta-seconds be the attribute-value converted to an integer. + const deltaSeconds = Number(attributeValue) + + // 4. Let cookie-age-limit be the maximum age of the cookie (which + // SHOULD be 400 days or less, see Section 4.1.2.2). + + // 5. Set delta-seconds to the smaller of its present value and cookie- + // age-limit. + // deltaSeconds = Math.min(deltaSeconds * 1000, maxExpiresMs) + + // 6. If delta-seconds is less than or equal to zero (0), let expiry- + // time be the earliest representable date and time. Otherwise, let + // the expiry-time be the current date and time plus delta-seconds + // seconds. + // const expiryTime = deltaSeconds <= 0 ? Date.now() : Date.now() + deltaSeconds + + // 7. Append an attribute to the cookie-attribute-list with an + // attribute-name of Max-Age and an attribute-value of expiry-time. + cookieAttributeList.maxAge = deltaSeconds + } else if (attributeNameLowercase === 'domain') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.3 + // If the attribute-name case-insensitively matches the string "Domain", + // the user agent MUST process the cookie-av as follows. + + // 1. Let cookie-domain be the attribute-value. + let cookieDomain = attributeValue + + // 2. If cookie-domain starts with %x2E ("."), let cookie-domain be + // cookie-domain without its leading %x2E ("."). + if (cookieDomain[0] === '.') { + cookieDomain = cookieDomain.slice(1) + } + + // 3. Convert the cookie-domain to lower case. + cookieDomain = cookieDomain.toLowerCase() + + // 4. Append an attribute to the cookie-attribute-list with an + // attribute-name of Domain and an attribute-value of cookie-domain. + cookieAttributeList.domain = cookieDomain + } else if (attributeNameLowercase === 'path') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.4 + // If the attribute-name case-insensitively matches the string "Path", + // the user agent MUST process the cookie-av as follows. + + // 1. If the attribute-value is empty or if the first character of the + // attribute-value is not %x2F ("/"): + let cookiePath = '' + if (attributeValue.length === 0 || attributeValue[0] !== '/') { + // 1. Let cookie-path be the default-path. + cookiePath = '/' + } else { + // Otherwise: + + // 1. Let cookie-path be the attribute-value. + cookiePath = attributeValue + } + + // 2. Append an attribute to the cookie-attribute-list with an + // attribute-name of Path and an attribute-value of cookie-path. + cookieAttributeList.path = cookiePath + } else if (attributeNameLowercase === 'secure') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.5 + // If the attribute-name case-insensitively matches the string "Secure", + // the user agent MUST append an attribute to the cookie-attribute-list + // with an attribute-name of Secure and an empty attribute-value. + + cookieAttributeList.secure = true + } else if (attributeNameLowercase === 'httponly') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.6 + // If the attribute-name case-insensitively matches the string + // "HttpOnly", the user agent MUST append an attribute to the cookie- + // attribute-list with an attribute-name of HttpOnly and an empty + // attribute-value. + + cookieAttributeList.httpOnly = true + } else if (attributeNameLowercase === 'samesite') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7 + // If the attribute-name case-insensitively matches the string + // "SameSite", the user agent MUST process the cookie-av as follows: + + // 1. Let enforcement be "Default". + let enforcement = 'Default' + + const attributeValueLowercase = attributeValue.toLowerCase() + // 2. If cookie-av's attribute-value is a case-insensitive match for + // "None", set enforcement to "None". + if (attributeValueLowercase.includes('none')) { + enforcement = 'None' + } + + // 3. If cookie-av's attribute-value is a case-insensitive match for + // "Strict", set enforcement to "Strict". + if (attributeValueLowercase.includes('strict')) { + enforcement = 'Strict' + } + + // 4. If cookie-av's attribute-value is a case-insensitive match for + // "Lax", set enforcement to "Lax". + if (attributeValueLowercase.includes('lax')) { + enforcement = 'Lax' + } + + // 5. Append an attribute to the cookie-attribute-list with an + // attribute-name of "SameSite" and an attribute-value of + // enforcement. + cookieAttributeList.sameSite = enforcement + } else { + cookieAttributeList.unparsed ??= [] + + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`) + } + + // 8. Return to Step 1 of this algorithm. + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) +} + +module.exports = { + parseSetCookie, + parseUnparsedAttributes +} + + +/***/ }), + +/***/ 3834: +/***/ ((module) => { + +"use strict"; + + +/** + * @param {string} value + * @returns {boolean} + */ +function isCTLExcludingHtab (value) { + if (value.length === 0) { + return false + } + + for (const char of value) { + const code = char.charCodeAt(0) + + if ( + (code >= 0x00 || code <= 0x08) || + (code >= 0x0A || code <= 0x1F) || + code === 0x7F + ) { + return false + } + } +} + +/** + CHAR = + token = 1* + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + * @param {string} name + */ +function validateCookieName (name) { + for (const char of name) { + const code = char.charCodeAt(0) + + if ( + (code <= 0x20 || code > 0x7F) || + char === '(' || + char === ')' || + char === '>' || + char === '<' || + char === '@' || + char === ',' || + char === ';' || + char === ':' || + char === '\\' || + char === '"' || + char === '/' || + char === '[' || + char === ']' || + char === '?' || + char === '=' || + char === '{' || + char === '}' + ) { + throw new Error('Invalid cookie name') + } + } +} + +/** + cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + ; US-ASCII characters excluding CTLs, + ; whitespace DQUOTE, comma, semicolon, + ; and backslash + * @param {string} value + */ +function validateCookieValue (value) { + for (const char of value) { + const code = char.charCodeAt(0) + + if ( + code < 0x21 || // exclude CTLs (0-31) + code === 0x22 || + code === 0x2C || + code === 0x3B || + code === 0x5C || + code > 0x7E // non-ascii + ) { + throw new Error('Invalid header value') + } + } +} + +/** + * path-value = + * @param {string} path + */ +function validateCookiePath (path) { + for (const char of path) { + const code = char.charCodeAt(0) + + if (code < 0x21 || char === ';') { + throw new Error('Invalid cookie path') + } + } +} + +/** + * I have no idea why these values aren't allowed to be honest, + * but Deno tests these. - Khafra + * @param {string} domain + */ +function validateCookieDomain (domain) { + if ( + domain.startsWith('-') || + domain.endsWith('.') || + domain.endsWith('-') + ) { + throw new Error('Invalid cookie domain') + } +} + +/** + * @see https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1 + * @param {number|Date} date + IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT + ; fixed length/zone/capitalization subset of the format + ; see Section 3.3 of [RFC5322] + + day-name = %x4D.6F.6E ; "Mon", case-sensitive + / %x54.75.65 ; "Tue", case-sensitive + / %x57.65.64 ; "Wed", case-sensitive + / %x54.68.75 ; "Thu", case-sensitive + / %x46.72.69 ; "Fri", case-sensitive + / %x53.61.74 ; "Sat", case-sensitive + / %x53.75.6E ; "Sun", case-sensitive + date1 = day SP month SP year + ; e.g., 02 Jun 1982 + + day = 2DIGIT + month = %x4A.61.6E ; "Jan", case-sensitive + / %x46.65.62 ; "Feb", case-sensitive + / %x4D.61.72 ; "Mar", case-sensitive + / %x41.70.72 ; "Apr", case-sensitive + / %x4D.61.79 ; "May", case-sensitive + / %x4A.75.6E ; "Jun", case-sensitive + / %x4A.75.6C ; "Jul", case-sensitive + / %x41.75.67 ; "Aug", case-sensitive + / %x53.65.70 ; "Sep", case-sensitive + / %x4F.63.74 ; "Oct", case-sensitive + / %x4E.6F.76 ; "Nov", case-sensitive + / %x44.65.63 ; "Dec", case-sensitive + year = 4DIGIT + + GMT = %x47.4D.54 ; "GMT", case-sensitive + + time-of-day = hour ":" minute ":" second + ; 00:00:00 - 23:59:60 (leap second) + + hour = 2DIGIT + minute = 2DIGIT + second = 2DIGIT + */ +function toIMFDate (date) { + if (typeof date === 'number') { + date = new Date(date) + } + + const days = [ + 'Sun', 'Mon', 'Tue', 'Wed', + 'Thu', 'Fri', 'Sat' + ] + + const months = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ] + + const dayName = days[date.getUTCDay()] + const day = date.getUTCDate().toString().padStart(2, '0') + const month = months[date.getUTCMonth()] + const year = date.getUTCFullYear() + const hour = date.getUTCHours().toString().padStart(2, '0') + const minute = date.getUTCMinutes().toString().padStart(2, '0') + const second = date.getUTCSeconds().toString().padStart(2, '0') + + return `${dayName}, ${day} ${month} ${year} ${hour}:${minute}:${second} GMT` +} + +/** + max-age-av = "Max-Age=" non-zero-digit *DIGIT + ; In practice, both expires-av and max-age-av + ; are limited to dates representable by the + ; user agent. + * @param {number} maxAge + */ +function validateCookieMaxAge (maxAge) { + if (maxAge < 0) { + throw new Error('Invalid cookie max-age') + } +} + +/** + * @see https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1 + * @param {import('./index').Cookie} cookie + */ +function stringify (cookie) { + if (cookie.name.length === 0) { + return null + } + + validateCookieName(cookie.name) + validateCookieValue(cookie.value) + + const out = [`${cookie.name}=${cookie.value}`] + + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1 + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2 + if (cookie.name.startsWith('__Secure-')) { + cookie.secure = true + } + + if (cookie.name.startsWith('__Host-')) { + cookie.secure = true + cookie.domain = null + cookie.path = '/' + } + + if (cookie.secure) { + out.push('Secure') + } + + if (cookie.httpOnly) { + out.push('HttpOnly') + } + + if (typeof cookie.maxAge === 'number') { + validateCookieMaxAge(cookie.maxAge) + out.push(`Max-Age=${cookie.maxAge}`) + } + + if (cookie.domain) { + validateCookieDomain(cookie.domain) + out.push(`Domain=${cookie.domain}`) + } + + if (cookie.path) { + validateCookiePath(cookie.path) + out.push(`Path=${cookie.path}`) + } + + if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') { + out.push(`Expires=${toIMFDate(cookie.expires)}`) + } + + if (cookie.sameSite) { + out.push(`SameSite=${cookie.sameSite}`) + } + + for (const part of cookie.unparsed) { + if (!part.includes('=')) { + throw new Error('Invalid unparsed') + } + + const [key, ...value] = part.split('=') + + out.push(`${key.trim()}=${value.join('=')}`) + } + + return out.join('; ') +} + +module.exports = { + isCTLExcludingHtab, + validateCookieName, + validateCookiePath, + validateCookieValue, + toIMFDate, + stringify +} + + +/***/ }), + +/***/ 59136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const net = __nccwpck_require__(69278) +const assert = __nccwpck_require__(42613) +const util = __nccwpck_require__(3440) +const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(68707) + +let tls // include tls conditionally since it is not always available + +// TODO: session re-use does not wait for the first +// connection to resolve the session and might therefore +// resolve the same servername multiple times even when +// re-use is enabled. + +let SessionCache +// FIXME: remove workaround when the Node bug is fixed +// https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 +if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) { + SessionCache = class WeakSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + this._sessionRegistry = new global.FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { + return + } + + const ref = this._sessionCache.get(key) + if (ref !== undefined && ref.deref() === undefined) { + this._sessionCache.delete(key) + } + }) + } + + get (sessionKey) { + const ref = this._sessionCache.get(sessionKey) + return ref ? ref.deref() : null + } + + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } + + this._sessionCache.set(sessionKey, new WeakRef(session)) + this._sessionRegistry.register(session, sessionKey) + } + } +} else { + SessionCache = class SimpleSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + } + + get (sessionKey) { + return this._sessionCache.get(sessionKey) + } + + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } + + if (this._sessionCache.size >= this._maxCachedSessions) { + // remove the oldest session + const { value: oldestKey } = this._sessionCache.keys().next() + this._sessionCache.delete(oldestKey) + } + + this._sessionCache.set(sessionKey, session) + } + } +} + +function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { + if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { + throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') + } + + const options = { path: socketPath, ...opts } + const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions) + timeout = timeout == null ? 10e3 : timeout + allowH2 = allowH2 != null ? allowH2 : false + return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { + let socket + if (protocol === 'https:') { + if (!tls) { + tls = __nccwpck_require__(64756) + } + servername = servername || options.servername || util.getServerName(host) || null + + const sessionKey = servername || hostname + const session = sessionCache.get(sessionKey) || null + + assert(sessionKey) + + socket = tls.connect({ + highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... + ...options, + servername, + session, + localAddress, + // TODO(HTTP/2): Add support for h2c + ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'], + socket: httpSocket, // upgrade socket connection + port: port || 443, + host: hostname + }) + + socket + .on('session', function (session) { + // TODO (fix): Can a session become invalid once established? Don't think so? + sessionCache.set(sessionKey, session) + }) + } else { + assert(!httpSocket, 'httpSocket can only be sent on TLS update') + socket = net.connect({ + highWaterMark: 64 * 1024, // Same as nodejs fs streams. + ...options, + localAddress, + port: port || 80, + host: hostname + }) + } + + // Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket + if (options.keepAlive == null || options.keepAlive) { + const keepAliveInitialDelay = options.keepAliveInitialDelay === undefined ? 60e3 : options.keepAliveInitialDelay + socket.setKeepAlive(true, keepAliveInitialDelay) + } + + const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout) + + socket + .setNoDelay(true) + .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () { + cancelTimeout() + + if (callback) { + const cb = callback + callback = null + cb(null, this) + } + }) + .on('error', function (err) { + cancelTimeout() + + if (callback) { + const cb = callback + callback = null + cb(err) + } + }) + + return socket + } +} + +function setupTimeout (onConnectTimeout, timeout) { + if (!timeout) { + return () => {} + } + + let s1 = null + let s2 = null + const timeoutId = setTimeout(() => { + // setImmediate is added to make sure that we priotorise socket error events over timeouts + s1 = setImmediate(() => { + if (process.platform === 'win32') { + // Windows needs an extra setImmediate probably due to implementation differences in the socket logic + s2 = setImmediate(() => onConnectTimeout()) + } else { + onConnectTimeout() + } + }) + }, timeout) + return () => { + clearTimeout(timeoutId) + clearImmediate(s1) + clearImmediate(s2) + } +} + +function onConnectTimeout (socket) { + util.destroy(socket, new ConnectTimeoutError()) +} + +module.exports = buildConnector + + +/***/ }), + +/***/ 10735: +/***/ ((module) => { + +"use strict"; + + +/** @type {Record} */ +const headerNameLowerCasedRecord = {} + +// https://developer.mozilla.org/docs/Web/HTTP/Headers +const wellknownHeaderNames = [ + 'Accept', + 'Accept-Encoding', + 'Accept-Language', + 'Accept-Ranges', + 'Access-Control-Allow-Credentials', + 'Access-Control-Allow-Headers', + 'Access-Control-Allow-Methods', + 'Access-Control-Allow-Origin', + 'Access-Control-Expose-Headers', + 'Access-Control-Max-Age', + 'Access-Control-Request-Headers', + 'Access-Control-Request-Method', + 'Age', + 'Allow', + 'Alt-Svc', + 'Alt-Used', + 'Authorization', + 'Cache-Control', + 'Clear-Site-Data', + 'Connection', + 'Content-Disposition', + 'Content-Encoding', + 'Content-Language', + 'Content-Length', + 'Content-Location', + 'Content-Range', + 'Content-Security-Policy', + 'Content-Security-Policy-Report-Only', + 'Content-Type', + 'Cookie', + 'Cross-Origin-Embedder-Policy', + 'Cross-Origin-Opener-Policy', + 'Cross-Origin-Resource-Policy', + 'Date', + 'Device-Memory', + 'Downlink', + 'ECT', + 'ETag', + 'Expect', + 'Expect-CT', + 'Expires', + 'Forwarded', + 'From', + 'Host', + 'If-Match', + 'If-Modified-Since', + 'If-None-Match', + 'If-Range', + 'If-Unmodified-Since', + 'Keep-Alive', + 'Last-Modified', + 'Link', + 'Location', + 'Max-Forwards', + 'Origin', + 'Permissions-Policy', + 'Pragma', + 'Proxy-Authenticate', + 'Proxy-Authorization', + 'RTT', + 'Range', + 'Referer', + 'Referrer-Policy', + 'Refresh', + 'Retry-After', + 'Sec-WebSocket-Accept', + 'Sec-WebSocket-Extensions', + 'Sec-WebSocket-Key', + 'Sec-WebSocket-Protocol', + 'Sec-WebSocket-Version', + 'Server', + 'Server-Timing', + 'Service-Worker-Allowed', + 'Service-Worker-Navigation-Preload', + 'Set-Cookie', + 'SourceMap', + 'Strict-Transport-Security', + 'Supports-Loading-Mode', + 'TE', + 'Timing-Allow-Origin', + 'Trailer', + 'Transfer-Encoding', + 'Upgrade', + 'Upgrade-Insecure-Requests', + 'User-Agent', + 'Vary', + 'Via', + 'WWW-Authenticate', + 'X-Content-Type-Options', + 'X-DNS-Prefetch-Control', + 'X-Frame-Options', + 'X-Permitted-Cross-Domain-Policies', + 'X-Powered-By', + 'X-Requested-With', + 'X-XSS-Protection' +] + +for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = wellknownHeaderNames[i] + const lowerCasedKey = key.toLowerCase() + headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = + lowerCasedKey +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(headerNameLowerCasedRecord, null) + +module.exports = { + wellknownHeaderNames, + headerNameLowerCasedRecord +} + + +/***/ }), + +/***/ 68707: +/***/ ((module) => { + +"use strict"; + + +class UndiciError extends Error { + constructor (message) { + super(message) + this.name = 'UndiciError' + this.code = 'UND_ERR' + } +} + +class ConnectTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ConnectTimeoutError) + this.name = 'ConnectTimeoutError' + this.message = message || 'Connect Timeout Error' + this.code = 'UND_ERR_CONNECT_TIMEOUT' + } +} + +class HeadersTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, HeadersTimeoutError) + this.name = 'HeadersTimeoutError' + this.message = message || 'Headers Timeout Error' + this.code = 'UND_ERR_HEADERS_TIMEOUT' + } +} + +class HeadersOverflowError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, HeadersOverflowError) + this.name = 'HeadersOverflowError' + this.message = message || 'Headers Overflow Error' + this.code = 'UND_ERR_HEADERS_OVERFLOW' + } +} + +class BodyTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, BodyTimeoutError) + this.name = 'BodyTimeoutError' + this.message = message || 'Body Timeout Error' + this.code = 'UND_ERR_BODY_TIMEOUT' + } +} + +class ResponseStatusCodeError extends UndiciError { + constructor (message, statusCode, headers, body) { + super(message) + Error.captureStackTrace(this, ResponseStatusCodeError) + this.name = 'ResponseStatusCodeError' + this.message = message || 'Response Status Code Error' + this.code = 'UND_ERR_RESPONSE_STATUS_CODE' + this.body = body + this.status = statusCode + this.statusCode = statusCode + this.headers = headers + } +} + +class InvalidArgumentError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InvalidArgumentError) + this.name = 'InvalidArgumentError' + this.message = message || 'Invalid Argument Error' + this.code = 'UND_ERR_INVALID_ARG' + } +} + +class InvalidReturnValueError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InvalidReturnValueError) + this.name = 'InvalidReturnValueError' + this.message = message || 'Invalid Return Value Error' + this.code = 'UND_ERR_INVALID_RETURN_VALUE' + } +} + +class RequestAbortedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, RequestAbortedError) + this.name = 'AbortError' + this.message = message || 'Request aborted' + this.code = 'UND_ERR_ABORTED' + } +} + +class InformationalError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InformationalError) + this.name = 'InformationalError' + this.message = message || 'Request information' + this.code = 'UND_ERR_INFO' + } +} + +class RequestContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, RequestContentLengthMismatchError) + this.name = 'RequestContentLengthMismatchError' + this.message = message || 'Request body length does not match content-length header' + this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' + } +} + +class ResponseContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ResponseContentLengthMismatchError) + this.name = 'ResponseContentLengthMismatchError' + this.message = message || 'Response body length does not match content-length header' + this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' + } +} + +class ClientDestroyedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ClientDestroyedError) + this.name = 'ClientDestroyedError' + this.message = message || 'The client is destroyed' + this.code = 'UND_ERR_DESTROYED' + } +} + +class ClientClosedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ClientClosedError) + this.name = 'ClientClosedError' + this.message = message || 'The client is closed' + this.code = 'UND_ERR_CLOSED' + } +} + +class SocketError extends UndiciError { + constructor (message, socket) { + super(message) + Error.captureStackTrace(this, SocketError) + this.name = 'SocketError' + this.message = message || 'Socket error' + this.code = 'UND_ERR_SOCKET' + this.socket = socket + } +} + +class NotSupportedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, NotSupportedError) + this.name = 'NotSupportedError' + this.message = message || 'Not supported error' + this.code = 'UND_ERR_NOT_SUPPORTED' + } +} + +class BalancedPoolMissingUpstreamError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, NotSupportedError) + this.name = 'MissingUpstreamError' + this.message = message || 'No upstream has been added to the BalancedPool' + this.code = 'UND_ERR_BPL_MISSING_UPSTREAM' + } +} + +class HTTPParserError extends Error { + constructor (message, code, data) { + super(message) + Error.captureStackTrace(this, HTTPParserError) + this.name = 'HTTPParserError' + this.code = code ? `HPE_${code}` : undefined + this.data = data ? data.toString() : undefined + } +} + +class ResponseExceededMaxSizeError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ResponseExceededMaxSizeError) + this.name = 'ResponseExceededMaxSizeError' + this.message = message || 'Response content exceeded max size' + this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE' + } +} + +class RequestRetryError extends UndiciError { + constructor (message, code, { headers, data }) { + super(message) + Error.captureStackTrace(this, RequestRetryError) + this.name = 'RequestRetryError' + this.message = message || 'Request retry error' + this.code = 'UND_ERR_REQ_RETRY' + this.statusCode = code + this.data = data + this.headers = headers + } +} + +module.exports = { + HTTPParserError, + UndiciError, + HeadersTimeoutError, + HeadersOverflowError, + BodyTimeoutError, + RequestContentLengthMismatchError, + ConnectTimeoutError, + ResponseStatusCodeError, + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError, + ClientDestroyedError, + ClientClosedError, + InformationalError, + SocketError, + NotSupportedError, + ResponseContentLengthMismatchError, + BalancedPoolMissingUpstreamError, + ResponseExceededMaxSizeError, + RequestRetryError +} + + +/***/ }), + +/***/ 44655: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + InvalidArgumentError, + NotSupportedError +} = __nccwpck_require__(68707) +const assert = __nccwpck_require__(42613) +const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(36443) +const util = __nccwpck_require__(3440) + +// tokenRegExp and headerCharRegex have been lifted from +// https://github.com/nodejs/node/blob/main/lib/_http_common.js + +/** + * Verifies that the given val is a valid HTTP token + * per the rules defined in RFC 7230 + * See https://tools.ietf.org/html/rfc7230#section-3.2.6 + */ +const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/ + +/** + * Matches if val contains an invalid field-vchar + * field-value = *( field-content / obs-fold ) + * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] + * field-vchar = VCHAR / obs-text + */ +const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/ + +// Verifies that a given path is valid does not contain control chars \x00 to \x20 +const invalidPathRegex = /[^\u0021-\u00ff]/ + +const kHandler = Symbol('handler') + +const channels = {} + +let extractBody + +try { + const diagnosticsChannel = __nccwpck_require__(31637) + channels.create = diagnosticsChannel.channel('undici:request:create') + channels.bodySent = diagnosticsChannel.channel('undici:request:bodySent') + channels.headers = diagnosticsChannel.channel('undici:request:headers') + channels.trailers = diagnosticsChannel.channel('undici:request:trailers') + channels.error = diagnosticsChannel.channel('undici:request:error') +} catch { + channels.create = { hasSubscribers: false } + channels.bodySent = { hasSubscribers: false } + channels.headers = { hasSubscribers: false } + channels.trailers = { hasSubscribers: false } + channels.error = { hasSubscribers: false } +} + +class Request { + constructor (origin, { + path, + method, + body, + headers, + query, + idempotent, + blocking, + upgrade, + headersTimeout, + bodyTimeout, + reset, + throwOnError, + expectContinue + }, handler) { + if (typeof path !== 'string') { + throw new InvalidArgumentError('path must be a string') + } else if ( + path[0] !== '/' && + !(path.startsWith('http://') || path.startsWith('https://')) && + method !== 'CONNECT' + ) { + throw new InvalidArgumentError('path must be an absolute URL or start with a slash') + } else if (invalidPathRegex.exec(path) !== null) { + throw new InvalidArgumentError('invalid request path') + } + + if (typeof method !== 'string') { + throw new InvalidArgumentError('method must be a string') + } else if (tokenRegExp.exec(method) === null) { + throw new InvalidArgumentError('invalid request method') + } + + if (upgrade && typeof upgrade !== 'string') { + throw new InvalidArgumentError('upgrade must be a string') + } + + if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('invalid headersTimeout') + } + + if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('invalid bodyTimeout') + } + + if (reset != null && typeof reset !== 'boolean') { + throw new InvalidArgumentError('invalid reset') + } + + if (expectContinue != null && typeof expectContinue !== 'boolean') { + throw new InvalidArgumentError('invalid expectContinue') + } + + this.headersTimeout = headersTimeout + + this.bodyTimeout = bodyTimeout + + this.throwOnError = throwOnError === true + + this.method = method + + this.abort = null + + if (body == null) { + this.body = null + } else if (util.isStream(body)) { + this.body = body + + const rState = this.body._readableState + if (!rState || !rState.autoDestroy) { + this.endHandler = function autoDestroy () { + util.destroy(this) + } + this.body.on('end', this.endHandler) + } + + this.errorHandler = err => { + if (this.abort) { + this.abort(err) + } else { + this.error = err + } + } + this.body.on('error', this.errorHandler) + } else if (util.isBuffer(body)) { + this.body = body.byteLength ? body : null + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null + } else if (typeof body === 'string') { + this.body = body.length ? Buffer.from(body) : null + } else if (util.isFormDataLike(body) || util.isIterable(body) || util.isBlobLike(body)) { + this.body = body + } else { + throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable') + } + + this.completed = false + + this.aborted = false + + this.upgrade = upgrade || null + + this.path = query ? util.buildURL(path, query) : path + + this.origin = origin + + this.idempotent = idempotent == null + ? method === 'HEAD' || method === 'GET' + : idempotent + + this.blocking = blocking == null ? false : blocking + + this.reset = reset == null ? null : reset + + this.host = null + + this.contentLength = null + + this.contentType = null + + this.headers = '' + + // Only for H2 + this.expectContinue = expectContinue != null ? expectContinue : false + + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(this, headers[i], headers[i + 1]) + } + } else if (headers && typeof headers === 'object') { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + processHeader(this, key, headers[key]) + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') + } + + if (util.isFormDataLike(this.body)) { + if (util.nodeMajor < 16 || (util.nodeMajor === 16 && util.nodeMinor < 8)) { + throw new InvalidArgumentError('Form-Data bodies are only supported in node v16.8 and newer.') + } + + if (!extractBody) { + extractBody = (__nccwpck_require__(8923).extractBody) + } + + const [bodyStream, contentType] = extractBody(body) + if (this.contentType == null) { + this.contentType = contentType + this.headers += `content-type: ${contentType}\r\n` + } + this.body = bodyStream.stream + this.contentLength = bodyStream.length + } else if (util.isBlobLike(body) && this.contentType == null && body.type) { + this.contentType = body.type + this.headers += `content-type: ${body.type}\r\n` + } + + util.validateHandler(handler, method, upgrade) + + this.servername = util.getServerName(this.host) + + this[kHandler] = handler + + if (channels.create.hasSubscribers) { + channels.create.publish({ request: this }) + } + } + + onBodySent (chunk) { + if (this[kHandler].onBodySent) { + try { + return this[kHandler].onBodySent(chunk) + } catch (err) { + this.abort(err) + } + } + } + + onRequestSent () { + if (channels.bodySent.hasSubscribers) { + channels.bodySent.publish({ request: this }) + } + + if (this[kHandler].onRequestSent) { + try { + return this[kHandler].onRequestSent() + } catch (err) { + this.abort(err) + } + } + } + + onConnect (abort) { + assert(!this.aborted) + assert(!this.completed) + + if (this.error) { + abort(this.error) + } else { + this.abort = abort + return this[kHandler].onConnect(abort) + } + } + + onHeaders (statusCode, headers, resume, statusText) { + assert(!this.aborted) + assert(!this.completed) + + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) + } + + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + } catch (err) { + this.abort(err) + } + } + + onData (chunk) { + assert(!this.aborted) + assert(!this.completed) + + try { + return this[kHandler].onData(chunk) + } catch (err) { + this.abort(err) + return false + } + } + + onUpgrade (statusCode, headers, socket) { + assert(!this.aborted) + assert(!this.completed) + + return this[kHandler].onUpgrade(statusCode, headers, socket) + } + + onComplete (trailers) { + this.onFinally() + + assert(!this.aborted) + + this.completed = true + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers }) + } + + try { + return this[kHandler].onComplete(trailers) + } catch (err) { + // TODO (fix): This might be a bad idea? + this.onError(err) + } + } + + onError (error) { + this.onFinally() + + if (channels.error.hasSubscribers) { + channels.error.publish({ request: this, error }) + } + + if (this.aborted) { + return + } + this.aborted = true + + return this[kHandler].onError(error) + } + + onFinally () { + if (this.errorHandler) { + this.body.off('error', this.errorHandler) + this.errorHandler = null + } + + if (this.endHandler) { + this.body.off('end', this.endHandler) + this.endHandler = null + } + } + + // TODO: adjust to support H2 + addHeader (key, value) { + processHeader(this, key, value) + return this + } + + static [kHTTP1BuildRequest] (origin, opts, handler) { + // TODO: Migrate header parsing here, to make Requests + // HTTP agnostic + return new Request(origin, opts, handler) + } + + static [kHTTP2BuildRequest] (origin, opts, handler) { + const headers = opts.headers + opts = { ...opts, headers: null } + + const request = new Request(origin, opts, handler) + + request.headers = {} + + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(request, headers[i], headers[i + 1], true) + } + } else if (headers && typeof headers === 'object') { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + processHeader(request, key, headers[key], true) + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') + } + + return request + } + + static [kHTTP2CopyHeaders] (raw) { + const rawHeaders = raw.split('\r\n') + const headers = {} + + for (const header of rawHeaders) { + const [key, value] = header.split(': ') + + if (value == null || value.length === 0) continue + + if (headers[key]) headers[key] += `,${value}` + else headers[key] = value + } + + return headers + } +} + +function processHeaderValue (key, val, skipAppend) { + if (val && typeof val === 'object') { + throw new InvalidArgumentError(`invalid ${key} header`) + } + + val = val != null ? `${val}` : '' + + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + + return skipAppend ? val : `${key}: ${val}\r\n` +} + +function processHeader (request, key, val, skipAppend = false) { + if (val && (typeof val === 'object' && !Array.isArray(val))) { + throw new InvalidArgumentError(`invalid ${key} header`) + } else if (val === undefined) { + return + } + + if ( + request.host === null && + key.length === 4 && + key.toLowerCase() === 'host' + ) { + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + // Consumed by Client + request.host = val + } else if ( + request.contentLength === null && + key.length === 14 && + key.toLowerCase() === 'content-length' + ) { + request.contentLength = parseInt(val, 10) + if (!Number.isFinite(request.contentLength)) { + throw new InvalidArgumentError('invalid content-length header') + } + } else if ( + request.contentType === null && + key.length === 12 && + key.toLowerCase() === 'content-type' + ) { + request.contentType = val + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) + else request.headers += processHeaderValue(key, val) + } else if ( + key.length === 17 && + key.toLowerCase() === 'transfer-encoding' + ) { + throw new InvalidArgumentError('invalid transfer-encoding header') + } else if ( + key.length === 10 && + key.toLowerCase() === 'connection' + ) { + const value = typeof val === 'string' ? val.toLowerCase() : null + if (value !== 'close' && value !== 'keep-alive') { + throw new InvalidArgumentError('invalid connection header') + } else if (value === 'close') { + request.reset = true + } + } else if ( + key.length === 10 && + key.toLowerCase() === 'keep-alive' + ) { + throw new InvalidArgumentError('invalid keep-alive header') + } else if ( + key.length === 7 && + key.toLowerCase() === 'upgrade' + ) { + throw new InvalidArgumentError('invalid upgrade header') + } else if ( + key.length === 6 && + key.toLowerCase() === 'expect' + ) { + throw new NotSupportedError('expect header not supported') + } else if (tokenRegExp.exec(key) === null) { + throw new InvalidArgumentError('invalid header key') + } else { + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + if (skipAppend) { + if (request.headers[key]) request.headers[key] += `,${processHeaderValue(key, val[i], skipAppend)}` + else request.headers[key] = processHeaderValue(key, val[i], skipAppend) + } else { + request.headers += processHeaderValue(key, val[i]) + } + } + } else { + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) + else request.headers += processHeaderValue(key, val) + } + } +} + +module.exports = Request + + +/***/ }), + +/***/ 36443: +/***/ ((module) => { + +module.exports = { + kClose: Symbol('close'), + kDestroy: Symbol('destroy'), + kDispatch: Symbol('dispatch'), + kUrl: Symbol('url'), + kWriting: Symbol('writing'), + kResuming: Symbol('resuming'), + kQueue: Symbol('queue'), + kConnect: Symbol('connect'), + kConnecting: Symbol('connecting'), + kHeadersList: Symbol('headers list'), + kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), + kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), + kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), + kKeepAliveTimeoutValue: Symbol('keep alive timeout'), + kKeepAlive: Symbol('keep alive'), + kHeadersTimeout: Symbol('headers timeout'), + kBodyTimeout: Symbol('body timeout'), + kServerName: Symbol('server name'), + kLocalAddress: Symbol('local address'), + kHost: Symbol('host'), + kNoRef: Symbol('no ref'), + kBodyUsed: Symbol('used'), + kRunning: Symbol('running'), + kBlocking: Symbol('blocking'), + kPending: Symbol('pending'), + kSize: Symbol('size'), + kBusy: Symbol('busy'), + kQueued: Symbol('queued'), + kFree: Symbol('free'), + kConnected: Symbol('connected'), + kClosed: Symbol('closed'), + kNeedDrain: Symbol('need drain'), + kReset: Symbol('reset'), + kDestroyed: Symbol.for('nodejs.stream.destroyed'), + kMaxHeadersSize: Symbol('max headers size'), + kRunningIdx: Symbol('running index'), + kPendingIdx: Symbol('pending index'), + kError: Symbol('error'), + kClients: Symbol('clients'), + kClient: Symbol('client'), + kParser: Symbol('parser'), + kOnDestroyed: Symbol('destroy callbacks'), + kPipelining: Symbol('pipelining'), + kSocket: Symbol('socket'), + kHostHeader: Symbol('host header'), + kConnector: Symbol('connector'), + kStrictContentLength: Symbol('strict content length'), + kMaxRedirections: Symbol('maxRedirections'), + kMaxRequests: Symbol('maxRequestsPerClient'), + kProxy: Symbol('proxy agent options'), + kCounter: Symbol('socket request counter'), + kInterceptors: Symbol('dispatch interceptors'), + kMaxResponseSize: Symbol('max response size'), + kHTTP2Session: Symbol('http2Session'), + kHTTP2SessionState: Symbol('http2Session state'), + kHTTP2BuildRequest: Symbol('http2 build request'), + kHTTP1BuildRequest: Symbol('http1 build request'), + kHTTP2CopyHeaders: Symbol('http2 copy headers'), + kHTTPConnVersion: Symbol('http connection version'), + kRetryHandlerDefaultRetry: Symbol('retry agent default retry'), + kConstruct: Symbol('constructable') +} + + +/***/ }), + +/***/ 3440: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const assert = __nccwpck_require__(42613) +const { kDestroyed, kBodyUsed } = __nccwpck_require__(36443) +const { IncomingMessage } = __nccwpck_require__(58611) +const stream = __nccwpck_require__(2203) +const net = __nccwpck_require__(69278) +const { InvalidArgumentError } = __nccwpck_require__(68707) +const { Blob } = __nccwpck_require__(20181) +const nodeUtil = __nccwpck_require__(39023) +const { stringify } = __nccwpck_require__(83480) +const { headerNameLowerCasedRecord } = __nccwpck_require__(10735) + +const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v)) + +function nop () {} + +function isStream (obj) { + return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function' +} + +// based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License) +function isBlobLike (object) { + return (Blob && object instanceof Blob) || ( + object && + typeof object === 'object' && + (typeof object.stream === 'function' || + typeof object.arrayBuffer === 'function') && + /^(Blob|File)$/.test(object[Symbol.toStringTag]) + ) +} + +function buildURL (url, queryParams) { + if (url.includes('?') || url.includes('#')) { + throw new Error('Query params cannot be passed when url already contains "?" or "#".') + } + + const stringified = stringify(queryParams) + + if (stringified) { + url += '?' + stringified + } + + return url +} + +function parseURL (url) { + if (typeof url === 'string') { + url = new URL(url) + + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } + + return url + } + + if (!url || typeof url !== 'object') { + throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') + } + + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } + + if (!(url instanceof URL)) { + if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) { + throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') + } + + if (url.path != null && typeof url.path !== 'string') { + throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') + } + + if (url.pathname != null && typeof url.pathname !== 'string') { + throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') + } + + if (url.hostname != null && typeof url.hostname !== 'string') { + throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') + } + + if (url.origin != null && typeof url.origin !== 'string') { + throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') + } + + const port = url.port != null + ? url.port + : (url.protocol === 'https:' ? 443 : 80) + let origin = url.origin != null + ? url.origin + : `${url.protocol}//${url.hostname}:${port}` + let path = url.path != null + ? url.path + : `${url.pathname || ''}${url.search || ''}` + + if (origin.endsWith('/')) { + origin = origin.substring(0, origin.length - 1) + } + + if (path && !path.startsWith('/')) { + path = `/${path}` + } + // new URL(path, origin) is unsafe when `path` contains an absolute URL + // From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL: + // If first parameter is a relative URL, second param is required, and will be used as the base URL. + // If first parameter is an absolute URL, a given second param will be ignored. + url = new URL(origin + path) + } + + return url +} + +function parseOrigin (url) { + url = parseURL(url) + + if (url.pathname !== '/' || url.search || url.hash) { + throw new InvalidArgumentError('invalid url') + } + + return url +} + +function getHostname (host) { + if (host[0] === '[') { + const idx = host.indexOf(']') + + assert(idx !== -1) + return host.substring(1, idx) + } + + const idx = host.indexOf(':') + if (idx === -1) return host + + return host.substring(0, idx) +} + +// IP addresses are not valid server names per RFC6066 +// > Currently, the only server names supported are DNS hostnames +function getServerName (host) { + if (!host) { + return null + } + + assert.strictEqual(typeof host, 'string') + + const servername = getHostname(host) + if (net.isIP(servername)) { + return '' + } + + return servername +} + +function deepClone (obj) { + return JSON.parse(JSON.stringify(obj)) +} + +function isAsyncIterable (obj) { + return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') +} + +function isIterable (obj) { + return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) +} + +function bodyLength (body) { + if (body == null) { + return 0 + } else if (isStream(body)) { + const state = body._readableState + return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) + ? state.length + : null + } else if (isBlobLike(body)) { + return body.size != null ? body.size : null + } else if (isBuffer(body)) { + return body.byteLength + } + + return null +} + +function isDestroyed (stream) { + return !stream || !!(stream.destroyed || stream[kDestroyed]) +} + +function isReadableAborted (stream) { + const state = stream && stream._readableState + return isDestroyed(stream) && state && !state.endEmitted +} + +function destroy (stream, err) { + if (stream == null || !isStream(stream) || isDestroyed(stream)) { + return + } + + if (typeof stream.destroy === 'function') { + if (Object.getPrototypeOf(stream).constructor === IncomingMessage) { + // See: https://github.com/nodejs/node/pull/38505/files + stream.socket = null + } + + stream.destroy(err) + } else if (err) { + process.nextTick((stream, err) => { + stream.emit('error', err) + }, stream, err) + } + + if (stream.destroyed !== true) { + stream[kDestroyed] = true + } +} + +const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/ +function parseKeepAliveTimeout (val) { + const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR) + return m ? parseInt(m[1], 10) * 1000 : null +} + +/** + * Retrieves a header name and returns its lowercase value. + * @param {string | Buffer} value Header name + * @returns {string} + */ +function headerNameToString (value) { + return headerNameLowerCasedRecord[value] || value.toLowerCase() +} + +function parseHeaders (headers, obj = {}) { + // For H2 support + if (!Array.isArray(headers)) return headers + + for (let i = 0; i < headers.length; i += 2) { + const key = headers[i].toString().toLowerCase() + let val = obj[key] + + if (!val) { + if (Array.isArray(headers[i + 1])) { + obj[key] = headers[i + 1].map(x => x.toString('utf8')) + } else { + obj[key] = headers[i + 1].toString('utf8') + } + } else { + if (!Array.isArray(val)) { + val = [val] + obj[key] = val + } + val.push(headers[i + 1].toString('utf8')) + } + } + + // See https://github.com/nodejs/node/pull/46528 + if ('content-length' in obj && 'content-disposition' in obj) { + obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1') + } + + return obj +} + +function parseRawHeaders (headers) { + const ret = [] + let hasContentLength = false + let contentDispositionIdx = -1 + + for (let n = 0; n < headers.length; n += 2) { + const key = headers[n + 0].toString() + const val = headers[n + 1].toString('utf8') + + if (key.length === 14 && (key === 'content-length' || key.toLowerCase() === 'content-length')) { + ret.push(key, val) + hasContentLength = true + } else if (key.length === 19 && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) { + contentDispositionIdx = ret.push(key, val) - 1 + } else { + ret.push(key, val) + } + } + + // See https://github.com/nodejs/node/pull/46528 + if (hasContentLength && contentDispositionIdx !== -1) { + ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString('latin1') + } + + return ret +} + +function isBuffer (buffer) { + // See, https://github.com/mcollina/undici/pull/319 + return buffer instanceof Uint8Array || Buffer.isBuffer(buffer) +} + +function validateHandler (handler, method, upgrade) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } + + if (typeof handler.onConnect !== 'function') { + throw new InvalidArgumentError('invalid onConnect method') + } + + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') + } + + if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { + throw new InvalidArgumentError('invalid onBodySent method') + } + + if (upgrade || method === 'CONNECT') { + if (typeof handler.onUpgrade !== 'function') { + throw new InvalidArgumentError('invalid onUpgrade method') + } + } else { + if (typeof handler.onHeaders !== 'function') { + throw new InvalidArgumentError('invalid onHeaders method') + } + + if (typeof handler.onData !== 'function') { + throw new InvalidArgumentError('invalid onData method') + } + + if (typeof handler.onComplete !== 'function') { + throw new InvalidArgumentError('invalid onComplete method') + } + } +} + +// A body is disturbed if it has been read from and it cannot +// be re-used without losing state or data. +function isDisturbed (body) { + return !!(body && ( + stream.isDisturbed + ? stream.isDisturbed(body) || body[kBodyUsed] // TODO (fix): Why is body[kBodyUsed] needed? + : body[kBodyUsed] || + body.readableDidRead || + (body._readableState && body._readableState.dataEmitted) || + isReadableAborted(body) + )) +} + +function isErrored (body) { + return !!(body && ( + stream.isErrored + ? stream.isErrored(body) + : /state: 'errored'/.test(nodeUtil.inspect(body) + ))) +} + +function isReadable (body) { + return !!(body && ( + stream.isReadable + ? stream.isReadable(body) + : /state: 'readable'/.test(nodeUtil.inspect(body) + ))) +} + +function getSocketInfo (socket) { + return { + localAddress: socket.localAddress, + localPort: socket.localPort, + remoteAddress: socket.remoteAddress, + remotePort: socket.remotePort, + remoteFamily: socket.remoteFamily, + timeout: socket.timeout, + bytesWritten: socket.bytesWritten, + bytesRead: socket.bytesRead + } +} + +async function * convertIterableToBuffer (iterable) { + for await (const chunk of iterable) { + yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk) + } +} + +let ReadableStream +function ReadableStreamFrom (iterable) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + if (ReadableStream.from) { + return ReadableStream.from(convertIterableToBuffer(iterable)) + } + + let iterator + return new ReadableStream( + { + async start () { + iterator = iterable[Symbol.asyncIterator]() + }, + async pull (controller) { + const { done, value } = await iterator.next() + if (done) { + queueMicrotask(() => { + controller.close() + }) + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) + controller.enqueue(new Uint8Array(buf)) + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + } + }, + 0 + ) +} + +// The chunk should be a FormData instance and contains +// all the required methods. +function isFormDataLike (object) { + return ( + object && + typeof object === 'object' && + typeof object.append === 'function' && + typeof object.delete === 'function' && + typeof object.get === 'function' && + typeof object.getAll === 'function' && + typeof object.has === 'function' && + typeof object.set === 'function' && + object[Symbol.toStringTag] === 'FormData' + ) +} + +function throwIfAborted (signal) { + if (!signal) { return } + if (typeof signal.throwIfAborted === 'function') { + signal.throwIfAborted() + } else { + if (signal.aborted) { + // DOMException not available < v17.0.0 + const err = new Error('The operation was aborted') + err.name = 'AbortError' + throw err + } + } +} + +function addAbortListener (signal, listener) { + if ('addEventListener' in signal) { + signal.addEventListener('abort', listener, { once: true }) + return () => signal.removeEventListener('abort', listener) + } + signal.addListener('abort', listener) + return () => signal.removeListener('abort', listener) +} + +const hasToWellFormed = !!String.prototype.toWellFormed + +/** + * @param {string} val + */ +function toUSVString (val) { + if (hasToWellFormed) { + return `${val}`.toWellFormed() + } else if (nodeUtil.toUSVString) { + return nodeUtil.toUSVString(val) + } + + return `${val}` +} + +// Parsed accordingly to RFC 9110 +// https://www.rfc-editor.org/rfc/rfc9110#field.content-range +function parseRangeHeader (range) { + if (range == null || range === '') return { start: 0, end: null, size: null } + + const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null + return m + ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } + : null +} + +const kEnumerableProperty = Object.create(null) +kEnumerableProperty.enumerable = true + +module.exports = { + kEnumerableProperty, + nop, + isDisturbed, + isErrored, + isReadable, + toUSVString, + isReadableAborted, + isBlobLike, + parseOrigin, + parseURL, + getServerName, + isStream, + isIterable, + isAsyncIterable, + isDestroyed, + headerNameToString, + parseRawHeaders, + parseHeaders, + parseKeepAliveTimeout, + destroy, + bodyLength, + deepClone, + ReadableStreamFrom, + isBuffer, + validateHandler, + getSocketInfo, + isFormDataLike, + buildURL, + throwIfAborted, + addAbortListener, + parseRangeHeader, + nodeMajor, + nodeMinor, + nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13), + safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'] +} + + +/***/ }), + +/***/ 50001: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Dispatcher = __nccwpck_require__(28611) +const { + ClientDestroyedError, + ClientClosedError, + InvalidArgumentError +} = __nccwpck_require__(68707) +const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(36443) + +const kDestroyed = Symbol('destroyed') +const kClosed = Symbol('closed') +const kOnDestroyed = Symbol('onDestroyed') +const kOnClosed = Symbol('onClosed') +const kInterceptedDispatch = Symbol('Intercepted Dispatch') + +class DispatcherBase extends Dispatcher { + constructor () { + super() + + this[kDestroyed] = false + this[kOnDestroyed] = null + this[kClosed] = false + this[kOnClosed] = [] + } + + get destroyed () { + return this[kDestroyed] + } + + get closed () { + return this[kClosed] + } + + get interceptors () { + return this[kInterceptors] + } + + set interceptors (newInterceptors) { + if (newInterceptors) { + for (let i = newInterceptors.length - 1; i >= 0; i--) { + const interceptor = this[kInterceptors][i] + if (typeof interceptor !== 'function') { + throw new InvalidArgumentError('interceptor must be an function') + } + } + } + + this[kInterceptors] = newInterceptors + } + + close (callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (this[kDestroyed]) { + queueMicrotask(() => callback(new ClientDestroyedError(), null)) + return + } + + if (this[kClosed]) { + if (this[kOnClosed]) { + this[kOnClosed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } + + this[kClosed] = true + this[kOnClosed].push(callback) + + const onClosed = () => { + const callbacks = this[kOnClosed] + this[kOnClosed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } + + // Should not error. + this[kClose]() + .then(() => this.destroy()) + .then(() => { + queueMicrotask(onClosed) + }) + } + + destroy (err, callback) { + if (typeof err === 'function') { + callback = err + err = null + } + + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.destroy(err, (err, data) => { + return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data) + }) + }) + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (this[kDestroyed]) { + if (this[kOnDestroyed]) { + this[kOnDestroyed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } + + if (!err) { + err = new ClientDestroyedError() + } + + this[kDestroyed] = true + this[kOnDestroyed] = this[kOnDestroyed] || [] + this[kOnDestroyed].push(callback) + + const onDestroyed = () => { + const callbacks = this[kOnDestroyed] + this[kOnDestroyed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } + + // Should not error. + this[kDestroy](err).then(() => { + queueMicrotask(onDestroyed) + }) + } + + [kInterceptedDispatch] (opts, handler) { + if (!this[kInterceptors] || this[kInterceptors].length === 0) { + this[kInterceptedDispatch] = this[kDispatch] + return this[kDispatch](opts, handler) + } + + let dispatch = this[kDispatch].bind(this) + for (let i = this[kInterceptors].length - 1; i >= 0; i--) { + dispatch = this[kInterceptors][i](dispatch) + } + this[kInterceptedDispatch] = dispatch + return dispatch(opts, handler) + } + + dispatch (opts, handler) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } + + try { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object.') + } + + if (this[kDestroyed] || this[kOnDestroyed]) { + throw new ClientDestroyedError() + } + + if (this[kClosed]) { + throw new ClientClosedError() + } + + return this[kInterceptedDispatch](opts, handler) + } catch (err) { + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') + } + + handler.onError(err) + + return false + } + } +} + +module.exports = DispatcherBase + + +/***/ }), + +/***/ 28611: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const EventEmitter = __nccwpck_require__(24434) + +class Dispatcher extends EventEmitter { + dispatch () { + throw new Error('not implemented') + } + + close () { + throw new Error('not implemented') + } + + destroy () { + throw new Error('not implemented') + } +} + +module.exports = Dispatcher + + +/***/ }), + +/***/ 8923: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Busboy = __nccwpck_require__(89581) +const util = __nccwpck_require__(3440) +const { + ReadableStreamFrom, + isBlobLike, + isReadableStreamLike, + readableStreamClose, + createDeferredPromise, + fullyReadBody +} = __nccwpck_require__(15523) +const { FormData } = __nccwpck_require__(43073) +const { kState } = __nccwpck_require__(89710) +const { webidl } = __nccwpck_require__(74222) +const { DOMException, structuredClone } = __nccwpck_require__(87326) +const { Blob, File: NativeFile } = __nccwpck_require__(20181) +const { kBodyUsed } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { isErrored } = __nccwpck_require__(3440) +const { isUint8Array, isArrayBuffer } = __nccwpck_require__(98253) +const { File: UndiciFile } = __nccwpck_require__(63041) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(94322) + +let random +try { + const crypto = __nccwpck_require__(77598) + random = (max) => crypto.randomInt(0, max) +} catch { + random = (max) => Math.floor(Math.random(max)) +} + +let ReadableStream = globalThis.ReadableStream + +/** @type {globalThis['File']} */ +const File = NativeFile ?? UndiciFile +const textEncoder = new TextEncoder() +const textDecoder = new TextDecoder() + +// https://fetch.spec.whatwg.org/#concept-bodyinit-extract +function extractBody (object, keepalive = false) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + // 1. Let stream be null. + let stream = null + + // 2. If object is a ReadableStream object, then set stream to object. + if (object instanceof ReadableStream) { + stream = object + } else if (isBlobLike(object)) { + // 3. Otherwise, if object is a Blob object, set stream to the + // result of running object’s get stream. + stream = object.stream() + } else { + // 4. Otherwise, set stream to a new ReadableStream object, and set + // up stream. + stream = new ReadableStream({ + async pull (controller) { + controller.enqueue( + typeof source === 'string' ? textEncoder.encode(source) : source + ) + queueMicrotask(() => readableStreamClose(controller)) + }, + start () {}, + type: undefined + }) + } + + // 5. Assert: stream is a ReadableStream object. + assert(isReadableStreamLike(stream)) + + // 6. Let action be null. + let action = null + + // 7. Let source be null. + let source = null + + // 8. Let length be null. + let length = null + + // 9. Let type be null. + let type = null + + // 10. Switch on object: + if (typeof object === 'string') { + // Set source to the UTF-8 encoding of object. + // Note: setting source to a Uint8Array here breaks some mocking assumptions. + source = object + + // Set type to `text/plain;charset=UTF-8`. + type = 'text/plain;charset=UTF-8' + } else if (object instanceof URLSearchParams) { + // URLSearchParams + + // spec says to run application/x-www-form-urlencoded on body.list + // this is implemented in Node.js as apart of an URLSearchParams instance toString method + // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490 + // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100 + + // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. + source = object.toString() + + // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. + type = 'application/x-www-form-urlencoded;charset=UTF-8' + } else if (isArrayBuffer(object)) { + // BufferSource/ArrayBuffer + + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.slice()) + } else if (ArrayBuffer.isView(object)) { + // BufferSource/ArrayBufferView + + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) + } else if (util.isFormDataLike(object)) { + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` + const prefix = `--${boundary}\r\nContent-Disposition: form-data` + + /*! formdata-polyfill. MIT License. Jimmy Wärting */ + const escape = (str) => + str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22') + const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n') + + // Set action to this step: run the multipart/form-data + // encoding algorithm, with object’s entry list and UTF-8. + // - This ensures that the body is immutable and can't be changed afterwords + // - That the content-length is calculated in advance. + // - And that all parts are pre-encoded and ready to be sent. + + const blobParts = [] + const rn = new Uint8Array([13, 10]) // '\r\n' + length = 0 + let hasUnknownSizeValue = false + + for (const [name, value] of object) { + if (typeof value === 'string') { + const chunk = textEncoder.encode(prefix + + `; name="${escape(normalizeLinefeeds(name))}"` + + `\r\n\r\n${normalizeLinefeeds(value)}\r\n`) + blobParts.push(chunk) + length += chunk.byteLength + } else { + const chunk = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + + (value.name ? `; filename="${escape(value.name)}"` : '') + '\r\n' + + `Content-Type: ${ + value.type || 'application/octet-stream' + }\r\n\r\n`) + blobParts.push(chunk, value, rn) + if (typeof value.size === 'number') { + length += chunk.byteLength + value.size + rn.byteLength + } else { + hasUnknownSizeValue = true + } + } + } + + const chunk = textEncoder.encode(`--${boundary}--`) + blobParts.push(chunk) + length += chunk.byteLength + if (hasUnknownSizeValue) { + length = null + } + + // Set source to object. + source = object + + action = async function * () { + for (const part of blobParts) { + if (part.stream) { + yield * part.stream() + } else { + yield part + } + } + } + + // Set type to `multipart/form-data; boundary=`, + // followed by the multipart/form-data boundary string generated + // by the multipart/form-data encoding algorithm. + type = 'multipart/form-data; boundary=' + boundary + } else if (isBlobLike(object)) { + // Blob + + // Set source to object. + source = object + + // Set length to object’s size. + length = object.size + + // If object’s type attribute is not the empty byte sequence, set + // type to its value. + if (object.type) { + type = object.type + } + } else if (typeof object[Symbol.asyncIterator] === 'function') { + // If keepalive is true, then throw a TypeError. + if (keepalive) { + throw new TypeError('keepalive') + } + + // If object is disturbed or locked, then throw a TypeError. + if (util.isDisturbed(object) || object.locked) { + throw new TypeError( + 'Response body object should not be disturbed or locked' + ) + } + + stream = + object instanceof ReadableStream ? object : ReadableStreamFrom(object) + } + + // 11. If source is a byte sequence, then set action to a + // step that returns source and length to source’s length. + if (typeof source === 'string' || util.isBuffer(source)) { + length = Buffer.byteLength(source) + } + + // 12. If action is non-null, then run these steps in in parallel: + if (action != null) { + // Run action. + let iterator + stream = new ReadableStream({ + async start () { + iterator = action(object)[Symbol.asyncIterator]() + }, + async pull (controller) { + const { value, done } = await iterator.next() + if (done) { + // When running action is done, close stream. + queueMicrotask(() => { + controller.close() + }) + } else { + // Whenever one or more bytes are available and stream is not errored, + // enqueue a Uint8Array wrapping an ArrayBuffer containing the available + // bytes into stream. + if (!isErrored(stream)) { + controller.enqueue(new Uint8Array(value)) + } + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + }, + type: undefined + }) + } + + // 13. Let body be a body whose stream is stream, source is source, + // and length is length. + const body = { stream, source, length } + + // 14. Return (body, type). + return [body, type] +} + +// https://fetch.spec.whatwg.org/#bodyinit-safely-extract +function safelyExtractBody (object, keepalive = false) { + if (!ReadableStream) { + // istanbul ignore next + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + // To safely extract a body and a `Content-Type` value from + // a byte sequence or BodyInit object object, run these steps: + + // 1. If object is a ReadableStream object, then: + if (object instanceof ReadableStream) { + // Assert: object is neither disturbed nor locked. + // istanbul ignore next + assert(!util.isDisturbed(object), 'The body has already been consumed.') + // istanbul ignore next + assert(!object.locked, 'The stream is locked.') + } + + // 2. Return the results of extracting object. + return extractBody(object, keepalive) +} + +function cloneBody (body) { + // To clone a body body, run these steps: + + // https://fetch.spec.whatwg.org/#concept-body-clone + + // 1. Let « out1, out2 » be the result of teeing body’s stream. + const [out1, out2] = body.stream.tee() + const out2Clone = structuredClone(out2, { transfer: [out2] }) + // This, for whatever reasons, unrefs out2Clone which allows + // the process to exit by itself. + const [, finalClone] = out2Clone.tee() + + // 2. Set body’s stream to out1. + body.stream = out1 + + // 3. Return a body whose stream is out2 and other members are copied from body. + return { + stream: finalClone, + length: body.length, + source: body.source + } +} + +async function * consumeBody (body) { + if (body) { + if (isUint8Array(body)) { + yield body + } else { + const stream = body.stream + + if (util.isDisturbed(stream)) { + throw new TypeError('The body has already been consumed.') + } + + if (stream.locked) { + throw new TypeError('The stream is locked.') + } + + // Compat. + stream[kBodyUsed] = true + + yield * stream + } + } +} + +function throwIfAborted (state) { + if (state.aborted) { + throw new DOMException('The operation was aborted.', 'AbortError') + } +} + +function bodyMixinMethods (instance) { + const methods = { + blob () { + // The blob() method steps are to return the result of + // running consume body with this and the following step + // given a byte sequence bytes: return a Blob whose + // contents are bytes and whose type attribute is this’s + // MIME type. + return specConsumeBody(this, (bytes) => { + let mimeType = bodyMimeType(this) + + if (mimeType === 'failure') { + mimeType = '' + } else if (mimeType) { + mimeType = serializeAMimeType(mimeType) + } + + // Return a Blob whose contents are bytes and type attribute + // is mimeType. + return new Blob([bytes], { type: mimeType }) + }, instance) + }, + + arrayBuffer () { + // The arrayBuffer() method steps are to return the result + // of running consume body with this and the following step + // given a byte sequence bytes: return a new ArrayBuffer + // whose contents are bytes. + return specConsumeBody(this, (bytes) => { + return new Uint8Array(bytes).buffer + }, instance) + }, + + text () { + // The text() method steps are to return the result of running + // consume body with this and UTF-8 decode. + return specConsumeBody(this, utf8DecodeBytes, instance) + }, + + json () { + // The json() method steps are to return the result of running + // consume body with this and parse JSON from bytes. + return specConsumeBody(this, parseJSONFromBytes, instance) + }, + + async formData () { + webidl.brandCheck(this, instance) + + throwIfAborted(this[kState]) + + const contentType = this.headers.get('Content-Type') + + // If mimeType’s essence is "multipart/form-data", then: + if (/multipart\/form-data/.test(contentType)) { + const headers = {} + for (const [key, value] of this.headers) headers[key.toLowerCase()] = value + + const responseFormData = new FormData() + + let busboy + + try { + busboy = new Busboy({ + headers, + preservePath: true + }) + } catch (err) { + throw new DOMException(`${err}`, 'AbortError') + } + + busboy.on('field', (name, value) => { + responseFormData.append(name, value) + }) + busboy.on('file', (name, value, filename, encoding, mimeType) => { + const chunks = [] + + if (encoding === 'base64' || encoding.toLowerCase() === 'base64') { + let base64chunk = '' + + value.on('data', (chunk) => { + base64chunk += chunk.toString().replace(/[\r\n]/gm, '') + + const end = base64chunk.length - base64chunk.length % 4 + chunks.push(Buffer.from(base64chunk.slice(0, end), 'base64')) + + base64chunk = base64chunk.slice(end) + }) + value.on('end', () => { + chunks.push(Buffer.from(base64chunk, 'base64')) + responseFormData.append(name, new File(chunks, filename, { type: mimeType })) + }) + } else { + value.on('data', (chunk) => { + chunks.push(chunk) + }) + value.on('end', () => { + responseFormData.append(name, new File(chunks, filename, { type: mimeType })) + }) + } + }) + + const busboyResolve = new Promise((resolve, reject) => { + busboy.on('finish', resolve) + busboy.on('error', (err) => reject(new TypeError(err))) + }) + + if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk) + busboy.end() + await busboyResolve + + return responseFormData + } else if (/application\/x-www-form-urlencoded/.test(contentType)) { + // Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then: + + // 1. Let entries be the result of parsing bytes. + let entries + try { + let text = '' + // application/x-www-form-urlencoded parser will keep the BOM. + // https://url.spec.whatwg.org/#concept-urlencoded-parser + // Note that streaming decoder is stateful and cannot be reused + const streamingDecoder = new TextDecoder('utf-8', { ignoreBOM: true }) + + for await (const chunk of consumeBody(this[kState].body)) { + if (!isUint8Array(chunk)) { + throw new TypeError('Expected Uint8Array chunk') + } + text += streamingDecoder.decode(chunk, { stream: true }) + } + text += streamingDecoder.decode() + entries = new URLSearchParams(text) + } catch (err) { + // istanbul ignore next: Unclear when new URLSearchParams can fail on a string. + // 2. If entries is failure, then throw a TypeError. + throw Object.assign(new TypeError(), { cause: err }) + } + + // 3. Return a new FormData object whose entries are entries. + const formData = new FormData() + for (const [name, value] of entries) { + formData.append(name, value) + } + return formData + } else { + // Wait a tick before checking if the request has been aborted. + // Otherwise, a TypeError can be thrown when an AbortError should. + await Promise.resolve() + + throwIfAborted(this[kState]) + + // Otherwise, throw a TypeError. + throw webidl.errors.exception({ + header: `${instance.name}.formData`, + message: 'Could not parse content as FormData.' + }) + } + } + } + + return methods +} + +function mixinBody (prototype) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype)) +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-body-consume-body + * @param {Response|Request} object + * @param {(value: unknown) => unknown} convertBytesToJSValue + * @param {Response|Request} instance + */ +async function specConsumeBody (object, convertBytesToJSValue, instance) { + webidl.brandCheck(object, instance) + + throwIfAborted(object[kState]) + + // 1. If object is unusable, then return a promise rejected + // with a TypeError. + if (bodyUnusable(object[kState].body)) { + throw new TypeError('Body is unusable') + } + + // 2. Let promise be a new promise. + const promise = createDeferredPromise() + + // 3. Let errorSteps given error be to reject promise with error. + const errorSteps = (error) => promise.reject(error) + + // 4. Let successSteps given a byte sequence data be to resolve + // promise with the result of running convertBytesToJSValue + // with data. If that threw an exception, then run errorSteps + // with that exception. + const successSteps = (data) => { + try { + promise.resolve(convertBytesToJSValue(data)) + } catch (e) { + errorSteps(e) + } + } + + // 5. If object’s body is null, then run successSteps with an + // empty byte sequence. + if (object[kState].body == null) { + successSteps(new Uint8Array()) + return promise.promise + } + + // 6. Otherwise, fully read object’s body given successSteps, + // errorSteps, and object’s relevant global object. + await fullyReadBody(object[kState].body, successSteps, errorSteps) + + // 7. Return promise. + return promise.promise +} + +// https://fetch.spec.whatwg.org/#body-unusable +function bodyUnusable (body) { + // An object including the Body interface mixin is + // said to be unusable if its body is non-null and + // its body’s stream is disturbed or locked. + return body != null && (body.stream.locked || util.isDisturbed(body.stream)) +} + +/** + * @see https://encoding.spec.whatwg.org/#utf-8-decode + * @param {Buffer} buffer + */ +function utf8DecodeBytes (buffer) { + if (buffer.length === 0) { + return '' + } + + // 1. Let buffer be the result of peeking three bytes from + // ioQueue, converted to a byte sequence. + + // 2. If buffer is 0xEF 0xBB 0xBF, then read three + // bytes from ioQueue. (Do nothing with those bytes.) + if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + buffer = buffer.subarray(3) + } + + // 3. Process a queue with an instance of UTF-8’s + // decoder, ioQueue, output, and "replacement". + const output = textDecoder.decode(buffer) + + // 4. Return output. + return output +} + +/** + * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value + * @param {Uint8Array} bytes + */ +function parseJSONFromBytes (bytes) { + return JSON.parse(utf8DecodeBytes(bytes)) +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-body-mime-type + * @param {import('./response').Response|import('./request').Request} object + */ +function bodyMimeType (object) { + const { headersList } = object[kState] + const contentType = headersList.get('content-type') + + if (contentType === null) { + return 'failure' + } + + return parseMIMEType(contentType) +} + +module.exports = { + extractBody, + safelyExtractBody, + cloneBody, + mixinBody +} + + +/***/ }), + +/***/ 87326: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { MessageChannel, receiveMessageOnPort } = __nccwpck_require__(28167) + +const corsSafeListedMethods = ['GET', 'HEAD', 'POST'] +const corsSafeListedMethodsSet = new Set(corsSafeListedMethods) + +const nullBodyStatus = [101, 204, 205, 304] + +const redirectStatus = [301, 302, 303, 307, 308] +const redirectStatusSet = new Set(redirectStatus) + +// https://fetch.spec.whatwg.org/#block-bad-port +const badPorts = [ + '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', + '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', + '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', + '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', + '2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697', + '10080' +] + +const badPortsSet = new Set(badPorts) + +// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies +const referrerPolicy = [ + '', + 'no-referrer', + 'no-referrer-when-downgrade', + 'same-origin', + 'origin', + 'strict-origin', + 'origin-when-cross-origin', + 'strict-origin-when-cross-origin', + 'unsafe-url' +] +const referrerPolicySet = new Set(referrerPolicy) + +const requestRedirect = ['follow', 'manual', 'error'] + +const safeMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE'] +const safeMethodsSet = new Set(safeMethods) + +const requestMode = ['navigate', 'same-origin', 'no-cors', 'cors'] + +const requestCredentials = ['omit', 'same-origin', 'include'] + +const requestCache = [ + 'default', + 'no-store', + 'reload', + 'no-cache', + 'force-cache', + 'only-if-cached' +] + +// https://fetch.spec.whatwg.org/#request-body-header-name +const requestBodyHeader = [ + 'content-encoding', + 'content-language', + 'content-location', + 'content-type', + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + 'content-length' +] + +// https://fetch.spec.whatwg.org/#enumdef-requestduplex +const requestDuplex = [ + 'half' +] + +// http://fetch.spec.whatwg.org/#forbidden-method +const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK'] +const forbiddenMethodsSet = new Set(forbiddenMethods) + +const subresource = [ + 'audio', + 'audioworklet', + 'font', + 'image', + 'manifest', + 'paintworklet', + 'script', + 'style', + 'track', + 'video', + 'xslt', + '' +] +const subresourceSet = new Set(subresource) + +/** @type {globalThis['DOMException']} */ +const DOMException = globalThis.DOMException ?? (() => { + // DOMException was only made a global in Node v17.0.0, + // but fetch supports >= v16.8. + try { + atob('~') + } catch (err) { + return Object.getPrototypeOf(err).constructor + } +})() + +let channel + +/** @type {globalThis['structuredClone']} */ +const structuredClone = + globalThis.structuredClone ?? + // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js + // structuredClone was added in v17.0.0, but fetch supports v16.8 + function structuredClone (value, options = undefined) { + if (arguments.length === 0) { + throw new TypeError('missing argument') + } + + if (!channel) { + channel = new MessageChannel() + } + channel.port1.unref() + channel.port2.unref() + channel.port1.postMessage(value, options?.transfer) + return receiveMessageOnPort(channel.port2).message + } + +module.exports = { + DOMException, + structuredClone, + subresource, + forbiddenMethods, + requestBodyHeader, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + redirectStatus, + corsSafeListedMethods, + nullBodyStatus, + safeMethods, + badPorts, + requestDuplex, + subresourceSet, + badPortsSet, + redirectStatusSet, + corsSafeListedMethodsSet, + safeMethodsSet, + forbiddenMethodsSet, + referrerPolicySet +} + + +/***/ }), + +/***/ 94322: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(42613) +const { atob } = __nccwpck_require__(20181) +const { isomorphicDecode } = __nccwpck_require__(15523) + +const encoder = new TextEncoder() + +/** + * @see https://mimesniff.spec.whatwg.org/#http-token-code-point + */ +const HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/ +const HTTP_WHITESPACE_REGEX = /(\u000A|\u000D|\u0009|\u0020)/ // eslint-disable-line +/** + * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point + */ +const HTTP_QUOTED_STRING_TOKENS = /[\u0009|\u0020-\u007E|\u0080-\u00FF]/ // eslint-disable-line + +// https://fetch.spec.whatwg.org/#data-url-processor +/** @param {URL} dataURL */ +function dataURLProcessor (dataURL) { + // 1. Assert: dataURL’s scheme is "data". + assert(dataURL.protocol === 'data:') + + // 2. Let input be the result of running the URL + // serializer on dataURL with exclude fragment + // set to true. + let input = URLSerializer(dataURL, true) + + // 3. Remove the leading "data:" string from input. + input = input.slice(5) + + // 4. Let position point at the start of input. + const position = { position: 0 } + + // 5. Let mimeType be the result of collecting a + // sequence of code points that are not equal + // to U+002C (,), given position. + let mimeType = collectASequenceOfCodePointsFast( + ',', + input, + position + ) + + // 6. Strip leading and trailing ASCII whitespace + // from mimeType. + // Undici implementation note: we need to store the + // length because if the mimetype has spaces removed, + // the wrong amount will be sliced from the input in + // step #9 + const mimeTypeLength = mimeType.length + mimeType = removeASCIIWhitespace(mimeType, true, true) + + // 7. If position is past the end of input, then + // return failure + if (position.position >= input.length) { + return 'failure' + } + + // 8. Advance position by 1. + position.position++ + + // 9. Let encodedBody be the remainder of input. + const encodedBody = input.slice(mimeTypeLength + 1) + + // 10. Let body be the percent-decoding of encodedBody. + let body = stringPercentDecode(encodedBody) + + // 11. If mimeType ends with U+003B (;), followed by + // zero or more U+0020 SPACE, followed by an ASCII + // case-insensitive match for "base64", then: + if (/;(\u0020){0,}base64$/i.test(mimeType)) { + // 1. Let stringBody be the isomorphic decode of body. + const stringBody = isomorphicDecode(body) + + // 2. Set body to the forgiving-base64 decode of + // stringBody. + body = forgivingBase64(stringBody) + + // 3. If body is failure, then return failure. + if (body === 'failure') { + return 'failure' + } + + // 4. Remove the last 6 code points from mimeType. + mimeType = mimeType.slice(0, -6) + + // 5. Remove trailing U+0020 SPACE code points from mimeType, + // if any. + mimeType = mimeType.replace(/(\u0020)+$/, '') + + // 6. Remove the last U+003B (;) code point from mimeType. + mimeType = mimeType.slice(0, -1) + } + + // 12. If mimeType starts with U+003B (;), then prepend + // "text/plain" to mimeType. + if (mimeType.startsWith(';')) { + mimeType = 'text/plain' + mimeType + } + + // 13. Let mimeTypeRecord be the result of parsing + // mimeType. + let mimeTypeRecord = parseMIMEType(mimeType) + + // 14. If mimeTypeRecord is failure, then set + // mimeTypeRecord to text/plain;charset=US-ASCII. + if (mimeTypeRecord === 'failure') { + mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII') + } + + // 15. Return a new data: URL struct whose MIME + // type is mimeTypeRecord and body is body. + // https://fetch.spec.whatwg.org/#data-url-struct + return { mimeType: mimeTypeRecord, body } +} + +// https://url.spec.whatwg.org/#concept-url-serializer +/** + * @param {URL} url + * @param {boolean} excludeFragment + */ +function URLSerializer (url, excludeFragment = false) { + if (!excludeFragment) { + return url.href + } + + const href = url.href + const hashLength = url.hash.length + + return hashLength === 0 ? href : href.substring(0, href.length - hashLength) +} + +// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points +/** + * @param {(char: string) => boolean} condition + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePoints (condition, input, position) { + // 1. Let result be the empty string. + let result = '' + + // 2. While position doesn’t point past the end of input and the + // code point at position within input meets the condition condition: + while (position.position < input.length && condition(input[position.position])) { + // 1. Append that code point to the end of result. + result += input[position.position] + + // 2. Advance position by 1. + position.position++ + } + + // 3. Return result. + return result +} + +/** + * A faster collectASequenceOfCodePoints that only works when comparing a single character. + * @param {string} char + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePointsFast (char, input, position) { + const idx = input.indexOf(char, position.position) + const start = position.position + + if (idx === -1) { + position.position = input.length + return input.slice(start) + } + + position.position = idx + return input.slice(start, position.position) +} + +// https://url.spec.whatwg.org/#string-percent-decode +/** @param {string} input */ +function stringPercentDecode (input) { + // 1. Let bytes be the UTF-8 encoding of input. + const bytes = encoder.encode(input) + + // 2. Return the percent-decoding of bytes. + return percentDecode(bytes) +} + +// https://url.spec.whatwg.org/#percent-decode +/** @param {Uint8Array} input */ +function percentDecode (input) { + // 1. Let output be an empty byte sequence. + /** @type {number[]} */ + const output = [] + + // 2. For each byte byte in input: + for (let i = 0; i < input.length; i++) { + const byte = input[i] + + // 1. If byte is not 0x25 (%), then append byte to output. + if (byte !== 0x25) { + output.push(byte) + + // 2. Otherwise, if byte is 0x25 (%) and the next two bytes + // after byte in input are not in the ranges + // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F), + // and 0x61 (a) to 0x66 (f), all inclusive, append byte + // to output. + } else if ( + byte === 0x25 && + !/^[0-9A-Fa-f]{2}$/i.test(String.fromCharCode(input[i + 1], input[i + 2])) + ) { + output.push(0x25) + + // 3. Otherwise: + } else { + // 1. Let bytePoint be the two bytes after byte in input, + // decoded, and then interpreted as hexadecimal number. + const nextTwoBytes = String.fromCharCode(input[i + 1], input[i + 2]) + const bytePoint = Number.parseInt(nextTwoBytes, 16) + + // 2. Append a byte whose value is bytePoint to output. + output.push(bytePoint) + + // 3. Skip the next two bytes in input. + i += 2 + } + } + + // 3. Return output. + return Uint8Array.from(output) +} + +// https://mimesniff.spec.whatwg.org/#parse-a-mime-type +/** @param {string} input */ +function parseMIMEType (input) { + // 1. Remove any leading and trailing HTTP whitespace + // from input. + input = removeHTTPWhitespace(input, true, true) + + // 2. Let position be a position variable for input, + // initially pointing at the start of input. + const position = { position: 0 } + + // 3. Let type be the result of collecting a sequence + // of code points that are not U+002F (/) from + // input, given position. + const type = collectASequenceOfCodePointsFast( + '/', + input, + position + ) + + // 4. If type is the empty string or does not solely + // contain HTTP token code points, then return failure. + // https://mimesniff.spec.whatwg.org/#http-token-code-point + if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { + return 'failure' + } + + // 5. If position is past the end of input, then return + // failure + if (position.position > input.length) { + return 'failure' + } + + // 6. Advance position by 1. (This skips past U+002F (/).) + position.position++ + + // 7. Let subtype be the result of collecting a sequence of + // code points that are not U+003B (;) from input, given + // position. + let subtype = collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 8. Remove any trailing HTTP whitespace from subtype. + subtype = removeHTTPWhitespace(subtype, false, true) + + // 9. If subtype is the empty string or does not solely + // contain HTTP token code points, then return failure. + if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { + return 'failure' + } + + const typeLowercase = type.toLowerCase() + const subtypeLowercase = subtype.toLowerCase() + + // 10. Let mimeType be a new MIME type record whose type + // is type, in ASCII lowercase, and subtype is subtype, + // in ASCII lowercase. + // https://mimesniff.spec.whatwg.org/#mime-type + const mimeType = { + type: typeLowercase, + subtype: subtypeLowercase, + /** @type {Map} */ + parameters: new Map(), + // https://mimesniff.spec.whatwg.org/#mime-type-essence + essence: `${typeLowercase}/${subtypeLowercase}` + } + + // 11. While position is not past the end of input: + while (position.position < input.length) { + // 1. Advance position by 1. (This skips past U+003B (;).) + position.position++ + + // 2. Collect a sequence of code points that are HTTP + // whitespace from input given position. + collectASequenceOfCodePoints( + // https://fetch.spec.whatwg.org/#http-whitespace + char => HTTP_WHITESPACE_REGEX.test(char), + input, + position + ) + + // 3. Let parameterName be the result of collecting a + // sequence of code points that are not U+003B (;) + // or U+003D (=) from input, given position. + let parameterName = collectASequenceOfCodePoints( + (char) => char !== ';' && char !== '=', + input, + position + ) + + // 4. Set parameterName to parameterName, in ASCII + // lowercase. + parameterName = parameterName.toLowerCase() + + // 5. If position is not past the end of input, then: + if (position.position < input.length) { + // 1. If the code point at position within input is + // U+003B (;), then continue. + if (input[position.position] === ';') { + continue + } + + // 2. Advance position by 1. (This skips past U+003D (=).) + position.position++ + } + + // 6. If position is past the end of input, then break. + if (position.position > input.length) { + break + } + + // 7. Let parameterValue be null. + let parameterValue = null + + // 8. If the code point at position within input is + // U+0022 ("), then: + if (input[position.position] === '"') { + // 1. Set parameterValue to the result of collecting + // an HTTP quoted string from input, given position + // and the extract-value flag. + parameterValue = collectAnHTTPQuotedString(input, position, true) + + // 2. Collect a sequence of code points that are not + // U+003B (;) from input, given position. + collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 9. Otherwise: + } else { + // 1. Set parameterValue to the result of collecting + // a sequence of code points that are not U+003B (;) + // from input, given position. + parameterValue = collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 2. Remove any trailing HTTP whitespace from parameterValue. + parameterValue = removeHTTPWhitespace(parameterValue, false, true) + + // 3. If parameterValue is the empty string, then continue. + if (parameterValue.length === 0) { + continue + } + } + + // 10. If all of the following are true + // - parameterName is not the empty string + // - parameterName solely contains HTTP token code points + // - parameterValue solely contains HTTP quoted-string token code points + // - mimeType’s parameters[parameterName] does not exist + // then set mimeType’s parameters[parameterName] to parameterValue. + if ( + parameterName.length !== 0 && + HTTP_TOKEN_CODEPOINTS.test(parameterName) && + (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && + !mimeType.parameters.has(parameterName) + ) { + mimeType.parameters.set(parameterName, parameterValue) + } + } + + // 12. Return mimeType. + return mimeType +} + +// https://infra.spec.whatwg.org/#forgiving-base64-decode +/** @param {string} data */ +function forgivingBase64 (data) { + // 1. Remove all ASCII whitespace from data. + data = data.replace(/[\u0009\u000A\u000C\u000D\u0020]/g, '') // eslint-disable-line + + // 2. If data’s code point length divides by 4 leaving + // no remainder, then: + if (data.length % 4 === 0) { + // 1. If data ends with one or two U+003D (=) code points, + // then remove them from data. + data = data.replace(/=?=$/, '') + } + + // 3. If data’s code point length divides by 4 leaving + // a remainder of 1, then return failure. + if (data.length % 4 === 1) { + return 'failure' + } + + // 4. If data contains a code point that is not one of + // U+002B (+) + // U+002F (/) + // ASCII alphanumeric + // then return failure. + if (/[^+/0-9A-Za-z]/.test(data)) { + return 'failure' + } + + const binary = atob(data) + const bytes = new Uint8Array(binary.length) + + for (let byte = 0; byte < binary.length; byte++) { + bytes[byte] = binary.charCodeAt(byte) + } + + return bytes +} + +// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string +// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string +/** + * @param {string} input + * @param {{ position: number }} position + * @param {boolean?} extractValue + */ +function collectAnHTTPQuotedString (input, position, extractValue) { + // 1. Let positionStart be position. + const positionStart = position.position + + // 2. Let value be the empty string. + let value = '' + + // 3. Assert: the code point at position within input + // is U+0022 ("). + assert(input[position.position] === '"') + + // 4. Advance position by 1. + position.position++ + + // 5. While true: + while (true) { + // 1. Append the result of collecting a sequence of code points + // that are not U+0022 (") or U+005C (\) from input, given + // position, to value. + value += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== '\\', + input, + position + ) + + // 2. If position is past the end of input, then break. + if (position.position >= input.length) { + break + } + + // 3. Let quoteOrBackslash be the code point at position within + // input. + const quoteOrBackslash = input[position.position] + + // 4. Advance position by 1. + position.position++ + + // 5. If quoteOrBackslash is U+005C (\), then: + if (quoteOrBackslash === '\\') { + // 1. If position is past the end of input, then append + // U+005C (\) to value and break. + if (position.position >= input.length) { + value += '\\' + break + } + + // 2. Append the code point at position within input to value. + value += input[position.position] + + // 3. Advance position by 1. + position.position++ + + // 6. Otherwise: + } else { + // 1. Assert: quoteOrBackslash is U+0022 ("). + assert(quoteOrBackslash === '"') + + // 2. Break. + break + } + } + + // 6. If the extract-value flag is set, then return value. + if (extractValue) { + return value + } + + // 7. Return the code points from positionStart to position, + // inclusive, within input. + return input.slice(positionStart, position.position) +} + +/** + * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type + */ +function serializeAMimeType (mimeType) { + assert(mimeType !== 'failure') + const { parameters, essence } = mimeType + + // 1. Let serialization be the concatenation of mimeType’s + // type, U+002F (/), and mimeType’s subtype. + let serialization = essence + + // 2. For each name → value of mimeType’s parameters: + for (let [name, value] of parameters.entries()) { + // 1. Append U+003B (;) to serialization. + serialization += ';' + + // 2. Append name to serialization. + serialization += name + + // 3. Append U+003D (=) to serialization. + serialization += '=' + + // 4. If value does not solely contain HTTP token code + // points or value is the empty string, then: + if (!HTTP_TOKEN_CODEPOINTS.test(value)) { + // 1. Precede each occurence of U+0022 (") or + // U+005C (\) in value with U+005C (\). + value = value.replace(/(\\|")/g, '\\$1') + + // 2. Prepend U+0022 (") to value. + value = '"' + value + + // 3. Append U+0022 (") to value. + value += '"' + } + + // 5. Append value to serialization. + serialization += value + } + + // 3. Return serialization. + return serialization +} + +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} char + */ +function isHTTPWhiteSpace (char) { + return char === '\r' || char === '\n' || char === '\t' || char === ' ' +} + +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} str + */ +function removeHTTPWhitespace (str, leading = true, trailing = true) { + let lead = 0 + let trail = str.length - 1 + + if (leading) { + for (; lead < str.length && isHTTPWhiteSpace(str[lead]); lead++); + } + + if (trailing) { + for (; trail > 0 && isHTTPWhiteSpace(str[trail]); trail--); + } + + return str.slice(lead, trail + 1) +} + +/** + * @see https://infra.spec.whatwg.org/#ascii-whitespace + * @param {string} char + */ +function isASCIIWhitespace (char) { + return char === '\r' || char === '\n' || char === '\t' || char === '\f' || char === ' ' +} + +/** + * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace + */ +function removeASCIIWhitespace (str, leading = true, trailing = true) { + let lead = 0 + let trail = str.length - 1 + + if (leading) { + for (; lead < str.length && isASCIIWhitespace(str[lead]); lead++); + } + + if (trailing) { + for (; trail > 0 && isASCIIWhitespace(str[trail]); trail--); + } + + return str.slice(lead, trail + 1) +} + +module.exports = { + dataURLProcessor, + URLSerializer, + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + stringPercentDecode, + parseMIMEType, + collectAnHTTPQuotedString, + serializeAMimeType +} + + +/***/ }), + +/***/ 63041: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Blob, File: NativeFile } = __nccwpck_require__(20181) +const { types } = __nccwpck_require__(39023) +const { kState } = __nccwpck_require__(89710) +const { isBlobLike } = __nccwpck_require__(15523) +const { webidl } = __nccwpck_require__(74222) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(94322) +const { kEnumerableProperty } = __nccwpck_require__(3440) +const encoder = new TextEncoder() + +class File extends Blob { + constructor (fileBits, fileName, options = {}) { + // The File constructor is invoked with two or three parameters, depending + // on whether the optional dictionary parameter is used. When the File() + // constructor is invoked, user agents must run the following steps: + webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' }) + + fileBits = webidl.converters['sequence'](fileBits) + fileName = webidl.converters.USVString(fileName) + options = webidl.converters.FilePropertyBag(options) + + // 1. Let bytes be the result of processing blob parts given fileBits and + // options. + // Note: Blob handles this for us + + // 2. Let n be the fileName argument to the constructor. + const n = fileName + + // 3. Process FilePropertyBag dictionary argument by running the following + // substeps: + + // 1. If the type member is provided and is not the empty string, let t + // be set to the type dictionary member. If t contains any characters + // outside the range U+0020 to U+007E, then set t to the empty string + // and return from these substeps. + // 2. Convert every character in t to ASCII lowercase. + let t = options.type + let d + + // eslint-disable-next-line no-labels + substep: { + if (t) { + t = parseMIMEType(t) + + if (t === 'failure') { + t = '' + // eslint-disable-next-line no-labels + break substep + } + + t = serializeAMimeType(t).toLowerCase() + } + + // 3. If the lastModified member is provided, let d be set to the + // lastModified dictionary member. If it is not provided, set d to the + // current date and time represented as the number of milliseconds since + // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). + d = options.lastModified + } + + // 4. Return a new File object F such that: + // F refers to the bytes byte sequence. + // F.size is set to the number of total bytes in bytes. + // F.name is set to n. + // F.type is set to t. + // F.lastModified is set to d. + + super(processBlobParts(fileBits, options), { type: t }) + this[kState] = { + name: n, + lastModified: d, + type: t + } + } + + get name () { + webidl.brandCheck(this, File) + + return this[kState].name + } + + get lastModified () { + webidl.brandCheck(this, File) + + return this[kState].lastModified + } + + get type () { + webidl.brandCheck(this, File) + + return this[kState].type + } +} + +class FileLike { + constructor (blobLike, fileName, options = {}) { + // TODO: argument idl type check + + // The File constructor is invoked with two or three parameters, depending + // on whether the optional dictionary parameter is used. When the File() + // constructor is invoked, user agents must run the following steps: + + // 1. Let bytes be the result of processing blob parts given fileBits and + // options. + + // 2. Let n be the fileName argument to the constructor. + const n = fileName + + // 3. Process FilePropertyBag dictionary argument by running the following + // substeps: + + // 1. If the type member is provided and is not the empty string, let t + // be set to the type dictionary member. If t contains any characters + // outside the range U+0020 to U+007E, then set t to the empty string + // and return from these substeps. + // TODO + const t = options.type + + // 2. Convert every character in t to ASCII lowercase. + // TODO + + // 3. If the lastModified member is provided, let d be set to the + // lastModified dictionary member. If it is not provided, set d to the + // current date and time represented as the number of milliseconds since + // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). + const d = options.lastModified ?? Date.now() + + // 4. Return a new File object F such that: + // F refers to the bytes byte sequence. + // F.size is set to the number of total bytes in bytes. + // F.name is set to n. + // F.type is set to t. + // F.lastModified is set to d. + + this[kState] = { + blobLike, + name: n, + type: t, + lastModified: d + } + } + + stream (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.stream(...args) + } + + arrayBuffer (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.arrayBuffer(...args) + } + + slice (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.slice(...args) + } + + text (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.text(...args) + } + + get size () { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.size + } + + get type () { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.type + } + + get name () { + webidl.brandCheck(this, FileLike) + + return this[kState].name + } + + get lastModified () { + webidl.brandCheck(this, FileLike) + + return this[kState].lastModified + } + + get [Symbol.toStringTag] () { + return 'File' + } +} + +Object.defineProperties(File.prototype, { + [Symbol.toStringTag]: { + value: 'File', + configurable: true + }, + name: kEnumerableProperty, + lastModified: kEnumerableProperty +}) + +webidl.converters.Blob = webidl.interfaceConverter(Blob) + +webidl.converters.BlobPart = function (V, opts) { + if (webidl.util.Type(V) === 'Object') { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if ( + ArrayBuffer.isView(V) || + types.isAnyArrayBuffer(V) + ) { + return webidl.converters.BufferSource(V, opts) + } + } + + return webidl.converters.USVString(V, opts) +} + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.BlobPart +) + +// https://www.w3.org/TR/FileAPI/#dfn-FilePropertyBag +webidl.converters.FilePropertyBag = webidl.dictionaryConverter([ + { + key: 'lastModified', + converter: webidl.converters['long long'], + get defaultValue () { + return Date.now() + } + }, + { + key: 'type', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'endings', + converter: (value) => { + value = webidl.converters.DOMString(value) + value = value.toLowerCase() + + if (value !== 'native') { + value = 'transparent' + } + + return value + }, + defaultValue: 'transparent' + } +]) + +/** + * @see https://www.w3.org/TR/FileAPI/#process-blob-parts + * @param {(NodeJS.TypedArray|Blob|string)[]} parts + * @param {{ type: string, endings: string }} options + */ +function processBlobParts (parts, options) { + // 1. Let bytes be an empty sequence of bytes. + /** @type {NodeJS.TypedArray[]} */ + const bytes = [] + + // 2. For each element in parts: + for (const element of parts) { + // 1. If element is a USVString, run the following substeps: + if (typeof element === 'string') { + // 1. Let s be element. + let s = element + + // 2. If the endings member of options is "native", set s + // to the result of converting line endings to native + // of element. + if (options.endings === 'native') { + s = convertLineEndingsNative(s) + } + + // 3. Append the result of UTF-8 encoding s to bytes. + bytes.push(encoder.encode(s)) + } else if ( + types.isAnyArrayBuffer(element) || + types.isTypedArray(element) + ) { + // 2. If element is a BufferSource, get a copy of the + // bytes held by the buffer source, and append those + // bytes to bytes. + if (!element.buffer) { // ArrayBuffer + bytes.push(new Uint8Array(element)) + } else { + bytes.push( + new Uint8Array(element.buffer, element.byteOffset, element.byteLength) + ) + } + } else if (isBlobLike(element)) { + // 3. If element is a Blob, append the bytes it represents + // to bytes. + bytes.push(element) + } + } + + // 3. Return bytes. + return bytes +} + +/** + * @see https://www.w3.org/TR/FileAPI/#convert-line-endings-to-native + * @param {string} s + */ +function convertLineEndingsNative (s) { + // 1. Let native line ending be be the code point U+000A LF. + let nativeLineEnding = '\n' + + // 2. If the underlying platform’s conventions are to + // represent newlines as a carriage return and line feed + // sequence, set native line ending to the code point + // U+000D CR followed by the code point U+000A LF. + if (process.platform === 'win32') { + nativeLineEnding = '\r\n' + } + + return s.replace(/\r?\n/g, nativeLineEnding) +} + +// If this function is moved to ./util.js, some tools (such as +// rollup) will warn about circular dependencies. See: +// https://github.com/nodejs/undici/issues/1629 +function isFileLike (object) { + return ( + (NativeFile && object instanceof NativeFile) || + object instanceof File || ( + object && + (typeof object.stream === 'function' || + typeof object.arrayBuffer === 'function') && + object[Symbol.toStringTag] === 'File' + ) + ) +} + +module.exports = { File, FileLike, isFileLike } + + +/***/ }), + +/***/ 43073: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(15523) +const { kState } = __nccwpck_require__(89710) +const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(63041) +const { webidl } = __nccwpck_require__(74222) +const { Blob, File: NativeFile } = __nccwpck_require__(20181) + +/** @type {globalThis['File']} */ +const File = NativeFile ?? UndiciFile + +// https://xhr.spec.whatwg.org/#formdata +class FormData { + constructor (form) { + if (form !== undefined) { + throw webidl.errors.conversionFailed({ + prefix: 'FormData constructor', + argument: 'Argument 1', + types: ['undefined'] + }) + } + + this[kState] = [] + } + + append (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.append' }) + + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } + + // 1. Let value be value if given; otherwise blobValue. + + name = webidl.converters.USVString(name) + value = isBlobLike(value) + ? webidl.converters.Blob(value, { strict: false }) + : webidl.converters.USVString(value) + filename = arguments.length === 3 + ? webidl.converters.USVString(filename) + : undefined + + // 2. Let entry be the result of creating an entry with + // name, value, and filename if given. + const entry = makeEntry(name, value, filename) + + // 3. Append entry to this’s entry list. + this[kState].push(entry) + } + + delete (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.delete' }) + + name = webidl.converters.USVString(name) + + // The delete(name) method steps are to remove all entries whose name + // is name from this’s entry list. + this[kState] = this[kState].filter(entry => entry.name !== name) + } + + get (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.get' }) + + name = webidl.converters.USVString(name) + + // 1. If there is no entry whose name is name in this’s entry list, + // then return null. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx === -1) { + return null + } + + // 2. Return the value of the first entry whose name is name from + // this’s entry list. + return this[kState][idx].value + } + + getAll (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.getAll' }) + + name = webidl.converters.USVString(name) + + // 1. If there is no entry whose name is name in this’s entry list, + // then return the empty list. + // 2. Return the values of all entries whose name is name, in order, + // from this’s entry list. + return this[kState] + .filter((entry) => entry.name === name) + .map((entry) => entry.value) + } + + has (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.has' }) + + name = webidl.converters.USVString(name) + + // The has(name) method steps are to return true if there is an entry + // whose name is name in this’s entry list; otherwise false. + return this[kState].findIndex((entry) => entry.name === name) !== -1 + } + + set (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.set' }) + + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } + + // The set(name, value) and set(name, blobValue, filename) method steps + // are: + + // 1. Let value be value if given; otherwise blobValue. + + name = webidl.converters.USVString(name) + value = isBlobLike(value) + ? webidl.converters.Blob(value, { strict: false }) + : webidl.converters.USVString(value) + filename = arguments.length === 3 + ? toUSVString(filename) + : undefined + + // 2. Let entry be the result of creating an entry with name, value, and + // filename if given. + const entry = makeEntry(name, value, filename) + + // 3. If there are entries in this’s entry list whose name is name, then + // replace the first such entry with entry and remove the others. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx !== -1) { + this[kState] = [ + ...this[kState].slice(0, idx), + entry, + ...this[kState].slice(idx + 1).filter((entry) => entry.name !== name) + ] + } else { + // 4. Otherwise, append entry to this’s entry list. + this[kState].push(entry) + } + } + + entries () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'key+value' + ) + } + + keys () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'key' + ) + } + + values () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'value' + ) + } + + /** + * @param {(value: string, key: string, self: FormData) => void} callbackFn + * @param {unknown} thisArg + */ + forEach (callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.forEach' }) + + if (typeof callbackFn !== 'function') { + throw new TypeError( + "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'." + ) + } + + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]) + } + } +} + +FormData.prototype[Symbol.iterator] = FormData.prototype.entries + +Object.defineProperties(FormData.prototype, { + [Symbol.toStringTag]: { + value: 'FormData', + configurable: true + } +}) + +/** + * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry + * @param {string} name + * @param {string|Blob} value + * @param {?string} filename + * @returns + */ +function makeEntry (name, value, filename) { + // 1. Set name to the result of converting name into a scalar value string. + // "To convert a string into a scalar value string, replace any surrogates + // with U+FFFD." + // see: https://nodejs.org/dist/latest-v18.x/docs/api/buffer.html#buftostringencoding-start-end + name = Buffer.from(name).toString('utf8') + + // 2. If value is a string, then set value to the result of converting + // value into a scalar value string. + if (typeof value === 'string') { + value = Buffer.from(value).toString('utf8') + } else { + // 3. Otherwise: + + // 1. If value is not a File object, then set value to a new File object, + // representing the same bytes, whose name attribute value is "blob" + if (!isFileLike(value)) { + value = value instanceof Blob + ? new File([value], 'blob', { type: value.type }) + : new FileLike(value, 'blob', { type: value.type }) + } + + // 2. If filename is given, then set value to a new File object, + // representing the same bytes, whose name attribute is filename. + if (filename !== undefined) { + /** @type {FilePropertyBag} */ + const options = { + type: value.type, + lastModified: value.lastModified + } + + value = (NativeFile && value instanceof NativeFile) || value instanceof UndiciFile + ? new File([value], filename, options) + : new FileLike(value, filename, options) + } + } + + // 4. Return an entry whose name is name and whose value is value. + return { name, value } +} + +module.exports = { FormData } + + +/***/ }), + +/***/ 75628: +/***/ ((module) => { + +"use strict"; + + +// In case of breaking changes, increase the version +// number to avoid conflicts. +const globalOrigin = Symbol.for('undici.globalOrigin.1') + +function getGlobalOrigin () { + return globalThis[globalOrigin] +} + +function setGlobalOrigin (newOrigin) { + if (newOrigin === undefined) { + Object.defineProperty(globalThis, globalOrigin, { + value: undefined, + writable: true, + enumerable: false, + configurable: false + }) + + return + } + + const parsedURL = new URL(newOrigin) + + if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') { + throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`) + } + + Object.defineProperty(globalThis, globalOrigin, { + value: parsedURL, + writable: true, + enumerable: false, + configurable: false + }) +} + +module.exports = { + getGlobalOrigin, + setGlobalOrigin +} + + +/***/ }), + +/***/ 26349: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch + + + +const { kHeadersList, kConstruct } = __nccwpck_require__(36443) +const { kGuard } = __nccwpck_require__(89710) +const { kEnumerableProperty } = __nccwpck_require__(3440) +const { + makeIterator, + isValidHeaderName, + isValidHeaderValue +} = __nccwpck_require__(15523) +const util = __nccwpck_require__(39023) +const { webidl } = __nccwpck_require__(74222) +const assert = __nccwpck_require__(42613) + +const kHeadersMap = Symbol('headers map') +const kHeadersSortedMap = Symbol('headers map sorted') + +/** + * @param {number} code + */ +function isHTTPWhiteSpaceCharCode (code) { + return code === 0x00a || code === 0x00d || code === 0x009 || code === 0x020 +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize + * @param {string} potentialValue + */ +function headerValueNormalize (potentialValue) { + // To normalize a byte sequence potentialValue, remove + // any leading and trailing HTTP whitespace bytes from + // potentialValue. + let i = 0; let j = potentialValue.length + + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i + + return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) +} + +function fill (headers, object) { + // To fill a Headers object headers with a given object object, run these steps: + + // 1. If object is a sequence, then for each header in object: + // Note: webidl conversion to array has already been done. + if (Array.isArray(object)) { + for (let i = 0; i < object.length; ++i) { + const header = object[i] + // 1. If header does not contain exactly two items, then throw a TypeError. + if (header.length !== 2) { + throw webidl.errors.exception({ + header: 'Headers constructor', + message: `expected name/value pair to be length 2, found ${header.length}.` + }) + } + + // 2. Append (header’s first item, header’s second item) to headers. + appendHeader(headers, header[0], header[1]) + } + } else if (typeof object === 'object' && object !== null) { + // Note: null should throw + + // 2. Otherwise, object is a record, then for each key → value in object, + // append (key, value) to headers + const keys = Object.keys(object) + for (let i = 0; i < keys.length; ++i) { + appendHeader(headers, keys[i], object[keys[i]]) + } + } else { + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) + } +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-headers-append + */ +function appendHeader (headers, name, value) { + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value, + type: 'header value' + }) + } + + // 3. If headers’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if headers’s guard is "request" and name is a + // forbidden header name, return. + // Note: undici does not implement forbidden header names + if (headers[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (headers[kGuard] === 'request-no-cors') { + // 5. Otherwise, if headers’s guard is "request-no-cors": + // TODO + } + + // 6. Otherwise, if headers’s guard is "response" and name is a + // forbidden response-header name, return. + + // 7. Append (name, value) to headers’s header list. + return headers[kHeadersList].append(name, value) + + // 8. If headers’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from headers +} + +class HeadersList { + /** @type {[string, string][]|null} */ + cookies = null + + constructor (init) { + if (init instanceof HeadersList) { + this[kHeadersMap] = new Map(init[kHeadersMap]) + this[kHeadersSortedMap] = init[kHeadersSortedMap] + this.cookies = init.cookies === null ? null : [...init.cookies] + } else { + this[kHeadersMap] = new Map(init) + this[kHeadersSortedMap] = null + } + } + + // https://fetch.spec.whatwg.org/#header-list-contains + contains (name) { + // A header list list contains a header name name if list + // contains a header whose name is a byte-case-insensitive + // match for name. + name = name.toLowerCase() + + return this[kHeadersMap].has(name) + } + + clear () { + this[kHeadersMap].clear() + this[kHeadersSortedMap] = null + this.cookies = null + } + + // https://fetch.spec.whatwg.org/#concept-header-list-append + append (name, value) { + this[kHeadersSortedMap] = null + + // 1. If list contains name, then set name to the first such + // header’s name. + const lowercaseName = name.toLowerCase() + const exists = this[kHeadersMap].get(lowercaseName) + + // 2. Append (name, value) to list. + if (exists) { + const delimiter = lowercaseName === 'cookie' ? '; ' : ', ' + this[kHeadersMap].set(lowercaseName, { + name: exists.name, + value: `${exists.value}${delimiter}${value}` + }) + } else { + this[kHeadersMap].set(lowercaseName, { name, value }) + } + + if (lowercaseName === 'set-cookie') { + this.cookies ??= [] + this.cookies.push(value) + } + } + + // https://fetch.spec.whatwg.org/#concept-header-list-set + set (name, value) { + this[kHeadersSortedMap] = null + const lowercaseName = name.toLowerCase() + + if (lowercaseName === 'set-cookie') { + this.cookies = [value] + } + + // 1. If list contains name, then set the value of + // the first such header to value and remove the + // others. + // 2. Otherwise, append header (name, value) to list. + this[kHeadersMap].set(lowercaseName, { name, value }) + } + + // https://fetch.spec.whatwg.org/#concept-header-list-delete + delete (name) { + this[kHeadersSortedMap] = null + + name = name.toLowerCase() + + if (name === 'set-cookie') { + this.cookies = null + } + + this[kHeadersMap].delete(name) + } + + // https://fetch.spec.whatwg.org/#concept-header-list-get + get (name) { + const value = this[kHeadersMap].get(name.toLowerCase()) + + // 1. If list does not contain name, then return null. + // 2. Return the values of all headers in list whose name + // is a byte-case-insensitive match for name, + // separated from each other by 0x2C 0x20, in order. + return value === undefined ? null : value.value + } + + * [Symbol.iterator] () { + // use the lowercased name + for (const [name, { value }] of this[kHeadersMap]) { + yield [name, value] + } + } + + get entries () { + const headers = {} + + if (this[kHeadersMap].size) { + for (const { name, value } of this[kHeadersMap].values()) { + headers[name] = value + } + } + + return headers + } +} + +// https://fetch.spec.whatwg.org/#headers-class +class Headers { + constructor (init = undefined) { + if (init === kConstruct) { + return + } + this[kHeadersList] = new HeadersList() + + // The new Headers(init) constructor steps are: + + // 1. Set this’s guard to "none". + this[kGuard] = 'none' + + // 2. If init is given, then fill this with init. + if (init !== undefined) { + init = webidl.converters.HeadersInit(init) + fill(this, init) + } + } + + // https://fetch.spec.whatwg.org/#dom-headers-append + append (name, value) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.append' }) + + name = webidl.converters.ByteString(name) + value = webidl.converters.ByteString(value) + + return appendHeader(this, name, value) + } + + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.delete' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.delete', + value: name, + type: 'header name' + }) + } + + // 2. If this’s guard is "immutable", then throw a TypeError. + // 3. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 4. Otherwise, if this’s guard is "request-no-cors", name + // is not a no-CORS-safelisted request-header name, and + // name is not a privileged no-CORS request-header name, + // return. + // 5. Otherwise, if this’s guard is "response" and name is + // a forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (this[kGuard] === 'request-no-cors') { + // TODO + } + + // 6. If this’s header list does not contain name, then + // return. + if (!this[kHeadersList].contains(name)) { + return + } + + // 7. Delete name from this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this. + this[kHeadersList].delete(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-get + get (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.get' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.get', + value: name, + type: 'header name' + }) + } + + // 2. Return the result of getting name from this’s header + // list. + return this[kHeadersList].get(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-has + has (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.has' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.has', + value: name, + type: 'header name' + }) + } + + // 2. Return true if this’s header list contains name; + // otherwise false. + return this[kHeadersList].contains(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-set + set (name, value) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.set' }) + + name = webidl.converters.ByteString(name) + value = webidl.converters.ByteString(value) + + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.set', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.set', + value, + type: 'header value' + }) + } + + // 3. If this’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 5. Otherwise, if this’s guard is "request-no-cors" and + // name/value is not a no-CORS-safelisted request-header, + // return. + // 6. Otherwise, if this’s guard is "response" and name is a + // forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (this[kGuard] === 'request-no-cors') { + // TODO + } + + // 7. Set (name, value) in this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this + this[kHeadersList].set(name, value) + } + + // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie + getSetCookie () { + webidl.brandCheck(this, Headers) + + // 1. If this’s header list does not contain `Set-Cookie`, then return « ». + // 2. Return the values of all headers in this’s header list whose name is + // a byte-case-insensitive match for `Set-Cookie`, in order. + + const list = this[kHeadersList].cookies + + if (list) { + return [...list] + } + + return [] + } + + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + get [kHeadersSortedMap] () { + if (this[kHeadersList][kHeadersSortedMap]) { + return this[kHeadersList][kHeadersSortedMap] + } + + // 1. Let headers be an empty list of headers with the key being the name + // and value the value. + const headers = [] + + // 2. Let names be the result of convert header names to a sorted-lowercase + // set with all the names of the headers in list. + const names = [...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1) + const cookies = this[kHeadersList].cookies + + // 3. For each name of names: + for (let i = 0; i < names.length; ++i) { + const [name, value] = names[i] + // 1. If name is `set-cookie`, then: + if (name === 'set-cookie') { + // 1. Let values be a list of all values of headers in list whose name + // is a byte-case-insensitive match for name, in order. + + // 2. For each value of values: + // 1. Append (name, value) to headers. + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]) + } + } else { + // 2. Otherwise: + + // 1. Let value be the result of getting name from list. + + // 2. Assert: value is non-null. + assert(value !== null) + + // 3. Append (name, value) to headers. + headers.push([name, value]) + } + } + + this[kHeadersList][kHeadersSortedMap] = headers + + // 4. Return headers. + return headers + } + + keys () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'key' + ) + } + + values () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'value') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'value' + ) + } + + entries () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key+value') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'key+value' + ) + } + + /** + * @param {(value: string, key: string, self: Headers) => void} callbackFn + * @param {unknown} thisArg + */ + forEach (callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.forEach' }) + + if (typeof callbackFn !== 'function') { + throw new TypeError( + "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." + ) + } + + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]) + } + } + + [Symbol.for('nodejs.util.inspect.custom')] () { + webidl.brandCheck(this, Headers) + + return this[kHeadersList] + } +} + +Headers.prototype[Symbol.iterator] = Headers.prototype.entries + +Object.defineProperties(Headers.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + getSetCookie: kEnumerableProperty, + keys: kEnumerableProperty, + values: kEnumerableProperty, + entries: kEnumerableProperty, + forEach: kEnumerableProperty, + [Symbol.iterator]: { enumerable: false }, + [Symbol.toStringTag]: { + value: 'Headers', + configurable: true + }, + [util.inspect.custom]: { + enumerable: false + } +}) + +webidl.converters.HeadersInit = function (V) { + if (webidl.util.Type(V) === 'Object') { + if (V[Symbol.iterator]) { + return webidl.converters['sequence>'](V) + } + + return webidl.converters['record'](V) + } + + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) +} + +module.exports = { + fill, + Headers, + HeadersList +} + + +/***/ }), + +/***/ 12315: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch + + + +const { + Response, + makeNetworkError, + makeAppropriateNetworkError, + filterResponse, + makeResponse +} = __nccwpck_require__(48676) +const { Headers } = __nccwpck_require__(26349) +const { Request, makeRequest } = __nccwpck_require__(25194) +const zlib = __nccwpck_require__(43106) +const { + bytesMatch, + makePolicyContainer, + clonePolicyContainer, + requestBadPort, + TAOCheck, + appendRequestOriginHeader, + responseLocationURL, + requestCurrentURL, + setRequestReferrerPolicyOnRedirect, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + createOpaqueTimingInfo, + appendFetchMetadata, + corsCheck, + crossOriginResourcePolicyCheck, + determineRequestsReferrer, + coarsenedSharedCurrentTime, + createDeferredPromise, + isBlobLike, + sameOrigin, + isCancelled, + isAborted, + isErrorLike, + fullyReadBody, + readableStreamClose, + isomorphicEncode, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme +} = __nccwpck_require__(15523) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(89710) +const assert = __nccwpck_require__(42613) +const { safelyExtractBody } = __nccwpck_require__(8923) +const { + redirectStatusSet, + nullBodyStatus, + safeMethodsSet, + requestBodyHeader, + subresourceSet, + DOMException +} = __nccwpck_require__(87326) +const { kHeadersList } = __nccwpck_require__(36443) +const EE = __nccwpck_require__(24434) +const { Readable, pipeline } = __nccwpck_require__(2203) +const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(3440) +const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(94322) +const { TransformStream } = __nccwpck_require__(63774) +const { getGlobalDispatcher } = __nccwpck_require__(32581) +const { webidl } = __nccwpck_require__(74222) +const { STATUS_CODES } = __nccwpck_require__(58611) +const GET_OR_HEAD = ['GET', 'HEAD'] + +/** @type {import('buffer').resolveObjectURL} */ +let resolveObjectURL +let ReadableStream = globalThis.ReadableStream + +class Fetch extends EE { + constructor (dispatcher) { + super() + + this.dispatcher = dispatcher + this.connection = null + this.dump = false + this.state = 'ongoing' + // 2 terminated listeners get added per request, + // but only 1 gets removed. If there are 20 redirects, + // 21 listeners will be added. + // See https://github.com/nodejs/undici/issues/1711 + // TODO (fix): Find and fix root cause for leaked listener. + this.setMaxListeners(21) + } + + terminate (reason) { + if (this.state !== 'ongoing') { + return + } + + this.state = 'terminated' + this.connection?.destroy(reason) + this.emit('terminated', reason) + } + + // https://fetch.spec.whatwg.org/#fetch-controller-abort + abort (error) { + if (this.state !== 'ongoing') { + return + } + + // 1. Set controller’s state to "aborted". + this.state = 'aborted' + + // 2. Let fallbackError be an "AbortError" DOMException. + // 3. Set error to fallbackError if it is not given. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') + } + + // 4. Let serializedError be StructuredSerialize(error). + // If that threw an exception, catch it, and let + // serializedError be StructuredSerialize(fallbackError). + + // 5. Set controller’s serialized abort reason to serializedError. + this.serializedAbortReason = error + + this.connection?.destroy(error) + this.emit('terminated', error) + } +} + +// https://fetch.spec.whatwg.org/#fetch-method +function fetch (input, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'globalThis.fetch' }) + + // 1. Let p be a new promise. + const p = createDeferredPromise() + + // 2. Let requestObject be the result of invoking the initial value of + // Request as constructor with input and init as arguments. If this throws + // an exception, reject p with it and return p. + let requestObject + + try { + requestObject = new Request(input, init) + } catch (e) { + p.reject(e) + return p.promise + } + + // 3. Let request be requestObject’s request. + const request = requestObject[kState] + + // 4. If requestObject’s signal’s aborted flag is set, then: + if (requestObject.signal.aborted) { + // 1. Abort the fetch() call with p, request, null, and + // requestObject’s signal’s abort reason. + abortFetch(p, request, null, requestObject.signal.reason) + + // 2. Return p. + return p.promise + } + + // 5. Let globalObject be request’s client’s global object. + const globalObject = request.client.globalObject + + // 6. If globalObject is a ServiceWorkerGlobalScope object, then set + // request’s service-workers mode to "none". + if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') { + request.serviceWorkers = 'none' + } + + // 7. Let responseObject be null. + let responseObject = null + + // 8. Let relevantRealm be this’s relevant Realm. + const relevantRealm = null + + // 9. Let locallyAborted be false. + let locallyAborted = false + + // 10. Let controller be null. + let controller = null + + // 11. Add the following abort steps to requestObject’s signal: + addAbortListener( + requestObject.signal, + () => { + // 1. Set locallyAborted to true. + locallyAborted = true + + // 2. Assert: controller is non-null. + assert(controller != null) + + // 3. Abort controller with requestObject’s signal’s abort reason. + controller.abort(requestObject.signal.reason) + + // 4. Abort the fetch() call with p, request, responseObject, + // and requestObject’s signal’s abort reason. + abortFetch(p, request, responseObject, requestObject.signal.reason) + } + ) + + // 12. Let handleFetchDone given response response be to finalize and + // report timing with response, globalObject, and "fetch". + const handleFetchDone = (response) => + finalizeAndReportTiming(response, 'fetch') + + // 13. Set controller to the result of calling fetch given request, + // with processResponseEndOfBody set to handleFetchDone, and processResponse + // given response being these substeps: + + const processResponse = (response) => { + // 1. If locallyAborted is true, terminate these substeps. + if (locallyAborted) { + return Promise.resolve() + } + + // 2. If response’s aborted flag is set, then: + if (response.aborted) { + // 1. Let deserializedError be the result of deserialize a serialized + // abort reason given controller’s serialized abort reason and + // relevantRealm. + + // 2. Abort the fetch() call with p, request, responseObject, and + // deserializedError. + + abortFetch(p, request, responseObject, controller.serializedAbortReason) + return Promise.resolve() + } + + // 3. If response is a network error, then reject p with a TypeError + // and terminate these substeps. + if (response.type === 'error') { + p.reject( + Object.assign(new TypeError('fetch failed'), { cause: response.error }) + ) + return Promise.resolve() + } + + // 4. Set responseObject to the result of creating a Response object, + // given response, "immutable", and relevantRealm. + responseObject = new Response() + responseObject[kState] = response + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kHeadersList] = response.headersList + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + + // 5. Resolve p with responseObject. + p.resolve(responseObject) + } + + controller = fetching({ + request, + processResponseEndOfBody: handleFetchDone, + processResponse, + dispatcher: init.dispatcher ?? getGlobalDispatcher() // undici + }) + + // 14. Return p. + return p.promise +} + +// https://fetch.spec.whatwg.org/#finalize-and-report-timing +function finalizeAndReportTiming (response, initiatorType = 'other') { + // 1. If response is an aborted network error, then return. + if (response.type === 'error' && response.aborted) { + return + } + + // 2. If response’s URL list is null or empty, then return. + if (!response.urlList?.length) { + return + } + + // 3. Let originalURL be response’s URL list[0]. + const originalURL = response.urlList[0] + + // 4. Let timingInfo be response’s timing info. + let timingInfo = response.timingInfo + + // 5. Let cacheState be response’s cache state. + let cacheState = response.cacheState + + // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. + if (!urlIsHttpHttpsScheme(originalURL)) { + return + } + + // 7. If timingInfo is null, then return. + if (timingInfo === null) { + return + } + + // 8. If response’s timing allow passed flag is not set, then: + if (!response.timingAllowPassed) { + // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. + timingInfo = createOpaqueTimingInfo({ + startTime: timingInfo.startTime + }) + + // 2. Set cacheState to the empty string. + cacheState = '' + } + + // 9. Set timingInfo’s end time to the coarsened shared current time + // given global’s relevant settings object’s cross-origin isolated + // capability. + // TODO: given global’s relevant settings object’s cross-origin isolated + // capability? + timingInfo.endTime = coarsenedSharedCurrentTime() + + // 10. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo + + // 11. Mark resource timing for timingInfo, originalURL, initiatorType, + // global, and cacheState. + markResourceTiming( + timingInfo, + originalURL, + initiatorType, + globalThis, + cacheState + ) +} + +// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing +function markResourceTiming (timingInfo, originalURL, initiatorType, globalThis, cacheState) { + if (nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 2)) { + performance.markResourceTiming(timingInfo, originalURL.href, initiatorType, globalThis, cacheState) + } +} + +// https://fetch.spec.whatwg.org/#abort-fetch +function abortFetch (p, request, responseObject, error) { + // Note: AbortSignal.reason was added in node v17.2.0 + // which would give us an undefined error to reject with. + // Remove this once node v16 is no longer supported. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') + } + + // 1. Reject promise with error. + p.reject(error) + + // 2. If request’s body is not null and is readable, then cancel request’s + // body with error. + if (request.body != null && isReadable(request.body?.stream)) { + request.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) + } + + // 3. If responseObject is null, then return. + if (responseObject == null) { + return + } + + // 4. Let response be responseObject’s response. + const response = responseObject[kState] + + // 5. If response’s body is not null and is readable, then error response’s + // body with error. + if (response.body != null && isReadable(response.body?.stream)) { + response.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) + } +} + +// https://fetch.spec.whatwg.org/#fetching +function fetching ({ + request, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseEndOfBody, + processResponseConsumeBody, + useParallelQueue = false, + dispatcher // undici +}) { + // 1. Let taskDestination be null. + let taskDestination = null + + // 2. Let crossOriginIsolatedCapability be false. + let crossOriginIsolatedCapability = false + + // 3. If request’s client is non-null, then: + if (request.client != null) { + // 1. Set taskDestination to request’s client’s global object. + taskDestination = request.client.globalObject + + // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin + // isolated capability. + crossOriginIsolatedCapability = + request.client.crossOriginIsolatedCapability + } + + // 4. If useParallelQueue is true, then set taskDestination to the result of + // starting a new parallel queue. + // TODO + + // 5. Let timingInfo be a new fetch timing info whose start time and + // post-redirect start time are the coarsened shared current time given + // crossOriginIsolatedCapability. + const currenTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability) + const timingInfo = createOpaqueTimingInfo({ + startTime: currenTime + }) + + // 6. Let fetchParams be a new fetch params whose + // request is request, + // timing info is timingInfo, + // process request body chunk length is processRequestBodyChunkLength, + // process request end-of-body is processRequestEndOfBody, + // process response is processResponse, + // process response consume body is processResponseConsumeBody, + // process response end-of-body is processResponseEndOfBody, + // task destination is taskDestination, + // and cross-origin isolated capability is crossOriginIsolatedCapability. + const fetchParams = { + controller: new Fetch(dispatcher), + request, + timingInfo, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseConsumeBody, + processResponseEndOfBody, + taskDestination, + crossOriginIsolatedCapability + } + + // 7. If request’s body is a byte sequence, then set request’s body to + // request’s body as a body. + // NOTE: Since fetching is only called from fetch, body should already be + // extracted. + assert(!request.body || request.body.stream) + + // 8. If request’s window is "client", then set request’s window to request’s + // client, if request’s client’s global object is a Window object; otherwise + // "no-window". + if (request.window === 'client') { + // TODO: What if request.client is null? + request.window = + request.client?.globalObject?.constructor?.name === 'Window' + ? request.client + : 'no-window' + } + + // 9. If request’s origin is "client", then set request’s origin to request’s + // client’s origin. + if (request.origin === 'client') { + // TODO: What if request.client is null? + request.origin = request.client?.origin + } + + // 10. If all of the following conditions are true: + // TODO + + // 11. If request’s policy container is "client", then: + if (request.policyContainer === 'client') { + // 1. If request’s client is non-null, then set request’s policy + // container to a clone of request’s client’s policy container. [HTML] + if (request.client != null) { + request.policyContainer = clonePolicyContainer( + request.client.policyContainer + ) + } else { + // 2. Otherwise, set request’s policy container to a new policy + // container. + request.policyContainer = makePolicyContainer() + } + } + + // 12. If request’s header list does not contain `Accept`, then: + if (!request.headersList.contains('accept')) { + // 1. Let value be `*/*`. + const value = '*/*' + + // 2. A user agent should set value to the first matching statement, if + // any, switching on request’s destination: + // "document" + // "frame" + // "iframe" + // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` + // "image" + // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` + // "style" + // `text/css,*/*;q=0.1` + // TODO + + // 3. Append `Accept`/value to request’s header list. + request.headersList.append('accept', value) + } + + // 13. If request’s header list does not contain `Accept-Language`, then + // user agents should append `Accept-Language`/an appropriate value to + // request’s header list. + if (!request.headersList.contains('accept-language')) { + request.headersList.append('accept-language', '*') + } + + // 14. If request’s priority is null, then use request’s initiator and + // destination appropriately in setting request’s priority to a + // user-agent-defined object. + if (request.priority === null) { + // TODO + } + + // 15. If request is a subresource request, then: + if (subresourceSet.has(request.destination)) { + // TODO + } + + // 16. Run main fetch given fetchParams. + mainFetch(fetchParams) + .catch(err => { + fetchParams.controller.terminate(err) + }) + + // 17. Return fetchParam's controller + return fetchParams.controller +} + +// https://fetch.spec.whatwg.org/#concept-main-fetch +async function mainFetch (fetchParams, recursive = false) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. If request’s local-URLs-only flag is set and request’s current URL is + // not local, then set response to a network error. + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { + response = makeNetworkError('local URLs only') + } + + // 4. Run report Content Security Policy violations for request. + // TODO + + // 5. Upgrade request to a potentially trustworthy URL, if appropriate. + tryUpgradeRequestToAPotentiallyTrustworthyURL(request) + + // 6. If should request be blocked due to a bad port, should fetching request + // be blocked as mixed content, or should request be blocked by Content + // Security Policy returns blocked, then set response to a network error. + if (requestBadPort(request) === 'blocked') { + response = makeNetworkError('bad port') + } + // TODO: should fetching request be blocked as mixed content? + // TODO: should request be blocked by Content Security Policy? + + // 7. If request’s referrer policy is the empty string, then set request’s + // referrer policy to request’s policy container’s referrer policy. + if (request.referrerPolicy === '') { + request.referrerPolicy = request.policyContainer.referrerPolicy + } + + // 8. If request’s referrer is not "no-referrer", then set request’s + // referrer to the result of invoking determine request’s referrer. + if (request.referrer !== 'no-referrer') { + request.referrer = determineRequestsReferrer(request) + } + + // 9. Set request’s current URL’s scheme to "https" if all of the following + // conditions are true: + // - request’s current URL’s scheme is "http" + // - request’s current URL’s host is a domain + // - Matching request’s current URL’s host per Known HSTS Host Domain Name + // Matching results in either a superdomain match with an asserted + // includeSubDomains directive or a congruent match (with or without an + // asserted includeSubDomains directive). [HSTS] + // TODO + + // 10. If recursive is false, then run the remaining steps in parallel. + // TODO + + // 11. If response is null, then set response to the result of running + // the steps corresponding to the first matching statement: + if (response === null) { + response = await (async () => { + const currentURL = requestCurrentURL(request) + + if ( + // - request’s current URL’s origin is same origin with request’s origin, + // and request’s response tainting is "basic" + (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') || + // request’s current URL’s scheme is "data" + (currentURL.protocol === 'data:') || + // - request’s mode is "navigate" or "websocket" + (request.mode === 'navigate' || request.mode === 'websocket') + ) { + // 1. Set request’s response tainting to "basic". + request.responseTainting = 'basic' + + // 2. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) + } + + // request’s mode is "same-origin" + if (request.mode === 'same-origin') { + // 1. Return a network error. + return makeNetworkError('request mode cannot be "same-origin"') + } + + // request’s mode is "no-cors" + if (request.mode === 'no-cors') { + // 1. If request’s redirect mode is not "follow", then return a network + // error. + if (request.redirect !== 'follow') { + return makeNetworkError( + 'redirect mode cannot be "follow" for "no-cors" request' + ) + } + + // 2. Set request’s response tainting to "opaque". + request.responseTainting = 'opaque' + + // 3. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) + } + + // request’s current URL’s scheme is not an HTTP(S) scheme + if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { + // Return a network error. + return makeNetworkError('URL scheme must be a HTTP(S) scheme') + } + + // - request’s use-CORS-preflight flag is set + // - request’s unsafe-request flag is set and either request’s method is + // not a CORS-safelisted method or CORS-unsafe request-header names with + // request’s header list is not empty + // 1. Set request’s response tainting to "cors". + // 2. Let corsWithPreflightResponse be the result of running HTTP fetch + // given fetchParams and true. + // 3. If corsWithPreflightResponse is a network error, then clear cache + // entries using request. + // 4. Return corsWithPreflightResponse. + // TODO + + // Otherwise + // 1. Set request’s response tainting to "cors". + request.responseTainting = 'cors' + + // 2. Return the result of running HTTP fetch given fetchParams. + return await httpFetch(fetchParams) + })() + } + + // 12. If recursive is true, then return response. + if (recursive) { + return response + } + + // 13. If response is not a network error and response is not a filtered + // response, then: + if (response.status !== 0 && !response.internalResponse) { + // If request’s response tainting is "cors", then: + if (request.responseTainting === 'cors') { + // 1. Let headerNames be the result of extracting header list values + // given `Access-Control-Expose-Headers` and response’s header list. + // TODO + // 2. If request’s credentials mode is not "include" and headerNames + // contains `*`, then set response’s CORS-exposed header-name list to + // all unique header names in response’s header list. + // TODO + // 3. Otherwise, if headerNames is not null or failure, then set + // response’s CORS-exposed header-name list to headerNames. + // TODO + } + + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (request.responseTainting === 'basic') { + response = filterResponse(response, 'basic') + } else if (request.responseTainting === 'cors') { + response = filterResponse(response, 'cors') + } else if (request.responseTainting === 'opaque') { + response = filterResponse(response, 'opaque') + } else { + assert(false) + } + } + + // 14. Let internalResponse be response, if response is a network error, + // and response’s internal response otherwise. + let internalResponse = + response.status === 0 ? response : response.internalResponse + + // 15. If internalResponse’s URL list is empty, then set it to a clone of + // request’s URL list. + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request.urlList) + } + + // 16. If request’s timing allow failed flag is unset, then set + // internalResponse’s timing allow passed flag. + if (!request.timingAllowFailed) { + response.timingAllowPassed = true + } + + // 17. If response is not a network error and any of the following returns + // blocked + // - should internalResponse to request be blocked as mixed content + // - should internalResponse to request be blocked by Content Security Policy + // - should internalResponse to request be blocked due to its MIME type + // - should internalResponse to request be blocked due to nosniff + // TODO + + // 18. If response’s type is "opaque", internalResponse’s status is 206, + // internalResponse’s range-requested flag is set, and request’s header + // list does not contain `Range`, then set response and internalResponse + // to a network error. + if ( + response.type === 'opaque' && + internalResponse.status === 206 && + internalResponse.rangeRequested && + !request.headers.contains('range') + ) { + response = internalResponse = makeNetworkError() + } + + // 19. If response is not a network error and either request’s method is + // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status, + // set internalResponse’s body to null and disregard any enqueuing toward + // it (if any). + if ( + response.status !== 0 && + (request.method === 'HEAD' || + request.method === 'CONNECT' || + nullBodyStatus.includes(internalResponse.status)) + ) { + internalResponse.body = null + fetchParams.controller.dump = true + } + + // 20. If request’s integrity metadata is not the empty string, then: + if (request.integrity) { + // 1. Let processBodyError be this step: run fetch finale given fetchParams + // and a network error. + const processBodyError = (reason) => + fetchFinale(fetchParams, makeNetworkError(reason)) + + // 2. If request’s response tainting is "opaque", or response’s body is null, + // then run processBodyError and abort these steps. + if (request.responseTainting === 'opaque' || response.body == null) { + processBodyError(response.error) + return + } + + // 3. Let processBody given bytes be these steps: + const processBody = (bytes) => { + // 1. If bytes do not match request’s integrity metadata, + // then run processBodyError and abort these steps. [SRI] + if (!bytesMatch(bytes, request.integrity)) { + processBodyError('integrity mismatch') + return + } + + // 2. Set response’s body to bytes as a body. + response.body = safelyExtractBody(bytes)[0] + + // 3. Run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } + + // 4. Fully read response’s body given processBody and processBodyError. + await fullyReadBody(response.body, processBody, processBodyError) + } else { + // 21. Otherwise, run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } +} + +// https://fetch.spec.whatwg.org/#concept-scheme-fetch +// given a fetch params fetchParams +function schemeFetch (fetchParams) { + // Note: since the connection is destroyed on redirect, which sets fetchParams to a + // cancelled state, we do not want this condition to trigger *unless* there have been + // no redirects. See https://github.com/nodejs/undici/issues/1776 + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { + return Promise.resolve(makeAppropriateNetworkError(fetchParams)) + } + + // 2. Let request be fetchParams’s request. + const { request } = fetchParams + + const { protocol: scheme } = requestCurrentURL(request) + + // 3. Switch on request’s current URL’s scheme and run the associated steps: + switch (scheme) { + case 'about:': { + // If request’s current URL’s path is the string "blank", then return a new response + // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) », + // and body is the empty byte sequence as a body. + + // Otherwise, return a network error. + return Promise.resolve(makeNetworkError('about scheme is not supported')) + } + case 'blob:': { + if (!resolveObjectURL) { + resolveObjectURL = (__nccwpck_require__(20181).resolveObjectURL) + } + + // 1. Let blobURLEntry be request’s current URL’s blob URL entry. + const blobURLEntry = requestCurrentURL(request) + + // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56 + // Buffer.resolveObjectURL does not ignore URL queries. + if (blobURLEntry.search.length !== 0) { + return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.')) + } + + const blobURLEntryObject = resolveObjectURL(blobURLEntry.toString()) + + // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s + // object is not a Blob object, then return a network error. + if (request.method !== 'GET' || !isBlobLike(blobURLEntryObject)) { + return Promise.resolve(makeNetworkError('invalid method')) + } + + // 3. Let bodyWithType be the result of safely extracting blobURLEntry’s object. + const bodyWithType = safelyExtractBody(blobURLEntryObject) + + // 4. Let body be bodyWithType’s body. + const body = bodyWithType[0] + + // 5. Let length be body’s length, serialized and isomorphic encoded. + const length = isomorphicEncode(`${body.length}`) + + // 6. Let type be bodyWithType’s type if it is non-null; otherwise the empty byte sequence. + const type = bodyWithType[1] ?? '' + + // 7. Return a new response whose status message is `OK`, header list is + // « (`Content-Length`, length), (`Content-Type`, type) », and body is body. + const response = makeResponse({ + statusText: 'OK', + headersList: [ + ['content-length', { name: 'Content-Length', value: length }], + ['content-type', { name: 'Content-Type', value: type }] + ] + }) + + response.body = body + + return Promise.resolve(response) + } + case 'data:': { + // 1. Let dataURLStruct be the result of running the + // data: URL processor on request’s current URL. + const currentURL = requestCurrentURL(request) + const dataURLStruct = dataURLProcessor(currentURL) + + // 2. If dataURLStruct is failure, then return a + // network error. + if (dataURLStruct === 'failure') { + return Promise.resolve(makeNetworkError('failed to fetch the data URL')) + } + + // 3. Let mimeType be dataURLStruct’s MIME type, serialized. + const mimeType = serializeAMimeType(dataURLStruct.mimeType) + + // 4. Return a response whose status message is `OK`, + // header list is « (`Content-Type`, mimeType) », + // and body is dataURLStruct’s body as a body. + return Promise.resolve(makeResponse({ + statusText: 'OK', + headersList: [ + ['content-type', { name: 'Content-Type', value: mimeType }] + ], + body: safelyExtractBody(dataURLStruct.body)[0] + })) + } + case 'file:': { + // For now, unfortunate as it is, file URLs are left as an exercise for the reader. + // When in doubt, return a network error. + return Promise.resolve(makeNetworkError('not implemented... yet...')) + } + case 'http:': + case 'https:': { + // Return the result of running HTTP fetch given fetchParams. + + return httpFetch(fetchParams) + .catch((err) => makeNetworkError(err)) + } + default: { + return Promise.resolve(makeNetworkError('unknown scheme')) + } + } +} + +// https://fetch.spec.whatwg.org/#finalize-response +function finalizeResponse (fetchParams, response) { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true + + // 2, If fetchParams’s process response done is not null, then queue a fetch + // task to run fetchParams’s process response done given response, with + // fetchParams’s task destination. + if (fetchParams.processResponseDone != null) { + queueMicrotask(() => fetchParams.processResponseDone(response)) + } +} + +// https://fetch.spec.whatwg.org/#fetch-finale +function fetchFinale (fetchParams, response) { + // 1. If response is a network error, then: + if (response.type === 'error') { + // 1. Set response’s URL list to « fetchParams’s request’s URL list[0] ». + response.urlList = [fetchParams.request.urlList[0]] + + // 2. Set response’s timing info to the result of creating an opaque timing + // info for fetchParams’s timing info. + response.timingInfo = createOpaqueTimingInfo({ + startTime: fetchParams.timingInfo.startTime + }) + } + + // 2. Let processResponseEndOfBody be the following steps: + const processResponseEndOfBody = () => { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true + + // If fetchParams’s process response end-of-body is not null, + // then queue a fetch task to run fetchParams’s process response + // end-of-body given response with fetchParams’s task destination. + if (fetchParams.processResponseEndOfBody != null) { + queueMicrotask(() => fetchParams.processResponseEndOfBody(response)) + } + } + + // 3. If fetchParams’s process response is non-null, then queue a fetch task + // to run fetchParams’s process response given response, with fetchParams’s + // task destination. + if (fetchParams.processResponse != null) { + queueMicrotask(() => fetchParams.processResponse(response)) + } + + // 4. If response’s body is null, then run processResponseEndOfBody. + if (response.body == null) { + processResponseEndOfBody() + } else { + // 5. Otherwise: + + // 1. Let transformStream be a new a TransformStream. + + // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, + // enqueues chunk in transformStream. + const identityTransformAlgorithm = (chunk, controller) => { + controller.enqueue(chunk) + } + + // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm + // and flushAlgorithm set to processResponseEndOfBody. + const transformStream = new TransformStream({ + start () {}, + transform: identityTransformAlgorithm, + flush: processResponseEndOfBody + }, { + size () { + return 1 + } + }, { + size () { + return 1 + } + }) + + // 4. Set response’s body to the result of piping response’s body through transformStream. + response.body = { stream: response.body.stream.pipeThrough(transformStream) } + } + + // 6. If fetchParams’s process response consume body is non-null, then: + if (fetchParams.processResponseConsumeBody != null) { + // 1. Let processBody given nullOrBytes be this step: run fetchParams’s + // process response consume body given response and nullOrBytes. + const processBody = (nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes) + + // 2. Let processBodyError be this step: run fetchParams’s process + // response consume body given response and failure. + const processBodyError = (failure) => fetchParams.processResponseConsumeBody(response, failure) + + // 3. If response’s body is null, then queue a fetch task to run processBody + // given null, with fetchParams’s task destination. + if (response.body == null) { + queueMicrotask(() => processBody(null)) + } else { + // 4. Otherwise, fully read response’s body given processBody, processBodyError, + // and fetchParams’s task destination. + return fullyReadBody(response.body, processBody, processBodyError) + } + return Promise.resolve() + } +} + +// https://fetch.spec.whatwg.org/#http-fetch +async function httpFetch (fetchParams) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. Let actualResponse be null. + let actualResponse = null + + // 4. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 5. If request’s service-workers mode is "all", then: + if (request.serviceWorkers === 'all') { + // TODO + } + + // 6. If response is null, then: + if (response === null) { + // 1. If makeCORSPreflight is true and one of these conditions is true: + // TODO + + // 2. If request’s redirect mode is "follow", then set request’s + // service-workers mode to "none". + if (request.redirect === 'follow') { + request.serviceWorkers = 'none' + } + + // 3. Set response and actualResponse to the result of running + // HTTP-network-or-cache fetch given fetchParams. + actualResponse = response = await httpNetworkOrCacheFetch(fetchParams) + + // 4. If request’s response tainting is "cors" and a CORS check + // for request and response returns failure, then return a network error. + if ( + request.responseTainting === 'cors' && + corsCheck(request, response) === 'failure' + ) { + return makeNetworkError('cors failure') + } + + // 5. If the TAO check for request and response returns failure, then set + // request’s timing allow failed flag. + if (TAOCheck(request, response) === 'failure') { + request.timingAllowFailed = true + } + } + + // 7. If either request’s response tainting or response’s type + // is "opaque", and the cross-origin resource policy check with + // request’s origin, request’s client, request’s destination, + // and actualResponse returns blocked, then return a network error. + if ( + (request.responseTainting === 'opaque' || response.type === 'opaque') && + crossOriginResourcePolicyCheck( + request.origin, + request.client, + request.destination, + actualResponse + ) === 'blocked' + ) { + return makeNetworkError('blocked') + } + + // 8. If actualResponse’s status is a redirect status, then: + if (redirectStatusSet.has(actualResponse.status)) { + // 1. If actualResponse’s status is not 303, request’s body is not null, + // and the connection uses HTTP/2, then user agents may, and are even + // encouraged to, transmit an RST_STREAM frame. + // See, https://github.com/whatwg/fetch/issues/1288 + if (request.redirect !== 'manual') { + fetchParams.controller.connection.destroy() + } + + // 2. Switch on request’s redirect mode: + if (request.redirect === 'error') { + // Set response to a network error. + response = makeNetworkError('unexpected redirect') + } else if (request.redirect === 'manual') { + // Set response to an opaque-redirect filtered response whose internal + // response is actualResponse. + // NOTE(spec): On the web this would return an `opaqueredirect` response, + // but that doesn't make sense server side. + // See https://github.com/nodejs/undici/issues/1193. + response = actualResponse + } else if (request.redirect === 'follow') { + // Set response to the result of running HTTP-redirect fetch given + // fetchParams and response. + response = await httpRedirectFetch(fetchParams, response) + } else { + assert(false) + } + } + + // 9. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo + + // 10. Return response. + return response +} + +// https://fetch.spec.whatwg.org/#http-redirect-fetch +function httpRedirectFetch (fetchParams, response) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let actualResponse be response, if response is not a filtered response, + // and response’s internal response otherwise. + const actualResponse = response.internalResponse + ? response.internalResponse + : response + + // 3. Let locationURL be actualResponse’s location URL given request’s current + // URL’s fragment. + let locationURL + + try { + locationURL = responseLocationURL( + actualResponse, + requestCurrentURL(request).hash + ) + + // 4. If locationURL is null, then return response. + if (locationURL == null) { + return response + } + } catch (err) { + // 5. If locationURL is failure, then return a network error. + return Promise.resolve(makeNetworkError(err)) + } + + // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network + // error. + if (!urlIsHttpHttpsScheme(locationURL)) { + return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme')) + } + + // 7. If request’s redirect count is 20, then return a network error. + if (request.redirectCount === 20) { + return Promise.resolve(makeNetworkError('redirect count exceeded')) + } + + // 8. Increase request’s redirect count by 1. + request.redirectCount += 1 + + // 9. If request’s mode is "cors", locationURL includes credentials, and + // request’s origin is not same origin with locationURL’s origin, then return + // a network error. + if ( + request.mode === 'cors' && + (locationURL.username || locationURL.password) && + !sameOrigin(request, locationURL) + ) { + return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')) + } + + // 10. If request’s response tainting is "cors" and locationURL includes + // credentials, then return a network error. + if ( + request.responseTainting === 'cors' && + (locationURL.username || locationURL.password) + ) { + return Promise.resolve(makeNetworkError( + 'URL cannot contain credentials for request mode "cors"' + )) + } + + // 11. If actualResponse’s status is not 303, request’s body is non-null, + // and request’s body’s source is null, then return a network error. + if ( + actualResponse.status !== 303 && + request.body != null && + request.body.source == null + ) { + return Promise.resolve(makeNetworkError()) + } + + // 12. If one of the following is true + // - actualResponse’s status is 301 or 302 and request’s method is `POST` + // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD` + if ( + ([301, 302].includes(actualResponse.status) && request.method === 'POST') || + (actualResponse.status === 303 && + !GET_OR_HEAD.includes(request.method)) + ) { + // then: + // 1. Set request’s method to `GET` and request’s body to null. + request.method = 'GET' + request.body = null + + // 2. For each headerName of request-body-header name, delete headerName from + // request’s header list. + for (const headerName of requestBodyHeader) { + request.headersList.delete(headerName) + } + } + + // 13. If request’s current URL’s origin is not same origin with locationURL’s + // origin, then for each headerName of CORS non-wildcard request-header name, + // delete headerName from request’s header list. + if (!sameOrigin(requestCurrentURL(request), locationURL)) { + // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name + request.headersList.delete('authorization') + + // https://fetch.spec.whatwg.org/#authentication-entries + request.headersList.delete('proxy-authorization', true) + + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. + request.headersList.delete('cookie') + request.headersList.delete('host') + } + + // 14. If request’s body is non-null, then set request’s body to the first return + // value of safely extracting request’s body’s source. + if (request.body != null) { + assert(request.body.source != null) + request.body = safelyExtractBody(request.body.source)[0] + } + + // 15. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 16. Set timingInfo’s redirect end time and post-redirect start time to the + // coarsened shared current time given fetchParams’s cross-origin isolated + // capability. + timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = + coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + + // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s + // redirect start time to timingInfo’s start time. + if (timingInfo.redirectStartTime === 0) { + timingInfo.redirectStartTime = timingInfo.startTime + } + + // 18. Append locationURL to request’s URL list. + request.urlList.push(locationURL) + + // 19. Invoke set request’s referrer policy on redirect on request and + // actualResponse. + setRequestReferrerPolicyOnRedirect(request, actualResponse) + + // 20. Return the result of running main fetch given fetchParams and true. + return mainFetch(fetchParams, true) +} + +// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch +async function httpNetworkOrCacheFetch ( + fetchParams, + isAuthenticationFetch = false, + isNewConnectionFetch = false +) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let httpFetchParams be null. + let httpFetchParams = null + + // 3. Let httpRequest be null. + let httpRequest = null + + // 4. Let response be null. + let response = null + + // 5. Let storedResponse be null. + // TODO: cache + + // 6. Let httpCache be null. + const httpCache = null + + // 7. Let the revalidatingFlag be unset. + const revalidatingFlag = false + + // 8. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. If request’s window is "no-window" and request’s redirect mode is + // "error", then set httpFetchParams to fetchParams and httpRequest to + // request. + if (request.window === 'no-window' && request.redirect === 'error') { + httpFetchParams = fetchParams + httpRequest = request + } else { + // Otherwise: + + // 1. Set httpRequest to a clone of request. + httpRequest = makeRequest(request) + + // 2. Set httpFetchParams to a copy of fetchParams. + httpFetchParams = { ...fetchParams } + + // 3. Set httpFetchParams’s request to httpRequest. + httpFetchParams.request = httpRequest + } + + // 3. Let includeCredentials be true if one of + const includeCredentials = + request.credentials === 'include' || + (request.credentials === 'same-origin' && + request.responseTainting === 'basic') + + // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s + // body is non-null; otherwise null. + const contentLength = httpRequest.body ? httpRequest.body.length : null + + // 5. Let contentLengthHeaderValue be null. + let contentLengthHeaderValue = null + + // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or + // `PUT`, then set contentLengthHeaderValue to `0`. + if ( + httpRequest.body == null && + ['POST', 'PUT'].includes(httpRequest.method) + ) { + contentLengthHeaderValue = '0' + } + + // 7. If contentLength is non-null, then set contentLengthHeaderValue to + // contentLength, serialized and isomorphic encoded. + if (contentLength != null) { + contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) + } + + // 8. If contentLengthHeaderValue is non-null, then append + // `Content-Length`/contentLengthHeaderValue to httpRequest’s header + // list. + if (contentLengthHeaderValue != null) { + httpRequest.headersList.append('content-length', contentLengthHeaderValue) + } + + // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`, + // contentLengthHeaderValue) to httpRequest’s header list. + + // 10. If contentLength is non-null and httpRequest’s keepalive is true, + // then: + if (contentLength != null && httpRequest.keepalive) { + // NOTE: keepalive is a noop outside of browser context. + } + + // 11. If httpRequest’s referrer is a URL, then append + // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, + // to httpRequest’s header list. + if (httpRequest.referrer instanceof URL) { + httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href)) + } + + // 12. Append a request `Origin` header for httpRequest. + appendRequestOriginHeader(httpRequest) + + // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA] + appendFetchMetadata(httpRequest) + + // 14. If httpRequest’s header list does not contain `User-Agent`, then + // user agents should append `User-Agent`/default `User-Agent` value to + // httpRequest’s header list. + if (!httpRequest.headersList.contains('user-agent')) { + httpRequest.headersList.append('user-agent', typeof esbuildDetection === 'undefined' ? 'undici' : 'node') + } + + // 15. If httpRequest’s cache mode is "default" and httpRequest’s header + // list contains `If-Modified-Since`, `If-None-Match`, + // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set + // httpRequest’s cache mode to "no-store". + if ( + httpRequest.cache === 'default' && + (httpRequest.headersList.contains('if-modified-since') || + httpRequest.headersList.contains('if-none-match') || + httpRequest.headersList.contains('if-unmodified-since') || + httpRequest.headersList.contains('if-match') || + httpRequest.headersList.contains('if-range')) + ) { + httpRequest.cache = 'no-store' + } + + // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent + // no-cache cache-control header modification flag is unset, and + // httpRequest’s header list does not contain `Cache-Control`, then append + // `Cache-Control`/`max-age=0` to httpRequest’s header list. + if ( + httpRequest.cache === 'no-cache' && + !httpRequest.preventNoCacheCacheControlHeaderModification && + !httpRequest.headersList.contains('cache-control') + ) { + httpRequest.headersList.append('cache-control', 'max-age=0') + } + + // 17. If httpRequest’s cache mode is "no-store" or "reload", then: + if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') { + // 1. If httpRequest’s header list does not contain `Pragma`, then append + // `Pragma`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('pragma')) { + httpRequest.headersList.append('pragma', 'no-cache') + } + + // 2. If httpRequest’s header list does not contain `Cache-Control`, + // then append `Cache-Control`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('cache-control')) { + httpRequest.headersList.append('cache-control', 'no-cache') + } + } + + // 18. If httpRequest’s header list contains `Range`, then append + // `Accept-Encoding`/`identity` to httpRequest’s header list. + if (httpRequest.headersList.contains('range')) { + httpRequest.headersList.append('accept-encoding', 'identity') + } + + // 19. Modify httpRequest’s header list per HTTP. Do not append a given + // header if httpRequest’s header list contains that header’s name. + // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 + if (!httpRequest.headersList.contains('accept-encoding')) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { + httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate') + } else { + httpRequest.headersList.append('accept-encoding', 'gzip, deflate') + } + } + + httpRequest.headersList.delete('host') + + // 20. If includeCredentials is true, then: + if (includeCredentials) { + // 1. If the user agent is not configured to block cookies for httpRequest + // (see section 7 of [COOKIES]), then: + // TODO: credentials + // 2. If httpRequest’s header list does not contain `Authorization`, then: + // TODO: credentials + } + + // 21. If there’s a proxy-authentication entry, use it as appropriate. + // TODO: proxy-authentication + + // 22. Set httpCache to the result of determining the HTTP cache + // partition, given httpRequest. + // TODO: cache + + // 23. If httpCache is null, then set httpRequest’s cache mode to + // "no-store". + if (httpCache == null) { + httpRequest.cache = 'no-store' + } + + // 24. If httpRequest’s cache mode is neither "no-store" nor "reload", + // then: + if (httpRequest.mode !== 'no-store' && httpRequest.mode !== 'reload') { + // TODO: cache + } + + // 9. If aborted, then return the appropriate network error for fetchParams. + // TODO + + // 10. If response is null, then: + if (response == null) { + // 1. If httpRequest’s cache mode is "only-if-cached", then return a + // network error. + if (httpRequest.mode === 'only-if-cached') { + return makeNetworkError('only if cached') + } + + // 2. Let forwardResponse be the result of running HTTP-network fetch + // given httpFetchParams, includeCredentials, and isNewConnectionFetch. + const forwardResponse = await httpNetworkFetch( + httpFetchParams, + includeCredentials, + isNewConnectionFetch + ) + + // 3. If httpRequest’s method is unsafe and forwardResponse’s status is + // in the range 200 to 399, inclusive, invalidate appropriate stored + // responses in httpCache, as per the "Invalidation" chapter of HTTP + // Caching, and set storedResponse to null. [HTTP-CACHING] + if ( + !safeMethodsSet.has(httpRequest.method) && + forwardResponse.status >= 200 && + forwardResponse.status <= 399 + ) { + // TODO: cache + } + + // 4. If the revalidatingFlag is set and forwardResponse’s status is 304, + // then: + if (revalidatingFlag && forwardResponse.status === 304) { + // TODO: cache + } + + // 5. If response is null, then: + if (response == null) { + // 1. Set response to forwardResponse. + response = forwardResponse + + // 2. Store httpRequest and forwardResponse in httpCache, as per the + // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING] + // TODO: cache + } + } + + // 11. Set response’s URL list to a clone of httpRequest’s URL list. + response.urlList = [...httpRequest.urlList] + + // 12. If httpRequest’s header list contains `Range`, then set response’s + // range-requested flag. + if (httpRequest.headersList.contains('range')) { + response.rangeRequested = true + } + + // 13. Set response’s request-includes-credentials to includeCredentials. + response.requestIncludesCredentials = includeCredentials + + // 14. If response’s status is 401, httpRequest’s response tainting is not + // "cors", includeCredentials is true, and request’s window is an environment + // settings object, then: + // TODO + + // 15. If response’s status is 407, then: + if (response.status === 407) { + // 1. If request’s window is "no-window", then return a network error. + if (request.window === 'no-window') { + return makeNetworkError() + } + + // 2. ??? + + // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } + + // 4. Prompt the end user as appropriate in request’s window and store + // the result as a proxy-authentication entry. [HTTP-AUTH] + // TODO: Invoke some kind of callback? + + // 5. Set response to the result of running HTTP-network-or-cache fetch given + // fetchParams. + // TODO + return makeNetworkError('proxy authentication required') + } + + // 16. If all of the following are true + if ( + // response’s status is 421 + response.status === 421 && + // isNewConnectionFetch is false + !isNewConnectionFetch && + // request’s body is null, or request’s body is non-null and request’s body’s source is non-null + (request.body == null || request.body.source != null) + ) { + // then: + + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } + + // 2. Set response to the result of running HTTP-network-or-cache + // fetch given fetchParams, isAuthenticationFetch, and true. + + // TODO (spec): The spec doesn't specify this but we need to cancel + // the active response before we can start a new one. + // https://github.com/whatwg/fetch/issues/1293 + fetchParams.controller.connection.destroy() + + response = await httpNetworkOrCacheFetch( + fetchParams, + isAuthenticationFetch, + true + ) + } + + // 17. If isAuthenticationFetch is true, then create an authentication entry + if (isAuthenticationFetch) { + // TODO + } + + // 18. Return response. + return response +} + +// https://fetch.spec.whatwg.org/#http-network-fetch +async function httpNetworkFetch ( + fetchParams, + includeCredentials = false, + forceNewConnection = false +) { + assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed) + + fetchParams.controller.connection = { + abort: null, + destroyed: false, + destroy (err) { + if (!this.destroyed) { + this.destroyed = true + this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError')) + } + } + } + + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 4. Let httpCache be the result of determining the HTTP cache partition, + // given request. + // TODO: cache + const httpCache = null + + // 5. If httpCache is null, then set request’s cache mode to "no-store". + if (httpCache == null) { + request.cache = 'no-store' + } + + // 6. Let networkPartitionKey be the result of determining the network + // partition key given request. + // TODO + + // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise + // "no". + const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars + + // 8. Switch on request’s mode: + if (request.mode === 'websocket') { + // Let connection be the result of obtaining a WebSocket connection, + // given request’s current URL. + // TODO + } else { + // Let connection be the result of obtaining a connection, given + // networkPartitionKey, request’s current URL’s origin, + // includeCredentials, and forceNewConnection. + // TODO + } + + // 9. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. If connection is failure, then return a network error. + + // 2. Set timingInfo’s final connection timing info to the result of + // calling clamp and coarsen connection timing info with connection’s + // timing info, timingInfo’s post-redirect start time, and fetchParams’s + // cross-origin isolated capability. + + // 3. If connection is not an HTTP/2 connection, request’s body is non-null, + // and request’s body’s source is null, then append (`Transfer-Encoding`, + // `chunked`) to request’s header list. + + // 4. Set timingInfo’s final network-request start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated + // capability. + + // 5. Set response to the result of making an HTTP request over connection + // using request with the following caveats: + + // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS] + // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] + + // - If request’s body is non-null, and request’s body’s source is null, + // then the user agent may have a buffer of up to 64 kibibytes and store + // a part of request’s body in that buffer. If the user agent reads from + // request’s body beyond that buffer’s size and the user agent needs to + // resend request, then instead return a network error. + + // - Set timingInfo’s final network-response start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated capability, + // immediately after the user agent’s HTTP parser receives the first byte + // of the response (e.g., frame header bytes for HTTP/2 or response status + // line for HTTP/1.x). + + // - Wait until all the headers are transmitted. + + // - Any responses whose status is in the range 100 to 199, inclusive, + // and is not 101, are to be ignored, except for the purposes of setting + // timingInfo’s final network-response start time above. + + // - If request’s header list contains `Transfer-Encoding`/`chunked` and + // response is transferred via HTTP/1.0 or older, then return a network + // error. + + // - If the HTTP request results in a TLS client certificate dialog, then: + + // 1. If request’s window is an environment settings object, make the + // dialog available in request’s window. + + // 2. Otherwise, return a network error. + + // To transmit request’s body body, run these steps: + let requestBody = null + // 1. If body is null and fetchParams’s process request end-of-body is + // non-null, then queue a fetch task given fetchParams’s process request + // end-of-body and fetchParams’s task destination. + if (request.body == null && fetchParams.processRequestEndOfBody) { + queueMicrotask(() => fetchParams.processRequestEndOfBody()) + } else if (request.body != null) { + // 2. Otherwise, if body is non-null: + + // 1. Let processBodyChunk given bytes be these steps: + const processBodyChunk = async function * (bytes) { + // 1. If the ongoing fetch is terminated, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. Run this step in parallel: transmit bytes. + yield bytes + + // 3. If fetchParams’s process request body is non-null, then run + // fetchParams’s process request body given bytes’s length. + fetchParams.processRequestBodyChunkLength?.(bytes.byteLength) + } + + // 2. Let processEndOfBody be these steps: + const processEndOfBody = () => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. If fetchParams’s process request end-of-body is non-null, + // then run fetchParams’s process request end-of-body. + if (fetchParams.processRequestEndOfBody) { + fetchParams.processRequestEndOfBody() + } + } + + // 3. Let processBodyError given e be these steps: + const processBodyError = (e) => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller. + if (e.name === 'AbortError') { + fetchParams.controller.abort() + } else { + fetchParams.controller.terminate(e) + } + } + + // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody, + // processBodyError, and fetchParams’s task destination. + requestBody = (async function * () { + try { + for await (const bytes of request.body.stream) { + yield * processBodyChunk(bytes) + } + processEndOfBody() + } catch (err) { + processBodyError(err) + } + })() + } + + try { + // socket is only provided for websockets + const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }) + + if (socket) { + response = makeResponse({ status, statusText, headersList, socket }) + } else { + const iterator = body[Symbol.asyncIterator]() + fetchParams.controller.next = () => iterator.next() + + response = makeResponse({ status, statusText, headersList }) + } + } catch (err) { + // 10. If aborted, then: + if (err.name === 'AbortError') { + // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame. + fetchParams.controller.connection.destroy() + + // 2. Return the appropriate network error for fetchParams. + return makeAppropriateNetworkError(fetchParams, err) + } + + return makeNetworkError(err) + } + + // 11. Let pullAlgorithm be an action that resumes the ongoing fetch + // if it is suspended. + const pullAlgorithm = () => { + fetchParams.controller.resume() + } + + // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s + // controller with reason, given reason. + const cancelAlgorithm = (reason) => { + fetchParams.controller.abort(reason) + } + + // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by + // the user agent. + // TODO + + // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object + // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. + // TODO + + // 15. Let stream be a new ReadableStream. + // 16. Set up stream with pullAlgorithm set to pullAlgorithm, + // cancelAlgorithm set to cancelAlgorithm, highWaterMark set to + // highWaterMark, and sizeAlgorithm set to sizeAlgorithm. + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + const stream = new ReadableStream( + { + async start (controller) { + fetchParams.controller.controller = controller + }, + async pull (controller) { + await pullAlgorithm(controller) + }, + async cancel (reason) { + await cancelAlgorithm(reason) + } + }, + { + highWaterMark: 0, + size () { + return 1 + } + } + ) + + // 17. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. Set response’s body to a new body whose stream is stream. + response.body = { stream } + + // 2. If response is not a network error and request’s cache mode is + // not "no-store", then update response in httpCache for request. + // TODO + + // 3. If includeCredentials is true and the user agent is not configured + // to block cookies for request (see section 7 of [COOKIES]), then run the + // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on + // the value of each header whose name is a byte-case-insensitive match for + // `Set-Cookie` in response’s header list, if any, and request’s current URL. + // TODO + + // 18. If aborted, then: + // TODO + + // 19. Run these steps in parallel: + + // 1. Run these steps, but abort when fetchParams is canceled: + fetchParams.controller.on('terminated', onAborted) + fetchParams.controller.resume = async () => { + // 1. While true + while (true) { + // 1-3. See onData... + + // 4. Set bytes to the result of handling content codings given + // codings and bytes. + let bytes + let isFailure + try { + const { done, value } = await fetchParams.controller.next() + + if (isAborted(fetchParams)) { + break + } + + bytes = done ? undefined : value + } catch (err) { + if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { + // zlib doesn't like empty streams. + bytes = undefined + } else { + bytes = err + + // err may be propagated from the result of calling readablestream.cancel, + // which might not be an error. https://github.com/nodejs/undici/issues/2009 + isFailure = true + } + } + + if (bytes === undefined) { + // 2. Otherwise, if the bytes transmission for response’s message + // body is done normally and stream is readable, then close + // stream, finalize response for fetchParams and response, and + // abort these in-parallel steps. + readableStreamClose(fetchParams.controller.controller) + + finalizeResponse(fetchParams, response) + + return + } + + // 5. Increase timingInfo’s decoded body size by bytes’s length. + timingInfo.decodedBodySize += bytes?.byteLength ?? 0 + + // 6. If bytes is failure, then terminate fetchParams’s controller. + if (isFailure) { + fetchParams.controller.terminate(bytes) + return + } + + // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes + // into stream. + fetchParams.controller.controller.enqueue(new Uint8Array(bytes)) + + // 8. If stream is errored, then terminate the ongoing fetch. + if (isErrored(stream)) { + fetchParams.controller.terminate() + return + } + + // 9. If stream doesn’t need more data ask the user agent to suspend + // the ongoing fetch. + if (!fetchParams.controller.controller.desiredSize) { + return + } + } + } + + // 2. If aborted, then: + function onAborted (reason) { + // 2. If fetchParams is aborted, then: + if (isAborted(fetchParams)) { + // 1. Set response’s aborted flag. + response.aborted = true + + // 2. If stream is readable, then error stream with the result of + // deserialize a serialized abort reason given fetchParams’s + // controller’s serialized abort reason and an + // implementation-defined realm. + if (isReadable(stream)) { + fetchParams.controller.controller.error( + fetchParams.controller.serializedAbortReason + ) + } + } else { + // 3. Otherwise, if stream is readable, error stream with a TypeError. + if (isReadable(stream)) { + fetchParams.controller.controller.error(new TypeError('terminated', { + cause: isErrorLike(reason) ? reason : undefined + })) + } + } + + // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame. + // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so. + fetchParams.controller.connection.destroy() + } + + // 20. Return response. + return response + + async function dispatch ({ body }) { + const url = requestCurrentURL(request) + /** @type {import('../..').Agent} */ + const agent = fetchParams.controller.dispatcher + + return new Promise((resolve, reject) => agent.dispatch( + { + path: url.pathname + url.search, + origin: url.origin, + method: request.method, + body: fetchParams.controller.dispatcher.isMockActive ? request.body && (request.body.source || request.body.stream) : body, + headers: request.headersList.entries, + maxRedirections: 0, + upgrade: request.mode === 'websocket' ? 'websocket' : undefined + }, + { + body: null, + abort: null, + + onConnect (abort) { + // TODO (fix): Do we need connection here? + const { connection } = fetchParams.controller + + if (connection.destroyed) { + abort(new DOMException('The operation was aborted.', 'AbortError')) + } else { + fetchParams.controller.on('terminated', abort) + this.abort = connection.abort = abort + } + }, + + onHeaders (status, headersList, resume, statusText) { + if (status < 200) { + return + } + + let codings = [] + let location = '' + + const headers = new Headers() + + // For H2, the headers are a plain JS object + // We distinguish between them and iterate accordingly + if (Array.isArray(headersList)) { + for (let n = 0; n < headersList.length; n += 2) { + const key = headersList[n + 0].toString('latin1') + const val = headersList[n + 1].toString('latin1') + if (key.toLowerCase() === 'content-encoding') { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + // "All content-coding values are case-insensitive..." + codings = val.toLowerCase().split(',').map((x) => x.trim()) + } else if (key.toLowerCase() === 'location') { + location = val + } + + headers[kHeadersList].append(key, val) + } + } else { + const keys = Object.keys(headersList) + for (const key of keys) { + const val = headersList[key] + if (key.toLowerCase() === 'content-encoding') { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + // "All content-coding values are case-insensitive..." + codings = val.toLowerCase().split(',').map((x) => x.trim()).reverse() + } else if (key.toLowerCase() === 'location') { + location = val + } + + headers[kHeadersList].append(key, val) + } + } + + this.body = new Readable({ read: resume }) + + const decoders = [] + + const willFollow = request.redirect === 'follow' && + location && + redirectStatusSet.has(status) + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { + for (const coding of codings) { + // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 + if (coding === 'x-gzip' || coding === 'gzip') { + decoders.push(zlib.createGunzip({ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })) + } else if (coding === 'deflate') { + decoders.push(zlib.createInflate()) + } else if (coding === 'br') { + decoders.push(zlib.createBrotliDecompress()) + } else { + decoders.length = 0 + break + } + } + } + + resolve({ + status, + statusText, + headersList: headers[kHeadersList], + body: decoders.length + ? pipeline(this.body, ...decoders, () => { }) + : this.body.on('error', () => {}) + }) + + return true + }, + + onData (chunk) { + if (fetchParams.controller.dump) { + return + } + + // 1. If one or more bytes have been transmitted from response’s + // message body, then: + + // 1. Let bytes be the transmitted bytes. + const bytes = chunk + + // 2. Let codings be the result of extracting header list values + // given `Content-Encoding` and response’s header list. + // See pullAlgorithm. + + // 3. Increase timingInfo’s encoded body size by bytes’s length. + timingInfo.encodedBodySize += bytes.byteLength + + // 4. See pullAlgorithm... + + return this.body.push(bytes) + }, + + onComplete () { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } + + fetchParams.controller.ended = true + + this.body.push(null) + }, + + onError (error) { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } + + this.body?.destroy(error) + + fetchParams.controller.terminate(error) + + reject(error) + }, + + onUpgrade (status, headersList, socket) { + if (status !== 101) { + return + } + + const headers = new Headers() + + for (let n = 0; n < headersList.length; n += 2) { + const key = headersList[n + 0].toString('latin1') + const val = headersList[n + 1].toString('latin1') + + headers[kHeadersList].append(key, val) + } + + resolve({ + status, + statusText: STATUS_CODES[status], + headersList: headers[kHeadersList], + socket + }) + + return true + } + } + )) + } +} + +module.exports = { + fetch, + Fetch, + fetching, + finalizeAndReportTiming +} + + +/***/ }), + +/***/ 25194: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/* globals AbortController */ + + + +const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(8923) +const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(26349) +const { FinalizationRegistry } = __nccwpck_require__(13194)() +const util = __nccwpck_require__(3440) +const { + isValidHTTPToken, + sameOrigin, + normalizeMethod, + makePolicyContainer, + normalizeMethodRecord +} = __nccwpck_require__(15523) +const { + forbiddenMethodsSet, + corsSafeListedMethodsSet, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + requestDuplex +} = __nccwpck_require__(87326) +const { kEnumerableProperty } = util +const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(89710) +const { webidl } = __nccwpck_require__(74222) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { URLSerializer } = __nccwpck_require__(94322) +const { kHeadersList, kConstruct } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = __nccwpck_require__(24434) + +let TransformStream = globalThis.TransformStream + +const kAbortController = Symbol('abortController') + +const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { + signal.removeEventListener('abort', abort) +}) + +// https://fetch.spec.whatwg.org/#request-class +class Request { + // https://fetch.spec.whatwg.org/#dom-request + constructor (input, init = {}) { + if (input === kConstruct) { + return + } + + webidl.argumentLengthCheck(arguments, 1, { header: 'Request constructor' }) + + input = webidl.converters.RequestInfo(input) + init = webidl.converters.RequestInit(init) + + // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object + this[kRealm] = { + settingsObject: { + baseUrl: getGlobalOrigin(), + get origin () { + return this.baseUrl?.origin + }, + policyContainer: makePolicyContainer() + } + } + + // 1. Let request be null. + let request = null + + // 2. Let fallbackMode be null. + let fallbackMode = null + + // 3. Let baseURL be this’s relevant settings object’s API base URL. + const baseUrl = this[kRealm].settingsObject.baseUrl + + // 4. Let signal be null. + let signal = null + + // 5. If input is a string, then: + if (typeof input === 'string') { + // 1. Let parsedURL be the result of parsing input with baseURL. + // 2. If parsedURL is failure, then throw a TypeError. + let parsedURL + try { + parsedURL = new URL(input, baseUrl) + } catch (err) { + throw new TypeError('Failed to parse URL from ' + input, { cause: err }) + } + + // 3. If parsedURL includes credentials, then throw a TypeError. + if (parsedURL.username || parsedURL.password) { + throw new TypeError( + 'Request cannot be constructed from a URL that includes credentials: ' + + input + ) + } + + // 4. Set request to a new request whose URL is parsedURL. + request = makeRequest({ urlList: [parsedURL] }) + + // 5. Set fallbackMode to "cors". + fallbackMode = 'cors' + } else { + // 6. Otherwise: + + // 7. Assert: input is a Request object. + assert(input instanceof Request) + + // 8. Set request to input’s request. + request = input[kState] + + // 9. Set signal to input’s signal. + signal = input[kSignal] + } + + // 7. Let origin be this’s relevant settings object’s origin. + const origin = this[kRealm].settingsObject.origin + + // 8. Let window be "client". + let window = 'client' + + // 9. If request’s window is an environment settings object and its origin + // is same origin with origin, then set window to request’s window. + if ( + request.window?.constructor?.name === 'EnvironmentSettingsObject' && + sameOrigin(request.window, origin) + ) { + window = request.window + } + + // 10. If init["window"] exists and is non-null, then throw a TypeError. + if (init.window != null) { + throw new TypeError(`'window' option '${window}' must be null`) + } + + // 11. If init["window"] exists, then set window to "no-window". + if ('window' in init) { + window = 'no-window' + } + + // 12. Set request to a new request with the following properties: + request = makeRequest({ + // URL request’s URL. + // undici implementation note: this is set as the first item in request's urlList in makeRequest + // method request’s method. + method: request.method, + // header list A copy of request’s header list. + // undici implementation note: headersList is cloned in makeRequest + headersList: request.headersList, + // unsafe-request flag Set. + unsafeRequest: request.unsafeRequest, + // client This’s relevant settings object. + client: this[kRealm].settingsObject, + // window window. + window, + // priority request’s priority. + priority: request.priority, + // origin request’s origin. The propagation of the origin is only significant for navigation requests + // being handled by a service worker. In this scenario a request can have an origin that is different + // from the current client. + origin: request.origin, + // referrer request’s referrer. + referrer: request.referrer, + // referrer policy request’s referrer policy. + referrerPolicy: request.referrerPolicy, + // mode request’s mode. + mode: request.mode, + // credentials mode request’s credentials mode. + credentials: request.credentials, + // cache mode request’s cache mode. + cache: request.cache, + // redirect mode request’s redirect mode. + redirect: request.redirect, + // integrity metadata request’s integrity metadata. + integrity: request.integrity, + // keepalive request’s keepalive. + keepalive: request.keepalive, + // reload-navigation flag request’s reload-navigation flag. + reloadNavigation: request.reloadNavigation, + // history-navigation flag request’s history-navigation flag. + historyNavigation: request.historyNavigation, + // URL list A clone of request’s URL list. + urlList: [...request.urlList] + }) + + const initHasKey = Object.keys(init).length !== 0 + + // 13. If init is not empty, then: + if (initHasKey) { + // 1. If request’s mode is "navigate", then set it to "same-origin". + if (request.mode === 'navigate') { + request.mode = 'same-origin' + } + + // 2. Unset request’s reload-navigation flag. + request.reloadNavigation = false + + // 3. Unset request’s history-navigation flag. + request.historyNavigation = false + + // 4. Set request’s origin to "client". + request.origin = 'client' + + // 5. Set request’s referrer to "client" + request.referrer = 'client' + + // 6. Set request’s referrer policy to the empty string. + request.referrerPolicy = '' + + // 7. Set request’s URL to request’s current URL. + request.url = request.urlList[request.urlList.length - 1] + + // 8. Set request’s URL list to « request’s URL ». + request.urlList = [request.url] + } + + // 14. If init["referrer"] exists, then: + if (init.referrer !== undefined) { + // 1. Let referrer be init["referrer"]. + const referrer = init.referrer + + // 2. If referrer is the empty string, then set request’s referrer to "no-referrer". + if (referrer === '') { + request.referrer = 'no-referrer' + } else { + // 1. Let parsedReferrer be the result of parsing referrer with + // baseURL. + // 2. If parsedReferrer is failure, then throw a TypeError. + let parsedReferrer + try { + parsedReferrer = new URL(referrer, baseUrl) + } catch (err) { + throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }) + } + + // 3. If one of the following is true + // - parsedReferrer’s scheme is "about" and path is the string "client" + // - parsedReferrer’s origin is not same origin with origin + // then set request’s referrer to "client". + if ( + (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') || + (origin && !sameOrigin(parsedReferrer, this[kRealm].settingsObject.baseUrl)) + ) { + request.referrer = 'client' + } else { + // 4. Otherwise, set request’s referrer to parsedReferrer. + request.referrer = parsedReferrer + } + } + } + + // 15. If init["referrerPolicy"] exists, then set request’s referrer policy + // to it. + if (init.referrerPolicy !== undefined) { + request.referrerPolicy = init.referrerPolicy + } + + // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise. + let mode + if (init.mode !== undefined) { + mode = init.mode + } else { + mode = fallbackMode + } + + // 17. If mode is "navigate", then throw a TypeError. + if (mode === 'navigate') { + throw webidl.errors.exception({ + header: 'Request constructor', + message: 'invalid request mode navigate.' + }) + } + + // 18. If mode is non-null, set request’s mode to mode. + if (mode != null) { + request.mode = mode + } + + // 19. If init["credentials"] exists, then set request’s credentials mode + // to it. + if (init.credentials !== undefined) { + request.credentials = init.credentials + } + + // 18. If init["cache"] exists, then set request’s cache mode to it. + if (init.cache !== undefined) { + request.cache = init.cache + } + + // 21. If request’s cache mode is "only-if-cached" and request’s mode is + // not "same-origin", then throw a TypeError. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + throw new TypeError( + "'only-if-cached' can be set only with 'same-origin' mode" + ) + } + + // 22. If init["redirect"] exists, then set request’s redirect mode to it. + if (init.redirect !== undefined) { + request.redirect = init.redirect + } + + // 23. If init["integrity"] exists, then set request’s integrity metadata to it. + if (init.integrity != null) { + request.integrity = String(init.integrity) + } + + // 24. If init["keepalive"] exists, then set request’s keepalive to it. + if (init.keepalive !== undefined) { + request.keepalive = Boolean(init.keepalive) + } + + // 25. If init["method"] exists, then: + if (init.method !== undefined) { + // 1. Let method be init["method"]. + let method = init.method + + // 2. If method is not a method or method is a forbidden method, then + // throw a TypeError. + if (!isValidHTTPToken(method)) { + throw new TypeError(`'${method}' is not a valid HTTP method.`) + } + + if (forbiddenMethodsSet.has(method.toUpperCase())) { + throw new TypeError(`'${method}' HTTP method is unsupported.`) + } + + // 3. Normalize method. + method = normalizeMethodRecord[method] ?? normalizeMethod(method) + + // 4. Set request’s method to method. + request.method = method + } + + // 26. If init["signal"] exists, then set signal to it. + if (init.signal !== undefined) { + signal = init.signal + } + + // 27. Set this’s request to request. + this[kState] = request + + // 28. Set this’s signal to a new AbortSignal object with this’s relevant + // Realm. + // TODO: could this be simplified with AbortSignal.any + // (https://dom.spec.whatwg.org/#dom-abortsignal-any) + const ac = new AbortController() + this[kSignal] = ac.signal + this[kSignal][kRealm] = this[kRealm] + + // 29. If signal is not null, then make this’s signal follow signal. + if (signal != null) { + if ( + !signal || + typeof signal.aborted !== 'boolean' || + typeof signal.addEventListener !== 'function' + ) { + throw new TypeError( + "Failed to construct 'Request': member signal is not of type AbortSignal." + ) + } + + if (signal.aborted) { + ac.abort(signal.reason) + } else { + // Keep a strong ref to ac while request object + // is alive. This is needed to prevent AbortController + // from being prematurely garbage collected. + // See, https://github.com/nodejs/undici/issues/1926. + this[kAbortController] = ac + + const acRef = new WeakRef(ac) + const abort = function () { + const ac = acRef.deref() + if (ac !== undefined) { + ac.abort(this.reason) + } + } + + // Third-party AbortControllers may not work with these. + // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619. + try { + // If the max amount of listeners is equal to the default, increase it + // This is only available in node >= v19.9.0 + if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) { + setMaxListeners(100, signal) + } else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { + setMaxListeners(100, signal) + } + } catch {} + + util.addAbortListener(signal, abort) + requestFinalizer.register(ac, { signal, abort }) + } + } + + // 30. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is request’s header list and guard is + // "request". + this[kHeaders] = new Headers(kConstruct) + this[kHeaders][kHeadersList] = request.headersList + this[kHeaders][kGuard] = 'request' + this[kHeaders][kRealm] = this[kRealm] + + // 31. If this’s request’s mode is "no-cors", then: + if (mode === 'no-cors') { + // 1. If this’s request’s method is not a CORS-safelisted method, + // then throw a TypeError. + if (!corsSafeListedMethodsSet.has(request.method)) { + throw new TypeError( + `'${request.method} is unsupported in no-cors mode.` + ) + } + + // 2. Set this’s headers’s guard to "request-no-cors". + this[kHeaders][kGuard] = 'request-no-cors' + } + + // 32. If init is not empty, then: + if (initHasKey) { + /** @type {HeadersList} */ + const headersList = this[kHeaders][kHeadersList] + // 1. Let headers be a copy of this’s headers and its associated header + // list. + // 2. If init["headers"] exists, then set headers to init["headers"]. + const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) + + // 3. Empty this’s headers’s header list. + headersList.clear() + + // 4. If headers is a Headers object, then for each header in its header + // list, append header’s name/header’s value to this’s headers. + if (headers instanceof HeadersList) { + for (const [key, val] of headers) { + headersList.append(key, val) + } + // Note: Copy the `set-cookie` meta-data. + headersList.cookies = headers.cookies + } else { + // 5. Otherwise, fill this’s headers with headers. + fillHeaders(this[kHeaders], headers) + } + } + + // 33. Let inputBody be input’s request’s body if input is a Request + // object; otherwise null. + const inputBody = input instanceof Request ? input[kState].body : null + + // 34. If either init["body"] exists and is non-null or inputBody is + // non-null, and request’s method is `GET` or `HEAD`, then throw a + // TypeError. + if ( + (init.body != null || inputBody != null) && + (request.method === 'GET' || request.method === 'HEAD') + ) { + throw new TypeError('Request with GET/HEAD method cannot have body.') + } + + // 35. Let initBody be null. + let initBody = null + + // 36. If init["body"] exists and is non-null, then: + if (init.body != null) { + // 1. Let Content-Type be null. + // 2. Set initBody and Content-Type to the result of extracting + // init["body"], with keepalive set to request’s keepalive. + const [extractedBody, contentType] = extractBody( + init.body, + request.keepalive + ) + initBody = extractedBody + + // 3, If Content-Type is non-null and this’s headers’s header list does + // not contain `Content-Type`, then append `Content-Type`/Content-Type to + // this’s headers. + if (contentType && !this[kHeaders][kHeadersList].contains('content-type')) { + this[kHeaders].append('content-type', contentType) + } + } + + // 37. Let inputOrInitBody be initBody if it is non-null; otherwise + // inputBody. + const inputOrInitBody = initBody ?? inputBody + + // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is + // null, then: + if (inputOrInitBody != null && inputOrInitBody.source == null) { + // 1. If initBody is non-null and init["duplex"] does not exist, + // then throw a TypeError. + if (initBody != null && init.duplex == null) { + throw new TypeError('RequestInit: duplex option is required when sending a body.') + } + + // 2. If this’s request’s mode is neither "same-origin" nor "cors", + // then throw a TypeError. + if (request.mode !== 'same-origin' && request.mode !== 'cors') { + throw new TypeError( + 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' + ) + } + + // 3. Set this’s request’s use-CORS-preflight flag. + request.useCORSPreflightFlag = true + } + + // 39. Let finalBody be inputOrInitBody. + let finalBody = inputOrInitBody + + // 40. If initBody is null and inputBody is non-null, then: + if (initBody == null && inputBody != null) { + // 1. If input is unusable, then throw a TypeError. + if (util.isDisturbed(inputBody.stream) || inputBody.stream.locked) { + throw new TypeError( + 'Cannot construct a Request with a Request object that has already been used.' + ) + } + + // 2. Set finalBody to the result of creating a proxy for inputBody. + if (!TransformStream) { + TransformStream = (__nccwpck_require__(63774).TransformStream) + } + + // https://streams.spec.whatwg.org/#readablestream-create-a-proxy + const identityTransform = new TransformStream() + inputBody.stream.pipeThrough(identityTransform) + finalBody = { + source: inputBody.source, + length: inputBody.length, + stream: identityTransform.readable + } + } + + // 41. Set this’s request’s body to finalBody. + this[kState].body = finalBody + } + + // Returns request’s HTTP method, which is "GET" by default. + get method () { + webidl.brandCheck(this, Request) + + // The method getter steps are to return this’s request’s method. + return this[kState].method + } + + // Returns the URL of request as a string. + get url () { + webidl.brandCheck(this, Request) + + // The url getter steps are to return this’s request’s URL, serialized. + return URLSerializer(this[kState].url) + } + + // Returns a Headers object consisting of the headers associated with request. + // Note that headers added in the network layer by the user agent will not + // be accounted for in this object, e.g., the "Host" header. + get headers () { + webidl.brandCheck(this, Request) + + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } + + // Returns the kind of resource requested by request, e.g., "document" + // or "script". + get destination () { + webidl.brandCheck(this, Request) + + // The destination getter are to return this’s request’s destination. + return this[kState].destination + } + + // Returns the referrer of request. Its value can be a same-origin URL if + // explicitly set in init, the empty string to indicate no referrer, and + // "about:client" when defaulting to the global’s default. This is used + // during fetching to determine the value of the `Referer` header of the + // request being made. + get referrer () { + webidl.brandCheck(this, Request) + + // 1. If this’s request’s referrer is "no-referrer", then return the + // empty string. + if (this[kState].referrer === 'no-referrer') { + return '' + } + + // 2. If this’s request’s referrer is "client", then return + // "about:client". + if (this[kState].referrer === 'client') { + return 'about:client' + } + + // Return this’s request’s referrer, serialized. + return this[kState].referrer.toString() + } + + // Returns the referrer policy associated with request. + // This is used during fetching to compute the value of the request’s + // referrer. + get referrerPolicy () { + webidl.brandCheck(this, Request) + + // The referrerPolicy getter steps are to return this’s request’s referrer policy. + return this[kState].referrerPolicy + } + + // Returns the mode associated with request, which is a string indicating + // whether the request will use CORS, or will be restricted to same-origin + // URLs. + get mode () { + webidl.brandCheck(this, Request) + + // The mode getter steps are to return this’s request’s mode. + return this[kState].mode + } + + // Returns the credentials mode associated with request, + // which is a string indicating whether credentials will be sent with the + // request always, never, or only when sent to a same-origin URL. + get credentials () { + // The credentials getter steps are to return this’s request’s credentials mode. + return this[kState].credentials + } + + // Returns the cache mode associated with request, + // which is a string indicating how the request will + // interact with the browser’s cache when fetching. + get cache () { + webidl.brandCheck(this, Request) + + // The cache getter steps are to return this’s request’s cache mode. + return this[kState].cache + } + + // Returns the redirect mode associated with request, + // which is a string indicating how redirects for the + // request will be handled during fetching. A request + // will follow redirects by default. + get redirect () { + webidl.brandCheck(this, Request) + + // The redirect getter steps are to return this’s request’s redirect mode. + return this[kState].redirect + } + + // Returns request’s subresource integrity metadata, which is a + // cryptographic hash of the resource being fetched. Its value + // consists of multiple hashes separated by whitespace. [SRI] + get integrity () { + webidl.brandCheck(this, Request) + + // The integrity getter steps are to return this’s request’s integrity + // metadata. + return this[kState].integrity + } + + // Returns a boolean indicating whether or not request can outlive the + // global in which it was created. + get keepalive () { + webidl.brandCheck(this, Request) + + // The keepalive getter steps are to return this’s request’s keepalive. + return this[kState].keepalive + } + + // Returns a boolean indicating whether or not request is for a reload + // navigation. + get isReloadNavigation () { + webidl.brandCheck(this, Request) + + // The isReloadNavigation getter steps are to return true if this’s + // request’s reload-navigation flag is set; otherwise false. + return this[kState].reloadNavigation + } + + // Returns a boolean indicating whether or not request is for a history + // navigation (a.k.a. back-foward navigation). + get isHistoryNavigation () { + webidl.brandCheck(this, Request) + + // The isHistoryNavigation getter steps are to return true if this’s request’s + // history-navigation flag is set; otherwise false. + return this[kState].historyNavigation + } + + // Returns the signal associated with request, which is an AbortSignal + // object indicating whether or not request has been aborted, and its + // abort event handler. + get signal () { + webidl.brandCheck(this, Request) + + // The signal getter steps are to return this’s signal. + return this[kSignal] + } + + get body () { + webidl.brandCheck(this, Request) + + return this[kState].body ? this[kState].body.stream : null + } + + get bodyUsed () { + webidl.brandCheck(this, Request) + + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + } + + get duplex () { + webidl.brandCheck(this, Request) + + return 'half' + } + + // Returns a clone of request. + clone () { + webidl.brandCheck(this, Request) + + // 1. If this is unusable, then throw a TypeError. + if (this.bodyUsed || this.body?.locked) { + throw new TypeError('unusable') + } + + // 2. Let clonedRequest be the result of cloning this’s request. + const clonedRequest = cloneRequest(this[kState]) + + // 3. Let clonedRequestObject be the result of creating a Request object, + // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. + const clonedRequestObject = new Request(kConstruct) + clonedRequestObject[kState] = clonedRequest + clonedRequestObject[kRealm] = this[kRealm] + clonedRequestObject[kHeaders] = new Headers(kConstruct) + clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList + clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard] + clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm] + + // 4. Make clonedRequestObject’s signal follow this’s signal. + const ac = new AbortController() + if (this.signal.aborted) { + ac.abort(this.signal.reason) + } else { + util.addAbortListener( + this.signal, + () => { + ac.abort(this.signal.reason) + } + ) + } + clonedRequestObject[kSignal] = ac.signal + + // 4. Return clonedRequestObject. + return clonedRequestObject + } +} + +mixinBody(Request) + +function makeRequest (init) { + // https://fetch.spec.whatwg.org/#requests + const request = { + method: 'GET', + localURLsOnly: false, + unsafeRequest: false, + body: null, + client: null, + reservedClient: null, + replacesClientId: '', + window: 'client', + keepalive: false, + serviceWorkers: 'all', + initiator: '', + destination: '', + priority: null, + origin: 'client', + policyContainer: 'client', + referrer: 'client', + referrerPolicy: '', + mode: 'no-cors', + useCORSPreflightFlag: false, + credentials: 'same-origin', + useCredentials: false, + cache: 'default', + redirect: 'follow', + integrity: '', + cryptoGraphicsNonceMetadata: '', + parserMetadata: '', + reloadNavigation: false, + historyNavigation: false, + userActivation: false, + taintedOrigin: false, + redirectCount: 0, + responseTainting: 'basic', + preventNoCacheCacheControlHeaderModification: false, + done: false, + timingAllowFailed: false, + ...init, + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList() + } + request.url = request.urlList[0] + return request +} + +// https://fetch.spec.whatwg.org/#concept-request-clone +function cloneRequest (request) { + // To clone a request request, run these steps: + + // 1. Let newRequest be a copy of request, except for its body. + const newRequest = makeRequest({ ...request, body: null }) + + // 2. If request’s body is non-null, set newRequest’s body to the + // result of cloning request’s body. + if (request.body != null) { + newRequest.body = cloneBody(request.body) + } + + // 3. Return newRequest. + return newRequest +} + +Object.defineProperties(Request.prototype, { + method: kEnumerableProperty, + url: kEnumerableProperty, + headers: kEnumerableProperty, + redirect: kEnumerableProperty, + clone: kEnumerableProperty, + signal: kEnumerableProperty, + duplex: kEnumerableProperty, + destination: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + isHistoryNavigation: kEnumerableProperty, + isReloadNavigation: kEnumerableProperty, + keepalive: kEnumerableProperty, + integrity: kEnumerableProperty, + cache: kEnumerableProperty, + credentials: kEnumerableProperty, + attribute: kEnumerableProperty, + referrerPolicy: kEnumerableProperty, + referrer: kEnumerableProperty, + mode: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Request', + configurable: true + } +}) + +webidl.converters.Request = webidl.interfaceConverter( + Request +) + +// https://fetch.spec.whatwg.org/#requestinfo +webidl.converters.RequestInfo = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) + } + + if (V instanceof Request) { + return webidl.converters.Request(V) + } + + return webidl.converters.USVString(V) +} + +webidl.converters.AbortSignal = webidl.interfaceConverter( + AbortSignal +) + +// https://fetch.spec.whatwg.org/#requestinit +webidl.converters.RequestInit = webidl.dictionaryConverter([ + { + key: 'method', + converter: webidl.converters.ByteString + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + }, + { + key: 'body', + converter: webidl.nullableConverter( + webidl.converters.BodyInit + ) + }, + { + key: 'referrer', + converter: webidl.converters.USVString + }, + { + key: 'referrerPolicy', + converter: webidl.converters.DOMString, + // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + allowedValues: referrerPolicy + }, + { + key: 'mode', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#concept-request-mode + allowedValues: requestMode + }, + { + key: 'credentials', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcredentials + allowedValues: requestCredentials + }, + { + key: 'cache', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcache + allowedValues: requestCache + }, + { + key: 'redirect', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestredirect + allowedValues: requestRedirect + }, + { + key: 'integrity', + converter: webidl.converters.DOMString + }, + { + key: 'keepalive', + converter: webidl.converters.boolean + }, + { + key: 'signal', + converter: webidl.nullableConverter( + (signal) => webidl.converters.AbortSignal( + signal, + { strict: false } + ) + ) + }, + { + key: 'window', + converter: webidl.converters.any + }, + { + key: 'duplex', + converter: webidl.converters.DOMString, + allowedValues: requestDuplex + } +]) + +module.exports = { Request, makeRequest } + + +/***/ }), + +/***/ 48676: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Headers, HeadersList, fill } = __nccwpck_require__(26349) +const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(8923) +const util = __nccwpck_require__(3440) +const { kEnumerableProperty } = util +const { + isValidReasonPhrase, + isCancelled, + isAborted, + isBlobLike, + serializeJavascriptValueToJSONString, + isErrorLike, + isomorphicEncode +} = __nccwpck_require__(15523) +const { + redirectStatusSet, + nullBodyStatus, + DOMException +} = __nccwpck_require__(87326) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(89710) +const { webidl } = __nccwpck_require__(74222) +const { FormData } = __nccwpck_require__(43073) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { URLSerializer } = __nccwpck_require__(94322) +const { kHeadersList, kConstruct } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { types } = __nccwpck_require__(39023) + +const ReadableStream = globalThis.ReadableStream || (__nccwpck_require__(63774).ReadableStream) +const textEncoder = new TextEncoder('utf-8') + +// https://fetch.spec.whatwg.org/#response-class +class Response { + // Creates network error Response. + static error () { + // TODO + const relevantRealm = { settingsObject: {} } + + // The static error() method steps are to return the result of creating a + // Response object, given a new network error, "immutable", and this’s + // relevant Realm. + const responseObject = new Response() + responseObject[kState] = makeNetworkError() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + return responseObject + } + + // https://fetch.spec.whatwg.org/#dom-response-json + static json (data, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' }) + + if (init !== null) { + init = webidl.converters.ResponseInit(init) + } + + // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data. + const bytes = textEncoder.encode( + serializeJavascriptValueToJSONString(data) + ) + + // 2. Let body be the result of extracting bytes. + const body = extractBody(bytes) + + // 3. Let responseObject be the result of creating a Response object, given a new response, + // "response", and this’s relevant Realm. + const relevantRealm = { settingsObject: {} } + const responseObject = new Response() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kGuard] = 'response' + responseObject[kHeaders][kRealm] = relevantRealm + + // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). + initializeResponse(responseObject, init, { body: body[0], type: 'application/json' }) + + // 5. Return responseObject. + return responseObject + } + + // Creates a redirect Response that redirects to url with status status. + static redirect (url, status = 302) { + const relevantRealm = { settingsObject: {} } + + webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' }) + + url = webidl.converters.USVString(url) + status = webidl.converters['unsigned short'](status) + + // 1. Let parsedURL be the result of parsing url with current settings + // object’s API base URL. + // 2. If parsedURL is failure, then throw a TypeError. + // TODO: base-URL? + let parsedURL + try { + parsedURL = new URL(url, getGlobalOrigin()) + } catch (err) { + throw Object.assign(new TypeError('Failed to parse URL from ' + url), { + cause: err + }) + } + + // 3. If status is not a redirect status, then throw a RangeError. + if (!redirectStatusSet.has(status)) { + throw new RangeError('Invalid status code ' + status) + } + + // 4. Let responseObject be the result of creating a Response object, + // given a new response, "immutable", and this’s relevant Realm. + const responseObject = new Response() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + + // 5. Set responseObject’s response’s status to status. + responseObject[kState].status = status + + // 6. Let value be parsedURL, serialized and isomorphic encoded. + const value = isomorphicEncode(URLSerializer(parsedURL)) + + // 7. Append `Location`/value to responseObject’s response’s header list. + responseObject[kState].headersList.append('location', value) + + // 8. Return responseObject. + return responseObject + } + + // https://fetch.spec.whatwg.org/#dom-response + constructor (body = null, init = {}) { + if (body !== null) { + body = webidl.converters.BodyInit(body) + } + + init = webidl.converters.ResponseInit(init) + + // TODO + this[kRealm] = { settingsObject: {} } + + // 1. Set this’s response to a new response. + this[kState] = makeResponse({}) + + // 2. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is this’s response’s header list and guard + // is "response". + this[kHeaders] = new Headers(kConstruct) + this[kHeaders][kGuard] = 'response' + this[kHeaders][kHeadersList] = this[kState].headersList + this[kHeaders][kRealm] = this[kRealm] + + // 3. Let bodyWithType be null. + let bodyWithType = null + + // 4. If body is non-null, then set bodyWithType to the result of extracting body. + if (body != null) { + const [extractedBody, type] = extractBody(body) + bodyWithType = { body: extractedBody, type } + } + + // 5. Perform initialize a response given this, init, and bodyWithType. + initializeResponse(this, init, bodyWithType) + } + + // Returns response’s type, e.g., "cors". + get type () { + webidl.brandCheck(this, Response) + + // The type getter steps are to return this’s response’s type. + return this[kState].type + } + + // Returns response’s URL, if it has one; otherwise the empty string. + get url () { + webidl.brandCheck(this, Response) + + const urlList = this[kState].urlList + + // The url getter steps are to return the empty string if this’s + // response’s URL is null; otherwise this’s response’s URL, + // serialized with exclude fragment set to true. + const url = urlList[urlList.length - 1] ?? null + + if (url === null) { + return '' + } + + return URLSerializer(url, true) + } + + // Returns whether response was obtained through a redirect. + get redirected () { + webidl.brandCheck(this, Response) + + // The redirected getter steps are to return true if this’s response’s URL + // list has more than one item; otherwise false. + return this[kState].urlList.length > 1 + } + + // Returns response’s status. + get status () { + webidl.brandCheck(this, Response) + + // The status getter steps are to return this’s response’s status. + return this[kState].status + } + + // Returns whether response’s status is an ok status. + get ok () { + webidl.brandCheck(this, Response) + + // The ok getter steps are to return true if this’s response’s status is an + // ok status; otherwise false. + return this[kState].status >= 200 && this[kState].status <= 299 + } + + // Returns response’s status message. + get statusText () { + webidl.brandCheck(this, Response) + + // The statusText getter steps are to return this’s response’s status + // message. + return this[kState].statusText + } + + // Returns response’s headers as Headers. + get headers () { + webidl.brandCheck(this, Response) + + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } + + get body () { + webidl.brandCheck(this, Response) + + return this[kState].body ? this[kState].body.stream : null + } + + get bodyUsed () { + webidl.brandCheck(this, Response) + + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + } + + // Returns a clone of response. + clone () { + webidl.brandCheck(this, Response) + + // 1. If this is unusable, then throw a TypeError. + if (this.bodyUsed || (this.body && this.body.locked)) { + throw webidl.errors.exception({ + header: 'Response.clone', + message: 'Body has already been consumed.' + }) + } + + // 2. Let clonedResponse be the result of cloning this’s response. + const clonedResponse = cloneResponse(this[kState]) + + // 3. Return the result of creating a Response object, given + // clonedResponse, this’s headers’s guard, and this’s relevant Realm. + const clonedResponseObject = new Response() + clonedResponseObject[kState] = clonedResponse + clonedResponseObject[kRealm] = this[kRealm] + clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList + clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard] + clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm] + + return clonedResponseObject + } +} + +mixinBody(Response) + +Object.defineProperties(Response.prototype, { + type: kEnumerableProperty, + url: kEnumerableProperty, + status: kEnumerableProperty, + ok: kEnumerableProperty, + redirected: kEnumerableProperty, + statusText: kEnumerableProperty, + headers: kEnumerableProperty, + clone: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Response', + configurable: true + } +}) + +Object.defineProperties(Response, { + json: kEnumerableProperty, + redirect: kEnumerableProperty, + error: kEnumerableProperty +}) + +// https://fetch.spec.whatwg.org/#concept-response-clone +function cloneResponse (response) { + // To clone a response response, run these steps: + + // 1. If response is a filtered response, then return a new identical + // filtered response whose internal response is a clone of response’s + // internal response. + if (response.internalResponse) { + return filterResponse( + cloneResponse(response.internalResponse), + response.type + ) + } + + // 2. Let newResponse be a copy of response, except for its body. + const newResponse = makeResponse({ ...response, body: null }) + + // 3. If response’s body is non-null, then set newResponse’s body to the + // result of cloning response’s body. + if (response.body != null) { + newResponse.body = cloneBody(response.body) + } + + // 4. Return newResponse. + return newResponse +} + +function makeResponse (init) { + return { + aborted: false, + rangeRequested: false, + timingAllowPassed: false, + requestIncludesCredentials: false, + type: 'default', + status: 200, + timingInfo: null, + cacheState: '', + statusText: '', + ...init, + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList(), + urlList: init.urlList ? [...init.urlList] : [] + } +} + +function makeNetworkError (reason) { + const isError = isErrorLike(reason) + return makeResponse({ + type: 'error', + status: 0, + error: isError + ? reason + : new Error(reason ? String(reason) : reason), + aborted: reason && reason.name === 'AbortError' + }) +} + +function makeFilteredResponse (response, state) { + state = { + internalResponse: response, + ...state + } + + return new Proxy(response, { + get (target, p) { + return p in state ? state[p] : target[p] + }, + set (target, p, value) { + assert(!(p in state)) + target[p] = value + return true + } + }) +} + +// https://fetch.spec.whatwg.org/#concept-filtered-response +function filterResponse (response, type) { + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (type === 'basic') { + // A basic filtered response is a filtered response whose type is "basic" + // and header list excludes any headers in internal response’s header list + // whose name is a forbidden response-header name. + + // Note: undici does not implement forbidden response-header names + return makeFilteredResponse(response, { + type: 'basic', + headersList: response.headersList + }) + } else if (type === 'cors') { + // A CORS filtered response is a filtered response whose type is "cors" + // and header list excludes any headers in internal response’s header + // list whose name is not a CORS-safelisted response-header name, given + // internal response’s CORS-exposed header-name list. + + // Note: undici does not implement CORS-safelisted response-header names + return makeFilteredResponse(response, { + type: 'cors', + headersList: response.headersList + }) + } else if (type === 'opaque') { + // An opaque filtered response is a filtered response whose type is + // "opaque", URL list is the empty list, status is 0, status message + // is the empty byte sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaque', + urlList: Object.freeze([]), + status: 0, + statusText: '', + body: null + }) + } else if (type === 'opaqueredirect') { + // An opaque-redirect filtered response is a filtered response whose type + // is "opaqueredirect", status is 0, status message is the empty byte + // sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaqueredirect', + status: 0, + statusText: '', + headersList: [], + body: null + }) + } else { + assert(false) + } +} + +// https://fetch.spec.whatwg.org/#appropriate-network-error +function makeAppropriateNetworkError (fetchParams, err = null) { + // 1. Assert: fetchParams is canceled. + assert(isCancelled(fetchParams)) + + // 2. Return an aborted network error if fetchParams is aborted; + // otherwise return a network error. + return isAborted(fetchParams) + ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err })) + : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err })) +} + +// https://whatpr.org/fetch/1392.html#initialize-a-response +function initializeResponse (response, init, body) { + // 1. If init["status"] is not in the range 200 to 599, inclusive, then + // throw a RangeError. + if (init.status !== null && (init.status < 200 || init.status > 599)) { + throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.') + } + + // 2. If init["statusText"] does not match the reason-phrase token production, + // then throw a TypeError. + if ('statusText' in init && init.statusText != null) { + // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2: + // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) + if (!isValidReasonPhrase(String(init.statusText))) { + throw new TypeError('Invalid statusText') + } + } + + // 3. Set response’s response’s status to init["status"]. + if ('status' in init && init.status != null) { + response[kState].status = init.status + } + + // 4. Set response’s response’s status message to init["statusText"]. + if ('statusText' in init && init.statusText != null) { + response[kState].statusText = init.statusText + } + + // 5. If init["headers"] exists, then fill response’s headers with init["headers"]. + if ('headers' in init && init.headers != null) { + fill(response[kHeaders], init.headers) + } + + // 6. If body was given, then: + if (body) { + // 1. If response's status is a null body status, then throw a TypeError. + if (nullBodyStatus.includes(response.status)) { + throw webidl.errors.exception({ + header: 'Response constructor', + message: 'Invalid response status code ' + response.status + }) + } + + // 2. Set response's body to body's body. + response[kState].body = body.body + + // 3. If body's type is non-null and response's header list does not contain + // `Content-Type`, then append (`Content-Type`, body's type) to response's header list. + if (body.type != null && !response[kState].headersList.contains('Content-Type')) { + response[kState].headersList.append('content-type', body.type) + } + } +} + +webidl.converters.ReadableStream = webidl.interfaceConverter( + ReadableStream +) + +webidl.converters.FormData = webidl.interfaceConverter( + FormData +) + +webidl.converters.URLSearchParams = webidl.interfaceConverter( + URLSearchParams +) + +// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit +webidl.converters.XMLHttpRequestBodyInit = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) + } + + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if (types.isArrayBuffer(V) || types.isTypedArray(V) || types.isDataView(V)) { + return webidl.converters.BufferSource(V) + } + + if (util.isFormDataLike(V)) { + return webidl.converters.FormData(V, { strict: false }) + } + + if (V instanceof URLSearchParams) { + return webidl.converters.URLSearchParams(V) + } + + return webidl.converters.DOMString(V) +} + +// https://fetch.spec.whatwg.org/#bodyinit +webidl.converters.BodyInit = function (V) { + if (V instanceof ReadableStream) { + return webidl.converters.ReadableStream(V) + } + + // Note: the spec doesn't include async iterables, + // this is an undici extension. + if (V?.[Symbol.asyncIterator]) { + return V + } + + return webidl.converters.XMLHttpRequestBodyInit(V) +} + +webidl.converters.ResponseInit = webidl.dictionaryConverter([ + { + key: 'status', + converter: webidl.converters['unsigned short'], + defaultValue: 200 + }, + { + key: 'statusText', + converter: webidl.converters.ByteString, + defaultValue: '' + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + } +]) + +module.exports = { + makeNetworkError, + makeResponse, + makeAppropriateNetworkError, + filterResponse, + Response, + cloneResponse +} + + +/***/ }), + +/***/ 89710: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kUrl: Symbol('url'), + kHeaders: Symbol('headers'), + kSignal: Symbol('signal'), + kState: Symbol('state'), + kGuard: Symbol('guard'), + kRealm: Symbol('realm') +} + + +/***/ }), + +/***/ 15523: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(87326) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { performance } = __nccwpck_require__(82987) +const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(3440) +const assert = __nccwpck_require__(42613) +const { isUint8Array } = __nccwpck_require__(98253) + +let supportedHashes = [] + +// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable +/** @type {import('crypto')|undefined} */ +let crypto + +try { + crypto = __nccwpck_require__(76982) + const possibleRelevantHashes = ['sha256', 'sha384', 'sha512'] + supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash)) +/* c8 ignore next 3 */ +} catch { +} + +function responseURL (response) { + // https://fetch.spec.whatwg.org/#responses + // A response has an associated URL. It is a pointer to the last URL + // in response’s URL list and null if response’s URL list is empty. + const urlList = response.urlList + const length = urlList.length + return length === 0 ? null : urlList[length - 1].toString() +} + +// https://fetch.spec.whatwg.org/#concept-response-location-url +function responseLocationURL (response, requestFragment) { + // 1. If response’s status is not a redirect status, then return null. + if (!redirectStatusSet.has(response.status)) { + return null + } + + // 2. Let location be the result of extracting header list values given + // `Location` and response’s header list. + let location = response.headersList.get('location') + + // 3. If location is a header value, then set location to the result of + // parsing location with response’s URL. + if (location !== null && isValidHeaderValue(location)) { + location = new URL(location, responseURL(response)) + } + + // 4. If location is a URL whose fragment is null, then set location’s + // fragment to requestFragment. + if (location && !location.hash) { + location.hash = requestFragment + } + + // 5. Return location. + return location +} + +/** @returns {URL} */ +function requestCurrentURL (request) { + return request.urlList[request.urlList.length - 1] +} + +function requestBadPort (request) { + // 1. Let url be request’s current URL. + const url = requestCurrentURL(request) + + // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, + // then return blocked. + if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { + return 'blocked' + } + + // 3. Return allowed. + return 'allowed' +} + +function isErrorLike (object) { + return object instanceof Error || ( + object?.constructor?.name === 'Error' || + object?.constructor?.name === 'DOMException' + ) +} + +// Check whether |statusText| is a ByteString and +// matches the Reason-Phrase token production. +// RFC 2616: https://tools.ietf.org/html/rfc2616 +// RFC 7230: https://tools.ietf.org/html/rfc7230 +// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )" +// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116 +function isValidReasonPhrase (statusText) { + for (let i = 0; i < statusText.length; ++i) { + const c = statusText.charCodeAt(i) + if ( + !( + ( + c === 0x09 || // HTAB + (c >= 0x20 && c <= 0x7e) || // SP / VCHAR + (c >= 0x80 && c <= 0xff) + ) // obs-text + ) + ) { + return false + } + } + return true +} + +/** + * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 + * @param {number} c + */ +function isTokenCharCode (c) { + switch (c) { + case 0x22: + case 0x28: + case 0x29: + case 0x2c: + case 0x2f: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0x40: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x7b: + case 0x7d: + // DQUOTE and "(),/:;<=>?@[\]{}" + return false + default: + // VCHAR %x21-7E + return c >= 0x21 && c <= 0x7e + } +} + +/** + * @param {string} characters + */ +function isValidHTTPToken (characters) { + if (characters.length === 0) { + return false + } + for (let i = 0; i < characters.length; ++i) { + if (!isTokenCharCode(characters.charCodeAt(i))) { + return false + } + } + return true +} + +/** + * @see https://fetch.spec.whatwg.org/#header-name + * @param {string} potentialValue + */ +function isValidHeaderName (potentialValue) { + return isValidHTTPToken(potentialValue) +} + +/** + * @see https://fetch.spec.whatwg.org/#header-value + * @param {string} potentialValue + */ +function isValidHeaderValue (potentialValue) { + // - Has no leading or trailing HTTP tab or space bytes. + // - Contains no 0x00 (NUL) or HTTP newline bytes. + if ( + potentialValue.startsWith('\t') || + potentialValue.startsWith(' ') || + potentialValue.endsWith('\t') || + potentialValue.endsWith(' ') + ) { + return false + } + + if ( + potentialValue.includes('\0') || + potentialValue.includes('\r') || + potentialValue.includes('\n') + ) { + return false + } + + return true +} + +// https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect +function setRequestReferrerPolicyOnRedirect (request, actualResponse) { + // Given a request request and a response actualResponse, this algorithm + // updates request’s referrer policy according to the Referrer-Policy + // header (if any) in actualResponse. + + // 1. Let policy be the result of executing § 8.1 Parse a referrer policy + // from a Referrer-Policy header on actualResponse. + + // 8.1 Parse a referrer policy from a Referrer-Policy header + // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list. + const { headersList } = actualResponse + // 2. Let policy be the empty string. + // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token. + // 4. Return policy. + const policyHeader = (headersList.get('referrer-policy') ?? '').split(',') + + // Note: As the referrer-policy can contain multiple policies + // separated by comma, we need to loop through all of them + // and pick the first valid one. + // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy + let policy = '' + if (policyHeader.length > 0) { + // The right-most policy takes precedence. + // The left-most policy is the fallback. + for (let i = policyHeader.length; i !== 0; i--) { + const token = policyHeader[i - 1].trim() + if (referrerPolicyTokens.has(token)) { + policy = token + break + } + } + } + + // 2. If policy is not the empty string, then set request’s referrer policy to policy. + if (policy !== '') { + request.referrerPolicy = policy + } +} + +// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check +function crossOriginResourcePolicyCheck () { + // TODO + return 'allowed' +} + +// https://fetch.spec.whatwg.org/#concept-cors-check +function corsCheck () { + // TODO + return 'success' +} + +// https://fetch.spec.whatwg.org/#concept-tao-check +function TAOCheck () { + // TODO + return 'success' +} + +function appendFetchMetadata (httpRequest) { + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header + // TODO + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header + + // 1. Assert: r’s url is a potentially trustworthy URL. + // TODO + + // 2. Let header be a Structured Header whose value is a token. + let header = null + + // 3. Set header’s value to r’s mode. + header = httpRequest.mode + + // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list. + httpRequest.headersList.set('sec-fetch-mode', header) + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header + // TODO + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header + // TODO +} + +// https://fetch.spec.whatwg.org/#append-a-request-origin-header +function appendRequestOriginHeader (request) { + // 1. Let serializedOrigin be the result of byte-serializing a request origin with request. + let serializedOrigin = request.origin + + // 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list. + if (request.responseTainting === 'cors' || request.mode === 'websocket') { + if (serializedOrigin) { + request.headersList.append('origin', serializedOrigin) + } + + // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then: + } else if (request.method !== 'GET' && request.method !== 'HEAD') { + // 1. Switch on request’s referrer policy: + switch (request.referrerPolicy) { + case 'no-referrer': + // Set serializedOrigin to `null`. + serializedOrigin = null + break + case 'no-referrer-when-downgrade': + case 'strict-origin': + case 'strict-origin-when-cross-origin': + // If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`. + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { + serializedOrigin = null + } + break + case 'same-origin': + // If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`. + if (!sameOrigin(request, requestCurrentURL(request))) { + serializedOrigin = null + } + break + default: + // Do nothing. + } + + if (serializedOrigin) { + // 2. Append (`Origin`, serializedOrigin) to request’s header list. + request.headersList.append('origin', serializedOrigin) + } + } +} + +function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) { + // TODO + return performance.now() +} + +// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info +function createOpaqueTimingInfo (timingInfo) { + return { + startTime: timingInfo.startTime ?? 0, + redirectStartTime: 0, + redirectEndTime: 0, + postRedirectStartTime: timingInfo.startTime ?? 0, + finalServiceWorkerStartTime: 0, + finalNetworkResponseStartTime: 0, + finalNetworkRequestStartTime: 0, + endTime: 0, + encodedBodySize: 0, + decodedBodySize: 0, + finalConnectionTimingInfo: null + } +} + +// https://html.spec.whatwg.org/multipage/origin.html#policy-container +function makePolicyContainer () { + // Note: the fetch spec doesn't make use of embedder policy or CSP list + return { + referrerPolicy: 'strict-origin-when-cross-origin' + } +} + +// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container +function clonePolicyContainer (policyContainer) { + return { + referrerPolicy: policyContainer.referrerPolicy + } +} + +// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer +function determineRequestsReferrer (request) { + // 1. Let policy be request's referrer policy. + const policy = request.referrerPolicy + + // Note: policy cannot (shouldn't) be null or an empty string. + assert(policy) + + // 2. Let environment be request’s client. + + let referrerSource = null + + // 3. Switch on request’s referrer: + if (request.referrer === 'client') { + // Note: node isn't a browser and doesn't implement document/iframes, + // so we bypass this step and replace it with our own. + + const globalOrigin = getGlobalOrigin() + + if (!globalOrigin || globalOrigin.origin === 'null') { + return 'no-referrer' + } + + // note: we need to clone it as it's mutated + referrerSource = new URL(globalOrigin) + } else if (request.referrer instanceof URL) { + // Let referrerSource be request’s referrer. + referrerSource = request.referrer + } + + // 4. Let request’s referrerURL be the result of stripping referrerSource for + // use as a referrer. + let referrerURL = stripURLForReferrer(referrerSource) + + // 5. Let referrerOrigin be the result of stripping referrerSource for use as + // a referrer, with the origin-only flag set to true. + const referrerOrigin = stripURLForReferrer(referrerSource, true) + + // 6. If the result of serializing referrerURL is a string whose length is + // greater than 4096, set referrerURL to referrerOrigin. + if (referrerURL.toString().length > 4096) { + referrerURL = referrerOrigin + } + + const areSameOrigin = sameOrigin(request, referrerURL) + const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && + !isURLPotentiallyTrustworthy(request.url) + + // 8. Execute the switch statements corresponding to the value of policy: + switch (policy) { + case 'origin': return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true) + case 'unsafe-url': return referrerURL + case 'same-origin': + return areSameOrigin ? referrerOrigin : 'no-referrer' + case 'origin-when-cross-origin': + return areSameOrigin ? referrerURL : referrerOrigin + case 'strict-origin-when-cross-origin': { + const currentURL = requestCurrentURL(request) + + // 1. If the origin of referrerURL and the origin of request’s current + // URL are the same, then return referrerURL. + if (sameOrigin(referrerURL, currentURL)) { + return referrerURL + } + + // 2. If referrerURL is a potentially trustworthy URL and request’s + // current URL is not a potentially trustworthy URL, then return no + // referrer. + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return 'no-referrer' + } + + // 3. Return referrerOrigin. + return referrerOrigin + } + case 'strict-origin': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + case 'no-referrer-when-downgrade': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + + default: // eslint-disable-line + return isNonPotentiallyTrustWorthy ? 'no-referrer' : referrerOrigin + } +} + +/** + * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url + * @param {URL} url + * @param {boolean|undefined} originOnly + */ +function stripURLForReferrer (url, originOnly) { + // 1. Assert: url is a URL. + assert(url instanceof URL) + + // 2. If url’s scheme is a local scheme, then return no referrer. + if (url.protocol === 'file:' || url.protocol === 'about:' || url.protocol === 'blank:') { + return 'no-referrer' + } + + // 3. Set url’s username to the empty string. + url.username = '' + + // 4. Set url’s password to the empty string. + url.password = '' + + // 5. Set url’s fragment to null. + url.hash = '' + + // 6. If the origin-only flag is true, then: + if (originOnly) { + // 1. Set url’s path to « the empty string ». + url.pathname = '' + + // 2. Set url’s query to null. + url.search = '' + } + + // 7. Return url. + return url +} + +function isURLPotentiallyTrustworthy (url) { + if (!(url instanceof URL)) { + return false + } + + // If child of about, return true + if (url.href === 'about:blank' || url.href === 'about:srcdoc') { + return true + } + + // If scheme is data, return true + if (url.protocol === 'data:') return true + + // If file, return true + if (url.protocol === 'file:') return true + + return isOriginPotentiallyTrustworthy(url.origin) + + function isOriginPotentiallyTrustworthy (origin) { + // If origin is explicitly null, return false + if (origin == null || origin === 'null') return false + + const originAsURL = new URL(origin) + + // If secure, return true + if (originAsURL.protocol === 'https:' || originAsURL.protocol === 'wss:') { + return true + } + + // If localhost or variants, return true + if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || + (originAsURL.hostname === 'localhost' || originAsURL.hostname.includes('localhost.')) || + (originAsURL.hostname.endsWith('.localhost'))) { + return true + } + + // If any other, return false + return false + } +} + +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist + * @param {Uint8Array} bytes + * @param {string} metadataList + */ +function bytesMatch (bytes, metadataList) { + // If node is not built with OpenSSL support, we cannot check + // a request's integrity, so allow it by default (the spec will + // allow requests if an invalid hash is given, as precedence). + /* istanbul ignore if: only if node is built with --without-ssl */ + if (crypto === undefined) { + return true + } + + // 1. Let parsedMetadata be the result of parsing metadataList. + const parsedMetadata = parseMetadata(metadataList) + + // 2. If parsedMetadata is no metadata, return true. + if (parsedMetadata === 'no metadata') { + return true + } + + // 3. If response is not eligible for integrity validation, return false. + // TODO + + // 4. If parsedMetadata is the empty set, return true. + if (parsedMetadata.length === 0) { + return true + } + + // 5. Let metadata be the result of getting the strongest + // metadata from parsedMetadata. + const strongest = getStrongestMetadata(parsedMetadata) + const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest) + + // 6. For each item in metadata: + for (const item of metadata) { + // 1. Let algorithm be the alg component of item. + const algorithm = item.algo + + // 2. Let expectedValue be the val component of item. + const expectedValue = item.hash + + // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e + // "be liberal with padding". This is annoying, and it's not even in the spec. + + // 3. Let actualValue be the result of applying algorithm to bytes. + let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64') + + if (actualValue[actualValue.length - 1] === '=') { + if (actualValue[actualValue.length - 2] === '=') { + actualValue = actualValue.slice(0, -2) + } else { + actualValue = actualValue.slice(0, -1) + } + } + + // 4. If actualValue is a case-sensitive match for expectedValue, + // return true. + if (compareBase64Mixed(actualValue, expectedValue)) { + return true + } + } + + // 7. Return false. + return false +} + +// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options +// https://www.w3.org/TR/CSP2/#source-list-syntax +// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1 +const parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i + +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata + * @param {string} metadata + */ +function parseMetadata (metadata) { + // 1. Let result be the empty set. + /** @type {{ algo: string, hash: string }[]} */ + const result = [] + + // 2. Let empty be equal to true. + let empty = true + + // 3. For each token returned by splitting metadata on spaces: + for (const token of metadata.split(' ')) { + // 1. Set empty to false. + empty = false + + // 2. Parse token as a hash-with-options. + const parsedToken = parseHashWithOptions.exec(token) + + // 3. If token does not parse, continue to the next token. + if ( + parsedToken === null || + parsedToken.groups === undefined || + parsedToken.groups.algo === undefined + ) { + // Note: Chromium blocks the request at this point, but Firefox + // gives a warning that an invalid integrity was given. The + // correct behavior is to ignore these, and subsequently not + // check the integrity of the resource. + continue + } + + // 4. Let algorithm be the hash-algo component of token. + const algorithm = parsedToken.groups.algo.toLowerCase() + + // 5. If algorithm is a hash function recognized by the user + // agent, add the parsed token to result. + if (supportedHashes.includes(algorithm)) { + result.push(parsedToken.groups) + } + } + + // 4. Return no metadata if empty is true, otherwise return result. + if (empty === true) { + return 'no metadata' + } + + return result +} + +/** + * @param {{ algo: 'sha256' | 'sha384' | 'sha512' }[]} metadataList + */ +function getStrongestMetadata (metadataList) { + // Let algorithm be the algo component of the first item in metadataList. + // Can be sha256 + let algorithm = metadataList[0].algo + // If the algorithm is sha512, then it is the strongest + // and we can return immediately + if (algorithm[3] === '5') { + return algorithm + } + + for (let i = 1; i < metadataList.length; ++i) { + const metadata = metadataList[i] + // If the algorithm is sha512, then it is the strongest + // and we can break the loop immediately + if (metadata.algo[3] === '5') { + algorithm = 'sha512' + break + // If the algorithm is sha384, then a potential sha256 or sha384 is ignored + } else if (algorithm[3] === '3') { + continue + // algorithm is sha256, check if algorithm is sha384 and if so, set it as + // the strongest + } else if (metadata.algo[3] === '3') { + algorithm = 'sha384' + } + } + return algorithm +} + +function filterMetadataListByAlgorithm (metadataList, algorithm) { + if (metadataList.length === 1) { + return metadataList + } + + let pos = 0 + for (let i = 0; i < metadataList.length; ++i) { + if (metadataList[i].algo === algorithm) { + metadataList[pos++] = metadataList[i] + } + } + + metadataList.length = pos + + return metadataList +} + +/** + * Compares two base64 strings, allowing for base64url + * in the second string. + * +* @param {string} actualValue always base64 + * @param {string} expectedValue base64 or base64url + * @returns {boolean} + */ +function compareBase64Mixed (actualValue, expectedValue) { + if (actualValue.length !== expectedValue.length) { + return false + } + for (let i = 0; i < actualValue.length; ++i) { + if (actualValue[i] !== expectedValue[i]) { + if ( + (actualValue[i] === '+' && expectedValue[i] === '-') || + (actualValue[i] === '/' && expectedValue[i] === '_') + ) { + continue + } + return false + } + } + + return true +} + +// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request +function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) { + // TODO +} + +/** + * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin} + * @param {URL} A + * @param {URL} B + */ +function sameOrigin (A, B) { + // 1. If A and B are the same opaque origin, then return true. + if (A.origin === B.origin && A.origin === 'null') { + return true + } + + // 2. If A and B are both tuple origins and their schemes, + // hosts, and port are identical, then return true. + if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { + return true + } + + // 3. Return false. + return false +} + +function createDeferredPromise () { + let res + let rej + const promise = new Promise((resolve, reject) => { + res = resolve + rej = reject + }) + + return { promise, resolve: res, reject: rej } +} + +function isAborted (fetchParams) { + return fetchParams.controller.state === 'aborted' +} + +function isCancelled (fetchParams) { + return fetchParams.controller.state === 'aborted' || + fetchParams.controller.state === 'terminated' +} + +const normalizeMethodRecord = { + delete: 'DELETE', + DELETE: 'DELETE', + get: 'GET', + GET: 'GET', + head: 'HEAD', + HEAD: 'HEAD', + options: 'OPTIONS', + OPTIONS: 'OPTIONS', + post: 'POST', + POST: 'POST', + put: 'PUT', + PUT: 'PUT' +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(normalizeMethodRecord, null) + +/** + * @see https://fetch.spec.whatwg.org/#concept-method-normalize + * @param {string} method + */ +function normalizeMethod (method) { + return normalizeMethodRecord[method.toLowerCase()] ?? method +} + +// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string +function serializeJavascriptValueToJSONString (value) { + // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »). + const result = JSON.stringify(value) + + // 2. If result is undefined, then throw a TypeError. + if (result === undefined) { + throw new TypeError('Value is not JSON serializable') + } + + // 3. Assert: result is a string. + assert(typeof result === 'string') + + // 4. Return result. + return result +} + +// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object +const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) + +/** + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {() => unknown[]} iterator + * @param {string} name name of the instance + * @param {'key'|'value'|'key+value'} kind + */ +function makeIterator (iterator, name, kind) { + const object = { + index: 0, + kind, + target: iterator + } + + const i = { + next () { + // 1. Let interface be the interface for which the iterator prototype object exists. + + // 2. Let thisValue be the this value. + + // 3. Let object be ? ToObject(thisValue). + + // 4. If object is a platform object, then perform a security + // check, passing: + + // 5. If object is not a default iterator object for interface, + // then throw a TypeError. + if (Object.getPrototypeOf(this) !== i) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.` + ) + } + + // 6. Let index be object’s index. + // 7. Let kind be object’s kind. + // 8. Let values be object’s target's value pairs to iterate over. + const { index, kind, target } = object + const values = target() + + // 9. Let len be the length of values. + const len = values.length + + // 10. If index is greater than or equal to len, then return + // CreateIterResultObject(undefined, true). + if (index >= len) { + return { value: undefined, done: true } + } + + // 11. Let pair be the entry in values at index index. + const pair = values[index] + + // 12. Set object’s index to index + 1. + object.index = index + 1 + + // 13. Return the iterator result for pair and kind. + return iteratorResult(pair, kind) + }, + // The class string of an iterator prototype object for a given interface is the + // result of concatenating the identifier of the interface and the string " Iterator". + [Symbol.toStringTag]: `${name} Iterator` + } + + // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%. + Object.setPrototypeOf(i, esIteratorPrototype) + // esIteratorPrototype needs to be the prototype of i + // which is the prototype of an empty object. Yes, it's confusing. + return Object.setPrototypeOf({}, i) +} + +// https://webidl.spec.whatwg.org/#iterator-result +function iteratorResult (pair, kind) { + let result + + // 1. Let result be a value determined by the value of kind: + switch (kind) { + case 'key': { + // 1. Let idlKey be pair’s key. + // 2. Let key be the result of converting idlKey to an + // ECMAScript value. + // 3. result is key. + result = pair[0] + break + } + case 'value': { + // 1. Let idlValue be pair’s value. + // 2. Let value be the result of converting idlValue to + // an ECMAScript value. + // 3. result is value. + result = pair[1] + break + } + case 'key+value': { + // 1. Let idlKey be pair’s key. + // 2. Let idlValue be pair’s value. + // 3. Let key be the result of converting idlKey to an + // ECMAScript value. + // 4. Let value be the result of converting idlValue to + // an ECMAScript value. + // 5. Let array be ! ArrayCreate(2). + // 6. Call ! CreateDataProperty(array, "0", key). + // 7. Call ! CreateDataProperty(array, "1", value). + // 8. result is array. + result = pair + break + } + } + + // 2. Return CreateIterResultObject(result, false). + return { value: result, done: false } +} + +/** + * @see https://fetch.spec.whatwg.org/#body-fully-read + */ +async function fullyReadBody (body, processBody, processBodyError) { + // 1. If taskDestination is null, then set taskDestination to + // the result of starting a new parallel queue. + + // 2. Let successSteps given a byte sequence bytes be to queue a + // fetch task to run processBody given bytes, with taskDestination. + const successSteps = processBody + + // 3. Let errorSteps be to queue a fetch task to run processBodyError, + // with taskDestination. + const errorSteps = processBodyError + + // 4. Let reader be the result of getting a reader for body’s stream. + // If that threw an exception, then run errorSteps with that + // exception and return. + let reader + + try { + reader = body.stream.getReader() + } catch (e) { + errorSteps(e) + return + } + + // 5. Read all bytes from reader, given successSteps and errorSteps. + try { + const result = await readAllBytes(reader) + successSteps(result) + } catch (e) { + errorSteps(e) + } +} + +/** @type {ReadableStream} */ +let ReadableStream = globalThis.ReadableStream + +function isReadableStreamLike (stream) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + return stream instanceof ReadableStream || ( + stream[Symbol.toStringTag] === 'ReadableStream' && + typeof stream.tee === 'function' + ) +} + +const MAXIMUM_ARGUMENT_LENGTH = 65535 + +/** + * @see https://infra.spec.whatwg.org/#isomorphic-decode + * @param {number[]|Uint8Array} input + */ +function isomorphicDecode (input) { + // 1. To isomorphic decode a byte sequence input, return a string whose code point + // length is equal to input’s length and whose code points have the same values + // as the values of input’s bytes, in the same order. + + if (input.length < MAXIMUM_ARGUMENT_LENGTH) { + return String.fromCharCode(...input) + } + + return input.reduce((previous, current) => previous + String.fromCharCode(current), '') +} + +/** + * @param {ReadableStreamController} controller + */ +function readableStreamClose (controller) { + try { + controller.close() + } catch (err) { + // TODO: add comment explaining why this error occurs. + if (!err.message.includes('Controller is already closed')) { + throw err + } + } +} + +/** + * @see https://infra.spec.whatwg.org/#isomorphic-encode + * @param {string} input + */ +function isomorphicEncode (input) { + // 1. Assert: input contains no code points greater than U+00FF. + for (let i = 0; i < input.length; i++) { + assert(input.charCodeAt(i) <= 0xFF) + } + + // 2. Return a byte sequence whose length is equal to input’s code + // point length and whose bytes have the same values as the + // values of input’s code points, in the same order + return input +} + +/** + * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes + * @see https://streams.spec.whatwg.org/#read-loop + * @param {ReadableStreamDefaultReader} reader + */ +async function readAllBytes (reader) { + const bytes = [] + let byteLength = 0 + + while (true) { + const { done, value: chunk } = await reader.read() + + if (done) { + // 1. Call successSteps with bytes. + return Buffer.concat(bytes, byteLength) + } + + // 1. If chunk is not a Uint8Array object, call failureSteps + // with a TypeError and abort these steps. + if (!isUint8Array(chunk)) { + throw new TypeError('Received non-Uint8Array chunk') + } + + // 2. Append the bytes represented by chunk to bytes. + bytes.push(chunk) + byteLength += chunk.length + + // 3. Read-loop given reader, bytes, successSteps, and failureSteps. + } +} + +/** + * @see https://fetch.spec.whatwg.org/#is-local + * @param {URL} url + */ +function urlIsLocal (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' +} + +/** + * @param {string|URL} url + */ +function urlHasHttpsScheme (url) { + if (typeof url === 'string') { + return url.startsWith('https:') + } + + return url.protocol === 'https:' +} + +/** + * @see https://fetch.spec.whatwg.org/#http-scheme + * @param {URL} url + */ +function urlIsHttpHttpsScheme (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'http:' || protocol === 'https:' +} + +/** + * Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0. + */ +const hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key)) + +module.exports = { + isAborted, + isCancelled, + createDeferredPromise, + ReadableStreamFrom, + toUSVString, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + coarsenedSharedCurrentTime, + determineRequestsReferrer, + makePolicyContainer, + clonePolicyContainer, + appendFetchMetadata, + appendRequestOriginHeader, + TAOCheck, + corsCheck, + crossOriginResourcePolicyCheck, + createOpaqueTimingInfo, + setRequestReferrerPolicyOnRedirect, + isValidHTTPToken, + requestBadPort, + requestCurrentURL, + responseURL, + responseLocationURL, + isBlobLike, + isURLPotentiallyTrustworthy, + isValidReasonPhrase, + sameOrigin, + normalizeMethod, + serializeJavascriptValueToJSONString, + makeIterator, + isValidHeaderName, + isValidHeaderValue, + hasOwn, + isErrorLike, + fullyReadBody, + bytesMatch, + isReadableStreamLike, + readableStreamClose, + isomorphicEncode, + isomorphicDecode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme, + readAllBytes, + normalizeMethodRecord, + parseMetadata +} + + +/***/ }), + +/***/ 74222: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { types } = __nccwpck_require__(39023) +const { hasOwn, toUSVString } = __nccwpck_require__(15523) + +/** @type {import('../../types/webidl').Webidl} */ +const webidl = {} +webidl.converters = {} +webidl.util = {} +webidl.errors = {} + +webidl.errors.exception = function (message) { + return new TypeError(`${message.header}: ${message.message}`) +} + +webidl.errors.conversionFailed = function (context) { + const plural = context.types.length === 1 ? '' : ' one of' + const message = + `${context.argument} could not be converted to` + + `${plural}: ${context.types.join(', ')}.` + + return webidl.errors.exception({ + header: context.prefix, + message + }) +} + +webidl.errors.invalidArgument = function (context) { + return webidl.errors.exception({ + header: context.prefix, + message: `"${context.value}" is an invalid ${context.type}.` + }) +} + +// https://webidl.spec.whatwg.org/#implements +webidl.brandCheck = function (V, I, opts = undefined) { + if (opts?.strict !== false && !(V instanceof I)) { + throw new TypeError('Illegal invocation') + } else { + return V?.[Symbol.toStringTag] === I.prototype[Symbol.toStringTag] + } +} + +webidl.argumentLengthCheck = function ({ length }, min, ctx) { + if (length < min) { + throw webidl.errors.exception({ + message: `${min} argument${min !== 1 ? 's' : ''} required, ` + + `but${length ? ' only' : ''} ${length} found.`, + ...ctx + }) + } +} + +webidl.illegalConstructor = function () { + throw webidl.errors.exception({ + header: 'TypeError', + message: 'Illegal constructor' + }) +} + +// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values +webidl.util.Type = function (V) { + switch (typeof V) { + case 'undefined': return 'Undefined' + case 'boolean': return 'Boolean' + case 'string': return 'String' + case 'symbol': return 'Symbol' + case 'number': return 'Number' + case 'bigint': return 'BigInt' + case 'function': + case 'object': { + if (V === null) { + return 'Null' + } + + return 'Object' + } + } +} + +// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint +webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) { + let upperBound + let lowerBound + + // 1. If bitLength is 64, then: + if (bitLength === 64) { + // 1. Let upperBound be 2^53 − 1. + upperBound = Math.pow(2, 53) - 1 + + // 2. If signedness is "unsigned", then let lowerBound be 0. + if (signedness === 'unsigned') { + lowerBound = 0 + } else { + // 3. Otherwise let lowerBound be −2^53 + 1. + lowerBound = Math.pow(-2, 53) + 1 + } + } else if (signedness === 'unsigned') { + // 2. Otherwise, if signedness is "unsigned", then: + + // 1. Let lowerBound be 0. + lowerBound = 0 + + // 2. Let upperBound be 2^bitLength − 1. + upperBound = Math.pow(2, bitLength) - 1 + } else { + // 3. Otherwise: + + // 1. Let lowerBound be -2^bitLength − 1. + lowerBound = Math.pow(-2, bitLength) - 1 + + // 2. Let upperBound be 2^bitLength − 1 − 1. + upperBound = Math.pow(2, bitLength - 1) - 1 + } + + // 4. Let x be ? ToNumber(V). + let x = Number(V) + + // 5. If x is −0, then set x to +0. + if (x === 0) { + x = 0 + } + + // 6. If the conversion is to an IDL type associated + // with the [EnforceRange] extended attribute, then: + if (opts.enforceRange === true) { + // 1. If x is NaN, +∞, or −∞, then throw a TypeError. + if ( + Number.isNaN(x) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Could not convert ${V} to an integer.` + }) + } + + // 2. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) + + // 3. If x < lowerBound or x > upperBound, then + // throw a TypeError. + if (x < lowerBound || x > upperBound) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` + }) + } + + // 4. Return x. + return x + } + + // 7. If x is not NaN and the conversion is to an IDL + // type associated with the [Clamp] extended + // attribute, then: + if (!Number.isNaN(x) && opts.clamp === true) { + // 1. Set x to min(max(x, lowerBound), upperBound). + x = Math.min(Math.max(x, lowerBound), upperBound) + + // 2. Round x to the nearest integer, choosing the + // even integer if it lies halfway between two, + // and choosing +0 rather than −0. + if (Math.floor(x) % 2 === 0) { + x = Math.floor(x) + } else { + x = Math.ceil(x) + } + + // 3. Return x. + return x + } + + // 8. If x is NaN, +0, +∞, or −∞, then return +0. + if ( + Number.isNaN(x) || + (x === 0 && Object.is(0, x)) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + return 0 + } + + // 9. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) + + // 10. Set x to x modulo 2^bitLength. + x = x % Math.pow(2, bitLength) + + // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, + // then return x − 2^bitLength. + if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { + return x - Math.pow(2, bitLength) + } + + // 12. Otherwise, return x. + return x +} + +// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart +webidl.util.IntegerPart = function (n) { + // 1. Let r be floor(abs(n)). + const r = Math.floor(Math.abs(n)) + + // 2. If n < 0, then return -1 × r. + if (n < 0) { + return -1 * r + } + + // 3. Otherwise, return r. + return r +} + +// https://webidl.spec.whatwg.org/#es-sequence +webidl.sequenceConverter = function (converter) { + return (V) => { + // 1. If Type(V) is not Object, throw a TypeError. + if (webidl.util.Type(V) !== 'Object') { + throw webidl.errors.exception({ + header: 'Sequence', + message: `Value of type ${webidl.util.Type(V)} is not an Object.` + }) + } + + // 2. Let method be ? GetMethod(V, @@iterator). + /** @type {Generator} */ + const method = V?.[Symbol.iterator]?.() + const seq = [] + + // 3. If method is undefined, throw a TypeError. + if ( + method === undefined || + typeof method.next !== 'function' + ) { + throw webidl.errors.exception({ + header: 'Sequence', + message: 'Object is not an iterator.' + }) + } + + // https://webidl.spec.whatwg.org/#create-sequence-from-iterable + while (true) { + const { done, value } = method.next() + + if (done) { + break + } + + seq.push(converter(value)) + } + + return seq + } +} + +// https://webidl.spec.whatwg.org/#es-to-record +webidl.recordConverter = function (keyConverter, valueConverter) { + return (O) => { + // 1. If Type(O) is not Object, throw a TypeError. + if (webidl.util.Type(O) !== 'Object') { + throw webidl.errors.exception({ + header: 'Record', + message: `Value of type ${webidl.util.Type(O)} is not an Object.` + }) + } + + // 2. Let result be a new empty instance of record. + const result = {} + + if (!types.isProxy(O)) { + // Object.keys only returns enumerable properties + const keys = Object.keys(O) + + for (const key of keys) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key) + + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key]) + + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } + + // 5. Return result. + return result + } + + // 3. Let keys be ? O.[[OwnPropertyKeys]](). + const keys = Reflect.ownKeys(O) + + // 4. For each key of keys. + for (const key of keys) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + const desc = Reflect.getOwnPropertyDescriptor(O, key) + + // 2. If desc is not undefined and desc.[[Enumerable]] is true: + if (desc?.enumerable) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key) + + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key]) + + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } + } + + // 5. Return result. + return result + } +} + +webidl.interfaceConverter = function (i) { + return (V, opts = {}) => { + if (opts.strict !== false && !(V instanceof i)) { + throw webidl.errors.exception({ + header: i.name, + message: `Expected ${V} to be an instance of ${i.name}.` + }) + } + + return V + } +} + +webidl.dictionaryConverter = function (converters) { + return (dictionary) => { + const type = webidl.util.Type(dictionary) + const dict = {} + + if (type === 'Null' || type === 'Undefined') { + return dict + } else if (type !== 'Object') { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` + }) + } + + for (const options of converters) { + const { key, defaultValue, required, converter } = options + + if (required === true) { + if (!hasOwn(dictionary, key)) { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `Missing required key "${key}".` + }) + } + } + + let value = dictionary[key] + const hasDefault = hasOwn(options, 'defaultValue') + + // Only use defaultValue if value is undefined and + // a defaultValue options was provided. + if (hasDefault && value !== null) { + value = value ?? defaultValue + } + + // A key can be optional and have no default value. + // When this happens, do not perform a conversion, + // and do not assign the key a value. + if (required || hasDefault || value !== undefined) { + value = converter(value) + + if ( + options.allowedValues && + !options.allowedValues.includes(value) + ) { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` + }) + } + + dict[key] = value + } + } + + return dict + } +} + +webidl.nullableConverter = function (converter) { + return (V) => { + if (V === null) { + return V + } + + return converter(V) + } +} + +// https://webidl.spec.whatwg.org/#es-DOMString +webidl.converters.DOMString = function (V, opts = {}) { + // 1. If V is null and the conversion is to an IDL type + // associated with the [LegacyNullToEmptyString] + // extended attribute, then return the DOMString value + // that represents the empty string. + if (V === null && opts.legacyNullToEmptyString) { + return '' + } + + // 2. Let x be ? ToString(V). + if (typeof V === 'symbol') { + throw new TypeError('Could not convert argument of type symbol to string.') + } + + // 3. Return the IDL DOMString value that represents the + // same sequence of code units as the one the + // ECMAScript String value x represents. + return String(V) +} + +// https://webidl.spec.whatwg.org/#es-ByteString +webidl.converters.ByteString = function (V) { + // 1. Let x be ? ToString(V). + // Note: DOMString converter perform ? ToString(V) + const x = webidl.converters.DOMString(V) + + // 2. If the value of any element of x is greater than + // 255, then throw a TypeError. + for (let index = 0; index < x.length; index++) { + if (x.charCodeAt(index) > 255) { + throw new TypeError( + 'Cannot convert argument to a ByteString because the character at ' + + `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` + ) + } + } + + // 3. Return an IDL ByteString value whose length is the + // length of x, and where the value of each element is + // the value of the corresponding element of x. + return x +} + +// https://webidl.spec.whatwg.org/#es-USVString +webidl.converters.USVString = toUSVString + +// https://webidl.spec.whatwg.org/#es-boolean +webidl.converters.boolean = function (V) { + // 1. Let x be the result of computing ToBoolean(V). + const x = Boolean(V) + + // 2. Return the IDL boolean value that is the one that represents + // the same truth value as the ECMAScript Boolean value x. + return x +} + +// https://webidl.spec.whatwg.org/#es-any +webidl.converters.any = function (V) { + return V +} + +// https://webidl.spec.whatwg.org/#es-long-long +webidl.converters['long long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 64, "signed"). + const x = webidl.util.ConvertToInt(V, 64, 'signed') + + // 2. Return the IDL long long value that represents + // the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-long-long +webidl.converters['unsigned long long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). + const x = webidl.util.ConvertToInt(V, 64, 'unsigned') + + // 2. Return the IDL unsigned long long value that + // represents the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-long +webidl.converters['unsigned long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). + const x = webidl.util.ConvertToInt(V, 32, 'unsigned') + + // 2. Return the IDL unsigned long value that + // represents the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-short +webidl.converters['unsigned short'] = function (V, opts) { + // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). + const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts) + + // 2. Return the IDL unsigned short value that represents + // the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#idl-ArrayBuffer +webidl.converters.ArrayBuffer = function (V, opts = {}) { + // 1. If Type(V) is not Object, or V does not have an + // [[ArrayBufferData]] internal slot, then throw a + // TypeError. + // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances + // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances + if ( + webidl.util.Type(V) !== 'Object' || + !types.isAnyArrayBuffer(V) + ) { + throw webidl.errors.conversionFailed({ + prefix: `${V}`, + argument: `${V}`, + types: ['ArrayBuffer'] + }) + } + + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V) is true, then throw a + // TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V) is true, then throw a + // TypeError. + // Note: resizable ArrayBuffers are currently a proposal. + + // 4. Return the IDL ArrayBuffer value that is a + // reference to the same object as V. + return V +} + +webidl.converters.TypedArray = function (V, T, opts = {}) { + // 1. Let T be the IDL type V is being converted to. + + // 2. If Type(V) is not Object, or V does not have a + // [[TypedArrayName]] internal slot with a value + // equal to T’s name, then throw a TypeError. + if ( + webidl.util.Type(V) !== 'Object' || + !types.isTypedArray(V) || + V.constructor.name !== T.name + ) { + throw webidl.errors.conversionFailed({ + prefix: `${T.name}`, + argument: `${V}`, + types: [T.name] + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 4. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + // Note: resizable array buffers are currently a proposal + + // 5. Return the IDL value of type T that is a reference + // to the same object as V. + return V +} + +webidl.converters.DataView = function (V, opts = {}) { + // 1. If Type(V) is not Object, or V does not have a + // [[DataView]] internal slot, then throw a TypeError. + if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) { + throw webidl.errors.exception({ + header: 'DataView', + message: 'Object is not a DataView.' + }) + } + + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, + // then throw a TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + // Note: resizable ArrayBuffers are currently a proposal + + // 4. Return the IDL DataView value that is a reference + // to the same object as V. + return V +} + +// https://webidl.spec.whatwg.org/#BufferSource +webidl.converters.BufferSource = function (V, opts = {}) { + if (types.isAnyArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, opts) + } + + if (types.isTypedArray(V)) { + return webidl.converters.TypedArray(V, V.constructor) + } + + if (types.isDataView(V)) { + return webidl.converters.DataView(V, opts) + } + + throw new TypeError(`Could not convert ${V} to a BufferSource.`) +} + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.ByteString +) + +webidl.converters['sequence>'] = webidl.sequenceConverter( + webidl.converters['sequence'] +) + +webidl.converters['record'] = webidl.recordConverter( + webidl.converters.ByteString, + webidl.converters.ByteString +) + +module.exports = { + webidl +} + + +/***/ }), + +/***/ 40396: +/***/ ((module) => { + +"use strict"; + + +/** + * @see https://encoding.spec.whatwg.org/#concept-encoding-get + * @param {string|undefined} label + */ +function getEncoding (label) { + if (!label) { + return 'failure' + } + + // 1. Remove any leading and trailing ASCII whitespace from label. + // 2. If label is an ASCII case-insensitive match for any of the + // labels listed in the table below, then return the + // corresponding encoding; otherwise return failure. + switch (label.trim().toLowerCase()) { + case 'unicode-1-1-utf-8': + case 'unicode11utf8': + case 'unicode20utf8': + case 'utf-8': + case 'utf8': + case 'x-unicode20utf8': + return 'UTF-8' + case '866': + case 'cp866': + case 'csibm866': + case 'ibm866': + return 'IBM866' + case 'csisolatin2': + case 'iso-8859-2': + case 'iso-ir-101': + case 'iso8859-2': + case 'iso88592': + case 'iso_8859-2': + case 'iso_8859-2:1987': + case 'l2': + case 'latin2': + return 'ISO-8859-2' + case 'csisolatin3': + case 'iso-8859-3': + case 'iso-ir-109': + case 'iso8859-3': + case 'iso88593': + case 'iso_8859-3': + case 'iso_8859-3:1988': + case 'l3': + case 'latin3': + return 'ISO-8859-3' + case 'csisolatin4': + case 'iso-8859-4': + case 'iso-ir-110': + case 'iso8859-4': + case 'iso88594': + case 'iso_8859-4': + case 'iso_8859-4:1988': + case 'l4': + case 'latin4': + return 'ISO-8859-4' + case 'csisolatincyrillic': + case 'cyrillic': + case 'iso-8859-5': + case 'iso-ir-144': + case 'iso8859-5': + case 'iso88595': + case 'iso_8859-5': + case 'iso_8859-5:1988': + return 'ISO-8859-5' + case 'arabic': + case 'asmo-708': + case 'csiso88596e': + case 'csiso88596i': + case 'csisolatinarabic': + case 'ecma-114': + case 'iso-8859-6': + case 'iso-8859-6-e': + case 'iso-8859-6-i': + case 'iso-ir-127': + case 'iso8859-6': + case 'iso88596': + case 'iso_8859-6': + case 'iso_8859-6:1987': + return 'ISO-8859-6' + case 'csisolatingreek': + case 'ecma-118': + case 'elot_928': + case 'greek': + case 'greek8': + case 'iso-8859-7': + case 'iso-ir-126': + case 'iso8859-7': + case 'iso88597': + case 'iso_8859-7': + case 'iso_8859-7:1987': + case 'sun_eu_greek': + return 'ISO-8859-7' + case 'csiso88598e': + case 'csisolatinhebrew': + case 'hebrew': + case 'iso-8859-8': + case 'iso-8859-8-e': + case 'iso-ir-138': + case 'iso8859-8': + case 'iso88598': + case 'iso_8859-8': + case 'iso_8859-8:1988': + case 'visual': + return 'ISO-8859-8' + case 'csiso88598i': + case 'iso-8859-8-i': + case 'logical': + return 'ISO-8859-8-I' + case 'csisolatin6': + case 'iso-8859-10': + case 'iso-ir-157': + case 'iso8859-10': + case 'iso885910': + case 'l6': + case 'latin6': + return 'ISO-8859-10' + case 'iso-8859-13': + case 'iso8859-13': + case 'iso885913': + return 'ISO-8859-13' + case 'iso-8859-14': + case 'iso8859-14': + case 'iso885914': + return 'ISO-8859-14' + case 'csisolatin9': + case 'iso-8859-15': + case 'iso8859-15': + case 'iso885915': + case 'iso_8859-15': + case 'l9': + return 'ISO-8859-15' + case 'iso-8859-16': + return 'ISO-8859-16' + case 'cskoi8r': + case 'koi': + case 'koi8': + case 'koi8-r': + case 'koi8_r': + return 'KOI8-R' + case 'koi8-ru': + case 'koi8-u': + return 'KOI8-U' + case 'csmacintosh': + case 'mac': + case 'macintosh': + case 'x-mac-roman': + return 'macintosh' + case 'iso-8859-11': + case 'iso8859-11': + case 'iso885911': + case 'tis-620': + case 'windows-874': + return 'windows-874' + case 'cp1250': + case 'windows-1250': + case 'x-cp1250': + return 'windows-1250' + case 'cp1251': + case 'windows-1251': + case 'x-cp1251': + return 'windows-1251' + case 'ansi_x3.4-1968': + case 'ascii': + case 'cp1252': + case 'cp819': + case 'csisolatin1': + case 'ibm819': + case 'iso-8859-1': + case 'iso-ir-100': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'iso_8859-1:1987': + case 'l1': + case 'latin1': + case 'us-ascii': + case 'windows-1252': + case 'x-cp1252': + return 'windows-1252' + case 'cp1253': + case 'windows-1253': + case 'x-cp1253': + return 'windows-1253' + case 'cp1254': + case 'csisolatin5': + case 'iso-8859-9': + case 'iso-ir-148': + case 'iso8859-9': + case 'iso88599': + case 'iso_8859-9': + case 'iso_8859-9:1989': + case 'l5': + case 'latin5': + case 'windows-1254': + case 'x-cp1254': + return 'windows-1254' + case 'cp1255': + case 'windows-1255': + case 'x-cp1255': + return 'windows-1255' + case 'cp1256': + case 'windows-1256': + case 'x-cp1256': + return 'windows-1256' + case 'cp1257': + case 'windows-1257': + case 'x-cp1257': + return 'windows-1257' + case 'cp1258': + case 'windows-1258': + case 'x-cp1258': + return 'windows-1258' + case 'x-mac-cyrillic': + case 'x-mac-ukrainian': + return 'x-mac-cyrillic' + case 'chinese': + case 'csgb2312': + case 'csiso58gb231280': + case 'gb2312': + case 'gb_2312': + case 'gb_2312-80': + case 'gbk': + case 'iso-ir-58': + case 'x-gbk': + return 'GBK' + case 'gb18030': + return 'gb18030' + case 'big5': + case 'big5-hkscs': + case 'cn-big5': + case 'csbig5': + case 'x-x-big5': + return 'Big5' + case 'cseucpkdfmtjapanese': + case 'euc-jp': + case 'x-euc-jp': + return 'EUC-JP' + case 'csiso2022jp': + case 'iso-2022-jp': + return 'ISO-2022-JP' + case 'csshiftjis': + case 'ms932': + case 'ms_kanji': + case 'shift-jis': + case 'shift_jis': + case 'sjis': + case 'windows-31j': + case 'x-sjis': + return 'Shift_JIS' + case 'cseuckr': + case 'csksc56011987': + case 'euc-kr': + case 'iso-ir-149': + case 'korean': + case 'ks_c_5601-1987': + case 'ks_c_5601-1989': + case 'ksc5601': + case 'ksc_5601': + case 'windows-949': + return 'EUC-KR' + case 'csiso2022kr': + case 'hz-gb-2312': + case 'iso-2022-cn': + case 'iso-2022-cn-ext': + case 'iso-2022-kr': + case 'replacement': + return 'replacement' + case 'unicodefffe': + case 'utf-16be': + return 'UTF-16BE' + case 'csunicode': + case 'iso-10646-ucs-2': + case 'ucs-2': + case 'unicode': + case 'unicodefeff': + case 'utf-16': + case 'utf-16le': + return 'UTF-16LE' + case 'x-user-defined': + return 'x-user-defined' + default: return 'failure' + } +} + +module.exports = { + getEncoding +} + + +/***/ }), + +/***/ 82160: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} = __nccwpck_require__(10165) +const { + kState, + kError, + kResult, + kEvents, + kAborted +} = __nccwpck_require__(86812) +const { webidl } = __nccwpck_require__(74222) +const { kEnumerableProperty } = __nccwpck_require__(3440) + +class FileReader extends EventTarget { + constructor () { + super() + + this[kState] = 'empty' + this[kResult] = null + this[kError] = null + this[kEvents] = { + loadend: null, + error: null, + abort: null, + load: null, + progress: null, + loadstart: null + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + * @param {import('buffer').Blob} blob + */ + readAsArrayBuffer (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsArrayBuffer' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsArrayBuffer(blob) method, when invoked, + // must initiate a read operation for blob with ArrayBuffer. + readOperation(this, blob, 'ArrayBuffer') + } + + /** + * @see https://w3c.github.io/FileAPI/#readAsBinaryString + * @param {import('buffer').Blob} blob + */ + readAsBinaryString (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsBinaryString' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsBinaryString(blob) method, when invoked, + // must initiate a read operation for blob with BinaryString. + readOperation(this, blob, 'BinaryString') + } + + /** + * @see https://w3c.github.io/FileAPI/#readAsDataText + * @param {import('buffer').Blob} blob + * @param {string?} encoding + */ + readAsText (blob, encoding = undefined) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsText' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + if (encoding !== undefined) { + encoding = webidl.converters.DOMString(encoding) + } + + // The readAsText(blob, encoding) method, when invoked, + // must initiate a read operation for blob with Text and encoding. + readOperation(this, blob, 'Text', encoding) + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL + * @param {import('buffer').Blob} blob + */ + readAsDataURL (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsDataURL' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsDataURL(blob) method, when invoked, must + // initiate a read operation for blob with DataURL. + readOperation(this, blob, 'DataURL') + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-abort + */ + abort () { + // 1. If this's state is "empty" or if this's state is + // "done" set this's result to null and terminate + // this algorithm. + if (this[kState] === 'empty' || this[kState] === 'done') { + this[kResult] = null + return + } + + // 2. If this's state is "loading" set this's state to + // "done" and set this's result to null. + if (this[kState] === 'loading') { + this[kState] = 'done' + this[kResult] = null + } + + // 3. If there are any tasks from this on the file reading + // task source in an affiliated task queue, then remove + // those tasks from that task queue. + this[kAborted] = true + + // 4. Terminate the algorithm for the read method being processed. + // TODO + + // 5. Fire a progress event called abort at this. + fireAProgressEvent('abort', this) + + // 6. If this's state is not "loading", fire a progress + // event called loadend at this. + if (this[kState] !== 'loading') { + fireAProgressEvent('loadend', this) + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-readystate + */ + get readyState () { + webidl.brandCheck(this, FileReader) + + switch (this[kState]) { + case 'empty': return this.EMPTY + case 'loading': return this.LOADING + case 'done': return this.DONE + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-result + */ + get result () { + webidl.brandCheck(this, FileReader) + + // The result attribute’s getter, when invoked, must return + // this's result. + return this[kResult] + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-error + */ + get error () { + webidl.brandCheck(this, FileReader) + + // The error attribute’s getter, when invoked, must return + // this's error. + return this[kError] + } + + get onloadend () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].loadend + } + + set onloadend (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].loadend) { + this.removeEventListener('loadend', this[kEvents].loadend) + } + + if (typeof fn === 'function') { + this[kEvents].loadend = fn + this.addEventListener('loadend', fn) + } else { + this[kEvents].loadend = null + } + } + + get onerror () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].error + } + + set onerror (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].error) { + this.removeEventListener('error', this[kEvents].error) + } + + if (typeof fn === 'function') { + this[kEvents].error = fn + this.addEventListener('error', fn) + } else { + this[kEvents].error = null + } + } + + get onloadstart () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].loadstart + } + + set onloadstart (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].loadstart) { + this.removeEventListener('loadstart', this[kEvents].loadstart) + } + + if (typeof fn === 'function') { + this[kEvents].loadstart = fn + this.addEventListener('loadstart', fn) + } else { + this[kEvents].loadstart = null + } + } + + get onprogress () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].progress + } + + set onprogress (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].progress) { + this.removeEventListener('progress', this[kEvents].progress) + } + + if (typeof fn === 'function') { + this[kEvents].progress = fn + this.addEventListener('progress', fn) + } else { + this[kEvents].progress = null + } + } + + get onload () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].load + } + + set onload (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].load) { + this.removeEventListener('load', this[kEvents].load) + } + + if (typeof fn === 'function') { + this[kEvents].load = fn + this.addEventListener('load', fn) + } else { + this[kEvents].load = null + } + } + + get onabort () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].abort + } + + set onabort (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].abort) { + this.removeEventListener('abort', this[kEvents].abort) + } + + if (typeof fn === 'function') { + this[kEvents].abort = fn + this.addEventListener('abort', fn) + } else { + this[kEvents].abort = null + } + } +} + +// https://w3c.github.io/FileAPI/#dom-filereader-empty +FileReader.EMPTY = FileReader.prototype.EMPTY = 0 +// https://w3c.github.io/FileAPI/#dom-filereader-loading +FileReader.LOADING = FileReader.prototype.LOADING = 1 +// https://w3c.github.io/FileAPI/#dom-filereader-done +FileReader.DONE = FileReader.prototype.DONE = 2 + +Object.defineProperties(FileReader.prototype, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors, + readAsArrayBuffer: kEnumerableProperty, + readAsBinaryString: kEnumerableProperty, + readAsText: kEnumerableProperty, + readAsDataURL: kEnumerableProperty, + abort: kEnumerableProperty, + readyState: kEnumerableProperty, + result: kEnumerableProperty, + error: kEnumerableProperty, + onloadstart: kEnumerableProperty, + onprogress: kEnumerableProperty, + onload: kEnumerableProperty, + onabort: kEnumerableProperty, + onerror: kEnumerableProperty, + onloadend: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'FileReader', + writable: false, + enumerable: false, + configurable: true + } +}) + +Object.defineProperties(FileReader, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors +}) + +module.exports = { + FileReader +} + + +/***/ }), + +/***/ 15976: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(74222) + +const kState = Symbol('ProgressEvent state') + +/** + * @see https://xhr.spec.whatwg.org/#progressevent + */ +class ProgressEvent extends Event { + constructor (type, eventInitDict = {}) { + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}) + + super(type, eventInitDict) + + this[kState] = { + lengthComputable: eventInitDict.lengthComputable, + loaded: eventInitDict.loaded, + total: eventInitDict.total + } + } + + get lengthComputable () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].lengthComputable + } + + get loaded () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].loaded + } + + get total () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].total + } +} + +webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ + { + key: 'lengthComputable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'loaded', + converter: webidl.converters['unsigned long long'], + defaultValue: 0 + }, + { + key: 'total', + converter: webidl.converters['unsigned long long'], + defaultValue: 0 + }, + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: false + } +]) + +module.exports = { + ProgressEvent +} + + +/***/ }), + +/***/ 86812: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kState: Symbol('FileReader state'), + kResult: Symbol('FileReader result'), + kError: Symbol('FileReader error'), + kLastProgressEventFired: Symbol('FileReader last progress event fired timestamp'), + kEvents: Symbol('FileReader events'), + kAborted: Symbol('FileReader aborted') +} + + +/***/ }), + +/***/ 10165: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + kState, + kError, + kResult, + kAborted, + kLastProgressEventFired +} = __nccwpck_require__(86812) +const { ProgressEvent } = __nccwpck_require__(15976) +const { getEncoding } = __nccwpck_require__(40396) +const { DOMException } = __nccwpck_require__(87326) +const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(94322) +const { types } = __nccwpck_require__(39023) +const { StringDecoder } = __nccwpck_require__(13193) +const { btoa } = __nccwpck_require__(20181) + +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} + +/** + * @see https://w3c.github.io/FileAPI/#readOperation + * @param {import('./filereader').FileReader} fr + * @param {import('buffer').Blob} blob + * @param {string} type + * @param {string?} encodingName + */ +function readOperation (fr, blob, type, encodingName) { + // 1. If fr’s state is "loading", throw an InvalidStateError + // DOMException. + if (fr[kState] === 'loading') { + throw new DOMException('Invalid state', 'InvalidStateError') + } + + // 2. Set fr’s state to "loading". + fr[kState] = 'loading' + + // 3. Set fr’s result to null. + fr[kResult] = null + + // 4. Set fr’s error to null. + fr[kError] = null + + // 5. Let stream be the result of calling get stream on blob. + /** @type {import('stream/web').ReadableStream} */ + const stream = blob.stream() + + // 6. Let reader be the result of getting a reader from stream. + const reader = stream.getReader() + + // 7. Let bytes be an empty byte sequence. + /** @type {Uint8Array[]} */ + const bytes = [] + + // 8. Let chunkPromise be the result of reading a chunk from + // stream with reader. + let chunkPromise = reader.read() + + // 9. Let isFirstChunk be true. + let isFirstChunk = true + + // 10. In parallel, while true: + // Note: "In parallel" just means non-blocking + // Note 2: readOperation itself cannot be async as double + // reading the body would then reject the promise, instead + // of throwing an error. + ;(async () => { + while (!fr[kAborted]) { + // 1. Wait for chunkPromise to be fulfilled or rejected. + try { + const { done, value } = await chunkPromise + + // 2. If chunkPromise is fulfilled, and isFirstChunk is + // true, queue a task to fire a progress event called + // loadstart at fr. + if (isFirstChunk && !fr[kAborted]) { + queueMicrotask(() => { + fireAProgressEvent('loadstart', fr) + }) + } + + // 3. Set isFirstChunk to false. + isFirstChunk = false + + // 4. If chunkPromise is fulfilled with an object whose + // done property is false and whose value property is + // a Uint8Array object, run these steps: + if (!done && types.isUint8Array(value)) { + // 1. Let bs be the byte sequence represented by the + // Uint8Array object. + + // 2. Append bs to bytes. + bytes.push(value) + + // 3. If roughly 50ms have passed since these steps + // were last invoked, queue a task to fire a + // progress event called progress at fr. + if ( + ( + fr[kLastProgressEventFired] === undefined || + Date.now() - fr[kLastProgressEventFired] >= 50 + ) && + !fr[kAborted] + ) { + fr[kLastProgressEventFired] = Date.now() + queueMicrotask(() => { + fireAProgressEvent('progress', fr) + }) + } + + // 4. Set chunkPromise to the result of reading a + // chunk from stream with reader. + chunkPromise = reader.read() + } else if (done) { + // 5. Otherwise, if chunkPromise is fulfilled with an + // object whose done property is true, queue a task + // to run the following steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' + + // 2. Let result be the result of package data given + // bytes, type, blob’s type, and encodingName. + try { + const result = packageData(bytes, type, blob.type, encodingName) + + // 4. Else: + + if (fr[kAborted]) { + return + } + + // 1. Set fr’s result to result. + fr[kResult] = result + + // 2. Fire a progress event called load at the fr. + fireAProgressEvent('load', fr) + } catch (error) { + // 3. If package data threw an exception error: + + // 1. Set fr’s error to error. + fr[kError] = error + + // 2. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) + } + + // 5. If fr’s state is not "loading", fire a progress + // event called loadend at the fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) + + break + } + } catch (error) { + if (fr[kAborted]) { + return + } + + // 6. Otherwise, if chunkPromise is rejected with an + // error error, queue a task to run the following + // steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' + + // 2. Set fr’s error to error. + fr[kError] = error + + // 3. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) + + // 4. If fr’s state is not "loading", fire a progress + // event called loadend at fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) + + break + } + } + })() +} + +/** + * @see https://w3c.github.io/FileAPI/#fire-a-progress-event + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e The name of the event + * @param {import('./filereader').FileReader} reader + */ +function fireAProgressEvent (e, reader) { + // The progress event e does not bubble. e.bubbles must be false + // The progress event e is NOT cancelable. e.cancelable must be false + const event = new ProgressEvent(e, { + bubbles: false, + cancelable: false + }) + + reader.dispatchEvent(event) +} + +/** + * @see https://w3c.github.io/FileAPI/#blob-package-data + * @param {Uint8Array[]} bytes + * @param {string} type + * @param {string?} mimeType + * @param {string?} encodingName + */ +function packageData (bytes, type, mimeType, encodingName) { + // 1. A Blob has an associated package data algorithm, given + // bytes, a type, a optional mimeType, and a optional + // encodingName, which switches on type and runs the + // associated steps: + + switch (type) { + case 'DataURL': { + // 1. Return bytes as a DataURL [RFC2397] subject to + // the considerations below: + // * Use mimeType as part of the Data URL if it is + // available in keeping with the Data URL + // specification [RFC2397]. + // * If mimeType is not available return a Data URL + // without a media-type. [RFC2397]. + + // https://datatracker.ietf.org/doc/html/rfc2397#section-3 + // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data + // mediatype := [ type "/" subtype ] *( ";" parameter ) + // data := *urlchar + // parameter := attribute "=" value + let dataURL = 'data:' + + const parsed = parseMIMEType(mimeType || 'application/octet-stream') + + if (parsed !== 'failure') { + dataURL += serializeAMimeType(parsed) + } + + dataURL += ';base64,' + + const decoder = new StringDecoder('latin1') + + for (const chunk of bytes) { + dataURL += btoa(decoder.write(chunk)) + } + + dataURL += btoa(decoder.end()) + + return dataURL + } + case 'Text': { + // 1. Let encoding be failure + let encoding = 'failure' + + // 2. If the encodingName is present, set encoding to the + // result of getting an encoding from encodingName. + if (encodingName) { + encoding = getEncoding(encodingName) + } + + // 3. If encoding is failure, and mimeType is present: + if (encoding === 'failure' && mimeType) { + // 1. Let type be the result of parse a MIME type + // given mimeType. + const type = parseMIMEType(mimeType) + + // 2. If type is not failure, set encoding to the result + // of getting an encoding from type’s parameters["charset"]. + if (type !== 'failure') { + encoding = getEncoding(type.parameters.get('charset')) + } + } + + // 4. If encoding is failure, then set encoding to UTF-8. + if (encoding === 'failure') { + encoding = 'UTF-8' + } + + // 5. Decode bytes using fallback encoding encoding, and + // return the result. + return decode(bytes, encoding) + } + case 'ArrayBuffer': { + // Return a new ArrayBuffer whose contents are bytes. + const sequence = combineByteSequences(bytes) + + return sequence.buffer + } + case 'BinaryString': { + // Return bytes as a binary string, in which every byte + // is represented by a code unit of equal value [0..255]. + let binaryString = '' + + const decoder = new StringDecoder('latin1') + + for (const chunk of bytes) { + binaryString += decoder.write(chunk) + } + + binaryString += decoder.end() + + return binaryString + } + } +} + +/** + * @see https://encoding.spec.whatwg.org/#decode + * @param {Uint8Array[]} ioQueue + * @param {string} encoding + */ +function decode (ioQueue, encoding) { + const bytes = combineByteSequences(ioQueue) + + // 1. Let BOMEncoding be the result of BOM sniffing ioQueue. + const BOMEncoding = BOMSniffing(bytes) + + let slice = 0 + + // 2. If BOMEncoding is non-null: + if (BOMEncoding !== null) { + // 1. Set encoding to BOMEncoding. + encoding = BOMEncoding + + // 2. Read three bytes from ioQueue, if BOMEncoding is + // UTF-8; otherwise read two bytes. + // (Do nothing with those bytes.) + slice = BOMEncoding === 'UTF-8' ? 3 : 2 + } + + // 3. Process a queue with an instance of encoding’s + // decoder, ioQueue, output, and "replacement". + + // 4. Return output. + + const sliced = bytes.slice(slice) + return new TextDecoder(encoding).decode(sliced) +} + +/** + * @see https://encoding.spec.whatwg.org/#bom-sniff + * @param {Uint8Array} ioQueue + */ +function BOMSniffing (ioQueue) { + // 1. Let BOM be the result of peeking 3 bytes from ioQueue, + // converted to a byte sequence. + const [a, b, c] = ioQueue + + // 2. For each of the rows in the table below, starting with + // the first one and going down, if BOM starts with the + // bytes given in the first column, then return the + // encoding given in the cell in the second column of that + // row. Otherwise, return null. + if (a === 0xEF && b === 0xBB && c === 0xBF) { + return 'UTF-8' + } else if (a === 0xFE && b === 0xFF) { + return 'UTF-16BE' + } else if (a === 0xFF && b === 0xFE) { + return 'UTF-16LE' + } + + return null +} + +/** + * @param {Uint8Array[]} sequences + */ +function combineByteSequences (sequences) { + const size = sequences.reduce((a, b) => { + return a + b.byteLength + }, 0) + + let offset = 0 + + return sequences.reduce((a, b) => { + a.set(b, offset) + offset += b.byteLength + return a + }, new Uint8Array(size)) +} + +module.exports = { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} + + +/***/ }), + +/***/ 32581: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +// We include a version number for the Dispatcher API. In case of breaking changes, +// this version number must be increased to avoid conflicts. +const globalDispatcher = Symbol.for('undici.globalDispatcher.1') +const { InvalidArgumentError } = __nccwpck_require__(68707) +const Agent = __nccwpck_require__(59965) + +if (getGlobalDispatcher() === undefined) { + setGlobalDispatcher(new Agent()) +} + +function setGlobalDispatcher (agent) { + if (!agent || typeof agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument agent must implement Agent') + } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }) +} + +function getGlobalDispatcher () { + return globalThis[globalDispatcher] +} + +module.exports = { + setGlobalDispatcher, + getGlobalDispatcher +} + + +/***/ }), + +/***/ 78840: +/***/ ((module) => { + +"use strict"; + + +module.exports = class DecoratorHandler { + constructor (handler) { + this.handler = handler + } + + onConnect (...args) { + return this.handler.onConnect(...args) + } + + onError (...args) { + return this.handler.onError(...args) + } + + onUpgrade (...args) { + return this.handler.onUpgrade(...args) + } + + onHeaders (...args) { + return this.handler.onHeaders(...args) + } + + onData (...args) { + return this.handler.onData(...args) + } + + onComplete (...args) { + return this.handler.onComplete(...args) + } + + onBodySent (...args) { + return this.handler.onBodySent(...args) + } +} + + +/***/ }), + +/***/ 48299: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const util = __nccwpck_require__(3440) +const { kBodyUsed } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { InvalidArgumentError } = __nccwpck_require__(68707) +const EE = __nccwpck_require__(24434) + +const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] + +const kBody = Symbol('body') + +class BodyAsyncIterable { + constructor (body) { + this[kBody] = body + this[kBodyUsed] = false + } + + async * [Symbol.asyncIterator] () { + assert(!this[kBodyUsed], 'disturbed') + this[kBodyUsed] = true + yield * this[kBody] + } +} + +class RedirectHandler { + constructor (dispatch, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + util.validateHandler(handler, opts.method, opts.upgrade) + + this.dispatch = dispatch + this.location = null + this.abort = null + this.opts = { ...opts, maxRedirections: 0 } // opts must be a copy + this.maxRedirections = maxRedirections + this.handler = handler + this.history = [] + + if (util.isStream(this.opts.body)) { + // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp + // so that it can be dispatched again? + // TODO (fix): Do we need 100-expect support to provide a way to do this properly? + if (util.bodyLength(this.opts.body) === 0) { + this.opts.body + .on('data', function () { + assert(false) + }) + } + + if (typeof this.opts.body.readableDidRead !== 'boolean') { + this.opts.body[kBodyUsed] = false + EE.prototype.on.call(this.opts.body, 'data', function () { + this[kBodyUsed] = true + }) + } + } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { + // TODO (fix): We can't access ReadableStream internal state + // to determine whether or not it has been disturbed. This is just + // a workaround. + this.opts.body = new BodyAsyncIterable(this.opts.body) + } else if ( + this.opts.body && + typeof this.opts.body !== 'string' && + !ArrayBuffer.isView(this.opts.body) && + util.isIterable(this.opts.body) + ) { + // TODO: Should we allow re-using iterable if !this.opts.idempotent + // or through some other flag? + this.opts.body = new BodyAsyncIterable(this.opts.body) + } + } + + onConnect (abort) { + this.abort = abort + this.handler.onConnect(abort, { history: this.history }) + } + + onUpgrade (statusCode, headers, socket) { + this.handler.onUpgrade(statusCode, headers, socket) + } + + onError (error) { + this.handler.onError(error) + } + + onHeaders (statusCode, headers, resume, statusText) { + this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) + ? null + : parseLocation(statusCode, headers) + + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)) + } + + if (!this.location) { + return this.handler.onHeaders(statusCode, headers, resume, statusText) + } + + const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) + const path = search ? `${pathname}${search}` : pathname + + // Remove headers referring to the original URL. + // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. + // https://tools.ietf.org/html/rfc7231#section-6.4 + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) + this.opts.path = path + this.opts.origin = origin + this.opts.maxRedirections = 0 + this.opts.query = null + + // https://tools.ietf.org/html/rfc7231#section-6.4.4 + // In case of HTTP 303, always replace method to be either HEAD or GET + if (statusCode === 303 && this.opts.method !== 'HEAD') { + this.opts.method = 'GET' + this.opts.body = null + } + } + + onData (chunk) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 + + TLDR: undici always ignores 3xx response bodies. + + Redirection is used to serve the requested resource from another URL, so it is assumes that + no body is generated (and thus can be ignored). Even though generating a body is not prohibited. + + For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually + (which means it's optional and not mandated) contain just an hyperlink to the value of + the Location response header, so the body can be ignored safely. + + For status 300, which is "Multiple Choices", the spec mentions both generating a Location + response header AND a response body with the other possible location to follow. + Since the spec explicitily chooses not to specify a format for such body and leave it to + servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it. + */ + } else { + return this.handler.onData(chunk) + } + } + + onComplete (trailers) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 + + TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections + and neither are useful if present. + + See comment on onData method above for more detailed informations. + */ + + this.location = null + this.abort = null + + this.dispatch(this.opts, this) + } else { + this.handler.onComplete(trailers) + } + } + + onBodySent (chunk) { + if (this.handler.onBodySent) { + this.handler.onBodySent(chunk) + } + } +} + +function parseLocation (statusCode, headers) { + if (redirectableStatusCodes.indexOf(statusCode) === -1) { + return null + } + + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toString().toLowerCase() === 'location') { + return headers[i + 1] + } + } +} + +// https://tools.ietf.org/html/rfc7231#section-6.4.4 +function shouldRemoveHeader (header, removeContent, unknownOrigin) { + if (header.length === 4) { + return util.headerNameToString(header) === 'host' + } + if (removeContent && util.headerNameToString(header).startsWith('content-')) { + return true + } + if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { + const name = util.headerNameToString(header) + return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization' + } + return false +} + +// https://tools.ietf.org/html/rfc7231#section-6.4 +function cleanRequestHeaders (headers, removeContent, unknownOrigin) { + const ret = [] + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]) + } + } + } else if (headers && typeof headers === 'object') { + for (const key of Object.keys(headers)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, headers[key]) + } + } + } else { + assert(headers == null, 'headers must be an object or an array') + } + return ret +} + +module.exports = RedirectHandler + + +/***/ }), + +/***/ 53573: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(42613) + +const { kRetryHandlerDefaultRetry } = __nccwpck_require__(36443) +const { RequestRetryError } = __nccwpck_require__(68707) +const { isDisturbed, parseHeaders, parseRangeHeader } = __nccwpck_require__(3440) + +function calculateRetryAfterHeader (retryAfter) { + const current = Date.now() + const diff = new Date(retryAfter).getTime() - current + + return diff +} + +class RetryHandler { + constructor (opts, handlers) { + const { retryOptions, ...dispatchOpts } = opts + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes + } = retryOptions ?? {} + + this.dispatch = handlers.dispatch + this.handler = handlers.handler + this.opts = dispatchOpts + this.abort = null + this.aborted = false + this.retryOpts = { + retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1000, // 30s, + timeout: minTimeout ?? 500, // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + 'ECONNRESET', + 'ECONNREFUSED', + 'ENOTFOUND', + 'ENETDOWN', + 'ENETUNREACH', + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'EPIPE' + ] + } + + this.retryCount = 0 + this.start = 0 + this.end = null + this.etag = null + this.resume = null + + // Handle possible onConnect duplication + this.handler.onConnect(reason => { + this.aborted = true + if (this.abort) { + this.abort(reason) + } else { + this.reason = reason + } + }) + } + + onRequestSent () { + if (this.handler.onRequestSent) { + this.handler.onRequestSent() + } + } + + onUpgrade (statusCode, headers, socket) { + if (this.handler.onUpgrade) { + this.handler.onUpgrade(statusCode, headers, socket) + } + } + + onConnect (abort) { + if (this.aborted) { + abort(this.reason) + } else { + this.abort = abort + } + } + + onBodySent (chunk) { + if (this.handler.onBodySent) return this.handler.onBodySent(chunk) + } + + static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { + const { statusCode, code, headers } = err + const { method, retryOptions } = opts + const { + maxRetries, + timeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions + let { counter, currentTimeout } = state + + currentTimeout = + currentTimeout != null && currentTimeout > 0 ? currentTimeout : timeout + + // Any code that is not a Undici's originated and allowed to retry + if ( + code && + code !== 'UND_ERR_REQ_RETRY' && + code !== 'UND_ERR_SOCKET' && + !errorCodes.includes(code) + ) { + cb(err) + return + } + + // If a set of method are provided and the current method is not in the list + if (Array.isArray(methods) && !methods.includes(method)) { + cb(err) + return + } + + // If a set of status code are provided and the current status code is not in the list + if ( + statusCode != null && + Array.isArray(statusCodes) && + !statusCodes.includes(statusCode) + ) { + cb(err) + return + } + + // If we reached the max number of retries + if (counter > maxRetries) { + cb(err) + return + } + + let retryAfterHeader = headers != null && headers['retry-after'] + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader) + retryAfterHeader = isNaN(retryAfterHeader) + ? calculateRetryAfterHeader(retryAfterHeader) + : retryAfterHeader * 1e3 // Retry-After is in seconds + } + + const retryTimeout = + retryAfterHeader > 0 + ? Math.min(retryAfterHeader, maxTimeout) + : Math.min(currentTimeout * timeoutFactor ** counter, maxTimeout) + + state.currentTimeout = retryTimeout + + setTimeout(() => cb(null), retryTimeout) + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const headers = parseHeaders(rawHeaders) + + this.retryCount += 1 + + if (statusCode >= 300) { + this.abort( + new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Checkpoint for resume from where we left it + if (this.resume != null) { + this.resume = null + + if (statusCode !== 206) { + return true + } + + const contentRange = parseRangeHeader(headers['content-range']) + // If no content range + if (!contentRange) { + this.abort( + new RequestRetryError('Content-Range mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Let's start with a weak etag check + if (this.etag != null && this.etag !== headers.etag) { + this.abort( + new RequestRetryError('ETag mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + const { start, size, end = size } = contentRange + + assert(this.start === start, 'content-range mismatch') + assert(this.end == null || this.end === end, 'content-range mismatch') + + this.resume = resume + return true + } + + if (this.end == null) { + if (statusCode === 206) { + // First time we receive 206 + const range = parseRangeHeader(headers['content-range']) + + if (range == null) { + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const { start, size, end = size } = range + + assert( + start != null && Number.isFinite(start) && this.start !== start, + 'content-range mismatch' + ) + assert(Number.isFinite(start)) + assert( + end != null && Number.isFinite(end) && this.end !== end, + 'invalid content-length' + ) + + this.start = start + this.end = end + } + + // We make our best to checkpoint the body for further range headers + if (this.end == null) { + const contentLength = headers['content-length'] + this.end = contentLength != null ? Number(contentLength) : null + } + + assert(Number.isFinite(this.start)) + assert( + this.end == null || Number.isFinite(this.end), + 'invalid content-length' + ) + + this.resume = resume + this.etag = headers.etag != null ? headers.etag : null + + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const err = new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + + this.abort(err) + + return false + } + + onData (chunk) { + this.start += chunk.length + + return this.handler.onData(chunk) + } + + onComplete (rawTrailers) { + this.retryCount = 0 + return this.handler.onComplete(rawTrailers) + } + + onError (err) { + if (this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount++, currentTimeout: this.retryAfter }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + onRetry.bind(this) + ) + + function onRetry (err) { + if (err != null || this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + if (this.start !== 0) { + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + range: `bytes=${this.start}-${this.end ?? ''}` + } + } + } + + try { + this.dispatch(this.opts, this) + } catch (err) { + this.handler.onError(err) + } + } + } +} + +module.exports = RetryHandler + + +/***/ }), + +/***/ 64415: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const RedirectHandler = __nccwpck_require__(48299) + +function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) { + return (dispatch) => { + return function Intercept (opts, handler) { + const { maxRedirections = defaultMaxRedirections } = opts + + if (!maxRedirections) { + return dispatch(opts, handler) + } + + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler) + opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting. + return dispatch(opts, redirectHandler) + } + } +} + +module.exports = createRedirectInterceptor + + +/***/ }), + +/***/ 52824: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; +const utils_1 = __nccwpck_require__(50172); +// C headers +var ERROR; +(function (ERROR) { + ERROR[ERROR["OK"] = 0] = "OK"; + ERROR[ERROR["INTERNAL"] = 1] = "INTERNAL"; + ERROR[ERROR["STRICT"] = 2] = "STRICT"; + ERROR[ERROR["LF_EXPECTED"] = 3] = "LF_EXPECTED"; + ERROR[ERROR["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; + ERROR[ERROR["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; + ERROR[ERROR["INVALID_METHOD"] = 6] = "INVALID_METHOD"; + ERROR[ERROR["INVALID_URL"] = 7] = "INVALID_URL"; + ERROR[ERROR["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; + ERROR[ERROR["INVALID_VERSION"] = 9] = "INVALID_VERSION"; + ERROR[ERROR["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; + ERROR[ERROR["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; + ERROR[ERROR["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; + ERROR[ERROR["INVALID_STATUS"] = 13] = "INVALID_STATUS"; + ERROR[ERROR["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; + ERROR[ERROR["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; + ERROR[ERROR["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; + ERROR[ERROR["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; + ERROR[ERROR["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; + ERROR[ERROR["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; + ERROR[ERROR["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; + ERROR[ERROR["PAUSED"] = 21] = "PAUSED"; + ERROR[ERROR["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; + ERROR[ERROR["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; + ERROR[ERROR["USER"] = 24] = "USER"; +})(ERROR = exports.ERROR || (exports.ERROR = {})); +var TYPE; +(function (TYPE) { + TYPE[TYPE["BOTH"] = 0] = "BOTH"; + TYPE[TYPE["REQUEST"] = 1] = "REQUEST"; + TYPE[TYPE["RESPONSE"] = 2] = "RESPONSE"; +})(TYPE = exports.TYPE || (exports.TYPE = {})); +var FLAGS; +(function (FLAGS) { + FLAGS[FLAGS["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; + FLAGS[FLAGS["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; + FLAGS[FLAGS["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; + FLAGS[FLAGS["CHUNKED"] = 8] = "CHUNKED"; + FLAGS[FLAGS["UPGRADE"] = 16] = "UPGRADE"; + FLAGS[FLAGS["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; + FLAGS[FLAGS["SKIPBODY"] = 64] = "SKIPBODY"; + FLAGS[FLAGS["TRAILING"] = 128] = "TRAILING"; + // 1 << 8 is unused + FLAGS[FLAGS["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; +})(FLAGS = exports.FLAGS || (exports.FLAGS = {})); +var LENIENT_FLAGS; +(function (LENIENT_FLAGS) { + LENIENT_FLAGS[LENIENT_FLAGS["HEADERS"] = 1] = "HEADERS"; + LENIENT_FLAGS[LENIENT_FLAGS["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; + LENIENT_FLAGS[LENIENT_FLAGS["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; +})(LENIENT_FLAGS = exports.LENIENT_FLAGS || (exports.LENIENT_FLAGS = {})); +var METHODS; +(function (METHODS) { + METHODS[METHODS["DELETE"] = 0] = "DELETE"; + METHODS[METHODS["GET"] = 1] = "GET"; + METHODS[METHODS["HEAD"] = 2] = "HEAD"; + METHODS[METHODS["POST"] = 3] = "POST"; + METHODS[METHODS["PUT"] = 4] = "PUT"; + /* pathological */ + METHODS[METHODS["CONNECT"] = 5] = "CONNECT"; + METHODS[METHODS["OPTIONS"] = 6] = "OPTIONS"; + METHODS[METHODS["TRACE"] = 7] = "TRACE"; + /* WebDAV */ + METHODS[METHODS["COPY"] = 8] = "COPY"; + METHODS[METHODS["LOCK"] = 9] = "LOCK"; + METHODS[METHODS["MKCOL"] = 10] = "MKCOL"; + METHODS[METHODS["MOVE"] = 11] = "MOVE"; + METHODS[METHODS["PROPFIND"] = 12] = "PROPFIND"; + METHODS[METHODS["PROPPATCH"] = 13] = "PROPPATCH"; + METHODS[METHODS["SEARCH"] = 14] = "SEARCH"; + METHODS[METHODS["UNLOCK"] = 15] = "UNLOCK"; + METHODS[METHODS["BIND"] = 16] = "BIND"; + METHODS[METHODS["REBIND"] = 17] = "REBIND"; + METHODS[METHODS["UNBIND"] = 18] = "UNBIND"; + METHODS[METHODS["ACL"] = 19] = "ACL"; + /* subversion */ + METHODS[METHODS["REPORT"] = 20] = "REPORT"; + METHODS[METHODS["MKACTIVITY"] = 21] = "MKACTIVITY"; + METHODS[METHODS["CHECKOUT"] = 22] = "CHECKOUT"; + METHODS[METHODS["MERGE"] = 23] = "MERGE"; + /* upnp */ + METHODS[METHODS["M-SEARCH"] = 24] = "M-SEARCH"; + METHODS[METHODS["NOTIFY"] = 25] = "NOTIFY"; + METHODS[METHODS["SUBSCRIBE"] = 26] = "SUBSCRIBE"; + METHODS[METHODS["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; + /* RFC-5789 */ + METHODS[METHODS["PATCH"] = 28] = "PATCH"; + METHODS[METHODS["PURGE"] = 29] = "PURGE"; + /* CalDAV */ + METHODS[METHODS["MKCALENDAR"] = 30] = "MKCALENDAR"; + /* RFC-2068, section 19.6.1.2 */ + METHODS[METHODS["LINK"] = 31] = "LINK"; + METHODS[METHODS["UNLINK"] = 32] = "UNLINK"; + /* icecast */ + METHODS[METHODS["SOURCE"] = 33] = "SOURCE"; + /* RFC-7540, section 11.6 */ + METHODS[METHODS["PRI"] = 34] = "PRI"; + /* RFC-2326 RTSP */ + METHODS[METHODS["DESCRIBE"] = 35] = "DESCRIBE"; + METHODS[METHODS["ANNOUNCE"] = 36] = "ANNOUNCE"; + METHODS[METHODS["SETUP"] = 37] = "SETUP"; + METHODS[METHODS["PLAY"] = 38] = "PLAY"; + METHODS[METHODS["PAUSE"] = 39] = "PAUSE"; + METHODS[METHODS["TEARDOWN"] = 40] = "TEARDOWN"; + METHODS[METHODS["GET_PARAMETER"] = 41] = "GET_PARAMETER"; + METHODS[METHODS["SET_PARAMETER"] = 42] = "SET_PARAMETER"; + METHODS[METHODS["REDIRECT"] = 43] = "REDIRECT"; + METHODS[METHODS["RECORD"] = 44] = "RECORD"; + /* RAOP */ + METHODS[METHODS["FLUSH"] = 45] = "FLUSH"; +})(METHODS = exports.METHODS || (exports.METHODS = {})); +exports.METHODS_HTTP = [ + METHODS.DELETE, + METHODS.GET, + METHODS.HEAD, + METHODS.POST, + METHODS.PUT, + METHODS.CONNECT, + METHODS.OPTIONS, + METHODS.TRACE, + METHODS.COPY, + METHODS.LOCK, + METHODS.MKCOL, + METHODS.MOVE, + METHODS.PROPFIND, + METHODS.PROPPATCH, + METHODS.SEARCH, + METHODS.UNLOCK, + METHODS.BIND, + METHODS.REBIND, + METHODS.UNBIND, + METHODS.ACL, + METHODS.REPORT, + METHODS.MKACTIVITY, + METHODS.CHECKOUT, + METHODS.MERGE, + METHODS['M-SEARCH'], + METHODS.NOTIFY, + METHODS.SUBSCRIBE, + METHODS.UNSUBSCRIBE, + METHODS.PATCH, + METHODS.PURGE, + METHODS.MKCALENDAR, + METHODS.LINK, + METHODS.UNLINK, + METHODS.PRI, + // TODO(indutny): should we allow it with HTTP? + METHODS.SOURCE, +]; +exports.METHODS_ICE = [ + METHODS.SOURCE, +]; +exports.METHODS_RTSP = [ + METHODS.OPTIONS, + METHODS.DESCRIBE, + METHODS.ANNOUNCE, + METHODS.SETUP, + METHODS.PLAY, + METHODS.PAUSE, + METHODS.TEARDOWN, + METHODS.GET_PARAMETER, + METHODS.SET_PARAMETER, + METHODS.REDIRECT, + METHODS.RECORD, + METHODS.FLUSH, + // For AirPlay + METHODS.GET, + METHODS.POST, +]; +exports.METHOD_MAP = utils_1.enumToMap(METHODS); +exports.H_METHOD_MAP = {}; +Object.keys(exports.METHOD_MAP).forEach((key) => { + if (/^H/.test(key)) { + exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key]; + } +}); +var FINISH; +(function (FINISH) { + FINISH[FINISH["SAFE"] = 0] = "SAFE"; + FINISH[FINISH["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; + FINISH[FINISH["UNSAFE"] = 2] = "UNSAFE"; +})(FINISH = exports.FINISH || (exports.FINISH = {})); +exports.ALPHA = []; +for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { + // Upper case + exports.ALPHA.push(String.fromCharCode(i)); + // Lower case + exports.ALPHA.push(String.fromCharCode(i + 0x20)); +} +exports.NUM_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, +}; +exports.HEX_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, + A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, + a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, +}; +exports.NUM = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', +]; +exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); +exports.MARK = ['-', '_', '.', '!', '~', '*', '\'', '(', ')']; +exports.USERINFO_CHARS = exports.ALPHANUM + .concat(exports.MARK) + .concat(['%', ';', ':', '&', '=', '+', '$', ',']); +// TODO(indutny): use RFC +exports.STRICT_URL_CHAR = [ + '!', '"', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + ':', ';', '<', '=', '>', + '@', '[', '\\', ']', '^', '_', + '`', + '{', '|', '}', '~', +].concat(exports.ALPHANUM); +exports.URL_CHAR = exports.STRICT_URL_CHAR + .concat(['\t', '\f']); +// All characters with 0x80 bit set to 1 +for (let i = 0x80; i <= 0xff; i++) { + exports.URL_CHAR.push(i); +} +exports.HEX = exports.NUM.concat(['a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']); +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +exports.STRICT_TOKEN = [ + '!', '#', '$', '%', '&', '\'', + '*', '+', '-', '.', + '^', '_', '`', + '|', '~', +].concat(exports.ALPHANUM); +exports.TOKEN = exports.STRICT_TOKEN.concat([' ']); +/* + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + */ +exports.HEADER_CHARS = ['\t']; +for (let i = 32; i <= 255; i++) { + if (i !== 127) { + exports.HEADER_CHARS.push(i); + } +} +// ',' = \x44 +exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); +exports.MAJOR = exports.NUM_MAP; +exports.MINOR = exports.MAJOR; +var HEADER_STATE; +(function (HEADER_STATE) { + HEADER_STATE[HEADER_STATE["GENERAL"] = 0] = "GENERAL"; + HEADER_STATE[HEADER_STATE["CONNECTION"] = 1] = "CONNECTION"; + HEADER_STATE[HEADER_STATE["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; + HEADER_STATE[HEADER_STATE["UPGRADE"] = 4] = "UPGRADE"; + HEADER_STATE[HEADER_STATE["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; + HEADER_STATE[HEADER_STATE["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; + HEADER_STATE[HEADER_STATE["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; +})(HEADER_STATE = exports.HEADER_STATE || (exports.HEADER_STATE = {})); +exports.SPECIAL_HEADERS = { + 'connection': HEADER_STATE.CONNECTION, + 'content-length': HEADER_STATE.CONTENT_LENGTH, + 'proxy-connection': HEADER_STATE.CONNECTION, + 'transfer-encoding': HEADER_STATE.TRANSFER_ENCODING, + 'upgrade': HEADER_STATE.UPGRADE, +}; +//# sourceMappingURL=constants.js.map + +/***/ }), + +/***/ 63870: +/***/ ((module) => { + +module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAQDscBAAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxweHyAhIyUoP0BBREVGR0hJSktMTU9QUVJT3gNXWVtcXWBiZWZnaGlqa2xtb3BxcnN0dXZ3eHl6e3x9foABggGFAYYBhwGJAYsBjAGNAY4BjwGQAZEBlAGVAZYBlwGYAZkBmgGbAZwBnQGeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B4AHhAeIB4wHkAeUB5gHnAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAZkCpAKwAv4C/gILIAEiBCACRw3zAUHdASEQDP8DCyABIhAgAkcN3QFBwwEhEAz+AwsgASIBIAJHDZABQfcAIRAM/QMLIAEiASACRw2GAUHvACEQDPwDCyABIgEgAkcNf0HqACEQDPsDCyABIgEgAkcNe0HoACEQDPoDCyABIgEgAkcNeEHmACEQDPkDCyABIgEgAkcNGkEYIRAM+AMLIAEiASACRw0UQRIhEAz3AwsgASIBIAJHDVlBxQAhEAz2AwsgASIBIAJHDUpBPyEQDPUDCyABIgEgAkcNSEE8IRAM9AMLIAEiASACRw1BQTEhEAzzAwsgAC0ALkEBRg3rAwyHAgsgACABIgEgAhDAgICAAEEBRw3mASAAQgA3AyAM5wELIAAgASIBIAIQtICAgAAiEA3nASABIQEM9QILAkAgASIBIAJHDQBBBiEQDPADCyAAIAFBAWoiASACELuAgIAAIhAN6AEgASEBDDELIABCADcDIEESIRAM1QMLIAEiECACRw0rQR0hEAztAwsCQCABIgEgAkYNACABQQFqIQFBECEQDNQDC0EHIRAM7AMLIABCACAAKQMgIhEgAiABIhBrrSISfSITIBMgEVYbNwMgIBEgElYiFEUN5QFBCCEQDOsDCwJAIAEiASACRg0AIABBiYCAgAA2AgggACABNgIEIAEhAUEUIRAM0gMLQQkhEAzqAwsgASEBIAApAyBQDeQBIAEhAQzyAgsCQCABIgEgAkcNAEELIRAM6QMLIAAgAUEBaiIBIAIQtoCAgAAiEA3lASABIQEM8gILIAAgASIBIAIQuICAgAAiEA3lASABIQEM8gILIAAgASIBIAIQuICAgAAiEA3mASABIQEMDQsgACABIgEgAhC6gICAACIQDecBIAEhAQzwAgsCQCABIgEgAkcNAEEPIRAM5QMLIAEtAAAiEEE7Rg0IIBBBDUcN6AEgAUEBaiEBDO8CCyAAIAEiASACELqAgIAAIhAN6AEgASEBDPICCwNAAkAgAS0AAEHwtYCAAGotAAAiEEEBRg0AIBBBAkcN6wEgACgCBCEQIABBADYCBCAAIBAgAUEBaiIBELmAgIAAIhAN6gEgASEBDPQCCyABQQFqIgEgAkcNAAtBEiEQDOIDCyAAIAEiASACELqAgIAAIhAN6QEgASEBDAoLIAEiASACRw0GQRshEAzgAwsCQCABIgEgAkcNAEEWIRAM4AMLIABBioCAgAA2AgggACABNgIEIAAgASACELiAgIAAIhAN6gEgASEBQSAhEAzGAwsCQCABIgEgAkYNAANAAkAgAS0AAEHwt4CAAGotAAAiEEECRg0AAkAgEEF/ag4E5QHsAQDrAewBCyABQQFqIQFBCCEQDMgDCyABQQFqIgEgAkcNAAtBFSEQDN8DC0EVIRAM3gMLA0ACQCABLQAAQfC5gIAAai0AACIQQQJGDQAgEEF/ag4E3gHsAeAB6wHsAQsgAUEBaiIBIAJHDQALQRghEAzdAwsCQCABIgEgAkYNACAAQYuAgIAANgIIIAAgATYCBCABIQFBByEQDMQDC0EZIRAM3AMLIAFBAWohAQwCCwJAIAEiFCACRw0AQRohEAzbAwsgFCEBAkAgFC0AAEFzag4U3QLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gIA7gILQQAhECAAQQA2AhwgAEGvi4CAADYCECAAQQI2AgwgACAUQQFqNgIUDNoDCwJAIAEtAAAiEEE7Rg0AIBBBDUcN6AEgAUEBaiEBDOUCCyABQQFqIQELQSIhEAy/AwsCQCABIhAgAkcNAEEcIRAM2AMLQgAhESAQIQEgEC0AAEFQag435wHmAQECAwQFBgcIAAAAAAAAAAkKCwwNDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxAREhMUAAtBHiEQDL0DC0ICIREM5QELQgMhEQzkAQtCBCERDOMBC0IFIREM4gELQgYhEQzhAQtCByERDOABC0IIIREM3wELQgkhEQzeAQtCCiERDN0BC0ILIREM3AELQgwhEQzbAQtCDSERDNoBC0IOIREM2QELQg8hEQzYAQtCCiERDNcBC0ILIREM1gELQgwhEQzVAQtCDSERDNQBC0IOIREM0wELQg8hEQzSAQtCACERAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAQLQAAQVBqDjflAeQBAAECAwQFBgfmAeYB5gHmAeYB5gHmAQgJCgsMDeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gEODxAREhPmAQtCAiERDOQBC0IDIREM4wELQgQhEQziAQtCBSERDOEBC0IGIREM4AELQgchEQzfAQtCCCERDN4BC0IJIREM3QELQgohEQzcAQtCCyERDNsBC0IMIREM2gELQg0hEQzZAQtCDiERDNgBC0IPIREM1wELQgohEQzWAQtCCyERDNUBC0IMIREM1AELQg0hEQzTAQtCDiERDNIBC0IPIREM0QELIABCACAAKQMgIhEgAiABIhBrrSISfSITIBMgEVYbNwMgIBEgElYiFEUN0gFBHyEQDMADCwJAIAEiASACRg0AIABBiYCAgAA2AgggACABNgIEIAEhAUEkIRAMpwMLQSAhEAy/AwsgACABIhAgAhC+gICAAEF/ag4FtgEAxQIB0QHSAQtBESEQDKQDCyAAQQE6AC8gECEBDLsDCyABIgEgAkcN0gFBJCEQDLsDCyABIg0gAkcNHkHGACEQDLoDCyAAIAEiASACELKAgIAAIhAN1AEgASEBDLUBCyABIhAgAkcNJkHQACEQDLgDCwJAIAEiASACRw0AQSghEAy4AwsgAEEANgIEIABBjICAgAA2AgggACABIAEQsYCAgAAiEA3TASABIQEM2AELAkAgASIQIAJHDQBBKSEQDLcDCyAQLQAAIgFBIEYNFCABQQlHDdMBIBBBAWohAQwVCwJAIAEiASACRg0AIAFBAWohAQwXC0EqIRAMtQMLAkAgASIQIAJHDQBBKyEQDLUDCwJAIBAtAAAiAUEJRg0AIAFBIEcN1QELIAAtACxBCEYN0wEgECEBDJEDCwJAIAEiASACRw0AQSwhEAy0AwsgAS0AAEEKRw3VASABQQFqIQEMyQILIAEiDiACRw3VAUEvIRAMsgMLA0ACQCABLQAAIhBBIEYNAAJAIBBBdmoOBADcAdwBANoBCyABIQEM4AELIAFBAWoiASACRw0AC0ExIRAMsQMLQTIhECABIhQgAkYNsAMgAiAUayAAKAIAIgFqIRUgFCABa0EDaiEWAkADQCAULQAAIhdBIHIgFyAXQb9/akH/AXFBGkkbQf8BcSABQfC7gIAAai0AAEcNAQJAIAFBA0cNAEEGIQEMlgMLIAFBAWohASAUQQFqIhQgAkcNAAsgACAVNgIADLEDCyAAQQA2AgAgFCEBDNkBC0EzIRAgASIUIAJGDa8DIAIgFGsgACgCACIBaiEVIBQgAWtBCGohFgJAA0AgFC0AACIXQSByIBcgF0G/f2pB/wFxQRpJG0H/AXEgAUH0u4CAAGotAABHDQECQCABQQhHDQBBBSEBDJUDCyABQQFqIQEgFEEBaiIUIAJHDQALIAAgFTYCAAywAwsgAEEANgIAIBQhAQzYAQtBNCEQIAEiFCACRg2uAyACIBRrIAAoAgAiAWohFSAUIAFrQQVqIRYCQANAIBQtAAAiF0EgciAXIBdBv39qQf8BcUEaSRtB/wFxIAFB0MKAgABqLQAARw0BAkAgAUEFRw0AQQchAQyUAwsgAUEBaiEBIBRBAWoiFCACRw0ACyAAIBU2AgAMrwMLIABBADYCACAUIQEM1wELAkAgASIBIAJGDQADQAJAIAEtAABBgL6AgABqLQAAIhBBAUYNACAQQQJGDQogASEBDN0BCyABQQFqIgEgAkcNAAtBMCEQDK4DC0EwIRAMrQMLAkAgASIBIAJGDQADQAJAIAEtAAAiEEEgRg0AIBBBdmoOBNkB2gHaAdkB2gELIAFBAWoiASACRw0AC0E4IRAMrQMLQTghEAysAwsDQAJAIAEtAAAiEEEgRg0AIBBBCUcNAwsgAUEBaiIBIAJHDQALQTwhEAyrAwsDQAJAIAEtAAAiEEEgRg0AAkACQCAQQXZqDgTaAQEB2gEACyAQQSxGDdsBCyABIQEMBAsgAUEBaiIBIAJHDQALQT8hEAyqAwsgASEBDNsBC0HAACEQIAEiFCACRg2oAyACIBRrIAAoAgAiAWohFiAUIAFrQQZqIRcCQANAIBQtAABBIHIgAUGAwICAAGotAABHDQEgAUEGRg2OAyABQQFqIQEgFEEBaiIUIAJHDQALIAAgFjYCAAypAwsgAEEANgIAIBQhAQtBNiEQDI4DCwJAIAEiDyACRw0AQcEAIRAMpwMLIABBjICAgAA2AgggACAPNgIEIA8hASAALQAsQX9qDgTNAdUB1wHZAYcDCyABQQFqIQEMzAELAkAgASIBIAJGDQADQAJAIAEtAAAiEEEgciAQIBBBv39qQf8BcUEaSRtB/wFxIhBBCUYNACAQQSBGDQACQAJAAkACQCAQQZ1/ag4TAAMDAwMDAwMBAwMDAwMDAwMDAgMLIAFBAWohAUExIRAMkQMLIAFBAWohAUEyIRAMkAMLIAFBAWohAUEzIRAMjwMLIAEhAQzQAQsgAUEBaiIBIAJHDQALQTUhEAylAwtBNSEQDKQDCwJAIAEiASACRg0AA0ACQCABLQAAQYC8gIAAai0AAEEBRg0AIAEhAQzTAQsgAUEBaiIBIAJHDQALQT0hEAykAwtBPSEQDKMDCyAAIAEiASACELCAgIAAIhAN1gEgASEBDAELIBBBAWohAQtBPCEQDIcDCwJAIAEiASACRw0AQcIAIRAMoAMLAkADQAJAIAEtAABBd2oOGAAC/gL+AoQD/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4CAP4CCyABQQFqIgEgAkcNAAtBwgAhEAygAwsgAUEBaiEBIAAtAC1BAXFFDb0BIAEhAQtBLCEQDIUDCyABIgEgAkcN0wFBxAAhEAydAwsDQAJAIAEtAABBkMCAgABqLQAAQQFGDQAgASEBDLcCCyABQQFqIgEgAkcNAAtBxQAhEAycAwsgDS0AACIQQSBGDbMBIBBBOkcNgQMgACgCBCEBIABBADYCBCAAIAEgDRCvgICAACIBDdABIA1BAWohAQyzAgtBxwAhECABIg0gAkYNmgMgAiANayAAKAIAIgFqIRYgDSABa0EFaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUGQwoCAAGotAABHDYADIAFBBUYN9AIgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMmgMLQcgAIRAgASINIAJGDZkDIAIgDWsgACgCACIBaiEWIA0gAWtBCWohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFBlsKAgABqLQAARw3/AgJAIAFBCUcNAEECIQEM9QILIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJkDCwJAIAEiDSACRw0AQckAIRAMmQMLAkACQCANLQAAIgFBIHIgASABQb9/akH/AXFBGkkbQf8BcUGSf2oOBwCAA4ADgAOAA4ADAYADCyANQQFqIQFBPiEQDIADCyANQQFqIQFBPyEQDP8CC0HKACEQIAEiDSACRg2XAyACIA1rIAAoAgAiAWohFiANIAFrQQFqIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQaDCgIAAai0AAEcN/QIgAUEBRg3wAiABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyXAwtBywAhECABIg0gAkYNlgMgAiANayAAKAIAIgFqIRYgDSABa0EOaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUGiwoCAAGotAABHDfwCIAFBDkYN8AIgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMlgMLQcwAIRAgASINIAJGDZUDIAIgDWsgACgCACIBaiEWIA0gAWtBD2ohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFBwMKAgABqLQAARw37AgJAIAFBD0cNAEEDIQEM8QILIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJUDC0HNACEQIAEiDSACRg2UAyACIA1rIAAoAgAiAWohFiANIAFrQQVqIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQdDCgIAAai0AAEcN+gICQCABQQVHDQBBBCEBDPACCyABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyUAwsCQCABIg0gAkcNAEHOACEQDJQDCwJAAkACQAJAIA0tAAAiAUEgciABIAFBv39qQf8BcUEaSRtB/wFxQZ1/ag4TAP0C/QL9Av0C/QL9Av0C/QL9Av0C/QL9AgH9Av0C/QICA/0CCyANQQFqIQFBwQAhEAz9AgsgDUEBaiEBQcIAIRAM/AILIA1BAWohAUHDACEQDPsCCyANQQFqIQFBxAAhEAz6AgsCQCABIgEgAkYNACAAQY2AgIAANgIIIAAgATYCBCABIQFBxQAhEAz6AgtBzwAhEAySAwsgECEBAkACQCAQLQAAQXZqDgQBqAKoAgCoAgsgEEEBaiEBC0EnIRAM+AILAkAgASIBIAJHDQBB0QAhEAyRAwsCQCABLQAAQSBGDQAgASEBDI0BCyABQQFqIQEgAC0ALUEBcUUNxwEgASEBDIwBCyABIhcgAkcNyAFB0gAhEAyPAwtB0wAhECABIhQgAkYNjgMgAiAUayAAKAIAIgFqIRYgFCABa0EBaiEXA0AgFC0AACABQdbCgIAAai0AAEcNzAEgAUEBRg3HASABQQFqIQEgFEEBaiIUIAJHDQALIAAgFjYCAAyOAwsCQCABIgEgAkcNAEHVACEQDI4DCyABLQAAQQpHDcwBIAFBAWohAQzHAQsCQCABIgEgAkcNAEHWACEQDI0DCwJAAkAgAS0AAEF2ag4EAM0BzQEBzQELIAFBAWohAQzHAQsgAUEBaiEBQcoAIRAM8wILIAAgASIBIAIQroCAgAAiEA3LASABIQFBzQAhEAzyAgsgAC0AKUEiRg2FAwymAgsCQCABIgEgAkcNAEHbACEQDIoDC0EAIRRBASEXQQEhFkEAIRACQAJAAkACQAJAAkACQAJAAkAgAS0AAEFQag4K1AHTAQABAgMEBQYI1QELQQIhEAwGC0EDIRAMBQtBBCEQDAQLQQUhEAwDC0EGIRAMAgtBByEQDAELQQghEAtBACEXQQAhFkEAIRQMzAELQQkhEEEBIRRBACEXQQAhFgzLAQsCQCABIgEgAkcNAEHdACEQDIkDCyABLQAAQS5HDcwBIAFBAWohAQymAgsgASIBIAJHDcwBQd8AIRAMhwMLAkAgASIBIAJGDQAgAEGOgICAADYCCCAAIAE2AgQgASEBQdAAIRAM7gILQeAAIRAMhgMLQeEAIRAgASIBIAJGDYUDIAIgAWsgACgCACIUaiEWIAEgFGtBA2ohFwNAIAEtAAAgFEHiwoCAAGotAABHDc0BIBRBA0YNzAEgFEEBaiEUIAFBAWoiASACRw0ACyAAIBY2AgAMhQMLQeIAIRAgASIBIAJGDYQDIAIgAWsgACgCACIUaiEWIAEgFGtBAmohFwNAIAEtAAAgFEHmwoCAAGotAABHDcwBIBRBAkYNzgEgFEEBaiEUIAFBAWoiASACRw0ACyAAIBY2AgAMhAMLQeMAIRAgASIBIAJGDYMDIAIgAWsgACgCACIUaiEWIAEgFGtBA2ohFwNAIAEtAAAgFEHpwoCAAGotAABHDcsBIBRBA0YNzgEgFEEBaiEUIAFBAWoiASACRw0ACyAAIBY2AgAMgwMLAkAgASIBIAJHDQBB5QAhEAyDAwsgACABQQFqIgEgAhCogICAACIQDc0BIAEhAUHWACEQDOkCCwJAIAEiASACRg0AA0ACQCABLQAAIhBBIEYNAAJAAkACQCAQQbh/ag4LAAHPAc8BzwHPAc8BzwHPAc8BAs8BCyABQQFqIQFB0gAhEAztAgsgAUEBaiEBQdMAIRAM7AILIAFBAWohAUHUACEQDOsCCyABQQFqIgEgAkcNAAtB5AAhEAyCAwtB5AAhEAyBAwsDQAJAIAEtAABB8MKAgABqLQAAIhBBAUYNACAQQX5qDgPPAdAB0QHSAQsgAUEBaiIBIAJHDQALQeYAIRAMgAMLAkAgASIBIAJGDQAgAUEBaiEBDAMLQecAIRAM/wILA0ACQCABLQAAQfDEgIAAai0AACIQQQFGDQACQCAQQX5qDgTSAdMB1AEA1QELIAEhAUHXACEQDOcCCyABQQFqIgEgAkcNAAtB6AAhEAz+AgsCQCABIgEgAkcNAEHpACEQDP4CCwJAIAEtAAAiEEF2ag4augHVAdUBvAHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHKAdUB1QEA0wELIAFBAWohAQtBBiEQDOMCCwNAAkAgAS0AAEHwxoCAAGotAABBAUYNACABIQEMngILIAFBAWoiASACRw0AC0HqACEQDPsCCwJAIAEiASACRg0AIAFBAWohAQwDC0HrACEQDPoCCwJAIAEiASACRw0AQewAIRAM+gILIAFBAWohAQwBCwJAIAEiASACRw0AQe0AIRAM+QILIAFBAWohAQtBBCEQDN4CCwJAIAEiFCACRw0AQe4AIRAM9wILIBQhAQJAAkACQCAULQAAQfDIgIAAai0AAEF/ag4H1AHVAdYBAJwCAQLXAQsgFEEBaiEBDAoLIBRBAWohAQzNAQtBACEQIABBADYCHCAAQZuSgIAANgIQIABBBzYCDCAAIBRBAWo2AhQM9gILAkADQAJAIAEtAABB8MiAgABqLQAAIhBBBEYNAAJAAkAgEEF/ag4H0gHTAdQB2QEABAHZAQsgASEBQdoAIRAM4AILIAFBAWohAUHcACEQDN8CCyABQQFqIgEgAkcNAAtB7wAhEAz2AgsgAUEBaiEBDMsBCwJAIAEiFCACRw0AQfAAIRAM9QILIBQtAABBL0cN1AEgFEEBaiEBDAYLAkAgASIUIAJHDQBB8QAhEAz0AgsCQCAULQAAIgFBL0cNACAUQQFqIQFB3QAhEAzbAgsgAUF2aiIEQRZLDdMBQQEgBHRBiYCAAnFFDdMBDMoCCwJAIAEiASACRg0AIAFBAWohAUHeACEQDNoCC0HyACEQDPICCwJAIAEiFCACRw0AQfQAIRAM8gILIBQhAQJAIBQtAABB8MyAgABqLQAAQX9qDgPJApQCANQBC0HhACEQDNgCCwJAIAEiFCACRg0AA0ACQCAULQAAQfDKgIAAai0AACIBQQNGDQACQCABQX9qDgLLAgDVAQsgFCEBQd8AIRAM2gILIBRBAWoiFCACRw0AC0HzACEQDPECC0HzACEQDPACCwJAIAEiASACRg0AIABBj4CAgAA2AgggACABNgIEIAEhAUHgACEQDNcCC0H1ACEQDO8CCwJAIAEiASACRw0AQfYAIRAM7wILIABBj4CAgAA2AgggACABNgIEIAEhAQtBAyEQDNQCCwNAIAEtAABBIEcNwwIgAUEBaiIBIAJHDQALQfcAIRAM7AILAkAgASIBIAJHDQBB+AAhEAzsAgsgAS0AAEEgRw3OASABQQFqIQEM7wELIAAgASIBIAIQrICAgAAiEA3OASABIQEMjgILAkAgASIEIAJHDQBB+gAhEAzqAgsgBC0AAEHMAEcN0QEgBEEBaiEBQRMhEAzPAQsCQCABIgQgAkcNAEH7ACEQDOkCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRADQCAELQAAIAFB8M6AgABqLQAARw3QASABQQVGDc4BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQfsAIRAM6AILAkAgASIEIAJHDQBB/AAhEAzoAgsCQAJAIAQtAABBvX9qDgwA0QHRAdEB0QHRAdEB0QHRAdEB0QEB0QELIARBAWohAUHmACEQDM8CCyAEQQFqIQFB5wAhEAzOAgsCQCABIgQgAkcNAEH9ACEQDOcCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDc8BIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEH9ACEQDOcCCyAAQQA2AgAgEEEBaiEBQRAhEAzMAQsCQCABIgQgAkcNAEH+ACEQDOYCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUH2zoCAAGotAABHDc4BIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEH+ACEQDOYCCyAAQQA2AgAgEEEBaiEBQRYhEAzLAQsCQCABIgQgAkcNAEH/ACEQDOUCCyACIARrIAAoAgAiAWohFCAEIAFrQQNqIRACQANAIAQtAAAgAUH8zoCAAGotAABHDc0BIAFBA0YNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEH/ACEQDOUCCyAAQQA2AgAgEEEBaiEBQQUhEAzKAQsCQCABIgQgAkcNAEGAASEQDOQCCyAELQAAQdkARw3LASAEQQFqIQFBCCEQDMkBCwJAIAEiBCACRw0AQYEBIRAM4wILAkACQCAELQAAQbJ/ag4DAMwBAcwBCyAEQQFqIQFB6wAhEAzKAgsgBEEBaiEBQewAIRAMyQILAkAgASIEIAJHDQBBggEhEAziAgsCQAJAIAQtAABBuH9qDggAywHLAcsBywHLAcsBAcsBCyAEQQFqIQFB6gAhEAzJAgsgBEEBaiEBQe0AIRAMyAILAkAgASIEIAJHDQBBgwEhEAzhAgsgAiAEayAAKAIAIgFqIRAgBCABa0ECaiEUAkADQCAELQAAIAFBgM+AgABqLQAARw3JASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBA2AgBBgwEhEAzhAgtBACEQIABBADYCACAUQQFqIQEMxgELAkAgASIEIAJHDQBBhAEhEAzgAgsgAiAEayAAKAIAIgFqIRQgBCABa0EEaiEQAkADQCAELQAAIAFBg8+AgABqLQAARw3IASABQQRGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBhAEhEAzgAgsgAEEANgIAIBBBAWohAUEjIRAMxQELAkAgASIEIAJHDQBBhQEhEAzfAgsCQAJAIAQtAABBtH9qDggAyAHIAcgByAHIAcgBAcgBCyAEQQFqIQFB7wAhEAzGAgsgBEEBaiEBQfAAIRAMxQILAkAgASIEIAJHDQBBhgEhEAzeAgsgBC0AAEHFAEcNxQEgBEEBaiEBDIMCCwJAIAEiBCACRw0AQYcBIRAM3QILIAIgBGsgACgCACIBaiEUIAQgAWtBA2ohEAJAA0AgBC0AACABQYjPgIAAai0AAEcNxQEgAUEDRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYcBIRAM3QILIABBADYCACAQQQFqIQFBLSEQDMIBCwJAIAEiBCACRw0AQYgBIRAM3AILIAIgBGsgACgCACIBaiEUIAQgAWtBCGohEAJAA0AgBC0AACABQdDPgIAAai0AAEcNxAEgAUEIRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYgBIRAM3AILIABBADYCACAQQQFqIQFBKSEQDMEBCwJAIAEiASACRw0AQYkBIRAM2wILQQEhECABLQAAQd8ARw3AASABQQFqIQEMgQILAkAgASIEIAJHDQBBigEhEAzaAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQA0AgBC0AACABQYzPgIAAai0AAEcNwQEgAUEBRg2vAiABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGKASEQDNkCCwJAIAEiBCACRw0AQYsBIRAM2QILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQY7PgIAAai0AAEcNwQEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYsBIRAM2QILIABBADYCACAQQQFqIQFBAiEQDL4BCwJAIAEiBCACRw0AQYwBIRAM2AILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfDPgIAAai0AAEcNwAEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYwBIRAM2AILIABBADYCACAQQQFqIQFBHyEQDL0BCwJAIAEiBCACRw0AQY0BIRAM1wILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfLPgIAAai0AAEcNvwEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQY0BIRAM1wILIABBADYCACAQQQFqIQFBCSEQDLwBCwJAIAEiBCACRw0AQY4BIRAM1gILAkACQCAELQAAQbd/ag4HAL8BvwG/Ab8BvwEBvwELIARBAWohAUH4ACEQDL0CCyAEQQFqIQFB+QAhEAy8AgsCQCABIgQgAkcNAEGPASEQDNUCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUGRz4CAAGotAABHDb0BIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGPASEQDNUCCyAAQQA2AgAgEEEBaiEBQRghEAy6AQsCQCABIgQgAkcNAEGQASEQDNQCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUGXz4CAAGotAABHDbwBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGQASEQDNQCCyAAQQA2AgAgEEEBaiEBQRchEAy5AQsCQCABIgQgAkcNAEGRASEQDNMCCyACIARrIAAoAgAiAWohFCAEIAFrQQZqIRACQANAIAQtAAAgAUGaz4CAAGotAABHDbsBIAFBBkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGRASEQDNMCCyAAQQA2AgAgEEEBaiEBQRUhEAy4AQsCQCABIgQgAkcNAEGSASEQDNICCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUGhz4CAAGotAABHDboBIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGSASEQDNICCyAAQQA2AgAgEEEBaiEBQR4hEAy3AQsCQCABIgQgAkcNAEGTASEQDNECCyAELQAAQcwARw24ASAEQQFqIQFBCiEQDLYBCwJAIAQgAkcNAEGUASEQDNACCwJAAkAgBC0AAEG/f2oODwC5AbkBuQG5AbkBuQG5AbkBuQG5AbkBuQG5AQG5AQsgBEEBaiEBQf4AIRAMtwILIARBAWohAUH/ACEQDLYCCwJAIAQgAkcNAEGVASEQDM8CCwJAAkAgBC0AAEG/f2oOAwC4AQG4AQsgBEEBaiEBQf0AIRAMtgILIARBAWohBEGAASEQDLUCCwJAIAQgAkcNAEGWASEQDM4CCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUGnz4CAAGotAABHDbYBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGWASEQDM4CCyAAQQA2AgAgEEEBaiEBQQshEAyzAQsCQCAEIAJHDQBBlwEhEAzNAgsCQAJAAkACQCAELQAAQVNqDiMAuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AQG4AbgBuAG4AbgBArgBuAG4AQO4AQsgBEEBaiEBQfsAIRAMtgILIARBAWohAUH8ACEQDLUCCyAEQQFqIQRBgQEhEAy0AgsgBEEBaiEEQYIBIRAMswILAkAgBCACRw0AQZgBIRAMzAILIAIgBGsgACgCACIBaiEUIAQgAWtBBGohEAJAA0AgBC0AACABQanPgIAAai0AAEcNtAEgAUEERg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZgBIRAMzAILIABBADYCACAQQQFqIQFBGSEQDLEBCwJAIAQgAkcNAEGZASEQDMsCCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUGuz4CAAGotAABHDbMBIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGZASEQDMsCCyAAQQA2AgAgEEEBaiEBQQYhEAywAQsCQCAEIAJHDQBBmgEhEAzKAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBtM+AgABqLQAARw2yASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBmgEhEAzKAgsgAEEANgIAIBBBAWohAUEcIRAMrwELAkAgBCACRw0AQZsBIRAMyQILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQbbPgIAAai0AAEcNsQEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZsBIRAMyQILIABBADYCACAQQQFqIQFBJyEQDK4BCwJAIAQgAkcNAEGcASEQDMgCCwJAAkAgBC0AAEGsf2oOAgABsQELIARBAWohBEGGASEQDK8CCyAEQQFqIQRBhwEhEAyuAgsCQCAEIAJHDQBBnQEhEAzHAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBuM+AgABqLQAARw2vASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBnQEhEAzHAgsgAEEANgIAIBBBAWohAUEmIRAMrAELAkAgBCACRw0AQZ4BIRAMxgILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQbrPgIAAai0AAEcNrgEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZ4BIRAMxgILIABBADYCACAQQQFqIQFBAyEQDKsBCwJAIAQgAkcNAEGfASEQDMUCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDa0BIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGfASEQDMUCCyAAQQA2AgAgEEEBaiEBQQwhEAyqAQsCQCAEIAJHDQBBoAEhEAzEAgsgAiAEayAAKAIAIgFqIRQgBCABa0EDaiEQAkADQCAELQAAIAFBvM+AgABqLQAARw2sASABQQNGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBoAEhEAzEAgsgAEEANgIAIBBBAWohAUENIRAMqQELAkAgBCACRw0AQaEBIRAMwwILAkACQCAELQAAQbp/ag4LAKwBrAGsAawBrAGsAawBrAGsAQGsAQsgBEEBaiEEQYsBIRAMqgILIARBAWohBEGMASEQDKkCCwJAIAQgAkcNAEGiASEQDMICCyAELQAAQdAARw2pASAEQQFqIQQM6QELAkAgBCACRw0AQaMBIRAMwQILAkACQCAELQAAQbd/ag4HAaoBqgGqAaoBqgEAqgELIARBAWohBEGOASEQDKgCCyAEQQFqIQFBIiEQDKYBCwJAIAQgAkcNAEGkASEQDMACCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUHAz4CAAGotAABHDagBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGkASEQDMACCyAAQQA2AgAgEEEBaiEBQR0hEAylAQsCQCAEIAJHDQBBpQEhEAy/AgsCQAJAIAQtAABBrn9qDgMAqAEBqAELIARBAWohBEGQASEQDKYCCyAEQQFqIQFBBCEQDKQBCwJAIAQgAkcNAEGmASEQDL4CCwJAAkACQAJAAkAgBC0AAEG/f2oOFQCqAaoBqgGqAaoBqgGqAaoBqgGqAQGqAaoBAqoBqgEDqgGqAQSqAQsgBEEBaiEEQYgBIRAMqAILIARBAWohBEGJASEQDKcCCyAEQQFqIQRBigEhEAymAgsgBEEBaiEEQY8BIRAMpQILIARBAWohBEGRASEQDKQCCwJAIAQgAkcNAEGnASEQDL0CCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDaUBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGnASEQDL0CCyAAQQA2AgAgEEEBaiEBQREhEAyiAQsCQCAEIAJHDQBBqAEhEAy8AgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFBws+AgABqLQAARw2kASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBqAEhEAy8AgsgAEEANgIAIBBBAWohAUEsIRAMoQELAkAgBCACRw0AQakBIRAMuwILIAIgBGsgACgCACIBaiEUIAQgAWtBBGohEAJAA0AgBC0AACABQcXPgIAAai0AAEcNowEgAUEERg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQakBIRAMuwILIABBADYCACAQQQFqIQFBKyEQDKABCwJAIAQgAkcNAEGqASEQDLoCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHKz4CAAGotAABHDaIBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGqASEQDLoCCyAAQQA2AgAgEEEBaiEBQRQhEAyfAQsCQCAEIAJHDQBBqwEhEAy5AgsCQAJAAkACQCAELQAAQb5/ag4PAAECpAGkAaQBpAGkAaQBpAGkAaQBpAGkAQOkAQsgBEEBaiEEQZMBIRAMogILIARBAWohBEGUASEQDKECCyAEQQFqIQRBlQEhEAygAgsgBEEBaiEEQZYBIRAMnwILAkAgBCACRw0AQawBIRAMuAILIAQtAABBxQBHDZ8BIARBAWohBAzgAQsCQCAEIAJHDQBBrQEhEAy3AgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFBzc+AgABqLQAARw2fASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBrQEhEAy3AgsgAEEANgIAIBBBAWohAUEOIRAMnAELAkAgBCACRw0AQa4BIRAMtgILIAQtAABB0ABHDZ0BIARBAWohAUElIRAMmwELAkAgBCACRw0AQa8BIRAMtQILIAIgBGsgACgCACIBaiEUIAQgAWtBCGohEAJAA0AgBC0AACABQdDPgIAAai0AAEcNnQEgAUEIRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQa8BIRAMtQILIABBADYCACAQQQFqIQFBKiEQDJoBCwJAIAQgAkcNAEGwASEQDLQCCwJAAkAgBC0AAEGrf2oOCwCdAZ0BnQGdAZ0BnQGdAZ0BnQEBnQELIARBAWohBEGaASEQDJsCCyAEQQFqIQRBmwEhEAyaAgsCQCAEIAJHDQBBsQEhEAyzAgsCQAJAIAQtAABBv39qDhQAnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBAZwBCyAEQQFqIQRBmQEhEAyaAgsgBEEBaiEEQZwBIRAMmQILAkAgBCACRw0AQbIBIRAMsgILIAIgBGsgACgCACIBaiEUIAQgAWtBA2ohEAJAA0AgBC0AACABQdnPgIAAai0AAEcNmgEgAUEDRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbIBIRAMsgILIABBADYCACAQQQFqIQFBISEQDJcBCwJAIAQgAkcNAEGzASEQDLECCyACIARrIAAoAgAiAWohFCAEIAFrQQZqIRACQANAIAQtAAAgAUHdz4CAAGotAABHDZkBIAFBBkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGzASEQDLECCyAAQQA2AgAgEEEBaiEBQRohEAyWAQsCQCAEIAJHDQBBtAEhEAywAgsCQAJAAkAgBC0AAEG7f2oOEQCaAZoBmgGaAZoBmgGaAZoBmgEBmgGaAZoBmgGaAQKaAQsgBEEBaiEEQZ0BIRAMmAILIARBAWohBEGeASEQDJcCCyAEQQFqIQRBnwEhEAyWAgsCQCAEIAJHDQBBtQEhEAyvAgsgAiAEayAAKAIAIgFqIRQgBCABa0EFaiEQAkADQCAELQAAIAFB5M+AgABqLQAARw2XASABQQVGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBtQEhEAyvAgsgAEEANgIAIBBBAWohAUEoIRAMlAELAkAgBCACRw0AQbYBIRAMrgILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQerPgIAAai0AAEcNlgEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbYBIRAMrgILIABBADYCACAQQQFqIQFBByEQDJMBCwJAIAQgAkcNAEG3ASEQDK0CCwJAAkAgBC0AAEG7f2oODgCWAZYBlgGWAZYBlgGWAZYBlgGWAZYBlgEBlgELIARBAWohBEGhASEQDJQCCyAEQQFqIQRBogEhEAyTAgsCQCAEIAJHDQBBuAEhEAysAgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFB7c+AgABqLQAARw2UASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBuAEhEAysAgsgAEEANgIAIBBBAWohAUESIRAMkQELAkAgBCACRw0AQbkBIRAMqwILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfDPgIAAai0AAEcNkwEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbkBIRAMqwILIABBADYCACAQQQFqIQFBICEQDJABCwJAIAQgAkcNAEG6ASEQDKoCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUHyz4CAAGotAABHDZIBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG6ASEQDKoCCyAAQQA2AgAgEEEBaiEBQQ8hEAyPAQsCQCAEIAJHDQBBuwEhEAypAgsCQAJAIAQtAABBt39qDgcAkgGSAZIBkgGSAQGSAQsgBEEBaiEEQaUBIRAMkAILIARBAWohBEGmASEQDI8CCwJAIAQgAkcNAEG8ASEQDKgCCyACIARrIAAoAgAiAWohFCAEIAFrQQdqIRACQANAIAQtAAAgAUH0z4CAAGotAABHDZABIAFBB0YNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG8ASEQDKgCCyAAQQA2AgAgEEEBaiEBQRshEAyNAQsCQCAEIAJHDQBBvQEhEAynAgsCQAJAAkAgBC0AAEG+f2oOEgCRAZEBkQGRAZEBkQGRAZEBkQEBkQGRAZEBkQGRAZEBApEBCyAEQQFqIQRBpAEhEAyPAgsgBEEBaiEEQacBIRAMjgILIARBAWohBEGoASEQDI0CCwJAIAQgAkcNAEG+ASEQDKYCCyAELQAAQc4ARw2NASAEQQFqIQQMzwELAkAgBCACRw0AQb8BIRAMpQILAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgBC0AAEG/f2oOFQABAgOcAQQFBpwBnAGcAQcICQoLnAEMDQ4PnAELIARBAWohAUHoACEQDJoCCyAEQQFqIQFB6QAhEAyZAgsgBEEBaiEBQe4AIRAMmAILIARBAWohAUHyACEQDJcCCyAEQQFqIQFB8wAhEAyWAgsgBEEBaiEBQfYAIRAMlQILIARBAWohAUH3ACEQDJQCCyAEQQFqIQFB+gAhEAyTAgsgBEEBaiEEQYMBIRAMkgILIARBAWohBEGEASEQDJECCyAEQQFqIQRBhQEhEAyQAgsgBEEBaiEEQZIBIRAMjwILIARBAWohBEGYASEQDI4CCyAEQQFqIQRBoAEhEAyNAgsgBEEBaiEEQaMBIRAMjAILIARBAWohBEGqASEQDIsCCwJAIAQgAkYNACAAQZCAgIAANgIIIAAgBDYCBEGrASEQDIsCC0HAASEQDKMCCyAAIAUgAhCqgICAACIBDYsBIAUhAQxcCwJAIAYgAkYNACAGQQFqIQUMjQELQcIBIRAMoQILA0ACQCAQLQAAQXZqDgSMAQAAjwEACyAQQQFqIhAgAkcNAAtBwwEhEAygAgsCQCAHIAJGDQAgAEGRgICAADYCCCAAIAc2AgQgByEBQQEhEAyHAgtBxAEhEAyfAgsCQCAHIAJHDQBBxQEhEAyfAgsCQAJAIActAABBdmoOBAHOAc4BAM4BCyAHQQFqIQYMjQELIAdBAWohBQyJAQsCQCAHIAJHDQBBxgEhEAyeAgsCQAJAIActAABBdmoOFwGPAY8BAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAQCPAQsgB0EBaiEHC0GwASEQDIQCCwJAIAggAkcNAEHIASEQDJ0CCyAILQAAQSBHDY0BIABBADsBMiAIQQFqIQFBswEhEAyDAgsgASEXAkADQCAXIgcgAkYNASAHLQAAQVBqQf8BcSIQQQpPDcwBAkAgAC8BMiIUQZkzSw0AIAAgFEEKbCIUOwEyIBBB//8DcyAUQf7/A3FJDQAgB0EBaiEXIAAgFCAQaiIQOwEyIBBB//8DcUHoB0kNAQsLQQAhECAAQQA2AhwgAEHBiYCAADYCECAAQQ02AgwgACAHQQFqNgIUDJwCC0HHASEQDJsCCyAAIAggAhCugICAACIQRQ3KASAQQRVHDYwBIABByAE2AhwgACAINgIUIABByZeAgAA2AhAgAEEVNgIMQQAhEAyaAgsCQCAJIAJHDQBBzAEhEAyaAgtBACEUQQEhF0EBIRZBACEQAkACQAJAAkACQAJAAkACQAJAIAktAABBUGoOCpYBlQEAAQIDBAUGCJcBC0ECIRAMBgtBAyEQDAULQQQhEAwEC0EFIRAMAwtBBiEQDAILQQchEAwBC0EIIRALQQAhF0EAIRZBACEUDI4BC0EJIRBBASEUQQAhF0EAIRYMjQELAkAgCiACRw0AQc4BIRAMmQILIAotAABBLkcNjgEgCkEBaiEJDMoBCyALIAJHDY4BQdABIRAMlwILAkAgCyACRg0AIABBjoCAgAA2AgggACALNgIEQbcBIRAM/gELQdEBIRAMlgILAkAgBCACRw0AQdIBIRAMlgILIAIgBGsgACgCACIQaiEUIAQgEGtBBGohCwNAIAQtAAAgEEH8z4CAAGotAABHDY4BIBBBBEYN6QEgEEEBaiEQIARBAWoiBCACRw0ACyAAIBQ2AgBB0gEhEAyVAgsgACAMIAIQrICAgAAiAQ2NASAMIQEMuAELAkAgBCACRw0AQdQBIRAMlAILIAIgBGsgACgCACIQaiEUIAQgEGtBAWohDANAIAQtAAAgEEGB0ICAAGotAABHDY8BIBBBAUYNjgEgEEEBaiEQIARBAWoiBCACRw0ACyAAIBQ2AgBB1AEhEAyTAgsCQCAEIAJHDQBB1gEhEAyTAgsgAiAEayAAKAIAIhBqIRQgBCAQa0ECaiELA0AgBC0AACAQQYPQgIAAai0AAEcNjgEgEEECRg2QASAQQQFqIRAgBEEBaiIEIAJHDQALIAAgFDYCAEHWASEQDJICCwJAIAQgAkcNAEHXASEQDJICCwJAAkAgBC0AAEG7f2oOEACPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BAY8BCyAEQQFqIQRBuwEhEAz5AQsgBEEBaiEEQbwBIRAM+AELAkAgBCACRw0AQdgBIRAMkQILIAQtAABByABHDYwBIARBAWohBAzEAQsCQCAEIAJGDQAgAEGQgICAADYCCCAAIAQ2AgRBvgEhEAz3AQtB2QEhEAyPAgsCQCAEIAJHDQBB2gEhEAyPAgsgBC0AAEHIAEYNwwEgAEEBOgAoDLkBCyAAQQI6AC8gACAEIAIQpoCAgAAiEA2NAUHCASEQDPQBCyAALQAoQX9qDgK3AbkBuAELA0ACQCAELQAAQXZqDgQAjgGOAQCOAQsgBEEBaiIEIAJHDQALQd0BIRAMiwILIABBADoALyAALQAtQQRxRQ2EAgsgAEEAOgAvIABBAToANCABIQEMjAELIBBBFUYN2gEgAEEANgIcIAAgATYCFCAAQaeOgIAANgIQIABBEjYCDEEAIRAMiAILAkAgACAQIAIQtICAgAAiBA0AIBAhAQyBAgsCQCAEQRVHDQAgAEEDNgIcIAAgEDYCFCAAQbCYgIAANgIQIABBFTYCDEEAIRAMiAILIABBADYCHCAAIBA2AhQgAEGnjoCAADYCECAAQRI2AgxBACEQDIcCCyAQQRVGDdYBIABBADYCHCAAIAE2AhQgAEHajYCAADYCECAAQRQ2AgxBACEQDIYCCyAAKAIEIRcgAEEANgIEIBAgEadqIhYhASAAIBcgECAWIBQbIhAQtYCAgAAiFEUNjQEgAEEHNgIcIAAgEDYCFCAAIBQ2AgxBACEQDIUCCyAAIAAvATBBgAFyOwEwIAEhAQtBKiEQDOoBCyAQQRVGDdEBIABBADYCHCAAIAE2AhQgAEGDjICAADYCECAAQRM2AgxBACEQDIICCyAQQRVGDc8BIABBADYCHCAAIAE2AhQgAEGaj4CAADYCECAAQSI2AgxBACEQDIECCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQt4CAgAAiEA0AIAFBAWohAQyNAQsgAEEMNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDIACCyAQQRVGDcwBIABBADYCHCAAIAE2AhQgAEGaj4CAADYCECAAQSI2AgxBACEQDP8BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQt4CAgAAiEA0AIAFBAWohAQyMAQsgAEENNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDP4BCyAQQRVGDckBIABBADYCHCAAIAE2AhQgAEHGjICAADYCECAAQSM2AgxBACEQDP0BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQuYCAgAAiEA0AIAFBAWohAQyLAQsgAEEONgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDPwBCyAAQQA2AhwgACABNgIUIABBwJWAgAA2AhAgAEECNgIMQQAhEAz7AQsgEEEVRg3FASAAQQA2AhwgACABNgIUIABBxoyAgAA2AhAgAEEjNgIMQQAhEAz6AQsgAEEQNgIcIAAgATYCFCAAIBA2AgxBACEQDPkBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQuYCAgAAiBA0AIAFBAWohAQzxAQsgAEERNgIcIAAgBDYCDCAAIAFBAWo2AhRBACEQDPgBCyAQQRVGDcEBIABBADYCHCAAIAE2AhQgAEHGjICAADYCECAAQSM2AgxBACEQDPcBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQuYCAgAAiEA0AIAFBAWohAQyIAQsgAEETNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDPYBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQuYCAgAAiBA0AIAFBAWohAQztAQsgAEEUNgIcIAAgBDYCDCAAIAFBAWo2AhRBACEQDPUBCyAQQRVGDb0BIABBADYCHCAAIAE2AhQgAEGaj4CAADYCECAAQSI2AgxBACEQDPQBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQt4CAgAAiEA0AIAFBAWohAQyGAQsgAEEWNgIcIAAgEDYCDCAAIAFBAWo2AhRBACEQDPMBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQt4CAgAAiBA0AIAFBAWohAQzpAQsgAEEXNgIcIAAgBDYCDCAAIAFBAWo2AhRBACEQDPIBCyAAQQA2AhwgACABNgIUIABBzZOAgAA2AhAgAEEMNgIMQQAhEAzxAQtCASERCyAQQQFqIQECQCAAKQMgIhJC//////////8PVg0AIAAgEkIEhiARhDcDICABIQEMhAELIABBADYCHCAAIAE2AhQgAEGtiYCAADYCECAAQQw2AgxBACEQDO8BCyAAQQA2AhwgACAQNgIUIABBzZOAgAA2AhAgAEEMNgIMQQAhEAzuAQsgACgCBCEXIABBADYCBCAQIBGnaiIWIQEgACAXIBAgFiAUGyIQELWAgIAAIhRFDXMgAEEFNgIcIAAgEDYCFCAAIBQ2AgxBACEQDO0BCyAAQQA2AhwgACAQNgIUIABBqpyAgAA2AhAgAEEPNgIMQQAhEAzsAQsgACAQIAIQtICAgAAiAQ0BIBAhAQtBDiEQDNEBCwJAIAFBFUcNACAAQQI2AhwgACAQNgIUIABBsJiAgAA2AhAgAEEVNgIMQQAhEAzqAQsgAEEANgIcIAAgEDYCFCAAQaeOgIAANgIQIABBEjYCDEEAIRAM6QELIAFBAWohEAJAIAAvATAiAUGAAXFFDQACQCAAIBAgAhC7gICAACIBDQAgECEBDHALIAFBFUcNugEgAEEFNgIcIAAgEDYCFCAAQfmXgIAANgIQIABBFTYCDEEAIRAM6QELAkAgAUGgBHFBoARHDQAgAC0ALUECcQ0AIABBADYCHCAAIBA2AhQgAEGWk4CAADYCECAAQQQ2AgxBACEQDOkBCyAAIBAgAhC9gICAABogECEBAkACQAJAAkACQCAAIBAgAhCzgICAAA4WAgEABAQEBAQEBAQEBAQEBAQEBAQEAwQLIABBAToALgsgACAALwEwQcAAcjsBMCAQIQELQSYhEAzRAQsgAEEjNgIcIAAgEDYCFCAAQaWWgIAANgIQIABBFTYCDEEAIRAM6QELIABBADYCHCAAIBA2AhQgAEHVi4CAADYCECAAQRE2AgxBACEQDOgBCyAALQAtQQFxRQ0BQcMBIRAMzgELAkAgDSACRg0AA0ACQCANLQAAQSBGDQAgDSEBDMQBCyANQQFqIg0gAkcNAAtBJSEQDOcBC0ElIRAM5gELIAAoAgQhBCAAQQA2AgQgACAEIA0Qr4CAgAAiBEUNrQEgAEEmNgIcIAAgBDYCDCAAIA1BAWo2AhRBACEQDOUBCyAQQRVGDasBIABBADYCHCAAIAE2AhQgAEH9jYCAADYCECAAQR02AgxBACEQDOQBCyAAQSc2AhwgACABNgIUIAAgEDYCDEEAIRAM4wELIBAhAUEBIRQCQAJAAkACQAJAAkACQCAALQAsQX5qDgcGBQUDAQIABQsgACAALwEwQQhyOwEwDAMLQQIhFAwBC0EEIRQLIABBAToALCAAIAAvATAgFHI7ATALIBAhAQtBKyEQDMoBCyAAQQA2AhwgACAQNgIUIABBq5KAgAA2AhAgAEELNgIMQQAhEAziAQsgAEEANgIcIAAgATYCFCAAQeGPgIAANgIQIABBCjYCDEEAIRAM4QELIABBADoALCAQIQEMvQELIBAhAUEBIRQCQAJAAkACQAJAIAAtACxBe2oOBAMBAgAFCyAAIAAvATBBCHI7ATAMAwtBAiEUDAELQQQhFAsgAEEBOgAsIAAgAC8BMCAUcjsBMAsgECEBC0EpIRAMxQELIABBADYCHCAAIAE2AhQgAEHwlICAADYCECAAQQM2AgxBACEQDN0BCwJAIA4tAABBDUcNACAAKAIEIQEgAEEANgIEAkAgACABIA4QsYCAgAAiAQ0AIA5BAWohAQx1CyAAQSw2AhwgACABNgIMIAAgDkEBajYCFEEAIRAM3QELIAAtAC1BAXFFDQFBxAEhEAzDAQsCQCAOIAJHDQBBLSEQDNwBCwJAAkADQAJAIA4tAABBdmoOBAIAAAMACyAOQQFqIg4gAkcNAAtBLSEQDN0BCyAAKAIEIQEgAEEANgIEAkAgACABIA4QsYCAgAAiAQ0AIA4hAQx0CyAAQSw2AhwgACAONgIUIAAgATYCDEEAIRAM3AELIAAoAgQhASAAQQA2AgQCQCAAIAEgDhCxgICAACIBDQAgDkEBaiEBDHMLIABBLDYCHCAAIAE2AgwgACAOQQFqNgIUQQAhEAzbAQsgACgCBCEEIABBADYCBCAAIAQgDhCxgICAACIEDaABIA4hAQzOAQsgEEEsRw0BIAFBAWohEEEBIQECQAJAAkACQAJAIAAtACxBe2oOBAMBAgQACyAQIQEMBAtBAiEBDAELQQQhAQsgAEEBOgAsIAAgAC8BMCABcjsBMCAQIQEMAQsgACAALwEwQQhyOwEwIBAhAQtBOSEQDL8BCyAAQQA6ACwgASEBC0E0IRAMvQELIAAgAC8BMEEgcjsBMCABIQEMAgsgACgCBCEEIABBADYCBAJAIAAgBCABELGAgIAAIgQNACABIQEMxwELIABBNzYCHCAAIAE2AhQgACAENgIMQQAhEAzUAQsgAEEIOgAsIAEhAQtBMCEQDLkBCwJAIAAtAChBAUYNACABIQEMBAsgAC0ALUEIcUUNkwEgASEBDAMLIAAtADBBIHENlAFBxQEhEAy3AQsCQCAPIAJGDQACQANAAkAgDy0AAEFQaiIBQf8BcUEKSQ0AIA8hAUE1IRAMugELIAApAyAiEUKZs+bMmbPmzBlWDQEgACARQgp+IhE3AyAgESABrUL/AYMiEkJ/hVYNASAAIBEgEnw3AyAgD0EBaiIPIAJHDQALQTkhEAzRAQsgACgCBCECIABBADYCBCAAIAIgD0EBaiIEELGAgIAAIgINlQEgBCEBDMMBC0E5IRAMzwELAkAgAC8BMCIBQQhxRQ0AIAAtAChBAUcNACAALQAtQQhxRQ2QAQsgACABQff7A3FBgARyOwEwIA8hAQtBNyEQDLQBCyAAIAAvATBBEHI7ATAMqwELIBBBFUYNiwEgAEEANgIcIAAgATYCFCAAQfCOgIAANgIQIABBHDYCDEEAIRAMywELIABBwwA2AhwgACABNgIMIAAgDUEBajYCFEEAIRAMygELAkAgAS0AAEE6Rw0AIAAoAgQhECAAQQA2AgQCQCAAIBAgARCvgICAACIQDQAgAUEBaiEBDGMLIABBwwA2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAMygELIABBADYCHCAAIAE2AhQgAEGxkYCAADYCECAAQQo2AgxBACEQDMkBCyAAQQA2AhwgACABNgIUIABBoJmAgAA2AhAgAEEeNgIMQQAhEAzIAQsgAEEANgIACyAAQYASOwEqIAAgF0EBaiIBIAIQqICAgAAiEA0BIAEhAQtBxwAhEAysAQsgEEEVRw2DASAAQdEANgIcIAAgATYCFCAAQeOXgIAANgIQIABBFTYCDEEAIRAMxAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDF4LIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMwwELIABBADYCHCAAIBQ2AhQgAEHBqICAADYCECAAQQc2AgwgAEEANgIAQQAhEAzCAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMXQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAzBAQtBACEQIABBADYCHCAAIAE2AhQgAEGAkYCAADYCECAAQQk2AgwMwAELIBBBFUYNfSAAQQA2AhwgACABNgIUIABBlI2AgAA2AhAgAEEhNgIMQQAhEAy/AQtBASEWQQAhF0EAIRRBASEQCyAAIBA6ACsgAUEBaiEBAkACQCAALQAtQRBxDQACQAJAAkAgAC0AKg4DAQACBAsgFkUNAwwCCyAUDQEMAgsgF0UNAQsgACgCBCEQIABBADYCBAJAIAAgECABEK2AgIAAIhANACABIQEMXAsgAEHYADYCHCAAIAE2AhQgACAQNgIMQQAhEAy+AQsgACgCBCEEIABBADYCBAJAIAAgBCABEK2AgIAAIgQNACABIQEMrQELIABB2QA2AhwgACABNgIUIAAgBDYCDEEAIRAMvQELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCtgICAACIEDQAgASEBDKsBCyAAQdoANgIcIAAgATYCFCAAIAQ2AgxBACEQDLwBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQrYCAgAAiBA0AIAEhAQypAQsgAEHcADYCHCAAIAE2AhQgACAENgIMQQAhEAy7AQsCQCABLQAAQVBqIhBB/wFxQQpPDQAgACAQOgAqIAFBAWohAUHPACEQDKIBCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQrYCAgAAiBA0AIAEhAQynAQsgAEHeADYCHCAAIAE2AhQgACAENgIMQQAhEAy6AQsgAEEANgIAIBdBAWohAQJAIAAtAClBI08NACABIQEMWQsgAEEANgIcIAAgATYCFCAAQdOJgIAANgIQIABBCDYCDEEAIRAMuQELIABBADYCAAtBACEQIABBADYCHCAAIAE2AhQgAEGQs4CAADYCECAAQQg2AgwMtwELIABBADYCACAXQQFqIQECQCAALQApQSFHDQAgASEBDFYLIABBADYCHCAAIAE2AhQgAEGbioCAADYCECAAQQg2AgxBACEQDLYBCyAAQQA2AgAgF0EBaiEBAkAgAC0AKSIQQV1qQQtPDQAgASEBDFULAkAgEEEGSw0AQQEgEHRBygBxRQ0AIAEhAQxVC0EAIRAgAEEANgIcIAAgATYCFCAAQfeJgIAANgIQIABBCDYCDAy1AQsgEEEVRg1xIABBADYCHCAAIAE2AhQgAEG5jYCAADYCECAAQRo2AgxBACEQDLQBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxUCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLMBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdIANgIcIAAgATYCFCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=' + + +/***/ }), + +/***/ 53434: +/***/ ((module) => { + +module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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IAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEBkgGTAZQBlQGWAZcBmAGZAZoBmwGcAZ0BngGfAaABoQGiAaMBpAGlAaYBpwGoAakBqgGrAawBrQGuAa8BsAGxAbIBswG0AbUBtgG3AcsBygG4AckBuQHIAboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBANwBC0EAIRAMxgELQQ4hEAzFAQtBDSEQDMQBC0EPIRAMwwELQRAhEAzCAQtBEyEQDMEBC0EUIRAMwAELQRUhEAy/AQtBFiEQDL4BC0EXIRAMvQELQRghEAy8AQtBGSEQDLsBC0EaIRAMugELQRshEAy5AQtBHCEQDLgBC0EIIRAMtwELQR0hEAy2AQtBICEQDLUBC0EfIRAMtAELQQchEAyzAQtBISEQDLIBC0EiIRAMsQELQR4hEAywAQtBIyEQDK8BC0ESIRAMrgELQREhEAytAQtBJCEQDKwBC0ElIRAMqwELQSYhEAyqAQtBJyEQDKkBC0HDASEQDKgBC0EpIRAMpwELQSshEAymAQtBLCEQDKUBC0EtIRAMpAELQS4hEAyjAQtBLyEQDKIBC0HEASEQDKEBC0EwIRAMoAELQTQhEAyfAQtBDCEQDJ4BC0ExIRAMnQELQTIhEAycAQtBMyEQDJsBC0E5IRAMmgELQTUhEAyZAQtBxQEhEAyYAQtBCyEQDJcBC0E6IRAMlgELQTYhEAyVAQtBCiEQDJQBC0E3IRAMkwELQTghEAySAQtBPCEQDJEBC0E7IRAMkAELQT0hEAyPAQtBCSEQDI4BC0EoIRAMjQELQT4hEAyMAQtBPyEQDIsBC0HAACEQDIoBC0HBACEQDIkBC0HCACEQDIgBC0HDACEQDIcBC0HEACEQDIYBC0HFACEQDIUBC0HGACEQDIQBC0EqIRAMgwELQccAIRAMggELQcgAIRAMgQELQckAIRAMgAELQcoAIRAMfwtBywAhEAx+C0HNACEQDH0LQcwAIRAMfAtBzgAhEAx7C0HPACEQDHoLQdAAIRAMeQtB0QAhEAx4C0HSACEQDHcLQdMAIRAMdgtB1AAhEAx1C0HWACEQDHQLQdUAIRAMcwtBBiEQDHILQdcAIRAMcQtBBSEQDHALQdgAIRAMbwtBBCEQDG4LQdkAIRAMbQtB2gAhEAxsC0HbACEQDGsLQdwAIRAMagtBAyEQDGkLQd0AIRAMaAtB3gAhEAxnC0HfACEQDGYLQeEAIRAMZQtB4AAhEAxkC0HiACEQDGMLQeMAIRAMYgtBAiEQDGELQeQAIRAMYAtB5QAhEAxfC0HmACEQDF4LQecAIRAMXQtB6AAhEAxcC0HpACEQDFsLQeoAIRAMWgtB6wAhEAxZC0HsACEQDFgLQe0AIRAMVwtB7gAhEAxWC0HvACEQDFULQfAAIRAMVAtB8QAhEAxTC0HyACEQDFILQfMAIRAMUQtB9AAhEAxQC0H1ACEQDE8LQfYAIRAMTgtB9wAhEAxNC0H4ACEQDEwLQfkAIRAMSwtB+gAhEAxKC0H7ACEQDEkLQfwAIRAMSAtB/QAhEAxHC0H+ACEQDEYLQf8AIRAMRQtBgAEhEAxEC0GBASEQDEMLQYIBIRAMQgtBgwEhEAxBC0GEASEQDEALQYUBIRAMPwtBhgEhEAw+C0GHASEQDD0LQYgBIRAMPAtBiQEhEAw7C0GKASEQDDoLQYsBIRAMOQtBjAEhEAw4C0GNASEQDDcLQY4BIRAMNgtBjwEhEAw1C0GQASEQDDQLQZEBIRAMMwtBkgEhEAwyC0GTASEQDDELQZQBIRAMMAtBlQEhEAwvC0GWASEQDC4LQZcBIRAMLQtBmAEhEAwsC0GZASEQDCsLQZoBIRAMKgtBmwEhEAwpC0GcASEQDCgLQZ0BIRAMJwtBngEhEAwmC0GfASEQDCULQaABIRAMJAtBoQEhEAwjC0GiASEQDCILQaMBIRAMIQtBpAEhEAwgC0GlASEQDB8LQaYBIRAMHgtBpwEhEAwdC0GoASEQDBwLQakBIRAMGwtBqgEhEAwaC0GrASEQDBkLQawBIRAMGAtBrQEhEAwXC0GuASEQDBYLQQEhEAwVC0GvASEQDBQLQbABIRAMEwtBsQEhEAwSC0GzASEQDBELQbIBIRAMEAtBtAEhEAwPC0G1ASEQDA4LQbYBIRAMDQtBtwEhEAwMC0G4ASEQDAsLQbkBIRAMCgtBugEhEAwJC0G7ASEQDAgLQcYBIRAMBwtBvAEhEAwGC0G9ASEQDAULQb4BIRAMBAtBvwEhEAwDC0HAASEQDAILQcIBIRAMAQtBwQEhEAsDQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB4fICEjJSg/QEFERUZHSElKS0xNT1BRUlPeA1dZW1xdYGJlZmdoaWprbG1vcHFyc3R1dnd4eXp7fH1+gAGCAYUBhgGHAYkBiwGMAY0BjgGPAZABkQGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0B3gHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMBmQKkArAC/gL+AgsgASIEIAJHDfMBQd0BIRAM/wMLIAEiECACRw3dAUHDASEQDP4DCyABIgEgAkcNkAFB9wAhEAz9AwsgASIBIAJHDYYBQe8AIRAM/AMLIAEiASACRw1/QeoAIRAM+wMLIAEiASACRw17QegAIRAM+gMLIAEiASACRw14QeYAIRAM+QMLIAEiASACRw0aQRghEAz4AwsgASIBIAJHDRRBEiEQDPcDCyABIgEgAkcNWUHFACEQDPYDCyABIgEgAkcNSkE/IRAM9QMLIAEiASACRw1IQTwhEAz0AwsgASIBIAJHDUFBMSEQDPMDCyAALQAuQQFGDesDDIcCCyAAIAEiASACEMCAgIAAQQFHDeYBIABCADcDIAznAQsgACABIgEgAhC0gICAACIQDecBIAEhAQz1AgsCQCABIgEgAkcNAEEGIRAM8AMLIAAgAUEBaiIBIAIQu4CAgAAiEA3oASABIQEMMQsgAEIANwMgQRIhEAzVAwsgASIQIAJHDStBHSEQDO0DCwJAIAEiASACRg0AIAFBAWohAUEQIRAM1AMLQQchEAzsAwsgAEIAIAApAyAiESACIAEiEGutIhJ9IhMgEyARVhs3AyAgESASViIURQ3lAUEIIRAM6wMLAkAgASIBIAJGDQAgAEGJgICAADYCCCAAIAE2AgQgASEBQRQhEAzSAwtBCSEQDOoDCyABIQEgACkDIFAN5AEgASEBDPICCwJAIAEiASACRw0AQQshEAzpAwsgACABQQFqIgEgAhC2gICAACIQDeUBIAEhAQzyAgsgACABIgEgAhC4gICAACIQDeUBIAEhAQzyAgsgACABIgEgAhC4gICAACIQDeYBIAEhAQwNCyAAIAEiASACELqAgIAAIhAN5wEgASEBDPACCwJAIAEiASACRw0AQQ8hEAzlAwsgAS0AACIQQTtGDQggEEENRw3oASABQQFqIQEM7wILIAAgASIBIAIQuoCAgAAiEA3oASABIQEM8gILA0ACQCABLQAAQfC1gIAAai0AACIQQQFGDQAgEEECRw3rASAAKAIEIRAgAEEANgIEIAAgECABQQFqIgEQuYCAgAAiEA3qASABIQEM9AILIAFBAWoiASACRw0AC0ESIRAM4gMLIAAgASIBIAIQuoCAgAAiEA3pASABIQEMCgsgASIBIAJHDQZBGyEQDOADCwJAIAEiASACRw0AQRYhEAzgAwsgAEGKgICAADYCCCAAIAE2AgQgACABIAIQuICAgAAiEA3qASABIQFBICEQDMYDCwJAIAEiASACRg0AA0ACQCABLQAAQfC3gIAAai0AACIQQQJGDQACQCAQQX9qDgTlAewBAOsB7AELIAFBAWohAUEIIRAMyAMLIAFBAWoiASACRw0AC0EVIRAM3wMLQRUhEAzeAwsDQAJAIAEtAABB8LmAgABqLQAAIhBBAkYNACAQQX9qDgTeAewB4AHrAewBCyABQQFqIgEgAkcNAAtBGCEQDN0DCwJAIAEiASACRg0AIABBi4CAgAA2AgggACABNgIEIAEhAUEHIRAMxAMLQRkhEAzcAwsgAUEBaiEBDAILAkAgASIUIAJHDQBBGiEQDNsDCyAUIQECQCAULQAAQXNqDhTdAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAu4C7gLuAgDuAgtBACEQIABBADYCHCAAQa+LgIAANgIQIABBAjYCDCAAIBRBAWo2AhQM2gMLAkAgAS0AACIQQTtGDQAgEEENRw3oASABQQFqIQEM5QILIAFBAWohAQtBIiEQDL8DCwJAIAEiECACRw0AQRwhEAzYAwtCACERIBAhASAQLQAAQVBqDjfnAeYBAQIDBAUGBwgAAAAAAAAACQoLDA0OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPEBESExQAC0EeIRAMvQMLQgIhEQzlAQtCAyERDOQBC0IEIREM4wELQgUhEQziAQtCBiERDOEBC0IHIREM4AELQgghEQzfAQtCCSERDN4BC0IKIREM3QELQgshEQzcAQtCDCERDNsBC0INIREM2gELQg4hEQzZAQtCDyERDNgBC0IKIREM1wELQgshEQzWAQtCDCERDNUBC0INIREM1AELQg4hEQzTAQtCDyERDNIBC0IAIRECQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAtAABBUGoON+UB5AEAAQIDBAUGB+YB5gHmAeYB5gHmAeYBCAkKCwwN5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAeYB5gHmAQ4PEBESE+YBC0ICIREM5AELQgMhEQzjAQtCBCERDOIBC0IFIREM4QELQgYhEQzgAQtCByERDN8BC0IIIREM3gELQgkhEQzdAQtCCiERDNwBC0ILIREM2wELQgwhEQzaAQtCDSERDNkBC0IOIREM2AELQg8hEQzXAQtCCiERDNYBC0ILIREM1QELQgwhEQzUAQtCDSERDNMBC0IOIREM0gELQg8hEQzRAQsgAEIAIAApAyAiESACIAEiEGutIhJ9IhMgEyARVhs3AyAgESASViIURQ3SAUEfIRAMwAMLAkAgASIBIAJGDQAgAEGJgICAADYCCCAAIAE2AgQgASEBQSQhEAynAwtBICEQDL8DCyAAIAEiECACEL6AgIAAQX9qDgW2AQDFAgHRAdIBC0ERIRAMpAMLIABBAToALyAQIQEMuwMLIAEiASACRw3SAUEkIRAMuwMLIAEiDSACRw0eQcYAIRAMugMLIAAgASIBIAIQsoCAgAAiEA3UASABIQEMtQELIAEiECACRw0mQdAAIRAMuAMLAkAgASIBIAJHDQBBKCEQDLgDCyAAQQA2AgQgAEGMgICAADYCCCAAIAEgARCxgICAACIQDdMBIAEhAQzYAQsCQCABIhAgAkcNAEEpIRAMtwMLIBAtAAAiAUEgRg0UIAFBCUcN0wEgEEEBaiEBDBULAkAgASIBIAJGDQAgAUEBaiEBDBcLQSohEAy1AwsCQCABIhAgAkcNAEErIRAMtQMLAkAgEC0AACIBQQlGDQAgAUEgRw3VAQsgAC0ALEEIRg3TASAQIQEMkQMLAkAgASIBIAJHDQBBLCEQDLQDCyABLQAAQQpHDdUBIAFBAWohAQzJAgsgASIOIAJHDdUBQS8hEAyyAwsDQAJAIAEtAAAiEEEgRg0AAkAgEEF2ag4EANwB3AEA2gELIAEhAQzgAQsgAUEBaiIBIAJHDQALQTEhEAyxAwtBMiEQIAEiFCACRg2wAyACIBRrIAAoAgAiAWohFSAUIAFrQQNqIRYCQANAIBQtAAAiF0EgciAXIBdBv39qQf8BcUEaSRtB/wFxIAFB8LuAgABqLQAARw0BAkAgAUEDRw0AQQYhAQyWAwsgAUEBaiEBIBRBAWoiFCACRw0ACyAAIBU2AgAMsQMLIABBADYCACAUIQEM2QELQTMhECABIhQgAkYNrwMgAiAUayAAKAIAIgFqIRUgFCABa0EIaiEWAkADQCAULQAAIhdBIHIgFyAXQb9/akH/AXFBGkkbQf8BcSABQfS7gIAAai0AAEcNAQJAIAFBCEcNAEEFIQEMlQMLIAFBAWohASAUQQFqIhQgAkcNAAsgACAVNgIADLADCyAAQQA2AgAgFCEBDNgBC0E0IRAgASIUIAJGDa4DIAIgFGsgACgCACIBaiEVIBQgAWtBBWohFgJAA0AgFC0AACIXQSByIBcgF0G/f2pB/wFxQRpJG0H/AXEgAUHQwoCAAGotAABHDQECQCABQQVHDQBBByEBDJQDCyABQQFqIQEgFEEBaiIUIAJHDQALIAAgFTYCAAyvAwsgAEEANgIAIBQhAQzXAQsCQCABIgEgAkYNAANAAkAgAS0AAEGAvoCAAGotAAAiEEEBRg0AIBBBAkYNCiABIQEM3QELIAFBAWoiASACRw0AC0EwIRAMrgMLQTAhEAytAwsCQCABIgEgAkYNAANAAkAgAS0AACIQQSBGDQAgEEF2ag4E2QHaAdoB2QHaAQsgAUEBaiIBIAJHDQALQTghEAytAwtBOCEQDKwDCwNAAkAgAS0AACIQQSBGDQAgEEEJRw0DCyABQQFqIgEgAkcNAAtBPCEQDKsDCwNAAkAgAS0AACIQQSBGDQACQAJAIBBBdmoOBNoBAQHaAQALIBBBLEYN2wELIAEhAQwECyABQQFqIgEgAkcNAAtBPyEQDKoDCyABIQEM2wELQcAAIRAgASIUIAJGDagDIAIgFGsgACgCACIBaiEWIBQgAWtBBmohFwJAA0AgFC0AAEEgciABQYDAgIAAai0AAEcNASABQQZGDY4DIAFBAWohASAUQQFqIhQgAkcNAAsgACAWNgIADKkDCyAAQQA2AgAgFCEBC0E2IRAMjgMLAkAgASIPIAJHDQBBwQAhEAynAwsgAEGMgICAADYCCCAAIA82AgQgDyEBIAAtACxBf2oOBM0B1QHXAdkBhwMLIAFBAWohAQzMAQsCQCABIgEgAkYNAANAAkAgAS0AACIQQSByIBAgEEG/f2pB/wFxQRpJG0H/AXEiEEEJRg0AIBBBIEYNAAJAAkACQAJAIBBBnX9qDhMAAwMDAwMDAwEDAwMDAwMDAwMCAwsgAUEBaiEBQTEhEAyRAwsgAUEBaiEBQTIhEAyQAwsgAUEBaiEBQTMhEAyPAwsgASEBDNABCyABQQFqIgEgAkcNAAtBNSEQDKUDC0E1IRAMpAMLAkAgASIBIAJGDQADQAJAIAEtAABBgLyAgABqLQAAQQFGDQAgASEBDNMBCyABQQFqIgEgAkcNAAtBPSEQDKQDC0E9IRAMowMLIAAgASIBIAIQsICAgAAiEA3WASABIQEMAQsgEEEBaiEBC0E8IRAMhwMLAkAgASIBIAJHDQBBwgAhEAygAwsCQANAAkAgAS0AAEF3ag4YAAL+Av4ChAP+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gL+Av4C/gIA/gILIAFBAWoiASACRw0AC0HCACEQDKADCyABQQFqIQEgAC0ALUEBcUUNvQEgASEBC0EsIRAMhQMLIAEiASACRw3TAUHEACEQDJ0DCwNAAkAgAS0AAEGQwICAAGotAABBAUYNACABIQEMtwILIAFBAWoiASACRw0AC0HFACEQDJwDCyANLQAAIhBBIEYNswEgEEE6Rw2BAyAAKAIEIQEgAEEANgIEIAAgASANEK+AgIAAIgEN0AEgDUEBaiEBDLMCC0HHACEQIAEiDSACRg2aAyACIA1rIAAoAgAiAWohFiANIAFrQQVqIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQZDCgIAAai0AAEcNgAMgAUEFRg30AiABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyaAwtByAAhECABIg0gAkYNmQMgAiANayAAKAIAIgFqIRYgDSABa0EJaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUGWwoCAAGotAABHDf8CAkAgAUEJRw0AQQIhAQz1AgsgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMmQMLAkAgASINIAJHDQBByQAhEAyZAwsCQAJAIA0tAAAiAUEgciABIAFBv39qQf8BcUEaSRtB/wFxQZJ/ag4HAIADgAOAA4ADgAMBgAMLIA1BAWohAUE+IRAMgAMLIA1BAWohAUE/IRAM/wILQcoAIRAgASINIAJGDZcDIAIgDWsgACgCACIBaiEWIA0gAWtBAWohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFBoMKAgABqLQAARw39AiABQQFGDfACIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJcDC0HLACEQIAEiDSACRg2WAyACIA1rIAAoAgAiAWohFiANIAFrQQ5qIRcDQCANLQAAIhRBIHIgFCAUQb9/akH/AXFBGkkbQf8BcSABQaLCgIAAai0AAEcN/AIgAUEORg3wAiABQQFqIQEgDUEBaiINIAJHDQALIAAgFjYCAAyWAwtBzAAhECABIg0gAkYNlQMgAiANayAAKAIAIgFqIRYgDSABa0EPaiEXA0AgDS0AACIUQSByIBQgFEG/f2pB/wFxQRpJG0H/AXEgAUHAwoCAAGotAABHDfsCAkAgAUEPRw0AQQMhAQzxAgsgAUEBaiEBIA1BAWoiDSACRw0ACyAAIBY2AgAMlQMLQc0AIRAgASINIAJGDZQDIAIgDWsgACgCACIBaiEWIA0gAWtBBWohFwNAIA0tAAAiFEEgciAUIBRBv39qQf8BcUEaSRtB/wFxIAFB0MKAgABqLQAARw36AgJAIAFBBUcNAEEEIQEM8AILIAFBAWohASANQQFqIg0gAkcNAAsgACAWNgIADJQDCwJAIAEiDSACRw0AQc4AIRAMlAMLAkACQAJAAkAgDS0AACIBQSByIAEgAUG/f2pB/wFxQRpJG0H/AXFBnX9qDhMA/QL9Av0C/QL9Av0C/QL9Av0C/QL9Av0CAf0C/QL9AgID/QILIA1BAWohAUHBACEQDP0CCyANQQFqIQFBwgAhEAz8AgsgDUEBaiEBQcMAIRAM+wILIA1BAWohAUHEACEQDPoCCwJAIAEiASACRg0AIABBjYCAgAA2AgggACABNgIEIAEhAUHFACEQDPoCC0HPACEQDJIDCyAQIQECQAJAIBAtAABBdmoOBAGoAqgCAKgCCyAQQQFqIQELQSchEAz4AgsCQCABIgEgAkcNAEHRACEQDJEDCwJAIAEtAABBIEYNACABIQEMjQELIAFBAWohASAALQAtQQFxRQ3HASABIQEMjAELIAEiFyACRw3IAUHSACEQDI8DC0HTACEQIAEiFCACRg2OAyACIBRrIAAoAgAiAWohFiAUIAFrQQFqIRcDQCAULQAAIAFB1sKAgABqLQAARw3MASABQQFGDccBIAFBAWohASAUQQFqIhQgAkcNAAsgACAWNgIADI4DCwJAIAEiASACRw0AQdUAIRAMjgMLIAEtAABBCkcNzAEgAUEBaiEBDMcBCwJAIAEiASACRw0AQdYAIRAMjQMLAkACQCABLQAAQXZqDgQAzQHNAQHNAQsgAUEBaiEBDMcBCyABQQFqIQFBygAhEAzzAgsgACABIgEgAhCugICAACIQDcsBIAEhAUHNACEQDPICCyAALQApQSJGDYUDDKYCCwJAIAEiASACRw0AQdsAIRAMigMLQQAhFEEBIRdBASEWQQAhEAJAAkACQAJAAkACQAJAAkACQCABLQAAQVBqDgrUAdMBAAECAwQFBgjVAQtBAiEQDAYLQQMhEAwFC0EEIRAMBAtBBSEQDAMLQQYhEAwCC0EHIRAMAQtBCCEQC0EAIRdBACEWQQAhFAzMAQtBCSEQQQEhFEEAIRdBACEWDMsBCwJAIAEiASACRw0AQd0AIRAMiQMLIAEtAABBLkcNzAEgAUEBaiEBDKYCCyABIgEgAkcNzAFB3wAhEAyHAwsCQCABIgEgAkYNACAAQY6AgIAANgIIIAAgATYCBCABIQFB0AAhEAzuAgtB4AAhEAyGAwtB4QAhECABIgEgAkYNhQMgAiABayAAKAIAIhRqIRYgASAUa0EDaiEXA0AgAS0AACAUQeLCgIAAai0AAEcNzQEgFEEDRg3MASAUQQFqIRQgAUEBaiIBIAJHDQALIAAgFjYCAAyFAwtB4gAhECABIgEgAkYNhAMgAiABayAAKAIAIhRqIRYgASAUa0ECaiEXA0AgAS0AACAUQebCgIAAai0AAEcNzAEgFEECRg3OASAUQQFqIRQgAUEBaiIBIAJHDQALIAAgFjYCAAyEAwtB4wAhECABIgEgAkYNgwMgAiABayAAKAIAIhRqIRYgASAUa0EDaiEXA0AgAS0AACAUQenCgIAAai0AAEcNywEgFEEDRg3OASAUQQFqIRQgAUEBaiIBIAJHDQALIAAgFjYCAAyDAwsCQCABIgEgAkcNAEHlACEQDIMDCyAAIAFBAWoiASACEKiAgIAAIhANzQEgASEBQdYAIRAM6QILAkAgASIBIAJGDQADQAJAIAEtAAAiEEEgRg0AAkACQAJAIBBBuH9qDgsAAc8BzwHPAc8BzwHPAc8BzwECzwELIAFBAWohAUHSACEQDO0CCyABQQFqIQFB0wAhEAzsAgsgAUEBaiEBQdQAIRAM6wILIAFBAWoiASACRw0AC0HkACEQDIIDC0HkACEQDIEDCwNAAkAgAS0AAEHwwoCAAGotAAAiEEEBRg0AIBBBfmoOA88B0AHRAdIBCyABQQFqIgEgAkcNAAtB5gAhEAyAAwsCQCABIgEgAkYNACABQQFqIQEMAwtB5wAhEAz/AgsDQAJAIAEtAABB8MSAgABqLQAAIhBBAUYNAAJAIBBBfmoOBNIB0wHUAQDVAQsgASEBQdcAIRAM5wILIAFBAWoiASACRw0AC0HoACEQDP4CCwJAIAEiASACRw0AQekAIRAM/gILAkAgAS0AACIQQXZqDhq6AdUB1QG8AdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAdUB1QHVAcoB1QHVAQDTAQsgAUEBaiEBC0EGIRAM4wILA0ACQCABLQAAQfDGgIAAai0AAEEBRg0AIAEhAQyeAgsgAUEBaiIBIAJHDQALQeoAIRAM+wILAkAgASIBIAJGDQAgAUEBaiEBDAMLQesAIRAM+gILAkAgASIBIAJHDQBB7AAhEAz6AgsgAUEBaiEBDAELAkAgASIBIAJHDQBB7QAhEAz5AgsgAUEBaiEBC0EEIRAM3gILAkAgASIUIAJHDQBB7gAhEAz3AgsgFCEBAkACQAJAIBQtAABB8MiAgABqLQAAQX9qDgfUAdUB1gEAnAIBAtcBCyAUQQFqIQEMCgsgFEEBaiEBDM0BC0EAIRAgAEEANgIcIABBm5KAgAA2AhAgAEEHNgIMIAAgFEEBajYCFAz2AgsCQANAAkAgAS0AAEHwyICAAGotAAAiEEEERg0AAkACQCAQQX9qDgfSAdMB1AHZAQAEAdkBCyABIQFB2gAhEAzgAgsgAUEBaiEBQdwAIRAM3wILIAFBAWoiASACRw0AC0HvACEQDPYCCyABQQFqIQEMywELAkAgASIUIAJHDQBB8AAhEAz1AgsgFC0AAEEvRw3UASAUQQFqIQEMBgsCQCABIhQgAkcNAEHxACEQDPQCCwJAIBQtAAAiAUEvRw0AIBRBAWohAUHdACEQDNsCCyABQXZqIgRBFksN0wFBASAEdEGJgIACcUUN0wEMygILAkAgASIBIAJGDQAgAUEBaiEBQd4AIRAM2gILQfIAIRAM8gILAkAgASIUIAJHDQBB9AAhEAzyAgsgFCEBAkAgFC0AAEHwzICAAGotAABBf2oOA8kClAIA1AELQeEAIRAM2AILAkAgASIUIAJGDQADQAJAIBQtAABB8MqAgABqLQAAIgFBA0YNAAJAIAFBf2oOAssCANUBCyAUIQFB3wAhEAzaAgsgFEEBaiIUIAJHDQALQfMAIRAM8QILQfMAIRAM8AILAkAgASIBIAJGDQAgAEGPgICAADYCCCAAIAE2AgQgASEBQeAAIRAM1wILQfUAIRAM7wILAkAgASIBIAJHDQBB9gAhEAzvAgsgAEGPgICAADYCCCAAIAE2AgQgASEBC0EDIRAM1AILA0AgAS0AAEEgRw3DAiABQQFqIgEgAkcNAAtB9wAhEAzsAgsCQCABIgEgAkcNAEH4ACEQDOwCCyABLQAAQSBHDc4BIAFBAWohAQzvAQsgACABIgEgAhCsgICAACIQDc4BIAEhAQyOAgsCQCABIgQgAkcNAEH6ACEQDOoCCyAELQAAQcwARw3RASAEQQFqIQFBEyEQDM8BCwJAIAEiBCACRw0AQfsAIRAM6QILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEANAIAQtAAAgAUHwzoCAAGotAABHDdABIAFBBUYNzgEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBB+wAhEAzoAgsCQCABIgQgAkcNAEH8ACEQDOgCCwJAAkAgBC0AAEG9f2oODADRAdEB0QHRAdEB0QHRAdEB0QHRAQHRAQsgBEEBaiEBQeYAIRAMzwILIARBAWohAUHnACEQDM4CCwJAIAEiBCACRw0AQf0AIRAM5wILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQe3PgIAAai0AAEcNzwEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQf0AIRAM5wILIABBADYCACAQQQFqIQFBECEQDMwBCwJAIAEiBCACRw0AQf4AIRAM5gILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQfbOgIAAai0AAEcNzgEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQf4AIRAM5gILIABBADYCACAQQQFqIQFBFiEQDMsBCwJAIAEiBCACRw0AQf8AIRAM5QILIAIgBGsgACgCACIBaiEUIAQgAWtBA2ohEAJAA0AgBC0AACABQfzOgIAAai0AAEcNzQEgAUEDRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQf8AIRAM5QILIABBADYCACAQQQFqIQFBBSEQDMoBCwJAIAEiBCACRw0AQYABIRAM5AILIAQtAABB2QBHDcsBIARBAWohAUEIIRAMyQELAkAgASIEIAJHDQBBgQEhEAzjAgsCQAJAIAQtAABBsn9qDgMAzAEBzAELIARBAWohAUHrACEQDMoCCyAEQQFqIQFB7AAhEAzJAgsCQCABIgQgAkcNAEGCASEQDOICCwJAAkAgBC0AAEG4f2oOCADLAcsBywHLAcsBywEBywELIARBAWohAUHqACEQDMkCCyAEQQFqIQFB7QAhEAzIAgsCQCABIgQgAkcNAEGDASEQDOECCyACIARrIAAoAgAiAWohECAEIAFrQQJqIRQCQANAIAQtAAAgAUGAz4CAAGotAABHDckBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgEDYCAEGDASEQDOECC0EAIRAgAEEANgIAIBRBAWohAQzGAQsCQCABIgQgAkcNAEGEASEQDOACCyACIARrIAAoAgAiAWohFCAEIAFrQQRqIRACQANAIAQtAAAgAUGDz4CAAGotAABHDcgBIAFBBEYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGEASEQDOACCyAAQQA2AgAgEEEBaiEBQSMhEAzFAQsCQCABIgQgAkcNAEGFASEQDN8CCwJAAkAgBC0AAEG0f2oOCADIAcgByAHIAcgByAEByAELIARBAWohAUHvACEQDMYCCyAEQQFqIQFB8AAhEAzFAgsCQCABIgQgAkcNAEGGASEQDN4CCyAELQAAQcUARw3FASAEQQFqIQEMgwILAkAgASIEIAJHDQBBhwEhEAzdAgsgAiAEayAAKAIAIgFqIRQgBCABa0EDaiEQAkADQCAELQAAIAFBiM+AgABqLQAARw3FASABQQNGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBhwEhEAzdAgsgAEEANgIAIBBBAWohAUEtIRAMwgELAkAgASIEIAJHDQBBiAEhEAzcAgsgAiAEayAAKAIAIgFqIRQgBCABa0EIaiEQAkADQCAELQAAIAFB0M+AgABqLQAARw3EASABQQhGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBiAEhEAzcAgsgAEEANgIAIBBBAWohAUEpIRAMwQELAkAgASIBIAJHDQBBiQEhEAzbAgtBASEQIAEtAABB3wBHDcABIAFBAWohAQyBAgsCQCABIgQgAkcNAEGKASEQDNoCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRADQCAELQAAIAFBjM+AgABqLQAARw3BASABQQFGDa8CIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQYoBIRAM2QILAkAgASIEIAJHDQBBiwEhEAzZAgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFBjs+AgABqLQAARw3BASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBiwEhEAzZAgsgAEEANgIAIBBBAWohAUECIRAMvgELAkAgASIEIAJHDQBBjAEhEAzYAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFB8M+AgABqLQAARw3AASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBjAEhEAzYAgsgAEEANgIAIBBBAWohAUEfIRAMvQELAkAgASIEIAJHDQBBjQEhEAzXAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFB8s+AgABqLQAARw2/ASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBjQEhEAzXAgsgAEEANgIAIBBBAWohAUEJIRAMvAELAkAgASIEIAJHDQBBjgEhEAzWAgsCQAJAIAQtAABBt39qDgcAvwG/Ab8BvwG/AQG/AQsgBEEBaiEBQfgAIRAMvQILIARBAWohAUH5ACEQDLwCCwJAIAEiBCACRw0AQY8BIRAM1QILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQZHPgIAAai0AAEcNvQEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQY8BIRAM1QILIABBADYCACAQQQFqIQFBGCEQDLoBCwJAIAEiBCACRw0AQZABIRAM1AILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQZfPgIAAai0AAEcNvAEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZABIRAM1AILIABBADYCACAQQQFqIQFBFyEQDLkBCwJAIAEiBCACRw0AQZEBIRAM0wILIAIgBGsgACgCACIBaiEUIAQgAWtBBmohEAJAA0AgBC0AACABQZrPgIAAai0AAEcNuwEgAUEGRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZEBIRAM0wILIABBADYCACAQQQFqIQFBFSEQDLgBCwJAIAEiBCACRw0AQZIBIRAM0gILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQaHPgIAAai0AAEcNugEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZIBIRAM0gILIABBADYCACAQQQFqIQFBHiEQDLcBCwJAIAEiBCACRw0AQZMBIRAM0QILIAQtAABBzABHDbgBIARBAWohAUEKIRAMtgELAkAgBCACRw0AQZQBIRAM0AILAkACQCAELQAAQb9/ag4PALkBuQG5AbkBuQG5AbkBuQG5AbkBuQG5AbkBAbkBCyAEQQFqIQFB/gAhEAy3AgsgBEEBaiEBQf8AIRAMtgILAkAgBCACRw0AQZUBIRAMzwILAkACQCAELQAAQb9/ag4DALgBAbgBCyAEQQFqIQFB/QAhEAy2AgsgBEEBaiEEQYABIRAMtQILAkAgBCACRw0AQZYBIRAMzgILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQafPgIAAai0AAEcNtgEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZYBIRAMzgILIABBADYCACAQQQFqIQFBCyEQDLMBCwJAIAQgAkcNAEGXASEQDM0CCwJAAkACQAJAIAQtAABBU2oOIwC4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBuAG4AbgBAbgBuAG4AbgBuAECuAG4AbgBA7gBCyAEQQFqIQFB+wAhEAy2AgsgBEEBaiEBQfwAIRAMtQILIARBAWohBEGBASEQDLQCCyAEQQFqIQRBggEhEAyzAgsCQCAEIAJHDQBBmAEhEAzMAgsgAiAEayAAKAIAIgFqIRQgBCABa0EEaiEQAkADQCAELQAAIAFBqc+AgABqLQAARw20ASABQQRGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBmAEhEAzMAgsgAEEANgIAIBBBAWohAUEZIRAMsQELAkAgBCACRw0AQZkBIRAMywILIAIgBGsgACgCACIBaiEUIAQgAWtBBWohEAJAA0AgBC0AACABQa7PgIAAai0AAEcNswEgAUEFRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZkBIRAMywILIABBADYCACAQQQFqIQFBBiEQDLABCwJAIAQgAkcNAEGaASEQDMoCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUG0z4CAAGotAABHDbIBIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGaASEQDMoCCyAAQQA2AgAgEEEBaiEBQRwhEAyvAQsCQCAEIAJHDQBBmwEhEAzJAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBts+AgABqLQAARw2xASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBmwEhEAzJAgsgAEEANgIAIBBBAWohAUEnIRAMrgELAkAgBCACRw0AQZwBIRAMyAILAkACQCAELQAAQax/ag4CAAGxAQsgBEEBaiEEQYYBIRAMrwILIARBAWohBEGHASEQDK4CCwJAIAQgAkcNAEGdASEQDMcCCyACIARrIAAoAgAiAWohFCAEIAFrQQFqIRACQANAIAQtAAAgAUG4z4CAAGotAABHDa8BIAFBAUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGdASEQDMcCCyAAQQA2AgAgEEEBaiEBQSYhEAysAQsCQCAEIAJHDQBBngEhEAzGAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFBus+AgABqLQAARw2uASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBngEhEAzGAgsgAEEANgIAIBBBAWohAUEDIRAMqwELAkAgBCACRw0AQZ8BIRAMxQILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQe3PgIAAai0AAEcNrQEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQZ8BIRAMxQILIABBADYCACAQQQFqIQFBDCEQDKoBCwJAIAQgAkcNAEGgASEQDMQCCyACIARrIAAoAgAiAWohFCAEIAFrQQNqIRACQANAIAQtAAAgAUG8z4CAAGotAABHDawBIAFBA0YNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGgASEQDMQCCyAAQQA2AgAgEEEBaiEBQQ0hEAypAQsCQCAEIAJHDQBBoQEhEAzDAgsCQAJAIAQtAABBun9qDgsArAGsAawBrAGsAawBrAGsAawBAawBCyAEQQFqIQRBiwEhEAyqAgsgBEEBaiEEQYwBIRAMqQILAkAgBCACRw0AQaIBIRAMwgILIAQtAABB0ABHDakBIARBAWohBAzpAQsCQCAEIAJHDQBBowEhEAzBAgsCQAJAIAQtAABBt39qDgcBqgGqAaoBqgGqAQCqAQsgBEEBaiEEQY4BIRAMqAILIARBAWohAUEiIRAMpgELAkAgBCACRw0AQaQBIRAMwAILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQcDPgIAAai0AAEcNqAEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQaQBIRAMwAILIABBADYCACAQQQFqIQFBHSEQDKUBCwJAIAQgAkcNAEGlASEQDL8CCwJAAkAgBC0AAEGuf2oOAwCoAQGoAQsgBEEBaiEEQZABIRAMpgILIARBAWohAUEEIRAMpAELAkAgBCACRw0AQaYBIRAMvgILAkACQAJAAkACQCAELQAAQb9/ag4VAKoBqgGqAaoBqgGqAaoBqgGqAaoBAaoBqgECqgGqAQOqAaoBBKoBCyAEQQFqIQRBiAEhEAyoAgsgBEEBaiEEQYkBIRAMpwILIARBAWohBEGKASEQDKYCCyAEQQFqIQRBjwEhEAylAgsgBEEBaiEEQZEBIRAMpAILAkAgBCACRw0AQacBIRAMvQILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQe3PgIAAai0AAEcNpQEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQacBIRAMvQILIABBADYCACAQQQFqIQFBESEQDKIBCwJAIAQgAkcNAEGoASEQDLwCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHCz4CAAGotAABHDaQBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGoASEQDLwCCyAAQQA2AgAgEEEBaiEBQSwhEAyhAQsCQCAEIAJHDQBBqQEhEAy7AgsgAiAEayAAKAIAIgFqIRQgBCABa0EEaiEQAkADQCAELQAAIAFBxc+AgABqLQAARw2jASABQQRGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBqQEhEAy7AgsgAEEANgIAIBBBAWohAUErIRAMoAELAkAgBCACRw0AQaoBIRAMugILIAIgBGsgACgCACIBaiEUIAQgAWtBAmohEAJAA0AgBC0AACABQcrPgIAAai0AAEcNogEgAUECRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQaoBIRAMugILIABBADYCACAQQQFqIQFBFCEQDJ8BCwJAIAQgAkcNAEGrASEQDLkCCwJAAkACQAJAIAQtAABBvn9qDg8AAQKkAaQBpAGkAaQBpAGkAaQBpAGkAaQBA6QBCyAEQQFqIQRBkwEhEAyiAgsgBEEBaiEEQZQBIRAMoQILIARBAWohBEGVASEQDKACCyAEQQFqIQRBlgEhEAyfAgsCQCAEIAJHDQBBrAEhEAy4AgsgBC0AAEHFAEcNnwEgBEEBaiEEDOABCwJAIAQgAkcNAEGtASEQDLcCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHNz4CAAGotAABHDZ8BIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEGtASEQDLcCCyAAQQA2AgAgEEEBaiEBQQ4hEAycAQsCQCAEIAJHDQBBrgEhEAy2AgsgBC0AAEHQAEcNnQEgBEEBaiEBQSUhEAybAQsCQCAEIAJHDQBBrwEhEAy1AgsgAiAEayAAKAIAIgFqIRQgBCABa0EIaiEQAkADQCAELQAAIAFB0M+AgABqLQAARw2dASABQQhGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBrwEhEAy1AgsgAEEANgIAIBBBAWohAUEqIRAMmgELAkAgBCACRw0AQbABIRAMtAILAkACQCAELQAAQat/ag4LAJ0BnQGdAZ0BnQGdAZ0BnQGdAQGdAQsgBEEBaiEEQZoBIRAMmwILIARBAWohBEGbASEQDJoCCwJAIAQgAkcNAEGxASEQDLMCCwJAAkAgBC0AAEG/f2oOFACcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAGcAZwBnAEBnAELIARBAWohBEGZASEQDJoCCyAEQQFqIQRBnAEhEAyZAgsCQCAEIAJHDQBBsgEhEAyyAgsgAiAEayAAKAIAIgFqIRQgBCABa0EDaiEQAkADQCAELQAAIAFB2c+AgABqLQAARw2aASABQQNGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBsgEhEAyyAgsgAEEANgIAIBBBAWohAUEhIRAMlwELAkAgBCACRw0AQbMBIRAMsQILIAIgBGsgACgCACIBaiEUIAQgAWtBBmohEAJAA0AgBC0AACABQd3PgIAAai0AAEcNmQEgAUEGRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbMBIRAMsQILIABBADYCACAQQQFqIQFBGiEQDJYBCwJAIAQgAkcNAEG0ASEQDLACCwJAAkACQCAELQAAQbt/ag4RAJoBmgGaAZoBmgGaAZoBmgGaAQGaAZoBmgGaAZoBApoBCyAEQQFqIQRBnQEhEAyYAgsgBEEBaiEEQZ4BIRAMlwILIARBAWohBEGfASEQDJYCCwJAIAQgAkcNAEG1ASEQDK8CCyACIARrIAAoAgAiAWohFCAEIAFrQQVqIRACQANAIAQtAAAgAUHkz4CAAGotAABHDZcBIAFBBUYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG1ASEQDK8CCyAAQQA2AgAgEEEBaiEBQSghEAyUAQsCQCAEIAJHDQBBtgEhEAyuAgsgAiAEayAAKAIAIgFqIRQgBCABa0ECaiEQAkADQCAELQAAIAFB6s+AgABqLQAARw2WASABQQJGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBtgEhEAyuAgsgAEEANgIAIBBBAWohAUEHIRAMkwELAkAgBCACRw0AQbcBIRAMrQILAkACQCAELQAAQbt/ag4OAJYBlgGWAZYBlgGWAZYBlgGWAZYBlgGWAQGWAQsgBEEBaiEEQaEBIRAMlAILIARBAWohBEGiASEQDJMCCwJAIAQgAkcNAEG4ASEQDKwCCyACIARrIAAoAgAiAWohFCAEIAFrQQJqIRACQANAIAQtAAAgAUHtz4CAAGotAABHDZQBIAFBAkYNASABQQFqIQEgBEEBaiIEIAJHDQALIAAgFDYCAEG4ASEQDKwCCyAAQQA2AgAgEEEBaiEBQRIhEAyRAQsCQCAEIAJHDQBBuQEhEAyrAgsgAiAEayAAKAIAIgFqIRQgBCABa0EBaiEQAkADQCAELQAAIAFB8M+AgABqLQAARw2TASABQQFGDQEgAUEBaiEBIARBAWoiBCACRw0ACyAAIBQ2AgBBuQEhEAyrAgsgAEEANgIAIBBBAWohAUEgIRAMkAELAkAgBCACRw0AQboBIRAMqgILIAIgBGsgACgCACIBaiEUIAQgAWtBAWohEAJAA0AgBC0AACABQfLPgIAAai0AAEcNkgEgAUEBRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQboBIRAMqgILIABBADYCACAQQQFqIQFBDyEQDI8BCwJAIAQgAkcNAEG7ASEQDKkCCwJAAkAgBC0AAEG3f2oOBwCSAZIBkgGSAZIBAZIBCyAEQQFqIQRBpQEhEAyQAgsgBEEBaiEEQaYBIRAMjwILAkAgBCACRw0AQbwBIRAMqAILIAIgBGsgACgCACIBaiEUIAQgAWtBB2ohEAJAA0AgBC0AACABQfTPgIAAai0AAEcNkAEgAUEHRg0BIAFBAWohASAEQQFqIgQgAkcNAAsgACAUNgIAQbwBIRAMqAILIABBADYCACAQQQFqIQFBGyEQDI0BCwJAIAQgAkcNAEG9ASEQDKcCCwJAAkACQCAELQAAQb5/ag4SAJEBkQGRAZEBkQGRAZEBkQGRAQGRAZEBkQGRAZEBkQECkQELIARBAWohBEGkASEQDI8CCyAEQQFqIQRBpwEhEAyOAgsgBEEBaiEEQagBIRAMjQILAkAgBCACRw0AQb4BIRAMpgILIAQtAABBzgBHDY0BIARBAWohBAzPAQsCQCAEIAJHDQBBvwEhEAylAgsCQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAELQAAQb9/ag4VAAECA5wBBAUGnAGcAZwBBwgJCgucAQwNDg+cAQsgBEEBaiEBQegAIRAMmgILIARBAWohAUHpACEQDJkCCyAEQQFqIQFB7gAhEAyYAgsgBEEBaiEBQfIAIRAMlwILIARBAWohAUHzACEQDJYCCyAEQQFqIQFB9gAhEAyVAgsgBEEBaiEBQfcAIRAMlAILIARBAWohAUH6ACEQDJMCCyAEQQFqIQRBgwEhEAySAgsgBEEBaiEEQYQBIRAMkQILIARBAWohBEGFASEQDJACCyAEQQFqIQRBkgEhEAyPAgsgBEEBaiEEQZgBIRAMjgILIARBAWohBEGgASEQDI0CCyAEQQFqIQRBowEhEAyMAgsgBEEBaiEEQaoBIRAMiwILAkAgBCACRg0AIABBkICAgAA2AgggACAENgIEQasBIRAMiwILQcABIRAMowILIAAgBSACEKqAgIAAIgENiwEgBSEBDFwLAkAgBiACRg0AIAZBAWohBQyNAQtBwgEhEAyhAgsDQAJAIBAtAABBdmoOBIwBAACPAQALIBBBAWoiECACRw0AC0HDASEQDKACCwJAIAcgAkYNACAAQZGAgIAANgIIIAAgBzYCBCAHIQFBASEQDIcCC0HEASEQDJ8CCwJAIAcgAkcNAEHFASEQDJ8CCwJAAkAgBy0AAEF2ag4EAc4BzgEAzgELIAdBAWohBgyNAQsgB0EBaiEFDIkBCwJAIAcgAkcNAEHGASEQDJ4CCwJAAkAgBy0AAEF2ag4XAY8BjwEBjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BAI8BCyAHQQFqIQcLQbABIRAMhAILAkAgCCACRw0AQcgBIRAMnQILIAgtAABBIEcNjQEgAEEAOwEyIAhBAWohAUGzASEQDIMCCyABIRcCQANAIBciByACRg0BIActAABBUGpB/wFxIhBBCk8NzAECQCAALwEyIhRBmTNLDQAgACAUQQpsIhQ7ATIgEEH//wNzIBRB/v8DcUkNACAHQQFqIRcgACAUIBBqIhA7ATIgEEH//wNxQegHSQ0BCwtBACEQIABBADYCHCAAQcGJgIAANgIQIABBDTYCDCAAIAdBAWo2AhQMnAILQccBIRAMmwILIAAgCCACEK6AgIAAIhBFDcoBIBBBFUcNjAEgAEHIATYCHCAAIAg2AhQgAEHJl4CAADYCECAAQRU2AgxBACEQDJoCCwJAIAkgAkcNAEHMASEQDJoCC0EAIRRBASEXQQEhFkEAIRACQAJAAkACQAJAAkACQAJAAkAgCS0AAEFQag4KlgGVAQABAgMEBQYIlwELQQIhEAwGC0EDIRAMBQtBBCEQDAQLQQUhEAwDC0EGIRAMAgtBByEQDAELQQghEAtBACEXQQAhFkEAIRQMjgELQQkhEEEBIRRBACEXQQAhFgyNAQsCQCAKIAJHDQBBzgEhEAyZAgsgCi0AAEEuRw2OASAKQQFqIQkMygELIAsgAkcNjgFB0AEhEAyXAgsCQCALIAJGDQAgAEGOgICAADYCCCAAIAs2AgRBtwEhEAz+AQtB0QEhEAyWAgsCQCAEIAJHDQBB0gEhEAyWAgsgAiAEayAAKAIAIhBqIRQgBCAQa0EEaiELA0AgBC0AACAQQfzPgIAAai0AAEcNjgEgEEEERg3pASAQQQFqIRAgBEEBaiIEIAJHDQALIAAgFDYCAEHSASEQDJUCCyAAIAwgAhCsgICAACIBDY0BIAwhAQy4AQsCQCAEIAJHDQBB1AEhEAyUAgsgAiAEayAAKAIAIhBqIRQgBCAQa0EBaiEMA0AgBC0AACAQQYHQgIAAai0AAEcNjwEgEEEBRg2OASAQQQFqIRAgBEEBaiIEIAJHDQALIAAgFDYCAEHUASEQDJMCCwJAIAQgAkcNAEHWASEQDJMCCyACIARrIAAoAgAiEGohFCAEIBBrQQJqIQsDQCAELQAAIBBBg9CAgABqLQAARw2OASAQQQJGDZABIBBBAWohECAEQQFqIgQgAkcNAAsgACAUNgIAQdYBIRAMkgILAkAgBCACRw0AQdcBIRAMkgILAkACQCAELQAAQbt/ag4QAI8BjwGPAY8BjwGPAY8BjwGPAY8BjwGPAY8BjwEBjwELIARBAWohBEG7ASEQDPkBCyAEQQFqIQRBvAEhEAz4AQsCQCAEIAJHDQBB2AEhEAyRAgsgBC0AAEHIAEcNjAEgBEEBaiEEDMQBCwJAIAQgAkYNACAAQZCAgIAANgIIIAAgBDYCBEG+ASEQDPcBC0HZASEQDI8CCwJAIAQgAkcNAEHaASEQDI8CCyAELQAAQcgARg3DASAAQQE6ACgMuQELIABBAjoALyAAIAQgAhCmgICAACIQDY0BQcIBIRAM9AELIAAtAChBf2oOArcBuQG4AQsDQAJAIAQtAABBdmoOBACOAY4BAI4BCyAEQQFqIgQgAkcNAAtB3QEhEAyLAgsgAEEAOgAvIAAtAC1BBHFFDYQCCyAAQQA6AC8gAEEBOgA0IAEhAQyMAQsgEEEVRg3aASAAQQA2AhwgACABNgIUIABBp46AgAA2AhAgAEESNgIMQQAhEAyIAgsCQCAAIBAgAhC0gICAACIEDQAgECEBDIECCwJAIARBFUcNACAAQQM2AhwgACAQNgIUIABBsJiAgAA2AhAgAEEVNgIMQQAhEAyIAgsgAEEANgIcIAAgEDYCFCAAQaeOgIAANgIQIABBEjYCDEEAIRAMhwILIBBBFUYN1gEgAEEANgIcIAAgATYCFCAAQdqNgIAANgIQIABBFDYCDEEAIRAMhgILIAAoAgQhFyAAQQA2AgQgECARp2oiFiEBIAAgFyAQIBYgFBsiEBC1gICAACIURQ2NASAAQQc2AhwgACAQNgIUIAAgFDYCDEEAIRAMhQILIAAgAC8BMEGAAXI7ATAgASEBC0EqIRAM6gELIBBBFUYN0QEgAEEANgIcIAAgATYCFCAAQYOMgIAANgIQIABBEzYCDEEAIRAMggILIBBBFUYNzwEgAEEANgIcIAAgATYCFCAAQZqPgIAANgIQIABBIjYCDEEAIRAMgQILIAAoAgQhECAAQQA2AgQCQCAAIBAgARC3gICAACIQDQAgAUEBaiEBDI0BCyAAQQw2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAMgAILIBBBFUYNzAEgAEEANgIcIAAgATYCFCAAQZqPgIAANgIQIABBIjYCDEEAIRAM/wELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC3gICAACIQDQAgAUEBaiEBDIwBCyAAQQ02AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM/gELIBBBFUYNyQEgAEEANgIcIAAgATYCFCAAQcaMgIAANgIQIABBIzYCDEEAIRAM/QELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC5gICAACIQDQAgAUEBaiEBDIsBCyAAQQ42AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM/AELIABBADYCHCAAIAE2AhQgAEHAlYCAADYCECAAQQI2AgxBACEQDPsBCyAQQRVGDcUBIABBADYCHCAAIAE2AhQgAEHGjICAADYCECAAQSM2AgxBACEQDPoBCyAAQRA2AhwgACABNgIUIAAgEDYCDEEAIRAM+QELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARC5gICAACIEDQAgAUEBaiEBDPEBCyAAQRE2AhwgACAENgIMIAAgAUEBajYCFEEAIRAM+AELIBBBFUYNwQEgAEEANgIcIAAgATYCFCAAQcaMgIAANgIQIABBIzYCDEEAIRAM9wELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC5gICAACIQDQAgAUEBaiEBDIgBCyAAQRM2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM9gELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARC5gICAACIEDQAgAUEBaiEBDO0BCyAAQRQ2AhwgACAENgIMIAAgAUEBajYCFEEAIRAM9QELIBBBFUYNvQEgAEEANgIcIAAgATYCFCAAQZqPgIAANgIQIABBIjYCDEEAIRAM9AELIAAoAgQhECAAQQA2AgQCQCAAIBAgARC3gICAACIQDQAgAUEBaiEBDIYBCyAAQRY2AhwgACAQNgIMIAAgAUEBajYCFEEAIRAM8wELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARC3gICAACIEDQAgAUEBaiEBDOkBCyAAQRc2AhwgACAENgIMIAAgAUEBajYCFEEAIRAM8gELIABBADYCHCAAIAE2AhQgAEHNk4CAADYCECAAQQw2AgxBACEQDPEBC0IBIRELIBBBAWohAQJAIAApAyAiEkL//////////w9WDQAgACASQgSGIBGENwMgIAEhAQyEAQsgAEEANgIcIAAgATYCFCAAQa2JgIAANgIQIABBDDYCDEEAIRAM7wELIABBADYCHCAAIBA2AhQgAEHNk4CAADYCECAAQQw2AgxBACEQDO4BCyAAKAIEIRcgAEEANgIEIBAgEadqIhYhASAAIBcgECAWIBQbIhAQtYCAgAAiFEUNcyAAQQU2AhwgACAQNgIUIAAgFDYCDEEAIRAM7QELIABBADYCHCAAIBA2AhQgAEGqnICAADYCECAAQQ82AgxBACEQDOwBCyAAIBAgAhC0gICAACIBDQEgECEBC0EOIRAM0QELAkAgAUEVRw0AIABBAjYCHCAAIBA2AhQgAEGwmICAADYCECAAQRU2AgxBACEQDOoBCyAAQQA2AhwgACAQNgIUIABBp46AgAA2AhAgAEESNgIMQQAhEAzpAQsgAUEBaiEQAkAgAC8BMCIBQYABcUUNAAJAIAAgECACELuAgIAAIgENACAQIQEMcAsgAUEVRw26ASAAQQU2AhwgACAQNgIUIABB+ZeAgAA2AhAgAEEVNgIMQQAhEAzpAQsCQCABQaAEcUGgBEcNACAALQAtQQJxDQAgAEEANgIcIAAgEDYCFCAAQZaTgIAANgIQIABBBDYCDEEAIRAM6QELIAAgECACEL2AgIAAGiAQIQECQAJAAkACQAJAIAAgECACELOAgIAADhYCAQAEBAQEBAQEBAQEBAQEBAQEBAQDBAsgAEEBOgAuCyAAIAAvATBBwAByOwEwIBAhAQtBJiEQDNEBCyAAQSM2AhwgACAQNgIUIABBpZaAgAA2AhAgAEEVNgIMQQAhEAzpAQsgAEEANgIcIAAgEDYCFCAAQdWLgIAANgIQIABBETYCDEEAIRAM6AELIAAtAC1BAXFFDQFBwwEhEAzOAQsCQCANIAJGDQADQAJAIA0tAABBIEYNACANIQEMxAELIA1BAWoiDSACRw0AC0ElIRAM5wELQSUhEAzmAQsgACgCBCEEIABBADYCBCAAIAQgDRCvgICAACIERQ2tASAAQSY2AhwgACAENgIMIAAgDUEBajYCFEEAIRAM5QELIBBBFUYNqwEgAEEANgIcIAAgATYCFCAAQf2NgIAANgIQIABBHTYCDEEAIRAM5AELIABBJzYCHCAAIAE2AhQgACAQNgIMQQAhEAzjAQsgECEBQQEhFAJAAkACQAJAAkACQAJAIAAtACxBfmoOBwYFBQMBAgAFCyAAIAAvATBBCHI7ATAMAwtBAiEUDAELQQQhFAsgAEEBOgAsIAAgAC8BMCAUcjsBMAsgECEBC0ErIRAMygELIABBADYCHCAAIBA2AhQgAEGrkoCAADYCECAAQQs2AgxBACEQDOIBCyAAQQA2AhwgACABNgIUIABB4Y+AgAA2AhAgAEEKNgIMQQAhEAzhAQsgAEEAOgAsIBAhAQy9AQsgECEBQQEhFAJAAkACQAJAAkAgAC0ALEF7ag4EAwECAAULIAAgAC8BMEEIcjsBMAwDC0ECIRQMAQtBBCEUCyAAQQE6ACwgACAALwEwIBRyOwEwCyAQIQELQSkhEAzFAQsgAEEANgIcIAAgATYCFCAAQfCUgIAANgIQIABBAzYCDEEAIRAM3QELAkAgDi0AAEENRw0AIAAoAgQhASAAQQA2AgQCQCAAIAEgDhCxgICAACIBDQAgDkEBaiEBDHULIABBLDYCHCAAIAE2AgwgACAOQQFqNgIUQQAhEAzdAQsgAC0ALUEBcUUNAUHEASEQDMMBCwJAIA4gAkcNAEEtIRAM3AELAkACQANAAkAgDi0AAEF2ag4EAgAAAwALIA5BAWoiDiACRw0AC0EtIRAM3QELIAAoAgQhASAAQQA2AgQCQCAAIAEgDhCxgICAACIBDQAgDiEBDHQLIABBLDYCHCAAIA42AhQgACABNgIMQQAhEAzcAQsgACgCBCEBIABBADYCBAJAIAAgASAOELGAgIAAIgENACAOQQFqIQEMcwsgAEEsNgIcIAAgATYCDCAAIA5BAWo2AhRBACEQDNsBCyAAKAIEIQQgAEEANgIEIAAgBCAOELGAgIAAIgQNoAEgDiEBDM4BCyAQQSxHDQEgAUEBaiEQQQEhAQJAAkACQAJAAkAgAC0ALEF7ag4EAwECBAALIBAhAQwEC0ECIQEMAQtBBCEBCyAAQQE6ACwgACAALwEwIAFyOwEwIBAhAQwBCyAAIAAvATBBCHI7ATAgECEBC0E5IRAMvwELIABBADoALCABIQELQTQhEAy9AQsgACAALwEwQSByOwEwIAEhAQwCCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQsYCAgAAiBA0AIAEhAQzHAQsgAEE3NgIcIAAgATYCFCAAIAQ2AgxBACEQDNQBCyAAQQg6ACwgASEBC0EwIRAMuQELAkAgAC0AKEEBRg0AIAEhAQwECyAALQAtQQhxRQ2TASABIQEMAwsgAC0AMEEgcQ2UAUHFASEQDLcBCwJAIA8gAkYNAAJAA0ACQCAPLQAAQVBqIgFB/wFxQQpJDQAgDyEBQTUhEAy6AQsgACkDICIRQpmz5syZs+bMGVYNASAAIBFCCn4iETcDICARIAGtQv8BgyISQn+FVg0BIAAgESASfDcDICAPQQFqIg8gAkcNAAtBOSEQDNEBCyAAKAIEIQIgAEEANgIEIAAgAiAPQQFqIgQQsYCAgAAiAg2VASAEIQEMwwELQTkhEAzPAQsCQCAALwEwIgFBCHFFDQAgAC0AKEEBRw0AIAAtAC1BCHFFDZABCyAAIAFB9/sDcUGABHI7ATAgDyEBC0E3IRAMtAELIAAgAC8BMEEQcjsBMAyrAQsgEEEVRg2LASAAQQA2AhwgACABNgIUIABB8I6AgAA2AhAgAEEcNgIMQQAhEAzLAQsgAEHDADYCHCAAIAE2AgwgACANQQFqNgIUQQAhEAzKAQsCQCABLQAAQTpHDQAgACgCBCEQIABBADYCBAJAIAAgECABEK+AgIAAIhANACABQQFqIQEMYwsgAEHDADYCHCAAIBA2AgwgACABQQFqNgIUQQAhEAzKAQsgAEEANgIcIAAgATYCFCAAQbGRgIAANgIQIABBCjYCDEEAIRAMyQELIABBADYCHCAAIAE2AhQgAEGgmYCAADYCECAAQR42AgxBACEQDMgBCyAAQQA2AgALIABBgBI7ASogACAXQQFqIgEgAhCogICAACIQDQEgASEBC0HHACEQDKwBCyAQQRVHDYMBIABB0QA2AhwgACABNgIUIABB45eAgAA2AhAgAEEVNgIMQQAhEAzEAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMXgsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAzDAQsgAEEANgIcIAAgFDYCFCAAQcGogIAANgIQIABBBzYCDCAAQQA2AgBBACEQDMIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxdCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDMEBC0EAIRAgAEEANgIcIAAgATYCFCAAQYCRgIAANgIQIABBCTYCDAzAAQsgEEEVRg19IABBADYCHCAAIAE2AhQgAEGUjYCAADYCECAAQSE2AgxBACEQDL8BC0EBIRZBACEXQQAhFEEBIRALIAAgEDoAKyABQQFqIQECQAJAIAAtAC1BEHENAAJAAkACQCAALQAqDgMBAAIECyAWRQ0DDAILIBQNAQwCCyAXRQ0BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQrYCAgAAiEA0AIAEhAQxcCyAAQdgANgIcIAAgATYCFCAAIBA2AgxBACEQDL4BCyAAKAIEIQQgAEEANgIEAkAgACAEIAEQrYCAgAAiBA0AIAEhAQytAQsgAEHZADYCHCAAIAE2AhQgACAENgIMQQAhEAy9AQsgACgCBCEEIABBADYCBAJAIAAgBCABEK2AgIAAIgQNACABIQEMqwELIABB2gA2AhwgACABNgIUIAAgBDYCDEEAIRAMvAELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCtgICAACIEDQAgASEBDKkBCyAAQdwANgIcIAAgATYCFCAAIAQ2AgxBACEQDLsBCwJAIAEtAABBUGoiEEH/AXFBCk8NACAAIBA6ACogAUEBaiEBQc8AIRAMogELIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCtgICAACIEDQAgASEBDKcBCyAAQd4ANgIcIAAgATYCFCAAIAQ2AgxBACEQDLoBCyAAQQA2AgAgF0EBaiEBAkAgAC0AKUEjTw0AIAEhAQxZCyAAQQA2AhwgACABNgIUIABB04mAgAA2AhAgAEEINgIMQQAhEAy5AQsgAEEANgIAC0EAIRAgAEEANgIcIAAgATYCFCAAQZCzgIAANgIQIABBCDYCDAy3AQsgAEEANgIAIBdBAWohAQJAIAAtAClBIUcNACABIQEMVgsgAEEANgIcIAAgATYCFCAAQZuKgIAANgIQIABBCDYCDEEAIRAMtgELIABBADYCACAXQQFqIQECQCAALQApIhBBXWpBC08NACABIQEMVQsCQCAQQQZLDQBBASAQdEHKAHFFDQAgASEBDFULQQAhECAAQQA2AhwgACABNgIUIABB94mAgAA2AhAgAEEINgIMDLUBCyAQQRVGDXEgAEEANgIcIAAgATYCFCAAQbmNgIAANgIQIABBGjYCDEEAIRAMtAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDFQLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMswELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDE0LIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMsgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDE0LIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMsQELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDFELIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMsAELIABBADYCHCAAIAE2AhQgAEHGioCAADYCECAAQQc2AgxBACEQDK8BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxJCyAAQdIANgIcIAAgATYCFCAAIBA2AgxBACEQDK4BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxJCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDK0BCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDKwBCyAAQQA2AhwgACABNgIUIABB3IiAgAA2AhAgAEEHNgIMQQAhEAyrAQsgEEE/Rw0BIAFBAWohAQtBBSEQDJABC0EAIRAgAEEANgIcIAAgATYCFCAAQf2SgIAANgIQIABBBzYCDAyoAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMQgsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAynAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMQgsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAymAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMRgsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAylAQsgACgCBCEBIABBADYCBAJAIAAgASAUEKeAgIAAIgENACAUIQEMPwsgAEHSADYCHCAAIBQ2AhQgACABNgIMQQAhEAykAQsgACgCBCEBIABBADYCBAJAIAAgASAUEKeAgIAAIgENACAUIQEMPwsgAEHTADYCHCAAIBQ2AhQgACABNgIMQQAhEAyjAQsgACgCBCEBIABBADYCBAJAIAAgASAUEKeAgIAAIgENACAUIQEMQwsgAEHlADYCHCAAIBQ2AhQgACABNgIMQQAhEAyiAQsgAEEANgIcIAAgFDYCFCAAQcOPgIAANgIQIABBBzYCDEEAIRAMoQELIABBADYCHCAAIAE2AhQgAEHDj4CAADYCECAAQQc2AgxBACEQDKABC0EAIRAgAEEANgIcIAAgFDYCFCAAQYycgIAANgIQIABBBzYCDAyfAQsgAEEANgIcIAAgFDYCFCAAQYycgIAANgIQIABBBzYCDEEAIRAMngELIABBADYCHCAAIBQ2AhQgAEH+kYCAADYCECAAQQc2AgxBACEQDJ0BCyAAQQA2AhwgACABNgIUIABBjpuAgAA2AhAgAEEGNgIMQQAhEAycAQsgEEEVRg1XIABBADYCHCAAIAE2AhQgAEHMjoCAADYCECAAQSA2AgxBACEQDJsBCyAAQQA2AgAgEEEBaiEBQSQhEAsgACAQOgApIAAoAgQhECAAQQA2AgQgACAQIAEQq4CAgAAiEA1UIAEhAQw+CyAAQQA2AgALQQAhECAAQQA2AhwgACAENgIUIABB8ZuAgAA2AhAgAEEGNgIMDJcBCyABQRVGDVAgAEEANgIcIAAgBTYCFCAAQfCMgIAANgIQIABBGzYCDEEAIRAMlgELIAAoAgQhBSAAQQA2AgQgACAFIBAQqYCAgAAiBQ0BIBBBAWohBQtBrQEhEAx7CyAAQcEBNgIcIAAgBTYCDCAAIBBBAWo2AhRBACEQDJMBCyAAKAIEIQYgAEEANgIEIAAgBiAQEKmAgIAAIgYNASAQQQFqIQYLQa4BIRAMeAsgAEHCATYCHCAAIAY2AgwgACAQQQFqNgIUQQAhEAyQAQsgAEEANgIcIAAgBzYCFCAAQZeLgIAANgIQIABBDTYCDEEAIRAMjwELIABBADYCHCAAIAg2AhQgAEHjkICAADYCECAAQQk2AgxBACEQDI4BCyAAQQA2AhwgACAINgIUIABBlI2AgAA2AhAgAEEhNgIMQQAhEAyNAQtBASEWQQAhF0EAIRRBASEQCyAAIBA6ACsgCUEBaiEIAkACQCAALQAtQRBxDQACQAJAAkAgAC0AKg4DAQACBAsgFkUNAwwCCyAUDQEMAgsgF0UNAQsgACgCBCEQIABBADYCBCAAIBAgCBCtgICAACIQRQ09IABByQE2AhwgACAINgIUIAAgEDYCDEEAIRAMjAELIAAoAgQhBCAAQQA2AgQgACAEIAgQrYCAgAAiBEUNdiAAQcoBNgIcIAAgCDYCFCAAIAQ2AgxBACEQDIsBCyAAKAIEIQQgAEEANgIEIAAgBCAJEK2AgIAAIgRFDXQgAEHLATYCHCAAIAk2AhQgACAENgIMQQAhEAyKAQsgACgCBCEEIABBADYCBCAAIAQgChCtgICAACIERQ1yIABBzQE2AhwgACAKNgIUIAAgBDYCDEEAIRAMiQELAkAgCy0AAEFQaiIQQf8BcUEKTw0AIAAgEDoAKiALQQFqIQpBtgEhEAxwCyAAKAIEIQQgAEEANgIEIAAgBCALEK2AgIAAIgRFDXAgAEHPATYCHCAAIAs2AhQgACAENgIMQQAhEAyIAQsgAEEANgIcIAAgBDYCFCAAQZCzgIAANgIQIABBCDYCDCAAQQA2AgBBACEQDIcBCyABQRVGDT8gAEEANgIcIAAgDDYCFCAAQcyOgIAANgIQIABBIDYCDEEAIRAMhgELIABBgQQ7ASggACgCBCEQIABCADcDACAAIBAgDEEBaiIMEKuAgIAAIhBFDTggAEHTATYCHCAAIAw2AhQgACAQNgIMQQAhEAyFAQsgAEEANgIAC0EAIRAgAEEANgIcIAAgBDYCFCAAQdibgIAANgIQIABBCDYCDAyDAQsgACgCBCEQIABCADcDACAAIBAgC0EBaiILEKuAgIAAIhANAUHGASEQDGkLIABBAjoAKAxVCyAAQdUBNgIcIAAgCzYCFCAAIBA2AgxBACEQDIABCyAQQRVGDTcgAEEANgIcIAAgBDYCFCAAQaSMgIAANgIQIABBEDYCDEEAIRAMfwsgAC0ANEEBRw00IAAgBCACELyAgIAAIhBFDTQgEEEVRw01IABB3AE2AhwgACAENgIUIABB1ZaAgAA2AhAgAEEVNgIMQQAhEAx+C0EAIRAgAEEANgIcIABBr4uAgAA2AhAgAEECNgIMIAAgFEEBajYCFAx9C0EAIRAMYwtBAiEQDGILQQ0hEAxhC0EPIRAMYAtBJSEQDF8LQRMhEAxeC0EVIRAMXQtBFiEQDFwLQRchEAxbC0EYIRAMWgtBGSEQDFkLQRohEAxYC0EbIRAMVwtBHCEQDFYLQR0hEAxVC0EfIRAMVAtBISEQDFMLQSMhEAxSC0HGACEQDFELQS4hEAxQC0EvIRAMTwtBOyEQDE4LQT0hEAxNC0HIACEQDEwLQckAIRAMSwtBywAhEAxKC0HMACEQDEkLQc4AIRAMSAtB0QAhEAxHC0HVACEQDEYLQdgAIRAMRQtB2QAhEAxEC0HbACEQDEMLQeQAIRAMQgtB5QAhEAxBC0HxACEQDEALQfQAIRAMPwtBjQEhEAw+C0GXASEQDD0LQakBIRAMPAtBrAEhEAw7C0HAASEQDDoLQbkBIRAMOQtBrwEhEAw4C0GxASEQDDcLQbIBIRAMNgtBtAEhEAw1C0G1ASEQDDQLQboBIRAMMwtBvQEhEAwyC0G/ASEQDDELQcEBIRAMMAsgAEEANgIcIAAgBDYCFCAAQemLgIAANgIQIABBHzYCDEEAIRAMSAsgAEHbATYCHCAAIAQ2AhQgAEH6loCAADYCECAAQRU2AgxBACEQDEcLIABB+AA2AhwgACAMNgIUIABBypiAgAA2AhAgAEEVNgIMQQAhEAxGCyAAQdEANgIcIAAgBTYCFCAAQbCXgIAANgIQIABBFTYCDEEAIRAMRQsgAEH5ADYCHCAAIAE2AhQgACAQNgIMQQAhEAxECyAAQfgANgIcIAAgATYCFCAAQcqYgIAANgIQIABBFTYCDEEAIRAMQwsgAEHkADYCHCAAIAE2AhQgAEHjl4CAADYCECAAQRU2AgxBACEQDEILIABB1wA2AhwgACABNgIUIABByZeAgAA2AhAgAEEVNgIMQQAhEAxBCyAAQQA2AhwgACABNgIUIABBuY2AgAA2AhAgAEEaNgIMQQAhEAxACyAAQcIANgIcIAAgATYCFCAAQeOYgIAANgIQIABBFTYCDEEAIRAMPwsgAEEANgIEIAAgDyAPELGAgIAAIgRFDQEgAEE6NgIcIAAgBDYCDCAAIA9BAWo2AhRBACEQDD4LIAAoAgQhBCAAQQA2AgQCQCAAIAQgARCxgICAACIERQ0AIABBOzYCHCAAIAQ2AgwgACABQQFqNgIUQQAhEAw+CyABQQFqIQEMLQsgD0EBaiEBDC0LIABBADYCHCAAIA82AhQgAEHkkoCAADYCECAAQQQ2AgxBACEQDDsLIABBNjYCHCAAIAQ2AhQgACACNgIMQQAhEAw6CyAAQS42AhwgACAONgIUIAAgBDYCDEEAIRAMOQsgAEHQADYCHCAAIAE2AhQgAEGRmICAADYCECAAQRU2AgxBACEQDDgLIA1BAWohAQwsCyAAQRU2AhwgACABNgIUIABBgpmAgAA2AhAgAEEVNgIMQQAhEAw2CyAAQRs2AhwgACABNgIUIABBkZeAgAA2AhAgAEEVNgIMQQAhEAw1CyAAQQ82AhwgACABNgIUIABBkZeAgAA2AhAgAEEVNgIMQQAhEAw0CyAAQQs2AhwgACABNgIUIABBkZeAgAA2AhAgAEEVNgIMQQAhEAwzCyAAQRo2AhwgACABNgIUIABBgpmAgAA2AhAgAEEVNgIMQQAhEAwyCyAAQQs2AhwgACABNgIUIABBgpmAgAA2AhAgAEEVNgIMQQAhEAwxCyAAQQo2AhwgACABNgIUIABB5JaAgAA2AhAgAEEVNgIMQQAhEAwwCyAAQR42AhwgACABNgIUIABB+ZeAgAA2AhAgAEEVNgIMQQAhEAwvCyAAQQA2AhwgACAQNgIUIABB2o2AgAA2AhAgAEEUNgIMQQAhEAwuCyAAQQQ2AhwgACABNgIUIABBsJiAgAA2AhAgAEEVNgIMQQAhEAwtCyAAQQA2AgAgC0EBaiELC0G4ASEQDBILIABBADYCACAQQQFqIQFB9QAhEAwRCyABIQECQCAALQApQQVHDQBB4wAhEAwRC0HiACEQDBALQQAhECAAQQA2AhwgAEHkkYCAADYCECAAQQc2AgwgACAUQQFqNgIUDCgLIABBADYCACAXQQFqIQFBwAAhEAwOC0EBIQELIAAgAToALCAAQQA2AgAgF0EBaiEBC0EoIRAMCwsgASEBC0E4IRAMCQsCQCABIg8gAkYNAANAAkAgDy0AAEGAvoCAAGotAAAiAUEBRg0AIAFBAkcNAyAPQQFqIQEMBAsgD0EBaiIPIAJHDQALQT4hEAwiC0E+IRAMIQsgAEEAOgAsIA8hAQwBC0ELIRAMBgtBOiEQDAULIAFBAWohAUEtIRAMBAsgACABOgAsIABBADYCACAWQQFqIQFBDCEQDAMLIABBADYCACAXQQFqIQFBCiEQDAILIABBADYCAAsgAEEAOgAsIA0hAUEJIRAMAAsLQQAhECAAQQA2AhwgACALNgIUIABBzZCAgAA2AhAgAEEJNgIMDBcLQQAhECAAQQA2AhwgACAKNgIUIABB6YqAgAA2AhAgAEEJNgIMDBYLQQAhECAAQQA2AhwgACAJNgIUIABBt5CAgAA2AhAgAEEJNgIMDBULQQAhECAAQQA2AhwgACAINgIUIABBnJGAgAA2AhAgAEEJNgIMDBQLQQAhECAAQQA2AhwgACABNgIUIABBzZCAgAA2AhAgAEEJNgIMDBMLQQAhECAAQQA2AhwgACABNgIUIABB6YqAgAA2AhAgAEEJNgIMDBILQQAhECAAQQA2AhwgACABNgIUIABBt5CAgAA2AhAgAEEJNgIMDBELQQAhECAAQQA2AhwgACABNgIUIABBnJGAgAA2AhAgAEEJNgIMDBALQQAhECAAQQA2AhwgACABNgIUIABBl5WAgAA2AhAgAEEPNgIMDA8LQQAhECAAQQA2AhwgACABNgIUIABBl5WAgAA2AhAgAEEPNgIMDA4LQQAhECAAQQA2AhwgACABNgIUIABBwJKAgAA2AhAgAEELNgIMDA0LQQAhECAAQQA2AhwgACABNgIUIABBlYmAgAA2AhAgAEELNgIMDAwLQQAhECAAQQA2AhwgACABNgIUIABB4Y+AgAA2AhAgAEEKNgIMDAsLQQAhECAAQQA2AhwgACABNgIUIABB+4+AgAA2AhAgAEEKNgIMDAoLQQAhECAAQQA2AhwgACABNgIUIABB8ZmAgAA2AhAgAEECNgIMDAkLQQAhECAAQQA2AhwgACABNgIUIABBxJSAgAA2AhAgAEECNgIMDAgLQQAhECAAQQA2AhwgACABNgIUIABB8pWAgAA2AhAgAEECNgIMDAcLIABBAjYCHCAAIAE2AhQgAEGcmoCAADYCECAAQRY2AgxBACEQDAYLQQEhEAwFC0HUACEQIAEiBCACRg0EIANBCGogACAEIAJB2MKAgABBChDFgICAACADKAIMIQQgAygCCA4DAQQCAAsQyoCAgAAACyAAQQA2AhwgAEG1moCAADYCECAAQRc2AgwgACAEQQFqNgIUQQAhEAwCCyAAQQA2AhwgACAENgIUIABBypqAgAA2AhAgAEEJNgIMQQAhEAwBCwJAIAEiBCACRw0AQSIhEAwBCyAAQYmAgIAANgIIIAAgBDYCBEEhIRALIANBEGokgICAgAAgEAuvAQECfyABKAIAIQYCQAJAIAIgA0YNACAEIAZqIQQgBiADaiACayEHIAIgBkF/cyAFaiIGaiEFA0ACQCACLQAAIAQtAABGDQBBAiEEDAMLAkAgBg0AQQAhBCAFIQIMAwsgBkF/aiEGIARBAWohBCACQQFqIgIgA0cNAAsgByEGIAMhAgsgAEEBNgIAIAEgBjYCACAAIAI2AgQPCyABQQA2AgAgACAENgIAIAAgAjYCBAsKACAAEMeAgIAAC/I2AQt/I4CAgIAAQRBrIgEkgICAgAACQEEAKAKg0ICAAA0AQQAQy4CAgABBgNSEgABrIgJB2QBJDQBBACEDAkBBACgC4NOAgAAiBA0AQQBCfzcC7NOAgABBAEKAgISAgIDAADcC5NOAgABBACABQQhqQXBxQdiq1aoFcyIENgLg04CAAEEAQQA2AvTTgIAAQQBBADYCxNOAgAALQQAgAjYCzNOAgABBAEGA1ISAADYCyNOAgABBAEGA1ISAADYCmNCAgABBACAENgKs0ICAAEEAQX82AqjQgIAAA0AgA0HE0ICAAGogA0G40ICAAGoiBDYCACAEIANBsNCAgABqIgU2AgAgA0G80ICAAGogBTYCACADQczQgIAAaiADQcDQgIAAaiIFNgIAIAUgBDYCACADQdTQgIAAaiADQcjQgIAAaiIENgIAIAQgBTYCACADQdDQgIAAaiAENgIAIANBIGoiA0GAAkcNAAtBgNSEgABBeEGA1ISAAGtBD3FBAEGA1ISAAEEIakEPcRsiA2oiBEEEaiACQUhqIgUgA2siA0EBcjYCAEEAQQAoAvDTgIAANgKk0ICAAEEAIAM2ApTQgIAAQQAgBDYCoNCAgABBgNSEgAAgBWpBODYCBAsCQAJAAkACQAJAAkACQAJAAkACQAJAAkAgAEHsAUsNAAJAQQAoAojQgIAAIgZBECAAQRNqQXBxIABBC0kbIgJBA3YiBHYiA0EDcUUNAAJAAkAgA0EBcSAEckEBcyIFQQN0IgRBsNCAgABqIgMgBEG40ICAAGooAgAiBCgCCCICRw0AQQAgBkF+IAV3cTYCiNCAgAAMAQsgAyACNgIIIAIgAzYCDAsgBEEIaiEDIAQgBUEDdCIFQQNyNgIEIAQgBWoiBCAEKAIEQQFyNgIEDAwLIAJBACgCkNCAgAAiB00NAQJAIANFDQACQAJAIAMgBHRBAiAEdCIDQQAgA2tycSIDQQAgA2txQX9qIgMgA0EMdkEQcSIDdiIEQQV2QQhxIgUgA3IgBCAFdiIDQQJ2QQRxIgRyIAMgBHYiA0EBdkECcSIEciADIAR2IgNBAXZBAXEiBHIgAyAEdmoiBEEDdCIDQbDQgIAAaiIFIANBuNCAgABqKAIAIgMoAggiAEcNAEEAIAZBfiAEd3EiBjYCiNCAgAAMAQsgBSAANgIIIAAgBTYCDAsgAyACQQNyNgIEIAMgBEEDdCIEaiAEIAJrIgU2AgAgAyACaiIAIAVBAXI2AgQCQCAHRQ0AIAdBeHFBsNCAgABqIQJBACgCnNCAgAAhBAJAAkAgBkEBIAdBA3Z0IghxDQBBACAGIAhyNgKI0ICAACACIQgMAQsgAigCCCEICyAIIAQ2AgwgAiAENgIIIAQgAjYCDCAEIAg2AggLIANBCGohA0EAIAA2ApzQgIAAQQAgBTYCkNCAgAAMDAtBACgCjNCAgAAiCUUNASAJQQAgCWtxQX9qIgMgA0EMdkEQcSIDdiIEQQV2QQhxIgUgA3IgBCAFdiIDQQJ2QQRxIgRyIAMgBHYiA0EBdkECcSIEciADIAR2IgNBAXZBAXEiBHIgAyAEdmpBAnRBuNKAgABqKAIAIgAoAgRBeHEgAmshBCAAIQUCQANAAkAgBSgCECIDDQAgBUEUaigCACIDRQ0CCyADKAIEQXhxIAJrIgUgBCAFIARJIgUbIQQgAyAAIAUbIQAgAyEFDAALCyAAKAIYIQoCQCAAKAIMIgggAEYNACAAKAIIIgNBACgCmNCAgABJGiAIIAM2AgggAyAINgIMDAsLAkAgAEEUaiIFKAIAIgMNACAAKAIQIgNFDQMgAEEQaiEFCwNAIAUhCyADIghBFGoiBSgCACIDDQAgCEEQaiEFIAgoAhAiAw0ACyALQQA2AgAMCgtBfyECIABBv39LDQAgAEETaiIDQXBxIQJBACgCjNCAgAAiB0UNAEEAIQsCQCACQYACSQ0AQR8hCyACQf///wdLDQAgA0EIdiIDIANBgP4/akEQdkEIcSIDdCIEIARBgOAfakEQdkEEcSIEdCIFIAVBgIAPakEQdkECcSIFdEEPdiADIARyIAVyayIDQQF0IAIgA0EVanZBAXFyQRxqIQsLQQAgAmshBAJAAkACQAJAIAtBAnRBuNKAgABqKAIAIgUNAEEAIQNBACEIDAELQQAhAyACQQBBGSALQQF2ayALQR9GG3QhAEEAIQgDQAJAIAUoAgRBeHEgAmsiBiAETw0AIAYhBCAFIQggBg0AQQAhBCAFIQggBSEDDAMLIAMgBUEUaigCACIGIAYgBSAAQR12QQRxakEQaigCACIFRhsgAyAGGyEDIABBAXQhACAFDQALCwJAIAMgCHINAEEAIQhBAiALdCIDQQAgA2tyIAdxIgNFDQMgA0EAIANrcUF/aiIDIANBDHZBEHEiA3YiBUEFdkEIcSIAIANyIAUgAHYiA0ECdkEEcSIFciADIAV2IgNBAXZBAnEiBXIgAyAFdiIDQQF2QQFxIgVyIAMgBXZqQQJ0QbjSgIAAaigCACEDCyADRQ0BCwNAIAMoAgRBeHEgAmsiBiAESSEAAkAgAygCECIFDQAgA0EUaigCACEFCyAGIAQgABshBCADIAggABshCCAFIQMgBQ0ACwsgCEUNACAEQQAoApDQgIAAIAJrTw0AIAgoAhghCwJAIAgoAgwiACAIRg0AIAgoAggiA0EAKAKY0ICAAEkaIAAgAzYCCCADIAA2AgwMCQsCQCAIQRRqIgUoAgAiAw0AIAgoAhAiA0UNAyAIQRBqIQULA0AgBSEGIAMiAEEUaiIFKAIAIgMNACAAQRBqIQUgACgCECIDDQALIAZBADYCAAwICwJAQQAoApDQgIAAIgMgAkkNAEEAKAKc0ICAACEEAkACQCADIAJrIgVBEEkNACAEIAJqIgAgBUEBcjYCBEEAIAU2ApDQgIAAQQAgADYCnNCAgAAgBCADaiAFNgIAIAQgAkEDcjYCBAwBCyAEIANBA3I2AgQgBCADaiIDIAMoAgRBAXI2AgRBAEEANgKc0ICAAEEAQQA2ApDQgIAACyAEQQhqIQMMCgsCQEEAKAKU0ICAACIAIAJNDQBBACgCoNCAgAAiAyACaiIEIAAgAmsiBUEBcjYCBEEAIAU2ApTQgIAAQQAgBDYCoNCAgAAgAyACQQNyNgIEIANBCGohAwwKCwJAAkBBACgC4NOAgABFDQBBACgC6NOAgAAhBAwBC0EAQn83AuzTgIAAQQBCgICEgICAwAA3AuTTgIAAQQAgAUEMakFwcUHYqtWqBXM2AuDTgIAAQQBBADYC9NOAgABBAEEANgLE04CAAEGAgAQhBAtBACEDAkAgBCACQccAaiIHaiIGQQAgBGsiC3EiCCACSw0AQQBBMDYC+NOAgAAMCgsCQEEAKALA04CAACIDRQ0AAkBBACgCuNOAgAAiBCAIaiIFIARNDQAgBSADTQ0BC0EAIQNBAEEwNgL404CAAAwKC0EALQDE04CAAEEEcQ0EAkACQAJAQQAoAqDQgIAAIgRFDQBByNOAgAAhAwNAAkAgAygCACIFIARLDQAgBSADKAIEaiAESw0DCyADKAIIIgMNAAsLQQAQy4CAgAAiAEF/Rg0FIAghBgJAQQAoAuTTgIAAIgNBf2oiBCAAcUUNACAIIABrIAQgAGpBACADa3FqIQYLIAYgAk0NBSAGQf7///8HSw0FAkBBACgCwNOAgAAiA0UNAEEAKAK404CAACIEIAZqIgUgBE0NBiAFIANLDQYLIAYQy4CAgAAiAyAARw0BDAcLIAYgAGsgC3EiBkH+////B0sNBCAGEMuAgIAAIgAgAygCACADKAIEakYNAyAAIQMLAkAgA0F/Rg0AIAJByABqIAZNDQACQCAHIAZrQQAoAujTgIAAIgRqQQAgBGtxIgRB/v///wdNDQAgAyEADAcLAkAgBBDLgICAAEF/Rg0AIAQgBmohBiADIQAMBwtBACAGaxDLgICAABoMBAsgAyEAIANBf0cNBQwDC0EAIQgMBwtBACEADAULIABBf0cNAgtBAEEAKALE04CAAEEEcjYCxNOAgAALIAhB/v///wdLDQEgCBDLgICAACEAQQAQy4CAgAAhAyAAQX9GDQEgA0F/Rg0BIAAgA08NASADIABrIgYgAkE4ak0NAQtBAEEAKAK404CAACAGaiIDNgK404CAAAJAIANBACgCvNOAgABNDQBBACADNgK804CAAAsCQAJAAkACQEEAKAKg0ICAACIERQ0AQcjTgIAAIQMDQCAAIAMoAgAiBSADKAIEIghqRg0CIAMoAggiAw0ADAMLCwJAAkBBACgCmNCAgAAiA0UNACAAIANPDQELQQAgADYCmNCAgAALQQAhA0EAIAY2AszTgIAAQQAgADYCyNOAgABBAEF/NgKo0ICAAEEAQQAoAuDTgIAANgKs0ICAAEEAQQA2AtTTgIAAA0AgA0HE0ICAAGogA0G40ICAAGoiBDYCACAEIANBsNCAgABqIgU2AgAgA0G80ICAAGogBTYCACADQczQgIAAaiADQcDQgIAAaiIFNgIAIAUgBDYCACADQdTQgIAAaiADQcjQgIAAaiIENgIAIAQgBTYCACADQdDQgIAAaiAENgIAIANBIGoiA0GAAkcNAAsgAEF4IABrQQ9xQQAgAEEIakEPcRsiA2oiBCAGQUhqIgUgA2siA0EBcjYCBEEAQQAoAvDTgIAANgKk0ICAAEEAIAM2ApTQgIAAQQAgBDYCoNCAgAAgACAFakE4NgIEDAILIAMtAAxBCHENACAEIAVJDQAgBCAATw0AIARBeCAEa0EPcUEAIARBCGpBD3EbIgVqIgBBACgClNCAgAAgBmoiCyAFayIFQQFyNgIEIAMgCCAGajYCBEEAQQAoAvDTgIAANgKk0ICAAEEAIAU2ApTQgIAAQQAgADYCoNCAgAAgBCALakE4NgIEDAELAkAgAEEAKAKY0ICAACIITw0AQQAgADYCmNCAgAAgACEICyAAIAZqIQVByNOAgAAhAwJAAkACQAJAAkACQAJAA0AgAygCACAFRg0BIAMoAggiAw0ADAILCyADLQAMQQhxRQ0BC0HI04CAACEDA0ACQCADKAIAIgUgBEsNACAFIAMoAgRqIgUgBEsNAwsgAygCCCEDDAALCyADIAA2AgAgAyADKAIEIAZqNgIEIABBeCAAa0EPcUEAIABBCGpBD3EbaiILIAJBA3I2AgQgBUF4IAVrQQ9xQQAgBUEIakEPcRtqIgYgCyACaiICayEDAkAgBiAERw0AQQAgAjYCoNCAgABBAEEAKAKU0ICAACADaiIDNgKU0ICAACACIANBAXI2AgQMAwsCQCAGQQAoApzQgIAARw0AQQAgAjYCnNCAgABBAEEAKAKQ0ICAACADaiIDNgKQ0ICAACACIANBAXI2AgQgAiADaiADNgIADAMLAkAgBigCBCIEQQNxQQFHDQAgBEF4cSEHAkACQCAEQf8BSw0AIAYoAggiBSAEQQN2IghBA3RBsNCAgABqIgBGGgJAIAYoAgwiBCAFRw0AQQBBACgCiNCAgABBfiAId3E2AojQgIAADAILIAQgAEYaIAQgBTYCCCAFIAQ2AgwMAQsgBigCGCEJAkACQCAGKAIMIgAgBkYNACAGKAIIIgQgCEkaIAAgBDYCCCAEIAA2AgwMAQsCQCAGQRRqIgQoAgAiBQ0AIAZBEGoiBCgCACIFDQBBACEADAELA0AgBCEIIAUiAEEUaiIEKAIAIgUNACAAQRBqIQQgACgCECIFDQALIAhBADYCAAsgCUUNAAJAAkAgBiAGKAIcIgVBAnRBuNKAgABqIgQoAgBHDQAgBCAANgIAIAANAUEAQQAoAozQgIAAQX4gBXdxNgKM0ICAAAwCCyAJQRBBFCAJKAIQIAZGG2ogADYCACAARQ0BCyAAIAk2AhgCQCAGKAIQIgRFDQAgACAENgIQIAQgADYCGAsgBigCFCIERQ0AIABBFGogBDYCACAEIAA2AhgLIAcgA2ohAyAGIAdqIgYoAgQhBAsgBiAEQX5xNgIEIAIgA2ogAzYCACACIANBAXI2AgQCQCADQf8BSw0AIANBeHFBsNCAgABqIQQCQAJAQQAoAojQgIAAIgVBASADQQN2dCIDcQ0AQQAgBSADcjYCiNCAgAAgBCEDDAELIAQoAgghAwsgAyACNgIMIAQgAjYCCCACIAQ2AgwgAiADNgIIDAMLQR8hBAJAIANB////B0sNACADQQh2IgQgBEGA/j9qQRB2QQhxIgR0IgUgBUGA4B9qQRB2QQRxIgV0IgAgAEGAgA9qQRB2QQJxIgB0QQ92IAQgBXIgAHJrIgRBAXQgAyAEQRVqdkEBcXJBHGohBAsgAiAENgIcIAJCADcCECAEQQJ0QbjSgIAAaiEFAkBBACgCjNCAgAAiAEEBIAR0IghxDQAgBSACNgIAQQAgACAIcjYCjNCAgAAgAiAFNgIYIAIgAjYCCCACIAI2AgwMAwsgA0EAQRkgBEEBdmsgBEEfRht0IQQgBSgCACEAA0AgACIFKAIEQXhxIANGDQIgBEEddiEAIARBAXQhBCAFIABBBHFqQRBqIggoAgAiAA0ACyAIIAI2AgAgAiAFNgIYIAIgAjYCDCACIAI2AggMAgsgAEF4IABrQQ9xQQAgAEEIakEPcRsiA2oiCyAGQUhqIgggA2siA0EBcjYCBCAAIAhqQTg2AgQgBCAFQTcgBWtBD3FBACAFQUlqQQ9xG2pBQWoiCCAIIARBEGpJGyIIQSM2AgRBAEEAKALw04CAADYCpNCAgABBACADNgKU0ICAAEEAIAs2AqDQgIAAIAhBEGpBACkC0NOAgAA3AgAgCEEAKQLI04CAADcCCEEAIAhBCGo2AtDTgIAAQQAgBjYCzNOAgABBACAANgLI04CAAEEAQQA2AtTTgIAAIAhBJGohAwNAIANBBzYCACADQQRqIgMgBUkNAAsgCCAERg0DIAggCCgCBEF+cTYCBCAIIAggBGsiADYCACAEIABBAXI2AgQCQCAAQf8BSw0AIABBeHFBsNCAgABqIQMCQAJAQQAoAojQgIAAIgVBASAAQQN2dCIAcQ0AQQAgBSAAcjYCiNCAgAAgAyEFDAELIAMoAgghBQsgBSAENgIMIAMgBDYCCCAEIAM2AgwgBCAFNgIIDAQLQR8hAwJAIABB////B0sNACAAQQh2IgMgA0GA/j9qQRB2QQhxIgN0IgUgBUGA4B9qQRB2QQRxIgV0IgggCEGAgA9qQRB2QQJxIgh0QQ92IAMgBXIgCHJrIgNBAXQgACADQRVqdkEBcXJBHGohAwsgBCADNgIcIARCADcCECADQQJ0QbjSgIAAaiEFAkBBACgCjNCAgAAiCEEBIAN0IgZxDQAgBSAENgIAQQAgCCAGcjYCjNCAgAAgBCAFNgIYIAQgBDYCCCAEIAQ2AgwMBAsgAEEAQRkgA0EBdmsgA0EfRht0IQMgBSgCACEIA0AgCCIFKAIEQXhxIABGDQMgA0EddiEIIANBAXQhAyAFIAhBBHFqQRBqIgYoAgAiCA0ACyAGIAQ2AgAgBCAFNgIYIAQgBDYCDCAEIAQ2AggMAwsgBSgCCCIDIAI2AgwgBSACNgIIIAJBADYCGCACIAU2AgwgAiADNgIICyALQQhqIQMMBQsgBSgCCCIDIAQ2AgwgBSAENgIIIARBADYCGCAEIAU2AgwgBCADNgIIC0EAKAKU0ICAACIDIAJNDQBBACgCoNCAgAAiBCACaiIFIAMgAmsiA0EBcjYCBEEAIAM2ApTQgIAAQQAgBTYCoNCAgAAgBCACQQNyNgIEIARBCGohAwwDC0EAIQNBAEEwNgL404CAAAwCCwJAIAtFDQACQAJAIAggCCgCHCIFQQJ0QbjSgIAAaiIDKAIARw0AIAMgADYCACAADQFBACAHQX4gBXdxIgc2AozQgIAADAILIAtBEEEUIAsoAhAgCEYbaiAANgIAIABFDQELIAAgCzYCGAJAIAgoAhAiA0UNACAAIAM2AhAgAyAANgIYCyAIQRRqKAIAIgNFDQAgAEEUaiADNgIAIAMgADYCGAsCQAJAIARBD0sNACAIIAQgAmoiA0EDcjYCBCAIIANqIgMgAygCBEEBcjYCBAwBCyAIIAJqIgAgBEEBcjYCBCAIIAJBA3I2AgQgACAEaiAENgIAAkAgBEH/AUsNACAEQXhxQbDQgIAAaiEDAkACQEEAKAKI0ICAACIFQQEgBEEDdnQiBHENAEEAIAUgBHI2AojQgIAAIAMhBAwBCyADKAIIIQQLIAQgADYCDCADIAA2AgggACADNgIMIAAgBDYCCAwBC0EfIQMCQCAEQf///wdLDQAgBEEIdiIDIANBgP4/akEQdkEIcSIDdCIFIAVBgOAfakEQdkEEcSIFdCICIAJBgIAPakEQdkECcSICdEEPdiADIAVyIAJyayIDQQF0IAQgA0EVanZBAXFyQRxqIQMLIAAgAzYCHCAAQgA3AhAgA0ECdEG40oCAAGohBQJAIAdBASADdCICcQ0AIAUgADYCAEEAIAcgAnI2AozQgIAAIAAgBTYCGCAAIAA2AgggACAANgIMDAELIARBAEEZIANBAXZrIANBH0YbdCEDIAUoAgAhAgJAA0AgAiIFKAIEQXhxIARGDQEgA0EddiECIANBAXQhAyAFIAJBBHFqQRBqIgYoAgAiAg0ACyAGIAA2AgAgACAFNgIYIAAgADYCDCAAIAA2AggMAQsgBSgCCCIDIAA2AgwgBSAANgIIIABBADYCGCAAIAU2AgwgACADNgIICyAIQQhqIQMMAQsCQCAKRQ0AAkACQCAAIAAoAhwiBUECdEG40oCAAGoiAygCAEcNACADIAg2AgAgCA0BQQAgCUF+IAV3cTYCjNCAgAAMAgsgCkEQQRQgCigCECAARhtqIAg2AgAgCEUNAQsgCCAKNgIYAkAgACgCECIDRQ0AIAggAzYCECADIAg2AhgLIABBFGooAgAiA0UNACAIQRRqIAM2AgAgAyAINgIYCwJAAkAgBEEPSw0AIAAgBCACaiIDQQNyNgIEIAAgA2oiAyADKAIEQQFyNgIEDAELIAAgAmoiBSAEQQFyNgIEIAAgAkEDcjYCBCAFIARqIAQ2AgACQCAHRQ0AIAdBeHFBsNCAgABqIQJBACgCnNCAgAAhAwJAAkBBASAHQQN2dCIIIAZxDQBBACAIIAZyNgKI0ICAACACIQgMAQsgAigCCCEICyAIIAM2AgwgAiADNgIIIAMgAjYCDCADIAg2AggLQQAgBTYCnNCAgABBACAENgKQ0ICAAAsgAEEIaiEDCyABQRBqJICAgIAAIAMLCgAgABDJgICAAAviDQEHfwJAIABFDQAgAEF4aiIBIABBfGooAgAiAkF4cSIAaiEDAkAgAkEBcQ0AIAJBA3FFDQEgASABKAIAIgJrIgFBACgCmNCAgAAiBEkNASACIABqIQACQCABQQAoApzQgIAARg0AAkAgAkH/AUsNACABKAIIIgQgAkEDdiIFQQN0QbDQgIAAaiIGRhoCQCABKAIMIgIgBEcNAEEAQQAoAojQgIAAQX4gBXdxNgKI0ICAAAwDCyACIAZGGiACIAQ2AgggBCACNgIMDAILIAEoAhghBwJAAkAgASgCDCIGIAFGDQAgASgCCCICIARJGiAGIAI2AgggAiAGNgIMDAELAkAgAUEUaiICKAIAIgQNACABQRBqIgIoAgAiBA0AQQAhBgwBCwNAIAIhBSAEIgZBFGoiAigCACIEDQAgBkEQaiECIAYoAhAiBA0ACyAFQQA2AgALIAdFDQECQAJAIAEgASgCHCIEQQJ0QbjSgIAAaiICKAIARw0AIAIgBjYCACAGDQFBAEEAKAKM0ICAAEF+IAR3cTYCjNCAgAAMAwsgB0EQQRQgBygCECABRhtqIAY2AgAgBkUNAgsgBiAHNgIYAkAgASgCECICRQ0AIAYgAjYCECACIAY2AhgLIAEoAhQiAkUNASAGQRRqIAI2AgAgAiAGNgIYDAELIAMoAgQiAkEDcUEDRw0AIAMgAkF+cTYCBEEAIAA2ApDQgIAAIAEgAGogADYCACABIABBAXI2AgQPCyABIANPDQAgAygCBCICQQFxRQ0AAkACQCACQQJxDQACQCADQQAoAqDQgIAARw0AQQAgATYCoNCAgABBAEEAKAKU0ICAACAAaiIANgKU0ICAACABIABBAXI2AgQgAUEAKAKc0ICAAEcNA0EAQQA2ApDQgIAAQQBBADYCnNCAgAAPCwJAIANBACgCnNCAgABHDQBBACABNgKc0ICAAEEAQQAoApDQgIAAIABqIgA2ApDQgIAAIAEgAEEBcjYCBCABIABqIAA2AgAPCyACQXhxIABqIQACQAJAIAJB/wFLDQAgAygCCCIEIAJBA3YiBUEDdEGw0ICAAGoiBkYaAkAgAygCDCICIARHDQBBAEEAKAKI0ICAAEF+IAV3cTYCiNCAgAAMAgsgAiAGRhogAiAENgIIIAQgAjYCDAwBCyADKAIYIQcCQAJAIAMoAgwiBiADRg0AIAMoAggiAkEAKAKY0ICAAEkaIAYgAjYCCCACIAY2AgwMAQsCQCADQRRqIgIoAgAiBA0AIANBEGoiAigCACIEDQBBACEGDAELA0AgAiEFIAQiBkEUaiICKAIAIgQNACAGQRBqIQIgBigCECIEDQALIAVBADYCAAsgB0UNAAJAAkAgAyADKAIcIgRBAnRBuNKAgABqIgIoAgBHDQAgAiAGNgIAIAYNAUEAQQAoAozQgIAAQX4gBHdxNgKM0ICAAAwCCyAHQRBBFCAHKAIQIANGG2ogBjYCACAGRQ0BCyAGIAc2AhgCQCADKAIQIgJFDQAgBiACNgIQIAIgBjYCGAsgAygCFCICRQ0AIAZBFGogAjYCACACIAY2AhgLIAEgAGogADYCACABIABBAXI2AgQgAUEAKAKc0ICAAEcNAUEAIAA2ApDQgIAADwsgAyACQX5xNgIEIAEgAGogADYCACABIABBAXI2AgQLAkAgAEH/AUsNACAAQXhxQbDQgIAAaiECAkACQEEAKAKI0ICAACIEQQEgAEEDdnQiAHENAEEAIAQgAHI2AojQgIAAIAIhAAwBCyACKAIIIQALIAAgATYCDCACIAE2AgggASACNgIMIAEgADYCCA8LQR8hAgJAIABB////B0sNACAAQQh2IgIgAkGA/j9qQRB2QQhxIgJ0IgQgBEGA4B9qQRB2QQRxIgR0IgYgBkGAgA9qQRB2QQJxIgZ0QQ92IAIgBHIgBnJrIgJBAXQgACACQRVqdkEBcXJBHGohAgsgASACNgIcIAFCADcCECACQQJ0QbjSgIAAaiEEAkACQEEAKAKM0ICAACIGQQEgAnQiA3ENACAEIAE2AgBBACAGIANyNgKM0ICAACABIAQ2AhggASABNgIIIAEgATYCDAwBCyAAQQBBGSACQQF2ayACQR9GG3QhAiAEKAIAIQYCQANAIAYiBCgCBEF4cSAARg0BIAJBHXYhBiACQQF0IQIgBCAGQQRxakEQaiIDKAIAIgYNAAsgAyABNgIAIAEgBDYCGCABIAE2AgwgASABNgIIDAELIAQoAggiACABNgIMIAQgATYCCCABQQA2AhggASAENgIMIAEgADYCCAtBAEEAKAKo0ICAAEF/aiIBQX8gARs2AqjQgIAACwsEAAAAC04AAkAgAA0APwBBEHQPCwJAIABB//8DcQ0AIABBf0wNAAJAIABBEHZAACIAQX9HDQBBAEEwNgL404CAAEF/DwsgAEEQdA8LEMqAgIAAAAvyAgIDfwF+AkAgAkUNACAAIAE6AAAgAiAAaiIDQX9qIAE6AAAgAkEDSQ0AIAAgAToAAiAAIAE6AAEgA0F9aiABOgAAIANBfmogAToAACACQQdJDQAgACABOgADIANBfGogAToAACACQQlJDQAgAEEAIABrQQNxIgRqIgMgAUH/AXFBgYKECGwiATYCACADIAIgBGtBfHEiBGoiAkF8aiABNgIAIARBCUkNACADIAE2AgggAyABNgIEIAJBeGogATYCACACQXRqIAE2AgAgBEEZSQ0AIAMgATYCGCADIAE2AhQgAyABNgIQIAMgATYCDCACQXBqIAE2AgAgAkFsaiABNgIAIAJBaGogATYCACACQWRqIAE2AgAgBCADQQRxQRhyIgVrIgJBIEkNACABrUKBgICAEH4hBiADIAVqIQEDQCABIAY3AxggASAGNwMQIAEgBjcDCCABIAY3AwAgAUEgaiEBIAJBYGoiAkEfSw0ACwsgAAsLjkgBAEGACAuGSAEAAAACAAAAAwAAAAAAAAAAAAAABAAAAAUAAAAAAAAAAAAAAAYAAAAHAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASW52YWxpZCBjaGFyIGluIHVybCBxdWVyeQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2JvZHkAQ29udGVudC1MZW5ndGggb3ZlcmZsb3cAQ2h1bmsgc2l6ZSBvdmVyZmxvdwBSZXNwb25zZSBvdmVyZmxvdwBJbnZhbGlkIG1ldGhvZCBmb3IgSFRUUC94LnggcmVxdWVzdABJbnZhbGlkIG1ldGhvZCBmb3IgUlRTUC94LnggcmVxdWVzdABFeHBlY3RlZCBTT1VSQ0UgbWV0aG9kIGZvciBJQ0UveC54IHJlcXVlc3QASW52YWxpZCBjaGFyIGluIHVybCBmcmFnbWVudCBzdGFydABFeHBlY3RlZCBkb3QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9zdGF0dXMASW52YWxpZCByZXNwb25zZSBzdGF0dXMASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucwBVc2VyIGNhbGxiYWNrIGVycm9yAGBvbl9yZXNldGAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2hlYWRlcmAgY2FsbGJhY2sgZXJyb3IAYG9uX21lc3NhZ2VfYmVnaW5gIGNhbGxiYWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==' + + +/***/ }), + +/***/ 50172: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.enumToMap = void 0; +function enumToMap(obj) { + const res = {}; + Object.keys(obj).forEach((key) => { + const value = obj[key]; + if (typeof value === 'number') { + res[key] = value; + } + }); + return res; +} +exports.enumToMap = enumToMap; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 47501: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kClients } = __nccwpck_require__(36443) +const Agent = __nccwpck_require__(59965) +const { + kAgent, + kMockAgentSet, + kMockAgentGet, + kDispatches, + kIsMockActive, + kNetConnect, + kGetNetConnect, + kOptions, + kFactory +} = __nccwpck_require__(91117) +const MockClient = __nccwpck_require__(47365) +const MockPool = __nccwpck_require__(94004) +const { matchValue, buildMockOptions } = __nccwpck_require__(53397) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(68707) +const Dispatcher = __nccwpck_require__(28611) +const Pluralizer = __nccwpck_require__(91529) +const PendingInterceptorsFormatter = __nccwpck_require__(56142) + +class FakeWeakRef { + constructor (value) { + this.value = value + } + + deref () { + return this.value + } +} + +class MockAgent extends Dispatcher { + constructor (opts) { + super(opts) + + this[kNetConnect] = true + this[kIsMockActive] = true + + // Instantiate Agent and encapsulate + if ((opts && opts.agent && typeof opts.agent.dispatch !== 'function')) { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + const agent = opts && opts.agent ? opts.agent : new Agent(opts) + this[kAgent] = agent + + this[kClients] = agent[kClients] + this[kOptions] = buildMockOptions(opts) + } + + get (origin) { + let dispatcher = this[kMockAgentGet](origin) + + if (!dispatcher) { + dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + } + return dispatcher + } + + dispatch (opts, handler) { + // Call MockAgent.get to perform additional setup before dispatching as normal + this.get(opts.origin) + return this[kAgent].dispatch(opts, handler) + } + + async close () { + await this[kAgent].close() + this[kClients].clear() + } + + deactivate () { + this[kIsMockActive] = false + } + + activate () { + this[kIsMockActive] = true + } + + enableNetConnect (matcher) { + if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher) + } else { + this[kNetConnect] = [matcher] + } + } else if (typeof matcher === 'undefined') { + this[kNetConnect] = true + } else { + throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') + } + } + + disableNetConnect () { + this[kNetConnect] = false + } + + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive () { + return this[kIsMockActive] + } + + [kMockAgentSet] (origin, dispatcher) { + this[kClients].set(origin, new FakeWeakRef(dispatcher)) + } + + [kFactory] (origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]) + return this[kOptions] && this[kOptions].connections === 1 + ? new MockClient(origin, mockOptions) + : new MockPool(origin, mockOptions) + } + + [kMockAgentGet] (origin) { + // First check if we can immediately find it + const ref = this[kClients].get(origin) + if (ref) { + return ref.deref() + } + + // If the origin is not a string create a dummy parent pool and return to user + if (typeof origin !== 'string') { + const dispatcher = this[kFactory]('http://localhost:9999') + this[kMockAgentSet](origin, dispatcher) + return dispatcher + } + + // If we match, create a pool and assign the same dispatches + for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) { + const nonExplicitDispatcher = nonExplicitRef.deref() + if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { + const dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches] + return dispatcher + } + } + } + + [kGetNetConnect] () { + return this[kNetConnect] + } + + pendingInterceptors () { + const mockAgentClients = this[kClients] + + return Array.from(mockAgentClients.entries()) + .flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin }))) + .filter(({ pending }) => pending) + } + + assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors() + + if (pending.length === 0) { + return + } + + const pluralizer = new Pluralizer('interceptor', 'interceptors').pluralize(pending.length) + + throw new UndiciError(` +${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: + +${pendingInterceptorsFormatter.format(pending)} +`.trim()) + } +} + +module.exports = MockAgent + + +/***/ }), + +/***/ 47365: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { promisify } = __nccwpck_require__(39023) +const Client = __nccwpck_require__(86197) +const { buildMockDispatch } = __nccwpck_require__(53397) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(91117) +const { MockInterceptor } = __nccwpck_require__(31511) +const Symbols = __nccwpck_require__(36443) +const { InvalidArgumentError } = __nccwpck_require__(68707) + +/** + * MockClient provides an API that extends the Client to influence the mockDispatches. + */ +class MockClient extends Client { + constructor (origin, opts) { + super(origin, opts) + + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } + + get [Symbols.kConnected] () { + return this[kConnected] + } + + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } + + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + } +} + +module.exports = MockClient + + +/***/ }), + +/***/ 52429: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { UndiciError } = __nccwpck_require__(68707) + +class MockNotMatchedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, MockNotMatchedError) + this.name = 'MockNotMatchedError' + this.message = message || 'The request does not match any registered mock dispatches' + this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED' + } +} + +module.exports = { + MockNotMatchedError +} + + +/***/ }), + +/***/ 31511: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(53397) +const { + kDispatches, + kDispatchKey, + kDefaultHeaders, + kDefaultTrailers, + kContentLength, + kMockDispatch +} = __nccwpck_require__(91117) +const { InvalidArgumentError } = __nccwpck_require__(68707) +const { buildURL } = __nccwpck_require__(3440) + +/** + * Defines the scope API for an interceptor reply + */ +class MockScope { + constructor (mockDispatch) { + this[kMockDispatch] = mockDispatch + } + + /** + * Delay a reply by a set amount in ms. + */ + delay (waitInMs) { + if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) { + throw new InvalidArgumentError('waitInMs must be a valid integer > 0') + } + + this[kMockDispatch].delay = waitInMs + return this + } + + /** + * For a defined reply, never mark as consumed. + */ + persist () { + this[kMockDispatch].persist = true + return this + } + + /** + * Allow one to define a reply for a set amount of matching requests. + */ + times (repeatTimes) { + if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { + throw new InvalidArgumentError('repeatTimes must be a valid integer > 0') + } + + this[kMockDispatch].times = repeatTimes + return this + } +} + +/** + * Defines an interceptor for a Mock + */ +class MockInterceptor { + constructor (opts, mockDispatches) { + if (typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object') + } + if (typeof opts.path === 'undefined') { + throw new InvalidArgumentError('opts.path must be defined') + } + if (typeof opts.method === 'undefined') { + opts.method = 'GET' + } + // See https://github.com/nodejs/undici/issues/1245 + // As per RFC 3986, clients are not supposed to send URI + // fragments to servers when they retrieve a document, + if (typeof opts.path === 'string') { + if (opts.query) { + opts.path = buildURL(opts.path, opts.query) + } else { + // Matches https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L1811 + const parsedURL = new URL(opts.path, 'data://') + opts.path = parsedURL.pathname + parsedURL.search + } + } + if (typeof opts.method === 'string') { + opts.method = opts.method.toUpperCase() + } + + this[kDispatchKey] = buildKey(opts) + this[kDispatches] = mockDispatches + this[kDefaultHeaders] = {} + this[kDefaultTrailers] = {} + this[kContentLength] = false + } + + createMockScopeDispatchData (statusCode, data, responseOptions = {}) { + const responseData = getResponseData(data) + const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {} + const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers } + const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers } + + return { statusCode, data, headers, trailers } + } + + validateReplyParameters (statusCode, data, responseOptions) { + if (typeof statusCode === 'undefined') { + throw new InvalidArgumentError('statusCode must be defined') + } + if (typeof data === 'undefined') { + throw new InvalidArgumentError('data must be defined') + } + if (typeof responseOptions !== 'object') { + throw new InvalidArgumentError('responseOptions must be an object') + } + } + + /** + * Mock an undici request with a defined reply. + */ + reply (replyData) { + // Values of reply aren't available right now as they + // can only be available when the reply callback is invoked. + if (typeof replyData === 'function') { + // We'll first wrap the provided callback in another function, + // this function will properly resolve the data from the callback + // when invoked. + const wrappedDefaultsCallback = (opts) => { + // Our reply options callback contains the parameter for statusCode, data and options. + const resolvedData = replyData(opts) + + // Check if it is in the right format + if (typeof resolvedData !== 'object') { + throw new InvalidArgumentError('reply options callback must return an object') + } + + const { statusCode, data = '', responseOptions = {} } = resolvedData + this.validateReplyParameters(statusCode, data, responseOptions) + // Since the values can be obtained immediately we return them + // from this higher order function that will be resolved later. + return { + ...this.createMockScopeDispatchData(statusCode, data, responseOptions) + } + } + + // Add usual dispatch data, but this time set the data parameter to function that will eventually provide data. + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback) + return new MockScope(newMockDispatch) + } + + // We can have either one or three parameters, if we get here, + // we should have 1-3 parameters. So we spread the arguments of + // this function to obtain the parameters, since replyData will always + // just be the statusCode. + const [statusCode, data = '', responseOptions = {}] = [...arguments] + this.validateReplyParameters(statusCode, data, responseOptions) + + // Send in-already provided data like usual + const dispatchData = this.createMockScopeDispatchData(statusCode, data, responseOptions) + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData) + return new MockScope(newMockDispatch) + } + + /** + * Mock an undici request with a defined error. + */ + replyWithError (error) { + if (typeof error === 'undefined') { + throw new InvalidArgumentError('error must be defined') + } + + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }) + return new MockScope(newMockDispatch) + } + + /** + * Set default reply headers on the interceptor for subsequent replies + */ + defaultReplyHeaders (headers) { + if (typeof headers === 'undefined') { + throw new InvalidArgumentError('headers must be defined') + } + + this[kDefaultHeaders] = headers + return this + } + + /** + * Set default reply trailers on the interceptor for subsequent replies + */ + defaultReplyTrailers (trailers) { + if (typeof trailers === 'undefined') { + throw new InvalidArgumentError('trailers must be defined') + } + + this[kDefaultTrailers] = trailers + return this + } + + /** + * Set reply content length header for replies on the interceptor + */ + replyContentLength () { + this[kContentLength] = true + return this + } +} + +module.exports.MockInterceptor = MockInterceptor +module.exports.MockScope = MockScope + + +/***/ }), + +/***/ 94004: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { promisify } = __nccwpck_require__(39023) +const Pool = __nccwpck_require__(35076) +const { buildMockDispatch } = __nccwpck_require__(53397) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(91117) +const { MockInterceptor } = __nccwpck_require__(31511) +const Symbols = __nccwpck_require__(36443) +const { InvalidArgumentError } = __nccwpck_require__(68707) + +/** + * MockPool provides an API that extends the Pool to influence the mockDispatches. + */ +class MockPool extends Pool { + constructor (origin, opts) { + super(origin, opts) + + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } + + get [Symbols.kConnected] () { + return this[kConnected] + } + + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } + + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + } +} + +module.exports = MockPool + + +/***/ }), + +/***/ 91117: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kAgent: Symbol('agent'), + kOptions: Symbol('options'), + kFactory: Symbol('factory'), + kDispatches: Symbol('dispatches'), + kDispatchKey: Symbol('dispatch key'), + kDefaultHeaders: Symbol('default headers'), + kDefaultTrailers: Symbol('default trailers'), + kContentLength: Symbol('content length'), + kMockAgent: Symbol('mock agent'), + kMockAgentSet: Symbol('mock agent set'), + kMockAgentGet: Symbol('mock agent get'), + kMockDispatch: Symbol('mock dispatch'), + kClose: Symbol('close'), + kOriginalClose: Symbol('original agent close'), + kOrigin: Symbol('origin'), + kIsMockActive: Symbol('is mock active'), + kNetConnect: Symbol('net connect'), + kGetNetConnect: Symbol('get net connect'), + kConnected: Symbol('connected') +} + + +/***/ }), + +/***/ 53397: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { MockNotMatchedError } = __nccwpck_require__(52429) +const { + kDispatches, + kMockAgent, + kOriginalDispatch, + kOrigin, + kGetNetConnect +} = __nccwpck_require__(91117) +const { buildURL, nop } = __nccwpck_require__(3440) +const { STATUS_CODES } = __nccwpck_require__(58611) +const { + types: { + isPromise + } +} = __nccwpck_require__(39023) + +function matchValue (match, value) { + if (typeof match === 'string') { + return match === value + } + if (match instanceof RegExp) { + return match.test(value) + } + if (typeof match === 'function') { + return match(value) === true + } + return false +} + +function lowerCaseEntries (headers) { + return Object.fromEntries( + Object.entries(headers).map(([headerName, headerValue]) => { + return [headerName.toLocaleLowerCase(), headerValue] + }) + ) +} + +/** + * @param {import('../../index').Headers|string[]|Record} headers + * @param {string} key + */ +function getHeaderByName (headers, key) { + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { + return headers[i + 1] + } + } + + return undefined + } else if (typeof headers.get === 'function') { + return headers.get(key) + } else { + return lowerCaseEntries(headers)[key.toLocaleLowerCase()] + } +} + +/** @param {string[]} headers */ +function buildHeadersFromArray (headers) { // fetch HeadersList + const clone = headers.slice() + const entries = [] + for (let index = 0; index < clone.length; index += 2) { + entries.push([clone[index], clone[index + 1]]) + } + return Object.fromEntries(entries) +} + +function matchHeaders (mockDispatch, headers) { + if (typeof mockDispatch.headers === 'function') { + if (Array.isArray(headers)) { // fetch HeadersList + headers = buildHeadersFromArray(headers) + } + return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {}) + } + if (typeof mockDispatch.headers === 'undefined') { + return true + } + if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { + return false + } + + for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { + const headerValue = getHeaderByName(headers, matchHeaderName) + + if (!matchValue(matchHeaderValue, headerValue)) { + return false + } + } + return true +} + +function safeUrl (path) { + if (typeof path !== 'string') { + return path + } + + const pathSegments = path.split('?') + + if (pathSegments.length !== 2) { + return path + } + + const qp = new URLSearchParams(pathSegments.pop()) + qp.sort() + return [...pathSegments, qp.toString()].join('?') +} + +function matchKey (mockDispatch, { path, method, body, headers }) { + const pathMatch = matchValue(mockDispatch.path, path) + const methodMatch = matchValue(mockDispatch.method, method) + const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true + const headersMatch = matchHeaders(mockDispatch, headers) + return pathMatch && methodMatch && bodyMatch && headersMatch +} + +function getResponseData (data) { + if (Buffer.isBuffer(data)) { + return data + } else if (typeof data === 'object') { + return JSON.stringify(data) + } else { + return data.toString() + } +} + +function getMockDispatch (mockDispatches, key) { + const basePath = key.query ? buildURL(key.path, key.query) : key.path + const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath + + // Match path + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(safeUrl(path), resolvedPath)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`) + } + + // Match method + matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}'`) + } + + // Match body + matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}'`) + } + + // Match headers + matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for headers '${typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers}'`) + } + + return matchedMockDispatches[0] +} + +function addMockDispatch (mockDispatches, key, data) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false } + const replyData = typeof data === 'function' ? { callback: data } : { ...data } + const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } } + mockDispatches.push(newMockDispatch) + return newMockDispatch +} + +function deleteMockDispatch (mockDispatches, key) { + const index = mockDispatches.findIndex(dispatch => { + if (!dispatch.consumed) { + return false + } + return matchKey(dispatch, key) + }) + if (index !== -1) { + mockDispatches.splice(index, 1) + } +} + +function buildKey (opts) { + const { path, method, body, headers, query } = opts + return { + path, + method, + body, + headers, + query + } +} + +function generateKeyValues (data) { + return Object.entries(data).reduce((keyValuePairs, [key, value]) => [ + ...keyValuePairs, + Buffer.from(`${key}`), + Array.isArray(value) ? value.map(x => Buffer.from(`${x}`)) : Buffer.from(`${value}`) + ], []) +} + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status + * @param {number} statusCode + */ +function getStatusText (statusCode) { + return STATUS_CODES[statusCode] || 'unknown' +} + +async function getResponse (body) { + const buffers = [] + for await (const data of body) { + buffers.push(data) + } + return Buffer.concat(buffers).toString('utf8') +} + +/** + * Mock dispatch function used to simulate undici dispatches + */ +function mockDispatch (opts, handler) { + // Get mock dispatch from built key + const key = buildKey(opts) + const mockDispatch = getMockDispatch(this[kDispatches], key) + + mockDispatch.timesInvoked++ + + // Here's where we resolve a callback if a callback is present for the dispatch data. + if (mockDispatch.data.callback) { + mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) } + } + + // Parse mockDispatch data + const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch + const { timesInvoked, times } = mockDispatch + + // If it's used up and not persistent, mark as consumed + mockDispatch.consumed = !persist && timesInvoked >= times + mockDispatch.pending = timesInvoked < times + + // If specified, trigger dispatch error + if (error !== null) { + deleteMockDispatch(this[kDispatches], key) + handler.onError(error) + return true + } + + // Handle the request with a delay if necessary + if (typeof delay === 'number' && delay > 0) { + setTimeout(() => { + handleReply(this[kDispatches]) + }, delay) + } else { + handleReply(this[kDispatches]) + } + + function handleReply (mockDispatches, _data = data) { + // fetch's HeadersList is a 1D string array + const optsHeaders = Array.isArray(opts.headers) + ? buildHeadersFromArray(opts.headers) + : opts.headers + const body = typeof _data === 'function' + ? _data({ ...opts, headers: optsHeaders }) + : _data + + // util.types.isPromise is likely needed for jest. + if (isPromise(body)) { + // If handleReply is asynchronous, throwing an error + // in the callback will reject the promise, rather than + // synchronously throw the error, which breaks some tests. + // Rather, we wait for the callback to resolve if it is a + // promise, and then re-run handleReply with the new body. + body.then((newData) => handleReply(mockDispatches, newData)) + return + } + + const responseData = getResponseData(body) + const responseHeaders = generateKeyValues(headers) + const responseTrailers = generateKeyValues(trailers) + + handler.abort = nop + handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode)) + handler.onData(Buffer.from(responseData)) + handler.onComplete(responseTrailers) + deleteMockDispatch(mockDispatches, key) + } + + function resume () {} + + return true +} + +function buildMockDispatch () { + const agent = this[kMockAgent] + const origin = this[kOrigin] + const originalDispatch = this[kOriginalDispatch] + + return function dispatch (opts, handler) { + if (agent.isMockActive) { + try { + mockDispatch.call(this, opts, handler) + } catch (error) { + if (error instanceof MockNotMatchedError) { + const netConnect = agent[kGetNetConnect]() + if (netConnect === false) { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) + } + if (checkNetConnect(netConnect, origin)) { + originalDispatch.call(this, opts, handler) + } else { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) + } + } else { + throw error + } + } + } else { + originalDispatch.call(this, opts, handler) + } + } +} + +function checkNetConnect (netConnect, origin) { + const url = new URL(origin) + if (netConnect === true) { + return true + } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { + return true + } + return false +} + +function buildMockOptions (opts) { + if (opts) { + const { agent, ...mockOptions } = opts + return mockOptions + } +} + +module.exports = { + getResponseData, + getMockDispatch, + addMockDispatch, + deleteMockDispatch, + buildKey, + generateKeyValues, + matchValue, + getResponse, + getStatusText, + mockDispatch, + buildMockDispatch, + checkNetConnect, + buildMockOptions, + getHeaderByName +} + + +/***/ }), + +/***/ 56142: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Transform } = __nccwpck_require__(2203) +const { Console } = __nccwpck_require__(64236) + +/** + * Gets the output of `console.table(…)` as a string. + */ +module.exports = class PendingInterceptorsFormatter { + constructor ({ disableColors } = {}) { + this.transform = new Transform({ + transform (chunk, _enc, cb) { + cb(null, chunk) + } + }) + + this.logger = new Console({ + stdout: this.transform, + inspectOptions: { + colors: !disableColors && !process.env.CI + } + }) + } + + format (pendingInterceptors) { + const withPrettyHeaders = pendingInterceptors.map( + ({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + Method: method, + Origin: origin, + Path: path, + 'Status code': statusCode, + Persistent: persist ? '✅' : '❌', + Invocations: timesInvoked, + Remaining: persist ? Infinity : times - timesInvoked + })) + + this.logger.table(withPrettyHeaders) + return this.transform.read().toString() + } +} + + +/***/ }), + +/***/ 91529: +/***/ ((module) => { + +"use strict"; + + +const singulars = { + pronoun: 'it', + is: 'is', + was: 'was', + this: 'this' +} + +const plurals = { + pronoun: 'they', + is: 'are', + was: 'were', + this: 'these' +} + +module.exports = class Pluralizer { + constructor (singular, plural) { + this.singular = singular + this.plural = plural + } + + pluralize (count) { + const one = count === 1 + const keys = one ? singulars : plurals + const noun = one ? this.singular : this.plural + return { ...keys, count, noun } + } +} + + +/***/ }), + +/***/ 34869: +/***/ ((module) => { + +"use strict"; +/* eslint-disable */ + + + +// Extracted from node/lib/internal/fixed_queue.js + +// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two. +const kSize = 2048; +const kMask = kSize - 1; + +// The FixedQueue is implemented as a singly-linked list of fixed-size +// circular buffers. It looks something like this: +// +// head tail +// | | +// v v +// +-----------+ <-----\ +-----------+ <------\ +-----------+ +// | [null] | \----- | next | \------- | next | +// +-----------+ +-----------+ +-----------+ +// | item | <-- bottom | item | <-- bottom | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | bottom --> | item | +// | item | | item | | item | +// | ... | | ... | | ... | +// | item | | item | | item | +// | item | | item | | item | +// | [empty] | <-- top | item | | item | +// | [empty] | | item | | item | +// | [empty] | | [empty] | <-- top top --> | [empty] | +// +-----------+ +-----------+ +-----------+ +// +// Or, if there is only one circular buffer, it looks something +// like either of these: +// +// head tail head tail +// | | | | +// v v v v +// +-----------+ +-----------+ +// | [null] | | [null] | +// +-----------+ +-----------+ +// | [empty] | | item | +// | [empty] | | item | +// | item | <-- bottom top --> | [empty] | +// | item | | [empty] | +// | [empty] | <-- top bottom --> | item | +// | [empty] | | item | +// +-----------+ +-----------+ +// +// Adding a value means moving `top` forward by one, removing means +// moving `bottom` forward by one. After reaching the end, the queue +// wraps around. +// +// When `top === bottom` the current queue is empty and when +// `top + 1 === bottom` it's full. This wastes a single space of storage +// but allows much quicker checks. + +class FixedCircularBuffer { + constructor() { + this.bottom = 0; + this.top = 0; + this.list = new Array(kSize); + this.next = null; + } + + isEmpty() { + return this.top === this.bottom; + } + + isFull() { + return ((this.top + 1) & kMask) === this.bottom; + } + + push(data) { + this.list[this.top] = data; + this.top = (this.top + 1) & kMask; + } + + shift() { + const nextItem = this.list[this.bottom]; + if (nextItem === undefined) + return null; + this.list[this.bottom] = undefined; + this.bottom = (this.bottom + 1) & kMask; + return nextItem; + } +} + +module.exports = class FixedQueue { + constructor() { + this.head = this.tail = new FixedCircularBuffer(); + } + + isEmpty() { + return this.head.isEmpty(); + } + + push(data) { + if (this.head.isFull()) { + // Head is full: Creates a new queue, sets the old queue's `.next` to it, + // and sets it as the new main queue. + this.head = this.head.next = new FixedCircularBuffer(); + } + this.head.push(data); + } + + shift() { + const tail = this.tail; + const next = tail.shift(); + if (tail.isEmpty() && tail.next !== null) { + // If there is another queue, it forms the new tail. + this.tail = tail.next; + } + return next; + } +}; + + +/***/ }), + +/***/ 58640: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const DispatcherBase = __nccwpck_require__(50001) +const FixedQueue = __nccwpck_require__(34869) +const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(36443) +const PoolStats = __nccwpck_require__(24622) + +const kClients = Symbol('clients') +const kNeedDrain = Symbol('needDrain') +const kQueue = Symbol('queue') +const kClosedResolve = Symbol('closed resolve') +const kOnDrain = Symbol('onDrain') +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kGetDispatcher = Symbol('get dispatcher') +const kAddClient = Symbol('add client') +const kRemoveClient = Symbol('remove client') +const kStats = Symbol('stats') + +class PoolBase extends DispatcherBase { + constructor () { + super() + + this[kQueue] = new FixedQueue() + this[kClients] = [] + this[kQueued] = 0 + + const pool = this + + this[kOnDrain] = function onDrain (origin, targets) { + const queue = pool[kQueue] + + let needDrain = false + + while (!needDrain) { + const item = queue.shift() + if (!item) { + break + } + pool[kQueued]-- + needDrain = !this.dispatch(item.opts, item.handler) + } + + this[kNeedDrain] = needDrain + + if (!this[kNeedDrain] && pool[kNeedDrain]) { + pool[kNeedDrain] = false + pool.emit('drain', origin, [pool, ...targets]) + } + + if (pool[kClosedResolve] && queue.isEmpty()) { + Promise + .all(pool[kClients].map(c => c.close())) + .then(pool[kClosedResolve]) + } + } + + this[kOnConnect] = (origin, targets) => { + pool.emit('connect', origin, [pool, ...targets]) + } + + this[kOnDisconnect] = (origin, targets, err) => { + pool.emit('disconnect', origin, [pool, ...targets], err) + } + + this[kOnConnectionError] = (origin, targets, err) => { + pool.emit('connectionError', origin, [pool, ...targets], err) + } + + this[kStats] = new PoolStats(this) + } + + get [kBusy] () { + return this[kNeedDrain] + } + + get [kConnected] () { + return this[kClients].filter(client => client[kConnected]).length + } + + get [kFree] () { + return this[kClients].filter(client => client[kConnected] && !client[kNeedDrain]).length + } + + get [kPending] () { + let ret = this[kQueued] + for (const { [kPending]: pending } of this[kClients]) { + ret += pending + } + return ret + } + + get [kRunning] () { + let ret = 0 + for (const { [kRunning]: running } of this[kClients]) { + ret += running + } + return ret + } + + get [kSize] () { + let ret = this[kQueued] + for (const { [kSize]: size } of this[kClients]) { + ret += size + } + return ret + } + + get stats () { + return this[kStats] + } + + async [kClose] () { + if (this[kQueue].isEmpty()) { + return Promise.all(this[kClients].map(c => c.close())) + } else { + return new Promise((resolve) => { + this[kClosedResolve] = resolve + }) + } + } + + async [kDestroy] (err) { + while (true) { + const item = this[kQueue].shift() + if (!item) { + break + } + item.handler.onError(err) + } + + return Promise.all(this[kClients].map(c => c.destroy(err))) + } + + [kDispatch] (opts, handler) { + const dispatcher = this[kGetDispatcher]() + + if (!dispatcher) { + this[kNeedDrain] = true + this[kQueue].push({ opts, handler }) + this[kQueued]++ + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true + this[kNeedDrain] = !this[kGetDispatcher]() + } + + return !this[kNeedDrain] + } + + [kAddClient] (client) { + client + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) + + this[kClients].push(client) + + if (this[kNeedDrain]) { + process.nextTick(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client[kUrl], [this, client]) + } + }) + } + + return this + } + + [kRemoveClient] (client) { + client.close(() => { + const idx = this[kClients].indexOf(client) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + }) + + this[kNeedDrain] = this[kClients].some(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + } +} + +module.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} + + +/***/ }), + +/***/ 24622: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(36443) +const kPool = Symbol('pool') + +class PoolStats { + constructor (pool) { + this[kPool] = pool + } + + get connected () { + return this[kPool][kConnected] + } + + get free () { + return this[kPool][kFree] + } + + get pending () { + return this[kPool][kPending] + } + + get queued () { + return this[kPool][kQueued] + } + + get running () { + return this[kPool][kRunning] + } + + get size () { + return this[kPool][kSize] + } +} + +module.exports = PoolStats + + +/***/ }), + +/***/ 35076: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher +} = __nccwpck_require__(58640) +const Client = __nccwpck_require__(86197) +const { + InvalidArgumentError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { kUrl, kInterceptors } = __nccwpck_require__(36443) +const buildConnector = __nccwpck_require__(59136) + +const kOptions = Symbol('options') +const kConnections = Symbol('connections') +const kFactory = Symbol('factory') + +function defaultFactory (origin, opts) { + return new Client(origin, opts) +} + +class Pool extends PoolBase { + constructor (origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + ...options + } = {}) { + super() + + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError('invalid connections') + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } + + this[kInterceptors] = options.interceptors && options.interceptors.Pool && Array.isArray(options.interceptors.Pool) + ? options.interceptors.Pool + : [] + this[kConnections] = connections || null + this[kUrl] = util.parseOrigin(origin) + this[kOptions] = { ...util.deepClone(options), connect, allowH2 } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kFactory] = factory + + this.on('connectionError', (origin, targets, error) => { + // If a connection error occurs, we remove the client from the pool, + // and emit a connectionError event. They will not be re-used. + // Fixes https://github.com/nodejs/undici/issues/3895 + for (const target of targets) { + // Do not use kRemoveClient here, as it will close the client, + // but the client cannot be closed in this state. + const idx = this[kClients].indexOf(target) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + } + }) + } + + [kGetDispatcher] () { + let dispatcher = this[kClients].find(dispatcher => !dispatcher[kNeedDrain]) + + if (dispatcher) { + return dispatcher + } + + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + dispatcher = this[kFactory](this[kUrl], this[kOptions]) + this[kAddClient](dispatcher) + } + + return dispatcher + } +} + +module.exports = Pool + + +/***/ }), + +/***/ 22720: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(36443) +const { URL } = __nccwpck_require__(87016) +const Agent = __nccwpck_require__(59965) +const Pool = __nccwpck_require__(35076) +const DispatcherBase = __nccwpck_require__(50001) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(68707) +const buildConnector = __nccwpck_require__(59136) + +const kAgent = Symbol('proxy agent') +const kClient = Symbol('proxy client') +const kProxyHeaders = Symbol('proxy headers') +const kRequestTls = Symbol('request tls settings') +const kProxyTls = Symbol('proxy tls settings') +const kConnectEndpoint = Symbol('connect endpoint function') + +function defaultProtocolPort (protocol) { + return protocol === 'https:' ? 443 : 80 +} + +function buildProxyOptions (opts) { + if (typeof opts === 'string') { + opts = { uri: opts } + } + + if (!opts || !opts.uri) { + throw new InvalidArgumentError('Proxy opts.uri is mandatory') + } + + return { + uri: opts.uri, + protocol: opts.protocol || 'https' + } +} + +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} + +class ProxyAgent extends DispatcherBase { + constructor (opts) { + super(opts) + this[kProxy] = buildProxyOptions(opts) + this[kAgent] = new Agent(opts) + this[kInterceptors] = opts.interceptors && opts.interceptors.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) + ? opts.interceptors.ProxyAgent + : [] + + if (typeof opts === 'string') { + opts = { uri: opts } + } + + if (!opts || !opts.uri) { + throw new InvalidArgumentError('Proxy opts.uri is mandatory') + } + + const { clientFactory = defaultFactory } = opts + + if (typeof clientFactory !== 'function') { + throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.') + } + + this[kRequestTls] = opts.requestTls + this[kProxyTls] = opts.proxyTls + this[kProxyHeaders] = opts.headers || {} + + const resolvedUrl = new URL(opts.uri) + const { origin, port, host, username, password } = resolvedUrl + + if (opts.auth && opts.token) { + throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') + } else if (opts.auth) { + /* @deprecated in favour of opts.token */ + this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` + } else if (opts.token) { + this[kProxyHeaders]['proxy-authorization'] = opts.token + } else if (username && password) { + this[kProxyHeaders]['proxy-authorization'] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString('base64')}` + } + + const connect = buildConnector({ ...opts.proxyTls }) + this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) + this[kClient] = clientFactory(resolvedUrl, { connect }) + this[kAgent] = new Agent({ + ...opts, + connect: async (opts, callback) => { + let requestedHost = opts.host + if (!opts.port) { + requestedHost += `:${defaultProtocolPort(opts.protocol)}` + } + try { + const { socket, statusCode } = await this[kClient].connect({ + origin, + port, + path: requestedHost, + signal: opts.signal, + headers: { + ...this[kProxyHeaders], + host + } + }) + if (statusCode !== 200) { + socket.on('error', () => {}).destroy() + callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) + } + if (opts.protocol !== 'https:') { + callback(null, socket) + return + } + let servername + if (this[kRequestTls]) { + servername = this[kRequestTls].servername + } else { + servername = opts.servername + } + this[kConnectEndpoint]({ ...opts, servername, httpSocket: socket }, callback) + } catch (err) { + callback(err) + } + } + }) + } + + dispatch (opts, handler) { + const { host } = new URL(opts.origin) + const headers = buildHeaders(opts.headers) + throwIfProxyAuthIsSent(headers) + return this[kAgent].dispatch( + { + ...opts, + headers: { + ...headers, + host + } + }, + handler + ) + } + + async [kClose] () { + await this[kAgent].close() + await this[kClient].close() + } + + async [kDestroy] () { + await this[kAgent].destroy() + await this[kClient].destroy() + } +} + +/** + * @param {string[] | Record} headers + * @returns {Record} + */ +function buildHeaders (headers) { + // When using undici.fetch, the headers list is stored + // as an array. + if (Array.isArray(headers)) { + /** @type {Record} */ + const headersPair = {} + + for (let i = 0; i < headers.length; i += 2) { + headersPair[headers[i]] = headers[i + 1] + } + + return headersPair + } + + return headers +} + +/** + * @param {Record} headers + * + * Previous versions of ProxyAgent suggests the Proxy-Authorization in request headers + * Nevertheless, it was changed and to avoid a security vulnerability by end users + * this check was created. + * It should be removed in the next major version for performance reasons + */ +function throwIfProxyAuthIsSent (headers) { + const existProxyAuth = headers && Object.keys(headers) + .find((key) => key.toLowerCase() === 'proxy-authorization') + if (existProxyAuth) { + throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor') + } +} + +module.exports = ProxyAgent + + +/***/ }), + +/***/ 28804: +/***/ ((module) => { + +"use strict"; + + +let fastNow = Date.now() +let fastNowTimeout + +const fastTimers = [] + +function onTimeout () { + fastNow = Date.now() + + let len = fastTimers.length + let idx = 0 + while (idx < len) { + const timer = fastTimers[idx] + + if (timer.state === 0) { + timer.state = fastNow + timer.delay + } else if (timer.state > 0 && fastNow >= timer.state) { + timer.state = -1 + timer.callback(timer.opaque) + } + + if (timer.state === -1) { + timer.state = -2 + if (idx !== len - 1) { + fastTimers[idx] = fastTimers.pop() + } else { + fastTimers.pop() + } + len -= 1 + } else { + idx += 1 + } + } + + if (fastTimers.length > 0) { + refreshTimeout() + } +} + +function refreshTimeout () { + if (fastNowTimeout && fastNowTimeout.refresh) { + fastNowTimeout.refresh() + } else { + clearTimeout(fastNowTimeout) + fastNowTimeout = setTimeout(onTimeout, 1e3) + if (fastNowTimeout.unref) { + fastNowTimeout.unref() + } + } +} + +class Timeout { + constructor (callback, delay, opaque) { + this.callback = callback + this.delay = delay + this.opaque = opaque + + // -2 not in timer list + // -1 in timer list but inactive + // 0 in timer list waiting for time + // > 0 in timer list waiting for time to expire + this.state = -2 + + this.refresh() + } + + refresh () { + if (this.state === -2) { + fastTimers.push(this) + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout() + } + } + + this.state = 0 + } + + clear () { + this.state = -1 + } +} + +module.exports = { + setTimeout (callback, delay, opaque) { + return delay < 1e3 + ? setTimeout(callback, delay, opaque) + : new Timeout(callback, delay, opaque) + }, + clearTimeout (timeout) { + if (timeout instanceof Timeout) { + timeout.clear() + } else { + clearTimeout(timeout) + } + } +} + + +/***/ }), + +/***/ 68550: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const diagnosticsChannel = __nccwpck_require__(31637) +const { uid, states } = __nccwpck_require__(45913) +const { + kReadyState, + kSentClose, + kByteParser, + kReceivedClose +} = __nccwpck_require__(62933) +const { fireEvent, failWebsocketConnection } = __nccwpck_require__(3574) +const { CloseEvent } = __nccwpck_require__(46255) +const { makeRequest } = __nccwpck_require__(25194) +const { fetching } = __nccwpck_require__(12315) +const { Headers } = __nccwpck_require__(26349) +const { getGlobalDispatcher } = __nccwpck_require__(32581) +const { kHeadersList } = __nccwpck_require__(36443) + +const channels = {} +channels.open = diagnosticsChannel.channel('undici:websocket:open') +channels.close = diagnosticsChannel.channel('undici:websocket:close') +channels.socketError = diagnosticsChannel.channel('undici:websocket:socket_error') + +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(76982) +} catch { + +} + +/** + * @see https://websockets.spec.whatwg.org/#concept-websocket-establish + * @param {URL} url + * @param {string|string[]} protocols + * @param {import('./websocket').WebSocket} ws + * @param {(response: any) => void} onEstablish + * @param {Partial} options + */ +function establishWebSocketConnection (url, protocols, ws, onEstablish, options) { + // 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s + // scheme is "ws", and to "https" otherwise. + const requestURL = url + + requestURL.protocol = url.protocol === 'ws:' ? 'http:' : 'https:' + + // 2. Let request be a new request, whose URL is requestURL, client is client, + // service-workers mode is "none", referrer is "no-referrer", mode is + // "websocket", credentials mode is "include", cache mode is "no-store" , + // and redirect mode is "error". + const request = makeRequest({ + urlList: [requestURL], + serviceWorkers: 'none', + referrer: 'no-referrer', + mode: 'websocket', + credentials: 'include', + cache: 'no-store', + redirect: 'error' + }) + + // Note: undici extension, allow setting custom headers. + if (options.headers) { + const headersList = new Headers(options.headers)[kHeadersList] + + request.headersList = headersList + } + + // 3. Append (`Upgrade`, `websocket`) to request’s header list. + // 4. Append (`Connection`, `Upgrade`) to request’s header list. + // Note: both of these are handled by undici currently. + // https://github.com/nodejs/undici/blob/68c269c4144c446f3f1220951338daef4a6b5ec4/lib/client.js#L1397 + + // 5. Let keyValue be a nonce consisting of a randomly selected + // 16-byte value that has been forgiving-base64-encoded and + // isomorphic encoded. + const keyValue = crypto.randomBytes(16).toString('base64') + + // 6. Append (`Sec-WebSocket-Key`, keyValue) to request’s + // header list. + request.headersList.append('sec-websocket-key', keyValue) + + // 7. Append (`Sec-WebSocket-Version`, `13`) to request’s + // header list. + request.headersList.append('sec-websocket-version', '13') + + // 8. For each protocol in protocols, combine + // (`Sec-WebSocket-Protocol`, protocol) in request’s header + // list. + for (const protocol of protocols) { + request.headersList.append('sec-websocket-protocol', protocol) + } + + // 9. Let permessageDeflate be a user-agent defined + // "permessage-deflate" extension header value. + // https://github.com/mozilla/gecko-dev/blob/ce78234f5e653a5d3916813ff990f053510227bc/netwerk/protocol/websocket/WebSocketChannel.cpp#L2673 + // TODO: enable once permessage-deflate is supported + const permessageDeflate = '' // 'permessage-deflate; 15' + + // 10. Append (`Sec-WebSocket-Extensions`, permessageDeflate) to + // request’s header list. + // request.headersList.append('sec-websocket-extensions', permessageDeflate) + + // 11. Fetch request with useParallelQueue set to true, and + // processResponse given response being these steps: + const controller = fetching({ + request, + useParallelQueue: true, + dispatcher: options.dispatcher ?? getGlobalDispatcher(), + processResponse (response) { + // 1. If response is a network error or its status is not 101, + // fail the WebSocket connection. + if (response.type === 'error' || response.status !== 101) { + failWebsocketConnection(ws, 'Received network error or non-101 status code.') + return + } + + // 2. If protocols is not the empty list and extracting header + // list values given `Sec-WebSocket-Protocol` and response’s + // header list results in null, failure, or the empty byte + // sequence, then fail the WebSocket connection. + if (protocols.length !== 0 && !response.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(ws, 'Server did not respond with sent protocols.') + return + } + + // 3. Follow the requirements stated step 2 to step 6, inclusive, + // of the last set of steps in section 4.1 of The WebSocket + // Protocol to validate response. This either results in fail + // the WebSocket connection or the WebSocket connection is + // established. + + // 2. If the response lacks an |Upgrade| header field or the |Upgrade| + // header field contains a value that is not an ASCII case- + // insensitive match for the value "websocket", the client MUST + // _Fail the WebSocket Connection_. + if (response.headersList.get('Upgrade')?.toLowerCase() !== 'websocket') { + failWebsocketConnection(ws, 'Server did not set Upgrade header to "websocket".') + return + } + + // 3. If the response lacks a |Connection| header field or the + // |Connection| header field doesn't contain a token that is an + // ASCII case-insensitive match for the value "Upgrade", the client + // MUST _Fail the WebSocket Connection_. + if (response.headersList.get('Connection')?.toLowerCase() !== 'upgrade') { + failWebsocketConnection(ws, 'Server did not set Connection header to "upgrade".') + return + } + + // 4. If the response lacks a |Sec-WebSocket-Accept| header field or + // the |Sec-WebSocket-Accept| contains a value other than the + // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket- + // Key| (as a string, not base64-decoded) with the string "258EAFA5- + // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and + // trailing whitespace, the client MUST _Fail the WebSocket + // Connection_. + const secWSAccept = response.headersList.get('Sec-WebSocket-Accept') + const digest = crypto.createHash('sha1').update(keyValue + uid).digest('base64') + if (secWSAccept !== digest) { + failWebsocketConnection(ws, 'Incorrect hash received in Sec-WebSocket-Accept header.') + return + } + + // 5. If the response includes a |Sec-WebSocket-Extensions| header + // field and this header field indicates the use of an extension + // that was not present in the client's handshake (the server has + // indicated an extension not requested by the client), the client + // MUST _Fail the WebSocket Connection_. (The parsing of this + // header field to determine which extensions are requested is + // discussed in Section 9.1.) + const secExtension = response.headersList.get('Sec-WebSocket-Extensions') + + if (secExtension !== null && secExtension !== permessageDeflate) { + failWebsocketConnection(ws, 'Received different permessage-deflate than the one set.') + return + } + + // 6. If the response includes a |Sec-WebSocket-Protocol| header field + // and this header field indicates the use of a subprotocol that was + // not present in the client's handshake (the server has indicated a + // subprotocol not requested by the client), the client MUST _Fail + // the WebSocket Connection_. + const secProtocol = response.headersList.get('Sec-WebSocket-Protocol') + + if (secProtocol !== null && secProtocol !== request.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.') + return + } + + response.socket.on('data', onSocketData) + response.socket.on('close', onSocketClose) + response.socket.on('error', onSocketError) + + if (channels.open.hasSubscribers) { + channels.open.publish({ + address: response.socket.address(), + protocol: secProtocol, + extensions: secExtension + }) + } + + onEstablish(response) + } + }) + + return controller +} + +/** + * @param {Buffer} chunk + */ +function onSocketData (chunk) { + if (!this.ws[kByteParser].write(chunk)) { + this.pause() + } +} + +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + */ +function onSocketClose () { + const { ws } = this + + // If the TCP connection was closed after the + // WebSocket closing handshake was completed, the WebSocket connection + // is said to have been closed _cleanly_. + const wasClean = ws[kSentClose] && ws[kReceivedClose] + + let code = 1005 + let reason = '' + + const result = ws[kByteParser].closingInfo + + if (result) { + code = result.code ?? 1005 + reason = result.reason + } else if (!ws[kSentClose]) { + // If _The WebSocket + // Connection is Closed_ and no Close control frame was received by the + // endpoint (such as could occur if the underlying transport connection + // is lost), _The WebSocket Connection Close Code_ is considered to be + // 1006. + code = 1006 + } + + // 1. Change the ready state to CLOSED (3). + ws[kReadyState] = states.CLOSED + + // 2. If the user agent was required to fail the WebSocket + // connection, or if the WebSocket connection was closed + // after being flagged as full, fire an event named error + // at the WebSocket object. + // TODO + + // 3. Fire an event named close at the WebSocket object, + // using CloseEvent, with the wasClean attribute + // initialized to true if the connection closed cleanly + // and false otherwise, the code attribute initialized to + // the WebSocket connection close code, and the reason + // attribute initialized to the result of applying UTF-8 + // decode without BOM to the WebSocket connection close + // reason. + fireEvent('close', ws, CloseEvent, { + wasClean, code, reason + }) + + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: ws, + code, + reason + }) + } +} + +function onSocketError (error) { + const { ws } = this + + ws[kReadyState] = states.CLOSING + + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(error) + } + + this.destroy() +} + +module.exports = { + establishWebSocketConnection +} + + +/***/ }), + +/***/ 45913: +/***/ ((module) => { + +"use strict"; + + +// This is a Globally Unique Identifier unique used +// to validate that the endpoint accepts websocket +// connections. +// See https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3 +const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} + +const states = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 +} + +const opcodes = { + CONTINUATION: 0x0, + TEXT: 0x1, + BINARY: 0x2, + CLOSE: 0x8, + PING: 0x9, + PONG: 0xA +} + +const maxUnsigned16Bit = 2 ** 16 - 1 // 65535 + +const parserStates = { + INFO: 0, + PAYLOADLENGTH_16: 2, + PAYLOADLENGTH_64: 3, + READ_DATA: 4 +} + +const emptyBuffer = Buffer.allocUnsafe(0) + +module.exports = { + uid, + staticPropertyDescriptors, + states, + opcodes, + maxUnsigned16Bit, + parserStates, + emptyBuffer +} + + +/***/ }), + +/***/ 46255: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(74222) +const { kEnumerableProperty } = __nccwpck_require__(3440) +const { MessagePort } = __nccwpck_require__(28167) + +/** + * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent + */ +class MessageEvent extends Event { + #eventInit + + constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent constructor' }) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.MessageEventInit(eventInitDict) + + super(type, eventInitDict) + + this.#eventInit = eventInitDict + } + + get data () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.data + } + + get origin () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.origin + } + + get lastEventId () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.lastEventId + } + + get source () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.source + } + + get ports () { + webidl.brandCheck(this, MessageEvent) + + if (!Object.isFrozen(this.#eventInit.ports)) { + Object.freeze(this.#eventInit.ports) + } + + return this.#eventInit.ports + } + + initMessageEvent ( + type, + bubbles = false, + cancelable = false, + data = null, + origin = '', + lastEventId = '', + source = null, + ports = [] + ) { + webidl.brandCheck(this, MessageEvent) + + webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent.initMessageEvent' }) + + return new MessageEvent(type, { + bubbles, cancelable, data, origin, lastEventId, source, ports + }) + } +} + +/** + * @see https://websockets.spec.whatwg.org/#the-closeevent-interface + */ +class CloseEvent extends Event { + #eventInit + + constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'CloseEvent constructor' }) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.CloseEventInit(eventInitDict) + + super(type, eventInitDict) + + this.#eventInit = eventInitDict + } + + get wasClean () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.wasClean + } + + get code () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.code + } + + get reason () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.reason + } +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface +class ErrorEvent extends Event { + #eventInit + + constructor (type, eventInitDict) { + webidl.argumentLengthCheck(arguments, 1, { header: 'ErrorEvent constructor' }) + + super(type, eventInitDict) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) + + this.#eventInit = eventInitDict + } + + get message () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.message + } + + get filename () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.filename + } + + get lineno () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.lineno + } + + get colno () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.colno + } + + get error () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.error + } +} + +Object.defineProperties(MessageEvent.prototype, { + [Symbol.toStringTag]: { + value: 'MessageEvent', + configurable: true + }, + data: kEnumerableProperty, + origin: kEnumerableProperty, + lastEventId: kEnumerableProperty, + source: kEnumerableProperty, + ports: kEnumerableProperty, + initMessageEvent: kEnumerableProperty +}) + +Object.defineProperties(CloseEvent.prototype, { + [Symbol.toStringTag]: { + value: 'CloseEvent', + configurable: true + }, + reason: kEnumerableProperty, + code: kEnumerableProperty, + wasClean: kEnumerableProperty +}) + +Object.defineProperties(ErrorEvent.prototype, { + [Symbol.toStringTag]: { + value: 'ErrorEvent', + configurable: true + }, + message: kEnumerableProperty, + filename: kEnumerableProperty, + lineno: kEnumerableProperty, + colno: kEnumerableProperty, + error: kEnumerableProperty +}) + +webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.MessagePort +) + +const eventInit = [ + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: false + } +] + +webidl.converters.MessageEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'data', + converter: webidl.converters.any, + defaultValue: null + }, + { + key: 'origin', + converter: webidl.converters.USVString, + defaultValue: '' + }, + { + key: 'lastEventId', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'source', + // Node doesn't implement WindowProxy or ServiceWorker, so the only + // valid value for source is a MessagePort. + converter: webidl.nullableConverter(webidl.converters.MessagePort), + defaultValue: null + }, + { + key: 'ports', + converter: webidl.converters['sequence'], + get defaultValue () { + return [] + } + } +]) + +webidl.converters.CloseEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'wasClean', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'code', + converter: webidl.converters['unsigned short'], + defaultValue: 0 + }, + { + key: 'reason', + converter: webidl.converters.USVString, + defaultValue: '' + } +]) + +webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'message', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'filename', + converter: webidl.converters.USVString, + defaultValue: '' + }, + { + key: 'lineno', + converter: webidl.converters['unsigned long'], + defaultValue: 0 + }, + { + key: 'colno', + converter: webidl.converters['unsigned long'], + defaultValue: 0 + }, + { + key: 'error', + converter: webidl.converters.any + } +]) + +module.exports = { + MessageEvent, + CloseEvent, + ErrorEvent +} + + +/***/ }), + +/***/ 31237: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { maxUnsigned16Bit } = __nccwpck_require__(45913) + +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(76982) +} catch { + +} + +class WebsocketFrameSend { + /** + * @param {Buffer|undefined} data + */ + constructor (data) { + this.frameData = data + this.maskKey = crypto.randomBytes(4) + } + + createFrame (opcode) { + const bodyLength = this.frameData?.byteLength ?? 0 + + /** @type {number} */ + let payloadLength = bodyLength // 0-125 + let offset = 6 + + if (bodyLength > maxUnsigned16Bit) { + offset += 8 // payload length is next 8 bytes + payloadLength = 127 + } else if (bodyLength > 125) { + offset += 2 // payload length is next 2 bytes + payloadLength = 126 + } + + const buffer = Buffer.allocUnsafe(bodyLength + offset) + + // Clear first 2 bytes, everything else is overwritten + buffer[0] = buffer[1] = 0 + buffer[0] |= 0x80 // FIN + buffer[0] = (buffer[0] & 0xF0) + opcode // opcode + + /*! ws. MIT License. Einar Otto Stangvik */ + buffer[offset - 4] = this.maskKey[0] + buffer[offset - 3] = this.maskKey[1] + buffer[offset - 2] = this.maskKey[2] + buffer[offset - 1] = this.maskKey[3] + + buffer[1] = payloadLength + + if (payloadLength === 126) { + buffer.writeUInt16BE(bodyLength, 2) + } else if (payloadLength === 127) { + // Clear extended payload length + buffer[2] = buffer[3] = 0 + buffer.writeUIntBE(bodyLength, 4, 6) + } + + buffer[1] |= 0x80 // MASK + + // mask body + for (let i = 0; i < bodyLength; i++) { + buffer[offset + i] = this.frameData[i] ^ this.maskKey[i % 4] + } + + return buffer + } +} + +module.exports = { + WebsocketFrameSend +} + + +/***/ }), + +/***/ 43171: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Writable } = __nccwpck_require__(2203) +const diagnosticsChannel = __nccwpck_require__(31637) +const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(45913) +const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(62933) +const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(3574) +const { WebsocketFrameSend } = __nccwpck_require__(31237) + +// This code was influenced by ws released under the MIT license. +// Copyright (c) 2011 Einar Otto Stangvik +// Copyright (c) 2013 Arnout Kazemier and contributors +// Copyright (c) 2016 Luigi Pinca and contributors + +const channels = {} +channels.ping = diagnosticsChannel.channel('undici:websocket:ping') +channels.pong = diagnosticsChannel.channel('undici:websocket:pong') + +class ByteParser extends Writable { + #buffers = [] + #byteOffset = 0 + + #state = parserStates.INFO + + #info = {} + #fragments = [] + + constructor (ws) { + super() + + this.ws = ws + } + + /** + * @param {Buffer} chunk + * @param {() => void} callback + */ + _write (chunk, _, callback) { + this.#buffers.push(chunk) + this.#byteOffset += chunk.length + + this.run(callback) + } + + /** + * Runs whenever a new chunk is received. + * Callback is called whenever there are no more chunks buffering, + * or not enough bytes are buffered to parse. + */ + run (callback) { + while (true) { + if (this.#state === parserStates.INFO) { + // If there aren't enough bytes to parse the payload length, etc. + if (this.#byteOffset < 2) { + return callback() + } + + const buffer = this.consume(2) + + this.#info.fin = (buffer[0] & 0x80) !== 0 + this.#info.opcode = buffer[0] & 0x0F + + // If we receive a fragmented message, we use the type of the first + // frame to parse the full message as binary/text, when it's terminated + this.#info.originalOpcode ??= this.#info.opcode + + this.#info.fragmented = !this.#info.fin && this.#info.opcode !== opcodes.CONTINUATION + + if (this.#info.fragmented && this.#info.opcode !== opcodes.BINARY && this.#info.opcode !== opcodes.TEXT) { + // Only text and binary frames can be fragmented + failWebsocketConnection(this.ws, 'Invalid frame type was fragmented.') + return + } + + const payloadLength = buffer[1] & 0x7F + + if (payloadLength <= 125) { + this.#info.payloadLength = payloadLength + this.#state = parserStates.READ_DATA + } else if (payloadLength === 126) { + this.#state = parserStates.PAYLOADLENGTH_16 + } else if (payloadLength === 127) { + this.#state = parserStates.PAYLOADLENGTH_64 + } + + if (this.#info.fragmented && payloadLength > 125) { + // A fragmented frame can't be fragmented itself + failWebsocketConnection(this.ws, 'Fragmented frame exceeded 125 bytes.') + return + } else if ( + (this.#info.opcode === opcodes.PING || + this.#info.opcode === opcodes.PONG || + this.#info.opcode === opcodes.CLOSE) && + payloadLength > 125 + ) { + // Control frames can have a payload length of 125 bytes MAX + failWebsocketConnection(this.ws, 'Payload length for control frame exceeded 125 bytes.') + return + } else if (this.#info.opcode === opcodes.CLOSE) { + if (payloadLength === 1) { + failWebsocketConnection(this.ws, 'Received close frame with a 1-byte body.') + return + } + + const body = this.consume(payloadLength) + + this.#info.closeInfo = this.parseCloseBody(false, body) + + if (!this.ws[kSentClose]) { + // If an endpoint receives a Close frame and did not previously send a + // Close frame, the endpoint MUST send a Close frame in response. (When + // sending a Close frame in response, the endpoint typically echos the + // status code it received.) + const body = Buffer.allocUnsafe(2) + body.writeUInt16BE(this.#info.closeInfo.code, 0) + const closeFrame = new WebsocketFrameSend(body) + + this.ws[kResponse].socket.write( + closeFrame.createFrame(opcodes.CLOSE), + (err) => { + if (!err) { + this.ws[kSentClose] = true + } + } + ) + } + + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this.ws[kReadyState] = states.CLOSING + this.ws[kReceivedClose] = true + + this.end() + + return + } else if (this.#info.opcode === opcodes.PING) { + // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in + // response, unless it already received a Close frame. + // A Pong frame sent in response to a Ping frame must have identical + // "Application data" + + const body = this.consume(payloadLength) + + if (!this.ws[kReceivedClose]) { + const frame = new WebsocketFrameSend(body) + + this.ws[kResponse].socket.write(frame.createFrame(opcodes.PONG)) + + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body + }) + } + } + + this.#state = parserStates.INFO + + if (this.#byteOffset > 0) { + continue + } else { + callback() + return + } + } else if (this.#info.opcode === opcodes.PONG) { + // A Pong frame MAY be sent unsolicited. This serves as a + // unidirectional heartbeat. A response to an unsolicited Pong frame is + // not expected. + + const body = this.consume(payloadLength) + + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body + }) + } + + if (this.#byteOffset > 0) { + continue + } else { + callback() + return + } + } + } else if (this.#state === parserStates.PAYLOADLENGTH_16) { + if (this.#byteOffset < 2) { + return callback() + } + + const buffer = this.consume(2) + + this.#info.payloadLength = buffer.readUInt16BE(0) + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.PAYLOADLENGTH_64) { + if (this.#byteOffset < 8) { + return callback() + } + + const buffer = this.consume(8) + const upper = buffer.readUInt32BE(0) + + // 2^31 is the maxinimum bytes an arraybuffer can contain + // on 32-bit systems. Although, on 64-bit systems, this is + // 2^53-1 bytes. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e + if (upper > 2 ** 31 - 1) { + failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.') + return + } + + const lower = buffer.readUInt32BE(4) + + this.#info.payloadLength = (upper << 8) + lower + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.READ_DATA) { + if (this.#byteOffset < this.#info.payloadLength) { + // If there is still more data in this chunk that needs to be read + return callback() + } else if (this.#byteOffset >= this.#info.payloadLength) { + // If the server sent multiple frames in a single chunk + + const body = this.consume(this.#info.payloadLength) + + this.#fragments.push(body) + + // If the frame is unfragmented, or a fragmented frame was terminated, + // a message was received + if (!this.#info.fragmented || (this.#info.fin && this.#info.opcode === opcodes.CONTINUATION)) { + const fullMessage = Buffer.concat(this.#fragments) + + websocketMessageReceived(this.ws, this.#info.originalOpcode, fullMessage) + + this.#info = {} + this.#fragments.length = 0 + } + + this.#state = parserStates.INFO + } + } + + if (this.#byteOffset > 0) { + continue + } else { + callback() + break + } + } + } + + /** + * Take n bytes from the buffered Buffers + * @param {number} n + * @returns {Buffer|null} + */ + consume (n) { + if (n > this.#byteOffset) { + return null + } else if (n === 0) { + return emptyBuffer + } + + if (this.#buffers[0].length === n) { + this.#byteOffset -= this.#buffers[0].length + return this.#buffers.shift() + } + + const buffer = Buffer.allocUnsafe(n) + let offset = 0 + + while (offset !== n) { + const next = this.#buffers[0] + const { length } = next + + if (length + offset === n) { + buffer.set(this.#buffers.shift(), offset) + break + } else if (length + offset > n) { + buffer.set(next.subarray(0, n - offset), offset) + this.#buffers[0] = next.subarray(n - offset) + break + } else { + buffer.set(this.#buffers.shift(), offset) + offset += next.length + } + } + + this.#byteOffset -= n + + return buffer + } + + parseCloseBody (onlyCode, data) { + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 + /** @type {number|undefined} */ + let code + + if (data.length >= 2) { + // _The WebSocket Connection Close Code_ is + // defined as the status code (Section 7.4) contained in the first Close + // control frame received by the application + code = data.readUInt16BE(0) + } + + if (onlyCode) { + if (!isValidStatusCode(code)) { + return null + } + + return { code } + } + + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6 + /** @type {Buffer} */ + let reason = data.subarray(2) + + // Remove BOM + if (reason[0] === 0xEF && reason[1] === 0xBB && reason[2] === 0xBF) { + reason = reason.subarray(3) + } + + if (code !== undefined && !isValidStatusCode(code)) { + return null + } + + try { + // TODO: optimize this + reason = new TextDecoder('utf-8', { fatal: true }).decode(reason) + } catch { + return null + } + + return { code, reason } + } + + get closingInfo () { + return this.#info.closeInfo + } +} + +module.exports = { + ByteParser +} + + +/***/ }), + +/***/ 62933: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kWebSocketURL: Symbol('url'), + kReadyState: Symbol('ready state'), + kController: Symbol('controller'), + kResponse: Symbol('response'), + kBinaryType: Symbol('binary type'), + kSentClose: Symbol('sent close'), + kReceivedClose: Symbol('received close'), + kByteParser: Symbol('byte parser') +} + + +/***/ }), + +/***/ 3574: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(62933) +const { states, opcodes } = __nccwpck_require__(45913) +const { MessageEvent, ErrorEvent } = __nccwpck_require__(46255) + +/* globals Blob */ + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isEstablished (ws) { + // If the server's response is validated as provided for above, it is + // said that _The WebSocket Connection is Established_ and that the + // WebSocket Connection is in the OPEN state. + return ws[kReadyState] === states.OPEN +} + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isClosing (ws) { + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + return ws[kReadyState] === states.CLOSING +} + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isClosed (ws) { + return ws[kReadyState] === states.CLOSED +} + +/** + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e + * @param {EventTarget} target + * @param {EventInit | undefined} eventInitDict + */ +function fireEvent (e, target, eventConstructor = Event, eventInitDict) { + // 1. If eventConstructor is not given, then let eventConstructor be Event. + + // 2. Let event be the result of creating an event given eventConstructor, + // in the relevant realm of target. + // 3. Initialize event’s type attribute to e. + const event = new eventConstructor(e, eventInitDict) // eslint-disable-line new-cap + + // 4. Initialize any other IDL attributes of event as described in the + // invocation of this algorithm. + + // 5. Return the result of dispatching event at target, with legacy target + // override flag set if set. + target.dispatchEvent(event) +} + +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @param {import('./websocket').WebSocket} ws + * @param {number} type Opcode + * @param {Buffer} data application data + */ +function websocketMessageReceived (ws, type, data) { + // 1. If ready state is not OPEN (1), then return. + if (ws[kReadyState] !== states.OPEN) { + return + } + + // 2. Let dataForEvent be determined by switching on type and binary type: + let dataForEvent + + if (type === opcodes.TEXT) { + // -> type indicates that the data is Text + // a new DOMString containing data + try { + dataForEvent = new TextDecoder('utf-8', { fatal: true }).decode(data) + } catch { + failWebsocketConnection(ws, 'Received invalid UTF-8 in text frame.') + return + } + } else if (type === opcodes.BINARY) { + if (ws[kBinaryType] === 'blob') { + // -> type indicates that the data is Binary and binary type is "blob" + // a new Blob object, created in the relevant Realm of the WebSocket + // object, that represents data as its raw data + dataForEvent = new Blob([data]) + } else { + // -> type indicates that the data is Binary and binary type is "arraybuffer" + // a new ArrayBuffer object, created in the relevant Realm of the + // WebSocket object, whose contents are data + dataForEvent = new Uint8Array(data).buffer + } + } + + // 3. Fire an event named message at the WebSocket object, using MessageEvent, + // with the origin attribute initialized to the serialization of the WebSocket + // object’s url's origin, and the data attribute initialized to dataForEvent. + fireEvent('message', ws, MessageEvent, { + origin: ws[kWebSocketURL].origin, + data: dataForEvent + }) +} + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455 + * @see https://datatracker.ietf.org/doc/html/rfc2616 + * @see https://bugs.chromium.org/p/chromium/issues/detail?id=398407 + * @param {string} protocol + */ +function isValidSubprotocol (protocol) { + // If present, this value indicates one + // or more comma-separated subprotocol the client wishes to speak, + // ordered by preference. The elements that comprise this value + // MUST be non-empty strings with characters in the range U+0021 to + // U+007E not including separator characters as defined in + // [RFC2616] and MUST all be unique strings. + if (protocol.length === 0) { + return false + } + + for (const char of protocol) { + const code = char.charCodeAt(0) + + if ( + code < 0x21 || + code > 0x7E || + char === '(' || + char === ')' || + char === '<' || + char === '>' || + char === '@' || + char === ',' || + char === ';' || + char === ':' || + char === '\\' || + char === '"' || + char === '/' || + char === '[' || + char === ']' || + char === '?' || + char === '=' || + char === '{' || + char === '}' || + code === 32 || // SP + code === 9 // HT + ) { + return false + } + } + + return true +} + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7-4 + * @param {number} code + */ +function isValidStatusCode (code) { + if (code >= 1000 && code < 1015) { + return ( + code !== 1004 && // reserved + code !== 1005 && // "MUST NOT be set as a status code" + code !== 1006 // "MUST NOT be set as a status code" + ) + } + + return code >= 3000 && code <= 4999 +} + +/** + * @param {import('./websocket').WebSocket} ws + * @param {string|undefined} reason + */ +function failWebsocketConnection (ws, reason) { + const { [kController]: controller, [kResponse]: response } = ws + + controller.abort() + + if (response?.socket && !response.socket.destroyed) { + response.socket.destroy() + } + + if (reason) { + fireEvent('error', ws, ErrorEvent, { + error: new Error(reason) + }) + } +} + +module.exports = { + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + failWebsocketConnection, + websocketMessageReceived +} + + +/***/ }), + +/***/ 55171: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(74222) +const { DOMException } = __nccwpck_require__(87326) +const { URLSerializer } = __nccwpck_require__(94322) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(45913) +const { + kWebSocketURL, + kReadyState, + kController, + kBinaryType, + kResponse, + kSentClose, + kByteParser +} = __nccwpck_require__(62933) +const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(3574) +const { establishWebSocketConnection } = __nccwpck_require__(68550) +const { WebsocketFrameSend } = __nccwpck_require__(31237) +const { ByteParser } = __nccwpck_require__(43171) +const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(3440) +const { getGlobalDispatcher } = __nccwpck_require__(32581) +const { types } = __nccwpck_require__(39023) + +let experimentalWarned = false + +// https://websockets.spec.whatwg.org/#interface-definition +class WebSocket extends EventTarget { + #events = { + open: null, + error: null, + close: null, + message: null + } + + #bufferedAmount = 0 + #protocol = '' + #extensions = '' + + /** + * @param {string} url + * @param {string|string[]} protocols + */ + constructor (url, protocols = []) { + super() + + webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket constructor' }) + + if (!experimentalWarned) { + experimentalWarned = true + process.emitWarning('WebSockets are experimental, expect them to change at any time.', { + code: 'UNDICI-WS' + }) + } + + const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols) + + url = webidl.converters.USVString(url) + protocols = options.protocols + + // 1. Let baseURL be this's relevant settings object's API base URL. + const baseURL = getGlobalOrigin() + + // 1. Let urlRecord be the result of applying the URL parser to url with baseURL. + let urlRecord + + try { + urlRecord = new URL(url, baseURL) + } catch (e) { + // 3. If urlRecord is failure, then throw a "SyntaxError" DOMException. + throw new DOMException(e, 'SyntaxError') + } + + // 4. If urlRecord’s scheme is "http", then set urlRecord’s scheme to "ws". + if (urlRecord.protocol === 'http:') { + urlRecord.protocol = 'ws:' + } else if (urlRecord.protocol === 'https:') { + // 5. Otherwise, if urlRecord’s scheme is "https", set urlRecord’s scheme to "wss". + urlRecord.protocol = 'wss:' + } + + // 6. If urlRecord’s scheme is not "ws" or "wss", then throw a "SyntaxError" DOMException. + if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') { + throw new DOMException( + `Expected a ws: or wss: protocol, got ${urlRecord.protocol}`, + 'SyntaxError' + ) + } + + // 7. If urlRecord’s fragment is non-null, then throw a "SyntaxError" + // DOMException. + if (urlRecord.hash || urlRecord.href.endsWith('#')) { + throw new DOMException('Got fragment', 'SyntaxError') + } + + // 8. If protocols is a string, set protocols to a sequence consisting + // of just that string. + if (typeof protocols === 'string') { + protocols = [protocols] + } + + // 9. If any of the values in protocols occur more than once or otherwise + // fail to match the requirements for elements that comprise the value + // of `Sec-WebSocket-Protocol` fields as defined by The WebSocket + // protocol, then throw a "SyntaxError" DOMException. + if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } + + if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } + + // 10. Set this's url to urlRecord. + this[kWebSocketURL] = new URL(urlRecord.href) + + // 11. Let client be this's relevant settings object. + + // 12. Run this step in parallel: + + // 1. Establish a WebSocket connection given urlRecord, protocols, + // and client. + this[kController] = establishWebSocketConnection( + urlRecord, + protocols, + this, + (response) => this.#onConnectionEstablished(response), + options + ) + + // Each WebSocket object has an associated ready state, which is a + // number representing the state of the connection. Initially it must + // be CONNECTING (0). + this[kReadyState] = WebSocket.CONNECTING + + // The extensions attribute must initially return the empty string. + + // The protocol attribute must initially return the empty string. + + // Each WebSocket object has an associated binary type, which is a + // BinaryType. Initially it must be "blob". + this[kBinaryType] = 'blob' + } + + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-close + * @param {number|undefined} code + * @param {string|undefined} reason + */ + close (code = undefined, reason = undefined) { + webidl.brandCheck(this, WebSocket) + + if (code !== undefined) { + code = webidl.converters['unsigned short'](code, { clamp: true }) + } + + if (reason !== undefined) { + reason = webidl.converters.USVString(reason) + } + + // 1. If code is present, but is neither an integer equal to 1000 nor an + // integer in the range 3000 to 4999, inclusive, throw an + // "InvalidAccessError" DOMException. + if (code !== undefined) { + if (code !== 1000 && (code < 3000 || code > 4999)) { + throw new DOMException('invalid code', 'InvalidAccessError') + } + } + + let reasonByteLength = 0 + + // 2. If reason is present, then run these substeps: + if (reason !== undefined) { + // 1. Let reasonBytes be the result of encoding reason. + // 2. If reasonBytes is longer than 123 bytes, then throw a + // "SyntaxError" DOMException. + reasonByteLength = Buffer.byteLength(reason) + + if (reasonByteLength > 123) { + throw new DOMException( + `Reason must be less than 123 bytes; received ${reasonByteLength}`, + 'SyntaxError' + ) + } + } + + // 3. Run the first matching steps from the following list: + if (this[kReadyState] === WebSocket.CLOSING || this[kReadyState] === WebSocket.CLOSED) { + // If this's ready state is CLOSING (2) or CLOSED (3) + // Do nothing. + } else if (!isEstablished(this)) { + // If the WebSocket connection is not yet established + // Fail the WebSocket connection and set this's ready state + // to CLOSING (2). + failWebsocketConnection(this, 'Connection was closed before it was established.') + this[kReadyState] = WebSocket.CLOSING + } else if (!isClosing(this)) { + // If the WebSocket closing handshake has not yet been started + // Start the WebSocket closing handshake and set this's ready + // state to CLOSING (2). + // - If neither code nor reason is present, the WebSocket Close + // message must not have a body. + // - If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + // - If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + + const frame = new WebsocketFrameSend() + + // If neither code nor reason is present, the WebSocket Close + // message must not have a body. + + // If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + if (code !== undefined && reason === undefined) { + frame.frameData = Buffer.allocUnsafe(2) + frame.frameData.writeUInt16BE(code, 0) + } else if (code !== undefined && reason !== undefined) { + // If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength) + frame.frameData.writeUInt16BE(code, 0) + // the body MAY contain UTF-8-encoded data with value /reason/ + frame.frameData.write(reason, 2, 'utf-8') + } else { + frame.frameData = emptyBuffer + } + + /** @type {import('stream').Duplex} */ + const socket = this[kResponse].socket + + socket.write(frame.createFrame(opcodes.CLOSE), (err) => { + if (!err) { + this[kSentClose] = true + } + }) + + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this[kReadyState] = states.CLOSING + } else { + // Otherwise + // Set this's ready state to CLOSING (2). + this[kReadyState] = WebSocket.CLOSING + } + } + + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-send + * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + */ + send (data) { + webidl.brandCheck(this, WebSocket) + + webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket.send' }) + + data = webidl.converters.WebSocketSendData(data) + + // 1. If this's ready state is CONNECTING, then throw an + // "InvalidStateError" DOMException. + if (this[kReadyState] === WebSocket.CONNECTING) { + throw new DOMException('Sent before connected.', 'InvalidStateError') + } + + // 2. Run the appropriate set of steps from the following list: + // https://datatracker.ietf.org/doc/html/rfc6455#section-6.1 + // https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 + + if (!isEstablished(this) || isClosing(this)) { + return + } + + /** @type {import('stream').Duplex} */ + const socket = this[kResponse].socket + + // If data is a string + if (typeof data === 'string') { + // If the WebSocket connection is established and the WebSocket + // closing handshake has not yet started, then the user agent + // must send a WebSocket Message comprised of the data argument + // using a text frame opcode; if the data cannot be sent, e.g. + // because it would need to be buffered but the buffer is full, + // the user agent must flag the WebSocket as full and then close + // the WebSocket connection. Any invocation of this method with a + // string argument that does not throw an exception must increase + // the bufferedAmount attribute by the number of bytes needed to + // express the argument as UTF-8. + + const value = Buffer.from(data) + const frame = new WebsocketFrameSend(value) + const buffer = frame.createFrame(opcodes.TEXT) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + } else if (types.isArrayBuffer(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need + // to be buffered but the buffer is full, the user agent must flag + // the WebSocket as full and then close the WebSocket connection. + // The data to be sent is the data stored in the buffer described + // by the ArrayBuffer object. Any invocation of this method with an + // ArrayBuffer argument that does not throw an exception must + // increase the bufferedAmount attribute by the length of the + // ArrayBuffer in bytes. + + const value = Buffer.from(data) + const frame = new WebsocketFrameSend(value) + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + } else if (ArrayBuffer.isView(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The + // data to be sent is the data stored in the section of the buffer + // described by the ArrayBuffer object that data references. Any + // invocation of this method with this kind of argument that does + // not throw an exception must increase the bufferedAmount attribute + // by the length of data’s buffer in bytes. + + const ab = Buffer.from(data, data.byteOffset, data.byteLength) + + const frame = new WebsocketFrameSend(ab) + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += ab.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= ab.byteLength + }) + } else if (isBlobLike(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The data + // to be sent is the raw data represented by the Blob object. Any + // invocation of this method with a Blob argument that does not throw + // an exception must increase the bufferedAmount attribute by the size + // of the Blob object’s raw data, in bytes. + + const frame = new WebsocketFrameSend() + + data.arrayBuffer().then((ab) => { + const value = Buffer.from(ab) + frame.frameData = value + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + }) + } + } + + get readyState () { + webidl.brandCheck(this, WebSocket) + + // The readyState getter steps are to return this's ready state. + return this[kReadyState] + } + + get bufferedAmount () { + webidl.brandCheck(this, WebSocket) + + return this.#bufferedAmount + } + + get url () { + webidl.brandCheck(this, WebSocket) + + // The url getter steps are to return this's url, serialized. + return URLSerializer(this[kWebSocketURL]) + } + + get extensions () { + webidl.brandCheck(this, WebSocket) + + return this.#extensions + } + + get protocol () { + webidl.brandCheck(this, WebSocket) + + return this.#protocol + } + + get onopen () { + webidl.brandCheck(this, WebSocket) + + return this.#events.open + } + + set onopen (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.open) { + this.removeEventListener('open', this.#events.open) + } + + if (typeof fn === 'function') { + this.#events.open = fn + this.addEventListener('open', fn) + } else { + this.#events.open = null + } + } + + get onerror () { + webidl.brandCheck(this, WebSocket) + + return this.#events.error + } + + set onerror (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.error) { + this.removeEventListener('error', this.#events.error) + } + + if (typeof fn === 'function') { + this.#events.error = fn + this.addEventListener('error', fn) + } else { + this.#events.error = null + } + } + + get onclose () { + webidl.brandCheck(this, WebSocket) + + return this.#events.close + } + + set onclose (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.close) { + this.removeEventListener('close', this.#events.close) + } + + if (typeof fn === 'function') { + this.#events.close = fn + this.addEventListener('close', fn) + } else { + this.#events.close = null + } + } + + get onmessage () { + webidl.brandCheck(this, WebSocket) + + return this.#events.message + } + + set onmessage (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.message) { + this.removeEventListener('message', this.#events.message) + } + + if (typeof fn === 'function') { + this.#events.message = fn + this.addEventListener('message', fn) + } else { + this.#events.message = null + } + } + + get binaryType () { + webidl.brandCheck(this, WebSocket) + + return this[kBinaryType] + } + + set binaryType (type) { + webidl.brandCheck(this, WebSocket) + + if (type !== 'blob' && type !== 'arraybuffer') { + this[kBinaryType] = 'blob' + } else { + this[kBinaryType] = type + } + } + + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + */ + #onConnectionEstablished (response) { + // processResponse is called when the "response’s header list has been received and initialized." + // once this happens, the connection is open + this[kResponse] = response + + const parser = new ByteParser(this) + parser.on('drain', function onParserDrain () { + this.ws[kResponse].socket.resume() + }) + + response.socket.ws = this + this[kByteParser] = parser + + // 1. Change the ready state to OPEN (1). + this[kReadyState] = states.OPEN + + // 2. Change the extensions attribute’s value to the extensions in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 + const extensions = response.headersList.get('sec-websocket-extensions') + + if (extensions !== null) { + this.#extensions = extensions + } + + // 3. Change the protocol attribute’s value to the subprotocol in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-1.9 + const protocol = response.headersList.get('sec-websocket-protocol') + + if (protocol !== null) { + this.#protocol = protocol + } + + // 4. Fire an event named open at the WebSocket object. + fireEvent('open', this) + } +} + +// https://websockets.spec.whatwg.org/#dom-websocket-connecting +WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING +// https://websockets.spec.whatwg.org/#dom-websocket-open +WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN +// https://websockets.spec.whatwg.org/#dom-websocket-closing +WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING +// https://websockets.spec.whatwg.org/#dom-websocket-closed +WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED + +Object.defineProperties(WebSocket.prototype, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors, + url: kEnumerableProperty, + readyState: kEnumerableProperty, + bufferedAmount: kEnumerableProperty, + onopen: kEnumerableProperty, + onerror: kEnumerableProperty, + onclose: kEnumerableProperty, + close: kEnumerableProperty, + onmessage: kEnumerableProperty, + binaryType: kEnumerableProperty, + send: kEnumerableProperty, + extensions: kEnumerableProperty, + protocol: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'WebSocket', + writable: false, + enumerable: false, + configurable: true + } +}) + +Object.defineProperties(WebSocket, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors +}) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.DOMString +) + +webidl.converters['DOMString or sequence'] = function (V) { + if (webidl.util.Type(V) === 'Object' && Symbol.iterator in V) { + return webidl.converters['sequence'](V) + } + + return webidl.converters.DOMString(V) +} + +// This implements the propsal made in https://github.com/whatwg/websockets/issues/42 +webidl.converters.WebSocketInit = webidl.dictionaryConverter([ + { + key: 'protocols', + converter: webidl.converters['DOMString or sequence'], + get defaultValue () { + return [] + } + }, + { + key: 'dispatcher', + converter: (V) => V, + get defaultValue () { + return getGlobalDispatcher() + } + }, + { + key: 'headers', + converter: webidl.nullableConverter(webidl.converters.HeadersInit) + } +]) + +webidl.converters['DOMString or sequence or WebSocketInit'] = function (V) { + if (webidl.util.Type(V) === 'Object' && !(Symbol.iterator in V)) { + return webidl.converters.WebSocketInit(V) + } + + return { protocols: webidl.converters['DOMString or sequence'](V) } +} + +webidl.converters.WebSocketSendData = function (V) { + if (webidl.util.Type(V) === 'Object') { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { + return webidl.converters.BufferSource(V) + } + } + + return webidl.converters.USVString(V) +} + +module.exports = { + WebSocket +} + + +/***/ }), + +/***/ 24488: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + +/** + * For Node.js, simply re-export the core `util.deprecate` function. + */ + +module.exports = __nccwpck_require__(39023).deprecate; + + +/***/ }), + +/***/ 12048: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(6415)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(51697)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(4676)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(69771)); + +var _nil = _interopRequireDefault(__nccwpck_require__(37723)); + +var _version = _interopRequireDefault(__nccwpck_require__(15868)); + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(37597)); + +var _parse = _interopRequireDefault(__nccwpck_require__(17267)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 10216: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 54221: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _default = { + randomUUID: _crypto.default.randomUUID +}; +exports["default"] = _default; + +/***/ }), + +/***/ 37723: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 17267: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 67879: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 12973: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 507: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 37597: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +exports.unsafeStringify = unsafeStringify; + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).slice(1)); +} + +function unsafeStringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; +} + +function stringify(arr, offset = 0) { + const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 6415: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(12973)); + +var _stringify = __nccwpck_require__(37597); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.unsafeStringify)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 51697: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(92930)); + +var _md = _interopRequireDefault(__nccwpck_require__(10216)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 92930: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports.URL = exports.DNS = void 0; +exports["default"] = v35; + +var _stringify = __nccwpck_require__(37597); + +var _parse = _interopRequireDefault(__nccwpck_require__(17267)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function v35(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + var _namespace; + + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (((_namespace = namespace) === null || _namespace === void 0 ? void 0 : _namespace.length) !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.unsafeStringify)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 4676: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _native = _interopRequireDefault(__nccwpck_require__(54221)); + +var _rng = _interopRequireDefault(__nccwpck_require__(12973)); + +var _stringify = __nccwpck_require__(37597); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + if (_native.default.randomUUID && !buf && !options) { + return _native.default.randomUUID(); + } + + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.unsafeStringify)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 69771: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(92930)); + +var _sha = _interopRequireDefault(__nccwpck_require__(507)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 36200: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(67879)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 15868: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.slice(14, 15), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 37125: +/***/ ((module) => { + +"use strict"; + + +var conversions = {}; +module.exports = conversions; + +function sign(x) { + return x < 0 ? -1 : 1; +} + +function evenRound(x) { + // Round x to the nearest integer, choosing the even integer if it lies halfway between two. + if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor) + return Math.floor(x); + } else { + return Math.round(x); + } +} + +function createNumberConversion(bitLength, typeOpts) { + if (!typeOpts.unsigned) { + --bitLength; + } + const lowerBound = typeOpts.unsigned ? 0 : -Math.pow(2, bitLength); + const upperBound = Math.pow(2, bitLength) - 1; + + const moduloVal = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength) : Math.pow(2, bitLength); + const moduloBound = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength - 1) : Math.pow(2, bitLength - 1); + + return function(V, opts) { + if (!opts) opts = {}; + + let x = +V; + + if (opts.enforceRange) { + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite number"); + } + + x = sign(x) * Math.floor(Math.abs(x)); + if (x < lowerBound || x > upperBound) { + throw new TypeError("Argument is not in byte range"); + } + + return x; + } + + if (!isNaN(x) && opts.clamp) { + x = evenRound(x); + + if (x < lowerBound) x = lowerBound; + if (x > upperBound) x = upperBound; + return x; + } + + if (!Number.isFinite(x) || x === 0) { + return 0; + } + + x = sign(x) * Math.floor(Math.abs(x)); + x = x % moduloVal; + + if (!typeOpts.unsigned && x >= moduloBound) { + return x - moduloVal; + } else if (typeOpts.unsigned) { + if (x < 0) { + x += moduloVal; + } else if (x === -0) { // don't return negative zero + return 0; + } + } + + return x; + } +} + +conversions["void"] = function () { + return undefined; +}; + +conversions["boolean"] = function (val) { + return !!val; +}; + +conversions["byte"] = createNumberConversion(8, { unsigned: false }); +conversions["octet"] = createNumberConversion(8, { unsigned: true }); + +conversions["short"] = createNumberConversion(16, { unsigned: false }); +conversions["unsigned short"] = createNumberConversion(16, { unsigned: true }); + +conversions["long"] = createNumberConversion(32, { unsigned: false }); +conversions["unsigned long"] = createNumberConversion(32, { unsigned: true }); + +conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 }); +conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 }); + +conversions["double"] = function (V) { + const x = +V; + + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite floating-point value"); + } + + return x; +}; + +conversions["unrestricted double"] = function (V) { + const x = +V; + + if (isNaN(x)) { + throw new TypeError("Argument is NaN"); + } + + return x; +}; + +// not quite valid, but good enough for JS +conversions["float"] = conversions["double"]; +conversions["unrestricted float"] = conversions["unrestricted double"]; + +conversions["DOMString"] = function (V, opts) { + if (!opts) opts = {}; + + if (opts.treatNullAsEmptyString && V === null) { + return ""; + } + + return String(V); +}; + +conversions["ByteString"] = function (V, opts) { + const x = String(V); + let c = undefined; + for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) { + if (c > 255) { + throw new TypeError("Argument is not a valid bytestring"); + } + } + + return x; +}; + +conversions["USVString"] = function (V) { + const S = String(V); + const n = S.length; + const U = []; + for (let i = 0; i < n; ++i) { + const c = S.charCodeAt(i); + if (c < 0xD800 || c > 0xDFFF) { + U.push(String.fromCodePoint(c)); + } else if (0xDC00 <= c && c <= 0xDFFF) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + if (i === n - 1) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + const d = S.charCodeAt(i + 1); + if (0xDC00 <= d && d <= 0xDFFF) { + const a = c & 0x3FF; + const b = d & 0x3FF; + U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b)); + ++i; + } else { + U.push(String.fromCodePoint(0xFFFD)); + } + } + } + } + + return U.join(''); +}; + +conversions["Date"] = function (V, opts) { + if (!(V instanceof Date)) { + throw new TypeError("Argument is not a Date object"); + } + if (isNaN(V)) { + return undefined; + } + + return V; +}; + +conversions["RegExp"] = function (V, opts) { + if (!(V instanceof RegExp)) { + V = new RegExp(V); + } + + return V; +}; + + +/***/ }), + +/***/ 23184: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +const usm = __nccwpck_require__(20905); + +exports.implementation = class URLImpl { + constructor(constructorArgs) { + const url = constructorArgs[0]; + const base = constructorArgs[1]; + + let parsedBase = null; + if (base !== undefined) { + parsedBase = usm.basicURLParse(base); + if (parsedBase === "failure") { + throw new TypeError("Invalid base URL"); + } + } + + const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase }); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + + // TODO: query stuff + } + + get href() { + return usm.serializeURL(this._url); + } + + set href(v) { + const parsedURL = usm.basicURLParse(v); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + } + + get origin() { + return usm.serializeURLOrigin(this._url); + } + + get protocol() { + return this._url.scheme + ":"; + } + + set protocol(v) { + usm.basicURLParse(v + ":", { url: this._url, stateOverride: "scheme start" }); + } + + get username() { + return this._url.username; + } + + set username(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setTheUsername(this._url, v); + } + + get password() { + return this._url.password; + } + + set password(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setThePassword(this._url, v); + } + + get host() { + const url = this._url; + + if (url.host === null) { + return ""; + } + + if (url.port === null) { + return usm.serializeHost(url.host); + } + + return usm.serializeHost(url.host) + ":" + usm.serializeInteger(url.port); + } + + set host(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "host" }); + } + + get hostname() { + if (this._url.host === null) { + return ""; + } + + return usm.serializeHost(this._url.host); + } + + set hostname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "hostname" }); + } + + get port() { + if (this._url.port === null) { + return ""; + } + + return usm.serializeInteger(this._url.port); + } + + set port(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + if (v === "") { + this._url.port = null; + } else { + usm.basicURLParse(v, { url: this._url, stateOverride: "port" }); + } + } + + get pathname() { + if (this._url.cannotBeABaseURL) { + return this._url.path[0]; + } + + if (this._url.path.length === 0) { + return ""; + } + + return "/" + this._url.path.join("/"); + } + + set pathname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + this._url.path = []; + usm.basicURLParse(v, { url: this._url, stateOverride: "path start" }); + } + + get search() { + if (this._url.query === null || this._url.query === "") { + return ""; + } + + return "?" + this._url.query; + } + + set search(v) { + // TODO: query stuff + + const url = this._url; + + if (v === "") { + url.query = null; + return; + } + + const input = v[0] === "?" ? v.substring(1) : v; + url.query = ""; + usm.basicURLParse(input, { url, stateOverride: "query" }); + } + + get hash() { + if (this._url.fragment === null || this._url.fragment === "") { + return ""; + } + + return "#" + this._url.fragment; + } + + set hash(v) { + if (v === "") { + this._url.fragment = null; + return; + } + + const input = v[0] === "#" ? v.substring(1) : v; + this._url.fragment = ""; + usm.basicURLParse(input, { url: this._url, stateOverride: "fragment" }); + } + + toJSON() { + return this.href; + } +}; + + +/***/ }), + +/***/ 66633: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const conversions = __nccwpck_require__(37125); +const utils = __nccwpck_require__(39857); +const Impl = __nccwpck_require__(23184); + +const impl = utils.implSymbol; + +function URL(url) { + if (!this || this[impl] || !(this instanceof URL)) { + throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function."); + } + if (arguments.length < 1) { + throw new TypeError("Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present."); + } + const args = []; + for (let i = 0; i < arguments.length && i < 2; ++i) { + args[i] = arguments[i]; + } + args[0] = conversions["USVString"](args[0]); + if (args[1] !== undefined) { + args[1] = conversions["USVString"](args[1]); + } + + module.exports.setup(this, args); +} + +URL.prototype.toJSON = function toJSON() { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + const args = []; + for (let i = 0; i < arguments.length && i < 0; ++i) { + args[i] = arguments[i]; + } + return this[impl].toJSON.apply(this[impl], args); +}; +Object.defineProperty(URL.prototype, "href", { + get() { + return this[impl].href; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].href = V; + }, + enumerable: true, + configurable: true +}); + +URL.prototype.toString = function () { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + return this.href; +}; + +Object.defineProperty(URL.prototype, "origin", { + get() { + return this[impl].origin; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "protocol", { + get() { + return this[impl].protocol; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].protocol = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "username", { + get() { + return this[impl].username; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].username = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "password", { + get() { + return this[impl].password; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].password = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "host", { + get() { + return this[impl].host; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].host = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hostname", { + get() { + return this[impl].hostname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hostname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "port", { + get() { + return this[impl].port; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].port = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "pathname", { + get() { + return this[impl].pathname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].pathname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "search", { + get() { + return this[impl].search; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].search = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hash", { + get() { + return this[impl].hash; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hash = V; + }, + enumerable: true, + configurable: true +}); + + +module.exports = { + is(obj) { + return !!obj && obj[impl] instanceof Impl.implementation; + }, + create(constructorArgs, privateData) { + let obj = Object.create(URL.prototype); + this.setup(obj, constructorArgs, privateData); + return obj; + }, + setup(obj, constructorArgs, privateData) { + if (!privateData) privateData = {}; + privateData.wrapper = obj; + + obj[impl] = new Impl.implementation(constructorArgs, privateData); + obj[impl][utils.wrapperSymbol] = obj; + }, + interface: URL, + expose: { + Window: { URL: URL }, + Worker: { URL: URL } + } +}; + + + +/***/ }), + +/***/ 62686: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +exports.URL = __nccwpck_require__(66633)["interface"]; +exports.serializeURL = __nccwpck_require__(20905).serializeURL; +exports.serializeURLOrigin = __nccwpck_require__(20905).serializeURLOrigin; +exports.basicURLParse = __nccwpck_require__(20905).basicURLParse; +exports.setTheUsername = __nccwpck_require__(20905).setTheUsername; +exports.setThePassword = __nccwpck_require__(20905).setThePassword; +exports.serializeHost = __nccwpck_require__(20905).serializeHost; +exports.serializeInteger = __nccwpck_require__(20905).serializeInteger; +exports.parseURL = __nccwpck_require__(20905).parseURL; + + +/***/ }), + +/***/ 20905: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const punycode = __nccwpck_require__(24876); +const tr46 = __nccwpck_require__(1552); + +const specialSchemes = { + ftp: 21, + file: null, + gopher: 70, + http: 80, + https: 443, + ws: 80, + wss: 443 +}; + +const failure = Symbol("failure"); + +function countSymbols(str) { + return punycode.ucs2.decode(str).length; +} + +function at(input, idx) { + const c = input[idx]; + return isNaN(c) ? undefined : String.fromCodePoint(c); +} + +function isASCIIDigit(c) { + return c >= 0x30 && c <= 0x39; +} + +function isASCIIAlpha(c) { + return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); +} + +function isASCIIAlphanumeric(c) { + return isASCIIAlpha(c) || isASCIIDigit(c); +} + +function isASCIIHex(c) { + return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); +} + +function isSingleDot(buffer) { + return buffer === "." || buffer.toLowerCase() === "%2e"; +} + +function isDoubleDot(buffer) { + buffer = buffer.toLowerCase(); + return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; +} + +function isWindowsDriveLetterCodePoints(cp1, cp2) { + return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124); +} + +function isWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|"); +} + +function isNormalizedWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":"; +} + +function containsForbiddenHostCodePoint(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function containsForbiddenHostCodePointExcludingPercent(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function isSpecialScheme(scheme) { + return specialSchemes[scheme] !== undefined; +} + +function isSpecial(url) { + return isSpecialScheme(url.scheme); +} + +function defaultPort(scheme) { + return specialSchemes[scheme]; +} + +function percentEncode(c) { + let hex = c.toString(16).toUpperCase(); + if (hex.length === 1) { + hex = "0" + hex; + } + + return "%" + hex; +} + +function utf8PercentEncode(c) { + const buf = new Buffer(c); + + let str = ""; + + for (let i = 0; i < buf.length; ++i) { + str += percentEncode(buf[i]); + } + + return str; +} + +function utf8PercentDecode(str) { + const input = new Buffer(str); + const output = []; + for (let i = 0; i < input.length; ++i) { + if (input[i] !== 37) { + output.push(input[i]); + } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { + output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); + i += 2; + } else { + output.push(input[i]); + } + } + return new Buffer(output).toString(); +} + +function isC0ControlPercentEncode(c) { + return c <= 0x1F || c > 0x7E; +} + +const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]); +function isPathPercentEncode(c) { + return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c); +} + +const extraUserinfoPercentEncodeSet = + new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]); +function isUserinfoPercentEncode(c) { + return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c); +} + +function percentEncodeChar(c, encodeSetPredicate) { + const cStr = String.fromCodePoint(c); + + if (encodeSetPredicate(c)) { + return utf8PercentEncode(cStr); + } + + return cStr; +} + +function parseIPv4Number(input) { + let R = 10; + + if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") { + input = input.substring(2); + R = 16; + } else if (input.length >= 2 && input.charAt(0) === "0") { + input = input.substring(1); + R = 8; + } + + if (input === "") { + return 0; + } + + const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/); + if (regex.test(input)) { + return failure; + } + + return parseInt(input, R); +} + +function parseIPv4(input) { + const parts = input.split("."); + if (parts[parts.length - 1] === "") { + if (parts.length > 1) { + parts.pop(); + } + } + + if (parts.length > 4) { + return input; + } + + const numbers = []; + for (const part of parts) { + if (part === "") { + return input; + } + const n = parseIPv4Number(part); + if (n === failure) { + return input; + } + + numbers.push(n); + } + + for (let i = 0; i < numbers.length - 1; ++i) { + if (numbers[i] > 255) { + return failure; + } + } + if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { + return failure; + } + + let ipv4 = numbers.pop(); + let counter = 0; + + for (const n of numbers) { + ipv4 += n * Math.pow(256, 3 - counter); + ++counter; + } + + return ipv4; +} + +function serializeIPv4(address) { + let output = ""; + let n = address; + + for (let i = 1; i <= 4; ++i) { + output = String(n % 256) + output; + if (i !== 4) { + output = "." + output; + } + n = Math.floor(n / 256); + } + + return output; +} + +function parseIPv6(input) { + const address = [0, 0, 0, 0, 0, 0, 0, 0]; + let pieceIndex = 0; + let compress = null; + let pointer = 0; + + input = punycode.ucs2.decode(input); + + if (input[pointer] === 58) { + if (input[pointer + 1] !== 58) { + return failure; + } + + pointer += 2; + ++pieceIndex; + compress = pieceIndex; + } + + while (pointer < input.length) { + if (pieceIndex === 8) { + return failure; + } + + if (input[pointer] === 58) { + if (compress !== null) { + return failure; + } + ++pointer; + ++pieceIndex; + compress = pieceIndex; + continue; + } + + let value = 0; + let length = 0; + + while (length < 4 && isASCIIHex(input[pointer])) { + value = value * 0x10 + parseInt(at(input, pointer), 16); + ++pointer; + ++length; + } + + if (input[pointer] === 46) { + if (length === 0) { + return failure; + } + + pointer -= length; + + if (pieceIndex > 6) { + return failure; + } + + let numbersSeen = 0; + + while (input[pointer] !== undefined) { + let ipv4Piece = null; + + if (numbersSeen > 0) { + if (input[pointer] === 46 && numbersSeen < 4) { + ++pointer; + } else { + return failure; + } + } + + if (!isASCIIDigit(input[pointer])) { + return failure; + } + + while (isASCIIDigit(input[pointer])) { + const number = parseInt(at(input, pointer)); + if (ipv4Piece === null) { + ipv4Piece = number; + } else if (ipv4Piece === 0) { + return failure; + } else { + ipv4Piece = ipv4Piece * 10 + number; + } + if (ipv4Piece > 255) { + return failure; + } + ++pointer; + } + + address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece; + + ++numbersSeen; + + if (numbersSeen === 2 || numbersSeen === 4) { + ++pieceIndex; + } + } + + if (numbersSeen !== 4) { + return failure; + } + + break; + } else if (input[pointer] === 58) { + ++pointer; + if (input[pointer] === undefined) { + return failure; + } + } else if (input[pointer] !== undefined) { + return failure; + } + + address[pieceIndex] = value; + ++pieceIndex; + } + + if (compress !== null) { + let swaps = pieceIndex - compress; + pieceIndex = 7; + while (pieceIndex !== 0 && swaps > 0) { + const temp = address[compress + swaps - 1]; + address[compress + swaps - 1] = address[pieceIndex]; + address[pieceIndex] = temp; + --pieceIndex; + --swaps; + } + } else if (compress === null && pieceIndex !== 8) { + return failure; + } + + return address; +} + +function serializeIPv6(address) { + let output = ""; + const seqResult = findLongestZeroSequence(address); + const compress = seqResult.idx; + let ignore0 = false; + + for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) { + if (ignore0 && address[pieceIndex] === 0) { + continue; + } else if (ignore0) { + ignore0 = false; + } + + if (compress === pieceIndex) { + const separator = pieceIndex === 0 ? "::" : ":"; + output += separator; + ignore0 = true; + continue; + } + + output += address[pieceIndex].toString(16); + + if (pieceIndex !== 7) { + output += ":"; + } + } + + return output; +} + +function parseHost(input, isSpecialArg) { + if (input[0] === "[") { + if (input[input.length - 1] !== "]") { + return failure; + } + + return parseIPv6(input.substring(1, input.length - 1)); + } + + if (!isSpecialArg) { + return parseOpaqueHost(input); + } + + const domain = utf8PercentDecode(input); + const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false); + if (asciiDomain === null) { + return failure; + } + + if (containsForbiddenHostCodePoint(asciiDomain)) { + return failure; + } + + const ipv4Host = parseIPv4(asciiDomain); + if (typeof ipv4Host === "number" || ipv4Host === failure) { + return ipv4Host; + } + + return asciiDomain; +} + +function parseOpaqueHost(input) { + if (containsForbiddenHostCodePointExcludingPercent(input)) { + return failure; + } + + let output = ""; + const decoded = punycode.ucs2.decode(input); + for (let i = 0; i < decoded.length; ++i) { + output += percentEncodeChar(decoded[i], isC0ControlPercentEncode); + } + return output; +} + +function findLongestZeroSequence(arr) { + let maxIdx = null; + let maxLen = 1; // only find elements > 1 + let currStart = null; + let currLen = 0; + + for (let i = 0; i < arr.length; ++i) { + if (arr[i] !== 0) { + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + currStart = null; + currLen = 0; + } else { + if (currStart === null) { + currStart = i; + } + ++currLen; + } + } + + // if trailing zeros + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + return { + idx: maxIdx, + len: maxLen + }; +} + +function serializeHost(host) { + if (typeof host === "number") { + return serializeIPv4(host); + } + + // IPv6 serializer + if (host instanceof Array) { + return "[" + serializeIPv6(host) + "]"; + } + + return host; +} + +function trimControlChars(url) { + return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, ""); +} + +function trimTabAndNewline(url) { + return url.replace(/\u0009|\u000A|\u000D/g, ""); +} + +function shortenPath(url) { + const path = url.path; + if (path.length === 0) { + return; + } + if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) { + return; + } + + path.pop(); +} + +function includesCredentials(url) { + return url.username !== "" || url.password !== ""; +} + +function cannotHaveAUsernamePasswordPort(url) { + return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file"; +} + +function isNormalizedWindowsDriveLetter(string) { + return /^[A-Za-z]:$/.test(string); +} + +function URLStateMachine(input, base, encodingOverride, url, stateOverride) { + this.pointer = 0; + this.input = input; + this.base = base || null; + this.encodingOverride = encodingOverride || "utf-8"; + this.stateOverride = stateOverride; + this.url = url; + this.failure = false; + this.parseError = false; + + if (!this.url) { + this.url = { + scheme: "", + username: "", + password: "", + host: null, + port: null, + path: [], + query: null, + fragment: null, + + cannotBeABaseURL: false + }; + + const res = trimControlChars(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + } + + const res = trimTabAndNewline(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + + this.state = stateOverride || "scheme start"; + + this.buffer = ""; + this.atFlag = false; + this.arrFlag = false; + this.passwordTokenSeenFlag = false; + + this.input = punycode.ucs2.decode(this.input); + + for (; this.pointer <= this.input.length; ++this.pointer) { + const c = this.input[this.pointer]; + const cStr = isNaN(c) ? undefined : String.fromCodePoint(c); + + // exec state machine + const ret = this["parse " + this.state](c, cStr); + if (!ret) { + break; // terminate algorithm + } else if (ret === failure) { + this.failure = true; + break; + } + } +} + +URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) { + if (isASCIIAlpha(c)) { + this.buffer += cStr.toLowerCase(); + this.state = "scheme"; + } else if (!this.stateOverride) { + this.state = "no scheme"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) { + if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) { + this.buffer += cStr.toLowerCase(); + } else if (c === 58) { + if (this.stateOverride) { + if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) { + return false; + } + + if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) { + return false; + } + + if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") { + return false; + } + + if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) { + return false; + } + } + this.url.scheme = this.buffer; + this.buffer = ""; + if (this.stateOverride) { + return false; + } + if (this.url.scheme === "file") { + if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) { + this.parseError = true; + } + this.state = "file"; + } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) { + this.state = "special relative or authority"; + } else if (isSpecial(this.url)) { + this.state = "special authority slashes"; + } else if (this.input[this.pointer + 1] === 47) { + this.state = "path or authority"; + ++this.pointer; + } else { + this.url.cannotBeABaseURL = true; + this.url.path.push(""); + this.state = "cannot-be-a-base-URL path"; + } + } else if (!this.stateOverride) { + this.buffer = ""; + this.state = "no scheme"; + this.pointer = -1; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) { + if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) { + return failure; + } else if (this.base.cannotBeABaseURL && c === 35) { + this.url.scheme = this.base.scheme; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.url.cannotBeABaseURL = true; + this.state = "fragment"; + } else if (this.base.scheme === "file") { + this.state = "file"; + --this.pointer; + } else { + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) { + if (c === 47) { + this.state = "authority"; + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative"] = function parseRelative(c) { + this.url.scheme = this.base.scheme; + if (isNaN(c)) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 47) { + this.state = "relative slash"; + } else if (c === 63) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else if (isSpecial(this.url) && c === 92) { + this.parseError = true; + this.state = "relative slash"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(0, this.base.path.length - 1); + + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) { + if (isSpecial(this.url) && (c === 47 || c === 92)) { + if (c === 92) { + this.parseError = true; + } + this.state = "special authority ignore slashes"; + } else if (c === 47) { + this.state = "authority"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "special authority ignore slashes"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) { + if (c !== 47 && c !== 92) { + this.state = "authority"; + --this.pointer; + } else { + this.parseError = true; + } + + return true; +}; + +URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) { + if (c === 64) { + this.parseError = true; + if (this.atFlag) { + this.buffer = "%40" + this.buffer; + } + this.atFlag = true; + + // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars + const len = countSymbols(this.buffer); + for (let pointer = 0; pointer < len; ++pointer) { + const codePoint = this.buffer.codePointAt(pointer); + + if (codePoint === 58 && !this.passwordTokenSeenFlag) { + this.passwordTokenSeenFlag = true; + continue; + } + const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode); + if (this.passwordTokenSeenFlag) { + this.url.password += encodedCodePoints; + } else { + this.url.username += encodedCodePoints; + } + } + this.buffer = ""; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + if (this.atFlag && this.buffer === "") { + this.parseError = true; + return failure; + } + this.pointer -= countSymbols(this.buffer) + 1; + this.buffer = ""; + this.state = "host"; + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse hostname"] = +URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { + if (this.stateOverride && this.url.scheme === "file") { + --this.pointer; + this.state = "file host"; + } else if (c === 58 && !this.arrFlag) { + if (this.buffer === "") { + this.parseError = true; + return failure; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "port"; + if (this.stateOverride === "hostname") { + return false; + } + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + --this.pointer; + if (isSpecial(this.url) && this.buffer === "") { + this.parseError = true; + return failure; + } else if (this.stateOverride && this.buffer === "" && + (includesCredentials(this.url) || this.url.port !== null)) { + this.parseError = true; + return false; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "path start"; + if (this.stateOverride) { + return false; + } + } else { + if (c === 91) { + this.arrFlag = true; + } else if (c === 93) { + this.arrFlag = false; + } + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) { + if (isASCIIDigit(c)) { + this.buffer += cStr; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92) || + this.stateOverride) { + if (this.buffer !== "") { + const port = parseInt(this.buffer); + if (port > Math.pow(2, 16) - 1) { + this.parseError = true; + return failure; + } + this.url.port = port === defaultPort(this.url.scheme) ? null : port; + this.buffer = ""; + } + if (this.stateOverride) { + return false; + } + this.state = "path start"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]); + +URLStateMachine.prototype["parse file"] = function parseFile(c) { + this.url.scheme = "file"; + + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file slash"; + } else if (this.base !== null && this.base.scheme === "file") { + if (isNaN(c)) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 63) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else { + if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points + !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) || + (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points + !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + shortenPath(this.url); + } else { + this.parseError = true; + } + + this.state = "path"; + --this.pointer; + } + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) { + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file host"; + } else { + if (this.base !== null && this.base.scheme === "file") { + if (isNormalizedWindowsDriveLetterString(this.base.path[0])) { + this.url.path.push(this.base.path[0]); + } else { + this.url.host = this.base.host; + } + } + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) { + if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { + --this.pointer; + if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) { + this.parseError = true; + this.state = "path"; + } else if (this.buffer === "") { + this.url.host = ""; + if (this.stateOverride) { + return false; + } + this.state = "path start"; + } else { + let host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + if (host === "localhost") { + host = ""; + } + this.url.host = host; + + if (this.stateOverride) { + return false; + } + + this.buffer = ""; + this.state = "path start"; + } + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse path start"] = function parsePathStart(c) { + if (isSpecial(this.url)) { + if (c === 92) { + this.parseError = true; + } + this.state = "path"; + + if (c !== 47 && c !== 92) { + --this.pointer; + } + } else if (!this.stateOverride && c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (!this.stateOverride && c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else if (c !== undefined) { + this.state = "path"; + if (c !== 47) { + --this.pointer; + } + } + + return true; +}; + +URLStateMachine.prototype["parse path"] = function parsePath(c) { + if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) || + (!this.stateOverride && (c === 63 || c === 35))) { + if (isSpecial(this.url) && c === 92) { + this.parseError = true; + } + + if (isDoubleDot(this.buffer)) { + shortenPath(this.url); + if (c !== 47 && !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } + } else if (isSingleDot(this.buffer) && c !== 47 && + !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } else if (!isSingleDot(this.buffer)) { + if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) { + if (this.url.host !== "" && this.url.host !== null) { + this.parseError = true; + this.url.host = ""; + } + this.buffer = this.buffer[0] + ":"; + } + this.url.path.push(this.buffer); + } + this.buffer = ""; + if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) { + while (this.url.path.length > 1 && this.url.path[0] === "") { + this.parseError = true; + this.url.path.shift(); + } + } + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += percentEncodeChar(c, isPathPercentEncode); + } + + return true; +}; + +URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) { + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else { + // TODO: Add: not a URL code point + if (!isNaN(c) && c !== 37) { + this.parseError = true; + } + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + if (!isNaN(c)) { + this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode); + } + } + + return true; +}; + +URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) { + if (isNaN(c) || (!this.stateOverride && c === 35)) { + if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") { + this.encodingOverride = "utf-8"; + } + + const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead + for (let i = 0; i < buffer.length; ++i) { + if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 || + buffer[i] === 0x3C || buffer[i] === 0x3E) { + this.url.query += percentEncode(buffer[i]); + } else { + this.url.query += String.fromCodePoint(buffer[i]); + } + } + + this.buffer = ""; + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse fragment"] = function parseFragment(c) { + if (isNaN(c)) { // do nothing + } else if (c === 0x0) { + this.parseError = true; + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode); + } + + return true; +}; + +function serializeURL(url, excludeFragment) { + let output = url.scheme + ":"; + if (url.host !== null) { + output += "//"; + + if (url.username !== "" || url.password !== "") { + output += url.username; + if (url.password !== "") { + output += ":" + url.password; + } + output += "@"; + } + + output += serializeHost(url.host); + + if (url.port !== null) { + output += ":" + url.port; + } + } else if (url.host === null && url.scheme === "file") { + output += "//"; + } + + if (url.cannotBeABaseURL) { + output += url.path[0]; + } else { + for (const string of url.path) { + output += "/" + string; + } + } + + if (url.query !== null) { + output += "?" + url.query; + } + + if (!excludeFragment && url.fragment !== null) { + output += "#" + url.fragment; + } + + return output; +} + +function serializeOrigin(tuple) { + let result = tuple.scheme + "://"; + result += serializeHost(tuple.host); + + if (tuple.port !== null) { + result += ":" + tuple.port; + } + + return result; +} + +module.exports.serializeURL = serializeURL; + +module.exports.serializeURLOrigin = function (url) { + // https://url.spec.whatwg.org/#concept-url-origin + switch (url.scheme) { + case "blob": + try { + return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0])); + } catch (e) { + // serializing an opaque origin returns "null" + return "null"; + } + case "ftp": + case "gopher": + case "http": + case "https": + case "ws": + case "wss": + return serializeOrigin({ + scheme: url.scheme, + host: url.host, + port: url.port + }); + case "file": + // spec says "exercise to the reader", chrome says "file://" + return "file://"; + default: + // serializing an opaque origin returns "null" + return "null"; + } +}; + +module.exports.basicURLParse = function (input, options) { + if (options === undefined) { + options = {}; + } + + const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride); + if (usm.failure) { + return "failure"; + } + + return usm.url; +}; + +module.exports.setTheUsername = function (url, username) { + url.username = ""; + const decoded = punycode.ucs2.decode(username); + for (let i = 0; i < decoded.length; ++i) { + url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.setThePassword = function (url, password) { + url.password = ""; + const decoded = punycode.ucs2.decode(password); + for (let i = 0; i < decoded.length; ++i) { + url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.serializeHost = serializeHost; + +module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort; + +module.exports.serializeInteger = function (integer) { + return String(integer); +}; + +module.exports.parseURL = function (input, options) { + if (options === undefined) { + options = {}; + } + + // We don't handle blobs, so this just delegates: + return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); +}; + + +/***/ }), + +/***/ 39857: +/***/ ((module) => { + +"use strict"; + + +module.exports.mixin = function mixin(target, source) { + const keys = Object.getOwnPropertyNames(source); + for (let i = 0; i < keys.length; ++i) { + Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i])); + } +}; + +module.exports.wrapperSymbol = Symbol("wrapper"); +module.exports.implSymbol = Symbol("impl"); + +module.exports.wrapperForImpl = function (impl) { + return impl[module.exports.wrapperSymbol]; +}; + +module.exports.implForWrapper = function (wrapper) { + return wrapper[module.exports.implSymbol]; +}; + + + +/***/ }), + +/***/ 58264: +/***/ ((module) => { + +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + + +/***/ }), + +/***/ 30538: +/***/ ((module) => { + +class Node { + /// value; + /// next; + + constructor(value) { + this.value = value; + + // TODO: Remove this when targeting Node.js 12. + this.next = undefined; + } +} + +class Queue { + // TODO: Use private class fields when targeting Node.js 12. + // #_head; + // #_tail; + // #_size; + + constructor() { + this.clear(); + } + + enqueue(value) { + const node = new Node(value); + + if (this._head) { + this._tail.next = node; + this._tail = node; + } else { + this._head = node; + this._tail = node; + } + + this._size++; + } + + dequeue() { + const current = this._head; + if (!current) { + return; + } + + this._head = this._head.next; + this._size--; + return current.value; + } + + clear() { + this._head = undefined; + this._tail = undefined; + this._size = 0; + } + + get size() { + return this._size; + } + + * [Symbol.iterator]() { + let current = this._head; + + while (current) { + yield current.value; + current = current.next; + } + } +} + +module.exports = Queue; + + +/***/ }), + +/***/ 42078: +/***/ ((module) => { + +module.exports = eval("require")("encoding"); + + +/***/ }), + +/***/ 60075: +/***/ ((module) => { + +module.exports = eval("require")("supports-color"); + + +/***/ }), + +/***/ 42613: +/***/ ((module) => { + +"use strict"; +module.exports = require("assert"); + +/***/ }), + +/***/ 90290: +/***/ ((module) => { + +"use strict"; +module.exports = require("async_hooks"); + +/***/ }), + +/***/ 20181: +/***/ ((module) => { + +"use strict"; +module.exports = require("buffer"); + +/***/ }), + +/***/ 35317: +/***/ ((module) => { + +"use strict"; +module.exports = require("child_process"); + +/***/ }), + +/***/ 64236: +/***/ ((module) => { + +"use strict"; +module.exports = require("console"); + +/***/ }), + +/***/ 76982: +/***/ ((module) => { + +"use strict"; +module.exports = require("crypto"); + +/***/ }), + +/***/ 31637: +/***/ ((module) => { + +"use strict"; +module.exports = require("diagnostics_channel"); + +/***/ }), + +/***/ 24434: +/***/ ((module) => { + +"use strict"; +module.exports = require("events"); + +/***/ }), + +/***/ 79896: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs"); + +/***/ }), + +/***/ 91943: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs/promises"); + +/***/ }), + +/***/ 58611: +/***/ ((module) => { + +"use strict"; +module.exports = require("http"); + +/***/ }), + +/***/ 85675: +/***/ ((module) => { + +"use strict"; +module.exports = require("http2"); + +/***/ }), + +/***/ 65692: +/***/ ((module) => { + +"use strict"; +module.exports = require("https"); + +/***/ }), + +/***/ 69278: +/***/ ((module) => { + +"use strict"; +module.exports = require("net"); + +/***/ }), + +/***/ 77598: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:crypto"); + +/***/ }), + +/***/ 78474: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:events"); + +/***/ }), + +/***/ 1708: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:process"); + +/***/ }), + +/***/ 57075: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:stream"); + +/***/ }), + +/***/ 57975: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:util"); + +/***/ }), + +/***/ 70857: +/***/ ((module) => { + +"use strict"; +module.exports = require("os"); + +/***/ }), + +/***/ 16928: +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ 82987: +/***/ ((module) => { + +"use strict"; +module.exports = require("perf_hooks"); + +/***/ }), + +/***/ 932: +/***/ ((module) => { + +"use strict"; +module.exports = require("process"); + +/***/ }), + +/***/ 24876: +/***/ ((module) => { + +"use strict"; +module.exports = require("punycode"); + +/***/ }), + +/***/ 83480: +/***/ ((module) => { + +"use strict"; +module.exports = require("querystring"); + +/***/ }), + +/***/ 2203: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream"); + +/***/ }), + +/***/ 63774: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream/web"); + +/***/ }), + +/***/ 13193: +/***/ ((module) => { + +"use strict"; +module.exports = require("string_decoder"); + +/***/ }), + +/***/ 53557: +/***/ ((module) => { + +"use strict"; +module.exports = require("timers"); + +/***/ }), + +/***/ 64756: +/***/ ((module) => { + +"use strict"; +module.exports = require("tls"); + +/***/ }), + +/***/ 52018: +/***/ ((module) => { + +"use strict"; +module.exports = require("tty"); + +/***/ }), + +/***/ 87016: +/***/ ((module) => { + +"use strict"; +module.exports = require("url"); + +/***/ }), + +/***/ 39023: +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }), + +/***/ 98253: +/***/ ((module) => { + +"use strict"; +module.exports = require("util/types"); + +/***/ }), + +/***/ 28167: +/***/ ((module) => { + +"use strict"; +module.exports = require("worker_threads"); + +/***/ }), + +/***/ 43106: +/***/ ((module) => { + +"use strict"; +module.exports = require("zlib"); + +/***/ }), + +/***/ 27182: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const WritableStream = (__nccwpck_require__(57075).Writable) +const inherits = (__nccwpck_require__(57975).inherits) + +const StreamSearch = __nccwpck_require__(84136) + +const PartStream = __nccwpck_require__(50612) +const HeaderParser = __nccwpck_require__(62271) + +const DASH = 45 +const B_ONEDASH = Buffer.from('-') +const B_CRLF = Buffer.from('\r\n') +const EMPTY_FN = function () {} + +function Dicer (cfg) { + if (!(this instanceof Dicer)) { return new Dicer(cfg) } + WritableStream.call(this, cfg) + + if (!cfg || (!cfg.headerFirst && typeof cfg.boundary !== 'string')) { throw new TypeError('Boundary required') } + + if (typeof cfg.boundary === 'string') { this.setBoundary(cfg.boundary) } else { this._bparser = undefined } + + this._headerFirst = cfg.headerFirst + + this._dashes = 0 + this._parts = 0 + this._finished = false + this._realFinish = false + this._isPreamble = true + this._justMatched = false + this._firstWrite = true + this._inHeader = true + this._part = undefined + this._cb = undefined + this._ignoreData = false + this._partOpts = { highWaterMark: cfg.partHwm } + this._pause = false + + const self = this + this._hparser = new HeaderParser(cfg) + this._hparser.on('header', function (header) { + self._inHeader = false + self._part.emit('header', header) + }) +} +inherits(Dicer, WritableStream) + +Dicer.prototype.emit = function (ev) { + if (ev === 'finish' && !this._realFinish) { + if (!this._finished) { + const self = this + process.nextTick(function () { + self.emit('error', new Error('Unexpected end of multipart data')) + if (self._part && !self._ignoreData) { + const type = (self._isPreamble ? 'Preamble' : 'Part') + self._part.emit('error', new Error(type + ' terminated early due to unexpected end of multipart data')) + self._part.push(null) + process.nextTick(function () { + self._realFinish = true + self.emit('finish') + self._realFinish = false + }) + return + } + self._realFinish = true + self.emit('finish') + self._realFinish = false + }) + } + } else { WritableStream.prototype.emit.apply(this, arguments) } +} + +Dicer.prototype._write = function (data, encoding, cb) { + // ignore unexpected data (e.g. extra trailer data after finished) + if (!this._hparser && !this._bparser) { return cb() } + + if (this._headerFirst && this._isPreamble) { + if (!this._part) { + this._part = new PartStream(this._partOpts) + if (this.listenerCount('preamble') !== 0) { this.emit('preamble', this._part) } else { this._ignore() } + } + const r = this._hparser.push(data) + if (!this._inHeader && r !== undefined && r < data.length) { data = data.slice(r) } else { return cb() } + } + + // allows for "easier" testing + if (this._firstWrite) { + this._bparser.push(B_CRLF) + this._firstWrite = false + } + + this._bparser.push(data) + + if (this._pause) { this._cb = cb } else { cb() } +} + +Dicer.prototype.reset = function () { + this._part = undefined + this._bparser = undefined + this._hparser = undefined +} + +Dicer.prototype.setBoundary = function (boundary) { + const self = this + this._bparser = new StreamSearch('\r\n--' + boundary) + this._bparser.on('info', function (isMatch, data, start, end) { + self._oninfo(isMatch, data, start, end) + }) +} + +Dicer.prototype._ignore = function () { + if (this._part && !this._ignoreData) { + this._ignoreData = true + this._part.on('error', EMPTY_FN) + // we must perform some kind of read on the stream even though we are + // ignoring the data, otherwise node's Readable stream will not emit 'end' + // after pushing null to the stream + this._part.resume() + } +} + +Dicer.prototype._oninfo = function (isMatch, data, start, end) { + let buf; const self = this; let i = 0; let r; let shouldWriteMore = true + + if (!this._part && this._justMatched && data) { + while (this._dashes < 2 && (start + i) < end) { + if (data[start + i] === DASH) { + ++i + ++this._dashes + } else { + if (this._dashes) { buf = B_ONEDASH } + this._dashes = 0 + break + } + } + if (this._dashes === 2) { + if ((start + i) < end && this.listenerCount('trailer') !== 0) { this.emit('trailer', data.slice(start + i, end)) } + this.reset() + this._finished = true + // no more parts will be added + if (self._parts === 0) { + self._realFinish = true + self.emit('finish') + self._realFinish = false + } + } + if (this._dashes) { return } + } + if (this._justMatched) { this._justMatched = false } + if (!this._part) { + this._part = new PartStream(this._partOpts) + this._part._read = function (n) { + self._unpause() + } + if (this._isPreamble && this.listenerCount('preamble') !== 0) { + this.emit('preamble', this._part) + } else if (this._isPreamble !== true && this.listenerCount('part') !== 0) { + this.emit('part', this._part) + } else { + this._ignore() + } + if (!this._isPreamble) { this._inHeader = true } + } + if (data && start < end && !this._ignoreData) { + if (this._isPreamble || !this._inHeader) { + if (buf) { shouldWriteMore = this._part.push(buf) } + shouldWriteMore = this._part.push(data.slice(start, end)) + if (!shouldWriteMore) { this._pause = true } + } else if (!this._isPreamble && this._inHeader) { + if (buf) { this._hparser.push(buf) } + r = this._hparser.push(data.slice(start, end)) + if (!this._inHeader && r !== undefined && r < end) { this._oninfo(false, data, start + r, end) } + } + } + if (isMatch) { + this._hparser.reset() + if (this._isPreamble) { this._isPreamble = false } else { + if (start !== end) { + ++this._parts + this._part.on('end', function () { + if (--self._parts === 0) { + if (self._finished) { + self._realFinish = true + self.emit('finish') + self._realFinish = false + } else { + self._unpause() + } + } + }) + } + } + this._part.push(null) + this._part = undefined + this._ignoreData = false + this._justMatched = true + this._dashes = 0 + } +} + +Dicer.prototype._unpause = function () { + if (!this._pause) { return } + + this._pause = false + if (this._cb) { + const cb = this._cb + this._cb = undefined + cb() + } +} + +module.exports = Dicer + + +/***/ }), + +/***/ 62271: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const EventEmitter = (__nccwpck_require__(78474).EventEmitter) +const inherits = (__nccwpck_require__(57975).inherits) +const getLimit = __nccwpck_require__(22393) + +const StreamSearch = __nccwpck_require__(84136) + +const B_DCRLF = Buffer.from('\r\n\r\n') +const RE_CRLF = /\r\n/g +const RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/ // eslint-disable-line no-control-regex + +function HeaderParser (cfg) { + EventEmitter.call(this) + + cfg = cfg || {} + const self = this + this.nread = 0 + this.maxed = false + this.npairs = 0 + this.maxHeaderPairs = getLimit(cfg, 'maxHeaderPairs', 2000) + this.maxHeaderSize = getLimit(cfg, 'maxHeaderSize', 80 * 1024) + this.buffer = '' + this.header = {} + this.finished = false + this.ss = new StreamSearch(B_DCRLF) + this.ss.on('info', function (isMatch, data, start, end) { + if (data && !self.maxed) { + if (self.nread + end - start >= self.maxHeaderSize) { + end = self.maxHeaderSize - self.nread + start + self.nread = self.maxHeaderSize + self.maxed = true + } else { self.nread += (end - start) } + + self.buffer += data.toString('binary', start, end) + } + if (isMatch) { self._finish() } + }) +} +inherits(HeaderParser, EventEmitter) + +HeaderParser.prototype.push = function (data) { + const r = this.ss.push(data) + if (this.finished) { return r } +} + +HeaderParser.prototype.reset = function () { + this.finished = false + this.buffer = '' + this.header = {} + this.ss.reset() +} + +HeaderParser.prototype._finish = function () { + if (this.buffer) { this._parseHeader() } + this.ss.matches = this.ss.maxMatches + const header = this.header + this.header = {} + this.buffer = '' + this.finished = true + this.nread = this.npairs = 0 + this.maxed = false + this.emit('header', header) +} + +HeaderParser.prototype._parseHeader = function () { + if (this.npairs === this.maxHeaderPairs) { return } + + const lines = this.buffer.split(RE_CRLF) + const len = lines.length + let m, h + + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + if (lines[i].length === 0) { continue } + if (lines[i][0] === '\t' || lines[i][0] === ' ') { + // folded header content + // RFC2822 says to just remove the CRLF and not the whitespace following + // it, so we follow the RFC and include the leading whitespace ... + if (h) { + this.header[h][this.header[h].length - 1] += lines[i] + continue + } + } + + const posColon = lines[i].indexOf(':') + if ( + posColon === -1 || + posColon === 0 + ) { + return + } + m = RE_HDR.exec(lines[i]) + h = m[1].toLowerCase() + this.header[h] = this.header[h] || [] + this.header[h].push((m[2] || '')) + if (++this.npairs === this.maxHeaderPairs) { break } + } +} + +module.exports = HeaderParser + + +/***/ }), + +/***/ 50612: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const inherits = (__nccwpck_require__(57975).inherits) +const ReadableStream = (__nccwpck_require__(57075).Readable) + +function PartStream (opts) { + ReadableStream.call(this, opts) +} +inherits(PartStream, ReadableStream) + +PartStream.prototype._read = function (n) {} + +module.exports = PartStream + + +/***/ }), + +/***/ 84136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +/** + * Copyright Brian White. All rights reserved. + * + * @see https://github.com/mscdex/streamsearch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation + * by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool + */ +const EventEmitter = (__nccwpck_require__(78474).EventEmitter) +const inherits = (__nccwpck_require__(57975).inherits) + +function SBMH (needle) { + if (typeof needle === 'string') { + needle = Buffer.from(needle) + } + + if (!Buffer.isBuffer(needle)) { + throw new TypeError('The needle has to be a String or a Buffer.') + } + + const needleLength = needle.length + + if (needleLength === 0) { + throw new Error('The needle cannot be an empty String/Buffer.') + } + + if (needleLength > 256) { + throw new Error('The needle cannot have a length bigger than 256.') + } + + this.maxMatches = Infinity + this.matches = 0 + + this._occ = new Array(256) + .fill(needleLength) // Initialize occurrence table. + this._lookbehind_size = 0 + this._needle = needle + this._bufpos = 0 + + this._lookbehind = Buffer.alloc(needleLength) + + // Populate occurrence table with analysis of the needle, + // ignoring last letter. + for (var i = 0; i < needleLength - 1; ++i) { // eslint-disable-line no-var + this._occ[needle[i]] = needleLength - 1 - i + } +} +inherits(SBMH, EventEmitter) + +SBMH.prototype.reset = function () { + this._lookbehind_size = 0 + this.matches = 0 + this._bufpos = 0 +} + +SBMH.prototype.push = function (chunk, pos) { + if (!Buffer.isBuffer(chunk)) { + chunk = Buffer.from(chunk, 'binary') + } + const chlen = chunk.length + this._bufpos = pos || 0 + let r + while (r !== chlen && this.matches < this.maxMatches) { r = this._sbmh_feed(chunk) } + return r +} + +SBMH.prototype._sbmh_feed = function (data) { + const len = data.length + const needle = this._needle + const needleLength = needle.length + const lastNeedleChar = needle[needleLength - 1] + + // Positive: points to a position in `data` + // pos == 3 points to data[3] + // Negative: points to a position in the lookbehind buffer + // pos == -2 points to lookbehind[lookbehind_size - 2] + let pos = -this._lookbehind_size + let ch + + if (pos < 0) { + // Lookbehind buffer is not empty. Perform Boyer-Moore-Horspool + // search with character lookup code that considers both the + // lookbehind buffer and the current round's haystack data. + // + // Loop until + // there is a match. + // or until + // we've moved past the position that requires the + // lookbehind buffer. In this case we switch to the + // optimized loop. + // or until + // the character to look at lies outside the haystack. + while (pos < 0 && pos <= len - needleLength) { + ch = this._sbmh_lookup_char(data, pos + needleLength - 1) + + if ( + ch === lastNeedleChar && + this._sbmh_memcmp(data, pos, needleLength - 1) + ) { + this._lookbehind_size = 0 + ++this.matches + this.emit('info', true) + + return (this._bufpos = pos + needleLength) + } + pos += this._occ[ch] + } + + // No match. + + if (pos < 0) { + // There's too few data for Boyer-Moore-Horspool to run, + // so let's use a different algorithm to skip as much as + // we can. + // Forward pos until + // the trailing part of lookbehind + data + // looks like the beginning of the needle + // or until + // pos == 0 + while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) { ++pos } + } + + if (pos >= 0) { + // Discard lookbehind buffer. + this.emit('info', false, this._lookbehind, 0, this._lookbehind_size) + this._lookbehind_size = 0 + } else { + // Cut off part of the lookbehind buffer that has + // been processed and append the entire haystack + // into it. + const bytesToCutOff = this._lookbehind_size + pos + if (bytesToCutOff > 0) { + // The cut off data is guaranteed not to contain the needle. + this.emit('info', false, this._lookbehind, 0, bytesToCutOff) + } + + this._lookbehind.copy(this._lookbehind, 0, bytesToCutOff, + this._lookbehind_size - bytesToCutOff) + this._lookbehind_size -= bytesToCutOff + + data.copy(this._lookbehind, this._lookbehind_size) + this._lookbehind_size += len + + this._bufpos = len + return len + } + } + + pos += (pos >= 0) * this._bufpos + + // Lookbehind buffer is now empty. We only need to check if the + // needle is in the haystack. + if (data.indexOf(needle, pos) !== -1) { + pos = data.indexOf(needle, pos) + ++this.matches + if (pos > 0) { this.emit('info', true, data, this._bufpos, pos) } else { this.emit('info', true) } + + return (this._bufpos = pos + needleLength) + } else { + pos = len - needleLength + } + + // There was no match. If there's trailing haystack data that we cannot + // match yet using the Boyer-Moore-Horspool algorithm (because the trailing + // data is less than the needle size) then match using a modified + // algorithm that starts matching from the beginning instead of the end. + // Whatever trailing data is left after running this algorithm is added to + // the lookbehind buffer. + while ( + pos < len && + ( + data[pos] !== needle[0] || + ( + (Buffer.compare( + data.subarray(pos, pos + len - pos), + needle.subarray(0, len - pos) + ) !== 0) + ) + ) + ) { + ++pos + } + if (pos < len) { + data.copy(this._lookbehind, 0, pos, pos + (len - pos)) + this._lookbehind_size = len - pos + } + + // Everything until pos is guaranteed not to contain needle data. + if (pos > 0) { this.emit('info', false, data, this._bufpos, pos < len ? pos : len) } + + this._bufpos = len + return len +} + +SBMH.prototype._sbmh_lookup_char = function (data, pos) { + return (pos < 0) + ? this._lookbehind[this._lookbehind_size + pos] + : data[pos] +} + +SBMH.prototype._sbmh_memcmp = function (data, pos, len) { + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + if (this._sbmh_lookup_char(data, pos + i) !== this._needle[i]) { return false } + } + return true +} + +module.exports = SBMH + + +/***/ }), + +/***/ 89581: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const WritableStream = (__nccwpck_require__(57075).Writable) +const { inherits } = __nccwpck_require__(57975) +const Dicer = __nccwpck_require__(27182) + +const MultipartParser = __nccwpck_require__(41192) +const UrlencodedParser = __nccwpck_require__(80855) +const parseParams = __nccwpck_require__(8929) + +function Busboy (opts) { + if (!(this instanceof Busboy)) { return new Busboy(opts) } + + if (typeof opts !== 'object') { + throw new TypeError('Busboy expected an options-Object.') + } + if (typeof opts.headers !== 'object') { + throw new TypeError('Busboy expected an options-Object with headers-attribute.') + } + if (typeof opts.headers['content-type'] !== 'string') { + throw new TypeError('Missing Content-Type-header.') + } + + const { + headers, + ...streamOptions + } = opts + + this.opts = { + autoDestroy: false, + ...streamOptions + } + WritableStream.call(this, this.opts) + + this._done = false + this._parser = this.getParserByHeaders(headers) + this._finished = false +} +inherits(Busboy, WritableStream) + +Busboy.prototype.emit = function (ev) { + if (ev === 'finish') { + if (!this._done) { + this._parser?.end() + return + } else if (this._finished) { + return + } + this._finished = true + } + WritableStream.prototype.emit.apply(this, arguments) +} + +Busboy.prototype.getParserByHeaders = function (headers) { + const parsed = parseParams(headers['content-type']) + + const cfg = { + defCharset: this.opts.defCharset, + fileHwm: this.opts.fileHwm, + headers, + highWaterMark: this.opts.highWaterMark, + isPartAFile: this.opts.isPartAFile, + limits: this.opts.limits, + parsedConType: parsed, + preservePath: this.opts.preservePath + } + + if (MultipartParser.detect.test(parsed[0])) { + return new MultipartParser(this, cfg) + } + if (UrlencodedParser.detect.test(parsed[0])) { + return new UrlencodedParser(this, cfg) + } + throw new Error('Unsupported Content-Type.') +} + +Busboy.prototype._write = function (chunk, encoding, cb) { + this._parser.write(chunk, cb) +} + +module.exports = Busboy +module.exports["default"] = Busboy +module.exports.Busboy = Busboy + +module.exports.Dicer = Dicer + + +/***/ }), + +/***/ 41192: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +// TODO: +// * support 1 nested multipart level +// (see second multipart example here: +// http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data) +// * support limits.fieldNameSize +// -- this will require modifications to utils.parseParams + +const { Readable } = __nccwpck_require__(57075) +const { inherits } = __nccwpck_require__(57975) + +const Dicer = __nccwpck_require__(27182) + +const parseParams = __nccwpck_require__(8929) +const decodeText = __nccwpck_require__(72747) +const basename = __nccwpck_require__(20692) +const getLimit = __nccwpck_require__(22393) + +const RE_BOUNDARY = /^boundary$/i +const RE_FIELD = /^form-data$/i +const RE_CHARSET = /^charset$/i +const RE_FILENAME = /^filename$/i +const RE_NAME = /^name$/i + +Multipart.detect = /^multipart\/form-data/i +function Multipart (boy, cfg) { + let i + let len + const self = this + let boundary + const limits = cfg.limits + const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined)) + const parsedConType = cfg.parsedConType || [] + const defCharset = cfg.defCharset || 'utf8' + const preservePath = cfg.preservePath + const fileOpts = { highWaterMark: cfg.fileHwm } + + for (i = 0, len = parsedConType.length; i < len; ++i) { + if (Array.isArray(parsedConType[i]) && + RE_BOUNDARY.test(parsedConType[i][0])) { + boundary = parsedConType[i][1] + break + } + } + + function checkFinished () { + if (nends === 0 && finished && !boy._done) { + finished = false + self.end() + } + } + + if (typeof boundary !== 'string') { throw new Error('Multipart: Boundary not found') } + + const fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) + const fileSizeLimit = getLimit(limits, 'fileSize', Infinity) + const filesLimit = getLimit(limits, 'files', Infinity) + const fieldsLimit = getLimit(limits, 'fields', Infinity) + const partsLimit = getLimit(limits, 'parts', Infinity) + const headerPairsLimit = getLimit(limits, 'headerPairs', 2000) + const headerSizeLimit = getLimit(limits, 'headerSize', 80 * 1024) + + let nfiles = 0 + let nfields = 0 + let nends = 0 + let curFile + let curField + let finished = false + + this._needDrain = false + this._pause = false + this._cb = undefined + this._nparts = 0 + this._boy = boy + + const parserCfg = { + boundary, + maxHeaderPairs: headerPairsLimit, + maxHeaderSize: headerSizeLimit, + partHwm: fileOpts.highWaterMark, + highWaterMark: cfg.highWaterMark + } + + this.parser = new Dicer(parserCfg) + this.parser.on('drain', function () { + self._needDrain = false + if (self._cb && !self._pause) { + const cb = self._cb + self._cb = undefined + cb() + } + }).on('part', function onPart (part) { + if (++self._nparts > partsLimit) { + self.parser.removeListener('part', onPart) + self.parser.on('part', skipPart) + boy.hitPartsLimit = true + boy.emit('partsLimit') + return skipPart(part) + } + + // hack because streams2 _always_ doesn't emit 'end' until nextTick, so let + // us emit 'end' early since we know the part has ended if we are already + // seeing the next part + if (curField) { + const field = curField + field.emit('end') + field.removeAllListeners('end') + } + + part.on('header', function (header) { + let contype + let fieldname + let parsed + let charset + let encoding + let filename + let nsize = 0 + + if (header['content-type']) { + parsed = parseParams(header['content-type'][0]) + if (parsed[0]) { + contype = parsed[0].toLowerCase() + for (i = 0, len = parsed.length; i < len; ++i) { + if (RE_CHARSET.test(parsed[i][0])) { + charset = parsed[i][1].toLowerCase() + break + } + } + } + } + + if (contype === undefined) { contype = 'text/plain' } + if (charset === undefined) { charset = defCharset } + + if (header['content-disposition']) { + parsed = parseParams(header['content-disposition'][0]) + if (!RE_FIELD.test(parsed[0])) { return skipPart(part) } + for (i = 0, len = parsed.length; i < len; ++i) { + if (RE_NAME.test(parsed[i][0])) { + fieldname = parsed[i][1] + } else if (RE_FILENAME.test(parsed[i][0])) { + filename = parsed[i][1] + if (!preservePath) { filename = basename(filename) } + } + } + } else { return skipPart(part) } + + if (header['content-transfer-encoding']) { encoding = header['content-transfer-encoding'][0].toLowerCase() } else { encoding = '7bit' } + + let onData, + onEnd + + if (isPartAFile(fieldname, contype, filename)) { + // file/binary field + if (nfiles === filesLimit) { + if (!boy.hitFilesLimit) { + boy.hitFilesLimit = true + boy.emit('filesLimit') + } + return skipPart(part) + } + + ++nfiles + + if (boy.listenerCount('file') === 0) { + self.parser._ignore() + return + } + + ++nends + const file = new FileStream(fileOpts) + curFile = file + file.on('end', function () { + --nends + self._pause = false + checkFinished() + if (self._cb && !self._needDrain) { + const cb = self._cb + self._cb = undefined + cb() + } + }) + file._read = function (n) { + if (!self._pause) { return } + self._pause = false + if (self._cb && !self._needDrain) { + const cb = self._cb + self._cb = undefined + cb() + } + } + boy.emit('file', fieldname, file, filename, encoding, contype) + + onData = function (data) { + if ((nsize += data.length) > fileSizeLimit) { + const extralen = fileSizeLimit - nsize + data.length + if (extralen > 0) { file.push(data.slice(0, extralen)) } + file.truncated = true + file.bytesRead = fileSizeLimit + part.removeAllListeners('data') + file.emit('limit') + return + } else if (!file.push(data)) { self._pause = true } + + file.bytesRead = nsize + } + + onEnd = function () { + curFile = undefined + file.push(null) + } + } else { + // non-file field + if (nfields === fieldsLimit) { + if (!boy.hitFieldsLimit) { + boy.hitFieldsLimit = true + boy.emit('fieldsLimit') + } + return skipPart(part) + } + + ++nfields + ++nends + let buffer = '' + let truncated = false + curField = part + + onData = function (data) { + if ((nsize += data.length) > fieldSizeLimit) { + const extralen = (fieldSizeLimit - (nsize - data.length)) + buffer += data.toString('binary', 0, extralen) + truncated = true + part.removeAllListeners('data') + } else { buffer += data.toString('binary') } + } + + onEnd = function () { + curField = undefined + if (buffer.length) { buffer = decodeText(buffer, 'binary', charset) } + boy.emit('field', fieldname, buffer, false, truncated, encoding, contype) + --nends + checkFinished() + } + } + + /* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become + broken. Streams2/streams3 is a huge black box of confusion, but + somehow overriding the sync state seems to fix things again (and still + seems to work for previous node versions). + */ + part._readableState.sync = false + + part.on('data', onData) + part.on('end', onEnd) + }).on('error', function (err) { + if (curFile) { curFile.emit('error', err) } + }) + }).on('error', function (err) { + boy.emit('error', err) + }).on('finish', function () { + finished = true + checkFinished() + }) +} + +Multipart.prototype.write = function (chunk, cb) { + const r = this.parser.write(chunk) + if (r && !this._pause) { + cb() + } else { + this._needDrain = !r + this._cb = cb + } +} + +Multipart.prototype.end = function () { + const self = this + + if (self.parser.writable) { + self.parser.end() + } else if (!self._boy._done) { + process.nextTick(function () { + self._boy._done = true + self._boy.emit('finish') + }) + } +} + +function skipPart (part) { + part.resume() +} + +function FileStream (opts) { + Readable.call(this, opts) + + this.bytesRead = 0 + + this.truncated = false +} + +inherits(FileStream, Readable) + +FileStream.prototype._read = function (n) {} + +module.exports = Multipart + + +/***/ }), + +/***/ 80855: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Decoder = __nccwpck_require__(11496) +const decodeText = __nccwpck_require__(72747) +const getLimit = __nccwpck_require__(22393) + +const RE_CHARSET = /^charset$/i + +UrlEncoded.detect = /^application\/x-www-form-urlencoded/i +function UrlEncoded (boy, cfg) { + const limits = cfg.limits + const parsedConType = cfg.parsedConType + this.boy = boy + + this.fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) + this.fieldNameSizeLimit = getLimit(limits, 'fieldNameSize', 100) + this.fieldsLimit = getLimit(limits, 'fields', Infinity) + + let charset + for (var i = 0, len = parsedConType.length; i < len; ++i) { // eslint-disable-line no-var + if (Array.isArray(parsedConType[i]) && + RE_CHARSET.test(parsedConType[i][0])) { + charset = parsedConType[i][1].toLowerCase() + break + } + } + + if (charset === undefined) { charset = cfg.defCharset || 'utf8' } + + this.decoder = new Decoder() + this.charset = charset + this._fields = 0 + this._state = 'key' + this._checkingBytes = true + this._bytesKey = 0 + this._bytesVal = 0 + this._key = '' + this._val = '' + this._keyTrunc = false + this._valTrunc = false + this._hitLimit = false +} + +UrlEncoded.prototype.write = function (data, cb) { + if (this._fields === this.fieldsLimit) { + if (!this.boy.hitFieldsLimit) { + this.boy.hitFieldsLimit = true + this.boy.emit('fieldsLimit') + } + return cb() + } + + let idxeq; let idxamp; let i; let p = 0; const len = data.length + + while (p < len) { + if (this._state === 'key') { + idxeq = idxamp = undefined + for (i = p; i < len; ++i) { + if (!this._checkingBytes) { ++p } + if (data[i] === 0x3D/* = */) { + idxeq = i + break + } else if (data[i] === 0x26/* & */) { + idxamp = i + break + } + if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) { + this._hitLimit = true + break + } else if (this._checkingBytes) { ++this._bytesKey } + } + + if (idxeq !== undefined) { + // key with assignment + if (idxeq > p) { this._key += this.decoder.write(data.toString('binary', p, idxeq)) } + this._state = 'val' + + this._hitLimit = false + this._checkingBytes = true + this._val = '' + this._bytesVal = 0 + this._valTrunc = false + this.decoder.reset() + + p = idxeq + 1 + } else if (idxamp !== undefined) { + // key with no assignment + ++this._fields + let key; const keyTrunc = this._keyTrunc + if (idxamp > p) { key = (this._key += this.decoder.write(data.toString('binary', p, idxamp))) } else { key = this._key } + + this._hitLimit = false + this._checkingBytes = true + this._key = '' + this._bytesKey = 0 + this._keyTrunc = false + this.decoder.reset() + + if (key.length) { + this.boy.emit('field', decodeText(key, 'binary', this.charset), + '', + keyTrunc, + false) + } + + p = idxamp + 1 + if (this._fields === this.fieldsLimit) { return cb() } + } else if (this._hitLimit) { + // we may not have hit the actual limit if there are encoded bytes... + if (i > p) { this._key += this.decoder.write(data.toString('binary', p, i)) } + p = i + if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) { + // yep, we actually did hit the limit + this._checkingBytes = false + this._keyTrunc = true + } + } else { + if (p < len) { this._key += this.decoder.write(data.toString('binary', p)) } + p = len + } + } else { + idxamp = undefined + for (i = p; i < len; ++i) { + if (!this._checkingBytes) { ++p } + if (data[i] === 0x26/* & */) { + idxamp = i + break + } + if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) { + this._hitLimit = true + break + } else if (this._checkingBytes) { ++this._bytesVal } + } + + if (idxamp !== undefined) { + ++this._fields + if (idxamp > p) { this._val += this.decoder.write(data.toString('binary', p, idxamp)) } + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + decodeText(this._val, 'binary', this.charset), + this._keyTrunc, + this._valTrunc) + this._state = 'key' + + this._hitLimit = false + this._checkingBytes = true + this._key = '' + this._bytesKey = 0 + this._keyTrunc = false + this.decoder.reset() + + p = idxamp + 1 + if (this._fields === this.fieldsLimit) { return cb() } + } else if (this._hitLimit) { + // we may not have hit the actual limit if there are encoded bytes... + if (i > p) { this._val += this.decoder.write(data.toString('binary', p, i)) } + p = i + if ((this._val === '' && this.fieldSizeLimit === 0) || + (this._bytesVal = this._val.length) === this.fieldSizeLimit) { + // yep, we actually did hit the limit + this._checkingBytes = false + this._valTrunc = true + } + } else { + if (p < len) { this._val += this.decoder.write(data.toString('binary', p)) } + p = len + } + } + } + cb() +} + +UrlEncoded.prototype.end = function () { + if (this.boy._done) { return } + + if (this._state === 'key' && this._key.length > 0) { + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + '', + this._keyTrunc, + false) + } else if (this._state === 'val') { + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + decodeText(this._val, 'binary', this.charset), + this._keyTrunc, + this._valTrunc) + } + this.boy._done = true + this.boy.emit('finish') +} + +module.exports = UrlEncoded + + +/***/ }), + +/***/ 11496: +/***/ ((module) => { + +"use strict"; + + +const RE_PLUS = /\+/g + +const HEX = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +] + +function Decoder () { + this.buffer = undefined +} +Decoder.prototype.write = function (str) { + // Replace '+' with ' ' before decoding + str = str.replace(RE_PLUS, ' ') + let res = '' + let i = 0; let p = 0; const len = str.length + for (; i < len; ++i) { + if (this.buffer !== undefined) { + if (!HEX[str.charCodeAt(i)]) { + res += '%' + this.buffer + this.buffer = undefined + --i // retry character + } else { + this.buffer += str[i] + ++p + if (this.buffer.length === 2) { + res += String.fromCharCode(parseInt(this.buffer, 16)) + this.buffer = undefined + } + } + } else if (str[i] === '%') { + if (i > p) { + res += str.substring(p, i) + p = i + } + this.buffer = '' + ++p + } + } + if (p < len && this.buffer === undefined) { res += str.substring(p) } + return res +} +Decoder.prototype.reset = function () { + this.buffer = undefined +} + +module.exports = Decoder + + +/***/ }), + +/***/ 20692: +/***/ ((module) => { + +"use strict"; + + +module.exports = function basename (path) { + if (typeof path !== 'string') { return '' } + for (var i = path.length - 1; i >= 0; --i) { // eslint-disable-line no-var + switch (path.charCodeAt(i)) { + case 0x2F: // '/' + case 0x5C: // '\' + path = path.slice(i + 1) + return (path === '..' || path === '.' ? '' : path) + } + } + return (path === '..' || path === '.' ? '' : path) +} + + +/***/ }), + +/***/ 72747: +/***/ (function(module) { + +"use strict"; + + +// Node has always utf-8 +const utf8Decoder = new TextDecoder('utf-8') +const textDecoders = new Map([ + ['utf-8', utf8Decoder], + ['utf8', utf8Decoder] +]) + +function getDecoder (charset) { + let lc + while (true) { + switch (charset) { + case 'utf-8': + case 'utf8': + return decoders.utf8 + case 'latin1': + case 'ascii': // TODO: Make these a separate, strict decoder? + case 'us-ascii': + case 'iso-8859-1': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'windows-1252': + case 'iso_8859-1:1987': + case 'cp1252': + case 'x-cp1252': + return decoders.latin1 + case 'utf16le': + case 'utf-16le': + case 'ucs2': + case 'ucs-2': + return decoders.utf16le + case 'base64': + return decoders.base64 + default: + if (lc === undefined) { + lc = true + charset = charset.toLowerCase() + continue + } + return decoders.other.bind(charset) + } + } +} + +const decoders = { + utf8: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.utf8Slice(0, data.length) + }, + + latin1: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + return data + } + return data.latin1Slice(0, data.length) + }, + + utf16le: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.ucs2Slice(0, data.length) + }, + + base64: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.base64Slice(0, data.length) + }, + + other: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + + if (textDecoders.has(this.toString())) { + try { + return textDecoders.get(this).decode(data) + } catch {} + } + return typeof data === 'string' + ? data + : data.toString() + } +} + +function decodeText (text, sourceEncoding, destEncoding) { + if (text) { + return getDecoder(destEncoding)(text, sourceEncoding) + } + return text +} + +module.exports = decodeText + + +/***/ }), + +/***/ 22393: +/***/ ((module) => { + +"use strict"; + + +module.exports = function getLimit (limits, name, defaultLimit) { + if ( + !limits || + limits[name] === undefined || + limits[name] === null + ) { return defaultLimit } + + if ( + typeof limits[name] !== 'number' || + isNaN(limits[name]) + ) { throw new TypeError('Limit ' + name + ' is not a valid number') } + + return limits[name] +} + + +/***/ }), + +/***/ 8929: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/* eslint-disable object-property-newline */ + + +const decodeText = __nccwpck_require__(72747) + +const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g + +const EncodedLookup = { + '%00': '\x00', '%01': '\x01', '%02': '\x02', '%03': '\x03', '%04': '\x04', + '%05': '\x05', '%06': '\x06', '%07': '\x07', '%08': '\x08', '%09': '\x09', + '%0a': '\x0a', '%0A': '\x0a', '%0b': '\x0b', '%0B': '\x0b', '%0c': '\x0c', + '%0C': '\x0c', '%0d': '\x0d', '%0D': '\x0d', '%0e': '\x0e', '%0E': '\x0e', + '%0f': '\x0f', '%0F': '\x0f', '%10': '\x10', '%11': '\x11', '%12': '\x12', + '%13': '\x13', '%14': '\x14', '%15': '\x15', '%16': '\x16', '%17': '\x17', + '%18': '\x18', '%19': '\x19', '%1a': '\x1a', '%1A': '\x1a', '%1b': '\x1b', + '%1B': '\x1b', '%1c': '\x1c', '%1C': '\x1c', '%1d': '\x1d', '%1D': '\x1d', + '%1e': '\x1e', '%1E': '\x1e', '%1f': '\x1f', '%1F': '\x1f', '%20': '\x20', + '%21': '\x21', '%22': '\x22', '%23': '\x23', '%24': '\x24', '%25': '\x25', + '%26': '\x26', '%27': '\x27', '%28': '\x28', '%29': '\x29', '%2a': '\x2a', + '%2A': '\x2a', '%2b': '\x2b', '%2B': '\x2b', '%2c': '\x2c', '%2C': '\x2c', + '%2d': '\x2d', '%2D': '\x2d', '%2e': '\x2e', '%2E': '\x2e', '%2f': '\x2f', + '%2F': '\x2f', '%30': '\x30', '%31': '\x31', '%32': '\x32', '%33': '\x33', + '%34': '\x34', '%35': '\x35', '%36': '\x36', '%37': '\x37', '%38': '\x38', + '%39': '\x39', '%3a': '\x3a', '%3A': '\x3a', '%3b': '\x3b', '%3B': '\x3b', + '%3c': '\x3c', '%3C': '\x3c', '%3d': '\x3d', '%3D': '\x3d', '%3e': '\x3e', + '%3E': '\x3e', '%3f': '\x3f', '%3F': '\x3f', '%40': '\x40', '%41': '\x41', + '%42': '\x42', '%43': '\x43', '%44': '\x44', '%45': '\x45', '%46': '\x46', + '%47': '\x47', '%48': '\x48', '%49': '\x49', '%4a': '\x4a', '%4A': '\x4a', + '%4b': '\x4b', '%4B': '\x4b', '%4c': '\x4c', '%4C': '\x4c', '%4d': '\x4d', + '%4D': '\x4d', '%4e': '\x4e', '%4E': '\x4e', '%4f': '\x4f', '%4F': '\x4f', + '%50': '\x50', '%51': '\x51', '%52': '\x52', '%53': '\x53', '%54': '\x54', + '%55': '\x55', '%56': '\x56', '%57': '\x57', '%58': '\x58', '%59': '\x59', + '%5a': '\x5a', '%5A': '\x5a', '%5b': '\x5b', '%5B': '\x5b', '%5c': '\x5c', + '%5C': '\x5c', '%5d': '\x5d', '%5D': '\x5d', '%5e': '\x5e', '%5E': '\x5e', + '%5f': '\x5f', '%5F': '\x5f', '%60': '\x60', '%61': '\x61', '%62': '\x62', + '%63': '\x63', '%64': '\x64', '%65': '\x65', '%66': '\x66', '%67': '\x67', + '%68': '\x68', '%69': '\x69', '%6a': '\x6a', '%6A': '\x6a', '%6b': '\x6b', + '%6B': '\x6b', '%6c': '\x6c', '%6C': '\x6c', '%6d': '\x6d', '%6D': '\x6d', + '%6e': '\x6e', '%6E': '\x6e', '%6f': '\x6f', '%6F': '\x6f', '%70': '\x70', + '%71': '\x71', '%72': '\x72', '%73': '\x73', '%74': '\x74', '%75': '\x75', + '%76': '\x76', '%77': '\x77', '%78': '\x78', '%79': '\x79', '%7a': '\x7a', + '%7A': '\x7a', '%7b': '\x7b', '%7B': '\x7b', '%7c': '\x7c', '%7C': '\x7c', + '%7d': '\x7d', '%7D': '\x7d', '%7e': '\x7e', '%7E': '\x7e', '%7f': '\x7f', + '%7F': '\x7f', '%80': '\x80', '%81': '\x81', '%82': '\x82', '%83': '\x83', + '%84': '\x84', '%85': '\x85', '%86': '\x86', '%87': '\x87', '%88': '\x88', + '%89': '\x89', '%8a': '\x8a', '%8A': '\x8a', '%8b': '\x8b', '%8B': '\x8b', + '%8c': '\x8c', '%8C': '\x8c', '%8d': '\x8d', '%8D': '\x8d', '%8e': '\x8e', + '%8E': '\x8e', '%8f': '\x8f', '%8F': '\x8f', '%90': '\x90', '%91': '\x91', + '%92': '\x92', '%93': '\x93', '%94': '\x94', '%95': '\x95', '%96': '\x96', + '%97': '\x97', '%98': '\x98', '%99': '\x99', '%9a': '\x9a', '%9A': '\x9a', + '%9b': '\x9b', '%9B': '\x9b', '%9c': '\x9c', '%9C': '\x9c', '%9d': '\x9d', + '%9D': '\x9d', '%9e': '\x9e', '%9E': '\x9e', '%9f': '\x9f', '%9F': '\x9f', + '%a0': '\xa0', '%A0': '\xa0', '%a1': '\xa1', '%A1': '\xa1', '%a2': '\xa2', + '%A2': '\xa2', '%a3': '\xa3', '%A3': '\xa3', '%a4': '\xa4', '%A4': '\xa4', + '%a5': '\xa5', '%A5': '\xa5', '%a6': '\xa6', '%A6': '\xa6', '%a7': '\xa7', + '%A7': '\xa7', '%a8': '\xa8', '%A8': '\xa8', '%a9': '\xa9', '%A9': '\xa9', + '%aa': '\xaa', '%Aa': '\xaa', '%aA': '\xaa', '%AA': '\xaa', '%ab': '\xab', + '%Ab': '\xab', '%aB': '\xab', '%AB': '\xab', '%ac': '\xac', '%Ac': '\xac', + '%aC': '\xac', '%AC': '\xac', '%ad': '\xad', '%Ad': '\xad', '%aD': '\xad', + '%AD': '\xad', '%ae': '\xae', '%Ae': '\xae', '%aE': '\xae', '%AE': '\xae', + '%af': '\xaf', '%Af': '\xaf', '%aF': '\xaf', '%AF': '\xaf', '%b0': '\xb0', + '%B0': '\xb0', '%b1': '\xb1', '%B1': '\xb1', '%b2': '\xb2', '%B2': '\xb2', + '%b3': '\xb3', '%B3': '\xb3', '%b4': '\xb4', '%B4': '\xb4', '%b5': '\xb5', + '%B5': '\xb5', '%b6': '\xb6', '%B6': '\xb6', '%b7': '\xb7', '%B7': '\xb7', + '%b8': '\xb8', '%B8': '\xb8', '%b9': '\xb9', '%B9': '\xb9', '%ba': '\xba', + '%Ba': '\xba', '%bA': '\xba', '%BA': '\xba', '%bb': '\xbb', '%Bb': '\xbb', + '%bB': '\xbb', '%BB': '\xbb', '%bc': '\xbc', '%Bc': '\xbc', '%bC': '\xbc', + '%BC': '\xbc', '%bd': '\xbd', '%Bd': '\xbd', '%bD': '\xbd', '%BD': '\xbd', + '%be': '\xbe', '%Be': '\xbe', '%bE': '\xbe', '%BE': '\xbe', '%bf': '\xbf', + '%Bf': '\xbf', '%bF': '\xbf', '%BF': '\xbf', '%c0': '\xc0', '%C0': '\xc0', + '%c1': '\xc1', '%C1': '\xc1', '%c2': '\xc2', '%C2': '\xc2', '%c3': '\xc3', + '%C3': '\xc3', '%c4': '\xc4', '%C4': '\xc4', '%c5': '\xc5', '%C5': '\xc5', + '%c6': '\xc6', '%C6': '\xc6', '%c7': '\xc7', '%C7': '\xc7', '%c8': '\xc8', + '%C8': '\xc8', '%c9': '\xc9', '%C9': '\xc9', '%ca': '\xca', '%Ca': '\xca', + '%cA': '\xca', '%CA': '\xca', '%cb': '\xcb', '%Cb': '\xcb', '%cB': '\xcb', + '%CB': '\xcb', '%cc': '\xcc', '%Cc': '\xcc', '%cC': '\xcc', '%CC': '\xcc', + '%cd': '\xcd', '%Cd': '\xcd', '%cD': '\xcd', '%CD': '\xcd', '%ce': '\xce', + '%Ce': '\xce', '%cE': '\xce', '%CE': '\xce', '%cf': '\xcf', '%Cf': '\xcf', + '%cF': '\xcf', '%CF': '\xcf', '%d0': '\xd0', '%D0': '\xd0', '%d1': '\xd1', + '%D1': '\xd1', '%d2': '\xd2', '%D2': '\xd2', '%d3': '\xd3', '%D3': '\xd3', + '%d4': '\xd4', '%D4': '\xd4', '%d5': '\xd5', '%D5': '\xd5', '%d6': '\xd6', + '%D6': '\xd6', '%d7': '\xd7', '%D7': '\xd7', '%d8': '\xd8', '%D8': '\xd8', + '%d9': '\xd9', '%D9': '\xd9', '%da': '\xda', '%Da': '\xda', '%dA': '\xda', + '%DA': '\xda', '%db': '\xdb', '%Db': '\xdb', '%dB': '\xdb', '%DB': '\xdb', + '%dc': '\xdc', '%Dc': '\xdc', '%dC': '\xdc', '%DC': '\xdc', '%dd': '\xdd', + '%Dd': '\xdd', '%dD': '\xdd', '%DD': '\xdd', '%de': '\xde', '%De': '\xde', + '%dE': '\xde', '%DE': '\xde', '%df': '\xdf', '%Df': '\xdf', '%dF': '\xdf', + '%DF': '\xdf', '%e0': '\xe0', '%E0': '\xe0', '%e1': '\xe1', '%E1': '\xe1', + '%e2': '\xe2', '%E2': '\xe2', '%e3': '\xe3', '%E3': '\xe3', '%e4': '\xe4', + '%E4': '\xe4', '%e5': '\xe5', '%E5': '\xe5', '%e6': '\xe6', '%E6': '\xe6', + '%e7': '\xe7', '%E7': '\xe7', '%e8': '\xe8', '%E8': '\xe8', '%e9': '\xe9', + '%E9': '\xe9', '%ea': '\xea', '%Ea': '\xea', '%eA': '\xea', '%EA': '\xea', + '%eb': '\xeb', '%Eb': '\xeb', '%eB': '\xeb', '%EB': '\xeb', '%ec': '\xec', + '%Ec': '\xec', '%eC': '\xec', '%EC': '\xec', '%ed': '\xed', '%Ed': '\xed', + '%eD': '\xed', '%ED': '\xed', '%ee': '\xee', '%Ee': '\xee', '%eE': '\xee', + '%EE': '\xee', '%ef': '\xef', '%Ef': '\xef', '%eF': '\xef', '%EF': '\xef', + '%f0': '\xf0', '%F0': '\xf0', '%f1': '\xf1', '%F1': '\xf1', '%f2': '\xf2', + '%F2': '\xf2', '%f3': '\xf3', '%F3': '\xf3', '%f4': '\xf4', '%F4': '\xf4', + '%f5': '\xf5', '%F5': '\xf5', '%f6': '\xf6', '%F6': '\xf6', '%f7': '\xf7', + '%F7': '\xf7', '%f8': '\xf8', '%F8': '\xf8', '%f9': '\xf9', '%F9': '\xf9', + '%fa': '\xfa', '%Fa': '\xfa', '%fA': '\xfa', '%FA': '\xfa', '%fb': '\xfb', + '%Fb': '\xfb', '%fB': '\xfb', '%FB': '\xfb', '%fc': '\xfc', '%Fc': '\xfc', + '%fC': '\xfc', '%FC': '\xfc', '%fd': '\xfd', '%Fd': '\xfd', '%fD': '\xfd', + '%FD': '\xfd', '%fe': '\xfe', '%Fe': '\xfe', '%fE': '\xfe', '%FE': '\xfe', + '%ff': '\xff', '%Ff': '\xff', '%fF': '\xff', '%FF': '\xff' +} + +function encodedReplacer (match) { + return EncodedLookup[match] +} + +const STATE_KEY = 0 +const STATE_VALUE = 1 +const STATE_CHARSET = 2 +const STATE_LANG = 3 + +function parseParams (str) { + const res = [] + let state = STATE_KEY + let charset = '' + let inquote = false + let escaping = false + let p = 0 + let tmp = '' + const len = str.length + + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + const char = str[i] + if (char === '\\' && inquote) { + if (escaping) { escaping = false } else { + escaping = true + continue + } + } else if (char === '"') { + if (!escaping) { + if (inquote) { + inquote = false + state = STATE_KEY + } else { inquote = true } + continue + } else { escaping = false } + } else { + if (escaping && inquote) { tmp += '\\' } + escaping = false + if ((state === STATE_CHARSET || state === STATE_LANG) && char === "'") { + if (state === STATE_CHARSET) { + state = STATE_LANG + charset = tmp.substring(1) + } else { state = STATE_VALUE } + tmp = '' + continue + } else if (state === STATE_KEY && + (char === '*' || char === '=') && + res.length) { + state = char === '*' + ? STATE_CHARSET + : STATE_VALUE + res[p] = [tmp, undefined] + tmp = '' + continue + } else if (!inquote && char === ';') { + state = STATE_KEY + if (charset) { + if (tmp.length) { + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), + 'binary', + charset) + } + charset = '' + } else if (tmp.length) { + tmp = decodeText(tmp, 'binary', 'utf8') + } + if (res[p] === undefined) { res[p] = tmp } else { res[p][1] = tmp } + tmp = '' + ++p + continue + } else if (!inquote && (char === ' ' || char === '\t')) { continue } + } + tmp += char + } + if (charset && tmp.length) { + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), + 'binary', + charset) + } else if (tmp) { + tmp = decodeText(tmp, 'binary', 'utf8') + } + + if (res[p] === undefined) { + if (tmp) { res[p] = tmp } + } else { res[p][1] = tmp } + + return res +} + +module.exports = parseParams + + +/***/ }), + +/***/ 76637: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AclRoleAccessorMethods = exports.Acl = void 0; +const promisify_1 = __nccwpck_require__(60206); +/** + * Attach functionality to a {@link Storage.acl} instance. This will add an + * object for each role group (owners, readers, and writers), with each object + * containing methods to add or delete a type of entity. + * + * As an example, here are a few methods that are created. + * + * myBucket.acl.readers.deleteGroup('groupId', function(err) {}); + * + * myBucket.acl.owners.addUser('email@example.com', function(err, acl) {}); + * + * myBucket.acl.writers.addDomain('example.com', function(err, acl) {}); + * + * @private + */ +class AclRoleAccessorMethods { + constructor() { + this.owners = {}; + this.readers = {}; + this.writers = {}; + /** + * An object of convenience methods to add or delete owner ACL permissions + * for a given entity. + * + * The supported methods include: + * + * - `myFile.acl.owners.addAllAuthenticatedUsers` + * - `myFile.acl.owners.deleteAllAuthenticatedUsers` + * - `myFile.acl.owners.addAllUsers` + * - `myFile.acl.owners.deleteAllUsers` + * - `myFile.acl.owners.addDomain` + * - `myFile.acl.owners.deleteDomain` + * - `myFile.acl.owners.addGroup` + * - `myFile.acl.owners.deleteGroup` + * - `myFile.acl.owners.addProject` + * - `myFile.acl.owners.deleteProject` + * - `myFile.acl.owners.addUser` + * - `myFile.acl.owners.deleteUser` + * + * @name Acl#owners + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * //- + * // Add a user as an owner of a file. + * //- + * const myBucket = gcs.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * myFile.acl.owners.addUser('email@example.com', function(err, aclObject) + * {}); + * + * //- + * // For reference, the above command is the same as running the following. + * //- + * myFile.acl.add({ + * entity: 'user-email@example.com', + * role: gcs.acl.OWNER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.owners.addUser('email@example.com').then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + this.owners = {}; + /** + * An object of convenience methods to add or delete reader ACL permissions + * for a given entity. + * + * The supported methods include: + * + * - `myFile.acl.readers.addAllAuthenticatedUsers` + * - `myFile.acl.readers.deleteAllAuthenticatedUsers` + * - `myFile.acl.readers.addAllUsers` + * - `myFile.acl.readers.deleteAllUsers` + * - `myFile.acl.readers.addDomain` + * - `myFile.acl.readers.deleteDomain` + * - `myFile.acl.readers.addGroup` + * - `myFile.acl.readers.deleteGroup` + * - `myFile.acl.readers.addProject` + * - `myFile.acl.readers.deleteProject` + * - `myFile.acl.readers.addUser` + * - `myFile.acl.readers.deleteUser` + * + * @name Acl#readers + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * //- + * // Add a user as a reader of a file. + * //- + * myFile.acl.readers.addUser('email@example.com', function(err, aclObject) + * {}); + * + * //- + * // For reference, the above command is the same as running the following. + * //- + * myFile.acl.add({ + * entity: 'user-email@example.com', + * role: gcs.acl.READER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.readers.addUser('email@example.com').then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + this.readers = {}; + /** + * An object of convenience methods to add or delete writer ACL permissions + * for a given entity. + * + * The supported methods include: + * + * - `myFile.acl.writers.addAllAuthenticatedUsers` + * - `myFile.acl.writers.deleteAllAuthenticatedUsers` + * - `myFile.acl.writers.addAllUsers` + * - `myFile.acl.writers.deleteAllUsers` + * - `myFile.acl.writers.addDomain` + * - `myFile.acl.writers.deleteDomain` + * - `myFile.acl.writers.addGroup` + * - `myFile.acl.writers.deleteGroup` + * - `myFile.acl.writers.addProject` + * - `myFile.acl.writers.deleteProject` + * - `myFile.acl.writers.addUser` + * - `myFile.acl.writers.deleteUser` + * + * @name Acl#writers + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * //- + * // Add a user as a writer of a file. + * //- + * myFile.acl.writers.addUser('email@example.com', function(err, aclObject) + * {}); + * + * //- + * // For reference, the above command is the same as running the following. + * //- + * myFile.acl.add({ + * entity: 'user-email@example.com', + * role: gcs.acl.WRITER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.writers.addUser('email@example.com').then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + this.writers = {}; + AclRoleAccessorMethods.roles.forEach(this._assignAccessMethods.bind(this)); + } + _assignAccessMethods(role) { + const accessMethods = AclRoleAccessorMethods.accessMethods; + const entities = AclRoleAccessorMethods.entities; + const roleGroup = role.toLowerCase() + 's'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this[roleGroup] = entities.reduce((acc, entity) => { + const isPrefix = entity.charAt(entity.length - 1) === '-'; + accessMethods.forEach(accessMethod => { + let method = accessMethod + entity[0].toUpperCase() + entity.substring(1); + if (isPrefix) { + method = method.replace('-', ''); + } + // Wrap the parent accessor method (e.g. `add` or `delete`) to avoid the + // more complex API of specifying an `entity` and `role`. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + acc[method] = (entityId, options, callback) => { + let apiEntity; + if (typeof options === 'function') { + callback = options; + options = {}; + } + if (isPrefix) { + apiEntity = entity + entityId; + } + else { + // If the entity is not a prefix, it is a special entity group + // that does not require further details. The accessor methods + // only accept a callback. + apiEntity = entity; + callback = entityId; + } + options = Object.assign({ + entity: apiEntity, + role, + }, options); + const args = [options]; + if (typeof callback === 'function') { + args.push(callback); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return this[accessMethod].apply(this, args); + }; + }); + return acc; + }, {}); + } +} +exports.AclRoleAccessorMethods = AclRoleAccessorMethods; +AclRoleAccessorMethods.accessMethods = ['add', 'delete']; +AclRoleAccessorMethods.entities = [ + // Special entity groups that do not require further specification. + 'allAuthenticatedUsers', + 'allUsers', + // Entity groups that require specification, e.g. `user-email@example.com`. + 'domain-', + 'group-', + 'project-', + 'user-', +]; +AclRoleAccessorMethods.roles = ['OWNER', 'READER', 'WRITER']; +/** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * An ACL consists of one or more entries, where each entry grants permissions + * to an entity. Permissions define the actions that can be performed against an + * object or bucket (for example, `READ` or `WRITE`); the entity defines who the + * permission applies to (for example, a specific user or group of users). + * + * Where an `entity` value is accepted, we follow the format the Cloud Storage + * API expects. + * + * Refer to + * https://cloud.google.com/storage/docs/json_api/v1/defaultObjectAccessControls + * for the most up-to-date values. + * + * - `user-userId` + * - `user-email` + * - `group-groupId` + * - `group-email` + * - `domain-domain` + * - `project-team-projectId` + * - `allUsers` + * - `allAuthenticatedUsers` + * + * Examples: + * + * - The user "liz@example.com" would be `user-liz@example.com`. + * - The group "example@googlegroups.com" would be + * `group-example@googlegroups.com`. + * - To refer to all members of the Google Apps for Business domain + * "example.com", the entity would be `domain-example.com`. + * + * For more detailed information, see + * {@link http://goo.gl/6qBBPO| About Access Control Lists}. + * + * @constructor Acl + * @mixin + * @param {object} options Configuration options. + */ +class Acl extends AclRoleAccessorMethods { + constructor(options) { + super(); + this.pathPrefix = options.pathPrefix; + this.request_ = options.request; + } + /** + * @typedef {array} AddAclResponse + * @property {object} 0 The Acl Objects. + * @property {object} 1 The full API response. + */ + /** + * @callback AddAclCallback + * @param {?Error} err Request error, if any. + * @param {object} acl The Acl Objects. + * @param {object} apiResponse The full API response. + */ + /** + * Add access controls on a {@link Bucket} or {@link File}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/insert| BucketAccessControls: insert API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/insert| ObjectAccessControls: insert API Documentation} + * + * @param {object} options Configuration options. + * @param {string} options.entity Whose permissions will be added. + * @param {string} options.role Permissions allowed for the defined entity. + * See {@link https://cloud.google.com/storage/docs/access-control Access + * Control}. + * @param {number} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {AddAclCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * const options = { + * entity: 'user-useremail@example.com', + * role: gcs.acl.OWNER_ROLE + * }; + * + * myBucket.acl.add(options, function(err, aclObject, apiResponse) {}); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * // Here is how you would grant ownership permissions to a user on a + * specific + * // revision of a file. + * //- + * myFile.acl.add({ + * entity: 'user-useremail@example.com', + * role: gcs.acl.OWNER_ROLE, + * generation: 1 + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_add_file_owner + * Example of adding an owner to a file: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_owner + * Example of adding an owner to a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_default_owner + * Example of adding a default owner to a bucket: + */ + add(options, callback) { + const query = {}; + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + this.request({ + method: 'POST', + uri: '', + qs: query, + maxRetries: 0, //explicitly set this value since this is a non-idempotent function + json: { + entity: options.entity, + role: options.role.toUpperCase(), + }, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + callback(null, this.makeAclObject_(resp), resp); + }); + } + /** + * @typedef {array} RemoveAclResponse + * @property {object} 0 The full API response. + */ + /** + * @callback RemoveAclCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Delete access controls on a {@link Bucket} or {@link File}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/delete| BucketAccessControls: delete API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/delete| ObjectAccessControls: delete API Documentation} + * + * @param {object} options Configuration object. + * @param {string} options.entity Whose permissions will be revoked. + * @param {int} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {RemoveAclCallback} callback The callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * myBucket.acl.delete({ + * entity: 'user-useremail@example.com' + * }, function(err, apiResponse) {}); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * //- + * myFile.acl.delete({ + * entity: 'user-useremail@example.com', + * generation: 1 + * }, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_owner + * Example of removing an owner from a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_default_owner + * Example of removing a default owner from a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_file_owner + * Example of removing an owner from a bucket: + */ + delete(options, callback) { + const query = {}; + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + this.request({ + method: 'DELETE', + uri: '/' + encodeURIComponent(options.entity), + qs: query, + }, (err, resp) => { + callback(err, resp); + }); + } + /** + * @typedef {array} GetAclResponse + * @property {object|object[]} 0 Single or array of Acl Objects. + * @property {object} 1 The full API response. + */ + /** + * @callback GetAclCallback + * @param {?Error} err Request error, if any. + * @param {object|object[]} acl Single or array of Acl Objects. + * @param {object} apiResponse The full API response. + */ + /** + * Get access controls on a {@link Bucket} or {@link File}. If + * an entity is omitted, you will receive an array of all applicable access + * controls. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/get| BucketAccessControls: get API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/get| ObjectAccessControls: get API Documentation} + * + * @param {object|function} [options] Configuration options. If you want to + * receive a list of all access controls, pass the callback function as + * the only argument. + * @param {string} options.entity Whose permissions will be fetched. + * @param {number} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetAclCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * myBucket.acl.get({ + * entity: 'user-useremail@example.com' + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // Get all access controls. + * //- + * myBucket.acl.get(function(err, aclObjects, apiResponse) { + * // aclObjects = [ + * // { + * // entity: 'user-useremail@example.com', + * // role: 'owner' + * // } + * // ] + * }); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * //- + * myFile.acl.get({ + * entity: 'user-useremail@example.com', + * generation: 1 + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.acl.get().then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_print_file_acl + * Example of printing a file's ACL: + * + * @example include:samples/acl.js + * region_tag:storage_print_file_acl_for_user + * Example of printing a file's ACL for a specific user: + * + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl + * Example of printing a bucket's ACL: + * + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl_for_user + * Example of printing a bucket's ACL for a specific user: + */ + get(optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : null; + const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb; + let path = ''; + const query = {}; + if (options) { + path = '/' + encodeURIComponent(options.entity); + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + } + this.request({ + uri: path, + qs: query, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + let results; + if (resp.items) { + results = resp.items.map(this.makeAclObject_); + } + else { + results = this.makeAclObject_(resp); + } + callback(null, results, resp); + }); + } + /** + * @typedef {array} UpdateAclResponse + * @property {object} 0 The updated Acl Objects. + * @property {object} 1 The full API response. + */ + /** + * @callback UpdateAclCallback + * @param {?Error} err Request error, if any. + * @param {object} acl The updated Acl Objects. + * @param {object} apiResponse The full API response. + */ + /** + * Update access controls on a {@link Bucket} or {@link File}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/update| BucketAccessControls: update API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/update| ObjectAccessControls: update API Documentation} + * + * @param {object} options Configuration options. + * @param {string} options.entity Whose permissions will be updated. + * @param {string} options.role Permissions allowed for the defined entity. + * See {@link Storage.acl}. + * @param {number} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {UpdateAclCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * const options = { + * entity: 'user-useremail@example.com', + * role: gcs.acl.WRITER_ROLE + * }; + * + * myBucket.acl.update(options, function(err, aclObject, apiResponse) {}); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * //- + * myFile.acl.update({ + * entity: 'user-useremail@example.com', + * role: gcs.acl.WRITER_ROLE, + * generation: 1 + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.update(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + update(options, callback) { + const query = {}; + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + this.request({ + method: 'PUT', + uri: '/' + encodeURIComponent(options.entity), + qs: query, + json: { + role: options.role.toUpperCase(), + }, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + callback(null, this.makeAclObject_(resp), resp); + }); + } + /** + * Transform API responses to a consistent object format. + * + * @private + */ + makeAclObject_(accessControlObject) { + const obj = { + entity: accessControlObject.entity, + role: accessControlObject.role, + }; + if (accessControlObject.projectTeam) { + obj.projectTeam = accessControlObject.projectTeam; + } + return obj; + } + /** + * Patch requests up to the bucket's request object. + * + * @private + * + * @param {string} method Action. + * @param {string} path Request path. + * @param {*} query Request query object. + * @param {*} body Request body contents. + * @param {function} callback Callback function. + */ + request(reqOpts, callback) { + reqOpts.uri = this.pathPrefix + reqOpts.uri; + this.request_(reqOpts, callback); + } +} +exports.Acl = Acl; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Acl, { + exclude: ['request'], +}); + + +/***/ }), + +/***/ 82887: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Bucket = exports.BucketExceptionMessages = exports.AvailableServiceObjectMethods = exports.BucketActionToHTTPMethod = void 0; +const index_js_1 = __nccwpck_require__(11325); +const paginator_1 = __nccwpck_require__(99469); +const promisify_1 = __nccwpck_require__(60206); +const fs = __importStar(__nccwpck_require__(79896)); +const mime_1 = __importDefault(__nccwpck_require__(94900)); +const path = __importStar(__nccwpck_require__(16928)); +const p_limit_1 = __importDefault(__nccwpck_require__(58890)); +const util_1 = __nccwpck_require__(39023); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +const util_js_1 = __nccwpck_require__(74557); +const acl_js_1 = __nccwpck_require__(76637); +const file_js_1 = __nccwpck_require__(69975); +const iam_js_1 = __nccwpck_require__(52880); +const notification_js_1 = __nccwpck_require__(18598); +const storage_js_1 = __nccwpck_require__(92848); +const signer_js_1 = __nccwpck_require__(7319); +const stream_1 = __nccwpck_require__(2203); +const url_1 = __nccwpck_require__(87016); +var BucketActionToHTTPMethod; +(function (BucketActionToHTTPMethod) { + BucketActionToHTTPMethod["list"] = "GET"; +})(BucketActionToHTTPMethod || (exports.BucketActionToHTTPMethod = BucketActionToHTTPMethod = {})); +var AvailableServiceObjectMethods; +(function (AvailableServiceObjectMethods) { + AvailableServiceObjectMethods[AvailableServiceObjectMethods["setMetadata"] = 0] = "setMetadata"; + AvailableServiceObjectMethods[AvailableServiceObjectMethods["delete"] = 1] = "delete"; +})(AvailableServiceObjectMethods || (exports.AvailableServiceObjectMethods = AvailableServiceObjectMethods = {})); +var BucketExceptionMessages; +(function (BucketExceptionMessages) { + BucketExceptionMessages["PROVIDE_SOURCE_FILE"] = "You must provide at least one source file."; + BucketExceptionMessages["DESTINATION_FILE_NOT_SPECIFIED"] = "A destination file must be specified."; + BucketExceptionMessages["CHANNEL_ID_REQUIRED"] = "An ID is required to create a channel."; + BucketExceptionMessages["TOPIC_NAME_REQUIRED"] = "A valid topic name is required."; + BucketExceptionMessages["CONFIGURATION_OBJECT_PREFIX_REQUIRED"] = "A configuration object with a prefix is required."; + BucketExceptionMessages["SPECIFY_FILE_NAME"] = "A file name must be specified."; + BucketExceptionMessages["METAGENERATION_NOT_PROVIDED"] = "A metageneration must be provided."; + BucketExceptionMessages["SUPPLY_NOTIFICATION_ID"] = "You must supply a notification ID."; +})(BucketExceptionMessages || (exports.BucketExceptionMessages = BucketExceptionMessages = {})); +/** + * @callback Crc32cGeneratorToStringCallback + * A method returning the CRC32C as a base64-encoded string. + * + * @returns {string} + * + * @example + * Hashing the string 'data' should return 'rth90Q==' + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.toString(); // 'rth90Q==' + * ``` + **/ +/** + * @callback Crc32cGeneratorValidateCallback + * A method validating a base64-encoded CRC32C string. + * + * @param {string} [value] base64-encoded CRC32C string to validate + * @returns {boolean} + * + * @example + * Should return `true` if the value matches, `false` otherwise + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.validate('DkjKuA=='); // false + * crc32c.validate('rth90Q=='); // true + * ``` + **/ +/** + * @callback Crc32cGeneratorUpdateCallback + * A method for passing `Buffer`s for CRC32C generation. + * + * @param {Buffer} [data] data to update CRC32C value with + * @returns {undefined} + * + * @example + * Hashing buffers from 'some ' and 'text\n' + * + * ```js + * const buffer1 = Buffer.from('some '); + * crc32c.update(buffer1); + * + * const buffer2 = Buffer.from('text\n'); + * crc32c.update(buffer2); + * + * crc32c.toString(); // 'DkjKuA==' + * ``` + **/ +/** + * @typedef {object} CRC32CValidator + * @property {Crc32cGeneratorToStringCallback} + * @property {Crc32cGeneratorValidateCallback} + * @property {Crc32cGeneratorUpdateCallback} + */ +/** + * A function that generates a CRC32C Validator. Defaults to {@link CRC32C} + * + * @name Bucket#crc32cGenerator + * @type {CRC32CValidator} + */ +/** + * Get and set IAM policies for your bucket. + * + * @name Bucket#iam + * @mixes Iam + * + * See {@link https://cloud.google.com/storage/docs/access-control/iam#short_title_iam_management| Cloud Storage IAM Management} + * See {@link https://cloud.google.com/iam/docs/granting-changing-revoking-access| Granting, Changing, and Revoking Access} + * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Get the IAM policy for your bucket. + * //- + * bucket.iam.getPolicy(function(err, policy) { + * console.log(policy); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.getPolicy().then(function(data) { + * const policy = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/iam.js + * region_tag:storage_view_bucket_iam_members + * Example of retrieving a bucket's IAM policy: + * + * @example include:samples/iam.js + * region_tag:storage_add_bucket_iam_member + * Example of adding to a bucket's IAM policy: + * + * @example include:samples/iam.js + * region_tag:storage_remove_bucket_iam_member + * Example of removing from a bucket's IAM policy: + */ +/** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * An ACL consists of one or more entries, where each entry grants permissions + * to an entity. Permissions define the actions that can be performed against + * an object or bucket (for example, `READ` or `WRITE`); the entity defines + * who the permission applies to (for example, a specific user or group of + * users). + * + * The `acl` object on a Bucket instance provides methods to get you a list of + * the ACLs defined on your bucket, as well as set, update, and delete them. + * + * Buckets also have + * {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs} + * for all created files. Default ACLs specify permissions that all new + * objects added to the bucket will inherit by default. You can add, delete, + * get, and update entities and permissions for these as well with + * {@link Bucket#acl.default}. + * + * See {@link http://goo.gl/6qBBPO| About Access Control Lists} + * See {@link https://cloud.google.com/storage/docs/access-control/lists#default| Default ACLs} + * + * @name Bucket#acl + * @mixes Acl + * @property {Acl} default Cloud Storage Buckets have + * {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs} + * for all created files. You can add, delete, get, and update entities and + * permissions for these as well. The method signatures and examples are all + * the same, after only prefixing the method call with `default`. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Make a bucket's contents publicly readable. + * //- + * const myBucket = storage.bucket('my-bucket'); + * + * const options = { + * entity: 'allUsers', + * role: storage.acl.READER_ROLE + * }; + * + * myBucket.acl.add(options, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl + * Example of printing a bucket's ACL: + * + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl_for_user + * Example of printing a bucket's ACL for a specific user: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_owner + * Example of adding an owner to a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_owner + * Example of removing an owner from a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_default_owner + * Example of adding a default owner to a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_default_owner + * Example of removing a default owner from a bucket: + */ +/** + * The API-formatted resource description of the bucket. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name Bucket#metadata + * @type {object} + */ +/** + * The bucket's name. + * @name Bucket#name + * @type {string} + */ +/** + * Get {@link File} objects for the files currently in the bucket as a + * readable object stream. + * + * @method Bucket#getFilesStream + * @param {GetFilesOptions} [query] Query object for listing files. + * @returns {ReadableStream} A readable stream that emits {@link File} instances. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getFilesStream() + * .on('error', console.error) + * .on('data', function(file) { + * // file is a File object. + * }) + * .on('end', function() { + * // All files retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * bucket.getFilesStream() + * .on('data', function(file) { + * this.end(); + * }); + * + * //- + * // If you're filtering files with a delimiter, you should use + * // {@link Bucket#getFiles} and set `autoPaginate: false` in order to + * // preserve the `apiResponse` argument. + * //- + * const prefixes = []; + * + * function callback(err, files, nextQuery, apiResponse) { + * prefixes = prefixes.concat(apiResponse.prefixes); + * + * if (nextQuery) { + * bucket.getFiles(nextQuery, callback); + * } else { + * // prefixes = The finished array of prefixes. + * } + * } + * + * bucket.getFiles({ + * autoPaginate: false, + * delimiter: '/' + * }, callback); + * ``` + */ +/** + * Create a Bucket object to interact with a Cloud Storage bucket. + * + * @class + * @hideconstructor + * + * @param {Storage} storage A {@link Storage} instance. + * @param {string} name The name of the bucket. + * @param {object} [options] Configuration object. + * @param {string} [options.userProject] User project. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * ``` + */ +class Bucket extends index_js_1.ServiceObject { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + getFilesStream(query) { + // placeholder body, overwritten in constructor + return new stream_1.Readable(); + } + constructor(storage, name, options) { + var _a, _b, _c, _d; + options = options || {}; + // Allow for "gs://"-style input, and strip any trailing slashes. + name = name.replace(/^gs:\/\//, '').replace(/\/+$/, ''); + const requestQueryObject = {}; + if ((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) { + requestQueryObject.ifGenerationMatch = + options.preconditionOpts.ifGenerationMatch; + } + if ((_b = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationNotMatch) { + requestQueryObject.ifGenerationNotMatch = + options.preconditionOpts.ifGenerationNotMatch; + } + if ((_c = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _c === void 0 ? void 0 : _c.ifMetagenerationMatch) { + requestQueryObject.ifMetagenerationMatch = + options.preconditionOpts.ifMetagenerationMatch; + } + if ((_d = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _d === void 0 ? void 0 : _d.ifMetagenerationNotMatch) { + requestQueryObject.ifMetagenerationNotMatch = + options.preconditionOpts.ifMetagenerationNotMatch; + } + const userProject = options.userProject; + if (typeof userProject === 'string') { + requestQueryObject.userProject = userProject; + } + const methods = { + /** + * Create a bucket. + * + * @method Bucket#create + * @param {CreateBucketRequest} [metadata] Metadata to set for the bucket. + * @param {CreateBucketCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * bucket.create(function(err, bucket, apiResponse) { + * if (!err) { + * // The bucket was created successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.create().then(function(data) { + * const bucket = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + create: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * IamDeleteBucketOptions Configuration options. + * @property {boolean} [ignoreNotFound = false] Ignore an error if + * the bucket does not exist. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} DeleteBucketResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DeleteBucketCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Delete the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/delete| Buckets: delete API Documentation} + * + * @method Bucket#delete + * @param {DeleteBucketOptions} [options] Configuration options. + * @param {boolean} [options.ignoreNotFound = false] Ignore an error if + * the bucket does not exist. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DeleteBucketCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * bucket.delete(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/buckets.js + * region_tag:storage_delete_bucket + * Another example: + */ + delete: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} BucketExistsOptions Configuration options for Bucket#exists(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} BucketExistsResponse + * @property {boolean} 0 Whether the {@link Bucket} exists. + */ + /** + * @callback BucketExistsCallback + * @param {?Error} err Request error, if any. + * @param {boolean} exists Whether the {@link Bucket} exists. + */ + /** + * Check if the bucket exists. + * + * @method Bucket#exists + * @param {BucketExistsOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {BucketExistsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.exists(function(err, exists) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.exists().then(function(data) { + * const exists = data[0]; + * }); + * ``` + */ + exists: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} [GetBucketOptions] Configuration options for Bucket#get() + * @property {boolean} [autoCreate] Automatically create the object if + * it does not exist. Default: `false` + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} GetBucketResponse + * @property {Bucket} 0 The {@link Bucket}. + * @property {object} 1 The full API response. + */ + /** + * @callback GetBucketCallback + * @param {?Error} err Request error, if any. + * @param {Bucket} bucket The {@link Bucket}. + * @param {object} apiResponse The full API response. + */ + /** + * Get a bucket if it exists. + * + * You may optionally use this to "get or create" an object by providing + * an object with `autoCreate` set to `true`. Any extra configuration that + * is normally required for the `create` method must be contained within + * this object as well. + * + * @method Bucket#get + * @param {GetBucketOptions} [options] Configuration options. + * @param {boolean} [options.autoCreate] Automatically create the object if + * it does not exist. Default: `false` + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetBucketCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.get(function(err, bucket, apiResponse) { + * // `bucket.metadata` has been populated. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.get().then(function(data) { + * const bucket = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + get: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} GetBucketMetadataResponse + * @property {object} 0 The bucket metadata. + * @property {object} 1 The full API response. + */ + /** + * @callback GetBucketMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The bucket metadata. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} GetBucketMetadataOptions Configuration options for Bucket#getMetadata(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Get the bucket's metadata. + * + * To set metadata, see {@link Bucket#setMetadata}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/get| Buckets: get API Documentation} + * + * @method Bucket#getMetadata + * @param {GetBucketMetadataOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getMetadata(function(err, metadata, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getMetadata().then(function(data) { + * const metadata = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/requesterPays.js + * region_tag:storage_get_requester_pays_status + * Example of retrieving the requester pays status of a bucket: + */ + getMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} SetBucketMetadataOptions Configuration options for Bucket#setMetadata(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} SetBucketMetadataResponse + * @property {object} apiResponse The full API response. + */ + /** + * @callback SetBucketMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The bucket metadata. + */ + /** + * Set the bucket's metadata. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @method Bucket#setMetadata + * @param {object} metadata The metadata you wish to set. + * @param {SetBucketMetadataOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Set website metadata field on the bucket. + * //- + * const metadata = { + * website: { + * mainPageSuffix: 'http://example.com', + * notFoundPage: 'http://example.com/404.html' + * } + * }; + * + * bucket.setMetadata(metadata, function(err, apiResponse) {}); + * + * //- + * // Enable versioning for your bucket. + * //- + * bucket.setMetadata({ + * versioning: { + * enabled: true + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Enable KMS encryption for objects within this bucket. + * //- + * bucket.setMetadata({ + * encryption: { + * defaultKmsKeyName: 'projects/grape-spaceship-123/...' + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Set the default event-based hold value for new objects in this + * // bucket. + * //- + * bucket.setMetadata({ + * defaultEventBasedHold: true + * }, function(err, apiResponse) {}); + * + * //- + * // Remove object lifecycle rules. + * //- + * bucket.setMetadata({ + * lifecycle: null + * }, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setMetadata(metadata).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + }; + super({ + parent: storage, + baseUrl: '/b', + id: name, + createMethod: storage.createBucket.bind(storage), + methods, + }); + this.name = name; + this.storage = storage; + this.userProject = options.userProject; + this.acl = new acl_js_1.Acl({ + request: this.request.bind(this), + pathPrefix: '/acl', + }); + this.acl.default = new acl_js_1.Acl({ + request: this.request.bind(this), + pathPrefix: '/defaultObjectAcl', + }); + this.crc32cGenerator = + options.crc32cGenerator || this.storage.crc32cGenerator; + this.iam = new iam_js_1.Iam(this); + this.getFilesStream = paginator_1.paginator.streamify('getFiles'); + this.instanceRetryValue = storage.retryOptions.autoRetry; + this.instancePreconditionOpts = options === null || options === void 0 ? void 0 : options.preconditionOpts; + } + /** + * The bucket's Cloud Storage URI (`gs://`) + * + * @example + * ```ts + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * // `gs://my-bucket` + * const href = bucket.cloudStorageURI.href; + * ``` + */ + get cloudStorageURI() { + const uri = new url_1.URL('gs://'); + uri.host = this.name; + return uri; + } + /** + * @typedef {object} AddLifecycleRuleOptions Configuration options for Bucket#addLifecycleRule(). + * @property {boolean} [append=true] The new rules will be appended to any + * pre-existing rules. + */ + /** + * + * @typedef {object} LifecycleRule The new lifecycle rule to be added to objects + * in this bucket. + * @property {string|object} action The action to be taken upon matching of + * all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'. + * **Note**: For configuring a raw-formatted rule object to be passed as `action` + * please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}. + * @property {object} condition Condition a bucket must meet before the + * action occurs on the bucket. Refer to following supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}. + * @property {string} [storageClass] When using the `setStorageClass` + * action, provide this option to dictate which storage class the object + * should update to. Please see + * [SetStorageClass option documentation]{@link https://cloud.google.com/storage/docs/lifecycle#setstorageclass} for supported transitions. + */ + /** + * Add an object lifecycle management rule to the bucket. + * + * By default, an Object Lifecycle Management rule provided to this method + * will be included to the existing policy. To replace all existing rules, + * supply the `options` argument, setting `append` to `false`. + * + * To add multiple rules, pass a list to the `rule` parameter. Calling this + * function multiple times asynchronously does not guarantee that all rules + * are added correctly. + * + * See {@link https://cloud.google.com/storage/docs/lifecycle| Object Lifecycle Management} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @param {LifecycleRule|LifecycleRule[]} rule The new lifecycle rule or rules to be added to objects + * in this bucket. + * @param {string|object} rule.action The action to be taken upon matching of + * all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'. + * **Note**: For configuring a raw-formatted rule object to be passed as `action` + * please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}. + * @param {object} rule.condition Condition a bucket must meet before the + * action occurson the bucket. Refer to followitn supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}. + * @param {string} [rule.storageClass] When using the `setStorageClass` + * action, provide this option to dictate which storage class the object + * should update to. + * @param {AddLifecycleRuleOptions} [options] Configuration object. + * @param {boolean} [options.append=true] Append the new rule to the existing + * policy. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Automatically have an object deleted from this bucket once it is 3 years + * // of age. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * age: 365 * 3 // Specified in days. + * } + * }, function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * const lifecycleRules = bucket.metadata.lifecycle.rule; + * + * // Iterate over the Object Lifecycle Management rules on this bucket. + * lifecycleRules.forEach(lifecycleRule => {}); + * }); + * + * //- + * // By default, the rule you provide will be added to the existing policy. + * // Optionally, you can disable this behavior to replace all of the + * // pre-existing rules. + * //- + * const options = { + * append: false + * }; + * + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * age: 365 * 3 // Specified in days. + * } + * }, options, function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * // All rules have been replaced with the new "delete" rule. + * + * // Iterate over the Object Lifecycle Management rules on this bucket. + * lifecycleRules.forEach(lifecycleRule => {}); + * }); + * + * //- + * // For objects created before 2018, "downgrade" the storage class. + * //- + * bucket.addLifecycleRule({ + * action: 'setStorageClass', + * storageClass: 'COLDLINE', + * condition: { + * createdBefore: new Date('2018') + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete objects created before 2016 which have the Coldline storage + * // class. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * matchesStorageClass: [ + * 'COLDLINE' + * ], + * createdBefore: new Date('2016') + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete object that has a noncurrent timestamp that is at least 100 days. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * daysSinceNoncurrentTime: 100 + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete object that has a noncurrent timestamp before 2020-01-01. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * noncurrentTimeBefore: new Date('2020-01-01') + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete object that has a customTime that is at least 100 days. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * daysSinceCustomTime: 100 + * } + * }, function(err, apiResponse) ()); + * + * //- + * // Delete object that has a customTime before 2020-01-01. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * customTimeBefore: new Date('2020-01-01') + * } + * }, function(err, apiResponse) {}); + * ``` + */ + addLifecycleRule(rule, optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + options = options || {}; + const rules = Array.isArray(rule) ? rule : [rule]; + for (const curRule of rules) { + if (curRule.condition.createdBefore instanceof Date) { + curRule.condition.createdBefore = curRule.condition.createdBefore + .toISOString() + .replace(/T.+$/, ''); + } + if (curRule.condition.customTimeBefore instanceof Date) { + curRule.condition.customTimeBefore = curRule.condition.customTimeBefore + .toISOString() + .replace(/T.+$/, ''); + } + if (curRule.condition.noncurrentTimeBefore instanceof Date) { + curRule.condition.noncurrentTimeBefore = + curRule.condition.noncurrentTimeBefore + .toISOString() + .replace(/T.+$/, ''); + } + } + if (options.append === false) { + this.setMetadata({ lifecycle: { rule: rules } }, options, callback); + return; + } + // The default behavior appends the previously-defined lifecycle rules with + // the new ones just passed in by the user. + this.getMetadata((err, metadata) => { + var _a, _b; + if (err) { + callback(err); + return; + } + const currentLifecycleRules = Array.isArray((_a = metadata.lifecycle) === null || _a === void 0 ? void 0 : _a.rule) + ? (_b = metadata.lifecycle) === null || _b === void 0 ? void 0 : _b.rule + : []; + this.setMetadata({ + lifecycle: { rule: currentLifecycleRules.concat(rules) }, + }, options, callback); + }); + } + /** + * @typedef {object} CombineOptions + * @property {string} [kmsKeyName] Resource name of the Cloud KMS key, of + * the form + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`, + * that will be used to encrypt the object. Overwrites the object + * metadata's `kms_key_name` value, if any. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback CombineCallback + * @param {?Error} err Request error, if any. + * @param {File} newFile The new {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} CombineResponse + * @property {File} 0 The new {@link File}. + * @property {object} 1 The full API response. + */ + /** + * Combine multiple files into one new file. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/compose| Objects: compose API Documentation} + * + * @throws {Error} if a non-array is provided as sources argument. + * @throws {Error} if no sources are provided. + * @throws {Error} if no destination is provided. + * + * @param {string[]|File[]} sources The source files that will be + * combined. + * @param {string|File} destination The file you would like the + * source files combined into. + * @param {CombineOptions} [options] Configuration options. + * @param {string} [options.kmsKeyName] Resource name of the Cloud KMS key, of + * the form + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`, + * that will be used to encrypt the object. Overwrites the object + * metadata's `kms_key_name` value, if any. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + + * @param {CombineCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const logBucket = storage.bucket('log-bucket'); + * + * const sources = [ + * logBucket.file('2013-logs.txt'), + * logBucket.file('2014-logs.txt') + * ]; + * + * const allLogs = logBucket.file('all-logs.txt'); + * + * logBucket.combine(sources, allLogs, function(err, newFile, apiResponse) { + * // newFile === allLogs + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * logBucket.combine(sources, allLogs).then(function(data) { + * const newFile = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + combine(sources, destination, optionsOrCallback, callback) { + var _a; + if (!Array.isArray(sources) || sources.length === 0) { + throw new Error(BucketExceptionMessages.PROVIDE_SOURCE_FILE); + } + if (!destination) { + throw new Error(BucketExceptionMessages.DESTINATION_FILE_NOT_SPECIFIED); + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, // Not relevant but param is required + AvailableServiceObjectMethods.setMetadata, // Same as above + options); + const convertToFile = (file) => { + if (file instanceof file_js_1.File) { + return file; + } + return this.file(file); + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + sources = sources.map(convertToFile); + const destinationFile = convertToFile(destination); + callback = callback || index_js_1.util.noop; + if (!destinationFile.metadata.contentType) { + const destinationContentType = mime_1.default.getType(destinationFile.name) || undefined; + if (destinationContentType) { + destinationFile.metadata.contentType = destinationContentType; + } + } + let maxRetries = this.storage.retryOptions.maxRetries; + if ((((_a = destinationFile === null || destinationFile === void 0 ? void 0 : destinationFile.instancePreconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === + undefined && + options.ifGenerationMatch === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + maxRetries = 0; + } + if (options.ifGenerationMatch === undefined) { + Object.assign(options, destinationFile.instancePreconditionOpts, options); + } + // Make the request from the destination File object. + destinationFile.request({ + method: 'POST', + uri: '/compose', + maxRetries, + json: { + destination: { + contentType: destinationFile.metadata.contentType, + contentEncoding: destinationFile.metadata.contentEncoding, + }, + sourceObjects: sources.map(source => { + const sourceObject = { + name: source.name, + }; + if (source.metadata && source.metadata.generation) { + sourceObject.generation = parseInt(source.metadata.generation.toString()); + } + return sourceObject; + }), + }, + qs: options, + }, (err, resp) => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + if (err) { + callback(err, null, resp); + return; + } + callback(null, destinationFile, resp); + }); + } + /** + * See a {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll request body}. + * + * @typedef {object} CreateChannelConfig + * @property {string} address The address where notifications are + * delivered for this channel. + * @property {string} [delimiter] Returns results in a directory-like mode. + * @property {number} [maxResults] Maximum number of `items` plus `prefixes` + * to return in a single page of responses. + * @property {string} [pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @property {string} [prefix] Filter results to objects whose names begin + * with this prefix. + * @property {string} [projection=noAcl] Set of properties to return. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {boolean} [versions=false] If `true`, lists all versions of an object + * as distinct results. + */ + /** + * @typedef {object} CreateChannelOptions + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} CreateChannelResponse + * @property {Channel} 0 The new {@link Channel}. + * @property {object} 1 The full API response. + */ + /** + * @callback CreateChannelCallback + * @param {?Error} err Request error, if any. + * @param {Channel} channel The new {@link Channel}. + * @param {object} apiResponse The full API response. + */ + /** + * Create a channel that will be notified when objects in this bucket changes. + * + * @throws {Error} If an ID is not provided. + * @throws {Error} If an address is not provided. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll API Documentation} + * + * @param {string} id The ID of the channel to create. + * @param {CreateChannelConfig} config Configuration for creating channel. + * @param {string} config.address The address where notifications are + * delivered for this channel. + * @param {string} [config.delimiter] Returns results in a directory-like mode. + * @param {number} [config.maxResults] Maximum number of `items` plus `prefixes` + * to return in a single page of responses. + * @param {string} [config.pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @param {string} [config.prefix] Filter results to objects whose names begin + * with this prefix. + * @param {string} [config.projection=noAcl] Set of properties to return. + * @param {string} [config.userProject] The ID of the project which will be + * billed for the request. + * @param {boolean} [config.versions=false] If `true`, lists all versions of an object + * as distinct results. + * @param {CreateChannelOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {CreateChannelCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const id = 'new-channel-id'; + * + * const config = { + * address: 'https://...' + * }; + * + * bucket.createChannel(id, config, function(err, channel, apiResponse) { + * if (!err) { + * // Channel created successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.createChannel(id, config).then(function(data) { + * const channel = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + createChannel(id, config, optionsOrCallback, callback) { + if (typeof id !== 'string') { + throw new Error(BucketExceptionMessages.CHANNEL_ID_REQUIRED); + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.request({ + method: 'POST', + uri: '/o/watch', + json: Object.assign({ + id, + type: 'web_hook', + }, config), + qs: options, + }, (err, apiResponse) => { + if (err) { + callback(err, null, apiResponse); + return; + } + const resourceId = apiResponse.resourceId; + const channel = this.storage.channel(id, resourceId); + channel.metadata = apiResponse; + callback(null, channel, apiResponse); + }); + } + /** + * Metadata to set for the Notification. + * + * @typedef {object} CreateNotificationOptions + * @property {object} [customAttributes] An optional list of additional + * attributes to attach to each Cloud PubSub message published for this + * notification subscription. + * @property {string[]} [eventTypes] If present, only send notifications about + * listed event types. If empty, sent notifications for all event types. + * @property {string} [objectNamePrefix] If present, only apply this + * notification configuration to object names that begin with this prefix. + * @property {string} [payloadFormat] The desired content of the Payload. + * Defaults to `JSON_API_V1`. + * + * Acceptable values are: + * - `JSON_API_V1` + * + * - `NONE` + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback CreateNotificationCallback + * @param {?Error} err Request error, if any. + * @param {Notification} notification The new {@link Notification}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} CreateNotificationResponse + * @property {Notification} 0 The new {@link Notification}. + * @property {object} 1 The full API response. + */ + /** + * Creates a notification subscription for the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/insert| Notifications: insert} + * + * @param {Topic|string} topic The Cloud PubSub topic to which this + * subscription publishes. If the project ID is omitted, the current + * project ID will be used. + * + * Acceptable formats are: + * - `projects/grape-spaceship-123/topics/my-topic` + * + * - `my-topic` + * @param {CreateNotificationOptions} [options] Metadata to set for the + * notification. + * @param {object} [options.customAttributes] An optional list of additional + * attributes to attach to each Cloud PubSub message published for this + * notification subscription. + * @param {string[]} [options.eventTypes] If present, only send notifications about + * listed event types. If empty, sent notifications for all event types. + * @param {string} [options.objectNamePrefix] If present, only apply this + * notification configuration to object names that begin with this prefix. + * @param {string} [options.payloadFormat] The desired content of the Payload. + * Defaults to `JSON_API_V1`. + * + * Acceptable values are: + * - `JSON_API_V1` + * + * - `NONE` + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {CreateNotificationCallback} [callback] Callback function. + * @returns {Promise} + * @throws {Error} If a valid topic is not provided. + * @see Notification#create + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const callback = function(err, notification, apiResponse) { + * if (!err) { + * // The notification was created successfully. + * } + * }; + * + * myBucket.createNotification('my-topic', callback); + * + * //- + * // Configure the nofiication by providing Notification metadata. + * //- + * const metadata = { + * objectNamePrefix: 'prefix-' + * }; + * + * myBucket.createNotification('my-topic', metadata, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.createNotification('my-topic').then(function(data) { + * const notification = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/createNotification.js + * region_tag:storage_create_bucket_notifications + * Another example: + */ + createNotification(topic, optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + const topicIsObject = topic !== null && typeof topic === 'object'; + if (topicIsObject && index_js_1.util.isCustomType(topic, 'pubsub/topic')) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + topic = topic.name; + } + if (typeof topic !== 'string') { + throw new Error(BucketExceptionMessages.TOPIC_NAME_REQUIRED); + } + const body = Object.assign({ topic }, options); + if (body.topic.indexOf('projects') !== 0) { + body.topic = 'projects/{{projectId}}/topics/' + body.topic; + } + body.topic = `//pubsub.${this.storage.universeDomain}/` + body.topic; + if (!body.payloadFormat) { + body.payloadFormat = 'JSON_API_V1'; + } + const query = {}; + if (body.userProject) { + query.userProject = body.userProject; + delete body.userProject; + } + this.request({ + method: 'POST', + uri: '/notificationConfigs', + json: (0, util_js_1.convertObjKeysToSnakeCase)(body), + qs: query, + maxRetries: 0, //explicitly set this value since this is a non-idempotent function + }, (err, apiResponse) => { + if (err) { + callback(err, null, apiResponse); + return; + } + const notification = this.notification(apiResponse.id); + notification.metadata = apiResponse; + callback(null, notification, apiResponse); + }); + } + /** + * @typedef {object} DeleteFilesOptions Query object. See {@link Bucket#getFiles} + * for all of the supported properties. + * @property {boolean} [force] Suppress errors until all files have been + * processed. + */ + /** + * @callback DeleteFilesCallback + * @param {?Error|?Error[]} err Request error, if any, or array of errors from + * files that were not able to be deleted. + * @param {object} [apiResponse] The full API response. + */ + /** + * Iterate over the bucket's files, calling `file.delete()` on each. + * + * This is not an atomic request. A delete attempt will be + * made for each file individually. Any one can fail, in which case only a + * portion of the files you intended to be deleted would have. + * + * Operations are performed in parallel, up to 10 at once. The first error + * breaks the loop and will execute the provided callback with it. Specify + * `{ force: true }` to suppress the errors until all files have had a chance + * to be processed. + * + * File preconditions cannot be passed to this function. It will not retry unless + * the idempotency strategy is set to retry always. + * + * The `query` object passed as the first argument will also be passed to + * {@link Bucket#getFiles}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/delete| Objects: delete API Documentation} + * + * @param {DeleteFilesOptions} [query] Query object. See {@link Bucket#getFiles} + * @param {boolean} [query.force] Suppress errors until all files have been + * processed. + * @param {DeleteFilesCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Delete all of the files in the bucket. + * //- + * bucket.deleteFiles(function(err) {}); + * + * //- + * // By default, if a file cannot be deleted, this method will stop deleting + * // files from your bucket. You can override this setting with `force: + * // true`. + * //- + * bucket.deleteFiles({ + * force: true + * }, function(errors) { + * // `errors`: + * // Array of errors if any occurred, otherwise null. + * }); + * + * //- + * // The first argument to this method acts as a query to + * // {@link Bucket#getFiles}. As an example, you can delete files + * // which match a prefix. + * //- + * bucket.deleteFiles({ + * prefix: 'images/' + * }, function(err) { + * if (!err) { + * // All files in the `images` directory have been deleted. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.deleteFiles().then(function() {}); + * ``` + */ + deleteFiles(queryOrCallback, callback) { + let query = {}; + if (typeof queryOrCallback === 'function') { + callback = queryOrCallback; + } + else if (queryOrCallback) { + query = queryOrCallback; + } + const MAX_PARALLEL_LIMIT = 10; + const MAX_QUEUE_SIZE = 1000; + const errors = []; + const deleteFile = (file) => { + return file.delete(query).catch(err => { + if (!query.force) { + throw err; + } + errors.push(err); + }); + }; + (async () => { + try { + let promises = []; + const limit = (0, p_limit_1.default)(MAX_PARALLEL_LIMIT); + const filesStream = this.getFilesStream(query); + for await (const curFile of filesStream) { + if (promises.length >= MAX_QUEUE_SIZE) { + await Promise.all(promises); + promises = []; + } + promises.push(limit(() => deleteFile(curFile)).catch(e => { + filesStream.destroy(); + throw e; + })); + } + await Promise.all(promises); + callback(errors.length > 0 ? errors : null); + } + catch (e) { + callback(e); + return; + } + })(); + } + /** + * @deprecated + * @typedef {array} DeleteLabelsResponse + * @property {object} 0 The full API response. + */ + /** + * @deprecated + * @callback DeleteLabelsCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata Bucket's metadata. + */ + /** + * @deprecated Use setMetadata directly + * Delete one or more labels from this bucket. + * + * @param {string|string[]} [labels] The labels to delete. If no labels are + * provided, all of the labels are removed. + * @param {DeleteLabelsCallback} [callback] Callback function. + * @param {DeleteLabelsOptions} [options] Options, including precondition options + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Delete all of the labels from this bucket. + * //- + * bucket.deleteLabels(function(err, apiResponse) {}); + * + * //- + * // Delete a single label. + * //- + * bucket.deleteLabels('labelone', function(err, apiResponse) {}); + * + * //- + * // Delete a specific set of labels. + * //- + * bucket.deleteLabels([ + * 'labelone', + * 'labeltwo' + * ], function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.deleteLabels().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + deleteLabels(labelsOrCallbackOrOptions, optionsOrCallback, callback) { + let labels = new Array(); + let options = {}; + if (typeof labelsOrCallbackOrOptions === 'function') { + callback = labelsOrCallbackOrOptions; + } + else if (typeof labelsOrCallbackOrOptions === 'string') { + labels = [labelsOrCallbackOrOptions]; + } + else if (Array.isArray(labelsOrCallbackOrOptions)) { + labels = labelsOrCallbackOrOptions; + } + else if (labelsOrCallbackOrOptions) { + options = labelsOrCallbackOrOptions; + } + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + const deleteLabels = (labels) => { + const nullLabelMap = labels.reduce((nullLabelMap, labelKey) => { + nullLabelMap[labelKey] = null; + return nullLabelMap; + }, {}); + if ((options === null || options === void 0 ? void 0 : options.ifMetagenerationMatch) !== undefined) { + this.setLabels(nullLabelMap, options, callback); + } + else { + this.setLabels(nullLabelMap, callback); + } + }; + if (labels.length === 0) { + this.getLabels((err, labels) => { + if (err) { + callback(err); + return; + } + deleteLabels(Object.keys(labels)); + }); + } + else { + deleteLabels(labels); + } + } + /** + * @typedef {array} DisableRequesterPaysResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DisableRequesterPaysCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + *

+ * Early Access Testers Only + *

+ * This feature is not yet widely-available. + *

+ *
+ * + * Disable `requesterPays` functionality from this bucket. + * + * @param {DisableRequesterPaysCallback} [callback] Callback function. + * @param {DisableRequesterPaysOptions} [options] Options, including precondition options + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.disableRequesterPays(function(err, apiResponse) { + * if (!err) { + * // requesterPays functionality disabled successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.disableRequesterPays().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/requesterPays.js + * region_tag:storage_disable_requester_pays + * Example of disabling requester pays: + */ + disableRequesterPays(optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.setMetadata({ + billing: { + requesterPays: false, + }, + }, options, callback); + } + /** + * Configuration object for enabling logging. + * + * @typedef {object} EnableLoggingOptions + * @property {string|Bucket} [bucket] The bucket for the log entries. By + * default, the current bucket is used. + * @property {string} prefix A unique prefix for log object names. + */ + /** + * Enable logging functionality for this bucket. This will make two API + * requests, first to grant Cloud Storage WRITE permission to the bucket, then + * to set the appropriate configuration on the Bucket's metadata. + * + * @param {EnableLoggingOptions} config Configuration options. + * @param {string|Bucket} [config.bucket] The bucket for the log entries. By + * default, the current bucket is used. + * @param {string} config.prefix A unique prefix for log object names. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * const config = { + * prefix: 'log' + * }; + * + * bucket.enableLogging(config, function(err, apiResponse) { + * if (!err) { + * // Logging functionality enabled successfully. + * } + * }); + * + * ``` + * @example + * Optionally, provide a destination bucket. + * ``` + * const config = { + * prefix: 'log', + * bucket: 'destination-bucket' + * }; + * + * bucket.enableLogging(config, function(err, apiResponse) {}); + * ``` + * + * @example + * If the callback is omitted, we'll return a Promise. + * ``` + * bucket.enableLogging(config).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + enableLogging(config, callback) { + if (!config || + typeof config === 'function' || + typeof config.prefix === 'undefined') { + throw new Error(BucketExceptionMessages.CONFIGURATION_OBJECT_PREFIX_REQUIRED); + } + let logBucket = this.id; + if (config.bucket && config.bucket instanceof Bucket) { + logBucket = config.bucket.id; + } + else if (config.bucket && typeof config.bucket === 'string') { + logBucket = config.bucket; + } + const options = {}; + if (config === null || config === void 0 ? void 0 : config.ifMetagenerationMatch) { + options.ifMetagenerationMatch = config.ifMetagenerationMatch; + } + if (config === null || config === void 0 ? void 0 : config.ifMetagenerationNotMatch) { + options.ifMetagenerationNotMatch = config.ifMetagenerationNotMatch; + } + (async () => { + try { + const [policy] = await this.iam.getPolicy(); + policy.bindings.push({ + members: ['group:cloud-storage-analytics@google.com'], + role: 'roles/storage.objectCreator', + }); + await this.iam.setPolicy(policy); + this.setMetadata({ + logging: { + logBucket, + logObjectPrefix: config.prefix, + }, + }, options, callback); + } + catch (e) { + callback(e); + return; + } + })(); + } + /** + * @typedef {array} EnableRequesterPaysResponse + * @property {object} 0 The full API response. + */ + /** + * @callback EnableRequesterPaysCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + *
+ * Early Access Testers Only + *

+ * This feature is not yet widely-available. + *

+ *
+ * + * Enable `requesterPays` functionality for this bucket. This enables you, the + * bucket owner, to have the requesting user assume the charges for the access + * to your bucket and its contents. + * + * @param {EnableRequesterPaysCallback | EnableRequesterPaysOptions} [optionsOrCallback] + * Callback function or precondition options. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.enableRequesterPays(function(err, apiResponse) { + * if (!err) { + * // requesterPays functionality enabled successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.enableRequesterPays().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/requesterPays.js + * region_tag:storage_enable_requester_pays + * Example of enabling requester pays: + */ + enableRequesterPays(optionsOrCallback, cb) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + cb = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.setMetadata({ + billing: { + requesterPays: true, + }, + }, options, cb); + } + /** + * Create a {@link File} object. See {@link File} to see how to handle + * the different use cases you may have. + * + * @param {string} name The name of the file in this bucket. + * @param {FileOptions} [options] Configuration options. + * @param {string|number} [options.generation] Only use a specific revision of + * this file. + * @param {string} [options.encryptionKey] A custom encryption key. See + * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}. + * @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will + * be used to encrypt the object. Must be in the format: + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`. + * KMS key ring must use the same location as the bucket. + * @param {string} [options.userProject] The ID of the project which will be + * billed for all requests made from File object. + * @returns {File} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const file = bucket.file('my-existing-file.png'); + * ``` + */ + file(name, options) { + if (!name) { + throw Error(BucketExceptionMessages.SPECIFY_FILE_NAME); + } + return new file_js_1.File(this, name, options); + } + /** + * @typedef {array} GetFilesResponse + * @property {File[]} 0 Array of {@link File} instances. + * @param {object} nextQuery 1 A query object to receive more results. + * @param {object} apiResponse 2 The full API response. + */ + /** + * @callback GetFilesCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files Array of {@link File} instances. + * @param {object} nextQuery A query object to receive more results. + * @param {object} apiResponse The full API response. + */ + /** + * Query object for listing files. + * + * @typedef {object} GetFilesOptions + * @property {boolean} [autoPaginate=true] Have pagination handled + * automatically. + * @property {string} [delimiter] Results will contain only objects whose + * names, aside from the prefix, do not contain delimiter. Objects whose + * names, aside from the prefix, contain delimiter will have their name + * truncated after the delimiter, returned in `apiResponse.prefixes`. + * Duplicate prefixes are omitted. + * @property {string} [endOffset] Filter results to objects whose names are + * lexicographically before endOffset. If startOffset is also set, the objects + * listed have names between startOffset (inclusive) and endOffset (exclusive). + * @property {boolean} [includeFoldersAsPrefixes] If true, includes folders and + * managed folders in the set of prefixes returned by the query. Only applicable if + * delimiter is set to / and autoPaginate is set to false. + * See: https://cloud.google.com/storage/docs/managed-folders + * @property {boolean} [includeTrailingDelimiter] If true, objects that end in + * exactly one instance of delimiter have their metadata included in items[] + * in addition to the relevant part of the object name appearing in prefixes[]. + * @property {string} [prefix] Filter results to objects whose names begin + * with this prefix. + * @property {string} [matchGlob] A glob pattern used to filter results, + * for example foo*bar + * @property {number} [maxApiCalls] Maximum number of API calls to make. + * @property {number} [maxResults] Maximum number of items plus prefixes to + * return per call. + * Note: By default will handle pagination automatically + * if more than 1 page worth of results are requested per call. + * When `autoPaginate` is set to `false` the smaller of `maxResults` + * or 1 page of results will be returned per call. + * @property {string} [pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @property {boolean} [softDeleted] If true, only soft-deleted object versions will be + * listed as distinct results in order of generation number. Note `soft_deleted` and + * `versions` cannot be set to true simultaneously. + * @property {string} [startOffset] Filter results to objects whose names are + * lexicographically equal to or after startOffset. If endOffset is also set, + * the objects listed have names between startOffset (inclusive) and endOffset (exclusive). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {boolean} [versions] If true, returns File objects scoped to + * their versions. + */ + /** + * Get {@link File} objects for the files currently in the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/list| Objects: list API Documentation} + * + * @param {GetFilesOptions} [query] Query object for listing files. + * @param {boolean} [query.autoPaginate=true] Have pagination handled + * automatically. + * @param {string} [query.delimiter] Results will contain only objects whose + * names, aside from the prefix, do not contain delimiter. Objects whose + * names, aside from the prefix, contain delimiter will have their name + * truncated after the delimiter, returned in `apiResponse.prefixes`. + * Duplicate prefixes are omitted. + * @param {string} [query.endOffset] Filter results to objects whose names are + * lexicographically before endOffset. If startOffset is also set, the objects + * listed have names between startOffset (inclusive) and endOffset (exclusive). + * @param {boolean} [query.includeFoldersAsPrefixes] If true, includes folders and + * managed folders in the set of prefixes returned by the query. Only applicable if + * delimiter is set to / and autoPaginate is set to false. + * See: https://cloud.google.com/storage/docs/managed-folders + * @param {boolean} [query.includeTrailingDelimiter] If true, objects that end in + * exactly one instance of delimiter have their metadata included in items[] + * in addition to the relevant part of the object name appearing in prefixes[]. + * @param {string} [query.prefix] Filter results to objects whose names begin + * with this prefix. + * @param {number} [query.maxApiCalls] Maximum number of API calls to make. + * @param {number} [query.maxResults] Maximum number of items plus prefixes to + * return per call. + * Note: By default will handle pagination automatically + * if more than 1 page worth of results are requested per call. + * When `autoPaginate` is set to `false` the smaller of `maxResults` + * or 1 page of results will be returned per call. + * @param {string} [query.pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @param {boolean} [query.softDeleted] If true, only soft-deleted object versions will be + * listed as distinct results in order of generation number. Note `soft_deleted` and + * `versions` cannot be set to true simultaneously. + * @param {string} [query.startOffset] Filter results to objects whose names are + * lexicographically equal to or after startOffset. If endOffset is also set, + * the objects listed have names between startOffset (inclusive) and endOffset (exclusive). + * @param {string} [query.userProject] The ID of the project which will be + * billed for the request. + * @param {boolean} [query.versions] If true, returns File objects scoped to + * their versions. + * @param {GetFilesCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getFiles(function(err, files) { + * if (!err) { + * // files is an array of File objects. + * } + * }); + * + * //- + * // If your bucket has versioning enabled, you can get all of your files + * // scoped to their generation. + * //- + * bucket.getFiles({ + * versions: true + * }, function(err, files) { + * // Each file is scoped to its generation. + * }); + * + * //- + * // To control how many API requests are made and page through the results + * // manually, set `autoPaginate` to `false`. + * //- + * const callback = function(err, files, nextQuery, apiResponse) { + * if (nextQuery) { + * // More results exist. + * bucket.getFiles(nextQuery, callback); + * } + * + * // The `metadata` property is populated for you with the metadata at the + * // time of fetching. + * files[0].metadata; + * + * // However, in cases where you are concerned the metadata could have + * // changed, use the `getMetadata` method. + * files[0].getMetadata(function(err, metadata) {}); + * }; + * + * bucket.getFiles({ + * autoPaginate: false + * }, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getFiles().then(function(data) { + * const files = data[0]; + * }); + * + * ``` + * @example + *
Simulating a File System

With `autoPaginate: false`, it's possible to iterate over files which incorporate a common structure using a delimiter.

Consider the following remote objects:

  1. "a"
  2. "a/b/c/d"
  3. "b/d/e"

Using a delimiter of `/` will return a single file, "a".

`apiResponse.prefixes` will return the "sub-directories" that were found:

  1. "a/"
  2. "b/"
+ * ``` + * bucket.getFiles({ + * autoPaginate: false, + * delimiter: '/' + * }, function(err, files, nextQuery, apiResponse) { + * // files = [ + * // {File} // File object for file "a" + * // ] + * + * // apiResponse.prefixes = [ + * // 'a/', + * // 'b/' + * // ] + * }); + * ``` + * + * @example + * Using prefixes, it's now possible to simulate a file system with follow-up requests. + * ``` + * bucket.getFiles({ + * autoPaginate: false, + * delimiter: '/', + * prefix: 'a/' + * }, function(err, files, nextQuery, apiResponse) { + * // No files found within "directory" a. + * // files = [] + * + * // However, a "sub-directory" was found. + * // This prefix can be used to continue traversing the "file system". + * // apiResponse.prefixes = [ + * // 'a/b/' + * // ] + * }); + * ``` + * + * @example include:samples/files.js + * region_tag:storage_list_files + * Another example: + * + * @example include:samples/files.js + * region_tag:storage_list_files_with_prefix + * Example of listing files, filtered by a prefix: + */ + getFiles(queryOrCallback, callback) { + let query = typeof queryOrCallback === 'object' ? queryOrCallback : {}; + if (!callback) { + callback = queryOrCallback; + } + query = Object.assign({}, query); + if (query.fields && + query.autoPaginate && + !query.fields.includes('nextPageToken')) { + query.fields = `${query.fields},nextPageToken`; + } + this.request({ + uri: '/o', + qs: query, + }, (err, resp) => { + if (err) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback(err, null, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const files = itemsArray.map((file) => { + const options = {}; + if (query.fields) { + const fileInstance = file; + return fileInstance; + } + if (query.versions) { + options.generation = file.generation; + } + if (file.kmsKeyName) { + options.kmsKeyName = file.kmsKeyName; + } + const fileInstance = this.file(file.name, options); + fileInstance.metadata = file; + return fileInstance; + }); + let nextQuery = null; + if (resp.nextPageToken) { + nextQuery = Object.assign({}, query, { + pageToken: resp.nextPageToken, + }); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback(null, files, nextQuery, resp); + }); + } + /** + * @deprecated + * @typedef {object} GetLabelsOptions Configuration options for Bucket#getLabels(). + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @deprecated + * @typedef {array} GetLabelsResponse + * @property {object} 0 Object of labels currently set on this bucket. + */ + /** + * @deprecated + * @callback GetLabelsCallback + * @param {?Error} err Request error, if any. + * @param {object} labels Object of labels currently set on this bucket. + */ + /** + * @deprecated Use getMetadata directly. + * Get the labels currently set on this bucket. + * + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetLabelsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getLabels(function(err, labels) { + * if (err) { + * // Error handling omitted. + * } + * + * // labels = { + * // label: 'labelValue', + * // ... + * // } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getLabels().then(function(data) { + * const labels = data[0]; + * }); + * ``` + */ + getLabels(optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.getMetadata(options, (err, metadata) => { + if (err) { + callback(err, null); + return; + } + callback(null, (metadata === null || metadata === void 0 ? void 0 : metadata.labels) || {}); + }); + } + /** + * @typedef {object} GetNotificationsOptions Configuration options for Bucket#getNotification(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback GetNotificationsCallback + * @param {?Error} err Request error, if any. + * @param {Notification[]} notifications Array of {@link Notification} + * instances. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} GetNotificationsResponse + * @property {Notification[]} 0 Array of {@link Notification} instances. + * @property {object} 1 The full API response. + */ + /** + * Retrieves a list of notification subscriptions for a given bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/list| Notifications: list} + * + * @param {GetNotificationsOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetNotificationsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * bucket.getNotifications(function(err, notifications, apiResponse) { + * if (!err) { + * // notifications is an array of Notification objects. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getNotifications().then(function(data) { + * const notifications = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/listNotifications.js + * region_tag:storage_list_bucket_notifications + * Another example: + */ + getNotifications(optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.request({ + uri: '/notificationConfigs', + qs: options, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const notifications = itemsArray.map((notification) => { + const notificationInstance = this.notification(notification.id); + notificationInstance.metadata = notification; + return notificationInstance; + }); + callback(null, notifications, resp); + }); + } + /** + * @typedef {array} GetSignedUrlResponse + * @property {object} 0 The signed URL. + */ + /** + * @callback GetSignedUrlCallback + * @param {?Error} err Request error, if any. + * @param {object} url The signed URL. + */ + /** + * @typedef {object} GetBucketSignedUrlConfig + * @property {string} action Only listing objects within a bucket (HTTP: GET) is supported for bucket-level signed URLs. + * @property {*} expires A timestamp when this link will expire. Any value + * given is passed to `new Date()`. + * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now. + * @property {string} [version='v2'] The signing version to use, either + * 'v2' or 'v4'. + * @property {boolean} [virtualHostedStyle=false] Use virtual hosted-style + * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style + * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instaed of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @property {string} [cname] The cname for this bucket, i.e., + * "https://cdn.example.com". + * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example} + * @property {object} [extensionHeaders] If these headers are used, the + * server will check to make sure that the client provides matching + * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers} + * for the requirements of this feature, most notably: + * - The header name must be prefixed with `x-goog-` + * - The header name must be all lowercase + * + * Note: Multi-valued header passed as an array in the extensionHeaders + * object is converted into a string, delimited by `,` with + * no space. Requests made using the signed URL will need to + * delimit multi-valued headers using a single `,` as well, or + * else the server will report a mismatched signature. + * @property {object} [queryParams] Additional query parameters to include + * in the signed URL. + */ + /** + * Get a signed URL to allow limited time access to a bucket. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed URL. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/access-control/signed-urls| Signed URLs Reference} + * + * @throws {Error} if an expiration timestamp from the past is given. + * + * @param {GetBucketSignedUrlConfig} config Configuration object. + * @param {string} config.action Currently only supports "list" (HTTP: GET). + * @param {*} config.expires A timestamp when this link will expire. Any value + * given is passed to `new Date()`. + * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now. + * @param {string} [config.version='v2'] The signing version to use, either + * 'v2' or 'v4'. + * @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style + * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style + * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instaed of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @param {string} [config.cname] The cname for this bucket, i.e., + * "https://cdn.example.com". + * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example} + * @param {object} [config.extensionHeaders] If these headers are used, the + * server will check to make sure that the client provides matching + * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers} + * for the requirements of this feature, most notably: + * - The header name must be prefixed with `x-goog-` + * - The header name must be all lowercase + * + * Note: Multi-valued header passed as an array in the extensionHeaders + * object is converted into a string, delimited by `,` with + * no space. Requests made using the signed URL will need to + * delimit multi-valued headers using a single `,` as well, or + * else the server will report a mismatched signature. + * @property {object} [config.queryParams] Additional query parameters to include + * in the signed URL. + * @param {GetSignedUrlCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * //- + * // Generate a URL that allows temporary access to list files in a bucket. + * //- + * const request = require('request'); + * + * const config = { + * action: 'list', + * expires: '03-17-2025' + * }; + * + * bucket.getSignedUrl(config, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The bucket is now available to be listed from this URL. + * request(url, function(err, resp) { + * // resp.statusCode = 200 + * }); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getSignedUrl(config).then(function(data) { + * const url = data[0]; + * }); + * ``` + */ + getSignedUrl(cfg, callback) { + const method = BucketActionToHTTPMethod[cfg.action]; + const signConfig = { + method, + expires: cfg.expires, + version: cfg.version, + cname: cfg.cname, + extensionHeaders: cfg.extensionHeaders || {}, + queryParams: cfg.queryParams || {}, + host: cfg.host, + signingEndpoint: cfg.signingEndpoint, + }; + if (!this.signer) { + this.signer = new signer_js_1.URLSigner(this.storage.authClient, this, undefined, this.storage); + } + this.signer + .getSignedUrl(signConfig) + .then(signedUrl => callback(null, signedUrl), callback); + } + /** + * @callback BucketLockCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Lock a previously-defined retention policy. This will prevent changes to + * the policy. + * + * @throws {Error} if a metageneration is not provided. + * + * @param {number|string} metageneration The bucket's metageneration. This is + * accesssible from calling {@link File#getMetadata}. + * @param {BucketLockCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * const metageneration = 2; + * + * bucket.lock(metageneration, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.lock(metageneration).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + lock(metageneration, callback) { + const metatype = typeof metageneration; + if (metatype !== 'number' && metatype !== 'string') { + throw new Error(BucketExceptionMessages.METAGENERATION_NOT_PROVIDED); + } + this.request({ + method: 'POST', + uri: '/lockRetentionPolicy', + qs: { + ifMetagenerationMatch: metageneration, + }, + }, callback); + } + /** + * @typedef {object} RestoreOptions Options for Bucket#restore(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/restore#resource| Object resource}. + * @param {number} [generation] If present, selects a specific revision of this object. + * @param {string} [projection] Specifies the set of properties to return. If used, must be 'full' or 'noAcl'. + */ + /** + * Restores a soft-deleted bucket + * @param {RestoreOptions} options Restore options. + * @returns {Promise} + */ + async restore(options) { + const [bucket] = await this.request({ + method: 'POST', + uri: '/restore', + qs: options, + }); + return bucket; + } + /** + * @typedef {array} MakeBucketPrivateResponse + * @property {File[]} 0 List of files made private. + */ + /** + * @callback MakeBucketPrivateCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files List of files made private. + */ + /** + * @typedef {object} MakeBucketPrivateOptions + * @property {boolean} [includeFiles=false] Make each file in the bucket + * private. + * @property {Metadata} [metadata] Define custom metadata properties to define + * along with the operation. + * @property {boolean} [force] Queue errors occurred while making files + * private until all files have been processed. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Make the bucket listing private. + * + * You may also choose to make the contents of the bucket private by + * specifying `includeFiles: true`. This will automatically run + * {@link File#makePrivate} for every file in the bucket. + * + * When specifying `includeFiles: true`, use `force: true` to delay execution + * of your callback until all files have been processed. By default, the + * callback is executed after the first error. Use `force` to queue such + * errors until all files have been processed, after which they will be + * returned as an array as the first argument to your callback. + * + * NOTE: This may cause the process to be long-running and use a high number + * of requests. Use with caution. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @param {MakeBucketPrivateOptions} [options] Configuration options. + * @param {boolean} [options.includeFiles=false] Make each file in the bucket + * private. + * @param {Metadata} [options.metadata] Define custom metadata properties to define + * along with the operation. + * @param {boolean} [options.force] Queue errors occurred while making files + * private until all files have been processed. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {MakeBucketPrivateCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Make the bucket private. + * //- + * bucket.makePrivate(function(err) {}); + * + * //- + * // Make the bucket and its contents private. + * //- + * const opts = { + * includeFiles: true + * }; + * + * bucket.makePrivate(opts, function(err, files) { + * // `err`: + * // The first error to occur, otherwise null. + * // + * // `files`: + * // Array of files successfully made private in the bucket. + * }); + * + * //- + * // Make the bucket and its contents private, using force to suppress errors + * // until all files have been processed. + * //- + * const opts = { + * includeFiles: true, + * force: true + * }; + * + * bucket.makePrivate(opts, function(errors, files) { + * // `errors`: + * // Array of errors if any occurred, otherwise null. + * // + * // `files`: + * // Array of files successfully made private in the bucket. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.makePrivate(opts).then(function(data) { + * const files = data[0]; + * }); + * ``` + */ + makePrivate(optionsOrCallback, callback) { + var _a, _b, _c, _d; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + options.private = true; + const query = { + predefinedAcl: 'projectPrivate', + }; + if (options.userProject) { + query.userProject = options.userProject; + } + if ((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) { + query.ifGenerationMatch = options.preconditionOpts.ifGenerationMatch; + } + if ((_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationNotMatch) { + query.ifGenerationNotMatch = + options.preconditionOpts.ifGenerationNotMatch; + } + if ((_c = options.preconditionOpts) === null || _c === void 0 ? void 0 : _c.ifMetagenerationMatch) { + query.ifMetagenerationMatch = + options.preconditionOpts.ifMetagenerationMatch; + } + if ((_d = options.preconditionOpts) === null || _d === void 0 ? void 0 : _d.ifMetagenerationNotMatch) { + query.ifMetagenerationNotMatch = + options.preconditionOpts.ifMetagenerationNotMatch; + } + // You aren't allowed to set both predefinedAcl & acl properties on a bucket + // so acl must explicitly be nullified. + const metadata = { ...options.metadata, acl: null }; + this.setMetadata(metadata, query, (err) => { + if (err) { + callback(err); + } + const internalCall = () => { + if (options.includeFiles) { + return (0, util_1.promisify)(this.makeAllFilesPublicPrivate_).call(this, options); + } + return Promise.resolve([]); + }; + internalCall() + .then(files => callback(null, files)) + .catch(callback); + }); + } + /** + * @typedef {object} MakeBucketPublicOptions + * @property {boolean} [includeFiles=false] Make each file in the bucket + * private. + * @property {boolean} [force] Queue errors occurred while making files + * private until all files have been processed. + */ + /** + * @callback MakeBucketPublicCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files List of files made public. + */ + /** + * @typedef {array} MakeBucketPublicResponse + * @property {File[]} 0 List of files made public. + */ + /** + * Make the bucket publicly readable. + * + * You may also choose to make the contents of the bucket publicly readable by + * specifying `includeFiles: true`. This will automatically run + * {@link File#makePublic} for every file in the bucket. + * + * When specifying `includeFiles: true`, use `force: true` to delay execution + * of your callback until all files have been processed. By default, the + * callback is executed after the first error. Use `force` to queue such + * errors until all files have been processed, after which they will be + * returned as an array as the first argument to your callback. + * + * NOTE: This may cause the process to be long-running and use a high number + * of requests. Use with caution. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @param {MakeBucketPublicOptions} [options] Configuration options. + * @param {boolean} [options.includeFiles=false] Make each file in the bucket + * private. + * @param {boolean} [options.force] Queue errors occurred while making files + * private until all files have been processed. + * @param {MakeBucketPublicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Make the bucket publicly readable. + * //- + * bucket.makePublic(function(err) {}); + * + * //- + * // Make the bucket and its contents publicly readable. + * //- + * const opts = { + * includeFiles: true + * }; + * + * bucket.makePublic(opts, function(err, files) { + * // `err`: + * // The first error to occur, otherwise null. + * // + * // `files`: + * // Array of files successfully made public in the bucket. + * }); + * + * //- + * // Make the bucket and its contents publicly readable, using force to + * // suppress errors until all files have been processed. + * //- + * const opts = { + * includeFiles: true, + * force: true + * }; + * + * bucket.makePublic(opts, function(errors, files) { + * // `errors`: + * // Array of errors if any occurred, otherwise null. + * // + * // `files`: + * // Array of files successfully made public in the bucket. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.makePublic(opts).then(function(data) { + * const files = data[0]; + * }); + * ``` + */ + makePublic(optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const req = { public: true, ...options }; + this.acl + .add({ + entity: 'allUsers', + role: 'READER', + }) + .then(() => { + return this.acl.default.add({ + entity: 'allUsers', + role: 'READER', + }); + }) + .then(() => { + if (req.includeFiles) { + return (0, util_1.promisify)(this.makeAllFilesPublicPrivate_).call(this, req); + } + return []; + }) + .then(files => callback(null, files), callback); + } + /** + * Get a reference to a Cloud Pub/Sub Notification. + * + * @param {string} id ID of notification. + * @returns {Notification} + * @see Notification + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const notification = bucket.notification('1'); + * ``` + */ + notification(id) { + if (!id) { + throw new Error(BucketExceptionMessages.SUPPLY_NOTIFICATION_ID); + } + return new notification_js_1.Notification(this, id); + } + /** + * Remove an already-existing retention policy from this bucket, if it is not + * locked. + * + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @param {SetBucketMetadataOptions} [options] Options, including precondition options + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * bucket.removeRetentionPeriod(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.removeRetentionPeriod().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + removeRetentionPeriod(optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + this.setMetadata({ + retentionPolicy: null, + }, options, callback); + } + /** + * Makes request and applies userProject query parameter if necessary. + * + * @private + * + * @param {object} reqOpts - The request options. + * @param {function} callback - The callback function. + */ + request(reqOpts, callback) { + if (this.userProject && (!reqOpts.qs || !reqOpts.qs.userProject)) { + reqOpts.qs = { ...reqOpts.qs, userProject: this.userProject }; + } + return super.request(reqOpts, callback); + } + /** + * @deprecated + * @typedef {array} SetLabelsResponse + * @property {object} 0 The bucket metadata. + */ + /** + * @deprecated + * @callback SetLabelsCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The bucket metadata. + */ + /** + * @deprecated + * @typedef {object} SetLabelsOptions Configuration options for Bucket#setLabels(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @deprecated Use setMetadata directly. + * Set labels on the bucket. + * + * This makes an underlying call to {@link Bucket#setMetadata}, which + * is a PATCH request. This means an individual label can be overwritten, but + * unmentioned labels will not be touched. + * + * @param {object} labels Labels to set on the bucket. + * @param {SetLabelsOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {SetLabelsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * const labels = { + * labelone: 'labelonevalue', + * labeltwo: 'labeltwovalue' + * }; + * + * bucket.setLabels(labels, function(err, metadata) { + * if (!err) { + * // Labels set successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setLabels(labels).then(function(data) { + * const metadata = data[0]; + * }); + * ``` + */ + setLabels(labels, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + callback = callback || index_js_1.util.noop; + this.setMetadata({ labels }, options, callback); + } + setMetadata(metadata, optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, AvailableServiceObjectMethods.setMetadata, options); + super + .setMetadata(metadata, options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } + /** + * Lock all objects contained in the bucket, based on their creation time. Any + * attempt to overwrite or delete objects younger than the retention period + * will result in a `PERMISSION_DENIED` error. + * + * An unlocked retention policy can be modified or removed from the bucket via + * {@link File#removeRetentionPeriod} and {@link File#setRetentionPeriod}. A + * locked retention policy cannot be removed or shortened in duration for the + * lifetime of the bucket. Attempting to remove or decrease period of a locked + * retention policy will result in a `PERMISSION_DENIED` error. You can still + * increase the policy. + * + * @param {*} duration In seconds, the minimum retention time for all objects + * contained in this bucket. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @param {SetBucketMetadataCallback} [options] Options, including precondition options. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * const DURATION_SECONDS = 15780000; // 6 months. + * + * //- + * // Lock the objects in this bucket for 6 months. + * //- + * bucket.setRetentionPeriod(DURATION_SECONDS, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setRetentionPeriod(DURATION_SECONDS).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setRetentionPeriod(duration, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + this.setMetadata({ + retentionPolicy: { + retentionPeriod: duration.toString(), + }, + }, options, callback); + } + /** + * + * @typedef {object} Cors + * @property {number} [maxAgeSeconds] The number of seconds the browser is + * allowed to make requests before it must repeat the preflight request. + * @property {string[]} [method] HTTP method allowed for cross origin resource + * sharing with this bucket. + * @property {string[]} [origin] an origin allowed for cross origin resource + * sharing with this bucket. + * @property {string[]} [responseHeader] A header allowed for cross origin + * resource sharing with this bucket. + */ + /** + * This can be used to set the CORS configuration on the bucket. + * + * The configuration will be overwritten with the value passed into this. + * + * @param {Cors[]} corsConfiguration The new CORS configuration to set + * @param {number} [corsConfiguration.maxAgeSeconds] The number of seconds the browser is + * allowed to make requests before it must repeat the preflight request. + * @param {string[]} [corsConfiguration.method] HTTP method allowed for cross origin resource + * sharing with this bucket. + * @param {string[]} [corsConfiguration.origin] an origin allowed for cross origin resource + * sharing with this bucket. + * @param {string[]} [corsConfiguration.responseHeader] A header allowed for cross origin + * resource sharing with this bucket. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @param {SetBucketMetadataOptions} [options] Options, including precondition options. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * const corsConfiguration = [{maxAgeSeconds: 3600}]; // 1 hour + * bucket.setCorsConfiguration(corsConfiguration); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setCorsConfiguration(corsConfiguration).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setCorsConfiguration(corsConfiguration, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + this.setMetadata({ + cors: corsConfiguration, + }, options, callback); + } + /** + * @typedef {object} SetBucketStorageClassOptions + * @property {string} [userProject] - The ID of the project which will be + * billed for the request. + */ + /** + * @callback SetBucketStorageClassCallback + * @param {?Error} err Request error, if any. + */ + /** + * Set the default storage class for new files in this bucket. + * + * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes} + * + * @param {string} storageClass The new storage class. (`standard`, + * `nearline`, `coldline`, or `archive`). + * **Note:** The storage classes `multi_regional`, `regional`, and + * `durable_reduced_availability` are now legacy and will be deprecated in + * the future. + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] - The ID of the project which will be + * billed for the request. + * @param {SetStorageClassCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.setStorageClass('nearline', function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * // The storage class was updated successfully. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setStorageClass('nearline').then(function() {}); + * ``` + */ + setStorageClass(storageClass, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + // In case we get input like `storageClass`, convert to `storage_class`. + storageClass = storageClass + .replace(/-/g, '_') + .replace(/([a-z])([A-Z])/g, (_, low, up) => { + return low + '_' + up; + }) + .toUpperCase(); + this.setMetadata({ storageClass }, options, callback); + } + /** + * Set a user project to be billed for all requests made from this Bucket + * object and any files referenced from this Bucket object. + * + * @param {string} userProject The user project. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.setUserProject('grape-spaceship-123'); + * ``` + */ + setUserProject(userProject) { + this.userProject = userProject; + const methods = [ + 'create', + 'delete', + 'exists', + 'get', + 'getMetadata', + 'setMetadata', + ]; + methods.forEach(method => { + const methodConfig = this.methods[method]; + if (typeof methodConfig === 'object') { + if (typeof methodConfig.reqOpts === 'object') { + Object.assign(methodConfig.reqOpts.qs, { userProject }); + } + else { + methodConfig.reqOpts = { + qs: { userProject }, + }; + } + } + }); + } + /** + * @typedef {object} UploadOptions Configuration options for Bucket#upload(). + * @property {string|File} [destination] The place to save + * your file. If given a string, the file will be uploaded to the bucket + * using the string as a filename. When given a File object, your local + * file will be uploaded to the File object's bucket and under the File + * object's name. Lastly, when this argument is omitted, the file is uploaded + * to your bucket using the name of the local file. + * @property {string} [encryptionKey] A custom encryption key. See + * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}. + * @property {boolean} [gzip] Automatically gzip the file. This will set + * `options.metadata.contentEncoding` to `gzip`. + * @property {string} [kmsKeyName] The name of the Cloud KMS key that will + * be used to encrypt the object. Must be in the format: + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`. + * @property {object} [metadata] See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body}. + * @property {string} [offset] The starting byte of the upload stream, for + * resuming an interrupted upload. Defaults to 0. + * @property {string} [predefinedAcl] Apply a predefined set of access + * controls to this object. + * + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @property {boolean} [private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @property {boolean} [public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @property {boolean} [resumable=true] Resumable uploads are automatically + * enabled and must be shut off explicitly by setting to false. + * @property {number} [timeout=60000] Set the HTTP request timeout in + * milliseconds. This option is not available for resumable uploads. + * Default: `60000` + * @property {string} [uri] The URI for an already-created resumable + * upload. See {@link File#createResumableUpload}. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string|boolean} [validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with an + * MD5 checksum for maximum reliability. CRC32c will provide better + * performance with less reliability. You may also choose to skip + * validation completely, however this is **not recommended**. + */ + /** + * @typedef {array} UploadResponse + * @property {object} 0 The uploaded {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback UploadCallback + * @param {?Error} err Request error, if any. + * @param {object} file The uploaded {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * Upload a file to the bucket. This is a convenience method that wraps + * {@link File#createWriteStream}. + * + * Resumable uploads are enabled by default + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload#uploads| Upload Options (Simple or Resumable)} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert| Objects: insert API Documentation} + * + * @param {string} pathString The fully qualified path to the file you + * wish to upload to your bucket. + * @param {UploadOptions} [options] Configuration options. + * @param {string|File} [options.destination] The place to save + * your file. If given a string, the file will be uploaded to the bucket + * using the string as a filename. When given a File object, your local + * file will be uploaded to the File object's bucket and under the File + * object's name. Lastly, when this argument is omitted, the file is uploaded + * to your bucket using the name of the local file. + * @param {string} [options.encryptionKey] A custom encryption key. See + * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}. + * @param {boolean} [options.gzip] Automatically gzip the file. This will set + * `options.metadata.contentEncoding` to `gzip`. + * @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will + * be used to encrypt the object. Must be in the format: + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`. + * @param {object} [options.metadata] See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body}. + * @param {string} [options.offset] The starting byte of the upload stream, for + * resuming an interrupted upload. Defaults to 0. + * @param {string} [options.predefinedAcl] Apply a predefined set of access + * controls to this object. + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @param {boolean} [options.private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @param {boolean} [options.public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @param {boolean} [options.resumable=true] Resumable uploads are automatically + * enabled and must be shut off explicitly by setting to false. + * @param {number} [options.timeout=60000] Set the HTTP request timeout in + * milliseconds. This option is not available for resumable uploads. + * Default: `60000` + * @param {string} [options.uri] The URI for an already-created resumable + * upload. See {@link File#createResumableUpload}. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {string|boolean} [options.validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with an + * MD5 checksum for maximum reliability. CRC32c will provide better + * performance with less reliability. You may also choose to skip + * validation completely, however this is **not recommended**. + * @param {UploadCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Upload a file from a local path. + * //- + * bucket.upload('/local/path/image.png', function(err, file, apiResponse) { + * // Your bucket now contains: + * // - "image.png" (with the contents of `/local/path/image.png') + * + * // `file` is an instance of a File object that refers to your new file. + * }); + * + * + * //- + * // It's not always that easy. You will likely want to specify the filename + * // used when your new file lands in your bucket. + * // + * // You may also want to set metadata or customize other options. + * //- + * const options = { + * destination: 'new-image.png', + * validation: 'crc32c', + * metadata: { + * metadata: { + * event: 'Fall trip to the zoo' + * } + * } + * }; + * + * bucket.upload('local-image.png', options, function(err, file) { + * // Your bucket now contains: + * // - "new-image.png" (with the contents of `local-image.png') + * + * // `file` is an instance of a File object that refers to your new file. + * }); + * + * //- + * // You can also have a file gzip'd on the fly. + * //- + * bucket.upload('index.html', { gzip: true }, function(err, file) { + * // Your bucket now contains: + * // - "index.html" (automatically compressed with gzip) + * + * // Downloading the file with `file.download` will automatically decode + * the + * // file. + * }); + * + * //- + * // You may also re-use a File object, {File}, that references + * // the file you wish to create or overwrite. + * //- + * const options = { + * destination: bucket.file('existing-file.png'), + * resumable: false + * }; + * + * bucket.upload('local-img.png', options, function(err, newFile) { + * // Your bucket now contains: + * // - "existing-file.png" (with the contents of `local-img.png') + * + * // Note: + * // The `newFile` parameter is equal to `file`. + * }); + * + * //- + * // To use + * // + * // Customer-supplied Encryption Keys, provide the `encryptionKey` + * option. + * //- + * const crypto = require('crypto'); + * const encryptionKey = crypto.randomBytes(32); + * + * bucket.upload('img.png', { + * encryptionKey: encryptionKey + * }, function(err, newFile) { + * // `img.png` was uploaded with your custom encryption key. + * + * // `newFile` is already configured to use the encryption key when making + * // operations on the remote object. + * + * // However, to use your encryption key later, you must create a `File` + * // instance with the `key` supplied: + * const file = bucket.file('img.png', { + * encryptionKey: encryptionKey + * }); + * + * // Or with `file#setEncryptionKey`: + * const file = bucket.file('img.png'); + * file.setEncryptionKey(encryptionKey); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.upload('local-image.png').then(function(data) { + * const file = data[0]; + * }); + * + * To upload a file from a URL, use {@link File#createWriteStream}. + * + * ``` + * @example include:samples/files.js + * region_tag:storage_upload_file + * Another example: + * + * @example include:samples/encryption.js + * region_tag:storage_upload_encrypted_file + * Example of uploading an encrypted file: + */ + upload(pathString, optionsOrCallback, callback) { + var _a, _b; + const upload = (numberOfRetries) => { + const returnValue = (0, async_retry_1.default)(async (bail) => { + await new Promise((resolve, reject) => { + var _a, _b; + if (numberOfRetries === 0 && + ((_b = (_a = newFile === null || newFile === void 0 ? void 0 : newFile.storage) === null || _a === void 0 ? void 0 : _a.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry)) { + newFile.storage.retryOptions.autoRetry = false; + } + const writable = newFile.createWriteStream(options); + if (options.onUploadProgress) { + writable.on('progress', options.onUploadProgress); + } + fs.createReadStream(pathString) + .on('error', bail) + .pipe(writable) + .on('error', err => { + if (this.storage.retryOptions.autoRetry && + this.storage.retryOptions.retryableErrorFn(err)) { + return reject(err); + } + else { + return bail(err); + } + }) + .on('finish', () => { + return resolve(); + }); + }); + }, { + retries: numberOfRetries, + factor: this.storage.retryOptions.retryDelayMultiplier, + maxTimeout: this.storage.retryOptions.maxRetryDelay * 1000, //convert to milliseconds + maxRetryTime: this.storage.retryOptions.totalTimeout * 1000, //convert to milliseconds + }); + if (!callback) { + return returnValue; + } + else { + return returnValue + .then(() => { + if (callback) { + return callback(null, newFile, newFile.metadata); + } + }) + .catch(callback); + } + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (global['GCLOUD_SANDBOX_ENV']) { + return; + } + let options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + options = Object.assign({ + metadata: {}, + }, options); + // Do not retry if precondition option ifGenerationMatch is not set + // because this is a file operation + let maxRetries = this.storage.retryOptions.maxRetries; + if ((((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === undefined && + ((_b = this.instancePreconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch) === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + maxRetries = 0; + } + let newFile; + if (options.destination instanceof file_js_1.File) { + newFile = options.destination; + } + else if (options.destination !== null && + typeof options.destination === 'string') { + // Use the string as the name of the file. + newFile = this.file(options.destination, { + encryptionKey: options.encryptionKey, + kmsKeyName: options.kmsKeyName, + preconditionOpts: this.instancePreconditionOpts, + }); + } + else { + // Resort to using the name of the incoming file. + const destination = path.basename(pathString); + newFile = this.file(destination, { + encryptionKey: options.encryptionKey, + kmsKeyName: options.kmsKeyName, + preconditionOpts: this.instancePreconditionOpts, + }); + } + upload(maxRetries); + } + /** + * @private + * + * @typedef {object} MakeAllFilesPublicPrivateOptions + * @property {boolean} [force] Suppress errors until all files have been + * processed. + * @property {boolean} [private] Make files private. + * @property {boolean} [public] Make files public. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @private + * + * @callback SetBucketMetadataCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files Files that were updated. + */ + /** + * @typedef {array} MakeAllFilesPublicPrivateResponse + * @property {File[]} 0 List of files affected. + */ + /** + * Iterate over all of a bucket's files, calling `file.makePublic()` (public) + * or `file.makePrivate()` (private) on each. + * + * Operations are performed in parallel, up to 10 at once. The first error + * breaks the loop, and will execute the provided callback with it. Specify + * `{ force: true }` to suppress the errors. + * + * @private + * + * @param {MakeAllFilesPublicPrivateOptions} [options] Configuration options. + * @param {boolean} [options.force] Suppress errors until all files have been + * processed. + * @param {boolean} [options.private] Make files private. + * @param {boolean} [options.public] Make files public. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + + * @param {MakeAllFilesPublicPrivateCallback} callback Callback function. + * + * @return {Promise} + */ + makeAllFilesPublicPrivate_(optionsOrCallback, callback) { + const MAX_PARALLEL_LIMIT = 10; + const errors = []; + const updatedFiles = []; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const processFile = async (file) => { + try { + await (options.public ? file.makePublic() : file.makePrivate(options)); + updatedFiles.push(file); + } + catch (e) { + if (!options.force) { + throw e; + } + errors.push(e); + } + }; + this.getFiles(options) + .then(([files]) => { + const limit = (0, p_limit_1.default)(MAX_PARALLEL_LIMIT); + const promises = files.map(file => { + return limit(() => processFile(file)); + }); + return Promise.all(promises); + }) + .then(() => callback(errors.length > 0 ? errors : null, updatedFiles), err => callback(err, updatedFiles)); + } + getId() { + return this.id; + } + disableAutoRetryConditionallyIdempotent_( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + coreOpts, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + methodType, localPreconditionOptions) { + var _a, _b; + if (typeof coreOpts === 'object' && + ((_b = (_a = coreOpts === null || coreOpts === void 0 ? void 0 : coreOpts.reqOpts) === null || _a === void 0 ? void 0 : _a.qs) === null || _b === void 0 ? void 0 : _b.ifMetagenerationMatch) === undefined && + (localPreconditionOptions === null || localPreconditionOptions === void 0 ? void 0 : localPreconditionOptions.ifMetagenerationMatch) === undefined && + (methodType === AvailableServiceObjectMethods.setMetadata || + methodType === AvailableServiceObjectMethods.delete) && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) { + this.storage.retryOptions.autoRetry = false; + } + else if (this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + this.storage.retryOptions.autoRetry = false; + } + } +} +exports.Bucket = Bucket; +/*! Developer Documentation + * + * These methods can be auto-paginated. + */ +paginator_1.paginator.extend(Bucket, 'getFiles'); +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Bucket, { + exclude: ['cloudStorageURI', 'request', 'file', 'notification', 'restore'], +}); + + +/***/ }), + +/***/ 12658: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Channel = void 0; +const index_js_1 = __nccwpck_require__(11325); +const promisify_1 = __nccwpck_require__(60206); +/** + * Create a channel object to interact with a Cloud Storage channel. + * + * See {@link https://cloud.google.com/storage/docs/object-change-notification| Object Change Notification} + * + * @class + * + * @param {string} id The ID of the channel. + * @param {string} resourceId The resource ID of the channel. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const channel = storage.channel('id', 'resource-id'); + * ``` + */ +class Channel extends index_js_1.ServiceObject { + constructor(storage, id, resourceId) { + const config = { + parent: storage, + baseUrl: '/channels', + // An ID shouldn't be included in the API requests. + // RE: + // https://github.com/GoogleCloudPlatform/google-cloud-node/issues/1145 + id: '', + methods: { + // Only need `request`. + }, + }; + super(config); + this.metadata.id = id; + this.metadata.resourceId = resourceId; + } + /** + * @typedef {array} StopResponse + * @property {object} 0 The full API response. + */ + /** + * @callback StopCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Stop this channel. + * + * @param {StopCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const channel = storage.channel('id', 'resource-id'); + * channel.stop(function(err, apiResponse) { + * if (!err) { + * // Channel stopped successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * channel.stop().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + stop(callback) { + callback = callback || index_js_1.util.noop; + this.request({ + method: 'POST', + uri: '/stop', + json: this.metadata, + }, (err, apiResponse) => { + callback(err, apiResponse); + }); + } +} +exports.Channel = Channel; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Channel); + + +/***/ }), + +/***/ 34317: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _CRC32C_crc32c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CRC32C_EXTENSION_TABLE = exports.CRC32C_EXTENSIONS = exports.CRC32C_EXCEPTION_MESSAGES = exports.CRC32C_DEFAULT_VALIDATOR_GENERATOR = exports.CRC32C = void 0; +const fs_1 = __nccwpck_require__(79896); +/** + * Ported from {@link https://github.com/google/crc32c/blob/21fc8ef30415a635e7351ffa0e5d5367943d4a94/src/crc32c_portable.cc#L16-L59 github.com/google/crc32c} + */ +const CRC32C_EXTENSIONS = [ + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, + 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c, + 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, + 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512, + 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, + 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf, + 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, + 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f, + 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, + 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e, + 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, + 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4, + 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, + 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5, + 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, + 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905, + 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, + 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8, + 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, + 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6, + 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, + 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351, +]; +exports.CRC32C_EXTENSIONS = CRC32C_EXTENSIONS; +const CRC32C_EXTENSION_TABLE = new Int32Array(CRC32C_EXTENSIONS); +exports.CRC32C_EXTENSION_TABLE = CRC32C_EXTENSION_TABLE; +const CRC32C_DEFAULT_VALIDATOR_GENERATOR = () => new CRC32C(); +exports.CRC32C_DEFAULT_VALIDATOR_GENERATOR = CRC32C_DEFAULT_VALIDATOR_GENERATOR; +const CRC32C_EXCEPTION_MESSAGES = { + INVALID_INIT_BASE64_RANGE: (l) => `base64-encoded data expected to equal 4 bytes, not ${l}`, + INVALID_INIT_BUFFER_LENGTH: (l) => `Buffer expected to equal 4 bytes, not ${l}`, + INVALID_INIT_INTEGER: (l) => `Number expected to be a safe, unsigned 32-bit integer, not ${l}`, +}; +exports.CRC32C_EXCEPTION_MESSAGES = CRC32C_EXCEPTION_MESSAGES; +class CRC32C { + /** + * Constructs a new `CRC32C` object. + * + * Reconstruction is recommended via the `CRC32C.from` static method. + * + * @param initialValue An initial CRC32C value - a signed 32-bit integer. + */ + constructor(initialValue = 0) { + /** Current CRC32C value */ + _CRC32C_crc32c.set(this, 0); + __classPrivateFieldSet(this, _CRC32C_crc32c, initialValue, "f"); + } + /** + * Calculates a CRC32C from a provided buffer. + * + * Implementation inspired from: + * - {@link https://github.com/google/crc32c/blob/21fc8ef30415a635e7351ffa0e5d5367943d4a94/src/crc32c_portable.cc github.com/google/crc32c} + * - {@link https://github.com/googleapis/python-crc32c/blob/a595e758c08df445a99c3bf132ee8e80a3ec4308/src/google_crc32c/python.py github.com/googleapis/python-crc32c} + * - {@link https://github.com/googleapis/java-storage/pull/1376/files github.com/googleapis/java-storage} + * + * @param data The `Buffer` to generate the CRC32C from + */ + update(data) { + let current = __classPrivateFieldGet(this, _CRC32C_crc32c, "f") ^ 0xffffffff; + for (const d of data) { + const tablePoly = CRC32C.CRC32C_EXTENSION_TABLE[(d ^ current) & 0xff]; + current = tablePoly ^ (current >>> 8); + } + __classPrivateFieldSet(this, _CRC32C_crc32c, current ^ 0xffffffff, "f"); + } + /** + * Validates a provided input to the current CRC32C value. + * + * @param input A Buffer, `CRC32C`-compatible object, base64-encoded data (string), or signed 32-bit integer + */ + validate(input) { + if (typeof input === 'number') { + return input === __classPrivateFieldGet(this, _CRC32C_crc32c, "f"); + } + else if (typeof input === 'string') { + return input === this.toString(); + } + else if (Buffer.isBuffer(input)) { + return Buffer.compare(input, this.toBuffer()) === 0; + } + else { + // `CRC32C`-like object + return input.toString() === this.toString(); + } + } + /** + * Returns a `Buffer` representation of the CRC32C value + */ + toBuffer() { + const buffer = Buffer.alloc(4); + buffer.writeInt32BE(__classPrivateFieldGet(this, _CRC32C_crc32c, "f")); + return buffer; + } + /** + * Returns a JSON-compatible, base64-encoded representation of the CRC32C value. + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify `JSON#stringify`} + */ + toJSON() { + return this.toString(); + } + /** + * Returns a base64-encoded representation of the CRC32C value. + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString `Object#toString`} + */ + toString() { + return this.toBuffer().toString('base64'); + } + /** + * Returns the `number` representation of the CRC32C value as a signed 32-bit integer + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf `Object#valueOf`} + */ + valueOf() { + return __classPrivateFieldGet(this, _CRC32C_crc32c, "f"); + } + /** + * Generates a `CRC32C` from a compatible buffer format. + * + * @param value 4-byte `ArrayBufferView`/`Buffer`/`TypedArray` + */ + static fromBuffer(value) { + let buffer; + if (Buffer.isBuffer(value)) { + buffer = value; + } + else if ('buffer' in value) { + // `ArrayBufferView` + buffer = Buffer.from(value.buffer); + } + else { + // `ArrayBuffer` + buffer = Buffer.from(value); + } + if (buffer.byteLength !== 4) { + throw new RangeError(CRC32C_EXCEPTION_MESSAGES.INVALID_INIT_BUFFER_LENGTH(buffer.byteLength)); + } + return new CRC32C(buffer.readInt32BE()); + } + static async fromFile(file) { + const crc32c = new CRC32C(); + await new Promise((resolve, reject) => { + (0, fs_1.createReadStream)(file) + .on('data', (d) => { + if (typeof d === 'string') { + crc32c.update(Buffer.from(d)); + } + else { + crc32c.update(d); + } + }) + .on('end', () => resolve()) + .on('error', reject); + }); + return crc32c; + } + /** + * Generates a `CRC32C` from 4-byte base64-encoded data (string). + * + * @param value 4-byte base64-encoded data (string) + */ + static fromString(value) { + const buffer = Buffer.from(value, 'base64'); + if (buffer.byteLength !== 4) { + throw new RangeError(CRC32C_EXCEPTION_MESSAGES.INVALID_INIT_BASE64_RANGE(buffer.byteLength)); + } + return this.fromBuffer(buffer); + } + /** + * Generates a `CRC32C` from a safe, unsigned 32-bit integer. + * + * @param value an unsigned 32-bit integer + */ + static fromNumber(value) { + if (!Number.isSafeInteger(value) || value > 2 ** 32 || value < -(2 ** 32)) { + throw new RangeError(CRC32C_EXCEPTION_MESSAGES.INVALID_INIT_INTEGER(value)); + } + return new CRC32C(value); + } + /** + * Generates a `CRC32C` from a variety of compatable types. + * Note: strings are treated as input, not as file paths to read from. + * + * @param value A number, 4-byte `ArrayBufferView`/`Buffer`/`TypedArray`, or 4-byte base64-encoded data (string) + */ + static from(value) { + if (typeof value === 'number') { + return this.fromNumber(value); + } + else if (typeof value === 'string') { + return this.fromString(value); + } + else if ('byteLength' in value) { + // `ArrayBuffer` | `Buffer` | `ArrayBufferView` + return this.fromBuffer(value); + } + else { + // `CRC32CValidator`/`CRC32C`-like + return this.fromString(value.toString()); + } + } +} +exports.CRC32C = CRC32C; +_CRC32C_crc32c = new WeakMap(); +CRC32C.CRC32C_EXTENSIONS = CRC32C_EXTENSIONS; +CRC32C.CRC32C_EXTENSION_TABLE = CRC32C_EXTENSION_TABLE; + + +/***/ }), + +/***/ 69975: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _File_instances, _File_validateIntegrity; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.File = exports.FileExceptionMessages = exports.RequestError = exports.STORAGE_POST_POLICY_BASE_URL = exports.ActionToHTTPMethod = void 0; +const index_js_1 = __nccwpck_require__(11325); +const promisify_1 = __nccwpck_require__(60206); +const crypto = __importStar(__nccwpck_require__(76982)); +const fs = __importStar(__nccwpck_require__(79896)); +const mime_1 = __importDefault(__nccwpck_require__(94900)); +const resumableUpload = __importStar(__nccwpck_require__(88043)); +const stream_1 = __nccwpck_require__(2203); +const zlib = __importStar(__nccwpck_require__(43106)); +const storage_js_1 = __nccwpck_require__(92848); +const bucket_js_1 = __nccwpck_require__(82887); +const acl_js_1 = __nccwpck_require__(76637); +const signer_js_1 = __nccwpck_require__(7319); +const util_js_1 = __nccwpck_require__(37325); +const duplexify_1 = __importDefault(__nccwpck_require__(29112)); +const util_js_2 = __nccwpck_require__(74557); +const crc32c_js_1 = __nccwpck_require__(34317); +const hash_stream_validator_js_1 = __nccwpck_require__(14873); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +var ActionToHTTPMethod; +(function (ActionToHTTPMethod) { + ActionToHTTPMethod["read"] = "GET"; + ActionToHTTPMethod["write"] = "PUT"; + ActionToHTTPMethod["delete"] = "DELETE"; + ActionToHTTPMethod["resumable"] = "POST"; +})(ActionToHTTPMethod || (exports.ActionToHTTPMethod = ActionToHTTPMethod = {})); +/** + * @deprecated - no longer used + */ +exports.STORAGE_POST_POLICY_BASE_URL = 'https://storage.googleapis.com'; +/** + * @private + */ +const GS_URL_REGEXP = /^gs:\/\/([a-z0-9_.-]+)\/(.+)$/; +/** + * @private + * This regex will match compressible content types. These are primarily text/*, +json, +text, +xml content types. + * This was based off of mime-db and may periodically need to be updated if new compressible content types become + * standards. + */ +const COMPRESSIBLE_MIME_REGEX = new RegExp([ + /^text\/|application\/ecmascript|application\/javascript|application\/json/, + /|application\/postscript|application\/rtf|application\/toml|application\/vnd.dart/, + /|application\/vnd.ms-fontobject|application\/wasm|application\/x-httpd-php|application\/x-ns-proxy-autoconfig/, + /|application\/x-sh(?!ockwave-flash)|application\/x-tar|application\/x-virtualbox-hdd|application\/x-virtualbox-ova|application\/x-virtualbox-ovf/, + /|^application\/x-virtualbox-vbox$|application\/x-virtualbox-vdi|application\/x-virtualbox-vhd|application\/x-virtualbox-vmdk/, + /|application\/xml|application\/xml-dtd|font\/otf|font\/ttf|image\/bmp|image\/vnd.adobe.photoshop|image\/vnd.microsoft.icon/, + /|image\/vnd.ms-dds|image\/x-icon|image\/x-ms-bmp|message\/rfc822|model\/gltf-binary|\+json|\+text|\+xml|\+yaml/, +] + .map(r => r.source) + .join(''), 'i'); +class RequestError extends Error { +} +exports.RequestError = RequestError; +const SEVEN_DAYS = 7 * 24 * 60 * 60; +const GS_UTIL_URL_REGEX = /(gs):\/\/([a-z0-9_.-]+)\/(.+)/g; +const HTTPS_PUBLIC_URL_REGEX = /(https):\/\/(storage\.googleapis\.com)\/([a-z0-9_.-]+)\/(.+)/g; +var FileExceptionMessages; +(function (FileExceptionMessages) { + FileExceptionMessages["EXPIRATION_TIME_NA"] = "An expiration time is not available."; + FileExceptionMessages["DESTINATION_NO_NAME"] = "Destination file should have a name."; + FileExceptionMessages["INVALID_VALIDATION_FILE_RANGE"] = "Cannot use validation with file ranges (start/end)."; + FileExceptionMessages["MD5_NOT_AVAILABLE"] = "MD5 verification was specified, but is not available for the requested object. MD5 is not available for composite objects."; + FileExceptionMessages["EQUALS_CONDITION_TWO_ELEMENTS"] = "Equals condition must be an array of 2 elements."; + FileExceptionMessages["STARTS_WITH_TWO_ELEMENTS"] = "StartsWith condition must be an array of 2 elements."; + FileExceptionMessages["CONTENT_LENGTH_RANGE_MIN_MAX"] = "ContentLengthRange must have numeric min & max fields."; + FileExceptionMessages["DOWNLOAD_MISMATCH"] = "The downloaded data did not match the data from the server. To be sure the content is the same, you should download the file again."; + FileExceptionMessages["UPLOAD_MISMATCH_DELETE_FAIL"] = "The uploaded data did not match the data from the server.\n As a precaution, we attempted to delete the file, but it was not successful.\n To be sure the content is the same, you should try removing the file manually,\n then uploading the file again.\n \n\nThe delete attempt failed with this message:\n\n "; + FileExceptionMessages["UPLOAD_MISMATCH"] = "The uploaded data did not match the data from the server.\n As a precaution, the file has been deleted.\n To be sure the content is the same, you should try uploading the file again."; + FileExceptionMessages["MD5_RESUMED_UPLOAD"] = "MD5 cannot be used with a continued resumable upload as MD5 cannot be extended from an existing value"; + FileExceptionMessages["MISSING_RESUME_CRC32C_FINAL_UPLOAD"] = "The CRC32C is missing for the final portion of a resumed upload, which is required for validation. Please provide `resumeCRC32C` if validation is required, or disable `validation`."; +})(FileExceptionMessages || (exports.FileExceptionMessages = FileExceptionMessages = {})); +/** + * A File object is created from your {@link Bucket} object using + * {@link Bucket#file}. + * + * @class + */ +class File extends index_js_1.ServiceObject { + /** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * An ACL consists of one or more entries, where each entry grants permissions + * to an entity. Permissions define the actions that can be performed against + * an object or bucket (for example, `READ` or `WRITE`); the entity defines + * who the permission applies to (for example, a specific user or group of + * users). + * + * The `acl` object on a File instance provides methods to get you a list of + * the ACLs defined on your bucket, as well as set, update, and delete them. + * + * See {@link http://goo.gl/6qBBPO| About Access Control lists} + * + * @name File#acl + * @mixes Acl + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * //- + * // Make a file publicly readable. + * //- + * const options = { + * entity: 'allUsers', + * role: storage.acl.READER_ROLE + * }; + * + * file.acl.add(options, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + /** + * The API-formatted resource description of the file. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name File#metadata + * @type {object} + */ + /** + * The file's name. + * @name File#name + * @type {string} + */ + /** + * @callback Crc32cGeneratorToStringCallback + * A method returning the CRC32C as a base64-encoded string. + * + * @returns {string} + * + * @example + * Hashing the string 'data' should return 'rth90Q==' + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.toString(); // 'rth90Q==' + * ``` + **/ + /** + * @callback Crc32cGeneratorValidateCallback + * A method validating a base64-encoded CRC32C string. + * + * @param {string} [value] base64-encoded CRC32C string to validate + * @returns {boolean} + * + * @example + * Should return `true` if the value matches, `false` otherwise + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.validate('DkjKuA=='); // false + * crc32c.validate('rth90Q=='); // true + * ``` + **/ + /** + * @callback Crc32cGeneratorUpdateCallback + * A method for passing `Buffer`s for CRC32C generation. + * + * @param {Buffer} [data] data to update CRC32C value with + * @returns {undefined} + * + * @example + * Hashing buffers from 'some ' and 'text\n' + * + * ```js + * const buffer1 = Buffer.from('some '); + * crc32c.update(buffer1); + * + * const buffer2 = Buffer.from('text\n'); + * crc32c.update(buffer2); + * + * crc32c.toString(); // 'DkjKuA==' + * ``` + **/ + /** + * @typedef {object} CRC32CValidator + * @property {Crc32cGeneratorToStringCallback} + * @property {Crc32cGeneratorValidateCallback} + * @property {Crc32cGeneratorUpdateCallback} + */ + /** + * @callback Crc32cGeneratorCallback + * @returns {CRC32CValidator} + */ + /** + * @typedef {object} FileOptions Options passed to the File constructor. + * @property {string} [encryptionKey] A custom encryption key. + * @property {number} [generation] Generation to scope the file to. + * @property {string} [kmsKeyName] Cloud KMS Key used to encrypt this + * object, if the object is encrypted by such a key. Limited availability; + * usable only by enabled projects. + * @property {string} [userProject] The ID of the project which will be + * billed for all requests made from File object. + * @property {Crc32cGeneratorCallback} [callback] A function that generates a CRC32C Validator. Defaults to {@link CRC32C} + */ + /** + * Constructs a file object. + * + * @param {Bucket} bucket The Bucket instance this file is + * attached to. + * @param {string} name The name of the remote file. + * @param {FileOptions} [options] Configuration options. + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * ``` + */ + constructor(bucket, name, options = {}) { + var _a, _b; + const requestQueryObject = {}; + let generation; + if (options.generation !== null) { + if (typeof options.generation === 'string') { + generation = Number(options.generation); + } + else { + generation = options.generation; + } + if (!isNaN(generation)) { + requestQueryObject.generation = generation; + } + } + Object.assign(requestQueryObject, options.preconditionOpts); + const userProject = options.userProject || bucket.userProject; + if (typeof userProject === 'string') { + requestQueryObject.userProject = userProject; + } + const methods = { + /** + * @typedef {array} DeleteFileResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DeleteFileCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Delete the file. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/delete| Objects: delete API Documentation} + * + * @method File#delete + * @param {object} [options] Configuration options. + * @param {boolean} [options.ignoreNotFound = false] Ignore an error if + * the file does not exist. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DeleteFileCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * file.delete(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_delete_file + * Another example: + */ + delete: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} FileExistsResponse + * @property {boolean} 0 Whether the {@link File} exists. + */ + /** + * @callback FileExistsCallback + * @param {?Error} err Request error, if any. + * @param {boolean} exists Whether the {@link File} exists. + */ + /** + * Check if the file exists. + * + * @method File#exists + * @param {options} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {FileExistsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.exists(function(err, exists) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.exists().then(function(data) { + * const exists = data[0]; + * }); + * ``` + */ + exists: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} GetFileResponse + * @property {File} 0 The {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback GetFileCallback + * @param {?Error} err Request error, if any. + * @param {File} file The {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * Get a file object and its metadata if it exists. + * + * @method File#get + * @param {options} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {number} [options.generation] The generation number to get + * @param {string} [options.restoreToken] If this is a soft-deleted object in an HNS-enabled bucket, returns the restore token which will + * be necessary to restore it if there's a name conflict with another object. + * @param {boolean} [options.softDeleted] If true, returns the soft-deleted object. + Object `generation` is required if `softDeleted` is set to True. + * @param {GetFileCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.get(function(err, file, apiResponse) { + * // file.metadata` has been populated. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.get().then(function(data) { + * const file = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + get: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} GetFileMetadataResponse + * @property {object} 0 The {@link File} metadata. + * @property {object} 1 The full API response. + */ + /** + * @callback GetFileMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The {@link File} metadata. + * @param {object} apiResponse The full API response. + */ + /** + * Get the file's metadata. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/get| Objects: get API Documentation} + * + * @method File#getMetadata + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetFileMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.getMetadata(function(err, metadata, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.getMetadata().then(function(data) { + * const metadata = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_get_metadata + * Another example: + */ + getMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} SetFileMetadataOptions Configuration options for File#setMetadata(). + * @param {string} [userProject] The ID of the project which will be billed for the request. + */ + /** + * @callback SetFileMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} SetFileMetadataResponse + * @property {object} 0 The full API response. + */ + /** + * Merge the given metadata with the current remote file's metadata. This + * will set metadata if it was previously unset or update previously set + * metadata. To unset previously set metadata, set its value to null. + * + * You can set custom key/value pairs in the metadata key of the given + * object, however the other properties outside of this object must adhere + * to the {@link https://goo.gl/BOnnCK| official API documentation}. + * + * + * See the examples below for more information. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/patch| Objects: patch API Documentation} + * + * @method File#setMetadata + * @param {object} [metadata] The metadata you wish to update. + * @param {SetFileMetadataOptions} [options] Configuration options. + * @param {SetFileMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * const metadata = { + * contentType: 'application/x-font-ttf', + * metadata: { + * my: 'custom', + * properties: 'go here' + * } + * }; + * + * file.setMetadata(metadata, function(err, apiResponse) {}); + * + * // Assuming current metadata = { hello: 'world', unsetMe: 'will do' } + * file.setMetadata({ + * metadata: { + * abc: '123', // will be set. + * unsetMe: null, // will be unset (deleted). + * hello: 'goodbye' // will be updated from 'world' to 'goodbye'. + * } + * }, function(err, apiResponse) { + * // metadata should now be { abc: '123', hello: 'goodbye' } + * }); + * + * //- + * // Set a temporary hold on this file from its bucket's retention period + * // configuration. + * // + * file.setMetadata({ + * temporaryHold: true + * }, function(err, apiResponse) {}); + * + * //- + * // Alternatively, you may set a temporary hold. This will follow the + * // same behavior as an event-based hold, with the exception that the + * // bucket's retention policy will not renew for this file from the time + * // the hold is released. + * //- + * file.setMetadata({ + * eventBasedHold: true + * }, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.setMetadata(metadata).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + }; + super({ + parent: bucket, + baseUrl: '/o', + id: encodeURIComponent(name), + methods, + }); + _File_instances.add(this); + this.bucket = bucket; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.storage = bucket.parent; + // @TODO Can this duplicate code from above be avoided? + if (options.generation !== null) { + let generation; + if (typeof options.generation === 'string') { + generation = Number(options.generation); + } + else { + generation = options.generation; + } + if (!isNaN(generation)) { + this.generation = generation; + } + } + this.kmsKeyName = options.kmsKeyName; + this.userProject = userProject; + this.name = name; + if (options.encryptionKey) { + this.setEncryptionKey(options.encryptionKey); + } + this.acl = new acl_js_1.Acl({ + request: this.request.bind(this), + pathPrefix: '/acl', + }); + this.crc32cGenerator = + options.crc32cGenerator || this.bucket.crc32cGenerator; + this.instanceRetryValue = (_b = (_a = this.storage) === null || _a === void 0 ? void 0 : _a.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry; + this.instancePreconditionOpts = options === null || options === void 0 ? void 0 : options.preconditionOpts; + } + /** + * The object's Cloud Storage URI (`gs://`) + * + * @example + * ```ts + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('image.png'); + * + * // `gs://my-bucket/image.png` + * const href = file.cloudStorageURI.href; + * ``` + */ + get cloudStorageURI() { + const uri = this.bucket.cloudStorageURI; + uri.pathname = this.name; + return uri; + } + /** + * A helper method for determining if a request should be retried based on preconditions. + * This should only be used for methods where the idempotency is determined by + * `ifGenerationMatch` + * @private + * + * A request should not be retried under the following conditions: + * - if precondition option `ifGenerationMatch` is not set OR + * - if `idempotencyStrategy` is set to `RetryNever` + */ + shouldRetryBasedOnPreconditionAndIdempotencyStrat(options) { + var _a; + return !(((options === null || options === void 0 ? void 0 : options.ifGenerationMatch) === undefined && + ((_a = this.instancePreconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever); + } + /** + * @typedef {array} CopyResponse + * @property {File} 0 The copied {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback CopyCallback + * @param {?Error} err Request error, if any. + * @param {File} copiedFile The copied {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} CopyOptions Configuration options for File#copy(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @property {string} [cacheControl] The cacheControl setting for the new file. + * @property {string} [contentEncoding] The contentEncoding setting for the new file. + * @property {string} [contentType] The contentType setting for the new file. + * @property {string} [destinationKmsKeyName] Resource name of the Cloud + * KMS key, of the form + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`, + * that will be used to encrypt the object. Overwrites the object + * metadata's `kms_key_name` value, if any. + * @property {Metadata} [metadata] Metadata to specify on the copied file. + * @property {string} [predefinedAcl] Set the ACL for the new file. + * @property {string} [token] A previously-returned `rewriteToken` from an + * unfinished rewrite request. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Copy this file to another file. By default, this will copy the file to the + * same bucket, but you can choose to copy it to another Bucket by providing + * a Bucket or File object or a URL starting with "gs://". + * The generation of the file will not be preserved. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite| Objects: rewrite API Documentation} + * + * @throws {Error} If the destination file is not provided. + * + * @param {string|Bucket|File} destination Destination file. + * @param {CopyOptions} [options] Configuration options. See an + * @param {CopyCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // You can pass in a variety of types for the destination. + * // + * // For all of the below examples, assume we are working with the following + * // Bucket and File objects. + * //- + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // If you pass in a string for the destination, the file is copied to its + * // current bucket, under the new name provided. + * //- + * file.copy('my-image-copy.png', function(err, copiedFile, apiResponse) { + * // `my-bucket` now contains: + * // - "my-image.png" + * // - "my-image-copy.png" + * + * // `copiedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // If you pass in a string starting with "gs://" for the destination, the + * // file is copied to the other bucket and under the new name provided. + * //- + * const newLocation = 'gs://another-bucket/my-image-copy.png'; + * file.copy(newLocation, function(err, copiedFile, apiResponse) { + * // `my-bucket` still contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image-copy.png" + * + * // `copiedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // If you pass in a Bucket object, the file will be copied to that bucket + * // using the same name. + * //- + * const anotherBucket = storage.bucket('another-bucket'); + * file.copy(anotherBucket, function(err, copiedFile, apiResponse) { + * // `my-bucket` still contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image.png" + * + * // `copiedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // If you pass in a File object, you have complete control over the new + * // bucket and filename. + * //- + * const anotherFile = anotherBucket.file('my-awesome-image.png'); + * file.copy(anotherFile, function(err, copiedFile, apiResponse) { + * // `my-bucket` still contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-awesome-image.png" + * + * // Note: + * // The `copiedFile` parameter is equal to `anotherFile`. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.copy(newLocation).then(function(data) { + * const newFile = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_copy_file + * Another example: + */ + copy(destination, optionsOrCallback, callback) { + var _a, _b; + const noDestinationError = new Error(FileExceptionMessages.DESTINATION_NO_NAME); + if (!destination) { + throw noDestinationError; + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = { ...optionsOrCallback }; + } + callback = callback || index_js_1.util.noop; + let destBucket; + let destName; + let newFile; + if (typeof destination === 'string') { + const parsedDestination = GS_URL_REGEXP.exec(destination); + if (parsedDestination !== null && parsedDestination.length === 3) { + destBucket = this.storage.bucket(parsedDestination[1]); + destName = parsedDestination[2]; + } + else { + destBucket = this.bucket; + destName = destination; + } + } + else if (destination instanceof bucket_js_1.Bucket) { + destBucket = destination; + destName = this.name; + } + else if (destination instanceof File) { + destBucket = destination.bucket; + destName = destination.name; + newFile = destination; + } + else { + throw noDestinationError; + } + const query = {}; + if (this.generation !== undefined) { + query.sourceGeneration = this.generation; + } + if (options.token !== undefined) { + query.rewriteToken = options.token; + } + if (options.userProject !== undefined) { + query.userProject = options.userProject; + delete options.userProject; + } + if (options.predefinedAcl !== undefined) { + query.destinationPredefinedAcl = options.predefinedAcl; + delete options.predefinedAcl; + } + newFile = newFile || destBucket.file(destName); + const headers = {}; + if (this.encryptionKey !== undefined) { + headers['x-goog-copy-source-encryption-algorithm'] = 'AES256'; + headers['x-goog-copy-source-encryption-key'] = this.encryptionKeyBase64; + headers['x-goog-copy-source-encryption-key-sha256'] = + this.encryptionKeyHash; + } + if (newFile.encryptionKey !== undefined) { + this.setEncryptionKey(newFile.encryptionKey); + } + else if (options.destinationKmsKeyName !== undefined) { + query.destinationKmsKeyName = options.destinationKmsKeyName; + delete options.destinationKmsKeyName; + } + else if (newFile.kmsKeyName !== undefined) { + query.destinationKmsKeyName = newFile.kmsKeyName; + } + if (query.destinationKmsKeyName) { + this.kmsKeyName = query.destinationKmsKeyName; + const keyIndex = this.interceptors.indexOf(this.encryptionKeyInterceptor); + if (keyIndex > -1) { + this.interceptors.splice(keyIndex, 1); + } + } + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options === null || options === void 0 ? void 0 : options.preconditionOpts)) { + this.storage.retryOptions.autoRetry = false; + } + if (((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) !== undefined) { + query.ifGenerationMatch = (_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch; + delete options.preconditionOpts; + } + this.request({ + method: 'POST', + uri: `/rewriteTo/b/${destBucket.name}/o/${encodeURIComponent(newFile.name)}`, + qs: query, + json: options, + headers, + }, (err, resp) => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + if (err) { + callback(err, null, resp); + return; + } + if (resp.rewriteToken) { + const options = { + token: resp.rewriteToken, + }; + if (query.userProject) { + options.userProject = query.userProject; + } + if (query.destinationKmsKeyName) { + options.destinationKmsKeyName = query.destinationKmsKeyName; + } + this.copy(newFile, options, callback); + return; + } + callback(null, newFile, resp); + }); + } + /** + * @typedef {object} CreateReadStreamOptions Configuration options for File#createReadStream. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string|boolean} [validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with a + * CRC32c checksum. You may use MD5 if preferred, but that hash is not + * supported for composite objects. An error will be raised if MD5 is + * specified but is not available. You may also choose to skip validation + * completely, however this is **not recommended**. + * @property {number} [start] A byte offset to begin the file's download + * from. Default is 0. NOTE: Byte ranges are inclusive; that is, + * `options.start = 0` and `options.end = 999` represent the first 1000 + * bytes in a file or object. NOTE: when specifying a byte range, data + * integrity is not available. + * @property {number} [end] A byte offset to stop reading the file at. + * NOTE: Byte ranges are inclusive; that is, `options.start = 0` and + * `options.end = 999` represent the first 1000 bytes in a file or object. + * NOTE: when specifying a byte range, data integrity is not available. + * @property {boolean} [decompress=true] Disable auto decompression of the + * received data. By default this option is set to `true`. + * Applicable in cases where the data was uploaded with + * `gzip: true` option. See {@link File#createWriteStream}. + */ + /** + * Create a readable stream to read the contents of the remote file. It can be + * piped to a writable stream or listened to for 'data' events to read a + * file's contents. + * + * In the unlikely event there is a mismatch between what you downloaded and + * the version in your Bucket, your error handler will receive an error with + * code "CONTENT_DOWNLOAD_MISMATCH". If you receive this error, the best + * recourse is to try downloading the file again. + * + * NOTE: Readable streams will emit the `end` event when the file is fully + * downloaded. + * + * @param {CreateReadStreamOptions} [options] Configuration options. + * @returns {ReadableStream} + * + * @example + * ``` + * //- + * //

Downloading a File

+ * // + * // The example below demonstrates how we can reference a remote file, then + * // pipe its contents to a local file. This is effectively creating a local + * // backup of your remote data. + * //- + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * const fs = require('fs'); + * const remoteFile = bucket.file('image.png'); + * const localFilename = '/Users/stephen/Photos/image.png'; + * + * remoteFile.createReadStream() + * .on('error', function(err) {}) + * .on('response', function(response) { + * // Server connected and responded with the specified status and headers. + * }) + * .on('end', function() { + * // The file is fully downloaded. + * }) + * .pipe(fs.createWriteStream(localFilename)); + * + * //- + * // To limit the downloaded data to only a byte range, pass an options + * // object. + * //- + * const logFile = myBucket.file('access_log'); + * logFile.createReadStream({ + * start: 10000, + * end: 20000 + * }) + * .on('error', function(err) {}) + * .pipe(fs.createWriteStream('/Users/stephen/logfile.txt')); + * + * //- + * // To read a tail byte range, specify only `options.end` as a negative + * // number. + * //- + * const logFile = myBucket.file('access_log'); + * logFile.createReadStream({ + * end: -100 + * }) + * .on('error', function(err) {}) + * .pipe(fs.createWriteStream('/Users/stephen/logfile.txt')); + * ``` + */ + createReadStream(options = {}) { + options = Object.assign({ decompress: true }, options); + const rangeRequest = typeof options.start === 'number' || typeof options.end === 'number'; + const tailRequest = options.end < 0; + let validateStream = undefined; + let request = undefined; + const throughStream = new util_js_2.PassThroughShim(); + let crc32c = true; + let md5 = false; + if (typeof options.validation === 'string') { + const value = options.validation.toLowerCase().trim(); + crc32c = value === 'crc32c'; + md5 = value === 'md5'; + } + else if (options.validation === false) { + crc32c = false; + } + const shouldRunValidation = !rangeRequest && (crc32c || md5); + if (rangeRequest) { + if (typeof options.validation === 'string' || + options.validation === true) { + throw new Error(FileExceptionMessages.INVALID_VALIDATION_FILE_RANGE); + } + // Range requests can't receive data integrity checks. + crc32c = false; + md5 = false; + } + const onComplete = (err) => { + if (err) { + // There is an issue with node-fetch 2.x that if the stream errors the underlying socket connection is not closed. + // This causes a memory leak, so cleanup the sockets manually here by destroying the agent. + if (request === null || request === void 0 ? void 0 : request.agent) { + request.agent.destroy(); + } + throughStream.destroy(err); + } + }; + // We listen to the response event from the request stream so that we + // can... + // + // 1) Intercept any data from going to the user if an error occurred. + // 2) Calculate the hashes from the http.IncomingMessage response + // stream, + // which will return the bytes from the source without decompressing + // gzip'd content. We then send it through decompressed, if + // applicable, to the user. + const onResponse = (err, _body, rawResponseStream) => { + if (err) { + // Get error message from the body. + this.getBufferFromReadable(rawResponseStream).then(body => { + err.message = body.toString('utf8'); + throughStream.destroy(err); + }); + return; + } + request = rawResponseStream.request; + const headers = rawResponseStream.toJSON().headers; + const isCompressed = headers['content-encoding'] === 'gzip'; + const hashes = {}; + // The object is safe to validate if: + // 1. It was stored gzip and returned to us gzip OR + // 2. It was never stored as gzip + const safeToValidate = (headers['x-goog-stored-content-encoding'] === 'gzip' && + isCompressed) || + headers['x-goog-stored-content-encoding'] === 'identity'; + const transformStreams = []; + if (shouldRunValidation) { + // The x-goog-hash header should be set with a crc32c and md5 hash. + // ex: headers['x-goog-hash'] = 'crc32c=xxxx,md5=xxxx' + if (typeof headers['x-goog-hash'] === 'string') { + headers['x-goog-hash'] + .split(',') + .forEach((hashKeyValPair) => { + const delimiterIndex = hashKeyValPair.indexOf('='); + const hashType = hashKeyValPair.substring(0, delimiterIndex); + const hashValue = hashKeyValPair.substring(delimiterIndex + 1); + hashes[hashType] = hashValue; + }); + } + validateStream = new hash_stream_validator_js_1.HashStreamValidator({ + crc32c, + md5, + crc32cGenerator: this.crc32cGenerator, + crc32cExpected: hashes.crc32c, + md5Expected: hashes.md5, + }); + } + if (md5 && !hashes.md5) { + const hashError = new RequestError(FileExceptionMessages.MD5_NOT_AVAILABLE); + hashError.code = 'MD5_NOT_AVAILABLE'; + throughStream.destroy(hashError); + return; + } + if (safeToValidate && shouldRunValidation && validateStream) { + transformStreams.push(validateStream); + } + if (isCompressed && options.decompress) { + transformStreams.push(zlib.createGunzip()); + } + (0, stream_1.pipeline)(rawResponseStream, ...transformStreams, throughStream, onComplete); + }; + // Authenticate the request, then pipe the remote API request to the stream + // returned to the user. + const makeRequest = () => { + const query = { alt: 'media' }; + if (this.generation) { + query.generation = this.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + const headers = { + 'Accept-Encoding': 'gzip', + 'Cache-Control': 'no-store', + }; + if (rangeRequest) { + const start = typeof options.start === 'number' ? options.start : '0'; + const end = typeof options.end === 'number' ? options.end : ''; + headers.Range = `bytes=${tailRequest ? end : `${start}-${end}`}`; + } + const reqOpts = { + uri: '', + headers, + qs: query, + }; + if (options[util_js_1.GCCL_GCS_CMD_KEY]) { + reqOpts[util_js_1.GCCL_GCS_CMD_KEY] = options[util_js_1.GCCL_GCS_CMD_KEY]; + } + this.requestStream(reqOpts) + .on('error', err => { + throughStream.destroy(err); + }) + .on('response', res => { + throughStream.emit('response', res); + index_js_1.util.handleResp(null, res, null, onResponse); + }) + .resume(); + }; + throughStream.on('reading', makeRequest); + return throughStream; + } + /** + * @callback CreateResumableUploadCallback + * @param {?Error} err Request error, if any. + * @param {string} uri The resumable upload's unique session URI. + */ + /** + * @typedef {array} CreateResumableUploadResponse + * @property {string} 0 The resumable upload's unique session URI. + */ + /** + * @typedef {object} CreateResumableUploadOptions + * @property {object} [metadata] Metadata to set on the file. + * @property {number} [offset] The starting byte of the upload stream for resuming an interrupted upload. + * @property {string} [origin] Origin header to set for the upload. + * @property {string} [predefinedAcl] Apply a predefined set of access + * controls to this object. + * + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @property {boolean} [private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @property {boolean} [public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string} [chunkSize] Create a separate request per chunk. This + * value is in bytes and should be a multiple of 256 KiB (2^18). + * {@link https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload| We recommend using at least 8 MiB for the chunk size.} + */ + /** + * Create a unique resumable upload session URI. This is the first step when + * performing a resumable upload. + * + * See the {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload| Resumable upload guide} + * for more on how the entire process works. + * + *

Note

+ * + * If you are just looking to perform a resumable upload without worrying + * about any of the details, see {@link File#createWriteStream}. Resumable + * uploads are performed by default. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload| Resumable upload guide} + * + * @param {CreateResumableUploadOptions} [options] Configuration options. + * @param {CreateResumableUploadCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * file.createResumableUpload(function(err, uri) { + * if (!err) { + * // `uri` can be used to PUT data to. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.createResumableUpload().then(function(data) { + * const uri = data[0]; + * }); + * ``` + */ + createResumableUpload(optionsOrCallback, callback) { + var _a, _b; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const retryOptions = this.storage.retryOptions; + if ((((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === undefined && + ((_b = this.instancePreconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch) === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + retryOptions.autoRetry = false; + } + resumableUpload.createURI({ + authClient: this.storage.authClient, + apiEndpoint: this.storage.apiEndpoint, + bucket: this.bucket.name, + customRequestOptions: this.getRequestInterceptors().reduce((reqOpts, interceptorFn) => interceptorFn(reqOpts), {}), + file: this.name, + generation: this.generation, + key: this.encryptionKey, + kmsKeyName: this.kmsKeyName, + metadata: options.metadata, + offset: options.offset, + origin: options.origin, + predefinedAcl: options.predefinedAcl, + private: options.private, + public: options.public, + userProject: options.userProject || this.userProject, + retryOptions: retryOptions, + params: (options === null || options === void 0 ? void 0 : options.preconditionOpts) || this.instancePreconditionOpts, + universeDomain: this.bucket.storage.universeDomain, + [util_js_1.GCCL_GCS_CMD_KEY]: options[util_js_1.GCCL_GCS_CMD_KEY], + }, callback); + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + } + /** + * @typedef {object} CreateWriteStreamOptions Configuration options for File#createWriteStream(). + * @property {string} [contentType] Alias for + * `options.metadata.contentType`. If set to `auto`, the file name is used + * to determine the contentType. + * @property {string|boolean} [gzip] If true, automatically gzip the file. + * If set to `auto`, the contentType is used to determine if the file + * should be gzipped. This will set `options.metadata.contentEncoding` to + * `gzip` if necessary. + * @property {object} [metadata] See the examples below or + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body} + * for more details. + * @property {number} [offset] The starting byte of the upload stream, for + * resuming an interrupted upload. Defaults to 0. + * @property {string} [predefinedAcl] Apply a predefined set of access + * controls to this object. + * + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @property {boolean} [private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @property {boolean} [public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @property {boolean} [resumable] Force a resumable upload. NOTE: When + * working with streams, the file format and size is unknown until it's + * completely consumed. Because of this, it's best for you to be explicit + * for what makes sense given your input. + * @property {number} [timeout=60000] Set the HTTP request timeout in + * milliseconds. This option is not available for resumable uploads. + * Default: `60000` + * @property {string} [uri] The URI for an already-created resumable + * upload. See {@link File#createResumableUpload}. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string|boolean} [validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with a + * CRC32c checksum. You may use MD5 if preferred, but that hash is not + * supported for composite objects. An error will be raised if MD5 is + * specified but is not available. You may also choose to skip validation + * completely, however this is **not recommended**. In addition to specifying + * validation type, providing `metadata.crc32c` or `metadata.md5Hash` will + * cause the server to perform validation in addition to client validation. + * NOTE: Validation is automatically skipped for objects that were + * uploaded using the `gzip` option and have already compressed content. + */ + /** + * Create a writable stream to overwrite the contents of the file in your + * bucket. + * + * A File object can also be used to create files for the first time. + * + * Resumable uploads are automatically enabled and must be shut off explicitly + * by setting `options.resumable` to `false`. + * + * + *

+ * There is some overhead when using a resumable upload that can cause + * noticeable performance degradation while uploading a series of small + * files. When uploading files less than 10MB, it is recommended that the + * resumable feature is disabled. + *

+ * + * NOTE: Writable streams will emit the `finish` event when the file is fully + * uploaded. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload Upload Options (Simple or Resumable)} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert Objects: insert API Documentation} + * + * @param {CreateWriteStreamOptions} [options] Configuration options. + * @returns {WritableStream} + * + * @example + * ``` + * const fs = require('fs'); + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * //

Uploading a File

+ * // + * // Now, consider a case where we want to upload a file to your bucket. You + * // have the option of using {@link Bucket#upload}, but that is just + * // a convenience method which will do the following. + * //- + * fs.createReadStream('/Users/stephen/Photos/birthday-at-the-zoo/panda.jpg') + * .pipe(file.createWriteStream()) + * .on('error', function(err) {}) + * .on('finish', function() { + * // The file upload is complete. + * }); + * + * //- + * //

Uploading a File with gzip compression

+ * //- + * fs.createReadStream('/Users/stephen/site/index.html') + * .pipe(file.createWriteStream({ gzip: true })) + * .on('error', function(err) {}) + * .on('finish', function() { + * // The file upload is complete. + * }); + * + * //- + * // Downloading the file with `createReadStream` will automatically decode + * // the file. + * //- + * + * //- + * //

Uploading a File with Metadata

+ * // + * // One last case you may run into is when you want to upload a file to your + * // bucket and set its metadata at the same time. Like above, you can use + * // {@link Bucket#upload} to do this, which is just a wrapper around + * // the following. + * //- + * fs.createReadStream('/Users/stephen/Photos/birthday-at-the-zoo/panda.jpg') + * .pipe(file.createWriteStream({ + * metadata: { + * contentType: 'image/jpeg', + * metadata: { + * custom: 'metadata' + * } + * } + * })) + * .on('error', function(err) {}) + * .on('finish', function() { + * // The file upload is complete. + * }); + * ``` + * + * //- + * //

Continuing a Resumable Upload

+ * // + * // One can capture a `uri` from a resumable upload to reuse later. + * // Additionally, for validation, one can also capture and pass `crc32c`. + * //- + * let uri: string | undefined = undefined; + * let resumeCRC32C: string | undefined = undefined; + * + * fs.createWriteStream() + * .on('uri', link => {uri = link}) + * .on('crc32', crc32c => {resumeCRC32C = crc32c}); + * + * // later... + * fs.createWriteStream({uri, resumeCRC32C}); + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + createWriteStream(options = {}) { + var _a; + (_a = options.metadata) !== null && _a !== void 0 ? _a : (options.metadata = {}); + if (options.contentType) { + options.metadata.contentType = options.contentType; + } + if (!options.metadata.contentType || + options.metadata.contentType === 'auto') { + const detectedContentType = mime_1.default.getType(this.name); + if (detectedContentType) { + options.metadata.contentType = detectedContentType; + } + } + let gzip = options.gzip; + if (gzip === 'auto') { + gzip = COMPRESSIBLE_MIME_REGEX.test(options.metadata.contentType || ''); + } + if (gzip) { + options.metadata.contentEncoding = 'gzip'; + } + let crc32c = true; + let md5 = false; + if (typeof options.validation === 'string') { + options.validation = options.validation.toLowerCase(); + crc32c = options.validation === 'crc32c'; + md5 = options.validation === 'md5'; + } + else if (options.validation === false) { + crc32c = false; + md5 = false; + } + if (options.offset) { + if (md5) { + throw new RangeError(FileExceptionMessages.MD5_RESUMED_UPLOAD); + } + if (crc32c && !options.isPartialUpload && !options.resumeCRC32C) { + throw new RangeError(FileExceptionMessages.MISSING_RESUME_CRC32C_FINAL_UPLOAD); + } + } + /** + * A callback for determining when the underlying pipeline is complete. + * It's possible the pipeline callback could error before the write stream + * calls `final` so by default this will destroy the write stream unless the + * write stream sets this callback via its `final` handler. + * @param error An optional error + */ + let pipelineCallback = error => { + writeStream.destroy(error || undefined); + }; + // A stream for consumer to write to + const writeStream = new stream_1.Writable({ + final(cb) { + // Set the pipeline callback to this callback so the pipeline's results + // can be populated to the consumer + pipelineCallback = cb; + emitStream.end(); + }, + write(chunk, encoding, cb) { + emitStream.write(chunk, encoding, cb); + }, + }); + // If the write stream, which is returned to the caller, catches an error we need to make sure that + // at least one of the streams in the pipeline below gets notified so that they + // all get cleaned up / destroyed. + writeStream.once('error', e => { + emitStream.destroy(e); + }); + // If the write stream is closed, cleanup the pipeline below by calling destroy on one of the streams. + writeStream.once('close', () => { + emitStream.destroy(); + }); + const transformStreams = []; + if (gzip) { + transformStreams.push(zlib.createGzip()); + } + const emitStream = new util_js_2.PassThroughShim(); + let hashCalculatingStream = null; + if (crc32c || md5) { + const crc32cInstance = options.resumeCRC32C + ? crc32c_js_1.CRC32C.from(options.resumeCRC32C) + : undefined; + hashCalculatingStream = new hash_stream_validator_js_1.HashStreamValidator({ + crc32c, + crc32cInstance, + md5, + crc32cGenerator: this.crc32cGenerator, + updateHashesOnly: true, + }); + transformStreams.push(hashCalculatingStream); + } + const fileWriteStream = (0, duplexify_1.default)(); + let fileWriteStreamMetadataReceived = false; + // Handing off emitted events to users + emitStream.on('reading', () => writeStream.emit('reading')); + emitStream.on('writing', () => writeStream.emit('writing')); + fileWriteStream.on('uri', evt => writeStream.emit('uri', evt)); + fileWriteStream.on('progress', evt => writeStream.emit('progress', evt)); + fileWriteStream.on('response', resp => writeStream.emit('response', resp)); + fileWriteStream.once('metadata', () => { + fileWriteStreamMetadataReceived = true; + }); + writeStream.once('writing', () => { + if (options.resumable === false) { + this.startSimpleUpload_(fileWriteStream, options); + } + else { + this.startResumableUpload_(fileWriteStream, options); + } + (0, stream_1.pipeline)(emitStream, ...transformStreams, fileWriteStream, async (e) => { + if (e) { + return pipelineCallback(e); + } + // We want to make sure we've received the metadata from the server in order + // to properly validate the object's integrity. Depending on the type of upload, + // the stream could close before the response is returned. + if (!fileWriteStreamMetadataReceived) { + try { + await new Promise((resolve, reject) => { + fileWriteStream.once('metadata', resolve); + fileWriteStream.once('error', reject); + }); + } + catch (e) { + return pipelineCallback(e); + } + } + // Emit the local CRC32C value for future validation, if validation is enabled. + if (hashCalculatingStream === null || hashCalculatingStream === void 0 ? void 0 : hashCalculatingStream.crc32c) { + writeStream.emit('crc32c', hashCalculatingStream.crc32c); + } + try { + // Metadata may not be ready if the upload is a partial upload, + // nothing to validate yet. + const metadataNotReady = options.isPartialUpload && !this.metadata; + if (hashCalculatingStream && !metadataNotReady) { + await __classPrivateFieldGet(this, _File_instances, "m", _File_validateIntegrity).call(this, hashCalculatingStream, { + crc32c, + md5, + }); + } + pipelineCallback(); + } + catch (e) { + pipelineCallback(e); + } + }); + }); + return writeStream; + } + delete(optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb; + this.disableAutoRetryConditionallyIdempotent_(this.methods.delete, bucket_js_1.AvailableServiceObjectMethods.delete, options); + super + .delete(options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } + /** + * @typedef {array} DownloadResponse + * @property [0] The contents of a File. + */ + /** + * @callback DownloadCallback + * @param err Request error, if any. + * @param contents The contents of a File. + */ + /** + * Convenience method to download a file into memory or to a local + * destination. + * + * @param {object} [options] Configuration options. The arguments match those + * passed to {@link File#createReadStream}. + * @param {string} [options.destination] Local file path to write the file's + * contents to. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DownloadCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Download a file into memory. The contents will be available as the + * second + * // argument in the demonstration below, `contents`. + * //- + * file.download(function(err, contents) {}); + * + * //- + * // Download a file to a local destination. + * //- + * file.download({ + * destination: '/Users/me/Desktop/file-backup.txt' + * }, function(err) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.download().then(function(data) { + * const contents = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_download_file + * Another example: + * + * @example include:samples/encryption.js + * region_tag:storage_download_encrypted_file + * Example of downloading an encrypted file: + * + * @example include:samples/requesterPays.js + * region_tag:storage_download_file_requester_pays + * Example of downloading a file where the requester pays: + */ + download(optionsOrCallback, cb) { + let options; + if (typeof optionsOrCallback === 'function') { + cb = optionsOrCallback; + options = {}; + } + else { + options = optionsOrCallback; + } + let called = false; + const callback = ((...args) => { + if (!called) + cb(...args); + called = true; + }); + const destination = options.destination; + delete options.destination; + const fileStream = this.createReadStream(options); + let receivedData = false; + if (destination) { + fileStream + .on('error', callback) + .once('data', data => { + receivedData = true; + // We know that the file exists the server - now we can truncate/write to a file + const writable = fs.createWriteStream(destination); + writable.write(data); + fileStream + .pipe(writable) + .on('error', (err) => { + callback(err, Buffer.from('')); + }) + .on('finish', () => { + callback(null, data); + }); + }) + .on('end', () => { + // In the case of an empty file no data will be received before the end event fires + if (!receivedData) { + const data = Buffer.alloc(0); + try { + fs.writeFileSync(destination, data); + callback(null, data); + } + catch (e) { + callback(e, data); + } + } + }); + } + else { + this.getBufferFromReadable(fileStream) + .then(contents => callback === null || callback === void 0 ? void 0 : callback(null, contents)) + .catch(callback); + } + } + /** + * The Storage API allows you to use a custom key for server-side encryption. + * + * See {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys} + * + * @param {string|buffer} encryptionKey An AES-256 encryption key. + * @returns {File} + * + * @example + * ``` + * const crypto = require('crypto'); + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const encryptionKey = crypto.randomBytes(32); + * + * const fileWithCustomEncryption = myBucket.file('my-file'); + * fileWithCustomEncryption.setEncryptionKey(encryptionKey); + * + * const fileWithoutCustomEncryption = myBucket.file('my-file'); + * + * fileWithCustomEncryption.save('data', function(err) { + * // Try to download with the File object that hasn't had + * // `setEncryptionKey()` called: + * fileWithoutCustomEncryption.download(function(err) { + * // We will receive an error: + * // err.message === 'Bad Request' + * + * // Try again with the File object we called `setEncryptionKey()` on: + * fileWithCustomEncryption.download(function(err, contents) { + * // contents.toString() === 'data' + * }); + * }); + * }); + * + * ``` + * @example include:samples/encryption.js + * region_tag:storage_upload_encrypted_file + * Example of uploading an encrypted file: + * + * @example include:samples/encryption.js + * region_tag:storage_download_encrypted_file + * Example of downloading an encrypted file: + */ + setEncryptionKey(encryptionKey) { + this.encryptionKey = encryptionKey; + this.encryptionKeyBase64 = Buffer.from(encryptionKey).toString('base64'); + this.encryptionKeyHash = crypto + .createHash('sha256') + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .update(this.encryptionKeyBase64, 'base64') + .digest('base64'); + this.encryptionKeyInterceptor = { + request: reqOpts => { + reqOpts.headers = reqOpts.headers || {}; + reqOpts.headers['x-goog-encryption-algorithm'] = 'AES256'; + reqOpts.headers['x-goog-encryption-key'] = this.encryptionKeyBase64; + reqOpts.headers['x-goog-encryption-key-sha256'] = + this.encryptionKeyHash; + return reqOpts; + }, + }; + this.interceptors.push(this.encryptionKeyInterceptor); + return this; + } + /** + * Gets a reference to a Cloud Storage {@link File} file from the provided URL in string format. + * @param {string} publicUrlOrGsUrl the URL as a string. Must be of the format gs://bucket/file + * or https://storage.googleapis.com/bucket/file. + * @param {Storage} storageInstance an instance of a Storage object. + * @param {FileOptions} [options] Configuration options + * @returns {File} + */ + static from(publicUrlOrGsUrl, storageInstance, options) { + const gsMatches = [...publicUrlOrGsUrl.matchAll(GS_UTIL_URL_REGEX)]; + const httpsMatches = [...publicUrlOrGsUrl.matchAll(HTTPS_PUBLIC_URL_REGEX)]; + if (gsMatches.length > 0) { + const bucket = new bucket_js_1.Bucket(storageInstance, gsMatches[0][2]); + return new File(bucket, gsMatches[0][3], options); + } + else if (httpsMatches.length > 0) { + const bucket = new bucket_js_1.Bucket(storageInstance, httpsMatches[0][3]); + return new File(bucket, httpsMatches[0][4], options); + } + else { + throw new Error('URL string must be of format gs://bucket/file or https://storage.googleapis.com/bucket/file'); + } + } + get(optionsOrCallback, cb) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + super + .get(options) + .then(resp => cb(null, ...resp)) + .catch(cb); + } + /** + * @typedef {array} GetExpirationDateResponse + * @property {date} 0 A Date object representing the earliest time this file's + * retention policy will expire. + */ + /** + * @callback GetExpirationDateCallback + * @param {?Error} err Request error, if any. + * @param {date} expirationDate A Date object representing the earliest time + * this file's retention policy will expire. + */ + /** + * If this bucket has a retention policy defined, use this method to get a + * Date object representing the earliest time this file will expire. + * + * @param {GetExpirationDateCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.getExpirationDate(function(err, expirationDate) { + * // expirationDate is a Date object. + * }); + * ``` + */ + getExpirationDate(callback) { + this.getMetadata((err, metadata, apiResponse) => { + if (err) { + callback(err, null, apiResponse); + return; + } + if (!metadata.retentionExpirationTime) { + const error = new Error(FileExceptionMessages.EXPIRATION_TIME_NA); + callback(error, null, apiResponse); + return; + } + callback(null, new Date(metadata.retentionExpirationTime), apiResponse); + }); + } + /** + * @typedef {array} GenerateSignedPostPolicyV2Response + * @property {object} 0 The document policy. + */ + /** + * @callback GenerateSignedPostPolicyV2Callback + * @param {?Error} err Request error, if any. + * @param {object} policy The document policy. + */ + /** + * Get a signed policy document to allow a user to upload data with a POST + * request. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed policy. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/xml-api/post-object-v2| POST Object with the V2 signing process} + * + * @throws {Error} If an expiration timestamp from the past is given. + * @throws {Error} If options.equals has an array with less or more than two + * members. + * @throws {Error} If options.startsWith has an array with less or more than two + * members. + * + * @param {object} options Configuration options. + * @param {array|array[]} [options.equals] Array of request parameters and + * their expected value (e.g. [['$', '']]). Values are + * translated into equality constraints in the conditions field of the + * policy document (e.g. ['eq', '$', '']). If only one + * equality condition is to be specified, options.equals can be a one- + * dimensional array (e.g. ['$', '']). + * @param {*} options.expires - A timestamp when this policy will expire. Any + * value given is passed to `new Date()`. + * @param {array|array[]} [options.startsWith] Array of request parameters and + * their expected prefixes (e.g. [['$', '']). Values are + * translated into starts-with constraints in the conditions field of the + * policy document (e.g. ['starts-with', '$', '']). If only + * one prefix condition is to be specified, options.startsWith can be a + * one- dimensional array (e.g. ['$', '']). + * @param {string} [options.acl] ACL for the object from possibly predefined + * ACLs. + * @param {string} [options.successRedirect] The URL to which the user client + * is redirected if the upload is successful. + * @param {string} [options.successStatus] - The status of the Google Storage + * response if the upload is successful (must be string). + * @param {object} [options.contentLengthRange] + * @param {number} [options.contentLengthRange.min] Minimum value for the + * request's content length. + * @param {number} [options.contentLengthRange.max] Maximum value for the + * request's content length. + * @param {GenerateSignedPostPolicyV2Callback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * const options = { + * equals: ['$Content-Type', 'image/jpeg'], + * expires: '10-25-2022', + * contentLengthRange: { + * min: 0, + * max: 1024 + * } + * }; + * + * file.generateSignedPostPolicyV2(options, function(err, policy) { + * // policy.string: the policy document in plain text. + * // policy.base64: the policy document in base64. + * // policy.signature: the policy signature in base64. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.generateSignedPostPolicyV2(options).then(function(data) { + * const policy = data[0]; + * }); + * ``` + */ + generateSignedPostPolicyV2(optionsOrCallback, cb) { + const args = (0, util_js_2.normalize)(optionsOrCallback, cb); + let options = args.options; + const callback = args.callback; + const expires = new Date(options.expires); + if (isNaN(expires.getTime())) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_INVALID); + } + if (expires.valueOf() < Date.now()) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_PAST); + } + options = Object.assign({}, options); + const conditions = [ + ['eq', '$key', this.name], + { + bucket: this.bucket.name, + }, + ]; + if (Array.isArray(options.equals)) { + if (!Array.isArray(options.equals[0])) { + options.equals = [options.equals]; + } + options.equals.forEach(condition => { + if (!Array.isArray(condition) || condition.length !== 2) { + throw new Error(FileExceptionMessages.EQUALS_CONDITION_TWO_ELEMENTS); + } + conditions.push(['eq', condition[0], condition[1]]); + }); + } + if (Array.isArray(options.startsWith)) { + if (!Array.isArray(options.startsWith[0])) { + options.startsWith = [options.startsWith]; + } + options.startsWith.forEach(condition => { + if (!Array.isArray(condition) || condition.length !== 2) { + throw new Error(FileExceptionMessages.STARTS_WITH_TWO_ELEMENTS); + } + conditions.push(['starts-with', condition[0], condition[1]]); + }); + } + if (options.acl) { + conditions.push({ + acl: options.acl, + }); + } + if (options.successRedirect) { + conditions.push({ + success_action_redirect: options.successRedirect, + }); + } + if (options.successStatus) { + conditions.push({ + success_action_status: options.successStatus, + }); + } + if (options.contentLengthRange) { + const min = options.contentLengthRange.min; + const max = options.contentLengthRange.max; + if (typeof min !== 'number' || typeof max !== 'number') { + throw new Error(FileExceptionMessages.CONTENT_LENGTH_RANGE_MIN_MAX); + } + conditions.push(['content-length-range', min, max]); + } + const policy = { + expiration: expires.toISOString(), + conditions, + }; + const policyString = JSON.stringify(policy); + const policyBase64 = Buffer.from(policyString).toString('base64'); + this.storage.authClient.sign(policyBase64, options.signingEndpoint).then(signature => { + callback(null, { + string: policyString, + base64: policyBase64, + signature, + }); + }, err => { + callback(new signer_js_1.SigningError(err.message)); + }); + } + /** + * @typedef {object} SignedPostPolicyV4Output + * @property {string} url The request URL. + * @property {object} fields The form fields to include in the POST request. + */ + /** + * @typedef {array} GenerateSignedPostPolicyV4Response + * @property {SignedPostPolicyV4Output} 0 An object containing the request URL and form fields. + */ + /** + * @callback GenerateSignedPostPolicyV4Callback + * @param {?Error} err Request error, if any. + * @param {SignedPostPolicyV4Output} output An object containing the request URL and form fields. + */ + /** + * Get a v4 signed policy document to allow a user to upload data with a POST + * request. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed policy. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/xml-api/post-object#policydocument| Policy Document Reference} + * + * @param {object} options Configuration options. + * @param {Date|number|string} options.expires - A timestamp when this policy will expire. Any + * value given is passed to `new Date()`. + * @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style + * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style + * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instead of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @param {string} [config.bucketBoundHostname] The bucket-bound hostname to return in + * the result, e.g. "https://cdn.example.com". + * @param {object} [config.fields] [Form fields]{@link https://cloud.google.com/storage/docs/xml-api/post-object#policydocument} + * to include in the signed policy. Any fields with key beginning with 'x-ignore-' + * will not be included in the policy to be signed. + * @param {object[]} [config.conditions] [Conditions]{@link https://cloud.google.com/storage/docs/authentication/signatures#policy-document} + * to include in the signed policy. All fields given in `config.fields` are + * automatically included in the conditions array, adding the same entry + * in both `fields` and `conditions` will result in duplicate entries. + * + * @param {GenerateSignedPostPolicyV4Callback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * const options = { + * expires: '10-25-2022', + * conditions: [ + * ['eq', '$Content-Type', 'image/jpeg'], + * ['content-length-range', 0, 1024], + * ], + * fields: { + * acl: 'public-read', + * 'x-goog-meta-foo': 'bar', + * 'x-ignore-mykey': 'data' + * } + * }; + * + * file.generateSignedPostPolicyV4(options, function(err, response) { + * // response.url The request URL + * // response.fields The form fields (including the signature) to include + * // to be used to upload objects by HTML forms. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.generateSignedPostPolicyV4(options).then(function(data) { + * const response = data[0]; + * // response.url The request URL + * // response.fields The form fields (including the signature) to include + * // to be used to upload objects by HTML forms. + * }); + * ``` + */ + generateSignedPostPolicyV4(optionsOrCallback, cb) { + const args = (0, util_js_2.normalize)(optionsOrCallback, cb); + let options = args.options; + const callback = args.callback; + const expires = new Date(options.expires); + if (isNaN(expires.getTime())) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_INVALID); + } + if (expires.valueOf() < Date.now()) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_PAST); + } + if (expires.valueOf() - Date.now() > SEVEN_DAYS * 1000) { + throw new Error(`Max allowed expiration is seven days (${SEVEN_DAYS} seconds).`); + } + options = Object.assign({}, options); + let fields = Object.assign({}, options.fields); + const now = new Date(); + const nowISO = (0, util_js_2.formatAsUTCISO)(now, true); + const todayISO = (0, util_js_2.formatAsUTCISO)(now); + const sign = async () => { + const { client_email } = await this.storage.authClient.getCredentials(); + const credential = `${client_email}/${todayISO}/auto/storage/goog4_request`; + fields = { + ...fields, + bucket: this.bucket.name, + key: this.name, + 'x-goog-date': nowISO, + 'x-goog-credential': credential, + 'x-goog-algorithm': 'GOOG4-RSA-SHA256', + }; + const conditions = options.conditions || []; + Object.entries(fields).forEach(([key, value]) => { + if (!key.startsWith('x-ignore-')) { + conditions.push({ [key]: value }); + } + }); + delete fields.bucket; + const expiration = (0, util_js_2.formatAsUTCISO)(expires, true, '-', ':'); + const policy = { + conditions, + expiration, + }; + const policyString = (0, util_js_2.unicodeJSONStringify)(policy); + const policyBase64 = Buffer.from(policyString).toString('base64'); + try { + const signature = await this.storage.authClient.sign(policyBase64, options.signingEndpoint); + const signatureHex = Buffer.from(signature, 'base64').toString('hex'); + const universe = this.parent.storage.universeDomain; + fields['policy'] = policyBase64; + fields['x-goog-signature'] = signatureHex; + let url; + if (this.storage.customEndpoint) { + url = this.storage.apiEndpoint; + } + else if (options.virtualHostedStyle) { + url = `https://${this.bucket.name}.storage.${universe}/`; + } + else if (options.bucketBoundHostname) { + url = `${options.bucketBoundHostname}/`; + } + else { + url = `https://storage.${universe}/${this.bucket.name}/`; + } + return { + url, + fields, + }; + } + catch (err) { + throw new signer_js_1.SigningError(err.message); + } + }; + sign().then(res => callback(null, res), callback); + } + /** + * @typedef {array} GetSignedUrlResponse + * @property {object} 0 The signed URL. + */ + /** + * @callback GetSignedUrlCallback + * @param {?Error} err Request error, if any. + * @param {object} url The signed URL. + */ + /** + * Get a signed URL to allow limited time access to the file. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed URL. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/access-control/signed-urls| Signed URLs Reference} + * + * @throws {Error} if an expiration timestamp from the past is given. + * + * @param {object} config Configuration object. + * @param {string} config.action "read" (HTTP: GET), "write" (HTTP: PUT), or + * "delete" (HTTP: DELETE), "resumable" (HTTP: POST). + * When using "resumable", the header `X-Goog-Resumable: start` has + * to be sent when making a request with the signed URL. + * @param {*} config.expires A timestamp when this link will expire. Any value + * given is passed to `new Date()`. + * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now. + * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example} + * @param {string} [config.version='v2'] The signing version to use, either + * 'v2' or 'v4'. + * @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style + * URLs (e.g. 'https://mybucket.storage.googleapis.com/...') instead of path-style + * (e.g. 'https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instaed of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @param {string} [config.cname] The cname for this bucket, i.e., + * "https://cdn.example.com". + * @param {string} [config.contentMd5] The MD5 digest value in base64. Just like + * if you provide this, the client must provide this HTTP header with this same + * value in its request, so to if this parameter is not provided here, + * the client must not provide any value for this HTTP header in its request. + * @param {string} [config.contentType] Just like if you provide this, the client + * must provide this HTTP header with this same value in its request, so to if + * this parameter is not provided here, the client must not provide any value + * for this HTTP header in its request. + * @param {object} [config.extensionHeaders] If these headers are used, the + * server will check to make sure that the client provides matching + * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers} + * for the requirements of this feature, most notably: + * - The header name must be prefixed with `x-goog-` + * - The header name must be all lowercase + * + * Note: Multi-valued header passed as an array in the extensionHeaders + * object is converted into a string, delimited by `,` with + * no space. Requests made using the signed URL will need to + * delimit multi-valued headers using a single `,` as well, or + * else the server will report a mismatched signature. + * @param {object} [config.queryParams] Additional query parameters to include + * in the signed URL. + * @param {string} [config.promptSaveAs] The filename to prompt the user to + * save the file as when the signed url is accessed. This is ignored if + * `config.responseDisposition` is set. + * @param {string} [config.responseDisposition] The + * {@link http://goo.gl/yMWxQV| response-content-disposition parameter} of the + * signed url. + * @param {*} [config.accessibleAt=Date.now()] A timestamp when this link became usable. Any value + * given is passed to `new Date()`. + * Note: Use for 'v4' only. + * @param {string} [config.responseType] The response-content-type parameter + * of the signed url. + * @param {GetSignedUrlCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Generate a URL that allows temporary access to download your file. + * //- + * const request = require('request'); + * + * const config = { + * action: 'read', + * expires: '03-17-2025', + * }; + * + * file.getSignedUrl(config, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The file is now available to read from this URL. + * request(url, function(err, resp) { + * // resp.statusCode = 200 + * }); + * }); + * + * //- + * // Generate a URL that allows temporary access to download your file. + * // Access will begin at accessibleAt and end at expires. + * //- + * const request = require('request'); + * + * const config = { + * action: 'read', + * expires: '03-17-2025', + * accessibleAt: '03-13-2025' + * }; + * + * file.getSignedUrl(config, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The file will be available to read from this URL from 03-13-2025 to 03-17-2025. + * request(url, function(err, resp) { + * // resp.statusCode = 200 + * }); + * }); + * + * //- + * // Generate a URL to allow write permissions. This means anyone with this + * URL + * // can send a POST request with new data that will overwrite the file. + * //- + * file.getSignedUrl({ + * action: 'write', + * expires: '03-17-2025' + * }, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The file is now available to be written to. + * const writeStream = request.put(url); + * writeStream.end('New data'); + * + * writeStream.on('complete', function(resp) { + * // Confirm the new content was saved. + * file.download(function(err, fileContents) { + * console.log('Contents:', fileContents.toString()); + * // Contents: New data + * }); + * }); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.getSignedUrl(config).then(function(data) { + * const url = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_generate_signed_url + * Another example: + */ + getSignedUrl(cfg, callback) { + const method = ActionToHTTPMethod[cfg.action]; + const extensionHeaders = (0, util_js_2.objectKeyToLowercase)(cfg.extensionHeaders || {}); + if (cfg.action === 'resumable') { + extensionHeaders['x-goog-resumable'] = 'start'; + } + const queryParams = Object.assign({}, cfg.queryParams); + if (typeof cfg.responseType === 'string') { + queryParams['response-content-type'] = cfg.responseType; + } + if (typeof cfg.promptSaveAs === 'string') { + queryParams['response-content-disposition'] = + 'attachment; filename="' + cfg.promptSaveAs + '"'; + } + if (typeof cfg.responseDisposition === 'string') { + queryParams['response-content-disposition'] = cfg.responseDisposition; + } + if (this.generation) { + queryParams['generation'] = this.generation.toString(); + } + const signConfig = { + method, + expires: cfg.expires, + accessibleAt: cfg.accessibleAt, + extensionHeaders, + queryParams, + contentMd5: cfg.contentMd5, + contentType: cfg.contentType, + host: cfg.host, + }; + if (cfg.cname) { + signConfig.cname = cfg.cname; + } + if (cfg.version) { + signConfig.version = cfg.version; + } + if (cfg.virtualHostedStyle) { + signConfig.virtualHostedStyle = cfg.virtualHostedStyle; + } + if (!this.signer) { + this.signer = new signer_js_1.URLSigner(this.storage.authClient, this.bucket, this, this.storage); + } + this.signer + .getSignedUrl(signConfig) + .then(signedUrl => callback(null, signedUrl), callback); + } + /** + * @callback IsPublicCallback + * @param {?Error} err Request error, if any. + * @param {boolean} resp Whether file is public or not. + */ + /** + * @typedef {array} IsPublicResponse + * @property {boolean} 0 Whether file is public or not. + */ + /** + * Check whether this file is public or not by sending + * a HEAD request without credentials. + * No errors from the server indicates that the current + * file is public. + * A 403-Forbidden error {@link https://cloud.google.com/storage/docs/json_api/v1/status-codes#403_Forbidden} + * indicates that file is private. + * Any other non 403 error is propagated to user. + * + * @param {IsPublicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Check whether the file is publicly accessible. + * //- + * file.isPublic(function(err, resp) { + * if (err) { + * console.error(err); + * return; + * } + * console.log(`the file ${file.id} is public: ${resp}`) ; + * }) + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.isPublic().then(function(data) { + * const resp = data[0]; + * }); + * ``` + */ + isPublic(callback) { + var _a; + // Build any custom headers based on the defined interceptors on the parent + // storage object and this object + const storageInterceptors = ((_a = this.storage) === null || _a === void 0 ? void 0 : _a.interceptors) || []; + const fileInterceptors = this.interceptors || []; + const allInterceptors = storageInterceptors.concat(fileInterceptors); + const headers = allInterceptors.reduce((acc, curInterceptor) => { + const currentHeaders = curInterceptor.request({ + uri: `${this.storage.apiEndpoint}/${this.bucket.name}/${encodeURIComponent(this.name)}`, + }); + Object.assign(acc, currentHeaders.headers); + return acc; + }, {}); + index_js_1.util.makeRequest({ + method: 'GET', + uri: `${this.storage.apiEndpoint}/${this.bucket.name}/${encodeURIComponent(this.name)}`, + headers, + }, { + retryOptions: this.storage.retryOptions, + }, (err) => { + if (err) { + const apiError = err; + if (apiError.code === 403) { + callback(null, false); + } + else { + callback(err); + } + } + else { + callback(null, true); + } + }); + } + /** + * @typedef {object} MakeFilePrivateOptions Configuration options for File#makePrivate(). + * @property {Metadata} [metadata] Define custom metadata properties to define + * along with the operation. + * @property {boolean} [strict] If true, set the file to be private to + * only the owner user. Otherwise, it will be private to the project. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback MakeFilePrivateCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} MakeFilePrivateResponse + * @property {object} 0 The full API response. + */ + /** + * Make a file private to the project and remove all other permissions. + * Set `options.strict` to true to make the file private to only the owner. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/patch| Objects: patch API Documentation} + * + * @param {MakeFilePrivateOptions} [options] Configuration options. + * @param {MakeFilePrivateCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Set the file private so only project maintainers can see and modify it. + * //- + * file.makePrivate(function(err) {}); + * + * //- + * // Set the file private so only the owner can see and modify it. + * //- + * file.makePrivate({ strict: true }, function(err) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.makePrivate().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + makePrivate(optionsOrCallback, callback) { + var _a, _b; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const query = { + predefinedAcl: options.strict ? 'private' : 'projectPrivate', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + }; + if (((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifMetagenerationMatch) !== undefined) { + query.ifMetagenerationMatch = + (_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifMetagenerationMatch; + delete options.preconditionOpts; + } + if (options.userProject) { + query.userProject = options.userProject; + } + // You aren't allowed to set both predefinedAcl & acl properties on a file, + // so acl must explicitly be nullified, destroying all previous acls on the + // file. + const metadata = { ...options.metadata, acl: null }; + this.setMetadata(metadata, query, callback); + } + /** + * @typedef {array} MakeFilePublicResponse + * @property {object} 0 The full API response. + */ + /** + * @callback MakeFilePublicCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Set a file to be publicly readable and maintain all previous permissions. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/insert| ObjectAccessControls: insert API Documentation} + * + * @param {MakeFilePublicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.makePublic(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.makePublic().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_make_public + * Another example: + */ + makePublic(callback) { + callback = callback || index_js_1.util.noop; + this.acl.add({ + entity: 'allUsers', + role: 'READER', + }, (err, acl, resp) => { + callback(err, resp); + }); + } + /** + * The public URL of this File + * Use {@link File#makePublic} to enable anonymous access via the returned URL. + * + * @returns {string} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const file = bucket.file('my-file'); + * + * // publicUrl will be "https://storage.googleapis.com/albums/my-file" + * const publicUrl = file.publicUrl(); + * ``` + */ + publicUrl() { + return `${this.storage.apiEndpoint}/${this.bucket.name}/${encodeURIComponent(this.name)}`; + } + /** + * @typedef {array} MoveFileAtomicResponse + * @property {File} 0 The moved {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback MoveFileAtomicCallback + * @param {?Error} err Request error, if any. + * @param {File} movedFile The moved {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} MoveFileAtomicOptions Configuration options for File#moveFileAtomic(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {object} [preconditionOpts] Precondition options. + * @property {number} [preconditionOpts.ifGenerationMatch] Makes the operation conditional on whether the object's current generation matches the given value. + */ + /** + * Move this file within the same HNS-enabled bucket. + * The source object must exist and be a live object. + * The source and destination object IDs must be different. + * Overwriting the destination object is allowed by default, but can be prevented + * using preconditions. + * If the destination path includes non-existent parent folders, they will be created. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/move| Objects: move API Documentation} + * + * @throws {Error} If the destination file is not provided. + * + * @param {string|File} destination Destination file name or File object within the same bucket.. + * @param {MoveFileAtomicOptions} [options] Configuration options. See an + * @param {MoveFileAtomicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Assume 'my-hns-bucket' is an HNS-enabled bucket. + * //- + * const bucket = storage.bucket('my-hns-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // If you pass in a string for the destination, the file is copied to its + * // current bucket, under the new name provided. + * //- + * file.moveFileAtomic('moved-image.png', function(err, movedFile, apiResponse) { + * // `my-hns-bucket` now contains: + * // - "moved-image.png" + * + * // `movedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // Move the file to a subdirectory, creating parent folders if necessary. + * //- + * file.moveFileAtomic('new-folder/subfolder/moved-image.png', function(err, movedFile, apiResponse) { + * // `my-hns-bucket` now contains: + * // - "new-folder/subfolder/moved-image.png" + * }); + * + * //- + * // Prevent overwriting an existing destination object using preconditions. + * //- + * file.moveFileAtomic('existing-destination.png', { + * preconditionOpts: { + * ifGenerationMatch: 0 // Fails if the destination object exists. + * } + * }, function(err, movedFile, apiResponse) { + * if (err) { + * // Handle the error (e.g., the destination object already exists). + * } else { + * // Move successful. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.moveFileAtomic('moved-image.png).then(function(data) { + * const newFile = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_move_file_hns + * Another example: + */ + moveFileAtomic(destination, optionsOrCallback, callback) { + var _a, _b; + const noDestinationError = new Error(FileExceptionMessages.DESTINATION_NO_NAME); + if (!destination) { + throw noDestinationError; + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = { ...optionsOrCallback }; + } + callback = callback || index_js_1.util.noop; + let destName; + let newFile; + if (typeof destination === 'string') { + const parsedDestination = GS_URL_REGEXP.exec(destination); + if (parsedDestination !== null && parsedDestination.length === 3) { + destName = parsedDestination[2]; + } + else { + destName = destination; + } + } + else if (destination instanceof File) { + destName = destination.name; + newFile = destination; + } + else { + throw noDestinationError; + } + newFile = newFile || this.bucket.file(destName); + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options === null || options === void 0 ? void 0 : options.preconditionOpts)) { + this.storage.retryOptions.autoRetry = false; + } + const query = {}; + if (options.userProject !== undefined) { + query.userProject = options.userProject; + delete options.userProject; + } + if (((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) !== undefined) { + query.ifGenerationMatch = (_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch; + delete options.preconditionOpts; + } + this.request({ + method: 'POST', + uri: `/moveTo/o/${encodeURIComponent(newFile.name)}`, + qs: query, + json: options, + }, (err, resp) => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + if (err) { + callback(err, null, resp); + return; + } + callback(null, newFile, resp); + }); + } + /** + * @typedef {array} MoveResponse + * @property {File} 0 The destination File. + * @property {object} 1 The full API response. + */ + /** + * @callback MoveCallback + * @param {?Error} err Request error, if any. + * @param {?File} destinationFile The destination File. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} MoveOptions Configuration options for File#move(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Move this file to another location. By default, this will rename the file + * and keep it in the same bucket, but you can choose to move it to another + * Bucket by providing a Bucket or File object or a URL beginning with + * "gs://". + * + * **Warning**: + * There is currently no atomic `move` method in the Cloud Storage API, + * so this method is a composition of {@link File#copy} (to the new + * location) and {@link File#delete} (from the old location). While + * unlikely, it is possible that an error returned to your callback could be + * triggered from either one of these API calls failing, which could leave a + * duplicate file lingering. The error message will indicate what operation + * has failed. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/copy| Objects: copy API Documentation} + * + * @throws {Error} If the destination file is not provided. + * + * @param {string|Bucket|File} destination Destination file. + * @param {MoveCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * //- + * // You can pass in a variety of types for the destination. + * // + * // For all of the below examples, assume we are working with the following + * // Bucket and File objects. + * //- + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // If you pass in a string for the destination, the file is moved to its + * // current bucket, under the new name provided. + * //- + * file.move('my-image-new.png', function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // but contains instead: + * // - "my-image-new.png" + * + * // `destinationFile` is an instance of a File object that refers to your + * // new file. + * }); + * + * //- + * // If you pass in a string starting with "gs://" for the destination, the + * // file is copied to the other bucket and under the new name provided. + * //- + * const newLocation = 'gs://another-bucket/my-image-new.png'; + * file.move(newLocation, function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image-new.png" + * + * // `destinationFile` is an instance of a File object that refers to your + * // new file. + * }); + * + * //- + * // If you pass in a Bucket object, the file will be moved to that bucket + * // using the same name. + * //- + * const anotherBucket = gcs.bucket('another-bucket'); + * + * file.move(anotherBucket, function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image.png" + * + * // `destinationFile` is an instance of a File object that refers to your + * // new file. + * }); + * + * //- + * // If you pass in a File object, you have complete control over the new + * // bucket and filename. + * //- + * const anotherFile = anotherBucket.file('my-awesome-image.png'); + * + * file.move(anotherFile, function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-awesome-image.png" + * + * // Note: + * // The `destinationFile` parameter is equal to `anotherFile`. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.move('my-image-new.png').then(function(data) { + * const destinationFile = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_move_file + * Another example: + */ + move(destination, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + callback = callback || index_js_1.util.noop; + this.copy(destination, options, (err, destinationFile, copyApiResponse) => { + if (err) { + err.message = 'file#copy failed with an error - ' + err.message; + callback(err, null, copyApiResponse); + return; + } + if (this.name !== destinationFile.name || + this.bucket.name !== destinationFile.bucket.name) { + this.delete(options, (err, apiResponse) => { + if (err) { + err.message = 'file#delete failed with an error - ' + err.message; + callback(err, destinationFile, apiResponse); + return; + } + callback(null, destinationFile, copyApiResponse); + }); + } + else { + callback(null, destinationFile, copyApiResponse); + } + }); + } + /** + * @typedef {array} RenameResponse + * @property {File} 0 The destination File. + * @property {object} 1 The full API response. + */ + /** + * @callback RenameCallback + * @param {?Error} err Request error, if any. + * @param {?File} destinationFile The destination File. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} RenameOptions Configuration options for File#move(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Rename this file. + * + * **Warning**: + * There is currently no atomic `rename` method in the Cloud Storage API, + * so this method is an alias of {@link File#move}, which in turn is a + * composition of {@link File#copy} (to the new location) and + * {@link File#delete} (from the old location). While + * unlikely, it is possible that an error returned to your callback could be + * triggered from either one of these API calls failing, which could leave a + * duplicate file lingering. The error message will indicate what operation + * has failed. + * + * @param {string|File} destinationFile Destination file. + * @param {RenameCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // You can pass in a string or a File object. + * // + * // For all of the below examples, assume we are working with the following + * // Bucket and File objects. + * //- + * + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // You can pass in a string for the destinationFile. + * //- + * file.rename('renamed-image.png', function(err, renamedFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // but contains instead: + * // - "renamed-image.png" + * + * // `renamedFile` is an instance of a File object that refers to your + * // renamed file. + * }); + * + * //- + * // You can pass in a File object. + * //- + * const anotherFile = anotherBucket.file('my-awesome-image.png'); + * + * file.rename(anotherFile, function(err, renamedFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * + * // Note: + * // The `renamedFile` parameter is equal to `anotherFile`. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.rename('my-renamed-image.png').then(function(data) { + * const renamedFile = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + rename(destinationFile, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + callback = callback || index_js_1.util.noop; + this.move(destinationFile, options, callback); + } + /** + * @typedef {object} RestoreOptions Options for File#restore(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + * @param {number} [generation] If present, selects a specific revision of this object. + * @param {string} [restoreToken] Returns an option that must be specified when getting a soft-deleted object from an HNS-enabled + * bucket that has a naming and generation conflict with another object in the same bucket. + * @param {string} [projection] Specifies the set of properties to return. If used, must be 'full' or 'noAcl'. + * @param {string | number} [ifGenerationMatch] Request proceeds if the generation of the target resource + * matches the value used in the precondition. + * If the values don't match, the request fails with a 412 Precondition Failed response. + * @param {string | number} [ifGenerationNotMatch] Request proceeds if the generation of the target resource does + * not match the value used in the precondition. If the values match, the request fails with a 304 Not Modified response. + * @param {string | number} [ifMetagenerationMatch] Request proceeds if the meta-generation of the target resource + * matches the value used in the precondition. + * If the values don't match, the request fails with a 412 Precondition Failed response. + * @param {string | number} [ifMetagenerationNotMatch] Request proceeds if the meta-generation of the target resource does + * not match the value used in the precondition. If the values match, the request fails with a 304 Not Modified response. + */ + /** + * Restores a soft-deleted file + * @param {RestoreOptions} options Restore options. + * @returns {Promise} + */ + async restore(options) { + const [file] = await this.request({ + method: 'POST', + uri: '/restore', + qs: options, + }); + return file; + } + /** + * Makes request and applies userProject query parameter if necessary. + * + * @private + * + * @param {object} reqOpts - The request options. + * @param {function} callback - The callback function. + */ + request(reqOpts, callback) { + return this.parent.request.call(this, reqOpts, callback); + } + /** + * @callback RotateEncryptionKeyCallback + * @extends CopyCallback + */ + /** + * @typedef RotateEncryptionKeyResponse + * @extends CopyResponse + */ + /** + * @param {string|buffer|object} RotateEncryptionKeyOptions Configuration options + * for File#rotateEncryptionKey(). + * If a string or Buffer is provided, it is interpreted as an AES-256, + * customer-supplied encryption key. If you'd like to use a Cloud KMS key + * name, you must specify an options object with the property name: + * `kmsKeyName`. + * @param {string|buffer} [options.encryptionKey] An AES-256 encryption key. + * @param {string} [options.kmsKeyName] A Cloud KMS key name. + */ + /** + * This method allows you to update the encryption key associated with this + * file. + * + * See {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys} + * + * @param {RotateEncryptionKeyOptions} [options] - Configuration options. + * @param {RotateEncryptionKeyCallback} [callback] + * @returns {Promise} + * + * @example include:samples/encryption.js + * region_tag:storage_rotate_encryption_key + * Example of rotating the encryption key for this file: + */ + rotateEncryptionKey(optionsOrCallback, callback) { + var _a; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + let options = {}; + if (typeof optionsOrCallback === 'string' || + optionsOrCallback instanceof Buffer) { + options = { + encryptionKey: optionsOrCallback, + }; + } + else if (typeof optionsOrCallback === 'object') { + options = optionsOrCallback; + } + const newFile = this.bucket.file(this.id, options); + const copyOptions = ((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) !== undefined + ? { preconditionOpts: options.preconditionOpts } + : {}; + this.copy(newFile, copyOptions, callback); + } + /** + * @typedef {object} SaveOptions + * @extends CreateWriteStreamOptions + */ + /** + * @callback SaveCallback + * @param {?Error} err Request error, if any. + */ + /** + * Write strings or buffers to a file. + * + * *This is a convenience method which wraps {@link File#createWriteStream}.* + * To upload arbitrary data to a file, please use {@link File#createWriteStream} directly. + * + * Resumable uploads are automatically enabled and must be shut off explicitly + * by setting `options.resumable` to `false`. + * + * Multipart uploads with retryable error codes will be retried 3 times with exponential backoff. + * + *

+ * There is some overhead when using a resumable upload that can cause + * noticeable performance degradation while uploading a series of small + * files. When uploading files less than 10MB, it is recommended that the + * resumable feature is disabled. + *

+ * + * @param {SaveData} data The data to write to a file. + * @param {SaveOptions} [options] See {@link File#createWriteStream}'s `options` + * parameter. + * @param {SaveCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * const contents = 'This is the contents of the file.'; + * + * file.save(contents, function(err) { + * if (!err) { + * // File written successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.save(contents).then(function() {}); + * ``` + */ + save(data, optionsOrCallback, callback) { + // tslint:enable:no-any + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + let maxRetries = this.storage.retryOptions.maxRetries; + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options === null || options === void 0 ? void 0 : options.preconditionOpts)) { + maxRetries = 0; + } + const returnValue = (0, async_retry_1.default)(async (bail) => { + return new Promise((resolve, reject) => { + if (maxRetries === 0) { + this.storage.retryOptions.autoRetry = false; + } + const writable = this.createWriteStream(options); + if (options.onUploadProgress) { + writable.on('progress', options.onUploadProgress); + } + const handleError = (err) => { + if (this.storage.retryOptions.autoRetry && + this.storage.retryOptions.retryableErrorFn(err)) { + return reject(err); + } + return bail(err); + }; + if (typeof data === 'string' || + Buffer.isBuffer(data) || + data instanceof Uint8Array) { + writable + .on('error', handleError) + .on('finish', () => resolve()) + .end(data); + } + else { + (0, stream_1.pipeline)(data, writable, err => { + if (err) { + if (typeof data !== 'function') { + // Only PipelineSourceFunction can be retried. Async-iterables + // and Readable streams can only be consumed once. + return bail(err); + } + handleError(err); + } + else { + resolve(); + } + }); + } + }); + }, { + retries: maxRetries, + factor: this.storage.retryOptions.retryDelayMultiplier, + maxTimeout: this.storage.retryOptions.maxRetryDelay * 1000, //convert to milliseconds + maxRetryTime: this.storage.retryOptions.totalTimeout * 1000, //convert to milliseconds + }); + if (!callback) { + return returnValue; + } + else { + return returnValue + .then(() => { + if (callback) { + return callback(); + } + }) + .catch(callback); + } + } + setMetadata(metadata, optionsOrCallback, cb) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, bucket_js_1.AvailableServiceObjectMethods.setMetadata, options); + super + .setMetadata(metadata, options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } + /** + * @typedef {array} SetStorageClassResponse + * @property {object} 0 The full API response. + */ + /** + * @typedef {object} SetStorageClassOptions Configuration options for File#setStorageClass(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback SetStorageClassCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Set the storage class for this file. + * + * See {@link https://cloud.google.com/storage/docs/per-object-storage-class| Per-Object Storage Class} + * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes} + * + * @param {string} storageClass The new storage class. (`standard`, + * `nearline`, `coldline`, or `archive`) + * **Note:** The storage classes `multi_regional` and `regional` + * are now legacy and will be deprecated in the future. + * @param {SetStorageClassOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {SetStorageClassCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * file.setStorageClass('nearline', function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * // The storage class was updated successfully. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.setStorageClass('nearline').then(function() {}); + * ``` + */ + setStorageClass(storageClass, optionsOrCallback, callback) { + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + const req = { + ...options, + // In case we get input like `storageClass`, convert to `storage_class`. + storageClass: storageClass + .replace(/-/g, '_') + .replace(/([a-z])([A-Z])/g, (_, low, up) => { + return low + '_' + up; + }) + .toUpperCase(), + }; + this.copy(this, req, (err, file, apiResponse) => { + if (err) { + callback(err, apiResponse); + return; + } + this.metadata = file.metadata; + callback(null, apiResponse); + }); + } + /** + * Set a user project to be billed for all requests made from this File + * object. + * + * @param {string} userProject The user project. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const file = bucket.file('my-file'); + * + * file.setUserProject('grape-spaceship-123'); + * ``` + */ + setUserProject(userProject) { + this.bucket.setUserProject.call(this, userProject); + } + /** + * This creates a resumable-upload upload stream. + * + * @param {Duplexify} stream - Duplexify stream of data to pipe to the file. + * @param {object=} options - Configuration object. + * + * @private + */ + startResumableUpload_(dup, options = {}) { + var _a; + (_a = options.metadata) !== null && _a !== void 0 ? _a : (options.metadata = {}); + const retryOptions = this.storage.retryOptions; + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options.preconditionOpts)) { + retryOptions.autoRetry = false; + } + const cfg = { + authClient: this.storage.authClient, + apiEndpoint: this.storage.apiEndpoint, + bucket: this.bucket.name, + customRequestOptions: this.getRequestInterceptors().reduce((reqOpts, interceptorFn) => interceptorFn(reqOpts), {}), + file: this.name, + generation: this.generation, + isPartialUpload: options.isPartialUpload, + key: this.encryptionKey, + kmsKeyName: this.kmsKeyName, + metadata: options.metadata, + offset: options.offset, + predefinedAcl: options.predefinedAcl, + private: options.private, + public: options.public, + uri: options.uri, + userProject: options.userProject || this.userProject, + retryOptions: { ...retryOptions }, + params: (options === null || options === void 0 ? void 0 : options.preconditionOpts) || this.instancePreconditionOpts, + chunkSize: options === null || options === void 0 ? void 0 : options.chunkSize, + highWaterMark: options === null || options === void 0 ? void 0 : options.highWaterMark, + universeDomain: this.bucket.storage.universeDomain, + [util_js_1.GCCL_GCS_CMD_KEY]: options[util_js_1.GCCL_GCS_CMD_KEY], + }; + let uploadStream; + try { + uploadStream = resumableUpload.upload(cfg); + } + catch (error) { + dup.destroy(error); + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + return; + } + uploadStream + .on('response', resp => { + dup.emit('response', resp); + }) + .on('uri', uri => { + dup.emit('uri', uri); + }) + .on('metadata', metadata => { + this.metadata = metadata; + dup.emit('metadata'); + }) + .on('finish', () => { + dup.emit('complete'); + }) + .on('progress', evt => dup.emit('progress', evt)); + dup.setWritable(uploadStream); + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + } + /** + * Takes a readable stream and pipes it to a remote file. Unlike + * `startResumableUpload_`, which uses the resumable upload technique, this + * method uses a simple upload (all or nothing). + * + * @param {Duplexify} dup - Duplexify stream of data to pipe to the file. + * @param {object=} options - Configuration object. + * + * @private + */ + startSimpleUpload_(dup, options = {}) { + var _a; + (_a = options.metadata) !== null && _a !== void 0 ? _a : (options.metadata = {}); + const apiEndpoint = this.storage.apiEndpoint; + const bucketName = this.bucket.name; + const uri = `${apiEndpoint}/upload/storage/v1/b/${bucketName}/o`; + const reqOpts = { + qs: { + name: this.name, + }, + uri: uri, + [util_js_1.GCCL_GCS_CMD_KEY]: options[util_js_1.GCCL_GCS_CMD_KEY], + }; + if (this.generation !== undefined) { + reqOpts.qs.ifGenerationMatch = this.generation; + } + if (this.kmsKeyName !== undefined) { + reqOpts.qs.kmsKeyName = this.kmsKeyName; + } + if (typeof options.timeout === 'number') { + reqOpts.timeout = options.timeout; + } + if (options.userProject || this.userProject) { + reqOpts.qs.userProject = options.userProject || this.userProject; + } + if (options.predefinedAcl) { + reqOpts.qs.predefinedAcl = options.predefinedAcl; + } + else if (options.private) { + reqOpts.qs.predefinedAcl = 'private'; + } + else if (options.public) { + reqOpts.qs.predefinedAcl = 'publicRead'; + } + Object.assign(reqOpts.qs, this.instancePreconditionOpts, options.preconditionOpts); + index_js_1.util.makeWritableStream(dup, { + makeAuthenticatedRequest: (reqOpts) => { + this.request(reqOpts, (err, body, resp) => { + if (err) { + dup.destroy(err); + return; + } + this.metadata = body; + dup.emit('metadata', body); + dup.emit('response', resp); + dup.emit('complete'); + }); + }, + metadata: options.metadata, + request: reqOpts, + }); + } + disableAutoRetryConditionallyIdempotent_( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + coreOpts, methodType, localPreconditionOptions) { + var _a, _b, _c, _d; + if ((typeof coreOpts === 'object' && + ((_b = (_a = coreOpts === null || coreOpts === void 0 ? void 0 : coreOpts.reqOpts) === null || _a === void 0 ? void 0 : _a.qs) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch) === undefined && + (localPreconditionOptions === null || localPreconditionOptions === void 0 ? void 0 : localPreconditionOptions.ifGenerationMatch) === undefined && + methodType === bucket_js_1.AvailableServiceObjectMethods.delete && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + this.storage.retryOptions.autoRetry = false; + } + if ((typeof coreOpts === 'object' && + ((_d = (_c = coreOpts === null || coreOpts === void 0 ? void 0 : coreOpts.reqOpts) === null || _c === void 0 ? void 0 : _c.qs) === null || _d === void 0 ? void 0 : _d.ifMetagenerationMatch) === undefined && + (localPreconditionOptions === null || localPreconditionOptions === void 0 ? void 0 : localPreconditionOptions.ifMetagenerationMatch) === undefined && + methodType === bucket_js_1.AvailableServiceObjectMethods.setMetadata && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + this.storage.retryOptions.autoRetry = false; + } + } + async getBufferFromReadable(readable) { + const buf = []; + for await (const chunk of readable) { + buf.push(chunk); + } + return Buffer.concat(buf); + } +} +exports.File = File; +_File_instances = new WeakSet(), _File_validateIntegrity = +/** + * + * @param hashCalculatingStream + * @param verify + * @returns {boolean} Returns `true` if valid, throws with error otherwise + */ +async function _File_validateIntegrity(hashCalculatingStream, verify = {}) { + const metadata = this.metadata; + // If we're doing validation, assume the worst + let dataMismatch = !!(verify.crc32c || verify.md5); + if (verify.crc32c && metadata.crc32c) { + dataMismatch = !hashCalculatingStream.test('crc32c', metadata.crc32c); + } + if (verify.md5 && metadata.md5Hash) { + dataMismatch = !hashCalculatingStream.test('md5', metadata.md5Hash); + } + if (dataMismatch) { + const errors = []; + let code = ''; + let message = ''; + try { + await this.delete(); + if (verify.md5 && !metadata.md5Hash) { + code = 'MD5_NOT_AVAILABLE'; + message = FileExceptionMessages.MD5_NOT_AVAILABLE; + } + else { + code = 'FILE_NO_UPLOAD'; + message = FileExceptionMessages.UPLOAD_MISMATCH; + } + } + catch (e) { + const error = e; + code = 'FILE_NO_UPLOAD_DELETE'; + message = `${FileExceptionMessages.UPLOAD_MISMATCH_DELETE_FAIL}${error.message}`; + errors.push(error); + } + const error = new RequestError(message); + error.code = code; + error.errors = errors; + throw error; + } + return true; +}; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(File, { + exclude: [ + 'cloudStorageURI', + 'publicUrl', + 'request', + 'save', + 'setEncryptionKey', + 'shouldRetryBasedOnPreconditionAndIdempotencyStrat', + 'getBufferFromReadable', + 'restore', + ], +}); + + +/***/ }), + +/***/ 14873: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _HashStreamValidator_crc32cHash, _HashStreamValidator_md5Hash, _HashStreamValidator_md5Digest; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HashStreamValidator = void 0; +const crypto_1 = __nccwpck_require__(76982); +const stream_1 = __nccwpck_require__(2203); +const crc32c_js_1 = __nccwpck_require__(34317); +const file_js_1 = __nccwpck_require__(69975); +class HashStreamValidator extends stream_1.Transform { + constructor(options = {}) { + super(); + this.updateHashesOnly = false; + _HashStreamValidator_crc32cHash.set(this, undefined); + _HashStreamValidator_md5Hash.set(this, undefined); + _HashStreamValidator_md5Digest.set(this, ''); + this.crc32cEnabled = !!options.crc32c; + this.md5Enabled = !!options.md5; + this.updateHashesOnly = !!options.updateHashesOnly; + this.crc32cExpected = options.crc32cExpected; + this.md5Expected = options.md5Expected; + if (this.crc32cEnabled) { + if (options.crc32cInstance) { + __classPrivateFieldSet(this, _HashStreamValidator_crc32cHash, options.crc32cInstance, "f"); + } + else { + const crc32cGenerator = options.crc32cGenerator || crc32c_js_1.CRC32C_DEFAULT_VALIDATOR_GENERATOR; + __classPrivateFieldSet(this, _HashStreamValidator_crc32cHash, crc32cGenerator(), "f"); + } + } + if (this.md5Enabled) { + __classPrivateFieldSet(this, _HashStreamValidator_md5Hash, (0, crypto_1.createHash)('md5'), "f"); + } + } + /** + * Return the current CRC32C value, if available. + */ + get crc32c() { + var _a; + return (_a = __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f")) === null || _a === void 0 ? void 0 : _a.toString(); + } + _flush(callback) { + if (__classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f")) { + __classPrivateFieldSet(this, _HashStreamValidator_md5Digest, __classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f").digest('base64'), "f"); + } + if (this.updateHashesOnly) { + callback(); + return; + } + // If we're doing validation, assume the worst-- a data integrity + // mismatch. If not, these tests won't be performed, and we can assume + // the best. + // We must check if the server decompressed the data on serve because hash + // validation is not possible in this case. + let failed = this.crc32cEnabled || this.md5Enabled; + if (this.crc32cEnabled && this.crc32cExpected) { + failed = !this.test('crc32c', this.crc32cExpected); + } + if (this.md5Enabled && this.md5Expected) { + failed = !this.test('md5', this.md5Expected); + } + if (failed) { + const mismatchError = new file_js_1.RequestError(file_js_1.FileExceptionMessages.DOWNLOAD_MISMATCH); + mismatchError.code = 'CONTENT_DOWNLOAD_MISMATCH'; + callback(mismatchError); + } + else { + callback(); + } + } + _transform(chunk, encoding, callback) { + this.push(chunk, encoding); + try { + if (__classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f")) + __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f").update(chunk); + if (__classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f")) + __classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f").update(chunk); + callback(); + } + catch (e) { + callback(e); + } + } + test(hash, sum) { + const check = Buffer.isBuffer(sum) ? sum.toString('base64') : sum; + if (hash === 'crc32c' && __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f")) { + return __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f").validate(check); + } + if (hash === 'md5' && __classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f")) { + return __classPrivateFieldGet(this, _HashStreamValidator_md5Digest, "f") === check; + } + return false; + } +} +exports.HashStreamValidator = HashStreamValidator; +_HashStreamValidator_crc32cHash = new WeakMap(), _HashStreamValidator_md5Hash = new WeakMap(), _HashStreamValidator_md5Digest = new WeakMap(); + + +/***/ }), + +/***/ 45891: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HmacKey = void 0; +const index_js_1 = __nccwpck_require__(11325); +const storage_js_1 = __nccwpck_require__(92848); +const promisify_1 = __nccwpck_require__(60206); +/** + * The API-formatted resource description of the HMAC key. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name HmacKey#metadata + * @type {object} + */ +/** + * An HmacKey object contains metadata of an HMAC key created from a + * service account through the {@link Storage} client using + * {@link Storage#createHmacKey}. + * + * See {@link https://cloud.google.com/storage/docs/authentication/hmackeys| HMAC keys documentation} + * + * @class + */ +class HmacKey extends index_js_1.ServiceObject { + /** + * @typedef {object} HmacKeyOptions + * @property {string} [projectId] The project ID of the project that owns + * the service account of the requested HMAC key. If not provided, + * the project ID used to instantiate the Storage client will be used. + */ + /** + * Constructs an HmacKey object. + * + * Note: this only create a local reference to an HMAC key, to create + * an HMAC key, use {@link Storage#createHmacKey}. + * + * @param {Storage} storage The Storage instance this HMAC key is + * attached to. + * @param {string} accessId The unique accessId for this HMAC key. + * @param {HmacKeyOptions} options Constructor configurations. + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const hmacKey = storage.hmacKey('access-id'); + * ``` + */ + constructor(storage, accessId, options) { + const methods = { + /** + * @typedef {object} DeleteHmacKeyOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * @typedef {array} DeleteHmacKeyResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DeleteHmacKeyCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Deletes an HMAC key. + * Key state must be set to `INACTIVE` prior to deletion. + * Caution: HMAC keys cannot be recovered once you delete them. + * + * The authenticated user must have `storage.hmacKeys.delete` permission for the project in which the key exists. + * + * @method HmacKey#delete + * @param {DeleteHmacKeyOptions} [options] Configuration options. + * @param {DeleteHmacKeyCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Delete HMAC key after making the key inactive. + * //- + * const hmacKey = storage.hmacKey('ACCESS_ID'); + * hmacKey.setMetadata({state: 'INACTIVE'}, (err, hmacKeyMetadata) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * hmacKey.delete((err) => { + * if (err) { + * console.error(err); + * return; + * } + * // The HMAC key is deleted. + * }); + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * const hmacKey = storage.hmacKey('ACCESS_ID'); + * hmacKey + * .setMetadata({state: 'INACTIVE'}) + * .then(() => { + * return hmacKey.delete(); + * }); + * ``` + */ + delete: true, + /** + * @callback GetHmacKeyCallback + * @param {?Error} err Request error, if any. + * @param {HmacKey} hmacKey this {@link HmacKey} instance. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} GetHmacKeyResponse + * @property {HmacKey} 0 This {@link HmacKey} instance. + * @property {object} 1 The full API response. + */ + /** + * @typedef {object} GetHmacKeyOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * Retrieves and populate an HMAC key's metadata, and return + * this {@link HmacKey} instance. + * + * HmacKey.get() does not give the HMAC key secret, as + * it is only returned on creation. + * + * The authenticated user must have `storage.hmacKeys.get` permission + * for the project in which the key exists. + * + * @method HmacKey#get + * @param {GetHmacKeyOptions} [options] Configuration options. + * @param {GetHmacKeyCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Get the HmacKey's Metadata. + * //- + * storage.hmacKey('ACCESS_ID') + * .get((err, hmacKey) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * // do something with the returned HmacKey object. + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * storage.hmacKey('ACCESS_ID') + * .get() + * .then((data) => { + * const hmacKey = data[0]; + * }); + * ``` + */ + get: true, + /** + * @typedef {object} GetHmacKeyMetadataOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * Retrieves and populate an HMAC key's metadata, and return + * the HMAC key's metadata as an object. + * + * HmacKey.getMetadata() does not give the HMAC key secret, as + * it is only returned on creation. + * + * The authenticated user must have `storage.hmacKeys.get` permission + * for the project in which the key exists. + * + * @method HmacKey#getMetadata + * @param {GetHmacKeyMetadataOptions} [options] Configuration options. + * @param {HmacKeyMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Get the HmacKey's metadata and populate to the metadata property. + * //- + * storage.hmacKey('ACCESS_ID') + * .getMetadata((err, hmacKeyMetadata) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * console.log(hmacKeyMetadata); + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * storage.hmacKey('ACCESS_ID') + * .getMetadata() + * .then((data) => { + * const hmacKeyMetadata = data[0]; + * console.log(hmacKeyMetadata); + * }); + * ``` + */ + getMetadata: true, + /** + * @typedef {object} SetHmacKeyMetadata Subset of {@link HmacKeyMetadata} to update. + * @property {string} state New state of the HmacKey. Either 'ACTIVE' or 'INACTIVE'. + * @property {string} [etag] Include an etag from a previous get HMAC key request + * to perform safe read-modify-write. + */ + /** + * @typedef {object} SetHmacKeyMetadataOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * @callback HmacKeyMetadataCallback + * @param {?Error} err Request error, if any. + * @param {HmacKeyMetadata} metadata The updated {@link HmacKeyMetadata} object. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} HmacKeyMetadataResponse + * @property {HmacKeyMetadata} 0 The updated {@link HmacKeyMetadata} object. + * @property {object} 1 The full API response. + */ + /** + * Updates the state of an HMAC key. See {@link SetHmacKeyMetadata} for + * valid states. + * + * @method HmacKey#setMetadata + * @param {SetHmacKeyMetadata} metadata The new metadata. + * @param {SetHmacKeyMetadataOptions} [options] Configuration options. + * @param {HmacKeyMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * const metadata = { + * state: 'INACTIVE', + * }; + * + * storage.hmacKey('ACCESS_ID') + * .setMetadata(metadata, (err, hmacKeyMetadata) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * console.log(hmacKeyMetadata); + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * storage.hmacKey('ACCESS_ID') + * .setMetadata(metadata) + * .then((data) => { + * const hmacKeyMetadata = data[0]; + * console.log(hmacKeyMetadata); + * }); + * ``` + */ + setMetadata: { + reqOpts: { + method: 'PUT', + }, + }, + }; + const projectId = (options && options.projectId) || storage.projectId; + super({ + parent: storage, + id: accessId, + baseUrl: `/projects/${projectId}/hmacKeys`, + methods, + }); + this.storage = storage; + this.instanceRetryValue = storage.retryOptions.autoRetry; + } + setMetadata(metadata, optionsOrCallback, cb) { + // ETag preconditions are not currently supported. Retries should be disabled if the idempotency strategy is not set to RetryAlways + if (this.storage.retryOptions.idempotencyStrategy !== + storage_js_1.IdempotencyStrategy.RetryAlways) { + this.storage.retryOptions.autoRetry = false; + } + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + super + .setMetadata(metadata, options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } +} +exports.HmacKey = HmacKey; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(HmacKey); + + +/***/ }), + +/***/ 52880: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Iam = exports.IAMExceptionMessages = void 0; +const promisify_1 = __nccwpck_require__(60206); +const util_js_1 = __nccwpck_require__(74557); +var IAMExceptionMessages; +(function (IAMExceptionMessages) { + IAMExceptionMessages["POLICY_OBJECT_REQUIRED"] = "A policy object is required."; + IAMExceptionMessages["PERMISSIONS_REQUIRED"] = "Permissions are required."; +})(IAMExceptionMessages || (exports.IAMExceptionMessages = IAMExceptionMessages = {})); +/** + * Get and set IAM policies for your Cloud Storage bucket. + * + * See {@link https://cloud.google.com/storage/docs/access-control/iam#short_title_iam_management| Cloud Storage IAM Management} + * See {@link https://cloud.google.com/iam/docs/granting-changing-revoking-access| Granting, Changing, and Revoking Access} + * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles} + * + * @constructor Iam + * + * @param {Bucket} bucket The parent instance. + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * // bucket.iam + * ``` + */ +class Iam { + constructor(bucket) { + this.request_ = bucket.request.bind(bucket); + this.resourceId_ = 'buckets/' + bucket.getId(); + } + /** + * @typedef {object} GetPolicyOptions Requested options for IAM#getPolicy(). + * @property {number} [requestedPolicyVersion] The version of IAM policies to + * request. If a policy with a condition is requested without setting + * this, the server will return an error. This must be set to a value + * of 3 to retrieve IAM policies containing conditions. This is to + * prevent client code that isn't aware of IAM conditions from + * interpreting and modifying policies incorrectly. The service might + * return a policy with version lower than the one that was requested, + * based on the feature syntax in the policy fetched. + * See {@link https://cloud.google.com/iam/docs/policies#versions| IAM Policy versions} + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} GetPolicyResponse + * @property {Policy} 0 The policy. + * @property {object} 1 The full API response. + */ + /** + * @typedef {object} Policy + * @property {PolicyBinding[]} policy.bindings Bindings associate members with roles. + * @property {string} [policy.etag] Etags are used to perform a read-modify-write. + * @property {number} [policy.version] The syntax schema version of the Policy. + * To set an IAM policy with conditional binding, this field must be set to + * 3 or greater. + * See {@link https://cloud.google.com/iam/docs/policies#versions| IAM Policy versions} + */ + /** + * @typedef {object} PolicyBinding + * @property {string} role Role that is assigned to members. + * @property {string[]} members Specifies the identities requesting access for the bucket. + * @property {Expr} [condition] The condition that is associated with this binding. + */ + /** + * @typedef {object} Expr + * @property {string} [title] An optional title for the expression, i.e. a + * short string describing its purpose. This can be used e.g. in UIs + * which allow to enter the expression. + * @property {string} [description] An optional description of the + * expression. This is a longer text which describes the expression, + * e.g. when hovered over it in a UI. + * @property {string} expression Textual representation of an expression in + * Common Expression Language syntax. The application context of the + * containing message determines which well-known feature set of CEL + * is supported.The condition that is associated with this binding. + * + * @see [Condition] https://cloud.google.com/storage/docs/access-control/iam#conditions + */ + /** + * Get the IAM policy. + * + * @param {GetPolicyOptions} [options] Request options. + * @param {GetPolicyCallback} [callback] Callback function. + * @returns {Promise} + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/getIamPolicy| Buckets: setIamPolicy API Documentation} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * bucket.iam.getPolicy( + * {requestedPolicyVersion: 3}, + * function(err, policy, apiResponse) { + * + * }, + * ); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.getPolicy({requestedPolicyVersion: 3}) + * .then(function(data) { + * const policy = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/iam.js + * region_tag:storage_view_bucket_iam_members + * Example of retrieving a bucket's IAM policy: + */ + getPolicy(optionsOrCallback, callback) { + const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback); + const qs = {}; + if (options.userProject) { + qs.userProject = options.userProject; + } + if (options.requestedPolicyVersion !== null && + options.requestedPolicyVersion !== undefined) { + qs.optionsRequestedPolicyVersion = options.requestedPolicyVersion; + } + this.request_({ + uri: '/iam', + qs, + }, cb); + } + /** + * Set the IAM policy. + * + * @throws {Error} If no policy is provided. + * + * @param {Policy} policy The policy. + * @param {SetPolicyOptions} [options] Configuration options. + * @param {SetPolicyCallback} callback Callback function. + * @returns {Promise} + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/setIamPolicy| Buckets: setIamPolicy API Documentation} + * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * const myPolicy = { + * bindings: [ + * { + * role: 'roles/storage.admin', + * members: + * ['serviceAccount:myotherproject@appspot.gserviceaccount.com'] + * } + * ] + * }; + * + * bucket.iam.setPolicy(myPolicy, function(err, policy, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.setPolicy(myPolicy).then(function(data) { + * const policy = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/iam.js + * region_tag:storage_add_bucket_iam_member + * Example of adding to a bucket's IAM policy: + * + * @example include:samples/iam.js + * region_tag:storage_remove_bucket_iam_member + * Example of removing from a bucket's IAM policy: + */ + setPolicy(policy, optionsOrCallback, callback) { + if (policy === null || typeof policy !== 'object') { + throw new Error(IAMExceptionMessages.POLICY_OBJECT_REQUIRED); + } + const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback); + let maxRetries; + if (policy.etag === undefined) { + maxRetries = 0; + } + this.request_({ + method: 'PUT', + uri: '/iam', + maxRetries, + json: Object.assign({ + resourceId: this.resourceId_, + }, policy), + qs: options, + }, cb); + } + /** + * Test a set of permissions for a resource. + * + * @throws {Error} If permissions are not provided. + * + * @param {string|string[]} permissions The permission(s) to test for. + * @param {TestIamPermissionsOptions} [options] Configuration object. + * @param {TestIamPermissionsCallback} [callback] Callback function. + * @returns {Promise} + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/testIamPermissions| Buckets: testIamPermissions API Documentation} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * //- + * // Test a single permission. + * //- + * const test = 'storage.buckets.delete'; + * + * bucket.iam.testPermissions(test, function(err, permissions, apiResponse) { + * console.log(permissions); + * // { + * // "storage.buckets.delete": true + * // } + * }); + * + * //- + * // Test several permissions at once. + * //- + * const tests = [ + * 'storage.buckets.delete', + * 'storage.buckets.get' + * ]; + * + * bucket.iam.testPermissions(tests, function(err, permissions) { + * console.log(permissions); + * // { + * // "storage.buckets.delete": false, + * // "storage.buckets.get": true + * // } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.testPermissions(test).then(function(data) { + * const permissions = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + testPermissions(permissions, optionsOrCallback, callback) { + if (!Array.isArray(permissions) && typeof permissions !== 'string') { + throw new Error(IAMExceptionMessages.PERMISSIONS_REQUIRED); + } + const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback); + const permissionsArray = Array.isArray(permissions) + ? permissions + : [permissions]; + const req = Object.assign({ + permissions: permissionsArray, + }, options); + this.request_({ + uri: '/iam/testPermissions', + qs: req, + useQuerystring: true, + }, (err, resp) => { + if (err) { + cb(err, null, resp); + return; + } + const availablePermissions = Array.isArray(resp.permissions) + ? resp.permissions + : []; + const permissionsHash = permissionsArray.reduce((acc, permission) => { + acc[permission] = availablePermissions.indexOf(permission) > -1; + return acc; + }, {}); + cb(null, permissionsHash, resp); + }); + } +} +exports.Iam = Iam; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Iam); + + +/***/ }), + +/***/ 28525: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Notification = exports.Iam = exports.HmacKey = exports.File = exports.Channel = exports.Bucket = exports.Storage = exports.RETRYABLE_ERR_FN_DEFAULT = exports.IdempotencyStrategy = exports.ApiError = void 0; +/** + * The `@google-cloud/storage` package has a single named export which is the + * {@link Storage} (ES6) class, which should be instantiated with `new`. + * + * See {@link Storage} and {@link ClientConfig} for client methods and + * configuration options. + * + * @module {Storage} @google-cloud/storage + * @alias nodejs-storage + * + * @example + * Install the client library with npm: + * ``` + * npm install --save @google-cloud/storage + * ``` + * + * @example + * Import the client library + * ``` + * const {Storage} = require('@google-cloud/storage'); + * ``` + * + * @example + * Create a client that uses Application + * Default Credentials (ADC): + * ``` + * const storage = new Storage(); + * ``` + * + * @example + * Create a client with explicit + * credentials: + * ``` + * const storage = new Storage({ projectId: + * 'your-project-id', keyFilename: '/path/to/keyfile.json' + * }); + * ``` + * + * @example include:samples/quickstart.js + * region_tag:storage_quickstart + * Full quickstart example: + */ +var index_js_1 = __nccwpck_require__(11325); +Object.defineProperty(exports, "ApiError", ({ enumerable: true, get: function () { return index_js_1.ApiError; } })); +var storage_js_1 = __nccwpck_require__(92848); +Object.defineProperty(exports, "IdempotencyStrategy", ({ enumerable: true, get: function () { return storage_js_1.IdempotencyStrategy; } })); +Object.defineProperty(exports, "RETRYABLE_ERR_FN_DEFAULT", ({ enumerable: true, get: function () { return storage_js_1.RETRYABLE_ERR_FN_DEFAULT; } })); +Object.defineProperty(exports, "Storage", ({ enumerable: true, get: function () { return storage_js_1.Storage; } })); +var bucket_js_1 = __nccwpck_require__(82887); +Object.defineProperty(exports, "Bucket", ({ enumerable: true, get: function () { return bucket_js_1.Bucket; } })); +__exportStar(__nccwpck_require__(34317), exports); +var channel_js_1 = __nccwpck_require__(12658); +Object.defineProperty(exports, "Channel", ({ enumerable: true, get: function () { return channel_js_1.Channel; } })); +var file_js_1 = __nccwpck_require__(69975); +Object.defineProperty(exports, "File", ({ enumerable: true, get: function () { return file_js_1.File; } })); +__exportStar(__nccwpck_require__(14873), exports); +var hmacKey_js_1 = __nccwpck_require__(45891); +Object.defineProperty(exports, "HmacKey", ({ enumerable: true, get: function () { return hmacKey_js_1.HmacKey; } })); +var iam_js_1 = __nccwpck_require__(52880); +Object.defineProperty(exports, "Iam", ({ enumerable: true, get: function () { return iam_js_1.Iam; } })); +var notification_js_1 = __nccwpck_require__(18598); +Object.defineProperty(exports, "Notification", ({ enumerable: true, get: function () { return notification_js_1.Notification; } })); +__exportStar(__nccwpck_require__(30004), exports); + + +/***/ }), + +/***/ 11325: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.util = exports.ApiError = exports.ServiceObject = exports.Service = void 0; +var service_js_1 = __nccwpck_require__(8542); +Object.defineProperty(exports, "Service", ({ enumerable: true, get: function () { return service_js_1.Service; } })); +var service_object_js_1 = __nccwpck_require__(72908); +Object.defineProperty(exports, "ServiceObject", ({ enumerable: true, get: function () { return service_object_js_1.ServiceObject; } })); +var util_js_1 = __nccwpck_require__(37325); +Object.defineProperty(exports, "ApiError", ({ enumerable: true, get: function () { return util_js_1.ApiError; } })); +Object.defineProperty(exports, "util", ({ enumerable: true, get: function () { return util_js_1.util; } })); + + +/***/ }), + +/***/ 72908: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ServiceObject = void 0; +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const promisify_1 = __nccwpck_require__(60206); +const events_1 = __nccwpck_require__(24434); +const util_js_1 = __nccwpck_require__(37325); +/** + * ServiceObject is a base class, meant to be inherited from by a "service + * object," like a BigQuery dataset or Storage bucket. + * + * Most of the time, these objects share common functionality; they can be + * created or deleted, and you can get or set their metadata. + * + * By inheriting from this class, a service object will be extended with these + * shared behaviors. Note that any method can be overridden when the service + * object requires specific behavior. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +class ServiceObject extends events_1.EventEmitter { + /* + * @constructor + * @alias module:common/service-object + * + * @private + * + * @param {object} config - Configuration object. + * @param {string} config.baseUrl - The base URL to make API requests to. + * @param {string} config.createMethod - The method which creates this object. + * @param {string=} config.id - The identifier of the object. For example, the + * name of a Storage bucket or Pub/Sub topic. + * @param {object=} config.methods - A map of each method name that should be inherited. + * @param {object} config.methods[].reqOpts - Default request options for this + * particular method. A common use case is when `setMetadata` requires a + * `PUT` method to override the default `PATCH`. + * @param {object} config.parent - The parent service instance. For example, an + * instance of Storage if the object is Bucket. + */ + constructor(config) { + super(); + this.metadata = {}; + this.baseUrl = config.baseUrl; + this.parent = config.parent; // Parent class. + this.id = config.id; // Name or ID (e.g. dataset ID, bucket name, etc). + this.createMethod = config.createMethod; + this.methods = config.methods || {}; + this.interceptors = []; + this.projectId = config.projectId; + if (config.methods) { + // This filters the ServiceObject instance (e.g. a "File") to only have + // the configured methods. We make a couple of exceptions for core- + // functionality ("request()" and "getRequestInterceptors()") + Object.getOwnPropertyNames(ServiceObject.prototype) + .filter(methodName => { + return ( + // All ServiceObjects need `request` and `getRequestInterceptors`. + // clang-format off + !/^request/.test(methodName) && + !/^getRequestInterceptors/.test(methodName) && + // clang-format on + // The ServiceObject didn't redefine the method. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this[methodName] === + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ServiceObject.prototype[methodName] && + // This method isn't wanted. + !config.methods[methodName]); + }) + .forEach(methodName => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this[methodName] = undefined; + }); + } + } + create(optionsOrCallback, callback) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const self = this; + const args = [this.id]; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + if (typeof optionsOrCallback === 'object') { + args.push(optionsOrCallback); + } + // Wrap the callback to return *this* instance of the object, not the + // newly-created one. + // tslint: disable-next-line no-any + function onCreate(...args) { + const [err, instance] = args; + if (!err) { + self.metadata = instance.metadata; + if (self.id && instance.metadata) { + self.id = instance.metadata.id; + } + args[1] = self; // replace the created `instance` with this one. + } + callback(...args); + } + args.push(onCreate); + // eslint-disable-next-line prefer-spread + this.createMethod.apply(null, args); + } + delete(optionsOrCallback, cb) { + var _a; + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const ignoreNotFound = options.ignoreNotFound; + delete options.ignoreNotFound; + const methodConfig = (typeof this.methods.delete === 'object' && this.methods.delete) || {}; + const reqOpts = { + method: 'DELETE', + uri: '', + ...methodConfig.reqOpts, + qs: { + ...(_a = methodConfig.reqOpts) === null || _a === void 0 ? void 0 : _a.qs, + ...options, + }, + }; + // The `request` method may have been overridden to hold any special + // behavior. Ensure we call the original `request` method. + ServiceObject.prototype.request.call(this, reqOpts, (err, body, res) => { + if (err) { + if (err.code === 404 && ignoreNotFound) { + err = null; + } + } + callback(err, res); + }); + } + exists(optionsOrCallback, cb) { + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + this.get(options, err => { + if (err) { + if (err.code === 404) { + callback(null, false); + } + else { + callback(err); + } + return; + } + callback(null, true); + }); + } + get(optionsOrCallback, cb) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const self = this; + const [opts, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const options = Object.assign({}, opts); + const autoCreate = options.autoCreate && typeof this.create === 'function'; + delete options.autoCreate; + function onCreate(err, instance, apiResponse) { + if (err) { + if (err.code === 409) { + self.get(options, callback); + return; + } + callback(err, null, apiResponse); + return; + } + callback(null, instance, apiResponse); + } + this.getMetadata(options, (err, metadata) => { + if (err) { + if (err.code === 404 && autoCreate) { + const args = []; + if (Object.keys(options).length > 0) { + args.push(options); + } + args.push(onCreate); + self.create(...args); + return; + } + callback(err, null, metadata); + return; + } + callback(null, self, metadata); + }); + } + getMetadata(optionsOrCallback, cb) { + var _a; + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const methodConfig = (typeof this.methods.getMetadata === 'object' && + this.methods.getMetadata) || + {}; + const reqOpts = { + uri: '', + ...methodConfig.reqOpts, + qs: { + ...(_a = methodConfig.reqOpts) === null || _a === void 0 ? void 0 : _a.qs, + ...options, + }, + }; + // The `request` method may have been overridden to hold any special + // behavior. Ensure we call the original `request` method. + ServiceObject.prototype.request.call(this, reqOpts, (err, body, res) => { + this.metadata = body; + callback(err, this.metadata, res); + }); + } + /** + * Return the user's custom request interceptors. + */ + getRequestInterceptors() { + // Interceptors should be returned in the order they were assigned. + const localInterceptors = this.interceptors + .filter(interceptor => typeof interceptor.request === 'function') + .map(interceptor => interceptor.request); + return this.parent.getRequestInterceptors().concat(localInterceptors); + } + setMetadata(metadata, optionsOrCallback, cb) { + var _a, _b; + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const methodConfig = (typeof this.methods.setMetadata === 'object' && + this.methods.setMetadata) || + {}; + const reqOpts = { + method: 'PATCH', + uri: '', + ...methodConfig.reqOpts, + json: { + ...(_a = methodConfig.reqOpts) === null || _a === void 0 ? void 0 : _a.json, + ...metadata, + }, + qs: { + ...(_b = methodConfig.reqOpts) === null || _b === void 0 ? void 0 : _b.qs, + ...options, + }, + }; + // The `request` method may have been overridden to hold any special + // behavior. Ensure we call the original `request` method. + ServiceObject.prototype.request.call(this, reqOpts, (err, body, res) => { + this.metadata = body; + callback(err, this.metadata, res); + }); + } + request_(reqOpts, callback) { + reqOpts = { ...reqOpts }; + if (this.projectId) { + reqOpts.projectId = this.projectId; + } + const isAbsoluteUrl = reqOpts.uri.indexOf('http') === 0; + const uriComponents = [this.baseUrl, this.id || '', reqOpts.uri]; + if (isAbsoluteUrl) { + uriComponents.splice(0, uriComponents.indexOf(reqOpts.uri)); + } + reqOpts.uri = uriComponents + .filter(x => x.trim()) // Limit to non-empty strings. + .map(uriComponent => { + const trimSlashesRegex = /^\/*|\/*$/g; + return uriComponent.replace(trimSlashesRegex, ''); + }) + .join('/'); + const childInterceptors = Array.isArray(reqOpts.interceptors_) + ? reqOpts.interceptors_ + : []; + const localInterceptors = [].slice.call(this.interceptors); + reqOpts.interceptors_ = childInterceptors.concat(localInterceptors); + if (reqOpts.shouldReturnStream) { + return this.parent.requestStream(reqOpts); + } + this.parent.request(reqOpts, callback); + } + request(reqOpts, callback) { + this.request_(reqOpts, callback); + } + /** + * Make an authenticated API request. + * + * @param {object} reqOpts - Request options that are passed to `request`. + * @param {string} reqOpts.uri - A URI relative to the baseUrl. + */ + requestStream(reqOpts) { + const opts = { ...reqOpts, shouldReturnStream: true }; + return this.request_(opts); + } +} +exports.ServiceObject = ServiceObject; +(0, promisify_1.promisifyAll)(ServiceObject, { exclude: ['getRequestInterceptors'] }); + + +/***/ }), + +/***/ 8542: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Service = exports.DEFAULT_PROJECT_ID_TOKEN = void 0; +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const google_auth_library_1 = __nccwpck_require__(492); +const uuid = __importStar(__nccwpck_require__(20607)); +const util_js_1 = __nccwpck_require__(37325); +const util_js_2 = __nccwpck_require__(74557); +exports.DEFAULT_PROJECT_ID_TOKEN = '{{projectId}}'; +class Service { + /** + * Service is a base class, meant to be inherited from by a "service," like + * BigQuery or Storage. + * + * This handles making authenticated requests by exposing a `makeReq_` + * function. + * + * @constructor + * @alias module:common/service + * + * @param {object} config - Configuration object. + * @param {string} config.baseUrl - The base URL to make API requests to. + * @param {string[]} config.scopes - The scopes required for the request. + * @param {object=} options - [Configuration object](#/docs). + */ + constructor(config, options = {}) { + this.baseUrl = config.baseUrl; + this.apiEndpoint = config.apiEndpoint; + this.timeout = options.timeout; + this.globalInterceptors = Array.isArray(options.interceptors_) + ? options.interceptors_ + : []; + this.interceptors = []; + this.packageJson = config.packageJson; + this.projectId = options.projectId || exports.DEFAULT_PROJECT_ID_TOKEN; + this.projectIdRequired = config.projectIdRequired !== false; + this.providedUserAgent = options.userAgent; + this.universeDomain = options.universeDomain || google_auth_library_1.DEFAULT_UNIVERSE; + this.customEndpoint = config.customEndpoint || false; + this.makeAuthenticatedRequest = util_js_1.util.makeAuthenticatedRequestFactory({ + ...config, + projectIdRequired: this.projectIdRequired, + projectId: this.projectId, + authClient: options.authClient || config.authClient, + credentials: options.credentials, + keyFile: options.keyFilename, + email: options.email, + clientOptions: { + universeDomain: options.universeDomain, + ...options.clientOptions, + }, + }); + this.authClient = this.makeAuthenticatedRequest.authClient; + const isCloudFunctionEnv = !!process.env.FUNCTION_NAME; + if (isCloudFunctionEnv) { + this.interceptors.push({ + request(reqOpts) { + reqOpts.forever = false; + return reqOpts; + }, + }); + } + } + /** + * Return the user's custom request interceptors. + */ + getRequestInterceptors() { + // Interceptors should be returned in the order they were assigned. + return [].slice + .call(this.globalInterceptors) + .concat(this.interceptors) + .filter(interceptor => typeof interceptor.request === 'function') + .map(interceptor => interceptor.request); + } + getProjectId(callback) { + if (!callback) { + return this.getProjectIdAsync(); + } + this.getProjectIdAsync().then(p => callback(null, p), callback); + } + async getProjectIdAsync() { + const projectId = await this.authClient.getProjectId(); + if (this.projectId === exports.DEFAULT_PROJECT_ID_TOKEN && projectId) { + this.projectId = projectId; + } + return this.projectId; + } + request_(reqOpts, callback) { + reqOpts = { ...reqOpts, timeout: this.timeout }; + const isAbsoluteUrl = reqOpts.uri.indexOf('http') === 0; + const uriComponents = [this.baseUrl]; + if (this.projectIdRequired) { + if (reqOpts.projectId) { + uriComponents.push('projects'); + uriComponents.push(reqOpts.projectId); + } + else { + uriComponents.push('projects'); + uriComponents.push(this.projectId); + } + } + uriComponents.push(reqOpts.uri); + if (isAbsoluteUrl) { + uriComponents.splice(0, uriComponents.indexOf(reqOpts.uri)); + } + reqOpts.uri = uriComponents + .map(uriComponent => { + const trimSlashesRegex = /^\/*|\/*$/g; + return uriComponent.replace(trimSlashesRegex, ''); + }) + .join('/') + // Some URIs have colon separators. + // Bad: https://.../projects/:list + // Good: https://.../projects:list + .replace(/\/:/g, ':'); + const requestInterceptors = this.getRequestInterceptors(); + const interceptorArray = Array.isArray(reqOpts.interceptors_) + ? reqOpts.interceptors_ + : []; + interceptorArray.forEach(interceptor => { + if (typeof interceptor.request === 'function') { + requestInterceptors.push(interceptor.request); + } + }); + requestInterceptors.forEach(requestInterceptor => { + reqOpts = requestInterceptor(reqOpts); + }); + delete reqOpts.interceptors_; + const pkg = this.packageJson; + let userAgent = (0, util_js_2.getUserAgentString)(); + if (this.providedUserAgent) { + userAgent = `${this.providedUserAgent} ${userAgent}`; + } + reqOpts.headers = { + ...reqOpts.headers, + 'User-Agent': userAgent, + 'x-goog-api-client': `${(0, util_js_2.getRuntimeTrackingString)()} gccl/${pkg.version}-${(0, util_js_2.getModuleFormat)()} gccl-invocation-id/${uuid.v4()}`, + }; + if (reqOpts[util_js_1.GCCL_GCS_CMD_KEY]) { + reqOpts.headers['x-goog-api-client'] += + ` gccl-gcs-cmd/${reqOpts[util_js_1.GCCL_GCS_CMD_KEY]}`; + } + if (reqOpts.shouldReturnStream) { + return this.makeAuthenticatedRequest(reqOpts); + } + else { + this.makeAuthenticatedRequest(reqOpts, callback); + } + } + /** + * Make an authenticated API request. + * + * @param {object} reqOpts - Request options that are passed to `request`. + * @param {string} reqOpts.uri - A URI relative to the baseUrl. + * @param {function} callback - The callback function passed to `request`. + */ + request(reqOpts, callback) { + Service.prototype.request_.call(this, reqOpts, callback); + } + /** + * Make an authenticated API request. + * + * @param {object} reqOpts - Request options that are passed to `request`. + * @param {string} reqOpts.uri - A URI relative to the baseUrl. + */ + requestStream(reqOpts) { + const opts = { ...reqOpts, shouldReturnStream: true }; + return Service.prototype.request_.call(this, opts); + } +} +exports.Service = Service; + + +/***/ }), + +/***/ 37325: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.util = exports.Util = exports.PartialFailureError = exports.ApiError = exports.GCCL_GCS_CMD_KEY = void 0; +/*! + * @module common/util + */ +const projectify_1 = __nccwpck_require__(87635); +const htmlEntities = __importStar(__nccwpck_require__(13660)); +const google_auth_library_1 = __nccwpck_require__(492); +const retry_request_1 = __importDefault(__nccwpck_require__(67842)); +const stream_1 = __nccwpck_require__(2203); +const teeny_request_1 = __nccwpck_require__(80321); +const uuid = __importStar(__nccwpck_require__(20607)); +const service_js_1 = __nccwpck_require__(8542); +const util_js_1 = __nccwpck_require__(74557); +const duplexify_1 = __importDefault(__nccwpck_require__(29112)); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const packageJson = (0, package_json_helper_cjs_1.getPackageJSON)(); +/** + * A unique symbol for providing a `gccl-gcs-cmd` value + * for the `X-Goog-API-Client` header. + * + * E.g. the `V` in `X-Goog-API-Client: gccl-gcs-cmd/V` + **/ +exports.GCCL_GCS_CMD_KEY = Symbol.for('GCCL_GCS_CMD'); +const requestDefaults = { + timeout: 60000, + gzip: true, + forever: true, + pool: { + maxSockets: Infinity, + }, +}; +/** + * Default behavior: Automatically retry retriable server errors. + * + * @const {boolean} + * @private + */ +const AUTO_RETRY_DEFAULT = true; +/** + * Default behavior: Only attempt to retry retriable errors 3 times. + * + * @const {number} + * @private + */ +const MAX_RETRY_DEFAULT = 3; +/** + * Custom error type for API errors. + * + * @param {object} errorBody - Error object. + */ +class ApiError extends Error { + constructor(errorBodyOrMessage) { + super(); + if (typeof errorBodyOrMessage !== 'object') { + this.message = errorBodyOrMessage || ''; + return; + } + const errorBody = errorBodyOrMessage; + this.code = errorBody.code; + this.errors = errorBody.errors; + this.response = errorBody.response; + try { + this.errors = JSON.parse(this.response.body).error.errors; + } + catch (e) { + this.errors = errorBody.errors; + } + this.message = ApiError.createMultiErrorMessage(errorBody, this.errors); + Error.captureStackTrace(this); + } + /** + * Pieces together an error message by combining all unique error messages + * returned from a single GoogleError + * + * @private + * + * @param {GoogleErrorBody} err The original error. + * @param {GoogleInnerError[]} [errors] Inner errors, if any. + * @returns {string} + */ + static createMultiErrorMessage(err, errors) { + const messages = new Set(); + if (err.message) { + messages.add(err.message); + } + if (errors && errors.length) { + errors.forEach(({ message }) => messages.add(message)); + } + else if (err.response && err.response.body) { + messages.add(htmlEntities.decode(err.response.body.toString())); + } + else if (!err.message) { + messages.add('A failure occurred during this request.'); + } + let messageArr = Array.from(messages); + if (messageArr.length > 1) { + messageArr = messageArr.map((message, i) => ` ${i + 1}. ${message}`); + messageArr.unshift('Multiple errors occurred during the request. Please see the `errors` array for complete details.\n'); + messageArr.push('\n'); + } + return messageArr.join('\n'); + } +} +exports.ApiError = ApiError; +/** + * Custom error type for partial errors returned from the API. + * + * @param {object} b - Error object. + */ +class PartialFailureError extends Error { + constructor(b) { + super(); + const errorObject = b; + this.errors = errorObject.errors; + this.name = 'PartialFailureError'; + this.response = errorObject.response; + this.message = ApiError.createMultiErrorMessage(errorObject, this.errors); + } +} +exports.PartialFailureError = PartialFailureError; +class Util { + constructor() { + this.ApiError = ApiError; + this.PartialFailureError = PartialFailureError; + } + /** + * No op. + * + * @example + * function doSomething(callback) { + * callback = callback || noop; + * } + */ + noop() { } + /** + * Uniformly process an API response. + * + * @param {*} err - Error value. + * @param {*} resp - Response value. + * @param {*} body - Body value. + * @param {function} callback - The callback function. + */ + handleResp(err, resp, body, callback) { + callback = callback || util.noop; + const parsedResp = { + err: err || null, + ...(resp && util.parseHttpRespMessage(resp)), + ...(body && util.parseHttpRespBody(body)), + }; + // Assign the parsed body to resp.body, even if { json: false } was passed + // as a request option. + // We assume that nobody uses the previously unparsed value of resp.body. + if (!parsedResp.err && resp && typeof parsedResp.body === 'object') { + parsedResp.resp.body = parsedResp.body; + } + if (parsedResp.err && resp) { + parsedResp.err.response = resp; + } + callback(parsedResp.err, parsedResp.body, parsedResp.resp); + } + /** + * Sniff an incoming HTTP response message for errors. + * + * @param {object} httpRespMessage - An incoming HTTP response message from `request`. + * @return {object} parsedHttpRespMessage - The parsed response. + * @param {?error} parsedHttpRespMessage.err - An error detected. + * @param {object} parsedHttpRespMessage.resp - The original response object. + */ + parseHttpRespMessage(httpRespMessage) { + const parsedHttpRespMessage = { + resp: httpRespMessage, + }; + if (httpRespMessage.statusCode < 200 || httpRespMessage.statusCode > 299) { + // Unknown error. Format according to ApiError standard. + parsedHttpRespMessage.err = new ApiError({ + errors: new Array(), + code: httpRespMessage.statusCode, + message: httpRespMessage.statusMessage, + response: httpRespMessage, + }); + } + return parsedHttpRespMessage; + } + /** + * Parse the response body from an HTTP request. + * + * @param {object} body - The response body. + * @return {object} parsedHttpRespMessage - The parsed response. + * @param {?error} parsedHttpRespMessage.err - An error detected. + * @param {object} parsedHttpRespMessage.body - The original body value provided + * will try to be JSON.parse'd. If it's successful, the parsed value will + * be returned here, otherwise the original value and an error will be returned. + */ + parseHttpRespBody(body) { + const parsedHttpRespBody = { + body, + }; + if (typeof body === 'string') { + try { + parsedHttpRespBody.body = JSON.parse(body); + } + catch (err) { + parsedHttpRespBody.body = body; + } + } + if (parsedHttpRespBody.body && parsedHttpRespBody.body.error) { + // Error from JSON API. + parsedHttpRespBody.err = new ApiError(parsedHttpRespBody.body.error); + } + return parsedHttpRespBody; + } + /** + * Take a Duplexify stream, fetch an authenticated connection header, and + * create an outgoing writable stream. + * + * @param {Duplexify} dup - Duplexify stream. + * @param {object} options - Configuration object. + * @param {module:common/connection} options.connection - A connection instance used to get a token with and send the request through. + * @param {object} options.metadata - Metadata to send at the head of the request. + * @param {object} options.request - Request object, in the format of a standard Node.js http.request() object. + * @param {string=} options.request.method - Default: "POST". + * @param {string=} options.request.qs.uploadType - Default: "multipart". + * @param {string=} options.streamContentType - Default: "application/octet-stream". + * @param {function} onComplete - Callback, executed after the writable Request stream has completed. + */ + makeWritableStream(dup, options, onComplete) { + var _a; + onComplete = onComplete || util.noop; + const writeStream = new ProgressStream(); + writeStream.on('progress', evt => dup.emit('progress', evt)); + dup.setWritable(writeStream); + const defaultReqOpts = { + method: 'POST', + qs: { + uploadType: 'multipart', + }, + timeout: 0, + maxRetries: 0, + }; + const metadata = options.metadata || {}; + const reqOpts = { + ...defaultReqOpts, + ...options.request, + qs: { + ...defaultReqOpts.qs, + ...(_a = options.request) === null || _a === void 0 ? void 0 : _a.qs, + }, + multipart: [ + { + 'Content-Type': 'application/json', + body: JSON.stringify(metadata), + }, + { + 'Content-Type': metadata.contentType || 'application/octet-stream', + body: writeStream, + }, + ], + }; + options.makeAuthenticatedRequest(reqOpts, { + onAuthenticated(err, authenticatedReqOpts) { + if (err) { + dup.destroy(err); + return; + } + requestDefaults.headers = util._getDefaultHeaders(reqOpts[exports.GCCL_GCS_CMD_KEY]); + const request = teeny_request_1.teenyRequest.defaults(requestDefaults); + request(authenticatedReqOpts, (err, resp, body) => { + util.handleResp(err, resp, body, (err, data) => { + if (err) { + dup.destroy(err); + return; + } + dup.emit('response', resp); + onComplete(data); + }); + }); + }, + }); + } + /** + * Returns true if the API request should be retried, given the error that was + * given the first time the request was attempted. This is used for rate limit + * related errors as well as intermittent server errors. + * + * @param {error} err - The API error to check if it is appropriate to retry. + * @return {boolean} True if the API request should be retried, false otherwise. + */ + shouldRetryRequest(err) { + if (err) { + if ([408, 429, 500, 502, 503, 504].indexOf(err.code) !== -1) { + return true; + } + if (err.errors) { + for (const e of err.errors) { + const reason = e.reason; + if (reason === 'rateLimitExceeded') { + return true; + } + if (reason === 'userRateLimitExceeded') { + return true; + } + if (reason && reason.includes('EAI_AGAIN')) { + return true; + } + } + } + } + return false; + } + /** + * Get a function for making authenticated requests. + * + * @param {object} config - Configuration object. + * @param {boolean=} config.autoRetry - Automatically retry requests if the + * response is related to rate limits or certain intermittent server + * errors. We will exponentially backoff subsequent requests by default. + * (default: true) + * @param {object=} config.credentials - Credentials object. + * @param {boolean=} config.customEndpoint - If true, just return the provided request options. Default: false. + * @param {boolean=} config.useAuthWithCustomEndpoint - If true, will authenticate when using a custom endpoint. Default: false. + * @param {string=} config.email - Account email address, required for PEM/P12 usage. + * @param {number=} config.maxRetries - Maximum number of automatic retries attempted before returning the error. (default: 3) + * @param {string=} config.keyFile - Path to a .json, .pem, or .p12 keyfile. + * @param {array} config.scopes - Array of scopes required for the API. + */ + makeAuthenticatedRequestFactory(config) { + const googleAutoAuthConfig = { ...config }; + if (googleAutoAuthConfig.projectId === service_js_1.DEFAULT_PROJECT_ID_TOKEN) { + delete googleAutoAuthConfig.projectId; + } + let authClient; + if (googleAutoAuthConfig.authClient instanceof google_auth_library_1.GoogleAuth) { + // Use an existing `GoogleAuth` + authClient = googleAutoAuthConfig.authClient; + } + else { + // Pass an `AuthClient` & `clientOptions` to `GoogleAuth`, if available + authClient = new google_auth_library_1.GoogleAuth({ + ...googleAutoAuthConfig, + authClient: googleAutoAuthConfig.authClient, + clientOptions: googleAutoAuthConfig.clientOptions, + }); + } + function makeAuthenticatedRequest(reqOpts, optionsOrCallback) { + let stream; + let projectId; + const reqConfig = { ...config }; + let activeRequest_; + if (!optionsOrCallback) { + stream = (0, duplexify_1.default)(); + reqConfig.stream = stream; + } + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : undefined; + const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : undefined; + async function setProjectId() { + projectId = await authClient.getProjectId(); + } + const onAuthenticated = async (err, authenticatedReqOpts) => { + const authLibraryError = err; + const autoAuthFailed = err && + typeof err.message === 'string' && + err.message.indexOf('Could not load the default credentials') > -1; + if (autoAuthFailed) { + // Even though authentication failed, the API might not actually + // care. + authenticatedReqOpts = reqOpts; + } + if (!err || autoAuthFailed) { + try { + // Try with existing `projectId` value + authenticatedReqOpts = util.decorateRequest(authenticatedReqOpts, projectId); + err = null; + } + catch (e) { + if (e instanceof projectify_1.MissingProjectIdError) { + // A `projectId` was required, but we don't have one. + try { + // Attempt to get the `projectId` + await setProjectId(); + authenticatedReqOpts = util.decorateRequest(authenticatedReqOpts, projectId); + err = null; + } + catch (e) { + // Re-use the "Could not load the default credentials error" if + // auto auth failed. + err = err || e; + } + } + else { + // Some other error unrelated to missing `projectId` + err = err || e; + } + } + } + if (err) { + if (stream) { + stream.destroy(err); + } + else { + const fn = options && options.onAuthenticated + ? options.onAuthenticated + : callback; + fn(err); + } + return; + } + if (options && options.onAuthenticated) { + options.onAuthenticated(null, authenticatedReqOpts); + } + else { + activeRequest_ = util.makeRequest(authenticatedReqOpts, reqConfig, (apiResponseError, ...params) => { + if (apiResponseError && + apiResponseError.code === 401 && + authLibraryError) { + // Re-use the "Could not load the default credentials error" if + // the API request failed due to missing credentials. + apiResponseError = authLibraryError; + } + callback(apiResponseError, ...params); + }); + } + }; + const prepareRequest = async () => { + try { + const getProjectId = async () => { + if (config.projectId && + config.projectId !== service_js_1.DEFAULT_PROJECT_ID_TOKEN) { + // The user provided a project ID. We don't need to check with the + // auth client, it could be incorrect. + return config.projectId; + } + if (config.projectIdRequired === false) { + // A projectId is not required. Return the default. + return service_js_1.DEFAULT_PROJECT_ID_TOKEN; + } + return setProjectId(); + }; + const authorizeRequest = async () => { + if (reqConfig.customEndpoint && + !reqConfig.useAuthWithCustomEndpoint) { + // Using a custom API override. Do not use `google-auth-library` for + // authentication. (ex: connecting to a local Datastore server) + return reqOpts; + } + else { + return authClient.authorizeRequest(reqOpts); + } + }; + const [_projectId, authorizedReqOpts] = await Promise.all([ + getProjectId(), + authorizeRequest(), + ]); + if (_projectId) { + projectId = _projectId; + } + return onAuthenticated(null, authorizedReqOpts); + } + catch (e) { + return onAuthenticated(e); + } + }; + prepareRequest(); + if (stream) { + return stream; + } + return { + abort() { + setImmediate(() => { + if (activeRequest_) { + activeRequest_.abort(); + activeRequest_ = null; + } + }); + }, + }; + } + const mar = makeAuthenticatedRequest; + mar.getCredentials = authClient.getCredentials.bind(authClient); + mar.authClient = authClient; + return mar; + } + /** + * Make a request through the `retryRequest` module with built-in error + * handling and exponential back off. + * + * @param {object} reqOpts - Request options in the format `request` expects. + * @param {object=} config - Configuration object. + * @param {boolean=} config.autoRetry - Automatically retry requests if the + * response is related to rate limits or certain intermittent server + * errors. We will exponentially backoff subsequent requests by default. + * (default: true) + * @param {number=} config.maxRetries - Maximum number of automatic retries + * attempted before returning the error. (default: 3) + * @param {object=} config.request - HTTP module for request calls. + * @param {function} callback - The callback function. + */ + makeRequest(reqOpts, config, callback) { + var _a, _b, _c, _d, _e; + let autoRetryValue = AUTO_RETRY_DEFAULT; + if (config.autoRetry !== undefined) { + autoRetryValue = config.autoRetry; + } + else if (((_a = config.retryOptions) === null || _a === void 0 ? void 0 : _a.autoRetry) !== undefined) { + autoRetryValue = config.retryOptions.autoRetry; + } + let maxRetryValue = MAX_RETRY_DEFAULT; + if (config.maxRetries !== undefined) { + maxRetryValue = config.maxRetries; + } + else if (((_b = config.retryOptions) === null || _b === void 0 ? void 0 : _b.maxRetries) !== undefined) { + maxRetryValue = config.retryOptions.maxRetries; + } + requestDefaults.headers = this._getDefaultHeaders(reqOpts[exports.GCCL_GCS_CMD_KEY]); + const options = { + request: teeny_request_1.teenyRequest.defaults(requestDefaults), + retries: autoRetryValue !== false ? maxRetryValue : 0, + noResponseRetries: autoRetryValue !== false ? maxRetryValue : 0, + shouldRetryFn(httpRespMessage) { + var _a, _b; + const err = util.parseHttpRespMessage(httpRespMessage).err; + if ((_a = config.retryOptions) === null || _a === void 0 ? void 0 : _a.retryableErrorFn) { + return err && ((_b = config.retryOptions) === null || _b === void 0 ? void 0 : _b.retryableErrorFn(err)); + } + return err && util.shouldRetryRequest(err); + }, + maxRetryDelay: (_c = config.retryOptions) === null || _c === void 0 ? void 0 : _c.maxRetryDelay, + retryDelayMultiplier: (_d = config.retryOptions) === null || _d === void 0 ? void 0 : _d.retryDelayMultiplier, + totalTimeout: (_e = config.retryOptions) === null || _e === void 0 ? void 0 : _e.totalTimeout, + }; + if (typeof reqOpts.maxRetries === 'number') { + options.retries = reqOpts.maxRetries; + options.noResponseRetries = reqOpts.maxRetries; + } + if (!config.stream) { + return (0, retry_request_1.default)(reqOpts, options, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (err, response, body) => { + util.handleResp(err, response, body, callback); + }); + } + const dup = config.stream; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let requestStream; + const isGetRequest = (reqOpts.method || 'GET').toUpperCase() === 'GET'; + if (isGetRequest) { + requestStream = (0, retry_request_1.default)(reqOpts, options); + dup.setReadable(requestStream); + } + else { + // Streaming writable HTTP requests cannot be retried. + requestStream = options.request(reqOpts); + dup.setWritable(requestStream); + } + // Replay the Request events back to the stream. + requestStream + .on('error', dup.destroy.bind(dup)) + .on('response', dup.emit.bind(dup, 'response')) + .on('complete', dup.emit.bind(dup, 'complete')); + dup.abort = requestStream.abort; + return dup; + } + /** + * Decorate the options about to be made in a request. + * + * @param {object} reqOpts - The options to be passed to `request`. + * @param {string} projectId - The project ID. + * @return {object} reqOpts - The decorated reqOpts. + */ + decorateRequest(reqOpts, projectId) { + delete reqOpts.autoPaginate; + delete reqOpts.autoPaginateVal; + delete reqOpts.objectMode; + if (reqOpts.qs !== null && typeof reqOpts.qs === 'object') { + delete reqOpts.qs.autoPaginate; + delete reqOpts.qs.autoPaginateVal; + reqOpts.qs = (0, projectify_1.replaceProjectIdToken)(reqOpts.qs, projectId); + } + if (Array.isArray(reqOpts.multipart)) { + reqOpts.multipart = reqOpts.multipart.map(part => { + return (0, projectify_1.replaceProjectIdToken)(part, projectId); + }); + } + if (reqOpts.json !== null && typeof reqOpts.json === 'object') { + delete reqOpts.json.autoPaginate; + delete reqOpts.json.autoPaginateVal; + reqOpts.json = (0, projectify_1.replaceProjectIdToken)(reqOpts.json, projectId); + } + reqOpts.uri = (0, projectify_1.replaceProjectIdToken)(reqOpts.uri, projectId); + return reqOpts; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + isCustomType(unknown, module) { + function getConstructorName(obj) { + return obj.constructor && obj.constructor.name.toLowerCase(); + } + const moduleNameParts = module.split('/'); + const parentModuleName = moduleNameParts[0] && moduleNameParts[0].toLowerCase(); + const subModuleName = moduleNameParts[1] && moduleNameParts[1].toLowerCase(); + if (subModuleName && getConstructorName(unknown) !== subModuleName) { + return false; + } + let walkingModule = unknown; + // eslint-disable-next-line no-constant-condition + while (true) { + if (getConstructorName(walkingModule) === parentModuleName) { + return true; + } + walkingModule = walkingModule.parent; + if (!walkingModule) { + return false; + } + } + } + /** + * Given two parameters, figure out if this is either: + * - Just a callback function + * - An options object, and then a callback function + * @param optionsOrCallback An options object or callback. + * @param cb A potentially undefined callback. + */ + maybeOptionsOrCallback(optionsOrCallback, cb) { + return typeof optionsOrCallback === 'function' + ? [{}, optionsOrCallback] + : [optionsOrCallback, cb]; + } + _getDefaultHeaders(gcclGcsCmd) { + const headers = { + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${uuid.v4()}`, + }; + if (gcclGcsCmd) { + headers['x-goog-api-client'] += ` gccl-gcs-cmd/${gcclGcsCmd}`; + } + return headers; + } +} +exports.Util = Util; +/** + * Basic Passthrough Stream that records the number of bytes read + * every time the cursor is moved. + */ +class ProgressStream extends stream_1.Transform { + constructor() { + super(...arguments); + this.bytesRead = 0; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _transform(chunk, encoding, callback) { + this.bytesRead += chunk.length; + this.emit('progress', { bytesWritten: this.bytesRead, contentLength: '*' }); + this.push(chunk); + callback(); + } +} +const util = new Util(); +exports.util = util; + + +/***/ }), + +/***/ 18598: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Notification = void 0; +const index_js_1 = __nccwpck_require__(11325); +const promisify_1 = __nccwpck_require__(60206); +/** + * The API-formatted resource description of the notification. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name Notification#metadata + * @type {object} + */ +/** + * A Notification object is created from your {@link Bucket} object using + * {@link Bucket#notification}. Use it to interact with Cloud Pub/Sub + * notifications. + * + * See {@link https://cloud.google.com/storage/docs/pubsub-notifications| Cloud Pub/Sub Notifications for Google Cloud Storage} + * + * @class + * @hideconstructor + * + * @param {Bucket} bucket The bucket instance this notification is attached to. + * @param {string} id The ID of the notification. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const notification = myBucket.notification('1'); + * ``` + */ +class Notification extends index_js_1.ServiceObject { + constructor(bucket, id) { + const requestQueryObject = {}; + const methods = { + /** + * Creates a notification subscription for the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/insert| Notifications: insert} + * @method Notification#create + * + * @param {Topic|string} topic The Cloud PubSub topic to which this + * subscription publishes. If the project ID is omitted, the current + * project ID will be used. + * + * Acceptable formats are: + * - `projects/grape-spaceship-123/topics/my-topic` + * + * - `my-topic` + * @param {CreateNotificationRequest} [options] Metadata to set for + * the notification. + * @param {CreateNotificationCallback} [callback] Callback function. + * @returns {Promise} + * @throws {Error} If a valid topic is not provided. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.create(function(err, notification, apiResponse) { + * if (!err) { + * // The notification was created successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.create().then(function(data) { + * const notification = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + create: true, + /** + * @typedef {array} DeleteNotificationResponse + * @property {object} 0 The full API response. + */ + /** + * Permanently deletes a notification subscription. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/delete| Notifications: delete API Documentation} + * + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DeleteNotificationCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.delete(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/deleteNotification.js + * region_tag:storage_delete_bucket_notification + * Another example: + */ + delete: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * Get a notification and its metadata if it exists. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/get| Notifications: get API Documentation} + * + * @param {object} [options] Configuration options. + * See {@link Bucket#createNotification} for create options. + * @param {boolean} [options.autoCreate] Automatically create the object if + * it does not exist. Default: `false`. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetNotificationCallback} [callback] Callback function. + * @return {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.get(function(err, notification, apiResponse) { + * // `notification.metadata` has been populated. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.get().then(function(data) { + * const notification = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + get: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * Get the notification's metadata. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/get| Notifications: get API Documentation} + * + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetNotificationMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.getMetadata(function(err, metadata, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.getMetadata().then(function(data) { + * const metadata = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/getMetadataNotifications.js + * region_tag:storage_print_pubsub_bucket_notification + * Another example: + */ + getMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} NotificationExistsResponse + * @property {boolean} 0 Whether the notification exists or not. + */ + /** + * @callback NotificationExistsCallback + * @param {?Error} err Request error, if any. + * @param {boolean} exists Whether the notification exists or not. + */ + /** + * Check if the notification exists. + * + * @method Notification#exists + * @param {NotificationExistsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.exists(function(err, exists) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.exists().then(function(data) { + * const exists = data[0]; + * }); + * ``` + */ + exists: true, + }; + super({ + parent: bucket, + baseUrl: '/notificationConfigs', + id: id.toString(), + createMethod: bucket.createNotification.bind(bucket), + methods, + }); + } +} +exports.Notification = Notification; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Notification); + + +/***/ }), + +/***/ 88043: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _Upload_instances, _Upload_gcclGcsCmd, _Upload_resetLocalBuffersCache, _Upload_addLocalBufferCache; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Upload = exports.PROTOCOL_REGEX = void 0; +exports.upload = upload; +exports.createURI = createURI; +exports.checkUploadStatus = checkUploadStatus; +const abort_controller_1 = __importDefault(__nccwpck_require__(17413)); +const crypto_1 = __nccwpck_require__(76982); +const gaxios = __importStar(__nccwpck_require__(97003)); +const google_auth_library_1 = __nccwpck_require__(492); +const stream_1 = __nccwpck_require__(2203); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +const uuid = __importStar(__nccwpck_require__(20607)); +const util_js_1 = __nccwpck_require__(74557); +const util_js_2 = __nccwpck_require__(37325); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const NOT_FOUND_STATUS_CODE = 404; +const RESUMABLE_INCOMPLETE_STATUS_CODE = 308; +const packageJson = (0, package_json_helper_cjs_1.getPackageJSON)(); +exports.PROTOCOL_REGEX = /^(\w*):\/\//; +class Upload extends stream_1.Writable { + constructor(cfg) { + var _a; + super(cfg); + _Upload_instances.add(this); + this.numBytesWritten = 0; + this.numRetries = 0; + this.currentInvocationId = { + checkUploadStatus: uuid.v4(), + chunk: uuid.v4(), + uri: uuid.v4(), + }; + /** + * A cache of buffers written to this instance, ready for consuming + */ + this.writeBuffers = []; + this.numChunksReadInRequest = 0; + /** + * An array of buffers used for caching the most recent upload chunk. + * We should not assume that the server received all bytes sent in the request. + * - https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + */ + this.localWriteCache = []; + this.localWriteCacheByteLength = 0; + this.upstreamEnded = false; + _Upload_gcclGcsCmd.set(this, void 0); + cfg = cfg || {}; + if (!cfg.bucket || !cfg.file) { + throw new Error('A bucket and file name are required'); + } + if (cfg.offset && !cfg.uri) { + throw new RangeError('Cannot provide an `offset` without providing a `uri`'); + } + if (cfg.isPartialUpload && !cfg.chunkSize) { + throw new RangeError('Cannot set `isPartialUpload` without providing a `chunkSize`'); + } + cfg.authConfig = cfg.authConfig || {}; + cfg.authConfig.scopes = [ + 'https://www.googleapis.com/auth/devstorage.full_control', + ]; + this.authClient = cfg.authClient || new google_auth_library_1.GoogleAuth(cfg.authConfig); + const universe = cfg.universeDomain || google_auth_library_1.DEFAULT_UNIVERSE; + this.apiEndpoint = `https://storage.${universe}`; + if (cfg.apiEndpoint && cfg.apiEndpoint !== this.apiEndpoint) { + this.apiEndpoint = this.sanitizeEndpoint(cfg.apiEndpoint); + const hostname = new URL(this.apiEndpoint).hostname; + // check if it is a domain of a known universe + const isDomain = hostname === universe; + const isDefaultUniverseDomain = hostname === google_auth_library_1.DEFAULT_UNIVERSE; + // check if it is a subdomain of a known universe + // by checking a last (universe's length + 1) of a hostname + const isSubDomainOfUniverse = hostname.slice(-(universe.length + 1)) === `.${universe}`; + const isSubDomainOfDefaultUniverse = hostname.slice(-(google_auth_library_1.DEFAULT_UNIVERSE.length + 1)) === + `.${google_auth_library_1.DEFAULT_UNIVERSE}`; + if (!isDomain && + !isDefaultUniverseDomain && + !isSubDomainOfUniverse && + !isSubDomainOfDefaultUniverse) { + // a custom, non-universe domain, + // use gaxios + this.authClient = gaxios; + } + } + this.baseURI = `${this.apiEndpoint}/upload/storage/v1/b`; + this.bucket = cfg.bucket; + const cacheKeyElements = [cfg.bucket, cfg.file]; + if (typeof cfg.generation === 'number') { + cacheKeyElements.push(`${cfg.generation}`); + } + this.cacheKey = cacheKeyElements.join('/'); + this.customRequestOptions = cfg.customRequestOptions || {}; + this.file = cfg.file; + this.generation = cfg.generation; + this.kmsKeyName = cfg.kmsKeyName; + this.metadata = cfg.metadata || {}; + this.offset = cfg.offset; + this.origin = cfg.origin; + this.params = cfg.params || {}; + this.userProject = cfg.userProject; + this.chunkSize = cfg.chunkSize; + this.retryOptions = cfg.retryOptions; + this.isPartialUpload = (_a = cfg.isPartialUpload) !== null && _a !== void 0 ? _a : false; + if (cfg.key) { + if (typeof cfg.key === 'string') { + const base64Key = Buffer.from(cfg.key).toString('base64'); + this.encryption = { + key: base64Key, + hash: (0, crypto_1.createHash)('sha256').update(cfg.key).digest('base64'), + }; + } + else { + const base64Key = cfg.key.toString('base64'); + this.encryption = { + key: base64Key, + hash: (0, crypto_1.createHash)('sha256').update(cfg.key).digest('base64'), + }; + } + } + this.predefinedAcl = cfg.predefinedAcl; + if (cfg.private) + this.predefinedAcl = 'private'; + if (cfg.public) + this.predefinedAcl = 'publicRead'; + const autoRetry = cfg.retryOptions.autoRetry; + this.uriProvidedManually = !!cfg.uri; + this.uri = cfg.uri; + if (this.offset) { + // we're resuming an incomplete upload + this.numBytesWritten = this.offset; + } + this.numRetries = 0; // counter for number of retries currently executed + if (!autoRetry) { + cfg.retryOptions.maxRetries = 0; + } + this.timeOfFirstRequest = Date.now(); + const contentLength = cfg.metadata + ? Number(cfg.metadata.contentLength) + : NaN; + this.contentLength = isNaN(contentLength) ? '*' : contentLength; + __classPrivateFieldSet(this, _Upload_gcclGcsCmd, cfg[util_js_2.GCCL_GCS_CMD_KEY], "f"); + this.once('writing', () => { + if (this.uri) { + this.continueUploading(); + } + else { + this.createURI(err => { + if (err) { + return this.destroy(err); + } + this.startUploading(); + return; + }); + } + }); + } + /** + * Prevent 'finish' event until the upload has succeeded. + * + * @param fireFinishEvent The finish callback + */ + _final(fireFinishEvent = () => { }) { + this.upstreamEnded = true; + this.once('uploadFinished', fireFinishEvent); + process.nextTick(() => { + this.emit('upstreamFinished'); + // it's possible `_write` may not be called - namely for empty object uploads + this.emit('writing'); + }); + } + /** + * Handles incoming data from upstream + * + * @param chunk The chunk to append to the buffer + * @param encoding The encoding of the chunk + * @param readCallback A callback for when the buffer has been read downstream + */ + _write(chunk, encoding, readCallback = () => { }) { + // Backwards-compatible event + this.emit('writing'); + this.writeBuffers.push(typeof chunk === 'string' ? Buffer.from(chunk, encoding) : chunk); + this.once('readFromChunkBuffer', readCallback); + process.nextTick(() => this.emit('wroteToChunkBuffer')); + } + /** + * Prepends the local buffer to write buffer and resets it. + * + * @param keepLastBytes number of bytes to keep from the end of the local buffer. + */ + prependLocalBufferToUpstream(keepLastBytes) { + // Typically, the upstream write buffers should be smaller than the local + // cache, so we can save time by setting the local cache as the new + // upstream write buffer array and appending the old array to it + let initialBuffers = []; + if (keepLastBytes) { + // we only want the last X bytes + let bytesKept = 0; + while (keepLastBytes > bytesKept) { + // load backwards because we want the last X bytes + // note: `localWriteCacheByteLength` is reset below + let buf = this.localWriteCache.pop(); + if (!buf) + break; + bytesKept += buf.byteLength; + if (bytesKept > keepLastBytes) { + // we have gone over the amount desired, let's keep the last X bytes + // of this buffer + const diff = bytesKept - keepLastBytes; + buf = buf.subarray(diff); + bytesKept -= diff; + } + initialBuffers.unshift(buf); + } + } + else { + // we're keeping all of the local cache, simply use it as the initial buffer + initialBuffers = this.localWriteCache; + } + // Append the old upstream to the new + const append = this.writeBuffers; + this.writeBuffers = initialBuffers; + for (const buf of append) { + this.writeBuffers.push(buf); + } + // reset last buffers sent + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + } + /** + * Retrieves data from upstream's buffer. + * + * @param limit The maximum amount to return from the buffer. + */ + *pullFromChunkBuffer(limit) { + while (limit) { + const buf = this.writeBuffers.shift(); + if (!buf) + break; + let bufToYield = buf; + if (buf.byteLength > limit) { + bufToYield = buf.subarray(0, limit); + this.writeBuffers.unshift(buf.subarray(limit)); + limit = 0; + } + else { + limit -= buf.byteLength; + } + yield bufToYield; + // Notify upstream we've read from the buffer and we're able to consume + // more. It can also potentially send more data down as we're currently + // iterating. + this.emit('readFromChunkBuffer'); + } + } + /** + * A handler for determining if data is ready to be read from upstream. + * + * @returns If there will be more chunks to read in the future + */ + async waitForNextChunk() { + const willBeMoreChunks = await new Promise(resolve => { + // There's data available - it should be digested + if (this.writeBuffers.length) { + return resolve(true); + } + // The upstream writable ended, we shouldn't expect any more data. + if (this.upstreamEnded) { + return resolve(false); + } + // Nothing immediate seems to be determined. We need to prepare some + // listeners to determine next steps... + const wroteToChunkBufferCallback = () => { + removeListeners(); + return resolve(true); + }; + const upstreamFinishedCallback = () => { + removeListeners(); + // this should be the last chunk, if there's anything there + if (this.writeBuffers.length) + return resolve(true); + return resolve(false); + }; + // Remove listeners when we're ready to callback. + const removeListeners = () => { + this.removeListener('wroteToChunkBuffer', wroteToChunkBufferCallback); + this.removeListener('upstreamFinished', upstreamFinishedCallback); + }; + // If there's data recently written it should be digested + this.once('wroteToChunkBuffer', wroteToChunkBufferCallback); + // If the upstream finishes let's see if there's anything to grab + this.once('upstreamFinished', upstreamFinishedCallback); + }); + return willBeMoreChunks; + } + /** + * Reads data from upstream up to the provided `limit`. + * Ends when the limit has reached or no data is expected to be pushed from upstream. + * + * @param limit The most amount of data this iterator should return. `Infinity` by default. + */ + async *upstreamIterator(limit = Infinity) { + // read from upstream chunk buffer + while (limit && (await this.waitForNextChunk())) { + // read until end or limit has been reached + for (const chunk of this.pullFromChunkBuffer(limit)) { + limit -= chunk.byteLength; + yield chunk; + } + } + } + createURI(callback) { + if (!callback) { + return this.createURIAsync(); + } + this.createURIAsync().then(r => callback(null, r), callback); + } + async createURIAsync() { + const metadata = { ...this.metadata }; + const headers = {}; + // Delete content length and content type from metadata if they exist. + // These are headers and should not be sent as part of the metadata. + if (metadata.contentLength) { + headers['X-Upload-Content-Length'] = metadata.contentLength.toString(); + delete metadata.contentLength; + } + if (metadata.contentType) { + headers['X-Upload-Content-Type'] = metadata.contentType; + delete metadata.contentType; + } + let googAPIClient = `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${this.currentInvocationId.uri}`; + if (__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")) { + googAPIClient += ` gccl-gcs-cmd/${__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")}`; + } + // Check if headers already exist before creating new ones + const reqOpts = { + method: 'POST', + url: [this.baseURI, this.bucket, 'o'].join('/'), + params: Object.assign({ + name: this.file, + uploadType: 'resumable', + }, this.params), + data: metadata, + headers: { + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': googAPIClient, + ...headers, + }, + }; + if (metadata.contentLength) { + reqOpts.headers['X-Upload-Content-Length'] = + metadata.contentLength.toString(); + } + if (metadata.contentType) { + reqOpts.headers['X-Upload-Content-Type'] = metadata.contentType; + } + if (typeof this.generation !== 'undefined') { + reqOpts.params.ifGenerationMatch = this.generation; + } + if (this.kmsKeyName) { + reqOpts.params.kmsKeyName = this.kmsKeyName; + } + if (this.predefinedAcl) { + reqOpts.params.predefinedAcl = this.predefinedAcl; + } + if (this.origin) { + reqOpts.headers.Origin = this.origin; + } + const uri = await (0, async_retry_1.default)(async (bail) => { + var _a, _b, _c; + try { + const res = await this.makeRequest(reqOpts); + // We have successfully got a URI we can now create a new invocation id + this.currentInvocationId.uri = uuid.v4(); + return res.headers.location; + } + catch (err) { + const e = err; + const apiError = { + code: (_a = e.response) === null || _a === void 0 ? void 0 : _a.status, + name: (_b = e.response) === null || _b === void 0 ? void 0 : _b.statusText, + message: (_c = e.response) === null || _c === void 0 ? void 0 : _c.statusText, + errors: [ + { + reason: e.code, + }, + ], + }; + if (this.retryOptions.maxRetries > 0 && + this.retryOptions.retryableErrorFn(apiError)) { + throw e; + } + else { + return bail(e); + } + } + }, { + retries: this.retryOptions.maxRetries, + factor: this.retryOptions.retryDelayMultiplier, + maxTimeout: this.retryOptions.maxRetryDelay * 1000, //convert to milliseconds + maxRetryTime: this.retryOptions.totalTimeout * 1000, //convert to milliseconds + }); + this.uri = uri; + this.offset = 0; + // emit the newly generated URI for future reuse, if necessary. + this.emit('uri', uri); + return uri; + } + async continueUploading() { + var _a; + (_a = this.offset) !== null && _a !== void 0 ? _a : (await this.getAndSetOffset()); + return this.startUploading(); + } + async startUploading() { + const multiChunkMode = !!this.chunkSize; + let responseReceived = false; + this.numChunksReadInRequest = 0; + if (!this.offset) { + this.offset = 0; + } + // Check if the offset (server) is too far behind the current stream + if (this.offset < this.numBytesWritten) { + const delta = this.numBytesWritten - this.offset; + const message = `The offset is lower than the number of bytes written. The server has ${this.offset} bytes and while ${this.numBytesWritten} bytes has been uploaded - thus ${delta} bytes are missing. Stopping as this could result in data loss. Initiate a new upload to continue.`; + this.emit('error', new RangeError(message)); + return; + } + // Check if we should 'fast-forward' to the relevant data to upload + if (this.numBytesWritten < this.offset) { + // 'fast-forward' to the byte where we need to upload. + // only push data from the byte after the one we left off on + const fastForwardBytes = this.offset - this.numBytesWritten; + for await (const _chunk of this.upstreamIterator(fastForwardBytes)) { + _chunk; // discard the data up until the point we want + } + this.numBytesWritten = this.offset; + } + let expectedUploadSize = undefined; + // Set `expectedUploadSize` to `contentLength - this.numBytesWritten`, if available + if (typeof this.contentLength === 'number') { + expectedUploadSize = this.contentLength - this.numBytesWritten; + } + // `expectedUploadSize` should be no more than the `chunkSize`. + // It's possible this is the last chunk request for a multiple + // chunk upload, thus smaller than the chunk size. + if (this.chunkSize) { + expectedUploadSize = expectedUploadSize + ? Math.min(this.chunkSize, expectedUploadSize) + : this.chunkSize; + } + // A queue for the upstream data + const upstreamQueue = this.upstreamIterator(expectedUploadSize); + // The primary read stream for this request. This stream retrieves no more + // than the exact requested amount from upstream. + const requestStream = new stream_1.Readable({ + read: async () => { + // Don't attempt to retrieve data upstream if we already have a response + if (responseReceived) + requestStream.push(null); + const result = await upstreamQueue.next(); + if (result.value) { + this.numChunksReadInRequest++; + if (multiChunkMode) { + // save ever buffer used in the request in multi-chunk mode + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_addLocalBufferCache).call(this, result.value); + } + else { + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_addLocalBufferCache).call(this, result.value); + } + this.numBytesWritten += result.value.byteLength; + this.emit('progress', { + bytesWritten: this.numBytesWritten, + contentLength: this.contentLength, + }); + requestStream.push(result.value); + } + if (result.done) { + requestStream.push(null); + } + }, + }); + let googAPIClient = `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${this.currentInvocationId.chunk}`; + if (__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")) { + googAPIClient += ` gccl-gcs-cmd/${__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")}`; + } + const headers = { + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': googAPIClient, + }; + // If using multiple chunk upload, set appropriate header + if (multiChunkMode) { + // We need to know how much data is available upstream to set the `Content-Range` header. + // https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + for await (const chunk of this.upstreamIterator(expectedUploadSize)) { + // This will conveniently track and keep the size of the buffers. + // We will reach either the expected upload size or the remainder of the stream. + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_addLocalBufferCache).call(this, chunk); + } + // This is the sum from the `#addLocalBufferCache` calls + const bytesToUpload = this.localWriteCacheByteLength; + // Important: we want to know if the upstream has ended and the queue is empty before + // unshifting data back into the queue. This way we will know if this is the last request or not. + const isLastChunkOfUpload = !(await this.waitForNextChunk()); + // Important: put the data back in the queue for the actual upload + this.prependLocalBufferToUpstream(); + let totalObjectSize = this.contentLength; + if (typeof this.contentLength !== 'number' && + isLastChunkOfUpload && + !this.isPartialUpload) { + // Let's let the server know this is the last chunk of the object since we didn't set it before. + totalObjectSize = bytesToUpload + this.numBytesWritten; + } + // `- 1` as the ending byte is inclusive in the request. + const endingByte = bytesToUpload + this.numBytesWritten - 1; + // `Content-Length` for multiple chunk uploads is the size of the chunk, + // not the overall object + headers['Content-Length'] = bytesToUpload; + headers['Content-Range'] = + `bytes ${this.offset}-${endingByte}/${totalObjectSize}`; + } + else { + headers['Content-Range'] = `bytes ${this.offset}-*/${this.contentLength}`; + } + const reqOpts = { + method: 'PUT', + url: this.uri, + headers, + body: requestStream, + }; + try { + const resp = await this.makeRequestStream(reqOpts); + if (resp) { + responseReceived = true; + await this.responseHandler(resp); + } + } + catch (e) { + const err = e; + if (this.retryOptions.retryableErrorFn(err)) { + this.attemptDelayedRetry({ + status: NaN, + data: err, + }); + return; + } + this.destroy(err); + } + } + // Process the API response to look for errors that came in + // the response body. + async responseHandler(resp) { + if (resp.data.error) { + this.destroy(resp.data.error); + return; + } + // At this point we can safely create a new id for the chunk + this.currentInvocationId.chunk = uuid.v4(); + const moreDataToUpload = await this.waitForNextChunk(); + const shouldContinueWithNextMultiChunkRequest = this.chunkSize && + resp.status === RESUMABLE_INCOMPLETE_STATUS_CODE && + resp.headers.range && + moreDataToUpload; + /** + * This is true when we're expecting to upload more data in a future request, + * yet the upstream for the upload session has been exhausted. + */ + const shouldContinueUploadInAnotherRequest = this.isPartialUpload && + resp.status === RESUMABLE_INCOMPLETE_STATUS_CODE && + !moreDataToUpload; + if (shouldContinueWithNextMultiChunkRequest) { + // Use the upper value in this header to determine where to start the next chunk. + // We should not assume that the server received all bytes sent in the request. + // https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + const range = resp.headers.range; + this.offset = Number(range.split('-')[1]) + 1; + // We should not assume that the server received all bytes sent in the request. + // - https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + const missingBytes = this.numBytesWritten - this.offset; + if (missingBytes) { + // As multi-chunk uploads send one chunk per request and pulls one + // chunk into the pipeline, prepending the missing bytes back should + // be fine for the next request. + this.prependLocalBufferToUpstream(missingBytes); + this.numBytesWritten -= missingBytes; + } + else { + // No bytes missing - no need to keep the local cache + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + } + // continue uploading next chunk + this.continueUploading(); + } + else if (!this.isSuccessfulResponse(resp.status) && + !shouldContinueUploadInAnotherRequest) { + const err = new Error('Upload failed'); + err.code = resp.status; + err.name = 'Upload failed'; + if (resp === null || resp === void 0 ? void 0 : resp.data) { + err.errors = [resp === null || resp === void 0 ? void 0 : resp.data]; + } + this.destroy(err); + } + else { + // no need to keep the cache + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + if (resp && resp.data) { + resp.data.size = Number(resp.data.size); + } + this.emit('metadata', resp.data); + // Allow the object (Upload) to continue naturally so the user's + // "finish" event fires. + this.emit('uploadFinished'); + } + } + /** + * Check the status of an existing resumable upload. + * + * @param cfg A configuration to use. `uri` is required. + * @returns the current upload status + */ + async checkUploadStatus(config = {}) { + let googAPIClient = `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${this.currentInvocationId.checkUploadStatus}`; + if (__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")) { + googAPIClient += ` gccl-gcs-cmd/${__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")}`; + } + const opts = { + method: 'PUT', + url: this.uri, + headers: { + 'Content-Length': 0, + 'Content-Range': 'bytes */*', + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': googAPIClient, + }, + }; + try { + const resp = await this.makeRequest(opts); + // Successfully got the offset we can now create a new offset invocation id + this.currentInvocationId.checkUploadStatus = uuid.v4(); + return resp; + } + catch (e) { + if (config.retry === false || + !(e instanceof Error) || + !this.retryOptions.retryableErrorFn(e)) { + throw e; + } + const retryDelay = this.getRetryDelay(); + if (retryDelay <= 0) { + throw e; + } + await new Promise(res => setTimeout(res, retryDelay)); + return this.checkUploadStatus(config); + } + } + async getAndSetOffset() { + try { + // we want to handle retries in this method. + const resp = await this.checkUploadStatus({ retry: false }); + if (resp.status === RESUMABLE_INCOMPLETE_STATUS_CODE) { + if (typeof resp.headers.range === 'string') { + this.offset = Number(resp.headers.range.split('-')[1]) + 1; + return; + } + } + this.offset = 0; + } + catch (e) { + const err = e; + if (this.retryOptions.retryableErrorFn(err)) { + this.attemptDelayedRetry({ + status: NaN, + data: err, + }); + return; + } + this.destroy(err); + } + } + async makeRequest(reqOpts) { + if (this.encryption) { + reqOpts.headers = reqOpts.headers || {}; + reqOpts.headers['x-goog-encryption-algorithm'] = 'AES256'; + reqOpts.headers['x-goog-encryption-key'] = this.encryption.key.toString(); + reqOpts.headers['x-goog-encryption-key-sha256'] = + this.encryption.hash.toString(); + } + if (this.userProject) { + reqOpts.params = reqOpts.params || {}; + reqOpts.params.userProject = this.userProject; + } + // Let gaxios know we will handle a 308 error code ourselves. + reqOpts.validateStatus = (status) => { + return (this.isSuccessfulResponse(status) || + status === RESUMABLE_INCOMPLETE_STATUS_CODE); + }; + const combinedReqOpts = { + ...this.customRequestOptions, + ...reqOpts, + headers: { + ...this.customRequestOptions.headers, + ...reqOpts.headers, + }, + }; + const res = await this.authClient.request(combinedReqOpts); + if (res.data && res.data.error) { + throw res.data.error; + } + return res; + } + async makeRequestStream(reqOpts) { + const controller = new abort_controller_1.default(); + const errorCallback = () => controller.abort(); + this.once('error', errorCallback); + if (this.userProject) { + reqOpts.params = reqOpts.params || {}; + reqOpts.params.userProject = this.userProject; + } + reqOpts.signal = controller.signal; + reqOpts.validateStatus = () => true; + const combinedReqOpts = { + ...this.customRequestOptions, + ...reqOpts, + headers: { + ...this.customRequestOptions.headers, + ...reqOpts.headers, + }, + }; + const res = await this.authClient.request(combinedReqOpts); + const successfulRequest = this.onResponse(res); + this.removeListener('error', errorCallback); + return successfulRequest ? res : null; + } + /** + * @return {bool} is the request good? + */ + onResponse(resp) { + if (resp.status !== 200 && + this.retryOptions.retryableErrorFn({ + code: resp.status, + message: resp.statusText, + name: resp.statusText, + })) { + this.attemptDelayedRetry(resp); + return false; + } + this.emit('response', resp); + return true; + } + /** + * @param resp GaxiosResponse object from previous attempt + */ + attemptDelayedRetry(resp) { + if (this.numRetries < this.retryOptions.maxRetries) { + if (resp.status === NOT_FOUND_STATUS_CODE && + this.numChunksReadInRequest === 0) { + this.startUploading(); + } + else { + const retryDelay = this.getRetryDelay(); + if (retryDelay <= 0) { + this.destroy(new Error(`Retry total time limit exceeded - ${JSON.stringify(resp.data)}`)); + return; + } + // Unshift the local cache back in case it's needed for the next request. + this.numBytesWritten -= this.localWriteCacheByteLength; + this.prependLocalBufferToUpstream(); + // We don't know how much data has been received by the server. + // `continueUploading` will recheck the offset via `getAndSetOffset`. + // If `offset` < `numberBytesReceived` then we will raise a RangeError + // as we've streamed too much data that has been missed - this should + // not be the case for multi-chunk uploads as `lastChunkSent` is the + // body of the entire request. + this.offset = undefined; + setTimeout(this.continueUploading.bind(this), retryDelay); + } + this.numRetries++; + } + else { + this.destroy(new Error(`Retry limit exceeded - ${JSON.stringify(resp.data)}`)); + } + } + /** + * The amount of time to wait before retrying the request, in milliseconds. + * If negative, do not retry. + * + * @returns the amount of time to wait, in milliseconds. + */ + getRetryDelay() { + const randomMs = Math.round(Math.random() * 1000); + const waitTime = Math.pow(this.retryOptions.retryDelayMultiplier, this.numRetries) * + 1000 + + randomMs; + const maxAllowableDelayMs = this.retryOptions.totalTimeout * 1000 - + (Date.now() - this.timeOfFirstRequest); + const maxRetryDelayMs = this.retryOptions.maxRetryDelay * 1000; + return Math.min(waitTime, maxRetryDelayMs, maxAllowableDelayMs); + } + /* + * Prepare user-defined API endpoint for compatibility with our API. + */ + sanitizeEndpoint(url) { + if (!exports.PROTOCOL_REGEX.test(url)) { + url = `https://${url}`; + } + return url.replace(/\/+$/, ''); // Remove trailing slashes + } + /** + * Check if a given status code is 2xx + * + * @param status The status code to check + * @returns if the status is 2xx + */ + isSuccessfulResponse(status) { + return status >= 200 && status < 300; + } +} +exports.Upload = Upload; +_Upload_gcclGcsCmd = new WeakMap(), _Upload_instances = new WeakSet(), _Upload_resetLocalBuffersCache = function _Upload_resetLocalBuffersCache() { + this.localWriteCache = []; + this.localWriteCacheByteLength = 0; +}, _Upload_addLocalBufferCache = function _Upload_addLocalBufferCache(buf) { + this.localWriteCache.push(buf); + this.localWriteCacheByteLength += buf.byteLength; +}; +function upload(cfg) { + return new Upload(cfg); +} +function createURI(cfg, callback) { + const up = new Upload(cfg); + if (!callback) { + return up.createURI(); + } + up.createURI().then(r => callback(null, r), callback); +} +/** + * Check the status of an existing resumable upload. + * + * @param cfg A configuration to use. `uri` is required. + * @returns the current upload status + */ +function checkUploadStatus(cfg) { + const up = new Upload(cfg); + return up.checkUploadStatus(); +} + + +/***/ }), + +/***/ 7319: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SigningError = exports.URLSigner = exports.PATH_STYLED_HOST = exports.SignerExceptionMessages = void 0; +const crypto = __importStar(__nccwpck_require__(76982)); +const url = __importStar(__nccwpck_require__(87016)); +const storage_js_1 = __nccwpck_require__(92848); +const util_js_1 = __nccwpck_require__(74557); +var SignerExceptionMessages; +(function (SignerExceptionMessages) { + SignerExceptionMessages["ACCESSIBLE_DATE_INVALID"] = "The accessible at date provided was invalid."; + SignerExceptionMessages["EXPIRATION_BEFORE_ACCESSIBLE_DATE"] = "An expiration date cannot be before accessible date."; + SignerExceptionMessages["X_GOOG_CONTENT_SHA256"] = "The header X-Goog-Content-SHA256 must be a hexadecimal string."; +})(SignerExceptionMessages || (exports.SignerExceptionMessages = SignerExceptionMessages = {})); +/* + * Default signing version for getSignedUrl is 'v2'. + */ +const DEFAULT_SIGNING_VERSION = 'v2'; +const SEVEN_DAYS = 7 * 24 * 60 * 60; +/** + * @const {string} + * @deprecated - unused + */ +exports.PATH_STYLED_HOST = 'https://storage.googleapis.com'; +class URLSigner { + constructor(auth, bucket, file, + /** + * A {@link Storage} object. + * + * @privateRemarks + * + * Technically this is a required field, however it would be a breaking change to + * move it before optional properties. In the next major we should refactor the + * constructor of this class to only accept a config object. + */ + storage = new storage_js_1.Storage()) { + this.auth = auth; + this.bucket = bucket; + this.file = file; + this.storage = storage; + } + getSignedUrl(cfg) { + const expiresInSeconds = this.parseExpires(cfg.expires); + const method = cfg.method; + const accessibleAtInSeconds = this.parseAccessibleAt(cfg.accessibleAt); + if (expiresInSeconds < accessibleAtInSeconds) { + throw new Error(SignerExceptionMessages.EXPIRATION_BEFORE_ACCESSIBLE_DATE); + } + let customHost; + // Default style is `path`. + const isVirtualHostedStyle = cfg.virtualHostedStyle || false; + if (cfg.cname) { + customHost = cfg.cname; + } + else if (isVirtualHostedStyle) { + customHost = `https://${this.bucket.name}.storage.${this.storage.universeDomain}`; + } + const secondsToMilliseconds = 1000; + const config = Object.assign({}, cfg, { + method, + expiration: expiresInSeconds, + accessibleAt: new Date(secondsToMilliseconds * accessibleAtInSeconds), + bucket: this.bucket.name, + file: this.file ? (0, util_js_1.encodeURI)(this.file.name, false) : undefined, + }); + if (customHost) { + config.cname = customHost; + } + const version = cfg.version || DEFAULT_SIGNING_VERSION; + let promise; + if (version === 'v2') { + promise = this.getSignedUrlV2(config); + } + else if (version === 'v4') { + promise = this.getSignedUrlV4(config); + } + else { + throw new Error(`Invalid signed URL version: ${version}. Supported versions are 'v2' and 'v4'.`); + } + return promise.then(query => { + var _a; + query = Object.assign(query, cfg.queryParams); + const signedUrl = new url.URL(((_a = cfg.host) === null || _a === void 0 ? void 0 : _a.toString()) || config.cname || this.storage.apiEndpoint); + signedUrl.pathname = this.getResourcePath(!!config.cname, this.bucket.name, config.file); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + signedUrl.search = (0, util_js_1.qsStringify)(query); + return signedUrl.href; + }); + } + getSignedUrlV2(config) { + const canonicalHeadersString = this.getCanonicalHeaders(config.extensionHeaders || {}); + const resourcePath = this.getResourcePath(false, config.bucket, config.file); + const blobToSign = [ + config.method, + config.contentMd5 || '', + config.contentType || '', + config.expiration, + canonicalHeadersString + resourcePath, + ].join('\n'); + const sign = async () => { + var _a; + const auth = this.auth; + try { + const signature = await auth.sign(blobToSign, (_a = config.signingEndpoint) === null || _a === void 0 ? void 0 : _a.toString()); + const credentials = await auth.getCredentials(); + return { + GoogleAccessId: credentials.client_email, + Expires: config.expiration, + Signature: signature, + }; + } + catch (err) { + const error = err; + const signingErr = new SigningError(error.message); + signingErr.stack = error.stack; + throw signingErr; + } + }; + return sign(); + } + getSignedUrlV4(config) { + var _a; + config.accessibleAt = config.accessibleAt + ? config.accessibleAt + : new Date(); + const millisecondsToSeconds = 1.0 / 1000.0; + const expiresPeriodInSeconds = config.expiration - config.accessibleAt.valueOf() * millisecondsToSeconds; + // v4 limit expiration to be 7 days maximum + if (expiresPeriodInSeconds > SEVEN_DAYS) { + throw new Error(`Max allowed expiration is seven days (${SEVEN_DAYS} seconds).`); + } + const extensionHeaders = Object.assign({}, config.extensionHeaders); + const fqdn = new url.URL(((_a = config.host) === null || _a === void 0 ? void 0 : _a.toString()) || config.cname || this.storage.apiEndpoint); + extensionHeaders.host = fqdn.hostname; + if (config.contentMd5) { + extensionHeaders['content-md5'] = config.contentMd5; + } + if (config.contentType) { + extensionHeaders['content-type'] = config.contentType; + } + let contentSha256; + const sha256Header = extensionHeaders['x-goog-content-sha256']; + if (sha256Header) { + if (typeof sha256Header !== 'string' || + !/[A-Fa-f0-9]{40}/.test(sha256Header)) { + throw new Error(SignerExceptionMessages.X_GOOG_CONTENT_SHA256); + } + contentSha256 = sha256Header; + } + const signedHeaders = Object.keys(extensionHeaders) + .map(header => header.toLowerCase()) + .sort() + .join(';'); + const extensionHeadersString = this.getCanonicalHeaders(extensionHeaders); + const datestamp = (0, util_js_1.formatAsUTCISO)(config.accessibleAt); + const credentialScope = `${datestamp}/auto/storage/goog4_request`; + const sign = async () => { + var _a; + const credentials = await this.auth.getCredentials(); + const credential = `${credentials.client_email}/${credentialScope}`; + const dateISO = (0, util_js_1.formatAsUTCISO)(config.accessibleAt ? config.accessibleAt : new Date(), true); + const queryParams = { + 'X-Goog-Algorithm': 'GOOG4-RSA-SHA256', + 'X-Goog-Credential': credential, + 'X-Goog-Date': dateISO, + 'X-Goog-Expires': expiresPeriodInSeconds.toString(10), + 'X-Goog-SignedHeaders': signedHeaders, + ...(config.queryParams || {}), + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const canonicalQueryParams = this.getCanonicalQueryParams(queryParams); + const canonicalRequest = this.getCanonicalRequest(config.method, this.getResourcePath(!!config.cname, config.bucket, config.file), canonicalQueryParams, extensionHeadersString, signedHeaders, contentSha256); + const hash = crypto + .createHash('sha256') + .update(canonicalRequest) + .digest('hex'); + const blobToSign = [ + 'GOOG4-RSA-SHA256', + dateISO, + credentialScope, + hash, + ].join('\n'); + try { + const signature = await this.auth.sign(blobToSign, (_a = config.signingEndpoint) === null || _a === void 0 ? void 0 : _a.toString()); + const signatureHex = Buffer.from(signature, 'base64').toString('hex'); + const signedQuery = Object.assign({}, queryParams, { + 'X-Goog-Signature': signatureHex, + }); + return signedQuery; + } + catch (err) { + const error = err; + const signingErr = new SigningError(error.message); + signingErr.stack = error.stack; + throw signingErr; + } + }; + return sign(); + } + /** + * Create canonical headers for signing v4 url. + * + * The canonical headers for v4-signing a request demands header names are + * first lowercased, followed by sorting the header names. + * Then, construct the canonical headers part of the request: + * + ":" + Trim() + "\n" + * .. + * + ":" + Trim() + "\n" + * + * @param headers + * @private + */ + getCanonicalHeaders(headers) { + // Sort headers by their lowercased names + const sortedHeaders = (0, util_js_1.objectEntries)(headers) + // Convert header names to lowercase + .map(([headerName, value]) => [ + headerName.toLowerCase(), + value, + ]) + .sort((a, b) => a[0].localeCompare(b[0])); + return sortedHeaders + .filter(([, value]) => value !== undefined) + .map(([headerName, value]) => { + // - Convert Array (multi-valued header) into string, delimited by + // ',' (no space). + // - Trim leading and trailing spaces. + // - Convert sequential (2+) spaces into a single space + const canonicalValue = `${value}`.trim().replace(/\s{2,}/g, ' '); + return `${headerName}:${canonicalValue}\n`; + }) + .join(''); + } + getCanonicalRequest(method, path, query, headers, signedHeaders, contentSha256) { + return [ + method, + path, + query, + headers, + signedHeaders, + contentSha256 || 'UNSIGNED-PAYLOAD', + ].join('\n'); + } + getCanonicalQueryParams(query) { + return (0, util_js_1.objectEntries)(query) + .map(([key, value]) => [(0, util_js_1.encodeURI)(key, true), (0, util_js_1.encodeURI)(value, true)]) + .sort((a, b) => (a[0] < b[0] ? -1 : 1)) + .map(([key, value]) => `${key}=${value}`) + .join('&'); + } + getResourcePath(cname, bucket, file) { + if (cname) { + return '/' + (file || ''); + } + else if (file) { + return `/${bucket}/${file}`; + } + else { + return `/${bucket}`; + } + } + parseExpires(expires, current = new Date()) { + const expiresInMSeconds = new Date(expires).valueOf(); + if (isNaN(expiresInMSeconds)) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_INVALID); + } + if (expiresInMSeconds < current.valueOf()) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_PAST); + } + return Math.floor(expiresInMSeconds / 1000); // The API expects seconds. + } + parseAccessibleAt(accessibleAt) { + const accessibleAtInMSeconds = new Date(accessibleAt || new Date()).valueOf(); + if (isNaN(accessibleAtInMSeconds)) { + throw new Error(SignerExceptionMessages.ACCESSIBLE_DATE_INVALID); + } + return Math.floor(accessibleAtInMSeconds / 1000); // The API expects seconds. + } +} +exports.URLSigner = URLSigner; +/** + * Custom error type for errors related to getting signed errors and policies. + * + * @private + */ +class SigningError extends Error { + constructor() { + super(...arguments); + this.name = 'SigningError'; + } +} +exports.SigningError = SigningError; + + +/***/ }), + +/***/ 92848: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Storage = exports.RETRYABLE_ERR_FN_DEFAULT = exports.MAX_RETRY_DELAY_DEFAULT = exports.TOTAL_TIMEOUT_DEFAULT = exports.RETRY_DELAY_MULTIPLIER_DEFAULT = exports.MAX_RETRY_DEFAULT = exports.AUTO_RETRY_DEFAULT = exports.PROTOCOL_REGEX = exports.StorageExceptionMessages = exports.ExceptionMessages = exports.IdempotencyStrategy = void 0; +const index_js_1 = __nccwpck_require__(11325); +const paginator_1 = __nccwpck_require__(99469); +const promisify_1 = __nccwpck_require__(60206); +const stream_1 = __nccwpck_require__(2203); +const bucket_js_1 = __nccwpck_require__(82887); +const channel_js_1 = __nccwpck_require__(12658); +const file_js_1 = __nccwpck_require__(69975); +const util_js_1 = __nccwpck_require__(74557); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const hmacKey_js_1 = __nccwpck_require__(45891); +const crc32c_js_1 = __nccwpck_require__(34317); +const google_auth_library_1 = __nccwpck_require__(492); +var IdempotencyStrategy; +(function (IdempotencyStrategy) { + IdempotencyStrategy[IdempotencyStrategy["RetryAlways"] = 0] = "RetryAlways"; + IdempotencyStrategy[IdempotencyStrategy["RetryConditional"] = 1] = "RetryConditional"; + IdempotencyStrategy[IdempotencyStrategy["RetryNever"] = 2] = "RetryNever"; +})(IdempotencyStrategy || (exports.IdempotencyStrategy = IdempotencyStrategy = {})); +var ExceptionMessages; +(function (ExceptionMessages) { + ExceptionMessages["EXPIRATION_DATE_INVALID"] = "The expiration date provided was invalid."; + ExceptionMessages["EXPIRATION_DATE_PAST"] = "An expiration date cannot be in the past."; +})(ExceptionMessages || (exports.ExceptionMessages = ExceptionMessages = {})); +var StorageExceptionMessages; +(function (StorageExceptionMessages) { + StorageExceptionMessages["BUCKET_NAME_REQUIRED"] = "A bucket name is needed to use Cloud Storage."; + StorageExceptionMessages["BUCKET_NAME_REQUIRED_CREATE"] = "A name is required to create a bucket."; + StorageExceptionMessages["HMAC_SERVICE_ACCOUNT"] = "The first argument must be a service account email to create an HMAC key."; + StorageExceptionMessages["HMAC_ACCESS_ID"] = "An access ID is needed to create an HmacKey object."; +})(StorageExceptionMessages || (exports.StorageExceptionMessages = StorageExceptionMessages = {})); +exports.PROTOCOL_REGEX = /^(\w*):\/\//; +/** + * Default behavior: Automatically retry retriable server errors. + * + * @const {boolean} + */ +exports.AUTO_RETRY_DEFAULT = true; +/** + * Default behavior: Only attempt to retry retriable errors 3 times. + * + * @const {number} + */ +exports.MAX_RETRY_DEFAULT = 3; +/** + * Default behavior: Wait twice as long as previous retry before retrying. + * + * @const {number} + */ +exports.RETRY_DELAY_MULTIPLIER_DEFAULT = 2; +/** + * Default behavior: If the operation doesn't succeed after 600 seconds, + * stop retrying. + * + * @const {number} + */ +exports.TOTAL_TIMEOUT_DEFAULT = 600; +/** + * Default behavior: Wait no more than 64 seconds between retries. + * + * @const {number} + */ +exports.MAX_RETRY_DELAY_DEFAULT = 64; +/** + * Default behavior: Retry conditionally idempotent operations if correct preconditions are set. + * + * @const {enum} + * @private + */ +const IDEMPOTENCY_STRATEGY_DEFAULT = IdempotencyStrategy.RetryConditional; +/** + * Returns true if the API request should be retried, given the error that was + * given the first time the request was attempted. + * @const + * @param {error} err - The API error to check if it is appropriate to retry. + * @return {boolean} True if the API request should be retried, false otherwise. + */ +const RETRYABLE_ERR_FN_DEFAULT = function (err) { + var _a; + const isConnectionProblem = (reason) => { + return (reason.includes('eai_again') || // DNS lookup error + reason === 'econnreset' || + reason === 'unexpected connection closure' || + reason === 'epipe' || + reason === 'socket connection timeout'); + }; + if (err) { + if ([408, 429, 500, 502, 503, 504].indexOf(err.code) !== -1) { + return true; + } + if (typeof err.code === 'string') { + if (['408', '429', '500', '502', '503', '504'].indexOf(err.code) !== -1) { + return true; + } + const reason = err.code.toLowerCase(); + if (isConnectionProblem(reason)) { + return true; + } + } + if (err.errors) { + for (const e of err.errors) { + const reason = (_a = e === null || e === void 0 ? void 0 : e.reason) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase(); + if (reason && isConnectionProblem(reason)) { + return true; + } + } + } + } + return false; +}; +exports.RETRYABLE_ERR_FN_DEFAULT = RETRYABLE_ERR_FN_DEFAULT; +/*! Developer Documentation + * + * Invoke this method to create a new Storage object bound with pre-determined + * configuration options. For each object that can be created (e.g., a bucket), + * there is an equivalent static and instance method. While they are classes, + * they can be instantiated without use of the `new` keyword. + */ +/** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * This object provides constants to refer to the three permission levels that + * can be granted to an entity: + * + * - `gcs.acl.OWNER_ROLE` - ("OWNER") + * - `gcs.acl.READER_ROLE` - ("READER") + * - `gcs.acl.WRITER_ROLE` - ("WRITER") + * + * See {@link https://cloud.google.com/storage/docs/access-control/lists| About Access Control Lists} + * + * @name Storage#acl + * @type {object} + * @property {string} OWNER_ROLE + * @property {string} READER_ROLE + * @property {string} WRITER_ROLE + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const albums = storage.bucket('albums'); + * + * //- + * // Make all of the files currently in a bucket publicly readable. + * //- + * const options = { + * entity: 'allUsers', + * role: storage.acl.READER_ROLE + * }; + * + * albums.acl.add(options, function(err, aclObject) {}); + * + * //- + * // Make any new objects added to a bucket publicly readable. + * //- + * albums.acl.default.add(options, function(err, aclObject) {}); + * + * //- + * // Grant a user ownership permissions to a bucket. + * //- + * albums.acl.add({ + * entity: 'user-useremail@example.com', + * role: storage.acl.OWNER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * albums.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ +/** + * Get {@link Bucket} objects for all of the buckets in your project as + * a readable object stream. + * + * @method Storage#getBucketsStream + * @param {GetBucketsRequest} [query] Query object for listing buckets. + * @returns {ReadableStream} A readable stream that emits {@link Bucket} + * instances. + * + * @example + * ``` + * storage.getBucketsStream() + * .on('error', console.error) + * .on('data', function(bucket) { + * // bucket is a Bucket object. + * }) + * .on('end', function() { + * // All buckets retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * storage.getBucketsStream() + * .on('data', function(bucket) { + * this.end(); + * }); + * ``` + */ +/** + * Get {@link HmacKey} objects for all of the HMAC keys in the project in a + * readable object stream. + * + * @method Storage#getHmacKeysStream + * @param {GetHmacKeysOptions} [options] Configuration options. + * @returns {ReadableStream} A readable stream that emits {@link HmacKey} + * instances. + * + * @example + * ``` + * storage.getHmacKeysStream() + * .on('error', console.error) + * .on('data', function(hmacKey) { + * // hmacKey is an HmacKey object. + * }) + * .on('end', function() { + * // All HmacKey retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * storage.getHmacKeysStream() + * .on('data', function(bucket) { + * this.end(); + * }); + * ``` + */ +/** + *

ACLs

+ * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share files with other users + * and allow other users to access your buckets and files. + * + * To learn more about ACLs, read this overview on + * {@link https://cloud.google.com/storage/docs/access-control| Access Control}. + * + * See {@link https://cloud.google.com/storage/docs/overview| Cloud Storage overview} + * See {@link https://cloud.google.com/storage/docs/access-control| Access Control} + * + * @class + */ +class Storage extends index_js_1.Service { + getBucketsStream() { + // placeholder body, overwritten in constructor + return new stream_1.Readable(); + } + getHmacKeysStream() { + // placeholder body, overwritten in constructor + return new stream_1.Readable(); + } + /** + * @callback Crc32cGeneratorToStringCallback + * A method returning the CRC32C as a base64-encoded string. + * + * @returns {string} + * + * @example + * Hashing the string 'data' should return 'rth90Q==' + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.toString(); // 'rth90Q==' + * ``` + **/ + /** + * @callback Crc32cGeneratorValidateCallback + * A method validating a base64-encoded CRC32C string. + * + * @param {string} [value] base64-encoded CRC32C string to validate + * @returns {boolean} + * + * @example + * Should return `true` if the value matches, `false` otherwise + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.validate('DkjKuA=='); // false + * crc32c.validate('rth90Q=='); // true + * ``` + **/ + /** + * @callback Crc32cGeneratorUpdateCallback + * A method for passing `Buffer`s for CRC32C generation. + * + * @param {Buffer} [data] data to update CRC32C value with + * @returns {undefined} + * + * @example + * Hashing buffers from 'some ' and 'text\n' + * + * ```js + * const buffer1 = Buffer.from('some '); + * crc32c.update(buffer1); + * + * const buffer2 = Buffer.from('text\n'); + * crc32c.update(buffer2); + * + * crc32c.toString(); // 'DkjKuA==' + * ``` + **/ + /** + * @typedef {object} CRC32CValidator + * @property {Crc32cGeneratorToStringCallback} + * @property {Crc32cGeneratorValidateCallback} + * @property {Crc32cGeneratorUpdateCallback} + */ + /** + * @callback Crc32cGeneratorCallback + * @returns {CRC32CValidator} + */ + /** + * @typedef {object} StorageOptions + * @property {string} [projectId] The project ID from the Google Developer's + * Console, e.g. 'grape-spaceship-123'. We will also check the environment + * variable `GCLOUD_PROJECT` for your project ID. If your app is running + * in an environment which supports {@link + * https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application + * Application Default Credentials}, your project ID will be detected + * automatically. + * @property {string} [keyFilename] Full path to the a .json, .pem, or .p12 key + * downloaded from the Google Developers Console. If you provide a path to + * a JSON file, the `projectId` option above is not necessary. NOTE: .pem and + * .p12 require you to specify the `email` option as well. + * @property {string} [email] Account email address. Required when using a .pem + * or .p12 keyFilename. + * @property {object} [credentials] Credentials object. + * @property {string} [credentials.client_email] + * @property {string} [credentials.private_key] + * @property {object} [retryOptions] Options for customizing retries. Retriable server errors + * will be retried with exponential delay between them dictated by the formula + * max(maxRetryDelay, retryDelayMultiplier*retryNumber) until maxRetries or totalTimeout + * has been reached. Retries will only happen if autoRetry is set to true. + * @property {boolean} [retryOptions.autoRetry=true] Automatically retry requests if the + * response is related to rate limits or certain intermittent server + * errors. We will exponentially backoff subsequent requests by default. + * @property {number} [retryOptions.retryDelayMultiplier = 2] the multiplier by which to + * increase the delay time between the completion of failed requests, and the + * initiation of the subsequent retrying request. + * @property {number} [retryOptions.totalTimeout = 600] The total time, starting from + * when the initial request is sent, after which an error will + * be returned, regardless of the retrying attempts made meanwhile. + * @property {number} [retryOptions.maxRetryDelay = 64] The maximum delay time between requests. + * When this value is reached, ``retryDelayMultiplier`` will no longer be used to + * increase delay time. + * @property {number} [retryOptions.maxRetries=3] Maximum number of automatic retries + * attempted before returning the error. + * @property {function} [retryOptions.retryableErrorFn] Function that returns true if a given + * error should be retried and false otherwise. + * @property {enum} [retryOptions.idempotencyStrategy=IdempotencyStrategy.RetryConditional] Enumeration + * controls how conditionally idempotent operations are retried. Possible values are: RetryAlways - + * will respect other retry settings and attempt to retry conditionally idempotent operations. RetryConditional - + * will retry conditionally idempotent operations if the correct preconditions are set. RetryNever - never + * retry a conditionally idempotent operation. + * @property {string} [userAgent] The value to be prepended to the User-Agent + * header in API requests. + * @property {object} [authClient] `AuthClient` or `GoogleAuth` client to reuse instead of creating a new one. + * @property {number} [timeout] The amount of time in milliseconds to wait per http request before timing out. + * @property {object[]} [interceptors_] Array of custom request interceptors to be returned in the order they were assigned. + * @property {string} [apiEndpoint = storage.google.com] The API endpoint of the service used to make requests. + * @property {boolean} [useAuthWithCustomEndpoint = false] Controls whether or not to use authentication when using a custom endpoint. + * @property {Crc32cGeneratorCallback} [callback] A function that generates a CRC32C Validator. Defaults to {@link CRC32C} + */ + /** + * Constructs the Storage client. + * + * @example + * Create a client that uses Application Default Credentials + * (ADC) + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * ``` + * + * @example + * Create a client with explicit credentials + * ``` + * const storage = new Storage({ + * projectId: 'your-project-id', + * keyFilename: '/path/to/keyfile.json' + * }); + * ``` + * + * @example + * Create a client with credentials passed + * by value as a JavaScript object + * ``` + * const storage = new Storage({ + * projectId: 'your-project-id', + * credentials: { + * type: 'service_account', + * project_id: 'xxxxxxx', + * private_key_id: 'xxxx', + * private_key:'-----BEGIN PRIVATE KEY-----xxxxxxx\n-----END PRIVATE KEY-----\n', + * client_email: 'xxxx', + * client_id: 'xxx', + * auth_uri: 'https://accounts.google.com/o/oauth2/auth', + * token_uri: 'https://oauth2.googleapis.com/token', + * auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs', + * client_x509_cert_url: 'xxx', + * } + * }); + * ``` + * + * @example + * Create a client with credentials passed + * by loading a JSON file directly from disk + * ``` + * const storage = new Storage({ + * projectId: 'your-project-id', + * credentials: require('/path/to-keyfile.json') + * }); + * ``` + * + * @example + * Create a client with an `AuthClient` (e.g. `DownscopedClient`) + * ``` + * const {DownscopedClient} = require('google-auth-library'); + * const authClient = new DownscopedClient({...}); + * + * const storage = new Storage({authClient}); + * ``` + * + * Additional samples: + * - https://github.com/googleapis/google-auth-library-nodejs#sample-usage-1 + * - https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/downscopedclient.js + * + * @param {StorageOptions} [options] Configuration options. + */ + constructor(options = {}) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; + const universe = options.universeDomain || google_auth_library_1.DEFAULT_UNIVERSE; + let apiEndpoint = `https://storage.${universe}`; + let customEndpoint = false; + // Note: EMULATOR_HOST is an experimental configuration variable. Use apiEndpoint instead. + const EMULATOR_HOST = process.env.STORAGE_EMULATOR_HOST; + if (typeof EMULATOR_HOST === 'string') { + apiEndpoint = Storage.sanitizeEndpoint(EMULATOR_HOST); + customEndpoint = true; + } + if (options.apiEndpoint && options.apiEndpoint !== apiEndpoint) { + apiEndpoint = Storage.sanitizeEndpoint(options.apiEndpoint); + customEndpoint = true; + } + options = Object.assign({}, options, { apiEndpoint }); + // Note: EMULATOR_HOST is an experimental configuration variable. Use apiEndpoint instead. + const baseUrl = EMULATOR_HOST || `${options.apiEndpoint}/storage/v1`; + const config = { + apiEndpoint: options.apiEndpoint, + retryOptions: { + autoRetry: ((_a = options.retryOptions) === null || _a === void 0 ? void 0 : _a.autoRetry) !== undefined + ? (_b = options.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry + : exports.AUTO_RETRY_DEFAULT, + maxRetries: ((_c = options.retryOptions) === null || _c === void 0 ? void 0 : _c.maxRetries) + ? (_d = options.retryOptions) === null || _d === void 0 ? void 0 : _d.maxRetries + : exports.MAX_RETRY_DEFAULT, + retryDelayMultiplier: ((_e = options.retryOptions) === null || _e === void 0 ? void 0 : _e.retryDelayMultiplier) + ? (_f = options.retryOptions) === null || _f === void 0 ? void 0 : _f.retryDelayMultiplier + : exports.RETRY_DELAY_MULTIPLIER_DEFAULT, + totalTimeout: ((_g = options.retryOptions) === null || _g === void 0 ? void 0 : _g.totalTimeout) + ? (_h = options.retryOptions) === null || _h === void 0 ? void 0 : _h.totalTimeout + : exports.TOTAL_TIMEOUT_DEFAULT, + maxRetryDelay: ((_j = options.retryOptions) === null || _j === void 0 ? void 0 : _j.maxRetryDelay) + ? (_k = options.retryOptions) === null || _k === void 0 ? void 0 : _k.maxRetryDelay + : exports.MAX_RETRY_DELAY_DEFAULT, + retryableErrorFn: ((_l = options.retryOptions) === null || _l === void 0 ? void 0 : _l.retryableErrorFn) + ? (_m = options.retryOptions) === null || _m === void 0 ? void 0 : _m.retryableErrorFn + : exports.RETRYABLE_ERR_FN_DEFAULT, + idempotencyStrategy: ((_o = options.retryOptions) === null || _o === void 0 ? void 0 : _o.idempotencyStrategy) !== undefined + ? (_p = options.retryOptions) === null || _p === void 0 ? void 0 : _p.idempotencyStrategy + : IDEMPOTENCY_STRATEGY_DEFAULT, + }, + baseUrl, + customEndpoint, + useAuthWithCustomEndpoint: options === null || options === void 0 ? void 0 : options.useAuthWithCustomEndpoint, + projectIdRequired: false, + scopes: [ + 'https://www.googleapis.com/auth/iam', + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/devstorage.full_control', + ], + packageJson: (0, package_json_helper_cjs_1.getPackageJSON)(), + }; + super(config, options); + /** + * Reference to {@link Storage.acl}. + * + * @name Storage#acl + * @see Storage.acl + */ + this.acl = Storage.acl; + this.crc32cGenerator = + options.crc32cGenerator || crc32c_js_1.CRC32C_DEFAULT_VALIDATOR_GENERATOR; + this.retryOptions = config.retryOptions; + this.getBucketsStream = paginator_1.paginator.streamify('getBuckets'); + this.getHmacKeysStream = paginator_1.paginator.streamify('getHmacKeys'); + } + static sanitizeEndpoint(url) { + if (!exports.PROTOCOL_REGEX.test(url)) { + url = `https://${url}`; + } + return url.replace(/\/+$/, ''); // Remove trailing slashes + } + /** + * Get a reference to a Cloud Storage bucket. + * + * @param {string} name Name of the bucket. + * @param {object} [options] Configuration object. + * @param {string} [options.kmsKeyName] A Cloud KMS key that will be used to + * encrypt objects inserted into this bucket, if no encryption method is + * specified. + * @param {string} [options.userProject] User project to be billed for all + * requests made from this Bucket object. + * @returns {Bucket} + * @see Bucket + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const albums = storage.bucket('albums'); + * const photos = storage.bucket('photos'); + * ``` + */ + bucket(name, options) { + if (!name) { + throw new Error(StorageExceptionMessages.BUCKET_NAME_REQUIRED); + } + return new bucket_js_1.Bucket(this, name, options); + } + /** + * Reference a channel to receive notifications about changes to your bucket. + * + * @param {string} id The ID of the channel. + * @param {string} resourceId The resource ID of the channel. + * @returns {Channel} + * @see Channel + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const channel = storage.channel('id', 'resource-id'); + * ``` + */ + channel(id, resourceId) { + return new channel_js_1.Channel(this, id, resourceId); + } + /** + * @typedef {array} CreateBucketResponse + * @property {Bucket} 0 The new {@link Bucket}. + * @property {object} 1 The full API response. + */ + /** + * @callback CreateBucketCallback + * @param {?Error} err Request error, if any. + * @param {Bucket} bucket The new {@link Bucket}. + * @param {object} apiResponse The full API response. + */ + /** + * Metadata to set for the bucket. + * + * @typedef {object} CreateBucketRequest + * @property {boolean} [archive=false] Specify the storage class as Archive. + * @property {object} [autoclass.enabled=false] Specify whether Autoclass is + * enabled for the bucket. + * @property {object} [autoclass.terminalStorageClass='NEARLINE'] The storage class that objects in an Autoclass bucket eventually transition to if + * they are not read for a certain length of time. Valid values are NEARLINE and ARCHIVE. + * @property {boolean} [coldline=false] Specify the storage class as Coldline. + * @property {Cors[]} [cors=[]] Specify the CORS configuration to use. + * @property {CustomPlacementConfig} [customPlacementConfig={}] Specify the bucket's regions for dual-region buckets. + * For more information, see {@link https://cloud.google.com/storage/docs/locations| Bucket Locations}. + * @property {boolean} [dra=false] Specify the storage class as Durable Reduced + * Availability. + * @property {boolean} [enableObjectRetention=false] Specifiy whether or not object retention should be enabled on this bucket. + * @property {object} [hierarchicalNamespace.enabled=false] Specify whether or not to enable hierarchical namespace on this bucket. + * @property {string} [location] Specify the bucket's location. If specifying + * a dual-region, the `customPlacementConfig` property should be set in conjunction. + * For more information, see {@link https://cloud.google.com/storage/docs/locations| Bucket Locations}. + * @property {boolean} [multiRegional=false] Specify the storage class as + * Multi-Regional. + * @property {boolean} [nearline=false] Specify the storage class as Nearline. + * @property {boolean} [regional=false] Specify the storage class as Regional. + * @property {boolean} [requesterPays=false] Force the use of the User Project metadata field to assign operational + * costs when an operation is made on a Bucket and its objects. + * @property {string} [rpo] For dual-region buckets, controls whether turbo + * replication is enabled (`ASYNC_TURBO`) or disabled (`DEFAULT`). + * @property {boolean} [standard=true] Specify the storage class as Standard. + * @property {string} [storageClass] The new storage class. (`standard`, + * `nearline`, `coldline`, or `archive`). + * **Note:** The storage classes `multi_regional`, `regional`, and + * `durable_reduced_availability` are now legacy and will be deprecated in + * the future. + * @property {Versioning} [versioning=undefined] Specify the versioning status. + * @property {string} [userProject] The ID of the project which will be billed + * for the request. + */ + /** + * Create a bucket. + * + * Cloud Storage uses a flat namespace, so you can't create a bucket with + * a name that is already in use. For more information, see + * {@link https://cloud.google.com/storage/docs/bucketnaming.html#requirements| Bucket Naming Guidelines}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/insert| Buckets: insert API Documentation} + * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes} + * + * @param {string} name Name of the bucket to create. + * @param {CreateBucketRequest} [metadata] Metadata to set for the bucket. + * @param {CreateBucketCallback} [callback] Callback function. + * @returns {Promise} + * @throws {Error} If a name is not provided. + * @see Bucket#create + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const callback = function(err, bucket, apiResponse) { + * // `bucket` is a Bucket object. + * }; + * + * storage.createBucket('new-bucket', callback); + * + * //- + * // Create a bucket in a specific location and region. See the + * // Official JSON API docs for complete details on the `location` + * option. + * // + * //- + * const metadata = { + * location: 'US-CENTRAL1', + * regional: true + * }; + * + * storage.createBucket('new-bucket', metadata, callback); + * + * //- + * // Create a bucket with a retention policy of 6 months. + * //- + * const metadata = { + * retentionPolicy: { + * retentionPeriod: 15780000 // 6 months in seconds. + * } + * }; + * + * storage.createBucket('new-bucket', metadata, callback); + * + * //- + * // Enable versioning on a new bucket. + * //- + * const metadata = { + * versioning: { + * enabled: true + * } + * }; + * + * storage.createBucket('new-bucket', metadata, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.createBucket('new-bucket').then(function(data) { + * const bucket = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/buckets.js + * region_tag:storage_create_bucket + * Another example: + */ + createBucket(name, metadataOrCallback, callback) { + if (!name) { + throw new Error(StorageExceptionMessages.BUCKET_NAME_REQUIRED_CREATE); + } + let metadata; + if (!callback) { + callback = metadataOrCallback; + metadata = {}; + } + else { + metadata = metadataOrCallback; + } + const body = { + ...metadata, + name, + }; + const storageClasses = { + archive: 'ARCHIVE', + coldline: 'COLDLINE', + dra: 'DURABLE_REDUCED_AVAILABILITY', + multiRegional: 'MULTI_REGIONAL', + nearline: 'NEARLINE', + regional: 'REGIONAL', + standard: 'STANDARD', + }; + const storageClassKeys = Object.keys(storageClasses); + for (const storageClass of storageClassKeys) { + if (body[storageClass]) { + if (metadata.storageClass && metadata.storageClass !== storageClass) { + throw new Error(`Both \`${storageClass}\` and \`storageClass\` were provided.`); + } + body.storageClass = storageClasses[storageClass]; + delete body[storageClass]; + } + } + if (body.requesterPays) { + body.billing = { + requesterPays: body.requesterPays, + }; + delete body.requesterPays; + } + const query = { + project: this.projectId, + }; + if (body.userProject) { + query.userProject = body.userProject; + delete body.userProject; + } + if (body.enableObjectRetention) { + query.enableObjectRetention = body.enableObjectRetention; + delete body.enableObjectRetention; + } + if (body.predefinedAcl) { + query.predefinedAcl = body.predefinedAcl; + delete body.predefinedAcl; + } + if (body.predefinedDefaultObjectAcl) { + query.predefinedDefaultObjectAcl = body.predefinedDefaultObjectAcl; + delete body.predefinedDefaultObjectAcl; + } + if (body.projection) { + query.projection = body.projection; + delete body.projection; + } + this.request({ + method: 'POST', + uri: '/b', + qs: query, + json: body, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + const bucket = this.bucket(name); + bucket.metadata = resp; + callback(null, bucket, resp); + }); + } + /** + * @typedef {object} CreateHmacKeyOptions + * @property {string} [projectId] The project ID of the project that owns + * the service account of the requested HMAC key. If not provided, + * the project ID used to instantiate the Storage client will be used. + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * @typedef {object} HmacKeyMetadata + * @property {string} accessId The access id identifies which HMAC key was + * used to sign a request when authenticating with HMAC. + * @property {string} etag Used to perform a read-modify-write of the key. + * @property {string} id The resource name of the HMAC key. + * @property {string} projectId The project ID. + * @property {string} serviceAccountEmail The service account's email this + * HMAC key is created for. + * @property {string} state The state of this HMAC key. One of "ACTIVE", + * "INACTIVE" or "DELETED". + * @property {string} timeCreated The creation time of the HMAC key in + * RFC 3339 format. + * @property {string} [updated] The time this HMAC key was last updated in + * RFC 3339 format. + */ + /** + * @typedef {array} CreateHmacKeyResponse + * @property {HmacKey} 0 The HmacKey instance created from API response. + * @property {string} 1 The HMAC key's secret used to access the XML API. + * @property {object} 3 The raw API response. + */ + /** + * @callback CreateHmacKeyCallback Callback function. + * @param {?Error} err Request error, if any. + * @param {HmacKey} hmacKey The HmacKey instance created from API response. + * @param {string} secret The HMAC key's secret used to access the XML API. + * @param {object} apiResponse The raw API response. + */ + /** + * Create an HMAC key associated with an service account to authenticate + * requests to the Cloud Storage XML API. + * + * See {@link https://cloud.google.com/storage/docs/authentication/hmackeys| HMAC keys documentation} + * + * @param {string} serviceAccountEmail The service account's email address + * with which the HMAC key is created for. + * @param {CreateHmacKeyCallback} [callback] Callback function. + * @return {Promise} + * + * @example + * ``` + * const {Storage} = require('google-cloud/storage'); + * const storage = new Storage(); + * + * // Replace with your service account's email address + * const serviceAccountEmail = + * 'my-service-account@appspot.gserviceaccount.com'; + * + * storage.createHmacKey(serviceAccountEmail, function(err, hmacKey, secret) { + * if (!err) { + * // Securely store the secret for use with the XML API. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.createHmacKey(serviceAccountEmail) + * .then((response) => { + * const hmacKey = response[0]; + * const secret = response[1]; + * // Securely store the secret for use with the XML API. + * }); + * ``` + */ + createHmacKey(serviceAccountEmail, optionsOrCb, cb) { + if (typeof serviceAccountEmail !== 'string') { + throw new Error(StorageExceptionMessages.HMAC_SERVICE_ACCOUNT); + } + const { options, callback } = (0, util_js_1.normalize)(optionsOrCb, cb); + const query = Object.assign({}, options, { serviceAccountEmail }); + const projectId = query.projectId || this.projectId; + delete query.projectId; + this.request({ + method: 'POST', + uri: `/projects/${projectId}/hmacKeys`, + qs: query, + maxRetries: 0, //explicitly set this value since this is a non-idempotent function + }, (err, resp) => { + if (err) { + callback(err, null, null, resp); + return; + } + const metadata = resp.metadata; + const hmacKey = this.hmacKey(metadata.accessId, { + projectId: metadata.projectId, + }); + hmacKey.metadata = resp.metadata; + callback(null, hmacKey, resp.secret, resp); + }); + } + /** + * Query object for listing buckets. + * + * @typedef {object} GetBucketsRequest + * @property {boolean} [autoPaginate=true] Have pagination handled + * automatically. + * @property {number} [maxApiCalls] Maximum number of API calls to make. + * @property {number} [maxResults] Maximum number of items plus prefixes to + * return per call. + * Note: By default will handle pagination automatically + * if more than 1 page worth of results are requested per call. + * When `autoPaginate` is set to `false` the smaller of `maxResults` + * or 1 page of results will be returned per call. + * @property {string} [pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @property {string} [userProject] The ID of the project which will be billed + * for the request. + * @param {boolean} [softDeleted] If true, returns the soft-deleted object. + * Object `generation` is required if `softDeleted` is set to True. + */ + /** + * @typedef {array} GetBucketsResponse + * @property {Bucket[]} 0 Array of {@link Bucket} instances. + * @property {object} 1 nextQuery A query object to receive more results. + * @property {object} 2 The full API response. + */ + /** + * @callback GetBucketsCallback + * @param {?Error} err Request error, if any. + * @param {Bucket[]} buckets Array of {@link Bucket} instances. + * @param {object} nextQuery A query object to receive more results. + * @param {object} apiResponse The full API response. + */ + /** + * Get Bucket objects for all of the buckets in your project. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/list| Buckets: list API Documentation} + * + * @param {GetBucketsRequest} [query] Query object for listing buckets. + * @param {GetBucketsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * storage.getBuckets(function(err, buckets) { + * if (!err) { + * // buckets is an array of Bucket objects. + * } + * }); + * + * //- + * // To control how many API requests are made and page through the results + * // manually, set `autoPaginate` to `false`. + * //- + * const callback = function(err, buckets, nextQuery, apiResponse) { + * if (nextQuery) { + * // More results exist. + * storage.getBuckets(nextQuery, callback); + * } + * + * // The `metadata` property is populated for you with the metadata at the + * // time of fetching. + * buckets[0].metadata; + * + * // However, in cases where you are concerned the metadata could have + * // changed, use the `getMetadata` method. + * buckets[0].getMetadata(function(err, metadata, apiResponse) {}); + * }; + * + * storage.getBuckets({ + * autoPaginate: false + * }, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.getBuckets().then(function(data) { + * const buckets = data[0]; + * }); + * + * ``` + * @example include:samples/buckets.js + * region_tag:storage_list_buckets + * Another example: + */ + getBuckets(optionsOrCallback, cb) { + const { options, callback } = (0, util_js_1.normalize)(optionsOrCallback, cb); + options.project = options.project || this.projectId; + this.request({ + uri: '/b', + qs: options, + }, (err, resp) => { + if (err) { + callback(err, null, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const buckets = itemsArray.map((bucket) => { + const bucketInstance = this.bucket(bucket.id); + bucketInstance.metadata = bucket; + return bucketInstance; + }); + const nextQuery = resp.nextPageToken + ? Object.assign({}, options, { pageToken: resp.nextPageToken }) + : null; + callback(null, buckets, nextQuery, resp); + }); + } + getHmacKeys(optionsOrCb, cb) { + const { options, callback } = (0, util_js_1.normalize)(optionsOrCb, cb); + const query = Object.assign({}, options); + const projectId = query.projectId || this.projectId; + delete query.projectId; + this.request({ + uri: `/projects/${projectId}/hmacKeys`, + qs: query, + }, (err, resp) => { + if (err) { + callback(err, null, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const hmacKeys = itemsArray.map((hmacKey) => { + const hmacKeyInstance = this.hmacKey(hmacKey.accessId, { + projectId: hmacKey.projectId, + }); + hmacKeyInstance.metadata = hmacKey; + return hmacKeyInstance; + }); + const nextQuery = resp.nextPageToken + ? Object.assign({}, options, { pageToken: resp.nextPageToken }) + : null; + callback(null, hmacKeys, nextQuery, resp); + }); + } + /** + * @typedef {array} GetServiceAccountResponse + * @property {object} 0 The service account resource. + * @property {object} 1 The full + * {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| API response}. + */ + /** + * @callback GetServiceAccountCallback + * @param {?Error} err Request error, if any. + * @param {object} serviceAccount The serviceAccount resource. + * @param {string} serviceAccount.emailAddress The service account email + * address. + * @param {object} apiResponse The full + * {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| API response}. + */ + /** + * Get the email address of this project's Google Cloud Storage service + * account. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount/get| Projects.serviceAccount: get API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| Projects.serviceAccount Resource} + * + * @param {object} [options] Configuration object. + * @param {string} [options.userProject] User project to be billed for this + * request. + * @param {GetServiceAccountCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * storage.getServiceAccount(function(err, serviceAccount, apiResponse) { + * if (!err) { + * const serviceAccountEmail = serviceAccount.emailAddress; + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.getServiceAccount().then(function(data) { + * const serviceAccountEmail = data[0].emailAddress; + * const apiResponse = data[1]; + * }); + * ``` + */ + getServiceAccount(optionsOrCallback, cb) { + const { options, callback } = (0, util_js_1.normalize)(optionsOrCallback, cb); + this.request({ + uri: `/projects/${this.projectId}/serviceAccount`, + qs: options, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + const camelCaseResponse = {}; + for (const prop in resp) { + // eslint-disable-next-line no-prototype-builtins + if (resp.hasOwnProperty(prop)) { + const camelCaseProp = prop.replace(/_(\w)/g, (_, match) => match.toUpperCase()); + camelCaseResponse[camelCaseProp] = resp[prop]; + } + } + callback(null, camelCaseResponse, resp); + }); + } + /** + * Get a reference to an HmacKey object. + * Note: this does not fetch the HMAC key's metadata. Use HmacKey#get() to + * retrieve and populate the metadata. + * + * To get a reference to an HMAC key that's not created for a service + * account in the same project used to instantiate the Storage client, + * supply the project's ID as `projectId` in the `options` argument. + * + * @param {string} accessId The HMAC key's access ID. + * @param {HmacKeyOptions} options HmacKey constructor options. + * @returns {HmacKey} + * @see HmacKey + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const hmacKey = storage.hmacKey('ACCESS_ID'); + * ``` + */ + hmacKey(accessId, options) { + if (!accessId) { + throw new Error(StorageExceptionMessages.HMAC_ACCESS_ID); + } + return new hmacKey_js_1.HmacKey(this, accessId, options); + } +} +exports.Storage = Storage; +/** + * {@link Bucket} class. + * + * @name Storage.Bucket + * @see Bucket + * @type {Constructor} + */ +Storage.Bucket = bucket_js_1.Bucket; +/** + * {@link Channel} class. + * + * @name Storage.Channel + * @see Channel + * @type {Constructor} + */ +Storage.Channel = channel_js_1.Channel; +/** + * {@link File} class. + * + * @name Storage.File + * @see File + * @type {Constructor} + */ +Storage.File = file_js_1.File; +/** + * {@link HmacKey} class. + * + * @name Storage.HmacKey + * @see HmacKey + * @type {Constructor} + */ +Storage.HmacKey = hmacKey_js_1.HmacKey; +Storage.acl = { + OWNER_ROLE: 'OWNER', + READER_ROLE: 'READER', + WRITER_ROLE: 'WRITER', +}; +/*! Developer Documentation + * + * These methods can be auto-paginated. + */ +paginator_1.paginator.extend(Storage, ['getBuckets', 'getHmacKeys']); +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Storage, { + exclude: ['bucket', 'channel', 'hmacKey'], +}); + + +/***/ }), + +/***/ 30004: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _XMLMultiPartUploadHelper_instances, _XMLMultiPartUploadHelper_setGoogApiClientHeaders, _XMLMultiPartUploadHelper_handleErrorResponse; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TransferManager = exports.MultiPartUploadError = void 0; +const file_js_1 = __nccwpck_require__(69975); +const p_limit_1 = __importDefault(__nccwpck_require__(58890)); +const path = __importStar(__nccwpck_require__(16928)); +const fs_1 = __nccwpck_require__(79896); +const crc32c_js_1 = __nccwpck_require__(34317); +const google_auth_library_1 = __nccwpck_require__(492); +const fast_xml_parser_1 = __nccwpck_require__(1290); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +const crypto_1 = __nccwpck_require__(76982); +const util_js_1 = __nccwpck_require__(37325); +const util_js_2 = __nccwpck_require__(74557); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const packageJson = (0, package_json_helper_cjs_1.getPackageJSON)(); +/** + * Default number of concurrently executing promises to use when calling uploadManyFiles. + * + */ +const DEFAULT_PARALLEL_UPLOAD_LIMIT = 5; +/** + * Default number of concurrently executing promises to use when calling downloadManyFiles. + * + */ +const DEFAULT_PARALLEL_DOWNLOAD_LIMIT = 5; +/** + * Default number of concurrently executing promises to use when calling downloadFileInChunks. + * + */ +const DEFAULT_PARALLEL_CHUNKED_DOWNLOAD_LIMIT = 5; +/** + * The minimum size threshold in bytes at which to apply a chunked download strategy when calling downloadFileInChunks. + * + */ +const DOWNLOAD_IN_CHUNKS_FILE_SIZE_THRESHOLD = 32 * 1024 * 1024; +/** + * The chunk size in bytes to use when calling downloadFileInChunks. + * + */ +const DOWNLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE = 32 * 1024 * 1024; +/** + * The chunk size in bytes to use when calling uploadFileInChunks. + * + */ +const UPLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE = 32 * 1024 * 1024; +/** + * Default number of concurrently executing promises to use when calling uploadFileInChunks. + * + */ +const DEFAULT_PARALLEL_CHUNKED_UPLOAD_LIMIT = 5; +const EMPTY_REGEX = '(?:)'; +/** + * The `gccl-gcs-cmd` value for the `X-Goog-API-Client` header. + * Example: `gccl-gcs-cmd/tm.upload_many` + * + * @see {@link GCCL_GCS_CMD}. + * @see {@link GCCL_GCS_CMD_KEY}. + */ +const GCCL_GCS_CMD_FEATURE = { + UPLOAD_MANY: 'tm.upload_many', + DOWNLOAD_MANY: 'tm.download_many', + UPLOAD_SHARDED: 'tm.upload_sharded', + DOWNLOAD_SHARDED: 'tm.download_sharded', +}; +const defaultMultiPartGenerator = (bucket, fileName, uploadId, partsMap) => { + return new XMLMultiPartUploadHelper(bucket, fileName, uploadId, partsMap); +}; +class MultiPartUploadError extends Error { + constructor(message, uploadId, partsMap) { + super(message); + this.uploadId = uploadId; + this.partsMap = partsMap; + } +} +exports.MultiPartUploadError = MultiPartUploadError; +/** + * Class representing an implementation of MPU in the XML API. This class is not meant for public usage. + * + * @private + * + */ +class XMLMultiPartUploadHelper { + constructor(bucket, fileName, uploadId, partsMap) { + _XMLMultiPartUploadHelper_instances.add(this); + this.authClient = bucket.storage.authClient || new google_auth_library_1.GoogleAuth(); + this.uploadId = uploadId || ''; + this.bucket = bucket; + this.fileName = fileName; + this.baseUrl = `https://${bucket.name}.${new URL(this.bucket.storage.apiEndpoint).hostname}/${fileName}`; + this.xmlBuilder = new fast_xml_parser_1.XMLBuilder({ arrayNodeName: 'Part' }); + this.xmlParser = new fast_xml_parser_1.XMLParser(); + this.partsMap = partsMap || new Map(); + this.retryOptions = { + retries: this.bucket.storage.retryOptions.maxRetries, + factor: this.bucket.storage.retryOptions.retryDelayMultiplier, + maxTimeout: this.bucket.storage.retryOptions.maxRetryDelay * 1000, + maxRetryTime: this.bucket.storage.retryOptions.totalTimeout * 1000, + }; + } + /** + * Initiates a multipart upload (MPU) to the XML API and stores the resultant upload id. + * + * @returns {Promise} + */ + async initiateUpload(headers = {}) { + const url = `${this.baseUrl}?uploads`; + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + headers: __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_setGoogApiClientHeaders).call(this, headers), + method: 'POST', + url, + }); + if (res.data && res.data.error) { + throw res.data.error; + } + const parsedXML = this.xmlParser.parse(res.data); + this.uploadId = parsedXML.InitiateMultipartUploadResult.UploadId; + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + } + }, this.retryOptions); + } + /** + * Uploads the provided chunk of data to the XML API using the previously created upload id. + * + * @param {number} partNumber the sequence number of this chunk. + * @param {Buffer} chunk the chunk of data to be uploaded. + * @param {string | false} validation whether or not to include the md5 hash in the headers to cause the server + * to validate the chunk was not corrupted. + * @returns {Promise} + */ + async uploadPart(partNumber, chunk, validation) { + const url = `${this.baseUrl}?partNumber=${partNumber}&uploadId=${this.uploadId}`; + let headers = __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_setGoogApiClientHeaders).call(this); + if (validation === 'md5') { + const hash = (0, crypto_1.createHash)('md5').update(chunk).digest('base64'); + headers = { + 'Content-MD5': hash, + }; + } + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + url, + method: 'PUT', + body: chunk, + headers, + }); + if (res.data && res.data.error) { + throw res.data.error; + } + this.partsMap.set(partNumber, res.headers['etag']); + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + } + }, this.retryOptions); + } + /** + * Sends the final request of the MPU to tell GCS the upload is now complete. + * + * @returns {Promise} + */ + async completeUpload() { + const url = `${this.baseUrl}?uploadId=${this.uploadId}`; + const sortedMap = new Map([...this.partsMap.entries()].sort((a, b) => a[0] - b[0])); + const parts = []; + for (const entry of sortedMap.entries()) { + parts.push({ PartNumber: entry[0], ETag: entry[1] }); + } + const body = `${this.xmlBuilder.build(parts)}`; + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + headers: __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_setGoogApiClientHeaders).call(this), + url, + method: 'POST', + body, + }); + if (res.data && res.data.error) { + throw res.data.error; + } + return res; + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + return; + } + }, this.retryOptions); + } + /** + * Aborts an multipart upload that is in progress. Once aborted, any parts in the process of being uploaded fail, + * and future requests using the upload ID fail. + * + * @returns {Promise} + */ + async abortUpload() { + const url = `${this.baseUrl}?uploadId=${this.uploadId}`; + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + url, + method: 'DELETE', + }); + if (res.data && res.data.error) { + throw res.data.error; + } + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + return; + } + }, this.retryOptions); + } +} +_XMLMultiPartUploadHelper_instances = new WeakSet(), _XMLMultiPartUploadHelper_setGoogApiClientHeaders = function _XMLMultiPartUploadHelper_setGoogApiClientHeaders(headers = {}) { + let headerFound = false; + let userAgentFound = false; + for (const [key, value] of Object.entries(headers)) { + if (key.toLocaleLowerCase().trim() === 'x-goog-api-client') { + headerFound = true; + // Prepend command feature to value, if not already there + if (!value.includes(GCCL_GCS_CMD_FEATURE.UPLOAD_SHARDED)) { + headers[key] = + `${value} gccl-gcs-cmd/${GCCL_GCS_CMD_FEATURE.UPLOAD_SHARDED}`; + } + } + else if (key.toLocaleLowerCase().trim() === 'user-agent') { + userAgentFound = true; + } + } + // If the header isn't present, add it + if (!headerFound) { + headers['x-goog-api-client'] = `${(0, util_js_2.getRuntimeTrackingString)()} gccl/${packageJson.version} gccl-gcs-cmd/${GCCL_GCS_CMD_FEATURE.UPLOAD_SHARDED}`; + } + // If the User-Agent isn't present, add it + if (!userAgentFound) { + headers['User-Agent'] = (0, util_js_2.getUserAgentString)(); + } + return headers; +}, _XMLMultiPartUploadHelper_handleErrorResponse = function _XMLMultiPartUploadHelper_handleErrorResponse(err, bail) { + if (this.bucket.storage.retryOptions.autoRetry && + this.bucket.storage.retryOptions.retryableErrorFn(err)) { + throw err; + } + else { + bail(err); + } +}; +/** + * Create a TransferManager object to perform parallel transfer operations on a Cloud Storage bucket. + * + * @class + * @hideconstructor + * + * @param {Bucket} bucket A {@link Bucket} instance + * + */ +class TransferManager { + constructor(bucket) { + this.bucket = bucket; + } + /** + * @typedef {object} UploadManyFilesOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when uploading the files. + * @property {Function} [customDestinationBuilder] A fuction that will take the current path of a local file + * and return a string representing a custom path to be used to upload the file to GCS. + * @property {boolean} [skipIfExists] Do not upload the file if it already exists in + * the bucket. This will set the precondition ifGenerationMatch = 0. + * @property {string} [prefix] A prefix to append to all of the uploaded files. + * @property {object} [passthroughOptions] {@link UploadOptions} Options to be passed through + * to each individual upload operation. + * + */ + /** + * Upload multiple files in parallel to the bucket. This is a convenience method + * that utilizes {@link Bucket#upload} to perform the upload. + * + * @param {array | string} [filePathsOrDirectory] An array of fully qualified paths to the files or a directory name. + * If a directory name is provided, the directory will be recursively walked and all files will be added to the upload list. + * to be uploaded to the bucket + * @param {UploadManyFilesOptions} [options] Configuration options. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Upload multiple files in parallel. + * //- + * const response = await transferManager.uploadManyFiles(['/local/path/file1.txt, 'local/path/file2.txt']); + * // Your bucket now contains: + * // - "local/path/file1.txt" (with the contents of '/local/path/file1.txt') + * // - "local/path/file2.txt" (with the contents of '/local/path/file2.txt') + * const response = await transferManager.uploadManyFiles('/local/directory'); + * // Your bucket will now contain all files contained in '/local/directory' maintaining the subdirectory structure. + * ``` + * + */ + async uploadManyFiles(filePathsOrDirectory, options = {}) { + var _a; + if (options.skipIfExists && ((_a = options.passthroughOptions) === null || _a === void 0 ? void 0 : _a.preconditionOpts)) { + options.passthroughOptions.preconditionOpts.ifGenerationMatch = 0; + } + else if (options.skipIfExists && + options.passthroughOptions === undefined) { + options.passthroughOptions = { + preconditionOpts: { + ifGenerationMatch: 0, + }, + }; + } + const limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_UPLOAD_LIMIT); + const promises = []; + let allPaths = []; + if (!Array.isArray(filePathsOrDirectory)) { + for await (const curPath of this.getPathsFromDirectory(filePathsOrDirectory)) { + allPaths.push(curPath); + } + } + else { + allPaths = filePathsOrDirectory; + } + for (const filePath of allPaths) { + const stat = await fs_1.promises.lstat(filePath); + if (stat.isDirectory()) { + continue; + } + const passThroughOptionsCopy = { + ...options.passthroughOptions, + [util_js_1.GCCL_GCS_CMD_KEY]: GCCL_GCS_CMD_FEATURE.UPLOAD_MANY, + }; + passThroughOptionsCopy.destination = options.customDestinationBuilder + ? options.customDestinationBuilder(filePath, options) + : filePath.split(path.sep).join(path.posix.sep); + if (options.prefix) { + passThroughOptionsCopy.destination = path.posix.join(...options.prefix.split(path.sep), passThroughOptionsCopy.destination); + } + promises.push(limit(() => this.bucket.upload(filePath, passThroughOptionsCopy))); + } + return Promise.all(promises); + } + /** + * @typedef {object} DownloadManyFilesOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when downloading the files. + * @property {string} [prefix] A prefix to append to all of the downloaded files. + * @property {string} [stripPrefix] A prefix to remove from all of the downloaded files. + * @property {object} [passthroughOptions] {@link DownloadOptions} Options to be passed through + * to each individual download operation. + * @property {boolean} [skipIfExists] Do not download the file if it already exists in + * the destination. + * + */ + /** + * Download multiple files in parallel to the local filesystem. This is a convenience method + * that utilizes {@link File#download} to perform the download. + * + * @param {array | string} [filesOrFolder] An array of file name strings or file objects to be downloaded. If + * a string is provided this will be treated as a GCS prefix and all files with that prefix will be downloaded. + * @param {DownloadManyFilesOptions} [options] Configuration options. Setting options.prefix or options.stripPrefix + * or options.passthroughOptions.destination will cause the downloaded files to be written to the file system + * instead of being returned as a buffer. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Download multiple files in parallel. + * //- + * const response = await transferManager.downloadManyFiles(['file1.txt', 'file2.txt']); + * // The following files have been downloaded: + * // - "file1.txt" (with the contents from my-bucket.file1.txt) + * // - "file2.txt" (with the contents from my-bucket.file2.txt) + * const response = await transferManager.downloadManyFiles([bucket.File('file1.txt'), bucket.File('file2.txt')]); + * // The following files have been downloaded: + * // - "file1.txt" (with the contents from my-bucket.file1.txt) + * // - "file2.txt" (with the contents from my-bucket.file2.txt) + * const response = await transferManager.downloadManyFiles('test-folder'); + * // All files with GCS prefix of 'test-folder' have been downloaded. + * ``` + * + */ + async downloadManyFiles(filesOrFolder, options = {}) { + const limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_DOWNLOAD_LIMIT); + const promises = []; + let files = []; + if (!Array.isArray(filesOrFolder)) { + const directoryFiles = await this.bucket.getFiles({ + prefix: filesOrFolder, + }); + files = directoryFiles[0]; + } + else { + files = filesOrFolder.map(curFile => { + if (typeof curFile === 'string') { + return this.bucket.file(curFile); + } + return curFile; + }); + } + const stripRegexString = options.stripPrefix + ? `^${options.stripPrefix}` + : EMPTY_REGEX; + const regex = new RegExp(stripRegexString, 'g'); + for (const file of files) { + const passThroughOptionsCopy = { + ...options.passthroughOptions, + [util_js_1.GCCL_GCS_CMD_KEY]: GCCL_GCS_CMD_FEATURE.DOWNLOAD_MANY, + }; + if (options.prefix || passThroughOptionsCopy.destination) { + passThroughOptionsCopy.destination = path.join(options.prefix || '', passThroughOptionsCopy.destination || '', file.name); + } + if (options.stripPrefix) { + passThroughOptionsCopy.destination = file.name.replace(regex, ''); + } + if (options.skipIfExists && + (0, fs_1.existsSync)(passThroughOptionsCopy.destination || '')) { + continue; + } + promises.push(limit(async () => { + const destination = passThroughOptionsCopy.destination; + if (destination && destination.endsWith(path.sep)) { + await fs_1.promises.mkdir(destination, { recursive: true }); + return Promise.resolve([ + Buffer.alloc(0), + ]); + } + return file.download(passThroughOptionsCopy); + })); + } + return Promise.all(promises); + } + /** + * @typedef {object} DownloadFileInChunksOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when downloading the file. + * @property {number} [chunkSizeBytes] The size in bytes of each chunk to be downloaded. + * @property {string | boolean} [validation] Whether or not to perform a CRC32C validation check when download is complete. + * @property {boolean} [noReturnData] Whether or not to return the downloaded data. A `true` value here would be useful for files with a size that will not fit into memory. + * + */ + /** + * Download a large file in chunks utilizing parallel download operations. This is a convenience method + * that utilizes {@link File#download} to perform the download. + * + * @param {File | string} fileOrName {@link File} to download. + * @param {DownloadFileInChunksOptions} [options] Configuration options. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Download a large file in chunks utilizing parallel operations. + * //- + * const response = await transferManager.downloadFileInChunks(bucket.file('large-file.txt'); + * // Your local directory now contains: + * // - "large-file.txt" (with the contents from my-bucket.large-file.txt) + * ``` + * + */ + async downloadFileInChunks(fileOrName, options = {}) { + let chunkSize = options.chunkSizeBytes || DOWNLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE; + let limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_CHUNKED_DOWNLOAD_LIMIT); + const noReturnData = Boolean(options.noReturnData); + const promises = []; + const file = typeof fileOrName === 'string' + ? this.bucket.file(fileOrName) + : fileOrName; + const fileInfo = await file.get(); + const size = parseInt(fileInfo[0].metadata.size.toString()); + // If the file size does not meet the threshold download it as a single chunk. + if (size < DOWNLOAD_IN_CHUNKS_FILE_SIZE_THRESHOLD) { + limit = (0, p_limit_1.default)(1); + chunkSize = size; + } + let start = 0; + const filePath = options.destination || path.basename(file.name); + const fileToWrite = await fs_1.promises.open(filePath, 'w'); + while (start < size) { + const chunkStart = start; + let chunkEnd = start + chunkSize - 1; + chunkEnd = chunkEnd > size ? size : chunkEnd; + promises.push(limit(async () => { + const resp = await file.download({ + start: chunkStart, + end: chunkEnd, + [util_js_1.GCCL_GCS_CMD_KEY]: GCCL_GCS_CMD_FEATURE.DOWNLOAD_SHARDED, + }); + const result = await fileToWrite.write(resp[0], 0, resp[0].length, chunkStart); + if (noReturnData) + return; + return result.buffer; + })); + start += chunkSize; + } + let chunks; + try { + chunks = await Promise.all(promises); + } + finally { + await fileToWrite.close(); + } + if (options.validation === 'crc32c' && fileInfo[0].metadata.crc32c) { + const downloadedCrc32C = await crc32c_js_1.CRC32C.fromFile(filePath); + if (!downloadedCrc32C.validate(fileInfo[0].metadata.crc32c)) { + const mismatchError = new file_js_1.RequestError(file_js_1.FileExceptionMessages.DOWNLOAD_MISMATCH); + mismatchError.code = 'CONTENT_DOWNLOAD_MISMATCH'; + throw mismatchError; + } + } + if (noReturnData) + return; + return [Buffer.concat(chunks, size)]; + } + /** + * @typedef {object} UploadFileInChunksOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when uploading the file. + * @property {number} [chunkSizeBytes] The size in bytes of each chunk to be uploaded. + * @property {string} [uploadName] Name of the file when saving to GCS. If ommitted the name is taken from the file path. + * @property {number} [maxQueueSize] The number of chunks to be uploaded to hold in memory concurrently. If not specified + * defaults to the specified concurrency limit. + * @property {string} [uploadId] If specified attempts to resume a previous upload. + * @property {Map} [partsMap] If specified alongside uploadId, attempts to resume a previous upload from the last chunk + * specified in partsMap + * @property {object} [headers] headers to be sent when initiating the multipart upload. + * See {@link https://cloud.google.com/storage/docs/xml-api/post-object-multipart#request_headers| Request Headers: Initiate a Multipart Upload} + * @property {boolean} [autoAbortFailure] boolean to indicate if an in progress upload session will be automatically aborted upon failure. If not set, + * failures will be automatically aborted. + * + */ + /** + * Upload a large file in chunks utilizing parallel upload opertions. If the upload fails, an uploadId and + * map containing all the successfully uploaded parts will be returned to the caller. These arguments can be used to + * resume the upload. + * + * @param {string} [filePath] The path of the file to be uploaded + * @param {UploadFileInChunksOptions} [options] Configuration options. + * @param {MultiPartHelperGenerator} [generator] A function that will return a type that implements the MPU interface. Most users will not need to use this. + * @returns {Promise} If successful a promise resolving to void, otherwise a error containing the message, uploadid, and parts map. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Upload a large file in chunks utilizing parallel operations. + * //- + * const response = await transferManager.uploadFileInChunks('large-file.txt'); + * // Your bucket now contains: + * // - "large-file.txt" + * ``` + * + * + */ + async uploadFileInChunks(filePath, options = {}, generator = defaultMultiPartGenerator) { + const chunkSize = options.chunkSizeBytes || UPLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE; + const limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_CHUNKED_UPLOAD_LIMIT); + const maxQueueSize = options.maxQueueSize || + options.concurrencyLimit || + DEFAULT_PARALLEL_CHUNKED_UPLOAD_LIMIT; + const fileName = options.uploadName || path.basename(filePath); + const mpuHelper = generator(this.bucket, fileName, options.uploadId, options.partsMap); + let partNumber = 1; + let promises = []; + try { + if (options.uploadId === undefined) { + await mpuHelper.initiateUpload(options.headers); + } + const startOrResumptionByte = mpuHelper.partsMap.size * chunkSize; + const readStream = (0, fs_1.createReadStream)(filePath, { + highWaterMark: chunkSize, + start: startOrResumptionByte, + }); + // p-limit only limits the number of running promises. We do not want to hold an entire + // large file in memory at once so promises acts a queue that will hold only maxQueueSize in memory. + for await (const curChunk of readStream) { + if (promises.length >= maxQueueSize) { + await Promise.all(promises); + promises = []; + } + promises.push(limit(() => mpuHelper.uploadPart(partNumber++, curChunk, options.validation))); + } + await Promise.all(promises); + return await mpuHelper.completeUpload(); + } + catch (e) { + if ((options.autoAbortFailure === undefined || options.autoAbortFailure) && + mpuHelper.uploadId) { + try { + await mpuHelper.abortUpload(); + return; + } + catch (e) { + throw new MultiPartUploadError(e.message, mpuHelper.uploadId, mpuHelper.partsMap); + } + } + throw new MultiPartUploadError(e.message, mpuHelper.uploadId, mpuHelper.partsMap); + } + } + async *getPathsFromDirectory(directory) { + const filesAndSubdirectories = await fs_1.promises.readdir(directory, { + withFileTypes: true, + }); + for (const curFileOrDirectory of filesAndSubdirectories) { + const fullPath = path.join(directory, curFileOrDirectory.name); + curFileOrDirectory.isDirectory() + ? yield* this.getPathsFromDirectory(fullPath) + : yield fullPath; + } + } +} +exports.TransferManager = TransferManager; + + +/***/ }), + +/***/ 74557: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = this && this.__createBinding || (Object.create ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + } + }; + } + Object.defineProperty(o, k2, desc); +} : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +}); +var __setModuleDefault = this && this.__setModuleDefault || (Object.create ? function (o, v) { + Object.defineProperty(o, "default", { + enumerable: true, + value: v + }); +} : function (o, v) { + o["default"] = v; +}); +var __importStar = this && this.__importStar || function () { + var ownKeys = function (o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +}(); +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports.PassThroughShim = void 0; +exports.normalize = normalize; +exports.objectEntries = objectEntries; +exports.fixedEncodeURIComponent = fixedEncodeURIComponent; +exports.encodeURI = encodeURI; +exports.qsStringify = qsStringify; +exports.objectKeyToLowercase = objectKeyToLowercase; +exports.unicodeJSONStringify = unicodeJSONStringify; +exports.convertObjKeysToSnakeCase = convertObjKeysToSnakeCase; +exports.formatAsUTCISO = formatAsUTCISO; +exports.getRuntimeTrackingString = getRuntimeTrackingString; +exports.getUserAgentString = getUserAgentString; +exports.getDirName = getDirName; +exports.getModuleFormat = getModuleFormat; +const path = __importStar(__nccwpck_require__(16928)); +const querystring = __importStar(__nccwpck_require__(83480)); +const stream_1 = __nccwpck_require__(2203); +const url = __importStar(__nccwpck_require__(87016)); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +// Done to avoid a problem with mangling of identifiers when using esModuleInterop +const fileURLToPath = url.fileURLToPath; +const isEsm = false; +function normalize(optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb; + return { + options, + callback + }; +} +/** + * Flatten an object into an Array of arrays, [[key, value], ..]. + * Implements Object.entries() for Node.js <8 + * @internal + */ +function objectEntries(obj) { + return Object.keys(obj).map(key => [key, obj[key]]); +} +/** + * Encode `str` with encodeURIComponent, plus these + * reserved characters: `! * ' ( )`. + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent| MDN: fixedEncodeURIComponent} + * + * @param {string} str The URI component to encode. + * @return {string} The encoded string. + */ +function fixedEncodeURIComponent(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, c => '%' + c.charCodeAt(0).toString(16).toUpperCase()); +} +/** + * URI encode `uri` for generating signed URLs, using fixedEncodeURIComponent. + * + * Encode every byte except `A-Z a-Z 0-9 ~ - . _`. + * + * @param {string} uri The URI to encode. + * @param [boolean=false] encodeSlash If `true`, the "/" character is not encoded. + * @return {string} The encoded string. + */ +function encodeURI(uri, encodeSlash) { + // Split the string by `/`, and conditionally rejoin them with either + // %2F if encodeSlash is `true`, or '/' if `false`. + return uri.split('/').map(fixedEncodeURIComponent).join(encodeSlash ? '%2F' : '/'); +} +/** + * Serialize an object to a URL query string using util.encodeURI(uri, true). + * @param {string} url The object to serialize. + * @return {string} Serialized string. + */ +function qsStringify(qs) { + return querystring.stringify(qs, '&', '=', { + encodeURIComponent: component => encodeURI(component, true) + }); +} +function objectKeyToLowercase(object) { + const newObj = {}; + for (let key of Object.keys(object)) { + const value = object[key]; + key = key.toLowerCase(); + newObj[key] = value; + } + return newObj; +} +/** + * JSON encode str, with unicode \u+ representation. + * @param {object} obj The object to encode. + * @return {string} Serialized string. + */ +function unicodeJSONStringify(obj) { + return JSON.stringify(obj).replace(/[\u0080-\uFFFF]/g, char => '\\u' + ('0000' + char.charCodeAt(0).toString(16)).slice(-4)); +} +/** + * Converts the given objects keys to snake_case + * @param {object} obj object to convert keys to snake case. + * @returns {object} object with keys converted to snake case. + */ +function convertObjKeysToSnakeCase(obj) { + if (obj instanceof Date || obj instanceof RegExp) { + return obj; + } + if (Array.isArray(obj)) { + return obj.map(convertObjKeysToSnakeCase); + } + if (obj instanceof Object) { + return Object.keys(obj).reduce((acc, cur) => { + const s = cur[0].toLocaleLowerCase() + cur.slice(1).replace(/([A-Z]+)/g, (match, p1) => { + return `_${p1.toLowerCase()}`; + }); + acc[s] = convertObjKeysToSnakeCase(obj[cur]); + return acc; + }, Object()); + } + return obj; +} +/** + * Formats the provided date object as a UTC ISO string. + * @param {Date} dateTimeToFormat date object to be formatted. + * @param {boolean} includeTime flag to include hours, minutes, seconds in output. + * @param {string} dateDelimiter delimiter between date components. + * @param {string} timeDelimiter delimiter between time components. + * @returns {string} UTC ISO format of provided date obect. + */ +function formatAsUTCISO(dateTimeToFormat, includeTime = false, dateDelimiter = '', timeDelimiter = '') { + const year = dateTimeToFormat.getUTCFullYear(); + const month = dateTimeToFormat.getUTCMonth() + 1; + const day = dateTimeToFormat.getUTCDate(); + const hour = dateTimeToFormat.getUTCHours(); + const minute = dateTimeToFormat.getUTCMinutes(); + const second = dateTimeToFormat.getUTCSeconds(); + let resultString = `${year.toString().padStart(4, '0')}${dateDelimiter}${month.toString().padStart(2, '0')}${dateDelimiter}${day.toString().padStart(2, '0')}`; + if (includeTime) { + resultString = `${resultString}T${hour.toString().padStart(2, '0')}${timeDelimiter}${minute.toString().padStart(2, '0')}${timeDelimiter}${second.toString().padStart(2, '0')}Z`; + } + return resultString; +} +/** + * Examines the runtime environment and returns the appropriate tracking string. + * @returns {string} metrics tracking string based on the current runtime environment. + */ +function getRuntimeTrackingString() { + if ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno && + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno.version && + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno.version.deno) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return `gl-deno/${globalThis.Deno.version.deno}`; + } else { + return `gl-node/${process.versions.node}`; + } +} +/** + * Looks at package.json and creates the user-agent string to be applied to request headers. + * @returns {string} user agent string. + */ +function getUserAgentString() { + const pkg = (0, package_json_helper_cjs_1.getPackageJSON)(); + const hyphenatedPackageName = pkg.name.replace('@google-cloud', 'gcloud-node') // For legacy purposes. + .replace('/', '-'); // For UA spec-compliance purposes. + return hyphenatedPackageName + '/' + pkg.version; +} +function getDirName() { + let dirToUse = ''; + try { + dirToUse = __dirname; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + dirToUse = __dirname; + } + return dirToUse; +} +function getModuleFormat() { + return isEsm ? 'ESM' : 'CJS'; +} +class PassThroughShim extends stream_1.PassThrough { + constructor() { + super(...arguments); + this.shouldEmitReading = true; + this.shouldEmitWriting = true; + } + _read(size) { + if (this.shouldEmitReading) { + this.emit('reading'); + this.shouldEmitReading = false; + } + super._read(size); + } + _write(chunk, encoding, callback) { + if (this.shouldEmitWriting) { + this.emit('writing'); + this.shouldEmitWriting = false; + } + // Per the nodejs documention, callback must be invoked on the next tick + process.nextTick(() => { + super._write(chunk, encoding, callback); + }); + } + _final(callback) { + // If the stream is empty (i.e. empty file) final will be invoked before _read / _write + // and we should still emit the proper events. + if (this.shouldEmitReading) { + this.emit('reading'); + this.shouldEmitReading = false; + } + if (this.shouldEmitWriting) { + this.emit('writing'); + this.shouldEmitWriting = false; + } + callback(null); + } +} +exports.PassThroughShim = PassThroughShim; + + +/***/ }), + +/***/ 13660: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.encode = encode; +exports.decodeEntity = decodeEntity; +exports.decode = decode; +var named_references_js_1 = __nccwpck_require__(56000); +var numeric_unicode_map_js_1 = __nccwpck_require__(53438); +var surrogate_pairs_js_1 = __nccwpck_require__(69718); +var allNamedReferences = __assign(__assign({}, named_references_js_1.namedReferences), { all: named_references_js_1.namedReferences.html5 }); +var encodeRegExps = { + specialChars: /[<>'"&]/g, + nonAscii: /[<>'"&\u0080-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, + nonAsciiPrintable: /[<>'"&\x01-\x08\x11-\x15\x17-\x1F\x7f-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, + nonAsciiPrintableOnly: /[\x01-\x08\x11-\x15\x17-\x1F\x7f-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, + extensive: /[\x01-\x0c\x0e-\x1f\x21-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7d\x7f-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g +}; +var defaultEncodeOptions = { + mode: 'specialChars', + level: 'all', + numeric: 'decimal' +}; +/** Encodes all the necessary (specified by `level`) characters in the text */ +function encode(text, _a) { + var _b = _a === void 0 ? defaultEncodeOptions : _a, _c = _b.mode, mode = _c === void 0 ? 'specialChars' : _c, _d = _b.numeric, numeric = _d === void 0 ? 'decimal' : _d, _e = _b.level, level = _e === void 0 ? 'all' : _e; + if (!text) { + return ''; + } + var encodeRegExp = encodeRegExps[mode]; + var references = allNamedReferences[level].characters; + var isHex = numeric === 'hexadecimal'; + return String.prototype.replace.call(text, encodeRegExp, function (input) { + var result = references[input]; + if (!result) { + var code = input.length > 1 ? (0, surrogate_pairs_js_1.getCodePoint)(input, 0) : input.charCodeAt(0); + result = (isHex ? '&#x' + code.toString(16) : '&#' + code) + ';'; + } + return result; + }); +} +var defaultDecodeOptions = { + scope: 'body', + level: 'all' +}; +var strict = /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);/g; +var attribute = /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+)[;=]?/g; +var baseDecodeRegExps = { + xml: { + strict: strict, + attribute: attribute, + body: named_references_js_1.bodyRegExps.xml + }, + html4: { + strict: strict, + attribute: attribute, + body: named_references_js_1.bodyRegExps.html4 + }, + html5: { + strict: strict, + attribute: attribute, + body: named_references_js_1.bodyRegExps.html5 + } +}; +var decodeRegExps = __assign(__assign({}, baseDecodeRegExps), { all: baseDecodeRegExps.html5 }); +var fromCharCode = String.fromCharCode; +var outOfBoundsChar = fromCharCode(65533); +var defaultDecodeEntityOptions = { + level: 'all' +}; +function getDecodedEntity(entity, references, isAttribute, isStrict) { + var decodeResult = entity; + var decodeEntityLastChar = entity[entity.length - 1]; + if (isAttribute && decodeEntityLastChar === '=') { + decodeResult = entity; + } + else if (isStrict && decodeEntityLastChar !== ';') { + decodeResult = entity; + } + else { + var decodeResultByReference = references[entity]; + if (decodeResultByReference) { + decodeResult = decodeResultByReference; + } + else if (entity[0] === '&' && entity[1] === '#') { + var decodeSecondChar = entity[2]; + var decodeCode = decodeSecondChar == 'x' || decodeSecondChar == 'X' + ? parseInt(entity.substr(3), 16) + : parseInt(entity.substr(2)); + decodeResult = + decodeCode >= 0x10ffff + ? outOfBoundsChar + : decodeCode > 65535 + ? (0, surrogate_pairs_js_1.fromCodePoint)(decodeCode) + : fromCharCode(numeric_unicode_map_js_1.numericUnicodeMap[decodeCode] || decodeCode); + } + } + return decodeResult; +} +/** Decodes a single entity */ +function decodeEntity(entity, _a) { + var _b = _a === void 0 ? defaultDecodeEntityOptions : _a, _c = _b.level, level = _c === void 0 ? 'all' : _c; + if (!entity) { + return ''; + } + return getDecodedEntity(entity, allNamedReferences[level].entities, false, false); +} +/** Decodes all entities in the text */ +function decode(text, _a) { + var _b = _a === void 0 ? defaultDecodeOptions : _a, _c = _b.level, level = _c === void 0 ? 'all' : _c, _d = _b.scope, scope = _d === void 0 ? level === 'xml' ? 'strict' : 'body' : _d; + if (!text) { + return ''; + } + var decodeRegExp = decodeRegExps[level][scope]; + var references = allNamedReferences[level].entities; + var isAttribute = scope === 'attribute'; + var isStrict = scope === 'strict'; + return text.replace(decodeRegExp, function (entity) { return getDecodedEntity(entity, references, isAttribute, isStrict); }); +} +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 56000: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.namedReferences = exports.bodyRegExps = void 0; +// This file is autogenerated by tools/process-named-references.ts +var pairDivider = "~"; +var blockDivider = "~~"; +function generateNamedReferences(input, prev) { + var entities = {}; + var characters = {}; + var blocks = input.split(blockDivider); + var isOptionalBlock = false; + for (var i = 0; blocks.length > i; i++) { + var entries = blocks[i].split(pairDivider); + for (var j = 0; j < entries.length; j += 2) { + var entity = entries[j]; + var character = entries[j + 1]; + var fullEntity = '&' + entity + ';'; + entities[fullEntity] = character; + if (isOptionalBlock) { + entities['&' + entity] = character; + } + characters[character] = fullEntity; + } + isOptionalBlock = true; + } + return prev ? + { entities: __assign(__assign({}, entities), prev.entities), characters: __assign(__assign({}, characters), prev.characters) } : + { entities: entities, characters: characters }; +} +exports.bodyRegExps = { + xml: /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g, + html4: /∉|&(?:nbsp|iexcl|cent|pound|curren|yen|brvbar|sect|uml|copy|ordf|laquo|not|shy|reg|macr|deg|plusmn|sup2|sup3|acute|micro|para|middot|cedil|sup1|ordm|raquo|frac14|frac12|frac34|iquest|Agrave|Aacute|Acirc|Atilde|Auml|Aring|AElig|Ccedil|Egrave|Eacute|Ecirc|Euml|Igrave|Iacute|Icirc|Iuml|ETH|Ntilde|Ograve|Oacute|Ocirc|Otilde|Ouml|times|Oslash|Ugrave|Uacute|Ucirc|Uuml|Yacute|THORN|szlig|agrave|aacute|acirc|atilde|auml|aring|aelig|ccedil|egrave|eacute|ecirc|euml|igrave|iacute|icirc|iuml|eth|ntilde|ograve|oacute|ocirc|otilde|ouml|divide|oslash|ugrave|uacute|ucirc|uuml|yacute|thorn|yuml|quot|amp|lt|gt|#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g, + html5: /·|℗|⋇|⪧|⩺|⋗|⦕|⩼|⪆|⥸|⋗|⋛|⪌|≷|≳|⪦|⩹|⋖|⋋|⋉|⥶|⩻|⦖|◃|⊴|◂|∉|⋹̸|⋵̸|∉|⋷|⋶|∌|∌|⋾|⋽|∥|⊠|⨱|⨰|&(?:AElig|AMP|Aacute|Acirc|Agrave|Aring|Atilde|Auml|COPY|Ccedil|ETH|Eacute|Ecirc|Egrave|Euml|GT|Iacute|Icirc|Igrave|Iuml|LT|Ntilde|Oacute|Ocirc|Ograve|Oslash|Otilde|Ouml|QUOT|REG|THORN|Uacute|Ucirc|Ugrave|Uuml|Yacute|aacute|acirc|acute|aelig|agrave|amp|aring|atilde|auml|brvbar|ccedil|cedil|cent|copy|curren|deg|divide|eacute|ecirc|egrave|eth|euml|frac12|frac14|frac34|gt|iacute|icirc|iexcl|igrave|iquest|iuml|laquo|lt|macr|micro|middot|nbsp|not|ntilde|oacute|ocirc|ograve|ordf|ordm|oslash|otilde|ouml|para|plusmn|pound|quot|raquo|reg|sect|shy|sup1|sup2|sup3|szlig|thorn|times|uacute|ucirc|ugrave|uml|uuml|yacute|yen|yuml|#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g +}; +exports.namedReferences = {}; +exports.namedReferences.xml = generateNamedReferences("lt~<~gt~>~quot~\"~apos~'~amp~&"); +exports.namedReferences.html4 = generateNamedReferences("apos~'~OElig~Œ~oelig~œ~Scaron~Š~scaron~š~Yuml~Ÿ~circ~ˆ~tilde~˜~ensp~ ~emsp~ ~thinsp~ ~zwnj~‌~zwj~‍~lrm~‎~rlm~‏~ndash~–~mdash~—~lsquo~‘~rsquo~’~sbquo~‚~ldquo~“~rdquo~”~bdquo~„~dagger~†~Dagger~‡~permil~‰~lsaquo~‹~rsaquo~›~euro~€~fnof~ƒ~Alpha~Α~Beta~Β~Gamma~Γ~Delta~Δ~Epsilon~Ε~Zeta~Ζ~Eta~Η~Theta~Θ~Iota~Ι~Kappa~Κ~Lambda~Λ~Mu~Μ~Nu~Ν~Xi~Ξ~Omicron~Ο~Pi~Π~Rho~Ρ~Sigma~Σ~Tau~Τ~Upsilon~Υ~Phi~Φ~Chi~Χ~Psi~Ψ~Omega~Ω~alpha~α~beta~β~gamma~γ~delta~δ~epsilon~ε~zeta~ζ~eta~η~theta~θ~iota~ι~kappa~κ~lambda~λ~mu~μ~nu~ν~xi~ξ~omicron~ο~pi~π~rho~ρ~sigmaf~ς~sigma~σ~tau~τ~upsilon~υ~phi~φ~chi~χ~psi~ψ~omega~ω~thetasym~ϑ~upsih~ϒ~piv~ϖ~bull~•~hellip~…~prime~′~Prime~″~oline~‾~frasl~⁄~weierp~℘~image~ℑ~real~ℜ~trade~™~alefsym~ℵ~larr~←~uarr~↑~rarr~→~darr~↓~harr~↔~crarr~↵~lArr~⇐~uArr~⇑~rArr~⇒~dArr~⇓~hArr~⇔~forall~∀~part~∂~exist~∃~empty~∅~nabla~∇~isin~∈~notin~∉~ni~∋~prod~∏~sum~∑~minus~−~lowast~∗~radic~√~prop~∝~infin~∞~ang~∠~and~∧~or~∨~cap~∩~cup~∪~int~∫~there4~∴~sim~∼~cong~≅~asymp~≈~ne~≠~equiv~≡~le~≤~ge~≥~sub~⊂~sup~⊃~nsub~⊄~sube~⊆~supe~⊇~oplus~⊕~otimes~⊗~perp~⊥~sdot~⋅~lceil~⌈~rceil~⌉~lfloor~⌊~rfloor~⌋~lang~〈~rang~〉~loz~◊~spades~♠~clubs~♣~hearts~♥~diams~♦~~nbsp~ ~iexcl~¡~cent~¢~pound~£~curren~¤~yen~¥~brvbar~¦~sect~§~uml~¨~copy~©~ordf~ª~laquo~«~not~¬~shy~­~reg~®~macr~¯~deg~°~plusmn~±~sup2~²~sup3~³~acute~´~micro~µ~para~¶~middot~·~cedil~¸~sup1~¹~ordm~º~raquo~»~frac14~¼~frac12~½~frac34~¾~iquest~¿~Agrave~À~Aacute~Á~Acirc~Â~Atilde~Ã~Auml~Ä~Aring~Å~AElig~Æ~Ccedil~Ç~Egrave~È~Eacute~É~Ecirc~Ê~Euml~Ë~Igrave~Ì~Iacute~Í~Icirc~Î~Iuml~Ï~ETH~Ð~Ntilde~Ñ~Ograve~Ò~Oacute~Ó~Ocirc~Ô~Otilde~Õ~Ouml~Ö~times~×~Oslash~Ø~Ugrave~Ù~Uacute~Ú~Ucirc~Û~Uuml~Ü~Yacute~Ý~THORN~Þ~szlig~ß~agrave~à~aacute~á~acirc~â~atilde~ã~auml~ä~aring~å~aelig~æ~ccedil~ç~egrave~è~eacute~é~ecirc~ê~euml~ë~igrave~ì~iacute~í~icirc~î~iuml~ï~eth~ð~ntilde~ñ~ograve~ò~oacute~ó~ocirc~ô~otilde~õ~ouml~ö~divide~÷~oslash~ø~ugrave~ù~uacute~ú~ucirc~û~uuml~ü~yacute~ý~thorn~þ~yuml~ÿ~quot~\"~amp~&~lt~<~gt~>"); +exports.namedReferences.html5 = generateNamedReferences("Abreve~Ă~Acy~А~Afr~𝔄~Amacr~Ā~And~⩓~Aogon~Ą~Aopf~𝔸~ApplyFunction~⁡~Ascr~𝒜~Assign~≔~Backslash~∖~Barv~⫧~Barwed~⌆~Bcy~Б~Because~∵~Bernoullis~ℬ~Bfr~𝔅~Bopf~𝔹~Breve~˘~Bscr~ℬ~Bumpeq~≎~CHcy~Ч~Cacute~Ć~Cap~⋒~CapitalDifferentialD~ⅅ~Cayleys~ℭ~Ccaron~Č~Ccirc~Ĉ~Cconint~∰~Cdot~Ċ~Cedilla~¸~CenterDot~·~Cfr~ℭ~CircleDot~⊙~CircleMinus~⊖~CirclePlus~⊕~CircleTimes~⊗~ClockwiseContourIntegral~∲~CloseCurlyDoubleQuote~”~CloseCurlyQuote~’~Colon~∷~Colone~⩴~Congruent~≡~Conint~∯~ContourIntegral~∮~Copf~ℂ~Coproduct~∐~CounterClockwiseContourIntegral~∳~Cross~⨯~Cscr~𝒞~Cup~⋓~CupCap~≍~DD~ⅅ~DDotrahd~⤑~DJcy~Ђ~DScy~Ѕ~DZcy~Џ~Darr~↡~Dashv~⫤~Dcaron~Ď~Dcy~Д~Del~∇~Dfr~𝔇~DiacriticalAcute~´~DiacriticalDot~˙~DiacriticalDoubleAcute~˝~DiacriticalGrave~`~DiacriticalTilde~˜~Diamond~⋄~DifferentialD~ⅆ~Dopf~𝔻~Dot~¨~DotDot~⃜~DotEqual~≐~DoubleContourIntegral~∯~DoubleDot~¨~DoubleDownArrow~⇓~DoubleLeftArrow~⇐~DoubleLeftRightArrow~⇔~DoubleLeftTee~⫤~DoubleLongLeftArrow~⟸~DoubleLongLeftRightArrow~⟺~DoubleLongRightArrow~⟹~DoubleRightArrow~⇒~DoubleRightTee~⊨~DoubleUpArrow~⇑~DoubleUpDownArrow~⇕~DoubleVerticalBar~∥~DownArrow~↓~DownArrowBar~⤓~DownArrowUpArrow~⇵~DownBreve~̑~DownLeftRightVector~⥐~DownLeftTeeVector~⥞~DownLeftVector~↽~DownLeftVectorBar~⥖~DownRightTeeVector~⥟~DownRightVector~⇁~DownRightVectorBar~⥗~DownTee~⊤~DownTeeArrow~↧~Downarrow~⇓~Dscr~𝒟~Dstrok~Đ~ENG~Ŋ~Ecaron~Ě~Ecy~Э~Edot~Ė~Efr~𝔈~Element~∈~Emacr~Ē~EmptySmallSquare~◻~EmptyVerySmallSquare~▫~Eogon~Ę~Eopf~𝔼~Equal~⩵~EqualTilde~≂~Equilibrium~⇌~Escr~ℰ~Esim~⩳~Exists~∃~ExponentialE~ⅇ~Fcy~Ф~Ffr~𝔉~FilledSmallSquare~◼~FilledVerySmallSquare~▪~Fopf~𝔽~ForAll~∀~Fouriertrf~ℱ~Fscr~ℱ~GJcy~Ѓ~Gammad~Ϝ~Gbreve~Ğ~Gcedil~Ģ~Gcirc~Ĝ~Gcy~Г~Gdot~Ġ~Gfr~𝔊~Gg~⋙~Gopf~𝔾~GreaterEqual~≥~GreaterEqualLess~⋛~GreaterFullEqual~≧~GreaterGreater~⪢~GreaterLess~≷~GreaterSlantEqual~⩾~GreaterTilde~≳~Gscr~𝒢~Gt~≫~HARDcy~Ъ~Hacek~ˇ~Hat~^~Hcirc~Ĥ~Hfr~ℌ~HilbertSpace~ℋ~Hopf~ℍ~HorizontalLine~─~Hscr~ℋ~Hstrok~Ħ~HumpDownHump~≎~HumpEqual~≏~IEcy~Е~IJlig~IJ~IOcy~Ё~Icy~И~Idot~İ~Ifr~ℑ~Im~ℑ~Imacr~Ī~ImaginaryI~ⅈ~Implies~⇒~Int~∬~Integral~∫~Intersection~⋂~InvisibleComma~⁣~InvisibleTimes~⁢~Iogon~Į~Iopf~𝕀~Iscr~ℐ~Itilde~Ĩ~Iukcy~І~Jcirc~Ĵ~Jcy~Й~Jfr~𝔍~Jopf~𝕁~Jscr~𝒥~Jsercy~Ј~Jukcy~Є~KHcy~Х~KJcy~Ќ~Kcedil~Ķ~Kcy~К~Kfr~𝔎~Kopf~𝕂~Kscr~𝒦~LJcy~Љ~Lacute~Ĺ~Lang~⟪~Laplacetrf~ℒ~Larr~↞~Lcaron~Ľ~Lcedil~Ļ~Lcy~Л~LeftAngleBracket~⟨~LeftArrow~←~LeftArrowBar~⇤~LeftArrowRightArrow~⇆~LeftCeiling~⌈~LeftDoubleBracket~⟦~LeftDownTeeVector~⥡~LeftDownVector~⇃~LeftDownVectorBar~⥙~LeftFloor~⌊~LeftRightArrow~↔~LeftRightVector~⥎~LeftTee~⊣~LeftTeeArrow~↤~LeftTeeVector~⥚~LeftTriangle~⊲~LeftTriangleBar~⧏~LeftTriangleEqual~⊴~LeftUpDownVector~⥑~LeftUpTeeVector~⥠~LeftUpVector~↿~LeftUpVectorBar~⥘~LeftVector~↼~LeftVectorBar~⥒~Leftarrow~⇐~Leftrightarrow~⇔~LessEqualGreater~⋚~LessFullEqual~≦~LessGreater~≶~LessLess~⪡~LessSlantEqual~⩽~LessTilde~≲~Lfr~𝔏~Ll~⋘~Lleftarrow~⇚~Lmidot~Ŀ~LongLeftArrow~⟵~LongLeftRightArrow~⟷~LongRightArrow~⟶~Longleftarrow~⟸~Longleftrightarrow~⟺~Longrightarrow~⟹~Lopf~𝕃~LowerLeftArrow~↙~LowerRightArrow~↘~Lscr~ℒ~Lsh~↰~Lstrok~Ł~Lt~≪~Map~⤅~Mcy~М~MediumSpace~ ~Mellintrf~ℳ~Mfr~𝔐~MinusPlus~∓~Mopf~𝕄~Mscr~ℳ~NJcy~Њ~Nacute~Ń~Ncaron~Ň~Ncedil~Ņ~Ncy~Н~NegativeMediumSpace~​~NegativeThickSpace~​~NegativeThinSpace~​~NegativeVeryThinSpace~​~NestedGreaterGreater~≫~NestedLessLess~≪~NewLine~\n~Nfr~𝔑~NoBreak~⁠~NonBreakingSpace~ ~Nopf~ℕ~Not~⫬~NotCongruent~≢~NotCupCap~≭~NotDoubleVerticalBar~∦~NotElement~∉~NotEqual~≠~NotEqualTilde~≂̸~NotExists~∄~NotGreater~≯~NotGreaterEqual~≱~NotGreaterFullEqual~≧̸~NotGreaterGreater~≫̸~NotGreaterLess~≹~NotGreaterSlantEqual~⩾̸~NotGreaterTilde~≵~NotHumpDownHump~≎̸~NotHumpEqual~≏̸~NotLeftTriangle~⋪~NotLeftTriangleBar~⧏̸~NotLeftTriangleEqual~⋬~NotLess~≮~NotLessEqual~≰~NotLessGreater~≸~NotLessLess~≪̸~NotLessSlantEqual~⩽̸~NotLessTilde~≴~NotNestedGreaterGreater~⪢̸~NotNestedLessLess~⪡̸~NotPrecedes~⊀~NotPrecedesEqual~⪯̸~NotPrecedesSlantEqual~⋠~NotReverseElement~∌~NotRightTriangle~⋫~NotRightTriangleBar~⧐̸~NotRightTriangleEqual~⋭~NotSquareSubset~⊏̸~NotSquareSubsetEqual~⋢~NotSquareSuperset~⊐̸~NotSquareSupersetEqual~⋣~NotSubset~⊂⃒~NotSubsetEqual~⊈~NotSucceeds~⊁~NotSucceedsEqual~⪰̸~NotSucceedsSlantEqual~⋡~NotSucceedsTilde~≿̸~NotSuperset~⊃⃒~NotSupersetEqual~⊉~NotTilde~≁~NotTildeEqual~≄~NotTildeFullEqual~≇~NotTildeTilde~≉~NotVerticalBar~∤~Nscr~𝒩~Ocy~О~Odblac~Ő~Ofr~𝔒~Omacr~Ō~Oopf~𝕆~OpenCurlyDoubleQuote~“~OpenCurlyQuote~‘~Or~⩔~Oscr~𝒪~Otimes~⨷~OverBar~‾~OverBrace~⏞~OverBracket~⎴~OverParenthesis~⏜~PartialD~∂~Pcy~П~Pfr~𝔓~PlusMinus~±~Poincareplane~ℌ~Popf~ℙ~Pr~⪻~Precedes~≺~PrecedesEqual~⪯~PrecedesSlantEqual~≼~PrecedesTilde~≾~Product~∏~Proportion~∷~Proportional~∝~Pscr~𝒫~Qfr~𝔔~Qopf~ℚ~Qscr~𝒬~RBarr~⤐~Racute~Ŕ~Rang~⟫~Rarr~↠~Rarrtl~⤖~Rcaron~Ř~Rcedil~Ŗ~Rcy~Р~Re~ℜ~ReverseElement~∋~ReverseEquilibrium~⇋~ReverseUpEquilibrium~⥯~Rfr~ℜ~RightAngleBracket~⟩~RightArrow~→~RightArrowBar~⇥~RightArrowLeftArrow~⇄~RightCeiling~⌉~RightDoubleBracket~⟧~RightDownTeeVector~⥝~RightDownVector~⇂~RightDownVectorBar~⥕~RightFloor~⌋~RightTee~⊢~RightTeeArrow~↦~RightTeeVector~⥛~RightTriangle~⊳~RightTriangleBar~⧐~RightTriangleEqual~⊵~RightUpDownVector~⥏~RightUpTeeVector~⥜~RightUpVector~↾~RightUpVectorBar~⥔~RightVector~⇀~RightVectorBar~⥓~Rightarrow~⇒~Ropf~ℝ~RoundImplies~⥰~Rrightarrow~⇛~Rscr~ℛ~Rsh~↱~RuleDelayed~⧴~SHCHcy~Щ~SHcy~Ш~SOFTcy~Ь~Sacute~Ś~Sc~⪼~Scedil~Ş~Scirc~Ŝ~Scy~С~Sfr~𝔖~ShortDownArrow~↓~ShortLeftArrow~←~ShortRightArrow~→~ShortUpArrow~↑~SmallCircle~∘~Sopf~𝕊~Sqrt~√~Square~□~SquareIntersection~⊓~SquareSubset~⊏~SquareSubsetEqual~⊑~SquareSuperset~⊐~SquareSupersetEqual~⊒~SquareUnion~⊔~Sscr~𝒮~Star~⋆~Sub~⋐~Subset~⋐~SubsetEqual~⊆~Succeeds~≻~SucceedsEqual~⪰~SucceedsSlantEqual~≽~SucceedsTilde~≿~SuchThat~∋~Sum~∑~Sup~⋑~Superset~⊃~SupersetEqual~⊇~Supset~⋑~TRADE~™~TSHcy~Ћ~TScy~Ц~Tab~\t~Tcaron~Ť~Tcedil~Ţ~Tcy~Т~Tfr~𝔗~Therefore~∴~ThickSpace~  ~ThinSpace~ ~Tilde~∼~TildeEqual~≃~TildeFullEqual~≅~TildeTilde~≈~Topf~𝕋~TripleDot~⃛~Tscr~𝒯~Tstrok~Ŧ~Uarr~↟~Uarrocir~⥉~Ubrcy~Ў~Ubreve~Ŭ~Ucy~У~Udblac~Ű~Ufr~𝔘~Umacr~Ū~UnderBar~_~UnderBrace~⏟~UnderBracket~⎵~UnderParenthesis~⏝~Union~⋃~UnionPlus~⊎~Uogon~Ų~Uopf~𝕌~UpArrow~↑~UpArrowBar~⤒~UpArrowDownArrow~⇅~UpDownArrow~↕~UpEquilibrium~⥮~UpTee~⊥~UpTeeArrow~↥~Uparrow~⇑~Updownarrow~⇕~UpperLeftArrow~↖~UpperRightArrow~↗~Upsi~ϒ~Uring~Ů~Uscr~𝒰~Utilde~Ũ~VDash~⊫~Vbar~⫫~Vcy~В~Vdash~⊩~Vdashl~⫦~Vee~⋁~Verbar~‖~Vert~‖~VerticalBar~∣~VerticalLine~|~VerticalSeparator~❘~VerticalTilde~≀~VeryThinSpace~ ~Vfr~𝔙~Vopf~𝕍~Vscr~𝒱~Vvdash~⊪~Wcirc~Ŵ~Wedge~⋀~Wfr~𝔚~Wopf~𝕎~Wscr~𝒲~Xfr~𝔛~Xopf~𝕏~Xscr~𝒳~YAcy~Я~YIcy~Ї~YUcy~Ю~Ycirc~Ŷ~Ycy~Ы~Yfr~𝔜~Yopf~𝕐~Yscr~𝒴~ZHcy~Ж~Zacute~Ź~Zcaron~Ž~Zcy~З~Zdot~Ż~ZeroWidthSpace~​~Zfr~ℨ~Zopf~ℤ~Zscr~𝒵~abreve~ă~ac~∾~acE~∾̳~acd~∿~acy~а~af~⁡~afr~𝔞~aleph~ℵ~amacr~ā~amalg~⨿~andand~⩕~andd~⩜~andslope~⩘~andv~⩚~ange~⦤~angle~∠~angmsd~∡~angmsdaa~⦨~angmsdab~⦩~angmsdac~⦪~angmsdad~⦫~angmsdae~⦬~angmsdaf~⦭~angmsdag~⦮~angmsdah~⦯~angrt~∟~angrtvb~⊾~angrtvbd~⦝~angsph~∢~angst~Å~angzarr~⍼~aogon~ą~aopf~𝕒~ap~≈~apE~⩰~apacir~⩯~ape~≊~apid~≋~approx~≈~approxeq~≊~ascr~𝒶~ast~*~asympeq~≍~awconint~∳~awint~⨑~bNot~⫭~backcong~≌~backepsilon~϶~backprime~‵~backsim~∽~backsimeq~⋍~barvee~⊽~barwed~⌅~barwedge~⌅~bbrk~⎵~bbrktbrk~⎶~bcong~≌~bcy~б~becaus~∵~because~∵~bemptyv~⦰~bepsi~϶~bernou~ℬ~beth~ℶ~between~≬~bfr~𝔟~bigcap~⋂~bigcirc~◯~bigcup~⋃~bigodot~⨀~bigoplus~⨁~bigotimes~⨂~bigsqcup~⨆~bigstar~★~bigtriangledown~▽~bigtriangleup~△~biguplus~⨄~bigvee~⋁~bigwedge~⋀~bkarow~⤍~blacklozenge~⧫~blacksquare~▪~blacktriangle~▴~blacktriangledown~▾~blacktriangleleft~◂~blacktriangleright~▸~blank~␣~blk12~▒~blk14~░~blk34~▓~block~█~bne~=⃥~bnequiv~≡⃥~bnot~⌐~bopf~𝕓~bot~⊥~bottom~⊥~bowtie~⋈~boxDL~╗~boxDR~╔~boxDl~╖~boxDr~╓~boxH~═~boxHD~╦~boxHU~╩~boxHd~╤~boxHu~╧~boxUL~╝~boxUR~╚~boxUl~╜~boxUr~╙~boxV~║~boxVH~╬~boxVL~╣~boxVR~╠~boxVh~╫~boxVl~╢~boxVr~╟~boxbox~⧉~boxdL~╕~boxdR~╒~boxdl~┐~boxdr~┌~boxh~─~boxhD~╥~boxhU~╨~boxhd~┬~boxhu~┴~boxminus~⊟~boxplus~⊞~boxtimes~⊠~boxuL~╛~boxuR~╘~boxul~┘~boxur~└~boxv~│~boxvH~╪~boxvL~╡~boxvR~╞~boxvh~┼~boxvl~┤~boxvr~├~bprime~‵~breve~˘~bscr~𝒷~bsemi~⁏~bsim~∽~bsime~⋍~bsol~\\~bsolb~⧅~bsolhsub~⟈~bullet~•~bump~≎~bumpE~⪮~bumpe~≏~bumpeq~≏~cacute~ć~capand~⩄~capbrcup~⩉~capcap~⩋~capcup~⩇~capdot~⩀~caps~∩︀~caret~⁁~caron~ˇ~ccaps~⩍~ccaron~č~ccirc~ĉ~ccups~⩌~ccupssm~⩐~cdot~ċ~cemptyv~⦲~centerdot~·~cfr~𝔠~chcy~ч~check~✓~checkmark~✓~cir~○~cirE~⧃~circeq~≗~circlearrowleft~↺~circlearrowright~↻~circledR~®~circledS~Ⓢ~circledast~⊛~circledcirc~⊚~circleddash~⊝~cire~≗~cirfnint~⨐~cirmid~⫯~cirscir~⧂~clubsuit~♣~colon~:~colone~≔~coloneq~≔~comma~,~commat~@~comp~∁~compfn~∘~complement~∁~complexes~ℂ~congdot~⩭~conint~∮~copf~𝕔~coprod~∐~copysr~℗~cross~✗~cscr~𝒸~csub~⫏~csube~⫑~csup~⫐~csupe~⫒~ctdot~⋯~cudarrl~⤸~cudarrr~⤵~cuepr~⋞~cuesc~⋟~cularr~↶~cularrp~⤽~cupbrcap~⩈~cupcap~⩆~cupcup~⩊~cupdot~⊍~cupor~⩅~cups~∪︀~curarr~↷~curarrm~⤼~curlyeqprec~⋞~curlyeqsucc~⋟~curlyvee~⋎~curlywedge~⋏~curvearrowleft~↶~curvearrowright~↷~cuvee~⋎~cuwed~⋏~cwconint~∲~cwint~∱~cylcty~⌭~dHar~⥥~daleth~ℸ~dash~‐~dashv~⊣~dbkarow~⤏~dblac~˝~dcaron~ď~dcy~д~dd~ⅆ~ddagger~‡~ddarr~⇊~ddotseq~⩷~demptyv~⦱~dfisht~⥿~dfr~𝔡~dharl~⇃~dharr~⇂~diam~⋄~diamond~⋄~diamondsuit~♦~die~¨~digamma~ϝ~disin~⋲~div~÷~divideontimes~⋇~divonx~⋇~djcy~ђ~dlcorn~⌞~dlcrop~⌍~dollar~$~dopf~𝕕~dot~˙~doteq~≐~doteqdot~≑~dotminus~∸~dotplus~∔~dotsquare~⊡~doublebarwedge~⌆~downarrow~↓~downdownarrows~⇊~downharpoonleft~⇃~downharpoonright~⇂~drbkarow~⤐~drcorn~⌟~drcrop~⌌~dscr~𝒹~dscy~ѕ~dsol~⧶~dstrok~đ~dtdot~⋱~dtri~▿~dtrif~▾~duarr~⇵~duhar~⥯~dwangle~⦦~dzcy~џ~dzigrarr~⟿~eDDot~⩷~eDot~≑~easter~⩮~ecaron~ě~ecir~≖~ecolon~≕~ecy~э~edot~ė~ee~ⅇ~efDot~≒~efr~𝔢~eg~⪚~egs~⪖~egsdot~⪘~el~⪙~elinters~⏧~ell~ℓ~els~⪕~elsdot~⪗~emacr~ē~emptyset~∅~emptyv~∅~emsp13~ ~emsp14~ ~eng~ŋ~eogon~ę~eopf~𝕖~epar~⋕~eparsl~⧣~eplus~⩱~epsi~ε~epsiv~ϵ~eqcirc~≖~eqcolon~≕~eqsim~≂~eqslantgtr~⪖~eqslantless~⪕~equals~=~equest~≟~equivDD~⩸~eqvparsl~⧥~erDot~≓~erarr~⥱~escr~ℯ~esdot~≐~esim~≂~excl~!~expectation~ℰ~exponentiale~ⅇ~fallingdotseq~≒~fcy~ф~female~♀~ffilig~ffi~fflig~ff~ffllig~ffl~ffr~𝔣~filig~fi~fjlig~fj~flat~♭~fllig~fl~fltns~▱~fopf~𝕗~fork~⋔~forkv~⫙~fpartint~⨍~frac13~⅓~frac15~⅕~frac16~⅙~frac18~⅛~frac23~⅔~frac25~⅖~frac35~⅗~frac38~⅜~frac45~⅘~frac56~⅚~frac58~⅝~frac78~⅞~frown~⌢~fscr~𝒻~gE~≧~gEl~⪌~gacute~ǵ~gammad~ϝ~gap~⪆~gbreve~ğ~gcirc~ĝ~gcy~г~gdot~ġ~gel~⋛~geq~≥~geqq~≧~geqslant~⩾~ges~⩾~gescc~⪩~gesdot~⪀~gesdoto~⪂~gesdotol~⪄~gesl~⋛︀~gesles~⪔~gfr~𝔤~gg~≫~ggg~⋙~gimel~ℷ~gjcy~ѓ~gl~≷~glE~⪒~gla~⪥~glj~⪤~gnE~≩~gnap~⪊~gnapprox~⪊~gne~⪈~gneq~⪈~gneqq~≩~gnsim~⋧~gopf~𝕘~grave~`~gscr~ℊ~gsim~≳~gsime~⪎~gsiml~⪐~gtcc~⪧~gtcir~⩺~gtdot~⋗~gtlPar~⦕~gtquest~⩼~gtrapprox~⪆~gtrarr~⥸~gtrdot~⋗~gtreqless~⋛~gtreqqless~⪌~gtrless~≷~gtrsim~≳~gvertneqq~≩︀~gvnE~≩︀~hairsp~ ~half~½~hamilt~ℋ~hardcy~ъ~harrcir~⥈~harrw~↭~hbar~ℏ~hcirc~ĥ~heartsuit~♥~hercon~⊹~hfr~𝔥~hksearow~⤥~hkswarow~⤦~hoarr~⇿~homtht~∻~hookleftarrow~↩~hookrightarrow~↪~hopf~𝕙~horbar~―~hscr~𝒽~hslash~ℏ~hstrok~ħ~hybull~⁃~hyphen~‐~ic~⁣~icy~и~iecy~е~iff~⇔~ifr~𝔦~ii~ⅈ~iiiint~⨌~iiint~∭~iinfin~⧜~iiota~℩~ijlig~ij~imacr~ī~imagline~ℐ~imagpart~ℑ~imath~ı~imof~⊷~imped~Ƶ~in~∈~incare~℅~infintie~⧝~inodot~ı~intcal~⊺~integers~ℤ~intercal~⊺~intlarhk~⨗~intprod~⨼~iocy~ё~iogon~į~iopf~𝕚~iprod~⨼~iscr~𝒾~isinE~⋹~isindot~⋵~isins~⋴~isinsv~⋳~isinv~∈~it~⁢~itilde~ĩ~iukcy~і~jcirc~ĵ~jcy~й~jfr~𝔧~jmath~ȷ~jopf~𝕛~jscr~𝒿~jsercy~ј~jukcy~є~kappav~ϰ~kcedil~ķ~kcy~к~kfr~𝔨~kgreen~ĸ~khcy~х~kjcy~ќ~kopf~𝕜~kscr~𝓀~lAarr~⇚~lAtail~⤛~lBarr~⤎~lE~≦~lEg~⪋~lHar~⥢~lacute~ĺ~laemptyv~⦴~lagran~ℒ~langd~⦑~langle~⟨~lap~⪅~larrb~⇤~larrbfs~⤟~larrfs~⤝~larrhk~↩~larrlp~↫~larrpl~⤹~larrsim~⥳~larrtl~↢~lat~⪫~latail~⤙~late~⪭~lates~⪭︀~lbarr~⤌~lbbrk~❲~lbrace~{~lbrack~[~lbrke~⦋~lbrksld~⦏~lbrkslu~⦍~lcaron~ľ~lcedil~ļ~lcub~{~lcy~л~ldca~⤶~ldquor~„~ldrdhar~⥧~ldrushar~⥋~ldsh~↲~leftarrow~←~leftarrowtail~↢~leftharpoondown~↽~leftharpoonup~↼~leftleftarrows~⇇~leftrightarrow~↔~leftrightarrows~⇆~leftrightharpoons~⇋~leftrightsquigarrow~↭~leftthreetimes~⋋~leg~⋚~leq~≤~leqq~≦~leqslant~⩽~les~⩽~lescc~⪨~lesdot~⩿~lesdoto~⪁~lesdotor~⪃~lesg~⋚︀~lesges~⪓~lessapprox~⪅~lessdot~⋖~lesseqgtr~⋚~lesseqqgtr~⪋~lessgtr~≶~lesssim~≲~lfisht~⥼~lfr~𝔩~lg~≶~lgE~⪑~lhard~↽~lharu~↼~lharul~⥪~lhblk~▄~ljcy~љ~ll~≪~llarr~⇇~llcorner~⌞~llhard~⥫~lltri~◺~lmidot~ŀ~lmoust~⎰~lmoustache~⎰~lnE~≨~lnap~⪉~lnapprox~⪉~lne~⪇~lneq~⪇~lneqq~≨~lnsim~⋦~loang~⟬~loarr~⇽~lobrk~⟦~longleftarrow~⟵~longleftrightarrow~⟷~longmapsto~⟼~longrightarrow~⟶~looparrowleft~↫~looparrowright~↬~lopar~⦅~lopf~𝕝~loplus~⨭~lotimes~⨴~lowbar~_~lozenge~◊~lozf~⧫~lpar~(~lparlt~⦓~lrarr~⇆~lrcorner~⌟~lrhar~⇋~lrhard~⥭~lrtri~⊿~lscr~𝓁~lsh~↰~lsim~≲~lsime~⪍~lsimg~⪏~lsqb~[~lsquor~‚~lstrok~ł~ltcc~⪦~ltcir~⩹~ltdot~⋖~lthree~⋋~ltimes~⋉~ltlarr~⥶~ltquest~⩻~ltrPar~⦖~ltri~◃~ltrie~⊴~ltrif~◂~lurdshar~⥊~luruhar~⥦~lvertneqq~≨︀~lvnE~≨︀~mDDot~∺~male~♂~malt~✠~maltese~✠~map~↦~mapsto~↦~mapstodown~↧~mapstoleft~↤~mapstoup~↥~marker~▮~mcomma~⨩~mcy~м~measuredangle~∡~mfr~𝔪~mho~℧~mid~∣~midast~*~midcir~⫰~minusb~⊟~minusd~∸~minusdu~⨪~mlcp~⫛~mldr~…~mnplus~∓~models~⊧~mopf~𝕞~mp~∓~mscr~𝓂~mstpos~∾~multimap~⊸~mumap~⊸~nGg~⋙̸~nGt~≫⃒~nGtv~≫̸~nLeftarrow~⇍~nLeftrightarrow~⇎~nLl~⋘̸~nLt~≪⃒~nLtv~≪̸~nRightarrow~⇏~nVDash~⊯~nVdash~⊮~nacute~ń~nang~∠⃒~nap~≉~napE~⩰̸~napid~≋̸~napos~ʼn~napprox~≉~natur~♮~natural~♮~naturals~ℕ~nbump~≎̸~nbumpe~≏̸~ncap~⩃~ncaron~ň~ncedil~ņ~ncong~≇~ncongdot~⩭̸~ncup~⩂~ncy~н~neArr~⇗~nearhk~⤤~nearr~↗~nearrow~↗~nedot~≐̸~nequiv~≢~nesear~⤨~nesim~≂̸~nexist~∄~nexists~∄~nfr~𝔫~ngE~≧̸~nge~≱~ngeq~≱~ngeqq~≧̸~ngeqslant~⩾̸~nges~⩾̸~ngsim~≵~ngt~≯~ngtr~≯~nhArr~⇎~nharr~↮~nhpar~⫲~nis~⋼~nisd~⋺~niv~∋~njcy~њ~nlArr~⇍~nlE~≦̸~nlarr~↚~nldr~‥~nle~≰~nleftarrow~↚~nleftrightarrow~↮~nleq~≰~nleqq~≦̸~nleqslant~⩽̸~nles~⩽̸~nless~≮~nlsim~≴~nlt~≮~nltri~⋪~nltrie~⋬~nmid~∤~nopf~𝕟~notinE~⋹̸~notindot~⋵̸~notinva~∉~notinvb~⋷~notinvc~⋶~notni~∌~notniva~∌~notnivb~⋾~notnivc~⋽~npar~∦~nparallel~∦~nparsl~⫽⃥~npart~∂̸~npolint~⨔~npr~⊀~nprcue~⋠~npre~⪯̸~nprec~⊀~npreceq~⪯̸~nrArr~⇏~nrarr~↛~nrarrc~⤳̸~nrarrw~↝̸~nrightarrow~↛~nrtri~⋫~nrtrie~⋭~nsc~⊁~nsccue~⋡~nsce~⪰̸~nscr~𝓃~nshortmid~∤~nshortparallel~∦~nsim~≁~nsime~≄~nsimeq~≄~nsmid~∤~nspar~∦~nsqsube~⋢~nsqsupe~⋣~nsubE~⫅̸~nsube~⊈~nsubset~⊂⃒~nsubseteq~⊈~nsubseteqq~⫅̸~nsucc~⊁~nsucceq~⪰̸~nsup~⊅~nsupE~⫆̸~nsupe~⊉~nsupset~⊃⃒~nsupseteq~⊉~nsupseteqq~⫆̸~ntgl~≹~ntlg~≸~ntriangleleft~⋪~ntrianglelefteq~⋬~ntriangleright~⋫~ntrianglerighteq~⋭~num~#~numero~№~numsp~ ~nvDash~⊭~nvHarr~⤄~nvap~≍⃒~nvdash~⊬~nvge~≥⃒~nvgt~>⃒~nvinfin~⧞~nvlArr~⤂~nvle~≤⃒~nvlt~<⃒~nvltrie~⊴⃒~nvrArr~⤃~nvrtrie~⊵⃒~nvsim~∼⃒~nwArr~⇖~nwarhk~⤣~nwarr~↖~nwarrow~↖~nwnear~⤧~oS~Ⓢ~oast~⊛~ocir~⊚~ocy~о~odash~⊝~odblac~ő~odiv~⨸~odot~⊙~odsold~⦼~ofcir~⦿~ofr~𝔬~ogon~˛~ogt~⧁~ohbar~⦵~ohm~Ω~oint~∮~olarr~↺~olcir~⦾~olcross~⦻~olt~⧀~omacr~ō~omid~⦶~ominus~⊖~oopf~𝕠~opar~⦷~operp~⦹~orarr~↻~ord~⩝~order~ℴ~orderof~ℴ~origof~⊶~oror~⩖~orslope~⩗~orv~⩛~oscr~ℴ~osol~⊘~otimesas~⨶~ovbar~⌽~par~∥~parallel~∥~parsim~⫳~parsl~⫽~pcy~п~percnt~%~period~.~pertenk~‱~pfr~𝔭~phiv~ϕ~phmmat~ℳ~phone~☎~pitchfork~⋔~planck~ℏ~planckh~ℎ~plankv~ℏ~plus~+~plusacir~⨣~plusb~⊞~pluscir~⨢~plusdo~∔~plusdu~⨥~pluse~⩲~plussim~⨦~plustwo~⨧~pm~±~pointint~⨕~popf~𝕡~pr~≺~prE~⪳~prap~⪷~prcue~≼~pre~⪯~prec~≺~precapprox~⪷~preccurlyeq~≼~preceq~⪯~precnapprox~⪹~precneqq~⪵~precnsim~⋨~precsim~≾~primes~ℙ~prnE~⪵~prnap~⪹~prnsim~⋨~profalar~⌮~profline~⌒~profsurf~⌓~propto~∝~prsim~≾~prurel~⊰~pscr~𝓅~puncsp~ ~qfr~𝔮~qint~⨌~qopf~𝕢~qprime~⁗~qscr~𝓆~quaternions~ℍ~quatint~⨖~quest~?~questeq~≟~rAarr~⇛~rAtail~⤜~rBarr~⤏~rHar~⥤~race~∽̱~racute~ŕ~raemptyv~⦳~rangd~⦒~range~⦥~rangle~⟩~rarrap~⥵~rarrb~⇥~rarrbfs~⤠~rarrc~⤳~rarrfs~⤞~rarrhk~↪~rarrlp~↬~rarrpl~⥅~rarrsim~⥴~rarrtl~↣~rarrw~↝~ratail~⤚~ratio~∶~rationals~ℚ~rbarr~⤍~rbbrk~❳~rbrace~}~rbrack~]~rbrke~⦌~rbrksld~⦎~rbrkslu~⦐~rcaron~ř~rcedil~ŗ~rcub~}~rcy~р~rdca~⤷~rdldhar~⥩~rdquor~”~rdsh~↳~realine~ℛ~realpart~ℜ~reals~ℝ~rect~▭~rfisht~⥽~rfr~𝔯~rhard~⇁~rharu~⇀~rharul~⥬~rhov~ϱ~rightarrow~→~rightarrowtail~↣~rightharpoondown~⇁~rightharpoonup~⇀~rightleftarrows~⇄~rightleftharpoons~⇌~rightrightarrows~⇉~rightsquigarrow~↝~rightthreetimes~⋌~ring~˚~risingdotseq~≓~rlarr~⇄~rlhar~⇌~rmoust~⎱~rmoustache~⎱~rnmid~⫮~roang~⟭~roarr~⇾~robrk~⟧~ropar~⦆~ropf~𝕣~roplus~⨮~rotimes~⨵~rpar~)~rpargt~⦔~rppolint~⨒~rrarr~⇉~rscr~𝓇~rsh~↱~rsqb~]~rsquor~’~rthree~⋌~rtimes~⋊~rtri~▹~rtrie~⊵~rtrif~▸~rtriltri~⧎~ruluhar~⥨~rx~℞~sacute~ś~sc~≻~scE~⪴~scap~⪸~sccue~≽~sce~⪰~scedil~ş~scirc~ŝ~scnE~⪶~scnap~⪺~scnsim~⋩~scpolint~⨓~scsim~≿~scy~с~sdotb~⊡~sdote~⩦~seArr~⇘~searhk~⤥~searr~↘~searrow~↘~semi~;~seswar~⤩~setminus~∖~setmn~∖~sext~✶~sfr~𝔰~sfrown~⌢~sharp~♯~shchcy~щ~shcy~ш~shortmid~∣~shortparallel~∥~sigmav~ς~simdot~⩪~sime~≃~simeq~≃~simg~⪞~simgE~⪠~siml~⪝~simlE~⪟~simne~≆~simplus~⨤~simrarr~⥲~slarr~←~smallsetminus~∖~smashp~⨳~smeparsl~⧤~smid~∣~smile~⌣~smt~⪪~smte~⪬~smtes~⪬︀~softcy~ь~sol~/~solb~⧄~solbar~⌿~sopf~𝕤~spadesuit~♠~spar~∥~sqcap~⊓~sqcaps~⊓︀~sqcup~⊔~sqcups~⊔︀~sqsub~⊏~sqsube~⊑~sqsubset~⊏~sqsubseteq~⊑~sqsup~⊐~sqsupe~⊒~sqsupset~⊐~sqsupseteq~⊒~squ~□~square~□~squarf~▪~squf~▪~srarr~→~sscr~𝓈~ssetmn~∖~ssmile~⌣~sstarf~⋆~star~☆~starf~★~straightepsilon~ϵ~straightphi~ϕ~strns~¯~subE~⫅~subdot~⪽~subedot~⫃~submult~⫁~subnE~⫋~subne~⊊~subplus~⪿~subrarr~⥹~subset~⊂~subseteq~⊆~subseteqq~⫅~subsetneq~⊊~subsetneqq~⫋~subsim~⫇~subsub~⫕~subsup~⫓~succ~≻~succapprox~⪸~succcurlyeq~≽~succeq~⪰~succnapprox~⪺~succneqq~⪶~succnsim~⋩~succsim~≿~sung~♪~supE~⫆~supdot~⪾~supdsub~⫘~supedot~⫄~suphsol~⟉~suphsub~⫗~suplarr~⥻~supmult~⫂~supnE~⫌~supne~⊋~supplus~⫀~supset~⊃~supseteq~⊇~supseteqq~⫆~supsetneq~⊋~supsetneqq~⫌~supsim~⫈~supsub~⫔~supsup~⫖~swArr~⇙~swarhk~⤦~swarr~↙~swarrow~↙~swnwar~⤪~target~⌖~tbrk~⎴~tcaron~ť~tcedil~ţ~tcy~т~tdot~⃛~telrec~⌕~tfr~𝔱~therefore~∴~thetav~ϑ~thickapprox~≈~thicksim~∼~thkap~≈~thksim~∼~timesb~⊠~timesbar~⨱~timesd~⨰~tint~∭~toea~⤨~top~⊤~topbot~⌶~topcir~⫱~topf~𝕥~topfork~⫚~tosa~⤩~tprime~‴~triangle~▵~triangledown~▿~triangleleft~◃~trianglelefteq~⊴~triangleq~≜~triangleright~▹~trianglerighteq~⊵~tridot~◬~trie~≜~triminus~⨺~triplus~⨹~trisb~⧍~tritime~⨻~trpezium~⏢~tscr~𝓉~tscy~ц~tshcy~ћ~tstrok~ŧ~twixt~≬~twoheadleftarrow~↞~twoheadrightarrow~↠~uHar~⥣~ubrcy~ў~ubreve~ŭ~ucy~у~udarr~⇅~udblac~ű~udhar~⥮~ufisht~⥾~ufr~𝔲~uharl~↿~uharr~↾~uhblk~▀~ulcorn~⌜~ulcorner~⌜~ulcrop~⌏~ultri~◸~umacr~ū~uogon~ų~uopf~𝕦~uparrow~↑~updownarrow~↕~upharpoonleft~↿~upharpoonright~↾~uplus~⊎~upsi~υ~upuparrows~⇈~urcorn~⌝~urcorner~⌝~urcrop~⌎~uring~ů~urtri~◹~uscr~𝓊~utdot~⋰~utilde~ũ~utri~▵~utrif~▴~uuarr~⇈~uwangle~⦧~vArr~⇕~vBar~⫨~vBarv~⫩~vDash~⊨~vangrt~⦜~varepsilon~ϵ~varkappa~ϰ~varnothing~∅~varphi~ϕ~varpi~ϖ~varpropto~∝~varr~↕~varrho~ϱ~varsigma~ς~varsubsetneq~⊊︀~varsubsetneqq~⫋︀~varsupsetneq~⊋︀~varsupsetneqq~⫌︀~vartheta~ϑ~vartriangleleft~⊲~vartriangleright~⊳~vcy~в~vdash~⊢~vee~∨~veebar~⊻~veeeq~≚~vellip~⋮~verbar~|~vert~|~vfr~𝔳~vltri~⊲~vnsub~⊂⃒~vnsup~⊃⃒~vopf~𝕧~vprop~∝~vrtri~⊳~vscr~𝓋~vsubnE~⫋︀~vsubne~⊊︀~vsupnE~⫌︀~vsupne~⊋︀~vzigzag~⦚~wcirc~ŵ~wedbar~⩟~wedge~∧~wedgeq~≙~wfr~𝔴~wopf~𝕨~wp~℘~wr~≀~wreath~≀~wscr~𝓌~xcap~⋂~xcirc~◯~xcup~⋃~xdtri~▽~xfr~𝔵~xhArr~⟺~xharr~⟷~xlArr~⟸~xlarr~⟵~xmap~⟼~xnis~⋻~xodot~⨀~xopf~𝕩~xoplus~⨁~xotime~⨂~xrArr~⟹~xrarr~⟶~xscr~𝓍~xsqcup~⨆~xuplus~⨄~xutri~△~xvee~⋁~xwedge~⋀~yacy~я~ycirc~ŷ~ycy~ы~yfr~𝔶~yicy~ї~yopf~𝕪~yscr~𝓎~yucy~ю~zacute~ź~zcaron~ž~zcy~з~zdot~ż~zeetrf~ℨ~zfr~𝔷~zhcy~ж~zigrarr~⇝~zopf~𝕫~zscr~𝓏~~AMP~&~COPY~©~GT~>~LT~<~QUOT~\"~REG~®", exports.namedReferences['html4']); +//# sourceMappingURL=named-references.js.map + +/***/ }), + +/***/ 53438: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.numericUnicodeMap = void 0; +exports.numericUnicodeMap = { + 0: 65533, + 128: 8364, + 130: 8218, + 131: 402, + 132: 8222, + 133: 8230, + 134: 8224, + 135: 8225, + 136: 710, + 137: 8240, + 138: 352, + 139: 8249, + 140: 338, + 142: 381, + 145: 8216, + 146: 8217, + 147: 8220, + 148: 8221, + 149: 8226, + 150: 8211, + 151: 8212, + 152: 732, + 153: 8482, + 154: 353, + 155: 8250, + 156: 339, + 158: 382, + 159: 376 +}; +//# sourceMappingURL=numeric-unicode-map.js.map + +/***/ }), + +/***/ 69718: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.highSurrogateTo = exports.highSurrogateFrom = exports.getCodePoint = exports.fromCodePoint = void 0; +exports.fromCodePoint = String.fromCodePoint || + function (astralCodePoint) { + return String.fromCharCode(Math.floor((astralCodePoint - 0x10000) / 0x400) + 0xd800, ((astralCodePoint - 0x10000) % 0x400) + 0xdc00); + }; +// @ts-expect-error - String.prototype.codePointAt might not exist in older node versions +exports.getCodePoint = String.prototype.codePointAt + ? function (input, position) { + return input.codePointAt(position); + } + : function (input, position) { + return (input.charCodeAt(position) - 0xd800) * 0x400 + input.charCodeAt(position + 1) - 0xdc00 + 0x10000; + }; +exports.highSurrogateFrom = 0xd800; +exports.highSurrogateTo = 0xdbff; +//# sourceMappingURL=surrogate-pairs.js.map + +/***/ }), + +/***/ 41969: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* eslint-disable node/no-missing-require */ + +function getPackageJSON() { + return __nccwpck_require__(72721); +} + +exports.getPackageJSON = getPackageJSON; + + +/***/ }), + +/***/ 50591: +/***/ ((module) => { + +(()=>{"use strict";var t={d:(e,n)=>{for(var i in n)t.o(n,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{XMLBuilder:()=>ft,XMLParser:()=>st,XMLValidator:()=>mt});const n=":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",i=new RegExp("^["+n+"]["+n+"\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$");function s(t,e){const n=[];let i=e.exec(t);for(;i;){const s=[];s.startIndex=e.lastIndex-i[0].length;const r=i.length;for(let t=0;t"!==t[o]&&" "!==t[o]&&"\t"!==t[o]&&"\n"!==t[o]&&"\r"!==t[o];o++)f+=t[o];if(f=f.trim(),"/"===f[f.length-1]&&(f=f.substring(0,f.length-1),o--),!r(f)){let e;return e=0===f.trim().length?"Invalid space after '<'.":"Tag '"+f+"' is an invalid name.",x("InvalidTag",e,N(t,o))}const p=c(t,o);if(!1===p)return x("InvalidAttr","Attributes for '"+f+"' have open quote.",N(t,o));let b=p.value;if(o=p.index,"/"===b[b.length-1]){const n=o-b.length;b=b.substring(0,b.length-1);const s=g(b,e);if(!0!==s)return x(s.err.code,s.err.msg,N(t,n+s.err.line));i=!0}else if(d){if(!p.tagClosed)return x("InvalidTag","Closing tag '"+f+"' doesn't have proper closing.",N(t,o));if(b.trim().length>0)return x("InvalidTag","Closing tag '"+f+"' can't have attributes or invalid starting.",N(t,a));if(0===n.length)return x("InvalidTag","Closing tag '"+f+"' has not been opened.",N(t,a));{const e=n.pop();if(f!==e.tagName){let n=N(t,e.tagStartPos);return x("InvalidTag","Expected closing tag '"+e.tagName+"' (opened in line "+n.line+", col "+n.col+") instead of closing tag '"+f+"'.",N(t,a))}0==n.length&&(s=!0)}}else{const r=g(b,e);if(!0!==r)return x(r.err.code,r.err.msg,N(t,o-b.length+r.err.line));if(!0===s)return x("InvalidXml","Multiple possible root nodes found.",N(t,o));-1!==e.unpairedTags.indexOf(f)||n.push({tagName:f,tagStartPos:a}),i=!0}for(o++;o0)||x("InvalidXml","Invalid '"+JSON.stringify(n.map((t=>t.tagName)),null,4).replace(/\r?\n/g,"")+"' found.",{line:1,col:1}):x("InvalidXml","Start tag expected.",1)}function l(t){return" "===t||"\t"===t||"\n"===t||"\r"===t}function u(t,e){const n=e;for(;e5&&"xml"===i)return x("InvalidXml","XML declaration allowed only at the start of the document.",N(t,e));if("?"==t[e]&&">"==t[e+1]){e++;break}}return e}function h(t,e){if(t.length>e+5&&"-"===t[e+1]&&"-"===t[e+2]){for(e+=3;e"===t[e+2]){e+=2;break}}else if(t.length>e+8&&"D"===t[e+1]&&"O"===t[e+2]&&"C"===t[e+3]&&"T"===t[e+4]&&"Y"===t[e+5]&&"P"===t[e+6]&&"E"===t[e+7]){let n=1;for(e+=8;e"===t[e]&&(n--,0===n))break}else if(t.length>e+9&&"["===t[e+1]&&"C"===t[e+2]&&"D"===t[e+3]&&"A"===t[e+4]&&"T"===t[e+5]&&"A"===t[e+6]&&"["===t[e+7])for(e+=8;e"===t[e+2]){e+=2;break}return e}const d='"',f="'";function c(t,e){let n="",i="",s=!1;for(;e"===t[e]&&""===i){s=!0;break}n+=t[e]}return""===i&&{value:n,index:e,tagClosed:s}}const p=new RegExp("(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['\"])(([\\s\\S])*?)\\5)?","g");function g(t,e){const n=s(t,p),i={};for(let t=0;t!1,commentPropName:!1,unpairedTags:[],processEntities:!0,htmlEntities:!1,ignoreDeclaration:!1,ignorePiTags:!1,transformTagName:!1,transformAttributeName:!1,updateTag:function(t,e,n){return t},captureMetaData:!1};let y;y="function"!=typeof Symbol?"@@xmlMetadata":Symbol("XML Node Metadata");class T{constructor(t){this.tagname=t,this.child=[],this[":@"]={}}add(t,e){"__proto__"===t&&(t="#__proto__"),this.child.push({[t]:e})}addChild(t,e){"__proto__"===t.tagname&&(t.tagname="#__proto__"),t[":@"]&&Object.keys(t[":@"]).length>0?this.child.push({[t.tagname]:t.child,":@":t[":@"]}):this.child.push({[t.tagname]:t.child}),void 0!==e&&(this.child[this.child.length-1][y]={startIndex:e})}static getMetaDataSymbol(){return y}}function w(t,e){const n={};if("O"!==t[e+3]||"C"!==t[e+4]||"T"!==t[e+5]||"Y"!==t[e+6]||"P"!==t[e+7]||"E"!==t[e+8])throw new Error("Invalid Tag instead of DOCTYPE");{e+=9;let i=1,s=!1,r=!1,o="";for(;e"===t[e]){if(r?"-"===t[e-1]&&"-"===t[e-2]&&(r=!1,i--):i--,0===i)break}else"["===t[e]?s=!0:o+=t[e];else{if(s&&C(t,"!ENTITY",e)){let i,s;e+=7,[i,s,e]=O(t,e+1),-1===s.indexOf("&")&&(n[i]={regx:RegExp(`&${i};`,"g"),val:s})}else if(s&&C(t,"!ELEMENT",e)){e+=8;const{index:n}=S(t,e+1);e=n}else if(s&&C(t,"!ATTLIST",e))e+=8;else if(s&&C(t,"!NOTATION",e)){e+=9;const{index:n}=A(t,e+1);e=n}else{if(!C(t,"!--",e))throw new Error("Invalid DOCTYPE");r=!0}i++,o=""}if(0!==i)throw new Error("Unclosed DOCTYPE")}return{entities:n,i:e}}const P=(t,e)=>{for(;e{for(const n of t){if("string"==typeof n&&e===n)return!0;if(n instanceof RegExp&&n.test(e))return!0}}:()=>!1}class k{constructor(t){this.options=t,this.currentNode=null,this.tagsNodeStack=[],this.docTypeEntities={},this.lastEntities={apos:{regex:/&(apos|#39|#x27);/g,val:"'"},gt:{regex:/&(gt|#62|#x3E);/g,val:">"},lt:{regex:/&(lt|#60|#x3C);/g,val:"<"},quot:{regex:/&(quot|#34|#x22);/g,val:'"'}},this.ampEntity={regex:/&(amp|#38|#x26);/g,val:"&"},this.htmlEntities={space:{regex:/&(nbsp|#160);/g,val:" "},cent:{regex:/&(cent|#162);/g,val:"¢"},pound:{regex:/&(pound|#163);/g,val:"£"},yen:{regex:/&(yen|#165);/g,val:"¥"},euro:{regex:/&(euro|#8364);/g,val:"€"},copyright:{regex:/&(copy|#169);/g,val:"©"},reg:{regex:/&(reg|#174);/g,val:"®"},inr:{regex:/&(inr|#8377);/g,val:"₹"},num_dec:{regex:/&#([0-9]{1,7});/g,val:(t,e)=>String.fromCodePoint(Number.parseInt(e,10))},num_hex:{regex:/&#x([0-9a-fA-F]{1,6});/g,val:(t,e)=>String.fromCodePoint(Number.parseInt(e,16))}},this.addExternalEntities=F,this.parseXml=X,this.parseTextData=L,this.resolveNameSpace=B,this.buildAttributesMap=G,this.isItStopNode=Z,this.replaceEntitiesValue=R,this.readStopNodeData=J,this.saveTextToParentTag=q,this.addChild=Y,this.ignoreAttributesFn=_(this.options.ignoreAttributes)}}function F(t){const e=Object.keys(t);for(let n=0;n0)){o||(t=this.replaceEntitiesValue(t));const i=this.options.tagValueProcessor(e,t,n,s,r);return null==i?t:typeof i!=typeof t||i!==t?i:this.options.trimValues||t.trim()===t?H(t,this.options.parseTagValue,this.options.numberParseOptions):t}}function B(t){if(this.options.removeNSPrefix){const e=t.split(":"),n="/"===t.charAt(0)?"/":"";if("xmlns"===e[0])return"";2===e.length&&(t=n+e[1])}return t}const U=new RegExp("([^\\s=]+)\\s*(=\\s*(['\"])([\\s\\S]*?)\\3)?","gm");function G(t,e,n){if(!0!==this.options.ignoreAttributes&&"string"==typeof t){const n=s(t,U),i=n.length,r={};for(let t=0;t",r,"Closing Tag is not closed.");let o=t.substring(r+2,e).trim();if(this.options.removeNSPrefix){const t=o.indexOf(":");-1!==t&&(o=o.substr(t+1))}this.options.transformTagName&&(o=this.options.transformTagName(o)),n&&(i=this.saveTextToParentTag(i,n,s));const a=s.substring(s.lastIndexOf(".")+1);if(o&&-1!==this.options.unpairedTags.indexOf(o))throw new Error(`Unpaired tag can not be used as closing tag: `);let l=0;a&&-1!==this.options.unpairedTags.indexOf(a)?(l=s.lastIndexOf(".",s.lastIndexOf(".")-1),this.tagsNodeStack.pop()):l=s.lastIndexOf("."),s=s.substring(0,l),n=this.tagsNodeStack.pop(),i="",r=e}else if("?"===t[r+1]){let e=z(t,r,!1,"?>");if(!e)throw new Error("Pi Tag is not closed.");if(i=this.saveTextToParentTag(i,n,s),this.options.ignoreDeclaration&&"?xml"===e.tagName||this.options.ignorePiTags);else{const t=new T(e.tagName);t.add(this.options.textNodeName,""),e.tagName!==e.tagExp&&e.attrExpPresent&&(t[":@"]=this.buildAttributesMap(e.tagExp,s,e.tagName)),this.addChild(n,t,s,r)}r=e.closeIndex+1}else if("!--"===t.substr(r+1,3)){const e=W(t,"--\x3e",r+4,"Comment is not closed.");if(this.options.commentPropName){const o=t.substring(r+4,e-2);i=this.saveTextToParentTag(i,n,s),n.add(this.options.commentPropName,[{[this.options.textNodeName]:o}])}r=e}else if("!D"===t.substr(r+1,2)){const e=w(t,r);this.docTypeEntities=e.entities,r=e.i}else if("!["===t.substr(r+1,2)){const e=W(t,"]]>",r,"CDATA is not closed.")-2,o=t.substring(r+9,e);i=this.saveTextToParentTag(i,n,s);let a=this.parseTextData(o,n.tagname,s,!0,!1,!0,!0);null==a&&(a=""),this.options.cdataPropName?n.add(this.options.cdataPropName,[{[this.options.textNodeName]:o}]):n.add(this.options.textNodeName,a),r=e+2}else{let o=z(t,r,this.options.removeNSPrefix),a=o.tagName;const l=o.rawTagName;let u=o.tagExp,h=o.attrExpPresent,d=o.closeIndex;this.options.transformTagName&&(a=this.options.transformTagName(a)),n&&i&&"!xml"!==n.tagname&&(i=this.saveTextToParentTag(i,n,s,!1));const f=n;f&&-1!==this.options.unpairedTags.indexOf(f.tagname)&&(n=this.tagsNodeStack.pop(),s=s.substring(0,s.lastIndexOf("."))),a!==e.tagname&&(s+=s?"."+a:a);const c=r;if(this.isItStopNode(this.options.stopNodes,s,a)){let e="";if(u.length>0&&u.lastIndexOf("/")===u.length-1)"/"===a[a.length-1]?(a=a.substr(0,a.length-1),s=s.substr(0,s.length-1),u=a):u=u.substr(0,u.length-1),r=o.closeIndex;else if(-1!==this.options.unpairedTags.indexOf(a))r=o.closeIndex;else{const n=this.readStopNodeData(t,l,d+1);if(!n)throw new Error(`Unexpected end of ${l}`);r=n.i,e=n.tagContent}const i=new T(a);a!==u&&h&&(i[":@"]=this.buildAttributesMap(u,s,a)),e&&(e=this.parseTextData(e,a,s,!0,h,!0,!0)),s=s.substr(0,s.lastIndexOf(".")),i.add(this.options.textNodeName,e),this.addChild(n,i,s,c)}else{if(u.length>0&&u.lastIndexOf("/")===u.length-1){"/"===a[a.length-1]?(a=a.substr(0,a.length-1),s=s.substr(0,s.length-1),u=a):u=u.substr(0,u.length-1),this.options.transformTagName&&(a=this.options.transformTagName(a));const t=new T(a);a!==u&&h&&(t[":@"]=this.buildAttributesMap(u,s,a)),this.addChild(n,t,s,c),s=s.substr(0,s.lastIndexOf("."))}else{const t=new T(a);this.tagsNodeStack.push(n),a!==u&&h&&(t[":@"]=this.buildAttributesMap(u,s,a)),this.addChild(n,t,s,c),n=t}i="",r=d}}else i+=t[r];return e.child};function Y(t,e,n,i){this.options.captureMetaData||(i=void 0);const s=this.options.updateTag(e.tagname,n,e[":@"]);!1===s||("string"==typeof s?(e.tagname=s,t.addChild(e,i)):t.addChild(e,i))}const R=function(t){if(this.options.processEntities){for(let e in this.docTypeEntities){const n=this.docTypeEntities[e];t=t.replace(n.regx,n.val)}for(let e in this.lastEntities){const n=this.lastEntities[e];t=t.replace(n.regex,n.val)}if(this.options.htmlEntities)for(let e in this.htmlEntities){const n=this.htmlEntities[e];t=t.replace(n.regex,n.val)}t=t.replace(this.ampEntity.regex,this.ampEntity.val)}return t};function q(t,e,n,i){return t&&(void 0===i&&(i=0===e.child.length),void 0!==(t=this.parseTextData(t,e.tagname,n,!1,!!e[":@"]&&0!==Object.keys(e[":@"]).length,i))&&""!==t&&e.add(this.options.textNodeName,t),t=""),t}function Z(t,e,n){const i="*."+n;for(const n in t){const s=t[n];if(i===s||e===s)return!0}return!1}function W(t,e,n,i){const s=t.indexOf(e,n);if(-1===s)throw new Error(i);return s+e.length-1}function z(t,e,n,i=">"){const s=function(t,e,n=">"){let i,s="";for(let r=e;r",n,`${e} is not closed`);if(t.substring(n+2,r).trim()===e&&(s--,0===s))return{tagContent:t.substring(i,n),i:r};n=r}else if("?"===t[n+1])n=W(t,"?>",n+1,"StopNode is not closed.");else if("!--"===t.substr(n+1,3))n=W(t,"--\x3e",n+3,"StopNode is not closed.");else if("!["===t.substr(n+1,2))n=W(t,"]]>",n,"StopNode is not closed.")-2;else{const i=z(t,n,">");i&&((i&&i.tagName)===e&&"/"!==i.tagExp[i.tagExp.length-1]&&s++,n=i.closeIndex)}}function H(t,e,n){if(e&&"string"==typeof t){const e=t.trim();return"true"===e||"false"!==e&&function(t,e={}){if(e=Object.assign({},V,e),!t||"string"!=typeof t)return t;let n=t.trim();if(void 0!==e.skipLike&&e.skipLike.test(n))return t;if("0"===t)return 0;if(e.hex&&j.test(n))return function(t){if(parseInt)return parseInt(t,16);if(Number.parseInt)return Number.parseInt(t,16);if(window&&window.parseInt)return window.parseInt(t,16);throw new Error("parseInt, Number.parseInt, window.parseInt are not supported")}(n);if(-1!==n.search(/.+[eE].+/))return function(t,e,n){if(!n.eNotation)return t;const i=e.match(M);if(i){let s=i[1]||"";const r=-1===i[3].indexOf("e")?"E":"e",o=i[2],a=s?t[o.length+1]===r:t[o.length]===r;return o.length>1&&a?t:1!==o.length||!i[3].startsWith(`.${r}`)&&i[3][0]!==r?n.leadingZeros&&!a?(e=(i[1]||"")+i[3],Number(e)):t:Number(e)}return t}(t,n,e);{const s=D.exec(n);if(s){const r=s[1]||"",o=s[2];let a=(i=s[3])&&-1!==i.indexOf(".")?("."===(i=i.replace(/0+$/,""))?i="0":"."===i[0]?i="0"+i:"."===i[i.length-1]&&(i=i.substring(0,i.length-1)),i):i;const l=r?"."===t[o.length+1]:"."===t[o.length];if(!e.leadingZeros&&(o.length>1||1===o.length&&!l))return t;{const i=Number(n),s=String(i);if(0===i||-0===i)return i;if(-1!==s.search(/[eE]/))return e.eNotation?i:t;if(-1!==n.indexOf("."))return"0"===s||s===a||s===`${r}${a}`?i:t;let l=o?a:n;return o?l===s||r+l===s?i:t:l===s||l===r+s?i:t}}return t}var i}(t,n)}return void 0!==t?t:""}const K=T.getMetaDataSymbol();function Q(t,e){return tt(t,e)}function tt(t,e,n){let i;const s={};for(let r=0;r0&&(s[e.textNodeName]=i):void 0!==i&&(s[e.textNodeName]=i),s}function et(t){const e=Object.keys(t);for(let t=0;t0&&(n="\n"),ot(t,e,"",n)}function ot(t,e,n,i){let s="",r=!1;for(let o=0;o`,r=!1;continue}if(l===e.commentPropName){s+=i+`\x3c!--${a[l][0][e.textNodeName]}--\x3e`,r=!0;continue}if("?"===l[0]){const t=lt(a[":@"],e),n="?xml"===l?"":i;let o=a[l][0][e.textNodeName];o=0!==o.length?" "+o:"",s+=n+`<${l}${o}${t}?>`,r=!0;continue}let h=i;""!==h&&(h+=e.indentBy);const d=i+`<${l}${lt(a[":@"],e)}`,f=ot(a[l],e,u,h);-1!==e.unpairedTags.indexOf(l)?e.suppressUnpairedNode?s+=d+">":s+=d+"/>":f&&0!==f.length||!e.suppressEmptyNode?f&&f.endsWith(">")?s+=d+`>${f}${i}`:(s+=d+">",f&&""!==i&&(f.includes("/>")||f.includes("`):s+=d+"/>",r=!0}return s}function at(t){const e=Object.keys(t);for(let n=0;n0&&e.processEntities)for(let n=0;n","g"),val:">"},{regex:new RegExp("<","g"),val:"<"},{regex:new RegExp("'","g"),val:"'"},{regex:new RegExp('"',"g"),val:"""}],processEntities:!0,stopNodes:[],oneListGroup:!1};function ft(t){this.options=Object.assign({},dt,t),!0===this.options.ignoreAttributes||this.options.attributesGroupName?this.isAttribute=function(){return!1}:(this.ignoreAttributesFn=_(this.options.ignoreAttributes),this.attrPrefixLen=this.options.attributeNamePrefix.length,this.isAttribute=gt),this.processTextOrObjNode=ct,this.options.format?(this.indentate=pt,this.tagEndChar=">\n",this.newLine="\n"):(this.indentate=function(){return""},this.tagEndChar=">",this.newLine="")}function ct(t,e,n,i){const s=this.j2x(t,n+1,i.concat(e));return void 0!==t[this.options.textNodeName]&&1===Object.keys(t).length?this.buildTextValNode(t[this.options.textNodeName],e,s.attrStr,n):this.buildObjectNode(s.val,e,s.attrStr,n)}function pt(t){return this.options.indentBy.repeat(t)}function gt(t){return!(!t.startsWith(this.options.attributeNamePrefix)||t===this.options.textNodeName)&&t.substr(this.attrPrefixLen)}ft.prototype.build=function(t){return this.options.preserveOrder?rt(t,this.options):(Array.isArray(t)&&this.options.arrayNodeName&&this.options.arrayNodeName.length>1&&(t={[this.options.arrayNodeName]:t}),this.j2x(t,0,[]).val)},ft.prototype.j2x=function(t,e,n){let i="",s="";const r=n.join(".");for(let o in t)if(Object.prototype.hasOwnProperty.call(t,o))if(void 0===t[o])this.isAttribute(o)&&(s+="");else if(null===t[o])this.isAttribute(o)||o===this.options.cdataPropName?s+="":"?"===o[0]?s+=this.indentate(e)+"<"+o+"?"+this.tagEndChar:s+=this.indentate(e)+"<"+o+"/"+this.tagEndChar;else if(t[o]instanceof Date)s+=this.buildTextValNode(t[o],o,"",e);else if("object"!=typeof t[o]){const n=this.isAttribute(o);if(n&&!this.ignoreAttributesFn(n,r))i+=this.buildAttrPairStr(n,""+t[o]);else if(!n)if(o===this.options.textNodeName){let e=this.options.tagValueProcessor(o,""+t[o]);s+=this.replaceEntitiesValue(e)}else s+=this.buildTextValNode(t[o],o,"",e)}else if(Array.isArray(t[o])){const i=t[o].length;let r="",a="";for(let l=0;l"+t+s}},ft.prototype.closeTag=function(t){let e="";return-1!==this.options.unpairedTags.indexOf(t)?this.options.suppressUnpairedNode||(e="/"):e=this.options.suppressEmptyNode?"/":`>`+this.newLine;if(!1!==this.options.commentPropName&&e===this.options.commentPropName)return this.indentate(i)+`\x3c!--${t}--\x3e`+this.newLine;if("?"===e[0])return this.indentate(i)+"<"+e+n+"?"+this.tagEndChar;{let s=this.options.tagValueProcessor(e,t);return s=this.replaceEntitiesValue(s),""===s?this.indentate(i)+"<"+e+n+this.closeTag(e)+this.tagEndChar:this.indentate(i)+"<"+e+n+">"+s+"0&&this.options.processEntities)for(let e=0;e { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/client-s3","description":"AWS SDK for JavaScript S3 Client for Node.js, Browser and React Native","version":"3.859.0","scripts":{"build":"concurrently \'yarn:build:cjs\' \'yarn:build:es\' \'yarn:build:types\'","build:cjs":"node ../../scripts/compilation/inline client-s3","build:es":"tsc -p tsconfig.es.json","build:include:deps":"lerna run --scope $npm_package_name --include-dependencies build","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"rimraf ./dist-* && rimraf *.tsbuildinfo","extract:docs":"api-extractor run --local","generate:client":"node ../../scripts/generate-clients/single-service --solo s3","test":"yarn g:vitest run","test:browser":"node ./test/browser-build/esbuild && yarn g:vitest run -c vitest.config.browser.ts","test:browser:watch":"node ./test/browser-build/esbuild && yarn g:vitest watch -c vitest.config.browser.ts","test:e2e":"yarn g:vitest run -c vitest.config.e2e.ts && yarn test:browser","test:e2e:watch":"yarn g:vitest watch -c vitest.config.e2e.ts","test:integration":"yarn g:vitest run -c vitest.config.integ.ts","test:integration:watch":"yarn g:vitest watch -c vitest.config.integ.ts","test:watch":"yarn g:vitest watch"},"main":"./dist-cjs/index.js","types":"./dist-types/index.d.ts","module":"./dist-es/index.js","sideEffects":false,"dependencies":{"@aws-crypto/sha1-browser":"5.2.0","@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"3.858.0","@aws-sdk/credential-provider-node":"3.859.0","@aws-sdk/middleware-bucket-endpoint":"3.840.0","@aws-sdk/middleware-expect-continue":"3.840.0","@aws-sdk/middleware-flexible-checksums":"3.858.0","@aws-sdk/middleware-host-header":"3.840.0","@aws-sdk/middleware-location-constraint":"3.840.0","@aws-sdk/middleware-logger":"3.840.0","@aws-sdk/middleware-recursion-detection":"3.840.0","@aws-sdk/middleware-sdk-s3":"3.858.0","@aws-sdk/middleware-ssec":"3.840.0","@aws-sdk/middleware-user-agent":"3.858.0","@aws-sdk/region-config-resolver":"3.840.0","@aws-sdk/signature-v4-multi-region":"3.858.0","@aws-sdk/types":"3.840.0","@aws-sdk/util-endpoints":"3.848.0","@aws-sdk/util-user-agent-browser":"3.840.0","@aws-sdk/util-user-agent-node":"3.858.0","@aws-sdk/xml-builder":"3.821.0","@smithy/config-resolver":"^4.1.4","@smithy/core":"^3.7.2","@smithy/eventstream-serde-browser":"^4.0.4","@smithy/eventstream-serde-config-resolver":"^4.1.2","@smithy/eventstream-serde-node":"^4.0.4","@smithy/fetch-http-handler":"^5.1.0","@smithy/hash-blob-browser":"^4.0.4","@smithy/hash-node":"^4.0.4","@smithy/hash-stream-node":"^4.0.4","@smithy/invalid-dependency":"^4.0.4","@smithy/md5-js":"^4.0.4","@smithy/middleware-content-length":"^4.0.4","@smithy/middleware-endpoint":"^4.1.17","@smithy/middleware-retry":"^4.1.18","@smithy/middleware-serde":"^4.0.8","@smithy/middleware-stack":"^4.0.4","@smithy/node-config-provider":"^4.1.3","@smithy/node-http-handler":"^4.1.0","@smithy/protocol-http":"^5.1.2","@smithy/smithy-client":"^4.4.9","@smithy/types":"^4.3.1","@smithy/url-parser":"^4.0.4","@smithy/util-base64":"^4.0.0","@smithy/util-body-length-browser":"^4.0.0","@smithy/util-body-length-node":"^4.0.0","@smithy/util-defaults-mode-browser":"^4.0.25","@smithy/util-defaults-mode-node":"^4.0.25","@smithy/util-endpoints":"^3.0.6","@smithy/util-middleware":"^4.0.4","@smithy/util-retry":"^4.0.6","@smithy/util-stream":"^4.2.3","@smithy/util-utf8":"^4.0.0","@smithy/util-waiter":"^4.0.6","@types/uuid":"^9.0.1","tslib":"^2.6.2","uuid":"^9.0.1"},"devDependencies":{"@aws-sdk/signature-v4-crt":"3.858.0","@tsconfig/node18":"18.2.4","@types/node":"^18.19.69","concurrently":"7.0.0","downlevel-dts":"0.10.1","rimraf":"3.0.2","typescript":"~5.8.3"},"engines":{"node":">=18.0.0"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["dist-*/**"],"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","browser":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.browser"},"react-native":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.native"},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-s3"}}'); + +/***/ }), + +/***/ 45188: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/client-sso","description":"AWS SDK for JavaScript Sso Client for Node.js, Browser and React Native","version":"3.858.0","scripts":{"build":"concurrently \'yarn:build:cjs\' \'yarn:build:es\' \'yarn:build:types\'","build:cjs":"node ../../scripts/compilation/inline client-sso","build:es":"tsc -p tsconfig.es.json","build:include:deps":"lerna run --scope $npm_package_name --include-dependencies build","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"rimraf ./dist-* && rimraf *.tsbuildinfo","extract:docs":"api-extractor run --local","generate:client":"node ../../scripts/generate-clients/single-service --solo sso"},"main":"./dist-cjs/index.js","types":"./dist-types/index.d.ts","module":"./dist-es/index.js","sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"3.858.0","@aws-sdk/middleware-host-header":"3.840.0","@aws-sdk/middleware-logger":"3.840.0","@aws-sdk/middleware-recursion-detection":"3.840.0","@aws-sdk/middleware-user-agent":"3.858.0","@aws-sdk/region-config-resolver":"3.840.0","@aws-sdk/types":"3.840.0","@aws-sdk/util-endpoints":"3.848.0","@aws-sdk/util-user-agent-browser":"3.840.0","@aws-sdk/util-user-agent-node":"3.858.0","@smithy/config-resolver":"^4.1.4","@smithy/core":"^3.7.2","@smithy/fetch-http-handler":"^5.1.0","@smithy/hash-node":"^4.0.4","@smithy/invalid-dependency":"^4.0.4","@smithy/middleware-content-length":"^4.0.4","@smithy/middleware-endpoint":"^4.1.17","@smithy/middleware-retry":"^4.1.18","@smithy/middleware-serde":"^4.0.8","@smithy/middleware-stack":"^4.0.4","@smithy/node-config-provider":"^4.1.3","@smithy/node-http-handler":"^4.1.0","@smithy/protocol-http":"^5.1.2","@smithy/smithy-client":"^4.4.9","@smithy/types":"^4.3.1","@smithy/url-parser":"^4.0.4","@smithy/util-base64":"^4.0.0","@smithy/util-body-length-browser":"^4.0.0","@smithy/util-body-length-node":"^4.0.0","@smithy/util-defaults-mode-browser":"^4.0.25","@smithy/util-defaults-mode-node":"^4.0.25","@smithy/util-endpoints":"^3.0.6","@smithy/util-middleware":"^4.0.4","@smithy/util-retry":"^4.0.6","@smithy/util-utf8":"^4.0.0","tslib":"^2.6.2"},"devDependencies":{"@tsconfig/node18":"18.2.4","@types/node":"^18.19.69","concurrently":"7.0.0","downlevel-dts":"0.10.1","rimraf":"3.0.2","typescript":"~5.8.3"},"engines":{"node":">=18.0.0"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["dist-*/**"],"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","browser":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.browser"},"react-native":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.native"},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-sso","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-sso"}}'); + +/***/ }), + +/***/ 39955: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/nested-clients","version":"3.858.0","description":"Nested clients for AWS SDK packages.","main":"./dist-cjs/index.js","module":"./dist-es/index.js","types":"./dist-types/index.d.ts","scripts":{"build":"yarn lint && concurrently \'yarn:build:cjs\' \'yarn:build:es\' \'yarn:build:types\'","build:cjs":"node ../../scripts/compilation/inline nested-clients","build:es":"tsc -p tsconfig.es.json","build:include:deps":"lerna run --scope $npm_package_name --include-dependencies build","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"rimraf ./dist-* && rimraf *.tsbuildinfo","lint":"node ../../scripts/validation/submodules-linter.js --pkg nested-clients","test":"yarn g:vitest run","test:watch":"yarn g:vitest watch"},"engines":{"node":">=18.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","dependencies":{"@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"3.858.0","@aws-sdk/middleware-host-header":"3.840.0","@aws-sdk/middleware-logger":"3.840.0","@aws-sdk/middleware-recursion-detection":"3.840.0","@aws-sdk/middleware-user-agent":"3.858.0","@aws-sdk/region-config-resolver":"3.840.0","@aws-sdk/types":"3.840.0","@aws-sdk/util-endpoints":"3.848.0","@aws-sdk/util-user-agent-browser":"3.840.0","@aws-sdk/util-user-agent-node":"3.858.0","@smithy/config-resolver":"^4.1.4","@smithy/core":"^3.7.2","@smithy/fetch-http-handler":"^5.1.0","@smithy/hash-node":"^4.0.4","@smithy/invalid-dependency":"^4.0.4","@smithy/middleware-content-length":"^4.0.4","@smithy/middleware-endpoint":"^4.1.17","@smithy/middleware-retry":"^4.1.18","@smithy/middleware-serde":"^4.0.8","@smithy/middleware-stack":"^4.0.4","@smithy/node-config-provider":"^4.1.3","@smithy/node-http-handler":"^4.1.0","@smithy/protocol-http":"^5.1.2","@smithy/smithy-client":"^4.4.9","@smithy/types":"^4.3.1","@smithy/url-parser":"^4.0.4","@smithy/util-base64":"^4.0.0","@smithy/util-body-length-browser":"^4.0.0","@smithy/util-body-length-node":"^4.0.0","@smithy/util-defaults-mode-browser":"^4.0.25","@smithy/util-defaults-mode-node":"^4.0.25","@smithy/util-endpoints":"^3.0.6","@smithy/util-middleware":"^4.0.4","@smithy/util-retry":"^4.0.6","@smithy/util-utf8":"^4.0.0","tslib":"^2.6.2"},"devDependencies":{"concurrently":"7.0.0","downlevel-dts":"0.10.1","rimraf":"3.0.2","typescript":"~5.8.3"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["./sso-oidc.d.ts","./sso-oidc.js","./sts.d.ts","./sts.js","dist-*/**"],"browser":{"./dist-es/submodules/sso-oidc/runtimeConfig":"./dist-es/submodules/sso-oidc/runtimeConfig.browser","./dist-es/submodules/sts/runtimeConfig":"./dist-es/submodules/sts/runtimeConfig.browser"},"react-native":{},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/packages/nested-clients","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"packages/nested-clients"},"exports":{"./sso-oidc":{"types":"./dist-types/submodules/sso-oidc/index.d.ts","module":"./dist-es/submodules/sso-oidc/index.js","node":"./dist-cjs/submodules/sso-oidc/index.js","import":"./dist-es/submodules/sso-oidc/index.js","require":"./dist-cjs/submodules/sso-oidc/index.js"},"./sts":{"types":"./dist-types/submodules/sts/index.d.ts","module":"./dist-es/submodules/sts/index.js","node":"./dist-cjs/submodules/sts/index.js","import":"./dist-es/submodules/sts/index.js","require":"./dist-cjs/submodules/sts/index.js"}}}'); + +/***/ }), + +/***/ 72721: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@google-cloud/storage","description":"Cloud Storage Client Library for Node.js","version":"7.16.0","license":"Apache-2.0","author":"Google Inc.","engines":{"node":">=14"},"repository":"googleapis/nodejs-storage","main":"./build/cjs/src/index.js","types":"./build/cjs/src/index.d.ts","type":"module","exports":{".":{"import":{"types":"./build/esm/src/index.d.ts","default":"./build/esm/src/index.js"},"require":{"types":"./build/cjs/src/index.d.ts","default":"./build/cjs/src/index.js"}}},"files":["build/cjs/src","build/cjs/package.json","!build/cjs/src/**/*.map","build/esm/src","!build/esm/src/**/*.map"],"keywords":["google apis client","google api client","google apis","google api","google","google cloud platform","google cloud","cloud","google storage","storage"],"scripts":{"all-test":"npm test && npm run system-test && npm run samples-test","benchwrapper":"node bin/benchwrapper.js","check":"gts check","clean":"rm -rf build/","compile:cjs":"tsc -p ./tsconfig.cjs.json","compile:esm":"tsc -p .","compile":"npm run compile:cjs && npm run compile:esm","conformance-test":"mocha --parallel build/cjs/conformance-test/ --require build/cjs/conformance-test/globalHooks.js","docs-test":"linkinator docs","docs":"jsdoc -c .jsdoc.json","fix":"gts fix","lint":"gts check","postcompile":"cp ./src/package-json-helper.cjs ./build/cjs/src && cp ./src/package-json-helper.cjs ./build/esm/src","postcompile:cjs":"babel --plugins gapic-tools/build/src/replaceImportMetaUrl,gapic-tools/build/src/toggleESMFlagVariable build/cjs/src/util.js -o build/cjs/src/util.js && cp internal-tooling/helpers/package.cjs.json build/cjs/package.json","precompile":"rm -rf build/","preconformance-test":"npm run compile:cjs -- --sourceMap","predocs-test":"npm run docs","predocs":"npm run compile:cjs -- --sourceMap","prelint":"cd samples; npm link ../; npm install","prepare":"npm run compile","presystem-test:esm":"npm run compile:esm","presystem-test":"npm run compile -- --sourceMap","pretest":"npm run compile -- --sourceMap","samples-test":"npm link && cd samples/ && npm link ../ && npm test && cd ../","system-test:esm":"mocha build/esm/system-test --timeout 600000 --exit","system-test":"mocha build/cjs/system-test --timeout 600000 --exit","test":"c8 mocha build/cjs/test"},"dependencies":{"@google-cloud/paginator":"^5.0.0","@google-cloud/projectify":"^4.0.0","@google-cloud/promisify":"<4.1.0","abort-controller":"^3.0.0","async-retry":"^1.3.3","duplexify":"^4.1.3","fast-xml-parser":"^4.4.1","gaxios":"^6.0.2","google-auth-library":"^9.6.3","html-entities":"^2.5.2","mime":"^3.0.0","p-limit":"^3.0.1","retry-request":"^7.0.0","teeny-request":"^9.0.0","uuid":"^8.0.0"},"devDependencies":{"@babel/cli":"^7.22.10","@babel/core":"^7.22.11","@google-cloud/pubsub":"^4.0.0","@grpc/grpc-js":"^1.0.3","@grpc/proto-loader":"^0.7.0","@types/async-retry":"^1.4.3","@types/duplexify":"^3.6.4","@types/mime":"^3.0.0","@types/mocha":"^9.1.1","@types/mockery":"^1.4.29","@types/node":"^22.0.0","@types/node-fetch":"^2.1.3","@types/proxyquire":"^1.3.28","@types/request":"^2.48.4","@types/sinon":"^17.0.0","@types/tmp":"0.2.6","@types/uuid":"^8.0.0","@types/yargs":"^17.0.10","c8":"^9.0.0","form-data":"^4.0.0","gapic-tools":"^0.4.0","gts":"^5.0.0","jsdoc":"^4.0.0","jsdoc-fresh":"^3.0.0","jsdoc-region-tag":"^3.0.0","linkinator":"^3.0.0","mocha":"^9.2.2","mockery":"^2.1.0","nock":"~13.5.0","node-fetch":"^2.6.7","pack-n-play":"^2.0.0","proxyquire":"^2.1.3","sinon":"^18.0.0","nise":"6.0.0","path-to-regexp":"6.3.0","tmp":"^0.2.0","typescript":"^5.1.6","yargs":"^17.3.1"}}'); + +/***/ }), + +/***/ 66495: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"gaxios","version":"6.7.1","description":"A simple common HTTP client specifically for Google APIs and services.","main":"build/src/index.js","types":"build/src/index.d.ts","files":["build/src"],"scripts":{"lint":"gts check","test":"c8 mocha build/test","presystem-test":"npm run compile","system-test":"mocha build/system-test --timeout 80000","compile":"tsc -p .","fix":"gts fix","prepare":"npm run compile","pretest":"npm run compile","webpack":"webpack","prebrowser-test":"npm run compile","browser-test":"node build/browser-test/browser-test-runner.js","docs":"compodoc src/","docs-test":"linkinator docs","predocs-test":"npm run docs","samples-test":"cd samples/ && npm link ../ && npm test && cd ../","prelint":"cd samples; npm link ../; npm install","clean":"gts clean","precompile":"gts clean"},"repository":"googleapis/gaxios","keywords":["google"],"engines":{"node":">=14"},"author":"Google, LLC","license":"Apache-2.0","devDependencies":{"@babel/plugin-proposal-private-methods":"^7.18.6","@compodoc/compodoc":"1.1.19","@types/cors":"^2.8.6","@types/express":"^4.16.1","@types/extend":"^3.0.1","@types/mocha":"^9.0.0","@types/multiparty":"0.0.36","@types/mv":"^2.1.0","@types/ncp":"^2.0.1","@types/node":"^20.0.0","@types/node-fetch":"^2.5.7","@types/sinon":"^17.0.0","@types/tmp":"0.2.6","@types/uuid":"^10.0.0","abort-controller":"^3.0.0","assert":"^2.0.0","browserify":"^17.0.0","c8":"^8.0.0","cheerio":"1.0.0-rc.10","cors":"^2.8.5","execa":"^5.0.0","express":"^4.16.4","form-data":"^4.0.0","gts":"^5.0.0","is-docker":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-coverage":"^2.0.0","karma-firefox-launcher":"^2.0.0","karma-mocha":"^2.0.0","karma-remap-coverage":"^0.1.5","karma-sourcemap-loader":"^0.4.0","karma-webpack":"5.0.0","linkinator":"^3.0.0","mocha":"^8.0.0","multiparty":"^4.2.1","mv":"^2.1.1","ncp":"^2.0.0","nock":"^13.0.0","null-loader":"^4.0.0","puppeteer":"^19.0.0","sinon":"^18.0.0","stream-browserify":"^3.0.0","tmp":"0.2.3","ts-loader":"^8.0.0","typescript":"^5.1.6","webpack":"^5.35.0","webpack-cli":"^4.0.0"},"dependencies":{"extend":"^3.0.2","https-proxy-agent":"^7.0.1","is-stream":"^2.0.0","node-fetch":"^2.6.9","uuid":"^9.0.1"}}'); + +/***/ }), + +/***/ 96066: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"google-auth-library","version":"9.15.1","author":"Google Inc.","description":"Google APIs Authentication Client Library for Node.js","engines":{"node":">=14"},"main":"./build/src/index.js","types":"./build/src/index.d.ts","repository":"googleapis/google-auth-library-nodejs.git","keywords":["google","api","google apis","client","client library"],"dependencies":{"base64-js":"^1.3.0","ecdsa-sig-formatter":"^1.0.11","gaxios":"^6.1.1","gcp-metadata":"^6.1.0","gtoken":"^7.0.0","jws":"^4.0.0"},"devDependencies":{"@types/base64-js":"^1.2.5","@types/chai":"^4.1.7","@types/jws":"^3.1.0","@types/mocha":"^9.0.0","@types/mv":"^2.1.0","@types/ncp":"^2.0.1","@types/node":"^20.4.2","@types/sinon":"^17.0.0","assert-rejects":"^1.0.0","c8":"^8.0.0","chai":"^4.2.0","cheerio":"1.0.0-rc.12","codecov":"^3.0.2","engine.io":"6.6.2","gts":"^5.0.0","is-docker":"^2.0.0","jsdoc":"^4.0.0","jsdoc-fresh":"^3.0.0","jsdoc-region-tag":"^3.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-coverage":"^2.0.0","karma-firefox-launcher":"^2.0.0","karma-mocha":"^2.0.0","karma-sourcemap-loader":"^0.4.0","karma-webpack":"5.0.0","keypair":"^1.0.4","linkinator":"^4.0.0","mocha":"^9.2.2","mv":"^2.1.1","ncp":"^2.0.0","nock":"^13.0.0","null-loader":"^4.0.0","pdfmake":"0.2.12","puppeteer":"^21.0.0","sinon":"^18.0.0","ts-loader":"^8.0.0","typescript":"^5.1.6","webpack":"^5.21.2","webpack-cli":"^4.0.0"},"files":["build/src","!build/src/**/*.map"],"scripts":{"test":"c8 mocha build/test","clean":"gts clean","prepare":"npm run compile","lint":"gts check","compile":"tsc -p .","fix":"gts fix","pretest":"npm run compile -- --sourceMap","docs":"jsdoc -c .jsdoc.json","samples-setup":"cd samples/ && npm link ../ && npm run setup && cd ../","samples-test":"cd samples/ && npm link ../ && npm test && cd ../","system-test":"mocha build/system-test --timeout 60000","presystem-test":"npm run compile -- --sourceMap","webpack":"webpack","browser-test":"karma start","docs-test":"linkinator docs","predocs-test":"npm run docs","prelint":"cd samples; npm link ../; npm install","precompile":"gts clean"},"license":"Apache-2.0"}'); + +/***/ }), + +/***/ 92472: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"],[[47,47],"disallowed_STD3_valid"],[[48,57],"valid"],[[58,64],"disallowed_STD3_valid"],[[65,65],"mapped",[97]],[[66,66],"mapped",[98]],[[67,67],"mapped",[99]],[[68,68],"mapped",[100]],[[69,69],"mapped",[101]],[[70,70],"mapped",[102]],[[71,71],"mapped",[103]],[[72,72],"mapped",[104]],[[73,73],"mapped",[105]],[[74,74],"mapped",[106]],[[75,75],"mapped",[107]],[[76,76],"mapped",[108]],[[77,77],"mapped",[109]],[[78,78],"mapped",[110]],[[79,79],"mapped",[111]],[[80,80],"mapped",[112]],[[81,81],"mapped",[113]],[[82,82],"mapped",[114]],[[83,83],"mapped",[115]],[[84,84],"mapped",[116]],[[85,85],"mapped",[117]],[[86,86],"mapped",[118]],[[87,87],"mapped",[119]],[[88,88],"mapped",[120]],[[89,89],"mapped",[121]],[[90,90],"mapped",[122]],[[91,96],"disallowed_STD3_valid"],[[97,122],"valid"],[[123,127],"disallowed_STD3_valid"],[[128,159],"disallowed"],[[160,160],"disallowed_STD3_mapped",[32]],[[161,167],"valid",[],"NV8"],[[168,168],"disallowed_STD3_mapped",[32,776]],[[169,169],"valid",[],"NV8"],[[170,170],"mapped",[97]],[[171,172],"valid",[],"NV8"],[[173,173],"ignored"],[[174,174],"valid",[],"NV8"],[[175,175],"disallowed_STD3_mapped",[32,772]],[[176,177],"valid",[],"NV8"],[[178,178],"mapped",[50]],[[179,179],"mapped",[51]],[[180,180],"disallowed_STD3_mapped",[32,769]],[[181,181],"mapped",[956]],[[182,182],"valid",[],"NV8"],[[183,183],"valid"],[[184,184],"disallowed_STD3_mapped",[32,807]],[[185,185],"mapped",[49]],[[186,186],"mapped",[111]],[[187,187],"valid",[],"NV8"],[[188,188],"mapped",[49,8260,52]],[[189,189],"mapped",[49,8260,50]],[[190,190],"mapped",[51,8260,52]],[[191,191],"valid",[],"NV8"],[[192,192],"mapped",[224]],[[193,193],"mapped",[225]],[[194,194],"mapped",[226]],[[195,195],"mapped",[227]],[[196,196],"mapped",[228]],[[197,197],"mapped",[229]],[[198,198],"mapped",[230]],[[199,199],"mapped",[231]],[[200,200],"mapped",[232]],[[201,201],"mapped",[233]],[[202,202],"mapped",[234]],[[203,203],"mapped",[235]],[[204,204],"mapped",[236]],[[205,205],"mapped",[237]],[[206,206],"mapped",[238]],[[207,207],"mapped",[239]],[[208,208],"mapped",[240]],[[209,209],"mapped",[241]],[[210,210],"mapped",[242]],[[211,211],"mapped",[243]],[[212,212],"mapped",[244]],[[213,213],"mapped",[245]],[[214,214],"mapped",[246]],[[215,215],"valid",[],"NV8"],[[216,216],"mapped",[248]],[[217,217],"mapped",[249]],[[218,218],"mapped",[250]],[[219,219],"mapped",[251]],[[220,220],"mapped",[252]],[[221,221],"mapped",[253]],[[222,222],"mapped",[254]],[[223,223],"deviation",[115,115]],[[224,246],"valid"],[[247,247],"valid",[],"NV8"],[[248,255],"valid"],[[256,256],"mapped",[257]],[[257,257],"valid"],[[258,258],"mapped",[259]],[[259,259],"valid"],[[260,260],"mapped",[261]],[[261,261],"valid"],[[262,262],"mapped",[263]],[[263,263],"valid"],[[264,264],"mapped",[265]],[[265,265],"valid"],[[266,266],"mapped",[267]],[[267,267],"valid"],[[268,268],"mapped",[269]],[[269,269],"valid"],[[270,270],"mapped",[271]],[[271,271],"valid"],[[272,272],"mapped",[273]],[[273,273],"valid"],[[274,274],"mapped",[275]],[[275,275],"valid"],[[276,276],"mapped",[277]],[[277,277],"valid"],[[278,278],"mapped",[279]],[[279,279],"valid"],[[280,280],"mapped",[281]],[[281,281],"valid"],[[282,282],"mapped",[283]],[[283,283],"valid"],[[284,284],"mapped",[285]],[[285,285],"valid"],[[286,286],"mapped",[287]],[[287,287],"valid"],[[288,288],"mapped",[289]],[[289,289],"valid"],[[290,290],"mapped",[291]],[[291,291],"valid"],[[292,292],"mapped",[293]],[[293,293],"valid"],[[294,294],"mapped",[295]],[[295,295],"valid"],[[296,296],"mapped",[297]],[[297,297],"valid"],[[298,298],"mapped",[299]],[[299,299],"valid"],[[300,300],"mapped",[301]],[[301,301],"valid"],[[302,302],"mapped",[303]],[[303,303],"valid"],[[304,304],"mapped",[105,775]],[[305,305],"valid"],[[306,307],"mapped",[105,106]],[[308,308],"mapped",[309]],[[309,309],"valid"],[[310,310],"mapped",[311]],[[311,312],"valid"],[[313,313],"mapped",[314]],[[314,314],"valid"],[[315,315],"mapped",[316]],[[316,316],"valid"],[[317,317],"mapped",[318]],[[318,318],"valid"],[[319,320],"mapped",[108,183]],[[321,321],"mapped",[322]],[[322,322],"valid"],[[323,323],"mapped",[324]],[[324,324],"valid"],[[325,325],"mapped",[326]],[[326,326],"valid"],[[327,327],"mapped",[328]],[[328,328],"valid"],[[329,329],"mapped",[700,110]],[[330,330],"mapped",[331]],[[331,331],"valid"],[[332,332],"mapped",[333]],[[333,333],"valid"],[[334,334],"mapped",[335]],[[335,335],"valid"],[[336,336],"mapped",[337]],[[337,337],"valid"],[[338,338],"mapped",[339]],[[339,339],"valid"],[[340,340],"mapped",[341]],[[341,341],"valid"],[[342,342],"mapped",[343]],[[343,343],"valid"],[[344,344],"mapped",[345]],[[345,345],"valid"],[[346,346],"mapped",[347]],[[347,347],"valid"],[[348,348],"mapped",[349]],[[349,349],"valid"],[[350,350],"mapped",[351]],[[351,351],"valid"],[[352,352],"mapped",[353]],[[353,353],"valid"],[[354,354],"mapped",[355]],[[355,355],"valid"],[[356,356],"mapped",[357]],[[357,357],"valid"],[[358,358],"mapped",[359]],[[359,359],"valid"],[[360,360],"mapped",[361]],[[361,361],"valid"],[[362,362],"mapped",[363]],[[363,363],"valid"],[[364,364],"mapped",[365]],[[365,365],"valid"],[[366,366],"mapped",[367]],[[367,367],"valid"],[[368,368],"mapped",[369]],[[369,369],"valid"],[[370,370],"mapped",[371]],[[371,371],"valid"],[[372,372],"mapped",[373]],[[373,373],"valid"],[[374,374],"mapped",[375]],[[375,375],"valid"],[[376,376],"mapped",[255]],[[377,377],"mapped",[378]],[[378,378],"valid"],[[379,379],"mapped",[380]],[[380,380],"valid"],[[381,381],"mapped",[382]],[[382,382],"valid"],[[383,383],"mapped",[115]],[[384,384],"valid"],[[385,385],"mapped",[595]],[[386,386],"mapped",[387]],[[387,387],"valid"],[[388,388],"mapped",[389]],[[389,389],"valid"],[[390,390],"mapped",[596]],[[391,391],"mapped",[392]],[[392,392],"valid"],[[393,393],"mapped",[598]],[[394,394],"mapped",[599]],[[395,395],"mapped",[396]],[[396,397],"valid"],[[398,398],"mapped",[477]],[[399,399],"mapped",[601]],[[400,400],"mapped",[603]],[[401,401],"mapped",[402]],[[402,402],"valid"],[[403,403],"mapped",[608]],[[404,404],"mapped",[611]],[[405,405],"valid"],[[406,406],"mapped",[617]],[[407,407],"mapped",[616]],[[408,408],"mapped",[409]],[[409,411],"valid"],[[412,412],"mapped",[623]],[[413,413],"mapped",[626]],[[414,414],"valid"],[[415,415],"mapped",[629]],[[416,416],"mapped",[417]],[[417,417],"valid"],[[418,418],"mapped",[419]],[[419,419],"valid"],[[420,420],"mapped",[421]],[[421,421],"valid"],[[422,422],"mapped",[640]],[[423,423],"mapped",[424]],[[424,424],"valid"],[[425,425],"mapped",[643]],[[426,427],"valid"],[[428,428],"mapped",[429]],[[429,429],"valid"],[[430,430],"mapped",[648]],[[431,431],"mapped",[432]],[[432,432],"valid"],[[433,433],"mapped",[650]],[[434,434],"mapped",[651]],[[435,435],"mapped",[436]],[[436,436],"valid"],[[437,437],"mapped",[438]],[[438,438],"valid"],[[439,439],"mapped",[658]],[[440,440],"mapped",[441]],[[441,443],"valid"],[[444,444],"mapped",[445]],[[445,451],"valid"],[[452,454],"mapped",[100,382]],[[455,457],"mapped",[108,106]],[[458,460],"mapped",[110,106]],[[461,461],"mapped",[462]],[[462,462],"valid"],[[463,463],"mapped",[464]],[[464,464],"valid"],[[465,465],"mapped",[466]],[[466,466],"valid"],[[467,467],"mapped",[468]],[[468,468],"valid"],[[469,469],"mapped",[470]],[[470,470],"valid"],[[471,471],"mapped",[472]],[[472,472],"valid"],[[473,473],"mapped",[474]],[[474,474],"valid"],[[475,475],"mapped",[476]],[[476,477],"valid"],[[478,478],"mapped",[479]],[[479,479],"valid"],[[480,480],"mapped",[481]],[[481,481],"valid"],[[482,482],"mapped",[483]],[[483,483],"valid"],[[484,484],"mapped",[485]],[[485,485],"valid"],[[486,486],"mapped",[487]],[[487,487],"valid"],[[488,488],"mapped",[489]],[[489,489],"valid"],[[490,490],"mapped",[491]],[[491,491],"valid"],[[492,492],"mapped",[493]],[[493,493],"valid"],[[494,494],"mapped",[495]],[[495,496],"valid"],[[497,499],"mapped",[100,122]],[[500,500],"mapped",[501]],[[501,501],"valid"],[[502,502],"mapped",[405]],[[503,503],"mapped",[447]],[[504,504],"mapped",[505]],[[505,505],"valid"],[[506,506],"mapped",[507]],[[507,507],"valid"],[[508,508],"mapped",[509]],[[509,509],"valid"],[[510,510],"mapped",[511]],[[511,511],"valid"],[[512,512],"mapped",[513]],[[513,513],"valid"],[[514,514],"mapped",[515]],[[515,515],"valid"],[[516,516],"mapped",[517]],[[517,517],"valid"],[[518,518],"mapped",[519]],[[519,519],"valid"],[[520,520],"mapped",[521]],[[521,521],"valid"],[[522,522],"mapped",[523]],[[523,523],"valid"],[[524,524],"mapped",[525]],[[525,525],"valid"],[[526,526],"mapped",[527]],[[527,527],"valid"],[[528,528],"mapped",[529]],[[529,529],"valid"],[[530,530],"mapped",[531]],[[531,531],"valid"],[[532,532],"mapped",[533]],[[533,533],"valid"],[[534,534],"mapped",[535]],[[535,535],"valid"],[[536,536],"mapped",[537]],[[537,537],"valid"],[[538,538],"mapped",[539]],[[539,539],"valid"],[[540,540],"mapped",[541]],[[541,541],"valid"],[[542,542],"mapped",[543]],[[543,543],"valid"],[[544,544],"mapped",[414]],[[545,545],"valid"],[[546,546],"mapped",[547]],[[547,547],"valid"],[[548,548],"mapped",[549]],[[549,549],"valid"],[[550,550],"mapped",[551]],[[551,551],"valid"],[[552,552],"mapped",[553]],[[553,553],"valid"],[[554,554],"mapped",[555]],[[555,555],"valid"],[[556,556],"mapped",[557]],[[557,557],"valid"],[[558,558],"mapped",[559]],[[559,559],"valid"],[[560,560],"mapped",[561]],[[561,561],"valid"],[[562,562],"mapped",[563]],[[563,563],"valid"],[[564,566],"valid"],[[567,569],"valid"],[[570,570],"mapped",[11365]],[[571,571],"mapped",[572]],[[572,572],"valid"],[[573,573],"mapped",[410]],[[574,574],"mapped",[11366]],[[575,576],"valid"],[[577,577],"mapped",[578]],[[578,578],"valid"],[[579,579],"mapped",[384]],[[580,580],"mapped",[649]],[[581,581],"mapped",[652]],[[582,582],"mapped",[583]],[[583,583],"valid"],[[584,584],"mapped",[585]],[[585,585],"valid"],[[586,586],"mapped",[587]],[[587,587],"valid"],[[588,588],"mapped",[589]],[[589,589],"valid"],[[590,590],"mapped",[591]],[[591,591],"valid"],[[592,680],"valid"],[[681,685],"valid"],[[686,687],"valid"],[[688,688],"mapped",[104]],[[689,689],"mapped",[614]],[[690,690],"mapped",[106]],[[691,691],"mapped",[114]],[[692,692],"mapped",[633]],[[693,693],"mapped",[635]],[[694,694],"mapped",[641]],[[695,695],"mapped",[119]],[[696,696],"mapped",[121]],[[697,705],"valid"],[[706,709],"valid",[],"NV8"],[[710,721],"valid"],[[722,727],"valid",[],"NV8"],[[728,728],"disallowed_STD3_mapped",[32,774]],[[729,729],"disallowed_STD3_mapped",[32,775]],[[730,730],"disallowed_STD3_mapped",[32,778]],[[731,731],"disallowed_STD3_mapped",[32,808]],[[732,732],"disallowed_STD3_mapped",[32,771]],[[733,733],"disallowed_STD3_mapped",[32,779]],[[734,734],"valid",[],"NV8"],[[735,735],"valid",[],"NV8"],[[736,736],"mapped",[611]],[[737,737],"mapped",[108]],[[738,738],"mapped",[115]],[[739,739],"mapped",[120]],[[740,740],"mapped",[661]],[[741,745],"valid",[],"NV8"],[[746,747],"valid",[],"NV8"],[[748,748],"valid"],[[749,749],"valid",[],"NV8"],[[750,750],"valid"],[[751,767],"valid",[],"NV8"],[[768,831],"valid"],[[832,832],"mapped",[768]],[[833,833],"mapped",[769]],[[834,834],"valid"],[[835,835],"mapped",[787]],[[836,836],"mapped",[776,769]],[[837,837],"mapped",[953]],[[838,846],"valid"],[[847,847],"ignored"],[[848,855],"valid"],[[856,860],"valid"],[[861,863],"valid"],[[864,865],"valid"],[[866,866],"valid"],[[867,879],"valid"],[[880,880],"mapped",[881]],[[881,881],"valid"],[[882,882],"mapped",[883]],[[883,883],"valid"],[[884,884],"mapped",[697]],[[885,885],"valid"],[[886,886],"mapped",[887]],[[887,887],"valid"],[[888,889],"disallowed"],[[890,890],"disallowed_STD3_mapped",[32,953]],[[891,893],"valid"],[[894,894],"disallowed_STD3_mapped",[59]],[[895,895],"mapped",[1011]],[[896,899],"disallowed"],[[900,900],"disallowed_STD3_mapped",[32,769]],[[901,901],"disallowed_STD3_mapped",[32,776,769]],[[902,902],"mapped",[940]],[[903,903],"mapped",[183]],[[904,904],"mapped",[941]],[[905,905],"mapped",[942]],[[906,906],"mapped",[943]],[[907,907],"disallowed"],[[908,908],"mapped",[972]],[[909,909],"disallowed"],[[910,910],"mapped",[973]],[[911,911],"mapped",[974]],[[912,912],"valid"],[[913,913],"mapped",[945]],[[914,914],"mapped",[946]],[[915,915],"mapped",[947]],[[916,916],"mapped",[948]],[[917,917],"mapped",[949]],[[918,918],"mapped",[950]],[[919,919],"mapped",[951]],[[920,920],"mapped",[952]],[[921,921],"mapped",[953]],[[922,922],"mapped",[954]],[[923,923],"mapped",[955]],[[924,924],"mapped",[956]],[[925,925],"mapped",[957]],[[926,926],"mapped",[958]],[[927,927],"mapped",[959]],[[928,928],"mapped",[960]],[[929,929],"mapped",[961]],[[930,930],"disallowed"],[[931,931],"mapped",[963]],[[932,932],"mapped",[964]],[[933,933],"mapped",[965]],[[934,934],"mapped",[966]],[[935,935],"mapped",[967]],[[936,936],"mapped",[968]],[[937,937],"mapped",[969]],[[938,938],"mapped",[970]],[[939,939],"mapped",[971]],[[940,961],"valid"],[[962,962],"deviation",[963]],[[963,974],"valid"],[[975,975],"mapped",[983]],[[976,976],"mapped",[946]],[[977,977],"mapped",[952]],[[978,978],"mapped",[965]],[[979,979],"mapped",[973]],[[980,980],"mapped",[971]],[[981,981],"mapped",[966]],[[982,982],"mapped",[960]],[[983,983],"valid"],[[984,984],"mapped",[985]],[[985,985],"valid"],[[986,986],"mapped",[987]],[[987,987],"valid"],[[988,988],"mapped",[989]],[[989,989],"valid"],[[990,990],"mapped",[991]],[[991,991],"valid"],[[992,992],"mapped",[993]],[[993,993],"valid"],[[994,994],"mapped",[995]],[[995,995],"valid"],[[996,996],"mapped",[997]],[[997,997],"valid"],[[998,998],"mapped",[999]],[[999,999],"valid"],[[1000,1000],"mapped",[1001]],[[1001,1001],"valid"],[[1002,1002],"mapped",[1003]],[[1003,1003],"valid"],[[1004,1004],"mapped",[1005]],[[1005,1005],"valid"],[[1006,1006],"mapped",[1007]],[[1007,1007],"valid"],[[1008,1008],"mapped",[954]],[[1009,1009],"mapped",[961]],[[1010,1010],"mapped",[963]],[[1011,1011],"valid"],[[1012,1012],"mapped",[952]],[[1013,1013],"mapped",[949]],[[1014,1014],"valid",[],"NV8"],[[1015,1015],"mapped",[1016]],[[1016,1016],"valid"],[[1017,1017],"mapped",[963]],[[1018,1018],"mapped",[1019]],[[1019,1019],"valid"],[[1020,1020],"valid"],[[1021,1021],"mapped",[891]],[[1022,1022],"mapped",[892]],[[1023,1023],"mapped",[893]],[[1024,1024],"mapped",[1104]],[[1025,1025],"mapped",[1105]],[[1026,1026],"mapped",[1106]],[[1027,1027],"mapped",[1107]],[[1028,1028],"mapped",[1108]],[[1029,1029],"mapped",[1109]],[[1030,1030],"mapped",[1110]],[[1031,1031],"mapped",[1111]],[[1032,1032],"mapped",[1112]],[[1033,1033],"mapped",[1113]],[[1034,1034],"mapped",[1114]],[[1035,1035],"mapped",[1115]],[[1036,1036],"mapped",[1116]],[[1037,1037],"mapped",[1117]],[[1038,1038],"mapped",[1118]],[[1039,1039],"mapped",[1119]],[[1040,1040],"mapped",[1072]],[[1041,1041],"mapped",[1073]],[[1042,1042],"mapped",[1074]],[[1043,1043],"mapped",[1075]],[[1044,1044],"mapped",[1076]],[[1045,1045],"mapped",[1077]],[[1046,1046],"mapped",[1078]],[[1047,1047],"mapped",[1079]],[[1048,1048],"mapped",[1080]],[[1049,1049],"mapped",[1081]],[[1050,1050],"mapped",[1082]],[[1051,1051],"mapped",[1083]],[[1052,1052],"mapped",[1084]],[[1053,1053],"mapped",[1085]],[[1054,1054],"mapped",[1086]],[[1055,1055],"mapped",[1087]],[[1056,1056],"mapped",[1088]],[[1057,1057],"mapped",[1089]],[[1058,1058],"mapped",[1090]],[[1059,1059],"mapped",[1091]],[[1060,1060],"mapped",[1092]],[[1061,1061],"mapped",[1093]],[[1062,1062],"mapped",[1094]],[[1063,1063],"mapped",[1095]],[[1064,1064],"mapped",[1096]],[[1065,1065],"mapped",[1097]],[[1066,1066],"mapped",[1098]],[[1067,1067],"mapped",[1099]],[[1068,1068],"mapped",[1100]],[[1069,1069],"mapped",[1101]],[[1070,1070],"mapped",[1102]],[[1071,1071],"mapped",[1103]],[[1072,1103],"valid"],[[1104,1104],"valid"],[[1105,1116],"valid"],[[1117,1117],"valid"],[[1118,1119],"valid"],[[1120,1120],"mapped",[1121]],[[1121,1121],"valid"],[[1122,1122],"mapped",[1123]],[[1123,1123],"valid"],[[1124,1124],"mapped",[1125]],[[1125,1125],"valid"],[[1126,1126],"mapped",[1127]],[[1127,1127],"valid"],[[1128,1128],"mapped",[1129]],[[1129,1129],"valid"],[[1130,1130],"mapped",[1131]],[[1131,1131],"valid"],[[1132,1132],"mapped",[1133]],[[1133,1133],"valid"],[[1134,1134],"mapped",[1135]],[[1135,1135],"valid"],[[1136,1136],"mapped",[1137]],[[1137,1137],"valid"],[[1138,1138],"mapped",[1139]],[[1139,1139],"valid"],[[1140,1140],"mapped",[1141]],[[1141,1141],"valid"],[[1142,1142],"mapped",[1143]],[[1143,1143],"valid"],[[1144,1144],"mapped",[1145]],[[1145,1145],"valid"],[[1146,1146],"mapped",[1147]],[[1147,1147],"valid"],[[1148,1148],"mapped",[1149]],[[1149,1149],"valid"],[[1150,1150],"mapped",[1151]],[[1151,1151],"valid"],[[1152,1152],"mapped",[1153]],[[1153,1153],"valid"],[[1154,1154],"valid",[],"NV8"],[[1155,1158],"valid"],[[1159,1159],"valid"],[[1160,1161],"valid",[],"NV8"],[[1162,1162],"mapped",[1163]],[[1163,1163],"valid"],[[1164,1164],"mapped",[1165]],[[1165,1165],"valid"],[[1166,1166],"mapped",[1167]],[[1167,1167],"valid"],[[1168,1168],"mapped",[1169]],[[1169,1169],"valid"],[[1170,1170],"mapped",[1171]],[[1171,1171],"valid"],[[1172,1172],"mapped",[1173]],[[1173,1173],"valid"],[[1174,1174],"mapped",[1175]],[[1175,1175],"valid"],[[1176,1176],"mapped",[1177]],[[1177,1177],"valid"],[[1178,1178],"mapped",[1179]],[[1179,1179],"valid"],[[1180,1180],"mapped",[1181]],[[1181,1181],"valid"],[[1182,1182],"mapped",[1183]],[[1183,1183],"valid"],[[1184,1184],"mapped",[1185]],[[1185,1185],"valid"],[[1186,1186],"mapped",[1187]],[[1187,1187],"valid"],[[1188,1188],"mapped",[1189]],[[1189,1189],"valid"],[[1190,1190],"mapped",[1191]],[[1191,1191],"valid"],[[1192,1192],"mapped",[1193]],[[1193,1193],"valid"],[[1194,1194],"mapped",[1195]],[[1195,1195],"valid"],[[1196,1196],"mapped",[1197]],[[1197,1197],"valid"],[[1198,1198],"mapped",[1199]],[[1199,1199],"valid"],[[1200,1200],"mapped",[1201]],[[1201,1201],"valid"],[[1202,1202],"mapped",[1203]],[[1203,1203],"valid"],[[1204,1204],"mapped",[1205]],[[1205,1205],"valid"],[[1206,1206],"mapped",[1207]],[[1207,1207],"valid"],[[1208,1208],"mapped",[1209]],[[1209,1209],"valid"],[[1210,1210],"mapped",[1211]],[[1211,1211],"valid"],[[1212,1212],"mapped",[1213]],[[1213,1213],"valid"],[[1214,1214],"mapped",[1215]],[[1215,1215],"valid"],[[1216,1216],"disallowed"],[[1217,1217],"mapped",[1218]],[[1218,1218],"valid"],[[1219,1219],"mapped",[1220]],[[1220,1220],"valid"],[[1221,1221],"mapped",[1222]],[[1222,1222],"valid"],[[1223,1223],"mapped",[1224]],[[1224,1224],"valid"],[[1225,1225],"mapped",[1226]],[[1226,1226],"valid"],[[1227,1227],"mapped",[1228]],[[1228,1228],"valid"],[[1229,1229],"mapped",[1230]],[[1230,1230],"valid"],[[1231,1231],"valid"],[[1232,1232],"mapped",[1233]],[[1233,1233],"valid"],[[1234,1234],"mapped",[1235]],[[1235,1235],"valid"],[[1236,1236],"mapped",[1237]],[[1237,1237],"valid"],[[1238,1238],"mapped",[1239]],[[1239,1239],"valid"],[[1240,1240],"mapped",[1241]],[[1241,1241],"valid"],[[1242,1242],"mapped",[1243]],[[1243,1243],"valid"],[[1244,1244],"mapped",[1245]],[[1245,1245],"valid"],[[1246,1246],"mapped",[1247]],[[1247,1247],"valid"],[[1248,1248],"mapped",[1249]],[[1249,1249],"valid"],[[1250,1250],"mapped",[1251]],[[1251,1251],"valid"],[[1252,1252],"mapped",[1253]],[[1253,1253],"valid"],[[1254,1254],"mapped",[1255]],[[1255,1255],"valid"],[[1256,1256],"mapped",[1257]],[[1257,1257],"valid"],[[1258,1258],"mapped",[1259]],[[1259,1259],"valid"],[[1260,1260],"mapped",[1261]],[[1261,1261],"valid"],[[1262,1262],"mapped",[1263]],[[1263,1263],"valid"],[[1264,1264],"mapped",[1265]],[[1265,1265],"valid"],[[1266,1266],"mapped",[1267]],[[1267,1267],"valid"],[[1268,1268],"mapped",[1269]],[[1269,1269],"valid"],[[1270,1270],"mapped",[1271]],[[1271,1271],"valid"],[[1272,1272],"mapped",[1273]],[[1273,1273],"valid"],[[1274,1274],"mapped",[1275]],[[1275,1275],"valid"],[[1276,1276],"mapped",[1277]],[[1277,1277],"valid"],[[1278,1278],"mapped",[1279]],[[1279,1279],"valid"],[[1280,1280],"mapped",[1281]],[[1281,1281],"valid"],[[1282,1282],"mapped",[1283]],[[1283,1283],"valid"],[[1284,1284],"mapped",[1285]],[[1285,1285],"valid"],[[1286,1286],"mapped",[1287]],[[1287,1287],"valid"],[[1288,1288],"mapped",[1289]],[[1289,1289],"valid"],[[1290,1290],"mapped",[1291]],[[1291,1291],"valid"],[[1292,1292],"mapped",[1293]],[[1293,1293],"valid"],[[1294,1294],"mapped",[1295]],[[1295,1295],"valid"],[[1296,1296],"mapped",[1297]],[[1297,1297],"valid"],[[1298,1298],"mapped",[1299]],[[1299,1299],"valid"],[[1300,1300],"mapped",[1301]],[[1301,1301],"valid"],[[1302,1302],"mapped",[1303]],[[1303,1303],"valid"],[[1304,1304],"mapped",[1305]],[[1305,1305],"valid"],[[1306,1306],"mapped",[1307]],[[1307,1307],"valid"],[[1308,1308],"mapped",[1309]],[[1309,1309],"valid"],[[1310,1310],"mapped",[1311]],[[1311,1311],"valid"],[[1312,1312],"mapped",[1313]],[[1313,1313],"valid"],[[1314,1314],"mapped",[1315]],[[1315,1315],"valid"],[[1316,1316],"mapped",[1317]],[[1317,1317],"valid"],[[1318,1318],"mapped",[1319]],[[1319,1319],"valid"],[[1320,1320],"mapped",[1321]],[[1321,1321],"valid"],[[1322,1322],"mapped",[1323]],[[1323,1323],"valid"],[[1324,1324],"mapped",[1325]],[[1325,1325],"valid"],[[1326,1326],"mapped",[1327]],[[1327,1327],"valid"],[[1328,1328],"disallowed"],[[1329,1329],"mapped",[1377]],[[1330,1330],"mapped",[1378]],[[1331,1331],"mapped",[1379]],[[1332,1332],"mapped",[1380]],[[1333,1333],"mapped",[1381]],[[1334,1334],"mapped",[1382]],[[1335,1335],"mapped",[1383]],[[1336,1336],"mapped",[1384]],[[1337,1337],"mapped",[1385]],[[1338,1338],"mapped",[1386]],[[1339,1339],"mapped",[1387]],[[1340,1340],"mapped",[1388]],[[1341,1341],"mapped",[1389]],[[1342,1342],"mapped",[1390]],[[1343,1343],"mapped",[1391]],[[1344,1344],"mapped",[1392]],[[1345,1345],"mapped",[1393]],[[1346,1346],"mapped",[1394]],[[1347,1347],"mapped",[1395]],[[1348,1348],"mapped",[1396]],[[1349,1349],"mapped",[1397]],[[1350,1350],"mapped",[1398]],[[1351,1351],"mapped",[1399]],[[1352,1352],"mapped",[1400]],[[1353,1353],"mapped",[1401]],[[1354,1354],"mapped",[1402]],[[1355,1355],"mapped",[1403]],[[1356,1356],"mapped",[1404]],[[1357,1357],"mapped",[1405]],[[1358,1358],"mapped",[1406]],[[1359,1359],"mapped",[1407]],[[1360,1360],"mapped",[1408]],[[1361,1361],"mapped",[1409]],[[1362,1362],"mapped",[1410]],[[1363,1363],"mapped",[1411]],[[1364,1364],"mapped",[1412]],[[1365,1365],"mapped",[1413]],[[1366,1366],"mapped",[1414]],[[1367,1368],"disallowed"],[[1369,1369],"valid"],[[1370,1375],"valid",[],"NV8"],[[1376,1376],"disallowed"],[[1377,1414],"valid"],[[1415,1415],"mapped",[1381,1410]],[[1416,1416],"disallowed"],[[1417,1417],"valid",[],"NV8"],[[1418,1418],"valid",[],"NV8"],[[1419,1420],"disallowed"],[[1421,1422],"valid",[],"NV8"],[[1423,1423],"valid",[],"NV8"],[[1424,1424],"disallowed"],[[1425,1441],"valid"],[[1442,1442],"valid"],[[1443,1455],"valid"],[[1456,1465],"valid"],[[1466,1466],"valid"],[[1467,1469],"valid"],[[1470,1470],"valid",[],"NV8"],[[1471,1471],"valid"],[[1472,1472],"valid",[],"NV8"],[[1473,1474],"valid"],[[1475,1475],"valid",[],"NV8"],[[1476,1476],"valid"],[[1477,1477],"valid"],[[1478,1478],"valid",[],"NV8"],[[1479,1479],"valid"],[[1480,1487],"disallowed"],[[1488,1514],"valid"],[[1515,1519],"disallowed"],[[1520,1524],"valid"],[[1525,1535],"disallowed"],[[1536,1539],"disallowed"],[[1540,1540],"disallowed"],[[1541,1541],"disallowed"],[[1542,1546],"valid",[],"NV8"],[[1547,1547],"valid",[],"NV8"],[[1548,1548],"valid",[],"NV8"],[[1549,1551],"valid",[],"NV8"],[[1552,1557],"valid"],[[1558,1562],"valid"],[[1563,1563],"valid",[],"NV8"],[[1564,1564],"disallowed"],[[1565,1565],"disallowed"],[[1566,1566],"valid",[],"NV8"],[[1567,1567],"valid",[],"NV8"],[[1568,1568],"valid"],[[1569,1594],"valid"],[[1595,1599],"valid"],[[1600,1600],"valid",[],"NV8"],[[1601,1618],"valid"],[[1619,1621],"valid"],[[1622,1624],"valid"],[[1625,1630],"valid"],[[1631,1631],"valid"],[[1632,1641],"valid"],[[1642,1645],"valid",[],"NV8"],[[1646,1647],"valid"],[[1648,1652],"valid"],[[1653,1653],"mapped",[1575,1652]],[[1654,1654],"mapped",[1608,1652]],[[1655,1655],"mapped",[1735,1652]],[[1656,1656],"mapped",[1610,1652]],[[1657,1719],"valid"],[[1720,1721],"valid"],[[1722,1726],"valid"],[[1727,1727],"valid"],[[1728,1742],"valid"],[[1743,1743],"valid"],[[1744,1747],"valid"],[[1748,1748],"valid",[],"NV8"],[[1749,1756],"valid"],[[1757,1757],"disallowed"],[[1758,1758],"valid",[],"NV8"],[[1759,1768],"valid"],[[1769,1769],"valid",[],"NV8"],[[1770,1773],"valid"],[[1774,1775],"valid"],[[1776,1785],"valid"],[[1786,1790],"valid"],[[1791,1791],"valid"],[[1792,1805],"valid",[],"NV8"],[[1806,1806],"disallowed"],[[1807,1807],"disallowed"],[[1808,1836],"valid"],[[1837,1839],"valid"],[[1840,1866],"valid"],[[1867,1868],"disallowed"],[[1869,1871],"valid"],[[1872,1901],"valid"],[[1902,1919],"valid"],[[1920,1968],"valid"],[[1969,1969],"valid"],[[1970,1983],"disallowed"],[[1984,2037],"valid"],[[2038,2042],"valid",[],"NV8"],[[2043,2047],"disallowed"],[[2048,2093],"valid"],[[2094,2095],"disallowed"],[[2096,2110],"valid",[],"NV8"],[[2111,2111],"disallowed"],[[2112,2139],"valid"],[[2140,2141],"disallowed"],[[2142,2142],"valid",[],"NV8"],[[2143,2207],"disallowed"],[[2208,2208],"valid"],[[2209,2209],"valid"],[[2210,2220],"valid"],[[2221,2226],"valid"],[[2227,2228],"valid"],[[2229,2274],"disallowed"],[[2275,2275],"valid"],[[2276,2302],"valid"],[[2303,2303],"valid"],[[2304,2304],"valid"],[[2305,2307],"valid"],[[2308,2308],"valid"],[[2309,2361],"valid"],[[2362,2363],"valid"],[[2364,2381],"valid"],[[2382,2382],"valid"],[[2383,2383],"valid"],[[2384,2388],"valid"],[[2389,2389],"valid"],[[2390,2391],"valid"],[[2392,2392],"mapped",[2325,2364]],[[2393,2393],"mapped",[2326,2364]],[[2394,2394],"mapped",[2327,2364]],[[2395,2395],"mapped",[2332,2364]],[[2396,2396],"mapped",[2337,2364]],[[2397,2397],"mapped",[2338,2364]],[[2398,2398],"mapped",[2347,2364]],[[2399,2399],"mapped",[2351,2364]],[[2400,2403],"valid"],[[2404,2405],"valid",[],"NV8"],[[2406,2415],"valid"],[[2416,2416],"valid",[],"NV8"],[[2417,2418],"valid"],[[2419,2423],"valid"],[[2424,2424],"valid"],[[2425,2426],"valid"],[[2427,2428],"valid"],[[2429,2429],"valid"],[[2430,2431],"valid"],[[2432,2432],"valid"],[[2433,2435],"valid"],[[2436,2436],"disallowed"],[[2437,2444],"valid"],[[2445,2446],"disallowed"],[[2447,2448],"valid"],[[2449,2450],"disallowed"],[[2451,2472],"valid"],[[2473,2473],"disallowed"],[[2474,2480],"valid"],[[2481,2481],"disallowed"],[[2482,2482],"valid"],[[2483,2485],"disallowed"],[[2486,2489],"valid"],[[2490,2491],"disallowed"],[[2492,2492],"valid"],[[2493,2493],"valid"],[[2494,2500],"valid"],[[2501,2502],"disallowed"],[[2503,2504],"valid"],[[2505,2506],"disallowed"],[[2507,2509],"valid"],[[2510,2510],"valid"],[[2511,2518],"disallowed"],[[2519,2519],"valid"],[[2520,2523],"disallowed"],[[2524,2524],"mapped",[2465,2492]],[[2525,2525],"mapped",[2466,2492]],[[2526,2526],"disallowed"],[[2527,2527],"mapped",[2479,2492]],[[2528,2531],"valid"],[[2532,2533],"disallowed"],[[2534,2545],"valid"],[[2546,2554],"valid",[],"NV8"],[[2555,2555],"valid",[],"NV8"],[[2556,2560],"disallowed"],[[2561,2561],"valid"],[[2562,2562],"valid"],[[2563,2563],"valid"],[[2564,2564],"disallowed"],[[2565,2570],"valid"],[[2571,2574],"disallowed"],[[2575,2576],"valid"],[[2577,2578],"disallowed"],[[2579,2600],"valid"],[[2601,2601],"disallowed"],[[2602,2608],"valid"],[[2609,2609],"disallowed"],[[2610,2610],"valid"],[[2611,2611],"mapped",[2610,2620]],[[2612,2612],"disallowed"],[[2613,2613],"valid"],[[2614,2614],"mapped",[2616,2620]],[[2615,2615],"disallowed"],[[2616,2617],"valid"],[[2618,2619],"disallowed"],[[2620,2620],"valid"],[[2621,2621],"disallowed"],[[2622,2626],"valid"],[[2627,2630],"disallowed"],[[2631,2632],"valid"],[[2633,2634],"disallowed"],[[2635,2637],"valid"],[[2638,2640],"disallowed"],[[2641,2641],"valid"],[[2642,2648],"disallowed"],[[2649,2649],"mapped",[2582,2620]],[[2650,2650],"mapped",[2583,2620]],[[2651,2651],"mapped",[2588,2620]],[[2652,2652],"valid"],[[2653,2653],"disallowed"],[[2654,2654],"mapped",[2603,2620]],[[2655,2661],"disallowed"],[[2662,2676],"valid"],[[2677,2677],"valid"],[[2678,2688],"disallowed"],[[2689,2691],"valid"],[[2692,2692],"disallowed"],[[2693,2699],"valid"],[[2700,2700],"valid"],[[2701,2701],"valid"],[[2702,2702],"disallowed"],[[2703,2705],"valid"],[[2706,2706],"disallowed"],[[2707,2728],"valid"],[[2729,2729],"disallowed"],[[2730,2736],"valid"],[[2737,2737],"disallowed"],[[2738,2739],"valid"],[[2740,2740],"disallowed"],[[2741,2745],"valid"],[[2746,2747],"disallowed"],[[2748,2757],"valid"],[[2758,2758],"disallowed"],[[2759,2761],"valid"],[[2762,2762],"disallowed"],[[2763,2765],"valid"],[[2766,2767],"disallowed"],[[2768,2768],"valid"],[[2769,2783],"disallowed"],[[2784,2784],"valid"],[[2785,2787],"valid"],[[2788,2789],"disallowed"],[[2790,2799],"valid"],[[2800,2800],"valid",[],"NV8"],[[2801,2801],"valid",[],"NV8"],[[2802,2808],"disallowed"],[[2809,2809],"valid"],[[2810,2816],"disallowed"],[[2817,2819],"valid"],[[2820,2820],"disallowed"],[[2821,2828],"valid"],[[2829,2830],"disallowed"],[[2831,2832],"valid"],[[2833,2834],"disallowed"],[[2835,2856],"valid"],[[2857,2857],"disallowed"],[[2858,2864],"valid"],[[2865,2865],"disallowed"],[[2866,2867],"valid"],[[2868,2868],"disallowed"],[[2869,2869],"valid"],[[2870,2873],"valid"],[[2874,2875],"disallowed"],[[2876,2883],"valid"],[[2884,2884],"valid"],[[2885,2886],"disallowed"],[[2887,2888],"valid"],[[2889,2890],"disallowed"],[[2891,2893],"valid"],[[2894,2901],"disallowed"],[[2902,2903],"valid"],[[2904,2907],"disallowed"],[[2908,2908],"mapped",[2849,2876]],[[2909,2909],"mapped",[2850,2876]],[[2910,2910],"disallowed"],[[2911,2913],"valid"],[[2914,2915],"valid"],[[2916,2917],"disallowed"],[[2918,2927],"valid"],[[2928,2928],"valid",[],"NV8"],[[2929,2929],"valid"],[[2930,2935],"valid",[],"NV8"],[[2936,2945],"disallowed"],[[2946,2947],"valid"],[[2948,2948],"disallowed"],[[2949,2954],"valid"],[[2955,2957],"disallowed"],[[2958,2960],"valid"],[[2961,2961],"disallowed"],[[2962,2965],"valid"],[[2966,2968],"disallowed"],[[2969,2970],"valid"],[[2971,2971],"disallowed"],[[2972,2972],"valid"],[[2973,2973],"disallowed"],[[2974,2975],"valid"],[[2976,2978],"disallowed"],[[2979,2980],"valid"],[[2981,2983],"disallowed"],[[2984,2986],"valid"],[[2987,2989],"disallowed"],[[2990,2997],"valid"],[[2998,2998],"valid"],[[2999,3001],"valid"],[[3002,3005],"disallowed"],[[3006,3010],"valid"],[[3011,3013],"disallowed"],[[3014,3016],"valid"],[[3017,3017],"disallowed"],[[3018,3021],"valid"],[[3022,3023],"disallowed"],[[3024,3024],"valid"],[[3025,3030],"disallowed"],[[3031,3031],"valid"],[[3032,3045],"disallowed"],[[3046,3046],"valid"],[[3047,3055],"valid"],[[3056,3058],"valid",[],"NV8"],[[3059,3066],"valid",[],"NV8"],[[3067,3071],"disallowed"],[[3072,3072],"valid"],[[3073,3075],"valid"],[[3076,3076],"disallowed"],[[3077,3084],"valid"],[[3085,3085],"disallowed"],[[3086,3088],"valid"],[[3089,3089],"disallowed"],[[3090,3112],"valid"],[[3113,3113],"disallowed"],[[3114,3123],"valid"],[[3124,3124],"valid"],[[3125,3129],"valid"],[[3130,3132],"disallowed"],[[3133,3133],"valid"],[[3134,3140],"valid"],[[3141,3141],"disallowed"],[[3142,3144],"valid"],[[3145,3145],"disallowed"],[[3146,3149],"valid"],[[3150,3156],"disallowed"],[[3157,3158],"valid"],[[3159,3159],"disallowed"],[[3160,3161],"valid"],[[3162,3162],"valid"],[[3163,3167],"disallowed"],[[3168,3169],"valid"],[[3170,3171],"valid"],[[3172,3173],"disallowed"],[[3174,3183],"valid"],[[3184,3191],"disallowed"],[[3192,3199],"valid",[],"NV8"],[[3200,3200],"disallowed"],[[3201,3201],"valid"],[[3202,3203],"valid"],[[3204,3204],"disallowed"],[[3205,3212],"valid"],[[3213,3213],"disallowed"],[[3214,3216],"valid"],[[3217,3217],"disallowed"],[[3218,3240],"valid"],[[3241,3241],"disallowed"],[[3242,3251],"valid"],[[3252,3252],"disallowed"],[[3253,3257],"valid"],[[3258,3259],"disallowed"],[[3260,3261],"valid"],[[3262,3268],"valid"],[[3269,3269],"disallowed"],[[3270,3272],"valid"],[[3273,3273],"disallowed"],[[3274,3277],"valid"],[[3278,3284],"disallowed"],[[3285,3286],"valid"],[[3287,3293],"disallowed"],[[3294,3294],"valid"],[[3295,3295],"disallowed"],[[3296,3297],"valid"],[[3298,3299],"valid"],[[3300,3301],"disallowed"],[[3302,3311],"valid"],[[3312,3312],"disallowed"],[[3313,3314],"valid"],[[3315,3328],"disallowed"],[[3329,3329],"valid"],[[3330,3331],"valid"],[[3332,3332],"disallowed"],[[3333,3340],"valid"],[[3341,3341],"disallowed"],[[3342,3344],"valid"],[[3345,3345],"disallowed"],[[3346,3368],"valid"],[[3369,3369],"valid"],[[3370,3385],"valid"],[[3386,3386],"valid"],[[3387,3388],"disallowed"],[[3389,3389],"valid"],[[3390,3395],"valid"],[[3396,3396],"valid"],[[3397,3397],"disallowed"],[[3398,3400],"valid"],[[3401,3401],"disallowed"],[[3402,3405],"valid"],[[3406,3406],"valid"],[[3407,3414],"disallowed"],[[3415,3415],"valid"],[[3416,3422],"disallowed"],[[3423,3423],"valid"],[[3424,3425],"valid"],[[3426,3427],"valid"],[[3428,3429],"disallowed"],[[3430,3439],"valid"],[[3440,3445],"valid",[],"NV8"],[[3446,3448],"disallowed"],[[3449,3449],"valid",[],"NV8"],[[3450,3455],"valid"],[[3456,3457],"disallowed"],[[3458,3459],"valid"],[[3460,3460],"disallowed"],[[3461,3478],"valid"],[[3479,3481],"disallowed"],[[3482,3505],"valid"],[[3506,3506],"disallowed"],[[3507,3515],"valid"],[[3516,3516],"disallowed"],[[3517,3517],"valid"],[[3518,3519],"disallowed"],[[3520,3526],"valid"],[[3527,3529],"disallowed"],[[3530,3530],"valid"],[[3531,3534],"disallowed"],[[3535,3540],"valid"],[[3541,3541],"disallowed"],[[3542,3542],"valid"],[[3543,3543],"disallowed"],[[3544,3551],"valid"],[[3552,3557],"disallowed"],[[3558,3567],"valid"],[[3568,3569],"disallowed"],[[3570,3571],"valid"],[[3572,3572],"valid",[],"NV8"],[[3573,3584],"disallowed"],[[3585,3634],"valid"],[[3635,3635],"mapped",[3661,3634]],[[3636,3642],"valid"],[[3643,3646],"disallowed"],[[3647,3647],"valid",[],"NV8"],[[3648,3662],"valid"],[[3663,3663],"valid",[],"NV8"],[[3664,3673],"valid"],[[3674,3675],"valid",[],"NV8"],[[3676,3712],"disallowed"],[[3713,3714],"valid"],[[3715,3715],"disallowed"],[[3716,3716],"valid"],[[3717,3718],"disallowed"],[[3719,3720],"valid"],[[3721,3721],"disallowed"],[[3722,3722],"valid"],[[3723,3724],"disallowed"],[[3725,3725],"valid"],[[3726,3731],"disallowed"],[[3732,3735],"valid"],[[3736,3736],"disallowed"],[[3737,3743],"valid"],[[3744,3744],"disallowed"],[[3745,3747],"valid"],[[3748,3748],"disallowed"],[[3749,3749],"valid"],[[3750,3750],"disallowed"],[[3751,3751],"valid"],[[3752,3753],"disallowed"],[[3754,3755],"valid"],[[3756,3756],"disallowed"],[[3757,3762],"valid"],[[3763,3763],"mapped",[3789,3762]],[[3764,3769],"valid"],[[3770,3770],"disallowed"],[[3771,3773],"valid"],[[3774,3775],"disallowed"],[[3776,3780],"valid"],[[3781,3781],"disallowed"],[[3782,3782],"valid"],[[3783,3783],"disallowed"],[[3784,3789],"valid"],[[3790,3791],"disallowed"],[[3792,3801],"valid"],[[3802,3803],"disallowed"],[[3804,3804],"mapped",[3755,3737]],[[3805,3805],"mapped",[3755,3745]],[[3806,3807],"valid"],[[3808,3839],"disallowed"],[[3840,3840],"valid"],[[3841,3850],"valid",[],"NV8"],[[3851,3851],"valid"],[[3852,3852],"mapped",[3851]],[[3853,3863],"valid",[],"NV8"],[[3864,3865],"valid"],[[3866,3871],"valid",[],"NV8"],[[3872,3881],"valid"],[[3882,3892],"valid",[],"NV8"],[[3893,3893],"valid"],[[3894,3894],"valid",[],"NV8"],[[3895,3895],"valid"],[[3896,3896],"valid",[],"NV8"],[[3897,3897],"valid"],[[3898,3901],"valid",[],"NV8"],[[3902,3906],"valid"],[[3907,3907],"mapped",[3906,4023]],[[3908,3911],"valid"],[[3912,3912],"disallowed"],[[3913,3916],"valid"],[[3917,3917],"mapped",[3916,4023]],[[3918,3921],"valid"],[[3922,3922],"mapped",[3921,4023]],[[3923,3926],"valid"],[[3927,3927],"mapped",[3926,4023]],[[3928,3931],"valid"],[[3932,3932],"mapped",[3931,4023]],[[3933,3944],"valid"],[[3945,3945],"mapped",[3904,4021]],[[3946,3946],"valid"],[[3947,3948],"valid"],[[3949,3952],"disallowed"],[[3953,3954],"valid"],[[3955,3955],"mapped",[3953,3954]],[[3956,3956],"valid"],[[3957,3957],"mapped",[3953,3956]],[[3958,3958],"mapped",[4018,3968]],[[3959,3959],"mapped",[4018,3953,3968]],[[3960,3960],"mapped",[4019,3968]],[[3961,3961],"mapped",[4019,3953,3968]],[[3962,3968],"valid"],[[3969,3969],"mapped",[3953,3968]],[[3970,3972],"valid"],[[3973,3973],"valid",[],"NV8"],[[3974,3979],"valid"],[[3980,3983],"valid"],[[3984,3986],"valid"],[[3987,3987],"mapped",[3986,4023]],[[3988,3989],"valid"],[[3990,3990],"valid"],[[3991,3991],"valid"],[[3992,3992],"disallowed"],[[3993,3996],"valid"],[[3997,3997],"mapped",[3996,4023]],[[3998,4001],"valid"],[[4002,4002],"mapped",[4001,4023]],[[4003,4006],"valid"],[[4007,4007],"mapped",[4006,4023]],[[4008,4011],"valid"],[[4012,4012],"mapped",[4011,4023]],[[4013,4013],"valid"],[[4014,4016],"valid"],[[4017,4023],"valid"],[[4024,4024],"valid"],[[4025,4025],"mapped",[3984,4021]],[[4026,4028],"valid"],[[4029,4029],"disallowed"],[[4030,4037],"valid",[],"NV8"],[[4038,4038],"valid"],[[4039,4044],"valid",[],"NV8"],[[4045,4045],"disallowed"],[[4046,4046],"valid",[],"NV8"],[[4047,4047],"valid",[],"NV8"],[[4048,4049],"valid",[],"NV8"],[[4050,4052],"valid",[],"NV8"],[[4053,4056],"valid",[],"NV8"],[[4057,4058],"valid",[],"NV8"],[[4059,4095],"disallowed"],[[4096,4129],"valid"],[[4130,4130],"valid"],[[4131,4135],"valid"],[[4136,4136],"valid"],[[4137,4138],"valid"],[[4139,4139],"valid"],[[4140,4146],"valid"],[[4147,4149],"valid"],[[4150,4153],"valid"],[[4154,4159],"valid"],[[4160,4169],"valid"],[[4170,4175],"valid",[],"NV8"],[[4176,4185],"valid"],[[4186,4249],"valid"],[[4250,4253],"valid"],[[4254,4255],"valid",[],"NV8"],[[4256,4293],"disallowed"],[[4294,4294],"disallowed"],[[4295,4295],"mapped",[11559]],[[4296,4300],"disallowed"],[[4301,4301],"mapped",[11565]],[[4302,4303],"disallowed"],[[4304,4342],"valid"],[[4343,4344],"valid"],[[4345,4346],"valid"],[[4347,4347],"valid",[],"NV8"],[[4348,4348],"mapped",[4316]],[[4349,4351],"valid"],[[4352,4441],"valid",[],"NV8"],[[4442,4446],"valid",[],"NV8"],[[4447,4448],"disallowed"],[[4449,4514],"valid",[],"NV8"],[[4515,4519],"valid",[],"NV8"],[[4520,4601],"valid",[],"NV8"],[[4602,4607],"valid",[],"NV8"],[[4608,4614],"valid"],[[4615,4615],"valid"],[[4616,4678],"valid"],[[4679,4679],"valid"],[[4680,4680],"valid"],[[4681,4681],"disallowed"],[[4682,4685],"valid"],[[4686,4687],"disallowed"],[[4688,4694],"valid"],[[4695,4695],"disallowed"],[[4696,4696],"valid"],[[4697,4697],"disallowed"],[[4698,4701],"valid"],[[4702,4703],"disallowed"],[[4704,4742],"valid"],[[4743,4743],"valid"],[[4744,4744],"valid"],[[4745,4745],"disallowed"],[[4746,4749],"valid"],[[4750,4751],"disallowed"],[[4752,4782],"valid"],[[4783,4783],"valid"],[[4784,4784],"valid"],[[4785,4785],"disallowed"],[[4786,4789],"valid"],[[4790,4791],"disallowed"],[[4792,4798],"valid"],[[4799,4799],"disallowed"],[[4800,4800],"valid"],[[4801,4801],"disallowed"],[[4802,4805],"valid"],[[4806,4807],"disallowed"],[[4808,4814],"valid"],[[4815,4815],"valid"],[[4816,4822],"valid"],[[4823,4823],"disallowed"],[[4824,4846],"valid"],[[4847,4847],"valid"],[[4848,4878],"valid"],[[4879,4879],"valid"],[[4880,4880],"valid"],[[4881,4881],"disallowed"],[[4882,4885],"valid"],[[4886,4887],"disallowed"],[[4888,4894],"valid"],[[4895,4895],"valid"],[[4896,4934],"valid"],[[4935,4935],"valid"],[[4936,4954],"valid"],[[4955,4956],"disallowed"],[[4957,4958],"valid"],[[4959,4959],"valid"],[[4960,4960],"valid",[],"NV8"],[[4961,4988],"valid",[],"NV8"],[[4989,4991],"disallowed"],[[4992,5007],"valid"],[[5008,5017],"valid",[],"NV8"],[[5018,5023],"disallowed"],[[5024,5108],"valid"],[[5109,5109],"valid"],[[5110,5111],"disallowed"],[[5112,5112],"mapped",[5104]],[[5113,5113],"mapped",[5105]],[[5114,5114],"mapped",[5106]],[[5115,5115],"mapped",[5107]],[[5116,5116],"mapped",[5108]],[[5117,5117],"mapped",[5109]],[[5118,5119],"disallowed"],[[5120,5120],"valid",[],"NV8"],[[5121,5740],"valid"],[[5741,5742],"valid",[],"NV8"],[[5743,5750],"valid"],[[5751,5759],"valid"],[[5760,5760],"disallowed"],[[5761,5786],"valid"],[[5787,5788],"valid",[],"NV8"],[[5789,5791],"disallowed"],[[5792,5866],"valid"],[[5867,5872],"valid",[],"NV8"],[[5873,5880],"valid"],[[5881,5887],"disallowed"],[[5888,5900],"valid"],[[5901,5901],"disallowed"],[[5902,5908],"valid"],[[5909,5919],"disallowed"],[[5920,5940],"valid"],[[5941,5942],"valid",[],"NV8"],[[5943,5951],"disallowed"],[[5952,5971],"valid"],[[5972,5983],"disallowed"],[[5984,5996],"valid"],[[5997,5997],"disallowed"],[[5998,6000],"valid"],[[6001,6001],"disallowed"],[[6002,6003],"valid"],[[6004,6015],"disallowed"],[[6016,6067],"valid"],[[6068,6069],"disallowed"],[[6070,6099],"valid"],[[6100,6102],"valid",[],"NV8"],[[6103,6103],"valid"],[[6104,6107],"valid",[],"NV8"],[[6108,6108],"valid"],[[6109,6109],"valid"],[[6110,6111],"disallowed"],[[6112,6121],"valid"],[[6122,6127],"disallowed"],[[6128,6137],"valid",[],"NV8"],[[6138,6143],"disallowed"],[[6144,6149],"valid",[],"NV8"],[[6150,6150],"disallowed"],[[6151,6154],"valid",[],"NV8"],[[6155,6157],"ignored"],[[6158,6158],"disallowed"],[[6159,6159],"disallowed"],[[6160,6169],"valid"],[[6170,6175],"disallowed"],[[6176,6263],"valid"],[[6264,6271],"disallowed"],[[6272,6313],"valid"],[[6314,6314],"valid"],[[6315,6319],"disallowed"],[[6320,6389],"valid"],[[6390,6399],"disallowed"],[[6400,6428],"valid"],[[6429,6430],"valid"],[[6431,6431],"disallowed"],[[6432,6443],"valid"],[[6444,6447],"disallowed"],[[6448,6459],"valid"],[[6460,6463],"disallowed"],[[6464,6464],"valid",[],"NV8"],[[6465,6467],"disallowed"],[[6468,6469],"valid",[],"NV8"],[[6470,6509],"valid"],[[6510,6511],"disallowed"],[[6512,6516],"valid"],[[6517,6527],"disallowed"],[[6528,6569],"valid"],[[6570,6571],"valid"],[[6572,6575],"disallowed"],[[6576,6601],"valid"],[[6602,6607],"disallowed"],[[6608,6617],"valid"],[[6618,6618],"valid",[],"XV8"],[[6619,6621],"disallowed"],[[6622,6623],"valid",[],"NV8"],[[6624,6655],"valid",[],"NV8"],[[6656,6683],"valid"],[[6684,6685],"disallowed"],[[6686,6687],"valid",[],"NV8"],[[6688,6750],"valid"],[[6751,6751],"disallowed"],[[6752,6780],"valid"],[[6781,6782],"disallowed"],[[6783,6793],"valid"],[[6794,6799],"disallowed"],[[6800,6809],"valid"],[[6810,6815],"disallowed"],[[6816,6822],"valid",[],"NV8"],[[6823,6823],"valid"],[[6824,6829],"valid",[],"NV8"],[[6830,6831],"disallowed"],[[6832,6845],"valid"],[[6846,6846],"valid",[],"NV8"],[[6847,6911],"disallowed"],[[6912,6987],"valid"],[[6988,6991],"disallowed"],[[6992,7001],"valid"],[[7002,7018],"valid",[],"NV8"],[[7019,7027],"valid"],[[7028,7036],"valid",[],"NV8"],[[7037,7039],"disallowed"],[[7040,7082],"valid"],[[7083,7085],"valid"],[[7086,7097],"valid"],[[7098,7103],"valid"],[[7104,7155],"valid"],[[7156,7163],"disallowed"],[[7164,7167],"valid",[],"NV8"],[[7168,7223],"valid"],[[7224,7226],"disallowed"],[[7227,7231],"valid",[],"NV8"],[[7232,7241],"valid"],[[7242,7244],"disallowed"],[[7245,7293],"valid"],[[7294,7295],"valid",[],"NV8"],[[7296,7359],"disallowed"],[[7360,7367],"valid",[],"NV8"],[[7368,7375],"disallowed"],[[7376,7378],"valid"],[[7379,7379],"valid",[],"NV8"],[[7380,7410],"valid"],[[7411,7414],"valid"],[[7415,7415],"disallowed"],[[7416,7417],"valid"],[[7418,7423],"disallowed"],[[7424,7467],"valid"],[[7468,7468],"mapped",[97]],[[7469,7469],"mapped",[230]],[[7470,7470],"mapped",[98]],[[7471,7471],"valid"],[[7472,7472],"mapped",[100]],[[7473,7473],"mapped",[101]],[[7474,7474],"mapped",[477]],[[7475,7475],"mapped",[103]],[[7476,7476],"mapped",[104]],[[7477,7477],"mapped",[105]],[[7478,7478],"mapped",[106]],[[7479,7479],"mapped",[107]],[[7480,7480],"mapped",[108]],[[7481,7481],"mapped",[109]],[[7482,7482],"mapped",[110]],[[7483,7483],"valid"],[[7484,7484],"mapped",[111]],[[7485,7485],"mapped",[547]],[[7486,7486],"mapped",[112]],[[7487,7487],"mapped",[114]],[[7488,7488],"mapped",[116]],[[7489,7489],"mapped",[117]],[[7490,7490],"mapped",[119]],[[7491,7491],"mapped",[97]],[[7492,7492],"mapped",[592]],[[7493,7493],"mapped",[593]],[[7494,7494],"mapped",[7426]],[[7495,7495],"mapped",[98]],[[7496,7496],"mapped",[100]],[[7497,7497],"mapped",[101]],[[7498,7498],"mapped",[601]],[[7499,7499],"mapped",[603]],[[7500,7500],"mapped",[604]],[[7501,7501],"mapped",[103]],[[7502,7502],"valid"],[[7503,7503],"mapped",[107]],[[7504,7504],"mapped",[109]],[[7505,7505],"mapped",[331]],[[7506,7506],"mapped",[111]],[[7507,7507],"mapped",[596]],[[7508,7508],"mapped",[7446]],[[7509,7509],"mapped",[7447]],[[7510,7510],"mapped",[112]],[[7511,7511],"mapped",[116]],[[7512,7512],"mapped",[117]],[[7513,7513],"mapped",[7453]],[[7514,7514],"mapped",[623]],[[7515,7515],"mapped",[118]],[[7516,7516],"mapped",[7461]],[[7517,7517],"mapped",[946]],[[7518,7518],"mapped",[947]],[[7519,7519],"mapped",[948]],[[7520,7520],"mapped",[966]],[[7521,7521],"mapped",[967]],[[7522,7522],"mapped",[105]],[[7523,7523],"mapped",[114]],[[7524,7524],"mapped",[117]],[[7525,7525],"mapped",[118]],[[7526,7526],"mapped",[946]],[[7527,7527],"mapped",[947]],[[7528,7528],"mapped",[961]],[[7529,7529],"mapped",[966]],[[7530,7530],"mapped",[967]],[[7531,7531],"valid"],[[7532,7543],"valid"],[[7544,7544],"mapped",[1085]],[[7545,7578],"valid"],[[7579,7579],"mapped",[594]],[[7580,7580],"mapped",[99]],[[7581,7581],"mapped",[597]],[[7582,7582],"mapped",[240]],[[7583,7583],"mapped",[604]],[[7584,7584],"mapped",[102]],[[7585,7585],"mapped",[607]],[[7586,7586],"mapped",[609]],[[7587,7587],"mapped",[613]],[[7588,7588],"mapped",[616]],[[7589,7589],"mapped",[617]],[[7590,7590],"mapped",[618]],[[7591,7591],"mapped",[7547]],[[7592,7592],"mapped",[669]],[[7593,7593],"mapped",[621]],[[7594,7594],"mapped",[7557]],[[7595,7595],"mapped",[671]],[[7596,7596],"mapped",[625]],[[7597,7597],"mapped",[624]],[[7598,7598],"mapped",[626]],[[7599,7599],"mapped",[627]],[[7600,7600],"mapped",[628]],[[7601,7601],"mapped",[629]],[[7602,7602],"mapped",[632]],[[7603,7603],"mapped",[642]],[[7604,7604],"mapped",[643]],[[7605,7605],"mapped",[427]],[[7606,7606],"mapped",[649]],[[7607,7607],"mapped",[650]],[[7608,7608],"mapped",[7452]],[[7609,7609],"mapped",[651]],[[7610,7610],"mapped",[652]],[[7611,7611],"mapped",[122]],[[7612,7612],"mapped",[656]],[[7613,7613],"mapped",[657]],[[7614,7614],"mapped",[658]],[[7615,7615],"mapped",[952]],[[7616,7619],"valid"],[[7620,7626],"valid"],[[7627,7654],"valid"],[[7655,7669],"valid"],[[7670,7675],"disallowed"],[[7676,7676],"valid"],[[7677,7677],"valid"],[[7678,7679],"valid"],[[7680,7680],"mapped",[7681]],[[7681,7681],"valid"],[[7682,7682],"mapped",[7683]],[[7683,7683],"valid"],[[7684,7684],"mapped",[7685]],[[7685,7685],"valid"],[[7686,7686],"mapped",[7687]],[[7687,7687],"valid"],[[7688,7688],"mapped",[7689]],[[7689,7689],"valid"],[[7690,7690],"mapped",[7691]],[[7691,7691],"valid"],[[7692,7692],"mapped",[7693]],[[7693,7693],"valid"],[[7694,7694],"mapped",[7695]],[[7695,7695],"valid"],[[7696,7696],"mapped",[7697]],[[7697,7697],"valid"],[[7698,7698],"mapped",[7699]],[[7699,7699],"valid"],[[7700,7700],"mapped",[7701]],[[7701,7701],"valid"],[[7702,7702],"mapped",[7703]],[[7703,7703],"valid"],[[7704,7704],"mapped",[7705]],[[7705,7705],"valid"],[[7706,7706],"mapped",[7707]],[[7707,7707],"valid"],[[7708,7708],"mapped",[7709]],[[7709,7709],"valid"],[[7710,7710],"mapped",[7711]],[[7711,7711],"valid"],[[7712,7712],"mapped",[7713]],[[7713,7713],"valid"],[[7714,7714],"mapped",[7715]],[[7715,7715],"valid"],[[7716,7716],"mapped",[7717]],[[7717,7717],"valid"],[[7718,7718],"mapped",[7719]],[[7719,7719],"valid"],[[7720,7720],"mapped",[7721]],[[7721,7721],"valid"],[[7722,7722],"mapped",[7723]],[[7723,7723],"valid"],[[7724,7724],"mapped",[7725]],[[7725,7725],"valid"],[[7726,7726],"mapped",[7727]],[[7727,7727],"valid"],[[7728,7728],"mapped",[7729]],[[7729,7729],"valid"],[[7730,7730],"mapped",[7731]],[[7731,7731],"valid"],[[7732,7732],"mapped",[7733]],[[7733,7733],"valid"],[[7734,7734],"mapped",[7735]],[[7735,7735],"valid"],[[7736,7736],"mapped",[7737]],[[7737,7737],"valid"],[[7738,7738],"mapped",[7739]],[[7739,7739],"valid"],[[7740,7740],"mapped",[7741]],[[7741,7741],"valid"],[[7742,7742],"mapped",[7743]],[[7743,7743],"valid"],[[7744,7744],"mapped",[7745]],[[7745,7745],"valid"],[[7746,7746],"mapped",[7747]],[[7747,7747],"valid"],[[7748,7748],"mapped",[7749]],[[7749,7749],"valid"],[[7750,7750],"mapped",[7751]],[[7751,7751],"valid"],[[7752,7752],"mapped",[7753]],[[7753,7753],"valid"],[[7754,7754],"mapped",[7755]],[[7755,7755],"valid"],[[7756,7756],"mapped",[7757]],[[7757,7757],"valid"],[[7758,7758],"mapped",[7759]],[[7759,7759],"valid"],[[7760,7760],"mapped",[7761]],[[7761,7761],"valid"],[[7762,7762],"mapped",[7763]],[[7763,7763],"valid"],[[7764,7764],"mapped",[7765]],[[7765,7765],"valid"],[[7766,7766],"mapped",[7767]],[[7767,7767],"valid"],[[7768,7768],"mapped",[7769]],[[7769,7769],"valid"],[[7770,7770],"mapped",[7771]],[[7771,7771],"valid"],[[7772,7772],"mapped",[7773]],[[7773,7773],"valid"],[[7774,7774],"mapped",[7775]],[[7775,7775],"valid"],[[7776,7776],"mapped",[7777]],[[7777,7777],"valid"],[[7778,7778],"mapped",[7779]],[[7779,7779],"valid"],[[7780,7780],"mapped",[7781]],[[7781,7781],"valid"],[[7782,7782],"mapped",[7783]],[[7783,7783],"valid"],[[7784,7784],"mapped",[7785]],[[7785,7785],"valid"],[[7786,7786],"mapped",[7787]],[[7787,7787],"valid"],[[7788,7788],"mapped",[7789]],[[7789,7789],"valid"],[[7790,7790],"mapped",[7791]],[[7791,7791],"valid"],[[7792,7792],"mapped",[7793]],[[7793,7793],"valid"],[[7794,7794],"mapped",[7795]],[[7795,7795],"valid"],[[7796,7796],"mapped",[7797]],[[7797,7797],"valid"],[[7798,7798],"mapped",[7799]],[[7799,7799],"valid"],[[7800,7800],"mapped",[7801]],[[7801,7801],"valid"],[[7802,7802],"mapped",[7803]],[[7803,7803],"valid"],[[7804,7804],"mapped",[7805]],[[7805,7805],"valid"],[[7806,7806],"mapped",[7807]],[[7807,7807],"valid"],[[7808,7808],"mapped",[7809]],[[7809,7809],"valid"],[[7810,7810],"mapped",[7811]],[[7811,7811],"valid"],[[7812,7812],"mapped",[7813]],[[7813,7813],"valid"],[[7814,7814],"mapped",[7815]],[[7815,7815],"valid"],[[7816,7816],"mapped",[7817]],[[7817,7817],"valid"],[[7818,7818],"mapped",[7819]],[[7819,7819],"valid"],[[7820,7820],"mapped",[7821]],[[7821,7821],"valid"],[[7822,7822],"mapped",[7823]],[[7823,7823],"valid"],[[7824,7824],"mapped",[7825]],[[7825,7825],"valid"],[[7826,7826],"mapped",[7827]],[[7827,7827],"valid"],[[7828,7828],"mapped",[7829]],[[7829,7833],"valid"],[[7834,7834],"mapped",[97,702]],[[7835,7835],"mapped",[7777]],[[7836,7837],"valid"],[[7838,7838],"mapped",[115,115]],[[7839,7839],"valid"],[[7840,7840],"mapped",[7841]],[[7841,7841],"valid"],[[7842,7842],"mapped",[7843]],[[7843,7843],"valid"],[[7844,7844],"mapped",[7845]],[[7845,7845],"valid"],[[7846,7846],"mapped",[7847]],[[7847,7847],"valid"],[[7848,7848],"mapped",[7849]],[[7849,7849],"valid"],[[7850,7850],"mapped",[7851]],[[7851,7851],"valid"],[[7852,7852],"mapped",[7853]],[[7853,7853],"valid"],[[7854,7854],"mapped",[7855]],[[7855,7855],"valid"],[[7856,7856],"mapped",[7857]],[[7857,7857],"valid"],[[7858,7858],"mapped",[7859]],[[7859,7859],"valid"],[[7860,7860],"mapped",[7861]],[[7861,7861],"valid"],[[7862,7862],"mapped",[7863]],[[7863,7863],"valid"],[[7864,7864],"mapped",[7865]],[[7865,7865],"valid"],[[7866,7866],"mapped",[7867]],[[7867,7867],"valid"],[[7868,7868],"mapped",[7869]],[[7869,7869],"valid"],[[7870,7870],"mapped",[7871]],[[7871,7871],"valid"],[[7872,7872],"mapped",[7873]],[[7873,7873],"valid"],[[7874,7874],"mapped",[7875]],[[7875,7875],"valid"],[[7876,7876],"mapped",[7877]],[[7877,7877],"valid"],[[7878,7878],"mapped",[7879]],[[7879,7879],"valid"],[[7880,7880],"mapped",[7881]],[[7881,7881],"valid"],[[7882,7882],"mapped",[7883]],[[7883,7883],"valid"],[[7884,7884],"mapped",[7885]],[[7885,7885],"valid"],[[7886,7886],"mapped",[7887]],[[7887,7887],"valid"],[[7888,7888],"mapped",[7889]],[[7889,7889],"valid"],[[7890,7890],"mapped",[7891]],[[7891,7891],"valid"],[[7892,7892],"mapped",[7893]],[[7893,7893],"valid"],[[7894,7894],"mapped",[7895]],[[7895,7895],"valid"],[[7896,7896],"mapped",[7897]],[[7897,7897],"valid"],[[7898,7898],"mapped",[7899]],[[7899,7899],"valid"],[[7900,7900],"mapped",[7901]],[[7901,7901],"valid"],[[7902,7902],"mapped",[7903]],[[7903,7903],"valid"],[[7904,7904],"mapped",[7905]],[[7905,7905],"valid"],[[7906,7906],"mapped",[7907]],[[7907,7907],"valid"],[[7908,7908],"mapped",[7909]],[[7909,7909],"valid"],[[7910,7910],"mapped",[7911]],[[7911,7911],"valid"],[[7912,7912],"mapped",[7913]],[[7913,7913],"valid"],[[7914,7914],"mapped",[7915]],[[7915,7915],"valid"],[[7916,7916],"mapped",[7917]],[[7917,7917],"valid"],[[7918,7918],"mapped",[7919]],[[7919,7919],"valid"],[[7920,7920],"mapped",[7921]],[[7921,7921],"valid"],[[7922,7922],"mapped",[7923]],[[7923,7923],"valid"],[[7924,7924],"mapped",[7925]],[[7925,7925],"valid"],[[7926,7926],"mapped",[7927]],[[7927,7927],"valid"],[[7928,7928],"mapped",[7929]],[[7929,7929],"valid"],[[7930,7930],"mapped",[7931]],[[7931,7931],"valid"],[[7932,7932],"mapped",[7933]],[[7933,7933],"valid"],[[7934,7934],"mapped",[7935]],[[7935,7935],"valid"],[[7936,7943],"valid"],[[7944,7944],"mapped",[7936]],[[7945,7945],"mapped",[7937]],[[7946,7946],"mapped",[7938]],[[7947,7947],"mapped",[7939]],[[7948,7948],"mapped",[7940]],[[7949,7949],"mapped",[7941]],[[7950,7950],"mapped",[7942]],[[7951,7951],"mapped",[7943]],[[7952,7957],"valid"],[[7958,7959],"disallowed"],[[7960,7960],"mapped",[7952]],[[7961,7961],"mapped",[7953]],[[7962,7962],"mapped",[7954]],[[7963,7963],"mapped",[7955]],[[7964,7964],"mapped",[7956]],[[7965,7965],"mapped",[7957]],[[7966,7967],"disallowed"],[[7968,7975],"valid"],[[7976,7976],"mapped",[7968]],[[7977,7977],"mapped",[7969]],[[7978,7978],"mapped",[7970]],[[7979,7979],"mapped",[7971]],[[7980,7980],"mapped",[7972]],[[7981,7981],"mapped",[7973]],[[7982,7982],"mapped",[7974]],[[7983,7983],"mapped",[7975]],[[7984,7991],"valid"],[[7992,7992],"mapped",[7984]],[[7993,7993],"mapped",[7985]],[[7994,7994],"mapped",[7986]],[[7995,7995],"mapped",[7987]],[[7996,7996],"mapped",[7988]],[[7997,7997],"mapped",[7989]],[[7998,7998],"mapped",[7990]],[[7999,7999],"mapped",[7991]],[[8000,8005],"valid"],[[8006,8007],"disallowed"],[[8008,8008],"mapped",[8000]],[[8009,8009],"mapped",[8001]],[[8010,8010],"mapped",[8002]],[[8011,8011],"mapped",[8003]],[[8012,8012],"mapped",[8004]],[[8013,8013],"mapped",[8005]],[[8014,8015],"disallowed"],[[8016,8023],"valid"],[[8024,8024],"disallowed"],[[8025,8025],"mapped",[8017]],[[8026,8026],"disallowed"],[[8027,8027],"mapped",[8019]],[[8028,8028],"disallowed"],[[8029,8029],"mapped",[8021]],[[8030,8030],"disallowed"],[[8031,8031],"mapped",[8023]],[[8032,8039],"valid"],[[8040,8040],"mapped",[8032]],[[8041,8041],"mapped",[8033]],[[8042,8042],"mapped",[8034]],[[8043,8043],"mapped",[8035]],[[8044,8044],"mapped",[8036]],[[8045,8045],"mapped",[8037]],[[8046,8046],"mapped",[8038]],[[8047,8047],"mapped",[8039]],[[8048,8048],"valid"],[[8049,8049],"mapped",[940]],[[8050,8050],"valid"],[[8051,8051],"mapped",[941]],[[8052,8052],"valid"],[[8053,8053],"mapped",[942]],[[8054,8054],"valid"],[[8055,8055],"mapped",[943]],[[8056,8056],"valid"],[[8057,8057],"mapped",[972]],[[8058,8058],"valid"],[[8059,8059],"mapped",[973]],[[8060,8060],"valid"],[[8061,8061],"mapped",[974]],[[8062,8063],"disallowed"],[[8064,8064],"mapped",[7936,953]],[[8065,8065],"mapped",[7937,953]],[[8066,8066],"mapped",[7938,953]],[[8067,8067],"mapped",[7939,953]],[[8068,8068],"mapped",[7940,953]],[[8069,8069],"mapped",[7941,953]],[[8070,8070],"mapped",[7942,953]],[[8071,8071],"mapped",[7943,953]],[[8072,8072],"mapped",[7936,953]],[[8073,8073],"mapped",[7937,953]],[[8074,8074],"mapped",[7938,953]],[[8075,8075],"mapped",[7939,953]],[[8076,8076],"mapped",[7940,953]],[[8077,8077],"mapped",[7941,953]],[[8078,8078],"mapped",[7942,953]],[[8079,8079],"mapped",[7943,953]],[[8080,8080],"mapped",[7968,953]],[[8081,8081],"mapped",[7969,953]],[[8082,8082],"mapped",[7970,953]],[[8083,8083],"mapped",[7971,953]],[[8084,8084],"mapped",[7972,953]],[[8085,8085],"mapped",[7973,953]],[[8086,8086],"mapped",[7974,953]],[[8087,8087],"mapped",[7975,953]],[[8088,8088],"mapped",[7968,953]],[[8089,8089],"mapped",[7969,953]],[[8090,8090],"mapped",[7970,953]],[[8091,8091],"mapped",[7971,953]],[[8092,8092],"mapped",[7972,953]],[[8093,8093],"mapped",[7973,953]],[[8094,8094],"mapped",[7974,953]],[[8095,8095],"mapped",[7975,953]],[[8096,8096],"mapped",[8032,953]],[[8097,8097],"mapped",[8033,953]],[[8098,8098],"mapped",[8034,953]],[[8099,8099],"mapped",[8035,953]],[[8100,8100],"mapped",[8036,953]],[[8101,8101],"mapped",[8037,953]],[[8102,8102],"mapped",[8038,953]],[[8103,8103],"mapped",[8039,953]],[[8104,8104],"mapped",[8032,953]],[[8105,8105],"mapped",[8033,953]],[[8106,8106],"mapped",[8034,953]],[[8107,8107],"mapped",[8035,953]],[[8108,8108],"mapped",[8036,953]],[[8109,8109],"mapped",[8037,953]],[[8110,8110],"mapped",[8038,953]],[[8111,8111],"mapped",[8039,953]],[[8112,8113],"valid"],[[8114,8114],"mapped",[8048,953]],[[8115,8115],"mapped",[945,953]],[[8116,8116],"mapped",[940,953]],[[8117,8117],"disallowed"],[[8118,8118],"valid"],[[8119,8119],"mapped",[8118,953]],[[8120,8120],"mapped",[8112]],[[8121,8121],"mapped",[8113]],[[8122,8122],"mapped",[8048]],[[8123,8123],"mapped",[940]],[[8124,8124],"mapped",[945,953]],[[8125,8125],"disallowed_STD3_mapped",[32,787]],[[8126,8126],"mapped",[953]],[[8127,8127],"disallowed_STD3_mapped",[32,787]],[[8128,8128],"disallowed_STD3_mapped",[32,834]],[[8129,8129],"disallowed_STD3_mapped",[32,776,834]],[[8130,8130],"mapped",[8052,953]],[[8131,8131],"mapped",[951,953]],[[8132,8132],"mapped",[942,953]],[[8133,8133],"disallowed"],[[8134,8134],"valid"],[[8135,8135],"mapped",[8134,953]],[[8136,8136],"mapped",[8050]],[[8137,8137],"mapped",[941]],[[8138,8138],"mapped",[8052]],[[8139,8139],"mapped",[942]],[[8140,8140],"mapped",[951,953]],[[8141,8141],"disallowed_STD3_mapped",[32,787,768]],[[8142,8142],"disallowed_STD3_mapped",[32,787,769]],[[8143,8143],"disallowed_STD3_mapped",[32,787,834]],[[8144,8146],"valid"],[[8147,8147],"mapped",[912]],[[8148,8149],"disallowed"],[[8150,8151],"valid"],[[8152,8152],"mapped",[8144]],[[8153,8153],"mapped",[8145]],[[8154,8154],"mapped",[8054]],[[8155,8155],"mapped",[943]],[[8156,8156],"disallowed"],[[8157,8157],"disallowed_STD3_mapped",[32,788,768]],[[8158,8158],"disallowed_STD3_mapped",[32,788,769]],[[8159,8159],"disallowed_STD3_mapped",[32,788,834]],[[8160,8162],"valid"],[[8163,8163],"mapped",[944]],[[8164,8167],"valid"],[[8168,8168],"mapped",[8160]],[[8169,8169],"mapped",[8161]],[[8170,8170],"mapped",[8058]],[[8171,8171],"mapped",[973]],[[8172,8172],"mapped",[8165]],[[8173,8173],"disallowed_STD3_mapped",[32,776,768]],[[8174,8174],"disallowed_STD3_mapped",[32,776,769]],[[8175,8175],"disallowed_STD3_mapped",[96]],[[8176,8177],"disallowed"],[[8178,8178],"mapped",[8060,953]],[[8179,8179],"mapped",[969,953]],[[8180,8180],"mapped",[974,953]],[[8181,8181],"disallowed"],[[8182,8182],"valid"],[[8183,8183],"mapped",[8182,953]],[[8184,8184],"mapped",[8056]],[[8185,8185],"mapped",[972]],[[8186,8186],"mapped",[8060]],[[8187,8187],"mapped",[974]],[[8188,8188],"mapped",[969,953]],[[8189,8189],"disallowed_STD3_mapped",[32,769]],[[8190,8190],"disallowed_STD3_mapped",[32,788]],[[8191,8191],"disallowed"],[[8192,8202],"disallowed_STD3_mapped",[32]],[[8203,8203],"ignored"],[[8204,8205],"deviation",[]],[[8206,8207],"disallowed"],[[8208,8208],"valid",[],"NV8"],[[8209,8209],"mapped",[8208]],[[8210,8214],"valid",[],"NV8"],[[8215,8215],"disallowed_STD3_mapped",[32,819]],[[8216,8227],"valid",[],"NV8"],[[8228,8230],"disallowed"],[[8231,8231],"valid",[],"NV8"],[[8232,8238],"disallowed"],[[8239,8239],"disallowed_STD3_mapped",[32]],[[8240,8242],"valid",[],"NV8"],[[8243,8243],"mapped",[8242,8242]],[[8244,8244],"mapped",[8242,8242,8242]],[[8245,8245],"valid",[],"NV8"],[[8246,8246],"mapped",[8245,8245]],[[8247,8247],"mapped",[8245,8245,8245]],[[8248,8251],"valid",[],"NV8"],[[8252,8252],"disallowed_STD3_mapped",[33,33]],[[8253,8253],"valid",[],"NV8"],[[8254,8254],"disallowed_STD3_mapped",[32,773]],[[8255,8262],"valid",[],"NV8"],[[8263,8263],"disallowed_STD3_mapped",[63,63]],[[8264,8264],"disallowed_STD3_mapped",[63,33]],[[8265,8265],"disallowed_STD3_mapped",[33,63]],[[8266,8269],"valid",[],"NV8"],[[8270,8274],"valid",[],"NV8"],[[8275,8276],"valid",[],"NV8"],[[8277,8278],"valid",[],"NV8"],[[8279,8279],"mapped",[8242,8242,8242,8242]],[[8280,8286],"valid",[],"NV8"],[[8287,8287],"disallowed_STD3_mapped",[32]],[[8288,8288],"ignored"],[[8289,8291],"disallowed"],[[8292,8292],"ignored"],[[8293,8293],"disallowed"],[[8294,8297],"disallowed"],[[8298,8303],"disallowed"],[[8304,8304],"mapped",[48]],[[8305,8305],"mapped",[105]],[[8306,8307],"disallowed"],[[8308,8308],"mapped",[52]],[[8309,8309],"mapped",[53]],[[8310,8310],"mapped",[54]],[[8311,8311],"mapped",[55]],[[8312,8312],"mapped",[56]],[[8313,8313],"mapped",[57]],[[8314,8314],"disallowed_STD3_mapped",[43]],[[8315,8315],"mapped",[8722]],[[8316,8316],"disallowed_STD3_mapped",[61]],[[8317,8317],"disallowed_STD3_mapped",[40]],[[8318,8318],"disallowed_STD3_mapped",[41]],[[8319,8319],"mapped",[110]],[[8320,8320],"mapped",[48]],[[8321,8321],"mapped",[49]],[[8322,8322],"mapped",[50]],[[8323,8323],"mapped",[51]],[[8324,8324],"mapped",[52]],[[8325,8325],"mapped",[53]],[[8326,8326],"mapped",[54]],[[8327,8327],"mapped",[55]],[[8328,8328],"mapped",[56]],[[8329,8329],"mapped",[57]],[[8330,8330],"disallowed_STD3_mapped",[43]],[[8331,8331],"mapped",[8722]],[[8332,8332],"disallowed_STD3_mapped",[61]],[[8333,8333],"disallowed_STD3_mapped",[40]],[[8334,8334],"disallowed_STD3_mapped",[41]],[[8335,8335],"disallowed"],[[8336,8336],"mapped",[97]],[[8337,8337],"mapped",[101]],[[8338,8338],"mapped",[111]],[[8339,8339],"mapped",[120]],[[8340,8340],"mapped",[601]],[[8341,8341],"mapped",[104]],[[8342,8342],"mapped",[107]],[[8343,8343],"mapped",[108]],[[8344,8344],"mapped",[109]],[[8345,8345],"mapped",[110]],[[8346,8346],"mapped",[112]],[[8347,8347],"mapped",[115]],[[8348,8348],"mapped",[116]],[[8349,8351],"disallowed"],[[8352,8359],"valid",[],"NV8"],[[8360,8360],"mapped",[114,115]],[[8361,8362],"valid",[],"NV8"],[[8363,8363],"valid",[],"NV8"],[[8364,8364],"valid",[],"NV8"],[[8365,8367],"valid",[],"NV8"],[[8368,8369],"valid",[],"NV8"],[[8370,8373],"valid",[],"NV8"],[[8374,8376],"valid",[],"NV8"],[[8377,8377],"valid",[],"NV8"],[[8378,8378],"valid",[],"NV8"],[[8379,8381],"valid",[],"NV8"],[[8382,8382],"valid",[],"NV8"],[[8383,8399],"disallowed"],[[8400,8417],"valid",[],"NV8"],[[8418,8419],"valid",[],"NV8"],[[8420,8426],"valid",[],"NV8"],[[8427,8427],"valid",[],"NV8"],[[8428,8431],"valid",[],"NV8"],[[8432,8432],"valid",[],"NV8"],[[8433,8447],"disallowed"],[[8448,8448],"disallowed_STD3_mapped",[97,47,99]],[[8449,8449],"disallowed_STD3_mapped",[97,47,115]],[[8450,8450],"mapped",[99]],[[8451,8451],"mapped",[176,99]],[[8452,8452],"valid",[],"NV8"],[[8453,8453],"disallowed_STD3_mapped",[99,47,111]],[[8454,8454],"disallowed_STD3_mapped",[99,47,117]],[[8455,8455],"mapped",[603]],[[8456,8456],"valid",[],"NV8"],[[8457,8457],"mapped",[176,102]],[[8458,8458],"mapped",[103]],[[8459,8462],"mapped",[104]],[[8463,8463],"mapped",[295]],[[8464,8465],"mapped",[105]],[[8466,8467],"mapped",[108]],[[8468,8468],"valid",[],"NV8"],[[8469,8469],"mapped",[110]],[[8470,8470],"mapped",[110,111]],[[8471,8472],"valid",[],"NV8"],[[8473,8473],"mapped",[112]],[[8474,8474],"mapped",[113]],[[8475,8477],"mapped",[114]],[[8478,8479],"valid",[],"NV8"],[[8480,8480],"mapped",[115,109]],[[8481,8481],"mapped",[116,101,108]],[[8482,8482],"mapped",[116,109]],[[8483,8483],"valid",[],"NV8"],[[8484,8484],"mapped",[122]],[[8485,8485],"valid",[],"NV8"],[[8486,8486],"mapped",[969]],[[8487,8487],"valid",[],"NV8"],[[8488,8488],"mapped",[122]],[[8489,8489],"valid",[],"NV8"],[[8490,8490],"mapped",[107]],[[8491,8491],"mapped",[229]],[[8492,8492],"mapped",[98]],[[8493,8493],"mapped",[99]],[[8494,8494],"valid",[],"NV8"],[[8495,8496],"mapped",[101]],[[8497,8497],"mapped",[102]],[[8498,8498],"disallowed"],[[8499,8499],"mapped",[109]],[[8500,8500],"mapped",[111]],[[8501,8501],"mapped",[1488]],[[8502,8502],"mapped",[1489]],[[8503,8503],"mapped",[1490]],[[8504,8504],"mapped",[1491]],[[8505,8505],"mapped",[105]],[[8506,8506],"valid",[],"NV8"],[[8507,8507],"mapped",[102,97,120]],[[8508,8508],"mapped",[960]],[[8509,8510],"mapped",[947]],[[8511,8511],"mapped",[960]],[[8512,8512],"mapped",[8721]],[[8513,8516],"valid",[],"NV8"],[[8517,8518],"mapped",[100]],[[8519,8519],"mapped",[101]],[[8520,8520],"mapped",[105]],[[8521,8521],"mapped",[106]],[[8522,8523],"valid",[],"NV8"],[[8524,8524],"valid",[],"NV8"],[[8525,8525],"valid",[],"NV8"],[[8526,8526],"valid"],[[8527,8527],"valid",[],"NV8"],[[8528,8528],"mapped",[49,8260,55]],[[8529,8529],"mapped",[49,8260,57]],[[8530,8530],"mapped",[49,8260,49,48]],[[8531,8531],"mapped",[49,8260,51]],[[8532,8532],"mapped",[50,8260,51]],[[8533,8533],"mapped",[49,8260,53]],[[8534,8534],"mapped",[50,8260,53]],[[8535,8535],"mapped",[51,8260,53]],[[8536,8536],"mapped",[52,8260,53]],[[8537,8537],"mapped",[49,8260,54]],[[8538,8538],"mapped",[53,8260,54]],[[8539,8539],"mapped",[49,8260,56]],[[8540,8540],"mapped",[51,8260,56]],[[8541,8541],"mapped",[53,8260,56]],[[8542,8542],"mapped",[55,8260,56]],[[8543,8543],"mapped",[49,8260]],[[8544,8544],"mapped",[105]],[[8545,8545],"mapped",[105,105]],[[8546,8546],"mapped",[105,105,105]],[[8547,8547],"mapped",[105,118]],[[8548,8548],"mapped",[118]],[[8549,8549],"mapped",[118,105]],[[8550,8550],"mapped",[118,105,105]],[[8551,8551],"mapped",[118,105,105,105]],[[8552,8552],"mapped",[105,120]],[[8553,8553],"mapped",[120]],[[8554,8554],"mapped",[120,105]],[[8555,8555],"mapped",[120,105,105]],[[8556,8556],"mapped",[108]],[[8557,8557],"mapped",[99]],[[8558,8558],"mapped",[100]],[[8559,8559],"mapped",[109]],[[8560,8560],"mapped",[105]],[[8561,8561],"mapped",[105,105]],[[8562,8562],"mapped",[105,105,105]],[[8563,8563],"mapped",[105,118]],[[8564,8564],"mapped",[118]],[[8565,8565],"mapped",[118,105]],[[8566,8566],"mapped",[118,105,105]],[[8567,8567],"mapped",[118,105,105,105]],[[8568,8568],"mapped",[105,120]],[[8569,8569],"mapped",[120]],[[8570,8570],"mapped",[120,105]],[[8571,8571],"mapped",[120,105,105]],[[8572,8572],"mapped",[108]],[[8573,8573],"mapped",[99]],[[8574,8574],"mapped",[100]],[[8575,8575],"mapped",[109]],[[8576,8578],"valid",[],"NV8"],[[8579,8579],"disallowed"],[[8580,8580],"valid"],[[8581,8584],"valid",[],"NV8"],[[8585,8585],"mapped",[48,8260,51]],[[8586,8587],"valid",[],"NV8"],[[8588,8591],"disallowed"],[[8592,8682],"valid",[],"NV8"],[[8683,8691],"valid",[],"NV8"],[[8692,8703],"valid",[],"NV8"],[[8704,8747],"valid",[],"NV8"],[[8748,8748],"mapped",[8747,8747]],[[8749,8749],"mapped",[8747,8747,8747]],[[8750,8750],"valid",[],"NV8"],[[8751,8751],"mapped",[8750,8750]],[[8752,8752],"mapped",[8750,8750,8750]],[[8753,8799],"valid",[],"NV8"],[[8800,8800],"disallowed_STD3_valid"],[[8801,8813],"valid",[],"NV8"],[[8814,8815],"disallowed_STD3_valid"],[[8816,8945],"valid",[],"NV8"],[[8946,8959],"valid",[],"NV8"],[[8960,8960],"valid",[],"NV8"],[[8961,8961],"valid",[],"NV8"],[[8962,9000],"valid",[],"NV8"],[[9001,9001],"mapped",[12296]],[[9002,9002],"mapped",[12297]],[[9003,9082],"valid",[],"NV8"],[[9083,9083],"valid",[],"NV8"],[[9084,9084],"valid",[],"NV8"],[[9085,9114],"valid",[],"NV8"],[[9115,9166],"valid",[],"NV8"],[[9167,9168],"valid",[],"NV8"],[[9169,9179],"valid",[],"NV8"],[[9180,9191],"valid",[],"NV8"],[[9192,9192],"valid",[],"NV8"],[[9193,9203],"valid",[],"NV8"],[[9204,9210],"valid",[],"NV8"],[[9211,9215],"disallowed"],[[9216,9252],"valid",[],"NV8"],[[9253,9254],"valid",[],"NV8"],[[9255,9279],"disallowed"],[[9280,9290],"valid",[],"NV8"],[[9291,9311],"disallowed"],[[9312,9312],"mapped",[49]],[[9313,9313],"mapped",[50]],[[9314,9314],"mapped",[51]],[[9315,9315],"mapped",[52]],[[9316,9316],"mapped",[53]],[[9317,9317],"mapped",[54]],[[9318,9318],"mapped",[55]],[[9319,9319],"mapped",[56]],[[9320,9320],"mapped",[57]],[[9321,9321],"mapped",[49,48]],[[9322,9322],"mapped",[49,49]],[[9323,9323],"mapped",[49,50]],[[9324,9324],"mapped",[49,51]],[[9325,9325],"mapped",[49,52]],[[9326,9326],"mapped",[49,53]],[[9327,9327],"mapped",[49,54]],[[9328,9328],"mapped",[49,55]],[[9329,9329],"mapped",[49,56]],[[9330,9330],"mapped",[49,57]],[[9331,9331],"mapped",[50,48]],[[9332,9332],"disallowed_STD3_mapped",[40,49,41]],[[9333,9333],"disallowed_STD3_mapped",[40,50,41]],[[9334,9334],"disallowed_STD3_mapped",[40,51,41]],[[9335,9335],"disallowed_STD3_mapped",[40,52,41]],[[9336,9336],"disallowed_STD3_mapped",[40,53,41]],[[9337,9337],"disallowed_STD3_mapped",[40,54,41]],[[9338,9338],"disallowed_STD3_mapped",[40,55,41]],[[9339,9339],"disallowed_STD3_mapped",[40,56,41]],[[9340,9340],"disallowed_STD3_mapped",[40,57,41]],[[9341,9341],"disallowed_STD3_mapped",[40,49,48,41]],[[9342,9342],"disallowed_STD3_mapped",[40,49,49,41]],[[9343,9343],"disallowed_STD3_mapped",[40,49,50,41]],[[9344,9344],"disallowed_STD3_mapped",[40,49,51,41]],[[9345,9345],"disallowed_STD3_mapped",[40,49,52,41]],[[9346,9346],"disallowed_STD3_mapped",[40,49,53,41]],[[9347,9347],"disallowed_STD3_mapped",[40,49,54,41]],[[9348,9348],"disallowed_STD3_mapped",[40,49,55,41]],[[9349,9349],"disallowed_STD3_mapped",[40,49,56,41]],[[9350,9350],"disallowed_STD3_mapped",[40,49,57,41]],[[9351,9351],"disallowed_STD3_mapped",[40,50,48,41]],[[9352,9371],"disallowed"],[[9372,9372],"disallowed_STD3_mapped",[40,97,41]],[[9373,9373],"disallowed_STD3_mapped",[40,98,41]],[[9374,9374],"disallowed_STD3_mapped",[40,99,41]],[[9375,9375],"disallowed_STD3_mapped",[40,100,41]],[[9376,9376],"disallowed_STD3_mapped",[40,101,41]],[[9377,9377],"disallowed_STD3_mapped",[40,102,41]],[[9378,9378],"disallowed_STD3_mapped",[40,103,41]],[[9379,9379],"disallowed_STD3_mapped",[40,104,41]],[[9380,9380],"disallowed_STD3_mapped",[40,105,41]],[[9381,9381],"disallowed_STD3_mapped",[40,106,41]],[[9382,9382],"disallowed_STD3_mapped",[40,107,41]],[[9383,9383],"disallowed_STD3_mapped",[40,108,41]],[[9384,9384],"disallowed_STD3_mapped",[40,109,41]],[[9385,9385],"disallowed_STD3_mapped",[40,110,41]],[[9386,9386],"disallowed_STD3_mapped",[40,111,41]],[[9387,9387],"disallowed_STD3_mapped",[40,112,41]],[[9388,9388],"disallowed_STD3_mapped",[40,113,41]],[[9389,9389],"disallowed_STD3_mapped",[40,114,41]],[[9390,9390],"disallowed_STD3_mapped",[40,115,41]],[[9391,9391],"disallowed_STD3_mapped",[40,116,41]],[[9392,9392],"disallowed_STD3_mapped",[40,117,41]],[[9393,9393],"disallowed_STD3_mapped",[40,118,41]],[[9394,9394],"disallowed_STD3_mapped",[40,119,41]],[[9395,9395],"disallowed_STD3_mapped",[40,120,41]],[[9396,9396],"disallowed_STD3_mapped",[40,121,41]],[[9397,9397],"disallowed_STD3_mapped",[40,122,41]],[[9398,9398],"mapped",[97]],[[9399,9399],"mapped",[98]],[[9400,9400],"mapped",[99]],[[9401,9401],"mapped",[100]],[[9402,9402],"mapped",[101]],[[9403,9403],"mapped",[102]],[[9404,9404],"mapped",[103]],[[9405,9405],"mapped",[104]],[[9406,9406],"mapped",[105]],[[9407,9407],"mapped",[106]],[[9408,9408],"mapped",[107]],[[9409,9409],"mapped",[108]],[[9410,9410],"mapped",[109]],[[9411,9411],"mapped",[110]],[[9412,9412],"mapped",[111]],[[9413,9413],"mapped",[112]],[[9414,9414],"mapped",[113]],[[9415,9415],"mapped",[114]],[[9416,9416],"mapped",[115]],[[9417,9417],"mapped",[116]],[[9418,9418],"mapped",[117]],[[9419,9419],"mapped",[118]],[[9420,9420],"mapped",[119]],[[9421,9421],"mapped",[120]],[[9422,9422],"mapped",[121]],[[9423,9423],"mapped",[122]],[[9424,9424],"mapped",[97]],[[9425,9425],"mapped",[98]],[[9426,9426],"mapped",[99]],[[9427,9427],"mapped",[100]],[[9428,9428],"mapped",[101]],[[9429,9429],"mapped",[102]],[[9430,9430],"mapped",[103]],[[9431,9431],"mapped",[104]],[[9432,9432],"mapped",[105]],[[9433,9433],"mapped",[106]],[[9434,9434],"mapped",[107]],[[9435,9435],"mapped",[108]],[[9436,9436],"mapped",[109]],[[9437,9437],"mapped",[110]],[[9438,9438],"mapped",[111]],[[9439,9439],"mapped",[112]],[[9440,9440],"mapped",[113]],[[9441,9441],"mapped",[114]],[[9442,9442],"mapped",[115]],[[9443,9443],"mapped",[116]],[[9444,9444],"mapped",[117]],[[9445,9445],"mapped",[118]],[[9446,9446],"mapped",[119]],[[9447,9447],"mapped",[120]],[[9448,9448],"mapped",[121]],[[9449,9449],"mapped",[122]],[[9450,9450],"mapped",[48]],[[9451,9470],"valid",[],"NV8"],[[9471,9471],"valid",[],"NV8"],[[9472,9621],"valid",[],"NV8"],[[9622,9631],"valid",[],"NV8"],[[9632,9711],"valid",[],"NV8"],[[9712,9719],"valid",[],"NV8"],[[9720,9727],"valid",[],"NV8"],[[9728,9747],"valid",[],"NV8"],[[9748,9749],"valid",[],"NV8"],[[9750,9751],"valid",[],"NV8"],[[9752,9752],"valid",[],"NV8"],[[9753,9753],"valid",[],"NV8"],[[9754,9839],"valid",[],"NV8"],[[9840,9841],"valid",[],"NV8"],[[9842,9853],"valid",[],"NV8"],[[9854,9855],"valid",[],"NV8"],[[9856,9865],"valid",[],"NV8"],[[9866,9873],"valid",[],"NV8"],[[9874,9884],"valid",[],"NV8"],[[9885,9885],"valid",[],"NV8"],[[9886,9887],"valid",[],"NV8"],[[9888,9889],"valid",[],"NV8"],[[9890,9905],"valid",[],"NV8"],[[9906,9906],"valid",[],"NV8"],[[9907,9916],"valid",[],"NV8"],[[9917,9919],"valid",[],"NV8"],[[9920,9923],"valid",[],"NV8"],[[9924,9933],"valid",[],"NV8"],[[9934,9934],"valid",[],"NV8"],[[9935,9953],"valid",[],"NV8"],[[9954,9954],"valid",[],"NV8"],[[9955,9955],"valid",[],"NV8"],[[9956,9959],"valid",[],"NV8"],[[9960,9983],"valid",[],"NV8"],[[9984,9984],"valid",[],"NV8"],[[9985,9988],"valid",[],"NV8"],[[9989,9989],"valid",[],"NV8"],[[9990,9993],"valid",[],"NV8"],[[9994,9995],"valid",[],"NV8"],[[9996,10023],"valid",[],"NV8"],[[10024,10024],"valid",[],"NV8"],[[10025,10059],"valid",[],"NV8"],[[10060,10060],"valid",[],"NV8"],[[10061,10061],"valid",[],"NV8"],[[10062,10062],"valid",[],"NV8"],[[10063,10066],"valid",[],"NV8"],[[10067,10069],"valid",[],"NV8"],[[10070,10070],"valid",[],"NV8"],[[10071,10071],"valid",[],"NV8"],[[10072,10078],"valid",[],"NV8"],[[10079,10080],"valid",[],"NV8"],[[10081,10087],"valid",[],"NV8"],[[10088,10101],"valid",[],"NV8"],[[10102,10132],"valid",[],"NV8"],[[10133,10135],"valid",[],"NV8"],[[10136,10159],"valid",[],"NV8"],[[10160,10160],"valid",[],"NV8"],[[10161,10174],"valid",[],"NV8"],[[10175,10175],"valid",[],"NV8"],[[10176,10182],"valid",[],"NV8"],[[10183,10186],"valid",[],"NV8"],[[10187,10187],"valid",[],"NV8"],[[10188,10188],"valid",[],"NV8"],[[10189,10189],"valid",[],"NV8"],[[10190,10191],"valid",[],"NV8"],[[10192,10219],"valid",[],"NV8"],[[10220,10223],"valid",[],"NV8"],[[10224,10239],"valid",[],"NV8"],[[10240,10495],"valid",[],"NV8"],[[10496,10763],"valid",[],"NV8"],[[10764,10764],"mapped",[8747,8747,8747,8747]],[[10765,10867],"valid",[],"NV8"],[[10868,10868],"disallowed_STD3_mapped",[58,58,61]],[[10869,10869],"disallowed_STD3_mapped",[61,61]],[[10870,10870],"disallowed_STD3_mapped",[61,61,61]],[[10871,10971],"valid",[],"NV8"],[[10972,10972],"mapped",[10973,824]],[[10973,11007],"valid",[],"NV8"],[[11008,11021],"valid",[],"NV8"],[[11022,11027],"valid",[],"NV8"],[[11028,11034],"valid",[],"NV8"],[[11035,11039],"valid",[],"NV8"],[[11040,11043],"valid",[],"NV8"],[[11044,11084],"valid",[],"NV8"],[[11085,11087],"valid",[],"NV8"],[[11088,11092],"valid",[],"NV8"],[[11093,11097],"valid",[],"NV8"],[[11098,11123],"valid",[],"NV8"],[[11124,11125],"disallowed"],[[11126,11157],"valid",[],"NV8"],[[11158,11159],"disallowed"],[[11160,11193],"valid",[],"NV8"],[[11194,11196],"disallowed"],[[11197,11208],"valid",[],"NV8"],[[11209,11209],"disallowed"],[[11210,11217],"valid",[],"NV8"],[[11218,11243],"disallowed"],[[11244,11247],"valid",[],"NV8"],[[11248,11263],"disallowed"],[[11264,11264],"mapped",[11312]],[[11265,11265],"mapped",[11313]],[[11266,11266],"mapped",[11314]],[[11267,11267],"mapped",[11315]],[[11268,11268],"mapped",[11316]],[[11269,11269],"mapped",[11317]],[[11270,11270],"mapped",[11318]],[[11271,11271],"mapped",[11319]],[[11272,11272],"mapped",[11320]],[[11273,11273],"mapped",[11321]],[[11274,11274],"mapped",[11322]],[[11275,11275],"mapped",[11323]],[[11276,11276],"mapped",[11324]],[[11277,11277],"mapped",[11325]],[[11278,11278],"mapped",[11326]],[[11279,11279],"mapped",[11327]],[[11280,11280],"mapped",[11328]],[[11281,11281],"mapped",[11329]],[[11282,11282],"mapped",[11330]],[[11283,11283],"mapped",[11331]],[[11284,11284],"mapped",[11332]],[[11285,11285],"mapped",[11333]],[[11286,11286],"mapped",[11334]],[[11287,11287],"mapped",[11335]],[[11288,11288],"mapped",[11336]],[[11289,11289],"mapped",[11337]],[[11290,11290],"mapped",[11338]],[[11291,11291],"mapped",[11339]],[[11292,11292],"mapped",[11340]],[[11293,11293],"mapped",[11341]],[[11294,11294],"mapped",[11342]],[[11295,11295],"mapped",[11343]],[[11296,11296],"mapped",[11344]],[[11297,11297],"mapped",[11345]],[[11298,11298],"mapped",[11346]],[[11299,11299],"mapped",[11347]],[[11300,11300],"mapped",[11348]],[[11301,11301],"mapped",[11349]],[[11302,11302],"mapped",[11350]],[[11303,11303],"mapped",[11351]],[[11304,11304],"mapped",[11352]],[[11305,11305],"mapped",[11353]],[[11306,11306],"mapped",[11354]],[[11307,11307],"mapped",[11355]],[[11308,11308],"mapped",[11356]],[[11309,11309],"mapped",[11357]],[[11310,11310],"mapped",[11358]],[[11311,11311],"disallowed"],[[11312,11358],"valid"],[[11359,11359],"disallowed"],[[11360,11360],"mapped",[11361]],[[11361,11361],"valid"],[[11362,11362],"mapped",[619]],[[11363,11363],"mapped",[7549]],[[11364,11364],"mapped",[637]],[[11365,11366],"valid"],[[11367,11367],"mapped",[11368]],[[11368,11368],"valid"],[[11369,11369],"mapped",[11370]],[[11370,11370],"valid"],[[11371,11371],"mapped",[11372]],[[11372,11372],"valid"],[[11373,11373],"mapped",[593]],[[11374,11374],"mapped",[625]],[[11375,11375],"mapped",[592]],[[11376,11376],"mapped",[594]],[[11377,11377],"valid"],[[11378,11378],"mapped",[11379]],[[11379,11379],"valid"],[[11380,11380],"valid"],[[11381,11381],"mapped",[11382]],[[11382,11383],"valid"],[[11384,11387],"valid"],[[11388,11388],"mapped",[106]],[[11389,11389],"mapped",[118]],[[11390,11390],"mapped",[575]],[[11391,11391],"mapped",[576]],[[11392,11392],"mapped",[11393]],[[11393,11393],"valid"],[[11394,11394],"mapped",[11395]],[[11395,11395],"valid"],[[11396,11396],"mapped",[11397]],[[11397,11397],"valid"],[[11398,11398],"mapped",[11399]],[[11399,11399],"valid"],[[11400,11400],"mapped",[11401]],[[11401,11401],"valid"],[[11402,11402],"mapped",[11403]],[[11403,11403],"valid"],[[11404,11404],"mapped",[11405]],[[11405,11405],"valid"],[[11406,11406],"mapped",[11407]],[[11407,11407],"valid"],[[11408,11408],"mapped",[11409]],[[11409,11409],"valid"],[[11410,11410],"mapped",[11411]],[[11411,11411],"valid"],[[11412,11412],"mapped",[11413]],[[11413,11413],"valid"],[[11414,11414],"mapped",[11415]],[[11415,11415],"valid"],[[11416,11416],"mapped",[11417]],[[11417,11417],"valid"],[[11418,11418],"mapped",[11419]],[[11419,11419],"valid"],[[11420,11420],"mapped",[11421]],[[11421,11421],"valid"],[[11422,11422],"mapped",[11423]],[[11423,11423],"valid"],[[11424,11424],"mapped",[11425]],[[11425,11425],"valid"],[[11426,11426],"mapped",[11427]],[[11427,11427],"valid"],[[11428,11428],"mapped",[11429]],[[11429,11429],"valid"],[[11430,11430],"mapped",[11431]],[[11431,11431],"valid"],[[11432,11432],"mapped",[11433]],[[11433,11433],"valid"],[[11434,11434],"mapped",[11435]],[[11435,11435],"valid"],[[11436,11436],"mapped",[11437]],[[11437,11437],"valid"],[[11438,11438],"mapped",[11439]],[[11439,11439],"valid"],[[11440,11440],"mapped",[11441]],[[11441,11441],"valid"],[[11442,11442],"mapped",[11443]],[[11443,11443],"valid"],[[11444,11444],"mapped",[11445]],[[11445,11445],"valid"],[[11446,11446],"mapped",[11447]],[[11447,11447],"valid"],[[11448,11448],"mapped",[11449]],[[11449,11449],"valid"],[[11450,11450],"mapped",[11451]],[[11451,11451],"valid"],[[11452,11452],"mapped",[11453]],[[11453,11453],"valid"],[[11454,11454],"mapped",[11455]],[[11455,11455],"valid"],[[11456,11456],"mapped",[11457]],[[11457,11457],"valid"],[[11458,11458],"mapped",[11459]],[[11459,11459],"valid"],[[11460,11460],"mapped",[11461]],[[11461,11461],"valid"],[[11462,11462],"mapped",[11463]],[[11463,11463],"valid"],[[11464,11464],"mapped",[11465]],[[11465,11465],"valid"],[[11466,11466],"mapped",[11467]],[[11467,11467],"valid"],[[11468,11468],"mapped",[11469]],[[11469,11469],"valid"],[[11470,11470],"mapped",[11471]],[[11471,11471],"valid"],[[11472,11472],"mapped",[11473]],[[11473,11473],"valid"],[[11474,11474],"mapped",[11475]],[[11475,11475],"valid"],[[11476,11476],"mapped",[11477]],[[11477,11477],"valid"],[[11478,11478],"mapped",[11479]],[[11479,11479],"valid"],[[11480,11480],"mapped",[11481]],[[11481,11481],"valid"],[[11482,11482],"mapped",[11483]],[[11483,11483],"valid"],[[11484,11484],"mapped",[11485]],[[11485,11485],"valid"],[[11486,11486],"mapped",[11487]],[[11487,11487],"valid"],[[11488,11488],"mapped",[11489]],[[11489,11489],"valid"],[[11490,11490],"mapped",[11491]],[[11491,11492],"valid"],[[11493,11498],"valid",[],"NV8"],[[11499,11499],"mapped",[11500]],[[11500,11500],"valid"],[[11501,11501],"mapped",[11502]],[[11502,11505],"valid"],[[11506,11506],"mapped",[11507]],[[11507,11507],"valid"],[[11508,11512],"disallowed"],[[11513,11519],"valid",[],"NV8"],[[11520,11557],"valid"],[[11558,11558],"disallowed"],[[11559,11559],"valid"],[[11560,11564],"disallowed"],[[11565,11565],"valid"],[[11566,11567],"disallowed"],[[11568,11621],"valid"],[[11622,11623],"valid"],[[11624,11630],"disallowed"],[[11631,11631],"mapped",[11617]],[[11632,11632],"valid",[],"NV8"],[[11633,11646],"disallowed"],[[11647,11647],"valid"],[[11648,11670],"valid"],[[11671,11679],"disallowed"],[[11680,11686],"valid"],[[11687,11687],"disallowed"],[[11688,11694],"valid"],[[11695,11695],"disallowed"],[[11696,11702],"valid"],[[11703,11703],"disallowed"],[[11704,11710],"valid"],[[11711,11711],"disallowed"],[[11712,11718],"valid"],[[11719,11719],"disallowed"],[[11720,11726],"valid"],[[11727,11727],"disallowed"],[[11728,11734],"valid"],[[11735,11735],"disallowed"],[[11736,11742],"valid"],[[11743,11743],"disallowed"],[[11744,11775],"valid"],[[11776,11799],"valid",[],"NV8"],[[11800,11803],"valid",[],"NV8"],[[11804,11805],"valid",[],"NV8"],[[11806,11822],"valid",[],"NV8"],[[11823,11823],"valid"],[[11824,11824],"valid",[],"NV8"],[[11825,11825],"valid",[],"NV8"],[[11826,11835],"valid",[],"NV8"],[[11836,11842],"valid",[],"NV8"],[[11843,11903],"disallowed"],[[11904,11929],"valid",[],"NV8"],[[11930,11930],"disallowed"],[[11931,11934],"valid",[],"NV8"],[[11935,11935],"mapped",[27597]],[[11936,12018],"valid",[],"NV8"],[[12019,12019],"mapped",[40863]],[[12020,12031],"disallowed"],[[12032,12032],"mapped",[19968]],[[12033,12033],"mapped",[20008]],[[12034,12034],"mapped",[20022]],[[12035,12035],"mapped",[20031]],[[12036,12036],"mapped",[20057]],[[12037,12037],"mapped",[20101]],[[12038,12038],"mapped",[20108]],[[12039,12039],"mapped",[20128]],[[12040,12040],"mapped",[20154]],[[12041,12041],"mapped",[20799]],[[12042,12042],"mapped",[20837]],[[12043,12043],"mapped",[20843]],[[12044,12044],"mapped",[20866]],[[12045,12045],"mapped",[20886]],[[12046,12046],"mapped",[20907]],[[12047,12047],"mapped",[20960]],[[12048,12048],"mapped",[20981]],[[12049,12049],"mapped",[20992]],[[12050,12050],"mapped",[21147]],[[12051,12051],"mapped",[21241]],[[12052,12052],"mapped",[21269]],[[12053,12053],"mapped",[21274]],[[12054,12054],"mapped",[21304]],[[12055,12055],"mapped",[21313]],[[12056,12056],"mapped",[21340]],[[12057,12057],"mapped",[21353]],[[12058,12058],"mapped",[21378]],[[12059,12059],"mapped",[21430]],[[12060,12060],"mapped",[21448]],[[12061,12061],"mapped",[21475]],[[12062,12062],"mapped",[22231]],[[12063,12063],"mapped",[22303]],[[12064,12064],"mapped",[22763]],[[12065,12065],"mapped",[22786]],[[12066,12066],"mapped",[22794]],[[12067,12067],"mapped",[22805]],[[12068,12068],"mapped",[22823]],[[12069,12069],"mapped",[22899]],[[12070,12070],"mapped",[23376]],[[12071,12071],"mapped",[23424]],[[12072,12072],"mapped",[23544]],[[12073,12073],"mapped",[23567]],[[12074,12074],"mapped",[23586]],[[12075,12075],"mapped",[23608]],[[12076,12076],"mapped",[23662]],[[12077,12077],"mapped",[23665]],[[12078,12078],"mapped",[24027]],[[12079,12079],"mapped",[24037]],[[12080,12080],"mapped",[24049]],[[12081,12081],"mapped",[24062]],[[12082,12082],"mapped",[24178]],[[12083,12083],"mapped",[24186]],[[12084,12084],"mapped",[24191]],[[12085,12085],"mapped",[24308]],[[12086,12086],"mapped",[24318]],[[12087,12087],"mapped",[24331]],[[12088,12088],"mapped",[24339]],[[12089,12089],"mapped",[24400]],[[12090,12090],"mapped",[24417]],[[12091,12091],"mapped",[24435]],[[12092,12092],"mapped",[24515]],[[12093,12093],"mapped",[25096]],[[12094,12094],"mapped",[25142]],[[12095,12095],"mapped",[25163]],[[12096,12096],"mapped",[25903]],[[12097,12097],"mapped",[25908]],[[12098,12098],"mapped",[25991]],[[12099,12099],"mapped",[26007]],[[12100,12100],"mapped",[26020]],[[12101,12101],"mapped",[26041]],[[12102,12102],"mapped",[26080]],[[12103,12103],"mapped",[26085]],[[12104,12104],"mapped",[26352]],[[12105,12105],"mapped",[26376]],[[12106,12106],"mapped",[26408]],[[12107,12107],"mapped",[27424]],[[12108,12108],"mapped",[27490]],[[12109,12109],"mapped",[27513]],[[12110,12110],"mapped",[27571]],[[12111,12111],"mapped",[27595]],[[12112,12112],"mapped",[27604]],[[12113,12113],"mapped",[27611]],[[12114,12114],"mapped",[27663]],[[12115,12115],"mapped",[27668]],[[12116,12116],"mapped",[27700]],[[12117,12117],"mapped",[28779]],[[12118,12118],"mapped",[29226]],[[12119,12119],"mapped",[29238]],[[12120,12120],"mapped",[29243]],[[12121,12121],"mapped",[29247]],[[12122,12122],"mapped",[29255]],[[12123,12123],"mapped",[29273]],[[12124,12124],"mapped",[29275]],[[12125,12125],"mapped",[29356]],[[12126,12126],"mapped",[29572]],[[12127,12127],"mapped",[29577]],[[12128,12128],"mapped",[29916]],[[12129,12129],"mapped",[29926]],[[12130,12130],"mapped",[29976]],[[12131,12131],"mapped",[29983]],[[12132,12132],"mapped",[29992]],[[12133,12133],"mapped",[30000]],[[12134,12134],"mapped",[30091]],[[12135,12135],"mapped",[30098]],[[12136,12136],"mapped",[30326]],[[12137,12137],"mapped",[30333]],[[12138,12138],"mapped",[30382]],[[12139,12139],"mapped",[30399]],[[12140,12140],"mapped",[30446]],[[12141,12141],"mapped",[30683]],[[12142,12142],"mapped",[30690]],[[12143,12143],"mapped",[30707]],[[12144,12144],"mapped",[31034]],[[12145,12145],"mapped",[31160]],[[12146,12146],"mapped",[31166]],[[12147,12147],"mapped",[31348]],[[12148,12148],"mapped",[31435]],[[12149,12149],"mapped",[31481]],[[12150,12150],"mapped",[31859]],[[12151,12151],"mapped",[31992]],[[12152,12152],"mapped",[32566]],[[12153,12153],"mapped",[32593]],[[12154,12154],"mapped",[32650]],[[12155,12155],"mapped",[32701]],[[12156,12156],"mapped",[32769]],[[12157,12157],"mapped",[32780]],[[12158,12158],"mapped",[32786]],[[12159,12159],"mapped",[32819]],[[12160,12160],"mapped",[32895]],[[12161,12161],"mapped",[32905]],[[12162,12162],"mapped",[33251]],[[12163,12163],"mapped",[33258]],[[12164,12164],"mapped",[33267]],[[12165,12165],"mapped",[33276]],[[12166,12166],"mapped",[33292]],[[12167,12167],"mapped",[33307]],[[12168,12168],"mapped",[33311]],[[12169,12169],"mapped",[33390]],[[12170,12170],"mapped",[33394]],[[12171,12171],"mapped",[33400]],[[12172,12172],"mapped",[34381]],[[12173,12173],"mapped",[34411]],[[12174,12174],"mapped",[34880]],[[12175,12175],"mapped",[34892]],[[12176,12176],"mapped",[34915]],[[12177,12177],"mapped",[35198]],[[12178,12178],"mapped",[35211]],[[12179,12179],"mapped",[35282]],[[12180,12180],"mapped",[35328]],[[12181,12181],"mapped",[35895]],[[12182,12182],"mapped",[35910]],[[12183,12183],"mapped",[35925]],[[12184,12184],"mapped",[35960]],[[12185,12185],"mapped",[35997]],[[12186,12186],"mapped",[36196]],[[12187,12187],"mapped",[36208]],[[12188,12188],"mapped",[36275]],[[12189,12189],"mapped",[36523]],[[12190,12190],"mapped",[36554]],[[12191,12191],"mapped",[36763]],[[12192,12192],"mapped",[36784]],[[12193,12193],"mapped",[36789]],[[12194,12194],"mapped",[37009]],[[12195,12195],"mapped",[37193]],[[12196,12196],"mapped",[37318]],[[12197,12197],"mapped",[37324]],[[12198,12198],"mapped",[37329]],[[12199,12199],"mapped",[38263]],[[12200,12200],"mapped",[38272]],[[12201,12201],"mapped",[38428]],[[12202,12202],"mapped",[38582]],[[12203,12203],"mapped",[38585]],[[12204,12204],"mapped",[38632]],[[12205,12205],"mapped",[38737]],[[12206,12206],"mapped",[38750]],[[12207,12207],"mapped",[38754]],[[12208,12208],"mapped",[38761]],[[12209,12209],"mapped",[38859]],[[12210,12210],"mapped",[38893]],[[12211,12211],"mapped",[38899]],[[12212,12212],"mapped",[38913]],[[12213,12213],"mapped",[39080]],[[12214,12214],"mapped",[39131]],[[12215,12215],"mapped",[39135]],[[12216,12216],"mapped",[39318]],[[12217,12217],"mapped",[39321]],[[12218,12218],"mapped",[39340]],[[12219,12219],"mapped",[39592]],[[12220,12220],"mapped",[39640]],[[12221,12221],"mapped",[39647]],[[12222,12222],"mapped",[39717]],[[12223,12223],"mapped",[39727]],[[12224,12224],"mapped",[39730]],[[12225,12225],"mapped",[39740]],[[12226,12226],"mapped",[39770]],[[12227,12227],"mapped",[40165]],[[12228,12228],"mapped",[40565]],[[12229,12229],"mapped",[40575]],[[12230,12230],"mapped",[40613]],[[12231,12231],"mapped",[40635]],[[12232,12232],"mapped",[40643]],[[12233,12233],"mapped",[40653]],[[12234,12234],"mapped",[40657]],[[12235,12235],"mapped",[40697]],[[12236,12236],"mapped",[40701]],[[12237,12237],"mapped",[40718]],[[12238,12238],"mapped",[40723]],[[12239,12239],"mapped",[40736]],[[12240,12240],"mapped",[40763]],[[12241,12241],"mapped",[40778]],[[12242,12242],"mapped",[40786]],[[12243,12243],"mapped",[40845]],[[12244,12244],"mapped",[40860]],[[12245,12245],"mapped",[40864]],[[12246,12271],"disallowed"],[[12272,12283],"disallowed"],[[12284,12287],"disallowed"],[[12288,12288],"disallowed_STD3_mapped",[32]],[[12289,12289],"valid",[],"NV8"],[[12290,12290],"mapped",[46]],[[12291,12292],"valid",[],"NV8"],[[12293,12295],"valid"],[[12296,12329],"valid",[],"NV8"],[[12330,12333],"valid"],[[12334,12341],"valid",[],"NV8"],[[12342,12342],"mapped",[12306]],[[12343,12343],"valid",[],"NV8"],[[12344,12344],"mapped",[21313]],[[12345,12345],"mapped",[21316]],[[12346,12346],"mapped",[21317]],[[12347,12347],"valid",[],"NV8"],[[12348,12348],"valid"],[[12349,12349],"valid",[],"NV8"],[[12350,12350],"valid",[],"NV8"],[[12351,12351],"valid",[],"NV8"],[[12352,12352],"disallowed"],[[12353,12436],"valid"],[[12437,12438],"valid"],[[12439,12440],"disallowed"],[[12441,12442],"valid"],[[12443,12443],"disallowed_STD3_mapped",[32,12441]],[[12444,12444],"disallowed_STD3_mapped",[32,12442]],[[12445,12446],"valid"],[[12447,12447],"mapped",[12424,12426]],[[12448,12448],"valid",[],"NV8"],[[12449,12542],"valid"],[[12543,12543],"mapped",[12467,12488]],[[12544,12548],"disallowed"],[[12549,12588],"valid"],[[12589,12589],"valid"],[[12590,12592],"disallowed"],[[12593,12593],"mapped",[4352]],[[12594,12594],"mapped",[4353]],[[12595,12595],"mapped",[4522]],[[12596,12596],"mapped",[4354]],[[12597,12597],"mapped",[4524]],[[12598,12598],"mapped",[4525]],[[12599,12599],"mapped",[4355]],[[12600,12600],"mapped",[4356]],[[12601,12601],"mapped",[4357]],[[12602,12602],"mapped",[4528]],[[12603,12603],"mapped",[4529]],[[12604,12604],"mapped",[4530]],[[12605,12605],"mapped",[4531]],[[12606,12606],"mapped",[4532]],[[12607,12607],"mapped",[4533]],[[12608,12608],"mapped",[4378]],[[12609,12609],"mapped",[4358]],[[12610,12610],"mapped",[4359]],[[12611,12611],"mapped",[4360]],[[12612,12612],"mapped",[4385]],[[12613,12613],"mapped",[4361]],[[12614,12614],"mapped",[4362]],[[12615,12615],"mapped",[4363]],[[12616,12616],"mapped",[4364]],[[12617,12617],"mapped",[4365]],[[12618,12618],"mapped",[4366]],[[12619,12619],"mapped",[4367]],[[12620,12620],"mapped",[4368]],[[12621,12621],"mapped",[4369]],[[12622,12622],"mapped",[4370]],[[12623,12623],"mapped",[4449]],[[12624,12624],"mapped",[4450]],[[12625,12625],"mapped",[4451]],[[12626,12626],"mapped",[4452]],[[12627,12627],"mapped",[4453]],[[12628,12628],"mapped",[4454]],[[12629,12629],"mapped",[4455]],[[12630,12630],"mapped",[4456]],[[12631,12631],"mapped",[4457]],[[12632,12632],"mapped",[4458]],[[12633,12633],"mapped",[4459]],[[12634,12634],"mapped",[4460]],[[12635,12635],"mapped",[4461]],[[12636,12636],"mapped",[4462]],[[12637,12637],"mapped",[4463]],[[12638,12638],"mapped",[4464]],[[12639,12639],"mapped",[4465]],[[12640,12640],"mapped",[4466]],[[12641,12641],"mapped",[4467]],[[12642,12642],"mapped",[4468]],[[12643,12643],"mapped",[4469]],[[12644,12644],"disallowed"],[[12645,12645],"mapped",[4372]],[[12646,12646],"mapped",[4373]],[[12647,12647],"mapped",[4551]],[[12648,12648],"mapped",[4552]],[[12649,12649],"mapped",[4556]],[[12650,12650],"mapped",[4558]],[[12651,12651],"mapped",[4563]],[[12652,12652],"mapped",[4567]],[[12653,12653],"mapped",[4569]],[[12654,12654],"mapped",[4380]],[[12655,12655],"mapped",[4573]],[[12656,12656],"mapped",[4575]],[[12657,12657],"mapped",[4381]],[[12658,12658],"mapped",[4382]],[[12659,12659],"mapped",[4384]],[[12660,12660],"mapped",[4386]],[[12661,12661],"mapped",[4387]],[[12662,12662],"mapped",[4391]],[[12663,12663],"mapped",[4393]],[[12664,12664],"mapped",[4395]],[[12665,12665],"mapped",[4396]],[[12666,12666],"mapped",[4397]],[[12667,12667],"mapped",[4398]],[[12668,12668],"mapped",[4399]],[[12669,12669],"mapped",[4402]],[[12670,12670],"mapped",[4406]],[[12671,12671],"mapped",[4416]],[[12672,12672],"mapped",[4423]],[[12673,12673],"mapped",[4428]],[[12674,12674],"mapped",[4593]],[[12675,12675],"mapped",[4594]],[[12676,12676],"mapped",[4439]],[[12677,12677],"mapped",[4440]],[[12678,12678],"mapped",[4441]],[[12679,12679],"mapped",[4484]],[[12680,12680],"mapped",[4485]],[[12681,12681],"mapped",[4488]],[[12682,12682],"mapped",[4497]],[[12683,12683],"mapped",[4498]],[[12684,12684],"mapped",[4500]],[[12685,12685],"mapped",[4510]],[[12686,12686],"mapped",[4513]],[[12687,12687],"disallowed"],[[12688,12689],"valid",[],"NV8"],[[12690,12690],"mapped",[19968]],[[12691,12691],"mapped",[20108]],[[12692,12692],"mapped",[19977]],[[12693,12693],"mapped",[22235]],[[12694,12694],"mapped",[19978]],[[12695,12695],"mapped",[20013]],[[12696,12696],"mapped",[19979]],[[12697,12697],"mapped",[30002]],[[12698,12698],"mapped",[20057]],[[12699,12699],"mapped",[19993]],[[12700,12700],"mapped",[19969]],[[12701,12701],"mapped",[22825]],[[12702,12702],"mapped",[22320]],[[12703,12703],"mapped",[20154]],[[12704,12727],"valid"],[[12728,12730],"valid"],[[12731,12735],"disallowed"],[[12736,12751],"valid",[],"NV8"],[[12752,12771],"valid",[],"NV8"],[[12772,12783],"disallowed"],[[12784,12799],"valid"],[[12800,12800],"disallowed_STD3_mapped",[40,4352,41]],[[12801,12801],"disallowed_STD3_mapped",[40,4354,41]],[[12802,12802],"disallowed_STD3_mapped",[40,4355,41]],[[12803,12803],"disallowed_STD3_mapped",[40,4357,41]],[[12804,12804],"disallowed_STD3_mapped",[40,4358,41]],[[12805,12805],"disallowed_STD3_mapped",[40,4359,41]],[[12806,12806],"disallowed_STD3_mapped",[40,4361,41]],[[12807,12807],"disallowed_STD3_mapped",[40,4363,41]],[[12808,12808],"disallowed_STD3_mapped",[40,4364,41]],[[12809,12809],"disallowed_STD3_mapped",[40,4366,41]],[[12810,12810],"disallowed_STD3_mapped",[40,4367,41]],[[12811,12811],"disallowed_STD3_mapped",[40,4368,41]],[[12812,12812],"disallowed_STD3_mapped",[40,4369,41]],[[12813,12813],"disallowed_STD3_mapped",[40,4370,41]],[[12814,12814],"disallowed_STD3_mapped",[40,44032,41]],[[12815,12815],"disallowed_STD3_mapped",[40,45208,41]],[[12816,12816],"disallowed_STD3_mapped",[40,45796,41]],[[12817,12817],"disallowed_STD3_mapped",[40,46972,41]],[[12818,12818],"disallowed_STD3_mapped",[40,47560,41]],[[12819,12819],"disallowed_STD3_mapped",[40,48148,41]],[[12820,12820],"disallowed_STD3_mapped",[40,49324,41]],[[12821,12821],"disallowed_STD3_mapped",[40,50500,41]],[[12822,12822],"disallowed_STD3_mapped",[40,51088,41]],[[12823,12823],"disallowed_STD3_mapped",[40,52264,41]],[[12824,12824],"disallowed_STD3_mapped",[40,52852,41]],[[12825,12825],"disallowed_STD3_mapped",[40,53440,41]],[[12826,12826],"disallowed_STD3_mapped",[40,54028,41]],[[12827,12827],"disallowed_STD3_mapped",[40,54616,41]],[[12828,12828],"disallowed_STD3_mapped",[40,51452,41]],[[12829,12829],"disallowed_STD3_mapped",[40,50724,51204,41]],[[12830,12830],"disallowed_STD3_mapped",[40,50724,54980,41]],[[12831,12831],"disallowed"],[[12832,12832],"disallowed_STD3_mapped",[40,19968,41]],[[12833,12833],"disallowed_STD3_mapped",[40,20108,41]],[[12834,12834],"disallowed_STD3_mapped",[40,19977,41]],[[12835,12835],"disallowed_STD3_mapped",[40,22235,41]],[[12836,12836],"disallowed_STD3_mapped",[40,20116,41]],[[12837,12837],"disallowed_STD3_mapped",[40,20845,41]],[[12838,12838],"disallowed_STD3_mapped",[40,19971,41]],[[12839,12839],"disallowed_STD3_mapped",[40,20843,41]],[[12840,12840],"disallowed_STD3_mapped",[40,20061,41]],[[12841,12841],"disallowed_STD3_mapped",[40,21313,41]],[[12842,12842],"disallowed_STD3_mapped",[40,26376,41]],[[12843,12843],"disallowed_STD3_mapped",[40,28779,41]],[[12844,12844],"disallowed_STD3_mapped",[40,27700,41]],[[12845,12845],"disallowed_STD3_mapped",[40,26408,41]],[[12846,12846],"disallowed_STD3_mapped",[40,37329,41]],[[12847,12847],"disallowed_STD3_mapped",[40,22303,41]],[[12848,12848],"disallowed_STD3_mapped",[40,26085,41]],[[12849,12849],"disallowed_STD3_mapped",[40,26666,41]],[[12850,12850],"disallowed_STD3_mapped",[40,26377,41]],[[12851,12851],"disallowed_STD3_mapped",[40,31038,41]],[[12852,12852],"disallowed_STD3_mapped",[40,21517,41]],[[12853,12853],"disallowed_STD3_mapped",[40,29305,41]],[[12854,12854],"disallowed_STD3_mapped",[40,36001,41]],[[12855,12855],"disallowed_STD3_mapped",[40,31069,41]],[[12856,12856],"disallowed_STD3_mapped",[40,21172,41]],[[12857,12857],"disallowed_STD3_mapped",[40,20195,41]],[[12858,12858],"disallowed_STD3_mapped",[40,21628,41]],[[12859,12859],"disallowed_STD3_mapped",[40,23398,41]],[[12860,12860],"disallowed_STD3_mapped",[40,30435,41]],[[12861,12861],"disallowed_STD3_mapped",[40,20225,41]],[[12862,12862],"disallowed_STD3_mapped",[40,36039,41]],[[12863,12863],"disallowed_STD3_mapped",[40,21332,41]],[[12864,12864],"disallowed_STD3_mapped",[40,31085,41]],[[12865,12865],"disallowed_STD3_mapped",[40,20241,41]],[[12866,12866],"disallowed_STD3_mapped",[40,33258,41]],[[12867,12867],"disallowed_STD3_mapped",[40,33267,41]],[[12868,12868],"mapped",[21839]],[[12869,12869],"mapped",[24188]],[[12870,12870],"mapped",[25991]],[[12871,12871],"mapped",[31631]],[[12872,12879],"valid",[],"NV8"],[[12880,12880],"mapped",[112,116,101]],[[12881,12881],"mapped",[50,49]],[[12882,12882],"mapped",[50,50]],[[12883,12883],"mapped",[50,51]],[[12884,12884],"mapped",[50,52]],[[12885,12885],"mapped",[50,53]],[[12886,12886],"mapped",[50,54]],[[12887,12887],"mapped",[50,55]],[[12888,12888],"mapped",[50,56]],[[12889,12889],"mapped",[50,57]],[[12890,12890],"mapped",[51,48]],[[12891,12891],"mapped",[51,49]],[[12892,12892],"mapped",[51,50]],[[12893,12893],"mapped",[51,51]],[[12894,12894],"mapped",[51,52]],[[12895,12895],"mapped",[51,53]],[[12896,12896],"mapped",[4352]],[[12897,12897],"mapped",[4354]],[[12898,12898],"mapped",[4355]],[[12899,12899],"mapped",[4357]],[[12900,12900],"mapped",[4358]],[[12901,12901],"mapped",[4359]],[[12902,12902],"mapped",[4361]],[[12903,12903],"mapped",[4363]],[[12904,12904],"mapped",[4364]],[[12905,12905],"mapped",[4366]],[[12906,12906],"mapped",[4367]],[[12907,12907],"mapped",[4368]],[[12908,12908],"mapped",[4369]],[[12909,12909],"mapped",[4370]],[[12910,12910],"mapped",[44032]],[[12911,12911],"mapped",[45208]],[[12912,12912],"mapped",[45796]],[[12913,12913],"mapped",[46972]],[[12914,12914],"mapped",[47560]],[[12915,12915],"mapped",[48148]],[[12916,12916],"mapped",[49324]],[[12917,12917],"mapped",[50500]],[[12918,12918],"mapped",[51088]],[[12919,12919],"mapped",[52264]],[[12920,12920],"mapped",[52852]],[[12921,12921],"mapped",[53440]],[[12922,12922],"mapped",[54028]],[[12923,12923],"mapped",[54616]],[[12924,12924],"mapped",[52280,44256]],[[12925,12925],"mapped",[51452,51032]],[[12926,12926],"mapped",[50864]],[[12927,12927],"valid",[],"NV8"],[[12928,12928],"mapped",[19968]],[[12929,12929],"mapped",[20108]],[[12930,12930],"mapped",[19977]],[[12931,12931],"mapped",[22235]],[[12932,12932],"mapped",[20116]],[[12933,12933],"mapped",[20845]],[[12934,12934],"mapped",[19971]],[[12935,12935],"mapped",[20843]],[[12936,12936],"mapped",[20061]],[[12937,12937],"mapped",[21313]],[[12938,12938],"mapped",[26376]],[[12939,12939],"mapped",[28779]],[[12940,12940],"mapped",[27700]],[[12941,12941],"mapped",[26408]],[[12942,12942],"mapped",[37329]],[[12943,12943],"mapped",[22303]],[[12944,12944],"mapped",[26085]],[[12945,12945],"mapped",[26666]],[[12946,12946],"mapped",[26377]],[[12947,12947],"mapped",[31038]],[[12948,12948],"mapped",[21517]],[[12949,12949],"mapped",[29305]],[[12950,12950],"mapped",[36001]],[[12951,12951],"mapped",[31069]],[[12952,12952],"mapped",[21172]],[[12953,12953],"mapped",[31192]],[[12954,12954],"mapped",[30007]],[[12955,12955],"mapped",[22899]],[[12956,12956],"mapped",[36969]],[[12957,12957],"mapped",[20778]],[[12958,12958],"mapped",[21360]],[[12959,12959],"mapped",[27880]],[[12960,12960],"mapped",[38917]],[[12961,12961],"mapped",[20241]],[[12962,12962],"mapped",[20889]],[[12963,12963],"mapped",[27491]],[[12964,12964],"mapped",[19978]],[[12965,12965],"mapped",[20013]],[[12966,12966],"mapped",[19979]],[[12967,12967],"mapped",[24038]],[[12968,12968],"mapped",[21491]],[[12969,12969],"mapped",[21307]],[[12970,12970],"mapped",[23447]],[[12971,12971],"mapped",[23398]],[[12972,12972],"mapped",[30435]],[[12973,12973],"mapped",[20225]],[[12974,12974],"mapped",[36039]],[[12975,12975],"mapped",[21332]],[[12976,12976],"mapped",[22812]],[[12977,12977],"mapped",[51,54]],[[12978,12978],"mapped",[51,55]],[[12979,12979],"mapped",[51,56]],[[12980,12980],"mapped",[51,57]],[[12981,12981],"mapped",[52,48]],[[12982,12982],"mapped",[52,49]],[[12983,12983],"mapped",[52,50]],[[12984,12984],"mapped",[52,51]],[[12985,12985],"mapped",[52,52]],[[12986,12986],"mapped",[52,53]],[[12987,12987],"mapped",[52,54]],[[12988,12988],"mapped",[52,55]],[[12989,12989],"mapped",[52,56]],[[12990,12990],"mapped",[52,57]],[[12991,12991],"mapped",[53,48]],[[12992,12992],"mapped",[49,26376]],[[12993,12993],"mapped",[50,26376]],[[12994,12994],"mapped",[51,26376]],[[12995,12995],"mapped",[52,26376]],[[12996,12996],"mapped",[53,26376]],[[12997,12997],"mapped",[54,26376]],[[12998,12998],"mapped",[55,26376]],[[12999,12999],"mapped",[56,26376]],[[13000,13000],"mapped",[57,26376]],[[13001,13001],"mapped",[49,48,26376]],[[13002,13002],"mapped",[49,49,26376]],[[13003,13003],"mapped",[49,50,26376]],[[13004,13004],"mapped",[104,103]],[[13005,13005],"mapped",[101,114,103]],[[13006,13006],"mapped",[101,118]],[[13007,13007],"mapped",[108,116,100]],[[13008,13008],"mapped",[12450]],[[13009,13009],"mapped",[12452]],[[13010,13010],"mapped",[12454]],[[13011,13011],"mapped",[12456]],[[13012,13012],"mapped",[12458]],[[13013,13013],"mapped",[12459]],[[13014,13014],"mapped",[12461]],[[13015,13015],"mapped",[12463]],[[13016,13016],"mapped",[12465]],[[13017,13017],"mapped",[12467]],[[13018,13018],"mapped",[12469]],[[13019,13019],"mapped",[12471]],[[13020,13020],"mapped",[12473]],[[13021,13021],"mapped",[12475]],[[13022,13022],"mapped",[12477]],[[13023,13023],"mapped",[12479]],[[13024,13024],"mapped",[12481]],[[13025,13025],"mapped",[12484]],[[13026,13026],"mapped",[12486]],[[13027,13027],"mapped",[12488]],[[13028,13028],"mapped",[12490]],[[13029,13029],"mapped",[12491]],[[13030,13030],"mapped",[12492]],[[13031,13031],"mapped",[12493]],[[13032,13032],"mapped",[12494]],[[13033,13033],"mapped",[12495]],[[13034,13034],"mapped",[12498]],[[13035,13035],"mapped",[12501]],[[13036,13036],"mapped",[12504]],[[13037,13037],"mapped",[12507]],[[13038,13038],"mapped",[12510]],[[13039,13039],"mapped",[12511]],[[13040,13040],"mapped",[12512]],[[13041,13041],"mapped",[12513]],[[13042,13042],"mapped",[12514]],[[13043,13043],"mapped",[12516]],[[13044,13044],"mapped",[12518]],[[13045,13045],"mapped",[12520]],[[13046,13046],"mapped",[12521]],[[13047,13047],"mapped",[12522]],[[13048,13048],"mapped",[12523]],[[13049,13049],"mapped",[12524]],[[13050,13050],"mapped",[12525]],[[13051,13051],"mapped",[12527]],[[13052,13052],"mapped",[12528]],[[13053,13053],"mapped",[12529]],[[13054,13054],"mapped",[12530]],[[13055,13055],"disallowed"],[[13056,13056],"mapped",[12450,12497,12540,12488]],[[13057,13057],"mapped",[12450,12523,12501,12449]],[[13058,13058],"mapped",[12450,12531,12506,12450]],[[13059,13059],"mapped",[12450,12540,12523]],[[13060,13060],"mapped",[12452,12491,12531,12464]],[[13061,13061],"mapped",[12452,12531,12481]],[[13062,13062],"mapped",[12454,12457,12531]],[[13063,13063],"mapped",[12456,12473,12463,12540,12489]],[[13064,13064],"mapped",[12456,12540,12459,12540]],[[13065,13065],"mapped",[12458,12531,12473]],[[13066,13066],"mapped",[12458,12540,12512]],[[13067,13067],"mapped",[12459,12452,12522]],[[13068,13068],"mapped",[12459,12521,12483,12488]],[[13069,13069],"mapped",[12459,12525,12522,12540]],[[13070,13070],"mapped",[12460,12525,12531]],[[13071,13071],"mapped",[12460,12531,12510]],[[13072,13072],"mapped",[12462,12460]],[[13073,13073],"mapped",[12462,12491,12540]],[[13074,13074],"mapped",[12461,12517,12522,12540]],[[13075,13075],"mapped",[12462,12523,12480,12540]],[[13076,13076],"mapped",[12461,12525]],[[13077,13077],"mapped",[12461,12525,12464,12521,12512]],[[13078,13078],"mapped",[12461,12525,12513,12540,12488,12523]],[[13079,13079],"mapped",[12461,12525,12527,12483,12488]],[[13080,13080],"mapped",[12464,12521,12512]],[[13081,13081],"mapped",[12464,12521,12512,12488,12531]],[[13082,13082],"mapped",[12463,12523,12476,12452,12525]],[[13083,13083],"mapped",[12463,12525,12540,12493]],[[13084,13084],"mapped",[12465,12540,12473]],[[13085,13085],"mapped",[12467,12523,12490]],[[13086,13086],"mapped",[12467,12540,12509]],[[13087,13087],"mapped",[12469,12452,12463,12523]],[[13088,13088],"mapped",[12469,12531,12481,12540,12512]],[[13089,13089],"mapped",[12471,12522,12531,12464]],[[13090,13090],"mapped",[12475,12531,12481]],[[13091,13091],"mapped",[12475,12531,12488]],[[13092,13092],"mapped",[12480,12540,12473]],[[13093,13093],"mapped",[12487,12471]],[[13094,13094],"mapped",[12489,12523]],[[13095,13095],"mapped",[12488,12531]],[[13096,13096],"mapped",[12490,12494]],[[13097,13097],"mapped",[12494,12483,12488]],[[13098,13098],"mapped",[12495,12452,12484]],[[13099,13099],"mapped",[12497,12540,12475,12531,12488]],[[13100,13100],"mapped",[12497,12540,12484]],[[13101,13101],"mapped",[12496,12540,12524,12523]],[[13102,13102],"mapped",[12500,12450,12473,12488,12523]],[[13103,13103],"mapped",[12500,12463,12523]],[[13104,13104],"mapped",[12500,12467]],[[13105,13105],"mapped",[12499,12523]],[[13106,13106],"mapped",[12501,12449,12521,12483,12489]],[[13107,13107],"mapped",[12501,12451,12540,12488]],[[13108,13108],"mapped",[12502,12483,12471,12455,12523]],[[13109,13109],"mapped",[12501,12521,12531]],[[13110,13110],"mapped",[12504,12463,12479,12540,12523]],[[13111,13111],"mapped",[12506,12477]],[[13112,13112],"mapped",[12506,12491,12498]],[[13113,13113],"mapped",[12504,12523,12484]],[[13114,13114],"mapped",[12506,12531,12473]],[[13115,13115],"mapped",[12506,12540,12472]],[[13116,13116],"mapped",[12505,12540,12479]],[[13117,13117],"mapped",[12509,12452,12531,12488]],[[13118,13118],"mapped",[12508,12523,12488]],[[13119,13119],"mapped",[12507,12531]],[[13120,13120],"mapped",[12509,12531,12489]],[[13121,13121],"mapped",[12507,12540,12523]],[[13122,13122],"mapped",[12507,12540,12531]],[[13123,13123],"mapped",[12510,12452,12463,12525]],[[13124,13124],"mapped",[12510,12452,12523]],[[13125,13125],"mapped",[12510,12483,12495]],[[13126,13126],"mapped",[12510,12523,12463]],[[13127,13127],"mapped",[12510,12531,12471,12519,12531]],[[13128,13128],"mapped",[12511,12463,12525,12531]],[[13129,13129],"mapped",[12511,12522]],[[13130,13130],"mapped",[12511,12522,12496,12540,12523]],[[13131,13131],"mapped",[12513,12460]],[[13132,13132],"mapped",[12513,12460,12488,12531]],[[13133,13133],"mapped",[12513,12540,12488,12523]],[[13134,13134],"mapped",[12516,12540,12489]],[[13135,13135],"mapped",[12516,12540,12523]],[[13136,13136],"mapped",[12518,12450,12531]],[[13137,13137],"mapped",[12522,12483,12488,12523]],[[13138,13138],"mapped",[12522,12521]],[[13139,13139],"mapped",[12523,12500,12540]],[[13140,13140],"mapped",[12523,12540,12502,12523]],[[13141,13141],"mapped",[12524,12512]],[[13142,13142],"mapped",[12524,12531,12488,12466,12531]],[[13143,13143],"mapped",[12527,12483,12488]],[[13144,13144],"mapped",[48,28857]],[[13145,13145],"mapped",[49,28857]],[[13146,13146],"mapped",[50,28857]],[[13147,13147],"mapped",[51,28857]],[[13148,13148],"mapped",[52,28857]],[[13149,13149],"mapped",[53,28857]],[[13150,13150],"mapped",[54,28857]],[[13151,13151],"mapped",[55,28857]],[[13152,13152],"mapped",[56,28857]],[[13153,13153],"mapped",[57,28857]],[[13154,13154],"mapped",[49,48,28857]],[[13155,13155],"mapped",[49,49,28857]],[[13156,13156],"mapped",[49,50,28857]],[[13157,13157],"mapped",[49,51,28857]],[[13158,13158],"mapped",[49,52,28857]],[[13159,13159],"mapped",[49,53,28857]],[[13160,13160],"mapped",[49,54,28857]],[[13161,13161],"mapped",[49,55,28857]],[[13162,13162],"mapped",[49,56,28857]],[[13163,13163],"mapped",[49,57,28857]],[[13164,13164],"mapped",[50,48,28857]],[[13165,13165],"mapped",[50,49,28857]],[[13166,13166],"mapped",[50,50,28857]],[[13167,13167],"mapped",[50,51,28857]],[[13168,13168],"mapped",[50,52,28857]],[[13169,13169],"mapped",[104,112,97]],[[13170,13170],"mapped",[100,97]],[[13171,13171],"mapped",[97,117]],[[13172,13172],"mapped",[98,97,114]],[[13173,13173],"mapped",[111,118]],[[13174,13174],"mapped",[112,99]],[[13175,13175],"mapped",[100,109]],[[13176,13176],"mapped",[100,109,50]],[[13177,13177],"mapped",[100,109,51]],[[13178,13178],"mapped",[105,117]],[[13179,13179],"mapped",[24179,25104]],[[13180,13180],"mapped",[26157,21644]],[[13181,13181],"mapped",[22823,27491]],[[13182,13182],"mapped",[26126,27835]],[[13183,13183],"mapped",[26666,24335,20250,31038]],[[13184,13184],"mapped",[112,97]],[[13185,13185],"mapped",[110,97]],[[13186,13186],"mapped",[956,97]],[[13187,13187],"mapped",[109,97]],[[13188,13188],"mapped",[107,97]],[[13189,13189],"mapped",[107,98]],[[13190,13190],"mapped",[109,98]],[[13191,13191],"mapped",[103,98]],[[13192,13192],"mapped",[99,97,108]],[[13193,13193],"mapped",[107,99,97,108]],[[13194,13194],"mapped",[112,102]],[[13195,13195],"mapped",[110,102]],[[13196,13196],"mapped",[956,102]],[[13197,13197],"mapped",[956,103]],[[13198,13198],"mapped",[109,103]],[[13199,13199],"mapped",[107,103]],[[13200,13200],"mapped",[104,122]],[[13201,13201],"mapped",[107,104,122]],[[13202,13202],"mapped",[109,104,122]],[[13203,13203],"mapped",[103,104,122]],[[13204,13204],"mapped",[116,104,122]],[[13205,13205],"mapped",[956,108]],[[13206,13206],"mapped",[109,108]],[[13207,13207],"mapped",[100,108]],[[13208,13208],"mapped",[107,108]],[[13209,13209],"mapped",[102,109]],[[13210,13210],"mapped",[110,109]],[[13211,13211],"mapped",[956,109]],[[13212,13212],"mapped",[109,109]],[[13213,13213],"mapped",[99,109]],[[13214,13214],"mapped",[107,109]],[[13215,13215],"mapped",[109,109,50]],[[13216,13216],"mapped",[99,109,50]],[[13217,13217],"mapped",[109,50]],[[13218,13218],"mapped",[107,109,50]],[[13219,13219],"mapped",[109,109,51]],[[13220,13220],"mapped",[99,109,51]],[[13221,13221],"mapped",[109,51]],[[13222,13222],"mapped",[107,109,51]],[[13223,13223],"mapped",[109,8725,115]],[[13224,13224],"mapped",[109,8725,115,50]],[[13225,13225],"mapped",[112,97]],[[13226,13226],"mapped",[107,112,97]],[[13227,13227],"mapped",[109,112,97]],[[13228,13228],"mapped",[103,112,97]],[[13229,13229],"mapped",[114,97,100]],[[13230,13230],"mapped",[114,97,100,8725,115]],[[13231,13231],"mapped",[114,97,100,8725,115,50]],[[13232,13232],"mapped",[112,115]],[[13233,13233],"mapped",[110,115]],[[13234,13234],"mapped",[956,115]],[[13235,13235],"mapped",[109,115]],[[13236,13236],"mapped",[112,118]],[[13237,13237],"mapped",[110,118]],[[13238,13238],"mapped",[956,118]],[[13239,13239],"mapped",[109,118]],[[13240,13240],"mapped",[107,118]],[[13241,13241],"mapped",[109,118]],[[13242,13242],"mapped",[112,119]],[[13243,13243],"mapped",[110,119]],[[13244,13244],"mapped",[956,119]],[[13245,13245],"mapped",[109,119]],[[13246,13246],"mapped",[107,119]],[[13247,13247],"mapped",[109,119]],[[13248,13248],"mapped",[107,969]],[[13249,13249],"mapped",[109,969]],[[13250,13250],"disallowed"],[[13251,13251],"mapped",[98,113]],[[13252,13252],"mapped",[99,99]],[[13253,13253],"mapped",[99,100]],[[13254,13254],"mapped",[99,8725,107,103]],[[13255,13255],"disallowed"],[[13256,13256],"mapped",[100,98]],[[13257,13257],"mapped",[103,121]],[[13258,13258],"mapped",[104,97]],[[13259,13259],"mapped",[104,112]],[[13260,13260],"mapped",[105,110]],[[13261,13261],"mapped",[107,107]],[[13262,13262],"mapped",[107,109]],[[13263,13263],"mapped",[107,116]],[[13264,13264],"mapped",[108,109]],[[13265,13265],"mapped",[108,110]],[[13266,13266],"mapped",[108,111,103]],[[13267,13267],"mapped",[108,120]],[[13268,13268],"mapped",[109,98]],[[13269,13269],"mapped",[109,105,108]],[[13270,13270],"mapped",[109,111,108]],[[13271,13271],"mapped",[112,104]],[[13272,13272],"disallowed"],[[13273,13273],"mapped",[112,112,109]],[[13274,13274],"mapped",[112,114]],[[13275,13275],"mapped",[115,114]],[[13276,13276],"mapped",[115,118]],[[13277,13277],"mapped",[119,98]],[[13278,13278],"mapped",[118,8725,109]],[[13279,13279],"mapped",[97,8725,109]],[[13280,13280],"mapped",[49,26085]],[[13281,13281],"mapped",[50,26085]],[[13282,13282],"mapped",[51,26085]],[[13283,13283],"mapped",[52,26085]],[[13284,13284],"mapped",[53,26085]],[[13285,13285],"mapped",[54,26085]],[[13286,13286],"mapped",[55,26085]],[[13287,13287],"mapped",[56,26085]],[[13288,13288],"mapped",[57,26085]],[[13289,13289],"mapped",[49,48,26085]],[[13290,13290],"mapped",[49,49,26085]],[[13291,13291],"mapped",[49,50,26085]],[[13292,13292],"mapped",[49,51,26085]],[[13293,13293],"mapped",[49,52,26085]],[[13294,13294],"mapped",[49,53,26085]],[[13295,13295],"mapped",[49,54,26085]],[[13296,13296],"mapped",[49,55,26085]],[[13297,13297],"mapped",[49,56,26085]],[[13298,13298],"mapped",[49,57,26085]],[[13299,13299],"mapped",[50,48,26085]],[[13300,13300],"mapped",[50,49,26085]],[[13301,13301],"mapped",[50,50,26085]],[[13302,13302],"mapped",[50,51,26085]],[[13303,13303],"mapped",[50,52,26085]],[[13304,13304],"mapped",[50,53,26085]],[[13305,13305],"mapped",[50,54,26085]],[[13306,13306],"mapped",[50,55,26085]],[[13307,13307],"mapped",[50,56,26085]],[[13308,13308],"mapped",[50,57,26085]],[[13309,13309],"mapped",[51,48,26085]],[[13310,13310],"mapped",[51,49,26085]],[[13311,13311],"mapped",[103,97,108]],[[13312,19893],"valid"],[[19894,19903],"disallowed"],[[19904,19967],"valid",[],"NV8"],[[19968,40869],"valid"],[[40870,40891],"valid"],[[40892,40899],"valid"],[[40900,40907],"valid"],[[40908,40908],"valid"],[[40909,40917],"valid"],[[40918,40959],"disallowed"],[[40960,42124],"valid"],[[42125,42127],"disallowed"],[[42128,42145],"valid",[],"NV8"],[[42146,42147],"valid",[],"NV8"],[[42148,42163],"valid",[],"NV8"],[[42164,42164],"valid",[],"NV8"],[[42165,42176],"valid",[],"NV8"],[[42177,42177],"valid",[],"NV8"],[[42178,42180],"valid",[],"NV8"],[[42181,42181],"valid",[],"NV8"],[[42182,42182],"valid",[],"NV8"],[[42183,42191],"disallowed"],[[42192,42237],"valid"],[[42238,42239],"valid",[],"NV8"],[[42240,42508],"valid"],[[42509,42511],"valid",[],"NV8"],[[42512,42539],"valid"],[[42540,42559],"disallowed"],[[42560,42560],"mapped",[42561]],[[42561,42561],"valid"],[[42562,42562],"mapped",[42563]],[[42563,42563],"valid"],[[42564,42564],"mapped",[42565]],[[42565,42565],"valid"],[[42566,42566],"mapped",[42567]],[[42567,42567],"valid"],[[42568,42568],"mapped",[42569]],[[42569,42569],"valid"],[[42570,42570],"mapped",[42571]],[[42571,42571],"valid"],[[42572,42572],"mapped",[42573]],[[42573,42573],"valid"],[[42574,42574],"mapped",[42575]],[[42575,42575],"valid"],[[42576,42576],"mapped",[42577]],[[42577,42577],"valid"],[[42578,42578],"mapped",[42579]],[[42579,42579],"valid"],[[42580,42580],"mapped",[42581]],[[42581,42581],"valid"],[[42582,42582],"mapped",[42583]],[[42583,42583],"valid"],[[42584,42584],"mapped",[42585]],[[42585,42585],"valid"],[[42586,42586],"mapped",[42587]],[[42587,42587],"valid"],[[42588,42588],"mapped",[42589]],[[42589,42589],"valid"],[[42590,42590],"mapped",[42591]],[[42591,42591],"valid"],[[42592,42592],"mapped",[42593]],[[42593,42593],"valid"],[[42594,42594],"mapped",[42595]],[[42595,42595],"valid"],[[42596,42596],"mapped",[42597]],[[42597,42597],"valid"],[[42598,42598],"mapped",[42599]],[[42599,42599],"valid"],[[42600,42600],"mapped",[42601]],[[42601,42601],"valid"],[[42602,42602],"mapped",[42603]],[[42603,42603],"valid"],[[42604,42604],"mapped",[42605]],[[42605,42607],"valid"],[[42608,42611],"valid",[],"NV8"],[[42612,42619],"valid"],[[42620,42621],"valid"],[[42622,42622],"valid",[],"NV8"],[[42623,42623],"valid"],[[42624,42624],"mapped",[42625]],[[42625,42625],"valid"],[[42626,42626],"mapped",[42627]],[[42627,42627],"valid"],[[42628,42628],"mapped",[42629]],[[42629,42629],"valid"],[[42630,42630],"mapped",[42631]],[[42631,42631],"valid"],[[42632,42632],"mapped",[42633]],[[42633,42633],"valid"],[[42634,42634],"mapped",[42635]],[[42635,42635],"valid"],[[42636,42636],"mapped",[42637]],[[42637,42637],"valid"],[[42638,42638],"mapped",[42639]],[[42639,42639],"valid"],[[42640,42640],"mapped",[42641]],[[42641,42641],"valid"],[[42642,42642],"mapped",[42643]],[[42643,42643],"valid"],[[42644,42644],"mapped",[42645]],[[42645,42645],"valid"],[[42646,42646],"mapped",[42647]],[[42647,42647],"valid"],[[42648,42648],"mapped",[42649]],[[42649,42649],"valid"],[[42650,42650],"mapped",[42651]],[[42651,42651],"valid"],[[42652,42652],"mapped",[1098]],[[42653,42653],"mapped",[1100]],[[42654,42654],"valid"],[[42655,42655],"valid"],[[42656,42725],"valid"],[[42726,42735],"valid",[],"NV8"],[[42736,42737],"valid"],[[42738,42743],"valid",[],"NV8"],[[42744,42751],"disallowed"],[[42752,42774],"valid",[],"NV8"],[[42775,42778],"valid"],[[42779,42783],"valid"],[[42784,42785],"valid",[],"NV8"],[[42786,42786],"mapped",[42787]],[[42787,42787],"valid"],[[42788,42788],"mapped",[42789]],[[42789,42789],"valid"],[[42790,42790],"mapped",[42791]],[[42791,42791],"valid"],[[42792,42792],"mapped",[42793]],[[42793,42793],"valid"],[[42794,42794],"mapped",[42795]],[[42795,42795],"valid"],[[42796,42796],"mapped",[42797]],[[42797,42797],"valid"],[[42798,42798],"mapped",[42799]],[[42799,42801],"valid"],[[42802,42802],"mapped",[42803]],[[42803,42803],"valid"],[[42804,42804],"mapped",[42805]],[[42805,42805],"valid"],[[42806,42806],"mapped",[42807]],[[42807,42807],"valid"],[[42808,42808],"mapped",[42809]],[[42809,42809],"valid"],[[42810,42810],"mapped",[42811]],[[42811,42811],"valid"],[[42812,42812],"mapped",[42813]],[[42813,42813],"valid"],[[42814,42814],"mapped",[42815]],[[42815,42815],"valid"],[[42816,42816],"mapped",[42817]],[[42817,42817],"valid"],[[42818,42818],"mapped",[42819]],[[42819,42819],"valid"],[[42820,42820],"mapped",[42821]],[[42821,42821],"valid"],[[42822,42822],"mapped",[42823]],[[42823,42823],"valid"],[[42824,42824],"mapped",[42825]],[[42825,42825],"valid"],[[42826,42826],"mapped",[42827]],[[42827,42827],"valid"],[[42828,42828],"mapped",[42829]],[[42829,42829],"valid"],[[42830,42830],"mapped",[42831]],[[42831,42831],"valid"],[[42832,42832],"mapped",[42833]],[[42833,42833],"valid"],[[42834,42834],"mapped",[42835]],[[42835,42835],"valid"],[[42836,42836],"mapped",[42837]],[[42837,42837],"valid"],[[42838,42838],"mapped",[42839]],[[42839,42839],"valid"],[[42840,42840],"mapped",[42841]],[[42841,42841],"valid"],[[42842,42842],"mapped",[42843]],[[42843,42843],"valid"],[[42844,42844],"mapped",[42845]],[[42845,42845],"valid"],[[42846,42846],"mapped",[42847]],[[42847,42847],"valid"],[[42848,42848],"mapped",[42849]],[[42849,42849],"valid"],[[42850,42850],"mapped",[42851]],[[42851,42851],"valid"],[[42852,42852],"mapped",[42853]],[[42853,42853],"valid"],[[42854,42854],"mapped",[42855]],[[42855,42855],"valid"],[[42856,42856],"mapped",[42857]],[[42857,42857],"valid"],[[42858,42858],"mapped",[42859]],[[42859,42859],"valid"],[[42860,42860],"mapped",[42861]],[[42861,42861],"valid"],[[42862,42862],"mapped",[42863]],[[42863,42863],"valid"],[[42864,42864],"mapped",[42863]],[[42865,42872],"valid"],[[42873,42873],"mapped",[42874]],[[42874,42874],"valid"],[[42875,42875],"mapped",[42876]],[[42876,42876],"valid"],[[42877,42877],"mapped",[7545]],[[42878,42878],"mapped",[42879]],[[42879,42879],"valid"],[[42880,42880],"mapped",[42881]],[[42881,42881],"valid"],[[42882,42882],"mapped",[42883]],[[42883,42883],"valid"],[[42884,42884],"mapped",[42885]],[[42885,42885],"valid"],[[42886,42886],"mapped",[42887]],[[42887,42888],"valid"],[[42889,42890],"valid",[],"NV8"],[[42891,42891],"mapped",[42892]],[[42892,42892],"valid"],[[42893,42893],"mapped",[613]],[[42894,42894],"valid"],[[42895,42895],"valid"],[[42896,42896],"mapped",[42897]],[[42897,42897],"valid"],[[42898,42898],"mapped",[42899]],[[42899,42899],"valid"],[[42900,42901],"valid"],[[42902,42902],"mapped",[42903]],[[42903,42903],"valid"],[[42904,42904],"mapped",[42905]],[[42905,42905],"valid"],[[42906,42906],"mapped",[42907]],[[42907,42907],"valid"],[[42908,42908],"mapped",[42909]],[[42909,42909],"valid"],[[42910,42910],"mapped",[42911]],[[42911,42911],"valid"],[[42912,42912],"mapped",[42913]],[[42913,42913],"valid"],[[42914,42914],"mapped",[42915]],[[42915,42915],"valid"],[[42916,42916],"mapped",[42917]],[[42917,42917],"valid"],[[42918,42918],"mapped",[42919]],[[42919,42919],"valid"],[[42920,42920],"mapped",[42921]],[[42921,42921],"valid"],[[42922,42922],"mapped",[614]],[[42923,42923],"mapped",[604]],[[42924,42924],"mapped",[609]],[[42925,42925],"mapped",[620]],[[42926,42927],"disallowed"],[[42928,42928],"mapped",[670]],[[42929,42929],"mapped",[647]],[[42930,42930],"mapped",[669]],[[42931,42931],"mapped",[43859]],[[42932,42932],"mapped",[42933]],[[42933,42933],"valid"],[[42934,42934],"mapped",[42935]],[[42935,42935],"valid"],[[42936,42998],"disallowed"],[[42999,42999],"valid"],[[43000,43000],"mapped",[295]],[[43001,43001],"mapped",[339]],[[43002,43002],"valid"],[[43003,43007],"valid"],[[43008,43047],"valid"],[[43048,43051],"valid",[],"NV8"],[[43052,43055],"disallowed"],[[43056,43065],"valid",[],"NV8"],[[43066,43071],"disallowed"],[[43072,43123],"valid"],[[43124,43127],"valid",[],"NV8"],[[43128,43135],"disallowed"],[[43136,43204],"valid"],[[43205,43213],"disallowed"],[[43214,43215],"valid",[],"NV8"],[[43216,43225],"valid"],[[43226,43231],"disallowed"],[[43232,43255],"valid"],[[43256,43258],"valid",[],"NV8"],[[43259,43259],"valid"],[[43260,43260],"valid",[],"NV8"],[[43261,43261],"valid"],[[43262,43263],"disallowed"],[[43264,43309],"valid"],[[43310,43311],"valid",[],"NV8"],[[43312,43347],"valid"],[[43348,43358],"disallowed"],[[43359,43359],"valid",[],"NV8"],[[43360,43388],"valid",[],"NV8"],[[43389,43391],"disallowed"],[[43392,43456],"valid"],[[43457,43469],"valid",[],"NV8"],[[43470,43470],"disallowed"],[[43471,43481],"valid"],[[43482,43485],"disallowed"],[[43486,43487],"valid",[],"NV8"],[[43488,43518],"valid"],[[43519,43519],"disallowed"],[[43520,43574],"valid"],[[43575,43583],"disallowed"],[[43584,43597],"valid"],[[43598,43599],"disallowed"],[[43600,43609],"valid"],[[43610,43611],"disallowed"],[[43612,43615],"valid",[],"NV8"],[[43616,43638],"valid"],[[43639,43641],"valid",[],"NV8"],[[43642,43643],"valid"],[[43644,43647],"valid"],[[43648,43714],"valid"],[[43715,43738],"disallowed"],[[43739,43741],"valid"],[[43742,43743],"valid",[],"NV8"],[[43744,43759],"valid"],[[43760,43761],"valid",[],"NV8"],[[43762,43766],"valid"],[[43767,43776],"disallowed"],[[43777,43782],"valid"],[[43783,43784],"disallowed"],[[43785,43790],"valid"],[[43791,43792],"disallowed"],[[43793,43798],"valid"],[[43799,43807],"disallowed"],[[43808,43814],"valid"],[[43815,43815],"disallowed"],[[43816,43822],"valid"],[[43823,43823],"disallowed"],[[43824,43866],"valid"],[[43867,43867],"valid",[],"NV8"],[[43868,43868],"mapped",[42791]],[[43869,43869],"mapped",[43831]],[[43870,43870],"mapped",[619]],[[43871,43871],"mapped",[43858]],[[43872,43875],"valid"],[[43876,43877],"valid"],[[43878,43887],"disallowed"],[[43888,43888],"mapped",[5024]],[[43889,43889],"mapped",[5025]],[[43890,43890],"mapped",[5026]],[[43891,43891],"mapped",[5027]],[[43892,43892],"mapped",[5028]],[[43893,43893],"mapped",[5029]],[[43894,43894],"mapped",[5030]],[[43895,43895],"mapped",[5031]],[[43896,43896],"mapped",[5032]],[[43897,43897],"mapped",[5033]],[[43898,43898],"mapped",[5034]],[[43899,43899],"mapped",[5035]],[[43900,43900],"mapped",[5036]],[[43901,43901],"mapped",[5037]],[[43902,43902],"mapped",[5038]],[[43903,43903],"mapped",[5039]],[[43904,43904],"mapped",[5040]],[[43905,43905],"mapped",[5041]],[[43906,43906],"mapped",[5042]],[[43907,43907],"mapped",[5043]],[[43908,43908],"mapped",[5044]],[[43909,43909],"mapped",[5045]],[[43910,43910],"mapped",[5046]],[[43911,43911],"mapped",[5047]],[[43912,43912],"mapped",[5048]],[[43913,43913],"mapped",[5049]],[[43914,43914],"mapped",[5050]],[[43915,43915],"mapped",[5051]],[[43916,43916],"mapped",[5052]],[[43917,43917],"mapped",[5053]],[[43918,43918],"mapped",[5054]],[[43919,43919],"mapped",[5055]],[[43920,43920],"mapped",[5056]],[[43921,43921],"mapped",[5057]],[[43922,43922],"mapped",[5058]],[[43923,43923],"mapped",[5059]],[[43924,43924],"mapped",[5060]],[[43925,43925],"mapped",[5061]],[[43926,43926],"mapped",[5062]],[[43927,43927],"mapped",[5063]],[[43928,43928],"mapped",[5064]],[[43929,43929],"mapped",[5065]],[[43930,43930],"mapped",[5066]],[[43931,43931],"mapped",[5067]],[[43932,43932],"mapped",[5068]],[[43933,43933],"mapped",[5069]],[[43934,43934],"mapped",[5070]],[[43935,43935],"mapped",[5071]],[[43936,43936],"mapped",[5072]],[[43937,43937],"mapped",[5073]],[[43938,43938],"mapped",[5074]],[[43939,43939],"mapped",[5075]],[[43940,43940],"mapped",[5076]],[[43941,43941],"mapped",[5077]],[[43942,43942],"mapped",[5078]],[[43943,43943],"mapped",[5079]],[[43944,43944],"mapped",[5080]],[[43945,43945],"mapped",[5081]],[[43946,43946],"mapped",[5082]],[[43947,43947],"mapped",[5083]],[[43948,43948],"mapped",[5084]],[[43949,43949],"mapped",[5085]],[[43950,43950],"mapped",[5086]],[[43951,43951],"mapped",[5087]],[[43952,43952],"mapped",[5088]],[[43953,43953],"mapped",[5089]],[[43954,43954],"mapped",[5090]],[[43955,43955],"mapped",[5091]],[[43956,43956],"mapped",[5092]],[[43957,43957],"mapped",[5093]],[[43958,43958],"mapped",[5094]],[[43959,43959],"mapped",[5095]],[[43960,43960],"mapped",[5096]],[[43961,43961],"mapped",[5097]],[[43962,43962],"mapped",[5098]],[[43963,43963],"mapped",[5099]],[[43964,43964],"mapped",[5100]],[[43965,43965],"mapped",[5101]],[[43966,43966],"mapped",[5102]],[[43967,43967],"mapped",[5103]],[[43968,44010],"valid"],[[44011,44011],"valid",[],"NV8"],[[44012,44013],"valid"],[[44014,44015],"disallowed"],[[44016,44025],"valid"],[[44026,44031],"disallowed"],[[44032,55203],"valid"],[[55204,55215],"disallowed"],[[55216,55238],"valid",[],"NV8"],[[55239,55242],"disallowed"],[[55243,55291],"valid",[],"NV8"],[[55292,55295],"disallowed"],[[55296,57343],"disallowed"],[[57344,63743],"disallowed"],[[63744,63744],"mapped",[35912]],[[63745,63745],"mapped",[26356]],[[63746,63746],"mapped",[36554]],[[63747,63747],"mapped",[36040]],[[63748,63748],"mapped",[28369]],[[63749,63749],"mapped",[20018]],[[63750,63750],"mapped",[21477]],[[63751,63752],"mapped",[40860]],[[63753,63753],"mapped",[22865]],[[63754,63754],"mapped",[37329]],[[63755,63755],"mapped",[21895]],[[63756,63756],"mapped",[22856]],[[63757,63757],"mapped",[25078]],[[63758,63758],"mapped",[30313]],[[63759,63759],"mapped",[32645]],[[63760,63760],"mapped",[34367]],[[63761,63761],"mapped",[34746]],[[63762,63762],"mapped",[35064]],[[63763,63763],"mapped",[37007]],[[63764,63764],"mapped",[27138]],[[63765,63765],"mapped",[27931]],[[63766,63766],"mapped",[28889]],[[63767,63767],"mapped",[29662]],[[63768,63768],"mapped",[33853]],[[63769,63769],"mapped",[37226]],[[63770,63770],"mapped",[39409]],[[63771,63771],"mapped",[20098]],[[63772,63772],"mapped",[21365]],[[63773,63773],"mapped",[27396]],[[63774,63774],"mapped",[29211]],[[63775,63775],"mapped",[34349]],[[63776,63776],"mapped",[40478]],[[63777,63777],"mapped",[23888]],[[63778,63778],"mapped",[28651]],[[63779,63779],"mapped",[34253]],[[63780,63780],"mapped",[35172]],[[63781,63781],"mapped",[25289]],[[63782,63782],"mapped",[33240]],[[63783,63783],"mapped",[34847]],[[63784,63784],"mapped",[24266]],[[63785,63785],"mapped",[26391]],[[63786,63786],"mapped",[28010]],[[63787,63787],"mapped",[29436]],[[63788,63788],"mapped",[37070]],[[63789,63789],"mapped",[20358]],[[63790,63790],"mapped",[20919]],[[63791,63791],"mapped",[21214]],[[63792,63792],"mapped",[25796]],[[63793,63793],"mapped",[27347]],[[63794,63794],"mapped",[29200]],[[63795,63795],"mapped",[30439]],[[63796,63796],"mapped",[32769]],[[63797,63797],"mapped",[34310]],[[63798,63798],"mapped",[34396]],[[63799,63799],"mapped",[36335]],[[63800,63800],"mapped",[38706]],[[63801,63801],"mapped",[39791]],[[63802,63802],"mapped",[40442]],[[63803,63803],"mapped",[30860]],[[63804,63804],"mapped",[31103]],[[63805,63805],"mapped",[32160]],[[63806,63806],"mapped",[33737]],[[63807,63807],"mapped",[37636]],[[63808,63808],"mapped",[40575]],[[63809,63809],"mapped",[35542]],[[63810,63810],"mapped",[22751]],[[63811,63811],"mapped",[24324]],[[63812,63812],"mapped",[31840]],[[63813,63813],"mapped",[32894]],[[63814,63814],"mapped",[29282]],[[63815,63815],"mapped",[30922]],[[63816,63816],"mapped",[36034]],[[63817,63817],"mapped",[38647]],[[63818,63818],"mapped",[22744]],[[63819,63819],"mapped",[23650]],[[63820,63820],"mapped",[27155]],[[63821,63821],"mapped",[28122]],[[63822,63822],"mapped",[28431]],[[63823,63823],"mapped",[32047]],[[63824,63824],"mapped",[32311]],[[63825,63825],"mapped",[38475]],[[63826,63826],"mapped",[21202]],[[63827,63827],"mapped",[32907]],[[63828,63828],"mapped",[20956]],[[63829,63829],"mapped",[20940]],[[63830,63830],"mapped",[31260]],[[63831,63831],"mapped",[32190]],[[63832,63832],"mapped",[33777]],[[63833,63833],"mapped",[38517]],[[63834,63834],"mapped",[35712]],[[63835,63835],"mapped",[25295]],[[63836,63836],"mapped",[27138]],[[63837,63837],"mapped",[35582]],[[63838,63838],"mapped",[20025]],[[63839,63839],"mapped",[23527]],[[63840,63840],"mapped",[24594]],[[63841,63841],"mapped",[29575]],[[63842,63842],"mapped",[30064]],[[63843,63843],"mapped",[21271]],[[63844,63844],"mapped",[30971]],[[63845,63845],"mapped",[20415]],[[63846,63846],"mapped",[24489]],[[63847,63847],"mapped",[19981]],[[63848,63848],"mapped",[27852]],[[63849,63849],"mapped",[25976]],[[63850,63850],"mapped",[32034]],[[63851,63851],"mapped",[21443]],[[63852,63852],"mapped",[22622]],[[63853,63853],"mapped",[30465]],[[63854,63854],"mapped",[33865]],[[63855,63855],"mapped",[35498]],[[63856,63856],"mapped",[27578]],[[63857,63857],"mapped",[36784]],[[63858,63858],"mapped",[27784]],[[63859,63859],"mapped",[25342]],[[63860,63860],"mapped",[33509]],[[63861,63861],"mapped",[25504]],[[63862,63862],"mapped",[30053]],[[63863,63863],"mapped",[20142]],[[63864,63864],"mapped",[20841]],[[63865,63865],"mapped",[20937]],[[63866,63866],"mapped",[26753]],[[63867,63867],"mapped",[31975]],[[63868,63868],"mapped",[33391]],[[63869,63869],"mapped",[35538]],[[63870,63870],"mapped",[37327]],[[63871,63871],"mapped",[21237]],[[63872,63872],"mapped",[21570]],[[63873,63873],"mapped",[22899]],[[63874,63874],"mapped",[24300]],[[63875,63875],"mapped",[26053]],[[63876,63876],"mapped",[28670]],[[63877,63877],"mapped",[31018]],[[63878,63878],"mapped",[38317]],[[63879,63879],"mapped",[39530]],[[63880,63880],"mapped",[40599]],[[63881,63881],"mapped",[40654]],[[63882,63882],"mapped",[21147]],[[63883,63883],"mapped",[26310]],[[63884,63884],"mapped",[27511]],[[63885,63885],"mapped",[36706]],[[63886,63886],"mapped",[24180]],[[63887,63887],"mapped",[24976]],[[63888,63888],"mapped",[25088]],[[63889,63889],"mapped",[25754]],[[63890,63890],"mapped",[28451]],[[63891,63891],"mapped",[29001]],[[63892,63892],"mapped",[29833]],[[63893,63893],"mapped",[31178]],[[63894,63894],"mapped",[32244]],[[63895,63895],"mapped",[32879]],[[63896,63896],"mapped",[36646]],[[63897,63897],"mapped",[34030]],[[63898,63898],"mapped",[36899]],[[63899,63899],"mapped",[37706]],[[63900,63900],"mapped",[21015]],[[63901,63901],"mapped",[21155]],[[63902,63902],"mapped",[21693]],[[63903,63903],"mapped",[28872]],[[63904,63904],"mapped",[35010]],[[63905,63905],"mapped",[35498]],[[63906,63906],"mapped",[24265]],[[63907,63907],"mapped",[24565]],[[63908,63908],"mapped",[25467]],[[63909,63909],"mapped",[27566]],[[63910,63910],"mapped",[31806]],[[63911,63911],"mapped",[29557]],[[63912,63912],"mapped",[20196]],[[63913,63913],"mapped",[22265]],[[63914,63914],"mapped",[23527]],[[63915,63915],"mapped",[23994]],[[63916,63916],"mapped",[24604]],[[63917,63917],"mapped",[29618]],[[63918,63918],"mapped",[29801]],[[63919,63919],"mapped",[32666]],[[63920,63920],"mapped",[32838]],[[63921,63921],"mapped",[37428]],[[63922,63922],"mapped",[38646]],[[63923,63923],"mapped",[38728]],[[63924,63924],"mapped",[38936]],[[63925,63925],"mapped",[20363]],[[63926,63926],"mapped",[31150]],[[63927,63927],"mapped",[37300]],[[63928,63928],"mapped",[38584]],[[63929,63929],"mapped",[24801]],[[63930,63930],"mapped",[20102]],[[63931,63931],"mapped",[20698]],[[63932,63932],"mapped",[23534]],[[63933,63933],"mapped",[23615]],[[63934,63934],"mapped",[26009]],[[63935,63935],"mapped",[27138]],[[63936,63936],"mapped",[29134]],[[63937,63937],"mapped",[30274]],[[63938,63938],"mapped",[34044]],[[63939,63939],"mapped",[36988]],[[63940,63940],"mapped",[40845]],[[63941,63941],"mapped",[26248]],[[63942,63942],"mapped",[38446]],[[63943,63943],"mapped",[21129]],[[63944,63944],"mapped",[26491]],[[63945,63945],"mapped",[26611]],[[63946,63946],"mapped",[27969]],[[63947,63947],"mapped",[28316]],[[63948,63948],"mapped",[29705]],[[63949,63949],"mapped",[30041]],[[63950,63950],"mapped",[30827]],[[63951,63951],"mapped",[32016]],[[63952,63952],"mapped",[39006]],[[63953,63953],"mapped",[20845]],[[63954,63954],"mapped",[25134]],[[63955,63955],"mapped",[38520]],[[63956,63956],"mapped",[20523]],[[63957,63957],"mapped",[23833]],[[63958,63958],"mapped",[28138]],[[63959,63959],"mapped",[36650]],[[63960,63960],"mapped",[24459]],[[63961,63961],"mapped",[24900]],[[63962,63962],"mapped",[26647]],[[63963,63963],"mapped",[29575]],[[63964,63964],"mapped",[38534]],[[63965,63965],"mapped",[21033]],[[63966,63966],"mapped",[21519]],[[63967,63967],"mapped",[23653]],[[63968,63968],"mapped",[26131]],[[63969,63969],"mapped",[26446]],[[63970,63970],"mapped",[26792]],[[63971,63971],"mapped",[27877]],[[63972,63972],"mapped",[29702]],[[63973,63973],"mapped",[30178]],[[63974,63974],"mapped",[32633]],[[63975,63975],"mapped",[35023]],[[63976,63976],"mapped",[35041]],[[63977,63977],"mapped",[37324]],[[63978,63978],"mapped",[38626]],[[63979,63979],"mapped",[21311]],[[63980,63980],"mapped",[28346]],[[63981,63981],"mapped",[21533]],[[63982,63982],"mapped",[29136]],[[63983,63983],"mapped",[29848]],[[63984,63984],"mapped",[34298]],[[63985,63985],"mapped",[38563]],[[63986,63986],"mapped",[40023]],[[63987,63987],"mapped",[40607]],[[63988,63988],"mapped",[26519]],[[63989,63989],"mapped",[28107]],[[63990,63990],"mapped",[33256]],[[63991,63991],"mapped",[31435]],[[63992,63992],"mapped",[31520]],[[63993,63993],"mapped",[31890]],[[63994,63994],"mapped",[29376]],[[63995,63995],"mapped",[28825]],[[63996,63996],"mapped",[35672]],[[63997,63997],"mapped",[20160]],[[63998,63998],"mapped",[33590]],[[63999,63999],"mapped",[21050]],[[64000,64000],"mapped",[20999]],[[64001,64001],"mapped",[24230]],[[64002,64002],"mapped",[25299]],[[64003,64003],"mapped",[31958]],[[64004,64004],"mapped",[23429]],[[64005,64005],"mapped",[27934]],[[64006,64006],"mapped",[26292]],[[64007,64007],"mapped",[36667]],[[64008,64008],"mapped",[34892]],[[64009,64009],"mapped",[38477]],[[64010,64010],"mapped",[35211]],[[64011,64011],"mapped",[24275]],[[64012,64012],"mapped",[20800]],[[64013,64013],"mapped",[21952]],[[64014,64015],"valid"],[[64016,64016],"mapped",[22618]],[[64017,64017],"valid"],[[64018,64018],"mapped",[26228]],[[64019,64020],"valid"],[[64021,64021],"mapped",[20958]],[[64022,64022],"mapped",[29482]],[[64023,64023],"mapped",[30410]],[[64024,64024],"mapped",[31036]],[[64025,64025],"mapped",[31070]],[[64026,64026],"mapped",[31077]],[[64027,64027],"mapped",[31119]],[[64028,64028],"mapped",[38742]],[[64029,64029],"mapped",[31934]],[[64030,64030],"mapped",[32701]],[[64031,64031],"valid"],[[64032,64032],"mapped",[34322]],[[64033,64033],"valid"],[[64034,64034],"mapped",[35576]],[[64035,64036],"valid"],[[64037,64037],"mapped",[36920]],[[64038,64038],"mapped",[37117]],[[64039,64041],"valid"],[[64042,64042],"mapped",[39151]],[[64043,64043],"mapped",[39164]],[[64044,64044],"mapped",[39208]],[[64045,64045],"mapped",[40372]],[[64046,64046],"mapped",[37086]],[[64047,64047],"mapped",[38583]],[[64048,64048],"mapped",[20398]],[[64049,64049],"mapped",[20711]],[[64050,64050],"mapped",[20813]],[[64051,64051],"mapped",[21193]],[[64052,64052],"mapped",[21220]],[[64053,64053],"mapped",[21329]],[[64054,64054],"mapped",[21917]],[[64055,64055],"mapped",[22022]],[[64056,64056],"mapped",[22120]],[[64057,64057],"mapped",[22592]],[[64058,64058],"mapped",[22696]],[[64059,64059],"mapped",[23652]],[[64060,64060],"mapped",[23662]],[[64061,64061],"mapped",[24724]],[[64062,64062],"mapped",[24936]],[[64063,64063],"mapped",[24974]],[[64064,64064],"mapped",[25074]],[[64065,64065],"mapped",[25935]],[[64066,64066],"mapped",[26082]],[[64067,64067],"mapped",[26257]],[[64068,64068],"mapped",[26757]],[[64069,64069],"mapped",[28023]],[[64070,64070],"mapped",[28186]],[[64071,64071],"mapped",[28450]],[[64072,64072],"mapped",[29038]],[[64073,64073],"mapped",[29227]],[[64074,64074],"mapped",[29730]],[[64075,64075],"mapped",[30865]],[[64076,64076],"mapped",[31038]],[[64077,64077],"mapped",[31049]],[[64078,64078],"mapped",[31048]],[[64079,64079],"mapped",[31056]],[[64080,64080],"mapped",[31062]],[[64081,64081],"mapped",[31069]],[[64082,64082],"mapped",[31117]],[[64083,64083],"mapped",[31118]],[[64084,64084],"mapped",[31296]],[[64085,64085],"mapped",[31361]],[[64086,64086],"mapped",[31680]],[[64087,64087],"mapped",[32244]],[[64088,64088],"mapped",[32265]],[[64089,64089],"mapped",[32321]],[[64090,64090],"mapped",[32626]],[[64091,64091],"mapped",[32773]],[[64092,64092],"mapped",[33261]],[[64093,64094],"mapped",[33401]],[[64095,64095],"mapped",[33879]],[[64096,64096],"mapped",[35088]],[[64097,64097],"mapped",[35222]],[[64098,64098],"mapped",[35585]],[[64099,64099],"mapped",[35641]],[[64100,64100],"mapped",[36051]],[[64101,64101],"mapped",[36104]],[[64102,64102],"mapped",[36790]],[[64103,64103],"mapped",[36920]],[[64104,64104],"mapped",[38627]],[[64105,64105],"mapped",[38911]],[[64106,64106],"mapped",[38971]],[[64107,64107],"mapped",[24693]],[[64108,64108],"mapped",[148206]],[[64109,64109],"mapped",[33304]],[[64110,64111],"disallowed"],[[64112,64112],"mapped",[20006]],[[64113,64113],"mapped",[20917]],[[64114,64114],"mapped",[20840]],[[64115,64115],"mapped",[20352]],[[64116,64116],"mapped",[20805]],[[64117,64117],"mapped",[20864]],[[64118,64118],"mapped",[21191]],[[64119,64119],"mapped",[21242]],[[64120,64120],"mapped",[21917]],[[64121,64121],"mapped",[21845]],[[64122,64122],"mapped",[21913]],[[64123,64123],"mapped",[21986]],[[64124,64124],"mapped",[22618]],[[64125,64125],"mapped",[22707]],[[64126,64126],"mapped",[22852]],[[64127,64127],"mapped",[22868]],[[64128,64128],"mapped",[23138]],[[64129,64129],"mapped",[23336]],[[64130,64130],"mapped",[24274]],[[64131,64131],"mapped",[24281]],[[64132,64132],"mapped",[24425]],[[64133,64133],"mapped",[24493]],[[64134,64134],"mapped",[24792]],[[64135,64135],"mapped",[24910]],[[64136,64136],"mapped",[24840]],[[64137,64137],"mapped",[24974]],[[64138,64138],"mapped",[24928]],[[64139,64139],"mapped",[25074]],[[64140,64140],"mapped",[25140]],[[64141,64141],"mapped",[25540]],[[64142,64142],"mapped",[25628]],[[64143,64143],"mapped",[25682]],[[64144,64144],"mapped",[25942]],[[64145,64145],"mapped",[26228]],[[64146,64146],"mapped",[26391]],[[64147,64147],"mapped",[26395]],[[64148,64148],"mapped",[26454]],[[64149,64149],"mapped",[27513]],[[64150,64150],"mapped",[27578]],[[64151,64151],"mapped",[27969]],[[64152,64152],"mapped",[28379]],[[64153,64153],"mapped",[28363]],[[64154,64154],"mapped",[28450]],[[64155,64155],"mapped",[28702]],[[64156,64156],"mapped",[29038]],[[64157,64157],"mapped",[30631]],[[64158,64158],"mapped",[29237]],[[64159,64159],"mapped",[29359]],[[64160,64160],"mapped",[29482]],[[64161,64161],"mapped",[29809]],[[64162,64162],"mapped",[29958]],[[64163,64163],"mapped",[30011]],[[64164,64164],"mapped",[30237]],[[64165,64165],"mapped",[30239]],[[64166,64166],"mapped",[30410]],[[64167,64167],"mapped",[30427]],[[64168,64168],"mapped",[30452]],[[64169,64169],"mapped",[30538]],[[64170,64170],"mapped",[30528]],[[64171,64171],"mapped",[30924]],[[64172,64172],"mapped",[31409]],[[64173,64173],"mapped",[31680]],[[64174,64174],"mapped",[31867]],[[64175,64175],"mapped",[32091]],[[64176,64176],"mapped",[32244]],[[64177,64177],"mapped",[32574]],[[64178,64178],"mapped",[32773]],[[64179,64179],"mapped",[33618]],[[64180,64180],"mapped",[33775]],[[64181,64181],"mapped",[34681]],[[64182,64182],"mapped",[35137]],[[64183,64183],"mapped",[35206]],[[64184,64184],"mapped",[35222]],[[64185,64185],"mapped",[35519]],[[64186,64186],"mapped",[35576]],[[64187,64187],"mapped",[35531]],[[64188,64188],"mapped",[35585]],[[64189,64189],"mapped",[35582]],[[64190,64190],"mapped",[35565]],[[64191,64191],"mapped",[35641]],[[64192,64192],"mapped",[35722]],[[64193,64193],"mapped",[36104]],[[64194,64194],"mapped",[36664]],[[64195,64195],"mapped",[36978]],[[64196,64196],"mapped",[37273]],[[64197,64197],"mapped",[37494]],[[64198,64198],"mapped",[38524]],[[64199,64199],"mapped",[38627]],[[64200,64200],"mapped",[38742]],[[64201,64201],"mapped",[38875]],[[64202,64202],"mapped",[38911]],[[64203,64203],"mapped",[38923]],[[64204,64204],"mapped",[38971]],[[64205,64205],"mapped",[39698]],[[64206,64206],"mapped",[40860]],[[64207,64207],"mapped",[141386]],[[64208,64208],"mapped",[141380]],[[64209,64209],"mapped",[144341]],[[64210,64210],"mapped",[15261]],[[64211,64211],"mapped",[16408]],[[64212,64212],"mapped",[16441]],[[64213,64213],"mapped",[152137]],[[64214,64214],"mapped",[154832]],[[64215,64215],"mapped",[163539]],[[64216,64216],"mapped",[40771]],[[64217,64217],"mapped",[40846]],[[64218,64255],"disallowed"],[[64256,64256],"mapped",[102,102]],[[64257,64257],"mapped",[102,105]],[[64258,64258],"mapped",[102,108]],[[64259,64259],"mapped",[102,102,105]],[[64260,64260],"mapped",[102,102,108]],[[64261,64262],"mapped",[115,116]],[[64263,64274],"disallowed"],[[64275,64275],"mapped",[1396,1398]],[[64276,64276],"mapped",[1396,1381]],[[64277,64277],"mapped",[1396,1387]],[[64278,64278],"mapped",[1406,1398]],[[64279,64279],"mapped",[1396,1389]],[[64280,64284],"disallowed"],[[64285,64285],"mapped",[1497,1460]],[[64286,64286],"valid"],[[64287,64287],"mapped",[1522,1463]],[[64288,64288],"mapped",[1506]],[[64289,64289],"mapped",[1488]],[[64290,64290],"mapped",[1491]],[[64291,64291],"mapped",[1492]],[[64292,64292],"mapped",[1499]],[[64293,64293],"mapped",[1500]],[[64294,64294],"mapped",[1501]],[[64295,64295],"mapped",[1512]],[[64296,64296],"mapped",[1514]],[[64297,64297],"disallowed_STD3_mapped",[43]],[[64298,64298],"mapped",[1513,1473]],[[64299,64299],"mapped",[1513,1474]],[[64300,64300],"mapped",[1513,1468,1473]],[[64301,64301],"mapped",[1513,1468,1474]],[[64302,64302],"mapped",[1488,1463]],[[64303,64303],"mapped",[1488,1464]],[[64304,64304],"mapped",[1488,1468]],[[64305,64305],"mapped",[1489,1468]],[[64306,64306],"mapped",[1490,1468]],[[64307,64307],"mapped",[1491,1468]],[[64308,64308],"mapped",[1492,1468]],[[64309,64309],"mapped",[1493,1468]],[[64310,64310],"mapped",[1494,1468]],[[64311,64311],"disallowed"],[[64312,64312],"mapped",[1496,1468]],[[64313,64313],"mapped",[1497,1468]],[[64314,64314],"mapped",[1498,1468]],[[64315,64315],"mapped",[1499,1468]],[[64316,64316],"mapped",[1500,1468]],[[64317,64317],"disallowed"],[[64318,64318],"mapped",[1502,1468]],[[64319,64319],"disallowed"],[[64320,64320],"mapped",[1504,1468]],[[64321,64321],"mapped",[1505,1468]],[[64322,64322],"disallowed"],[[64323,64323],"mapped",[1507,1468]],[[64324,64324],"mapped",[1508,1468]],[[64325,64325],"disallowed"],[[64326,64326],"mapped",[1510,1468]],[[64327,64327],"mapped",[1511,1468]],[[64328,64328],"mapped",[1512,1468]],[[64329,64329],"mapped",[1513,1468]],[[64330,64330],"mapped",[1514,1468]],[[64331,64331],"mapped",[1493,1465]],[[64332,64332],"mapped",[1489,1471]],[[64333,64333],"mapped",[1499,1471]],[[64334,64334],"mapped",[1508,1471]],[[64335,64335],"mapped",[1488,1500]],[[64336,64337],"mapped",[1649]],[[64338,64341],"mapped",[1659]],[[64342,64345],"mapped",[1662]],[[64346,64349],"mapped",[1664]],[[64350,64353],"mapped",[1658]],[[64354,64357],"mapped",[1663]],[[64358,64361],"mapped",[1657]],[[64362,64365],"mapped",[1700]],[[64366,64369],"mapped",[1702]],[[64370,64373],"mapped",[1668]],[[64374,64377],"mapped",[1667]],[[64378,64381],"mapped",[1670]],[[64382,64385],"mapped",[1671]],[[64386,64387],"mapped",[1677]],[[64388,64389],"mapped",[1676]],[[64390,64391],"mapped",[1678]],[[64392,64393],"mapped",[1672]],[[64394,64395],"mapped",[1688]],[[64396,64397],"mapped",[1681]],[[64398,64401],"mapped",[1705]],[[64402,64405],"mapped",[1711]],[[64406,64409],"mapped",[1715]],[[64410,64413],"mapped",[1713]],[[64414,64415],"mapped",[1722]],[[64416,64419],"mapped",[1723]],[[64420,64421],"mapped",[1728]],[[64422,64425],"mapped",[1729]],[[64426,64429],"mapped",[1726]],[[64430,64431],"mapped",[1746]],[[64432,64433],"mapped",[1747]],[[64434,64449],"valid",[],"NV8"],[[64450,64466],"disallowed"],[[64467,64470],"mapped",[1709]],[[64471,64472],"mapped",[1735]],[[64473,64474],"mapped",[1734]],[[64475,64476],"mapped",[1736]],[[64477,64477],"mapped",[1735,1652]],[[64478,64479],"mapped",[1739]],[[64480,64481],"mapped",[1733]],[[64482,64483],"mapped",[1737]],[[64484,64487],"mapped",[1744]],[[64488,64489],"mapped",[1609]],[[64490,64491],"mapped",[1574,1575]],[[64492,64493],"mapped",[1574,1749]],[[64494,64495],"mapped",[1574,1608]],[[64496,64497],"mapped",[1574,1735]],[[64498,64499],"mapped",[1574,1734]],[[64500,64501],"mapped",[1574,1736]],[[64502,64504],"mapped",[1574,1744]],[[64505,64507],"mapped",[1574,1609]],[[64508,64511],"mapped",[1740]],[[64512,64512],"mapped",[1574,1580]],[[64513,64513],"mapped",[1574,1581]],[[64514,64514],"mapped",[1574,1605]],[[64515,64515],"mapped",[1574,1609]],[[64516,64516],"mapped",[1574,1610]],[[64517,64517],"mapped",[1576,1580]],[[64518,64518],"mapped",[1576,1581]],[[64519,64519],"mapped",[1576,1582]],[[64520,64520],"mapped",[1576,1605]],[[64521,64521],"mapped",[1576,1609]],[[64522,64522],"mapped",[1576,1610]],[[64523,64523],"mapped",[1578,1580]],[[64524,64524],"mapped",[1578,1581]],[[64525,64525],"mapped",[1578,1582]],[[64526,64526],"mapped",[1578,1605]],[[64527,64527],"mapped",[1578,1609]],[[64528,64528],"mapped",[1578,1610]],[[64529,64529],"mapped",[1579,1580]],[[64530,64530],"mapped",[1579,1605]],[[64531,64531],"mapped",[1579,1609]],[[64532,64532],"mapped",[1579,1610]],[[64533,64533],"mapped",[1580,1581]],[[64534,64534],"mapped",[1580,1605]],[[64535,64535],"mapped",[1581,1580]],[[64536,64536],"mapped",[1581,1605]],[[64537,64537],"mapped",[1582,1580]],[[64538,64538],"mapped",[1582,1581]],[[64539,64539],"mapped",[1582,1605]],[[64540,64540],"mapped",[1587,1580]],[[64541,64541],"mapped",[1587,1581]],[[64542,64542],"mapped",[1587,1582]],[[64543,64543],"mapped",[1587,1605]],[[64544,64544],"mapped",[1589,1581]],[[64545,64545],"mapped",[1589,1605]],[[64546,64546],"mapped",[1590,1580]],[[64547,64547],"mapped",[1590,1581]],[[64548,64548],"mapped",[1590,1582]],[[64549,64549],"mapped",[1590,1605]],[[64550,64550],"mapped",[1591,1581]],[[64551,64551],"mapped",[1591,1605]],[[64552,64552],"mapped",[1592,1605]],[[64553,64553],"mapped",[1593,1580]],[[64554,64554],"mapped",[1593,1605]],[[64555,64555],"mapped",[1594,1580]],[[64556,64556],"mapped",[1594,1605]],[[64557,64557],"mapped",[1601,1580]],[[64558,64558],"mapped",[1601,1581]],[[64559,64559],"mapped",[1601,1582]],[[64560,64560],"mapped",[1601,1605]],[[64561,64561],"mapped",[1601,1609]],[[64562,64562],"mapped",[1601,1610]],[[64563,64563],"mapped",[1602,1581]],[[64564,64564],"mapped",[1602,1605]],[[64565,64565],"mapped",[1602,1609]],[[64566,64566],"mapped",[1602,1610]],[[64567,64567],"mapped",[1603,1575]],[[64568,64568],"mapped",[1603,1580]],[[64569,64569],"mapped",[1603,1581]],[[64570,64570],"mapped",[1603,1582]],[[64571,64571],"mapped",[1603,1604]],[[64572,64572],"mapped",[1603,1605]],[[64573,64573],"mapped",[1603,1609]],[[64574,64574],"mapped",[1603,1610]],[[64575,64575],"mapped",[1604,1580]],[[64576,64576],"mapped",[1604,1581]],[[64577,64577],"mapped",[1604,1582]],[[64578,64578],"mapped",[1604,1605]],[[64579,64579],"mapped",[1604,1609]],[[64580,64580],"mapped",[1604,1610]],[[64581,64581],"mapped",[1605,1580]],[[64582,64582],"mapped",[1605,1581]],[[64583,64583],"mapped",[1605,1582]],[[64584,64584],"mapped",[1605,1605]],[[64585,64585],"mapped",[1605,1609]],[[64586,64586],"mapped",[1605,1610]],[[64587,64587],"mapped",[1606,1580]],[[64588,64588],"mapped",[1606,1581]],[[64589,64589],"mapped",[1606,1582]],[[64590,64590],"mapped",[1606,1605]],[[64591,64591],"mapped",[1606,1609]],[[64592,64592],"mapped",[1606,1610]],[[64593,64593],"mapped",[1607,1580]],[[64594,64594],"mapped",[1607,1605]],[[64595,64595],"mapped",[1607,1609]],[[64596,64596],"mapped",[1607,1610]],[[64597,64597],"mapped",[1610,1580]],[[64598,64598],"mapped",[1610,1581]],[[64599,64599],"mapped",[1610,1582]],[[64600,64600],"mapped",[1610,1605]],[[64601,64601],"mapped",[1610,1609]],[[64602,64602],"mapped",[1610,1610]],[[64603,64603],"mapped",[1584,1648]],[[64604,64604],"mapped",[1585,1648]],[[64605,64605],"mapped",[1609,1648]],[[64606,64606],"disallowed_STD3_mapped",[32,1612,1617]],[[64607,64607],"disallowed_STD3_mapped",[32,1613,1617]],[[64608,64608],"disallowed_STD3_mapped",[32,1614,1617]],[[64609,64609],"disallowed_STD3_mapped",[32,1615,1617]],[[64610,64610],"disallowed_STD3_mapped",[32,1616,1617]],[[64611,64611],"disallowed_STD3_mapped",[32,1617,1648]],[[64612,64612],"mapped",[1574,1585]],[[64613,64613],"mapped",[1574,1586]],[[64614,64614],"mapped",[1574,1605]],[[64615,64615],"mapped",[1574,1606]],[[64616,64616],"mapped",[1574,1609]],[[64617,64617],"mapped",[1574,1610]],[[64618,64618],"mapped",[1576,1585]],[[64619,64619],"mapped",[1576,1586]],[[64620,64620],"mapped",[1576,1605]],[[64621,64621],"mapped",[1576,1606]],[[64622,64622],"mapped",[1576,1609]],[[64623,64623],"mapped",[1576,1610]],[[64624,64624],"mapped",[1578,1585]],[[64625,64625],"mapped",[1578,1586]],[[64626,64626],"mapped",[1578,1605]],[[64627,64627],"mapped",[1578,1606]],[[64628,64628],"mapped",[1578,1609]],[[64629,64629],"mapped",[1578,1610]],[[64630,64630],"mapped",[1579,1585]],[[64631,64631],"mapped",[1579,1586]],[[64632,64632],"mapped",[1579,1605]],[[64633,64633],"mapped",[1579,1606]],[[64634,64634],"mapped",[1579,1609]],[[64635,64635],"mapped",[1579,1610]],[[64636,64636],"mapped",[1601,1609]],[[64637,64637],"mapped",[1601,1610]],[[64638,64638],"mapped",[1602,1609]],[[64639,64639],"mapped",[1602,1610]],[[64640,64640],"mapped",[1603,1575]],[[64641,64641],"mapped",[1603,1604]],[[64642,64642],"mapped",[1603,1605]],[[64643,64643],"mapped",[1603,1609]],[[64644,64644],"mapped",[1603,1610]],[[64645,64645],"mapped",[1604,1605]],[[64646,64646],"mapped",[1604,1609]],[[64647,64647],"mapped",[1604,1610]],[[64648,64648],"mapped",[1605,1575]],[[64649,64649],"mapped",[1605,1605]],[[64650,64650],"mapped",[1606,1585]],[[64651,64651],"mapped",[1606,1586]],[[64652,64652],"mapped",[1606,1605]],[[64653,64653],"mapped",[1606,1606]],[[64654,64654],"mapped",[1606,1609]],[[64655,64655],"mapped",[1606,1610]],[[64656,64656],"mapped",[1609,1648]],[[64657,64657],"mapped",[1610,1585]],[[64658,64658],"mapped",[1610,1586]],[[64659,64659],"mapped",[1610,1605]],[[64660,64660],"mapped",[1610,1606]],[[64661,64661],"mapped",[1610,1609]],[[64662,64662],"mapped",[1610,1610]],[[64663,64663],"mapped",[1574,1580]],[[64664,64664],"mapped",[1574,1581]],[[64665,64665],"mapped",[1574,1582]],[[64666,64666],"mapped",[1574,1605]],[[64667,64667],"mapped",[1574,1607]],[[64668,64668],"mapped",[1576,1580]],[[64669,64669],"mapped",[1576,1581]],[[64670,64670],"mapped",[1576,1582]],[[64671,64671],"mapped",[1576,1605]],[[64672,64672],"mapped",[1576,1607]],[[64673,64673],"mapped",[1578,1580]],[[64674,64674],"mapped",[1578,1581]],[[64675,64675],"mapped",[1578,1582]],[[64676,64676],"mapped",[1578,1605]],[[64677,64677],"mapped",[1578,1607]],[[64678,64678],"mapped",[1579,1605]],[[64679,64679],"mapped",[1580,1581]],[[64680,64680],"mapped",[1580,1605]],[[64681,64681],"mapped",[1581,1580]],[[64682,64682],"mapped",[1581,1605]],[[64683,64683],"mapped",[1582,1580]],[[64684,64684],"mapped",[1582,1605]],[[64685,64685],"mapped",[1587,1580]],[[64686,64686],"mapped",[1587,1581]],[[64687,64687],"mapped",[1587,1582]],[[64688,64688],"mapped",[1587,1605]],[[64689,64689],"mapped",[1589,1581]],[[64690,64690],"mapped",[1589,1582]],[[64691,64691],"mapped",[1589,1605]],[[64692,64692],"mapped",[1590,1580]],[[64693,64693],"mapped",[1590,1581]],[[64694,64694],"mapped",[1590,1582]],[[64695,64695],"mapped",[1590,1605]],[[64696,64696],"mapped",[1591,1581]],[[64697,64697],"mapped",[1592,1605]],[[64698,64698],"mapped",[1593,1580]],[[64699,64699],"mapped",[1593,1605]],[[64700,64700],"mapped",[1594,1580]],[[64701,64701],"mapped",[1594,1605]],[[64702,64702],"mapped",[1601,1580]],[[64703,64703],"mapped",[1601,1581]],[[64704,64704],"mapped",[1601,1582]],[[64705,64705],"mapped",[1601,1605]],[[64706,64706],"mapped",[1602,1581]],[[64707,64707],"mapped",[1602,1605]],[[64708,64708],"mapped",[1603,1580]],[[64709,64709],"mapped",[1603,1581]],[[64710,64710],"mapped",[1603,1582]],[[64711,64711],"mapped",[1603,1604]],[[64712,64712],"mapped",[1603,1605]],[[64713,64713],"mapped",[1604,1580]],[[64714,64714],"mapped",[1604,1581]],[[64715,64715],"mapped",[1604,1582]],[[64716,64716],"mapped",[1604,1605]],[[64717,64717],"mapped",[1604,1607]],[[64718,64718],"mapped",[1605,1580]],[[64719,64719],"mapped",[1605,1581]],[[64720,64720],"mapped",[1605,1582]],[[64721,64721],"mapped",[1605,1605]],[[64722,64722],"mapped",[1606,1580]],[[64723,64723],"mapped",[1606,1581]],[[64724,64724],"mapped",[1606,1582]],[[64725,64725],"mapped",[1606,1605]],[[64726,64726],"mapped",[1606,1607]],[[64727,64727],"mapped",[1607,1580]],[[64728,64728],"mapped",[1607,1605]],[[64729,64729],"mapped",[1607,1648]],[[64730,64730],"mapped",[1610,1580]],[[64731,64731],"mapped",[1610,1581]],[[64732,64732],"mapped",[1610,1582]],[[64733,64733],"mapped",[1610,1605]],[[64734,64734],"mapped",[1610,1607]],[[64735,64735],"mapped",[1574,1605]],[[64736,64736],"mapped",[1574,1607]],[[64737,64737],"mapped",[1576,1605]],[[64738,64738],"mapped",[1576,1607]],[[64739,64739],"mapped",[1578,1605]],[[64740,64740],"mapped",[1578,1607]],[[64741,64741],"mapped",[1579,1605]],[[64742,64742],"mapped",[1579,1607]],[[64743,64743],"mapped",[1587,1605]],[[64744,64744],"mapped",[1587,1607]],[[64745,64745],"mapped",[1588,1605]],[[64746,64746],"mapped",[1588,1607]],[[64747,64747],"mapped",[1603,1604]],[[64748,64748],"mapped",[1603,1605]],[[64749,64749],"mapped",[1604,1605]],[[64750,64750],"mapped",[1606,1605]],[[64751,64751],"mapped",[1606,1607]],[[64752,64752],"mapped",[1610,1605]],[[64753,64753],"mapped",[1610,1607]],[[64754,64754],"mapped",[1600,1614,1617]],[[64755,64755],"mapped",[1600,1615,1617]],[[64756,64756],"mapped",[1600,1616,1617]],[[64757,64757],"mapped",[1591,1609]],[[64758,64758],"mapped",[1591,1610]],[[64759,64759],"mapped",[1593,1609]],[[64760,64760],"mapped",[1593,1610]],[[64761,64761],"mapped",[1594,1609]],[[64762,64762],"mapped",[1594,1610]],[[64763,64763],"mapped",[1587,1609]],[[64764,64764],"mapped",[1587,1610]],[[64765,64765],"mapped",[1588,1609]],[[64766,64766],"mapped",[1588,1610]],[[64767,64767],"mapped",[1581,1609]],[[64768,64768],"mapped",[1581,1610]],[[64769,64769],"mapped",[1580,1609]],[[64770,64770],"mapped",[1580,1610]],[[64771,64771],"mapped",[1582,1609]],[[64772,64772],"mapped",[1582,1610]],[[64773,64773],"mapped",[1589,1609]],[[64774,64774],"mapped",[1589,1610]],[[64775,64775],"mapped",[1590,1609]],[[64776,64776],"mapped",[1590,1610]],[[64777,64777],"mapped",[1588,1580]],[[64778,64778],"mapped",[1588,1581]],[[64779,64779],"mapped",[1588,1582]],[[64780,64780],"mapped",[1588,1605]],[[64781,64781],"mapped",[1588,1585]],[[64782,64782],"mapped",[1587,1585]],[[64783,64783],"mapped",[1589,1585]],[[64784,64784],"mapped",[1590,1585]],[[64785,64785],"mapped",[1591,1609]],[[64786,64786],"mapped",[1591,1610]],[[64787,64787],"mapped",[1593,1609]],[[64788,64788],"mapped",[1593,1610]],[[64789,64789],"mapped",[1594,1609]],[[64790,64790],"mapped",[1594,1610]],[[64791,64791],"mapped",[1587,1609]],[[64792,64792],"mapped",[1587,1610]],[[64793,64793],"mapped",[1588,1609]],[[64794,64794],"mapped",[1588,1610]],[[64795,64795],"mapped",[1581,1609]],[[64796,64796],"mapped",[1581,1610]],[[64797,64797],"mapped",[1580,1609]],[[64798,64798],"mapped",[1580,1610]],[[64799,64799],"mapped",[1582,1609]],[[64800,64800],"mapped",[1582,1610]],[[64801,64801],"mapped",[1589,1609]],[[64802,64802],"mapped",[1589,1610]],[[64803,64803],"mapped",[1590,1609]],[[64804,64804],"mapped",[1590,1610]],[[64805,64805],"mapped",[1588,1580]],[[64806,64806],"mapped",[1588,1581]],[[64807,64807],"mapped",[1588,1582]],[[64808,64808],"mapped",[1588,1605]],[[64809,64809],"mapped",[1588,1585]],[[64810,64810],"mapped",[1587,1585]],[[64811,64811],"mapped",[1589,1585]],[[64812,64812],"mapped",[1590,1585]],[[64813,64813],"mapped",[1588,1580]],[[64814,64814],"mapped",[1588,1581]],[[64815,64815],"mapped",[1588,1582]],[[64816,64816],"mapped",[1588,1605]],[[64817,64817],"mapped",[1587,1607]],[[64818,64818],"mapped",[1588,1607]],[[64819,64819],"mapped",[1591,1605]],[[64820,64820],"mapped",[1587,1580]],[[64821,64821],"mapped",[1587,1581]],[[64822,64822],"mapped",[1587,1582]],[[64823,64823],"mapped",[1588,1580]],[[64824,64824],"mapped",[1588,1581]],[[64825,64825],"mapped",[1588,1582]],[[64826,64826],"mapped",[1591,1605]],[[64827,64827],"mapped",[1592,1605]],[[64828,64829],"mapped",[1575,1611]],[[64830,64831],"valid",[],"NV8"],[[64832,64847],"disallowed"],[[64848,64848],"mapped",[1578,1580,1605]],[[64849,64850],"mapped",[1578,1581,1580]],[[64851,64851],"mapped",[1578,1581,1605]],[[64852,64852],"mapped",[1578,1582,1605]],[[64853,64853],"mapped",[1578,1605,1580]],[[64854,64854],"mapped",[1578,1605,1581]],[[64855,64855],"mapped",[1578,1605,1582]],[[64856,64857],"mapped",[1580,1605,1581]],[[64858,64858],"mapped",[1581,1605,1610]],[[64859,64859],"mapped",[1581,1605,1609]],[[64860,64860],"mapped",[1587,1581,1580]],[[64861,64861],"mapped",[1587,1580,1581]],[[64862,64862],"mapped",[1587,1580,1609]],[[64863,64864],"mapped",[1587,1605,1581]],[[64865,64865],"mapped",[1587,1605,1580]],[[64866,64867],"mapped",[1587,1605,1605]],[[64868,64869],"mapped",[1589,1581,1581]],[[64870,64870],"mapped",[1589,1605,1605]],[[64871,64872],"mapped",[1588,1581,1605]],[[64873,64873],"mapped",[1588,1580,1610]],[[64874,64875],"mapped",[1588,1605,1582]],[[64876,64877],"mapped",[1588,1605,1605]],[[64878,64878],"mapped",[1590,1581,1609]],[[64879,64880],"mapped",[1590,1582,1605]],[[64881,64882],"mapped",[1591,1605,1581]],[[64883,64883],"mapped",[1591,1605,1605]],[[64884,64884],"mapped",[1591,1605,1610]],[[64885,64885],"mapped",[1593,1580,1605]],[[64886,64887],"mapped",[1593,1605,1605]],[[64888,64888],"mapped",[1593,1605,1609]],[[64889,64889],"mapped",[1594,1605,1605]],[[64890,64890],"mapped",[1594,1605,1610]],[[64891,64891],"mapped",[1594,1605,1609]],[[64892,64893],"mapped",[1601,1582,1605]],[[64894,64894],"mapped",[1602,1605,1581]],[[64895,64895],"mapped",[1602,1605,1605]],[[64896,64896],"mapped",[1604,1581,1605]],[[64897,64897],"mapped",[1604,1581,1610]],[[64898,64898],"mapped",[1604,1581,1609]],[[64899,64900],"mapped",[1604,1580,1580]],[[64901,64902],"mapped",[1604,1582,1605]],[[64903,64904],"mapped",[1604,1605,1581]],[[64905,64905],"mapped",[1605,1581,1580]],[[64906,64906],"mapped",[1605,1581,1605]],[[64907,64907],"mapped",[1605,1581,1610]],[[64908,64908],"mapped",[1605,1580,1581]],[[64909,64909],"mapped",[1605,1580,1605]],[[64910,64910],"mapped",[1605,1582,1580]],[[64911,64911],"mapped",[1605,1582,1605]],[[64912,64913],"disallowed"],[[64914,64914],"mapped",[1605,1580,1582]],[[64915,64915],"mapped",[1607,1605,1580]],[[64916,64916],"mapped",[1607,1605,1605]],[[64917,64917],"mapped",[1606,1581,1605]],[[64918,64918],"mapped",[1606,1581,1609]],[[64919,64920],"mapped",[1606,1580,1605]],[[64921,64921],"mapped",[1606,1580,1609]],[[64922,64922],"mapped",[1606,1605,1610]],[[64923,64923],"mapped",[1606,1605,1609]],[[64924,64925],"mapped",[1610,1605,1605]],[[64926,64926],"mapped",[1576,1582,1610]],[[64927,64927],"mapped",[1578,1580,1610]],[[64928,64928],"mapped",[1578,1580,1609]],[[64929,64929],"mapped",[1578,1582,1610]],[[64930,64930],"mapped",[1578,1582,1609]],[[64931,64931],"mapped",[1578,1605,1610]],[[64932,64932],"mapped",[1578,1605,1609]],[[64933,64933],"mapped",[1580,1605,1610]],[[64934,64934],"mapped",[1580,1581,1609]],[[64935,64935],"mapped",[1580,1605,1609]],[[64936,64936],"mapped",[1587,1582,1609]],[[64937,64937],"mapped",[1589,1581,1610]],[[64938,64938],"mapped",[1588,1581,1610]],[[64939,64939],"mapped",[1590,1581,1610]],[[64940,64940],"mapped",[1604,1580,1610]],[[64941,64941],"mapped",[1604,1605,1610]],[[64942,64942],"mapped",[1610,1581,1610]],[[64943,64943],"mapped",[1610,1580,1610]],[[64944,64944],"mapped",[1610,1605,1610]],[[64945,64945],"mapped",[1605,1605,1610]],[[64946,64946],"mapped",[1602,1605,1610]],[[64947,64947],"mapped",[1606,1581,1610]],[[64948,64948],"mapped",[1602,1605,1581]],[[64949,64949],"mapped",[1604,1581,1605]],[[64950,64950],"mapped",[1593,1605,1610]],[[64951,64951],"mapped",[1603,1605,1610]],[[64952,64952],"mapped",[1606,1580,1581]],[[64953,64953],"mapped",[1605,1582,1610]],[[64954,64954],"mapped",[1604,1580,1605]],[[64955,64955],"mapped",[1603,1605,1605]],[[64956,64956],"mapped",[1604,1580,1605]],[[64957,64957],"mapped",[1606,1580,1581]],[[64958,64958],"mapped",[1580,1581,1610]],[[64959,64959],"mapped",[1581,1580,1610]],[[64960,64960],"mapped",[1605,1580,1610]],[[64961,64961],"mapped",[1601,1605,1610]],[[64962,64962],"mapped",[1576,1581,1610]],[[64963,64963],"mapped",[1603,1605,1605]],[[64964,64964],"mapped",[1593,1580,1605]],[[64965,64965],"mapped",[1589,1605,1605]],[[64966,64966],"mapped",[1587,1582,1610]],[[64967,64967],"mapped",[1606,1580,1610]],[[64968,64975],"disallowed"],[[64976,65007],"disallowed"],[[65008,65008],"mapped",[1589,1604,1746]],[[65009,65009],"mapped",[1602,1604,1746]],[[65010,65010],"mapped",[1575,1604,1604,1607]],[[65011,65011],"mapped",[1575,1603,1576,1585]],[[65012,65012],"mapped",[1605,1581,1605,1583]],[[65013,65013],"mapped",[1589,1604,1593,1605]],[[65014,65014],"mapped",[1585,1587,1608,1604]],[[65015,65015],"mapped",[1593,1604,1610,1607]],[[65016,65016],"mapped",[1608,1587,1604,1605]],[[65017,65017],"mapped",[1589,1604,1609]],[[65018,65018],"disallowed_STD3_mapped",[1589,1604,1609,32,1575,1604,1604,1607,32,1593,1604,1610,1607,32,1608,1587,1604,1605]],[[65019,65019],"disallowed_STD3_mapped",[1580,1604,32,1580,1604,1575,1604,1607]],[[65020,65020],"mapped",[1585,1740,1575,1604]],[[65021,65021],"valid",[],"NV8"],[[65022,65023],"disallowed"],[[65024,65039],"ignored"],[[65040,65040],"disallowed_STD3_mapped",[44]],[[65041,65041],"mapped",[12289]],[[65042,65042],"disallowed"],[[65043,65043],"disallowed_STD3_mapped",[58]],[[65044,65044],"disallowed_STD3_mapped",[59]],[[65045,65045],"disallowed_STD3_mapped",[33]],[[65046,65046],"disallowed_STD3_mapped",[63]],[[65047,65047],"mapped",[12310]],[[65048,65048],"mapped",[12311]],[[65049,65049],"disallowed"],[[65050,65055],"disallowed"],[[65056,65059],"valid"],[[65060,65062],"valid"],[[65063,65069],"valid"],[[65070,65071],"valid"],[[65072,65072],"disallowed"],[[65073,65073],"mapped",[8212]],[[65074,65074],"mapped",[8211]],[[65075,65076],"disallowed_STD3_mapped",[95]],[[65077,65077],"disallowed_STD3_mapped",[40]],[[65078,65078],"disallowed_STD3_mapped",[41]],[[65079,65079],"disallowed_STD3_mapped",[123]],[[65080,65080],"disallowed_STD3_mapped",[125]],[[65081,65081],"mapped",[12308]],[[65082,65082],"mapped",[12309]],[[65083,65083],"mapped",[12304]],[[65084,65084],"mapped",[12305]],[[65085,65085],"mapped",[12298]],[[65086,65086],"mapped",[12299]],[[65087,65087],"mapped",[12296]],[[65088,65088],"mapped",[12297]],[[65089,65089],"mapped",[12300]],[[65090,65090],"mapped",[12301]],[[65091,65091],"mapped",[12302]],[[65092,65092],"mapped",[12303]],[[65093,65094],"valid",[],"NV8"],[[65095,65095],"disallowed_STD3_mapped",[91]],[[65096,65096],"disallowed_STD3_mapped",[93]],[[65097,65100],"disallowed_STD3_mapped",[32,773]],[[65101,65103],"disallowed_STD3_mapped",[95]],[[65104,65104],"disallowed_STD3_mapped",[44]],[[65105,65105],"mapped",[12289]],[[65106,65106],"disallowed"],[[65107,65107],"disallowed"],[[65108,65108],"disallowed_STD3_mapped",[59]],[[65109,65109],"disallowed_STD3_mapped",[58]],[[65110,65110],"disallowed_STD3_mapped",[63]],[[65111,65111],"disallowed_STD3_mapped",[33]],[[65112,65112],"mapped",[8212]],[[65113,65113],"disallowed_STD3_mapped",[40]],[[65114,65114],"disallowed_STD3_mapped",[41]],[[65115,65115],"disallowed_STD3_mapped",[123]],[[65116,65116],"disallowed_STD3_mapped",[125]],[[65117,65117],"mapped",[12308]],[[65118,65118],"mapped",[12309]],[[65119,65119],"disallowed_STD3_mapped",[35]],[[65120,65120],"disallowed_STD3_mapped",[38]],[[65121,65121],"disallowed_STD3_mapped",[42]],[[65122,65122],"disallowed_STD3_mapped",[43]],[[65123,65123],"mapped",[45]],[[65124,65124],"disallowed_STD3_mapped",[60]],[[65125,65125],"disallowed_STD3_mapped",[62]],[[65126,65126],"disallowed_STD3_mapped",[61]],[[65127,65127],"disallowed"],[[65128,65128],"disallowed_STD3_mapped",[92]],[[65129,65129],"disallowed_STD3_mapped",[36]],[[65130,65130],"disallowed_STD3_mapped",[37]],[[65131,65131],"disallowed_STD3_mapped",[64]],[[65132,65135],"disallowed"],[[65136,65136],"disallowed_STD3_mapped",[32,1611]],[[65137,65137],"mapped",[1600,1611]],[[65138,65138],"disallowed_STD3_mapped",[32,1612]],[[65139,65139],"valid"],[[65140,65140],"disallowed_STD3_mapped",[32,1613]],[[65141,65141],"disallowed"],[[65142,65142],"disallowed_STD3_mapped",[32,1614]],[[65143,65143],"mapped",[1600,1614]],[[65144,65144],"disallowed_STD3_mapped",[32,1615]],[[65145,65145],"mapped",[1600,1615]],[[65146,65146],"disallowed_STD3_mapped",[32,1616]],[[65147,65147],"mapped",[1600,1616]],[[65148,65148],"disallowed_STD3_mapped",[32,1617]],[[65149,65149],"mapped",[1600,1617]],[[65150,65150],"disallowed_STD3_mapped",[32,1618]],[[65151,65151],"mapped",[1600,1618]],[[65152,65152],"mapped",[1569]],[[65153,65154],"mapped",[1570]],[[65155,65156],"mapped",[1571]],[[65157,65158],"mapped",[1572]],[[65159,65160],"mapped",[1573]],[[65161,65164],"mapped",[1574]],[[65165,65166],"mapped",[1575]],[[65167,65170],"mapped",[1576]],[[65171,65172],"mapped",[1577]],[[65173,65176],"mapped",[1578]],[[65177,65180],"mapped",[1579]],[[65181,65184],"mapped",[1580]],[[65185,65188],"mapped",[1581]],[[65189,65192],"mapped",[1582]],[[65193,65194],"mapped",[1583]],[[65195,65196],"mapped",[1584]],[[65197,65198],"mapped",[1585]],[[65199,65200],"mapped",[1586]],[[65201,65204],"mapped",[1587]],[[65205,65208],"mapped",[1588]],[[65209,65212],"mapped",[1589]],[[65213,65216],"mapped",[1590]],[[65217,65220],"mapped",[1591]],[[65221,65224],"mapped",[1592]],[[65225,65228],"mapped",[1593]],[[65229,65232],"mapped",[1594]],[[65233,65236],"mapped",[1601]],[[65237,65240],"mapped",[1602]],[[65241,65244],"mapped",[1603]],[[65245,65248],"mapped",[1604]],[[65249,65252],"mapped",[1605]],[[65253,65256],"mapped",[1606]],[[65257,65260],"mapped",[1607]],[[65261,65262],"mapped",[1608]],[[65263,65264],"mapped",[1609]],[[65265,65268],"mapped",[1610]],[[65269,65270],"mapped",[1604,1570]],[[65271,65272],"mapped",[1604,1571]],[[65273,65274],"mapped",[1604,1573]],[[65275,65276],"mapped",[1604,1575]],[[65277,65278],"disallowed"],[[65279,65279],"ignored"],[[65280,65280],"disallowed"],[[65281,65281],"disallowed_STD3_mapped",[33]],[[65282,65282],"disallowed_STD3_mapped",[34]],[[65283,65283],"disallowed_STD3_mapped",[35]],[[65284,65284],"disallowed_STD3_mapped",[36]],[[65285,65285],"disallowed_STD3_mapped",[37]],[[65286,65286],"disallowed_STD3_mapped",[38]],[[65287,65287],"disallowed_STD3_mapped",[39]],[[65288,65288],"disallowed_STD3_mapped",[40]],[[65289,65289],"disallowed_STD3_mapped",[41]],[[65290,65290],"disallowed_STD3_mapped",[42]],[[65291,65291],"disallowed_STD3_mapped",[43]],[[65292,65292],"disallowed_STD3_mapped",[44]],[[65293,65293],"mapped",[45]],[[65294,65294],"mapped",[46]],[[65295,65295],"disallowed_STD3_mapped",[47]],[[65296,65296],"mapped",[48]],[[65297,65297],"mapped",[49]],[[65298,65298],"mapped",[50]],[[65299,65299],"mapped",[51]],[[65300,65300],"mapped",[52]],[[65301,65301],"mapped",[53]],[[65302,65302],"mapped",[54]],[[65303,65303],"mapped",[55]],[[65304,65304],"mapped",[56]],[[65305,65305],"mapped",[57]],[[65306,65306],"disallowed_STD3_mapped",[58]],[[65307,65307],"disallowed_STD3_mapped",[59]],[[65308,65308],"disallowed_STD3_mapped",[60]],[[65309,65309],"disallowed_STD3_mapped",[61]],[[65310,65310],"disallowed_STD3_mapped",[62]],[[65311,65311],"disallowed_STD3_mapped",[63]],[[65312,65312],"disallowed_STD3_mapped",[64]],[[65313,65313],"mapped",[97]],[[65314,65314],"mapped",[98]],[[65315,65315],"mapped",[99]],[[65316,65316],"mapped",[100]],[[65317,65317],"mapped",[101]],[[65318,65318],"mapped",[102]],[[65319,65319],"mapped",[103]],[[65320,65320],"mapped",[104]],[[65321,65321],"mapped",[105]],[[65322,65322],"mapped",[106]],[[65323,65323],"mapped",[107]],[[65324,65324],"mapped",[108]],[[65325,65325],"mapped",[109]],[[65326,65326],"mapped",[110]],[[65327,65327],"mapped",[111]],[[65328,65328],"mapped",[112]],[[65329,65329],"mapped",[113]],[[65330,65330],"mapped",[114]],[[65331,65331],"mapped",[115]],[[65332,65332],"mapped",[116]],[[65333,65333],"mapped",[117]],[[65334,65334],"mapped",[118]],[[65335,65335],"mapped",[119]],[[65336,65336],"mapped",[120]],[[65337,65337],"mapped",[121]],[[65338,65338],"mapped",[122]],[[65339,65339],"disallowed_STD3_mapped",[91]],[[65340,65340],"disallowed_STD3_mapped",[92]],[[65341,65341],"disallowed_STD3_mapped",[93]],[[65342,65342],"disallowed_STD3_mapped",[94]],[[65343,65343],"disallowed_STD3_mapped",[95]],[[65344,65344],"disallowed_STD3_mapped",[96]],[[65345,65345],"mapped",[97]],[[65346,65346],"mapped",[98]],[[65347,65347],"mapped",[99]],[[65348,65348],"mapped",[100]],[[65349,65349],"mapped",[101]],[[65350,65350],"mapped",[102]],[[65351,65351],"mapped",[103]],[[65352,65352],"mapped",[104]],[[65353,65353],"mapped",[105]],[[65354,65354],"mapped",[106]],[[65355,65355],"mapped",[107]],[[65356,65356],"mapped",[108]],[[65357,65357],"mapped",[109]],[[65358,65358],"mapped",[110]],[[65359,65359],"mapped",[111]],[[65360,65360],"mapped",[112]],[[65361,65361],"mapped",[113]],[[65362,65362],"mapped",[114]],[[65363,65363],"mapped",[115]],[[65364,65364],"mapped",[116]],[[65365,65365],"mapped",[117]],[[65366,65366],"mapped",[118]],[[65367,65367],"mapped",[119]],[[65368,65368],"mapped",[120]],[[65369,65369],"mapped",[121]],[[65370,65370],"mapped",[122]],[[65371,65371],"disallowed_STD3_mapped",[123]],[[65372,65372],"disallowed_STD3_mapped",[124]],[[65373,65373],"disallowed_STD3_mapped",[125]],[[65374,65374],"disallowed_STD3_mapped",[126]],[[65375,65375],"mapped",[10629]],[[65376,65376],"mapped",[10630]],[[65377,65377],"mapped",[46]],[[65378,65378],"mapped",[12300]],[[65379,65379],"mapped",[12301]],[[65380,65380],"mapped",[12289]],[[65381,65381],"mapped",[12539]],[[65382,65382],"mapped",[12530]],[[65383,65383],"mapped",[12449]],[[65384,65384],"mapped",[12451]],[[65385,65385],"mapped",[12453]],[[65386,65386],"mapped",[12455]],[[65387,65387],"mapped",[12457]],[[65388,65388],"mapped",[12515]],[[65389,65389],"mapped",[12517]],[[65390,65390],"mapped",[12519]],[[65391,65391],"mapped",[12483]],[[65392,65392],"mapped",[12540]],[[65393,65393],"mapped",[12450]],[[65394,65394],"mapped",[12452]],[[65395,65395],"mapped",[12454]],[[65396,65396],"mapped",[12456]],[[65397,65397],"mapped",[12458]],[[65398,65398],"mapped",[12459]],[[65399,65399],"mapped",[12461]],[[65400,65400],"mapped",[12463]],[[65401,65401],"mapped",[12465]],[[65402,65402],"mapped",[12467]],[[65403,65403],"mapped",[12469]],[[65404,65404],"mapped",[12471]],[[65405,65405],"mapped",[12473]],[[65406,65406],"mapped",[12475]],[[65407,65407],"mapped",[12477]],[[65408,65408],"mapped",[12479]],[[65409,65409],"mapped",[12481]],[[65410,65410],"mapped",[12484]],[[65411,65411],"mapped",[12486]],[[65412,65412],"mapped",[12488]],[[65413,65413],"mapped",[12490]],[[65414,65414],"mapped",[12491]],[[65415,65415],"mapped",[12492]],[[65416,65416],"mapped",[12493]],[[65417,65417],"mapped",[12494]],[[65418,65418],"mapped",[12495]],[[65419,65419],"mapped",[12498]],[[65420,65420],"mapped",[12501]],[[65421,65421],"mapped",[12504]],[[65422,65422],"mapped",[12507]],[[65423,65423],"mapped",[12510]],[[65424,65424],"mapped",[12511]],[[65425,65425],"mapped",[12512]],[[65426,65426],"mapped",[12513]],[[65427,65427],"mapped",[12514]],[[65428,65428],"mapped",[12516]],[[65429,65429],"mapped",[12518]],[[65430,65430],"mapped",[12520]],[[65431,65431],"mapped",[12521]],[[65432,65432],"mapped",[12522]],[[65433,65433],"mapped",[12523]],[[65434,65434],"mapped",[12524]],[[65435,65435],"mapped",[12525]],[[65436,65436],"mapped",[12527]],[[65437,65437],"mapped",[12531]],[[65438,65438],"mapped",[12441]],[[65439,65439],"mapped",[12442]],[[65440,65440],"disallowed"],[[65441,65441],"mapped",[4352]],[[65442,65442],"mapped",[4353]],[[65443,65443],"mapped",[4522]],[[65444,65444],"mapped",[4354]],[[65445,65445],"mapped",[4524]],[[65446,65446],"mapped",[4525]],[[65447,65447],"mapped",[4355]],[[65448,65448],"mapped",[4356]],[[65449,65449],"mapped",[4357]],[[65450,65450],"mapped",[4528]],[[65451,65451],"mapped",[4529]],[[65452,65452],"mapped",[4530]],[[65453,65453],"mapped",[4531]],[[65454,65454],"mapped",[4532]],[[65455,65455],"mapped",[4533]],[[65456,65456],"mapped",[4378]],[[65457,65457],"mapped",[4358]],[[65458,65458],"mapped",[4359]],[[65459,65459],"mapped",[4360]],[[65460,65460],"mapped",[4385]],[[65461,65461],"mapped",[4361]],[[65462,65462],"mapped",[4362]],[[65463,65463],"mapped",[4363]],[[65464,65464],"mapped",[4364]],[[65465,65465],"mapped",[4365]],[[65466,65466],"mapped",[4366]],[[65467,65467],"mapped",[4367]],[[65468,65468],"mapped",[4368]],[[65469,65469],"mapped",[4369]],[[65470,65470],"mapped",[4370]],[[65471,65473],"disallowed"],[[65474,65474],"mapped",[4449]],[[65475,65475],"mapped",[4450]],[[65476,65476],"mapped",[4451]],[[65477,65477],"mapped",[4452]],[[65478,65478],"mapped",[4453]],[[65479,65479],"mapped",[4454]],[[65480,65481],"disallowed"],[[65482,65482],"mapped",[4455]],[[65483,65483],"mapped",[4456]],[[65484,65484],"mapped",[4457]],[[65485,65485],"mapped",[4458]],[[65486,65486],"mapped",[4459]],[[65487,65487],"mapped",[4460]],[[65488,65489],"disallowed"],[[65490,65490],"mapped",[4461]],[[65491,65491],"mapped",[4462]],[[65492,65492],"mapped",[4463]],[[65493,65493],"mapped",[4464]],[[65494,65494],"mapped",[4465]],[[65495,65495],"mapped",[4466]],[[65496,65497],"disallowed"],[[65498,65498],"mapped",[4467]],[[65499,65499],"mapped",[4468]],[[65500,65500],"mapped",[4469]],[[65501,65503],"disallowed"],[[65504,65504],"mapped",[162]],[[65505,65505],"mapped",[163]],[[65506,65506],"mapped",[172]],[[65507,65507],"disallowed_STD3_mapped",[32,772]],[[65508,65508],"mapped",[166]],[[65509,65509],"mapped",[165]],[[65510,65510],"mapped",[8361]],[[65511,65511],"disallowed"],[[65512,65512],"mapped",[9474]],[[65513,65513],"mapped",[8592]],[[65514,65514],"mapped",[8593]],[[65515,65515],"mapped",[8594]],[[65516,65516],"mapped",[8595]],[[65517,65517],"mapped",[9632]],[[65518,65518],"mapped",[9675]],[[65519,65528],"disallowed"],[[65529,65531],"disallowed"],[[65532,65532],"disallowed"],[[65533,65533],"disallowed"],[[65534,65535],"disallowed"],[[65536,65547],"valid"],[[65548,65548],"disallowed"],[[65549,65574],"valid"],[[65575,65575],"disallowed"],[[65576,65594],"valid"],[[65595,65595],"disallowed"],[[65596,65597],"valid"],[[65598,65598],"disallowed"],[[65599,65613],"valid"],[[65614,65615],"disallowed"],[[65616,65629],"valid"],[[65630,65663],"disallowed"],[[65664,65786],"valid"],[[65787,65791],"disallowed"],[[65792,65794],"valid",[],"NV8"],[[65795,65798],"disallowed"],[[65799,65843],"valid",[],"NV8"],[[65844,65846],"disallowed"],[[65847,65855],"valid",[],"NV8"],[[65856,65930],"valid",[],"NV8"],[[65931,65932],"valid",[],"NV8"],[[65933,65935],"disallowed"],[[65936,65947],"valid",[],"NV8"],[[65948,65951],"disallowed"],[[65952,65952],"valid",[],"NV8"],[[65953,65999],"disallowed"],[[66000,66044],"valid",[],"NV8"],[[66045,66045],"valid"],[[66046,66175],"disallowed"],[[66176,66204],"valid"],[[66205,66207],"disallowed"],[[66208,66256],"valid"],[[66257,66271],"disallowed"],[[66272,66272],"valid"],[[66273,66299],"valid",[],"NV8"],[[66300,66303],"disallowed"],[[66304,66334],"valid"],[[66335,66335],"valid"],[[66336,66339],"valid",[],"NV8"],[[66340,66351],"disallowed"],[[66352,66368],"valid"],[[66369,66369],"valid",[],"NV8"],[[66370,66377],"valid"],[[66378,66378],"valid",[],"NV8"],[[66379,66383],"disallowed"],[[66384,66426],"valid"],[[66427,66431],"disallowed"],[[66432,66461],"valid"],[[66462,66462],"disallowed"],[[66463,66463],"valid",[],"NV8"],[[66464,66499],"valid"],[[66500,66503],"disallowed"],[[66504,66511],"valid"],[[66512,66517],"valid",[],"NV8"],[[66518,66559],"disallowed"],[[66560,66560],"mapped",[66600]],[[66561,66561],"mapped",[66601]],[[66562,66562],"mapped",[66602]],[[66563,66563],"mapped",[66603]],[[66564,66564],"mapped",[66604]],[[66565,66565],"mapped",[66605]],[[66566,66566],"mapped",[66606]],[[66567,66567],"mapped",[66607]],[[66568,66568],"mapped",[66608]],[[66569,66569],"mapped",[66609]],[[66570,66570],"mapped",[66610]],[[66571,66571],"mapped",[66611]],[[66572,66572],"mapped",[66612]],[[66573,66573],"mapped",[66613]],[[66574,66574],"mapped",[66614]],[[66575,66575],"mapped",[66615]],[[66576,66576],"mapped",[66616]],[[66577,66577],"mapped",[66617]],[[66578,66578],"mapped",[66618]],[[66579,66579],"mapped",[66619]],[[66580,66580],"mapped",[66620]],[[66581,66581],"mapped",[66621]],[[66582,66582],"mapped",[66622]],[[66583,66583],"mapped",[66623]],[[66584,66584],"mapped",[66624]],[[66585,66585],"mapped",[66625]],[[66586,66586],"mapped",[66626]],[[66587,66587],"mapped",[66627]],[[66588,66588],"mapped",[66628]],[[66589,66589],"mapped",[66629]],[[66590,66590],"mapped",[66630]],[[66591,66591],"mapped",[66631]],[[66592,66592],"mapped",[66632]],[[66593,66593],"mapped",[66633]],[[66594,66594],"mapped",[66634]],[[66595,66595],"mapped",[66635]],[[66596,66596],"mapped",[66636]],[[66597,66597],"mapped",[66637]],[[66598,66598],"mapped",[66638]],[[66599,66599],"mapped",[66639]],[[66600,66637],"valid"],[[66638,66717],"valid"],[[66718,66719],"disallowed"],[[66720,66729],"valid"],[[66730,66815],"disallowed"],[[66816,66855],"valid"],[[66856,66863],"disallowed"],[[66864,66915],"valid"],[[66916,66926],"disallowed"],[[66927,66927],"valid",[],"NV8"],[[66928,67071],"disallowed"],[[67072,67382],"valid"],[[67383,67391],"disallowed"],[[67392,67413],"valid"],[[67414,67423],"disallowed"],[[67424,67431],"valid"],[[67432,67583],"disallowed"],[[67584,67589],"valid"],[[67590,67591],"disallowed"],[[67592,67592],"valid"],[[67593,67593],"disallowed"],[[67594,67637],"valid"],[[67638,67638],"disallowed"],[[67639,67640],"valid"],[[67641,67643],"disallowed"],[[67644,67644],"valid"],[[67645,67646],"disallowed"],[[67647,67647],"valid"],[[67648,67669],"valid"],[[67670,67670],"disallowed"],[[67671,67679],"valid",[],"NV8"],[[67680,67702],"valid"],[[67703,67711],"valid",[],"NV8"],[[67712,67742],"valid"],[[67743,67750],"disallowed"],[[67751,67759],"valid",[],"NV8"],[[67760,67807],"disallowed"],[[67808,67826],"valid"],[[67827,67827],"disallowed"],[[67828,67829],"valid"],[[67830,67834],"disallowed"],[[67835,67839],"valid",[],"NV8"],[[67840,67861],"valid"],[[67862,67865],"valid",[],"NV8"],[[67866,67867],"valid",[],"NV8"],[[67868,67870],"disallowed"],[[67871,67871],"valid",[],"NV8"],[[67872,67897],"valid"],[[67898,67902],"disallowed"],[[67903,67903],"valid",[],"NV8"],[[67904,67967],"disallowed"],[[67968,68023],"valid"],[[68024,68027],"disallowed"],[[68028,68029],"valid",[],"NV8"],[[68030,68031],"valid"],[[68032,68047],"valid",[],"NV8"],[[68048,68049],"disallowed"],[[68050,68095],"valid",[],"NV8"],[[68096,68099],"valid"],[[68100,68100],"disallowed"],[[68101,68102],"valid"],[[68103,68107],"disallowed"],[[68108,68115],"valid"],[[68116,68116],"disallowed"],[[68117,68119],"valid"],[[68120,68120],"disallowed"],[[68121,68147],"valid"],[[68148,68151],"disallowed"],[[68152,68154],"valid"],[[68155,68158],"disallowed"],[[68159,68159],"valid"],[[68160,68167],"valid",[],"NV8"],[[68168,68175],"disallowed"],[[68176,68184],"valid",[],"NV8"],[[68185,68191],"disallowed"],[[68192,68220],"valid"],[[68221,68223],"valid",[],"NV8"],[[68224,68252],"valid"],[[68253,68255],"valid",[],"NV8"],[[68256,68287],"disallowed"],[[68288,68295],"valid"],[[68296,68296],"valid",[],"NV8"],[[68297,68326],"valid"],[[68327,68330],"disallowed"],[[68331,68342],"valid",[],"NV8"],[[68343,68351],"disallowed"],[[68352,68405],"valid"],[[68406,68408],"disallowed"],[[68409,68415],"valid",[],"NV8"],[[68416,68437],"valid"],[[68438,68439],"disallowed"],[[68440,68447],"valid",[],"NV8"],[[68448,68466],"valid"],[[68467,68471],"disallowed"],[[68472,68479],"valid",[],"NV8"],[[68480,68497],"valid"],[[68498,68504],"disallowed"],[[68505,68508],"valid",[],"NV8"],[[68509,68520],"disallowed"],[[68521,68527],"valid",[],"NV8"],[[68528,68607],"disallowed"],[[68608,68680],"valid"],[[68681,68735],"disallowed"],[[68736,68736],"mapped",[68800]],[[68737,68737],"mapped",[68801]],[[68738,68738],"mapped",[68802]],[[68739,68739],"mapped",[68803]],[[68740,68740],"mapped",[68804]],[[68741,68741],"mapped",[68805]],[[68742,68742],"mapped",[68806]],[[68743,68743],"mapped",[68807]],[[68744,68744],"mapped",[68808]],[[68745,68745],"mapped",[68809]],[[68746,68746],"mapped",[68810]],[[68747,68747],"mapped",[68811]],[[68748,68748],"mapped",[68812]],[[68749,68749],"mapped",[68813]],[[68750,68750],"mapped",[68814]],[[68751,68751],"mapped",[68815]],[[68752,68752],"mapped",[68816]],[[68753,68753],"mapped",[68817]],[[68754,68754],"mapped",[68818]],[[68755,68755],"mapped",[68819]],[[68756,68756],"mapped",[68820]],[[68757,68757],"mapped",[68821]],[[68758,68758],"mapped",[68822]],[[68759,68759],"mapped",[68823]],[[68760,68760],"mapped",[68824]],[[68761,68761],"mapped",[68825]],[[68762,68762],"mapped",[68826]],[[68763,68763],"mapped",[68827]],[[68764,68764],"mapped",[68828]],[[68765,68765],"mapped",[68829]],[[68766,68766],"mapped",[68830]],[[68767,68767],"mapped",[68831]],[[68768,68768],"mapped",[68832]],[[68769,68769],"mapped",[68833]],[[68770,68770],"mapped",[68834]],[[68771,68771],"mapped",[68835]],[[68772,68772],"mapped",[68836]],[[68773,68773],"mapped",[68837]],[[68774,68774],"mapped",[68838]],[[68775,68775],"mapped",[68839]],[[68776,68776],"mapped",[68840]],[[68777,68777],"mapped",[68841]],[[68778,68778],"mapped",[68842]],[[68779,68779],"mapped",[68843]],[[68780,68780],"mapped",[68844]],[[68781,68781],"mapped",[68845]],[[68782,68782],"mapped",[68846]],[[68783,68783],"mapped",[68847]],[[68784,68784],"mapped",[68848]],[[68785,68785],"mapped",[68849]],[[68786,68786],"mapped",[68850]],[[68787,68799],"disallowed"],[[68800,68850],"valid"],[[68851,68857],"disallowed"],[[68858,68863],"valid",[],"NV8"],[[68864,69215],"disallowed"],[[69216,69246],"valid",[],"NV8"],[[69247,69631],"disallowed"],[[69632,69702],"valid"],[[69703,69709],"valid",[],"NV8"],[[69710,69713],"disallowed"],[[69714,69733],"valid",[],"NV8"],[[69734,69743],"valid"],[[69744,69758],"disallowed"],[[69759,69759],"valid"],[[69760,69818],"valid"],[[69819,69820],"valid",[],"NV8"],[[69821,69821],"disallowed"],[[69822,69825],"valid",[],"NV8"],[[69826,69839],"disallowed"],[[69840,69864],"valid"],[[69865,69871],"disallowed"],[[69872,69881],"valid"],[[69882,69887],"disallowed"],[[69888,69940],"valid"],[[69941,69941],"disallowed"],[[69942,69951],"valid"],[[69952,69955],"valid",[],"NV8"],[[69956,69967],"disallowed"],[[69968,70003],"valid"],[[70004,70005],"valid",[],"NV8"],[[70006,70006],"valid"],[[70007,70015],"disallowed"],[[70016,70084],"valid"],[[70085,70088],"valid",[],"NV8"],[[70089,70089],"valid",[],"NV8"],[[70090,70092],"valid"],[[70093,70093],"valid",[],"NV8"],[[70094,70095],"disallowed"],[[70096,70105],"valid"],[[70106,70106],"valid"],[[70107,70107],"valid",[],"NV8"],[[70108,70108],"valid"],[[70109,70111],"valid",[],"NV8"],[[70112,70112],"disallowed"],[[70113,70132],"valid",[],"NV8"],[[70133,70143],"disallowed"],[[70144,70161],"valid"],[[70162,70162],"disallowed"],[[70163,70199],"valid"],[[70200,70205],"valid",[],"NV8"],[[70206,70271],"disallowed"],[[70272,70278],"valid"],[[70279,70279],"disallowed"],[[70280,70280],"valid"],[[70281,70281],"disallowed"],[[70282,70285],"valid"],[[70286,70286],"disallowed"],[[70287,70301],"valid"],[[70302,70302],"disallowed"],[[70303,70312],"valid"],[[70313,70313],"valid",[],"NV8"],[[70314,70319],"disallowed"],[[70320,70378],"valid"],[[70379,70383],"disallowed"],[[70384,70393],"valid"],[[70394,70399],"disallowed"],[[70400,70400],"valid"],[[70401,70403],"valid"],[[70404,70404],"disallowed"],[[70405,70412],"valid"],[[70413,70414],"disallowed"],[[70415,70416],"valid"],[[70417,70418],"disallowed"],[[70419,70440],"valid"],[[70441,70441],"disallowed"],[[70442,70448],"valid"],[[70449,70449],"disallowed"],[[70450,70451],"valid"],[[70452,70452],"disallowed"],[[70453,70457],"valid"],[[70458,70459],"disallowed"],[[70460,70468],"valid"],[[70469,70470],"disallowed"],[[70471,70472],"valid"],[[70473,70474],"disallowed"],[[70475,70477],"valid"],[[70478,70479],"disallowed"],[[70480,70480],"valid"],[[70481,70486],"disallowed"],[[70487,70487],"valid"],[[70488,70492],"disallowed"],[[70493,70499],"valid"],[[70500,70501],"disallowed"],[[70502,70508],"valid"],[[70509,70511],"disallowed"],[[70512,70516],"valid"],[[70517,70783],"disallowed"],[[70784,70853],"valid"],[[70854,70854],"valid",[],"NV8"],[[70855,70855],"valid"],[[70856,70863],"disallowed"],[[70864,70873],"valid"],[[70874,71039],"disallowed"],[[71040,71093],"valid"],[[71094,71095],"disallowed"],[[71096,71104],"valid"],[[71105,71113],"valid",[],"NV8"],[[71114,71127],"valid",[],"NV8"],[[71128,71133],"valid"],[[71134,71167],"disallowed"],[[71168,71232],"valid"],[[71233,71235],"valid",[],"NV8"],[[71236,71236],"valid"],[[71237,71247],"disallowed"],[[71248,71257],"valid"],[[71258,71295],"disallowed"],[[71296,71351],"valid"],[[71352,71359],"disallowed"],[[71360,71369],"valid"],[[71370,71423],"disallowed"],[[71424,71449],"valid"],[[71450,71452],"disallowed"],[[71453,71467],"valid"],[[71468,71471],"disallowed"],[[71472,71481],"valid"],[[71482,71487],"valid",[],"NV8"],[[71488,71839],"disallowed"],[[71840,71840],"mapped",[71872]],[[71841,71841],"mapped",[71873]],[[71842,71842],"mapped",[71874]],[[71843,71843],"mapped",[71875]],[[71844,71844],"mapped",[71876]],[[71845,71845],"mapped",[71877]],[[71846,71846],"mapped",[71878]],[[71847,71847],"mapped",[71879]],[[71848,71848],"mapped",[71880]],[[71849,71849],"mapped",[71881]],[[71850,71850],"mapped",[71882]],[[71851,71851],"mapped",[71883]],[[71852,71852],"mapped",[71884]],[[71853,71853],"mapped",[71885]],[[71854,71854],"mapped",[71886]],[[71855,71855],"mapped",[71887]],[[71856,71856],"mapped",[71888]],[[71857,71857],"mapped",[71889]],[[71858,71858],"mapped",[71890]],[[71859,71859],"mapped",[71891]],[[71860,71860],"mapped",[71892]],[[71861,71861],"mapped",[71893]],[[71862,71862],"mapped",[71894]],[[71863,71863],"mapped",[71895]],[[71864,71864],"mapped",[71896]],[[71865,71865],"mapped",[71897]],[[71866,71866],"mapped",[71898]],[[71867,71867],"mapped",[71899]],[[71868,71868],"mapped",[71900]],[[71869,71869],"mapped",[71901]],[[71870,71870],"mapped",[71902]],[[71871,71871],"mapped",[71903]],[[71872,71913],"valid"],[[71914,71922],"valid",[],"NV8"],[[71923,71934],"disallowed"],[[71935,71935],"valid"],[[71936,72383],"disallowed"],[[72384,72440],"valid"],[[72441,73727],"disallowed"],[[73728,74606],"valid"],[[74607,74648],"valid"],[[74649,74649],"valid"],[[74650,74751],"disallowed"],[[74752,74850],"valid",[],"NV8"],[[74851,74862],"valid",[],"NV8"],[[74863,74863],"disallowed"],[[74864,74867],"valid",[],"NV8"],[[74868,74868],"valid",[],"NV8"],[[74869,74879],"disallowed"],[[74880,75075],"valid"],[[75076,77823],"disallowed"],[[77824,78894],"valid"],[[78895,82943],"disallowed"],[[82944,83526],"valid"],[[83527,92159],"disallowed"],[[92160,92728],"valid"],[[92729,92735],"disallowed"],[[92736,92766],"valid"],[[92767,92767],"disallowed"],[[92768,92777],"valid"],[[92778,92781],"disallowed"],[[92782,92783],"valid",[],"NV8"],[[92784,92879],"disallowed"],[[92880,92909],"valid"],[[92910,92911],"disallowed"],[[92912,92916],"valid"],[[92917,92917],"valid",[],"NV8"],[[92918,92927],"disallowed"],[[92928,92982],"valid"],[[92983,92991],"valid",[],"NV8"],[[92992,92995],"valid"],[[92996,92997],"valid",[],"NV8"],[[92998,93007],"disallowed"],[[93008,93017],"valid"],[[93018,93018],"disallowed"],[[93019,93025],"valid",[],"NV8"],[[93026,93026],"disallowed"],[[93027,93047],"valid"],[[93048,93052],"disallowed"],[[93053,93071],"valid"],[[93072,93951],"disallowed"],[[93952,94020],"valid"],[[94021,94031],"disallowed"],[[94032,94078],"valid"],[[94079,94094],"disallowed"],[[94095,94111],"valid"],[[94112,110591],"disallowed"],[[110592,110593],"valid"],[[110594,113663],"disallowed"],[[113664,113770],"valid"],[[113771,113775],"disallowed"],[[113776,113788],"valid"],[[113789,113791],"disallowed"],[[113792,113800],"valid"],[[113801,113807],"disallowed"],[[113808,113817],"valid"],[[113818,113819],"disallowed"],[[113820,113820],"valid",[],"NV8"],[[113821,113822],"valid"],[[113823,113823],"valid",[],"NV8"],[[113824,113827],"ignored"],[[113828,118783],"disallowed"],[[118784,119029],"valid",[],"NV8"],[[119030,119039],"disallowed"],[[119040,119078],"valid",[],"NV8"],[[119079,119080],"disallowed"],[[119081,119081],"valid",[],"NV8"],[[119082,119133],"valid",[],"NV8"],[[119134,119134],"mapped",[119127,119141]],[[119135,119135],"mapped",[119128,119141]],[[119136,119136],"mapped",[119128,119141,119150]],[[119137,119137],"mapped",[119128,119141,119151]],[[119138,119138],"mapped",[119128,119141,119152]],[[119139,119139],"mapped",[119128,119141,119153]],[[119140,119140],"mapped",[119128,119141,119154]],[[119141,119154],"valid",[],"NV8"],[[119155,119162],"disallowed"],[[119163,119226],"valid",[],"NV8"],[[119227,119227],"mapped",[119225,119141]],[[119228,119228],"mapped",[119226,119141]],[[119229,119229],"mapped",[119225,119141,119150]],[[119230,119230],"mapped",[119226,119141,119150]],[[119231,119231],"mapped",[119225,119141,119151]],[[119232,119232],"mapped",[119226,119141,119151]],[[119233,119261],"valid",[],"NV8"],[[119262,119272],"valid",[],"NV8"],[[119273,119295],"disallowed"],[[119296,119365],"valid",[],"NV8"],[[119366,119551],"disallowed"],[[119552,119638],"valid",[],"NV8"],[[119639,119647],"disallowed"],[[119648,119665],"valid",[],"NV8"],[[119666,119807],"disallowed"],[[119808,119808],"mapped",[97]],[[119809,119809],"mapped",[98]],[[119810,119810],"mapped",[99]],[[119811,119811],"mapped",[100]],[[119812,119812],"mapped",[101]],[[119813,119813],"mapped",[102]],[[119814,119814],"mapped",[103]],[[119815,119815],"mapped",[104]],[[119816,119816],"mapped",[105]],[[119817,119817],"mapped",[106]],[[119818,119818],"mapped",[107]],[[119819,119819],"mapped",[108]],[[119820,119820],"mapped",[109]],[[119821,119821],"mapped",[110]],[[119822,119822],"mapped",[111]],[[119823,119823],"mapped",[112]],[[119824,119824],"mapped",[113]],[[119825,119825],"mapped",[114]],[[119826,119826],"mapped",[115]],[[119827,119827],"mapped",[116]],[[119828,119828],"mapped",[117]],[[119829,119829],"mapped",[118]],[[119830,119830],"mapped",[119]],[[119831,119831],"mapped",[120]],[[119832,119832],"mapped",[121]],[[119833,119833],"mapped",[122]],[[119834,119834],"mapped",[97]],[[119835,119835],"mapped",[98]],[[119836,119836],"mapped",[99]],[[119837,119837],"mapped",[100]],[[119838,119838],"mapped",[101]],[[119839,119839],"mapped",[102]],[[119840,119840],"mapped",[103]],[[119841,119841],"mapped",[104]],[[119842,119842],"mapped",[105]],[[119843,119843],"mapped",[106]],[[119844,119844],"mapped",[107]],[[119845,119845],"mapped",[108]],[[119846,119846],"mapped",[109]],[[119847,119847],"mapped",[110]],[[119848,119848],"mapped",[111]],[[119849,119849],"mapped",[112]],[[119850,119850],"mapped",[113]],[[119851,119851],"mapped",[114]],[[119852,119852],"mapped",[115]],[[119853,119853],"mapped",[116]],[[119854,119854],"mapped",[117]],[[119855,119855],"mapped",[118]],[[119856,119856],"mapped",[119]],[[119857,119857],"mapped",[120]],[[119858,119858],"mapped",[121]],[[119859,119859],"mapped",[122]],[[119860,119860],"mapped",[97]],[[119861,119861],"mapped",[98]],[[119862,119862],"mapped",[99]],[[119863,119863],"mapped",[100]],[[119864,119864],"mapped",[101]],[[119865,119865],"mapped",[102]],[[119866,119866],"mapped",[103]],[[119867,119867],"mapped",[104]],[[119868,119868],"mapped",[105]],[[119869,119869],"mapped",[106]],[[119870,119870],"mapped",[107]],[[119871,119871],"mapped",[108]],[[119872,119872],"mapped",[109]],[[119873,119873],"mapped",[110]],[[119874,119874],"mapped",[111]],[[119875,119875],"mapped",[112]],[[119876,119876],"mapped",[113]],[[119877,119877],"mapped",[114]],[[119878,119878],"mapped",[115]],[[119879,119879],"mapped",[116]],[[119880,119880],"mapped",[117]],[[119881,119881],"mapped",[118]],[[119882,119882],"mapped",[119]],[[119883,119883],"mapped",[120]],[[119884,119884],"mapped",[121]],[[119885,119885],"mapped",[122]],[[119886,119886],"mapped",[97]],[[119887,119887],"mapped",[98]],[[119888,119888],"mapped",[99]],[[119889,119889],"mapped",[100]],[[119890,119890],"mapped",[101]],[[119891,119891],"mapped",[102]],[[119892,119892],"mapped",[103]],[[119893,119893],"disallowed"],[[119894,119894],"mapped",[105]],[[119895,119895],"mapped",[106]],[[119896,119896],"mapped",[107]],[[119897,119897],"mapped",[108]],[[119898,119898],"mapped",[109]],[[119899,119899],"mapped",[110]],[[119900,119900],"mapped",[111]],[[119901,119901],"mapped",[112]],[[119902,119902],"mapped",[113]],[[119903,119903],"mapped",[114]],[[119904,119904],"mapped",[115]],[[119905,119905],"mapped",[116]],[[119906,119906],"mapped",[117]],[[119907,119907],"mapped",[118]],[[119908,119908],"mapped",[119]],[[119909,119909],"mapped",[120]],[[119910,119910],"mapped",[121]],[[119911,119911],"mapped",[122]],[[119912,119912],"mapped",[97]],[[119913,119913],"mapped",[98]],[[119914,119914],"mapped",[99]],[[119915,119915],"mapped",[100]],[[119916,119916],"mapped",[101]],[[119917,119917],"mapped",[102]],[[119918,119918],"mapped",[103]],[[119919,119919],"mapped",[104]],[[119920,119920],"mapped",[105]],[[119921,119921],"mapped",[106]],[[119922,119922],"mapped",[107]],[[119923,119923],"mapped",[108]],[[119924,119924],"mapped",[109]],[[119925,119925],"mapped",[110]],[[119926,119926],"mapped",[111]],[[119927,119927],"mapped",[112]],[[119928,119928],"mapped",[113]],[[119929,119929],"mapped",[114]],[[119930,119930],"mapped",[115]],[[119931,119931],"mapped",[116]],[[119932,119932],"mapped",[117]],[[119933,119933],"mapped",[118]],[[119934,119934],"mapped",[119]],[[119935,119935],"mapped",[120]],[[119936,119936],"mapped",[121]],[[119937,119937],"mapped",[122]],[[119938,119938],"mapped",[97]],[[119939,119939],"mapped",[98]],[[119940,119940],"mapped",[99]],[[119941,119941],"mapped",[100]],[[119942,119942],"mapped",[101]],[[119943,119943],"mapped",[102]],[[119944,119944],"mapped",[103]],[[119945,119945],"mapped",[104]],[[119946,119946],"mapped",[105]],[[119947,119947],"mapped",[106]],[[119948,119948],"mapped",[107]],[[119949,119949],"mapped",[108]],[[119950,119950],"mapped",[109]],[[119951,119951],"mapped",[110]],[[119952,119952],"mapped",[111]],[[119953,119953],"mapped",[112]],[[119954,119954],"mapped",[113]],[[119955,119955],"mapped",[114]],[[119956,119956],"mapped",[115]],[[119957,119957],"mapped",[116]],[[119958,119958],"mapped",[117]],[[119959,119959],"mapped",[118]],[[119960,119960],"mapped",[119]],[[119961,119961],"mapped",[120]],[[119962,119962],"mapped",[121]],[[119963,119963],"mapped",[122]],[[119964,119964],"mapped",[97]],[[119965,119965],"disallowed"],[[119966,119966],"mapped",[99]],[[119967,119967],"mapped",[100]],[[119968,119969],"disallowed"],[[119970,119970],"mapped",[103]],[[119971,119972],"disallowed"],[[119973,119973],"mapped",[106]],[[119974,119974],"mapped",[107]],[[119975,119976],"disallowed"],[[119977,119977],"mapped",[110]],[[119978,119978],"mapped",[111]],[[119979,119979],"mapped",[112]],[[119980,119980],"mapped",[113]],[[119981,119981],"disallowed"],[[119982,119982],"mapped",[115]],[[119983,119983],"mapped",[116]],[[119984,119984],"mapped",[117]],[[119985,119985],"mapped",[118]],[[119986,119986],"mapped",[119]],[[119987,119987],"mapped",[120]],[[119988,119988],"mapped",[121]],[[119989,119989],"mapped",[122]],[[119990,119990],"mapped",[97]],[[119991,119991],"mapped",[98]],[[119992,119992],"mapped",[99]],[[119993,119993],"mapped",[100]],[[119994,119994],"disallowed"],[[119995,119995],"mapped",[102]],[[119996,119996],"disallowed"],[[119997,119997],"mapped",[104]],[[119998,119998],"mapped",[105]],[[119999,119999],"mapped",[106]],[[120000,120000],"mapped",[107]],[[120001,120001],"mapped",[108]],[[120002,120002],"mapped",[109]],[[120003,120003],"mapped",[110]],[[120004,120004],"disallowed"],[[120005,120005],"mapped",[112]],[[120006,120006],"mapped",[113]],[[120007,120007],"mapped",[114]],[[120008,120008],"mapped",[115]],[[120009,120009],"mapped",[116]],[[120010,120010],"mapped",[117]],[[120011,120011],"mapped",[118]],[[120012,120012],"mapped",[119]],[[120013,120013],"mapped",[120]],[[120014,120014],"mapped",[121]],[[120015,120015],"mapped",[122]],[[120016,120016],"mapped",[97]],[[120017,120017],"mapped",[98]],[[120018,120018],"mapped",[99]],[[120019,120019],"mapped",[100]],[[120020,120020],"mapped",[101]],[[120021,120021],"mapped",[102]],[[120022,120022],"mapped",[103]],[[120023,120023],"mapped",[104]],[[120024,120024],"mapped",[105]],[[120025,120025],"mapped",[106]],[[120026,120026],"mapped",[107]],[[120027,120027],"mapped",[108]],[[120028,120028],"mapped",[109]],[[120029,120029],"mapped",[110]],[[120030,120030],"mapped",[111]],[[120031,120031],"mapped",[112]],[[120032,120032],"mapped",[113]],[[120033,120033],"mapped",[114]],[[120034,120034],"mapped",[115]],[[120035,120035],"mapped",[116]],[[120036,120036],"mapped",[117]],[[120037,120037],"mapped",[118]],[[120038,120038],"mapped",[119]],[[120039,120039],"mapped",[120]],[[120040,120040],"mapped",[121]],[[120041,120041],"mapped",[122]],[[120042,120042],"mapped",[97]],[[120043,120043],"mapped",[98]],[[120044,120044],"mapped",[99]],[[120045,120045],"mapped",[100]],[[120046,120046],"mapped",[101]],[[120047,120047],"mapped",[102]],[[120048,120048],"mapped",[103]],[[120049,120049],"mapped",[104]],[[120050,120050],"mapped",[105]],[[120051,120051],"mapped",[106]],[[120052,120052],"mapped",[107]],[[120053,120053],"mapped",[108]],[[120054,120054],"mapped",[109]],[[120055,120055],"mapped",[110]],[[120056,120056],"mapped",[111]],[[120057,120057],"mapped",[112]],[[120058,120058],"mapped",[113]],[[120059,120059],"mapped",[114]],[[120060,120060],"mapped",[115]],[[120061,120061],"mapped",[116]],[[120062,120062],"mapped",[117]],[[120063,120063],"mapped",[118]],[[120064,120064],"mapped",[119]],[[120065,120065],"mapped",[120]],[[120066,120066],"mapped",[121]],[[120067,120067],"mapped",[122]],[[120068,120068],"mapped",[97]],[[120069,120069],"mapped",[98]],[[120070,120070],"disallowed"],[[120071,120071],"mapped",[100]],[[120072,120072],"mapped",[101]],[[120073,120073],"mapped",[102]],[[120074,120074],"mapped",[103]],[[120075,120076],"disallowed"],[[120077,120077],"mapped",[106]],[[120078,120078],"mapped",[107]],[[120079,120079],"mapped",[108]],[[120080,120080],"mapped",[109]],[[120081,120081],"mapped",[110]],[[120082,120082],"mapped",[111]],[[120083,120083],"mapped",[112]],[[120084,120084],"mapped",[113]],[[120085,120085],"disallowed"],[[120086,120086],"mapped",[115]],[[120087,120087],"mapped",[116]],[[120088,120088],"mapped",[117]],[[120089,120089],"mapped",[118]],[[120090,120090],"mapped",[119]],[[120091,120091],"mapped",[120]],[[120092,120092],"mapped",[121]],[[120093,120093],"disallowed"],[[120094,120094],"mapped",[97]],[[120095,120095],"mapped",[98]],[[120096,120096],"mapped",[99]],[[120097,120097],"mapped",[100]],[[120098,120098],"mapped",[101]],[[120099,120099],"mapped",[102]],[[120100,120100],"mapped",[103]],[[120101,120101],"mapped",[104]],[[120102,120102],"mapped",[105]],[[120103,120103],"mapped",[106]],[[120104,120104],"mapped",[107]],[[120105,120105],"mapped",[108]],[[120106,120106],"mapped",[109]],[[120107,120107],"mapped",[110]],[[120108,120108],"mapped",[111]],[[120109,120109],"mapped",[112]],[[120110,120110],"mapped",[113]],[[120111,120111],"mapped",[114]],[[120112,120112],"mapped",[115]],[[120113,120113],"mapped",[116]],[[120114,120114],"mapped",[117]],[[120115,120115],"mapped",[118]],[[120116,120116],"mapped",[119]],[[120117,120117],"mapped",[120]],[[120118,120118],"mapped",[121]],[[120119,120119],"mapped",[122]],[[120120,120120],"mapped",[97]],[[120121,120121],"mapped",[98]],[[120122,120122],"disallowed"],[[120123,120123],"mapped",[100]],[[120124,120124],"mapped",[101]],[[120125,120125],"mapped",[102]],[[120126,120126],"mapped",[103]],[[120127,120127],"disallowed"],[[120128,120128],"mapped",[105]],[[120129,120129],"mapped",[106]],[[120130,120130],"mapped",[107]],[[120131,120131],"mapped",[108]],[[120132,120132],"mapped",[109]],[[120133,120133],"disallowed"],[[120134,120134],"mapped",[111]],[[120135,120137],"disallowed"],[[120138,120138],"mapped",[115]],[[120139,120139],"mapped",[116]],[[120140,120140],"mapped",[117]],[[120141,120141],"mapped",[118]],[[120142,120142],"mapped",[119]],[[120143,120143],"mapped",[120]],[[120144,120144],"mapped",[121]],[[120145,120145],"disallowed"],[[120146,120146],"mapped",[97]],[[120147,120147],"mapped",[98]],[[120148,120148],"mapped",[99]],[[120149,120149],"mapped",[100]],[[120150,120150],"mapped",[101]],[[120151,120151],"mapped",[102]],[[120152,120152],"mapped",[103]],[[120153,120153],"mapped",[104]],[[120154,120154],"mapped",[105]],[[120155,120155],"mapped",[106]],[[120156,120156],"mapped",[107]],[[120157,120157],"mapped",[108]],[[120158,120158],"mapped",[109]],[[120159,120159],"mapped",[110]],[[120160,120160],"mapped",[111]],[[120161,120161],"mapped",[112]],[[120162,120162],"mapped",[113]],[[120163,120163],"mapped",[114]],[[120164,120164],"mapped",[115]],[[120165,120165],"mapped",[116]],[[120166,120166],"mapped",[117]],[[120167,120167],"mapped",[118]],[[120168,120168],"mapped",[119]],[[120169,120169],"mapped",[120]],[[120170,120170],"mapped",[121]],[[120171,120171],"mapped",[122]],[[120172,120172],"mapped",[97]],[[120173,120173],"mapped",[98]],[[120174,120174],"mapped",[99]],[[120175,120175],"mapped",[100]],[[120176,120176],"mapped",[101]],[[120177,120177],"mapped",[102]],[[120178,120178],"mapped",[103]],[[120179,120179],"mapped",[104]],[[120180,120180],"mapped",[105]],[[120181,120181],"mapped",[106]],[[120182,120182],"mapped",[107]],[[120183,120183],"mapped",[108]],[[120184,120184],"mapped",[109]],[[120185,120185],"mapped",[110]],[[120186,120186],"mapped",[111]],[[120187,120187],"mapped",[112]],[[120188,120188],"mapped",[113]],[[120189,120189],"mapped",[114]],[[120190,120190],"mapped",[115]],[[120191,120191],"mapped",[116]],[[120192,120192],"mapped",[117]],[[120193,120193],"mapped",[118]],[[120194,120194],"mapped",[119]],[[120195,120195],"mapped",[120]],[[120196,120196],"mapped",[121]],[[120197,120197],"mapped",[122]],[[120198,120198],"mapped",[97]],[[120199,120199],"mapped",[98]],[[120200,120200],"mapped",[99]],[[120201,120201],"mapped",[100]],[[120202,120202],"mapped",[101]],[[120203,120203],"mapped",[102]],[[120204,120204],"mapped",[103]],[[120205,120205],"mapped",[104]],[[120206,120206],"mapped",[105]],[[120207,120207],"mapped",[106]],[[120208,120208],"mapped",[107]],[[120209,120209],"mapped",[108]],[[120210,120210],"mapped",[109]],[[120211,120211],"mapped",[110]],[[120212,120212],"mapped",[111]],[[120213,120213],"mapped",[112]],[[120214,120214],"mapped",[113]],[[120215,120215],"mapped",[114]],[[120216,120216],"mapped",[115]],[[120217,120217],"mapped",[116]],[[120218,120218],"mapped",[117]],[[120219,120219],"mapped",[118]],[[120220,120220],"mapped",[119]],[[120221,120221],"mapped",[120]],[[120222,120222],"mapped",[121]],[[120223,120223],"mapped",[122]],[[120224,120224],"mapped",[97]],[[120225,120225],"mapped",[98]],[[120226,120226],"mapped",[99]],[[120227,120227],"mapped",[100]],[[120228,120228],"mapped",[101]],[[120229,120229],"mapped",[102]],[[120230,120230],"mapped",[103]],[[120231,120231],"mapped",[104]],[[120232,120232],"mapped",[105]],[[120233,120233],"mapped",[106]],[[120234,120234],"mapped",[107]],[[120235,120235],"mapped",[108]],[[120236,120236],"mapped",[109]],[[120237,120237],"mapped",[110]],[[120238,120238],"mapped",[111]],[[120239,120239],"mapped",[112]],[[120240,120240],"mapped",[113]],[[120241,120241],"mapped",[114]],[[120242,120242],"mapped",[115]],[[120243,120243],"mapped",[116]],[[120244,120244],"mapped",[117]],[[120245,120245],"mapped",[118]],[[120246,120246],"mapped",[119]],[[120247,120247],"mapped",[120]],[[120248,120248],"mapped",[121]],[[120249,120249],"mapped",[122]],[[120250,120250],"mapped",[97]],[[120251,120251],"mapped",[98]],[[120252,120252],"mapped",[99]],[[120253,120253],"mapped",[100]],[[120254,120254],"mapped",[101]],[[120255,120255],"mapped",[102]],[[120256,120256],"mapped",[103]],[[120257,120257],"mapped",[104]],[[120258,120258],"mapped",[105]],[[120259,120259],"mapped",[106]],[[120260,120260],"mapped",[107]],[[120261,120261],"mapped",[108]],[[120262,120262],"mapped",[109]],[[120263,120263],"mapped",[110]],[[120264,120264],"mapped",[111]],[[120265,120265],"mapped",[112]],[[120266,120266],"mapped",[113]],[[120267,120267],"mapped",[114]],[[120268,120268],"mapped",[115]],[[120269,120269],"mapped",[116]],[[120270,120270],"mapped",[117]],[[120271,120271],"mapped",[118]],[[120272,120272],"mapped",[119]],[[120273,120273],"mapped",[120]],[[120274,120274],"mapped",[121]],[[120275,120275],"mapped",[122]],[[120276,120276],"mapped",[97]],[[120277,120277],"mapped",[98]],[[120278,120278],"mapped",[99]],[[120279,120279],"mapped",[100]],[[120280,120280],"mapped",[101]],[[120281,120281],"mapped",[102]],[[120282,120282],"mapped",[103]],[[120283,120283],"mapped",[104]],[[120284,120284],"mapped",[105]],[[120285,120285],"mapped",[106]],[[120286,120286],"mapped",[107]],[[120287,120287],"mapped",[108]],[[120288,120288],"mapped",[109]],[[120289,120289],"mapped",[110]],[[120290,120290],"mapped",[111]],[[120291,120291],"mapped",[112]],[[120292,120292],"mapped",[113]],[[120293,120293],"mapped",[114]],[[120294,120294],"mapped",[115]],[[120295,120295],"mapped",[116]],[[120296,120296],"mapped",[117]],[[120297,120297],"mapped",[118]],[[120298,120298],"mapped",[119]],[[120299,120299],"mapped",[120]],[[120300,120300],"mapped",[121]],[[120301,120301],"mapped",[122]],[[120302,120302],"mapped",[97]],[[120303,120303],"mapped",[98]],[[120304,120304],"mapped",[99]],[[120305,120305],"mapped",[100]],[[120306,120306],"mapped",[101]],[[120307,120307],"mapped",[102]],[[120308,120308],"mapped",[103]],[[120309,120309],"mapped",[104]],[[120310,120310],"mapped",[105]],[[120311,120311],"mapped",[106]],[[120312,120312],"mapped",[107]],[[120313,120313],"mapped",[108]],[[120314,120314],"mapped",[109]],[[120315,120315],"mapped",[110]],[[120316,120316],"mapped",[111]],[[120317,120317],"mapped",[112]],[[120318,120318],"mapped",[113]],[[120319,120319],"mapped",[114]],[[120320,120320],"mapped",[115]],[[120321,120321],"mapped",[116]],[[120322,120322],"mapped",[117]],[[120323,120323],"mapped",[118]],[[120324,120324],"mapped",[119]],[[120325,120325],"mapped",[120]],[[120326,120326],"mapped",[121]],[[120327,120327],"mapped",[122]],[[120328,120328],"mapped",[97]],[[120329,120329],"mapped",[98]],[[120330,120330],"mapped",[99]],[[120331,120331],"mapped",[100]],[[120332,120332],"mapped",[101]],[[120333,120333],"mapped",[102]],[[120334,120334],"mapped",[103]],[[120335,120335],"mapped",[104]],[[120336,120336],"mapped",[105]],[[120337,120337],"mapped",[106]],[[120338,120338],"mapped",[107]],[[120339,120339],"mapped",[108]],[[120340,120340],"mapped",[109]],[[120341,120341],"mapped",[110]],[[120342,120342],"mapped",[111]],[[120343,120343],"mapped",[112]],[[120344,120344],"mapped",[113]],[[120345,120345],"mapped",[114]],[[120346,120346],"mapped",[115]],[[120347,120347],"mapped",[116]],[[120348,120348],"mapped",[117]],[[120349,120349],"mapped",[118]],[[120350,120350],"mapped",[119]],[[120351,120351],"mapped",[120]],[[120352,120352],"mapped",[121]],[[120353,120353],"mapped",[122]],[[120354,120354],"mapped",[97]],[[120355,120355],"mapped",[98]],[[120356,120356],"mapped",[99]],[[120357,120357],"mapped",[100]],[[120358,120358],"mapped",[101]],[[120359,120359],"mapped",[102]],[[120360,120360],"mapped",[103]],[[120361,120361],"mapped",[104]],[[120362,120362],"mapped",[105]],[[120363,120363],"mapped",[106]],[[120364,120364],"mapped",[107]],[[120365,120365],"mapped",[108]],[[120366,120366],"mapped",[109]],[[120367,120367],"mapped",[110]],[[120368,120368],"mapped",[111]],[[120369,120369],"mapped",[112]],[[120370,120370],"mapped",[113]],[[120371,120371],"mapped",[114]],[[120372,120372],"mapped",[115]],[[120373,120373],"mapped",[116]],[[120374,120374],"mapped",[117]],[[120375,120375],"mapped",[118]],[[120376,120376],"mapped",[119]],[[120377,120377],"mapped",[120]],[[120378,120378],"mapped",[121]],[[120379,120379],"mapped",[122]],[[120380,120380],"mapped",[97]],[[120381,120381],"mapped",[98]],[[120382,120382],"mapped",[99]],[[120383,120383],"mapped",[100]],[[120384,120384],"mapped",[101]],[[120385,120385],"mapped",[102]],[[120386,120386],"mapped",[103]],[[120387,120387],"mapped",[104]],[[120388,120388],"mapped",[105]],[[120389,120389],"mapped",[106]],[[120390,120390],"mapped",[107]],[[120391,120391],"mapped",[108]],[[120392,120392],"mapped",[109]],[[120393,120393],"mapped",[110]],[[120394,120394],"mapped",[111]],[[120395,120395],"mapped",[112]],[[120396,120396],"mapped",[113]],[[120397,120397],"mapped",[114]],[[120398,120398],"mapped",[115]],[[120399,120399],"mapped",[116]],[[120400,120400],"mapped",[117]],[[120401,120401],"mapped",[118]],[[120402,120402],"mapped",[119]],[[120403,120403],"mapped",[120]],[[120404,120404],"mapped",[121]],[[120405,120405],"mapped",[122]],[[120406,120406],"mapped",[97]],[[120407,120407],"mapped",[98]],[[120408,120408],"mapped",[99]],[[120409,120409],"mapped",[100]],[[120410,120410],"mapped",[101]],[[120411,120411],"mapped",[102]],[[120412,120412],"mapped",[103]],[[120413,120413],"mapped",[104]],[[120414,120414],"mapped",[105]],[[120415,120415],"mapped",[106]],[[120416,120416],"mapped",[107]],[[120417,120417],"mapped",[108]],[[120418,120418],"mapped",[109]],[[120419,120419],"mapped",[110]],[[120420,120420],"mapped",[111]],[[120421,120421],"mapped",[112]],[[120422,120422],"mapped",[113]],[[120423,120423],"mapped",[114]],[[120424,120424],"mapped",[115]],[[120425,120425],"mapped",[116]],[[120426,120426],"mapped",[117]],[[120427,120427],"mapped",[118]],[[120428,120428],"mapped",[119]],[[120429,120429],"mapped",[120]],[[120430,120430],"mapped",[121]],[[120431,120431],"mapped",[122]],[[120432,120432],"mapped",[97]],[[120433,120433],"mapped",[98]],[[120434,120434],"mapped",[99]],[[120435,120435],"mapped",[100]],[[120436,120436],"mapped",[101]],[[120437,120437],"mapped",[102]],[[120438,120438],"mapped",[103]],[[120439,120439],"mapped",[104]],[[120440,120440],"mapped",[105]],[[120441,120441],"mapped",[106]],[[120442,120442],"mapped",[107]],[[120443,120443],"mapped",[108]],[[120444,120444],"mapped",[109]],[[120445,120445],"mapped",[110]],[[120446,120446],"mapped",[111]],[[120447,120447],"mapped",[112]],[[120448,120448],"mapped",[113]],[[120449,120449],"mapped",[114]],[[120450,120450],"mapped",[115]],[[120451,120451],"mapped",[116]],[[120452,120452],"mapped",[117]],[[120453,120453],"mapped",[118]],[[120454,120454],"mapped",[119]],[[120455,120455],"mapped",[120]],[[120456,120456],"mapped",[121]],[[120457,120457],"mapped",[122]],[[120458,120458],"mapped",[97]],[[120459,120459],"mapped",[98]],[[120460,120460],"mapped",[99]],[[120461,120461],"mapped",[100]],[[120462,120462],"mapped",[101]],[[120463,120463],"mapped",[102]],[[120464,120464],"mapped",[103]],[[120465,120465],"mapped",[104]],[[120466,120466],"mapped",[105]],[[120467,120467],"mapped",[106]],[[120468,120468],"mapped",[107]],[[120469,120469],"mapped",[108]],[[120470,120470],"mapped",[109]],[[120471,120471],"mapped",[110]],[[120472,120472],"mapped",[111]],[[120473,120473],"mapped",[112]],[[120474,120474],"mapped",[113]],[[120475,120475],"mapped",[114]],[[120476,120476],"mapped",[115]],[[120477,120477],"mapped",[116]],[[120478,120478],"mapped",[117]],[[120479,120479],"mapped",[118]],[[120480,120480],"mapped",[119]],[[120481,120481],"mapped",[120]],[[120482,120482],"mapped",[121]],[[120483,120483],"mapped",[122]],[[120484,120484],"mapped",[305]],[[120485,120485],"mapped",[567]],[[120486,120487],"disallowed"],[[120488,120488],"mapped",[945]],[[120489,120489],"mapped",[946]],[[120490,120490],"mapped",[947]],[[120491,120491],"mapped",[948]],[[120492,120492],"mapped",[949]],[[120493,120493],"mapped",[950]],[[120494,120494],"mapped",[951]],[[120495,120495],"mapped",[952]],[[120496,120496],"mapped",[953]],[[120497,120497],"mapped",[954]],[[120498,120498],"mapped",[955]],[[120499,120499],"mapped",[956]],[[120500,120500],"mapped",[957]],[[120501,120501],"mapped",[958]],[[120502,120502],"mapped",[959]],[[120503,120503],"mapped",[960]],[[120504,120504],"mapped",[961]],[[120505,120505],"mapped",[952]],[[120506,120506],"mapped",[963]],[[120507,120507],"mapped",[964]],[[120508,120508],"mapped",[965]],[[120509,120509],"mapped",[966]],[[120510,120510],"mapped",[967]],[[120511,120511],"mapped",[968]],[[120512,120512],"mapped",[969]],[[120513,120513],"mapped",[8711]],[[120514,120514],"mapped",[945]],[[120515,120515],"mapped",[946]],[[120516,120516],"mapped",[947]],[[120517,120517],"mapped",[948]],[[120518,120518],"mapped",[949]],[[120519,120519],"mapped",[950]],[[120520,120520],"mapped",[951]],[[120521,120521],"mapped",[952]],[[120522,120522],"mapped",[953]],[[120523,120523],"mapped",[954]],[[120524,120524],"mapped",[955]],[[120525,120525],"mapped",[956]],[[120526,120526],"mapped",[957]],[[120527,120527],"mapped",[958]],[[120528,120528],"mapped",[959]],[[120529,120529],"mapped",[960]],[[120530,120530],"mapped",[961]],[[120531,120532],"mapped",[963]],[[120533,120533],"mapped",[964]],[[120534,120534],"mapped",[965]],[[120535,120535],"mapped",[966]],[[120536,120536],"mapped",[967]],[[120537,120537],"mapped",[968]],[[120538,120538],"mapped",[969]],[[120539,120539],"mapped",[8706]],[[120540,120540],"mapped",[949]],[[120541,120541],"mapped",[952]],[[120542,120542],"mapped",[954]],[[120543,120543],"mapped",[966]],[[120544,120544],"mapped",[961]],[[120545,120545],"mapped",[960]],[[120546,120546],"mapped",[945]],[[120547,120547],"mapped",[946]],[[120548,120548],"mapped",[947]],[[120549,120549],"mapped",[948]],[[120550,120550],"mapped",[949]],[[120551,120551],"mapped",[950]],[[120552,120552],"mapped",[951]],[[120553,120553],"mapped",[952]],[[120554,120554],"mapped",[953]],[[120555,120555],"mapped",[954]],[[120556,120556],"mapped",[955]],[[120557,120557],"mapped",[956]],[[120558,120558],"mapped",[957]],[[120559,120559],"mapped",[958]],[[120560,120560],"mapped",[959]],[[120561,120561],"mapped",[960]],[[120562,120562],"mapped",[961]],[[120563,120563],"mapped",[952]],[[120564,120564],"mapped",[963]],[[120565,120565],"mapped",[964]],[[120566,120566],"mapped",[965]],[[120567,120567],"mapped",[966]],[[120568,120568],"mapped",[967]],[[120569,120569],"mapped",[968]],[[120570,120570],"mapped",[969]],[[120571,120571],"mapped",[8711]],[[120572,120572],"mapped",[945]],[[120573,120573],"mapped",[946]],[[120574,120574],"mapped",[947]],[[120575,120575],"mapped",[948]],[[120576,120576],"mapped",[949]],[[120577,120577],"mapped",[950]],[[120578,120578],"mapped",[951]],[[120579,120579],"mapped",[952]],[[120580,120580],"mapped",[953]],[[120581,120581],"mapped",[954]],[[120582,120582],"mapped",[955]],[[120583,120583],"mapped",[956]],[[120584,120584],"mapped",[957]],[[120585,120585],"mapped",[958]],[[120586,120586],"mapped",[959]],[[120587,120587],"mapped",[960]],[[120588,120588],"mapped",[961]],[[120589,120590],"mapped",[963]],[[120591,120591],"mapped",[964]],[[120592,120592],"mapped",[965]],[[120593,120593],"mapped",[966]],[[120594,120594],"mapped",[967]],[[120595,120595],"mapped",[968]],[[120596,120596],"mapped",[969]],[[120597,120597],"mapped",[8706]],[[120598,120598],"mapped",[949]],[[120599,120599],"mapped",[952]],[[120600,120600],"mapped",[954]],[[120601,120601],"mapped",[966]],[[120602,120602],"mapped",[961]],[[120603,120603],"mapped",[960]],[[120604,120604],"mapped",[945]],[[120605,120605],"mapped",[946]],[[120606,120606],"mapped",[947]],[[120607,120607],"mapped",[948]],[[120608,120608],"mapped",[949]],[[120609,120609],"mapped",[950]],[[120610,120610],"mapped",[951]],[[120611,120611],"mapped",[952]],[[120612,120612],"mapped",[953]],[[120613,120613],"mapped",[954]],[[120614,120614],"mapped",[955]],[[120615,120615],"mapped",[956]],[[120616,120616],"mapped",[957]],[[120617,120617],"mapped",[958]],[[120618,120618],"mapped",[959]],[[120619,120619],"mapped",[960]],[[120620,120620],"mapped",[961]],[[120621,120621],"mapped",[952]],[[120622,120622],"mapped",[963]],[[120623,120623],"mapped",[964]],[[120624,120624],"mapped",[965]],[[120625,120625],"mapped",[966]],[[120626,120626],"mapped",[967]],[[120627,120627],"mapped",[968]],[[120628,120628],"mapped",[969]],[[120629,120629],"mapped",[8711]],[[120630,120630],"mapped",[945]],[[120631,120631],"mapped",[946]],[[120632,120632],"mapped",[947]],[[120633,120633],"mapped",[948]],[[120634,120634],"mapped",[949]],[[120635,120635],"mapped",[950]],[[120636,120636],"mapped",[951]],[[120637,120637],"mapped",[952]],[[120638,120638],"mapped",[953]],[[120639,120639],"mapped",[954]],[[120640,120640],"mapped",[955]],[[120641,120641],"mapped",[956]],[[120642,120642],"mapped",[957]],[[120643,120643],"mapped",[958]],[[120644,120644],"mapped",[959]],[[120645,120645],"mapped",[960]],[[120646,120646],"mapped",[961]],[[120647,120648],"mapped",[963]],[[120649,120649],"mapped",[964]],[[120650,120650],"mapped",[965]],[[120651,120651],"mapped",[966]],[[120652,120652],"mapped",[967]],[[120653,120653],"mapped",[968]],[[120654,120654],"mapped",[969]],[[120655,120655],"mapped",[8706]],[[120656,120656],"mapped",[949]],[[120657,120657],"mapped",[952]],[[120658,120658],"mapped",[954]],[[120659,120659],"mapped",[966]],[[120660,120660],"mapped",[961]],[[120661,120661],"mapped",[960]],[[120662,120662],"mapped",[945]],[[120663,120663],"mapped",[946]],[[120664,120664],"mapped",[947]],[[120665,120665],"mapped",[948]],[[120666,120666],"mapped",[949]],[[120667,120667],"mapped",[950]],[[120668,120668],"mapped",[951]],[[120669,120669],"mapped",[952]],[[120670,120670],"mapped",[953]],[[120671,120671],"mapped",[954]],[[120672,120672],"mapped",[955]],[[120673,120673],"mapped",[956]],[[120674,120674],"mapped",[957]],[[120675,120675],"mapped",[958]],[[120676,120676],"mapped",[959]],[[120677,120677],"mapped",[960]],[[120678,120678],"mapped",[961]],[[120679,120679],"mapped",[952]],[[120680,120680],"mapped",[963]],[[120681,120681],"mapped",[964]],[[120682,120682],"mapped",[965]],[[120683,120683],"mapped",[966]],[[120684,120684],"mapped",[967]],[[120685,120685],"mapped",[968]],[[120686,120686],"mapped",[969]],[[120687,120687],"mapped",[8711]],[[120688,120688],"mapped",[945]],[[120689,120689],"mapped",[946]],[[120690,120690],"mapped",[947]],[[120691,120691],"mapped",[948]],[[120692,120692],"mapped",[949]],[[120693,120693],"mapped",[950]],[[120694,120694],"mapped",[951]],[[120695,120695],"mapped",[952]],[[120696,120696],"mapped",[953]],[[120697,120697],"mapped",[954]],[[120698,120698],"mapped",[955]],[[120699,120699],"mapped",[956]],[[120700,120700],"mapped",[957]],[[120701,120701],"mapped",[958]],[[120702,120702],"mapped",[959]],[[120703,120703],"mapped",[960]],[[120704,120704],"mapped",[961]],[[120705,120706],"mapped",[963]],[[120707,120707],"mapped",[964]],[[120708,120708],"mapped",[965]],[[120709,120709],"mapped",[966]],[[120710,120710],"mapped",[967]],[[120711,120711],"mapped",[968]],[[120712,120712],"mapped",[969]],[[120713,120713],"mapped",[8706]],[[120714,120714],"mapped",[949]],[[120715,120715],"mapped",[952]],[[120716,120716],"mapped",[954]],[[120717,120717],"mapped",[966]],[[120718,120718],"mapped",[961]],[[120719,120719],"mapped",[960]],[[120720,120720],"mapped",[945]],[[120721,120721],"mapped",[946]],[[120722,120722],"mapped",[947]],[[120723,120723],"mapped",[948]],[[120724,120724],"mapped",[949]],[[120725,120725],"mapped",[950]],[[120726,120726],"mapped",[951]],[[120727,120727],"mapped",[952]],[[120728,120728],"mapped",[953]],[[120729,120729],"mapped",[954]],[[120730,120730],"mapped",[955]],[[120731,120731],"mapped",[956]],[[120732,120732],"mapped",[957]],[[120733,120733],"mapped",[958]],[[120734,120734],"mapped",[959]],[[120735,120735],"mapped",[960]],[[120736,120736],"mapped",[961]],[[120737,120737],"mapped",[952]],[[120738,120738],"mapped",[963]],[[120739,120739],"mapped",[964]],[[120740,120740],"mapped",[965]],[[120741,120741],"mapped",[966]],[[120742,120742],"mapped",[967]],[[120743,120743],"mapped",[968]],[[120744,120744],"mapped",[969]],[[120745,120745],"mapped",[8711]],[[120746,120746],"mapped",[945]],[[120747,120747],"mapped",[946]],[[120748,120748],"mapped",[947]],[[120749,120749],"mapped",[948]],[[120750,120750],"mapped",[949]],[[120751,120751],"mapped",[950]],[[120752,120752],"mapped",[951]],[[120753,120753],"mapped",[952]],[[120754,120754],"mapped",[953]],[[120755,120755],"mapped",[954]],[[120756,120756],"mapped",[955]],[[120757,120757],"mapped",[956]],[[120758,120758],"mapped",[957]],[[120759,120759],"mapped",[958]],[[120760,120760],"mapped",[959]],[[120761,120761],"mapped",[960]],[[120762,120762],"mapped",[961]],[[120763,120764],"mapped",[963]],[[120765,120765],"mapped",[964]],[[120766,120766],"mapped",[965]],[[120767,120767],"mapped",[966]],[[120768,120768],"mapped",[967]],[[120769,120769],"mapped",[968]],[[120770,120770],"mapped",[969]],[[120771,120771],"mapped",[8706]],[[120772,120772],"mapped",[949]],[[120773,120773],"mapped",[952]],[[120774,120774],"mapped",[954]],[[120775,120775],"mapped",[966]],[[120776,120776],"mapped",[961]],[[120777,120777],"mapped",[960]],[[120778,120779],"mapped",[989]],[[120780,120781],"disallowed"],[[120782,120782],"mapped",[48]],[[120783,120783],"mapped",[49]],[[120784,120784],"mapped",[50]],[[120785,120785],"mapped",[51]],[[120786,120786],"mapped",[52]],[[120787,120787],"mapped",[53]],[[120788,120788],"mapped",[54]],[[120789,120789],"mapped",[55]],[[120790,120790],"mapped",[56]],[[120791,120791],"mapped",[57]],[[120792,120792],"mapped",[48]],[[120793,120793],"mapped",[49]],[[120794,120794],"mapped",[50]],[[120795,120795],"mapped",[51]],[[120796,120796],"mapped",[52]],[[120797,120797],"mapped",[53]],[[120798,120798],"mapped",[54]],[[120799,120799],"mapped",[55]],[[120800,120800],"mapped",[56]],[[120801,120801],"mapped",[57]],[[120802,120802],"mapped",[48]],[[120803,120803],"mapped",[49]],[[120804,120804],"mapped",[50]],[[120805,120805],"mapped",[51]],[[120806,120806],"mapped",[52]],[[120807,120807],"mapped",[53]],[[120808,120808],"mapped",[54]],[[120809,120809],"mapped",[55]],[[120810,120810],"mapped",[56]],[[120811,120811],"mapped",[57]],[[120812,120812],"mapped",[48]],[[120813,120813],"mapped",[49]],[[120814,120814],"mapped",[50]],[[120815,120815],"mapped",[51]],[[120816,120816],"mapped",[52]],[[120817,120817],"mapped",[53]],[[120818,120818],"mapped",[54]],[[120819,120819],"mapped",[55]],[[120820,120820],"mapped",[56]],[[120821,120821],"mapped",[57]],[[120822,120822],"mapped",[48]],[[120823,120823],"mapped",[49]],[[120824,120824],"mapped",[50]],[[120825,120825],"mapped",[51]],[[120826,120826],"mapped",[52]],[[120827,120827],"mapped",[53]],[[120828,120828],"mapped",[54]],[[120829,120829],"mapped",[55]],[[120830,120830],"mapped",[56]],[[120831,120831],"mapped",[57]],[[120832,121343],"valid",[],"NV8"],[[121344,121398],"valid"],[[121399,121402],"valid",[],"NV8"],[[121403,121452],"valid"],[[121453,121460],"valid",[],"NV8"],[[121461,121461],"valid"],[[121462,121475],"valid",[],"NV8"],[[121476,121476],"valid"],[[121477,121483],"valid",[],"NV8"],[[121484,121498],"disallowed"],[[121499,121503],"valid"],[[121504,121504],"disallowed"],[[121505,121519],"valid"],[[121520,124927],"disallowed"],[[124928,125124],"valid"],[[125125,125126],"disallowed"],[[125127,125135],"valid",[],"NV8"],[[125136,125142],"valid"],[[125143,126463],"disallowed"],[[126464,126464],"mapped",[1575]],[[126465,126465],"mapped",[1576]],[[126466,126466],"mapped",[1580]],[[126467,126467],"mapped",[1583]],[[126468,126468],"disallowed"],[[126469,126469],"mapped",[1608]],[[126470,126470],"mapped",[1586]],[[126471,126471],"mapped",[1581]],[[126472,126472],"mapped",[1591]],[[126473,126473],"mapped",[1610]],[[126474,126474],"mapped",[1603]],[[126475,126475],"mapped",[1604]],[[126476,126476],"mapped",[1605]],[[126477,126477],"mapped",[1606]],[[126478,126478],"mapped",[1587]],[[126479,126479],"mapped",[1593]],[[126480,126480],"mapped",[1601]],[[126481,126481],"mapped",[1589]],[[126482,126482],"mapped",[1602]],[[126483,126483],"mapped",[1585]],[[126484,126484],"mapped",[1588]],[[126485,126485],"mapped",[1578]],[[126486,126486],"mapped",[1579]],[[126487,126487],"mapped",[1582]],[[126488,126488],"mapped",[1584]],[[126489,126489],"mapped",[1590]],[[126490,126490],"mapped",[1592]],[[126491,126491],"mapped",[1594]],[[126492,126492],"mapped",[1646]],[[126493,126493],"mapped",[1722]],[[126494,126494],"mapped",[1697]],[[126495,126495],"mapped",[1647]],[[126496,126496],"disallowed"],[[126497,126497],"mapped",[1576]],[[126498,126498],"mapped",[1580]],[[126499,126499],"disallowed"],[[126500,126500],"mapped",[1607]],[[126501,126502],"disallowed"],[[126503,126503],"mapped",[1581]],[[126504,126504],"disallowed"],[[126505,126505],"mapped",[1610]],[[126506,126506],"mapped",[1603]],[[126507,126507],"mapped",[1604]],[[126508,126508],"mapped",[1605]],[[126509,126509],"mapped",[1606]],[[126510,126510],"mapped",[1587]],[[126511,126511],"mapped",[1593]],[[126512,126512],"mapped",[1601]],[[126513,126513],"mapped",[1589]],[[126514,126514],"mapped",[1602]],[[126515,126515],"disallowed"],[[126516,126516],"mapped",[1588]],[[126517,126517],"mapped",[1578]],[[126518,126518],"mapped",[1579]],[[126519,126519],"mapped",[1582]],[[126520,126520],"disallowed"],[[126521,126521],"mapped",[1590]],[[126522,126522],"disallowed"],[[126523,126523],"mapped",[1594]],[[126524,126529],"disallowed"],[[126530,126530],"mapped",[1580]],[[126531,126534],"disallowed"],[[126535,126535],"mapped",[1581]],[[126536,126536],"disallowed"],[[126537,126537],"mapped",[1610]],[[126538,126538],"disallowed"],[[126539,126539],"mapped",[1604]],[[126540,126540],"disallowed"],[[126541,126541],"mapped",[1606]],[[126542,126542],"mapped",[1587]],[[126543,126543],"mapped",[1593]],[[126544,126544],"disallowed"],[[126545,126545],"mapped",[1589]],[[126546,126546],"mapped",[1602]],[[126547,126547],"disallowed"],[[126548,126548],"mapped",[1588]],[[126549,126550],"disallowed"],[[126551,126551],"mapped",[1582]],[[126552,126552],"disallowed"],[[126553,126553],"mapped",[1590]],[[126554,126554],"disallowed"],[[126555,126555],"mapped",[1594]],[[126556,126556],"disallowed"],[[126557,126557],"mapped",[1722]],[[126558,126558],"disallowed"],[[126559,126559],"mapped",[1647]],[[126560,126560],"disallowed"],[[126561,126561],"mapped",[1576]],[[126562,126562],"mapped",[1580]],[[126563,126563],"disallowed"],[[126564,126564],"mapped",[1607]],[[126565,126566],"disallowed"],[[126567,126567],"mapped",[1581]],[[126568,126568],"mapped",[1591]],[[126569,126569],"mapped",[1610]],[[126570,126570],"mapped",[1603]],[[126571,126571],"disallowed"],[[126572,126572],"mapped",[1605]],[[126573,126573],"mapped",[1606]],[[126574,126574],"mapped",[1587]],[[126575,126575],"mapped",[1593]],[[126576,126576],"mapped",[1601]],[[126577,126577],"mapped",[1589]],[[126578,126578],"mapped",[1602]],[[126579,126579],"disallowed"],[[126580,126580],"mapped",[1588]],[[126581,126581],"mapped",[1578]],[[126582,126582],"mapped",[1579]],[[126583,126583],"mapped",[1582]],[[126584,126584],"disallowed"],[[126585,126585],"mapped",[1590]],[[126586,126586],"mapped",[1592]],[[126587,126587],"mapped",[1594]],[[126588,126588],"mapped",[1646]],[[126589,126589],"disallowed"],[[126590,126590],"mapped",[1697]],[[126591,126591],"disallowed"],[[126592,126592],"mapped",[1575]],[[126593,126593],"mapped",[1576]],[[126594,126594],"mapped",[1580]],[[126595,126595],"mapped",[1583]],[[126596,126596],"mapped",[1607]],[[126597,126597],"mapped",[1608]],[[126598,126598],"mapped",[1586]],[[126599,126599],"mapped",[1581]],[[126600,126600],"mapped",[1591]],[[126601,126601],"mapped",[1610]],[[126602,126602],"disallowed"],[[126603,126603],"mapped",[1604]],[[126604,126604],"mapped",[1605]],[[126605,126605],"mapped",[1606]],[[126606,126606],"mapped",[1587]],[[126607,126607],"mapped",[1593]],[[126608,126608],"mapped",[1601]],[[126609,126609],"mapped",[1589]],[[126610,126610],"mapped",[1602]],[[126611,126611],"mapped",[1585]],[[126612,126612],"mapped",[1588]],[[126613,126613],"mapped",[1578]],[[126614,126614],"mapped",[1579]],[[126615,126615],"mapped",[1582]],[[126616,126616],"mapped",[1584]],[[126617,126617],"mapped",[1590]],[[126618,126618],"mapped",[1592]],[[126619,126619],"mapped",[1594]],[[126620,126624],"disallowed"],[[126625,126625],"mapped",[1576]],[[126626,126626],"mapped",[1580]],[[126627,126627],"mapped",[1583]],[[126628,126628],"disallowed"],[[126629,126629],"mapped",[1608]],[[126630,126630],"mapped",[1586]],[[126631,126631],"mapped",[1581]],[[126632,126632],"mapped",[1591]],[[126633,126633],"mapped",[1610]],[[126634,126634],"disallowed"],[[126635,126635],"mapped",[1604]],[[126636,126636],"mapped",[1605]],[[126637,126637],"mapped",[1606]],[[126638,126638],"mapped",[1587]],[[126639,126639],"mapped",[1593]],[[126640,126640],"mapped",[1601]],[[126641,126641],"mapped",[1589]],[[126642,126642],"mapped",[1602]],[[126643,126643],"mapped",[1585]],[[126644,126644],"mapped",[1588]],[[126645,126645],"mapped",[1578]],[[126646,126646],"mapped",[1579]],[[126647,126647],"mapped",[1582]],[[126648,126648],"mapped",[1584]],[[126649,126649],"mapped",[1590]],[[126650,126650],"mapped",[1592]],[[126651,126651],"mapped",[1594]],[[126652,126703],"disallowed"],[[126704,126705],"valid",[],"NV8"],[[126706,126975],"disallowed"],[[126976,127019],"valid",[],"NV8"],[[127020,127023],"disallowed"],[[127024,127123],"valid",[],"NV8"],[[127124,127135],"disallowed"],[[127136,127150],"valid",[],"NV8"],[[127151,127152],"disallowed"],[[127153,127166],"valid",[],"NV8"],[[127167,127167],"valid",[],"NV8"],[[127168,127168],"disallowed"],[[127169,127183],"valid",[],"NV8"],[[127184,127184],"disallowed"],[[127185,127199],"valid",[],"NV8"],[[127200,127221],"valid",[],"NV8"],[[127222,127231],"disallowed"],[[127232,127232],"disallowed"],[[127233,127233],"disallowed_STD3_mapped",[48,44]],[[127234,127234],"disallowed_STD3_mapped",[49,44]],[[127235,127235],"disallowed_STD3_mapped",[50,44]],[[127236,127236],"disallowed_STD3_mapped",[51,44]],[[127237,127237],"disallowed_STD3_mapped",[52,44]],[[127238,127238],"disallowed_STD3_mapped",[53,44]],[[127239,127239],"disallowed_STD3_mapped",[54,44]],[[127240,127240],"disallowed_STD3_mapped",[55,44]],[[127241,127241],"disallowed_STD3_mapped",[56,44]],[[127242,127242],"disallowed_STD3_mapped",[57,44]],[[127243,127244],"valid",[],"NV8"],[[127245,127247],"disallowed"],[[127248,127248],"disallowed_STD3_mapped",[40,97,41]],[[127249,127249],"disallowed_STD3_mapped",[40,98,41]],[[127250,127250],"disallowed_STD3_mapped",[40,99,41]],[[127251,127251],"disallowed_STD3_mapped",[40,100,41]],[[127252,127252],"disallowed_STD3_mapped",[40,101,41]],[[127253,127253],"disallowed_STD3_mapped",[40,102,41]],[[127254,127254],"disallowed_STD3_mapped",[40,103,41]],[[127255,127255],"disallowed_STD3_mapped",[40,104,41]],[[127256,127256],"disallowed_STD3_mapped",[40,105,41]],[[127257,127257],"disallowed_STD3_mapped",[40,106,41]],[[127258,127258],"disallowed_STD3_mapped",[40,107,41]],[[127259,127259],"disallowed_STD3_mapped",[40,108,41]],[[127260,127260],"disallowed_STD3_mapped",[40,109,41]],[[127261,127261],"disallowed_STD3_mapped",[40,110,41]],[[127262,127262],"disallowed_STD3_mapped",[40,111,41]],[[127263,127263],"disallowed_STD3_mapped",[40,112,41]],[[127264,127264],"disallowed_STD3_mapped",[40,113,41]],[[127265,127265],"disallowed_STD3_mapped",[40,114,41]],[[127266,127266],"disallowed_STD3_mapped",[40,115,41]],[[127267,127267],"disallowed_STD3_mapped",[40,116,41]],[[127268,127268],"disallowed_STD3_mapped",[40,117,41]],[[127269,127269],"disallowed_STD3_mapped",[40,118,41]],[[127270,127270],"disallowed_STD3_mapped",[40,119,41]],[[127271,127271],"disallowed_STD3_mapped",[40,120,41]],[[127272,127272],"disallowed_STD3_mapped",[40,121,41]],[[127273,127273],"disallowed_STD3_mapped",[40,122,41]],[[127274,127274],"mapped",[12308,115,12309]],[[127275,127275],"mapped",[99]],[[127276,127276],"mapped",[114]],[[127277,127277],"mapped",[99,100]],[[127278,127278],"mapped",[119,122]],[[127279,127279],"disallowed"],[[127280,127280],"mapped",[97]],[[127281,127281],"mapped",[98]],[[127282,127282],"mapped",[99]],[[127283,127283],"mapped",[100]],[[127284,127284],"mapped",[101]],[[127285,127285],"mapped",[102]],[[127286,127286],"mapped",[103]],[[127287,127287],"mapped",[104]],[[127288,127288],"mapped",[105]],[[127289,127289],"mapped",[106]],[[127290,127290],"mapped",[107]],[[127291,127291],"mapped",[108]],[[127292,127292],"mapped",[109]],[[127293,127293],"mapped",[110]],[[127294,127294],"mapped",[111]],[[127295,127295],"mapped",[112]],[[127296,127296],"mapped",[113]],[[127297,127297],"mapped",[114]],[[127298,127298],"mapped",[115]],[[127299,127299],"mapped",[116]],[[127300,127300],"mapped",[117]],[[127301,127301],"mapped",[118]],[[127302,127302],"mapped",[119]],[[127303,127303],"mapped",[120]],[[127304,127304],"mapped",[121]],[[127305,127305],"mapped",[122]],[[127306,127306],"mapped",[104,118]],[[127307,127307],"mapped",[109,118]],[[127308,127308],"mapped",[115,100]],[[127309,127309],"mapped",[115,115]],[[127310,127310],"mapped",[112,112,118]],[[127311,127311],"mapped",[119,99]],[[127312,127318],"valid",[],"NV8"],[[127319,127319],"valid",[],"NV8"],[[127320,127326],"valid",[],"NV8"],[[127327,127327],"valid",[],"NV8"],[[127328,127337],"valid",[],"NV8"],[[127338,127338],"mapped",[109,99]],[[127339,127339],"mapped",[109,100]],[[127340,127343],"disallowed"],[[127344,127352],"valid",[],"NV8"],[[127353,127353],"valid",[],"NV8"],[[127354,127354],"valid",[],"NV8"],[[127355,127356],"valid",[],"NV8"],[[127357,127358],"valid",[],"NV8"],[[127359,127359],"valid",[],"NV8"],[[127360,127369],"valid",[],"NV8"],[[127370,127373],"valid",[],"NV8"],[[127374,127375],"valid",[],"NV8"],[[127376,127376],"mapped",[100,106]],[[127377,127386],"valid",[],"NV8"],[[127387,127461],"disallowed"],[[127462,127487],"valid",[],"NV8"],[[127488,127488],"mapped",[12411,12363]],[[127489,127489],"mapped",[12467,12467]],[[127490,127490],"mapped",[12469]],[[127491,127503],"disallowed"],[[127504,127504],"mapped",[25163]],[[127505,127505],"mapped",[23383]],[[127506,127506],"mapped",[21452]],[[127507,127507],"mapped",[12487]],[[127508,127508],"mapped",[20108]],[[127509,127509],"mapped",[22810]],[[127510,127510],"mapped",[35299]],[[127511,127511],"mapped",[22825]],[[127512,127512],"mapped",[20132]],[[127513,127513],"mapped",[26144]],[[127514,127514],"mapped",[28961]],[[127515,127515],"mapped",[26009]],[[127516,127516],"mapped",[21069]],[[127517,127517],"mapped",[24460]],[[127518,127518],"mapped",[20877]],[[127519,127519],"mapped",[26032]],[[127520,127520],"mapped",[21021]],[[127521,127521],"mapped",[32066]],[[127522,127522],"mapped",[29983]],[[127523,127523],"mapped",[36009]],[[127524,127524],"mapped",[22768]],[[127525,127525],"mapped",[21561]],[[127526,127526],"mapped",[28436]],[[127527,127527],"mapped",[25237]],[[127528,127528],"mapped",[25429]],[[127529,127529],"mapped",[19968]],[[127530,127530],"mapped",[19977]],[[127531,127531],"mapped",[36938]],[[127532,127532],"mapped",[24038]],[[127533,127533],"mapped",[20013]],[[127534,127534],"mapped",[21491]],[[127535,127535],"mapped",[25351]],[[127536,127536],"mapped",[36208]],[[127537,127537],"mapped",[25171]],[[127538,127538],"mapped",[31105]],[[127539,127539],"mapped",[31354]],[[127540,127540],"mapped",[21512]],[[127541,127541],"mapped",[28288]],[[127542,127542],"mapped",[26377]],[[127543,127543],"mapped",[26376]],[[127544,127544],"mapped",[30003]],[[127545,127545],"mapped",[21106]],[[127546,127546],"mapped",[21942]],[[127547,127551],"disallowed"],[[127552,127552],"mapped",[12308,26412,12309]],[[127553,127553],"mapped",[12308,19977,12309]],[[127554,127554],"mapped",[12308,20108,12309]],[[127555,127555],"mapped",[12308,23433,12309]],[[127556,127556],"mapped",[12308,28857,12309]],[[127557,127557],"mapped",[12308,25171,12309]],[[127558,127558],"mapped",[12308,30423,12309]],[[127559,127559],"mapped",[12308,21213,12309]],[[127560,127560],"mapped",[12308,25943,12309]],[[127561,127567],"disallowed"],[[127568,127568],"mapped",[24471]],[[127569,127569],"mapped",[21487]],[[127570,127743],"disallowed"],[[127744,127776],"valid",[],"NV8"],[[127777,127788],"valid",[],"NV8"],[[127789,127791],"valid",[],"NV8"],[[127792,127797],"valid",[],"NV8"],[[127798,127798],"valid",[],"NV8"],[[127799,127868],"valid",[],"NV8"],[[127869,127869],"valid",[],"NV8"],[[127870,127871],"valid",[],"NV8"],[[127872,127891],"valid",[],"NV8"],[[127892,127903],"valid",[],"NV8"],[[127904,127940],"valid",[],"NV8"],[[127941,127941],"valid",[],"NV8"],[[127942,127946],"valid",[],"NV8"],[[127947,127950],"valid",[],"NV8"],[[127951,127955],"valid",[],"NV8"],[[127956,127967],"valid",[],"NV8"],[[127968,127984],"valid",[],"NV8"],[[127985,127991],"valid",[],"NV8"],[[127992,127999],"valid",[],"NV8"],[[128000,128062],"valid",[],"NV8"],[[128063,128063],"valid",[],"NV8"],[[128064,128064],"valid",[],"NV8"],[[128065,128065],"valid",[],"NV8"],[[128066,128247],"valid",[],"NV8"],[[128248,128248],"valid",[],"NV8"],[[128249,128252],"valid",[],"NV8"],[[128253,128254],"valid",[],"NV8"],[[128255,128255],"valid",[],"NV8"],[[128256,128317],"valid",[],"NV8"],[[128318,128319],"valid",[],"NV8"],[[128320,128323],"valid",[],"NV8"],[[128324,128330],"valid",[],"NV8"],[[128331,128335],"valid",[],"NV8"],[[128336,128359],"valid",[],"NV8"],[[128360,128377],"valid",[],"NV8"],[[128378,128378],"disallowed"],[[128379,128419],"valid",[],"NV8"],[[128420,128420],"disallowed"],[[128421,128506],"valid",[],"NV8"],[[128507,128511],"valid",[],"NV8"],[[128512,128512],"valid",[],"NV8"],[[128513,128528],"valid",[],"NV8"],[[128529,128529],"valid",[],"NV8"],[[128530,128532],"valid",[],"NV8"],[[128533,128533],"valid",[],"NV8"],[[128534,128534],"valid",[],"NV8"],[[128535,128535],"valid",[],"NV8"],[[128536,128536],"valid",[],"NV8"],[[128537,128537],"valid",[],"NV8"],[[128538,128538],"valid",[],"NV8"],[[128539,128539],"valid",[],"NV8"],[[128540,128542],"valid",[],"NV8"],[[128543,128543],"valid",[],"NV8"],[[128544,128549],"valid",[],"NV8"],[[128550,128551],"valid",[],"NV8"],[[128552,128555],"valid",[],"NV8"],[[128556,128556],"valid",[],"NV8"],[[128557,128557],"valid",[],"NV8"],[[128558,128559],"valid",[],"NV8"],[[128560,128563],"valid",[],"NV8"],[[128564,128564],"valid",[],"NV8"],[[128565,128576],"valid",[],"NV8"],[[128577,128578],"valid",[],"NV8"],[[128579,128580],"valid",[],"NV8"],[[128581,128591],"valid",[],"NV8"],[[128592,128639],"valid",[],"NV8"],[[128640,128709],"valid",[],"NV8"],[[128710,128719],"valid",[],"NV8"],[[128720,128720],"valid",[],"NV8"],[[128721,128735],"disallowed"],[[128736,128748],"valid",[],"NV8"],[[128749,128751],"disallowed"],[[128752,128755],"valid",[],"NV8"],[[128756,128767],"disallowed"],[[128768,128883],"valid",[],"NV8"],[[128884,128895],"disallowed"],[[128896,128980],"valid",[],"NV8"],[[128981,129023],"disallowed"],[[129024,129035],"valid",[],"NV8"],[[129036,129039],"disallowed"],[[129040,129095],"valid",[],"NV8"],[[129096,129103],"disallowed"],[[129104,129113],"valid",[],"NV8"],[[129114,129119],"disallowed"],[[129120,129159],"valid",[],"NV8"],[[129160,129167],"disallowed"],[[129168,129197],"valid",[],"NV8"],[[129198,129295],"disallowed"],[[129296,129304],"valid",[],"NV8"],[[129305,129407],"disallowed"],[[129408,129412],"valid",[],"NV8"],[[129413,129471],"disallowed"],[[129472,129472],"valid",[],"NV8"],[[129473,131069],"disallowed"],[[131070,131071],"disallowed"],[[131072,173782],"valid"],[[173783,173823],"disallowed"],[[173824,177972],"valid"],[[177973,177983],"disallowed"],[[177984,178205],"valid"],[[178206,178207],"disallowed"],[[178208,183969],"valid"],[[183970,194559],"disallowed"],[[194560,194560],"mapped",[20029]],[[194561,194561],"mapped",[20024]],[[194562,194562],"mapped",[20033]],[[194563,194563],"mapped",[131362]],[[194564,194564],"mapped",[20320]],[[194565,194565],"mapped",[20398]],[[194566,194566],"mapped",[20411]],[[194567,194567],"mapped",[20482]],[[194568,194568],"mapped",[20602]],[[194569,194569],"mapped",[20633]],[[194570,194570],"mapped",[20711]],[[194571,194571],"mapped",[20687]],[[194572,194572],"mapped",[13470]],[[194573,194573],"mapped",[132666]],[[194574,194574],"mapped",[20813]],[[194575,194575],"mapped",[20820]],[[194576,194576],"mapped",[20836]],[[194577,194577],"mapped",[20855]],[[194578,194578],"mapped",[132380]],[[194579,194579],"mapped",[13497]],[[194580,194580],"mapped",[20839]],[[194581,194581],"mapped",[20877]],[[194582,194582],"mapped",[132427]],[[194583,194583],"mapped",[20887]],[[194584,194584],"mapped",[20900]],[[194585,194585],"mapped",[20172]],[[194586,194586],"mapped",[20908]],[[194587,194587],"mapped",[20917]],[[194588,194588],"mapped",[168415]],[[194589,194589],"mapped",[20981]],[[194590,194590],"mapped",[20995]],[[194591,194591],"mapped",[13535]],[[194592,194592],"mapped",[21051]],[[194593,194593],"mapped",[21062]],[[194594,194594],"mapped",[21106]],[[194595,194595],"mapped",[21111]],[[194596,194596],"mapped",[13589]],[[194597,194597],"mapped",[21191]],[[194598,194598],"mapped",[21193]],[[194599,194599],"mapped",[21220]],[[194600,194600],"mapped",[21242]],[[194601,194601],"mapped",[21253]],[[194602,194602],"mapped",[21254]],[[194603,194603],"mapped",[21271]],[[194604,194604],"mapped",[21321]],[[194605,194605],"mapped",[21329]],[[194606,194606],"mapped",[21338]],[[194607,194607],"mapped",[21363]],[[194608,194608],"mapped",[21373]],[[194609,194611],"mapped",[21375]],[[194612,194612],"mapped",[133676]],[[194613,194613],"mapped",[28784]],[[194614,194614],"mapped",[21450]],[[194615,194615],"mapped",[21471]],[[194616,194616],"mapped",[133987]],[[194617,194617],"mapped",[21483]],[[194618,194618],"mapped",[21489]],[[194619,194619],"mapped",[21510]],[[194620,194620],"mapped",[21662]],[[194621,194621],"mapped",[21560]],[[194622,194622],"mapped",[21576]],[[194623,194623],"mapped",[21608]],[[194624,194624],"mapped",[21666]],[[194625,194625],"mapped",[21750]],[[194626,194626],"mapped",[21776]],[[194627,194627],"mapped",[21843]],[[194628,194628],"mapped",[21859]],[[194629,194630],"mapped",[21892]],[[194631,194631],"mapped",[21913]],[[194632,194632],"mapped",[21931]],[[194633,194633],"mapped",[21939]],[[194634,194634],"mapped",[21954]],[[194635,194635],"mapped",[22294]],[[194636,194636],"mapped",[22022]],[[194637,194637],"mapped",[22295]],[[194638,194638],"mapped",[22097]],[[194639,194639],"mapped",[22132]],[[194640,194640],"mapped",[20999]],[[194641,194641],"mapped",[22766]],[[194642,194642],"mapped",[22478]],[[194643,194643],"mapped",[22516]],[[194644,194644],"mapped",[22541]],[[194645,194645],"mapped",[22411]],[[194646,194646],"mapped",[22578]],[[194647,194647],"mapped",[22577]],[[194648,194648],"mapped",[22700]],[[194649,194649],"mapped",[136420]],[[194650,194650],"mapped",[22770]],[[194651,194651],"mapped",[22775]],[[194652,194652],"mapped",[22790]],[[194653,194653],"mapped",[22810]],[[194654,194654],"mapped",[22818]],[[194655,194655],"mapped",[22882]],[[194656,194656],"mapped",[136872]],[[194657,194657],"mapped",[136938]],[[194658,194658],"mapped",[23020]],[[194659,194659],"mapped",[23067]],[[194660,194660],"mapped",[23079]],[[194661,194661],"mapped",[23000]],[[194662,194662],"mapped",[23142]],[[194663,194663],"mapped",[14062]],[[194664,194664],"disallowed"],[[194665,194665],"mapped",[23304]],[[194666,194667],"mapped",[23358]],[[194668,194668],"mapped",[137672]],[[194669,194669],"mapped",[23491]],[[194670,194670],"mapped",[23512]],[[194671,194671],"mapped",[23527]],[[194672,194672],"mapped",[23539]],[[194673,194673],"mapped",[138008]],[[194674,194674],"mapped",[23551]],[[194675,194675],"mapped",[23558]],[[194676,194676],"disallowed"],[[194677,194677],"mapped",[23586]],[[194678,194678],"mapped",[14209]],[[194679,194679],"mapped",[23648]],[[194680,194680],"mapped",[23662]],[[194681,194681],"mapped",[23744]],[[194682,194682],"mapped",[23693]],[[194683,194683],"mapped",[138724]],[[194684,194684],"mapped",[23875]],[[194685,194685],"mapped",[138726]],[[194686,194686],"mapped",[23918]],[[194687,194687],"mapped",[23915]],[[194688,194688],"mapped",[23932]],[[194689,194689],"mapped",[24033]],[[194690,194690],"mapped",[24034]],[[194691,194691],"mapped",[14383]],[[194692,194692],"mapped",[24061]],[[194693,194693],"mapped",[24104]],[[194694,194694],"mapped",[24125]],[[194695,194695],"mapped",[24169]],[[194696,194696],"mapped",[14434]],[[194697,194697],"mapped",[139651]],[[194698,194698],"mapped",[14460]],[[194699,194699],"mapped",[24240]],[[194700,194700],"mapped",[24243]],[[194701,194701],"mapped",[24246]],[[194702,194702],"mapped",[24266]],[[194703,194703],"mapped",[172946]],[[194704,194704],"mapped",[24318]],[[194705,194706],"mapped",[140081]],[[194707,194707],"mapped",[33281]],[[194708,194709],"mapped",[24354]],[[194710,194710],"mapped",[14535]],[[194711,194711],"mapped",[144056]],[[194712,194712],"mapped",[156122]],[[194713,194713],"mapped",[24418]],[[194714,194714],"mapped",[24427]],[[194715,194715],"mapped",[14563]],[[194716,194716],"mapped",[24474]],[[194717,194717],"mapped",[24525]],[[194718,194718],"mapped",[24535]],[[194719,194719],"mapped",[24569]],[[194720,194720],"mapped",[24705]],[[194721,194721],"mapped",[14650]],[[194722,194722],"mapped",[14620]],[[194723,194723],"mapped",[24724]],[[194724,194724],"mapped",[141012]],[[194725,194725],"mapped",[24775]],[[194726,194726],"mapped",[24904]],[[194727,194727],"mapped",[24908]],[[194728,194728],"mapped",[24910]],[[194729,194729],"mapped",[24908]],[[194730,194730],"mapped",[24954]],[[194731,194731],"mapped",[24974]],[[194732,194732],"mapped",[25010]],[[194733,194733],"mapped",[24996]],[[194734,194734],"mapped",[25007]],[[194735,194735],"mapped",[25054]],[[194736,194736],"mapped",[25074]],[[194737,194737],"mapped",[25078]],[[194738,194738],"mapped",[25104]],[[194739,194739],"mapped",[25115]],[[194740,194740],"mapped",[25181]],[[194741,194741],"mapped",[25265]],[[194742,194742],"mapped",[25300]],[[194743,194743],"mapped",[25424]],[[194744,194744],"mapped",[142092]],[[194745,194745],"mapped",[25405]],[[194746,194746],"mapped",[25340]],[[194747,194747],"mapped",[25448]],[[194748,194748],"mapped",[25475]],[[194749,194749],"mapped",[25572]],[[194750,194750],"mapped",[142321]],[[194751,194751],"mapped",[25634]],[[194752,194752],"mapped",[25541]],[[194753,194753],"mapped",[25513]],[[194754,194754],"mapped",[14894]],[[194755,194755],"mapped",[25705]],[[194756,194756],"mapped",[25726]],[[194757,194757],"mapped",[25757]],[[194758,194758],"mapped",[25719]],[[194759,194759],"mapped",[14956]],[[194760,194760],"mapped",[25935]],[[194761,194761],"mapped",[25964]],[[194762,194762],"mapped",[143370]],[[194763,194763],"mapped",[26083]],[[194764,194764],"mapped",[26360]],[[194765,194765],"mapped",[26185]],[[194766,194766],"mapped",[15129]],[[194767,194767],"mapped",[26257]],[[194768,194768],"mapped",[15112]],[[194769,194769],"mapped",[15076]],[[194770,194770],"mapped",[20882]],[[194771,194771],"mapped",[20885]],[[194772,194772],"mapped",[26368]],[[194773,194773],"mapped",[26268]],[[194774,194774],"mapped",[32941]],[[194775,194775],"mapped",[17369]],[[194776,194776],"mapped",[26391]],[[194777,194777],"mapped",[26395]],[[194778,194778],"mapped",[26401]],[[194779,194779],"mapped",[26462]],[[194780,194780],"mapped",[26451]],[[194781,194781],"mapped",[144323]],[[194782,194782],"mapped",[15177]],[[194783,194783],"mapped",[26618]],[[194784,194784],"mapped",[26501]],[[194785,194785],"mapped",[26706]],[[194786,194786],"mapped",[26757]],[[194787,194787],"mapped",[144493]],[[194788,194788],"mapped",[26766]],[[194789,194789],"mapped",[26655]],[[194790,194790],"mapped",[26900]],[[194791,194791],"mapped",[15261]],[[194792,194792],"mapped",[26946]],[[194793,194793],"mapped",[27043]],[[194794,194794],"mapped",[27114]],[[194795,194795],"mapped",[27304]],[[194796,194796],"mapped",[145059]],[[194797,194797],"mapped",[27355]],[[194798,194798],"mapped",[15384]],[[194799,194799],"mapped",[27425]],[[194800,194800],"mapped",[145575]],[[194801,194801],"mapped",[27476]],[[194802,194802],"mapped",[15438]],[[194803,194803],"mapped",[27506]],[[194804,194804],"mapped",[27551]],[[194805,194805],"mapped",[27578]],[[194806,194806],"mapped",[27579]],[[194807,194807],"mapped",[146061]],[[194808,194808],"mapped",[138507]],[[194809,194809],"mapped",[146170]],[[194810,194810],"mapped",[27726]],[[194811,194811],"mapped",[146620]],[[194812,194812],"mapped",[27839]],[[194813,194813],"mapped",[27853]],[[194814,194814],"mapped",[27751]],[[194815,194815],"mapped",[27926]],[[194816,194816],"mapped",[27966]],[[194817,194817],"mapped",[28023]],[[194818,194818],"mapped",[27969]],[[194819,194819],"mapped",[28009]],[[194820,194820],"mapped",[28024]],[[194821,194821],"mapped",[28037]],[[194822,194822],"mapped",[146718]],[[194823,194823],"mapped",[27956]],[[194824,194824],"mapped",[28207]],[[194825,194825],"mapped",[28270]],[[194826,194826],"mapped",[15667]],[[194827,194827],"mapped",[28363]],[[194828,194828],"mapped",[28359]],[[194829,194829],"mapped",[147153]],[[194830,194830],"mapped",[28153]],[[194831,194831],"mapped",[28526]],[[194832,194832],"mapped",[147294]],[[194833,194833],"mapped",[147342]],[[194834,194834],"mapped",[28614]],[[194835,194835],"mapped",[28729]],[[194836,194836],"mapped",[28702]],[[194837,194837],"mapped",[28699]],[[194838,194838],"mapped",[15766]],[[194839,194839],"mapped",[28746]],[[194840,194840],"mapped",[28797]],[[194841,194841],"mapped",[28791]],[[194842,194842],"mapped",[28845]],[[194843,194843],"mapped",[132389]],[[194844,194844],"mapped",[28997]],[[194845,194845],"mapped",[148067]],[[194846,194846],"mapped",[29084]],[[194847,194847],"disallowed"],[[194848,194848],"mapped",[29224]],[[194849,194849],"mapped",[29237]],[[194850,194850],"mapped",[29264]],[[194851,194851],"mapped",[149000]],[[194852,194852],"mapped",[29312]],[[194853,194853],"mapped",[29333]],[[194854,194854],"mapped",[149301]],[[194855,194855],"mapped",[149524]],[[194856,194856],"mapped",[29562]],[[194857,194857],"mapped",[29579]],[[194858,194858],"mapped",[16044]],[[194859,194859],"mapped",[29605]],[[194860,194861],"mapped",[16056]],[[194862,194862],"mapped",[29767]],[[194863,194863],"mapped",[29788]],[[194864,194864],"mapped",[29809]],[[194865,194865],"mapped",[29829]],[[194866,194866],"mapped",[29898]],[[194867,194867],"mapped",[16155]],[[194868,194868],"mapped",[29988]],[[194869,194869],"mapped",[150582]],[[194870,194870],"mapped",[30014]],[[194871,194871],"mapped",[150674]],[[194872,194872],"mapped",[30064]],[[194873,194873],"mapped",[139679]],[[194874,194874],"mapped",[30224]],[[194875,194875],"mapped",[151457]],[[194876,194876],"mapped",[151480]],[[194877,194877],"mapped",[151620]],[[194878,194878],"mapped",[16380]],[[194879,194879],"mapped",[16392]],[[194880,194880],"mapped",[30452]],[[194881,194881],"mapped",[151795]],[[194882,194882],"mapped",[151794]],[[194883,194883],"mapped",[151833]],[[194884,194884],"mapped",[151859]],[[194885,194885],"mapped",[30494]],[[194886,194887],"mapped",[30495]],[[194888,194888],"mapped",[30538]],[[194889,194889],"mapped",[16441]],[[194890,194890],"mapped",[30603]],[[194891,194891],"mapped",[16454]],[[194892,194892],"mapped",[16534]],[[194893,194893],"mapped",[152605]],[[194894,194894],"mapped",[30798]],[[194895,194895],"mapped",[30860]],[[194896,194896],"mapped",[30924]],[[194897,194897],"mapped",[16611]],[[194898,194898],"mapped",[153126]],[[194899,194899],"mapped",[31062]],[[194900,194900],"mapped",[153242]],[[194901,194901],"mapped",[153285]],[[194902,194902],"mapped",[31119]],[[194903,194903],"mapped",[31211]],[[194904,194904],"mapped",[16687]],[[194905,194905],"mapped",[31296]],[[194906,194906],"mapped",[31306]],[[194907,194907],"mapped",[31311]],[[194908,194908],"mapped",[153980]],[[194909,194910],"mapped",[154279]],[[194911,194911],"disallowed"],[[194912,194912],"mapped",[16898]],[[194913,194913],"mapped",[154539]],[[194914,194914],"mapped",[31686]],[[194915,194915],"mapped",[31689]],[[194916,194916],"mapped",[16935]],[[194917,194917],"mapped",[154752]],[[194918,194918],"mapped",[31954]],[[194919,194919],"mapped",[17056]],[[194920,194920],"mapped",[31976]],[[194921,194921],"mapped",[31971]],[[194922,194922],"mapped",[32000]],[[194923,194923],"mapped",[155526]],[[194924,194924],"mapped",[32099]],[[194925,194925],"mapped",[17153]],[[194926,194926],"mapped",[32199]],[[194927,194927],"mapped",[32258]],[[194928,194928],"mapped",[32325]],[[194929,194929],"mapped",[17204]],[[194930,194930],"mapped",[156200]],[[194931,194931],"mapped",[156231]],[[194932,194932],"mapped",[17241]],[[194933,194933],"mapped",[156377]],[[194934,194934],"mapped",[32634]],[[194935,194935],"mapped",[156478]],[[194936,194936],"mapped",[32661]],[[194937,194937],"mapped",[32762]],[[194938,194938],"mapped",[32773]],[[194939,194939],"mapped",[156890]],[[194940,194940],"mapped",[156963]],[[194941,194941],"mapped",[32864]],[[194942,194942],"mapped",[157096]],[[194943,194943],"mapped",[32880]],[[194944,194944],"mapped",[144223]],[[194945,194945],"mapped",[17365]],[[194946,194946],"mapped",[32946]],[[194947,194947],"mapped",[33027]],[[194948,194948],"mapped",[17419]],[[194949,194949],"mapped",[33086]],[[194950,194950],"mapped",[23221]],[[194951,194951],"mapped",[157607]],[[194952,194952],"mapped",[157621]],[[194953,194953],"mapped",[144275]],[[194954,194954],"mapped",[144284]],[[194955,194955],"mapped",[33281]],[[194956,194956],"mapped",[33284]],[[194957,194957],"mapped",[36766]],[[194958,194958],"mapped",[17515]],[[194959,194959],"mapped",[33425]],[[194960,194960],"mapped",[33419]],[[194961,194961],"mapped",[33437]],[[194962,194962],"mapped",[21171]],[[194963,194963],"mapped",[33457]],[[194964,194964],"mapped",[33459]],[[194965,194965],"mapped",[33469]],[[194966,194966],"mapped",[33510]],[[194967,194967],"mapped",[158524]],[[194968,194968],"mapped",[33509]],[[194969,194969],"mapped",[33565]],[[194970,194970],"mapped",[33635]],[[194971,194971],"mapped",[33709]],[[194972,194972],"mapped",[33571]],[[194973,194973],"mapped",[33725]],[[194974,194974],"mapped",[33767]],[[194975,194975],"mapped",[33879]],[[194976,194976],"mapped",[33619]],[[194977,194977],"mapped",[33738]],[[194978,194978],"mapped",[33740]],[[194979,194979],"mapped",[33756]],[[194980,194980],"mapped",[158774]],[[194981,194981],"mapped",[159083]],[[194982,194982],"mapped",[158933]],[[194983,194983],"mapped",[17707]],[[194984,194984],"mapped",[34033]],[[194985,194985],"mapped",[34035]],[[194986,194986],"mapped",[34070]],[[194987,194987],"mapped",[160714]],[[194988,194988],"mapped",[34148]],[[194989,194989],"mapped",[159532]],[[194990,194990],"mapped",[17757]],[[194991,194991],"mapped",[17761]],[[194992,194992],"mapped",[159665]],[[194993,194993],"mapped",[159954]],[[194994,194994],"mapped",[17771]],[[194995,194995],"mapped",[34384]],[[194996,194996],"mapped",[34396]],[[194997,194997],"mapped",[34407]],[[194998,194998],"mapped",[34409]],[[194999,194999],"mapped",[34473]],[[195000,195000],"mapped",[34440]],[[195001,195001],"mapped",[34574]],[[195002,195002],"mapped",[34530]],[[195003,195003],"mapped",[34681]],[[195004,195004],"mapped",[34600]],[[195005,195005],"mapped",[34667]],[[195006,195006],"mapped",[34694]],[[195007,195007],"disallowed"],[[195008,195008],"mapped",[34785]],[[195009,195009],"mapped",[34817]],[[195010,195010],"mapped",[17913]],[[195011,195011],"mapped",[34912]],[[195012,195012],"mapped",[34915]],[[195013,195013],"mapped",[161383]],[[195014,195014],"mapped",[35031]],[[195015,195015],"mapped",[35038]],[[195016,195016],"mapped",[17973]],[[195017,195017],"mapped",[35066]],[[195018,195018],"mapped",[13499]],[[195019,195019],"mapped",[161966]],[[195020,195020],"mapped",[162150]],[[195021,195021],"mapped",[18110]],[[195022,195022],"mapped",[18119]],[[195023,195023],"mapped",[35488]],[[195024,195024],"mapped",[35565]],[[195025,195025],"mapped",[35722]],[[195026,195026],"mapped",[35925]],[[195027,195027],"mapped",[162984]],[[195028,195028],"mapped",[36011]],[[195029,195029],"mapped",[36033]],[[195030,195030],"mapped",[36123]],[[195031,195031],"mapped",[36215]],[[195032,195032],"mapped",[163631]],[[195033,195033],"mapped",[133124]],[[195034,195034],"mapped",[36299]],[[195035,195035],"mapped",[36284]],[[195036,195036],"mapped",[36336]],[[195037,195037],"mapped",[133342]],[[195038,195038],"mapped",[36564]],[[195039,195039],"mapped",[36664]],[[195040,195040],"mapped",[165330]],[[195041,195041],"mapped",[165357]],[[195042,195042],"mapped",[37012]],[[195043,195043],"mapped",[37105]],[[195044,195044],"mapped",[37137]],[[195045,195045],"mapped",[165678]],[[195046,195046],"mapped",[37147]],[[195047,195047],"mapped",[37432]],[[195048,195048],"mapped",[37591]],[[195049,195049],"mapped",[37592]],[[195050,195050],"mapped",[37500]],[[195051,195051],"mapped",[37881]],[[195052,195052],"mapped",[37909]],[[195053,195053],"mapped",[166906]],[[195054,195054],"mapped",[38283]],[[195055,195055],"mapped",[18837]],[[195056,195056],"mapped",[38327]],[[195057,195057],"mapped",[167287]],[[195058,195058],"mapped",[18918]],[[195059,195059],"mapped",[38595]],[[195060,195060],"mapped",[23986]],[[195061,195061],"mapped",[38691]],[[195062,195062],"mapped",[168261]],[[195063,195063],"mapped",[168474]],[[195064,195064],"mapped",[19054]],[[195065,195065],"mapped",[19062]],[[195066,195066],"mapped",[38880]],[[195067,195067],"mapped",[168970]],[[195068,195068],"mapped",[19122]],[[195069,195069],"mapped",[169110]],[[195070,195071],"mapped",[38923]],[[195072,195072],"mapped",[38953]],[[195073,195073],"mapped",[169398]],[[195074,195074],"mapped",[39138]],[[195075,195075],"mapped",[19251]],[[195076,195076],"mapped",[39209]],[[195077,195077],"mapped",[39335]],[[195078,195078],"mapped",[39362]],[[195079,195079],"mapped",[39422]],[[195080,195080],"mapped",[19406]],[[195081,195081],"mapped",[170800]],[[195082,195082],"mapped",[39698]],[[195083,195083],"mapped",[40000]],[[195084,195084],"mapped",[40189]],[[195085,195085],"mapped",[19662]],[[195086,195086],"mapped",[19693]],[[195087,195087],"mapped",[40295]],[[195088,195088],"mapped",[172238]],[[195089,195089],"mapped",[19704]],[[195090,195090],"mapped",[172293]],[[195091,195091],"mapped",[172558]],[[195092,195092],"mapped",[172689]],[[195093,195093],"mapped",[40635]],[[195094,195094],"mapped",[19798]],[[195095,195095],"mapped",[40697]],[[195096,195096],"mapped",[40702]],[[195097,195097],"mapped",[40709]],[[195098,195098],"mapped",[40719]],[[195099,195099],"mapped",[40726]],[[195100,195100],"mapped",[40763]],[[195101,195101],"mapped",[173568]],[[195102,196605],"disallowed"],[[196606,196607],"disallowed"],[[196608,262141],"disallowed"],[[262142,262143],"disallowed"],[[262144,327677],"disallowed"],[[327678,327679],"disallowed"],[[327680,393213],"disallowed"],[[393214,393215],"disallowed"],[[393216,458749],"disallowed"],[[458750,458751],"disallowed"],[[458752,524285],"disallowed"],[[524286,524287],"disallowed"],[[524288,589821],"disallowed"],[[589822,589823],"disallowed"],[[589824,655357],"disallowed"],[[655358,655359],"disallowed"],[[655360,720893],"disallowed"],[[720894,720895],"disallowed"],[[720896,786429],"disallowed"],[[786430,786431],"disallowed"],[[786432,851965],"disallowed"],[[851966,851967],"disallowed"],[[851968,917501],"disallowed"],[[917502,917503],"disallowed"],[[917504,917504],"disallowed"],[[917505,917505],"disallowed"],[[917506,917535],"disallowed"],[[917536,917631],"disallowed"],[[917632,917759],"disallowed"],[[917760,917999],"ignored"],[[918000,983037],"disallowed"],[[983038,983039],"disallowed"],[[983040,1048573],"disallowed"],[[1048574,1048575],"disallowed"],[[1048576,1114109],"disallowed"],[[1114110,1114111],"disallowed"]]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +const core = __nccwpck_require__(37484); +const { Storage } = __nccwpck_require__(28525); +const { + S3Client, + HeadObjectCommand, + GetObjectCommand, +} = __nccwpck_require__(53711); +const fs = (__nccwpck_require__(79896).promises); +const rawFs = __nccwpck_require__(79896); +const path = __nccwpck_require__(16928); +const cp = __nccwpck_require__(35317); +const os = __nccwpck_require__(70857); +const util = __nccwpck_require__(39023); +const exec = util.promisify(cp.exec); +function sleep(ms) { + return new Promise((res) => setTimeout(res, ms)); +} +function expandTilde(inputPath) { + if (inputPath.charAt(0) === "~") { + const home = os.homedir(); + return home + inputPath.slice(1); + } + return inputPath; +} +async function run() { + try { + // Get inputs + const provider = core.getInput("provider").toLowerCase(); + const bucketName = core.getInput("bucket"); + let prefix = core.getInput("prefix"); + const primaryKeyInput = core.getInput("primary-key"); + const primaryKeyGenerator = core.getInput("primary-key-generator"); + const fallbackKeysInput = core.getInput("fallback-keys"); + const fallbackKeyGenerator = core.getInput("fallback-key-generator"); + const localPathInput = core.getInput("local-path"); + const skipDownload = core.getInput("skip-download") === "true"; + const localPath = path.resolve(process.cwd(), expandTilde(localPathInput)); + if (!primaryKeyInput && !primaryKeyGenerator) { + throw new Error( + 'Either "primary-key" or "primary-key-generator" must be provided' + ); + } + const retryAttempts = parseInt(core.getInput("retries") || "3", 10); + const retryBaseDelayMs = parseInt( + core.getInput("retry-delay-ms") || "1000", + 10 + ); + const downloadPartCount = Math.max( + 1, + parseInt(core.getInput("download-part-count") || "128", 10) + ); + const downloadConcurrencyInput = parseInt( + core.getInput("download-concurrency") || "32", + 10 + ); + // Save state for post + core.saveState("provider", provider); + core.saveState("bucketName", bucketName); + core.saveState("local-path", localPath); + let gcsStorage, gcsBucket, s3Client; + + // Only initialize storage clients if we're actually going to use them + // When skip-download is true, we don't need credentials for downloading + const needsCredentials = !skipDownload; + + if (provider === "gcs") { + const base64Key = core.getInput("gcs-key"); + if (!base64Key) { + if (needsCredentials) { + throw new Error("gcs-key is required when skip-download is false"); + } + core.warning("GCS key not provided. Cache operations will be skipped."); + core.setOutput("cache-hit", "false"); + core.setOutput("restored", "false"); + core.setOutput("path", localPath); + return; + } + core.saveState("base64Key", base64Key); + // Decode base64 key to JSON + const jsonKeyString = Buffer.from(base64Key, "base64").toString("utf-8"); + let credentials; + try { + credentials = JSON.parse(jsonKeyString); + } catch (err) { + throw new Error("Invalid base64 encoded JSON key"); + } + // Initialize GCS client + gcsStorage = new Storage({ credentials }); + gcsBucket = gcsStorage.bucket(bucketName); + } else if (provider === "s3") { + const s3AccessKey = core.getInput("s3-access-key"); + const s3SecretKey = core.getInput("s3-secret-key"); + const s3Endpoint = core.getInput("s3-endpoint"); + const s3Region = core.getInput("s3-region"); + + if (!s3AccessKey || !s3SecretKey) { + if (needsCredentials) { + throw new Error("s3-access-key and s3-secret-key are required when skip-download is false"); + } + core.warning("S3 credentials not provided. Cache operations will be skipped."); + core.setOutput("cache-hit", "false"); + core.setOutput("restored", "false"); + core.setOutput("path", localPath); + return; + } + + core.saveState("s3AccessKey", s3AccessKey); + core.saveState("s3SecretKey", s3SecretKey); + core.saveState("s3Endpoint", s3Endpoint); + core.saveState("s3Region", s3Region); + // Initialize S3 client + const s3Config = { + region: s3Region || "auto", + credentials: { + accessKeyId: s3AccessKey, + secretAccessKey: s3SecretKey, + }, + forcePathStyle: true, + }; + if (s3Endpoint) { + s3Config.endpoint = s3Endpoint; + } + s3Client = new S3Client(s3Config); + } else { + throw new Error(`Unsupported provider: ${provider}`); + } + // Normalize prefix + if (prefix && !prefix.endsWith("/")) { + prefix += "/"; + } + if (!prefix) { + prefix = ""; + } + core.saveState("prefix", prefix); + // Determine primary key (without extension) + let primary = ""; + if (primaryKeyGenerator) { + // Create temp file for PRIMARY_KEY + const primaryKeyPath = path.join( + os.tmpdir(), + `primary_key_${process.pid}.txt` + ); + await fs.writeFile(primaryKeyPath, ""); + // Create temp script file + const scriptPath = path.join( + os.tmpdir(), + `primary_gen_${process.pid}.sh` + ); + const scriptContent = `#!/bin/bash\n${primaryKeyGenerator}`; + await fs.writeFile(scriptPath, scriptContent); + await fs.chmod(scriptPath, 0o755); + // Execute the script + await new Promise((resolve, reject) => { + const child = cp.execFile(scriptPath, { + env: { ...process.env, PRIMARY_KEY: primaryKeyPath }, + }); + let stdout = ""; + let stderr = ""; + child.stdout.on("data", (data) => { + stdout += data; + }); + child.stderr.on("data", (data) => { + stderr += data; + }); + child.on("close", (code) => { + if (code !== 0) { + reject( + new Error( + `Primary script exited with code ${code}. Stderr: ${stderr}` + ) + ); + } else { + core.info(`Primary script output: ${stdout}`); + if (stderr) core.warning(`Primary script stderr: ${stderr}`); + resolve(); + } + }); + }); + // Read generated primary key + const primaryContent = await fs.readFile(primaryKeyPath, "utf-8"); + const primaryLines = primaryContent + .split("\n") + .map((k) => k.trim()) + .filter((k) => k.length > 0); + if (primaryLines.length !== 1) { + throw new Error("Primary key generator must produce exactly one key"); + } + primary = primaryLines[0]; + // Clean up temp files + await fs.unlink(scriptPath).catch(() => {}); + await fs.unlink(primaryKeyPath).catch(() => {}); + } else { + primary = primaryKeyInput.trim(); + if (!primary) { + throw new Error("Primary key is empty"); + } + } + core.saveState("primaryKey", primary); + // Optionally skip restore phase + if (skipDownload) { + core.setOutput("cache-hit", false); + core.saveState("cacheHit", false); + core.setOutput("path", localPath); + core.setOutput("restored", false); + console.log("skip-download parameter is true, skipping cache restore"); + return; + } + // Determine fallback keys (without extension) + let fallbacks = []; + if (fallbackKeyGenerator) { + // Create temp file for FALLBACK_KEYS + const fallbackKeysPath = path.join( + os.tmpdir(), + `fallback_keys_${process.pid}.txt` + ); + await fs.writeFile(fallbackKeysPath, ""); + // Create temp script file + const scriptPath = path.join( + os.tmpdir(), + `fallback_gen_${process.pid}.sh` + ); + const scriptContent = `#!/bin/bash\n${fallbackKeyGenerator}`; + await fs.writeFile(scriptPath, scriptContent); + await fs.chmod(scriptPath, 0o755); + // Execute the script + await new Promise((resolve, reject) => { + const child = cp.execFile(scriptPath, { + env: { ...process.env, FALLBACK_KEYS: fallbackKeysPath }, + }); + let stdout = ""; + let stderr = ""; + child.stdout.on("data", (data) => { + stdout += data; + }); + child.stderr.on("data", (data) => { + stderr += data; + }); + child.on("close", (code) => { + if (code !== 0) { + reject( + new Error( + `Fallback script exited with code ${code}. Stderr: ${stderr}` + ) + ); + } else { + core.info(`Fallback script output: ${stdout}`); + if (stderr) core.warning(`Fallback script stderr: ${stderr}`); + resolve(); + } + }); + }); + // Read generated fallback keys + const fallbacksContent = await fs.readFile(fallbackKeysPath, "utf-8"); + fallbacks = fallbacksContent + .split("\n") + .map((k) => k.trim()) + .filter((k) => k.length > 0); + // Clean up temp files + await fs.unlink(scriptPath).catch(() => {}); + await fs.unlink(fallbackKeysPath).catch(() => {}); + } else if (fallbackKeysInput) { + fallbacks = fallbackKeysInput + .split(",") + .map((k) => k.trim()) + .filter((k) => k.length > 0); + } + // Add extension to all keys + const primaryWithExt = primary + ".tar.zst"; + const fallbacksWithExt = fallbacks.map((k) => k + ".tar.zst"); + const keys = [primaryWithExt, ...fallbacksWithExt]; + if (keys.length === 0) { + throw new Error("No keys provided or generated"); + } + // Check existence in parallel + const existsPromises = keys.map(async (key) => { + const fullPath = prefix + key; + if (provider === "gcs") { + const [exists] = await gcsBucket.file(fullPath).exists(); + return exists; + } else if (provider === "s3") { + try { + await s3Client.send( + new HeadObjectCommand({ Bucket: bucketName, Key: fullPath }) + ); + return true; + } catch (err) { + if (err.name === "NotFound") { + return false; + } + throw err; + } + } + }); + const existsResults = await Promise.all(existsPromises); + // Find the first existing key in order + let selectedIndex = -1; + for (let i = 0; i < existsResults.length; i++) { + if (existsResults[i]) { + selectedIndex = i; + break; + } + } + const cacheHit = selectedIndex === 0; + core.setOutput("cache-hit", cacheHit); + core.saveState("cacheHit", cacheHit); + let restored = false; + if (selectedIndex !== -1) { + // Download and extract the selected archive + const selectedKey = keys[selectedIndex]; + const fullPath = prefix + selectedKey; + const tempDir = os.tmpdir(); + const tempArchive = path.join(tempDir, `cache_${process.pid}.tar.zst`); + const tempTar = path.join(tempDir, `cache_${process.pid}.tar`); + let fileSize = 0; + if (provider === "gcs") { + const file = gcsBucket.file(fullPath); + const [metadata] = await file.getMetadata(); + fileSize = Number(metadata.size); + } else if (provider === "s3") { + const head = await s3Client.send( + new HeadObjectCommand({ Bucket: bucketName, Key: fullPath }) + ); + fileSize = head.ContentLength; + } + if (fileSize === 0) { + await fs.writeFile(tempArchive, ""); + } else { + await fs.writeFile(tempArchive, ""); + await fs.truncate(tempArchive, fileSize); + // Derive part size from desired part count + const partSize = Math.max(1, Math.ceil(fileSize / downloadPartCount)); + const numParts = Math.max(1, Math.ceil(fileSize / partSize)); + const downloadConcurrency = Math.max( + 1, + Math.min(downloadConcurrencyInput, numParts) + ); + console.log( + `Downloading ${fileSize} bytes in ${numParts} parts (concurrency=${downloadConcurrency})` + ); + async function downloadPart(start, end) { + for (let attempt = 1; attempt <= retryAttempts; attempt++) { + let readStream; + let writeStream; + try { + if (provider === "gcs") { + const file = gcsBucket.file(fullPath); + readStream = file.createReadStream({ start, end }); + } else if (provider === "s3") { + const getCommand = new GetObjectCommand({ + Bucket: bucketName, + Key: fullPath, + Range: `bytes=${start}-${end}`, + }); + const response = await s3Client.send(getCommand); + readStream = response.Body; + } + writeStream = rawFs.createWriteStream(tempArchive, { + flags: "r+", + start, + }); + await new Promise((resolve, reject) => { + const onError = async (err) => { + cleanup(); + reject(err); + }; + const onFinish = () => { + cleanup(); + resolve(); + }; + const cleanup = () => { + if (readStream) { + readStream.removeListener("error", onError); + } + if (writeStream) { + writeStream.removeListener("error", onError); + writeStream.removeListener("finish", onFinish); + } + }; + writeStream.on("finish", onFinish); + writeStream.on("error", onError); + readStream.on("error", onError); + readStream.pipe(writeStream); + }); + return; // success + } catch (err) { + if (attempt >= retryAttempts) { + core.error( + `Download part ${start}-${end} failed after ${attempt} attempts: ${err.message}` + ); + throw err; + } + const backoff = + retryBaseDelayMs * Math.pow(2, attempt - 1) + + Math.floor(Math.random() * retryBaseDelayMs); + core.warning( + `Download part ${start}-${end} attempt ${attempt} failed: ${err.message}. Retrying in ${backoff}ms` + ); + await sleep(backoff); + } + } + } + let nextIndex = 0; + async function worker() { + while (true) { + const i = nextIndex++; + if (i >= numParts) return; + const start = i * partSize; + const end = Math.min(start + partSize - 1, fileSize - 1); + if (start > end) continue; + await downloadPart(start, end); + } + } + const workers = []; + for (let w = 0; w < downloadConcurrency; w++) { + workers.push(worker()); + } + await Promise.all(workers); + } + // Decompress + await exec(`zstd -d ${tempArchive} -o ${tempTar}`); + // Create local directory if needed + await fs.mkdir(localPath, { recursive: true }); + // Extract + await exec(`tar -xf ${tempTar} -C ${localPath}`); + // Clean up temps + await fs.unlink(tempArchive).catch(() => {}); + await fs.unlink(tempTar).catch(() => {}); + restored = true; + console.log(`Restored cache from ${fullPath} to ${localPath}`); + } else { + console.log("Cache miss: no matching keys found"); + } + // Set outputs + core.setOutput("path", localPath); + core.setOutput("restored", restored); + } catch (error) { + core.setFailed(error.message); + } +} +run(); + +module.exports = __webpack_exports__; +/******/ })() +; \ No newline at end of file diff --git a/.github/actions/cloud-cache/dist/post/index.js b/.github/actions/cloud-cache/dist/post/index.js new file mode 100644 index 0000000..a7c1cdc --- /dev/null +++ b/.github/actions/cloud-cache/dist/post/index.js @@ -0,0 +1,108651 @@ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 44914: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.issue = exports.issueCommand = void 0; +const os = __importStar(__nccwpck_require__(70857)); +const utils_1 = __nccwpck_require__(30302); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return (0, utils_1.toCommandValue)(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return (0, utils_1.toCommandValue)(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 37484: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.platform = exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = exports.markdownSummary = exports.summary = exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; +const command_1 = __nccwpck_require__(44914); +const file_command_1 = __nccwpck_require__(24753); +const utils_1 = __nccwpck_require__(30302); +const os = __importStar(__nccwpck_require__(70857)); +const path = __importStar(__nccwpck_require__(16928)); +const oidc_utils_1 = __nccwpck_require__(35306); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode || (exports.ExitCode = ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = (0, utils_1.toCommandValue)(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + return (0, file_command_1.issueFileCommand)('ENV', (0, file_command_1.prepareKeyValueMessage)(name, val)); + } + (0, command_1.issueCommand)('set-env', { name }, convertedVal); +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + (0, command_1.issueCommand)('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + (0, file_command_1.issueFileCommand)('PATH', inputPath); + } + else { + (0, command_1.issueCommand)('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); +} +exports.getMultilineInput = getMultilineInput; +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +exports.getBooleanInput = getBooleanInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return (0, file_command_1.issueFileCommand)('OUTPUT', (0, file_command_1.prepareKeyValueMessage)(name, value)); + } + process.stdout.write(os.EOL); + (0, command_1.issueCommand)('set-output', { name }, (0, utils_1.toCommandValue)(value)); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + (0, command_1.issue)('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + (0, command_1.issueCommand)('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function error(message, properties = {}) { + (0, command_1.issueCommand)('error', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds a warning issue + * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function warning(message, properties = {}) { + (0, command_1.issueCommand)('warning', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + (0, command_1.issueCommand)('notice', (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + (0, command_1.issue)('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + (0, command_1.issue)('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return (0, file_command_1.issueFileCommand)('STATE', (0, file_command_1.prepareKeyValueMessage)(name, value)); + } + (0, command_1.issueCommand)('save-state', { name }, (0, utils_1.toCommandValue)(value)); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); +} +exports.getIDToken = getIDToken; +/** + * Summary exports + */ +var summary_1 = __nccwpck_require__(71847); +Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); +/** + * @deprecated use core.summary + */ +var summary_2 = __nccwpck_require__(71847); +Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); +/** + * Path exports + */ +var path_utils_1 = __nccwpck_require__(31976); +Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); +Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); +Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); +/** + * Platform utilities exports + */ +exports.platform = __importStar(__nccwpck_require__(18968)); +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 24753: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// For internal use, subject to change. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +const crypto = __importStar(__nccwpck_require__(76982)); +const fs = __importStar(__nccwpck_require__(79896)); +const os = __importStar(__nccwpck_require__(70857)); +const utils_1 = __nccwpck_require__(30302); +function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${(0, utils_1.toCommandValue)(message)}${os.EOL}`, { + encoding: 'utf8' + }); +} +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${crypto.randomUUID()}`; + const convertedValue = (0, utils_1.toCommandValue)(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; +//# sourceMappingURL=file-command.js.map + +/***/ }), + +/***/ 35306: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OidcClient = void 0; +const http_client_1 = __nccwpck_require__(54844); +const auth_1 = __nccwpck_require__(44552); +const core_1 = __nccwpck_require__(37484); +class OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + (0, core_1.debug)(`ID token url is ${id_token_url}`); + const id_token = yield OidcClient.getCall(id_token_url); + (0, core_1.setSecret)(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +exports.OidcClient = OidcClient; +//# sourceMappingURL=oidc-utils.js.map + +/***/ }), + +/***/ 31976: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; +const path = __importStar(__nccwpck_require__(16928)); +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +exports.toPosixPath = toPosixPath; +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +exports.toWin32Path = toWin32Path; +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +exports.toPlatformPath = toPlatformPath; +//# sourceMappingURL=path-utils.js.map + +/***/ }), + +/***/ 18968: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getDetails = exports.isLinux = exports.isMacOS = exports.isWindows = exports.arch = exports.platform = void 0; +const os_1 = __importDefault(__nccwpck_require__(70857)); +const exec = __importStar(__nccwpck_require__(95236)); +const getWindowsInfo = () => __awaiter(void 0, void 0, void 0, function* () { + const { stdout: version } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', undefined, { + silent: true + }); + const { stdout: name } = yield exec.getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', undefined, { + silent: true + }); + return { + name: name.trim(), + version: version.trim() + }; +}); +const getMacOsInfo = () => __awaiter(void 0, void 0, void 0, function* () { + var _a, _b, _c, _d; + const { stdout } = yield exec.getExecOutput('sw_vers', undefined, { + silent: true + }); + const version = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ''; + const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ''; + return { + name, + version + }; +}); +const getLinuxInfo = () => __awaiter(void 0, void 0, void 0, function* () { + const { stdout } = yield exec.getExecOutput('lsb_release', ['-i', '-r', '-s'], { + silent: true + }); + const [name, version] = stdout.trim().split('\n'); + return { + name, + version + }; +}); +exports.platform = os_1.default.platform(); +exports.arch = os_1.default.arch(); +exports.isWindows = exports.platform === 'win32'; +exports.isMacOS = exports.platform === 'darwin'; +exports.isLinux = exports.platform === 'linux'; +function getDetails() { + return __awaiter(this, void 0, void 0, function* () { + return Object.assign(Object.assign({}, (yield (exports.isWindows + ? getWindowsInfo() + : exports.isMacOS + ? getMacOsInfo() + : getLinuxInfo()))), { platform: exports.platform, + arch: exports.arch, + isWindows: exports.isWindows, + isMacOS: exports.isMacOS, + isLinux: exports.isLinux }); + }); +} +exports.getDetails = getDetails; +//# sourceMappingURL=platform.js.map + +/***/ }), + +/***/ 71847: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __nccwpck_require__(70857); +const fs_1 = __nccwpck_require__(79896); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +exports.markdownSummary = _summary; +exports.summary = _summary; +//# sourceMappingURL=summary.js.map + +/***/ }), + +/***/ 30302: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toCommandProperties = exports.toCommandValue = void 0; +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 95236: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getExecOutput = exports.exec = void 0; +const string_decoder_1 = __nccwpck_require__(13193); +const tr = __importStar(__nccwpck_require__(6665)); +/** + * Exec a command. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code + */ +function exec(commandLine, args, options) { + return __awaiter(this, void 0, void 0, function* () { + const commandArgs = tr.argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + // Path to tool to execute should be first arg + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new tr.ToolRunner(toolPath, args, options); + return runner.exec(); + }); +} +exports.exec = exec; +/** + * Exec a command and get the output. + * Output will be streamed to the live console. + * Returns promise with the exit code and collected stdout and stderr + * + * @param commandLine command to execute (can include additional args). Must be correctly escaped. + * @param args optional arguments for tool. Escaping is handled by the lib. + * @param options optional exec options. See ExecOptions + * @returns Promise exit code, stdout, and stderr + */ +function getExecOutput(commandLine, args, options) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + let stdout = ''; + let stderr = ''; + //Using string decoder covers the case where a mult-byte character is split + const stdoutDecoder = new string_decoder_1.StringDecoder('utf8'); + const stderrDecoder = new string_decoder_1.StringDecoder('utf8'); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + //flush any remaining characters + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); +} +exports.getExecOutput = getExecOutput; +//# sourceMappingURL=exec.js.map + +/***/ }), + +/***/ 6665: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.argStringToArray = exports.ToolRunner = void 0; +const os = __importStar(__nccwpck_require__(70857)); +const events = __importStar(__nccwpck_require__(24434)); +const child = __importStar(__nccwpck_require__(35317)); +const path = __importStar(__nccwpck_require__(16928)); +const io = __importStar(__nccwpck_require__(94994)); +const ioUtil = __importStar(__nccwpck_require__(75207)); +const timers_1 = __nccwpck_require__(53557); +/* eslint-disable @typescript-eslint/unbound-method */ +const IS_WINDOWS = process.platform === 'win32'; +/* + * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. + */ +class ToolRunner extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; + } + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } + } + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool + if (IS_WINDOWS) { + // Windows + cmd file + if (this._isCmdFile()) { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows + verbatim + else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } + } + // Windows (regular) + else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } + } + } + else { + // OSX/Linux - this can likely be improved with some form of quoting. + // creating processes on Unix is fundamentally different than Windows. + // on Unix, execvp() takes an arg array. + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + return cmd; + } + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n = s.indexOf(os.EOL); + while (n > -1) { + const line = s.substring(0, n); + onLine(line); + // the rest of the string ... + s = s.substring(n + os.EOL.length); + n = s.indexOf(os.EOL); + } + return s; + } + catch (err) { + // streaming lines to console is best effort. Don't fail a build. + this._debug(`error processing line. Failed with error ${err}`); + return ''; + } + } + _getSpawnFileName() { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + return process.env['COMSPEC'] || 'cmd.exe'; + } + } + return this.toolPath; + } + _getSpawnArgs(options) { + if (IS_WINDOWS) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += ' '; + argline += options.windowsVerbatimArguments + ? a + : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; + } + } + return this.args; + } + _endsWith(str, end) { + return str.endsWith(end); + } + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return (this._endsWith(upperToolPath, '.CMD') || + this._endsWith(upperToolPath, '.BAT')); + } + _windowsQuoteCmdArg(arg) { + // for .exe, apply the normal quoting rules that libuv applies + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + // otherwise apply quoting rules specific to the cmd.exe command line parser. + // the libuv rules are generic and are not designed specifically for cmd.exe + // command line parser. + // + // for a detailed description of the cmd.exe command line parser, refer to + // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 + // need quotes for empty arg + if (!arg) { + return '""'; + } + // determine whether the arg needs to be quoted + const cmdSpecialChars = [ + ' ', + '\t', + '&', + '(', + ')', + '[', + ']', + '{', + '}', + '^', + '=', + ';', + '!', + "'", + '+', + ',', + '`', + '~', + '|', + '<', + '>', + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some(x => x === char)) { + needsQuotes = true; + break; + } + } + // short-circuit if quotes not needed + if (!needsQuotes) { + return arg; + } + // the following quoting rules are very similar to the rules that by libuv applies. + // + // 1) wrap the string in quotes + // + // 2) double-up quotes - i.e. " => "" + // + // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately + // doesn't work well with a cmd.exe command line. + // + // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. + // for example, the command line: + // foo.exe "myarg:""my val""" + // is parsed by a .NET console app into an arg array: + // [ "myarg:\"my val\"" ] + // which is the same end result when applying libuv quoting rules. although the actual + // command line from libuv quoting rules would look like: + // foo.exe "myarg:\"my val\"" + // + // 3) double-up slashes that precede a quote, + // e.g. hello \world => "hello \world" + // hello\"world => "hello\\""world" + // hello\\"world => "hello\\\\""world" + // hello world\ => "hello world\\" + // + // technically this is not required for a cmd.exe command line, or the batch argument parser. + // the reasons for including this as a .cmd quoting rule are: + // + // a) this is optimized for the scenario where the argument is passed from the .cmd file to an + // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. + // + // b) it's what we've been doing previously (by deferring to node default behavior) and we + // haven't heard any complaints about that aspect. + // + // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be + // escaped when used on the command line directly - even though within a .cmd file % can be escaped + // by using %%. + // + // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts + // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. + // + // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would + // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the + // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args + // to an external program. + // + // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. + // % can be escaped within a .cmd file. + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; // double the slash + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; // double the quote + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _uvQuoteCmdArg(arg) { + // Tool runner wraps child_process.spawn() and needs to apply the same quoting as + // Node in certain cases where the undocumented spawn option windowsVerbatimArguments + // is used. + // + // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, + // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), + // pasting copyright notice from Node within this function: + // + // Copyright Joyent, Inc. and other Node contributors. All rights reserved. + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the "Software"), to + // deal in the Software without restriction, including without limitation the + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + // sell copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + // IN THE SOFTWARE. + if (!arg) { + // Need double quotation for empty argument + return '""'; + } + if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { + // No quotation needed + return arg; + } + if (!arg.includes('"') && !arg.includes('\\')) { + // No embedded double quotes or backslashes, so I can just wrap + // quote marks around the whole thing. + return `"${arg}"`; + } + // Expected input/output: + // input : hello"world + // output: "hello\"world" + // input : hello""world + // output: "hello\"\"world" + // input : hello\world + // output: hello\world + // input : hello\\world + // output: hello\\world + // input : hello\"world + // output: "hello\\\"world" + // input : hello\\"world + // output: "hello\\\\\"world" + // input : hello world\ + // output: "hello world\\" - note the comment in libuv actually reads "hello world\" + // but it appears the comment is wrong, it should be "hello world\\" + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + // walk the string in reverse + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === '\\') { + reverse += '\\'; + } + else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '\\'; + } + else { + quoteHit = false; + } + } + reverse += '"'; + return reverse + .split('') + .reverse() + .join(''); + } + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 10000 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; + } + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result['windowsVerbatimArguments'] = + options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; + } + /** + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code + * + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number + */ + exec() { + return __awaiter(this, void 0, void 0, function* () { + // root the tool path if it is unrooted and contains relative pathing + if (!ioUtil.isRooted(this.toolPath) && + (this.toolPath.includes('/') || + (IS_WINDOWS && this.toolPath.includes('\\')))) { + // prefer options.cwd if it is specified, however options.cwd may also need to be rooted + this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + // if the tool is only a file name, then resolve it from the PATH + // otherwise verify it exists (add extension on Windows if necessary) + this.toolPath = yield io.which(this.toolPath, true); + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug('arguments:'); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on('debug', (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield ioUtil.exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ''; + if (cp.stdout) { + cp.stdout.on('data', (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ''; + if (cp.stderr) { + cp.stderr.on('data', (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && + optionsNonNull.errStream && + optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr + ? optionsNonNull.errStream + : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on('error', (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on('exit', (code) => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on('close', (code) => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on('done', (error, exitCode) => { + if (stdbuffer.length > 0) { + this.emit('stdline', stdbuffer); + } + if (errbuffer.length > 0) { + this.emit('errline', errbuffer); + } + cp.removeAllListeners(); + if (error) { + reject(error); + } + else { + resolve(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error('child process missing stdin'); + } + cp.stdin.end(this.options.input); + } + })); + }); + } +} +exports.ToolRunner = ToolRunner; +/** + * Convert an arg string to an array of args. Handles escaping + * + * @param argString string of arguments + * @returns string[] array of arguments + */ +function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ''; + function append(c) { + // we only escape double quotes. + if (escaped && c !== '"') { + arg += '\\'; + } + arg += c; + escaped = false; + } + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } + else { + append(c); + } + continue; + } + if (c === '\\' && escaped) { + append(c); + continue; + } + if (c === '\\' && inQuotes) { + escaped = true; + continue; + } + if (c === ' ' && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ''; + } + continue; + } + append(c); + } + if (arg.length > 0) { + args.push(arg.trim()); + } + return args; +} +exports.argStringToArray = argStringToArray; +class ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; // tracks whether the process has exited and stdio is closed + this.processError = ''; + this.processExitCode = 0; + this.processExited = false; // tracks whether the process has exited + this.processStderr = false; // tracks whether stderr was written to + this.delay = 10000; // 10 seconds + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error('toolPath must not be empty'); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } + else if (this.processExited) { + this.timeout = timers_1.setTimeout(ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit('debug', message); + } + _setResult() { + // determine whether there is an error + let error; + if (this.processExited) { + if (this.processError) { + error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } + else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } + else if (this.processStderr && this.options.failOnStdErr) { + error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + // clear the timeout + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit('done', error, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / + 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); + } +} +//# sourceMappingURL=toolrunner.js.map + +/***/ }), + +/***/ 44552: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BasicCredentialHandler = BasicCredentialHandler; +class BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BearerCredentialHandler = BearerCredentialHandler; +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; +//# sourceMappingURL=auth.js.map + +/***/ }), + +/***/ 54844: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; +const http = __importStar(__nccwpck_require__(58611)); +const https = __importStar(__nccwpck_require__(65692)); +const pm = __importStar(__nccwpck_require__(54988)); +const tunnel = __importStar(__nccwpck_require__(20770)); +const undici_1 = __nccwpck_require__(46752); +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes || (exports.HttpCodes = HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers || (exports.Headers = Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes || (exports.MediaTypes = MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } +} +exports.HttpClientError = HttpClientError; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } + readBodyBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + const chunks = []; + this.message.on('data', (chunk) => { + chunks.push(chunk); + }); + this.message.on('end', () => { + resolve(Buffer.concat(chunks)); + }); + })); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + getAgentDispatcher(serverUrl) { + const parsedUrl = new URL(serverUrl); + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (!useProxy) { + return; + } + return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (!useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if tunneling agent isn't assigned create a new agent + if (!agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _getProxyAgentDispatcher(parsedUrl, proxyUrl) { + let proxyAgent; + if (this._keepAlive) { + proxyAgent = this._proxyAgentDispatcher; + } + // if agent is already assigned use that agent. + if (proxyAgent) { + return proxyAgent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + proxyAgent = new undici_1.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, ((proxyUrl.username || proxyUrl.password) && { + token: `Basic ${Buffer.from(`${proxyUrl.username}:${proxyUrl.password}`).toString('base64')}` + }))); + this._proxyAgentDispatcher = proxyAgent; + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + proxyAgent.options = Object.assign(proxyAgent.options.requestTls || {}, { + rejectUnauthorized: false + }); + } + return proxyAgent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +exports.HttpClient = HttpClient; +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 54988: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkBypass = exports.getProxyUrl = void 0; +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + try { + return new DecodedURL(proxyVar); + } + catch (_a) { + if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://')) + return new DecodedURL(`http://${proxyVar}`); + } + } + else { + return undefined; + } +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperNoProxyItem === '*' || + upperReqHosts.some(x => x === upperNoProxyItem || + x.endsWith(`.${upperNoProxyItem}`) || + (upperNoProxyItem.startsWith('.') && + x.endsWith(`${upperNoProxyItem}`)))) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; +function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return (hostLower === 'localhost' || + hostLower.startsWith('127.') || + hostLower.startsWith('[::1]') || + hostLower.startsWith('[0:0:0:0:0:0:0:1]')); +} +class DecodedURL extends URL { + constructor(url, base) { + super(url, base); + this._decodedUsername = decodeURIComponent(super.username); + this._decodedPassword = decodeURIComponent(super.password); + } + get username() { + return this._decodedUsername; + } + get password() { + return this._decodedPassword; + } +} +//# sourceMappingURL=proxy.js.map + +/***/ }), + +/***/ 75207: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getCmdPath = exports.tryGetExecutablePath = exports.isRooted = exports.isDirectory = exports.exists = exports.READONLY = exports.UV_FS_O_EXLOCK = exports.IS_WINDOWS = exports.unlink = exports.symlink = exports.stat = exports.rmdir = exports.rm = exports.rename = exports.readlink = exports.readdir = exports.open = exports.mkdir = exports.lstat = exports.copyFile = exports.chmod = void 0; +const fs = __importStar(__nccwpck_require__(79896)); +const path = __importStar(__nccwpck_require__(16928)); +_a = fs.promises +// export const {open} = 'fs' +, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.open = _a.open, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rm = _a.rm, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; +// export const {open} = 'fs' +exports.IS_WINDOWS = process.platform === 'win32'; +// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691 +exports.UV_FS_O_EXLOCK = 0x10000000; +exports.READONLY = fs.constants.O_RDONLY; +function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exports.stat(fsPath); + } + catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } + return true; + }); +} +exports.exists = exists; +function isDirectory(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); + return stats.isDirectory(); + }); +} +exports.isDirectory = isDirectory; +/** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (exports.IS_WINDOWS) { + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); +} +exports.isRooted = isRooted; +/** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ +function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { + // test file exists + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // on Windows, test for valid extension + const upperExt = path.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = undefined; + try { + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = path.dirname(filePath); + const upperName = path.basename(filePath).toUpperCase(); + for (const actualName of yield exports.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path.join(directory, actualName); + break; + } + } + } + catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ''; + }); +} +exports.tryGetExecutablePath = tryGetExecutablePath; +function normalizeSeparators(p) { + p = p || ''; + if (exports.IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); + } + // remove redundant slashes + return p.replace(/\/\/+/g, '/'); +} +// on Mac/Linux, test the execute bit +// R W X R W X R W X +// 256 128 64 32 16 8 4 2 1 +function isUnixExecutable(stats) { + return ((stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && stats.uid === process.getuid())); +} +// Get the path of cmd.exe in windows +function getCmdPath() { + var _a; + return (_a = process.env['COMSPEC']) !== null && _a !== void 0 ? _a : `cmd.exe`; +} +exports.getCmdPath = getCmdPath; +//# sourceMappingURL=io-util.js.map + +/***/ }), + +/***/ 94994: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.findInPath = exports.which = exports.mkdirP = exports.rmRF = exports.mv = exports.cp = void 0; +const assert_1 = __nccwpck_require__(42613); +const path = __importStar(__nccwpck_require__(16928)); +const ioUtil = __importStar(__nccwpck_require__(75207)); +/** + * Copies a file or folder. + * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js + * + * @param source source path + * @param dest destination path + * @param options optional. See CopyOptions. + */ +function cp(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + const { force, recursive, copySourceDirectory } = readCopyOptions(options); + const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; + // Dest is an existing file, but not forcing + if (destStat && destStat.isFile() && !force) { + return; + } + // If dest is an existing directory, should copy inside. + const newDest = destStat && destStat.isDirectory() && copySourceDirectory + ? path.join(dest, path.basename(source)) + : dest; + if (!(yield ioUtil.exists(source))) { + throw new Error(`no such file or directory: ${source}`); + } + const sourceStat = yield ioUtil.stat(source); + if (sourceStat.isDirectory()) { + if (!recursive) { + throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); + } + else { + yield cpDirRecursive(source, newDest, 0, force); + } + } + else { + if (path.relative(source, newDest) === '') { + // a file cannot be copied to itself + throw new Error(`'${newDest}' and '${source}' are the same file`); + } + yield copyFile(source, newDest, force); + } + }); +} +exports.cp = cp; +/** + * Moves a path. + * + * @param source source path + * @param dest destination path + * @param options optional. See MoveOptions. + */ +function mv(source, dest, options = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (yield ioUtil.exists(dest)) { + let destExists = true; + if (yield ioUtil.isDirectory(dest)) { + // If dest is directory copy src into dest + dest = path.join(dest, path.basename(source)); + destExists = yield ioUtil.exists(dest); + } + if (destExists) { + if (options.force == null || options.force) { + yield rmRF(dest); + } + else { + throw new Error('Destination already exists'); + } + } + } + yield mkdirP(path.dirname(dest)); + yield ioUtil.rename(source, dest); + }); +} +exports.mv = mv; +/** + * Remove a path recursively with force + * + * @param inputPath path to remove + */ +function rmRF(inputPath) { + return __awaiter(this, void 0, void 0, function* () { + if (ioUtil.IS_WINDOWS) { + // Check for invalid characters + // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file + if (/[*"<>|]/.test(inputPath)) { + throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'); + } + } + try { + // note if path does not exist, error is silent + yield ioUtil.rm(inputPath, { + force: true, + maxRetries: 3, + recursive: true, + retryDelay: 300 + }); + } + catch (err) { + throw new Error(`File was unable to be removed ${err}`); + } + }); +} +exports.rmRF = rmRF; +/** + * Make a directory. Creates the full path with folders in between + * Will throw if it fails + * + * @param fsPath path to create + * @returns Promise + */ +function mkdirP(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, 'a path argument must be provided'); + yield ioUtil.mkdir(fsPath, { recursive: true }); + }); +} +exports.mkdirP = mkdirP; +/** + * Returns path of a tool had the tool actually been invoked. Resolves via paths. + * If you check and the tool does not exist, it will throw. + * + * @param tool name of the tool + * @param check whether to check if tool exists + * @returns Promise path to tool + */ +function which(tool, check) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // recursive when check=true + if (check) { + const result = yield which(tool, false); + if (!result) { + if (ioUtil.IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } + else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ''; + }); +} +exports.which = which; +/** + * Returns a list of all occurrences of the given tool on the system path. + * + * @returns Promise the paths of the tool + */ +function findInPath(tool) { + return __awaiter(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + // build the list of extensions to try + const extensions = []; + if (ioUtil.IS_WINDOWS && process.env['PATHEXT']) { + for (const extension of process.env['PATHEXT'].split(path.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + // if it's rooted, return it if exists. otherwise return empty. + if (ioUtil.isRooted(tool)) { + const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + // if any path separators, return empty + if (tool.includes(path.sep)) { + return []; + } + // build the list of directories + // + // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, + // it feels like we should not do this. Checking the current directory seems like more of a use + // case of a shell, and the which() function exposed by the toolkit should strive for consistency + // across platforms. + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(path.delimiter)) { + if (p) { + directories.push(p); + } + } + } + // find all matches + const matches = []; + for (const directory of directories) { + const filePath = yield ioUtil.tryGetExecutablePath(path.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); +} +exports.findInPath = findInPath; +function readCopyOptions(options) { + const force = options.force == null ? true : options.force; + const recursive = Boolean(options.recursive); + const copySourceDirectory = options.copySourceDirectory == null + ? true + : Boolean(options.copySourceDirectory); + return { force, recursive, copySourceDirectory }; +} +function cpDirRecursive(sourceDir, destDir, currentDepth, force) { + return __awaiter(this, void 0, void 0, function* () { + // Ensure there is not a run away recursive copy + if (currentDepth >= 255) + return; + currentDepth++; + yield mkdirP(destDir); + const files = yield ioUtil.readdir(sourceDir); + for (const fileName of files) { + const srcFile = `${sourceDir}/${fileName}`; + const destFile = `${destDir}/${fileName}`; + const srcFileStat = yield ioUtil.lstat(srcFile); + if (srcFileStat.isDirectory()) { + // Recurse + yield cpDirRecursive(srcFile, destFile, currentDepth, force); + } + else { + yield copyFile(srcFile, destFile, force); + } + } + // Change the mode for the newly created directory + yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); + }); +} +// Buffered file copy +function copyFile(srcFile, destFile, force) { + return __awaiter(this, void 0, void 0, function* () { + if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { + // unlink/re-link it + try { + yield ioUtil.lstat(destFile); + yield ioUtil.unlink(destFile); + } + catch (e) { + // Try to override file permission + if (e.code === 'EPERM') { + yield ioUtil.chmod(destFile, '0666'); + yield ioUtil.unlink(destFile); + } + // other errors = it doesn't exist, no work to do + } + // Copy over symlink + const symlinkFull = yield ioUtil.readlink(srcFile); + yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); + } + else if (!(yield ioUtil.exists(destFile)) || force) { + yield ioUtil.copyFile(srcFile, destFile); + } + }); +} +//# sourceMappingURL=io.js.map + +/***/ }), + +/***/ 56863: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32 = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +var index_1 = __nccwpck_require__(62110); +var AwsCrc32 = /** @class */ (function () { + function AwsCrc32() { + this.crc32 = new index_1.Crc32(); + } + AwsCrc32.prototype.update = function (toHash) { + if ((0, util_1.isEmptyData)(toHash)) + return; + this.crc32.update((0, util_1.convertToBuffer)(toHash)); + }; + AwsCrc32.prototype.digest = function () { + return tslib_1.__awaiter(this, void 0, void 0, function () { + return tslib_1.__generator(this, function (_a) { + return [2 /*return*/, (0, util_1.numToUint8)(this.crc32.digest())]; + }); + }); + }; + AwsCrc32.prototype.reset = function () { + this.crc32 = new index_1.Crc32(); + }; + return AwsCrc32; +}()); +exports.AwsCrc32 = AwsCrc32; +//# sourceMappingURL=aws_crc32.js.map + +/***/ }), + +/***/ 62110: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32 = exports.Crc32 = exports.crc32 = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +function crc32(data) { + return new Crc32().update(data).digest(); +} +exports.crc32 = crc32; +var Crc32 = /** @class */ (function () { + function Crc32() { + this.checksum = 0xffffffff; + } + Crc32.prototype.update = function (data) { + var e_1, _a; + try { + for (var data_1 = tslib_1.__values(data), data_1_1 = data_1.next(); !data_1_1.done; data_1_1 = data_1.next()) { + var byte = data_1_1.value; + this.checksum = + (this.checksum >>> 8) ^ lookupTable[(this.checksum ^ byte) & 0xff]; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (data_1_1 && !data_1_1.done && (_a = data_1.return)) _a.call(data_1); + } + finally { if (e_1) throw e_1.error; } + } + return this; + }; + Crc32.prototype.digest = function () { + return (this.checksum ^ 0xffffffff) >>> 0; + }; + return Crc32; +}()); +exports.Crc32 = Crc32; +// prettier-ignore +var a_lookUpTable = [ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +]; +var lookupTable = (0, util_1.uint32ArrayFrom)(a_lookUpTable); +var aws_crc32_1 = __nccwpck_require__(56863); +Object.defineProperty(exports, "AwsCrc32", ({ enumerable: true, get: function () { return aws_crc32_1.AwsCrc32; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 95405: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32c = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +var index_1 = __nccwpck_require__(91491); +var AwsCrc32c = /** @class */ (function () { + function AwsCrc32c() { + this.crc32c = new index_1.Crc32c(); + } + AwsCrc32c.prototype.update = function (toHash) { + if ((0, util_1.isEmptyData)(toHash)) + return; + this.crc32c.update((0, util_1.convertToBuffer)(toHash)); + }; + AwsCrc32c.prototype.digest = function () { + return tslib_1.__awaiter(this, void 0, void 0, function () { + return tslib_1.__generator(this, function (_a) { + return [2 /*return*/, (0, util_1.numToUint8)(this.crc32c.digest())]; + }); + }); + }; + AwsCrc32c.prototype.reset = function () { + this.crc32c = new index_1.Crc32c(); + }; + return AwsCrc32c; +}()); +exports.AwsCrc32c = AwsCrc32c; +//# sourceMappingURL=aws_crc32c.js.map + +/***/ }), + +/***/ 91491: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsCrc32c = exports.Crc32c = exports.crc32c = void 0; +var tslib_1 = __nccwpck_require__(61860); +var util_1 = __nccwpck_require__(95667); +function crc32c(data) { + return new Crc32c().update(data).digest(); +} +exports.crc32c = crc32c; +var Crc32c = /** @class */ (function () { + function Crc32c() { + this.checksum = 0xffffffff; + } + Crc32c.prototype.update = function (data) { + var e_1, _a; + try { + for (var data_1 = tslib_1.__values(data), data_1_1 = data_1.next(); !data_1_1.done; data_1_1 = data_1.next()) { + var byte = data_1_1.value; + this.checksum = + (this.checksum >>> 8) ^ lookupTable[(this.checksum ^ byte) & 0xff]; + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (data_1_1 && !data_1_1.done && (_a = data_1.return)) _a.call(data_1); + } + finally { if (e_1) throw e_1.error; } + } + return this; + }; + Crc32c.prototype.digest = function () { + return (this.checksum ^ 0xffffffff) >>> 0; + }; + return Crc32c; +}()); +exports.Crc32c = Crc32c; +// prettier-ignore +var a_lookupTable = [ + 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, + 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, + 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, + 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, + 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, + 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, + 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, + 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, + 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, + 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, + 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, + 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, + 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, + 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, + 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, + 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, + 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, + 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, + 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, + 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, + 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, + 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, + 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, + 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, + 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, + 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, + 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, + 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, + 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, + 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, + 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, + 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351, +]; +var lookupTable = (0, util_1.uint32ArrayFrom)(a_lookupTable); +var aws_crc32c_1 = __nccwpck_require__(95405); +Object.defineProperty(exports, "AwsCrc32c", ({ enumerable: true, get: function () { return aws_crc32c_1.AwsCrc32c; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 45675: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.convertToBuffer = void 0; +var util_utf8_1 = __nccwpck_require__(47515); +// Quick polyfill +var fromUtf8 = typeof Buffer !== "undefined" && Buffer.from + ? function (input) { return Buffer.from(input, "utf8"); } + : util_utf8_1.fromUtf8; +function convertToBuffer(data) { + // Already a Uint8, do nothing + if (data instanceof Uint8Array) + return data; + if (typeof data === "string") { + return fromUtf8(data); + } + if (ArrayBuffer.isView(data)) { + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT); + } + return new Uint8Array(data); +} +exports.convertToBuffer = convertToBuffer; +//# sourceMappingURL=convertToBuffer.js.map + +/***/ }), + +/***/ 95667: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.uint32ArrayFrom = exports.numToUint8 = exports.isEmptyData = exports.convertToBuffer = void 0; +var convertToBuffer_1 = __nccwpck_require__(45675); +Object.defineProperty(exports, "convertToBuffer", ({ enumerable: true, get: function () { return convertToBuffer_1.convertToBuffer; } })); +var isEmptyData_1 = __nccwpck_require__(14658); +Object.defineProperty(exports, "isEmptyData", ({ enumerable: true, get: function () { return isEmptyData_1.isEmptyData; } })); +var numToUint8_1 = __nccwpck_require__(35436); +Object.defineProperty(exports, "numToUint8", ({ enumerable: true, get: function () { return numToUint8_1.numToUint8; } })); +var uint32ArrayFrom_1 = __nccwpck_require__(50673); +Object.defineProperty(exports, "uint32ArrayFrom", ({ enumerable: true, get: function () { return uint32ArrayFrom_1.uint32ArrayFrom; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 14658: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isEmptyData = void 0; +function isEmptyData(data) { + if (typeof data === "string") { + return data.length === 0; + } + return data.byteLength === 0; +} +exports.isEmptyData = isEmptyData; +//# sourceMappingURL=isEmptyData.js.map + +/***/ }), + +/***/ 35436: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.numToUint8 = void 0; +function numToUint8(num) { + return new Uint8Array([ + (num & 0xff000000) >> 24, + (num & 0x00ff0000) >> 16, + (num & 0x0000ff00) >> 8, + num & 0x000000ff, + ]); +} +exports.numToUint8 = numToUint8; +//# sourceMappingURL=numToUint8.js.map + +/***/ }), + +/***/ 50673: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.uint32ArrayFrom = void 0; +// IE 11 does not support Array.from, so we do it manually +function uint32ArrayFrom(a_lookUpTable) { + if (!Uint32Array.from) { + var return_array = new Uint32Array(a_lookUpTable.length); + var a_index = 0; + while (a_index < a_lookUpTable.length) { + return_array[a_index] = a_lookUpTable[a_index]; + a_index += 1; + } + return return_array; + } + return Uint32Array.from(a_lookUpTable); +} +exports.uint32ArrayFrom = uint32ArrayFrom; +//# sourceMappingURL=uint32ArrayFrom.js.map + +/***/ }), + +/***/ 78756: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + isArrayBuffer: () => isArrayBuffer +}); +module.exports = __toCommonJS(src_exports); +var isArrayBuffer = /* @__PURE__ */ __name((arg) => typeof ArrayBuffer === "function" && arg instanceof ArrayBuffer || Object.prototype.toString.call(arg) === "[object ArrayBuffer]", "isArrayBuffer"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 19077: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromArrayBuffer: () => fromArrayBuffer, + fromString: () => fromString +}); +module.exports = __toCommonJS(src_exports); +var import_is_array_buffer = __nccwpck_require__(78756); +var import_buffer = __nccwpck_require__(20181); +var fromArrayBuffer = /* @__PURE__ */ __name((input, offset = 0, length = input.byteLength - offset) => { + if (!(0, import_is_array_buffer.isArrayBuffer)(input)) { + throw new TypeError(`The "input" argument must be ArrayBuffer. Received type ${typeof input} (${input})`); + } + return import_buffer.Buffer.from(input, offset, length); +}, "fromArrayBuffer"); +var fromString = /* @__PURE__ */ __name((input, encoding) => { + if (typeof input !== "string") { + throw new TypeError(`The "input" argument must be of type string. Received type ${typeof input} (${input})`); + } + return encoding ? import_buffer.Buffer.from(input, encoding) : import_buffer.Buffer.from(input); +}, "fromString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 47515: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromUtf8: () => fromUtf8, + toUint8Array: () => toUint8Array, + toUtf8: () => toUtf8 +}); +module.exports = __toCommonJS(src_exports); + +// src/fromUtf8.ts +var import_util_buffer_from = __nccwpck_require__(19077); +var fromUtf8 = /* @__PURE__ */ __name((input) => { + const buf = (0, import_util_buffer_from.fromString)(input, "utf8"); + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength / Uint8Array.BYTES_PER_ELEMENT); +}, "fromUtf8"); + +// src/toUint8Array.ts +var toUint8Array = /* @__PURE__ */ __name((data) => { + if (typeof data === "string") { + return fromUtf8(data); + } + if (ArrayBuffer.isView(data)) { + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT); + } + return new Uint8Array(data); +}, "toUint8Array"); + +// src/toUtf8.ts + +var toUtf8 = /* @__PURE__ */ __name((input) => { + if (typeof input === "string") { + return input; + } + if (typeof input !== "object" || typeof input.byteOffset !== "number" || typeof input.byteLength !== "number") { + throw new Error("@smithy/util-utf8: toUtf8 encoder function only accepts string | Uint8Array."); + } + return (0, import_util_buffer_from.fromArrayBuffer)(input.buffer, input.byteOffset, input.byteLength).toString("utf8"); +}, "toUtf8"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 7168: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.defaultS3HttpAuthSchemeProvider = exports.defaultS3HttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const signature_v4_multi_region_1 = __nccwpck_require__(5785); +const middleware_endpoint_1 = __nccwpck_require__(40099); +const util_middleware_1 = __nccwpck_require__(76324); +const endpointResolver_1 = __nccwpck_require__(57526); +const createEndpointRuleSetHttpAuthSchemeParametersProvider = (defaultHttpAuthSchemeParametersProvider) => async (config, context, input) => { + if (!input) { + throw new Error(`Could not find \`input\` for \`defaultEndpointRuleSetHttpAuthSchemeParametersProvider\``); + } + const defaultParameters = await defaultHttpAuthSchemeParametersProvider(config, context, input); + const instructionsFn = (0, util_middleware_1.getSmithyContext)(context)?.commandInstance?.constructor + ?.getEndpointParameterInstructions; + if (!instructionsFn) { + throw new Error(`getEndpointParameterInstructions() is not defined on \`${context.commandName}\``); + } + const endpointParameters = await (0, middleware_endpoint_1.resolveParams)(input, { getEndpointParameterInstructions: instructionsFn }, config); + return Object.assign(defaultParameters, endpointParameters); +}; +const _defaultS3HttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultS3HttpAuthSchemeParametersProvider = createEndpointRuleSetHttpAuthSchemeParametersProvider(_defaultS3HttpAuthSchemeParametersProvider); +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "s3", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createAwsAuthSigv4aHttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4a", + signingProperties: { + name: "s3", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +const createEndpointRuleSetHttpAuthSchemeProvider = (defaultEndpointResolver, defaultHttpAuthSchemeResolver, createHttpAuthOptionFunctions) => { + const endpointRuleSetHttpAuthSchemeProvider = (authParameters) => { + const endpoint = defaultEndpointResolver(authParameters); + const authSchemes = endpoint.properties?.authSchemes; + if (!authSchemes) { + return defaultHttpAuthSchemeResolver(authParameters); + } + const options = []; + for (const scheme of authSchemes) { + const { name: resolvedName, properties = {}, ...rest } = scheme; + const name = resolvedName.toLowerCase(); + if (resolvedName !== name) { + console.warn(`HttpAuthScheme has been normalized with lowercasing: \`${resolvedName}\` to \`${name}\``); + } + let schemeId; + if (name === "sigv4a") { + schemeId = "aws.auth#sigv4a"; + const sigv4Present = authSchemes.find((s) => { + const name = s.name.toLowerCase(); + return name !== "sigv4a" && name.startsWith("sigv4"); + }); + if (signature_v4_multi_region_1.SignatureV4MultiRegion.sigv4aDependency() === "none" && sigv4Present) { + continue; + } + } + else if (name.startsWith("sigv4")) { + schemeId = "aws.auth#sigv4"; + } + else { + throw new Error(`Unknown HttpAuthScheme found in \`@smithy.rules#endpointRuleSet\`: \`${name}\``); + } + const createOption = createHttpAuthOptionFunctions[schemeId]; + if (!createOption) { + throw new Error(`Could not find HttpAuthOption create function for \`${schemeId}\``); + } + const option = createOption(authParameters); + option.schemeId = schemeId; + option.signingProperties = { ...(option.signingProperties || {}), ...rest, ...properties }; + options.push(option); + } + return options; + }; + return endpointRuleSetHttpAuthSchemeProvider; +}; +const _defaultS3HttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + options.push(createAwsAuthSigv4aHttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultS3HttpAuthSchemeProvider = createEndpointRuleSetHttpAuthSchemeProvider(endpointResolver_1.defaultEndpointResolver, _defaultS3HttpAuthSchemeProvider, { + "aws.auth#sigv4": createAwsAuthSigv4HttpAuthOption, + "aws.auth#sigv4a": createAwsAuthSigv4aHttpAuthOption, +}); +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config); + const config_1 = (0, core_1.resolveAwsSdkSigV4AConfig)(config_0); + return Object.assign(config_1, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 57526: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(62999); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: [ + "Accelerate", + "Bucket", + "DisableAccessPoints", + "DisableMultiRegionAccessPoints", + "DisableS3ExpressSessionAuth", + "Endpoint", + "ForcePathStyle", + "Region", + "UseArnRegion", + "UseDualStack", + "UseFIPS", + "UseGlobalEndpoint", + "UseObjectLambdaEndpoint", + "UseS3ExpressControlEndpoint", + ], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 62999: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const cp = "required", cq = "type", cr = "rules", cs = "conditions", ct = "fn", cu = "argv", cv = "ref", cw = "assign", cx = "url", cy = "properties", cz = "backend", cA = "authSchemes", cB = "disableDoubleEncoding", cC = "signingName", cD = "signingRegion", cE = "headers", cF = "signingRegionSet"; +const a = 6, b = false, c = true, d = "isSet", e = "booleanEquals", f = "error", g = "aws.partition", h = "stringEquals", i = "getAttr", j = "name", k = "substring", l = "bucketSuffix", m = "parseURL", n = "endpoint", o = "tree", p = "aws.isVirtualHostableS3Bucket", q = "{url#scheme}://{Bucket}.{url#authority}{url#path}", r = "not", s = "accessPointSuffix", t = "{url#scheme}://{url#authority}{url#path}", u = "hardwareType", v = "regionPrefix", w = "bucketAliasSuffix", x = "outpostId", y = "isValidHostLabel", z = "sigv4a", A = "s3-outposts", B = "s3", C = "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", D = "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", E = "https://{Bucket}.s3.{partitionResult#dnsSuffix}", F = "aws.parseArn", G = "bucketArn", H = "arnType", I = "", J = "s3-object-lambda", K = "accesspoint", L = "accessPointName", M = "{url#scheme}://{accessPointName}-{bucketArn#accountId}.{url#authority}{url#path}", N = "mrapPartition", O = "outpostType", P = "arnPrefix", Q = "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", R = "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", S = "https://s3.{partitionResult#dnsSuffix}", T = { [cp]: false, [cq]: "String" }, U = { [cp]: true, "default": false, [cq]: "Boolean" }, V = { [cp]: false, [cq]: "Boolean" }, W = { [ct]: e, [cu]: [{ [cv]: "Accelerate" }, true] }, X = { [ct]: e, [cu]: [{ [cv]: "UseFIPS" }, true] }, Y = { [ct]: e, [cu]: [{ [cv]: "UseDualStack" }, true] }, Z = { [ct]: d, [cu]: [{ [cv]: "Endpoint" }] }, aa = { [ct]: g, [cu]: [{ [cv]: "Region" }], [cw]: "partitionResult" }, ab = { [ct]: h, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "partitionResult" }, j] }, "aws-cn"] }, ac = { [ct]: d, [cu]: [{ [cv]: "Bucket" }] }, ad = { [cv]: "Bucket" }, ae = { [cs]: [Y], [f]: "S3Express does not support Dual-stack.", [cq]: f }, af = { [cs]: [W], [f]: "S3Express does not support S3 Accelerate.", [cq]: f }, ag = { [cs]: [Z, { [ct]: m, [cu]: [{ [cv]: "Endpoint" }], [cw]: "url" }], [cr]: [{ [cs]: [{ [ct]: d, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }] }, { [ct]: e, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }, true] }], [cr]: [{ [cs]: [{ [ct]: e, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "url" }, "isIp"] }, true] }], [cr]: [{ [cs]: [{ [ct]: "uriEncode", [cu]: [ad], [cw]: "uri_encoded_bucket" }], [cr]: [{ [n]: { [cx]: "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: p, [cu]: [ad, false] }], [cr]: [{ [n]: { [cx]: q, [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }, { [f]: "S3Express bucket name is not a valid virtual hostable name.", [cq]: f }], [cq]: o }, { [cs]: [{ [ct]: e, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "url" }, "isIp"] }, true] }], [cr]: [{ [cs]: [{ [ct]: "uriEncode", [cu]: [ad], [cw]: "uri_encoded_bucket" }], [cr]: [{ [n]: { [cx]: "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: p, [cu]: [ad, false] }], [cr]: [{ [n]: { [cx]: q, [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], [cq]: o }, { [f]: "S3Express bucket name is not a valid virtual hostable name.", [cq]: f }], [cq]: o }, ah = { [ct]: m, [cu]: [{ [cv]: "Endpoint" }], [cw]: "url" }, ai = { [ct]: e, [cu]: [{ [ct]: i, [cu]: [{ [cv]: "url" }, "isIp"] }, true] }, aj = { [cv]: "url" }, ak = { [ct]: "uriEncode", [cu]: [ad], [cw]: "uri_encoded_bucket" }, al = { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: "s3express", [cD]: "{Region}" }] }, am = {}, an = { [ct]: p, [cu]: [ad, false] }, ao = { [f]: "S3Express bucket name is not a valid virtual hostable name.", [cq]: f }, ap = { [ct]: d, [cu]: [{ [cv]: "UseS3ExpressControlEndpoint" }] }, aq = { [ct]: e, [cu]: [{ [cv]: "UseS3ExpressControlEndpoint" }, true] }, ar = { [ct]: r, [cu]: [Z] }, as = { [f]: "Unrecognized S3Express bucket name format.", [cq]: f }, at = { [ct]: r, [cu]: [ac] }, au = { [cv]: u }, av = { [cs]: [ar], [f]: "Expected a endpoint to be specified but no endpoint was found", [cq]: f }, aw = { [cA]: [{ [cB]: true, [j]: z, [cC]: A, [cF]: ["*"] }, { [cB]: true, [j]: "sigv4", [cC]: A, [cD]: "{Region}" }] }, ax = { [ct]: e, [cu]: [{ [cv]: "ForcePathStyle" }, false] }, ay = { [cv]: "ForcePathStyle" }, az = { [ct]: e, [cu]: [{ [cv]: "Accelerate" }, false] }, aA = { [ct]: h, [cu]: [{ [cv]: "Region" }, "aws-global"] }, aB = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "us-east-1" }] }, aC = { [ct]: r, [cu]: [aA] }, aD = { [ct]: e, [cu]: [{ [cv]: "UseGlobalEndpoint" }, true] }, aE = { [cx]: "https://{Bucket}.s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "{Region}" }] }, [cE]: {} }, aF = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "{Region}" }] }, aG = { [ct]: e, [cu]: [{ [cv]: "UseGlobalEndpoint" }, false] }, aH = { [ct]: e, [cu]: [{ [cv]: "UseDualStack" }, false] }, aI = { [cx]: "https://{Bucket}.s3-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aJ = { [ct]: e, [cu]: [{ [cv]: "UseFIPS" }, false] }, aK = { [cx]: "https://{Bucket}.s3-accelerate.dualstack.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aL = { [cx]: "https://{Bucket}.s3.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aM = { [ct]: e, [cu]: [{ [ct]: i, [cu]: [aj, "isIp"] }, false] }, aN = { [cx]: C, [cy]: aF, [cE]: {} }, aO = { [cx]: q, [cy]: aF, [cE]: {} }, aP = { [n]: aO, [cq]: n }, aQ = { [cx]: D, [cy]: aF, [cE]: {} }, aR = { [cx]: "https://{Bucket}.s3.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, aS = { [f]: "Invalid region: region was not a valid DNS name.", [cq]: f }, aT = { [cv]: G }, aU = { [cv]: H }, aV = { [ct]: i, [cu]: [aT, "service"] }, aW = { [cv]: L }, aX = { [cs]: [Y], [f]: "S3 Object Lambda does not support Dual-stack", [cq]: f }, aY = { [cs]: [W], [f]: "S3 Object Lambda does not support S3 Accelerate", [cq]: f }, aZ = { [cs]: [{ [ct]: d, [cu]: [{ [cv]: "DisableAccessPoints" }] }, { [ct]: e, [cu]: [{ [cv]: "DisableAccessPoints" }, true] }], [f]: "Access points are not supported for this operation", [cq]: f }, ba = { [cs]: [{ [ct]: d, [cu]: [{ [cv]: "UseArnRegion" }] }, { [ct]: e, [cu]: [{ [cv]: "UseArnRegion" }, false] }, { [ct]: r, [cu]: [{ [ct]: h, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }, "{Region}"] }] }], [f]: "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", [cq]: f }, bb = { [ct]: i, [cu]: [{ [cv]: "bucketPartition" }, j] }, bc = { [ct]: i, [cu]: [aT, "accountId"] }, bd = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: J, [cD]: "{bucketArn#region}" }] }, be = { [f]: "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName}`", [cq]: f }, bf = { [f]: "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", [cq]: f }, bg = { [f]: "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", [cq]: f }, bh = { [f]: "Client was configured for partition `{partitionResult#name}` but ARN (`{Bucket}`) has `{bucketPartition#name}`", [cq]: f }, bi = { [f]: "Invalid ARN: The ARN may only contain a single resource component after `accesspoint`.", [cq]: f }, bj = { [f]: "Invalid ARN: Expected a resource of the format `accesspoint:` but no name was provided", [cq]: f }, bk = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: B, [cD]: "{bucketArn#region}" }] }, bl = { [cA]: [{ [cB]: true, [j]: z, [cC]: A, [cF]: ["*"] }, { [cB]: true, [j]: "sigv4", [cC]: A, [cD]: "{bucketArn#region}" }] }, bm = { [ct]: F, [cu]: [ad] }, bn = { [cx]: "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bo = { [cx]: "https://s3-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bp = { [cx]: "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bq = { [cx]: Q, [cy]: aF, [cE]: {} }, br = { [cx]: "https://s3.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aF, [cE]: {} }, bs = { [cv]: "UseObjectLambdaEndpoint" }, bt = { [cA]: [{ [cB]: true, [j]: "sigv4", [cC]: J, [cD]: "{Region}" }] }, bu = { [cx]: "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bv = { [cx]: "https://s3-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bw = { [cx]: "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bx = { [cx]: t, [cy]: aF, [cE]: {} }, by = { [cx]: "https://s3.{Region}.{partitionResult#dnsSuffix}", [cy]: aF, [cE]: {} }, bz = [{ [cv]: "Region" }], bA = [{ [cv]: "Endpoint" }], bB = [ad], bC = [Y], bD = [W], bE = [Z, ah], bF = [{ [ct]: d, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }] }, { [ct]: e, [cu]: [{ [cv]: "DisableS3ExpressSessionAuth" }, true] }], bG = [ak], bH = [an], bI = [aa], bJ = [X], bK = [{ [ct]: k, [cu]: [ad, 6, 14, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 14, 16, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bL = [{ [cs]: [X], [n]: { [cx]: "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: {} }, [cq]: n }, { [n]: { [cx]: "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: {} }, [cq]: n }], bM = [{ [ct]: k, [cu]: [ad, 6, 15, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 15, 17, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bN = [{ [ct]: k, [cu]: [ad, 6, 19, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 19, 21, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bO = [{ [ct]: k, [cu]: [ad, 6, 20, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 20, 22, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bP = [{ [ct]: k, [cu]: [ad, 6, 26, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 26, 28, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bQ = [{ [cs]: [X], [n]: { [cx]: "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }, { [n]: { [cx]: "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", [cy]: { [cz]: "S3Express", [cA]: [{ [cB]: true, [j]: "sigv4-s3express", [cC]: "s3express", [cD]: "{Region}" }] }, [cE]: {} }, [cq]: n }], bR = [ad, 0, 7, true], bS = [{ [ct]: k, [cu]: [ad, 7, 15, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 15, 17, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bT = [{ [ct]: k, [cu]: [ad, 7, 16, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 16, 18, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bU = [{ [ct]: k, [cu]: [ad, 7, 20, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 20, 22, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bV = [{ [ct]: k, [cu]: [ad, 7, 21, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 21, 23, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bW = [{ [ct]: k, [cu]: [ad, 7, 27, true], [cw]: "s3expressAvailabilityZoneId" }, { [ct]: k, [cu]: [ad, 27, 29, true], [cw]: "s3expressAvailabilityZoneDelim" }, { [ct]: h, [cu]: [{ [cv]: "s3expressAvailabilityZoneDelim" }, "--"] }], bX = [ac], bY = [{ [ct]: y, [cu]: [{ [cv]: x }, false] }], bZ = [{ [ct]: h, [cu]: [{ [cv]: v }, "beta"] }], ca = ["*"], cb = [{ [ct]: y, [cu]: [{ [cv]: "Region" }, false] }], cc = [{ [ct]: h, [cu]: [{ [cv]: "Region" }, "us-east-1"] }], cd = [{ [ct]: h, [cu]: [aU, K] }], ce = [{ [ct]: i, [cu]: [aT, "resourceId[1]"], [cw]: L }, { [ct]: r, [cu]: [{ [ct]: h, [cu]: [aW, I] }] }], cf = [aT, "resourceId[1]"], cg = [{ [ct]: r, [cu]: [{ [ct]: h, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }, I] }] }], ch = [{ [ct]: r, [cu]: [{ [ct]: d, [cu]: [{ [ct]: i, [cu]: [aT, "resourceId[2]"] }] }] }], ci = [aT, "resourceId[2]"], cj = [{ [ct]: g, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }], [cw]: "bucketPartition" }], ck = [{ [ct]: h, [cu]: [bb, { [ct]: i, [cu]: [{ [cv]: "partitionResult" }, j] }] }], cl = [{ [ct]: y, [cu]: [{ [ct]: i, [cu]: [aT, "region"] }, true] }], cm = [{ [ct]: y, [cu]: [bc, false] }], cn = [{ [ct]: y, [cu]: [aW, false] }], co = [{ [ct]: y, [cu]: [{ [cv]: "Region" }, true] }]; +const _data = { version: "1.0", parameters: { Bucket: T, Region: T, UseFIPS: U, UseDualStack: U, Endpoint: T, ForcePathStyle: U, Accelerate: U, UseGlobalEndpoint: U, UseObjectLambdaEndpoint: V, Key: T, Prefix: T, CopySource: T, DisableAccessPoints: V, DisableMultiRegionAccessPoints: U, UseArnRegion: V, UseS3ExpressControlEndpoint: V, DisableS3ExpressSessionAuth: V }, [cr]: [{ [cs]: [{ [ct]: d, [cu]: bz }], [cr]: [{ [cs]: [W, X], error: "Accelerate cannot be used with FIPS", [cq]: f }, { [cs]: [Y, Z], error: "Cannot set dual-stack in combination with a custom endpoint.", [cq]: f }, { [cs]: [Z, X], error: "A custom endpoint cannot be combined with FIPS", [cq]: f }, { [cs]: [Z, W], error: "A custom endpoint cannot be combined with S3 Accelerate", [cq]: f }, { [cs]: [X, aa, ab], error: "Partition does not support FIPS", [cq]: f }, { [cs]: [ac, { [ct]: k, [cu]: [ad, 0, a, c], [cw]: l }, { [ct]: h, [cu]: [{ [cv]: l }, "--x-s3"] }], [cr]: [ae, af, ag, { [cs]: [ap, aq], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: [ak, ar], [cr]: [{ [cs]: bJ, endpoint: { [cx]: "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: al, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://s3express-control.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: al, [cE]: am }, [cq]: n }], [cq]: o }], [cq]: o }], [cq]: o }, { [cs]: bH, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: bF, [cr]: [{ [cs]: bK, [cr]: bL, [cq]: o }, { [cs]: bM, [cr]: bL, [cq]: o }, { [cs]: bN, [cr]: bL, [cq]: o }, { [cs]: bO, [cr]: bL, [cq]: o }, { [cs]: bP, [cr]: bL, [cq]: o }, as], [cq]: o }, { [cs]: bK, [cr]: bQ, [cq]: o }, { [cs]: bM, [cr]: bQ, [cq]: o }, { [cs]: bN, [cr]: bQ, [cq]: o }, { [cs]: bO, [cr]: bQ, [cq]: o }, { [cs]: bP, [cr]: bQ, [cq]: o }, as], [cq]: o }], [cq]: o }, ao], [cq]: o }, { [cs]: [ac, { [ct]: k, [cu]: bR, [cw]: s }, { [ct]: h, [cu]: [{ [cv]: s }, "--xa-s3"] }], [cr]: [ae, af, ag, { [cs]: bH, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: bF, [cr]: [{ [cs]: bS, [cr]: bL, [cq]: o }, { [cs]: bT, [cr]: bL, [cq]: o }, { [cs]: bU, [cr]: bL, [cq]: o }, { [cs]: bV, [cr]: bL, [cq]: o }, { [cs]: bW, [cr]: bL, [cq]: o }, as], [cq]: o }, { [cs]: bS, [cr]: bQ, [cq]: o }, { [cs]: bT, [cr]: bQ, [cq]: o }, { [cs]: bU, [cr]: bQ, [cq]: o }, { [cs]: bV, [cr]: bQ, [cq]: o }, { [cs]: bW, [cr]: bQ, [cq]: o }, as], [cq]: o }], [cq]: o }, ao], [cq]: o }, { [cs]: [at, ap, aq], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: bE, endpoint: { [cx]: t, [cy]: al, [cE]: am }, [cq]: n }, { [cs]: bJ, endpoint: { [cx]: "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", [cy]: al, [cE]: am }, [cq]: n }], [cq]: o }], [cq]: o }, { [cs]: [ac, { [ct]: k, [cu]: [ad, 49, 50, c], [cw]: u }, { [ct]: k, [cu]: [ad, 8, 12, c], [cw]: v }, { [ct]: k, [cu]: bR, [cw]: w }, { [ct]: k, [cu]: [ad, 32, 49, c], [cw]: x }, { [ct]: g, [cu]: bz, [cw]: "regionPartition" }, { [ct]: h, [cu]: [{ [cv]: w }, "--op-s3"] }], [cr]: [{ [cs]: bY, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [au, "e"] }], [cr]: [{ [cs]: bZ, [cr]: [av, { [cs]: bE, endpoint: { [cx]: "https://{Bucket}.ec2.{url#authority}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { endpoint: { [cx]: "https://{Bucket}.ec2.s3-outposts.{Region}.{regionPartition#dnsSuffix}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { [cs]: [{ [ct]: h, [cu]: [au, "o"] }], [cr]: [{ [cs]: bZ, [cr]: [av, { [cs]: bE, endpoint: { [cx]: "https://{Bucket}.op-{outpostId}.{url#authority}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { endpoint: { [cx]: "https://{Bucket}.op-{outpostId}.s3-outposts.{Region}.{regionPartition#dnsSuffix}", [cy]: aw, [cE]: am }, [cq]: n }], [cq]: o }, { error: "Unrecognized hardware type: \"Expected hardware type o or e but got {hardwareType}\"", [cq]: f }], [cq]: o }, { error: "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`.", [cq]: f }], [cq]: o }, { [cs]: bX, [cr]: [{ [cs]: [Z, { [ct]: r, [cu]: [{ [ct]: d, [cu]: [{ [ct]: m, [cu]: bA }] }] }], error: "Custom endpoint `{Endpoint}` was not a valid URI", [cq]: f }, { [cs]: [ax, an], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: cb, [cr]: [{ [cs]: [W, ab], error: "S3 Accelerate cannot be used in this region", [cq]: f }, { [cs]: [Y, X, az, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, X, az, ar, aC, aD], [cr]: [{ endpoint: aE, [cq]: n }], [cq]: o }, { [cs]: [Y, X, az, ar, aC, aG], endpoint: aE, [cq]: n }, { [cs]: [aH, X, az, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3-fips.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, X, az, ar, aC, aD], [cr]: [{ endpoint: aI, [cq]: n }], [cq]: o }, { [cs]: [aH, X, az, ar, aC, aG], endpoint: aI, [cq]: n }, { [cs]: [Y, aJ, W, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3-accelerate.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, aJ, W, ar, aC, aD], [cr]: [{ endpoint: aK, [cq]: n }], [cq]: o }, { [cs]: [Y, aJ, W, ar, aC, aG], endpoint: aK, [cq]: n }, { [cs]: [Y, aJ, az, ar, aA], endpoint: { [cx]: "https://{Bucket}.s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, aJ, az, ar, aC, aD], [cr]: [{ endpoint: aL, [cq]: n }], [cq]: o }, { [cs]: [Y, aJ, az, ar, aC, aG], endpoint: aL, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, ai, aA], endpoint: { [cx]: C, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, aM, aA], endpoint: { [cx]: q, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, ai, aC, aD], [cr]: [{ [cs]: cc, endpoint: aN, [cq]: n }, { endpoint: aN, [cq]: n }], [cq]: o }, { [cs]: [aH, aJ, az, Z, ah, aM, aC, aD], [cr]: [{ [cs]: cc, endpoint: aO, [cq]: n }, aP], [cq]: o }, { [cs]: [aH, aJ, az, Z, ah, ai, aC, aG], endpoint: aN, [cq]: n }, { [cs]: [aH, aJ, az, Z, ah, aM, aC, aG], endpoint: aO, [cq]: n }, { [cs]: [aH, aJ, W, ar, aA], endpoint: { [cx]: D, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, W, ar, aC, aD], [cr]: [{ [cs]: cc, endpoint: aQ, [cq]: n }, { endpoint: aQ, [cq]: n }], [cq]: o }, { [cs]: [aH, aJ, W, ar, aC, aG], endpoint: aQ, [cq]: n }, { [cs]: [aH, aJ, az, ar, aA], endpoint: { [cx]: E, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, aJ, az, ar, aC, aD], [cr]: [{ [cs]: cc, endpoint: { [cx]: E, [cy]: aF, [cE]: am }, [cq]: n }, { endpoint: aR, [cq]: n }], [cq]: o }, { [cs]: [aH, aJ, az, ar, aC, aG], endpoint: aR, [cq]: n }], [cq]: o }, aS], [cq]: o }], [cq]: o }, { [cs]: [Z, ah, { [ct]: h, [cu]: [{ [ct]: i, [cu]: [aj, "scheme"] }, "http"] }, { [ct]: p, [cu]: [ad, c] }, ax, aJ, aH, az], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: cb, [cr]: [aP], [cq]: o }, aS], [cq]: o }], [cq]: o }, { [cs]: [ax, { [ct]: F, [cu]: bB, [cw]: G }], [cr]: [{ [cs]: [{ [ct]: i, [cu]: [aT, "resourceId[0]"], [cw]: H }, { [ct]: r, [cu]: [{ [ct]: h, [cu]: [aU, I] }] }], [cr]: [{ [cs]: [{ [ct]: h, [cu]: [aV, J] }], [cr]: [{ [cs]: cd, [cr]: [{ [cs]: ce, [cr]: [aX, aY, { [cs]: cg, [cr]: [aZ, { [cs]: ch, [cr]: [ba, { [cs]: cj, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: ck, [cr]: [{ [cs]: cl, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [bc, I] }], error: "Invalid ARN: Missing account id", [cq]: f }, { [cs]: cm, [cr]: [{ [cs]: cn, [cr]: [{ [cs]: bE, endpoint: { [cx]: M, [cy]: bd, [cE]: am }, [cq]: n }, { [cs]: bJ, endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-object-lambda-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bd, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-object-lambda.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bd, [cE]: am }, [cq]: n }], [cq]: o }, be], [cq]: o }, bf], [cq]: o }, bg], [cq]: o }, bh], [cq]: o }], [cq]: o }], [cq]: o }, bi], [cq]: o }, { error: "Invalid ARN: bucket ARN is missing a region", [cq]: f }], [cq]: o }, bj], [cq]: o }, { error: "Invalid ARN: Object Lambda ARNs only support `accesspoint` arn types, but found: `{arnType}`", [cq]: f }], [cq]: o }, { [cs]: cd, [cr]: [{ [cs]: ce, [cr]: [{ [cs]: cg, [cr]: [{ [cs]: cd, [cr]: [{ [cs]: cg, [cr]: [aZ, { [cs]: ch, [cr]: [ba, { [cs]: cj, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [bb, "{partitionResult#name}"] }], [cr]: [{ [cs]: cl, [cr]: [{ [cs]: [{ [ct]: h, [cu]: [aV, B] }], [cr]: [{ [cs]: cm, [cr]: [{ [cs]: cn, [cr]: [{ [cs]: bD, error: "Access Points do not support S3 Accelerate", [cq]: f }, { [cs]: [X, Y], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint-fips.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [X, aH], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [aJ, Y], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH, Z, ah], endpoint: { [cx]: M, [cy]: bk, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH], endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bk, [cE]: am }, [cq]: n }], [cq]: o }, be], [cq]: o }, bf], [cq]: o }, { error: "Invalid ARN: The ARN was not for the S3 service, found: {bucketArn#service}", [cq]: f }], [cq]: o }, bg], [cq]: o }, bh], [cq]: o }], [cq]: o }], [cq]: o }, bi], [cq]: o }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: y, [cu]: [aW, c] }], [cr]: [{ [cs]: bC, error: "S3 MRAP does not support dual-stack", [cq]: f }, { [cs]: bJ, error: "S3 MRAP does not support FIPS", [cq]: f }, { [cs]: bD, error: "S3 MRAP does not support S3 Accelerate", [cq]: f }, { [cs]: [{ [ct]: e, [cu]: [{ [cv]: "DisableMultiRegionAccessPoints" }, c] }], error: "Invalid configuration: Multi-Region Access Point ARNs are disabled.", [cq]: f }, { [cs]: [{ [ct]: g, [cu]: bz, [cw]: N }], [cr]: [{ [cs]: [{ [ct]: h, [cu]: [{ [ct]: i, [cu]: [{ [cv]: N }, j] }, { [ct]: i, [cu]: [aT, "partition"] }] }], [cr]: [{ endpoint: { [cx]: "https://{accessPointName}.accesspoint.s3-global.{mrapPartition#dnsSuffix}", [cy]: { [cA]: [{ [cB]: c, name: z, [cC]: B, [cF]: ca }] }, [cE]: am }, [cq]: n }], [cq]: o }, { error: "Client was configured for partition `{mrapPartition#name}` but bucket referred to partition `{bucketArn#partition}`", [cq]: f }], [cq]: o }], [cq]: o }, { error: "Invalid Access Point Name", [cq]: f }], [cq]: o }, bj], [cq]: o }, { [cs]: [{ [ct]: h, [cu]: [aV, A] }], [cr]: [{ [cs]: bC, error: "S3 Outposts does not support Dual-stack", [cq]: f }, { [cs]: bJ, error: "S3 Outposts does not support FIPS", [cq]: f }, { [cs]: bD, error: "S3 Outposts does not support S3 Accelerate", [cq]: f }, { [cs]: [{ [ct]: d, [cu]: [{ [ct]: i, [cu]: [aT, "resourceId[4]"] }] }], error: "Invalid Arn: Outpost Access Point ARN contains sub resources", [cq]: f }, { [cs]: [{ [ct]: i, [cu]: cf, [cw]: x }], [cr]: [{ [cs]: bY, [cr]: [ba, { [cs]: cj, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: ck, [cr]: [{ [cs]: cl, [cr]: [{ [cs]: cm, [cr]: [{ [cs]: [{ [ct]: i, [cu]: ci, [cw]: O }], [cr]: [{ [cs]: [{ [ct]: i, [cu]: [aT, "resourceId[3]"], [cw]: L }], [cr]: [{ [cs]: [{ [ct]: h, [cu]: [{ [cv]: O }, K] }], [cr]: [{ [cs]: bE, endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.{outpostId}.{url#authority}", [cy]: bl, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://{accessPointName}-{bucketArn#accountId}.{outpostId}.s3-outposts.{bucketArn#region}.{bucketPartition#dnsSuffix}", [cy]: bl, [cE]: am }, [cq]: n }], [cq]: o }, { error: "Expected an outpost type `accesspoint`, found {outpostType}", [cq]: f }], [cq]: o }, { error: "Invalid ARN: expected an access point name", [cq]: f }], [cq]: o }, { error: "Invalid ARN: Expected a 4-component resource", [cq]: f }], [cq]: o }, bf], [cq]: o }, bg], [cq]: o }, bh], [cq]: o }], [cq]: o }], [cq]: o }, { error: "Invalid ARN: The outpost Id may only contain a-z, A-Z, 0-9 and `-`. Found: `{outpostId}`", [cq]: f }], [cq]: o }, { error: "Invalid ARN: The Outpost Id was not set", [cq]: f }], [cq]: o }, { error: "Invalid ARN: Unrecognized format: {Bucket} (type: {arnType})", [cq]: f }], [cq]: o }, { error: "Invalid ARN: No ARN type specified", [cq]: f }], [cq]: o }, { [cs]: [{ [ct]: k, [cu]: [ad, 0, 4, b], [cw]: P }, { [ct]: h, [cu]: [{ [cv]: P }, "arn:"] }, { [ct]: r, [cu]: [{ [ct]: d, [cu]: [bm] }] }], error: "Invalid ARN: `{Bucket}` was not a valid ARN", [cq]: f }, { [cs]: [{ [ct]: e, [cu]: [ay, c] }, bm], error: "Path-style addressing cannot be used with ARN buckets", [cq]: f }, { [cs]: bG, [cr]: [{ [cs]: bI, [cr]: [{ [cs]: [az], [cr]: [{ [cs]: [Y, ar, X, aA], endpoint: { [cx]: "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, ar, X, aC, aD], [cr]: [{ endpoint: bn, [cq]: n }], [cq]: o }, { [cs]: [Y, ar, X, aC, aG], endpoint: bn, [cq]: n }, { [cs]: [aH, ar, X, aA], endpoint: { [cx]: "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, ar, X, aC, aD], [cr]: [{ endpoint: bo, [cq]: n }], [cq]: o }, { [cs]: [aH, ar, X, aC, aG], endpoint: bo, [cq]: n }, { [cs]: [Y, ar, aJ, aA], endpoint: { [cx]: "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [Y, ar, aJ, aC, aD], [cr]: [{ endpoint: bp, [cq]: n }], [cq]: o }, { [cs]: [Y, ar, aJ, aC, aG], endpoint: bp, [cq]: n }, { [cs]: [aH, Z, ah, aJ, aA], endpoint: { [cx]: Q, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, Z, ah, aJ, aC, aD], [cr]: [{ [cs]: cc, endpoint: bq, [cq]: n }, { endpoint: bq, [cq]: n }], [cq]: o }, { [cs]: [aH, Z, ah, aJ, aC, aG], endpoint: bq, [cq]: n }, { [cs]: [aH, ar, aJ, aA], endpoint: { [cx]: R, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aH, ar, aJ, aC, aD], [cr]: [{ [cs]: cc, endpoint: { [cx]: R, [cy]: aF, [cE]: am }, [cq]: n }, { endpoint: br, [cq]: n }], [cq]: o }, { [cs]: [aH, ar, aJ, aC, aG], endpoint: br, [cq]: n }], [cq]: o }, { error: "Path-style addressing cannot be used with S3 Accelerate", [cq]: f }], [cq]: o }], [cq]: o }], [cq]: o }, { [cs]: [{ [ct]: d, [cu]: [bs] }, { [ct]: e, [cu]: [bs, c] }], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: co, [cr]: [aX, aY, { [cs]: bE, endpoint: { [cx]: t, [cy]: bt, [cE]: am }, [cq]: n }, { [cs]: bJ, endpoint: { [cx]: "https://s3-object-lambda-fips.{Region}.{partitionResult#dnsSuffix}", [cy]: bt, [cE]: am }, [cq]: n }, { endpoint: { [cx]: "https://s3-object-lambda.{Region}.{partitionResult#dnsSuffix}", [cy]: bt, [cE]: am }, [cq]: n }], [cq]: o }, aS], [cq]: o }], [cq]: o }, { [cs]: [at], [cr]: [{ [cs]: bI, [cr]: [{ [cs]: co, [cr]: [{ [cs]: [X, Y, ar, aA], endpoint: { [cx]: "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [X, Y, ar, aC, aD], [cr]: [{ endpoint: bu, [cq]: n }], [cq]: o }, { [cs]: [X, Y, ar, aC, aG], endpoint: bu, [cq]: n }, { [cs]: [X, aH, ar, aA], endpoint: { [cx]: "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [X, aH, ar, aC, aD], [cr]: [{ endpoint: bv, [cq]: n }], [cq]: o }, { [cs]: [X, aH, ar, aC, aG], endpoint: bv, [cq]: n }, { [cs]: [aJ, Y, ar, aA], endpoint: { [cx]: "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aJ, Y, ar, aC, aD], [cr]: [{ endpoint: bw, [cq]: n }], [cq]: o }, { [cs]: [aJ, Y, ar, aC, aG], endpoint: bw, [cq]: n }, { [cs]: [aJ, aH, Z, ah, aA], endpoint: { [cx]: t, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH, Z, ah, aC, aD], [cr]: [{ [cs]: cc, endpoint: bx, [cq]: n }, { endpoint: bx, [cq]: n }], [cq]: o }, { [cs]: [aJ, aH, Z, ah, aC, aG], endpoint: bx, [cq]: n }, { [cs]: [aJ, aH, ar, aA], endpoint: { [cx]: S, [cy]: aB, [cE]: am }, [cq]: n }, { [cs]: [aJ, aH, ar, aC, aD], [cr]: [{ [cs]: cc, endpoint: { [cx]: S, [cy]: aF, [cE]: am }, [cq]: n }, { endpoint: by, [cq]: n }], [cq]: o }, { [cs]: [aJ, aH, ar, aC, aG], endpoint: by, [cq]: n }], [cq]: o }, aS], [cq]: o }], [cq]: o }], [cq]: o }, { error: "A region must be set when sending requests to S3.", [cq]: f }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 53711: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + AbortMultipartUploadCommand: () => AbortMultipartUploadCommand, + AnalyticsFilter: () => AnalyticsFilter, + AnalyticsS3ExportFileFormat: () => AnalyticsS3ExportFileFormat, + ArchiveStatus: () => ArchiveStatus, + BucketAccelerateStatus: () => BucketAccelerateStatus, + BucketAlreadyExists: () => BucketAlreadyExists, + BucketAlreadyOwnedByYou: () => BucketAlreadyOwnedByYou, + BucketCannedACL: () => BucketCannedACL, + BucketLocationConstraint: () => BucketLocationConstraint, + BucketLogsPermission: () => BucketLogsPermission, + BucketType: () => BucketType, + BucketVersioningStatus: () => BucketVersioningStatus, + ChecksumAlgorithm: () => ChecksumAlgorithm, + ChecksumMode: () => ChecksumMode, + ChecksumType: () => ChecksumType, + CompleteMultipartUploadCommand: () => CompleteMultipartUploadCommand, + CompleteMultipartUploadOutputFilterSensitiveLog: () => CompleteMultipartUploadOutputFilterSensitiveLog, + CompleteMultipartUploadRequestFilterSensitiveLog: () => CompleteMultipartUploadRequestFilterSensitiveLog, + CompressionType: () => CompressionType, + CopyObjectCommand: () => CopyObjectCommand, + CopyObjectOutputFilterSensitiveLog: () => CopyObjectOutputFilterSensitiveLog, + CopyObjectRequestFilterSensitiveLog: () => CopyObjectRequestFilterSensitiveLog, + CreateBucketCommand: () => CreateBucketCommand, + CreateBucketMetadataConfigurationCommand: () => CreateBucketMetadataConfigurationCommand, + CreateBucketMetadataTableConfigurationCommand: () => CreateBucketMetadataTableConfigurationCommand, + CreateMultipartUploadCommand: () => CreateMultipartUploadCommand, + CreateMultipartUploadOutputFilterSensitiveLog: () => CreateMultipartUploadOutputFilterSensitiveLog, + CreateMultipartUploadRequestFilterSensitiveLog: () => CreateMultipartUploadRequestFilterSensitiveLog, + CreateSessionCommand: () => CreateSessionCommand, + CreateSessionOutputFilterSensitiveLog: () => CreateSessionOutputFilterSensitiveLog, + CreateSessionRequestFilterSensitiveLog: () => CreateSessionRequestFilterSensitiveLog, + DataRedundancy: () => DataRedundancy, + DeleteBucketAnalyticsConfigurationCommand: () => DeleteBucketAnalyticsConfigurationCommand, + DeleteBucketCommand: () => DeleteBucketCommand, + DeleteBucketCorsCommand: () => DeleteBucketCorsCommand, + DeleteBucketEncryptionCommand: () => DeleteBucketEncryptionCommand, + DeleteBucketIntelligentTieringConfigurationCommand: () => DeleteBucketIntelligentTieringConfigurationCommand, + DeleteBucketInventoryConfigurationCommand: () => DeleteBucketInventoryConfigurationCommand, + DeleteBucketLifecycleCommand: () => DeleteBucketLifecycleCommand, + DeleteBucketMetadataConfigurationCommand: () => DeleteBucketMetadataConfigurationCommand, + DeleteBucketMetadataTableConfigurationCommand: () => DeleteBucketMetadataTableConfigurationCommand, + DeleteBucketMetricsConfigurationCommand: () => DeleteBucketMetricsConfigurationCommand, + DeleteBucketOwnershipControlsCommand: () => DeleteBucketOwnershipControlsCommand, + DeleteBucketPolicyCommand: () => DeleteBucketPolicyCommand, + DeleteBucketReplicationCommand: () => DeleteBucketReplicationCommand, + DeleteBucketTaggingCommand: () => DeleteBucketTaggingCommand, + DeleteBucketWebsiteCommand: () => DeleteBucketWebsiteCommand, + DeleteMarkerReplicationStatus: () => DeleteMarkerReplicationStatus, + DeleteObjectCommand: () => DeleteObjectCommand, + DeleteObjectTaggingCommand: () => DeleteObjectTaggingCommand, + DeleteObjectsCommand: () => DeleteObjectsCommand, + DeletePublicAccessBlockCommand: () => DeletePublicAccessBlockCommand, + EncodingType: () => EncodingType, + EncryptionFilterSensitiveLog: () => EncryptionFilterSensitiveLog, + EncryptionTypeMismatch: () => EncryptionTypeMismatch, + Event: () => Event, + ExistingObjectReplicationStatus: () => ExistingObjectReplicationStatus, + ExpirationState: () => ExpirationState, + ExpirationStatus: () => ExpirationStatus, + ExpressionType: () => ExpressionType, + FileHeaderInfo: () => FileHeaderInfo, + FilterRuleName: () => FilterRuleName, + GetBucketAccelerateConfigurationCommand: () => GetBucketAccelerateConfigurationCommand, + GetBucketAclCommand: () => GetBucketAclCommand, + GetBucketAnalyticsConfigurationCommand: () => GetBucketAnalyticsConfigurationCommand, + GetBucketCorsCommand: () => GetBucketCorsCommand, + GetBucketEncryptionCommand: () => GetBucketEncryptionCommand, + GetBucketEncryptionOutputFilterSensitiveLog: () => GetBucketEncryptionOutputFilterSensitiveLog, + GetBucketIntelligentTieringConfigurationCommand: () => GetBucketIntelligentTieringConfigurationCommand, + GetBucketInventoryConfigurationCommand: () => GetBucketInventoryConfigurationCommand, + GetBucketInventoryConfigurationOutputFilterSensitiveLog: () => GetBucketInventoryConfigurationOutputFilterSensitiveLog, + GetBucketLifecycleConfigurationCommand: () => GetBucketLifecycleConfigurationCommand, + GetBucketLocationCommand: () => GetBucketLocationCommand, + GetBucketLoggingCommand: () => GetBucketLoggingCommand, + GetBucketMetadataConfigurationCommand: () => GetBucketMetadataConfigurationCommand, + GetBucketMetadataTableConfigurationCommand: () => GetBucketMetadataTableConfigurationCommand, + GetBucketMetricsConfigurationCommand: () => GetBucketMetricsConfigurationCommand, + GetBucketNotificationConfigurationCommand: () => GetBucketNotificationConfigurationCommand, + GetBucketOwnershipControlsCommand: () => GetBucketOwnershipControlsCommand, + GetBucketPolicyCommand: () => GetBucketPolicyCommand, + GetBucketPolicyStatusCommand: () => GetBucketPolicyStatusCommand, + GetBucketReplicationCommand: () => GetBucketReplicationCommand, + GetBucketRequestPaymentCommand: () => GetBucketRequestPaymentCommand, + GetBucketTaggingCommand: () => GetBucketTaggingCommand, + GetBucketVersioningCommand: () => GetBucketVersioningCommand, + GetBucketWebsiteCommand: () => GetBucketWebsiteCommand, + GetObjectAclCommand: () => GetObjectAclCommand, + GetObjectAttributesCommand: () => GetObjectAttributesCommand, + GetObjectAttributesRequestFilterSensitiveLog: () => GetObjectAttributesRequestFilterSensitiveLog, + GetObjectCommand: () => GetObjectCommand, + GetObjectLegalHoldCommand: () => GetObjectLegalHoldCommand, + GetObjectLockConfigurationCommand: () => GetObjectLockConfigurationCommand, + GetObjectOutputFilterSensitiveLog: () => GetObjectOutputFilterSensitiveLog, + GetObjectRequestFilterSensitiveLog: () => GetObjectRequestFilterSensitiveLog, + GetObjectRetentionCommand: () => GetObjectRetentionCommand, + GetObjectTaggingCommand: () => GetObjectTaggingCommand, + GetObjectTorrentCommand: () => GetObjectTorrentCommand, + GetObjectTorrentOutputFilterSensitiveLog: () => GetObjectTorrentOutputFilterSensitiveLog, + GetPublicAccessBlockCommand: () => GetPublicAccessBlockCommand, + HeadBucketCommand: () => HeadBucketCommand, + HeadObjectCommand: () => HeadObjectCommand, + HeadObjectOutputFilterSensitiveLog: () => HeadObjectOutputFilterSensitiveLog, + HeadObjectRequestFilterSensitiveLog: () => HeadObjectRequestFilterSensitiveLog, + IdempotencyParameterMismatch: () => IdempotencyParameterMismatch, + IntelligentTieringAccessTier: () => IntelligentTieringAccessTier, + IntelligentTieringStatus: () => IntelligentTieringStatus, + InvalidObjectState: () => InvalidObjectState, + InvalidRequest: () => InvalidRequest, + InvalidWriteOffset: () => InvalidWriteOffset, + InventoryConfigurationFilterSensitiveLog: () => InventoryConfigurationFilterSensitiveLog, + InventoryConfigurationState: () => InventoryConfigurationState, + InventoryDestinationFilterSensitiveLog: () => InventoryDestinationFilterSensitiveLog, + InventoryEncryptionFilterSensitiveLog: () => InventoryEncryptionFilterSensitiveLog, + InventoryFormat: () => InventoryFormat, + InventoryFrequency: () => InventoryFrequency, + InventoryIncludedObjectVersions: () => InventoryIncludedObjectVersions, + InventoryOptionalField: () => InventoryOptionalField, + InventoryS3BucketDestinationFilterSensitiveLog: () => InventoryS3BucketDestinationFilterSensitiveLog, + JSONType: () => JSONType, + ListBucketAnalyticsConfigurationsCommand: () => ListBucketAnalyticsConfigurationsCommand, + ListBucketIntelligentTieringConfigurationsCommand: () => ListBucketIntelligentTieringConfigurationsCommand, + ListBucketInventoryConfigurationsCommand: () => ListBucketInventoryConfigurationsCommand, + ListBucketInventoryConfigurationsOutputFilterSensitiveLog: () => ListBucketInventoryConfigurationsOutputFilterSensitiveLog, + ListBucketMetricsConfigurationsCommand: () => ListBucketMetricsConfigurationsCommand, + ListBucketsCommand: () => ListBucketsCommand, + ListDirectoryBucketsCommand: () => ListDirectoryBucketsCommand, + ListMultipartUploadsCommand: () => ListMultipartUploadsCommand, + ListObjectVersionsCommand: () => ListObjectVersionsCommand, + ListObjectsCommand: () => ListObjectsCommand, + ListObjectsV2Command: () => ListObjectsV2Command, + ListPartsCommand: () => ListPartsCommand, + ListPartsRequestFilterSensitiveLog: () => ListPartsRequestFilterSensitiveLog, + LocationType: () => LocationType, + MFADelete: () => MFADelete, + MFADeleteStatus: () => MFADeleteStatus, + MetadataDirective: () => MetadataDirective, + MetricsFilter: () => MetricsFilter, + MetricsStatus: () => MetricsStatus, + NoSuchBucket: () => NoSuchBucket, + NoSuchKey: () => NoSuchKey, + NoSuchUpload: () => NoSuchUpload, + NotFound: () => NotFound, + ObjectAlreadyInActiveTierError: () => ObjectAlreadyInActiveTierError, + ObjectAttributes: () => ObjectAttributes, + ObjectCannedACL: () => ObjectCannedACL, + ObjectLockEnabled: () => ObjectLockEnabled, + ObjectLockLegalHoldStatus: () => ObjectLockLegalHoldStatus, + ObjectLockMode: () => ObjectLockMode, + ObjectLockRetentionMode: () => ObjectLockRetentionMode, + ObjectNotInActiveTierError: () => ObjectNotInActiveTierError, + ObjectOwnership: () => ObjectOwnership, + ObjectStorageClass: () => ObjectStorageClass, + ObjectVersionStorageClass: () => ObjectVersionStorageClass, + OptionalObjectAttributes: () => OptionalObjectAttributes, + OutputLocationFilterSensitiveLog: () => OutputLocationFilterSensitiveLog, + OwnerOverride: () => OwnerOverride, + PartitionDateSource: () => PartitionDateSource, + Payer: () => Payer, + Permission: () => Permission, + Protocol: () => Protocol, + PutBucketAccelerateConfigurationCommand: () => PutBucketAccelerateConfigurationCommand, + PutBucketAclCommand: () => PutBucketAclCommand, + PutBucketAnalyticsConfigurationCommand: () => PutBucketAnalyticsConfigurationCommand, + PutBucketCorsCommand: () => PutBucketCorsCommand, + PutBucketEncryptionCommand: () => PutBucketEncryptionCommand, + PutBucketEncryptionRequestFilterSensitiveLog: () => PutBucketEncryptionRequestFilterSensitiveLog, + PutBucketIntelligentTieringConfigurationCommand: () => PutBucketIntelligentTieringConfigurationCommand, + PutBucketInventoryConfigurationCommand: () => PutBucketInventoryConfigurationCommand, + PutBucketInventoryConfigurationRequestFilterSensitiveLog: () => PutBucketInventoryConfigurationRequestFilterSensitiveLog, + PutBucketLifecycleConfigurationCommand: () => PutBucketLifecycleConfigurationCommand, + PutBucketLoggingCommand: () => PutBucketLoggingCommand, + PutBucketMetricsConfigurationCommand: () => PutBucketMetricsConfigurationCommand, + PutBucketNotificationConfigurationCommand: () => PutBucketNotificationConfigurationCommand, + PutBucketOwnershipControlsCommand: () => PutBucketOwnershipControlsCommand, + PutBucketPolicyCommand: () => PutBucketPolicyCommand, + PutBucketReplicationCommand: () => PutBucketReplicationCommand, + PutBucketRequestPaymentCommand: () => PutBucketRequestPaymentCommand, + PutBucketTaggingCommand: () => PutBucketTaggingCommand, + PutBucketVersioningCommand: () => PutBucketVersioningCommand, + PutBucketWebsiteCommand: () => PutBucketWebsiteCommand, + PutObjectAclCommand: () => PutObjectAclCommand, + PutObjectCommand: () => PutObjectCommand, + PutObjectLegalHoldCommand: () => PutObjectLegalHoldCommand, + PutObjectLockConfigurationCommand: () => PutObjectLockConfigurationCommand, + PutObjectOutputFilterSensitiveLog: () => PutObjectOutputFilterSensitiveLog, + PutObjectRequestFilterSensitiveLog: () => PutObjectRequestFilterSensitiveLog, + PutObjectRetentionCommand: () => PutObjectRetentionCommand, + PutObjectTaggingCommand: () => PutObjectTaggingCommand, + PutPublicAccessBlockCommand: () => PutPublicAccessBlockCommand, + QuoteFields: () => QuoteFields, + RenameObjectCommand: () => RenameObjectCommand, + ReplicaModificationsStatus: () => ReplicaModificationsStatus, + ReplicationRuleStatus: () => ReplicationRuleStatus, + ReplicationStatus: () => ReplicationStatus, + ReplicationTimeStatus: () => ReplicationTimeStatus, + RequestCharged: () => RequestCharged, + RequestPayer: () => RequestPayer, + RestoreObjectCommand: () => RestoreObjectCommand, + RestoreObjectRequestFilterSensitiveLog: () => RestoreObjectRequestFilterSensitiveLog, + RestoreRequestFilterSensitiveLog: () => RestoreRequestFilterSensitiveLog, + RestoreRequestType: () => RestoreRequestType, + S3: () => S3, + S3Client: () => S3Client, + S3LocationFilterSensitiveLog: () => S3LocationFilterSensitiveLog, + S3ServiceException: () => S3ServiceException, + S3TablesBucketType: () => S3TablesBucketType, + SSEKMSFilterSensitiveLog: () => SSEKMSFilterSensitiveLog, + SelectObjectContentCommand: () => SelectObjectContentCommand, + SelectObjectContentEventStream: () => SelectObjectContentEventStream, + SelectObjectContentEventStreamFilterSensitiveLog: () => SelectObjectContentEventStreamFilterSensitiveLog, + SelectObjectContentOutputFilterSensitiveLog: () => SelectObjectContentOutputFilterSensitiveLog, + SelectObjectContentRequestFilterSensitiveLog: () => SelectObjectContentRequestFilterSensitiveLog, + ServerSideEncryption: () => ServerSideEncryption, + ServerSideEncryptionByDefaultFilterSensitiveLog: () => ServerSideEncryptionByDefaultFilterSensitiveLog, + ServerSideEncryptionConfigurationFilterSensitiveLog: () => ServerSideEncryptionConfigurationFilterSensitiveLog, + ServerSideEncryptionRuleFilterSensitiveLog: () => ServerSideEncryptionRuleFilterSensitiveLog, + SessionCredentialsFilterSensitiveLog: () => SessionCredentialsFilterSensitiveLog, + SessionMode: () => SessionMode, + SseKmsEncryptedObjectsStatus: () => SseKmsEncryptedObjectsStatus, + StorageClass: () => StorageClass, + StorageClassAnalysisSchemaVersion: () => StorageClassAnalysisSchemaVersion, + TableSseAlgorithm: () => TableSseAlgorithm, + TaggingDirective: () => TaggingDirective, + Tier: () => Tier, + TooManyParts: () => TooManyParts, + TransitionDefaultMinimumObjectSize: () => TransitionDefaultMinimumObjectSize, + TransitionStorageClass: () => TransitionStorageClass, + Type: () => Type, + UpdateBucketMetadataInventoryTableConfigurationCommand: () => UpdateBucketMetadataInventoryTableConfigurationCommand, + UpdateBucketMetadataJournalTableConfigurationCommand: () => UpdateBucketMetadataJournalTableConfigurationCommand, + UploadPartCommand: () => UploadPartCommand, + UploadPartCopyCommand: () => UploadPartCopyCommand, + UploadPartCopyOutputFilterSensitiveLog: () => UploadPartCopyOutputFilterSensitiveLog, + UploadPartCopyRequestFilterSensitiveLog: () => UploadPartCopyRequestFilterSensitiveLog, + UploadPartOutputFilterSensitiveLog: () => UploadPartOutputFilterSensitiveLog, + UploadPartRequestFilterSensitiveLog: () => UploadPartRequestFilterSensitiveLog, + WriteGetObjectResponseCommand: () => WriteGetObjectResponseCommand, + WriteGetObjectResponseRequestFilterSensitiveLog: () => WriteGetObjectResponseRequestFilterSensitiveLog, + __Client: () => import_smithy_client.Client, + paginateListBuckets: () => paginateListBuckets, + paginateListDirectoryBuckets: () => paginateListDirectoryBuckets, + paginateListObjectsV2: () => paginateListObjectsV2, + paginateListParts: () => paginateListParts, + waitForBucketExists: () => waitForBucketExists, + waitForBucketNotExists: () => waitForBucketNotExists, + waitForObjectExists: () => waitForObjectExists, + waitForObjectNotExists: () => waitForObjectNotExists, + waitUntilBucketExists: () => waitUntilBucketExists, + waitUntilBucketNotExists: () => waitUntilBucketNotExists, + waitUntilObjectExists: () => waitUntilObjectExists, + waitUntilObjectNotExists: () => waitUntilObjectNotExists +}); +module.exports = __toCommonJS(index_exports); + +// src/S3Client.ts +var import_middleware_expect_continue = __nccwpck_require__(84745); +var import_middleware_flexible_checksums = __nccwpck_require__(29836); +var import_middleware_host_header = __nccwpck_require__(52590); +var import_middleware_logger = __nccwpck_require__(85242); +var import_middleware_recursion_detection = __nccwpck_require__(81568); +var import_middleware_sdk_s32 = __nccwpck_require__(77445); +var import_middleware_user_agent = __nccwpck_require__(32959); +var import_config_resolver = __nccwpck_require__(39316); +var import_core3 = __nccwpck_require__(90402); +var import_eventstream_serde_config_resolver = __nccwpck_require__(86895); +var import_middleware_content_length = __nccwpck_require__(47212); + +var import_middleware_retry = __nccwpck_require__(19618); + +var import_httpAuthSchemeProvider = __nccwpck_require__(7168); + +// src/commands/CreateSessionCommand.ts +var import_middleware_sdk_s3 = __nccwpck_require__(77445); +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_serde = __nccwpck_require__(83255); + + +// src/endpoint/EndpointParameters.ts +var resolveClientEndpointParameters = /* @__PURE__ */ __name((options) => { + return Object.assign(options, { + useFipsEndpoint: options.useFipsEndpoint ?? false, + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + forcePathStyle: options.forcePathStyle ?? false, + useAccelerateEndpoint: options.useAccelerateEndpoint ?? false, + useGlobalEndpoint: options.useGlobalEndpoint ?? false, + disableMultiregionAccessPoints: options.disableMultiregionAccessPoints ?? false, + defaultSigningName: "s3" + }); +}, "resolveClientEndpointParameters"); +var commonParams = { + ForcePathStyle: { type: "clientContextParams", name: "forcePathStyle" }, + UseArnRegion: { type: "clientContextParams", name: "useArnRegion" }, + DisableMultiRegionAccessPoints: { type: "clientContextParams", name: "disableMultiregionAccessPoints" }, + Accelerate: { type: "clientContextParams", name: "useAccelerateEndpoint" }, + DisableS3ExpressSessionAuth: { type: "clientContextParams", name: "disableS3ExpressSessionAuth" }, + UseGlobalEndpoint: { type: "builtInParams", name: "useGlobalEndpoint" }, + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" } +}; + +// src/models/models_0.ts + + +// src/models/S3ServiceException.ts +var import_smithy_client = __nccwpck_require__(61411); +var S3ServiceException = class _S3ServiceException extends import_smithy_client.ServiceException { + static { + __name(this, "S3ServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _S3ServiceException.prototype); + } +}; + +// src/models/models_0.ts +var RequestCharged = { + requester: "requester" +}; +var RequestPayer = { + requester: "requester" +}; +var NoSuchUpload = class _NoSuchUpload extends S3ServiceException { + static { + __name(this, "NoSuchUpload"); + } + name = "NoSuchUpload"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NoSuchUpload", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NoSuchUpload.prototype); + } +}; +var BucketAccelerateStatus = { + Enabled: "Enabled", + Suspended: "Suspended" +}; +var Type = { + AmazonCustomerByEmail: "AmazonCustomerByEmail", + CanonicalUser: "CanonicalUser", + Group: "Group" +}; +var Permission = { + FULL_CONTROL: "FULL_CONTROL", + READ: "READ", + READ_ACP: "READ_ACP", + WRITE: "WRITE", + WRITE_ACP: "WRITE_ACP" +}; +var OwnerOverride = { + Destination: "Destination" +}; +var ChecksumType = { + COMPOSITE: "COMPOSITE", + FULL_OBJECT: "FULL_OBJECT" +}; +var ServerSideEncryption = { + AES256: "AES256", + aws_fsx: "aws:fsx", + aws_kms: "aws:kms", + aws_kms_dsse: "aws:kms:dsse" +}; +var ObjectCannedACL = { + authenticated_read: "authenticated-read", + aws_exec_read: "aws-exec-read", + bucket_owner_full_control: "bucket-owner-full-control", + bucket_owner_read: "bucket-owner-read", + private: "private", + public_read: "public-read", + public_read_write: "public-read-write" +}; +var ChecksumAlgorithm = { + CRC32: "CRC32", + CRC32C: "CRC32C", + CRC64NVME: "CRC64NVME", + SHA1: "SHA1", + SHA256: "SHA256" +}; +var MetadataDirective = { + COPY: "COPY", + REPLACE: "REPLACE" +}; +var ObjectLockLegalHoldStatus = { + OFF: "OFF", + ON: "ON" +}; +var ObjectLockMode = { + COMPLIANCE: "COMPLIANCE", + GOVERNANCE: "GOVERNANCE" +}; +var StorageClass = { + DEEP_ARCHIVE: "DEEP_ARCHIVE", + EXPRESS_ONEZONE: "EXPRESS_ONEZONE", + FSX_OPENZFS: "FSX_OPENZFS", + GLACIER: "GLACIER", + GLACIER_IR: "GLACIER_IR", + INTELLIGENT_TIERING: "INTELLIGENT_TIERING", + ONEZONE_IA: "ONEZONE_IA", + OUTPOSTS: "OUTPOSTS", + REDUCED_REDUNDANCY: "REDUCED_REDUNDANCY", + SNOW: "SNOW", + STANDARD: "STANDARD", + STANDARD_IA: "STANDARD_IA" +}; +var TaggingDirective = { + COPY: "COPY", + REPLACE: "REPLACE" +}; +var ObjectNotInActiveTierError = class _ObjectNotInActiveTierError extends S3ServiceException { + static { + __name(this, "ObjectNotInActiveTierError"); + } + name = "ObjectNotInActiveTierError"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ObjectNotInActiveTierError", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ObjectNotInActiveTierError.prototype); + } +}; +var BucketAlreadyExists = class _BucketAlreadyExists extends S3ServiceException { + static { + __name(this, "BucketAlreadyExists"); + } + name = "BucketAlreadyExists"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "BucketAlreadyExists", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _BucketAlreadyExists.prototype); + } +}; +var BucketAlreadyOwnedByYou = class _BucketAlreadyOwnedByYou extends S3ServiceException { + static { + __name(this, "BucketAlreadyOwnedByYou"); + } + name = "BucketAlreadyOwnedByYou"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "BucketAlreadyOwnedByYou", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _BucketAlreadyOwnedByYou.prototype); + } +}; +var BucketCannedACL = { + authenticated_read: "authenticated-read", + private: "private", + public_read: "public-read", + public_read_write: "public-read-write" +}; +var DataRedundancy = { + SingleAvailabilityZone: "SingleAvailabilityZone", + SingleLocalZone: "SingleLocalZone" +}; +var BucketType = { + Directory: "Directory" +}; +var LocationType = { + AvailabilityZone: "AvailabilityZone", + LocalZone: "LocalZone" +}; +var BucketLocationConstraint = { + EU: "EU", + af_south_1: "af-south-1", + ap_east_1: "ap-east-1", + ap_northeast_1: "ap-northeast-1", + ap_northeast_2: "ap-northeast-2", + ap_northeast_3: "ap-northeast-3", + ap_south_1: "ap-south-1", + ap_south_2: "ap-south-2", + ap_southeast_1: "ap-southeast-1", + ap_southeast_2: "ap-southeast-2", + ap_southeast_3: "ap-southeast-3", + ap_southeast_4: "ap-southeast-4", + ap_southeast_5: "ap-southeast-5", + ca_central_1: "ca-central-1", + cn_north_1: "cn-north-1", + cn_northwest_1: "cn-northwest-1", + eu_central_1: "eu-central-1", + eu_central_2: "eu-central-2", + eu_north_1: "eu-north-1", + eu_south_1: "eu-south-1", + eu_south_2: "eu-south-2", + eu_west_1: "eu-west-1", + eu_west_2: "eu-west-2", + eu_west_3: "eu-west-3", + il_central_1: "il-central-1", + me_central_1: "me-central-1", + me_south_1: "me-south-1", + sa_east_1: "sa-east-1", + us_east_2: "us-east-2", + us_gov_east_1: "us-gov-east-1", + us_gov_west_1: "us-gov-west-1", + us_west_1: "us-west-1", + us_west_2: "us-west-2" +}; +var ObjectOwnership = { + BucketOwnerEnforced: "BucketOwnerEnforced", + BucketOwnerPreferred: "BucketOwnerPreferred", + ObjectWriter: "ObjectWriter" +}; +var InventoryConfigurationState = { + DISABLED: "DISABLED", + ENABLED: "ENABLED" +}; +var TableSseAlgorithm = { + AES256: "AES256", + aws_kms: "aws:kms" +}; +var ExpirationState = { + DISABLED: "DISABLED", + ENABLED: "ENABLED" +}; +var SessionMode = { + ReadOnly: "ReadOnly", + ReadWrite: "ReadWrite" +}; +var NoSuchBucket = class _NoSuchBucket extends S3ServiceException { + static { + __name(this, "NoSuchBucket"); + } + name = "NoSuchBucket"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NoSuchBucket", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NoSuchBucket.prototype); + } +}; +var AnalyticsFilter; +((AnalyticsFilter2) => { + AnalyticsFilter2.visit = /* @__PURE__ */ __name((value, visitor) => { + if (value.Prefix !== void 0) return visitor.Prefix(value.Prefix); + if (value.Tag !== void 0) return visitor.Tag(value.Tag); + if (value.And !== void 0) return visitor.And(value.And); + return visitor._(value.$unknown[0], value.$unknown[1]); + }, "visit"); +})(AnalyticsFilter || (AnalyticsFilter = {})); +var AnalyticsS3ExportFileFormat = { + CSV: "CSV" +}; +var StorageClassAnalysisSchemaVersion = { + V_1: "V_1" +}; +var IntelligentTieringStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var IntelligentTieringAccessTier = { + ARCHIVE_ACCESS: "ARCHIVE_ACCESS", + DEEP_ARCHIVE_ACCESS: "DEEP_ARCHIVE_ACCESS" +}; +var InventoryFormat = { + CSV: "CSV", + ORC: "ORC", + Parquet: "Parquet" +}; +var InventoryIncludedObjectVersions = { + All: "All", + Current: "Current" +}; +var InventoryOptionalField = { + BucketKeyStatus: "BucketKeyStatus", + ChecksumAlgorithm: "ChecksumAlgorithm", + ETag: "ETag", + EncryptionStatus: "EncryptionStatus", + IntelligentTieringAccessTier: "IntelligentTieringAccessTier", + IsMultipartUploaded: "IsMultipartUploaded", + LastModifiedDate: "LastModifiedDate", + ObjectAccessControlList: "ObjectAccessControlList", + ObjectLockLegalHoldStatus: "ObjectLockLegalHoldStatus", + ObjectLockMode: "ObjectLockMode", + ObjectLockRetainUntilDate: "ObjectLockRetainUntilDate", + ObjectOwner: "ObjectOwner", + ReplicationStatus: "ReplicationStatus", + Size: "Size", + StorageClass: "StorageClass" +}; +var InventoryFrequency = { + Daily: "Daily", + Weekly: "Weekly" +}; +var TransitionStorageClass = { + DEEP_ARCHIVE: "DEEP_ARCHIVE", + GLACIER: "GLACIER", + GLACIER_IR: "GLACIER_IR", + INTELLIGENT_TIERING: "INTELLIGENT_TIERING", + ONEZONE_IA: "ONEZONE_IA", + STANDARD_IA: "STANDARD_IA" +}; +var ExpirationStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var TransitionDefaultMinimumObjectSize = { + all_storage_classes_128K: "all_storage_classes_128K", + varies_by_storage_class: "varies_by_storage_class" +}; +var BucketLogsPermission = { + FULL_CONTROL: "FULL_CONTROL", + READ: "READ", + WRITE: "WRITE" +}; +var PartitionDateSource = { + DeliveryTime: "DeliveryTime", + EventTime: "EventTime" +}; +var S3TablesBucketType = { + aws: "aws", + customer: "customer" +}; +var MetricsFilter; +((MetricsFilter2) => { + MetricsFilter2.visit = /* @__PURE__ */ __name((value, visitor) => { + if (value.Prefix !== void 0) return visitor.Prefix(value.Prefix); + if (value.Tag !== void 0) return visitor.Tag(value.Tag); + if (value.AccessPointArn !== void 0) return visitor.AccessPointArn(value.AccessPointArn); + if (value.And !== void 0) return visitor.And(value.And); + return visitor._(value.$unknown[0], value.$unknown[1]); + }, "visit"); +})(MetricsFilter || (MetricsFilter = {})); +var Event = { + s3_IntelligentTiering: "s3:IntelligentTiering", + s3_LifecycleExpiration_: "s3:LifecycleExpiration:*", + s3_LifecycleExpiration_Delete: "s3:LifecycleExpiration:Delete", + s3_LifecycleExpiration_DeleteMarkerCreated: "s3:LifecycleExpiration:DeleteMarkerCreated", + s3_LifecycleTransition: "s3:LifecycleTransition", + s3_ObjectAcl_Put: "s3:ObjectAcl:Put", + s3_ObjectCreated_: "s3:ObjectCreated:*", + s3_ObjectCreated_CompleteMultipartUpload: "s3:ObjectCreated:CompleteMultipartUpload", + s3_ObjectCreated_Copy: "s3:ObjectCreated:Copy", + s3_ObjectCreated_Post: "s3:ObjectCreated:Post", + s3_ObjectCreated_Put: "s3:ObjectCreated:Put", + s3_ObjectRemoved_: "s3:ObjectRemoved:*", + s3_ObjectRemoved_Delete: "s3:ObjectRemoved:Delete", + s3_ObjectRemoved_DeleteMarkerCreated: "s3:ObjectRemoved:DeleteMarkerCreated", + s3_ObjectRestore_: "s3:ObjectRestore:*", + s3_ObjectRestore_Completed: "s3:ObjectRestore:Completed", + s3_ObjectRestore_Delete: "s3:ObjectRestore:Delete", + s3_ObjectRestore_Post: "s3:ObjectRestore:Post", + s3_ObjectTagging_: "s3:ObjectTagging:*", + s3_ObjectTagging_Delete: "s3:ObjectTagging:Delete", + s3_ObjectTagging_Put: "s3:ObjectTagging:Put", + s3_ReducedRedundancyLostObject: "s3:ReducedRedundancyLostObject", + s3_Replication_: "s3:Replication:*", + s3_Replication_OperationFailedReplication: "s3:Replication:OperationFailedReplication", + s3_Replication_OperationMissedThreshold: "s3:Replication:OperationMissedThreshold", + s3_Replication_OperationNotTracked: "s3:Replication:OperationNotTracked", + s3_Replication_OperationReplicatedAfterThreshold: "s3:Replication:OperationReplicatedAfterThreshold" +}; +var FilterRuleName = { + prefix: "prefix", + suffix: "suffix" +}; +var DeleteMarkerReplicationStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var MetricsStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ReplicationTimeStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ExistingObjectReplicationStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ReplicaModificationsStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var SseKmsEncryptedObjectsStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var ReplicationRuleStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var Payer = { + BucketOwner: "BucketOwner", + Requester: "Requester" +}; +var MFADeleteStatus = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var BucketVersioningStatus = { + Enabled: "Enabled", + Suspended: "Suspended" +}; +var Protocol = { + http: "http", + https: "https" +}; +var ReplicationStatus = { + COMPLETE: "COMPLETE", + COMPLETED: "COMPLETED", + FAILED: "FAILED", + PENDING: "PENDING", + REPLICA: "REPLICA" +}; +var ChecksumMode = { + ENABLED: "ENABLED" +}; +var InvalidObjectState = class _InvalidObjectState extends S3ServiceException { + static { + __name(this, "InvalidObjectState"); + } + name = "InvalidObjectState"; + $fault = "client"; + StorageClass; + AccessTier; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidObjectState", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidObjectState.prototype); + this.StorageClass = opts.StorageClass; + this.AccessTier = opts.AccessTier; + } +}; +var NoSuchKey = class _NoSuchKey extends S3ServiceException { + static { + __name(this, "NoSuchKey"); + } + name = "NoSuchKey"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NoSuchKey", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NoSuchKey.prototype); + } +}; +var ObjectAttributes = { + CHECKSUM: "Checksum", + ETAG: "ETag", + OBJECT_PARTS: "ObjectParts", + OBJECT_SIZE: "ObjectSize", + STORAGE_CLASS: "StorageClass" +}; +var ObjectLockEnabled = { + Enabled: "Enabled" +}; +var ObjectLockRetentionMode = { + COMPLIANCE: "COMPLIANCE", + GOVERNANCE: "GOVERNANCE" +}; +var NotFound = class _NotFound extends S3ServiceException { + static { + __name(this, "NotFound"); + } + name = "NotFound"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "NotFound", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _NotFound.prototype); + } +}; +var ArchiveStatus = { + ARCHIVE_ACCESS: "ARCHIVE_ACCESS", + DEEP_ARCHIVE_ACCESS: "DEEP_ARCHIVE_ACCESS" +}; +var EncodingType = { + url: "url" +}; +var CompleteMultipartUploadOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "CompleteMultipartUploadOutputFilterSensitiveLog"); +var CompleteMultipartUploadRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "CompleteMultipartUploadRequestFilterSensitiveLog"); +var CopyObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CopyObjectOutputFilterSensitiveLog"); +var CopyObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING }, + ...obj.CopySourceSSECustomerKey && { CopySourceSSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "CopyObjectRequestFilterSensitiveLog"); +var CreateMultipartUploadOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CreateMultipartUploadOutputFilterSensitiveLog"); +var CreateMultipartUploadRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CreateMultipartUploadRequestFilterSensitiveLog"); +var SessionCredentialsFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SecretAccessKey && { SecretAccessKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SessionToken && { SessionToken: import_smithy_client.SENSITIVE_STRING } +}), "SessionCredentialsFilterSensitiveLog"); +var CreateSessionOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING }, + ...obj.Credentials && { Credentials: SessionCredentialsFilterSensitiveLog(obj.Credentials) } +}), "CreateSessionOutputFilterSensitiveLog"); +var CreateSessionRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "CreateSessionRequestFilterSensitiveLog"); +var ServerSideEncryptionByDefaultFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.KMSMasterKeyID && { KMSMasterKeyID: import_smithy_client.SENSITIVE_STRING } +}), "ServerSideEncryptionByDefaultFilterSensitiveLog"); +var ServerSideEncryptionRuleFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.ApplyServerSideEncryptionByDefault && { + ApplyServerSideEncryptionByDefault: ServerSideEncryptionByDefaultFilterSensitiveLog( + obj.ApplyServerSideEncryptionByDefault + ) + } +}), "ServerSideEncryptionRuleFilterSensitiveLog"); +var ServerSideEncryptionConfigurationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Rules && { Rules: obj.Rules.map((item) => ServerSideEncryptionRuleFilterSensitiveLog(item)) } +}), "ServerSideEncryptionConfigurationFilterSensitiveLog"); +var GetBucketEncryptionOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.ServerSideEncryptionConfiguration && { + ServerSideEncryptionConfiguration: ServerSideEncryptionConfigurationFilterSensitiveLog( + obj.ServerSideEncryptionConfiguration + ) + } +}), "GetBucketEncryptionOutputFilterSensitiveLog"); +var SSEKMSFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.KeyId && { KeyId: import_smithy_client.SENSITIVE_STRING } +}), "SSEKMSFilterSensitiveLog"); +var InventoryEncryptionFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMS && { SSEKMS: SSEKMSFilterSensitiveLog(obj.SSEKMS) } +}), "InventoryEncryptionFilterSensitiveLog"); +var InventoryS3BucketDestinationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Encryption && { Encryption: InventoryEncryptionFilterSensitiveLog(obj.Encryption) } +}), "InventoryS3BucketDestinationFilterSensitiveLog"); +var InventoryDestinationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.S3BucketDestination && { + S3BucketDestination: InventoryS3BucketDestinationFilterSensitiveLog(obj.S3BucketDestination) + } +}), "InventoryDestinationFilterSensitiveLog"); +var InventoryConfigurationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Destination && { Destination: InventoryDestinationFilterSensitiveLog(obj.Destination) } +}), "InventoryConfigurationFilterSensitiveLog"); +var GetBucketInventoryConfigurationOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.InventoryConfiguration && { + InventoryConfiguration: InventoryConfigurationFilterSensitiveLog(obj.InventoryConfiguration) + } +}), "GetBucketInventoryConfigurationOutputFilterSensitiveLog"); +var GetObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "GetObjectOutputFilterSensitiveLog"); +var GetObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "GetObjectRequestFilterSensitiveLog"); +var GetObjectAttributesRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "GetObjectAttributesRequestFilterSensitiveLog"); +var GetObjectTorrentOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj +}), "GetObjectTorrentOutputFilterSensitiveLog"); +var HeadObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "HeadObjectOutputFilterSensitiveLog"); +var HeadObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "HeadObjectRequestFilterSensitiveLog"); +var ListBucketInventoryConfigurationsOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.InventoryConfigurationList && { + InventoryConfigurationList: obj.InventoryConfigurationList.map( + (item) => InventoryConfigurationFilterSensitiveLog(item) + ) + } +}), "ListBucketInventoryConfigurationsOutputFilterSensitiveLog"); + +// src/protocols/Aws_restXml.ts +var import_core = __nccwpck_require__(8704); +var import_xml_builder = __nccwpck_require__(94274); +var import_core2 = __nccwpck_require__(90402); +var import_protocol_http = __nccwpck_require__(72356); + +var import_uuid = __nccwpck_require__(12048); + +// src/models/models_1.ts + +var ObjectStorageClass = { + DEEP_ARCHIVE: "DEEP_ARCHIVE", + EXPRESS_ONEZONE: "EXPRESS_ONEZONE", + FSX_OPENZFS: "FSX_OPENZFS", + GLACIER: "GLACIER", + GLACIER_IR: "GLACIER_IR", + INTELLIGENT_TIERING: "INTELLIGENT_TIERING", + ONEZONE_IA: "ONEZONE_IA", + OUTPOSTS: "OUTPOSTS", + REDUCED_REDUNDANCY: "REDUCED_REDUNDANCY", + SNOW: "SNOW", + STANDARD: "STANDARD", + STANDARD_IA: "STANDARD_IA" +}; +var OptionalObjectAttributes = { + RESTORE_STATUS: "RestoreStatus" +}; +var ObjectVersionStorageClass = { + STANDARD: "STANDARD" +}; +var MFADelete = { + Disabled: "Disabled", + Enabled: "Enabled" +}; +var EncryptionTypeMismatch = class _EncryptionTypeMismatch extends S3ServiceException { + static { + __name(this, "EncryptionTypeMismatch"); + } + name = "EncryptionTypeMismatch"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "EncryptionTypeMismatch", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _EncryptionTypeMismatch.prototype); + } +}; +var InvalidRequest = class _InvalidRequest extends S3ServiceException { + static { + __name(this, "InvalidRequest"); + } + name = "InvalidRequest"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidRequest", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidRequest.prototype); + } +}; +var InvalidWriteOffset = class _InvalidWriteOffset extends S3ServiceException { + static { + __name(this, "InvalidWriteOffset"); + } + name = "InvalidWriteOffset"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidWriteOffset", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidWriteOffset.prototype); + } +}; +var TooManyParts = class _TooManyParts extends S3ServiceException { + static { + __name(this, "TooManyParts"); + } + name = "TooManyParts"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "TooManyParts", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _TooManyParts.prototype); + } +}; +var IdempotencyParameterMismatch = class _IdempotencyParameterMismatch extends S3ServiceException { + static { + __name(this, "IdempotencyParameterMismatch"); + } + name = "IdempotencyParameterMismatch"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "IdempotencyParameterMismatch", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _IdempotencyParameterMismatch.prototype); + } +}; +var ObjectAlreadyInActiveTierError = class _ObjectAlreadyInActiveTierError extends S3ServiceException { + static { + __name(this, "ObjectAlreadyInActiveTierError"); + } + name = "ObjectAlreadyInActiveTierError"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ObjectAlreadyInActiveTierError", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ObjectAlreadyInActiveTierError.prototype); + } +}; +var Tier = { + Bulk: "Bulk", + Expedited: "Expedited", + Standard: "Standard" +}; +var ExpressionType = { + SQL: "SQL" +}; +var CompressionType = { + BZIP2: "BZIP2", + GZIP: "GZIP", + NONE: "NONE" +}; +var FileHeaderInfo = { + IGNORE: "IGNORE", + NONE: "NONE", + USE: "USE" +}; +var JSONType = { + DOCUMENT: "DOCUMENT", + LINES: "LINES" +}; +var QuoteFields = { + ALWAYS: "ALWAYS", + ASNEEDED: "ASNEEDED" +}; +var RestoreRequestType = { + SELECT: "SELECT" +}; +var SelectObjectContentEventStream; +((SelectObjectContentEventStream3) => { + SelectObjectContentEventStream3.visit = /* @__PURE__ */ __name((value, visitor) => { + if (value.Records !== void 0) return visitor.Records(value.Records); + if (value.Stats !== void 0) return visitor.Stats(value.Stats); + if (value.Progress !== void 0) return visitor.Progress(value.Progress); + if (value.Cont !== void 0) return visitor.Cont(value.Cont); + if (value.End !== void 0) return visitor.End(value.End); + return visitor._(value.$unknown[0], value.$unknown[1]); + }, "visit"); +})(SelectObjectContentEventStream || (SelectObjectContentEventStream = {})); +var ListPartsRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "ListPartsRequestFilterSensitiveLog"); +var PutBucketEncryptionRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.ServerSideEncryptionConfiguration && { + ServerSideEncryptionConfiguration: ServerSideEncryptionConfigurationFilterSensitiveLog( + obj.ServerSideEncryptionConfiguration + ) + } +}), "PutBucketEncryptionRequestFilterSensitiveLog"); +var PutBucketInventoryConfigurationRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.InventoryConfiguration && { + InventoryConfiguration: InventoryConfigurationFilterSensitiveLog(obj.InventoryConfiguration) + } +}), "PutBucketInventoryConfigurationRequestFilterSensitiveLog"); +var PutObjectOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "PutObjectOutputFilterSensitiveLog"); +var PutObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING }, + ...obj.SSEKMSEncryptionContext && { SSEKMSEncryptionContext: import_smithy_client.SENSITIVE_STRING } +}), "PutObjectRequestFilterSensitiveLog"); +var EncryptionFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.KMSKeyId && { KMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "EncryptionFilterSensitiveLog"); +var S3LocationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Encryption && { Encryption: EncryptionFilterSensitiveLog(obj.Encryption) } +}), "S3LocationFilterSensitiveLog"); +var OutputLocationFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.S3 && { S3: S3LocationFilterSensitiveLog(obj.S3) } +}), "OutputLocationFilterSensitiveLog"); +var RestoreRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.OutputLocation && { OutputLocation: OutputLocationFilterSensitiveLog(obj.OutputLocation) } +}), "RestoreRequestFilterSensitiveLog"); +var RestoreObjectRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.RestoreRequest && { RestoreRequest: RestoreRequestFilterSensitiveLog(obj.RestoreRequest) } +}), "RestoreObjectRequestFilterSensitiveLog"); +var SelectObjectContentEventStreamFilterSensitiveLog = /* @__PURE__ */ __name((obj) => { + if (obj.Records !== void 0) return { Records: obj.Records }; + if (obj.Stats !== void 0) return { Stats: obj.Stats }; + if (obj.Progress !== void 0) return { Progress: obj.Progress }; + if (obj.Cont !== void 0) return { Cont: obj.Cont }; + if (obj.End !== void 0) return { End: obj.End }; + if (obj.$unknown !== void 0) return { [obj.$unknown[0]]: "UNKNOWN" }; +}, "SelectObjectContentEventStreamFilterSensitiveLog"); +var SelectObjectContentOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Payload && { Payload: "STREAMING_CONTENT" } +}), "SelectObjectContentOutputFilterSensitiveLog"); +var SelectObjectContentRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "SelectObjectContentRequestFilterSensitiveLog"); +var UploadPartOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartOutputFilterSensitiveLog"); +var UploadPartRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartRequestFilterSensitiveLog"); +var UploadPartCopyOutputFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartCopyOutputFilterSensitiveLog"); +var UploadPartCopyRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSECustomerKey && { SSECustomerKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.CopySourceSSECustomerKey && { CopySourceSSECustomerKey: import_smithy_client.SENSITIVE_STRING } +}), "UploadPartCopyRequestFilterSensitiveLog"); +var WriteGetObjectResponseRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SSEKMSKeyId && { SSEKMSKeyId: import_smithy_client.SENSITIVE_STRING } +}), "WriteGetObjectResponseRequestFilterSensitiveLog"); + +// src/protocols/Aws_restXml.ts +var se_AbortMultipartUploadCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaimit]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMIT]), () => (0, import_smithy_client.dateToUtcString)(input[_IMIT]).toString()] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "AbortMultipartUpload"], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_AbortMultipartUploadCommand"); +var se_CompleteMultipartUploadCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xacc]: input[_CCRC], + [_xacc_]: input[_CCRCC], + [_xacc__]: input[_CCRCNVME], + [_xacs]: input[_CSHA], + [_xacs_]: input[_CSHAh], + [_xact]: input[_CT], + [_xamos]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_MOS]), () => input[_MOS].toString()], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_im]: input[_IM], + [_inm]: input[_INM], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + let contents; + if (input.MultipartUpload !== void 0) { + contents = se_CompletedMultipartUpload(input.MultipartUpload, context); + contents = contents.n("CompleteMultipartUpload"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CompleteMultipartUploadCommand"); +var se_CopyObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + [_xaa]: input[_ACL], + [_cc]: input[_CC], + [_xaca]: input[_CA], + [_cd]: input[_CD], + [_ce]: input[_CE], + [_cl]: input[_CL], + [_ct]: input[_CTo], + [_xacs__]: input[_CS], + [_xacsim]: input[_CSIM], + [_xacsims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIMS]).toString()], + [_xacsinm]: input[_CSINM], + [_xacsius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIUS]).toString()], + [_e]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagwa]: input[_GWACP], + [_xamd]: input[_MD], + [_xatd]: input[_TD], + [_xasse]: input[_SSE], + [_xasc]: input[_SC], + [_xawrl]: input[_WRL], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()], + [_xacssseca]: input[_CSSSECA], + [_xacssseck]: input[_CSSSECK], + [_xacssseckm]: input[_CSSSECKMD], + [_xarp]: input[_RP], + [_xat]: input[_T], + [_xaolm]: input[_OLM], + [_xaolrud]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString()], + [_xaollh]: input[_OLLHS], + [_xaebo]: input[_EBO], + [_xasebo]: input[_ESBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "CopyObject"] + }); + let body; + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_CopyObjectCommand"); +var se_CreateBucketCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaa]: input[_ACL], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagw]: input[_GW], + [_xagwa]: input[_GWACP], + [_xabole]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLEFB]), () => input[_OLEFB].toString()], + [_xaoo]: input[_OO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + let body; + let contents; + if (input.CreateBucketConfiguration !== void 0) { + contents = se_CreateBucketConfiguration(input.CreateBucketConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).b(body); + return b.build(); +}, "se_CreateBucketCommand"); +var se_CreateBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mC]: [, ""] + }); + let body; + let contents; + if (input.MetadataConfiguration !== void 0) { + contents = se_MetadataConfiguration(input.MetadataConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateBucketMetadataConfigurationCommand"); +var se_CreateBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mT]: [, ""] + }); + let body; + let contents; + if (input.MetadataTableConfiguration !== void 0) { + contents = se_MetadataTableConfiguration(input.MetadataTableConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateBucketMetadataTableConfigurationCommand"); +var se_CreateMultipartUploadCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + [_xaa]: input[_ACL], + [_cc]: input[_CC], + [_cd]: input[_CD], + [_ce]: input[_CE], + [_cl]: input[_CL], + [_ct]: input[_CTo], + [_e]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagwa]: input[_GWACP], + [_xasse]: input[_SSE], + [_xasc]: input[_SC], + [_xawrl]: input[_WRL], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()], + [_xarp]: input[_RP], + [_xat]: input[_T], + [_xaolm]: input[_OLM], + [_xaolrud]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString()], + [_xaollh]: input[_OLLHS], + [_xaebo]: input[_EBO], + [_xaca]: input[_CA], + [_xact]: input[_CT] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_u]: [, ""] + }); + let body; + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateMultipartUploadCommand"); +var se_CreateSessionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xacsm]: input[_SM], + [_xasse]: input[_SSE], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_s]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_CreateSessionCommand"); +var se_DeleteBucketCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + let body; + b.m("DELETE").h(headers).b(body); + return b.build(); +}, "se_DeleteBucketCommand"); +var se_DeleteBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketAnalyticsConfigurationCommand"); +var se_DeleteBucketCorsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_c]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketCorsCommand"); +var se_DeleteBucketEncryptionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_en]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketEncryptionCommand"); +var se_DeleteBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketIntelligentTieringConfigurationCommand"); +var se_DeleteBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketInventoryConfigurationCommand"); +var se_DeleteBucketLifecycleCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_l]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketLifecycleCommand"); +var se_DeleteBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mC]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketMetadataConfigurationCommand"); +var se_DeleteBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mT]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketMetadataTableConfigurationCommand"); +var se_DeleteBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketMetricsConfigurationCommand"); +var se_DeleteBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_oC]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketOwnershipControlsCommand"); +var se_DeleteBucketPolicyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_p]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketPolicyCommand"); +var se_DeleteBucketReplicationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_r]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketReplicationCommand"); +var se_DeleteBucketTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketTaggingCommand"); +var se_DeleteBucketWebsiteCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_w]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteBucketWebsiteCommand"); +var se_DeleteObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xam]: input[_MFA], + [_xarp]: input[_RP], + [_xabgr]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BGR]), () => input[_BGR].toString()], + [_xaebo]: input[_EBO], + [_im]: input[_IM], + [_xaimlmt]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMLMT]), () => (0, import_smithy_client.dateToUtcString)(input[_IMLMT]).toString()], + [_xaims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMS]), () => input[_IMS].toString()] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "DeleteObject"], + [_vI]: [, input[_VI]] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteObjectCommand"); +var se_DeleteObjectsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xam]: input[_MFA], + [_xarp]: input[_RP], + [_xabgr]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BGR]), () => input[_BGR].toString()], + [_xaebo]: input[_EBO], + [_xasca]: input[_CA] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_d]: [, ""] + }); + let body; + let contents; + if (input.Delete !== void 0) { + contents = se_Delete(input.Delete, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteObjectsCommand"); +var se_DeleteObjectTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeleteObjectTaggingCommand"); +var se_DeletePublicAccessBlockCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pAB]: [, ""] + }); + let body; + b.m("DELETE").h(headers).q(query).b(body); + return b.build(); +}, "se_DeletePublicAccessBlockCommand"); +var se_GetBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ac]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketAccelerateConfigurationCommand"); +var se_GetBucketAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketAclCommand"); +var se_GetBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_xi]: [, "GetBucketAnalyticsConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketAnalyticsConfigurationCommand"); +var se_GetBucketCorsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_c]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketCorsCommand"); +var se_GetBucketEncryptionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_en]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketEncryptionCommand"); +var se_GetBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_xi]: [, "GetBucketIntelligentTieringConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketIntelligentTieringConfigurationCommand"); +var se_GetBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_xi]: [, "GetBucketInventoryConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketInventoryConfigurationCommand"); +var se_GetBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_l]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketLifecycleConfigurationCommand"); +var se_GetBucketLocationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_lo]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketLocationCommand"); +var se_GetBucketLoggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_log]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketLoggingCommand"); +var se_GetBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mC]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketMetadataConfigurationCommand"); +var se_GetBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mT]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketMetadataTableConfigurationCommand"); +var se_GetBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_xi]: [, "GetBucketMetricsConfiguration"], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketMetricsConfigurationCommand"); +var se_GetBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_n]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketNotificationConfigurationCommand"); +var se_GetBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_oC]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketOwnershipControlsCommand"); +var se_GetBucketPolicyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_p]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketPolicyCommand"); +var se_GetBucketPolicyStatusCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pS]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketPolicyStatusCommand"); +var se_GetBucketReplicationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_r]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketReplicationCommand"); +var se_GetBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_rP]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketRequestPaymentCommand"); +var se_GetBucketTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketTaggingCommand"); +var se_GetBucketVersioningCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_v]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketVersioningCommand"); +var se_GetBucketWebsiteCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_w]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetBucketWebsiteCommand"); +var se_GetObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_im]: input[_IM], + [_ims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMSf]), () => (0, import_smithy_client.dateToUtcString)(input[_IMSf]).toString()], + [_inm]: input[_INM], + [_ius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IUS]), () => (0, import_smithy_client.dateToUtcString)(input[_IUS]).toString()], + [_ra]: input[_R], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xacm]: input[_CM] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "GetObject"], + [_rcc]: [, input[_RCC]], + [_rcd]: [, input[_RCD]], + [_rce]: [, input[_RCE]], + [_rcl]: [, input[_RCL]], + [_rct]: [, input[_RCT]], + [_re]: [() => input.ResponseExpires !== void 0, () => (0, import_smithy_client.dateToUtcString)(input[_RE]).toString()], + [_vI]: [, input[_VI]], + [_pN]: [() => input.PartNumber !== void 0, () => input[_PN].toString()] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectCommand"); +var se_GetObjectAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectAclCommand"); +var se_GetObjectAttributesCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xamp]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_MP]), () => input[_MP].toString()], + [_xapnm]: input[_PNM], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaoa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OA]), () => (input[_OA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_at]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectAttributesCommand"); +var se_GetObjectLegalHoldCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_lh]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectLegalHoldCommand"); +var se_GetObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ol]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectLockConfigurationCommand"); +var se_GetObjectRetentionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_ret]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectRetentionCommand"); +var se_GetObjectTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectTaggingCommand"); +var se_GetObjectTorrentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_to]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetObjectTorrentCommand"); +var se_GetPublicAccessBlockCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pAB]: [, ""] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetPublicAccessBlockCommand"); +var se_HeadBucketCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + let body; + b.m("HEAD").h(headers).b(body); + return b.build(); +}, "se_HeadBucketCommand"); +var se_HeadObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_im]: input[_IM], + [_ims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IMSf]), () => (0, import_smithy_client.dateToUtcString)(input[_IMSf]).toString()], + [_inm]: input[_INM], + [_ius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_IUS]), () => (0, import_smithy_client.dateToUtcString)(input[_IUS]).toString()], + [_ra]: input[_R], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xacm]: input[_CM] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_rcc]: [, input[_RCC]], + [_rcd]: [, input[_RCD]], + [_rce]: [, input[_RCE]], + [_rcl]: [, input[_RCL]], + [_rct]: [, input[_RCT]], + [_re]: [() => input.ResponseExpires !== void 0, () => (0, import_smithy_client.dateToUtcString)(input[_RE]).toString()], + [_vI]: [, input[_VI]], + [_pN]: [() => input.PartNumber !== void 0, () => input[_PN].toString()] + }); + let body; + b.m("HEAD").h(headers).q(query).b(body); + return b.build(); +}, "se_HeadObjectCommand"); +var se_ListBucketAnalyticsConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_xi]: [, "ListBucketAnalyticsConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketAnalyticsConfigurationsCommand"); +var se_ListBucketIntelligentTieringConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_xi]: [, "ListBucketIntelligentTieringConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketIntelligentTieringConfigurationsCommand"); +var se_ListBucketInventoryConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_xi]: [, "ListBucketInventoryConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketInventoryConfigurationsCommand"); +var se_ListBucketMetricsConfigurationsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_xi]: [, "ListBucketMetricsConfigurations"], + [_ct_]: [, input[_CTon]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketMetricsConfigurationsCommand"); +var se_ListBucketsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = {}; + b.bp("/"); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "ListBuckets"], + [_mb]: [() => input.MaxBuckets !== void 0, () => input[_MB].toString()], + [_ct_]: [, input[_CTon]], + [_pr]: [, input[_P]], + [_br]: [, input[_BR]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListBucketsCommand"); +var se_ListDirectoryBucketsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = {}; + b.bp("/"); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "ListDirectoryBuckets"], + [_ct_]: [, input[_CTon]], + [_mdb]: [() => input.MaxDirectoryBuckets !== void 0, () => input[_MDB].toString()] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListDirectoryBucketsCommand"); +var se_ListMultipartUploadsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_u]: [, ""], + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_km]: [, input[_KM]], + [_mu]: [() => input.MaxUploads !== void 0, () => input[_MU].toString()], + [_pr]: [, input[_P]], + [_uim]: [, input[_UIM]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListMultipartUploadsCommand"); +var se_ListObjectsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaooa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OOA]), () => (input[_OOA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_ma]: [, input[_M]], + [_mk]: [() => input.MaxKeys !== void 0, () => input[_MK].toString()], + [_pr]: [, input[_P]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListObjectsCommand"); +var se_ListObjectsV2Command = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xaooa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OOA]), () => (input[_OOA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_lt]: [, "2"], + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_mk]: [() => input.MaxKeys !== void 0, () => input[_MK].toString()], + [_pr]: [, input[_P]], + [_ct_]: [, input[_CTon]], + [_fo]: [() => input.FetchOwner !== void 0, () => input[_FO].toString()], + [_sa]: [, input[_SA]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListObjectsV2Command"); +var se_ListObjectVersionsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xaebo]: input[_EBO], + [_xarp]: input[_RP], + [_xaooa]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OOA]), () => (input[_OOA] || []).map(import_smithy_client.quoteHeader).join(", ")] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ver]: [, ""], + [_de]: [, input[_D]], + [_et]: [, input[_ET]], + [_km]: [, input[_KM]], + [_mk]: [() => input.MaxKeys !== void 0, () => input[_MK].toString()], + [_pr]: [, input[_P]], + [_vim]: [, input[_VIM]] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListObjectVersionsCommand"); +var se_ListPartsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "ListParts"], + [_mp]: [() => input.MaxParts !== void 0, () => input[_MP].toString()], + [_pnm]: [, input[_PNM]], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListPartsCommand"); +var se_PutBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO], + [_xasca]: input[_CA] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ac]: [, ""] + }); + let body; + let contents; + if (input.AccelerateConfiguration !== void 0) { + contents = se_AccelerateConfiguration(input.AccelerateConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketAccelerateConfigurationCommand"); +var se_PutBucketAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaa]: input[_ACL], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagw]: input[_GW], + [_xagwa]: input[_GWACP], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""] + }); + let body; + let contents; + if (input.AccessControlPolicy !== void 0) { + contents = se_AccessControlPolicy(input.AccessControlPolicy, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketAclCommand"); +var se_PutBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_a]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.AnalyticsConfiguration !== void 0) { + contents = se_AnalyticsConfiguration(input.AnalyticsConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketAnalyticsConfigurationCommand"); +var se_PutBucketCorsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_c]: [, ""] + }); + let body; + let contents; + if (input.CORSConfiguration !== void 0) { + contents = se_CORSConfiguration(input.CORSConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketCorsCommand"); +var se_PutBucketEncryptionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_en]: [, ""] + }); + let body; + let contents; + if (input.ServerSideEncryptionConfiguration !== void 0) { + contents = se_ServerSideEncryptionConfiguration(input.ServerSideEncryptionConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketEncryptionCommand"); +var se_PutBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_it]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.IntelligentTieringConfiguration !== void 0) { + contents = se_IntelligentTieringConfiguration(input.IntelligentTieringConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketIntelligentTieringConfigurationCommand"); +var se_PutBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_in]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.InventoryConfiguration !== void 0) { + contents = se_InventoryConfiguration(input.InventoryConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketInventoryConfigurationCommand"); +var se_PutBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xasca]: input[_CA], + [_xaebo]: input[_EBO], + [_xatdmos]: input[_TDMOS] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_l]: [, ""] + }); + let body; + let contents; + if (input.LifecycleConfiguration !== void 0) { + contents = se_BucketLifecycleConfiguration(input.LifecycleConfiguration, context); + contents = contents.n("LifecycleConfiguration"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketLifecycleConfigurationCommand"); +var se_PutBucketLoggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_log]: [, ""] + }); + let body; + let contents; + if (input.BucketLoggingStatus !== void 0) { + contents = se_BucketLoggingStatus(input.BucketLoggingStatus, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketLoggingCommand"); +var se_PutBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_m]: [, ""], + [_i]: [, (0, import_smithy_client.expectNonNull)(input[_I], `Id`)] + }); + let body; + let contents; + if (input.MetricsConfiguration !== void 0) { + contents = se_MetricsConfiguration(input.MetricsConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketMetricsConfigurationCommand"); +var se_PutBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaebo]: input[_EBO], + [_xasdv]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SDV]), () => input[_SDV].toString()] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_n]: [, ""] + }); + let body; + let contents; + if (input.NotificationConfiguration !== void 0) { + contents = se_NotificationConfiguration(input.NotificationConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketNotificationConfigurationCommand"); +var se_PutBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xaebo]: input[_EBO], + [_xasca]: input[_CA] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_oC]: [, ""] + }); + let body; + let contents; + if (input.OwnershipControls !== void 0) { + contents = se_OwnershipControls(input.OwnershipControls, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketOwnershipControlsCommand"); +var se_PutBucketPolicyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "text/plain", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xacrsba]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CRSBA]), () => input[_CRSBA].toString()], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_p]: [, ""] + }); + let body; + let contents; + if (input.Policy !== void 0) { + contents = input.Policy; + body = contents; + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketPolicyCommand"); +var se_PutBucketReplicationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xabolt]: input[_To], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_r]: [, ""] + }); + let body; + let contents; + if (input.ReplicationConfiguration !== void 0) { + contents = se_ReplicationConfiguration(input.ReplicationConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketReplicationCommand"); +var se_PutBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_rP]: [, ""] + }); + let body; + let contents; + if (input.RequestPaymentConfiguration !== void 0) { + contents = se_RequestPaymentConfiguration(input.RequestPaymentConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketRequestPaymentCommand"); +var se_PutBucketTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""] + }); + let body; + let contents; + if (input.Tagging !== void 0) { + contents = se_Tagging(input.Tagging, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketTaggingCommand"); +var se_PutBucketVersioningCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xam]: input[_MFA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_v]: [, ""] + }); + let body; + let contents; + if (input.VersioningConfiguration !== void 0) { + contents = se_VersioningConfiguration(input.VersioningConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketVersioningCommand"); +var se_PutBucketWebsiteCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_w]: [, ""] + }); + let body; + let contents; + if (input.WebsiteConfiguration !== void 0) { + contents = se_WebsiteConfiguration(input.WebsiteConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutBucketWebsiteCommand"); +var se_PutObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + [_ct]: input[_CTo] || "application/octet-stream", + [_xaa]: input[_ACL], + [_cc]: input[_CC], + [_cd]: input[_CD], + [_ce]: input[_CE], + [_cl]: input[_CL], + [_cl_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CLo]), () => input[_CLo].toString()], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xacc]: input[_CCRC], + [_xacc_]: input[_CCRCC], + [_xacc__]: input[_CCRCNVME], + [_xacs]: input[_CSHA], + [_xacs_]: input[_CSHAh], + [_e]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_im]: input[_IM], + [_inm]: input[_INM], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagwa]: input[_GWACP], + [_xawob]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_WOB]), () => input[_WOB].toString()], + [_xasse]: input[_SSE], + [_xasc]: input[_SC], + [_xawrl]: input[_WRL], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xasseakki]: input[_SSEKMSKI], + [_xassec]: input[_SSEKMSEC], + [_xassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()], + [_xarp]: input[_RP], + [_xat]: input[_T], + [_xaolm]: input[_OLM], + [_xaolrud]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString()], + [_xaollh]: input[_OLLHS], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "PutObject"] + }); + let body; + let contents; + if (input.Body !== void 0) { + contents = input.Body; + body = contents; + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectCommand"); +var se_PutObjectAclCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xaa]: input[_ACL], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xagfc]: input[_GFC], + [_xagr]: input[_GR], + [_xagra]: input[_GRACP], + [_xagw]: input[_GW], + [_xagwa]: input[_GWACP], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_acl]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.AccessControlPolicy !== void 0) { + contents = se_AccessControlPolicy(input.AccessControlPolicy, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectAclCommand"); +var se_PutObjectLegalHoldCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_lh]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.LegalHold !== void 0) { + contents = se_ObjectLockLegalHold(input.LegalHold, context); + contents = contents.n("LegalHold"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectLegalHoldCommand"); +var se_PutObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_xabolt]: input[_To], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_ol]: [, ""] + }); + let body; + let contents; + if (input.ObjectLockConfiguration !== void 0) { + contents = se_ObjectLockConfiguration(input.ObjectLockConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectLockConfigurationCommand"); +var se_PutObjectRetentionCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_xabgr]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BGR]), () => input[_BGR].toString()], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_ret]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.Retention !== void 0) { + contents = se_ObjectLockRetention(input.Retention, context); + contents = contents.n("Retention"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectRetentionCommand"); +var se_PutObjectTaggingCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO], + [_xarp]: input[_RP] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_t]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.Tagging !== void 0) { + contents = se_Tagging(input.Tagging, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutObjectTaggingCommand"); +var se_PutPublicAccessBlockCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_pAB]: [, ""] + }); + let body; + let contents; + if (input.PublicAccessBlockConfiguration !== void 0) { + contents = se_PublicAccessBlockConfiguration(input.PublicAccessBlockConfiguration, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_PutPublicAccessBlockCommand"); +var se_RenameObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xars]: input[_RS], + [_im]: input[_DIM], + [_inm]: input[_DINM], + [_ims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_DIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_DIMS]).toString()], + [_ius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_DIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_DIUS]).toString()], + [_xarsim]: input[_SIM], + [_xarsinm]: input[_SINM], + [_xarsims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_SIMS]).toString()], + [_xarsius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_SIUS]).toString()], + [_xact_]: input[_CTl] ?? (0, import_uuid.v4)() + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_rO]: [, ""] + }); + let body; + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_RenameObjectCommand"); +var se_RestoreObjectCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xarp]: input[_RP], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_res]: [, ""], + [_vI]: [, input[_VI]] + }); + let body; + let contents; + if (input.RestoreRequest !== void 0) { + contents = se_RestoreRequest(input.RestoreRequest, context); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_RestoreObjectCommand"); +var se_SelectObjectContentCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_se]: [, ""], + [_st]: [, "2"] + }); + let body; + body = _ve; + const bn = new import_xml_builder.XmlNode(_SOCR); + bn.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + bn.cc(input, _Ex); + bn.cc(input, _ETx); + if (input[_IS] != null) { + bn.c(se_InputSerialization(input[_IS], context).n(_IS)); + } + if (input[_OS] != null) { + bn.c(se_OutputSerialization(input[_OS], context).n(_OS)); + } + if (input[_RPe] != null) { + bn.c(se_RequestProgress(input[_RPe], context).n(_RPe)); + } + if (input[_SR] != null) { + bn.c(se_ScanRange(input[_SR], context).n(_SR)); + } + body += bn.toString(); + b.m("POST").h(headers).q(query).b(body); + return b.build(); +}, "se_SelectObjectContentCommand"); +var se_UpdateBucketMetadataInventoryTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mIT]: [, ""] + }); + let body; + let contents; + if (input.InventoryTableConfiguration !== void 0) { + contents = se_InventoryTableConfigurationUpdates(input.InventoryTableConfiguration, context); + contents = contents.n("InventoryTableConfiguration"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UpdateBucketMetadataInventoryTableConfigurationCommand"); +var se_UpdateBucketMetadataJournalTableConfigurationCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/xml", + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xaebo]: input[_EBO] + }); + b.bp("/"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + const query = (0, import_smithy_client.map)({ + [_mJT]: [, ""] + }); + let body; + let contents; + if (input.JournalTableConfiguration !== void 0) { + contents = se_JournalTableConfigurationUpdates(input.JournalTableConfiguration, context); + contents = contents.n("JournalTableConfiguration"); + body = _ve; + contents.a("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); + body += contents.toString(); + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UpdateBucketMetadataJournalTableConfigurationCommand"); +var se_UploadPartCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "content-type": "application/octet-stream", + [_cl_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CLo]), () => input[_CLo].toString()], + [_cm]: input[_CMD], + [_xasca]: input[_CA], + [_xacc]: input[_CCRC], + [_xacc_]: input[_CCRCC], + [_xacc__]: input[_CCRCNVME], + [_xacs]: input[_CSHA], + [_xacs_]: input[_CSHAh], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "UploadPart"], + [_pN]: [(0, import_smithy_client.expectNonNull)(input.PartNumber, `PartNumber`) != null, () => input[_PN].toString()], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + let contents; + if (input.Body !== void 0) { + contents = input.Body; + body = contents; + } + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UploadPartCommand"); +var se_UploadPartCopyCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xacs__]: input[_CS], + [_xacsim]: input[_CSIM], + [_xacsims]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIMS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIMS]).toString()], + [_xacsinm]: input[_CSINM], + [_xacsius]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CSIUS]), () => (0, import_smithy_client.dateToUtcString)(input[_CSIUS]).toString()], + [_xacsr]: input[_CSR], + [_xasseca]: input[_SSECA], + [_xasseck]: input[_SSECK], + [_xasseckm]: input[_SSECKMD], + [_xacssseca]: input[_CSSSECA], + [_xacssseck]: input[_CSSSECK], + [_xacssseckm]: input[_CSSSECKMD], + [_xarp]: input[_RP], + [_xaebo]: input[_EBO], + [_xasebo]: input[_ESBO] + }); + b.bp("/{Key+}"); + b.p("Bucket", () => input.Bucket, "{Bucket}", false); + b.p("Key", () => input.Key, "{Key+}", true); + const query = (0, import_smithy_client.map)({ + [_xi]: [, "UploadPartCopy"], + [_pN]: [(0, import_smithy_client.expectNonNull)(input.PartNumber, `PartNumber`) != null, () => input[_PN].toString()], + [_uI]: [, (0, import_smithy_client.expectNonNull)(input[_UI], `UploadId`)] + }); + let body; + b.m("PUT").h(headers).q(query).b(body); + return b.build(); +}, "se_UploadPartCopyCommand"); +var se_WriteGetObjectResponseCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core2.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + "x-amz-content-sha256": "UNSIGNED-PAYLOAD", + ...input.Metadata !== void 0 && Object.keys(input.Metadata).reduce((acc, suffix) => { + acc[`x-amz-meta-${suffix.toLowerCase()}`] = input.Metadata[suffix]; + return acc; + }, {}), + "content-type": "application/octet-stream", + [_xarr]: input[_RR], + [_xart]: input[_RT], + [_xafs]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_SCt]), () => input[_SCt].toString()], + [_xafec]: input[_EC], + [_xafem]: input[_EM], + [_xafhar]: input[_AR], + [_xafhcc]: input[_CC], + [_xafhcd]: input[_CD], + [_xafhce]: input[_CE], + [_xafhcl]: input[_CL], + [_cl_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_CLo]), () => input[_CLo].toString()], + [_xafhcr]: input[_CR], + [_xafhct]: input[_CTo], + [_xafhxacc]: input[_CCRC], + [_xafhxacc_]: input[_CCRCC], + [_xafhxacc__]: input[_CCRCNVME], + [_xafhxacs]: input[_CSHA], + [_xafhxacs_]: input[_CSHAh], + [_xafhxadm]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_DM]), () => input[_DM].toString()], + [_xafhe]: input[_ETa], + [_xafhe_]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_E]), () => (0, import_smithy_client.dateToUtcString)(input[_E]).toString()], + [_xafhxae]: input[_Exp], + [_xafhlm]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_LM]), () => (0, import_smithy_client.dateToUtcString)(input[_LM]).toString()], + [_xafhxamm]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_MM]), () => input[_MM].toString()], + [_xafhxaolm]: input[_OLM], + [_xafhxaollh]: input[_OLLHS], + [_xafhxaolrud]: [ + () => (0, import_smithy_client.isSerializableHeaderValue)(input[_OLRUD]), + () => (0, import_smithy_client.serializeDateTime)(input[_OLRUD]).toString() + ], + [_xafhxampc]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_PC]), () => input[_PC].toString()], + [_xafhxars]: input[_RSe], + [_xafhxarc]: input[_RC], + [_xafhxar]: input[_Re], + [_xafhxasse]: input[_SSE], + [_xafhxasseca]: input[_SSECA], + [_xafhxasseakki]: input[_SSEKMSKI], + [_xafhxasseckm]: input[_SSECKMD], + [_xafhxasc]: input[_SC], + [_xafhxatc]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_TC]), () => input[_TC].toString()], + [_xafhxavi]: input[_VI], + [_xafhxassebke]: [() => (0, import_smithy_client.isSerializableHeaderValue)(input[_BKE]), () => input[_BKE].toString()] + }); + b.bp("/WriteGetObjectResponse"); + let body; + let contents; + if (input.Body !== void 0) { + contents = input.Body; + body = contents; + } + let { hostname: resolvedHostname } = await context.endpoint(); + if (context.disableHostPrefix !== true) { + resolvedHostname = "{RequestRoute}." + resolvedHostname; + if (input.RequestRoute === void 0) { + throw new Error("Empty value provided for input host prefix: RequestRoute."); + } + resolvedHostname = resolvedHostname.replace("{RequestRoute}", input.RequestRoute); + if (!(0, import_protocol_http.isValidHostname)(resolvedHostname)) { + throw new Error("ValidationError: prefixed hostname must be hostname compatible."); + } + } + b.hn(resolvedHostname); + b.m("POST").h(headers).b(body); + return b.build(); +}, "se_WriteGetObjectResponseCommand"); +var de_AbortMultipartUploadCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_AbortMultipartUploadCommand"); +var de_CompleteMultipartUploadCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_Exp]: [, output.headers[_xae]], + [_SSE]: [, output.headers[_xasse]], + [_VI]: [, output.headers[_xavi]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(data[_CCRC]); + } + if (data[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(data[_CCRCC]); + } + if (data[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(data[_CCRCNVME]); + } + if (data[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(data[_CSHA]); + } + if (data[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(data[_CSHAh]); + } + if (data[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(data[_CT]); + } + if (data[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(data[_ETa]); + } + if (data[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(data[_K]); + } + if (data[_L] != null) { + contents[_L] = (0, import_smithy_client.expectString)(data[_L]); + } + return contents; +}, "de_CompleteMultipartUploadCommand"); +var de_CopyObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_Exp]: [, output.headers[_xae]], + [_CSVI]: [, output.headers[_xacsvi]], + [_VI]: [, output.headers[_xavi]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.CopyObjectResult = de_CopyObjectResult(data, context); + return contents; +}, "de_CopyObjectCommand"); +var de_CreateBucketCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_L]: [, output.headers[_lo]], + [_BA]: [, output.headers[_xaba]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_CreateBucketCommand"); +var de_CreateBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_CreateBucketMetadataConfigurationCommand"); +var de_CreateBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_CreateBucketMetadataTableConfigurationCommand"); +var de_CreateMultipartUploadCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_AD]: [ + () => void 0 !== output.headers[_xaad], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_xaad])) + ], + [_ARI]: [, output.headers[_xaari]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]], + [_CA]: [, output.headers[_xaca]], + [_CT]: [, output.headers[_xact]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(data[_K]); + } + if (data[_UI] != null) { + contents[_UI] = (0, import_smithy_client.expectString)(data[_UI]); + } + return contents; +}, "de_CreateMultipartUploadCommand"); +var de_CreateSessionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_SSE]: [, output.headers[_xasse]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_C] != null) { + contents[_C] = de_SessionCredentials(data[_C], context); + } + return contents; +}, "de_CreateSessionCommand"); +var de_DeleteBucketCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketCommand"); +var de_DeleteBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketAnalyticsConfigurationCommand"); +var de_DeleteBucketCorsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketCorsCommand"); +var de_DeleteBucketEncryptionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketEncryptionCommand"); +var de_DeleteBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketIntelligentTieringConfigurationCommand"); +var de_DeleteBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketInventoryConfigurationCommand"); +var de_DeleteBucketLifecycleCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketLifecycleCommand"); +var de_DeleteBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketMetadataConfigurationCommand"); +var de_DeleteBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketMetadataTableConfigurationCommand"); +var de_DeleteBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketMetricsConfigurationCommand"); +var de_DeleteBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketOwnershipControlsCommand"); +var de_DeleteBucketPolicyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketPolicyCommand"); +var de_DeleteBucketReplicationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketReplicationCommand"); +var de_DeleteBucketTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketTaggingCommand"); +var de_DeleteBucketWebsiteCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteBucketWebsiteCommand"); +var de_DeleteObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_VI]: [, output.headers[_xavi]], + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteObjectCommand"); +var de_DeleteObjectsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Deleted === "") { + contents[_De] = []; + } else if (data[_De] != null) { + contents[_De] = de_DeletedObjects((0, import_smithy_client.getArrayIfSingleItem)(data[_De]), context); + } + if (data.Error === "") { + contents[_Err] = []; + } else if (data[_Er] != null) { + contents[_Err] = de_Errors((0, import_smithy_client.getArrayIfSingleItem)(data[_Er]), context); + } + return contents; +}, "de_DeleteObjectsCommand"); +var de_DeleteObjectTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_VI]: [, output.headers[_xavi]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeleteObjectTaggingCommand"); +var de_DeletePublicAccessBlockCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 204 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_DeletePublicAccessBlockCommand"); +var de_GetBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(data[_S]); + } + return contents; +}, "de_GetBucketAccelerateConfigurationCommand"); +var de_GetBucketAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.AccessControlList === "") { + contents[_Gr] = []; + } else if (data[_ACLc] != null && data[_ACLc][_G] != null) { + contents[_Gr] = de_Grants((0, import_smithy_client.getArrayIfSingleItem)(data[_ACLc][_G]), context); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + return contents; +}, "de_GetBucketAclCommand"); +var de_GetBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.AnalyticsConfiguration = de_AnalyticsConfiguration(data, context); + return contents; +}, "de_GetBucketAnalyticsConfigurationCommand"); +var de_GetBucketCorsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CORSRule === "") { + contents[_CORSRu] = []; + } else if (data[_CORSR] != null) { + contents[_CORSRu] = de_CORSRules((0, import_smithy_client.getArrayIfSingleItem)(data[_CORSR]), context); + } + return contents; +}, "de_GetBucketCorsCommand"); +var de_GetBucketEncryptionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.ServerSideEncryptionConfiguration = de_ServerSideEncryptionConfiguration(data, context); + return contents; +}, "de_GetBucketEncryptionCommand"); +var de_GetBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.IntelligentTieringConfiguration = de_IntelligentTieringConfiguration(data, context); + return contents; +}, "de_GetBucketIntelligentTieringConfigurationCommand"); +var de_GetBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.InventoryConfiguration = de_InventoryConfiguration(data, context); + return contents; +}, "de_GetBucketInventoryConfigurationCommand"); +var de_GetBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_TDMOS]: [, output.headers[_xatdmos]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Rule === "") { + contents[_Rul] = []; + } else if (data[_Ru] != null) { + contents[_Rul] = de_LifecycleRules((0, import_smithy_client.getArrayIfSingleItem)(data[_Ru]), context); + } + return contents; +}, "de_GetBucketLifecycleConfigurationCommand"); +var de_GetBucketLocationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_LC] != null) { + contents[_LC] = (0, import_smithy_client.expectString)(data[_LC]); + } + return contents; +}, "de_GetBucketLocationCommand"); +var de_GetBucketLoggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_LE] != null) { + contents[_LE] = de_LoggingEnabled(data[_LE], context); + } + return contents; +}, "de_GetBucketLoggingCommand"); +var de_GetBucketMetadataConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.GetBucketMetadataConfigurationResult = de_GetBucketMetadataConfigurationResult(data, context); + return contents; +}, "de_GetBucketMetadataConfigurationCommand"); +var de_GetBucketMetadataTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.GetBucketMetadataTableConfigurationResult = de_GetBucketMetadataTableConfigurationResult(data, context); + return contents; +}, "de_GetBucketMetadataTableConfigurationCommand"); +var de_GetBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.MetricsConfiguration = de_MetricsConfiguration(data, context); + return contents; +}, "de_GetBucketMetricsConfigurationCommand"); +var de_GetBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_EBC] != null) { + contents[_EBC] = de_EventBridgeConfiguration(data[_EBC], context); + } + if (data.CloudFunctionConfiguration === "") { + contents[_LFC] = []; + } else if (data[_CFC] != null) { + contents[_LFC] = de_LambdaFunctionConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_CFC]), context); + } + if (data.QueueConfiguration === "") { + contents[_QCu] = []; + } else if (data[_QC] != null) { + contents[_QCu] = de_QueueConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_QC]), context); + } + if (data.TopicConfiguration === "") { + contents[_TCop] = []; + } else if (data[_TCo] != null) { + contents[_TCop] = de_TopicConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_TCo]), context); + } + return contents; +}, "de_GetBucketNotificationConfigurationCommand"); +var de_GetBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.OwnershipControls = de_OwnershipControls(data, context); + return contents; +}, "de_GetBucketOwnershipControlsCommand"); +var de_GetBucketPolicyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = await collectBodyString(output.body, context); + contents.Policy = (0, import_smithy_client.expectString)(data); + return contents; +}, "de_GetBucketPolicyCommand"); +var de_GetBucketPolicyStatusCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.PolicyStatus = de_PolicyStatus(data, context); + return contents; +}, "de_GetBucketPolicyStatusCommand"); +var de_GetBucketReplicationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.ReplicationConfiguration = de_ReplicationConfiguration(data, context); + return contents; +}, "de_GetBucketReplicationCommand"); +var de_GetBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_Pa] != null) { + contents[_Pa] = (0, import_smithy_client.expectString)(data[_Pa]); + } + return contents; +}, "de_GetBucketRequestPaymentCommand"); +var de_GetBucketTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.TagSet === "") { + contents[_TS] = []; + } else if (data[_TS] != null && data[_TS][_Ta] != null) { + contents[_TS] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(data[_TS][_Ta]), context); + } + return contents; +}, "de_GetBucketTaggingCommand"); +var de_GetBucketVersioningCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_MDf] != null) { + contents[_MFAD] = (0, import_smithy_client.expectString)(data[_MDf]); + } + if (data[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(data[_S]); + } + return contents; +}, "de_GetBucketVersioningCommand"); +var de_GetBucketWebsiteCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_ED] != null) { + contents[_ED] = de_ErrorDocument(data[_ED], context); + } + if (data[_ID] != null) { + contents[_ID] = de_IndexDocument(data[_ID], context); + } + if (data[_RART] != null) { + contents[_RART] = de_RedirectAllRequestsTo(data[_RART], context); + } + if (data.RoutingRules === "") { + contents[_RRo] = []; + } else if (data[_RRo] != null && data[_RRo][_RRou] != null) { + contents[_RRo] = de_RoutingRules((0, import_smithy_client.getArrayIfSingleItem)(data[_RRo][_RRou]), context); + } + return contents; +}, "de_GetBucketWebsiteCommand"); +var de_GetObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_AR]: [, output.headers[_ar]], + [_Exp]: [, output.headers[_xae]], + [_Re]: [, output.headers[_xar]], + [_LM]: [() => void 0 !== output.headers[_lm], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_lm]))], + [_CLo]: [() => void 0 !== output.headers[_cl_], () => (0, import_smithy_client.strictParseLong)(output.headers[_cl_])], + [_ETa]: [, output.headers[_eta]], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_CT]: [, output.headers[_xact]], + [_MM]: [() => void 0 !== output.headers[_xamm], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xamm])], + [_VI]: [, output.headers[_xavi]], + [_CC]: [, output.headers[_cc]], + [_CD]: [, output.headers[_cd]], + [_CE]: [, output.headers[_ce]], + [_CL]: [, output.headers[_cl]], + [_CR]: [, output.headers[_cr]], + [_CTo]: [, output.headers[_ct]], + [_E]: [() => void 0 !== output.headers[_e], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_e]))], + [_ES]: [, output.headers[_ex]], + [_WRL]: [, output.headers[_xawrl]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_SC]: [, output.headers[_xasc]], + [_RC]: [, output.headers[_xarc]], + [_RSe]: [, output.headers[_xars_]], + [_PC]: [() => void 0 !== output.headers[_xampc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xampc])], + [_TC]: [() => void 0 !== output.headers[_xatc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xatc])], + [_OLM]: [, output.headers[_xaolm]], + [_OLRUD]: [ + () => void 0 !== output.headers[_xaolrud], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output.headers[_xaolrud])) + ], + [_OLLHS]: [, output.headers[_xaollh]], + Metadata: [ + , + Object.keys(output.headers).filter((header) => header.startsWith("x-amz-meta-")).reduce((acc, header) => { + acc[header.substring(11)] = output.headers[header]; + return acc; + }, {}) + ] + }); + const data = output.body; + context.sdkStreamMixin(data); + contents.Body = data; + return contents; +}, "de_GetObjectCommand"); +var de_GetObjectAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.AccessControlList === "") { + contents[_Gr] = []; + } else if (data[_ACLc] != null && data[_ACLc][_G] != null) { + contents[_Gr] = de_Grants((0, import_smithy_client.getArrayIfSingleItem)(data[_ACLc][_G]), context); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + return contents; +}, "de_GetObjectAclCommand"); +var de_GetObjectAttributesCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_LM]: [() => void 0 !== output.headers[_lm], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_lm]))], + [_VI]: [, output.headers[_xavi]], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_Ch] != null) { + contents[_Ch] = de_Checksum(data[_Ch], context); + } + if (data[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(data[_ETa]); + } + if (data[_OP] != null) { + contents[_OP] = de_GetObjectAttributesParts(data[_OP], context); + } + if (data[_OSb] != null) { + contents[_OSb] = (0, import_smithy_client.strictParseLong)(data[_OSb]); + } + if (data[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(data[_SC]); + } + return contents; +}, "de_GetObjectAttributesCommand"); +var de_GetObjectLegalHoldCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.LegalHold = de_ObjectLockLegalHold(data, context); + return contents; +}, "de_GetObjectLegalHoldCommand"); +var de_GetObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.ObjectLockConfiguration = de_ObjectLockConfiguration(data, context); + return contents; +}, "de_GetObjectLockConfigurationCommand"); +var de_GetObjectRetentionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.Retention = de_ObjectLockRetention(data, context); + return contents; +}, "de_GetObjectRetentionCommand"); +var de_GetObjectTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_VI]: [, output.headers[_xavi]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.TagSet === "") { + contents[_TS] = []; + } else if (data[_TS] != null && data[_TS][_Ta] != null) { + contents[_TS] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(data[_TS][_Ta]), context); + } + return contents; +}, "de_GetObjectTaggingCommand"); +var de_GetObjectTorrentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = output.body; + context.sdkStreamMixin(data); + contents.Body = data; + return contents; +}, "de_GetObjectTorrentCommand"); +var de_GetPublicAccessBlockCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.PublicAccessBlockConfiguration = de_PublicAccessBlockConfiguration(data, context); + return contents; +}, "de_GetPublicAccessBlockCommand"); +var de_HeadBucketCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_BA]: [, output.headers[_xaba]], + [_BLT]: [, output.headers[_xablt]], + [_BLN]: [, output.headers[_xabln]], + [_BR]: [, output.headers[_xabr]], + [_APA]: [() => void 0 !== output.headers[_xaapa], () => (0, import_smithy_client.parseBoolean)(output.headers[_xaapa])] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_HeadBucketCommand"); +var de_HeadObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_DM]: [() => void 0 !== output.headers[_xadm], () => (0, import_smithy_client.parseBoolean)(output.headers[_xadm])], + [_AR]: [, output.headers[_ar]], + [_Exp]: [, output.headers[_xae]], + [_Re]: [, output.headers[_xar]], + [_AS]: [, output.headers[_xaas]], + [_LM]: [() => void 0 !== output.headers[_lm], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_lm]))], + [_CLo]: [() => void 0 !== output.headers[_cl_], () => (0, import_smithy_client.strictParseLong)(output.headers[_cl_])], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_CT]: [, output.headers[_xact]], + [_ETa]: [, output.headers[_eta]], + [_MM]: [() => void 0 !== output.headers[_xamm], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xamm])], + [_VI]: [, output.headers[_xavi]], + [_CC]: [, output.headers[_cc]], + [_CD]: [, output.headers[_cd]], + [_CE]: [, output.headers[_ce]], + [_CL]: [, output.headers[_cl]], + [_CTo]: [, output.headers[_ct]], + [_CR]: [, output.headers[_cr]], + [_E]: [() => void 0 !== output.headers[_e], () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_e]))], + [_ES]: [, output.headers[_ex]], + [_WRL]: [, output.headers[_xawrl]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_SC]: [, output.headers[_xasc]], + [_RC]: [, output.headers[_xarc]], + [_RSe]: [, output.headers[_xars_]], + [_PC]: [() => void 0 !== output.headers[_xampc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xampc])], + [_TC]: [() => void 0 !== output.headers[_xatc], () => (0, import_smithy_client.strictParseInt32)(output.headers[_xatc])], + [_OLM]: [, output.headers[_xaolm]], + [_OLRUD]: [ + () => void 0 !== output.headers[_xaolrud], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output.headers[_xaolrud])) + ], + [_OLLHS]: [, output.headers[_xaollh]], + Metadata: [ + , + Object.keys(output.headers).filter((header) => header.startsWith("x-amz-meta-")).reduce((acc, header) => { + acc[header.substring(11)] = output.headers[header]; + return acc; + }, {}) + ] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_HeadObjectCommand"); +var de_ListBucketAnalyticsConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.AnalyticsConfiguration === "") { + contents[_ACLn] = []; + } else if (data[_AC] != null) { + contents[_ACLn] = de_AnalyticsConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_AC]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketAnalyticsConfigurationsCommand"); +var de_ListBucketIntelligentTieringConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data.IntelligentTieringConfiguration === "") { + contents[_ITCL] = []; + } else if (data[_ITC] != null) { + contents[_ITCL] = de_IntelligentTieringConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_ITC]), context); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketIntelligentTieringConfigurationsCommand"); +var de_ListBucketInventoryConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data.InventoryConfiguration === "") { + contents[_ICL] = []; + } else if (data[_IC] != null) { + contents[_ICL] = de_InventoryConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_IC]), context); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketInventoryConfigurationsCommand"); +var de_ListBucketMetricsConfigurationsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data.MetricsConfiguration === "") { + contents[_MCL] = []; + } else if (data[_MC] != null) { + contents[_MCL] = de_MetricsConfigurationList((0, import_smithy_client.getArrayIfSingleItem)(data[_MC]), context); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + return contents; +}, "de_ListBucketMetricsConfigurationsCommand"); +var de_ListBucketsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Buckets === "") { + contents[_Bu] = []; + } else if (data[_Bu] != null && data[_Bu][_B] != null) { + contents[_Bu] = de_Buckets((0, import_smithy_client.getArrayIfSingleItem)(data[_Bu][_B]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + return contents; +}, "de_ListBucketsCommand"); +var de_ListDirectoryBucketsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.Buckets === "") { + contents[_Bu] = []; + } else if (data[_Bu] != null && data[_Bu][_B] != null) { + contents[_Bu] = de_Buckets((0, import_smithy_client.getArrayIfSingleItem)(data[_Bu][_B]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + return contents; +}, "de_ListDirectoryBucketsCommand"); +var de_ListMultipartUploadsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_KM] != null) { + contents[_KM] = (0, import_smithy_client.expectString)(data[_KM]); + } + if (data[_MU] != null) { + contents[_MU] = (0, import_smithy_client.strictParseInt32)(data[_MU]); + } + if (data[_NKM] != null) { + contents[_NKM] = (0, import_smithy_client.expectString)(data[_NKM]); + } + if (data[_NUIM] != null) { + contents[_NUIM] = (0, import_smithy_client.expectString)(data[_NUIM]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + if (data[_UIM] != null) { + contents[_UIM] = (0, import_smithy_client.expectString)(data[_UIM]); + } + if (data.Upload === "") { + contents[_Up] = []; + } else if (data[_U] != null) { + contents[_Up] = de_MultipartUploadList((0, import_smithy_client.getArrayIfSingleItem)(data[_U]), context); + } + return contents; +}, "de_ListMultipartUploadsCommand"); +var de_ListObjectsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data.Contents === "") { + contents[_Co] = []; + } else if (data[_Co] != null) { + contents[_Co] = de_ObjectList((0, import_smithy_client.getArrayIfSingleItem)(data[_Co]), context); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_M] != null) { + contents[_M] = (0, import_smithy_client.expectString)(data[_M]); + } + if (data[_MK] != null) { + contents[_MK] = (0, import_smithy_client.strictParseInt32)(data[_MK]); + } + if (data[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(data[_N]); + } + if (data[_NM] != null) { + contents[_NM] = (0, import_smithy_client.expectString)(data[_NM]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + return contents; +}, "de_ListObjectsCommand"); +var de_ListObjectsV2Command = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data.Contents === "") { + contents[_Co] = []; + } else if (data[_Co] != null) { + contents[_Co] = de_ObjectList((0, import_smithy_client.getArrayIfSingleItem)(data[_Co]), context); + } + if (data[_CTon] != null) { + contents[_CTon] = (0, import_smithy_client.expectString)(data[_CTon]); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_KC] != null) { + contents[_KC] = (0, import_smithy_client.strictParseInt32)(data[_KC]); + } + if (data[_MK] != null) { + contents[_MK] = (0, import_smithy_client.strictParseInt32)(data[_MK]); + } + if (data[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(data[_N]); + } + if (data[_NCT] != null) { + contents[_NCT] = (0, import_smithy_client.expectString)(data[_NCT]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + if (data[_SA] != null) { + contents[_SA] = (0, import_smithy_client.expectString)(data[_SA]); + } + return contents; +}, "de_ListObjectsV2Command"); +var de_ListObjectVersionsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data.CommonPrefixes === "") { + contents[_CP] = []; + } else if (data[_CP] != null) { + contents[_CP] = de_CommonPrefixList((0, import_smithy_client.getArrayIfSingleItem)(data[_CP]), context); + } + if (data.DeleteMarker === "") { + contents[_DMe] = []; + } else if (data[_DM] != null) { + contents[_DMe] = de_DeleteMarkers((0, import_smithy_client.getArrayIfSingleItem)(data[_DM]), context); + } + if (data[_D] != null) { + contents[_D] = (0, import_smithy_client.expectString)(data[_D]); + } + if (data[_ET] != null) { + contents[_ET] = (0, import_smithy_client.expectString)(data[_ET]); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_KM] != null) { + contents[_KM] = (0, import_smithy_client.expectString)(data[_KM]); + } + if (data[_MK] != null) { + contents[_MK] = (0, import_smithy_client.strictParseInt32)(data[_MK]); + } + if (data[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(data[_N]); + } + if (data[_NKM] != null) { + contents[_NKM] = (0, import_smithy_client.expectString)(data[_NKM]); + } + if (data[_NVIM] != null) { + contents[_NVIM] = (0, import_smithy_client.expectString)(data[_NVIM]); + } + if (data[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(data[_P]); + } + if (data[_VIM] != null) { + contents[_VIM] = (0, import_smithy_client.expectString)(data[_VIM]); + } + if (data.Version === "") { + contents[_Ve] = []; + } else if (data[_V] != null) { + contents[_Ve] = de_ObjectVersionList((0, import_smithy_client.getArrayIfSingleItem)(data[_V]), context); + } + return contents; +}, "de_ListObjectVersionsCommand"); +var de_ListPartsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_AD]: [ + () => void 0 !== output.headers[_xaad], + () => (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc7231DateTime)(output.headers[_xaad])) + ], + [_ARI]: [, output.headers[_xaari]], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)), "body"); + if (data[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(data[_B]); + } + if (data[_CA] != null) { + contents[_CA] = (0, import_smithy_client.expectString)(data[_CA]); + } + if (data[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(data[_CT]); + } + if (data[_In] != null) { + contents[_In] = de_Initiator(data[_In], context); + } + if (data[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(data[_IT]); + } + if (data[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(data[_K]); + } + if (data[_MP] != null) { + contents[_MP] = (0, import_smithy_client.strictParseInt32)(data[_MP]); + } + if (data[_NPNM] != null) { + contents[_NPNM] = (0, import_smithy_client.expectString)(data[_NPNM]); + } + if (data[_O] != null) { + contents[_O] = de_Owner(data[_O], context); + } + if (data[_PNM] != null) { + contents[_PNM] = (0, import_smithy_client.expectString)(data[_PNM]); + } + if (data.Part === "") { + contents[_Part] = []; + } else if (data[_Par] != null) { + contents[_Part] = de_Parts((0, import_smithy_client.getArrayIfSingleItem)(data[_Par]), context); + } + if (data[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(data[_SC]); + } + if (data[_UI] != null) { + contents[_UI] = (0, import_smithy_client.expectString)(data[_UI]); + } + return contents; +}, "de_ListPartsCommand"); +var de_PutBucketAccelerateConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketAccelerateConfigurationCommand"); +var de_PutBucketAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketAclCommand"); +var de_PutBucketAnalyticsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketAnalyticsConfigurationCommand"); +var de_PutBucketCorsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketCorsCommand"); +var de_PutBucketEncryptionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketEncryptionCommand"); +var de_PutBucketIntelligentTieringConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketIntelligentTieringConfigurationCommand"); +var de_PutBucketInventoryConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketInventoryConfigurationCommand"); +var de_PutBucketLifecycleConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_TDMOS]: [, output.headers[_xatdmos]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketLifecycleConfigurationCommand"); +var de_PutBucketLoggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketLoggingCommand"); +var de_PutBucketMetricsConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketMetricsConfigurationCommand"); +var de_PutBucketNotificationConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketNotificationConfigurationCommand"); +var de_PutBucketOwnershipControlsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketOwnershipControlsCommand"); +var de_PutBucketPolicyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketPolicyCommand"); +var de_PutBucketReplicationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketReplicationCommand"); +var de_PutBucketRequestPaymentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketRequestPaymentCommand"); +var de_PutBucketTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketTaggingCommand"); +var de_PutBucketVersioningCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketVersioningCommand"); +var de_PutBucketWebsiteCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutBucketWebsiteCommand"); +var de_PutObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_Exp]: [, output.headers[_xae]], + [_ETa]: [, output.headers[_eta]], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_CT]: [, output.headers[_xact]], + [_SSE]: [, output.headers[_xasse]], + [_VI]: [, output.headers[_xavi]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_SSEKMSEC]: [, output.headers[_xassec]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_Si]: [() => void 0 !== output.headers[_xaos], () => (0, import_smithy_client.strictParseLong)(output.headers[_xaos])], + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectCommand"); +var de_PutObjectAclCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectAclCommand"); +var de_PutObjectLegalHoldCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectLegalHoldCommand"); +var de_PutObjectLockConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectLockConfigurationCommand"); +var de_PutObjectRetentionCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectRetentionCommand"); +var de_PutObjectTaggingCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_VI]: [, output.headers[_xavi]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutObjectTaggingCommand"); +var de_PutPublicAccessBlockCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_PutPublicAccessBlockCommand"); +var de_RenameObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_RenameObjectCommand"); +var de_RestoreObjectCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_RC]: [, output.headers[_xarc]], + [_ROP]: [, output.headers[_xarop]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_RestoreObjectCommand"); +var de_SelectObjectContentCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = output.body; + contents.Payload = de_SelectObjectContentEventStream(data, context); + return contents; +}, "de_SelectObjectContentCommand"); +var de_UpdateBucketMetadataInventoryTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_UpdateBucketMetadataInventoryTableConfigurationCommand"); +var de_UpdateBucketMetadataJournalTableConfigurationCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_UpdateBucketMetadataJournalTableConfigurationCommand"); +var de_UploadPartCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_SSE]: [, output.headers[_xasse]], + [_ETa]: [, output.headers[_eta]], + [_CCRC]: [, output.headers[_xacc]], + [_CCRCC]: [, output.headers[_xacc_]], + [_CCRCNVME]: [, output.headers[_xacc__]], + [_CSHA]: [, output.headers[_xacs]], + [_CSHAh]: [, output.headers[_xacs_]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_UploadPartCommand"); +var de_UploadPartCopyCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output), + [_CSVI]: [, output.headers[_xacsvi]], + [_SSE]: [, output.headers[_xasse]], + [_SSECA]: [, output.headers[_xasseca]], + [_SSECKMD]: [, output.headers[_xasseckm]], + [_SSEKMSKI]: [, output.headers[_xasseakki]], + [_BKE]: [() => void 0 !== output.headers[_xassebke], () => (0, import_smithy_client.parseBoolean)(output.headers[_xassebke])], + [_RC]: [, output.headers[_xarc]] + }); + const data = (0, import_smithy_client.expectObject)(await (0, import_core.parseXmlBody)(output.body, context)); + contents.CopyPartResult = de_CopyPartResult(data, context); + return contents; +}, "de_UploadPartCopyCommand"); +var de_WriteGetObjectResponseCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_WriteGetObjectResponseCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core.parseXmlErrorBody)(output.body, context) + }; + const errorCode = (0, import_core.loadRestXmlErrorCode)(output, parsedOutput.body); + switch (errorCode) { + case "NoSuchUpload": + case "com.amazonaws.s3#NoSuchUpload": + throw await de_NoSuchUploadRes(parsedOutput, context); + case "ObjectNotInActiveTierError": + case "com.amazonaws.s3#ObjectNotInActiveTierError": + throw await de_ObjectNotInActiveTierErrorRes(parsedOutput, context); + case "BucketAlreadyExists": + case "com.amazonaws.s3#BucketAlreadyExists": + throw await de_BucketAlreadyExistsRes(parsedOutput, context); + case "BucketAlreadyOwnedByYou": + case "com.amazonaws.s3#BucketAlreadyOwnedByYou": + throw await de_BucketAlreadyOwnedByYouRes(parsedOutput, context); + case "NoSuchBucket": + case "com.amazonaws.s3#NoSuchBucket": + throw await de_NoSuchBucketRes(parsedOutput, context); + case "InvalidObjectState": + case "com.amazonaws.s3#InvalidObjectState": + throw await de_InvalidObjectStateRes(parsedOutput, context); + case "NoSuchKey": + case "com.amazonaws.s3#NoSuchKey": + throw await de_NoSuchKeyRes(parsedOutput, context); + case "NotFound": + case "com.amazonaws.s3#NotFound": + throw await de_NotFoundRes(parsedOutput, context); + case "EncryptionTypeMismatch": + case "com.amazonaws.s3#EncryptionTypeMismatch": + throw await de_EncryptionTypeMismatchRes(parsedOutput, context); + case "InvalidRequest": + case "com.amazonaws.s3#InvalidRequest": + throw await de_InvalidRequestRes(parsedOutput, context); + case "InvalidWriteOffset": + case "com.amazonaws.s3#InvalidWriteOffset": + throw await de_InvalidWriteOffsetRes(parsedOutput, context); + case "TooManyParts": + case "com.amazonaws.s3#TooManyParts": + throw await de_TooManyPartsRes(parsedOutput, context); + case "IdempotencyParameterMismatch": + case "com.amazonaws.s3#IdempotencyParameterMismatch": + throw await de_IdempotencyParameterMismatchRes(parsedOutput, context); + case "ObjectAlreadyInActiveTierError": + case "com.amazonaws.s3#ObjectAlreadyInActiveTierError": + throw await de_ObjectAlreadyInActiveTierErrorRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody, + errorCode + }); + } +}, "de_CommandError"); +var throwDefaultError = (0, import_smithy_client.withBaseException)(S3ServiceException); +var de_BucketAlreadyExistsRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new BucketAlreadyExists({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_BucketAlreadyExistsRes"); +var de_BucketAlreadyOwnedByYouRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new BucketAlreadyOwnedByYou({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_BucketAlreadyOwnedByYouRes"); +var de_EncryptionTypeMismatchRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new EncryptionTypeMismatch({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_EncryptionTypeMismatchRes"); +var de_IdempotencyParameterMismatchRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new IdempotencyParameterMismatch({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_IdempotencyParameterMismatchRes"); +var de_InvalidObjectStateRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + if (data[_AT] != null) { + contents[_AT] = (0, import_smithy_client.expectString)(data[_AT]); + } + if (data[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(data[_SC]); + } + const exception = new InvalidObjectState({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidObjectStateRes"); +var de_InvalidRequestRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new InvalidRequest({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidRequestRes"); +var de_InvalidWriteOffsetRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new InvalidWriteOffset({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidWriteOffsetRes"); +var de_NoSuchBucketRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NoSuchBucket({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NoSuchBucketRes"); +var de_NoSuchKeyRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NoSuchKey({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NoSuchKeyRes"); +var de_NoSuchUploadRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NoSuchUpload({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NoSuchUploadRes"); +var de_NotFoundRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new NotFound({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_NotFoundRes"); +var de_ObjectAlreadyInActiveTierErrorRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new ObjectAlreadyInActiveTierError({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_ObjectAlreadyInActiveTierErrorRes"); +var de_ObjectNotInActiveTierErrorRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new ObjectNotInActiveTierError({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_ObjectNotInActiveTierErrorRes"); +var de_TooManyPartsRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const exception = new TooManyParts({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_TooManyPartsRes"); +var de_SelectObjectContentEventStream = /* @__PURE__ */ __name((output, context) => { + return context.eventStreamMarshaller.deserialize(output, async (event) => { + if (event["Records"] != null) { + return { + Records: await de_RecordsEvent_event(event["Records"], context) + }; + } + if (event["Stats"] != null) { + return { + Stats: await de_StatsEvent_event(event["Stats"], context) + }; + } + if (event["Progress"] != null) { + return { + Progress: await de_ProgressEvent_event(event["Progress"], context) + }; + } + if (event["Cont"] != null) { + return { + Cont: await de_ContinuationEvent_event(event["Cont"], context) + }; + } + if (event["End"] != null) { + return { + End: await de_EndEvent_event(event["End"], context) + }; + } + return { $unknown: event }; + }); +}, "de_SelectObjectContentEventStream"); +var de_ContinuationEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + Object.assign(contents, de_ContinuationEvent(data, context)); + return contents; +}, "de_ContinuationEvent_event"); +var de_EndEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + Object.assign(contents, de_EndEvent(data, context)); + return contents; +}, "de_EndEvent_event"); +var de_ProgressEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + contents.Details = de_Progress(data, context); + return contents; +}, "de_ProgressEvent_event"); +var de_RecordsEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + contents.Payload = output.body; + return contents; +}, "de_RecordsEvent_event"); +var de_StatsEvent_event = /* @__PURE__ */ __name(async (output, context) => { + const contents = {}; + const data = await (0, import_core.parseXmlBody)(output.body, context); + contents.Details = de_Stats(data, context); + return contents; +}, "de_StatsEvent_event"); +var se_AbortIncompleteMultipartUpload = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AIMU); + if (input[_DAI] != null) { + bn.c(import_xml_builder.XmlNode.of(_DAI, String(input[_DAI])).n(_DAI)); + } + return bn; +}, "se_AbortIncompleteMultipartUpload"); +var se_AccelerateConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ACc); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_BAS, input[_S]).n(_S)); + } + return bn; +}, "se_AccelerateConfiguration"); +var se_AccessControlPolicy = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ACP); + bn.lc(input, "Grants", "AccessControlList", () => se_Grants(input[_Gr], context)); + if (input[_O] != null) { + bn.c(se_Owner(input[_O], context).n(_O)); + } + return bn; +}, "se_AccessControlPolicy"); +var se_AccessControlTranslation = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ACT); + if (input[_O] != null) { + bn.c(import_xml_builder.XmlNode.of(_OOw, input[_O]).n(_O)); + } + return bn; +}, "se_AccessControlTranslation"); +var se_AllowedHeaders = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_AH, entry); + return n.n(_me); + }); +}, "se_AllowedHeaders"); +var se_AllowedMethods = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_AM, entry); + return n.n(_me); + }); +}, "se_AllowedMethods"); +var se_AllowedOrigins = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_AO, entry); + return n.n(_me); + }); +}, "se_AllowedOrigins"); +var se_AnalyticsAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_AnalyticsAndOperator"); +var se_AnalyticsConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_AI, input[_I]).n(_I)); + } + if (input[_F] != null) { + bn.c(se_AnalyticsFilter(input[_F], context).n(_F)); + } + if (input[_SCA] != null) { + bn.c(se_StorageClassAnalysis(input[_SCA], context).n(_SCA)); + } + return bn; +}, "se_AnalyticsConfiguration"); +var se_AnalyticsExportDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AED); + if (input[_SBD] != null) { + bn.c(se_AnalyticsS3BucketDestination(input[_SBD], context).n(_SBD)); + } + return bn; +}, "se_AnalyticsExportDestination"); +var se_AnalyticsFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_AF); + AnalyticsFilter.visit(input, { + Prefix: /* @__PURE__ */ __name((value) => { + if (input[_P] != null) { + bn.c(import_xml_builder.XmlNode.of(_P, value).n(_P)); + } + }, "Prefix"), + Tag: /* @__PURE__ */ __name((value) => { + if (input[_Ta] != null) { + bn.c(se_Tag(value, context).n(_Ta)); + } + }, "Tag"), + And: /* @__PURE__ */ __name((value) => { + if (input[_A] != null) { + bn.c(se_AnalyticsAndOperator(value, context).n(_A)); + } + }, "And"), + _: /* @__PURE__ */ __name((name, value) => { + if (!(value instanceof import_xml_builder.XmlNode || value instanceof import_xml_builder.XmlText)) { + throw new Error("Unable to serialize unknown union members in XML."); + } + bn.c(new import_xml_builder.XmlNode(name).c(value)); + }, "_") + }); + return bn; +}, "se_AnalyticsFilter"); +var se_AnalyticsS3BucketDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ASBD); + if (input[_Fo] != null) { + bn.c(import_xml_builder.XmlNode.of(_ASEFF, input[_Fo]).n(_Fo)); + } + if (input[_BAI] != null) { + bn.c(import_xml_builder.XmlNode.of(_AIc, input[_BAI]).n(_BAI)); + } + if (input[_B] != null) { + bn.c(import_xml_builder.XmlNode.of(_BN, input[_B]).n(_B)); + } + bn.cc(input, _P); + return bn; +}, "se_AnalyticsS3BucketDestination"); +var se_BucketInfo = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_BI); + bn.cc(input, _DR); + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_BT, input[_Ty]).n(_Ty)); + } + return bn; +}, "se_BucketInfo"); +var se_BucketLifecycleConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_BLC); + bn.l(input, "Rules", "Rule", () => se_LifecycleRules(input[_Rul], context)); + return bn; +}, "se_BucketLifecycleConfiguration"); +var se_BucketLoggingStatus = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_BLS); + if (input[_LE] != null) { + bn.c(se_LoggingEnabled(input[_LE], context).n(_LE)); + } + return bn; +}, "se_BucketLoggingStatus"); +var se_CompletedMultipartUpload = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CMU); + bn.l(input, "Parts", "Part", () => se_CompletedPartList(input[_Part], context)); + return bn; +}, "se_CompletedMultipartUpload"); +var se_CompletedPart = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CPo); + bn.cc(input, _ETa); + bn.cc(input, _CCRC); + bn.cc(input, _CCRCC); + bn.cc(input, _CCRCNVME); + bn.cc(input, _CSHA); + bn.cc(input, _CSHAh); + if (input[_PN] != null) { + bn.c(import_xml_builder.XmlNode.of(_PN, String(input[_PN])).n(_PN)); + } + return bn; +}, "se_CompletedPart"); +var se_CompletedPartList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_CompletedPart(entry, context); + return n.n(_me); + }); +}, "se_CompletedPartList"); +var se_Condition = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Con); + bn.cc(input, _HECRE); + bn.cc(input, _KPE); + return bn; +}, "se_Condition"); +var se_CORSConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CORSC); + bn.l(input, "CORSRules", "CORSRule", () => se_CORSRules(input[_CORSRu], context)); + return bn; +}, "se_CORSConfiguration"); +var se_CORSRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CORSR); + bn.cc(input, _ID_); + bn.l(input, "AllowedHeaders", "AllowedHeader", () => se_AllowedHeaders(input[_AHl], context)); + bn.l(input, "AllowedMethods", "AllowedMethod", () => se_AllowedMethods(input[_AMl], context)); + bn.l(input, "AllowedOrigins", "AllowedOrigin", () => se_AllowedOrigins(input[_AOl], context)); + bn.l(input, "ExposeHeaders", "ExposeHeader", () => se_ExposeHeaders(input[_EH], context)); + if (input[_MAS] != null) { + bn.c(import_xml_builder.XmlNode.of(_MAS, String(input[_MAS])).n(_MAS)); + } + return bn; +}, "se_CORSRule"); +var se_CORSRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_CORSRule(entry, context); + return n.n(_me); + }); +}, "se_CORSRules"); +var se_CreateBucketConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CBC); + if (input[_LC] != null) { + bn.c(import_xml_builder.XmlNode.of(_BLCu, input[_LC]).n(_LC)); + } + if (input[_L] != null) { + bn.c(se_LocationInfo(input[_L], context).n(_L)); + } + if (input[_B] != null) { + bn.c(se_BucketInfo(input[_B], context).n(_B)); + } + bn.lc(input, "Tags", "Tags", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_CreateBucketConfiguration"); +var se_CSVInput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CSVIn); + bn.cc(input, _FHI); + bn.cc(input, _Com); + bn.cc(input, _QEC); + bn.cc(input, _RD); + bn.cc(input, _FD); + bn.cc(input, _QCuo); + if (input[_AQRD] != null) { + bn.c(import_xml_builder.XmlNode.of(_AQRD, String(input[_AQRD])).n(_AQRD)); + } + return bn; +}, "se_CSVInput"); +var se_CSVOutput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_CSVO); + bn.cc(input, _QF); + bn.cc(input, _QEC); + bn.cc(input, _RD); + bn.cc(input, _FD); + bn.cc(input, _QCuo); + return bn; +}, "se_CSVOutput"); +var se_DefaultRetention = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_DRe); + if (input[_Mo] != null) { + bn.c(import_xml_builder.XmlNode.of(_OLRM, input[_Mo]).n(_Mo)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_Y] != null) { + bn.c(import_xml_builder.XmlNode.of(_Y, String(input[_Y])).n(_Y)); + } + return bn; +}, "se_DefaultRetention"); +var se_Delete = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Del); + bn.l(input, "Objects", "Object", () => se_ObjectIdentifierList(input[_Ob], context)); + if (input[_Q] != null) { + bn.c(import_xml_builder.XmlNode.of(_Q, String(input[_Q])).n(_Q)); + } + return bn; +}, "se_Delete"); +var se_DeleteMarkerReplication = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_DMR); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_DMRS, input[_S]).n(_S)); + } + return bn; +}, "se_DeleteMarkerReplication"); +var se_Destination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Des); + if (input[_B] != null) { + bn.c(import_xml_builder.XmlNode.of(_BN, input[_B]).n(_B)); + } + if (input[_Ac] != null) { + bn.c(import_xml_builder.XmlNode.of(_AIc, input[_Ac]).n(_Ac)); + } + bn.cc(input, _SC); + if (input[_ACT] != null) { + bn.c(se_AccessControlTranslation(input[_ACT], context).n(_ACT)); + } + if (input[_ECn] != null) { + bn.c(se_EncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + if (input[_RTe] != null) { + bn.c(se_ReplicationTime(input[_RTe], context).n(_RTe)); + } + if (input[_Me] != null) { + bn.c(se_Metrics(input[_Me], context).n(_Me)); + } + return bn; +}, "se_Destination"); +var se_Encryption = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_En); + if (input[_ETn] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSE, input[_ETn]).n(_ETn)); + } + if (input[_KMSKI] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSEKMSKI, input[_KMSKI]).n(_KMSKI)); + } + bn.cc(input, _KMSC); + return bn; +}, "se_Encryption"); +var se_EncryptionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ECn); + bn.cc(input, _RKKID); + return bn; +}, "se_EncryptionConfiguration"); +var se_ErrorDocument = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ED); + if (input[_K] != null) { + bn.c(import_xml_builder.XmlNode.of(_OK, input[_K]).n(_K)); + } + return bn; +}, "se_ErrorDocument"); +var se_EventBridgeConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_EBC); + return bn; +}, "se_EventBridgeConfiguration"); +var se_EventList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_Ev, entry); + return n.n(_me); + }); +}, "se_EventList"); +var se_ExistingObjectReplication = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_EOR); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_EORS, input[_S]).n(_S)); + } + return bn; +}, "se_ExistingObjectReplication"); +var se_ExposeHeaders = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_EHx, entry); + return n.n(_me); + }); +}, "se_ExposeHeaders"); +var se_FilterRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_FR); + if (input[_N] != null) { + bn.c(import_xml_builder.XmlNode.of(_FRN, input[_N]).n(_N)); + } + if (input[_Va] != null) { + bn.c(import_xml_builder.XmlNode.of(_FRV, input[_Va]).n(_Va)); + } + return bn; +}, "se_FilterRule"); +var se_FilterRuleList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_FilterRule(entry, context); + return n.n(_me); + }); +}, "se_FilterRuleList"); +var se_GlacierJobParameters = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_GJP); + bn.cc(input, _Ti); + return bn; +}, "se_GlacierJobParameters"); +var se_Grant = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_G); + if (input[_Gra] != null) { + const n = se_Grantee(input[_Gra], context).n(_Gra); + n.a("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + bn.c(n); + } + bn.cc(input, _Pe); + return bn; +}, "se_Grant"); +var se_Grantee = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Gra); + bn.cc(input, _DN); + bn.cc(input, _EA); + bn.cc(input, _ID_); + bn.cc(input, _URI); + bn.a("xsi:type", input[_Ty]); + return bn; +}, "se_Grantee"); +var se_Grants = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Grant(entry, context); + return n.n(_G); + }); +}, "se_Grants"); +var se_IndexDocument = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ID); + bn.cc(input, _Su); + return bn; +}, "se_IndexDocument"); +var se_InputSerialization = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IS); + if (input[_CSV] != null) { + bn.c(se_CSVInput(input[_CSV], context).n(_CSV)); + } + bn.cc(input, _CTom); + if (input[_JSON] != null) { + bn.c(se_JSONInput(input[_JSON], context).n(_JSON)); + } + if (input[_Parq] != null) { + bn.c(se_ParquetInput(input[_Parq], context).n(_Parq)); + } + return bn; +}, "se_InputSerialization"); +var se_IntelligentTieringAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_IntelligentTieringAndOperator"); +var se_IntelligentTieringConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITI, input[_I]).n(_I)); + } + if (input[_F] != null) { + bn.c(se_IntelligentTieringFilter(input[_F], context).n(_F)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITS, input[_S]).n(_S)); + } + bn.l(input, "Tierings", "Tiering", () => se_TieringList(input[_Tie], context)); + return bn; +}, "se_IntelligentTieringConfiguration"); +var se_IntelligentTieringFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITF); + bn.cc(input, _P); + if (input[_Ta] != null) { + bn.c(se_Tag(input[_Ta], context).n(_Ta)); + } + if (input[_A] != null) { + bn.c(se_IntelligentTieringAndOperator(input[_A], context).n(_A)); + } + return bn; +}, "se_IntelligentTieringFilter"); +var se_InventoryConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IC); + if (input[_Des] != null) { + bn.c(se_InventoryDestination(input[_Des], context).n(_Des)); + } + if (input[_IE] != null) { + bn.c(import_xml_builder.XmlNode.of(_IE, String(input[_IE])).n(_IE)); + } + if (input[_F] != null) { + bn.c(se_InventoryFilter(input[_F], context).n(_F)); + } + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_II, input[_I]).n(_I)); + } + if (input[_IOV] != null) { + bn.c(import_xml_builder.XmlNode.of(_IIOV, input[_IOV]).n(_IOV)); + } + bn.lc(input, "OptionalFields", "OptionalFields", () => se_InventoryOptionalFields(input[_OF], context)); + if (input[_Sc] != null) { + bn.c(se_InventorySchedule(input[_Sc], context).n(_Sc)); + } + return bn; +}, "se_InventoryConfiguration"); +var se_InventoryDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IDn); + if (input[_SBD] != null) { + bn.c(se_InventoryS3BucketDestination(input[_SBD], context).n(_SBD)); + } + return bn; +}, "se_InventoryDestination"); +var se_InventoryEncryption = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IEn); + if (input[_SSES] != null) { + bn.c(se_SSES3(input[_SSES], context).n(_SS)); + } + if (input[_SSEKMS] != null) { + bn.c(se_SSEKMS(input[_SSEKMS], context).n(_SK)); + } + return bn; +}, "se_InventoryEncryption"); +var se_InventoryFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_IF); + bn.cc(input, _P); + return bn; +}, "se_InventoryFilter"); +var se_InventoryOptionalFields = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = import_xml_builder.XmlNode.of(_IOF, entry); + return n.n(_Fi); + }); +}, "se_InventoryOptionalFields"); +var se_InventoryS3BucketDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ISBD); + bn.cc(input, _AIc); + if (input[_B] != null) { + bn.c(import_xml_builder.XmlNode.of(_BN, input[_B]).n(_B)); + } + if (input[_Fo] != null) { + bn.c(import_xml_builder.XmlNode.of(_IFn, input[_Fo]).n(_Fo)); + } + bn.cc(input, _P); + if (input[_En] != null) { + bn.c(se_InventoryEncryption(input[_En], context).n(_En)); + } + return bn; +}, "se_InventoryS3BucketDestination"); +var se_InventorySchedule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ISn); + if (input[_Fr] != null) { + bn.c(import_xml_builder.XmlNode.of(_IFnv, input[_Fr]).n(_Fr)); + } + return bn; +}, "se_InventorySchedule"); +var se_InventoryTableConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITCn); + if (input[_CSo] != null) { + bn.c(import_xml_builder.XmlNode.of(_ICS, input[_CSo]).n(_CSo)); + } + if (input[_ECn] != null) { + bn.c(se_MetadataTableEncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + return bn; +}, "se_InventoryTableConfiguration"); +var se_InventoryTableConfigurationUpdates = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ITCU); + if (input[_CSo] != null) { + bn.c(import_xml_builder.XmlNode.of(_ICS, input[_CSo]).n(_CSo)); + } + if (input[_ECn] != null) { + bn.c(se_MetadataTableEncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + return bn; +}, "se_InventoryTableConfigurationUpdates"); +var se_JournalTableConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JTC); + if (input[_REe] != null) { + bn.c(se_RecordExpiration(input[_REe], context).n(_REe)); + } + if (input[_ECn] != null) { + bn.c(se_MetadataTableEncryptionConfiguration(input[_ECn], context).n(_ECn)); + } + return bn; +}, "se_JournalTableConfiguration"); +var se_JournalTableConfigurationUpdates = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JTCU); + if (input[_REe] != null) { + bn.c(se_RecordExpiration(input[_REe], context).n(_REe)); + } + return bn; +}, "se_JournalTableConfigurationUpdates"); +var se_JSONInput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JSONI); + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_JSONT, input[_Ty]).n(_Ty)); + } + return bn; +}, "se_JSONInput"); +var se_JSONOutput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_JSONO); + bn.cc(input, _RD); + return bn; +}, "se_JSONOutput"); +var se_LambdaFunctionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LFCa); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_NI, input[_I]).n(_I)); + } + if (input[_LFA] != null) { + bn.c(import_xml_builder.XmlNode.of(_LFA, input[_LFA]).n(_CF)); + } + bn.l(input, "Events", "Event", () => se_EventList(input[_Eve], context)); + if (input[_F] != null) { + bn.c(se_NotificationConfigurationFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_LambdaFunctionConfiguration"); +var se_LambdaFunctionConfigurationList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_LambdaFunctionConfiguration(entry, context); + return n.n(_me); + }); +}, "se_LambdaFunctionConfigurationList"); +var se_LifecycleExpiration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LEi); + if (input[_Dat] != null) { + bn.c(import_xml_builder.XmlNode.of(_Dat, (0, import_smithy_client.serializeDateTime)(input[_Dat]).toString()).n(_Dat)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_EODM] != null) { + bn.c(import_xml_builder.XmlNode.of(_EODM, String(input[_EODM])).n(_EODM)); + } + return bn; +}, "se_LifecycleExpiration"); +var se_LifecycleRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LR); + if (input[_Exp] != null) { + bn.c(se_LifecycleExpiration(input[_Exp], context).n(_Exp)); + } + bn.cc(input, _ID_); + bn.cc(input, _P); + if (input[_F] != null) { + bn.c(se_LifecycleRuleFilter(input[_F], context).n(_F)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_ESx, input[_S]).n(_S)); + } + bn.l(input, "Transitions", "Transition", () => se_TransitionList(input[_Tr], context)); + bn.l( + input, + "NoncurrentVersionTransitions", + "NoncurrentVersionTransition", + () => se_NoncurrentVersionTransitionList(input[_NVT], context) + ); + if (input[_NVE] != null) { + bn.c(se_NoncurrentVersionExpiration(input[_NVE], context).n(_NVE)); + } + if (input[_AIMU] != null) { + bn.c(se_AbortIncompleteMultipartUpload(input[_AIMU], context).n(_AIMU)); + } + return bn; +}, "se_LifecycleRule"); +var se_LifecycleRuleAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LRAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + if (input[_OSGT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSGTB, String(input[_OSGT])).n(_OSGT)); + } + if (input[_OSLT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSLTB, String(input[_OSLT])).n(_OSLT)); + } + return bn; +}, "se_LifecycleRuleAndOperator"); +var se_LifecycleRuleFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LRF); + bn.cc(input, _P); + if (input[_Ta] != null) { + bn.c(se_Tag(input[_Ta], context).n(_Ta)); + } + if (input[_OSGT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSGTB, String(input[_OSGT])).n(_OSGT)); + } + if (input[_OSLT] != null) { + bn.c(import_xml_builder.XmlNode.of(_OSLTB, String(input[_OSLT])).n(_OSLT)); + } + if (input[_A] != null) { + bn.c(se_LifecycleRuleAndOperator(input[_A], context).n(_A)); + } + return bn; +}, "se_LifecycleRuleFilter"); +var se_LifecycleRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_LifecycleRule(entry, context); + return n.n(_me); + }); +}, "se_LifecycleRules"); +var se_LocationInfo = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LI); + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_LT, input[_Ty]).n(_Ty)); + } + if (input[_N] != null) { + bn.c(import_xml_builder.XmlNode.of(_LNAS, input[_N]).n(_N)); + } + return bn; +}, "se_LocationInfo"); +var se_LoggingEnabled = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_LE); + bn.cc(input, _TB); + bn.lc(input, "TargetGrants", "TargetGrants", () => se_TargetGrants(input[_TG], context)); + bn.cc(input, _TP); + if (input[_TOKF] != null) { + bn.c(se_TargetObjectKeyFormat(input[_TOKF], context).n(_TOKF)); + } + return bn; +}, "se_LoggingEnabled"); +var se_MetadataConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MCe); + if (input[_JTC] != null) { + bn.c(se_JournalTableConfiguration(input[_JTC], context).n(_JTC)); + } + if (input[_ITCn] != null) { + bn.c(se_InventoryTableConfiguration(input[_ITCn], context).n(_ITCn)); + } + return bn; +}, "se_MetadataConfiguration"); +var se_MetadataEntry = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_ME); + if (input[_N] != null) { + bn.c(import_xml_builder.XmlNode.of(_MKe, input[_N]).n(_N)); + } + if (input[_Va] != null) { + bn.c(import_xml_builder.XmlNode.of(_MV, input[_Va]).n(_Va)); + } + return bn; +}, "se_MetadataEntry"); +var se_MetadataTableConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MTC); + if (input[_STD] != null) { + bn.c(se_S3TablesDestination(input[_STD], context).n(_STD)); + } + return bn; +}, "se_MetadataTableConfiguration"); +var se_MetadataTableEncryptionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MTEC); + if (input[_SAs] != null) { + bn.c(import_xml_builder.XmlNode.of(_TSA, input[_SAs]).n(_SAs)); + } + bn.cc(input, _KKA); + return bn; +}, "se_MetadataTableEncryptionConfiguration"); +var se_Metrics = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Me); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_MS, input[_S]).n(_S)); + } + if (input[_ETv] != null) { + bn.c(se_ReplicationTimeValue(input[_ETv], context).n(_ETv)); + } + return bn; +}, "se_Metrics"); +var se_MetricsAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + bn.cc(input, _APAc); + return bn; +}, "se_MetricsAndOperator"); +var se_MetricsConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_MI, input[_I]).n(_I)); + } + if (input[_F] != null) { + bn.c(se_MetricsFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_MetricsConfiguration"); +var se_MetricsFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_MF); + MetricsFilter.visit(input, { + Prefix: /* @__PURE__ */ __name((value) => { + if (input[_P] != null) { + bn.c(import_xml_builder.XmlNode.of(_P, value).n(_P)); + } + }, "Prefix"), + Tag: /* @__PURE__ */ __name((value) => { + if (input[_Ta] != null) { + bn.c(se_Tag(value, context).n(_Ta)); + } + }, "Tag"), + AccessPointArn: /* @__PURE__ */ __name((value) => { + if (input[_APAc] != null) { + bn.c(import_xml_builder.XmlNode.of(_APAc, value).n(_APAc)); + } + }, "AccessPointArn"), + And: /* @__PURE__ */ __name((value) => { + if (input[_A] != null) { + bn.c(se_MetricsAndOperator(value, context).n(_A)); + } + }, "And"), + _: /* @__PURE__ */ __name((name, value) => { + if (!(value instanceof import_xml_builder.XmlNode || value instanceof import_xml_builder.XmlText)) { + throw new Error("Unable to serialize unknown union members in XML."); + } + bn.c(new import_xml_builder.XmlNode(name).c(value)); + }, "_") + }); + return bn; +}, "se_MetricsFilter"); +var se_NoncurrentVersionExpiration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NVE); + if (input[_ND] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_ND])).n(_ND)); + } + if (input[_NNV] != null) { + bn.c(import_xml_builder.XmlNode.of(_VC, String(input[_NNV])).n(_NNV)); + } + return bn; +}, "se_NoncurrentVersionExpiration"); +var se_NoncurrentVersionTransition = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NVTo); + if (input[_ND] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_ND])).n(_ND)); + } + if (input[_SC] != null) { + bn.c(import_xml_builder.XmlNode.of(_TSC, input[_SC]).n(_SC)); + } + if (input[_NNV] != null) { + bn.c(import_xml_builder.XmlNode.of(_VC, String(input[_NNV])).n(_NNV)); + } + return bn; +}, "se_NoncurrentVersionTransition"); +var se_NoncurrentVersionTransitionList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_NoncurrentVersionTransition(entry, context); + return n.n(_me); + }); +}, "se_NoncurrentVersionTransitionList"); +var se_NotificationConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NC); + bn.l(input, "TopicConfigurations", "TopicConfiguration", () => se_TopicConfigurationList(input[_TCop], context)); + bn.l(input, "QueueConfigurations", "QueueConfiguration", () => se_QueueConfigurationList(input[_QCu], context)); + bn.l( + input, + "LambdaFunctionConfigurations", + "CloudFunctionConfiguration", + () => se_LambdaFunctionConfigurationList(input[_LFC], context) + ); + if (input[_EBC] != null) { + bn.c(se_EventBridgeConfiguration(input[_EBC], context).n(_EBC)); + } + return bn; +}, "se_NotificationConfiguration"); +var se_NotificationConfigurationFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_NCF); + if (input[_K] != null) { + bn.c(se_S3KeyFilter(input[_K], context).n(_SKe)); + } + return bn; +}, "se_NotificationConfigurationFilter"); +var se_ObjectIdentifier = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OI); + if (input[_K] != null) { + bn.c(import_xml_builder.XmlNode.of(_OK, input[_K]).n(_K)); + } + if (input[_VI] != null) { + bn.c(import_xml_builder.XmlNode.of(_OVI, input[_VI]).n(_VI)); + } + bn.cc(input, _ETa); + if (input[_LMT] != null) { + bn.c(import_xml_builder.XmlNode.of(_LMT, (0, import_smithy_client.dateToUtcString)(input[_LMT]).toString()).n(_LMT)); + } + if (input[_Si] != null) { + bn.c(import_xml_builder.XmlNode.of(_Si, String(input[_Si])).n(_Si)); + } + return bn; +}, "se_ObjectIdentifier"); +var se_ObjectIdentifierList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_ObjectIdentifier(entry, context); + return n.n(_me); + }); +}, "se_ObjectIdentifierList"); +var se_ObjectLockConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLC); + bn.cc(input, _OLE); + if (input[_Ru] != null) { + bn.c(se_ObjectLockRule(input[_Ru], context).n(_Ru)); + } + return bn; +}, "se_ObjectLockConfiguration"); +var se_ObjectLockLegalHold = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLLH); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_OLLHS, input[_S]).n(_S)); + } + return bn; +}, "se_ObjectLockLegalHold"); +var se_ObjectLockRetention = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLR); + if (input[_Mo] != null) { + bn.c(import_xml_builder.XmlNode.of(_OLRM, input[_Mo]).n(_Mo)); + } + if (input[_RUD] != null) { + bn.c(import_xml_builder.XmlNode.of(_Dat, (0, import_smithy_client.serializeDateTime)(input[_RUD]).toString()).n(_RUD)); + } + return bn; +}, "se_ObjectLockRetention"); +var se_ObjectLockRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OLRb); + if (input[_DRe] != null) { + bn.c(se_DefaultRetention(input[_DRe], context).n(_DRe)); + } + return bn; +}, "se_ObjectLockRule"); +var se_OutputLocation = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OL); + if (input[_S_] != null) { + bn.c(se_S3Location(input[_S_], context).n(_S_)); + } + return bn; +}, "se_OutputLocation"); +var se_OutputSerialization = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OS); + if (input[_CSV] != null) { + bn.c(se_CSVOutput(input[_CSV], context).n(_CSV)); + } + if (input[_JSON] != null) { + bn.c(se_JSONOutput(input[_JSON], context).n(_JSON)); + } + return bn; +}, "se_OutputSerialization"); +var se_Owner = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_O); + bn.cc(input, _DN); + bn.cc(input, _ID_); + return bn; +}, "se_Owner"); +var se_OwnershipControls = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OC); + bn.l(input, "Rules", "Rule", () => se_OwnershipControlsRules(input[_Rul], context)); + return bn; +}, "se_OwnershipControls"); +var se_OwnershipControlsRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_OCR); + bn.cc(input, _OO); + return bn; +}, "se_OwnershipControlsRule"); +var se_OwnershipControlsRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_OwnershipControlsRule(entry, context); + return n.n(_me); + }); +}, "se_OwnershipControlsRules"); +var se_ParquetInput = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_PI); + return bn; +}, "se_ParquetInput"); +var se_PartitionedPrefix = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_PP); + bn.cc(input, _PDS); + return bn; +}, "se_PartitionedPrefix"); +var se_PublicAccessBlockConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_PABC); + if (input[_BPA] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_BPA])).n(_BPA)); + } + if (input[_IPA] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_IPA])).n(_IPA)); + } + if (input[_BPP] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_BPP])).n(_BPP)); + } + if (input[_RPB] != null) { + bn.c(import_xml_builder.XmlNode.of(_Se, String(input[_RPB])).n(_RPB)); + } + return bn; +}, "se_PublicAccessBlockConfiguration"); +var se_QueueConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_QC); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_NI, input[_I]).n(_I)); + } + if (input[_QA] != null) { + bn.c(import_xml_builder.XmlNode.of(_QA, input[_QA]).n(_Qu)); + } + bn.l(input, "Events", "Event", () => se_EventList(input[_Eve], context)); + if (input[_F] != null) { + bn.c(se_NotificationConfigurationFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_QueueConfiguration"); +var se_QueueConfigurationList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_QueueConfiguration(entry, context); + return n.n(_me); + }); +}, "se_QueueConfigurationList"); +var se_RecordExpiration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_REe); + if (input[_Exp] != null) { + bn.c(import_xml_builder.XmlNode.of(_ESxp, input[_Exp]).n(_Exp)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_RED, String(input[_Da])).n(_Da)); + } + return bn; +}, "se_RecordExpiration"); +var se_Redirect = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Red); + bn.cc(input, _HN); + bn.cc(input, _HRC); + bn.cc(input, _Pr); + bn.cc(input, _RKPW); + bn.cc(input, _RKW); + return bn; +}, "se_Redirect"); +var se_RedirectAllRequestsTo = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RART); + bn.cc(input, _HN); + bn.cc(input, _Pr); + return bn; +}, "se_RedirectAllRequestsTo"); +var se_ReplicaModifications = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RM); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_RMS, input[_S]).n(_S)); + } + return bn; +}, "se_ReplicaModifications"); +var se_ReplicationConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RCe); + bn.cc(input, _Ro); + bn.l(input, "Rules", "Rule", () => se_ReplicationRules(input[_Rul], context)); + return bn; +}, "se_ReplicationConfiguration"); +var se_ReplicationRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRe); + bn.cc(input, _ID_); + if (input[_Pri] != null) { + bn.c(import_xml_builder.XmlNode.of(_Pri, String(input[_Pri])).n(_Pri)); + } + bn.cc(input, _P); + if (input[_F] != null) { + bn.c(se_ReplicationRuleFilter(input[_F], context).n(_F)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_RRS, input[_S]).n(_S)); + } + if (input[_SSC] != null) { + bn.c(se_SourceSelectionCriteria(input[_SSC], context).n(_SSC)); + } + if (input[_EOR] != null) { + bn.c(se_ExistingObjectReplication(input[_EOR], context).n(_EOR)); + } + if (input[_Des] != null) { + bn.c(se_Destination(input[_Des], context).n(_Des)); + } + if (input[_DMR] != null) { + bn.c(se_DeleteMarkerReplication(input[_DMR], context).n(_DMR)); + } + return bn; +}, "se_ReplicationRule"); +var se_ReplicationRuleAndOperator = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRAO); + bn.cc(input, _P); + bn.l(input, "Tags", "Tag", () => se_TagSet(input[_Tag], context)); + return bn; +}, "se_ReplicationRuleAndOperator"); +var se_ReplicationRuleFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRF); + bn.cc(input, _P); + if (input[_Ta] != null) { + bn.c(se_Tag(input[_Ta], context).n(_Ta)); + } + if (input[_A] != null) { + bn.c(se_ReplicationRuleAndOperator(input[_A], context).n(_A)); + } + return bn; +}, "se_ReplicationRuleFilter"); +var se_ReplicationRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_ReplicationRule(entry, context); + return n.n(_me); + }); +}, "se_ReplicationRules"); +var se_ReplicationTime = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RTe); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_RTS, input[_S]).n(_S)); + } + if (input[_Tim] != null) { + bn.c(se_ReplicationTimeValue(input[_Tim], context).n(_Tim)); + } + return bn; +}, "se_ReplicationTime"); +var se_ReplicationTimeValue = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RTV); + if (input[_Mi] != null) { + bn.c(import_xml_builder.XmlNode.of(_Mi, String(input[_Mi])).n(_Mi)); + } + return bn; +}, "se_ReplicationTimeValue"); +var se_RequestPaymentConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RPC); + bn.cc(input, _Pa); + return bn; +}, "se_RequestPaymentConfiguration"); +var se_RequestProgress = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RPe); + if (input[_Ena] != null) { + bn.c(import_xml_builder.XmlNode.of(_ERP, String(input[_Ena])).n(_Ena)); + } + return bn; +}, "se_RequestProgress"); +var se_RestoreRequest = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRes); + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_GJP] != null) { + bn.c(se_GlacierJobParameters(input[_GJP], context).n(_GJP)); + } + if (input[_Ty] != null) { + bn.c(import_xml_builder.XmlNode.of(_RRT, input[_Ty]).n(_Ty)); + } + bn.cc(input, _Ti); + bn.cc(input, _Desc); + if (input[_SP] != null) { + bn.c(se_SelectParameters(input[_SP], context).n(_SP)); + } + if (input[_OL] != null) { + bn.c(se_OutputLocation(input[_OL], context).n(_OL)); + } + return bn; +}, "se_RestoreRequest"); +var se_RoutingRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_RRou); + if (input[_Con] != null) { + bn.c(se_Condition(input[_Con], context).n(_Con)); + } + if (input[_Red] != null) { + bn.c(se_Redirect(input[_Red], context).n(_Red)); + } + return bn; +}, "se_RoutingRule"); +var se_RoutingRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_RoutingRule(entry, context); + return n.n(_RRou); + }); +}, "se_RoutingRules"); +var se_S3KeyFilter = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SKF); + bn.l(input, "FilterRules", "FilterRule", () => se_FilterRuleList(input[_FRi], context)); + return bn; +}, "se_S3KeyFilter"); +var se_S3Location = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SL); + bn.cc(input, _BN); + if (input[_P] != null) { + bn.c(import_xml_builder.XmlNode.of(_LP, input[_P]).n(_P)); + } + if (input[_En] != null) { + bn.c(se_Encryption(input[_En], context).n(_En)); + } + if (input[_CACL] != null) { + bn.c(import_xml_builder.XmlNode.of(_OCACL, input[_CACL]).n(_CACL)); + } + bn.lc(input, "AccessControlList", "AccessControlList", () => se_Grants(input[_ACLc], context)); + if (input[_T] != null) { + bn.c(se_Tagging(input[_T], context).n(_T)); + } + bn.lc(input, "UserMetadata", "UserMetadata", () => se_UserMetadata(input[_UM], context)); + bn.cc(input, _SC); + return bn; +}, "se_S3Location"); +var se_S3TablesDestination = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_STD); + if (input[_TBA] != null) { + bn.c(import_xml_builder.XmlNode.of(_STBA, input[_TBA]).n(_TBA)); + } + if (input[_TN] != null) { + bn.c(import_xml_builder.XmlNode.of(_STN, input[_TN]).n(_TN)); + } + return bn; +}, "se_S3TablesDestination"); +var se_ScanRange = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SR); + if (input[_St] != null) { + bn.c(import_xml_builder.XmlNode.of(_St, String(input[_St])).n(_St)); + } + if (input[_End] != null) { + bn.c(import_xml_builder.XmlNode.of(_End, String(input[_End])).n(_End)); + } + return bn; +}, "se_ScanRange"); +var se_SelectParameters = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SP); + if (input[_IS] != null) { + bn.c(se_InputSerialization(input[_IS], context).n(_IS)); + } + bn.cc(input, _ETx); + bn.cc(input, _Ex); + if (input[_OS] != null) { + bn.c(se_OutputSerialization(input[_OS], context).n(_OS)); + } + return bn; +}, "se_SelectParameters"); +var se_ServerSideEncryptionByDefault = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSEBD); + if (input[_SSEA] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSE, input[_SSEA]).n(_SSEA)); + } + if (input[_KMSMKID] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSEKMSKI, input[_KMSMKID]).n(_KMSMKID)); + } + return bn; +}, "se_ServerSideEncryptionByDefault"); +var se_ServerSideEncryptionConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSEC); + bn.l(input, "Rules", "Rule", () => se_ServerSideEncryptionRules(input[_Rul], context)); + return bn; +}, "se_ServerSideEncryptionConfiguration"); +var se_ServerSideEncryptionRule = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSER); + if (input[_ASSEBD] != null) { + bn.c(se_ServerSideEncryptionByDefault(input[_ASSEBD], context).n(_ASSEBD)); + } + if (input[_BKE] != null) { + bn.c(import_xml_builder.XmlNode.of(_BKE, String(input[_BKE])).n(_BKE)); + } + return bn; +}, "se_ServerSideEncryptionRule"); +var se_ServerSideEncryptionRules = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_ServerSideEncryptionRule(entry, context); + return n.n(_me); + }); +}, "se_ServerSideEncryptionRules"); +var se_SimplePrefix = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SPi); + return bn; +}, "se_SimplePrefix"); +var se_SourceSelectionCriteria = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SSC); + if (input[_SKEO] != null) { + bn.c(se_SseKmsEncryptedObjects(input[_SKEO], context).n(_SKEO)); + } + if (input[_RM] != null) { + bn.c(se_ReplicaModifications(input[_RM], context).n(_RM)); + } + return bn; +}, "se_SourceSelectionCriteria"); +var se_SSEKMS = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SK); + if (input[_KI] != null) { + bn.c(import_xml_builder.XmlNode.of(_SSEKMSKI, input[_KI]).n(_KI)); + } + return bn; +}, "se_SSEKMS"); +var se_SseKmsEncryptedObjects = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SKEO); + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_SKEOS, input[_S]).n(_S)); + } + return bn; +}, "se_SseKmsEncryptedObjects"); +var se_SSES3 = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SS); + return bn; +}, "se_SSES3"); +var se_StorageClassAnalysis = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SCA); + if (input[_DE] != null) { + bn.c(se_StorageClassAnalysisDataExport(input[_DE], context).n(_DE)); + } + return bn; +}, "se_StorageClassAnalysis"); +var se_StorageClassAnalysisDataExport = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_SCADE); + if (input[_OSV] != null) { + bn.c(import_xml_builder.XmlNode.of(_SCASV, input[_OSV]).n(_OSV)); + } + if (input[_Des] != null) { + bn.c(se_AnalyticsExportDestination(input[_Des], context).n(_Des)); + } + return bn; +}, "se_StorageClassAnalysisDataExport"); +var se_Tag = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Ta); + if (input[_K] != null) { + bn.c(import_xml_builder.XmlNode.of(_OK, input[_K]).n(_K)); + } + bn.cc(input, _Va); + return bn; +}, "se_Tag"); +var se_Tagging = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_T); + bn.lc(input, "TagSet", "TagSet", () => se_TagSet(input[_TS], context)); + return bn; +}, "se_Tagging"); +var se_TagSet = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Tag(entry, context); + return n.n(_Ta); + }); +}, "se_TagSet"); +var se_TargetGrant = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_TGa); + if (input[_Gra] != null) { + const n = se_Grantee(input[_Gra], context).n(_Gra); + n.a("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + bn.c(n); + } + if (input[_Pe] != null) { + bn.c(import_xml_builder.XmlNode.of(_BLP, input[_Pe]).n(_Pe)); + } + return bn; +}, "se_TargetGrant"); +var se_TargetGrants = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_TargetGrant(entry, context); + return n.n(_G); + }); +}, "se_TargetGrants"); +var se_TargetObjectKeyFormat = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_TOKF); + if (input[_SPi] != null) { + bn.c(se_SimplePrefix(input[_SPi], context).n(_SPi)); + } + if (input[_PP] != null) { + bn.c(se_PartitionedPrefix(input[_PP], context).n(_PP)); + } + return bn; +}, "se_TargetObjectKeyFormat"); +var se_Tiering = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Tier); + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITD, String(input[_Da])).n(_Da)); + } + if (input[_AT] != null) { + bn.c(import_xml_builder.XmlNode.of(_ITAT, input[_AT]).n(_AT)); + } + return bn; +}, "se_Tiering"); +var se_TieringList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Tiering(entry, context); + return n.n(_me); + }); +}, "se_TieringList"); +var se_TopicConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_TCo); + if (input[_I] != null) { + bn.c(import_xml_builder.XmlNode.of(_NI, input[_I]).n(_I)); + } + if (input[_TA] != null) { + bn.c(import_xml_builder.XmlNode.of(_TA, input[_TA]).n(_Top)); + } + bn.l(input, "Events", "Event", () => se_EventList(input[_Eve], context)); + if (input[_F] != null) { + bn.c(se_NotificationConfigurationFilter(input[_F], context).n(_F)); + } + return bn; +}, "se_TopicConfiguration"); +var se_TopicConfigurationList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_TopicConfiguration(entry, context); + return n.n(_me); + }); +}, "se_TopicConfigurationList"); +var se_Transition = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_Tra); + if (input[_Dat] != null) { + bn.c(import_xml_builder.XmlNode.of(_Dat, (0, import_smithy_client.serializeDateTime)(input[_Dat]).toString()).n(_Dat)); + } + if (input[_Da] != null) { + bn.c(import_xml_builder.XmlNode.of(_Da, String(input[_Da])).n(_Da)); + } + if (input[_SC] != null) { + bn.c(import_xml_builder.XmlNode.of(_TSC, input[_SC]).n(_SC)); + } + return bn; +}, "se_Transition"); +var se_TransitionList = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_Transition(entry, context); + return n.n(_me); + }); +}, "se_TransitionList"); +var se_UserMetadata = /* @__PURE__ */ __name((input, context) => { + return input.filter((e) => e != null).map((entry) => { + const n = se_MetadataEntry(entry, context); + return n.n(_ME); + }); +}, "se_UserMetadata"); +var se_VersioningConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_VCe); + if (input[_MFAD] != null) { + bn.c(import_xml_builder.XmlNode.of(_MFAD, input[_MFAD]).n(_MDf)); + } + if (input[_S] != null) { + bn.c(import_xml_builder.XmlNode.of(_BVS, input[_S]).n(_S)); + } + return bn; +}, "se_VersioningConfiguration"); +var se_WebsiteConfiguration = /* @__PURE__ */ __name((input, context) => { + const bn = new import_xml_builder.XmlNode(_WC); + if (input[_ED] != null) { + bn.c(se_ErrorDocument(input[_ED], context).n(_ED)); + } + if (input[_ID] != null) { + bn.c(se_IndexDocument(input[_ID], context).n(_ID)); + } + if (input[_RART] != null) { + bn.c(se_RedirectAllRequestsTo(input[_RART], context).n(_RART)); + } + bn.lc(input, "RoutingRules", "RoutingRules", () => se_RoutingRules(input[_RRo], context)); + return bn; +}, "se_WebsiteConfiguration"); +var de_AbortIncompleteMultipartUpload = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DAI] != null) { + contents[_DAI] = (0, import_smithy_client.strictParseInt32)(output[_DAI]); + } + return contents; +}, "de_AbortIncompleteMultipartUpload"); +var de_AccessControlTranslation = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_O] != null) { + contents[_O] = (0, import_smithy_client.expectString)(output[_O]); + } + return contents; +}, "de_AccessControlTranslation"); +var de_AllowedHeaders = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_AllowedHeaders"); +var de_AllowedMethods = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_AllowedMethods"); +var de_AllowedOrigins = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_AllowedOrigins"); +var de_AnalyticsAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + return contents; +}, "de_AnalyticsAndOperator"); +var de_AnalyticsConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output.Filter === "") { + } else if (output[_F] != null) { + contents[_F] = de_AnalyticsFilter((0, import_smithy_client.expectUnion)(output[_F]), context); + } + if (output[_SCA] != null) { + contents[_SCA] = de_StorageClassAnalysis(output[_SCA], context); + } + return contents; +}, "de_AnalyticsConfiguration"); +var de_AnalyticsConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_AnalyticsConfiguration(entry, context); + }); +}, "de_AnalyticsConfigurationList"); +var de_AnalyticsExportDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SBD] != null) { + contents[_SBD] = de_AnalyticsS3BucketDestination(output[_SBD], context); + } + return contents; +}, "de_AnalyticsExportDestination"); +var de_AnalyticsFilter = /* @__PURE__ */ __name((output, context) => { + if (output[_P] != null) { + return { + Prefix: (0, import_smithy_client.expectString)(output[_P]) + }; + } + if (output[_Ta] != null) { + return { + Tag: de_Tag(output[_Ta], context) + }; + } + if (output[_A] != null) { + return { + And: de_AnalyticsAndOperator(output[_A], context) + }; + } + return { $unknown: Object.entries(output)[0] }; +}, "de_AnalyticsFilter"); +var de_AnalyticsS3BucketDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Fo] != null) { + contents[_Fo] = (0, import_smithy_client.expectString)(output[_Fo]); + } + if (output[_BAI] != null) { + contents[_BAI] = (0, import_smithy_client.expectString)(output[_BAI]); + } + if (output[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(output[_B]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + return contents; +}, "de_AnalyticsS3BucketDestination"); +var de_Bucket = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(output[_N]); + } + if (output[_CDr] != null) { + contents[_CDr] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_CDr])); + } + if (output[_BR] != null) { + contents[_BR] = (0, import_smithy_client.expectString)(output[_BR]); + } + if (output[_BA] != null) { + contents[_BA] = (0, import_smithy_client.expectString)(output[_BA]); + } + return contents; +}, "de_Bucket"); +var de_Buckets = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Bucket(entry, context); + }); +}, "de_Buckets"); +var de_Checksum = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + return contents; +}, "de_Checksum"); +var de_ChecksumAlgorithmList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_ChecksumAlgorithmList"); +var de_CommonPrefix = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + return contents; +}, "de_CommonPrefix"); +var de_CommonPrefixList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_CommonPrefix(entry, context); + }); +}, "de_CommonPrefixList"); +var de_Condition = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_HECRE] != null) { + contents[_HECRE] = (0, import_smithy_client.expectString)(output[_HECRE]); + } + if (output[_KPE] != null) { + contents[_KPE] = (0, import_smithy_client.expectString)(output[_KPE]); + } + return contents; +}, "de_Condition"); +var de_ContinuationEvent = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_ContinuationEvent"); +var de_CopyObjectResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_CopyObjectResult"); +var de_CopyPartResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_CopyPartResult"); +var de_CORSRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output.AllowedHeader === "") { + contents[_AHl] = []; + } else if (output[_AH] != null) { + contents[_AHl] = de_AllowedHeaders((0, import_smithy_client.getArrayIfSingleItem)(output[_AH]), context); + } + if (output.AllowedMethod === "") { + contents[_AMl] = []; + } else if (output[_AM] != null) { + contents[_AMl] = de_AllowedMethods((0, import_smithy_client.getArrayIfSingleItem)(output[_AM]), context); + } + if (output.AllowedOrigin === "") { + contents[_AOl] = []; + } else if (output[_AO] != null) { + contents[_AOl] = de_AllowedOrigins((0, import_smithy_client.getArrayIfSingleItem)(output[_AO]), context); + } + if (output.ExposeHeader === "") { + contents[_EH] = []; + } else if (output[_EHx] != null) { + contents[_EH] = de_ExposeHeaders((0, import_smithy_client.getArrayIfSingleItem)(output[_EHx]), context); + } + if (output[_MAS] != null) { + contents[_MAS] = (0, import_smithy_client.strictParseInt32)(output[_MAS]); + } + return contents; +}, "de_CORSRule"); +var de_CORSRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_CORSRule(entry, context); + }); +}, "de_CORSRules"); +var de_DefaultRetention = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Mo] != null) { + contents[_Mo] = (0, import_smithy_client.expectString)(output[_Mo]); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_Y] != null) { + contents[_Y] = (0, import_smithy_client.strictParseInt32)(output[_Y]); + } + return contents; +}, "de_DefaultRetention"); +var de_DeletedObject = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_DM] != null) { + contents[_DM] = (0, import_smithy_client.parseBoolean)(output[_DM]); + } + if (output[_DMVI] != null) { + contents[_DMVI] = (0, import_smithy_client.expectString)(output[_DMVI]); + } + return contents; +}, "de_DeletedObject"); +var de_DeletedObjects = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_DeletedObject(entry, context); + }); +}, "de_DeletedObjects"); +var de_DeleteMarkerEntry = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_IL] != null) { + contents[_IL] = (0, import_smithy_client.parseBoolean)(output[_IL]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + return contents; +}, "de_DeleteMarkerEntry"); +var de_DeleteMarkerReplication = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_DeleteMarkerReplication"); +var de_DeleteMarkers = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_DeleteMarkerEntry(entry, context); + }); +}, "de_DeleteMarkers"); +var de_Destination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(output[_B]); + } + if (output[_Ac] != null) { + contents[_Ac] = (0, import_smithy_client.expectString)(output[_Ac]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_ACT] != null) { + contents[_ACT] = de_AccessControlTranslation(output[_ACT], context); + } + if (output[_ECn] != null) { + contents[_ECn] = de_EncryptionConfiguration(output[_ECn], context); + } + if (output[_RTe] != null) { + contents[_RTe] = de_ReplicationTime(output[_RTe], context); + } + if (output[_Me] != null) { + contents[_Me] = de_Metrics(output[_Me], context); + } + return contents; +}, "de_Destination"); +var de_DestinationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TBT] != null) { + contents[_TBT] = (0, import_smithy_client.expectString)(output[_TBT]); + } + if (output[_TBA] != null) { + contents[_TBA] = (0, import_smithy_client.expectString)(output[_TBA]); + } + if (output[_TNa] != null) { + contents[_TNa] = (0, import_smithy_client.expectString)(output[_TNa]); + } + return contents; +}, "de_DestinationResult"); +var de_EncryptionConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_RKKID] != null) { + contents[_RKKID] = (0, import_smithy_client.expectString)(output[_RKKID]); + } + return contents; +}, "de_EncryptionConfiguration"); +var de_EndEvent = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_EndEvent"); +var de__Error = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_Cod] != null) { + contents[_Cod] = (0, import_smithy_client.expectString)(output[_Cod]); + } + if (output[_Mes] != null) { + contents[_Mes] = (0, import_smithy_client.expectString)(output[_Mes]); + } + return contents; +}, "de__Error"); +var de_ErrorDetails = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_EC] != null) { + contents[_EC] = (0, import_smithy_client.expectString)(output[_EC]); + } + if (output[_EM] != null) { + contents[_EM] = (0, import_smithy_client.expectString)(output[_EM]); + } + return contents; +}, "de_ErrorDetails"); +var de_ErrorDocument = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + return contents; +}, "de_ErrorDocument"); +var de_Errors = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de__Error(entry, context); + }); +}, "de_Errors"); +var de_EventBridgeConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_EventBridgeConfiguration"); +var de_EventList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_EventList"); +var de_ExistingObjectReplication = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_ExistingObjectReplication"); +var de_ExposeHeaders = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_ExposeHeaders"); +var de_FilterRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_N] != null) { + contents[_N] = (0, import_smithy_client.expectString)(output[_N]); + } + if (output[_Va] != null) { + contents[_Va] = (0, import_smithy_client.expectString)(output[_Va]); + } + return contents; +}, "de_FilterRule"); +var de_FilterRuleList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_FilterRule(entry, context); + }); +}, "de_FilterRuleList"); +var de_GetBucketMetadataConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_MCR] != null) { + contents[_MCR] = de_MetadataConfigurationResult(output[_MCR], context); + } + return contents; +}, "de_GetBucketMetadataConfigurationResult"); +var de_GetBucketMetadataTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_MTCR] != null) { + contents[_MTCR] = de_MetadataTableConfigurationResult(output[_MTCR], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_Er] != null) { + contents[_Er] = de_ErrorDetails(output[_Er], context); + } + return contents; +}, "de_GetBucketMetadataTableConfigurationResult"); +var de_GetObjectAttributesParts = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PC] != null) { + contents[_TPC] = (0, import_smithy_client.strictParseInt32)(output[_PC]); + } + if (output[_PNM] != null) { + contents[_PNM] = (0, import_smithy_client.expectString)(output[_PNM]); + } + if (output[_NPNM] != null) { + contents[_NPNM] = (0, import_smithy_client.expectString)(output[_NPNM]); + } + if (output[_MP] != null) { + contents[_MP] = (0, import_smithy_client.strictParseInt32)(output[_MP]); + } + if (output[_IT] != null) { + contents[_IT] = (0, import_smithy_client.parseBoolean)(output[_IT]); + } + if (output.Part === "") { + contents[_Part] = []; + } else if (output[_Par] != null) { + contents[_Part] = de_PartsList((0, import_smithy_client.getArrayIfSingleItem)(output[_Par]), context); + } + return contents; +}, "de_GetObjectAttributesParts"); +var de_Grant = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Gra] != null) { + contents[_Gra] = de_Grantee(output[_Gra], context); + } + if (output[_Pe] != null) { + contents[_Pe] = (0, import_smithy_client.expectString)(output[_Pe]); + } + return contents; +}, "de_Grant"); +var de_Grantee = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DN] != null) { + contents[_DN] = (0, import_smithy_client.expectString)(output[_DN]); + } + if (output[_EA] != null) { + contents[_EA] = (0, import_smithy_client.expectString)(output[_EA]); + } + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_URI] != null) { + contents[_URI] = (0, import_smithy_client.expectString)(output[_URI]); + } + if (output[_x] != null) { + contents[_Ty] = (0, import_smithy_client.expectString)(output[_x]); + } + return contents; +}, "de_Grantee"); +var de_Grants = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Grant(entry, context); + }); +}, "de_Grants"); +var de_IndexDocument = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Su] != null) { + contents[_Su] = (0, import_smithy_client.expectString)(output[_Su]); + } + return contents; +}, "de_IndexDocument"); +var de_Initiator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_DN] != null) { + contents[_DN] = (0, import_smithy_client.expectString)(output[_DN]); + } + return contents; +}, "de_Initiator"); +var de_IntelligentTieringAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + return contents; +}, "de_IntelligentTieringAndOperator"); +var de_IntelligentTieringConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_F] != null) { + contents[_F] = de_IntelligentTieringFilter(output[_F], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output.Tiering === "") { + contents[_Tie] = []; + } else if (output[_Tier] != null) { + contents[_Tie] = de_TieringList((0, import_smithy_client.getArrayIfSingleItem)(output[_Tier]), context); + } + return contents; +}, "de_IntelligentTieringConfiguration"); +var de_IntelligentTieringConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_IntelligentTieringConfiguration(entry, context); + }); +}, "de_IntelligentTieringConfigurationList"); +var de_IntelligentTieringFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_Ta] != null) { + contents[_Ta] = de_Tag(output[_Ta], context); + } + if (output[_A] != null) { + contents[_A] = de_IntelligentTieringAndOperator(output[_A], context); + } + return contents; +}, "de_IntelligentTieringFilter"); +var de_InventoryConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Des] != null) { + contents[_Des] = de_InventoryDestination(output[_Des], context); + } + if (output[_IE] != null) { + contents[_IE] = (0, import_smithy_client.parseBoolean)(output[_IE]); + } + if (output[_F] != null) { + contents[_F] = de_InventoryFilter(output[_F], context); + } + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_IOV] != null) { + contents[_IOV] = (0, import_smithy_client.expectString)(output[_IOV]); + } + if (output.OptionalFields === "") { + contents[_OF] = []; + } else if (output[_OF] != null && output[_OF][_Fi] != null) { + contents[_OF] = de_InventoryOptionalFields((0, import_smithy_client.getArrayIfSingleItem)(output[_OF][_Fi]), context); + } + if (output[_Sc] != null) { + contents[_Sc] = de_InventorySchedule(output[_Sc], context); + } + return contents; +}, "de_InventoryConfiguration"); +var de_InventoryConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_InventoryConfiguration(entry, context); + }); +}, "de_InventoryConfigurationList"); +var de_InventoryDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SBD] != null) { + contents[_SBD] = de_InventoryS3BucketDestination(output[_SBD], context); + } + return contents; +}, "de_InventoryDestination"); +var de_InventoryEncryption = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SS] != null) { + contents[_SSES] = de_SSES3(output[_SS], context); + } + if (output[_SK] != null) { + contents[_SSEKMS] = de_SSEKMS(output[_SK], context); + } + return contents; +}, "de_InventoryEncryption"); +var de_InventoryFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + return contents; +}, "de_InventoryFilter"); +var de_InventoryOptionalFields = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return (0, import_smithy_client.expectString)(entry); + }); +}, "de_InventoryOptionalFields"); +var de_InventoryS3BucketDestination = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_AIc] != null) { + contents[_AIc] = (0, import_smithy_client.expectString)(output[_AIc]); + } + if (output[_B] != null) { + contents[_B] = (0, import_smithy_client.expectString)(output[_B]); + } + if (output[_Fo] != null) { + contents[_Fo] = (0, import_smithy_client.expectString)(output[_Fo]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_En] != null) { + contents[_En] = de_InventoryEncryption(output[_En], context); + } + return contents; +}, "de_InventoryS3BucketDestination"); +var de_InventorySchedule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Fr] != null) { + contents[_Fr] = (0, import_smithy_client.expectString)(output[_Fr]); + } + return contents; +}, "de_InventorySchedule"); +var de_InventoryTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_CSo] != null) { + contents[_CSo] = (0, import_smithy_client.expectString)(output[_CSo]); + } + if (output[_TSa] != null) { + contents[_TSa] = (0, import_smithy_client.expectString)(output[_TSa]); + } + if (output[_Er] != null) { + contents[_Er] = de_ErrorDetails(output[_Er], context); + } + if (output[_TN] != null) { + contents[_TN] = (0, import_smithy_client.expectString)(output[_TN]); + } + if (output[_TAa] != null) { + contents[_TAa] = (0, import_smithy_client.expectString)(output[_TAa]); + } + return contents; +}, "de_InventoryTableConfigurationResult"); +var de_JournalTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TSa] != null) { + contents[_TSa] = (0, import_smithy_client.expectString)(output[_TSa]); + } + if (output[_Er] != null) { + contents[_Er] = de_ErrorDetails(output[_Er], context); + } + if (output[_TN] != null) { + contents[_TN] = (0, import_smithy_client.expectString)(output[_TN]); + } + if (output[_TAa] != null) { + contents[_TAa] = (0, import_smithy_client.expectString)(output[_TAa]); + } + if (output[_REe] != null) { + contents[_REe] = de_RecordExpiration(output[_REe], context); + } + return contents; +}, "de_JournalTableConfigurationResult"); +var de_LambdaFunctionConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_CF] != null) { + contents[_LFA] = (0, import_smithy_client.expectString)(output[_CF]); + } + if (output.Event === "") { + contents[_Eve] = []; + } else if (output[_Ev] != null) { + contents[_Eve] = de_EventList((0, import_smithy_client.getArrayIfSingleItem)(output[_Ev]), context); + } + if (output[_F] != null) { + contents[_F] = de_NotificationConfigurationFilter(output[_F], context); + } + return contents; +}, "de_LambdaFunctionConfiguration"); +var de_LambdaFunctionConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_LambdaFunctionConfiguration(entry, context); + }); +}, "de_LambdaFunctionConfigurationList"); +var de_LifecycleExpiration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Dat] != null) { + contents[_Dat] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Dat])); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_EODM] != null) { + contents[_EODM] = (0, import_smithy_client.parseBoolean)(output[_EODM]); + } + return contents; +}, "de_LifecycleExpiration"); +var de_LifecycleRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Exp] != null) { + contents[_Exp] = de_LifecycleExpiration(output[_Exp], context); + } + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_F] != null) { + contents[_F] = de_LifecycleRuleFilter(output[_F], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output.Transition === "") { + contents[_Tr] = []; + } else if (output[_Tra] != null) { + contents[_Tr] = de_TransitionList((0, import_smithy_client.getArrayIfSingleItem)(output[_Tra]), context); + } + if (output.NoncurrentVersionTransition === "") { + contents[_NVT] = []; + } else if (output[_NVTo] != null) { + contents[_NVT] = de_NoncurrentVersionTransitionList((0, import_smithy_client.getArrayIfSingleItem)(output[_NVTo]), context); + } + if (output[_NVE] != null) { + contents[_NVE] = de_NoncurrentVersionExpiration(output[_NVE], context); + } + if (output[_AIMU] != null) { + contents[_AIMU] = de_AbortIncompleteMultipartUpload(output[_AIMU], context); + } + return contents; +}, "de_LifecycleRule"); +var de_LifecycleRuleAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + if (output[_OSGT] != null) { + contents[_OSGT] = (0, import_smithy_client.strictParseLong)(output[_OSGT]); + } + if (output[_OSLT] != null) { + contents[_OSLT] = (0, import_smithy_client.strictParseLong)(output[_OSLT]); + } + return contents; +}, "de_LifecycleRuleAndOperator"); +var de_LifecycleRuleFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_Ta] != null) { + contents[_Ta] = de_Tag(output[_Ta], context); + } + if (output[_OSGT] != null) { + contents[_OSGT] = (0, import_smithy_client.strictParseLong)(output[_OSGT]); + } + if (output[_OSLT] != null) { + contents[_OSLT] = (0, import_smithy_client.strictParseLong)(output[_OSLT]); + } + if (output[_A] != null) { + contents[_A] = de_LifecycleRuleAndOperator(output[_A], context); + } + return contents; +}, "de_LifecycleRuleFilter"); +var de_LifecycleRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_LifecycleRule(entry, context); + }); +}, "de_LifecycleRules"); +var de_LoggingEnabled = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TB] != null) { + contents[_TB] = (0, import_smithy_client.expectString)(output[_TB]); + } + if (output.TargetGrants === "") { + contents[_TG] = []; + } else if (output[_TG] != null && output[_TG][_G] != null) { + contents[_TG] = de_TargetGrants((0, import_smithy_client.getArrayIfSingleItem)(output[_TG][_G]), context); + } + if (output[_TP] != null) { + contents[_TP] = (0, import_smithy_client.expectString)(output[_TP]); + } + if (output[_TOKF] != null) { + contents[_TOKF] = de_TargetObjectKeyFormat(output[_TOKF], context); + } + return contents; +}, "de_LoggingEnabled"); +var de_MetadataConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DRes] != null) { + contents[_DRes] = de_DestinationResult(output[_DRes], context); + } + if (output[_JTCR] != null) { + contents[_JTCR] = de_JournalTableConfigurationResult(output[_JTCR], context); + } + if (output[_ITCR] != null) { + contents[_ITCR] = de_InventoryTableConfigurationResult(output[_ITCR], context); + } + return contents; +}, "de_MetadataConfigurationResult"); +var de_MetadataTableConfigurationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_STDR] != null) { + contents[_STDR] = de_S3TablesDestinationResult(output[_STDR], context); + } + return contents; +}, "de_MetadataTableConfigurationResult"); +var de_Metrics = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_ETv] != null) { + contents[_ETv] = de_ReplicationTimeValue(output[_ETv], context); + } + return contents; +}, "de_Metrics"); +var de_MetricsAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + if (output[_APAc] != null) { + contents[_APAc] = (0, import_smithy_client.expectString)(output[_APAc]); + } + return contents; +}, "de_MetricsAndOperator"); +var de_MetricsConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output.Filter === "") { + } else if (output[_F] != null) { + contents[_F] = de_MetricsFilter((0, import_smithy_client.expectUnion)(output[_F]), context); + } + return contents; +}, "de_MetricsConfiguration"); +var de_MetricsConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_MetricsConfiguration(entry, context); + }); +}, "de_MetricsConfigurationList"); +var de_MetricsFilter = /* @__PURE__ */ __name((output, context) => { + if (output[_P] != null) { + return { + Prefix: (0, import_smithy_client.expectString)(output[_P]) + }; + } + if (output[_Ta] != null) { + return { + Tag: de_Tag(output[_Ta], context) + }; + } + if (output[_APAc] != null) { + return { + AccessPointArn: (0, import_smithy_client.expectString)(output[_APAc]) + }; + } + if (output[_A] != null) { + return { + And: de_MetricsAndOperator(output[_A], context) + }; + } + return { $unknown: Object.entries(output)[0] }; +}, "de_MetricsFilter"); +var de_MultipartUpload = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_UI] != null) { + contents[_UI] = (0, import_smithy_client.expectString)(output[_UI]); + } + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_Ini] != null) { + contents[_Ini] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Ini])); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_In] != null) { + contents[_In] = de_Initiator(output[_In], context); + } + if (output[_CA] != null) { + contents[_CA] = (0, import_smithy_client.expectString)(output[_CA]); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + return contents; +}, "de_MultipartUpload"); +var de_MultipartUploadList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_MultipartUpload(entry, context); + }); +}, "de_MultipartUploadList"); +var de_NoncurrentVersionExpiration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ND] != null) { + contents[_ND] = (0, import_smithy_client.strictParseInt32)(output[_ND]); + } + if (output[_NNV] != null) { + contents[_NNV] = (0, import_smithy_client.strictParseInt32)(output[_NNV]); + } + return contents; +}, "de_NoncurrentVersionExpiration"); +var de_NoncurrentVersionTransition = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ND] != null) { + contents[_ND] = (0, import_smithy_client.strictParseInt32)(output[_ND]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_NNV] != null) { + contents[_NNV] = (0, import_smithy_client.strictParseInt32)(output[_NNV]); + } + return contents; +}, "de_NoncurrentVersionTransition"); +var de_NoncurrentVersionTransitionList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_NoncurrentVersionTransition(entry, context); + }); +}, "de_NoncurrentVersionTransitionList"); +var de_NotificationConfigurationFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SKe] != null) { + contents[_K] = de_S3KeyFilter(output[_SKe], context); + } + return contents; +}, "de_NotificationConfigurationFilter"); +var de__Object = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output.ChecksumAlgorithm === "") { + contents[_CA] = []; + } else if (output[_CA] != null) { + contents[_CA] = de_ChecksumAlgorithmList((0, import_smithy_client.getArrayIfSingleItem)(output[_CA]), context); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_RSes] != null) { + contents[_RSes] = de_RestoreStatus(output[_RSes], context); + } + return contents; +}, "de__Object"); +var de_ObjectList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de__Object(entry, context); + }); +}, "de_ObjectList"); +var de_ObjectLockConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_OLE] != null) { + contents[_OLE] = (0, import_smithy_client.expectString)(output[_OLE]); + } + if (output[_Ru] != null) { + contents[_Ru] = de_ObjectLockRule(output[_Ru], context); + } + return contents; +}, "de_ObjectLockConfiguration"); +var de_ObjectLockLegalHold = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_ObjectLockLegalHold"); +var de_ObjectLockRetention = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Mo] != null) { + contents[_Mo] = (0, import_smithy_client.expectString)(output[_Mo]); + } + if (output[_RUD] != null) { + contents[_RUD] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_RUD])); + } + return contents; +}, "de_ObjectLockRetention"); +var de_ObjectLockRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DRe] != null) { + contents[_DRe] = de_DefaultRetention(output[_DRe], context); + } + return contents; +}, "de_ObjectLockRule"); +var de_ObjectPart = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PN] != null) { + contents[_PN] = (0, import_smithy_client.strictParseInt32)(output[_PN]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_ObjectPart"); +var de_ObjectVersion = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output.ChecksumAlgorithm === "") { + contents[_CA] = []; + } else if (output[_CA] != null) { + contents[_CA] = de_ChecksumAlgorithmList((0, import_smithy_client.getArrayIfSingleItem)(output[_CA]), context); + } + if (output[_CT] != null) { + contents[_CT] = (0, import_smithy_client.expectString)(output[_CT]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_VI] != null) { + contents[_VI] = (0, import_smithy_client.expectString)(output[_VI]); + } + if (output[_IL] != null) { + contents[_IL] = (0, import_smithy_client.parseBoolean)(output[_IL]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_O] != null) { + contents[_O] = de_Owner(output[_O], context); + } + if (output[_RSes] != null) { + contents[_RSes] = de_RestoreStatus(output[_RSes], context); + } + return contents; +}, "de_ObjectVersion"); +var de_ObjectVersionList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ObjectVersion(entry, context); + }); +}, "de_ObjectVersionList"); +var de_Owner = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DN] != null) { + contents[_DN] = (0, import_smithy_client.expectString)(output[_DN]); + } + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + return contents; +}, "de_Owner"); +var de_OwnershipControls = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output.Rule === "") { + contents[_Rul] = []; + } else if (output[_Ru] != null) { + contents[_Rul] = de_OwnershipControlsRules((0, import_smithy_client.getArrayIfSingleItem)(output[_Ru]), context); + } + return contents; +}, "de_OwnershipControls"); +var de_OwnershipControlsRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_OO] != null) { + contents[_OO] = (0, import_smithy_client.expectString)(output[_OO]); + } + return contents; +}, "de_OwnershipControlsRule"); +var de_OwnershipControlsRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_OwnershipControlsRule(entry, context); + }); +}, "de_OwnershipControlsRules"); +var de_Part = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PN] != null) { + contents[_PN] = (0, import_smithy_client.strictParseInt32)(output[_PN]); + } + if (output[_LM] != null) { + contents[_LM] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_LM])); + } + if (output[_ETa] != null) { + contents[_ETa] = (0, import_smithy_client.expectString)(output[_ETa]); + } + if (output[_Si] != null) { + contents[_Si] = (0, import_smithy_client.strictParseLong)(output[_Si]); + } + if (output[_CCRC] != null) { + contents[_CCRC] = (0, import_smithy_client.expectString)(output[_CCRC]); + } + if (output[_CCRCC] != null) { + contents[_CCRCC] = (0, import_smithy_client.expectString)(output[_CCRCC]); + } + if (output[_CCRCNVME] != null) { + contents[_CCRCNVME] = (0, import_smithy_client.expectString)(output[_CCRCNVME]); + } + if (output[_CSHA] != null) { + contents[_CSHA] = (0, import_smithy_client.expectString)(output[_CSHA]); + } + if (output[_CSHAh] != null) { + contents[_CSHAh] = (0, import_smithy_client.expectString)(output[_CSHAh]); + } + return contents; +}, "de_Part"); +var de_PartitionedPrefix = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_PDS] != null) { + contents[_PDS] = (0, import_smithy_client.expectString)(output[_PDS]); + } + return contents; +}, "de_PartitionedPrefix"); +var de_Parts = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Part(entry, context); + }); +}, "de_Parts"); +var de_PartsList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ObjectPart(entry, context); + }); +}, "de_PartsList"); +var de_PolicyStatus = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_IP] != null) { + contents[_IP] = (0, import_smithy_client.parseBoolean)(output[_IP]); + } + return contents; +}, "de_PolicyStatus"); +var de_Progress = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_BS] != null) { + contents[_BS] = (0, import_smithy_client.strictParseLong)(output[_BS]); + } + if (output[_BP] != null) { + contents[_BP] = (0, import_smithy_client.strictParseLong)(output[_BP]); + } + if (output[_BRy] != null) { + contents[_BRy] = (0, import_smithy_client.strictParseLong)(output[_BRy]); + } + return contents; +}, "de_Progress"); +var de_PublicAccessBlockConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_BPA] != null) { + contents[_BPA] = (0, import_smithy_client.parseBoolean)(output[_BPA]); + } + if (output[_IPA] != null) { + contents[_IPA] = (0, import_smithy_client.parseBoolean)(output[_IPA]); + } + if (output[_BPP] != null) { + contents[_BPP] = (0, import_smithy_client.parseBoolean)(output[_BPP]); + } + if (output[_RPB] != null) { + contents[_RPB] = (0, import_smithy_client.parseBoolean)(output[_RPB]); + } + return contents; +}, "de_PublicAccessBlockConfiguration"); +var de_QueueConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_Qu] != null) { + contents[_QA] = (0, import_smithy_client.expectString)(output[_Qu]); + } + if (output.Event === "") { + contents[_Eve] = []; + } else if (output[_Ev] != null) { + contents[_Eve] = de_EventList((0, import_smithy_client.getArrayIfSingleItem)(output[_Ev]), context); + } + if (output[_F] != null) { + contents[_F] = de_NotificationConfigurationFilter(output[_F], context); + } + return contents; +}, "de_QueueConfiguration"); +var de_QueueConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_QueueConfiguration(entry, context); + }); +}, "de_QueueConfigurationList"); +var de_RecordExpiration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Exp] != null) { + contents[_Exp] = (0, import_smithy_client.expectString)(output[_Exp]); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + return contents; +}, "de_RecordExpiration"); +var de_Redirect = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_HN] != null) { + contents[_HN] = (0, import_smithy_client.expectString)(output[_HN]); + } + if (output[_HRC] != null) { + contents[_HRC] = (0, import_smithy_client.expectString)(output[_HRC]); + } + if (output[_Pr] != null) { + contents[_Pr] = (0, import_smithy_client.expectString)(output[_Pr]); + } + if (output[_RKPW] != null) { + contents[_RKPW] = (0, import_smithy_client.expectString)(output[_RKPW]); + } + if (output[_RKW] != null) { + contents[_RKW] = (0, import_smithy_client.expectString)(output[_RKW]); + } + return contents; +}, "de_Redirect"); +var de_RedirectAllRequestsTo = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_HN] != null) { + contents[_HN] = (0, import_smithy_client.expectString)(output[_HN]); + } + if (output[_Pr] != null) { + contents[_Pr] = (0, import_smithy_client.expectString)(output[_Pr]); + } + return contents; +}, "de_RedirectAllRequestsTo"); +var de_ReplicaModifications = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_ReplicaModifications"); +var de_ReplicationConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Ro] != null) { + contents[_Ro] = (0, import_smithy_client.expectString)(output[_Ro]); + } + if (output.Rule === "") { + contents[_Rul] = []; + } else if (output[_Ru] != null) { + contents[_Rul] = de_ReplicationRules((0, import_smithy_client.getArrayIfSingleItem)(output[_Ru]), context); + } + return contents; +}, "de_ReplicationConfiguration"); +var de_ReplicationRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ID_] != null) { + contents[_ID_] = (0, import_smithy_client.expectString)(output[_ID_]); + } + if (output[_Pri] != null) { + contents[_Pri] = (0, import_smithy_client.strictParseInt32)(output[_Pri]); + } + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_F] != null) { + contents[_F] = de_ReplicationRuleFilter(output[_F], context); + } + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_SSC] != null) { + contents[_SSC] = de_SourceSelectionCriteria(output[_SSC], context); + } + if (output[_EOR] != null) { + contents[_EOR] = de_ExistingObjectReplication(output[_EOR], context); + } + if (output[_Des] != null) { + contents[_Des] = de_Destination(output[_Des], context); + } + if (output[_DMR] != null) { + contents[_DMR] = de_DeleteMarkerReplication(output[_DMR], context); + } + return contents; +}, "de_ReplicationRule"); +var de_ReplicationRuleAndOperator = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output.Tag === "") { + contents[_Tag] = []; + } else if (output[_Ta] != null) { + contents[_Tag] = de_TagSet((0, import_smithy_client.getArrayIfSingleItem)(output[_Ta]), context); + } + return contents; +}, "de_ReplicationRuleAndOperator"); +var de_ReplicationRuleFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_P] != null) { + contents[_P] = (0, import_smithy_client.expectString)(output[_P]); + } + if (output[_Ta] != null) { + contents[_Ta] = de_Tag(output[_Ta], context); + } + if (output[_A] != null) { + contents[_A] = de_ReplicationRuleAndOperator(output[_A], context); + } + return contents; +}, "de_ReplicationRuleFilter"); +var de_ReplicationRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ReplicationRule(entry, context); + }); +}, "de_ReplicationRules"); +var de_ReplicationTime = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + if (output[_Tim] != null) { + contents[_Tim] = de_ReplicationTimeValue(output[_Tim], context); + } + return contents; +}, "de_ReplicationTime"); +var de_ReplicationTimeValue = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Mi] != null) { + contents[_Mi] = (0, import_smithy_client.strictParseInt32)(output[_Mi]); + } + return contents; +}, "de_ReplicationTimeValue"); +var de_RestoreStatus = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_IRIP] != null) { + contents[_IRIP] = (0, import_smithy_client.parseBoolean)(output[_IRIP]); + } + if (output[_REDe] != null) { + contents[_REDe] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_REDe])); + } + return contents; +}, "de_RestoreStatus"); +var de_RoutingRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Con] != null) { + contents[_Con] = de_Condition(output[_Con], context); + } + if (output[_Red] != null) { + contents[_Red] = de_Redirect(output[_Red], context); + } + return contents; +}, "de_RoutingRule"); +var de_RoutingRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_RoutingRule(entry, context); + }); +}, "de_RoutingRules"); +var de_S3KeyFilter = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output.FilterRule === "") { + contents[_FRi] = []; + } else if (output[_FR] != null) { + contents[_FRi] = de_FilterRuleList((0, import_smithy_client.getArrayIfSingleItem)(output[_FR]), context); + } + return contents; +}, "de_S3KeyFilter"); +var de_S3TablesDestinationResult = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_TBA] != null) { + contents[_TBA] = (0, import_smithy_client.expectString)(output[_TBA]); + } + if (output[_TN] != null) { + contents[_TN] = (0, import_smithy_client.expectString)(output[_TN]); + } + if (output[_TAa] != null) { + contents[_TAa] = (0, import_smithy_client.expectString)(output[_TAa]); + } + if (output[_TNa] != null) { + contents[_TNa] = (0, import_smithy_client.expectString)(output[_TNa]); + } + return contents; +}, "de_S3TablesDestinationResult"); +var de_ServerSideEncryptionByDefault = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SSEA] != null) { + contents[_SSEA] = (0, import_smithy_client.expectString)(output[_SSEA]); + } + if (output[_KMSMKID] != null) { + contents[_KMSMKID] = (0, import_smithy_client.expectString)(output[_KMSMKID]); + } + return contents; +}, "de_ServerSideEncryptionByDefault"); +var de_ServerSideEncryptionConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output.Rule === "") { + contents[_Rul] = []; + } else if (output[_Ru] != null) { + contents[_Rul] = de_ServerSideEncryptionRules((0, import_smithy_client.getArrayIfSingleItem)(output[_Ru]), context); + } + return contents; +}, "de_ServerSideEncryptionConfiguration"); +var de_ServerSideEncryptionRule = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ASSEBD] != null) { + contents[_ASSEBD] = de_ServerSideEncryptionByDefault(output[_ASSEBD], context); + } + if (output[_BKE] != null) { + contents[_BKE] = (0, import_smithy_client.parseBoolean)(output[_BKE]); + } + return contents; +}, "de_ServerSideEncryptionRule"); +var de_ServerSideEncryptionRules = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_ServerSideEncryptionRule(entry, context); + }); +}, "de_ServerSideEncryptionRules"); +var de_SessionCredentials = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_AKI] != null) { + contents[_AKI] = (0, import_smithy_client.expectString)(output[_AKI]); + } + if (output[_SAK] != null) { + contents[_SAK] = (0, import_smithy_client.expectString)(output[_SAK]); + } + if (output[_ST] != null) { + contents[_ST] = (0, import_smithy_client.expectString)(output[_ST]); + } + if (output[_Exp] != null) { + contents[_Exp] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Exp])); + } + return contents; +}, "de_SessionCredentials"); +var de_SimplePrefix = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_SimplePrefix"); +var de_SourceSelectionCriteria = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SKEO] != null) { + contents[_SKEO] = de_SseKmsEncryptedObjects(output[_SKEO], context); + } + if (output[_RM] != null) { + contents[_RM] = de_ReplicaModifications(output[_RM], context); + } + return contents; +}, "de_SourceSelectionCriteria"); +var de_SSEKMS = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_KI] != null) { + contents[_KI] = (0, import_smithy_client.expectString)(output[_KI]); + } + return contents; +}, "de_SSEKMS"); +var de_SseKmsEncryptedObjects = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_S] != null) { + contents[_S] = (0, import_smithy_client.expectString)(output[_S]); + } + return contents; +}, "de_SseKmsEncryptedObjects"); +var de_SSES3 = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + return contents; +}, "de_SSES3"); +var de_Stats = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_BS] != null) { + contents[_BS] = (0, import_smithy_client.strictParseLong)(output[_BS]); + } + if (output[_BP] != null) { + contents[_BP] = (0, import_smithy_client.strictParseLong)(output[_BP]); + } + if (output[_BRy] != null) { + contents[_BRy] = (0, import_smithy_client.strictParseLong)(output[_BRy]); + } + return contents; +}, "de_Stats"); +var de_StorageClassAnalysis = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_DE] != null) { + contents[_DE] = de_StorageClassAnalysisDataExport(output[_DE], context); + } + return contents; +}, "de_StorageClassAnalysis"); +var de_StorageClassAnalysisDataExport = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_OSV] != null) { + contents[_OSV] = (0, import_smithy_client.expectString)(output[_OSV]); + } + if (output[_Des] != null) { + contents[_Des] = de_AnalyticsExportDestination(output[_Des], context); + } + return contents; +}, "de_StorageClassAnalysisDataExport"); +var de_Tag = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_K] != null) { + contents[_K] = (0, import_smithy_client.expectString)(output[_K]); + } + if (output[_Va] != null) { + contents[_Va] = (0, import_smithy_client.expectString)(output[_Va]); + } + return contents; +}, "de_Tag"); +var de_TagSet = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Tag(entry, context); + }); +}, "de_TagSet"); +var de_TargetGrant = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Gra] != null) { + contents[_Gra] = de_Grantee(output[_Gra], context); + } + if (output[_Pe] != null) { + contents[_Pe] = (0, import_smithy_client.expectString)(output[_Pe]); + } + return contents; +}, "de_TargetGrant"); +var de_TargetGrants = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_TargetGrant(entry, context); + }); +}, "de_TargetGrants"); +var de_TargetObjectKeyFormat = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_SPi] != null) { + contents[_SPi] = de_SimplePrefix(output[_SPi], context); + } + if (output[_PP] != null) { + contents[_PP] = de_PartitionedPrefix(output[_PP], context); + } + return contents; +}, "de_TargetObjectKeyFormat"); +var de_Tiering = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_AT] != null) { + contents[_AT] = (0, import_smithy_client.expectString)(output[_AT]); + } + return contents; +}, "de_Tiering"); +var de_TieringList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Tiering(entry, context); + }); +}, "de_TieringList"); +var de_TopicConfiguration = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_I] != null) { + contents[_I] = (0, import_smithy_client.expectString)(output[_I]); + } + if (output[_Top] != null) { + contents[_TA] = (0, import_smithy_client.expectString)(output[_Top]); + } + if (output.Event === "") { + contents[_Eve] = []; + } else if (output[_Ev] != null) { + contents[_Eve] = de_EventList((0, import_smithy_client.getArrayIfSingleItem)(output[_Ev]), context); + } + if (output[_F] != null) { + contents[_F] = de_NotificationConfigurationFilter(output[_F], context); + } + return contents; +}, "de_TopicConfiguration"); +var de_TopicConfigurationList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_TopicConfiguration(entry, context); + }); +}, "de_TopicConfigurationList"); +var de_Transition = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_Dat] != null) { + contents[_Dat] = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.parseRfc3339DateTimeWithOffset)(output[_Dat])); + } + if (output[_Da] != null) { + contents[_Da] = (0, import_smithy_client.strictParseInt32)(output[_Da]); + } + if (output[_SC] != null) { + contents[_SC] = (0, import_smithy_client.expectString)(output[_SC]); + } + return contents; +}, "de_Transition"); +var de_TransitionList = /* @__PURE__ */ __name((output, context) => { + return (output || []).filter((e) => e != null).map((entry) => { + return de_Transition(entry, context); + }); +}, "de_TransitionList"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); +var collectBodyString = /* @__PURE__ */ __name((streamBody, context) => (0, import_smithy_client.collectBody)(streamBody, context).then((body) => context.utf8Encoder(body)), "collectBodyString"); +var _A = "And"; +var _AAO = "AnalyticsAndOperator"; +var _AC = "AnalyticsConfiguration"; +var _ACL = "ACL"; +var _ACLc = "AccessControlList"; +var _ACLn = "AnalyticsConfigurationList"; +var _ACP = "AccessControlPolicy"; +var _ACT = "AccessControlTranslation"; +var _ACc = "AccelerateConfiguration"; +var _AD = "AbortDate"; +var _AED = "AnalyticsExportDestination"; +var _AF = "AnalyticsFilter"; +var _AH = "AllowedHeader"; +var _AHl = "AllowedHeaders"; +var _AI = "AnalyticsId"; +var _AIMU = "AbortIncompleteMultipartUpload"; +var _AIc = "AccountId"; +var _AKI = "AccessKeyId"; +var _AM = "AllowedMethod"; +var _AMl = "AllowedMethods"; +var _AO = "AllowedOrigin"; +var _AOl = "AllowedOrigins"; +var _APA = "AccessPointAlias"; +var _APAc = "AccessPointArn"; +var _AQRD = "AllowQuotedRecordDelimiter"; +var _AR = "AcceptRanges"; +var _ARI = "AbortRuleId"; +var _AS = "ArchiveStatus"; +var _ASBD = "AnalyticsS3BucketDestination"; +var _ASEFF = "AnalyticsS3ExportFileFormat"; +var _ASSEBD = "ApplyServerSideEncryptionByDefault"; +var _AT = "AccessTier"; +var _Ac = "Account"; +var _B = "Bucket"; +var _BA = "BucketArn"; +var _BAI = "BucketAccountId"; +var _BAS = "BucketAccelerateStatus"; +var _BGR = "BypassGovernanceRetention"; +var _BI = "BucketInfo"; +var _BKE = "BucketKeyEnabled"; +var _BLC = "BucketLifecycleConfiguration"; +var _BLCu = "BucketLocationConstraint"; +var _BLN = "BucketLocationName"; +var _BLP = "BucketLogsPermission"; +var _BLS = "BucketLoggingStatus"; +var _BLT = "BucketLocationType"; +var _BN = "BucketName"; +var _BP = "BytesProcessed"; +var _BPA = "BlockPublicAcls"; +var _BPP = "BlockPublicPolicy"; +var _BR = "BucketRegion"; +var _BRy = "BytesReturned"; +var _BS = "BytesScanned"; +var _BT = "BucketType"; +var _BVS = "BucketVersioningStatus"; +var _Bu = "Buckets"; +var _C = "Credentials"; +var _CA = "ChecksumAlgorithm"; +var _CACL = "CannedACL"; +var _CBC = "CreateBucketConfiguration"; +var _CC = "CacheControl"; +var _CCRC = "ChecksumCRC32"; +var _CCRCC = "ChecksumCRC32C"; +var _CCRCNVME = "ChecksumCRC64NVME"; +var _CD = "ContentDisposition"; +var _CDr = "CreationDate"; +var _CE = "ContentEncoding"; +var _CF = "CloudFunction"; +var _CFC = "CloudFunctionConfiguration"; +var _CL = "ContentLanguage"; +var _CLo = "ContentLength"; +var _CM = "ChecksumMode"; +var _CMD = "ContentMD5"; +var _CMU = "CompletedMultipartUpload"; +var _CORSC = "CORSConfiguration"; +var _CORSR = "CORSRule"; +var _CORSRu = "CORSRules"; +var _CP = "CommonPrefixes"; +var _CPo = "CompletedPart"; +var _CR = "ContentRange"; +var _CRSBA = "ConfirmRemoveSelfBucketAccess"; +var _CS = "CopySource"; +var _CSHA = "ChecksumSHA1"; +var _CSHAh = "ChecksumSHA256"; +var _CSIM = "CopySourceIfMatch"; +var _CSIMS = "CopySourceIfModifiedSince"; +var _CSINM = "CopySourceIfNoneMatch"; +var _CSIUS = "CopySourceIfUnmodifiedSince"; +var _CSR = "CopySourceRange"; +var _CSSSECA = "CopySourceSSECustomerAlgorithm"; +var _CSSSECK = "CopySourceSSECustomerKey"; +var _CSSSECKMD = "CopySourceSSECustomerKeyMD5"; +var _CSV = "CSV"; +var _CSVI = "CopySourceVersionId"; +var _CSVIn = "CSVInput"; +var _CSVO = "CSVOutput"; +var _CSo = "ConfigurationState"; +var _CT = "ChecksumType"; +var _CTl = "ClientToken"; +var _CTo = "ContentType"; +var _CTom = "CompressionType"; +var _CTon = "ContinuationToken"; +var _Ch = "Checksum"; +var _Co = "Contents"; +var _Cod = "Code"; +var _Com = "Comments"; +var _Con = "Condition"; +var _D = "Delimiter"; +var _DAI = "DaysAfterInitiation"; +var _DE = "DataExport"; +var _DIM = "DestinationIfMatch"; +var _DIMS = "DestinationIfModifiedSince"; +var _DINM = "DestinationIfNoneMatch"; +var _DIUS = "DestinationIfUnmodifiedSince"; +var _DM = "DeleteMarker"; +var _DMR = "DeleteMarkerReplication"; +var _DMRS = "DeleteMarkerReplicationStatus"; +var _DMVI = "DeleteMarkerVersionId"; +var _DMe = "DeleteMarkers"; +var _DN = "DisplayName"; +var _DR = "DataRedundancy"; +var _DRe = "DefaultRetention"; +var _DRes = "DestinationResult"; +var _Da = "Days"; +var _Dat = "Date"; +var _De = "Deleted"; +var _Del = "Delete"; +var _Des = "Destination"; +var _Desc = "Description"; +var _E = "Expires"; +var _EA = "EmailAddress"; +var _EBC = "EventBridgeConfiguration"; +var _EBO = "ExpectedBucketOwner"; +var _EC = "ErrorCode"; +var _ECn = "EncryptionConfiguration"; +var _ED = "ErrorDocument"; +var _EH = "ExposeHeaders"; +var _EHx = "ExposeHeader"; +var _EM = "ErrorMessage"; +var _EODM = "ExpiredObjectDeleteMarker"; +var _EOR = "ExistingObjectReplication"; +var _EORS = "ExistingObjectReplicationStatus"; +var _ERP = "EnableRequestProgress"; +var _ES = "ExpiresString"; +var _ESBO = "ExpectedSourceBucketOwner"; +var _ESx = "ExpirationStatus"; +var _ESxp = "ExpirationState"; +var _ET = "EncodingType"; +var _ETa = "ETag"; +var _ETn = "EncryptionType"; +var _ETv = "EventThreshold"; +var _ETx = "ExpressionType"; +var _En = "Encryption"; +var _Ena = "Enabled"; +var _End = "End"; +var _Er = "Error"; +var _Err = "Errors"; +var _Ev = "Event"; +var _Eve = "Events"; +var _Ex = "Expression"; +var _Exp = "Expiration"; +var _F = "Filter"; +var _FD = "FieldDelimiter"; +var _FHI = "FileHeaderInfo"; +var _FO = "FetchOwner"; +var _FR = "FilterRule"; +var _FRN = "FilterRuleName"; +var _FRV = "FilterRuleValue"; +var _FRi = "FilterRules"; +var _Fi = "Field"; +var _Fo = "Format"; +var _Fr = "Frequency"; +var _G = "Grant"; +var _GFC = "GrantFullControl"; +var _GJP = "GlacierJobParameters"; +var _GR = "GrantRead"; +var _GRACP = "GrantReadACP"; +var _GW = "GrantWrite"; +var _GWACP = "GrantWriteACP"; +var _Gr = "Grants"; +var _Gra = "Grantee"; +var _HECRE = "HttpErrorCodeReturnedEquals"; +var _HN = "HostName"; +var _HRC = "HttpRedirectCode"; +var _I = "Id"; +var _IC = "InventoryConfiguration"; +var _ICL = "InventoryConfigurationList"; +var _ICS = "InventoryConfigurationState"; +var _ID = "IndexDocument"; +var _ID_ = "ID"; +var _IDn = "InventoryDestination"; +var _IE = "IsEnabled"; +var _IEn = "InventoryEncryption"; +var _IF = "InventoryFilter"; +var _IFn = "InventoryFormat"; +var _IFnv = "InventoryFrequency"; +var _II = "InventoryId"; +var _IIOV = "InventoryIncludedObjectVersions"; +var _IL = "IsLatest"; +var _IM = "IfMatch"; +var _IMIT = "IfMatchInitiatedTime"; +var _IMLMT = "IfMatchLastModifiedTime"; +var _IMS = "IfMatchSize"; +var _IMSf = "IfModifiedSince"; +var _INM = "IfNoneMatch"; +var _IOF = "InventoryOptionalField"; +var _IOV = "IncludedObjectVersions"; +var _IP = "IsPublic"; +var _IPA = "IgnorePublicAcls"; +var _IRIP = "IsRestoreInProgress"; +var _IS = "InputSerialization"; +var _ISBD = "InventoryS3BucketDestination"; +var _ISn = "InventorySchedule"; +var _IT = "IsTruncated"; +var _ITAO = "IntelligentTieringAndOperator"; +var _ITAT = "IntelligentTieringAccessTier"; +var _ITC = "IntelligentTieringConfiguration"; +var _ITCL = "IntelligentTieringConfigurationList"; +var _ITCR = "InventoryTableConfigurationResult"; +var _ITCU = "InventoryTableConfigurationUpdates"; +var _ITCn = "InventoryTableConfiguration"; +var _ITD = "IntelligentTieringDays"; +var _ITF = "IntelligentTieringFilter"; +var _ITI = "IntelligentTieringId"; +var _ITS = "IntelligentTieringStatus"; +var _IUS = "IfUnmodifiedSince"; +var _In = "Initiator"; +var _Ini = "Initiated"; +var _JSON = "JSON"; +var _JSONI = "JSONInput"; +var _JSONO = "JSONOutput"; +var _JSONT = "JSONType"; +var _JTC = "JournalTableConfiguration"; +var _JTCR = "JournalTableConfigurationResult"; +var _JTCU = "JournalTableConfigurationUpdates"; +var _K = "Key"; +var _KC = "KeyCount"; +var _KI = "KeyId"; +var _KKA = "KmsKeyArn"; +var _KM = "KeyMarker"; +var _KMSC = "KMSContext"; +var _KMSKI = "KMSKeyId"; +var _KMSMKID = "KMSMasterKeyID"; +var _KPE = "KeyPrefixEquals"; +var _L = "Location"; +var _LC = "LocationConstraint"; +var _LE = "LoggingEnabled"; +var _LEi = "LifecycleExpiration"; +var _LFA = "LambdaFunctionArn"; +var _LFC = "LambdaFunctionConfigurations"; +var _LFCa = "LambdaFunctionConfiguration"; +var _LI = "LocationInfo"; +var _LM = "LastModified"; +var _LMT = "LastModifiedTime"; +var _LNAS = "LocationNameAsString"; +var _LP = "LocationPrefix"; +var _LR = "LifecycleRule"; +var _LRAO = "LifecycleRuleAndOperator"; +var _LRF = "LifecycleRuleFilter"; +var _LT = "LocationType"; +var _M = "Marker"; +var _MAO = "MetricsAndOperator"; +var _MAS = "MaxAgeSeconds"; +var _MB = "MaxBuckets"; +var _MC = "MetricsConfiguration"; +var _MCL = "MetricsConfigurationList"; +var _MCR = "MetadataConfigurationResult"; +var _MCe = "MetadataConfiguration"; +var _MD = "MetadataDirective"; +var _MDB = "MaxDirectoryBuckets"; +var _MDf = "MfaDelete"; +var _ME = "MetadataEntry"; +var _MF = "MetricsFilter"; +var _MFA = "MFA"; +var _MFAD = "MFADelete"; +var _MI = "MetricsId"; +var _MK = "MaxKeys"; +var _MKe = "MetadataKey"; +var _MM = "MissingMeta"; +var _MOS = "MpuObjectSize"; +var _MP = "MaxParts"; +var _MS = "MetricsStatus"; +var _MTC = "MetadataTableConfiguration"; +var _MTCR = "MetadataTableConfigurationResult"; +var _MTEC = "MetadataTableEncryptionConfiguration"; +var _MU = "MaxUploads"; +var _MV = "MetadataValue"; +var _Me = "Metrics"; +var _Mes = "Message"; +var _Mi = "Minutes"; +var _Mo = "Mode"; +var _N = "Name"; +var _NC = "NotificationConfiguration"; +var _NCF = "NotificationConfigurationFilter"; +var _NCT = "NextContinuationToken"; +var _ND = "NoncurrentDays"; +var _NI = "NotificationId"; +var _NKM = "NextKeyMarker"; +var _NM = "NextMarker"; +var _NNV = "NewerNoncurrentVersions"; +var _NPNM = "NextPartNumberMarker"; +var _NUIM = "NextUploadIdMarker"; +var _NVE = "NoncurrentVersionExpiration"; +var _NVIM = "NextVersionIdMarker"; +var _NVT = "NoncurrentVersionTransitions"; +var _NVTo = "NoncurrentVersionTransition"; +var _O = "Owner"; +var _OA = "ObjectAttributes"; +var _OC = "OwnershipControls"; +var _OCACL = "ObjectCannedACL"; +var _OCR = "OwnershipControlsRule"; +var _OF = "OptionalFields"; +var _OI = "ObjectIdentifier"; +var _OK = "ObjectKey"; +var _OL = "OutputLocation"; +var _OLC = "ObjectLockConfiguration"; +var _OLE = "ObjectLockEnabled"; +var _OLEFB = "ObjectLockEnabledForBucket"; +var _OLLH = "ObjectLockLegalHold"; +var _OLLHS = "ObjectLockLegalHoldStatus"; +var _OLM = "ObjectLockMode"; +var _OLR = "ObjectLockRetention"; +var _OLRM = "ObjectLockRetentionMode"; +var _OLRUD = "ObjectLockRetainUntilDate"; +var _OLRb = "ObjectLockRule"; +var _OO = "ObjectOwnership"; +var _OOA = "OptionalObjectAttributes"; +var _OOw = "OwnerOverride"; +var _OP = "ObjectParts"; +var _OS = "OutputSerialization"; +var _OSGT = "ObjectSizeGreaterThan"; +var _OSGTB = "ObjectSizeGreaterThanBytes"; +var _OSLT = "ObjectSizeLessThan"; +var _OSLTB = "ObjectSizeLessThanBytes"; +var _OSV = "OutputSchemaVersion"; +var _OSb = "ObjectSize"; +var _OVI = "ObjectVersionId"; +var _Ob = "Objects"; +var _P = "Prefix"; +var _PABC = "PublicAccessBlockConfiguration"; +var _PC = "PartsCount"; +var _PDS = "PartitionDateSource"; +var _PI = "ParquetInput"; +var _PN = "PartNumber"; +var _PNM = "PartNumberMarker"; +var _PP = "PartitionedPrefix"; +var _Pa = "Payer"; +var _Par = "Part"; +var _Parq = "Parquet"; +var _Part = "Parts"; +var _Pe = "Permission"; +var _Pr = "Protocol"; +var _Pri = "Priority"; +var _Q = "Quiet"; +var _QA = "QueueArn"; +var _QC = "QueueConfiguration"; +var _QCu = "QueueConfigurations"; +var _QCuo = "QuoteCharacter"; +var _QEC = "QuoteEscapeCharacter"; +var _QF = "QuoteFields"; +var _Qu = "Queue"; +var _R = "Range"; +var _RART = "RedirectAllRequestsTo"; +var _RC = "RequestCharged"; +var _RCC = "ResponseCacheControl"; +var _RCD = "ResponseContentDisposition"; +var _RCE = "ResponseContentEncoding"; +var _RCL = "ResponseContentLanguage"; +var _RCT = "ResponseContentType"; +var _RCe = "ReplicationConfiguration"; +var _RD = "RecordDelimiter"; +var _RE = "ResponseExpires"; +var _RED = "RecordExpirationDays"; +var _REDe = "RestoreExpiryDate"; +var _REe = "RecordExpiration"; +var _RKKID = "ReplicaKmsKeyID"; +var _RKPW = "ReplaceKeyPrefixWith"; +var _RKW = "ReplaceKeyWith"; +var _RM = "ReplicaModifications"; +var _RMS = "ReplicaModificationsStatus"; +var _ROP = "RestoreOutputPath"; +var _RP = "RequestPayer"; +var _RPB = "RestrictPublicBuckets"; +var _RPC = "RequestPaymentConfiguration"; +var _RPe = "RequestProgress"; +var _RR = "RequestRoute"; +var _RRAO = "ReplicationRuleAndOperator"; +var _RRF = "ReplicationRuleFilter"; +var _RRS = "ReplicationRuleStatus"; +var _RRT = "RestoreRequestType"; +var _RRe = "ReplicationRule"; +var _RRes = "RestoreRequest"; +var _RRo = "RoutingRules"; +var _RRou = "RoutingRule"; +var _RS = "RenameSource"; +var _RSe = "ReplicationStatus"; +var _RSes = "RestoreStatus"; +var _RT = "RequestToken"; +var _RTS = "ReplicationTimeStatus"; +var _RTV = "ReplicationTimeValue"; +var _RTe = "ReplicationTime"; +var _RUD = "RetainUntilDate"; +var _Re = "Restore"; +var _Red = "Redirect"; +var _Ro = "Role"; +var _Ru = "Rule"; +var _Rul = "Rules"; +var _S = "Status"; +var _SA = "StartAfter"; +var _SAK = "SecretAccessKey"; +var _SAs = "SseAlgorithm"; +var _SBD = "S3BucketDestination"; +var _SC = "StorageClass"; +var _SCA = "StorageClassAnalysis"; +var _SCADE = "StorageClassAnalysisDataExport"; +var _SCASV = "StorageClassAnalysisSchemaVersion"; +var _SCt = "StatusCode"; +var _SDV = "SkipDestinationValidation"; +var _SIM = "SourceIfMatch"; +var _SIMS = "SourceIfModifiedSince"; +var _SINM = "SourceIfNoneMatch"; +var _SIUS = "SourceIfUnmodifiedSince"; +var _SK = "SSE-KMS"; +var _SKEO = "SseKmsEncryptedObjects"; +var _SKEOS = "SseKmsEncryptedObjectsStatus"; +var _SKF = "S3KeyFilter"; +var _SKe = "S3Key"; +var _SL = "S3Location"; +var _SM = "SessionMode"; +var _SOCR = "SelectObjectContentRequest"; +var _SP = "SelectParameters"; +var _SPi = "SimplePrefix"; +var _SR = "ScanRange"; +var _SS = "SSE-S3"; +var _SSC = "SourceSelectionCriteria"; +var _SSE = "ServerSideEncryption"; +var _SSEA = "SSEAlgorithm"; +var _SSEBD = "ServerSideEncryptionByDefault"; +var _SSEC = "ServerSideEncryptionConfiguration"; +var _SSECA = "SSECustomerAlgorithm"; +var _SSECK = "SSECustomerKey"; +var _SSECKMD = "SSECustomerKeyMD5"; +var _SSEKMS = "SSEKMS"; +var _SSEKMSEC = "SSEKMSEncryptionContext"; +var _SSEKMSKI = "SSEKMSKeyId"; +var _SSER = "ServerSideEncryptionRule"; +var _SSES = "SSES3"; +var _ST = "SessionToken"; +var _STBA = "S3TablesBucketArn"; +var _STD = "S3TablesDestination"; +var _STDR = "S3TablesDestinationResult"; +var _STN = "S3TablesName"; +var _S_ = "S3"; +var _Sc = "Schedule"; +var _Se = "Setting"; +var _Si = "Size"; +var _St = "Start"; +var _Su = "Suffix"; +var _T = "Tagging"; +var _TA = "TopicArn"; +var _TAa = "TableArn"; +var _TB = "TargetBucket"; +var _TBA = "TableBucketArn"; +var _TBT = "TableBucketType"; +var _TC = "TagCount"; +var _TCo = "TopicConfiguration"; +var _TCop = "TopicConfigurations"; +var _TD = "TaggingDirective"; +var _TDMOS = "TransitionDefaultMinimumObjectSize"; +var _TG = "TargetGrants"; +var _TGa = "TargetGrant"; +var _TN = "TableName"; +var _TNa = "TableNamespace"; +var _TOKF = "TargetObjectKeyFormat"; +var _TP = "TargetPrefix"; +var _TPC = "TotalPartsCount"; +var _TS = "TagSet"; +var _TSA = "TableSseAlgorithm"; +var _TSC = "TransitionStorageClass"; +var _TSa = "TableStatus"; +var _Ta = "Tag"; +var _Tag = "Tags"; +var _Ti = "Tier"; +var _Tie = "Tierings"; +var _Tier = "Tiering"; +var _Tim = "Time"; +var _To = "Token"; +var _Top = "Topic"; +var _Tr = "Transitions"; +var _Tra = "Transition"; +var _Ty = "Type"; +var _U = "Upload"; +var _UI = "UploadId"; +var _UIM = "UploadIdMarker"; +var _UM = "UserMetadata"; +var _URI = "URI"; +var _Up = "Uploads"; +var _V = "Version"; +var _VC = "VersionCount"; +var _VCe = "VersioningConfiguration"; +var _VI = "VersionId"; +var _VIM = "VersionIdMarker"; +var _Va = "Value"; +var _Ve = "Versions"; +var _WC = "WebsiteConfiguration"; +var _WOB = "WriteOffsetBytes"; +var _WRL = "WebsiteRedirectLocation"; +var _Y = "Years"; +var _a = "analytics"; +var _ac = "accelerate"; +var _acl = "acl"; +var _ar = "accept-ranges"; +var _at = "attributes"; +var _br = "bucket-region"; +var _c = "cors"; +var _cc = "cache-control"; +var _cd = "content-disposition"; +var _ce = "content-encoding"; +var _cl = "content-language"; +var _cl_ = "content-length"; +var _cm = "content-md5"; +var _cr = "content-range"; +var _ct = "content-type"; +var _ct_ = "continuation-token"; +var _d = "delete"; +var _de = "delimiter"; +var _e = "expires"; +var _en = "encryption"; +var _et = "encoding-type"; +var _eta = "etag"; +var _ex = "expiresstring"; +var _fo = "fetch-owner"; +var _i = "id"; +var _im = "if-match"; +var _ims = "if-modified-since"; +var _in = "inventory"; +var _inm = "if-none-match"; +var _it = "intelligent-tiering"; +var _ius = "if-unmodified-since"; +var _km = "key-marker"; +var _l = "lifecycle"; +var _lh = "legal-hold"; +var _lm = "last-modified"; +var _lo = "location"; +var _log = "logging"; +var _lt = "list-type"; +var _m = "metrics"; +var _mC = "metadataConfiguration"; +var _mIT = "metadataInventoryTable"; +var _mJT = "metadataJournalTable"; +var _mT = "metadataTable"; +var _ma = "marker"; +var _mb = "max-buckets"; +var _mdb = "max-directory-buckets"; +var _me = "member"; +var _mk = "max-keys"; +var _mp = "max-parts"; +var _mu = "max-uploads"; +var _n = "notification"; +var _oC = "ownershipControls"; +var _ol = "object-lock"; +var _p = "policy"; +var _pAB = "publicAccessBlock"; +var _pN = "partNumber"; +var _pS = "policyStatus"; +var _pnm = "part-number-marker"; +var _pr = "prefix"; +var _r = "replication"; +var _rO = "renameObject"; +var _rP = "requestPayment"; +var _ra = "range"; +var _rcc = "response-cache-control"; +var _rcd = "response-content-disposition"; +var _rce = "response-content-encoding"; +var _rcl = "response-content-language"; +var _rct = "response-content-type"; +var _re = "response-expires"; +var _res = "restore"; +var _ret = "retention"; +var _s = "session"; +var _sa = "start-after"; +var _se = "select"; +var _st = "select-type"; +var _t = "tagging"; +var _to = "torrent"; +var _u = "uploads"; +var _uI = "uploadId"; +var _uim = "upload-id-marker"; +var _v = "versioning"; +var _vI = "versionId"; +var _ve = ''; +var _ver = "versions"; +var _vim = "version-id-marker"; +var _w = "website"; +var _x = "xsi:type"; +var _xaa = "x-amz-acl"; +var _xaad = "x-amz-abort-date"; +var _xaapa = "x-amz-access-point-alias"; +var _xaari = "x-amz-abort-rule-id"; +var _xaas = "x-amz-archive-status"; +var _xaba = "x-amz-bucket-arn"; +var _xabgr = "x-amz-bypass-governance-retention"; +var _xabln = "x-amz-bucket-location-name"; +var _xablt = "x-amz-bucket-location-type"; +var _xabole = "x-amz-bucket-object-lock-enabled"; +var _xabolt = "x-amz-bucket-object-lock-token"; +var _xabr = "x-amz-bucket-region"; +var _xaca = "x-amz-checksum-algorithm"; +var _xacc = "x-amz-checksum-crc32"; +var _xacc_ = "x-amz-checksum-crc32c"; +var _xacc__ = "x-amz-checksum-crc64nvme"; +var _xacm = "x-amz-checksum-mode"; +var _xacrsba = "x-amz-confirm-remove-self-bucket-access"; +var _xacs = "x-amz-checksum-sha1"; +var _xacs_ = "x-amz-checksum-sha256"; +var _xacs__ = "x-amz-copy-source"; +var _xacsim = "x-amz-copy-source-if-match"; +var _xacsims = "x-amz-copy-source-if-modified-since"; +var _xacsinm = "x-amz-copy-source-if-none-match"; +var _xacsius = "x-amz-copy-source-if-unmodified-since"; +var _xacsm = "x-amz-create-session-mode"; +var _xacsr = "x-amz-copy-source-range"; +var _xacssseca = "x-amz-copy-source-server-side-encryption-customer-algorithm"; +var _xacssseck = "x-amz-copy-source-server-side-encryption-customer-key"; +var _xacssseckm = "x-amz-copy-source-server-side-encryption-customer-key-md5"; +var _xacsvi = "x-amz-copy-source-version-id"; +var _xact = "x-amz-checksum-type"; +var _xact_ = "x-amz-client-token"; +var _xadm = "x-amz-delete-marker"; +var _xae = "x-amz-expiration"; +var _xaebo = "x-amz-expected-bucket-owner"; +var _xafec = "x-amz-fwd-error-code"; +var _xafem = "x-amz-fwd-error-message"; +var _xafhar = "x-amz-fwd-header-accept-ranges"; +var _xafhcc = "x-amz-fwd-header-cache-control"; +var _xafhcd = "x-amz-fwd-header-content-disposition"; +var _xafhce = "x-amz-fwd-header-content-encoding"; +var _xafhcl = "x-amz-fwd-header-content-language"; +var _xafhcr = "x-amz-fwd-header-content-range"; +var _xafhct = "x-amz-fwd-header-content-type"; +var _xafhe = "x-amz-fwd-header-etag"; +var _xafhe_ = "x-amz-fwd-header-expires"; +var _xafhlm = "x-amz-fwd-header-last-modified"; +var _xafhxacc = "x-amz-fwd-header-x-amz-checksum-crc32"; +var _xafhxacc_ = "x-amz-fwd-header-x-amz-checksum-crc32c"; +var _xafhxacc__ = "x-amz-fwd-header-x-amz-checksum-crc64nvme"; +var _xafhxacs = "x-amz-fwd-header-x-amz-checksum-sha1"; +var _xafhxacs_ = "x-amz-fwd-header-x-amz-checksum-sha256"; +var _xafhxadm = "x-amz-fwd-header-x-amz-delete-marker"; +var _xafhxae = "x-amz-fwd-header-x-amz-expiration"; +var _xafhxamm = "x-amz-fwd-header-x-amz-missing-meta"; +var _xafhxampc = "x-amz-fwd-header-x-amz-mp-parts-count"; +var _xafhxaollh = "x-amz-fwd-header-x-amz-object-lock-legal-hold"; +var _xafhxaolm = "x-amz-fwd-header-x-amz-object-lock-mode"; +var _xafhxaolrud = "x-amz-fwd-header-x-amz-object-lock-retain-until-date"; +var _xafhxar = "x-amz-fwd-header-x-amz-restore"; +var _xafhxarc = "x-amz-fwd-header-x-amz-request-charged"; +var _xafhxars = "x-amz-fwd-header-x-amz-replication-status"; +var _xafhxasc = "x-amz-fwd-header-x-amz-storage-class"; +var _xafhxasse = "x-amz-fwd-header-x-amz-server-side-encryption"; +var _xafhxasseakki = "x-amz-fwd-header-x-amz-server-side-encryption-aws-kms-key-id"; +var _xafhxassebke = "x-amz-fwd-header-x-amz-server-side-encryption-bucket-key-enabled"; +var _xafhxasseca = "x-amz-fwd-header-x-amz-server-side-encryption-customer-algorithm"; +var _xafhxasseckm = "x-amz-fwd-header-x-amz-server-side-encryption-customer-key-md5"; +var _xafhxatc = "x-amz-fwd-header-x-amz-tagging-count"; +var _xafhxavi = "x-amz-fwd-header-x-amz-version-id"; +var _xafs = "x-amz-fwd-status"; +var _xagfc = "x-amz-grant-full-control"; +var _xagr = "x-amz-grant-read"; +var _xagra = "x-amz-grant-read-acp"; +var _xagw = "x-amz-grant-write"; +var _xagwa = "x-amz-grant-write-acp"; +var _xaimit = "x-amz-if-match-initiated-time"; +var _xaimlmt = "x-amz-if-match-last-modified-time"; +var _xaims = "x-amz-if-match-size"; +var _xam = "x-amz-mfa"; +var _xamd = "x-amz-metadata-directive"; +var _xamm = "x-amz-missing-meta"; +var _xamos = "x-amz-mp-object-size"; +var _xamp = "x-amz-max-parts"; +var _xampc = "x-amz-mp-parts-count"; +var _xaoa = "x-amz-object-attributes"; +var _xaollh = "x-amz-object-lock-legal-hold"; +var _xaolm = "x-amz-object-lock-mode"; +var _xaolrud = "x-amz-object-lock-retain-until-date"; +var _xaoo = "x-amz-object-ownership"; +var _xaooa = "x-amz-optional-object-attributes"; +var _xaos = "x-amz-object-size"; +var _xapnm = "x-amz-part-number-marker"; +var _xar = "x-amz-restore"; +var _xarc = "x-amz-request-charged"; +var _xarop = "x-amz-restore-output-path"; +var _xarp = "x-amz-request-payer"; +var _xarr = "x-amz-request-route"; +var _xars = "x-amz-rename-source"; +var _xars_ = "x-amz-replication-status"; +var _xarsim = "x-amz-rename-source-if-match"; +var _xarsims = "x-amz-rename-source-if-modified-since"; +var _xarsinm = "x-amz-rename-source-if-none-match"; +var _xarsius = "x-amz-rename-source-if-unmodified-since"; +var _xart = "x-amz-request-token"; +var _xasc = "x-amz-storage-class"; +var _xasca = "x-amz-sdk-checksum-algorithm"; +var _xasdv = "x-amz-skip-destination-validation"; +var _xasebo = "x-amz-source-expected-bucket-owner"; +var _xasse = "x-amz-server-side-encryption"; +var _xasseakki = "x-amz-server-side-encryption-aws-kms-key-id"; +var _xassebke = "x-amz-server-side-encryption-bucket-key-enabled"; +var _xassec = "x-amz-server-side-encryption-context"; +var _xasseca = "x-amz-server-side-encryption-customer-algorithm"; +var _xasseck = "x-amz-server-side-encryption-customer-key"; +var _xasseckm = "x-amz-server-side-encryption-customer-key-md5"; +var _xat = "x-amz-tagging"; +var _xatc = "x-amz-tagging-count"; +var _xatd = "x-amz-tagging-directive"; +var _xatdmos = "x-amz-transition-default-minimum-object-size"; +var _xavi = "x-amz-version-id"; +var _xawob = "x-amz-write-offset-bytes"; +var _xawrl = "x-amz-website-redirect-location"; +var _xi = "x-id"; + +// src/commands/CreateSessionCommand.ts +var CreateSessionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s3.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "CreateSession", {}).n("S3Client", "CreateSessionCommand").f(CreateSessionRequestFilterSensitiveLog, CreateSessionOutputFilterSensitiveLog).ser(se_CreateSessionCommand).de(de_CreateSessionCommand).build() { + static { + __name(this, "CreateSessionCommand"); + } +}; + +// src/S3Client.ts +var import_runtimeConfig = __nccwpck_require__(35745); + +// src/runtimeExtensions.ts +var import_region_config_resolver = __nccwpck_require__(36463); + + + +// src/auth/httpAuthExtensionConfiguration.ts +var getHttpAuthExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + } + }; +}, "getHttpAuthExtensionConfiguration"); +var resolveHttpAuthRuntimeConfig = /* @__PURE__ */ __name((config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials() + }; +}, "resolveHttpAuthRuntimeConfig"); + +// src/runtimeExtensions.ts +var resolveRuntimeExtensions = /* @__PURE__ */ __name((runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign( + (0, import_region_config_resolver.getAwsRegionExtensionConfiguration)(runtimeConfig), + (0, import_smithy_client.getDefaultExtensionConfiguration)(runtimeConfig), + (0, import_protocol_http.getHttpHandlerExtensionConfiguration)(runtimeConfig), + getHttpAuthExtensionConfiguration(runtimeConfig) + ); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign( + runtimeConfig, + (0, import_region_config_resolver.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), + (0, import_smithy_client.resolveDefaultRuntimeConfig)(extensionConfiguration), + (0, import_protocol_http.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), + resolveHttpAuthRuntimeConfig(extensionConfiguration) + ); +}, "resolveRuntimeExtensions"); + +// src/S3Client.ts +var S3Client = class extends import_smithy_client.Client { + static { + __name(this, "S3Client"); + } + /** + * The resolved configuration of S3Client class. This is resolved and normalized from the {@link S3ClientConfig | constructor configuration interface}. + */ + config; + constructor(...[configuration]) { + const _config_0 = (0, import_runtimeConfig.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = resolveClientEndpointParameters(_config_0); + const _config_2 = (0, import_middleware_user_agent.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, import_middleware_flexible_checksums.resolveFlexibleChecksumsConfig)(_config_2); + const _config_4 = (0, import_middleware_retry.resolveRetryConfig)(_config_3); + const _config_5 = (0, import_config_resolver.resolveRegionConfig)(_config_4); + const _config_6 = (0, import_middleware_host_header.resolveHostHeaderConfig)(_config_5); + const _config_7 = (0, import_middleware_endpoint.resolveEndpointConfig)(_config_6); + const _config_8 = (0, import_eventstream_serde_config_resolver.resolveEventStreamSerdeConfig)(_config_7); + const _config_9 = (0, import_httpAuthSchemeProvider.resolveHttpAuthSchemeConfig)(_config_8); + const _config_10 = (0, import_middleware_sdk_s32.resolveS3Config)(_config_9, { session: [() => this, CreateSessionCommand] }); + const _config_11 = resolveRuntimeExtensions(_config_10, configuration?.extensions || []); + this.config = _config_11; + this.middlewareStack.use((0, import_middleware_user_agent.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_retry.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_content_length.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_host_header.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_logger.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_recursion_detection.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use( + (0, import_core3.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: import_httpAuthSchemeProvider.defaultS3HttpAuthSchemeParametersProvider, + identityProviderConfigProvider: /* @__PURE__ */ __name(async (config) => new import_core3.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials, + "aws.auth#sigv4a": config.credentials + }), "identityProviderConfigProvider") + }) + ); + this.middlewareStack.use((0, import_core3.getHttpSigningPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getValidateBucketNamePlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_expect_continue.getAddExpectContinuePlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getRegionRedirectMiddlewarePlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getS3ExpressPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_sdk_s32.getS3ExpressHttpSigningPlugin)(this.config)); + } + /** + * Destroy underlying resources, like sockets. It's usually not necessary to do this. + * However in Node.js, it's best to explicitly shut down the client's agent when it is no longer needed. + * Otherwise, sockets might stay open for quite a long time before the server terminates them. + */ + destroy() { + super.destroy(); + } +}; + +// src/S3.ts + + +// src/commands/AbortMultipartUploadCommand.ts +var import_middleware_sdk_s33 = __nccwpck_require__(77445); + + + +var AbortMultipartUploadCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s33.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "AbortMultipartUpload", {}).n("S3Client", "AbortMultipartUploadCommand").f(void 0, void 0).ser(se_AbortMultipartUploadCommand).de(de_AbortMultipartUploadCommand).build() { + static { + __name(this, "AbortMultipartUploadCommand"); + } +}; + +// src/commands/CompleteMultipartUploadCommand.ts +var import_middleware_sdk_s34 = __nccwpck_require__(77445); +var import_middleware_ssec = __nccwpck_require__(35568); + + + +var CompleteMultipartUploadCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s34.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "CompleteMultipartUpload", {}).n("S3Client", "CompleteMultipartUploadCommand").f(CompleteMultipartUploadRequestFilterSensitiveLog, CompleteMultipartUploadOutputFilterSensitiveLog).ser(se_CompleteMultipartUploadCommand).de(de_CompleteMultipartUploadCommand).build() { + static { + __name(this, "CompleteMultipartUploadCommand"); + } +}; + +// src/commands/CopyObjectCommand.ts +var import_middleware_sdk_s35 = __nccwpck_require__(77445); + + + + +var CopyObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" }, + CopySource: { type: "contextParams", name: "CopySource" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s35.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "CopyObject", {}).n("S3Client", "CopyObjectCommand").f(CopyObjectRequestFilterSensitiveLog, CopyObjectOutputFilterSensitiveLog).ser(se_CopyObjectCommand).de(de_CopyObjectCommand).build() { + static { + __name(this, "CopyObjectCommand"); + } +}; + +// src/commands/CreateBucketCommand.ts +var import_middleware_location_constraint = __nccwpck_require__(23209); +var import_middleware_sdk_s36 = __nccwpck_require__(77445); + + + +var CreateBucketCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + DisableAccessPoints: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s36.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_location_constraint.getLocationConstraintPlugin)(config) + ]; +}).s("AmazonS3", "CreateBucket", {}).n("S3Client", "CreateBucketCommand").f(void 0, void 0).ser(se_CreateBucketCommand).de(de_CreateBucketCommand).build() { + static { + __name(this, "CreateBucketCommand"); + } +}; + +// src/commands/CreateBucketMetadataConfigurationCommand.ts + + + + +var CreateBucketMetadataConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "CreateBucketMetadataConfiguration", {}).n("S3Client", "CreateBucketMetadataConfigurationCommand").f(void 0, void 0).ser(se_CreateBucketMetadataConfigurationCommand).de(de_CreateBucketMetadataConfigurationCommand).build() { + static { + __name(this, "CreateBucketMetadataConfigurationCommand"); + } +}; + +// src/commands/CreateBucketMetadataTableConfigurationCommand.ts + + + + +var CreateBucketMetadataTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "CreateBucketMetadataTableConfiguration", {}).n("S3Client", "CreateBucketMetadataTableConfigurationCommand").f(void 0, void 0).ser(se_CreateBucketMetadataTableConfigurationCommand).de(de_CreateBucketMetadataTableConfigurationCommand).build() { + static { + __name(this, "CreateBucketMetadataTableConfigurationCommand"); + } +}; + +// src/commands/CreateMultipartUploadCommand.ts +var import_middleware_sdk_s37 = __nccwpck_require__(77445); + + + + +var CreateMultipartUploadCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s37.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "CreateMultipartUpload", {}).n("S3Client", "CreateMultipartUploadCommand").f(CreateMultipartUploadRequestFilterSensitiveLog, CreateMultipartUploadOutputFilterSensitiveLog).ser(se_CreateMultipartUploadCommand).de(de_CreateMultipartUploadCommand).build() { + static { + __name(this, "CreateMultipartUploadCommand"); + } +}; + +// src/commands/DeleteBucketAnalyticsConfigurationCommand.ts + + + +var DeleteBucketAnalyticsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketAnalyticsConfiguration", {}).n("S3Client", "DeleteBucketAnalyticsConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketAnalyticsConfigurationCommand).de(de_DeleteBucketAnalyticsConfigurationCommand).build() { + static { + __name(this, "DeleteBucketAnalyticsConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketCommand.ts + + + +var DeleteBucketCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucket", {}).n("S3Client", "DeleteBucketCommand").f(void 0, void 0).ser(se_DeleteBucketCommand).de(de_DeleteBucketCommand).build() { + static { + __name(this, "DeleteBucketCommand"); + } +}; + +// src/commands/DeleteBucketCorsCommand.ts + + + +var DeleteBucketCorsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketCors", {}).n("S3Client", "DeleteBucketCorsCommand").f(void 0, void 0).ser(se_DeleteBucketCorsCommand).de(de_DeleteBucketCorsCommand).build() { + static { + __name(this, "DeleteBucketCorsCommand"); + } +}; + +// src/commands/DeleteBucketEncryptionCommand.ts + + + +var DeleteBucketEncryptionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketEncryption", {}).n("S3Client", "DeleteBucketEncryptionCommand").f(void 0, void 0).ser(se_DeleteBucketEncryptionCommand).de(de_DeleteBucketEncryptionCommand).build() { + static { + __name(this, "DeleteBucketEncryptionCommand"); + } +}; + +// src/commands/DeleteBucketIntelligentTieringConfigurationCommand.ts + + + +var DeleteBucketIntelligentTieringConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketIntelligentTieringConfiguration", {}).n("S3Client", "DeleteBucketIntelligentTieringConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketIntelligentTieringConfigurationCommand).de(de_DeleteBucketIntelligentTieringConfigurationCommand).build() { + static { + __name(this, "DeleteBucketIntelligentTieringConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketInventoryConfigurationCommand.ts + + + +var DeleteBucketInventoryConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketInventoryConfiguration", {}).n("S3Client", "DeleteBucketInventoryConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketInventoryConfigurationCommand).de(de_DeleteBucketInventoryConfigurationCommand).build() { + static { + __name(this, "DeleteBucketInventoryConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketLifecycleCommand.ts + + + +var DeleteBucketLifecycleCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketLifecycle", {}).n("S3Client", "DeleteBucketLifecycleCommand").f(void 0, void 0).ser(se_DeleteBucketLifecycleCommand).de(de_DeleteBucketLifecycleCommand).build() { + static { + __name(this, "DeleteBucketLifecycleCommand"); + } +}; + +// src/commands/DeleteBucketMetadataConfigurationCommand.ts + + + +var DeleteBucketMetadataConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketMetadataConfiguration", {}).n("S3Client", "DeleteBucketMetadataConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketMetadataConfigurationCommand).de(de_DeleteBucketMetadataConfigurationCommand).build() { + static { + __name(this, "DeleteBucketMetadataConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketMetadataTableConfigurationCommand.ts + + + +var DeleteBucketMetadataTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketMetadataTableConfiguration", {}).n("S3Client", "DeleteBucketMetadataTableConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketMetadataTableConfigurationCommand).de(de_DeleteBucketMetadataTableConfigurationCommand).build() { + static { + __name(this, "DeleteBucketMetadataTableConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketMetricsConfigurationCommand.ts + + + +var DeleteBucketMetricsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketMetricsConfiguration", {}).n("S3Client", "DeleteBucketMetricsConfigurationCommand").f(void 0, void 0).ser(se_DeleteBucketMetricsConfigurationCommand).de(de_DeleteBucketMetricsConfigurationCommand).build() { + static { + __name(this, "DeleteBucketMetricsConfigurationCommand"); + } +}; + +// src/commands/DeleteBucketOwnershipControlsCommand.ts + + + +var DeleteBucketOwnershipControlsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketOwnershipControls", {}).n("S3Client", "DeleteBucketOwnershipControlsCommand").f(void 0, void 0).ser(se_DeleteBucketOwnershipControlsCommand).de(de_DeleteBucketOwnershipControlsCommand).build() { + static { + __name(this, "DeleteBucketOwnershipControlsCommand"); + } +}; + +// src/commands/DeleteBucketPolicyCommand.ts + + + +var DeleteBucketPolicyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketPolicy", {}).n("S3Client", "DeleteBucketPolicyCommand").f(void 0, void 0).ser(se_DeleteBucketPolicyCommand).de(de_DeleteBucketPolicyCommand).build() { + static { + __name(this, "DeleteBucketPolicyCommand"); + } +}; + +// src/commands/DeleteBucketReplicationCommand.ts + + + +var DeleteBucketReplicationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketReplication", {}).n("S3Client", "DeleteBucketReplicationCommand").f(void 0, void 0).ser(se_DeleteBucketReplicationCommand).de(de_DeleteBucketReplicationCommand).build() { + static { + __name(this, "DeleteBucketReplicationCommand"); + } +}; + +// src/commands/DeleteBucketTaggingCommand.ts + + + +var DeleteBucketTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketTagging", {}).n("S3Client", "DeleteBucketTaggingCommand").f(void 0, void 0).ser(se_DeleteBucketTaggingCommand).de(de_DeleteBucketTaggingCommand).build() { + static { + __name(this, "DeleteBucketTaggingCommand"); + } +}; + +// src/commands/DeleteBucketWebsiteCommand.ts + + + +var DeleteBucketWebsiteCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeleteBucketWebsite", {}).n("S3Client", "DeleteBucketWebsiteCommand").f(void 0, void 0).ser(se_DeleteBucketWebsiteCommand).de(de_DeleteBucketWebsiteCommand).build() { + static { + __name(this, "DeleteBucketWebsiteCommand"); + } +}; + +// src/commands/DeleteObjectCommand.ts +var import_middleware_sdk_s38 = __nccwpck_require__(77445); + + + +var DeleteObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s38.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "DeleteObject", {}).n("S3Client", "DeleteObjectCommand").f(void 0, void 0).ser(se_DeleteObjectCommand).de(de_DeleteObjectCommand).build() { + static { + __name(this, "DeleteObjectCommand"); + } +}; + +// src/commands/DeleteObjectsCommand.ts + +var import_middleware_sdk_s39 = __nccwpck_require__(77445); + + + +var DeleteObjectsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s39.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "DeleteObjects", {}).n("S3Client", "DeleteObjectsCommand").f(void 0, void 0).ser(se_DeleteObjectsCommand).de(de_DeleteObjectsCommand).build() { + static { + __name(this, "DeleteObjectsCommand"); + } +}; + +// src/commands/DeleteObjectTaggingCommand.ts +var import_middleware_sdk_s310 = __nccwpck_require__(77445); + + + +var DeleteObjectTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s310.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "DeleteObjectTagging", {}).n("S3Client", "DeleteObjectTaggingCommand").f(void 0, void 0).ser(se_DeleteObjectTaggingCommand).de(de_DeleteObjectTaggingCommand).build() { + static { + __name(this, "DeleteObjectTaggingCommand"); + } +}; + +// src/commands/DeletePublicAccessBlockCommand.ts + + + +var DeletePublicAccessBlockCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "DeletePublicAccessBlock", {}).n("S3Client", "DeletePublicAccessBlockCommand").f(void 0, void 0).ser(se_DeletePublicAccessBlockCommand).de(de_DeletePublicAccessBlockCommand).build() { + static { + __name(this, "DeletePublicAccessBlockCommand"); + } +}; + +// src/commands/GetBucketAccelerateConfigurationCommand.ts +var import_middleware_sdk_s311 = __nccwpck_require__(77445); + + + +var GetBucketAccelerateConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s311.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketAccelerateConfiguration", {}).n("S3Client", "GetBucketAccelerateConfigurationCommand").f(void 0, void 0).ser(se_GetBucketAccelerateConfigurationCommand).de(de_GetBucketAccelerateConfigurationCommand).build() { + static { + __name(this, "GetBucketAccelerateConfigurationCommand"); + } +}; + +// src/commands/GetBucketAclCommand.ts +var import_middleware_sdk_s312 = __nccwpck_require__(77445); + + + +var GetBucketAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s312.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketAcl", {}).n("S3Client", "GetBucketAclCommand").f(void 0, void 0).ser(se_GetBucketAclCommand).de(de_GetBucketAclCommand).build() { + static { + __name(this, "GetBucketAclCommand"); + } +}; + +// src/commands/GetBucketAnalyticsConfigurationCommand.ts +var import_middleware_sdk_s313 = __nccwpck_require__(77445); + + + +var GetBucketAnalyticsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s313.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketAnalyticsConfiguration", {}).n("S3Client", "GetBucketAnalyticsConfigurationCommand").f(void 0, void 0).ser(se_GetBucketAnalyticsConfigurationCommand).de(de_GetBucketAnalyticsConfigurationCommand).build() { + static { + __name(this, "GetBucketAnalyticsConfigurationCommand"); + } +}; + +// src/commands/GetBucketCorsCommand.ts +var import_middleware_sdk_s314 = __nccwpck_require__(77445); + + + +var GetBucketCorsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s314.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketCors", {}).n("S3Client", "GetBucketCorsCommand").f(void 0, void 0).ser(se_GetBucketCorsCommand).de(de_GetBucketCorsCommand).build() { + static { + __name(this, "GetBucketCorsCommand"); + } +}; + +// src/commands/GetBucketEncryptionCommand.ts +var import_middleware_sdk_s315 = __nccwpck_require__(77445); + + + +var GetBucketEncryptionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s315.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketEncryption", {}).n("S3Client", "GetBucketEncryptionCommand").f(void 0, GetBucketEncryptionOutputFilterSensitiveLog).ser(se_GetBucketEncryptionCommand).de(de_GetBucketEncryptionCommand).build() { + static { + __name(this, "GetBucketEncryptionCommand"); + } +}; + +// src/commands/GetBucketIntelligentTieringConfigurationCommand.ts +var import_middleware_sdk_s316 = __nccwpck_require__(77445); + + + +var GetBucketIntelligentTieringConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s316.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketIntelligentTieringConfiguration", {}).n("S3Client", "GetBucketIntelligentTieringConfigurationCommand").f(void 0, void 0).ser(se_GetBucketIntelligentTieringConfigurationCommand).de(de_GetBucketIntelligentTieringConfigurationCommand).build() { + static { + __name(this, "GetBucketIntelligentTieringConfigurationCommand"); + } +}; + +// src/commands/GetBucketInventoryConfigurationCommand.ts +var import_middleware_sdk_s317 = __nccwpck_require__(77445); + + + +var GetBucketInventoryConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s317.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketInventoryConfiguration", {}).n("S3Client", "GetBucketInventoryConfigurationCommand").f(void 0, GetBucketInventoryConfigurationOutputFilterSensitiveLog).ser(se_GetBucketInventoryConfigurationCommand).de(de_GetBucketInventoryConfigurationCommand).build() { + static { + __name(this, "GetBucketInventoryConfigurationCommand"); + } +}; + +// src/commands/GetBucketLifecycleConfigurationCommand.ts +var import_middleware_sdk_s318 = __nccwpck_require__(77445); + + + +var GetBucketLifecycleConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s318.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketLifecycleConfiguration", {}).n("S3Client", "GetBucketLifecycleConfigurationCommand").f(void 0, void 0).ser(se_GetBucketLifecycleConfigurationCommand).de(de_GetBucketLifecycleConfigurationCommand).build() { + static { + __name(this, "GetBucketLifecycleConfigurationCommand"); + } +}; + +// src/commands/GetBucketLocationCommand.ts +var import_middleware_sdk_s319 = __nccwpck_require__(77445); + + + +var GetBucketLocationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s319.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketLocation", {}).n("S3Client", "GetBucketLocationCommand").f(void 0, void 0).ser(se_GetBucketLocationCommand).de(de_GetBucketLocationCommand).build() { + static { + __name(this, "GetBucketLocationCommand"); + } +}; + +// src/commands/GetBucketLoggingCommand.ts +var import_middleware_sdk_s320 = __nccwpck_require__(77445); + + + +var GetBucketLoggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s320.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketLogging", {}).n("S3Client", "GetBucketLoggingCommand").f(void 0, void 0).ser(se_GetBucketLoggingCommand).de(de_GetBucketLoggingCommand).build() { + static { + __name(this, "GetBucketLoggingCommand"); + } +}; + +// src/commands/GetBucketMetadataConfigurationCommand.ts +var import_middleware_sdk_s321 = __nccwpck_require__(77445); + + + +var GetBucketMetadataConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s321.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketMetadataConfiguration", {}).n("S3Client", "GetBucketMetadataConfigurationCommand").f(void 0, void 0).ser(se_GetBucketMetadataConfigurationCommand).de(de_GetBucketMetadataConfigurationCommand).build() { + static { + __name(this, "GetBucketMetadataConfigurationCommand"); + } +}; + +// src/commands/GetBucketMetadataTableConfigurationCommand.ts +var import_middleware_sdk_s322 = __nccwpck_require__(77445); + + + +var GetBucketMetadataTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s322.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketMetadataTableConfiguration", {}).n("S3Client", "GetBucketMetadataTableConfigurationCommand").f(void 0, void 0).ser(se_GetBucketMetadataTableConfigurationCommand).de(de_GetBucketMetadataTableConfigurationCommand).build() { + static { + __name(this, "GetBucketMetadataTableConfigurationCommand"); + } +}; + +// src/commands/GetBucketMetricsConfigurationCommand.ts +var import_middleware_sdk_s323 = __nccwpck_require__(77445); + + + +var GetBucketMetricsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s323.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketMetricsConfiguration", {}).n("S3Client", "GetBucketMetricsConfigurationCommand").f(void 0, void 0).ser(se_GetBucketMetricsConfigurationCommand).de(de_GetBucketMetricsConfigurationCommand).build() { + static { + __name(this, "GetBucketMetricsConfigurationCommand"); + } +}; + +// src/commands/GetBucketNotificationConfigurationCommand.ts +var import_middleware_sdk_s324 = __nccwpck_require__(77445); + + + +var GetBucketNotificationConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s324.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketNotificationConfiguration", {}).n("S3Client", "GetBucketNotificationConfigurationCommand").f(void 0, void 0).ser(se_GetBucketNotificationConfigurationCommand).de(de_GetBucketNotificationConfigurationCommand).build() { + static { + __name(this, "GetBucketNotificationConfigurationCommand"); + } +}; + +// src/commands/GetBucketOwnershipControlsCommand.ts +var import_middleware_sdk_s325 = __nccwpck_require__(77445); + + + +var GetBucketOwnershipControlsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s325.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketOwnershipControls", {}).n("S3Client", "GetBucketOwnershipControlsCommand").f(void 0, void 0).ser(se_GetBucketOwnershipControlsCommand).de(de_GetBucketOwnershipControlsCommand).build() { + static { + __name(this, "GetBucketOwnershipControlsCommand"); + } +}; + +// src/commands/GetBucketPolicyCommand.ts +var import_middleware_sdk_s326 = __nccwpck_require__(77445); + + + +var GetBucketPolicyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s326.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketPolicy", {}).n("S3Client", "GetBucketPolicyCommand").f(void 0, void 0).ser(se_GetBucketPolicyCommand).de(de_GetBucketPolicyCommand).build() { + static { + __name(this, "GetBucketPolicyCommand"); + } +}; + +// src/commands/GetBucketPolicyStatusCommand.ts +var import_middleware_sdk_s327 = __nccwpck_require__(77445); + + + +var GetBucketPolicyStatusCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s327.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketPolicyStatus", {}).n("S3Client", "GetBucketPolicyStatusCommand").f(void 0, void 0).ser(se_GetBucketPolicyStatusCommand).de(de_GetBucketPolicyStatusCommand).build() { + static { + __name(this, "GetBucketPolicyStatusCommand"); + } +}; + +// src/commands/GetBucketReplicationCommand.ts +var import_middleware_sdk_s328 = __nccwpck_require__(77445); + + + +var GetBucketReplicationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s328.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketReplication", {}).n("S3Client", "GetBucketReplicationCommand").f(void 0, void 0).ser(se_GetBucketReplicationCommand).de(de_GetBucketReplicationCommand).build() { + static { + __name(this, "GetBucketReplicationCommand"); + } +}; + +// src/commands/GetBucketRequestPaymentCommand.ts +var import_middleware_sdk_s329 = __nccwpck_require__(77445); + + + +var GetBucketRequestPaymentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s329.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketRequestPayment", {}).n("S3Client", "GetBucketRequestPaymentCommand").f(void 0, void 0).ser(se_GetBucketRequestPaymentCommand).de(de_GetBucketRequestPaymentCommand).build() { + static { + __name(this, "GetBucketRequestPaymentCommand"); + } +}; + +// src/commands/GetBucketTaggingCommand.ts +var import_middleware_sdk_s330 = __nccwpck_require__(77445); + + + +var GetBucketTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s330.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketTagging", {}).n("S3Client", "GetBucketTaggingCommand").f(void 0, void 0).ser(se_GetBucketTaggingCommand).de(de_GetBucketTaggingCommand).build() { + static { + __name(this, "GetBucketTaggingCommand"); + } +}; + +// src/commands/GetBucketVersioningCommand.ts +var import_middleware_sdk_s331 = __nccwpck_require__(77445); + + + +var GetBucketVersioningCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s331.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketVersioning", {}).n("S3Client", "GetBucketVersioningCommand").f(void 0, void 0).ser(se_GetBucketVersioningCommand).de(de_GetBucketVersioningCommand).build() { + static { + __name(this, "GetBucketVersioningCommand"); + } +}; + +// src/commands/GetBucketWebsiteCommand.ts +var import_middleware_sdk_s332 = __nccwpck_require__(77445); + + + +var GetBucketWebsiteCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s332.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetBucketWebsite", {}).n("S3Client", "GetBucketWebsiteCommand").f(void 0, void 0).ser(se_GetBucketWebsiteCommand).de(de_GetBucketWebsiteCommand).build() { + static { + __name(this, "GetBucketWebsiteCommand"); + } +}; + +// src/commands/GetObjectAclCommand.ts +var import_middleware_sdk_s333 = __nccwpck_require__(77445); + + + +var GetObjectAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s333.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectAcl", {}).n("S3Client", "GetObjectAclCommand").f(void 0, void 0).ser(se_GetObjectAclCommand).de(de_GetObjectAclCommand).build() { + static { + __name(this, "GetObjectAclCommand"); + } +}; + +// src/commands/GetObjectAttributesCommand.ts +var import_middleware_sdk_s334 = __nccwpck_require__(77445); + + + + +var GetObjectAttributesCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s334.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectAttributes", {}).n("S3Client", "GetObjectAttributesCommand").f(GetObjectAttributesRequestFilterSensitiveLog, void 0).ser(se_GetObjectAttributesCommand).de(de_GetObjectAttributesCommand).build() { + static { + __name(this, "GetObjectAttributesCommand"); + } +}; + +// src/commands/GetObjectCommand.ts + +var import_middleware_sdk_s335 = __nccwpck_require__(77445); + + + + +var GetObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestChecksumRequired: false, + requestValidationModeMember: "ChecksumMode", + responseAlgorithms: ["CRC64NVME", "CRC32", "CRC32C", "SHA256", "SHA1"] + }), + (0, import_middleware_ssec.getSsecPlugin)(config), + (0, import_middleware_sdk_s335.getS3ExpiresMiddlewarePlugin)(config) + ]; +}).s("AmazonS3", "GetObject", {}).n("S3Client", "GetObjectCommand").f(GetObjectRequestFilterSensitiveLog, GetObjectOutputFilterSensitiveLog).ser(se_GetObjectCommand).de(de_GetObjectCommand).build() { + static { + __name(this, "GetObjectCommand"); + } +}; + +// src/commands/GetObjectLegalHoldCommand.ts +var import_middleware_sdk_s336 = __nccwpck_require__(77445); + + + +var GetObjectLegalHoldCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s336.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectLegalHold", {}).n("S3Client", "GetObjectLegalHoldCommand").f(void 0, void 0).ser(se_GetObjectLegalHoldCommand).de(de_GetObjectLegalHoldCommand).build() { + static { + __name(this, "GetObjectLegalHoldCommand"); + } +}; + +// src/commands/GetObjectLockConfigurationCommand.ts +var import_middleware_sdk_s337 = __nccwpck_require__(77445); + + + +var GetObjectLockConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s337.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectLockConfiguration", {}).n("S3Client", "GetObjectLockConfigurationCommand").f(void 0, void 0).ser(se_GetObjectLockConfigurationCommand).de(de_GetObjectLockConfigurationCommand).build() { + static { + __name(this, "GetObjectLockConfigurationCommand"); + } +}; + +// src/commands/GetObjectRetentionCommand.ts +var import_middleware_sdk_s338 = __nccwpck_require__(77445); + + + +var GetObjectRetentionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s338.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectRetention", {}).n("S3Client", "GetObjectRetentionCommand").f(void 0, void 0).ser(se_GetObjectRetentionCommand).de(de_GetObjectRetentionCommand).build() { + static { + __name(this, "GetObjectRetentionCommand"); + } +}; + +// src/commands/GetObjectTaggingCommand.ts +var import_middleware_sdk_s339 = __nccwpck_require__(77445); + + + +var GetObjectTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s339.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetObjectTagging", {}).n("S3Client", "GetObjectTaggingCommand").f(void 0, void 0).ser(se_GetObjectTaggingCommand).de(de_GetObjectTaggingCommand).build() { + static { + __name(this, "GetObjectTaggingCommand"); + } +}; + +// src/commands/GetObjectTorrentCommand.ts + + + +var GetObjectTorrentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "GetObjectTorrent", {}).n("S3Client", "GetObjectTorrentCommand").f(void 0, GetObjectTorrentOutputFilterSensitiveLog).ser(se_GetObjectTorrentCommand).de(de_GetObjectTorrentCommand).build() { + static { + __name(this, "GetObjectTorrentCommand"); + } +}; + +// src/commands/GetPublicAccessBlockCommand.ts +var import_middleware_sdk_s340 = __nccwpck_require__(77445); + + + +var GetPublicAccessBlockCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s340.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "GetPublicAccessBlock", {}).n("S3Client", "GetPublicAccessBlockCommand").f(void 0, void 0).ser(se_GetPublicAccessBlockCommand).de(de_GetPublicAccessBlockCommand).build() { + static { + __name(this, "GetPublicAccessBlockCommand"); + } +}; + +// src/commands/HeadBucketCommand.ts +var import_middleware_sdk_s341 = __nccwpck_require__(77445); + + + +var HeadBucketCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s341.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "HeadBucket", {}).n("S3Client", "HeadBucketCommand").f(void 0, void 0).ser(se_HeadBucketCommand).de(de_HeadBucketCommand).build() { + static { + __name(this, "HeadBucketCommand"); + } +}; + +// src/commands/HeadObjectCommand.ts +var import_middleware_sdk_s342 = __nccwpck_require__(77445); + + + + +var HeadObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s342.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config), + (0, import_middleware_sdk_s342.getS3ExpiresMiddlewarePlugin)(config) + ]; +}).s("AmazonS3", "HeadObject", {}).n("S3Client", "HeadObjectCommand").f(HeadObjectRequestFilterSensitiveLog, HeadObjectOutputFilterSensitiveLog).ser(se_HeadObjectCommand).de(de_HeadObjectCommand).build() { + static { + __name(this, "HeadObjectCommand"); + } +}; + +// src/commands/ListBucketAnalyticsConfigurationsCommand.ts +var import_middleware_sdk_s343 = __nccwpck_require__(77445); + + + +var ListBucketAnalyticsConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s343.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketAnalyticsConfigurations", {}).n("S3Client", "ListBucketAnalyticsConfigurationsCommand").f(void 0, void 0).ser(se_ListBucketAnalyticsConfigurationsCommand).de(de_ListBucketAnalyticsConfigurationsCommand).build() { + static { + __name(this, "ListBucketAnalyticsConfigurationsCommand"); + } +}; + +// src/commands/ListBucketIntelligentTieringConfigurationsCommand.ts +var import_middleware_sdk_s344 = __nccwpck_require__(77445); + + + +var ListBucketIntelligentTieringConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s344.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketIntelligentTieringConfigurations", {}).n("S3Client", "ListBucketIntelligentTieringConfigurationsCommand").f(void 0, void 0).ser(se_ListBucketIntelligentTieringConfigurationsCommand).de(de_ListBucketIntelligentTieringConfigurationsCommand).build() { + static { + __name(this, "ListBucketIntelligentTieringConfigurationsCommand"); + } +}; + +// src/commands/ListBucketInventoryConfigurationsCommand.ts +var import_middleware_sdk_s345 = __nccwpck_require__(77445); + + + +var ListBucketInventoryConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s345.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketInventoryConfigurations", {}).n("S3Client", "ListBucketInventoryConfigurationsCommand").f(void 0, ListBucketInventoryConfigurationsOutputFilterSensitiveLog).ser(se_ListBucketInventoryConfigurationsCommand).de(de_ListBucketInventoryConfigurationsCommand).build() { + static { + __name(this, "ListBucketInventoryConfigurationsCommand"); + } +}; + +// src/commands/ListBucketMetricsConfigurationsCommand.ts +var import_middleware_sdk_s346 = __nccwpck_require__(77445); + + + +var ListBucketMetricsConfigurationsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s346.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBucketMetricsConfigurations", {}).n("S3Client", "ListBucketMetricsConfigurationsCommand").f(void 0, void 0).ser(se_ListBucketMetricsConfigurationsCommand).de(de_ListBucketMetricsConfigurationsCommand).build() { + static { + __name(this, "ListBucketMetricsConfigurationsCommand"); + } +}; + +// src/commands/ListBucketsCommand.ts +var import_middleware_sdk_s347 = __nccwpck_require__(77445); + + + +var ListBucketsCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s347.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListBuckets", {}).n("S3Client", "ListBucketsCommand").f(void 0, void 0).ser(se_ListBucketsCommand).de(de_ListBucketsCommand).build() { + static { + __name(this, "ListBucketsCommand"); + } +}; + +// src/commands/ListDirectoryBucketsCommand.ts +var import_middleware_sdk_s348 = __nccwpck_require__(77445); + + + +var ListDirectoryBucketsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s348.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListDirectoryBuckets", {}).n("S3Client", "ListDirectoryBucketsCommand").f(void 0, void 0).ser(se_ListDirectoryBucketsCommand).de(de_ListDirectoryBucketsCommand).build() { + static { + __name(this, "ListDirectoryBucketsCommand"); + } +}; + +// src/commands/ListMultipartUploadsCommand.ts +var import_middleware_sdk_s349 = __nccwpck_require__(77445); + + + +var ListMultipartUploadsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s349.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListMultipartUploads", {}).n("S3Client", "ListMultipartUploadsCommand").f(void 0, void 0).ser(se_ListMultipartUploadsCommand).de(de_ListMultipartUploadsCommand).build() { + static { + __name(this, "ListMultipartUploadsCommand"); + } +}; + +// src/commands/ListObjectsCommand.ts +var import_middleware_sdk_s350 = __nccwpck_require__(77445); + + + +var ListObjectsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s350.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListObjects", {}).n("S3Client", "ListObjectsCommand").f(void 0, void 0).ser(se_ListObjectsCommand).de(de_ListObjectsCommand).build() { + static { + __name(this, "ListObjectsCommand"); + } +}; + +// src/commands/ListObjectsV2Command.ts +var import_middleware_sdk_s351 = __nccwpck_require__(77445); + + + +var ListObjectsV2Command = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s351.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListObjectsV2", {}).n("S3Client", "ListObjectsV2Command").f(void 0, void 0).ser(se_ListObjectsV2Command).de(de_ListObjectsV2Command).build() { + static { + __name(this, "ListObjectsV2Command"); + } +}; + +// src/commands/ListObjectVersionsCommand.ts +var import_middleware_sdk_s352 = __nccwpck_require__(77445); + + + +var ListObjectVersionsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Prefix: { type: "contextParams", name: "Prefix" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s352.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "ListObjectVersions", {}).n("S3Client", "ListObjectVersionsCommand").f(void 0, void 0).ser(se_ListObjectVersionsCommand).de(de_ListObjectVersionsCommand).build() { + static { + __name(this, "ListObjectVersionsCommand"); + } +}; + +// src/commands/ListPartsCommand.ts +var import_middleware_sdk_s353 = __nccwpck_require__(77445); + + + + +var ListPartsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s353.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "ListParts", {}).n("S3Client", "ListPartsCommand").f(ListPartsRequestFilterSensitiveLog, void 0).ser(se_ListPartsCommand).de(de_ListPartsCommand).build() { + static { + __name(this, "ListPartsCommand"); + } +}; + +// src/commands/PutBucketAccelerateConfigurationCommand.ts + + + + +var PutBucketAccelerateConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }) + ]; +}).s("AmazonS3", "PutBucketAccelerateConfiguration", {}).n("S3Client", "PutBucketAccelerateConfigurationCommand").f(void 0, void 0).ser(se_PutBucketAccelerateConfigurationCommand).de(de_PutBucketAccelerateConfigurationCommand).build() { + static { + __name(this, "PutBucketAccelerateConfigurationCommand"); + } +}; + +// src/commands/PutBucketAclCommand.ts + + + + +var PutBucketAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketAcl", {}).n("S3Client", "PutBucketAclCommand").f(void 0, void 0).ser(se_PutBucketAclCommand).de(de_PutBucketAclCommand).build() { + static { + __name(this, "PutBucketAclCommand"); + } +}; + +// src/commands/PutBucketAnalyticsConfigurationCommand.ts + + + +var PutBucketAnalyticsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketAnalyticsConfiguration", {}).n("S3Client", "PutBucketAnalyticsConfigurationCommand").f(void 0, void 0).ser(se_PutBucketAnalyticsConfigurationCommand).de(de_PutBucketAnalyticsConfigurationCommand).build() { + static { + __name(this, "PutBucketAnalyticsConfigurationCommand"); + } +}; + +// src/commands/PutBucketCorsCommand.ts + + + + +var PutBucketCorsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketCors", {}).n("S3Client", "PutBucketCorsCommand").f(void 0, void 0).ser(se_PutBucketCorsCommand).de(de_PutBucketCorsCommand).build() { + static { + __name(this, "PutBucketCorsCommand"); + } +}; + +// src/commands/PutBucketEncryptionCommand.ts + + + + +var PutBucketEncryptionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketEncryption", {}).n("S3Client", "PutBucketEncryptionCommand").f(PutBucketEncryptionRequestFilterSensitiveLog, void 0).ser(se_PutBucketEncryptionCommand).de(de_PutBucketEncryptionCommand).build() { + static { + __name(this, "PutBucketEncryptionCommand"); + } +}; + +// src/commands/PutBucketIntelligentTieringConfigurationCommand.ts + + + +var PutBucketIntelligentTieringConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketIntelligentTieringConfiguration", {}).n("S3Client", "PutBucketIntelligentTieringConfigurationCommand").f(void 0, void 0).ser(se_PutBucketIntelligentTieringConfigurationCommand).de(de_PutBucketIntelligentTieringConfigurationCommand).build() { + static { + __name(this, "PutBucketIntelligentTieringConfigurationCommand"); + } +}; + +// src/commands/PutBucketInventoryConfigurationCommand.ts + + + +var PutBucketInventoryConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketInventoryConfiguration", {}).n("S3Client", "PutBucketInventoryConfigurationCommand").f(PutBucketInventoryConfigurationRequestFilterSensitiveLog, void 0).ser(se_PutBucketInventoryConfigurationCommand).de(de_PutBucketInventoryConfigurationCommand).build() { + static { + __name(this, "PutBucketInventoryConfigurationCommand"); + } +}; + +// src/commands/PutBucketLifecycleConfigurationCommand.ts + +var import_middleware_sdk_s354 = __nccwpck_require__(77445); + + + +var PutBucketLifecycleConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s354.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutBucketLifecycleConfiguration", {}).n("S3Client", "PutBucketLifecycleConfigurationCommand").f(void 0, void 0).ser(se_PutBucketLifecycleConfigurationCommand).de(de_PutBucketLifecycleConfigurationCommand).build() { + static { + __name(this, "PutBucketLifecycleConfigurationCommand"); + } +}; + +// src/commands/PutBucketLoggingCommand.ts + + + + +var PutBucketLoggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketLogging", {}).n("S3Client", "PutBucketLoggingCommand").f(void 0, void 0).ser(se_PutBucketLoggingCommand).de(de_PutBucketLoggingCommand).build() { + static { + __name(this, "PutBucketLoggingCommand"); + } +}; + +// src/commands/PutBucketMetricsConfigurationCommand.ts + + + +var PutBucketMetricsConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketMetricsConfiguration", {}).n("S3Client", "PutBucketMetricsConfigurationCommand").f(void 0, void 0).ser(se_PutBucketMetricsConfigurationCommand).de(de_PutBucketMetricsConfigurationCommand).build() { + static { + __name(this, "PutBucketMetricsConfigurationCommand"); + } +}; + +// src/commands/PutBucketNotificationConfigurationCommand.ts + + + +var PutBucketNotificationConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "PutBucketNotificationConfiguration", {}).n("S3Client", "PutBucketNotificationConfigurationCommand").f(void 0, void 0).ser(se_PutBucketNotificationConfigurationCommand).de(de_PutBucketNotificationConfigurationCommand).build() { + static { + __name(this, "PutBucketNotificationConfigurationCommand"); + } +}; + +// src/commands/PutBucketOwnershipControlsCommand.ts + + + + +var PutBucketOwnershipControlsCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketOwnershipControls", {}).n("S3Client", "PutBucketOwnershipControlsCommand").f(void 0, void 0).ser(se_PutBucketOwnershipControlsCommand).de(de_PutBucketOwnershipControlsCommand).build() { + static { + __name(this, "PutBucketOwnershipControlsCommand"); + } +}; + +// src/commands/PutBucketPolicyCommand.ts + + + + +var PutBucketPolicyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketPolicy", {}).n("S3Client", "PutBucketPolicyCommand").f(void 0, void 0).ser(se_PutBucketPolicyCommand).de(de_PutBucketPolicyCommand).build() { + static { + __name(this, "PutBucketPolicyCommand"); + } +}; + +// src/commands/PutBucketReplicationCommand.ts + + + + +var PutBucketReplicationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketReplication", {}).n("S3Client", "PutBucketReplicationCommand").f(void 0, void 0).ser(se_PutBucketReplicationCommand).de(de_PutBucketReplicationCommand).build() { + static { + __name(this, "PutBucketReplicationCommand"); + } +}; + +// src/commands/PutBucketRequestPaymentCommand.ts + + + + +var PutBucketRequestPaymentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketRequestPayment", {}).n("S3Client", "PutBucketRequestPaymentCommand").f(void 0, void 0).ser(se_PutBucketRequestPaymentCommand).de(de_PutBucketRequestPaymentCommand).build() { + static { + __name(this, "PutBucketRequestPaymentCommand"); + } +}; + +// src/commands/PutBucketTaggingCommand.ts + + + + +var PutBucketTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketTagging", {}).n("S3Client", "PutBucketTaggingCommand").f(void 0, void 0).ser(se_PutBucketTaggingCommand).de(de_PutBucketTaggingCommand).build() { + static { + __name(this, "PutBucketTaggingCommand"); + } +}; + +// src/commands/PutBucketVersioningCommand.ts + + + + +var PutBucketVersioningCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketVersioning", {}).n("S3Client", "PutBucketVersioningCommand").f(void 0, void 0).ser(se_PutBucketVersioningCommand).de(de_PutBucketVersioningCommand).build() { + static { + __name(this, "PutBucketVersioningCommand"); + } +}; + +// src/commands/PutBucketWebsiteCommand.ts + + + + +var PutBucketWebsiteCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutBucketWebsite", {}).n("S3Client", "PutBucketWebsiteCommand").f(void 0, void 0).ser(se_PutBucketWebsiteCommand).de(de_PutBucketWebsiteCommand).build() { + static { + __name(this, "PutBucketWebsiteCommand"); + } +}; + +// src/commands/PutObjectAclCommand.ts + +var import_middleware_sdk_s355 = __nccwpck_require__(77445); + + + +var PutObjectAclCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s355.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectAcl", {}).n("S3Client", "PutObjectAclCommand").f(void 0, void 0).ser(se_PutObjectAclCommand).de(de_PutObjectAclCommand).build() { + static { + __name(this, "PutObjectAclCommand"); + } +}; + +// src/commands/PutObjectCommand.ts + +var import_middleware_sdk_s356 = __nccwpck_require__(77445); + + + + +var PutObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }), + (0, import_middleware_sdk_s356.getCheckContentLengthHeaderPlugin)(config), + (0, import_middleware_sdk_s356.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "PutObject", {}).n("S3Client", "PutObjectCommand").f(PutObjectRequestFilterSensitiveLog, PutObjectOutputFilterSensitiveLog).ser(se_PutObjectCommand).de(de_PutObjectCommand).build() { + static { + __name(this, "PutObjectCommand"); + } +}; + +// src/commands/PutObjectLegalHoldCommand.ts + +var import_middleware_sdk_s357 = __nccwpck_require__(77445); + + + +var PutObjectLegalHoldCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s357.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectLegalHold", {}).n("S3Client", "PutObjectLegalHoldCommand").f(void 0, void 0).ser(se_PutObjectLegalHoldCommand).de(de_PutObjectLegalHoldCommand).build() { + static { + __name(this, "PutObjectLegalHoldCommand"); + } +}; + +// src/commands/PutObjectLockConfigurationCommand.ts + +var import_middleware_sdk_s358 = __nccwpck_require__(77445); + + + +var PutObjectLockConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s358.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectLockConfiguration", {}).n("S3Client", "PutObjectLockConfigurationCommand").f(void 0, void 0).ser(se_PutObjectLockConfigurationCommand).de(de_PutObjectLockConfigurationCommand).build() { + static { + __name(this, "PutObjectLockConfigurationCommand"); + } +}; + +// src/commands/PutObjectRetentionCommand.ts + +var import_middleware_sdk_s359 = __nccwpck_require__(77445); + + + +var PutObjectRetentionCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s359.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectRetention", {}).n("S3Client", "PutObjectRetentionCommand").f(void 0, void 0).ser(se_PutObjectRetentionCommand).de(de_PutObjectRetentionCommand).build() { + static { + __name(this, "PutObjectRetentionCommand"); + } +}; + +// src/commands/PutObjectTaggingCommand.ts + +var import_middleware_sdk_s360 = __nccwpck_require__(77445); + + + +var PutObjectTaggingCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }), + (0, import_middleware_sdk_s360.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "PutObjectTagging", {}).n("S3Client", "PutObjectTaggingCommand").f(void 0, void 0).ser(se_PutObjectTaggingCommand).de(de_PutObjectTaggingCommand).build() { + static { + __name(this, "PutObjectTaggingCommand"); + } +}; + +// src/commands/PutPublicAccessBlockCommand.ts + + + + +var PutPublicAccessBlockCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "PutPublicAccessBlock", {}).n("S3Client", "PutPublicAccessBlockCommand").f(void 0, void 0).ser(se_PutPublicAccessBlockCommand).de(de_PutPublicAccessBlockCommand).build() { + static { + __name(this, "PutPublicAccessBlockCommand"); + } +}; + +// src/commands/RenameObjectCommand.ts +var import_middleware_sdk_s361 = __nccwpck_require__(77445); + + + +var RenameObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s361.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "RenameObject", {}).n("S3Client", "RenameObjectCommand").f(void 0, void 0).ser(se_RenameObjectCommand).de(de_RenameObjectCommand).build() { + static { + __name(this, "RenameObjectCommand"); + } +}; + +// src/commands/RestoreObjectCommand.ts + +var import_middleware_sdk_s362 = __nccwpck_require__(77445); + + + +var RestoreObjectCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }), + (0, import_middleware_sdk_s362.getThrow200ExceptionsPlugin)(config) + ]; +}).s("AmazonS3", "RestoreObject", {}).n("S3Client", "RestoreObjectCommand").f(RestoreObjectRequestFilterSensitiveLog, void 0).ser(se_RestoreObjectCommand).de(de_RestoreObjectCommand).build() { + static { + __name(this, "RestoreObjectCommand"); + } +}; + +// src/commands/SelectObjectContentCommand.ts +var import_middleware_sdk_s363 = __nccwpck_require__(77445); + + + + +var SelectObjectContentCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s363.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "SelectObjectContent", { + /** + * @internal + */ + eventStream: { + output: true + } +}).n("S3Client", "SelectObjectContentCommand").f(SelectObjectContentRequestFilterSensitiveLog, SelectObjectContentOutputFilterSensitiveLog).ser(se_SelectObjectContentCommand).de(de_SelectObjectContentCommand).build() { + static { + __name(this, "SelectObjectContentCommand"); + } +}; + +// src/commands/UpdateBucketMetadataInventoryTableConfigurationCommand.ts + + + + +var UpdateBucketMetadataInventoryTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "UpdateBucketMetadataInventoryTableConfiguration", {}).n("S3Client", "UpdateBucketMetadataInventoryTableConfigurationCommand").f(void 0, void 0).ser(se_UpdateBucketMetadataInventoryTableConfigurationCommand).de(de_UpdateBucketMetadataInventoryTableConfigurationCommand).build() { + static { + __name(this, "UpdateBucketMetadataInventoryTableConfigurationCommand"); + } +}; + +// src/commands/UpdateBucketMetadataJournalTableConfigurationCommand.ts + + + + +var UpdateBucketMetadataJournalTableConfigurationCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseS3ExpressControlEndpoint: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: true + }) + ]; +}).s("AmazonS3", "UpdateBucketMetadataJournalTableConfiguration", {}).n("S3Client", "UpdateBucketMetadataJournalTableConfigurationCommand").f(void 0, void 0).ser(se_UpdateBucketMetadataJournalTableConfigurationCommand).de(de_UpdateBucketMetadataJournalTableConfigurationCommand).build() { + static { + __name(this, "UpdateBucketMetadataJournalTableConfigurationCommand"); + } +}; + +// src/commands/UploadPartCommand.ts + +var import_middleware_sdk_s364 = __nccwpck_require__(77445); + + + + +var UploadPartCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + Bucket: { type: "contextParams", name: "Bucket" }, + Key: { type: "contextParams", name: "Key" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_flexible_checksums.getFlexibleChecksumsPlugin)(config, { + requestAlgorithmMember: { httpHeader: "x-amz-sdk-checksum-algorithm", name: "ChecksumAlgorithm" }, + requestChecksumRequired: false + }), + (0, import_middleware_sdk_s364.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "UploadPart", {}).n("S3Client", "UploadPartCommand").f(UploadPartRequestFilterSensitiveLog, UploadPartOutputFilterSensitiveLog).ser(se_UploadPartCommand).de(de_UploadPartCommand).build() { + static { + __name(this, "UploadPartCommand"); + } +}; + +// src/commands/UploadPartCopyCommand.ts +var import_middleware_sdk_s365 = __nccwpck_require__(77445); + + + + +var UploadPartCopyCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + DisableS3ExpressSessionAuth: { type: "staticContextParams", value: true }, + Bucket: { type: "contextParams", name: "Bucket" } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()), + (0, import_middleware_sdk_s365.getThrow200ExceptionsPlugin)(config), + (0, import_middleware_ssec.getSsecPlugin)(config) + ]; +}).s("AmazonS3", "UploadPartCopy", {}).n("S3Client", "UploadPartCopyCommand").f(UploadPartCopyRequestFilterSensitiveLog, UploadPartCopyOutputFilterSensitiveLog).ser(se_UploadPartCopyCommand).de(de_UploadPartCopyCommand).build() { + static { + __name(this, "UploadPartCopyCommand"); + } +}; + +// src/commands/WriteGetObjectResponseCommand.ts + + + +var WriteGetObjectResponseCommand = class extends import_smithy_client.Command.classBuilder().ep({ + ...commonParams, + UseObjectLambdaEndpoint: { type: "staticContextParams", value: true } +}).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AmazonS3", "WriteGetObjectResponse", {}).n("S3Client", "WriteGetObjectResponseCommand").f(WriteGetObjectResponseRequestFilterSensitiveLog, void 0).ser(se_WriteGetObjectResponseCommand).de(de_WriteGetObjectResponseCommand).build() { + static { + __name(this, "WriteGetObjectResponseCommand"); + } +}; + +// src/S3.ts +var commands = { + AbortMultipartUploadCommand, + CompleteMultipartUploadCommand, + CopyObjectCommand, + CreateBucketCommand, + CreateBucketMetadataConfigurationCommand, + CreateBucketMetadataTableConfigurationCommand, + CreateMultipartUploadCommand, + CreateSessionCommand, + DeleteBucketCommand, + DeleteBucketAnalyticsConfigurationCommand, + DeleteBucketCorsCommand, + DeleteBucketEncryptionCommand, + DeleteBucketIntelligentTieringConfigurationCommand, + DeleteBucketInventoryConfigurationCommand, + DeleteBucketLifecycleCommand, + DeleteBucketMetadataConfigurationCommand, + DeleteBucketMetadataTableConfigurationCommand, + DeleteBucketMetricsConfigurationCommand, + DeleteBucketOwnershipControlsCommand, + DeleteBucketPolicyCommand, + DeleteBucketReplicationCommand, + DeleteBucketTaggingCommand, + DeleteBucketWebsiteCommand, + DeleteObjectCommand, + DeleteObjectsCommand, + DeleteObjectTaggingCommand, + DeletePublicAccessBlockCommand, + GetBucketAccelerateConfigurationCommand, + GetBucketAclCommand, + GetBucketAnalyticsConfigurationCommand, + GetBucketCorsCommand, + GetBucketEncryptionCommand, + GetBucketIntelligentTieringConfigurationCommand, + GetBucketInventoryConfigurationCommand, + GetBucketLifecycleConfigurationCommand, + GetBucketLocationCommand, + GetBucketLoggingCommand, + GetBucketMetadataConfigurationCommand, + GetBucketMetadataTableConfigurationCommand, + GetBucketMetricsConfigurationCommand, + GetBucketNotificationConfigurationCommand, + GetBucketOwnershipControlsCommand, + GetBucketPolicyCommand, + GetBucketPolicyStatusCommand, + GetBucketReplicationCommand, + GetBucketRequestPaymentCommand, + GetBucketTaggingCommand, + GetBucketVersioningCommand, + GetBucketWebsiteCommand, + GetObjectCommand, + GetObjectAclCommand, + GetObjectAttributesCommand, + GetObjectLegalHoldCommand, + GetObjectLockConfigurationCommand, + GetObjectRetentionCommand, + GetObjectTaggingCommand, + GetObjectTorrentCommand, + GetPublicAccessBlockCommand, + HeadBucketCommand, + HeadObjectCommand, + ListBucketAnalyticsConfigurationsCommand, + ListBucketIntelligentTieringConfigurationsCommand, + ListBucketInventoryConfigurationsCommand, + ListBucketMetricsConfigurationsCommand, + ListBucketsCommand, + ListDirectoryBucketsCommand, + ListMultipartUploadsCommand, + ListObjectsCommand, + ListObjectsV2Command, + ListObjectVersionsCommand, + ListPartsCommand, + PutBucketAccelerateConfigurationCommand, + PutBucketAclCommand, + PutBucketAnalyticsConfigurationCommand, + PutBucketCorsCommand, + PutBucketEncryptionCommand, + PutBucketIntelligentTieringConfigurationCommand, + PutBucketInventoryConfigurationCommand, + PutBucketLifecycleConfigurationCommand, + PutBucketLoggingCommand, + PutBucketMetricsConfigurationCommand, + PutBucketNotificationConfigurationCommand, + PutBucketOwnershipControlsCommand, + PutBucketPolicyCommand, + PutBucketReplicationCommand, + PutBucketRequestPaymentCommand, + PutBucketTaggingCommand, + PutBucketVersioningCommand, + PutBucketWebsiteCommand, + PutObjectCommand, + PutObjectAclCommand, + PutObjectLegalHoldCommand, + PutObjectLockConfigurationCommand, + PutObjectRetentionCommand, + PutObjectTaggingCommand, + PutPublicAccessBlockCommand, + RenameObjectCommand, + RestoreObjectCommand, + SelectObjectContentCommand, + UpdateBucketMetadataInventoryTableConfigurationCommand, + UpdateBucketMetadataJournalTableConfigurationCommand, + UploadPartCommand, + UploadPartCopyCommand, + WriteGetObjectResponseCommand +}; +var S3 = class extends S3Client { + static { + __name(this, "S3"); + } +}; +(0, import_smithy_client.createAggregatedClient)(commands, S3); + +// src/pagination/ListBucketsPaginator.ts +var import_core4 = __nccwpck_require__(90402); +var paginateListBuckets = (0, import_core4.createPaginator)(S3Client, ListBucketsCommand, "ContinuationToken", "ContinuationToken", "MaxBuckets"); + +// src/pagination/ListDirectoryBucketsPaginator.ts +var import_core5 = __nccwpck_require__(90402); +var paginateListDirectoryBuckets = (0, import_core5.createPaginator)(S3Client, ListDirectoryBucketsCommand, "ContinuationToken", "ContinuationToken", "MaxDirectoryBuckets"); + +// src/pagination/ListObjectsV2Paginator.ts +var import_core6 = __nccwpck_require__(90402); +var paginateListObjectsV2 = (0, import_core6.createPaginator)(S3Client, ListObjectsV2Command, "ContinuationToken", "NextContinuationToken", "MaxKeys"); + +// src/pagination/ListPartsPaginator.ts +var import_core7 = __nccwpck_require__(90402); +var paginateListParts = (0, import_core7.createPaginator)(S3Client, ListPartsCommand, "PartNumberMarker", "NextPartNumberMarker", "MaxParts"); + +// src/waiters/waitForBucketExists.ts +var import_util_waiter = __nccwpck_require__(95290); +var checkState = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadBucketCommand(input)); + reason = result; + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.RETRY, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForBucketExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState); +}, "waitForBucketExists"); +var waitUntilBucketExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilBucketExists"); + +// src/waiters/waitForBucketNotExists.ts + +var checkState2 = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadBucketCommand(input)); + reason = result; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForBucketNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState2); +}, "waitForBucketNotExists"); +var waitUntilBucketNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState2); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilBucketNotExists"); + +// src/waiters/waitForObjectExists.ts + +var checkState3 = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadObjectCommand(input)); + reason = result; + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.RETRY, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForObjectExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState3); +}, "waitForObjectExists"); +var waitUntilObjectExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState3); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilObjectExists"); + +// src/waiters/waitForObjectNotExists.ts + +var checkState4 = /* @__PURE__ */ __name(async (client, input) => { + let reason; + try { + const result = await client.send(new HeadObjectCommand(input)); + reason = result; + } catch (exception) { + reason = exception; + if (exception.name && exception.name == "NotFound") { + return { state: import_util_waiter.WaiterState.SUCCESS, reason }; + } + } + return { state: import_util_waiter.WaiterState.RETRY, reason }; +}, "checkState"); +var waitForObjectNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + return (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState4); +}, "waitForObjectNotExists"); +var waitUntilObjectNotExists = /* @__PURE__ */ __name(async (params, input) => { + const serviceDefaults = { minDelay: 5, maxDelay: 120 }; + const result = await (0, import_util_waiter.createWaiter)({ ...serviceDefaults, ...params }, input, checkState4); + return (0, import_util_waiter.checkExceptions)(result); +}, "waitUntilObjectNotExists"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 35745: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(27413)); +const core_1 = __nccwpck_require__(8704); +const credential_provider_node_1 = __nccwpck_require__(5861); +const middleware_bucket_endpoint_1 = __nccwpck_require__(26518); +const middleware_flexible_checksums_1 = __nccwpck_require__(29836); +const middleware_sdk_s3_1 = __nccwpck_require__(77445); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const eventstream_serde_node_1 = __nccwpck_require__(69770); +const hash_node_1 = __nccwpck_require__(5092); +const hash_stream_node_1 = __nccwpck_require__(45317); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(74070); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + credentialDefaultProvider: config?.credentialDefaultProvider ?? credential_provider_node_1.defaultProvider, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + disableS3ExpressSessionAuth: config?.disableS3ExpressSessionAuth ?? (0, node_config_provider_1.loadConfig)(middleware_sdk_s3_1.NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, loaderConfig), + eventStreamSerdeProvider: config?.eventStreamSerdeProvider ?? eventstream_serde_node_1.eventStreamSerdeProvider, + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + md5: config?.md5 ?? hash_node_1.Hash.bind(null, "md5"), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestChecksumCalculation: config?.requestChecksumCalculation ?? + (0, node_config_provider_1.loadConfig)(middleware_flexible_checksums_1.NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS, loaderConfig), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + responseChecksumValidation: config?.responseChecksumValidation ?? + (0, node_config_provider_1.loadConfig)(middleware_flexible_checksums_1.NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS, loaderConfig), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha1: config?.sha1 ?? hash_node_1.Hash.bind(null, "sha1"), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + sigv4aSigningRegionSet: config?.sigv4aSigningRegionSet ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_SIGV4A_CONFIG_OPTIONS, loaderConfig), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + streamHasher: config?.streamHasher ?? hash_stream_node_1.readableStreamHasher, + useArnRegion: config?.useArnRegion ?? (0, node_config_provider_1.loadConfig)(middleware_bucket_endpoint_1.NODE_USE_ARN_REGION_CONFIG_OPTIONS, loaderConfig), + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 74070: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const signature_v4_multi_region_1 = __nccwpck_require__(5785); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_stream_1 = __nccwpck_require__(4252); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(7168); +const endpointResolver_1 = __nccwpck_require__(57526); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2006-03-01", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + getAwsChunkedEncodingStream: config?.getAwsChunkedEncodingStream ?? util_stream_1.getAwsChunkedEncodingStream, + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultS3HttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "aws.auth#sigv4a", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4a"), + signer: new core_1.AwsSdkSigV4ASigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + sdkStreamMixin: config?.sdkStreamMixin ?? util_stream_1.sdkStreamMixin, + serviceId: config?.serviceId ?? "S3", + signerConstructor: config?.signerConstructor ?? signature_v4_multi_region_1.SignatureV4MultiRegion, + signingEscapePath: config?.signingEscapePath ?? false, + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + useArnRegion: config?.useArnRegion ?? undefined, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 62041: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.defaultSSOHttpAuthSchemeProvider = exports.defaultSSOHttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const util_middleware_1 = __nccwpck_require__(76324); +const defaultSSOHttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultSSOHttpAuthSchemeParametersProvider = defaultSSOHttpAuthSchemeParametersProvider; +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "awsssoportal", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createSmithyApiNoAuthHttpAuthOption(authParameters) { + return { + schemeId: "smithy.api#noAuth", + }; +} +const defaultSSOHttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + case "GetRoleCredentials": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + case "ListAccountRoles": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + case "ListAccounts": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + case "Logout": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultSSOHttpAuthSchemeProvider = defaultSSOHttpAuthSchemeProvider; +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config); + return Object.assign(config_0, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 13903: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(41308); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: ["Endpoint", "Region", "UseDualStack", "UseFIPS"], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 41308: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const u = "required", v = "fn", w = "argv", x = "ref"; +const a = true, b = "isSet", c = "booleanEquals", d = "error", e = "endpoint", f = "tree", g = "PartitionResult", h = "getAttr", i = { [u]: false, "type": "String" }, j = { [u]: true, "default": false, "type": "Boolean" }, k = { [x]: "Endpoint" }, l = { [v]: c, [w]: [{ [x]: "UseFIPS" }, true] }, m = { [v]: c, [w]: [{ [x]: "UseDualStack" }, true] }, n = {}, o = { [v]: h, [w]: [{ [x]: g }, "supportsFIPS"] }, p = { [x]: g }, q = { [v]: c, [w]: [true, { [v]: h, [w]: [p, "supportsDualStack"] }] }, r = [l], s = [m], t = [{ [x]: "Region" }]; +const _data = { version: "1.0", parameters: { Region: i, UseDualStack: j, UseFIPS: j, Endpoint: i }, rules: [{ conditions: [{ [v]: b, [w]: [k] }], rules: [{ conditions: r, error: "Invalid Configuration: FIPS and custom endpoint are not supported", type: d }, { conditions: s, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", type: d }, { endpoint: { url: k, properties: n, headers: n }, type: e }], type: f }, { conditions: [{ [v]: b, [w]: t }], rules: [{ conditions: [{ [v]: "aws.partition", [w]: t, assign: g }], rules: [{ conditions: [l, m], rules: [{ conditions: [{ [v]: c, [w]: [a, o] }, q], rules: [{ endpoint: { url: "https://portal.sso-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", type: d }], type: f }, { conditions: r, rules: [{ conditions: [{ [v]: c, [w]: [o, a] }], rules: [{ conditions: [{ [v]: "stringEquals", [w]: [{ [v]: h, [w]: [p, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://portal.sso.{Region}.amazonaws.com", properties: n, headers: n }, type: e }, { endpoint: { url: "https://portal.sso-fips.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS is enabled but this partition does not support FIPS", type: d }], type: f }, { conditions: s, rules: [{ conditions: [q], rules: [{ endpoint: { url: "https://portal.sso.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "DualStack is enabled but this partition does not support DualStack", type: d }], type: f }, { endpoint: { url: "https://portal.sso.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }], type: f }, { error: "Invalid Configuration: Missing Region", type: d }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 62054: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + GetRoleCredentialsCommand: () => GetRoleCredentialsCommand, + GetRoleCredentialsRequestFilterSensitiveLog: () => GetRoleCredentialsRequestFilterSensitiveLog, + GetRoleCredentialsResponseFilterSensitiveLog: () => GetRoleCredentialsResponseFilterSensitiveLog, + InvalidRequestException: () => InvalidRequestException, + ListAccountRolesCommand: () => ListAccountRolesCommand, + ListAccountRolesRequestFilterSensitiveLog: () => ListAccountRolesRequestFilterSensitiveLog, + ListAccountsCommand: () => ListAccountsCommand, + ListAccountsRequestFilterSensitiveLog: () => ListAccountsRequestFilterSensitiveLog, + LogoutCommand: () => LogoutCommand, + LogoutRequestFilterSensitiveLog: () => LogoutRequestFilterSensitiveLog, + ResourceNotFoundException: () => ResourceNotFoundException, + RoleCredentialsFilterSensitiveLog: () => RoleCredentialsFilterSensitiveLog, + SSO: () => SSO, + SSOClient: () => SSOClient, + SSOServiceException: () => SSOServiceException, + TooManyRequestsException: () => TooManyRequestsException, + UnauthorizedException: () => UnauthorizedException, + __Client: () => import_smithy_client.Client, + paginateListAccountRoles: () => paginateListAccountRoles, + paginateListAccounts: () => paginateListAccounts +}); +module.exports = __toCommonJS(index_exports); + +// src/SSOClient.ts +var import_middleware_host_header = __nccwpck_require__(52590); +var import_middleware_logger = __nccwpck_require__(85242); +var import_middleware_recursion_detection = __nccwpck_require__(81568); +var import_middleware_user_agent = __nccwpck_require__(32959); +var import_config_resolver = __nccwpck_require__(39316); +var import_core = __nccwpck_require__(90402); +var import_middleware_content_length = __nccwpck_require__(47212); +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_retry = __nccwpck_require__(19618); + +var import_httpAuthSchemeProvider = __nccwpck_require__(62041); + +// src/endpoint/EndpointParameters.ts +var resolveClientEndpointParameters = /* @__PURE__ */ __name((options) => { + return Object.assign(options, { + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + useFipsEndpoint: options.useFipsEndpoint ?? false, + defaultSigningName: "awsssoportal" + }); +}, "resolveClientEndpointParameters"); +var commonParams = { + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" } +}; + +// src/SSOClient.ts +var import_runtimeConfig = __nccwpck_require__(82696); + +// src/runtimeExtensions.ts +var import_region_config_resolver = __nccwpck_require__(36463); +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client = __nccwpck_require__(61411); + +// src/auth/httpAuthExtensionConfiguration.ts +var getHttpAuthExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + } + }; +}, "getHttpAuthExtensionConfiguration"); +var resolveHttpAuthRuntimeConfig = /* @__PURE__ */ __name((config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials() + }; +}, "resolveHttpAuthRuntimeConfig"); + +// src/runtimeExtensions.ts +var resolveRuntimeExtensions = /* @__PURE__ */ __name((runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign( + (0, import_region_config_resolver.getAwsRegionExtensionConfiguration)(runtimeConfig), + (0, import_smithy_client.getDefaultExtensionConfiguration)(runtimeConfig), + (0, import_protocol_http.getHttpHandlerExtensionConfiguration)(runtimeConfig), + getHttpAuthExtensionConfiguration(runtimeConfig) + ); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign( + runtimeConfig, + (0, import_region_config_resolver.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), + (0, import_smithy_client.resolveDefaultRuntimeConfig)(extensionConfiguration), + (0, import_protocol_http.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), + resolveHttpAuthRuntimeConfig(extensionConfiguration) + ); +}, "resolveRuntimeExtensions"); + +// src/SSOClient.ts +var SSOClient = class extends import_smithy_client.Client { + static { + __name(this, "SSOClient"); + } + /** + * The resolved configuration of SSOClient class. This is resolved and normalized from the {@link SSOClientConfig | constructor configuration interface}. + */ + config; + constructor(...[configuration]) { + const _config_0 = (0, import_runtimeConfig.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = resolveClientEndpointParameters(_config_0); + const _config_2 = (0, import_middleware_user_agent.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, import_middleware_retry.resolveRetryConfig)(_config_2); + const _config_4 = (0, import_config_resolver.resolveRegionConfig)(_config_3); + const _config_5 = (0, import_middleware_host_header.resolveHostHeaderConfig)(_config_4); + const _config_6 = (0, import_middleware_endpoint.resolveEndpointConfig)(_config_5); + const _config_7 = (0, import_httpAuthSchemeProvider.resolveHttpAuthSchemeConfig)(_config_6); + const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []); + this.config = _config_8; + this.middlewareStack.use((0, import_middleware_user_agent.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_retry.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_content_length.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_host_header.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_logger.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_recursion_detection.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use( + (0, import_core.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: import_httpAuthSchemeProvider.defaultSSOHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: /* @__PURE__ */ __name(async (config) => new import_core.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials + }), "identityProviderConfigProvider") + }) + ); + this.middlewareStack.use((0, import_core.getHttpSigningPlugin)(this.config)); + } + /** + * Destroy underlying resources, like sockets. It's usually not necessary to do this. + * However in Node.js, it's best to explicitly shut down the client's agent when it is no longer needed. + * Otherwise, sockets might stay open for quite a long time before the server terminates them. + */ + destroy() { + super.destroy(); + } +}; + +// src/SSO.ts + + +// src/commands/GetRoleCredentialsCommand.ts + +var import_middleware_serde = __nccwpck_require__(83255); + + +// src/models/models_0.ts + + +// src/models/SSOServiceException.ts + +var SSOServiceException = class _SSOServiceException extends import_smithy_client.ServiceException { + static { + __name(this, "SSOServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _SSOServiceException.prototype); + } +}; + +// src/models/models_0.ts +var InvalidRequestException = class _InvalidRequestException extends SSOServiceException { + static { + __name(this, "InvalidRequestException"); + } + name = "InvalidRequestException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidRequestException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidRequestException.prototype); + } +}; +var ResourceNotFoundException = class _ResourceNotFoundException extends SSOServiceException { + static { + __name(this, "ResourceNotFoundException"); + } + name = "ResourceNotFoundException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ResourceNotFoundException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ResourceNotFoundException.prototype); + } +}; +var TooManyRequestsException = class _TooManyRequestsException extends SSOServiceException { + static { + __name(this, "TooManyRequestsException"); + } + name = "TooManyRequestsException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "TooManyRequestsException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _TooManyRequestsException.prototype); + } +}; +var UnauthorizedException = class _UnauthorizedException extends SSOServiceException { + static { + __name(this, "UnauthorizedException"); + } + name = "UnauthorizedException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "UnauthorizedException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _UnauthorizedException.prototype); + } +}; +var GetRoleCredentialsRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "GetRoleCredentialsRequestFilterSensitiveLog"); +var RoleCredentialsFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.secretAccessKey && { secretAccessKey: import_smithy_client.SENSITIVE_STRING }, + ...obj.sessionToken && { sessionToken: import_smithy_client.SENSITIVE_STRING } +}), "RoleCredentialsFilterSensitiveLog"); +var GetRoleCredentialsResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.roleCredentials && { roleCredentials: RoleCredentialsFilterSensitiveLog(obj.roleCredentials) } +}), "GetRoleCredentialsResponseFilterSensitiveLog"); +var ListAccountRolesRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "ListAccountRolesRequestFilterSensitiveLog"); +var ListAccountsRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "ListAccountsRequestFilterSensitiveLog"); +var LogoutRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client.SENSITIVE_STRING } +}), "LogoutRequestFilterSensitiveLog"); + +// src/protocols/Aws_restJson1.ts +var import_core2 = __nccwpck_require__(8704); + + +var se_GetRoleCredentialsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/federation/credentials"); + const query = (0, import_smithy_client.map)({ + [_rn]: [, (0, import_smithy_client.expectNonNull)(input[_rN], `roleName`)], + [_ai]: [, (0, import_smithy_client.expectNonNull)(input[_aI], `accountId`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_GetRoleCredentialsCommand"); +var se_ListAccountRolesCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/assignment/roles"); + const query = (0, import_smithy_client.map)({ + [_nt]: [, input[_nT]], + [_mr]: [() => input.maxResults !== void 0, () => input[_mR].toString()], + [_ai]: [, (0, import_smithy_client.expectNonNull)(input[_aI], `accountId`)] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListAccountRolesCommand"); +var se_ListAccountsCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/assignment/accounts"); + const query = (0, import_smithy_client.map)({ + [_nt]: [, input[_nT]], + [_mr]: [() => input.maxResults !== void 0, () => input[_mR].toString()] + }); + let body; + b.m("GET").h(headers).q(query).b(body); + return b.build(); +}, "se_ListAccountsCommand"); +var se_LogoutCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core.requestBuilder)(input, context); + const headers = (0, import_smithy_client.map)({}, import_smithy_client.isSerializableHeaderValue, { + [_xasbt]: input[_aT] + }); + b.bp("/logout"); + let body; + b.m("POST").h(headers).b(body); + return b.build(); +}, "se_LogoutCommand"); +var de_GetRoleCredentialsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client.take)(data, { + roleCredentials: import_smithy_client._json + }); + Object.assign(contents, doc); + return contents; +}, "de_GetRoleCredentialsCommand"); +var de_ListAccountRolesCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client.take)(data, { + nextToken: import_smithy_client.expectString, + roleList: import_smithy_client._json + }); + Object.assign(contents, doc); + return contents; +}, "de_ListAccountRolesCommand"); +var de_ListAccountsCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client.expectNonNull)((0, import_smithy_client.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client.take)(data, { + accountList: import_smithy_client._json, + nextToken: import_smithy_client.expectString + }); + Object.assign(contents, doc); + return contents; +}, "de_ListAccountsCommand"); +var de_LogoutCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client.map)({ + $metadata: deserializeMetadata(output) + }); + await (0, import_smithy_client.collectBody)(output.body, context); + return contents; +}, "de_LogoutCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core2.parseJsonErrorBody)(output.body, context) + }; + const errorCode = (0, import_core2.loadRestJsonErrorCode)(output, parsedOutput.body); + switch (errorCode) { + case "InvalidRequestException": + case "com.amazonaws.sso#InvalidRequestException": + throw await de_InvalidRequestExceptionRes(parsedOutput, context); + case "ResourceNotFoundException": + case "com.amazonaws.sso#ResourceNotFoundException": + throw await de_ResourceNotFoundExceptionRes(parsedOutput, context); + case "TooManyRequestsException": + case "com.amazonaws.sso#TooManyRequestsException": + throw await de_TooManyRequestsExceptionRes(parsedOutput, context); + case "UnauthorizedException": + case "com.amazonaws.sso#UnauthorizedException": + throw await de_UnauthorizedExceptionRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody, + errorCode + }); + } +}, "de_CommandError"); +var throwDefaultError = (0, import_smithy_client.withBaseException)(SSOServiceException); +var de_InvalidRequestExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidRequestException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidRequestExceptionRes"); +var de_ResourceNotFoundExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new ResourceNotFoundException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_ResourceNotFoundExceptionRes"); +var de_TooManyRequestsExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new TooManyRequestsException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_TooManyRequestsExceptionRes"); +var de_UnauthorizedExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client.take)(data, { + message: import_smithy_client.expectString + }); + Object.assign(contents, doc); + const exception = new UnauthorizedException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client.decorateServiceException)(exception, parsedOutput.body); +}, "de_UnauthorizedExceptionRes"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); +var _aI = "accountId"; +var _aT = "accessToken"; +var _ai = "account_id"; +var _mR = "maxResults"; +var _mr = "max_result"; +var _nT = "nextToken"; +var _nt = "next_token"; +var _rN = "roleName"; +var _rn = "role_name"; +var _xasbt = "x-amz-sso_bearer_token"; + +// src/commands/GetRoleCredentialsCommand.ts +var GetRoleCredentialsCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "GetRoleCredentials", {}).n("SSOClient", "GetRoleCredentialsCommand").f(GetRoleCredentialsRequestFilterSensitiveLog, GetRoleCredentialsResponseFilterSensitiveLog).ser(se_GetRoleCredentialsCommand).de(de_GetRoleCredentialsCommand).build() { + static { + __name(this, "GetRoleCredentialsCommand"); + } +}; + +// src/commands/ListAccountRolesCommand.ts + + + +var ListAccountRolesCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "ListAccountRoles", {}).n("SSOClient", "ListAccountRolesCommand").f(ListAccountRolesRequestFilterSensitiveLog, void 0).ser(se_ListAccountRolesCommand).de(de_ListAccountRolesCommand).build() { + static { + __name(this, "ListAccountRolesCommand"); + } +}; + +// src/commands/ListAccountsCommand.ts + + + +var ListAccountsCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "ListAccounts", {}).n("SSOClient", "ListAccountsCommand").f(ListAccountsRequestFilterSensitiveLog, void 0).ser(se_ListAccountsCommand).de(de_ListAccountsCommand).build() { + static { + __name(this, "ListAccountsCommand"); + } +}; + +// src/commands/LogoutCommand.ts + + + +var LogoutCommand = class extends import_smithy_client.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("SWBPortalService", "Logout", {}).n("SSOClient", "LogoutCommand").f(LogoutRequestFilterSensitiveLog, void 0).ser(se_LogoutCommand).de(de_LogoutCommand).build() { + static { + __name(this, "LogoutCommand"); + } +}; + +// src/SSO.ts +var commands = { + GetRoleCredentialsCommand, + ListAccountRolesCommand, + ListAccountsCommand, + LogoutCommand +}; +var SSO = class extends SSOClient { + static { + __name(this, "SSO"); + } +}; +(0, import_smithy_client.createAggregatedClient)(commands, SSO); + +// src/pagination/ListAccountRolesPaginator.ts + +var paginateListAccountRoles = (0, import_core.createPaginator)(SSOClient, ListAccountRolesCommand, "nextToken", "nextToken", "maxResults"); + +// src/pagination/ListAccountsPaginator.ts + +var paginateListAccounts = (0, import_core.createPaginator)(SSOClient, ListAccountsCommand, "nextToken", "nextToken", "maxResults"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 82696: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(45188)); +const core_1 = __nccwpck_require__(8704); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const hash_node_1 = __nccwpck_require__(5092); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(8073); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 8073: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const core_2 = __nccwpck_require__(90402); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(62041); +const endpointResolver_1 = __nccwpck_require__(13903); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2019-06-10", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSSOHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + serviceId: config?.serviceId ?? "SSO", + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 8704: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const tslib_1 = __nccwpck_require__(61860); +tslib_1.__exportStar(__nccwpck_require__(5152), exports); +tslib_1.__exportStar(__nccwpck_require__(97523), exports); +tslib_1.__exportStar(__nccwpck_require__(37288), exports); + + +/***/ }), + +/***/ 5152: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/client/index.ts +var index_exports = {}; +__export(index_exports, { + emitWarningIfUnsupportedVersion: () => emitWarningIfUnsupportedVersion, + setCredentialFeature: () => setCredentialFeature, + setFeature: () => setFeature, + setTokenFeature: () => setTokenFeature, + state: () => state +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/client/emitWarningIfUnsupportedVersion.ts +var state = { + warningEmitted: false +}; +var emitWarningIfUnsupportedVersion = /* @__PURE__ */ __name((version) => { + if (version && !state.warningEmitted && parseInt(version.substring(1, version.indexOf("."))) < 18) { + state.warningEmitted = true; + process.emitWarning( + `NodeDeprecationWarning: The AWS SDK for JavaScript (v3) will +no longer support Node.js 16.x on January 6, 2025. + +To continue receiving updates to AWS services, bug fixes, and security +updates please upgrade to a supported Node.js LTS version. + +More information can be found at: https://a.co/74kJMmI` + ); + } +}, "emitWarningIfUnsupportedVersion"); + +// src/submodules/client/setCredentialFeature.ts +function setCredentialFeature(credentials, feature, value) { + if (!credentials.$source) { + credentials.$source = {}; + } + credentials.$source[feature] = value; + return credentials; +} +__name(setCredentialFeature, "setCredentialFeature"); + +// src/submodules/client/setFeature.ts +function setFeature(context, feature, value) { + if (!context.__aws_sdk_context) { + context.__aws_sdk_context = { + features: {} + }; + } else if (!context.__aws_sdk_context.features) { + context.__aws_sdk_context.features = {}; + } + context.__aws_sdk_context.features[feature] = value; +} +__name(setFeature, "setFeature"); + +// src/submodules/client/setTokenFeature.ts +function setTokenFeature(token, feature, value) { + if (!token.$source) { + token.$source = {}; + } + token.$source[feature] = value; + return token; +} +__name(setTokenFeature, "setTokenFeature"); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 97523: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/httpAuthSchemes/index.ts +var index_exports = {}; +__export(index_exports, { + AWSSDKSigV4Signer: () => AWSSDKSigV4Signer, + AwsSdkSigV4ASigner: () => AwsSdkSigV4ASigner, + AwsSdkSigV4Signer: () => AwsSdkSigV4Signer, + NODE_AUTH_SCHEME_PREFERENCE_OPTIONS: () => NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, + NODE_SIGV4A_CONFIG_OPTIONS: () => NODE_SIGV4A_CONFIG_OPTIONS, + getBearerTokenEnvKey: () => getBearerTokenEnvKey, + resolveAWSSDKSigV4Config: () => resolveAWSSDKSigV4Config, + resolveAwsSdkSigV4AConfig: () => resolveAwsSdkSigV4AConfig, + resolveAwsSdkSigV4Config: () => resolveAwsSdkSigV4Config, + validateSigningProperties: () => validateSigningProperties +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts +var import_protocol_http2 = __nccwpck_require__(72356); + +// src/submodules/httpAuthSchemes/utils/getDateHeader.ts +var import_protocol_http = __nccwpck_require__(72356); +var getDateHeader = /* @__PURE__ */ __name((response) => import_protocol_http.HttpResponse.isInstance(response) ? response.headers?.date ?? response.headers?.Date : void 0, "getDateHeader"); + +// src/submodules/httpAuthSchemes/utils/getSkewCorrectedDate.ts +var getSkewCorrectedDate = /* @__PURE__ */ __name((systemClockOffset) => new Date(Date.now() + systemClockOffset), "getSkewCorrectedDate"); + +// src/submodules/httpAuthSchemes/utils/isClockSkewed.ts +var isClockSkewed = /* @__PURE__ */ __name((clockTime, systemClockOffset) => Math.abs(getSkewCorrectedDate(systemClockOffset).getTime() - clockTime) >= 3e5, "isClockSkewed"); + +// src/submodules/httpAuthSchemes/utils/getUpdatedSystemClockOffset.ts +var getUpdatedSystemClockOffset = /* @__PURE__ */ __name((clockTime, currentSystemClockOffset) => { + const clockTimeInMs = Date.parse(clockTime); + if (isClockSkewed(clockTimeInMs, currentSystemClockOffset)) { + return clockTimeInMs - Date.now(); + } + return currentSystemClockOffset; +}, "getUpdatedSystemClockOffset"); + +// src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4Signer.ts +var throwSigningPropertyError = /* @__PURE__ */ __name((name, property) => { + if (!property) { + throw new Error(`Property \`${name}\` is not resolved for AWS SDK SigV4Auth`); + } + return property; +}, "throwSigningPropertyError"); +var validateSigningProperties = /* @__PURE__ */ __name(async (signingProperties) => { + const context = throwSigningPropertyError( + "context", + signingProperties.context + ); + const config = throwSigningPropertyError("config", signingProperties.config); + const authScheme = context.endpointV2?.properties?.authSchemes?.[0]; + const signerFunction = throwSigningPropertyError( + "signer", + config.signer + ); + const signer = await signerFunction(authScheme); + const signingRegion = signingProperties?.signingRegion; + const signingRegionSet = signingProperties?.signingRegionSet; + const signingName = signingProperties?.signingName; + return { + config, + signer, + signingRegion, + signingRegionSet, + signingName + }; +}, "validateSigningProperties"); +var AwsSdkSigV4Signer = class { + static { + __name(this, "AwsSdkSigV4Signer"); + } + async sign(httpRequest, identity, signingProperties) { + if (!import_protocol_http2.HttpRequest.isInstance(httpRequest)) { + throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); + } + const validatedProps = await validateSigningProperties(signingProperties); + const { config, signer } = validatedProps; + let { signingRegion, signingName } = validatedProps; + const handlerExecutionContext = signingProperties.context; + if (handlerExecutionContext?.authSchemes?.length ?? 0 > 1) { + const [first, second] = handlerExecutionContext.authSchemes; + if (first?.name === "sigv4a" && second?.name === "sigv4") { + signingRegion = second?.signingRegion ?? signingRegion; + signingName = second?.signingName ?? signingName; + } + } + const signedRequest = await signer.sign(httpRequest, { + signingDate: getSkewCorrectedDate(config.systemClockOffset), + signingRegion, + signingService: signingName + }); + return signedRequest; + } + errorHandler(signingProperties) { + return (error) => { + const serverTime = error.ServerTime ?? getDateHeader(error.$response); + if (serverTime) { + const config = throwSigningPropertyError("config", signingProperties.config); + const initialSystemClockOffset = config.systemClockOffset; + config.systemClockOffset = getUpdatedSystemClockOffset(serverTime, config.systemClockOffset); + const clockSkewCorrected = config.systemClockOffset !== initialSystemClockOffset; + if (clockSkewCorrected && error.$metadata) { + error.$metadata.clockSkewCorrected = true; + } + } + throw error; + }; + } + successHandler(httpResponse, signingProperties) { + const dateHeader = getDateHeader(httpResponse); + if (dateHeader) { + const config = throwSigningPropertyError("config", signingProperties.config); + config.systemClockOffset = getUpdatedSystemClockOffset(dateHeader, config.systemClockOffset); + } + } +}; +var AWSSDKSigV4Signer = AwsSdkSigV4Signer; + +// src/submodules/httpAuthSchemes/aws_sdk/AwsSdkSigV4ASigner.ts +var import_protocol_http3 = __nccwpck_require__(72356); +var AwsSdkSigV4ASigner = class extends AwsSdkSigV4Signer { + static { + __name(this, "AwsSdkSigV4ASigner"); + } + async sign(httpRequest, identity, signingProperties) { + if (!import_protocol_http3.HttpRequest.isInstance(httpRequest)) { + throw new Error("The request is not an instance of `HttpRequest` and cannot be signed"); + } + const { config, signer, signingRegion, signingRegionSet, signingName } = await validateSigningProperties( + signingProperties + ); + const configResolvedSigningRegionSet = await config.sigv4aSigningRegionSet?.(); + const multiRegionOverride = (configResolvedSigningRegionSet ?? signingRegionSet ?? [signingRegion]).join(","); + const signedRequest = await signer.sign(httpRequest, { + signingDate: getSkewCorrectedDate(config.systemClockOffset), + signingRegion: multiRegionOverride, + signingService: signingName + }); + return signedRequest; + } +}; + +// src/submodules/httpAuthSchemes/utils/getArrayForCommaSeparatedString.ts +var getArrayForCommaSeparatedString = /* @__PURE__ */ __name((str) => typeof str === "string" && str.length > 0 ? str.split(",").map((item) => item.trim()) : [], "getArrayForCommaSeparatedString"); + +// src/submodules/httpAuthSchemes/utils/getBearerTokenEnvKey.ts +var getBearerTokenEnvKey = /* @__PURE__ */ __name((signingName) => `AWS_BEARER_TOKEN_${signingName.replace(/[\s-]/g, "_").toUpperCase()}`, "getBearerTokenEnvKey"); + +// src/submodules/httpAuthSchemes/aws_sdk/NODE_AUTH_SCHEME_PREFERENCE_OPTIONS.ts +var NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY = "AWS_AUTH_SCHEME_PREFERENCE"; +var NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY = "auth_scheme_preference"; +var NODE_AUTH_SCHEME_PREFERENCE_OPTIONS = { + /** + * Retrieves auth scheme preference from environment variables + * @param env - Node process environment object + * @returns Array of auth scheme strings if preference is set, undefined otherwise + */ + environmentVariableSelector: /* @__PURE__ */ __name((env, options) => { + if (options?.signingName) { + const bearerTokenKey = getBearerTokenEnvKey(options.signingName); + if (bearerTokenKey in env) return ["httpBearerAuth"]; + } + if (!(NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY in env)) return void 0; + return getArrayForCommaSeparatedString(env[NODE_AUTH_SCHEME_PREFERENCE_ENV_KEY]); + }, "environmentVariableSelector"), + /** + * Retrieves auth scheme preference from config file + * @param profile - Config profile object + * @returns Array of auth scheme strings if preference is set, undefined otherwise + */ + configFileSelector: /* @__PURE__ */ __name((profile) => { + if (!(NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY in profile)) return void 0; + return getArrayForCommaSeparatedString(profile[NODE_AUTH_SCHEME_PREFERENCE_CONFIG_KEY]); + }, "configFileSelector"), + /** + * Default auth scheme preference if not specified in environment or config + */ + default: [] +}; + +// src/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4AConfig.ts +var import_core = __nccwpck_require__(90402); +var import_property_provider = __nccwpck_require__(71238); +var resolveAwsSdkSigV4AConfig = /* @__PURE__ */ __name((config) => { + config.sigv4aSigningRegionSet = (0, import_core.normalizeProvider)(config.sigv4aSigningRegionSet); + return config; +}, "resolveAwsSdkSigV4AConfig"); +var NODE_SIGV4A_CONFIG_OPTIONS = { + environmentVariableSelector(env) { + if (env.AWS_SIGV4A_SIGNING_REGION_SET) { + return env.AWS_SIGV4A_SIGNING_REGION_SET.split(",").map((_) => _.trim()); + } + throw new import_property_provider.ProviderError("AWS_SIGV4A_SIGNING_REGION_SET not set in env.", { + tryNextLink: true + }); + }, + configFileSelector(profile) { + if (profile.sigv4a_signing_region_set) { + return (profile.sigv4a_signing_region_set ?? "").split(",").map((_) => _.trim()); + } + throw new import_property_provider.ProviderError("sigv4a_signing_region_set not set in profile.", { + tryNextLink: true + }); + }, + default: void 0 +}; + +// src/submodules/httpAuthSchemes/aws_sdk/resolveAwsSdkSigV4Config.ts +var import_client = __nccwpck_require__(5152); +var import_core2 = __nccwpck_require__(90402); +var import_signature_v4 = __nccwpck_require__(75118); +var resolveAwsSdkSigV4Config = /* @__PURE__ */ __name((config) => { + let inputCredentials = config.credentials; + let isUserSupplied = !!config.credentials; + let resolvedCredentials = void 0; + Object.defineProperty(config, "credentials", { + set(credentials) { + if (credentials && credentials !== inputCredentials && credentials !== resolvedCredentials) { + isUserSupplied = true; + } + inputCredentials = credentials; + const memoizedProvider = normalizeCredentialProvider(config, { + credentials: inputCredentials, + credentialDefaultProvider: config.credentialDefaultProvider + }); + const boundProvider = bindCallerConfig(config, memoizedProvider); + if (isUserSupplied && !boundProvider.attributed) { + resolvedCredentials = /* @__PURE__ */ __name(async (options) => boundProvider(options).then( + (creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_CODE", "e") + ), "resolvedCredentials"); + resolvedCredentials.memoized = boundProvider.memoized; + resolvedCredentials.configBound = boundProvider.configBound; + resolvedCredentials.attributed = true; + } else { + resolvedCredentials = boundProvider; + } + }, + get() { + return resolvedCredentials; + }, + enumerable: true, + configurable: true + }); + config.credentials = inputCredentials; + const { + // Default for signingEscapePath + signingEscapePath = true, + // Default for systemClockOffset + systemClockOffset = config.systemClockOffset || 0, + // No default for sha256 since it is platform dependent + sha256 + } = config; + let signer; + if (config.signer) { + signer = (0, import_core2.normalizeProvider)(config.signer); + } else if (config.regionInfoProvider) { + signer = /* @__PURE__ */ __name(() => (0, import_core2.normalizeProvider)(config.region)().then( + async (region) => [ + await config.regionInfoProvider(region, { + useFipsEndpoint: await config.useFipsEndpoint(), + useDualstackEndpoint: await config.useDualstackEndpoint() + }) || {}, + region + ] + ).then(([regionInfo, region]) => { + const { signingRegion, signingService } = regionInfo; + config.signingRegion = config.signingRegion || signingRegion || region; + config.signingName = config.signingName || signingService || config.serviceId; + const params = { + ...config, + credentials: config.credentials, + region: config.signingRegion, + service: config.signingName, + sha256, + uriEscapePath: signingEscapePath + }; + const SignerCtor = config.signerConstructor || import_signature_v4.SignatureV4; + return new SignerCtor(params); + }), "signer"); + } else { + signer = /* @__PURE__ */ __name(async (authScheme) => { + authScheme = Object.assign( + {}, + { + name: "sigv4", + signingName: config.signingName || config.defaultSigningName, + signingRegion: await (0, import_core2.normalizeProvider)(config.region)(), + properties: {} + }, + authScheme + ); + const signingRegion = authScheme.signingRegion; + const signingService = authScheme.signingName; + config.signingRegion = config.signingRegion || signingRegion; + config.signingName = config.signingName || signingService || config.serviceId; + const params = { + ...config, + credentials: config.credentials, + region: config.signingRegion, + service: config.signingName, + sha256, + uriEscapePath: signingEscapePath + }; + const SignerCtor = config.signerConstructor || import_signature_v4.SignatureV4; + return new SignerCtor(params); + }, "signer"); + } + const resolvedConfig = Object.assign(config, { + systemClockOffset, + signingEscapePath, + signer + }); + return resolvedConfig; +}, "resolveAwsSdkSigV4Config"); +var resolveAWSSDKSigV4Config = resolveAwsSdkSigV4Config; +function normalizeCredentialProvider(config, { + credentials, + credentialDefaultProvider +}) { + let credentialsProvider; + if (credentials) { + if (!credentials?.memoized) { + credentialsProvider = (0, import_core2.memoizeIdentityProvider)(credentials, import_core2.isIdentityExpired, import_core2.doesIdentityRequireRefresh); + } else { + credentialsProvider = credentials; + } + } else { + if (credentialDefaultProvider) { + credentialsProvider = (0, import_core2.normalizeProvider)( + credentialDefaultProvider( + Object.assign({}, config, { + parentClientConfig: config + }) + ) + ); + } else { + credentialsProvider = /* @__PURE__ */ __name(async () => { + throw new Error( + "@aws-sdk/core::resolveAwsSdkSigV4Config - `credentials` not provided and no credentialDefaultProvider was configured." + ); + }, "credentialsProvider"); + } + } + credentialsProvider.memoized = true; + return credentialsProvider; +} +__name(normalizeCredentialProvider, "normalizeCredentialProvider"); +function bindCallerConfig(config, credentialsProvider) { + if (credentialsProvider.configBound) { + return credentialsProvider; + } + const fn = /* @__PURE__ */ __name(async (options) => credentialsProvider({ ...options, callerClientConfig: config }), "fn"); + fn.memoized = credentialsProvider.memoized; + fn.configBound = true; + return fn; +} +__name(bindCallerConfig, "bindCallerConfig"); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 37288: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/protocols/index.ts +var index_exports = {}; +__export(index_exports, { + AwsEc2QueryProtocol: () => AwsEc2QueryProtocol, + AwsJson1_0Protocol: () => AwsJson1_0Protocol, + AwsJson1_1Protocol: () => AwsJson1_1Protocol, + AwsJsonRpcProtocol: () => AwsJsonRpcProtocol, + AwsQueryProtocol: () => AwsQueryProtocol, + AwsRestJsonProtocol: () => AwsRestJsonProtocol, + AwsRestXmlProtocol: () => AwsRestXmlProtocol, + JsonCodec: () => JsonCodec, + JsonShapeDeserializer: () => JsonShapeDeserializer, + JsonShapeSerializer: () => JsonShapeSerializer, + XmlCodec: () => XmlCodec, + XmlShapeDeserializer: () => XmlShapeDeserializer, + XmlShapeSerializer: () => XmlShapeSerializer, + _toBool: () => _toBool, + _toNum: () => _toNum, + _toStr: () => _toStr, + awsExpectUnion: () => awsExpectUnion, + loadRestJsonErrorCode: () => loadRestJsonErrorCode, + loadRestXmlErrorCode: () => loadRestXmlErrorCode, + parseJsonBody: () => parseJsonBody, + parseJsonErrorBody: () => parseJsonErrorBody, + parseXmlBody: () => parseXmlBody, + parseXmlErrorBody: () => parseXmlErrorBody +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/protocols/coercing-serializers.ts +var _toStr = /* @__PURE__ */ __name((val) => { + if (val == null) { + return val; + } + if (typeof val === "number" || typeof val === "bigint") { + const warning = new Error(`Received number ${val} where a string was expected.`); + warning.name = "Warning"; + console.warn(warning); + return String(val); + } + if (typeof val === "boolean") { + const warning = new Error(`Received boolean ${val} where a string was expected.`); + warning.name = "Warning"; + console.warn(warning); + return String(val); + } + return val; +}, "_toStr"); +var _toBool = /* @__PURE__ */ __name((val) => { + if (val == null) { + return val; + } + if (typeof val === "number") { + } + if (typeof val === "string") { + const lowercase = val.toLowerCase(); + if (val !== "" && lowercase !== "false" && lowercase !== "true") { + const warning = new Error(`Received string "${val}" where a boolean was expected.`); + warning.name = "Warning"; + console.warn(warning); + } + return val !== "" && lowercase !== "false"; + } + return val; +}, "_toBool"); +var _toNum = /* @__PURE__ */ __name((val) => { + if (val == null) { + return val; + } + if (typeof val === "boolean") { + } + if (typeof val === "string") { + const num = Number(val); + if (num.toString() !== val) { + const warning = new Error(`Received string "${val}" where a number was expected.`); + warning.name = "Warning"; + console.warn(warning); + return val; + } + return num; + } + return val; +}, "_toNum"); + +// src/submodules/protocols/json/AwsJsonRpcProtocol.ts +var import_protocols = __nccwpck_require__(93422); +var import_schema3 = __nccwpck_require__(26890); +var import_util_body_length_browser = __nccwpck_require__(12098); + +// src/submodules/protocols/ConfigurableSerdeContext.ts +var SerdeContextConfig = class { + static { + __name(this, "SerdeContextConfig"); + } + serdeContext; + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + } +}; + +// src/submodules/protocols/json/JsonShapeDeserializer.ts +var import_schema = __nccwpck_require__(26890); +var import_serde2 = __nccwpck_require__(92430); +var import_util_base64 = __nccwpck_require__(68385); + +// src/submodules/protocols/json/jsonReviver.ts +var import_serde = __nccwpck_require__(92430); +function jsonReviver(key, value, context) { + if (context?.source) { + const numericString = context.source; + if (typeof value === "number") { + if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER || numericString !== String(value)) { + const isFractional = numericString.includes("."); + if (isFractional) { + return new import_serde.NumericValue(numericString, "bigDecimal"); + } else { + return BigInt(numericString); + } + } + } + } + return value; +} +__name(jsonReviver, "jsonReviver"); + +// src/submodules/protocols/common.ts +var import_smithy_client = __nccwpck_require__(61411); +var collectBodyString = /* @__PURE__ */ __name((streamBody, context) => (0, import_smithy_client.collectBody)(streamBody, context).then((body) => context.utf8Encoder(body)), "collectBodyString"); + +// src/submodules/protocols/json/parseJsonBody.ts +var parseJsonBody = /* @__PURE__ */ __name((streamBody, context) => collectBodyString(streamBody, context).then((encoded) => { + if (encoded.length) { + try { + return JSON.parse(encoded); + } catch (e) { + if (e?.name === "SyntaxError") { + Object.defineProperty(e, "$responseBodyText", { + value: encoded + }); + } + throw e; + } + } + return {}; +}), "parseJsonBody"); +var parseJsonErrorBody = /* @__PURE__ */ __name(async (errorBody, context) => { + const value = await parseJsonBody(errorBody, context); + value.message = value.message ?? value.Message; + return value; +}, "parseJsonErrorBody"); +var loadRestJsonErrorCode = /* @__PURE__ */ __name((output, data) => { + const findKey = /* @__PURE__ */ __name((object, key) => Object.keys(object).find((k) => k.toLowerCase() === key.toLowerCase()), "findKey"); + const sanitizeErrorCode = /* @__PURE__ */ __name((rawValue) => { + let cleanValue = rawValue; + if (typeof cleanValue === "number") { + cleanValue = cleanValue.toString(); + } + if (cleanValue.indexOf(",") >= 0) { + cleanValue = cleanValue.split(",")[0]; + } + if (cleanValue.indexOf(":") >= 0) { + cleanValue = cleanValue.split(":")[0]; + } + if (cleanValue.indexOf("#") >= 0) { + cleanValue = cleanValue.split("#")[1]; + } + return cleanValue; + }, "sanitizeErrorCode"); + const headerKey = findKey(output.headers, "x-amzn-errortype"); + if (headerKey !== void 0) { + return sanitizeErrorCode(output.headers[headerKey]); + } + if (data && typeof data === "object") { + const codeKey = findKey(data, "code"); + if (codeKey && data[codeKey] !== void 0) { + return sanitizeErrorCode(data[codeKey]); + } + if (data["__type"] !== void 0) { + return sanitizeErrorCode(data["__type"]); + } + } +}, "loadRestJsonErrorCode"); + +// src/submodules/protocols/json/JsonShapeDeserializer.ts +var JsonShapeDeserializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "JsonShapeDeserializer"); + } + async read(schema, data) { + return this._read( + schema, + typeof data === "string" ? JSON.parse(data, jsonReviver) : await parseJsonBody(data, this.serdeContext) + ); + } + readObject(schema, data) { + return this._read(schema, data); + } + _read(schema, value) { + const isObject = value !== null && typeof value === "object"; + const ns = import_schema.NormalizedSchema.of(schema); + if (ns.isListSchema() && Array.isArray(value)) { + const listMember = ns.getValueSchema(); + const out = []; + const sparse = !!ns.getMergedTraits().sparse; + for (const item of value) { + if (sparse || item != null) { + out.push(this._read(listMember, item)); + } + } + return out; + } else if (ns.isMapSchema() && isObject) { + const mapMember = ns.getValueSchema(); + const out = {}; + const sparse = !!ns.getMergedTraits().sparse; + for (const [_k, _v] of Object.entries(value)) { + if (sparse || _v != null) { + out[_k] = this._read(mapMember, _v); + } + } + return out; + } else if (ns.isStructSchema() && isObject) { + const out = {}; + for (const [memberName, memberSchema] of ns.structIterator()) { + const fromKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName; + const deserializedValue = this._read(memberSchema, value[fromKey]); + if (deserializedValue != null) { + out[memberName] = deserializedValue; + } + } + return out; + } + if (ns.isBlobSchema() && typeof value === "string") { + return (0, import_util_base64.fromBase64)(value); + } + const mediaType = ns.getMergedTraits().mediaType; + if (ns.isStringSchema() && typeof value === "string" && mediaType) { + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + return import_serde2.LazyJsonString.from(value); + } + } + if (ns.isTimestampSchema()) { + const options = this.settings.timestampFormat; + const format = options.useTrait ? ns.getSchema() === import_schema.SCHEMA.TIMESTAMP_DEFAULT ? options.default : ns.getSchema() ?? options.default : options.default; + switch (format) { + case import_schema.SCHEMA.TIMESTAMP_DATE_TIME: + return (0, import_serde2.parseRfc3339DateTimeWithOffset)(value); + case import_schema.SCHEMA.TIMESTAMP_HTTP_DATE: + return (0, import_serde2.parseRfc7231DateTime)(value); + case import_schema.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + return (0, import_serde2.parseEpochTimestamp)(value); + default: + console.warn("Missing timestamp format, parsing value with Date constructor:", value); + return new Date(value); + } + } + if (ns.isBigIntegerSchema() && (typeof value === "number" || typeof value === "string")) { + return BigInt(value); + } + if (ns.isBigDecimalSchema() && value != void 0) { + if (value instanceof import_serde2.NumericValue) { + return value; + } + return new import_serde2.NumericValue(String(value), "bigDecimal"); + } + if (ns.isNumericSchema() && typeof value === "string") { + switch (value) { + case "Infinity": + return Infinity; + case "-Infinity": + return -Infinity; + case "NaN": + return NaN; + } + } + return value; + } +}; + +// src/submodules/protocols/json/JsonShapeSerializer.ts +var import_schema2 = __nccwpck_require__(26890); +var import_serde4 = __nccwpck_require__(92430); +var import_serde5 = __nccwpck_require__(92430); + +// src/submodules/protocols/json/jsonReplacer.ts +var import_serde3 = __nccwpck_require__(92430); +var NUMERIC_CONTROL_CHAR = String.fromCharCode(925); +var JsonReplacer = class { + static { + __name(this, "JsonReplacer"); + } + /** + * Stores placeholder key to true serialized value lookup. + */ + values = /* @__PURE__ */ new Map(); + counter = 0; + stage = 0; + /** + * Creates a jsonReplacer function that reserves big integer and big decimal values + * for later replacement. + */ + createReplacer() { + if (this.stage === 1) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer already created."); + } + if (this.stage === 2) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer exhausted."); + } + this.stage = 1; + return (key, value) => { + if (value instanceof import_serde3.NumericValue) { + const v = `${NUMERIC_CONTROL_CHAR + +"nv" + this.counter++}_` + value.string; + this.values.set(`"${v}"`, value.string); + return v; + } + if (typeof value === "bigint") { + const s = value.toString(); + const v = `${NUMERIC_CONTROL_CHAR + "b" + this.counter++}_` + s; + this.values.set(`"${v}"`, s); + return v; + } + return value; + }; + } + /** + * Replaces placeholder keys with their true values. + */ + replaceInJson(json) { + if (this.stage === 0) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer not created yet."); + } + if (this.stage === 2) { + throw new Error("@aws-sdk/core/protocols - JsonReplacer exhausted."); + } + this.stage = 2; + if (this.counter === 0) { + return json; + } + for (const [key, value] of this.values) { + json = json.replace(key, value); + } + return json; + } +}; + +// src/submodules/protocols/json/JsonShapeSerializer.ts +var JsonShapeSerializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "JsonShapeSerializer"); + } + buffer; + rootSchema; + write(schema, value) { + this.rootSchema = import_schema2.NormalizedSchema.of(schema); + this.buffer = this._write(this.rootSchema, value); + } + flush() { + if (this.rootSchema?.isStructSchema() || this.rootSchema?.isDocumentSchema()) { + const replacer = new JsonReplacer(); + return replacer.replaceInJson(JSON.stringify(this.buffer, replacer.createReplacer(), 0)); + } + return this.buffer; + } + _write(schema, value, container) { + const isObject = value !== null && typeof value === "object"; + const ns = import_schema2.NormalizedSchema.of(schema); + if (ns.isListSchema() && Array.isArray(value)) { + const listMember = ns.getValueSchema(); + const out = []; + const sparse = !!ns.getMergedTraits().sparse; + for (const item of value) { + if (sparse || item != null) { + out.push(this._write(listMember, item)); + } + } + return out; + } else if (ns.isMapSchema() && isObject) { + const mapMember = ns.getValueSchema(); + const out = {}; + const sparse = !!ns.getMergedTraits().sparse; + for (const [_k, _v] of Object.entries(value)) { + if (sparse || _v != null) { + out[_k] = this._write(mapMember, _v); + } + } + return out; + } else if (ns.isStructSchema() && isObject) { + const out = {}; + for (const [memberName, memberSchema] of ns.structIterator()) { + const targetKey = this.settings.jsonName ? memberSchema.getMergedTraits().jsonName ?? memberName : memberName; + const serializableValue = this._write(memberSchema, value[memberName], ns); + if (serializableValue !== void 0) { + out[targetKey] = serializableValue; + } + } + return out; + } + if (value === null && container?.isStructSchema()) { + return void 0; + } + if (ns.isBlobSchema() && (value instanceof Uint8Array || typeof value === "string")) { + if (ns === this.rootSchema) { + return value; + } + if (!this.serdeContext?.base64Encoder) { + throw new Error("Missing base64Encoder in serdeContext"); + } + return this.serdeContext?.base64Encoder(value); + } + if (ns.isTimestampSchema() && value instanceof Date) { + const options = this.settings.timestampFormat; + const format = options.useTrait ? ns.getSchema() === import_schema2.SCHEMA.TIMESTAMP_DEFAULT ? options.default : ns.getSchema() ?? options.default : options.default; + switch (format) { + case import_schema2.SCHEMA.TIMESTAMP_DATE_TIME: + return value.toISOString().replace(".000Z", "Z"); + case import_schema2.SCHEMA.TIMESTAMP_HTTP_DATE: + return (0, import_serde4.dateToUtcString)(value); + case import_schema2.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + return value.getTime() / 1e3; + default: + console.warn("Missing timestamp format, using epoch seconds", value); + return value.getTime() / 1e3; + } + } + if (ns.isNumericSchema() && typeof value === "number") { + if (Math.abs(value) === Infinity || isNaN(value)) { + return String(value); + } + } + const mediaType = ns.getMergedTraits().mediaType; + if (ns.isStringSchema() && typeof value === "string" && mediaType) { + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + return import_serde5.LazyJsonString.from(value); + } + } + return value; + } +}; + +// src/submodules/protocols/json/JsonCodec.ts +var JsonCodec = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "JsonCodec"); + } + createSerializer() { + const serializer = new JsonShapeSerializer(this.settings); + serializer.setSerdeContext(this.serdeContext); + return serializer; + } + createDeserializer() { + const deserializer = new JsonShapeDeserializer(this.settings); + deserializer.setSerdeContext(this.serdeContext); + return deserializer; + } +}; + +// src/submodules/protocols/json/AwsJsonRpcProtocol.ts +var AwsJsonRpcProtocol = class extends import_protocols.RpcProtocol { + static { + __name(this, "AwsJsonRpcProtocol"); + } + serializer; + deserializer; + codec; + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + this.codec = new JsonCodec({ + timestampFormat: { + useTrait: true, + default: import_schema3.SCHEMA.TIMESTAMP_EPOCH_SECONDS + }, + jsonName: false + }); + this.serializer = this.codec.createSerializer(); + this.deserializer = this.codec.createDeserializer(); + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + if (!request.path.endsWith("/")) { + request.path += "/"; + } + Object.assign(request.headers, { + "content-type": `application/x-amz-json-${this.getJsonRpcVersion()}`, + "x-amz-target": (this.getJsonRpcVersion() === "1.0" ? `JsonRpc10.` : `JsonProtocol.`) + import_schema3.NormalizedSchema.of(operationSchema).getName() + }); + if ((0, import_schema3.deref)(operationSchema.input) === "unit" || !request.body) { + request.body = "{}"; + } + try { + request.headers["content-length"] = String((0, import_util_body_length_browser.calculateBodyLength)(request.body)); + } catch (e) { + } + return request; + } + getPayloadCodec() { + return this.codec; + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = loadRestJsonErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const registry = import_schema3.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.getSchema(errorIdentifier); + } catch (e) { + const baseExceptionSchema = import_schema3.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), dataObject); + } + throw new Error(errorName); + } + const ns = import_schema3.NormalizedSchema.of(errorSchema); + const message = dataObject.message ?? dataObject.Message ?? "Unknown"; + const exception = new errorSchema.ctor(message); + await this.deserializeHttpMessage(errorSchema, context, response, dataObject); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().jsonName ?? name; + output[name] = this.codec.createDeserializer().readObject(member, dataObject[target]); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } +}; + +// src/submodules/protocols/json/AwsJson1_0Protocol.ts +var AwsJson1_0Protocol = class extends AwsJsonRpcProtocol { + static { + __name(this, "AwsJson1_0Protocol"); + } + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + } + getShapeId() { + return "aws.protocols#awsJson1_0"; + } + getJsonRpcVersion() { + return "1.0"; + } +}; + +// src/submodules/protocols/json/AwsJson1_1Protocol.ts +var AwsJson1_1Protocol = class extends AwsJsonRpcProtocol { + static { + __name(this, "AwsJson1_1Protocol"); + } + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + } + getShapeId() { + return "aws.protocols#awsJson1_1"; + } + getJsonRpcVersion() { + return "1.1"; + } +}; + +// src/submodules/protocols/json/AwsRestJsonProtocol.ts +var import_protocols2 = __nccwpck_require__(93422); +var import_schema4 = __nccwpck_require__(26890); +var import_util_body_length_browser2 = __nccwpck_require__(12098); +var AwsRestJsonProtocol = class extends import_protocols2.HttpBindingProtocol { + static { + __name(this, "AwsRestJsonProtocol"); + } + serializer; + deserializer; + codec; + constructor({ defaultNamespace }) { + super({ + defaultNamespace + }); + const settings = { + timestampFormat: { + useTrait: true, + default: import_schema4.SCHEMA.TIMESTAMP_EPOCH_SECONDS + }, + httpBindings: true, + jsonName: true + }; + this.codec = new JsonCodec(settings); + this.serializer = new import_protocols2.HttpInterceptingShapeSerializer(this.codec.createSerializer(), settings); + this.deserializer = new import_protocols2.HttpInterceptingShapeDeserializer(this.codec.createDeserializer(), settings); + } + getShapeId() { + return "aws.protocols#restJson1"; + } + getPayloadCodec() { + return this.codec; + } + setSerdeContext(serdeContext) { + this.codec.setSerdeContext(serdeContext); + super.setSerdeContext(serdeContext); + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + const inputSchema = import_schema4.NormalizedSchema.of(operationSchema.input); + const members = inputSchema.getMemberSchemas(); + if (!request.headers["content-type"]) { + const httpPayloadMember = Object.values(members).find((m) => { + return !!m.getMergedTraits().httpPayload; + }); + if (httpPayloadMember) { + const mediaType = httpPayloadMember.getMergedTraits().mediaType; + if (mediaType) { + request.headers["content-type"] = mediaType; + } else if (httpPayloadMember.isStringSchema()) { + request.headers["content-type"] = "text/plain"; + } else if (httpPayloadMember.isBlobSchema()) { + request.headers["content-type"] = "application/octet-stream"; + } else { + request.headers["content-type"] = "application/json"; + } + } else if (!inputSchema.isUnitSchema()) { + const hasBody = Object.values(members).find((m) => { + const { httpQuery, httpQueryParams, httpHeader, httpLabel, httpPrefixHeaders } = m.getMergedTraits(); + return !httpQuery && !httpQueryParams && !httpHeader && !httpLabel && httpPrefixHeaders === void 0; + }); + if (hasBody) { + request.headers["content-type"] = "application/json"; + } + } + } + if (request.headers["content-type"] && !request.body) { + request.body = "{}"; + } + if (request.body) { + try { + request.headers["content-length"] = String((0, import_util_body_length_browser2.calculateBodyLength)(request.body)); + } catch (e) { + } + } + return request; + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = loadRestJsonErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const registry = import_schema4.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.getSchema(errorIdentifier); + } catch (e) { + const baseExceptionSchema = import_schema4.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), dataObject); + } + throw new Error(errorName); + } + const ns = import_schema4.NormalizedSchema.of(errorSchema); + const message = dataObject.message ?? dataObject.Message ?? "Unknown"; + const exception = new errorSchema.ctor(message); + await this.deserializeHttpMessage(errorSchema, context, response, dataObject); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().jsonName ?? name; + output[name] = this.codec.createDeserializer().readObject(member, dataObject[target]); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } +}; + +// src/submodules/protocols/json/awsExpectUnion.ts +var import_smithy_client2 = __nccwpck_require__(61411); +var awsExpectUnion = /* @__PURE__ */ __name((value) => { + if (value == null) { + return void 0; + } + if (typeof value === "object" && "__type" in value) { + delete value.__type; + } + return (0, import_smithy_client2.expectUnion)(value); +}, "awsExpectUnion"); + +// src/submodules/protocols/query/AwsQueryProtocol.ts +var import_protocols5 = __nccwpck_require__(93422); +var import_schema7 = __nccwpck_require__(26890); +var import_util_body_length_browser3 = __nccwpck_require__(12098); + +// src/submodules/protocols/xml/XmlShapeDeserializer.ts +var import_protocols3 = __nccwpck_require__(93422); +var import_schema5 = __nccwpck_require__(26890); +var import_smithy_client3 = __nccwpck_require__(61411); +var import_util_utf8 = __nccwpck_require__(71577); +var import_fast_xml_parser = __nccwpck_require__(50591); +var XmlShapeDeserializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + this.stringDeserializer = new import_protocols3.FromStringShapeDeserializer(settings); + } + static { + __name(this, "XmlShapeDeserializer"); + } + stringDeserializer; + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + this.stringDeserializer.setSerdeContext(serdeContext); + } + /** + * @param schema - describing the data. + * @param bytes - serialized data. + * @param key - used by AwsQuery to step one additional depth into the object before reading it. + */ + read(schema, bytes, key) { + const ns = import_schema5.NormalizedSchema.of(schema); + const memberSchemas = ns.getMemberSchemas(); + const isEventPayload = ns.isStructSchema() && ns.isMemberSchema() && !!Object.values(memberSchemas).find((memberNs) => { + return !!memberNs.getMemberTraits().eventPayload; + }); + if (isEventPayload) { + const output = {}; + const memberName = Object.keys(memberSchemas)[0]; + const eventMemberSchema = memberSchemas[memberName]; + if (eventMemberSchema.isBlobSchema()) { + output[memberName] = bytes; + } else { + output[memberName] = this.read(memberSchemas[memberName], bytes); + } + return output; + } + const xmlString = (this.serdeContext?.utf8Encoder ?? import_util_utf8.toUtf8)(bytes); + const parsedObject = this.parseXml(xmlString); + return this.readSchema(schema, key ? parsedObject[key] : parsedObject); + } + readSchema(_schema, value) { + const ns = import_schema5.NormalizedSchema.of(_schema); + const traits = ns.getMergedTraits(); + if (ns.isListSchema() && !Array.isArray(value)) { + return this.readSchema(ns, [value]); + } + if (value == null) { + return value; + } + if (typeof value === "object") { + const sparse = !!traits.sparse; + const flat = !!traits.xmlFlattened; + if (ns.isListSchema()) { + const listValue = ns.getValueSchema(); + const buffer2 = []; + const sourceKey = listValue.getMergedTraits().xmlName ?? "member"; + const source = flat ? value : (value[0] ?? value)[sourceKey]; + const sourceArray = Array.isArray(source) ? source : [source]; + for (const v of sourceArray) { + if (v != null || sparse) { + buffer2.push(this.readSchema(listValue, v)); + } + } + return buffer2; + } + const buffer = {}; + if (ns.isMapSchema()) { + const keyNs = ns.getKeySchema(); + const memberNs = ns.getValueSchema(); + let entries; + if (flat) { + entries = Array.isArray(value) ? value : [value]; + } else { + entries = Array.isArray(value.entry) ? value.entry : [value.entry]; + } + const keyProperty = keyNs.getMergedTraits().xmlName ?? "key"; + const valueProperty = memberNs.getMergedTraits().xmlName ?? "value"; + for (const entry of entries) { + const key = entry[keyProperty]; + const value2 = entry[valueProperty]; + if (value2 != null || sparse) { + buffer[key] = this.readSchema(memberNs, value2); + } + } + return buffer; + } + if (ns.isStructSchema()) { + for (const [memberName, memberSchema] of ns.structIterator()) { + const memberTraits = memberSchema.getMergedTraits(); + const xmlObjectKey = !memberTraits.httpPayload ? memberSchema.getMemberTraits().xmlName ?? memberName : memberTraits.xmlName ?? memberSchema.getName(); + if (value[xmlObjectKey] != null) { + buffer[memberName] = this.readSchema(memberSchema, value[xmlObjectKey]); + } + } + return buffer; + } + if (ns.isDocumentSchema()) { + return value; + } + throw new Error(`@aws-sdk/core/protocols - xml deserializer unhandled schema type for ${ns.getName(true)}`); + } + if (ns.isListSchema()) { + return []; + } + if (ns.isMapSchema() || ns.isStructSchema()) { + return {}; + } + return this.stringDeserializer.read(ns, value); + } + parseXml(xml) { + if (xml.length) { + const parser = new import_fast_xml_parser.XMLParser({ + attributeNamePrefix: "", + htmlEntities: true, + ignoreAttributes: false, + ignoreDeclaration: true, + parseTagValue: false, + trimValues: false, + tagValueProcessor: /* @__PURE__ */ __name((_, val) => val.trim() === "" && val.includes("\n") ? "" : void 0, "tagValueProcessor") + }); + parser.addEntity("#xD", "\r"); + parser.addEntity("#10", "\n"); + let parsedObj; + try { + parsedObj = parser.parse(xml, true); + } catch (e) { + if (e && typeof e === "object") { + Object.defineProperty(e, "$responseBodyText", { + value: xml + }); + } + throw e; + } + const textNodeName = "#text"; + const key = Object.keys(parsedObj)[0]; + const parsedObjToReturn = parsedObj[key]; + if (parsedObjToReturn[textNodeName]) { + parsedObjToReturn[key] = parsedObjToReturn[textNodeName]; + delete parsedObjToReturn[textNodeName]; + } + return (0, import_smithy_client3.getValueFromTextNode)(parsedObjToReturn); + } + return {}; + } +}; + +// src/submodules/protocols/query/QueryShapeSerializer.ts +var import_protocols4 = __nccwpck_require__(93422); +var import_schema6 = __nccwpck_require__(26890); +var import_serde6 = __nccwpck_require__(92430); +var import_smithy_client4 = __nccwpck_require__(61411); +var import_util_base642 = __nccwpck_require__(68385); +var QueryShapeSerializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "QueryShapeSerializer"); + } + buffer; + write(schema, value, prefix = "") { + if (this.buffer === void 0) { + this.buffer = ""; + } + const ns = import_schema6.NormalizedSchema.of(schema); + if (prefix && !prefix.endsWith(".")) { + prefix += "."; + } + if (ns.isBlobSchema()) { + if (typeof value === "string" || value instanceof Uint8Array) { + this.writeKey(prefix); + this.writeValue((this.serdeContext?.base64Encoder ?? import_util_base642.toBase64)(value)); + } + } else if (ns.isBooleanSchema() || ns.isNumericSchema() || ns.isStringSchema()) { + if (value != null) { + this.writeKey(prefix); + this.writeValue(String(value)); + } + } else if (ns.isBigIntegerSchema()) { + if (value != null) { + this.writeKey(prefix); + this.writeValue(String(value)); + } + } else if (ns.isBigDecimalSchema()) { + if (value != null) { + this.writeKey(prefix); + this.writeValue(value instanceof import_serde6.NumericValue ? value.string : String(value)); + } + } else if (ns.isTimestampSchema()) { + if (value instanceof Date) { + this.writeKey(prefix); + const format = (0, import_protocols4.determineTimestampFormat)(ns, this.settings); + switch (format) { + case import_schema6.SCHEMA.TIMESTAMP_DATE_TIME: + this.writeValue(value.toISOString().replace(".000Z", "Z")); + break; + case import_schema6.SCHEMA.TIMESTAMP_HTTP_DATE: + this.writeValue((0, import_smithy_client4.dateToUtcString)(value)); + break; + case import_schema6.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + this.writeValue(String(value.getTime() / 1e3)); + break; + } + } + } else if (ns.isDocumentSchema()) { + throw new Error(`@aws-sdk/core/protocols - QuerySerializer unsupported document type ${ns.getName(true)}`); + } else if (ns.isListSchema()) { + if (Array.isArray(value)) { + if (value.length === 0) { + if (this.settings.serializeEmptyLists) { + this.writeKey(prefix); + this.writeValue(""); + } + } else { + const member = ns.getValueSchema(); + const flat = this.settings.flattenLists || ns.getMergedTraits().xmlFlattened; + let i = 1; + for (const item of value) { + if (item == null) { + continue; + } + const suffix = this.getKey("member", member.getMergedTraits().xmlName); + const key = flat ? `${prefix}${i}` : `${prefix}${suffix}.${i}`; + this.write(member, item, key); + ++i; + } + } + } + } else if (ns.isMapSchema()) { + if (value && typeof value === "object") { + const keySchema = ns.getKeySchema(); + const memberSchema = ns.getValueSchema(); + const flat = ns.getMergedTraits().xmlFlattened; + let i = 1; + for (const [k, v] of Object.entries(value)) { + if (v == null) { + continue; + } + const keySuffix = this.getKey("key", keySchema.getMergedTraits().xmlName); + const key = flat ? `${prefix}${i}.${keySuffix}` : `${prefix}entry.${i}.${keySuffix}`; + const valueSuffix = this.getKey("value", memberSchema.getMergedTraits().xmlName); + const valueKey = flat ? `${prefix}${i}.${valueSuffix}` : `${prefix}entry.${i}.${valueSuffix}`; + this.write(keySchema, k, key); + this.write(memberSchema, v, valueKey); + ++i; + } + } + } else if (ns.isStructSchema()) { + if (value && typeof value === "object") { + for (const [memberName, member] of ns.structIterator()) { + if (value[memberName] == null) { + continue; + } + const suffix = this.getKey(memberName, member.getMergedTraits().xmlName); + const key = `${prefix}${suffix}`; + this.write(member, value[memberName], key); + } + } + } else if (ns.isUnitSchema()) { + } else { + throw new Error(`@aws-sdk/core/protocols - QuerySerializer unrecognized schema type ${ns.getName(true)}`); + } + } + flush() { + if (this.buffer === void 0) { + throw new Error("@aws-sdk/core/protocols - QuerySerializer cannot flush with nothing written to buffer."); + } + const str = this.buffer; + delete this.buffer; + return str; + } + getKey(memberName, xmlName) { + const key = xmlName ?? memberName; + if (this.settings.capitalizeKeys) { + return key[0].toUpperCase() + key.slice(1); + } + return key; + } + writeKey(key) { + if (key.endsWith(".")) { + key = key.slice(0, key.length - 1); + } + this.buffer += `&${(0, import_protocols4.extendedEncodeURIComponent)(key)}=`; + } + writeValue(value) { + this.buffer += (0, import_protocols4.extendedEncodeURIComponent)(value); + } +}; + +// src/submodules/protocols/query/AwsQueryProtocol.ts +var AwsQueryProtocol = class extends import_protocols5.RpcProtocol { + constructor(options) { + super({ + defaultNamespace: options.defaultNamespace + }); + this.options = options; + const settings = { + timestampFormat: { + useTrait: true, + default: import_schema7.SCHEMA.TIMESTAMP_DATE_TIME + }, + httpBindings: false, + xmlNamespace: options.xmlNamespace, + serviceNamespace: options.defaultNamespace, + serializeEmptyLists: true + }; + this.serializer = new QueryShapeSerializer(settings); + this.deserializer = new XmlShapeDeserializer(settings); + } + static { + __name(this, "AwsQueryProtocol"); + } + serializer; + deserializer; + getShapeId() { + return "aws.protocols#awsQuery"; + } + setSerdeContext(serdeContext) { + this.serializer.setSerdeContext(serdeContext); + this.deserializer.setSerdeContext(serdeContext); + } + getPayloadCodec() { + throw new Error("AWSQuery protocol has no payload codec."); + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + if (!request.path.endsWith("/")) { + request.path += "/"; + } + Object.assign(request.headers, { + "content-type": `application/x-www-form-urlencoded` + }); + if ((0, import_schema7.deref)(operationSchema.input) === "unit" || !request.body) { + request.body = ""; + } + request.body = `Action=${operationSchema.name.split("#")[1]}&Version=${this.options.version}` + request.body; + if (request.body.endsWith("&")) { + request.body = request.body.slice(-1); + } + try { + request.headers["content-length"] = String((0, import_util_body_length_browser3.calculateBodyLength)(request.body)); + } catch (e) { + } + return request; + } + async deserializeResponse(operationSchema, context, response) { + const deserializer = this.deserializer; + const ns = import_schema7.NormalizedSchema.of(operationSchema.output); + const dataObject = {}; + if (response.statusCode >= 300) { + const bytes2 = await (0, import_protocols5.collectBody)(response.body, context); + if (bytes2.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(import_schema7.SCHEMA.DOCUMENT, bytes2)); + } + await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response)); + } + for (const header in response.headers) { + const value = response.headers[header]; + delete response.headers[header]; + response.headers[header.toLowerCase()] = value; + } + const awsQueryResultKey = ns.isStructSchema() && this.useNestedResult() ? operationSchema.name.split("#")[1] + "Result" : void 0; + const bytes = await (0, import_protocols5.collectBody)(response.body, context); + if (bytes.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(ns, bytes, awsQueryResultKey)); + } + const output = { + $metadata: this.deserializeMetadata(response), + ...dataObject + }; + return output; + } + /** + * EC2 Query overrides this. + */ + useNestedResult() { + return true; + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = this.loadQueryErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const errorDataSource = this.loadQueryError(dataObject); + const registry = import_schema7.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.find( + (schema) => import_schema7.NormalizedSchema.of(schema).getMergedTraits().awsQueryError?.[0] === errorName + ); + if (!errorSchema) { + errorSchema = registry.getSchema(errorIdentifier); + } + } catch (e) { + const baseExceptionSchema = import_schema7.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), errorDataSource); + } + throw new Error(errorName); + } + const ns = import_schema7.NormalizedSchema.of(errorSchema); + const message = this.loadQueryErrorMessage(dataObject); + const exception = new errorSchema.ctor(message); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().xmlName ?? name; + const value = errorDataSource[target] ?? dataObject[target]; + output[name] = this.deserializer.readSchema(member, value); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } + /** + * The variations in the error and error message locations are attributed to + * divergence between AWS Query and EC2 Query behavior. + */ + loadQueryErrorCode(output, data) { + const code = (data.Errors?.[0]?.Error ?? data.Errors?.Error ?? data.Error)?.Code; + if (code !== void 0) { + return code; + } + if (output.statusCode == 404) { + return "NotFound"; + } + } + loadQueryError(data) { + return data.Errors?.[0]?.Error ?? data.Errors?.Error ?? data.Error; + } + loadQueryErrorMessage(data) { + const errorData = this.loadQueryError(data); + return errorData?.message ?? errorData?.Message ?? data.message ?? data.Message ?? "Unknown"; + } +}; + +// src/submodules/protocols/query/AwsEc2QueryProtocol.ts +var AwsEc2QueryProtocol = class extends AwsQueryProtocol { + constructor(options) { + super(options); + this.options = options; + const ec2Settings = { + capitalizeKeys: true, + flattenLists: true, + serializeEmptyLists: false + }; + Object.assign(this.serializer.settings, ec2Settings); + } + static { + __name(this, "AwsEc2QueryProtocol"); + } + /** + * EC2 Query reads XResponse.XResult instead of XResponse directly. + */ + useNestedResult() { + return false; + } +}; + +// src/submodules/protocols/xml/AwsRestXmlProtocol.ts +var import_protocols6 = __nccwpck_require__(93422); +var import_schema9 = __nccwpck_require__(26890); +var import_util_body_length_browser4 = __nccwpck_require__(12098); + +// src/submodules/protocols/xml/parseXmlBody.ts +var import_smithy_client5 = __nccwpck_require__(61411); +var import_fast_xml_parser2 = __nccwpck_require__(50591); +var parseXmlBody = /* @__PURE__ */ __name((streamBody, context) => collectBodyString(streamBody, context).then((encoded) => { + if (encoded.length) { + const parser = new import_fast_xml_parser2.XMLParser({ + attributeNamePrefix: "", + htmlEntities: true, + ignoreAttributes: false, + ignoreDeclaration: true, + parseTagValue: false, + trimValues: false, + tagValueProcessor: /* @__PURE__ */ __name((_, val) => val.trim() === "" && val.includes("\n") ? "" : void 0, "tagValueProcessor") + }); + parser.addEntity("#xD", "\r"); + parser.addEntity("#10", "\n"); + let parsedObj; + try { + parsedObj = parser.parse(encoded, true); + } catch (e) { + if (e && typeof e === "object") { + Object.defineProperty(e, "$responseBodyText", { + value: encoded + }); + } + throw e; + } + const textNodeName = "#text"; + const key = Object.keys(parsedObj)[0]; + const parsedObjToReturn = parsedObj[key]; + if (parsedObjToReturn[textNodeName]) { + parsedObjToReturn[key] = parsedObjToReturn[textNodeName]; + delete parsedObjToReturn[textNodeName]; + } + return (0, import_smithy_client5.getValueFromTextNode)(parsedObjToReturn); + } + return {}; +}), "parseXmlBody"); +var parseXmlErrorBody = /* @__PURE__ */ __name(async (errorBody, context) => { + const value = await parseXmlBody(errorBody, context); + if (value.Error) { + value.Error.message = value.Error.message ?? value.Error.Message; + } + return value; +}, "parseXmlErrorBody"); +var loadRestXmlErrorCode = /* @__PURE__ */ __name((output, data) => { + if (data?.Error?.Code !== void 0) { + return data.Error.Code; + } + if (data?.Code !== void 0) { + return data.Code; + } + if (output.statusCode == 404) { + return "NotFound"; + } +}, "loadRestXmlErrorCode"); + +// src/submodules/protocols/xml/XmlShapeSerializer.ts +var import_xml_builder = __nccwpck_require__(94274); +var import_schema8 = __nccwpck_require__(26890); +var import_serde7 = __nccwpck_require__(92430); +var import_smithy_client6 = __nccwpck_require__(61411); +var import_util_base643 = __nccwpck_require__(68385); +var XmlShapeSerializer = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "XmlShapeSerializer"); + } + stringBuffer; + byteBuffer; + buffer; + write(schema, value) { + const ns = import_schema8.NormalizedSchema.of(schema); + if (ns.isStringSchema() && typeof value === "string") { + this.stringBuffer = value; + } else if (ns.isBlobSchema()) { + this.byteBuffer = "byteLength" in value ? value : (this.serdeContext?.base64Decoder ?? import_util_base643.fromBase64)(value); + } else { + this.buffer = this.writeStruct(ns, value, void 0); + const traits = ns.getMergedTraits(); + if (traits.httpPayload && !traits.xmlName) { + this.buffer.withName(ns.getName()); + } + } + } + flush() { + if (this.byteBuffer !== void 0) { + const bytes = this.byteBuffer; + delete this.byteBuffer; + return bytes; + } + if (this.stringBuffer !== void 0) { + const str = this.stringBuffer; + delete this.stringBuffer; + return str; + } + const buffer = this.buffer; + if (this.settings.xmlNamespace) { + if (!buffer?.attributes?.["xmlns"]) { + buffer.addAttribute("xmlns", this.settings.xmlNamespace); + } + } + delete this.buffer; + return buffer.toString(); + } + writeStruct(ns, value, parentXmlns) { + const traits = ns.getMergedTraits(); + const name = ns.isMemberSchema() && !traits.httpPayload ? ns.getMemberTraits().xmlName ?? ns.getMemberName() : traits.xmlName ?? ns.getName(); + if (!name || !ns.isStructSchema()) { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, cannot write struct with empty name or non-struct, schema=${ns.getName( + true + )}.` + ); + } + const structXmlNode = import_xml_builder.XmlNode.of(name); + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(ns, parentXmlns); + if (xmlns) { + structXmlNode.addAttribute(xmlnsAttr, xmlns); + } + for (const [memberName, memberSchema] of ns.structIterator()) { + const val = value[memberName]; + if (val != null) { + if (memberSchema.getMergedTraits().xmlAttribute) { + structXmlNode.addAttribute( + memberSchema.getMergedTraits().xmlName ?? memberName, + this.writeSimple(memberSchema, val) + ); + continue; + } + if (memberSchema.isListSchema()) { + this.writeList(memberSchema, val, structXmlNode, xmlns); + } else if (memberSchema.isMapSchema()) { + this.writeMap(memberSchema, val, structXmlNode, xmlns); + } else if (memberSchema.isStructSchema()) { + structXmlNode.addChildNode(this.writeStruct(memberSchema, val, xmlns)); + } else { + const memberNode = import_xml_builder.XmlNode.of(memberSchema.getMergedTraits().xmlName ?? memberSchema.getMemberName()); + this.writeSimpleInto(memberSchema, val, memberNode, xmlns); + structXmlNode.addChildNode(memberNode); + } + } + } + return structXmlNode; + } + writeList(listMember, array, container, parentXmlns) { + if (!listMember.isMemberSchema()) { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, cannot write non-member list: ${listMember.getName(true)}` + ); + } + const listTraits = listMember.getMergedTraits(); + const listValueSchema = listMember.getValueSchema(); + const listValueTraits = listValueSchema.getMergedTraits(); + const sparse = !!listValueTraits.sparse; + const flat = !!listTraits.xmlFlattened; + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(listMember, parentXmlns); + const writeItem = /* @__PURE__ */ __name((container2, value) => { + if (listValueSchema.isListSchema()) { + this.writeList(listValueSchema, Array.isArray(value) ? value : [value], container2, xmlns); + } else if (listValueSchema.isMapSchema()) { + this.writeMap(listValueSchema, value, container2, xmlns); + } else if (listValueSchema.isStructSchema()) { + const struct = this.writeStruct(listValueSchema, value, xmlns); + container2.addChildNode( + struct.withName(flat ? listTraits.xmlName ?? listMember.getMemberName() : listValueTraits.xmlName ?? "member") + ); + } else { + const listItemNode = import_xml_builder.XmlNode.of( + flat ? listTraits.xmlName ?? listMember.getMemberName() : listValueTraits.xmlName ?? "member" + ); + this.writeSimpleInto(listValueSchema, value, listItemNode, xmlns); + container2.addChildNode(listItemNode); + } + }, "writeItem"); + if (flat) { + for (const value of array) { + if (sparse || value != null) { + writeItem(container, value); + } + } + } else { + const listNode = import_xml_builder.XmlNode.of(listTraits.xmlName ?? listMember.getMemberName()); + if (xmlns) { + listNode.addAttribute(xmlnsAttr, xmlns); + } + for (const value of array) { + if (sparse || value != null) { + writeItem(listNode, value); + } + } + container.addChildNode(listNode); + } + } + writeMap(mapMember, map, container, parentXmlns, containerIsMap = false) { + if (!mapMember.isMemberSchema()) { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, cannot write non-member map: ${mapMember.getName(true)}` + ); + } + const mapTraits = mapMember.getMergedTraits(); + const mapKeySchema = mapMember.getKeySchema(); + const mapKeyTraits = mapKeySchema.getMergedTraits(); + const keyTag = mapKeyTraits.xmlName ?? "key"; + const mapValueSchema = mapMember.getValueSchema(); + const mapValueTraits = mapValueSchema.getMergedTraits(); + const valueTag = mapValueTraits.xmlName ?? "value"; + const sparse = !!mapValueTraits.sparse; + const flat = !!mapTraits.xmlFlattened; + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(mapMember, parentXmlns); + const addKeyValue = /* @__PURE__ */ __name((entry, key, val) => { + const keyNode = import_xml_builder.XmlNode.of(keyTag, key); + const [keyXmlnsAttr, keyXmlns] = this.getXmlnsAttribute(mapKeySchema, xmlns); + if (keyXmlns) { + keyNode.addAttribute(keyXmlnsAttr, keyXmlns); + } + entry.addChildNode(keyNode); + let valueNode = import_xml_builder.XmlNode.of(valueTag); + if (mapValueSchema.isListSchema()) { + this.writeList(mapValueSchema, val, valueNode, xmlns); + } else if (mapValueSchema.isMapSchema()) { + this.writeMap(mapValueSchema, val, valueNode, xmlns, true); + } else if (mapValueSchema.isStructSchema()) { + valueNode = this.writeStruct(mapValueSchema, val, xmlns); + } else { + this.writeSimpleInto(mapValueSchema, val, valueNode, xmlns); + } + entry.addChildNode(valueNode); + }, "addKeyValue"); + if (flat) { + for (const [key, val] of Object.entries(map)) { + if (sparse || val != null) { + const entry = import_xml_builder.XmlNode.of(mapTraits.xmlName ?? mapMember.getMemberName()); + addKeyValue(entry, key, val); + container.addChildNode(entry); + } + } + } else { + let mapNode; + if (!containerIsMap) { + mapNode = import_xml_builder.XmlNode.of(mapTraits.xmlName ?? mapMember.getMemberName()); + if (xmlns) { + mapNode.addAttribute(xmlnsAttr, xmlns); + } + container.addChildNode(mapNode); + } + for (const [key, val] of Object.entries(map)) { + if (sparse || val != null) { + const entry = import_xml_builder.XmlNode.of("entry"); + addKeyValue(entry, key, val); + (containerIsMap ? container : mapNode).addChildNode(entry); + } + } + } + } + writeSimple(_schema, value) { + if (null === value) { + throw new Error("@aws-sdk/core/protocols - (XML serializer) cannot write null value."); + } + const ns = import_schema8.NormalizedSchema.of(_schema); + let nodeContents = null; + if (value && typeof value === "object") { + if (ns.isBlobSchema()) { + nodeContents = (this.serdeContext?.base64Encoder ?? import_util_base643.toBase64)(value); + } else if (ns.isTimestampSchema() && value instanceof Date) { + const options = this.settings.timestampFormat; + const format = options.useTrait ? ns.getSchema() === import_schema8.SCHEMA.TIMESTAMP_DEFAULT ? options.default : ns.getSchema() ?? options.default : options.default; + switch (format) { + case import_schema8.SCHEMA.TIMESTAMP_DATE_TIME: + nodeContents = value.toISOString().replace(".000Z", "Z"); + break; + case import_schema8.SCHEMA.TIMESTAMP_HTTP_DATE: + nodeContents = (0, import_smithy_client6.dateToUtcString)(value); + break; + case import_schema8.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + nodeContents = String(value.getTime() / 1e3); + break; + default: + console.warn("Missing timestamp format, using http date", value); + nodeContents = (0, import_smithy_client6.dateToUtcString)(value); + break; + } + } else if (ns.isBigDecimalSchema() && value) { + if (value instanceof import_serde7.NumericValue) { + return value.string; + } + return String(value); + } else if (ns.isMapSchema() || ns.isListSchema()) { + throw new Error( + "@aws-sdk/core/protocols - xml serializer, cannot call _write() on List/Map schema, call writeList or writeMap() instead." + ); + } else { + throw new Error( + `@aws-sdk/core/protocols - xml serializer, unhandled schema type for object value and schema: ${ns.getName( + true + )}` + ); + } + } + if (ns.isStringSchema() || ns.isBooleanSchema() || ns.isNumericSchema() || ns.isBigIntegerSchema() || ns.isBigDecimalSchema()) { + nodeContents = String(value); + } + if (nodeContents === null) { + throw new Error(`Unhandled schema-value pair ${ns.getName(true)}=${value}`); + } + return nodeContents; + } + writeSimpleInto(_schema, value, into, parentXmlns) { + const nodeContents = this.writeSimple(_schema, value); + const ns = import_schema8.NormalizedSchema.of(_schema); + const content = new import_xml_builder.XmlText(nodeContents); + const [xmlnsAttr, xmlns] = this.getXmlnsAttribute(ns, parentXmlns); + if (xmlns) { + into.addAttribute(xmlnsAttr, xmlns); + } + into.addChildNode(content); + } + getXmlnsAttribute(ns, parentXmlns) { + const traits = ns.getMergedTraits(); + const [prefix, xmlns] = traits.xmlNamespace ?? []; + if (xmlns && xmlns !== parentXmlns) { + return [prefix ? `xmlns:${prefix}` : "xmlns", xmlns]; + } + return [void 0, void 0]; + } +}; + +// src/submodules/protocols/xml/XmlCodec.ts +var XmlCodec = class extends SerdeContextConfig { + constructor(settings) { + super(); + this.settings = settings; + } + static { + __name(this, "XmlCodec"); + } + createSerializer() { + const serializer = new XmlShapeSerializer(this.settings); + serializer.setSerdeContext(this.serdeContext); + return serializer; + } + createDeserializer() { + const deserializer = new XmlShapeDeserializer(this.settings); + deserializer.setSerdeContext(this.serdeContext); + return deserializer; + } +}; + +// src/submodules/protocols/xml/AwsRestXmlProtocol.ts +var AwsRestXmlProtocol = class extends import_protocols6.HttpBindingProtocol { + static { + __name(this, "AwsRestXmlProtocol"); + } + codec; + serializer; + deserializer; + constructor(options) { + super(options); + const settings = { + timestampFormat: { + useTrait: true, + default: import_schema9.SCHEMA.TIMESTAMP_DATE_TIME + }, + httpBindings: true, + xmlNamespace: options.xmlNamespace, + serviceNamespace: options.defaultNamespace + }; + this.codec = new XmlCodec(settings); + this.serializer = new import_protocols6.HttpInterceptingShapeSerializer(this.codec.createSerializer(), settings); + this.deserializer = new import_protocols6.HttpInterceptingShapeDeserializer(this.codec.createDeserializer(), settings); + } + getPayloadCodec() { + return this.codec; + } + getShapeId() { + return "aws.protocols#restXml"; + } + async serializeRequest(operationSchema, input, context) { + const request = await super.serializeRequest(operationSchema, input, context); + const ns = import_schema9.NormalizedSchema.of(operationSchema.input); + const members = ns.getMemberSchemas(); + request.path = String(request.path).split("/").filter((segment) => { + return segment !== "{Bucket}"; + }).join("/") || "/"; + if (!request.headers["content-type"]) { + const httpPayloadMember = Object.values(members).find((m) => { + return !!m.getMergedTraits().httpPayload; + }); + if (httpPayloadMember) { + const mediaType = httpPayloadMember.getMergedTraits().mediaType; + if (mediaType) { + request.headers["content-type"] = mediaType; + } else if (httpPayloadMember.isStringSchema()) { + request.headers["content-type"] = "text/plain"; + } else if (httpPayloadMember.isBlobSchema()) { + request.headers["content-type"] = "application/octet-stream"; + } else { + request.headers["content-type"] = "application/xml"; + } + } else if (!ns.isUnitSchema()) { + const hasBody = Object.values(members).find((m) => { + const { httpQuery, httpQueryParams, httpHeader, httpLabel, httpPrefixHeaders } = m.getMergedTraits(); + return !httpQuery && !httpQueryParams && !httpHeader && !httpLabel && httpPrefixHeaders === void 0; + }); + if (hasBody) { + request.headers["content-type"] = "application/xml"; + } + } + } + if (request.headers["content-type"] === "application/xml") { + if (typeof request.body === "string") { + request.body = '' + request.body; + } + } + if (request.body) { + try { + request.headers["content-length"] = String((0, import_util_body_length_browser4.calculateBodyLength)(request.body)); + } catch (e) { + } + } + return request; + } + async deserializeResponse(operationSchema, context, response) { + return super.deserializeResponse(operationSchema, context, response); + } + async handleError(operationSchema, context, response, dataObject, metadata) { + const errorIdentifier = loadRestXmlErrorCode(response, dataObject) ?? "Unknown"; + let namespace = this.options.defaultNamespace; + let errorName = errorIdentifier; + if (errorIdentifier.includes("#")) { + [namespace, errorName] = errorIdentifier.split("#"); + } + const registry = import_schema9.TypeRegistry.for(namespace); + let errorSchema; + try { + errorSchema = registry.getSchema(errorIdentifier); + } catch (e) { + const baseExceptionSchema = import_schema9.TypeRegistry.for("smithy.ts.sdk.synthetic." + namespace).getBaseException(); + if (baseExceptionSchema) { + const ErrorCtor = baseExceptionSchema.ctor; + throw Object.assign(new ErrorCtor(errorName), dataObject); + } + throw new Error(errorName); + } + const ns = import_schema9.NormalizedSchema.of(errorSchema); + const message = dataObject.Error?.message ?? dataObject.Error?.Message ?? dataObject.message ?? dataObject.Message ?? "Unknown"; + const exception = new errorSchema.ctor(message); + await this.deserializeHttpMessage(errorSchema, context, response, dataObject); + const output = {}; + for (const [name, member] of ns.structIterator()) { + const target = member.getMergedTraits().xmlName ?? name; + const value = dataObject.Error?.[target] ?? dataObject[target]; + output[name] = this.codec.createDeserializer().readSchema(member, value); + } + Object.assign(exception, { + $metadata: metadata, + $response: response, + $fault: ns.getMergedTraits().error, + message, + ...output + }); + throw exception; + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 55606: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + ENV_ACCOUNT_ID: () => ENV_ACCOUNT_ID, + ENV_CREDENTIAL_SCOPE: () => ENV_CREDENTIAL_SCOPE, + ENV_EXPIRATION: () => ENV_EXPIRATION, + ENV_KEY: () => ENV_KEY, + ENV_SECRET: () => ENV_SECRET, + ENV_SESSION: () => ENV_SESSION, + fromEnv: () => fromEnv +}); +module.exports = __toCommonJS(index_exports); + +// src/fromEnv.ts +var import_client = __nccwpck_require__(5152); +var import_property_provider = __nccwpck_require__(71238); +var ENV_KEY = "AWS_ACCESS_KEY_ID"; +var ENV_SECRET = "AWS_SECRET_ACCESS_KEY"; +var ENV_SESSION = "AWS_SESSION_TOKEN"; +var ENV_EXPIRATION = "AWS_CREDENTIAL_EXPIRATION"; +var ENV_CREDENTIAL_SCOPE = "AWS_CREDENTIAL_SCOPE"; +var ENV_ACCOUNT_ID = "AWS_ACCOUNT_ID"; +var fromEnv = /* @__PURE__ */ __name((init) => async () => { + init?.logger?.debug("@aws-sdk/credential-provider-env - fromEnv"); + const accessKeyId = process.env[ENV_KEY]; + const secretAccessKey = process.env[ENV_SECRET]; + const sessionToken = process.env[ENV_SESSION]; + const expiry = process.env[ENV_EXPIRATION]; + const credentialScope = process.env[ENV_CREDENTIAL_SCOPE]; + const accountId = process.env[ENV_ACCOUNT_ID]; + if (accessKeyId && secretAccessKey) { + const credentials = { + accessKeyId, + secretAccessKey, + ...sessionToken && { sessionToken }, + ...expiry && { expiration: new Date(expiry) }, + ...credentialScope && { credentialScope }, + ...accountId && { accountId } + }; + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_ENV_VARS", "g"); + return credentials; + } + throw new import_property_provider.CredentialsProviderError("Unable to find environment variable credentials.", { logger: init?.logger }); +}, "fromEnv"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 1509: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkUrl = void 0; +const property_provider_1 = __nccwpck_require__(71238); +const LOOPBACK_CIDR_IPv4 = "127.0.0.0/8"; +const LOOPBACK_CIDR_IPv6 = "::1/128"; +const ECS_CONTAINER_HOST = "169.254.170.2"; +const EKS_CONTAINER_HOST_IPv4 = "169.254.170.23"; +const EKS_CONTAINER_HOST_IPv6 = "[fd00:ec2::23]"; +const checkUrl = (url, logger) => { + if (url.protocol === "https:") { + return; + } + if (url.hostname === ECS_CONTAINER_HOST || + url.hostname === EKS_CONTAINER_HOST_IPv4 || + url.hostname === EKS_CONTAINER_HOST_IPv6) { + return; + } + if (url.hostname.includes("[")) { + if (url.hostname === "[::1]" || url.hostname === "[0000:0000:0000:0000:0000:0000:0000:0001]") { + return; + } + } + else { + if (url.hostname === "localhost") { + return; + } + const ipComponents = url.hostname.split("."); + const inRange = (component) => { + const num = parseInt(component, 10); + return 0 <= num && num <= 255; + }; + if (ipComponents[0] === "127" && + inRange(ipComponents[1]) && + inRange(ipComponents[2]) && + inRange(ipComponents[3]) && + ipComponents.length === 4) { + return; + } + } + throw new property_provider_1.CredentialsProviderError(`URL not accepted. It must either be HTTPS or match one of the following: + - loopback CIDR 127.0.0.0/8 or [::1/128] + - ECS container host 169.254.170.2 + - EKS container host 169.254.170.23 or [fd00:ec2::23]`, { logger }); +}; +exports.checkUrl = checkUrl; + + +/***/ }), + +/***/ 68712: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromHttp = void 0; +const tslib_1 = __nccwpck_require__(61860); +const client_1 = __nccwpck_require__(5152); +const node_http_handler_1 = __nccwpck_require__(61279); +const property_provider_1 = __nccwpck_require__(71238); +const promises_1 = tslib_1.__importDefault(__nccwpck_require__(91943)); +const checkUrl_1 = __nccwpck_require__(1509); +const requestHelpers_1 = __nccwpck_require__(78914); +const retry_wrapper_1 = __nccwpck_require__(51122); +const AWS_CONTAINER_CREDENTIALS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"; +const DEFAULT_LINK_LOCAL_HOST = "http://169.254.170.2"; +const AWS_CONTAINER_CREDENTIALS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI"; +const AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE = "AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE"; +const AWS_CONTAINER_AUTHORIZATION_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN"; +const fromHttp = (options = {}) => { + options.logger?.debug("@aws-sdk/credential-provider-http - fromHttp"); + let host; + const relative = options.awsContainerCredentialsRelativeUri ?? process.env[AWS_CONTAINER_CREDENTIALS_RELATIVE_URI]; + const full = options.awsContainerCredentialsFullUri ?? process.env[AWS_CONTAINER_CREDENTIALS_FULL_URI]; + const token = options.awsContainerAuthorizationToken ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN]; + const tokenFile = options.awsContainerAuthorizationTokenFile ?? process.env[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE]; + const warn = options.logger?.constructor?.name === "NoOpLogger" || !options.logger ? console.warn : options.logger.warn; + if (relative && full) { + warn("@aws-sdk/credential-provider-http: " + + "you have set both awsContainerCredentialsRelativeUri and awsContainerCredentialsFullUri."); + warn("awsContainerCredentialsFullUri will take precedence."); + } + if (token && tokenFile) { + warn("@aws-sdk/credential-provider-http: " + + "you have set both awsContainerAuthorizationToken and awsContainerAuthorizationTokenFile."); + warn("awsContainerAuthorizationToken will take precedence."); + } + if (full) { + host = full; + } + else if (relative) { + host = `${DEFAULT_LINK_LOCAL_HOST}${relative}`; + } + else { + throw new property_provider_1.CredentialsProviderError(`No HTTP credential provider host provided. +Set AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.`, { logger: options.logger }); + } + const url = new URL(host); + (0, checkUrl_1.checkUrl)(url, options.logger); + const requestHandler = new node_http_handler_1.NodeHttpHandler({ + requestTimeout: options.timeout ?? 1000, + connectionTimeout: options.timeout ?? 1000, + }); + return (0, retry_wrapper_1.retryWrapper)(async () => { + const request = (0, requestHelpers_1.createGetRequest)(url); + if (token) { + request.headers.Authorization = token; + } + else if (tokenFile) { + request.headers.Authorization = (await promises_1.default.readFile(tokenFile)).toString(); + } + try { + const result = await requestHandler.handle(request); + return (0, requestHelpers_1.getCredentials)(result.response).then((creds) => (0, client_1.setCredentialFeature)(creds, "CREDENTIALS_HTTP", "z")); + } + catch (e) { + throw new property_provider_1.CredentialsProviderError(String(e), { logger: options.logger }); + } + }, options.maxRetries ?? 3, options.timeout ?? 1000); +}; +exports.fromHttp = fromHttp; + + +/***/ }), + +/***/ 78914: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createGetRequest = createGetRequest; +exports.getCredentials = getCredentials; +const property_provider_1 = __nccwpck_require__(71238); +const protocol_http_1 = __nccwpck_require__(72356); +const smithy_client_1 = __nccwpck_require__(61411); +const util_stream_1 = __nccwpck_require__(4252); +function createGetRequest(url) { + return new protocol_http_1.HttpRequest({ + protocol: url.protocol, + hostname: url.hostname, + port: Number(url.port), + path: url.pathname, + query: Array.from(url.searchParams.entries()).reduce((acc, [k, v]) => { + acc[k] = v; + return acc; + }, {}), + fragment: url.hash, + }); +} +async function getCredentials(response, logger) { + const stream = (0, util_stream_1.sdkStreamMixin)(response.body); + const str = await stream.transformToString(); + if (response.statusCode === 200) { + const parsed = JSON.parse(str); + if (typeof parsed.AccessKeyId !== "string" || + typeof parsed.SecretAccessKey !== "string" || + typeof parsed.Token !== "string" || + typeof parsed.Expiration !== "string") { + throw new property_provider_1.CredentialsProviderError("HTTP credential provider response not of the required format, an object matching: " + + "{ AccessKeyId: string, SecretAccessKey: string, Token: string, Expiration: string(rfc3339) }", { logger }); + } + return { + accessKeyId: parsed.AccessKeyId, + secretAccessKey: parsed.SecretAccessKey, + sessionToken: parsed.Token, + expiration: (0, smithy_client_1.parseRfc3339DateTime)(parsed.Expiration), + }; + } + if (response.statusCode >= 400 && response.statusCode < 500) { + let parsedBody = {}; + try { + parsedBody = JSON.parse(str); + } + catch (e) { } + throw Object.assign(new property_provider_1.CredentialsProviderError(`Server responded with status: ${response.statusCode}`, { logger }), { + Code: parsedBody.Code, + Message: parsedBody.Message, + }); + } + throw new property_provider_1.CredentialsProviderError(`Server responded with status: ${response.statusCode}`, { logger }); +} + + +/***/ }), + +/***/ 51122: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.retryWrapper = void 0; +const retryWrapper = (toRetry, maxRetries, delayMs) => { + return async () => { + for (let i = 0; i < maxRetries; ++i) { + try { + return await toRetry(); + } + catch (e) { + await new Promise((resolve) => setTimeout(resolve, delayMs)); + } + } + return await toRetry(); + }; +}; +exports.retryWrapper = retryWrapper; + + +/***/ }), + +/***/ 98605: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromHttp = void 0; +var fromHttp_1 = __nccwpck_require__(68712); +Object.defineProperty(exports, "fromHttp", ({ enumerable: true, get: function () { return fromHttp_1.fromHttp; } })); + + +/***/ }), + +/***/ 98250: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromIni: () => fromIni +}); +module.exports = __toCommonJS(index_exports); + +// src/fromIni.ts + + +// src/resolveProfileData.ts + + +// src/resolveAssumeRoleCredentials.ts + + +var import_shared_ini_file_loader = __nccwpck_require__(94964); + +// src/resolveCredentialSource.ts +var import_client = __nccwpck_require__(5152); +var import_property_provider = __nccwpck_require__(71238); +var resolveCredentialSource = /* @__PURE__ */ __name((credentialSource, profileName, logger) => { + const sourceProvidersMap = { + EcsContainer: /* @__PURE__ */ __name(async (options) => { + const { fromHttp } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(98605))); + const { fromContainerMetadata } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + logger?.debug("@aws-sdk/credential-provider-ini - credential_source is EcsContainer"); + return async () => (0, import_property_provider.chain)(fromHttp(options ?? {}), fromContainerMetadata(options))().then(setNamedProvider); + }, "EcsContainer"), + Ec2InstanceMetadata: /* @__PURE__ */ __name(async (options) => { + logger?.debug("@aws-sdk/credential-provider-ini - credential_source is Ec2InstanceMetadata"); + const { fromInstanceMetadata } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + return async () => fromInstanceMetadata(options)().then(setNamedProvider); + }, "Ec2InstanceMetadata"), + Environment: /* @__PURE__ */ __name(async (options) => { + logger?.debug("@aws-sdk/credential-provider-ini - credential_source is Environment"); + const { fromEnv } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(55606))); + return async () => fromEnv(options)().then(setNamedProvider); + }, "Environment") + }; + if (credentialSource in sourceProvidersMap) { + return sourceProvidersMap[credentialSource]; + } else { + throw new import_property_provider.CredentialsProviderError( + `Unsupported credential source in profile ${profileName}. Got ${credentialSource}, expected EcsContainer or Ec2InstanceMetadata or Environment.`, + { logger } + ); + } +}, "resolveCredentialSource"); +var setNamedProvider = /* @__PURE__ */ __name((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_NAMED_PROVIDER", "p"), "setNamedProvider"); + +// src/resolveAssumeRoleCredentials.ts +var isAssumeRoleProfile = /* @__PURE__ */ __name((arg, { profile = "default", logger } = {}) => { + return Boolean(arg) && typeof arg === "object" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1 && ["undefined", "string"].indexOf(typeof arg.external_id) > -1 && ["undefined", "string"].indexOf(typeof arg.mfa_serial) > -1 && (isAssumeRoleWithSourceProfile(arg, { profile, logger }) || isCredentialSourceProfile(arg, { profile, logger })); +}, "isAssumeRoleProfile"); +var isAssumeRoleWithSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger }) => { + const withSourceProfile = typeof arg.source_profile === "string" && typeof arg.credential_source === "undefined"; + if (withSourceProfile) { + logger?.debug?.(` ${profile} isAssumeRoleWithSourceProfile source_profile=${arg.source_profile}`); + } + return withSourceProfile; +}, "isAssumeRoleWithSourceProfile"); +var isCredentialSourceProfile = /* @__PURE__ */ __name((arg, { profile, logger }) => { + const withProviderProfile = typeof arg.credential_source === "string" && typeof arg.source_profile === "undefined"; + if (withProviderProfile) { + logger?.debug?.(` ${profile} isCredentialSourceProfile credential_source=${arg.credential_source}`); + } + return withProviderProfile; +}, "isCredentialSourceProfile"); +var resolveAssumeRoleCredentials = /* @__PURE__ */ __name(async (profileName, profiles, options, visitedProfiles = {}) => { + options.logger?.debug("@aws-sdk/credential-provider-ini - resolveAssumeRoleCredentials (STS)"); + const profileData = profiles[profileName]; + const { source_profile, region } = profileData; + if (!options.roleAssumer) { + const { getDefaultRoleAssumer } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(1136))); + options.roleAssumer = getDefaultRoleAssumer( + { + ...options.clientConfig, + credentialProviderLogger: options.logger, + parentClientConfig: { + ...options?.parentClientConfig, + region: region ?? options?.parentClientConfig?.region + } + }, + options.clientPlugins + ); + } + if (source_profile && source_profile in visitedProfiles) { + throw new import_property_provider.CredentialsProviderError( + `Detected a cycle attempting to resolve credentials for profile ${(0, import_shared_ini_file_loader.getProfileName)(options)}. Profiles visited: ` + Object.keys(visitedProfiles).join(", "), + { logger: options.logger } + ); + } + options.logger?.debug( + `@aws-sdk/credential-provider-ini - finding credential resolver using ${source_profile ? `source_profile=[${source_profile}]` : `profile=[${profileName}]`}` + ); + const sourceCredsProvider = source_profile ? resolveProfileData( + source_profile, + profiles, + options, + { + ...visitedProfiles, + [source_profile]: true + }, + isCredentialSourceWithoutRoleArn(profiles[source_profile] ?? {}) + ) : (await resolveCredentialSource(profileData.credential_source, profileName, options.logger)(options))(); + if (isCredentialSourceWithoutRoleArn(profileData)) { + return sourceCredsProvider.then((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o")); + } else { + const params = { + RoleArn: profileData.role_arn, + RoleSessionName: profileData.role_session_name || `aws-sdk-js-${Date.now()}`, + ExternalId: profileData.external_id, + DurationSeconds: parseInt(profileData.duration_seconds || "3600", 10) + }; + const { mfa_serial } = profileData; + if (mfa_serial) { + if (!options.mfaCodeProvider) { + throw new import_property_provider.CredentialsProviderError( + `Profile ${profileName} requires multi-factor authentication, but no MFA code callback was provided.`, + { logger: options.logger, tryNextLink: false } + ); + } + params.SerialNumber = mfa_serial; + params.TokenCode = await options.mfaCodeProvider(mfa_serial); + } + const sourceCreds = await sourceCredsProvider; + return options.roleAssumer(sourceCreds, params).then( + (creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SOURCE_PROFILE", "o") + ); + } +}, "resolveAssumeRoleCredentials"); +var isCredentialSourceWithoutRoleArn = /* @__PURE__ */ __name((section) => { + return !section.role_arn && !!section.credential_source; +}, "isCredentialSourceWithoutRoleArn"); + +// src/resolveProcessCredentials.ts + +var isProcessProfile = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.credential_process === "string", "isProcessProfile"); +var resolveProcessCredentials = /* @__PURE__ */ __name(async (options, profile) => Promise.resolve().then(() => __toESM(__nccwpck_require__(75360))).then( + ({ fromProcess }) => fromProcess({ + ...options, + profile + })().then((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_PROCESS", "v")) +), "resolveProcessCredentials"); + +// src/resolveSsoCredentials.ts + +var resolveSsoCredentials = /* @__PURE__ */ __name(async (profile, profileData, options = {}) => { + const { fromSSO } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(60998))); + return fromSSO({ + profile, + logger: options.logger, + parentClientConfig: options.parentClientConfig, + clientConfig: options.clientConfig + })().then((creds) => { + if (profileData.sso_session) { + return (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO", "r"); + } else { + return (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_SSO_LEGACY", "t"); + } + }); +}, "resolveSsoCredentials"); +var isSsoProfile = /* @__PURE__ */ __name((arg) => arg && (typeof arg.sso_start_url === "string" || typeof arg.sso_account_id === "string" || typeof arg.sso_session === "string" || typeof arg.sso_region === "string" || typeof arg.sso_role_name === "string"), "isSsoProfile"); + +// src/resolveStaticCredentials.ts + +var isStaticCredsProfile = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.aws_access_key_id === "string" && typeof arg.aws_secret_access_key === "string" && ["undefined", "string"].indexOf(typeof arg.aws_session_token) > -1 && ["undefined", "string"].indexOf(typeof arg.aws_account_id) > -1, "isStaticCredsProfile"); +var resolveStaticCredentials = /* @__PURE__ */ __name(async (profile, options) => { + options?.logger?.debug("@aws-sdk/credential-provider-ini - resolveStaticCredentials"); + const credentials = { + accessKeyId: profile.aws_access_key_id, + secretAccessKey: profile.aws_secret_access_key, + sessionToken: profile.aws_session_token, + ...profile.aws_credential_scope && { credentialScope: profile.aws_credential_scope }, + ...profile.aws_account_id && { accountId: profile.aws_account_id } + }; + return (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_PROFILE", "n"); +}, "resolveStaticCredentials"); + +// src/resolveWebIdentityCredentials.ts + +var isWebIdentityProfile = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.web_identity_token_file === "string" && typeof arg.role_arn === "string" && ["undefined", "string"].indexOf(typeof arg.role_session_name) > -1, "isWebIdentityProfile"); +var resolveWebIdentityCredentials = /* @__PURE__ */ __name(async (profile, options) => Promise.resolve().then(() => __toESM(__nccwpck_require__(29956))).then( + ({ fromTokenFile }) => fromTokenFile({ + webIdentityTokenFile: profile.web_identity_token_file, + roleArn: profile.role_arn, + roleSessionName: profile.role_session_name, + roleAssumerWithWebIdentity: options.roleAssumerWithWebIdentity, + logger: options.logger, + parentClientConfig: options.parentClientConfig + })().then((creds) => (0, import_client.setCredentialFeature)(creds, "CREDENTIALS_PROFILE_STS_WEB_ID_TOKEN", "q")) +), "resolveWebIdentityCredentials"); + +// src/resolveProfileData.ts +var resolveProfileData = /* @__PURE__ */ __name(async (profileName, profiles, options, visitedProfiles = {}, isAssumeRoleRecursiveCall = false) => { + const data = profiles[profileName]; + if (Object.keys(visitedProfiles).length > 0 && isStaticCredsProfile(data)) { + return resolveStaticCredentials(data, options); + } + if (isAssumeRoleRecursiveCall || isAssumeRoleProfile(data, { profile: profileName, logger: options.logger })) { + return resolveAssumeRoleCredentials(profileName, profiles, options, visitedProfiles); + } + if (isStaticCredsProfile(data)) { + return resolveStaticCredentials(data, options); + } + if (isWebIdentityProfile(data)) { + return resolveWebIdentityCredentials(data, options); + } + if (isProcessProfile(data)) { + return resolveProcessCredentials(options, profileName); + } + if (isSsoProfile(data)) { + return await resolveSsoCredentials(profileName, data, options); + } + throw new import_property_provider.CredentialsProviderError( + `Could not resolve credentials using profile: [${profileName}] in configuration/credentials file(s).`, + { logger: options.logger } + ); +}, "resolveProfileData"); + +// src/fromIni.ts +var fromIni = /* @__PURE__ */ __name((_init = {}) => async ({ callerClientConfig } = {}) => { + const init = { + ..._init, + parentClientConfig: { + ...callerClientConfig, + ..._init.parentClientConfig + } + }; + init.logger?.debug("@aws-sdk/credential-provider-ini - fromIni"); + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + return resolveProfileData( + (0, import_shared_ini_file_loader.getProfileName)({ + profile: _init.profile ?? callerClientConfig?.profile + }), + profiles, + init + ); +}, "fromIni"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 5861: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + credentialsTreatedAsExpired: () => credentialsTreatedAsExpired, + credentialsWillNeedRefresh: () => credentialsWillNeedRefresh, + defaultProvider: () => defaultProvider +}); +module.exports = __toCommonJS(index_exports); + +// src/defaultProvider.ts +var import_credential_provider_env = __nccwpck_require__(55606); + +var import_shared_ini_file_loader = __nccwpck_require__(94964); + +// src/remoteProvider.ts +var import_property_provider = __nccwpck_require__(71238); +var ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED"; +var remoteProvider = /* @__PURE__ */ __name(async (init) => { + const { ENV_CMDS_FULL_URI, ENV_CMDS_RELATIVE_URI, fromContainerMetadata, fromInstanceMetadata } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + if (process.env[ENV_CMDS_RELATIVE_URI] || process.env[ENV_CMDS_FULL_URI]) { + init.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromHttp/fromContainerMetadata"); + const { fromHttp } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(98605))); + return (0, import_property_provider.chain)(fromHttp(init), fromContainerMetadata(init)); + } + if (process.env[ENV_IMDS_DISABLED] && process.env[ENV_IMDS_DISABLED] !== "false") { + return async () => { + throw new import_property_provider.CredentialsProviderError("EC2 Instance Metadata Service access disabled", { logger: init.logger }); + }; + } + init.logger?.debug("@aws-sdk/credential-provider-node - remoteProvider::fromInstanceMetadata"); + return fromInstanceMetadata(init); +}, "remoteProvider"); + +// src/defaultProvider.ts +var multipleCredentialSourceWarningEmitted = false; +var defaultProvider = /* @__PURE__ */ __name((init = {}) => (0, import_property_provider.memoize)( + (0, import_property_provider.chain)( + async () => { + const profile = init.profile ?? process.env[import_shared_ini_file_loader.ENV_PROFILE]; + if (profile) { + const envStaticCredentialsAreSet = process.env[import_credential_provider_env.ENV_KEY] && process.env[import_credential_provider_env.ENV_SECRET]; + if (envStaticCredentialsAreSet) { + if (!multipleCredentialSourceWarningEmitted) { + const warnFn = init.logger?.warn && init.logger?.constructor?.name !== "NoOpLogger" ? init.logger.warn : console.warn; + warnFn( + `@aws-sdk/credential-provider-node - defaultProvider::fromEnv WARNING: + Multiple credential sources detected: + Both AWS_PROFILE and the pair AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY static credentials are set. + This SDK will proceed with the AWS_PROFILE value. + + However, a future version may change this behavior to prefer the ENV static credentials. + Please ensure that your environment only sets either the AWS_PROFILE or the + AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY pair. +` + ); + multipleCredentialSourceWarningEmitted = true; + } + } + throw new import_property_provider.CredentialsProviderError("AWS_PROFILE is set, skipping fromEnv provider.", { + logger: init.logger, + tryNextLink: true + }); + } + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromEnv"); + return (0, import_credential_provider_env.fromEnv)(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromSSO"); + const { ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoSession } = init; + if (!ssoStartUrl && !ssoAccountId && !ssoRegion && !ssoRoleName && !ssoSession) { + throw new import_property_provider.CredentialsProviderError( + "Skipping SSO provider in default chain (inputs do not include SSO fields).", + { logger: init.logger } + ); + } + const { fromSSO } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(60998))); + return fromSSO(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromIni"); + const { fromIni } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(98250))); + return fromIni(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromProcess"); + const { fromProcess } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(75360))); + return fromProcess(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::fromTokenFile"); + const { fromTokenFile } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(29956))); + return fromTokenFile(init)(); + }, + async () => { + init.logger?.debug("@aws-sdk/credential-provider-node - defaultProvider::remoteProvider"); + return (await remoteProvider(init))(); + }, + async () => { + throw new import_property_provider.CredentialsProviderError("Could not load credentials from any providers", { + tryNextLink: false, + logger: init.logger + }); + } + ), + credentialsTreatedAsExpired, + credentialsWillNeedRefresh +), "defaultProvider"); +var credentialsWillNeedRefresh = /* @__PURE__ */ __name((credentials) => credentials?.expiration !== void 0, "credentialsWillNeedRefresh"); +var credentialsTreatedAsExpired = /* @__PURE__ */ __name((credentials) => credentials?.expiration !== void 0 && credentials.expiration.getTime() - Date.now() < 3e5, "credentialsTreatedAsExpired"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 75360: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromProcess: () => fromProcess +}); +module.exports = __toCommonJS(index_exports); + +// src/fromProcess.ts +var import_shared_ini_file_loader = __nccwpck_require__(94964); + +// src/resolveProcessCredentials.ts +var import_property_provider = __nccwpck_require__(71238); +var import_child_process = __nccwpck_require__(35317); +var import_util = __nccwpck_require__(39023); + +// src/getValidatedProcessCredentials.ts +var import_client = __nccwpck_require__(5152); +var getValidatedProcessCredentials = /* @__PURE__ */ __name((profileName, data, profiles) => { + if (data.Version !== 1) { + throw Error(`Profile ${profileName} credential_process did not return Version 1.`); + } + if (data.AccessKeyId === void 0 || data.SecretAccessKey === void 0) { + throw Error(`Profile ${profileName} credential_process returned invalid credentials.`); + } + if (data.Expiration) { + const currentTime = /* @__PURE__ */ new Date(); + const expireTime = new Date(data.Expiration); + if (expireTime < currentTime) { + throw Error(`Profile ${profileName} credential_process returned expired credentials.`); + } + } + let accountId = data.AccountId; + if (!accountId && profiles?.[profileName]?.aws_account_id) { + accountId = profiles[profileName].aws_account_id; + } + const credentials = { + accessKeyId: data.AccessKeyId, + secretAccessKey: data.SecretAccessKey, + ...data.SessionToken && { sessionToken: data.SessionToken }, + ...data.Expiration && { expiration: new Date(data.Expiration) }, + ...data.CredentialScope && { credentialScope: data.CredentialScope }, + ...accountId && { accountId } + }; + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_PROCESS", "w"); + return credentials; +}, "getValidatedProcessCredentials"); + +// src/resolveProcessCredentials.ts +var resolveProcessCredentials = /* @__PURE__ */ __name(async (profileName, profiles, logger) => { + const profile = profiles[profileName]; + if (profiles[profileName]) { + const credentialProcess = profile["credential_process"]; + if (credentialProcess !== void 0) { + const execPromise = (0, import_util.promisify)(import_child_process.exec); + try { + const { stdout } = await execPromise(credentialProcess); + let data; + try { + data = JSON.parse(stdout.trim()); + } catch { + throw Error(`Profile ${profileName} credential_process returned invalid JSON.`); + } + return getValidatedProcessCredentials(profileName, data, profiles); + } catch (error) { + throw new import_property_provider.CredentialsProviderError(error.message, { logger }); + } + } else { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} did not contain credential_process.`, { logger }); + } + } else { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} could not be found in shared credentials file.`, { + logger + }); + } +}, "resolveProcessCredentials"); + +// src/fromProcess.ts +var fromProcess = /* @__PURE__ */ __name((init = {}) => async ({ callerClientConfig } = {}) => { + init.logger?.debug("@aws-sdk/credential-provider-process - fromProcess"); + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + return resolveProcessCredentials( + (0, import_shared_ini_file_loader.getProfileName)({ + profile: init.profile ?? callerClientConfig?.profile + }), + profiles, + init.logger + ); +}, "fromProcess"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 60998: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __esm = (fn, res) => function __init() { + return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; +}; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/loadSso.ts +var loadSso_exports = {}; +__export(loadSso_exports, { + GetRoleCredentialsCommand: () => import_client_sso.GetRoleCredentialsCommand, + SSOClient: () => import_client_sso.SSOClient +}); +var import_client_sso; +var init_loadSso = __esm({ + "src/loadSso.ts"() { + "use strict"; + import_client_sso = __nccwpck_require__(62054); + } +}); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromSSO: () => fromSSO, + isSsoProfile: () => isSsoProfile, + validateSsoProfile: () => validateSsoProfile +}); +module.exports = __toCommonJS(index_exports); + +// src/fromSSO.ts + + + +// src/isSsoProfile.ts +var isSsoProfile = /* @__PURE__ */ __name((arg) => arg && (typeof arg.sso_start_url === "string" || typeof arg.sso_account_id === "string" || typeof arg.sso_session === "string" || typeof arg.sso_region === "string" || typeof arg.sso_role_name === "string"), "isSsoProfile"); + +// src/resolveSSOCredentials.ts +var import_client = __nccwpck_require__(5152); +var import_token_providers = __nccwpck_require__(75433); +var import_property_provider = __nccwpck_require__(71238); +var import_shared_ini_file_loader = __nccwpck_require__(94964); +var SHOULD_FAIL_CREDENTIAL_CHAIN = false; +var resolveSSOCredentials = /* @__PURE__ */ __name(async ({ + ssoStartUrl, + ssoSession, + ssoAccountId, + ssoRegion, + ssoRoleName, + ssoClient, + clientConfig, + parentClientConfig, + profile, + logger +}) => { + let token; + const refreshMessage = `To refresh this SSO session run aws sso login with the corresponding profile.`; + if (ssoSession) { + try { + const _token = await (0, import_token_providers.fromSso)({ profile })(); + token = { + accessToken: _token.token, + expiresAt: new Date(_token.expiration).toISOString() + }; + } catch (e) { + throw new import_property_provider.CredentialsProviderError(e.message, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + } else { + try { + token = await (0, import_shared_ini_file_loader.getSSOTokenFromFile)(ssoStartUrl); + } catch (e) { + throw new import_property_provider.CredentialsProviderError(`The SSO session associated with this profile is invalid. ${refreshMessage}`, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + } + if (new Date(token.expiresAt).getTime() - Date.now() <= 0) { + throw new import_property_provider.CredentialsProviderError(`The SSO session associated with this profile has expired. ${refreshMessage}`, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + const { accessToken } = token; + const { SSOClient: SSOClient2, GetRoleCredentialsCommand: GetRoleCredentialsCommand2 } = await Promise.resolve().then(() => (init_loadSso(), loadSso_exports)); + const sso = ssoClient || new SSOClient2( + Object.assign({}, clientConfig ?? {}, { + logger: clientConfig?.logger ?? parentClientConfig?.logger, + region: clientConfig?.region ?? ssoRegion + }) + ); + let ssoResp; + try { + ssoResp = await sso.send( + new GetRoleCredentialsCommand2({ + accountId: ssoAccountId, + roleName: ssoRoleName, + accessToken + }) + ); + } catch (e) { + throw new import_property_provider.CredentialsProviderError(e, { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + const { + roleCredentials: { accessKeyId, secretAccessKey, sessionToken, expiration, credentialScope, accountId } = {} + } = ssoResp; + if (!accessKeyId || !secretAccessKey || !sessionToken || !expiration) { + throw new import_property_provider.CredentialsProviderError("SSO returns an invalid temporary credential.", { + tryNextLink: SHOULD_FAIL_CREDENTIAL_CHAIN, + logger + }); + } + const credentials = { + accessKeyId, + secretAccessKey, + sessionToken, + expiration: new Date(expiration), + ...credentialScope && { credentialScope }, + ...accountId && { accountId } + }; + if (ssoSession) { + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_SSO", "s"); + } else { + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_SSO_LEGACY", "u"); + } + return credentials; +}, "resolveSSOCredentials"); + +// src/validateSsoProfile.ts + +var validateSsoProfile = /* @__PURE__ */ __name((profile, logger) => { + const { sso_start_url, sso_account_id, sso_region, sso_role_name } = profile; + if (!sso_start_url || !sso_account_id || !sso_region || !sso_role_name) { + throw new import_property_provider.CredentialsProviderError( + `Profile is configured with invalid SSO credentials. Required parameters "sso_account_id", "sso_region", "sso_role_name", "sso_start_url". Got ${Object.keys(profile).join( + ", " + )} +Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html`, + { tryNextLink: false, logger } + ); + } + return profile; +}, "validateSsoProfile"); + +// src/fromSSO.ts +var fromSSO = /* @__PURE__ */ __name((init = {}) => async ({ callerClientConfig } = {}) => { + init.logger?.debug("@aws-sdk/credential-provider-sso - fromSSO"); + const { ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoSession } = init; + const { ssoClient } = init; + const profileName = (0, import_shared_ini_file_loader.getProfileName)({ + profile: init.profile ?? callerClientConfig?.profile + }); + if (!ssoStartUrl && !ssoAccountId && !ssoRegion && !ssoRoleName && !ssoSession) { + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + const profile = profiles[profileName]; + if (!profile) { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} was not found.`, { logger: init.logger }); + } + if (!isSsoProfile(profile)) { + throw new import_property_provider.CredentialsProviderError(`Profile ${profileName} is not configured with SSO credentials.`, { + logger: init.logger + }); + } + if (profile?.sso_session) { + const ssoSessions = await (0, import_shared_ini_file_loader.loadSsoSessionData)(init); + const session = ssoSessions[profile.sso_session]; + const conflictMsg = ` configurations in profile ${profileName} and sso-session ${profile.sso_session}`; + if (ssoRegion && ssoRegion !== session.sso_region) { + throw new import_property_provider.CredentialsProviderError(`Conflicting SSO region` + conflictMsg, { + tryNextLink: false, + logger: init.logger + }); + } + if (ssoStartUrl && ssoStartUrl !== session.sso_start_url) { + throw new import_property_provider.CredentialsProviderError(`Conflicting SSO start_url` + conflictMsg, { + tryNextLink: false, + logger: init.logger + }); + } + profile.sso_region = session.sso_region; + profile.sso_start_url = session.sso_start_url; + } + const { sso_start_url, sso_account_id, sso_region, sso_role_name, sso_session } = validateSsoProfile( + profile, + init.logger + ); + return resolveSSOCredentials({ + ssoStartUrl: sso_start_url, + ssoSession: sso_session, + ssoAccountId: sso_account_id, + ssoRegion: sso_region, + ssoRoleName: sso_role_name, + ssoClient, + clientConfig: init.clientConfig, + parentClientConfig: init.parentClientConfig, + profile: profileName + }); + } else if (!ssoStartUrl || !ssoAccountId || !ssoRegion || !ssoRoleName) { + throw new import_property_provider.CredentialsProviderError( + 'Incomplete configuration. The fromSSO() argument hash must include "ssoStartUrl", "ssoAccountId", "ssoRegion", "ssoRoleName"', + { tryNextLink: false, logger: init.logger } + ); + } else { + return resolveSSOCredentials({ + ssoStartUrl, + ssoSession, + ssoAccountId, + ssoRegion, + ssoRoleName, + ssoClient, + clientConfig: init.clientConfig, + parentClientConfig: init.parentClientConfig, + profile: profileName + }); + } +}, "fromSSO"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 88079: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromTokenFile = void 0; +const client_1 = __nccwpck_require__(5152); +const property_provider_1 = __nccwpck_require__(71238); +const fs_1 = __nccwpck_require__(79896); +const fromWebToken_1 = __nccwpck_require__(34453); +const ENV_TOKEN_FILE = "AWS_WEB_IDENTITY_TOKEN_FILE"; +const ENV_ROLE_ARN = "AWS_ROLE_ARN"; +const ENV_ROLE_SESSION_NAME = "AWS_ROLE_SESSION_NAME"; +const fromTokenFile = (init = {}) => async () => { + init.logger?.debug("@aws-sdk/credential-provider-web-identity - fromTokenFile"); + const webIdentityTokenFile = init?.webIdentityTokenFile ?? process.env[ENV_TOKEN_FILE]; + const roleArn = init?.roleArn ?? process.env[ENV_ROLE_ARN]; + const roleSessionName = init?.roleSessionName ?? process.env[ENV_ROLE_SESSION_NAME]; + if (!webIdentityTokenFile || !roleArn) { + throw new property_provider_1.CredentialsProviderError("Web identity configuration not specified", { + logger: init.logger, + }); + } + const credentials = await (0, fromWebToken_1.fromWebToken)({ + ...init, + webIdentityToken: (0, fs_1.readFileSync)(webIdentityTokenFile, { encoding: "ascii" }), + roleArn, + roleSessionName, + })(); + if (webIdentityTokenFile === process.env[ENV_TOKEN_FILE]) { + (0, client_1.setCredentialFeature)(credentials, "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN", "h"); + } + return credentials; +}; +exports.fromTokenFile = fromTokenFile; + + +/***/ }), + +/***/ 34453: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromWebToken = void 0; +const fromWebToken = (init) => async (awsIdentityProperties) => { + init.logger?.debug("@aws-sdk/credential-provider-web-identity - fromWebToken"); + const { roleArn, roleSessionName, webIdentityToken, providerId, policyArns, policy, durationSeconds } = init; + let { roleAssumerWithWebIdentity } = init; + if (!roleAssumerWithWebIdentity) { + const { getDefaultRoleAssumerWithWebIdentity } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(1136))); + roleAssumerWithWebIdentity = getDefaultRoleAssumerWithWebIdentity({ + ...init.clientConfig, + credentialProviderLogger: init.logger, + parentClientConfig: { + ...awsIdentityProperties?.callerClientConfig, + ...init.parentClientConfig, + }, + }, init.clientPlugins); + } + return roleAssumerWithWebIdentity({ + RoleArn: roleArn, + RoleSessionName: roleSessionName ?? `aws-sdk-js-session-${Date.now()}`, + WebIdentityToken: webIdentityToken, + ProviderId: providerId, + PolicyArns: policyArns, + Policy: policy, + DurationSeconds: durationSeconds, + }); +}; +exports.fromWebToken = fromWebToken; + + +/***/ }), + +/***/ 29956: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +module.exports = __toCommonJS(index_exports); +__reExport(index_exports, __nccwpck_require__(88079), module.exports); +__reExport(index_exports, __nccwpck_require__(34453), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 26518: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_DISABLE_MULTIREGION_ACCESS_POINT_CONFIG_OPTIONS: () => NODE_DISABLE_MULTIREGION_ACCESS_POINT_CONFIG_OPTIONS, + NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME: () => NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME, + NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME: () => NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME, + NODE_USE_ARN_REGION_CONFIG_OPTIONS: () => NODE_USE_ARN_REGION_CONFIG_OPTIONS, + NODE_USE_ARN_REGION_ENV_NAME: () => NODE_USE_ARN_REGION_ENV_NAME, + NODE_USE_ARN_REGION_INI_NAME: () => NODE_USE_ARN_REGION_INI_NAME, + bucketEndpointMiddleware: () => bucketEndpointMiddleware, + bucketEndpointMiddlewareOptions: () => bucketEndpointMiddlewareOptions, + bucketHostname: () => bucketHostname, + getArnResources: () => getArnResources, + getBucketEndpointPlugin: () => getBucketEndpointPlugin, + getSuffixForArnEndpoint: () => getSuffixForArnEndpoint, + resolveBucketEndpointConfig: () => resolveBucketEndpointConfig, + validateAccountId: () => validateAccountId, + validateDNSHostLabel: () => validateDNSHostLabel, + validateNoDualstack: () => validateNoDualstack, + validateNoFIPS: () => validateNoFIPS, + validateOutpostService: () => validateOutpostService, + validatePartition: () => validatePartition, + validateRegion: () => validateRegion +}); +module.exports = __toCommonJS(index_exports); + +// src/NodeDisableMultiregionAccessPointConfigOptions.ts +var import_util_config_provider = __nccwpck_require__(56716); +var NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME = "AWS_S3_DISABLE_MULTIREGION_ACCESS_POINTS"; +var NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME = "s3_disable_multiregion_access_points"; +var NODE_DISABLE_MULTIREGION_ACCESS_POINT_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => (0, import_util_config_provider.booleanSelector)(env, NODE_DISABLE_MULTIREGION_ACCESS_POINT_ENV_NAME, import_util_config_provider.SelectorType.ENV), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => (0, import_util_config_provider.booleanSelector)(profile, NODE_DISABLE_MULTIREGION_ACCESS_POINT_INI_NAME, import_util_config_provider.SelectorType.CONFIG), "configFileSelector"), + default: false +}; + +// src/NodeUseArnRegionConfigOptions.ts + +var NODE_USE_ARN_REGION_ENV_NAME = "AWS_S3_USE_ARN_REGION"; +var NODE_USE_ARN_REGION_INI_NAME = "s3_use_arn_region"; +var NODE_USE_ARN_REGION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => (0, import_util_config_provider.booleanSelector)(env, NODE_USE_ARN_REGION_ENV_NAME, import_util_config_provider.SelectorType.ENV), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => (0, import_util_config_provider.booleanSelector)(profile, NODE_USE_ARN_REGION_INI_NAME, import_util_config_provider.SelectorType.CONFIG), "configFileSelector"), + /** + * useArnRegion has specific behavior when undefined instead of false. + * We therefore use undefined as the default value instead of false. + */ + default: void 0 +}; + +// src/bucketEndpointMiddleware.ts +var import_util_arn_parser = __nccwpck_require__(56369); +var import_protocol_http = __nccwpck_require__(72356); + +// src/bucketHostnameUtils.ts +var DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/; +var IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/; +var DOTS_PATTERN = /\.\./; +var DOT_PATTERN = /\./; +var S3_HOSTNAME_PATTERN = /^(.+\.)?s3(-fips)?(\.dualstack)?[.-]([a-z0-9-]+)\./; +var S3_US_EAST_1_ALTNAME_PATTERN = /^s3(-external-1)?\.amazonaws\.com$/; +var AWS_PARTITION_SUFFIX = "amazonaws.com"; +var isBucketNameOptions = /* @__PURE__ */ __name((options) => typeof options.bucketName === "string", "isBucketNameOptions"); +var isDnsCompatibleBucketName = /* @__PURE__ */ __name((bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName), "isDnsCompatibleBucketName"); +var getRegionalSuffix = /* @__PURE__ */ __name((hostname) => { + const parts = hostname.match(S3_HOSTNAME_PATTERN); + return [parts[4], hostname.replace(new RegExp(`^${parts[0]}`), "")]; +}, "getRegionalSuffix"); +var getSuffix = /* @__PURE__ */ __name((hostname) => S3_US_EAST_1_ALTNAME_PATTERN.test(hostname) ? ["us-east-1", AWS_PARTITION_SUFFIX] : getRegionalSuffix(hostname), "getSuffix"); +var getSuffixForArnEndpoint = /* @__PURE__ */ __name((hostname) => S3_US_EAST_1_ALTNAME_PATTERN.test(hostname) ? [hostname.replace(`.${AWS_PARTITION_SUFFIX}`, ""), AWS_PARTITION_SUFFIX] : getRegionalSuffix(hostname), "getSuffixForArnEndpoint"); +var validateArnEndpointOptions = /* @__PURE__ */ __name((options) => { + if (options.pathStyleEndpoint) { + throw new Error("Path-style S3 endpoint is not supported when bucket is an ARN"); + } + if (options.accelerateEndpoint) { + throw new Error("Accelerate endpoint is not supported when bucket is an ARN"); + } + if (!options.tlsCompatible) { + throw new Error("HTTPS is required when bucket is an ARN"); + } +}, "validateArnEndpointOptions"); +var validateService = /* @__PURE__ */ __name((service) => { + if (service !== "s3" && service !== "s3-outposts" && service !== "s3-object-lambda") { + throw new Error("Expect 's3' or 's3-outposts' or 's3-object-lambda' in ARN service component"); + } +}, "validateService"); +var validateS3Service = /* @__PURE__ */ __name((service) => { + if (service !== "s3") { + throw new Error("Expect 's3' in Accesspoint ARN service component"); + } +}, "validateS3Service"); +var validateOutpostService = /* @__PURE__ */ __name((service) => { + if (service !== "s3-outposts") { + throw new Error("Expect 's3-posts' in Outpost ARN service component"); + } +}, "validateOutpostService"); +var validatePartition = /* @__PURE__ */ __name((partition, options) => { + if (partition !== options.clientPartition) { + throw new Error(`Partition in ARN is incompatible, got "${partition}" but expected "${options.clientPartition}"`); + } +}, "validatePartition"); +var validateRegion = /* @__PURE__ */ __name((region, options) => { +}, "validateRegion"); +var validateRegionalClient = /* @__PURE__ */ __name((region) => { + if (["s3-external-1", "aws-global"].includes(region)) { + throw new Error(`Client region ${region} is not regional`); + } +}, "validateRegionalClient"); +var validateAccountId = /* @__PURE__ */ __name((accountId) => { + if (!/[0-9]{12}/.exec(accountId)) { + throw new Error("Access point ARN accountID does not match regex '[0-9]{12}'"); + } +}, "validateAccountId"); +var validateDNSHostLabel = /* @__PURE__ */ __name((label, options = { tlsCompatible: true }) => { + if (label.length >= 64 || !/^[a-z0-9][a-z0-9.-]*[a-z0-9]$/.test(label) || /(\d+\.){3}\d+/.test(label) || /[.-]{2}/.test(label) || options?.tlsCompatible && DOT_PATTERN.test(label)) { + throw new Error(`Invalid DNS label ${label}`); + } +}, "validateDNSHostLabel"); +var validateCustomEndpoint = /* @__PURE__ */ __name((options) => { + if (options.isCustomEndpoint) { + if (options.dualstackEndpoint) throw new Error("Dualstack endpoint is not supported with custom endpoint"); + if (options.accelerateEndpoint) throw new Error("Accelerate endpoint is not supported with custom endpoint"); + } +}, "validateCustomEndpoint"); +var getArnResources = /* @__PURE__ */ __name((resource) => { + const delimiter = resource.includes(":") ? ":" : "/"; + const [resourceType, ...rest] = resource.split(delimiter); + if (resourceType === "accesspoint") { + if (rest.length !== 1 || rest[0] === "") { + throw new Error(`Access Point ARN should have one resource accesspoint${delimiter}{accesspointname}`); + } + return { accesspointName: rest[0] }; + } else if (resourceType === "outpost") { + if (!rest[0] || rest[1] !== "accesspoint" || !rest[2] || rest.length !== 3) { + throw new Error( + `Outpost ARN should have resource outpost${delimiter}{outpostId}${delimiter}accesspoint${delimiter}{accesspointName}` + ); + } + const [outpostId, _, accesspointName] = rest; + return { outpostId, accesspointName }; + } else { + throw new Error(`ARN resource should begin with 'accesspoint${delimiter}' or 'outpost${delimiter}'`); + } +}, "getArnResources"); +var validateNoDualstack = /* @__PURE__ */ __name((dualstackEndpoint) => { +}, "validateNoDualstack"); +var validateNoFIPS = /* @__PURE__ */ __name((useFipsEndpoint) => { + if (useFipsEndpoint) throw new Error(`FIPS region is not supported with Outpost.`); +}, "validateNoFIPS"); +var validateMrapAlias = /* @__PURE__ */ __name((name) => { + try { + name.split(".").forEach((label) => { + validateDNSHostLabel(label); + }); + } catch (e) { + throw new Error(`"${name}" is not a DNS compatible name.`); + } +}, "validateMrapAlias"); + +// src/bucketHostname.ts +var bucketHostname = /* @__PURE__ */ __name((options) => { + validateCustomEndpoint(options); + return isBucketNameOptions(options) ? ( + // Construct endpoint when bucketName is a string referring to a bucket name + getEndpointFromBucketName(options) + ) : ( + // Construct endpoint when bucketName is an ARN referring to an S3 resource like Access Point + getEndpointFromArn(options) + ); +}, "bucketHostname"); +var getEndpointFromBucketName = /* @__PURE__ */ __name(({ + accelerateEndpoint = false, + clientRegion: region, + baseHostname, + bucketName, + dualstackEndpoint = false, + fipsEndpoint = false, + pathStyleEndpoint = false, + tlsCompatible = true, + isCustomEndpoint = false +}) => { + const [clientRegion, hostnameSuffix] = isCustomEndpoint ? [region, baseHostname] : getSuffix(baseHostname); + if (pathStyleEndpoint || !isDnsCompatibleBucketName(bucketName) || tlsCompatible && DOT_PATTERN.test(bucketName)) { + return { + bucketEndpoint: false, + hostname: dualstackEndpoint ? `s3.dualstack.${clientRegion}.${hostnameSuffix}` : baseHostname + }; + } + if (accelerateEndpoint) { + baseHostname = `s3-accelerate${dualstackEndpoint ? ".dualstack" : ""}.${hostnameSuffix}`; + } else if (dualstackEndpoint) { + baseHostname = `s3.dualstack.${clientRegion}.${hostnameSuffix}`; + } + return { + bucketEndpoint: true, + hostname: `${bucketName}.${baseHostname}` + }; +}, "getEndpointFromBucketName"); +var getEndpointFromArn = /* @__PURE__ */ __name((options) => { + const { isCustomEndpoint, baseHostname, clientRegion } = options; + const hostnameSuffix = isCustomEndpoint ? baseHostname : getSuffixForArnEndpoint(baseHostname)[1]; + const { + pathStyleEndpoint, + accelerateEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + bucketName, + clientPartition = "aws" + } = options; + validateArnEndpointOptions({ pathStyleEndpoint, accelerateEndpoint, tlsCompatible }); + const { service, partition, accountId, region, resource } = bucketName; + validateService(service); + validatePartition(partition, { clientPartition }); + validateAccountId(accountId); + const { accesspointName, outpostId } = getArnResources(resource); + if (service === "s3-object-lambda") { + return getEndpointFromObjectLambdaArn({ ...options, tlsCompatible, bucketName, accesspointName, hostnameSuffix }); + } + if (region === "") { + return getEndpointFromMRAPArn({ ...options, clientRegion, mrapAlias: accesspointName, hostnameSuffix }); + } + if (outpostId) { + return getEndpointFromOutpostArn({ ...options, clientRegion, outpostId, accesspointName, hostnameSuffix }); + } + return getEndpointFromAccessPointArn({ ...options, clientRegion, accesspointName, hostnameSuffix }); +}, "getEndpointFromArn"); +var getEndpointFromObjectLambdaArn = /* @__PURE__ */ __name(({ + dualstackEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + accesspointName, + bucketName, + hostnameSuffix +}) => { + const { accountId, region, service } = bucketName; + validateRegionalClient(clientRegion); + const DNSHostLabel = `${accesspointName}-${accountId}`; + validateDNSHostLabel(DNSHostLabel, { tlsCompatible }); + const endpointRegion = useArnRegion ? region : clientRegion; + const signingRegion = useArnRegion ? region : clientSigningRegion; + return { + bucketEndpoint: true, + hostname: `${DNSHostLabel}.${service}${fipsEndpoint ? "-fips" : ""}.${endpointRegion}.${hostnameSuffix}`, + signingRegion, + signingService: service + }; +}, "getEndpointFromObjectLambdaArn"); +var getEndpointFromMRAPArn = /* @__PURE__ */ __name(({ + disableMultiregionAccessPoints, + dualstackEndpoint = false, + isCustomEndpoint, + mrapAlias, + hostnameSuffix +}) => { + if (disableMultiregionAccessPoints === true) { + throw new Error("SDK is attempting to use a MRAP ARN. Please enable to feature."); + } + validateMrapAlias(mrapAlias); + return { + bucketEndpoint: true, + hostname: `${mrapAlias}${isCustomEndpoint ? "" : `.accesspoint.s3-global`}.${hostnameSuffix}`, + signingRegion: "*" + }; +}, "getEndpointFromMRAPArn"); +var getEndpointFromOutpostArn = /* @__PURE__ */ __name(({ + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + bucketName, + outpostId, + dualstackEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + accesspointName, + isCustomEndpoint, + hostnameSuffix +}) => { + validateRegionalClient(clientRegion); + const DNSHostLabel = `${accesspointName}-${bucketName.accountId}`; + validateDNSHostLabel(DNSHostLabel, { tlsCompatible }); + const endpointRegion = useArnRegion ? bucketName.region : clientRegion; + const signingRegion = useArnRegion ? bucketName.region : clientSigningRegion; + validateOutpostService(bucketName.service); + validateDNSHostLabel(outpostId, { tlsCompatible }); + validateNoFIPS(fipsEndpoint); + const hostnamePrefix = `${DNSHostLabel}.${outpostId}`; + return { + bucketEndpoint: true, + hostname: `${hostnamePrefix}${isCustomEndpoint ? "" : `.s3-outposts.${endpointRegion}`}.${hostnameSuffix}`, + signingRegion, + signingService: "s3-outposts" + }; +}, "getEndpointFromOutpostArn"); +var getEndpointFromAccessPointArn = /* @__PURE__ */ __name(({ + useArnRegion, + clientRegion, + clientSigningRegion = clientRegion, + bucketName, + dualstackEndpoint = false, + fipsEndpoint = false, + tlsCompatible = true, + accesspointName, + isCustomEndpoint, + hostnameSuffix +}) => { + validateRegionalClient(clientRegion); + const hostnamePrefix = `${accesspointName}-${bucketName.accountId}`; + validateDNSHostLabel(hostnamePrefix, { tlsCompatible }); + const endpointRegion = useArnRegion ? bucketName.region : clientRegion; + const signingRegion = useArnRegion ? bucketName.region : clientSigningRegion; + validateS3Service(bucketName.service); + return { + bucketEndpoint: true, + hostname: `${hostnamePrefix}${isCustomEndpoint ? "" : `.s3-accesspoint${fipsEndpoint ? "-fips" : ""}${dualstackEndpoint ? ".dualstack" : ""}.${endpointRegion}`}.${hostnameSuffix}`, + signingRegion + }; +}, "getEndpointFromAccessPointArn"); + +// src/bucketEndpointMiddleware.ts +var bucketEndpointMiddleware = /* @__PURE__ */ __name((options) => (next, context) => async (args) => { + const { Bucket: bucketName } = args.input; + let replaceBucketInPath = options.bucketEndpoint; + const request = args.request; + if (import_protocol_http.HttpRequest.isInstance(request)) { + if (options.bucketEndpoint) { + request.hostname = bucketName; + } else if ((0, import_util_arn_parser.validate)(bucketName)) { + const bucketArn = (0, import_util_arn_parser.parse)(bucketName); + const clientRegion = await options.region(); + const useDualstackEndpoint = await options.useDualstackEndpoint(); + const useFipsEndpoint = await options.useFipsEndpoint(); + const { partition, signingRegion = clientRegion } = await options.regionInfoProvider(clientRegion, { useDualstackEndpoint, useFipsEndpoint }) || {}; + const useArnRegion = await options.useArnRegion(); + const { + hostname, + bucketEndpoint, + signingRegion: modifiedSigningRegion, + signingService + } = bucketHostname({ + bucketName: bucketArn, + baseHostname: request.hostname, + accelerateEndpoint: options.useAccelerateEndpoint, + dualstackEndpoint: useDualstackEndpoint, + fipsEndpoint: useFipsEndpoint, + pathStyleEndpoint: options.forcePathStyle, + tlsCompatible: request.protocol === "https:", + useArnRegion, + clientPartition: partition, + clientSigningRegion: signingRegion, + clientRegion, + isCustomEndpoint: options.isCustomEndpoint, + disableMultiregionAccessPoints: await options.disableMultiregionAccessPoints() + }); + if (modifiedSigningRegion && modifiedSigningRegion !== signingRegion) { + context["signing_region"] = modifiedSigningRegion; + } + if (signingService && signingService !== "s3") { + context["signing_service"] = signingService; + } + request.hostname = hostname; + replaceBucketInPath = bucketEndpoint; + } else { + const clientRegion = await options.region(); + const dualstackEndpoint = await options.useDualstackEndpoint(); + const fipsEndpoint = await options.useFipsEndpoint(); + const { hostname, bucketEndpoint } = bucketHostname({ + bucketName, + clientRegion, + baseHostname: request.hostname, + accelerateEndpoint: options.useAccelerateEndpoint, + dualstackEndpoint, + fipsEndpoint, + pathStyleEndpoint: options.forcePathStyle, + tlsCompatible: request.protocol === "https:", + isCustomEndpoint: options.isCustomEndpoint + }); + request.hostname = hostname; + replaceBucketInPath = bucketEndpoint; + } + if (replaceBucketInPath) { + request.path = request.path.replace(/^(\/)?[^\/]+/, ""); + if (request.path === "") { + request.path = "/"; + } + } + } + return next({ ...args, request }); +}, "bucketEndpointMiddleware"); +var bucketEndpointMiddlewareOptions = { + tags: ["BUCKET_ENDPOINT"], + name: "bucketEndpointMiddleware", + relation: "before", + toMiddleware: "hostHeaderMiddleware", + override: true +}; +var getBucketEndpointPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo(bucketEndpointMiddleware(options), bucketEndpointMiddlewareOptions); + }, "applyToStack") +}), "getBucketEndpointPlugin"); + +// src/configurations.ts +function resolveBucketEndpointConfig(input) { + const { + bucketEndpoint = false, + forcePathStyle = false, + useAccelerateEndpoint = false, + // useArnRegion has specific behavior when undefined instead of false. + useArnRegion, + disableMultiregionAccessPoints = false + } = input; + return Object.assign(input, { + bucketEndpoint, + forcePathStyle, + useAccelerateEndpoint, + useArnRegion: typeof useArnRegion === "function" ? useArnRegion : () => Promise.resolve(useArnRegion), + disableMultiregionAccessPoints: typeof disableMultiregionAccessPoints === "function" ? disableMultiregionAccessPoints : () => Promise.resolve(disableMultiregionAccessPoints) + }); +} +__name(resolveBucketEndpointConfig, "resolveBucketEndpointConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 84745: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + addExpectContinueMiddleware: () => addExpectContinueMiddleware, + addExpectContinueMiddlewareOptions: () => addExpectContinueMiddlewareOptions, + getAddExpectContinuePlugin: () => getAddExpectContinuePlugin +}); +module.exports = __toCommonJS(index_exports); +var import_protocol_http = __nccwpck_require__(72356); +function addExpectContinueMiddleware(options) { + return (next) => async (args) => { + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request) && request.body && options.runtime === "node") { + if (options.requestHandler?.constructor?.name !== "FetchHttpHandler") { + request.headers = { + ...request.headers, + Expect: "100-continue" + }; + } + } + return next({ + ...args, + request + }); + }; +} +__name(addExpectContinueMiddleware, "addExpectContinueMiddleware"); +var addExpectContinueMiddlewareOptions = { + step: "build", + tags: ["SET_EXPECT_HEADER", "EXPECT_HEADER"], + name: "addExpectContinueMiddleware", + override: true +}; +var getAddExpectContinuePlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(addExpectContinueMiddleware(options), addExpectContinueMiddlewareOptions); + }, "applyToStack") +}), "getAddExpectContinuePlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 23321: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getCrc32ChecksumAlgorithmFunction = void 0; +const tslib_1 = __nccwpck_require__(61860); +const crc32_1 = __nccwpck_require__(62110); +const util_1 = __nccwpck_require__(95667); +const zlib = tslib_1.__importStar(__nccwpck_require__(43106)); +class NodeCrc32 { + checksum = 0; + update(data) { + this.checksum = zlib.crc32(data, this.checksum); + } + async digest() { + return (0, util_1.numToUint8)(this.checksum); + } + reset() { + this.checksum = 0; + } +} +const getCrc32ChecksumAlgorithmFunction = () => { + if (typeof zlib.crc32 === "undefined") { + return crc32_1.AwsCrc32; + } + return NodeCrc32; +}; +exports.getCrc32ChecksumAlgorithmFunction = getCrc32ChecksumAlgorithmFunction; + + +/***/ }), + +/***/ 29836: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + CONFIG_REQUEST_CHECKSUM_CALCULATION: () => CONFIG_REQUEST_CHECKSUM_CALCULATION, + CONFIG_RESPONSE_CHECKSUM_VALIDATION: () => CONFIG_RESPONSE_CHECKSUM_VALIDATION, + ChecksumAlgorithm: () => ChecksumAlgorithm, + ChecksumLocation: () => ChecksumLocation, + DEFAULT_CHECKSUM_ALGORITHM: () => DEFAULT_CHECKSUM_ALGORITHM, + DEFAULT_REQUEST_CHECKSUM_CALCULATION: () => DEFAULT_REQUEST_CHECKSUM_CALCULATION, + DEFAULT_RESPONSE_CHECKSUM_VALIDATION: () => DEFAULT_RESPONSE_CHECKSUM_VALIDATION, + ENV_REQUEST_CHECKSUM_CALCULATION: () => ENV_REQUEST_CHECKSUM_CALCULATION, + ENV_RESPONSE_CHECKSUM_VALIDATION: () => ENV_RESPONSE_CHECKSUM_VALIDATION, + NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS: () => NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS, + NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS: () => NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS, + RequestChecksumCalculation: () => RequestChecksumCalculation, + ResponseChecksumValidation: () => ResponseChecksumValidation, + crc64NvmeCrtContainer: () => crc64NvmeCrtContainer, + flexibleChecksumsMiddleware: () => flexibleChecksumsMiddleware, + flexibleChecksumsMiddlewareOptions: () => flexibleChecksumsMiddlewareOptions, + getFlexibleChecksumsPlugin: () => getFlexibleChecksumsPlugin, + resolveFlexibleChecksumsConfig: () => resolveFlexibleChecksumsConfig +}); +module.exports = __toCommonJS(index_exports); + +// src/constants.ts +var RequestChecksumCalculation = { + /** + * When set, a checksum will be calculated for all request payloads of operations + * modeled with the {@link httpChecksum} trait where `requestChecksumRequired` is `true` + * AND/OR a `requestAlgorithmMember` is modeled. + * {@link https://smithy.io/2.0/aws/aws-core.html#aws-protocols-httpchecksum-trait httpChecksum} + */ + WHEN_SUPPORTED: "WHEN_SUPPORTED", + /** + * When set, a checksum will only be calculated for request payloads of operations + * modeled with the {@link httpChecksum} trait where `requestChecksumRequired` is `true` + * OR where a `requestAlgorithmMember` is modeled and the user sets it. + * {@link https://smithy.io/2.0/aws/aws-core.html#aws-protocols-httpchecksum-trait httpChecksum} + */ + WHEN_REQUIRED: "WHEN_REQUIRED" +}; +var DEFAULT_REQUEST_CHECKSUM_CALCULATION = RequestChecksumCalculation.WHEN_SUPPORTED; +var ResponseChecksumValidation = { + /** + * When set, checksum validation MUST be performed on all response payloads of operations + * modeled with the {@link httpChecksum} trait where `responseAlgorithms` is modeled, + * except when no modeled checksum algorithms are supported by an SDK. + * {@link https://smithy.io/2.0/aws/aws-core.html#aws-protocols-httpchecksum-trait httpChecksum} + */ + WHEN_SUPPORTED: "WHEN_SUPPORTED", + /** + * When set, checksum validation MUST NOT be performed on response payloads of operations UNLESS + * the SDK supports the modeled checksum algorithms AND the user has set the `requestValidationModeMember` to `ENABLED`. + * It is currently impossible to model an operation as requiring a response checksum, + * but this setting leaves the door open for future updates. + */ + WHEN_REQUIRED: "WHEN_REQUIRED" +}; +var DEFAULT_RESPONSE_CHECKSUM_VALIDATION = RequestChecksumCalculation.WHEN_SUPPORTED; +var ChecksumAlgorithm = /* @__PURE__ */ ((ChecksumAlgorithm3) => { + ChecksumAlgorithm3["MD5"] = "MD5"; + ChecksumAlgorithm3["CRC32"] = "CRC32"; + ChecksumAlgorithm3["CRC32C"] = "CRC32C"; + ChecksumAlgorithm3["CRC64NVME"] = "CRC64NVME"; + ChecksumAlgorithm3["SHA1"] = "SHA1"; + ChecksumAlgorithm3["SHA256"] = "SHA256"; + return ChecksumAlgorithm3; +})(ChecksumAlgorithm || {}); +var ChecksumLocation = /* @__PURE__ */ ((ChecksumLocation2) => { + ChecksumLocation2["HEADER"] = "header"; + ChecksumLocation2["TRAILER"] = "trailer"; + return ChecksumLocation2; +})(ChecksumLocation || {}); +var DEFAULT_CHECKSUM_ALGORITHM = "CRC32" /* CRC32 */; + +// src/stringUnionSelector.ts +var stringUnionSelector = /* @__PURE__ */ __name((obj, key, union, type) => { + if (!(key in obj)) return void 0; + const value = obj[key].toUpperCase(); + if (!Object.values(union).includes(value)) { + throw new TypeError(`Cannot load ${type} '${key}'. Expected one of ${Object.values(union)}, got '${obj[key]}'.`); + } + return value; +}, "stringUnionSelector"); + +// src/NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS.ts +var ENV_REQUEST_CHECKSUM_CALCULATION = "AWS_REQUEST_CHECKSUM_CALCULATION"; +var CONFIG_REQUEST_CHECKSUM_CALCULATION = "request_checksum_calculation"; +var NODE_REQUEST_CHECKSUM_CALCULATION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => stringUnionSelector(env, ENV_REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation, "env" /* ENV */), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => stringUnionSelector(profile, CONFIG_REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation, "shared config entry" /* CONFIG */), "configFileSelector"), + default: DEFAULT_REQUEST_CHECKSUM_CALCULATION +}; + +// src/NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS.ts +var ENV_RESPONSE_CHECKSUM_VALIDATION = "AWS_RESPONSE_CHECKSUM_VALIDATION"; +var CONFIG_RESPONSE_CHECKSUM_VALIDATION = "response_checksum_validation"; +var NODE_RESPONSE_CHECKSUM_VALIDATION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => stringUnionSelector(env, ENV_RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation, "env" /* ENV */), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => stringUnionSelector(profile, CONFIG_RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation, "shared config entry" /* CONFIG */), "configFileSelector"), + default: DEFAULT_RESPONSE_CHECKSUM_VALIDATION +}; + +// src/crc64-nvme-crt-container.ts +var crc64NvmeCrtContainer = { + CrtCrc64Nvme: null +}; + +// src/flexibleChecksumsMiddleware.ts +var import_core = __nccwpck_require__(8704); +var import_protocol_http = __nccwpck_require__(72356); +var import_util_stream = __nccwpck_require__(4252); + +// src/types.ts +var CLIENT_SUPPORTED_ALGORITHMS = [ + "CRC32" /* CRC32 */, + "CRC32C" /* CRC32C */, + "CRC64NVME" /* CRC64NVME */, + "SHA1" /* SHA1 */, + "SHA256" /* SHA256 */ +]; +var PRIORITY_ORDER_ALGORITHMS = [ + "SHA256" /* SHA256 */, + "SHA1" /* SHA1 */, + "CRC32" /* CRC32 */, + "CRC32C" /* CRC32C */, + "CRC64NVME" /* CRC64NVME */ +]; + +// src/getChecksumAlgorithmForRequest.ts +var getChecksumAlgorithmForRequest = /* @__PURE__ */ __name((input, { requestChecksumRequired, requestAlgorithmMember, requestChecksumCalculation }) => { + if (!requestAlgorithmMember) { + return requestChecksumCalculation === RequestChecksumCalculation.WHEN_SUPPORTED || requestChecksumRequired ? DEFAULT_CHECKSUM_ALGORITHM : void 0; + } + if (!input[requestAlgorithmMember]) { + return void 0; + } + const checksumAlgorithm = input[requestAlgorithmMember]; + if (!CLIENT_SUPPORTED_ALGORITHMS.includes(checksumAlgorithm)) { + throw new Error( + `The checksum algorithm "${checksumAlgorithm}" is not supported by the client. Select one of ${CLIENT_SUPPORTED_ALGORITHMS}.` + ); + } + return checksumAlgorithm; +}, "getChecksumAlgorithmForRequest"); + +// src/getChecksumLocationName.ts +var getChecksumLocationName = /* @__PURE__ */ __name((algorithm) => algorithm === "MD5" /* MD5 */ ? "content-md5" : `x-amz-checksum-${algorithm.toLowerCase()}`, "getChecksumLocationName"); + +// src/hasHeader.ts +var hasHeader = /* @__PURE__ */ __name((header, headers) => { + const soughtHeader = header.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return true; + } + } + return false; +}, "hasHeader"); + +// src/hasHeaderWithPrefix.ts +var hasHeaderWithPrefix = /* @__PURE__ */ __name((headerPrefix, headers) => { + const soughtHeaderPrefix = headerPrefix.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (headerName.toLowerCase().startsWith(soughtHeaderPrefix)) { + return true; + } + } + return false; +}, "hasHeaderWithPrefix"); + +// src/isStreaming.ts +var import_is_array_buffer = __nccwpck_require__(86130); +var isStreaming = /* @__PURE__ */ __name((body) => body !== void 0 && typeof body !== "string" && !ArrayBuffer.isView(body) && !(0, import_is_array_buffer.isArrayBuffer)(body), "isStreaming"); + +// src/selectChecksumAlgorithmFunction.ts +var import_crc32c = __nccwpck_require__(91491); +var import_getCrc32ChecksumAlgorithmFunction = __nccwpck_require__(23321); +var selectChecksumAlgorithmFunction = /* @__PURE__ */ __name((checksumAlgorithm, config) => { + switch (checksumAlgorithm) { + case "MD5" /* MD5 */: + return config.md5; + case "CRC32" /* CRC32 */: + return (0, import_getCrc32ChecksumAlgorithmFunction.getCrc32ChecksumAlgorithmFunction)(); + case "CRC32C" /* CRC32C */: + return import_crc32c.AwsCrc32c; + case "CRC64NVME" /* CRC64NVME */: + if (typeof crc64NvmeCrtContainer.CrtCrc64Nvme !== "function") { + throw new Error( + `Please check whether you have installed the "@aws-sdk/crc64-nvme-crt" package explicitly. +You must also register the package by calling [require("@aws-sdk/crc64-nvme-crt");] or an ESM equivalent such as [import "@aws-sdk/crc64-nvme-crt";]. +For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt` + ); + } + return crc64NvmeCrtContainer.CrtCrc64Nvme; + case "SHA1" /* SHA1 */: + return config.sha1; + case "SHA256" /* SHA256 */: + return config.sha256; + default: + throw new Error(`Unsupported checksum algorithm: ${checksumAlgorithm}`); + } +}, "selectChecksumAlgorithmFunction"); + +// src/stringHasher.ts +var import_util_utf8 = __nccwpck_require__(71577); +var stringHasher = /* @__PURE__ */ __name((checksumAlgorithmFn, body) => { + const hash = new checksumAlgorithmFn(); + hash.update((0, import_util_utf8.toUint8Array)(body || "")); + return hash.digest(); +}, "stringHasher"); + +// src/flexibleChecksumsMiddleware.ts +var flexibleChecksumsMiddlewareOptions = { + name: "flexibleChecksumsMiddleware", + step: "build", + tags: ["BODY_CHECKSUM"], + override: true +}; +var flexibleChecksumsMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + if (hasHeaderWithPrefix("x-amz-checksum-", args.request.headers)) { + return next(args); + } + const { request, input } = args; + const { body: requestBody, headers } = request; + const { base64Encoder, streamHasher } = config; + const { requestChecksumRequired, requestAlgorithmMember } = middlewareConfig; + const requestChecksumCalculation = await config.requestChecksumCalculation(); + const requestAlgorithmMemberName = requestAlgorithmMember?.name; + const requestAlgorithmMemberHttpHeader = requestAlgorithmMember?.httpHeader; + if (requestAlgorithmMemberName && !input[requestAlgorithmMemberName]) { + if (requestChecksumCalculation === RequestChecksumCalculation.WHEN_SUPPORTED || requestChecksumRequired) { + input[requestAlgorithmMemberName] = DEFAULT_CHECKSUM_ALGORITHM; + if (requestAlgorithmMemberHttpHeader) { + headers[requestAlgorithmMemberHttpHeader] = DEFAULT_CHECKSUM_ALGORITHM; + } + } + } + const checksumAlgorithm = getChecksumAlgorithmForRequest(input, { + requestChecksumRequired, + requestAlgorithmMember: requestAlgorithmMember?.name, + requestChecksumCalculation + }); + let updatedBody = requestBody; + let updatedHeaders = headers; + if (checksumAlgorithm) { + switch (checksumAlgorithm) { + case "CRC32" /* CRC32 */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_CRC32", "U"); + break; + case "CRC32C" /* CRC32C */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_CRC32C", "V"); + break; + case "CRC64NVME" /* CRC64NVME */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_CRC64", "W"); + break; + case "SHA1" /* SHA1 */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_SHA1", "X"); + break; + case "SHA256" /* SHA256 */: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_SHA256", "Y"); + break; + } + const checksumLocationName = getChecksumLocationName(checksumAlgorithm); + const checksumAlgorithmFn = selectChecksumAlgorithmFunction(checksumAlgorithm, config); + if (isStreaming(requestBody)) { + const { getAwsChunkedEncodingStream, bodyLengthChecker } = config; + updatedBody = getAwsChunkedEncodingStream( + typeof config.requestStreamBufferSize === "number" && config.requestStreamBufferSize >= 8 * 1024 ? (0, import_util_stream.createBufferedReadable)(requestBody, config.requestStreamBufferSize, context.logger) : requestBody, + { + base64Encoder, + bodyLengthChecker, + checksumLocationName, + checksumAlgorithmFn, + streamHasher + } + ); + updatedHeaders = { + ...headers, + "content-encoding": headers["content-encoding"] ? `${headers["content-encoding"]},aws-chunked` : "aws-chunked", + "transfer-encoding": "chunked", + "x-amz-decoded-content-length": headers["content-length"], + "x-amz-content-sha256": "STREAMING-UNSIGNED-PAYLOAD-TRAILER", + "x-amz-trailer": checksumLocationName + }; + delete updatedHeaders["content-length"]; + } else if (!hasHeader(checksumLocationName, headers)) { + const rawChecksum = await stringHasher(checksumAlgorithmFn, requestBody); + updatedHeaders = { + ...headers, + [checksumLocationName]: base64Encoder(rawChecksum) + }; + } + } + const result = await next({ + ...args, + request: { + ...request, + headers: updatedHeaders, + body: updatedBody + } + }); + return result; +}, "flexibleChecksumsMiddleware"); + +// src/flexibleChecksumsInputMiddleware.ts + +var flexibleChecksumsInputMiddlewareOptions = { + name: "flexibleChecksumsInputMiddleware", + toMiddleware: "serializerMiddleware", + relation: "before", + tags: ["BODY_CHECKSUM"], + override: true +}; +var flexibleChecksumsInputMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => { + const input = args.input; + const { requestValidationModeMember } = middlewareConfig; + const requestChecksumCalculation = await config.requestChecksumCalculation(); + const responseChecksumValidation = await config.responseChecksumValidation(); + switch (requestChecksumCalculation) { + case RequestChecksumCalculation.WHEN_REQUIRED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_WHEN_REQUIRED", "a"); + break; + case RequestChecksumCalculation.WHEN_SUPPORTED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_REQ_WHEN_SUPPORTED", "Z"); + break; + } + switch (responseChecksumValidation) { + case ResponseChecksumValidation.WHEN_REQUIRED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_RES_WHEN_REQUIRED", "c"); + break; + case ResponseChecksumValidation.WHEN_SUPPORTED: + (0, import_core.setFeature)(context, "FLEXIBLE_CHECKSUMS_RES_WHEN_SUPPORTED", "b"); + break; + } + if (requestValidationModeMember && !input[requestValidationModeMember]) { + if (responseChecksumValidation === ResponseChecksumValidation.WHEN_SUPPORTED) { + input[requestValidationModeMember] = "ENABLED"; + } + } + return next(args); +}, "flexibleChecksumsInputMiddleware"); + +// src/flexibleChecksumsResponseMiddleware.ts + + +// src/getChecksumAlgorithmListForResponse.ts +var getChecksumAlgorithmListForResponse = /* @__PURE__ */ __name((responseAlgorithms = []) => { + const validChecksumAlgorithms = []; + for (const algorithm of PRIORITY_ORDER_ALGORITHMS) { + if (!responseAlgorithms.includes(algorithm) || !CLIENT_SUPPORTED_ALGORITHMS.includes(algorithm)) { + continue; + } + validChecksumAlgorithms.push(algorithm); + } + return validChecksumAlgorithms; +}, "getChecksumAlgorithmListForResponse"); + +// src/isChecksumWithPartNumber.ts +var isChecksumWithPartNumber = /* @__PURE__ */ __name((checksum) => { + const lastHyphenIndex = checksum.lastIndexOf("-"); + if (lastHyphenIndex !== -1) { + const numberPart = checksum.slice(lastHyphenIndex + 1); + if (!numberPart.startsWith("0")) { + const number = parseInt(numberPart, 10); + if (!isNaN(number) && number >= 1 && number <= 1e4) { + return true; + } + } + } + return false; +}, "isChecksumWithPartNumber"); + +// src/validateChecksumFromResponse.ts + + +// src/getChecksum.ts +var getChecksum = /* @__PURE__ */ __name(async (body, { checksumAlgorithmFn, base64Encoder }) => base64Encoder(await stringHasher(checksumAlgorithmFn, body)), "getChecksum"); + +// src/validateChecksumFromResponse.ts +var validateChecksumFromResponse = /* @__PURE__ */ __name(async (response, { config, responseAlgorithms, logger }) => { + const checksumAlgorithms = getChecksumAlgorithmListForResponse(responseAlgorithms); + const { body: responseBody, headers: responseHeaders } = response; + for (const algorithm of checksumAlgorithms) { + const responseHeader = getChecksumLocationName(algorithm); + const checksumFromResponse = responseHeaders[responseHeader]; + if (checksumFromResponse) { + let checksumAlgorithmFn; + try { + checksumAlgorithmFn = selectChecksumAlgorithmFunction(algorithm, config); + } catch (error) { + if (algorithm === "CRC64NVME" /* CRC64NVME */) { + logger?.warn(`Skipping ${"CRC64NVME" /* CRC64NVME */} checksum validation: ${error.message}`); + continue; + } + throw error; + } + const { base64Encoder } = config; + if (isStreaming(responseBody)) { + response.body = (0, import_util_stream.createChecksumStream)({ + expectedChecksum: checksumFromResponse, + checksumSourceLocation: responseHeader, + checksum: new checksumAlgorithmFn(), + source: responseBody, + base64Encoder + }); + return; + } + const checksum = await getChecksum(responseBody, { checksumAlgorithmFn, base64Encoder }); + if (checksum === checksumFromResponse) { + break; + } + throw new Error( + `Checksum mismatch: expected "${checksum}" but received "${checksumFromResponse}" in response header "${responseHeader}".` + ); + } + } +}, "validateChecksumFromResponse"); + +// src/flexibleChecksumsResponseMiddleware.ts +var flexibleChecksumsResponseMiddlewareOptions = { + name: "flexibleChecksumsResponseMiddleware", + toMiddleware: "deserializerMiddleware", + relation: "after", + tags: ["BODY_CHECKSUM"], + override: true +}; +var flexibleChecksumsResponseMiddleware = /* @__PURE__ */ __name((config, middlewareConfig) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + const input = args.input; + const result = await next(args); + const response = result.response; + const { requestValidationModeMember, responseAlgorithms } = middlewareConfig; + if (requestValidationModeMember && input[requestValidationModeMember] === "ENABLED") { + const { clientName, commandName } = context; + const isS3WholeObjectMultipartGetResponseChecksum = clientName === "S3Client" && commandName === "GetObjectCommand" && getChecksumAlgorithmListForResponse(responseAlgorithms).every((algorithm) => { + const responseHeader = getChecksumLocationName(algorithm); + const checksumFromResponse = response.headers[responseHeader]; + return !checksumFromResponse || isChecksumWithPartNumber(checksumFromResponse); + }); + if (isS3WholeObjectMultipartGetResponseChecksum) { + return result; + } + await validateChecksumFromResponse(response, { + config, + responseAlgorithms, + logger: context.logger + }); + } + return result; +}, "flexibleChecksumsResponseMiddleware"); + +// src/getFlexibleChecksumsPlugin.ts +var getFlexibleChecksumsPlugin = /* @__PURE__ */ __name((config, middlewareConfig) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(flexibleChecksumsMiddleware(config, middlewareConfig), flexibleChecksumsMiddlewareOptions); + clientStack.addRelativeTo( + flexibleChecksumsInputMiddleware(config, middlewareConfig), + flexibleChecksumsInputMiddlewareOptions + ); + clientStack.addRelativeTo( + flexibleChecksumsResponseMiddleware(config, middlewareConfig), + flexibleChecksumsResponseMiddlewareOptions + ); + }, "applyToStack") +}), "getFlexibleChecksumsPlugin"); + +// src/resolveFlexibleChecksumsConfig.ts +var import_util_middleware = __nccwpck_require__(76324); +var resolveFlexibleChecksumsConfig = /* @__PURE__ */ __name((input) => { + const { requestChecksumCalculation, responseChecksumValidation, requestStreamBufferSize } = input; + return Object.assign(input, { + requestChecksumCalculation: (0, import_util_middleware.normalizeProvider)(requestChecksumCalculation ?? DEFAULT_REQUEST_CHECKSUM_CALCULATION), + responseChecksumValidation: (0, import_util_middleware.normalizeProvider)(responseChecksumValidation ?? DEFAULT_RESPONSE_CHECKSUM_VALIDATION), + requestStreamBufferSize: Number(requestStreamBufferSize ?? 0) + }); +}, "resolveFlexibleChecksumsConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 52590: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getHostHeaderPlugin: () => getHostHeaderPlugin, + hostHeaderMiddleware: () => hostHeaderMiddleware, + hostHeaderMiddlewareOptions: () => hostHeaderMiddlewareOptions, + resolveHostHeaderConfig: () => resolveHostHeaderConfig +}); +module.exports = __toCommonJS(index_exports); +var import_protocol_http = __nccwpck_require__(72356); +function resolveHostHeaderConfig(input) { + return input; +} +__name(resolveHostHeaderConfig, "resolveHostHeaderConfig"); +var hostHeaderMiddleware = /* @__PURE__ */ __name((options) => (next) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) return next(args); + const { request } = args; + const { handlerProtocol = "" } = options.requestHandler.metadata || {}; + if (handlerProtocol.indexOf("h2") >= 0 && !request.headers[":authority"]) { + delete request.headers["host"]; + request.headers[":authority"] = request.hostname + (request.port ? ":" + request.port : ""); + } else if (!request.headers["host"]) { + let host = request.hostname; + if (request.port != null) host += `:${request.port}`; + request.headers["host"] = host; + } + return next(args); +}, "hostHeaderMiddleware"); +var hostHeaderMiddlewareOptions = { + name: "hostHeaderMiddleware", + step: "build", + priority: "low", + tags: ["HOST"], + override: true +}; +var getHostHeaderPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(hostHeaderMiddleware(options), hostHeaderMiddlewareOptions); + }, "applyToStack") +}), "getHostHeaderPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 23209: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getLocationConstraintPlugin: () => getLocationConstraintPlugin, + locationConstraintMiddleware: () => locationConstraintMiddleware, + locationConstraintMiddlewareOptions: () => locationConstraintMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); +function locationConstraintMiddleware(options) { + return (next) => async (args) => { + const { CreateBucketConfiguration } = args.input; + const region = await options.region(); + if (!CreateBucketConfiguration?.LocationConstraint && !CreateBucketConfiguration?.Location) { + args = { + ...args, + input: { + ...args.input, + CreateBucketConfiguration: region === "us-east-1" ? void 0 : { LocationConstraint: region } + } + }; + } + return next(args); + }; +} +__name(locationConstraintMiddleware, "locationConstraintMiddleware"); +var locationConstraintMiddlewareOptions = { + step: "initialize", + tags: ["LOCATION_CONSTRAINT", "CREATE_BUCKET_CONFIGURATION"], + name: "locationConstraintMiddleware", + override: true +}; +var getLocationConstraintPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(locationConstraintMiddleware(config), locationConstraintMiddlewareOptions); + }, "applyToStack") +}), "getLocationConstraintPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 85242: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getLoggerPlugin: () => getLoggerPlugin, + loggerMiddleware: () => loggerMiddleware, + loggerMiddlewareOptions: () => loggerMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); + +// src/loggerMiddleware.ts +var loggerMiddleware = /* @__PURE__ */ __name(() => (next, context) => async (args) => { + try { + const response = await next(args); + const { clientName, commandName, logger, dynamoDbDocumentClientOptions = {} } = context; + const { overrideInputFilterSensitiveLog, overrideOutputFilterSensitiveLog } = dynamoDbDocumentClientOptions; + const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog; + const outputFilterSensitiveLog = overrideOutputFilterSensitiveLog ?? context.outputFilterSensitiveLog; + const { $metadata, ...outputWithoutMetadata } = response.output; + logger?.info?.({ + clientName, + commandName, + input: inputFilterSensitiveLog(args.input), + output: outputFilterSensitiveLog(outputWithoutMetadata), + metadata: $metadata + }); + return response; + } catch (error) { + const { clientName, commandName, logger, dynamoDbDocumentClientOptions = {} } = context; + const { overrideInputFilterSensitiveLog } = dynamoDbDocumentClientOptions; + const inputFilterSensitiveLog = overrideInputFilterSensitiveLog ?? context.inputFilterSensitiveLog; + logger?.error?.({ + clientName, + commandName, + input: inputFilterSensitiveLog(args.input), + error, + metadata: error.$metadata + }); + throw error; + } +}, "loggerMiddleware"); +var loggerMiddlewareOptions = { + name: "loggerMiddleware", + tags: ["LOGGER"], + step: "initialize", + override: true +}; +var getLoggerPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(loggerMiddleware(), loggerMiddlewareOptions); + }, "applyToStack") +}), "getLoggerPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 81568: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + addRecursionDetectionMiddlewareOptions: () => addRecursionDetectionMiddlewareOptions, + getRecursionDetectionPlugin: () => getRecursionDetectionPlugin, + recursionDetectionMiddleware: () => recursionDetectionMiddleware +}); +module.exports = __toCommonJS(index_exports); +var import_protocol_http = __nccwpck_require__(72356); +var TRACE_ID_HEADER_NAME = "X-Amzn-Trace-Id"; +var ENV_LAMBDA_FUNCTION_NAME = "AWS_LAMBDA_FUNCTION_NAME"; +var ENV_TRACE_ID = "_X_AMZN_TRACE_ID"; +var recursionDetectionMiddleware = /* @__PURE__ */ __name((options) => (next) => async (args) => { + const { request } = args; + if (!import_protocol_http.HttpRequest.isInstance(request) || options.runtime !== "node") { + return next(args); + } + const traceIdHeader = Object.keys(request.headers ?? {}).find((h) => h.toLowerCase() === TRACE_ID_HEADER_NAME.toLowerCase()) ?? TRACE_ID_HEADER_NAME; + if (request.headers.hasOwnProperty(traceIdHeader)) { + return next(args); + } + const functionName = process.env[ENV_LAMBDA_FUNCTION_NAME]; + const traceId = process.env[ENV_TRACE_ID]; + const nonEmptyString = /* @__PURE__ */ __name((str) => typeof str === "string" && str.length > 0, "nonEmptyString"); + if (nonEmptyString(functionName) && nonEmptyString(traceId)) { + request.headers[TRACE_ID_HEADER_NAME] = traceId; + } + return next({ + ...args, + request + }); +}, "recursionDetectionMiddleware"); +var addRecursionDetectionMiddlewareOptions = { + step: "build", + tags: ["RECURSION_DETECTION"], + name: "recursionDetectionMiddleware", + override: true, + priority: "low" +}; +var getRecursionDetectionPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(recursionDetectionMiddleware(options), addRecursionDetectionMiddlewareOptions); + }, "applyToStack") +}), "getRecursionDetectionPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 77445: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS: () => NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS, + S3ExpressIdentityCache: () => S3ExpressIdentityCache, + S3ExpressIdentityCacheEntry: () => S3ExpressIdentityCacheEntry, + S3ExpressIdentityProviderImpl: () => S3ExpressIdentityProviderImpl, + SignatureV4S3Express: () => SignatureV4S3Express, + checkContentLengthHeader: () => checkContentLengthHeader, + checkContentLengthHeaderMiddlewareOptions: () => checkContentLengthHeaderMiddlewareOptions, + getCheckContentLengthHeaderPlugin: () => getCheckContentLengthHeaderPlugin, + getRegionRedirectMiddlewarePlugin: () => getRegionRedirectMiddlewarePlugin, + getS3ExpiresMiddlewarePlugin: () => getS3ExpiresMiddlewarePlugin, + getS3ExpressHttpSigningPlugin: () => getS3ExpressHttpSigningPlugin, + getS3ExpressPlugin: () => getS3ExpressPlugin, + getThrow200ExceptionsPlugin: () => getThrow200ExceptionsPlugin, + getValidateBucketNamePlugin: () => getValidateBucketNamePlugin, + regionRedirectEndpointMiddleware: () => regionRedirectEndpointMiddleware, + regionRedirectEndpointMiddlewareOptions: () => regionRedirectEndpointMiddlewareOptions, + regionRedirectMiddleware: () => regionRedirectMiddleware, + regionRedirectMiddlewareOptions: () => regionRedirectMiddlewareOptions, + resolveS3Config: () => resolveS3Config, + s3ExpiresMiddleware: () => s3ExpiresMiddleware, + s3ExpiresMiddlewareOptions: () => s3ExpiresMiddlewareOptions, + s3ExpressHttpSigningMiddleware: () => s3ExpressHttpSigningMiddleware, + s3ExpressHttpSigningMiddlewareOptions: () => s3ExpressHttpSigningMiddlewareOptions, + s3ExpressMiddleware: () => s3ExpressMiddleware, + s3ExpressMiddlewareOptions: () => s3ExpressMiddlewareOptions, + throw200ExceptionsMiddleware: () => throw200ExceptionsMiddleware, + throw200ExceptionsMiddlewareOptions: () => throw200ExceptionsMiddlewareOptions, + validateBucketNameMiddleware: () => validateBucketNameMiddleware, + validateBucketNameMiddlewareOptions: () => validateBucketNameMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); + +// src/check-content-length-header.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client = __nccwpck_require__(61411); +var CONTENT_LENGTH_HEADER = "content-length"; +var DECODED_CONTENT_LENGTH_HEADER = "x-amz-decoded-content-length"; +function checkContentLengthHeader() { + return (next, context) => async (args) => { + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request)) { + if (!(CONTENT_LENGTH_HEADER in request.headers) && !(DECODED_CONTENT_LENGTH_HEADER in request.headers)) { + const message = `Are you using a Stream of unknown length as the Body of a PutObject request? Consider using Upload instead from @aws-sdk/lib-storage.`; + if (typeof context?.logger?.warn === "function" && !(context.logger instanceof import_smithy_client.NoOpLogger)) { + context.logger.warn(message); + } else { + console.warn(message); + } + } + } + return next({ ...args }); + }; +} +__name(checkContentLengthHeader, "checkContentLengthHeader"); +var checkContentLengthHeaderMiddlewareOptions = { + step: "finalizeRequest", + tags: ["CHECK_CONTENT_LENGTH_HEADER"], + name: "getCheckContentLengthHeaderPlugin", + override: true +}; +var getCheckContentLengthHeaderPlugin = /* @__PURE__ */ __name((unused) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(checkContentLengthHeader(), checkContentLengthHeaderMiddlewareOptions); + }, "applyToStack") +}), "getCheckContentLengthHeaderPlugin"); + +// src/region-redirect-endpoint-middleware.ts +var regionRedirectEndpointMiddleware = /* @__PURE__ */ __name((config) => { + return (next, context) => async (args) => { + const originalRegion = await config.region(); + const regionProviderRef = config.region; + let unlock = /* @__PURE__ */ __name(() => { + }, "unlock"); + if (context.__s3RegionRedirect) { + Object.defineProperty(config, "region", { + writable: false, + value: /* @__PURE__ */ __name(async () => { + return context.__s3RegionRedirect; + }, "value") + }); + unlock = /* @__PURE__ */ __name(() => Object.defineProperty(config, "region", { + writable: true, + value: regionProviderRef + }), "unlock"); + } + try { + const result = await next(args); + if (context.__s3RegionRedirect) { + unlock(); + const region = await config.region(); + if (originalRegion !== region) { + throw new Error("Region was not restored following S3 region redirect."); + } + } + return result; + } catch (e) { + unlock(); + throw e; + } + }; +}, "regionRedirectEndpointMiddleware"); +var regionRedirectEndpointMiddlewareOptions = { + tags: ["REGION_REDIRECT", "S3"], + name: "regionRedirectEndpointMiddleware", + override: true, + relation: "before", + toMiddleware: "endpointV2Middleware" +}; + +// src/region-redirect-middleware.ts +function regionRedirectMiddleware(clientConfig) { + return (next, context) => async (args) => { + try { + return await next(args); + } catch (err) { + if (clientConfig.followRegionRedirects) { + if (err?.$metadata?.httpStatusCode === 301 || // err.name === "PermanentRedirect" && --> removing the error name check, as that allows for HEAD operations (which have the 301 status code, but not the same error name) to be covered for region redirection as well + err?.$metadata?.httpStatusCode === 400 && err?.name === "IllegalLocationConstraintException") { + try { + const actualRegion = err.$response.headers["x-amz-bucket-region"]; + context.logger?.debug(`Redirecting from ${await clientConfig.region()} to ${actualRegion}`); + context.__s3RegionRedirect = actualRegion; + } catch (e) { + throw new Error("Region redirect failed: " + e); + } + return next(args); + } + } + throw err; + } + }; +} +__name(regionRedirectMiddleware, "regionRedirectMiddleware"); +var regionRedirectMiddlewareOptions = { + step: "initialize", + tags: ["REGION_REDIRECT", "S3"], + name: "regionRedirectMiddleware", + override: true +}; +var getRegionRedirectMiddlewarePlugin = /* @__PURE__ */ __name((clientConfig) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(regionRedirectMiddleware(clientConfig), regionRedirectMiddlewareOptions); + clientStack.addRelativeTo(regionRedirectEndpointMiddleware(clientConfig), regionRedirectEndpointMiddlewareOptions); + }, "applyToStack") +}), "getRegionRedirectMiddlewarePlugin"); + +// src/s3-expires-middleware.ts + + +var s3ExpiresMiddleware = /* @__PURE__ */ __name((config) => { + return (next, context) => async (args) => { + const result = await next(args); + const { response } = result; + if (import_protocol_http.HttpResponse.isInstance(response)) { + if (response.headers.expires) { + response.headers.expiresstring = response.headers.expires; + try { + (0, import_smithy_client.parseRfc7231DateTime)(response.headers.expires); + } catch (e) { + context.logger?.warn( + `AWS SDK Warning for ${context.clientName}::${context.commandName} response parsing (${response.headers.expires}): ${e}` + ); + delete response.headers.expires; + } + } + } + return result; + }; +}, "s3ExpiresMiddleware"); +var s3ExpiresMiddlewareOptions = { + tags: ["S3"], + name: "s3ExpiresMiddleware", + override: true, + relation: "after", + toMiddleware: "deserializerMiddleware" +}; +var getS3ExpiresMiddlewarePlugin = /* @__PURE__ */ __name((clientConfig) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo(s3ExpiresMiddleware(clientConfig), s3ExpiresMiddlewareOptions); + }, "applyToStack") +}), "getS3ExpiresMiddlewarePlugin"); + +// src/s3-express/classes/S3ExpressIdentityCache.ts +var S3ExpressIdentityCache = class _S3ExpressIdentityCache { + constructor(data = {}) { + this.data = data; + } + static { + __name(this, "S3ExpressIdentityCache"); + } + lastPurgeTime = Date.now(); + static EXPIRED_CREDENTIAL_PURGE_INTERVAL_MS = 3e4; + get(key) { + const entry = this.data[key]; + if (!entry) { + return; + } + return entry; + } + set(key, entry) { + this.data[key] = entry; + return entry; + } + delete(key) { + delete this.data[key]; + } + async purgeExpired() { + const now = Date.now(); + if (this.lastPurgeTime + _S3ExpressIdentityCache.EXPIRED_CREDENTIAL_PURGE_INTERVAL_MS > now) { + return; + } + for (const key in this.data) { + const entry = this.data[key]; + if (!entry.isRefreshing) { + const credential = await entry.identity; + if (credential.expiration) { + if (credential.expiration.getTime() < now) { + delete this.data[key]; + } + } + } + } + } +}; + +// src/s3-express/classes/S3ExpressIdentityCacheEntry.ts +var S3ExpressIdentityCacheEntry = class { + /** + * @param identity - stored identity. + * @param accessed - timestamp of last access in epoch ms. + * @param isRefreshing - this key is currently in the process of being refreshed (background). + */ + constructor(_identity, isRefreshing = false, accessed = Date.now()) { + this._identity = _identity; + this.isRefreshing = isRefreshing; + this.accessed = accessed; + } + static { + __name(this, "S3ExpressIdentityCacheEntry"); + } + get identity() { + this.accessed = Date.now(); + return this._identity; + } +}; + +// src/s3-express/classes/S3ExpressIdentityProviderImpl.ts +var S3ExpressIdentityProviderImpl = class _S3ExpressIdentityProviderImpl { + constructor(createSessionFn, cache = new S3ExpressIdentityCache()) { + this.createSessionFn = createSessionFn; + this.cache = cache; + } + static { + __name(this, "S3ExpressIdentityProviderImpl"); + } + static REFRESH_WINDOW_MS = 6e4; + async getS3ExpressIdentity(awsIdentity, identityProperties) { + const key = identityProperties.Bucket; + const { cache } = this; + const entry = cache.get(key); + if (entry) { + return entry.identity.then((identity) => { + const isExpired = (identity.expiration?.getTime() ?? 0) < Date.now(); + if (isExpired) { + return cache.set(key, new S3ExpressIdentityCacheEntry(this.getIdentity(key))).identity; + } + const isExpiringSoon = (identity.expiration?.getTime() ?? 0) < Date.now() + _S3ExpressIdentityProviderImpl.REFRESH_WINDOW_MS; + if (isExpiringSoon && !entry.isRefreshing) { + entry.isRefreshing = true; + this.getIdentity(key).then((id) => { + cache.set(key, new S3ExpressIdentityCacheEntry(Promise.resolve(id))); + }); + } + return identity; + }); + } + return cache.set(key, new S3ExpressIdentityCacheEntry(this.getIdentity(key))).identity; + } + async getIdentity(key) { + await this.cache.purgeExpired().catch((error) => { + console.warn("Error while clearing expired entries in S3ExpressIdentityCache: \n" + error); + }); + const session = await this.createSessionFn(key); + if (!session.Credentials?.AccessKeyId || !session.Credentials?.SecretAccessKey) { + throw new Error("s3#createSession response credential missing AccessKeyId or SecretAccessKey."); + } + const identity = { + accessKeyId: session.Credentials.AccessKeyId, + secretAccessKey: session.Credentials.SecretAccessKey, + sessionToken: session.Credentials.SessionToken, + expiration: session.Credentials.Expiration ? new Date(session.Credentials.Expiration) : void 0 + }; + return identity; + } +}; + +// src/s3-express/classes/SignatureV4S3Express.ts +var import_signature_v4 = __nccwpck_require__(75118); + +// src/s3-express/constants.ts +var import_util_config_provider = __nccwpck_require__(56716); +var S3_EXPRESS_BUCKET_TYPE = "Directory"; +var S3_EXPRESS_BACKEND = "S3Express"; +var S3_EXPRESS_AUTH_SCHEME = "sigv4-s3express"; +var SESSION_TOKEN_QUERY_PARAM = "X-Amz-S3session-Token"; +var SESSION_TOKEN_HEADER = SESSION_TOKEN_QUERY_PARAM.toLowerCase(); +var NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_ENV_NAME = "AWS_S3_DISABLE_EXPRESS_SESSION_AUTH"; +var NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_INI_NAME = "s3_disable_express_session_auth"; +var NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => (0, import_util_config_provider.booleanSelector)(env, NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_ENV_NAME, import_util_config_provider.SelectorType.ENV), "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => (0, import_util_config_provider.booleanSelector)(profile, NODE_DISABLE_S3_EXPRESS_SESSION_AUTH_INI_NAME, import_util_config_provider.SelectorType.CONFIG), "configFileSelector"), + default: false +}; + +// src/s3-express/classes/SignatureV4S3Express.ts +var SignatureV4S3Express = class extends import_signature_v4.SignatureV4 { + static { + __name(this, "SignatureV4S3Express"); + } + /** + * Signs with alternate provided credentials instead of those provided in the + * constructor. + * + * Additionally omits the credential sessionToken and assigns it to the + * alternate header field for S3 Express. + */ + async signWithCredentials(requestToSign, credentials, options) { + const credentialsWithoutSessionToken = getCredentialsWithoutSessionToken(credentials); + requestToSign.headers[SESSION_TOKEN_HEADER] = credentials.sessionToken; + const privateAccess = this; + setSingleOverride(privateAccess, credentialsWithoutSessionToken); + return privateAccess.signRequest(requestToSign, options ?? {}); + } + /** + * Similar to {@link SignatureV4S3Express#signWithCredentials} but for presigning. + */ + async presignWithCredentials(requestToSign, credentials, options) { + const credentialsWithoutSessionToken = getCredentialsWithoutSessionToken(credentials); + delete requestToSign.headers[SESSION_TOKEN_HEADER]; + requestToSign.headers[SESSION_TOKEN_QUERY_PARAM] = credentials.sessionToken; + requestToSign.query = requestToSign.query ?? {}; + requestToSign.query[SESSION_TOKEN_QUERY_PARAM] = credentials.sessionToken; + const privateAccess = this; + setSingleOverride(privateAccess, credentialsWithoutSessionToken); + return this.presign(requestToSign, options); + } +}; +function getCredentialsWithoutSessionToken(credentials) { + const credentialsWithoutSessionToken = { + accessKeyId: credentials.accessKeyId, + secretAccessKey: credentials.secretAccessKey, + expiration: credentials.expiration + }; + return credentialsWithoutSessionToken; +} +__name(getCredentialsWithoutSessionToken, "getCredentialsWithoutSessionToken"); +function setSingleOverride(privateAccess, credentialsWithoutSessionToken) { + const id = setTimeout(() => { + throw new Error("SignatureV4S3Express credential override was created but not called."); + }, 10); + const currentCredentialProvider = privateAccess.credentialProvider; + const overrideCredentialsProviderOnce = /* @__PURE__ */ __name(() => { + clearTimeout(id); + privateAccess.credentialProvider = currentCredentialProvider; + return Promise.resolve(credentialsWithoutSessionToken); + }, "overrideCredentialsProviderOnce"); + privateAccess.credentialProvider = overrideCredentialsProviderOnce; +} +__name(setSingleOverride, "setSingleOverride"); + +// src/s3-express/functions/s3ExpressMiddleware.ts +var import_core = __nccwpck_require__(8704); + +var s3ExpressMiddleware = /* @__PURE__ */ __name((options) => { + return (next, context) => async (args) => { + if (context.endpointV2) { + const endpoint = context.endpointV2; + const isS3ExpressAuth = endpoint.properties?.authSchemes?.[0]?.name === S3_EXPRESS_AUTH_SCHEME; + const isS3ExpressBucket = endpoint.properties?.backend === S3_EXPRESS_BACKEND || endpoint.properties?.bucketType === S3_EXPRESS_BUCKET_TYPE; + if (isS3ExpressBucket) { + (0, import_core.setFeature)(context, "S3_EXPRESS_BUCKET", "J"); + context.isS3ExpressBucket = true; + } + if (isS3ExpressAuth) { + const requestBucket = args.input.Bucket; + if (requestBucket) { + const s3ExpressIdentity = await options.s3ExpressIdentityProvider.getS3ExpressIdentity( + await options.credentials(), + { + Bucket: requestBucket + } + ); + context.s3ExpressIdentity = s3ExpressIdentity; + if (import_protocol_http.HttpRequest.isInstance(args.request) && s3ExpressIdentity.sessionToken) { + args.request.headers[SESSION_TOKEN_HEADER] = s3ExpressIdentity.sessionToken; + } + } + } + } + return next(args); + }; +}, "s3ExpressMiddleware"); +var s3ExpressMiddlewareOptions = { + name: "s3ExpressMiddleware", + step: "build", + tags: ["S3", "S3_EXPRESS"], + override: true +}; +var getS3ExpressPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(s3ExpressMiddleware(options), s3ExpressMiddlewareOptions); + }, "applyToStack") +}), "getS3ExpressPlugin"); + +// src/s3-express/functions/s3ExpressHttpSigningMiddleware.ts +var import_core2 = __nccwpck_require__(90402); + +var import_util_middleware = __nccwpck_require__(76324); + +// src/s3-express/functions/signS3Express.ts +var signS3Express = /* @__PURE__ */ __name(async (s3ExpressIdentity, signingOptions, request, sigV4MultiRegionSigner) => { + const signedRequest = await sigV4MultiRegionSigner.signWithCredentials(request, s3ExpressIdentity, {}); + if (signedRequest.headers["X-Amz-Security-Token"] || signedRequest.headers["x-amz-security-token"]) { + throw new Error("X-Amz-Security-Token must not be set for s3-express requests."); + } + return signedRequest; +}, "signS3Express"); + +// src/s3-express/functions/s3ExpressHttpSigningMiddleware.ts +var defaultErrorHandler = /* @__PURE__ */ __name((signingProperties) => (error) => { + throw error; +}, "defaultErrorHandler"); +var defaultSuccessHandler = /* @__PURE__ */ __name((httpResponse, signingProperties) => { +}, "defaultSuccessHandler"); +var s3ExpressHttpSigningMiddlewareOptions = import_core2.httpSigningMiddlewareOptions; +var s3ExpressHttpSigningMiddleware = /* @__PURE__ */ __name((config) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const scheme = smithyContext.selectedHttpAuthScheme; + if (!scheme) { + throw new Error(`No HttpAuthScheme was selected: unable to sign request`); + } + const { + httpAuthOption: { signingProperties = {} }, + identity, + signer + } = scheme; + let request; + if (context.s3ExpressIdentity) { + request = await signS3Express( + context.s3ExpressIdentity, + signingProperties, + args.request, + await config.signer() + ); + } else { + request = await signer.sign(args.request, identity, signingProperties); + } + const output = await next({ + ...args, + request + }).catch((signer.errorHandler || defaultErrorHandler)(signingProperties)); + (signer.successHandler || defaultSuccessHandler)(output.response, signingProperties); + return output; +}, "s3ExpressHttpSigningMiddleware"); +var getS3ExpressHttpSigningPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo( + s3ExpressHttpSigningMiddleware(config), + import_core2.httpSigningMiddlewareOptions + ); + }, "applyToStack") +}), "getS3ExpressHttpSigningPlugin"); + +// src/s3Configuration.ts +var resolveS3Config = /* @__PURE__ */ __name((input, { + session +}) => { + const [s3ClientProvider, CreateSessionCommandCtor] = session; + const { + forcePathStyle, + useAccelerateEndpoint, + disableMultiregionAccessPoints, + followRegionRedirects, + s3ExpressIdentityProvider, + bucketEndpoint + } = input; + return Object.assign(input, { + forcePathStyle: forcePathStyle ?? false, + useAccelerateEndpoint: useAccelerateEndpoint ?? false, + disableMultiregionAccessPoints: disableMultiregionAccessPoints ?? false, + followRegionRedirects: followRegionRedirects ?? false, + s3ExpressIdentityProvider: s3ExpressIdentityProvider ?? new S3ExpressIdentityProviderImpl( + async (key) => s3ClientProvider().send( + new CreateSessionCommandCtor({ + Bucket: key + }) + ) + ), + bucketEndpoint: bucketEndpoint ?? false + }); +}, "resolveS3Config"); + +// src/throw-200-exceptions.ts + +var import_util_stream = __nccwpck_require__(4252); +var THROW_IF_EMPTY_BODY = { + CopyObjectCommand: true, + UploadPartCopyCommand: true, + CompleteMultipartUploadCommand: true +}; +var MAX_BYTES_TO_INSPECT = 3e3; +var throw200ExceptionsMiddleware = /* @__PURE__ */ __name((config) => (next, context) => async (args) => { + const result = await next(args); + const { response } = result; + if (!import_protocol_http.HttpResponse.isInstance(response)) { + return result; + } + const { statusCode, body: sourceBody } = response; + if (statusCode < 200 || statusCode >= 300) { + return result; + } + const isSplittableStream = typeof sourceBody?.stream === "function" || typeof sourceBody?.pipe === "function" || typeof sourceBody?.tee === "function"; + if (!isSplittableStream) { + return result; + } + let bodyCopy = sourceBody; + let body = sourceBody; + if (sourceBody && typeof sourceBody === "object" && !(sourceBody instanceof Uint8Array)) { + [bodyCopy, body] = await (0, import_util_stream.splitStream)(sourceBody); + } + response.body = body; + const bodyBytes = await collectBody(bodyCopy, { + streamCollector: /* @__PURE__ */ __name(async (stream) => { + return (0, import_util_stream.headStream)(stream, MAX_BYTES_TO_INSPECT); + }, "streamCollector") + }); + if (typeof bodyCopy?.destroy === "function") { + bodyCopy.destroy(); + } + const bodyStringTail = config.utf8Encoder(bodyBytes.subarray(bodyBytes.length - 16)); + if (bodyBytes.length === 0 && THROW_IF_EMPTY_BODY[context.commandName]) { + const err = new Error("S3 aborted request"); + err.name = "InternalError"; + throw err; + } + if (bodyStringTail && bodyStringTail.endsWith("")) { + response.statusCode = 400; + } + return result; +}, "throw200ExceptionsMiddleware"); +var collectBody = /* @__PURE__ */ __name((streamBody = new Uint8Array(), context) => { + if (streamBody instanceof Uint8Array) { + return Promise.resolve(streamBody); + } + return context.streamCollector(streamBody) || Promise.resolve(new Uint8Array()); +}, "collectBody"); +var throw200ExceptionsMiddlewareOptions = { + relation: "after", + toMiddleware: "deserializerMiddleware", + tags: ["THROW_200_EXCEPTIONS", "S3"], + name: "throw200ExceptionsMiddleware", + override: true +}; +var getThrow200ExceptionsPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.addRelativeTo(throw200ExceptionsMiddleware(config), throw200ExceptionsMiddlewareOptions); + }, "applyToStack") +}), "getThrow200ExceptionsPlugin"); + +// src/validate-bucket-name.ts +var import_util_arn_parser = __nccwpck_require__(56369); + +// src/bucket-endpoint-middleware.ts +function bucketEndpointMiddleware(options) { + return (next, context) => async (args) => { + if (options.bucketEndpoint) { + const endpoint = context.endpointV2; + if (endpoint) { + const bucket = args.input.Bucket; + if (typeof bucket === "string") { + try { + const bucketEndpointUrl = new URL(bucket); + context.endpointV2 = { + ...endpoint, + url: bucketEndpointUrl + }; + } catch (e) { + const warning = `@aws-sdk/middleware-sdk-s3: bucketEndpoint=true was set but Bucket=${bucket} could not be parsed as URL.`; + if (context.logger?.constructor?.name === "NoOpLogger") { + console.warn(warning); + } else { + context.logger?.warn?.(warning); + } + throw e; + } + } + } + } + return next(args); + }; +} +__name(bucketEndpointMiddleware, "bucketEndpointMiddleware"); +var bucketEndpointMiddlewareOptions = { + name: "bucketEndpointMiddleware", + override: true, + relation: "after", + toMiddleware: "endpointV2Middleware" +}; + +// src/validate-bucket-name.ts +function validateBucketNameMiddleware({ bucketEndpoint }) { + return (next) => async (args) => { + const { + input: { Bucket } + } = args; + if (!bucketEndpoint && typeof Bucket === "string" && !(0, import_util_arn_parser.validate)(Bucket) && Bucket.indexOf("/") >= 0) { + const err = new Error(`Bucket name shouldn't contain '/', received '${Bucket}'`); + err.name = "InvalidBucketName"; + throw err; + } + return next({ ...args }); + }; +} +__name(validateBucketNameMiddleware, "validateBucketNameMiddleware"); +var validateBucketNameMiddlewareOptions = { + step: "initialize", + tags: ["VALIDATE_BUCKET_NAME"], + name: "validateBucketNameMiddleware", + override: true +}; +var getValidateBucketNamePlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(validateBucketNameMiddleware(options), validateBucketNameMiddlewareOptions); + clientStack.addRelativeTo(bucketEndpointMiddleware(options), bucketEndpointMiddlewareOptions); + }, "applyToStack") +}), "getValidateBucketNamePlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 35568: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + getSsecPlugin: () => getSsecPlugin, + isValidBase64EncodedSSECustomerKey: () => isValidBase64EncodedSSECustomerKey, + ssecMiddleware: () => ssecMiddleware, + ssecMiddlewareOptions: () => ssecMiddlewareOptions +}); +module.exports = __toCommonJS(index_exports); +function ssecMiddleware(options) { + return (next) => async (args) => { + const input = { ...args.input }; + const properties = [ + { + target: "SSECustomerKey", + hash: "SSECustomerKeyMD5" + }, + { + target: "CopySourceSSECustomerKey", + hash: "CopySourceSSECustomerKeyMD5" + } + ]; + for (const prop of properties) { + const value = input[prop.target]; + if (value) { + let valueForHash; + if (typeof value === "string") { + if (isValidBase64EncodedSSECustomerKey(value, options)) { + valueForHash = options.base64Decoder(value); + } else { + valueForHash = options.utf8Decoder(value); + input[prop.target] = options.base64Encoder(valueForHash); + } + } else { + valueForHash = ArrayBuffer.isView(value) ? new Uint8Array(value.buffer, value.byteOffset, value.byteLength) : new Uint8Array(value); + input[prop.target] = options.base64Encoder(valueForHash); + } + const hash = new options.md5(); + hash.update(valueForHash); + input[prop.hash] = options.base64Encoder(await hash.digest()); + } + } + return next({ + ...args, + input + }); + }; +} +__name(ssecMiddleware, "ssecMiddleware"); +var ssecMiddlewareOptions = { + name: "ssecMiddleware", + step: "initialize", + tags: ["SSE"], + override: true +}; +var getSsecPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(ssecMiddleware(config), ssecMiddlewareOptions); + }, "applyToStack") +}), "getSsecPlugin"); +function isValidBase64EncodedSSECustomerKey(str, options) { + const base64Regex = /^(?:[A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/; + if (!base64Regex.test(str)) return false; + try { + const decodedBytes = options.base64Decoder(str); + return decodedBytes.length === 32; + } catch { + return false; + } +} +__name(isValidBase64EncodedSSECustomerKey, "isValidBase64EncodedSSECustomerKey"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 32959: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + DEFAULT_UA_APP_ID: () => DEFAULT_UA_APP_ID, + getUserAgentMiddlewareOptions: () => getUserAgentMiddlewareOptions, + getUserAgentPlugin: () => getUserAgentPlugin, + resolveUserAgentConfig: () => resolveUserAgentConfig, + userAgentMiddleware: () => userAgentMiddleware +}); +module.exports = __toCommonJS(index_exports); + +// src/configurations.ts +var import_core = __nccwpck_require__(90402); +var DEFAULT_UA_APP_ID = void 0; +function isValidUserAgentAppId(appId) { + if (appId === void 0) { + return true; + } + return typeof appId === "string" && appId.length <= 50; +} +__name(isValidUserAgentAppId, "isValidUserAgentAppId"); +function resolveUserAgentConfig(input) { + const normalizedAppIdProvider = (0, import_core.normalizeProvider)(input.userAgentAppId ?? DEFAULT_UA_APP_ID); + const { customUserAgent } = input; + return Object.assign(input, { + customUserAgent: typeof customUserAgent === "string" ? [[customUserAgent]] : customUserAgent, + userAgentAppId: /* @__PURE__ */ __name(async () => { + const appId = await normalizedAppIdProvider(); + if (!isValidUserAgentAppId(appId)) { + const logger = input.logger?.constructor?.name === "NoOpLogger" || !input.logger ? console : input.logger; + if (typeof appId !== "string") { + logger?.warn("userAgentAppId must be a string or undefined."); + } else if (appId.length > 50) { + logger?.warn("The provided userAgentAppId exceeds the maximum length of 50 characters."); + } + } + return appId; + }, "userAgentAppId") + }); +} +__name(resolveUserAgentConfig, "resolveUserAgentConfig"); + +// src/user-agent-middleware.ts +var import_util_endpoints = __nccwpck_require__(83068); +var import_protocol_http = __nccwpck_require__(72356); + +// src/check-features.ts +var import_core2 = __nccwpck_require__(8704); +var ACCOUNT_ID_ENDPOINT_REGEX = /\d{12}\.ddb/; +async function checkFeatures(context, config, args) { + const request = args.request; + if (request?.headers?.["smithy-protocol"] === "rpc-v2-cbor") { + (0, import_core2.setFeature)(context, "PROTOCOL_RPC_V2_CBOR", "M"); + } + if (typeof config.retryStrategy === "function") { + const retryStrategy = await config.retryStrategy(); + if (typeof retryStrategy.acquireInitialRetryToken === "function") { + if (retryStrategy.constructor?.name?.includes("Adaptive")) { + (0, import_core2.setFeature)(context, "RETRY_MODE_ADAPTIVE", "F"); + } else { + (0, import_core2.setFeature)(context, "RETRY_MODE_STANDARD", "E"); + } + } else { + (0, import_core2.setFeature)(context, "RETRY_MODE_LEGACY", "D"); + } + } + if (typeof config.accountIdEndpointMode === "function") { + const endpointV2 = context.endpointV2; + if (String(endpointV2?.url?.hostname).match(ACCOUNT_ID_ENDPOINT_REGEX)) { + (0, import_core2.setFeature)(context, "ACCOUNT_ID_ENDPOINT", "O"); + } + switch (await config.accountIdEndpointMode?.()) { + case "disabled": + (0, import_core2.setFeature)(context, "ACCOUNT_ID_MODE_DISABLED", "Q"); + break; + case "preferred": + (0, import_core2.setFeature)(context, "ACCOUNT_ID_MODE_PREFERRED", "P"); + break; + case "required": + (0, import_core2.setFeature)(context, "ACCOUNT_ID_MODE_REQUIRED", "R"); + break; + } + } + const identity = context.__smithy_context?.selectedHttpAuthScheme?.identity; + if (identity?.$source) { + const credentials = identity; + if (credentials.accountId) { + (0, import_core2.setFeature)(context, "RESOLVED_ACCOUNT_ID", "T"); + } + for (const [key, value] of Object.entries(credentials.$source ?? {})) { + (0, import_core2.setFeature)(context, key, value); + } + } +} +__name(checkFeatures, "checkFeatures"); + +// src/constants.ts +var USER_AGENT = "user-agent"; +var X_AMZ_USER_AGENT = "x-amz-user-agent"; +var SPACE = " "; +var UA_NAME_SEPARATOR = "/"; +var UA_NAME_ESCAPE_REGEX = /[^\!\$\%\&\'\*\+\-\.\^\_\`\|\~\d\w]/g; +var UA_VALUE_ESCAPE_REGEX = /[^\!\$\%\&\'\*\+\-\.\^\_\`\|\~\d\w\#]/g; +var UA_ESCAPE_CHAR = "-"; + +// src/encode-features.ts +var BYTE_LIMIT = 1024; +function encodeFeatures(features) { + let buffer = ""; + for (const key in features) { + const val = features[key]; + if (buffer.length + val.length + 1 <= BYTE_LIMIT) { + if (buffer.length) { + buffer += "," + val; + } else { + buffer += val; + } + continue; + } + break; + } + return buffer; +} +__name(encodeFeatures, "encodeFeatures"); + +// src/user-agent-middleware.ts +var userAgentMiddleware = /* @__PURE__ */ __name((options) => (next, context) => async (args) => { + const { request } = args; + if (!import_protocol_http.HttpRequest.isInstance(request)) { + return next(args); + } + const { headers } = request; + const userAgent = context?.userAgent?.map(escapeUserAgent) || []; + const defaultUserAgent = (await options.defaultUserAgentProvider()).map(escapeUserAgent); + await checkFeatures(context, options, args); + const awsContext = context; + defaultUserAgent.push( + `m/${encodeFeatures( + Object.assign({}, context.__smithy_context?.features, awsContext.__aws_sdk_context?.features) + )}` + ); + const customUserAgent = options?.customUserAgent?.map(escapeUserAgent) || []; + const appId = await options.userAgentAppId(); + if (appId) { + defaultUserAgent.push(escapeUserAgent([`app/${appId}`])); + } + const prefix = (0, import_util_endpoints.getUserAgentPrefix)(); + const sdkUserAgentValue = (prefix ? [prefix] : []).concat([...defaultUserAgent, ...userAgent, ...customUserAgent]).join(SPACE); + const normalUAValue = [ + ...defaultUserAgent.filter((section) => section.startsWith("aws-sdk-")), + ...customUserAgent + ].join(SPACE); + if (options.runtime !== "browser") { + if (normalUAValue) { + headers[X_AMZ_USER_AGENT] = headers[X_AMZ_USER_AGENT] ? `${headers[USER_AGENT]} ${normalUAValue}` : normalUAValue; + } + headers[USER_AGENT] = sdkUserAgentValue; + } else { + headers[X_AMZ_USER_AGENT] = sdkUserAgentValue; + } + return next({ + ...args, + request + }); +}, "userAgentMiddleware"); +var escapeUserAgent = /* @__PURE__ */ __name((userAgentPair) => { + const name = userAgentPair[0].split(UA_NAME_SEPARATOR).map((part) => part.replace(UA_NAME_ESCAPE_REGEX, UA_ESCAPE_CHAR)).join(UA_NAME_SEPARATOR); + const version = userAgentPair[1]?.replace(UA_VALUE_ESCAPE_REGEX, UA_ESCAPE_CHAR); + const prefixSeparatorIndex = name.indexOf(UA_NAME_SEPARATOR); + const prefix = name.substring(0, prefixSeparatorIndex); + let uaName = name.substring(prefixSeparatorIndex + 1); + if (prefix === "api") { + uaName = uaName.toLowerCase(); + } + return [prefix, uaName, version].filter((item) => item && item.length > 0).reduce((acc, item, index) => { + switch (index) { + case 0: + return item; + case 1: + return `${acc}/${item}`; + default: + return `${acc}#${item}`; + } + }, ""); +}, "escapeUserAgent"); +var getUserAgentMiddlewareOptions = { + name: "getUserAgentMiddleware", + step: "build", + priority: "low", + tags: ["SET_USER_AGENT", "USER_AGENT"], + override: true +}; +var getUserAgentPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: /* @__PURE__ */ __name((clientStack) => { + clientStack.add(userAgentMiddleware(config), getUserAgentMiddlewareOptions); + }, "applyToStack") +}), "getUserAgentPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 8396: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.defaultSSOOIDCHttpAuthSchemeProvider = exports.defaultSSOOIDCHttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const util_middleware_1 = __nccwpck_require__(76324); +const defaultSSOOIDCHttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultSSOOIDCHttpAuthSchemeParametersProvider = defaultSSOOIDCHttpAuthSchemeParametersProvider; +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "sso-oauth", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createSmithyApiNoAuthHttpAuthOption(authParameters) { + return { + schemeId: "smithy.api#noAuth", + }; +} +const defaultSSOOIDCHttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + case "CreateToken": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultSSOOIDCHttpAuthSchemeProvider = defaultSSOOIDCHttpAuthSchemeProvider; +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, core_1.resolveAwsSdkSigV4Config)(config); + return Object.assign(config_0, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 90546: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(69947); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: ["Endpoint", "Region", "UseDualStack", "UseFIPS"], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 69947: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const u = "required", v = "fn", w = "argv", x = "ref"; +const a = true, b = "isSet", c = "booleanEquals", d = "error", e = "endpoint", f = "tree", g = "PartitionResult", h = "getAttr", i = { [u]: false, "type": "String" }, j = { [u]: true, "default": false, "type": "Boolean" }, k = { [x]: "Endpoint" }, l = { [v]: c, [w]: [{ [x]: "UseFIPS" }, true] }, m = { [v]: c, [w]: [{ [x]: "UseDualStack" }, true] }, n = {}, o = { [v]: h, [w]: [{ [x]: g }, "supportsFIPS"] }, p = { [x]: g }, q = { [v]: c, [w]: [true, { [v]: h, [w]: [p, "supportsDualStack"] }] }, r = [l], s = [m], t = [{ [x]: "Region" }]; +const _data = { version: "1.0", parameters: { Region: i, UseDualStack: j, UseFIPS: j, Endpoint: i }, rules: [{ conditions: [{ [v]: b, [w]: [k] }], rules: [{ conditions: r, error: "Invalid Configuration: FIPS and custom endpoint are not supported", type: d }, { conditions: s, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", type: d }, { endpoint: { url: k, properties: n, headers: n }, type: e }], type: f }, { conditions: [{ [v]: b, [w]: t }], rules: [{ conditions: [{ [v]: "aws.partition", [w]: t, assign: g }], rules: [{ conditions: [l, m], rules: [{ conditions: [{ [v]: c, [w]: [a, o] }, q], rules: [{ endpoint: { url: "https://oidc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", type: d }], type: f }, { conditions: r, rules: [{ conditions: [{ [v]: c, [w]: [o, a] }], rules: [{ conditions: [{ [v]: "stringEquals", [w]: [{ [v]: h, [w]: [p, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://oidc.{Region}.amazonaws.com", properties: n, headers: n }, type: e }, { endpoint: { url: "https://oidc-fips.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "FIPS is enabled but this partition does not support FIPS", type: d }], type: f }, { conditions: s, rules: [{ conditions: [q], rules: [{ endpoint: { url: "https://oidc.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: n, headers: n }, type: e }], type: f }, { error: "DualStack is enabled but this partition does not support DualStack", type: d }], type: f }, { endpoint: { url: "https://oidc.{Region}.{PartitionResult#dnsSuffix}", properties: n, headers: n }, type: e }], type: f }], type: f }, { error: "Invalid Configuration: Missing Region", type: d }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 89443: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/sso-oidc/index.ts +var index_exports = {}; +__export(index_exports, { + $Command: () => import_smithy_client6.Command, + AccessDeniedException: () => AccessDeniedException, + AuthorizationPendingException: () => AuthorizationPendingException, + CreateTokenCommand: () => CreateTokenCommand, + CreateTokenRequestFilterSensitiveLog: () => CreateTokenRequestFilterSensitiveLog, + CreateTokenResponseFilterSensitiveLog: () => CreateTokenResponseFilterSensitiveLog, + ExpiredTokenException: () => ExpiredTokenException, + InternalServerException: () => InternalServerException, + InvalidClientException: () => InvalidClientException, + InvalidGrantException: () => InvalidGrantException, + InvalidRequestException: () => InvalidRequestException, + InvalidScopeException: () => InvalidScopeException, + SSOOIDC: () => SSOOIDC, + SSOOIDCClient: () => SSOOIDCClient, + SSOOIDCServiceException: () => SSOOIDCServiceException, + SlowDownException: () => SlowDownException, + UnauthorizedClientException: () => UnauthorizedClientException, + UnsupportedGrantTypeException: () => UnsupportedGrantTypeException, + __Client: () => import_smithy_client2.Client +}); +module.exports = __toCommonJS(index_exports); + +// src/submodules/sso-oidc/SSOOIDCClient.ts +var import_middleware_host_header = __nccwpck_require__(52590); +var import_middleware_logger = __nccwpck_require__(85242); +var import_middleware_recursion_detection = __nccwpck_require__(81568); +var import_middleware_user_agent = __nccwpck_require__(32959); +var import_config_resolver = __nccwpck_require__(39316); +var import_core = __nccwpck_require__(90402); +var import_middleware_content_length = __nccwpck_require__(47212); +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_retry = __nccwpck_require__(19618); +var import_smithy_client2 = __nccwpck_require__(61411); +var import_httpAuthSchemeProvider = __nccwpck_require__(8396); + +// src/submodules/sso-oidc/endpoint/EndpointParameters.ts +var resolveClientEndpointParameters = /* @__PURE__ */ __name((options) => { + return Object.assign(options, { + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + useFipsEndpoint: options.useFipsEndpoint ?? false, + defaultSigningName: "sso-oauth" + }); +}, "resolveClientEndpointParameters"); +var commonParams = { + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" } +}; + +// src/submodules/sso-oidc/SSOOIDCClient.ts +var import_runtimeConfig = __nccwpck_require__(16901); + +// src/submodules/sso-oidc/runtimeExtensions.ts +var import_region_config_resolver = __nccwpck_require__(36463); +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/auth/httpAuthExtensionConfiguration.ts +var getHttpAuthExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + } + }; +}, "getHttpAuthExtensionConfiguration"); +var resolveHttpAuthRuntimeConfig = /* @__PURE__ */ __name((config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials() + }; +}, "resolveHttpAuthRuntimeConfig"); + +// src/submodules/sso-oidc/runtimeExtensions.ts +var resolveRuntimeExtensions = /* @__PURE__ */ __name((runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign( + (0, import_region_config_resolver.getAwsRegionExtensionConfiguration)(runtimeConfig), + (0, import_smithy_client.getDefaultExtensionConfiguration)(runtimeConfig), + (0, import_protocol_http.getHttpHandlerExtensionConfiguration)(runtimeConfig), + getHttpAuthExtensionConfiguration(runtimeConfig) + ); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign( + runtimeConfig, + (0, import_region_config_resolver.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), + (0, import_smithy_client.resolveDefaultRuntimeConfig)(extensionConfiguration), + (0, import_protocol_http.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), + resolveHttpAuthRuntimeConfig(extensionConfiguration) + ); +}, "resolveRuntimeExtensions"); + +// src/submodules/sso-oidc/SSOOIDCClient.ts +var SSOOIDCClient = class extends import_smithy_client2.Client { + static { + __name(this, "SSOOIDCClient"); + } + /** + * The resolved configuration of SSOOIDCClient class. This is resolved and normalized from the {@link SSOOIDCClientConfig | constructor configuration interface}. + */ + config; + constructor(...[configuration]) { + const _config_0 = (0, import_runtimeConfig.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = resolveClientEndpointParameters(_config_0); + const _config_2 = (0, import_middleware_user_agent.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, import_middleware_retry.resolveRetryConfig)(_config_2); + const _config_4 = (0, import_config_resolver.resolveRegionConfig)(_config_3); + const _config_5 = (0, import_middleware_host_header.resolveHostHeaderConfig)(_config_4); + const _config_6 = (0, import_middleware_endpoint.resolveEndpointConfig)(_config_5); + const _config_7 = (0, import_httpAuthSchemeProvider.resolveHttpAuthSchemeConfig)(_config_6); + const _config_8 = resolveRuntimeExtensions(_config_7, configuration?.extensions || []); + this.config = _config_8; + this.middlewareStack.use((0, import_middleware_user_agent.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_retry.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_content_length.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_host_header.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_logger.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, import_middleware_recursion_detection.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use( + (0, import_core.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: import_httpAuthSchemeProvider.defaultSSOOIDCHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: /* @__PURE__ */ __name(async (config) => new import_core.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials + }), "identityProviderConfigProvider") + }) + ); + this.middlewareStack.use((0, import_core.getHttpSigningPlugin)(this.config)); + } + /** + * Destroy underlying resources, like sockets. It's usually not necessary to do this. + * However in Node.js, it's best to explicitly shut down the client's agent when it is no longer needed. + * Otherwise, sockets might stay open for quite a long time before the server terminates them. + */ + destroy() { + super.destroy(); + } +}; + +// src/submodules/sso-oidc/SSOOIDC.ts +var import_smithy_client7 = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/commands/CreateTokenCommand.ts +var import_middleware_endpoint2 = __nccwpck_require__(40099); +var import_middleware_serde = __nccwpck_require__(83255); +var import_smithy_client6 = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/models/models_0.ts +var import_smithy_client4 = __nccwpck_require__(61411); + +// src/submodules/sso-oidc/models/SSOOIDCServiceException.ts +var import_smithy_client3 = __nccwpck_require__(61411); +var SSOOIDCServiceException = class _SSOOIDCServiceException extends import_smithy_client3.ServiceException { + static { + __name(this, "SSOOIDCServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _SSOOIDCServiceException.prototype); + } +}; + +// src/submodules/sso-oidc/models/models_0.ts +var AccessDeniedException = class _AccessDeniedException extends SSOOIDCServiceException { + static { + __name(this, "AccessDeniedException"); + } + name = "AccessDeniedException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be access_denied.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "AccessDeniedException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _AccessDeniedException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var AuthorizationPendingException = class _AuthorizationPendingException extends SSOOIDCServiceException { + static { + __name(this, "AuthorizationPendingException"); + } + name = "AuthorizationPendingException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * authorization_pending.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "AuthorizationPendingException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _AuthorizationPendingException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var CreateTokenRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.clientSecret && { clientSecret: import_smithy_client4.SENSITIVE_STRING }, + ...obj.refreshToken && { refreshToken: import_smithy_client4.SENSITIVE_STRING }, + ...obj.codeVerifier && { codeVerifier: import_smithy_client4.SENSITIVE_STRING } +}), "CreateTokenRequestFilterSensitiveLog"); +var CreateTokenResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.accessToken && { accessToken: import_smithy_client4.SENSITIVE_STRING }, + ...obj.refreshToken && { refreshToken: import_smithy_client4.SENSITIVE_STRING }, + ...obj.idToken && { idToken: import_smithy_client4.SENSITIVE_STRING } +}), "CreateTokenResponseFilterSensitiveLog"); +var ExpiredTokenException = class _ExpiredTokenException extends SSOOIDCServiceException { + static { + __name(this, "ExpiredTokenException"); + } + name = "ExpiredTokenException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be expired_token.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ExpiredTokenException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ExpiredTokenException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InternalServerException = class _InternalServerException extends SSOOIDCServiceException { + static { + __name(this, "InternalServerException"); + } + name = "InternalServerException"; + $fault = "server"; + /** + *

Single error code. For this exception the value will be server_error.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InternalServerException", + $fault: "server", + ...opts + }); + Object.setPrototypeOf(this, _InternalServerException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidClientException = class _InvalidClientException extends SSOOIDCServiceException { + static { + __name(this, "InvalidClientException"); + } + name = "InvalidClientException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * invalid_client.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidClientException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidClientException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidGrantException = class _InvalidGrantException extends SSOOIDCServiceException { + static { + __name(this, "InvalidGrantException"); + } + name = "InvalidGrantException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be invalid_grant.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidGrantException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidGrantException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidRequestException = class _InvalidRequestException extends SSOOIDCServiceException { + static { + __name(this, "InvalidRequestException"); + } + name = "InvalidRequestException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * invalid_request.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidRequestException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidRequestException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var InvalidScopeException = class _InvalidScopeException extends SSOOIDCServiceException { + static { + __name(this, "InvalidScopeException"); + } + name = "InvalidScopeException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be invalid_scope.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidScopeException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidScopeException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var SlowDownException = class _SlowDownException extends SSOOIDCServiceException { + static { + __name(this, "SlowDownException"); + } + name = "SlowDownException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be slow_down.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "SlowDownException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _SlowDownException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var UnauthorizedClientException = class _UnauthorizedClientException extends SSOOIDCServiceException { + static { + __name(this, "UnauthorizedClientException"); + } + name = "UnauthorizedClientException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * unauthorized_client.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "UnauthorizedClientException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _UnauthorizedClientException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; +var UnsupportedGrantTypeException = class _UnsupportedGrantTypeException extends SSOOIDCServiceException { + static { + __name(this, "UnsupportedGrantTypeException"); + } + name = "UnsupportedGrantTypeException"; + $fault = "client"; + /** + *

Single error code. For this exception the value will be + * unsupported_grant_type.

+ * @public + */ + error; + /** + *

Human-readable text providing additional information, used to assist the client developer + * in understanding the error that occurred.

+ * @public + */ + error_description; + /** + * @internal + */ + constructor(opts) { + super({ + name: "UnsupportedGrantTypeException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _UnsupportedGrantTypeException.prototype); + this.error = opts.error; + this.error_description = opts.error_description; + } +}; + +// src/submodules/sso-oidc/protocols/Aws_restJson1.ts +var import_core2 = __nccwpck_require__(8704); +var import_core3 = __nccwpck_require__(90402); +var import_smithy_client5 = __nccwpck_require__(61411); +var se_CreateTokenCommand = /* @__PURE__ */ __name(async (input, context) => { + const b = (0, import_core3.requestBuilder)(input, context); + const headers = { + "content-type": "application/json" + }; + b.bp("/token"); + let body; + body = JSON.stringify( + (0, import_smithy_client5.take)(input, { + clientId: [], + clientSecret: [], + code: [], + codeVerifier: [], + deviceCode: [], + grantType: [], + redirectUri: [], + refreshToken: [], + scope: /* @__PURE__ */ __name((_) => (0, import_smithy_client5._json)(_), "scope") + }) + ); + b.m("POST").h(headers).b(body); + return b.build(); +}, "se_CreateTokenCommand"); +var de_CreateTokenCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode !== 200 && output.statusCode >= 300) { + return de_CommandError(output, context); + } + const contents = (0, import_smithy_client5.map)({ + $metadata: deserializeMetadata(output) + }); + const data = (0, import_smithy_client5.expectNonNull)((0, import_smithy_client5.expectObject)(await (0, import_core2.parseJsonBody)(output.body, context)), "body"); + const doc = (0, import_smithy_client5.take)(data, { + accessToken: import_smithy_client5.expectString, + expiresIn: import_smithy_client5.expectInt32, + idToken: import_smithy_client5.expectString, + refreshToken: import_smithy_client5.expectString, + tokenType: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + return contents; +}, "de_CreateTokenCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core2.parseJsonErrorBody)(output.body, context) + }; + const errorCode = (0, import_core2.loadRestJsonErrorCode)(output, parsedOutput.body); + switch (errorCode) { + case "AccessDeniedException": + case "com.amazonaws.ssooidc#AccessDeniedException": + throw await de_AccessDeniedExceptionRes(parsedOutput, context); + case "AuthorizationPendingException": + case "com.amazonaws.ssooidc#AuthorizationPendingException": + throw await de_AuthorizationPendingExceptionRes(parsedOutput, context); + case "ExpiredTokenException": + case "com.amazonaws.ssooidc#ExpiredTokenException": + throw await de_ExpiredTokenExceptionRes(parsedOutput, context); + case "InternalServerException": + case "com.amazonaws.ssooidc#InternalServerException": + throw await de_InternalServerExceptionRes(parsedOutput, context); + case "InvalidClientException": + case "com.amazonaws.ssooidc#InvalidClientException": + throw await de_InvalidClientExceptionRes(parsedOutput, context); + case "InvalidGrantException": + case "com.amazonaws.ssooidc#InvalidGrantException": + throw await de_InvalidGrantExceptionRes(parsedOutput, context); + case "InvalidRequestException": + case "com.amazonaws.ssooidc#InvalidRequestException": + throw await de_InvalidRequestExceptionRes(parsedOutput, context); + case "InvalidScopeException": + case "com.amazonaws.ssooidc#InvalidScopeException": + throw await de_InvalidScopeExceptionRes(parsedOutput, context); + case "SlowDownException": + case "com.amazonaws.ssooidc#SlowDownException": + throw await de_SlowDownExceptionRes(parsedOutput, context); + case "UnauthorizedClientException": + case "com.amazonaws.ssooidc#UnauthorizedClientException": + throw await de_UnauthorizedClientExceptionRes(parsedOutput, context); + case "UnsupportedGrantTypeException": + case "com.amazonaws.ssooidc#UnsupportedGrantTypeException": + throw await de_UnsupportedGrantTypeExceptionRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody, + errorCode + }); + } +}, "de_CommandError"); +var throwDefaultError = (0, import_smithy_client5.withBaseException)(SSOOIDCServiceException); +var de_AccessDeniedExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new AccessDeniedException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_AccessDeniedExceptionRes"); +var de_AuthorizationPendingExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new AuthorizationPendingException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_AuthorizationPendingExceptionRes"); +var de_ExpiredTokenExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new ExpiredTokenException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_ExpiredTokenExceptionRes"); +var de_InternalServerExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InternalServerException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InternalServerExceptionRes"); +var de_InvalidClientExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidClientException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidClientExceptionRes"); +var de_InvalidGrantExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidGrantException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidGrantExceptionRes"); +var de_InvalidRequestExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidRequestException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidRequestExceptionRes"); +var de_InvalidScopeExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new InvalidScopeException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_InvalidScopeExceptionRes"); +var de_SlowDownExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new SlowDownException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_SlowDownExceptionRes"); +var de_UnauthorizedClientExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new UnauthorizedClientException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_UnauthorizedClientExceptionRes"); +var de_UnsupportedGrantTypeExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const contents = (0, import_smithy_client5.map)({}); + const data = parsedOutput.body; + const doc = (0, import_smithy_client5.take)(data, { + error: import_smithy_client5.expectString, + error_description: import_smithy_client5.expectString + }); + Object.assign(contents, doc); + const exception = new UnsupportedGrantTypeException({ + $metadata: deserializeMetadata(parsedOutput), + ...contents + }); + return (0, import_smithy_client5.decorateServiceException)(exception, parsedOutput.body); +}, "de_UnsupportedGrantTypeExceptionRes"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); + +// src/submodules/sso-oidc/commands/CreateTokenCommand.ts +var CreateTokenCommand = class extends import_smithy_client6.Command.classBuilder().ep(commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint2.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AWSSSOOIDCService", "CreateToken", {}).n("SSOOIDCClient", "CreateTokenCommand").f(CreateTokenRequestFilterSensitiveLog, CreateTokenResponseFilterSensitiveLog).ser(se_CreateTokenCommand).de(de_CreateTokenCommand).build() { + static { + __name(this, "CreateTokenCommand"); + } +}; + +// src/submodules/sso-oidc/SSOOIDC.ts +var commands = { + CreateTokenCommand +}; +var SSOOIDC = class extends SSOOIDCClient { + static { + __name(this, "SSOOIDC"); + } +}; +(0, import_smithy_client7.createAggregatedClient)(commands, SSOOIDC); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 16901: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(39955)); +const core_1 = __nccwpck_require__(8704); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const hash_node_1 = __nccwpck_require__(5092); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(1546); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 1546: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const core_2 = __nccwpck_require__(90402); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(8396); +const endpointResolver_1 = __nccwpck_require__(90546); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2019-06-10", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSSOOIDCHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + serviceId: config?.serviceId ?? "SSO OIDC", + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 63723: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.STSClient = exports.__Client = void 0; +const middleware_host_header_1 = __nccwpck_require__(52590); +const middleware_logger_1 = __nccwpck_require__(85242); +const middleware_recursion_detection_1 = __nccwpck_require__(81568); +const middleware_user_agent_1 = __nccwpck_require__(32959); +const config_resolver_1 = __nccwpck_require__(39316); +const core_1 = __nccwpck_require__(90402); +const middleware_content_length_1 = __nccwpck_require__(47212); +const middleware_endpoint_1 = __nccwpck_require__(40099); +const middleware_retry_1 = __nccwpck_require__(19618); +const smithy_client_1 = __nccwpck_require__(61411); +Object.defineProperty(exports, "__Client", ({ enumerable: true, get: function () { return smithy_client_1.Client; } })); +const httpAuthSchemeProvider_1 = __nccwpck_require__(27851); +const EndpointParameters_1 = __nccwpck_require__(76811); +const runtimeConfig_1 = __nccwpck_require__(36578); +const runtimeExtensions_1 = __nccwpck_require__(37742); +class STSClient extends smithy_client_1.Client { + config; + constructor(...[configuration]) { + const _config_0 = (0, runtimeConfig_1.getRuntimeConfig)(configuration || {}); + super(_config_0); + this.initConfig = _config_0; + const _config_1 = (0, EndpointParameters_1.resolveClientEndpointParameters)(_config_0); + const _config_2 = (0, middleware_user_agent_1.resolveUserAgentConfig)(_config_1); + const _config_3 = (0, middleware_retry_1.resolveRetryConfig)(_config_2); + const _config_4 = (0, config_resolver_1.resolveRegionConfig)(_config_3); + const _config_5 = (0, middleware_host_header_1.resolveHostHeaderConfig)(_config_4); + const _config_6 = (0, middleware_endpoint_1.resolveEndpointConfig)(_config_5); + const _config_7 = (0, httpAuthSchemeProvider_1.resolveHttpAuthSchemeConfig)(_config_6); + const _config_8 = (0, runtimeExtensions_1.resolveRuntimeExtensions)(_config_7, configuration?.extensions || []); + this.config = _config_8; + this.middlewareStack.use((0, middleware_user_agent_1.getUserAgentPlugin)(this.config)); + this.middlewareStack.use((0, middleware_retry_1.getRetryPlugin)(this.config)); + this.middlewareStack.use((0, middleware_content_length_1.getContentLengthPlugin)(this.config)); + this.middlewareStack.use((0, middleware_host_header_1.getHostHeaderPlugin)(this.config)); + this.middlewareStack.use((0, middleware_logger_1.getLoggerPlugin)(this.config)); + this.middlewareStack.use((0, middleware_recursion_detection_1.getRecursionDetectionPlugin)(this.config)); + this.middlewareStack.use((0, core_1.getHttpAuthSchemeEndpointRuleSetPlugin)(this.config, { + httpAuthSchemeParametersProvider: httpAuthSchemeProvider_1.defaultSTSHttpAuthSchemeParametersProvider, + identityProviderConfigProvider: async (config) => new core_1.DefaultIdentityProviderConfig({ + "aws.auth#sigv4": config.credentials, + }), + })); + this.middlewareStack.use((0, core_1.getHttpSigningPlugin)(this.config)); + } + destroy() { + super.destroy(); + } +} +exports.STSClient = STSClient; + + +/***/ }), + +/***/ 34532: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthRuntimeConfig = exports.getHttpAuthExtensionConfiguration = void 0; +const getHttpAuthExtensionConfiguration = (runtimeConfig) => { + const _httpAuthSchemes = runtimeConfig.httpAuthSchemes; + let _httpAuthSchemeProvider = runtimeConfig.httpAuthSchemeProvider; + let _credentials = runtimeConfig.credentials; + return { + setHttpAuthScheme(httpAuthScheme) { + const index = _httpAuthSchemes.findIndex((scheme) => scheme.schemeId === httpAuthScheme.schemeId); + if (index === -1) { + _httpAuthSchemes.push(httpAuthScheme); + } + else { + _httpAuthSchemes.splice(index, 1, httpAuthScheme); + } + }, + httpAuthSchemes() { + return _httpAuthSchemes; + }, + setHttpAuthSchemeProvider(httpAuthSchemeProvider) { + _httpAuthSchemeProvider = httpAuthSchemeProvider; + }, + httpAuthSchemeProvider() { + return _httpAuthSchemeProvider; + }, + setCredentials(credentials) { + _credentials = credentials; + }, + credentials() { + return _credentials; + }, + }; +}; +exports.getHttpAuthExtensionConfiguration = getHttpAuthExtensionConfiguration; +const resolveHttpAuthRuntimeConfig = (config) => { + return { + httpAuthSchemes: config.httpAuthSchemes(), + httpAuthSchemeProvider: config.httpAuthSchemeProvider(), + credentials: config.credentials(), + }; +}; +exports.resolveHttpAuthRuntimeConfig = resolveHttpAuthRuntimeConfig; + + +/***/ }), + +/***/ 27851: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveHttpAuthSchemeConfig = exports.resolveStsAuthConfig = exports.defaultSTSHttpAuthSchemeProvider = exports.defaultSTSHttpAuthSchemeParametersProvider = void 0; +const core_1 = __nccwpck_require__(8704); +const util_middleware_1 = __nccwpck_require__(76324); +const STSClient_1 = __nccwpck_require__(63723); +const defaultSTSHttpAuthSchemeParametersProvider = async (config, context, input) => { + return { + operation: (0, util_middleware_1.getSmithyContext)(context).operation, + region: (await (0, util_middleware_1.normalizeProvider)(config.region)()) || + (() => { + throw new Error("expected `region` to be configured for `aws.auth#sigv4`"); + })(), + }; +}; +exports.defaultSTSHttpAuthSchemeParametersProvider = defaultSTSHttpAuthSchemeParametersProvider; +function createAwsAuthSigv4HttpAuthOption(authParameters) { + return { + schemeId: "aws.auth#sigv4", + signingProperties: { + name: "sts", + region: authParameters.region, + }, + propertiesExtractor: (config, context) => ({ + signingProperties: { + config, + context, + }, + }), + }; +} +function createSmithyApiNoAuthHttpAuthOption(authParameters) { + return { + schemeId: "smithy.api#noAuth", + }; +} +const defaultSTSHttpAuthSchemeProvider = (authParameters) => { + const options = []; + switch (authParameters.operation) { + case "AssumeRoleWithWebIdentity": { + options.push(createSmithyApiNoAuthHttpAuthOption(authParameters)); + break; + } + default: { + options.push(createAwsAuthSigv4HttpAuthOption(authParameters)); + } + } + return options; +}; +exports.defaultSTSHttpAuthSchemeProvider = defaultSTSHttpAuthSchemeProvider; +const resolveStsAuthConfig = (input) => Object.assign(input, { + stsClientCtor: STSClient_1.STSClient, +}); +exports.resolveStsAuthConfig = resolveStsAuthConfig; +const resolveHttpAuthSchemeConfig = (config) => { + const config_0 = (0, exports.resolveStsAuthConfig)(config); + const config_1 = (0, core_1.resolveAwsSdkSigV4Config)(config_0); + return Object.assign(config_1, { + authSchemePreference: (0, util_middleware_1.normalizeProvider)(config.authSchemePreference ?? []), + }); +}; +exports.resolveHttpAuthSchemeConfig = resolveHttpAuthSchemeConfig; + + +/***/ }), + +/***/ 76811: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.commonParams = exports.resolveClientEndpointParameters = void 0; +const resolveClientEndpointParameters = (options) => { + return Object.assign(options, { + useDualstackEndpoint: options.useDualstackEndpoint ?? false, + useFipsEndpoint: options.useFipsEndpoint ?? false, + useGlobalEndpoint: options.useGlobalEndpoint ?? false, + defaultSigningName: "sts", + }); +}; +exports.resolveClientEndpointParameters = resolveClientEndpointParameters; +exports.commonParams = { + UseGlobalEndpoint: { type: "builtInParams", name: "useGlobalEndpoint" }, + UseFIPS: { type: "builtInParams", name: "useFipsEndpoint" }, + Endpoint: { type: "builtInParams", name: "endpoint" }, + Region: { type: "builtInParams", name: "region" }, + UseDualStack: { type: "builtInParams", name: "useDualstackEndpoint" }, +}; + + +/***/ }), + +/***/ 59765: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.defaultEndpointResolver = void 0; +const util_endpoints_1 = __nccwpck_require__(83068); +const util_endpoints_2 = __nccwpck_require__(79674); +const ruleset_1 = __nccwpck_require__(31670); +const cache = new util_endpoints_2.EndpointCache({ + size: 50, + params: ["Endpoint", "Region", "UseDualStack", "UseFIPS", "UseGlobalEndpoint"], +}); +const defaultEndpointResolver = (endpointParams, context = {}) => { + return cache.get(endpointParams, () => (0, util_endpoints_2.resolveEndpoint)(ruleset_1.ruleSet, { + endpointParams: endpointParams, + logger: context.logger, + })); +}; +exports.defaultEndpointResolver = defaultEndpointResolver; +util_endpoints_2.customEndpointFunctions.aws = util_endpoints_1.awsEndpointFunctions; + + +/***/ }), + +/***/ 31670: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ruleSet = void 0; +const F = "required", G = "type", H = "fn", I = "argv", J = "ref"; +const a = false, b = true, c = "booleanEquals", d = "stringEquals", e = "sigv4", f = "sts", g = "us-east-1", h = "endpoint", i = "https://sts.{Region}.{PartitionResult#dnsSuffix}", j = "tree", k = "error", l = "getAttr", m = { [F]: false, [G]: "String" }, n = { [F]: true, "default": false, [G]: "Boolean" }, o = { [J]: "Endpoint" }, p = { [H]: "isSet", [I]: [{ [J]: "Region" }] }, q = { [J]: "Region" }, r = { [H]: "aws.partition", [I]: [q], "assign": "PartitionResult" }, s = { [J]: "UseFIPS" }, t = { [J]: "UseDualStack" }, u = { "url": "https://sts.amazonaws.com", "properties": { "authSchemes": [{ "name": e, "signingName": f, "signingRegion": g }] }, "headers": {} }, v = {}, w = { "conditions": [{ [H]: d, [I]: [q, "aws-global"] }], [h]: u, [G]: h }, x = { [H]: c, [I]: [s, true] }, y = { [H]: c, [I]: [t, true] }, z = { [H]: l, [I]: [{ [J]: "PartitionResult" }, "supportsFIPS"] }, A = { [J]: "PartitionResult" }, B = { [H]: c, [I]: [true, { [H]: l, [I]: [A, "supportsDualStack"] }] }, C = [{ [H]: "isSet", [I]: [o] }], D = [x], E = [y]; +const _data = { version: "1.0", parameters: { Region: m, UseDualStack: n, UseFIPS: n, Endpoint: m, UseGlobalEndpoint: n }, rules: [{ conditions: [{ [H]: c, [I]: [{ [J]: "UseGlobalEndpoint" }, b] }, { [H]: "not", [I]: C }, p, r, { [H]: c, [I]: [s, a] }, { [H]: c, [I]: [t, a] }], rules: [{ conditions: [{ [H]: d, [I]: [q, "ap-northeast-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-south-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-southeast-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "ap-southeast-2"] }], endpoint: u, [G]: h }, w, { conditions: [{ [H]: d, [I]: [q, "ca-central-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-central-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-north-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-2"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "eu-west-3"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "sa-east-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, g] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-east-2"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-west-1"] }], endpoint: u, [G]: h }, { conditions: [{ [H]: d, [I]: [q, "us-west-2"] }], endpoint: u, [G]: h }, { endpoint: { url: i, properties: { authSchemes: [{ name: e, signingName: f, signingRegion: "{Region}" }] }, headers: v }, [G]: h }], [G]: j }, { conditions: C, rules: [{ conditions: D, error: "Invalid Configuration: FIPS and custom endpoint are not supported", [G]: k }, { conditions: E, error: "Invalid Configuration: Dualstack and custom endpoint are not supported", [G]: k }, { endpoint: { url: o, properties: v, headers: v }, [G]: h }], [G]: j }, { conditions: [p], rules: [{ conditions: [r], rules: [{ conditions: [x, y], rules: [{ conditions: [{ [H]: c, [I]: [b, z] }, B], rules: [{ endpoint: { url: "https://sts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "FIPS and DualStack are enabled, but this partition does not support one or both", [G]: k }], [G]: j }, { conditions: D, rules: [{ conditions: [{ [H]: c, [I]: [z, b] }], rules: [{ conditions: [{ [H]: d, [I]: [{ [H]: l, [I]: [A, "name"] }, "aws-us-gov"] }], endpoint: { url: "https://sts.{Region}.amazonaws.com", properties: v, headers: v }, [G]: h }, { endpoint: { url: "https://sts-fips.{Region}.{PartitionResult#dnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "FIPS is enabled but this partition does not support FIPS", [G]: k }], [G]: j }, { conditions: E, rules: [{ conditions: [B], rules: [{ endpoint: { url: "https://sts.{Region}.{PartitionResult#dualStackDnsSuffix}", properties: v, headers: v }, [G]: h }], [G]: j }, { error: "DualStack is enabled but this partition does not support DualStack", [G]: k }], [G]: j }, w, { endpoint: { url: i, properties: v, headers: v }, [G]: h }], [G]: j }], [G]: j }, { error: "Invalid Configuration: Missing Region", [G]: k }] }; +exports.ruleSet = _data; + + +/***/ }), + +/***/ 1136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/sts/index.ts +var index_exports = {}; +__export(index_exports, { + AssumeRoleCommand: () => AssumeRoleCommand, + AssumeRoleResponseFilterSensitiveLog: () => AssumeRoleResponseFilterSensitiveLog, + AssumeRoleWithWebIdentityCommand: () => AssumeRoleWithWebIdentityCommand, + AssumeRoleWithWebIdentityRequestFilterSensitiveLog: () => AssumeRoleWithWebIdentityRequestFilterSensitiveLog, + AssumeRoleWithWebIdentityResponseFilterSensitiveLog: () => AssumeRoleWithWebIdentityResponseFilterSensitiveLog, + ClientInputEndpointParameters: () => import_EndpointParameters3.ClientInputEndpointParameters, + CredentialsFilterSensitiveLog: () => CredentialsFilterSensitiveLog, + ExpiredTokenException: () => ExpiredTokenException, + IDPCommunicationErrorException: () => IDPCommunicationErrorException, + IDPRejectedClaimException: () => IDPRejectedClaimException, + InvalidIdentityTokenException: () => InvalidIdentityTokenException, + MalformedPolicyDocumentException: () => MalformedPolicyDocumentException, + PackedPolicyTooLargeException: () => PackedPolicyTooLargeException, + RegionDisabledException: () => RegionDisabledException, + STS: () => STS, + STSServiceException: () => STSServiceException, + decorateDefaultCredentialProvider: () => decorateDefaultCredentialProvider, + getDefaultRoleAssumer: () => getDefaultRoleAssumer2, + getDefaultRoleAssumerWithWebIdentity: () => getDefaultRoleAssumerWithWebIdentity2 +}); +module.exports = __toCommonJS(index_exports); +__reExport(index_exports, __nccwpck_require__(63723), module.exports); + +// src/submodules/sts/STS.ts +var import_smithy_client6 = __nccwpck_require__(61411); + +// src/submodules/sts/commands/AssumeRoleCommand.ts +var import_middleware_endpoint = __nccwpck_require__(40099); +var import_middleware_serde = __nccwpck_require__(83255); +var import_smithy_client4 = __nccwpck_require__(61411); +var import_EndpointParameters = __nccwpck_require__(76811); + +// src/submodules/sts/models/models_0.ts +var import_smithy_client2 = __nccwpck_require__(61411); + +// src/submodules/sts/models/STSServiceException.ts +var import_smithy_client = __nccwpck_require__(61411); +var STSServiceException = class _STSServiceException extends import_smithy_client.ServiceException { + static { + __name(this, "STSServiceException"); + } + /** + * @internal + */ + constructor(options) { + super(options); + Object.setPrototypeOf(this, _STSServiceException.prototype); + } +}; + +// src/submodules/sts/models/models_0.ts +var CredentialsFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.SecretAccessKey && { SecretAccessKey: import_smithy_client2.SENSITIVE_STRING } +}), "CredentialsFilterSensitiveLog"); +var AssumeRoleResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Credentials && { Credentials: CredentialsFilterSensitiveLog(obj.Credentials) } +}), "AssumeRoleResponseFilterSensitiveLog"); +var ExpiredTokenException = class _ExpiredTokenException extends STSServiceException { + static { + __name(this, "ExpiredTokenException"); + } + name = "ExpiredTokenException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "ExpiredTokenException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _ExpiredTokenException.prototype); + } +}; +var MalformedPolicyDocumentException = class _MalformedPolicyDocumentException extends STSServiceException { + static { + __name(this, "MalformedPolicyDocumentException"); + } + name = "MalformedPolicyDocumentException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "MalformedPolicyDocumentException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _MalformedPolicyDocumentException.prototype); + } +}; +var PackedPolicyTooLargeException = class _PackedPolicyTooLargeException extends STSServiceException { + static { + __name(this, "PackedPolicyTooLargeException"); + } + name = "PackedPolicyTooLargeException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "PackedPolicyTooLargeException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _PackedPolicyTooLargeException.prototype); + } +}; +var RegionDisabledException = class _RegionDisabledException extends STSServiceException { + static { + __name(this, "RegionDisabledException"); + } + name = "RegionDisabledException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "RegionDisabledException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _RegionDisabledException.prototype); + } +}; +var IDPRejectedClaimException = class _IDPRejectedClaimException extends STSServiceException { + static { + __name(this, "IDPRejectedClaimException"); + } + name = "IDPRejectedClaimException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "IDPRejectedClaimException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _IDPRejectedClaimException.prototype); + } +}; +var InvalidIdentityTokenException = class _InvalidIdentityTokenException extends STSServiceException { + static { + __name(this, "InvalidIdentityTokenException"); + } + name = "InvalidIdentityTokenException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "InvalidIdentityTokenException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _InvalidIdentityTokenException.prototype); + } +}; +var AssumeRoleWithWebIdentityRequestFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.WebIdentityToken && { WebIdentityToken: import_smithy_client2.SENSITIVE_STRING } +}), "AssumeRoleWithWebIdentityRequestFilterSensitiveLog"); +var AssumeRoleWithWebIdentityResponseFilterSensitiveLog = /* @__PURE__ */ __name((obj) => ({ + ...obj, + ...obj.Credentials && { Credentials: CredentialsFilterSensitiveLog(obj.Credentials) } +}), "AssumeRoleWithWebIdentityResponseFilterSensitiveLog"); +var IDPCommunicationErrorException = class _IDPCommunicationErrorException extends STSServiceException { + static { + __name(this, "IDPCommunicationErrorException"); + } + name = "IDPCommunicationErrorException"; + $fault = "client"; + /** + * @internal + */ + constructor(opts) { + super({ + name: "IDPCommunicationErrorException", + $fault: "client", + ...opts + }); + Object.setPrototypeOf(this, _IDPCommunicationErrorException.prototype); + } +}; + +// src/submodules/sts/protocols/Aws_query.ts +var import_core = __nccwpck_require__(8704); +var import_protocol_http = __nccwpck_require__(72356); +var import_smithy_client3 = __nccwpck_require__(61411); +var se_AssumeRoleCommand = /* @__PURE__ */ __name(async (input, context) => { + const headers = SHARED_HEADERS; + let body; + body = buildFormUrlencodedString({ + ...se_AssumeRoleRequest(input, context), + [_A]: _AR, + [_V]: _ + }); + return buildHttpRpcRequest(context, headers, "/", void 0, body); +}, "se_AssumeRoleCommand"); +var se_AssumeRoleWithWebIdentityCommand = /* @__PURE__ */ __name(async (input, context) => { + const headers = SHARED_HEADERS; + let body; + body = buildFormUrlencodedString({ + ...se_AssumeRoleWithWebIdentityRequest(input, context), + [_A]: _ARWWI, + [_V]: _ + }); + return buildHttpRpcRequest(context, headers, "/", void 0, body); +}, "se_AssumeRoleWithWebIdentityCommand"); +var de_AssumeRoleCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + const data = await (0, import_core.parseXmlBody)(output.body, context); + let contents = {}; + contents = de_AssumeRoleResponse(data.AssumeRoleResult, context); + const response = { + $metadata: deserializeMetadata(output), + ...contents + }; + return response; +}, "de_AssumeRoleCommand"); +var de_AssumeRoleWithWebIdentityCommand = /* @__PURE__ */ __name(async (output, context) => { + if (output.statusCode >= 300) { + return de_CommandError(output, context); + } + const data = await (0, import_core.parseXmlBody)(output.body, context); + let contents = {}; + contents = de_AssumeRoleWithWebIdentityResponse(data.AssumeRoleWithWebIdentityResult, context); + const response = { + $metadata: deserializeMetadata(output), + ...contents + }; + return response; +}, "de_AssumeRoleWithWebIdentityCommand"); +var de_CommandError = /* @__PURE__ */ __name(async (output, context) => { + const parsedOutput = { + ...output, + body: await (0, import_core.parseXmlErrorBody)(output.body, context) + }; + const errorCode = loadQueryErrorCode(output, parsedOutput.body); + switch (errorCode) { + case "ExpiredTokenException": + case "com.amazonaws.sts#ExpiredTokenException": + throw await de_ExpiredTokenExceptionRes(parsedOutput, context); + case "MalformedPolicyDocument": + case "com.amazonaws.sts#MalformedPolicyDocumentException": + throw await de_MalformedPolicyDocumentExceptionRes(parsedOutput, context); + case "PackedPolicyTooLarge": + case "com.amazonaws.sts#PackedPolicyTooLargeException": + throw await de_PackedPolicyTooLargeExceptionRes(parsedOutput, context); + case "RegionDisabledException": + case "com.amazonaws.sts#RegionDisabledException": + throw await de_RegionDisabledExceptionRes(parsedOutput, context); + case "IDPCommunicationError": + case "com.amazonaws.sts#IDPCommunicationErrorException": + throw await de_IDPCommunicationErrorExceptionRes(parsedOutput, context); + case "IDPRejectedClaim": + case "com.amazonaws.sts#IDPRejectedClaimException": + throw await de_IDPRejectedClaimExceptionRes(parsedOutput, context); + case "InvalidIdentityToken": + case "com.amazonaws.sts#InvalidIdentityTokenException": + throw await de_InvalidIdentityTokenExceptionRes(parsedOutput, context); + default: + const parsedBody = parsedOutput.body; + return throwDefaultError({ + output, + parsedBody: parsedBody.Error, + errorCode + }); + } +}, "de_CommandError"); +var de_ExpiredTokenExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_ExpiredTokenException(body.Error, context); + const exception = new ExpiredTokenException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_ExpiredTokenExceptionRes"); +var de_IDPCommunicationErrorExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_IDPCommunicationErrorException(body.Error, context); + const exception = new IDPCommunicationErrorException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_IDPCommunicationErrorExceptionRes"); +var de_IDPRejectedClaimExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_IDPRejectedClaimException(body.Error, context); + const exception = new IDPRejectedClaimException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_IDPRejectedClaimExceptionRes"); +var de_InvalidIdentityTokenExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_InvalidIdentityTokenException(body.Error, context); + const exception = new InvalidIdentityTokenException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_InvalidIdentityTokenExceptionRes"); +var de_MalformedPolicyDocumentExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_MalformedPolicyDocumentException(body.Error, context); + const exception = new MalformedPolicyDocumentException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_MalformedPolicyDocumentExceptionRes"); +var de_PackedPolicyTooLargeExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_PackedPolicyTooLargeException(body.Error, context); + const exception = new PackedPolicyTooLargeException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_PackedPolicyTooLargeExceptionRes"); +var de_RegionDisabledExceptionRes = /* @__PURE__ */ __name(async (parsedOutput, context) => { + const body = parsedOutput.body; + const deserialized = de_RegionDisabledException(body.Error, context); + const exception = new RegionDisabledException({ + $metadata: deserializeMetadata(parsedOutput), + ...deserialized + }); + return (0, import_smithy_client3.decorateServiceException)(exception, body); +}, "de_RegionDisabledExceptionRes"); +var se_AssumeRoleRequest = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_RA] != null) { + entries[_RA] = input[_RA]; + } + if (input[_RSN] != null) { + entries[_RSN] = input[_RSN]; + } + if (input[_PA] != null) { + const memberEntries = se_policyDescriptorListType(input[_PA], context); + if (input[_PA]?.length === 0) { + entries.PolicyArns = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `PolicyArns.${key}`; + entries[loc] = value; + }); + } + if (input[_P] != null) { + entries[_P] = input[_P]; + } + if (input[_DS] != null) { + entries[_DS] = input[_DS]; + } + if (input[_T] != null) { + const memberEntries = se_tagListType(input[_T], context); + if (input[_T]?.length === 0) { + entries.Tags = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `Tags.${key}`; + entries[loc] = value; + }); + } + if (input[_TTK] != null) { + const memberEntries = se_tagKeyListType(input[_TTK], context); + if (input[_TTK]?.length === 0) { + entries.TransitiveTagKeys = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `TransitiveTagKeys.${key}`; + entries[loc] = value; + }); + } + if (input[_EI] != null) { + entries[_EI] = input[_EI]; + } + if (input[_SN] != null) { + entries[_SN] = input[_SN]; + } + if (input[_TC] != null) { + entries[_TC] = input[_TC]; + } + if (input[_SI] != null) { + entries[_SI] = input[_SI]; + } + if (input[_PC] != null) { + const memberEntries = se_ProvidedContextsListType(input[_PC], context); + if (input[_PC]?.length === 0) { + entries.ProvidedContexts = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `ProvidedContexts.${key}`; + entries[loc] = value; + }); + } + return entries; +}, "se_AssumeRoleRequest"); +var se_AssumeRoleWithWebIdentityRequest = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_RA] != null) { + entries[_RA] = input[_RA]; + } + if (input[_RSN] != null) { + entries[_RSN] = input[_RSN]; + } + if (input[_WIT] != null) { + entries[_WIT] = input[_WIT]; + } + if (input[_PI] != null) { + entries[_PI] = input[_PI]; + } + if (input[_PA] != null) { + const memberEntries = se_policyDescriptorListType(input[_PA], context); + if (input[_PA]?.length === 0) { + entries.PolicyArns = []; + } + Object.entries(memberEntries).forEach(([key, value]) => { + const loc = `PolicyArns.${key}`; + entries[loc] = value; + }); + } + if (input[_P] != null) { + entries[_P] = input[_P]; + } + if (input[_DS] != null) { + entries[_DS] = input[_DS]; + } + return entries; +}, "se_AssumeRoleWithWebIdentityRequest"); +var se_policyDescriptorListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + const memberEntries = se_PolicyDescriptorType(entry, context); + Object.entries(memberEntries).forEach(([key, value]) => { + entries[`member.${counter}.${key}`] = value; + }); + counter++; + } + return entries; +}, "se_policyDescriptorListType"); +var se_PolicyDescriptorType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_a] != null) { + entries[_a] = input[_a]; + } + return entries; +}, "se_PolicyDescriptorType"); +var se_ProvidedContext = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_PAr] != null) { + entries[_PAr] = input[_PAr]; + } + if (input[_CA] != null) { + entries[_CA] = input[_CA]; + } + return entries; +}, "se_ProvidedContext"); +var se_ProvidedContextsListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + const memberEntries = se_ProvidedContext(entry, context); + Object.entries(memberEntries).forEach(([key, value]) => { + entries[`member.${counter}.${key}`] = value; + }); + counter++; + } + return entries; +}, "se_ProvidedContextsListType"); +var se_Tag = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + if (input[_K] != null) { + entries[_K] = input[_K]; + } + if (input[_Va] != null) { + entries[_Va] = input[_Va]; + } + return entries; +}, "se_Tag"); +var se_tagKeyListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + entries[`member.${counter}`] = entry; + counter++; + } + return entries; +}, "se_tagKeyListType"); +var se_tagListType = /* @__PURE__ */ __name((input, context) => { + const entries = {}; + let counter = 1; + for (const entry of input) { + if (entry === null) { + continue; + } + const memberEntries = se_Tag(entry, context); + Object.entries(memberEntries).forEach(([key, value]) => { + entries[`member.${counter}.${key}`] = value; + }); + counter++; + } + return entries; +}, "se_tagListType"); +var de_AssumedRoleUser = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_ARI] != null) { + contents[_ARI] = (0, import_smithy_client3.expectString)(output[_ARI]); + } + if (output[_Ar] != null) { + contents[_Ar] = (0, import_smithy_client3.expectString)(output[_Ar]); + } + return contents; +}, "de_AssumedRoleUser"); +var de_AssumeRoleResponse = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_C] != null) { + contents[_C] = de_Credentials(output[_C], context); + } + if (output[_ARU] != null) { + contents[_ARU] = de_AssumedRoleUser(output[_ARU], context); + } + if (output[_PPS] != null) { + contents[_PPS] = (0, import_smithy_client3.strictParseInt32)(output[_PPS]); + } + if (output[_SI] != null) { + contents[_SI] = (0, import_smithy_client3.expectString)(output[_SI]); + } + return contents; +}, "de_AssumeRoleResponse"); +var de_AssumeRoleWithWebIdentityResponse = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_C] != null) { + contents[_C] = de_Credentials(output[_C], context); + } + if (output[_SFWIT] != null) { + contents[_SFWIT] = (0, import_smithy_client3.expectString)(output[_SFWIT]); + } + if (output[_ARU] != null) { + contents[_ARU] = de_AssumedRoleUser(output[_ARU], context); + } + if (output[_PPS] != null) { + contents[_PPS] = (0, import_smithy_client3.strictParseInt32)(output[_PPS]); + } + if (output[_Pr] != null) { + contents[_Pr] = (0, import_smithy_client3.expectString)(output[_Pr]); + } + if (output[_Au] != null) { + contents[_Au] = (0, import_smithy_client3.expectString)(output[_Au]); + } + if (output[_SI] != null) { + contents[_SI] = (0, import_smithy_client3.expectString)(output[_SI]); + } + return contents; +}, "de_AssumeRoleWithWebIdentityResponse"); +var de_Credentials = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_AKI] != null) { + contents[_AKI] = (0, import_smithy_client3.expectString)(output[_AKI]); + } + if (output[_SAK] != null) { + contents[_SAK] = (0, import_smithy_client3.expectString)(output[_SAK]); + } + if (output[_ST] != null) { + contents[_ST] = (0, import_smithy_client3.expectString)(output[_ST]); + } + if (output[_E] != null) { + contents[_E] = (0, import_smithy_client3.expectNonNull)((0, import_smithy_client3.parseRfc3339DateTimeWithOffset)(output[_E])); + } + return contents; +}, "de_Credentials"); +var de_ExpiredTokenException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_ExpiredTokenException"); +var de_IDPCommunicationErrorException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_IDPCommunicationErrorException"); +var de_IDPRejectedClaimException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_IDPRejectedClaimException"); +var de_InvalidIdentityTokenException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_InvalidIdentityTokenException"); +var de_MalformedPolicyDocumentException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_MalformedPolicyDocumentException"); +var de_PackedPolicyTooLargeException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_PackedPolicyTooLargeException"); +var de_RegionDisabledException = /* @__PURE__ */ __name((output, context) => { + const contents = {}; + if (output[_m] != null) { + contents[_m] = (0, import_smithy_client3.expectString)(output[_m]); + } + return contents; +}, "de_RegionDisabledException"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); +var throwDefaultError = (0, import_smithy_client3.withBaseException)(STSServiceException); +var buildHttpRpcRequest = /* @__PURE__ */ __name(async (context, headers, path, resolvedHostname, body) => { + const { hostname, protocol = "https", port, path: basePath } = await context.endpoint(); + const contents = { + protocol, + hostname, + port, + method: "POST", + path: basePath.endsWith("/") ? basePath.slice(0, -1) + path : basePath + path, + headers + }; + if (resolvedHostname !== void 0) { + contents.hostname = resolvedHostname; + } + if (body !== void 0) { + contents.body = body; + } + return new import_protocol_http.HttpRequest(contents); +}, "buildHttpRpcRequest"); +var SHARED_HEADERS = { + "content-type": "application/x-www-form-urlencoded" +}; +var _ = "2011-06-15"; +var _A = "Action"; +var _AKI = "AccessKeyId"; +var _AR = "AssumeRole"; +var _ARI = "AssumedRoleId"; +var _ARU = "AssumedRoleUser"; +var _ARWWI = "AssumeRoleWithWebIdentity"; +var _Ar = "Arn"; +var _Au = "Audience"; +var _C = "Credentials"; +var _CA = "ContextAssertion"; +var _DS = "DurationSeconds"; +var _E = "Expiration"; +var _EI = "ExternalId"; +var _K = "Key"; +var _P = "Policy"; +var _PA = "PolicyArns"; +var _PAr = "ProviderArn"; +var _PC = "ProvidedContexts"; +var _PI = "ProviderId"; +var _PPS = "PackedPolicySize"; +var _Pr = "Provider"; +var _RA = "RoleArn"; +var _RSN = "RoleSessionName"; +var _SAK = "SecretAccessKey"; +var _SFWIT = "SubjectFromWebIdentityToken"; +var _SI = "SourceIdentity"; +var _SN = "SerialNumber"; +var _ST = "SessionToken"; +var _T = "Tags"; +var _TC = "TokenCode"; +var _TTK = "TransitiveTagKeys"; +var _V = "Version"; +var _Va = "Value"; +var _WIT = "WebIdentityToken"; +var _a = "arn"; +var _m = "message"; +var buildFormUrlencodedString = /* @__PURE__ */ __name((formEntries) => Object.entries(formEntries).map(([key, value]) => (0, import_smithy_client3.extendedEncodeURIComponent)(key) + "=" + (0, import_smithy_client3.extendedEncodeURIComponent)(value)).join("&"), "buildFormUrlencodedString"); +var loadQueryErrorCode = /* @__PURE__ */ __name((output, data) => { + if (data.Error?.Code !== void 0) { + return data.Error.Code; + } + if (output.statusCode == 404) { + return "NotFound"; + } +}, "loadQueryErrorCode"); + +// src/submodules/sts/commands/AssumeRoleCommand.ts +var AssumeRoleCommand = class extends import_smithy_client4.Command.classBuilder().ep(import_EndpointParameters.commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AWSSecurityTokenServiceV20110615", "AssumeRole", {}).n("STSClient", "AssumeRoleCommand").f(void 0, AssumeRoleResponseFilterSensitiveLog).ser(se_AssumeRoleCommand).de(de_AssumeRoleCommand).build() { + static { + __name(this, "AssumeRoleCommand"); + } +}; + +// src/submodules/sts/commands/AssumeRoleWithWebIdentityCommand.ts +var import_middleware_endpoint2 = __nccwpck_require__(40099); +var import_middleware_serde2 = __nccwpck_require__(83255); +var import_smithy_client5 = __nccwpck_require__(61411); +var import_EndpointParameters2 = __nccwpck_require__(76811); +var AssumeRoleWithWebIdentityCommand = class extends import_smithy_client5.Command.classBuilder().ep(import_EndpointParameters2.commonParams).m(function(Command, cs, config, o) { + return [ + (0, import_middleware_serde2.getSerdePlugin)(config, this.serialize, this.deserialize), + (0, import_middleware_endpoint2.getEndpointPlugin)(config, Command.getEndpointParameterInstructions()) + ]; +}).s("AWSSecurityTokenServiceV20110615", "AssumeRoleWithWebIdentity", {}).n("STSClient", "AssumeRoleWithWebIdentityCommand").f(AssumeRoleWithWebIdentityRequestFilterSensitiveLog, AssumeRoleWithWebIdentityResponseFilterSensitiveLog).ser(se_AssumeRoleWithWebIdentityCommand).de(de_AssumeRoleWithWebIdentityCommand).build() { + static { + __name(this, "AssumeRoleWithWebIdentityCommand"); + } +}; + +// src/submodules/sts/STS.ts +var import_STSClient = __nccwpck_require__(63723); +var commands = { + AssumeRoleCommand, + AssumeRoleWithWebIdentityCommand +}; +var STS = class extends import_STSClient.STSClient { + static { + __name(this, "STS"); + } +}; +(0, import_smithy_client6.createAggregatedClient)(commands, STS); + +// src/submodules/sts/index.ts +var import_EndpointParameters3 = __nccwpck_require__(76811); + +// src/submodules/sts/defaultStsRoleAssumers.ts +var import_client = __nccwpck_require__(5152); +var ASSUME_ROLE_DEFAULT_REGION = "us-east-1"; +var getAccountIdFromAssumedRoleUser = /* @__PURE__ */ __name((assumedRoleUser) => { + if (typeof assumedRoleUser?.Arn === "string") { + const arnComponents = assumedRoleUser.Arn.split(":"); + if (arnComponents.length > 4 && arnComponents[4] !== "") { + return arnComponents[4]; + } + } + return void 0; +}, "getAccountIdFromAssumedRoleUser"); +var resolveRegion = /* @__PURE__ */ __name(async (_region, _parentRegion, credentialProviderLogger) => { + const region = typeof _region === "function" ? await _region() : _region; + const parentRegion = typeof _parentRegion === "function" ? await _parentRegion() : _parentRegion; + credentialProviderLogger?.debug?.( + "@aws-sdk/client-sts::resolveRegion", + "accepting first of:", + `${region} (provider)`, + `${parentRegion} (parent client)`, + `${ASSUME_ROLE_DEFAULT_REGION} (STS default)` + ); + return region ?? parentRegion ?? ASSUME_ROLE_DEFAULT_REGION; +}, "resolveRegion"); +var getDefaultRoleAssumer = /* @__PURE__ */ __name((stsOptions, STSClient3) => { + let stsClient; + let closureSourceCreds; + return async (sourceCreds, params) => { + closureSourceCreds = sourceCreds; + if (!stsClient) { + const { + logger = stsOptions?.parentClientConfig?.logger, + region, + requestHandler = stsOptions?.parentClientConfig?.requestHandler, + credentialProviderLogger + } = stsOptions; + const resolvedRegion = await resolveRegion( + region, + stsOptions?.parentClientConfig?.region, + credentialProviderLogger + ); + const isCompatibleRequestHandler = !isH2(requestHandler); + stsClient = new STSClient3({ + profile: stsOptions?.parentClientConfig?.profile, + // A hack to make sts client uses the credential in current closure. + credentialDefaultProvider: /* @__PURE__ */ __name(() => async () => closureSourceCreds, "credentialDefaultProvider"), + region: resolvedRegion, + requestHandler: isCompatibleRequestHandler ? requestHandler : void 0, + logger + }); + } + const { Credentials: Credentials2, AssumedRoleUser: AssumedRoleUser2 } = await stsClient.send(new AssumeRoleCommand(params)); + if (!Credentials2 || !Credentials2.AccessKeyId || !Credentials2.SecretAccessKey) { + throw new Error(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`); + } + const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser2); + const credentials = { + accessKeyId: Credentials2.AccessKeyId, + secretAccessKey: Credentials2.SecretAccessKey, + sessionToken: Credentials2.SessionToken, + expiration: Credentials2.Expiration, + // TODO(credentialScope): access normally when shape is updated. + ...Credentials2.CredentialScope && { credentialScope: Credentials2.CredentialScope }, + ...accountId && { accountId } + }; + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_STS_ASSUME_ROLE", "i"); + return credentials; + }; +}, "getDefaultRoleAssumer"); +var getDefaultRoleAssumerWithWebIdentity = /* @__PURE__ */ __name((stsOptions, STSClient3) => { + let stsClient; + return async (params) => { + if (!stsClient) { + const { + logger = stsOptions?.parentClientConfig?.logger, + region, + requestHandler = stsOptions?.parentClientConfig?.requestHandler, + credentialProviderLogger + } = stsOptions; + const resolvedRegion = await resolveRegion( + region, + stsOptions?.parentClientConfig?.region, + credentialProviderLogger + ); + const isCompatibleRequestHandler = !isH2(requestHandler); + stsClient = new STSClient3({ + profile: stsOptions?.parentClientConfig?.profile, + region: resolvedRegion, + requestHandler: isCompatibleRequestHandler ? requestHandler : void 0, + logger + }); + } + const { Credentials: Credentials2, AssumedRoleUser: AssumedRoleUser2 } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params)); + if (!Credentials2 || !Credentials2.AccessKeyId || !Credentials2.SecretAccessKey) { + throw new Error(`Invalid response from STS.assumeRoleWithWebIdentity call with role ${params.RoleArn}`); + } + const accountId = getAccountIdFromAssumedRoleUser(AssumedRoleUser2); + const credentials = { + accessKeyId: Credentials2.AccessKeyId, + secretAccessKey: Credentials2.SecretAccessKey, + sessionToken: Credentials2.SessionToken, + expiration: Credentials2.Expiration, + // TODO(credentialScope): access normally when shape is updated. + ...Credentials2.CredentialScope && { credentialScope: Credentials2.CredentialScope }, + ...accountId && { accountId } + }; + if (accountId) { + (0, import_client.setCredentialFeature)(credentials, "RESOLVED_ACCOUNT_ID", "T"); + } + (0, import_client.setCredentialFeature)(credentials, "CREDENTIALS_STS_ASSUME_ROLE_WEB_ID", "k"); + return credentials; + }; +}, "getDefaultRoleAssumerWithWebIdentity"); +var isH2 = /* @__PURE__ */ __name((requestHandler) => { + return requestHandler?.metadata?.handlerProtocol === "h2"; +}, "isH2"); + +// src/submodules/sts/defaultRoleAssumers.ts +var import_STSClient2 = __nccwpck_require__(63723); +var getCustomizableStsClientCtor = /* @__PURE__ */ __name((baseCtor, customizations) => { + if (!customizations) return baseCtor; + else + return class CustomizableSTSClient extends baseCtor { + static { + __name(this, "CustomizableSTSClient"); + } + constructor(config) { + super(config); + for (const customization of customizations) { + this.middlewareStack.use(customization); + } + } + }; +}, "getCustomizableStsClientCtor"); +var getDefaultRoleAssumer2 = /* @__PURE__ */ __name((stsOptions = {}, stsPlugins) => getDefaultRoleAssumer(stsOptions, getCustomizableStsClientCtor(import_STSClient2.STSClient, stsPlugins)), "getDefaultRoleAssumer"); +var getDefaultRoleAssumerWithWebIdentity2 = /* @__PURE__ */ __name((stsOptions = {}, stsPlugins) => getDefaultRoleAssumerWithWebIdentity(stsOptions, getCustomizableStsClientCtor(import_STSClient2.STSClient, stsPlugins)), "getDefaultRoleAssumerWithWebIdentity"); +var decorateDefaultCredentialProvider = /* @__PURE__ */ __name((provider) => (input) => provider({ + roleAssumer: getDefaultRoleAssumer2(input), + roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity2(input), + ...input +}), "decorateDefaultCredentialProvider"); +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 36578: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const tslib_1 = __nccwpck_require__(61860); +const package_json_1 = tslib_1.__importDefault(__nccwpck_require__(39955)); +const core_1 = __nccwpck_require__(8704); +const util_user_agent_node_1 = __nccwpck_require__(51656); +const config_resolver_1 = __nccwpck_require__(39316); +const core_2 = __nccwpck_require__(90402); +const hash_node_1 = __nccwpck_require__(5092); +const middleware_retry_1 = __nccwpck_require__(19618); +const node_config_provider_1 = __nccwpck_require__(55704); +const node_http_handler_1 = __nccwpck_require__(61279); +const util_body_length_node_1 = __nccwpck_require__(13638); +const util_retry_1 = __nccwpck_require__(15518); +const runtimeConfig_shared_1 = __nccwpck_require__(24443); +const smithy_client_1 = __nccwpck_require__(61411); +const util_defaults_mode_node_1 = __nccwpck_require__(15435); +const smithy_client_2 = __nccwpck_require__(61411); +const getRuntimeConfig = (config) => { + (0, smithy_client_2.emitWarningIfUnsupportedVersion)(process.version); + const defaultsMode = (0, util_defaults_mode_node_1.resolveDefaultsModeConfig)(config); + const defaultConfigProvider = () => defaultsMode().then(smithy_client_1.loadConfigsForDefaultMode); + const clientSharedValues = (0, runtimeConfig_shared_1.getRuntimeConfig)(config); + (0, core_1.emitWarningIfUnsupportedVersion)(process.version); + const loaderConfig = { + profile: config?.profile, + logger: clientSharedValues.logger, + }; + return { + ...clientSharedValues, + ...config, + runtime: "node", + defaultsMode, + authSchemePreference: config?.authSchemePreference ?? (0, node_config_provider_1.loadConfig)(core_1.NODE_AUTH_SCHEME_PREFERENCE_OPTIONS, loaderConfig), + bodyLengthChecker: config?.bodyLengthChecker ?? util_body_length_node_1.calculateBodyLength, + defaultUserAgentProvider: config?.defaultUserAgentProvider ?? + (0, util_user_agent_node_1.createDefaultUserAgentProvider)({ serviceId: clientSharedValues.serviceId, clientVersion: package_json_1.default.version }), + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4") || + (async (idProps) => await config.credentialDefaultProvider(idProps?.__config || {})()), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + maxAttempts: config?.maxAttempts ?? (0, node_config_provider_1.loadConfig)(middleware_retry_1.NODE_MAX_ATTEMPT_CONFIG_OPTIONS, config), + region: config?.region ?? + (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_REGION_CONFIG_OPTIONS, { ...config_resolver_1.NODE_REGION_CONFIG_FILE_OPTIONS, ...loaderConfig }), + requestHandler: node_http_handler_1.NodeHttpHandler.create(config?.requestHandler ?? defaultConfigProvider), + retryMode: config?.retryMode ?? + (0, node_config_provider_1.loadConfig)({ + ...middleware_retry_1.NODE_RETRY_MODE_CONFIG_OPTIONS, + default: async () => (await defaultConfigProvider()).retryMode || util_retry_1.DEFAULT_RETRY_MODE, + }, config), + sha256: config?.sha256 ?? hash_node_1.Hash.bind(null, "sha256"), + streamCollector: config?.streamCollector ?? node_http_handler_1.streamCollector, + useDualstackEndpoint: config?.useDualstackEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + useFipsEndpoint: config?.useFipsEndpoint ?? (0, node_config_provider_1.loadConfig)(config_resolver_1.NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, loaderConfig), + userAgentAppId: config?.userAgentAppId ?? (0, node_config_provider_1.loadConfig)(util_user_agent_node_1.NODE_APP_ID_CONFIG_OPTIONS, loaderConfig), + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 24443: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntimeConfig = void 0; +const core_1 = __nccwpck_require__(8704); +const core_2 = __nccwpck_require__(90402); +const smithy_client_1 = __nccwpck_require__(61411); +const url_parser_1 = __nccwpck_require__(14494); +const util_base64_1 = __nccwpck_require__(68385); +const util_utf8_1 = __nccwpck_require__(71577); +const httpAuthSchemeProvider_1 = __nccwpck_require__(27851); +const endpointResolver_1 = __nccwpck_require__(59765); +const getRuntimeConfig = (config) => { + return { + apiVersion: "2011-06-15", + base64Decoder: config?.base64Decoder ?? util_base64_1.fromBase64, + base64Encoder: config?.base64Encoder ?? util_base64_1.toBase64, + disableHostPrefix: config?.disableHostPrefix ?? false, + endpointProvider: config?.endpointProvider ?? endpointResolver_1.defaultEndpointResolver, + extensions: config?.extensions ?? [], + httpAuthSchemeProvider: config?.httpAuthSchemeProvider ?? httpAuthSchemeProvider_1.defaultSTSHttpAuthSchemeProvider, + httpAuthSchemes: config?.httpAuthSchemes ?? [ + { + schemeId: "aws.auth#sigv4", + identityProvider: (ipc) => ipc.getIdentityProvider("aws.auth#sigv4"), + signer: new core_1.AwsSdkSigV4Signer(), + }, + { + schemeId: "smithy.api#noAuth", + identityProvider: (ipc) => ipc.getIdentityProvider("smithy.api#noAuth") || (async () => ({})), + signer: new core_2.NoAuthSigner(), + }, + ], + logger: config?.logger ?? new smithy_client_1.NoOpLogger(), + serviceId: config?.serviceId ?? "STS", + urlParser: config?.urlParser ?? url_parser_1.parseUrl, + utf8Decoder: config?.utf8Decoder ?? util_utf8_1.fromUtf8, + utf8Encoder: config?.utf8Encoder ?? util_utf8_1.toUtf8, + }; +}; +exports.getRuntimeConfig = getRuntimeConfig; + + +/***/ }), + +/***/ 37742: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.resolveRuntimeExtensions = void 0; +const region_config_resolver_1 = __nccwpck_require__(36463); +const protocol_http_1 = __nccwpck_require__(72356); +const smithy_client_1 = __nccwpck_require__(61411); +const httpAuthExtensionConfiguration_1 = __nccwpck_require__(34532); +const resolveRuntimeExtensions = (runtimeConfig, extensions) => { + const extensionConfiguration = Object.assign((0, region_config_resolver_1.getAwsRegionExtensionConfiguration)(runtimeConfig), (0, smithy_client_1.getDefaultExtensionConfiguration)(runtimeConfig), (0, protocol_http_1.getHttpHandlerExtensionConfiguration)(runtimeConfig), (0, httpAuthExtensionConfiguration_1.getHttpAuthExtensionConfiguration)(runtimeConfig)); + extensions.forEach((extension) => extension.configure(extensionConfiguration)); + return Object.assign(runtimeConfig, (0, region_config_resolver_1.resolveAwsRegionExtensionConfiguration)(extensionConfiguration), (0, smithy_client_1.resolveDefaultRuntimeConfig)(extensionConfiguration), (0, protocol_http_1.resolveHttpHandlerRuntimeConfig)(extensionConfiguration), (0, httpAuthExtensionConfiguration_1.resolveHttpAuthRuntimeConfig)(extensionConfiguration)); +}; +exports.resolveRuntimeExtensions = resolveRuntimeExtensions; + + +/***/ }), + +/***/ 36463: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_REGION_CONFIG_FILE_OPTIONS: () => NODE_REGION_CONFIG_FILE_OPTIONS, + NODE_REGION_CONFIG_OPTIONS: () => NODE_REGION_CONFIG_OPTIONS, + REGION_ENV_NAME: () => REGION_ENV_NAME, + REGION_INI_NAME: () => REGION_INI_NAME, + getAwsRegionExtensionConfiguration: () => getAwsRegionExtensionConfiguration, + resolveAwsRegionExtensionConfiguration: () => resolveAwsRegionExtensionConfiguration, + resolveRegionConfig: () => resolveRegionConfig +}); +module.exports = __toCommonJS(index_exports); + +// src/extensions/index.ts +var getAwsRegionExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return { + setRegion(region) { + runtimeConfig.region = region; + }, + region() { + return runtimeConfig.region; + } + }; +}, "getAwsRegionExtensionConfiguration"); +var resolveAwsRegionExtensionConfiguration = /* @__PURE__ */ __name((awsRegionExtensionConfiguration) => { + return { + region: awsRegionExtensionConfiguration.region() + }; +}, "resolveAwsRegionExtensionConfiguration"); + +// src/regionConfig/config.ts +var REGION_ENV_NAME = "AWS_REGION"; +var REGION_INI_NAME = "region"; +var NODE_REGION_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env) => env[REGION_ENV_NAME], "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => profile[REGION_INI_NAME], "configFileSelector"), + default: /* @__PURE__ */ __name(() => { + throw new Error("Region is missing"); + }, "default") +}; +var NODE_REGION_CONFIG_FILE_OPTIONS = { + preferredFile: "credentials" +}; + +// src/regionConfig/isFipsRegion.ts +var isFipsRegion = /* @__PURE__ */ __name((region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips")), "isFipsRegion"); + +// src/regionConfig/getRealRegion.ts +var getRealRegion = /* @__PURE__ */ __name((region) => isFipsRegion(region) ? ["fips-aws-global", "aws-fips"].includes(region) ? "us-east-1" : region.replace(/fips-(dkr-|prod-)?|-fips/, "") : region, "getRealRegion"); + +// src/regionConfig/resolveRegionConfig.ts +var resolveRegionConfig = /* @__PURE__ */ __name((input) => { + const { region, useFipsEndpoint } = input; + if (!region) { + throw new Error("Region is missing"); + } + return Object.assign(input, { + region: /* @__PURE__ */ __name(async () => { + if (typeof region === "string") { + return getRealRegion(region); + } + const providedRegion = await region(); + return getRealRegion(providedRegion); + }, "region"), + useFipsEndpoint: /* @__PURE__ */ __name(async () => { + const providedRegion = typeof region === "string" ? region : await region(); + if (isFipsRegion(providedRegion)) { + return true; + } + return typeof useFipsEndpoint !== "function" ? Promise.resolve(!!useFipsEndpoint) : useFipsEndpoint(); + }, "useFipsEndpoint") + }); +}, "resolveRegionConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 5785: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + SignatureV4MultiRegion: () => SignatureV4MultiRegion, + signatureV4CrtContainer: () => signatureV4CrtContainer +}); +module.exports = __toCommonJS(index_exports); + +// src/SignatureV4MultiRegion.ts +var import_middleware_sdk_s3 = __nccwpck_require__(77445); +var import_signature_v4 = __nccwpck_require__(75118); + +// src/signature-v4-crt-container.ts +var signatureV4CrtContainer = { + CrtSignerV4: null +}; + +// src/SignatureV4MultiRegion.ts +var SignatureV4MultiRegion = class { + static { + __name(this, "SignatureV4MultiRegion"); + } + sigv4aSigner; + sigv4Signer; + signerOptions; + static sigv4aDependency() { + if (typeof signatureV4CrtContainer.CrtSignerV4 === "function") { + return "crt"; + } else if (typeof import_signature_v4.signatureV4aContainer.SignatureV4a === "function") { + return "js"; + } + return "none"; + } + constructor(options) { + this.sigv4Signer = new import_middleware_sdk_s3.SignatureV4S3Express(options); + this.signerOptions = options; + } + async sign(requestToSign, options = {}) { + if (options.signingRegion === "*") { + return this.getSigv4aSigner().sign(requestToSign, options); + } + return this.sigv4Signer.sign(requestToSign, options); + } + /** + * Sign with alternate credentials to the ones provided in the constructor. + * Note: This is only supported for SigV4a when using the CRT implementation. + */ + async signWithCredentials(requestToSign, credentials, options = {}) { + if (options.signingRegion === "*") { + const signer = this.getSigv4aSigner(); + const CrtSignerV4 = signatureV4CrtContainer.CrtSignerV4; + if (CrtSignerV4 && signer instanceof CrtSignerV4) { + return signer.signWithCredentials(requestToSign, credentials, options); + } else { + throw new Error( + `signWithCredentials with signingRegion '*' is only supported when using the CRT dependency @aws-sdk/signature-v4-crt. Please check whether you have installed the "@aws-sdk/signature-v4-crt" package explicitly. You must also register the package by calling [require("@aws-sdk/signature-v4-crt");] or an ESM equivalent such as [import "@aws-sdk/signature-v4-crt";]. For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt` + ); + } + } + return this.sigv4Signer.signWithCredentials(requestToSign, credentials, options); + } + /** + * Presign a request. + * Note: This is only supported for SigV4a when using the CRT implementation. + */ + async presign(originalRequest, options = {}) { + if (options.signingRegion === "*") { + const signer = this.getSigv4aSigner(); + const CrtSignerV4 = signatureV4CrtContainer.CrtSignerV4; + if (CrtSignerV4 && signer instanceof CrtSignerV4) { + return signer.presign(originalRequest, options); + } else { + throw new Error( + `presign with signingRegion '*' is only supported when using the CRT dependency @aws-sdk/signature-v4-crt. Please check whether you have installed the "@aws-sdk/signature-v4-crt" package explicitly. You must also register the package by calling [require("@aws-sdk/signature-v4-crt");] or an ESM equivalent such as [import "@aws-sdk/signature-v4-crt";]. For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt` + ); + } + } + return this.sigv4Signer.presign(originalRequest, options); + } + async presignWithCredentials(originalRequest, credentials, options = {}) { + if (options.signingRegion === "*") { + throw new Error("Method presignWithCredentials is not supported for [signingRegion=*]."); + } + return this.sigv4Signer.presignWithCredentials(originalRequest, credentials, options); + } + getSigv4aSigner() { + if (!this.sigv4aSigner) { + const CrtSignerV4 = signatureV4CrtContainer.CrtSignerV4; + const JsSigV4aSigner = import_signature_v4.signatureV4aContainer.SignatureV4a; + if (this.signerOptions.runtime === "node") { + if (!CrtSignerV4 && !JsSigV4aSigner) { + throw new Error( + "Neither CRT nor JS SigV4a implementation is available. Please load either @aws-sdk/signature-v4-crt or @aws-sdk/signature-v4a. For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt" + ); + } + if (CrtSignerV4 && typeof CrtSignerV4 === "function") { + this.sigv4aSigner = new CrtSignerV4({ + ...this.signerOptions, + signingAlgorithm: 1 + }); + } else if (JsSigV4aSigner && typeof JsSigV4aSigner === "function") { + this.sigv4aSigner = new JsSigV4aSigner({ + ...this.signerOptions + }); + } else { + throw new Error( + "Available SigV4a implementation is not a valid constructor. Please ensure you've properly imported @aws-sdk/signature-v4-crt or @aws-sdk/signature-v4a.For more information please go to https://github.com/aws/aws-sdk-js-v3#functionality-requiring-aws-common-runtime-crt" + ); + } + } else { + if (!JsSigV4aSigner || typeof JsSigV4aSigner !== "function") { + throw new Error( + "JS SigV4a implementation is not available or not a valid constructor. Please check whether you have installed the @aws-sdk/signature-v4a package explicitly. The CRT implementation is not available for browsers. You must also register the package by calling [require('@aws-sdk/signature-v4a');] or an ESM equivalent such as [import '@aws-sdk/signature-v4a';]. For more information please go to https://github.com/aws/aws-sdk-js-v3#using-javascript-non-crt-implementation-of-sigv4a" + ); + } + this.sigv4aSigner = new JsSigV4aSigner({ + ...this.signerOptions + }); + } + } + return this.sigv4aSigner; + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 75433: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + fromEnvSigningName: () => fromEnvSigningName, + fromSso: () => fromSso, + fromStatic: () => fromStatic, + nodeProvider: () => nodeProvider +}); +module.exports = __toCommonJS(index_exports); + +// src/fromEnvSigningName.ts +var import_client = __nccwpck_require__(5152); +var import_httpAuthSchemes = __nccwpck_require__(97523); +var import_property_provider = __nccwpck_require__(71238); +var fromEnvSigningName = /* @__PURE__ */ __name(({ logger, signingName } = {}) => async () => { + logger?.debug?.("@aws-sdk/token-providers - fromEnvSigningName"); + if (!signingName) { + throw new import_property_provider.TokenProviderError("Please pass 'signingName' to compute environment variable key", { logger }); + } + const bearerTokenKey = (0, import_httpAuthSchemes.getBearerTokenEnvKey)(signingName); + if (!(bearerTokenKey in process.env)) { + throw new import_property_provider.TokenProviderError(`Token not present in '${bearerTokenKey}' environment variable`, { logger }); + } + const token = { token: process.env[bearerTokenKey] }; + (0, import_client.setTokenFeature)(token, "BEARER_SERVICE_ENV_VARS", "3"); + return token; +}, "fromEnvSigningName"); + +// src/fromSso.ts + + + +// src/constants.ts +var EXPIRE_WINDOW_MS = 5 * 60 * 1e3; +var REFRESH_MESSAGE = `To refresh this SSO session run 'aws sso login' with the corresponding profile.`; + +// src/getSsoOidcClient.ts +var getSsoOidcClient = /* @__PURE__ */ __name(async (ssoRegion, init = {}) => { + const { SSOOIDCClient } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(89443))); + const ssoOidcClient = new SSOOIDCClient( + Object.assign({}, init.clientConfig ?? {}, { + region: ssoRegion ?? init.clientConfig?.region, + logger: init.clientConfig?.logger ?? init.parentClientConfig?.logger + }) + ); + return ssoOidcClient; +}, "getSsoOidcClient"); + +// src/getNewSsoOidcToken.ts +var getNewSsoOidcToken = /* @__PURE__ */ __name(async (ssoToken, ssoRegion, init = {}) => { + const { CreateTokenCommand } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(89443))); + const ssoOidcClient = await getSsoOidcClient(ssoRegion, init); + return ssoOidcClient.send( + new CreateTokenCommand({ + clientId: ssoToken.clientId, + clientSecret: ssoToken.clientSecret, + refreshToken: ssoToken.refreshToken, + grantType: "refresh_token" + }) + ); +}, "getNewSsoOidcToken"); + +// src/validateTokenExpiry.ts + +var validateTokenExpiry = /* @__PURE__ */ __name((token) => { + if (token.expiration && token.expiration.getTime() < Date.now()) { + throw new import_property_provider.TokenProviderError(`Token is expired. ${REFRESH_MESSAGE}`, false); + } +}, "validateTokenExpiry"); + +// src/validateTokenKey.ts + +var validateTokenKey = /* @__PURE__ */ __name((key, value, forRefresh = false) => { + if (typeof value === "undefined") { + throw new import_property_provider.TokenProviderError( + `Value not present for '${key}' in SSO Token${forRefresh ? ". Cannot refresh" : ""}. ${REFRESH_MESSAGE}`, + false + ); + } +}, "validateTokenKey"); + +// src/writeSSOTokenToFile.ts +var import_shared_ini_file_loader = __nccwpck_require__(94964); +var import_fs = __nccwpck_require__(79896); +var { writeFile } = import_fs.promises; +var writeSSOTokenToFile = /* @__PURE__ */ __name((id, ssoToken) => { + const tokenFilepath = (0, import_shared_ini_file_loader.getSSOTokenFilepath)(id); + const tokenString = JSON.stringify(ssoToken, null, 2); + return writeFile(tokenFilepath, tokenString); +}, "writeSSOTokenToFile"); + +// src/fromSso.ts +var lastRefreshAttemptTime = /* @__PURE__ */ new Date(0); +var fromSso = /* @__PURE__ */ __name((_init = {}) => async ({ callerClientConfig } = {}) => { + const init = { + ..._init, + parentClientConfig: { + ...callerClientConfig, + ..._init.parentClientConfig + } + }; + init.logger?.debug("@aws-sdk/token-providers - fromSso"); + const profiles = await (0, import_shared_ini_file_loader.parseKnownFiles)(init); + const profileName = (0, import_shared_ini_file_loader.getProfileName)({ + profile: init.profile ?? callerClientConfig?.profile + }); + const profile = profiles[profileName]; + if (!profile) { + throw new import_property_provider.TokenProviderError(`Profile '${profileName}' could not be found in shared credentials file.`, false); + } else if (!profile["sso_session"]) { + throw new import_property_provider.TokenProviderError(`Profile '${profileName}' is missing required property 'sso_session'.`); + } + const ssoSessionName = profile["sso_session"]; + const ssoSessions = await (0, import_shared_ini_file_loader.loadSsoSessionData)(init); + const ssoSession = ssoSessions[ssoSessionName]; + if (!ssoSession) { + throw new import_property_provider.TokenProviderError( + `Sso session '${ssoSessionName}' could not be found in shared credentials file.`, + false + ); + } + for (const ssoSessionRequiredKey of ["sso_start_url", "sso_region"]) { + if (!ssoSession[ssoSessionRequiredKey]) { + throw new import_property_provider.TokenProviderError( + `Sso session '${ssoSessionName}' is missing required property '${ssoSessionRequiredKey}'.`, + false + ); + } + } + const ssoStartUrl = ssoSession["sso_start_url"]; + const ssoRegion = ssoSession["sso_region"]; + let ssoToken; + try { + ssoToken = await (0, import_shared_ini_file_loader.getSSOTokenFromFile)(ssoSessionName); + } catch (e) { + throw new import_property_provider.TokenProviderError( + `The SSO session token associated with profile=${profileName} was not found or is invalid. ${REFRESH_MESSAGE}`, + false + ); + } + validateTokenKey("accessToken", ssoToken.accessToken); + validateTokenKey("expiresAt", ssoToken.expiresAt); + const { accessToken, expiresAt } = ssoToken; + const existingToken = { token: accessToken, expiration: new Date(expiresAt) }; + if (existingToken.expiration.getTime() - Date.now() > EXPIRE_WINDOW_MS) { + return existingToken; + } + if (Date.now() - lastRefreshAttemptTime.getTime() < 30 * 1e3) { + validateTokenExpiry(existingToken); + return existingToken; + } + validateTokenKey("clientId", ssoToken.clientId, true); + validateTokenKey("clientSecret", ssoToken.clientSecret, true); + validateTokenKey("refreshToken", ssoToken.refreshToken, true); + try { + lastRefreshAttemptTime.setTime(Date.now()); + const newSsoOidcToken = await getNewSsoOidcToken(ssoToken, ssoRegion, init); + validateTokenKey("accessToken", newSsoOidcToken.accessToken); + validateTokenKey("expiresIn", newSsoOidcToken.expiresIn); + const newTokenExpiration = new Date(Date.now() + newSsoOidcToken.expiresIn * 1e3); + try { + await writeSSOTokenToFile(ssoSessionName, { + ...ssoToken, + accessToken: newSsoOidcToken.accessToken, + expiresAt: newTokenExpiration.toISOString(), + refreshToken: newSsoOidcToken.refreshToken + }); + } catch (error) { + } + return { + token: newSsoOidcToken.accessToken, + expiration: newTokenExpiration + }; + } catch (error) { + validateTokenExpiry(existingToken); + return existingToken; + } +}, "fromSso"); + +// src/fromStatic.ts + +var fromStatic = /* @__PURE__ */ __name(({ token, logger }) => async () => { + logger?.debug("@aws-sdk/token-providers - fromStatic"); + if (!token || !token.token) { + throw new import_property_provider.TokenProviderError(`Please pass a valid token to fromStatic`, false); + } + return token; +}, "fromStatic"); + +// src/nodeProvider.ts + +var nodeProvider = /* @__PURE__ */ __name((init = {}) => (0, import_property_provider.memoize)( + (0, import_property_provider.chain)(fromSso(init), async () => { + throw new import_property_provider.TokenProviderError("Could not load token from any providers", false); + }), + (token) => token.expiration !== void 0 && token.expiration.getTime() - Date.now() < 3e5, + (token) => token.expiration !== void 0 +), "nodeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 56369: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + build: () => build, + parse: () => parse, + validate: () => validate +}); +module.exports = __toCommonJS(index_exports); +var validate = /* @__PURE__ */ __name((str) => typeof str === "string" && str.indexOf("arn:") === 0 && str.split(":").length >= 6, "validate"); +var parse = /* @__PURE__ */ __name((arn) => { + const segments = arn.split(":"); + if (segments.length < 6 || segments[0] !== "arn") throw new Error("Malformed ARN"); + const [ + , + //Skip "arn" literal + partition, + service, + region, + accountId, + ...resource + ] = segments; + return { + partition, + service, + region, + accountId, + resource: resource.join(":") + }; +}, "parse"); +var build = /* @__PURE__ */ __name((arnObject) => { + const { partition = "aws", service, region, accountId, resource } = arnObject; + if ([service, region, accountId, resource].some((segment) => typeof segment !== "string")) { + throw new Error("Input ARN object is invalid"); + } + return `arn:${partition}:${service}:${region}:${accountId}:${resource}`; +}, "build"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 83068: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + ConditionObject: () => import_util_endpoints.ConditionObject, + DeprecatedObject: () => import_util_endpoints.DeprecatedObject, + EndpointError: () => import_util_endpoints.EndpointError, + EndpointObject: () => import_util_endpoints.EndpointObject, + EndpointObjectHeaders: () => import_util_endpoints.EndpointObjectHeaders, + EndpointObjectProperties: () => import_util_endpoints.EndpointObjectProperties, + EndpointParams: () => import_util_endpoints.EndpointParams, + EndpointResolverOptions: () => import_util_endpoints.EndpointResolverOptions, + EndpointRuleObject: () => import_util_endpoints.EndpointRuleObject, + ErrorRuleObject: () => import_util_endpoints.ErrorRuleObject, + EvaluateOptions: () => import_util_endpoints.EvaluateOptions, + Expression: () => import_util_endpoints.Expression, + FunctionArgv: () => import_util_endpoints.FunctionArgv, + FunctionObject: () => import_util_endpoints.FunctionObject, + FunctionReturn: () => import_util_endpoints.FunctionReturn, + ParameterObject: () => import_util_endpoints.ParameterObject, + ReferenceObject: () => import_util_endpoints.ReferenceObject, + ReferenceRecord: () => import_util_endpoints.ReferenceRecord, + RuleSetObject: () => import_util_endpoints.RuleSetObject, + RuleSetRules: () => import_util_endpoints.RuleSetRules, + TreeRuleObject: () => import_util_endpoints.TreeRuleObject, + awsEndpointFunctions: () => awsEndpointFunctions, + getUserAgentPrefix: () => getUserAgentPrefix, + isIpAddress: () => import_util_endpoints.isIpAddress, + partition: () => partition, + resolveDefaultAwsRegionalEndpointsConfig: () => resolveDefaultAwsRegionalEndpointsConfig, + resolveEndpoint: () => import_util_endpoints.resolveEndpoint, + setPartitionInfo: () => setPartitionInfo, + toEndpointV1: () => toEndpointV1, + useDefaultPartitionInfo: () => useDefaultPartitionInfo +}); +module.exports = __toCommonJS(index_exports); + +// src/aws.ts + + +// src/lib/aws/isVirtualHostableS3Bucket.ts + + +// src/lib/isIpAddress.ts +var import_util_endpoints = __nccwpck_require__(79674); + +// src/lib/aws/isVirtualHostableS3Bucket.ts +var isVirtualHostableS3Bucket = /* @__PURE__ */ __name((value, allowSubDomains = false) => { + if (allowSubDomains) { + for (const label of value.split(".")) { + if (!isVirtualHostableS3Bucket(label)) { + return false; + } + } + return true; + } + if (!(0, import_util_endpoints.isValidHostLabel)(value)) { + return false; + } + if (value.length < 3 || value.length > 63) { + return false; + } + if (value !== value.toLowerCase()) { + return false; + } + if ((0, import_util_endpoints.isIpAddress)(value)) { + return false; + } + return true; +}, "isVirtualHostableS3Bucket"); + +// src/lib/aws/parseArn.ts +var ARN_DELIMITER = ":"; +var RESOURCE_DELIMITER = "/"; +var parseArn = /* @__PURE__ */ __name((value) => { + const segments = value.split(ARN_DELIMITER); + if (segments.length < 6) return null; + const [arn, partition2, service, region, accountId, ...resourcePath] = segments; + if (arn !== "arn" || partition2 === "" || service === "" || resourcePath.join(ARN_DELIMITER) === "") return null; + const resourceId = resourcePath.map((resource) => resource.split(RESOURCE_DELIMITER)).flat(); + return { + partition: partition2, + service, + region, + accountId, + resourceId + }; +}, "parseArn"); + +// src/lib/aws/partitions.json +var partitions_default = { + partitions: [{ + id: "aws", + outputs: { + dnsSuffix: "amazonaws.com", + dualStackDnsSuffix: "api.aws", + implicitGlobalRegion: "us-east-1", + name: "aws", + supportsDualStack: true, + supportsFIPS: true + }, + regionRegex: "^(us|eu|ap|sa|ca|me|af|il|mx)\\-\\w+\\-\\d+$", + regions: { + "af-south-1": { + description: "Africa (Cape Town)" + }, + "ap-east-1": { + description: "Asia Pacific (Hong Kong)" + }, + "ap-east-2": { + description: "Asia Pacific (Taipei)" + }, + "ap-northeast-1": { + description: "Asia Pacific (Tokyo)" + }, + "ap-northeast-2": { + description: "Asia Pacific (Seoul)" + }, + "ap-northeast-3": { + description: "Asia Pacific (Osaka)" + }, + "ap-south-1": { + description: "Asia Pacific (Mumbai)" + }, + "ap-south-2": { + description: "Asia Pacific (Hyderabad)" + }, + "ap-southeast-1": { + description: "Asia Pacific (Singapore)" + }, + "ap-southeast-2": { + description: "Asia Pacific (Sydney)" + }, + "ap-southeast-3": { + description: "Asia Pacific (Jakarta)" + }, + "ap-southeast-4": { + description: "Asia Pacific (Melbourne)" + }, + "ap-southeast-5": { + description: "Asia Pacific (Malaysia)" + }, + "ap-southeast-7": { + description: "Asia Pacific (Thailand)" + }, + "aws-global": { + description: "AWS Standard global region" + }, + "ca-central-1": { + description: "Canada (Central)" + }, + "ca-west-1": { + description: "Canada West (Calgary)" + }, + "eu-central-1": { + description: "Europe (Frankfurt)" + }, + "eu-central-2": { + description: "Europe (Zurich)" + }, + "eu-north-1": { + description: "Europe (Stockholm)" + }, + "eu-south-1": { + description: "Europe (Milan)" + }, + "eu-south-2": { + description: "Europe (Spain)" + }, + "eu-west-1": { + description: "Europe (Ireland)" + }, + "eu-west-2": { + description: "Europe (London)" + }, + "eu-west-3": { + description: "Europe (Paris)" + }, + "il-central-1": { + description: "Israel (Tel Aviv)" + }, + "me-central-1": { + description: "Middle East (UAE)" + }, + "me-south-1": { + description: "Middle East (Bahrain)" + }, + "mx-central-1": { + description: "Mexico (Central)" + }, + "sa-east-1": { + description: "South America (Sao Paulo)" + }, + "us-east-1": { + description: "US East (N. Virginia)" + }, + "us-east-2": { + description: "US East (Ohio)" + }, + "us-west-1": { + description: "US West (N. California)" + }, + "us-west-2": { + description: "US West (Oregon)" + } + } + }, { + id: "aws-cn", + outputs: { + dnsSuffix: "amazonaws.com.cn", + dualStackDnsSuffix: "api.amazonwebservices.com.cn", + implicitGlobalRegion: "cn-northwest-1", + name: "aws-cn", + supportsDualStack: true, + supportsFIPS: true + }, + regionRegex: "^cn\\-\\w+\\-\\d+$", + regions: { + "aws-cn-global": { + description: "AWS China global region" + }, + "cn-north-1": { + description: "China (Beijing)" + }, + "cn-northwest-1": { + description: "China (Ningxia)" + } + } + }, { + id: "aws-us-gov", + outputs: { + dnsSuffix: "amazonaws.com", + dualStackDnsSuffix: "api.aws", + implicitGlobalRegion: "us-gov-west-1", + name: "aws-us-gov", + supportsDualStack: true, + supportsFIPS: true + }, + regionRegex: "^us\\-gov\\-\\w+\\-\\d+$", + regions: { + "aws-us-gov-global": { + description: "AWS GovCloud (US) global region" + }, + "us-gov-east-1": { + description: "AWS GovCloud (US-East)" + }, + "us-gov-west-1": { + description: "AWS GovCloud (US-West)" + } + } + }, { + id: "aws-iso", + outputs: { + dnsSuffix: "c2s.ic.gov", + dualStackDnsSuffix: "c2s.ic.gov", + implicitGlobalRegion: "us-iso-east-1", + name: "aws-iso", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^us\\-iso\\-\\w+\\-\\d+$", + regions: { + "aws-iso-global": { + description: "AWS ISO (US) global region" + }, + "us-iso-east-1": { + description: "US ISO East" + }, + "us-iso-west-1": { + description: "US ISO WEST" + } + } + }, { + id: "aws-iso-b", + outputs: { + dnsSuffix: "sc2s.sgov.gov", + dualStackDnsSuffix: "sc2s.sgov.gov", + implicitGlobalRegion: "us-isob-east-1", + name: "aws-iso-b", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^us\\-isob\\-\\w+\\-\\d+$", + regions: { + "aws-iso-b-global": { + description: "AWS ISOB (US) global region" + }, + "us-isob-east-1": { + description: "US ISOB East (Ohio)" + } + } + }, { + id: "aws-iso-e", + outputs: { + dnsSuffix: "cloud.adc-e.uk", + dualStackDnsSuffix: "cloud.adc-e.uk", + implicitGlobalRegion: "eu-isoe-west-1", + name: "aws-iso-e", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^eu\\-isoe\\-\\w+\\-\\d+$", + regions: { + "aws-iso-e-global": { + description: "AWS ISOE (Europe) global region" + }, + "eu-isoe-west-1": { + description: "EU ISOE West" + } + } + }, { + id: "aws-iso-f", + outputs: { + dnsSuffix: "csp.hci.ic.gov", + dualStackDnsSuffix: "csp.hci.ic.gov", + implicitGlobalRegion: "us-isof-south-1", + name: "aws-iso-f", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^us\\-isof\\-\\w+\\-\\d+$", + regions: { + "aws-iso-f-global": { + description: "AWS ISOF global region" + }, + "us-isof-east-1": { + description: "US ISOF EAST" + }, + "us-isof-south-1": { + description: "US ISOF SOUTH" + } + } + }, { + id: "aws-eusc", + outputs: { + dnsSuffix: "amazonaws.eu", + dualStackDnsSuffix: "amazonaws.eu", + implicitGlobalRegion: "eusc-de-east-1", + name: "aws-eusc", + supportsDualStack: false, + supportsFIPS: true + }, + regionRegex: "^eusc\\-(de)\\-\\w+\\-\\d+$", + regions: { + "eusc-de-east-1": { + description: "EU (Germany)" + } + } + }], + version: "1.1" +}; + +// src/lib/aws/partition.ts +var selectedPartitionsInfo = partitions_default; +var selectedUserAgentPrefix = ""; +var partition = /* @__PURE__ */ __name((value) => { + const { partitions } = selectedPartitionsInfo; + for (const partition2 of partitions) { + const { regions, outputs } = partition2; + for (const [region, regionData] of Object.entries(regions)) { + if (region === value) { + return { + ...outputs, + ...regionData + }; + } + } + } + for (const partition2 of partitions) { + const { regionRegex, outputs } = partition2; + if (new RegExp(regionRegex).test(value)) { + return { + ...outputs + }; + } + } + const DEFAULT_PARTITION = partitions.find((partition2) => partition2.id === "aws"); + if (!DEFAULT_PARTITION) { + throw new Error( + "Provided region was not found in the partition array or regex, and default partition with id 'aws' doesn't exist." + ); + } + return { + ...DEFAULT_PARTITION.outputs + }; +}, "partition"); +var setPartitionInfo = /* @__PURE__ */ __name((partitionsInfo, userAgentPrefix = "") => { + selectedPartitionsInfo = partitionsInfo; + selectedUserAgentPrefix = userAgentPrefix; +}, "setPartitionInfo"); +var useDefaultPartitionInfo = /* @__PURE__ */ __name(() => { + setPartitionInfo(partitions_default, ""); +}, "useDefaultPartitionInfo"); +var getUserAgentPrefix = /* @__PURE__ */ __name(() => selectedUserAgentPrefix, "getUserAgentPrefix"); + +// src/aws.ts +var awsEndpointFunctions = { + isVirtualHostableS3Bucket, + parseArn, + partition +}; +import_util_endpoints.customEndpointFunctions.aws = awsEndpointFunctions; + +// src/resolveDefaultAwsRegionalEndpointsConfig.ts +var import_url_parser = __nccwpck_require__(14494); +var resolveDefaultAwsRegionalEndpointsConfig = /* @__PURE__ */ __name((input) => { + if (typeof input.endpointProvider !== "function") { + throw new Error("@aws-sdk/util-endpoint - endpointProvider and endpoint missing in config for this client."); + } + const { endpoint } = input; + if (endpoint === void 0) { + input.endpoint = async () => { + return toEndpointV1( + input.endpointProvider( + { + Region: typeof input.region === "function" ? await input.region() : input.region, + UseDualStack: typeof input.useDualstackEndpoint === "function" ? await input.useDualstackEndpoint() : input.useDualstackEndpoint, + UseFIPS: typeof input.useFipsEndpoint === "function" ? await input.useFipsEndpoint() : input.useFipsEndpoint, + Endpoint: void 0 + }, + { logger: input.logger } + ) + ); + }; + } + return input; +}, "resolveDefaultAwsRegionalEndpointsConfig"); +var toEndpointV1 = /* @__PURE__ */ __name((endpoint) => (0, import_url_parser.parseUrl)(endpoint.url), "toEndpointV1"); + +// src/resolveEndpoint.ts + + +// src/types/EndpointError.ts + + +// src/types/EndpointRuleObject.ts + + +// src/types/ErrorRuleObject.ts + + +// src/types/RuleSetObject.ts + + +// src/types/TreeRuleObject.ts + + +// src/types/shared.ts + +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 51656: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + NODE_APP_ID_CONFIG_OPTIONS: () => NODE_APP_ID_CONFIG_OPTIONS, + UA_APP_ID_ENV_NAME: () => UA_APP_ID_ENV_NAME, + UA_APP_ID_INI_NAME: () => UA_APP_ID_INI_NAME, + createDefaultUserAgentProvider: () => createDefaultUserAgentProvider, + crtAvailability: () => crtAvailability, + defaultUserAgent: () => defaultUserAgent +}); +module.exports = __toCommonJS(index_exports); + +// src/defaultUserAgent.ts +var import_os = __nccwpck_require__(70857); +var import_process = __nccwpck_require__(932); + +// src/crt-availability.ts +var crtAvailability = { + isCrtAvailable: false +}; + +// src/is-crt-available.ts +var isCrtAvailable = /* @__PURE__ */ __name(() => { + if (crtAvailability.isCrtAvailable) { + return ["md/crt-avail"]; + } + return null; +}, "isCrtAvailable"); + +// src/defaultUserAgent.ts +var createDefaultUserAgentProvider = /* @__PURE__ */ __name(({ serviceId, clientVersion }) => { + return async (config) => { + const sections = [ + // sdk-metadata + ["aws-sdk-js", clientVersion], + // ua-metadata + ["ua", "2.1"], + // os-metadata + [`os/${(0, import_os.platform)()}`, (0, import_os.release)()], + // language-metadata + // ECMAScript edition doesn't matter in JS, so no version needed. + ["lang/js"], + ["md/nodejs", `${import_process.versions.node}`] + ]; + const crtAvailable = isCrtAvailable(); + if (crtAvailable) { + sections.push(crtAvailable); + } + if (serviceId) { + sections.push([`api/${serviceId}`, clientVersion]); + } + if (import_process.env.AWS_EXECUTION_ENV) { + sections.push([`exec-env/${import_process.env.AWS_EXECUTION_ENV}`]); + } + const appId = await config?.userAgentAppId?.(); + const resolvedUserAgent = appId ? [...sections, [`app/${appId}`]] : [...sections]; + return resolvedUserAgent; + }; +}, "createDefaultUserAgentProvider"); +var defaultUserAgent = createDefaultUserAgentProvider; + +// src/nodeAppIdConfigOptions.ts +var import_middleware_user_agent = __nccwpck_require__(32959); +var UA_APP_ID_ENV_NAME = "AWS_SDK_UA_APP_ID"; +var UA_APP_ID_INI_NAME = "sdk_ua_app_id"; +var UA_APP_ID_INI_NAME_DEPRECATED = "sdk-ua-app-id"; +var NODE_APP_ID_CONFIG_OPTIONS = { + environmentVariableSelector: /* @__PURE__ */ __name((env2) => env2[UA_APP_ID_ENV_NAME], "environmentVariableSelector"), + configFileSelector: /* @__PURE__ */ __name((profile) => profile[UA_APP_ID_INI_NAME] ?? profile[UA_APP_ID_INI_NAME_DEPRECATED], "configFileSelector"), + default: import_middleware_user_agent.DEFAULT_UA_APP_ID +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 94274: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var index_exports = {}; +__export(index_exports, { + XmlNode: () => XmlNode, + XmlText: () => XmlText +}); +module.exports = __toCommonJS(index_exports); + +// src/escape-attribute.ts +function escapeAttribute(value) { + return value.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); +} +__name(escapeAttribute, "escapeAttribute"); + +// src/escape-element.ts +function escapeElement(value) { + return value.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(//g, ">").replace(/\r/g, " ").replace(/\n/g, " ").replace(/\u0085/g, "…").replace(/\u2028/, "
"); +} +__name(escapeElement, "escapeElement"); + +// src/XmlText.ts +var XmlText = class { + constructor(value) { + this.value = value; + } + static { + __name(this, "XmlText"); + } + toString() { + return escapeElement("" + this.value); + } +}; + +// src/XmlNode.ts +var XmlNode = class _XmlNode { + constructor(name, children = []) { + this.name = name; + this.children = children; + } + static { + __name(this, "XmlNode"); + } + attributes = {}; + static of(name, childText, withName) { + const node = new _XmlNode(name); + if (childText !== void 0) { + node.addChildNode(new XmlText(childText)); + } + if (withName !== void 0) { + node.withName(withName); + } + return node; + } + withName(name) { + this.name = name; + return this; + } + addAttribute(name, value) { + this.attributes[name] = value; + return this; + } + addChildNode(child) { + this.children.push(child); + return this; + } + removeAttribute(name) { + delete this.attributes[name]; + return this; + } + /** + * @internal + * Alias of {@link XmlNode#withName(string)} for codegen brevity. + */ + n(name) { + this.name = name; + return this; + } + /** + * @internal + * Alias of {@link XmlNode#addChildNode(string)} for codegen brevity. + */ + c(child) { + this.children.push(child); + return this; + } + /** + * @internal + * Checked version of {@link XmlNode#addAttribute(string)} for codegen brevity. + */ + a(name, value) { + if (value != null) { + this.attributes[name] = value; + } + return this; + } + /** + * Create a child node. + * Used in serialization of string fields. + * @internal + */ + cc(input, field, withName = field) { + if (input[field] != null) { + const node = _XmlNode.of(field, input[field]).withName(withName); + this.c(node); + } + } + /** + * Creates list child nodes. + * @internal + */ + l(input, listName, memberName, valueProvider) { + if (input[listName] != null) { + const nodes = valueProvider(); + nodes.map((node) => { + node.withName(memberName); + this.c(node); + }); + } + } + /** + * Creates list child nodes with container. + * @internal + */ + lc(input, listName, memberName, valueProvider) { + if (input[listName] != null) { + const nodes = valueProvider(); + const containerNode = new _XmlNode(memberName); + nodes.map((node) => { + containerNode.c(node); + }); + this.c(containerNode); + } + } + toString() { + const hasChildren = Boolean(this.children.length); + let xmlText = `<${this.name}`; + const attributes = this.attributes; + for (const attributeName of Object.keys(attributes)) { + const attribute = attributes[attributeName]; + if (attribute != null) { + xmlText += ` ${attributeName}="${escapeAttribute("" + attribute)}"`; + } + } + return xmlText += !hasChildren ? "/>" : `>${this.children.map((c) => c.toString()).join("")}`; + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 99469: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/*! + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ResourceStream = exports.paginator = exports.Paginator = void 0; +/*! + * @module common/paginator + */ +const arrify = __nccwpck_require__(26251); +const extend = __nccwpck_require__(23860); +const resource_stream_1 = __nccwpck_require__(97618); +Object.defineProperty(exports, "ResourceStream", ({ enumerable: true, get: function () { return resource_stream_1.ResourceStream; } })); +/*! Developer Documentation + * + * paginator is used to auto-paginate `nextQuery` methods as well as + * streamifying them. + * + * Before: + * + * search.query('done=true', function(err, results, nextQuery) { + * search.query(nextQuery, function(err, results, nextQuery) {}); + * }); + * + * After: + * + * search.query('done=true', function(err, results) {}); + * + * Methods to extend should be written to accept callbacks and return a + * `nextQuery`. + */ +class Paginator { + /** + * Cache the original method, then overwrite it on the Class's prototype. + * + * @param {function} Class - The parent class of the methods to extend. + * @param {string|string[]} methodNames - Name(s) of the methods to extend. + */ + // tslint:disable-next-line:variable-name + extend(Class, methodNames) { + methodNames = arrify(methodNames); + methodNames.forEach(methodName => { + const originalMethod = Class.prototype[methodName]; + // map the original method to a private member + Class.prototype[methodName + '_'] = originalMethod; + // overwrite the original to auto-paginate + /* eslint-disable @typescript-eslint/no-explicit-any */ + Class.prototype[methodName] = function (...args) { + const parsedArguments = paginator.parseArguments_(args); + return paginator.run_(parsedArguments, originalMethod.bind(this)); + }; + }); + } + /** + * Wraps paginated API calls in a readable object stream. + * + * This method simply calls the nextQuery recursively, emitting results to a + * stream. The stream ends when `nextQuery` is null. + * + * `maxResults` will act as a cap for how many results are fetched and emitted + * to the stream. + * + * @param {string} methodName - Name of the method to streamify. + * @return {function} - Wrapped function. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + streamify(methodName) { + return function ( + /* eslint-disable @typescript-eslint/no-explicit-any */ + ...args) { + const parsedArguments = paginator.parseArguments_(args); + const originalMethod = this[methodName + '_'] || this[methodName]; + return paginator.runAsStream_(parsedArguments, originalMethod.bind(this)); + }; + } + /** + * Parse a pseudo-array `arguments` for a query and callback. + * + * @param {array} args - The original `arguments` pseduo-array that the original + * method received. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + parseArguments_(args) { + let query; + let autoPaginate = true; + let maxApiCalls = -1; + let maxResults = -1; + let callback; + const firstArgument = args[0]; + const lastArgument = args[args.length - 1]; + if (typeof firstArgument === 'function') { + callback = firstArgument; + } + else { + query = firstArgument; + } + if (typeof lastArgument === 'function') { + callback = lastArgument; + } + if (typeof query === 'object') { + query = extend(true, {}, query); + // Check if the user only asked for a certain amount of results. + if (query.maxResults && typeof query.maxResults === 'number') { + // `maxResults` is used API-wide. + maxResults = query.maxResults; + } + else if (typeof query.pageSize === 'number') { + // `pageSize` is Pub/Sub's `maxResults`. + maxResults = query.pageSize; + } + if (query.maxApiCalls && typeof query.maxApiCalls === 'number') { + maxApiCalls = query.maxApiCalls; + delete query.maxApiCalls; + } + // maxResults is the user specified limit. + if (maxResults !== -1 || query.autoPaginate === false) { + autoPaginate = false; + } + } + const parsedArguments = { + query: query || {}, + autoPaginate, + maxApiCalls, + maxResults, + callback, + }; + parsedArguments.streamOptions = extend(true, {}, parsedArguments.query); + delete parsedArguments.streamOptions.autoPaginate; + delete parsedArguments.streamOptions.maxResults; + delete parsedArguments.streamOptions.pageSize; + return parsedArguments; + } + /** + * This simply checks to see if `autoPaginate` is set or not, if it's true + * then we buffer all results, otherwise simply call the original method. + * + * @param {array} parsedArguments - Parsed arguments from the original method + * call. + * @param {object=|string=} parsedArguments.query - Query object. This is most + * commonly an object, but to make the API more simple, it can also be a + * string in some places. + * @param {function=} parsedArguments.callback - Callback function. + * @param {boolean} parsedArguments.autoPaginate - Auto-pagination enabled. + * @param {boolean} parsedArguments.maxApiCalls - Maximum API calls to make. + * @param {number} parsedArguments.maxResults - Maximum results to return. + * @param {function} originalMethod - The cached method that accepts a callback + * and returns `nextQuery` to receive more results. + */ + run_(parsedArguments, originalMethod) { + const query = parsedArguments.query; + const callback = parsedArguments.callback; + if (!parsedArguments.autoPaginate) { + return originalMethod(query, callback); + } + const results = new Array(); + let otherArgs = []; + const promise = new Promise((resolve, reject) => { + const stream = paginator.runAsStream_(parsedArguments, originalMethod); + stream + .on('error', reject) + .on('data', (data) => results.push(data)) + .on('end', () => { + otherArgs = stream._otherArgs || []; + resolve(results); + }); + }); + if (!callback) { + return promise.then(results => [results, query, ...otherArgs]); + } + promise.then(results => callback(null, results, query, ...otherArgs), (err) => callback(err)); + } + /** + * This method simply calls the nextQuery recursively, emitting results to a + * stream. The stream ends when `nextQuery` is null. + * + * `maxResults` will act as a cap for how many results are fetched and emitted + * to the stream. + * + * @param {object=|string=} parsedArguments.query - Query object. This is most + * commonly an object, but to make the API more simple, it can also be a + * string in some places. + * @param {function=} parsedArguments.callback - Callback function. + * @param {boolean} parsedArguments.autoPaginate - Auto-pagination enabled. + * @param {boolean} parsedArguments.maxApiCalls - Maximum API calls to make. + * @param {number} parsedArguments.maxResults - Maximum results to return. + * @param {function} originalMethod - The cached method that accepts a callback + * and returns `nextQuery` to receive more results. + * @return {stream} - Readable object stream. + */ + /* eslint-disable @typescript-eslint/no-explicit-any */ + runAsStream_(parsedArguments, originalMethod) { + return new resource_stream_1.ResourceStream(parsedArguments, originalMethod); + } +} +exports.Paginator = Paginator; +const paginator = new Paginator(); +exports.paginator = paginator; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 97618: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/*! + * Copyright 2019 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ResourceStream = void 0; +const stream_1 = __nccwpck_require__(2203); +class ResourceStream extends stream_1.Transform { + constructor(args, requestFn) { + const options = Object.assign({ objectMode: true }, args.streamOptions); + super(options); + this._ended = false; + this._maxApiCalls = args.maxApiCalls === -1 ? Infinity : args.maxApiCalls; + this._nextQuery = args.query; + this._reading = false; + this._requestFn = requestFn; + this._requestsMade = 0; + this._resultsToSend = args.maxResults === -1 ? Infinity : args.maxResults; + this._otherArgs = []; + } + /* eslint-disable @typescript-eslint/no-explicit-any */ + end(...args) { + this._ended = true; + return super.end(...args); + } + _read() { + if (this._reading) { + return; + } + this._reading = true; + // Wrap in a try/catch to catch input linting errors, e.g. + // an invalid BigQuery query. These errors are thrown in an + // async fashion, which makes them un-catchable by the user. + try { + this._requestFn(this._nextQuery, (err, results, nextQuery, ...otherArgs) => { + if (err) { + this.destroy(err); + return; + } + this._otherArgs = otherArgs; + this._nextQuery = nextQuery; + if (this._resultsToSend !== Infinity) { + results = results.splice(0, this._resultsToSend); + this._resultsToSend -= results.length; + } + let more = true; + for (const result of results) { + if (this._ended) { + break; + } + more = this.push(result); + } + const isFinished = !this._nextQuery || this._resultsToSend < 1; + const madeMaxCalls = ++this._requestsMade >= this._maxApiCalls; + if (isFinished || madeMaxCalls) { + this.end(); + } + if (more && !this._ended) { + setImmediate(() => this._read()); + } + this._reading = false; + }); + } + catch (e) { + this.destroy(e); + } + } +} +exports.ResourceStream = ResourceStream; +//# sourceMappingURL=resource-stream.js.map + +/***/ }), + +/***/ 87635: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.MissingProjectIdError = exports.replaceProjectIdToken = void 0; +const stream_1 = __nccwpck_require__(2203); +// Copyright 2014 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/** + * Populate the `{{projectId}}` placeholder. + * + * @throws {Error} If a projectId is required, but one is not provided. + * + * @param {*} - Any input value that may contain a placeholder. Arrays and objects will be looped. + * @param {string} projectId - A projectId. If not provided + * @return {*} - The original argument with all placeholders populated. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function replaceProjectIdToken(value, projectId) { + if (Array.isArray(value)) { + value = value.map(v => replaceProjectIdToken(v, projectId)); + } + if (value !== null && + typeof value === 'object' && + !(value instanceof Buffer) && + !(value instanceof stream_1.Stream) && + typeof value.hasOwnProperty === 'function') { + for (const opt in value) { + // eslint-disable-next-line no-prototype-builtins + if (value.hasOwnProperty(opt)) { + value[opt] = replaceProjectIdToken(value[opt], projectId); + } + } + } + if (typeof value === 'string' && + value.indexOf('{{projectId}}') > -1) { + if (!projectId || projectId === '{{projectId}}') { + throw new MissingProjectIdError(); + } + value = value.replace(/{{projectId}}/g, projectId); + } + return value; +} +exports.replaceProjectIdToken = replaceProjectIdToken; +/** + * Custom error type for missing project ID errors. + */ +class MissingProjectIdError extends Error { + constructor() { + super(...arguments); + this.message = `Sorry, we cannot connect to Cloud Services without a project + ID. You may specify one with an environment variable named + "GOOGLE_CLOUD_PROJECT".`.replace(/ +/g, ' '); + } +} +exports.MissingProjectIdError = MissingProjectIdError; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 60206: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/* eslint-disable prefer-rest-params */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.callbackifyAll = exports.callbackify = exports.promisifyAll = exports.promisify = void 0; +/** + * Wraps a callback style function to conditionally return a promise. + * + * @param {function} originalMethod - The method to promisify. + * @param {object=} options - Promise options. + * @param {boolean} options.singular - Resolve the promise with single arg instead of an array. + * @return {function} wrapped + */ +function promisify(originalMethod, options) { + if (originalMethod.promisified_) { + return originalMethod; + } + options = options || {}; + const slice = Array.prototype.slice; + // tslint:disable-next-line:no-any + const wrapper = function () { + let last; + for (last = arguments.length - 1; last >= 0; last--) { + const arg = arguments[last]; + if (typeof arg === 'undefined') { + continue; // skip trailing undefined. + } + if (typeof arg !== 'function') { + break; // non-callback last argument found. + } + return originalMethod.apply(this, arguments); + } + // peel trailing undefined. + const args = slice.call(arguments, 0, last + 1); + // tslint:disable-next-line:variable-name + let PromiseCtor = Promise; + // Because dedupe will likely create a single install of + // @google-cloud/common to be shared amongst all modules, we need to + // localize it at the Service level. + if (this && this.Promise) { + PromiseCtor = this.Promise; + } + return new PromiseCtor((resolve, reject) => { + // tslint:disable-next-line:no-any + args.push((...args) => { + const callbackArgs = slice.call(args); + const err = callbackArgs.shift(); + if (err) { + return reject(err); + } + if (options.singular && callbackArgs.length === 1) { + resolve(callbackArgs[0]); + } + else { + resolve(callbackArgs); + } + }); + originalMethod.apply(this, args); + }); + }; + wrapper.promisified_ = true; + return wrapper; +} +exports.promisify = promisify; +/** + * Promisifies certain Class methods. This will not promisify private or + * streaming methods. + * + * @param {module:common/service} Class - Service class. + * @param {object=} options - Configuration object. + */ +// tslint:disable-next-line:variable-name +function promisifyAll(Class, options) { + const exclude = (options && options.exclude) || []; + const ownPropertyNames = Object.getOwnPropertyNames(Class.prototype); + const methods = ownPropertyNames.filter(methodName => { + // clang-format off + return (!exclude.includes(methodName) && + typeof Class.prototype[methodName] === 'function' && // is it a function? + !/(^_|(Stream|_)|promise$)|^constructor$/.test(methodName) // is it promisable? + ); + // clang-format on + }); + methods.forEach(methodName => { + const originalMethod = Class.prototype[methodName]; + if (!originalMethod.promisified_) { + Class.prototype[methodName] = exports.promisify(originalMethod, options); + } + }); +} +exports.promisifyAll = promisifyAll; +/** + * Wraps a promisy type function to conditionally call a callback function. + * + * @param {function} originalMethod - The method to callbackify. + * @param {object=} options - Callback options. + * @param {boolean} options.singular - Pass to the callback a single arg instead of an array. + * @return {function} wrapped + */ +function callbackify(originalMethod) { + if (originalMethod.callbackified_) { + return originalMethod; + } + // tslint:disable-next-line:no-any + const wrapper = function () { + if (typeof arguments[arguments.length - 1] !== 'function') { + return originalMethod.apply(this, arguments); + } + const cb = Array.prototype.pop.call(arguments); + originalMethod.apply(this, arguments).then( + // tslint:disable-next-line:no-any + (res) => { + res = Array.isArray(res) ? res : [res]; + cb(null, ...res); + }, (err) => cb(err)); + }; + wrapper.callbackified_ = true; + return wrapper; +} +exports.callbackify = callbackify; +/** + * Callbackifies certain Class methods. This will not callbackify private or + * streaming methods. + * + * @param {module:common/service} Class - Service class. + * @param {object=} options - Configuration object. + */ +function callbackifyAll( +// tslint:disable-next-line:variable-name +Class, options) { + const exclude = (options && options.exclude) || []; + const ownPropertyNames = Object.getOwnPropertyNames(Class.prototype); + const methods = ownPropertyNames.filter(methodName => { + // clang-format off + return (!exclude.includes(methodName) && + typeof Class.prototype[methodName] === 'function' && // is it a function? + !/^_|(Stream|_)|^constructor$/.test(methodName) // is it callbackifyable? + ); + // clang-format on + }); + methods.forEach(methodName => { + const originalMethod = Class.prototype[methodName]; + if (!originalMethod.callbackified_) { + Class.prototype[methodName] = exports.callbackify(originalMethod); + } + }); +} +exports.callbackifyAll = callbackifyAll; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 1290: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const validator = __nccwpck_require__(67266); +const XMLParser = __nccwpck_require__(44079); +const XMLBuilder = __nccwpck_require__(79708); + +module.exports = { + XMLParser: XMLParser, + XMLValidator: validator, + XMLBuilder: XMLBuilder +} + +/***/ }), + +/***/ 9209: +/***/ ((module) => { + +function getIgnoreAttributesFn(ignoreAttributes) { + if (typeof ignoreAttributes === 'function') { + return ignoreAttributes + } + if (Array.isArray(ignoreAttributes)) { + return (attrName) => { + for (const pattern of ignoreAttributes) { + if (typeof pattern === 'string' && attrName === pattern) { + return true + } + if (pattern instanceof RegExp && pattern.test(attrName)) { + return true + } + } + } + } + return () => false +} + +module.exports = getIgnoreAttributesFn + +/***/ }), + +/***/ 55506: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +const nameStartChar = ':A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD'; +const nameChar = nameStartChar + '\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040'; +const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*' +const regexName = new RegExp('^' + nameRegexp + '$'); + +const getAllMatches = function(string, regex) { + const matches = []; + let match = regex.exec(string); + while (match) { + const allmatches = []; + allmatches.startIndex = regex.lastIndex - match[0].length; + const len = match.length; + for (let index = 0; index < len; index++) { + allmatches.push(match[index]); + } + matches.push(allmatches); + match = regex.exec(string); + } + return matches; +}; + +const isName = function(string) { + const match = regexName.exec(string); + return !(match === null || typeof match === 'undefined'); +}; + +exports.isExist = function(v) { + return typeof v !== 'undefined'; +}; + +exports.isEmptyObject = function(obj) { + return Object.keys(obj).length === 0; +}; + +/** + * Copy all the properties of a into b. + * @param {*} target + * @param {*} a + */ +exports.merge = function(target, a, arrayMode) { + if (a) { + const keys = Object.keys(a); // will return an array of own properties + const len = keys.length; //don't make it inline + for (let i = 0; i < len; i++) { + if (arrayMode === 'strict') { + target[keys[i]] = [ a[keys[i]] ]; + } else { + target[keys[i]] = a[keys[i]]; + } + } + } +}; +/* exports.merge =function (b,a){ + return Object.assign(b,a); +} */ + +exports.getValue = function(v) { + if (exports.isExist(v)) { + return v; + } else { + return ''; + } +}; + +// const fakeCall = function(a) {return a;}; +// const fakeCallNoReturn = function() {}; + +exports.isName = isName; +exports.getAllMatches = getAllMatches; +exports.nameRegexp = nameRegexp; + + +/***/ }), + +/***/ 67266: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +const util = __nccwpck_require__(55506); + +const defaultOptions = { + allowBooleanAttributes: false, //A tag can have attributes without any value + unpairedTags: [] +}; + +//const tagsPattern = new RegExp("<\\/?([\\w:\\-_\.]+)\\s*\/?>","g"); +exports.validate = function (xmlData, options) { + options = Object.assign({}, defaultOptions, options); + + //xmlData = xmlData.replace(/(\r\n|\n|\r)/gm,"");//make it single line + //xmlData = xmlData.replace(/(^\s*<\?xml.*?\?>)/g,"");//Remove XML starting tag + //xmlData = xmlData.replace(/()/g,"");//Remove DOCTYPE + const tags = []; + let tagFound = false; + + //indicates that the root tag has been closed (aka. depth 0 has been reached) + let reachedRoot = false; + + if (xmlData[0] === '\ufeff') { + // check for byte order mark (BOM) + xmlData = xmlData.substr(1); + } + + for (let i = 0; i < xmlData.length; i++) { + + if (xmlData[i] === '<' && xmlData[i+1] === '?') { + i+=2; + i = readPI(xmlData,i); + if (i.err) return i; + }else if (xmlData[i] === '<') { + //starting of tag + //read until you reach to '>' avoiding any '>' in attribute value + let tagStartPos = i; + i++; + + if (xmlData[i] === '!') { + i = readCommentAndCDATA(xmlData, i); + continue; + } else { + let closingTag = false; + if (xmlData[i] === '/') { + //closing tag + closingTag = true; + i++; + } + //read tagname + let tagName = ''; + for (; i < xmlData.length && + xmlData[i] !== '>' && + xmlData[i] !== ' ' && + xmlData[i] !== '\t' && + xmlData[i] !== '\n' && + xmlData[i] !== '\r'; i++ + ) { + tagName += xmlData[i]; + } + tagName = tagName.trim(); + //console.log(tagName); + + if (tagName[tagName.length - 1] === '/') { + //self closing tag without attributes + tagName = tagName.substring(0, tagName.length - 1); + //continue; + i--; + } + if (!validateTagName(tagName)) { + let msg; + if (tagName.trim().length === 0) { + msg = "Invalid space after '<'."; + } else { + msg = "Tag '"+tagName+"' is an invalid name."; + } + return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i)); + } + + const result = readAttributeStr(xmlData, i); + if (result === false) { + return getErrorObject('InvalidAttr', "Attributes for '"+tagName+"' have open quote.", getLineNumberForPosition(xmlData, i)); + } + let attrStr = result.value; + i = result.index; + + if (attrStr[attrStr.length - 1] === '/') { + //self closing tag + const attrStrStart = i - attrStr.length; + attrStr = attrStr.substring(0, attrStr.length - 1); + const isValid = validateAttributeString(attrStr, options); + if (isValid === true) { + tagFound = true; + //continue; //text may presents after self closing tag + } else { + //the result from the nested function returns the position of the error within the attribute + //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute + //this gives us the absolute index in the entire xml, which we can use to find the line at last + return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line)); + } + } else if (closingTag) { + if (!result.tagClosed) { + return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' doesn't have proper closing.", getLineNumberForPosition(xmlData, i)); + } else if (attrStr.trim().length > 0) { + return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos)); + } else if (tags.length === 0) { + return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' has not been opened.", getLineNumberForPosition(xmlData, tagStartPos)); + } else { + const otg = tags.pop(); + if (tagName !== otg.tagName) { + let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos); + return getErrorObject('InvalidTag', + "Expected closing tag '"+otg.tagName+"' (opened in line "+openPos.line+", col "+openPos.col+") instead of closing tag '"+tagName+"'.", + getLineNumberForPosition(xmlData, tagStartPos)); + } + + //when there are no more tags, we reached the root level. + if (tags.length == 0) { + reachedRoot = true; + } + } + } else { + const isValid = validateAttributeString(attrStr, options); + if (isValid !== true) { + //the result from the nested function returns the position of the error within the attribute + //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute + //this gives us the absolute index in the entire xml, which we can use to find the line at last + return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line)); + } + + //if the root level has been reached before ... + if (reachedRoot === true) { + return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i)); + } else if(options.unpairedTags.indexOf(tagName) !== -1){ + //don't push into stack + } else { + tags.push({tagName, tagStartPos}); + } + tagFound = true; + } + + //skip tag text value + //It may include comments and CDATA value + for (i++; i < xmlData.length; i++) { + if (xmlData[i] === '<') { + if (xmlData[i + 1] === '!') { + //comment or CADATA + i++; + i = readCommentAndCDATA(xmlData, i); + continue; + } else if (xmlData[i+1] === '?') { + i = readPI(xmlData, ++i); + if (i.err) return i; + } else{ + break; + } + } else if (xmlData[i] === '&') { + const afterAmp = validateAmpersand(xmlData, i); + if (afterAmp == -1) + return getErrorObject('InvalidChar', "char '&' is not expected.", getLineNumberForPosition(xmlData, i)); + i = afterAmp; + }else{ + if (reachedRoot === true && !isWhiteSpace(xmlData[i])) { + return getErrorObject('InvalidXml', "Extra text at the end", getLineNumberForPosition(xmlData, i)); + } + } + } //end of reading tag text value + if (xmlData[i] === '<') { + i--; + } + } + } else { + if ( isWhiteSpace(xmlData[i])) { + continue; + } + return getErrorObject('InvalidChar', "char '"+xmlData[i]+"' is not expected.", getLineNumberForPosition(xmlData, i)); + } + } + + if (!tagFound) { + return getErrorObject('InvalidXml', 'Start tag expected.', 1); + }else if (tags.length == 1) { + return getErrorObject('InvalidTag', "Unclosed tag '"+tags[0].tagName+"'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos)); + }else if (tags.length > 0) { + return getErrorObject('InvalidXml', "Invalid '"+ + JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\r?\n/g, '')+ + "' found.", {line: 1, col: 1}); + } + + return true; +}; + +function isWhiteSpace(char){ + return char === ' ' || char === '\t' || char === '\n' || char === '\r'; +} +/** + * Read Processing insstructions and skip + * @param {*} xmlData + * @param {*} i + */ +function readPI(xmlData, i) { + const start = i; + for (; i < xmlData.length; i++) { + if (xmlData[i] == '?' || xmlData[i] == ' ') { + //tagname + const tagname = xmlData.substr(start, i - start); + if (i > 5 && tagname === 'xml') { + return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i)); + } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') { + //check if valid attribut string + i++; + break; + } else { + continue; + } + } + } + return i; +} + +function readCommentAndCDATA(xmlData, i) { + if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') { + //comment + for (i += 3; i < xmlData.length; i++) { + if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') { + i += 2; + break; + } + } + } else if ( + xmlData.length > i + 8 && + xmlData[i + 1] === 'D' && + xmlData[i + 2] === 'O' && + xmlData[i + 3] === 'C' && + xmlData[i + 4] === 'T' && + xmlData[i + 5] === 'Y' && + xmlData[i + 6] === 'P' && + xmlData[i + 7] === 'E' + ) { + let angleBracketsCount = 1; + for (i += 8; i < xmlData.length; i++) { + if (xmlData[i] === '<') { + angleBracketsCount++; + } else if (xmlData[i] === '>') { + angleBracketsCount--; + if (angleBracketsCount === 0) { + break; + } + } + } + } else if ( + xmlData.length > i + 9 && + xmlData[i + 1] === '[' && + xmlData[i + 2] === 'C' && + xmlData[i + 3] === 'D' && + xmlData[i + 4] === 'A' && + xmlData[i + 5] === 'T' && + xmlData[i + 6] === 'A' && + xmlData[i + 7] === '[' + ) { + for (i += 8; i < xmlData.length; i++) { + if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') { + i += 2; + break; + } + } + } + + return i; +} + +const doubleQuote = '"'; +const singleQuote = "'"; + +/** + * Keep reading xmlData until '<' is found outside the attribute value. + * @param {string} xmlData + * @param {number} i + */ +function readAttributeStr(xmlData, i) { + let attrStr = ''; + let startChar = ''; + let tagClosed = false; + for (; i < xmlData.length; i++) { + if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) { + if (startChar === '') { + startChar = xmlData[i]; + } else if (startChar !== xmlData[i]) { + //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa + } else { + startChar = ''; + } + } else if (xmlData[i] === '>') { + if (startChar === '') { + tagClosed = true; + break; + } + } + attrStr += xmlData[i]; + } + if (startChar !== '') { + return false; + } + + return { + value: attrStr, + index: i, + tagClosed: tagClosed + }; +} + +/** + * Select all the attributes whether valid or invalid. + */ +const validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s\\S])*?)\\5)?', 'g'); + +//attr, ="sd", a="amit's", a="sd"b="saf", ab cd="" + +function validateAttributeString(attrStr, options) { + //console.log("start:"+attrStr+":end"); + + //if(attrStr.trim().length === 0) return true; //empty string + + const matches = util.getAllMatches(attrStr, validAttrStrRegxp); + const attrNames = {}; + + for (let i = 0; i < matches.length; i++) { + if (matches[i][1].length === 0) { + //nospace before attribute name: a="sd"b="saf" + return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(matches[i])) + } else if (matches[i][3] !== undefined && matches[i][4] === undefined) { + return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' is without value.", getPositionFromMatch(matches[i])); + } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) { + //independent attribute: ab + return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(matches[i])); + } + /* else if(matches[i][6] === undefined){//attribute without value: ab= + return { err: { code:"InvalidAttr",msg:"attribute " + matches[i][2] + " has no value assigned."}}; + } */ + const attrName = matches[i][2]; + if (!validateAttrName(attrName)) { + return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(matches[i])); + } + if (!attrNames.hasOwnProperty(attrName)) { + //check for duplicate attribute. + attrNames[attrName] = 1; + } else { + return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(matches[i])); + } + } + + return true; +} + +function validateNumberAmpersand(xmlData, i) { + let re = /\d/; + if (xmlData[i] === 'x') { + i++; + re = /[\da-fA-F]/; + } + for (; i < xmlData.length; i++) { + if (xmlData[i] === ';') + return i; + if (!xmlData[i].match(re)) + break; + } + return -1; +} + +function validateAmpersand(xmlData, i) { + // https://www.w3.org/TR/xml/#dt-charref + i++; + if (xmlData[i] === ';') + return -1; + if (xmlData[i] === '#') { + i++; + return validateNumberAmpersand(xmlData, i); + } + let count = 0; + for (; i < xmlData.length; i++, count++) { + if (xmlData[i].match(/\w/) && count < 20) + continue; + if (xmlData[i] === ';') + break; + return -1; + } + return i; +} + +function getErrorObject(code, message, lineNumber) { + return { + err: { + code: code, + msg: message, + line: lineNumber.line || lineNumber, + col: lineNumber.col, + }, + }; +} + +function validateAttrName(attrName) { + return util.isName(attrName); +} + +// const startsWithXML = /^xml/i; + +function validateTagName(tagname) { + return util.isName(tagname) /* && !tagname.match(startsWithXML) */; +} + +//this function returns the line number for the character at the given index +function getLineNumberForPosition(xmlData, index) { + const lines = xmlData.substring(0, index).split(/\r?\n/); + return { + line: lines.length, + + // column number is last line's length + 1, because column numbering starts at 1: + col: lines[lines.length - 1].length + 1 + }; +} + +//this function returns the position of the first character of match within attrStr +function getPositionFromMatch(match) { + return match.startIndex + match[1].length; +} + + +/***/ }), + +/***/ 79708: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +//parse Empty Node as self closing node +const buildFromOrderedJs = __nccwpck_require__(80984); +const getIgnoreAttributesFn = __nccwpck_require__(9209) + +const defaultOptions = { + attributeNamePrefix: '@_', + attributesGroupName: false, + textNodeName: '#text', + ignoreAttributes: true, + cdataPropName: false, + format: false, + indentBy: ' ', + suppressEmptyNode: false, + suppressUnpairedNode: true, + suppressBooleanAttributes: true, + tagValueProcessor: function(key, a) { + return a; + }, + attributeValueProcessor: function(attrName, a) { + return a; + }, + preserveOrder: false, + commentPropName: false, + unpairedTags: [], + entities: [ + { regex: new RegExp("&", "g"), val: "&" },//it must be on top + { regex: new RegExp(">", "g"), val: ">" }, + { regex: new RegExp("<", "g"), val: "<" }, + { regex: new RegExp("\'", "g"), val: "'" }, + { regex: new RegExp("\"", "g"), val: """ } + ], + processEntities: true, + stopNodes: [], + // transformTagName: false, + // transformAttributeName: false, + oneListGroup: false +}; + +function Builder(options) { + this.options = Object.assign({}, defaultOptions, options); + if (this.options.ignoreAttributes === true || this.options.attributesGroupName) { + this.isAttribute = function(/*a*/) { + return false; + }; + } else { + this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes) + this.attrPrefixLen = this.options.attributeNamePrefix.length; + this.isAttribute = isAttribute; + } + + this.processTextOrObjNode = processTextOrObjNode + + if (this.options.format) { + this.indentate = indentate; + this.tagEndChar = '>\n'; + this.newLine = '\n'; + } else { + this.indentate = function() { + return ''; + }; + this.tagEndChar = '>'; + this.newLine = ''; + } +} + +Builder.prototype.build = function(jObj) { + if(this.options.preserveOrder){ + return buildFromOrderedJs(jObj, this.options); + }else { + if(Array.isArray(jObj) && this.options.arrayNodeName && this.options.arrayNodeName.length > 1){ + jObj = { + [this.options.arrayNodeName] : jObj + } + } + return this.j2x(jObj, 0, []).val; + } +}; + +Builder.prototype.j2x = function(jObj, level, ajPath) { + let attrStr = ''; + let val = ''; + const jPath = ajPath.join('.') + for (let key in jObj) { + if(!Object.prototype.hasOwnProperty.call(jObj, key)) continue; + if (typeof jObj[key] === 'undefined') { + // supress undefined node only if it is not an attribute + if (this.isAttribute(key)) { + val += ''; + } + } else if (jObj[key] === null) { + // null attribute should be ignored by the attribute list, but should not cause the tag closing + if (this.isAttribute(key)) { + val += ''; + } else if (key === this.options.cdataPropName) { + val += ''; + } else if (key[0] === '?') { + val += this.indentate(level) + '<' + key + '?' + this.tagEndChar; + } else { + val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + } + // val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + } else if (jObj[key] instanceof Date) { + val += this.buildTextValNode(jObj[key], key, '', level); + } else if (typeof jObj[key] !== 'object') { + //premitive type + const attr = this.isAttribute(key); + if (attr && !this.ignoreAttributesFn(attr, jPath)) { + attrStr += this.buildAttrPairStr(attr, '' + jObj[key]); + } else if (!attr) { + //tag value + if (key === this.options.textNodeName) { + let newval = this.options.tagValueProcessor(key, '' + jObj[key]); + val += this.replaceEntitiesValue(newval); + } else { + val += this.buildTextValNode(jObj[key], key, '', level); + } + } + } else if (Array.isArray(jObj[key])) { + //repeated nodes + const arrLen = jObj[key].length; + let listTagVal = ""; + let listTagAttr = ""; + for (let j = 0; j < arrLen; j++) { + const item = jObj[key][j]; + if (typeof item === 'undefined') { + // supress undefined node + } else if (item === null) { + if(key[0] === "?") val += this.indentate(level) + '<' + key + '?' + this.tagEndChar; + else val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + // val += this.indentate(level) + '<' + key + '/' + this.tagEndChar; + } else if (typeof item === 'object') { + if(this.options.oneListGroup){ + const result = this.j2x(item, level + 1, ajPath.concat(key)); + listTagVal += result.val; + if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) { + listTagAttr += result.attrStr + } + }else{ + listTagVal += this.processTextOrObjNode(item, key, level, ajPath) + } + } else { + if (this.options.oneListGroup) { + let textValue = this.options.tagValueProcessor(key, item); + textValue = this.replaceEntitiesValue(textValue); + listTagVal += textValue; + } else { + listTagVal += this.buildTextValNode(item, key, '', level); + } + } + } + if(this.options.oneListGroup){ + listTagVal = this.buildObjectNode(listTagVal, key, listTagAttr, level); + } + val += listTagVal; + } else { + //nested node + if (this.options.attributesGroupName && key === this.options.attributesGroupName) { + const Ks = Object.keys(jObj[key]); + const L = Ks.length; + for (let j = 0; j < L; j++) { + attrStr += this.buildAttrPairStr(Ks[j], '' + jObj[key][Ks[j]]); + } + } else { + val += this.processTextOrObjNode(jObj[key], key, level, ajPath) + } + } + } + return {attrStr: attrStr, val: val}; +}; + +Builder.prototype.buildAttrPairStr = function(attrName, val){ + val = this.options.attributeValueProcessor(attrName, '' + val); + val = this.replaceEntitiesValue(val); + if (this.options.suppressBooleanAttributes && val === "true") { + return ' ' + attrName; + } else return ' ' + attrName + '="' + val + '"'; +} + +function processTextOrObjNode (object, key, level, ajPath) { + const result = this.j2x(object, level + 1, ajPath.concat(key)); + if (object[this.options.textNodeName] !== undefined && Object.keys(object).length === 1) { + return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level); + } else { + return this.buildObjectNode(result.val, key, result.attrStr, level); + } +} + +Builder.prototype.buildObjectNode = function(val, key, attrStr, level) { + if(val === ""){ + if(key[0] === "?") return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar; + else { + return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar; + } + }else{ + + let tagEndExp = '' + val + tagEndExp ); + } else if (this.options.commentPropName !== false && key === this.options.commentPropName && piClosingChar.length === 0) { + return this.indentate(level) + `` + this.newLine; + }else { + return ( + this.indentate(level) + '<' + key + attrStr + piClosingChar + this.tagEndChar + + val + + this.indentate(level) + tagEndExp ); + } + } +} + +Builder.prototype.closeTag = function(key){ + let closeTag = ""; + if(this.options.unpairedTags.indexOf(key) !== -1){ //unpaired + if(!this.options.suppressUnpairedNode) closeTag = "/" + }else if(this.options.suppressEmptyNode){ //empty + closeTag = "/"; + }else{ + closeTag = `>` + this.newLine; + }else if (this.options.commentPropName !== false && key === this.options.commentPropName) { + return this.indentate(level) + `` + this.newLine; + }else if(key[0] === "?") {//PI tag + return this.indentate(level) + '<' + key + attrStr+ '?' + this.tagEndChar; + }else{ + let textValue = this.options.tagValueProcessor(key, val); + textValue = this.replaceEntitiesValue(textValue); + + if( textValue === ''){ + return this.indentate(level) + '<' + key + attrStr + this.closeTag(key) + this.tagEndChar; + }else{ + return this.indentate(level) + '<' + key + attrStr + '>' + + textValue + + ' 0 && this.options.processEntities){ + for (let i=0; i { + +const EOL = "\n"; + +/** + * + * @param {array} jArray + * @param {any} options + * @returns + */ +function toXml(jArray, options) { + let indentation = ""; + if (options.format && options.indentBy.length > 0) { + indentation = EOL; + } + return arrToStr(jArray, options, "", indentation); +} + +function arrToStr(arr, options, jPath, indentation) { + let xmlStr = ""; + let isPreviousElementTag = false; + + for (let i = 0; i < arr.length; i++) { + const tagObj = arr[i]; + const tagName = propName(tagObj); + if(tagName === undefined) continue; + + let newJPath = ""; + if (jPath.length === 0) newJPath = tagName + else newJPath = `${jPath}.${tagName}`; + + if (tagName === options.textNodeName) { + let tagText = tagObj[tagName]; + if (!isStopNode(newJPath, options)) { + tagText = options.tagValueProcessor(tagName, tagText); + tagText = replaceEntitiesValue(tagText, options); + } + if (isPreviousElementTag) { + xmlStr += indentation; + } + xmlStr += tagText; + isPreviousElementTag = false; + continue; + } else if (tagName === options.cdataPropName) { + if (isPreviousElementTag) { + xmlStr += indentation; + } + xmlStr += ``; + isPreviousElementTag = false; + continue; + } else if (tagName === options.commentPropName) { + xmlStr += indentation + ``; + isPreviousElementTag = true; + continue; + } else if (tagName[0] === "?") { + const attStr = attr_to_str(tagObj[":@"], options); + const tempInd = tagName === "?xml" ? "" : indentation; + let piTextNodeName = tagObj[tagName][0][options.textNodeName]; + piTextNodeName = piTextNodeName.length !== 0 ? " " + piTextNodeName : ""; //remove extra spacing + xmlStr += tempInd + `<${tagName}${piTextNodeName}${attStr}?>`; + isPreviousElementTag = true; + continue; + } + let newIdentation = indentation; + if (newIdentation !== "") { + newIdentation += options.indentBy; + } + const attStr = attr_to_str(tagObj[":@"], options); + const tagStart = indentation + `<${tagName}${attStr}`; + const tagValue = arrToStr(tagObj[tagName], options, newJPath, newIdentation); + if (options.unpairedTags.indexOf(tagName) !== -1) { + if (options.suppressUnpairedNode) xmlStr += tagStart + ">"; + else xmlStr += tagStart + "/>"; + } else if ((!tagValue || tagValue.length === 0) && options.suppressEmptyNode) { + xmlStr += tagStart + "/>"; + } else if (tagValue && tagValue.endsWith(">")) { + xmlStr += tagStart + `>${tagValue}${indentation}`; + } else { + xmlStr += tagStart + ">"; + if (tagValue && indentation !== "" && (tagValue.includes("/>") || tagValue.includes("`; + } + isPreviousElementTag = true; + } + + return xmlStr; +} + +function propName(obj) { + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if(!obj.hasOwnProperty(key)) continue; + if (key !== ":@") return key; + } +} + +function attr_to_str(attrMap, options) { + let attrStr = ""; + if (attrMap && !options.ignoreAttributes) { + for (let attr in attrMap) { + if(!attrMap.hasOwnProperty(attr)) continue; + let attrVal = options.attributeValueProcessor(attr, attrMap[attr]); + attrVal = replaceEntitiesValue(attrVal, options); + if (attrVal === true && options.suppressBooleanAttributes) { + attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}`; + } else { + attrStr += ` ${attr.substr(options.attributeNamePrefix.length)}="${attrVal}"`; + } + } + } + return attrStr; +} + +function isStopNode(jPath, options) { + jPath = jPath.substr(0, jPath.length - options.textNodeName.length - 1); + let tagName = jPath.substr(jPath.lastIndexOf(".") + 1); + for (let index in options.stopNodes) { + if (options.stopNodes[index] === jPath || options.stopNodes[index] === "*." + tagName) return true; + } + return false; +} + +function replaceEntitiesValue(textValue, options) { + if (textValue && textValue.length > 0 && options.processEntities) { + for (let i = 0; i < options.entities.length; i++) { + const entity = options.entities[i]; + textValue = textValue.replace(entity.regex, entity.val); + } + } + return textValue; +} +module.exports = toXml; + + +/***/ }), + +/***/ 56988: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const util = __nccwpck_require__(55506); + +//TODO: handle comments +function readDocType(xmlData, i){ + + const entities = {}; + if( xmlData[i + 3] === 'O' && + xmlData[i + 4] === 'C' && + xmlData[i + 5] === 'T' && + xmlData[i + 6] === 'Y' && + xmlData[i + 7] === 'P' && + xmlData[i + 8] === 'E') + { + i = i+9; + let angleBracketsCount = 1; + let hasBody = false, comment = false; + let exp = ""; + for(;i') { //Read tag content + if(comment){ + if( xmlData[i - 1] === "-" && xmlData[i - 2] === "-"){ + comment = false; + angleBracketsCount--; + } + }else{ + angleBracketsCount--; + } + if (angleBracketsCount === 0) { + break; + } + }else if( xmlData[i] === '['){ + hasBody = true; + }else{ + exp += xmlData[i]; + } + } + if(angleBracketsCount !== 0){ + throw new Error(`Unclosed DOCTYPE`); + } + }else{ + throw new Error(`Invalid Tag instead of DOCTYPE`); + } + return {entities, i}; +} + +function readEntityExp(xmlData,i){ + //External entities are not supported + // + + //Parameter entities are not supported + // + + //Internal entities are supported + // + + //read EntityName + let entityName = ""; + for (; i < xmlData.length && (xmlData[i] !== "'" && xmlData[i] !== '"' ); i++) { + // if(xmlData[i] === " ") continue; + // else + entityName += xmlData[i]; + } + entityName = entityName.trim(); + if(entityName.indexOf(" ") !== -1) throw new Error("External entites are not supported"); + + //read Entity Value + const startChar = xmlData[i++]; + let val = "" + for (; i < xmlData.length && xmlData[i] !== startChar ; i++) { + val += xmlData[i]; + } + return [entityName, val, i]; +} + +function isComment(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === '-' && + xmlData[i+3] === '-') return true + return false +} +function isEntity(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'E' && + xmlData[i+3] === 'N' && + xmlData[i+4] === 'T' && + xmlData[i+5] === 'I' && + xmlData[i+6] === 'T' && + xmlData[i+7] === 'Y') return true + return false +} +function isElement(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'E' && + xmlData[i+3] === 'L' && + xmlData[i+4] === 'E' && + xmlData[i+5] === 'M' && + xmlData[i+6] === 'E' && + xmlData[i+7] === 'N' && + xmlData[i+8] === 'T') return true + return false +} + +function isAttlist(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'A' && + xmlData[i+3] === 'T' && + xmlData[i+4] === 'T' && + xmlData[i+5] === 'L' && + xmlData[i+6] === 'I' && + xmlData[i+7] === 'S' && + xmlData[i+8] === 'T') return true + return false +} +function isNotation(xmlData, i){ + if(xmlData[i+1] === '!' && + xmlData[i+2] === 'N' && + xmlData[i+3] === 'O' && + xmlData[i+4] === 'T' && + xmlData[i+5] === 'A' && + xmlData[i+6] === 'T' && + xmlData[i+7] === 'I' && + xmlData[i+8] === 'O' && + xmlData[i+9] === 'N') return true + return false +} + +function validateEntityName(name){ + if (util.isName(name)) + return name; + else + throw new Error(`Invalid entity name ${name}`); +} + +module.exports = readDocType; + + +/***/ }), + +/***/ 81392: +/***/ ((__unused_webpack_module, exports) => { + + +const defaultOptions = { + preserveOrder: false, + attributeNamePrefix: '@_', + attributesGroupName: false, + textNodeName: '#text', + ignoreAttributes: true, + removeNSPrefix: false, // remove NS from tag name or attribute name if true + allowBooleanAttributes: false, //a tag can have attributes without any value + //ignoreRootElement : false, + parseTagValue: true, + parseAttributeValue: false, + trimValues: true, //Trim string values of tag and attributes + cdataPropName: false, + numberParseOptions: { + hex: true, + leadingZeros: true, + eNotation: true + }, + tagValueProcessor: function(tagName, val) { + return val; + }, + attributeValueProcessor: function(attrName, val) { + return val; + }, + stopNodes: [], //nested tags will not be parsed even for errors + alwaysCreateTextNode: false, + isArray: () => false, + commentPropName: false, + unpairedTags: [], + processEntities: true, + htmlEntities: false, + ignoreDeclaration: false, + ignorePiTags: false, + transformTagName: false, + transformAttributeName: false, + updateTag: function(tagName, jPath, attrs){ + return tagName + }, + // skipEmptyListItem: false +}; + +const buildOptions = function(options) { + return Object.assign({}, defaultOptions, options); +}; + +exports.buildOptions = buildOptions; +exports.defaultOptions = defaultOptions; + +/***/ }), + +/***/ 19036: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +///@ts-check + +const util = __nccwpck_require__(55506); +const xmlNode = __nccwpck_require__(72964); +const readDocType = __nccwpck_require__(56988); +const toNumber = __nccwpck_require__(82203); +const getIgnoreAttributesFn = __nccwpck_require__(9209) + +// const regx = +// '<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)' +// .replace(/NAME/g, util.nameRegexp); + +//const tagsRegx = new RegExp("<(\\/?[\\w:\\-\._]+)([^>]*)>(\\s*"+cdataRegx+")*([^<]+)?","g"); +//const tagsRegx = new RegExp("<(\\/?)((\\w*:)?([\\w:\\-\._]+))([^>]*)>([^<]*)("+cdataRegx+"([^<]*))*([^<]+)?","g"); + +class OrderedObjParser{ + constructor(options){ + this.options = options; + this.currentNode = null; + this.tagsNodeStack = []; + this.docTypeEntities = {}; + this.lastEntities = { + "apos" : { regex: /&(apos|#39|#x27);/g, val : "'"}, + "gt" : { regex: /&(gt|#62|#x3E);/g, val : ">"}, + "lt" : { regex: /&(lt|#60|#x3C);/g, val : "<"}, + "quot" : { regex: /&(quot|#34|#x22);/g, val : "\""}, + }; + this.ampEntity = { regex: /&(amp|#38|#x26);/g, val : "&"}; + this.htmlEntities = { + "space": { regex: /&(nbsp|#160);/g, val: " " }, + // "lt" : { regex: /&(lt|#60);/g, val: "<" }, + // "gt" : { regex: /&(gt|#62);/g, val: ">" }, + // "amp" : { regex: /&(amp|#38);/g, val: "&" }, + // "quot" : { regex: /&(quot|#34);/g, val: "\"" }, + // "apos" : { regex: /&(apos|#39);/g, val: "'" }, + "cent" : { regex: /&(cent|#162);/g, val: "¢" }, + "pound" : { regex: /&(pound|#163);/g, val: "£" }, + "yen" : { regex: /&(yen|#165);/g, val: "¥" }, + "euro" : { regex: /&(euro|#8364);/g, val: "€" }, + "copyright" : { regex: /&(copy|#169);/g, val: "©" }, + "reg" : { regex: /&(reg|#174);/g, val: "®" }, + "inr" : { regex: /&(inr|#8377);/g, val: "₹" }, + "num_dec": { regex: /&#([0-9]{1,7});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 10)) }, + "num_hex": { regex: /&#x([0-9a-fA-F]{1,6});/g, val : (_, str) => String.fromCharCode(Number.parseInt(str, 16)) }, + }; + this.addExternalEntities = addExternalEntities; + this.parseXml = parseXml; + this.parseTextData = parseTextData; + this.resolveNameSpace = resolveNameSpace; + this.buildAttributesMap = buildAttributesMap; + this.isItStopNode = isItStopNode; + this.replaceEntitiesValue = replaceEntitiesValue; + this.readStopNodeData = readStopNodeData; + this.saveTextToParentTag = saveTextToParentTag; + this.addChild = addChild; + this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes) + } + +} + +function addExternalEntities(externalEntities){ + const entKeys = Object.keys(externalEntities); + for (let i = 0; i < entKeys.length; i++) { + const ent = entKeys[i]; + this.lastEntities[ent] = { + regex: new RegExp("&"+ent+";","g"), + val : externalEntities[ent] + } + } +} + +/** + * @param {string} val + * @param {string} tagName + * @param {string} jPath + * @param {boolean} dontTrim + * @param {boolean} hasAttributes + * @param {boolean} isLeafNode + * @param {boolean} escapeEntities + */ +function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) { + if (val !== undefined) { + if (this.options.trimValues && !dontTrim) { + val = val.trim(); + } + if(val.length > 0){ + if(!escapeEntities) val = this.replaceEntitiesValue(val); + + const newval = this.options.tagValueProcessor(tagName, val, jPath, hasAttributes, isLeafNode); + if(newval === null || newval === undefined){ + //don't parse + return val; + }else if(typeof newval !== typeof val || newval !== val){ + //overwrite + return newval; + }else if(this.options.trimValues){ + return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions); + }else{ + const trimmedVal = val.trim(); + if(trimmedVal === val){ + return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions); + }else{ + return val; + } + } + } + } +} + +function resolveNameSpace(tagname) { + if (this.options.removeNSPrefix) { + const tags = tagname.split(':'); + const prefix = tagname.charAt(0) === '/' ? '/' : ''; + if (tags[0] === 'xmlns') { + return ''; + } + if (tags.length === 2) { + tagname = prefix + tags[1]; + } + } + return tagname; +} + +//TODO: change regex to capture NS +//const attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm"); +const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm'); + +function buildAttributesMap(attrStr, jPath, tagName) { + if (this.options.ignoreAttributes !== true && typeof attrStr === 'string') { + // attrStr = attrStr.replace(/\r?\n/g, ' '); + //attrStr = attrStr || attrStr.trim(); + + const matches = util.getAllMatches(attrStr, attrsRegx); + const len = matches.length; //don't make it inline + const attrs = {}; + for (let i = 0; i < len; i++) { + const attrName = this.resolveNameSpace(matches[i][1]); + if (this.ignoreAttributesFn(attrName, jPath)) { + continue + } + let oldVal = matches[i][4]; + let aName = this.options.attributeNamePrefix + attrName; + if (attrName.length) { + if (this.options.transformAttributeName) { + aName = this.options.transformAttributeName(aName); + } + if(aName === "__proto__") aName = "#__proto__"; + if (oldVal !== undefined) { + if (this.options.trimValues) { + oldVal = oldVal.trim(); + } + oldVal = this.replaceEntitiesValue(oldVal); + const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPath); + if(newVal === null || newVal === undefined){ + //don't parse + attrs[aName] = oldVal; + }else if(typeof newVal !== typeof oldVal || newVal !== oldVal){ + //overwrite + attrs[aName] = newVal; + }else{ + //parse + attrs[aName] = parseValue( + oldVal, + this.options.parseAttributeValue, + this.options.numberParseOptions + ); + } + } else if (this.options.allowBooleanAttributes) { + attrs[aName] = true; + } + } + } + if (!Object.keys(attrs).length) { + return; + } + if (this.options.attributesGroupName) { + const attrCollection = {}; + attrCollection[this.options.attributesGroupName] = attrs; + return attrCollection; + } + return attrs + } +} + +const parseXml = function(xmlData) { + xmlData = xmlData.replace(/\r\n?/g, "\n"); //TODO: remove this line + const xmlObj = new xmlNode('!xml'); + let currentNode = xmlObj; + let textData = ""; + let jPath = ""; + for(let i=0; i< xmlData.length; i++){//for each char in XML data + const ch = xmlData[i]; + if(ch === '<'){ + // const nextIndex = i+1; + // const _2ndChar = xmlData[nextIndex]; + if( xmlData[i+1] === '/') {//Closing Tag + const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.") + let tagName = xmlData.substring(i+2,closeIndex).trim(); + + if(this.options.removeNSPrefix){ + const colonIndex = tagName.indexOf(":"); + if(colonIndex !== -1){ + tagName = tagName.substr(colonIndex+1); + } + } + + if(this.options.transformTagName) { + tagName = this.options.transformTagName(tagName); + } + + if(currentNode){ + textData = this.saveTextToParentTag(textData, currentNode, jPath); + } + + //check if last tag of nested tag was unpaired tag + const lastTagName = jPath.substring(jPath.lastIndexOf(".")+1); + if(tagName && this.options.unpairedTags.indexOf(tagName) !== -1 ){ + throw new Error(`Unpaired tag can not be used as closing tag: `); + } + let propIndex = 0 + if(lastTagName && this.options.unpairedTags.indexOf(lastTagName) !== -1 ){ + propIndex = jPath.lastIndexOf('.', jPath.lastIndexOf('.')-1) + this.tagsNodeStack.pop(); + }else{ + propIndex = jPath.lastIndexOf("."); + } + jPath = jPath.substring(0, propIndex); + + currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope + textData = ""; + i = closeIndex; + } else if( xmlData[i+1] === '?') { + + let tagData = readTagExp(xmlData,i, false, "?>"); + if(!tagData) throw new Error("Pi Tag is not closed."); + + textData = this.saveTextToParentTag(textData, currentNode, jPath); + if( (this.options.ignoreDeclaration && tagData.tagName === "?xml") || this.options.ignorePiTags){ + + }else{ + + const childNode = new xmlNode(tagData.tagName); + childNode.add(this.options.textNodeName, ""); + + if(tagData.tagName !== tagData.tagExp && tagData.attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath, tagData.tagName); + } + this.addChild(currentNode, childNode, jPath) + + } + + + i = tagData.closeIndex + 1; + } else if(xmlData.substr(i + 1, 3) === '!--') { + const endIndex = findClosingIndex(xmlData, "-->", i+4, "Comment is not closed.") + if(this.options.commentPropName){ + const comment = xmlData.substring(i + 4, endIndex - 2); + + textData = this.saveTextToParentTag(textData, currentNode, jPath); + + currentNode.add(this.options.commentPropName, [ { [this.options.textNodeName] : comment } ]); + } + i = endIndex; + } else if( xmlData.substr(i + 1, 2) === '!D') { + const result = readDocType(xmlData, i); + this.docTypeEntities = result.entities; + i = result.i; + }else if(xmlData.substr(i + 1, 2) === '![') { + const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2; + const tagExp = xmlData.substring(i + 9,closeIndex); + + textData = this.saveTextToParentTag(textData, currentNode, jPath); + + let val = this.parseTextData(tagExp, currentNode.tagname, jPath, true, false, true, true); + if(val == undefined) val = ""; + + //cdata should be set even if it is 0 length string + if(this.options.cdataPropName){ + currentNode.add(this.options.cdataPropName, [ { [this.options.textNodeName] : tagExp } ]); + }else{ + currentNode.add(this.options.textNodeName, val); + } + + i = closeIndex + 2; + }else {//Opening tag + let result = readTagExp(xmlData,i, this.options.removeNSPrefix); + let tagName= result.tagName; + const rawTagName = result.rawTagName; + let tagExp = result.tagExp; + let attrExpPresent = result.attrExpPresent; + let closeIndex = result.closeIndex; + + if (this.options.transformTagName) { + tagName = this.options.transformTagName(tagName); + } + + //save text as child node + if (currentNode && textData) { + if(currentNode.tagname !== '!xml'){ + //when nested tag is found + textData = this.saveTextToParentTag(textData, currentNode, jPath, false); + } + } + + //check if last tag was unpaired tag + const lastTag = currentNode; + if(lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1 ){ + currentNode = this.tagsNodeStack.pop(); + jPath = jPath.substring(0, jPath.lastIndexOf(".")); + } + if(tagName !== xmlObj.tagname){ + jPath += jPath ? "." + tagName : tagName; + } + if (this.isItStopNode(this.options.stopNodes, jPath, tagName)) { + let tagContent = ""; + //self-closing tag + if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){ + if(tagName[tagName.length - 1] === "/"){ //remove trailing '/' + tagName = tagName.substr(0, tagName.length - 1); + jPath = jPath.substr(0, jPath.length - 1); + tagExp = tagName; + }else{ + tagExp = tagExp.substr(0, tagExp.length - 1); + } + i = result.closeIndex; + } + //unpaired tag + else if(this.options.unpairedTags.indexOf(tagName) !== -1){ + + i = result.closeIndex; + } + //normal tag + else{ + //read until closing tag is found + const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1); + if(!result) throw new Error(`Unexpected end of ${rawTagName}`); + i = result.i; + tagContent = result.tagContent; + } + + const childNode = new xmlNode(tagName); + if(tagName !== tagExp && attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName); + } + if(tagContent) { + tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true); + } + + jPath = jPath.substr(0, jPath.lastIndexOf(".")); + childNode.add(this.options.textNodeName, tagContent); + + this.addChild(currentNode, childNode, jPath) + }else{ + //selfClosing tag + if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){ + if(tagName[tagName.length - 1] === "/"){ //remove trailing '/' + tagName = tagName.substr(0, tagName.length - 1); + jPath = jPath.substr(0, jPath.length - 1); + tagExp = tagName; + }else{ + tagExp = tagExp.substr(0, tagExp.length - 1); + } + + if(this.options.transformTagName) { + tagName = this.options.transformTagName(tagName); + } + + const childNode = new xmlNode(tagName); + if(tagName !== tagExp && attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName); + } + this.addChild(currentNode, childNode, jPath) + jPath = jPath.substr(0, jPath.lastIndexOf(".")); + } + //opening tag + else{ + const childNode = new xmlNode( tagName); + this.tagsNodeStack.push(currentNode); + + if(tagName !== tagExp && attrExpPresent){ + childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName); + } + this.addChild(currentNode, childNode, jPath) + currentNode = childNode; + } + textData = ""; + i = closeIndex; + } + } + }else{ + textData += xmlData[i]; + } + } + return xmlObj.child; +} + +function addChild(currentNode, childNode, jPath){ + const result = this.options.updateTag(childNode.tagname, jPath, childNode[":@"]) + if(result === false){ + }else if(typeof result === "string"){ + childNode.tagname = result + currentNode.addChild(childNode); + }else{ + currentNode.addChild(childNode); + } +} + +const replaceEntitiesValue = function(val){ + + if(this.options.processEntities){ + for(let entityName in this.docTypeEntities){ + const entity = this.docTypeEntities[entityName]; + val = val.replace( entity.regx, entity.val); + } + for(let entityName in this.lastEntities){ + const entity = this.lastEntities[entityName]; + val = val.replace( entity.regex, entity.val); + } + if(this.options.htmlEntities){ + for(let entityName in this.htmlEntities){ + const entity = this.htmlEntities[entityName]; + val = val.replace( entity.regex, entity.val); + } + } + val = val.replace( this.ampEntity.regex, this.ampEntity.val); + } + return val; +} +function saveTextToParentTag(textData, currentNode, jPath, isLeafNode) { + if (textData) { //store previously collected data as textNode + if(isLeafNode === undefined) isLeafNode = currentNode.child.length === 0 + + textData = this.parseTextData(textData, + currentNode.tagname, + jPath, + false, + currentNode[":@"] ? Object.keys(currentNode[":@"]).length !== 0 : false, + isLeafNode); + + if (textData !== undefined && textData !== "") + currentNode.add(this.options.textNodeName, textData); + textData = ""; + } + return textData; +} + +//TODO: use jPath to simplify the logic +/** + * + * @param {string[]} stopNodes + * @param {string} jPath + * @param {string} currentTagName + */ +function isItStopNode(stopNodes, jPath, currentTagName){ + const allNodesExp = "*." + currentTagName; + for (const stopNodePath in stopNodes) { + const stopNodeExp = stopNodes[stopNodePath]; + if( allNodesExp === stopNodeExp || jPath === stopNodeExp ) return true; + } + return false; +} + +/** + * Returns the tag Expression and where it is ending handling single-double quotes situation + * @param {string} xmlData + * @param {number} i starting index + * @returns + */ +function tagExpWithClosingIndex(xmlData, i, closingChar = ">"){ + let attrBoundary; + let tagExp = ""; + for (let index = i; index < xmlData.length; index++) { + let ch = xmlData[index]; + if (attrBoundary) { + if (ch === attrBoundary) attrBoundary = "";//reset + } else if (ch === '"' || ch === "'") { + attrBoundary = ch; + } else if (ch === closingChar[0]) { + if(closingChar[1]){ + if(xmlData[index + 1] === closingChar[1]){ + return { + data: tagExp, + index: index + } + } + }else{ + return { + data: tagExp, + index: index + } + } + } else if (ch === '\t') { + ch = " " + } + tagExp += ch; + } +} + +function findClosingIndex(xmlData, str, i, errMsg){ + const closingIndex = xmlData.indexOf(str, i); + if(closingIndex === -1){ + throw new Error(errMsg) + }else{ + return closingIndex + str.length - 1; + } +} + +function readTagExp(xmlData,i, removeNSPrefix, closingChar = ">"){ + const result = tagExpWithClosingIndex(xmlData, i+1, closingChar); + if(!result) return; + let tagExp = result.data; + const closeIndex = result.index; + const separatorIndex = tagExp.search(/\s/); + let tagName = tagExp; + let attrExpPresent = true; + if(separatorIndex !== -1){//separate tag name and attributes expression + tagName = tagExp.substring(0, separatorIndex); + tagExp = tagExp.substring(separatorIndex + 1).trimStart(); + } + + const rawTagName = tagName; + if(removeNSPrefix){ + const colonIndex = tagName.indexOf(":"); + if(colonIndex !== -1){ + tagName = tagName.substr(colonIndex+1); + attrExpPresent = tagName !== result.data.substr(colonIndex + 1); + } + } + + return { + tagName: tagName, + tagExp: tagExp, + closeIndex: closeIndex, + attrExpPresent: attrExpPresent, + rawTagName: rawTagName, + } +} +/** + * find paired tag for a stop node + * @param {string} xmlData + * @param {string} tagName + * @param {number} i + */ +function readStopNodeData(xmlData, tagName, i){ + const startIndex = i; + // Starting at 1 since we already have an open tag + let openTagCount = 1; + + for (; i < xmlData.length; i++) { + if( xmlData[i] === "<"){ + if (xmlData[i+1] === "/") {//close tag + const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`); + let closeTagName = xmlData.substring(i+2,closeIndex).trim(); + if(closeTagName === tagName){ + openTagCount--; + if (openTagCount === 0) { + return { + tagContent: xmlData.substring(startIndex, i), + i : closeIndex + } + } + } + i=closeIndex; + } else if(xmlData[i+1] === '?') { + const closeIndex = findClosingIndex(xmlData, "?>", i+1, "StopNode is not closed.") + i=closeIndex; + } else if(xmlData.substr(i + 1, 3) === '!--') { + const closeIndex = findClosingIndex(xmlData, "-->", i+3, "StopNode is not closed.") + i=closeIndex; + } else if(xmlData.substr(i + 1, 2) === '![') { + const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2; + i=closeIndex; + } else { + const tagData = readTagExp(xmlData, i, '>') + + if (tagData) { + const openTagName = tagData && tagData.tagName; + if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length-1] !== "/") { + openTagCount++; + } + i=tagData.closeIndex; + } + } + } + }//end for loop +} + +function parseValue(val, shouldParse, options) { + if (shouldParse && typeof val === 'string') { + //console.log(options) + const newval = val.trim(); + if(newval === 'true' ) return true; + else if(newval === 'false' ) return false; + else return toNumber(val, options); + } else { + if (util.isExist(val)) { + return val; + } else { + return ''; + } + } +} + + +module.exports = OrderedObjParser; + + +/***/ }), + +/***/ 44079: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { buildOptions} = __nccwpck_require__(81392); +const OrderedObjParser = __nccwpck_require__(19036); +const { prettify} = __nccwpck_require__(40185); +const validator = __nccwpck_require__(67266); + +class XMLParser{ + + constructor(options){ + this.externalEntities = {}; + this.options = buildOptions(options); + + } + /** + * Parse XML dats to JS object + * @param {string|Buffer} xmlData + * @param {boolean|Object} validationOption + */ + parse(xmlData,validationOption){ + if(typeof xmlData === "string"){ + }else if( xmlData.toString){ + xmlData = xmlData.toString(); + }else{ + throw new Error("XML data is accepted in String or Bytes[] form.") + } + if( validationOption){ + if(validationOption === true) validationOption = {}; //validate with default options + + const result = validator.validate(xmlData, validationOption); + if (result !== true) { + throw Error( `${result.err.msg}:${result.err.line}:${result.err.col}` ) + } + } + const orderedObjParser = new OrderedObjParser(this.options); + orderedObjParser.addExternalEntities(this.externalEntities); + const orderedResult = orderedObjParser.parseXml(xmlData); + if(this.options.preserveOrder || orderedResult === undefined) return orderedResult; + else return prettify(orderedResult, this.options); + } + + /** + * Add Entity which is not by default supported by this library + * @param {string} key + * @param {string} value + */ + addEntity(key, value){ + if(value.indexOf("&") !== -1){ + throw new Error("Entity value can't have '&'") + }else if(key.indexOf("&") !== -1 || key.indexOf(";") !== -1){ + throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for ' '") + }else if(value === "&"){ + throw new Error("An entity with value '&' is not permitted"); + }else{ + this.externalEntities[key] = value; + } + } +} + +module.exports = XMLParser; + +/***/ }), + +/***/ 40185: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +/** + * + * @param {array} node + * @param {any} options + * @returns + */ +function prettify(node, options){ + return compress( node, options); +} + +/** + * + * @param {array} arr + * @param {object} options + * @param {string} jPath + * @returns object + */ +function compress(arr, options, jPath){ + let text; + const compressedObj = {}; + for (let i = 0; i < arr.length; i++) { + const tagObj = arr[i]; + const property = propName(tagObj); + let newJpath = ""; + if(jPath === undefined) newJpath = property; + else newJpath = jPath + "." + property; + + if(property === options.textNodeName){ + if(text === undefined) text = tagObj[property]; + else text += "" + tagObj[property]; + }else if(property === undefined){ + continue; + }else if(tagObj[property]){ + + let val = compress(tagObj[property], options, newJpath); + const isLeaf = isLeafTag(val, options); + + if(tagObj[":@"]){ + assignAttributes( val, tagObj[":@"], newJpath, options); + }else if(Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode){ + val = val[options.textNodeName]; + }else if(Object.keys(val).length === 0){ + if(options.alwaysCreateTextNode) val[options.textNodeName] = ""; + else val = ""; + } + + if(compressedObj[property] !== undefined && compressedObj.hasOwnProperty(property)) { + if(!Array.isArray(compressedObj[property])) { + compressedObj[property] = [ compressedObj[property] ]; + } + compressedObj[property].push(val); + }else{ + //TODO: if a node is not an array, then check if it should be an array + //also determine if it is a leaf node + if (options.isArray(property, newJpath, isLeaf )) { + compressedObj[property] = [val]; + }else{ + compressedObj[property] = val; + } + } + } + + } + // if(text && text.length > 0) compressedObj[options.textNodeName] = text; + if(typeof text === "string"){ + if(text.length > 0) compressedObj[options.textNodeName] = text; + }else if(text !== undefined) compressedObj[options.textNodeName] = text; + return compressedObj; +} + +function propName(obj){ + const keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if(key !== ":@") return key; + } +} + +function assignAttributes(obj, attrMap, jpath, options){ + if (attrMap) { + const keys = Object.keys(attrMap); + const len = keys.length; //don't make it inline + for (let i = 0; i < len; i++) { + const atrrName = keys[i]; + if (options.isArray(atrrName, jpath + "." + atrrName, true, true)) { + obj[atrrName] = [ attrMap[atrrName] ]; + } else { + obj[atrrName] = attrMap[atrrName]; + } + } + } +} + +function isLeafTag(obj, options){ + const { textNodeName } = options; + const propCount = Object.keys(obj).length; + + if (propCount === 0) { + return true; + } + + if ( + propCount === 1 && + (obj[textNodeName] || typeof obj[textNodeName] === "boolean" || obj[textNodeName] === 0) + ) { + return true; + } + + return false; +} +exports.prettify = prettify; + + +/***/ }), + +/***/ 72964: +/***/ ((module) => { + +"use strict"; + + +class XmlNode{ + constructor(tagname) { + this.tagname = tagname; + this.child = []; //nested tags, text, cdata, comments in order + this[":@"] = {}; //attributes map + } + add(key,val){ + // this.child.push( {name : key, val: val, isCdata: isCdata }); + if(key === "__proto__") key = "#__proto__"; + this.child.push( {[key]: val }); + } + addChild(node) { + if(node.tagname === "__proto__") node.tagname = "#__proto__"; + if(node[":@"] && Object.keys(node[":@"]).length > 0){ + this.child.push( { [node.tagname]: node.child, [":@"]: node[":@"] }); + }else{ + this.child.push( { [node.tagname]: node.child }); + } + }; +}; + + +module.exports = XmlNode; + +/***/ }), + +/***/ 82203: +/***/ ((module) => { + +const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/; +const numRegex = /^([\-\+])?(0*)([0-9]*(\.[0-9]*)?)$/; +// const octRegex = /^0x[a-z0-9]+/; +// const binRegex = /0x[a-z0-9]+/; + + +const consider = { + hex : true, + // oct: false, + leadingZeros: true, + decimalPoint: "\.", + eNotation: true, + //skipLike: /regex/ +}; + +function toNumber(str, options = {}){ + options = Object.assign({}, consider, options ); + if(!str || typeof str !== "string" ) return str; + + let trimmedStr = str.trim(); + + if(options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str; + else if(str==="0") return 0; + else if (options.hex && hexRegex.test(trimmedStr)) { + return parse_int(trimmedStr, 16); + // }else if (options.oct && octRegex.test(str)) { + // return Number.parseInt(val, 8); + }else if (trimmedStr.search(/[eE]/)!== -1) { //eNotation + const notation = trimmedStr.match(/^([-\+])?(0*)([0-9]*(\.[0-9]*)?[eE][-\+]?[0-9]+)$/); + // +00.123 => [ , '+', '00', '.123', .. + if(notation){ + // console.log(notation) + if(options.leadingZeros){ //accept with leading zeros + trimmedStr = (notation[1] || "") + notation[3]; + }else{ + if(notation[2] === "0" && notation[3][0]=== "."){ //valid number + }else{ + return str; + } + } + return options.eNotation ? Number(trimmedStr) : str; + }else{ + return str; + } + // }else if (options.parseBin && binRegex.test(str)) { + // return Number.parseInt(val, 2); + }else{ + //separate negative sign, leading zeros, and rest number + const match = numRegex.exec(trimmedStr); + // +00.123 => [ , '+', '00', '.123', .. + if(match){ + const sign = match[1]; + const leadingZeros = match[2]; + let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros + //trim ending zeros for floating number + + if(!options.leadingZeros && leadingZeros.length > 0 && sign && trimmedStr[2] !== ".") return str; //-0123 + else if(!options.leadingZeros && leadingZeros.length > 0 && !sign && trimmedStr[1] !== ".") return str; //0123 + else if(options.leadingZeros && leadingZeros===str) return 0; //00 + + else{//no leading zeros or leading zeros are allowed + const num = Number(trimmedStr); + const numStr = "" + num; + + if(numStr.search(/[eE]/) !== -1){ //given number is long and parsed to eNotation + if(options.eNotation) return num; + else return str; + }else if(trimmedStr.indexOf(".") !== -1){ //floating number + if(numStr === "0" && (numTrimmedByZeros === "") ) return num; //0.0 + else if(numStr === numTrimmedByZeros) return num; //0.456. 0.79000 + else if( sign && numStr === "-"+numTrimmedByZeros) return num; + else return str; + } + + if(leadingZeros){ + return (numTrimmedByZeros === numStr) || (sign+numTrimmedByZeros === numStr) ? num : str + }else { + return (trimmedStr === numStr) || (trimmedStr === sign+numStr) ? num : str + } + } + }else{ //non-numeric string + return str; + } + } +} + +/** + * + * @param {string} numStr without leading zeros + * @returns + */ +function trimZeros(numStr){ + if(numStr && numStr.indexOf(".") !== -1){//float + numStr = numStr.replace(/0+$/, ""); //remove ending zeros + if(numStr === ".") numStr = "0"; + else if(numStr[0] === ".") numStr = "0"+numStr; + else if(numStr[numStr.length-1] === ".") numStr = numStr.substr(0,numStr.length-1); + return numStr; + } + return numStr; +} + +function parse_int(numStr, base){ + //polyfill + if(parseInt) return parseInt(numStr, base); + else if(Number.parseInt) return Number.parseInt(numStr, base); + else if(window && window.parseInt) return window.parseInt(numStr, base); + else throw new Error("parseInt, Number.parseInt, window.parseInt are not supported") +} + +module.exports = toNumber; + +/***/ }), + +/***/ 20607: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(21150)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(19220)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(4289)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(36658)); + +var _nil = _interopRequireDefault(__nccwpck_require__(97608)); + +var _version = _interopRequireDefault(__nccwpck_require__(25807)); + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +var _parse = _interopRequireDefault(__nccwpck_require__(36712)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 90039: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 97608: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 36712: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 42456: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 18874: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 39490: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 77318: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function stringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 21150: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(18874)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.default)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 19220: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(38465)); + +var _md = _interopRequireDefault(__nccwpck_require__(90039)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 38465: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = _default; +exports.URL = exports.DNS = void 0; + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +var _parse = _interopRequireDefault(__nccwpck_require__(36712)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (namespace.length !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 4289: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(18874)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(77318)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.default)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 36658: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(38465)); + +var _sha = _interopRequireDefault(__nccwpck_require__(39490)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 75869: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(42456)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 25807: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(75869)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.substr(14, 1), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 39316: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + CONFIG_USE_DUALSTACK_ENDPOINT: () => CONFIG_USE_DUALSTACK_ENDPOINT, + CONFIG_USE_FIPS_ENDPOINT: () => CONFIG_USE_FIPS_ENDPOINT, + DEFAULT_USE_DUALSTACK_ENDPOINT: () => DEFAULT_USE_DUALSTACK_ENDPOINT, + DEFAULT_USE_FIPS_ENDPOINT: () => DEFAULT_USE_FIPS_ENDPOINT, + ENV_USE_DUALSTACK_ENDPOINT: () => ENV_USE_DUALSTACK_ENDPOINT, + ENV_USE_FIPS_ENDPOINT: () => ENV_USE_FIPS_ENDPOINT, + NODE_REGION_CONFIG_FILE_OPTIONS: () => NODE_REGION_CONFIG_FILE_OPTIONS, + NODE_REGION_CONFIG_OPTIONS: () => NODE_REGION_CONFIG_OPTIONS, + NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS: () => NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS, + NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS: () => NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS, + REGION_ENV_NAME: () => REGION_ENV_NAME, + REGION_INI_NAME: () => REGION_INI_NAME, + getRegionInfo: () => getRegionInfo, + resolveCustomEndpointsConfig: () => resolveCustomEndpointsConfig, + resolveEndpointsConfig: () => resolveEndpointsConfig, + resolveRegionConfig: () => resolveRegionConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/endpointsConfig/NodeUseDualstackEndpointConfigOptions.ts +var import_util_config_provider = __nccwpck_require__(56716); +var ENV_USE_DUALSTACK_ENDPOINT = "AWS_USE_DUALSTACK_ENDPOINT"; +var CONFIG_USE_DUALSTACK_ENDPOINT = "use_dualstack_endpoint"; +var DEFAULT_USE_DUALSTACK_ENDPOINT = false; +var NODE_USE_DUALSTACK_ENDPOINT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => (0, import_util_config_provider.booleanSelector)(env, ENV_USE_DUALSTACK_ENDPOINT, import_util_config_provider.SelectorType.ENV), + configFileSelector: (profile) => (0, import_util_config_provider.booleanSelector)(profile, CONFIG_USE_DUALSTACK_ENDPOINT, import_util_config_provider.SelectorType.CONFIG), + default: false +}; + +// src/endpointsConfig/NodeUseFipsEndpointConfigOptions.ts + +var ENV_USE_FIPS_ENDPOINT = "AWS_USE_FIPS_ENDPOINT"; +var CONFIG_USE_FIPS_ENDPOINT = "use_fips_endpoint"; +var DEFAULT_USE_FIPS_ENDPOINT = false; +var NODE_USE_FIPS_ENDPOINT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => (0, import_util_config_provider.booleanSelector)(env, ENV_USE_FIPS_ENDPOINT, import_util_config_provider.SelectorType.ENV), + configFileSelector: (profile) => (0, import_util_config_provider.booleanSelector)(profile, CONFIG_USE_FIPS_ENDPOINT, import_util_config_provider.SelectorType.CONFIG), + default: false +}; + +// src/endpointsConfig/resolveCustomEndpointsConfig.ts +var import_util_middleware = __nccwpck_require__(76324); +var resolveCustomEndpointsConfig = /* @__PURE__ */ __name((input) => { + const { tls, endpoint, urlParser, useDualstackEndpoint } = input; + return Object.assign(input, { + tls: tls ?? true, + endpoint: (0, import_util_middleware.normalizeProvider)(typeof endpoint === "string" ? urlParser(endpoint) : endpoint), + isCustomEndpoint: true, + useDualstackEndpoint: (0, import_util_middleware.normalizeProvider)(useDualstackEndpoint ?? false) + }); +}, "resolveCustomEndpointsConfig"); + +// src/endpointsConfig/resolveEndpointsConfig.ts + + +// src/endpointsConfig/utils/getEndpointFromRegion.ts +var getEndpointFromRegion = /* @__PURE__ */ __name(async (input) => { + const { tls = true } = input; + const region = await input.region(); + const dnsHostRegex = new RegExp(/^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$/); + if (!dnsHostRegex.test(region)) { + throw new Error("Invalid region in client config"); + } + const useDualstackEndpoint = await input.useDualstackEndpoint(); + const useFipsEndpoint = await input.useFipsEndpoint(); + const { hostname } = await input.regionInfoProvider(region, { useDualstackEndpoint, useFipsEndpoint }) ?? {}; + if (!hostname) { + throw new Error("Cannot resolve hostname from client config"); + } + return input.urlParser(`${tls ? "https:" : "http:"}//${hostname}`); +}, "getEndpointFromRegion"); + +// src/endpointsConfig/resolveEndpointsConfig.ts +var resolveEndpointsConfig = /* @__PURE__ */ __name((input) => { + const useDualstackEndpoint = (0, import_util_middleware.normalizeProvider)(input.useDualstackEndpoint ?? false); + const { endpoint, useFipsEndpoint, urlParser, tls } = input; + return Object.assign(input, { + tls: tls ?? true, + endpoint: endpoint ? (0, import_util_middleware.normalizeProvider)(typeof endpoint === "string" ? urlParser(endpoint) : endpoint) : () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }), + isCustomEndpoint: !!endpoint, + useDualstackEndpoint + }); +}, "resolveEndpointsConfig"); + +// src/regionConfig/config.ts +var REGION_ENV_NAME = "AWS_REGION"; +var REGION_INI_NAME = "region"; +var NODE_REGION_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[REGION_ENV_NAME], + configFileSelector: (profile) => profile[REGION_INI_NAME], + default: () => { + throw new Error("Region is missing"); + } +}; +var NODE_REGION_CONFIG_FILE_OPTIONS = { + preferredFile: "credentials" +}; + +// src/regionConfig/isFipsRegion.ts +var isFipsRegion = /* @__PURE__ */ __name((region) => typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips")), "isFipsRegion"); + +// src/regionConfig/getRealRegion.ts +var getRealRegion = /* @__PURE__ */ __name((region) => isFipsRegion(region) ? ["fips-aws-global", "aws-fips"].includes(region) ? "us-east-1" : region.replace(/fips-(dkr-|prod-)?|-fips/, "") : region, "getRealRegion"); + +// src/regionConfig/resolveRegionConfig.ts +var resolveRegionConfig = /* @__PURE__ */ __name((input) => { + const { region, useFipsEndpoint } = input; + if (!region) { + throw new Error("Region is missing"); + } + return Object.assign(input, { + region: async () => { + if (typeof region === "string") { + return getRealRegion(region); + } + const providedRegion = await region(); + return getRealRegion(providedRegion); + }, + useFipsEndpoint: async () => { + const providedRegion = typeof region === "string" ? region : await region(); + if (isFipsRegion(providedRegion)) { + return true; + } + return typeof useFipsEndpoint !== "function" ? Promise.resolve(!!useFipsEndpoint) : useFipsEndpoint(); + } + }); +}, "resolveRegionConfig"); + +// src/regionInfo/getHostnameFromVariants.ts +var getHostnameFromVariants = /* @__PURE__ */ __name((variants = [], { useFipsEndpoint, useDualstackEndpoint }) => variants.find( + ({ tags }) => useFipsEndpoint === tags.includes("fips") && useDualstackEndpoint === tags.includes("dualstack") +)?.hostname, "getHostnameFromVariants"); + +// src/regionInfo/getResolvedHostname.ts +var getResolvedHostname = /* @__PURE__ */ __name((resolvedRegion, { regionHostname, partitionHostname }) => regionHostname ? regionHostname : partitionHostname ? partitionHostname.replace("{region}", resolvedRegion) : void 0, "getResolvedHostname"); + +// src/regionInfo/getResolvedPartition.ts +var getResolvedPartition = /* @__PURE__ */ __name((region, { partitionHash }) => Object.keys(partitionHash || {}).find((key) => partitionHash[key].regions.includes(region)) ?? "aws", "getResolvedPartition"); + +// src/regionInfo/getResolvedSigningRegion.ts +var getResolvedSigningRegion = /* @__PURE__ */ __name((hostname, { signingRegion, regionRegex, useFipsEndpoint }) => { + if (signingRegion) { + return signingRegion; + } else if (useFipsEndpoint) { + const regionRegexJs = regionRegex.replace("\\\\", "\\").replace(/^\^/g, "\\.").replace(/\$$/g, "\\."); + const regionRegexmatchArray = hostname.match(regionRegexJs); + if (regionRegexmatchArray) { + return regionRegexmatchArray[0].slice(1, -1); + } + } +}, "getResolvedSigningRegion"); + +// src/regionInfo/getRegionInfo.ts +var getRegionInfo = /* @__PURE__ */ __name((region, { + useFipsEndpoint = false, + useDualstackEndpoint = false, + signingService, + regionHash, + partitionHash +}) => { + const partition = getResolvedPartition(region, { partitionHash }); + const resolvedRegion = region in regionHash ? region : partitionHash[partition]?.endpoint ?? region; + const hostnameOptions = { useFipsEndpoint, useDualstackEndpoint }; + const regionHostname = getHostnameFromVariants(regionHash[resolvedRegion]?.variants, hostnameOptions); + const partitionHostname = getHostnameFromVariants(partitionHash[partition]?.variants, hostnameOptions); + const hostname = getResolvedHostname(resolvedRegion, { regionHostname, partitionHostname }); + if (hostname === void 0) { + throw new Error(`Endpoint resolution failed for: ${{ resolvedRegion, useFipsEndpoint, useDualstackEndpoint }}`); + } + const signingRegion = getResolvedSigningRegion(hostname, { + signingRegion: regionHash[resolvedRegion]?.signingRegion, + regionRegex: partitionHash[partition].regionRegex, + useFipsEndpoint + }); + return { + partition, + signingService, + hostname, + ...signingRegion && { signingRegion }, + ...regionHash[resolvedRegion]?.signingService && { + signingService: regionHash[resolvedRegion].signingService + } + }; +}, "getRegionInfo"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 90402: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + DefaultIdentityProviderConfig: () => DefaultIdentityProviderConfig, + EXPIRATION_MS: () => EXPIRATION_MS, + HttpApiKeyAuthSigner: () => HttpApiKeyAuthSigner, + HttpBearerAuthSigner: () => HttpBearerAuthSigner, + NoAuthSigner: () => NoAuthSigner, + createIsIdentityExpiredFunction: () => createIsIdentityExpiredFunction, + createPaginator: () => createPaginator, + doesIdentityRequireRefresh: () => doesIdentityRequireRefresh, + getHttpAuthSchemeEndpointRuleSetPlugin: () => getHttpAuthSchemeEndpointRuleSetPlugin, + getHttpAuthSchemePlugin: () => getHttpAuthSchemePlugin, + getHttpSigningPlugin: () => getHttpSigningPlugin, + getSmithyContext: () => getSmithyContext, + httpAuthSchemeEndpointRuleSetMiddlewareOptions: () => httpAuthSchemeEndpointRuleSetMiddlewareOptions, + httpAuthSchemeMiddleware: () => httpAuthSchemeMiddleware, + httpAuthSchemeMiddlewareOptions: () => httpAuthSchemeMiddlewareOptions, + httpSigningMiddleware: () => httpSigningMiddleware, + httpSigningMiddlewareOptions: () => httpSigningMiddlewareOptions, + isIdentityExpired: () => isIdentityExpired, + memoizeIdentityProvider: () => memoizeIdentityProvider, + normalizeProvider: () => normalizeProvider, + requestBuilder: () => import_protocols.requestBuilder, + setFeature: () => setFeature +}); +module.exports = __toCommonJS(src_exports); + +// src/getSmithyContext.ts +var import_types = __nccwpck_require__(90690); +var getSmithyContext = /* @__PURE__ */ __name((context) => context[import_types.SMITHY_CONTEXT_KEY] || (context[import_types.SMITHY_CONTEXT_KEY] = {}), "getSmithyContext"); + +// src/middleware-http-auth-scheme/httpAuthSchemeMiddleware.ts +var import_util_middleware = __nccwpck_require__(76324); + +// src/middleware-http-auth-scheme/resolveAuthOptions.ts +var resolveAuthOptions = /* @__PURE__ */ __name((candidateAuthOptions, authSchemePreference) => { + if (!authSchemePreference || authSchemePreference.length === 0) { + return candidateAuthOptions; + } + const preferredAuthOptions = []; + for (const preferredSchemeName of authSchemePreference) { + for (const candidateAuthOption of candidateAuthOptions) { + const candidateAuthSchemeName = candidateAuthOption.schemeId.split("#")[1]; + if (candidateAuthSchemeName === preferredSchemeName) { + preferredAuthOptions.push(candidateAuthOption); + } + } + } + for (const candidateAuthOption of candidateAuthOptions) { + if (!preferredAuthOptions.find(({ schemeId }) => schemeId === candidateAuthOption.schemeId)) { + preferredAuthOptions.push(candidateAuthOption); + } + } + return preferredAuthOptions; +}, "resolveAuthOptions"); + +// src/middleware-http-auth-scheme/httpAuthSchemeMiddleware.ts +function convertHttpAuthSchemesToMap(httpAuthSchemes) { + const map = /* @__PURE__ */ new Map(); + for (const scheme of httpAuthSchemes) { + map.set(scheme.schemeId, scheme); + } + return map; +} +__name(convertHttpAuthSchemesToMap, "convertHttpAuthSchemesToMap"); +var httpAuthSchemeMiddleware = /* @__PURE__ */ __name((config, mwOptions) => (next, context) => async (args) => { + const options = config.httpAuthSchemeProvider( + await mwOptions.httpAuthSchemeParametersProvider(config, context, args.input) + ); + const authSchemePreference = config.authSchemePreference ? await config.authSchemePreference() : []; + const resolvedOptions = resolveAuthOptions(options, authSchemePreference); + const authSchemes = convertHttpAuthSchemesToMap(config.httpAuthSchemes); + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const failureReasons = []; + for (const option of resolvedOptions) { + const scheme = authSchemes.get(option.schemeId); + if (!scheme) { + failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` was not enabled for this service.`); + continue; + } + const identityProvider = scheme.identityProvider(await mwOptions.identityProviderConfigProvider(config)); + if (!identityProvider) { + failureReasons.push(`HttpAuthScheme \`${option.schemeId}\` did not have an IdentityProvider configured.`); + continue; + } + const { identityProperties = {}, signingProperties = {} } = option.propertiesExtractor?.(config, context) || {}; + option.identityProperties = Object.assign(option.identityProperties || {}, identityProperties); + option.signingProperties = Object.assign(option.signingProperties || {}, signingProperties); + smithyContext.selectedHttpAuthScheme = { + httpAuthOption: option, + identity: await identityProvider(option.identityProperties), + signer: scheme.signer + }; + break; + } + if (!smithyContext.selectedHttpAuthScheme) { + throw new Error(failureReasons.join("\n")); + } + return next(args); +}, "httpAuthSchemeMiddleware"); + +// src/middleware-http-auth-scheme/getHttpAuthSchemeEndpointRuleSetPlugin.ts +var httpAuthSchemeEndpointRuleSetMiddlewareOptions = { + step: "serialize", + tags: ["HTTP_AUTH_SCHEME"], + name: "httpAuthSchemeMiddleware", + override: true, + relation: "before", + toMiddleware: "endpointV2Middleware" +}; +var getHttpAuthSchemeEndpointRuleSetPlugin = /* @__PURE__ */ __name((config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider +}) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo( + httpAuthSchemeMiddleware(config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider + }), + httpAuthSchemeEndpointRuleSetMiddlewareOptions + ); + } +}), "getHttpAuthSchemeEndpointRuleSetPlugin"); + +// src/middleware-http-auth-scheme/getHttpAuthSchemePlugin.ts +var import_middleware_serde = __nccwpck_require__(83255); +var httpAuthSchemeMiddlewareOptions = { + step: "serialize", + tags: ["HTTP_AUTH_SCHEME"], + name: "httpAuthSchemeMiddleware", + override: true, + relation: "before", + toMiddleware: import_middleware_serde.serializerMiddlewareOption.name +}; +var getHttpAuthSchemePlugin = /* @__PURE__ */ __name((config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider +}) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo( + httpAuthSchemeMiddleware(config, { + httpAuthSchemeParametersProvider, + identityProviderConfigProvider + }), + httpAuthSchemeMiddlewareOptions + ); + } +}), "getHttpAuthSchemePlugin"); + +// src/middleware-http-signing/httpSigningMiddleware.ts +var import_protocol_http = __nccwpck_require__(72356); + +var defaultErrorHandler = /* @__PURE__ */ __name((signingProperties) => (error) => { + throw error; +}, "defaultErrorHandler"); +var defaultSuccessHandler = /* @__PURE__ */ __name((httpResponse, signingProperties) => { +}, "defaultSuccessHandler"); +var httpSigningMiddleware = /* @__PURE__ */ __name((config) => (next, context) => async (args) => { + if (!import_protocol_http.HttpRequest.isInstance(args.request)) { + return next(args); + } + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const scheme = smithyContext.selectedHttpAuthScheme; + if (!scheme) { + throw new Error(`No HttpAuthScheme was selected: unable to sign request`); + } + const { + httpAuthOption: { signingProperties = {} }, + identity, + signer + } = scheme; + const output = await next({ + ...args, + request: await signer.sign(args.request, identity, signingProperties) + }).catch((signer.errorHandler || defaultErrorHandler)(signingProperties)); + (signer.successHandler || defaultSuccessHandler)(output.response, signingProperties); + return output; +}, "httpSigningMiddleware"); + +// src/middleware-http-signing/getHttpSigningMiddleware.ts +var httpSigningMiddlewareOptions = { + step: "finalizeRequest", + tags: ["HTTP_SIGNING"], + name: "httpSigningMiddleware", + aliases: ["apiKeyMiddleware", "tokenMiddleware", "awsAuthMiddleware"], + override: true, + relation: "after", + toMiddleware: "retryMiddleware" +}; +var getHttpSigningPlugin = /* @__PURE__ */ __name((config) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo(httpSigningMiddleware(config), httpSigningMiddlewareOptions); + } +}), "getHttpSigningPlugin"); + +// src/normalizeProvider.ts +var normalizeProvider = /* @__PURE__ */ __name((input) => { + if (typeof input === "function") + return input; + const promisified = Promise.resolve(input); + return () => promisified; +}, "normalizeProvider"); + +// src/pagination/createPaginator.ts +var makePagedClientRequest = /* @__PURE__ */ __name(async (CommandCtor, client, input, withCommand = (_) => _, ...args) => { + let command = new CommandCtor(input); + command = withCommand(command) ?? command; + return await client.send(command, ...args); +}, "makePagedClientRequest"); +function createPaginator(ClientCtor, CommandCtor, inputTokenName, outputTokenName, pageSizeTokenName) { + return /* @__PURE__ */ __name(async function* paginateOperation(config, input, ...additionalArguments) { + const _input = input; + let token = config.startingToken ?? _input[inputTokenName]; + let hasNext = true; + let page; + while (hasNext) { + _input[inputTokenName] = token; + if (pageSizeTokenName) { + _input[pageSizeTokenName] = _input[pageSizeTokenName] ?? config.pageSize; + } + if (config.client instanceof ClientCtor) { + page = await makePagedClientRequest( + CommandCtor, + config.client, + input, + config.withCommand, + ...additionalArguments + ); + } else { + throw new Error(`Invalid client, expected instance of ${ClientCtor.name}`); + } + yield page; + const prevToken = token; + token = get(page, outputTokenName); + hasNext = !!(token && (!config.stopOnSameToken || token !== prevToken)); + } + return void 0; + }, "paginateOperation"); +} +__name(createPaginator, "createPaginator"); +var get = /* @__PURE__ */ __name((fromObject, path) => { + let cursor = fromObject; + const pathComponents = path.split("."); + for (const step of pathComponents) { + if (!cursor || typeof cursor !== "object") { + return void 0; + } + cursor = cursor[step]; + } + return cursor; +}, "get"); + +// src/protocols/requestBuilder.ts +var import_protocols = __nccwpck_require__(93422); + +// src/setFeature.ts +function setFeature(context, feature, value) { + if (!context.__smithy_context) { + context.__smithy_context = { + features: {} + }; + } else if (!context.__smithy_context.features) { + context.__smithy_context.features = {}; + } + context.__smithy_context.features[feature] = value; +} +__name(setFeature, "setFeature"); + +// src/util-identity-and-auth/DefaultIdentityProviderConfig.ts +var DefaultIdentityProviderConfig = class { + /** + * Creates an IdentityProviderConfig with a record of scheme IDs to identity providers. + * + * @param config scheme IDs and identity providers to configure + */ + constructor(config) { + this.authSchemes = /* @__PURE__ */ new Map(); + for (const [key, value] of Object.entries(config)) { + if (value !== void 0) { + this.authSchemes.set(key, value); + } + } + } + static { + __name(this, "DefaultIdentityProviderConfig"); + } + getIdentityProvider(schemeId) { + return this.authSchemes.get(schemeId); + } +}; + +// src/util-identity-and-auth/httpAuthSchemes/httpApiKeyAuth.ts + + +var HttpApiKeyAuthSigner = class { + static { + __name(this, "HttpApiKeyAuthSigner"); + } + async sign(httpRequest, identity, signingProperties) { + if (!signingProperties) { + throw new Error( + "request could not be signed with `apiKey` since the `name` and `in` signer properties are missing" + ); + } + if (!signingProperties.name) { + throw new Error("request could not be signed with `apiKey` since the `name` signer property is missing"); + } + if (!signingProperties.in) { + throw new Error("request could not be signed with `apiKey` since the `in` signer property is missing"); + } + if (!identity.apiKey) { + throw new Error("request could not be signed with `apiKey` since the `apiKey` is not defined"); + } + const clonedRequest = import_protocol_http.HttpRequest.clone(httpRequest); + if (signingProperties.in === import_types.HttpApiKeyAuthLocation.QUERY) { + clonedRequest.query[signingProperties.name] = identity.apiKey; + } else if (signingProperties.in === import_types.HttpApiKeyAuthLocation.HEADER) { + clonedRequest.headers[signingProperties.name] = signingProperties.scheme ? `${signingProperties.scheme} ${identity.apiKey}` : identity.apiKey; + } else { + throw new Error( + "request can only be signed with `apiKey` locations `query` or `header`, but found: `" + signingProperties.in + "`" + ); + } + return clonedRequest; + } +}; + +// src/util-identity-and-auth/httpAuthSchemes/httpBearerAuth.ts + +var HttpBearerAuthSigner = class { + static { + __name(this, "HttpBearerAuthSigner"); + } + async sign(httpRequest, identity, signingProperties) { + const clonedRequest = import_protocol_http.HttpRequest.clone(httpRequest); + if (!identity.token) { + throw new Error("request could not be signed with `token` since the `token` is not defined"); + } + clonedRequest.headers["Authorization"] = `Bearer ${identity.token}`; + return clonedRequest; + } +}; + +// src/util-identity-and-auth/httpAuthSchemes/noAuth.ts +var NoAuthSigner = class { + static { + __name(this, "NoAuthSigner"); + } + async sign(httpRequest, identity, signingProperties) { + return httpRequest; + } +}; + +// src/util-identity-and-auth/memoizeIdentityProvider.ts +var createIsIdentityExpiredFunction = /* @__PURE__ */ __name((expirationMs) => (identity) => doesIdentityRequireRefresh(identity) && identity.expiration.getTime() - Date.now() < expirationMs, "createIsIdentityExpiredFunction"); +var EXPIRATION_MS = 3e5; +var isIdentityExpired = createIsIdentityExpiredFunction(EXPIRATION_MS); +var doesIdentityRequireRefresh = /* @__PURE__ */ __name((identity) => identity.expiration !== void 0, "doesIdentityRequireRefresh"); +var memoizeIdentityProvider = /* @__PURE__ */ __name((provider, isExpired, requiresRefresh) => { + if (provider === void 0) { + return void 0; + } + const normalizedProvider = typeof provider !== "function" ? async () => Promise.resolve(provider) : provider; + let resolved; + let pending; + let hasResult; + let isConstant = false; + const coalesceProvider = /* @__PURE__ */ __name(async (options) => { + if (!pending) { + pending = normalizedProvider(options); + } + try { + resolved = await pending; + hasResult = true; + isConstant = false; + } finally { + pending = void 0; + } + return resolved; + }, "coalesceProvider"); + if (isExpired === void 0) { + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(options); + } + return resolved; + }; + } + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(options); + } + if (isConstant) { + return resolved; + } + if (!requiresRefresh(resolved)) { + isConstant = true; + return resolved; + } + if (isExpired(resolved)) { + await coalesceProvider(options); + return resolved; + } + return resolved; + }; +}, "memoizeIdentityProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 93422: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/protocols/index.ts +var protocols_exports = {}; +__export(protocols_exports, { + FromStringShapeDeserializer: () => FromStringShapeDeserializer, + HttpBindingProtocol: () => HttpBindingProtocol, + HttpInterceptingShapeDeserializer: () => HttpInterceptingShapeDeserializer, + HttpInterceptingShapeSerializer: () => HttpInterceptingShapeSerializer, + RequestBuilder: () => RequestBuilder, + RpcProtocol: () => RpcProtocol, + ToStringShapeSerializer: () => ToStringShapeSerializer, + collectBody: () => collectBody, + determineTimestampFormat: () => determineTimestampFormat, + extendedEncodeURIComponent: () => extendedEncodeURIComponent, + requestBuilder: () => requestBuilder, + resolvedPath: () => resolvedPath +}); +module.exports = __toCommonJS(protocols_exports); + +// src/submodules/protocols/collect-stream-body.ts +var import_util_stream = __nccwpck_require__(4252); +var collectBody = async (streamBody = new Uint8Array(), context) => { + if (streamBody instanceof Uint8Array) { + return import_util_stream.Uint8ArrayBlobAdapter.mutate(streamBody); + } + if (!streamBody) { + return import_util_stream.Uint8ArrayBlobAdapter.mutate(new Uint8Array()); + } + const fromContext = context.streamCollector(streamBody); + return import_util_stream.Uint8ArrayBlobAdapter.mutate(await fromContext); +}; + +// src/submodules/protocols/extended-encode-uri-component.ts +function extendedEncodeURIComponent(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, function(c) { + return "%" + c.charCodeAt(0).toString(16).toUpperCase(); + }); +} + +// src/submodules/protocols/HttpBindingProtocol.ts +var import_schema2 = __nccwpck_require__(26890); +var import_protocol_http2 = __nccwpck_require__(72356); + +// src/submodules/protocols/HttpProtocol.ts +var import_schema = __nccwpck_require__(26890); +var import_serde = __nccwpck_require__(92430); +var import_protocol_http = __nccwpck_require__(72356); +var import_util_stream2 = __nccwpck_require__(4252); +var HttpProtocol = class { + constructor(options) { + this.options = options; + } + getRequestType() { + return import_protocol_http.HttpRequest; + } + getResponseType() { + return import_protocol_http.HttpResponse; + } + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + this.serializer.setSerdeContext(serdeContext); + this.deserializer.setSerdeContext(serdeContext); + if (this.getPayloadCodec()) { + this.getPayloadCodec().setSerdeContext(serdeContext); + } + } + updateServiceEndpoint(request, endpoint) { + if ("url" in endpoint) { + request.protocol = endpoint.url.protocol; + request.hostname = endpoint.url.hostname; + request.port = endpoint.url.port ? Number(endpoint.url.port) : void 0; + request.path = endpoint.url.pathname; + request.fragment = endpoint.url.hash || void 0; + request.username = endpoint.url.username || void 0; + request.password = endpoint.url.password || void 0; + for (const [k, v] of endpoint.url.searchParams.entries()) { + if (!request.query) { + request.query = {}; + } + request.query[k] = v; + } + return request; + } else { + request.protocol = endpoint.protocol; + request.hostname = endpoint.hostname; + request.port = endpoint.port ? Number(endpoint.port) : void 0; + request.path = endpoint.path; + request.query = { + ...endpoint.query + }; + return request; + } + } + setHostPrefix(request, operationSchema, input) { + const operationNs = import_schema.NormalizedSchema.of(operationSchema); + const inputNs = import_schema.NormalizedSchema.of(operationSchema.input); + if (operationNs.getMergedTraits().endpoint) { + let hostPrefix = operationNs.getMergedTraits().endpoint?.[0]; + if (typeof hostPrefix === "string") { + const hostLabelInputs = [...inputNs.structIterator()].filter( + ([, member]) => member.getMergedTraits().hostLabel + ); + for (const [name] of hostLabelInputs) { + const replacement = input[name]; + if (typeof replacement !== "string") { + throw new Error(`@smithy/core/schema - ${name} in input must be a string as hostLabel.`); + } + hostPrefix = hostPrefix.replace(`{${name}}`, replacement); + } + request.hostname = hostPrefix + request.hostname; + } + } + } + deserializeMetadata(output) { + return { + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] + }; + } + async deserializeHttpMessage(schema, context, response, arg4, arg5) { + let dataObject; + if (arg4 instanceof Set) { + dataObject = arg5; + } else { + dataObject = arg4; + } + const deserializer = this.deserializer; + const ns = import_schema.NormalizedSchema.of(schema); + const nonHttpBindingMembers = []; + for (const [memberName, memberSchema] of ns.structIterator()) { + const memberTraits = memberSchema.getMemberTraits(); + if (memberTraits.httpPayload) { + const isStreaming = memberSchema.isStreaming(); + if (isStreaming) { + const isEventStream = memberSchema.isStructSchema(); + if (isEventStream) { + const context2 = this.serdeContext; + if (!context2.eventStreamMarshaller) { + throw new Error("@smithy/core - HttpProtocol: eventStreamMarshaller missing in serdeContext."); + } + const memberSchemas = memberSchema.getMemberSchemas(); + dataObject[memberName] = context2.eventStreamMarshaller.deserialize(response.body, async (event) => { + const unionMember = Object.keys(event).find((key) => { + return key !== "__type"; + }) ?? ""; + if (unionMember in memberSchemas) { + const eventStreamSchema = memberSchemas[unionMember]; + return { + [unionMember]: await deserializer.read(eventStreamSchema, event[unionMember].body) + }; + } else { + return { + $unknown: event + }; + } + }); + } else { + dataObject[memberName] = (0, import_util_stream2.sdkStreamMixin)(response.body); + } + } else if (response.body) { + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + dataObject[memberName] = await deserializer.read(memberSchema, bytes); + } + } + } else if (memberTraits.httpHeader) { + const key = String(memberTraits.httpHeader).toLowerCase(); + const value = response.headers[key]; + if (null != value) { + if (memberSchema.isListSchema()) { + const headerListValueSchema = memberSchema.getValueSchema(); + let sections; + if (headerListValueSchema.isTimestampSchema() && headerListValueSchema.getSchema() === import_schema.SCHEMA.TIMESTAMP_DEFAULT) { + sections = (0, import_serde.splitEvery)(value, ",", 2); + } else { + sections = (0, import_serde.splitHeader)(value); + } + const list = []; + for (const section of sections) { + list.push(await deserializer.read([headerListValueSchema, { httpHeader: key }], section.trim())); + } + dataObject[memberName] = list; + } else { + dataObject[memberName] = await deserializer.read(memberSchema, value); + } + } + } else if (memberTraits.httpPrefixHeaders !== void 0) { + dataObject[memberName] = {}; + for (const [header, value] of Object.entries(response.headers)) { + if (header.startsWith(memberTraits.httpPrefixHeaders)) { + dataObject[memberName][header.slice(memberTraits.httpPrefixHeaders.length)] = await deserializer.read( + [memberSchema.getValueSchema(), { httpHeader: header }], + value + ); + } + } + } else if (memberTraits.httpResponseCode) { + dataObject[memberName] = response.statusCode; + } else { + nonHttpBindingMembers.push(memberName); + } + } + return nonHttpBindingMembers; + } +}; + +// src/submodules/protocols/HttpBindingProtocol.ts +var HttpBindingProtocol = class extends HttpProtocol { + async serializeRequest(operationSchema, _input, context) { + const input = { + ..._input ?? {} + }; + const serializer = this.serializer; + const query = {}; + const headers = {}; + const endpoint = await context.endpoint(); + const ns = import_schema2.NormalizedSchema.of(operationSchema?.input); + const schema = ns.getSchema(); + let hasNonHttpBindingMember = false; + let payload; + const request = new import_protocol_http2.HttpRequest({ + protocol: "", + hostname: "", + port: void 0, + path: "", + fragment: void 0, + query, + headers, + body: void 0 + }); + if (endpoint) { + this.updateServiceEndpoint(request, endpoint); + this.setHostPrefix(request, operationSchema, input); + const opTraits = import_schema2.NormalizedSchema.translateTraits(operationSchema.traits); + if (opTraits.http) { + request.method = opTraits.http[0]; + const [path, search] = opTraits.http[1].split("?"); + if (request.path == "/") { + request.path = path; + } else { + request.path += path; + } + const traitSearchParams = new URLSearchParams(search ?? ""); + Object.assign(query, Object.fromEntries(traitSearchParams)); + } + } + for (const [memberName, memberNs] of ns.structIterator()) { + const memberTraits = memberNs.getMergedTraits() ?? {}; + const inputMemberValue = input[memberName]; + if (inputMemberValue == null) { + continue; + } + if (memberTraits.httpPayload) { + const isStreaming = memberNs.isStreaming(); + if (isStreaming) { + const isEventStream = memberNs.isStructSchema(); + if (isEventStream) { + throw new Error("serialization of event streams is not yet implemented"); + } else { + payload = inputMemberValue; + } + } else { + serializer.write(memberNs, inputMemberValue); + payload = serializer.flush(); + } + delete input[memberName]; + } else if (memberTraits.httpLabel) { + serializer.write(memberNs, inputMemberValue); + const replacement = serializer.flush(); + if (request.path.includes(`{${memberName}+}`)) { + request.path = request.path.replace( + `{${memberName}+}`, + replacement.split("/").map(extendedEncodeURIComponent).join("/") + ); + } else if (request.path.includes(`{${memberName}}`)) { + request.path = request.path.replace(`{${memberName}}`, extendedEncodeURIComponent(replacement)); + } + delete input[memberName]; + } else if (memberTraits.httpHeader) { + serializer.write(memberNs, inputMemberValue); + headers[memberTraits.httpHeader.toLowerCase()] = String(serializer.flush()); + delete input[memberName]; + } else if (typeof memberTraits.httpPrefixHeaders === "string") { + for (const [key, val] of Object.entries(inputMemberValue)) { + const amalgam = memberTraits.httpPrefixHeaders + key; + serializer.write([memberNs.getValueSchema(), { httpHeader: amalgam }], val); + headers[amalgam.toLowerCase()] = serializer.flush(); + } + delete input[memberName]; + } else if (memberTraits.httpQuery || memberTraits.httpQueryParams) { + this.serializeQuery(memberNs, inputMemberValue, query); + delete input[memberName]; + } else { + hasNonHttpBindingMember = true; + } + } + if (hasNonHttpBindingMember && input) { + serializer.write(schema, input); + payload = serializer.flush(); + } + request.headers = headers; + request.query = query; + request.body = payload; + return request; + } + serializeQuery(ns, data, query) { + const serializer = this.serializer; + const traits = ns.getMergedTraits(); + if (traits.httpQueryParams) { + for (const [key, val] of Object.entries(data)) { + if (!(key in query)) { + this.serializeQuery( + import_schema2.NormalizedSchema.of([ + ns.getValueSchema(), + { + // We pass on the traits to the sub-schema + // because we are still in the process of serializing the map itself. + ...traits, + httpQuery: key, + httpQueryParams: void 0 + } + ]), + val, + query + ); + } + } + return; + } + if (ns.isListSchema()) { + const sparse = !!ns.getMergedTraits().sparse; + const buffer = []; + for (const item of data) { + serializer.write([ns.getValueSchema(), traits], item); + const serializable = serializer.flush(); + if (sparse || serializable !== void 0) { + buffer.push(serializable); + } + } + query[traits.httpQuery] = buffer; + } else { + serializer.write([ns, traits], data); + query[traits.httpQuery] = serializer.flush(); + } + } + async deserializeResponse(operationSchema, context, response) { + const deserializer = this.deserializer; + const ns = import_schema2.NormalizedSchema.of(operationSchema.output); + const dataObject = {}; + if (response.statusCode >= 300) { + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(import_schema2.SCHEMA.DOCUMENT, bytes)); + } + await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response)); + throw new Error("@smithy/core/protocols - HTTP Protocol error handler failed to throw."); + } + for (const header in response.headers) { + const value = response.headers[header]; + delete response.headers[header]; + response.headers[header.toLowerCase()] = value; + } + const nonHttpBindingMembers = await this.deserializeHttpMessage(ns, context, response, dataObject); + if (nonHttpBindingMembers.length) { + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + const dataFromBody = await deserializer.read(ns, bytes); + for (const member of nonHttpBindingMembers) { + dataObject[member] = dataFromBody[member]; + } + } + } + const output = { + $metadata: this.deserializeMetadata(response), + ...dataObject + }; + return output; + } +}; + +// src/submodules/protocols/RpcProtocol.ts +var import_schema3 = __nccwpck_require__(26890); +var import_protocol_http3 = __nccwpck_require__(72356); +var RpcProtocol = class extends HttpProtocol { + async serializeRequest(operationSchema, input, context) { + const serializer = this.serializer; + const query = {}; + const headers = {}; + const endpoint = await context.endpoint(); + const ns = import_schema3.NormalizedSchema.of(operationSchema?.input); + const schema = ns.getSchema(); + let payload; + const request = new import_protocol_http3.HttpRequest({ + protocol: "", + hostname: "", + port: void 0, + path: "/", + fragment: void 0, + query, + headers, + body: void 0 + }); + if (endpoint) { + this.updateServiceEndpoint(request, endpoint); + this.setHostPrefix(request, operationSchema, input); + } + const _input = { + ...input + }; + if (input) { + serializer.write(schema, _input); + payload = serializer.flush(); + } + request.headers = headers; + request.query = query; + request.body = payload; + request.method = "POST"; + return request; + } + async deserializeResponse(operationSchema, context, response) { + const deserializer = this.deserializer; + const ns = import_schema3.NormalizedSchema.of(operationSchema.output); + const dataObject = {}; + if (response.statusCode >= 300) { + const bytes2 = await collectBody(response.body, context); + if (bytes2.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(import_schema3.SCHEMA.DOCUMENT, bytes2)); + } + await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response)); + throw new Error("@smithy/core/protocols - RPC Protocol error handler failed to throw."); + } + for (const header in response.headers) { + const value = response.headers[header]; + delete response.headers[header]; + response.headers[header.toLowerCase()] = value; + } + const bytes = await collectBody(response.body, context); + if (bytes.byteLength > 0) { + Object.assign(dataObject, await deserializer.read(ns, bytes)); + } + const output = { + $metadata: this.deserializeMetadata(response), + ...dataObject + }; + return output; + } +}; + +// src/submodules/protocols/requestBuilder.ts +var import_protocol_http4 = __nccwpck_require__(72356); + +// src/submodules/protocols/resolve-path.ts +var resolvedPath = (resolvedPath2, input, memberName, labelValueProvider, uriLabel, isGreedyLabel) => { + if (input != null && input[memberName] !== void 0) { + const labelValue = labelValueProvider(); + if (labelValue.length <= 0) { + throw new Error("Empty value provided for input HTTP label: " + memberName + "."); + } + resolvedPath2 = resolvedPath2.replace( + uriLabel, + isGreedyLabel ? labelValue.split("/").map((segment) => extendedEncodeURIComponent(segment)).join("/") : extendedEncodeURIComponent(labelValue) + ); + } else { + throw new Error("No value provided for input HTTP label: " + memberName + "."); + } + return resolvedPath2; +}; + +// src/submodules/protocols/requestBuilder.ts +function requestBuilder(input, context) { + return new RequestBuilder(input, context); +} +var RequestBuilder = class { + constructor(input, context) { + this.input = input; + this.context = context; + this.query = {}; + this.method = ""; + this.headers = {}; + this.path = ""; + this.body = null; + this.hostname = ""; + this.resolvePathStack = []; + } + async build() { + const { hostname, protocol = "https", port, path: basePath } = await this.context.endpoint(); + this.path = basePath; + for (const resolvePath of this.resolvePathStack) { + resolvePath(this.path); + } + return new import_protocol_http4.HttpRequest({ + protocol, + hostname: this.hostname || hostname, + port, + method: this.method, + path: this.path, + query: this.query, + body: this.body, + headers: this.headers + }); + } + /** + * Brevity setter for "hostname". + */ + hn(hostname) { + this.hostname = hostname; + return this; + } + /** + * Brevity initial builder for "basepath". + */ + bp(uriLabel) { + this.resolvePathStack.push((basePath) => { + this.path = `${basePath?.endsWith("/") ? basePath.slice(0, -1) : basePath || ""}` + uriLabel; + }); + return this; + } + /** + * Brevity incremental builder for "path". + */ + p(memberName, labelValueProvider, uriLabel, isGreedyLabel) { + this.resolvePathStack.push((path) => { + this.path = resolvedPath(path, this.input, memberName, labelValueProvider, uriLabel, isGreedyLabel); + }); + return this; + } + /** + * Brevity setter for "headers". + */ + h(headers) { + this.headers = headers; + return this; + } + /** + * Brevity setter for "query". + */ + q(query) { + this.query = query; + return this; + } + /** + * Brevity setter for "body". + */ + b(body) { + this.body = body; + return this; + } + /** + * Brevity setter for "method". + */ + m(method) { + this.method = method; + return this; + } +}; + +// src/submodules/protocols/serde/FromStringShapeDeserializer.ts +var import_schema5 = __nccwpck_require__(26890); +var import_serde2 = __nccwpck_require__(92430); +var import_util_base64 = __nccwpck_require__(68385); +var import_util_utf8 = __nccwpck_require__(71577); + +// src/submodules/protocols/serde/determineTimestampFormat.ts +var import_schema4 = __nccwpck_require__(26890); +function determineTimestampFormat(ns, settings) { + if (settings.timestampFormat.useTrait) { + if (ns.isTimestampSchema() && (ns.getSchema() === import_schema4.SCHEMA.TIMESTAMP_DATE_TIME || ns.getSchema() === import_schema4.SCHEMA.TIMESTAMP_HTTP_DATE || ns.getSchema() === import_schema4.SCHEMA.TIMESTAMP_EPOCH_SECONDS)) { + return ns.getSchema(); + } + } + const { httpLabel, httpPrefixHeaders, httpHeader, httpQuery } = ns.getMergedTraits(); + const bindingFormat = settings.httpBindings ? typeof httpPrefixHeaders === "string" || Boolean(httpHeader) ? import_schema4.SCHEMA.TIMESTAMP_HTTP_DATE : Boolean(httpQuery) || Boolean(httpLabel) ? import_schema4.SCHEMA.TIMESTAMP_DATE_TIME : void 0 : void 0; + return bindingFormat ?? settings.timestampFormat.default; +} + +// src/submodules/protocols/serde/FromStringShapeDeserializer.ts +var FromStringShapeDeserializer = class { + constructor(settings) { + this.settings = settings; + } + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + } + read(_schema, data) { + const ns = import_schema5.NormalizedSchema.of(_schema); + if (ns.isListSchema()) { + return (0, import_serde2.splitHeader)(data).map((item) => this.read(ns.getValueSchema(), item)); + } + if (ns.isBlobSchema()) { + return (this.serdeContext?.base64Decoder ?? import_util_base64.fromBase64)(data); + } + if (ns.isTimestampSchema()) { + const format = determineTimestampFormat(ns, this.settings); + switch (format) { + case import_schema5.SCHEMA.TIMESTAMP_DATE_TIME: + return (0, import_serde2.parseRfc3339DateTimeWithOffset)(data); + case import_schema5.SCHEMA.TIMESTAMP_HTTP_DATE: + return (0, import_serde2.parseRfc7231DateTime)(data); + case import_schema5.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + return (0, import_serde2.parseEpochTimestamp)(data); + default: + console.warn("Missing timestamp format, parsing value with Date constructor:", data); + return new Date(data); + } + } + if (ns.isStringSchema()) { + const mediaType = ns.getMergedTraits().mediaType; + let intermediateValue = data; + if (mediaType) { + if (ns.getMergedTraits().httpHeader) { + intermediateValue = this.base64ToUtf8(intermediateValue); + } + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + intermediateValue = import_serde2.LazyJsonString.from(intermediateValue); + } + return intermediateValue; + } + } + switch (true) { + case ns.isNumericSchema(): + return Number(data); + case ns.isBigIntegerSchema(): + return BigInt(data); + case ns.isBigDecimalSchema(): + return new import_serde2.NumericValue(data, "bigDecimal"); + case ns.isBooleanSchema(): + return String(data).toLowerCase() === "true"; + } + return data; + } + base64ToUtf8(base64String) { + return (this.serdeContext?.utf8Encoder ?? import_util_utf8.toUtf8)((this.serdeContext?.base64Decoder ?? import_util_base64.fromBase64)(base64String)); + } +}; + +// src/submodules/protocols/serde/HttpInterceptingShapeDeserializer.ts +var import_schema6 = __nccwpck_require__(26890); +var import_util_utf82 = __nccwpck_require__(71577); +var HttpInterceptingShapeDeserializer = class { + constructor(codecDeserializer, codecSettings) { + this.codecDeserializer = codecDeserializer; + this.stringDeserializer = new FromStringShapeDeserializer(codecSettings); + } + setSerdeContext(serdeContext) { + this.stringDeserializer.setSerdeContext(serdeContext); + this.codecDeserializer.setSerdeContext(serdeContext); + this.serdeContext = serdeContext; + } + read(schema, data) { + const ns = import_schema6.NormalizedSchema.of(schema); + const traits = ns.getMergedTraits(); + const toString = this.serdeContext?.utf8Encoder ?? import_util_utf82.toUtf8; + if (traits.httpHeader || traits.httpResponseCode) { + return this.stringDeserializer.read(ns, toString(data)); + } + if (traits.httpPayload) { + if (ns.isBlobSchema()) { + const toBytes = this.serdeContext?.utf8Decoder ?? import_util_utf82.fromUtf8; + if (typeof data === "string") { + return toBytes(data); + } + return data; + } else if (ns.isStringSchema()) { + if ("byteLength" in data) { + return toString(data); + } + return data; + } + } + return this.codecDeserializer.read(ns, data); + } +}; + +// src/submodules/protocols/serde/HttpInterceptingShapeSerializer.ts +var import_schema8 = __nccwpck_require__(26890); + +// src/submodules/protocols/serde/ToStringShapeSerializer.ts +var import_schema7 = __nccwpck_require__(26890); +var import_serde3 = __nccwpck_require__(92430); +var import_util_base642 = __nccwpck_require__(68385); +var ToStringShapeSerializer = class { + constructor(settings) { + this.settings = settings; + this.stringBuffer = ""; + this.serdeContext = void 0; + } + setSerdeContext(serdeContext) { + this.serdeContext = serdeContext; + } + write(schema, value) { + const ns = import_schema7.NormalizedSchema.of(schema); + switch (typeof value) { + case "object": + if (value === null) { + this.stringBuffer = "null"; + return; + } + if (ns.isTimestampSchema()) { + if (!(value instanceof Date)) { + throw new Error( + `@smithy/core/protocols - received non-Date value ${value} when schema expected Date in ${ns.getName(true)}` + ); + } + const format = determineTimestampFormat(ns, this.settings); + switch (format) { + case import_schema7.SCHEMA.TIMESTAMP_DATE_TIME: + this.stringBuffer = value.toISOString().replace(".000Z", "Z"); + break; + case import_schema7.SCHEMA.TIMESTAMP_HTTP_DATE: + this.stringBuffer = (0, import_serde3.dateToUtcString)(value); + break; + case import_schema7.SCHEMA.TIMESTAMP_EPOCH_SECONDS: + this.stringBuffer = String(value.getTime() / 1e3); + break; + default: + console.warn("Missing timestamp format, using epoch seconds", value); + this.stringBuffer = String(value.getTime() / 1e3); + } + return; + } + if (ns.isBlobSchema() && "byteLength" in value) { + this.stringBuffer = (this.serdeContext?.base64Encoder ?? import_util_base642.toBase64)(value); + return; + } + if (ns.isListSchema() && Array.isArray(value)) { + let buffer = ""; + for (const item of value) { + this.write([ns.getValueSchema(), ns.getMergedTraits()], item); + const headerItem = this.flush(); + const serialized = ns.getValueSchema().isTimestampSchema() ? headerItem : (0, import_serde3.quoteHeader)(headerItem); + if (buffer !== "") { + buffer += ", "; + } + buffer += serialized; + } + this.stringBuffer = buffer; + return; + } + this.stringBuffer = JSON.stringify(value, null, 2); + break; + case "string": + const mediaType = ns.getMergedTraits().mediaType; + let intermediateValue = value; + if (mediaType) { + const isJson = mediaType === "application/json" || mediaType.endsWith("+json"); + if (isJson) { + intermediateValue = import_serde3.LazyJsonString.from(intermediateValue); + } + if (ns.getMergedTraits().httpHeader) { + this.stringBuffer = (this.serdeContext?.base64Encoder ?? import_util_base642.toBase64)(intermediateValue.toString()); + return; + } + } + this.stringBuffer = value; + break; + default: + this.stringBuffer = String(value); + } + } + flush() { + const buffer = this.stringBuffer; + this.stringBuffer = ""; + return buffer; + } +}; + +// src/submodules/protocols/serde/HttpInterceptingShapeSerializer.ts +var HttpInterceptingShapeSerializer = class { + constructor(codecSerializer, codecSettings, stringSerializer = new ToStringShapeSerializer(codecSettings)) { + this.codecSerializer = codecSerializer; + this.stringSerializer = stringSerializer; + } + setSerdeContext(serdeContext) { + this.codecSerializer.setSerdeContext(serdeContext); + this.stringSerializer.setSerdeContext(serdeContext); + } + write(schema, value) { + const ns = import_schema8.NormalizedSchema.of(schema); + const traits = ns.getMergedTraits(); + if (traits.httpHeader || traits.httpLabel || traits.httpQuery) { + this.stringSerializer.write(ns, value); + this.buffer = this.stringSerializer.flush(); + return; + } + return this.codecSerializer.write(ns, value); + } + flush() { + if (this.buffer !== void 0) { + const buffer = this.buffer; + this.buffer = void 0; + return buffer; + } + return this.codecSerializer.flush(); + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 26890: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/schema/index.ts +var schema_exports = {}; +__export(schema_exports, { + ErrorSchema: () => ErrorSchema, + ListSchema: () => ListSchema, + MapSchema: () => MapSchema, + NormalizedSchema: () => NormalizedSchema, + OperationSchema: () => OperationSchema, + SCHEMA: () => SCHEMA, + Schema: () => Schema, + SimpleSchema: () => SimpleSchema, + StructureSchema: () => StructureSchema, + TypeRegistry: () => TypeRegistry, + deref: () => deref, + deserializerMiddlewareOption: () => deserializerMiddlewareOption, + error: () => error, + getSchemaSerdePlugin: () => getSchemaSerdePlugin, + list: () => list, + map: () => map, + op: () => op, + serializerMiddlewareOption: () => serializerMiddlewareOption, + sim: () => sim, + struct: () => struct +}); +module.exports = __toCommonJS(schema_exports); + +// src/submodules/schema/deref.ts +var deref = (schemaRef) => { + if (typeof schemaRef === "function") { + return schemaRef(); + } + return schemaRef; +}; + +// src/submodules/schema/middleware/schemaDeserializationMiddleware.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_util_middleware = __nccwpck_require__(76324); +var schemaDeserializationMiddleware = (config) => (next, context) => async (args) => { + const { response } = await next(args); + const { operationSchema } = (0, import_util_middleware.getSmithyContext)(context); + try { + const parsed = await config.protocol.deserializeResponse( + operationSchema, + { + ...config, + ...context + }, + response + ); + return { + response, + output: parsed + }; + } catch (error2) { + Object.defineProperty(error2, "$response", { + value: response + }); + if (!("$metadata" in error2)) { + const hint = `Deserialization error: to see the raw response, inspect the hidden field {error}.$response on this object.`; + try { + error2.message += "\n " + hint; + } catch (e) { + if (!context.logger || context.logger?.constructor?.name === "NoOpLogger") { + console.warn(hint); + } else { + context.logger?.warn?.(hint); + } + } + if (typeof error2.$responseBodyText !== "undefined") { + if (error2.$response) { + error2.$response.body = error2.$responseBodyText; + } + } + try { + if (import_protocol_http.HttpResponse.isInstance(response)) { + const { headers = {} } = response; + const headerEntries = Object.entries(headers); + error2.$metadata = { + httpStatusCode: response.statusCode, + requestId: findHeader(/^x-[\w-]+-request-?id$/, headerEntries), + extendedRequestId: findHeader(/^x-[\w-]+-id-2$/, headerEntries), + cfId: findHeader(/^x-[\w-]+-cf-id$/, headerEntries) + }; + } + } catch (e) { + } + } + throw error2; + } +}; +var findHeader = (pattern, headers) => { + return (headers.find(([k]) => { + return k.match(pattern); + }) || [void 0, void 0])[1]; +}; + +// src/submodules/schema/middleware/schemaSerializationMiddleware.ts +var import_util_middleware2 = __nccwpck_require__(76324); +var schemaSerializationMiddleware = (config) => (next, context) => async (args) => { + const { operationSchema } = (0, import_util_middleware2.getSmithyContext)(context); + const endpoint = context.endpointV2?.url && config.urlParser ? async () => config.urlParser(context.endpointV2.url) : config.endpoint; + const request = await config.protocol.serializeRequest(operationSchema, args.input, { + ...config, + ...context, + endpoint + }); + return next({ + ...args, + request + }); +}; + +// src/submodules/schema/middleware/getSchemaSerdePlugin.ts +var deserializerMiddlewareOption = { + name: "deserializerMiddleware", + step: "deserialize", + tags: ["DESERIALIZER"], + override: true +}; +var serializerMiddlewareOption = { + name: "serializerMiddleware", + step: "serialize", + tags: ["SERIALIZER"], + override: true +}; +function getSchemaSerdePlugin(config) { + return { + applyToStack: (commandStack) => { + commandStack.add(schemaSerializationMiddleware(config), serializerMiddlewareOption); + commandStack.add(schemaDeserializationMiddleware(config), deserializerMiddlewareOption); + config.protocol.setSerdeContext(config); + } + }; +} + +// src/submodules/schema/TypeRegistry.ts +var TypeRegistry = class _TypeRegistry { + constructor(namespace, schemas = /* @__PURE__ */ new Map()) { + this.namespace = namespace; + this.schemas = schemas; + } + static { + this.registries = /* @__PURE__ */ new Map(); + } + /** + * @param namespace - specifier. + * @returns the schema for that namespace, creating it if necessary. + */ + static for(namespace) { + if (!_TypeRegistry.registries.has(namespace)) { + _TypeRegistry.registries.set(namespace, new _TypeRegistry(namespace)); + } + return _TypeRegistry.registries.get(namespace); + } + /** + * Adds the given schema to a type registry with the same namespace. + * + * @param shapeId - to be registered. + * @param schema - to be registered. + */ + register(shapeId, schema) { + const qualifiedName = this.normalizeShapeId(shapeId); + const registry = _TypeRegistry.for(this.getNamespace(shapeId)); + registry.schemas.set(qualifiedName, schema); + } + /** + * @param shapeId - query. + * @returns the schema. + */ + getSchema(shapeId) { + const id = this.normalizeShapeId(shapeId); + if (!this.schemas.has(id)) { + throw new Error(`@smithy/core/schema - schema not found for ${id}`); + } + return this.schemas.get(id); + } + /** + * The smithy-typescript code generator generates a synthetic (i.e. unmodeled) base exception, + * because generated SDKs before the introduction of schemas have the notion of a ServiceBaseException, which + * is unique per service/model. + * + * This is generated under a unique prefix that is combined with the service namespace, and this + * method is used to retrieve it. + * + * The base exception synthetic schema is used when an error is returned by a service, but we cannot + * determine what existing schema to use to deserialize it. + * + * @returns the synthetic base exception of the service namespace associated with this registry instance. + */ + getBaseException() { + for (const [id, schema] of this.schemas.entries()) { + if (id.startsWith("smithy.ts.sdk.synthetic.") && id.endsWith("ServiceException")) { + return schema; + } + } + return void 0; + } + /** + * @param predicate - criterion. + * @returns a schema in this registry matching the predicate. + */ + find(predicate) { + return [...this.schemas.values()].find(predicate); + } + /** + * Unloads the current TypeRegistry. + */ + destroy() { + _TypeRegistry.registries.delete(this.namespace); + this.schemas.clear(); + } + normalizeShapeId(shapeId) { + if (shapeId.includes("#")) { + return shapeId; + } + return this.namespace + "#" + shapeId; + } + getNamespace(shapeId) { + return this.normalizeShapeId(shapeId).split("#")[0]; + } +}; + +// src/submodules/schema/schemas/Schema.ts +var Schema = class { + constructor(name, traits) { + this.name = name; + this.traits = traits; + } +}; + +// src/submodules/schema/schemas/ListSchema.ts +var ListSchema = class _ListSchema extends Schema { + constructor(name, traits, valueSchema) { + super(name, traits); + this.name = name; + this.traits = traits; + this.valueSchema = valueSchema; + this.symbol = _ListSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::ListSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _ListSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const list2 = lhs; + return list2.symbol === _ListSchema.symbol; + } + return isPrototype; + } +}; +function list(namespace, name, traits = {}, valueSchema) { + const schema = new ListSchema( + namespace + "#" + name, + traits, + typeof valueSchema === "function" ? valueSchema() : valueSchema + ); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/MapSchema.ts +var MapSchema = class _MapSchema extends Schema { + constructor(name, traits, keySchema, valueSchema) { + super(name, traits); + this.name = name; + this.traits = traits; + this.keySchema = keySchema; + this.valueSchema = valueSchema; + this.symbol = _MapSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::MapSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _MapSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const map2 = lhs; + return map2.symbol === _MapSchema.symbol; + } + return isPrototype; + } +}; +function map(namespace, name, traits = {}, keySchema, valueSchema) { + const schema = new MapSchema( + namespace + "#" + name, + traits, + keySchema, + typeof valueSchema === "function" ? valueSchema() : valueSchema + ); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/OperationSchema.ts +var OperationSchema = class extends Schema { + constructor(name, traits, input, output) { + super(name, traits); + this.name = name; + this.traits = traits; + this.input = input; + this.output = output; + } +}; +function op(namespace, name, traits = {}, input, output) { + const schema = new OperationSchema(namespace + "#" + name, traits, input, output); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/StructureSchema.ts +var StructureSchema = class _StructureSchema extends Schema { + constructor(name, traits, memberNames, memberList) { + super(name, traits); + this.name = name; + this.traits = traits; + this.memberNames = memberNames; + this.memberList = memberList; + this.symbol = _StructureSchema.symbol; + this.members = {}; + for (let i = 0; i < memberNames.length; ++i) { + this.members[memberNames[i]] = Array.isArray(memberList[i]) ? memberList[i] : [memberList[i], 0]; + } + } + static { + this.symbol = Symbol.for("@smithy/core/schema::StructureSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _StructureSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const struct2 = lhs; + return struct2.symbol === _StructureSchema.symbol; + } + return isPrototype; + } +}; +function struct(namespace, name, traits, memberNames, memberList) { + const schema = new StructureSchema(namespace + "#" + name, traits, memberNames, memberList); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/ErrorSchema.ts +var ErrorSchema = class _ErrorSchema extends StructureSchema { + constructor(name, traits, memberNames, memberList, ctor) { + super(name, traits, memberNames, memberList); + this.name = name; + this.traits = traits; + this.memberNames = memberNames; + this.memberList = memberList; + this.ctor = ctor; + this.symbol = _ErrorSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::ErrorSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _ErrorSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const err = lhs; + return err.symbol === _ErrorSchema.symbol; + } + return isPrototype; + } +}; +function error(namespace, name, traits = {}, memberNames, memberList, ctor) { + const schema = new ErrorSchema(namespace + "#" + name, traits, memberNames, memberList, ctor); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/sentinels.ts +var SCHEMA = { + BLOB: 21, + // 21 + STREAMING_BLOB: 42, + // 42 + BOOLEAN: 2, + // 2 + STRING: 0, + // 0 + NUMERIC: 1, + // 1 + BIG_INTEGER: 17, + // 17 + BIG_DECIMAL: 19, + // 19 + DOCUMENT: 15, + // 15 + TIMESTAMP_DEFAULT: 4, + // 4 + TIMESTAMP_DATE_TIME: 5, + // 5 + TIMESTAMP_HTTP_DATE: 6, + // 6 + TIMESTAMP_EPOCH_SECONDS: 7, + // 7 + LIST_MODIFIER: 64, + // 64 + MAP_MODIFIER: 128 + // 128 +}; + +// src/submodules/schema/schemas/SimpleSchema.ts +var SimpleSchema = class _SimpleSchema extends Schema { + constructor(name, schemaRef, traits) { + super(name, traits); + this.name = name; + this.schemaRef = schemaRef; + this.traits = traits; + this.symbol = _SimpleSchema.symbol; + } + static { + this.symbol = Symbol.for("@smithy/core/schema::SimpleSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _SimpleSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const sim2 = lhs; + return sim2.symbol === _SimpleSchema.symbol; + } + return isPrototype; + } +}; +function sim(namespace, name, schemaRef, traits) { + const schema = new SimpleSchema(namespace + "#" + name, schemaRef, traits); + TypeRegistry.for(namespace).register(name, schema); + return schema; +} + +// src/submodules/schema/schemas/NormalizedSchema.ts +var NormalizedSchema = class _NormalizedSchema { + /** + * @param ref - a polymorphic SchemaRef to be dereferenced/normalized. + * @param memberName - optional memberName if this NormalizedSchema should be considered a member schema. + */ + constructor(ref, memberName) { + this.ref = ref; + this.memberName = memberName; + this.symbol = _NormalizedSchema.symbol; + const traitStack = []; + let _ref = ref; + let schema = ref; + this._isMemberSchema = false; + while (Array.isArray(_ref)) { + traitStack.push(_ref[1]); + _ref = _ref[0]; + schema = deref(_ref); + this._isMemberSchema = true; + } + if (traitStack.length > 0) { + this.memberTraits = {}; + for (let i = traitStack.length - 1; i >= 0; --i) { + const traitSet = traitStack[i]; + Object.assign(this.memberTraits, _NormalizedSchema.translateTraits(traitSet)); + } + } else { + this.memberTraits = 0; + } + if (schema instanceof _NormalizedSchema) { + this.name = schema.name; + this.traits = schema.traits; + this._isMemberSchema = schema._isMemberSchema; + this.schema = schema.schema; + this.memberTraits = Object.assign({}, schema.getMemberTraits(), this.getMemberTraits()); + this.normalizedTraits = void 0; + this.ref = schema.ref; + this.memberName = memberName ?? schema.memberName; + return; + } + this.schema = deref(schema); + if (this.schema && typeof this.schema === "object") { + this.traits = this.schema?.traits ?? {}; + } else { + this.traits = 0; + } + this.name = (typeof this.schema === "object" ? this.schema?.name : void 0) ?? this.memberName ?? this.getSchemaName(); + if (this._isMemberSchema && !memberName) { + throw new Error( + `@smithy/core/schema - NormalizedSchema member schema ${this.getName( + true + )} must initialize with memberName argument.` + ); + } + } + static { + this.symbol = Symbol.for("@smithy/core/schema::NormalizedSchema"); + } + static [Symbol.hasInstance](lhs) { + const isPrototype = _NormalizedSchema.prototype.isPrototypeOf(lhs); + if (!isPrototype && typeof lhs === "object" && lhs !== null) { + const ns = lhs; + return ns.symbol === _NormalizedSchema.symbol; + } + return isPrototype; + } + /** + * Static constructor that attempts to avoid wrapping a NormalizedSchema within another. + */ + static of(ref, memberName) { + if (ref instanceof _NormalizedSchema) { + return ref; + } + return new _NormalizedSchema(ref, memberName); + } + /** + * @param indicator - numeric indicator for preset trait combination. + * @returns equivalent trait object. + */ + static translateTraits(indicator) { + if (typeof indicator === "object") { + return indicator; + } + indicator = indicator | 0; + const traits = {}; + if ((indicator & 1) === 1) { + traits.httpLabel = 1; + } + if ((indicator >> 1 & 1) === 1) { + traits.idempotent = 1; + } + if ((indicator >> 2 & 1) === 1) { + traits.idempotencyToken = 1; + } + if ((indicator >> 3 & 1) === 1) { + traits.sensitive = 1; + } + if ((indicator >> 4 & 1) === 1) { + traits.httpPayload = 1; + } + if ((indicator >> 5 & 1) === 1) { + traits.httpResponseCode = 1; + } + if ((indicator >> 6 & 1) === 1) { + traits.httpQueryParams = 1; + } + return traits; + } + /** + * Creates a normalized member schema from the given schema and member name. + */ + static memberFrom(memberSchema, memberName) { + if (memberSchema instanceof _NormalizedSchema) { + memberSchema.memberName = memberName; + memberSchema._isMemberSchema = true; + return memberSchema; + } + return new _NormalizedSchema(memberSchema, memberName); + } + /** + * @returns the underlying non-normalized schema. + */ + getSchema() { + if (this.schema instanceof _NormalizedSchema) { + return this.schema = this.schema.getSchema(); + } + if (this.schema instanceof SimpleSchema) { + return deref(this.schema.schemaRef); + } + return deref(this.schema); + } + /** + * @param withNamespace - qualifies the name. + * @returns e.g. `MyShape` or `com.namespace#MyShape`. + */ + getName(withNamespace = false) { + if (!withNamespace) { + if (this.name && this.name.includes("#")) { + return this.name.split("#")[1]; + } + } + return this.name || void 0; + } + /** + * @returns the member name if the schema is a member schema. + * @throws Error when the schema isn't a member schema. + */ + getMemberName() { + if (!this.isMemberSchema()) { + throw new Error(`@smithy/core/schema - cannot get member name on non-member schema: ${this.getName(true)}`); + } + return this.memberName; + } + isMemberSchema() { + return this._isMemberSchema; + } + isUnitSchema() { + return this.getSchema() === "unit"; + } + /** + * boolean methods on this class help control flow in shape serialization and deserialization. + */ + isListSchema() { + const inner = this.getSchema(); + if (typeof inner === "number") { + return inner >= SCHEMA.LIST_MODIFIER && inner < SCHEMA.MAP_MODIFIER; + } + return inner instanceof ListSchema; + } + isMapSchema() { + const inner = this.getSchema(); + if (typeof inner === "number") { + return inner >= SCHEMA.MAP_MODIFIER && inner <= 255; + } + return inner instanceof MapSchema; + } + isDocumentSchema() { + return this.getSchema() === SCHEMA.DOCUMENT; + } + isStructSchema() { + const inner = this.getSchema(); + return inner !== null && typeof inner === "object" && "members" in inner || inner instanceof StructureSchema; + } + isBlobSchema() { + return this.getSchema() === SCHEMA.BLOB || this.getSchema() === SCHEMA.STREAMING_BLOB; + } + isTimestampSchema() { + const schema = this.getSchema(); + return typeof schema === "number" && schema >= SCHEMA.TIMESTAMP_DEFAULT && schema <= SCHEMA.TIMESTAMP_EPOCH_SECONDS; + } + isStringSchema() { + return this.getSchema() === SCHEMA.STRING; + } + isBooleanSchema() { + return this.getSchema() === SCHEMA.BOOLEAN; + } + isNumericSchema() { + return this.getSchema() === SCHEMA.NUMERIC; + } + isBigIntegerSchema() { + return this.getSchema() === SCHEMA.BIG_INTEGER; + } + isBigDecimalSchema() { + return this.getSchema() === SCHEMA.BIG_DECIMAL; + } + isStreaming() { + const streaming = !!this.getMergedTraits().streaming; + if (streaming) { + return true; + } + return this.getSchema() === SCHEMA.STREAMING_BLOB; + } + /** + * @returns own traits merged with member traits, where member traits of the same trait key take priority. + * This method is cached. + */ + getMergedTraits() { + if (this.normalizedTraits) { + return this.normalizedTraits; + } + this.normalizedTraits = { + ...this.getOwnTraits(), + ...this.getMemberTraits() + }; + return this.normalizedTraits; + } + /** + * @returns only the member traits. If the schema is not a member, this returns empty. + */ + getMemberTraits() { + return _NormalizedSchema.translateTraits(this.memberTraits); + } + /** + * @returns only the traits inherent to the shape or member target shape if this schema is a member. + * If there are any member traits they are excluded. + */ + getOwnTraits() { + return _NormalizedSchema.translateTraits(this.traits); + } + /** + * @returns the map's key's schema. Returns a dummy Document schema if this schema is a Document. + * + * @throws Error if the schema is not a Map or Document. + */ + getKeySchema() { + if (this.isDocumentSchema()) { + return _NormalizedSchema.memberFrom([SCHEMA.DOCUMENT, 0], "key"); + } + if (!this.isMapSchema()) { + throw new Error(`@smithy/core/schema - cannot get key schema for non-map schema: ${this.getName(true)}`); + } + const schema = this.getSchema(); + if (typeof schema === "number") { + return _NormalizedSchema.memberFrom([63 & schema, 0], "key"); + } + return _NormalizedSchema.memberFrom([schema.keySchema, 0], "key"); + } + /** + * @returns the schema of the map's value or list's member. + * Returns a dummy Document schema if this schema is a Document. + * + * @throws Error if the schema is not a Map, List, nor Document. + */ + getValueSchema() { + const schema = this.getSchema(); + if (typeof schema === "number") { + if (this.isMapSchema()) { + return _NormalizedSchema.memberFrom([63 & schema, 0], "value"); + } else if (this.isListSchema()) { + return _NormalizedSchema.memberFrom([63 & schema, 0], "member"); + } + } + if (schema && typeof schema === "object") { + if (this.isStructSchema()) { + throw new Error(`cannot call getValueSchema() with StructureSchema ${this.getName(true)}`); + } + const collection = schema; + if ("valueSchema" in collection) { + if (this.isMapSchema()) { + return _NormalizedSchema.memberFrom([collection.valueSchema, 0], "value"); + } else if (this.isListSchema()) { + return _NormalizedSchema.memberFrom([collection.valueSchema, 0], "member"); + } + } + } + if (this.isDocumentSchema()) { + return _NormalizedSchema.memberFrom([SCHEMA.DOCUMENT, 0], "value"); + } + throw new Error(`@smithy/core/schema - the schema ${this.getName(true)} does not have a value member.`); + } + /** + * @returns the NormalizedSchema for the given member name. The returned instance will return true for `isMemberSchema()` + * and will have the member name given. + * @param member - which member to retrieve and wrap. + * + * @throws Error if member does not exist or the schema is neither a document nor structure. + * Note that errors are assumed to be structures and unions are considered structures for these purposes. + */ + getMemberSchema(member) { + if (this.isStructSchema()) { + const struct2 = this.getSchema(); + if (!(member in struct2.members)) { + throw new Error( + `@smithy/core/schema - the schema ${this.getName(true)} does not have a member with name=${member}.` + ); + } + return _NormalizedSchema.memberFrom(struct2.members[member], member); + } + if (this.isDocumentSchema()) { + return _NormalizedSchema.memberFrom([SCHEMA.DOCUMENT, 0], member); + } + throw new Error(`@smithy/core/schema - the schema ${this.getName(true)} does not have members.`); + } + /** + * This can be used for checking the members as a hashmap. + * Prefer the structIterator method for iteration. + * + * This does NOT return list and map members, it is only for structures. + * + * @returns a map of member names to member schemas (normalized). + */ + getMemberSchemas() { + const { schema } = this; + const struct2 = schema; + if (!struct2 || typeof struct2 !== "object") { + return {}; + } + if ("members" in struct2) { + const buffer = {}; + for (const member of struct2.memberNames) { + buffer[member] = this.getMemberSchema(member); + } + return buffer; + } + return {}; + } + /** + * Allows iteration over members of a structure schema. + * Each yield is a pair of the member name and member schema. + * + * This avoids the overhead of calling Object.entries(ns.getMemberSchemas()). + */ + *structIterator() { + if (this.isUnitSchema()) { + return; + } + if (!this.isStructSchema()) { + throw new Error("@smithy/core/schema - cannot acquire structIterator on non-struct schema."); + } + const struct2 = this.getSchema(); + for (let i = 0; i < struct2.memberNames.length; ++i) { + yield [struct2.memberNames[i], _NormalizedSchema.memberFrom([struct2.memberList[i], 0], struct2.memberNames[i])]; + } + } + /** + * @returns a last-resort human-readable name for the schema if it has no other identifiers. + */ + getSchemaName() { + const schema = this.getSchema(); + if (typeof schema === "number") { + const _schema = 63 & schema; + const container = 192 & schema; + const type = Object.entries(SCHEMA).find(([, value]) => { + return value === _schema; + })?.[0] ?? "Unknown"; + switch (container) { + case SCHEMA.MAP_MODIFIER: + return `${type}Map`; + case SCHEMA.LIST_MODIFIER: + return `${type}List`; + case 0: + return type; + } + } + return "Unknown"; + } +}; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 92430: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/submodules/serde/index.ts +var serde_exports = {}; +__export(serde_exports, { + LazyJsonString: () => LazyJsonString, + NumericValue: () => NumericValue, + copyDocumentWithTransform: () => copyDocumentWithTransform, + dateToUtcString: () => dateToUtcString, + expectBoolean: () => expectBoolean, + expectByte: () => expectByte, + expectFloat32: () => expectFloat32, + expectInt: () => expectInt, + expectInt32: () => expectInt32, + expectLong: () => expectLong, + expectNonNull: () => expectNonNull, + expectNumber: () => expectNumber, + expectObject: () => expectObject, + expectShort: () => expectShort, + expectString: () => expectString, + expectUnion: () => expectUnion, + handleFloat: () => handleFloat, + limitedParseDouble: () => limitedParseDouble, + limitedParseFloat: () => limitedParseFloat, + limitedParseFloat32: () => limitedParseFloat32, + logger: () => logger, + nv: () => nv, + parseBoolean: () => parseBoolean, + parseEpochTimestamp: () => parseEpochTimestamp, + parseRfc3339DateTime: () => parseRfc3339DateTime, + parseRfc3339DateTimeWithOffset: () => parseRfc3339DateTimeWithOffset, + parseRfc7231DateTime: () => parseRfc7231DateTime, + quoteHeader: () => quoteHeader, + splitEvery: () => splitEvery, + splitHeader: () => splitHeader, + strictParseByte: () => strictParseByte, + strictParseDouble: () => strictParseDouble, + strictParseFloat: () => strictParseFloat, + strictParseFloat32: () => strictParseFloat32, + strictParseInt: () => strictParseInt, + strictParseInt32: () => strictParseInt32, + strictParseLong: () => strictParseLong, + strictParseShort: () => strictParseShort +}); +module.exports = __toCommonJS(serde_exports); + +// src/submodules/serde/copyDocumentWithTransform.ts +var import_schema = __nccwpck_require__(26890); +var copyDocumentWithTransform = (source, schemaRef, transform = (_) => _) => { + const ns = import_schema.NormalizedSchema.of(schemaRef); + switch (typeof source) { + case "undefined": + case "boolean": + case "number": + case "string": + case "bigint": + case "symbol": + return transform(source, ns); + case "function": + case "object": + if (source === null) { + return transform(null, ns); + } + if (Array.isArray(source)) { + const newArray = new Array(source.length); + let i = 0; + for (const item of source) { + newArray[i++] = copyDocumentWithTransform(item, ns.getValueSchema(), transform); + } + return transform(newArray, ns); + } + if ("byteLength" in source) { + const newBytes = new Uint8Array(source.byteLength); + newBytes.set(source, 0); + return transform(newBytes, ns); + } + if (source instanceof Date) { + return transform(source, ns); + } + const newObject = {}; + if (ns.isMapSchema()) { + for (const key of Object.keys(source)) { + newObject[key] = copyDocumentWithTransform(source[key], ns.getValueSchema(), transform); + } + } else if (ns.isStructSchema()) { + for (const [key, memberSchema] of ns.structIterator()) { + newObject[key] = copyDocumentWithTransform(source[key], memberSchema, transform); + } + } else if (ns.isDocumentSchema()) { + for (const key of Object.keys(source)) { + newObject[key] = copyDocumentWithTransform(source[key], ns.getValueSchema(), transform); + } + } + return transform(newObject, ns); + default: + return transform(source, ns); + } +}; + +// src/submodules/serde/parse-utils.ts +var parseBoolean = (value) => { + switch (value) { + case "true": + return true; + case "false": + return false; + default: + throw new Error(`Unable to parse boolean value "${value}"`); + } +}; +var expectBoolean = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "number") { + if (value === 0 || value === 1) { + logger.warn(stackTraceWarning(`Expected boolean, got ${typeof value}: ${value}`)); + } + if (value === 0) { + return false; + } + if (value === 1) { + return true; + } + } + if (typeof value === "string") { + const lower = value.toLowerCase(); + if (lower === "false" || lower === "true") { + logger.warn(stackTraceWarning(`Expected boolean, got ${typeof value}: ${value}`)); + } + if (lower === "false") { + return false; + } + if (lower === "true") { + return true; + } + } + if (typeof value === "boolean") { + return value; + } + throw new TypeError(`Expected boolean, got ${typeof value}: ${value}`); +}; +var expectNumber = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "string") { + const parsed = parseFloat(value); + if (!Number.isNaN(parsed)) { + if (String(parsed) !== String(value)) { + logger.warn(stackTraceWarning(`Expected number but observed string: ${value}`)); + } + return parsed; + } + } + if (typeof value === "number") { + return value; + } + throw new TypeError(`Expected number, got ${typeof value}: ${value}`); +}; +var MAX_FLOAT = Math.ceil(2 ** 127 * (2 - 2 ** -23)); +var expectFloat32 = (value) => { + const expected = expectNumber(value); + if (expected !== void 0 && !Number.isNaN(expected) && expected !== Infinity && expected !== -Infinity) { + if (Math.abs(expected) > MAX_FLOAT) { + throw new TypeError(`Expected 32-bit float, got ${value}`); + } + } + return expected; +}; +var expectLong = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (Number.isInteger(value) && !Number.isNaN(value)) { + return value; + } + throw new TypeError(`Expected integer, got ${typeof value}: ${value}`); +}; +var expectInt = expectLong; +var expectInt32 = (value) => expectSizedInt(value, 32); +var expectShort = (value) => expectSizedInt(value, 16); +var expectByte = (value) => expectSizedInt(value, 8); +var expectSizedInt = (value, size) => { + const expected = expectLong(value); + if (expected !== void 0 && castInt(expected, size) !== expected) { + throw new TypeError(`Expected ${size}-bit integer, got ${value}`); + } + return expected; +}; +var castInt = (value, size) => { + switch (size) { + case 32: + return Int32Array.of(value)[0]; + case 16: + return Int16Array.of(value)[0]; + case 8: + return Int8Array.of(value)[0]; + } +}; +var expectNonNull = (value, location) => { + if (value === null || value === void 0) { + if (location) { + throw new TypeError(`Expected a non-null value for ${location}`); + } + throw new TypeError("Expected a non-null value"); + } + return value; +}; +var expectObject = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "object" && !Array.isArray(value)) { + return value; + } + const receivedType = Array.isArray(value) ? "array" : typeof value; + throw new TypeError(`Expected object, got ${receivedType}: ${value}`); +}; +var expectString = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value === "string") { + return value; + } + if (["boolean", "number", "bigint"].includes(typeof value)) { + logger.warn(stackTraceWarning(`Expected string, got ${typeof value}: ${value}`)); + return String(value); + } + throw new TypeError(`Expected string, got ${typeof value}: ${value}`); +}; +var expectUnion = (value) => { + if (value === null || value === void 0) { + return void 0; + } + const asObject = expectObject(value); + const setKeys = Object.entries(asObject).filter(([, v]) => v != null).map(([k]) => k); + if (setKeys.length === 0) { + throw new TypeError(`Unions must have exactly one non-null member. None were found.`); + } + if (setKeys.length > 1) { + throw new TypeError(`Unions must have exactly one non-null member. Keys ${setKeys} were not null.`); + } + return asObject; +}; +var strictParseDouble = (value) => { + if (typeof value == "string") { + return expectNumber(parseNumber(value)); + } + return expectNumber(value); +}; +var strictParseFloat = strictParseDouble; +var strictParseFloat32 = (value) => { + if (typeof value == "string") { + return expectFloat32(parseNumber(value)); + } + return expectFloat32(value); +}; +var NUMBER_REGEX = /(-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)|(-?Infinity)|(NaN)/g; +var parseNumber = (value) => { + const matches = value.match(NUMBER_REGEX); + if (matches === null || matches[0].length !== value.length) { + throw new TypeError(`Expected real number, got implicit NaN`); + } + return parseFloat(value); +}; +var limitedParseDouble = (value) => { + if (typeof value == "string") { + return parseFloatString(value); + } + return expectNumber(value); +}; +var handleFloat = limitedParseDouble; +var limitedParseFloat = limitedParseDouble; +var limitedParseFloat32 = (value) => { + if (typeof value == "string") { + return parseFloatString(value); + } + return expectFloat32(value); +}; +var parseFloatString = (value) => { + switch (value) { + case "NaN": + return NaN; + case "Infinity": + return Infinity; + case "-Infinity": + return -Infinity; + default: + throw new Error(`Unable to parse float value: ${value}`); + } +}; +var strictParseLong = (value) => { + if (typeof value === "string") { + return expectLong(parseNumber(value)); + } + return expectLong(value); +}; +var strictParseInt = strictParseLong; +var strictParseInt32 = (value) => { + if (typeof value === "string") { + return expectInt32(parseNumber(value)); + } + return expectInt32(value); +}; +var strictParseShort = (value) => { + if (typeof value === "string") { + return expectShort(parseNumber(value)); + } + return expectShort(value); +}; +var strictParseByte = (value) => { + if (typeof value === "string") { + return expectByte(parseNumber(value)); + } + return expectByte(value); +}; +var stackTraceWarning = (message) => { + return String(new TypeError(message).stack || message).split("\n").slice(0, 5).filter((s) => !s.includes("stackTraceWarning")).join("\n"); +}; +var logger = { + warn: console.warn +}; + +// src/submodules/serde/date-utils.ts +var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; +var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; +function dateToUtcString(date) { + const year = date.getUTCFullYear(); + const month = date.getUTCMonth(); + const dayOfWeek = date.getUTCDay(); + const dayOfMonthInt = date.getUTCDate(); + const hoursInt = date.getUTCHours(); + const minutesInt = date.getUTCMinutes(); + const secondsInt = date.getUTCSeconds(); + const dayOfMonthString = dayOfMonthInt < 10 ? `0${dayOfMonthInt}` : `${dayOfMonthInt}`; + const hoursString = hoursInt < 10 ? `0${hoursInt}` : `${hoursInt}`; + const minutesString = minutesInt < 10 ? `0${minutesInt}` : `${minutesInt}`; + const secondsString = secondsInt < 10 ? `0${secondsInt}` : `${secondsInt}`; + return `${DAYS[dayOfWeek]}, ${dayOfMonthString} ${MONTHS[month]} ${year} ${hoursString}:${minutesString}:${secondsString} GMT`; +} +var RFC3339 = new RegExp(/^(\d{4})-(\d{2})-(\d{2})[tT](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?[zZ]$/); +var parseRfc3339DateTime = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value !== "string") { + throw new TypeError("RFC-3339 date-times must be expressed as strings"); + } + const match = RFC3339.exec(value); + if (!match) { + throw new TypeError("Invalid RFC-3339 date-time value"); + } + const [_, yearStr, monthStr, dayStr, hours, minutes, seconds, fractionalMilliseconds] = match; + const year = strictParseShort(stripLeadingZeroes(yearStr)); + const month = parseDateValue(monthStr, "month", 1, 12); + const day = parseDateValue(dayStr, "day", 1, 31); + return buildDate(year, month, day, { hours, minutes, seconds, fractionalMilliseconds }); +}; +var RFC3339_WITH_OFFSET = new RegExp( + /^(\d{4})-(\d{2})-(\d{2})[tT](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(([-+]\d{2}\:\d{2})|[zZ])$/ +); +var parseRfc3339DateTimeWithOffset = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value !== "string") { + throw new TypeError("RFC-3339 date-times must be expressed as strings"); + } + const match = RFC3339_WITH_OFFSET.exec(value); + if (!match) { + throw new TypeError("Invalid RFC-3339 date-time value"); + } + const [_, yearStr, monthStr, dayStr, hours, minutes, seconds, fractionalMilliseconds, offsetStr] = match; + const year = strictParseShort(stripLeadingZeroes(yearStr)); + const month = parseDateValue(monthStr, "month", 1, 12); + const day = parseDateValue(dayStr, "day", 1, 31); + const date = buildDate(year, month, day, { hours, minutes, seconds, fractionalMilliseconds }); + if (offsetStr.toUpperCase() != "Z") { + date.setTime(date.getTime() - parseOffsetToMilliseconds(offsetStr)); + } + return date; +}; +var IMF_FIXDATE = new RegExp( + /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? GMT$/ +); +var RFC_850_DATE = new RegExp( + /^(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? GMT$/ +); +var ASC_TIME = new RegExp( + /^(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( [1-9]|\d{2}) (\d{1,2}):(\d{2}):(\d{2})(?:\.(\d+))? (\d{4})$/ +); +var parseRfc7231DateTime = (value) => { + if (value === null || value === void 0) { + return void 0; + } + if (typeof value !== "string") { + throw new TypeError("RFC-7231 date-times must be expressed as strings"); + } + let match = IMF_FIXDATE.exec(value); + if (match) { + const [_, dayStr, monthStr, yearStr, hours, minutes, seconds, fractionalMilliseconds] = match; + return buildDate( + strictParseShort(stripLeadingZeroes(yearStr)), + parseMonthByShortName(monthStr), + parseDateValue(dayStr, "day", 1, 31), + { hours, minutes, seconds, fractionalMilliseconds } + ); + } + match = RFC_850_DATE.exec(value); + if (match) { + const [_, dayStr, monthStr, yearStr, hours, minutes, seconds, fractionalMilliseconds] = match; + return adjustRfc850Year( + buildDate(parseTwoDigitYear(yearStr), parseMonthByShortName(monthStr), parseDateValue(dayStr, "day", 1, 31), { + hours, + minutes, + seconds, + fractionalMilliseconds + }) + ); + } + match = ASC_TIME.exec(value); + if (match) { + const [_, monthStr, dayStr, hours, minutes, seconds, fractionalMilliseconds, yearStr] = match; + return buildDate( + strictParseShort(stripLeadingZeroes(yearStr)), + parseMonthByShortName(monthStr), + parseDateValue(dayStr.trimLeft(), "day", 1, 31), + { hours, minutes, seconds, fractionalMilliseconds } + ); + } + throw new TypeError("Invalid RFC-7231 date-time value"); +}; +var parseEpochTimestamp = (value) => { + if (value === null || value === void 0) { + return void 0; + } + let valueAsDouble; + if (typeof value === "number") { + valueAsDouble = value; + } else if (typeof value === "string") { + valueAsDouble = strictParseDouble(value); + } else if (typeof value === "object" && value.tag === 1) { + valueAsDouble = value.value; + } else { + throw new TypeError("Epoch timestamps must be expressed as floating point numbers or their string representation"); + } + if (Number.isNaN(valueAsDouble) || valueAsDouble === Infinity || valueAsDouble === -Infinity) { + throw new TypeError("Epoch timestamps must be valid, non-Infinite, non-NaN numerics"); + } + return new Date(Math.round(valueAsDouble * 1e3)); +}; +var buildDate = (year, month, day, time) => { + const adjustedMonth = month - 1; + validateDayOfMonth(year, adjustedMonth, day); + return new Date( + Date.UTC( + year, + adjustedMonth, + day, + parseDateValue(time.hours, "hour", 0, 23), + parseDateValue(time.minutes, "minute", 0, 59), + // seconds can go up to 60 for leap seconds + parseDateValue(time.seconds, "seconds", 0, 60), + parseMilliseconds(time.fractionalMilliseconds) + ) + ); +}; +var parseTwoDigitYear = (value) => { + const thisYear = (/* @__PURE__ */ new Date()).getUTCFullYear(); + const valueInThisCentury = Math.floor(thisYear / 100) * 100 + strictParseShort(stripLeadingZeroes(value)); + if (valueInThisCentury < thisYear) { + return valueInThisCentury + 100; + } + return valueInThisCentury; +}; +var FIFTY_YEARS_IN_MILLIS = 50 * 365 * 24 * 60 * 60 * 1e3; +var adjustRfc850Year = (input) => { + if (input.getTime() - (/* @__PURE__ */ new Date()).getTime() > FIFTY_YEARS_IN_MILLIS) { + return new Date( + Date.UTC( + input.getUTCFullYear() - 100, + input.getUTCMonth(), + input.getUTCDate(), + input.getUTCHours(), + input.getUTCMinutes(), + input.getUTCSeconds(), + input.getUTCMilliseconds() + ) + ); + } + return input; +}; +var parseMonthByShortName = (value) => { + const monthIdx = MONTHS.indexOf(value); + if (monthIdx < 0) { + throw new TypeError(`Invalid month: ${value}`); + } + return monthIdx + 1; +}; +var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; +var validateDayOfMonth = (year, month, day) => { + let maxDays = DAYS_IN_MONTH[month]; + if (month === 1 && isLeapYear(year)) { + maxDays = 29; + } + if (day > maxDays) { + throw new TypeError(`Invalid day for ${MONTHS[month]} in ${year}: ${day}`); + } +}; +var isLeapYear = (year) => { + return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0); +}; +var parseDateValue = (value, type, lower, upper) => { + const dateVal = strictParseByte(stripLeadingZeroes(value)); + if (dateVal < lower || dateVal > upper) { + throw new TypeError(`${type} must be between ${lower} and ${upper}, inclusive`); + } + return dateVal; +}; +var parseMilliseconds = (value) => { + if (value === null || value === void 0) { + return 0; + } + return strictParseFloat32("0." + value) * 1e3; +}; +var parseOffsetToMilliseconds = (value) => { + const directionStr = value[0]; + let direction = 1; + if (directionStr == "+") { + direction = 1; + } else if (directionStr == "-") { + direction = -1; + } else { + throw new TypeError(`Offset direction, ${directionStr}, must be "+" or "-"`); + } + const hour = Number(value.substring(1, 3)); + const minute = Number(value.substring(4, 6)); + return direction * (hour * 60 + minute) * 60 * 1e3; +}; +var stripLeadingZeroes = (value) => { + let idx = 0; + while (idx < value.length - 1 && value.charAt(idx) === "0") { + idx++; + } + if (idx === 0) { + return value; + } + return value.slice(idx); +}; + +// src/submodules/serde/lazy-json.ts +var LazyJsonString = function LazyJsonString2(val) { + const str = Object.assign(new String(val), { + deserializeJSON() { + return JSON.parse(String(val)); + }, + toString() { + return String(val); + }, + toJSON() { + return String(val); + } + }); + return str; +}; +LazyJsonString.from = (object) => { + if (object && typeof object === "object" && (object instanceof LazyJsonString || "deserializeJSON" in object)) { + return object; + } else if (typeof object === "string" || Object.getPrototypeOf(object) === String.prototype) { + return LazyJsonString(String(object)); + } + return LazyJsonString(JSON.stringify(object)); +}; +LazyJsonString.fromObject = LazyJsonString.from; + +// src/submodules/serde/quote-header.ts +function quoteHeader(part) { + if (part.includes(",") || part.includes('"')) { + part = `"${part.replace(/"/g, '\\"')}"`; + } + return part; +} + +// src/submodules/serde/split-every.ts +function splitEvery(value, delimiter, numDelimiters) { + if (numDelimiters <= 0 || !Number.isInteger(numDelimiters)) { + throw new Error("Invalid number of delimiters (" + numDelimiters + ") for splitEvery."); + } + const segments = value.split(delimiter); + if (numDelimiters === 1) { + return segments; + } + const compoundSegments = []; + let currentSegment = ""; + for (let i = 0; i < segments.length; i++) { + if (currentSegment === "") { + currentSegment = segments[i]; + } else { + currentSegment += delimiter + segments[i]; + } + if ((i + 1) % numDelimiters === 0) { + compoundSegments.push(currentSegment); + currentSegment = ""; + } + } + if (currentSegment !== "") { + compoundSegments.push(currentSegment); + } + return compoundSegments; +} + +// src/submodules/serde/split-header.ts +var splitHeader = (value) => { + const z = value.length; + const values = []; + let withinQuotes = false; + let prevChar = void 0; + let anchor = 0; + for (let i = 0; i < z; ++i) { + const char = value[i]; + switch (char) { + case `"`: + if (prevChar !== "\\") { + withinQuotes = !withinQuotes; + } + break; + case ",": + if (!withinQuotes) { + values.push(value.slice(anchor, i)); + anchor = i + 1; + } + break; + default: + } + prevChar = char; + } + values.push(value.slice(anchor)); + return values.map((v) => { + v = v.trim(); + const z2 = v.length; + if (z2 < 2) { + return v; + } + if (v[0] === `"` && v[z2 - 1] === `"`) { + v = v.slice(1, z2 - 1); + } + return v.replace(/\\"/g, '"'); + }); +}; + +// src/submodules/serde/value/NumericValue.ts +var NumericValue = class _NumericValue { + constructor(string, type) { + this.string = string; + this.type = type; + let dot = 0; + for (let i = 0; i < string.length; ++i) { + const char = string.charCodeAt(i); + if (i === 0 && char === 45) { + continue; + } + if (char === 46) { + if (dot) { + throw new Error("@smithy/core/serde - NumericValue must contain at most one decimal point."); + } + dot = 1; + continue; + } + if (char < 48 || char > 57) { + throw new Error( + `@smithy/core/serde - NumericValue must only contain [0-9], at most one decimal point ".", and an optional negation prefix "-".` + ); + } + } + } + toString() { + return this.string; + } + static [Symbol.hasInstance](object) { + if (!object || typeof object !== "object") { + return false; + } + const _nv = object; + const prototypeMatch = _NumericValue.prototype.isPrototypeOf(object.constructor?.prototype); + if (prototypeMatch) { + return prototypeMatch; + } + if (typeof _nv.string === "string" && typeof _nv.type === "string" && _nv.constructor?.name === "NumericValue") { + return true; + } + return prototypeMatch; + } +}; +function nv(input) { + return new NumericValue(String(input), "bigDecimal"); +} +// Annotate the CommonJS export names for ESM import in node: +0 && (0); + + +/***/ }), + +/***/ 40566: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + DEFAULT_MAX_RETRIES: () => DEFAULT_MAX_RETRIES, + DEFAULT_TIMEOUT: () => DEFAULT_TIMEOUT, + ENV_CMDS_AUTH_TOKEN: () => ENV_CMDS_AUTH_TOKEN, + ENV_CMDS_FULL_URI: () => ENV_CMDS_FULL_URI, + ENV_CMDS_RELATIVE_URI: () => ENV_CMDS_RELATIVE_URI, + Endpoint: () => Endpoint, + fromContainerMetadata: () => fromContainerMetadata, + fromInstanceMetadata: () => fromInstanceMetadata, + getInstanceMetadataEndpoint: () => getInstanceMetadataEndpoint, + httpRequest: () => httpRequest, + providerConfigFromInit: () => providerConfigFromInit +}); +module.exports = __toCommonJS(src_exports); + +// src/fromContainerMetadata.ts + +var import_url = __nccwpck_require__(87016); + +// src/remoteProvider/httpRequest.ts +var import_property_provider = __nccwpck_require__(71238); +var import_buffer = __nccwpck_require__(20181); +var import_http = __nccwpck_require__(58611); +function httpRequest(options) { + return new Promise((resolve, reject) => { + const req = (0, import_http.request)({ + method: "GET", + ...options, + // Node.js http module doesn't accept hostname with square brackets + // Refs: https://github.com/nodejs/node/issues/39738 + hostname: options.hostname?.replace(/^\[(.+)\]$/, "$1") + }); + req.on("error", (err) => { + reject(Object.assign(new import_property_provider.ProviderError("Unable to connect to instance metadata service"), err)); + req.destroy(); + }); + req.on("timeout", () => { + reject(new import_property_provider.ProviderError("TimeoutError from instance metadata service")); + req.destroy(); + }); + req.on("response", (res) => { + const { statusCode = 400 } = res; + if (statusCode < 200 || 300 <= statusCode) { + reject( + Object.assign(new import_property_provider.ProviderError("Error response received from instance metadata service"), { statusCode }) + ); + req.destroy(); + } + const chunks = []; + res.on("data", (chunk) => { + chunks.push(chunk); + }); + res.on("end", () => { + resolve(import_buffer.Buffer.concat(chunks)); + req.destroy(); + }); + }); + req.end(); + }); +} +__name(httpRequest, "httpRequest"); + +// src/remoteProvider/ImdsCredentials.ts +var isImdsCredentials = /* @__PURE__ */ __name((arg) => Boolean(arg) && typeof arg === "object" && typeof arg.AccessKeyId === "string" && typeof arg.SecretAccessKey === "string" && typeof arg.Token === "string" && typeof arg.Expiration === "string", "isImdsCredentials"); +var fromImdsCredentials = /* @__PURE__ */ __name((creds) => ({ + accessKeyId: creds.AccessKeyId, + secretAccessKey: creds.SecretAccessKey, + sessionToken: creds.Token, + expiration: new Date(creds.Expiration), + ...creds.AccountId && { accountId: creds.AccountId } +}), "fromImdsCredentials"); + +// src/remoteProvider/RemoteProviderInit.ts +var DEFAULT_TIMEOUT = 1e3; +var DEFAULT_MAX_RETRIES = 0; +var providerConfigFromInit = /* @__PURE__ */ __name(({ + maxRetries = DEFAULT_MAX_RETRIES, + timeout = DEFAULT_TIMEOUT +}) => ({ maxRetries, timeout }), "providerConfigFromInit"); + +// src/remoteProvider/retry.ts +var retry = /* @__PURE__ */ __name((toRetry, maxRetries) => { + let promise = toRetry(); + for (let i = 0; i < maxRetries; i++) { + promise = promise.catch(toRetry); + } + return promise; +}, "retry"); + +// src/fromContainerMetadata.ts +var ENV_CMDS_FULL_URI = "AWS_CONTAINER_CREDENTIALS_FULL_URI"; +var ENV_CMDS_RELATIVE_URI = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"; +var ENV_CMDS_AUTH_TOKEN = "AWS_CONTAINER_AUTHORIZATION_TOKEN"; +var fromContainerMetadata = /* @__PURE__ */ __name((init = {}) => { + const { timeout, maxRetries } = providerConfigFromInit(init); + return () => retry(async () => { + const requestOptions = await getCmdsUri({ logger: init.logger }); + const credsResponse = JSON.parse(await requestFromEcsImds(timeout, requestOptions)); + if (!isImdsCredentials(credsResponse)) { + throw new import_property_provider.CredentialsProviderError("Invalid response received from instance metadata service.", { + logger: init.logger + }); + } + return fromImdsCredentials(credsResponse); + }, maxRetries); +}, "fromContainerMetadata"); +var requestFromEcsImds = /* @__PURE__ */ __name(async (timeout, options) => { + if (process.env[ENV_CMDS_AUTH_TOKEN]) { + options.headers = { + ...options.headers, + Authorization: process.env[ENV_CMDS_AUTH_TOKEN] + }; + } + const buffer = await httpRequest({ + ...options, + timeout + }); + return buffer.toString(); +}, "requestFromEcsImds"); +var CMDS_IP = "169.254.170.2"; +var GREENGRASS_HOSTS = { + localhost: true, + "127.0.0.1": true +}; +var GREENGRASS_PROTOCOLS = { + "http:": true, + "https:": true +}; +var getCmdsUri = /* @__PURE__ */ __name(async ({ logger }) => { + if (process.env[ENV_CMDS_RELATIVE_URI]) { + return { + hostname: CMDS_IP, + path: process.env[ENV_CMDS_RELATIVE_URI] + }; + } + if (process.env[ENV_CMDS_FULL_URI]) { + const parsed = (0, import_url.parse)(process.env[ENV_CMDS_FULL_URI]); + if (!parsed.hostname || !(parsed.hostname in GREENGRASS_HOSTS)) { + throw new import_property_provider.CredentialsProviderError(`${parsed.hostname} is not a valid container metadata service hostname`, { + tryNextLink: false, + logger + }); + } + if (!parsed.protocol || !(parsed.protocol in GREENGRASS_PROTOCOLS)) { + throw new import_property_provider.CredentialsProviderError(`${parsed.protocol} is not a valid container metadata service protocol`, { + tryNextLink: false, + logger + }); + } + return { + ...parsed, + port: parsed.port ? parseInt(parsed.port, 10) : void 0 + }; + } + throw new import_property_provider.CredentialsProviderError( + `The container metadata credential provider cannot be used unless the ${ENV_CMDS_RELATIVE_URI} or ${ENV_CMDS_FULL_URI} environment variable is set`, + { + tryNextLink: false, + logger + } + ); +}, "getCmdsUri"); + +// src/fromInstanceMetadata.ts + + + +// src/error/InstanceMetadataV1FallbackError.ts + +var InstanceMetadataV1FallbackError = class _InstanceMetadataV1FallbackError extends import_property_provider.CredentialsProviderError { + constructor(message, tryNextLink = true) { + super(message, tryNextLink); + this.tryNextLink = tryNextLink; + this.name = "InstanceMetadataV1FallbackError"; + Object.setPrototypeOf(this, _InstanceMetadataV1FallbackError.prototype); + } + static { + __name(this, "InstanceMetadataV1FallbackError"); + } +}; + +// src/utils/getInstanceMetadataEndpoint.ts +var import_node_config_provider = __nccwpck_require__(55704); +var import_url_parser = __nccwpck_require__(14494); + +// src/config/Endpoint.ts +var Endpoint = /* @__PURE__ */ ((Endpoint2) => { + Endpoint2["IPv4"] = "http://169.254.169.254"; + Endpoint2["IPv6"] = "http://[fd00:ec2::254]"; + return Endpoint2; +})(Endpoint || {}); + +// src/config/EndpointConfigOptions.ts +var ENV_ENDPOINT_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT"; +var CONFIG_ENDPOINT_NAME = "ec2_metadata_service_endpoint"; +var ENDPOINT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[ENV_ENDPOINT_NAME], + configFileSelector: (profile) => profile[CONFIG_ENDPOINT_NAME], + default: void 0 +}; + +// src/config/EndpointMode.ts +var EndpointMode = /* @__PURE__ */ ((EndpointMode2) => { + EndpointMode2["IPv4"] = "IPv4"; + EndpointMode2["IPv6"] = "IPv6"; + return EndpointMode2; +})(EndpointMode || {}); + +// src/config/EndpointModeConfigOptions.ts +var ENV_ENDPOINT_MODE_NAME = "AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE"; +var CONFIG_ENDPOINT_MODE_NAME = "ec2_metadata_service_endpoint_mode"; +var ENDPOINT_MODE_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[ENV_ENDPOINT_MODE_NAME], + configFileSelector: (profile) => profile[CONFIG_ENDPOINT_MODE_NAME], + default: "IPv4" /* IPv4 */ +}; + +// src/utils/getInstanceMetadataEndpoint.ts +var getInstanceMetadataEndpoint = /* @__PURE__ */ __name(async () => (0, import_url_parser.parseUrl)(await getFromEndpointConfig() || await getFromEndpointModeConfig()), "getInstanceMetadataEndpoint"); +var getFromEndpointConfig = /* @__PURE__ */ __name(async () => (0, import_node_config_provider.loadConfig)(ENDPOINT_CONFIG_OPTIONS)(), "getFromEndpointConfig"); +var getFromEndpointModeConfig = /* @__PURE__ */ __name(async () => { + const endpointMode = await (0, import_node_config_provider.loadConfig)(ENDPOINT_MODE_CONFIG_OPTIONS)(); + switch (endpointMode) { + case "IPv4" /* IPv4 */: + return "http://169.254.169.254" /* IPv4 */; + case "IPv6" /* IPv6 */: + return "http://[fd00:ec2::254]" /* IPv6 */; + default: + throw new Error(`Unsupported endpoint mode: ${endpointMode}. Select from ${Object.values(EndpointMode)}`); + } +}, "getFromEndpointModeConfig"); + +// src/utils/getExtendedInstanceMetadataCredentials.ts +var STATIC_STABILITY_REFRESH_INTERVAL_SECONDS = 5 * 60; +var STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS = 5 * 60; +var STATIC_STABILITY_DOC_URL = "https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html"; +var getExtendedInstanceMetadataCredentials = /* @__PURE__ */ __name((credentials, logger) => { + const refreshInterval = STATIC_STABILITY_REFRESH_INTERVAL_SECONDS + Math.floor(Math.random() * STATIC_STABILITY_REFRESH_INTERVAL_JITTER_WINDOW_SECONDS); + const newExpiration = new Date(Date.now() + refreshInterval * 1e3); + logger.warn( + `Attempting credential expiration extension due to a credential service availability issue. A refresh of these credentials will be attempted after ${new Date(newExpiration)}. +For more information, please visit: ` + STATIC_STABILITY_DOC_URL + ); + const originalExpiration = credentials.originalExpiration ?? credentials.expiration; + return { + ...credentials, + ...originalExpiration ? { originalExpiration } : {}, + expiration: newExpiration + }; +}, "getExtendedInstanceMetadataCredentials"); + +// src/utils/staticStabilityProvider.ts +var staticStabilityProvider = /* @__PURE__ */ __name((provider, options = {}) => { + const logger = options?.logger || console; + let pastCredentials; + return async () => { + let credentials; + try { + credentials = await provider(); + if (credentials.expiration && credentials.expiration.getTime() < Date.now()) { + credentials = getExtendedInstanceMetadataCredentials(credentials, logger); + } + } catch (e) { + if (pastCredentials) { + logger.warn("Credential renew failed: ", e); + credentials = getExtendedInstanceMetadataCredentials(pastCredentials, logger); + } else { + throw e; + } + } + pastCredentials = credentials; + return credentials; + }; +}, "staticStabilityProvider"); + +// src/fromInstanceMetadata.ts +var IMDS_PATH = "/latest/meta-data/iam/security-credentials/"; +var IMDS_TOKEN_PATH = "/latest/api/token"; +var AWS_EC2_METADATA_V1_DISABLED = "AWS_EC2_METADATA_V1_DISABLED"; +var PROFILE_AWS_EC2_METADATA_V1_DISABLED = "ec2_metadata_v1_disabled"; +var X_AWS_EC2_METADATA_TOKEN = "x-aws-ec2-metadata-token"; +var fromInstanceMetadata = /* @__PURE__ */ __name((init = {}) => staticStabilityProvider(getInstanceMetadataProvider(init), { logger: init.logger }), "fromInstanceMetadata"); +var getInstanceMetadataProvider = /* @__PURE__ */ __name((init = {}) => { + let disableFetchToken = false; + const { logger, profile } = init; + const { timeout, maxRetries } = providerConfigFromInit(init); + const getCredentials = /* @__PURE__ */ __name(async (maxRetries2, options) => { + const isImdsV1Fallback = disableFetchToken || options.headers?.[X_AWS_EC2_METADATA_TOKEN] == null; + if (isImdsV1Fallback) { + let fallbackBlockedFromProfile = false; + let fallbackBlockedFromProcessEnv = false; + const configValue = await (0, import_node_config_provider.loadConfig)( + { + environmentVariableSelector: (env) => { + const envValue = env[AWS_EC2_METADATA_V1_DISABLED]; + fallbackBlockedFromProcessEnv = !!envValue && envValue !== "false"; + if (envValue === void 0) { + throw new import_property_provider.CredentialsProviderError( + `${AWS_EC2_METADATA_V1_DISABLED} not set in env, checking config file next.`, + { logger: init.logger } + ); + } + return fallbackBlockedFromProcessEnv; + }, + configFileSelector: (profile2) => { + const profileValue = profile2[PROFILE_AWS_EC2_METADATA_V1_DISABLED]; + fallbackBlockedFromProfile = !!profileValue && profileValue !== "false"; + return fallbackBlockedFromProfile; + }, + default: false + }, + { + profile + } + )(); + if (init.ec2MetadataV1Disabled || configValue) { + const causes = []; + if (init.ec2MetadataV1Disabled) + causes.push("credential provider initialization (runtime option ec2MetadataV1Disabled)"); + if (fallbackBlockedFromProfile) + causes.push(`config file profile (${PROFILE_AWS_EC2_METADATA_V1_DISABLED})`); + if (fallbackBlockedFromProcessEnv) + causes.push(`process environment variable (${AWS_EC2_METADATA_V1_DISABLED})`); + throw new InstanceMetadataV1FallbackError( + `AWS EC2 Metadata v1 fallback has been blocked by AWS SDK configuration in the following: [${causes.join( + ", " + )}].` + ); + } + } + const imdsProfile = (await retry(async () => { + let profile2; + try { + profile2 = await getProfile(options); + } catch (err) { + if (err.statusCode === 401) { + disableFetchToken = false; + } + throw err; + } + return profile2; + }, maxRetries2)).trim(); + return retry(async () => { + let creds; + try { + creds = await getCredentialsFromProfile(imdsProfile, options, init); + } catch (err) { + if (err.statusCode === 401) { + disableFetchToken = false; + } + throw err; + } + return creds; + }, maxRetries2); + }, "getCredentials"); + return async () => { + const endpoint = await getInstanceMetadataEndpoint(); + if (disableFetchToken) { + logger?.debug("AWS SDK Instance Metadata", "using v1 fallback (no token fetch)"); + return getCredentials(maxRetries, { ...endpoint, timeout }); + } else { + let token; + try { + token = (await getMetadataToken({ ...endpoint, timeout })).toString(); + } catch (error) { + if (error?.statusCode === 400) { + throw Object.assign(error, { + message: "EC2 Metadata token request returned error" + }); + } else if (error.message === "TimeoutError" || [403, 404, 405].includes(error.statusCode)) { + disableFetchToken = true; + } + logger?.debug("AWS SDK Instance Metadata", "using v1 fallback (initial)"); + return getCredentials(maxRetries, { ...endpoint, timeout }); + } + return getCredentials(maxRetries, { + ...endpoint, + headers: { + [X_AWS_EC2_METADATA_TOKEN]: token + }, + timeout + }); + } + }; +}, "getInstanceMetadataProvider"); +var getMetadataToken = /* @__PURE__ */ __name(async (options) => httpRequest({ + ...options, + path: IMDS_TOKEN_PATH, + method: "PUT", + headers: { + "x-aws-ec2-metadata-token-ttl-seconds": "21600" + } +}), "getMetadataToken"); +var getProfile = /* @__PURE__ */ __name(async (options) => (await httpRequest({ ...options, path: IMDS_PATH })).toString(), "getProfile"); +var getCredentialsFromProfile = /* @__PURE__ */ __name(async (profile, options, init) => { + const credentialsResponse = JSON.parse( + (await httpRequest({ + ...options, + path: IMDS_PATH + profile + })).toString() + ); + if (!isImdsCredentials(credentialsResponse)) { + throw new import_property_provider.CredentialsProviderError("Invalid response received from instance metadata service.", { + logger: init.logger + }); + } + return fromImdsCredentials(credentialsResponse); +}, "getCredentialsFromProfile"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 37788: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EventStreamCodec: () => EventStreamCodec, + HeaderMarshaller: () => HeaderMarshaller, + Int64: () => Int64, + MessageDecoderStream: () => MessageDecoderStream, + MessageEncoderStream: () => MessageEncoderStream, + SmithyMessageDecoderStream: () => SmithyMessageDecoderStream, + SmithyMessageEncoderStream: () => SmithyMessageEncoderStream +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamCodec.ts +var import_crc322 = __nccwpck_require__(62110); + +// src/HeaderMarshaller.ts + + +// src/Int64.ts +var import_util_hex_encoding = __nccwpck_require__(96435); +var Int64 = class _Int64 { + constructor(bytes) { + this.bytes = bytes; + if (bytes.byteLength !== 8) { + throw new Error("Int64 buffers must be exactly 8 bytes"); + } + } + static { + __name(this, "Int64"); + } + static fromNumber(number) { + if (number > 9223372036854776e3 || number < -9223372036854776e3) { + throw new Error(`${number} is too large (or, if negative, too small) to represent as an Int64`); + } + const bytes = new Uint8Array(8); + for (let i = 7, remaining = Math.abs(Math.round(number)); i > -1 && remaining > 0; i--, remaining /= 256) { + bytes[i] = remaining; + } + if (number < 0) { + negate(bytes); + } + return new _Int64(bytes); + } + /** + * Called implicitly by infix arithmetic operators. + */ + valueOf() { + const bytes = this.bytes.slice(0); + const negative = bytes[0] & 128; + if (negative) { + negate(bytes); + } + return parseInt((0, import_util_hex_encoding.toHex)(bytes), 16) * (negative ? -1 : 1); + } + toString() { + return String(this.valueOf()); + } +}; +function negate(bytes) { + for (let i = 0; i < 8; i++) { + bytes[i] ^= 255; + } + for (let i = 7; i > -1; i--) { + bytes[i]++; + if (bytes[i] !== 0) + break; + } +} +__name(negate, "negate"); + +// src/HeaderMarshaller.ts +var HeaderMarshaller = class { + constructor(toUtf8, fromUtf8) { + this.toUtf8 = toUtf8; + this.fromUtf8 = fromUtf8; + } + static { + __name(this, "HeaderMarshaller"); + } + format(headers) { + const chunks = []; + for (const headerName of Object.keys(headers)) { + const bytes = this.fromUtf8(headerName); + chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName])); + } + const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0)); + let position = 0; + for (const chunk of chunks) { + out.set(chunk, position); + position += chunk.byteLength; + } + return out; + } + formatHeaderValue(header) { + switch (header.type) { + case "boolean": + return Uint8Array.from([header.value ? 0 /* boolTrue */ : 1 /* boolFalse */]); + case "byte": + return Uint8Array.from([2 /* byte */, header.value]); + case "short": + const shortView = new DataView(new ArrayBuffer(3)); + shortView.setUint8(0, 3 /* short */); + shortView.setInt16(1, header.value, false); + return new Uint8Array(shortView.buffer); + case "integer": + const intView = new DataView(new ArrayBuffer(5)); + intView.setUint8(0, 4 /* integer */); + intView.setInt32(1, header.value, false); + return new Uint8Array(intView.buffer); + case "long": + const longBytes = new Uint8Array(9); + longBytes[0] = 5 /* long */; + longBytes.set(header.value.bytes, 1); + return longBytes; + case "binary": + const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength)); + binView.setUint8(0, 6 /* byteArray */); + binView.setUint16(1, header.value.byteLength, false); + const binBytes = new Uint8Array(binView.buffer); + binBytes.set(header.value, 3); + return binBytes; + case "string": + const utf8Bytes = this.fromUtf8(header.value); + const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength)); + strView.setUint8(0, 7 /* string */); + strView.setUint16(1, utf8Bytes.byteLength, false); + const strBytes = new Uint8Array(strView.buffer); + strBytes.set(utf8Bytes, 3); + return strBytes; + case "timestamp": + const tsBytes = new Uint8Array(9); + tsBytes[0] = 8 /* timestamp */; + tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1); + return tsBytes; + case "uuid": + if (!UUID_PATTERN.test(header.value)) { + throw new Error(`Invalid UUID received: ${header.value}`); + } + const uuidBytes = new Uint8Array(17); + uuidBytes[0] = 9 /* uuid */; + uuidBytes.set((0, import_util_hex_encoding.fromHex)(header.value.replace(/\-/g, "")), 1); + return uuidBytes; + } + } + parse(headers) { + const out = {}; + let position = 0; + while (position < headers.byteLength) { + const nameLength = headers.getUint8(position++); + const name = this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, nameLength)); + position += nameLength; + switch (headers.getUint8(position++)) { + case 0 /* boolTrue */: + out[name] = { + type: BOOLEAN_TAG, + value: true + }; + break; + case 1 /* boolFalse */: + out[name] = { + type: BOOLEAN_TAG, + value: false + }; + break; + case 2 /* byte */: + out[name] = { + type: BYTE_TAG, + value: headers.getInt8(position++) + }; + break; + case 3 /* short */: + out[name] = { + type: SHORT_TAG, + value: headers.getInt16(position, false) + }; + position += 2; + break; + case 4 /* integer */: + out[name] = { + type: INT_TAG, + value: headers.getInt32(position, false) + }; + position += 4; + break; + case 5 /* long */: + out[name] = { + type: LONG_TAG, + value: new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)) + }; + position += 8; + break; + case 6 /* byteArray */: + const binaryLength = headers.getUint16(position, false); + position += 2; + out[name] = { + type: BINARY_TAG, + value: new Uint8Array(headers.buffer, headers.byteOffset + position, binaryLength) + }; + position += binaryLength; + break; + case 7 /* string */: + const stringLength = headers.getUint16(position, false); + position += 2; + out[name] = { + type: STRING_TAG, + value: this.toUtf8(new Uint8Array(headers.buffer, headers.byteOffset + position, stringLength)) + }; + position += stringLength; + break; + case 8 /* timestamp */: + out[name] = { + type: TIMESTAMP_TAG, + value: new Date(new Int64(new Uint8Array(headers.buffer, headers.byteOffset + position, 8)).valueOf()) + }; + position += 8; + break; + case 9 /* uuid */: + const uuidBytes = new Uint8Array(headers.buffer, headers.byteOffset + position, 16); + position += 16; + out[name] = { + type: UUID_TAG, + value: `${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(0, 4))}-${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(4, 6))}-${(0, import_util_hex_encoding.toHex)( + uuidBytes.subarray(6, 8) + )}-${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(8, 10))}-${(0, import_util_hex_encoding.toHex)(uuidBytes.subarray(10))}` + }; + break; + default: + throw new Error(`Unrecognized header type tag`); + } + } + return out; + } +}; +var BOOLEAN_TAG = "boolean"; +var BYTE_TAG = "byte"; +var SHORT_TAG = "short"; +var INT_TAG = "integer"; +var LONG_TAG = "long"; +var BINARY_TAG = "binary"; +var STRING_TAG = "string"; +var TIMESTAMP_TAG = "timestamp"; +var UUID_TAG = "uuid"; +var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/; + +// src/splitMessage.ts +var import_crc32 = __nccwpck_require__(62110); +var PRELUDE_MEMBER_LENGTH = 4; +var PRELUDE_LENGTH = PRELUDE_MEMBER_LENGTH * 2; +var CHECKSUM_LENGTH = 4; +var MINIMUM_MESSAGE_LENGTH = PRELUDE_LENGTH + CHECKSUM_LENGTH * 2; +function splitMessage({ byteLength, byteOffset, buffer }) { + if (byteLength < MINIMUM_MESSAGE_LENGTH) { + throw new Error("Provided message too short to accommodate event stream message overhead"); + } + const view = new DataView(buffer, byteOffset, byteLength); + const messageLength = view.getUint32(0, false); + if (byteLength !== messageLength) { + throw new Error("Reported message length does not match received message length"); + } + const headerLength = view.getUint32(PRELUDE_MEMBER_LENGTH, false); + const expectedPreludeChecksum = view.getUint32(PRELUDE_LENGTH, false); + const expectedMessageChecksum = view.getUint32(byteLength - CHECKSUM_LENGTH, false); + const checksummer = new import_crc32.Crc32().update(new Uint8Array(buffer, byteOffset, PRELUDE_LENGTH)); + if (expectedPreludeChecksum !== checksummer.digest()) { + throw new Error( + `The prelude checksum specified in the message (${expectedPreludeChecksum}) does not match the calculated CRC32 checksum (${checksummer.digest()})` + ); + } + checksummer.update( + new Uint8Array(buffer, byteOffset + PRELUDE_LENGTH, byteLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH)) + ); + if (expectedMessageChecksum !== checksummer.digest()) { + throw new Error( + `The message checksum (${checksummer.digest()}) did not match the expected value of ${expectedMessageChecksum}` + ); + } + return { + headers: new DataView(buffer, byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH, headerLength), + body: new Uint8Array( + buffer, + byteOffset + PRELUDE_LENGTH + CHECKSUM_LENGTH + headerLength, + messageLength - headerLength - (PRELUDE_LENGTH + CHECKSUM_LENGTH + CHECKSUM_LENGTH) + ) + }; +} +__name(splitMessage, "splitMessage"); + +// src/EventStreamCodec.ts +var EventStreamCodec = class { + static { + __name(this, "EventStreamCodec"); + } + constructor(toUtf8, fromUtf8) { + this.headerMarshaller = new HeaderMarshaller(toUtf8, fromUtf8); + this.messageBuffer = []; + this.isEndOfStream = false; + } + feed(message) { + this.messageBuffer.push(this.decode(message)); + } + endOfStream() { + this.isEndOfStream = true; + } + getMessage() { + const message = this.messageBuffer.pop(); + const isEndOfStream = this.isEndOfStream; + return { + getMessage() { + return message; + }, + isEndOfStream() { + return isEndOfStream; + } + }; + } + getAvailableMessages() { + const messages = this.messageBuffer; + this.messageBuffer = []; + const isEndOfStream = this.isEndOfStream; + return { + getMessages() { + return messages; + }, + isEndOfStream() { + return isEndOfStream; + } + }; + } + /** + * Convert a structured JavaScript object with tagged headers into a binary + * event stream message. + */ + encode({ headers: rawHeaders, body }) { + const headers = this.headerMarshaller.format(rawHeaders); + const length = headers.byteLength + body.byteLength + 16; + const out = new Uint8Array(length); + const view = new DataView(out.buffer, out.byteOffset, out.byteLength); + const checksum = new import_crc322.Crc32(); + view.setUint32(0, length, false); + view.setUint32(4, headers.byteLength, false); + view.setUint32(8, checksum.update(out.subarray(0, 8)).digest(), false); + out.set(headers, 12); + out.set(body, headers.byteLength + 12); + view.setUint32(length - 4, checksum.update(out.subarray(8, length - 4)).digest(), false); + return out; + } + /** + * Convert a binary event stream message into a JavaScript object with an + * opaque, binary body and tagged, parsed headers. + */ + decode(message) { + const { headers, body } = splitMessage(message); + return { headers: this.headerMarshaller.parse(headers), body }; + } + /** + * Convert a structured JavaScript object with tagged headers into a binary + * event stream message header. + */ + formatHeaders(rawHeaders) { + return this.headerMarshaller.format(rawHeaders); + } +}; + +// src/MessageDecoderStream.ts +var MessageDecoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "MessageDecoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const bytes of this.options.inputStream) { + const decoded = this.options.decoder.decode(bytes); + yield decoded; + } + } +}; + +// src/MessageEncoderStream.ts +var MessageEncoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "MessageEncoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const msg of this.options.messageStream) { + const encoded = this.options.encoder.encode(msg); + yield encoded; + } + if (this.options.includeEndFrame) { + yield new Uint8Array(0); + } + } +}; + +// src/SmithyMessageDecoderStream.ts +var SmithyMessageDecoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "SmithyMessageDecoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const message of this.options.messageStream) { + const deserialized = await this.options.deserializer(message); + if (deserialized === void 0) + continue; + yield deserialized; + } + } +}; + +// src/SmithyMessageEncoderStream.ts +var SmithyMessageEncoderStream = class { + constructor(options) { + this.options = options; + } + static { + __name(this, "SmithyMessageEncoderStream"); + } + [Symbol.asyncIterator]() { + return this.asyncIterator(); + } + async *asyncIterator() { + for await (const chunk of this.options.inputStream) { + const payloadBuf = this.options.serializer(chunk); + yield payloadBuf; + } + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 86895: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + resolveEventStreamSerdeConfig: () => resolveEventStreamSerdeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamSerdeConfig.ts +var resolveEventStreamSerdeConfig = /* @__PURE__ */ __name((input) => Object.assign(input, { + eventStreamMarshaller: input.eventStreamSerdeProvider(input) +}), "resolveEventStreamSerdeConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 69770: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EventStreamMarshaller: () => EventStreamMarshaller, + eventStreamSerdeProvider: () => eventStreamSerdeProvider +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamMarshaller.ts +var import_eventstream_serde_universal = __nccwpck_require__(14221); +var import_stream = __nccwpck_require__(2203); + +// src/utils.ts +async function* readabletoIterable(readStream) { + let streamEnded = false; + let generationEnded = false; + const records = new Array(); + readStream.on("error", (err) => { + if (!streamEnded) { + streamEnded = true; + } + if (err) { + throw err; + } + }); + readStream.on("data", (data) => { + records.push(data); + }); + readStream.on("end", () => { + streamEnded = true; + }); + while (!generationEnded) { + const value = await new Promise((resolve) => setTimeout(() => resolve(records.shift()), 0)); + if (value) { + yield value; + } + generationEnded = streamEnded && records.length === 0; + } +} +__name(readabletoIterable, "readabletoIterable"); + +// src/EventStreamMarshaller.ts +var EventStreamMarshaller = class { + static { + __name(this, "EventStreamMarshaller"); + } + constructor({ utf8Encoder, utf8Decoder }) { + this.universalMarshaller = new import_eventstream_serde_universal.EventStreamMarshaller({ + utf8Decoder, + utf8Encoder + }); + } + deserialize(body, deserializer) { + const bodyIterable = typeof body[Symbol.asyncIterator] === "function" ? body : readabletoIterable(body); + return this.universalMarshaller.deserialize(bodyIterable, deserializer); + } + serialize(input, serializer) { + return import_stream.Readable.from(this.universalMarshaller.serialize(input, serializer)); + } +}; + +// src/provider.ts +var eventStreamSerdeProvider = /* @__PURE__ */ __name((options) => new EventStreamMarshaller(options), "eventStreamSerdeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 14221: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EventStreamMarshaller: () => EventStreamMarshaller, + eventStreamSerdeProvider: () => eventStreamSerdeProvider +}); +module.exports = __toCommonJS(src_exports); + +// src/EventStreamMarshaller.ts +var import_eventstream_codec = __nccwpck_require__(37788); + +// src/getChunkedStream.ts +function getChunkedStream(source) { + let currentMessageTotalLength = 0; + let currentMessagePendingLength = 0; + let currentMessage = null; + let messageLengthBuffer = null; + const allocateMessage = /* @__PURE__ */ __name((size) => { + if (typeof size !== "number") { + throw new Error("Attempted to allocate an event message where size was not a number: " + size); + } + currentMessageTotalLength = size; + currentMessagePendingLength = 4; + currentMessage = new Uint8Array(size); + const currentMessageView = new DataView(currentMessage.buffer); + currentMessageView.setUint32(0, size, false); + }, "allocateMessage"); + const iterator = /* @__PURE__ */ __name(async function* () { + const sourceIterator = source[Symbol.asyncIterator](); + while (true) { + const { value, done } = await sourceIterator.next(); + if (done) { + if (!currentMessageTotalLength) { + return; + } else if (currentMessageTotalLength === currentMessagePendingLength) { + yield currentMessage; + } else { + throw new Error("Truncated event message received."); + } + return; + } + const chunkLength = value.length; + let currentOffset = 0; + while (currentOffset < chunkLength) { + if (!currentMessage) { + const bytesRemaining = chunkLength - currentOffset; + if (!messageLengthBuffer) { + messageLengthBuffer = new Uint8Array(4); + } + const numBytesForTotal = Math.min( + 4 - currentMessagePendingLength, + // remaining bytes to fill the messageLengthBuffer + bytesRemaining + // bytes left in chunk + ); + messageLengthBuffer.set( + // @ts-ignore error TS2532: Object is possibly 'undefined' for value + value.slice(currentOffset, currentOffset + numBytesForTotal), + currentMessagePendingLength + ); + currentMessagePendingLength += numBytesForTotal; + currentOffset += numBytesForTotal; + if (currentMessagePendingLength < 4) { + break; + } + allocateMessage(new DataView(messageLengthBuffer.buffer).getUint32(0, false)); + messageLengthBuffer = null; + } + const numBytesToWrite = Math.min( + currentMessageTotalLength - currentMessagePendingLength, + // number of bytes left to complete message + chunkLength - currentOffset + // number of bytes left in the original chunk + ); + currentMessage.set( + // @ts-ignore error TS2532: Object is possibly 'undefined' for value + value.slice(currentOffset, currentOffset + numBytesToWrite), + currentMessagePendingLength + ); + currentMessagePendingLength += numBytesToWrite; + currentOffset += numBytesToWrite; + if (currentMessageTotalLength && currentMessageTotalLength === currentMessagePendingLength) { + yield currentMessage; + currentMessage = null; + currentMessageTotalLength = 0; + currentMessagePendingLength = 0; + } + } + } + }, "iterator"); + return { + [Symbol.asyncIterator]: iterator + }; +} +__name(getChunkedStream, "getChunkedStream"); + +// src/getUnmarshalledStream.ts +function getMessageUnmarshaller(deserializer, toUtf8) { + return async function(message) { + const { value: messageType } = message.headers[":message-type"]; + if (messageType === "error") { + const unmodeledError = new Error(message.headers[":error-message"].value || "UnknownError"); + unmodeledError.name = message.headers[":error-code"].value; + throw unmodeledError; + } else if (messageType === "exception") { + const code = message.headers[":exception-type"].value; + const exception = { [code]: message }; + const deserializedException = await deserializer(exception); + if (deserializedException.$unknown) { + const error = new Error(toUtf8(message.body)); + error.name = code; + throw error; + } + throw deserializedException[code]; + } else if (messageType === "event") { + const event = { + [message.headers[":event-type"].value]: message + }; + const deserialized = await deserializer(event); + if (deserialized.$unknown) + return; + return deserialized; + } else { + throw Error(`Unrecognizable event type: ${message.headers[":event-type"].value}`); + } + }; +} +__name(getMessageUnmarshaller, "getMessageUnmarshaller"); + +// src/EventStreamMarshaller.ts +var EventStreamMarshaller = class { + static { + __name(this, "EventStreamMarshaller"); + } + constructor({ utf8Encoder, utf8Decoder }) { + this.eventStreamCodec = new import_eventstream_codec.EventStreamCodec(utf8Encoder, utf8Decoder); + this.utfEncoder = utf8Encoder; + } + deserialize(body, deserializer) { + const inputStream = getChunkedStream(body); + return new import_eventstream_codec.SmithyMessageDecoderStream({ + messageStream: new import_eventstream_codec.MessageDecoderStream({ inputStream, decoder: this.eventStreamCodec }), + // @ts-expect-error Type 'T' is not assignable to type 'Record' + deserializer: getMessageUnmarshaller(deserializer, this.utfEncoder) + }); + } + serialize(inputStream, serializer) { + return new import_eventstream_codec.MessageEncoderStream({ + messageStream: new import_eventstream_codec.SmithyMessageEncoderStream({ inputStream, serializer }), + encoder: this.eventStreamCodec, + includeEndFrame: true + }); + } +}; + +// src/provider.ts +var eventStreamSerdeProvider = /* @__PURE__ */ __name((options) => new EventStreamMarshaller(options), "eventStreamSerdeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 47809: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + FetchHttpHandler: () => FetchHttpHandler, + keepAliveSupport: () => keepAliveSupport, + streamCollector: () => streamCollector +}); +module.exports = __toCommonJS(src_exports); + +// src/fetch-http-handler.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_querystring_builder = __nccwpck_require__(18256); + +// src/create-request.ts +function createRequest(url, requestOptions) { + return new Request(url, requestOptions); +} +__name(createRequest, "createRequest"); + +// src/request-timeout.ts +function requestTimeout(timeoutInMs = 0) { + return new Promise((resolve, reject) => { + if (timeoutInMs) { + setTimeout(() => { + const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`); + timeoutError.name = "TimeoutError"; + reject(timeoutError); + }, timeoutInMs); + } + }); +} +__name(requestTimeout, "requestTimeout"); + +// src/fetch-http-handler.ts +var keepAliveSupport = { + supported: void 0 +}; +var FetchHttpHandler = class _FetchHttpHandler { + static { + __name(this, "FetchHttpHandler"); + } + /** + * @returns the input if it is an HttpHandler of any class, + * or instantiates a new instance of this handler. + */ + static create(instanceOrOptions) { + if (typeof instanceOrOptions?.handle === "function") { + return instanceOrOptions; + } + return new _FetchHttpHandler(instanceOrOptions); + } + constructor(options) { + if (typeof options === "function") { + this.configProvider = options().then((opts) => opts || {}); + } else { + this.config = options ?? {}; + this.configProvider = Promise.resolve(this.config); + } + if (keepAliveSupport.supported === void 0) { + keepAliveSupport.supported = Boolean( + typeof Request !== "undefined" && "keepalive" in createRequest("https://[::1]") + ); + } + } + destroy() { + } + async handle(request, { abortSignal, requestTimeout: requestTimeout2 } = {}) { + if (!this.config) { + this.config = await this.configProvider; + } + const requestTimeoutInMs = requestTimeout2 ?? this.config.requestTimeout; + const keepAlive = this.config.keepAlive === true; + const credentials = this.config.credentials; + if (abortSignal?.aborted) { + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + return Promise.reject(abortError); + } + let path = request.path; + const queryString = (0, import_querystring_builder.buildQueryString)(request.query || {}); + if (queryString) { + path += `?${queryString}`; + } + if (request.fragment) { + path += `#${request.fragment}`; + } + let auth = ""; + if (request.username != null || request.password != null) { + const username = request.username ?? ""; + const password = request.password ?? ""; + auth = `${username}:${password}@`; + } + const { port, method } = request; + const url = `${request.protocol}//${auth}${request.hostname}${port ? `:${port}` : ""}${path}`; + const body = method === "GET" || method === "HEAD" ? void 0 : request.body; + const requestOptions = { + body, + headers: new Headers(request.headers), + method, + credentials + }; + if (this.config?.cache) { + requestOptions.cache = this.config.cache; + } + if (body) { + requestOptions.duplex = "half"; + } + if (typeof AbortController !== "undefined") { + requestOptions.signal = abortSignal; + } + if (keepAliveSupport.supported) { + requestOptions.keepalive = keepAlive; + } + if (typeof this.config.requestInit === "function") { + Object.assign(requestOptions, this.config.requestInit(request)); + } + let removeSignalEventListener = /* @__PURE__ */ __name(() => { + }, "removeSignalEventListener"); + const fetchRequest = createRequest(url, requestOptions); + const raceOfPromises = [ + fetch(fetchRequest).then((response) => { + const fetchHeaders = response.headers; + const transformedHeaders = {}; + for (const pair of fetchHeaders.entries()) { + transformedHeaders[pair[0]] = pair[1]; + } + const hasReadableStream = response.body != void 0; + if (!hasReadableStream) { + return response.blob().then((body2) => ({ + response: new import_protocol_http.HttpResponse({ + headers: transformedHeaders, + reason: response.statusText, + statusCode: response.status, + body: body2 + }) + })); + } + return { + response: new import_protocol_http.HttpResponse({ + headers: transformedHeaders, + reason: response.statusText, + statusCode: response.status, + body: response.body + }) + }; + }), + requestTimeout(requestTimeoutInMs) + ]; + if (abortSignal) { + raceOfPromises.push( + new Promise((resolve, reject) => { + const onAbort = /* @__PURE__ */ __name(() => { + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + }, "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + const signal = abortSignal; + signal.addEventListener("abort", onAbort, { once: true }); + removeSignalEventListener = /* @__PURE__ */ __name(() => signal.removeEventListener("abort", onAbort), "removeSignalEventListener"); + } else { + abortSignal.onabort = onAbort; + } + }) + ); + } + return Promise.race(raceOfPromises).finally(removeSignalEventListener); + } + updateHttpClientConfig(key, value) { + this.config = void 0; + this.configProvider = this.configProvider.then((config) => { + config[key] = value; + return config; + }); + } + httpHandlerConfigs() { + return this.config ?? {}; + } +}; + +// src/stream-collector.ts +var import_util_base64 = __nccwpck_require__(68385); +var streamCollector = /* @__PURE__ */ __name(async (stream) => { + if (typeof Blob === "function" && stream instanceof Blob || stream.constructor?.name === "Blob") { + if (Blob.prototype.arrayBuffer !== void 0) { + return new Uint8Array(await stream.arrayBuffer()); + } + return collectBlob(stream); + } + return collectStream(stream); +}, "streamCollector"); +async function collectBlob(blob) { + const base64 = await readToBase64(blob); + const arrayBuffer = (0, import_util_base64.fromBase64)(base64); + return new Uint8Array(arrayBuffer); +} +__name(collectBlob, "collectBlob"); +async function collectStream(stream) { + const chunks = []; + const reader = stream.getReader(); + let isDone = false; + let length = 0; + while (!isDone) { + const { done, value } = await reader.read(); + if (value) { + chunks.push(value); + length += value.length; + } + isDone = done; + } + const collected = new Uint8Array(length); + let offset = 0; + for (const chunk of chunks) { + collected.set(chunk, offset); + offset += chunk.length; + } + return collected; +} +__name(collectStream, "collectStream"); +function readToBase64(blob) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => { + if (reader.readyState !== 2) { + return reject(new Error("Reader aborted too early")); + } + const result = reader.result ?? ""; + const commaIndex = result.indexOf(","); + const dataOffset = commaIndex > -1 ? commaIndex + 1 : result.length; + resolve(result.substring(dataOffset)); + }; + reader.onabort = () => reject(new Error("Read aborted")); + reader.onerror = () => reject(reader.error); + reader.readAsDataURL(blob); + }); +} +__name(readToBase64, "readToBase64"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 5092: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Hash: () => Hash +}); +module.exports = __toCommonJS(src_exports); +var import_util_buffer_from = __nccwpck_require__(44151); +var import_util_utf8 = __nccwpck_require__(71577); +var import_buffer = __nccwpck_require__(20181); +var import_crypto = __nccwpck_require__(76982); +var Hash = class { + static { + __name(this, "Hash"); + } + constructor(algorithmIdentifier, secret) { + this.algorithmIdentifier = algorithmIdentifier; + this.secret = secret; + this.reset(); + } + update(toHash, encoding) { + this.hash.update((0, import_util_utf8.toUint8Array)(castSourceData(toHash, encoding))); + } + digest() { + return Promise.resolve(this.hash.digest()); + } + reset() { + this.hash = this.secret ? (0, import_crypto.createHmac)(this.algorithmIdentifier, castSourceData(this.secret)) : (0, import_crypto.createHash)(this.algorithmIdentifier); + } +}; +function castSourceData(toCast, encoding) { + if (import_buffer.Buffer.isBuffer(toCast)) { + return toCast; + } + if (typeof toCast === "string") { + return (0, import_util_buffer_from.fromString)(toCast, encoding); + } + if (ArrayBuffer.isView(toCast)) { + return (0, import_util_buffer_from.fromArrayBuffer)(toCast.buffer, toCast.byteOffset, toCast.byteLength); + } + return (0, import_util_buffer_from.fromArrayBuffer)(toCast); +} +__name(castSourceData, "castSourceData"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 45317: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fileStreamHasher: () => fileStreamHasher, + readableStreamHasher: () => readableStreamHasher +}); +module.exports = __toCommonJS(src_exports); + +// src/fileStreamHasher.ts +var import_fs = __nccwpck_require__(79896); + +// src/HashCalculator.ts +var import_util_utf8 = __nccwpck_require__(71577); +var import_stream = __nccwpck_require__(2203); +var HashCalculator = class extends import_stream.Writable { + constructor(hash, options) { + super(options); + this.hash = hash; + } + static { + __name(this, "HashCalculator"); + } + _write(chunk, encoding, callback) { + try { + this.hash.update((0, import_util_utf8.toUint8Array)(chunk)); + } catch (err) { + return callback(err); + } + callback(); + } +}; + +// src/fileStreamHasher.ts +var fileStreamHasher = /* @__PURE__ */ __name((hashCtor, fileStream) => new Promise((resolve, reject) => { + if (!isReadStream(fileStream)) { + reject(new Error("Unable to calculate hash for non-file streams.")); + return; + } + const fileStreamTee = (0, import_fs.createReadStream)(fileStream.path, { + start: fileStream.start, + end: fileStream.end + }); + const hash = new hashCtor(); + const hashCalculator = new HashCalculator(hash); + fileStreamTee.pipe(hashCalculator); + fileStreamTee.on("error", (err) => { + hashCalculator.end(); + reject(err); + }); + hashCalculator.on("error", reject); + hashCalculator.on("finish", function() { + hash.digest().then(resolve).catch(reject); + }); +}), "fileStreamHasher"); +var isReadStream = /* @__PURE__ */ __name((stream) => typeof stream.path === "string", "isReadStream"); + +// src/readableStreamHasher.ts +var readableStreamHasher = /* @__PURE__ */ __name((hashCtor, readableStream) => { + if (readableStream.readableFlowing !== null) { + throw new Error("Unable to calculate hash for flowing readable stream"); + } + const hash = new hashCtor(); + const hashCalculator = new HashCalculator(hash); + readableStream.pipe(hashCalculator); + return new Promise((resolve, reject) => { + readableStream.on("error", (err) => { + hashCalculator.end(); + reject(err); + }); + hashCalculator.on("error", reject); + hashCalculator.on("finish", () => { + hash.digest().then(resolve).catch(reject); + }); + }); +}, "readableStreamHasher"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 86130: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + isArrayBuffer: () => isArrayBuffer +}); +module.exports = __toCommonJS(src_exports); +var isArrayBuffer = /* @__PURE__ */ __name((arg) => typeof ArrayBuffer === "function" && arg instanceof ArrayBuffer || Object.prototype.toString.call(arg) === "[object ArrayBuffer]", "isArrayBuffer"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 47212: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + contentLengthMiddleware: () => contentLengthMiddleware, + contentLengthMiddlewareOptions: () => contentLengthMiddlewareOptions, + getContentLengthPlugin: () => getContentLengthPlugin +}); +module.exports = __toCommonJS(src_exports); +var import_protocol_http = __nccwpck_require__(72356); +var CONTENT_LENGTH_HEADER = "content-length"; +function contentLengthMiddleware(bodyLengthChecker) { + return (next) => async (args) => { + const request = args.request; + if (import_protocol_http.HttpRequest.isInstance(request)) { + const { body, headers } = request; + if (body && Object.keys(headers).map((str) => str.toLowerCase()).indexOf(CONTENT_LENGTH_HEADER) === -1) { + try { + const length = bodyLengthChecker(body); + request.headers = { + ...request.headers, + [CONTENT_LENGTH_HEADER]: String(length) + }; + } catch (error) { + } + } + } + return next({ + ...args, + request + }); + }; +} +__name(contentLengthMiddleware, "contentLengthMiddleware"); +var contentLengthMiddlewareOptions = { + step: "build", + tags: ["SET_CONTENT_LENGTH", "CONTENT_LENGTH"], + name: "contentLengthMiddleware", + override: true +}; +var getContentLengthPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: (clientStack) => { + clientStack.add(contentLengthMiddleware(options.bodyLengthChecker), contentLengthMiddlewareOptions); + } +}), "getContentLengthPlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 76041: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getEndpointFromConfig = void 0; +const node_config_provider_1 = __nccwpck_require__(55704); +const getEndpointUrlConfig_1 = __nccwpck_require__(18008); +const getEndpointFromConfig = async (serviceId) => (0, node_config_provider_1.loadConfig)((0, getEndpointUrlConfig_1.getEndpointUrlConfig)(serviceId !== null && serviceId !== void 0 ? serviceId : ""))(); +exports.getEndpointFromConfig = getEndpointFromConfig; + + +/***/ }), + +/***/ 18008: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getEndpointUrlConfig = void 0; +const shared_ini_file_loader_1 = __nccwpck_require__(94964); +const ENV_ENDPOINT_URL = "AWS_ENDPOINT_URL"; +const CONFIG_ENDPOINT_URL = "endpoint_url"; +const getEndpointUrlConfig = (serviceId) => ({ + environmentVariableSelector: (env) => { + const serviceSuffixParts = serviceId.split(" ").map((w) => w.toUpperCase()); + const serviceEndpointUrl = env[[ENV_ENDPOINT_URL, ...serviceSuffixParts].join("_")]; + if (serviceEndpointUrl) + return serviceEndpointUrl; + const endpointUrl = env[ENV_ENDPOINT_URL]; + if (endpointUrl) + return endpointUrl; + return undefined; + }, + configFileSelector: (profile, config) => { + if (config && profile.services) { + const servicesSection = config[["services", profile.services].join(shared_ini_file_loader_1.CONFIG_PREFIX_SEPARATOR)]; + if (servicesSection) { + const servicePrefixParts = serviceId.split(" ").map((w) => w.toLowerCase()); + const endpointUrl = servicesSection[[servicePrefixParts.join("_"), CONFIG_ENDPOINT_URL].join(shared_ini_file_loader_1.CONFIG_PREFIX_SEPARATOR)]; + if (endpointUrl) + return endpointUrl; + } + } + const endpointUrl = profile[CONFIG_ENDPOINT_URL]; + if (endpointUrl) + return endpointUrl; + return undefined; + }, + default: undefined, +}); +exports.getEndpointUrlConfig = getEndpointUrlConfig; + + +/***/ }), + +/***/ 40099: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + endpointMiddleware: () => endpointMiddleware, + endpointMiddlewareOptions: () => endpointMiddlewareOptions, + getEndpointFromInstructions: () => getEndpointFromInstructions, + getEndpointPlugin: () => getEndpointPlugin, + resolveEndpointConfig: () => resolveEndpointConfig, + resolveEndpointRequiredConfig: () => resolveEndpointRequiredConfig, + resolveParams: () => resolveParams, + toEndpointV1: () => toEndpointV1 +}); +module.exports = __toCommonJS(src_exports); + +// src/service-customizations/s3.ts +var resolveParamsForS3 = /* @__PURE__ */ __name(async (endpointParams) => { + const bucket = endpointParams?.Bucket || ""; + if (typeof endpointParams.Bucket === "string") { + endpointParams.Bucket = bucket.replace(/#/g, encodeURIComponent("#")).replace(/\?/g, encodeURIComponent("?")); + } + if (isArnBucketName(bucket)) { + if (endpointParams.ForcePathStyle === true) { + throw new Error("Path-style addressing cannot be used with ARN buckets"); + } + } else if (!isDnsCompatibleBucketName(bucket) || bucket.indexOf(".") !== -1 && !String(endpointParams.Endpoint).startsWith("http:") || bucket.toLowerCase() !== bucket || bucket.length < 3) { + endpointParams.ForcePathStyle = true; + } + if (endpointParams.DisableMultiRegionAccessPoints) { + endpointParams.disableMultiRegionAccessPoints = true; + endpointParams.DisableMRAP = true; + } + return endpointParams; +}, "resolveParamsForS3"); +var DOMAIN_PATTERN = /^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/; +var IP_ADDRESS_PATTERN = /(\d+\.){3}\d+/; +var DOTS_PATTERN = /\.\./; +var isDnsCompatibleBucketName = /* @__PURE__ */ __name((bucketName) => DOMAIN_PATTERN.test(bucketName) && !IP_ADDRESS_PATTERN.test(bucketName) && !DOTS_PATTERN.test(bucketName), "isDnsCompatibleBucketName"); +var isArnBucketName = /* @__PURE__ */ __name((bucketName) => { + const [arn, partition, service, , , bucket] = bucketName.split(":"); + const isArn = arn === "arn" && bucketName.split(":").length >= 6; + const isValidArn = Boolean(isArn && partition && service && bucket); + if (isArn && !isValidArn) { + throw new Error(`Invalid ARN: ${bucketName} was an invalid ARN.`); + } + return isValidArn; +}, "isArnBucketName"); + +// src/adaptors/createConfigValueProvider.ts +var createConfigValueProvider = /* @__PURE__ */ __name((configKey, canonicalEndpointParamKey, config) => { + const configProvider = /* @__PURE__ */ __name(async () => { + const configValue = config[configKey] ?? config[canonicalEndpointParamKey]; + if (typeof configValue === "function") { + return configValue(); + } + return configValue; + }, "configProvider"); + if (configKey === "credentialScope" || canonicalEndpointParamKey === "CredentialScope") { + return async () => { + const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials; + const configValue = credentials?.credentialScope ?? credentials?.CredentialScope; + return configValue; + }; + } + if (configKey === "accountId" || canonicalEndpointParamKey === "AccountId") { + return async () => { + const credentials = typeof config.credentials === "function" ? await config.credentials() : config.credentials; + const configValue = credentials?.accountId ?? credentials?.AccountId; + return configValue; + }; + } + if (configKey === "endpoint" || canonicalEndpointParamKey === "endpoint") { + return async () => { + if (config.isCustomEndpoint === false) { + return void 0; + } + const endpoint = await configProvider(); + if (endpoint && typeof endpoint === "object") { + if ("url" in endpoint) { + return endpoint.url.href; + } + if ("hostname" in endpoint) { + const { protocol, hostname, port, path } = endpoint; + return `${protocol}//${hostname}${port ? ":" + port : ""}${path}`; + } + } + return endpoint; + }; + } + return configProvider; +}, "createConfigValueProvider"); + +// src/adaptors/getEndpointFromInstructions.ts +var import_getEndpointFromConfig = __nccwpck_require__(76041); + +// src/adaptors/toEndpointV1.ts +var import_url_parser = __nccwpck_require__(14494); +var toEndpointV1 = /* @__PURE__ */ __name((endpoint) => { + if (typeof endpoint === "object") { + if ("url" in endpoint) { + return (0, import_url_parser.parseUrl)(endpoint.url); + } + return endpoint; + } + return (0, import_url_parser.parseUrl)(endpoint); +}, "toEndpointV1"); + +// src/adaptors/getEndpointFromInstructions.ts +var getEndpointFromInstructions = /* @__PURE__ */ __name(async (commandInput, instructionsSupplier, clientConfig, context) => { + if (!clientConfig.isCustomEndpoint) { + let endpointFromConfig; + if (clientConfig.serviceConfiguredEndpoint) { + endpointFromConfig = await clientConfig.serviceConfiguredEndpoint(); + } else { + endpointFromConfig = await (0, import_getEndpointFromConfig.getEndpointFromConfig)(clientConfig.serviceId); + } + if (endpointFromConfig) { + clientConfig.endpoint = () => Promise.resolve(toEndpointV1(endpointFromConfig)); + clientConfig.isCustomEndpoint = true; + } + } + const endpointParams = await resolveParams(commandInput, instructionsSupplier, clientConfig); + if (typeof clientConfig.endpointProvider !== "function") { + throw new Error("config.endpointProvider is not set."); + } + const endpoint = clientConfig.endpointProvider(endpointParams, context); + return endpoint; +}, "getEndpointFromInstructions"); +var resolveParams = /* @__PURE__ */ __name(async (commandInput, instructionsSupplier, clientConfig) => { + const endpointParams = {}; + const instructions = instructionsSupplier?.getEndpointParameterInstructions?.() || {}; + for (const [name, instruction] of Object.entries(instructions)) { + switch (instruction.type) { + case "staticContextParams": + endpointParams[name] = instruction.value; + break; + case "contextParams": + endpointParams[name] = commandInput[instruction.name]; + break; + case "clientContextParams": + case "builtInParams": + endpointParams[name] = await createConfigValueProvider(instruction.name, name, clientConfig)(); + break; + case "operationContextParams": + endpointParams[name] = instruction.get(commandInput); + break; + default: + throw new Error("Unrecognized endpoint parameter instruction: " + JSON.stringify(instruction)); + } + } + if (Object.keys(instructions).length === 0) { + Object.assign(endpointParams, clientConfig); + } + if (String(clientConfig.serviceId).toLowerCase() === "s3") { + await resolveParamsForS3(endpointParams); + } + return endpointParams; +}, "resolveParams"); + +// src/endpointMiddleware.ts +var import_core = __nccwpck_require__(90402); +var import_util_middleware = __nccwpck_require__(76324); +var endpointMiddleware = /* @__PURE__ */ __name(({ + config, + instructions +}) => { + return (next, context) => async (args) => { + if (config.isCustomEndpoint) { + (0, import_core.setFeature)(context, "ENDPOINT_OVERRIDE", "N"); + } + const endpoint = await getEndpointFromInstructions( + args.input, + { + getEndpointParameterInstructions() { + return instructions; + } + }, + { ...config }, + context + ); + context.endpointV2 = endpoint; + context.authSchemes = endpoint.properties?.authSchemes; + const authScheme = context.authSchemes?.[0]; + if (authScheme) { + context["signing_region"] = authScheme.signingRegion; + context["signing_service"] = authScheme.signingName; + const smithyContext = (0, import_util_middleware.getSmithyContext)(context); + const httpAuthOption = smithyContext?.selectedHttpAuthScheme?.httpAuthOption; + if (httpAuthOption) { + httpAuthOption.signingProperties = Object.assign( + httpAuthOption.signingProperties || {}, + { + signing_region: authScheme.signingRegion, + signingRegion: authScheme.signingRegion, + signing_service: authScheme.signingName, + signingName: authScheme.signingName, + signingRegionSet: authScheme.signingRegionSet + }, + authScheme.properties + ); + } + } + return next({ + ...args + }); + }; +}, "endpointMiddleware"); + +// src/getEndpointPlugin.ts +var import_middleware_serde = __nccwpck_require__(83255); +var endpointMiddlewareOptions = { + step: "serialize", + tags: ["ENDPOINT_PARAMETERS", "ENDPOINT_V2", "ENDPOINT"], + name: "endpointV2Middleware", + override: true, + relation: "before", + toMiddleware: import_middleware_serde.serializerMiddlewareOption.name +}; +var getEndpointPlugin = /* @__PURE__ */ __name((config, instructions) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo( + endpointMiddleware({ + config, + instructions + }), + endpointMiddlewareOptions + ); + } +}), "getEndpointPlugin"); + +// src/resolveEndpointConfig.ts + +var import_getEndpointFromConfig2 = __nccwpck_require__(76041); +var resolveEndpointConfig = /* @__PURE__ */ __name((input) => { + const tls = input.tls ?? true; + const { endpoint, useDualstackEndpoint, useFipsEndpoint } = input; + const customEndpointProvider = endpoint != null ? async () => toEndpointV1(await (0, import_util_middleware.normalizeProvider)(endpoint)()) : void 0; + const isCustomEndpoint = !!endpoint; + const resolvedConfig = Object.assign(input, { + endpoint: customEndpointProvider, + tls, + isCustomEndpoint, + useDualstackEndpoint: (0, import_util_middleware.normalizeProvider)(useDualstackEndpoint ?? false), + useFipsEndpoint: (0, import_util_middleware.normalizeProvider)(useFipsEndpoint ?? false) + }); + let configuredEndpointPromise = void 0; + resolvedConfig.serviceConfiguredEndpoint = async () => { + if (input.serviceId && !configuredEndpointPromise) { + configuredEndpointPromise = (0, import_getEndpointFromConfig2.getEndpointFromConfig)(input.serviceId); + } + return configuredEndpointPromise; + }; + return resolvedConfig; +}, "resolveEndpointConfig"); + +// src/resolveEndpointRequiredConfig.ts +var resolveEndpointRequiredConfig = /* @__PURE__ */ __name((input) => { + const { endpoint } = input; + if (endpoint === void 0) { + input.endpoint = async () => { + throw new Error( + "@smithy/middleware-endpoint: (default endpointRuleSet) endpoint is not set - you must configure an endpoint." + ); + }; + } + return input; +}, "resolveEndpointRequiredConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 19618: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + AdaptiveRetryStrategy: () => AdaptiveRetryStrategy, + CONFIG_MAX_ATTEMPTS: () => CONFIG_MAX_ATTEMPTS, + CONFIG_RETRY_MODE: () => CONFIG_RETRY_MODE, + ENV_MAX_ATTEMPTS: () => ENV_MAX_ATTEMPTS, + ENV_RETRY_MODE: () => ENV_RETRY_MODE, + NODE_MAX_ATTEMPT_CONFIG_OPTIONS: () => NODE_MAX_ATTEMPT_CONFIG_OPTIONS, + NODE_RETRY_MODE_CONFIG_OPTIONS: () => NODE_RETRY_MODE_CONFIG_OPTIONS, + StandardRetryStrategy: () => StandardRetryStrategy, + defaultDelayDecider: () => defaultDelayDecider, + defaultRetryDecider: () => defaultRetryDecider, + getOmitRetryHeadersPlugin: () => getOmitRetryHeadersPlugin, + getRetryAfterHint: () => getRetryAfterHint, + getRetryPlugin: () => getRetryPlugin, + omitRetryHeadersMiddleware: () => omitRetryHeadersMiddleware, + omitRetryHeadersMiddlewareOptions: () => omitRetryHeadersMiddlewareOptions, + resolveRetryConfig: () => resolveRetryConfig, + retryMiddleware: () => retryMiddleware, + retryMiddlewareOptions: () => retryMiddlewareOptions +}); +module.exports = __toCommonJS(src_exports); + +// src/AdaptiveRetryStrategy.ts + + +// src/StandardRetryStrategy.ts +var import_protocol_http = __nccwpck_require__(72356); + + +var import_uuid = __nccwpck_require__(12048); + +// src/defaultRetryQuota.ts +var import_util_retry = __nccwpck_require__(15518); +var getDefaultRetryQuota = /* @__PURE__ */ __name((initialRetryTokens, options) => { + const MAX_CAPACITY = initialRetryTokens; + const noRetryIncrement = options?.noRetryIncrement ?? import_util_retry.NO_RETRY_INCREMENT; + const retryCost = options?.retryCost ?? import_util_retry.RETRY_COST; + const timeoutRetryCost = options?.timeoutRetryCost ?? import_util_retry.TIMEOUT_RETRY_COST; + let availableCapacity = initialRetryTokens; + const getCapacityAmount = /* @__PURE__ */ __name((error) => error.name === "TimeoutError" ? timeoutRetryCost : retryCost, "getCapacityAmount"); + const hasRetryTokens = /* @__PURE__ */ __name((error) => getCapacityAmount(error) <= availableCapacity, "hasRetryTokens"); + const retrieveRetryTokens = /* @__PURE__ */ __name((error) => { + if (!hasRetryTokens(error)) { + throw new Error("No retry token available"); + } + const capacityAmount = getCapacityAmount(error); + availableCapacity -= capacityAmount; + return capacityAmount; + }, "retrieveRetryTokens"); + const releaseRetryTokens = /* @__PURE__ */ __name((capacityReleaseAmount) => { + availableCapacity += capacityReleaseAmount ?? noRetryIncrement; + availableCapacity = Math.min(availableCapacity, MAX_CAPACITY); + }, "releaseRetryTokens"); + return Object.freeze({ + hasRetryTokens, + retrieveRetryTokens, + releaseRetryTokens + }); +}, "getDefaultRetryQuota"); + +// src/delayDecider.ts + +var defaultDelayDecider = /* @__PURE__ */ __name((delayBase, attempts) => Math.floor(Math.min(import_util_retry.MAXIMUM_RETRY_DELAY, Math.random() * 2 ** attempts * delayBase)), "defaultDelayDecider"); + +// src/retryDecider.ts +var import_service_error_classification = __nccwpck_require__(42058); +var defaultRetryDecider = /* @__PURE__ */ __name((error) => { + if (!error) { + return false; + } + return (0, import_service_error_classification.isRetryableByTrait)(error) || (0, import_service_error_classification.isClockSkewError)(error) || (0, import_service_error_classification.isThrottlingError)(error) || (0, import_service_error_classification.isTransientError)(error); +}, "defaultRetryDecider"); + +// src/util.ts +var asSdkError = /* @__PURE__ */ __name((error) => { + if (error instanceof Error) + return error; + if (error instanceof Object) + return Object.assign(new Error(), error); + if (typeof error === "string") + return new Error(error); + return new Error(`AWS SDK error wrapper for ${error}`); +}, "asSdkError"); + +// src/StandardRetryStrategy.ts +var StandardRetryStrategy = class { + constructor(maxAttemptsProvider, options) { + this.maxAttemptsProvider = maxAttemptsProvider; + this.mode = import_util_retry.RETRY_MODES.STANDARD; + this.retryDecider = options?.retryDecider ?? defaultRetryDecider; + this.delayDecider = options?.delayDecider ?? defaultDelayDecider; + this.retryQuota = options?.retryQuota ?? getDefaultRetryQuota(import_util_retry.INITIAL_RETRY_TOKENS); + } + static { + __name(this, "StandardRetryStrategy"); + } + shouldRetry(error, attempts, maxAttempts) { + return attempts < maxAttempts && this.retryDecider(error) && this.retryQuota.hasRetryTokens(error); + } + async getMaxAttempts() { + let maxAttempts; + try { + maxAttempts = await this.maxAttemptsProvider(); + } catch (error) { + maxAttempts = import_util_retry.DEFAULT_MAX_ATTEMPTS; + } + return maxAttempts; + } + async retry(next, args, options) { + let retryTokenAmount; + let attempts = 0; + let totalDelay = 0; + const maxAttempts = await this.getMaxAttempts(); + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request)) { + request.headers[import_util_retry.INVOCATION_ID_HEADER] = (0, import_uuid.v4)(); + } + while (true) { + try { + if (import_protocol_http.HttpRequest.isInstance(request)) { + request.headers[import_util_retry.REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`; + } + if (options?.beforeRequest) { + await options.beforeRequest(); + } + const { response, output } = await next(args); + if (options?.afterRequest) { + options.afterRequest(response); + } + this.retryQuota.releaseRetryTokens(retryTokenAmount); + output.$metadata.attempts = attempts + 1; + output.$metadata.totalRetryDelay = totalDelay; + return { response, output }; + } catch (e) { + const err = asSdkError(e); + attempts++; + if (this.shouldRetry(err, attempts, maxAttempts)) { + retryTokenAmount = this.retryQuota.retrieveRetryTokens(err); + const delayFromDecider = this.delayDecider( + (0, import_service_error_classification.isThrottlingError)(err) ? import_util_retry.THROTTLING_RETRY_DELAY_BASE : import_util_retry.DEFAULT_RETRY_DELAY_BASE, + attempts + ); + const delayFromResponse = getDelayFromRetryAfterHeader(err.$response); + const delay = Math.max(delayFromResponse || 0, delayFromDecider); + totalDelay += delay; + await new Promise((resolve) => setTimeout(resolve, delay)); + continue; + } + if (!err.$metadata) { + err.$metadata = {}; + } + err.$metadata.attempts = attempts; + err.$metadata.totalRetryDelay = totalDelay; + throw err; + } + } + } +}; +var getDelayFromRetryAfterHeader = /* @__PURE__ */ __name((response) => { + if (!import_protocol_http.HttpResponse.isInstance(response)) + return; + const retryAfterHeaderName = Object.keys(response.headers).find((key) => key.toLowerCase() === "retry-after"); + if (!retryAfterHeaderName) + return; + const retryAfter = response.headers[retryAfterHeaderName]; + const retryAfterSeconds = Number(retryAfter); + if (!Number.isNaN(retryAfterSeconds)) + return retryAfterSeconds * 1e3; + const retryAfterDate = new Date(retryAfter); + return retryAfterDate.getTime() - Date.now(); +}, "getDelayFromRetryAfterHeader"); + +// src/AdaptiveRetryStrategy.ts +var AdaptiveRetryStrategy = class extends StandardRetryStrategy { + static { + __name(this, "AdaptiveRetryStrategy"); + } + constructor(maxAttemptsProvider, options) { + const { rateLimiter, ...superOptions } = options ?? {}; + super(maxAttemptsProvider, superOptions); + this.rateLimiter = rateLimiter ?? new import_util_retry.DefaultRateLimiter(); + this.mode = import_util_retry.RETRY_MODES.ADAPTIVE; + } + async retry(next, args) { + return super.retry(next, args, { + beforeRequest: async () => { + return this.rateLimiter.getSendToken(); + }, + afterRequest: (response) => { + this.rateLimiter.updateClientSendingRate(response); + } + }); + } +}; + +// src/configurations.ts +var import_util_middleware = __nccwpck_require__(76324); + +var ENV_MAX_ATTEMPTS = "AWS_MAX_ATTEMPTS"; +var CONFIG_MAX_ATTEMPTS = "max_attempts"; +var NODE_MAX_ATTEMPT_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => { + const value = env[ENV_MAX_ATTEMPTS]; + if (!value) + return void 0; + const maxAttempt = parseInt(value); + if (Number.isNaN(maxAttempt)) { + throw new Error(`Environment variable ${ENV_MAX_ATTEMPTS} mast be a number, got "${value}"`); + } + return maxAttempt; + }, + configFileSelector: (profile) => { + const value = profile[CONFIG_MAX_ATTEMPTS]; + if (!value) + return void 0; + const maxAttempt = parseInt(value); + if (Number.isNaN(maxAttempt)) { + throw new Error(`Shared config file entry ${CONFIG_MAX_ATTEMPTS} mast be a number, got "${value}"`); + } + return maxAttempt; + }, + default: import_util_retry.DEFAULT_MAX_ATTEMPTS +}; +var resolveRetryConfig = /* @__PURE__ */ __name((input) => { + const { retryStrategy, retryMode: _retryMode, maxAttempts: _maxAttempts } = input; + const maxAttempts = (0, import_util_middleware.normalizeProvider)(_maxAttempts ?? import_util_retry.DEFAULT_MAX_ATTEMPTS); + return Object.assign(input, { + maxAttempts, + retryStrategy: async () => { + if (retryStrategy) { + return retryStrategy; + } + const retryMode = await (0, import_util_middleware.normalizeProvider)(_retryMode)(); + if (retryMode === import_util_retry.RETRY_MODES.ADAPTIVE) { + return new import_util_retry.AdaptiveRetryStrategy(maxAttempts); + } + return new import_util_retry.StandardRetryStrategy(maxAttempts); + } + }); +}, "resolveRetryConfig"); +var ENV_RETRY_MODE = "AWS_RETRY_MODE"; +var CONFIG_RETRY_MODE = "retry_mode"; +var NODE_RETRY_MODE_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => env[ENV_RETRY_MODE], + configFileSelector: (profile) => profile[CONFIG_RETRY_MODE], + default: import_util_retry.DEFAULT_RETRY_MODE +}; + +// src/omitRetryHeadersMiddleware.ts + + +var omitRetryHeadersMiddleware = /* @__PURE__ */ __name(() => (next) => async (args) => { + const { request } = args; + if (import_protocol_http.HttpRequest.isInstance(request)) { + delete request.headers[import_util_retry.INVOCATION_ID_HEADER]; + delete request.headers[import_util_retry.REQUEST_HEADER]; + } + return next(args); +}, "omitRetryHeadersMiddleware"); +var omitRetryHeadersMiddlewareOptions = { + name: "omitRetryHeadersMiddleware", + tags: ["RETRY", "HEADERS", "OMIT_RETRY_HEADERS"], + relation: "before", + toMiddleware: "awsAuthMiddleware", + override: true +}; +var getOmitRetryHeadersPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: (clientStack) => { + clientStack.addRelativeTo(omitRetryHeadersMiddleware(), omitRetryHeadersMiddlewareOptions); + } +}), "getOmitRetryHeadersPlugin"); + +// src/retryMiddleware.ts + + +var import_smithy_client = __nccwpck_require__(61411); + + +var import_isStreamingPayload = __nccwpck_require__(49831); +var retryMiddleware = /* @__PURE__ */ __name((options) => (next, context) => async (args) => { + let retryStrategy = await options.retryStrategy(); + const maxAttempts = await options.maxAttempts(); + if (isRetryStrategyV2(retryStrategy)) { + retryStrategy = retryStrategy; + let retryToken = await retryStrategy.acquireInitialRetryToken(context["partition_id"]); + let lastError = new Error(); + let attempts = 0; + let totalRetryDelay = 0; + const { request } = args; + const isRequest = import_protocol_http.HttpRequest.isInstance(request); + if (isRequest) { + request.headers[import_util_retry.INVOCATION_ID_HEADER] = (0, import_uuid.v4)(); + } + while (true) { + try { + if (isRequest) { + request.headers[import_util_retry.REQUEST_HEADER] = `attempt=${attempts + 1}; max=${maxAttempts}`; + } + const { response, output } = await next(args); + retryStrategy.recordSuccess(retryToken); + output.$metadata.attempts = attempts + 1; + output.$metadata.totalRetryDelay = totalRetryDelay; + return { response, output }; + } catch (e) { + const retryErrorInfo = getRetryErrorInfo(e); + lastError = asSdkError(e); + if (isRequest && (0, import_isStreamingPayload.isStreamingPayload)(request)) { + (context.logger instanceof import_smithy_client.NoOpLogger ? console : context.logger)?.warn( + "An error was encountered in a non-retryable streaming request." + ); + throw lastError; + } + try { + retryToken = await retryStrategy.refreshRetryTokenForRetry(retryToken, retryErrorInfo); + } catch (refreshError) { + if (!lastError.$metadata) { + lastError.$metadata = {}; + } + lastError.$metadata.attempts = attempts + 1; + lastError.$metadata.totalRetryDelay = totalRetryDelay; + throw lastError; + } + attempts = retryToken.getRetryCount(); + const delay = retryToken.getRetryDelay(); + totalRetryDelay += delay; + await new Promise((resolve) => setTimeout(resolve, delay)); + } + } + } else { + retryStrategy = retryStrategy; + if (retryStrategy?.mode) + context.userAgent = [...context.userAgent || [], ["cfg/retry-mode", retryStrategy.mode]]; + return retryStrategy.retry(next, args); + } +}, "retryMiddleware"); +var isRetryStrategyV2 = /* @__PURE__ */ __name((retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" && typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" && typeof retryStrategy.recordSuccess !== "undefined", "isRetryStrategyV2"); +var getRetryErrorInfo = /* @__PURE__ */ __name((error) => { + const errorInfo = { + error, + errorType: getRetryErrorType(error) + }; + const retryAfterHint = getRetryAfterHint(error.$response); + if (retryAfterHint) { + errorInfo.retryAfterHint = retryAfterHint; + } + return errorInfo; +}, "getRetryErrorInfo"); +var getRetryErrorType = /* @__PURE__ */ __name((error) => { + if ((0, import_service_error_classification.isThrottlingError)(error)) + return "THROTTLING"; + if ((0, import_service_error_classification.isTransientError)(error)) + return "TRANSIENT"; + if ((0, import_service_error_classification.isServerError)(error)) + return "SERVER_ERROR"; + return "CLIENT_ERROR"; +}, "getRetryErrorType"); +var retryMiddlewareOptions = { + name: "retryMiddleware", + tags: ["RETRY"], + step: "finalizeRequest", + priority: "high", + override: true +}; +var getRetryPlugin = /* @__PURE__ */ __name((options) => ({ + applyToStack: (clientStack) => { + clientStack.add(retryMiddleware(options), retryMiddlewareOptions); + } +}), "getRetryPlugin"); +var getRetryAfterHint = /* @__PURE__ */ __name((response) => { + if (!import_protocol_http.HttpResponse.isInstance(response)) + return; + const retryAfterHeaderName = Object.keys(response.headers).find((key) => key.toLowerCase() === "retry-after"); + if (!retryAfterHeaderName) + return; + const retryAfter = response.headers[retryAfterHeaderName]; + const retryAfterSeconds = Number(retryAfter); + if (!Number.isNaN(retryAfterSeconds)) + return new Date(retryAfterSeconds * 1e3); + const retryAfterDate = new Date(retryAfter); + return retryAfterDate; +}, "getRetryAfterHint"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 49831: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isStreamingPayload = void 0; +const stream_1 = __nccwpck_require__(2203); +const isStreamingPayload = (request) => (request === null || request === void 0 ? void 0 : request.body) instanceof stream_1.Readable || + (typeof ReadableStream !== "undefined" && (request === null || request === void 0 ? void 0 : request.body) instanceof ReadableStream); +exports.isStreamingPayload = isStreamingPayload; + + +/***/ }), + +/***/ 83255: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + deserializerMiddleware: () => deserializerMiddleware, + deserializerMiddlewareOption: () => deserializerMiddlewareOption, + getSerdePlugin: () => getSerdePlugin, + serializerMiddleware: () => serializerMiddleware, + serializerMiddlewareOption: () => serializerMiddlewareOption +}); +module.exports = __toCommonJS(src_exports); + +// src/deserializerMiddleware.ts +var import_protocol_http = __nccwpck_require__(72356); +var deserializerMiddleware = /* @__PURE__ */ __name((options, deserializer) => (next, context) => async (args) => { + const { response } = await next(args); + try { + const parsed = await deserializer(response, options); + return { + response, + output: parsed + }; + } catch (error) { + Object.defineProperty(error, "$response", { + value: response + }); + if (!("$metadata" in error)) { + const hint = `Deserialization error: to see the raw response, inspect the hidden field {error}.$response on this object.`; + try { + error.message += "\n " + hint; + } catch (e) { + if (!context.logger || context.logger?.constructor?.name === "NoOpLogger") { + console.warn(hint); + } else { + context.logger?.warn?.(hint); + } + } + if (typeof error.$responseBodyText !== "undefined") { + if (error.$response) { + error.$response.body = error.$responseBodyText; + } + } + try { + if (import_protocol_http.HttpResponse.isInstance(response)) { + const { headers = {} } = response; + const headerEntries = Object.entries(headers); + error.$metadata = { + httpStatusCode: response.statusCode, + requestId: findHeader(/^x-[\w-]+-request-?id$/, headerEntries), + extendedRequestId: findHeader(/^x-[\w-]+-id-2$/, headerEntries), + cfId: findHeader(/^x-[\w-]+-cf-id$/, headerEntries) + }; + } + } catch (e) { + } + } + throw error; + } +}, "deserializerMiddleware"); +var findHeader = /* @__PURE__ */ __name((pattern, headers) => { + return (headers.find(([k]) => { + return k.match(pattern); + }) || [void 0, void 0])[1]; +}, "findHeader"); + +// src/serializerMiddleware.ts +var serializerMiddleware = /* @__PURE__ */ __name((options, serializer) => (next, context) => async (args) => { + const endpointConfig = options; + const endpoint = context.endpointV2?.url && endpointConfig.urlParser ? async () => endpointConfig.urlParser(context.endpointV2.url) : endpointConfig.endpoint; + if (!endpoint) { + throw new Error("No valid endpoint provider available."); + } + const request = await serializer(args.input, { ...options, endpoint }); + return next({ + ...args, + request + }); +}, "serializerMiddleware"); + +// src/serdePlugin.ts +var deserializerMiddlewareOption = { + name: "deserializerMiddleware", + step: "deserialize", + tags: ["DESERIALIZER"], + override: true +}; +var serializerMiddlewareOption = { + name: "serializerMiddleware", + step: "serialize", + tags: ["SERIALIZER"], + override: true +}; +function getSerdePlugin(config, serializer, deserializer) { + return { + applyToStack: (commandStack) => { + commandStack.add(deserializerMiddleware(config, deserializer), deserializerMiddlewareOption); + commandStack.add(serializerMiddleware(config, serializer), serializerMiddlewareOption); + } + }; +} +__name(getSerdePlugin, "getSerdePlugin"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 9208: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + constructStack: () => constructStack +}); +module.exports = __toCommonJS(src_exports); + +// src/MiddlewareStack.ts +var getAllAliases = /* @__PURE__ */ __name((name, aliases) => { + const _aliases = []; + if (name) { + _aliases.push(name); + } + if (aliases) { + for (const alias of aliases) { + _aliases.push(alias); + } + } + return _aliases; +}, "getAllAliases"); +var getMiddlewareNameWithAliases = /* @__PURE__ */ __name((name, aliases) => { + return `${name || "anonymous"}${aliases && aliases.length > 0 ? ` (a.k.a. ${aliases.join(",")})` : ""}`; +}, "getMiddlewareNameWithAliases"); +var constructStack = /* @__PURE__ */ __name(() => { + let absoluteEntries = []; + let relativeEntries = []; + let identifyOnResolve = false; + const entriesNameSet = /* @__PURE__ */ new Set(); + const sort = /* @__PURE__ */ __name((entries) => entries.sort( + (a, b) => stepWeights[b.step] - stepWeights[a.step] || priorityWeights[b.priority || "normal"] - priorityWeights[a.priority || "normal"] + ), "sort"); + const removeByName = /* @__PURE__ */ __name((toRemove) => { + let isRemoved = false; + const filterCb = /* @__PURE__ */ __name((entry) => { + const aliases = getAllAliases(entry.name, entry.aliases); + if (aliases.includes(toRemove)) { + isRemoved = true; + for (const alias of aliases) { + entriesNameSet.delete(alias); + } + return false; + } + return true; + }, "filterCb"); + absoluteEntries = absoluteEntries.filter(filterCb); + relativeEntries = relativeEntries.filter(filterCb); + return isRemoved; + }, "removeByName"); + const removeByReference = /* @__PURE__ */ __name((toRemove) => { + let isRemoved = false; + const filterCb = /* @__PURE__ */ __name((entry) => { + if (entry.middleware === toRemove) { + isRemoved = true; + for (const alias of getAllAliases(entry.name, entry.aliases)) { + entriesNameSet.delete(alias); + } + return false; + } + return true; + }, "filterCb"); + absoluteEntries = absoluteEntries.filter(filterCb); + relativeEntries = relativeEntries.filter(filterCb); + return isRemoved; + }, "removeByReference"); + const cloneTo = /* @__PURE__ */ __name((toStack) => { + absoluteEntries.forEach((entry) => { + toStack.add(entry.middleware, { ...entry }); + }); + relativeEntries.forEach((entry) => { + toStack.addRelativeTo(entry.middleware, { ...entry }); + }); + toStack.identifyOnResolve?.(stack.identifyOnResolve()); + return toStack; + }, "cloneTo"); + const expandRelativeMiddlewareList = /* @__PURE__ */ __name((from) => { + const expandedMiddlewareList = []; + from.before.forEach((entry) => { + if (entry.before.length === 0 && entry.after.length === 0) { + expandedMiddlewareList.push(entry); + } else { + expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); + } + }); + expandedMiddlewareList.push(from); + from.after.reverse().forEach((entry) => { + if (entry.before.length === 0 && entry.after.length === 0) { + expandedMiddlewareList.push(entry); + } else { + expandedMiddlewareList.push(...expandRelativeMiddlewareList(entry)); + } + }); + return expandedMiddlewareList; + }, "expandRelativeMiddlewareList"); + const getMiddlewareList = /* @__PURE__ */ __name((debug = false) => { + const normalizedAbsoluteEntries = []; + const normalizedRelativeEntries = []; + const normalizedEntriesNameMap = {}; + absoluteEntries.forEach((entry) => { + const normalizedEntry = { + ...entry, + before: [], + after: [] + }; + for (const alias of getAllAliases(normalizedEntry.name, normalizedEntry.aliases)) { + normalizedEntriesNameMap[alias] = normalizedEntry; + } + normalizedAbsoluteEntries.push(normalizedEntry); + }); + relativeEntries.forEach((entry) => { + const normalizedEntry = { + ...entry, + before: [], + after: [] + }; + for (const alias of getAllAliases(normalizedEntry.name, normalizedEntry.aliases)) { + normalizedEntriesNameMap[alias] = normalizedEntry; + } + normalizedRelativeEntries.push(normalizedEntry); + }); + normalizedRelativeEntries.forEach((entry) => { + if (entry.toMiddleware) { + const toMiddleware = normalizedEntriesNameMap[entry.toMiddleware]; + if (toMiddleware === void 0) { + if (debug) { + return; + } + throw new Error( + `${entry.toMiddleware} is not found when adding ${getMiddlewareNameWithAliases(entry.name, entry.aliases)} middleware ${entry.relation} ${entry.toMiddleware}` + ); + } + if (entry.relation === "after") { + toMiddleware.after.push(entry); + } + if (entry.relation === "before") { + toMiddleware.before.push(entry); + } + } + }); + const mainChain = sort(normalizedAbsoluteEntries).map(expandRelativeMiddlewareList).reduce( + (wholeList, expandedMiddlewareList) => { + wholeList.push(...expandedMiddlewareList); + return wholeList; + }, + [] + ); + return mainChain; + }, "getMiddlewareList"); + const stack = { + add: (middleware, options = {}) => { + const { name, override, aliases: _aliases } = options; + const entry = { + step: "initialize", + priority: "normal", + middleware, + ...options + }; + const aliases = getAllAliases(name, _aliases); + if (aliases.length > 0) { + if (aliases.some((alias) => entriesNameSet.has(alias))) { + if (!override) + throw new Error(`Duplicate middleware name '${getMiddlewareNameWithAliases(name, _aliases)}'`); + for (const alias of aliases) { + const toOverrideIndex = absoluteEntries.findIndex( + (entry2) => entry2.name === alias || entry2.aliases?.some((a) => a === alias) + ); + if (toOverrideIndex === -1) { + continue; + } + const toOverride = absoluteEntries[toOverrideIndex]; + if (toOverride.step !== entry.step || entry.priority !== toOverride.priority) { + throw new Error( + `"${getMiddlewareNameWithAliases(toOverride.name, toOverride.aliases)}" middleware with ${toOverride.priority} priority in ${toOverride.step} step cannot be overridden by "${getMiddlewareNameWithAliases(name, _aliases)}" middleware with ${entry.priority} priority in ${entry.step} step.` + ); + } + absoluteEntries.splice(toOverrideIndex, 1); + } + } + for (const alias of aliases) { + entriesNameSet.add(alias); + } + } + absoluteEntries.push(entry); + }, + addRelativeTo: (middleware, options) => { + const { name, override, aliases: _aliases } = options; + const entry = { + middleware, + ...options + }; + const aliases = getAllAliases(name, _aliases); + if (aliases.length > 0) { + if (aliases.some((alias) => entriesNameSet.has(alias))) { + if (!override) + throw new Error(`Duplicate middleware name '${getMiddlewareNameWithAliases(name, _aliases)}'`); + for (const alias of aliases) { + const toOverrideIndex = relativeEntries.findIndex( + (entry2) => entry2.name === alias || entry2.aliases?.some((a) => a === alias) + ); + if (toOverrideIndex === -1) { + continue; + } + const toOverride = relativeEntries[toOverrideIndex]; + if (toOverride.toMiddleware !== entry.toMiddleware || toOverride.relation !== entry.relation) { + throw new Error( + `"${getMiddlewareNameWithAliases(toOverride.name, toOverride.aliases)}" middleware ${toOverride.relation} "${toOverride.toMiddleware}" middleware cannot be overridden by "${getMiddlewareNameWithAliases(name, _aliases)}" middleware ${entry.relation} "${entry.toMiddleware}" middleware.` + ); + } + relativeEntries.splice(toOverrideIndex, 1); + } + } + for (const alias of aliases) { + entriesNameSet.add(alias); + } + } + relativeEntries.push(entry); + }, + clone: () => cloneTo(constructStack()), + use: (plugin) => { + plugin.applyToStack(stack); + }, + remove: (toRemove) => { + if (typeof toRemove === "string") + return removeByName(toRemove); + else + return removeByReference(toRemove); + }, + removeByTag: (toRemove) => { + let isRemoved = false; + const filterCb = /* @__PURE__ */ __name((entry) => { + const { tags, name, aliases: _aliases } = entry; + if (tags && tags.includes(toRemove)) { + const aliases = getAllAliases(name, _aliases); + for (const alias of aliases) { + entriesNameSet.delete(alias); + } + isRemoved = true; + return false; + } + return true; + }, "filterCb"); + absoluteEntries = absoluteEntries.filter(filterCb); + relativeEntries = relativeEntries.filter(filterCb); + return isRemoved; + }, + concat: (from) => { + const cloned = cloneTo(constructStack()); + cloned.use(from); + cloned.identifyOnResolve( + identifyOnResolve || cloned.identifyOnResolve() || (from.identifyOnResolve?.() ?? false) + ); + return cloned; + }, + applyToStack: cloneTo, + identify: () => { + return getMiddlewareList(true).map((mw) => { + const step = mw.step ?? mw.relation + " " + mw.toMiddleware; + return getMiddlewareNameWithAliases(mw.name, mw.aliases) + " - " + step; + }); + }, + identifyOnResolve(toggle) { + if (typeof toggle === "boolean") + identifyOnResolve = toggle; + return identifyOnResolve; + }, + resolve: (handler, context) => { + for (const middleware of getMiddlewareList().map((entry) => entry.middleware).reverse()) { + handler = middleware(handler, context); + } + if (identifyOnResolve) { + console.log(stack.identify()); + } + return handler; + } + }; + return stack; +}, "constructStack"); +var stepWeights = { + initialize: 5, + serialize: 4, + build: 3, + finalizeRequest: 2, + deserialize: 1 +}; +var priorityWeights = { + high: 3, + normal: 2, + low: 1 +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 55704: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + loadConfig: () => loadConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/configLoader.ts + + +// src/fromEnv.ts +var import_property_provider = __nccwpck_require__(71238); + +// src/getSelectorName.ts +function getSelectorName(functionString) { + try { + const constants = new Set(Array.from(functionString.match(/([A-Z_]){3,}/g) ?? [])); + constants.delete("CONFIG"); + constants.delete("CONFIG_PREFIX_SEPARATOR"); + constants.delete("ENV"); + return [...constants].join(", "); + } catch (e) { + return functionString; + } +} +__name(getSelectorName, "getSelectorName"); + +// src/fromEnv.ts +var fromEnv = /* @__PURE__ */ __name((envVarSelector, options) => async () => { + try { + const config = envVarSelector(process.env, options); + if (config === void 0) { + throw new Error(); + } + return config; + } catch (e) { + throw new import_property_provider.CredentialsProviderError( + e.message || `Not found in ENV: ${getSelectorName(envVarSelector.toString())}`, + { logger: options?.logger } + ); + } +}, "fromEnv"); + +// src/fromSharedConfigFiles.ts + +var import_shared_ini_file_loader = __nccwpck_require__(94964); +var fromSharedConfigFiles = /* @__PURE__ */ __name((configSelector, { preferredFile = "config", ...init } = {}) => async () => { + const profile = (0, import_shared_ini_file_loader.getProfileName)(init); + const { configFile, credentialsFile } = await (0, import_shared_ini_file_loader.loadSharedConfigFiles)(init); + const profileFromCredentials = credentialsFile[profile] || {}; + const profileFromConfig = configFile[profile] || {}; + const mergedProfile = preferredFile === "config" ? { ...profileFromCredentials, ...profileFromConfig } : { ...profileFromConfig, ...profileFromCredentials }; + try { + const cfgFile = preferredFile === "config" ? configFile : credentialsFile; + const configValue = configSelector(mergedProfile, cfgFile); + if (configValue === void 0) { + throw new Error(); + } + return configValue; + } catch (e) { + throw new import_property_provider.CredentialsProviderError( + e.message || `Not found in config files w/ profile [${profile}]: ${getSelectorName(configSelector.toString())}`, + { logger: init.logger } + ); + } +}, "fromSharedConfigFiles"); + +// src/fromStatic.ts + +var isFunction = /* @__PURE__ */ __name((func) => typeof func === "function", "isFunction"); +var fromStatic = /* @__PURE__ */ __name((defaultValue) => isFunction(defaultValue) ? async () => await defaultValue() : (0, import_property_provider.fromStatic)(defaultValue), "fromStatic"); + +// src/configLoader.ts +var loadConfig = /* @__PURE__ */ __name(({ environmentVariableSelector, configFileSelector, default: defaultValue }, configuration = {}) => { + const { signingName, logger } = configuration; + const envOptions = { signingName, logger }; + return (0, import_property_provider.memoize)( + (0, import_property_provider.chain)( + fromEnv(environmentVariableSelector, envOptions), + fromSharedConfigFiles(configFileSelector, configuration), + fromStatic(defaultValue) + ) + ); +}, "loadConfig"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 61279: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + DEFAULT_REQUEST_TIMEOUT: () => DEFAULT_REQUEST_TIMEOUT, + NodeHttp2Handler: () => NodeHttp2Handler, + NodeHttpHandler: () => NodeHttpHandler, + streamCollector: () => streamCollector +}); +module.exports = __toCommonJS(src_exports); + +// src/node-http-handler.ts +var import_protocol_http = __nccwpck_require__(72356); +var import_querystring_builder = __nccwpck_require__(18256); +var import_http = __nccwpck_require__(58611); +var import_https = __nccwpck_require__(65692); + +// src/constants.ts +var NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "EPIPE", "ETIMEDOUT"]; + +// src/get-transformed-headers.ts +var getTransformedHeaders = /* @__PURE__ */ __name((headers) => { + const transformedHeaders = {}; + for (const name of Object.keys(headers)) { + const headerValues = headers[name]; + transformedHeaders[name] = Array.isArray(headerValues) ? headerValues.join(",") : headerValues; + } + return transformedHeaders; +}, "getTransformedHeaders"); + +// src/timing.ts +var timing = { + setTimeout: (cb, ms) => setTimeout(cb, ms), + clearTimeout: (timeoutId) => clearTimeout(timeoutId) +}; + +// src/set-connection-timeout.ts +var DEFER_EVENT_LISTENER_TIME = 1e3; +var setConnectionTimeout = /* @__PURE__ */ __name((request, reject, timeoutInMs = 0) => { + if (!timeoutInMs) { + return -1; + } + const registerTimeout = /* @__PURE__ */ __name((offset) => { + const timeoutId = timing.setTimeout(() => { + request.destroy(); + reject( + Object.assign(new Error(`Socket timed out without establishing a connection within ${timeoutInMs} ms`), { + name: "TimeoutError" + }) + ); + }, timeoutInMs - offset); + const doWithSocket = /* @__PURE__ */ __name((socket) => { + if (socket?.connecting) { + socket.on("connect", () => { + timing.clearTimeout(timeoutId); + }); + } else { + timing.clearTimeout(timeoutId); + } + }, "doWithSocket"); + if (request.socket) { + doWithSocket(request.socket); + } else { + request.on("socket", doWithSocket); + } + }, "registerTimeout"); + if (timeoutInMs < 2e3) { + registerTimeout(0); + return 0; + } + return timing.setTimeout(registerTimeout.bind(null, DEFER_EVENT_LISTENER_TIME), DEFER_EVENT_LISTENER_TIME); +}, "setConnectionTimeout"); + +// src/set-socket-keep-alive.ts +var DEFER_EVENT_LISTENER_TIME2 = 3e3; +var setSocketKeepAlive = /* @__PURE__ */ __name((request, { keepAlive, keepAliveMsecs }, deferTimeMs = DEFER_EVENT_LISTENER_TIME2) => { + if (keepAlive !== true) { + return -1; + } + const registerListener = /* @__PURE__ */ __name(() => { + if (request.socket) { + request.socket.setKeepAlive(keepAlive, keepAliveMsecs || 0); + } else { + request.on("socket", (socket) => { + socket.setKeepAlive(keepAlive, keepAliveMsecs || 0); + }); + } + }, "registerListener"); + if (deferTimeMs === 0) { + registerListener(); + return 0; + } + return timing.setTimeout(registerListener, deferTimeMs); +}, "setSocketKeepAlive"); + +// src/set-socket-timeout.ts +var DEFER_EVENT_LISTENER_TIME3 = 3e3; +var setSocketTimeout = /* @__PURE__ */ __name((request, reject, timeoutInMs = DEFAULT_REQUEST_TIMEOUT) => { + const registerTimeout = /* @__PURE__ */ __name((offset) => { + const timeout = timeoutInMs - offset; + const onTimeout = /* @__PURE__ */ __name(() => { + request.destroy(); + reject(Object.assign(new Error(`Connection timed out after ${timeoutInMs} ms`), { name: "TimeoutError" })); + }, "onTimeout"); + if (request.socket) { + request.socket.setTimeout(timeout, onTimeout); + request.on("close", () => request.socket?.removeListener("timeout", onTimeout)); + } else { + request.setTimeout(timeout, onTimeout); + } + }, "registerTimeout"); + if (0 < timeoutInMs && timeoutInMs < 6e3) { + registerTimeout(0); + return 0; + } + return timing.setTimeout( + registerTimeout.bind(null, timeoutInMs === 0 ? 0 : DEFER_EVENT_LISTENER_TIME3), + DEFER_EVENT_LISTENER_TIME3 + ); +}, "setSocketTimeout"); + +// src/write-request-body.ts +var import_stream = __nccwpck_require__(2203); +var MIN_WAIT_TIME = 6e3; +async function writeRequestBody(httpRequest, request, maxContinueTimeoutMs = MIN_WAIT_TIME) { + const headers = request.headers ?? {}; + const expect = headers["Expect"] || headers["expect"]; + let timeoutId = -1; + let sendBody = true; + if (expect === "100-continue") { + sendBody = await Promise.race([ + new Promise((resolve) => { + timeoutId = Number(timing.setTimeout(() => resolve(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs))); + }), + new Promise((resolve) => { + httpRequest.on("continue", () => { + timing.clearTimeout(timeoutId); + resolve(true); + }); + httpRequest.on("response", () => { + timing.clearTimeout(timeoutId); + resolve(false); + }); + httpRequest.on("error", () => { + timing.clearTimeout(timeoutId); + resolve(false); + }); + }) + ]); + } + if (sendBody) { + writeBody(httpRequest, request.body); + } +} +__name(writeRequestBody, "writeRequestBody"); +function writeBody(httpRequest, body) { + if (body instanceof import_stream.Readable) { + body.pipe(httpRequest); + return; + } + if (body) { + if (Buffer.isBuffer(body) || typeof body === "string") { + httpRequest.end(body); + return; + } + const uint8 = body; + if (typeof uint8 === "object" && uint8.buffer && typeof uint8.byteOffset === "number" && typeof uint8.byteLength === "number") { + httpRequest.end(Buffer.from(uint8.buffer, uint8.byteOffset, uint8.byteLength)); + return; + } + httpRequest.end(Buffer.from(body)); + return; + } + httpRequest.end(); +} +__name(writeBody, "writeBody"); + +// src/node-http-handler.ts +var DEFAULT_REQUEST_TIMEOUT = 0; +var NodeHttpHandler = class _NodeHttpHandler { + constructor(options) { + this.socketWarningTimestamp = 0; + // Node http handler is hard-coded to http/1.1: https://github.com/nodejs/node/blob/ff5664b83b89c55e4ab5d5f60068fb457f1f5872/lib/_http_server.js#L286 + this.metadata = { handlerProtocol: "http/1.1" }; + this.configProvider = new Promise((resolve, reject) => { + if (typeof options === "function") { + options().then((_options) => { + resolve(this.resolveDefaultConfig(_options)); + }).catch(reject); + } else { + resolve(this.resolveDefaultConfig(options)); + } + }); + } + static { + __name(this, "NodeHttpHandler"); + } + /** + * @returns the input if it is an HttpHandler of any class, + * or instantiates a new instance of this handler. + */ + static create(instanceOrOptions) { + if (typeof instanceOrOptions?.handle === "function") { + return instanceOrOptions; + } + return new _NodeHttpHandler(instanceOrOptions); + } + /** + * @internal + * + * @param agent - http(s) agent in use by the NodeHttpHandler instance. + * @param socketWarningTimestamp - last socket usage check timestamp. + * @param logger - channel for the warning. + * @returns timestamp of last emitted warning. + */ + static checkSocketUsage(agent, socketWarningTimestamp, logger = console) { + const { sockets, requests, maxSockets } = agent; + if (typeof maxSockets !== "number" || maxSockets === Infinity) { + return socketWarningTimestamp; + } + const interval = 15e3; + if (Date.now() - interval < socketWarningTimestamp) { + return socketWarningTimestamp; + } + if (sockets && requests) { + for (const origin in sockets) { + const socketsInUse = sockets[origin]?.length ?? 0; + const requestsEnqueued = requests[origin]?.length ?? 0; + if (socketsInUse >= maxSockets && requestsEnqueued >= 2 * maxSockets) { + logger?.warn?.( + `@smithy/node-http-handler:WARN - socket usage at capacity=${socketsInUse} and ${requestsEnqueued} additional requests are enqueued. +See https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/node-configuring-maxsockets.html +or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler config.` + ); + return Date.now(); + } + } + } + return socketWarningTimestamp; + } + resolveDefaultConfig(options) { + const { requestTimeout, connectionTimeout, socketTimeout, socketAcquisitionWarningTimeout, httpAgent, httpsAgent } = options || {}; + const keepAlive = true; + const maxSockets = 50; + return { + connectionTimeout, + requestTimeout: requestTimeout ?? socketTimeout, + socketAcquisitionWarningTimeout, + httpAgent: (() => { + if (httpAgent instanceof import_http.Agent || typeof httpAgent?.destroy === "function") { + return httpAgent; + } + return new import_http.Agent({ keepAlive, maxSockets, ...httpAgent }); + })(), + httpsAgent: (() => { + if (httpsAgent instanceof import_https.Agent || typeof httpsAgent?.destroy === "function") { + return httpsAgent; + } + return new import_https.Agent({ keepAlive, maxSockets, ...httpsAgent }); + })(), + logger: console + }; + } + destroy() { + this.config?.httpAgent?.destroy(); + this.config?.httpsAgent?.destroy(); + } + async handle(request, { abortSignal, requestTimeout } = {}) { + if (!this.config) { + this.config = await this.configProvider; + } + return new Promise((_resolve, _reject) => { + let writeRequestBodyPromise = void 0; + const timeouts = []; + const resolve = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + timeouts.forEach(timing.clearTimeout); + _resolve(arg); + }, "resolve"); + const reject = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + timeouts.forEach(timing.clearTimeout); + _reject(arg); + }, "reject"); + if (!this.config) { + throw new Error("Node HTTP request handler config is not resolved"); + } + if (abortSignal?.aborted) { + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + return; + } + const isSSL = request.protocol === "https:"; + const agent = isSSL ? this.config.httpsAgent : this.config.httpAgent; + timeouts.push( + timing.setTimeout( + () => { + this.socketWarningTimestamp = _NodeHttpHandler.checkSocketUsage( + agent, + this.socketWarningTimestamp, + this.config.logger + ); + }, + this.config.socketAcquisitionWarningTimeout ?? (this.config.requestTimeout ?? 2e3) + (this.config.connectionTimeout ?? 1e3) + ) + ); + const queryString = (0, import_querystring_builder.buildQueryString)(request.query || {}); + let auth = void 0; + if (request.username != null || request.password != null) { + const username = request.username ?? ""; + const password = request.password ?? ""; + auth = `${username}:${password}`; + } + let path = request.path; + if (queryString) { + path += `?${queryString}`; + } + if (request.fragment) { + path += `#${request.fragment}`; + } + let hostname = request.hostname ?? ""; + if (hostname[0] === "[" && hostname.endsWith("]")) { + hostname = request.hostname.slice(1, -1); + } else { + hostname = request.hostname; + } + const nodeHttpsOptions = { + headers: request.headers, + host: hostname, + method: request.method, + path, + port: request.port, + agent, + auth + }; + const requestFunc = isSSL ? import_https.request : import_http.request; + const req = requestFunc(nodeHttpsOptions, (res) => { + const httpResponse = new import_protocol_http.HttpResponse({ + statusCode: res.statusCode || -1, + reason: res.statusMessage, + headers: getTransformedHeaders(res.headers), + body: res + }); + resolve({ response: httpResponse }); + }); + req.on("error", (err) => { + if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) { + reject(Object.assign(err, { name: "TimeoutError" })); + } else { + reject(err); + } + }); + if (abortSignal) { + const onAbort = /* @__PURE__ */ __name(() => { + req.destroy(); + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + }, "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + const signal = abortSignal; + signal.addEventListener("abort", onAbort, { once: true }); + req.once("close", () => signal.removeEventListener("abort", onAbort)); + } else { + abortSignal.onabort = onAbort; + } + } + const effectiveRequestTimeout = requestTimeout ?? this.config.requestTimeout; + timeouts.push(setConnectionTimeout(req, reject, this.config.connectionTimeout)); + timeouts.push(setSocketTimeout(req, reject, effectiveRequestTimeout)); + const httpAgent = nodeHttpsOptions.agent; + if (typeof httpAgent === "object" && "keepAlive" in httpAgent) { + timeouts.push( + setSocketKeepAlive(req, { + // @ts-expect-error keepAlive is not public on httpAgent. + keepAlive: httpAgent.keepAlive, + // @ts-expect-error keepAliveMsecs is not public on httpAgent. + keepAliveMsecs: httpAgent.keepAliveMsecs + }) + ); + } + writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout).catch((e) => { + timeouts.forEach(timing.clearTimeout); + return _reject(e); + }); + }); + } + updateHttpClientConfig(key, value) { + this.config = void 0; + this.configProvider = this.configProvider.then((config) => { + return { + ...config, + [key]: value + }; + }); + } + httpHandlerConfigs() { + return this.config ?? {}; + } +}; + +// src/node-http2-handler.ts + + +var import_http22 = __nccwpck_require__(85675); + +// src/node-http2-connection-manager.ts +var import_http2 = __toESM(__nccwpck_require__(85675)); + +// src/node-http2-connection-pool.ts +var NodeHttp2ConnectionPool = class { + constructor(sessions) { + this.sessions = []; + this.sessions = sessions ?? []; + } + static { + __name(this, "NodeHttp2ConnectionPool"); + } + poll() { + if (this.sessions.length > 0) { + return this.sessions.shift(); + } + } + offerLast(session) { + this.sessions.push(session); + } + contains(session) { + return this.sessions.includes(session); + } + remove(session) { + this.sessions = this.sessions.filter((s) => s !== session); + } + [Symbol.iterator]() { + return this.sessions[Symbol.iterator](); + } + destroy(connection) { + for (const session of this.sessions) { + if (session === connection) { + if (!session.destroyed) { + session.destroy(); + } + } + } + } +}; + +// src/node-http2-connection-manager.ts +var NodeHttp2ConnectionManager = class { + constructor(config) { + this.sessionCache = /* @__PURE__ */ new Map(); + this.config = config; + if (this.config.maxConcurrency && this.config.maxConcurrency <= 0) { + throw new RangeError("maxConcurrency must be greater than zero."); + } + } + static { + __name(this, "NodeHttp2ConnectionManager"); + } + lease(requestContext, connectionConfiguration) { + const url = this.getUrlString(requestContext); + const existingPool = this.sessionCache.get(url); + if (existingPool) { + const existingSession = existingPool.poll(); + if (existingSession && !this.config.disableConcurrency) { + return existingSession; + } + } + const session = import_http2.default.connect(url); + if (this.config.maxConcurrency) { + session.settings({ maxConcurrentStreams: this.config.maxConcurrency }, (err) => { + if (err) { + throw new Error( + "Fail to set maxConcurrentStreams to " + this.config.maxConcurrency + "when creating new session for " + requestContext.destination.toString() + ); + } + }); + } + session.unref(); + const destroySessionCb = /* @__PURE__ */ __name(() => { + session.destroy(); + this.deleteSession(url, session); + }, "destroySessionCb"); + session.on("goaway", destroySessionCb); + session.on("error", destroySessionCb); + session.on("frameError", destroySessionCb); + session.on("close", () => this.deleteSession(url, session)); + if (connectionConfiguration.requestTimeout) { + session.setTimeout(connectionConfiguration.requestTimeout, destroySessionCb); + } + const connectionPool = this.sessionCache.get(url) || new NodeHttp2ConnectionPool(); + connectionPool.offerLast(session); + this.sessionCache.set(url, connectionPool); + return session; + } + /** + * Delete a session from the connection pool. + * @param authority The authority of the session to delete. + * @param session The session to delete. + */ + deleteSession(authority, session) { + const existingConnectionPool = this.sessionCache.get(authority); + if (!existingConnectionPool) { + return; + } + if (!existingConnectionPool.contains(session)) { + return; + } + existingConnectionPool.remove(session); + this.sessionCache.set(authority, existingConnectionPool); + } + release(requestContext, session) { + const cacheKey = this.getUrlString(requestContext); + this.sessionCache.get(cacheKey)?.offerLast(session); + } + destroy() { + for (const [key, connectionPool] of this.sessionCache) { + for (const session of connectionPool) { + if (!session.destroyed) { + session.destroy(); + } + connectionPool.remove(session); + } + this.sessionCache.delete(key); + } + } + setMaxConcurrentStreams(maxConcurrentStreams) { + if (maxConcurrentStreams && maxConcurrentStreams <= 0) { + throw new RangeError("maxConcurrentStreams must be greater than zero."); + } + this.config.maxConcurrency = maxConcurrentStreams; + } + setDisableConcurrentStreams(disableConcurrentStreams) { + this.config.disableConcurrency = disableConcurrentStreams; + } + getUrlString(request) { + return request.destination.toString(); + } +}; + +// src/node-http2-handler.ts +var NodeHttp2Handler = class _NodeHttp2Handler { + constructor(options) { + this.metadata = { handlerProtocol: "h2" }; + this.connectionManager = new NodeHttp2ConnectionManager({}); + this.configProvider = new Promise((resolve, reject) => { + if (typeof options === "function") { + options().then((opts) => { + resolve(opts || {}); + }).catch(reject); + } else { + resolve(options || {}); + } + }); + } + static { + __name(this, "NodeHttp2Handler"); + } + /** + * @returns the input if it is an HttpHandler of any class, + * or instantiates a new instance of this handler. + */ + static create(instanceOrOptions) { + if (typeof instanceOrOptions?.handle === "function") { + return instanceOrOptions; + } + return new _NodeHttp2Handler(instanceOrOptions); + } + destroy() { + this.connectionManager.destroy(); + } + async handle(request, { abortSignal, requestTimeout } = {}) { + if (!this.config) { + this.config = await this.configProvider; + this.connectionManager.setDisableConcurrentStreams(this.config.disableConcurrentStreams || false); + if (this.config.maxConcurrentStreams) { + this.connectionManager.setMaxConcurrentStreams(this.config.maxConcurrentStreams); + } + } + const { requestTimeout: configRequestTimeout, disableConcurrentStreams } = this.config; + const effectiveRequestTimeout = requestTimeout ?? configRequestTimeout; + return new Promise((_resolve, _reject) => { + let fulfilled = false; + let writeRequestBodyPromise = void 0; + const resolve = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + _resolve(arg); + }, "resolve"); + const reject = /* @__PURE__ */ __name(async (arg) => { + await writeRequestBodyPromise; + _reject(arg); + }, "reject"); + if (abortSignal?.aborted) { + fulfilled = true; + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + reject(abortError); + return; + } + const { hostname, method, port, protocol, query } = request; + let auth = ""; + if (request.username != null || request.password != null) { + const username = request.username ?? ""; + const password = request.password ?? ""; + auth = `${username}:${password}@`; + } + const authority = `${protocol}//${auth}${hostname}${port ? `:${port}` : ""}`; + const requestContext = { destination: new URL(authority) }; + const session = this.connectionManager.lease(requestContext, { + requestTimeout: this.config?.sessionTimeout, + disableConcurrentStreams: disableConcurrentStreams || false + }); + const rejectWithDestroy = /* @__PURE__ */ __name((err) => { + if (disableConcurrentStreams) { + this.destroySession(session); + } + fulfilled = true; + reject(err); + }, "rejectWithDestroy"); + const queryString = (0, import_querystring_builder.buildQueryString)(query || {}); + let path = request.path; + if (queryString) { + path += `?${queryString}`; + } + if (request.fragment) { + path += `#${request.fragment}`; + } + const req = session.request({ + ...request.headers, + [import_http22.constants.HTTP2_HEADER_PATH]: path, + [import_http22.constants.HTTP2_HEADER_METHOD]: method + }); + session.ref(); + req.on("response", (headers) => { + const httpResponse = new import_protocol_http.HttpResponse({ + statusCode: headers[":status"] || -1, + headers: getTransformedHeaders(headers), + body: req + }); + fulfilled = true; + resolve({ response: httpResponse }); + if (disableConcurrentStreams) { + session.close(); + this.connectionManager.deleteSession(authority, session); + } + }); + if (effectiveRequestTimeout) { + req.setTimeout(effectiveRequestTimeout, () => { + req.close(); + const timeoutError = new Error(`Stream timed out because of no activity for ${effectiveRequestTimeout} ms`); + timeoutError.name = "TimeoutError"; + rejectWithDestroy(timeoutError); + }); + } + if (abortSignal) { + const onAbort = /* @__PURE__ */ __name(() => { + req.close(); + const abortError = new Error("Request aborted"); + abortError.name = "AbortError"; + rejectWithDestroy(abortError); + }, "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + const signal = abortSignal; + signal.addEventListener("abort", onAbort, { once: true }); + req.once("close", () => signal.removeEventListener("abort", onAbort)); + } else { + abortSignal.onabort = onAbort; + } + } + req.on("frameError", (type, code, id) => { + rejectWithDestroy(new Error(`Frame type id ${type} in stream id ${id} has failed with code ${code}.`)); + }); + req.on("error", rejectWithDestroy); + req.on("aborted", () => { + rejectWithDestroy( + new Error(`HTTP/2 stream is abnormally aborted in mid-communication with result code ${req.rstCode}.`) + ); + }); + req.on("close", () => { + session.unref(); + if (disableConcurrentStreams) { + session.destroy(); + } + if (!fulfilled) { + rejectWithDestroy(new Error("Unexpected error: http2 request did not get a response")); + } + }); + writeRequestBodyPromise = writeRequestBody(req, request, effectiveRequestTimeout); + }); + } + updateHttpClientConfig(key, value) { + this.config = void 0; + this.configProvider = this.configProvider.then((config) => { + return { + ...config, + [key]: value + }; + }); + } + httpHandlerConfigs() { + return this.config ?? {}; + } + /** + * Destroys a session. + * @param session - the session to destroy. + */ + destroySession(session) { + if (!session.destroyed) { + session.destroy(); + } + } +}; + +// src/stream-collector/collector.ts + +var Collector = class extends import_stream.Writable { + constructor() { + super(...arguments); + this.bufferedBytes = []; + } + static { + __name(this, "Collector"); + } + _write(chunk, encoding, callback) { + this.bufferedBytes.push(chunk); + callback(); + } +}; + +// src/stream-collector/index.ts +var streamCollector = /* @__PURE__ */ __name((stream) => { + if (isReadableStreamInstance(stream)) { + return collectReadableStream(stream); + } + return new Promise((resolve, reject) => { + const collector = new Collector(); + stream.pipe(collector); + stream.on("error", (err) => { + collector.end(); + reject(err); + }); + collector.on("error", reject); + collector.on("finish", function() { + const bytes = new Uint8Array(Buffer.concat(this.bufferedBytes)); + resolve(bytes); + }); + }); +}, "streamCollector"); +var isReadableStreamInstance = /* @__PURE__ */ __name((stream) => typeof ReadableStream === "function" && stream instanceof ReadableStream, "isReadableStreamInstance"); +async function collectReadableStream(stream) { + const chunks = []; + const reader = stream.getReader(); + let isDone = false; + let length = 0; + while (!isDone) { + const { done, value } = await reader.read(); + if (value) { + chunks.push(value); + length += value.length; + } + isDone = done; + } + const collected = new Uint8Array(length); + let offset = 0; + for (const chunk of chunks) { + collected.set(chunk, offset); + offset += chunk.length; + } + return collected; +} +__name(collectReadableStream, "collectReadableStream"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 71238: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + CredentialsProviderError: () => CredentialsProviderError, + ProviderError: () => ProviderError, + TokenProviderError: () => TokenProviderError, + chain: () => chain, + fromStatic: () => fromStatic, + memoize: () => memoize +}); +module.exports = __toCommonJS(src_exports); + +// src/ProviderError.ts +var ProviderError = class _ProviderError extends Error { + constructor(message, options = true) { + let logger; + let tryNextLink = true; + if (typeof options === "boolean") { + logger = void 0; + tryNextLink = options; + } else if (options != null && typeof options === "object") { + logger = options.logger; + tryNextLink = options.tryNextLink ?? true; + } + super(message); + this.name = "ProviderError"; + this.tryNextLink = tryNextLink; + Object.setPrototypeOf(this, _ProviderError.prototype); + logger?.debug?.(`@smithy/property-provider ${tryNextLink ? "->" : "(!)"} ${message}`); + } + static { + __name(this, "ProviderError"); + } + /** + * @deprecated use new operator. + */ + static from(error, options = true) { + return Object.assign(new this(error.message, options), error); + } +}; + +// src/CredentialsProviderError.ts +var CredentialsProviderError = class _CredentialsProviderError extends ProviderError { + /** + * @override + */ + constructor(message, options = true) { + super(message, options); + this.name = "CredentialsProviderError"; + Object.setPrototypeOf(this, _CredentialsProviderError.prototype); + } + static { + __name(this, "CredentialsProviderError"); + } +}; + +// src/TokenProviderError.ts +var TokenProviderError = class _TokenProviderError extends ProviderError { + /** + * @override + */ + constructor(message, options = true) { + super(message, options); + this.name = "TokenProviderError"; + Object.setPrototypeOf(this, _TokenProviderError.prototype); + } + static { + __name(this, "TokenProviderError"); + } +}; + +// src/chain.ts +var chain = /* @__PURE__ */ __name((...providers) => async () => { + if (providers.length === 0) { + throw new ProviderError("No providers in chain"); + } + let lastProviderError; + for (const provider of providers) { + try { + const credentials = await provider(); + return credentials; + } catch (err) { + lastProviderError = err; + if (err?.tryNextLink) { + continue; + } + throw err; + } + } + throw lastProviderError; +}, "chain"); + +// src/fromStatic.ts +var fromStatic = /* @__PURE__ */ __name((staticValue) => () => Promise.resolve(staticValue), "fromStatic"); + +// src/memoize.ts +var memoize = /* @__PURE__ */ __name((provider, isExpired, requiresRefresh) => { + let resolved; + let pending; + let hasResult; + let isConstant = false; + const coalesceProvider = /* @__PURE__ */ __name(async () => { + if (!pending) { + pending = provider(); + } + try { + resolved = await pending; + hasResult = true; + isConstant = false; + } finally { + pending = void 0; + } + return resolved; + }, "coalesceProvider"); + if (isExpired === void 0) { + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(); + } + return resolved; + }; + } + return async (options) => { + if (!hasResult || options?.forceRefresh) { + resolved = await coalesceProvider(); + } + if (isConstant) { + return resolved; + } + if (requiresRefresh && !requiresRefresh(resolved)) { + isConstant = true; + return resolved; + } + if (isExpired(resolved)) { + await coalesceProvider(); + return resolved; + } + return resolved; + }; +}, "memoize"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 72356: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Field: () => Field, + Fields: () => Fields, + HttpRequest: () => HttpRequest, + HttpResponse: () => HttpResponse, + IHttpRequest: () => import_types.HttpRequest, + getHttpHandlerExtensionConfiguration: () => getHttpHandlerExtensionConfiguration, + isValidHostname: () => isValidHostname, + resolveHttpHandlerRuntimeConfig: () => resolveHttpHandlerRuntimeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/extensions/httpExtensionConfiguration.ts +var getHttpHandlerExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return { + setHttpHandler(handler) { + runtimeConfig.httpHandler = handler; + }, + httpHandler() { + return runtimeConfig.httpHandler; + }, + updateHttpClientConfig(key, value) { + runtimeConfig.httpHandler?.updateHttpClientConfig(key, value); + }, + httpHandlerConfigs() { + return runtimeConfig.httpHandler.httpHandlerConfigs(); + } + }; +}, "getHttpHandlerExtensionConfiguration"); +var resolveHttpHandlerRuntimeConfig = /* @__PURE__ */ __name((httpHandlerExtensionConfiguration) => { + return { + httpHandler: httpHandlerExtensionConfiguration.httpHandler() + }; +}, "resolveHttpHandlerRuntimeConfig"); + +// src/Field.ts +var import_types = __nccwpck_require__(90690); +var Field = class { + static { + __name(this, "Field"); + } + constructor({ name, kind = import_types.FieldPosition.HEADER, values = [] }) { + this.name = name; + this.kind = kind; + this.values = values; + } + /** + * Appends a value to the field. + * + * @param value The value to append. + */ + add(value) { + this.values.push(value); + } + /** + * Overwrite existing field values. + * + * @param values The new field values. + */ + set(values) { + this.values = values; + } + /** + * Remove all matching entries from list. + * + * @param value Value to remove. + */ + remove(value) { + this.values = this.values.filter((v) => v !== value); + } + /** + * Get comma-delimited string. + * + * @returns String representation of {@link Field}. + */ + toString() { + return this.values.map((v) => v.includes(",") || v.includes(" ") ? `"${v}"` : v).join(", "); + } + /** + * Get string values as a list + * + * @returns Values in {@link Field} as a list. + */ + get() { + return this.values; + } +}; + +// src/Fields.ts +var Fields = class { + constructor({ fields = [], encoding = "utf-8" }) { + this.entries = {}; + fields.forEach(this.setField.bind(this)); + this.encoding = encoding; + } + static { + __name(this, "Fields"); + } + /** + * Set entry for a {@link Field} name. The `name` + * attribute will be used to key the collection. + * + * @param field The {@link Field} to set. + */ + setField(field) { + this.entries[field.name.toLowerCase()] = field; + } + /** + * Retrieve {@link Field} entry by name. + * + * @param name The name of the {@link Field} entry + * to retrieve + * @returns The {@link Field} if it exists. + */ + getField(name) { + return this.entries[name.toLowerCase()]; + } + /** + * Delete entry from collection. + * + * @param name Name of the entry to delete. + */ + removeField(name) { + delete this.entries[name.toLowerCase()]; + } + /** + * Helper function for retrieving specific types of fields. + * Used to grab all headers or all trailers. + * + * @param kind {@link FieldPosition} of entries to retrieve. + * @returns The {@link Field} entries with the specified + * {@link FieldPosition}. + */ + getByType(kind) { + return Object.values(this.entries).filter((field) => field.kind === kind); + } +}; + +// src/httpRequest.ts + +var HttpRequest = class _HttpRequest { + static { + __name(this, "HttpRequest"); + } + constructor(options) { + this.method = options.method || "GET"; + this.hostname = options.hostname || "localhost"; + this.port = options.port; + this.query = options.query || {}; + this.headers = options.headers || {}; + this.body = options.body; + this.protocol = options.protocol ? options.protocol.slice(-1) !== ":" ? `${options.protocol}:` : options.protocol : "https:"; + this.path = options.path ? options.path.charAt(0) !== "/" ? `/${options.path}` : options.path : "/"; + this.username = options.username; + this.password = options.password; + this.fragment = options.fragment; + } + /** + * Note: this does not deep-clone the body. + */ + static clone(request) { + const cloned = new _HttpRequest({ + ...request, + headers: { ...request.headers } + }); + if (cloned.query) { + cloned.query = cloneQuery(cloned.query); + } + return cloned; + } + /** + * This method only actually asserts that request is the interface {@link IHttpRequest}, + * and not necessarily this concrete class. Left in place for API stability. + * + * Do not call instance methods on the input of this function, and + * do not assume it has the HttpRequest prototype. + */ + static isInstance(request) { + if (!request) { + return false; + } + const req = request; + return "method" in req && "protocol" in req && "hostname" in req && "path" in req && typeof req["query"] === "object" && typeof req["headers"] === "object"; + } + /** + * @deprecated use static HttpRequest.clone(request) instead. It's not safe to call + * this method because {@link HttpRequest.isInstance} incorrectly + * asserts that IHttpRequest (interface) objects are of type HttpRequest (class). + */ + clone() { + return _HttpRequest.clone(this); + } +}; +function cloneQuery(query) { + return Object.keys(query).reduce((carry, paramName) => { + const param = query[paramName]; + return { + ...carry, + [paramName]: Array.isArray(param) ? [...param] : param + }; + }, {}); +} +__name(cloneQuery, "cloneQuery"); + +// src/httpResponse.ts +var HttpResponse = class { + static { + __name(this, "HttpResponse"); + } + constructor(options) { + this.statusCode = options.statusCode; + this.reason = options.reason; + this.headers = options.headers || {}; + this.body = options.body; + } + static isInstance(response) { + if (!response) + return false; + const resp = response; + return typeof resp.statusCode === "number" && typeof resp.headers === "object"; + } +}; + +// src/isValidHostname.ts +function isValidHostname(hostname) { + const hostPattern = /^[a-z0-9][a-z0-9\.\-]*[a-z0-9]$/; + return hostPattern.test(hostname); +} +__name(isValidHostname, "isValidHostname"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 18256: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + buildQueryString: () => buildQueryString +}); +module.exports = __toCommonJS(src_exports); +var import_util_uri_escape = __nccwpck_require__(80146); +function buildQueryString(query) { + const parts = []; + for (let key of Object.keys(query).sort()) { + const value = query[key]; + key = (0, import_util_uri_escape.escapeUri)(key); + if (Array.isArray(value)) { + for (let i = 0, iLen = value.length; i < iLen; i++) { + parts.push(`${key}=${(0, import_util_uri_escape.escapeUri)(value[i])}`); + } + } else { + let qsEntry = key; + if (value || typeof value === "string") { + qsEntry += `=${(0, import_util_uri_escape.escapeUri)(value)}`; + } + parts.push(qsEntry); + } + } + return parts.join("&"); +} +__name(buildQueryString, "buildQueryString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 18822: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + parseQueryString: () => parseQueryString +}); +module.exports = __toCommonJS(src_exports); +function parseQueryString(querystring) { + const query = {}; + querystring = querystring.replace(/^\?/, ""); + if (querystring) { + for (const pair of querystring.split("&")) { + let [key, value = null] = pair.split("="); + key = decodeURIComponent(key); + if (value) { + value = decodeURIComponent(value); + } + if (!(key in query)) { + query[key] = value; + } else if (Array.isArray(query[key])) { + query[key].push(value); + } else { + query[key] = [query[key], value]; + } + } + } + return query; +} +__name(parseQueryString, "parseQueryString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 42058: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + isBrowserNetworkError: () => isBrowserNetworkError, + isClockSkewCorrectedError: () => isClockSkewCorrectedError, + isClockSkewError: () => isClockSkewError, + isRetryableByTrait: () => isRetryableByTrait, + isServerError: () => isServerError, + isThrottlingError: () => isThrottlingError, + isTransientError: () => isTransientError +}); +module.exports = __toCommonJS(src_exports); + +// src/constants.ts +var CLOCK_SKEW_ERROR_CODES = [ + "AuthFailure", + "InvalidSignatureException", + "RequestExpired", + "RequestInTheFuture", + "RequestTimeTooSkewed", + "SignatureDoesNotMatch" +]; +var THROTTLING_ERROR_CODES = [ + "BandwidthLimitExceeded", + "EC2ThrottledException", + "LimitExceededException", + "PriorRequestNotComplete", + "ProvisionedThroughputExceededException", + "RequestLimitExceeded", + "RequestThrottled", + "RequestThrottledException", + "SlowDown", + "ThrottledException", + "Throttling", + "ThrottlingException", + "TooManyRequestsException", + "TransactionInProgressException" + // DynamoDB +]; +var TRANSIENT_ERROR_CODES = ["TimeoutError", "RequestTimeout", "RequestTimeoutException"]; +var TRANSIENT_ERROR_STATUS_CODES = [500, 502, 503, 504]; +var NODEJS_TIMEOUT_ERROR_CODES = ["ECONNRESET", "ECONNREFUSED", "EPIPE", "ETIMEDOUT"]; +var NODEJS_NETWORK_ERROR_CODES = ["EHOSTUNREACH", "ENETUNREACH", "ENOTFOUND"]; + +// src/index.ts +var isRetryableByTrait = /* @__PURE__ */ __name((error) => error.$retryable !== void 0, "isRetryableByTrait"); +var isClockSkewError = /* @__PURE__ */ __name((error) => CLOCK_SKEW_ERROR_CODES.includes(error.name), "isClockSkewError"); +var isClockSkewCorrectedError = /* @__PURE__ */ __name((error) => error.$metadata?.clockSkewCorrected, "isClockSkewCorrectedError"); +var isBrowserNetworkError = /* @__PURE__ */ __name((error) => { + const errorMessages = /* @__PURE__ */ new Set([ + "Failed to fetch", + // Chrome + "NetworkError when attempting to fetch resource", + // Firefox + "The Internet connection appears to be offline", + // Safari 16 + "Load failed", + // Safari 17+ + "Network request failed" + // `cross-fetch` + ]); + const isValid = error && error instanceof TypeError; + if (!isValid) { + return false; + } + return errorMessages.has(error.message); +}, "isBrowserNetworkError"); +var isThrottlingError = /* @__PURE__ */ __name((error) => error.$metadata?.httpStatusCode === 429 || THROTTLING_ERROR_CODES.includes(error.name) || error.$retryable?.throttling == true, "isThrottlingError"); +var isTransientError = /* @__PURE__ */ __name((error, depth = 0) => isClockSkewCorrectedError(error) || TRANSIENT_ERROR_CODES.includes(error.name) || NODEJS_TIMEOUT_ERROR_CODES.includes(error?.code || "") || NODEJS_NETWORK_ERROR_CODES.includes(error?.code || "") || TRANSIENT_ERROR_STATUS_CODES.includes(error.$metadata?.httpStatusCode || 0) || isBrowserNetworkError(error) || error.cause !== void 0 && depth <= 10 && isTransientError(error.cause, depth + 1), "isTransientError"); +var isServerError = /* @__PURE__ */ __name((error) => { + if (error.$metadata?.httpStatusCode !== void 0) { + const statusCode = error.$metadata.httpStatusCode; + if (500 <= statusCode && statusCode <= 599 && !isTransientError(error)) { + return true; + } + return false; + } + return false; +}, "isServerError"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 54172: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getHomeDir = void 0; +const os_1 = __nccwpck_require__(70857); +const path_1 = __nccwpck_require__(16928); +const homeDirCache = {}; +const getHomeDirCacheKey = () => { + if (process && process.geteuid) { + return `${process.geteuid()}`; + } + return "DEFAULT"; +}; +const getHomeDir = () => { + const { HOME, USERPROFILE, HOMEPATH, HOMEDRIVE = `C:${path_1.sep}` } = process.env; + if (HOME) + return HOME; + if (USERPROFILE) + return USERPROFILE; + if (HOMEPATH) + return `${HOMEDRIVE}${HOMEPATH}`; + const homeDirCacheKey = getHomeDirCacheKey(); + if (!homeDirCache[homeDirCacheKey]) + homeDirCache[homeDirCacheKey] = (0, os_1.homedir)(); + return homeDirCache[homeDirCacheKey]; +}; +exports.getHomeDir = getHomeDir; + + +/***/ }), + +/***/ 20269: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getSSOTokenFilepath = void 0; +const crypto_1 = __nccwpck_require__(76982); +const path_1 = __nccwpck_require__(16928); +const getHomeDir_1 = __nccwpck_require__(54172); +const getSSOTokenFilepath = (id) => { + const hasher = (0, crypto_1.createHash)("sha1"); + const cacheName = hasher.update(id).digest("hex"); + return (0, path_1.join)((0, getHomeDir_1.getHomeDir)(), ".aws", "sso", "cache", `${cacheName}.json`); +}; +exports.getSSOTokenFilepath = getSSOTokenFilepath; + + +/***/ }), + +/***/ 11326: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getSSOTokenFromFile = void 0; +const fs_1 = __nccwpck_require__(79896); +const getSSOTokenFilepath_1 = __nccwpck_require__(20269); +const { readFile } = fs_1.promises; +const getSSOTokenFromFile = async (id) => { + const ssoTokenFilepath = (0, getSSOTokenFilepath_1.getSSOTokenFilepath)(id); + const ssoTokenText = await readFile(ssoTokenFilepath, "utf8"); + return JSON.parse(ssoTokenText); +}; +exports.getSSOTokenFromFile = getSSOTokenFromFile; + + +/***/ }), + +/***/ 94964: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + CONFIG_PREFIX_SEPARATOR: () => CONFIG_PREFIX_SEPARATOR, + DEFAULT_PROFILE: () => DEFAULT_PROFILE, + ENV_PROFILE: () => ENV_PROFILE, + getProfileName: () => getProfileName, + loadSharedConfigFiles: () => loadSharedConfigFiles, + loadSsoSessionData: () => loadSsoSessionData, + parseKnownFiles: () => parseKnownFiles +}); +module.exports = __toCommonJS(src_exports); +__reExport(src_exports, __nccwpck_require__(54172), module.exports); + +// src/getProfileName.ts +var ENV_PROFILE = "AWS_PROFILE"; +var DEFAULT_PROFILE = "default"; +var getProfileName = /* @__PURE__ */ __name((init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE, "getProfileName"); + +// src/index.ts +__reExport(src_exports, __nccwpck_require__(20269), module.exports); +__reExport(src_exports, __nccwpck_require__(11326), module.exports); + +// src/loadSharedConfigFiles.ts + + +// src/getConfigData.ts +var import_types = __nccwpck_require__(90690); +var getConfigData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => { + const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR); + if (indexOfSeparator === -1) { + return false; + } + return Object.values(import_types.IniSectionType).includes(key.substring(0, indexOfSeparator)); +}).reduce( + (acc, [key, value]) => { + const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR); + const updatedKey = key.substring(0, indexOfSeparator) === import_types.IniSectionType.PROFILE ? key.substring(indexOfSeparator + 1) : key; + acc[updatedKey] = value; + return acc; + }, + { + // Populate default profile, if present. + ...data.default && { default: data.default } + } +), "getConfigData"); + +// src/getConfigFilepath.ts +var import_path = __nccwpck_require__(16928); +var import_getHomeDir = __nccwpck_require__(54172); +var ENV_CONFIG_PATH = "AWS_CONFIG_FILE"; +var getConfigFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CONFIG_PATH] || (0, import_path.join)((0, import_getHomeDir.getHomeDir)(), ".aws", "config"), "getConfigFilepath"); + +// src/getCredentialsFilepath.ts + +var import_getHomeDir2 = __nccwpck_require__(54172); +var ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE"; +var getCredentialsFilepath = /* @__PURE__ */ __name(() => process.env[ENV_CREDENTIALS_PATH] || (0, import_path.join)((0, import_getHomeDir2.getHomeDir)(), ".aws", "credentials"), "getCredentialsFilepath"); + +// src/loadSharedConfigFiles.ts +var import_getHomeDir3 = __nccwpck_require__(54172); + +// src/parseIni.ts + +var prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/; +var profileNameBlockList = ["__proto__", "profile __proto__"]; +var parseIni = /* @__PURE__ */ __name((iniData) => { + const map = {}; + let currentSection; + let currentSubSection; + for (const iniLine of iniData.split(/\r?\n/)) { + const trimmedLine = iniLine.split(/(^|\s)[;#]/)[0].trim(); + const isSection = trimmedLine[0] === "[" && trimmedLine[trimmedLine.length - 1] === "]"; + if (isSection) { + currentSection = void 0; + currentSubSection = void 0; + const sectionName = trimmedLine.substring(1, trimmedLine.length - 1); + const matches = prefixKeyRegex.exec(sectionName); + if (matches) { + const [, prefix, , name] = matches; + if (Object.values(import_types.IniSectionType).includes(prefix)) { + currentSection = [prefix, name].join(CONFIG_PREFIX_SEPARATOR); + } + } else { + currentSection = sectionName; + } + if (profileNameBlockList.includes(sectionName)) { + throw new Error(`Found invalid profile name "${sectionName}"`); + } + } else if (currentSection) { + const indexOfEqualsSign = trimmedLine.indexOf("="); + if (![0, -1].includes(indexOfEqualsSign)) { + const [name, value] = [ + trimmedLine.substring(0, indexOfEqualsSign).trim(), + trimmedLine.substring(indexOfEqualsSign + 1).trim() + ]; + if (value === "") { + currentSubSection = name; + } else { + if (currentSubSection && iniLine.trimStart() === iniLine) { + currentSubSection = void 0; + } + map[currentSection] = map[currentSection] || {}; + const key = currentSubSection ? [currentSubSection, name].join(CONFIG_PREFIX_SEPARATOR) : name; + map[currentSection][key] = value; + } + } + } + } + return map; +}, "parseIni"); + +// src/loadSharedConfigFiles.ts +var import_slurpFile = __nccwpck_require__(54246); +var swallowError = /* @__PURE__ */ __name(() => ({}), "swallowError"); +var CONFIG_PREFIX_SEPARATOR = "."; +var loadSharedConfigFiles = /* @__PURE__ */ __name(async (init = {}) => { + const { filepath = getCredentialsFilepath(), configFilepath = getConfigFilepath() } = init; + const homeDir = (0, import_getHomeDir3.getHomeDir)(); + const relativeHomeDirPrefix = "~/"; + let resolvedFilepath = filepath; + if (filepath.startsWith(relativeHomeDirPrefix)) { + resolvedFilepath = (0, import_path.join)(homeDir, filepath.slice(2)); + } + let resolvedConfigFilepath = configFilepath; + if (configFilepath.startsWith(relativeHomeDirPrefix)) { + resolvedConfigFilepath = (0, import_path.join)(homeDir, configFilepath.slice(2)); + } + const parsedFiles = await Promise.all([ + (0, import_slurpFile.slurpFile)(resolvedConfigFilepath, { + ignoreCache: init.ignoreCache + }).then(parseIni).then(getConfigData).catch(swallowError), + (0, import_slurpFile.slurpFile)(resolvedFilepath, { + ignoreCache: init.ignoreCache + }).then(parseIni).catch(swallowError) + ]); + return { + configFile: parsedFiles[0], + credentialsFile: parsedFiles[1] + }; +}, "loadSharedConfigFiles"); + +// src/getSsoSessionData.ts + +var getSsoSessionData = /* @__PURE__ */ __name((data) => Object.entries(data).filter(([key]) => key.startsWith(import_types.IniSectionType.SSO_SESSION + CONFIG_PREFIX_SEPARATOR)).reduce((acc, [key, value]) => ({ ...acc, [key.substring(key.indexOf(CONFIG_PREFIX_SEPARATOR) + 1)]: value }), {}), "getSsoSessionData"); + +// src/loadSsoSessionData.ts +var import_slurpFile2 = __nccwpck_require__(54246); +var swallowError2 = /* @__PURE__ */ __name(() => ({}), "swallowError"); +var loadSsoSessionData = /* @__PURE__ */ __name(async (init = {}) => (0, import_slurpFile2.slurpFile)(init.configFilepath ?? getConfigFilepath()).then(parseIni).then(getSsoSessionData).catch(swallowError2), "loadSsoSessionData"); + +// src/mergeConfigFiles.ts +var mergeConfigFiles = /* @__PURE__ */ __name((...files) => { + const merged = {}; + for (const file of files) { + for (const [key, values] of Object.entries(file)) { + if (merged[key] !== void 0) { + Object.assign(merged[key], values); + } else { + merged[key] = values; + } + } + } + return merged; +}, "mergeConfigFiles"); + +// src/parseKnownFiles.ts +var parseKnownFiles = /* @__PURE__ */ __name(async (init) => { + const parsedFiles = await loadSharedConfigFiles(init); + return mergeConfigFiles(parsedFiles.configFile, parsedFiles.credentialsFile); +}, "parseKnownFiles"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 54246: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.slurpFile = void 0; +const fs_1 = __nccwpck_require__(79896); +const { readFile } = fs_1.promises; +const filePromisesHash = {}; +const slurpFile = (path, options) => { + if (!filePromisesHash[path] || (options === null || options === void 0 ? void 0 : options.ignoreCache)) { + filePromisesHash[path] = readFile(path, "utf8"); + } + return filePromisesHash[path]; +}; +exports.slurpFile = slurpFile; + + +/***/ }), + +/***/ 75118: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + ALGORITHM_IDENTIFIER: () => ALGORITHM_IDENTIFIER, + ALGORITHM_IDENTIFIER_V4A: () => ALGORITHM_IDENTIFIER_V4A, + ALGORITHM_QUERY_PARAM: () => ALGORITHM_QUERY_PARAM, + ALWAYS_UNSIGNABLE_HEADERS: () => ALWAYS_UNSIGNABLE_HEADERS, + AMZ_DATE_HEADER: () => AMZ_DATE_HEADER, + AMZ_DATE_QUERY_PARAM: () => AMZ_DATE_QUERY_PARAM, + AUTH_HEADER: () => AUTH_HEADER, + CREDENTIAL_QUERY_PARAM: () => CREDENTIAL_QUERY_PARAM, + DATE_HEADER: () => DATE_HEADER, + EVENT_ALGORITHM_IDENTIFIER: () => EVENT_ALGORITHM_IDENTIFIER, + EXPIRES_QUERY_PARAM: () => EXPIRES_QUERY_PARAM, + GENERATED_HEADERS: () => GENERATED_HEADERS, + HOST_HEADER: () => HOST_HEADER, + KEY_TYPE_IDENTIFIER: () => KEY_TYPE_IDENTIFIER, + MAX_CACHE_SIZE: () => MAX_CACHE_SIZE, + MAX_PRESIGNED_TTL: () => MAX_PRESIGNED_TTL, + PROXY_HEADER_PATTERN: () => PROXY_HEADER_PATTERN, + REGION_SET_PARAM: () => REGION_SET_PARAM, + SEC_HEADER_PATTERN: () => SEC_HEADER_PATTERN, + SHA256_HEADER: () => SHA256_HEADER, + SIGNATURE_HEADER: () => SIGNATURE_HEADER, + SIGNATURE_QUERY_PARAM: () => SIGNATURE_QUERY_PARAM, + SIGNED_HEADERS_QUERY_PARAM: () => SIGNED_HEADERS_QUERY_PARAM, + SignatureV4: () => SignatureV4, + SignatureV4Base: () => SignatureV4Base, + TOKEN_HEADER: () => TOKEN_HEADER, + TOKEN_QUERY_PARAM: () => TOKEN_QUERY_PARAM, + UNSIGNABLE_PATTERNS: () => UNSIGNABLE_PATTERNS, + UNSIGNED_PAYLOAD: () => UNSIGNED_PAYLOAD, + clearCredentialCache: () => clearCredentialCache, + createScope: () => createScope, + getCanonicalHeaders: () => getCanonicalHeaders, + getCanonicalQuery: () => getCanonicalQuery, + getPayloadHash: () => getPayloadHash, + getSigningKey: () => getSigningKey, + hasHeader: () => hasHeader, + moveHeadersToQuery: () => moveHeadersToQuery, + prepareRequest: () => prepareRequest, + signatureV4aContainer: () => signatureV4aContainer +}); +module.exports = __toCommonJS(src_exports); + +// src/SignatureV4.ts + +var import_util_utf85 = __nccwpck_require__(71577); + +// src/constants.ts +var ALGORITHM_QUERY_PARAM = "X-Amz-Algorithm"; +var CREDENTIAL_QUERY_PARAM = "X-Amz-Credential"; +var AMZ_DATE_QUERY_PARAM = "X-Amz-Date"; +var SIGNED_HEADERS_QUERY_PARAM = "X-Amz-SignedHeaders"; +var EXPIRES_QUERY_PARAM = "X-Amz-Expires"; +var SIGNATURE_QUERY_PARAM = "X-Amz-Signature"; +var TOKEN_QUERY_PARAM = "X-Amz-Security-Token"; +var REGION_SET_PARAM = "X-Amz-Region-Set"; +var AUTH_HEADER = "authorization"; +var AMZ_DATE_HEADER = AMZ_DATE_QUERY_PARAM.toLowerCase(); +var DATE_HEADER = "date"; +var GENERATED_HEADERS = [AUTH_HEADER, AMZ_DATE_HEADER, DATE_HEADER]; +var SIGNATURE_HEADER = SIGNATURE_QUERY_PARAM.toLowerCase(); +var SHA256_HEADER = "x-amz-content-sha256"; +var TOKEN_HEADER = TOKEN_QUERY_PARAM.toLowerCase(); +var HOST_HEADER = "host"; +var ALWAYS_UNSIGNABLE_HEADERS = { + authorization: true, + "cache-control": true, + connection: true, + expect: true, + from: true, + "keep-alive": true, + "max-forwards": true, + pragma: true, + referer: true, + te: true, + trailer: true, + "transfer-encoding": true, + upgrade: true, + "user-agent": true, + "x-amzn-trace-id": true +}; +var PROXY_HEADER_PATTERN = /^proxy-/; +var SEC_HEADER_PATTERN = /^sec-/; +var UNSIGNABLE_PATTERNS = [/^proxy-/i, /^sec-/i]; +var ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256"; +var ALGORITHM_IDENTIFIER_V4A = "AWS4-ECDSA-P256-SHA256"; +var EVENT_ALGORITHM_IDENTIFIER = "AWS4-HMAC-SHA256-PAYLOAD"; +var UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; +var MAX_CACHE_SIZE = 50; +var KEY_TYPE_IDENTIFIER = "aws4_request"; +var MAX_PRESIGNED_TTL = 60 * 60 * 24 * 7; + +// src/credentialDerivation.ts +var import_util_hex_encoding = __nccwpck_require__(96435); +var import_util_utf8 = __nccwpck_require__(71577); +var signingKeyCache = {}; +var cacheQueue = []; +var createScope = /* @__PURE__ */ __name((shortDate, region, service) => `${shortDate}/${region}/${service}/${KEY_TYPE_IDENTIFIER}`, "createScope"); +var getSigningKey = /* @__PURE__ */ __name(async (sha256Constructor, credentials, shortDate, region, service) => { + const credsHash = await hmac(sha256Constructor, credentials.secretAccessKey, credentials.accessKeyId); + const cacheKey = `${shortDate}:${region}:${service}:${(0, import_util_hex_encoding.toHex)(credsHash)}:${credentials.sessionToken}`; + if (cacheKey in signingKeyCache) { + return signingKeyCache[cacheKey]; + } + cacheQueue.push(cacheKey); + while (cacheQueue.length > MAX_CACHE_SIZE) { + delete signingKeyCache[cacheQueue.shift()]; + } + let key = `AWS4${credentials.secretAccessKey}`; + for (const signable of [shortDate, region, service, KEY_TYPE_IDENTIFIER]) { + key = await hmac(sha256Constructor, key, signable); + } + return signingKeyCache[cacheKey] = key; +}, "getSigningKey"); +var clearCredentialCache = /* @__PURE__ */ __name(() => { + cacheQueue.length = 0; + Object.keys(signingKeyCache).forEach((cacheKey) => { + delete signingKeyCache[cacheKey]; + }); +}, "clearCredentialCache"); +var hmac = /* @__PURE__ */ __name((ctor, secret, data) => { + const hash = new ctor(secret); + hash.update((0, import_util_utf8.toUint8Array)(data)); + return hash.digest(); +}, "hmac"); + +// src/getCanonicalHeaders.ts +var getCanonicalHeaders = /* @__PURE__ */ __name(({ headers }, unsignableHeaders, signableHeaders) => { + const canonical = {}; + for (const headerName of Object.keys(headers).sort()) { + if (headers[headerName] == void 0) { + continue; + } + const canonicalHeaderName = headerName.toLowerCase(); + if (canonicalHeaderName in ALWAYS_UNSIGNABLE_HEADERS || unsignableHeaders?.has(canonicalHeaderName) || PROXY_HEADER_PATTERN.test(canonicalHeaderName) || SEC_HEADER_PATTERN.test(canonicalHeaderName)) { + if (!signableHeaders || signableHeaders && !signableHeaders.has(canonicalHeaderName)) { + continue; + } + } + canonical[canonicalHeaderName] = headers[headerName].trim().replace(/\s+/g, " "); + } + return canonical; +}, "getCanonicalHeaders"); + +// src/getPayloadHash.ts +var import_is_array_buffer = __nccwpck_require__(86130); + +var import_util_utf82 = __nccwpck_require__(71577); +var getPayloadHash = /* @__PURE__ */ __name(async ({ headers, body }, hashConstructor) => { + for (const headerName of Object.keys(headers)) { + if (headerName.toLowerCase() === SHA256_HEADER) { + return headers[headerName]; + } + } + if (body == void 0) { + return "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + } else if (typeof body === "string" || ArrayBuffer.isView(body) || (0, import_is_array_buffer.isArrayBuffer)(body)) { + const hashCtor = new hashConstructor(); + hashCtor.update((0, import_util_utf82.toUint8Array)(body)); + return (0, import_util_hex_encoding.toHex)(await hashCtor.digest()); + } + return UNSIGNED_PAYLOAD; +}, "getPayloadHash"); + +// src/HeaderFormatter.ts + +var import_util_utf83 = __nccwpck_require__(71577); +var HeaderFormatter = class { + static { + __name(this, "HeaderFormatter"); + } + format(headers) { + const chunks = []; + for (const headerName of Object.keys(headers)) { + const bytes = (0, import_util_utf83.fromUtf8)(headerName); + chunks.push(Uint8Array.from([bytes.byteLength]), bytes, this.formatHeaderValue(headers[headerName])); + } + const out = new Uint8Array(chunks.reduce((carry, bytes) => carry + bytes.byteLength, 0)); + let position = 0; + for (const chunk of chunks) { + out.set(chunk, position); + position += chunk.byteLength; + } + return out; + } + formatHeaderValue(header) { + switch (header.type) { + case "boolean": + return Uint8Array.from([header.value ? 0 /* boolTrue */ : 1 /* boolFalse */]); + case "byte": + return Uint8Array.from([2 /* byte */, header.value]); + case "short": + const shortView = new DataView(new ArrayBuffer(3)); + shortView.setUint8(0, 3 /* short */); + shortView.setInt16(1, header.value, false); + return new Uint8Array(shortView.buffer); + case "integer": + const intView = new DataView(new ArrayBuffer(5)); + intView.setUint8(0, 4 /* integer */); + intView.setInt32(1, header.value, false); + return new Uint8Array(intView.buffer); + case "long": + const longBytes = new Uint8Array(9); + longBytes[0] = 5 /* long */; + longBytes.set(header.value.bytes, 1); + return longBytes; + case "binary": + const binView = new DataView(new ArrayBuffer(3 + header.value.byteLength)); + binView.setUint8(0, 6 /* byteArray */); + binView.setUint16(1, header.value.byteLength, false); + const binBytes = new Uint8Array(binView.buffer); + binBytes.set(header.value, 3); + return binBytes; + case "string": + const utf8Bytes = (0, import_util_utf83.fromUtf8)(header.value); + const strView = new DataView(new ArrayBuffer(3 + utf8Bytes.byteLength)); + strView.setUint8(0, 7 /* string */); + strView.setUint16(1, utf8Bytes.byteLength, false); + const strBytes = new Uint8Array(strView.buffer); + strBytes.set(utf8Bytes, 3); + return strBytes; + case "timestamp": + const tsBytes = new Uint8Array(9); + tsBytes[0] = 8 /* timestamp */; + tsBytes.set(Int64.fromNumber(header.value.valueOf()).bytes, 1); + return tsBytes; + case "uuid": + if (!UUID_PATTERN.test(header.value)) { + throw new Error(`Invalid UUID received: ${header.value}`); + } + const uuidBytes = new Uint8Array(17); + uuidBytes[0] = 9 /* uuid */; + uuidBytes.set((0, import_util_hex_encoding.fromHex)(header.value.replace(/\-/g, "")), 1); + return uuidBytes; + } + } +}; +var UUID_PATTERN = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/; +var Int64 = class _Int64 { + constructor(bytes) { + this.bytes = bytes; + if (bytes.byteLength !== 8) { + throw new Error("Int64 buffers must be exactly 8 bytes"); + } + } + static { + __name(this, "Int64"); + } + static fromNumber(number) { + if (number > 9223372036854776e3 || number < -9223372036854776e3) { + throw new Error(`${number} is too large (or, if negative, too small) to represent as an Int64`); + } + const bytes = new Uint8Array(8); + for (let i = 7, remaining = Math.abs(Math.round(number)); i > -1 && remaining > 0; i--, remaining /= 256) { + bytes[i] = remaining; + } + if (number < 0) { + negate(bytes); + } + return new _Int64(bytes); + } + /** + * Called implicitly by infix arithmetic operators. + */ + valueOf() { + const bytes = this.bytes.slice(0); + const negative = bytes[0] & 128; + if (negative) { + negate(bytes); + } + return parseInt((0, import_util_hex_encoding.toHex)(bytes), 16) * (negative ? -1 : 1); + } + toString() { + return String(this.valueOf()); + } +}; +function negate(bytes) { + for (let i = 0; i < 8; i++) { + bytes[i] ^= 255; + } + for (let i = 7; i > -1; i--) { + bytes[i]++; + if (bytes[i] !== 0) + break; + } +} +__name(negate, "negate"); + +// src/headerUtil.ts +var hasHeader = /* @__PURE__ */ __name((soughtHeader, headers) => { + soughtHeader = soughtHeader.toLowerCase(); + for (const headerName of Object.keys(headers)) { + if (soughtHeader === headerName.toLowerCase()) { + return true; + } + } + return false; +}, "hasHeader"); + +// src/moveHeadersToQuery.ts +var import_protocol_http = __nccwpck_require__(72356); +var moveHeadersToQuery = /* @__PURE__ */ __name((request, options = {}) => { + const { headers, query = {} } = import_protocol_http.HttpRequest.clone(request); + for (const name of Object.keys(headers)) { + const lname = name.toLowerCase(); + if (lname.slice(0, 6) === "x-amz-" && !options.unhoistableHeaders?.has(lname) || options.hoistableHeaders?.has(lname)) { + query[name] = headers[name]; + delete headers[name]; + } + } + return { + ...request, + headers, + query + }; +}, "moveHeadersToQuery"); + +// src/prepareRequest.ts + +var prepareRequest = /* @__PURE__ */ __name((request) => { + request = import_protocol_http.HttpRequest.clone(request); + for (const headerName of Object.keys(request.headers)) { + if (GENERATED_HEADERS.indexOf(headerName.toLowerCase()) > -1) { + delete request.headers[headerName]; + } + } + return request; +}, "prepareRequest"); + +// src/SignatureV4Base.ts + +var import_util_middleware = __nccwpck_require__(76324); + +var import_util_utf84 = __nccwpck_require__(71577); + +// src/getCanonicalQuery.ts +var import_util_uri_escape = __nccwpck_require__(80146); +var getCanonicalQuery = /* @__PURE__ */ __name(({ query = {} }) => { + const keys = []; + const serialized = {}; + for (const key of Object.keys(query)) { + if (key.toLowerCase() === SIGNATURE_HEADER) { + continue; + } + const encodedKey = (0, import_util_uri_escape.escapeUri)(key); + keys.push(encodedKey); + const value = query[key]; + if (typeof value === "string") { + serialized[encodedKey] = `${encodedKey}=${(0, import_util_uri_escape.escapeUri)(value)}`; + } else if (Array.isArray(value)) { + serialized[encodedKey] = value.slice(0).reduce((encoded, value2) => encoded.concat([`${encodedKey}=${(0, import_util_uri_escape.escapeUri)(value2)}`]), []).sort().join("&"); + } + } + return keys.sort().map((key) => serialized[key]).filter((serialized2) => serialized2).join("&"); +}, "getCanonicalQuery"); + +// src/utilDate.ts +var iso8601 = /* @__PURE__ */ __name((time) => toDate(time).toISOString().replace(/\.\d{3}Z$/, "Z"), "iso8601"); +var toDate = /* @__PURE__ */ __name((time) => { + if (typeof time === "number") { + return new Date(time * 1e3); + } + if (typeof time === "string") { + if (Number(time)) { + return new Date(Number(time) * 1e3); + } + return new Date(time); + } + return time; +}, "toDate"); + +// src/SignatureV4Base.ts +var SignatureV4Base = class { + static { + __name(this, "SignatureV4Base"); + } + constructor({ + applyChecksum, + credentials, + region, + service, + sha256, + uriEscapePath = true + }) { + this.service = service; + this.sha256 = sha256; + this.uriEscapePath = uriEscapePath; + this.applyChecksum = typeof applyChecksum === "boolean" ? applyChecksum : true; + this.regionProvider = (0, import_util_middleware.normalizeProvider)(region); + this.credentialProvider = (0, import_util_middleware.normalizeProvider)(credentials); + } + createCanonicalRequest(request, canonicalHeaders, payloadHash) { + const sortedHeaders = Object.keys(canonicalHeaders).sort(); + return `${request.method} +${this.getCanonicalPath(request)} +${getCanonicalQuery(request)} +${sortedHeaders.map((name) => `${name}:${canonicalHeaders[name]}`).join("\n")} + +${sortedHeaders.join(";")} +${payloadHash}`; + } + async createStringToSign(longDate, credentialScope, canonicalRequest, algorithmIdentifier) { + const hash = new this.sha256(); + hash.update((0, import_util_utf84.toUint8Array)(canonicalRequest)); + const hashedRequest = await hash.digest(); + return `${algorithmIdentifier} +${longDate} +${credentialScope} +${(0, import_util_hex_encoding.toHex)(hashedRequest)}`; + } + getCanonicalPath({ path }) { + if (this.uriEscapePath) { + const normalizedPathSegments = []; + for (const pathSegment of path.split("/")) { + if (pathSegment?.length === 0) + continue; + if (pathSegment === ".") + continue; + if (pathSegment === "..") { + normalizedPathSegments.pop(); + } else { + normalizedPathSegments.push(pathSegment); + } + } + const normalizedPath = `${path?.startsWith("/") ? "/" : ""}${normalizedPathSegments.join("/")}${normalizedPathSegments.length > 0 && path?.endsWith("/") ? "/" : ""}`; + const doubleEncoded = (0, import_util_uri_escape.escapeUri)(normalizedPath); + return doubleEncoded.replace(/%2F/g, "/"); + } + return path; + } + validateResolvedCredentials(credentials) { + if (typeof credentials !== "object" || // @ts-expect-error: Property 'accessKeyId' does not exist on type 'object'.ts(2339) + typeof credentials.accessKeyId !== "string" || // @ts-expect-error: Property 'secretAccessKey' does not exist on type 'object'.ts(2339) + typeof credentials.secretAccessKey !== "string") { + throw new Error("Resolved credential object is not valid"); + } + } + formatDate(now) { + const longDate = iso8601(now).replace(/[\-:]/g, ""); + return { + longDate, + shortDate: longDate.slice(0, 8) + }; + } + getCanonicalHeaderList(headers) { + return Object.keys(headers).sort().join(";"); + } +}; + +// src/SignatureV4.ts +var SignatureV4 = class extends SignatureV4Base { + constructor({ + applyChecksum, + credentials, + region, + service, + sha256, + uriEscapePath = true + }) { + super({ + applyChecksum, + credentials, + region, + service, + sha256, + uriEscapePath + }); + this.headerFormatter = new HeaderFormatter(); + } + static { + __name(this, "SignatureV4"); + } + async presign(originalRequest, options = {}) { + const { + signingDate = /* @__PURE__ */ new Date(), + expiresIn = 3600, + unsignableHeaders, + unhoistableHeaders, + signableHeaders, + hoistableHeaders, + signingRegion, + signingService + } = options; + const credentials = await this.credentialProvider(); + this.validateResolvedCredentials(credentials); + const region = signingRegion ?? await this.regionProvider(); + const { longDate, shortDate } = this.formatDate(signingDate); + if (expiresIn > MAX_PRESIGNED_TTL) { + return Promise.reject( + "Signature version 4 presigned URLs must have an expiration date less than one week in the future" + ); + } + const scope = createScope(shortDate, region, signingService ?? this.service); + const request = moveHeadersToQuery(prepareRequest(originalRequest), { unhoistableHeaders, hoistableHeaders }); + if (credentials.sessionToken) { + request.query[TOKEN_QUERY_PARAM] = credentials.sessionToken; + } + request.query[ALGORITHM_QUERY_PARAM] = ALGORITHM_IDENTIFIER; + request.query[CREDENTIAL_QUERY_PARAM] = `${credentials.accessKeyId}/${scope}`; + request.query[AMZ_DATE_QUERY_PARAM] = longDate; + request.query[EXPIRES_QUERY_PARAM] = expiresIn.toString(10); + const canonicalHeaders = getCanonicalHeaders(request, unsignableHeaders, signableHeaders); + request.query[SIGNED_HEADERS_QUERY_PARAM] = this.getCanonicalHeaderList(canonicalHeaders); + request.query[SIGNATURE_QUERY_PARAM] = await this.getSignature( + longDate, + scope, + this.getSigningKey(credentials, region, shortDate, signingService), + this.createCanonicalRequest(request, canonicalHeaders, await getPayloadHash(originalRequest, this.sha256)) + ); + return request; + } + async sign(toSign, options) { + if (typeof toSign === "string") { + return this.signString(toSign, options); + } else if (toSign.headers && toSign.payload) { + return this.signEvent(toSign, options); + } else if (toSign.message) { + return this.signMessage(toSign, options); + } else { + return this.signRequest(toSign, options); + } + } + async signEvent({ headers, payload }, { signingDate = /* @__PURE__ */ new Date(), priorSignature, signingRegion, signingService }) { + const region = signingRegion ?? await this.regionProvider(); + const { shortDate, longDate } = this.formatDate(signingDate); + const scope = createScope(shortDate, region, signingService ?? this.service); + const hashedPayload = await getPayloadHash({ headers: {}, body: payload }, this.sha256); + const hash = new this.sha256(); + hash.update(headers); + const hashedHeaders = (0, import_util_hex_encoding.toHex)(await hash.digest()); + const stringToSign = [ + EVENT_ALGORITHM_IDENTIFIER, + longDate, + scope, + priorSignature, + hashedHeaders, + hashedPayload + ].join("\n"); + return this.signString(stringToSign, { signingDate, signingRegion: region, signingService }); + } + async signMessage(signableMessage, { signingDate = /* @__PURE__ */ new Date(), signingRegion, signingService }) { + const promise = this.signEvent( + { + headers: this.headerFormatter.format(signableMessage.message.headers), + payload: signableMessage.message.body + }, + { + signingDate, + signingRegion, + signingService, + priorSignature: signableMessage.priorSignature + } + ); + return promise.then((signature) => { + return { message: signableMessage.message, signature }; + }); + } + async signString(stringToSign, { signingDate = /* @__PURE__ */ new Date(), signingRegion, signingService } = {}) { + const credentials = await this.credentialProvider(); + this.validateResolvedCredentials(credentials); + const region = signingRegion ?? await this.regionProvider(); + const { shortDate } = this.formatDate(signingDate); + const hash = new this.sha256(await this.getSigningKey(credentials, region, shortDate, signingService)); + hash.update((0, import_util_utf85.toUint8Array)(stringToSign)); + return (0, import_util_hex_encoding.toHex)(await hash.digest()); + } + async signRequest(requestToSign, { + signingDate = /* @__PURE__ */ new Date(), + signableHeaders, + unsignableHeaders, + signingRegion, + signingService + } = {}) { + const credentials = await this.credentialProvider(); + this.validateResolvedCredentials(credentials); + const region = signingRegion ?? await this.regionProvider(); + const request = prepareRequest(requestToSign); + const { longDate, shortDate } = this.formatDate(signingDate); + const scope = createScope(shortDate, region, signingService ?? this.service); + request.headers[AMZ_DATE_HEADER] = longDate; + if (credentials.sessionToken) { + request.headers[TOKEN_HEADER] = credentials.sessionToken; + } + const payloadHash = await getPayloadHash(request, this.sha256); + if (!hasHeader(SHA256_HEADER, request.headers) && this.applyChecksum) { + request.headers[SHA256_HEADER] = payloadHash; + } + const canonicalHeaders = getCanonicalHeaders(request, unsignableHeaders, signableHeaders); + const signature = await this.getSignature( + longDate, + scope, + this.getSigningKey(credentials, region, shortDate, signingService), + this.createCanonicalRequest(request, canonicalHeaders, payloadHash) + ); + request.headers[AUTH_HEADER] = `${ALGORITHM_IDENTIFIER} Credential=${credentials.accessKeyId}/${scope}, SignedHeaders=${this.getCanonicalHeaderList(canonicalHeaders)}, Signature=${signature}`; + return request; + } + async getSignature(longDate, credentialScope, keyPromise, canonicalRequest) { + const stringToSign = await this.createStringToSign( + longDate, + credentialScope, + canonicalRequest, + ALGORITHM_IDENTIFIER + ); + const hash = new this.sha256(await keyPromise); + hash.update((0, import_util_utf85.toUint8Array)(stringToSign)); + return (0, import_util_hex_encoding.toHex)(await hash.digest()); + } + getSigningKey(credentials, region, shortDate, service) { + return getSigningKey(this.sha256, credentials, shortDate, region, service || this.service); + } +}; + +// src/signature-v4a-container.ts +var signatureV4aContainer = { + SignatureV4a: null +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 61411: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Client: () => Client, + Command: () => Command, + NoOpLogger: () => NoOpLogger, + SENSITIVE_STRING: () => SENSITIVE_STRING, + ServiceException: () => ServiceException, + _json: () => _json, + collectBody: () => import_protocols.collectBody, + convertMap: () => convertMap, + createAggregatedClient: () => createAggregatedClient, + decorateServiceException: () => decorateServiceException, + emitWarningIfUnsupportedVersion: () => emitWarningIfUnsupportedVersion, + extendedEncodeURIComponent: () => import_protocols.extendedEncodeURIComponent, + getArrayIfSingleItem: () => getArrayIfSingleItem, + getDefaultClientConfiguration: () => getDefaultClientConfiguration, + getDefaultExtensionConfiguration: () => getDefaultExtensionConfiguration, + getValueFromTextNode: () => getValueFromTextNode, + isSerializableHeaderValue: () => isSerializableHeaderValue, + loadConfigsForDefaultMode: () => loadConfigsForDefaultMode, + map: () => map, + resolveDefaultRuntimeConfig: () => resolveDefaultRuntimeConfig, + resolvedPath: () => import_protocols.resolvedPath, + serializeDateTime: () => serializeDateTime, + serializeFloat: () => serializeFloat, + take: () => take, + throwDefaultError: () => throwDefaultError, + withBaseException: () => withBaseException +}); +module.exports = __toCommonJS(src_exports); + +// src/client.ts +var import_middleware_stack = __nccwpck_require__(9208); +var Client = class { + constructor(config) { + this.config = config; + this.middlewareStack = (0, import_middleware_stack.constructStack)(); + } + static { + __name(this, "Client"); + } + send(command, optionsOrCb, cb) { + const options = typeof optionsOrCb !== "function" ? optionsOrCb : void 0; + const callback = typeof optionsOrCb === "function" ? optionsOrCb : cb; + const useHandlerCache = options === void 0 && this.config.cacheMiddleware === true; + let handler; + if (useHandlerCache) { + if (!this.handlers) { + this.handlers = /* @__PURE__ */ new WeakMap(); + } + const handlers = this.handlers; + if (handlers.has(command.constructor)) { + handler = handlers.get(command.constructor); + } else { + handler = command.resolveMiddleware(this.middlewareStack, this.config, options); + handlers.set(command.constructor, handler); + } + } else { + delete this.handlers; + handler = command.resolveMiddleware(this.middlewareStack, this.config, options); + } + if (callback) { + handler(command).then( + (result) => callback(null, result.output), + (err) => callback(err) + ).catch( + // prevent any errors thrown in the callback from triggering an + // unhandled promise rejection + () => { + } + ); + } else { + return handler(command).then((result) => result.output); + } + } + destroy() { + this.config?.requestHandler?.destroy?.(); + delete this.handlers; + } +}; + +// src/collect-stream-body.ts +var import_protocols = __nccwpck_require__(93422); + +// src/command.ts + +var import_types = __nccwpck_require__(90690); +var Command = class { + constructor() { + this.middlewareStack = (0, import_middleware_stack.constructStack)(); + } + static { + __name(this, "Command"); + } + /** + * Factory for Command ClassBuilder. + * @internal + */ + static classBuilder() { + return new ClassBuilder(); + } + /** + * @internal + */ + resolveMiddlewareWithContext(clientStack, configuration, options, { + middlewareFn, + clientName, + commandName, + inputFilterSensitiveLog, + outputFilterSensitiveLog, + smithyContext, + additionalContext, + CommandCtor + }) { + for (const mw of middlewareFn.bind(this)(CommandCtor, clientStack, configuration, options)) { + this.middlewareStack.use(mw); + } + const stack = clientStack.concat(this.middlewareStack); + const { logger } = configuration; + const handlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog, + outputFilterSensitiveLog, + [import_types.SMITHY_CONTEXT_KEY]: { + commandInstance: this, + ...smithyContext + }, + ...additionalContext + }; + const { requestHandler } = configuration; + return stack.resolve( + (request) => requestHandler.handle(request.request, options || {}), + handlerExecutionContext + ); + } +}; +var ClassBuilder = class { + constructor() { + this._init = () => { + }; + this._ep = {}; + this._middlewareFn = () => []; + this._commandName = ""; + this._clientName = ""; + this._additionalContext = {}; + this._smithyContext = {}; + this._inputFilterSensitiveLog = (_) => _; + this._outputFilterSensitiveLog = (_) => _; + this._serializer = null; + this._deserializer = null; + } + static { + __name(this, "ClassBuilder"); + } + /** + * Optional init callback. + */ + init(cb) { + this._init = cb; + } + /** + * Set the endpoint parameter instructions. + */ + ep(endpointParameterInstructions) { + this._ep = endpointParameterInstructions; + return this; + } + /** + * Add any number of middleware. + */ + m(middlewareSupplier) { + this._middlewareFn = middlewareSupplier; + return this; + } + /** + * Set the initial handler execution context Smithy field. + */ + s(service, operation, smithyContext = {}) { + this._smithyContext = { + service, + operation, + ...smithyContext + }; + return this; + } + /** + * Set the initial handler execution context. + */ + c(additionalContext = {}) { + this._additionalContext = additionalContext; + return this; + } + /** + * Set constant string identifiers for the operation. + */ + n(clientName, commandName) { + this._clientName = clientName; + this._commandName = commandName; + return this; + } + /** + * Set the input and output sensistive log filters. + */ + f(inputFilter = (_) => _, outputFilter = (_) => _) { + this._inputFilterSensitiveLog = inputFilter; + this._outputFilterSensitiveLog = outputFilter; + return this; + } + /** + * Sets the serializer. + */ + ser(serializer) { + this._serializer = serializer; + return this; + } + /** + * Sets the deserializer. + */ + de(deserializer) { + this._deserializer = deserializer; + return this; + } + /** + * Sets input/output schema for the operation. + */ + sc(operation) { + this._operationSchema = operation; + this._smithyContext.operationSchema = operation; + return this; + } + /** + * @returns a Command class with the classBuilder properties. + */ + build() { + const closure = this; + let CommandRef; + return CommandRef = class extends Command { + /** + * @public + */ + constructor(...[input]) { + super(); + /** + * @internal + */ + // @ts-ignore used in middlewareFn closure. + this.serialize = closure._serializer; + /** + * @internal + */ + // @ts-ignore used in middlewareFn closure. + this.deserialize = closure._deserializer; + this.input = input ?? {}; + closure._init(this); + this.schema = closure._operationSchema; + } + static { + __name(this, "CommandRef"); + } + /** + * @public + */ + static getEndpointParameterInstructions() { + return closure._ep; + } + /** + * @internal + */ + resolveMiddleware(stack, configuration, options) { + return this.resolveMiddlewareWithContext(stack, configuration, options, { + CommandCtor: CommandRef, + middlewareFn: closure._middlewareFn, + clientName: closure._clientName, + commandName: closure._commandName, + inputFilterSensitiveLog: closure._inputFilterSensitiveLog, + outputFilterSensitiveLog: closure._outputFilterSensitiveLog, + smithyContext: closure._smithyContext, + additionalContext: closure._additionalContext + }); + } + }; + } +}; + +// src/constants.ts +var SENSITIVE_STRING = "***SensitiveInformation***"; + +// src/create-aggregated-client.ts +var createAggregatedClient = /* @__PURE__ */ __name((commands, Client2) => { + for (const command of Object.keys(commands)) { + const CommandCtor = commands[command]; + const methodImpl = /* @__PURE__ */ __name(async function(args, optionsOrCb, cb) { + const command2 = new CommandCtor(args); + if (typeof optionsOrCb === "function") { + this.send(command2, optionsOrCb); + } else if (typeof cb === "function") { + if (typeof optionsOrCb !== "object") + throw new Error(`Expected http options but got ${typeof optionsOrCb}`); + this.send(command2, optionsOrCb || {}, cb); + } else { + return this.send(command2, optionsOrCb); + } + }, "methodImpl"); + const methodName = (command[0].toLowerCase() + command.slice(1)).replace(/Command$/, ""); + Client2.prototype[methodName] = methodImpl; + } +}, "createAggregatedClient"); + +// src/exceptions.ts +var ServiceException = class _ServiceException extends Error { + static { + __name(this, "ServiceException"); + } + constructor(options) { + super(options.message); + Object.setPrototypeOf(this, Object.getPrototypeOf(this).constructor.prototype); + this.name = options.name; + this.$fault = options.$fault; + this.$metadata = options.$metadata; + } + /** + * Checks if a value is an instance of ServiceException (duck typed) + */ + static isInstance(value) { + if (!value) + return false; + const candidate = value; + return _ServiceException.prototype.isPrototypeOf(candidate) || Boolean(candidate.$fault) && Boolean(candidate.$metadata) && (candidate.$fault === "client" || candidate.$fault === "server"); + } + /** + * Custom instanceof check to support the operator for ServiceException base class + */ + static [Symbol.hasInstance](instance) { + if (!instance) + return false; + const candidate = instance; + if (this === _ServiceException) { + return _ServiceException.isInstance(instance); + } + if (_ServiceException.isInstance(instance)) { + if (candidate.name && this.name) { + return this.prototype.isPrototypeOf(instance) || candidate.name === this.name; + } + return this.prototype.isPrototypeOf(instance); + } + return false; + } +}; +var decorateServiceException = /* @__PURE__ */ __name((exception, additions = {}) => { + Object.entries(additions).filter(([, v]) => v !== void 0).forEach(([k, v]) => { + if (exception[k] == void 0 || exception[k] === "") { + exception[k] = v; + } + }); + const message = exception.message || exception.Message || "UnknownError"; + exception.message = message; + delete exception.Message; + return exception; +}, "decorateServiceException"); + +// src/default-error-handler.ts +var throwDefaultError = /* @__PURE__ */ __name(({ output, parsedBody, exceptionCtor, errorCode }) => { + const $metadata = deserializeMetadata(output); + const statusCode = $metadata.httpStatusCode ? $metadata.httpStatusCode + "" : void 0; + const response = new exceptionCtor({ + name: parsedBody?.code || parsedBody?.Code || errorCode || statusCode || "UnknownError", + $fault: "client", + $metadata + }); + throw decorateServiceException(response, parsedBody); +}, "throwDefaultError"); +var withBaseException = /* @__PURE__ */ __name((ExceptionCtor) => { + return ({ output, parsedBody, errorCode }) => { + throwDefaultError({ output, parsedBody, exceptionCtor: ExceptionCtor, errorCode }); + }; +}, "withBaseException"); +var deserializeMetadata = /* @__PURE__ */ __name((output) => ({ + httpStatusCode: output.statusCode, + requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"], + extendedRequestId: output.headers["x-amz-id-2"], + cfId: output.headers["x-amz-cf-id"] +}), "deserializeMetadata"); + +// src/defaults-mode.ts +var loadConfigsForDefaultMode = /* @__PURE__ */ __name((mode) => { + switch (mode) { + case "standard": + return { + retryMode: "standard", + connectionTimeout: 3100 + }; + case "in-region": + return { + retryMode: "standard", + connectionTimeout: 1100 + }; + case "cross-region": + return { + retryMode: "standard", + connectionTimeout: 3100 + }; + case "mobile": + return { + retryMode: "standard", + connectionTimeout: 3e4 + }; + default: + return {}; + } +}, "loadConfigsForDefaultMode"); + +// src/emitWarningIfUnsupportedVersion.ts +var warningEmitted = false; +var emitWarningIfUnsupportedVersion = /* @__PURE__ */ __name((version) => { + if (version && !warningEmitted && parseInt(version.substring(1, version.indexOf("."))) < 16) { + warningEmitted = true; + } +}, "emitWarningIfUnsupportedVersion"); + +// src/extended-encode-uri-component.ts + + +// src/extensions/checksum.ts + +var getChecksumConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const checksumAlgorithms = []; + for (const id in import_types.AlgorithmId) { + const algorithmId = import_types.AlgorithmId[id]; + if (runtimeConfig[algorithmId] === void 0) { + continue; + } + checksumAlgorithms.push({ + algorithmId: () => algorithmId, + checksumConstructor: () => runtimeConfig[algorithmId] + }); + } + return { + addChecksumAlgorithm(algo) { + checksumAlgorithms.push(algo); + }, + checksumAlgorithms() { + return checksumAlgorithms; + } + }; +}, "getChecksumConfiguration"); +var resolveChecksumRuntimeConfig = /* @__PURE__ */ __name((clientConfig) => { + const runtimeConfig = {}; + clientConfig.checksumAlgorithms().forEach((checksumAlgorithm) => { + runtimeConfig[checksumAlgorithm.algorithmId()] = checksumAlgorithm.checksumConstructor(); + }); + return runtimeConfig; +}, "resolveChecksumRuntimeConfig"); + +// src/extensions/retry.ts +var getRetryConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return { + setRetryStrategy(retryStrategy) { + runtimeConfig.retryStrategy = retryStrategy; + }, + retryStrategy() { + return runtimeConfig.retryStrategy; + } + }; +}, "getRetryConfiguration"); +var resolveRetryRuntimeConfig = /* @__PURE__ */ __name((retryStrategyConfiguration) => { + const runtimeConfig = {}; + runtimeConfig.retryStrategy = retryStrategyConfiguration.retryStrategy(); + return runtimeConfig; +}, "resolveRetryRuntimeConfig"); + +// src/extensions/defaultExtensionConfiguration.ts +var getDefaultExtensionConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return Object.assign(getChecksumConfiguration(runtimeConfig), getRetryConfiguration(runtimeConfig)); +}, "getDefaultExtensionConfiguration"); +var getDefaultClientConfiguration = getDefaultExtensionConfiguration; +var resolveDefaultRuntimeConfig = /* @__PURE__ */ __name((config) => { + return Object.assign(resolveChecksumRuntimeConfig(config), resolveRetryRuntimeConfig(config)); +}, "resolveDefaultRuntimeConfig"); + +// src/get-array-if-single-item.ts +var getArrayIfSingleItem = /* @__PURE__ */ __name((mayBeArray) => Array.isArray(mayBeArray) ? mayBeArray : [mayBeArray], "getArrayIfSingleItem"); + +// src/get-value-from-text-node.ts +var getValueFromTextNode = /* @__PURE__ */ __name((obj) => { + const textNodeName = "#text"; + for (const key in obj) { + if (obj.hasOwnProperty(key) && obj[key][textNodeName] !== void 0) { + obj[key] = obj[key][textNodeName]; + } else if (typeof obj[key] === "object" && obj[key] !== null) { + obj[key] = getValueFromTextNode(obj[key]); + } + } + return obj; +}, "getValueFromTextNode"); + +// src/is-serializable-header-value.ts +var isSerializableHeaderValue = /* @__PURE__ */ __name((value) => { + return value != null; +}, "isSerializableHeaderValue"); + +// src/NoOpLogger.ts +var NoOpLogger = class { + static { + __name(this, "NoOpLogger"); + } + trace() { + } + debug() { + } + info() { + } + warn() { + } + error() { + } +}; + +// src/object-mapping.ts +function map(arg0, arg1, arg2) { + let target; + let filter; + let instructions; + if (typeof arg1 === "undefined" && typeof arg2 === "undefined") { + target = {}; + instructions = arg0; + } else { + target = arg0; + if (typeof arg1 === "function") { + filter = arg1; + instructions = arg2; + return mapWithFilter(target, filter, instructions); + } else { + instructions = arg1; + } + } + for (const key of Object.keys(instructions)) { + if (!Array.isArray(instructions[key])) { + target[key] = instructions[key]; + continue; + } + applyInstruction(target, null, instructions, key); + } + return target; +} +__name(map, "map"); +var convertMap = /* @__PURE__ */ __name((target) => { + const output = {}; + for (const [k, v] of Object.entries(target || {})) { + output[k] = [, v]; + } + return output; +}, "convertMap"); +var take = /* @__PURE__ */ __name((source, instructions) => { + const out = {}; + for (const key in instructions) { + applyInstruction(out, source, instructions, key); + } + return out; +}, "take"); +var mapWithFilter = /* @__PURE__ */ __name((target, filter, instructions) => { + return map( + target, + Object.entries(instructions).reduce( + (_instructions, [key, value]) => { + if (Array.isArray(value)) { + _instructions[key] = value; + } else { + if (typeof value === "function") { + _instructions[key] = [filter, value()]; + } else { + _instructions[key] = [filter, value]; + } + } + return _instructions; + }, + {} + ) + ); +}, "mapWithFilter"); +var applyInstruction = /* @__PURE__ */ __name((target, source, instructions, targetKey) => { + if (source !== null) { + let instruction = instructions[targetKey]; + if (typeof instruction === "function") { + instruction = [, instruction]; + } + const [filter2 = nonNullish, valueFn = pass, sourceKey = targetKey] = instruction; + if (typeof filter2 === "function" && filter2(source[sourceKey]) || typeof filter2 !== "function" && !!filter2) { + target[targetKey] = valueFn(source[sourceKey]); + } + return; + } + let [filter, value] = instructions[targetKey]; + if (typeof value === "function") { + let _value; + const defaultFilterPassed = filter === void 0 && (_value = value()) != null; + const customFilterPassed = typeof filter === "function" && !!filter(void 0) || typeof filter !== "function" && !!filter; + if (defaultFilterPassed) { + target[targetKey] = _value; + } else if (customFilterPassed) { + target[targetKey] = value(); + } + } else { + const defaultFilterPassed = filter === void 0 && value != null; + const customFilterPassed = typeof filter === "function" && !!filter(value) || typeof filter !== "function" && !!filter; + if (defaultFilterPassed || customFilterPassed) { + target[targetKey] = value; + } + } +}, "applyInstruction"); +var nonNullish = /* @__PURE__ */ __name((_) => _ != null, "nonNullish"); +var pass = /* @__PURE__ */ __name((_) => _, "pass"); + +// src/resolve-path.ts + + +// src/ser-utils.ts +var serializeFloat = /* @__PURE__ */ __name((value) => { + if (value !== value) { + return "NaN"; + } + switch (value) { + case Infinity: + return "Infinity"; + case -Infinity: + return "-Infinity"; + default: + return value; + } +}, "serializeFloat"); +var serializeDateTime = /* @__PURE__ */ __name((date) => date.toISOString().replace(".000Z", "Z"), "serializeDateTime"); + +// src/serde-json.ts +var _json = /* @__PURE__ */ __name((obj) => { + if (obj == null) { + return {}; + } + if (Array.isArray(obj)) { + return obj.filter((_) => _ != null).map(_json); + } + if (typeof obj === "object") { + const target = {}; + for (const key of Object.keys(obj)) { + if (obj[key] == null) { + continue; + } + target[key] = _json(obj[key]); + } + return target; + } + return obj; +}, "_json"); + +// src/index.ts +__reExport(src_exports, __nccwpck_require__(92430), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 90690: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + AlgorithmId: () => AlgorithmId, + EndpointURLScheme: () => EndpointURLScheme, + FieldPosition: () => FieldPosition, + HttpApiKeyAuthLocation: () => HttpApiKeyAuthLocation, + HttpAuthLocation: () => HttpAuthLocation, + IniSectionType: () => IniSectionType, + RequestHandlerProtocol: () => RequestHandlerProtocol, + SMITHY_CONTEXT_KEY: () => SMITHY_CONTEXT_KEY, + getDefaultClientConfiguration: () => getDefaultClientConfiguration, + resolveDefaultRuntimeConfig: () => resolveDefaultRuntimeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/auth/auth.ts +var HttpAuthLocation = /* @__PURE__ */ ((HttpAuthLocation2) => { + HttpAuthLocation2["HEADER"] = "header"; + HttpAuthLocation2["QUERY"] = "query"; + return HttpAuthLocation2; +})(HttpAuthLocation || {}); + +// src/auth/HttpApiKeyAuth.ts +var HttpApiKeyAuthLocation = /* @__PURE__ */ ((HttpApiKeyAuthLocation2) => { + HttpApiKeyAuthLocation2["HEADER"] = "header"; + HttpApiKeyAuthLocation2["QUERY"] = "query"; + return HttpApiKeyAuthLocation2; +})(HttpApiKeyAuthLocation || {}); + +// src/endpoint.ts +var EndpointURLScheme = /* @__PURE__ */ ((EndpointURLScheme2) => { + EndpointURLScheme2["HTTP"] = "http"; + EndpointURLScheme2["HTTPS"] = "https"; + return EndpointURLScheme2; +})(EndpointURLScheme || {}); + +// src/extensions/checksum.ts +var AlgorithmId = /* @__PURE__ */ ((AlgorithmId2) => { + AlgorithmId2["MD5"] = "md5"; + AlgorithmId2["CRC32"] = "crc32"; + AlgorithmId2["CRC32C"] = "crc32c"; + AlgorithmId2["SHA1"] = "sha1"; + AlgorithmId2["SHA256"] = "sha256"; + return AlgorithmId2; +})(AlgorithmId || {}); +var getChecksumConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + const checksumAlgorithms = []; + if (runtimeConfig.sha256 !== void 0) { + checksumAlgorithms.push({ + algorithmId: () => "sha256" /* SHA256 */, + checksumConstructor: () => runtimeConfig.sha256 + }); + } + if (runtimeConfig.md5 != void 0) { + checksumAlgorithms.push({ + algorithmId: () => "md5" /* MD5 */, + checksumConstructor: () => runtimeConfig.md5 + }); + } + return { + addChecksumAlgorithm(algo) { + checksumAlgorithms.push(algo); + }, + checksumAlgorithms() { + return checksumAlgorithms; + } + }; +}, "getChecksumConfiguration"); +var resolveChecksumRuntimeConfig = /* @__PURE__ */ __name((clientConfig) => { + const runtimeConfig = {}; + clientConfig.checksumAlgorithms().forEach((checksumAlgorithm) => { + runtimeConfig[checksumAlgorithm.algorithmId()] = checksumAlgorithm.checksumConstructor(); + }); + return runtimeConfig; +}, "resolveChecksumRuntimeConfig"); + +// src/extensions/defaultClientConfiguration.ts +var getDefaultClientConfiguration = /* @__PURE__ */ __name((runtimeConfig) => { + return getChecksumConfiguration(runtimeConfig); +}, "getDefaultClientConfiguration"); +var resolveDefaultRuntimeConfig = /* @__PURE__ */ __name((config) => { + return resolveChecksumRuntimeConfig(config); +}, "resolveDefaultRuntimeConfig"); + +// src/http.ts +var FieldPosition = /* @__PURE__ */ ((FieldPosition2) => { + FieldPosition2[FieldPosition2["HEADER"] = 0] = "HEADER"; + FieldPosition2[FieldPosition2["TRAILER"] = 1] = "TRAILER"; + return FieldPosition2; +})(FieldPosition || {}); + +// src/middleware.ts +var SMITHY_CONTEXT_KEY = "__smithy_context"; + +// src/profile.ts +var IniSectionType = /* @__PURE__ */ ((IniSectionType2) => { + IniSectionType2["PROFILE"] = "profile"; + IniSectionType2["SSO_SESSION"] = "sso-session"; + IniSectionType2["SERVICES"] = "services"; + return IniSectionType2; +})(IniSectionType || {}); + +// src/transfer.ts +var RequestHandlerProtocol = /* @__PURE__ */ ((RequestHandlerProtocol2) => { + RequestHandlerProtocol2["HTTP_0_9"] = "http/0.9"; + RequestHandlerProtocol2["HTTP_1_0"] = "http/1.0"; + RequestHandlerProtocol2["TDS_8_0"] = "tds/8.0"; + return RequestHandlerProtocol2; +})(RequestHandlerProtocol || {}); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 14494: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + parseUrl: () => parseUrl +}); +module.exports = __toCommonJS(src_exports); +var import_querystring_parser = __nccwpck_require__(18822); +var parseUrl = /* @__PURE__ */ __name((url) => { + if (typeof url === "string") { + return parseUrl(new URL(url)); + } + const { hostname, pathname, port, protocol, search } = url; + let query; + if (search) { + query = (0, import_querystring_parser.parseQueryString)(search); + } + return { + hostname, + port: port ? parseInt(port) : void 0, + protocol, + path: pathname, + query + }; +}, "parseUrl"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 72674: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fromBase64 = void 0; +const util_buffer_from_1 = __nccwpck_require__(44151); +const BASE64_REGEX = /^[A-Za-z0-9+/]*={0,2}$/; +const fromBase64 = (input) => { + if ((input.length * 3) % 4 !== 0) { + throw new TypeError(`Incorrect padding on base64 string.`); + } + if (!BASE64_REGEX.exec(input)) { + throw new TypeError(`Invalid base64 string.`); + } + const buffer = (0, util_buffer_from_1.fromString)(input, "base64"); + return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength); +}; +exports.fromBase64 = fromBase64; + + +/***/ }), + +/***/ 68385: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +module.exports = __toCommonJS(src_exports); +__reExport(src_exports, __nccwpck_require__(72674), module.exports); +__reExport(src_exports, __nccwpck_require__(14871), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 14871: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toBase64 = void 0; +const util_buffer_from_1 = __nccwpck_require__(44151); +const util_utf8_1 = __nccwpck_require__(71577); +const toBase64 = (_input) => { + let input; + if (typeof _input === "string") { + input = (0, util_utf8_1.fromUtf8)(_input); + } + else { + input = _input; + } + if (typeof input !== "object" || typeof input.byteOffset !== "number" || typeof input.byteLength !== "number") { + throw new Error("@smithy/util-base64: toBase64 encoder function only accepts string | Uint8Array."); + } + return (0, util_buffer_from_1.fromArrayBuffer)(input.buffer, input.byteOffset, input.byteLength).toString("base64"); +}; +exports.toBase64 = toBase64; + + +/***/ }), + +/***/ 12098: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + calculateBodyLength: () => calculateBodyLength +}); +module.exports = __toCommonJS(src_exports); + +// src/calculateBodyLength.ts +var TEXT_ENCODER = typeof TextEncoder == "function" ? new TextEncoder() : null; +var calculateBodyLength = /* @__PURE__ */ __name((body) => { + if (typeof body === "string") { + if (TEXT_ENCODER) { + return TEXT_ENCODER.encode(body).byteLength; + } + let len = body.length; + for (let i = len - 1; i >= 0; i--) { + const code = body.charCodeAt(i); + if (code > 127 && code <= 2047) + len++; + else if (code > 2047 && code <= 65535) + len += 2; + if (code >= 56320 && code <= 57343) + i--; + } + return len; + } else if (typeof body.byteLength === "number") { + return body.byteLength; + } else if (typeof body.size === "number") { + return body.size; + } + throw new Error(`Body Length computation failed for ${body}`); +}, "calculateBodyLength"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 13638: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + calculateBodyLength: () => calculateBodyLength +}); +module.exports = __toCommonJS(src_exports); + +// src/calculateBodyLength.ts +var import_fs = __nccwpck_require__(79896); +var calculateBodyLength = /* @__PURE__ */ __name((body) => { + if (!body) { + return 0; + } + if (typeof body === "string") { + return Buffer.byteLength(body); + } else if (typeof body.byteLength === "number") { + return body.byteLength; + } else if (typeof body.size === "number") { + return body.size; + } else if (typeof body.start === "number" && typeof body.end === "number") { + return body.end + 1 - body.start; + } else if (typeof body.path === "string" || Buffer.isBuffer(body.path)) { + return (0, import_fs.lstatSync)(body.path).size; + } else if (typeof body.fd === "number") { + return (0, import_fs.fstatSync)(body.fd).size; + } + throw new Error(`Body Length computation failed for ${body}`); +}, "calculateBodyLength"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 44151: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromArrayBuffer: () => fromArrayBuffer, + fromString: () => fromString +}); +module.exports = __toCommonJS(src_exports); +var import_is_array_buffer = __nccwpck_require__(86130); +var import_buffer = __nccwpck_require__(20181); +var fromArrayBuffer = /* @__PURE__ */ __name((input, offset = 0, length = input.byteLength - offset) => { + if (!(0, import_is_array_buffer.isArrayBuffer)(input)) { + throw new TypeError(`The "input" argument must be ArrayBuffer. Received type ${typeof input} (${input})`); + } + return import_buffer.Buffer.from(input, offset, length); +}, "fromArrayBuffer"); +var fromString = /* @__PURE__ */ __name((input, encoding) => { + if (typeof input !== "string") { + throw new TypeError(`The "input" argument must be of type string. Received type ${typeof input} (${input})`); + } + return encoding ? import_buffer.Buffer.from(input, encoding) : import_buffer.Buffer.from(input); +}, "fromString"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 56716: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + SelectorType: () => SelectorType, + booleanSelector: () => booleanSelector, + numberSelector: () => numberSelector +}); +module.exports = __toCommonJS(src_exports); + +// src/booleanSelector.ts +var booleanSelector = /* @__PURE__ */ __name((obj, key, type) => { + if (!(key in obj)) + return void 0; + if (obj[key] === "true") + return true; + if (obj[key] === "false") + return false; + throw new Error(`Cannot load ${type} "${key}". Expected "true" or "false", got ${obj[key]}.`); +}, "booleanSelector"); + +// src/numberSelector.ts +var numberSelector = /* @__PURE__ */ __name((obj, key, type) => { + if (!(key in obj)) + return void 0; + const numberValue = parseInt(obj[key], 10); + if (Number.isNaN(numberValue)) { + throw new TypeError(`Cannot load ${type} '${key}'. Expected number, got '${obj[key]}'.`); + } + return numberValue; +}, "numberSelector"); + +// src/types.ts +var SelectorType = /* @__PURE__ */ ((SelectorType2) => { + SelectorType2["ENV"] = "env"; + SelectorType2["CONFIG"] = "shared config entry"; + return SelectorType2; +})(SelectorType || {}); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 15435: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + resolveDefaultsModeConfig: () => resolveDefaultsModeConfig +}); +module.exports = __toCommonJS(src_exports); + +// src/resolveDefaultsModeConfig.ts +var import_config_resolver = __nccwpck_require__(39316); +var import_node_config_provider = __nccwpck_require__(55704); +var import_property_provider = __nccwpck_require__(71238); + +// src/constants.ts +var AWS_EXECUTION_ENV = "AWS_EXECUTION_ENV"; +var AWS_REGION_ENV = "AWS_REGION"; +var AWS_DEFAULT_REGION_ENV = "AWS_DEFAULT_REGION"; +var ENV_IMDS_DISABLED = "AWS_EC2_METADATA_DISABLED"; +var DEFAULTS_MODE_OPTIONS = ["in-region", "cross-region", "mobile", "standard", "legacy"]; +var IMDS_REGION_PATH = "/latest/meta-data/placement/region"; + +// src/defaultsModeConfig.ts +var AWS_DEFAULTS_MODE_ENV = "AWS_DEFAULTS_MODE"; +var AWS_DEFAULTS_MODE_CONFIG = "defaults_mode"; +var NODE_DEFAULTS_MODE_CONFIG_OPTIONS = { + environmentVariableSelector: (env) => { + return env[AWS_DEFAULTS_MODE_ENV]; + }, + configFileSelector: (profile) => { + return profile[AWS_DEFAULTS_MODE_CONFIG]; + }, + default: "legacy" +}; + +// src/resolveDefaultsModeConfig.ts +var resolveDefaultsModeConfig = /* @__PURE__ */ __name(({ + region = (0, import_node_config_provider.loadConfig)(import_config_resolver.NODE_REGION_CONFIG_OPTIONS), + defaultsMode = (0, import_node_config_provider.loadConfig)(NODE_DEFAULTS_MODE_CONFIG_OPTIONS) +} = {}) => (0, import_property_provider.memoize)(async () => { + const mode = typeof defaultsMode === "function" ? await defaultsMode() : defaultsMode; + switch (mode?.toLowerCase()) { + case "auto": + return resolveNodeDefaultsModeAuto(region); + case "in-region": + case "cross-region": + case "mobile": + case "standard": + case "legacy": + return Promise.resolve(mode?.toLocaleLowerCase()); + case void 0: + return Promise.resolve("legacy"); + default: + throw new Error( + `Invalid parameter for "defaultsMode", expect ${DEFAULTS_MODE_OPTIONS.join(", ")}, got ${mode}` + ); + } +}), "resolveDefaultsModeConfig"); +var resolveNodeDefaultsModeAuto = /* @__PURE__ */ __name(async (clientRegion) => { + if (clientRegion) { + const resolvedRegion = typeof clientRegion === "function" ? await clientRegion() : clientRegion; + const inferredRegion = await inferPhysicalRegion(); + if (!inferredRegion) { + return "standard"; + } + if (resolvedRegion === inferredRegion) { + return "in-region"; + } else { + return "cross-region"; + } + } + return "standard"; +}, "resolveNodeDefaultsModeAuto"); +var inferPhysicalRegion = /* @__PURE__ */ __name(async () => { + if (process.env[AWS_EXECUTION_ENV] && (process.env[AWS_REGION_ENV] || process.env[AWS_DEFAULT_REGION_ENV])) { + return process.env[AWS_REGION_ENV] ?? process.env[AWS_DEFAULT_REGION_ENV]; + } + if (!process.env[ENV_IMDS_DISABLED]) { + try { + const { getInstanceMetadataEndpoint, httpRequest } = await Promise.resolve().then(() => __toESM(__nccwpck_require__(40566))); + const endpoint = await getInstanceMetadataEndpoint(); + return (await httpRequest({ ...endpoint, path: IMDS_REGION_PATH })).toString(); + } catch (e) { + } + } +}, "inferPhysicalRegion"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 79674: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + EndpointCache: () => EndpointCache, + EndpointError: () => EndpointError, + customEndpointFunctions: () => customEndpointFunctions, + isIpAddress: () => isIpAddress, + isValidHostLabel: () => isValidHostLabel, + resolveEndpoint: () => resolveEndpoint +}); +module.exports = __toCommonJS(src_exports); + +// src/cache/EndpointCache.ts +var EndpointCache = class { + /** + * @param [size] - desired average maximum capacity. A buffer of 10 additional keys will be allowed + * before keys are dropped. + * @param [params] - list of params to consider as part of the cache key. + * + * If the params list is not populated, no caching will happen. + * This may be out of order depending on how the object is created and arrives to this class. + */ + constructor({ size, params }) { + this.data = /* @__PURE__ */ new Map(); + this.parameters = []; + this.capacity = size ?? 50; + if (params) { + this.parameters = params; + } + } + static { + __name(this, "EndpointCache"); + } + /** + * @param endpointParams - query for endpoint. + * @param resolver - provider of the value if not present. + * @returns endpoint corresponding to the query. + */ + get(endpointParams, resolver) { + const key = this.hash(endpointParams); + if (key === false) { + return resolver(); + } + if (!this.data.has(key)) { + if (this.data.size > this.capacity + 10) { + const keys = this.data.keys(); + let i = 0; + while (true) { + const { value, done } = keys.next(); + this.data.delete(value); + if (done || ++i > 10) { + break; + } + } + } + this.data.set(key, resolver()); + } + return this.data.get(key); + } + size() { + return this.data.size; + } + /** + * @returns cache key or false if not cachable. + */ + hash(endpointParams) { + let buffer = ""; + const { parameters } = this; + if (parameters.length === 0) { + return false; + } + for (const param of parameters) { + const val = String(endpointParams[param] ?? ""); + if (val.includes("|;")) { + return false; + } + buffer += val + "|;"; + } + return buffer; + } +}; + +// src/lib/isIpAddress.ts +var IP_V4_REGEX = new RegExp( + `^(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}$` +); +var isIpAddress = /* @__PURE__ */ __name((value) => IP_V4_REGEX.test(value) || value.startsWith("[") && value.endsWith("]"), "isIpAddress"); + +// src/lib/isValidHostLabel.ts +var VALID_HOST_LABEL_REGEX = new RegExp(`^(?!.*-$)(?!-)[a-zA-Z0-9-]{1,63}$`); +var isValidHostLabel = /* @__PURE__ */ __name((value, allowSubDomains = false) => { + if (!allowSubDomains) { + return VALID_HOST_LABEL_REGEX.test(value); + } + const labels = value.split("."); + for (const label of labels) { + if (!isValidHostLabel(label)) { + return false; + } + } + return true; +}, "isValidHostLabel"); + +// src/utils/customEndpointFunctions.ts +var customEndpointFunctions = {}; + +// src/debug/debugId.ts +var debugId = "endpoints"; + +// src/debug/toDebugString.ts +function toDebugString(input) { + if (typeof input !== "object" || input == null) { + return input; + } + if ("ref" in input) { + return `$${toDebugString(input.ref)}`; + } + if ("fn" in input) { + return `${input.fn}(${(input.argv || []).map(toDebugString).join(", ")})`; + } + return JSON.stringify(input, null, 2); +} +__name(toDebugString, "toDebugString"); + +// src/types/EndpointError.ts +var EndpointError = class extends Error { + static { + __name(this, "EndpointError"); + } + constructor(message) { + super(message); + this.name = "EndpointError"; + } +}; + +// src/lib/booleanEquals.ts +var booleanEquals = /* @__PURE__ */ __name((value1, value2) => value1 === value2, "booleanEquals"); + +// src/lib/getAttrPathList.ts +var getAttrPathList = /* @__PURE__ */ __name((path) => { + const parts = path.split("."); + const pathList = []; + for (const part of parts) { + const squareBracketIndex = part.indexOf("["); + if (squareBracketIndex !== -1) { + if (part.indexOf("]") !== part.length - 1) { + throw new EndpointError(`Path: '${path}' does not end with ']'`); + } + const arrayIndex = part.slice(squareBracketIndex + 1, -1); + if (Number.isNaN(parseInt(arrayIndex))) { + throw new EndpointError(`Invalid array index: '${arrayIndex}' in path: '${path}'`); + } + if (squareBracketIndex !== 0) { + pathList.push(part.slice(0, squareBracketIndex)); + } + pathList.push(arrayIndex); + } else { + pathList.push(part); + } + } + return pathList; +}, "getAttrPathList"); + +// src/lib/getAttr.ts +var getAttr = /* @__PURE__ */ __name((value, path) => getAttrPathList(path).reduce((acc, index) => { + if (typeof acc !== "object") { + throw new EndpointError(`Index '${index}' in '${path}' not found in '${JSON.stringify(value)}'`); + } else if (Array.isArray(acc)) { + return acc[parseInt(index)]; + } + return acc[index]; +}, value), "getAttr"); + +// src/lib/isSet.ts +var isSet = /* @__PURE__ */ __name((value) => value != null, "isSet"); + +// src/lib/not.ts +var not = /* @__PURE__ */ __name((value) => !value, "not"); + +// src/lib/parseURL.ts +var import_types3 = __nccwpck_require__(90690); +var DEFAULT_PORTS = { + [import_types3.EndpointURLScheme.HTTP]: 80, + [import_types3.EndpointURLScheme.HTTPS]: 443 +}; +var parseURL = /* @__PURE__ */ __name((value) => { + const whatwgURL = (() => { + try { + if (value instanceof URL) { + return value; + } + if (typeof value === "object" && "hostname" in value) { + const { hostname: hostname2, port, protocol: protocol2 = "", path = "", query = {} } = value; + const url = new URL(`${protocol2}//${hostname2}${port ? `:${port}` : ""}${path}`); + url.search = Object.entries(query).map(([k, v]) => `${k}=${v}`).join("&"); + return url; + } + return new URL(value); + } catch (error) { + return null; + } + })(); + if (!whatwgURL) { + console.error(`Unable to parse ${JSON.stringify(value)} as a whatwg URL.`); + return null; + } + const urlString = whatwgURL.href; + const { host, hostname, pathname, protocol, search } = whatwgURL; + if (search) { + return null; + } + const scheme = protocol.slice(0, -1); + if (!Object.values(import_types3.EndpointURLScheme).includes(scheme)) { + return null; + } + const isIp = isIpAddress(hostname); + const inputContainsDefaultPort = urlString.includes(`${host}:${DEFAULT_PORTS[scheme]}`) || typeof value === "string" && value.includes(`${host}:${DEFAULT_PORTS[scheme]}`); + const authority = `${host}${inputContainsDefaultPort ? `:${DEFAULT_PORTS[scheme]}` : ``}`; + return { + scheme, + authority, + path: pathname, + normalizedPath: pathname.endsWith("/") ? pathname : `${pathname}/`, + isIp + }; +}, "parseURL"); + +// src/lib/stringEquals.ts +var stringEquals = /* @__PURE__ */ __name((value1, value2) => value1 === value2, "stringEquals"); + +// src/lib/substring.ts +var substring = /* @__PURE__ */ __name((input, start, stop, reverse) => { + if (start >= stop || input.length < stop) { + return null; + } + if (!reverse) { + return input.substring(start, stop); + } + return input.substring(input.length - stop, input.length - start); +}, "substring"); + +// src/lib/uriEncode.ts +var uriEncode = /* @__PURE__ */ __name((value) => encodeURIComponent(value).replace(/[!*'()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`), "uriEncode"); + +// src/utils/endpointFunctions.ts +var endpointFunctions = { + booleanEquals, + getAttr, + isSet, + isValidHostLabel, + not, + parseURL, + stringEquals, + substring, + uriEncode +}; + +// src/utils/evaluateTemplate.ts +var evaluateTemplate = /* @__PURE__ */ __name((template, options) => { + const evaluatedTemplateArr = []; + const templateContext = { + ...options.endpointParams, + ...options.referenceRecord + }; + let currentIndex = 0; + while (currentIndex < template.length) { + const openingBraceIndex = template.indexOf("{", currentIndex); + if (openingBraceIndex === -1) { + evaluatedTemplateArr.push(template.slice(currentIndex)); + break; + } + evaluatedTemplateArr.push(template.slice(currentIndex, openingBraceIndex)); + const closingBraceIndex = template.indexOf("}", openingBraceIndex); + if (closingBraceIndex === -1) { + evaluatedTemplateArr.push(template.slice(openingBraceIndex)); + break; + } + if (template[openingBraceIndex + 1] === "{" && template[closingBraceIndex + 1] === "}") { + evaluatedTemplateArr.push(template.slice(openingBraceIndex + 1, closingBraceIndex)); + currentIndex = closingBraceIndex + 2; + } + const parameterName = template.substring(openingBraceIndex + 1, closingBraceIndex); + if (parameterName.includes("#")) { + const [refName, attrName] = parameterName.split("#"); + evaluatedTemplateArr.push(getAttr(templateContext[refName], attrName)); + } else { + evaluatedTemplateArr.push(templateContext[parameterName]); + } + currentIndex = closingBraceIndex + 1; + } + return evaluatedTemplateArr.join(""); +}, "evaluateTemplate"); + +// src/utils/getReferenceValue.ts +var getReferenceValue = /* @__PURE__ */ __name(({ ref }, options) => { + const referenceRecord = { + ...options.endpointParams, + ...options.referenceRecord + }; + return referenceRecord[ref]; +}, "getReferenceValue"); + +// src/utils/evaluateExpression.ts +var evaluateExpression = /* @__PURE__ */ __name((obj, keyName, options) => { + if (typeof obj === "string") { + return evaluateTemplate(obj, options); + } else if (obj["fn"]) { + return callFunction(obj, options); + } else if (obj["ref"]) { + return getReferenceValue(obj, options); + } + throw new EndpointError(`'${keyName}': ${String(obj)} is not a string, function or reference.`); +}, "evaluateExpression"); + +// src/utils/callFunction.ts +var callFunction = /* @__PURE__ */ __name(({ fn, argv }, options) => { + const evaluatedArgs = argv.map( + (arg) => ["boolean", "number"].includes(typeof arg) ? arg : evaluateExpression(arg, "arg", options) + ); + const fnSegments = fn.split("."); + if (fnSegments[0] in customEndpointFunctions && fnSegments[1] != null) { + return customEndpointFunctions[fnSegments[0]][fnSegments[1]](...evaluatedArgs); + } + return endpointFunctions[fn](...evaluatedArgs); +}, "callFunction"); + +// src/utils/evaluateCondition.ts +var evaluateCondition = /* @__PURE__ */ __name(({ assign, ...fnArgs }, options) => { + if (assign && assign in options.referenceRecord) { + throw new EndpointError(`'${assign}' is already defined in Reference Record.`); + } + const value = callFunction(fnArgs, options); + options.logger?.debug?.(`${debugId} evaluateCondition: ${toDebugString(fnArgs)} = ${toDebugString(value)}`); + return { + result: value === "" ? true : !!value, + ...assign != null && { toAssign: { name: assign, value } } + }; +}, "evaluateCondition"); + +// src/utils/evaluateConditions.ts +var evaluateConditions = /* @__PURE__ */ __name((conditions = [], options) => { + const conditionsReferenceRecord = {}; + for (const condition of conditions) { + const { result, toAssign } = evaluateCondition(condition, { + ...options, + referenceRecord: { + ...options.referenceRecord, + ...conditionsReferenceRecord + } + }); + if (!result) { + return { result }; + } + if (toAssign) { + conditionsReferenceRecord[toAssign.name] = toAssign.value; + options.logger?.debug?.(`${debugId} assign: ${toAssign.name} := ${toDebugString(toAssign.value)}`); + } + } + return { result: true, referenceRecord: conditionsReferenceRecord }; +}, "evaluateConditions"); + +// src/utils/getEndpointHeaders.ts +var getEndpointHeaders = /* @__PURE__ */ __name((headers, options) => Object.entries(headers).reduce( + (acc, [headerKey, headerVal]) => ({ + ...acc, + [headerKey]: headerVal.map((headerValEntry) => { + const processedExpr = evaluateExpression(headerValEntry, "Header value entry", options); + if (typeof processedExpr !== "string") { + throw new EndpointError(`Header '${headerKey}' value '${processedExpr}' is not a string`); + } + return processedExpr; + }) + }), + {} +), "getEndpointHeaders"); + +// src/utils/getEndpointProperty.ts +var getEndpointProperty = /* @__PURE__ */ __name((property, options) => { + if (Array.isArray(property)) { + return property.map((propertyEntry) => getEndpointProperty(propertyEntry, options)); + } + switch (typeof property) { + case "string": + return evaluateTemplate(property, options); + case "object": + if (property === null) { + throw new EndpointError(`Unexpected endpoint property: ${property}`); + } + return getEndpointProperties(property, options); + case "boolean": + return property; + default: + throw new EndpointError(`Unexpected endpoint property type: ${typeof property}`); + } +}, "getEndpointProperty"); + +// src/utils/getEndpointProperties.ts +var getEndpointProperties = /* @__PURE__ */ __name((properties, options) => Object.entries(properties).reduce( + (acc, [propertyKey, propertyVal]) => ({ + ...acc, + [propertyKey]: getEndpointProperty(propertyVal, options) + }), + {} +), "getEndpointProperties"); + +// src/utils/getEndpointUrl.ts +var getEndpointUrl = /* @__PURE__ */ __name((endpointUrl, options) => { + const expression = evaluateExpression(endpointUrl, "Endpoint URL", options); + if (typeof expression === "string") { + try { + return new URL(expression); + } catch (error) { + console.error(`Failed to construct URL with ${expression}`, error); + throw error; + } + } + throw new EndpointError(`Endpoint URL must be a string, got ${typeof expression}`); +}, "getEndpointUrl"); + +// src/utils/evaluateEndpointRule.ts +var evaluateEndpointRule = /* @__PURE__ */ __name((endpointRule, options) => { + const { conditions, endpoint } = endpointRule; + const { result, referenceRecord } = evaluateConditions(conditions, options); + if (!result) { + return; + } + const endpointRuleOptions = { + ...options, + referenceRecord: { ...options.referenceRecord, ...referenceRecord } + }; + const { url, properties, headers } = endpoint; + options.logger?.debug?.(`${debugId} Resolving endpoint from template: ${toDebugString(endpoint)}`); + return { + ...headers != void 0 && { + headers: getEndpointHeaders(headers, endpointRuleOptions) + }, + ...properties != void 0 && { + properties: getEndpointProperties(properties, endpointRuleOptions) + }, + url: getEndpointUrl(url, endpointRuleOptions) + }; +}, "evaluateEndpointRule"); + +// src/utils/evaluateErrorRule.ts +var evaluateErrorRule = /* @__PURE__ */ __name((errorRule, options) => { + const { conditions, error } = errorRule; + const { result, referenceRecord } = evaluateConditions(conditions, options); + if (!result) { + return; + } + throw new EndpointError( + evaluateExpression(error, "Error", { + ...options, + referenceRecord: { ...options.referenceRecord, ...referenceRecord } + }) + ); +}, "evaluateErrorRule"); + +// src/utils/evaluateTreeRule.ts +var evaluateTreeRule = /* @__PURE__ */ __name((treeRule, options) => { + const { conditions, rules } = treeRule; + const { result, referenceRecord } = evaluateConditions(conditions, options); + if (!result) { + return; + } + return evaluateRules(rules, { + ...options, + referenceRecord: { ...options.referenceRecord, ...referenceRecord } + }); +}, "evaluateTreeRule"); + +// src/utils/evaluateRules.ts +var evaluateRules = /* @__PURE__ */ __name((rules, options) => { + for (const rule of rules) { + if (rule.type === "endpoint") { + const endpointOrUndefined = evaluateEndpointRule(rule, options); + if (endpointOrUndefined) { + return endpointOrUndefined; + } + } else if (rule.type === "error") { + evaluateErrorRule(rule, options); + } else if (rule.type === "tree") { + const endpointOrUndefined = evaluateTreeRule(rule, options); + if (endpointOrUndefined) { + return endpointOrUndefined; + } + } else { + throw new EndpointError(`Unknown endpoint rule: ${rule}`); + } + } + throw new EndpointError(`Rules evaluation failed`); +}, "evaluateRules"); + +// src/resolveEndpoint.ts +var resolveEndpoint = /* @__PURE__ */ __name((ruleSetObject, options) => { + const { endpointParams, logger } = options; + const { parameters, rules } = ruleSetObject; + options.logger?.debug?.(`${debugId} Initial EndpointParams: ${toDebugString(endpointParams)}`); + const paramsWithDefault = Object.entries(parameters).filter(([, v]) => v.default != null).map(([k, v]) => [k, v.default]); + if (paramsWithDefault.length > 0) { + for (const [paramKey, paramDefaultValue] of paramsWithDefault) { + endpointParams[paramKey] = endpointParams[paramKey] ?? paramDefaultValue; + } + } + const requiredParams = Object.entries(parameters).filter(([, v]) => v.required).map(([k]) => k); + for (const requiredParam of requiredParams) { + if (endpointParams[requiredParam] == null) { + throw new EndpointError(`Missing required parameter: '${requiredParam}'`); + } + } + const endpoint = evaluateRules(rules, { endpointParams, logger, referenceRecord: {} }); + options.logger?.debug?.(`${debugId} Resolved endpoint: ${toDebugString(endpoint)}`); + return endpoint; +}, "resolveEndpoint"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 96435: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromHex: () => fromHex, + toHex: () => toHex +}); +module.exports = __toCommonJS(src_exports); +var SHORT_TO_HEX = {}; +var HEX_TO_SHORT = {}; +for (let i = 0; i < 256; i++) { + let encodedByte = i.toString(16).toLowerCase(); + if (encodedByte.length === 1) { + encodedByte = `0${encodedByte}`; + } + SHORT_TO_HEX[i] = encodedByte; + HEX_TO_SHORT[encodedByte] = i; +} +function fromHex(encoded) { + if (encoded.length % 2 !== 0) { + throw new Error("Hex encoded strings must have an even number length"); + } + const out = new Uint8Array(encoded.length / 2); + for (let i = 0; i < encoded.length; i += 2) { + const encodedByte = encoded.slice(i, i + 2).toLowerCase(); + if (encodedByte in HEX_TO_SHORT) { + out[i / 2] = HEX_TO_SHORT[encodedByte]; + } else { + throw new Error(`Cannot decode unrecognized sequence ${encodedByte} as hexadecimal`); + } + } + return out; +} +__name(fromHex, "fromHex"); +function toHex(bytes) { + let out = ""; + for (let i = 0; i < bytes.byteLength; i++) { + out += SHORT_TO_HEX[bytes[i]]; + } + return out; +} +__name(toHex, "toHex"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 76324: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + getSmithyContext: () => getSmithyContext, + normalizeProvider: () => normalizeProvider +}); +module.exports = __toCommonJS(src_exports); + +// src/getSmithyContext.ts +var import_types = __nccwpck_require__(90690); +var getSmithyContext = /* @__PURE__ */ __name((context) => context[import_types.SMITHY_CONTEXT_KEY] || (context[import_types.SMITHY_CONTEXT_KEY] = {}), "getSmithyContext"); + +// src/normalizeProvider.ts +var normalizeProvider = /* @__PURE__ */ __name((input) => { + if (typeof input === "function") + return input; + const promisified = Promise.resolve(input); + return () => promisified; +}, "normalizeProvider"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 15518: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + AdaptiveRetryStrategy: () => AdaptiveRetryStrategy, + ConfiguredRetryStrategy: () => ConfiguredRetryStrategy, + DEFAULT_MAX_ATTEMPTS: () => DEFAULT_MAX_ATTEMPTS, + DEFAULT_RETRY_DELAY_BASE: () => DEFAULT_RETRY_DELAY_BASE, + DEFAULT_RETRY_MODE: () => DEFAULT_RETRY_MODE, + DefaultRateLimiter: () => DefaultRateLimiter, + INITIAL_RETRY_TOKENS: () => INITIAL_RETRY_TOKENS, + INVOCATION_ID_HEADER: () => INVOCATION_ID_HEADER, + MAXIMUM_RETRY_DELAY: () => MAXIMUM_RETRY_DELAY, + NO_RETRY_INCREMENT: () => NO_RETRY_INCREMENT, + REQUEST_HEADER: () => REQUEST_HEADER, + RETRY_COST: () => RETRY_COST, + RETRY_MODES: () => RETRY_MODES, + StandardRetryStrategy: () => StandardRetryStrategy, + THROTTLING_RETRY_DELAY_BASE: () => THROTTLING_RETRY_DELAY_BASE, + TIMEOUT_RETRY_COST: () => TIMEOUT_RETRY_COST +}); +module.exports = __toCommonJS(src_exports); + +// src/config.ts +var RETRY_MODES = /* @__PURE__ */ ((RETRY_MODES2) => { + RETRY_MODES2["STANDARD"] = "standard"; + RETRY_MODES2["ADAPTIVE"] = "adaptive"; + return RETRY_MODES2; +})(RETRY_MODES || {}); +var DEFAULT_MAX_ATTEMPTS = 3; +var DEFAULT_RETRY_MODE = "standard" /* STANDARD */; + +// src/DefaultRateLimiter.ts +var import_service_error_classification = __nccwpck_require__(42058); +var DefaultRateLimiter = class _DefaultRateLimiter { + constructor(options) { + // Pre-set state variables + this.currentCapacity = 0; + this.enabled = false; + this.lastMaxRate = 0; + this.measuredTxRate = 0; + this.requestCount = 0; + this.lastTimestamp = 0; + this.timeWindow = 0; + this.beta = options?.beta ?? 0.7; + this.minCapacity = options?.minCapacity ?? 1; + this.minFillRate = options?.minFillRate ?? 0.5; + this.scaleConstant = options?.scaleConstant ?? 0.4; + this.smooth = options?.smooth ?? 0.8; + const currentTimeInSeconds = this.getCurrentTimeInSeconds(); + this.lastThrottleTime = currentTimeInSeconds; + this.lastTxRateBucket = Math.floor(this.getCurrentTimeInSeconds()); + this.fillRate = this.minFillRate; + this.maxCapacity = this.minCapacity; + } + static { + __name(this, "DefaultRateLimiter"); + } + static { + /** + * Only used in testing. + */ + this.setTimeoutFn = setTimeout; + } + getCurrentTimeInSeconds() { + return Date.now() / 1e3; + } + async getSendToken() { + return this.acquireTokenBucket(1); + } + async acquireTokenBucket(amount) { + if (!this.enabled) { + return; + } + this.refillTokenBucket(); + if (amount > this.currentCapacity) { + const delay = (amount - this.currentCapacity) / this.fillRate * 1e3; + await new Promise((resolve) => _DefaultRateLimiter.setTimeoutFn(resolve, delay)); + } + this.currentCapacity = this.currentCapacity - amount; + } + refillTokenBucket() { + const timestamp = this.getCurrentTimeInSeconds(); + if (!this.lastTimestamp) { + this.lastTimestamp = timestamp; + return; + } + const fillAmount = (timestamp - this.lastTimestamp) * this.fillRate; + this.currentCapacity = Math.min(this.maxCapacity, this.currentCapacity + fillAmount); + this.lastTimestamp = timestamp; + } + updateClientSendingRate(response) { + let calculatedRate; + this.updateMeasuredRate(); + if ((0, import_service_error_classification.isThrottlingError)(response)) { + const rateToUse = !this.enabled ? this.measuredTxRate : Math.min(this.measuredTxRate, this.fillRate); + this.lastMaxRate = rateToUse; + this.calculateTimeWindow(); + this.lastThrottleTime = this.getCurrentTimeInSeconds(); + calculatedRate = this.cubicThrottle(rateToUse); + this.enableTokenBucket(); + } else { + this.calculateTimeWindow(); + calculatedRate = this.cubicSuccess(this.getCurrentTimeInSeconds()); + } + const newRate = Math.min(calculatedRate, 2 * this.measuredTxRate); + this.updateTokenBucketRate(newRate); + } + calculateTimeWindow() { + this.timeWindow = this.getPrecise(Math.pow(this.lastMaxRate * (1 - this.beta) / this.scaleConstant, 1 / 3)); + } + cubicThrottle(rateToUse) { + return this.getPrecise(rateToUse * this.beta); + } + cubicSuccess(timestamp) { + return this.getPrecise( + this.scaleConstant * Math.pow(timestamp - this.lastThrottleTime - this.timeWindow, 3) + this.lastMaxRate + ); + } + enableTokenBucket() { + this.enabled = true; + } + updateTokenBucketRate(newRate) { + this.refillTokenBucket(); + this.fillRate = Math.max(newRate, this.minFillRate); + this.maxCapacity = Math.max(newRate, this.minCapacity); + this.currentCapacity = Math.min(this.currentCapacity, this.maxCapacity); + } + updateMeasuredRate() { + const t = this.getCurrentTimeInSeconds(); + const timeBucket = Math.floor(t * 2) / 2; + this.requestCount++; + if (timeBucket > this.lastTxRateBucket) { + const currentRate = this.requestCount / (timeBucket - this.lastTxRateBucket); + this.measuredTxRate = this.getPrecise(currentRate * this.smooth + this.measuredTxRate * (1 - this.smooth)); + this.requestCount = 0; + this.lastTxRateBucket = timeBucket; + } + } + getPrecise(num) { + return parseFloat(num.toFixed(8)); + } +}; + +// src/constants.ts +var DEFAULT_RETRY_DELAY_BASE = 100; +var MAXIMUM_RETRY_DELAY = 20 * 1e3; +var THROTTLING_RETRY_DELAY_BASE = 500; +var INITIAL_RETRY_TOKENS = 500; +var RETRY_COST = 5; +var TIMEOUT_RETRY_COST = 10; +var NO_RETRY_INCREMENT = 1; +var INVOCATION_ID_HEADER = "amz-sdk-invocation-id"; +var REQUEST_HEADER = "amz-sdk-request"; + +// src/defaultRetryBackoffStrategy.ts +var getDefaultRetryBackoffStrategy = /* @__PURE__ */ __name(() => { + let delayBase = DEFAULT_RETRY_DELAY_BASE; + const computeNextBackoffDelay = /* @__PURE__ */ __name((attempts) => { + return Math.floor(Math.min(MAXIMUM_RETRY_DELAY, Math.random() * 2 ** attempts * delayBase)); + }, "computeNextBackoffDelay"); + const setDelayBase = /* @__PURE__ */ __name((delay) => { + delayBase = delay; + }, "setDelayBase"); + return { + computeNextBackoffDelay, + setDelayBase + }; +}, "getDefaultRetryBackoffStrategy"); + +// src/defaultRetryToken.ts +var createDefaultRetryToken = /* @__PURE__ */ __name(({ + retryDelay, + retryCount, + retryCost +}) => { + const getRetryCount = /* @__PURE__ */ __name(() => retryCount, "getRetryCount"); + const getRetryDelay = /* @__PURE__ */ __name(() => Math.min(MAXIMUM_RETRY_DELAY, retryDelay), "getRetryDelay"); + const getRetryCost = /* @__PURE__ */ __name(() => retryCost, "getRetryCost"); + return { + getRetryCount, + getRetryDelay, + getRetryCost + }; +}, "createDefaultRetryToken"); + +// src/StandardRetryStrategy.ts +var StandardRetryStrategy = class { + constructor(maxAttempts) { + this.maxAttempts = maxAttempts; + this.mode = "standard" /* STANDARD */; + this.capacity = INITIAL_RETRY_TOKENS; + this.retryBackoffStrategy = getDefaultRetryBackoffStrategy(); + this.maxAttemptsProvider = typeof maxAttempts === "function" ? maxAttempts : async () => maxAttempts; + } + static { + __name(this, "StandardRetryStrategy"); + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars + async acquireInitialRetryToken(retryTokenScope) { + return createDefaultRetryToken({ + retryDelay: DEFAULT_RETRY_DELAY_BASE, + retryCount: 0 + }); + } + async refreshRetryTokenForRetry(token, errorInfo) { + const maxAttempts = await this.getMaxAttempts(); + if (this.shouldRetry(token, errorInfo, maxAttempts)) { + const errorType = errorInfo.errorType; + this.retryBackoffStrategy.setDelayBase( + errorType === "THROTTLING" ? THROTTLING_RETRY_DELAY_BASE : DEFAULT_RETRY_DELAY_BASE + ); + const delayFromErrorType = this.retryBackoffStrategy.computeNextBackoffDelay(token.getRetryCount()); + const retryDelay = errorInfo.retryAfterHint ? Math.max(errorInfo.retryAfterHint.getTime() - Date.now() || 0, delayFromErrorType) : delayFromErrorType; + const capacityCost = this.getCapacityCost(errorType); + this.capacity -= capacityCost; + return createDefaultRetryToken({ + retryDelay, + retryCount: token.getRetryCount() + 1, + retryCost: capacityCost + }); + } + throw new Error("No retry token available"); + } + recordSuccess(token) { + this.capacity = Math.max(INITIAL_RETRY_TOKENS, this.capacity + (token.getRetryCost() ?? NO_RETRY_INCREMENT)); + } + /** + * @returns the current available retry capacity. + * + * This number decreases when retries are executed and refills when requests or retries succeed. + */ + getCapacity() { + return this.capacity; + } + async getMaxAttempts() { + try { + return await this.maxAttemptsProvider(); + } catch (error) { + console.warn(`Max attempts provider could not resolve. Using default of ${DEFAULT_MAX_ATTEMPTS}`); + return DEFAULT_MAX_ATTEMPTS; + } + } + shouldRetry(tokenToRenew, errorInfo, maxAttempts) { + const attempts = tokenToRenew.getRetryCount() + 1; + return attempts < maxAttempts && this.capacity >= this.getCapacityCost(errorInfo.errorType) && this.isRetryableError(errorInfo.errorType); + } + getCapacityCost(errorType) { + return errorType === "TRANSIENT" ? TIMEOUT_RETRY_COST : RETRY_COST; + } + isRetryableError(errorType) { + return errorType === "THROTTLING" || errorType === "TRANSIENT"; + } +}; + +// src/AdaptiveRetryStrategy.ts +var AdaptiveRetryStrategy = class { + constructor(maxAttemptsProvider, options) { + this.maxAttemptsProvider = maxAttemptsProvider; + this.mode = "adaptive" /* ADAPTIVE */; + const { rateLimiter } = options ?? {}; + this.rateLimiter = rateLimiter ?? new DefaultRateLimiter(); + this.standardRetryStrategy = new StandardRetryStrategy(maxAttemptsProvider); + } + static { + __name(this, "AdaptiveRetryStrategy"); + } + async acquireInitialRetryToken(retryTokenScope) { + await this.rateLimiter.getSendToken(); + return this.standardRetryStrategy.acquireInitialRetryToken(retryTokenScope); + } + async refreshRetryTokenForRetry(tokenToRenew, errorInfo) { + this.rateLimiter.updateClientSendingRate(errorInfo); + return this.standardRetryStrategy.refreshRetryTokenForRetry(tokenToRenew, errorInfo); + } + recordSuccess(token) { + this.rateLimiter.updateClientSendingRate({}); + this.standardRetryStrategy.recordSuccess(token); + } +}; + +// src/ConfiguredRetryStrategy.ts +var ConfiguredRetryStrategy = class extends StandardRetryStrategy { + static { + __name(this, "ConfiguredRetryStrategy"); + } + /** + * @param maxAttempts - the maximum number of retry attempts allowed. + * e.g., if set to 3, then 4 total requests are possible. + * @param computeNextBackoffDelay - a millisecond delay for each retry or a function that takes the retry attempt + * and returns the delay. + * + * @example exponential backoff. + * ```js + * new Client({ + * retryStrategy: new ConfiguredRetryStrategy(3, (attempt) => attempt ** 2) + * }); + * ``` + * @example constant delay. + * ```js + * new Client({ + * retryStrategy: new ConfiguredRetryStrategy(3, 2000) + * }); + * ``` + */ + constructor(maxAttempts, computeNextBackoffDelay = DEFAULT_RETRY_DELAY_BASE) { + super(typeof maxAttempts === "function" ? maxAttempts : async () => maxAttempts); + if (typeof computeNextBackoffDelay === "number") { + this.computeNextBackoffDelay = () => computeNextBackoffDelay; + } else { + this.computeNextBackoffDelay = computeNextBackoffDelay; + } + } + async refreshRetryTokenForRetry(tokenToRenew, errorInfo) { + const token = await super.refreshRetryTokenForRetry(tokenToRenew, errorInfo); + token.getRetryDelay = () => this.computeNextBackoffDelay(token.getRetryCount()); + return token; + } +}; +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 31732: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ByteArrayCollector = void 0; +class ByteArrayCollector { + constructor(allocByteArray) { + this.allocByteArray = allocByteArray; + this.byteLength = 0; + this.byteArrays = []; + } + push(byteArray) { + this.byteArrays.push(byteArray); + this.byteLength += byteArray.byteLength; + } + flush() { + if (this.byteArrays.length === 1) { + const bytes = this.byteArrays[0]; + this.reset(); + return bytes; + } + const aggregation = this.allocByteArray(this.byteLength); + let cursor = 0; + for (let i = 0; i < this.byteArrays.length; ++i) { + const bytes = this.byteArrays[i]; + aggregation.set(bytes, cursor); + cursor += bytes.byteLength; + } + this.reset(); + return aggregation; + } + reset() { + this.byteArrays = []; + this.byteLength = 0; + } +} +exports.ByteArrayCollector = ByteArrayCollector; + + +/***/ }), + +/***/ 87753: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ChecksumStream = void 0; +const ReadableStreamRef = typeof ReadableStream === "function" ? ReadableStream : function () { }; +class ChecksumStream extends ReadableStreamRef { +} +exports.ChecksumStream = ChecksumStream; + + +/***/ }), + +/***/ 71775: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ChecksumStream = void 0; +const util_base64_1 = __nccwpck_require__(68385); +const stream_1 = __nccwpck_require__(2203); +class ChecksumStream extends stream_1.Duplex { + constructor({ expectedChecksum, checksum, source, checksumSourceLocation, base64Encoder, }) { + var _a, _b; + super(); + if (typeof source.pipe === "function") { + this.source = source; + } + else { + throw new Error(`@smithy/util-stream: unsupported source type ${(_b = (_a = source === null || source === void 0 ? void 0 : source.constructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : source} in ChecksumStream.`); + } + this.base64Encoder = base64Encoder !== null && base64Encoder !== void 0 ? base64Encoder : util_base64_1.toBase64; + this.expectedChecksum = expectedChecksum; + this.checksum = checksum; + this.checksumSourceLocation = checksumSourceLocation; + this.source.pipe(this); + } + _read(size) { } + _write(chunk, encoding, callback) { + try { + this.checksum.update(chunk); + this.push(chunk); + } + catch (e) { + return callback(e); + } + return callback(); + } + async _final(callback) { + try { + const digest = await this.checksum.digest(); + const received = this.base64Encoder(digest); + if (this.expectedChecksum !== received) { + return callback(new Error(`Checksum mismatch: expected "${this.expectedChecksum}" but received "${received}"` + + ` in response header "${this.checksumSourceLocation}".`)); + } + } + catch (e) { + return callback(e); + } + this.push(null); + return callback(); + } +} +exports.ChecksumStream = ChecksumStream; + + +/***/ }), + +/***/ 94129: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createChecksumStream = void 0; +const util_base64_1 = __nccwpck_require__(68385); +const stream_type_check_1 = __nccwpck_require__(4414); +const ChecksumStream_browser_1 = __nccwpck_require__(87753); +const createChecksumStream = ({ expectedChecksum, checksum, source, checksumSourceLocation, base64Encoder, }) => { + var _a, _b; + if (!(0, stream_type_check_1.isReadableStream)(source)) { + throw new Error(`@smithy/util-stream: unsupported source type ${(_b = (_a = source === null || source === void 0 ? void 0 : source.constructor) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : source} in ChecksumStream.`); + } + const encoder = base64Encoder !== null && base64Encoder !== void 0 ? base64Encoder : util_base64_1.toBase64; + if (typeof TransformStream !== "function") { + throw new Error("@smithy/util-stream: unable to instantiate ChecksumStream because API unavailable: ReadableStream/TransformStream."); + } + const transform = new TransformStream({ + start() { }, + async transform(chunk, controller) { + checksum.update(chunk); + controller.enqueue(chunk); + }, + async flush(controller) { + const digest = await checksum.digest(); + const received = encoder(digest); + if (expectedChecksum !== received) { + const error = new Error(`Checksum mismatch: expected "${expectedChecksum}" but received "${received}"` + + ` in response header "${checksumSourceLocation}".`); + controller.error(error); + } + else { + controller.terminate(); + } + }, + }); + source.pipeThrough(transform); + const readable = transform.readable; + Object.setPrototypeOf(readable, ChecksumStream_browser_1.ChecksumStream.prototype); + return readable; +}; +exports.createChecksumStream = createChecksumStream; + + +/***/ }), + +/***/ 5639: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createChecksumStream = createChecksumStream; +const stream_type_check_1 = __nccwpck_require__(4414); +const ChecksumStream_1 = __nccwpck_require__(71775); +const createChecksumStream_browser_1 = __nccwpck_require__(94129); +function createChecksumStream(init) { + if (typeof ReadableStream === "function" && (0, stream_type_check_1.isReadableStream)(init.source)) { + return (0, createChecksumStream_browser_1.createChecksumStream)(init); + } + return new ChecksumStream_1.ChecksumStream(init); +} + + +/***/ }), + +/***/ 72005: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createBufferedReadable = createBufferedReadable; +const node_stream_1 = __nccwpck_require__(57075); +const ByteArrayCollector_1 = __nccwpck_require__(31732); +const createBufferedReadableStream_1 = __nccwpck_require__(78213); +const stream_type_check_1 = __nccwpck_require__(4414); +function createBufferedReadable(upstream, size, logger) { + if ((0, stream_type_check_1.isReadableStream)(upstream)) { + return (0, createBufferedReadableStream_1.createBufferedReadableStream)(upstream, size, logger); + } + const downstream = new node_stream_1.Readable({ read() { } }); + let streamBufferingLoggedWarning = false; + let bytesSeen = 0; + const buffers = [ + "", + new ByteArrayCollector_1.ByteArrayCollector((size) => new Uint8Array(size)), + new ByteArrayCollector_1.ByteArrayCollector((size) => Buffer.from(new Uint8Array(size))), + ]; + let mode = -1; + upstream.on("data", (chunk) => { + const chunkMode = (0, createBufferedReadableStream_1.modeOf)(chunk, true); + if (mode !== chunkMode) { + if (mode >= 0) { + downstream.push((0, createBufferedReadableStream_1.flush)(buffers, mode)); + } + mode = chunkMode; + } + if (mode === -1) { + downstream.push(chunk); + return; + } + const chunkSize = (0, createBufferedReadableStream_1.sizeOf)(chunk); + bytesSeen += chunkSize; + const bufferSize = (0, createBufferedReadableStream_1.sizeOf)(buffers[mode]); + if (chunkSize >= size && bufferSize === 0) { + downstream.push(chunk); + } + else { + const newSize = (0, createBufferedReadableStream_1.merge)(buffers, mode, chunk); + if (!streamBufferingLoggedWarning && bytesSeen > size * 2) { + streamBufferingLoggedWarning = true; + logger === null || logger === void 0 ? void 0 : logger.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`); + } + if (newSize >= size) { + downstream.push((0, createBufferedReadableStream_1.flush)(buffers, mode)); + } + } + }); + upstream.on("end", () => { + if (mode !== -1) { + const remainder = (0, createBufferedReadableStream_1.flush)(buffers, mode); + if ((0, createBufferedReadableStream_1.sizeOf)(remainder) > 0) { + downstream.push(remainder); + } + } + downstream.push(null); + }); + return downstream; +} + + +/***/ }), + +/***/ 78213: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createBufferedReadable = void 0; +exports.createBufferedReadableStream = createBufferedReadableStream; +exports.merge = merge; +exports.flush = flush; +exports.sizeOf = sizeOf; +exports.modeOf = modeOf; +const ByteArrayCollector_1 = __nccwpck_require__(31732); +function createBufferedReadableStream(upstream, size, logger) { + const reader = upstream.getReader(); + let streamBufferingLoggedWarning = false; + let bytesSeen = 0; + const buffers = ["", new ByteArrayCollector_1.ByteArrayCollector((size) => new Uint8Array(size))]; + let mode = -1; + const pull = async (controller) => { + const { value, done } = await reader.read(); + const chunk = value; + if (done) { + if (mode !== -1) { + const remainder = flush(buffers, mode); + if (sizeOf(remainder) > 0) { + controller.enqueue(remainder); + } + } + controller.close(); + } + else { + const chunkMode = modeOf(chunk, false); + if (mode !== chunkMode) { + if (mode >= 0) { + controller.enqueue(flush(buffers, mode)); + } + mode = chunkMode; + } + if (mode === -1) { + controller.enqueue(chunk); + return; + } + const chunkSize = sizeOf(chunk); + bytesSeen += chunkSize; + const bufferSize = sizeOf(buffers[mode]); + if (chunkSize >= size && bufferSize === 0) { + controller.enqueue(chunk); + } + else { + const newSize = merge(buffers, mode, chunk); + if (!streamBufferingLoggedWarning && bytesSeen > size * 2) { + streamBufferingLoggedWarning = true; + logger === null || logger === void 0 ? void 0 : logger.warn(`@smithy/util-stream - stream chunk size ${chunkSize} is below threshold of ${size}, automatically buffering.`); + } + if (newSize >= size) { + controller.enqueue(flush(buffers, mode)); + } + else { + await pull(controller); + } + } + } + }; + return new ReadableStream({ + pull, + }); +} +exports.createBufferedReadable = createBufferedReadableStream; +function merge(buffers, mode, chunk) { + switch (mode) { + case 0: + buffers[0] += chunk; + return sizeOf(buffers[0]); + case 1: + case 2: + buffers[mode].push(chunk); + return sizeOf(buffers[mode]); + } +} +function flush(buffers, mode) { + switch (mode) { + case 0: + const s = buffers[0]; + buffers[0] = ""; + return s; + case 1: + case 2: + return buffers[mode].flush(); + } + throw new Error(`@smithy/util-stream - invalid index ${mode} given to flush()`); +} +function sizeOf(chunk) { + var _a, _b; + return (_b = (_a = chunk === null || chunk === void 0 ? void 0 : chunk.byteLength) !== null && _a !== void 0 ? _a : chunk === null || chunk === void 0 ? void 0 : chunk.length) !== null && _b !== void 0 ? _b : 0; +} +function modeOf(chunk, allowBuffer = true) { + if (allowBuffer && typeof Buffer !== "undefined" && chunk instanceof Buffer) { + return 2; + } + if (chunk instanceof Uint8Array) { + return 1; + } + if (typeof chunk === "string") { + return 0; + } + return -1; +} + + +/***/ }), + +/***/ 6522: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getAwsChunkedEncodingStream = void 0; +const stream_1 = __nccwpck_require__(2203); +const getAwsChunkedEncodingStream = (readableStream, options) => { + const { base64Encoder, bodyLengthChecker, checksumAlgorithmFn, checksumLocationName, streamHasher } = options; + const checksumRequired = base64Encoder !== undefined && + checksumAlgorithmFn !== undefined && + checksumLocationName !== undefined && + streamHasher !== undefined; + const digest = checksumRequired ? streamHasher(checksumAlgorithmFn, readableStream) : undefined; + const awsChunkedEncodingStream = new stream_1.Readable({ read: () => { } }); + readableStream.on("data", (data) => { + const length = bodyLengthChecker(data) || 0; + awsChunkedEncodingStream.push(`${length.toString(16)}\r\n`); + awsChunkedEncodingStream.push(data); + awsChunkedEncodingStream.push("\r\n"); + }); + readableStream.on("end", async () => { + awsChunkedEncodingStream.push(`0\r\n`); + if (checksumRequired) { + const checksum = base64Encoder(await digest); + awsChunkedEncodingStream.push(`${checksumLocationName}:${checksum}\r\n`); + awsChunkedEncodingStream.push(`\r\n`); + } + awsChunkedEncodingStream.push(null); + }); + return awsChunkedEncodingStream; +}; +exports.getAwsChunkedEncodingStream = getAwsChunkedEncodingStream; + + +/***/ }), + +/***/ 80066: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.headStream = headStream; +async function headStream(stream, bytes) { + var _a; + let byteLengthCounter = 0; + const chunks = []; + const reader = stream.getReader(); + let isDone = false; + while (!isDone) { + const { done, value } = await reader.read(); + if (value) { + chunks.push(value); + byteLengthCounter += (_a = value === null || value === void 0 ? void 0 : value.byteLength) !== null && _a !== void 0 ? _a : 0; + } + if (byteLengthCounter >= bytes) { + break; + } + isDone = done; + } + reader.releaseLock(); + const collected = new Uint8Array(Math.min(bytes, byteLengthCounter)); + let offset = 0; + for (const chunk of chunks) { + if (chunk.byteLength > collected.byteLength - offset) { + collected.set(chunk.subarray(0, collected.byteLength - offset), offset); + break; + } + else { + collected.set(chunk, offset); + } + offset += chunk.length; + } + return collected; +} + + +/***/ }), + +/***/ 88412: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.headStream = void 0; +const stream_1 = __nccwpck_require__(2203); +const headStream_browser_1 = __nccwpck_require__(80066); +const stream_type_check_1 = __nccwpck_require__(4414); +const headStream = (stream, bytes) => { + if ((0, stream_type_check_1.isReadableStream)(stream)) { + return (0, headStream_browser_1.headStream)(stream, bytes); + } + return new Promise((resolve, reject) => { + const collector = new Collector(); + collector.limit = bytes; + stream.pipe(collector); + stream.on("error", (err) => { + collector.end(); + reject(err); + }); + collector.on("error", reject); + collector.on("finish", function () { + const bytes = new Uint8Array(Buffer.concat(this.buffers)); + resolve(bytes); + }); + }); +}; +exports.headStream = headStream; +class Collector extends stream_1.Writable { + constructor() { + super(...arguments); + this.buffers = []; + this.limit = Infinity; + this.bytesBuffered = 0; + } + _write(chunk, encoding, callback) { + var _a; + this.buffers.push(chunk); + this.bytesBuffered += (_a = chunk.byteLength) !== null && _a !== void 0 ? _a : 0; + if (this.bytesBuffered >= this.limit) { + const excess = this.bytesBuffered - this.limit; + const tailBuffer = this.buffers[this.buffers.length - 1]; + this.buffers[this.buffers.length - 1] = tailBuffer.subarray(0, tailBuffer.byteLength - excess); + this.emit("finish"); + } + callback(); + } +} + + +/***/ }), + +/***/ 4252: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + Uint8ArrayBlobAdapter: () => Uint8ArrayBlobAdapter +}); +module.exports = __toCommonJS(src_exports); + +// src/blob/transforms.ts +var import_util_base64 = __nccwpck_require__(68385); +var import_util_utf8 = __nccwpck_require__(71577); +function transformToString(payload, encoding = "utf-8") { + if (encoding === "base64") { + return (0, import_util_base64.toBase64)(payload); + } + return (0, import_util_utf8.toUtf8)(payload); +} +__name(transformToString, "transformToString"); +function transformFromString(str, encoding) { + if (encoding === "base64") { + return Uint8ArrayBlobAdapter.mutate((0, import_util_base64.fromBase64)(str)); + } + return Uint8ArrayBlobAdapter.mutate((0, import_util_utf8.fromUtf8)(str)); +} +__name(transformFromString, "transformFromString"); + +// src/blob/Uint8ArrayBlobAdapter.ts +var Uint8ArrayBlobAdapter = class _Uint8ArrayBlobAdapter extends Uint8Array { + static { + __name(this, "Uint8ArrayBlobAdapter"); + } + /** + * @param source - such as a string or Stream. + * @returns a new Uint8ArrayBlobAdapter extending Uint8Array. + */ + static fromString(source, encoding = "utf-8") { + switch (typeof source) { + case "string": + return transformFromString(source, encoding); + default: + throw new Error(`Unsupported conversion from ${typeof source} to Uint8ArrayBlobAdapter.`); + } + } + /** + * @param source - Uint8Array to be mutated. + * @returns the same Uint8Array but with prototype switched to Uint8ArrayBlobAdapter. + */ + static mutate(source) { + Object.setPrototypeOf(source, _Uint8ArrayBlobAdapter.prototype); + return source; + } + /** + * @param encoding - default 'utf-8'. + * @returns the blob as string. + */ + transformToString(encoding = "utf-8") { + return transformToString(this, encoding); + } +}; + +// src/index.ts +__reExport(src_exports, __nccwpck_require__(71775), module.exports); +__reExport(src_exports, __nccwpck_require__(5639), module.exports); +__reExport(src_exports, __nccwpck_require__(72005), module.exports); +__reExport(src_exports, __nccwpck_require__(6522), module.exports); +__reExport(src_exports, __nccwpck_require__(88412), module.exports); +__reExport(src_exports, __nccwpck_require__(77201), module.exports); +__reExport(src_exports, __nccwpck_require__(82108), module.exports); +__reExport(src_exports, __nccwpck_require__(4414), module.exports); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 82207: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sdkStreamMixin = void 0; +const fetch_http_handler_1 = __nccwpck_require__(47809); +const util_base64_1 = __nccwpck_require__(68385); +const util_hex_encoding_1 = __nccwpck_require__(96435); +const util_utf8_1 = __nccwpck_require__(71577); +const stream_type_check_1 = __nccwpck_require__(4414); +const ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED = "The stream has already been transformed."; +const sdkStreamMixin = (stream) => { + var _a, _b; + if (!isBlobInstance(stream) && !(0, stream_type_check_1.isReadableStream)(stream)) { + const name = ((_b = (_a = stream === null || stream === void 0 ? void 0 : stream.__proto__) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) || stream; + throw new Error(`Unexpected stream implementation, expect Blob or ReadableStream, got ${name}`); + } + let transformed = false; + const transformToByteArray = async () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + transformed = true; + return await (0, fetch_http_handler_1.streamCollector)(stream); + }; + const blobToWebStream = (blob) => { + if (typeof blob.stream !== "function") { + throw new Error("Cannot transform payload Blob to web stream. Please make sure the Blob.stream() is polyfilled.\n" + + "If you are using React Native, this API is not yet supported, see: https://react-native.canny.io/feature-requests/p/fetch-streaming-body"); + } + return blob.stream(); + }; + return Object.assign(stream, { + transformToByteArray: transformToByteArray, + transformToString: async (encoding) => { + const buf = await transformToByteArray(); + if (encoding === "base64") { + return (0, util_base64_1.toBase64)(buf); + } + else if (encoding === "hex") { + return (0, util_hex_encoding_1.toHex)(buf); + } + else if (encoding === undefined || encoding === "utf8" || encoding === "utf-8") { + return (0, util_utf8_1.toUtf8)(buf); + } + else if (typeof TextDecoder === "function") { + return new TextDecoder(encoding).decode(buf); + } + else { + throw new Error("TextDecoder is not available, please make sure polyfill is provided."); + } + }, + transformToWebStream: () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + transformed = true; + if (isBlobInstance(stream)) { + return blobToWebStream(stream); + } + else if ((0, stream_type_check_1.isReadableStream)(stream)) { + return stream; + } + else { + throw new Error(`Cannot transform payload to web stream, got ${stream}`); + } + }, + }); +}; +exports.sdkStreamMixin = sdkStreamMixin; +const isBlobInstance = (stream) => typeof Blob === "function" && stream instanceof Blob; + + +/***/ }), + +/***/ 77201: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sdkStreamMixin = void 0; +const node_http_handler_1 = __nccwpck_require__(61279); +const util_buffer_from_1 = __nccwpck_require__(44151); +const stream_1 = __nccwpck_require__(2203); +const sdk_stream_mixin_browser_1 = __nccwpck_require__(82207); +const ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED = "The stream has already been transformed."; +const sdkStreamMixin = (stream) => { + var _a, _b; + if (!(stream instanceof stream_1.Readable)) { + try { + return (0, sdk_stream_mixin_browser_1.sdkStreamMixin)(stream); + } + catch (e) { + const name = ((_b = (_a = stream === null || stream === void 0 ? void 0 : stream.__proto__) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) || stream; + throw new Error(`Unexpected stream implementation, expect Stream.Readable instance, got ${name}`); + } + } + let transformed = false; + const transformToByteArray = async () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + transformed = true; + return await (0, node_http_handler_1.streamCollector)(stream); + }; + return Object.assign(stream, { + transformToByteArray, + transformToString: async (encoding) => { + const buf = await transformToByteArray(); + if (encoding === undefined || Buffer.isEncoding(encoding)) { + return (0, util_buffer_from_1.fromArrayBuffer)(buf.buffer, buf.byteOffset, buf.byteLength).toString(encoding); + } + else { + const decoder = new TextDecoder(encoding); + return decoder.decode(buf); + } + }, + transformToWebStream: () => { + if (transformed) { + throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED); + } + if (stream.readableFlowing !== null) { + throw new Error("The stream has been consumed by other callbacks."); + } + if (typeof stream_1.Readable.toWeb !== "function") { + throw new Error("Readable.toWeb() is not supported. Please ensure a polyfill is available."); + } + transformed = true; + return stream_1.Readable.toWeb(stream); + }, + }); +}; +exports.sdkStreamMixin = sdkStreamMixin; + + +/***/ }), + +/***/ 17570: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.splitStream = splitStream; +async function splitStream(stream) { + if (typeof stream.stream === "function") { + stream = stream.stream(); + } + const readableStream = stream; + return readableStream.tee(); +} + + +/***/ }), + +/***/ 82108: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.splitStream = splitStream; +const stream_1 = __nccwpck_require__(2203); +const splitStream_browser_1 = __nccwpck_require__(17570); +const stream_type_check_1 = __nccwpck_require__(4414); +async function splitStream(stream) { + if ((0, stream_type_check_1.isReadableStream)(stream) || (0, stream_type_check_1.isBlob)(stream)) { + return (0, splitStream_browser_1.splitStream)(stream); + } + const stream1 = new stream_1.PassThrough(); + const stream2 = new stream_1.PassThrough(); + stream.pipe(stream1); + stream.pipe(stream2); + return [stream1, stream2]; +} + + +/***/ }), + +/***/ 4414: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isBlob = exports.isReadableStream = void 0; +const isReadableStream = (stream) => { + var _a; + return typeof ReadableStream === "function" && + (((_a = stream === null || stream === void 0 ? void 0 : stream.constructor) === null || _a === void 0 ? void 0 : _a.name) === ReadableStream.name || stream instanceof ReadableStream); +}; +exports.isReadableStream = isReadableStream; +const isBlob = (blob) => { + var _a; + return typeof Blob === "function" && (((_a = blob === null || blob === void 0 ? void 0 : blob.constructor) === null || _a === void 0 ? void 0 : _a.name) === Blob.name || blob instanceof Blob); +}; +exports.isBlob = isBlob; + + +/***/ }), + +/***/ 80146: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + escapeUri: () => escapeUri, + escapeUriPath: () => escapeUriPath +}); +module.exports = __toCommonJS(src_exports); + +// src/escape-uri.ts +var escapeUri = /* @__PURE__ */ __name((uri) => ( + // AWS percent-encodes some extra non-standard characters in a URI + encodeURIComponent(uri).replace(/[!'()*]/g, hexEncode) +), "escapeUri"); +var hexEncode = /* @__PURE__ */ __name((c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`, "hexEncode"); + +// src/escape-uri-path.ts +var escapeUriPath = /* @__PURE__ */ __name((uri) => uri.split("/").map(escapeUri).join("/"), "escapeUriPath"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 71577: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + fromUtf8: () => fromUtf8, + toUint8Array: () => toUint8Array, + toUtf8: () => toUtf8 +}); +module.exports = __toCommonJS(src_exports); + +// src/fromUtf8.ts +var import_util_buffer_from = __nccwpck_require__(44151); +var fromUtf8 = /* @__PURE__ */ __name((input) => { + const buf = (0, import_util_buffer_from.fromString)(input, "utf8"); + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength / Uint8Array.BYTES_PER_ELEMENT); +}, "fromUtf8"); + +// src/toUint8Array.ts +var toUint8Array = /* @__PURE__ */ __name((data) => { + if (typeof data === "string") { + return fromUtf8(data); + } + if (ArrayBuffer.isView(data)) { + return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT); + } + return new Uint8Array(data); +}, "toUint8Array"); + +// src/toUtf8.ts + +var toUtf8 = /* @__PURE__ */ __name((input) => { + if (typeof input === "string") { + return input; + } + if (typeof input !== "object" || typeof input.byteOffset !== "number" || typeof input.byteLength !== "number") { + throw new Error("@smithy/util-utf8: toUtf8 encoder function only accepts string | Uint8Array."); + } + return (0, import_util_buffer_from.fromArrayBuffer)(input.buffer, input.byteOffset, input.byteLength).toString("utf8"); +}, "toUtf8"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 95290: +/***/ ((module) => { + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/index.ts +var src_exports = {}; +__export(src_exports, { + WaiterState: () => WaiterState, + checkExceptions: () => checkExceptions, + createWaiter: () => createWaiter, + waiterServiceDefaults: () => waiterServiceDefaults +}); +module.exports = __toCommonJS(src_exports); + +// src/utils/sleep.ts +var sleep = /* @__PURE__ */ __name((seconds) => { + return new Promise((resolve) => setTimeout(resolve, seconds * 1e3)); +}, "sleep"); + +// src/waiter.ts +var waiterServiceDefaults = { + minDelay: 2, + maxDelay: 120 +}; +var WaiterState = /* @__PURE__ */ ((WaiterState2) => { + WaiterState2["ABORTED"] = "ABORTED"; + WaiterState2["FAILURE"] = "FAILURE"; + WaiterState2["SUCCESS"] = "SUCCESS"; + WaiterState2["RETRY"] = "RETRY"; + WaiterState2["TIMEOUT"] = "TIMEOUT"; + return WaiterState2; +})(WaiterState || {}); +var checkExceptions = /* @__PURE__ */ __name((result) => { + if (result.state === "ABORTED" /* ABORTED */) { + const abortError = new Error( + `${JSON.stringify({ + ...result, + reason: "Request was aborted" + })}` + ); + abortError.name = "AbortError"; + throw abortError; + } else if (result.state === "TIMEOUT" /* TIMEOUT */) { + const timeoutError = new Error( + `${JSON.stringify({ + ...result, + reason: "Waiter has timed out" + })}` + ); + timeoutError.name = "TimeoutError"; + throw timeoutError; + } else if (result.state !== "SUCCESS" /* SUCCESS */) { + throw new Error(`${JSON.stringify(result)}`); + } + return result; +}, "checkExceptions"); + +// src/poller.ts +var exponentialBackoffWithJitter = /* @__PURE__ */ __name((minDelay, maxDelay, attemptCeiling, attempt) => { + if (attempt > attemptCeiling) + return maxDelay; + const delay = minDelay * 2 ** (attempt - 1); + return randomInRange(minDelay, delay); +}, "exponentialBackoffWithJitter"); +var randomInRange = /* @__PURE__ */ __name((min, max) => min + Math.random() * (max - min), "randomInRange"); +var runPolling = /* @__PURE__ */ __name(async ({ minDelay, maxDelay, maxWaitTime, abortController, client, abortSignal }, input, acceptorChecks) => { + const observedResponses = {}; + const { state, reason } = await acceptorChecks(client, input); + if (reason) { + const message = createMessageFromResponse(reason); + observedResponses[message] |= 0; + observedResponses[message] += 1; + } + if (state !== "RETRY" /* RETRY */) { + return { state, reason, observedResponses }; + } + let currentAttempt = 1; + const waitUntil = Date.now() + maxWaitTime * 1e3; + const attemptCeiling = Math.log(maxDelay / minDelay) / Math.log(2) + 1; + while (true) { + if (abortController?.signal?.aborted || abortSignal?.aborted) { + const message = "AbortController signal aborted."; + observedResponses[message] |= 0; + observedResponses[message] += 1; + return { state: "ABORTED" /* ABORTED */, observedResponses }; + } + const delay = exponentialBackoffWithJitter(minDelay, maxDelay, attemptCeiling, currentAttempt); + if (Date.now() + delay * 1e3 > waitUntil) { + return { state: "TIMEOUT" /* TIMEOUT */, observedResponses }; + } + await sleep(delay); + const { state: state2, reason: reason2 } = await acceptorChecks(client, input); + if (reason2) { + const message = createMessageFromResponse(reason2); + observedResponses[message] |= 0; + observedResponses[message] += 1; + } + if (state2 !== "RETRY" /* RETRY */) { + return { state: state2, reason: reason2, observedResponses }; + } + currentAttempt += 1; + } +}, "runPolling"); +var createMessageFromResponse = /* @__PURE__ */ __name((reason) => { + if (reason?.$responseBodyText) { + return `Deserialization error for body: ${reason.$responseBodyText}`; + } + if (reason?.$metadata?.httpStatusCode) { + if (reason.$response || reason.message) { + return `${reason.$response.statusCode ?? reason.$metadata.httpStatusCode ?? "Unknown"}: ${reason.message}`; + } + return `${reason.$metadata.httpStatusCode}: OK`; + } + return String(reason?.message ?? JSON.stringify(reason) ?? "Unknown"); +}, "createMessageFromResponse"); + +// src/utils/validate.ts +var validateWaiterOptions = /* @__PURE__ */ __name((options) => { + if (options.maxWaitTime <= 0) { + throw new Error(`WaiterConfiguration.maxWaitTime must be greater than 0`); + } else if (options.minDelay <= 0) { + throw new Error(`WaiterConfiguration.minDelay must be greater than 0`); + } else if (options.maxDelay <= 0) { + throw new Error(`WaiterConfiguration.maxDelay must be greater than 0`); + } else if (options.maxWaitTime <= options.minDelay) { + throw new Error( + `WaiterConfiguration.maxWaitTime [${options.maxWaitTime}] must be greater than WaiterConfiguration.minDelay [${options.minDelay}] for this waiter` + ); + } else if (options.maxDelay < options.minDelay) { + throw new Error( + `WaiterConfiguration.maxDelay [${options.maxDelay}] must be greater than WaiterConfiguration.minDelay [${options.minDelay}] for this waiter` + ); + } +}, "validateWaiterOptions"); + +// src/createWaiter.ts +var abortTimeout = /* @__PURE__ */ __name((abortSignal) => { + let onAbort; + const promise = new Promise((resolve) => { + onAbort = /* @__PURE__ */ __name(() => resolve({ state: "ABORTED" /* ABORTED */ }), "onAbort"); + if (typeof abortSignal.addEventListener === "function") { + abortSignal.addEventListener("abort", onAbort); + } else { + abortSignal.onabort = onAbort; + } + }); + return { + clearListener() { + if (typeof abortSignal.removeEventListener === "function") { + abortSignal.removeEventListener("abort", onAbort); + } + }, + aborted: promise + }; +}, "abortTimeout"); +var createWaiter = /* @__PURE__ */ __name(async (options, input, acceptorChecks) => { + const params = { + ...waiterServiceDefaults, + ...options + }; + validateWaiterOptions(params); + const exitConditions = [runPolling(params, input, acceptorChecks)]; + const finalize = []; + if (options.abortSignal) { + const { aborted, clearListener } = abortTimeout(options.abortSignal); + finalize.push(clearListener); + exitConditions.push(aborted); + } + if (options.abortController?.signal) { + const { aborted, clearListener } = abortTimeout(options.abortController.signal); + finalize.push(clearListener); + exitConditions.push(aborted); + } + return Promise.race(exitConditions).then((result) => { + for (const fn of finalize) { + fn(); + } + return result; + }); +}, "createWaiter"); +// Annotate the CommonJS export names for ESM import in node: + +0 && (0); + + + +/***/ }), + +/***/ 48662: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function once(emitter, name, { signal } = {}) { + return new Promise((resolve, reject) => { + function cleanup() { + signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', cleanup); + emitter.removeListener(name, onEvent); + emitter.removeListener('error', onError); + } + function onEvent(...args) { + cleanup(); + resolve(args); + } + function onError(err) { + cleanup(); + reject(err); + } + signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', cleanup); + emitter.on(name, onEvent); + emitter.on('error', onError); + }); +} +exports["default"] = once; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 17413: +/***/ ((module, exports, __nccwpck_require__) => { + +"use strict"; +/** + * @author Toru Nagashima + * See LICENSE file in root directory for full license. + */ + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var eventTargetShim = __nccwpck_require__(16577); + +/** + * The signal class. + * @see https://dom.spec.whatwg.org/#abortsignal + */ +class AbortSignal extends eventTargetShim.EventTarget { + /** + * AbortSignal cannot be constructed directly. + */ + constructor() { + super(); + throw new TypeError("AbortSignal cannot be constructed directly"); + } + /** + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise. + */ + get aborted() { + const aborted = abortedFlags.get(this); + if (typeof aborted !== "boolean") { + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`); + } + return aborted; + } +} +eventTargetShim.defineEventAttribute(AbortSignal.prototype, "abort"); +/** + * Create an AbortSignal object. + */ +function createAbortSignal() { + const signal = Object.create(AbortSignal.prototype); + eventTargetShim.EventTarget.call(signal); + abortedFlags.set(signal, false); + return signal; +} +/** + * Abort a given signal. + */ +function abortSignal(signal) { + if (abortedFlags.get(signal) !== false) { + return; + } + abortedFlags.set(signal, true); + signal.dispatchEvent({ type: "abort" }); +} +/** + * Aborted flag for each instances. + */ +const abortedFlags = new WeakMap(); +// Properties should be enumerable. +Object.defineProperties(AbortSignal.prototype, { + aborted: { enumerable: true }, +}); +// `toString()` should return `"[object AbortSignal]"` +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortSignal", + }); +} + +/** + * The AbortController. + * @see https://dom.spec.whatwg.org/#abortcontroller + */ +class AbortController { + /** + * Initialize this controller. + */ + constructor() { + signals.set(this, createAbortSignal()); + } + /** + * Returns the `AbortSignal` object associated with this object. + */ + get signal() { + return getSignal(this); + } + /** + * Abort and signal to any observers that the associated activity is to be aborted. + */ + abort() { + abortSignal(getSignal(this)); + } +} +/** + * Associated signals. + */ +const signals = new WeakMap(); +/** + * Get the associated signal of a given controller. + */ +function getSignal(controller) { + const signal = signals.get(controller); + if (signal == null) { + throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`); + } + return signal; +} +// Properties should be enumerable. +Object.defineProperties(AbortController.prototype, { + signal: { enumerable: true }, + abort: { enumerable: true }, +}); +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortController.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortController", + }); +} + +exports.AbortController = AbortController; +exports.AbortSignal = AbortSignal; +exports["default"] = AbortController; + +module.exports = AbortController +module.exports.AbortController = module.exports["default"] = AbortController +module.exports.AbortSignal = AbortSignal +//# sourceMappingURL=abort-controller.js.map + + +/***/ }), + +/***/ 15183: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.req = exports.json = exports.toBuffer = void 0; +const http = __importStar(__nccwpck_require__(58611)); +const https = __importStar(__nccwpck_require__(65692)); +async function toBuffer(stream) { + let length = 0; + const chunks = []; + for await (const chunk of stream) { + length += chunk.length; + chunks.push(chunk); + } + return Buffer.concat(chunks, length); +} +exports.toBuffer = toBuffer; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function json(stream) { + const buf = await toBuffer(stream); + const str = buf.toString('utf8'); + try { + return JSON.parse(str); + } + catch (_err) { + const err = _err; + err.message += ` (input: ${str})`; + throw err; + } +} +exports.json = json; +function req(url, opts = {}) { + const href = typeof url === 'string' ? url : url.href; + const req = (href.startsWith('https:') ? https : http).request(url, opts); + const promise = new Promise((resolve, reject) => { + req + .once('response', resolve) + .once('error', reject) + .end(); + }); + req.then = promise.then.bind(promise); + return req; +} +exports.req = req; +//# sourceMappingURL=helpers.js.map + +/***/ }), + +/***/ 98894: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Agent = void 0; +const net = __importStar(__nccwpck_require__(69278)); +const http = __importStar(__nccwpck_require__(58611)); +const https_1 = __nccwpck_require__(65692); +__exportStar(__nccwpck_require__(15183), exports); +const INTERNAL = Symbol('AgentBaseInternalState'); +class Agent extends http.Agent { + constructor(opts) { + super(opts); + this[INTERNAL] = {}; + } + /** + * Determine whether this is an `http` or `https` request. + */ + isSecureEndpoint(options) { + if (options) { + // First check the `secureEndpoint` property explicitly, since this + // means that a parent `Agent` is "passing through" to this instance. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof options.secureEndpoint === 'boolean') { + return options.secureEndpoint; + } + // If no explicit `secure` endpoint, check if `protocol` property is + // set. This will usually be the case since using a full string URL + // or `URL` instance should be the most common usage. + if (typeof options.protocol === 'string') { + return options.protocol === 'https:'; + } + } + // Finally, if no `protocol` property was set, then fall back to + // checking the stack trace of the current call stack, and try to + // detect the "https" module. + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack + .split('\n') + .some((l) => l.indexOf('(https.js:') !== -1 || + l.indexOf('node:https:') !== -1); + } + // In order to support async signatures in `connect()` and Node's native + // connection pooling in `http.Agent`, the array of sockets for each origin + // has to be updated synchronously. This is so the length of the array is + // accurate when `addRequest()` is next called. We achieve this by creating a + // fake socket and adding it to `sockets[origin]` and incrementing + // `totalSocketCount`. + incrementSockets(name) { + // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no + // need to create a fake socket because Node.js native connection pooling + // will never be invoked. + if (this.maxSockets === Infinity && this.maxTotalSockets === Infinity) { + return null; + } + // All instances of `sockets` are expected TypeScript errors. The + // alternative is to add it as a private property of this class but that + // will break TypeScript subclassing. + if (!this.sockets[name]) { + // @ts-expect-error `sockets` is readonly in `@types/node` + this.sockets[name] = []; + } + const fakeSocket = new net.Socket({ writable: false }); + this.sockets[name].push(fakeSocket); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount++; + return fakeSocket; + } + decrementSockets(name, socket) { + if (!this.sockets[name] || socket === null) { + return; + } + const sockets = this.sockets[name]; + const index = sockets.indexOf(socket); + if (index !== -1) { + sockets.splice(index, 1); + // @ts-expect-error `totalSocketCount` isn't defined in `@types/node` + this.totalSocketCount--; + if (sockets.length === 0) { + // @ts-expect-error `sockets` is readonly in `@types/node` + delete this.sockets[name]; + } + } + } + // In order to properly update the socket pool, we need to call `getName()` on + // the core `https.Agent` if it is a secureEndpoint. + getName(options) { + const secureEndpoint = this.isSecureEndpoint(options); + if (secureEndpoint) { + // @ts-expect-error `getName()` isn't defined in `@types/node` + return https_1.Agent.prototype.getName.call(this, options); + } + // @ts-expect-error `getName()` isn't defined in `@types/node` + return super.getName(options); + } + createSocket(req, options, cb) { + const connectOpts = { + ...options, + secureEndpoint: this.isSecureEndpoint(options), + }; + const name = this.getName(connectOpts); + const fakeSocket = this.incrementSockets(name); + Promise.resolve() + .then(() => this.connect(req, connectOpts)) + .then((socket) => { + this.decrementSockets(name, fakeSocket); + if (socket instanceof http.Agent) { + try { + // @ts-expect-error `addRequest()` isn't defined in `@types/node` + return socket.addRequest(req, connectOpts); + } + catch (err) { + return cb(err); + } + } + this[INTERNAL].currentSocket = socket; + // @ts-expect-error `createSocket()` isn't defined in `@types/node` + super.createSocket(req, options, cb); + }, (err) => { + this.decrementSockets(name, fakeSocket); + cb(err); + }); + } + createConnection() { + const socket = this[INTERNAL].currentSocket; + this[INTERNAL].currentSocket = undefined; + if (!socket) { + throw new Error('No socket was returned in the `connect()` function'); + } + return socket; + } + get defaultPort() { + return (this[INTERNAL].defaultPort ?? + (this.protocol === 'https:' ? 443 : 80)); + } + set defaultPort(v) { + if (this[INTERNAL]) { + this[INTERNAL].defaultPort = v; + } + } + get protocol() { + return (this[INTERNAL].protocol ?? + (this.isSecureEndpoint() ? 'https:' : 'http:')); + } + set protocol(v) { + if (this[INTERNAL]) { + this[INTERNAL].protocol = v; + } + } +} +exports.Agent = Agent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 26251: +/***/ ((module) => { + +"use strict"; + + +const arrify = value => { + if (value === null || value === undefined) { + return []; + } + + if (Array.isArray(value)) { + return value; + } + + if (typeof value === 'string') { + return [value]; + } + + if (typeof value[Symbol.iterator] === 'function') { + return [...value]; + } + + return [value]; +}; + +module.exports = arrify; + + +/***/ }), + +/***/ 45195: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +// Packages +var retrier = __nccwpck_require__(5546); + +function retry(fn, opts) { + function run(resolve, reject) { + var options = opts || {}; + var op; + + // Default `randomize` to true + if (!('randomize' in options)) { + options.randomize = true; + } + + op = retrier.operation(options); + + // We allow the user to abort retrying + // this makes sense in the cases where + // knowledge is obtained that retrying + // would be futile (e.g.: auth errors) + + function bail(err) { + reject(err || new Error('Aborted')); + } + + function onError(err, num) { + if (err.bail) { + bail(err); + return; + } + + if (!op.retry(err)) { + reject(op.mainError()); + } else if (options.onRetry) { + options.onRetry(err, num); + } + } + + function runAttempt(num) { + var val; + + try { + val = fn(bail, num); + } catch (err) { + onError(err, num); + return; + } + + Promise.resolve(val) + .then(resolve) + .catch(function catchIt(err) { + onError(err, num); + }); + } + + op.attempt(runAttempt); + } + + return new Promise(run); +} + +module.exports = retry; + + +/***/ }), + +/***/ 38793: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + + +/***/ }), + +/***/ 51259: +/***/ (function(module) { + +;(function (globalObject) { + 'use strict'; + +/* + * bignumber.js v9.3.1 + * A JavaScript library for arbitrary-precision arithmetic. + * https://github.com/MikeMcl/bignumber.js + * Copyright (c) 2025 Michael Mclaughlin + * MIT Licensed. + * + * BigNumber.prototype methods | BigNumber methods + * | + * absoluteValue abs | clone + * comparedTo | config set + * decimalPlaces dp | DECIMAL_PLACES + * dividedBy div | ROUNDING_MODE + * dividedToIntegerBy idiv | EXPONENTIAL_AT + * exponentiatedBy pow | RANGE + * integerValue | CRYPTO + * isEqualTo eq | MODULO_MODE + * isFinite | POW_PRECISION + * isGreaterThan gt | FORMAT + * isGreaterThanOrEqualTo gte | ALPHABET + * isInteger | isBigNumber + * isLessThan lt | maximum max + * isLessThanOrEqualTo lte | minimum min + * isNaN | random + * isNegative | sum + * isPositive | + * isZero | + * minus | + * modulo mod | + * multipliedBy times | + * negated | + * plus | + * precision sd | + * shiftedBy | + * squareRoot sqrt | + * toExponential | + * toFixed | + * toFormat | + * toFraction | + * toJSON | + * toNumber | + * toPrecision | + * toString | + * valueOf | + * + */ + + + var BigNumber, + isNumeric = /^-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i, + mathceil = Math.ceil, + mathfloor = Math.floor, + + bignumberError = '[BigNumber Error] ', + tooManyDigits = bignumberError + 'Number primitive has more than 15 significant digits: ', + + BASE = 1e14, + LOG_BASE = 14, + MAX_SAFE_INTEGER = 0x1fffffffffffff, // 2^53 - 1 + // MAX_INT32 = 0x7fffffff, // 2^31 - 1 + POWS_TEN = [1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13], + SQRT_BASE = 1e7, + + // EDITABLE + // The limit on the value of DECIMAL_PLACES, TO_EXP_NEG, TO_EXP_POS, MIN_EXP, MAX_EXP, and + // the arguments to toExponential, toFixed, toFormat, and toPrecision. + MAX = 1E9; // 0 to MAX_INT32 + + + /* + * Create and return a BigNumber constructor. + */ + function clone(configObject) { + var div, convertBase, parseNumeric, + P = BigNumber.prototype = { constructor: BigNumber, toString: null, valueOf: null }, + ONE = new BigNumber(1), + + + //----------------------------- EDITABLE CONFIG DEFAULTS ------------------------------- + + + // The default values below must be integers within the inclusive ranges stated. + // The values can also be changed at run-time using BigNumber.set. + + // The maximum number of decimal places for operations involving division. + DECIMAL_PLACES = 20, // 0 to MAX + + // The rounding mode used when rounding to the above decimal places, and when using + // toExponential, toFixed, toFormat and toPrecision, and round (default value). + // UP 0 Away from zero. + // DOWN 1 Towards zero. + // CEIL 2 Towards +Infinity. + // FLOOR 3 Towards -Infinity. + // HALF_UP 4 Towards nearest neighbour. If equidistant, up. + // HALF_DOWN 5 Towards nearest neighbour. If equidistant, down. + // HALF_EVEN 6 Towards nearest neighbour. If equidistant, towards even neighbour. + // HALF_CEIL 7 Towards nearest neighbour. If equidistant, towards +Infinity. + // HALF_FLOOR 8 Towards nearest neighbour. If equidistant, towards -Infinity. + ROUNDING_MODE = 4, // 0 to 8 + + // EXPONENTIAL_AT : [TO_EXP_NEG , TO_EXP_POS] + + // The exponent value at and beneath which toString returns exponential notation. + // Number type: -7 + TO_EXP_NEG = -7, // 0 to -MAX + + // The exponent value at and above which toString returns exponential notation. + // Number type: 21 + TO_EXP_POS = 21, // 0 to MAX + + // RANGE : [MIN_EXP, MAX_EXP] + + // The minimum exponent value, beneath which underflow to zero occurs. + // Number type: -324 (5e-324) + MIN_EXP = -1e7, // -1 to -MAX + + // The maximum exponent value, above which overflow to Infinity occurs. + // Number type: 308 (1.7976931348623157e+308) + // For MAX_EXP > 1e7, e.g. new BigNumber('1e100000000').plus(1) may be slow. + MAX_EXP = 1e7, // 1 to MAX + + // Whether to use cryptographically-secure random number generation, if available. + CRYPTO = false, // true or false + + // The modulo mode used when calculating the modulus: a mod n. + // The quotient (q = a / n) is calculated according to the corresponding rounding mode. + // The remainder (r) is calculated as: r = a - n * q. + // + // UP 0 The remainder is positive if the dividend is negative, else is negative. + // DOWN 1 The remainder has the same sign as the dividend. + // This modulo mode is commonly known as 'truncated division' and is + // equivalent to (a % n) in JavaScript. + // FLOOR 3 The remainder has the same sign as the divisor (Python %). + // HALF_EVEN 6 This modulo mode implements the IEEE 754 remainder function. + // EUCLID 9 Euclidian division. q = sign(n) * floor(a / abs(n)). + // The remainder is always positive. + // + // The truncated division, floored division, Euclidian division and IEEE 754 remainder + // modes are commonly used for the modulus operation. + // Although the other rounding modes can also be used, they may not give useful results. + MODULO_MODE = 1, // 0 to 9 + + // The maximum number of significant digits of the result of the exponentiatedBy operation. + // If POW_PRECISION is 0, there will be unlimited significant digits. + POW_PRECISION = 0, // 0 to MAX + + // The format specification used by the BigNumber.prototype.toFormat method. + FORMAT = { + prefix: '', + groupSize: 3, + secondaryGroupSize: 0, + groupSeparator: ',', + decimalSeparator: '.', + fractionGroupSize: 0, + fractionGroupSeparator: '\xA0', // non-breaking space + suffix: '' + }, + + // The alphabet used for base conversion. It must be at least 2 characters long, with no '+', + // '-', '.', whitespace, or repeated character. + // '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_' + ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz', + alphabetHasNormalDecimalDigits = true; + + + //------------------------------------------------------------------------------------------ + + + // CONSTRUCTOR + + + /* + * The BigNumber constructor and exported function. + * Create and return a new instance of a BigNumber object. + * + * v {number|string|BigNumber} A numeric value. + * [b] {number} The base of v. Integer, 2 to ALPHABET.length inclusive. + */ + function BigNumber(v, b) { + var alphabet, c, caseChanged, e, i, isNum, len, str, + x = this; + + // Enable constructor call without `new`. + if (!(x instanceof BigNumber)) return new BigNumber(v, b); + + if (b == null) { + + if (v && v._isBigNumber === true) { + x.s = v.s; + + if (!v.c || v.e > MAX_EXP) { + x.c = x.e = null; + } else if (v.e < MIN_EXP) { + x.c = [x.e = 0]; + } else { + x.e = v.e; + x.c = v.c.slice(); + } + + return; + } + + if ((isNum = typeof v == 'number') && v * 0 == 0) { + + // Use `1 / n` to handle minus zero also. + x.s = 1 / v < 0 ? (v = -v, -1) : 1; + + // Fast path for integers, where n < 2147483648 (2**31). + if (v === ~~v) { + for (e = 0, i = v; i >= 10; i /= 10, e++); + + if (e > MAX_EXP) { + x.c = x.e = null; + } else { + x.e = e; + x.c = [v]; + } + + return; + } + + str = String(v); + } else { + + if (!isNumeric.test(str = String(v))) return parseNumeric(x, str, isNum); + + x.s = str.charCodeAt(0) == 45 ? (str = str.slice(1), -1) : 1; + } + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + + // Exponential form? + if ((i = str.search(/e/i)) > 0) { + + // Determine exponent. + if (e < 0) e = i; + e += +str.slice(i + 1); + str = str.substring(0, i); + } else if (e < 0) { + + // Integer. + e = str.length; + } + + } else { + + // '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + intCheck(b, 2, ALPHABET.length, 'Base'); + + // Allow exponential notation to be used with base 10 argument, while + // also rounding to DECIMAL_PLACES as with other bases. + if (b == 10 && alphabetHasNormalDecimalDigits) { + x = new BigNumber(v); + return round(x, DECIMAL_PLACES + x.e + 1, ROUNDING_MODE); + } + + str = String(v); + + if (isNum = typeof v == 'number') { + + // Avoid potential interpretation of Infinity and NaN as base 44+ values. + if (v * 0 != 0) return parseNumeric(x, str, isNum, b); + + x.s = 1 / v < 0 ? (str = str.slice(1), -1) : 1; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (BigNumber.DEBUG && str.replace(/^0\.0*|\./, '').length > 15) { + throw Error + (tooManyDigits + v); + } + } else { + x.s = str.charCodeAt(0) === 45 ? (str = str.slice(1), -1) : 1; + } + + alphabet = ALPHABET.slice(0, b); + e = i = 0; + + // Check that str is a valid base b number. + // Don't use RegExp, so alphabet can contain special characters. + for (len = str.length; i < len; i++) { + if (alphabet.indexOf(c = str.charAt(i)) < 0) { + if (c == '.') { + + // If '.' is not the first character and it has not be found before. + if (i > e) { + e = len; + continue; + } + } else if (!caseChanged) { + + // Allow e.g. hexadecimal 'FF' as well as 'ff'. + if (str == str.toUpperCase() && (str = str.toLowerCase()) || + str == str.toLowerCase() && (str = str.toUpperCase())) { + caseChanged = true; + i = -1; + e = 0; + continue; + } + } + + return parseNumeric(x, String(v), isNum, b); + } + } + + // Prevent later check for length on converted number. + isNum = false; + str = convertBase(str, b, 10, x.s); + + // Decimal point? + if ((e = str.indexOf('.')) > -1) str = str.replace('.', ''); + else e = str.length; + } + + // Determine leading zeros. + for (i = 0; str.charCodeAt(i) === 48; i++); + + // Determine trailing zeros. + for (len = str.length; str.charCodeAt(--len) === 48;); + + if (str = str.slice(i, ++len)) { + len -= i; + + // '[BigNumber Error] Number primitive has more than 15 significant digits: {n}' + if (isNum && BigNumber.DEBUG && + len > 15 && (v > MAX_SAFE_INTEGER || v !== mathfloor(v))) { + throw Error + (tooManyDigits + (x.s * v)); + } + + // Overflow? + if ((e = e - i - 1) > MAX_EXP) { + + // Infinity. + x.c = x.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + x.c = [x.e = 0]; + } else { + x.e = e; + x.c = []; + + // Transform base + + // e is the base 10 exponent. + // i is where to slice str to get the first element of the coefficient array. + i = (e + 1) % LOG_BASE; + if (e < 0) i += LOG_BASE; // i < 1 + + if (i < len) { + if (i) x.c.push(+str.slice(0, i)); + + for (len -= LOG_BASE; i < len;) { + x.c.push(+str.slice(i, i += LOG_BASE)); + } + + i = LOG_BASE - (str = str.slice(i)).length; + } else { + i -= len; + } + + for (; i--; str += '0'); + x.c.push(+str); + } + } else { + + // Zero. + x.c = [x.e = 0]; + } + } + + + // CONSTRUCTOR PROPERTIES + + + BigNumber.clone = clone; + + BigNumber.ROUND_UP = 0; + BigNumber.ROUND_DOWN = 1; + BigNumber.ROUND_CEIL = 2; + BigNumber.ROUND_FLOOR = 3; + BigNumber.ROUND_HALF_UP = 4; + BigNumber.ROUND_HALF_DOWN = 5; + BigNumber.ROUND_HALF_EVEN = 6; + BigNumber.ROUND_HALF_CEIL = 7; + BigNumber.ROUND_HALF_FLOOR = 8; + BigNumber.EUCLID = 9; + + + /* + * Configure infrequently-changing library-wide settings. + * + * Accept an object with the following optional properties (if the value of a property is + * a number, it must be an integer within the inclusive range stated): + * + * DECIMAL_PLACES {number} 0 to MAX + * ROUNDING_MODE {number} 0 to 8 + * EXPONENTIAL_AT {number|number[]} -MAX to MAX or [-MAX to 0, 0 to MAX] + * RANGE {number|number[]} -MAX to MAX (not zero) or [-MAX to -1, 1 to MAX] + * CRYPTO {boolean} true or false + * MODULO_MODE {number} 0 to 9 + * POW_PRECISION {number} 0 to MAX + * ALPHABET {string} A string of two or more unique characters which does + * not contain '.'. + * FORMAT {object} An object with some of the following properties: + * prefix {string} + * groupSize {number} + * secondaryGroupSize {number} + * groupSeparator {string} + * decimalSeparator {string} + * fractionGroupSize {number} + * fractionGroupSeparator {string} + * suffix {string} + * + * (The values assigned to the above FORMAT object properties are not checked for validity.) + * + * E.g. + * BigNumber.config({ DECIMAL_PLACES : 20, ROUNDING_MODE : 4 }) + * + * Ignore properties/parameters set to null or undefined, except for ALPHABET. + * + * Return an object with the properties current values. + */ + BigNumber.config = BigNumber.set = function (obj) { + var p, v; + + if (obj != null) { + + if (typeof obj == 'object') { + + // DECIMAL_PLACES {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] DECIMAL_PLACES {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'DECIMAL_PLACES')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + DECIMAL_PLACES = v; + } + + // ROUNDING_MODE {number} Integer, 0 to 8 inclusive. + // '[BigNumber Error] ROUNDING_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'ROUNDING_MODE')) { + v = obj[p]; + intCheck(v, 0, 8, p); + ROUNDING_MODE = v; + } + + // EXPONENTIAL_AT {number|number[]} + // Integer, -MAX to MAX inclusive or + // [integer -MAX to 0 inclusive, 0 to MAX inclusive]. + // '[BigNumber Error] EXPONENTIAL_AT {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'EXPONENTIAL_AT')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, 0, p); + intCheck(v[1], 0, MAX, p); + TO_EXP_NEG = v[0]; + TO_EXP_POS = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + TO_EXP_NEG = -(TO_EXP_POS = v < 0 ? -v : v); + } + } + + // RANGE {number|number[]} Non-zero integer, -MAX to MAX inclusive or + // [integer -MAX to -1 inclusive, integer 1 to MAX inclusive]. + // '[BigNumber Error] RANGE {not a primitive number|not an integer|out of range|cannot be zero}: {v}' + if (obj.hasOwnProperty(p = 'RANGE')) { + v = obj[p]; + if (v && v.pop) { + intCheck(v[0], -MAX, -1, p); + intCheck(v[1], 1, MAX, p); + MIN_EXP = v[0]; + MAX_EXP = v[1]; + } else { + intCheck(v, -MAX, MAX, p); + if (v) { + MIN_EXP = -(MAX_EXP = v < 0 ? -v : v); + } else { + throw Error + (bignumberError + p + ' cannot be zero: ' + v); + } + } + } + + // CRYPTO {boolean} true or false. + // '[BigNumber Error] CRYPTO not true or false: {v}' + // '[BigNumber Error] crypto unavailable' + if (obj.hasOwnProperty(p = 'CRYPTO')) { + v = obj[p]; + if (v === !!v) { + if (v) { + if (typeof crypto != 'undefined' && crypto && + (crypto.getRandomValues || crypto.randomBytes)) { + CRYPTO = v; + } else { + CRYPTO = !v; + throw Error + (bignumberError + 'crypto unavailable'); + } + } else { + CRYPTO = v; + } + } else { + throw Error + (bignumberError + p + ' not true or false: ' + v); + } + } + + // MODULO_MODE {number} Integer, 0 to 9 inclusive. + // '[BigNumber Error] MODULO_MODE {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'MODULO_MODE')) { + v = obj[p]; + intCheck(v, 0, 9, p); + MODULO_MODE = v; + } + + // POW_PRECISION {number} Integer, 0 to MAX inclusive. + // '[BigNumber Error] POW_PRECISION {not a primitive number|not an integer|out of range}: {v}' + if (obj.hasOwnProperty(p = 'POW_PRECISION')) { + v = obj[p]; + intCheck(v, 0, MAX, p); + POW_PRECISION = v; + } + + // FORMAT {object} + // '[BigNumber Error] FORMAT not an object: {v}' + if (obj.hasOwnProperty(p = 'FORMAT')) { + v = obj[p]; + if (typeof v == 'object') FORMAT = v; + else throw Error + (bignumberError + p + ' not an object: ' + v); + } + + // ALPHABET {string} + // '[BigNumber Error] ALPHABET invalid: {v}' + if (obj.hasOwnProperty(p = 'ALPHABET')) { + v = obj[p]; + + // Disallow if less than two characters, + // or if it contains '+', '-', '.', whitespace, or a repeated character. + if (typeof v == 'string' && !/^.?$|[+\-.\s]|(.).*\1/.test(v)) { + alphabetHasNormalDecimalDigits = v.slice(0, 10) == '0123456789'; + ALPHABET = v; + } else { + throw Error + (bignumberError + p + ' invalid: ' + v); + } + } + + } else { + + // '[BigNumber Error] Object expected: {v}' + throw Error + (bignumberError + 'Object expected: ' + obj); + } + } + + return { + DECIMAL_PLACES: DECIMAL_PLACES, + ROUNDING_MODE: ROUNDING_MODE, + EXPONENTIAL_AT: [TO_EXP_NEG, TO_EXP_POS], + RANGE: [MIN_EXP, MAX_EXP], + CRYPTO: CRYPTO, + MODULO_MODE: MODULO_MODE, + POW_PRECISION: POW_PRECISION, + FORMAT: FORMAT, + ALPHABET: ALPHABET + }; + }; + + + /* + * Return true if v is a BigNumber instance, otherwise return false. + * + * If BigNumber.DEBUG is true, throw if a BigNumber instance is not well-formed. + * + * v {any} + * + * '[BigNumber Error] Invalid BigNumber: {v}' + */ + BigNumber.isBigNumber = function (v) { + if (!v || v._isBigNumber !== true) return false; + if (!BigNumber.DEBUG) return true; + + var i, n, + c = v.c, + e = v.e, + s = v.s; + + out: if ({}.toString.call(c) == '[object Array]') { + + if ((s === 1 || s === -1) && e >= -MAX && e <= MAX && e === mathfloor(e)) { + + // If the first element is zero, the BigNumber value must be zero. + if (c[0] === 0) { + if (e === 0 && c.length === 1) return true; + break out; + } + + // Calculate number of digits that c[0] should have, based on the exponent. + i = (e + 1) % LOG_BASE; + if (i < 1) i += LOG_BASE; + + // Calculate number of digits of c[0]. + //if (Math.ceil(Math.log(c[0] + 1) / Math.LN10) == i) { + if (String(c[0]).length == i) { + + for (i = 0; i < c.length; i++) { + n = c[i]; + if (n < 0 || n >= BASE || n !== mathfloor(n)) break out; + } + + // Last element cannot be zero, unless it is the only element. + if (n !== 0) return true; + } + } + + // Infinity/NaN + } else if (c === null && e === null && (s === null || s === 1 || s === -1)) { + return true; + } + + throw Error + (bignumberError + 'Invalid BigNumber: ' + v); + }; + + + /* + * Return a new BigNumber whose value is the maximum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.maximum = BigNumber.max = function () { + return maxOrMin(arguments, -1); + }; + + + /* + * Return a new BigNumber whose value is the minimum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.minimum = BigNumber.min = function () { + return maxOrMin(arguments, 1); + }; + + + /* + * Return a new BigNumber with a random value equal to or greater than 0 and less than 1, + * and with dp, or DECIMAL_PLACES if dp is omitted, decimal places (or less if trailing + * zeros are produced). + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp}' + * '[BigNumber Error] crypto unavailable' + */ + BigNumber.random = (function () { + var pow2_53 = 0x20000000000000; + + // Return a 53 bit integer n, where 0 <= n < 9007199254740992. + // Check if Math.random() produces more than 32 bits of randomness. + // If it does, assume at least 53 bits are produced, otherwise assume at least 30 bits. + // 0x40000000 is 2^30, 0x800000 is 2^23, 0x1fffff is 2^21 - 1. + var random53bitInt = (Math.random() * pow2_53) & 0x1fffff + ? function () { return mathfloor(Math.random() * pow2_53); } + : function () { return ((Math.random() * 0x40000000 | 0) * 0x800000) + + (Math.random() * 0x800000 | 0); }; + + return function (dp) { + var a, b, e, k, v, + i = 0, + c = [], + rand = new BigNumber(ONE); + + if (dp == null) dp = DECIMAL_PLACES; + else intCheck(dp, 0, MAX); + + k = mathceil(dp / LOG_BASE); + + if (CRYPTO) { + + // Browsers supporting crypto.getRandomValues. + if (crypto.getRandomValues) { + + a = crypto.getRandomValues(new Uint32Array(k *= 2)); + + for (; i < k;) { + + // 53 bits: + // ((Math.pow(2, 32) - 1) * Math.pow(2, 21)).toString(2) + // 11111 11111111 11111111 11111111 11100000 00000000 00000000 + // ((Math.pow(2, 32) - 1) >>> 11).toString(2) + // 11111 11111111 11111111 + // 0x20000 is 2^21. + v = a[i] * 0x20000 + (a[i + 1] >>> 11); + + // Rejection sampling: + // 0 <= v < 9007199254740992 + // Probability that v >= 9e15, is + // 7199254740992 / 9007199254740992 ~= 0.0008, i.e. 1 in 1251 + if (v >= 9e15) { + b = crypto.getRandomValues(new Uint32Array(2)); + a[i] = b[0]; + a[i + 1] = b[1]; + } else { + + // 0 <= v <= 8999999999999999 + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 2; + } + } + i = k / 2; + + // Node.js supporting crypto.randomBytes. + } else if (crypto.randomBytes) { + + // buffer + a = crypto.randomBytes(k *= 7); + + for (; i < k;) { + + // 0x1000000000000 is 2^48, 0x10000000000 is 2^40 + // 0x100000000 is 2^32, 0x1000000 is 2^24 + // 11111 11111111 11111111 11111111 11111111 11111111 11111111 + // 0 <= v < 9007199254740992 + v = ((a[i] & 31) * 0x1000000000000) + (a[i + 1] * 0x10000000000) + + (a[i + 2] * 0x100000000) + (a[i + 3] * 0x1000000) + + (a[i + 4] << 16) + (a[i + 5] << 8) + a[i + 6]; + + if (v >= 9e15) { + crypto.randomBytes(7).copy(a, i); + } else { + + // 0 <= (v % 1e14) <= 99999999999999 + c.push(v % 1e14); + i += 7; + } + } + i = k / 7; + } else { + CRYPTO = false; + throw Error + (bignumberError + 'crypto unavailable'); + } + } + + // Use Math.random. + if (!CRYPTO) { + + for (; i < k;) { + v = random53bitInt(); + if (v < 9e15) c[i++] = v % 1e14; + } + } + + k = c[--i]; + dp %= LOG_BASE; + + // Convert trailing digits to zeros according to dp. + if (k && dp) { + v = POWS_TEN[LOG_BASE - dp]; + c[i] = mathfloor(k / v) * v; + } + + // Remove trailing elements which are zero. + for (; c[i] === 0; c.pop(), i--); + + // Zero? + if (i < 0) { + c = [e = 0]; + } else { + + // Remove leading elements which are zero and adjust exponent accordingly. + for (e = -1 ; c[0] === 0; c.splice(0, 1), e -= LOG_BASE); + + // Count the digits of the first element of c to determine leading zeros, and... + for (i = 1, v = c[0]; v >= 10; v /= 10, i++); + + // adjust the exponent accordingly. + if (i < LOG_BASE) e -= LOG_BASE - i; + } + + rand.e = e; + rand.c = c; + return rand; + }; + })(); + + + /* + * Return a BigNumber whose value is the sum of the arguments. + * + * arguments {number|string|BigNumber} + */ + BigNumber.sum = function () { + var i = 1, + args = arguments, + sum = new BigNumber(args[0]); + for (; i < args.length;) sum = sum.plus(args[i++]); + return sum; + }; + + + // PRIVATE FUNCTIONS + + + // Called by BigNumber and BigNumber.prototype.toString. + convertBase = (function () { + var decimal = '0123456789'; + + /* + * Convert string of baseIn to an array of numbers of baseOut. + * Eg. toBaseOut('255', 10, 16) returns [15, 15]. + * Eg. toBaseOut('ff', 16, 10) returns [2, 5, 5]. + */ + function toBaseOut(str, baseIn, baseOut, alphabet) { + var j, + arr = [0], + arrL, + i = 0, + len = str.length; + + for (; i < len;) { + for (arrL = arr.length; arrL--; arr[arrL] *= baseIn); + + arr[0] += alphabet.indexOf(str.charAt(i++)); + + for (j = 0; j < arr.length; j++) { + + if (arr[j] > baseOut - 1) { + if (arr[j + 1] == null) arr[j + 1] = 0; + arr[j + 1] += arr[j] / baseOut | 0; + arr[j] %= baseOut; + } + } + } + + return arr.reverse(); + } + + // Convert a numeric string of baseIn to a numeric string of baseOut. + // If the caller is toString, we are converting from base 10 to baseOut. + // If the caller is BigNumber, we are converting from baseIn to base 10. + return function (str, baseIn, baseOut, sign, callerIsToString) { + var alphabet, d, e, k, r, x, xc, y, + i = str.indexOf('.'), + dp = DECIMAL_PLACES, + rm = ROUNDING_MODE; + + // Non-integer. + if (i >= 0) { + k = POW_PRECISION; + + // Unlimited precision. + POW_PRECISION = 0; + str = str.replace('.', ''); + y = new BigNumber(baseIn); + x = y.pow(str.length - i); + POW_PRECISION = k; + + // Convert str as if an integer, then restore the fraction part by dividing the + // result by its base raised to a power. + + y.c = toBaseOut(toFixedPoint(coeffToString(x.c), x.e, '0'), + 10, baseOut, decimal); + y.e = y.c.length; + } + + // Convert the number as integer. + + xc = toBaseOut(str, baseIn, baseOut, callerIsToString + ? (alphabet = ALPHABET, decimal) + : (alphabet = decimal, ALPHABET)); + + // xc now represents str as an integer and converted to baseOut. e is the exponent. + e = k = xc.length; + + // Remove trailing zeros. + for (; xc[--k] == 0; xc.pop()); + + // Zero? + if (!xc[0]) return alphabet.charAt(0); + + // Does str represent an integer? If so, no need for the division. + if (i < 0) { + --e; + } else { + x.c = xc; + x.e = e; + + // The sign is needed for correct rounding. + x.s = sign; + x = div(x, y, dp, rm, baseOut); + xc = x.c; + r = x.r; + e = x.e; + } + + // xc now represents str converted to baseOut. + + // The index of the rounding digit. + d = e + dp + 1; + + // The rounding digit: the digit to the right of the digit that may be rounded up. + i = xc[d]; + + // Look at the rounding digits and mode to determine whether to round up. + + k = baseOut / 2; + r = r || d < 0 || xc[d + 1] != null; + + r = rm < 4 ? (i != null || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : i > k || i == k &&(rm == 4 || r || rm == 6 && xc[d - 1] & 1 || + rm == (x.s < 0 ? 8 : 7)); + + // If the index of the rounding digit is not greater than zero, or xc represents + // zero, then the result of the base conversion is zero or, if rounding up, a value + // such as 0.00001. + if (d < 1 || !xc[0]) { + + // 1^-dp or 0 + str = r ? toFixedPoint(alphabet.charAt(1), -dp, alphabet.charAt(0)) : alphabet.charAt(0); + } else { + + // Truncate xc to the required number of decimal places. + xc.length = d; + + // Round up? + if (r) { + + // Rounding up may mean the previous digit has to be rounded up and so on. + for (--baseOut; ++xc[--d] > baseOut;) { + xc[d] = 0; + + if (!d) { + ++e; + xc = [1].concat(xc); + } + } + } + + // Determine trailing zeros. + for (k = xc.length; !xc[--k];); + + // E.g. [4, 11, 15] becomes 4bf. + for (i = 0, str = ''; i <= k; str += alphabet.charAt(xc[i++])); + + // Add leading zeros, decimal point and trailing zeros as required. + str = toFixedPoint(str, e, alphabet.charAt(0)); + } + + // The caller will add the sign. + return str; + }; + })(); + + + // Perform division in the specified base. Called by div and convertBase. + div = (function () { + + // Assume non-zero x and k. + function multiply(x, k, base) { + var m, temp, xlo, xhi, + carry = 0, + i = x.length, + klo = k % SQRT_BASE, + khi = k / SQRT_BASE | 0; + + for (x = x.slice(); i--;) { + xlo = x[i] % SQRT_BASE; + xhi = x[i] / SQRT_BASE | 0; + m = khi * xlo + xhi * klo; + temp = klo * xlo + ((m % SQRT_BASE) * SQRT_BASE) + carry; + carry = (temp / base | 0) + (m / SQRT_BASE | 0) + khi * xhi; + x[i] = temp % base; + } + + if (carry) x = [carry].concat(x); + + return x; + } + + function compare(a, b, aL, bL) { + var i, cmp; + + if (aL != bL) { + cmp = aL > bL ? 1 : -1; + } else { + + for (i = cmp = 0; i < aL; i++) { + + if (a[i] != b[i]) { + cmp = a[i] > b[i] ? 1 : -1; + break; + } + } + } + + return cmp; + } + + function subtract(a, b, aL, base) { + var i = 0; + + // Subtract b from a. + for (; aL--;) { + a[aL] -= i; + i = a[aL] < b[aL] ? 1 : 0; + a[aL] = i * base + a[aL] - b[aL]; + } + + // Remove leading zeros. + for (; !a[0] && a.length > 1; a.splice(0, 1)); + } + + // x: dividend, y: divisor. + return function (x, y, dp, rm, base) { + var cmp, e, i, more, n, prod, prodL, q, qc, rem, remL, rem0, xi, xL, yc0, + yL, yz, + s = x.s == y.s ? 1 : -1, + xc = x.c, + yc = y.c; + + // Either NaN, Infinity or 0? + if (!xc || !xc[0] || !yc || !yc[0]) { + + return new BigNumber( + + // Return NaN if either NaN, or both Infinity or 0. + !x.s || !y.s || (xc ? yc && xc[0] == yc[0] : !yc) ? NaN : + + // Return ±0 if x is ±0 or y is ±Infinity, or return ±Infinity as y is ±0. + xc && xc[0] == 0 || !yc ? s * 0 : s / 0 + ); + } + + q = new BigNumber(s); + qc = q.c = []; + e = x.e - y.e; + s = dp + e + 1; + + if (!base) { + base = BASE; + e = bitFloor(x.e / LOG_BASE) - bitFloor(y.e / LOG_BASE); + s = s / LOG_BASE | 0; + } + + // Result exponent may be one less then the current value of e. + // The coefficients of the BigNumbers from convertBase may have trailing zeros. + for (i = 0; yc[i] == (xc[i] || 0); i++); + + if (yc[i] > (xc[i] || 0)) e--; + + if (s < 0) { + qc.push(1); + more = true; + } else { + xL = xc.length; + yL = yc.length; + i = 0; + s += 2; + + // Normalise xc and yc so highest order digit of yc is >= base / 2. + + n = mathfloor(base / (yc[0] + 1)); + + // Not necessary, but to handle odd bases where yc[0] == (base / 2) - 1. + // if (n > 1 || n++ == 1 && yc[0] < base / 2) { + if (n > 1) { + yc = multiply(yc, n, base); + xc = multiply(xc, n, base); + yL = yc.length; + xL = xc.length; + } + + xi = yL; + rem = xc.slice(0, yL); + remL = rem.length; + + // Add zeros to make remainder as long as divisor. + for (; remL < yL; rem[remL++] = 0); + yz = yc.slice(); + yz = [0].concat(yz); + yc0 = yc[0]; + if (yc[1] >= base / 2) yc0++; + // Not necessary, but to prevent trial digit n > base, when using base 3. + // else if (base == 3 && yc0 == 1) yc0 = 1 + 1e-15; + + do { + n = 0; + + // Compare divisor and remainder. + cmp = compare(yc, rem, yL, remL); + + // If divisor < remainder. + if (cmp < 0) { + + // Calculate trial digit, n. + + rem0 = rem[0]; + if (yL != remL) rem0 = rem0 * base + (rem[1] || 0); + + // n is how many times the divisor goes into the current remainder. + n = mathfloor(rem0 / yc0); + + // Algorithm: + // product = divisor multiplied by trial digit (n). + // Compare product and remainder. + // If product is greater than remainder: + // Subtract divisor from product, decrement trial digit. + // Subtract product from remainder. + // If product was less than remainder at the last compare: + // Compare new remainder and divisor. + // If remainder is greater than divisor: + // Subtract divisor from remainder, increment trial digit. + + if (n > 1) { + + // n may be > base only when base is 3. + if (n >= base) n = base - 1; + + // product = divisor * trial digit. + prod = multiply(yc, n, base); + prodL = prod.length; + remL = rem.length; + + // Compare product and remainder. + // If product > remainder then trial digit n too high. + // n is 1 too high about 5% of the time, and is not known to have + // ever been more than 1 too high. + while (compare(prod, rem, prodL, remL) == 1) { + n--; + + // Subtract divisor from product. + subtract(prod, yL < prodL ? yz : yc, prodL, base); + prodL = prod.length; + cmp = 1; + } + } else { + + // n is 0 or 1, cmp is -1. + // If n is 0, there is no need to compare yc and rem again below, + // so change cmp to 1 to avoid it. + // If n is 1, leave cmp as -1, so yc and rem are compared again. + if (n == 0) { + + // divisor < remainder, so n must be at least 1. + cmp = n = 1; + } + + // product = divisor + prod = yc.slice(); + prodL = prod.length; + } + + if (prodL < remL) prod = [0].concat(prod); + + // Subtract product from remainder. + subtract(rem, prod, remL, base); + remL = rem.length; + + // If product was < remainder. + if (cmp == -1) { + + // Compare divisor and new remainder. + // If divisor < new remainder, subtract divisor from remainder. + // Trial digit n too low. + // n is 1 too low about 5% of the time, and very rarely 2 too low. + while (compare(yc, rem, yL, remL) < 1) { + n++; + + // Subtract divisor from remainder. + subtract(rem, yL < remL ? yz : yc, remL, base); + remL = rem.length; + } + } + } else if (cmp === 0) { + n++; + rem = [0]; + } // else cmp === 1 and n will be 0 + + // Add the next digit, n, to the result array. + qc[i++] = n; + + // Update the remainder. + if (rem[0]) { + rem[remL++] = xc[xi] || 0; + } else { + rem = [xc[xi]]; + remL = 1; + } + } while ((xi++ < xL || rem[0] != null) && s--); + + more = rem[0] != null; + + // Leading zero? + if (!qc[0]) qc.splice(0, 1); + } + + if (base == BASE) { + + // To calculate q.e, first get the number of digits of qc[0]. + for (i = 1, s = qc[0]; s >= 10; s /= 10, i++); + + round(q, dp + (q.e = i + e * LOG_BASE - 1) + 1, rm, more); + + // Caller is convertBase. + } else { + q.e = e; + q.r = +more; + } + + return q; + }; + })(); + + + /* + * Return a string representing the value of BigNumber n in fixed-point or exponential + * notation rounded to the specified decimal places or significant digits. + * + * n: a BigNumber. + * i: the index of the last digit required (i.e. the digit that may be rounded up). + * rm: the rounding mode. + * id: 1 (toExponential) or 2 (toPrecision). + */ + function format(n, i, rm, id) { + var c0, e, ne, len, str; + + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + if (!n.c) return n.toString(); + + c0 = n.c[0]; + ne = n.e; + + if (i == null) { + str = coeffToString(n.c); + str = id == 1 || id == 2 && (ne <= TO_EXP_NEG || ne >= TO_EXP_POS) + ? toExponential(str, ne) + : toFixedPoint(str, ne, '0'); + } else { + n = round(new BigNumber(n), i, rm); + + // n.e may have changed if the value was rounded up. + e = n.e; + + str = coeffToString(n.c); + len = str.length; + + // toPrecision returns exponential notation if the number of significant digits + // specified is less than the number of digits necessary to represent the integer + // part of the value in fixed-point notation. + + // Exponential notation. + if (id == 1 || id == 2 && (i <= e || e <= TO_EXP_NEG)) { + + // Append zeros? + for (; len < i; str += '0', len++); + str = toExponential(str, e); + + // Fixed-point notation. + } else { + i -= ne + (id === 2 && e > ne); + str = toFixedPoint(str, e, '0'); + + // Append zeros? + if (e + 1 > len) { + if (--i > 0) for (str += '.'; i--; str += '0'); + } else { + i += e - len; + if (i > 0) { + if (e + 1 == len) str += '.'; + for (; i--; str += '0'); + } + } + } + } + + return n.s < 0 && c0 ? '-' + str : str; + } + + + // Handle BigNumber.max and BigNumber.min. + // If any number is NaN, return NaN. + function maxOrMin(args, n) { + var k, y, + i = 1, + x = new BigNumber(args[0]); + + for (; i < args.length; i++) { + y = new BigNumber(args[i]); + if (!y.s || (k = compare(x, y)) === n || k === 0 && x.s === n) { + x = y; + } + } + + return x; + } + + + /* + * Strip trailing zeros, calculate base 10 exponent and check against MIN_EXP and MAX_EXP. + * Called by minus, plus and times. + */ + function normalise(n, c, e) { + var i = 1, + j = c.length; + + // Remove trailing zeros. + for (; !c[--j]; c.pop()); + + // Calculate the base 10 exponent. First get the number of digits of c[0]. + for (j = c[0]; j >= 10; j /= 10, i++); + + // Overflow? + if ((e = i + e * LOG_BASE - 1) > MAX_EXP) { + + // Infinity. + n.c = n.e = null; + + // Underflow? + } else if (e < MIN_EXP) { + + // Zero. + n.c = [n.e = 0]; + } else { + n.e = e; + n.c = c; + } + + return n; + } + + + // Handle values that fail the validity test in BigNumber. + parseNumeric = (function () { + var basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i, + dotAfter = /^([^.]+)\.$/, + dotBefore = /^\.([^.]+)$/, + isInfinityOrNaN = /^-?(Infinity|NaN)$/, + whitespaceOrPlus = /^\s*\+(?=[\w.])|^\s+|\s+$/g; + + return function (x, str, isNum, b) { + var base, + s = isNum ? str : str.replace(whitespaceOrPlus, ''); + + // No exception on ±Infinity or NaN. + if (isInfinityOrNaN.test(s)) { + x.s = isNaN(s) ? null : s < 0 ? -1 : 1; + } else { + if (!isNum) { + + // basePrefix = /^(-?)0([xbo])(?=\w[\w.]*$)/i + s = s.replace(basePrefix, function (m, p1, p2) { + base = (p2 = p2.toLowerCase()) == 'x' ? 16 : p2 == 'b' ? 2 : 8; + return !b || b == base ? p1 : m; + }); + + if (b) { + base = b; + + // E.g. '1.' to '1', '.1' to '0.1' + s = s.replace(dotAfter, '$1').replace(dotBefore, '0.$1'); + } + + if (str != s) return new BigNumber(s, base); + } + + // '[BigNumber Error] Not a number: {n}' + // '[BigNumber Error] Not a base {b} number: {n}' + if (BigNumber.DEBUG) { + throw Error + (bignumberError + 'Not a' + (b ? ' base ' + b : '') + ' number: ' + str); + } + + // NaN + x.s = null; + } + + x.c = x.e = null; + } + })(); + + + /* + * Round x to sd significant digits using rounding mode rm. Check for over/under-flow. + * If r is truthy, it is known that there are more digits after the rounding digit. + */ + function round(x, sd, rm, r) { + var d, i, j, k, n, ni, rd, + xc = x.c, + pows10 = POWS_TEN; + + // if x is not Infinity or NaN... + if (xc) { + + // rd is the rounding digit, i.e. the digit after the digit that may be rounded up. + // n is a base 1e14 number, the value of the element of array x.c containing rd. + // ni is the index of n within x.c. + // d is the number of digits of n. + // i is the index of rd within n including leading zeros. + // j is the actual index of rd within n (if < 0, rd is a leading zero). + out: { + + // Get the number of digits of the first element of xc. + for (d = 1, k = xc[0]; k >= 10; k /= 10, d++); + i = sd - d; + + // If the rounding digit is in the first element of xc... + if (i < 0) { + i += LOG_BASE; + j = sd; + n = xc[ni = 0]; + + // Get the rounding digit at index j of n. + rd = mathfloor(n / pows10[d - j - 1] % 10); + } else { + ni = mathceil((i + 1) / LOG_BASE); + + if (ni >= xc.length) { + + if (r) { + + // Needed by sqrt. + for (; xc.length <= ni; xc.push(0)); + n = rd = 0; + d = 1; + i %= LOG_BASE; + j = i - LOG_BASE + 1; + } else { + break out; + } + } else { + n = k = xc[ni]; + + // Get the number of digits of n. + for (d = 1; k >= 10; k /= 10, d++); + + // Get the index of rd within n. + i %= LOG_BASE; + + // Get the index of rd within n, adjusted for leading zeros. + // The number of leading zeros of n is given by LOG_BASE - d. + j = i - LOG_BASE + d; + + // Get the rounding digit at index j of n. + rd = j < 0 ? 0 : mathfloor(n / pows10[d - j - 1] % 10); + } + } + + r = r || sd < 0 || + + // Are there any non-zero digits after the rounding digit? + // The expression n % pows10[d - j - 1] returns all digits of n to the right + // of the digit at j, e.g. if n is 908714 and j is 2, the expression gives 714. + xc[ni + 1] != null || (j < 0 ? n : n % pows10[d - j - 1]); + + r = rm < 4 + ? (rd || r) && (rm == 0 || rm == (x.s < 0 ? 3 : 2)) + : rd > 5 || rd == 5 && (rm == 4 || r || rm == 6 && + + // Check whether the digit to the left of the rounding digit is odd. + ((i > 0 ? j > 0 ? n / pows10[d - j] : 0 : xc[ni - 1]) % 10) & 1 || + rm == (x.s < 0 ? 8 : 7)); + + if (sd < 1 || !xc[0]) { + xc.length = 0; + + if (r) { + + // Convert sd to decimal places. + sd -= x.e + 1; + + // 1, 0.1, 0.01, 0.001, 0.0001 etc. + xc[0] = pows10[(LOG_BASE - sd % LOG_BASE) % LOG_BASE]; + x.e = -sd || 0; + } else { + + // Zero. + xc[0] = x.e = 0; + } + + return x; + } + + // Remove excess digits. + if (i == 0) { + xc.length = ni; + k = 1; + ni--; + } else { + xc.length = ni + 1; + k = pows10[LOG_BASE - i]; + + // E.g. 56700 becomes 56000 if 7 is the rounding digit. + // j > 0 means i > number of leading zeros of n. + xc[ni] = j > 0 ? mathfloor(n / pows10[d - j] % pows10[j]) * k : 0; + } + + // Round up? + if (r) { + + for (; ;) { + + // If the digit to be rounded up is in the first element of xc... + if (ni == 0) { + + // i will be the length of xc[0] before k is added. + for (i = 1, j = xc[0]; j >= 10; j /= 10, i++); + j = xc[0] += k; + for (k = 1; j >= 10; j /= 10, k++); + + // if i != k the length has increased. + if (i != k) { + x.e++; + if (xc[0] == BASE) xc[0] = 1; + } + + break; + } else { + xc[ni] += k; + if (xc[ni] != BASE) break; + xc[ni--] = 0; + k = 1; + } + } + } + + // Remove trailing zeros. + for (i = xc.length; xc[--i] === 0; xc.pop()); + } + + // Overflow? Infinity. + if (x.e > MAX_EXP) { + x.c = x.e = null; + + // Underflow? Zero. + } else if (x.e < MIN_EXP) { + x.c = [x.e = 0]; + } + } + + return x; + } + + + function valueOf(n) { + var str, + e = n.e; + + if (e === null) return n.toString(); + + str = coeffToString(n.c); + + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(str, e) + : toFixedPoint(str, e, '0'); + + return n.s < 0 ? '-' + str : str; + } + + + // PROTOTYPE/INSTANCE METHODS + + + /* + * Return a new BigNumber whose value is the absolute value of this BigNumber. + */ + P.absoluteValue = P.abs = function () { + var x = new BigNumber(this); + if (x.s < 0) x.s = 1; + return x; + }; + + + /* + * Return + * 1 if the value of this BigNumber is greater than the value of BigNumber(y, b), + * -1 if the value of this BigNumber is less than the value of BigNumber(y, b), + * 0 if they have the same value, + * or null if the value of either is NaN. + */ + P.comparedTo = function (y, b) { + return compare(this, new BigNumber(y, b)); + }; + + + /* + * If dp is undefined or null or true or false, return the number of decimal places of the + * value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * + * Otherwise, if dp is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of dp decimal places using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * [dp] {number} Decimal places: integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.decimalPlaces = P.dp = function (dp, rm) { + var c, n, v, + x = this; + + if (dp != null) { + intCheck(dp, 0, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), dp + x.e + 1, rm); + } + + if (!(c = x.c)) return null; + n = ((v = c.length - 1) - bitFloor(this.e / LOG_BASE)) * LOG_BASE; + + // Subtract the number of trailing zeros of the last number. + if (v = c[v]) for (; v % 10 == 0; v /= 10, n--); + if (n < 0) n = 0; + + return n; + }; + + + /* + * n / 0 = I + * n / N = N + * n / I = 0 + * 0 / n = 0 + * 0 / 0 = N + * 0 / N = N + * 0 / I = 0 + * N / n = N + * N / 0 = N + * N / N = N + * N / I = N + * I / n = I + * I / 0 = I + * I / N = N + * I / I = N + * + * Return a new BigNumber whose value is the value of this BigNumber divided by the value of + * BigNumber(y, b), rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.dividedBy = P.div = function (y, b) { + return div(this, new BigNumber(y, b), DECIMAL_PLACES, ROUNDING_MODE); + }; + + + /* + * Return a new BigNumber whose value is the integer part of dividing the value of this + * BigNumber by the value of BigNumber(y, b). + */ + P.dividedToIntegerBy = P.idiv = function (y, b) { + return div(this, new BigNumber(y, b), 0, 1); + }; + + + /* + * Return a BigNumber whose value is the value of this BigNumber exponentiated by n. + * + * If m is present, return the result modulo m. + * If n is negative round according to DECIMAL_PLACES and ROUNDING_MODE. + * If POW_PRECISION is non-zero and m is not present, round to POW_PRECISION using ROUNDING_MODE. + * + * The modular power operation works efficiently when x, n, and m are integers, otherwise it + * is equivalent to calculating x.exponentiatedBy(n).modulo(m) with a POW_PRECISION of 0. + * + * n {number|string|BigNumber} The exponent. An integer. + * [m] {number|string|BigNumber} The modulus. + * + * '[BigNumber Error] Exponent not an integer: {n}' + */ + P.exponentiatedBy = P.pow = function (n, m) { + var half, isModExp, i, k, more, nIsBig, nIsNeg, nIsOdd, y, + x = this; + + n = new BigNumber(n); + + // Allow NaN and ±Infinity, but not other non-integers. + if (n.c && !n.isInteger()) { + throw Error + (bignumberError + 'Exponent not an integer: ' + valueOf(n)); + } + + if (m != null) m = new BigNumber(m); + + // Exponent of MAX_SAFE_INTEGER is 15. + nIsBig = n.e > 14; + + // If x is NaN, ±Infinity, ±0 or ±1, or n is ±Infinity, NaN or ±0. + if (!x.c || !x.c[0] || x.c[0] == 1 && !x.e && x.c.length == 1 || !n.c || !n.c[0]) { + + // The sign of the result of pow when x is negative depends on the evenness of n. + // If +n overflows to ±Infinity, the evenness of n would be not be known. + y = new BigNumber(Math.pow(+valueOf(x), nIsBig ? n.s * (2 - isOdd(n)) : +valueOf(n))); + return m ? y.mod(m) : y; + } + + nIsNeg = n.s < 0; + + if (m) { + + // x % m returns NaN if abs(m) is zero, or m is NaN. + if (m.c ? !m.c[0] : !m.s) return new BigNumber(NaN); + + isModExp = !nIsNeg && x.isInteger() && m.isInteger(); + + if (isModExp) x = x.mod(m); + + // Overflow to ±Infinity: >=2**1e10 or >=1.0000024**1e15. + // Underflow to ±0: <=0.79**1e10 or <=0.9999975**1e15. + } else if (n.e > 9 && (x.e > 0 || x.e < -1 || (x.e == 0 + // [1, 240000000] + ? x.c[0] > 1 || nIsBig && x.c[1] >= 24e7 + // [80000000000000] [99999750000000] + : x.c[0] < 8e13 || nIsBig && x.c[0] <= 9999975e7))) { + + // If x is negative and n is odd, k = -0, else k = 0. + k = x.s < 0 && isOdd(n) ? -0 : 0; + + // If x >= 1, k = ±Infinity. + if (x.e > -1) k = 1 / k; + + // If n is negative return ±0, else return ±Infinity. + return new BigNumber(nIsNeg ? 1 / k : k); + + } else if (POW_PRECISION) { + + // Truncating each coefficient array to a length of k after each multiplication + // equates to truncating significant digits to POW_PRECISION + [28, 41], + // i.e. there will be a minimum of 28 guard digits retained. + k = mathceil(POW_PRECISION / LOG_BASE + 2); + } + + if (nIsBig) { + half = new BigNumber(0.5); + if (nIsNeg) n.s = 1; + nIsOdd = isOdd(n); + } else { + i = Math.abs(+valueOf(n)); + nIsOdd = i % 2; + } + + y = new BigNumber(ONE); + + // Performs 54 loop iterations for n of 9007199254740991. + for (; ;) { + + if (nIsOdd) { + y = y.times(x); + if (!y.c) break; + + if (k) { + if (y.c.length > k) y.c.length = k; + } else if (isModExp) { + y = y.mod(m); //y = y.minus(div(y, m, 0, MODULO_MODE).times(m)); + } + } + + if (i) { + i = mathfloor(i / 2); + if (i === 0) break; + nIsOdd = i % 2; + } else { + n = n.times(half); + round(n, n.e + 1, 1); + + if (n.e > 14) { + nIsOdd = isOdd(n); + } else { + i = +valueOf(n); + if (i === 0) break; + nIsOdd = i % 2; + } + } + + x = x.times(x); + + if (k) { + if (x.c && x.c.length > k) x.c.length = k; + } else if (isModExp) { + x = x.mod(m); //x = x.minus(div(x, m, 0, MODULO_MODE).times(m)); + } + } + + if (isModExp) return y; + if (nIsNeg) y = ONE.div(y); + + return m ? y.mod(m) : k ? round(y, POW_PRECISION, ROUNDING_MODE, more) : y; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber rounded to an integer + * using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {rm}' + */ + P.integerValue = function (rm) { + var n = new BigNumber(this); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + return round(n, n.e + 1, rm); + }; + + + /* + * Return true if the value of this BigNumber is equal to the value of BigNumber(y, b), + * otherwise return false. + */ + P.isEqualTo = P.eq = function (y, b) { + return compare(this, new BigNumber(y, b)) === 0; + }; + + + /* + * Return true if the value of this BigNumber is a finite number, otherwise return false. + */ + P.isFinite = function () { + return !!this.c; + }; + + + /* + * Return true if the value of this BigNumber is greater than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isGreaterThan = P.gt = function (y, b) { + return compare(this, new BigNumber(y, b)) > 0; + }; + + + /* + * Return true if the value of this BigNumber is greater than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isGreaterThanOrEqualTo = P.gte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === 1 || b === 0; + + }; + + + /* + * Return true if the value of this BigNumber is an integer, otherwise return false. + */ + P.isInteger = function () { + return !!this.c && bitFloor(this.e / LOG_BASE) > this.c.length - 2; + }; + + + /* + * Return true if the value of this BigNumber is less than the value of BigNumber(y, b), + * otherwise return false. + */ + P.isLessThan = P.lt = function (y, b) { + return compare(this, new BigNumber(y, b)) < 0; + }; + + + /* + * Return true if the value of this BigNumber is less than or equal to the value of + * BigNumber(y, b), otherwise return false. + */ + P.isLessThanOrEqualTo = P.lte = function (y, b) { + return (b = compare(this, new BigNumber(y, b))) === -1 || b === 0; + }; + + + /* + * Return true if the value of this BigNumber is NaN, otherwise return false. + */ + P.isNaN = function () { + return !this.s; + }; + + + /* + * Return true if the value of this BigNumber is negative, otherwise return false. + */ + P.isNegative = function () { + return this.s < 0; + }; + + + /* + * Return true if the value of this BigNumber is positive, otherwise return false. + */ + P.isPositive = function () { + return this.s > 0; + }; + + + /* + * Return true if the value of this BigNumber is 0 or -0, otherwise return false. + */ + P.isZero = function () { + return !!this.c && this.c[0] == 0; + }; + + + /* + * n - 0 = n + * n - N = N + * n - I = -I + * 0 - n = -n + * 0 - 0 = 0 + * 0 - N = N + * 0 - I = -I + * N - n = N + * N - 0 = N + * N - N = N + * N - I = N + * I - n = I + * I - 0 = I + * I - N = N + * I - I = N + * + * Return a new BigNumber whose value is the value of this BigNumber minus the value of + * BigNumber(y, b). + */ + P.minus = function (y, b) { + var i, j, t, xLTy, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.plus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Either Infinity? + if (!xc || !yc) return xc ? (y.s = -b, y) : new BigNumber(yc ? x : NaN); + + // Either zero? + if (!xc[0] || !yc[0]) { + + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + return yc[0] ? (y.s = -b, y) : new BigNumber(xc[0] ? x : + + // IEEE 754 (2008) 6.3: n - n = -0 when rounding to -Infinity + ROUNDING_MODE == 3 ? -0 : 0); + } + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Determine which is the bigger number. + if (a = xe - ye) { + + if (xLTy = a < 0) { + a = -a; + t = xc; + } else { + ye = xe; + t = yc; + } + + t.reverse(); + + // Prepend zeros to equalise exponents. + for (b = a; b--; t.push(0)); + t.reverse(); + } else { + + // Exponents equal. Check digit by digit. + j = (xLTy = (a = xc.length) < (b = yc.length)) ? a : b; + + for (a = b = 0; b < j; b++) { + + if (xc[b] != yc[b]) { + xLTy = xc[b] < yc[b]; + break; + } + } + } + + // x < y? Point xc to the array of the bigger number. + if (xLTy) { + t = xc; + xc = yc; + yc = t; + y.s = -y.s; + } + + b = (j = yc.length) - (i = xc.length); + + // Append zeros to xc if shorter. + // No need to add zeros to yc if shorter as subtract only needs to start at yc.length. + if (b > 0) for (; b--; xc[i++] = 0); + b = BASE - 1; + + // Subtract yc from xc. + for (; j > a;) { + + if (xc[--j] < yc[j]) { + for (i = j; i && !xc[--i]; xc[i] = b); + --xc[i]; + xc[j] += BASE; + } + + xc[j] -= yc[j]; + } + + // Remove leading zeros and adjust exponent accordingly. + for (; xc[0] == 0; xc.splice(0, 1), --ye); + + // Zero? + if (!xc[0]) { + + // Following IEEE 754 (2008) 6.3, + // n - n = +0 but n - n = -0 when rounding towards -Infinity. + y.s = ROUNDING_MODE == 3 ? -1 : 1; + y.c = [y.e = 0]; + return y; + } + + // No need to check for Infinity as +x - +y != Infinity && -x - -y != Infinity + // for finite x and y. + return normalise(y, xc, ye); + }; + + + /* + * n % 0 = N + * n % N = N + * n % I = n + * 0 % n = 0 + * -0 % n = -0 + * 0 % 0 = N + * 0 % N = N + * 0 % I = 0 + * N % n = N + * N % 0 = N + * N % N = N + * N % I = N + * I % n = N + * I % 0 = N + * I % N = N + * I % I = N + * + * Return a new BigNumber whose value is the value of this BigNumber modulo the value of + * BigNumber(y, b). The result depends on the value of MODULO_MODE. + */ + P.modulo = P.mod = function (y, b) { + var q, s, + x = this; + + y = new BigNumber(y, b); + + // Return NaN if x is Infinity or NaN, or y is NaN or zero. + if (!x.c || !y.s || y.c && !y.c[0]) { + return new BigNumber(NaN); + + // Return x if y is Infinity or x is zero. + } else if (!y.c || x.c && !x.c[0]) { + return new BigNumber(x); + } + + if (MODULO_MODE == 9) { + + // Euclidian division: q = sign(y) * floor(x / abs(y)) + // r = x - qy where 0 <= r < abs(y) + s = y.s; + y.s = 1; + q = div(x, y, 0, 3); + y.s = s; + q.s *= s; + } else { + q = div(x, y, 0, MODULO_MODE); + } + + y = x.minus(q.times(y)); + + // To match JavaScript %, ensure sign of zero is sign of dividend. + if (!y.c[0] && MODULO_MODE == 1) y.s = x.s; + + return y; + }; + + + /* + * n * 0 = 0 + * n * N = N + * n * I = I + * 0 * n = 0 + * 0 * 0 = 0 + * 0 * N = N + * 0 * I = N + * N * n = N + * N * 0 = N + * N * N = N + * N * I = N + * I * n = I + * I * 0 = N + * I * N = N + * I * I = I + * + * Return a new BigNumber whose value is the value of this BigNumber multiplied by the value + * of BigNumber(y, b). + */ + P.multipliedBy = P.times = function (y, b) { + var c, e, i, j, k, m, xcL, xlo, xhi, ycL, ylo, yhi, zc, + base, sqrtBase, + x = this, + xc = x.c, + yc = (y = new BigNumber(y, b)).c; + + // Either NaN, ±Infinity or ±0? + if (!xc || !yc || !xc[0] || !yc[0]) { + + // Return NaN if either is NaN, or one is 0 and the other is Infinity. + if (!x.s || !y.s || xc && !xc[0] && !yc || yc && !yc[0] && !xc) { + y.c = y.e = y.s = null; + } else { + y.s *= x.s; + + // Return ±Infinity if either is ±Infinity. + if (!xc || !yc) { + y.c = y.e = null; + + // Return ±0 if either is ±0. + } else { + y.c = [0]; + y.e = 0; + } + } + + return y; + } + + e = bitFloor(x.e / LOG_BASE) + bitFloor(y.e / LOG_BASE); + y.s *= x.s; + xcL = xc.length; + ycL = yc.length; + + // Ensure xc points to longer array and xcL to its length. + if (xcL < ycL) { + zc = xc; + xc = yc; + yc = zc; + i = xcL; + xcL = ycL; + ycL = i; + } + + // Initialise the result array with zeros. + for (i = xcL + ycL, zc = []; i--; zc.push(0)); + + base = BASE; + sqrtBase = SQRT_BASE; + + for (i = ycL; --i >= 0;) { + c = 0; + ylo = yc[i] % sqrtBase; + yhi = yc[i] / sqrtBase | 0; + + for (k = xcL, j = i + k; j > i;) { + xlo = xc[--k] % sqrtBase; + xhi = xc[k] / sqrtBase | 0; + m = yhi * xlo + xhi * ylo; + xlo = ylo * xlo + ((m % sqrtBase) * sqrtBase) + zc[j] + c; + c = (xlo / base | 0) + (m / sqrtBase | 0) + yhi * xhi; + zc[j--] = xlo % base; + } + + zc[j] = c; + } + + if (c) { + ++e; + } else { + zc.splice(0, 1); + } + + return normalise(y, zc, e); + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber negated, + * i.e. multiplied by -1. + */ + P.negated = function () { + var x = new BigNumber(this); + x.s = -x.s || null; + return x; + }; + + + /* + * n + 0 = n + * n + N = N + * n + I = I + * 0 + n = n + * 0 + 0 = 0 + * 0 + N = N + * 0 + I = I + * N + n = N + * N + 0 = N + * N + N = N + * N + I = N + * I + n = I + * I + 0 = I + * I + N = N + * I + I = I + * + * Return a new BigNumber whose value is the value of this BigNumber plus the value of + * BigNumber(y, b). + */ + P.plus = function (y, b) { + var t, + x = this, + a = x.s; + + y = new BigNumber(y, b); + b = y.s; + + // Either NaN? + if (!a || !b) return new BigNumber(NaN); + + // Signs differ? + if (a != b) { + y.s = -b; + return x.minus(y); + } + + var xe = x.e / LOG_BASE, + ye = y.e / LOG_BASE, + xc = x.c, + yc = y.c; + + if (!xe || !ye) { + + // Return ±Infinity if either ±Infinity. + if (!xc || !yc) return new BigNumber(a / 0); + + // Either zero? + // Return y if y is non-zero, x if x is non-zero, or zero if both are zero. + if (!xc[0] || !yc[0]) return yc[0] ? y : new BigNumber(xc[0] ? x : a * 0); + } + + xe = bitFloor(xe); + ye = bitFloor(ye); + xc = xc.slice(); + + // Prepend zeros to equalise exponents. Faster to use reverse then do unshifts. + if (a = xe - ye) { + if (a > 0) { + ye = xe; + t = yc; + } else { + a = -a; + t = xc; + } + + t.reverse(); + for (; a--; t.push(0)); + t.reverse(); + } + + a = xc.length; + b = yc.length; + + // Point xc to the longer array, and b to the shorter length. + if (a - b < 0) { + t = yc; + yc = xc; + xc = t; + b = a; + } + + // Only start adding at yc.length - 1 as the further digits of xc can be ignored. + for (a = 0; b;) { + a = (xc[--b] = xc[b] + yc[b] + a) / BASE | 0; + xc[b] = BASE === xc[b] ? 0 : xc[b] % BASE; + } + + if (a) { + xc = [a].concat(xc); + ++ye; + } + + // No need to check for zero, as +x + +y != 0 && -x + -y != 0 + // ye = MAX_EXP + 1 possible + return normalise(y, xc, ye); + }; + + + /* + * If sd is undefined or null or true or false, return the number of significant digits of + * the value of this BigNumber, or null if the value of this BigNumber is ±Infinity or NaN. + * If sd is true include integer-part trailing zeros in the count. + * + * Otherwise, if sd is a number, return a new BigNumber whose value is the value of this + * BigNumber rounded to a maximum of sd significant digits using rounding mode rm, or + * ROUNDING_MODE if rm is omitted. + * + * sd {number|boolean} number: significant digits: integer, 1 to MAX inclusive. + * boolean: whether to count integer-part trailing zeros: true or false. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.precision = P.sd = function (sd, rm) { + var c, n, v, + x = this; + + if (sd != null && sd !== !!sd) { + intCheck(sd, 1, MAX); + if (rm == null) rm = ROUNDING_MODE; + else intCheck(rm, 0, 8); + + return round(new BigNumber(x), sd, rm); + } + + if (!(c = x.c)) return null; + v = c.length - 1; + n = v * LOG_BASE + 1; + + if (v = c[v]) { + + // Subtract the number of trailing zeros of the last element. + for (; v % 10 == 0; v /= 10, n--); + + // Add the number of digits of the first element. + for (v = c[0]; v >= 10; v /= 10, n++); + } + + if (sd && x.e + 1 > n) n = x.e + 1; + + return n; + }; + + + /* + * Return a new BigNumber whose value is the value of this BigNumber shifted by k places + * (powers of 10). Shift to the right if n > 0, and to the left if n < 0. + * + * k {number} Integer, -MAX_SAFE_INTEGER to MAX_SAFE_INTEGER inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {k}' + */ + P.shiftedBy = function (k) { + intCheck(k, -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER); + return this.times('1e' + k); + }; + + + /* + * sqrt(-n) = N + * sqrt(N) = N + * sqrt(-I) = N + * sqrt(I) = I + * sqrt(0) = 0 + * sqrt(-0) = -0 + * + * Return a new BigNumber whose value is the square root of the value of this BigNumber, + * rounded according to DECIMAL_PLACES and ROUNDING_MODE. + */ + P.squareRoot = P.sqrt = function () { + var m, n, r, rep, t, + x = this, + c = x.c, + s = x.s, + e = x.e, + dp = DECIMAL_PLACES + 4, + half = new BigNumber('0.5'); + + // Negative/NaN/Infinity/zero? + if (s !== 1 || !c || !c[0]) { + return new BigNumber(!s || s < 0 && (!c || c[0]) ? NaN : c ? x : 1 / 0); + } + + // Initial estimate. + s = Math.sqrt(+valueOf(x)); + + // Math.sqrt underflow/overflow? + // Pass x to Math.sqrt as integer, then adjust the exponent of the result. + if (s == 0 || s == 1 / 0) { + n = coeffToString(c); + if ((n.length + e) % 2 == 0) n += '0'; + s = Math.sqrt(+n); + e = bitFloor((e + 1) / 2) - (e < 0 || e % 2); + + if (s == 1 / 0) { + n = '5e' + e; + } else { + n = s.toExponential(); + n = n.slice(0, n.indexOf('e') + 1) + e; + } + + r = new BigNumber(n); + } else { + r = new BigNumber(s + ''); + } + + // Check for zero. + // r could be zero if MIN_EXP is changed after the this value was created. + // This would cause a division by zero (x/t) and hence Infinity below, which would cause + // coeffToString to throw. + if (r.c[0]) { + e = r.e; + s = e + dp; + if (s < 3) s = 0; + + // Newton-Raphson iteration. + for (; ;) { + t = r; + r = half.times(t.plus(div(x, t, dp, 1))); + + if (coeffToString(t.c).slice(0, s) === (n = coeffToString(r.c)).slice(0, s)) { + + // The exponent of r may here be one less than the final result exponent, + // e.g 0.0009999 (e-4) --> 0.001 (e-3), so adjust s so the rounding digits + // are indexed correctly. + if (r.e < e) --s; + n = n.slice(s - 3, s + 1); + + // The 4th rounding digit may be in error by -1 so if the 4 rounding digits + // are 9999 or 4999 (i.e. approaching a rounding boundary) continue the + // iteration. + if (n == '9999' || !rep && n == '4999') { + + // On the first iteration only, check to see if rounding up gives the + // exact result as the nines may infinitely repeat. + if (!rep) { + round(t, t.e + DECIMAL_PLACES + 2, 0); + + if (t.times(t).eq(x)) { + r = t; + break; + } + } + + dp += 4; + s += 4; + rep = 1; + } else { + + // If rounding digits are null, 0{0,4} or 50{0,3}, check for exact + // result. If not, then there are further digits and m will be truthy. + if (!+n || !+n.slice(1) && n.charAt(0) == '5') { + + // Truncate to the first rounding digit. + round(r, r.e + DECIMAL_PLACES + 2, 1); + m = !r.times(r).eq(x); + } + + break; + } + } + } + } + + return round(r, r.e + DECIMAL_PLACES + 1, ROUNDING_MODE, m); + }; + + + /* + * Return a string representing the value of this BigNumber in exponential notation and + * rounded using ROUNDING_MODE to dp fixed decimal places. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toExponential = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp++; + } + return format(this, dp, rm, 1); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounding + * to dp fixed decimal places using rounding mode rm, or ROUNDING_MODE if rm is omitted. + * + * Note: as with JavaScript's number type, (-0).toFixed(0) is '0', + * but e.g. (-0.00001).toFixed(0) is '-0'. + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + */ + P.toFixed = function (dp, rm) { + if (dp != null) { + intCheck(dp, 0, MAX); + dp = dp + this.e + 1; + } + return format(this, dp, rm); + }; + + + /* + * Return a string representing the value of this BigNumber in fixed-point notation rounded + * using rm or ROUNDING_MODE to dp decimal places, and formatted according to the properties + * of the format or FORMAT object (see BigNumber.set). + * + * The formatting object may contain some or all of the properties shown below. + * + * FORMAT = { + * prefix: '', + * groupSize: 3, + * secondaryGroupSize: 0, + * groupSeparator: ',', + * decimalSeparator: '.', + * fractionGroupSize: 0, + * fractionGroupSeparator: '\xA0', // non-breaking space + * suffix: '' + * }; + * + * [dp] {number} Decimal places. Integer, 0 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * [format] {object} Formatting options. See FORMAT pbject above. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {dp|rm}' + * '[BigNumber Error] Argument not an object: {format}' + */ + P.toFormat = function (dp, rm, format) { + var str, + x = this; + + if (format == null) { + if (dp != null && rm && typeof rm == 'object') { + format = rm; + rm = null; + } else if (dp && typeof dp == 'object') { + format = dp; + dp = rm = null; + } else { + format = FORMAT; + } + } else if (typeof format != 'object') { + throw Error + (bignumberError + 'Argument not an object: ' + format); + } + + str = x.toFixed(dp, rm); + + if (x.c) { + var i, + arr = str.split('.'), + g1 = +format.groupSize, + g2 = +format.secondaryGroupSize, + groupSeparator = format.groupSeparator || '', + intPart = arr[0], + fractionPart = arr[1], + isNeg = x.s < 0, + intDigits = isNeg ? intPart.slice(1) : intPart, + len = intDigits.length; + + if (g2) { + i = g1; + g1 = g2; + g2 = i; + len -= i; + } + + if (g1 > 0 && len > 0) { + i = len % g1 || g1; + intPart = intDigits.substr(0, i); + for (; i < len; i += g1) intPart += groupSeparator + intDigits.substr(i, g1); + if (g2 > 0) intPart += groupSeparator + intDigits.slice(i); + if (isNeg) intPart = '-' + intPart; + } + + str = fractionPart + ? intPart + (format.decimalSeparator || '') + ((g2 = +format.fractionGroupSize) + ? fractionPart.replace(new RegExp('\\d{' + g2 + '}\\B', 'g'), + '$&' + (format.fractionGroupSeparator || '')) + : fractionPart) + : intPart; + } + + return (format.prefix || '') + str + (format.suffix || ''); + }; + + + /* + * Return an array of two BigNumbers representing the value of this BigNumber as a simple + * fraction with an integer numerator and an integer denominator. + * The denominator will be a positive non-zero value less than or equal to the specified + * maximum denominator. If a maximum denominator is not specified, the denominator will be + * the lowest value necessary to represent the number exactly. + * + * [md] {number|string|BigNumber} Integer >= 1, or Infinity. The maximum denominator. + * + * '[BigNumber Error] Argument {not an integer|out of range} : {md}' + */ + P.toFraction = function (md) { + var d, d0, d1, d2, e, exp, n, n0, n1, q, r, s, + x = this, + xc = x.c; + + if (md != null) { + n = new BigNumber(md); + + // Throw if md is less than one or is not an integer, unless it is Infinity. + if (!n.isInteger() && (n.c || n.s !== 1) || n.lt(ONE)) { + throw Error + (bignumberError + 'Argument ' + + (n.isInteger() ? 'out of range: ' : 'not an integer: ') + valueOf(n)); + } + } + + if (!xc) return new BigNumber(x); + + d = new BigNumber(ONE); + n1 = d0 = new BigNumber(ONE); + d1 = n0 = new BigNumber(ONE); + s = coeffToString(xc); + + // Determine initial denominator. + // d is a power of 10 and the minimum max denominator that specifies the value exactly. + e = d.e = s.length - x.e - 1; + d.c[0] = POWS_TEN[(exp = e % LOG_BASE) < 0 ? LOG_BASE + exp : exp]; + md = !md || n.comparedTo(d) > 0 ? (e > 0 ? d : n1) : n; + + exp = MAX_EXP; + MAX_EXP = 1 / 0; + n = new BigNumber(s); + + // n0 = d1 = 0 + n0.c[0] = 0; + + for (; ;) { + q = div(n, d, 0, 1); + d2 = d0.plus(q.times(d1)); + if (d2.comparedTo(md) == 1) break; + d0 = d1; + d1 = d2; + n1 = n0.plus(q.times(d2 = n1)); + n0 = d2; + d = n.minus(q.times(d2 = d)); + n = d2; + } + + d2 = div(md.minus(d0), d1, 0, 1); + n0 = n0.plus(d2.times(n1)); + d0 = d0.plus(d2.times(d1)); + n0.s = n1.s = x.s; + e = e * 2; + + // Determine which fraction is closer to x, n0/d0 or n1/d1 + r = div(n1, d1, e, ROUNDING_MODE).minus(x).abs().comparedTo( + div(n0, d0, e, ROUNDING_MODE).minus(x).abs()) < 1 ? [n1, d1] : [n0, d0]; + + MAX_EXP = exp; + + return r; + }; + + + /* + * Return the value of this BigNumber converted to a number primitive. + */ + P.toNumber = function () { + return +valueOf(this); + }; + + + /* + * Return a string representing the value of this BigNumber rounded to sd significant digits + * using rounding mode rm or ROUNDING_MODE. If sd is less than the number of digits + * necessary to represent the integer part of the value in fixed-point notation, then use + * exponential notation. + * + * [sd] {number} Significant digits. Integer, 1 to MAX inclusive. + * [rm] {number} Rounding mode. Integer, 0 to 8 inclusive. + * + * '[BigNumber Error] Argument {not a primitive number|not an integer|out of range}: {sd|rm}' + */ + P.toPrecision = function (sd, rm) { + if (sd != null) intCheck(sd, 1, MAX); + return format(this, sd, rm, 2); + }; + + + /* + * Return a string representing the value of this BigNumber in base b, or base 10 if b is + * omitted. If a base is specified, including base 10, round according to DECIMAL_PLACES and + * ROUNDING_MODE. If a base is not specified, and this BigNumber has a positive exponent + * that is equal to or greater than TO_EXP_POS, or a negative exponent equal to or less than + * TO_EXP_NEG, return exponential notation. + * + * [b] {number} Integer, 2 to ALPHABET.length inclusive. + * + * '[BigNumber Error] Base {not a primitive number|not an integer|out of range}: {b}' + */ + P.toString = function (b) { + var str, + n = this, + s = n.s, + e = n.e; + + // Infinity or NaN? + if (e === null) { + if (s) { + str = 'Infinity'; + if (s < 0) str = '-' + str; + } else { + str = 'NaN'; + } + } else { + if (b == null) { + str = e <= TO_EXP_NEG || e >= TO_EXP_POS + ? toExponential(coeffToString(n.c), e) + : toFixedPoint(coeffToString(n.c), e, '0'); + } else if (b === 10 && alphabetHasNormalDecimalDigits) { + n = round(new BigNumber(n), DECIMAL_PLACES + e + 1, ROUNDING_MODE); + str = toFixedPoint(coeffToString(n.c), n.e, '0'); + } else { + intCheck(b, 2, ALPHABET.length, 'Base'); + str = convertBase(toFixedPoint(coeffToString(n.c), e, '0'), 10, b, s, true); + } + + if (s < 0 && n.c[0]) str = '-' + str; + } + + return str; + }; + + + /* + * Return as toString, but do not accept a base argument, and include the minus sign for + * negative zero. + */ + P.valueOf = P.toJSON = function () { + return valueOf(this); + }; + + + P._isBigNumber = true; + + if (configObject != null) BigNumber.set(configObject); + + return BigNumber; + } + + + // PRIVATE HELPER FUNCTIONS + + // These functions don't need access to variables, + // e.g. DECIMAL_PLACES, in the scope of the `clone` function above. + + + function bitFloor(n) { + var i = n | 0; + return n > 0 || n === i ? i : i - 1; + } + + + // Return a coefficient array as a string of base 10 digits. + function coeffToString(a) { + var s, z, + i = 1, + j = a.length, + r = a[0] + ''; + + for (; i < j;) { + s = a[i++] + ''; + z = LOG_BASE - s.length; + for (; z--; s = '0' + s); + r += s; + } + + // Determine trailing zeros. + for (j = r.length; r.charCodeAt(--j) === 48;); + + return r.slice(0, j + 1 || 1); + } + + + // Compare the value of BigNumbers x and y. + function compare(x, y) { + var a, b, + xc = x.c, + yc = y.c, + i = x.s, + j = y.s, + k = x.e, + l = y.e; + + // Either NaN? + if (!i || !j) return null; + + a = xc && !xc[0]; + b = yc && !yc[0]; + + // Either zero? + if (a || b) return a ? b ? 0 : -j : i; + + // Signs differ? + if (i != j) return i; + + a = i < 0; + b = k == l; + + // Either Infinity? + if (!xc || !yc) return b ? 0 : !xc ^ a ? 1 : -1; + + // Compare exponents. + if (!b) return k > l ^ a ? 1 : -1; + + j = (k = xc.length) < (l = yc.length) ? k : l; + + // Compare digit by digit. + for (i = 0; i < j; i++) if (xc[i] != yc[i]) return xc[i] > yc[i] ^ a ? 1 : -1; + + // Compare lengths. + return k == l ? 0 : k > l ^ a ? 1 : -1; + } + + + /* + * Check that n is a primitive number, an integer, and in range, otherwise throw. + */ + function intCheck(n, min, max, name) { + if (n < min || n > max || n !== mathfloor(n)) { + throw Error + (bignumberError + (name || 'Argument') + (typeof n == 'number' + ? n < min || n > max ? ' out of range: ' : ' not an integer: ' + : ' not a primitive number: ') + String(n)); + } + } + + + // Assumes finite n. + function isOdd(n) { + var k = n.c.length - 1; + return bitFloor(n.e / LOG_BASE) == k && n.c[k] % 2 != 0; + } + + + function toExponential(str, e) { + return (str.length > 1 ? str.charAt(0) + '.' + str.slice(1) : str) + + (e < 0 ? 'e' : 'e+') + e; + } + + + function toFixedPoint(str, e, z) { + var len, zs; + + // Negative exponent? + if (e < 0) { + + // Prepend zeros. + for (zs = z + '.'; ++e; zs += z); + str = zs + str; + + // Positive exponent + } else { + len = str.length; + + // Append zeros. + if (++e > len) { + for (zs = z, e -= len; --e; zs += z); + str += zs; + } else if (e < len) { + str = str.slice(0, e) + '.' + str.slice(e); + } + } + + return str; + } + + + // EXPORT + + + BigNumber = clone(); + BigNumber['default'] = BigNumber.BigNumber = BigNumber; + + // AMD. + if (typeof define == 'function' && define.amd) { + define(function () { return BigNumber; }); + + // Node.js and other environments that support module.exports. + } else if ( true && module.exports) { + module.exports = BigNumber; + + // Browser. + } else { + if (!globalObject) { + globalObject = typeof self != 'undefined' && self ? self : window; + } + + globalObject.BigNumber = BigNumber; + } +})(this); + + +/***/ }), + +/***/ 39732: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/*jshint node:true */ + +var Buffer = (__nccwpck_require__(20181).Buffer); // browserify +var SlowBuffer = (__nccwpck_require__(20181).SlowBuffer); + +module.exports = bufferEq; + +function bufferEq(a, b) { + + // shortcutting on type is necessary for correctness + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + return false; + } + + // buffer sizes should be well-known information, so despite this + // shortcutting, it doesn't leak any information about the *contents* of the + // buffers. + if (a.length !== b.length) { + return false; + } + + var c = 0; + for (var i = 0; i < a.length; i++) { + /*jshint bitwise:false */ + c |= a[i] ^ b[i]; // XOR + } + return c === 0; +} + +bufferEq.install = function() { + Buffer.prototype.equal = SlowBuffer.prototype.equal = function equal(that) { + return bufferEq(this, that); + }; +}; + +var origBufEqual = Buffer.prototype.equal; +var origSlowBufEqual = SlowBuffer.prototype.equal; +bufferEq.restore = function() { + Buffer.prototype.equal = origBufEqual; + SlowBuffer.prototype.equal = origSlowBufEqual; +}; + + +/***/ }), + +/***/ 6110: +/***/ ((module, exports, __nccwpck_require__) => { + +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + let m; + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + // eslint-disable-next-line no-return-assign + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && (m = navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)) && parseInt(m[1], 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug') || exports.storage.getItem('DEBUG') ; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = __nccwpck_require__(40897)(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; + + +/***/ }), + +/***/ 40897: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = __nccwpck_require__(70744); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + let namespacesCache; + let enabledCache; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => { + if (enableOverride !== null) { + return enableOverride; + } + if (namespacesCache !== createDebug.namespaces) { + namespacesCache = createDebug.namespaces; + enabledCache = createDebug.enabled(namespace); + } + + return enabledCache; + }, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + createDebug.namespaces = namespaces; + + createDebug.names = []; + createDebug.skips = []; + + const split = (typeof namespaces === 'string' ? namespaces : '') + .trim() + .replace(/\s+/g, ',') + .split(',') + .filter(Boolean); + + for (const ns of split) { + if (ns[0] === '-') { + createDebug.skips.push(ns.slice(1)); + } else { + createDebug.names.push(ns); + } + } + } + + /** + * Checks if the given string matches a namespace template, honoring + * asterisks as wildcards. + * + * @param {String} search + * @param {String} template + * @return {Boolean} + */ + function matchesTemplate(search, template) { + let searchIndex = 0; + let templateIndex = 0; + let starIndex = -1; + let matchIndex = 0; + + while (searchIndex < search.length) { + if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) { + // Match character or proceed with wildcard + if (template[templateIndex] === '*') { + starIndex = templateIndex; + matchIndex = searchIndex; + templateIndex++; // Skip the '*' + } else { + searchIndex++; + templateIndex++; + } + } else if (starIndex !== -1) { // eslint-disable-line no-negated-condition + // Backtrack to the last '*' and try to match more characters + templateIndex = starIndex + 1; + matchIndex++; + searchIndex = matchIndex; + } else { + return false; // No match + } + } + + // Handle trailing '*' in template + while (templateIndex < template.length && template[templateIndex] === '*') { + templateIndex++; + } + + return templateIndex === template.length; + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names, + ...createDebug.skips.map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + for (const skip of createDebug.skips) { + if (matchesTemplate(name, skip)) { + return false; + } + } + + for (const ns of createDebug.names) { + if (matchesTemplate(name, ns)) { + return true; + } + } + + return false; + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; + + +/***/ }), + +/***/ 2830: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = __nccwpck_require__(6110); +} else { + module.exports = __nccwpck_require__(95108); +} + + +/***/ }), + +/***/ 95108: +/***/ ((module, exports, __nccwpck_require__) => { + +/** + * Module dependencies. + */ + +const tty = __nccwpck_require__(52018); +const util = __nccwpck_require__(39023); + +/** + * This is the Node.js implementation of `debug()`. + */ + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.destroy = util.deprecate( + () => {}, + 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' +); + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = __nccwpck_require__(60075); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; +} + +/** + * Invokes `util.formatWithOptions()` with the specified arguments and writes to stderr. + */ + +function log(...args) { + return process.stderr.write(util.formatWithOptions(exports.inspectOpts, ...args) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +module.exports = __nccwpck_require__(40897)(exports); + +const {formatters} = module.exports; + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); +}; + +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; + + +/***/ }), + +/***/ 29112: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var stream = __nccwpck_require__(86131) +var eos = __nccwpck_require__(31424) +var inherits = __nccwpck_require__(39598) +var shift = __nccwpck_require__(34633) + +var SIGNAL_FLUSH = (Buffer.from && Buffer.from !== Uint8Array.from) + ? Buffer.from([0]) + : new Buffer([0]) + +var onuncork = function(self, fn) { + if (self._corked) self.once('uncork', fn) + else fn() +} + +var autoDestroy = function (self, err) { + if (self._autoDestroy) self.destroy(err) +} + +var destroyer = function(self, end) { + return function(err) { + if (err) autoDestroy(self, err.message === 'premature close' ? null : err) + else if (end && !self._ended) self.end() + } +} + +var end = function(ws, fn) { + if (!ws) return fn() + if (ws._writableState && ws._writableState.finished) return fn() + if (ws._writableState) return ws.end(fn) + ws.end() + fn() +} + +var noop = function() {} + +var toStreams2 = function(rs) { + return new (stream.Readable)({objectMode:true, highWaterMark:16}).wrap(rs) +} + +var Duplexify = function(writable, readable, opts) { + if (!(this instanceof Duplexify)) return new Duplexify(writable, readable, opts) + stream.Duplex.call(this, opts) + + this._writable = null + this._readable = null + this._readable2 = null + + this._autoDestroy = !opts || opts.autoDestroy !== false + this._forwardDestroy = !opts || opts.destroy !== false + this._forwardEnd = !opts || opts.end !== false + this._corked = 1 // start corked + this._ondrain = null + this._drained = false + this._forwarding = false + this._unwrite = null + this._unread = null + this._ended = false + + this.destroyed = false + + if (writable) this.setWritable(writable) + if (readable) this.setReadable(readable) +} + +inherits(Duplexify, stream.Duplex) + +Duplexify.obj = function(writable, readable, opts) { + if (!opts) opts = {} + opts.objectMode = true + opts.highWaterMark = 16 + return new Duplexify(writable, readable, opts) +} + +Duplexify.prototype.cork = function() { + if (++this._corked === 1) this.emit('cork') +} + +Duplexify.prototype.uncork = function() { + if (this._corked && --this._corked === 0) this.emit('uncork') +} + +Duplexify.prototype.setWritable = function(writable) { + if (this._unwrite) this._unwrite() + + if (this.destroyed) { + if (writable && writable.destroy) writable.destroy() + return + } + + if (writable === null || writable === false) { + this.end() + return + } + + var self = this + var unend = eos(writable, {writable:true, readable:false}, destroyer(this, this._forwardEnd)) + + var ondrain = function() { + var ondrain = self._ondrain + self._ondrain = null + if (ondrain) ondrain() + } + + var clear = function() { + self._writable.removeListener('drain', ondrain) + unend() + } + + if (this._unwrite) process.nextTick(ondrain) // force a drain on stream reset to avoid livelocks + + this._writable = writable + this._writable.on('drain', ondrain) + this._unwrite = clear + + this.uncork() // always uncork setWritable +} + +Duplexify.prototype.setReadable = function(readable) { + if (this._unread) this._unread() + + if (this.destroyed) { + if (readable && readable.destroy) readable.destroy() + return + } + + if (readable === null || readable === false) { + this.push(null) + this.resume() + return + } + + var self = this + var unend = eos(readable, {writable:false, readable:true}, destroyer(this)) + + var onreadable = function() { + self._forward() + } + + var onend = function() { + self.push(null) + } + + var clear = function() { + self._readable2.removeListener('readable', onreadable) + self._readable2.removeListener('end', onend) + unend() + } + + this._drained = true + this._readable = readable + this._readable2 = readable._readableState ? readable : toStreams2(readable) + this._readable2.on('readable', onreadable) + this._readable2.on('end', onend) + this._unread = clear + + this._forward() +} + +Duplexify.prototype._read = function() { + this._drained = true + this._forward() +} + +Duplexify.prototype._forward = function() { + if (this._forwarding || !this._readable2 || !this._drained) return + this._forwarding = true + + var data + + while (this._drained && (data = shift(this._readable2)) !== null) { + if (this.destroyed) continue + this._drained = this.push(data) + } + + this._forwarding = false +} + +Duplexify.prototype.destroy = function(err, cb) { + if (!cb) cb = noop + if (this.destroyed) return cb(null) + this.destroyed = true + + var self = this + process.nextTick(function() { + self._destroy(err) + cb(null) + }) +} + +Duplexify.prototype._destroy = function(err) { + if (err) { + var ondrain = this._ondrain + this._ondrain = null + if (ondrain) ondrain(err) + else this.emit('error', err) + } + + if (this._forwardDestroy) { + if (this._readable && this._readable.destroy) this._readable.destroy() + if (this._writable && this._writable.destroy) this._writable.destroy() + } + + this.emit('close') +} + +Duplexify.prototype._write = function(data, enc, cb) { + if (this.destroyed) return + if (this._corked) return onuncork(this, this._write.bind(this, data, enc, cb)) + if (data === SIGNAL_FLUSH) return this._finish(cb) + if (!this._writable) return cb() + + if (this._writable.write(data) === false) this._ondrain = cb + else if (!this.destroyed) cb() +} + +Duplexify.prototype._finish = function(cb) { + var self = this + this.emit('preend') + onuncork(this, function() { + end(self._forwardEnd && self._writable, function() { + // haxx to not emit prefinish twice + if (self._writableState.prefinished === false) self._writableState.prefinished = true + self.emit('prefinish') + onuncork(self, cb) + }) + }) +} + +Duplexify.prototype.end = function(data, enc, cb) { + if (typeof data === 'function') return this.end(null, null, data) + if (typeof enc === 'function') return this.end(data, null, enc) + this._ended = true + if (data) this.write(data) + if (!this._writableState.ending && !this._writableState.destroyed) this.write(SIGNAL_FLUSH) + return stream.Writable.prototype.end.call(this, cb) +} + +module.exports = Duplexify + + +/***/ }), + +/***/ 325: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var Buffer = (__nccwpck_require__(93058).Buffer); + +var getParamBytesForAlg = __nccwpck_require__(5028); + +var MAX_OCTET = 0x80, + CLASS_UNIVERSAL = 0, + PRIMITIVE_BIT = 0x20, + TAG_SEQ = 0x10, + TAG_INT = 0x02, + ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6), + ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6); + +function base64Url(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function signatureAsBuffer(signature) { + if (Buffer.isBuffer(signature)) { + return signature; + } else if ('string' === typeof signature) { + return Buffer.from(signature, 'base64'); + } + + throw new TypeError('ECDSA signature must be a Base64 string or a Buffer'); +} + +function derToJose(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + // the DER encoded param should at most be the param size, plus a padding + // zero, since due to being a signed integer + var maxEncodedParamLength = paramBytes + 1; + + var inputLength = signature.length; + + var offset = 0; + if (signature[offset++] !== ENCODED_TAG_SEQ) { + throw new Error('Could not find expected "seq"'); + } + + var seqLength = signature[offset++]; + if (seqLength === (MAX_OCTET | 1)) { + seqLength = signature[offset++]; + } + + if (inputLength - offset < seqLength) { + throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining'); + } + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "r"'); + } + + var rLength = signature[offset++]; + + if (inputLength - offset - 2 < rLength) { + throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available'); + } + + if (maxEncodedParamLength < rLength) { + throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var rOffset = offset; + offset += rLength; + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "s"'); + } + + var sLength = signature[offset++]; + + if (inputLength - offset !== sLength) { + throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"'); + } + + if (maxEncodedParamLength < sLength) { + throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var sOffset = offset; + offset += sLength; + + if (offset !== inputLength) { + throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain'); + } + + var rPadding = paramBytes - rLength, + sPadding = paramBytes - sLength; + + var dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength); + + for (offset = 0; offset < rPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength); + + offset = paramBytes; + + for (var o = offset; offset < o + sPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength); + + dst = dst.toString('base64'); + dst = base64Url(dst); + + return dst; +} + +function countPadding(buf, start, stop) { + var padding = 0; + while (start + padding < stop && buf[start + padding] === 0) { + ++padding; + } + + var needsSign = buf[start + padding] >= MAX_OCTET; + if (needsSign) { + --padding; + } + + return padding; +} + +function joseToDer(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + var signatureBytes = signature.length; + if (signatureBytes !== paramBytes * 2) { + throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"'); + } + + var rPadding = countPadding(signature, 0, paramBytes); + var sPadding = countPadding(signature, paramBytes, signature.length); + var rLength = paramBytes - rPadding; + var sLength = paramBytes - sPadding; + + var rsBytes = 1 + 1 + rLength + 1 + 1 + sLength; + + var shortLength = rsBytes < MAX_OCTET; + + var dst = Buffer.allocUnsafe((shortLength ? 2 : 3) + rsBytes); + + var offset = 0; + dst[offset++] = ENCODED_TAG_SEQ; + if (shortLength) { + // Bit 8 has value "0" + // bits 7-1 give the length. + dst[offset++] = rsBytes; + } else { + // Bit 8 of first octet has value "1" + // bits 7-1 give the number of additional length octets. + dst[offset++] = MAX_OCTET | 1; + // length, base 256 + dst[offset++] = rsBytes & 0xff; + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = rLength; + if (rPadding < 0) { + dst[offset++] = 0; + offset += signature.copy(dst, offset, 0, paramBytes); + } else { + offset += signature.copy(dst, offset, rPadding, paramBytes); + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = sLength; + if (sPadding < 0) { + dst[offset++] = 0; + signature.copy(dst, offset, paramBytes); + } else { + signature.copy(dst, offset, paramBytes + sPadding); + } + + return dst; +} + +module.exports = { + derToJose: derToJose, + joseToDer: joseToDer +}; + + +/***/ }), + +/***/ 5028: +/***/ ((module) => { + +"use strict"; + + +function getParamSize(keySize) { + var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1); + return result; +} + +var paramBytesForAlg = { + ES256: getParamSize(256), + ES384: getParamSize(384), + ES512: getParamSize(521) +}; + +function getParamBytesForAlg(alg) { + var paramBytes = paramBytesForAlg[alg]; + if (paramBytes) { + return paramBytes; + } + + throw new Error('Unknown algorithm "' + alg + '"'); +} + +module.exports = getParamBytesForAlg; + + +/***/ }), + +/***/ 31424: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var once = __nccwpck_require__(55560); + +var noop = function() {}; + +var qnt = global.Bare ? queueMicrotask : process.nextTick.bind(process); + +var isRequest = function(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +}; + +var isChildProcess = function(stream) { + return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 +}; + +var eos = function(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + + callback = once(callback || noop); + + var ws = stream._writableState; + var rs = stream._readableState; + var readable = opts.readable || (opts.readable !== false && stream.readable); + var writable = opts.writable || (opts.writable !== false && stream.writable); + var cancelled = false; + + var onlegacyfinish = function() { + if (!stream.writable) onfinish(); + }; + + var onfinish = function() { + writable = false; + if (!readable) callback.call(stream); + }; + + var onend = function() { + readable = false; + if (!writable) callback.call(stream); + }; + + var onexit = function(exitCode) { + callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); + }; + + var onerror = function(err) { + callback.call(stream, err); + }; + + var onclose = function() { + qnt(onclosenexttick); + }; + + var onclosenexttick = function() { + if (cancelled) return; + if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close')); + }; + + var onrequest = function() { + stream.req.on('finish', onfinish); + }; + + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest(); + else stream.on('request', onrequest); + } else if (writable && !ws) { // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + + if (isChildProcess(stream)) stream.on('exit', onexit); + + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + + return function() { + cancelled = true; + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('exit', onexit); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +}; + +module.exports = eos; + + +/***/ }), + +/***/ 16577: +/***/ ((module, exports) => { + +"use strict"; +/** + * @author Toru Nagashima + * @copyright 2015 Toru Nagashima. All rights reserved. + * See LICENSE file in root directory for full license. + */ + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +/** + * @typedef {object} PrivateData + * @property {EventTarget} eventTarget The event target. + * @property {{type:string}} event The original event object. + * @property {number} eventPhase The current event phase. + * @property {EventTarget|null} currentTarget The current event target. + * @property {boolean} canceled The flag to prevent default. + * @property {boolean} stopped The flag to stop propagation. + * @property {boolean} immediateStopped The flag to stop propagation immediately. + * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null. + * @property {number} timeStamp The unix time. + * @private + */ + +/** + * Private data for event wrappers. + * @type {WeakMap} + * @private + */ +const privateData = new WeakMap(); + +/** + * Cache for wrapper classes. + * @type {WeakMap} + * @private + */ +const wrappers = new WeakMap(); + +/** + * Get private data. + * @param {Event} event The event object to get private data. + * @returns {PrivateData} The private data of the event. + * @private + */ +function pd(event) { + const retv = privateData.get(event); + console.assert( + retv != null, + "'this' is expected an Event object, but got", + event + ); + return retv +} + +/** + * https://dom.spec.whatwg.org/#set-the-canceled-flag + * @param data {PrivateData} private data. + */ +function setCancelFlag(data) { + if (data.passiveListener != null) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error( + "Unable to preventDefault inside passive event listener invocation.", + data.passiveListener + ); + } + return + } + if (!data.event.cancelable) { + return + } + + data.canceled = true; + if (typeof data.event.preventDefault === "function") { + data.event.preventDefault(); + } +} + +/** + * @see https://dom.spec.whatwg.org/#interface-event + * @private + */ +/** + * The event wrapper. + * @constructor + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Event|{type:string}} event The original event to wrap. + */ +function Event(eventTarget, event) { + privateData.set(this, { + eventTarget, + event, + eventPhase: 2, + currentTarget: eventTarget, + canceled: false, + stopped: false, + immediateStopped: false, + passiveListener: null, + timeStamp: event.timeStamp || Date.now(), + }); + + // https://heycam.github.io/webidl/#Unforgeable + Object.defineProperty(this, "isTrusted", { value: false, enumerable: true }); + + // Define accessors + const keys = Object.keys(event); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in this)) { + Object.defineProperty(this, key, defineRedirectDescriptor(key)); + } + } +} + +// Should be enumerable, but class methods are not enumerable. +Event.prototype = { + /** + * The type of this event. + * @type {string} + */ + get type() { + return pd(this).event.type + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get target() { + return pd(this).eventTarget + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get currentTarget() { + return pd(this).currentTarget + }, + + /** + * @returns {EventTarget[]} The composed path of this event. + */ + composedPath() { + const currentTarget = pd(this).currentTarget; + if (currentTarget == null) { + return [] + } + return [currentTarget] + }, + + /** + * Constant of NONE. + * @type {number} + */ + get NONE() { + return 0 + }, + + /** + * Constant of CAPTURING_PHASE. + * @type {number} + */ + get CAPTURING_PHASE() { + return 1 + }, + + /** + * Constant of AT_TARGET. + * @type {number} + */ + get AT_TARGET() { + return 2 + }, + + /** + * Constant of BUBBLING_PHASE. + * @type {number} + */ + get BUBBLING_PHASE() { + return 3 + }, + + /** + * The target of this event. + * @type {number} + */ + get eventPhase() { + return pd(this).eventPhase + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopPropagation() { + const data = pd(this); + + data.stopped = true; + if (typeof data.event.stopPropagation === "function") { + data.event.stopPropagation(); + } + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopImmediatePropagation() { + const data = pd(this); + + data.stopped = true; + data.immediateStopped = true; + if (typeof data.event.stopImmediatePropagation === "function") { + data.event.stopImmediatePropagation(); + } + }, + + /** + * The flag to be bubbling. + * @type {boolean} + */ + get bubbles() { + return Boolean(pd(this).event.bubbles) + }, + + /** + * The flag to be cancelable. + * @type {boolean} + */ + get cancelable() { + return Boolean(pd(this).event.cancelable) + }, + + /** + * Cancel this event. + * @returns {void} + */ + preventDefault() { + setCancelFlag(pd(this)); + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + */ + get defaultPrevented() { + return pd(this).canceled + }, + + /** + * The flag to be composed. + * @type {boolean} + */ + get composed() { + return Boolean(pd(this).event.composed) + }, + + /** + * The unix time of this event. + * @type {number} + */ + get timeStamp() { + return pd(this).timeStamp + }, + + /** + * The target of this event. + * @type {EventTarget} + * @deprecated + */ + get srcElement() { + return pd(this).eventTarget + }, + + /** + * The flag to stop event bubbling. + * @type {boolean} + * @deprecated + */ + get cancelBubble() { + return pd(this).stopped + }, + set cancelBubble(value) { + if (!value) { + return + } + const data = pd(this); + + data.stopped = true; + if (typeof data.event.cancelBubble === "boolean") { + data.event.cancelBubble = true; + } + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + * @deprecated + */ + get returnValue() { + return !pd(this).canceled + }, + set returnValue(value) { + if (!value) { + setCancelFlag(pd(this)); + } + }, + + /** + * Initialize this event object. But do nothing under event dispatching. + * @param {string} type The event type. + * @param {boolean} [bubbles=false] The flag to be possible to bubble up. + * @param {boolean} [cancelable=false] The flag to be possible to cancel. + * @deprecated + */ + initEvent() { + // Do nothing. + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(Event.prototype, "constructor", { + value: Event, + configurable: true, + writable: true, +}); + +// Ensure `event instanceof window.Event` is `true`. +if (typeof window !== "undefined" && typeof window.Event !== "undefined") { + Object.setPrototypeOf(Event.prototype, window.Event.prototype); + + // Make association for wrappers. + wrappers.set(window.Event.prototype, Event); +} + +/** + * Get the property descriptor to redirect a given property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to redirect the property. + * @private + */ +function defineRedirectDescriptor(key) { + return { + get() { + return pd(this).event[key] + }, + set(value) { + pd(this).event[key] = value; + }, + configurable: true, + enumerable: true, + } +} + +/** + * Get the property descriptor to call a given method property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to call the method property. + * @private + */ +function defineCallDescriptor(key) { + return { + value() { + const event = pd(this).event; + return event[key].apply(event, arguments) + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define new wrapper class. + * @param {Function} BaseEvent The base wrapper class. + * @param {Object} proto The prototype of the original event. + * @returns {Function} The defined wrapper class. + * @private + */ +function defineWrapper(BaseEvent, proto) { + const keys = Object.keys(proto); + if (keys.length === 0) { + return BaseEvent + } + + /** CustomEvent */ + function CustomEvent(eventTarget, event) { + BaseEvent.call(this, eventTarget, event); + } + + CustomEvent.prototype = Object.create(BaseEvent.prototype, { + constructor: { value: CustomEvent, configurable: true, writable: true }, + }); + + // Define accessors. + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in BaseEvent.prototype)) { + const descriptor = Object.getOwnPropertyDescriptor(proto, key); + const isFunc = typeof descriptor.value === "function"; + Object.defineProperty( + CustomEvent.prototype, + key, + isFunc + ? defineCallDescriptor(key) + : defineRedirectDescriptor(key) + ); + } + } + + return CustomEvent +} + +/** + * Get the wrapper class of a given prototype. + * @param {Object} proto The prototype of the original event to get its wrapper. + * @returns {Function} The wrapper class. + * @private + */ +function getWrapper(proto) { + if (proto == null || proto === Object.prototype) { + return Event + } + + let wrapper = wrappers.get(proto); + if (wrapper == null) { + wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto); + wrappers.set(proto, wrapper); + } + return wrapper +} + +/** + * Wrap a given event to management a dispatching. + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Object} event The event to wrap. + * @returns {Event} The wrapper instance. + * @private + */ +function wrapEvent(eventTarget, event) { + const Wrapper = getWrapper(Object.getPrototypeOf(event)); + return new Wrapper(eventTarget, event) +} + +/** + * Get the immediateStopped flag of a given event. + * @param {Event} event The event to get. + * @returns {boolean} The flag to stop propagation immediately. + * @private + */ +function isStopped(event) { + return pd(event).immediateStopped +} + +/** + * Set the current event phase of a given event. + * @param {Event} event The event to set current target. + * @param {number} eventPhase New event phase. + * @returns {void} + * @private + */ +function setEventPhase(event, eventPhase) { + pd(event).eventPhase = eventPhase; +} + +/** + * Set the current target of a given event. + * @param {Event} event The event to set current target. + * @param {EventTarget|null} currentTarget New current target. + * @returns {void} + * @private + */ +function setCurrentTarget(event, currentTarget) { + pd(event).currentTarget = currentTarget; +} + +/** + * Set a passive listener of a given event. + * @param {Event} event The event to set current target. + * @param {Function|null} passiveListener New passive listener. + * @returns {void} + * @private + */ +function setPassiveListener(event, passiveListener) { + pd(event).passiveListener = passiveListener; +} + +/** + * @typedef {object} ListenerNode + * @property {Function} listener + * @property {1|2|3} listenerType + * @property {boolean} passive + * @property {boolean} once + * @property {ListenerNode|null} next + * @private + */ + +/** + * @type {WeakMap>} + * @private + */ +const listenersMap = new WeakMap(); + +// Listener types +const CAPTURE = 1; +const BUBBLE = 2; +const ATTRIBUTE = 3; + +/** + * Check whether a given value is an object or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if the value is an object. + */ +function isObject(x) { + return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax +} + +/** + * Get listeners. + * @param {EventTarget} eventTarget The event target to get. + * @returns {Map} The listeners. + * @private + */ +function getListeners(eventTarget) { + const listeners = listenersMap.get(eventTarget); + if (listeners == null) { + throw new TypeError( + "'this' is expected an EventTarget object, but got another value." + ) + } + return listeners +} + +/** + * Get the property descriptor for the event attribute of a given event. + * @param {string} eventName The event name to get property descriptor. + * @returns {PropertyDescriptor} The property descriptor. + * @private + */ +function defineEventAttributeDescriptor(eventName) { + return { + get() { + const listeners = getListeners(this); + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + return node.listener + } + node = node.next; + } + return null + }, + + set(listener) { + if (typeof listener !== "function" && !isObject(listener)) { + listener = null; // eslint-disable-line no-param-reassign + } + const listeners = getListeners(this); + + // Traverse to the tail while removing old value. + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + // Remove old value. + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + node = node.next; + } + + // Add new value. + if (listener !== null) { + const newNode = { + listener, + listenerType: ATTRIBUTE, + passive: false, + once: false, + next: null, + }; + if (prev === null) { + listeners.set(eventName, newNode); + } else { + prev.next = newNode; + } + } + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define an event attribute (e.g. `eventTarget.onclick`). + * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite. + * @param {string} eventName The event name to define. + * @returns {void} + */ +function defineEventAttribute(eventTargetPrototype, eventName) { + Object.defineProperty( + eventTargetPrototype, + `on${eventName}`, + defineEventAttributeDescriptor(eventName) + ); +} + +/** + * Define a custom EventTarget with event attributes. + * @param {string[]} eventNames Event names for event attributes. + * @returns {EventTarget} The custom EventTarget. + * @private + */ +function defineCustomEventTarget(eventNames) { + /** CustomEventTarget */ + function CustomEventTarget() { + EventTarget.call(this); + } + + CustomEventTarget.prototype = Object.create(EventTarget.prototype, { + constructor: { + value: CustomEventTarget, + configurable: true, + writable: true, + }, + }); + + for (let i = 0; i < eventNames.length; ++i) { + defineEventAttribute(CustomEventTarget.prototype, eventNames[i]); + } + + return CustomEventTarget +} + +/** + * EventTarget. + * + * - This is constructor if no arguments. + * - This is a function which returns a CustomEventTarget constructor if there are arguments. + * + * For example: + * + * class A extends EventTarget {} + * class B extends EventTarget("message") {} + * class C extends EventTarget("message", "error") {} + * class D extends EventTarget(["message", "error"]) {} + */ +function EventTarget() { + /*eslint-disable consistent-return */ + if (this instanceof EventTarget) { + listenersMap.set(this, new Map()); + return + } + if (arguments.length === 1 && Array.isArray(arguments[0])) { + return defineCustomEventTarget(arguments[0]) + } + if (arguments.length > 0) { + const types = new Array(arguments.length); + for (let i = 0; i < arguments.length; ++i) { + types[i] = arguments[i]; + } + return defineCustomEventTarget(types) + } + throw new TypeError("Cannot call a class as a function") + /*eslint-enable consistent-return */ +} + +// Should be enumerable, but class methods are not enumerable. +EventTarget.prototype = { + /** + * Add a given listener to this event target. + * @param {string} eventName The event name to add. + * @param {Function} listener The listener to add. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + addEventListener(eventName, listener, options) { + if (listener == null) { + return + } + if (typeof listener !== "function" && !isObject(listener)) { + throw new TypeError("'listener' should be a function or an object.") + } + + const listeners = getListeners(this); + const optionsIsObj = isObject(options); + const capture = optionsIsObj + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + const newNode = { + listener, + listenerType, + passive: optionsIsObj && Boolean(options.passive), + once: optionsIsObj && Boolean(options.once), + next: null, + }; + + // Set it as the first node if the first node is null. + let node = listeners.get(eventName); + if (node === undefined) { + listeners.set(eventName, newNode); + return + } + + // Traverse to the tail while checking duplication.. + let prev = null; + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + // Should ignore duplication. + return + } + prev = node; + node = node.next; + } + + // Add it. + prev.next = newNode; + }, + + /** + * Remove a given listener from this event target. + * @param {string} eventName The event name to remove. + * @param {Function} listener The listener to remove. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + removeEventListener(eventName, listener, options) { + if (listener == null) { + return + } + + const listeners = getListeners(this); + const capture = isObject(options) + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + return + } + + prev = node; + node = node.next; + } + }, + + /** + * Dispatch a given event. + * @param {Event|{type:string}} event The event to dispatch. + * @returns {boolean} `false` if canceled. + */ + dispatchEvent(event) { + if (event == null || typeof event.type !== "string") { + throw new TypeError('"event.type" should be a string.') + } + + // If listeners aren't registered, terminate. + const listeners = getListeners(this); + const eventName = event.type; + let node = listeners.get(eventName); + if (node == null) { + return true + } + + // Since we cannot rewrite several properties, so wrap object. + const wrappedEvent = wrapEvent(this, event); + + // This doesn't process capturing phase and bubbling phase. + // This isn't participating in a tree. + let prev = null; + while (node != null) { + // Remove this listener if it's once + if (node.once) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + // Call this listener + setPassiveListener( + wrappedEvent, + node.passive ? node.listener : null + ); + if (typeof node.listener === "function") { + try { + node.listener.call(this, wrappedEvent); + } catch (err) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error(err); + } + } + } else if ( + node.listenerType !== ATTRIBUTE && + typeof node.listener.handleEvent === "function" + ) { + node.listener.handleEvent(wrappedEvent); + } + + // Break if `event.stopImmediatePropagation` was called. + if (isStopped(wrappedEvent)) { + break + } + + node = node.next; + } + setPassiveListener(wrappedEvent, null); + setEventPhase(wrappedEvent, 0); + setCurrentTarget(wrappedEvent, null); + + return !wrappedEvent.defaultPrevented + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(EventTarget.prototype, "constructor", { + value: EventTarget, + configurable: true, + writable: true, +}); + +// Ensure `eventTarget instanceof window.EventTarget` is `true`. +if ( + typeof window !== "undefined" && + typeof window.EventTarget !== "undefined" +) { + Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype); +} + +exports.defineEventAttribute = defineEventAttribute; +exports.EventTarget = EventTarget; +exports["default"] = EventTarget; + +module.exports = EventTarget +module.exports.EventTarget = module.exports["default"] = EventTarget +module.exports.defineEventAttribute = defineEventAttribute +//# sourceMappingURL=event-target-shim.js.map + + +/***/ }), + +/***/ 23860: +/***/ ((module) => { + +"use strict"; + + +var hasOwn = Object.prototype.hasOwnProperty; +var toStr = Object.prototype.toString; +var defineProperty = Object.defineProperty; +var gOPD = Object.getOwnPropertyDescriptor; + +var isArray = function isArray(arr) { + if (typeof Array.isArray === 'function') { + return Array.isArray(arr); + } + + return toStr.call(arr) === '[object Array]'; +}; + +var isPlainObject = function isPlainObject(obj) { + if (!obj || toStr.call(obj) !== '[object Object]') { + return false; + } + + var hasOwnConstructor = hasOwn.call(obj, 'constructor'); + var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf'); + // Not own constructor property must be Object + if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + var key; + for (key in obj) { /**/ } + + return typeof key === 'undefined' || hasOwn.call(obj, key); +}; + +// If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target +var setProperty = function setProperty(target, options) { + if (defineProperty && options.name === '__proto__') { + defineProperty(target, options.name, { + enumerable: true, + configurable: true, + value: options.newValue, + writable: true + }); + } else { + target[options.name] = options.newValue; + } +}; + +// Return undefined instead of __proto__ if '__proto__' is not an own property +var getProperty = function getProperty(obj, name) { + if (name === '__proto__') { + if (!hasOwn.call(obj, name)) { + return void 0; + } else if (gOPD) { + // In early versions of node, obj['__proto__'] is buggy when obj has + // __proto__ as an own property. Object.getOwnPropertyDescriptor() works. + return gOPD(obj, name).value; + } + } + + return obj[name]; +}; + +module.exports = function extend() { + var options, name, src, copy, copyIsArray, clone; + var target = arguments[0]; + var i = 1; + var length = arguments.length; + var deep = false; + + // Handle a deep copy situation + if (typeof target === 'boolean') { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + if (target == null || (typeof target !== 'object' && typeof target !== 'function')) { + target = {}; + } + + for (; i < length; ++i) { + options = arguments[i]; + // Only deal with non-null/undefined values + if (options != null) { + // Extend the base object + for (name in options) { + src = getProperty(target, name); + copy = getProperty(options, name); + + // Prevent never-ending loop + if (target !== copy) { + // Recurse if we're merging plain objects or arrays + if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && isArray(src) ? src : []; + } else { + clone = src && isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + setProperty(target, { name: name, newValue: extend(deep, clone, copy) }); + + // Don't bring in undefined values + } else if (typeof copy !== 'undefined') { + setProperty(target, { name: name, newValue: copy }); + } + } + } + } + } + + // Return the modified object + return target; +}; + + +/***/ }), + +/***/ 47506: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GaxiosError = exports.GAXIOS_ERROR_SYMBOL = void 0; +exports.defaultErrorRedactor = defaultErrorRedactor; +const url_1 = __nccwpck_require__(87016); +const util_1 = __nccwpck_require__(63155); +const extend_1 = __importDefault(__nccwpck_require__(23860)); +/** + * Support `instanceof` operator for `GaxiosError`s in different versions of this library. + * + * @see {@link GaxiosError[Symbol.hasInstance]} + */ +exports.GAXIOS_ERROR_SYMBOL = Symbol.for(`${util_1.pkg.name}-gaxios-error`); +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ +class GaxiosError extends Error { + /** + * Support `instanceof` operator for `GaxiosError` across builds/duplicated files. + * + * @see {@link GAXIOS_ERROR_SYMBOL} + * @see {@link GaxiosError[GAXIOS_ERROR_SYMBOL]} + */ + static [(_a = exports.GAXIOS_ERROR_SYMBOL, Symbol.hasInstance)](instance) { + if (instance && + typeof instance === 'object' && + exports.GAXIOS_ERROR_SYMBOL in instance && + instance[exports.GAXIOS_ERROR_SYMBOL] === util_1.pkg.version) { + return true; + } + // fallback to native + return Function.prototype[Symbol.hasInstance].call(GaxiosError, instance); + } + constructor(message, config, response, error) { + var _b; + super(message); + this.config = config; + this.response = response; + this.error = error; + /** + * Support `instanceof` operator for `GaxiosError` across builds/duplicated files. + * + * @see {@link GAXIOS_ERROR_SYMBOL} + * @see {@link GaxiosError[Symbol.hasInstance]} + * @see {@link https://github.com/microsoft/TypeScript/issues/13965#issuecomment-278570200} + * @see {@link https://stackoverflow.com/questions/46618852/require-and-instanceof} + * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/@@hasInstance#reverting_to_default_instanceof_behavior} + */ + this[_a] = util_1.pkg.version; + // deep-copy config as we do not want to mutate + // the existing config for future retries/use + this.config = (0, extend_1.default)(true, {}, config); + if (this.response) { + this.response.config = (0, extend_1.default)(true, {}, this.response.config); + } + if (this.response) { + try { + this.response.data = translateData(this.config.responseType, (_b = this.response) === null || _b === void 0 ? void 0 : _b.data); + } + catch (_c) { + // best effort - don't throw an error within an error + // we could set `this.response.config.responseType = 'unknown'`, but + // that would mutate future calls with this config object. + } + this.status = this.response.status; + } + if (error && 'code' in error && error.code) { + this.code = error.code; + } + if (config.errorRedactor) { + config.errorRedactor({ + config: this.config, + response: this.response, + }); + } + } +} +exports.GaxiosError = GaxiosError; +function translateData(responseType, data) { + switch (responseType) { + case 'stream': + return data; + case 'json': + return JSON.parse(JSON.stringify(data)); + case 'arraybuffer': + return JSON.parse(Buffer.from(data).toString('utf8')); + case 'blob': + return JSON.parse(data.text()); + default: + return data; + } +} +/** + * An experimental error redactor. + * + * @param config Config to potentially redact properties of + * @param response Config to potentially redact properties of + * + * @experimental + */ +function defaultErrorRedactor(data) { + const REDACT = '< - See `errorRedactor` option in `gaxios` for configuration>.'; + function redactHeaders(headers) { + if (!headers) + return; + for (const key of Object.keys(headers)) { + // any casing of `Authentication` + if (/^authentication$/i.test(key)) { + headers[key] = REDACT; + } + // any casing of `Authorization` + if (/^authorization$/i.test(key)) { + headers[key] = REDACT; + } + // anything containing secret, such as 'client secret' + if (/secret/i.test(key)) { + headers[key] = REDACT; + } + } + } + function redactString(obj, key) { + if (typeof obj === 'object' && + obj !== null && + typeof obj[key] === 'string') { + const text = obj[key]; + if (/grant_type=/i.test(text) || + /assertion=/i.test(text) || + /secret/i.test(text)) { + obj[key] = REDACT; + } + } + } + function redactObject(obj) { + if (typeof obj === 'object' && obj !== null) { + if ('grant_type' in obj) { + obj['grant_type'] = REDACT; + } + if ('assertion' in obj) { + obj['assertion'] = REDACT; + } + if ('client_secret' in obj) { + obj['client_secret'] = REDACT; + } + } + } + if (data.config) { + redactHeaders(data.config.headers); + redactString(data.config, 'data'); + redactObject(data.config.data); + redactString(data.config, 'body'); + redactObject(data.config.body); + try { + const url = new url_1.URL('', data.config.url); + if (url.searchParams.has('token')) { + url.searchParams.set('token', REDACT); + } + if (url.searchParams.has('client_secret')) { + url.searchParams.set('client_secret', REDACT); + } + data.config.url = url.toString(); + } + catch (_b) { + // ignore error - no need to parse an invalid URL + } + } + if (data.response) { + defaultErrorRedactor({ config: data.response.config }); + redactHeaders(data.response.headers); + redactString(data.response, 'data'); + redactObject(data.response.data); + } + return data; +} +//# sourceMappingURL=common.js.map + +/***/ }), + +/***/ 6010: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _Gaxios_instances, _a, _Gaxios_urlMayUseProxy, _Gaxios_applyRequestInterceptors, _Gaxios_applyResponseInterceptors, _Gaxios_prepareRequest, _Gaxios_proxyAgent, _Gaxios_getProxyAgent; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Gaxios = void 0; +const extend_1 = __importDefault(__nccwpck_require__(23860)); +const https_1 = __nccwpck_require__(65692); +const node_fetch_1 = __importDefault(__nccwpck_require__(26705)); +const querystring_1 = __importDefault(__nccwpck_require__(83480)); +const is_stream_1 = __importDefault(__nccwpck_require__(96543)); +const url_1 = __nccwpck_require__(87016); +const common_1 = __nccwpck_require__(47506); +const retry_1 = __nccwpck_require__(32789); +const stream_1 = __nccwpck_require__(2203); +const uuid_1 = __nccwpck_require__(12048); +const interceptor_1 = __nccwpck_require__(85608); +/* eslint-disable @typescript-eslint/no-explicit-any */ +const fetch = hasFetch() ? window.fetch : node_fetch_1.default; +function hasWindow() { + return typeof window !== 'undefined' && !!window; +} +function hasFetch() { + return hasWindow() && !!window.fetch; +} +function hasBuffer() { + return typeof Buffer !== 'undefined'; +} +function hasHeader(options, header) { + return !!getHeader(options, header); +} +function getHeader(options, header) { + header = header.toLowerCase(); + for (const key of Object.keys((options === null || options === void 0 ? void 0 : options.headers) || {})) { + if (header === key.toLowerCase()) { + return options.headers[key]; + } + } + return undefined; +} +class Gaxios { + /** + * The Gaxios class is responsible for making HTTP requests. + * @param defaults The default set of options to be used for this instance. + */ + constructor(defaults) { + _Gaxios_instances.add(this); + this.agentCache = new Map(); + this.defaults = defaults || {}; + this.interceptors = { + request: new interceptor_1.GaxiosInterceptorManager(), + response: new interceptor_1.GaxiosInterceptorManager(), + }; + } + /** + * Perform an HTTP request with the given options. + * @param opts Set of HTTP options that will be used for this HTTP request. + */ + async request(opts = {}) { + opts = await __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_prepareRequest).call(this, opts); + opts = await __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_applyRequestInterceptors).call(this, opts); + return __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_applyResponseInterceptors).call(this, this._request(opts)); + } + async _defaultAdapter(opts) { + const fetchImpl = opts.fetchImplementation || fetch; + const res = (await fetchImpl(opts.url, opts)); + const data = await this.getResponseData(opts, res); + return this.translateResponse(opts, res, data); + } + /** + * Internal, retryable version of the `request` method. + * @param opts Set of HTTP options that will be used for this HTTP request. + */ + async _request(opts = {}) { + var _b; + try { + let translatedResponse; + if (opts.adapter) { + translatedResponse = await opts.adapter(opts, this._defaultAdapter.bind(this)); + } + else { + translatedResponse = await this._defaultAdapter(opts); + } + if (!opts.validateStatus(translatedResponse.status)) { + if (opts.responseType === 'stream') { + let response = ''; + await new Promise(resolve => { + (translatedResponse === null || translatedResponse === void 0 ? void 0 : translatedResponse.data).on('data', chunk => { + response += chunk; + }); + (translatedResponse === null || translatedResponse === void 0 ? void 0 : translatedResponse.data).on('end', resolve); + }); + translatedResponse.data = response; + } + throw new common_1.GaxiosError(`Request failed with status code ${translatedResponse.status}`, opts, translatedResponse); + } + return translatedResponse; + } + catch (e) { + const err = e instanceof common_1.GaxiosError + ? e + : new common_1.GaxiosError(e.message, opts, undefined, e); + const { shouldRetry, config } = await (0, retry_1.getRetryConfig)(err); + if (shouldRetry && config) { + err.config.retryConfig.currentRetryAttempt = + config.retryConfig.currentRetryAttempt; + // The error's config could be redacted - therefore we only want to + // copy the retry state over to the existing config + opts.retryConfig = (_b = err.config) === null || _b === void 0 ? void 0 : _b.retryConfig; + return this._request(opts); + } + throw err; + } + } + async getResponseData(opts, res) { + switch (opts.responseType) { + case 'stream': + return res.body; + case 'json': { + let data = await res.text(); + try { + data = JSON.parse(data); + } + catch (_b) { + // continue + } + return data; + } + case 'arraybuffer': + return res.arrayBuffer(); + case 'blob': + return res.blob(); + case 'text': + return res.text(); + default: + return this.getResponseDataFromContentType(res); + } + } + /** + * By default, throw for any non-2xx status code + * @param status status code from the HTTP response + */ + validateStatus(status) { + return status >= 200 && status < 300; + } + /** + * Encode a set of key/value pars into a querystring format (?foo=bar&baz=boo) + * @param params key value pars to encode + */ + paramsSerializer(params) { + return querystring_1.default.stringify(params); + } + translateResponse(opts, res, data) { + // headers need to be converted from a map to an obj + const headers = {}; + res.headers.forEach((value, key) => { + headers[key] = value; + }); + return { + config: opts, + data: data, + headers, + status: res.status, + statusText: res.statusText, + // XMLHttpRequestLike + request: { + responseURL: res.url, + }, + }; + } + /** + * Attempts to parse a response by looking at the Content-Type header. + * @param {FetchResponse} response the HTTP response. + * @returns {Promise} a promise that resolves to the response data. + */ + async getResponseDataFromContentType(response) { + let contentType = response.headers.get('Content-Type'); + if (contentType === null) { + // Maintain existing functionality by calling text() + return response.text(); + } + contentType = contentType.toLowerCase(); + if (contentType.includes('application/json')) { + let data = await response.text(); + try { + data = JSON.parse(data); + } + catch (_b) { + // continue + } + return data; + } + else if (contentType.match(/^text\//)) { + return response.text(); + } + else { + // If the content type is something not easily handled, just return the raw data (blob) + return response.blob(); + } + } + /** + * Creates an async generator that yields the pieces of a multipart/related request body. + * This implementation follows the spec: https://www.ietf.org/rfc/rfc2387.txt. However, recursive + * multipart/related requests are not currently supported. + * + * @param {GaxioMultipartOptions[]} multipartOptions the pieces to turn into a multipart/related body. + * @param {string} boundary the boundary string to be placed between each part. + */ + async *getMultipartRequest(multipartOptions, boundary) { + const finale = `--${boundary}--`; + for (const currentPart of multipartOptions) { + const partContentType = currentPart.headers['Content-Type'] || 'application/octet-stream'; + const preamble = `--${boundary}\r\nContent-Type: ${partContentType}\r\n\r\n`; + yield preamble; + if (typeof currentPart.content === 'string') { + yield currentPart.content; + } + else { + yield* currentPart.content; + } + yield '\r\n'; + } + yield finale; + } +} +exports.Gaxios = Gaxios; +_a = Gaxios, _Gaxios_instances = new WeakSet(), _Gaxios_urlMayUseProxy = function _Gaxios_urlMayUseProxy(url, noProxy = []) { + var _b, _c; + const candidate = new url_1.URL(url); + const noProxyList = [...noProxy]; + const noProxyEnvList = ((_c = ((_b = process.env.NO_PROXY) !== null && _b !== void 0 ? _b : process.env.no_proxy)) === null || _c === void 0 ? void 0 : _c.split(',')) || []; + for (const rule of noProxyEnvList) { + noProxyList.push(rule.trim()); + } + for (const rule of noProxyList) { + // Match regex + if (rule instanceof RegExp) { + if (rule.test(candidate.toString())) { + return false; + } + } + // Match URL + else if (rule instanceof url_1.URL) { + if (rule.origin === candidate.origin) { + return false; + } + } + // Match string regex + else if (rule.startsWith('*.') || rule.startsWith('.')) { + const cleanedRule = rule.replace(/^\*\./, '.'); + if (candidate.hostname.endsWith(cleanedRule)) { + return false; + } + } + // Basic string match + else if (rule === candidate.origin || + rule === candidate.hostname || + rule === candidate.href) { + return false; + } + } + return true; +}, _Gaxios_applyRequestInterceptors = +/** + * Applies the request interceptors. The request interceptors are applied after the + * call to prepareRequest is completed. + * + * @param {GaxiosOptions} options The current set of options. + * + * @returns {Promise} Promise that resolves to the set of options or response after interceptors are applied. + */ +async function _Gaxios_applyRequestInterceptors(options) { + let promiseChain = Promise.resolve(options); + for (const interceptor of this.interceptors.request.values()) { + if (interceptor) { + promiseChain = promiseChain.then(interceptor.resolved, interceptor.rejected); + } + } + return promiseChain; +}, _Gaxios_applyResponseInterceptors = +/** + * Applies the response interceptors. The response interceptors are applied after the + * call to request is made. + * + * @param {GaxiosOptions} options The current set of options. + * + * @returns {Promise} Promise that resolves to the set of options or response after interceptors are applied. + */ +async function _Gaxios_applyResponseInterceptors(response) { + let promiseChain = Promise.resolve(response); + for (const interceptor of this.interceptors.response.values()) { + if (interceptor) { + promiseChain = promiseChain.then(interceptor.resolved, interceptor.rejected); + } + } + return promiseChain; +}, _Gaxios_prepareRequest = +/** + * Validates the options, merges them with defaults, and prepare request. + * + * @param options The original options passed from the client. + * @returns Prepared options, ready to make a request + */ +async function _Gaxios_prepareRequest(options) { + var _b, _c, _d, _e; + const opts = (0, extend_1.default)(true, {}, this.defaults, options); + if (!opts.url) { + throw new Error('URL is required.'); + } + // baseUrl has been deprecated, remove in 2.0 + const baseUrl = opts.baseUrl || opts.baseURL; + if (baseUrl) { + opts.url = baseUrl.toString() + opts.url; + } + opts.paramsSerializer = opts.paramsSerializer || this.paramsSerializer; + if (opts.params && Object.keys(opts.params).length > 0) { + let additionalQueryParams = opts.paramsSerializer(opts.params); + if (additionalQueryParams.startsWith('?')) { + additionalQueryParams = additionalQueryParams.slice(1); + } + const prefix = opts.url.toString().includes('?') ? '&' : '?'; + opts.url = opts.url + prefix + additionalQueryParams; + } + if (typeof options.maxContentLength === 'number') { + opts.size = options.maxContentLength; + } + if (typeof options.maxRedirects === 'number') { + opts.follow = options.maxRedirects; + } + opts.headers = opts.headers || {}; + if (opts.multipart === undefined && opts.data) { + const isFormData = typeof FormData === 'undefined' + ? false + : (opts === null || opts === void 0 ? void 0 : opts.data) instanceof FormData; + if (is_stream_1.default.readable(opts.data)) { + opts.body = opts.data; + } + else if (hasBuffer() && Buffer.isBuffer(opts.data)) { + // Do not attempt to JSON.stringify() a Buffer: + opts.body = opts.data; + if (!hasHeader(opts, 'Content-Type')) { + opts.headers['Content-Type'] = 'application/json'; + } + } + else if (typeof opts.data === 'object') { + // If www-form-urlencoded content type has been set, but data is + // provided as an object, serialize the content using querystring: + if (!isFormData) { + if (getHeader(opts, 'content-type') === + 'application/x-www-form-urlencoded') { + opts.body = opts.paramsSerializer(opts.data); + } + else { + // } else if (!(opts.data instanceof FormData)) { + if (!hasHeader(opts, 'Content-Type')) { + opts.headers['Content-Type'] = 'application/json'; + } + opts.body = JSON.stringify(opts.data); + } + } + } + else { + opts.body = opts.data; + } + } + else if (opts.multipart && opts.multipart.length > 0) { + // note: once the minimum version reaches Node 16, + // this can be replaced with randomUUID() function from crypto + // and the dependency on UUID removed + const boundary = (0, uuid_1.v4)(); + opts.headers['Content-Type'] = `multipart/related; boundary=${boundary}`; + const bodyStream = new stream_1.PassThrough(); + opts.body = bodyStream; + (0, stream_1.pipeline)(this.getMultipartRequest(opts.multipart, boundary), bodyStream, () => { }); + } + opts.validateStatus = opts.validateStatus || this.validateStatus; + opts.responseType = opts.responseType || 'unknown'; + if (!opts.headers['Accept'] && opts.responseType === 'json') { + opts.headers['Accept'] = 'application/json'; + } + opts.method = opts.method || 'GET'; + const proxy = opts.proxy || + ((_b = process === null || process === void 0 ? void 0 : process.env) === null || _b === void 0 ? void 0 : _b.HTTPS_PROXY) || + ((_c = process === null || process === void 0 ? void 0 : process.env) === null || _c === void 0 ? void 0 : _c.https_proxy) || + ((_d = process === null || process === void 0 ? void 0 : process.env) === null || _d === void 0 ? void 0 : _d.HTTP_PROXY) || + ((_e = process === null || process === void 0 ? void 0 : process.env) === null || _e === void 0 ? void 0 : _e.http_proxy); + const urlMayUseProxy = __classPrivateFieldGet(this, _Gaxios_instances, "m", _Gaxios_urlMayUseProxy).call(this, opts.url, opts.noProxy); + if (opts.agent) { + // don't do any of the following options - use the user-provided agent. + } + else if (proxy && urlMayUseProxy) { + const HttpsProxyAgent = await __classPrivateFieldGet(_a, _a, "m", _Gaxios_getProxyAgent).call(_a); + if (this.agentCache.has(proxy)) { + opts.agent = this.agentCache.get(proxy); + } + else { + opts.agent = new HttpsProxyAgent(proxy, { + cert: opts.cert, + key: opts.key, + }); + this.agentCache.set(proxy, opts.agent); + } + } + else if (opts.cert && opts.key) { + // Configure client for mTLS + if (this.agentCache.has(opts.key)) { + opts.agent = this.agentCache.get(opts.key); + } + else { + opts.agent = new https_1.Agent({ + cert: opts.cert, + key: opts.key, + }); + this.agentCache.set(opts.key, opts.agent); + } + } + if (typeof opts.errorRedactor !== 'function' && + opts.errorRedactor !== false) { + opts.errorRedactor = common_1.defaultErrorRedactor; + } + return opts; +}, _Gaxios_getProxyAgent = async function _Gaxios_getProxyAgent() { + __classPrivateFieldSet(this, _a, __classPrivateFieldGet(this, _a, "f", _Gaxios_proxyAgent) || (await Promise.resolve().then(() => __importStar(__nccwpck_require__(3669)))).HttpsProxyAgent, "f", _Gaxios_proxyAgent); + return __classPrivateFieldGet(this, _a, "f", _Gaxios_proxyAgent); +}; +/** + * A cache for the lazily-loaded proxy agent. + * + * Should use {@link Gaxios[#getProxyAgent]} to retrieve. + */ +// using `import` to dynamically import the types here +_Gaxios_proxyAgent = { value: void 0 }; +//# sourceMappingURL=gaxios.js.map + +/***/ }), + +/***/ 97003: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.instance = exports.Gaxios = exports.GaxiosError = void 0; +exports.request = request; +const gaxios_1 = __nccwpck_require__(6010); +Object.defineProperty(exports, "Gaxios", ({ enumerable: true, get: function () { return gaxios_1.Gaxios; } })); +var common_1 = __nccwpck_require__(47506); +Object.defineProperty(exports, "GaxiosError", ({ enumerable: true, get: function () { return common_1.GaxiosError; } })); +__exportStar(__nccwpck_require__(85608), exports); +/** + * The default instance used when the `request` method is directly + * invoked. + */ +exports.instance = new gaxios_1.Gaxios(); +/** + * Make an HTTP request using the given options. + * @param opts Options for the request + */ +async function request(opts) { + return exports.instance.request(opts); +} +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 85608: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2024 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GaxiosInterceptorManager = void 0; +/** + * Class to manage collections of GaxiosInterceptors for both requests and responses. + */ +class GaxiosInterceptorManager extends Set { +} +exports.GaxiosInterceptorManager = GaxiosInterceptorManager; +//# sourceMappingURL=interceptor.js.map + +/***/ }), + +/***/ 32789: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2018 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRetryConfig = getRetryConfig; +async function getRetryConfig(err) { + let config = getConfig(err); + if (!err || !err.config || (!config && !err.config.retry)) { + return { shouldRetry: false }; + } + config = config || {}; + config.currentRetryAttempt = config.currentRetryAttempt || 0; + config.retry = + config.retry === undefined || config.retry === null ? 3 : config.retry; + config.httpMethodsToRetry = config.httpMethodsToRetry || [ + 'GET', + 'HEAD', + 'PUT', + 'OPTIONS', + 'DELETE', + ]; + config.noResponseRetries = + config.noResponseRetries === undefined || config.noResponseRetries === null + ? 2 + : config.noResponseRetries; + config.retryDelayMultiplier = config.retryDelayMultiplier + ? config.retryDelayMultiplier + : 2; + config.timeOfFirstRequest = config.timeOfFirstRequest + ? config.timeOfFirstRequest + : Date.now(); + config.totalTimeout = config.totalTimeout + ? config.totalTimeout + : Number.MAX_SAFE_INTEGER; + config.maxRetryDelay = config.maxRetryDelay + ? config.maxRetryDelay + : Number.MAX_SAFE_INTEGER; + // If this wasn't in the list of status codes where we want + // to automatically retry, return. + const retryRanges = [ + // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + // 1xx - Retry (Informational, request still processing) + // 2xx - Do not retry (Success) + // 3xx - Do not retry (Redirect) + // 4xx - Do not retry (Client errors) + // 408 - Retry ("Request Timeout") + // 429 - Retry ("Too Many Requests") + // 5xx - Retry (Server errors) + [100, 199], + [408, 408], + [429, 429], + [500, 599], + ]; + config.statusCodesToRetry = config.statusCodesToRetry || retryRanges; + // Put the config back into the err + err.config.retryConfig = config; + // Determine if we should retry the request + const shouldRetryFn = config.shouldRetry || shouldRetryRequest; + if (!(await shouldRetryFn(err))) { + return { shouldRetry: false, config: err.config }; + } + const delay = getNextRetryDelay(config); + // We're going to retry! Incremenent the counter. + err.config.retryConfig.currentRetryAttempt += 1; + // Create a promise that invokes the retry after the backOffDelay + const backoff = config.retryBackoff + ? config.retryBackoff(err, delay) + : new Promise(resolve => { + setTimeout(resolve, delay); + }); + // Notify the user if they added an `onRetryAttempt` handler + if (config.onRetryAttempt) { + config.onRetryAttempt(err); + } + // Return the promise in which recalls Gaxios to retry the request + await backoff; + return { shouldRetry: true, config: err.config }; +} +/** + * Determine based on config if we should retry the request. + * @param err The GaxiosError passed to the interceptor. + */ +function shouldRetryRequest(err) { + var _a; + const config = getConfig(err); + // node-fetch raises an AbortError if signaled: + // https://github.com/bitinn/node-fetch#request-cancellation-with-abortsignal + if (err.name === 'AbortError' || ((_a = err.error) === null || _a === void 0 ? void 0 : _a.name) === 'AbortError') { + return false; + } + // If there's no config, or retries are disabled, return. + if (!config || config.retry === 0) { + return false; + } + // Check if this error has no response (ETIMEDOUT, ENOTFOUND, etc) + if (!err.response && + (config.currentRetryAttempt || 0) >= config.noResponseRetries) { + return false; + } + // Only retry with configured HttpMethods. + if (!err.config.method || + config.httpMethodsToRetry.indexOf(err.config.method.toUpperCase()) < 0) { + return false; + } + // If this wasn't in the list of status codes where we want + // to automatically retry, return. + if (err.response && err.response.status) { + let isInRange = false; + for (const [min, max] of config.statusCodesToRetry) { + const status = err.response.status; + if (status >= min && status <= max) { + isInRange = true; + break; + } + } + if (!isInRange) { + return false; + } + } + // If we are out of retry attempts, return + config.currentRetryAttempt = config.currentRetryAttempt || 0; + if (config.currentRetryAttempt >= config.retry) { + return false; + } + return true; +} +/** + * Acquire the raxConfig object from an GaxiosError if available. + * @param err The Gaxios error with a config object. + */ +function getConfig(err) { + if (err && err.config && err.config.retryConfig) { + return err.config.retryConfig; + } + return; +} +/** + * Gets the delay to wait before the next retry. + * + * @param {RetryConfig} config The current set of retry options + * @returns {number} the amount of ms to wait before the next retry attempt. + */ +function getNextRetryDelay(config) { + var _a; + // Calculate time to wait with exponential backoff. + // If this is the first retry, look for a configured retryDelay. + const retryDelay = config.currentRetryAttempt ? 0 : (_a = config.retryDelay) !== null && _a !== void 0 ? _a : 100; + // Formula: retryDelay + ((retryDelayMultiplier^currentRetryAttempt - 1 / 2) * 1000) + const calculatedDelay = retryDelay + + ((Math.pow(config.retryDelayMultiplier, config.currentRetryAttempt) - 1) / + 2) * + 1000; + const maxAllowableDelay = config.totalTimeout - (Date.now() - config.timeOfFirstRequest); + return Math.min(calculatedDelay, maxAllowableDelay, config.maxRetryDelay); +} +//# sourceMappingURL=retry.js.map + +/***/ }), + +/***/ 63155: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2023 Google LLC +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.pkg = void 0; +exports.pkg = __nccwpck_require__(66495); +//# sourceMappingURL=util.js.map + +/***/ }), + +/***/ 70381: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GCE_LINUX_BIOS_PATHS = void 0; +exports.isGoogleCloudServerless = isGoogleCloudServerless; +exports.isGoogleComputeEngineLinux = isGoogleComputeEngineLinux; +exports.isGoogleComputeEngineMACAddress = isGoogleComputeEngineMACAddress; +exports.isGoogleComputeEngine = isGoogleComputeEngine; +exports.detectGCPResidency = detectGCPResidency; +const fs_1 = __nccwpck_require__(79896); +const os_1 = __nccwpck_require__(70857); +/** + * Known paths unique to Google Compute Engine Linux instances + */ +exports.GCE_LINUX_BIOS_PATHS = { + BIOS_DATE: '/sys/class/dmi/id/bios_date', + BIOS_VENDOR: '/sys/class/dmi/id/bios_vendor', +}; +const GCE_MAC_ADDRESS_REGEX = /^42:01/; +/** + * Determines if the process is running on a Google Cloud Serverless environment (Cloud Run or Cloud Functions instance). + * + * Uses the: + * - {@link https://cloud.google.com/run/docs/container-contract#env-vars Cloud Run environment variables}. + * - {@link https://cloud.google.com/functions/docs/env-var Cloud Functions environment variables}. + * + * @returns {boolean} `true` if the process is running on GCP serverless, `false` otherwise. + */ +function isGoogleCloudServerless() { + /** + * `CLOUD_RUN_JOB` is used for Cloud Run Jobs + * - See {@link https://cloud.google.com/run/docs/container-contract#env-vars Cloud Run environment variables}. + * + * `FUNCTION_NAME` is used in older Cloud Functions environments: + * - See {@link https://cloud.google.com/functions/docs/env-var Python 3.7 and Go 1.11}. + * + * `K_SERVICE` is used in Cloud Run and newer Cloud Functions environments: + * - See {@link https://cloud.google.com/run/docs/container-contract#env-vars Cloud Run environment variables}. + * - See {@link https://cloud.google.com/functions/docs/env-var Cloud Functions newer runtimes}. + */ + const isGFEnvironment = process.env.CLOUD_RUN_JOB || + process.env.FUNCTION_NAME || + process.env.K_SERVICE; + return !!isGFEnvironment; +} +/** + * Determines if the process is running on a Linux Google Compute Engine instance. + * + * @returns {boolean} `true` if the process is running on Linux GCE, `false` otherwise. + */ +function isGoogleComputeEngineLinux() { + if ((0, os_1.platform)() !== 'linux') + return false; + try { + // ensure this file exist + (0, fs_1.statSync)(exports.GCE_LINUX_BIOS_PATHS.BIOS_DATE); + // ensure this file exist and matches + const biosVendor = (0, fs_1.readFileSync)(exports.GCE_LINUX_BIOS_PATHS.BIOS_VENDOR, 'utf8'); + return /Google/.test(biosVendor); + } + catch (_a) { + return false; + } +} +/** + * Determines if the process is running on a Google Compute Engine instance with a known + * MAC address. + * + * @returns {boolean} `true` if the process is running on GCE (as determined by MAC address), `false` otherwise. + */ +function isGoogleComputeEngineMACAddress() { + const interfaces = (0, os_1.networkInterfaces)(); + for (const item of Object.values(interfaces)) { + if (!item) + continue; + for (const { mac } of item) { + if (GCE_MAC_ADDRESS_REGEX.test(mac)) { + return true; + } + } + } + return false; +} +/** + * Determines if the process is running on a Google Compute Engine instance. + * + * @returns {boolean} `true` if the process is running on GCE, `false` otherwise. + */ +function isGoogleComputeEngine() { + return isGoogleComputeEngineLinux() || isGoogleComputeEngineMACAddress(); +} +/** + * Determines if the process is running on Google Cloud Platform. + * + * @returns {boolean} `true` if the process is running on GCP, `false` otherwise. + */ +function detectGCPResidency() { + return isGoogleCloudServerless() || isGoogleComputeEngine(); +} +//# sourceMappingURL=gcp-residency.js.map + +/***/ }), + +/***/ 23046: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/** + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.gcpResidencyCache = exports.METADATA_SERVER_DETECTION = exports.HEADERS = exports.HEADER_VALUE = exports.HEADER_NAME = exports.SECONDARY_HOST_ADDRESS = exports.HOST_ADDRESS = exports.BASE_PATH = void 0; +exports.instance = instance; +exports.project = project; +exports.universe = universe; +exports.bulk = bulk; +exports.isAvailable = isAvailable; +exports.resetIsAvailableCache = resetIsAvailableCache; +exports.getGCPResidency = getGCPResidency; +exports.setGCPResidency = setGCPResidency; +exports.requestTimeout = requestTimeout; +const gaxios_1 = __nccwpck_require__(97003); +const jsonBigint = __nccwpck_require__(14826); +const gcp_residency_1 = __nccwpck_require__(70381); +const logger = __nccwpck_require__(81577); +exports.BASE_PATH = '/computeMetadata/v1'; +exports.HOST_ADDRESS = 'http://169.254.169.254'; +exports.SECONDARY_HOST_ADDRESS = 'http://metadata.google.internal.'; +exports.HEADER_NAME = 'Metadata-Flavor'; +exports.HEADER_VALUE = 'Google'; +exports.HEADERS = Object.freeze({ [exports.HEADER_NAME]: exports.HEADER_VALUE }); +const log = logger.log('gcp metadata'); +/** + * Metadata server detection override options. + * + * Available via `process.env.METADATA_SERVER_DETECTION`. + */ +exports.METADATA_SERVER_DETECTION = Object.freeze({ + 'assume-present': "don't try to ping the metadata server, but assume it's present", + none: "don't try to ping the metadata server, but don't try to use it either", + 'bios-only': "treat the result of a BIOS probe as canonical (don't fall back to pinging)", + 'ping-only': 'skip the BIOS probe, and go straight to pinging', +}); +/** + * Returns the base URL while taking into account the GCE_METADATA_HOST + * environment variable if it exists. + * + * @returns The base URL, e.g., http://169.254.169.254/computeMetadata/v1. + */ +function getBaseUrl(baseUrl) { + if (!baseUrl) { + baseUrl = + process.env.GCE_METADATA_IP || + process.env.GCE_METADATA_HOST || + exports.HOST_ADDRESS; + } + // If no scheme is provided default to HTTP: + if (!/^https?:\/\//.test(baseUrl)) { + baseUrl = `http://${baseUrl}`; + } + return new URL(exports.BASE_PATH, baseUrl).href; +} +// Accepts an options object passed from the user to the API. In previous +// versions of the API, it referred to a `Request` or an `Axios` request +// options object. Now it refers to an object with very limited property +// names. This is here to help ensure users don't pass invalid options when +// they upgrade from 0.4 to 0.5 to 0.8. +function validate(options) { + Object.keys(options).forEach(key => { + switch (key) { + case 'params': + case 'property': + case 'headers': + break; + case 'qs': + throw new Error("'qs' is not a valid configuration option. Please use 'params' instead."); + default: + throw new Error(`'${key}' is not a valid configuration option.`); + } + }); +} +async function metadataAccessor(type, options = {}, noResponseRetries = 3, fastFail = false) { + let metadataKey = ''; + let params = {}; + let headers = {}; + if (typeof type === 'object') { + const metadataAccessor = type; + metadataKey = metadataAccessor.metadataKey; + params = metadataAccessor.params || params; + headers = metadataAccessor.headers || headers; + noResponseRetries = metadataAccessor.noResponseRetries || noResponseRetries; + fastFail = metadataAccessor.fastFail || fastFail; + } + else { + metadataKey = type; + } + if (typeof options === 'string') { + metadataKey += `/${options}`; + } + else { + validate(options); + if (options.property) { + metadataKey += `/${options.property}`; + } + headers = options.headers || headers; + params = options.params || params; + } + const requestMethod = fastFail ? fastFailMetadataRequest : gaxios_1.request; + const req = { + url: `${getBaseUrl()}/${metadataKey}`, + headers: { ...exports.HEADERS, ...headers }, + retryConfig: { noResponseRetries }, + params, + responseType: 'text', + timeout: requestTimeout(), + }; + log.info('instance request %j', req); + const res = await requestMethod(req); + log.info('instance metadata is %s', res.data); + // NOTE: node.js converts all incoming headers to lower case. + if (res.headers[exports.HEADER_NAME.toLowerCase()] !== exports.HEADER_VALUE) { + throw new Error(`Invalid response from metadata service: incorrect ${exports.HEADER_NAME} header. Expected '${exports.HEADER_VALUE}', got ${res.headers[exports.HEADER_NAME.toLowerCase()] ? `'${res.headers[exports.HEADER_NAME.toLowerCase()]}'` : 'no header'}`); + } + if (typeof res.data === 'string') { + try { + return jsonBigint.parse(res.data); + } + catch (_a) { + /* ignore */ + } + } + return res.data; +} +async function fastFailMetadataRequest(options) { + var _a; + const secondaryOptions = { + ...options, + url: (_a = options.url) === null || _a === void 0 ? void 0 : _a.toString().replace(getBaseUrl(), getBaseUrl(exports.SECONDARY_HOST_ADDRESS)), + }; + // We race a connection between DNS/IP to metadata server. There are a couple + // reasons for this: + // + // 1. the DNS is slow in some GCP environments; by checking both, we might + // detect the runtime environment signficantly faster. + // 2. we can't just check the IP, which is tarpitted and slow to respond + // on a user's local machine. + // + // Additional logic has been added to make sure that we don't create an + // unhandled rejection in scenarios where a failure happens sometime + // after a success. + // + // Note, however, if a failure happens prior to a success, a rejection should + // occur, this is for folks running locally. + // + let responded = false; + const r1 = (0, gaxios_1.request)(options) + .then(res => { + responded = true; + return res; + }) + .catch(err => { + if (responded) { + return r2; + } + else { + responded = true; + throw err; + } + }); + const r2 = (0, gaxios_1.request)(secondaryOptions) + .then(res => { + responded = true; + return res; + }) + .catch(err => { + if (responded) { + return r1; + } + else { + responded = true; + throw err; + } + }); + return Promise.race([r1, r2]); +} +/** + * Obtain metadata for the current GCE instance. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const serviceAccount: {} = await instance('service-accounts/'); + * const serviceAccountEmail: string = await instance('service-accounts/default/email'); + * ``` + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function instance(options) { + return metadataAccessor('instance', options); +} +/** + * Obtain metadata for the current GCP project. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const projectId: string = await project('project-id'); + * const numericProjectId: number = await project('numeric-project-id'); + * ``` + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function project(options) { + return metadataAccessor('project', options); +} +/** + * Obtain metadata for the current universe. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const universeDomain: string = await universe('universe-domain'); + * ``` + */ +function universe(options) { + return metadataAccessor('universe', options); +} +/** + * Retrieve metadata items in parallel. + * + * @see {@link https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys} + * + * @example + * ``` + * const data = await bulk([ + * { + * metadataKey: 'instance', + * }, + * { + * metadataKey: 'project/project-id', + * }, + * ] as const); + * + * // data.instance; + * // data['project/project-id']; + * ``` + * + * @param properties The metadata properties to retrieve + * @returns The metadata in `metadatakey:value` format + */ +async function bulk(properties) { + const r = {}; + await Promise.all(properties.map(item => { + return (async () => { + const res = await metadataAccessor(item); + const key = item.metadataKey; + r[key] = res; + })(); + })); + return r; +} +/* + * How many times should we retry detecting GCP environment. + */ +function detectGCPAvailableRetries() { + return process.env.DETECT_GCP_RETRIES + ? Number(process.env.DETECT_GCP_RETRIES) + : 0; +} +let cachedIsAvailableResponse; +/** + * Determine if the metadata server is currently available. + */ +async function isAvailable() { + if (process.env.METADATA_SERVER_DETECTION) { + const value = process.env.METADATA_SERVER_DETECTION.trim().toLocaleLowerCase(); + if (!(value in exports.METADATA_SERVER_DETECTION)) { + throw new RangeError(`Unknown \`METADATA_SERVER_DETECTION\` env variable. Got \`${value}\`, but it should be \`${Object.keys(exports.METADATA_SERVER_DETECTION).join('`, `')}\`, or unset`); + } + switch (value) { + case 'assume-present': + return true; + case 'none': + return false; + case 'bios-only': + return getGCPResidency(); + case 'ping-only': + // continue, we want to ping the server + } + } + try { + // If a user is instantiating several GCP libraries at the same time, + // this may result in multiple calls to isAvailable(), to detect the + // runtime environment. We use the same promise for each of these calls + // to reduce the network load. + if (cachedIsAvailableResponse === undefined) { + cachedIsAvailableResponse = metadataAccessor('instance', undefined, detectGCPAvailableRetries(), + // If the default HOST_ADDRESS has been overridden, we should not + // make an effort to try SECONDARY_HOST_ADDRESS (as we are likely in + // a non-GCP environment): + !(process.env.GCE_METADATA_IP || process.env.GCE_METADATA_HOST)); + } + await cachedIsAvailableResponse; + return true; + } + catch (e) { + const err = e; + if (process.env.DEBUG_AUTH) { + console.info(err); + } + if (err.type === 'request-timeout') { + // If running in a GCP environment, metadata endpoint should return + // within ms. + return false; + } + if (err.response && err.response.status === 404) { + return false; + } + else { + if (!(err.response && err.response.status === 404) && + // A warning is emitted if we see an unexpected err.code, or err.code + // is not populated: + (!err.code || + ![ + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'ENETUNREACH', + 'ENOENT', + 'ENOTFOUND', + 'ECONNREFUSED', + ].includes(err.code))) { + let code = 'UNKNOWN'; + if (err.code) + code = err.code; + process.emitWarning(`received unexpected error = ${err.message} code = ${code}`, 'MetadataLookupWarning'); + } + // Failure to resolve the metadata service means that it is not available. + return false; + } + } +} +/** + * reset the memoized isAvailable() lookup. + */ +function resetIsAvailableCache() { + cachedIsAvailableResponse = undefined; +} +/** + * A cache for the detected GCP Residency. + */ +exports.gcpResidencyCache = null; +/** + * Detects GCP Residency. + * Caches results to reduce costs for subsequent calls. + * + * @see setGCPResidency for setting + */ +function getGCPResidency() { + if (exports.gcpResidencyCache === null) { + setGCPResidency(); + } + return exports.gcpResidencyCache; +} +/** + * Sets the detected GCP Residency. + * Useful for forcing metadata server detection behavior. + * + * Set `null` to autodetect the environment (default behavior). + * @see getGCPResidency for getting + */ +function setGCPResidency(value = null) { + exports.gcpResidencyCache = value !== null ? value : (0, gcp_residency_1.detectGCPResidency)(); +} +/** + * Obtain the timeout for requests to the metadata server. + * + * In certain environments and conditions requests can take longer than + * the default timeout to complete. This function will determine the + * appropriate timeout based on the environment. + * + * @returns {number} a request timeout duration in milliseconds. + */ +function requestTimeout() { + return getGCPResidency() ? 0 : 3000; +} +__exportStar(__nccwpck_require__(70381), exports); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 34810: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2012 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AuthClient = exports.DEFAULT_EAGER_REFRESH_THRESHOLD_MILLIS = exports.DEFAULT_UNIVERSE = void 0; +const events_1 = __nccwpck_require__(24434); +const gaxios_1 = __nccwpck_require__(97003); +const transporters_1 = __nccwpck_require__(67633); +const util_1 = __nccwpck_require__(37870); +/** + * The default cloud universe + * + * @see {@link AuthJSONOptions.universe_domain} + */ +exports.DEFAULT_UNIVERSE = 'googleapis.com'; +/** + * The default {@link AuthClientOptions.eagerRefreshThresholdMillis} + */ +exports.DEFAULT_EAGER_REFRESH_THRESHOLD_MILLIS = 5 * 60 * 1000; +class AuthClient extends events_1.EventEmitter { + constructor(opts = {}) { + var _a, _b, _c, _d, _e; + super(); + this.credentials = {}; + this.eagerRefreshThresholdMillis = exports.DEFAULT_EAGER_REFRESH_THRESHOLD_MILLIS; + this.forceRefreshOnFailure = false; + this.universeDomain = exports.DEFAULT_UNIVERSE; + const options = (0, util_1.originalOrCamelOptions)(opts); + // Shared auth options + this.apiKey = opts.apiKey; + this.projectId = (_a = options.get('project_id')) !== null && _a !== void 0 ? _a : null; + this.quotaProjectId = options.get('quota_project_id'); + this.credentials = (_b = options.get('credentials')) !== null && _b !== void 0 ? _b : {}; + this.universeDomain = (_c = options.get('universe_domain')) !== null && _c !== void 0 ? _c : exports.DEFAULT_UNIVERSE; + // Shared client options + this.transporter = (_d = opts.transporter) !== null && _d !== void 0 ? _d : new transporters_1.DefaultTransporter(); + if (opts.transporterOptions) { + this.transporter.defaults = opts.transporterOptions; + } + if (opts.eagerRefreshThresholdMillis) { + this.eagerRefreshThresholdMillis = opts.eagerRefreshThresholdMillis; + } + this.forceRefreshOnFailure = (_e = opts.forceRefreshOnFailure) !== null && _e !== void 0 ? _e : false; + } + /** + * Return the {@link Gaxios `Gaxios`} instance from the {@link AuthClient.transporter}. + * + * @expiremental + */ + get gaxios() { + if (this.transporter instanceof gaxios_1.Gaxios) { + return this.transporter; + } + else if (this.transporter instanceof transporters_1.DefaultTransporter) { + return this.transporter.instance; + } + else if ('instance' in this.transporter && + this.transporter.instance instanceof gaxios_1.Gaxios) { + return this.transporter.instance; + } + return null; + } + /** + * Sets the auth credentials. + */ + setCredentials(credentials) { + this.credentials = credentials; + } + /** + * Append additional headers, e.g., x-goog-user-project, shared across the + * classes inheriting AuthClient. This method should be used by any method + * that overrides getRequestMetadataAsync(), which is a shared helper for + * setting request information in both gRPC and HTTP API calls. + * + * @param headers object to append additional headers to. + */ + addSharedMetadataHeaders(headers) { + // quota_project_id, stored in application_default_credentials.json, is set in + // the x-goog-user-project header, to indicate an alternate account for + // billing and quota: + if (!headers['x-goog-user-project'] && // don't override a value the user sets. + this.quotaProjectId) { + headers['x-goog-user-project'] = this.quotaProjectId; + } + return headers; + } + /** + * Retry config for Auth-related requests. + * + * @remarks + * + * This is not a part of the default {@link AuthClient.transporter transporter/gaxios} + * config as some downstream APIs would prefer if customers explicitly enable retries, + * such as GCS. + */ + static get RETRY_CONFIG() { + return { + retry: true, + retryConfig: { + httpMethodsToRetry: ['GET', 'PUT', 'POST', 'HEAD', 'OPTIONS', 'DELETE'], + }, + }; + } +} +exports.AuthClient = AuthClient; + + +/***/ }), + +/***/ 81261: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _a, _AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsClient = void 0; +const awsrequestsigner_1 = __nccwpck_require__(27647); +const baseexternalclient_1 = __nccwpck_require__(142); +const defaultawssecuritycredentialssupplier_1 = __nccwpck_require__(69157); +const util_1 = __nccwpck_require__(37870); +/** + * AWS external account client. This is used for AWS workloads, where + * AWS STS GetCallerIdentity serialized signed requests are exchanged for + * GCP access token. + */ +class AwsClient extends baseexternalclient_1.BaseExternalAccountClient { + /** + * Instantiates an AwsClient instance using the provided JSON + * object loaded from an external account credentials file. + * An error is thrown if the credential is not a valid AWS credential. + * @param options The external account options object typically loaded + * from the external account JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + super(options, additionalOptions); + const opts = (0, util_1.originalOrCamelOptions)(options); + const credentialSource = opts.get('credential_source'); + const awsSecurityCredentialsSupplier = opts.get('aws_security_credentials_supplier'); + // Validate credential sourcing configuration. + if (!credentialSource && !awsSecurityCredentialsSupplier) { + throw new Error('A credential source or AWS security credentials supplier must be specified.'); + } + if (credentialSource && awsSecurityCredentialsSupplier) { + throw new Error('Only one of credential source or AWS security credentials supplier can be specified.'); + } + if (awsSecurityCredentialsSupplier) { + this.awsSecurityCredentialsSupplier = awsSecurityCredentialsSupplier; + this.regionalCredVerificationUrl = + __classPrivateFieldGet(_a, _a, "f", _AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL); + this.credentialSourceType = 'programmatic'; + } + else { + const credentialSourceOpts = (0, util_1.originalOrCamelOptions)(credentialSource); + this.environmentId = credentialSourceOpts.get('environment_id'); + // This is only required if the AWS region is not available in the + // AWS_REGION or AWS_DEFAULT_REGION environment variables. + const regionUrl = credentialSourceOpts.get('region_url'); + // This is only required if AWS security credentials are not available in + // environment variables. + const securityCredentialsUrl = credentialSourceOpts.get('url'); + const imdsV2SessionTokenUrl = credentialSourceOpts.get('imdsv2_session_token_url'); + this.awsSecurityCredentialsSupplier = + new defaultawssecuritycredentialssupplier_1.DefaultAwsSecurityCredentialsSupplier({ + regionUrl: regionUrl, + securityCredentialsUrl: securityCredentialsUrl, + imdsV2SessionTokenUrl: imdsV2SessionTokenUrl, + }); + this.regionalCredVerificationUrl = credentialSourceOpts.get('regional_cred_verification_url'); + this.credentialSourceType = 'aws'; + // Data validators. + this.validateEnvironmentId(); + } + this.awsRequestSigner = null; + this.region = ''; + } + validateEnvironmentId() { + var _b; + const match = (_b = this.environmentId) === null || _b === void 0 ? void 0 : _b.match(/^(aws)(\d+)$/); + if (!match || !this.regionalCredVerificationUrl) { + throw new Error('No valid AWS "credential_source" provided'); + } + else if (parseInt(match[2], 10) !== 1) { + throw new Error(`aws version "${match[2]}" is not supported in the current build.`); + } + } + /** + * Triggered when an external subject token is needed to be exchanged for a + * GCP access token via GCP STS endpoint. This will call the + * {@link AwsSecurityCredentialsSupplier} to retrieve an AWS region and AWS + * Security Credentials, then use them to create a signed AWS STS request that + * can be exchanged for a GCP access token. + * @return A promise that resolves with the external subject token. + */ + async retrieveSubjectToken() { + // Initialize AWS request signer if not already initialized. + if (!this.awsRequestSigner) { + this.region = await this.awsSecurityCredentialsSupplier.getAwsRegion(this.supplierContext); + this.awsRequestSigner = new awsrequestsigner_1.AwsRequestSigner(async () => { + return this.awsSecurityCredentialsSupplier.getAwsSecurityCredentials(this.supplierContext); + }, this.region); + } + // Generate signed request to AWS STS GetCallerIdentity API. + // Use the required regional endpoint. Otherwise, the request will fail. + const options = await this.awsRequestSigner.getRequestOptions({ + ..._a.RETRY_CONFIG, + url: this.regionalCredVerificationUrl.replace('{region}', this.region), + method: 'POST', + }); + // The GCP STS endpoint expects the headers to be formatted as: + // [ + // {key: 'x-amz-date', value: '...'}, + // {key: 'Authorization', value: '...'}, + // ... + // ] + // And then serialized as: + // encodeURIComponent(JSON.stringify({ + // url: '...', + // method: 'POST', + // headers: [{key: 'x-amz-date', value: '...'}, ...] + // })) + const reformattedHeader = []; + const extendedHeaders = Object.assign({ + // The full, canonical resource name of the workload identity pool + // provider, with or without the HTTPS prefix. + // Including this header as part of the signature is recommended to + // ensure data integrity. + 'x-goog-cloud-target-resource': this.audience, + }, options.headers); + // Reformat header to GCP STS expected format. + for (const key in extendedHeaders) { + reformattedHeader.push({ + key, + value: extendedHeaders[key], + }); + } + // Serialize the reformatted signed request. + return encodeURIComponent(JSON.stringify({ + url: options.url, + method: options.method, + headers: reformattedHeader, + })); + } +} +exports.AwsClient = AwsClient; +_a = AwsClient; +_AwsClient_DEFAULT_AWS_REGIONAL_CREDENTIAL_VERIFICATION_URL = { value: 'https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15' }; +/** + * @deprecated AWS client no validates the EC2 metadata address. + **/ +AwsClient.AWS_EC2_METADATA_IPV4_ADDRESS = '169.254.169.254'; +/** + * @deprecated AWS client no validates the EC2 metadata address. + **/ +AwsClient.AWS_EC2_METADATA_IPV6_ADDRESS = 'fd00:ec2::254'; + + +/***/ }), + +/***/ 27647: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AwsRequestSigner = void 0; +const crypto_1 = __nccwpck_require__(88851); +/** AWS Signature Version 4 signing algorithm identifier. */ +const AWS_ALGORITHM = 'AWS4-HMAC-SHA256'; +/** + * The termination string for the AWS credential scope value as defined in + * https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html + */ +const AWS_REQUEST_TYPE = 'aws4_request'; +/** + * Implements an AWS API request signer based on the AWS Signature Version 4 + * signing process. + * https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html + */ +class AwsRequestSigner { + /** + * Instantiates an AWS API request signer used to send authenticated signed + * requests to AWS APIs based on the AWS Signature Version 4 signing process. + * This also provides a mechanism to generate the signed request without + * sending it. + * @param getCredentials A mechanism to retrieve AWS security credentials + * when needed. + * @param region The AWS region to use. + */ + constructor(getCredentials, region) { + this.getCredentials = getCredentials; + this.region = region; + this.crypto = (0, crypto_1.createCrypto)(); + } + /** + * Generates the signed request for the provided HTTP request for calling + * an AWS API. This follows the steps described at: + * https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html + * @param amzOptions The AWS request options that need to be signed. + * @return A promise that resolves with the GaxiosOptions containing the + * signed HTTP request parameters. + */ + async getRequestOptions(amzOptions) { + if (!amzOptions.url) { + throw new Error('"url" is required in "amzOptions"'); + } + // Stringify JSON requests. This will be set in the request body of the + // generated signed request. + const requestPayloadData = typeof amzOptions.data === 'object' + ? JSON.stringify(amzOptions.data) + : amzOptions.data; + const url = amzOptions.url; + const method = amzOptions.method || 'GET'; + const requestPayload = amzOptions.body || requestPayloadData; + const additionalAmzHeaders = amzOptions.headers; + const awsSecurityCredentials = await this.getCredentials(); + const uri = new URL(url); + const headerMap = await generateAuthenticationHeaderMap({ + crypto: this.crypto, + host: uri.host, + canonicalUri: uri.pathname, + canonicalQuerystring: uri.search.substr(1), + method, + region: this.region, + securityCredentials: awsSecurityCredentials, + requestPayload, + additionalAmzHeaders, + }); + // Append additional optional headers, eg. X-Amz-Target, Content-Type, etc. + const headers = Object.assign( + // Add x-amz-date if available. + headerMap.amzDate ? { 'x-amz-date': headerMap.amzDate } : {}, { + Authorization: headerMap.authorizationHeader, + host: uri.host, + }, additionalAmzHeaders || {}); + if (awsSecurityCredentials.token) { + Object.assign(headers, { + 'x-amz-security-token': awsSecurityCredentials.token, + }); + } + const awsSignedReq = { + url, + method: method, + headers, + }; + if (typeof requestPayload !== 'undefined') { + awsSignedReq.body = requestPayload; + } + return awsSignedReq; + } +} +exports.AwsRequestSigner = AwsRequestSigner; +/** + * Creates the HMAC-SHA256 hash of the provided message using the + * provided key. + * + * @param crypto The crypto instance used to facilitate cryptographic + * operations. + * @param key The HMAC-SHA256 key to use. + * @param msg The message to hash. + * @return The computed hash bytes. + */ +async function sign(crypto, key, msg) { + return await crypto.signWithHmacSha256(key, msg); +} +/** + * Calculates the signing key used to calculate the signature for + * AWS Signature Version 4 based on: + * https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html + * + * @param crypto The crypto instance used to facilitate cryptographic + * operations. + * @param key The AWS secret access key. + * @param dateStamp The '%Y%m%d' date format. + * @param region The AWS region. + * @param serviceName The AWS service name, eg. sts. + * @return The signing key bytes. + */ +async function getSigningKey(crypto, key, dateStamp, region, serviceName) { + const kDate = await sign(crypto, `AWS4${key}`, dateStamp); + const kRegion = await sign(crypto, kDate, region); + const kService = await sign(crypto, kRegion, serviceName); + const kSigning = await sign(crypto, kService, 'aws4_request'); + return kSigning; +} +/** + * Generates the authentication header map needed for generating the AWS + * Signature Version 4 signed request. + * + * @param option The options needed to compute the authentication header map. + * @return The AWS authentication header map which constitutes of the following + * components: amz-date, authorization header and canonical query string. + */ +async function generateAuthenticationHeaderMap(options) { + const additionalAmzHeaders = options.additionalAmzHeaders || {}; + const requestPayload = options.requestPayload || ''; + // iam.amazonaws.com host => iam service. + // sts.us-east-2.amazonaws.com => sts service. + const serviceName = options.host.split('.')[0]; + const now = new Date(); + // Format: '%Y%m%dT%H%M%SZ'. + const amzDate = now + .toISOString() + .replace(/[-:]/g, '') + .replace(/\.[0-9]+/, ''); + // Format: '%Y%m%d'. + const dateStamp = now.toISOString().replace(/[-]/g, '').replace(/T.*/, ''); + // Change all additional headers to be lower case. + const reformattedAdditionalAmzHeaders = {}; + Object.keys(additionalAmzHeaders).forEach(key => { + reformattedAdditionalAmzHeaders[key.toLowerCase()] = + additionalAmzHeaders[key]; + }); + // Add AWS token if available. + if (options.securityCredentials.token) { + reformattedAdditionalAmzHeaders['x-amz-security-token'] = + options.securityCredentials.token; + } + // Header keys need to be sorted alphabetically. + const amzHeaders = Object.assign({ + host: options.host, + }, + // Previously the date was not fixed with x-amz- and could be provided manually. + // https://github.com/boto/botocore/blob/879f8440a4e9ace5d3cf145ce8b3d5e5ffb892ef/tests/unit/auth/aws4_testsuite/get-header-value-trim.req + reformattedAdditionalAmzHeaders.date ? {} : { 'x-amz-date': amzDate }, reformattedAdditionalAmzHeaders); + let canonicalHeaders = ''; + const signedHeadersList = Object.keys(amzHeaders).sort(); + signedHeadersList.forEach(key => { + canonicalHeaders += `${key}:${amzHeaders[key]}\n`; + }); + const signedHeaders = signedHeadersList.join(';'); + const payloadHash = await options.crypto.sha256DigestHex(requestPayload); + // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html + const canonicalRequest = `${options.method}\n` + + `${options.canonicalUri}\n` + + `${options.canonicalQuerystring}\n` + + `${canonicalHeaders}\n` + + `${signedHeaders}\n` + + `${payloadHash}`; + const credentialScope = `${dateStamp}/${options.region}/${serviceName}/${AWS_REQUEST_TYPE}`; + // https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html + const stringToSign = `${AWS_ALGORITHM}\n` + + `${amzDate}\n` + + `${credentialScope}\n` + + (await options.crypto.sha256DigestHex(canonicalRequest)); + // https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html + const signingKey = await getSigningKey(options.crypto, options.securityCredentials.secretAccessKey, dateStamp, options.region, serviceName); + const signature = await sign(options.crypto, signingKey, stringToSign); + // https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html + const authorizationHeader = `${AWS_ALGORITHM} Credential=${options.securityCredentials.accessKeyId}/` + + `${credentialScope}, SignedHeaders=${signedHeaders}, ` + + `Signature=${(0, crypto_1.fromArrayBufferToHex)(signature)}`; + return { + // Do not return x-amz-date if date is available. + amzDate: reformattedAdditionalAmzHeaders.date ? undefined : amzDate, + authorizationHeader, + canonicalQuerystring: options.canonicalQuerystring, + }; +} + + +/***/ }), + +/***/ 142: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _BaseExternalAccountClient_instances, _BaseExternalAccountClient_pendingAccessToken, _BaseExternalAccountClient_internalRefreshAccessTokenAsync; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.BaseExternalAccountClient = exports.DEFAULT_UNIVERSE = exports.CLOUD_RESOURCE_MANAGER = exports.EXTERNAL_ACCOUNT_TYPE = exports.EXPIRATION_TIME_OFFSET = void 0; +const stream = __nccwpck_require__(2203); +const authclient_1 = __nccwpck_require__(34810); +const sts = __nccwpck_require__(121); +const util_1 = __nccwpck_require__(37870); +/** + * The required token exchange grant_type: rfc8693#section-2.1 + */ +const STS_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange'; +/** + * The requested token exchange requested_token_type: rfc8693#section-2.1 + */ +const STS_REQUEST_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token'; +/** The default OAuth scope to request when none is provided. */ +const DEFAULT_OAUTH_SCOPE = 'https://www.googleapis.com/auth/cloud-platform'; +/** Default impersonated token lifespan in seconds.*/ +const DEFAULT_TOKEN_LIFESPAN = 3600; +/** + * Offset to take into account network delays and server clock skews. + */ +exports.EXPIRATION_TIME_OFFSET = 5 * 60 * 1000; +/** + * The credentials JSON file type for external account clients. + * There are 3 types of JSON configs: + * 1. authorized_user => Google end user credential + * 2. service_account => Google service account credential + * 3. external_Account => non-GCP service (eg. AWS, Azure, K8s) + */ +exports.EXTERNAL_ACCOUNT_TYPE = 'external_account'; +/** + * Cloud resource manager URL used to retrieve project information. + * + * @deprecated use {@link BaseExternalAccountClient.cloudResourceManagerURL} instead + **/ +exports.CLOUD_RESOURCE_MANAGER = 'https://cloudresourcemanager.googleapis.com/v1/projects/'; +/** The workforce audience pattern. */ +const WORKFORCE_AUDIENCE_PATTERN = '//iam\\.googleapis\\.com/locations/[^/]+/workforcePools/[^/]+/providers/.+'; +const DEFAULT_TOKEN_URL = 'https://sts.{universeDomain}/v1/token'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = __nccwpck_require__(96066); +/** + * For backwards compatibility. + */ +var authclient_2 = __nccwpck_require__(34810); +Object.defineProperty(exports, "DEFAULT_UNIVERSE", ({ enumerable: true, get: function () { return authclient_2.DEFAULT_UNIVERSE; } })); +/** + * Base external account client. This is used to instantiate AuthClients for + * exchanging external account credentials for GCP access token and authorizing + * requests to GCP APIs. + * The base class implements common logic for exchanging various type of + * external credentials for GCP access token. The logic of determining and + * retrieving the external credential based on the environment and + * credential_source will be left for the subclasses. + */ +class BaseExternalAccountClient extends authclient_1.AuthClient { + /** + * Instantiate a BaseExternalAccountClient instance using the provided JSON + * object loaded from an external account credentials file. + * @param options The external account options object typically loaded + * from the external account JSON credential file. The camelCased options + * are aliases for the snake_cased options. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + var _a; + super({ ...options, ...additionalOptions }); + _BaseExternalAccountClient_instances.add(this); + /** + * A pending access token request. Used for concurrent calls. + */ + _BaseExternalAccountClient_pendingAccessToken.set(this, null); + const opts = (0, util_1.originalOrCamelOptions)(options); + const type = opts.get('type'); + if (type && type !== exports.EXTERNAL_ACCOUNT_TYPE) { + throw new Error(`Expected "${exports.EXTERNAL_ACCOUNT_TYPE}" type but ` + + `received "${options.type}"`); + } + const clientId = opts.get('client_id'); + const clientSecret = opts.get('client_secret'); + const tokenUrl = (_a = opts.get('token_url')) !== null && _a !== void 0 ? _a : DEFAULT_TOKEN_URL.replace('{universeDomain}', this.universeDomain); + const subjectTokenType = opts.get('subject_token_type'); + const workforcePoolUserProject = opts.get('workforce_pool_user_project'); + const serviceAccountImpersonationUrl = opts.get('service_account_impersonation_url'); + const serviceAccountImpersonation = opts.get('service_account_impersonation'); + const serviceAccountImpersonationLifetime = (0, util_1.originalOrCamelOptions)(serviceAccountImpersonation).get('token_lifetime_seconds'); + this.cloudResourceManagerURL = new URL(opts.get('cloud_resource_manager_url') || + `https://cloudresourcemanager.${this.universeDomain}/v1/projects/`); + if (clientId) { + this.clientAuth = { + confidentialClientType: 'basic', + clientId, + clientSecret, + }; + } + this.stsCredential = new sts.StsCredentials(tokenUrl, this.clientAuth); + this.scopes = opts.get('scopes') || [DEFAULT_OAUTH_SCOPE]; + this.cachedAccessToken = null; + this.audience = opts.get('audience'); + this.subjectTokenType = subjectTokenType; + this.workforcePoolUserProject = workforcePoolUserProject; + const workforceAudiencePattern = new RegExp(WORKFORCE_AUDIENCE_PATTERN); + if (this.workforcePoolUserProject && + !this.audience.match(workforceAudiencePattern)) { + throw new Error('workforcePoolUserProject should not be set for non-workforce pool ' + + 'credentials.'); + } + this.serviceAccountImpersonationUrl = serviceAccountImpersonationUrl; + this.serviceAccountImpersonationLifetime = + serviceAccountImpersonationLifetime; + if (this.serviceAccountImpersonationLifetime) { + this.configLifetimeRequested = true; + } + else { + this.configLifetimeRequested = false; + this.serviceAccountImpersonationLifetime = DEFAULT_TOKEN_LIFESPAN; + } + this.projectNumber = this.getProjectNumber(this.audience); + this.supplierContext = { + audience: this.audience, + subjectTokenType: this.subjectTokenType, + transporter: this.transporter, + }; + } + /** The service account email to be impersonated, if available. */ + getServiceAccountEmail() { + var _a; + if (this.serviceAccountImpersonationUrl) { + if (this.serviceAccountImpersonationUrl.length > 256) { + /** + * Prevents DOS attacks. + * @see {@link https://github.com/googleapis/google-auth-library-nodejs/security/code-scanning/84} + **/ + throw new RangeError(`URL is too long: ${this.serviceAccountImpersonationUrl}`); + } + // Parse email from URL. The formal looks as follows: + // https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/name@project-id.iam.gserviceaccount.com:generateAccessToken + const re = /serviceAccounts\/(?[^:]+):generateAccessToken$/; + const result = re.exec(this.serviceAccountImpersonationUrl); + return ((_a = result === null || result === void 0 ? void 0 : result.groups) === null || _a === void 0 ? void 0 : _a.email) || null; + } + return null; + } + /** + * Provides a mechanism to inject GCP access tokens directly. + * When the provided credential expires, a new credential, using the + * external account options, is retrieved. + * @param credentials The Credentials object to set on the current client. + */ + setCredentials(credentials) { + super.setCredentials(credentials); + this.cachedAccessToken = credentials; + } + /** + * @return A promise that resolves with the current GCP access token + * response. If the current credential is expired, a new one is retrieved. + */ + async getAccessToken() { + // If cached access token is unavailable or expired, force refresh. + if (!this.cachedAccessToken || this.isExpired(this.cachedAccessToken)) { + await this.refreshAccessTokenAsync(); + } + // Return GCP access token in GetAccessTokenResponse format. + return { + token: this.cachedAccessToken.access_token, + res: this.cachedAccessToken.res, + }; + } + /** + * The main authentication interface. It takes an optional url which when + * present is the endpoint being accessed, and returns a Promise which + * resolves with authorization header fields. + * + * The result has the form: + * { Authorization: 'Bearer ' } + */ + async getRequestHeaders() { + const accessTokenResponse = await this.getAccessToken(); + const headers = { + Authorization: `Bearer ${accessTokenResponse.token}`, + }; + return this.addSharedMetadataHeaders(headers); + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + /** + * @return A promise that resolves with the project ID corresponding to the + * current workload identity pool or current workforce pool if + * determinable. For workforce pool credential, it returns the project ID + * corresponding to the workforcePoolUserProject. + * This is introduced to match the current pattern of using the Auth + * library: + * const projectId = await auth.getProjectId(); + * const url = `https://dns.googleapis.com/dns/v1/projects/${projectId}`; + * const res = await client.request({ url }); + * The resource may not have permission + * (resourcemanager.projects.get) to call this API or the required + * scopes may not be selected: + * https://cloud.google.com/resource-manager/reference/rest/v1/projects/get#authorization-scopes + */ + async getProjectId() { + const projectNumber = this.projectNumber || this.workforcePoolUserProject; + if (this.projectId) { + // Return previously determined project ID. + return this.projectId; + } + else if (projectNumber) { + // Preferable not to use request() to avoid retrial policies. + const headers = await this.getRequestHeaders(); + const response = await this.transporter.request({ + ...BaseExternalAccountClient.RETRY_CONFIG, + headers, + url: `${this.cloudResourceManagerURL.toString()}${projectNumber}`, + responseType: 'json', + }); + this.projectId = response.data.projectId; + return this.projectId; + } + return null; + } + /** + * Authenticates the provided HTTP request, processes it and resolves with the + * returned response. + * @param opts The HTTP request options. + * @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure. + * @return A promise that resolves with the successful response. + */ + async requestAsync(opts, reAuthRetried = false) { + let response; + try { + const requestHeaders = await this.getRequestHeaders(); + opts.headers = opts.headers || {}; + if (requestHeaders && requestHeaders['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = + requestHeaders['x-goog-user-project']; + } + if (requestHeaders && requestHeaders.Authorization) { + opts.headers.Authorization = requestHeaders.Authorization; + } + response = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - forceRefreshOnFailure is true + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + this.forceRefreshOnFailure) { + await this.refreshAccessTokenAsync(); + return await this.requestAsync(opts, true); + } + } + throw e; + } + return response; + } + /** + * Forces token refresh, even if unexpired tokens are currently cached. + * External credentials are exchanged for GCP access tokens via the token + * exchange endpoint and other settings provided in the client options + * object. + * If the service_account_impersonation_url is provided, an additional + * step to exchange the external account GCP access token for a service + * account impersonated token is performed. + * @return A promise that resolves with the fresh GCP access tokens. + */ + async refreshAccessTokenAsync() { + // Use an existing access token request, or cache a new one + __classPrivateFieldSet(this, _BaseExternalAccountClient_pendingAccessToken, __classPrivateFieldGet(this, _BaseExternalAccountClient_pendingAccessToken, "f") || __classPrivateFieldGet(this, _BaseExternalAccountClient_instances, "m", _BaseExternalAccountClient_internalRefreshAccessTokenAsync).call(this), "f"); + try { + return await __classPrivateFieldGet(this, _BaseExternalAccountClient_pendingAccessToken, "f"); + } + finally { + // clear pending access token for future requests + __classPrivateFieldSet(this, _BaseExternalAccountClient_pendingAccessToken, null, "f"); + } + } + /** + * Returns the workload identity pool project number if it is determinable + * from the audience resource name. + * @param audience The STS audience used to determine the project number. + * @return The project number associated with the workload identity pool, if + * this can be determined from the STS audience field. Otherwise, null is + * returned. + */ + getProjectNumber(audience) { + // STS audience pattern: + // //iam.googleapis.com/projects/$PROJECT_NUMBER/locations/... + const match = audience.match(/\/projects\/([^/]+)/); + if (!match) { + return null; + } + return match[1]; + } + /** + * Exchanges an external account GCP access token for a service + * account impersonated access token using iamcredentials + * GenerateAccessToken API. + * @param token The access token to exchange for a service account access + * token. + * @return A promise that resolves with the service account impersonated + * credentials response. + */ + async getImpersonatedAccessToken(token) { + const opts = { + ...BaseExternalAccountClient.RETRY_CONFIG, + url: this.serviceAccountImpersonationUrl, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + data: { + scope: this.getScopesArray(), + lifetime: this.serviceAccountImpersonationLifetime + 's', + }, + responseType: 'json', + }; + const response = await this.transporter.request(opts); + const successResponse = response.data; + return { + access_token: successResponse.accessToken, + // Convert from ISO format to timestamp. + expiry_date: new Date(successResponse.expireTime).getTime(), + res: response, + }; + } + /** + * Returns whether the provided credentials are expired or not. + * If there is no expiry time, assumes the token is not expired or expiring. + * @param accessToken The credentials to check for expiration. + * @return Whether the credentials are expired or not. + */ + isExpired(accessToken) { + const now = new Date().getTime(); + return accessToken.expiry_date + ? now >= accessToken.expiry_date - this.eagerRefreshThresholdMillis + : false; + } + /** + * @return The list of scopes for the requested GCP access token. + */ + getScopesArray() { + // Since scopes can be provided as string or array, the type should + // be normalized. + if (typeof this.scopes === 'string') { + return [this.scopes]; + } + return this.scopes || [DEFAULT_OAUTH_SCOPE]; + } + getMetricsHeaderValue() { + const nodeVersion = process.version.replace(/^v/, ''); + const saImpersonation = this.serviceAccountImpersonationUrl !== undefined; + const credentialSourceType = this.credentialSourceType + ? this.credentialSourceType + : 'unknown'; + return `gl-node/${nodeVersion} auth/${pkg.version} google-byoid-sdk source/${credentialSourceType} sa-impersonation/${saImpersonation} config-lifetime/${this.configLifetimeRequested}`; + } +} +exports.BaseExternalAccountClient = BaseExternalAccountClient; +_BaseExternalAccountClient_pendingAccessToken = new WeakMap(), _BaseExternalAccountClient_instances = new WeakSet(), _BaseExternalAccountClient_internalRefreshAccessTokenAsync = async function _BaseExternalAccountClient_internalRefreshAccessTokenAsync() { + // Retrieve the external credential. + const subjectToken = await this.retrieveSubjectToken(); + // Construct the STS credentials options. + const stsCredentialsOptions = { + grantType: STS_GRANT_TYPE, + audience: this.audience, + requestedTokenType: STS_REQUEST_TOKEN_TYPE, + subjectToken, + subjectTokenType: this.subjectTokenType, + // generateAccessToken requires the provided access token to have + // scopes: + // https://www.googleapis.com/auth/iam or + // https://www.googleapis.com/auth/cloud-platform + // The new service account access token scopes will match the user + // provided ones. + scope: this.serviceAccountImpersonationUrl + ? [DEFAULT_OAUTH_SCOPE] + : this.getScopesArray(), + }; + // Exchange the external credentials for a GCP access token. + // Client auth is prioritized over passing the workforcePoolUserProject + // parameter for STS token exchange. + const additionalOptions = !this.clientAuth && this.workforcePoolUserProject + ? { userProject: this.workforcePoolUserProject } + : undefined; + const additionalHeaders = { + 'x-goog-api-client': this.getMetricsHeaderValue(), + }; + const stsResponse = await this.stsCredential.exchangeToken(stsCredentialsOptions, additionalHeaders, additionalOptions); + if (this.serviceAccountImpersonationUrl) { + this.cachedAccessToken = await this.getImpersonatedAccessToken(stsResponse.access_token); + } + else if (stsResponse.expires_in) { + // Save response in cached access token. + this.cachedAccessToken = { + access_token: stsResponse.access_token, + expiry_date: new Date().getTime() + stsResponse.expires_in * 1000, + res: stsResponse.res, + }; + } + else { + // Save response in cached access token. + this.cachedAccessToken = { + access_token: stsResponse.access_token, + res: stsResponse.res, + }; + } + // Save credentials. + this.credentials = {}; + Object.assign(this.credentials, this.cachedAccessToken); + delete this.credentials.res; + // Trigger tokens event to notify external listeners. + this.emit('tokens', { + refresh_token: null, + expiry_date: this.cachedAccessToken.expiry_date, + access_token: this.cachedAccessToken.access_token, + token_type: 'Bearer', + id_token: null, + }); + // Return the cached access token. + return this.cachedAccessToken; +}; + + +/***/ }), + +/***/ 20977: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2013 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Compute = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const gcpMetadata = __nccwpck_require__(23046); +const oauth2client_1 = __nccwpck_require__(10091); +class Compute extends oauth2client_1.OAuth2Client { + /** + * Google Compute Engine service account credentials. + * + * Retrieve access token from the metadata server. + * See: https://cloud.google.com/compute/docs/access/authenticate-workloads#applications + */ + constructor(options = {}) { + super(options); + // Start with an expired refresh token, which will automatically be + // refreshed before the first API call is made. + this.credentials = { expiry_date: 1, refresh_token: 'compute-placeholder' }; + this.serviceAccountEmail = options.serviceAccountEmail || 'default'; + this.scopes = Array.isArray(options.scopes) + ? options.scopes + : options.scopes + ? [options.scopes] + : []; + } + /** + * Refreshes the access token. + * @param refreshToken Unused parameter + */ + async refreshTokenNoCache( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + refreshToken) { + const tokenPath = `service-accounts/${this.serviceAccountEmail}/token`; + let data; + try { + const instanceOptions = { + property: tokenPath, + }; + if (this.scopes.length > 0) { + instanceOptions.params = { + scopes: this.scopes.join(','), + }; + } + data = await gcpMetadata.instance(instanceOptions); + } + catch (e) { + if (e instanceof gaxios_1.GaxiosError) { + e.message = `Could not refresh access token: ${e.message}`; + this.wrapError(e); + } + throw e; + } + const tokens = data; + if (data && data.expires_in) { + tokens.expiry_date = new Date().getTime() + data.expires_in * 1000; + delete tokens.expires_in; + } + this.emit('tokens', tokens); + return { tokens, res: null }; + } + /** + * Fetches an ID token. + * @param targetAudience the audience for the fetched ID token. + */ + async fetchIdToken(targetAudience) { + const idTokenPath = `service-accounts/${this.serviceAccountEmail}/identity` + + `?format=full&audience=${targetAudience}`; + let idToken; + try { + const instanceOptions = { + property: idTokenPath, + }; + idToken = await gcpMetadata.instance(instanceOptions); + } + catch (e) { + if (e instanceof Error) { + e.message = `Could not fetch ID token: ${e.message}`; + } + throw e; + } + return idToken; + } + wrapError(e) { + const res = e.response; + if (res && res.status) { + e.status = res.status; + if (res.status === 403) { + e.message = + 'A Forbidden error was returned while attempting to retrieve an access ' + + 'token for the Compute Engine built-in service account. This may be because the Compute ' + + 'Engine instance does not have the correct permission scopes specified: ' + + e.message; + } + else if (res.status === 404) { + e.message = + 'A Not Found error was returned while attempting to retrieve an access' + + 'token for the Compute Engine built-in service account. This may be because the Compute ' + + 'Engine instance does not have any permission scopes specified: ' + + e.message; + } + } + } +} +exports.Compute = Compute; + + +/***/ }), + +/***/ 69157: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _DefaultAwsSecurityCredentialsSupplier_instances, _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken, _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName, _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials, _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get, _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DefaultAwsSecurityCredentialsSupplier = void 0; +/** + * Internal AWS security credentials supplier implementation used by {@link AwsClient} + * when a credential source is provided instead of a user defined supplier. + * The logic is summarized as: + * 1. If imdsv2_session_token_url is provided in the credential source, then + * fetch the aws session token and include it in the headers of the + * metadata requests. This is a requirement for IDMSv2 but optional + * for IDMSv1. + * 2. Retrieve AWS region from availability-zone. + * 3a. Check AWS credentials in environment variables. If not found, get + * from security-credentials endpoint. + * 3b. Get AWS credentials from security-credentials endpoint. In order + * to retrieve this, the AWS role needs to be determined by calling + * security-credentials endpoint without any argument. Then the + * credentials can be retrieved via: security-credentials/role_name + * 4. Generate the signed request to AWS STS GetCallerIdentity action. + * 5. Inject x-goog-cloud-target-resource into header and serialize the + * signed request. This will be the subject-token to pass to GCP STS. + */ +class DefaultAwsSecurityCredentialsSupplier { + /** + * Instantiates a new DefaultAwsSecurityCredentialsSupplier using information + * from the credential_source stored in the ADC file. + * @param opts The default aws security credentials supplier options object to + * build the supplier with. + */ + constructor(opts) { + _DefaultAwsSecurityCredentialsSupplier_instances.add(this); + this.regionUrl = opts.regionUrl; + this.securityCredentialsUrl = opts.securityCredentialsUrl; + this.imdsV2SessionTokenUrl = opts.imdsV2SessionTokenUrl; + this.additionalGaxiosOptions = opts.additionalGaxiosOptions; + } + /** + * Returns the active AWS region. This first checks to see if the region + * is available as an environment variable. If it is not, then the supplier + * will call the region URL. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link AwsClient}, contains the requested audience and subject token type + * for the external account identity. + * @return A promise that resolves with the AWS region string. + */ + async getAwsRegion(context) { + // Priority order for region determination: + // AWS_REGION > AWS_DEFAULT_REGION > metadata server. + if (__classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get)) { + return __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get); + } + const metadataHeaders = {}; + if (!__classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get) && this.imdsV2SessionTokenUrl) { + metadataHeaders['x-aws-ec2-metadata-token'] = + await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken).call(this, context.transporter); + } + if (!this.regionUrl) { + throw new Error('Unable to determine AWS region due to missing ' + + '"options.credential_source.region_url"'); + } + const opts = { + ...this.additionalGaxiosOptions, + url: this.regionUrl, + method: 'GET', + responseType: 'text', + headers: metadataHeaders, + }; + const response = await context.transporter.request(opts); + // Remove last character. For example, if us-east-2b is returned, + // the region would be us-east-2. + return response.data.substr(0, response.data.length - 1); + } + /** + * Returns AWS security credentials. This first checks to see if the credentials + * is available as environment variables. If it is not, then the supplier + * will call the security credentials URL. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link AwsClient}, contains the requested audience and subject token type + * for the external account identity. + * @return A promise that resolves with the AWS security credentials. + */ + async getAwsSecurityCredentials(context) { + // Check environment variables for permanent credentials first. + // https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html + if (__classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get)) { + return __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "a", _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get); + } + const metadataHeaders = {}; + if (this.imdsV2SessionTokenUrl) { + metadataHeaders['x-aws-ec2-metadata-token'] = + await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken).call(this, context.transporter); + } + // Since the role on a VM can change, we don't need to cache it. + const roleName = await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName).call(this, metadataHeaders, context.transporter); + // Temporary credentials typically last for several hours. + // Expiration is returned in response. + // Consider future optimization of this logic to cache AWS tokens + // until their natural expiration. + const awsCreds = await __classPrivateFieldGet(this, _DefaultAwsSecurityCredentialsSupplier_instances, "m", _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials).call(this, roleName, metadataHeaders, context.transporter); + return { + accessKeyId: awsCreds.AccessKeyId, + secretAccessKey: awsCreds.SecretAccessKey, + token: awsCreds.Token, + }; + } +} +exports.DefaultAwsSecurityCredentialsSupplier = DefaultAwsSecurityCredentialsSupplier; +_DefaultAwsSecurityCredentialsSupplier_instances = new WeakSet(), _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken = +/** + * @param transporter The transporter to use for requests. + * @return A promise that resolves with the IMDSv2 Session Token. + */ +async function _DefaultAwsSecurityCredentialsSupplier_getImdsV2SessionToken(transporter) { + const opts = { + ...this.additionalGaxiosOptions, + url: this.imdsV2SessionTokenUrl, + method: 'PUT', + responseType: 'text', + headers: { 'x-aws-ec2-metadata-token-ttl-seconds': '300' }, + }; + const response = await transporter.request(opts); + return response.data; +}, _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName = +/** + * @param headers The headers to be used in the metadata request. + * @param transporter The transporter to use for requests. + * @return A promise that resolves with the assigned role to the current + * AWS VM. This is needed for calling the security-credentials endpoint. + */ +async function _DefaultAwsSecurityCredentialsSupplier_getAwsRoleName(headers, transporter) { + if (!this.securityCredentialsUrl) { + throw new Error('Unable to determine AWS role name due to missing ' + + '"options.credential_source.url"'); + } + const opts = { + ...this.additionalGaxiosOptions, + url: this.securityCredentialsUrl, + method: 'GET', + responseType: 'text', + headers: headers, + }; + const response = await transporter.request(opts); + return response.data; +}, _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials = +/** + * Retrieves the temporary AWS credentials by calling the security-credentials + * endpoint as specified in the `credential_source` object. + * @param roleName The role attached to the current VM. + * @param headers The headers to be used in the metadata request. + * @param transporter The transporter to use for requests. + * @return A promise that resolves with the temporary AWS credentials + * needed for creating the GetCallerIdentity signed request. + */ +async function _DefaultAwsSecurityCredentialsSupplier_retrieveAwsSecurityCredentials(roleName, headers, transporter) { + const response = await transporter.request({ + ...this.additionalGaxiosOptions, + url: `${this.securityCredentialsUrl}/${roleName}`, + responseType: 'json', + headers: headers, + }); + return response.data; +}, _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get = function _DefaultAwsSecurityCredentialsSupplier_regionFromEnv_get() { + // The AWS region can be provided through AWS_REGION or AWS_DEFAULT_REGION. + // Only one is required. + return (process.env['AWS_REGION'] || process.env['AWS_DEFAULT_REGION'] || null); +}, _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get = function _DefaultAwsSecurityCredentialsSupplier_securityCredentialsFromEnv_get() { + // Both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are required. + if (process.env['AWS_ACCESS_KEY_ID'] && + process.env['AWS_SECRET_ACCESS_KEY']) { + return { + accessKeyId: process.env['AWS_ACCESS_KEY_ID'], + secretAccessKey: process.env['AWS_SECRET_ACCESS_KEY'], + token: process.env['AWS_SESSION_TOKEN'], + }; + } + return null; +}; + + +/***/ }), + +/***/ 77556: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DownscopedClient = exports.EXPIRATION_TIME_OFFSET = exports.MAX_ACCESS_BOUNDARY_RULES_COUNT = void 0; +const stream = __nccwpck_require__(2203); +const authclient_1 = __nccwpck_require__(34810); +const sts = __nccwpck_require__(121); +/** + * The required token exchange grant_type: rfc8693#section-2.1 + */ +const STS_GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:token-exchange'; +/** + * The requested token exchange requested_token_type: rfc8693#section-2.1 + */ +const STS_REQUEST_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token'; +/** + * The requested token exchange subject_token_type: rfc8693#section-2.1 + */ +const STS_SUBJECT_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:access_token'; +/** + * The maximum number of access boundary rules a Credential Access Boundary + * can contain. + */ +exports.MAX_ACCESS_BOUNDARY_RULES_COUNT = 10; +/** + * Offset to take into account network delays and server clock skews. + */ +exports.EXPIRATION_TIME_OFFSET = 5 * 60 * 1000; +/** + * Defines a set of Google credentials that are downscoped from an existing set + * of Google OAuth2 credentials. This is useful to restrict the Identity and + * Access Management (IAM) permissions that a short-lived credential can use. + * The common pattern of usage is to have a token broker with elevated access + * generate these downscoped credentials from higher access source credentials + * and pass the downscoped short-lived access tokens to a token consumer via + * some secure authenticated channel for limited access to Google Cloud Storage + * resources. + */ +class DownscopedClient extends authclient_1.AuthClient { + /** + * Instantiates a downscoped client object using the provided source + * AuthClient and credential access boundary rules. + * To downscope permissions of a source AuthClient, a Credential Access + * Boundary that specifies which resources the new credential can access, as + * well as an upper bound on the permissions that are available on each + * resource, has to be defined. A downscoped client can then be instantiated + * using the source AuthClient and the Credential Access Boundary. + * @param authClient The source AuthClient to be downscoped based on the + * provided Credential Access Boundary rules. + * @param credentialAccessBoundary The Credential Access Boundary which + * contains a list of access boundary rules. Each rule contains information + * on the resource that the rule applies to, the upper bound of the + * permissions that are available on that resource and an optional + * condition to further restrict permissions. + * @param additionalOptions **DEPRECATED, set this in the provided `authClient`.** + * Optional additional behavior customization options. + * @param quotaProjectId **DEPRECATED, set this in the provided `authClient`.** + * Optional quota project id for setting up in the x-goog-user-project header. + */ + constructor(authClient, credentialAccessBoundary, additionalOptions, quotaProjectId) { + super({ ...additionalOptions, quotaProjectId }); + this.authClient = authClient; + this.credentialAccessBoundary = credentialAccessBoundary; + // Check 1-10 Access Boundary Rules are defined within Credential Access + // Boundary. + if (credentialAccessBoundary.accessBoundary.accessBoundaryRules.length === 0) { + throw new Error('At least one access boundary rule needs to be defined.'); + } + else if (credentialAccessBoundary.accessBoundary.accessBoundaryRules.length > + exports.MAX_ACCESS_BOUNDARY_RULES_COUNT) { + throw new Error('The provided access boundary has more than ' + + `${exports.MAX_ACCESS_BOUNDARY_RULES_COUNT} access boundary rules.`); + } + // Check at least one permission should be defined in each Access Boundary + // Rule. + for (const rule of credentialAccessBoundary.accessBoundary + .accessBoundaryRules) { + if (rule.availablePermissions.length === 0) { + throw new Error('At least one permission should be defined in access boundary rules.'); + } + } + this.stsCredential = new sts.StsCredentials(`https://sts.${this.universeDomain}/v1/token`); + this.cachedDownscopedAccessToken = null; + } + /** + * Provides a mechanism to inject Downscoped access tokens directly. + * The expiry_date field is required to facilitate determination of the token + * expiration which would make it easier for the token consumer to handle. + * @param credentials The Credentials object to set on the current client. + */ + setCredentials(credentials) { + if (!credentials.expiry_date) { + throw new Error('The access token expiry_date field is missing in the provided ' + + 'credentials.'); + } + super.setCredentials(credentials); + this.cachedDownscopedAccessToken = credentials; + } + async getAccessToken() { + // If the cached access token is unavailable or expired, force refresh. + // The Downscoped access token will be returned in + // DownscopedAccessTokenResponse format. + if (!this.cachedDownscopedAccessToken || + this.isExpired(this.cachedDownscopedAccessToken)) { + await this.refreshAccessTokenAsync(); + } + // Return Downscoped access token in DownscopedAccessTokenResponse format. + return { + token: this.cachedDownscopedAccessToken.access_token, + expirationTime: this.cachedDownscopedAccessToken.expiry_date, + res: this.cachedDownscopedAccessToken.res, + }; + } + /** + * The main authentication interface. It takes an optional url which when + * present is the endpoint being accessed, and returns a Promise which + * resolves with authorization header fields. + * + * The result has the form: + * { Authorization: 'Bearer ' } + */ + async getRequestHeaders() { + const accessTokenResponse = await this.getAccessToken(); + const headers = { + Authorization: `Bearer ${accessTokenResponse.token}`, + }; + return this.addSharedMetadataHeaders(headers); + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + /** + * Authenticates the provided HTTP request, processes it and resolves with the + * returned response. + * @param opts The HTTP request options. + * @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure + * @return A promise that resolves with the successful response. + */ + async requestAsync(opts, reAuthRetried = false) { + let response; + try { + const requestHeaders = await this.getRequestHeaders(); + opts.headers = opts.headers || {}; + if (requestHeaders && requestHeaders['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = + requestHeaders['x-goog-user-project']; + } + if (requestHeaders && requestHeaders.Authorization) { + opts.headers.Authorization = requestHeaders.Authorization; + } + response = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - forceRefreshOnFailure is true + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + this.forceRefreshOnFailure) { + await this.refreshAccessTokenAsync(); + return await this.requestAsync(opts, true); + } + } + throw e; + } + return response; + } + /** + * Forces token refresh, even if unexpired tokens are currently cached. + * GCP access tokens are retrieved from authclient object/source credential. + * Then GCP access tokens are exchanged for downscoped access tokens via the + * token exchange endpoint. + * @return A promise that resolves with the fresh downscoped access token. + */ + async refreshAccessTokenAsync() { + var _a; + // Retrieve GCP access token from source credential. + const subjectToken = (await this.authClient.getAccessToken()).token; + // Construct the STS credentials options. + const stsCredentialsOptions = { + grantType: STS_GRANT_TYPE, + requestedTokenType: STS_REQUEST_TOKEN_TYPE, + subjectToken: subjectToken, + subjectTokenType: STS_SUBJECT_TOKEN_TYPE, + }; + // Exchange the source AuthClient access token for a Downscoped access + // token. + const stsResponse = await this.stsCredential.exchangeToken(stsCredentialsOptions, undefined, this.credentialAccessBoundary); + /** + * The STS endpoint will only return the expiration time for the downscoped + * access token if the original access token represents a service account. + * The downscoped token's expiration time will always match the source + * credential expiration. When no expires_in is returned, we can copy the + * source credential's expiration time. + */ + const sourceCredExpireDate = ((_a = this.authClient.credentials) === null || _a === void 0 ? void 0 : _a.expiry_date) || null; + const expiryDate = stsResponse.expires_in + ? new Date().getTime() + stsResponse.expires_in * 1000 + : sourceCredExpireDate; + // Save response in cached access token. + this.cachedDownscopedAccessToken = { + access_token: stsResponse.access_token, + expiry_date: expiryDate, + res: stsResponse.res, + }; + // Save credentials. + this.credentials = {}; + Object.assign(this.credentials, this.cachedDownscopedAccessToken); + delete this.credentials.res; + // Trigger tokens event to notify external listeners. + this.emit('tokens', { + refresh_token: null, + expiry_date: this.cachedDownscopedAccessToken.expiry_date, + access_token: this.cachedDownscopedAccessToken.access_token, + token_type: 'Bearer', + id_token: null, + }); + // Return the cached access token. + return this.cachedDownscopedAccessToken; + } + /** + * Returns whether the provided credentials are expired or not. + * If there is no expiry time, assumes the token is not expired or expiring. + * @param downscopedAccessToken The credentials to check for expiration. + * @return Whether the credentials are expired or not. + */ + isExpired(downscopedAccessToken) { + const now = new Date().getTime(); + return downscopedAccessToken.expiry_date + ? now >= + downscopedAccessToken.expiry_date - this.eagerRefreshThresholdMillis + : false; + } +} +exports.DownscopedClient = DownscopedClient; + + +/***/ }), + +/***/ 60963: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GCPEnv = void 0; +exports.clear = clear; +exports.getEnv = getEnv; +const gcpMetadata = __nccwpck_require__(23046); +var GCPEnv; +(function (GCPEnv) { + GCPEnv["APP_ENGINE"] = "APP_ENGINE"; + GCPEnv["KUBERNETES_ENGINE"] = "KUBERNETES_ENGINE"; + GCPEnv["CLOUD_FUNCTIONS"] = "CLOUD_FUNCTIONS"; + GCPEnv["COMPUTE_ENGINE"] = "COMPUTE_ENGINE"; + GCPEnv["CLOUD_RUN"] = "CLOUD_RUN"; + GCPEnv["NONE"] = "NONE"; +})(GCPEnv || (exports.GCPEnv = GCPEnv = {})); +let envPromise; +function clear() { + envPromise = undefined; +} +async function getEnv() { + if (envPromise) { + return envPromise; + } + envPromise = getEnvMemoized(); + return envPromise; +} +async function getEnvMemoized() { + let env = GCPEnv.NONE; + if (isAppEngine()) { + env = GCPEnv.APP_ENGINE; + } + else if (isCloudFunction()) { + env = GCPEnv.CLOUD_FUNCTIONS; + } + else if (await isComputeEngine()) { + if (await isKubernetesEngine()) { + env = GCPEnv.KUBERNETES_ENGINE; + } + else if (isCloudRun()) { + env = GCPEnv.CLOUD_RUN; + } + else { + env = GCPEnv.COMPUTE_ENGINE; + } + } + else { + env = GCPEnv.NONE; + } + return env; +} +function isAppEngine() { + return !!(process.env.GAE_SERVICE || process.env.GAE_MODULE_NAME); +} +function isCloudFunction() { + return !!(process.env.FUNCTION_NAME || process.env.FUNCTION_TARGET); +} +/** + * This check only verifies that the environment is running knative. + * This must be run *after* checking for Kubernetes, otherwise it will + * return a false positive. + */ +function isCloudRun() { + return !!process.env.K_CONFIGURATION; +} +async function isKubernetesEngine() { + try { + await gcpMetadata.instance('attributes/cluster-name'); + return true; + } + catch (e) { + return false; + } +} +async function isComputeEngine() { + return gcpMetadata.isAvailable(); +} + + +/***/ }), + +/***/ 43247: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.InvalidSubjectTokenError = exports.InvalidMessageFieldError = exports.InvalidCodeFieldError = exports.InvalidTokenTypeFieldError = exports.InvalidExpirationTimeFieldError = exports.InvalidSuccessFieldError = exports.InvalidVersionFieldError = exports.ExecutableResponseError = exports.ExecutableResponse = void 0; +const SAML_SUBJECT_TOKEN_TYPE = 'urn:ietf:params:oauth:token-type:saml2'; +const OIDC_SUBJECT_TOKEN_TYPE1 = 'urn:ietf:params:oauth:token-type:id_token'; +const OIDC_SUBJECT_TOKEN_TYPE2 = 'urn:ietf:params:oauth:token-type:jwt'; +/** + * Defines the response of a 3rd party executable run by the pluggable auth client. + */ +class ExecutableResponse { + /** + * Instantiates an ExecutableResponse instance using the provided JSON object + * from the output of the executable. + * @param responseJson Response from a 3rd party executable, loaded from a + * run of the executable or a cached output file. + */ + constructor(responseJson) { + // Check that the required fields exist in the json response. + if (!responseJson.version) { + throw new InvalidVersionFieldError("Executable response must contain a 'version' field."); + } + if (responseJson.success === undefined) { + throw new InvalidSuccessFieldError("Executable response must contain a 'success' field."); + } + this.version = responseJson.version; + this.success = responseJson.success; + // Validate required fields for a successful response. + if (this.success) { + this.expirationTime = responseJson.expiration_time; + this.tokenType = responseJson.token_type; + // Validate token type field. + if (this.tokenType !== SAML_SUBJECT_TOKEN_TYPE && + this.tokenType !== OIDC_SUBJECT_TOKEN_TYPE1 && + this.tokenType !== OIDC_SUBJECT_TOKEN_TYPE2) { + throw new InvalidTokenTypeFieldError("Executable response must contain a 'token_type' field when successful " + + `and it must be one of ${OIDC_SUBJECT_TOKEN_TYPE1}, ${OIDC_SUBJECT_TOKEN_TYPE2}, or ${SAML_SUBJECT_TOKEN_TYPE}.`); + } + // Validate subject token. + if (this.tokenType === SAML_SUBJECT_TOKEN_TYPE) { + if (!responseJson.saml_response) { + throw new InvalidSubjectTokenError(`Executable response must contain a 'saml_response' field when token_type=${SAML_SUBJECT_TOKEN_TYPE}.`); + } + this.subjectToken = responseJson.saml_response; + } + else { + if (!responseJson.id_token) { + throw new InvalidSubjectTokenError("Executable response must contain a 'id_token' field when " + + `token_type=${OIDC_SUBJECT_TOKEN_TYPE1} or ${OIDC_SUBJECT_TOKEN_TYPE2}.`); + } + this.subjectToken = responseJson.id_token; + } + } + else { + // Both code and message must be provided for unsuccessful responses. + if (!responseJson.code) { + throw new InvalidCodeFieldError("Executable response must contain a 'code' field when unsuccessful."); + } + if (!responseJson.message) { + throw new InvalidMessageFieldError("Executable response must contain a 'message' field when unsuccessful."); + } + this.errorCode = responseJson.code; + this.errorMessage = responseJson.message; + } + } + /** + * @return A boolean representing if the response has a valid token. Returns + * true when the response was successful and the token is not expired. + */ + isValid() { + return !this.isExpired() && this.success; + } + /** + * @return A boolean representing if the response is expired. Returns true if the + * provided timeout has passed. + */ + isExpired() { + return (this.expirationTime !== undefined && + this.expirationTime < Math.round(Date.now() / 1000)); + } +} +exports.ExecutableResponse = ExecutableResponse; +/** + * An error thrown by the ExecutableResponse class. + */ +class ExecutableResponseError extends Error { + constructor(message) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} +exports.ExecutableResponseError = ExecutableResponseError; +/** + * An error thrown when the 'version' field in an executable response is missing or invalid. + */ +class InvalidVersionFieldError extends ExecutableResponseError { +} +exports.InvalidVersionFieldError = InvalidVersionFieldError; +/** + * An error thrown when the 'success' field in an executable response is missing or invalid. + */ +class InvalidSuccessFieldError extends ExecutableResponseError { +} +exports.InvalidSuccessFieldError = InvalidSuccessFieldError; +/** + * An error thrown when the 'expiration_time' field in an executable response is missing or invalid. + */ +class InvalidExpirationTimeFieldError extends ExecutableResponseError { +} +exports.InvalidExpirationTimeFieldError = InvalidExpirationTimeFieldError; +/** + * An error thrown when the 'token_type' field in an executable response is missing or invalid. + */ +class InvalidTokenTypeFieldError extends ExecutableResponseError { +} +exports.InvalidTokenTypeFieldError = InvalidTokenTypeFieldError; +/** + * An error thrown when the 'code' field in an executable response is missing or invalid. + */ +class InvalidCodeFieldError extends ExecutableResponseError { +} +exports.InvalidCodeFieldError = InvalidCodeFieldError; +/** + * An error thrown when the 'message' field in an executable response is missing or invalid. + */ +class InvalidMessageFieldError extends ExecutableResponseError { +} +exports.InvalidMessageFieldError = InvalidMessageFieldError; +/** + * An error thrown when the subject token in an executable response is missing or invalid. + */ +class InvalidSubjectTokenError extends ExecutableResponseError { +} +exports.InvalidSubjectTokenError = InvalidSubjectTokenError; + + +/***/ }), + +/***/ 34240: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ExternalAccountAuthorizedUserClient = exports.EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = void 0; +const authclient_1 = __nccwpck_require__(34810); +const oauth2common_1 = __nccwpck_require__(6653); +const gaxios_1 = __nccwpck_require__(97003); +const stream = __nccwpck_require__(2203); +const baseexternalclient_1 = __nccwpck_require__(142); +/** + * The credentials JSON file type for external account authorized user clients. + */ +exports.EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE = 'external_account_authorized_user'; +const DEFAULT_TOKEN_URL = 'https://sts.{universeDomain}/v1/oauthtoken'; +/** + * Handler for token refresh requests sent to the token_url endpoint for external + * authorized user credentials. + */ +class ExternalAccountAuthorizedUserHandler extends oauth2common_1.OAuthClientAuthHandler { + /** + * Initializes an ExternalAccountAuthorizedUserHandler instance. + * @param url The URL of the token refresh endpoint. + * @param transporter The transporter to use for the refresh request. + * @param clientAuthentication The client authentication credentials to use + * for the refresh request. + */ + constructor(url, transporter, clientAuthentication) { + super(clientAuthentication); + this.url = url; + this.transporter = transporter; + } + /** + * Requests a new access token from the token_url endpoint using the provided + * refresh token. + * @param refreshToken The refresh token to use to generate a new access token. + * @param additionalHeaders Optional additional headers to pass along the + * request. + * @return A promise that resolves with the token refresh response containing + * the requested access token and its expiration time. + */ + async refreshToken(refreshToken, additionalHeaders) { + const values = new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: refreshToken, + }); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + ...additionalHeaders, + }; + const opts = { + ...ExternalAccountAuthorizedUserHandler.RETRY_CONFIG, + url: this.url, + method: 'POST', + headers, + data: values.toString(), + responseType: 'json', + }; + // Apply OAuth client authentication. + this.applyClientAuthenticationOptions(opts); + try { + const response = await this.transporter.request(opts); + // Successful response. + const tokenRefreshResponse = response.data; + tokenRefreshResponse.res = response; + return tokenRefreshResponse; + } + catch (error) { + // Translate error to OAuthError. + if (error instanceof gaxios_1.GaxiosError && error.response) { + throw (0, oauth2common_1.getErrorFromOAuthErrorResponse)(error.response.data, + // Preserve other fields from the original error. + error); + } + // Request could fail before the server responds. + throw error; + } + } +} +/** + * External Account Authorized User Client. This is used for OAuth2 credentials + * sourced using external identities through Workforce Identity Federation. + * Obtaining the initial access and refresh token can be done through the + * Google Cloud CLI. + */ +class ExternalAccountAuthorizedUserClient extends authclient_1.AuthClient { + /** + * Instantiates an ExternalAccountAuthorizedUserClient instances using the + * provided JSON object loaded from a credentials files. + * An error is throws if the credential is not valid. + * @param options The external account authorized user option object typically + * from the external accoutn authorized user JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + var _a; + super({ ...options, ...additionalOptions }); + if (options.universe_domain) { + this.universeDomain = options.universe_domain; + } + this.refreshToken = options.refresh_token; + const clientAuth = { + confidentialClientType: 'basic', + clientId: options.client_id, + clientSecret: options.client_secret, + }; + this.externalAccountAuthorizedUserHandler = + new ExternalAccountAuthorizedUserHandler((_a = options.token_url) !== null && _a !== void 0 ? _a : DEFAULT_TOKEN_URL.replace('{universeDomain}', this.universeDomain), this.transporter, clientAuth); + this.cachedAccessToken = null; + this.quotaProjectId = options.quota_project_id; + // As threshold could be zero, + // eagerRefreshThresholdMillis || EXPIRATION_TIME_OFFSET will override the + // zero value. + if (typeof (additionalOptions === null || additionalOptions === void 0 ? void 0 : additionalOptions.eagerRefreshThresholdMillis) !== 'number') { + this.eagerRefreshThresholdMillis = baseexternalclient_1.EXPIRATION_TIME_OFFSET; + } + else { + this.eagerRefreshThresholdMillis = additionalOptions + .eagerRefreshThresholdMillis; + } + this.forceRefreshOnFailure = !!(additionalOptions === null || additionalOptions === void 0 ? void 0 : additionalOptions.forceRefreshOnFailure); + } + async getAccessToken() { + // If cached access token is unavailable or expired, force refresh. + if (!this.cachedAccessToken || this.isExpired(this.cachedAccessToken)) { + await this.refreshAccessTokenAsync(); + } + // Return GCP access token in GetAccessTokenResponse format. + return { + token: this.cachedAccessToken.access_token, + res: this.cachedAccessToken.res, + }; + } + async getRequestHeaders() { + const accessTokenResponse = await this.getAccessToken(); + const headers = { + Authorization: `Bearer ${accessTokenResponse.token}`, + }; + return this.addSharedMetadataHeaders(headers); + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + /** + * Authenticates the provided HTTP request, processes it and resolves with the + * returned response. + * @param opts The HTTP request options. + * @param reAuthRetried Whether the current attempt is a retry after a failed attempt due to an auth failure. + * @return A promise that resolves with the successful response. + */ + async requestAsync(opts, reAuthRetried = false) { + let response; + try { + const requestHeaders = await this.getRequestHeaders(); + opts.headers = opts.headers || {}; + if (requestHeaders && requestHeaders['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = + requestHeaders['x-goog-user-project']; + } + if (requestHeaders && requestHeaders.Authorization) { + opts.headers.Authorization = requestHeaders.Authorization; + } + response = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - forceRefreshOnFailure is true + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + this.forceRefreshOnFailure) { + await this.refreshAccessTokenAsync(); + return await this.requestAsync(opts, true); + } + } + throw e; + } + return response; + } + /** + * Forces token refresh, even if unexpired tokens are currently cached. + * @return A promise that resolves with the refreshed credential. + */ + async refreshAccessTokenAsync() { + // Refresh the access token using the refresh token. + const refreshResponse = await this.externalAccountAuthorizedUserHandler.refreshToken(this.refreshToken); + this.cachedAccessToken = { + access_token: refreshResponse.access_token, + expiry_date: new Date().getTime() + refreshResponse.expires_in * 1000, + res: refreshResponse.res, + }; + if (refreshResponse.refresh_token !== undefined) { + this.refreshToken = refreshResponse.refresh_token; + } + return this.cachedAccessToken; + } + /** + * Returns whether the provided credentials are expired or not. + * If there is no expiry time, assumes the token is not expired or expiring. + * @param credentials The credentials to check for expiration. + * @return Whether the credentials are expired or not. + */ + isExpired(credentials) { + const now = new Date().getTime(); + return credentials.expiry_date + ? now >= credentials.expiry_date - this.eagerRefreshThresholdMillis + : false; + } +} +exports.ExternalAccountAuthorizedUserClient = ExternalAccountAuthorizedUserClient; + + +/***/ }), + +/***/ 88323: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ExternalAccountClient = void 0; +const baseexternalclient_1 = __nccwpck_require__(142); +const identitypoolclient_1 = __nccwpck_require__(29960); +const awsclient_1 = __nccwpck_require__(81261); +const pluggable_auth_client_1 = __nccwpck_require__(46077); +/** + * Dummy class with no constructor. Developers are expected to use fromJSON. + */ +class ExternalAccountClient { + constructor() { + throw new Error('ExternalAccountClients should be initialized via: ' + + 'ExternalAccountClient.fromJSON(), ' + + 'directly via explicit constructors, eg. ' + + 'new AwsClient(options), new IdentityPoolClient(options), new' + + 'PluggableAuthClientOptions, or via ' + + 'new GoogleAuth(options).getClient()'); + } + /** + * This static method will instantiate the + * corresponding type of external account credential depending on the + * underlying credential source. + * @param options The external account options object typically loaded + * from the external account JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + * @return A BaseExternalAccountClient instance or null if the options + * provided do not correspond to an external account credential. + */ + static fromJSON(options, additionalOptions) { + var _a, _b; + if (options && options.type === baseexternalclient_1.EXTERNAL_ACCOUNT_TYPE) { + if ((_a = options.credential_source) === null || _a === void 0 ? void 0 : _a.environment_id) { + return new awsclient_1.AwsClient(options, additionalOptions); + } + else if ((_b = options.credential_source) === null || _b === void 0 ? void 0 : _b.executable) { + return new pluggable_auth_client_1.PluggableAuthClient(options, additionalOptions); + } + else { + return new identitypoolclient_1.IdentityPoolClient(options, additionalOptions); + } + } + else { + return null; + } + } +} +exports.ExternalAccountClient = ExternalAccountClient; + + +/***/ }), + +/***/ 10932: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var _a, _b, _c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FileSubjectTokenSupplier = void 0; +const util_1 = __nccwpck_require__(39023); +const fs = __nccwpck_require__(79896); +// fs.readfile is undefined in browser karma tests causing +// `npm run browser-test` to fail as test.oauth2.ts imports this file via +// src/index.ts. +// Fallback to void function to avoid promisify throwing a TypeError. +const readFile = (0, util_1.promisify)((_a = fs.readFile) !== null && _a !== void 0 ? _a : (() => { })); +const realpath = (0, util_1.promisify)((_b = fs.realpath) !== null && _b !== void 0 ? _b : (() => { })); +const lstat = (0, util_1.promisify)((_c = fs.lstat) !== null && _c !== void 0 ? _c : (() => { })); +/** + * Internal subject token supplier implementation used when a file location + * is configured in the credential configuration used to build an {@link IdentityPoolClient} + */ +class FileSubjectTokenSupplier { + /** + * Instantiates a new file based subject token supplier. + * @param opts The file subject token supplier options to build the supplier + * with. + */ + constructor(opts) { + this.filePath = opts.filePath; + this.formatType = opts.formatType; + this.subjectTokenFieldName = opts.subjectTokenFieldName; + } + /** + * Returns the subject token stored at the file specified in the constructor. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link IdentityPoolClient}, contains the requested audience and subject + * token type for the external account identity. Not used. + */ + async getSubjectToken(context) { + // Make sure there is a file at the path. lstatSync will throw if there is + // nothing there. + let parsedFilePath = this.filePath; + try { + // Resolve path to actual file in case of symlink. Expect a thrown error + // if not resolvable. + parsedFilePath = await realpath(parsedFilePath); + if (!(await lstat(parsedFilePath)).isFile()) { + throw new Error(); + } + } + catch (err) { + if (err instanceof Error) { + err.message = `The file at ${parsedFilePath} does not exist, or it is not a file. ${err.message}`; + } + throw err; + } + let subjectToken; + const rawText = await readFile(parsedFilePath, { encoding: 'utf8' }); + if (this.formatType === 'text') { + subjectToken = rawText; + } + else if (this.formatType === 'json' && this.subjectTokenFieldName) { + const json = JSON.parse(rawText); + subjectToken = json[this.subjectTokenFieldName]; + } + if (!subjectToken) { + throw new Error('Unable to parse the subject_token from the credential_source file'); + } + return subjectToken; + } +} +exports.FileSubjectTokenSupplier = FileSubjectTokenSupplier; + + +/***/ }), + +/***/ 95934: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _GoogleAuth_instances, _GoogleAuth_pendingAuthClient, _GoogleAuth_prepareAndCacheClient, _GoogleAuth_determineClient; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GoogleAuth = exports.GoogleAuthExceptionMessages = exports.CLOUD_SDK_CLIENT_ID = void 0; +const child_process_1 = __nccwpck_require__(35317); +const fs = __nccwpck_require__(79896); +const gcpMetadata = __nccwpck_require__(23046); +const os = __nccwpck_require__(70857); +const path = __nccwpck_require__(16928); +const crypto_1 = __nccwpck_require__(88851); +const transporters_1 = __nccwpck_require__(67633); +const computeclient_1 = __nccwpck_require__(20977); +const idtokenclient_1 = __nccwpck_require__(12718); +const envDetect_1 = __nccwpck_require__(60963); +const jwtclient_1 = __nccwpck_require__(75277); +const refreshclient_1 = __nccwpck_require__(99807); +const impersonated_1 = __nccwpck_require__(39964); +const externalclient_1 = __nccwpck_require__(88323); +const baseexternalclient_1 = __nccwpck_require__(142); +const authclient_1 = __nccwpck_require__(34810); +const externalAccountAuthorizedUserClient_1 = __nccwpck_require__(34240); +const util_1 = __nccwpck_require__(37870); +exports.CLOUD_SDK_CLIENT_ID = '764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com'; +exports.GoogleAuthExceptionMessages = { + API_KEY_WITH_CREDENTIALS: 'API Keys and Credentials are mutually exclusive authentication methods and cannot be used together.', + NO_PROJECT_ID_FOUND: 'Unable to detect a Project Id in the current environment. \n' + + 'To learn more about authentication and Google APIs, visit: \n' + + 'https://cloud.google.com/docs/authentication/getting-started', + NO_CREDENTIALS_FOUND: 'Unable to find credentials in current environment. \n' + + 'To learn more about authentication and Google APIs, visit: \n' + + 'https://cloud.google.com/docs/authentication/getting-started', + NO_ADC_FOUND: 'Could not load the default credentials. Browse to https://cloud.google.com/docs/authentication/getting-started for more information.', + NO_UNIVERSE_DOMAIN_FOUND: 'Unable to detect a Universe Domain in the current environment.\n' + + 'To learn more about Universe Domain retrieval, visit: \n' + + 'https://cloud.google.com/compute/docs/metadata/predefined-metadata-keys', +}; +class GoogleAuth { + // Note: this properly is only public to satisfy unit tests. + // https://github.com/Microsoft/TypeScript/issues/5228 + get isGCE() { + return this.checkIsGCE; + } + /** + * Configuration is resolved in the following order of precedence: + * - {@link GoogleAuthOptions.credentials `credentials`} + * - {@link GoogleAuthOptions.keyFilename `keyFilename`} + * - {@link GoogleAuthOptions.keyFile `keyFile`} + * + * {@link GoogleAuthOptions.clientOptions `clientOptions`} are passed to the + * {@link AuthClient `AuthClient`s}. + * + * @param opts + */ + constructor(opts = {}) { + _GoogleAuth_instances.add(this); + /** + * Caches a value indicating whether the auth layer is running on Google + * Compute Engine. + * @private + */ + this.checkIsGCE = undefined; + // To save the contents of the JSON credential file + this.jsonContent = null; + this.cachedCredential = null; + /** + * A pending {@link AuthClient}. Used for concurrent {@link GoogleAuth.getClient} calls. + */ + _GoogleAuth_pendingAuthClient.set(this, null); + this.clientOptions = {}; + this._cachedProjectId = opts.projectId || null; + this.cachedCredential = opts.authClient || null; + this.keyFilename = opts.keyFilename || opts.keyFile; + this.scopes = opts.scopes; + this.clientOptions = opts.clientOptions || {}; + this.jsonContent = opts.credentials || null; + this.apiKey = opts.apiKey || this.clientOptions.apiKey || null; + // Cannot use both API Key + Credentials + if (this.apiKey && (this.jsonContent || this.clientOptions.credentials)) { + throw new RangeError(exports.GoogleAuthExceptionMessages.API_KEY_WITH_CREDENTIALS); + } + if (opts.universeDomain) { + this.clientOptions.universeDomain = opts.universeDomain; + } + } + // GAPIC client libraries should always use self-signed JWTs. The following + // variables are set on the JWT client in order to indicate the type of library, + // and sign the JWT with the correct audience and scopes (if not supplied). + setGapicJWTValues(client) { + client.defaultServicePath = this.defaultServicePath; + client.useJWTAccessWithScope = this.useJWTAccessWithScope; + client.defaultScopes = this.defaultScopes; + } + getProjectId(callback) { + if (callback) { + this.getProjectIdAsync().then(r => callback(null, r), callback); + } + else { + return this.getProjectIdAsync(); + } + } + /** + * A temporary method for internal `getProjectId` usages where `null` is + * acceptable. In a future major release, `getProjectId` should return `null` + * (as the `Promise` base signature describes) and this private + * method should be removed. + * + * @returns Promise that resolves with project id (or `null`) + */ + async getProjectIdOptional() { + try { + return await this.getProjectId(); + } + catch (e) { + if (e instanceof Error && + e.message === exports.GoogleAuthExceptionMessages.NO_PROJECT_ID_FOUND) { + return null; + } + else { + throw e; + } + } + } + /** + * A private method for finding and caching a projectId. + * + * Supports environments in order of precedence: + * - GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variable + * - GOOGLE_APPLICATION_CREDENTIALS JSON file + * - Cloud SDK: `gcloud config config-helper --format json` + * - GCE project ID from metadata server + * + * @returns projectId + */ + async findAndCacheProjectId() { + let projectId = null; + projectId || (projectId = await this.getProductionProjectId()); + projectId || (projectId = await this.getFileProjectId()); + projectId || (projectId = await this.getDefaultServiceProjectId()); + projectId || (projectId = await this.getGCEProjectId()); + projectId || (projectId = await this.getExternalAccountClientProjectId()); + if (projectId) { + this._cachedProjectId = projectId; + return projectId; + } + else { + throw new Error(exports.GoogleAuthExceptionMessages.NO_PROJECT_ID_FOUND); + } + } + async getProjectIdAsync() { + if (this._cachedProjectId) { + return this._cachedProjectId; + } + if (!this._findProjectIdPromise) { + this._findProjectIdPromise = this.findAndCacheProjectId(); + } + return this._findProjectIdPromise; + } + /** + * Retrieves a universe domain from the metadata server via + * {@link gcpMetadata.universe}. + * + * @returns a universe domain + */ + async getUniverseDomainFromMetadataServer() { + var _a; + let universeDomain; + try { + universeDomain = await gcpMetadata.universe('universe-domain'); + universeDomain || (universeDomain = authclient_1.DEFAULT_UNIVERSE); + } + catch (e) { + if (e && ((_a = e === null || e === void 0 ? void 0 : e.response) === null || _a === void 0 ? void 0 : _a.status) === 404) { + universeDomain = authclient_1.DEFAULT_UNIVERSE; + } + else { + throw e; + } + } + return universeDomain; + } + /** + * Retrieves, caches, and returns the universe domain in the following order + * of precedence: + * - The universe domain in {@link GoogleAuth.clientOptions} + * - An existing or ADC {@link AuthClient}'s universe domain + * - {@link gcpMetadata.universe}, if {@link Compute} client + * + * @returns The universe domain + */ + async getUniverseDomain() { + let universeDomain = (0, util_1.originalOrCamelOptions)(this.clientOptions).get('universe_domain'); + try { + universeDomain !== null && universeDomain !== void 0 ? universeDomain : (universeDomain = (await this.getClient()).universeDomain); + } + catch (_a) { + // client or ADC is not available + universeDomain !== null && universeDomain !== void 0 ? universeDomain : (universeDomain = authclient_1.DEFAULT_UNIVERSE); + } + return universeDomain; + } + /** + * @returns Any scopes (user-specified or default scopes specified by the + * client library) that need to be set on the current Auth client. + */ + getAnyScopes() { + return this.scopes || this.defaultScopes; + } + getApplicationDefault(optionsOrCallback = {}, callback) { + let options; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else { + options = optionsOrCallback; + } + if (callback) { + this.getApplicationDefaultAsync(options).then(r => callback(null, r.credential, r.projectId), callback); + } + else { + return this.getApplicationDefaultAsync(options); + } + } + async getApplicationDefaultAsync(options = {}) { + // If we've already got a cached credential, return it. + // This will also preserve one's configured quota project, in case they + // set one directly on the credential previously. + if (this.cachedCredential) { + // cache, while preserving existing quota project preferences + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, this.cachedCredential, null); + } + let credential; + // Check for the existence of a local environment variable pointing to the + // location of the credential file. This is typically used in local + // developer scenarios. + credential = + await this._tryGetApplicationCredentialsFromEnvironmentVariable(options); + if (credential) { + if (credential instanceof jwtclient_1.JWT) { + credential.scopes = this.scopes; + } + else if (credential instanceof baseexternalclient_1.BaseExternalAccountClient) { + credential.scopes = this.getAnyScopes(); + } + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, credential); + } + // Look in the well-known credential file location. + credential = + await this._tryGetApplicationCredentialsFromWellKnownFile(options); + if (credential) { + if (credential instanceof jwtclient_1.JWT) { + credential.scopes = this.scopes; + } + else if (credential instanceof baseexternalclient_1.BaseExternalAccountClient) { + credential.scopes = this.getAnyScopes(); + } + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, credential); + } + // Determine if we're running on GCE. + if (await this._checkIsGCE()) { + options.scopes = this.getAnyScopes(); + return await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, new computeclient_1.Compute(options)); + } + throw new Error(exports.GoogleAuthExceptionMessages.NO_ADC_FOUND); + } + /** + * Determines whether the auth layer is running on Google Compute Engine. + * Checks for GCP Residency, then fallback to checking if metadata server + * is available. + * + * @returns A promise that resolves with the boolean. + * @api private + */ + async _checkIsGCE() { + if (this.checkIsGCE === undefined) { + this.checkIsGCE = + gcpMetadata.getGCPResidency() || (await gcpMetadata.isAvailable()); + } + return this.checkIsGCE; + } + /** + * Attempts to load default credentials from the environment variable path.. + * @returns Promise that resolves with the OAuth2Client or null. + * @api private + */ + async _tryGetApplicationCredentialsFromEnvironmentVariable(options) { + const credentialsPath = process.env['GOOGLE_APPLICATION_CREDENTIALS'] || + process.env['google_application_credentials']; + if (!credentialsPath || credentialsPath.length === 0) { + return null; + } + try { + return this._getApplicationCredentialsFromFilePath(credentialsPath, options); + } + catch (e) { + if (e instanceof Error) { + e.message = `Unable to read the credential file specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable: ${e.message}`; + } + throw e; + } + } + /** + * Attempts to load default credentials from a well-known file location + * @return Promise that resolves with the OAuth2Client or null. + * @api private + */ + async _tryGetApplicationCredentialsFromWellKnownFile(options) { + // First, figure out the location of the file, depending upon the OS type. + let location = null; + if (this._isWindows()) { + // Windows + location = process.env['APPDATA']; + } + else { + // Linux or Mac + const home = process.env['HOME']; + if (home) { + location = path.join(home, '.config'); + } + } + // If we found the root path, expand it. + if (location) { + location = path.join(location, 'gcloud', 'application_default_credentials.json'); + if (!fs.existsSync(location)) { + location = null; + } + } + // The file does not exist. + if (!location) { + return null; + } + // The file seems to exist. Try to use it. + const client = await this._getApplicationCredentialsFromFilePath(location, options); + return client; + } + /** + * Attempts to load default credentials from a file at the given path.. + * @param filePath The path to the file to read. + * @returns Promise that resolves with the OAuth2Client + * @api private + */ + async _getApplicationCredentialsFromFilePath(filePath, options = {}) { + // Make sure the path looks like a string. + if (!filePath || filePath.length === 0) { + throw new Error('The file path is invalid.'); + } + // Make sure there is a file at the path. lstatSync will throw if there is + // nothing there. + try { + // Resolve path to actual file in case of symlink. Expect a thrown error + // if not resolvable. + filePath = fs.realpathSync(filePath); + if (!fs.lstatSync(filePath).isFile()) { + throw new Error(); + } + } + catch (err) { + if (err instanceof Error) { + err.message = `The file at ${filePath} does not exist, or it is not a file. ${err.message}`; + } + throw err; + } + // Now open a read stream on the file, and parse it. + const readStream = fs.createReadStream(filePath); + return this.fromStream(readStream, options); + } + /** + * Create a credentials instance using a given impersonated input options. + * @param json The impersonated input object. + * @returns JWT or UserRefresh Client with data + */ + fromImpersonatedJSON(json) { + var _a, _b, _c, _d; + if (!json) { + throw new Error('Must pass in a JSON object containing an impersonated refresh token'); + } + if (json.type !== impersonated_1.IMPERSONATED_ACCOUNT_TYPE) { + throw new Error(`The incoming JSON object does not have the "${impersonated_1.IMPERSONATED_ACCOUNT_TYPE}" type`); + } + if (!json.source_credentials) { + throw new Error('The incoming JSON object does not contain a source_credentials field'); + } + if (!json.service_account_impersonation_url) { + throw new Error('The incoming JSON object does not contain a service_account_impersonation_url field'); + } + const sourceClient = this.fromJSON(json.source_credentials); + if (((_a = json.service_account_impersonation_url) === null || _a === void 0 ? void 0 : _a.length) > 256) { + /** + * Prevents DOS attacks. + * @see {@link https://github.com/googleapis/google-auth-library-nodejs/security/code-scanning/85} + **/ + throw new RangeError(`Target principal is too long: ${json.service_account_impersonation_url}`); + } + // Extract service account from service_account_impersonation_url + const targetPrincipal = (_c = (_b = /(?[^/]+):(generateAccessToken|generateIdToken)$/.exec(json.service_account_impersonation_url)) === null || _b === void 0 ? void 0 : _b.groups) === null || _c === void 0 ? void 0 : _c.target; + if (!targetPrincipal) { + throw new RangeError(`Cannot extract target principal from ${json.service_account_impersonation_url}`); + } + const targetScopes = (_d = this.getAnyScopes()) !== null && _d !== void 0 ? _d : []; + return new impersonated_1.Impersonated({ + ...json, + sourceClient, + targetPrincipal, + targetScopes: Array.isArray(targetScopes) ? targetScopes : [targetScopes], + }); + } + /** + * Create a credentials instance using the given input options. + * This client is not cached. + * + * **Important**: If you accept a credential configuration (credential JSON/File/Stream) from an external source for authentication to Google Cloud, you must validate it before providing it to any Google API or library. Providing an unvalidated credential configuration to Google APIs can compromise the security of your systems and data. For more information, refer to {@link https://cloud.google.com/docs/authentication/external/externally-sourced-credentials Validate credential configurations from external sources}. + * + * @param json The input object. + * @param options The JWT or UserRefresh options for the client + * @returns JWT or UserRefresh Client with data + */ + fromJSON(json, options = {}) { + let client; + // user's preferred universe domain + const preferredUniverseDomain = (0, util_1.originalOrCamelOptions)(options).get('universe_domain'); + if (json.type === refreshclient_1.USER_REFRESH_ACCOUNT_TYPE) { + client = new refreshclient_1.UserRefreshClient(options); + client.fromJSON(json); + } + else if (json.type === impersonated_1.IMPERSONATED_ACCOUNT_TYPE) { + client = this.fromImpersonatedJSON(json); + } + else if (json.type === baseexternalclient_1.EXTERNAL_ACCOUNT_TYPE) { + client = externalclient_1.ExternalAccountClient.fromJSON(json, options); + client.scopes = this.getAnyScopes(); + } + else if (json.type === externalAccountAuthorizedUserClient_1.EXTERNAL_ACCOUNT_AUTHORIZED_USER_TYPE) { + client = new externalAccountAuthorizedUserClient_1.ExternalAccountAuthorizedUserClient(json, options); + } + else { + options.scopes = this.scopes; + client = new jwtclient_1.JWT(options); + this.setGapicJWTValues(client); + client.fromJSON(json); + } + if (preferredUniverseDomain) { + client.universeDomain = preferredUniverseDomain; + } + return client; + } + /** + * Return a JWT or UserRefreshClient from JavaScript object, caching both the + * object used to instantiate and the client. + * @param json The input object. + * @param options The JWT or UserRefresh options for the client + * @returns JWT or UserRefresh Client with data + */ + _cacheClientFromJSON(json, options) { + const client = this.fromJSON(json, options); + // cache both raw data used to instantiate client and client itself. + this.jsonContent = json; + this.cachedCredential = client; + return client; + } + fromStream(inputStream, optionsOrCallback = {}, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else { + options = optionsOrCallback; + } + if (callback) { + this.fromStreamAsync(inputStream, options).then(r => callback(null, r), callback); + } + else { + return this.fromStreamAsync(inputStream, options); + } + } + fromStreamAsync(inputStream, options) { + return new Promise((resolve, reject) => { + if (!inputStream) { + throw new Error('Must pass in a stream containing the Google auth settings.'); + } + const chunks = []; + inputStream + .setEncoding('utf8') + .on('error', reject) + .on('data', chunk => chunks.push(chunk)) + .on('end', () => { + try { + try { + const data = JSON.parse(chunks.join('')); + const r = this._cacheClientFromJSON(data, options); + return resolve(r); + } + catch (err) { + // If we failed parsing this.keyFileName, assume that it + // is a PEM or p12 certificate: + if (!this.keyFilename) + throw err; + const client = new jwtclient_1.JWT({ + ...this.clientOptions, + keyFile: this.keyFilename, + }); + this.cachedCredential = client; + this.setGapicJWTValues(client); + return resolve(client); + } + } + catch (err) { + return reject(err); + } + }); + }); + } + /** + * Create a credentials instance using the given API key string. + * The created client is not cached. In order to create and cache it use the {@link GoogleAuth.getClient `getClient`} method after first providing an {@link GoogleAuth.apiKey `apiKey`}. + * + * @param apiKey The API key string + * @param options An optional options object. + * @returns A JWT loaded from the key + */ + fromAPIKey(apiKey, options = {}) { + return new jwtclient_1.JWT({ ...options, apiKey }); + } + /** + * Determines whether the current operating system is Windows. + * @api private + */ + _isWindows() { + const sys = os.platform(); + if (sys && sys.length >= 3) { + if (sys.substring(0, 3).toLowerCase() === 'win') { + return true; + } + } + return false; + } + /** + * Run the Google Cloud SDK command that prints the default project ID + */ + async getDefaultServiceProjectId() { + return new Promise(resolve => { + (0, child_process_1.exec)('gcloud config config-helper --format json', (err, stdout) => { + if (!err && stdout) { + try { + const projectId = JSON.parse(stdout).configuration.properties.core.project; + resolve(projectId); + return; + } + catch (e) { + // ignore errors + } + } + resolve(null); + }); + }); + } + /** + * Loads the project id from environment variables. + * @api private + */ + getProductionProjectId() { + return (process.env['GCLOUD_PROJECT'] || + process.env['GOOGLE_CLOUD_PROJECT'] || + process.env['gcloud_project'] || + process.env['google_cloud_project']); + } + /** + * Loads the project id from the GOOGLE_APPLICATION_CREDENTIALS json file. + * @api private + */ + async getFileProjectId() { + if (this.cachedCredential) { + // Try to read the project ID from the cached credentials file + return this.cachedCredential.projectId; + } + // Ensure the projectId is loaded from the keyFile if available. + if (this.keyFilename) { + const creds = await this.getClient(); + if (creds && creds.projectId) { + return creds.projectId; + } + } + // Try to load a credentials file and read its project ID + const r = await this._tryGetApplicationCredentialsFromEnvironmentVariable(); + if (r) { + return r.projectId; + } + else { + return null; + } + } + /** + * Gets the project ID from external account client if available. + */ + async getExternalAccountClientProjectId() { + if (!this.jsonContent || this.jsonContent.type !== baseexternalclient_1.EXTERNAL_ACCOUNT_TYPE) { + return null; + } + const creds = await this.getClient(); + // Do not suppress the underlying error, as the error could contain helpful + // information for debugging and fixing. This is especially true for + // external account creds as in order to get the project ID, the following + // operations have to succeed: + // 1. Valid credentials file should be supplied. + // 2. Ability to retrieve access tokens from STS token exchange API. + // 3. Ability to exchange for service account impersonated credentials (if + // enabled). + // 4. Ability to get project info using the access token from step 2 or 3. + // Without surfacing the error, it is harder for developers to determine + // which step went wrong. + return await creds.getProjectId(); + } + /** + * Gets the Compute Engine project ID if it can be inferred. + */ + async getGCEProjectId() { + try { + const r = await gcpMetadata.project('project-id'); + return r; + } + catch (e) { + // Ignore any errors + return null; + } + } + getCredentials(callback) { + if (callback) { + this.getCredentialsAsync().then(r => callback(null, r), callback); + } + else { + return this.getCredentialsAsync(); + } + } + async getCredentialsAsync() { + const client = await this.getClient(); + if (client instanceof impersonated_1.Impersonated) { + return { client_email: client.getTargetPrincipal() }; + } + if (client instanceof baseexternalclient_1.BaseExternalAccountClient) { + const serviceAccountEmail = client.getServiceAccountEmail(); + if (serviceAccountEmail) { + return { + client_email: serviceAccountEmail, + universe_domain: client.universeDomain, + }; + } + } + if (this.jsonContent) { + return { + client_email: this.jsonContent.client_email, + private_key: this.jsonContent.private_key, + universe_domain: this.jsonContent.universe_domain, + }; + } + if (await this._checkIsGCE()) { + const [client_email, universe_domain] = await Promise.all([ + gcpMetadata.instance('service-accounts/default/email'), + this.getUniverseDomain(), + ]); + return { client_email, universe_domain }; + } + throw new Error(exports.GoogleAuthExceptionMessages.NO_CREDENTIALS_FOUND); + } + /** + * Automatically obtain an {@link AuthClient `AuthClient`} based on the + * provided configuration. If no options were passed, use Application + * Default Credentials. + */ + async getClient() { + if (this.cachedCredential) { + return this.cachedCredential; + } + // Use an existing auth client request, or cache a new one + __classPrivateFieldSet(this, _GoogleAuth_pendingAuthClient, __classPrivateFieldGet(this, _GoogleAuth_pendingAuthClient, "f") || __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_determineClient).call(this), "f"); + try { + return await __classPrivateFieldGet(this, _GoogleAuth_pendingAuthClient, "f"); + } + finally { + // reset the pending auth client in case it is changed later + __classPrivateFieldSet(this, _GoogleAuth_pendingAuthClient, null, "f"); + } + } + /** + * Creates a client which will fetch an ID token for authorization. + * @param targetAudience the audience for the fetched ID token. + * @returns IdTokenClient for making HTTP calls authenticated with ID tokens. + */ + async getIdTokenClient(targetAudience) { + const client = await this.getClient(); + if (!('fetchIdToken' in client)) { + throw new Error('Cannot fetch ID token in this environment, use GCE or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to a service account credentials JSON file.'); + } + return new idtokenclient_1.IdTokenClient({ targetAudience, idTokenProvider: client }); + } + /** + * Automatically obtain application default credentials, and return + * an access token for making requests. + */ + async getAccessToken() { + const client = await this.getClient(); + return (await client.getAccessToken()).token; + } + /** + * Obtain the HTTP headers that will provide authorization for a given + * request. + */ + async getRequestHeaders(url) { + const client = await this.getClient(); + return client.getRequestHeaders(url); + } + /** + * Obtain credentials for a request, then attach the appropriate headers to + * the request options. + * @param opts Axios or Request options on which to attach the headers + */ + async authorizeRequest(opts) { + opts = opts || {}; + const url = opts.url || opts.uri; + const client = await this.getClient(); + const headers = await client.getRequestHeaders(url); + opts.headers = Object.assign(opts.headers || {}, headers); + return opts; + } + /** + * Automatically obtain application default credentials, and make an + * HTTP request using the given options. + * @param opts Axios request options for the HTTP request. + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async request(opts) { + const client = await this.getClient(); + return client.request(opts); + } + /** + * Determine the compute environment in which the code is running. + */ + getEnv() { + return (0, envDetect_1.getEnv)(); + } + /** + * Sign the given data with the current private key, or go out + * to the IAM API to sign it. + * @param data The data to be signed. + * @param endpoint A custom endpoint to use. + * + * @example + * ``` + * sign('data', 'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/'); + * ``` + */ + async sign(data, endpoint) { + const client = await this.getClient(); + const universe = await this.getUniverseDomain(); + endpoint = + endpoint || + `https://iamcredentials.${universe}/v1/projects/-/serviceAccounts/`; + if (client instanceof impersonated_1.Impersonated) { + const signed = await client.sign(data); + return signed.signedBlob; + } + const crypto = (0, crypto_1.createCrypto)(); + if (client instanceof jwtclient_1.JWT && client.key) { + const sign = await crypto.sign(client.key, data); + return sign; + } + const creds = await this.getCredentials(); + if (!creds.client_email) { + throw new Error('Cannot sign data without `client_email`.'); + } + return this.signBlob(crypto, creds.client_email, data, endpoint); + } + async signBlob(crypto, emailOrUniqueId, data, endpoint) { + const url = new URL(endpoint + `${emailOrUniqueId}:signBlob`); + const res = await this.request({ + method: 'POST', + url: url.href, + data: { + payload: crypto.encodeBase64StringUtf8(data), + }, + retry: true, + retryConfig: { + httpMethodsToRetry: ['POST'], + }, + }); + return res.data.signedBlob; + } +} +exports.GoogleAuth = GoogleAuth; +_GoogleAuth_pendingAuthClient = new WeakMap(), _GoogleAuth_instances = new WeakSet(), _GoogleAuth_prepareAndCacheClient = async function _GoogleAuth_prepareAndCacheClient(credential, quotaProjectIdOverride = process.env['GOOGLE_CLOUD_QUOTA_PROJECT'] || null) { + const projectId = await this.getProjectIdOptional(); + if (quotaProjectIdOverride) { + credential.quotaProjectId = quotaProjectIdOverride; + } + this.cachedCredential = credential; + return { credential, projectId }; +}, _GoogleAuth_determineClient = async function _GoogleAuth_determineClient() { + if (this.jsonContent) { + return this._cacheClientFromJSON(this.jsonContent, this.clientOptions); + } + else if (this.keyFilename) { + const filePath = path.resolve(this.keyFilename); + const stream = fs.createReadStream(filePath); + return await this.fromStreamAsync(stream, this.clientOptions); + } + else if (this.apiKey) { + const client = await this.fromAPIKey(this.apiKey, this.clientOptions); + client.scopes = this.scopes; + const { credential } = await __classPrivateFieldGet(this, _GoogleAuth_instances, "m", _GoogleAuth_prepareAndCacheClient).call(this, client); + return credential; + } + else { + const { credential } = await this.getApplicationDefaultAsync(this.clientOptions); + return credential; + } +}; +/** + * Export DefaultTransporter as a static property of the class. + */ +GoogleAuth.DefaultTransporter = transporters_1.DefaultTransporter; + + +/***/ }), + +/***/ 89390: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2014 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IAMAuth = void 0; +class IAMAuth { + /** + * IAM credentials. + * + * @param selector the iam authority selector + * @param token the token + * @constructor + */ + constructor(selector, token) { + this.selector = selector; + this.token = token; + this.selector = selector; + this.token = token; + } + /** + * Acquire the HTTP headers required to make an authenticated request. + */ + getRequestHeaders() { + return { + 'x-goog-iam-authority-selector': this.selector, + 'x-goog-iam-authorization-token': this.token, + }; + } +} +exports.IAMAuth = IAMAuth; + + +/***/ }), + +/***/ 29960: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IdentityPoolClient = void 0; +const baseexternalclient_1 = __nccwpck_require__(142); +const util_1 = __nccwpck_require__(37870); +const filesubjecttokensupplier_1 = __nccwpck_require__(10932); +const urlsubjecttokensupplier_1 = __nccwpck_require__(24627); +/** + * Defines the Url-sourced and file-sourced external account clients mainly + * used for K8s and Azure workloads. + */ +class IdentityPoolClient extends baseexternalclient_1.BaseExternalAccountClient { + /** + * Instantiate an IdentityPoolClient instance using the provided JSON + * object loaded from an external account credentials file. + * An error is thrown if the credential is not a valid file-sourced or + * url-sourced credential or a workforce pool user project is provided + * with a non workforce audience. + * @param options The external account options object typically loaded + * from the external account JSON credential file. The camelCased options + * are aliases for the snake_cased options. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + super(options, additionalOptions); + const opts = (0, util_1.originalOrCamelOptions)(options); + const credentialSource = opts.get('credential_source'); + const subjectTokenSupplier = opts.get('subject_token_supplier'); + // Validate credential sourcing configuration. + if (!credentialSource && !subjectTokenSupplier) { + throw new Error('A credential source or subject token supplier must be specified.'); + } + if (credentialSource && subjectTokenSupplier) { + throw new Error('Only one of credential source or subject token supplier can be specified.'); + } + if (subjectTokenSupplier) { + this.subjectTokenSupplier = subjectTokenSupplier; + this.credentialSourceType = 'programmatic'; + } + else { + const credentialSourceOpts = (0, util_1.originalOrCamelOptions)(credentialSource); + const formatOpts = (0, util_1.originalOrCamelOptions)(credentialSourceOpts.get('format')); + // Text is the default format type. + const formatType = formatOpts.get('type') || 'text'; + const formatSubjectTokenFieldName = formatOpts.get('subject_token_field_name'); + if (formatType !== 'json' && formatType !== 'text') { + throw new Error(`Invalid credential_source format "${formatType}"`); + } + if (formatType === 'json' && !formatSubjectTokenFieldName) { + throw new Error('Missing subject_token_field_name for JSON credential_source format'); + } + const file = credentialSourceOpts.get('file'); + const url = credentialSourceOpts.get('url'); + const headers = credentialSourceOpts.get('headers'); + if (file && url) { + throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.'); + } + else if (file && !url) { + this.credentialSourceType = 'file'; + this.subjectTokenSupplier = new filesubjecttokensupplier_1.FileSubjectTokenSupplier({ + filePath: file, + formatType: formatType, + subjectTokenFieldName: formatSubjectTokenFieldName, + }); + } + else if (!file && url) { + this.credentialSourceType = 'url'; + this.subjectTokenSupplier = new urlsubjecttokensupplier_1.UrlSubjectTokenSupplier({ + url: url, + formatType: formatType, + subjectTokenFieldName: formatSubjectTokenFieldName, + headers: headers, + additionalGaxiosOptions: IdentityPoolClient.RETRY_CONFIG, + }); + } + else { + throw new Error('No valid Identity Pool "credential_source" provided, must be either file or url.'); + } + } + } + /** + * Triggered when a external subject token is needed to be exchanged for a GCP + * access token via GCP STS endpoint. Gets a subject token by calling + * the configured {@link SubjectTokenSupplier} + * @return A promise that resolves with the external subject token. + */ + async retrieveSubjectToken() { + return this.subjectTokenSupplier.getSubjectToken(this.supplierContext); + } +} +exports.IdentityPoolClient = IdentityPoolClient; + + +/***/ }), + +/***/ 12718: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.IdTokenClient = void 0; +const oauth2client_1 = __nccwpck_require__(10091); +class IdTokenClient extends oauth2client_1.OAuth2Client { + /** + * Google ID Token client + * + * Retrieve ID token from the metadata server. + * See: https://cloud.google.com/docs/authentication/get-id-token#metadata-server + */ + constructor(options) { + super(options); + this.targetAudience = options.targetAudience; + this.idTokenProvider = options.idTokenProvider; + } + async getRequestMetadataAsync( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + url) { + if (!this.credentials.id_token || + !this.credentials.expiry_date || + this.isTokenExpiring()) { + const idToken = await this.idTokenProvider.fetchIdToken(this.targetAudience); + this.credentials = { + id_token: idToken, + expiry_date: this.getIdTokenExpiryDate(idToken), + }; + } + const headers = { + Authorization: 'Bearer ' + this.credentials.id_token, + }; + return { headers }; + } + getIdTokenExpiryDate(idToken) { + const payloadB64 = idToken.split('.')[1]; + if (payloadB64) { + const payload = JSON.parse(Buffer.from(payloadB64, 'base64').toString('ascii')); + return payload.exp * 1000; + } + } +} +exports.IdTokenClient = IdTokenClient; + + +/***/ }), + +/***/ 39964: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Impersonated = exports.IMPERSONATED_ACCOUNT_TYPE = void 0; +const oauth2client_1 = __nccwpck_require__(10091); +const gaxios_1 = __nccwpck_require__(97003); +const util_1 = __nccwpck_require__(37870); +exports.IMPERSONATED_ACCOUNT_TYPE = 'impersonated_service_account'; +class Impersonated extends oauth2client_1.OAuth2Client { + /** + * Impersonated service account credentials. + * + * Create a new access token by impersonating another service account. + * + * Impersonated Credentials allowing credentials issued to a user or + * service account to impersonate another. The source project using + * Impersonated Credentials must enable the "IAMCredentials" API. + * Also, the target service account must grant the orginating principal + * the "Service Account Token Creator" IAM role. + * + * @param {object} options - The configuration object. + * @param {object} [options.sourceClient] the source credential used as to + * acquire the impersonated credentials. + * @param {string} [options.targetPrincipal] the service account to + * impersonate. + * @param {string[]} [options.delegates] the chained list of delegates + * required to grant the final access_token. If set, the sequence of + * identities must have "Service Account Token Creator" capability granted to + * the preceding identity. For example, if set to [serviceAccountB, + * serviceAccountC], the sourceCredential must have the Token Creator role on + * serviceAccountB. serviceAccountB must have the Token Creator on + * serviceAccountC. Finally, C must have Token Creator on target_principal. + * If left unset, sourceCredential must have that role on targetPrincipal. + * @param {string[]} [options.targetScopes] scopes to request during the + * authorization grant. + * @param {number} [options.lifetime] number of seconds the delegated + * credential should be valid for up to 3600 seconds by default, or 43,200 + * seconds by extending the token's lifetime, see: + * https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials#sa-credentials-oauth + * @param {string} [options.endpoint] api endpoint override. + */ + constructor(options = {}) { + var _a, _b, _c, _d, _e, _f; + super(options); + // Start with an expired refresh token, which will automatically be + // refreshed before the first API call is made. + this.credentials = { + expiry_date: 1, + refresh_token: 'impersonated-placeholder', + }; + this.sourceClient = (_a = options.sourceClient) !== null && _a !== void 0 ? _a : new oauth2client_1.OAuth2Client(); + this.targetPrincipal = (_b = options.targetPrincipal) !== null && _b !== void 0 ? _b : ''; + this.delegates = (_c = options.delegates) !== null && _c !== void 0 ? _c : []; + this.targetScopes = (_d = options.targetScopes) !== null && _d !== void 0 ? _d : []; + this.lifetime = (_e = options.lifetime) !== null && _e !== void 0 ? _e : 3600; + const usingExplicitUniverseDomain = !!(0, util_1.originalOrCamelOptions)(options).get('universe_domain'); + if (!usingExplicitUniverseDomain) { + // override the default universe with the source's universe + this.universeDomain = this.sourceClient.universeDomain; + } + else if (this.sourceClient.universeDomain !== this.universeDomain) { + // non-default universe and is not matching the source - this could be a credential leak + throw new RangeError(`Universe domain ${this.sourceClient.universeDomain} in source credentials does not match ${this.universeDomain} universe domain set for impersonated credentials.`); + } + this.endpoint = + (_f = options.endpoint) !== null && _f !== void 0 ? _f : `https://iamcredentials.${this.universeDomain}`; + } + /** + * Signs some bytes. + * + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob Reference Documentation} + * @param blobToSign String to sign. + * + * @returns A {@link SignBlobResponse} denoting the keyID and signedBlob in base64 string + */ + async sign(blobToSign) { + await this.sourceClient.getAccessToken(); + const name = `projects/-/serviceAccounts/${this.targetPrincipal}`; + const u = `${this.endpoint}/v1/${name}:signBlob`; + const body = { + delegates: this.delegates, + payload: Buffer.from(blobToSign).toString('base64'), + }; + const res = await this.sourceClient.request({ + ...Impersonated.RETRY_CONFIG, + url: u, + data: body, + method: 'POST', + }); + return res.data; + } + /** The service account email to be impersonated. */ + getTargetPrincipal() { + return this.targetPrincipal; + } + /** + * Refreshes the access token. + */ + async refreshToken() { + var _a, _b, _c, _d, _e, _f; + try { + await this.sourceClient.getAccessToken(); + const name = 'projects/-/serviceAccounts/' + this.targetPrincipal; + const u = `${this.endpoint}/v1/${name}:generateAccessToken`; + const body = { + delegates: this.delegates, + scope: this.targetScopes, + lifetime: this.lifetime + 's', + }; + const res = await this.sourceClient.request({ + ...Impersonated.RETRY_CONFIG, + url: u, + data: body, + method: 'POST', + }); + const tokenResponse = res.data; + this.credentials.access_token = tokenResponse.accessToken; + this.credentials.expiry_date = Date.parse(tokenResponse.expireTime); + return { + tokens: this.credentials, + res, + }; + } + catch (error) { + if (!(error instanceof Error)) + throw error; + let status = 0; + let message = ''; + if (error instanceof gaxios_1.GaxiosError) { + status = (_c = (_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.status; + message = (_f = (_e = (_d = error === null || error === void 0 ? void 0 : error.response) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.error) === null || _f === void 0 ? void 0 : _f.message; + } + if (status && message) { + error.message = `${status}: unable to impersonate: ${message}`; + throw error; + } + else { + error.message = `unable to impersonate: ${error}`; + throw error; + } + } + } + /** + * Generates an OpenID Connect ID token for a service account. + * + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateIdToken Reference Documentation} + * + * @param targetAudience the audience for the fetched ID token. + * @param options the for the request + * @return an OpenID Connect ID token + */ + async fetchIdToken(targetAudience, options) { + var _a, _b; + await this.sourceClient.getAccessToken(); + const name = `projects/-/serviceAccounts/${this.targetPrincipal}`; + const u = `${this.endpoint}/v1/${name}:generateIdToken`; + const body = { + delegates: this.delegates, + audience: targetAudience, + includeEmail: (_a = options === null || options === void 0 ? void 0 : options.includeEmail) !== null && _a !== void 0 ? _a : true, + useEmailAzp: (_b = options === null || options === void 0 ? void 0 : options.includeEmail) !== null && _b !== void 0 ? _b : true, + }; + const res = await this.sourceClient.request({ + ...Impersonated.RETRY_CONFIG, + url: u, + data: body, + method: 'POST', + }); + return res.data.token; + } +} +exports.Impersonated = Impersonated; + + +/***/ }), + +/***/ 27060: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2015 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.JWTAccess = void 0; +const jws = __nccwpck_require__(33324); +const util_1 = __nccwpck_require__(37870); +const DEFAULT_HEADER = { + alg: 'RS256', + typ: 'JWT', +}; +class JWTAccess { + /** + * JWTAccess service account credentials. + * + * Create a new access token by using the credential to create a new JWT token + * that's recognized as the access token. + * + * @param email the service account email address. + * @param key the private key that will be used to sign the token. + * @param keyId the ID of the private key used to sign the token. + */ + constructor(email, key, keyId, eagerRefreshThresholdMillis) { + this.cache = new util_1.LRUCache({ + capacity: 500, + maxAge: 60 * 60 * 1000, + }); + this.email = email; + this.key = key; + this.keyId = keyId; + this.eagerRefreshThresholdMillis = + eagerRefreshThresholdMillis !== null && eagerRefreshThresholdMillis !== void 0 ? eagerRefreshThresholdMillis : 5 * 60 * 1000; + } + /** + * Ensures that we're caching a key appropriately, giving precedence to scopes vs. url + * + * @param url The URI being authorized. + * @param scopes The scope or scopes being authorized + * @returns A string that returns the cached key. + */ + getCachedKey(url, scopes) { + let cacheKey = url; + if (scopes && Array.isArray(scopes) && scopes.length) { + cacheKey = url ? `${url}_${scopes.join('_')}` : `${scopes.join('_')}`; + } + else if (typeof scopes === 'string') { + cacheKey = url ? `${url}_${scopes}` : scopes; + } + if (!cacheKey) { + throw Error('Scopes or url must be provided'); + } + return cacheKey; + } + /** + * Get a non-expired access token, after refreshing if necessary. + * + * @param url The URI being authorized. + * @param additionalClaims An object with a set of additional claims to + * include in the payload. + * @returns An object that includes the authorization header. + */ + getRequestHeaders(url, additionalClaims, scopes) { + // Return cached authorization headers, unless we are within + // eagerRefreshThresholdMillis ms of them expiring: + const key = this.getCachedKey(url, scopes); + const cachedToken = this.cache.get(key); + const now = Date.now(); + if (cachedToken && + cachedToken.expiration - now > this.eagerRefreshThresholdMillis) { + return cachedToken.headers; + } + const iat = Math.floor(Date.now() / 1000); + const exp = JWTAccess.getExpirationTime(iat); + let defaultClaims; + // Turn scopes into space-separated string + if (Array.isArray(scopes)) { + scopes = scopes.join(' '); + } + // If scopes are specified, sign with scopes + if (scopes) { + defaultClaims = { + iss: this.email, + sub: this.email, + scope: scopes, + exp, + iat, + }; + } + else { + defaultClaims = { + iss: this.email, + sub: this.email, + aud: url, + exp, + iat, + }; + } + // if additionalClaims are provided, ensure they do not collide with + // other required claims. + if (additionalClaims) { + for (const claim in defaultClaims) { + if (additionalClaims[claim]) { + throw new Error(`The '${claim}' property is not allowed when passing additionalClaims. This claim is included in the JWT by default.`); + } + } + } + const header = this.keyId + ? { ...DEFAULT_HEADER, kid: this.keyId } + : DEFAULT_HEADER; + const payload = Object.assign(defaultClaims, additionalClaims); + // Sign the jwt and add it to the cache + const signedJWT = jws.sign({ header, payload, secret: this.key }); + const headers = { Authorization: `Bearer ${signedJWT}` }; + this.cache.set(key, { + expiration: exp * 1000, + headers, + }); + return headers; + } + /** + * Returns an expiration time for the JWT token. + * + * @param iat The issued at time for the JWT. + * @returns An expiration time for the JWT. + */ + static getExpirationTime(iat) { + const exp = iat + 3600; // 3600 seconds = 1 hour + return exp; + } + /** + * Create a JWTAccess credentials instance using the given input options. + * @param json The input object. + */ + fromJSON(json) { + if (!json) { + throw new Error('Must pass in a JSON object containing the service account auth settings.'); + } + if (!json.client_email) { + throw new Error('The incoming JSON object does not contain a client_email field'); + } + if (!json.private_key) { + throw new Error('The incoming JSON object does not contain a private_key field'); + } + // Extract the relevant information from the json key file. + this.email = json.client_email; + this.key = json.private_key; + this.keyId = json.private_key_id; + this.projectId = json.project_id; + } + fromStream(inputStream, callback) { + if (callback) { + this.fromStreamAsync(inputStream).then(() => callback(), callback); + } + else { + return this.fromStreamAsync(inputStream); + } + } + fromStreamAsync(inputStream) { + return new Promise((resolve, reject) => { + if (!inputStream) { + reject(new Error('Must pass in a stream containing the service account auth settings.')); + } + let s = ''; + inputStream + .setEncoding('utf8') + .on('data', chunk => (s += chunk)) + .on('error', reject) + .on('end', () => { + try { + const data = JSON.parse(s); + this.fromJSON(data); + resolve(); + } + catch (err) { + reject(err); + } + }); + }); + } +} +exports.JWTAccess = JWTAccess; + + +/***/ }), + +/***/ 75277: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2013 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.JWT = void 0; +const gtoken_1 = __nccwpck_require__(28568); +const jwtaccess_1 = __nccwpck_require__(27060); +const oauth2client_1 = __nccwpck_require__(10091); +const authclient_1 = __nccwpck_require__(34810); +class JWT extends oauth2client_1.OAuth2Client { + constructor(optionsOrEmail, keyFile, key, scopes, subject, keyId) { + const opts = optionsOrEmail && typeof optionsOrEmail === 'object' + ? optionsOrEmail + : { email: optionsOrEmail, keyFile, key, keyId, scopes, subject }; + super(opts); + this.email = opts.email; + this.keyFile = opts.keyFile; + this.key = opts.key; + this.keyId = opts.keyId; + this.scopes = opts.scopes; + this.subject = opts.subject; + this.additionalClaims = opts.additionalClaims; + // Start with an expired refresh token, which will automatically be + // refreshed before the first API call is made. + this.credentials = { refresh_token: 'jwt-placeholder', expiry_date: 1 }; + } + /** + * Creates a copy of the credential with the specified scopes. + * @param scopes List of requested scopes or a single scope. + * @return The cloned instance. + */ + createScoped(scopes) { + const jwt = new JWT(this); + jwt.scopes = scopes; + return jwt; + } + /** + * Obtains the metadata to be sent with the request. + * + * @param url the URI being authorized. + */ + async getRequestMetadataAsync(url) { + url = this.defaultServicePath ? `https://${this.defaultServicePath}/` : url; + const useSelfSignedJWT = (!this.hasUserScopes() && url) || + (this.useJWTAccessWithScope && this.hasAnyScopes()) || + this.universeDomain !== authclient_1.DEFAULT_UNIVERSE; + if (this.subject && this.universeDomain !== authclient_1.DEFAULT_UNIVERSE) { + throw new RangeError(`Service Account user is configured for the credential. Domain-wide delegation is not supported in universes other than ${authclient_1.DEFAULT_UNIVERSE}`); + } + if (!this.apiKey && useSelfSignedJWT) { + if (this.additionalClaims && + this.additionalClaims.target_audience) { + const { tokens } = await this.refreshToken(); + return { + headers: this.addSharedMetadataHeaders({ + Authorization: `Bearer ${tokens.id_token}`, + }), + }; + } + else { + // no scopes have been set, but a uri has been provided. Use JWTAccess + // credentials. + if (!this.access) { + this.access = new jwtaccess_1.JWTAccess(this.email, this.key, this.keyId, this.eagerRefreshThresholdMillis); + } + let scopes; + if (this.hasUserScopes()) { + scopes = this.scopes; + } + else if (!url) { + scopes = this.defaultScopes; + } + const useScopes = this.useJWTAccessWithScope || + this.universeDomain !== authclient_1.DEFAULT_UNIVERSE; + const headers = await this.access.getRequestHeaders(url !== null && url !== void 0 ? url : undefined, this.additionalClaims, + // Scopes take precedent over audience for signing, + // so we only provide them if `useJWTAccessWithScope` is on or + // if we are in a non-default universe + useScopes ? scopes : undefined); + return { headers: this.addSharedMetadataHeaders(headers) }; + } + } + else if (this.hasAnyScopes() || this.apiKey) { + return super.getRequestMetadataAsync(url); + } + else { + // If no audience, apiKey, or scopes are provided, we should not attempt + // to populate any headers: + return { headers: {} }; + } + } + /** + * Fetches an ID token. + * @param targetAudience the audience for the fetched ID token. + */ + async fetchIdToken(targetAudience) { + // Create a new gToken for fetching an ID token + const gtoken = new gtoken_1.GoogleToken({ + iss: this.email, + sub: this.subject, + scope: this.scopes || this.defaultScopes, + keyFile: this.keyFile, + key: this.key, + additionalClaims: { target_audience: targetAudience }, + transporter: this.transporter, + }); + await gtoken.getToken({ + forceRefresh: true, + }); + if (!gtoken.idToken) { + throw new Error('Unknown error: Failed to fetch ID token'); + } + return gtoken.idToken; + } + /** + * Determine if there are currently scopes available. + */ + hasUserScopes() { + if (!this.scopes) { + return false; + } + return this.scopes.length > 0; + } + /** + * Are there any default or user scopes defined. + */ + hasAnyScopes() { + if (this.scopes && this.scopes.length > 0) + return true; + if (this.defaultScopes && this.defaultScopes.length > 0) + return true; + return false; + } + authorize(callback) { + if (callback) { + this.authorizeAsync().then(r => callback(null, r), callback); + } + else { + return this.authorizeAsync(); + } + } + async authorizeAsync() { + const result = await this.refreshToken(); + if (!result) { + throw new Error('No result returned'); + } + this.credentials = result.tokens; + this.credentials.refresh_token = 'jwt-placeholder'; + this.key = this.gtoken.key; + this.email = this.gtoken.iss; + return result.tokens; + } + /** + * Refreshes the access token. + * @param refreshToken ignored + * @private + */ + async refreshTokenNoCache( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + refreshToken) { + const gtoken = this.createGToken(); + const token = await gtoken.getToken({ + forceRefresh: this.isTokenExpiring(), + }); + const tokens = { + access_token: token.access_token, + token_type: 'Bearer', + expiry_date: gtoken.expiresAt, + id_token: gtoken.idToken, + }; + this.emit('tokens', tokens); + return { res: null, tokens }; + } + /** + * Create a gToken if it doesn't already exist. + */ + createGToken() { + if (!this.gtoken) { + this.gtoken = new gtoken_1.GoogleToken({ + iss: this.email, + sub: this.subject, + scope: this.scopes || this.defaultScopes, + keyFile: this.keyFile, + key: this.key, + additionalClaims: this.additionalClaims, + transporter: this.transporter, + }); + } + return this.gtoken; + } + /** + * Create a JWT credentials instance using the given input options. + * @param json The input object. + * + * @remarks + * + * **Important**: If you accept a credential configuration (credential JSON/File/Stream) from an external source for authentication to Google Cloud, you must validate it before providing it to any Google API or library. Providing an unvalidated credential configuration to Google APIs can compromise the security of your systems and data. For more information, refer to {@link https://cloud.google.com/docs/authentication/external/externally-sourced-credentials Validate credential configurations from external sources}. + */ + fromJSON(json) { + if (!json) { + throw new Error('Must pass in a JSON object containing the service account auth settings.'); + } + if (!json.client_email) { + throw new Error('The incoming JSON object does not contain a client_email field'); + } + if (!json.private_key) { + throw new Error('The incoming JSON object does not contain a private_key field'); + } + // Extract the relevant information from the json key file. + this.email = json.client_email; + this.key = json.private_key; + this.keyId = json.private_key_id; + this.projectId = json.project_id; + this.quotaProjectId = json.quota_project_id; + this.universeDomain = json.universe_domain || this.universeDomain; + } + fromStream(inputStream, callback) { + if (callback) { + this.fromStreamAsync(inputStream).then(() => callback(), callback); + } + else { + return this.fromStreamAsync(inputStream); + } + } + fromStreamAsync(inputStream) { + return new Promise((resolve, reject) => { + if (!inputStream) { + throw new Error('Must pass in a stream containing the service account auth settings.'); + } + let s = ''; + inputStream + .setEncoding('utf8') + .on('error', reject) + .on('data', chunk => (s += chunk)) + .on('end', () => { + try { + const data = JSON.parse(s); + this.fromJSON(data); + resolve(); + } + catch (e) { + reject(e); + } + }); + }); + } + /** + * Creates a JWT credentials instance using an API Key for authentication. + * @param apiKey The API Key in string form. + */ + fromAPIKey(apiKey) { + if (typeof apiKey !== 'string') { + throw new Error('Must provide an API Key string.'); + } + this.apiKey = apiKey; + } + /** + * Using the key or keyFile on the JWT client, obtain an object that contains + * the key and the client email. + */ + async getCredentials() { + if (this.key) { + return { private_key: this.key, client_email: this.email }; + } + else if (this.keyFile) { + const gtoken = this.createGToken(); + const creds = await gtoken.getCredentials(this.keyFile); + return { private_key: creds.privateKey, client_email: creds.clientEmail }; + } + throw new Error('A key or a keyFile must be provided to getCredentials.'); + } +} +exports.JWT = JWT; + + +/***/ }), + +/***/ 53882: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2014 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.LoginTicket = void 0; +class LoginTicket { + /** + * Create a simple class to extract user ID from an ID Token + * + * @param {string} env Envelope of the jwt + * @param {TokenPayload} pay Payload of the jwt + * @constructor + */ + constructor(env, pay) { + this.envelope = env; + this.payload = pay; + } + getEnvelope() { + return this.envelope; + } + getPayload() { + return this.payload; + } + /** + * Create a simple class to extract user ID from an ID Token + * + * @return The user ID + */ + getUserId() { + const payload = this.getPayload(); + if (payload && payload.sub) { + return payload.sub; + } + return null; + } + /** + * Returns attributes from the login ticket. This can contain + * various information about the user session. + * + * @return The envelope and payload + */ + getAttributes() { + return { envelope: this.getEnvelope(), payload: this.getPayload() }; + } +} +exports.LoginTicket = LoginTicket; + + +/***/ }), + +/***/ 10091: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OAuth2Client = exports.ClientAuthentication = exports.CertificateFormat = exports.CodeChallengeMethod = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const querystring = __nccwpck_require__(83480); +const stream = __nccwpck_require__(2203); +const formatEcdsa = __nccwpck_require__(325); +const crypto_1 = __nccwpck_require__(88851); +const authclient_1 = __nccwpck_require__(34810); +const loginticket_1 = __nccwpck_require__(53882); +var CodeChallengeMethod; +(function (CodeChallengeMethod) { + CodeChallengeMethod["Plain"] = "plain"; + CodeChallengeMethod["S256"] = "S256"; +})(CodeChallengeMethod || (exports.CodeChallengeMethod = CodeChallengeMethod = {})); +var CertificateFormat; +(function (CertificateFormat) { + CertificateFormat["PEM"] = "PEM"; + CertificateFormat["JWK"] = "JWK"; +})(CertificateFormat || (exports.CertificateFormat = CertificateFormat = {})); +/** + * The client authentication type. Supported values are basic, post, and none. + * https://datatracker.ietf.org/doc/html/rfc7591#section-2 + */ +var ClientAuthentication; +(function (ClientAuthentication) { + ClientAuthentication["ClientSecretPost"] = "ClientSecretPost"; + ClientAuthentication["ClientSecretBasic"] = "ClientSecretBasic"; + ClientAuthentication["None"] = "None"; +})(ClientAuthentication || (exports.ClientAuthentication = ClientAuthentication = {})); +class OAuth2Client extends authclient_1.AuthClient { + constructor(optionsOrClientId, clientSecret, redirectUri) { + const opts = optionsOrClientId && typeof optionsOrClientId === 'object' + ? optionsOrClientId + : { clientId: optionsOrClientId, clientSecret, redirectUri }; + super(opts); + this.certificateCache = {}; + this.certificateExpiry = null; + this.certificateCacheFormat = CertificateFormat.PEM; + this.refreshTokenPromises = new Map(); + this._clientId = opts.clientId; + this._clientSecret = opts.clientSecret; + this.redirectUri = opts.redirectUri; + this.endpoints = { + tokenInfoUrl: 'https://oauth2.googleapis.com/tokeninfo', + oauth2AuthBaseUrl: 'https://accounts.google.com/o/oauth2/v2/auth', + oauth2TokenUrl: 'https://oauth2.googleapis.com/token', + oauth2RevokeUrl: 'https://oauth2.googleapis.com/revoke', + oauth2FederatedSignonPemCertsUrl: 'https://www.googleapis.com/oauth2/v1/certs', + oauth2FederatedSignonJwkCertsUrl: 'https://www.googleapis.com/oauth2/v3/certs', + oauth2IapPublicKeyUrl: 'https://www.gstatic.com/iap/verify/public_key', + ...opts.endpoints, + }; + this.clientAuthentication = + opts.clientAuthentication || ClientAuthentication.ClientSecretPost; + this.issuers = opts.issuers || [ + 'accounts.google.com', + 'https://accounts.google.com', + this.universeDomain, + ]; + } + /** + * Generates URL for consent page landing. + * @param opts Options. + * @return URL to consent page. + */ + generateAuthUrl(opts = {}) { + if (opts.code_challenge_method && !opts.code_challenge) { + throw new Error('If a code_challenge_method is provided, code_challenge must be included.'); + } + opts.response_type = opts.response_type || 'code'; + opts.client_id = opts.client_id || this._clientId; + opts.redirect_uri = opts.redirect_uri || this.redirectUri; + // Allow scopes to be passed either as array or a string + if (Array.isArray(opts.scope)) { + opts.scope = opts.scope.join(' '); + } + const rootUrl = this.endpoints.oauth2AuthBaseUrl.toString(); + return (rootUrl + + '?' + + querystring.stringify(opts)); + } + generateCodeVerifier() { + // To make the code compatible with browser SubtleCrypto we need to make + // this method async. + throw new Error('generateCodeVerifier is removed, please use generateCodeVerifierAsync instead.'); + } + /** + * Convenience method to automatically generate a code_verifier, and its + * resulting SHA256. If used, this must be paired with a S256 + * code_challenge_method. + * + * For a full example see: + * https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/oauth2-codeVerifier.js + */ + async generateCodeVerifierAsync() { + // base64 encoding uses 6 bits per character, and we want to generate128 + // characters. 6*128/8 = 96. + const crypto = (0, crypto_1.createCrypto)(); + const randomString = crypto.randomBytesBase64(96); + // The valid characters in the code_verifier are [A-Z]/[a-z]/[0-9]/ + // "-"/"."/"_"/"~". Base64 encoded strings are pretty close, so we're just + // swapping out a few chars. + const codeVerifier = randomString + .replace(/\+/g, '~') + .replace(/=/g, '_') + .replace(/\//g, '-'); + // Generate the base64 encoded SHA256 + const unencodedCodeChallenge = await crypto.sha256DigestBase64(codeVerifier); + // We need to use base64UrlEncoding instead of standard base64 + const codeChallenge = unencodedCodeChallenge + .split('=')[0] + .replace(/\+/g, '-') + .replace(/\//g, '_'); + return { codeVerifier, codeChallenge }; + } + getToken(codeOrOptions, callback) { + const options = typeof codeOrOptions === 'string' ? { code: codeOrOptions } : codeOrOptions; + if (callback) { + this.getTokenAsync(options).then(r => callback(null, r.tokens, r.res), e => callback(e, null, e.response)); + } + else { + return this.getTokenAsync(options); + } + } + async getTokenAsync(options) { + const url = this.endpoints.oauth2TokenUrl.toString(); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + }; + const values = { + client_id: options.client_id || this._clientId, + code_verifier: options.codeVerifier, + code: options.code, + grant_type: 'authorization_code', + redirect_uri: options.redirect_uri || this.redirectUri, + }; + if (this.clientAuthentication === ClientAuthentication.ClientSecretBasic) { + const basic = Buffer.from(`${this._clientId}:${this._clientSecret}`); + headers['Authorization'] = `Basic ${basic.toString('base64')}`; + } + if (this.clientAuthentication === ClientAuthentication.ClientSecretPost) { + values.client_secret = this._clientSecret; + } + const res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + method: 'POST', + url, + data: querystring.stringify(values), + headers, + }); + const tokens = res.data; + if (res.data && res.data.expires_in) { + tokens.expiry_date = new Date().getTime() + res.data.expires_in * 1000; + delete tokens.expires_in; + } + this.emit('tokens', tokens); + return { tokens, res }; + } + /** + * Refreshes the access token. + * @param refresh_token Existing refresh token. + * @private + */ + async refreshToken(refreshToken) { + if (!refreshToken) { + return this.refreshTokenNoCache(refreshToken); + } + // If a request to refresh using the same token has started, + // return the same promise. + if (this.refreshTokenPromises.has(refreshToken)) { + return this.refreshTokenPromises.get(refreshToken); + } + const p = this.refreshTokenNoCache(refreshToken).then(r => { + this.refreshTokenPromises.delete(refreshToken); + return r; + }, e => { + this.refreshTokenPromises.delete(refreshToken); + throw e; + }); + this.refreshTokenPromises.set(refreshToken, p); + return p; + } + async refreshTokenNoCache(refreshToken) { + var _a; + if (!refreshToken) { + throw new Error('No refresh token is set.'); + } + const url = this.endpoints.oauth2TokenUrl.toString(); + const data = { + refresh_token: refreshToken, + client_id: this._clientId, + client_secret: this._clientSecret, + grant_type: 'refresh_token', + }; + let res; + try { + // request for new token + res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + method: 'POST', + url, + data: querystring.stringify(data), + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + }); + } + catch (e) { + if (e instanceof gaxios_1.GaxiosError && + e.message === 'invalid_grant' && + ((_a = e.response) === null || _a === void 0 ? void 0 : _a.data) && + /ReAuth/i.test(e.response.data.error_description)) { + e.message = JSON.stringify(e.response.data); + } + throw e; + } + const tokens = res.data; + // TODO: de-duplicate this code from a few spots + if (res.data && res.data.expires_in) { + tokens.expiry_date = new Date().getTime() + res.data.expires_in * 1000; + delete tokens.expires_in; + } + this.emit('tokens', tokens); + return { tokens, res }; + } + refreshAccessToken(callback) { + if (callback) { + this.refreshAccessTokenAsync().then(r => callback(null, r.credentials, r.res), callback); + } + else { + return this.refreshAccessTokenAsync(); + } + } + async refreshAccessTokenAsync() { + const r = await this.refreshToken(this.credentials.refresh_token); + const tokens = r.tokens; + tokens.refresh_token = this.credentials.refresh_token; + this.credentials = tokens; + return { credentials: this.credentials, res: r.res }; + } + getAccessToken(callback) { + if (callback) { + this.getAccessTokenAsync().then(r => callback(null, r.token, r.res), callback); + } + else { + return this.getAccessTokenAsync(); + } + } + async getAccessTokenAsync() { + const shouldRefresh = !this.credentials.access_token || this.isTokenExpiring(); + if (shouldRefresh) { + if (!this.credentials.refresh_token) { + if (this.refreshHandler) { + const refreshedAccessToken = await this.processAndValidateRefreshHandler(); + if (refreshedAccessToken === null || refreshedAccessToken === void 0 ? void 0 : refreshedAccessToken.access_token) { + this.setCredentials(refreshedAccessToken); + return { token: this.credentials.access_token }; + } + } + else { + throw new Error('No refresh token or refresh handler callback is set.'); + } + } + const r = await this.refreshAccessTokenAsync(); + if (!r.credentials || (r.credentials && !r.credentials.access_token)) { + throw new Error('Could not refresh access token.'); + } + return { token: r.credentials.access_token, res: r.res }; + } + else { + return { token: this.credentials.access_token }; + } + } + /** + * The main authentication interface. It takes an optional url which when + * present is the endpoint being accessed, and returns a Promise which + * resolves with authorization header fields. + * + * In OAuth2Client, the result has the form: + * { Authorization: 'Bearer ' } + * @param url The optional url being authorized + */ + async getRequestHeaders(url) { + const headers = (await this.getRequestMetadataAsync(url)).headers; + return headers; + } + async getRequestMetadataAsync( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + url) { + const thisCreds = this.credentials; + if (!thisCreds.access_token && + !thisCreds.refresh_token && + !this.apiKey && + !this.refreshHandler) { + throw new Error('No access, refresh token, API key or refresh handler callback is set.'); + } + if (thisCreds.access_token && !this.isTokenExpiring()) { + thisCreds.token_type = thisCreds.token_type || 'Bearer'; + const headers = { + Authorization: thisCreds.token_type + ' ' + thisCreds.access_token, + }; + return { headers: this.addSharedMetadataHeaders(headers) }; + } + // If refreshHandler exists, call processAndValidateRefreshHandler(). + if (this.refreshHandler) { + const refreshedAccessToken = await this.processAndValidateRefreshHandler(); + if (refreshedAccessToken === null || refreshedAccessToken === void 0 ? void 0 : refreshedAccessToken.access_token) { + this.setCredentials(refreshedAccessToken); + const headers = { + Authorization: 'Bearer ' + this.credentials.access_token, + }; + return { headers: this.addSharedMetadataHeaders(headers) }; + } + } + if (this.apiKey) { + return { headers: { 'X-Goog-Api-Key': this.apiKey } }; + } + let r = null; + let tokens = null; + try { + r = await this.refreshToken(thisCreds.refresh_token); + tokens = r.tokens; + } + catch (err) { + const e = err; + if (e.response && + (e.response.status === 403 || e.response.status === 404)) { + e.message = `Could not refresh access token: ${e.message}`; + } + throw e; + } + const credentials = this.credentials; + credentials.token_type = credentials.token_type || 'Bearer'; + tokens.refresh_token = credentials.refresh_token; + this.credentials = tokens; + const headers = { + Authorization: credentials.token_type + ' ' + tokens.access_token, + }; + return { headers: this.addSharedMetadataHeaders(headers), res: r.res }; + } + /** + * Generates an URL to revoke the given token. + * @param token The existing token to be revoked. + * + * @deprecated use instance method {@link OAuth2Client.getRevokeTokenURL} + */ + static getRevokeTokenUrl(token) { + return new OAuth2Client().getRevokeTokenURL(token).toString(); + } + /** + * Generates a URL to revoke the given token. + * + * @param token The existing token to be revoked. + */ + getRevokeTokenURL(token) { + const url = new URL(this.endpoints.oauth2RevokeUrl); + url.searchParams.append('token', token); + return url; + } + revokeToken(token, callback) { + const opts = { + ...OAuth2Client.RETRY_CONFIG, + url: this.getRevokeTokenURL(token).toString(), + method: 'POST', + }; + if (callback) { + this.transporter + .request(opts) + .then(r => callback(null, r), callback); + } + else { + return this.transporter.request(opts); + } + } + revokeCredentials(callback) { + if (callback) { + this.revokeCredentialsAsync().then(res => callback(null, res), callback); + } + else { + return this.revokeCredentialsAsync(); + } + } + async revokeCredentialsAsync() { + const token = this.credentials.access_token; + this.credentials = {}; + if (token) { + return this.revokeToken(token); + } + else { + throw new Error('No access token to revoke.'); + } + } + request(opts, callback) { + if (callback) { + this.requestAsync(opts).then(r => callback(null, r), e => { + return callback(e, e.response); + }); + } + else { + return this.requestAsync(opts); + } + } + async requestAsync(opts, reAuthRetried = false) { + let r2; + try { + const r = await this.getRequestMetadataAsync(opts.url); + opts.headers = opts.headers || {}; + if (r.headers && r.headers['x-goog-user-project']) { + opts.headers['x-goog-user-project'] = r.headers['x-goog-user-project']; + } + if (r.headers && r.headers.Authorization) { + opts.headers.Authorization = r.headers.Authorization; + } + if (this.apiKey) { + opts.headers['X-Goog-Api-Key'] = this.apiKey; + } + r2 = await this.transporter.request(opts); + } + catch (e) { + const res = e.response; + if (res) { + const statusCode = res.status; + // Retry the request for metadata if the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - An access_token and refresh_token were available, but either no + // expiry_date was available or the forceRefreshOnFailure flag is set. + // The absent expiry_date case can happen when developers stash the + // access_token and refresh_token for later use, but the access_token + // fails on the first try because it's expired. Some developers may + // choose to enable forceRefreshOnFailure to mitigate time-related + // errors. + // Or the following criteria are true: + // - We haven't already retried. It only makes sense to retry once. + // - The response was a 401 or a 403 + // - The request didn't send a readableStream + // - No refresh_token was available + // - An access_token and a refreshHandler callback were available, but + // either no expiry_date was available or the forceRefreshOnFailure + // flag is set. The access_token fails on the first try because it's + // expired. Some developers may choose to enable forceRefreshOnFailure + // to mitigate time-related errors. + const mayRequireRefresh = this.credentials && + this.credentials.access_token && + this.credentials.refresh_token && + (!this.credentials.expiry_date || this.forceRefreshOnFailure); + const mayRequireRefreshWithNoRefreshToken = this.credentials && + this.credentials.access_token && + !this.credentials.refresh_token && + (!this.credentials.expiry_date || this.forceRefreshOnFailure) && + this.refreshHandler; + const isReadableStream = res.config.data instanceof stream.Readable; + const isAuthErr = statusCode === 401 || statusCode === 403; + if (!reAuthRetried && + isAuthErr && + !isReadableStream && + mayRequireRefresh) { + await this.refreshAccessTokenAsync(); + return this.requestAsync(opts, true); + } + else if (!reAuthRetried && + isAuthErr && + !isReadableStream && + mayRequireRefreshWithNoRefreshToken) { + const refreshedAccessToken = await this.processAndValidateRefreshHandler(); + if (refreshedAccessToken === null || refreshedAccessToken === void 0 ? void 0 : refreshedAccessToken.access_token) { + this.setCredentials(refreshedAccessToken); + } + return this.requestAsync(opts, true); + } + } + throw e; + } + return r2; + } + verifyIdToken(options, callback) { + // This function used to accept two arguments instead of an options object. + // Check the types to help users upgrade with less pain. + // This check can be removed after a 2.0 release. + if (callback && typeof callback !== 'function') { + throw new Error('This method accepts an options object as the first parameter, which includes the idToken, audience, and maxExpiry.'); + } + if (callback) { + this.verifyIdTokenAsync(options).then(r => callback(null, r), callback); + } + else { + return this.verifyIdTokenAsync(options); + } + } + async verifyIdTokenAsync(options) { + if (!options.idToken) { + throw new Error('The verifyIdToken method requires an ID Token'); + } + const response = await this.getFederatedSignonCertsAsync(); + const login = await this.verifySignedJwtWithCertsAsync(options.idToken, response.certs, options.audience, this.issuers, options.maxExpiry); + return login; + } + /** + * Obtains information about the provisioned access token. Especially useful + * if you want to check the scopes that were provisioned to a given token. + * + * @param accessToken Required. The Access Token for which you want to get + * user info. + */ + async getTokenInfo(accessToken) { + const { data } = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: `Bearer ${accessToken}`, + }, + url: this.endpoints.tokenInfoUrl.toString(), + }); + const info = Object.assign({ + expiry_date: new Date().getTime() + data.expires_in * 1000, + scopes: data.scope.split(' '), + }, data); + delete info.expires_in; + delete info.scope; + return info; + } + getFederatedSignonCerts(callback) { + if (callback) { + this.getFederatedSignonCertsAsync().then(r => callback(null, r.certs, r.res), callback); + } + else { + return this.getFederatedSignonCertsAsync(); + } + } + async getFederatedSignonCertsAsync() { + const nowTime = new Date().getTime(); + const format = (0, crypto_1.hasBrowserCrypto)() + ? CertificateFormat.JWK + : CertificateFormat.PEM; + if (this.certificateExpiry && + nowTime < this.certificateExpiry.getTime() && + this.certificateCacheFormat === format) { + return { certs: this.certificateCache, format }; + } + let res; + let url; + switch (format) { + case CertificateFormat.PEM: + url = this.endpoints.oauth2FederatedSignonPemCertsUrl.toString(); + break; + case CertificateFormat.JWK: + url = this.endpoints.oauth2FederatedSignonJwkCertsUrl.toString(); + break; + default: + throw new Error(`Unsupported certificate format ${format}`); + } + try { + res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + url, + }); + } + catch (e) { + if (e instanceof Error) { + e.message = `Failed to retrieve verification certificates: ${e.message}`; + } + throw e; + } + const cacheControl = res ? res.headers['cache-control'] : undefined; + let cacheAge = -1; + if (cacheControl) { + const pattern = new RegExp('max-age=([0-9]*)'); + const regexResult = pattern.exec(cacheControl); + if (regexResult && regexResult.length === 2) { + // Cache results with max-age (in seconds) + cacheAge = Number(regexResult[1]) * 1000; // milliseconds + } + } + let certificates = {}; + switch (format) { + case CertificateFormat.PEM: + certificates = res.data; + break; + case CertificateFormat.JWK: + for (const key of res.data.keys) { + certificates[key.kid] = key; + } + break; + default: + throw new Error(`Unsupported certificate format ${format}`); + } + const now = new Date(); + this.certificateExpiry = + cacheAge === -1 ? null : new Date(now.getTime() + cacheAge); + this.certificateCache = certificates; + this.certificateCacheFormat = format; + return { certs: certificates, format, res }; + } + getIapPublicKeys(callback) { + if (callback) { + this.getIapPublicKeysAsync().then(r => callback(null, r.pubkeys, r.res), callback); + } + else { + return this.getIapPublicKeysAsync(); + } + } + async getIapPublicKeysAsync() { + let res; + const url = this.endpoints.oauth2IapPublicKeyUrl.toString(); + try { + res = await this.transporter.request({ + ...OAuth2Client.RETRY_CONFIG, + url, + }); + } + catch (e) { + if (e instanceof Error) { + e.message = `Failed to retrieve verification certificates: ${e.message}`; + } + throw e; + } + return { pubkeys: res.data, res }; + } + verifySignedJwtWithCerts() { + // To make the code compatible with browser SubtleCrypto we need to make + // this method async. + throw new Error('verifySignedJwtWithCerts is removed, please use verifySignedJwtWithCertsAsync instead.'); + } + /** + * Verify the id token is signed with the correct certificate + * and is from the correct audience. + * @param jwt The jwt to verify (The ID Token in this case). + * @param certs The array of certs to test the jwt against. + * @param requiredAudience The audience to test the jwt against. + * @param issuers The allowed issuers of the jwt (Optional). + * @param maxExpiry The max expiry the certificate can be (Optional). + * @return Returns a promise resolving to LoginTicket on verification. + */ + async verifySignedJwtWithCertsAsync(jwt, certs, requiredAudience, issuers, maxExpiry) { + const crypto = (0, crypto_1.createCrypto)(); + if (!maxExpiry) { + maxExpiry = OAuth2Client.DEFAULT_MAX_TOKEN_LIFETIME_SECS_; + } + const segments = jwt.split('.'); + if (segments.length !== 3) { + throw new Error('Wrong number of segments in token: ' + jwt); + } + const signed = segments[0] + '.' + segments[1]; + let signature = segments[2]; + let envelope; + let payload; + try { + envelope = JSON.parse(crypto.decodeBase64StringUtf8(segments[0])); + } + catch (err) { + if (err instanceof Error) { + err.message = `Can't parse token envelope: ${segments[0]}': ${err.message}`; + } + throw err; + } + if (!envelope) { + throw new Error("Can't parse token envelope: " + segments[0]); + } + try { + payload = JSON.parse(crypto.decodeBase64StringUtf8(segments[1])); + } + catch (err) { + if (err instanceof Error) { + err.message = `Can't parse token payload '${segments[0]}`; + } + throw err; + } + if (!payload) { + throw new Error("Can't parse token payload: " + segments[1]); + } + if (!Object.prototype.hasOwnProperty.call(certs, envelope.kid)) { + // If this is not present, then there's no reason to attempt verification + throw new Error('No pem found for envelope: ' + JSON.stringify(envelope)); + } + const cert = certs[envelope.kid]; + if (envelope.alg === 'ES256') { + signature = formatEcdsa.joseToDer(signature, 'ES256').toString('base64'); + } + const verified = await crypto.verify(cert, signed, signature); + if (!verified) { + throw new Error('Invalid token signature: ' + jwt); + } + if (!payload.iat) { + throw new Error('No issue time in token: ' + JSON.stringify(payload)); + } + if (!payload.exp) { + throw new Error('No expiration time in token: ' + JSON.stringify(payload)); + } + const iat = Number(payload.iat); + if (isNaN(iat)) + throw new Error('iat field using invalid format'); + const exp = Number(payload.exp); + if (isNaN(exp)) + throw new Error('exp field using invalid format'); + const now = new Date().getTime() / 1000; + if (exp >= now + maxExpiry) { + throw new Error('Expiration time too far in future: ' + JSON.stringify(payload)); + } + const earliest = iat - OAuth2Client.CLOCK_SKEW_SECS_; + const latest = exp + OAuth2Client.CLOCK_SKEW_SECS_; + if (now < earliest) { + throw new Error('Token used too early, ' + + now + + ' < ' + + earliest + + ': ' + + JSON.stringify(payload)); + } + if (now > latest) { + throw new Error('Token used too late, ' + + now + + ' > ' + + latest + + ': ' + + JSON.stringify(payload)); + } + if (issuers && issuers.indexOf(payload.iss) < 0) { + throw new Error('Invalid issuer, expected one of [' + + issuers + + '], but got ' + + payload.iss); + } + // Check the audience matches if we have one + if (typeof requiredAudience !== 'undefined' && requiredAudience !== null) { + const aud = payload.aud; + let audVerified = false; + // If the requiredAudience is an array, check if it contains token + // audience + if (requiredAudience.constructor === Array) { + audVerified = requiredAudience.indexOf(aud) > -1; + } + else { + audVerified = aud === requiredAudience; + } + if (!audVerified) { + throw new Error('Wrong recipient, payload audience != requiredAudience'); + } + } + return new loginticket_1.LoginTicket(envelope, payload); + } + /** + * Returns a promise that resolves with AccessTokenResponse type if + * refreshHandler is defined. + * If not, nothing is returned. + */ + async processAndValidateRefreshHandler() { + if (this.refreshHandler) { + const accessTokenResponse = await this.refreshHandler(); + if (!accessTokenResponse.access_token) { + throw new Error('No access token is returned by the refreshHandler callback.'); + } + return accessTokenResponse; + } + return; + } + /** + * Returns true if a token is expired or will expire within + * eagerRefreshThresholdMillismilliseconds. + * If there is no expiry time, assumes the token is not expired or expiring. + */ + isTokenExpiring() { + const expiryDate = this.credentials.expiry_date; + return expiryDate + ? expiryDate <= new Date().getTime() + this.eagerRefreshThresholdMillis + : false; + } +} +exports.OAuth2Client = OAuth2Client; +/** + * @deprecated use instance's {@link OAuth2Client.endpoints} + */ +OAuth2Client.GOOGLE_TOKEN_INFO_URL = 'https://oauth2.googleapis.com/tokeninfo'; +/** + * Clock skew - five minutes in seconds + */ +OAuth2Client.CLOCK_SKEW_SECS_ = 300; +/** + * The default max Token Lifetime is one day in seconds + */ +OAuth2Client.DEFAULT_MAX_TOKEN_LIFETIME_SECS_ = 86400; + + +/***/ }), + +/***/ 6653: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OAuthClientAuthHandler = void 0; +exports.getErrorFromOAuthErrorResponse = getErrorFromOAuthErrorResponse; +const querystring = __nccwpck_require__(83480); +const crypto_1 = __nccwpck_require__(88851); +/** List of HTTP methods that accept request bodies. */ +const METHODS_SUPPORTING_REQUEST_BODY = ['PUT', 'POST', 'PATCH']; +/** + * Abstract class for handling client authentication in OAuth-based + * operations. + * When request-body client authentication is used, only application/json and + * application/x-www-form-urlencoded content types for HTTP methods that support + * request bodies are supported. + */ +class OAuthClientAuthHandler { + /** + * Instantiates an OAuth client authentication handler. + * @param clientAuthentication The client auth credentials. + */ + constructor(clientAuthentication) { + this.clientAuthentication = clientAuthentication; + this.crypto = (0, crypto_1.createCrypto)(); + } + /** + * Applies client authentication on the OAuth request's headers or POST + * body but does not process the request. + * @param opts The GaxiosOptions whose headers or data are to be modified + * depending on the client authentication mechanism to be used. + * @param bearerToken The optional bearer token to use for authentication. + * When this is used, no client authentication credentials are needed. + */ + applyClientAuthenticationOptions(opts, bearerToken) { + // Inject authenticated header. + this.injectAuthenticatedHeaders(opts, bearerToken); + // Inject authenticated request body. + if (!bearerToken) { + this.injectAuthenticatedRequestBody(opts); + } + } + /** + * Applies client authentication on the request's header if either + * basic authentication or bearer token authentication is selected. + * + * @param opts The GaxiosOptions whose headers or data are to be modified + * depending on the client authentication mechanism to be used. + * @param bearerToken The optional bearer token to use for authentication. + * When this is used, no client authentication credentials are needed. + */ + injectAuthenticatedHeaders(opts, bearerToken) { + var _a; + // Bearer token prioritized higher than basic Auth. + if (bearerToken) { + opts.headers = opts.headers || {}; + Object.assign(opts.headers, { + Authorization: `Bearer ${bearerToken}}`, + }); + } + else if (((_a = this.clientAuthentication) === null || _a === void 0 ? void 0 : _a.confidentialClientType) === 'basic') { + opts.headers = opts.headers || {}; + const clientId = this.clientAuthentication.clientId; + const clientSecret = this.clientAuthentication.clientSecret || ''; + const base64EncodedCreds = this.crypto.encodeBase64StringUtf8(`${clientId}:${clientSecret}`); + Object.assign(opts.headers, { + Authorization: `Basic ${base64EncodedCreds}`, + }); + } + } + /** + * Applies client authentication on the request's body if request-body + * client authentication is selected. + * + * @param opts The GaxiosOptions whose headers or data are to be modified + * depending on the client authentication mechanism to be used. + */ + injectAuthenticatedRequestBody(opts) { + var _a; + if (((_a = this.clientAuthentication) === null || _a === void 0 ? void 0 : _a.confidentialClientType) === 'request-body') { + const method = (opts.method || 'GET').toUpperCase(); + // Inject authenticated request body. + if (METHODS_SUPPORTING_REQUEST_BODY.indexOf(method) !== -1) { + // Get content-type. + let contentType; + const headers = opts.headers || {}; + for (const key in headers) { + if (key.toLowerCase() === 'content-type' && headers[key]) { + contentType = headers[key].toLowerCase(); + break; + } + } + if (contentType === 'application/x-www-form-urlencoded') { + opts.data = opts.data || ''; + const data = querystring.parse(opts.data); + Object.assign(data, { + client_id: this.clientAuthentication.clientId, + client_secret: this.clientAuthentication.clientSecret || '', + }); + opts.data = querystring.stringify(data); + } + else if (contentType === 'application/json') { + opts.data = opts.data || {}; + Object.assign(opts.data, { + client_id: this.clientAuthentication.clientId, + client_secret: this.clientAuthentication.clientSecret || '', + }); + } + else { + throw new Error(`${contentType} content-types are not supported with ` + + `${this.clientAuthentication.confidentialClientType} ` + + 'client authentication'); + } + } + else { + throw new Error(`${method} HTTP method does not support ` + + `${this.clientAuthentication.confidentialClientType} ` + + 'client authentication'); + } + } + } + /** + * Retry config for Auth-related requests. + * + * @remarks + * + * This is not a part of the default {@link AuthClient.transporter transporter/gaxios} + * config as some downstream APIs would prefer if customers explicitly enable retries, + * such as GCS. + */ + static get RETRY_CONFIG() { + return { + retry: true, + retryConfig: { + httpMethodsToRetry: ['GET', 'PUT', 'POST', 'HEAD', 'OPTIONS', 'DELETE'], + }, + }; + } +} +exports.OAuthClientAuthHandler = OAuthClientAuthHandler; +/** + * Converts an OAuth error response to a native JavaScript Error. + * @param resp The OAuth error response to convert to a native Error object. + * @param err The optional original error. If provided, the error properties + * will be copied to the new error. + * @return The converted native Error object. + */ +function getErrorFromOAuthErrorResponse(resp, err) { + // Error response. + const errorCode = resp.error; + const errorDescription = resp.error_description; + const errorUri = resp.error_uri; + let message = `Error code ${errorCode}`; + if (typeof errorDescription !== 'undefined') { + message += `: ${errorDescription}`; + } + if (typeof errorUri !== 'undefined') { + message += ` - ${errorUri}`; + } + const newError = new Error(message); + // Copy properties from original error to newly generated error. + if (err) { + const keys = Object.keys(err); + if (err.stack) { + // Copy error.stack if available. + keys.push('stack'); + } + keys.forEach(key => { + // Do not overwrite the message field. + if (key !== 'message') { + Object.defineProperty(newError, key, { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value: err[key], + writable: false, + enumerable: true, + }); + } + }); + } + return newError; +} + + +/***/ }), + +/***/ 62045: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PassThroughClient = void 0; +const authclient_1 = __nccwpck_require__(34810); +/** + * An AuthClient without any Authentication information. Useful for: + * - Anonymous access + * - Local Emulators + * - Testing Environments + * + */ +class PassThroughClient extends authclient_1.AuthClient { + /** + * Creates a request without any authentication headers or checks. + * + * @remarks + * + * In testing environments it may be useful to change the provided + * {@link AuthClient.transporter} for any desired request overrides/handling. + * + * @param opts + * @returns The response of the request. + */ + async request(opts) { + return this.transporter.request(opts); + } + /** + * A required method of the base class. + * Always will return an empty object. + * + * @returns {} + */ + async getAccessToken() { + return {}; + } + /** + * A required method of the base class. + * Always will return an empty object. + * + * @returns {} + */ + async getRequestHeaders() { + return {}; + } +} +exports.PassThroughClient = PassThroughClient; +const a = new PassThroughClient(); +a.getAccessToken(); + + +/***/ }), + +/***/ 46077: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PluggableAuthClient = exports.ExecutableError = void 0; +const baseexternalclient_1 = __nccwpck_require__(142); +const executable_response_1 = __nccwpck_require__(43247); +const pluggable_auth_handler_1 = __nccwpck_require__(908); +/** + * Error thrown from the executable run by PluggableAuthClient. + */ +class ExecutableError extends Error { + constructor(message, code) { + super(`The executable failed with exit code: ${code} and error message: ${message}.`); + this.code = code; + Object.setPrototypeOf(this, new.target.prototype); + } +} +exports.ExecutableError = ExecutableError; +/** + * The default executable timeout when none is provided, in milliseconds. + */ +const DEFAULT_EXECUTABLE_TIMEOUT_MILLIS = 30 * 1000; +/** + * The minimum allowed executable timeout in milliseconds. + */ +const MINIMUM_EXECUTABLE_TIMEOUT_MILLIS = 5 * 1000; +/** + * The maximum allowed executable timeout in milliseconds. + */ +const MAXIMUM_EXECUTABLE_TIMEOUT_MILLIS = 120 * 1000; +/** + * The environment variable to check to see if executable can be run. + * Value must be set to '1' for the executable to run. + */ +const GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES = 'GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES'; +/** + * The maximum currently supported executable version. + */ +const MAXIMUM_EXECUTABLE_VERSION = 1; +/** + * PluggableAuthClient enables the exchange of workload identity pool external credentials for + * Google access tokens by retrieving 3rd party tokens through a user supplied executable. These + * scripts/executables are completely independent of the Google Cloud Auth libraries. These + * credentials plug into ADC and will call the specified executable to retrieve the 3rd party token + * to be exchanged for a Google access token. + * + *

To use these credentials, the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment variable + * must be set to '1'. This is for security reasons. + * + *

Both OIDC and SAML are supported. The executable must adhere to a specific response format + * defined below. + * + *

The executable must print out the 3rd party token to STDOUT in JSON format. When an + * output_file is specified in the credential configuration, the executable must also handle writing the + * JSON response to this file. + * + *

+ * OIDC response sample:
+ * {
+ *   "version": 1,
+ *   "success": true,
+ *   "token_type": "urn:ietf:params:oauth:token-type:id_token",
+ *   "id_token": "HEADER.PAYLOAD.SIGNATURE",
+ *   "expiration_time": 1620433341
+ * }
+ *
+ * SAML2 response sample:
+ * {
+ *   "version": 1,
+ *   "success": true,
+ *   "token_type": "urn:ietf:params:oauth:token-type:saml2",
+ *   "saml_response": "...",
+ *   "expiration_time": 1620433341
+ * }
+ *
+ * Error response sample:
+ * {
+ *   "version": 1,
+ *   "success": false,
+ *   "code": "401",
+ *   "message": "Error message."
+ * }
+ * 
+ * + *

The "expiration_time" field in the JSON response is only required for successful + * responses when an output file was specified in the credential configuration + * + *

The auth libraries will populate certain environment variables that will be accessible by the + * executable, such as: GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE, GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE, + * GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE, GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL, and + * GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE. + * + *

Please see this repositories README for a complete executable request/response specification. + */ +class PluggableAuthClient extends baseexternalclient_1.BaseExternalAccountClient { + /** + * Instantiates a PluggableAuthClient instance using the provided JSON + * object loaded from an external account credentials file. + * An error is thrown if the credential is not a valid pluggable auth credential. + * @param options The external account options object typically loaded from + * the external account JSON credential file. + * @param additionalOptions **DEPRECATED, all options are available in the + * `options` parameter.** Optional additional behavior customization options. + * These currently customize expiration threshold time and whether to retry + * on 401/403 API request errors. + */ + constructor(options, additionalOptions) { + super(options, additionalOptions); + if (!options.credential_source.executable) { + throw new Error('No valid Pluggable Auth "credential_source" provided.'); + } + this.command = options.credential_source.executable.command; + if (!this.command) { + throw new Error('No valid Pluggable Auth "credential_source" provided.'); + } + // Check if the provided timeout exists and if it is valid. + if (options.credential_source.executable.timeout_millis === undefined) { + this.timeoutMillis = DEFAULT_EXECUTABLE_TIMEOUT_MILLIS; + } + else { + this.timeoutMillis = options.credential_source.executable.timeout_millis; + if (this.timeoutMillis < MINIMUM_EXECUTABLE_TIMEOUT_MILLIS || + this.timeoutMillis > MAXIMUM_EXECUTABLE_TIMEOUT_MILLIS) { + throw new Error(`Timeout must be between ${MINIMUM_EXECUTABLE_TIMEOUT_MILLIS} and ` + + `${MAXIMUM_EXECUTABLE_TIMEOUT_MILLIS} milliseconds.`); + } + } + this.outputFile = options.credential_source.executable.output_file; + this.handler = new pluggable_auth_handler_1.PluggableAuthHandler({ + command: this.command, + timeoutMillis: this.timeoutMillis, + outputFile: this.outputFile, + }); + this.credentialSourceType = 'executable'; + } + /** + * Triggered when an external subject token is needed to be exchanged for a + * GCP access token via GCP STS endpoint. + * This uses the `options.credential_source` object to figure out how + * to retrieve the token using the current environment. In this case, + * this calls a user provided executable which returns the subject token. + * The logic is summarized as: + * 1. Validated that the executable is allowed to run. The + * GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment must be set to + * 1 for security reasons. + * 2. If an output file is specified by the user, check the file location + * for a response. If the file exists and contains a valid response, + * return the subject token from the file. + * 3. Call the provided executable and return response. + * @return A promise that resolves with the external subject token. + */ + async retrieveSubjectToken() { + // Check if the executable is allowed to run. + if (process.env[GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES] !== '1') { + throw new Error('Pluggable Auth executables need to be explicitly allowed to run by ' + + 'setting the GOOGLE_EXTERNAL_ACCOUNT_ALLOW_EXECUTABLES environment ' + + 'Variable to 1.'); + } + let executableResponse = undefined; + // Try to get cached executable response from output file. + if (this.outputFile) { + executableResponse = await this.handler.retrieveCachedResponse(); + } + // If no response from output file, call the executable. + if (!executableResponse) { + // Set up environment map with required values for the executable. + const envMap = new Map(); + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_AUDIENCE', this.audience); + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_TOKEN_TYPE', this.subjectTokenType); + // Always set to 0 because interactive mode is not supported. + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_INTERACTIVE', '0'); + if (this.outputFile) { + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_OUTPUT_FILE', this.outputFile); + } + const serviceAccountEmail = this.getServiceAccountEmail(); + if (serviceAccountEmail) { + envMap.set('GOOGLE_EXTERNAL_ACCOUNT_IMPERSONATED_EMAIL', serviceAccountEmail); + } + executableResponse = + await this.handler.retrieveResponseFromExecutable(envMap); + } + if (executableResponse.version > MAXIMUM_EXECUTABLE_VERSION) { + throw new Error(`Version of executable is not currently supported, maximum supported version is ${MAXIMUM_EXECUTABLE_VERSION}.`); + } + // Check that response was successful. + if (!executableResponse.success) { + throw new ExecutableError(executableResponse.errorMessage, executableResponse.errorCode); + } + // Check that response contains expiration time if output file was specified. + if (this.outputFile) { + if (!executableResponse.expirationTime) { + throw new executable_response_1.InvalidExpirationTimeFieldError('The executable response must contain the `expiration_time` field for successful responses when an output_file has been specified in the configuration.'); + } + } + // Check that response is not expired. + if (executableResponse.isExpired()) { + throw new Error('Executable response is expired.'); + } + // Return subject token from response. + return executableResponse.subjectToken; + } +} +exports.PluggableAuthClient = PluggableAuthClient; + + +/***/ }), + +/***/ 908: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PluggableAuthHandler = void 0; +const pluggable_auth_client_1 = __nccwpck_require__(46077); +const executable_response_1 = __nccwpck_require__(43247); +const childProcess = __nccwpck_require__(35317); +const fs = __nccwpck_require__(79896); +/** + * A handler used to retrieve 3rd party token responses from user defined + * executables and cached file output for the PluggableAuthClient class. + */ +class PluggableAuthHandler { + /** + * Instantiates a PluggableAuthHandler instance using the provided + * PluggableAuthHandlerOptions object. + */ + constructor(options) { + if (!options.command) { + throw new Error('No command provided.'); + } + this.commandComponents = PluggableAuthHandler.parseCommand(options.command); + this.timeoutMillis = options.timeoutMillis; + if (!this.timeoutMillis) { + throw new Error('No timeoutMillis provided.'); + } + this.outputFile = options.outputFile; + } + /** + * Calls user provided executable to get a 3rd party subject token and + * returns the response. + * @param envMap a Map of additional Environment Variables required for + * the executable. + * @return A promise that resolves with the executable response. + */ + retrieveResponseFromExecutable(envMap) { + return new Promise((resolve, reject) => { + // Spawn process to run executable using added environment variables. + const child = childProcess.spawn(this.commandComponents[0], this.commandComponents.slice(1), { + env: { ...process.env, ...Object.fromEntries(envMap) }, + }); + let output = ''; + // Append stdout to output as executable runs. + child.stdout.on('data', (data) => { + output += data; + }); + // Append stderr as executable runs. + child.stderr.on('data', (err) => { + output += err; + }); + // Set up a timeout to end the child process and throw an error. + const timeout = setTimeout(() => { + // Kill child process and remove listeners so 'close' event doesn't get + // read after child process is killed. + child.removeAllListeners(); + child.kill(); + return reject(new Error('The executable failed to finish within the timeout specified.')); + }, this.timeoutMillis); + child.on('close', (code) => { + // Cancel timeout if executable closes before timeout is reached. + clearTimeout(timeout); + if (code === 0) { + // If the executable completed successfully, try to return the parsed response. + try { + const responseJson = JSON.parse(output); + const response = new executable_response_1.ExecutableResponse(responseJson); + return resolve(response); + } + catch (error) { + if (error instanceof executable_response_1.ExecutableResponseError) { + return reject(error); + } + return reject(new executable_response_1.ExecutableResponseError(`The executable returned an invalid response: ${output}`)); + } + } + else { + return reject(new pluggable_auth_client_1.ExecutableError(output, code.toString())); + } + }); + }); + } + /** + * Checks user provided output file for response from previous run of + * executable and return the response if it exists, is formatted correctly, and is not expired. + */ + async retrieveCachedResponse() { + if (!this.outputFile || this.outputFile.length === 0) { + return undefined; + } + let filePath; + try { + filePath = await fs.promises.realpath(this.outputFile); + } + catch (_a) { + // If file path cannot be resolved, return undefined. + return undefined; + } + if (!(await fs.promises.lstat(filePath)).isFile()) { + // If path does not lead to file, return undefined. + return undefined; + } + const responseString = await fs.promises.readFile(filePath, { + encoding: 'utf8', + }); + if (responseString === '') { + return undefined; + } + try { + const responseJson = JSON.parse(responseString); + const response = new executable_response_1.ExecutableResponse(responseJson); + // Check if response is successful and unexpired. + if (response.isValid()) { + return new executable_response_1.ExecutableResponse(responseJson); + } + return undefined; + } + catch (error) { + if (error instanceof executable_response_1.ExecutableResponseError) { + throw error; + } + throw new executable_response_1.ExecutableResponseError(`The output file contained an invalid response: ${responseString}`); + } + } + /** + * Parses given command string into component array, splitting on spaces unless + * spaces are between quotation marks. + */ + static parseCommand(command) { + // Split the command into components by splitting on spaces, + // unless spaces are contained in quotation marks. + const components = command.match(/(?:[^\s"]+|"[^"]*")+/g); + if (!components) { + throw new Error(`Provided command: "${command}" could not be parsed.`); + } + // Remove quotation marks from the beginning and end of each component if they are present. + for (let i = 0; i < components.length; i++) { + if (components[i][0] === '"' && components[i].slice(-1) === '"') { + components[i] = components[i].slice(1, -1); + } + } + return components; + } +} +exports.PluggableAuthHandler = PluggableAuthHandler; + + +/***/ }), + +/***/ 99807: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2015 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UserRefreshClient = exports.USER_REFRESH_ACCOUNT_TYPE = void 0; +const oauth2client_1 = __nccwpck_require__(10091); +const querystring_1 = __nccwpck_require__(83480); +exports.USER_REFRESH_ACCOUNT_TYPE = 'authorized_user'; +class UserRefreshClient extends oauth2client_1.OAuth2Client { + constructor(optionsOrClientId, clientSecret, refreshToken, eagerRefreshThresholdMillis, forceRefreshOnFailure) { + const opts = optionsOrClientId && typeof optionsOrClientId === 'object' + ? optionsOrClientId + : { + clientId: optionsOrClientId, + clientSecret, + refreshToken, + eagerRefreshThresholdMillis, + forceRefreshOnFailure, + }; + super(opts); + this._refreshToken = opts.refreshToken; + this.credentials.refresh_token = opts.refreshToken; + } + /** + * Refreshes the access token. + * @param refreshToken An ignored refreshToken.. + * @param callback Optional callback. + */ + async refreshTokenNoCache( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + refreshToken) { + return super.refreshTokenNoCache(this._refreshToken); + } + async fetchIdToken(targetAudience) { + const res = await this.transporter.request({ + ...UserRefreshClient.RETRY_CONFIG, + url: this.endpoints.oauth2TokenUrl, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + method: 'POST', + data: (0, querystring_1.stringify)({ + client_id: this._clientId, + client_secret: this._clientSecret, + grant_type: 'refresh_token', + refresh_token: this._refreshToken, + target_audience: targetAudience, + }), + }); + return res.data.id_token; + } + /** + * Create a UserRefreshClient credentials instance using the given input + * options. + * @param json The input object. + */ + fromJSON(json) { + if (!json) { + throw new Error('Must pass in a JSON object containing the user refresh token'); + } + if (json.type !== 'authorized_user') { + throw new Error('The incoming JSON object does not have the "authorized_user" type'); + } + if (!json.client_id) { + throw new Error('The incoming JSON object does not contain a client_id field'); + } + if (!json.client_secret) { + throw new Error('The incoming JSON object does not contain a client_secret field'); + } + if (!json.refresh_token) { + throw new Error('The incoming JSON object does not contain a refresh_token field'); + } + this._clientId = json.client_id; + this._clientSecret = json.client_secret; + this._refreshToken = json.refresh_token; + this.credentials.refresh_token = json.refresh_token; + this.quotaProjectId = json.quota_project_id; + this.universeDomain = json.universe_domain || this.universeDomain; + } + fromStream(inputStream, callback) { + if (callback) { + this.fromStreamAsync(inputStream).then(() => callback(), callback); + } + else { + return this.fromStreamAsync(inputStream); + } + } + async fromStreamAsync(inputStream) { + return new Promise((resolve, reject) => { + if (!inputStream) { + return reject(new Error('Must pass in a stream containing the user refresh token.')); + } + let s = ''; + inputStream + .setEncoding('utf8') + .on('error', reject) + .on('data', chunk => (s += chunk)) + .on('end', () => { + try { + const data = JSON.parse(s); + this.fromJSON(data); + return resolve(); + } + catch (err) { + return reject(err); + } + }); + }); + } + /** + * Create a UserRefreshClient credentials instance using the given input + * options. + * @param json The input object. + */ + static fromJSON(json) { + const client = new UserRefreshClient(); + client.fromJSON(json); + return client; + } +} +exports.UserRefreshClient = UserRefreshClient; + + +/***/ }), + +/***/ 121: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.StsCredentials = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const querystring = __nccwpck_require__(83480); +const transporters_1 = __nccwpck_require__(67633); +const oauth2common_1 = __nccwpck_require__(6653); +/** + * Implements the OAuth 2.0 token exchange based on + * https://tools.ietf.org/html/rfc8693 + */ +class StsCredentials extends oauth2common_1.OAuthClientAuthHandler { + /** + * Initializes an STS credentials instance. + * @param tokenExchangeEndpoint The token exchange endpoint. + * @param clientAuthentication The client authentication credentials if + * available. + */ + constructor(tokenExchangeEndpoint, clientAuthentication) { + super(clientAuthentication); + this.tokenExchangeEndpoint = tokenExchangeEndpoint; + this.transporter = new transporters_1.DefaultTransporter(); + } + /** + * Exchanges the provided token for another type of token based on the + * rfc8693 spec. + * @param stsCredentialsOptions The token exchange options used to populate + * the token exchange request. + * @param additionalHeaders Optional additional headers to pass along the + * request. + * @param options Optional additional GCP-specific non-spec defined options + * to send with the request. + * Example: `&options=${encodeUriComponent(JSON.stringified(options))}` + * @return A promise that resolves with the token exchange response containing + * the requested token and its expiration time. + */ + async exchangeToken(stsCredentialsOptions, additionalHeaders, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + options) { + var _a, _b, _c; + const values = { + grant_type: stsCredentialsOptions.grantType, + resource: stsCredentialsOptions.resource, + audience: stsCredentialsOptions.audience, + scope: (_a = stsCredentialsOptions.scope) === null || _a === void 0 ? void 0 : _a.join(' '), + requested_token_type: stsCredentialsOptions.requestedTokenType, + subject_token: stsCredentialsOptions.subjectToken, + subject_token_type: stsCredentialsOptions.subjectTokenType, + actor_token: (_b = stsCredentialsOptions.actingParty) === null || _b === void 0 ? void 0 : _b.actorToken, + actor_token_type: (_c = stsCredentialsOptions.actingParty) === null || _c === void 0 ? void 0 : _c.actorTokenType, + // Non-standard GCP-specific options. + options: options && JSON.stringify(options), + }; + // Remove undefined fields. + Object.keys(values).forEach(key => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (typeof values[key] === 'undefined') { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + delete values[key]; + } + }); + const headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + }; + // Inject additional STS headers if available. + Object.assign(headers, additionalHeaders || {}); + const opts = { + ...StsCredentials.RETRY_CONFIG, + url: this.tokenExchangeEndpoint.toString(), + method: 'POST', + headers, + data: querystring.stringify(values), + responseType: 'json', + }; + // Apply OAuth client authentication. + this.applyClientAuthenticationOptions(opts); + try { + const response = await this.transporter.request(opts); + // Successful response. + const stsSuccessfulResponse = response.data; + stsSuccessfulResponse.res = response; + return stsSuccessfulResponse; + } + catch (error) { + // Translate error to OAuthError. + if (error instanceof gaxios_1.GaxiosError && error.response) { + throw (0, oauth2common_1.getErrorFromOAuthErrorResponse)(error.response.data, + // Preserve other fields from the original error. + error); + } + // Request could fail before the server responds. + throw error; + } + } +} +exports.StsCredentials = StsCredentials; + + +/***/ }), + +/***/ 24627: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.UrlSubjectTokenSupplier = void 0; +/** + * Internal subject token supplier implementation used when a URL + * is configured in the credential configuration used to build an {@link IdentityPoolClient} + */ +class UrlSubjectTokenSupplier { + /** + * Instantiates a URL subject token supplier. + * @param opts The URL subject token supplier options to build the supplier with. + */ + constructor(opts) { + this.url = opts.url; + this.formatType = opts.formatType; + this.subjectTokenFieldName = opts.subjectTokenFieldName; + this.headers = opts.headers; + this.additionalGaxiosOptions = opts.additionalGaxiosOptions; + } + /** + * Sends a GET request to the URL provided in the constructor and resolves + * with the returned external subject token. + * @param context {@link ExternalAccountSupplierContext} from the calling + * {@link IdentityPoolClient}, contains the requested audience and subject + * token type for the external account identity. Not used. + */ + async getSubjectToken(context) { + const opts = { + ...this.additionalGaxiosOptions, + url: this.url, + method: 'GET', + headers: this.headers, + responseType: this.formatType, + }; + let subjectToken; + if (this.formatType === 'text') { + const response = await context.transporter.request(opts); + subjectToken = response.data; + } + else if (this.formatType === 'json' && this.subjectTokenFieldName) { + const response = await context.transporter.request(opts); + subjectToken = response.data[this.subjectTokenFieldName]; + } + if (!subjectToken) { + throw new Error('Unable to parse the subject_token from the credential_source URL'); + } + return subjectToken; + } +} +exports.UrlSubjectTokenSupplier = UrlSubjectTokenSupplier; + + +/***/ }), + +/***/ 93438: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/* global window */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.BrowserCrypto = void 0; +// This file implements crypto functions we need using in-browser +// SubtleCrypto interface `window.crypto.subtle`. +const base64js = __nccwpck_require__(38793); +const crypto_1 = __nccwpck_require__(88851); +class BrowserCrypto { + constructor() { + if (typeof window === 'undefined' || + window.crypto === undefined || + window.crypto.subtle === undefined) { + throw new Error("SubtleCrypto not found. Make sure it's an https:// website."); + } + } + async sha256DigestBase64(str) { + // SubtleCrypto digest() method is async, so we must make + // this method async as well. + // To calculate SHA256 digest using SubtleCrypto, we first + // need to convert an input string to an ArrayBuffer: + const inputBuffer = new TextEncoder().encode(str); + // Result is ArrayBuffer as well. + const outputBuffer = await window.crypto.subtle.digest('SHA-256', inputBuffer); + return base64js.fromByteArray(new Uint8Array(outputBuffer)); + } + randomBytesBase64(count) { + const array = new Uint8Array(count); + window.crypto.getRandomValues(array); + return base64js.fromByteArray(array); + } + static padBase64(base64) { + // base64js requires padding, so let's add some '=' + while (base64.length % 4 !== 0) { + base64 += '='; + } + return base64; + } + async verify(pubkey, data, signature) { + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: 'SHA-256' }, + }; + const dataArray = new TextEncoder().encode(data); + const signatureArray = base64js.toByteArray(BrowserCrypto.padBase64(signature)); + const cryptoKey = await window.crypto.subtle.importKey('jwk', pubkey, algo, true, ['verify']); + // SubtleCrypto's verify method is async so we must make + // this method async as well. + const result = await window.crypto.subtle.verify(algo, cryptoKey, signatureArray, dataArray); + return result; + } + async sign(privateKey, data) { + const algo = { + name: 'RSASSA-PKCS1-v1_5', + hash: { name: 'SHA-256' }, + }; + const dataArray = new TextEncoder().encode(data); + const cryptoKey = await window.crypto.subtle.importKey('jwk', privateKey, algo, true, ['sign']); + // SubtleCrypto's sign method is async so we must make + // this method async as well. + const result = await window.crypto.subtle.sign(algo, cryptoKey, dataArray); + return base64js.fromByteArray(new Uint8Array(result)); + } + decodeBase64StringUtf8(base64) { + const uint8array = base64js.toByteArray(BrowserCrypto.padBase64(base64)); + const result = new TextDecoder().decode(uint8array); + return result; + } + encodeBase64StringUtf8(text) { + const uint8array = new TextEncoder().encode(text); + const result = base64js.fromByteArray(uint8array); + return result; + } + /** + * Computes the SHA-256 hash of the provided string. + * @param str The plain text string to hash. + * @return A promise that resolves with the SHA-256 hash of the provided + * string in hexadecimal encoding. + */ + async sha256DigestHex(str) { + // SubtleCrypto digest() method is async, so we must make + // this method async as well. + // To calculate SHA256 digest using SubtleCrypto, we first + // need to convert an input string to an ArrayBuffer: + const inputBuffer = new TextEncoder().encode(str); + // Result is ArrayBuffer as well. + const outputBuffer = await window.crypto.subtle.digest('SHA-256', inputBuffer); + return (0, crypto_1.fromArrayBufferToHex)(outputBuffer); + } + /** + * Computes the HMAC hash of a message using the provided crypto key and the + * SHA-256 algorithm. + * @param key The secret crypto key in utf-8 or ArrayBuffer format. + * @param msg The plain text message. + * @return A promise that resolves with the HMAC-SHA256 hash in ArrayBuffer + * format. + */ + async signWithHmacSha256(key, msg) { + // Convert key, if provided in ArrayBuffer format, to string. + const rawKey = typeof key === 'string' + ? key + : String.fromCharCode(...new Uint16Array(key)); + const enc = new TextEncoder(); + const cryptoKey = await window.crypto.subtle.importKey('raw', enc.encode(rawKey), { + name: 'HMAC', + hash: { + name: 'SHA-256', + }, + }, false, ['sign']); + return window.crypto.subtle.sign('HMAC', cryptoKey, enc.encode(msg)); + } +} +exports.BrowserCrypto = BrowserCrypto; + + +/***/ }), + +/***/ 88851: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/* global window */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createCrypto = createCrypto; +exports.hasBrowserCrypto = hasBrowserCrypto; +exports.fromArrayBufferToHex = fromArrayBufferToHex; +const crypto_1 = __nccwpck_require__(93438); +const crypto_2 = __nccwpck_require__(27388); +function createCrypto() { + if (hasBrowserCrypto()) { + return new crypto_1.BrowserCrypto(); + } + return new crypto_2.NodeCrypto(); +} +function hasBrowserCrypto() { + return (typeof window !== 'undefined' && + typeof window.crypto !== 'undefined' && + typeof window.crypto.subtle !== 'undefined'); +} +/** + * Converts an ArrayBuffer to a hexadecimal string. + * @param arrayBuffer The ArrayBuffer to convert to hexadecimal string. + * @return The hexadecimal encoding of the ArrayBuffer. + */ +function fromArrayBufferToHex(arrayBuffer) { + // Convert buffer to byte array. + const byteArray = Array.from(new Uint8Array(arrayBuffer)); + // Convert bytes to hex string. + return byteArray + .map(byte => { + return byte.toString(16).padStart(2, '0'); + }) + .join(''); +} + + +/***/ }), + +/***/ 27388: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.NodeCrypto = void 0; +const crypto = __nccwpck_require__(76982); +class NodeCrypto { + async sha256DigestBase64(str) { + return crypto.createHash('sha256').update(str).digest('base64'); + } + randomBytesBase64(count) { + return crypto.randomBytes(count).toString('base64'); + } + async verify(pubkey, data, signature) { + const verifier = crypto.createVerify('RSA-SHA256'); + verifier.update(data); + verifier.end(); + return verifier.verify(pubkey, signature, 'base64'); + } + async sign(privateKey, data) { + const signer = crypto.createSign('RSA-SHA256'); + signer.update(data); + signer.end(); + return signer.sign(privateKey, 'base64'); + } + decodeBase64StringUtf8(base64) { + return Buffer.from(base64, 'base64').toString('utf-8'); + } + encodeBase64StringUtf8(text) { + return Buffer.from(text, 'utf-8').toString('base64'); + } + /** + * Computes the SHA-256 hash of the provided string. + * @param str The plain text string to hash. + * @return A promise that resolves with the SHA-256 hash of the provided + * string in hexadecimal encoding. + */ + async sha256DigestHex(str) { + return crypto.createHash('sha256').update(str).digest('hex'); + } + /** + * Computes the HMAC hash of a message using the provided crypto key and the + * SHA-256 algorithm. + * @param key The secret crypto key in utf-8 or ArrayBuffer format. + * @param msg The plain text message. + * @return A promise that resolves with the HMAC-SHA256 hash in ArrayBuffer + * format. + */ + async signWithHmacSha256(key, msg) { + const cryptoKey = typeof key === 'string' ? key : toBuffer(key); + return toArrayBuffer(crypto.createHmac('sha256', cryptoKey).update(msg).digest()); + } +} +exports.NodeCrypto = NodeCrypto; +/** + * Converts a Node.js Buffer to an ArrayBuffer. + * https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer + * @param buffer The Buffer input to covert. + * @return The ArrayBuffer representation of the input. + */ +function toArrayBuffer(buffer) { + return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); +} +/** + * Converts an ArrayBuffer to a Node.js Buffer. + * @param arrayBuffer The ArrayBuffer input to covert. + * @return The Buffer representation of the input. + */ +function toBuffer(arrayBuffer) { + return Buffer.from(arrayBuffer); +} + + +/***/ }), + +/***/ 492: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GoogleAuth = exports.auth = exports.DefaultTransporter = exports.PassThroughClient = exports.ExecutableError = exports.PluggableAuthClient = exports.DownscopedClient = exports.BaseExternalAccountClient = exports.ExternalAccountClient = exports.IdentityPoolClient = exports.AwsRequestSigner = exports.AwsClient = exports.UserRefreshClient = exports.LoginTicket = exports.ClientAuthentication = exports.OAuth2Client = exports.CodeChallengeMethod = exports.Impersonated = exports.JWT = exports.JWTAccess = exports.IdTokenClient = exports.IAMAuth = exports.GCPEnv = exports.Compute = exports.DEFAULT_UNIVERSE = exports.AuthClient = exports.gaxios = exports.gcpMetadata = void 0; +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +const googleauth_1 = __nccwpck_require__(95934); +Object.defineProperty(exports, "GoogleAuth", ({ enumerable: true, get: function () { return googleauth_1.GoogleAuth; } })); +// Export common deps to ensure types/instances are the exact match. Useful +// for consistently configuring the library across versions. +exports.gcpMetadata = __nccwpck_require__(23046); +exports.gaxios = __nccwpck_require__(97003); +var authclient_1 = __nccwpck_require__(34810); +Object.defineProperty(exports, "AuthClient", ({ enumerable: true, get: function () { return authclient_1.AuthClient; } })); +Object.defineProperty(exports, "DEFAULT_UNIVERSE", ({ enumerable: true, get: function () { return authclient_1.DEFAULT_UNIVERSE; } })); +var computeclient_1 = __nccwpck_require__(20977); +Object.defineProperty(exports, "Compute", ({ enumerable: true, get: function () { return computeclient_1.Compute; } })); +var envDetect_1 = __nccwpck_require__(60963); +Object.defineProperty(exports, "GCPEnv", ({ enumerable: true, get: function () { return envDetect_1.GCPEnv; } })); +var iam_1 = __nccwpck_require__(89390); +Object.defineProperty(exports, "IAMAuth", ({ enumerable: true, get: function () { return iam_1.IAMAuth; } })); +var idtokenclient_1 = __nccwpck_require__(12718); +Object.defineProperty(exports, "IdTokenClient", ({ enumerable: true, get: function () { return idtokenclient_1.IdTokenClient; } })); +var jwtaccess_1 = __nccwpck_require__(27060); +Object.defineProperty(exports, "JWTAccess", ({ enumerable: true, get: function () { return jwtaccess_1.JWTAccess; } })); +var jwtclient_1 = __nccwpck_require__(75277); +Object.defineProperty(exports, "JWT", ({ enumerable: true, get: function () { return jwtclient_1.JWT; } })); +var impersonated_1 = __nccwpck_require__(39964); +Object.defineProperty(exports, "Impersonated", ({ enumerable: true, get: function () { return impersonated_1.Impersonated; } })); +var oauth2client_1 = __nccwpck_require__(10091); +Object.defineProperty(exports, "CodeChallengeMethod", ({ enumerable: true, get: function () { return oauth2client_1.CodeChallengeMethod; } })); +Object.defineProperty(exports, "OAuth2Client", ({ enumerable: true, get: function () { return oauth2client_1.OAuth2Client; } })); +Object.defineProperty(exports, "ClientAuthentication", ({ enumerable: true, get: function () { return oauth2client_1.ClientAuthentication; } })); +var loginticket_1 = __nccwpck_require__(53882); +Object.defineProperty(exports, "LoginTicket", ({ enumerable: true, get: function () { return loginticket_1.LoginTicket; } })); +var refreshclient_1 = __nccwpck_require__(99807); +Object.defineProperty(exports, "UserRefreshClient", ({ enumerable: true, get: function () { return refreshclient_1.UserRefreshClient; } })); +var awsclient_1 = __nccwpck_require__(81261); +Object.defineProperty(exports, "AwsClient", ({ enumerable: true, get: function () { return awsclient_1.AwsClient; } })); +var awsrequestsigner_1 = __nccwpck_require__(27647); +Object.defineProperty(exports, "AwsRequestSigner", ({ enumerable: true, get: function () { return awsrequestsigner_1.AwsRequestSigner; } })); +var identitypoolclient_1 = __nccwpck_require__(29960); +Object.defineProperty(exports, "IdentityPoolClient", ({ enumerable: true, get: function () { return identitypoolclient_1.IdentityPoolClient; } })); +var externalclient_1 = __nccwpck_require__(88323); +Object.defineProperty(exports, "ExternalAccountClient", ({ enumerable: true, get: function () { return externalclient_1.ExternalAccountClient; } })); +var baseexternalclient_1 = __nccwpck_require__(142); +Object.defineProperty(exports, "BaseExternalAccountClient", ({ enumerable: true, get: function () { return baseexternalclient_1.BaseExternalAccountClient; } })); +var downscopedclient_1 = __nccwpck_require__(77556); +Object.defineProperty(exports, "DownscopedClient", ({ enumerable: true, get: function () { return downscopedclient_1.DownscopedClient; } })); +var pluggable_auth_client_1 = __nccwpck_require__(46077); +Object.defineProperty(exports, "PluggableAuthClient", ({ enumerable: true, get: function () { return pluggable_auth_client_1.PluggableAuthClient; } })); +Object.defineProperty(exports, "ExecutableError", ({ enumerable: true, get: function () { return pluggable_auth_client_1.ExecutableError; } })); +var passthrough_1 = __nccwpck_require__(62045); +Object.defineProperty(exports, "PassThroughClient", ({ enumerable: true, get: function () { return passthrough_1.PassThroughClient; } })); +var transporters_1 = __nccwpck_require__(67633); +Object.defineProperty(exports, "DefaultTransporter", ({ enumerable: true, get: function () { return transporters_1.DefaultTransporter; } })); +const auth = new googleauth_1.GoogleAuth(); +exports.auth = auth; + + +/***/ }), + +/***/ 78290: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.validate = validate; +// Accepts an options object passed from the user to the API. In the +// previous version of the API, it referred to a `Request` options object. +// Now it refers to an Axiox Request Config object. This is here to help +// ensure users don't pass invalid options when they upgrade from 0.x to 1.x. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function validate(options) { + const vpairs = [ + { invalid: 'uri', expected: 'url' }, + { invalid: 'json', expected: 'data' }, + { invalid: 'qs', expected: 'params' }, + ]; + for (const pair of vpairs) { + if (options[pair.invalid]) { + const e = `'${pair.invalid}' is not a valid configuration option. Please use '${pair.expected}' instead. This library is using Axios for requests. Please see https://github.com/axios/axios to learn more about the valid request options.`; + throw new Error(e); + } + } +} + + +/***/ }), + +/***/ 67633: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.DefaultTransporter = void 0; +const gaxios_1 = __nccwpck_require__(97003); +const options_1 = __nccwpck_require__(78290); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const pkg = __nccwpck_require__(96066); +const PRODUCT_NAME = 'google-api-nodejs-client'; +class DefaultTransporter { + constructor() { + /** + * A configurable, replacable `Gaxios` instance. + */ + this.instance = new gaxios_1.Gaxios(); + } + /** + * Configures request options before making a request. + * @param opts GaxiosOptions options. + * @return Configured options. + */ + configure(opts = {}) { + opts.headers = opts.headers || {}; + if (typeof window === 'undefined') { + // set transporter user agent if not in browser + const uaValue = opts.headers['User-Agent']; + if (!uaValue) { + opts.headers['User-Agent'] = DefaultTransporter.USER_AGENT; + } + else if (!uaValue.includes(`${PRODUCT_NAME}/`)) { + opts.headers['User-Agent'] = + `${uaValue} ${DefaultTransporter.USER_AGENT}`; + } + // track google-auth-library-nodejs version: + if (!opts.headers['x-goog-api-client']) { + const nodeVersion = process.version.replace(/^v/, ''); + opts.headers['x-goog-api-client'] = `gl-node/${nodeVersion}`; + } + } + return opts; + } + /** + * Makes a request using Gaxios with given options. + * @param opts GaxiosOptions options. + * @param callback optional callback that contains GaxiosResponse object. + * @return GaxiosPromise, assuming no callback is passed. + */ + request(opts) { + // ensure the user isn't passing in request-style options + opts = this.configure(opts); + (0, options_1.validate)(opts); + return this.instance.request(opts).catch(e => { + throw this.processError(e); + }); + } + get defaults() { + return this.instance.defaults; + } + set defaults(opts) { + this.instance.defaults = opts; + } + /** + * Changes the error to include details from the body. + */ + processError(e) { + const res = e.response; + const err = e; + const body = res ? res.data : null; + if (res && body && body.error && res.status !== 200) { + if (typeof body.error === 'string') { + err.message = body.error; + err.status = res.status; + } + else if (Array.isArray(body.error.errors)) { + err.message = body.error.errors + .map((err2) => err2.message) + .join('\n'); + err.code = body.error.code; + err.errors = body.error.errors; + } + else { + err.message = body.error.message; + err.code = body.error.code; + } + } + else if (res && res.status >= 400) { + // Consider all 4xx and 5xx responses errors. + err.message = body; + err.status = res.status; + } + return err; + } +} +exports.DefaultTransporter = DefaultTransporter; +/** + * Default user agent. + */ +DefaultTransporter.USER_AGENT = `${PRODUCT_NAME}/${pkg.version}`; + + +/***/ }), + +/***/ 37870: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _LRUCache_instances, _LRUCache_cache, _LRUCache_moveToEnd, _LRUCache_evict; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.LRUCache = void 0; +exports.snakeToCamel = snakeToCamel; +exports.originalOrCamelOptions = originalOrCamelOptions; +/** + * Returns the camel case of a provided string. + * + * @remarks + * + * Match any `_` and not `_` pair, then return the uppercase of the not `_` + * character. + * + * @internal + * + * @param str the string to convert + * @returns the camelCase'd string + */ +function snakeToCamel(str) { + return str.replace(/([_][^_])/g, match => match.slice(1).toUpperCase()); +} +/** + * Get the value of `obj[key]` or `obj[camelCaseKey]`, with a preference + * for original, non-camelCase key. + * + * @param obj object to lookup a value in + * @returns a `get` function for getting `obj[key || snakeKey]`, if available + */ +function originalOrCamelOptions(obj) { + /** + * + * @param key an index of object, preferably snake_case + * @returns the value `obj[key || snakeKey]`, if available + */ + function get(key) { + var _a; + const o = (obj || {}); + return (_a = o[key]) !== null && _a !== void 0 ? _a : o[snakeToCamel(key)]; + } + return { get }; +} +/** + * A simple LRU cache utility. + * Not meant for external usage. + * + * @experimental + * @internal + */ +class LRUCache { + constructor(options) { + _LRUCache_instances.add(this); + /** + * Maps are in order. Thus, the older item is the first item. + * + * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map} + */ + _LRUCache_cache.set(this, new Map()); + this.capacity = options.capacity; + this.maxAge = options.maxAge; + } + /** + * Add an item to the cache. + * + * @param key the key to upsert + * @param value the value of the key + */ + set(key, value) { + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_moveToEnd).call(this, key, value); + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_evict).call(this); + } + /** + * Get an item from the cache. + * + * @param key the key to retrieve + */ + get(key) { + const item = __classPrivateFieldGet(this, _LRUCache_cache, "f").get(key); + if (!item) + return; + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_moveToEnd).call(this, key, item.value); + __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_evict).call(this); + return item.value; + } +} +exports.LRUCache = LRUCache; +_LRUCache_cache = new WeakMap(), _LRUCache_instances = new WeakSet(), _LRUCache_moveToEnd = function _LRUCache_moveToEnd(key, value) { + __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(key); + __classPrivateFieldGet(this, _LRUCache_cache, "f").set(key, { + value, + lastAccessed: Date.now(), + }); +}, _LRUCache_evict = function _LRUCache_evict() { + const cutoffDate = this.maxAge ? Date.now() - this.maxAge : 0; + /** + * Because we know Maps are in order, this item is both the + * last item in the list (capacity) and oldest (maxAge). + */ + let oldestItem = __classPrivateFieldGet(this, _LRUCache_cache, "f").entries().next(); + while (!oldestItem.done && + (__classPrivateFieldGet(this, _LRUCache_cache, "f").size > this.capacity || // too many + oldestItem.value[1].lastAccessed < cutoffDate) // too old + ) { + __classPrivateFieldGet(this, _LRUCache_cache, "f").delete(oldestItem.value[0]); + oldestItem = __classPrivateFieldGet(this, _LRUCache_cache, "f").entries().next(); + } +}; + + +/***/ }), + +/***/ 71628: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Colours = void 0; +/** + * Handles figuring out if we can use ANSI colours and handing out the escape codes. + * + * This is for package-internal use only, and may change at any time. + * + * @private + * @internal + */ +class Colours { + /** + * @param stream The stream (e.g. process.stderr) + * @returns true if the stream should have colourization enabled + */ + static isEnabled(stream) { + return (stream.isTTY && + (typeof stream.getColorDepth === 'function' + ? stream.getColorDepth() > 2 + : true)); + } + static refresh() { + Colours.enabled = Colours.isEnabled(process.stderr); + if (!this.enabled) { + Colours.reset = ''; + Colours.bright = ''; + Colours.dim = ''; + Colours.red = ''; + Colours.green = ''; + Colours.yellow = ''; + Colours.blue = ''; + Colours.magenta = ''; + Colours.cyan = ''; + Colours.white = ''; + Colours.grey = ''; + } + else { + Colours.reset = '\u001b[0m'; + Colours.bright = '\u001b[1m'; + Colours.dim = '\u001b[2m'; + Colours.red = '\u001b[31m'; + Colours.green = '\u001b[32m'; + Colours.yellow = '\u001b[33m'; + Colours.blue = '\u001b[34m'; + Colours.magenta = '\u001b[35m'; + Colours.cyan = '\u001b[36m'; + Colours.white = '\u001b[37m'; + Colours.grey = '\u001b[90m'; + } + } +} +exports.Colours = Colours; +Colours.enabled = false; +Colours.reset = ''; +Colours.bright = ''; +Colours.dim = ''; +Colours.red = ''; +Colours.green = ''; +Colours.yellow = ''; +Colours.blue = ''; +Colours.magenta = ''; +Colours.cyan = ''; +Colours.white = ''; +Colours.grey = ''; +Colours.refresh(); +//# sourceMappingURL=colours.js.map + +/***/ }), + +/***/ 81577: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__nccwpck_require__(74788), exports); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 74788: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2021-2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.env = exports.DebugLogBackendBase = exports.placeholder = exports.AdhocDebugLogger = exports.LogSeverity = void 0; +exports.getNodeBackend = getNodeBackend; +exports.getDebugBackend = getDebugBackend; +exports.getStructuredBackend = getStructuredBackend; +exports.setBackend = setBackend; +exports.log = log; +const node_events_1 = __nccwpck_require__(78474); +const process = __importStar(__nccwpck_require__(1708)); +const util = __importStar(__nccwpck_require__(57975)); +const colours_1 = __nccwpck_require__(71628); +// Some functions (as noted) are based on the Node standard library, from +// the following file: +// +// https://github.com/nodejs/node/blob/main/lib/internal/util/debuglog.js +/** + * This module defines an ad-hoc debug logger for Google Cloud Platform + * client libraries in Node. An ad-hoc debug logger is a tool which lets + * users use an external, unified interface (in this case, environment + * variables) to determine what logging they want to see at runtime. This + * isn't necessarily fed into the console, but is meant to be under the + * control of the user. The kind of logging that will be produced by this + * is more like "call retry happened", not "event you'd want to record + * in Cloud Logger". + * + * More for Googlers implementing libraries with it: + * go/cloud-client-logging-design + */ +/** + * Possible log levels. These are a subset of Cloud Observability levels. + * https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity + */ +var LogSeverity; +(function (LogSeverity) { + LogSeverity["DEFAULT"] = "DEFAULT"; + LogSeverity["DEBUG"] = "DEBUG"; + LogSeverity["INFO"] = "INFO"; + LogSeverity["WARNING"] = "WARNING"; + LogSeverity["ERROR"] = "ERROR"; +})(LogSeverity || (exports.LogSeverity = LogSeverity = {})); +/** + * Our logger instance. This actually contains the meat of dealing + * with log lines, including EventEmitter. This contains the function + * that will be passed back to users of the package. + */ +class AdhocDebugLogger extends node_events_1.EventEmitter { + /** + * @param upstream The backend will pass a function that will be + * called whenever our logger function is invoked. + */ + constructor(namespace, upstream) { + super(); + this.namespace = namespace; + this.upstream = upstream; + this.func = Object.assign(this.invoke.bind(this), { + // Also add an instance pointer back to us. + instance: this, + // And pull over the EventEmitter functionality. + on: (event, listener) => this.on(event, listener), + }); + // Convenience methods for log levels. + this.func.debug = (...args) => this.invokeSeverity(LogSeverity.DEBUG, ...args); + this.func.info = (...args) => this.invokeSeverity(LogSeverity.INFO, ...args); + this.func.warn = (...args) => this.invokeSeverity(LogSeverity.WARNING, ...args); + this.func.error = (...args) => this.invokeSeverity(LogSeverity.ERROR, ...args); + this.func.sublog = (namespace) => log(namespace, this.func); + } + invoke(fields, ...args) { + // Push out any upstream logger first. + if (this.upstream) { + this.upstream(fields, ...args); + } + // Emit sink events. + this.emit('log', fields, args); + } + invokeSeverity(severity, ...args) { + this.invoke({ severity }, ...args); + } +} +exports.AdhocDebugLogger = AdhocDebugLogger; +/** + * This can be used in place of a real logger while waiting for Promises or disabling logging. + */ +exports.placeholder = new AdhocDebugLogger('', () => { }).func; +/** + * The base class for debug logging backends. It's possible to use this, but the + * same non-guarantees above still apply (unstable interface, etc). + * + * @private + * @internal + */ +class DebugLogBackendBase { + constructor() { + var _a; + this.cached = new Map(); + this.filters = []; + this.filtersSet = false; + // Look for the Node config variable for what systems to enable. We'll store + // these for the log method below, which will call setFilters() once. + let nodeFlag = (_a = process.env[exports.env.nodeEnables]) !== null && _a !== void 0 ? _a : '*'; + if (nodeFlag === 'all') { + nodeFlag = '*'; + } + this.filters = nodeFlag.split(','); + } + log(namespace, fields, ...args) { + try { + if (!this.filtersSet) { + this.setFilters(); + this.filtersSet = true; + } + let logger = this.cached.get(namespace); + if (!logger) { + logger = this.makeLogger(namespace); + this.cached.set(namespace, logger); + } + logger(fields, ...args); + } + catch (e) { + // Silently ignore all errors; we don't want them to interfere with + // the user's running app. + // e; + console.error(e); + } + } +} +exports.DebugLogBackendBase = DebugLogBackendBase; +// The basic backend. This one definitely works, but it's less feature-filled. +// +// Rather than using util.debuglog, this implements the same basic logic directly. +// The reason for this decision is that debuglog checks the value of the +// NODE_DEBUG environment variable before any user code runs; we therefore +// can't pipe our own enables into it (and util.debuglog will never print unless +// the user duplicates it into NODE_DEBUG, which isn't reasonable). +// +class NodeBackend extends DebugLogBackendBase { + constructor() { + super(...arguments); + // Default to allowing all systems, since we gate earlier based on whether the + // variable is empty. + this.enabledRegexp = /.*/g; + } + isEnabled(namespace) { + return this.enabledRegexp.test(namespace); + } + makeLogger(namespace) { + if (!this.enabledRegexp.test(namespace)) { + return () => { }; + } + return (fields, ...args) => { + var _a; + // TODO: `fields` needs to be turned into a string here, one way or another. + const nscolour = `${colours_1.Colours.green}${namespace}${colours_1.Colours.reset}`; + const pid = `${colours_1.Colours.yellow}${process.pid}${colours_1.Colours.reset}`; + let level; + switch (fields.severity) { + case LogSeverity.ERROR: + level = `${colours_1.Colours.red}${fields.severity}${colours_1.Colours.reset}`; + break; + case LogSeverity.INFO: + level = `${colours_1.Colours.magenta}${fields.severity}${colours_1.Colours.reset}`; + break; + case LogSeverity.WARNING: + level = `${colours_1.Colours.yellow}${fields.severity}${colours_1.Colours.reset}`; + break; + default: + level = (_a = fields.severity) !== null && _a !== void 0 ? _a : LogSeverity.DEFAULT; + break; + } + const msg = util.formatWithOptions({ colors: colours_1.Colours.enabled }, ...args); + const filteredFields = Object.assign({}, fields); + delete filteredFields.severity; + const fieldsJson = Object.getOwnPropertyNames(filteredFields).length + ? JSON.stringify(filteredFields) + : ''; + const fieldsColour = fieldsJson + ? `${colours_1.Colours.grey}${fieldsJson}${colours_1.Colours.reset}` + : ''; + console.error('%s [%s|%s] %s%s', pid, nscolour, level, msg, fieldsJson ? ` ${fieldsColour}` : ''); + }; + } + // Regexp patterns below are from here: + // https://github.com/nodejs/node/blob/c0aebed4b3395bd65d54b18d1fd00f071002ac20/lib/internal/util/debuglog.js#L36 + setFilters() { + const totalFilters = this.filters.join(','); + const regexp = totalFilters + .replace(/[|\\{}()[\]^$+?.]/g, '\\$&') + .replace(/\*/g, '.*') + .replace(/,/g, '$|^'); + this.enabledRegexp = new RegExp(`^${regexp}$`, 'i'); + } +} +/** + * @returns A backend based on Node util.debuglog; this is the default. + */ +function getNodeBackend() { + return new NodeBackend(); +} +class DebugBackend extends DebugLogBackendBase { + constructor(pkg) { + super(); + this.debugPkg = pkg; + } + makeLogger(namespace) { + const debugLogger = this.debugPkg(namespace); + return (fields, ...args) => { + // TODO: `fields` needs to be turned into a string here. + debugLogger(args[0], ...args.slice(1)); + }; + } + setFilters() { + var _a; + const existingFilters = (_a = process.env['NODE_DEBUG']) !== null && _a !== void 0 ? _a : ''; + process.env['NODE_DEBUG'] = `${existingFilters}${existingFilters ? ',' : ''}${this.filters.join(',')}`; + } +} +/** + * Creates a "debug" package backend. The user must call require('debug') and pass + * the resulting object to this function. + * + * ``` + * setBackend(getDebugBackend(require('debug'))) + * ``` + * + * https://www.npmjs.com/package/debug + * + * Note: Google does not explicitly endorse or recommend this package; it's just + * being provided as an option. + * + * @returns A backend based on the npm "debug" package. + */ +function getDebugBackend(debugPkg) { + return new DebugBackend(debugPkg); +} +/** + * This pretty much works like the Node logger, but it outputs structured + * logging JSON matching Google Cloud's ingestion specs. Rather than handling + * its own output, it wraps another backend. The passed backend must be a subclass + * of `DebugLogBackendBase` (any of the backends exposed by this package will work). + */ +class StructuredBackend extends DebugLogBackendBase { + constructor(upstream) { + var _a; + super(); + this.upstream = (_a = upstream) !== null && _a !== void 0 ? _a : new NodeBackend(); + } + makeLogger(namespace) { + const debugLogger = this.upstream.makeLogger(namespace); + return (fields, ...args) => { + var _a; + const severity = (_a = fields.severity) !== null && _a !== void 0 ? _a : LogSeverity.INFO; + const json = Object.assign({ + severity, + message: util.format(...args), + }, fields); + const jsonString = JSON.stringify(json); + debugLogger(fields, jsonString); + }; + } + setFilters() { + this.upstream.setFilters(); + } +} +/** + * Creates a "structured logging" backend. This pretty much works like the + * Node logger, but it outputs structured logging JSON matching Google + * Cloud's ingestion specs instead of plain text. + * + * ``` + * setBackend(getStructuredBackend()) + * ``` + * + * @param upstream If you want to use something besides the Node backend to + * write the actual log lines into, pass that here. + * @returns A backend based on Google Cloud structured logging. + */ +function getStructuredBackend(upstream) { + return new StructuredBackend(upstream); +} +/** + * The environment variables that we standardized on, for all ad-hoc logging. + */ +exports.env = { + /** + * Filter wildcards specific to the Node syntax, and similar to the built-in + * utils.debuglog() environment variable. If missing, disables logging. + */ + nodeEnables: 'GOOGLE_SDK_NODE_LOGGING', +}; +// Keep a copy of all namespaced loggers so users can reliably .on() them. +// Note that these cached functions will need to deal with changes in the backend. +const loggerCache = new Map(); +// Our current global backend. This might be: +let cachedBackend = undefined; +/** + * Set the backend to use for our log output. + * - A backend object + * - null to disable logging + * - undefined for "nothing yet", defaults to the Node backend + * + * @param backend Results from one of the get*Backend() functions. + */ +function setBackend(backend) { + cachedBackend = backend; + loggerCache.clear(); +} +/** + * Creates a logging function. Multiple calls to this with the same namespace + * will produce the same logger, with the same event emitter hooks. + * + * Namespaces can be a simple string ("system" name), or a qualified string + * (system:subsystem), which can be used for filtering, or for "system:*". + * + * @param namespace The namespace, a descriptive text string. + * @returns A function you can call that works similar to console.log(). + */ +function log(namespace, parent) { + // If the enable flag isn't set, do nothing. + const enablesFlag = process.env[exports.env.nodeEnables]; + if (!enablesFlag) { + return exports.placeholder; + } + // This might happen mostly if the typings are dropped in a user's code, + // or if they're calling from JavaScript. + if (!namespace) { + return exports.placeholder; + } + // Handle sub-loggers. + if (parent) { + namespace = `${parent.instance.namespace}:${namespace}`; + } + // Reuse loggers so things like event sinks are persistent. + const existing = loggerCache.get(namespace); + if (existing) { + return existing.func; + } + // Do we have a backend yet? + if (cachedBackend === null) { + // Explicitly disabled. + return exports.placeholder; + } + else if (cachedBackend === undefined) { + // One hasn't been made yet, so default to Node. + cachedBackend = getNodeBackend(); + } + // The logger is further wrapped so we can handle the backend changing out. + const logger = (() => { + let previousBackend = undefined; + const newLogger = new AdhocDebugLogger(namespace, (fields, ...args) => { + if (previousBackend !== cachedBackend) { + // Did the user pass a custom backend? + if (cachedBackend === null) { + // Explicitly disabled. + return; + } + else if (cachedBackend === undefined) { + // One hasn't been made yet, so default to Node. + cachedBackend = getNodeBackend(); + } + previousBackend = cachedBackend; + } + cachedBackend === null || cachedBackend === void 0 ? void 0 : cachedBackend.log(namespace, fields, ...args); + }); + return newLogger; + })(); + loggerCache.set(namespace, logger); + return logger.func; +} +//# sourceMappingURL=logging-utils.js.map + +/***/ }), + +/***/ 28568: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/** + * Copyright 2018 Google LLC + * + * Distributed under MIT license. + * See file LICENSE for detail or copy at https://opensource.org/licenses/MIT + */ +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _GoogleToken_instances, _GoogleToken_inFlightRequest, _GoogleToken_getTokenAsync, _GoogleToken_getTokenAsyncInner, _GoogleToken_ensureEmail, _GoogleToken_revokeTokenAsync, _GoogleToken_configure, _GoogleToken_requestToken; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.GoogleToken = void 0; +const fs = __nccwpck_require__(79896); +const gaxios_1 = __nccwpck_require__(97003); +const jws = __nccwpck_require__(33324); +const path = __nccwpck_require__(16928); +const util_1 = __nccwpck_require__(39023); +const readFile = fs.readFile + ? (0, util_1.promisify)(fs.readFile) + : async () => { + // if running in the web-browser, fs.readFile may not have been shimmed. + throw new ErrorWithCode('use key rather than keyFile.', 'MISSING_CREDENTIALS'); + }; +const GOOGLE_TOKEN_URL = 'https://www.googleapis.com/oauth2/v4/token'; +const GOOGLE_REVOKE_TOKEN_URL = 'https://accounts.google.com/o/oauth2/revoke?token='; +class ErrorWithCode extends Error { + constructor(message, code) { + super(message); + this.code = code; + } +} +class GoogleToken { + get accessToken() { + return this.rawToken ? this.rawToken.access_token : undefined; + } + get idToken() { + return this.rawToken ? this.rawToken.id_token : undefined; + } + get tokenType() { + return this.rawToken ? this.rawToken.token_type : undefined; + } + get refreshToken() { + return this.rawToken ? this.rawToken.refresh_token : undefined; + } + /** + * Create a GoogleToken. + * + * @param options Configuration object. + */ + constructor(options) { + _GoogleToken_instances.add(this); + this.transporter = { + request: opts => (0, gaxios_1.request)(opts), + }; + _GoogleToken_inFlightRequest.set(this, void 0); + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_configure).call(this, options); + } + /** + * Returns whether the token has expired. + * + * @return true if the token has expired, false otherwise. + */ + hasExpired() { + const now = new Date().getTime(); + if (this.rawToken && this.expiresAt) { + return now >= this.expiresAt; + } + else { + return true; + } + } + /** + * Returns whether the token will expire within eagerRefreshThresholdMillis + * + * @return true if the token will be expired within eagerRefreshThresholdMillis, false otherwise. + */ + isTokenExpiring() { + var _a; + const now = new Date().getTime(); + const eagerRefreshThresholdMillis = (_a = this.eagerRefreshThresholdMillis) !== null && _a !== void 0 ? _a : 0; + if (this.rawToken && this.expiresAt) { + return this.expiresAt <= now + eagerRefreshThresholdMillis; + } + else { + return true; + } + } + getToken(callback, opts = {}) { + if (typeof callback === 'object') { + opts = callback; + callback = undefined; + } + opts = Object.assign({ + forceRefresh: false, + }, opts); + if (callback) { + const cb = callback; + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_getTokenAsync).call(this, opts).then(t => cb(null, t), callback); + return; + } + return __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_getTokenAsync).call(this, opts); + } + /** + * Given a keyFile, extract the key and client email if available + * @param keyFile Path to a json, pem, or p12 file that contains the key. + * @returns an object with privateKey and clientEmail properties + */ + async getCredentials(keyFile) { + const ext = path.extname(keyFile); + switch (ext) { + case '.json': { + const key = await readFile(keyFile, 'utf8'); + const body = JSON.parse(key); + const privateKey = body.private_key; + const clientEmail = body.client_email; + if (!privateKey || !clientEmail) { + throw new ErrorWithCode('private_key and client_email are required.', 'MISSING_CREDENTIALS'); + } + return { privateKey, clientEmail }; + } + case '.der': + case '.crt': + case '.pem': { + const privateKey = await readFile(keyFile, 'utf8'); + return { privateKey }; + } + case '.p12': + case '.pfx': { + throw new ErrorWithCode('*.p12 certificates are not supported after v6.1.2. ' + + 'Consider utilizing *.json format or converting *.p12 to *.pem using the OpenSSL CLI.', 'UNKNOWN_CERTIFICATE_TYPE'); + } + default: + throw new ErrorWithCode('Unknown certificate type. Type is determined based on file extension. ' + + 'Current supported extensions are *.json, and *.pem.', 'UNKNOWN_CERTIFICATE_TYPE'); + } + } + revokeToken(callback) { + if (callback) { + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_revokeTokenAsync).call(this).then(() => callback(), callback); + return; + } + return __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_revokeTokenAsync).call(this); + } +} +exports.GoogleToken = GoogleToken; +_GoogleToken_inFlightRequest = new WeakMap(), _GoogleToken_instances = new WeakSet(), _GoogleToken_getTokenAsync = async function _GoogleToken_getTokenAsync(opts) { + if (__classPrivateFieldGet(this, _GoogleToken_inFlightRequest, "f") && !opts.forceRefresh) { + return __classPrivateFieldGet(this, _GoogleToken_inFlightRequest, "f"); + } + try { + return await (__classPrivateFieldSet(this, _GoogleToken_inFlightRequest, __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_getTokenAsyncInner).call(this, opts), "f")); + } + finally { + __classPrivateFieldSet(this, _GoogleToken_inFlightRequest, undefined, "f"); + } +}, _GoogleToken_getTokenAsyncInner = async function _GoogleToken_getTokenAsyncInner(opts) { + if (this.isTokenExpiring() === false && opts.forceRefresh === false) { + return Promise.resolve(this.rawToken); + } + if (!this.key && !this.keyFile) { + throw new Error('No key or keyFile set.'); + } + if (!this.key && this.keyFile) { + const creds = await this.getCredentials(this.keyFile); + this.key = creds.privateKey; + this.iss = creds.clientEmail || this.iss; + if (!creds.clientEmail) { + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_ensureEmail).call(this); + } + } + return __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_requestToken).call(this); +}, _GoogleToken_ensureEmail = function _GoogleToken_ensureEmail() { + if (!this.iss) { + throw new ErrorWithCode('email is required.', 'MISSING_CREDENTIALS'); + } +}, _GoogleToken_revokeTokenAsync = async function _GoogleToken_revokeTokenAsync() { + if (!this.accessToken) { + throw new Error('No token to revoke.'); + } + const url = GOOGLE_REVOKE_TOKEN_URL + this.accessToken; + await this.transporter.request({ + url, + retry: true, + }); + __classPrivateFieldGet(this, _GoogleToken_instances, "m", _GoogleToken_configure).call(this, { + email: this.iss, + sub: this.sub, + key: this.key, + keyFile: this.keyFile, + scope: this.scope, + additionalClaims: this.additionalClaims, + }); +}, _GoogleToken_configure = function _GoogleToken_configure(options = {}) { + this.keyFile = options.keyFile; + this.key = options.key; + this.rawToken = undefined; + this.iss = options.email || options.iss; + this.sub = options.sub; + this.additionalClaims = options.additionalClaims; + if (typeof options.scope === 'object') { + this.scope = options.scope.join(' '); + } + else { + this.scope = options.scope; + } + this.eagerRefreshThresholdMillis = options.eagerRefreshThresholdMillis; + if (options.transporter) { + this.transporter = options.transporter; + } +}, _GoogleToken_requestToken = +/** + * Request the token from Google. + */ +async function _GoogleToken_requestToken() { + var _a, _b; + const iat = Math.floor(new Date().getTime() / 1000); + const additionalClaims = this.additionalClaims || {}; + const payload = Object.assign({ + iss: this.iss, + scope: this.scope, + aud: GOOGLE_TOKEN_URL, + exp: iat + 3600, + iat, + sub: this.sub, + }, additionalClaims); + const signedJWT = jws.sign({ + header: { alg: 'RS256' }, + payload, + secret: this.key, + }); + try { + const r = await this.transporter.request({ + method: 'POST', + url: GOOGLE_TOKEN_URL, + data: { + grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', + assertion: signedJWT, + }, + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'json', + retryConfig: { + httpMethodsToRetry: ['POST'], + }, + }); + this.rawToken = r.data; + this.expiresAt = + r.data.expires_in === null || r.data.expires_in === undefined + ? undefined + : (iat + r.data.expires_in) * 1000; + return this.rawToken; + } + catch (e) { + this.rawToken = undefined; + this.tokenExpires = undefined; + const body = e.response && ((_a = e.response) === null || _a === void 0 ? void 0 : _a.data) + ? (_b = e.response) === null || _b === void 0 ? void 0 : _b.data + : {}; + if (body.error) { + const desc = body.error_description + ? `: ${body.error_description}` + : ''; + e.message = `${body.error}${desc}`; + } + throw e; + } +}; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 77847: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const net_1 = __importDefault(__nccwpck_require__(69278)); +const tls_1 = __importDefault(__nccwpck_require__(64756)); +const url_1 = __importDefault(__nccwpck_require__(87016)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const once_1 = __importDefault(__nccwpck_require__(48662)); +const agent_base_1 = __nccwpck_require__(32960); +const debug = (0, debug_1.default)('http-proxy-agent'); +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +/** + * The `HttpProxyAgent` implements an HTTP Agent subclass that connects + * to the specified "HTTP proxy server" in order to proxy HTTP requests. + * + * @api public + */ +class HttpProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('Creating new HttpProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + const parsed = url_1.default.parse(req.path); + if (!parsed.protocol) { + parsed.protocol = 'http:'; + } + if (!parsed.hostname) { + parsed.hostname = opts.hostname || opts.host || null; + } + if (parsed.port == null && typeof opts.port) { + parsed.port = String(opts.port); + } + if (parsed.port === '80') { + // if port is 80, then we can remove the port so that the + // ":80" portion is not on the produced URL + parsed.port = ''; + } + // Change the `http.ClientRequest` instance's "path" field + // to the absolute path of the URL that will be requested. + req.path = url_1.default.format(parsed); + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + req.setHeader('Proxy-Authorization', `Basic ${Buffer.from(proxy.auth).toString('base64')}`); + } + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + // At this point, the http ClientRequest's internal `_header` field + // might have already been set. If this is the case then we'll need + // to re-generate the string since we just changed the `req.path`. + if (req._header) { + let first; + let endOfHeaders; + debug('Regenerating stored HTTP header string for request'); + req._header = null; + req._implicitHeader(); + if (req.output && req.output.length > 0) { + // Node < 12 + debug('Patching connection write() output buffer with updated header'); + first = req.output[0]; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.output[0] = req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.output); + } + else if (req.outputData && req.outputData.length > 0) { + // Node >= 12 + debug('Patching connection write() output buffer with updated header'); + first = req.outputData[0].data; + endOfHeaders = first.indexOf('\r\n\r\n') + 4; + req.outputData[0].data = + req._header + first.substring(endOfHeaders); + debug('Output buffer: %o', req.outputData[0].data); + } + } + // Wait for the socket's `connect` event, so that this `callback()` + // function throws instead of the `http` request machinery. This is + // important for i.e. `PacProxyAgent` which determines a failed proxy + // connection via the `callback()` function throwing. + yield (0, once_1.default)(socket, 'connect'); + return socket; + }); + } +} +exports["default"] = HttpProxyAgent; +//# sourceMappingURL=agent.js.map + +/***/ }), + +/***/ 81970: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const agent_1 = __importDefault(__nccwpck_require__(77847)); +function createHttpProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpProxyAgent) { + createHttpProxyAgent.HttpProxyAgent = agent_1.default; + createHttpProxyAgent.prototype = agent_1.default.prototype; +})(createHttpProxyAgent || (createHttpProxyAgent = {})); +module.exports = createHttpProxyAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 32960: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = __nccwpck_require__(24434); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const promisify_1 = __importDefault(__nccwpck_require__(62600)); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 62600: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports["default"] = promisify; +//# sourceMappingURL=promisify.js.map + +/***/ }), + +/***/ 3669: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpsProxyAgent = void 0; +const net = __importStar(__nccwpck_require__(69278)); +const tls = __importStar(__nccwpck_require__(64756)); +const assert_1 = __importDefault(__nccwpck_require__(42613)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const agent_base_1 = __nccwpck_require__(98894); +const url_1 = __nccwpck_require__(87016); +const parse_proxy_response_1 = __nccwpck_require__(37943); +const debug = (0, debug_1.default)('https-proxy-agent'); +const setServernameFromNonIpHost = (options) => { + if (options.servername === undefined && + options.host && + !net.isIP(options.host)) { + return { + ...options, + servername: options.host, + }; + } + return options; +}; +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(proxy, opts) { + super(opts); + this.options = { path: undefined }; + this.proxy = typeof proxy === 'string' ? new url_1.URL(proxy) : proxy; + this.proxyHeaders = opts?.headers ?? {}; + debug('Creating new HttpsProxyAgent instance: %o', this.proxy.href); + // Trim off the brackets from IPv6 addresses + const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ''); + const port = this.proxy.port + ? parseInt(this.proxy.port, 10) + : this.proxy.protocol === 'https:' + ? 443 + : 80; + this.connectOpts = { + // Attempt to negotiate http/1.1 for proxy servers that support http/2 + ALPNProtocols: ['http/1.1'], + ...(opts ? omit(opts, 'headers') : null), + host, + port, + }; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + */ + async connect(req, opts) { + const { proxy } = this; + if (!opts.host) { + throw new TypeError('No "host" provided'); + } + // Create a socket connection to the proxy server. + let socket; + if (proxy.protocol === 'https:') { + debug('Creating `tls.Socket`: %o', this.connectOpts); + socket = tls.connect(setServernameFromNonIpHost(this.connectOpts)); + } + else { + debug('Creating `net.Socket`: %o', this.connectOpts); + socket = net.connect(this.connectOpts); + } + const headers = typeof this.proxyHeaders === 'function' + ? this.proxyHeaders() + : { ...this.proxyHeaders }; + const host = net.isIPv6(opts.host) ? `[${opts.host}]` : opts.host; + let payload = `CONNECT ${host}:${opts.port} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.username || proxy.password) { + const auth = `${decodeURIComponent(proxy.username)}:${decodeURIComponent(proxy.password)}`; + headers['Proxy-Authorization'] = `Basic ${Buffer.from(auth).toString('base64')}`; + } + headers.Host = `${host}:${opts.port}`; + if (!headers['Proxy-Connection']) { + headers['Proxy-Connection'] = this.keepAlive + ? 'Keep-Alive' + : 'close'; + } + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = (0, parse_proxy_response_1.parseProxyResponse)(socket); + socket.write(`${payload}\r\n`); + const { connect, buffered } = await proxyResponsePromise; + req.emit('proxyConnect', connect); + this.emit('proxyConnect', connect, req); + if (connect.statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + return tls.connect({ + ...omit(setServernameFromNonIpHost(opts), 'host', 'path', 'port'), + socket, + }); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net.Socket({ writable: false }); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('Replaying proxy buffer for failed request'); + (0, assert_1.default)(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + } +} +HttpsProxyAgent.protocols = ['http', 'https']; +exports.HttpsProxyAgent = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 37943: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.parseProxyResponse = void 0; +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const debug = (0, debug_1.default)('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('readable', read); + } + function onend() { + cleanup(); + debug('onend'); + reject(new Error('Proxy connection ended before receiving CONNECT response')); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const headerParts = buffered + .slice(0, endOfHeaders) + .toString('ascii') + .split('\r\n'); + const firstLine = headerParts.shift(); + if (!firstLine) { + socket.destroy(); + return reject(new Error('No header received from proxy CONNECT response')); + } + const firstLineParts = firstLine.split(' '); + const statusCode = +firstLineParts[1]; + const statusText = firstLineParts.slice(2).join(' '); + const headers = {}; + for (const header of headerParts) { + if (!header) + continue; + const firstColon = header.indexOf(':'); + if (firstColon === -1) { + socket.destroy(); + return reject(new Error(`Invalid header from proxy CONNECT response: "${header}"`)); + } + const key = header.slice(0, firstColon).toLowerCase(); + const value = header.slice(firstColon + 1).trimStart(); + const current = headers[key]; + if (typeof current === 'string') { + headers[key] = [current, value]; + } + else if (Array.isArray(current)) { + current.push(value); + } + else { + headers[key] = value; + } + } + debug('got proxy server response: %o %o', firstLine, headers); + cleanup(); + resolve({ + connect: { + statusCode, + statusText, + headers, + }, + buffered, + }); + } + socket.on('error', onerror); + socket.on('end', onend); + read(); + }); +} +exports.parseProxyResponse = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map + +/***/ }), + +/***/ 39598: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +try { + var util = __nccwpck_require__(39023); + /* istanbul ignore next */ + if (typeof util.inherits !== 'function') throw ''; + module.exports = util.inherits; +} catch (e) { + /* istanbul ignore next */ + module.exports = __nccwpck_require__(26589); +} + + +/***/ }), + +/***/ 26589: +/***/ ((module) => { + +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }) + } + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } +} + + +/***/ }), + +/***/ 96543: +/***/ ((module) => { + +"use strict"; + + +const isStream = stream => + stream !== null && + typeof stream === 'object' && + typeof stream.pipe === 'function'; + +isStream.writable = stream => + isStream(stream) && + stream.writable !== false && + typeof stream._write === 'function' && + typeof stream._writableState === 'object'; + +isStream.readable = stream => + isStream(stream) && + stream.readable !== false && + typeof stream._read === 'function' && + typeof stream._readableState === 'object'; + +isStream.duplex = stream => + isStream.writable(stream) && + isStream.readable(stream); + +isStream.transform = stream => + isStream.duplex(stream) && + typeof stream._transform === 'function'; + +module.exports = isStream; + + +/***/ }), + +/***/ 14826: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var json_stringify = (__nccwpck_require__(93651).stringify); +var json_parse = __nccwpck_require__(3197); + +module.exports = function(options) { + return { + parse: json_parse(options), + stringify: json_stringify + } +}; +//create the default method members with no options applied for backwards compatibility +module.exports.parse = json_parse(); +module.exports.stringify = json_stringify; + + +/***/ }), + +/***/ 3197: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var BigNumber = null; + +// regexpxs extracted from +// (c) BSD-3-Clause +// https://github.com/fastify/secure-json-parse/graphs/contributors and https://github.com/hapijs/bourne/graphs/contributors + +const suspectProtoRx = /(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])/; +const suspectConstructorRx = /(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)/; + +/* + json_parse.js + 2012-06-20 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + This file creates a json_parse function. + During create you can (optionally) specify some behavioural switches + + require('json-bigint')(options) + + The optional options parameter holds switches that drive certain + aspects of the parsing process: + * options.strict = true will warn about duplicate-key usage in the json. + The default (strict = false) will silently ignore those and overwrite + values for keys that are in duplicate use. + + The resulting function follows this signature: + json_parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = json_parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + This is a reference implementation. You are free to copy, modify, or + redistribute. + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. +*/ + +/*members "", "\"", "\/", "\\", at, b, call, charAt, f, fromCharCode, + hasOwnProperty, message, n, name, prototype, push, r, t, text +*/ + +var json_parse = function (options) { + 'use strict'; + + // This is a function that can parse a JSON text, producing a JavaScript + // data structure. It is a simple, recursive descent parser. It does not use + // eval or regular expressions, so it can be used as a model for implementing + // a JSON parser in other languages. + + // We are defining the function inside of another function to avoid creating + // global variables. + + // Default options one can override by passing options to the parse() + var _options = { + strict: false, // not being strict means do not generate syntax errors for "duplicate key" + storeAsString: false, // toggles whether the values should be stored as BigNumber (default) or a string + alwaysParseAsBig: false, // toggles whether all numbers should be Big + useNativeBigInt: false, // toggles whether to use native BigInt instead of bignumber.js + protoAction: 'error', + constructorAction: 'error', + }; + + // If there are options, then use them to override the default _options + if (options !== undefined && options !== null) { + if (options.strict === true) { + _options.strict = true; + } + if (options.storeAsString === true) { + _options.storeAsString = true; + } + _options.alwaysParseAsBig = + options.alwaysParseAsBig === true ? options.alwaysParseAsBig : false; + _options.useNativeBigInt = + options.useNativeBigInt === true ? options.useNativeBigInt : false; + + if (typeof options.constructorAction !== 'undefined') { + if ( + options.constructorAction === 'error' || + options.constructorAction === 'ignore' || + options.constructorAction === 'preserve' + ) { + _options.constructorAction = options.constructorAction; + } else { + throw new Error( + `Incorrect value for constructorAction option, must be "error", "ignore" or undefined but passed ${options.constructorAction}` + ); + } + } + + if (typeof options.protoAction !== 'undefined') { + if ( + options.protoAction === 'error' || + options.protoAction === 'ignore' || + options.protoAction === 'preserve' + ) { + _options.protoAction = options.protoAction; + } else { + throw new Error( + `Incorrect value for protoAction option, must be "error", "ignore" or undefined but passed ${options.protoAction}` + ); + } + } + } + + var at, // The index of the current character + ch, // The current character + escapee = { + '"': '"', + '\\': '\\', + '/': '/', + b: '\b', + f: '\f', + n: '\n', + r: '\r', + t: '\t', + }, + text, + error = function (m) { + // Call error when something is wrong. + + throw { + name: 'SyntaxError', + message: m, + at: at, + text: text, + }; + }, + next = function (c) { + // If a c parameter is provided, verify that it matches the current character. + + if (c && c !== ch) { + error("Expected '" + c + "' instead of '" + ch + "'"); + } + + // Get the next character. When there are no more characters, + // return the empty string. + + ch = text.charAt(at); + at += 1; + return ch; + }, + number = function () { + // Parse a number value. + + var number, + string = ''; + + if (ch === '-') { + string = '-'; + next('-'); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + if (ch === '.') { + string += '.'; + while (next() && ch >= '0' && ch <= '9') { + string += ch; + } + } + if (ch === 'e' || ch === 'E') { + string += ch; + next(); + if (ch === '-' || ch === '+') { + string += ch; + next(); + } + while (ch >= '0' && ch <= '9') { + string += ch; + next(); + } + } + number = +string; + if (!isFinite(number)) { + error('Bad number'); + } else { + if (BigNumber == null) BigNumber = __nccwpck_require__(51259); + //if (number > 9007199254740992 || number < -9007199254740992) + // Bignumber has stricter check: everything with length > 15 digits disallowed + if (string.length > 15) + return _options.storeAsString + ? string + : _options.useNativeBigInt + ? BigInt(string) + : new BigNumber(string); + else + return !_options.alwaysParseAsBig + ? number + : _options.useNativeBigInt + ? BigInt(number) + : new BigNumber(number); + } + }, + string = function () { + // Parse a string value. + + var hex, + i, + string = '', + uffff; + + // When parsing for string values, we must look for " and \ characters. + + if (ch === '"') { + var startAt = at; + while (next()) { + if (ch === '"') { + if (at - 1 > startAt) string += text.substring(startAt, at - 1); + next(); + return string; + } + if (ch === '\\') { + if (at - 1 > startAt) string += text.substring(startAt, at - 1); + next(); + if (ch === 'u') { + uffff = 0; + for (i = 0; i < 4; i += 1) { + hex = parseInt(next(), 16); + if (!isFinite(hex)) { + break; + } + uffff = uffff * 16 + hex; + } + string += String.fromCharCode(uffff); + } else if (typeof escapee[ch] === 'string') { + string += escapee[ch]; + } else { + break; + } + startAt = at; + } + } + } + error('Bad string'); + }, + white = function () { + // Skip whitespace. + + while (ch && ch <= ' ') { + next(); + } + }, + word = function () { + // true, false, or null. + + switch (ch) { + case 't': + next('t'); + next('r'); + next('u'); + next('e'); + return true; + case 'f': + next('f'); + next('a'); + next('l'); + next('s'); + next('e'); + return false; + case 'n': + next('n'); + next('u'); + next('l'); + next('l'); + return null; + } + error("Unexpected '" + ch + "'"); + }, + value, // Place holder for the value function. + array = function () { + // Parse an array value. + + var array = []; + + if (ch === '[') { + next('['); + white(); + if (ch === ']') { + next(']'); + return array; // empty array + } + while (ch) { + array.push(value()); + white(); + if (ch === ']') { + next(']'); + return array; + } + next(','); + white(); + } + } + error('Bad array'); + }, + object = function () { + // Parse an object value. + + var key, + object = Object.create(null); + + if (ch === '{') { + next('{'); + white(); + if (ch === '}') { + next('}'); + return object; // empty object + } + while (ch) { + key = string(); + white(); + next(':'); + if ( + _options.strict === true && + Object.hasOwnProperty.call(object, key) + ) { + error('Duplicate key "' + key + '"'); + } + + if (suspectProtoRx.test(key) === true) { + if (_options.protoAction === 'error') { + error('Object contains forbidden prototype property'); + } else if (_options.protoAction === 'ignore') { + value(); + } else { + object[key] = value(); + } + } else if (suspectConstructorRx.test(key) === true) { + if (_options.constructorAction === 'error') { + error('Object contains forbidden constructor property'); + } else if (_options.constructorAction === 'ignore') { + value(); + } else { + object[key] = value(); + } + } else { + object[key] = value(); + } + + white(); + if (ch === '}') { + next('}'); + return object; + } + next(','); + white(); + } + } + error('Bad object'); + }; + + value = function () { + // Parse a JSON value. It could be an object, an array, a string, a number, + // or a word. + + white(); + switch (ch) { + case '{': + return object(); + case '[': + return array(); + case '"': + return string(); + case '-': + return number(); + default: + return ch >= '0' && ch <= '9' ? number() : word(); + } + }; + + // Return the json_parse function. It will have access to all of the above + // functions and variables. + + return function (source, reviver) { + var result; + + text = source + ''; + at = 0; + ch = ' '; + result = value(); + white(); + if (ch) { + error('Syntax error'); + } + + // If there is a reviver function, we recursively walk the new structure, + // passing each name/value pair to the reviver function for possible + // transformation, starting with a temporary root object that holds the result + // in an empty key. If there is not a reviver function, we simply return the + // result. + + return typeof reviver === 'function' + ? (function walk(holder, key) { + var k, + v, + value = holder[key]; + if (value && typeof value === 'object') { + Object.keys(value).forEach(function (k) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + }); + } + return reviver.call(holder, key, value); + })({ '': result }, '') + : result; + }; +}; + +module.exports = json_parse; + + +/***/ }), + +/***/ 93651: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var BigNumber = __nccwpck_require__(51259); + +/* + json2.js + 2013-05-26 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, regexp: true */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +var JSON = module.exports; + +(function () { + 'use strict'; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' + ? c + : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key], + isBigNumber = value != null && (value instanceof BigNumber || BigNumber.isBigNumber(value)); + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + if (isBigNumber) { + return value; + } else { + return quote(value); + } + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + case 'bigint': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 + ? '[]' + : gap + ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' + : '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + if (typeof rep[i] === 'string') { + k = rep[i]; + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + Object.keys(value).forEach(function(k) { + var v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + }); + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 + ? '{}' + : gap + ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' + : '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } +}()); + + +/***/ }), + +/***/ 38622: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var Buffer = (__nccwpck_require__(93058).Buffer); +var crypto = __nccwpck_require__(76982); +var formatEcdsa = __nccwpck_require__(325); +var util = __nccwpck_require__(39023); + +var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".' +var MSG_INVALID_SECRET = 'secret must be a string or buffer'; +var MSG_INVALID_VERIFIER_KEY = 'key must be a string or a buffer'; +var MSG_INVALID_SIGNER_KEY = 'key must be a string, a buffer or an object'; + +var supportsKeyObjects = typeof crypto.createPublicKey === 'function'; +if (supportsKeyObjects) { + MSG_INVALID_VERIFIER_KEY += ' or a KeyObject'; + MSG_INVALID_SECRET += 'or a KeyObject'; +} + +function checkIsPublicKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.type !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.asymmetricKeyType !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } +}; + +function checkIsPrivateKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (typeof key === 'object') { + return; + } + + throw typeError(MSG_INVALID_SIGNER_KEY); +}; + +function checkIsSecretKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return key; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_SECRET); + } + + if (key.type !== 'secret') { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_SECRET); + } +} + +function fromBase64(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function toBase64(base64url) { + base64url = base64url.toString(); + + var padding = 4 - base64url.length % 4; + if (padding !== 4) { + for (var i = 0; i < padding; ++i) { + base64url += '='; + } + } + + return base64url + .replace(/\-/g, '+') + .replace(/_/g, '/'); +} + +function typeError(template) { + var args = [].slice.call(arguments, 1); + var errMsg = util.format.bind(util, template).apply(null, args); + return new TypeError(errMsg); +} + +function bufferOrString(obj) { + return Buffer.isBuffer(obj) || typeof obj === 'string'; +} + +function normalizeInput(thing) { + if (!bufferOrString(thing)) + thing = JSON.stringify(thing); + return thing; +} + +function createHmacSigner(bits) { + return function sign(thing, secret) { + checkIsSecretKey(secret); + thing = normalizeInput(thing); + var hmac = crypto.createHmac('sha' + bits, secret); + var sig = (hmac.update(thing), hmac.digest('base64')) + return fromBase64(sig); + } +} + +var bufferEqual; +var timingSafeEqual = 'timingSafeEqual' in crypto ? function timingSafeEqual(a, b) { + if (a.byteLength !== b.byteLength) { + return false; + } + + return crypto.timingSafeEqual(a, b) +} : function timingSafeEqual(a, b) { + if (!bufferEqual) { + bufferEqual = __nccwpck_require__(39732); + } + + return bufferEqual(a, b) +} + +function createHmacVerifier(bits) { + return function verify(thing, signature, secret) { + var computedSig = createHmacSigner(bits)(thing, secret); + return timingSafeEqual(Buffer.from(signature), Buffer.from(computedSig)); + } +} + +function createKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + // Even though we are specifying "RSA" here, this works with ECDSA + // keys as well. + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign(privateKey, 'base64')); + return fromBase64(sig); + } +} + +function createKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify(publicKey, signature, 'base64'); + } +} + +function createPSSKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign({ + key: privateKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, 'base64')); + return fromBase64(sig); + } +} + +function createPSSKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify({ + key: publicKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, signature, 'base64'); + } +} + +function createECDSASigner(bits) { + var inner = createKeySigner(bits); + return function sign() { + var signature = inner.apply(null, arguments); + signature = formatEcdsa.derToJose(signature, 'ES' + bits); + return signature; + }; +} + +function createECDSAVerifer(bits) { + var inner = createKeyVerifier(bits); + return function verify(thing, signature, publicKey) { + signature = formatEcdsa.joseToDer(signature, 'ES' + bits).toString('base64'); + var result = inner(thing, signature, publicKey); + return result; + }; +} + +function createNoneSigner() { + return function sign() { + return ''; + } +} + +function createNoneVerifier() { + return function verify(thing, signature) { + return signature === ''; + } +} + +module.exports = function jwa(algorithm) { + var signerFactories = { + hs: createHmacSigner, + rs: createKeySigner, + ps: createPSSKeySigner, + es: createECDSASigner, + none: createNoneSigner, + } + var verifierFactories = { + hs: createHmacVerifier, + rs: createKeyVerifier, + ps: createPSSKeyVerifier, + es: createECDSAVerifer, + none: createNoneVerifier, + } + var match = algorithm.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/); + if (!match) + throw typeError(MSG_INVALID_ALGORITHM, algorithm); + var algo = (match[1] || match[3]).toLowerCase(); + var bits = match[2]; + + return { + sign: signerFactories[algo](bits), + verify: verifierFactories[algo](bits), + } +}; + + +/***/ }), + +/***/ 33324: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +/*global exports*/ +var SignStream = __nccwpck_require__(78600); +var VerifyStream = __nccwpck_require__(4368); + +var ALGORITHMS = [ + 'HS256', 'HS384', 'HS512', + 'RS256', 'RS384', 'RS512', + 'PS256', 'PS384', 'PS512', + 'ES256', 'ES384', 'ES512' +]; + +exports.ALGORITHMS = ALGORITHMS; +exports.sign = SignStream.sign; +exports.verify = VerifyStream.verify; +exports.decode = VerifyStream.decode; +exports.isValid = VerifyStream.isValid; +exports.createSign = function createSign(opts) { + return new SignStream(opts); +}; +exports.createVerify = function createVerify(opts) { + return new VerifyStream(opts); +}; + + +/***/ }), + +/***/ 41831: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module, process*/ +var Buffer = (__nccwpck_require__(93058).Buffer); +var Stream = __nccwpck_require__(2203); +var util = __nccwpck_require__(39023); + +function DataStream(data) { + this.buffer = null; + this.writable = true; + this.readable = true; + + // No input + if (!data) { + this.buffer = Buffer.alloc(0); + return this; + } + + // Stream + if (typeof data.pipe === 'function') { + this.buffer = Buffer.alloc(0); + data.pipe(this); + return this; + } + + // Buffer or String + // or Object (assumedly a passworded key) + if (data.length || typeof data === 'object') { + this.buffer = data; + this.writable = false; + process.nextTick(function () { + this.emit('end', data); + this.readable = false; + this.emit('close'); + }.bind(this)); + return this; + } + + throw new TypeError('Unexpected data type ('+ typeof data + ')'); +} +util.inherits(DataStream, Stream); + +DataStream.prototype.write = function write(data) { + this.buffer = Buffer.concat([this.buffer, Buffer.from(data)]); + this.emit('data', data); +}; + +DataStream.prototype.end = function end(data) { + if (data) + this.write(data); + this.emit('end', data); + this.emit('close'); + this.writable = false; + this.readable = false; +}; + +module.exports = DataStream; + + +/***/ }), + +/***/ 78600: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(93058).Buffer); +var DataStream = __nccwpck_require__(41831); +var jwa = __nccwpck_require__(38622); +var Stream = __nccwpck_require__(2203); +var toString = __nccwpck_require__(95126); +var util = __nccwpck_require__(39023); + +function base64url(string, encoding) { + return Buffer + .from(string, encoding) + .toString('base64') + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function jwsSecuredInput(header, payload, encoding) { + encoding = encoding || 'utf8'; + var encodedHeader = base64url(toString(header), 'binary'); + var encodedPayload = base64url(toString(payload), encoding); + return util.format('%s.%s', encodedHeader, encodedPayload); +} + +function jwsSign(opts) { + var header = opts.header; + var payload = opts.payload; + var secretOrKey = opts.secret || opts.privateKey; + var encoding = opts.encoding; + var algo = jwa(header.alg); + var securedInput = jwsSecuredInput(header, payload, encoding); + var signature = algo.sign(securedInput, secretOrKey); + return util.format('%s.%s', securedInput, signature); +} + +function SignStream(opts) { + var secret = opts.secret||opts.privateKey||opts.key; + var secretStream = new DataStream(secret); + this.readable = true; + this.header = opts.header; + this.encoding = opts.encoding; + this.secret = this.privateKey = this.key = secretStream; + this.payload = new DataStream(opts.payload); + this.secret.once('close', function () { + if (!this.payload.writable && this.readable) + this.sign(); + }.bind(this)); + + this.payload.once('close', function () { + if (!this.secret.writable && this.readable) + this.sign(); + }.bind(this)); +} +util.inherits(SignStream, Stream); + +SignStream.prototype.sign = function sign() { + try { + var signature = jwsSign({ + header: this.header, + payload: this.payload.buffer, + secret: this.secret.buffer, + encoding: this.encoding + }); + this.emit('done', signature); + this.emit('data', signature); + this.emit('end'); + this.readable = false; + return signature; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +SignStream.sign = jwsSign; + +module.exports = SignStream; + + +/***/ }), + +/***/ 95126: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(20181).Buffer); + +module.exports = function toString(obj) { + if (typeof obj === 'string') + return obj; + if (typeof obj === 'number' || Buffer.isBuffer(obj)) + return obj.toString(); + return JSON.stringify(obj); +}; + + +/***/ }), + +/***/ 4368: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*global module*/ +var Buffer = (__nccwpck_require__(93058).Buffer); +var DataStream = __nccwpck_require__(41831); +var jwa = __nccwpck_require__(38622); +var Stream = __nccwpck_require__(2203); +var toString = __nccwpck_require__(95126); +var util = __nccwpck_require__(39023); +var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/; + +function isObject(thing) { + return Object.prototype.toString.call(thing) === '[object Object]'; +} + +function safeJsonParse(thing) { + if (isObject(thing)) + return thing; + try { return JSON.parse(thing); } + catch (e) { return undefined; } +} + +function headerFromJWS(jwsSig) { + var encodedHeader = jwsSig.split('.', 1)[0]; + return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary')); +} + +function securedInputFromJWS(jwsSig) { + return jwsSig.split('.', 2).join('.'); +} + +function signatureFromJWS(jwsSig) { + return jwsSig.split('.')[2]; +} + +function payloadFromJWS(jwsSig, encoding) { + encoding = encoding || 'utf8'; + var payload = jwsSig.split('.')[1]; + return Buffer.from(payload, 'base64').toString(encoding); +} + +function isValidJws(string) { + return JWS_REGEX.test(string) && !!headerFromJWS(string); +} + +function jwsVerify(jwsSig, algorithm, secretOrKey) { + if (!algorithm) { + var err = new Error("Missing algorithm parameter for jws.verify"); + err.code = "MISSING_ALGORITHM"; + throw err; + } + jwsSig = toString(jwsSig); + var signature = signatureFromJWS(jwsSig); + var securedInput = securedInputFromJWS(jwsSig); + var algo = jwa(algorithm); + return algo.verify(securedInput, signature, secretOrKey); +} + +function jwsDecode(jwsSig, opts) { + opts = opts || {}; + jwsSig = toString(jwsSig); + + if (!isValidJws(jwsSig)) + return null; + + var header = headerFromJWS(jwsSig); + + if (!header) + return null; + + var payload = payloadFromJWS(jwsSig); + if (header.typ === 'JWT' || opts.json) + payload = JSON.parse(payload, opts.encoding); + + return { + header: header, + payload: payload, + signature: signatureFromJWS(jwsSig) + }; +} + +function VerifyStream(opts) { + opts = opts || {}; + var secretOrKey = opts.secret||opts.publicKey||opts.key; + var secretStream = new DataStream(secretOrKey); + this.readable = true; + this.algorithm = opts.algorithm; + this.encoding = opts.encoding; + this.secret = this.publicKey = this.key = secretStream; + this.signature = new DataStream(opts.signature); + this.secret.once('close', function () { + if (!this.signature.writable && this.readable) + this.verify(); + }.bind(this)); + + this.signature.once('close', function () { + if (!this.secret.writable && this.readable) + this.verify(); + }.bind(this)); +} +util.inherits(VerifyStream, Stream); +VerifyStream.prototype.verify = function verify() { + try { + var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer); + var obj = jwsDecode(this.signature.buffer, this.encoding); + this.emit('done', valid, obj); + this.emit('data', valid); + this.emit('end'); + this.readable = false; + return valid; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +VerifyStream.decode = jwsDecode; +VerifyStream.isValid = isValidJws; +VerifyStream.verify = jwsVerify; + +module.exports = VerifyStream; + + +/***/ }), + +/***/ 14402: +/***/ ((module) => { + +"use strict"; + + +/** + * @param typeMap [Object] Map of MIME type -> Array[extensions] + * @param ... + */ +function Mime() { + this._types = Object.create(null); + this._extensions = Object.create(null); + + for (let i = 0; i < arguments.length; i++) { + this.define(arguments[i]); + } + + this.define = this.define.bind(this); + this.getType = this.getType.bind(this); + this.getExtension = this.getExtension.bind(this); +} + +/** + * Define mimetype -> extension mappings. Each key is a mime-type that maps + * to an array of extensions associated with the type. The first extension is + * used as the default extension for the type. + * + * e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']}); + * + * If a type declares an extension that has already been defined, an error will + * be thrown. To suppress this error and force the extension to be associated + * with the new type, pass `force`=true. Alternatively, you may prefix the + * extension with "*" to map the type to extension, without mapping the + * extension to the type. + * + * e.g. mime.define({'audio/wav', ['wav']}, {'audio/x-wav', ['*wav']}); + * + * + * @param map (Object) type definitions + * @param force (Boolean) if true, force overriding of existing definitions + */ +Mime.prototype.define = function(typeMap, force) { + for (let type in typeMap) { + let extensions = typeMap[type].map(function(t) { + return t.toLowerCase(); + }); + type = type.toLowerCase(); + + for (let i = 0; i < extensions.length; i++) { + const ext = extensions[i]; + + // '*' prefix = not the preferred type for this extension. So fixup the + // extension, and skip it. + if (ext[0] === '*') { + continue; + } + + if (!force && (ext in this._types)) { + throw new Error( + 'Attempt to change mapping for "' + ext + + '" extension from "' + this._types[ext] + '" to "' + type + + '". Pass `force=true` to allow this, otherwise remove "' + ext + + '" from the list of extensions for "' + type + '".' + ); + } + + this._types[ext] = type; + } + + // Use first extension as default + if (force || !this._extensions[type]) { + const ext = extensions[0]; + this._extensions[type] = (ext[0] !== '*') ? ext : ext.substr(1); + } + } +}; + +/** + * Lookup a mime type based on extension + */ +Mime.prototype.getType = function(path) { + path = String(path); + let last = path.replace(/^.*[/\\]/, '').toLowerCase(); + let ext = last.replace(/^.*\./, '').toLowerCase(); + + let hasPath = last.length < path.length; + let hasDot = ext.length < last.length - 1; + + return (hasDot || !hasPath) && this._types[ext] || null; +}; + +/** + * Return file extension associated with a mime type + */ +Mime.prototype.getExtension = function(type) { + type = /^\s*([^;\s]*)/.test(type) && RegExp.$1; + return type && this._extensions[type.toLowerCase()] || null; +}; + +module.exports = Mime; + + +/***/ }), + +/***/ 94900: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +let Mime = __nccwpck_require__(14402); +module.exports = new Mime(__nccwpck_require__(83725), __nccwpck_require__(68548)); + + +/***/ }), + +/***/ 68548: +/***/ ((module) => { + +module.exports = {"application/prs.cww":["cww"],"application/vnd.1000minds.decision-model+xml":["1km"],"application/vnd.3gpp.pic-bw-large":["plb"],"application/vnd.3gpp.pic-bw-small":["psb"],"application/vnd.3gpp.pic-bw-var":["pvb"],"application/vnd.3gpp2.tcap":["tcap"],"application/vnd.3m.post-it-notes":["pwn"],"application/vnd.accpac.simply.aso":["aso"],"application/vnd.accpac.simply.imp":["imp"],"application/vnd.acucobol":["acu"],"application/vnd.acucorp":["atc","acutc"],"application/vnd.adobe.air-application-installer-package+zip":["air"],"application/vnd.adobe.formscentral.fcdt":["fcdt"],"application/vnd.adobe.fxp":["fxp","fxpl"],"application/vnd.adobe.xdp+xml":["xdp"],"application/vnd.adobe.xfdf":["xfdf"],"application/vnd.ahead.space":["ahead"],"application/vnd.airzip.filesecure.azf":["azf"],"application/vnd.airzip.filesecure.azs":["azs"],"application/vnd.amazon.ebook":["azw"],"application/vnd.americandynamics.acc":["acc"],"application/vnd.amiga.ami":["ami"],"application/vnd.android.package-archive":["apk"],"application/vnd.anser-web-certificate-issue-initiation":["cii"],"application/vnd.anser-web-funds-transfer-initiation":["fti"],"application/vnd.antix.game-component":["atx"],"application/vnd.apple.installer+xml":["mpkg"],"application/vnd.apple.keynote":["key"],"application/vnd.apple.mpegurl":["m3u8"],"application/vnd.apple.numbers":["numbers"],"application/vnd.apple.pages":["pages"],"application/vnd.apple.pkpass":["pkpass"],"application/vnd.aristanetworks.swi":["swi"],"application/vnd.astraea-software.iota":["iota"],"application/vnd.audiograph":["aep"],"application/vnd.balsamiq.bmml+xml":["bmml"],"application/vnd.blueice.multipass":["mpm"],"application/vnd.bmi":["bmi"],"application/vnd.businessobjects":["rep"],"application/vnd.chemdraw+xml":["cdxml"],"application/vnd.chipnuts.karaoke-mmd":["mmd"],"application/vnd.cinderella":["cdy"],"application/vnd.citationstyles.style+xml":["csl"],"application/vnd.claymore":["cla"],"application/vnd.cloanto.rp9":["rp9"],"application/vnd.clonk.c4group":["c4g","c4d","c4f","c4p","c4u"],"application/vnd.cluetrust.cartomobile-config":["c11amc"],"application/vnd.cluetrust.cartomobile-config-pkg":["c11amz"],"application/vnd.commonspace":["csp"],"application/vnd.contact.cmsg":["cdbcmsg"],"application/vnd.cosmocaller":["cmc"],"application/vnd.crick.clicker":["clkx"],"application/vnd.crick.clicker.keyboard":["clkk"],"application/vnd.crick.clicker.palette":["clkp"],"application/vnd.crick.clicker.template":["clkt"],"application/vnd.crick.clicker.wordbank":["clkw"],"application/vnd.criticaltools.wbs+xml":["wbs"],"application/vnd.ctc-posml":["pml"],"application/vnd.cups-ppd":["ppd"],"application/vnd.curl.car":["car"],"application/vnd.curl.pcurl":["pcurl"],"application/vnd.dart":["dart"],"application/vnd.data-vision.rdz":["rdz"],"application/vnd.dbf":["dbf"],"application/vnd.dece.data":["uvf","uvvf","uvd","uvvd"],"application/vnd.dece.ttml+xml":["uvt","uvvt"],"application/vnd.dece.unspecified":["uvx","uvvx"],"application/vnd.dece.zip":["uvz","uvvz"],"application/vnd.denovo.fcselayout-link":["fe_launch"],"application/vnd.dna":["dna"],"application/vnd.dolby.mlp":["mlp"],"application/vnd.dpgraph":["dpg"],"application/vnd.dreamfactory":["dfac"],"application/vnd.ds-keypoint":["kpxx"],"application/vnd.dvb.ait":["ait"],"application/vnd.dvb.service":["svc"],"application/vnd.dynageo":["geo"],"application/vnd.ecowin.chart":["mag"],"application/vnd.enliven":["nml"],"application/vnd.epson.esf":["esf"],"application/vnd.epson.msf":["msf"],"application/vnd.epson.quickanime":["qam"],"application/vnd.epson.salt":["slt"],"application/vnd.epson.ssf":["ssf"],"application/vnd.eszigno3+xml":["es3","et3"],"application/vnd.ezpix-album":["ez2"],"application/vnd.ezpix-package":["ez3"],"application/vnd.fdf":["fdf"],"application/vnd.fdsn.mseed":["mseed"],"application/vnd.fdsn.seed":["seed","dataless"],"application/vnd.flographit":["gph"],"application/vnd.fluxtime.clip":["ftc"],"application/vnd.framemaker":["fm","frame","maker","book"],"application/vnd.frogans.fnc":["fnc"],"application/vnd.frogans.ltf":["ltf"],"application/vnd.fsc.weblaunch":["fsc"],"application/vnd.fujitsu.oasys":["oas"],"application/vnd.fujitsu.oasys2":["oa2"],"application/vnd.fujitsu.oasys3":["oa3"],"application/vnd.fujitsu.oasysgp":["fg5"],"application/vnd.fujitsu.oasysprs":["bh2"],"application/vnd.fujixerox.ddd":["ddd"],"application/vnd.fujixerox.docuworks":["xdw"],"application/vnd.fujixerox.docuworks.binder":["xbd"],"application/vnd.fuzzysheet":["fzs"],"application/vnd.genomatix.tuxedo":["txd"],"application/vnd.geogebra.file":["ggb"],"application/vnd.geogebra.tool":["ggt"],"application/vnd.geometry-explorer":["gex","gre"],"application/vnd.geonext":["gxt"],"application/vnd.geoplan":["g2w"],"application/vnd.geospace":["g3w"],"application/vnd.gmx":["gmx"],"application/vnd.google-apps.document":["gdoc"],"application/vnd.google-apps.presentation":["gslides"],"application/vnd.google-apps.spreadsheet":["gsheet"],"application/vnd.google-earth.kml+xml":["kml"],"application/vnd.google-earth.kmz":["kmz"],"application/vnd.grafeq":["gqf","gqs"],"application/vnd.groove-account":["gac"],"application/vnd.groove-help":["ghf"],"application/vnd.groove-identity-message":["gim"],"application/vnd.groove-injector":["grv"],"application/vnd.groove-tool-message":["gtm"],"application/vnd.groove-tool-template":["tpl"],"application/vnd.groove-vcard":["vcg"],"application/vnd.hal+xml":["hal"],"application/vnd.handheld-entertainment+xml":["zmm"],"application/vnd.hbci":["hbci"],"application/vnd.hhe.lesson-player":["les"],"application/vnd.hp-hpgl":["hpgl"],"application/vnd.hp-hpid":["hpid"],"application/vnd.hp-hps":["hps"],"application/vnd.hp-jlyt":["jlt"],"application/vnd.hp-pcl":["pcl"],"application/vnd.hp-pclxl":["pclxl"],"application/vnd.hydrostatix.sof-data":["sfd-hdstx"],"application/vnd.ibm.minipay":["mpy"],"application/vnd.ibm.modcap":["afp","listafp","list3820"],"application/vnd.ibm.rights-management":["irm"],"application/vnd.ibm.secure-container":["sc"],"application/vnd.iccprofile":["icc","icm"],"application/vnd.igloader":["igl"],"application/vnd.immervision-ivp":["ivp"],"application/vnd.immervision-ivu":["ivu"],"application/vnd.insors.igm":["igm"],"application/vnd.intercon.formnet":["xpw","xpx"],"application/vnd.intergeo":["i2g"],"application/vnd.intu.qbo":["qbo"],"application/vnd.intu.qfx":["qfx"],"application/vnd.ipunplugged.rcprofile":["rcprofile"],"application/vnd.irepository.package+xml":["irp"],"application/vnd.is-xpr":["xpr"],"application/vnd.isac.fcs":["fcs"],"application/vnd.jam":["jam"],"application/vnd.jcp.javame.midlet-rms":["rms"],"application/vnd.jisp":["jisp"],"application/vnd.joost.joda-archive":["joda"],"application/vnd.kahootz":["ktz","ktr"],"application/vnd.kde.karbon":["karbon"],"application/vnd.kde.kchart":["chrt"],"application/vnd.kde.kformula":["kfo"],"application/vnd.kde.kivio":["flw"],"application/vnd.kde.kontour":["kon"],"application/vnd.kde.kpresenter":["kpr","kpt"],"application/vnd.kde.kspread":["ksp"],"application/vnd.kde.kword":["kwd","kwt"],"application/vnd.kenameaapp":["htke"],"application/vnd.kidspiration":["kia"],"application/vnd.kinar":["kne","knp"],"application/vnd.koan":["skp","skd","skt","skm"],"application/vnd.kodak-descriptor":["sse"],"application/vnd.las.las+xml":["lasxml"],"application/vnd.llamagraphics.life-balance.desktop":["lbd"],"application/vnd.llamagraphics.life-balance.exchange+xml":["lbe"],"application/vnd.lotus-1-2-3":["123"],"application/vnd.lotus-approach":["apr"],"application/vnd.lotus-freelance":["pre"],"application/vnd.lotus-notes":["nsf"],"application/vnd.lotus-organizer":["org"],"application/vnd.lotus-screencam":["scm"],"application/vnd.lotus-wordpro":["lwp"],"application/vnd.macports.portpkg":["portpkg"],"application/vnd.mapbox-vector-tile":["mvt"],"application/vnd.mcd":["mcd"],"application/vnd.medcalcdata":["mc1"],"application/vnd.mediastation.cdkey":["cdkey"],"application/vnd.mfer":["mwf"],"application/vnd.mfmp":["mfm"],"application/vnd.micrografx.flo":["flo"],"application/vnd.micrografx.igx":["igx"],"application/vnd.mif":["mif"],"application/vnd.mobius.daf":["daf"],"application/vnd.mobius.dis":["dis"],"application/vnd.mobius.mbk":["mbk"],"application/vnd.mobius.mqy":["mqy"],"application/vnd.mobius.msl":["msl"],"application/vnd.mobius.plc":["plc"],"application/vnd.mobius.txf":["txf"],"application/vnd.mophun.application":["mpn"],"application/vnd.mophun.certificate":["mpc"],"application/vnd.mozilla.xul+xml":["xul"],"application/vnd.ms-artgalry":["cil"],"application/vnd.ms-cab-compressed":["cab"],"application/vnd.ms-excel":["xls","xlm","xla","xlc","xlt","xlw"],"application/vnd.ms-excel.addin.macroenabled.12":["xlam"],"application/vnd.ms-excel.sheet.binary.macroenabled.12":["xlsb"],"application/vnd.ms-excel.sheet.macroenabled.12":["xlsm"],"application/vnd.ms-excel.template.macroenabled.12":["xltm"],"application/vnd.ms-fontobject":["eot"],"application/vnd.ms-htmlhelp":["chm"],"application/vnd.ms-ims":["ims"],"application/vnd.ms-lrm":["lrm"],"application/vnd.ms-officetheme":["thmx"],"application/vnd.ms-outlook":["msg"],"application/vnd.ms-pki.seccat":["cat"],"application/vnd.ms-pki.stl":["*stl"],"application/vnd.ms-powerpoint":["ppt","pps","pot"],"application/vnd.ms-powerpoint.addin.macroenabled.12":["ppam"],"application/vnd.ms-powerpoint.presentation.macroenabled.12":["pptm"],"application/vnd.ms-powerpoint.slide.macroenabled.12":["sldm"],"application/vnd.ms-powerpoint.slideshow.macroenabled.12":["ppsm"],"application/vnd.ms-powerpoint.template.macroenabled.12":["potm"],"application/vnd.ms-project":["mpp","mpt"],"application/vnd.ms-word.document.macroenabled.12":["docm"],"application/vnd.ms-word.template.macroenabled.12":["dotm"],"application/vnd.ms-works":["wps","wks","wcm","wdb"],"application/vnd.ms-wpl":["wpl"],"application/vnd.ms-xpsdocument":["xps"],"application/vnd.mseq":["mseq"],"application/vnd.musician":["mus"],"application/vnd.muvee.style":["msty"],"application/vnd.mynfc":["taglet"],"application/vnd.neurolanguage.nlu":["nlu"],"application/vnd.nitf":["ntf","nitf"],"application/vnd.noblenet-directory":["nnd"],"application/vnd.noblenet-sealer":["nns"],"application/vnd.noblenet-web":["nnw"],"application/vnd.nokia.n-gage.ac+xml":["*ac"],"application/vnd.nokia.n-gage.data":["ngdat"],"application/vnd.nokia.n-gage.symbian.install":["n-gage"],"application/vnd.nokia.radio-preset":["rpst"],"application/vnd.nokia.radio-presets":["rpss"],"application/vnd.novadigm.edm":["edm"],"application/vnd.novadigm.edx":["edx"],"application/vnd.novadigm.ext":["ext"],"application/vnd.oasis.opendocument.chart":["odc"],"application/vnd.oasis.opendocument.chart-template":["otc"],"application/vnd.oasis.opendocument.database":["odb"],"application/vnd.oasis.opendocument.formula":["odf"],"application/vnd.oasis.opendocument.formula-template":["odft"],"application/vnd.oasis.opendocument.graphics":["odg"],"application/vnd.oasis.opendocument.graphics-template":["otg"],"application/vnd.oasis.opendocument.image":["odi"],"application/vnd.oasis.opendocument.image-template":["oti"],"application/vnd.oasis.opendocument.presentation":["odp"],"application/vnd.oasis.opendocument.presentation-template":["otp"],"application/vnd.oasis.opendocument.spreadsheet":["ods"],"application/vnd.oasis.opendocument.spreadsheet-template":["ots"],"application/vnd.oasis.opendocument.text":["odt"],"application/vnd.oasis.opendocument.text-master":["odm"],"application/vnd.oasis.opendocument.text-template":["ott"],"application/vnd.oasis.opendocument.text-web":["oth"],"application/vnd.olpc-sugar":["xo"],"application/vnd.oma.dd2+xml":["dd2"],"application/vnd.openblox.game+xml":["obgx"],"application/vnd.openofficeorg.extension":["oxt"],"application/vnd.openstreetmap.data+xml":["osm"],"application/vnd.openxmlformats-officedocument.presentationml.presentation":["pptx"],"application/vnd.openxmlformats-officedocument.presentationml.slide":["sldx"],"application/vnd.openxmlformats-officedocument.presentationml.slideshow":["ppsx"],"application/vnd.openxmlformats-officedocument.presentationml.template":["potx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":["xlsx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.template":["xltx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.document":["docx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.template":["dotx"],"application/vnd.osgeo.mapguide.package":["mgp"],"application/vnd.osgi.dp":["dp"],"application/vnd.osgi.subsystem":["esa"],"application/vnd.palm":["pdb","pqa","oprc"],"application/vnd.pawaafile":["paw"],"application/vnd.pg.format":["str"],"application/vnd.pg.osasli":["ei6"],"application/vnd.picsel":["efif"],"application/vnd.pmi.widget":["wg"],"application/vnd.pocketlearn":["plf"],"application/vnd.powerbuilder6":["pbd"],"application/vnd.previewsystems.box":["box"],"application/vnd.proteus.magazine":["mgz"],"application/vnd.publishare-delta-tree":["qps"],"application/vnd.pvi.ptid1":["ptid"],"application/vnd.quark.quarkxpress":["qxd","qxt","qwd","qwt","qxl","qxb"],"application/vnd.rar":["rar"],"application/vnd.realvnc.bed":["bed"],"application/vnd.recordare.musicxml":["mxl"],"application/vnd.recordare.musicxml+xml":["musicxml"],"application/vnd.rig.cryptonote":["cryptonote"],"application/vnd.rim.cod":["cod"],"application/vnd.rn-realmedia":["rm"],"application/vnd.rn-realmedia-vbr":["rmvb"],"application/vnd.route66.link66+xml":["link66"],"application/vnd.sailingtracker.track":["st"],"application/vnd.seemail":["see"],"application/vnd.sema":["sema"],"application/vnd.semd":["semd"],"application/vnd.semf":["semf"],"application/vnd.shana.informed.formdata":["ifm"],"application/vnd.shana.informed.formtemplate":["itp"],"application/vnd.shana.informed.interchange":["iif"],"application/vnd.shana.informed.package":["ipk"],"application/vnd.simtech-mindmapper":["twd","twds"],"application/vnd.smaf":["mmf"],"application/vnd.smart.teacher":["teacher"],"application/vnd.software602.filler.form+xml":["fo"],"application/vnd.solent.sdkm+xml":["sdkm","sdkd"],"application/vnd.spotfire.dxp":["dxp"],"application/vnd.spotfire.sfs":["sfs"],"application/vnd.stardivision.calc":["sdc"],"application/vnd.stardivision.draw":["sda"],"application/vnd.stardivision.impress":["sdd"],"application/vnd.stardivision.math":["smf"],"application/vnd.stardivision.writer":["sdw","vor"],"application/vnd.stardivision.writer-global":["sgl"],"application/vnd.stepmania.package":["smzip"],"application/vnd.stepmania.stepchart":["sm"],"application/vnd.sun.wadl+xml":["wadl"],"application/vnd.sun.xml.calc":["sxc"],"application/vnd.sun.xml.calc.template":["stc"],"application/vnd.sun.xml.draw":["sxd"],"application/vnd.sun.xml.draw.template":["std"],"application/vnd.sun.xml.impress":["sxi"],"application/vnd.sun.xml.impress.template":["sti"],"application/vnd.sun.xml.math":["sxm"],"application/vnd.sun.xml.writer":["sxw"],"application/vnd.sun.xml.writer.global":["sxg"],"application/vnd.sun.xml.writer.template":["stw"],"application/vnd.sus-calendar":["sus","susp"],"application/vnd.svd":["svd"],"application/vnd.symbian.install":["sis","sisx"],"application/vnd.syncml+xml":["xsm"],"application/vnd.syncml.dm+wbxml":["bdm"],"application/vnd.syncml.dm+xml":["xdm"],"application/vnd.syncml.dmddf+xml":["ddf"],"application/vnd.tao.intent-module-archive":["tao"],"application/vnd.tcpdump.pcap":["pcap","cap","dmp"],"application/vnd.tmobile-livetv":["tmo"],"application/vnd.trid.tpt":["tpt"],"application/vnd.triscape.mxs":["mxs"],"application/vnd.trueapp":["tra"],"application/vnd.ufdl":["ufd","ufdl"],"application/vnd.uiq.theme":["utz"],"application/vnd.umajin":["umj"],"application/vnd.unity":["unityweb"],"application/vnd.uoml+xml":["uoml"],"application/vnd.vcx":["vcx"],"application/vnd.visio":["vsd","vst","vss","vsw"],"application/vnd.visionary":["vis"],"application/vnd.vsf":["vsf"],"application/vnd.wap.wbxml":["wbxml"],"application/vnd.wap.wmlc":["wmlc"],"application/vnd.wap.wmlscriptc":["wmlsc"],"application/vnd.webturbo":["wtb"],"application/vnd.wolfram.player":["nbp"],"application/vnd.wordperfect":["wpd"],"application/vnd.wqd":["wqd"],"application/vnd.wt.stf":["stf"],"application/vnd.xara":["xar"],"application/vnd.xfdl":["xfdl"],"application/vnd.yamaha.hv-dic":["hvd"],"application/vnd.yamaha.hv-script":["hvs"],"application/vnd.yamaha.hv-voice":["hvp"],"application/vnd.yamaha.openscoreformat":["osf"],"application/vnd.yamaha.openscoreformat.osfpvg+xml":["osfpvg"],"application/vnd.yamaha.smaf-audio":["saf"],"application/vnd.yamaha.smaf-phrase":["spf"],"application/vnd.yellowriver-custom-menu":["cmp"],"application/vnd.zul":["zir","zirz"],"application/vnd.zzazz.deck+xml":["zaz"],"application/x-7z-compressed":["7z"],"application/x-abiword":["abw"],"application/x-ace-compressed":["ace"],"application/x-apple-diskimage":["*dmg"],"application/x-arj":["arj"],"application/x-authorware-bin":["aab","x32","u32","vox"],"application/x-authorware-map":["aam"],"application/x-authorware-seg":["aas"],"application/x-bcpio":["bcpio"],"application/x-bdoc":["*bdoc"],"application/x-bittorrent":["torrent"],"application/x-blorb":["blb","blorb"],"application/x-bzip":["bz"],"application/x-bzip2":["bz2","boz"],"application/x-cbr":["cbr","cba","cbt","cbz","cb7"],"application/x-cdlink":["vcd"],"application/x-cfs-compressed":["cfs"],"application/x-chat":["chat"],"application/x-chess-pgn":["pgn"],"application/x-chrome-extension":["crx"],"application/x-cocoa":["cco"],"application/x-conference":["nsc"],"application/x-cpio":["cpio"],"application/x-csh":["csh"],"application/x-debian-package":["*deb","udeb"],"application/x-dgc-compressed":["dgc"],"application/x-director":["dir","dcr","dxr","cst","cct","cxt","w3d","fgd","swa"],"application/x-doom":["wad"],"application/x-dtbncx+xml":["ncx"],"application/x-dtbook+xml":["dtb"],"application/x-dtbresource+xml":["res"],"application/x-dvi":["dvi"],"application/x-envoy":["evy"],"application/x-eva":["eva"],"application/x-font-bdf":["bdf"],"application/x-font-ghostscript":["gsf"],"application/x-font-linux-psf":["psf"],"application/x-font-pcf":["pcf"],"application/x-font-snf":["snf"],"application/x-font-type1":["pfa","pfb","pfm","afm"],"application/x-freearc":["arc"],"application/x-futuresplash":["spl"],"application/x-gca-compressed":["gca"],"application/x-glulx":["ulx"],"application/x-gnumeric":["gnumeric"],"application/x-gramps-xml":["gramps"],"application/x-gtar":["gtar"],"application/x-hdf":["hdf"],"application/x-httpd-php":["php"],"application/x-install-instructions":["install"],"application/x-iso9660-image":["*iso"],"application/x-iwork-keynote-sffkey":["*key"],"application/x-iwork-numbers-sffnumbers":["*numbers"],"application/x-iwork-pages-sffpages":["*pages"],"application/x-java-archive-diff":["jardiff"],"application/x-java-jnlp-file":["jnlp"],"application/x-keepass2":["kdbx"],"application/x-latex":["latex"],"application/x-lua-bytecode":["luac"],"application/x-lzh-compressed":["lzh","lha"],"application/x-makeself":["run"],"application/x-mie":["mie"],"application/x-mobipocket-ebook":["prc","mobi"],"application/x-ms-application":["application"],"application/x-ms-shortcut":["lnk"],"application/x-ms-wmd":["wmd"],"application/x-ms-wmz":["wmz"],"application/x-ms-xbap":["xbap"],"application/x-msaccess":["mdb"],"application/x-msbinder":["obd"],"application/x-mscardfile":["crd"],"application/x-msclip":["clp"],"application/x-msdos-program":["*exe"],"application/x-msdownload":["*exe","*dll","com","bat","*msi"],"application/x-msmediaview":["mvb","m13","m14"],"application/x-msmetafile":["*wmf","*wmz","*emf","emz"],"application/x-msmoney":["mny"],"application/x-mspublisher":["pub"],"application/x-msschedule":["scd"],"application/x-msterminal":["trm"],"application/x-mswrite":["wri"],"application/x-netcdf":["nc","cdf"],"application/x-ns-proxy-autoconfig":["pac"],"application/x-nzb":["nzb"],"application/x-perl":["pl","pm"],"application/x-pilot":["*prc","*pdb"],"application/x-pkcs12":["p12","pfx"],"application/x-pkcs7-certificates":["p7b","spc"],"application/x-pkcs7-certreqresp":["p7r"],"application/x-rar-compressed":["*rar"],"application/x-redhat-package-manager":["rpm"],"application/x-research-info-systems":["ris"],"application/x-sea":["sea"],"application/x-sh":["sh"],"application/x-shar":["shar"],"application/x-shockwave-flash":["swf"],"application/x-silverlight-app":["xap"],"application/x-sql":["sql"],"application/x-stuffit":["sit"],"application/x-stuffitx":["sitx"],"application/x-subrip":["srt"],"application/x-sv4cpio":["sv4cpio"],"application/x-sv4crc":["sv4crc"],"application/x-t3vm-image":["t3"],"application/x-tads":["gam"],"application/x-tar":["tar"],"application/x-tcl":["tcl","tk"],"application/x-tex":["tex"],"application/x-tex-tfm":["tfm"],"application/x-texinfo":["texinfo","texi"],"application/x-tgif":["*obj"],"application/x-ustar":["ustar"],"application/x-virtualbox-hdd":["hdd"],"application/x-virtualbox-ova":["ova"],"application/x-virtualbox-ovf":["ovf"],"application/x-virtualbox-vbox":["vbox"],"application/x-virtualbox-vbox-extpack":["vbox-extpack"],"application/x-virtualbox-vdi":["vdi"],"application/x-virtualbox-vhd":["vhd"],"application/x-virtualbox-vmdk":["vmdk"],"application/x-wais-source":["src"],"application/x-web-app-manifest+json":["webapp"],"application/x-x509-ca-cert":["der","crt","pem"],"application/x-xfig":["fig"],"application/x-xliff+xml":["*xlf"],"application/x-xpinstall":["xpi"],"application/x-xz":["xz"],"application/x-zmachine":["z1","z2","z3","z4","z5","z6","z7","z8"],"audio/vnd.dece.audio":["uva","uvva"],"audio/vnd.digital-winds":["eol"],"audio/vnd.dra":["dra"],"audio/vnd.dts":["dts"],"audio/vnd.dts.hd":["dtshd"],"audio/vnd.lucent.voice":["lvp"],"audio/vnd.ms-playready.media.pya":["pya"],"audio/vnd.nuera.ecelp4800":["ecelp4800"],"audio/vnd.nuera.ecelp7470":["ecelp7470"],"audio/vnd.nuera.ecelp9600":["ecelp9600"],"audio/vnd.rip":["rip"],"audio/x-aac":["aac"],"audio/x-aiff":["aif","aiff","aifc"],"audio/x-caf":["caf"],"audio/x-flac":["flac"],"audio/x-m4a":["*m4a"],"audio/x-matroska":["mka"],"audio/x-mpegurl":["m3u"],"audio/x-ms-wax":["wax"],"audio/x-ms-wma":["wma"],"audio/x-pn-realaudio":["ram","ra"],"audio/x-pn-realaudio-plugin":["rmp"],"audio/x-realaudio":["*ra"],"audio/x-wav":["*wav"],"chemical/x-cdx":["cdx"],"chemical/x-cif":["cif"],"chemical/x-cmdf":["cmdf"],"chemical/x-cml":["cml"],"chemical/x-csml":["csml"],"chemical/x-xyz":["xyz"],"image/prs.btif":["btif"],"image/prs.pti":["pti"],"image/vnd.adobe.photoshop":["psd"],"image/vnd.airzip.accelerator.azv":["azv"],"image/vnd.dece.graphic":["uvi","uvvi","uvg","uvvg"],"image/vnd.djvu":["djvu","djv"],"image/vnd.dvb.subtitle":["*sub"],"image/vnd.dwg":["dwg"],"image/vnd.dxf":["dxf"],"image/vnd.fastbidsheet":["fbs"],"image/vnd.fpx":["fpx"],"image/vnd.fst":["fst"],"image/vnd.fujixerox.edmics-mmr":["mmr"],"image/vnd.fujixerox.edmics-rlc":["rlc"],"image/vnd.microsoft.icon":["ico"],"image/vnd.ms-dds":["dds"],"image/vnd.ms-modi":["mdi"],"image/vnd.ms-photo":["wdp"],"image/vnd.net-fpx":["npx"],"image/vnd.pco.b16":["b16"],"image/vnd.tencent.tap":["tap"],"image/vnd.valve.source.texture":["vtf"],"image/vnd.wap.wbmp":["wbmp"],"image/vnd.xiff":["xif"],"image/vnd.zbrush.pcx":["pcx"],"image/x-3ds":["3ds"],"image/x-cmu-raster":["ras"],"image/x-cmx":["cmx"],"image/x-freehand":["fh","fhc","fh4","fh5","fh7"],"image/x-icon":["*ico"],"image/x-jng":["jng"],"image/x-mrsid-image":["sid"],"image/x-ms-bmp":["*bmp"],"image/x-pcx":["*pcx"],"image/x-pict":["pic","pct"],"image/x-portable-anymap":["pnm"],"image/x-portable-bitmap":["pbm"],"image/x-portable-graymap":["pgm"],"image/x-portable-pixmap":["ppm"],"image/x-rgb":["rgb"],"image/x-tga":["tga"],"image/x-xbitmap":["xbm"],"image/x-xpixmap":["xpm"],"image/x-xwindowdump":["xwd"],"message/vnd.wfa.wsc":["wsc"],"model/vnd.collada+xml":["dae"],"model/vnd.dwf":["dwf"],"model/vnd.gdl":["gdl"],"model/vnd.gtw":["gtw"],"model/vnd.mts":["mts"],"model/vnd.opengex":["ogex"],"model/vnd.parasolid.transmit.binary":["x_b"],"model/vnd.parasolid.transmit.text":["x_t"],"model/vnd.sap.vds":["vds"],"model/vnd.usdz+zip":["usdz"],"model/vnd.valve.source.compiled-map":["bsp"],"model/vnd.vtu":["vtu"],"text/prs.lines.tag":["dsc"],"text/vnd.curl":["curl"],"text/vnd.curl.dcurl":["dcurl"],"text/vnd.curl.mcurl":["mcurl"],"text/vnd.curl.scurl":["scurl"],"text/vnd.dvb.subtitle":["sub"],"text/vnd.fly":["fly"],"text/vnd.fmi.flexstor":["flx"],"text/vnd.graphviz":["gv"],"text/vnd.in3d.3dml":["3dml"],"text/vnd.in3d.spot":["spot"],"text/vnd.sun.j2me.app-descriptor":["jad"],"text/vnd.wap.wml":["wml"],"text/vnd.wap.wmlscript":["wmls"],"text/x-asm":["s","asm"],"text/x-c":["c","cc","cxx","cpp","h","hh","dic"],"text/x-component":["htc"],"text/x-fortran":["f","for","f77","f90"],"text/x-handlebars-template":["hbs"],"text/x-java-source":["java"],"text/x-lua":["lua"],"text/x-markdown":["mkd"],"text/x-nfo":["nfo"],"text/x-opml":["opml"],"text/x-org":["*org"],"text/x-pascal":["p","pas"],"text/x-processing":["pde"],"text/x-sass":["sass"],"text/x-scss":["scss"],"text/x-setext":["etx"],"text/x-sfv":["sfv"],"text/x-suse-ymp":["ymp"],"text/x-uuencode":["uu"],"text/x-vcalendar":["vcs"],"text/x-vcard":["vcf"],"video/vnd.dece.hd":["uvh","uvvh"],"video/vnd.dece.mobile":["uvm","uvvm"],"video/vnd.dece.pd":["uvp","uvvp"],"video/vnd.dece.sd":["uvs","uvvs"],"video/vnd.dece.video":["uvv","uvvv"],"video/vnd.dvb.file":["dvb"],"video/vnd.fvt":["fvt"],"video/vnd.mpegurl":["mxu","m4u"],"video/vnd.ms-playready.media.pyv":["pyv"],"video/vnd.uvvu.mp4":["uvu","uvvu"],"video/vnd.vivo":["viv"],"video/x-f4v":["f4v"],"video/x-fli":["fli"],"video/x-flv":["flv"],"video/x-m4v":["m4v"],"video/x-matroska":["mkv","mk3d","mks"],"video/x-mng":["mng"],"video/x-ms-asf":["asf","asx"],"video/x-ms-vob":["vob"],"video/x-ms-wm":["wm"],"video/x-ms-wmv":["wmv"],"video/x-ms-wmx":["wmx"],"video/x-ms-wvx":["wvx"],"video/x-msvideo":["avi"],"video/x-sgi-movie":["movie"],"video/x-smv":["smv"],"x-conference/x-cooltalk":["ice"]}; + +/***/ }), + +/***/ 83725: +/***/ ((module) => { + +module.exports = {"application/andrew-inset":["ez"],"application/applixware":["aw"],"application/atom+xml":["atom"],"application/atomcat+xml":["atomcat"],"application/atomdeleted+xml":["atomdeleted"],"application/atomsvc+xml":["atomsvc"],"application/atsc-dwd+xml":["dwd"],"application/atsc-held+xml":["held"],"application/atsc-rsat+xml":["rsat"],"application/bdoc":["bdoc"],"application/calendar+xml":["xcs"],"application/ccxml+xml":["ccxml"],"application/cdfx+xml":["cdfx"],"application/cdmi-capability":["cdmia"],"application/cdmi-container":["cdmic"],"application/cdmi-domain":["cdmid"],"application/cdmi-object":["cdmio"],"application/cdmi-queue":["cdmiq"],"application/cu-seeme":["cu"],"application/dash+xml":["mpd"],"application/davmount+xml":["davmount"],"application/docbook+xml":["dbk"],"application/dssc+der":["dssc"],"application/dssc+xml":["xdssc"],"application/ecmascript":["es","ecma"],"application/emma+xml":["emma"],"application/emotionml+xml":["emotionml"],"application/epub+zip":["epub"],"application/exi":["exi"],"application/express":["exp"],"application/fdt+xml":["fdt"],"application/font-tdpfr":["pfr"],"application/geo+json":["geojson"],"application/gml+xml":["gml"],"application/gpx+xml":["gpx"],"application/gxf":["gxf"],"application/gzip":["gz"],"application/hjson":["hjson"],"application/hyperstudio":["stk"],"application/inkml+xml":["ink","inkml"],"application/ipfix":["ipfix"],"application/its+xml":["its"],"application/java-archive":["jar","war","ear"],"application/java-serialized-object":["ser"],"application/java-vm":["class"],"application/javascript":["js","mjs"],"application/json":["json","map"],"application/json5":["json5"],"application/jsonml+json":["jsonml"],"application/ld+json":["jsonld"],"application/lgr+xml":["lgr"],"application/lost+xml":["lostxml"],"application/mac-binhex40":["hqx"],"application/mac-compactpro":["cpt"],"application/mads+xml":["mads"],"application/manifest+json":["webmanifest"],"application/marc":["mrc"],"application/marcxml+xml":["mrcx"],"application/mathematica":["ma","nb","mb"],"application/mathml+xml":["mathml"],"application/mbox":["mbox"],"application/mediaservercontrol+xml":["mscml"],"application/metalink+xml":["metalink"],"application/metalink4+xml":["meta4"],"application/mets+xml":["mets"],"application/mmt-aei+xml":["maei"],"application/mmt-usd+xml":["musd"],"application/mods+xml":["mods"],"application/mp21":["m21","mp21"],"application/mp4":["mp4s","m4p"],"application/msword":["doc","dot"],"application/mxf":["mxf"],"application/n-quads":["nq"],"application/n-triples":["nt"],"application/node":["cjs"],"application/octet-stream":["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"],"application/oda":["oda"],"application/oebps-package+xml":["opf"],"application/ogg":["ogx"],"application/omdoc+xml":["omdoc"],"application/onenote":["onetoc","onetoc2","onetmp","onepkg"],"application/oxps":["oxps"],"application/p2p-overlay+xml":["relo"],"application/patch-ops-error+xml":["xer"],"application/pdf":["pdf"],"application/pgp-encrypted":["pgp"],"application/pgp-signature":["asc","sig"],"application/pics-rules":["prf"],"application/pkcs10":["p10"],"application/pkcs7-mime":["p7m","p7c"],"application/pkcs7-signature":["p7s"],"application/pkcs8":["p8"],"application/pkix-attr-cert":["ac"],"application/pkix-cert":["cer"],"application/pkix-crl":["crl"],"application/pkix-pkipath":["pkipath"],"application/pkixcmp":["pki"],"application/pls+xml":["pls"],"application/postscript":["ai","eps","ps"],"application/provenance+xml":["provx"],"application/pskc+xml":["pskcxml"],"application/raml+yaml":["raml"],"application/rdf+xml":["rdf","owl"],"application/reginfo+xml":["rif"],"application/relax-ng-compact-syntax":["rnc"],"application/resource-lists+xml":["rl"],"application/resource-lists-diff+xml":["rld"],"application/rls-services+xml":["rs"],"application/route-apd+xml":["rapd"],"application/route-s-tsid+xml":["sls"],"application/route-usd+xml":["rusd"],"application/rpki-ghostbusters":["gbr"],"application/rpki-manifest":["mft"],"application/rpki-roa":["roa"],"application/rsd+xml":["rsd"],"application/rss+xml":["rss"],"application/rtf":["rtf"],"application/sbml+xml":["sbml"],"application/scvp-cv-request":["scq"],"application/scvp-cv-response":["scs"],"application/scvp-vp-request":["spq"],"application/scvp-vp-response":["spp"],"application/sdp":["sdp"],"application/senml+xml":["senmlx"],"application/sensml+xml":["sensmlx"],"application/set-payment-initiation":["setpay"],"application/set-registration-initiation":["setreg"],"application/shf+xml":["shf"],"application/sieve":["siv","sieve"],"application/smil+xml":["smi","smil"],"application/sparql-query":["rq"],"application/sparql-results+xml":["srx"],"application/srgs":["gram"],"application/srgs+xml":["grxml"],"application/sru+xml":["sru"],"application/ssdl+xml":["ssdl"],"application/ssml+xml":["ssml"],"application/swid+xml":["swidtag"],"application/tei+xml":["tei","teicorpus"],"application/thraud+xml":["tfi"],"application/timestamped-data":["tsd"],"application/toml":["toml"],"application/trig":["trig"],"application/ttml+xml":["ttml"],"application/ubjson":["ubj"],"application/urc-ressheet+xml":["rsheet"],"application/urc-targetdesc+xml":["td"],"application/voicexml+xml":["vxml"],"application/wasm":["wasm"],"application/widget":["wgt"],"application/winhlp":["hlp"],"application/wsdl+xml":["wsdl"],"application/wspolicy+xml":["wspolicy"],"application/xaml+xml":["xaml"],"application/xcap-att+xml":["xav"],"application/xcap-caps+xml":["xca"],"application/xcap-diff+xml":["xdf"],"application/xcap-el+xml":["xel"],"application/xcap-ns+xml":["xns"],"application/xenc+xml":["xenc"],"application/xhtml+xml":["xhtml","xht"],"application/xliff+xml":["xlf"],"application/xml":["xml","xsl","xsd","rng"],"application/xml-dtd":["dtd"],"application/xop+xml":["xop"],"application/xproc+xml":["xpl"],"application/xslt+xml":["*xsl","xslt"],"application/xspf+xml":["xspf"],"application/xv+xml":["mxml","xhvml","xvml","xvm"],"application/yang":["yang"],"application/yin+xml":["yin"],"application/zip":["zip"],"audio/3gpp":["*3gpp"],"audio/adpcm":["adp"],"audio/amr":["amr"],"audio/basic":["au","snd"],"audio/midi":["mid","midi","kar","rmi"],"audio/mobile-xmf":["mxmf"],"audio/mp3":["*mp3"],"audio/mp4":["m4a","mp4a"],"audio/mpeg":["mpga","mp2","mp2a","mp3","m2a","m3a"],"audio/ogg":["oga","ogg","spx","opus"],"audio/s3m":["s3m"],"audio/silk":["sil"],"audio/wav":["wav"],"audio/wave":["*wav"],"audio/webm":["weba"],"audio/xm":["xm"],"font/collection":["ttc"],"font/otf":["otf"],"font/ttf":["ttf"],"font/woff":["woff"],"font/woff2":["woff2"],"image/aces":["exr"],"image/apng":["apng"],"image/avif":["avif"],"image/bmp":["bmp"],"image/cgm":["cgm"],"image/dicom-rle":["drle"],"image/emf":["emf"],"image/fits":["fits"],"image/g3fax":["g3"],"image/gif":["gif"],"image/heic":["heic"],"image/heic-sequence":["heics"],"image/heif":["heif"],"image/heif-sequence":["heifs"],"image/hej2k":["hej2"],"image/hsj2":["hsj2"],"image/ief":["ief"],"image/jls":["jls"],"image/jp2":["jp2","jpg2"],"image/jpeg":["jpeg","jpg","jpe"],"image/jph":["jph"],"image/jphc":["jhc"],"image/jpm":["jpm"],"image/jpx":["jpx","jpf"],"image/jxr":["jxr"],"image/jxra":["jxra"],"image/jxrs":["jxrs"],"image/jxs":["jxs"],"image/jxsc":["jxsc"],"image/jxsi":["jxsi"],"image/jxss":["jxss"],"image/ktx":["ktx"],"image/ktx2":["ktx2"],"image/png":["png"],"image/sgi":["sgi"],"image/svg+xml":["svg","svgz"],"image/t38":["t38"],"image/tiff":["tif","tiff"],"image/tiff-fx":["tfx"],"image/webp":["webp"],"image/wmf":["wmf"],"message/disposition-notification":["disposition-notification"],"message/global":["u8msg"],"message/global-delivery-status":["u8dsn"],"message/global-disposition-notification":["u8mdn"],"message/global-headers":["u8hdr"],"message/rfc822":["eml","mime"],"model/3mf":["3mf"],"model/gltf+json":["gltf"],"model/gltf-binary":["glb"],"model/iges":["igs","iges"],"model/mesh":["msh","mesh","silo"],"model/mtl":["mtl"],"model/obj":["obj"],"model/step+xml":["stpx"],"model/step+zip":["stpz"],"model/step-xml+zip":["stpxz"],"model/stl":["stl"],"model/vrml":["wrl","vrml"],"model/x3d+binary":["*x3db","x3dbz"],"model/x3d+fastinfoset":["x3db"],"model/x3d+vrml":["*x3dv","x3dvz"],"model/x3d+xml":["x3d","x3dz"],"model/x3d-vrml":["x3dv"],"text/cache-manifest":["appcache","manifest"],"text/calendar":["ics","ifb"],"text/coffeescript":["coffee","litcoffee"],"text/css":["css"],"text/csv":["csv"],"text/html":["html","htm","shtml"],"text/jade":["jade"],"text/jsx":["jsx"],"text/less":["less"],"text/markdown":["markdown","md"],"text/mathml":["mml"],"text/mdx":["mdx"],"text/n3":["n3"],"text/plain":["txt","text","conf","def","list","log","in","ini"],"text/richtext":["rtx"],"text/rtf":["*rtf"],"text/sgml":["sgml","sgm"],"text/shex":["shex"],"text/slim":["slim","slm"],"text/spdx":["spdx"],"text/stylus":["stylus","styl"],"text/tab-separated-values":["tsv"],"text/troff":["t","tr","roff","man","me","ms"],"text/turtle":["ttl"],"text/uri-list":["uri","uris","urls"],"text/vcard":["vcard"],"text/vtt":["vtt"],"text/xml":["*xml"],"text/yaml":["yaml","yml"],"video/3gpp":["3gp","3gpp"],"video/3gpp2":["3g2"],"video/h261":["h261"],"video/h263":["h263"],"video/h264":["h264"],"video/iso.segment":["m4s"],"video/jpeg":["jpgv"],"video/jpm":["*jpm","jpgm"],"video/mj2":["mj2","mjp2"],"video/mp2t":["ts"],"video/mp4":["mp4","mp4v","mpg4"],"video/mpeg":["mpeg","mpg","mpe","m1v","m2v"],"video/ogg":["ogv"],"video/quicktime":["qt","mov"],"video/webm":["webm"]}; + +/***/ }), + +/***/ 70744: +/***/ ((module) => { + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function (val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} + + +/***/ }), + +/***/ 26705: +/***/ ((module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var Stream = _interopDefault(__nccwpck_require__(2203)); +var http = _interopDefault(__nccwpck_require__(58611)); +var Url = _interopDefault(__nccwpck_require__(87016)); +var whatwgUrl = _interopDefault(__nccwpck_require__(62686)); +var https = _interopDefault(__nccwpck_require__(65692)); +var zlib = _interopDefault(__nccwpck_require__(43106)); + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = (__nccwpck_require__(42078).convert); +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); +const URL = Url.URL || whatwgUrl.URL; + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +/** + * Wrapper around `new URL` to handle arbitrary URLs + * + * @param {string} urlStr + * @return {void} + */ +function parseURL(urlStr) { + /* + Check whether the URL is absolute or not + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 + */ + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { + urlStr = new URL(urlStr).toString(); + } + + // Fallback to old implementation for arbitrary URLs + return parse_url(urlStr); +} + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parseURL(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parseURL(`${input}`); + } + input = {}; + } else { + parsedURL = parseURL(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +const URL$1 = Url.URL || whatwgUrl.URL; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; + +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { + const orig = new URL$1(original).hostname; + const dest = new URL$1(destination).hostname; + + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); +}; + +/** + * isSameProtocol reports whether the two provided URLs use the same protocol. + * + * Both domains must already be in canonical form. + * @param {string|URL} original + * @param {string|URL} destination + */ +const isSameProtocol = function isSameProtocol(destination, original) { + const orig = new URL$1(original).protocol; + const dest = new URL$1(destination).protocol; + + return orig === dest; +}; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + destroyStream(request.body, error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + + if (response && response.body) { + destroyStream(response.body, err); + } + + finalize(); + }); + + fixResponseChunkedTransferBadEnding(req, function (err) { + if (signal && signal.aborted) { + return; + } + + if (response && response.body) { + destroyStream(response.body, err); + } + }); + + /* c8 ignore next 18 */ + if (parseInt(process.version.substring(1)) < 14) { + // Before Node.js 14, pipeline() does not fully support async iterators and does not always + // properly handle when the socket close/end events are out of order. + req.on('socket', function (s) { + s.addListener('close', function (hadError) { + // if a data listener is still present we didn't end cleanly + const hasDataListener = s.listenerCount('data') > 0; + + // if end happened before close but the socket didn't emit an error, do it now + if (response && hasDataListener && !hadError && !(signal && signal.aborted)) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + response.body.emit('error', err); + } + }); + }); + } + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + let locationURL = null; + try { + locationURL = location === null ? null : new URL$1(location, request.url).toString(); + } catch (err) { + // error here can only be invalid URL in Location: header + // do not throw when options.redirect == manual + // let the user extract the errorneous redirect URL + if (request.redirect !== 'manual') { + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); + finalize(); + return; + } + } + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + if (!isDomainOrSubdomain(request.url, locationURL) || !isSameProtocol(request.url, locationURL)) { + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { + requestOpts.headers.delete(name); + } + } + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + raw.on('end', function () { + // some old IIS servers return zero-length OK deflate responses, so 'data' is never emitted. + if (!response) { + response = new Response(body, response_options); + resolve(response); + } + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +function fixResponseChunkedTransferBadEnding(request, errorCallback) { + let socket; + + request.on('socket', function (s) { + socket = s; + }); + + request.on('response', function (response) { + const headers = response.headers; + + if (headers['transfer-encoding'] === 'chunked' && !headers['content-length']) { + response.once('close', function (hadError) { + // tests for socket presence, as in some situations the + // the 'socket' event is not triggered for the request + // (happens in deno), avoids `TypeError` + // if a data listener is still present we didn't end cleanly + const hasDataListener = socket && socket.listenerCount('data') > 0; + + if (hasDataListener && !hadError) { + const err = new Error('Premature close'); + err.code = 'ERR_STREAM_PREMATURE_CLOSE'; + errorCallback(err); + } + }); + } + }); +} + +function destroyStream(stream, err) { + if (stream.destroy) { + stream.destroy(err); + } else { + // node < 8 + stream.emit('error', err); + stream.end(); + } +} + +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +module.exports = exports = fetch; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports["default"] = exports; +exports.Headers = Headers; +exports.Request = Request; +exports.Response = Response; +exports.FetchError = FetchError; +exports.AbortError = AbortError; + + +/***/ }), + +/***/ 55560: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var wrappy = __nccwpck_require__(58264) +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + + +/***/ }), + +/***/ 58890: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const Queue = __nccwpck_require__(30538); + +const pLimit = concurrency => { + if (!((Number.isInteger(concurrency) || concurrency === Infinity) && concurrency > 0)) { + throw new TypeError('Expected `concurrency` to be a number from 1 and up'); + } + + const queue = new Queue(); + let activeCount = 0; + + const next = () => { + activeCount--; + + if (queue.size > 0) { + queue.dequeue()(); + } + }; + + const run = async (fn, resolve, ...args) => { + activeCount++; + + const result = (async () => fn(...args))(); + + resolve(result); + + try { + await result; + } catch {} + + next(); + }; + + const enqueue = (fn, resolve, ...args) => { + queue.enqueue(run.bind(null, fn, resolve, ...args)); + + (async () => { + // This function needs to wait until the next microtask before comparing + // `activeCount` to `concurrency`, because `activeCount` is updated asynchronously + // when the run function is dequeued and called. The comparison in the if-statement + // needs to happen asynchronously as well to get an up-to-date value for `activeCount`. + await Promise.resolve(); + + if (activeCount < concurrency && queue.size > 0) { + queue.dequeue()(); + } + })(); + }; + + const generator = (fn, ...args) => new Promise(resolve => { + enqueue(fn, resolve, ...args); + }); + + Object.defineProperties(generator, { + activeCount: { + get: () => activeCount + }, + pendingCount: { + get: () => queue.size + }, + clearQueue: { + value: () => { + queue.clear(); + } + } + }); + + return generator; +}; + +module.exports = pLimit; + + +/***/ }), + +/***/ 25500: +/***/ ((module) => { + +"use strict"; + + +const codes = {}; + +function createErrorType(code, message, Base) { + if (!Base) { + Base = Error + } + + function getMessage (arg1, arg2, arg3) { + if (typeof message === 'string') { + return message + } else { + return message(arg1, arg2, arg3) + } + } + + class NodeError extends Base { + constructor (arg1, arg2, arg3) { + super(getMessage(arg1, arg2, arg3)); + } + } + + NodeError.prototype.name = Base.name; + NodeError.prototype.code = code; + + codes[code] = NodeError; +} + +// https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js +function oneOf(expected, thing) { + if (Array.isArray(expected)) { + const len = expected.length; + expected = expected.map((i) => String(i)); + if (len > 2) { + return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` + + expected[len - 1]; + } else if (len === 2) { + return `one of ${thing} ${expected[0]} or ${expected[1]}`; + } else { + return `of ${thing} ${expected[0]}`; + } + } else { + return `of ${thing} ${String(expected)}`; + } +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith +function startsWith(str, search, pos) { + return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith +function endsWith(str, search, this_len) { + if (this_len === undefined || this_len > str.length) { + this_len = str.length; + } + return str.substring(this_len - search.length, this_len) === search; +} + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes +function includes(str, search, start) { + if (typeof start !== 'number') { + start = 0; + } + + if (start + search.length > str.length) { + return false; + } else { + return str.indexOf(search, start) !== -1; + } +} + +createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) { + return 'The value "' + value + '" is invalid for option "' + name + '"' +}, TypeError); +createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) { + // determiner: 'must be' or 'must not be' + let determiner; + if (typeof expected === 'string' && startsWith(expected, 'not ')) { + determiner = 'must not be'; + expected = expected.replace(/^not /, ''); + } else { + determiner = 'must be'; + } + + let msg; + if (endsWith(name, ' argument')) { + // For cases like 'first argument' + msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`; + } else { + const type = includes(name, '.') ? 'property' : 'argument'; + msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`; + } + + msg += `. Received type ${typeof actual}`; + return msg; +}, TypeError); +createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); +createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) { + return 'The ' + name + ' method is not implemented' +}); +createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close'); +createErrorType('ERR_STREAM_DESTROYED', function (name) { + return 'Cannot call ' + name + ' after a stream was destroyed'; +}); +createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); +createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); +createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end'); +createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +createErrorType('ERR_UNKNOWN_ENCODING', function (arg) { + return 'Unknown encoding: ' + arg +}, TypeError); +createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); + +module.exports.F = codes; + + +/***/ }), + +/***/ 82063: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + + + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +}; +/**/ + +module.exports = Duplex; +var Readable = __nccwpck_require__(86893); +var Writable = __nccwpck_require__(38797); +__nccwpck_require__(39598)(Duplex, Readable); +{ + // Allow the keys array to be GC'ed. + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + Readable.call(this, options); + Writable.call(this, options); + this.allowHalfOpen = true; + if (options) { + if (options.readable === false) this.readable = false; + if (options.writable === false) this.writable = false; + if (options.allowHalfOpen === false) { + this.allowHalfOpen = false; + this.once('end', onend); + } + } +} +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); +Object.defineProperty(Duplex.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); +Object.defineProperty(Duplex.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } +}); + +// the no-half-open enforcer +function onend() { + // If the writable side ended, then we're ok. + if (this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + process.nextTick(onEndNT, this); +} +function onEndNT(self) { + self.end(); +} +Object.defineProperty(Duplex.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +/***/ }), + +/***/ 35283: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + + + +module.exports = PassThrough; +var Transform = __nccwpck_require__(12337); +__nccwpck_require__(39598)(PassThrough, Transform); +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + Transform.call(this, options); +} +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; + +/***/ }), + +/***/ 86893: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +module.exports = Readable; + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = (__nccwpck_require__(24434).EventEmitter); +var EElistenerCount = function EElistenerCount(emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = __nccwpck_require__(63283); +/**/ + +var Buffer = (__nccwpck_require__(20181).Buffer); +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ +var debugUtil = __nccwpck_require__(39023); +var debug; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function debug() {}; +} +/**/ + +var BufferList = __nccwpck_require__(77336); +var destroyImpl = __nccwpck_require__(65089); +var _require = __nccwpck_require__(54874), + getHighWaterMark = _require.getHighWaterMark; +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_STREAM_PUSH_AFTER_EOF = _require$codes.ERR_STREAM_PUSH_AFTER_EOF, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_STREAM_UNSHIFT_AFTER_END_EVENT = _require$codes.ERR_STREAM_UNSHIFT_AFTER_END_EVENT; + +// Lazy loaded to improve the startup performance. +var StringDecoder; +var createReadableStreamAsyncIterator; +var from; +__nccwpck_require__(39598)(Readable, Stream); +var errorOrDestroy = destroyImpl.errorOrDestroy; +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (Array.isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} +function ReadableState(options, stream, isDuplex) { + Duplex = Duplex || __nccwpck_require__(82063); + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + this.highWaterMark = getHighWaterMark(this, options, 'readableHighWaterMark', isDuplex); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + this.paused = true; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = options.emitClose !== false; + + // Should .destroy() be called after 'end' (and potentially 'finish') + this.autoDestroy = !!options.autoDestroy; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = (__nccwpck_require__(80634)/* .StringDecoder */ .I); + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} +function Readable(options) { + Duplex = Duplex || __nccwpck_require__(82063); + if (!(this instanceof Readable)) return new Readable(options); + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the ReadableState constructor, at least with V8 6.5 + var isDuplex = this instanceof Duplex; + this._readableState = new ReadableState(options, this, isDuplex); + + // legacy + this.readable = true; + if (options) { + if (typeof options.read === 'function') this._read = options.read; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + Stream.call(this); +} +Object.defineProperty(Readable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + debug('readableAddChunk', chunk); + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + errorOrDestroy(stream, er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (addToFront) { + if (state.endEmitted) errorOrDestroy(stream, new ERR_STREAM_UNSHIFT_AFTER_END_EVENT());else addChunk(stream, state, chunk, true); + } else if (state.ended) { + errorOrDestroy(stream, new ERR_STREAM_PUSH_AFTER_EOF()); + } else if (state.destroyed) { + return false; + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + maybeReadMore(stream, state); + } + } + + // We can push more data if we are below the highWaterMark. + // Also, if we have no data yet, we can stand some more bytes. + // This is to work around cases where hwm=0, such as the repl. + return !state.ended && (state.length < state.highWaterMark || state.length === 0); +} +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + state.awaitDrain = 0; + stream.emit('data', chunk); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer', 'Uint8Array'], chunk); + } + return er; +} +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = (__nccwpck_require__(80634)/* .StringDecoder */ .I); + var decoder = new StringDecoder(enc); + this._readableState.decoder = decoder; + // If setEncoding(null), decoder.encoding equals utf8 + this._readableState.encoding = this._readableState.decoder.encoding; + + // Iterate over current buffer to convert already stored Buffers: + var p = this._readableState.buffer.head; + var content = ''; + while (p !== null) { + content += decoder.write(p.data); + p = p.next; + } + this._readableState.buffer.clear(); + if (content !== '') this._readableState.buffer.push(content); + this._readableState.length = content.length; + return this; +}; + +// Don't raise the hwm > 1GB +var MAX_HWM = 0x40000000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + // TODO(ronag): Throw ERR_VALUE_OUT_OF_RANGE. + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && ((state.highWaterMark !== 0 ? state.length >= state.highWaterMark : state.length > 0) || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + if (ret === null) { + state.needReadable = state.length <= state.highWaterMark; + n = 0; + } else { + state.length -= n; + state.awaitDrain = 0; + } + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + if (ret !== null) this.emit('data', ret); + return ret; +}; +function onEofChunk(stream, state) { + debug('onEofChunk'); + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + if (state.sync) { + // if we are sync, wait until next tick to emit the data. + // Otherwise we risk emitting data in the flow() + // the readable code triggers during a read() call + emitReadable(stream); + } else { + // emit 'readable' now to make sure it gets picked up. + state.needReadable = false; + if (!state.emittedReadable) { + state.emittedReadable = true; + emitReadable_(stream); + } + } +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + debug('emitReadable', state.needReadable, state.emittedReadable); + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + process.nextTick(emitReadable_, stream); + } +} +function emitReadable_(stream) { + var state = stream._readableState; + debug('emitReadable_', state.destroyed, state.length, state.ended); + if (!state.destroyed && (state.length || state.ended)) { + stream.emit('readable'); + state.emittedReadable = false; + } + + // The stream needs another readable event if + // 1. It is not flowing, as the flow mechanism will take + // care of it. + // 2. It is not ended. + // 3. It is below the highWaterMark, so we can schedule + // another readable later. + state.needReadable = !state.flowing && !state.ended && state.length <= state.highWaterMark; + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + process.nextTick(maybeReadMore_, stream, state); + } +} +function maybeReadMore_(stream, state) { + // Attempt to read more data if we should. + // + // The conditions for reading more data are (one of): + // - Not enough data buffered (state.length < state.highWaterMark). The loop + // is responsible for filling the buffer with enough data if such data + // is available. If highWaterMark is 0 and we are not in the flowing mode + // we should _not_ attempt to buffer any extra data. We'll get more data + // when the stream consumer calls read() instead. + // - No data in the buffer, and the stream is in flowing mode. In this mode + // the loop below is responsible for ensuring read() is called. Failing to + // call read here would abort the flow and there's no other mechanism for + // continuing the flow if the stream consumer has just subscribed to the + // 'data' event. + // + // In addition to the above conditions to keep reading data, the following + // conditions prevent the data from being read: + // - The stream has ended (state.ended). + // - There is already a pending 'read' operation (state.reading). This is a + // case where the the stream has called the implementation defined _read() + // method, but they are processing the call asynchronously and have _not_ + // called push() with new data. In this case we skip performing more + // read()s. The execution ends in this method again after the _read() ends + // up calling push() with more data. + while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0)) { + var len = state.length; + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + errorOrDestroy(this, new ERR_METHOD_NOT_IMPLEMENTED('_read()')); +}; +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) process.nextTick(endFn);else src.once('end', endFn); + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + var ret = dest.write(chunk); + debug('dest.write', ret); + if (ret === false) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', state.awaitDrain); + state.awaitDrain++; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) errorOrDestroy(dest, er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + return dest; +}; +function pipeOnDrain(src) { + return function pipeOnDrainFunctionResult() { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { + hasUnpiped: false + }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + for (var i = 0; i < len; i++) dests[i].emit('unpipe', this, { + hasUnpiped: false + }); + return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + dest.emit('unpipe', this, unpipeInfo); + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + var state = this._readableState; + if (ev === 'data') { + // update readableListening so that resume() may be a no-op + // a few lines down. This is needed to support once('readable'). + state.readableListening = this.listenerCount('readable') > 0; + + // Try start flowing on next tick if stream isn't explicitly paused + if (state.flowing !== false) this.resume(); + } else if (ev === 'readable') { + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.flowing = false; + state.emittedReadable = false; + debug('on readable', state.length, state.reading); + if (state.length) { + emitReadable(this); + } else if (!state.reading) { + process.nextTick(nReadingNextTick, this); + } + } + } + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; +Readable.prototype.removeListener = function (ev, fn) { + var res = Stream.prototype.removeListener.call(this, ev, fn); + if (ev === 'readable') { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +}; +Readable.prototype.removeAllListeners = function (ev) { + var res = Stream.prototype.removeAllListeners.apply(this, arguments); + if (ev === 'readable' || ev === undefined) { + // We need to check if there is someone still listening to + // readable and reset the state. However this needs to happen + // after readable has been emitted but before I/O (nextTick) to + // support once('readable', fn) cycles. This means that calling + // resume within the same tick will have no + // effect. + process.nextTick(updateReadableListening, this); + } + return res; +}; +function updateReadableListening(self) { + var state = self._readableState; + state.readableListening = self.listenerCount('readable') > 0; + if (state.resumeScheduled && !state.paused) { + // flowing needs to be set to true now, otherwise + // the upcoming resume will not flow. + state.flowing = true; + + // crude way to check if we should resume + } else if (self.listenerCount('data') > 0) { + self.resume(); + } +} +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + // we flow only if there is no one listening + // for readable, but we still have to call + // resume() + state.flowing = !state.readableListening; + resume(this, state); + } + state.paused = false; + return this; +}; +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + process.nextTick(resume_, stream, state); + } +} +function resume_(stream, state) { + debug('resume', state.reading); + if (!state.reading) { + stream.read(0); + } + state.resumeScheduled = false; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (this._readableState.flowing !== false) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + this._readableState.paused = true; + return this; +}; +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null); +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + var state = this._readableState; + var paused = false; + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + _this.push(null); + }); + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function methodWrap(method) { + return function methodWrapReturnFunction() { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + return this; +}; +if (typeof Symbol === 'function') { + Readable.prototype[Symbol.asyncIterator] = function () { + if (createReadableStreamAsyncIterator === undefined) { + createReadableStreamAsyncIterator = __nccwpck_require__(14868); + } + return createReadableStreamAsyncIterator(this); + }; +} +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.highWaterMark; + } +}); +Object.defineProperty(Readable.prototype, 'readableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState && this._readableState.buffer; + } +}); +Object.defineProperty(Readable.prototype, 'readableFlowing', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.flowing; + }, + set: function set(state) { + if (this._readableState) { + this._readableState.flowing = state; + } + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; +Object.defineProperty(Readable.prototype, 'readableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._readableState.length; + } +}); + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.first();else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = state.buffer.consume(n, state.decoder); + } + return ret; +} +function endReadable(stream) { + var state = stream._readableState; + debug('endReadable', state.endEmitted); + if (!state.endEmitted) { + state.ended = true; + process.nextTick(endReadableNT, state, stream); + } +} +function endReadableNT(state, stream) { + debug('endReadableNT', state.endEmitted, state.length); + + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the writable side is ready for autoDestroy as well + var wState = stream._writableState; + if (!wState || wState.autoDestroy && wState.finished) { + stream.destroy(); + } + } + } +} +if (typeof Symbol === 'function') { + Readable.from = function (iterable, opts) { + if (from === undefined) { + from = __nccwpck_require__(4659); + } + return from(Readable, iterable, opts); + }; +} +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} + +/***/ }), + +/***/ 12337: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + + + +module.exports = Transform; +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING, + ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0; +var Duplex = __nccwpck_require__(82063); +__nccwpck_require__(39598)(Transform, Duplex); +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + var cb = ts.writecb; + if (cb === null) { + return this.emit('error', new ERR_MULTIPLE_CALLBACK()); + } + ts.writechunk = null; + ts.writecb = null; + if (data != null) + // single equals check for both `null` and `undefined` + this.push(data); + cb(er); + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + Duplex.call(this, options); + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} +function prefinish() { + var _this = this; + if (typeof this._flush === 'function' && !this._readableState.destroyed) { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()')); +}; +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + if (ts.writechunk !== null && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; +Transform.prototype._destroy = function (err, cb) { + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + }); +}; +function done(stream, er, data) { + if (er) return stream.emit('error', er); + if (data != null) + // single equals check for both `null` and `undefined` + stream.push(data); + + // TODO(BridgeAR): Write a test for these two error cases + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0(); + if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING(); + return stream.push(null); +} + +/***/ }), + +/***/ 38797: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + + + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var internalUtil = { + deprecate: __nccwpck_require__(24488) +}; +/**/ + +/**/ +var Stream = __nccwpck_require__(63283); +/**/ + +var Buffer = (__nccwpck_require__(20181).Buffer); +var OurUint8Array = (typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {}).Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} +var destroyImpl = __nccwpck_require__(65089); +var _require = __nccwpck_require__(54874), + getHighWaterMark = _require.getHighWaterMark; +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE, + ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED, + ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK, + ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED, + ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES, + ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END, + ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING; +var errorOrDestroy = destroyImpl.errorOrDestroy; +__nccwpck_require__(39598)(Writable, Stream); +function nop() {} +function WritableState(options, stream, isDuplex) { + Duplex = Duplex || __nccwpck_require__(82063); + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream, + // e.g. options.readableObjectMode vs. options.writableObjectMode, etc. + if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // Should close be emitted on destroy. Defaults to true. + this.emitClose = options.emitClose !== false; + + // Should .destroy() be called after 'finish' (and potentially 'end') + this.autoDestroy = !!options.autoDestroy; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function writableStateBufferGetter() { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function value(object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function realHasInstance(object) { + return object instanceof this; + }; +} +function Writable(options) { + Duplex = Duplex || __nccwpck_require__(82063); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + + // Checking for a Stream.Duplex instance is faster here instead of inside + // the WritableState constructor, at least with V8 6.5 + var isDuplex = this instanceof Duplex; + if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options); + this._writableState = new WritableState(options, this, isDuplex); + + // legacy. + this.writable = true; + if (options) { + if (typeof options.write === 'function') this._write = options.write; + if (typeof options.writev === 'function') this._writev = options.writev; + if (typeof options.destroy === 'function') this._destroy = options.destroy; + if (typeof options.final === 'function') this._final = options.final; + } + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + errorOrDestroy(this, new ERR_STREAM_CANNOT_PIPE()); +}; +function writeAfterEnd(stream, cb) { + var er = new ERR_STREAM_WRITE_AFTER_END(); + // TODO: defer error events consistently everywhere, not just the cb + errorOrDestroy(stream, er); + process.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var er; + if (chunk === null) { + er = new ERR_STREAM_NULL_VALUES(); + } else if (typeof chunk !== 'string' && !state.objectMode) { + er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk); + } + if (er) { + errorOrDestroy(stream, er); + process.nextTick(cb, er); + return false; + } + return true; +} +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + if (typeof cb !== 'function') cb = nop; + if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + return ret; +}; +Writable.prototype.cork = function () { + this._writableState.corked++; +}; +Writable.prototype.uncork = function () { + var state = this._writableState; + if (state.corked) { + state.corked--; + if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; +Object.defineProperty(Writable.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState && this._writableState.getBuffer(); + } +}); +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + state.length += len; + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + return ret; +} +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + process.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + process.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + errorOrDestroy(stream, er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK(); + onwriteStateUpdate(state); + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state) || stream.destroyed; + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + if (sync) { + process.nextTick(afterWrite, stream, state, finished, cb); + } else { + afterWrite(stream, state, finished, cb); + } + } +} +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + if (entry === null) state.lastBufferedRequest = null; + } + state.bufferedRequest = entry; + state.bufferProcessing = false; +} +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()')); +}; +Writable.prototype._writev = null; +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending) endWritable(this, state, cb); + return this; +}; +Object.defineProperty(Writable.prototype, 'writableLength', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + return this._writableState.length; + } +}); +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + errorOrDestroy(stream, err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function' && !state.destroyed) { + state.pendingcb++; + state.finalCalled = true; + process.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + if (state.autoDestroy) { + // In case of duplex streams we need a way to detect + // if the readable side is ready for autoDestroy as well + var rState = stream._readableState; + if (!rState || rState.autoDestroy && rState.endEmitted) { + stream.destroy(); + } + } + } + } + return need; +} +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) process.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + + // reuse the free corkReq. + state.corkedRequestsFree.next = corkReq; +} +Object.defineProperty(Writable.prototype, 'destroyed', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function get() { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function set(value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + cb(err); +}; + +/***/ }), + +/***/ 14868: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var _Object$setPrototypeO; +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var finished = __nccwpck_require__(36815); +var kLastResolve = Symbol('lastResolve'); +var kLastReject = Symbol('lastReject'); +var kError = Symbol('error'); +var kEnded = Symbol('ended'); +var kLastPromise = Symbol('lastPromise'); +var kHandlePromise = Symbol('handlePromise'); +var kStream = Symbol('stream'); +function createIterResult(value, done) { + return { + value: value, + done: done + }; +} +function readAndResolve(iter) { + var resolve = iter[kLastResolve]; + if (resolve !== null) { + var data = iter[kStream].read(); + // we defer if data is null + // we can be expecting either 'end' or + // 'error' + if (data !== null) { + iter[kLastPromise] = null; + iter[kLastResolve] = null; + iter[kLastReject] = null; + resolve(createIterResult(data, false)); + } + } +} +function onReadable(iter) { + // we wait for the next tick, because it might + // emit an error with process.nextTick + process.nextTick(readAndResolve, iter); +} +function wrapForNext(lastPromise, iter) { + return function (resolve, reject) { + lastPromise.then(function () { + if (iter[kEnded]) { + resolve(createIterResult(undefined, true)); + return; + } + iter[kHandlePromise](resolve, reject); + }, reject); + }; +} +var AsyncIteratorPrototype = Object.getPrototypeOf(function () {}); +var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = { + get stream() { + return this[kStream]; + }, + next: function next() { + var _this = this; + // if we have detected an error in the meanwhile + // reject straight away + var error = this[kError]; + if (error !== null) { + return Promise.reject(error); + } + if (this[kEnded]) { + return Promise.resolve(createIterResult(undefined, true)); + } + if (this[kStream].destroyed) { + // We need to defer via nextTick because if .destroy(err) is + // called, the error will be emitted via nextTick, and + // we cannot guarantee that there is no error lingering around + // waiting to be emitted. + return new Promise(function (resolve, reject) { + process.nextTick(function () { + if (_this[kError]) { + reject(_this[kError]); + } else { + resolve(createIterResult(undefined, true)); + } + }); + }); + } + + // if we have multiple next() calls + // we will wait for the previous Promise to finish + // this logic is optimized to support for await loops, + // where next() is only called once at a time + var lastPromise = this[kLastPromise]; + var promise; + if (lastPromise) { + promise = new Promise(wrapForNext(lastPromise, this)); + } else { + // fast path needed to support multiple this.push() + // without triggering the next() queue + var data = this[kStream].read(); + if (data !== null) { + return Promise.resolve(createIterResult(data, false)); + } + promise = new Promise(this[kHandlePromise]); + } + this[kLastPromise] = promise; + return promise; + } +}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () { + return this; +}), _defineProperty(_Object$setPrototypeO, "return", function _return() { + var _this2 = this; + // destroy(err, cb) is a private API + // we can guarantee we have that here, because we control the + // Readable class this is attached to + return new Promise(function (resolve, reject) { + _this2[kStream].destroy(null, function (err) { + if (err) { + reject(err); + return; + } + resolve(createIterResult(undefined, true)); + }); + }); +}), _Object$setPrototypeO), AsyncIteratorPrototype); +var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) { + var _Object$create; + var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, { + value: stream, + writable: true + }), _defineProperty(_Object$create, kLastResolve, { + value: null, + writable: true + }), _defineProperty(_Object$create, kLastReject, { + value: null, + writable: true + }), _defineProperty(_Object$create, kError, { + value: null, + writable: true + }), _defineProperty(_Object$create, kEnded, { + value: stream._readableState.endEmitted, + writable: true + }), _defineProperty(_Object$create, kHandlePromise, { + value: function value(resolve, reject) { + var data = iterator[kStream].read(); + if (data) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(data, false)); + } else { + iterator[kLastResolve] = resolve; + iterator[kLastReject] = reject; + } + }, + writable: true + }), _Object$create)); + iterator[kLastPromise] = null; + finished(stream, function (err) { + if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') { + var reject = iterator[kLastReject]; + // reject if we are waiting for data in the Promise + // returned by next() and store the error + if (reject !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + reject(err); + } + iterator[kError] = err; + return; + } + var resolve = iterator[kLastResolve]; + if (resolve !== null) { + iterator[kLastPromise] = null; + iterator[kLastResolve] = null; + iterator[kLastReject] = null; + resolve(createIterResult(undefined, true)); + } + iterator[kEnded] = true; + }); + stream.on('readable', onReadable.bind(null, iterator)); + return iterator; +}; +module.exports = createReadableStreamAsyncIterator; + +/***/ }), + +/***/ 77336: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } +function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var _require = __nccwpck_require__(20181), + Buffer = _require.Buffer; +var _require2 = __nccwpck_require__(39023), + inspect = _require2.inspect; +var custom = inspect && inspect.custom || 'inspect'; +function copyBuffer(src, target, offset) { + Buffer.prototype.copy.call(src, target, offset); +} +module.exports = /*#__PURE__*/function () { + function BufferList() { + _classCallCheck(this, BufferList); + this.head = null; + this.tail = null; + this.length = 0; + } + _createClass(BufferList, [{ + key: "push", + value: function push(v) { + var entry = { + data: v, + next: null + }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + } + }, { + key: "unshift", + value: function unshift(v) { + var entry = { + data: v, + next: this.head + }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + } + }, { + key: "shift", + value: function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + } + }, { + key: "clear", + value: function clear() { + this.head = this.tail = null; + this.length = 0; + } + }, { + key: "join", + value: function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) ret += s + p.data; + return ret; + } + }, { + key: "concat", + value: function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + } + + // Consumes a specified amount of bytes or characters from the buffered data. + }, { + key: "consume", + value: function consume(n, hasStrings) { + var ret; + if (n < this.head.data.length) { + // `slice` is the same for buffers and strings. + ret = this.head.data.slice(0, n); + this.head.data = this.head.data.slice(n); + } else if (n === this.head.data.length) { + // First chunk is a perfect match. + ret = this.shift(); + } else { + // Result spans more than one buffer. + ret = hasStrings ? this._getString(n) : this._getBuffer(n); + } + return ret; + } + }, { + key: "first", + value: function first() { + return this.head.data; + } + + // Consumes a specified amount of characters from the buffered data. + }, { + key: "_getString", + value: function _getString(n) { + var p = this.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + + // Consumes a specified amount of bytes from the buffered data. + }, { + key: "_getBuffer", + value: function _getBuffer(n) { + var ret = Buffer.allocUnsafe(n); + var p = this.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) this.head = p.next;else this.head = this.tail = null; + } else { + this.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + this.length -= c; + return ret; + } + + // Make sure the linked list only shows the minimal necessary information. + }, { + key: custom, + value: function value(_, options) { + return inspect(this, _objectSpread(_objectSpread({}, options), {}, { + // Only inspect one level. + depth: 0, + // It should not recurse. + customInspect: false + })); + } + }]); + return BufferList; +}(); + +/***/ }), + +/***/ 65089: +/***/ ((module) => { + +"use strict"; + + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err) { + if (!this._writableState) { + process.nextTick(emitErrorNT, this, err); + } else if (!this._writableState.errorEmitted) { + this._writableState.errorEmitted = true; + process.nextTick(emitErrorNT, this, err); + } + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + this._destroy(err || null, function (err) { + if (!cb && err) { + if (!_this._writableState) { + process.nextTick(emitErrorAndCloseNT, _this, err); + } else if (!_this._writableState.errorEmitted) { + _this._writableState.errorEmitted = true; + process.nextTick(emitErrorAndCloseNT, _this, err); + } else { + process.nextTick(emitCloseNT, _this); + } + } else if (cb) { + process.nextTick(emitCloseNT, _this); + cb(err); + } else { + process.nextTick(emitCloseNT, _this); + } + }); + return this; +} +function emitErrorAndCloseNT(self, err) { + emitErrorNT(self, err); + emitCloseNT(self); +} +function emitCloseNT(self) { + if (self._writableState && !self._writableState.emitClose) return; + if (self._readableState && !self._readableState.emitClose) return; + self.emit('close'); +} +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finalCalled = false; + this._writableState.prefinished = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} +function emitErrorNT(self, err) { + self.emit('error', err); +} +function errorOrDestroy(stream, err) { + // We have tests that rely on errors being emitted + // in the same tick, so changing this is semver major. + // For now when you opt-in to autoDestroy we allow + // the error to be emitted nextTick. In a future + // semver major update we should change the default to this. + + var rState = stream._readableState; + var wState = stream._writableState; + if (rState && rState.autoDestroy || wState && wState.autoDestroy) stream.destroy(err);else stream.emit('error', err); +} +module.exports = { + destroy: destroy, + undestroy: undestroy, + errorOrDestroy: errorOrDestroy +}; + +/***/ }), + +/***/ 36815: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Ported from https://github.com/mafintosh/end-of-stream with +// permission from the author, Mathias Buus (@mafintosh). + + + +var ERR_STREAM_PREMATURE_CLOSE = (__nccwpck_require__(25500)/* .codes */ .F).ERR_STREAM_PREMATURE_CLOSE; +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + callback.apply(this, args); + }; +} +function noop() {} +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} +function eos(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + callback = once(callback || noop); + var readable = opts.readable || opts.readable !== false && stream.readable; + var writable = opts.writable || opts.writable !== false && stream.writable; + var onlegacyfinish = function onlegacyfinish() { + if (!stream.writable) onfinish(); + }; + var writableEnded = stream._writableState && stream._writableState.finished; + var onfinish = function onfinish() { + writable = false; + writableEnded = true; + if (!readable) callback.call(stream); + }; + var readableEnded = stream._readableState && stream._readableState.endEmitted; + var onend = function onend() { + readable = false; + readableEnded = true; + if (!writable) callback.call(stream); + }; + var onerror = function onerror(err) { + callback.call(stream, err); + }; + var onclose = function onclose() { + var err; + if (readable && !readableEnded) { + if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + if (writable && !writableEnded) { + if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE(); + return callback.call(stream, err); + } + }; + var onrequest = function onrequest() { + stream.req.on('finish', onfinish); + }; + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest();else stream.on('request', onrequest); + } else if (writable && !stream._writableState) { + // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + return function () { + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +} +module.exports = eos; + +/***/ }), + +/***/ 4659: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } +function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } +function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); } +function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } +var ERR_INVALID_ARG_TYPE = (__nccwpck_require__(25500)/* .codes */ .F).ERR_INVALID_ARG_TYPE; +function from(Readable, iterable, opts) { + var iterator; + if (iterable && typeof iterable.next === 'function') { + iterator = iterable; + } else if (iterable && iterable[Symbol.asyncIterator]) iterator = iterable[Symbol.asyncIterator]();else if (iterable && iterable[Symbol.iterator]) iterator = iterable[Symbol.iterator]();else throw new ERR_INVALID_ARG_TYPE('iterable', ['Iterable'], iterable); + var readable = new Readable(_objectSpread({ + objectMode: true + }, opts)); + // Reading boolean to protect against _read + // being called before last iteration completion. + var reading = false; + readable._read = function () { + if (!reading) { + reading = true; + next(); + } + }; + function next() { + return _next2.apply(this, arguments); + } + function _next2() { + _next2 = _asyncToGenerator(function* () { + try { + var _yield$iterator$next = yield iterator.next(), + value = _yield$iterator$next.value, + done = _yield$iterator$next.done; + if (done) { + readable.push(null); + } else if (readable.push(yield value)) { + next(); + } else { + reading = false; + } + } catch (err) { + readable.destroy(err); + } + }); + return _next2.apply(this, arguments); + } + return readable; +} +module.exports = from; + + +/***/ }), + +/***/ 16701: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Ported from https://github.com/mafintosh/pump with +// permission from the author, Mathias Buus (@mafintosh). + + + +var eos; +function once(callback) { + var called = false; + return function () { + if (called) return; + called = true; + callback.apply(void 0, arguments); + }; +} +var _require$codes = (__nccwpck_require__(25500)/* .codes */ .F), + ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS, + ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED; +function noop(err) { + // Rethrow the error if it exists to avoid swallowing it + if (err) throw err; +} +function isRequest(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +} +function destroyer(stream, reading, writing, callback) { + callback = once(callback); + var closed = false; + stream.on('close', function () { + closed = true; + }); + if (eos === undefined) eos = __nccwpck_require__(36815); + eos(stream, { + readable: reading, + writable: writing + }, function (err) { + if (err) return callback(err); + closed = true; + callback(); + }); + var destroyed = false; + return function (err) { + if (closed) return; + if (destroyed) return; + destroyed = true; + + // request.destroy just do .end - .abort is what we want + if (isRequest(stream)) return stream.abort(); + if (typeof stream.destroy === 'function') return stream.destroy(); + callback(err || new ERR_STREAM_DESTROYED('pipe')); + }; +} +function call(fn) { + fn(); +} +function pipe(from, to) { + return from.pipe(to); +} +function popCallback(streams) { + if (!streams.length) return noop; + if (typeof streams[streams.length - 1] !== 'function') return noop; + return streams.pop(); +} +function pipeline() { + for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) { + streams[_key] = arguments[_key]; + } + var callback = popCallback(streams); + if (Array.isArray(streams[0])) streams = streams[0]; + if (streams.length < 2) { + throw new ERR_MISSING_ARGS('streams'); + } + var error; + var destroys = streams.map(function (stream, i) { + var reading = i < streams.length - 1; + var writing = i > 0; + return destroyer(stream, reading, writing, function (err) { + if (!error) error = err; + if (err) destroys.forEach(call); + if (reading) return; + destroys.forEach(call); + callback(error); + }); + }); + return streams.reduce(pipe); +} +module.exports = pipeline; + +/***/ }), + +/***/ 54874: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var ERR_INVALID_OPT_VALUE = (__nccwpck_require__(25500)/* .codes */ .F).ERR_INVALID_OPT_VALUE; +function highWaterMarkFrom(options, isDuplex, duplexKey) { + return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null; +} +function getHighWaterMark(state, options, duplexKey, isDuplex) { + var hwm = highWaterMarkFrom(options, isDuplex, duplexKey); + if (hwm != null) { + if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) { + var name = isDuplex ? duplexKey : 'highWaterMark'; + throw new ERR_INVALID_OPT_VALUE(name, hwm); + } + return Math.floor(hwm); + } + + // Default value + return state.objectMode ? 16 : 16 * 1024; +} +module.exports = { + getHighWaterMark: getHighWaterMark +}; + +/***/ }), + +/***/ 63283: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(2203); + + +/***/ }), + +/***/ 86131: +/***/ ((module, exports, __nccwpck_require__) => { + +var Stream = __nccwpck_require__(2203); +if (process.env.READABLE_STREAM === 'disable' && Stream) { + module.exports = Stream.Readable; + Object.assign(module.exports, Stream); + module.exports.Stream = Stream; +} else { + exports = module.exports = __nccwpck_require__(86893); + exports.Stream = Stream || exports; + exports.Readable = exports; + exports.Writable = __nccwpck_require__(38797); + exports.Duplex = __nccwpck_require__(82063); + exports.Transform = __nccwpck_require__(12337); + exports.PassThrough = __nccwpck_require__(35283); + exports.finished = __nccwpck_require__(36815); + exports.pipeline = __nccwpck_require__(16701); +} + + +/***/ }), + +/***/ 67842: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const {PassThrough} = __nccwpck_require__(2203); +const extend = __nccwpck_require__(23860); + +let debug = () => {}; +if ( + typeof process !== 'undefined' && + 'env' in process && + typeof process.env === 'object' && + process.env.DEBUG === 'retry-request' +) { + debug = message => { + console.log('retry-request:', message); + }; +} + +const DEFAULTS = { + objectMode: false, + retries: 2, + + /* + The maximum time to delay in seconds. If retryDelayMultiplier results in a + delay greater than maxRetryDelay, retries should delay by maxRetryDelay + seconds instead. + */ + maxRetryDelay: 64, + + /* + The multiplier by which to increase the delay time between the completion of + failed requests, and the initiation of the subsequent retrying request. + */ + retryDelayMultiplier: 2, + + /* + The length of time to keep retrying in seconds. The last sleep period will + be shortened as necessary, so that the last retry runs at deadline (and not + considerably beyond it). The total time starting from when the initial + request is sent, after which an error will be returned, regardless of the + retrying attempts made meanwhile. + */ + totalTimeout: 600, + + noResponseRetries: 2, + currentRetryAttempt: 0, + shouldRetryFn: function (response) { + const retryRanges = [ + // https://en.wikipedia.org/wiki/List_of_HTTP_status_codes + // 1xx - Retry (Informational, request still processing) + // 2xx - Do not retry (Success) + // 3xx - Do not retry (Redirect) + // 4xx - Do not retry (Client errors) + // 429 - Retry ("Too Many Requests") + // 5xx - Retry (Server errors) + [100, 199], + [429, 429], + [500, 599], + ]; + + const statusCode = response.statusCode; + debug(`Response status: ${statusCode}`); + + let range; + while ((range = retryRanges.shift())) { + if (statusCode >= range[0] && statusCode <= range[1]) { + // Not a successful status or redirect. + return true; + } + } + }, +}; + +function retryRequest(requestOpts, opts, callback) { + if (typeof requestOpts === 'string') { + requestOpts = {url: requestOpts}; + } + + const streamMode = typeof arguments[arguments.length - 1] !== 'function'; + + if (typeof opts === 'function') { + callback = opts; + } + + const manualCurrentRetryAttemptWasSet = + opts && typeof opts.currentRetryAttempt === 'number'; + opts = extend({}, DEFAULTS, opts); + + if (typeof opts.request === 'undefined') { + throw new Error('A request library must be provided to retry-request.'); + } + + let currentRetryAttempt = opts.currentRetryAttempt; + + let numNoResponseAttempts = 0; + let streamResponseHandled = false; + + let retryStream; + let requestStream; + let delayStream; + + let activeRequest; + const retryRequest = { + abort: function () { + if (activeRequest && activeRequest.abort) { + activeRequest.abort(); + } + }, + }; + + if (streamMode) { + retryStream = new PassThrough({objectMode: opts.objectMode}); + retryStream.abort = resetStreams; + } + + const timeOfFirstRequest = Date.now(); + if (currentRetryAttempt > 0) { + retryAfterDelay(currentRetryAttempt); + } else { + makeRequest(); + } + + if (streamMode) { + return retryStream; + } else { + return retryRequest; + } + + function resetStreams() { + delayStream = null; + + if (requestStream) { + requestStream.abort && requestStream.abort(); + requestStream.cancel && requestStream.cancel(); + + if (requestStream.destroy) { + requestStream.destroy(); + } else if (requestStream.end) { + requestStream.end(); + } + } + } + + function makeRequest() { + let finishHandled = false; + currentRetryAttempt++; + debug(`Current retry attempt: ${currentRetryAttempt}`); + + function handleFinish(args = []) { + if (!finishHandled) { + finishHandled = true; + retryStream.emit('complete', ...args); + } + } + + if (streamMode) { + streamResponseHandled = false; + + delayStream = new PassThrough({objectMode: opts.objectMode}); + requestStream = opts.request(requestOpts); + + setImmediate(() => { + retryStream.emit('request'); + }); + + requestStream + // gRPC via google-cloud-node can emit an `error` as well as a `response` + // Whichever it emits, we run with-- we can't run with both. That's what + // is up with the `streamResponseHandled` tracking. + .on('error', err => { + if (streamResponseHandled) { + return; + } + + streamResponseHandled = true; + onResponse(err); + }) + .on('response', (resp, body) => { + if (streamResponseHandled) { + return; + } + + streamResponseHandled = true; + onResponse(null, resp, body); + }) + .on('complete', (...params) => handleFinish(params)) + .on('finish', (...params) => handleFinish(params)); + + requestStream.pipe(delayStream); + } else { + activeRequest = opts.request(requestOpts, onResponse); + } + } + + function retryAfterDelay(currentRetryAttempt) { + if (streamMode) { + resetStreams(); + } + + const nextRetryDelay = getNextRetryDelay({ + maxRetryDelay: opts.maxRetryDelay, + retryDelayMultiplier: opts.retryDelayMultiplier, + retryNumber: currentRetryAttempt, + timeOfFirstRequest, + totalTimeout: opts.totalTimeout, + }); + debug(`Next retry delay: ${nextRetryDelay}`); + + if (nextRetryDelay <= 0) { + numNoResponseAttempts = opts.noResponseRetries + 1; + return; + } + + setTimeout(makeRequest, nextRetryDelay); + } + + function onResponse(err, response, body) { + // An error such as DNS resolution. + if (err) { + numNoResponseAttempts++; + + if (numNoResponseAttempts <= opts.noResponseRetries) { + retryAfterDelay(numNoResponseAttempts); + } else { + if (streamMode) { + retryStream.emit('error', err); + retryStream.end(); + } else { + callback(err, response, body); + } + } + + return; + } + + // Send the response to see if we should try again. + // NOTE: "currentRetryAttempt" isn't accurate by default, as it counts + // the very first request sent as the first "retry". It is only accurate + // when a user provides their own "currentRetryAttempt" option at + // instantiation. + const adjustedCurrentRetryAttempt = manualCurrentRetryAttemptWasSet + ? currentRetryAttempt + : currentRetryAttempt - 1; + if ( + adjustedCurrentRetryAttempt < opts.retries && + opts.shouldRetryFn(response) + ) { + retryAfterDelay(currentRetryAttempt); + return; + } + + // No more attempts need to be made, just continue on. + if (streamMode) { + retryStream.emit('response', response); + delayStream.pipe(retryStream); + requestStream.on('error', err => { + retryStream.destroy(err); + }); + } else { + callback(err, response, body); + } + } +} + +module.exports = retryRequest; + +function getNextRetryDelay(config) { + const { + maxRetryDelay, + retryDelayMultiplier, + retryNumber, + timeOfFirstRequest, + totalTimeout, + } = config; + + const maxRetryDelayMs = maxRetryDelay * 1000; + const totalTimeoutMs = totalTimeout * 1000; + + const jitter = Math.floor(Math.random() * 1000); + const calculatedNextRetryDelay = + Math.pow(retryDelayMultiplier, retryNumber) * 1000 + jitter; + + const maxAllowableDelayMs = + totalTimeoutMs - (Date.now() - timeOfFirstRequest); + + return Math.min( + calculatedNextRetryDelay, + maxAllowableDelayMs, + maxRetryDelayMs + ); +} + +module.exports.defaults = DEFAULTS; +module.exports.getNextRetryDelay = getNextRetryDelay; + + +/***/ }), + +/***/ 5546: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(67084); + +/***/ }), + +/***/ 67084: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +var RetryOperation = __nccwpck_require__(39538); + +exports.operation = function(options) { + var timeouts = exports.timeouts(options); + return new RetryOperation(timeouts, { + forever: options && (options.forever || options.retries === Infinity), + unref: options && options.unref, + maxRetryTime: options && options.maxRetryTime + }); +}; + +exports.timeouts = function(options) { + if (options instanceof Array) { + return [].concat(options); + } + + var opts = { + retries: 10, + factor: 2, + minTimeout: 1 * 1000, + maxTimeout: Infinity, + randomize: false + }; + for (var key in options) { + opts[key] = options[key]; + } + + if (opts.minTimeout > opts.maxTimeout) { + throw new Error('minTimeout is greater than maxTimeout'); + } + + var timeouts = []; + for (var i = 0; i < opts.retries; i++) { + timeouts.push(this.createTimeout(i, opts)); + } + + if (options && options.forever && !timeouts.length) { + timeouts.push(this.createTimeout(i, opts)); + } + + // sort the array numerically ascending + timeouts.sort(function(a,b) { + return a - b; + }); + + return timeouts; +}; + +exports.createTimeout = function(attempt, opts) { + var random = (opts.randomize) + ? (Math.random() + 1) + : 1; + + var timeout = Math.round(random * Math.max(opts.minTimeout, 1) * Math.pow(opts.factor, attempt)); + timeout = Math.min(timeout, opts.maxTimeout); + + return timeout; +}; + +exports.wrap = function(obj, options, methods) { + if (options instanceof Array) { + methods = options; + options = null; + } + + if (!methods) { + methods = []; + for (var key in obj) { + if (typeof obj[key] === 'function') { + methods.push(key); + } + } + } + + for (var i = 0; i < methods.length; i++) { + var method = methods[i]; + var original = obj[method]; + + obj[method] = function retryWrapper(original) { + var op = exports.operation(options); + var args = Array.prototype.slice.call(arguments, 1); + var callback = args.pop(); + + args.push(function(err) { + if (op.retry(err)) { + return; + } + if (err) { + arguments[0] = op.mainError(); + } + callback.apply(this, arguments); + }); + + op.attempt(function() { + original.apply(obj, args); + }); + }.bind(obj, original); + obj[method].options = options; + } +}; + + +/***/ }), + +/***/ 39538: +/***/ ((module) => { + +function RetryOperation(timeouts, options) { + // Compatibility for the old (timeouts, retryForever) signature + if (typeof options === 'boolean') { + options = { forever: options }; + } + + this._originalTimeouts = JSON.parse(JSON.stringify(timeouts)); + this._timeouts = timeouts; + this._options = options || {}; + this._maxRetryTime = options && options.maxRetryTime || Infinity; + this._fn = null; + this._errors = []; + this._attempts = 1; + this._operationTimeout = null; + this._operationTimeoutCb = null; + this._timeout = null; + this._operationStart = null; + this._timer = null; + + if (this._options.forever) { + this._cachedTimeouts = this._timeouts.slice(0); + } +} +module.exports = RetryOperation; + +RetryOperation.prototype.reset = function() { + this._attempts = 1; + this._timeouts = this._originalTimeouts.slice(0); +} + +RetryOperation.prototype.stop = function() { + if (this._timeout) { + clearTimeout(this._timeout); + } + if (this._timer) { + clearTimeout(this._timer); + } + + this._timeouts = []; + this._cachedTimeouts = null; +}; + +RetryOperation.prototype.retry = function(err) { + if (this._timeout) { + clearTimeout(this._timeout); + } + + if (!err) { + return false; + } + var currentTime = new Date().getTime(); + if (err && currentTime - this._operationStart >= this._maxRetryTime) { + this._errors.push(err); + this._errors.unshift(new Error('RetryOperation timeout occurred')); + return false; + } + + this._errors.push(err); + + var timeout = this._timeouts.shift(); + if (timeout === undefined) { + if (this._cachedTimeouts) { + // retry forever, only keep last error + this._errors.splice(0, this._errors.length - 1); + timeout = this._cachedTimeouts.slice(-1); + } else { + return false; + } + } + + var self = this; + this._timer = setTimeout(function() { + self._attempts++; + + if (self._operationTimeoutCb) { + self._timeout = setTimeout(function() { + self._operationTimeoutCb(self._attempts); + }, self._operationTimeout); + + if (self._options.unref) { + self._timeout.unref(); + } + } + + self._fn(self._attempts); + }, timeout); + + if (this._options.unref) { + this._timer.unref(); + } + + return true; +}; + +RetryOperation.prototype.attempt = function(fn, timeoutOps) { + this._fn = fn; + + if (timeoutOps) { + if (timeoutOps.timeout) { + this._operationTimeout = timeoutOps.timeout; + } + if (timeoutOps.cb) { + this._operationTimeoutCb = timeoutOps.cb; + } + } + + var self = this; + if (this._operationTimeoutCb) { + this._timeout = setTimeout(function() { + self._operationTimeoutCb(); + }, self._operationTimeout); + } + + this._operationStart = new Date().getTime(); + + this._fn(this._attempts); +}; + +RetryOperation.prototype.try = function(fn) { + console.log('Using RetryOperation.try() is deprecated'); + this.attempt(fn); +}; + +RetryOperation.prototype.start = function(fn) { + console.log('Using RetryOperation.start() is deprecated'); + this.attempt(fn); +}; + +RetryOperation.prototype.start = RetryOperation.prototype.try; + +RetryOperation.prototype.errors = function() { + return this._errors; +}; + +RetryOperation.prototype.attempts = function() { + return this._attempts; +}; + +RetryOperation.prototype.mainError = function() { + if (this._errors.length === 0) { + return null; + } + + var counts = {}; + var mainError = null; + var mainErrorCount = 0; + + for (var i = 0; i < this._errors.length; i++) { + var error = this._errors[i]; + var message = error.message; + var count = (counts[message] || 0) + 1; + + counts[message] = count; + + if (count >= mainErrorCount) { + mainError = error; + mainErrorCount = count; + } + } + + return mainError; +}; + + +/***/ }), + +/***/ 93058: +/***/ ((module, exports, __nccwpck_require__) => { + +/*! safe-buffer. MIT License. Feross Aboukhadijeh */ +/* eslint-disable node/no-deprecated-api */ +var buffer = __nccwpck_require__(20181) +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.prototype = Object.create(Buffer.prototype) + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + + +/***/ }), + +/***/ 71546: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var stubs = __nccwpck_require__(33897) + +/* + * StreamEvents can be used 2 ways: + * + * 1: + * function MyStream() { + * require('stream-events').call(this) + * } + * + * 2: + * require('stream-events')(myStream) + */ +function StreamEvents(stream) { + stream = stream || this + + var cfg = { + callthrough: true, + calls: 1 + } + + stubs(stream, '_read', cfg, stream.emit.bind(stream, 'reading')) + stubs(stream, '_write', cfg, stream.emit.bind(stream, 'writing')) + + return stream +} + +module.exports = StreamEvents + + +/***/ }), + +/***/ 34633: +/***/ ((module) => { + +module.exports = shift + +function shift (stream) { + var rs = stream._readableState + if (!rs) return null + return (rs.objectMode || typeof stream._duplexState === 'number') ? stream.read() : stream.read(getStateLength(rs)) +} + +function getStateLength (state) { + if (state.buffer.length) { + var idx = state.bufferIndex || 0 + // Since node 6.3.0 state.buffer is a BufferList not an array + if (state.buffer.head) { + return state.buffer.head.data.length + } else if (state.buffer.length - idx > 0 && state.buffer[idx]) { + return state.buffer[idx].length + } + } + + return state.length +} + + +/***/ }), + +/***/ 80634: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +/**/ + +var Buffer = (__nccwpck_require__(93058).Buffer); +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.I = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} + +/***/ }), + +/***/ 33897: +/***/ ((module) => { + +"use strict"; + + +module.exports = function stubs(obj, method, cfg, stub) { + if (!obj || !method || !obj[method]) + throw new Error('You must provide an object and a key for an existing method') + + if (!stub) { + stub = cfg + cfg = {} + } + + stub = stub || function() {} + + cfg.callthrough = cfg.callthrough || false + cfg.calls = cfg.calls || 0 + + var norevert = cfg.calls === 0 + + var cached = obj[method].bind(obj) + + obj[method] = function() { + var args = [].slice.call(arguments) + var returnVal + + if (cfg.callthrough) + returnVal = cached.apply(obj, args) + + returnVal = stub.apply(obj, args) || returnVal + + if (!norevert && --cfg.calls === 0) + obj[method] = cached + + return returnVal + } +} + + +/***/ }), + +/***/ 97745: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TeenyStatistics = exports.TeenyStatisticsWarning = void 0; +/** + * @class TeenyStatisticsWarning + * @extends Error + * @description While an error, is used for emitting warnings when + * meeting certain configured thresholds. + * @see process.emitWarning + */ +class TeenyStatisticsWarning extends Error { + /** + * @param {string} message + */ + constructor(message) { + super(message); + this.threshold = 0; + this.type = ''; + this.value = 0; + this.name = this.constructor.name; + Error.captureStackTrace(this, this.constructor); + } +} +exports.TeenyStatisticsWarning = TeenyStatisticsWarning; +TeenyStatisticsWarning.CONCURRENT_REQUESTS = 'ConcurrentRequestsExceededWarning'; +/** + * @class TeenyStatistics + * @description Maintain various statistics internal to teeny-request. Tracking + * is not automatic and must be instrumented within teeny-request. + */ +class TeenyStatistics { + /** + * @param {TeenyStatisticsOptions} [opts] + */ + constructor(opts) { + /** + * @type {number} + * @private + * @default 0 + */ + this._concurrentRequests = 0; + /** + * @type {boolean} + * @private + * @default false + */ + this._didConcurrentRequestWarn = false; + this._options = TeenyStatistics._prepareOptions(opts); + } + /** + * Returns a copy of the current options. + * @return {TeenyStatisticsOptions} + */ + getOptions() { + return Object.assign({}, this._options); + } + /** + * Change configured statistics options. This will not preserve unspecified + * options that were previously specified, i.e. this is a reset of options. + * @param {TeenyStatisticsOptions} [opts] + * @returns {TeenyStatisticsConfig} The previous options. + * @see _prepareOptions + */ + setOptions(opts) { + const oldOpts = this._options; + this._options = TeenyStatistics._prepareOptions(opts); + return oldOpts; + } + /** + * @readonly + * @return {TeenyStatisticsCounters} + */ + get counters() { + return { + concurrentRequests: this._concurrentRequests, + }; + } + /** + * @description Should call this right before making a request. + */ + requestStarting() { + this._concurrentRequests++; + if (this._options.concurrentRequests > 0 && + this._concurrentRequests >= this._options.concurrentRequests && + !this._didConcurrentRequestWarn) { + this._didConcurrentRequestWarn = true; + const warning = new TeenyStatisticsWarning('Possible excessive concurrent requests detected. ' + + this._concurrentRequests + + ' requests in-flight, which exceeds the configured threshold of ' + + this._options.concurrentRequests + + '. Use the TEENY_REQUEST_WARN_CONCURRENT_REQUESTS environment ' + + 'variable or the concurrentRequests option of teeny-request to ' + + 'increase or disable (0) this warning.'); + warning.type = TeenyStatisticsWarning.CONCURRENT_REQUESTS; + warning.value = this._concurrentRequests; + warning.threshold = this._options.concurrentRequests; + process.emitWarning(warning); + } + } + /** + * @description When using `requestStarting`, call this after the request + * has finished. + */ + requestFinished() { + // TODO negative? + this._concurrentRequests--; + } + /** + * Configuration Precedence: + * 1. Dependency inversion via defined option. + * 2. Global numeric environment variable. + * 3. Built-in default. + * This will not preserve unspecified options previously specified. + * @param {TeenyStatisticsOptions} [opts] + * @returns {TeenyStatisticsOptions} + * @private + */ + static _prepareOptions({ concurrentRequests: diConcurrentRequests, } = {}) { + let concurrentRequests = this.DEFAULT_WARN_CONCURRENT_REQUESTS; + const envConcurrentRequests = Number(process.env.TEENY_REQUEST_WARN_CONCURRENT_REQUESTS); + if (diConcurrentRequests !== undefined) { + concurrentRequests = diConcurrentRequests; + } + else if (!Number.isNaN(envConcurrentRequests)) { + concurrentRequests = envConcurrentRequests; + } + return { concurrentRequests }; + } +} +exports.TeenyStatistics = TeenyStatistics; +/** + * @description A default threshold representing when to warn about excessive + * in-flight/concurrent requests. + * @type {number} + * @static + * @readonly + * @default 5000 + */ +TeenyStatistics.DEFAULT_WARN_CONCURRENT_REQUESTS = 5000; +//# sourceMappingURL=TeenyStatistics.js.map + +/***/ }), + +/***/ 34003: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * @license + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getAgent = exports.pool = void 0; +const http_1 = __nccwpck_require__(58611); +const https_1 = __nccwpck_require__(65692); +// eslint-disable-next-line node/no-deprecated-api +const url_1 = __nccwpck_require__(87016); +exports.pool = new Map(); +/** + * Determines if a proxy should be considered based on the environment. + * + * @param uri The request uri + * @returns {boolean} + */ +function shouldUseProxyForURI(uri) { + const noProxyEnv = process.env.NO_PROXY || process.env.no_proxy; + if (!noProxyEnv) { + return true; + } + const givenURI = new URL(uri); + for (const noProxyRaw of noProxyEnv.split(',')) { + const noProxy = noProxyRaw.trim(); + if (noProxy === givenURI.origin || noProxy === givenURI.hostname) { + return false; + } + else if (noProxy.startsWith('*.') || noProxy.startsWith('.')) { + const noProxyWildcard = noProxy.replace(/^\*\./, '.'); + if (givenURI.hostname.endsWith(noProxyWildcard)) { + return false; + } + } + } + return true; +} +/** + * Returns a custom request Agent if one is found, otherwise returns undefined + * which will result in the global http(s) Agent being used. + * @private + * @param {string} uri The request uri + * @param {Options} reqOpts The request options + * @returns {HttpAnyAgent|undefined} + */ +function getAgent(uri, reqOpts) { + const isHttp = uri.startsWith('http://'); + const proxy = reqOpts.proxy || + process.env.HTTP_PROXY || + process.env.http_proxy || + process.env.HTTPS_PROXY || + process.env.https_proxy; + const poolOptions = Object.assign({}, reqOpts.pool); + const manuallyProvidedProxy = !!reqOpts.proxy; + const shouldUseProxy = manuallyProvidedProxy || shouldUseProxyForURI(uri); + if (proxy && shouldUseProxy) { + // tslint:disable-next-line variable-name + const Agent = isHttp + ? __nccwpck_require__(81970) + : __nccwpck_require__(6518); + const proxyOpts = { ...(0, url_1.parse)(proxy), ...poolOptions }; + return new Agent(proxyOpts); + } + let key = isHttp ? 'http' : 'https'; + if (reqOpts.forever) { + key += ':forever'; + if (!exports.pool.has(key)) { + // tslint:disable-next-line variable-name + const Agent = isHttp ? http_1.Agent : https_1.Agent; + exports.pool.set(key, new Agent({ ...poolOptions, keepAlive: true })); + } + } + return exports.pool.get(key); +} +exports.getAgent = getAgent; +//# sourceMappingURL=agents.js.map + +/***/ }), + +/***/ 80321: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/** + * @license + * Copyright 2018 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.teenyRequest = exports.RequestError = void 0; +const node_fetch_1 = __nccwpck_require__(26705); +const stream_1 = __nccwpck_require__(2203); +const uuid = __nccwpck_require__(12048); +const agents_1 = __nccwpck_require__(34003); +const TeenyStatistics_1 = __nccwpck_require__(97745); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const streamEvents = __nccwpck_require__(71546); +class RequestError extends Error { +} +exports.RequestError = RequestError; +/** + * Convert options from Request to Fetch format + * @private + * @param reqOpts Request options + */ +function requestToFetchOptions(reqOpts) { + const options = { + method: reqOpts.method || 'GET', + ...(reqOpts.timeout && { timeout: reqOpts.timeout }), + ...(typeof reqOpts.gzip === 'boolean' && { compress: reqOpts.gzip }), + }; + if (typeof reqOpts.json === 'object') { + // Add Content-type: application/json header + reqOpts.headers = reqOpts.headers || {}; + reqOpts.headers['Content-Type'] = 'application/json'; + // Set body to JSON representation of value + options.body = JSON.stringify(reqOpts.json); + } + else { + if (Buffer.isBuffer(reqOpts.body)) { + options.body = reqOpts.body; + } + else if (typeof reqOpts.body !== 'string') { + options.body = JSON.stringify(reqOpts.body); + } + else { + options.body = reqOpts.body; + } + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + options.headers = reqOpts.headers; + let uri = (reqOpts.uri || + reqOpts.url); + if (!uri) { + throw new Error('Missing uri or url in reqOpts.'); + } + if (reqOpts.useQuerystring === true || typeof reqOpts.qs === 'object') { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const qs = __nccwpck_require__(83480); + const params = qs.stringify(reqOpts.qs); + uri = uri + '?' + params; + } + options.agent = (0, agents_1.getAgent)(uri, reqOpts); + return { uri, options }; +} +/** + * Convert a response from `fetch` to `request` format. + * @private + * @param opts The `request` options used to create the request. + * @param res The Fetch response + * @returns A `request` response object + */ +function fetchToRequestResponse(opts, res) { + const request = {}; + request.agent = opts.agent || false; + request.headers = (opts.headers || {}); + request.href = res.url; + // headers need to be converted from a map to an obj + const resHeaders = {}; + res.headers.forEach((value, key) => (resHeaders[key] = value)); + const response = Object.assign(res.body, { + statusCode: res.status, + statusMessage: res.statusText, + request, + body: res.body, + headers: resHeaders, + toJSON: () => ({ headers: resHeaders }), + }); + return response; +} +/** + * Create POST body from two parts as multipart/related content-type + * @private + * @param boundary + * @param multipart + */ +function createMultipartStream(boundary, multipart) { + const finale = `--${boundary}--`; + const stream = new stream_1.PassThrough(); + for (const part of multipart) { + const preamble = `--${boundary}\r\nContent-Type: ${part['Content-Type']}\r\n\r\n`; + stream.write(preamble); + if (typeof part.body === 'string') { + stream.write(part.body); + stream.write('\r\n'); + } + else { + part.body.pipe(stream, { end: false }); + part.body.on('end', () => { + stream.write('\r\n'); + stream.write(finale); + stream.end(); + }); + } + } + return stream; +} +function teenyRequest(reqOpts, callback) { + const { uri, options } = requestToFetchOptions(reqOpts); + const multipart = reqOpts.multipart; + if (reqOpts.multipart && multipart.length === 2) { + if (!callback) { + // TODO: add support for multipart uploads through streaming + throw new Error('Multipart without callback is not implemented.'); + } + const boundary = uuid.v4(); + options.headers['Content-Type'] = `multipart/related; boundary=${boundary}`; + options.body = createMultipartStream(boundary, multipart); + // Multipart upload + teenyRequest.stats.requestStarting(); + (0, node_fetch_1.default)(uri, options).then(res => { + teenyRequest.stats.requestFinished(); + const header = res.headers.get('content-type'); + const response = fetchToRequestResponse(options, res); + const body = response.body; + if (header === 'application/json' || + header === 'application/json; charset=utf-8') { + res.json().then(json => { + response.body = json; + callback(null, response, json); + }, (err) => { + callback(err, response, body); + }); + return; + } + res.text().then(text => { + response.body = text; + callback(null, response, text); + }, err => { + callback(err, response, body); + }); + }, err => { + teenyRequest.stats.requestFinished(); + callback(err, null, null); + }); + return; + } + if (callback === undefined) { + // Stream mode + const requestStream = streamEvents(new stream_1.PassThrough()); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let responseStream; + requestStream.once('reading', () => { + if (responseStream) { + (0, stream_1.pipeline)(responseStream, requestStream, () => { }); + } + else { + requestStream.once('response', () => { + (0, stream_1.pipeline)(responseStream, requestStream, () => { }); + }); + } + }); + options.compress = false; + teenyRequest.stats.requestStarting(); + (0, node_fetch_1.default)(uri, options).then(res => { + teenyRequest.stats.requestFinished(); + responseStream = res.body; + responseStream.on('error', (err) => { + requestStream.emit('error', err); + }); + const response = fetchToRequestResponse(options, res); + requestStream.emit('response', response); + }, err => { + teenyRequest.stats.requestFinished(); + requestStream.emit('error', err); + }); + // fetch doesn't supply the raw HTTP stream, instead it + // returns a PassThrough piped from the HTTP response + // stream. + return requestStream; + } + // GET or POST with callback + teenyRequest.stats.requestStarting(); + (0, node_fetch_1.default)(uri, options).then(res => { + teenyRequest.stats.requestFinished(); + const header = res.headers.get('content-type'); + const response = fetchToRequestResponse(options, res); + const body = response.body; + if (header === 'application/json' || + header === 'application/json; charset=utf-8') { + if (response.statusCode === 204) { + // Probably a DELETE + callback(null, response, body); + return; + } + res.json().then(json => { + response.body = json; + callback(null, response, json); + }, err => { + callback(err, response, body); + }); + return; + } + res.text().then(text => { + const response = fetchToRequestResponse(options, res); + response.body = text; + callback(null, response, text); + }, err => { + callback(err, response, body); + }); + }, err => { + teenyRequest.stats.requestFinished(); + callback(err, null, null); + }); + return; +} +exports.teenyRequest = teenyRequest; +teenyRequest.defaults = (defaults) => { + return (reqOpts, callback) => { + const opts = { ...defaults, ...reqOpts }; + if (callback === undefined) { + return teenyRequest(opts); + } + teenyRequest(opts, callback); + }; +}; +/** + * Single instance of an interface for keeping track of things. + */ +teenyRequest.stats = new TeenyStatistics_1.TeenyStatistics(); +teenyRequest.resetStats = () => { + teenyRequest.stats = new TeenyStatistics_1.TeenyStatistics(teenyRequest.stats.getOptions()); +}; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 77954: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = __nccwpck_require__(24434); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const promisify_1 = __importDefault(__nccwpck_require__(44446)); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 44446: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports["default"] = promisify; +//# sourceMappingURL=promisify.js.map + +/***/ }), + +/***/ 15299: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const net_1 = __importDefault(__nccwpck_require__(69278)); +const tls_1 = __importDefault(__nccwpck_require__(64756)); +const url_1 = __importDefault(__nccwpck_require__(87016)); +const assert_1 = __importDefault(__nccwpck_require__(42613)); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const agent_base_1 = __nccwpck_require__(77954); +const parse_proxy_response_1 = __importDefault(__nccwpck_require__(27742)); +const debug = debug_1.default('https-proxy-agent:agent'); +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + * + * @api public + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('creating new HttpsProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + // ALPN is supported by Node.js >= v5. + // attempt to negotiate http/1.1 for proxy servers that support http/2 + if (this.secureProxy && !('ALPNProtocols' in proxy)) { + proxy.ALPNProtocols = ['http 1.1']; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + const headers = Object.assign({}, proxy.headers); + const hostname = `${opts.host}:${opts.port}`; + let payload = `CONNECT ${hostname} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + headers['Proxy-Authorization'] = `Basic ${Buffer.from(proxy.auth).toString('base64')}`; + } + // The `Host` header should only include the port + // number when it is not the default port. + let { host, port, secureEndpoint } = opts; + if (!isDefaultPort(port, secureEndpoint)) { + host += `:${port}`; + } + headers.Host = host; + headers.Connection = 'close'; + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = parse_proxy_response_1.default(socket); + socket.write(`${payload}\r\n`); + const { statusCode, buffered } = yield proxyResponsePromise; + if (statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + const servername = opts.servername || opts.host; + return tls_1.default.connect(Object.assign(Object.assign({}, omit(opts, 'host', 'hostname', 'path', 'port')), { socket, + servername })); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net_1.default.Socket({ writable: false }); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('replaying proxy buffer for failed request'); + assert_1.default(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + }); + } +} +exports["default"] = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function isDefaultPort(port, secure) { + return Boolean((!secure && port === 80) || (secure && port === 443)); +} +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=agent.js.map + +/***/ }), + +/***/ 6518: +/***/ (function(module, __unused_webpack_exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const agent_1 = __importDefault(__nccwpck_require__(15299)); +function createHttpsProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpsProxyAgent) { + createHttpsProxyAgent.HttpsProxyAgent = agent_1.default; + createHttpsProxyAgent.prototype = agent_1.default.prototype; +})(createHttpsProxyAgent || (createHttpsProxyAgent = {})); +module.exports = createHttpsProxyAgent; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 27742: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const debug_1 = __importDefault(__nccwpck_require__(2830)); +const debug = debug_1.default('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('close', onclose); + socket.removeListener('readable', read); + } + function onclose(err) { + debug('onclose had error %o', err); + } + function onend() { + debug('onend'); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const firstLine = buffered.toString('ascii', 0, buffered.indexOf('\r\n')); + const statusCode = +firstLine.split(' ')[1]; + debug('got proxy server response: %o', firstLine); + resolve({ + statusCode, + buffered + }); + } + socket.on('error', onerror); + socket.on('close', onclose); + socket.on('end', onend); + read(); + }); +} +exports["default"] = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map + +/***/ }), + +/***/ 1552: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var punycode = __nccwpck_require__(24876); +var mappingTable = __nccwpck_require__(92472); + +var PROCESSING_OPTIONS = { + TRANSITIONAL: 0, + NONTRANSITIONAL: 1 +}; + +function normalize(str) { // fix bug in v8 + return str.split('\u0000').map(function (s) { return s.normalize('NFC'); }).join('\u0000'); +} + +function findStatus(val) { + var start = 0; + var end = mappingTable.length - 1; + + while (start <= end) { + var mid = Math.floor((start + end) / 2); + + var target = mappingTable[mid]; + if (target[0][0] <= val && target[0][1] >= val) { + return target; + } else if (target[0][0] > val) { + end = mid - 1; + } else { + start = mid + 1; + } + } + + return null; +} + +var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + +function countSymbols(string) { + return string + // replace every surrogate pair with a BMP symbol + .replace(regexAstralSymbols, '_') + // then get the length + .length; +} + +function mapChars(domain_name, useSTD3, processing_option) { + var hasError = false; + var processed = ""; + + var len = countSymbols(domain_name); + for (var i = 0; i < len; ++i) { + var codePoint = domain_name.codePointAt(i); + var status = findStatus(codePoint); + + switch (status[1]) { + case "disallowed": + hasError = true; + processed += String.fromCodePoint(codePoint); + break; + case "ignored": + break; + case "mapped": + processed += String.fromCodePoint.apply(String, status[2]); + break; + case "deviation": + if (processing_option === PROCESSING_OPTIONS.TRANSITIONAL) { + processed += String.fromCodePoint.apply(String, status[2]); + } else { + processed += String.fromCodePoint(codePoint); + } + break; + case "valid": + processed += String.fromCodePoint(codePoint); + break; + case "disallowed_STD3_mapped": + if (useSTD3) { + hasError = true; + processed += String.fromCodePoint(codePoint); + } else { + processed += String.fromCodePoint.apply(String, status[2]); + } + break; + case "disallowed_STD3_valid": + if (useSTD3) { + hasError = true; + } + + processed += String.fromCodePoint(codePoint); + break; + } + } + + return { + string: processed, + error: hasError + }; +} + +var combiningMarksRegex = /[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8\u19C9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDE2C-\uDE37\uDEDF-\uDEEA\uDF01-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDE30-\uDE40\uDEAB-\uDEB7]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD83A[\uDCD0-\uDCD6]|\uDB40[\uDD00-\uDDEF]/; + +function validateLabel(label, processing_option) { + if (label.substr(0, 4) === "xn--") { + label = punycode.toUnicode(label); + processing_option = PROCESSING_OPTIONS.NONTRANSITIONAL; + } + + var error = false; + + if (normalize(label) !== label || + (label[3] === "-" && label[4] === "-") || + label[0] === "-" || label[label.length - 1] === "-" || + label.indexOf(".") !== -1 || + label.search(combiningMarksRegex) === 0) { + error = true; + } + + var len = countSymbols(label); + for (var i = 0; i < len; ++i) { + var status = findStatus(label.codePointAt(i)); + if ((processing === PROCESSING_OPTIONS.TRANSITIONAL && status[1] !== "valid") || + (processing === PROCESSING_OPTIONS.NONTRANSITIONAL && + status[1] !== "valid" && status[1] !== "deviation")) { + error = true; + break; + } + } + + return { + label: label, + error: error + }; +} + +function processing(domain_name, useSTD3, processing_option) { + var result = mapChars(domain_name, useSTD3, processing_option); + result.string = normalize(result.string); + + var labels = result.string.split("."); + for (var i = 0; i < labels.length; ++i) { + try { + var validation = validateLabel(labels[i]); + labels[i] = validation.label; + result.error = result.error || validation.error; + } catch(e) { + result.error = true; + } + } + + return { + string: labels.join("."), + error: result.error + }; +} + +module.exports.toASCII = function(domain_name, useSTD3, processing_option, verifyDnsLength) { + var result = processing(domain_name, useSTD3, processing_option); + var labels = result.string.split("."); + labels = labels.map(function(l) { + try { + return punycode.toASCII(l); + } catch(e) { + result.error = true; + return l; + } + }); + + if (verifyDnsLength) { + var total = labels.slice(0, labels.length - 1).join(".").length; + if (total.length > 253 || total.length === 0) { + result.error = true; + } + + for (var i=0; i < labels.length; ++i) { + if (labels.length > 63 || labels.length === 0) { + result.error = true; + break; + } + } + } + + if (result.error) return null; + return labels.join("."); +}; + +module.exports.toUnicode = function(domain_name, useSTD3) { + var result = processing(domain_name, useSTD3, PROCESSING_OPTIONS.NONTRANSITIONAL); + + return { + domain: result.string, + error: result.error + }; +}; + +module.exports.PROCESSING_OPTIONS = PROCESSING_OPTIONS; + + +/***/ }), + +/***/ 61860: +/***/ ((module) => { + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +/* global global, define, Symbol, Reflect, Promise, SuppressedError, Iterator */ +var __extends; +var __assign; +var __rest; +var __decorate; +var __param; +var __esDecorate; +var __runInitializers; +var __propKey; +var __setFunctionName; +var __metadata; +var __awaiter; +var __generator; +var __exportStar; +var __values; +var __read; +var __spread; +var __spreadArrays; +var __spreadArray; +var __await; +var __asyncGenerator; +var __asyncDelegator; +var __asyncValues; +var __makeTemplateObject; +var __importStar; +var __importDefault; +var __classPrivateFieldGet; +var __classPrivateFieldSet; +var __classPrivateFieldIn; +var __createBinding; +var __addDisposableResource; +var __disposeResources; +var __rewriteRelativeImportExtension; +(function (factory) { + var root = typeof global === "object" ? global : typeof self === "object" ? self : typeof this === "object" ? this : {}; + if (typeof define === "function" && define.amd) { + define("tslib", ["exports"], function (exports) { factory(createExporter(root, createExporter(exports))); }); + } + else if ( true && typeof module.exports === "object") { + factory(createExporter(root, createExporter(module.exports))); + } + else { + factory(createExporter(root)); + } + function createExporter(exports, previous) { + if (exports !== root) { + if (typeof Object.create === "function") { + Object.defineProperty(exports, "__esModule", { value: true }); + } + else { + exports.__esModule = true; + } + } + return function (id, v) { return exports[id] = previous ? previous(id, v) : v; }; + } +}) +(function (exporter) { + var extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + + __extends = function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + + __assign = Object.assign || function (t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + + __rest = function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; + }; + + __decorate = function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; + }; + + __param = function (paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } + }; + + __esDecorate = function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { + function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } + var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; + var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; + var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); + var _, done = false; + for (var i = decorators.length - 1; i >= 0; i--) { + var context = {}; + for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; + for (var p in contextIn.access) context.access[p] = contextIn.access[p]; + context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; + var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); + if (kind === "accessor") { + if (result === void 0) continue; + if (result === null || typeof result !== "object") throw new TypeError("Object expected"); + if (_ = accept(result.get)) descriptor.get = _; + if (_ = accept(result.set)) descriptor.set = _; + if (_ = accept(result.init)) initializers.unshift(_); + } + else if (_ = accept(result)) { + if (kind === "field") initializers.unshift(_); + else descriptor[key] = _; + } + } + if (target) Object.defineProperty(target, contextIn.name, descriptor); + done = true; + }; + + __runInitializers = function (thisArg, initializers, value) { + var useValue = arguments.length > 2; + for (var i = 0; i < initializers.length; i++) { + value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); + } + return useValue ? value : void 0; + }; + + __propKey = function (x) { + return typeof x === "symbol" ? x : "".concat(x); + }; + + __setFunctionName = function (f, name, prefix) { + if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; + return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); + }; + + __metadata = function (metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); + }; + + __awaiter = function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); + }; + + __generator = function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); + return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } + }; + + __exportStar = function(m, o) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); + }; + + __createBinding = Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + }); + + __values = function (o) { + var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; + if (m) return m.call(o); + if (o && typeof o.length === "number") return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; + throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); + }; + + __read = function (o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; + }; + + /** @deprecated */ + __spread = function () { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; + }; + + /** @deprecated */ + __spreadArrays = function () { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + }; + + __spreadArray = function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); + }; + + __await = function (v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); + }; + + __asyncGenerator = function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i; + function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; } + function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } + }; + + __asyncDelegator = function (o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } + }; + + __asyncValues = function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } + }; + + __makeTemplateObject = function (cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; + }; + + var __setModuleDefault = Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }; + + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + + __importStar = function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; + + __importDefault = function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + + __classPrivateFieldGet = function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); + }; + + __classPrivateFieldSet = function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; + }; + + __classPrivateFieldIn = function (state, receiver) { + if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); + return typeof state === "function" ? receiver === state : state.has(receiver); + }; + + __addDisposableResource = function (env, value, async) { + if (value !== null && value !== void 0) { + if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); + var dispose, inner; + if (async) { + if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); + dispose = value[Symbol.asyncDispose]; + } + if (dispose === void 0) { + if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); + dispose = value[Symbol.dispose]; + if (async) inner = dispose; + } + if (typeof dispose !== "function") throw new TypeError("Object not disposable."); + if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } }; + env.stack.push({ value: value, dispose: dispose, async: async }); + } + else if (async) { + env.stack.push({ async: true }); + } + return value; + }; + + var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; + }; + + __disposeResources = function (env) { + function fail(e) { + env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; + env.hasError = true; + } + var r, s = 0; + function next() { + while (r = env.stack.pop()) { + try { + if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next); + if (r.dispose) { + var result = r.dispose.call(r.value); + if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + else s |= 1; + } + catch (e) { + fail(e); + } + } + if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve(); + if (env.hasError) throw env.error; + } + return next(); + }; + + __rewriteRelativeImportExtension = function (path, preserveJsx) { + if (typeof path === "string" && /^\.\.?\//.test(path)) { + return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) { + return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js"); + }); + } + return path; + }; + + exporter("__extends", __extends); + exporter("__assign", __assign); + exporter("__rest", __rest); + exporter("__decorate", __decorate); + exporter("__param", __param); + exporter("__esDecorate", __esDecorate); + exporter("__runInitializers", __runInitializers); + exporter("__propKey", __propKey); + exporter("__setFunctionName", __setFunctionName); + exporter("__metadata", __metadata); + exporter("__awaiter", __awaiter); + exporter("__generator", __generator); + exporter("__exportStar", __exportStar); + exporter("__createBinding", __createBinding); + exporter("__values", __values); + exporter("__read", __read); + exporter("__spread", __spread); + exporter("__spreadArrays", __spreadArrays); + exporter("__spreadArray", __spreadArray); + exporter("__await", __await); + exporter("__asyncGenerator", __asyncGenerator); + exporter("__asyncDelegator", __asyncDelegator); + exporter("__asyncValues", __asyncValues); + exporter("__makeTemplateObject", __makeTemplateObject); + exporter("__importStar", __importStar); + exporter("__importDefault", __importDefault); + exporter("__classPrivateFieldGet", __classPrivateFieldGet); + exporter("__classPrivateFieldSet", __classPrivateFieldSet); + exporter("__classPrivateFieldIn", __classPrivateFieldIn); + exporter("__addDisposableResource", __addDisposableResource); + exporter("__disposeResources", __disposeResources); + exporter("__rewriteRelativeImportExtension", __rewriteRelativeImportExtension); +}); + +0 && (0); + + +/***/ }), + +/***/ 20770: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(20218); + + +/***/ }), + +/***/ 20218: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +var net = __nccwpck_require__(69278); +var tls = __nccwpck_require__(64756); +var http = __nccwpck_require__(58611); +var https = __nccwpck_require__(65692); +var events = __nccwpck_require__(24434); +var assert = __nccwpck_require__(42613); +var util = __nccwpck_require__(39023); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + + +/***/ }), + +/***/ 46752: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Client = __nccwpck_require__(86197) +const Dispatcher = __nccwpck_require__(28611) +const errors = __nccwpck_require__(68707) +const Pool = __nccwpck_require__(35076) +const BalancedPool = __nccwpck_require__(81093) +const Agent = __nccwpck_require__(59965) +const util = __nccwpck_require__(3440) +const { InvalidArgumentError } = errors +const api = __nccwpck_require__(56615) +const buildConnector = __nccwpck_require__(59136) +const MockClient = __nccwpck_require__(47365) +const MockAgent = __nccwpck_require__(47501) +const MockPool = __nccwpck_require__(94004) +const mockErrors = __nccwpck_require__(52429) +const ProxyAgent = __nccwpck_require__(22720) +const RetryHandler = __nccwpck_require__(53573) +const { getGlobalDispatcher, setGlobalDispatcher } = __nccwpck_require__(32581) +const DecoratorHandler = __nccwpck_require__(78840) +const RedirectHandler = __nccwpck_require__(48299) +const createRedirectInterceptor = __nccwpck_require__(64415) + +let hasCrypto +try { + __nccwpck_require__(76982) + hasCrypto = true +} catch { + hasCrypto = false +} + +Object.assign(Dispatcher.prototype, api) + +module.exports.Dispatcher = Dispatcher +module.exports.Client = Client +module.exports.Pool = Pool +module.exports.BalancedPool = BalancedPool +module.exports.Agent = Agent +module.exports.ProxyAgent = ProxyAgent +module.exports.RetryHandler = RetryHandler + +module.exports.DecoratorHandler = DecoratorHandler +module.exports.RedirectHandler = RedirectHandler +module.exports.createRedirectInterceptor = createRedirectInterceptor + +module.exports.buildConnector = buildConnector +module.exports.errors = errors + +function makeDispatcher (fn) { + return (url, opts, handler) => { + if (typeof opts === 'function') { + handler = opts + opts = null + } + + if (!url || (typeof url !== 'string' && typeof url !== 'object' && !(url instanceof URL))) { + throw new InvalidArgumentError('invalid url') + } + + if (opts != null && typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (opts && opts.path != null) { + if (typeof opts.path !== 'string') { + throw new InvalidArgumentError('invalid opts.path') + } + + let path = opts.path + if (!opts.path.startsWith('/')) { + path = `/${path}` + } + + url = new URL(util.parseOrigin(url).origin + path) + } else { + if (!opts) { + opts = typeof url === 'object' ? url : {} + } + + url = util.parseURL(url) + } + + const { agent, dispatcher = getGlobalDispatcher() } = opts + + if (agent) { + throw new InvalidArgumentError('unsupported opts.agent. Did you mean opts.client?') + } + + return fn.call(dispatcher, { + ...opts, + origin: url.origin, + path: url.search ? `${url.pathname}${url.search}` : url.pathname, + method: opts.method || (opts.body ? 'PUT' : 'GET') + }, handler) + } +} + +module.exports.setGlobalDispatcher = setGlobalDispatcher +module.exports.getGlobalDispatcher = getGlobalDispatcher + +if (util.nodeMajor > 16 || (util.nodeMajor === 16 && util.nodeMinor >= 8)) { + let fetchImpl = null + module.exports.fetch = async function fetch (resource) { + if (!fetchImpl) { + fetchImpl = (__nccwpck_require__(12315).fetch) + } + + try { + return await fetchImpl(...arguments) + } catch (err) { + if (typeof err === 'object') { + Error.captureStackTrace(err, this) + } + + throw err + } + } + module.exports.Headers = __nccwpck_require__(26349).Headers + module.exports.Response = __nccwpck_require__(48676).Response + module.exports.Request = __nccwpck_require__(25194).Request + module.exports.FormData = __nccwpck_require__(43073).FormData + module.exports.File = __nccwpck_require__(63041).File + module.exports.FileReader = __nccwpck_require__(82160).FileReader + + const { setGlobalOrigin, getGlobalOrigin } = __nccwpck_require__(75628) + + module.exports.setGlobalOrigin = setGlobalOrigin + module.exports.getGlobalOrigin = getGlobalOrigin + + const { CacheStorage } = __nccwpck_require__(44738) + const { kConstruct } = __nccwpck_require__(80296) + + // Cache & CacheStorage are tightly coupled with fetch. Even if it may run + // in an older version of Node, it doesn't have any use without fetch. + module.exports.caches = new CacheStorage(kConstruct) +} + +if (util.nodeMajor >= 16) { + const { deleteCookie, getCookies, getSetCookies, setCookie } = __nccwpck_require__(53168) + + module.exports.deleteCookie = deleteCookie + module.exports.getCookies = getCookies + module.exports.getSetCookies = getSetCookies + module.exports.setCookie = setCookie + + const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(94322) + + module.exports.parseMIMEType = parseMIMEType + module.exports.serializeAMimeType = serializeAMimeType +} + +if (util.nodeMajor >= 18 && hasCrypto) { + const { WebSocket } = __nccwpck_require__(55171) + + module.exports.WebSocket = WebSocket +} + +module.exports.request = makeDispatcher(api.request) +module.exports.stream = makeDispatcher(api.stream) +module.exports.pipeline = makeDispatcher(api.pipeline) +module.exports.connect = makeDispatcher(api.connect) +module.exports.upgrade = makeDispatcher(api.upgrade) + +module.exports.MockClient = MockClient +module.exports.MockPool = MockPool +module.exports.MockAgent = MockAgent +module.exports.mockErrors = mockErrors + + +/***/ }), + +/***/ 59965: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { InvalidArgumentError } = __nccwpck_require__(68707) +const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = __nccwpck_require__(36443) +const DispatcherBase = __nccwpck_require__(50001) +const Pool = __nccwpck_require__(35076) +const Client = __nccwpck_require__(86197) +const util = __nccwpck_require__(3440) +const createRedirectInterceptor = __nccwpck_require__(64415) +const { WeakRef, FinalizationRegistry } = __nccwpck_require__(13194)() + +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kMaxRedirections = Symbol('maxRedirections') +const kOnDrain = Symbol('onDrain') +const kFactory = Symbol('factory') +const kFinalizer = Symbol('finalizer') +const kOptions = Symbol('options') + +function defaultFactory (origin, opts) { + return opts && opts.connections === 1 + ? new Client(origin, opts) + : new Pool(origin, opts) +} + +class Agent extends DispatcherBase { + constructor ({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + super() + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (!Number.isInteger(maxRedirections) || maxRedirections < 0) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + if (connect && typeof connect !== 'function') { + connect = { ...connect } + } + + this[kInterceptors] = options.interceptors && options.interceptors.Agent && Array.isArray(options.interceptors.Agent) + ? options.interceptors.Agent + : [createRedirectInterceptor({ maxRedirections })] + + this[kOptions] = { ...util.deepClone(options), connect } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kMaxRedirections] = maxRedirections + this[kFactory] = factory + this[kClients] = new Map() + this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => { + const ref = this[kClients].get(key) + if (ref !== undefined && ref.deref() === undefined) { + this[kClients].delete(key) + } + }) + + const agent = this + + this[kOnDrain] = (origin, targets) => { + agent.emit('drain', origin, [agent, ...targets]) + } + + this[kOnConnect] = (origin, targets) => { + agent.emit('connect', origin, [agent, ...targets]) + } + + this[kOnDisconnect] = (origin, targets, err) => { + agent.emit('disconnect', origin, [agent, ...targets], err) + } + + this[kOnConnectionError] = (origin, targets, err) => { + agent.emit('connectionError', origin, [agent, ...targets], err) + } + } + + get [kRunning] () { + let ret = 0 + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore next: gc is undeterministic */ + if (client) { + ret += client[kRunning] + } + } + return ret + } + + [kDispatch] (opts, handler) { + let key + if (opts.origin && (typeof opts.origin === 'string' || opts.origin instanceof URL)) { + key = String(opts.origin) + } else { + throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.') + } + + const ref = this[kClients].get(key) + + let dispatcher = ref ? ref.deref() : null + if (!dispatcher) { + dispatcher = this[kFactory](opts.origin, this[kOptions]) + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) + + this[kClients].set(key, new WeakRef(dispatcher)) + this[kFinalizer].register(dispatcher, key) + } + + return dispatcher.dispatch(opts, handler) + } + + async [kClose] () { + const closePromises = [] + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore else: gc is undeterministic */ + if (client) { + closePromises.push(client.close()) + } + } + + await Promise.all(closePromises) + } + + async [kDestroy] (err) { + const destroyPromises = [] + for (const ref of this[kClients].values()) { + const client = ref.deref() + /* istanbul ignore else: gc is undeterministic */ + if (client) { + destroyPromises.push(client.destroy(err)) + } + } + + await Promise.all(destroyPromises) + } +} + +module.exports = Agent + + +/***/ }), + +/***/ 80158: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { addAbortListener } = __nccwpck_require__(3440) +const { RequestAbortedError } = __nccwpck_require__(68707) + +const kListener = Symbol('kListener') +const kSignal = Symbol('kSignal') + +function abort (self) { + if (self.abort) { + self.abort() + } else { + self.onError(new RequestAbortedError()) + } +} + +function addSignal (self, signal) { + self[kSignal] = null + self[kListener] = null + + if (!signal) { + return + } + + if (signal.aborted) { + abort(self) + return + } + + self[kSignal] = signal + self[kListener] = () => { + abort(self) + } + + addAbortListener(self[kSignal], self[kListener]) +} + +function removeSignal (self) { + if (!self[kSignal]) { + return + } + + if ('removeEventListener' in self[kSignal]) { + self[kSignal].removeEventListener('abort', self[kListener]) + } else { + self[kSignal].removeListener('abort', self[kListener]) + } + + self[kSignal] = null + self[kListener] = null +} + +module.exports = { + addSignal, + removeSignal +} + + +/***/ }), + +/***/ 34660: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { AsyncResource } = __nccwpck_require__(90290) +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { addSignal, removeSignal } = __nccwpck_require__(80158) + +class ConnectHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + const { signal, opaque, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + super('UNDICI_CONNECT') + + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.callback = callback + this.abort = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders () { + throw new SocketError('bad connect', null) + } + + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this + + removeSignal(this) + + this.callback = null + + let headers = rawHeaders + // Indicates is an HTTP2Session + if (headers != null) { + headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + } + + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + socket, + opaque, + context + }) + } + + onError (err) { + const { callback, opaque } = this + + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + } +} + +function connect (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + const connectHandler = new ConnectHandler(opts, callback) + this.dispatch({ ...opts, method: 'CONNECT' }, connectHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = connect + + +/***/ }), + +/***/ 76862: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + Readable, + Duplex, + PassThrough +} = __nccwpck_require__(2203) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { AsyncResource } = __nccwpck_require__(90290) +const { addSignal, removeSignal } = __nccwpck_require__(80158) +const assert = __nccwpck_require__(42613) + +const kResume = Symbol('resume') + +class PipelineRequest extends Readable { + constructor () { + super({ autoDestroy: true }) + + this[kResume] = null + } + + _read () { + const { [kResume]: resume } = this + + if (resume) { + this[kResume] = null + resume() + } + } + + _destroy (err, callback) { + this._read() + + callback(err) + } +} + +class PipelineResponse extends Readable { + constructor (resume) { + super({ autoDestroy: true }) + this[kResume] = resume + } + + _read () { + this[kResume]() + } + + _destroy (err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } + + callback(err) + } +} + +class PipelineHandler extends AsyncResource { + constructor (opts, handler) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof handler !== 'function') { + throw new InvalidArgumentError('invalid handler') + } + + const { signal, method, opaque, onInfo, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_PIPELINE') + + this.opaque = opaque || null + this.responseHeaders = responseHeaders || null + this.handler = handler + this.abort = null + this.context = null + this.onInfo = onInfo || null + + this.req = new PipelineRequest().on('error', util.nop) + + this.ret = new Duplex({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body } = this + + if (body && body.resume) { + body.resume() + } + }, + write: (chunk, encoding, callback) => { + const { req } = this + + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback() + } else { + req[kResume] = callback + } + }, + destroy: (err, callback) => { + const { body, req, res, ret, abort } = this + + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError() + } + + if (abort && err) { + abort() + } + + util.destroy(body, err) + util.destroy(req, err) + util.destroy(res, err) + + removeSignal(this) + + callback(err) + } + }).on('prefinish', () => { + const { req } = this + + // Node < 15 does not call _final in same tick. + req.push(null) + }) + + this.res = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + const { ret, res } = this + + assert(!res, 'pipeline cannot be retried') + + if (ret.destroyed) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume) { + const { opaque, handler, context } = this + + if (statusCode < 200) { + if (this.onInfo) { + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.onInfo({ statusCode, headers }) + } + return + } + + this.res = new PipelineResponse(resume) + + let body + try { + this.handler = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + body = this.runInAsyncScope(handler, null, { + statusCode, + headers, + opaque, + body: this.res, + context + }) + } catch (err) { + this.res.on('error', util.nop) + throw err + } + + if (!body || typeof body.on !== 'function') { + throw new InvalidReturnValueError('expected Readable') + } + + body + .on('data', (chunk) => { + const { ret, body } = this + + if (!ret.push(chunk) && body.pause) { + body.pause() + } + }) + .on('error', (err) => { + const { ret } = this + + util.destroy(ret, err) + }) + .on('end', () => { + const { ret } = this + + ret.push(null) + }) + .on('close', () => { + const { ret } = this + + if (!ret._readableState.ended) { + util.destroy(ret, new RequestAbortedError()) + } + }) + + this.body = body + } + + onData (chunk) { + const { res } = this + return res.push(chunk) + } + + onComplete (trailers) { + const { res } = this + res.push(null) + } + + onError (err) { + const { ret } = this + this.handler = null + util.destroy(ret, err) + } +} + +function pipeline (opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler) + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler) + return pipelineHandler.ret + } catch (err) { + return new PassThrough().destroy(err) + } +} + +module.exports = pipeline + + +/***/ }), + +/***/ 14043: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Readable = __nccwpck_require__(49927) +const { + InvalidArgumentError, + RequestAbortedError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { getResolveErrorBodyCallback } = __nccwpck_require__(87655) +const { AsyncResource } = __nccwpck_require__(90290) +const { addSignal, removeSignal } = __nccwpck_require__(80158) + +class RequestHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError, highWaterMark } = opts + + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (highWaterMark && (typeof highWaterMark !== 'number' || highWaterMark < 0)) { + throw new InvalidArgumentError('invalid highWaterMark') + } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_REQUEST') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.res = null + this.abort = null + this.body = body + this.trailers = {} + this.context = null + this.onInfo = onInfo || null + this.throwOnError = throwOnError + this.highWaterMark = highWaterMark + + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { callback, opaque, abort, context, responseHeaders, highWaterMark } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) + } + return + } + + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + const body = new Readable({ resume, abort, contentType, highWaterMark }) + + this.callback = null + this.res = body + if (callback !== null) { + if (this.throwOnError && statusCode >= 400) { + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body, contentType, statusCode, statusMessage, headers } + ) + } else { + this.runInAsyncScope(callback, null, null, { + statusCode, + headers, + trailers: this.trailers, + opaque, + body, + context + }) + } + } + } + + onData (chunk) { + const { res } = this + return res.push(chunk) + } + + onComplete (trailers) { + const { res } = this + + removeSignal(this) + + util.parseHeaders(trailers, this.trailers) + + res.push(null) + } + + onError (err) { + const { res, callback, body, opaque } = this + + removeSignal(this) + + if (callback) { + // TODO: Does this need queueMicrotask? + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + + if (res) { + this.res = null + // Ensure all queued handlers are invoked before destroying res. + queueMicrotask(() => { + util.destroy(res, err) + }) + } + + if (body) { + this.body = null + util.destroy(body, err) + } + } +} + +function request (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + this.dispatch(opts, new RequestHandler(opts, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = request +module.exports.RequestHandler = RequestHandler + + +/***/ }), + +/***/ 3560: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { finished, PassThrough } = __nccwpck_require__(2203) +const { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { getResolveErrorBodyCallback } = __nccwpck_require__(87655) +const { AsyncResource } = __nccwpck_require__(90290) +const { addSignal, removeSignal } = __nccwpck_require__(80158) + +class StreamHandler extends AsyncResource { + constructor (opts, factory, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + const { signal, method, opaque, body, onInfo, responseHeaders, throwOnError } = opts + + try { + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('invalid factory') + } + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + if (method === 'CONNECT') { + throw new InvalidArgumentError('invalid method') + } + + if (onInfo && typeof onInfo !== 'function') { + throw new InvalidArgumentError('invalid onInfo callback') + } + + super('UNDICI_STREAM') + } catch (err) { + if (util.isStream(body)) { + util.destroy(body.on('error', util.nop), err) + } + throw err + } + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.factory = factory + this.callback = callback + this.res = null + this.abort = null + this.context = null + this.trailers = null + this.body = body + this.onInfo = onInfo || null + this.throwOnError = throwOnError || false + + if (util.isStream(body)) { + body.on('error', (err) => { + this.onError(err) + }) + } + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = context + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const { factory, opaque, context, callback, responseHeaders } = this + + const headers = responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers }) + } + return + } + + this.factory = null + + let res + + if (this.throwOnError && statusCode >= 400) { + const parsedHeaders = responseHeaders === 'raw' ? util.parseHeaders(rawHeaders) : headers + const contentType = parsedHeaders['content-type'] + res = new PassThrough() + + this.callback = null + this.runInAsyncScope(getResolveErrorBodyCallback, null, + { callback, body: res, contentType, statusCode, statusMessage, headers } + ) + } else { + if (factory === null) { + return + } + + res = this.runInAsyncScope(factory, null, { + statusCode, + headers, + opaque, + context + }) + + if ( + !res || + typeof res.write !== 'function' || + typeof res.end !== 'function' || + typeof res.on !== 'function' + ) { + throw new InvalidReturnValueError('expected Writable') + } + + // TODO: Avoid finished. It registers an unnecessary amount of listeners. + finished(res, { readable: false }, (err) => { + const { callback, res, opaque, trailers, abort } = this + + this.res = null + if (err || !res.readable) { + util.destroy(res, err) + } + + this.callback = null + this.runInAsyncScope(callback, null, err || null, { opaque, trailers }) + + if (err) { + abort() + } + }) + } + + res.on('drain', resume) + + this.res = res + + const needDrain = res.writableNeedDrain !== undefined + ? res.writableNeedDrain + : res._writableState && res._writableState.needDrain + + return needDrain !== true + } + + onData (chunk) { + const { res } = this + + return res ? res.write(chunk) : true + } + + onComplete (trailers) { + const { res } = this + + removeSignal(this) + + if (!res) { + return + } + + this.trailers = util.parseHeaders(trailers) + + res.end() + } + + onError (err) { + const { res, callback, opaque, body } = this + + removeSignal(this) + + this.factory = null + + if (res) { + this.res = null + util.destroy(res, err) + } else if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + + if (body) { + this.body = null + util.destroy(body, err) + } + } +} + +function stream (opts, factory, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + this.dispatch(opts, new StreamHandler(opts, factory, callback)) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = stream + + +/***/ }), + +/***/ 61882: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { InvalidArgumentError, RequestAbortedError, SocketError } = __nccwpck_require__(68707) +const { AsyncResource } = __nccwpck_require__(90290) +const util = __nccwpck_require__(3440) +const { addSignal, removeSignal } = __nccwpck_require__(80158) +const assert = __nccwpck_require__(42613) + +class UpgradeHandler extends AsyncResource { + constructor (opts, callback) { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('invalid opts') + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + const { signal, opaque, responseHeaders } = opts + + if (signal && typeof signal.on !== 'function' && typeof signal.addEventListener !== 'function') { + throw new InvalidArgumentError('signal must be an EventEmitter or EventTarget') + } + + super('UNDICI_UPGRADE') + + this.responseHeaders = responseHeaders || null + this.opaque = opaque || null + this.callback = callback + this.abort = null + this.context = null + + addSignal(this, signal) + } + + onConnect (abort, context) { + if (!this.callback) { + throw new RequestAbortedError() + } + + this.abort = abort + this.context = null + } + + onHeaders () { + throw new SocketError('bad upgrade', null) + } + + onUpgrade (statusCode, rawHeaders, socket) { + const { callback, opaque, context } = this + + assert.strictEqual(statusCode, 101) + + removeSignal(this) + + this.callback = null + const headers = this.responseHeaders === 'raw' ? util.parseRawHeaders(rawHeaders) : util.parseHeaders(rawHeaders) + this.runInAsyncScope(callback, null, null, { + headers, + socket, + opaque, + context + }) + } + + onError (err) { + const { callback, opaque } = this + + removeSignal(this) + + if (callback) { + this.callback = null + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }) + }) + } + } +} + +function upgrade (opts, callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + try { + const upgradeHandler = new UpgradeHandler(opts, callback) + this.dispatch({ + ...opts, + method: opts.method || 'GET', + upgrade: opts.protocol || 'Websocket' + }, upgradeHandler) + } catch (err) { + if (typeof callback !== 'function') { + throw err + } + const opaque = opts && opts.opaque + queueMicrotask(() => callback(err, { opaque })) + } +} + +module.exports = upgrade + + +/***/ }), + +/***/ 56615: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +module.exports.request = __nccwpck_require__(14043) +module.exports.stream = __nccwpck_require__(3560) +module.exports.pipeline = __nccwpck_require__(76862) +module.exports.upgrade = __nccwpck_require__(61882) +module.exports.connect = __nccwpck_require__(34660) + + +/***/ }), + +/***/ 49927: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// Ported from https://github.com/nodejs/undici/pull/907 + + + +const assert = __nccwpck_require__(42613) +const { Readable } = __nccwpck_require__(2203) +const { RequestAbortedError, NotSupportedError, InvalidArgumentError } = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { ReadableStreamFrom, toUSVString } = __nccwpck_require__(3440) + +let Blob + +const kConsume = Symbol('kConsume') +const kReading = Symbol('kReading') +const kBody = Symbol('kBody') +const kAbort = Symbol('abort') +const kContentType = Symbol('kContentType') + +const noop = () => {} + +module.exports = class BodyReadable extends Readable { + constructor ({ + resume, + abort, + contentType = '', + highWaterMark = 64 * 1024 // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }) + + this._readableState.dataEmitted = false + + this[kAbort] = abort + this[kConsume] = null + this[kBody] = null + this[kContentType] = contentType + + // Is stream being consumed through Readable API? + // This is an optimization so that we avoid checking + // for 'data' and 'readable' listeners in the hot path + // inside push(). + this[kReading] = false + } + + destroy (err) { + if (this.destroyed) { + // Node < 16 + return this + } + + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError() + } + + if (err) { + this[kAbort]() + } + + return super.destroy(err) + } + + emit (ev, ...args) { + if (ev === 'data') { + // Node < 16.7 + this._readableState.dataEmitted = true + } else if (ev === 'error') { + // Node < 16 + this._readableState.errorEmitted = true + } + return super.emit(ev, ...args) + } + + on (ev, ...args) { + if (ev === 'data' || ev === 'readable') { + this[kReading] = true + } + return super.on(ev, ...args) + } + + addListener (ev, ...args) { + return this.on(ev, ...args) + } + + off (ev, ...args) { + const ret = super.off(ev, ...args) + if (ev === 'data' || ev === 'readable') { + this[kReading] = ( + this.listenerCount('data') > 0 || + this.listenerCount('readable') > 0 + ) + } + return ret + } + + removeListener (ev, ...args) { + return this.off(ev, ...args) + } + + push (chunk) { + if (this[kConsume] && chunk !== null && this.readableLength === 0) { + consumePush(this[kConsume], chunk) + return this[kReading] ? super.push(chunk) : true + } + return super.push(chunk) + } + + // https://fetch.spec.whatwg.org/#dom-body-text + async text () { + return consume(this, 'text') + } + + // https://fetch.spec.whatwg.org/#dom-body-json + async json () { + return consume(this, 'json') + } + + // https://fetch.spec.whatwg.org/#dom-body-blob + async blob () { + return consume(this, 'blob') + } + + // https://fetch.spec.whatwg.org/#dom-body-arraybuffer + async arrayBuffer () { + return consume(this, 'arrayBuffer') + } + + // https://fetch.spec.whatwg.org/#dom-body-formdata + async formData () { + // TODO: Implement. + throw new NotSupportedError() + } + + // https://fetch.spec.whatwg.org/#dom-body-bodyused + get bodyUsed () { + return util.isDisturbed(this) + } + + // https://fetch.spec.whatwg.org/#dom-body-body + get body () { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this) + if (this[kConsume]) { + // TODO: Is this the best way to force a lock? + this[kBody].getReader() // Ensure stream is locked. + assert(this[kBody].locked) + } + } + return this[kBody] + } + + dump (opts) { + let limit = opts && Number.isFinite(opts.limit) ? opts.limit : 262144 + const signal = opts && opts.signal + + if (signal) { + try { + if (typeof signal !== 'object' || !('aborted' in signal)) { + throw new InvalidArgumentError('signal must be an AbortSignal') + } + util.throwIfAborted(signal) + } catch (err) { + return Promise.reject(err) + } + } + + if (this.closed) { + return Promise.resolve(null) + } + + return new Promise((resolve, reject) => { + const signalListenerCleanup = signal + ? util.addAbortListener(signal, () => { + this.destroy() + }) + : noop + + this + .on('close', function () { + signalListenerCleanup() + if (signal && signal.aborted) { + reject(signal.reason || Object.assign(new Error('The operation was aborted'), { name: 'AbortError' })) + } else { + resolve(null) + } + }) + .on('error', noop) + .on('data', function (chunk) { + limit -= chunk.length + if (limit <= 0) { + this.destroy() + } + }) + .resume() + }) + } +} + +// https://streams.spec.whatwg.org/#readablestream-locked +function isLocked (self) { + // Consume is an implicit lock. + return (self[kBody] && self[kBody].locked === true) || self[kConsume] +} + +// https://fetch.spec.whatwg.org/#body-unusable +function isUnusable (self) { + return util.isDisturbed(self) || isLocked(self) +} + +async function consume (stream, type) { + if (isUnusable(stream)) { + throw new TypeError('unusable') + } + + assert(!stream[kConsume]) + + return new Promise((resolve, reject) => { + stream[kConsume] = { + type, + stream, + resolve, + reject, + length: 0, + body: [] + } + + stream + .on('error', function (err) { + consumeFinish(this[kConsume], err) + }) + .on('close', function () { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()) + } + }) + + process.nextTick(consumeStart, stream[kConsume]) + }) +} + +function consumeStart (consume) { + if (consume.body === null) { + return + } + + const { _readableState: state } = consume.stream + + for (const chunk of state.buffer) { + consumePush(consume, chunk) + } + + if (state.endEmitted) { + consumeEnd(this[kConsume]) + } else { + consume.stream.on('end', function () { + consumeEnd(this[kConsume]) + }) + } + + consume.stream.resume() + + while (consume.stream.read() != null) { + // Loop + } +} + +function consumeEnd (consume) { + const { type, body, resolve, stream, length } = consume + + try { + if (type === 'text') { + resolve(toUSVString(Buffer.concat(body))) + } else if (type === 'json') { + resolve(JSON.parse(Buffer.concat(body))) + } else if (type === 'arrayBuffer') { + const dst = new Uint8Array(length) + + let pos = 0 + for (const buf of body) { + dst.set(buf, pos) + pos += buf.byteLength + } + + resolve(dst.buffer) + } else if (type === 'blob') { + if (!Blob) { + Blob = (__nccwpck_require__(20181).Blob) + } + resolve(new Blob(body, { type: stream[kContentType] })) + } + + consumeFinish(consume) + } catch (err) { + stream.destroy(err) + } +} + +function consumePush (consume, chunk) { + consume.length += chunk.length + consume.body.push(chunk) +} + +function consumeFinish (consume, err) { + if (consume.body === null) { + return + } + + if (err) { + consume.reject(err) + } else { + consume.resolve() + } + + consume.type = null + consume.stream = null + consume.resolve = null + consume.reject = null + consume.length = 0 + consume.body = null +} + + +/***/ }), + +/***/ 87655: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(42613) +const { + ResponseStatusCodeError +} = __nccwpck_require__(68707) +const { toUSVString } = __nccwpck_require__(3440) + +async function getResolveErrorBodyCallback ({ callback, body, contentType, statusCode, statusMessage, headers }) { + assert(body) + + let chunks = [] + let limit = 0 + + for await (const chunk of body) { + chunks.push(chunk) + limit += chunk.length + if (limit > 128 * 1024) { + chunks = null + break + } + } + + if (statusCode === 204 || !contentType || !chunks) { + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) + return + } + + try { + if (contentType.startsWith('application/json')) { + const payload = JSON.parse(toUSVString(Buffer.concat(chunks))) + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) + return + } + + if (contentType.startsWith('text/')) { + const payload = toUSVString(Buffer.concat(chunks)) + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers, payload)) + return + } + } catch (err) { + // Process in a fallback if error + } + + process.nextTick(callback, new ResponseStatusCodeError(`Response status code ${statusCode}${statusMessage ? `: ${statusMessage}` : ''}`, statusCode, headers)) +} + +module.exports = { getResolveErrorBodyCallback } + + +/***/ }), + +/***/ 81093: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + BalancedPoolMissingUpstreamError, + InvalidArgumentError +} = __nccwpck_require__(68707) +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} = __nccwpck_require__(58640) +const Pool = __nccwpck_require__(35076) +const { kUrl, kInterceptors } = __nccwpck_require__(36443) +const { parseOrigin } = __nccwpck_require__(3440) +const kFactory = Symbol('factory') + +const kOptions = Symbol('options') +const kGreatestCommonDivisor = Symbol('kGreatestCommonDivisor') +const kCurrentWeight = Symbol('kCurrentWeight') +const kIndex = Symbol('kIndex') +const kWeight = Symbol('kWeight') +const kMaxWeightPerServer = Symbol('kMaxWeightPerServer') +const kErrorPenalty = Symbol('kErrorPenalty') + +function getGreatestCommonDivisor (a, b) { + if (b === 0) return a + return getGreatestCommonDivisor(b, a % b) +} + +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} + +class BalancedPool extends PoolBase { + constructor (upstreams = [], { factory = defaultFactory, ...opts } = {}) { + super() + + this[kOptions] = opts + this[kIndex] = -1 + this[kCurrentWeight] = 0 + + this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100 + this[kErrorPenalty] = this[kOptions].errorPenalty || 15 + + if (!Array.isArray(upstreams)) { + upstreams = [upstreams] + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + this[kInterceptors] = opts.interceptors && opts.interceptors.BalancedPool && Array.isArray(opts.interceptors.BalancedPool) + ? opts.interceptors.BalancedPool + : [] + this[kFactory] = factory + + for (const upstream of upstreams) { + this.addUpstream(upstream) + } + this._updateBalancedPoolStats() + } + + addUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin + + if (this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + ))) { + return this + } + const pool = this[kFactory](upstreamOrigin, Object.assign({}, this[kOptions])) + + this[kAddClient](pool) + pool.on('connect', () => { + pool[kWeight] = Math.min(this[kMaxWeightPerServer], pool[kWeight] + this[kErrorPenalty]) + }) + + pool.on('connectionError', () => { + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + }) + + pool.on('disconnect', (...args) => { + const err = args[2] + if (err && err.code === 'UND_ERR_SOCKET') { + // decrease the weight of the pool. + pool[kWeight] = Math.max(1, pool[kWeight] - this[kErrorPenalty]) + this._updateBalancedPoolStats() + } + }) + + for (const client of this[kClients]) { + client[kWeight] = this[kMaxWeightPerServer] + } + + this._updateBalancedPoolStats() + + return this + } + + _updateBalancedPoolStats () { + this[kGreatestCommonDivisor] = this[kClients].map(p => p[kWeight]).reduce(getGreatestCommonDivisor, 0) + } + + removeUpstream (upstream) { + const upstreamOrigin = parseOrigin(upstream).origin + + const pool = this[kClients].find((pool) => ( + pool[kUrl].origin === upstreamOrigin && + pool.closed !== true && + pool.destroyed !== true + )) + + if (pool) { + this[kRemoveClient](pool) + } + + return this + } + + get upstreams () { + return this[kClients] + .filter(dispatcher => dispatcher.closed !== true && dispatcher.destroyed !== true) + .map((p) => p[kUrl].origin) + } + + [kGetDispatcher] () { + // We validate that pools is greater than 0, + // otherwise we would have to wait until an upstream + // is added, which might never happen. + if (this[kClients].length === 0) { + throw new BalancedPoolMissingUpstreamError() + } + + const dispatcher = this[kClients].find(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + + if (!dispatcher) { + return + } + + const allClientsBusy = this[kClients].map(pool => pool[kNeedDrain]).reduce((a, b) => a && b, true) + + if (allClientsBusy) { + return + } + + let counter = 0 + + let maxWeightIndex = this[kClients].findIndex(pool => !pool[kNeedDrain]) + + while (counter++ < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length + const pool = this[kClients][this[kIndex]] + + // find pool index with the largest weight + if (pool[kWeight] > this[kClients][maxWeightIndex][kWeight] && !pool[kNeedDrain]) { + maxWeightIndex = this[kIndex] + } + + // decrease the current weight every `this[kClients].length`. + if (this[kIndex] === 0) { + // Set the current weight to the next lower weight. + this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor] + + if (this[kCurrentWeight] <= 0) { + this[kCurrentWeight] = this[kMaxWeightPerServer] + } + } + if (pool[kWeight] >= this[kCurrentWeight] && (!pool[kNeedDrain])) { + return pool + } + } + + this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight] + this[kIndex] = maxWeightIndex + return this[kClients][maxWeightIndex] + } +} + +module.exports = BalancedPool + + +/***/ }), + +/***/ 50479: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kConstruct } = __nccwpck_require__(80296) +const { urlEquals, fieldValues: getFieldValues } = __nccwpck_require__(23993) +const { kEnumerableProperty, isDisturbed } = __nccwpck_require__(3440) +const { kHeadersList } = __nccwpck_require__(36443) +const { webidl } = __nccwpck_require__(74222) +const { Response, cloneResponse } = __nccwpck_require__(48676) +const { Request } = __nccwpck_require__(25194) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(89710) +const { fetching } = __nccwpck_require__(12315) +const { urlIsHttpHttpsScheme, createDeferredPromise, readAllBytes } = __nccwpck_require__(15523) +const assert = __nccwpck_require__(42613) +const { getGlobalDispatcher } = __nccwpck_require__(32581) + +/** + * @see https://w3c.github.io/ServiceWorker/#dfn-cache-batch-operation + * @typedef {Object} CacheBatchOperation + * @property {'delete' | 'put'} type + * @property {any} request + * @property {any} response + * @property {import('../../types/cache').CacheQueryOptions} options + */ + +/** + * @see https://w3c.github.io/ServiceWorker/#dfn-request-response-list + * @typedef {[any, any][]} requestResponseList + */ + +class Cache { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list + * @type {requestResponseList} + */ + #relevantRequestResponseList + + constructor () { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor() + } + + this.#relevantRequestResponseList = arguments[1] + } + + async match (request, options = {}) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.match' }) + + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + const p = await this.matchAll(request, options) + + if (p.length === 0) { + return + } + + return p[0] + } + + async matchAll (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) + + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + // 1. + let r = null + + // 2. + if (request !== undefined) { + if (request instanceof Request) { + // 2.1.1 + r = request[kState] + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { + // 2.2.1 + r = new Request(request)[kState] + } + } + + // 5. + // 5.1 + const responses = [] + + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + responses.push(requestResponse[1]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) + + // 5.3.2 + for (const requestResponse of requestResponses) { + responses.push(requestResponse[1]) + } + } + + // 5.4 + // We don't implement CORs so we don't need to loop over the responses, yay! + + // 5.5.1 + const responseList = [] + + // 5.5.2 + for (const response of responses) { + // 5.5.2.1 + const responseObject = new Response(response.body?.source ?? null) + const body = responseObject[kState].body + responseObject[kState] = response + responseObject[kState].body = body + responseObject[kHeaders][kHeadersList] = response.headersList + responseObject[kHeaders][kGuard] = 'immutable' + + responseList.push(responseObject) + } + + // 6. + return Object.freeze(responseList) + } + + async add (request) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.add' }) + + request = webidl.converters.RequestInfo(request) + + // 1. + const requests = [request] + + // 2. + const responseArrayPromise = this.addAll(requests) + + // 3. + return await responseArrayPromise + } + + async addAll (requests) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.addAll' }) + + requests = webidl.converters['sequence'](requests) + + // 1. + const responsePromises = [] + + // 2. + const requestList = [] + + // 3. + for (const request of requests) { + if (typeof request === 'string') { + continue + } + + // 3.1 + const r = request[kState] + + // 3.2 + if (!urlIsHttpHttpsScheme(r.url) || r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Expected http/s scheme when method is not GET.' + }) + } + } + + // 4. + /** @type {ReturnType[]} */ + const fetchControllers = [] + + // 5. + for (const request of requests) { + // 5.1 + const r = new Request(request)[kState] + + // 5.2 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Expected http/s scheme.' + }) + } + + // 5.4 + r.initiator = 'fetch' + r.destination = 'subresource' + + // 5.5 + requestList.push(r) + + // 5.6 + const responsePromise = createDeferredPromise() + + // 5.7 + fetchControllers.push(fetching({ + request: r, + dispatcher: getGlobalDispatcher(), + processResponse (response) { + // 1. + if (response.type === 'error' || response.status === 206 || response.status < 200 || response.status > 299) { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'Received an invalid status code or the request failed.' + })) + } else if (response.headersList.contains('vary')) { // 2. + // 2.1 + const fieldValues = getFieldValues(response.headersList.get('vary')) + + // 2.2 + for (const fieldValue of fieldValues) { + // 2.2.1 + if (fieldValue === '*') { + responsePromise.reject(webidl.errors.exception({ + header: 'Cache.addAll', + message: 'invalid vary field value' + })) + + for (const controller of fetchControllers) { + controller.abort() + } + + return + } + } + } + }, + processResponseEndOfBody (response) { + // 1. + if (response.aborted) { + responsePromise.reject(new DOMException('aborted', 'AbortError')) + return + } + + // 2. + responsePromise.resolve(response) + } + })) + + // 5.8 + responsePromises.push(responsePromise.promise) + } + + // 6. + const p = Promise.all(responsePromises) + + // 7. + const responses = await p + + // 7.1 + const operations = [] + + // 7.2 + let index = 0 + + // 7.3 + for (const response of responses) { + // 7.3.1 + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 7.3.2 + request: requestList[index], // 7.3.3 + response // 7.3.4 + } + + operations.push(operation) // 7.3.5 + + index++ // 7.3.6 + } + + // 7.5 + const cacheJobPromise = createDeferredPromise() + + // 7.6.1 + let errorData = null + + // 7.6.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + // 7.6.3 + queueMicrotask(() => { + // 7.6.3.1 + if (errorData === null) { + cacheJobPromise.resolve(undefined) + } else { + // 7.6.3.2 + cacheJobPromise.reject(errorData) + } + }) + + // 7.7 + return cacheJobPromise.promise + } + + async put (request, response) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 2, { header: 'Cache.put' }) + + request = webidl.converters.RequestInfo(request) + response = webidl.converters.Response(response) + + // 1. + let innerRequest = null + + // 2. + if (request instanceof Request) { + innerRequest = request[kState] + } else { // 3. + innerRequest = new Request(request)[kState] + } + + // 4. + if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Expected an http/s scheme when method is not GET' + }) + } + + // 5. + const innerResponse = response[kState] + + // 6. + if (innerResponse.status === 206) { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Got 206 status' + }) + } + + // 7. + if (innerResponse.headersList.contains('vary')) { + // 7.1. + const fieldValues = getFieldValues(innerResponse.headersList.get('vary')) + + // 7.2. + for (const fieldValue of fieldValues) { + // 7.2.1 + if (fieldValue === '*') { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Got * vary field value' + }) + } + } + } + + // 8. + if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { + throw webidl.errors.exception({ + header: 'Cache.put', + message: 'Response body is locked or disturbed' + }) + } + + // 9. + const clonedResponse = cloneResponse(innerResponse) + + // 10. + const bodyReadPromise = createDeferredPromise() + + // 11. + if (innerResponse.body != null) { + // 11.1 + const stream = innerResponse.body.stream + + // 11.2 + const reader = stream.getReader() + + // 11.3 + readAllBytes(reader).then(bodyReadPromise.resolve, bodyReadPromise.reject) + } else { + bodyReadPromise.resolve(undefined) + } + + // 12. + /** @type {CacheBatchOperation[]} */ + const operations = [] + + // 13. + /** @type {CacheBatchOperation} */ + const operation = { + type: 'put', // 14. + request: innerRequest, // 15. + response: clonedResponse // 16. + } + + // 17. + operations.push(operation) + + // 19. + const bytes = await bodyReadPromise.promise + + if (clonedResponse.body != null) { + clonedResponse.body.source = bytes + } + + // 19.1 + const cacheJobPromise = createDeferredPromise() + + // 19.2.1 + let errorData = null + + // 19.2.2 + try { + this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + // 19.2.3 + queueMicrotask(() => { + // 19.2.3.1 + if (errorData === null) { + cacheJobPromise.resolve() + } else { // 19.2.3.2 + cacheJobPromise.reject(errorData) + } + }) + + return cacheJobPromise.promise + } + + async delete (request, options = {}) { + webidl.brandCheck(this, Cache) + webidl.argumentLengthCheck(arguments, 1, { header: 'Cache.delete' }) + + request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + /** + * @type {Request} + */ + let r = null + + if (request instanceof Request) { + r = request[kState] + + if (r.method !== 'GET' && !options.ignoreMethod) { + return false + } + } else { + assert(typeof request === 'string') + + r = new Request(request)[kState] + } + + /** @type {CacheBatchOperation[]} */ + const operations = [] + + /** @type {CacheBatchOperation} */ + const operation = { + type: 'delete', + request: r, + options + } + + operations.push(operation) + + const cacheJobPromise = createDeferredPromise() + + let errorData = null + let requestResponses + + try { + requestResponses = this.#batchCacheOperations(operations) + } catch (e) { + errorData = e + } + + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(!!requestResponses?.length) + } else { + cacheJobPromise.reject(errorData) + } + }) + + return cacheJobPromise.promise + } + + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys + * @param {any} request + * @param {import('../../types/cache').CacheQueryOptions} options + * @returns {readonly Request[]} + */ + async keys (request = undefined, options = {}) { + webidl.brandCheck(this, Cache) + + if (request !== undefined) request = webidl.converters.RequestInfo(request) + options = webidl.converters.CacheQueryOptions(options) + + // 1. + let r = null + + // 2. + if (request !== undefined) { + // 2.1 + if (request instanceof Request) { + // 2.1.1 + r = request[kState] + + // 2.1.2 + if (r.method !== 'GET' && !options.ignoreMethod) { + return [] + } + } else if (typeof request === 'string') { // 2.2 + r = new Request(request)[kState] + } + } + + // 4. + const promise = createDeferredPromise() + + // 5. + // 5.1 + const requests = [] + + // 5.2 + if (request === undefined) { + // 5.2.1 + for (const requestResponse of this.#relevantRequestResponseList) { + // 5.2.1.1 + requests.push(requestResponse[0]) + } + } else { // 5.3 + // 5.3.1 + const requestResponses = this.#queryCache(r, options) + + // 5.3.2 + for (const requestResponse of requestResponses) { + // 5.3.2.1 + requests.push(requestResponse[0]) + } + } + + // 5.4 + queueMicrotask(() => { + // 5.4.1 + const requestList = [] + + // 5.4.2 + for (const request of requests) { + const requestObject = new Request('https://a') + requestObject[kState] = request + requestObject[kHeaders][kHeadersList] = request.headersList + requestObject[kHeaders][kGuard] = 'immutable' + requestObject[kRealm] = request.client + + // 5.4.2.1 + requestList.push(requestObject) + } + + // 5.4.3 + promise.resolve(Object.freeze(requestList)) + }) + + return promise.promise + } + + /** + * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm + * @param {CacheBatchOperation[]} operations + * @returns {requestResponseList} + */ + #batchCacheOperations (operations) { + // 1. + const cache = this.#relevantRequestResponseList + + // 2. + const backupCache = [...cache] + + // 3. + const addedItems = [] + + // 4.1 + const resultList = [] + + try { + // 4.2 + for (const operation of operations) { + // 4.2.1 + if (operation.type !== 'delete' && operation.type !== 'put') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'operation type does not match "delete" or "put"' + }) + } + + // 4.2.2 + if (operation.type === 'delete' && operation.response != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'delete operation should not have an associated response' + }) + } + + // 4.2.3 + if (this.#queryCache(operation.request, operation.options, addedItems).length) { + throw new DOMException('???', 'InvalidStateError') + } + + // 4.2.4 + let requestResponses + + // 4.2.5 + if (operation.type === 'delete') { + // 4.2.5.1 + requestResponses = this.#queryCache(operation.request, operation.options) + + // TODO: the spec is wrong, this is needed to pass WPTs + if (requestResponses.length === 0) { + return [] + } + + // 4.2.5.2 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) + + // 4.2.5.2.1 + cache.splice(idx, 1) + } + } else if (operation.type === 'put') { // 4.2.6 + // 4.2.6.1 + if (operation.response == null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'put operation should have an associated response' + }) + } + + // 4.2.6.2 + const r = operation.request + + // 4.2.6.3 + if (!urlIsHttpHttpsScheme(r.url)) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'expected http or https scheme' + }) + } + + // 4.2.6.4 + if (r.method !== 'GET') { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'not get method' + }) + } + + // 4.2.6.5 + if (operation.options != null) { + throw webidl.errors.exception({ + header: 'Cache.#batchCacheOperations', + message: 'options must not be defined' + }) + } + + // 4.2.6.6 + requestResponses = this.#queryCache(operation.request) + + // 4.2.6.7 + for (const requestResponse of requestResponses) { + const idx = cache.indexOf(requestResponse) + assert(idx !== -1) + + // 4.2.6.7.1 + cache.splice(idx, 1) + } + + // 4.2.6.8 + cache.push([operation.request, operation.response]) + + // 4.2.6.10 + addedItems.push([operation.request, operation.response]) + } + + // 4.2.7 + resultList.push([operation.request, operation.response]) + } + + // 4.3 + return resultList + } catch (e) { // 5. + // 5.1 + this.#relevantRequestResponseList.length = 0 + + // 5.2 + this.#relevantRequestResponseList = backupCache + + // 5.3 + throw e + } + } + + /** + * @see https://w3c.github.io/ServiceWorker/#query-cache + * @param {any} requestQuery + * @param {import('../../types/cache').CacheQueryOptions} options + * @param {requestResponseList} targetStorage + * @returns {requestResponseList} + */ + #queryCache (requestQuery, options, targetStorage) { + /** @type {requestResponseList} */ + const resultList = [] + + const storage = targetStorage ?? this.#relevantRequestResponseList + + for (const requestResponse of storage) { + const [cachedRequest, cachedResponse] = requestResponse + if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse, options)) { + resultList.push(requestResponse) + } + } + + return resultList + } + + /** + * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm + * @param {any} requestQuery + * @param {any} request + * @param {any | null} response + * @param {import('../../types/cache').CacheQueryOptions | undefined} options + * @returns {boolean} + */ + #requestMatchesCachedItem (requestQuery, request, response = null, options) { + // if (options?.ignoreMethod === false && request.method === 'GET') { + // return false + // } + + const queryURL = new URL(requestQuery.url) + + const cachedURL = new URL(request.url) + + if (options?.ignoreSearch) { + cachedURL.search = '' + + queryURL.search = '' + } + + if (!urlEquals(queryURL, cachedURL, true)) { + return false + } + + if ( + response == null || + options?.ignoreVary || + !response.headersList.contains('vary') + ) { + return true + } + + const fieldValues = getFieldValues(response.headersList.get('vary')) + + for (const fieldValue of fieldValues) { + if (fieldValue === '*') { + return false + } + + const requestValue = request.headersList.get(fieldValue) + const queryValue = requestQuery.headersList.get(fieldValue) + + // If one has the header and the other doesn't, or one has + // a different value than the other, return false + if (requestValue !== queryValue) { + return false + } + } + + return true + } +} + +Object.defineProperties(Cache.prototype, { + [Symbol.toStringTag]: { + value: 'Cache', + configurable: true + }, + match: kEnumerableProperty, + matchAll: kEnumerableProperty, + add: kEnumerableProperty, + addAll: kEnumerableProperty, + put: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) + +const cacheQueryOptionConverters = [ + { + key: 'ignoreSearch', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'ignoreMethod', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'ignoreVary', + converter: webidl.converters.boolean, + defaultValue: false + } +] + +webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters) + +webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ + ...cacheQueryOptionConverters, + { + key: 'cacheName', + converter: webidl.converters.DOMString + } +]) + +webidl.converters.Response = webidl.interfaceConverter(Response) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.RequestInfo +) + +module.exports = { + Cache +} + + +/***/ }), + +/***/ 44738: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kConstruct } = __nccwpck_require__(80296) +const { Cache } = __nccwpck_require__(50479) +const { webidl } = __nccwpck_require__(74222) +const { kEnumerableProperty } = __nccwpck_require__(3440) + +class CacheStorage { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map + * @type {Map} + */ + async has (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.has' }) + + cacheName = webidl.converters.DOMString(cacheName) + + // 2.1.1 + // 2.2 + return this.#caches.has(cacheName) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open + * @param {string} cacheName + * @returns {Promise} + */ + async open (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.open' }) + + cacheName = webidl.converters.DOMString(cacheName) + + // 2.1 + if (this.#caches.has(cacheName)) { + // await caches.open('v1') !== await caches.open('v1') + + // 2.1.1 + const cache = this.#caches.get(cacheName) + + // 2.1.1.1 + return new Cache(kConstruct, cache) + } + + // 2.2 + const cache = [] + + // 2.3 + this.#caches.set(cacheName, cache) + + // 2.4 + return new Cache(kConstruct, cache) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete + * @param {string} cacheName + * @returns {Promise} + */ + async delete (cacheName) { + webidl.brandCheck(this, CacheStorage) + webidl.argumentLengthCheck(arguments, 1, { header: 'CacheStorage.delete' }) + + cacheName = webidl.converters.DOMString(cacheName) + + return this.#caches.delete(cacheName) + } + + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys + * @returns {string[]} + */ + async keys () { + webidl.brandCheck(this, CacheStorage) + + // 2.1 + const keys = this.#caches.keys() + + // 2.2 + return [...keys] + } +} + +Object.defineProperties(CacheStorage.prototype, { + [Symbol.toStringTag]: { + value: 'CacheStorage', + configurable: true + }, + match: kEnumerableProperty, + has: kEnumerableProperty, + open: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty +}) + +module.exports = { + CacheStorage +} + + +/***/ }), + +/***/ 80296: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +module.exports = { + kConstruct: (__nccwpck_require__(36443).kConstruct) +} + + +/***/ }), + +/***/ 23993: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const assert = __nccwpck_require__(42613) +const { URLSerializer } = __nccwpck_require__(94322) +const { isValidHeaderName } = __nccwpck_require__(15523) + +/** + * @see https://url.spec.whatwg.org/#concept-url-equals + * @param {URL} A + * @param {URL} B + * @param {boolean | undefined} excludeFragment + * @returns {boolean} + */ +function urlEquals (A, B, excludeFragment = false) { + const serializedA = URLSerializer(A, excludeFragment) + + const serializedB = URLSerializer(B, excludeFragment) + + return serializedA === serializedB +} + +/** + * @see https://github.com/chromium/chromium/blob/694d20d134cb553d8d89e5500b9148012b1ba299/content/browser/cache_storage/cache_storage_cache.cc#L260-L262 + * @param {string} header + */ +function fieldValues (header) { + assert(header !== null) + + const values = [] + + for (let value of header.split(',')) { + value = value.trim() + + if (!value.length) { + continue + } else if (!isValidHeaderName(value)) { + continue + } + + values.push(value) + } + + return values +} + +module.exports = { + urlEquals, + fieldValues +} + + +/***/ }), + +/***/ 86197: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// @ts-check + + + +/* global WebAssembly */ + +const assert = __nccwpck_require__(42613) +const net = __nccwpck_require__(69278) +const http = __nccwpck_require__(58611) +const { pipeline } = __nccwpck_require__(2203) +const util = __nccwpck_require__(3440) +const timers = __nccwpck_require__(28804) +const Request = __nccwpck_require__(44655) +const DispatcherBase = __nccwpck_require__(50001) +const { + RequestContentLengthMismatchError, + ResponseContentLengthMismatchError, + InvalidArgumentError, + RequestAbortedError, + HeadersTimeoutError, + HeadersOverflowError, + SocketError, + InformationalError, + BodyTimeoutError, + HTTPParserError, + ResponseExceededMaxSizeError, + ClientDestroyedError +} = __nccwpck_require__(68707) +const buildConnector = __nccwpck_require__(59136) +const { + kUrl, + kReset, + kServerName, + kClient, + kBusy, + kParser, + kConnect, + kBlocking, + kResuming, + kRunning, + kPending, + kSize, + kWriting, + kQueue, + kConnected, + kConnecting, + kNeedDrain, + kNoRef, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kSocket, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kConnector, + kMaxRedirections, + kMaxRequests, + kCounter, + kClose, + kDestroy, + kDispatch, + kInterceptors, + kLocalAddress, + kMaxResponseSize, + kHTTPConnVersion, + // HTTP2 + kHost, + kHTTP2Session, + kHTTP2SessionState, + kHTTP2BuildRequest, + kHTTP2CopyHeaders, + kHTTP1BuildRequest +} = __nccwpck_require__(36443) + +/** @type {import('http2')} */ +let http2 +try { + http2 = __nccwpck_require__(85675) +} catch { + // @ts-ignore + http2 = { constants: {} } +} + +const { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS + } +} = http2 + +// Experimental +let h2ExperimentalWarned = false + +const FastBuffer = Buffer[Symbol.species] + +const kClosedResolve = Symbol('kClosedResolve') + +const channels = {} + +try { + const diagnosticsChannel = __nccwpck_require__(31637) + channels.sendHeaders = diagnosticsChannel.channel('undici:client:sendHeaders') + channels.beforeConnect = diagnosticsChannel.channel('undici:client:beforeConnect') + channels.connectError = diagnosticsChannel.channel('undici:client:connectError') + channels.connected = diagnosticsChannel.channel('undici:client:connected') +} catch { + channels.sendHeaders = { hasSubscribers: false } + channels.beforeConnect = { hasSubscribers: false } + channels.connectError = { hasSubscribers: false } + channels.connected = { hasSubscribers: false } +} + +/** + * @type {import('../types/client').default} + */ +class Client extends DispatcherBase { + /** + * + * @param {string|URL} url + * @param {import('../types/client').Client.Options} options + */ + constructor (url, { + interceptors, + maxHeaderSize, + headersTimeout, + socketTimeout, + requestTimeout, + connectTimeout, + bodyTimeout, + idleTimeout, + keepAlive, + keepAliveTimeout, + maxKeepAliveTimeout, + keepAliveMaxTimeout, + keepAliveTimeoutThreshold, + socketPath, + pipelining, + tls, + strictContentLength, + maxCachedSessions, + maxRedirections, + connect, + maxRequestsPerClient, + localAddress, + maxResponseSize, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + // h2 + allowH2, + maxConcurrentStreams + } = {}) { + super() + + if (keepAlive !== undefined) { + throw new InvalidArgumentError('unsupported keepAlive, use pipelining=0 instead') + } + + if (socketTimeout !== undefined) { + throw new InvalidArgumentError('unsupported socketTimeout, use headersTimeout & bodyTimeout instead') + } + + if (requestTimeout !== undefined) { + throw new InvalidArgumentError('unsupported requestTimeout, use headersTimeout & bodyTimeout instead') + } + + if (idleTimeout !== undefined) { + throw new InvalidArgumentError('unsupported idleTimeout, use keepAliveTimeout instead') + } + + if (maxKeepAliveTimeout !== undefined) { + throw new InvalidArgumentError('unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead') + } + + if (maxHeaderSize != null && !Number.isFinite(maxHeaderSize)) { + throw new InvalidArgumentError('invalid maxHeaderSize') + } + + if (socketPath != null && typeof socketPath !== 'string') { + throw new InvalidArgumentError('invalid socketPath') + } + + if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { + throw new InvalidArgumentError('invalid connectTimeout') + } + + if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveTimeout') + } + + if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { + throw new InvalidArgumentError('invalid keepAliveMaxTimeout') + } + + if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { + throw new InvalidArgumentError('invalid keepAliveTimeoutThreshold') + } + + if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('headersTimeout must be a positive integer or zero') + } + + if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('bodyTimeout must be a positive integer or zero') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { + throw new InvalidArgumentError('maxRequestsPerClient must be a positive number') + } + + if (localAddress != null && (typeof localAddress !== 'string' || net.isIP(localAddress) === 0)) { + throw new InvalidArgumentError('localAddress must be valid string IP address') + } + + if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { + throw new InvalidArgumentError('maxResponseSize must be a positive number') + } + + if ( + autoSelectFamilyAttemptTimeout != null && + (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1) + ) { + throw new InvalidArgumentError('autoSelectFamilyAttemptTimeout must be a positive number') + } + + // h2 + if (allowH2 != null && typeof allowH2 !== 'boolean') { + throw new InvalidArgumentError('allowH2 must be a valid boolean value') + } + + if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== 'number' || maxConcurrentStreams < 1)) { + throw new InvalidArgumentError('maxConcurrentStreams must be a possitive integer, greater than 0') + } + + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } + + this[kInterceptors] = interceptors && interceptors.Client && Array.isArray(interceptors.Client) + ? interceptors.Client + : [createRedirectInterceptor({ maxRedirections })] + this[kUrl] = util.parseOrigin(url) + this[kConnector] = connect + this[kSocket] = null + this[kPipelining] = pipelining != null ? pipelining : 1 + this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize + this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout + this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 600e3 : keepAliveMaxTimeout + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 1e3 : keepAliveTimeoutThreshold + this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout] + this[kServerName] = null + this[kLocalAddress] = localAddress != null ? localAddress : null + this[kResuming] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kNeedDrain] = 0 // 0, idle, 1, scheduled, 2 resuming + this[kHostHeader] = `host: ${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}\r\n` + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 300e3 + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 300e3 + this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength + this[kMaxRedirections] = maxRedirections + this[kMaxRequests] = maxRequestsPerClient + this[kClosedResolve] = null + this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1 + this[kHTTPConnVersion] = 'h1' + + // HTTP/2 + this[kHTTP2Session] = null + this[kHTTP2SessionState] = !allowH2 + ? null + : { + // streams: null, // Fixed queue of streams - For future support of `push` + openStreams: 0, // Keep track of them to decide wether or not unref the session + maxConcurrentStreams: maxConcurrentStreams != null ? maxConcurrentStreams : 100 // Max peerConcurrentStreams for a Node h2 server + } + this[kHost] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ''}` + + // kQueue is built up of 3 sections separated by + // the kRunningIdx and kPendingIdx indices. + // | complete | running | pending | + // ^ kRunningIdx ^ kPendingIdx ^ kQueue.length + // kRunningIdx points to the first running element. + // kPendingIdx points to the first pending element. + // This implements a fast queue with an amortized + // time of O(1). + + this[kQueue] = [] + this[kRunningIdx] = 0 + this[kPendingIdx] = 0 + } + + get pipelining () { + return this[kPipelining] + } + + set pipelining (value) { + this[kPipelining] = value + resume(this, true) + } + + get [kPending] () { + return this[kQueue].length - this[kPendingIdx] + } + + get [kRunning] () { + return this[kPendingIdx] - this[kRunningIdx] + } + + get [kSize] () { + return this[kQueue].length - this[kRunningIdx] + } + + get [kConnected] () { + return !!this[kSocket] && !this[kConnecting] && !this[kSocket].destroyed + } + + get [kBusy] () { + const socket = this[kSocket] + return ( + (socket && (socket[kReset] || socket[kWriting] || socket[kBlocking])) || + (this[kSize] >= (this[kPipelining] || 1)) || + this[kPending] > 0 + ) + } + + /* istanbul ignore: only used for test */ + [kConnect] (cb) { + connect(this) + this.once('connect', cb) + } + + [kDispatch] (opts, handler) { + const origin = opts.origin || this[kUrl].origin + + const request = this[kHTTPConnVersion] === 'h2' + ? Request[kHTTP2BuildRequest](origin, opts, handler) + : Request[kHTTP1BuildRequest](origin, opts, handler) + + this[kQueue].push(request) + if (this[kResuming]) { + // Do nothing. + } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { + // Wait a tick in case stream/iterator is ended in the same tick. + this[kResuming] = 1 + process.nextTick(resume, this) + } else { + resume(this, true) + } + + if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { + this[kNeedDrain] = 2 + } + + return this[kNeedDrain] < 2 + } + + async [kClose] () { + // TODO: for H2 we need to gracefully flush the remaining enqueued + // request and close each stream. + return new Promise((resolve) => { + if (!this[kSize]) { + resolve(null) + } else { + this[kClosedResolve] = resolve + } + }) + } + + async [kDestroy] (err) { + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(this, request, err) + } + + const callback = () => { + if (this[kClosedResolve]) { + // TODO (fix): Should we error here with ClientDestroyedError? + this[kClosedResolve]() + this[kClosedResolve] = null + } + resolve() + } + + if (this[kHTTP2Session] != null) { + util.destroy(this[kHTTP2Session], err) + this[kHTTP2Session] = null + this[kHTTP2SessionState] = null + } + + if (!this[kSocket]) { + queueMicrotask(callback) + } else { + util.destroy(this[kSocket].on('close', callback), err) + } + + resume(this) + }) + } +} + +function onHttp2SessionError (err) { + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') + + this[kSocket][kError] = err + + onError(this[kClient], err) +} + +function onHttp2FrameError (type, code, id) { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + + if (id === 0) { + this[kSocket][kError] = err + onError(this[kClient], err) + } +} + +function onHttp2SessionEnd () { + util.destroy(this, new SocketError('other side closed')) + util.destroy(this[kSocket], new SocketError('other side closed')) +} + +function onHTTP2GoAway (code) { + const client = this[kClient] + const err = new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${code}`) + client[kSocket] = null + client[kHTTP2Session] = null + + if (client.destroyed) { + assert(this[kPending] === 0) + + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(this, request, err) + } + } else if (client[kRunning] > 0) { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + + errorRequest(client, request, err) + } + + client[kPendingIdx] = client[kRunningIdx] + + assert(client[kRunning] === 0) + + client.emit('disconnect', + client[kUrl], + [client], + err + ) + + resume(client) +} + +const constants = __nccwpck_require__(52824) +const createRedirectInterceptor = __nccwpck_require__(64415) +const EMPTY_BUF = Buffer.alloc(0) + +async function lazyllhttp () { + const llhttpWasmData = process.env.JEST_WORKER_ID ? __nccwpck_require__(63870) : undefined + + let mod + try { + mod = await WebAssembly.compile(Buffer.from(__nccwpck_require__(53434), 'base64')) + } catch (e) { + /* istanbul ignore next */ + + // We could check if the error was caused by the simd option not + // being enabled, but the occurring of this other error + // * https://github.com/emscripten-core/emscripten/issues/11495 + // got me to remove that check to avoid breaking Node 12. + mod = await WebAssembly.compile(Buffer.from(llhttpWasmData || __nccwpck_require__(63870), 'base64')) + } + + return await WebAssembly.instantiate(mod, { + env: { + /* eslint-disable camelcase */ + + wasm_on_url: (p, at, len) => { + /* istanbul ignore next */ + return 0 + }, + wasm_on_status: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onStatus(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_begin: (p) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onMessageBegin() || 0 + }, + wasm_on_header_field: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderField(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_header_value: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onHeaderValue(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_headers_complete: (p, statusCode, upgrade, shouldKeepAlive) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onHeadersComplete(statusCode, Boolean(upgrade), Boolean(shouldKeepAlive)) || 0 + }, + wasm_on_body: (p, at, len) => { + assert.strictEqual(currentParser.ptr, p) + const start = at - currentBufferPtr + currentBufferRef.byteOffset + return currentParser.onBody(new FastBuffer(currentBufferRef.buffer, start, len)) || 0 + }, + wasm_on_message_complete: (p) => { + assert.strictEqual(currentParser.ptr, p) + return currentParser.onMessageComplete() || 0 + } + + /* eslint-enable camelcase */ + } + }) +} + +let llhttpInstance = null +let llhttpPromise = lazyllhttp() +llhttpPromise.catch() + +let currentParser = null +let currentBufferRef = null +let currentBufferSize = 0 +let currentBufferPtr = null + +const TIMEOUT_HEADERS = 1 +const TIMEOUT_BODY = 2 +const TIMEOUT_IDLE = 3 + +class Parser { + constructor (client, socket, { exports }) { + assert(Number.isFinite(client[kMaxHeadersSize]) && client[kMaxHeadersSize] > 0) + + this.llhttp = exports + this.ptr = this.llhttp.llhttp_alloc(constants.TYPE.RESPONSE) + this.client = client + this.socket = socket + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + this.statusCode = null + this.statusText = '' + this.upgrade = false + this.headers = [] + this.headersSize = 0 + this.headersMaxSize = client[kMaxHeadersSize] + this.shouldKeepAlive = false + this.paused = false + this.resume = this.resume.bind(this) + + this.bytesRead = 0 + + this.keepAlive = '' + this.contentLength = '' + this.connection = '' + this.maxResponseSize = client[kMaxResponseSize] + } + + setTimeout (value, type) { + this.timeoutType = type + if (value !== this.timeoutValue) { + timers.clearTimeout(this.timeout) + if (value) { + this.timeout = timers.setTimeout(onParserTimeout, value, this) + // istanbul ignore else: only for jest + if (this.timeout.unref) { + this.timeout.unref() + } + } else { + this.timeout = null + } + this.timeoutValue = value + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + } + + resume () { + if (this.socket.destroyed || !this.paused) { + return + } + + assert(this.ptr != null) + assert(currentParser == null) + + this.llhttp.llhttp_resume(this.ptr) + + assert(this.timeoutType === TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + this.paused = false + this.execute(this.socket.read() || EMPTY_BUF) // Flush parser. + this.readMore() + } + + readMore () { + while (!this.paused && this.ptr) { + const chunk = this.socket.read() + if (chunk === null) { + break + } + this.execute(chunk) + } + } + + execute (data) { + assert(this.ptr != null) + assert(currentParser == null) + assert(!this.paused) + + const { socket, llhttp } = this + + if (data.length > currentBufferSize) { + if (currentBufferPtr) { + llhttp.free(currentBufferPtr) + } + currentBufferSize = Math.ceil(data.length / 4096) * 4096 + currentBufferPtr = llhttp.malloc(currentBufferSize) + } + + new Uint8Array(llhttp.memory.buffer, currentBufferPtr, currentBufferSize).set(data) + + // Call `execute` on the wasm parser. + // We pass the `llhttp_parser` pointer address, the pointer address of buffer view data, + // and finally the length of bytes to parse. + // The return value is an error code or `constants.ERROR.OK`. + try { + let ret + + try { + currentBufferRef = data + currentParser = this + ret = llhttp.llhttp_execute(this.ptr, currentBufferPtr, data.length) + /* eslint-disable-next-line no-useless-catch */ + } catch (err) { + /* istanbul ignore next: difficult to make a test case for */ + throw err + } finally { + currentParser = null + currentBufferRef = null + } + + const offset = llhttp.llhttp_get_error_pos(this.ptr) - currentBufferPtr + + if (ret === constants.ERROR.PAUSED_UPGRADE) { + this.onUpgrade(data.slice(offset)) + } else if (ret === constants.ERROR.PAUSED) { + this.paused = true + socket.unshift(data.slice(offset)) + } else if (ret !== constants.ERROR.OK) { + const ptr = llhttp.llhttp_get_error_reason(this.ptr) + let message = '' + /* istanbul ignore else: difficult to make a test case for */ + if (ptr) { + const len = new Uint8Array(llhttp.memory.buffer, ptr).indexOf(0) + message = + 'Response does not match the HTTP/1.1 protocol (' + + Buffer.from(llhttp.memory.buffer, ptr, len).toString() + + ')' + } + throw new HTTPParserError(message, constants.ERROR[ret], data.slice(offset)) + } + } catch (err) { + util.destroy(socket, err) + } + } + + destroy () { + assert(this.ptr != null) + assert(currentParser == null) + + this.llhttp.llhttp_free(this.ptr) + this.ptr = null + + timers.clearTimeout(this.timeout) + this.timeout = null + this.timeoutValue = null + this.timeoutType = null + + this.paused = false + } + + onStatus (buf) { + this.statusText = buf.toString() + } + + onMessageBegin () { + const { socket, client } = this + + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + if (!request) { + return -1 + } + } + + onHeaderField (buf) { + const len = this.headers.length + + if ((len & 1) === 0) { + this.headers.push(buf) + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + } + + this.trackHeader(buf.length) + } + + onHeaderValue (buf) { + let len = this.headers.length + + if ((len & 1) === 1) { + this.headers.push(buf) + len += 1 + } else { + this.headers[len - 1] = Buffer.concat([this.headers[len - 1], buf]) + } + + const key = this.headers[len - 2] + if (key.length === 10 && key.toString().toLowerCase() === 'keep-alive') { + this.keepAlive += buf.toString() + } else if (key.length === 10 && key.toString().toLowerCase() === 'connection') { + this.connection += buf.toString() + } else if (key.length === 14 && key.toString().toLowerCase() === 'content-length') { + this.contentLength += buf.toString() + } + + this.trackHeader(buf.length) + } + + trackHeader (len) { + this.headersSize += len + if (this.headersSize >= this.headersMaxSize) { + util.destroy(this.socket, new HeadersOverflowError()) + } + } + + onUpgrade (head) { + const { upgrade, client, socket, headers, statusCode } = this + + assert(upgrade) + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert(!socket.destroyed) + assert(socket === client[kSocket]) + assert(!this.paused) + assert(request.upgrade || request.method === 'CONNECT') + + this.statusCode = null + this.statusText = '' + this.shouldKeepAlive = null + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + socket.unshift(head) + + socket[kParser].destroy() + socket[kParser] = null + + socket[kClient] = null + socket[kError] = null + socket + .removeListener('error', onSocketError) + .removeListener('readable', onSocketReadable) + .removeListener('end', onSocketEnd) + .removeListener('close', onSocketClose) + + client[kSocket] = null + client[kQueue][client[kRunningIdx]++] = null + client.emit('disconnect', client[kUrl], [client], new InformationalError('upgrade')) + + try { + request.onUpgrade(statusCode, headers, socket) + } catch (err) { + util.destroy(socket, err) + } + + resume(client) + } + + onHeadersComplete (statusCode, upgrade, shouldKeepAlive) { + const { client, socket, headers, statusText } = this + + /* istanbul ignore next: difficult to make a test case for */ + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + + /* istanbul ignore next: difficult to make a test case for */ + if (!request) { + return -1 + } + + assert(!this.upgrade) + assert(this.statusCode < 200) + + if (statusCode === 100) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))) + return -1 + } + + /* this can only happen if server is misbehaving */ + if (upgrade && !request.upgrade) { + util.destroy(socket, new SocketError('bad upgrade', util.getSocketInfo(socket))) + return -1 + } + + assert.strictEqual(this.timeoutType, TIMEOUT_HEADERS) + + this.statusCode = statusCode + this.shouldKeepAlive = ( + shouldKeepAlive || + // Override llhttp value which does not allow keepAlive for HEAD. + (request.method === 'HEAD' && !socket[kReset] && this.connection.toLowerCase() === 'keep-alive') + ) + + if (this.statusCode >= 200) { + const bodyTimeout = request.bodyTimeout != null + ? request.bodyTimeout + : client[kBodyTimeout] + this.setTimeout(bodyTimeout, TIMEOUT_BODY) + } else if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + if (request.method === 'CONNECT') { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } + + if (upgrade) { + assert(client[kRunning] === 1) + this.upgrade = true + return 2 + } + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + if (this.shouldKeepAlive && client[kPipelining]) { + const keepAliveTimeout = this.keepAlive ? util.parseKeepAliveTimeout(this.keepAlive) : null + + if (keepAliveTimeout != null) { + const timeout = Math.min( + keepAliveTimeout - client[kKeepAliveTimeoutThreshold], + client[kKeepAliveMaxTimeout] + ) + if (timeout <= 0) { + socket[kReset] = true + } else { + client[kKeepAliveTimeoutValue] = timeout + } + } else { + client[kKeepAliveTimeoutValue] = client[kKeepAliveDefaultTimeout] + } + } else { + // Stop more requests from being dispatched. + socket[kReset] = true + } + + const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false + + if (request.aborted) { + return -1 + } + + if (request.method === 'HEAD') { + return 1 + } + + if (statusCode < 200) { + return 1 + } + + if (socket[kBlocking]) { + socket[kBlocking] = false + resume(client) + } + + return pause ? constants.ERROR.PAUSED : 0 + } + + onBody (buf) { + const { client, socket, statusCode, maxResponseSize } = this + + if (socket.destroyed) { + return -1 + } + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert.strictEqual(this.timeoutType, TIMEOUT_BODY) + if (this.timeout) { + // istanbul ignore else: only for jest + if (this.timeout.refresh) { + this.timeout.refresh() + } + } + + assert(statusCode >= 200) + + if (maxResponseSize > -1 && this.bytesRead + buf.length > maxResponseSize) { + util.destroy(socket, new ResponseExceededMaxSizeError()) + return -1 + } + + this.bytesRead += buf.length + + if (request.onData(buf) === false) { + return constants.ERROR.PAUSED + } + } + + onMessageComplete () { + const { client, socket, statusCode, upgrade, headers, contentLength, bytesRead, shouldKeepAlive } = this + + if (socket.destroyed && (!statusCode || shouldKeepAlive)) { + return -1 + } + + if (upgrade) { + return + } + + const request = client[kQueue][client[kRunningIdx]] + assert(request) + + assert(statusCode >= 100) + + this.statusCode = null + this.statusText = '' + this.bytesRead = 0 + this.contentLength = '' + this.keepAlive = '' + this.connection = '' + + assert(this.headers.length % 2 === 0) + this.headers = [] + this.headersSize = 0 + + if (statusCode < 200) { + return + } + + /* istanbul ignore next: should be handled by llhttp? */ + if (request.method !== 'HEAD' && contentLength && bytesRead !== parseInt(contentLength, 10)) { + util.destroy(socket, new ResponseContentLengthMismatchError()) + return -1 + } + + request.onComplete(headers) + + client[kQueue][client[kRunningIdx]++] = null + + if (socket[kWriting]) { + assert.strictEqual(client[kRunning], 0) + // Response completed before request. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (!shouldKeepAlive) { + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (socket[kReset] && client[kRunning] === 0) { + // Destroy socket once all requests have completed. + // The request at the tail of the pipeline is the one + // that requested reset and no further requests should + // have been queued since then. + util.destroy(socket, new InformationalError('reset')) + return constants.ERROR.PAUSED + } else if (client[kPipelining] === 1) { + // We must wait a full event loop cycle to reuse this socket to make sure + // that non-spec compliant servers are not closing the connection even if they + // said they won't. + setImmediate(resume, client) + } else { + resume(client) + } + } +} + +function onParserTimeout (parser) { + const { socket, timeoutType, client } = parser + + /* istanbul ignore else */ + if (timeoutType === TIMEOUT_HEADERS) { + if (!socket[kWriting] || socket.writableNeedDrain || client[kRunning] > 1) { + assert(!parser.paused, 'cannot be paused while waiting for headers') + util.destroy(socket, new HeadersTimeoutError()) + } + } else if (timeoutType === TIMEOUT_BODY) { + if (!parser.paused) { + util.destroy(socket, new BodyTimeoutError()) + } + } else if (timeoutType === TIMEOUT_IDLE) { + assert(client[kRunning] === 0 && client[kKeepAliveTimeoutValue]) + util.destroy(socket, new InformationalError('socket idle timeout')) + } +} + +function onSocketReadable () { + const { [kParser]: parser } = this + if (parser) { + parser.readMore() + } +} + +function onSocketError (err) { + const { [kClient]: client, [kParser]: parser } = this + + assert(err.code !== 'ERR_TLS_CERT_ALTNAME_INVALID') + + if (client[kHTTPConnVersion] !== 'h2') { + // On Mac OS, we get an ECONNRESET even if there is a full body to be forwarded + // to the user. + if (err.code === 'ECONNRESET' && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so for as a valid response. + parser.onMessageComplete() + return + } + } + + this[kError] = err + + onError(this[kClient], err) +} + +function onError (client, err) { + if ( + client[kRunning] === 0 && + err.code !== 'UND_ERR_INFO' && + err.code !== 'UND_ERR_SOCKET' + ) { + // Error is not caused by running request and not a recoverable + // socket error. + + assert(client[kPendingIdx] === client[kRunningIdx]) + + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(client, request, err) + } + assert(client[kSize] === 0) + } +} + +function onSocketEnd () { + const { [kParser]: parser, [kClient]: client } = this + + if (client[kHTTPConnVersion] !== 'h2') { + if (parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + return + } + } + + util.destroy(this, new SocketError('other side closed', util.getSocketInfo(this))) +} + +function onSocketClose () { + const { [kClient]: client, [kParser]: parser } = this + + if (client[kHTTPConnVersion] === 'h1' && parser) { + if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { + // We treat all incoming data so far as a valid response. + parser.onMessageComplete() + } + + this[kParser].destroy() + this[kParser] = null + } + + const err = this[kError] || new SocketError('closed', util.getSocketInfo(this)) + + client[kSocket] = null + + if (client.destroyed) { + assert(client[kPending] === 0) + + // Fail entire queue. + const requests = client[kQueue].splice(client[kRunningIdx]) + for (let i = 0; i < requests.length; i++) { + const request = requests[i] + errorRequest(client, request, err) + } + } else if (client[kRunning] > 0 && err.code !== 'UND_ERR_INFO') { + // Fail head of pipeline. + const request = client[kQueue][client[kRunningIdx]] + client[kQueue][client[kRunningIdx]++] = null + + errorRequest(client, request, err) + } + + client[kPendingIdx] = client[kRunningIdx] + + assert(client[kRunning] === 0) + + client.emit('disconnect', client[kUrl], [client], err) + + resume(client) +} + +async function connect (client) { + assert(!client[kConnecting]) + assert(!client[kSocket]) + + let { host, hostname, protocol, port } = client[kUrl] + + // Resolve ipv6 + if (hostname[0] === '[') { + const idx = hostname.indexOf(']') + + assert(idx !== -1) + const ip = hostname.substring(1, idx) + + assert(net.isIP(ip)) + hostname = ip + } + + client[kConnecting] = true + + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }) + } + + try { + const socket = await new Promise((resolve, reject) => { + client[kConnector]({ + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket) => { + if (err) { + reject(err) + } else { + resolve(socket) + } + }) + }) + + if (client.destroyed) { + util.destroy(socket.on('error', () => {}), new ClientDestroyedError()) + return + } + + client[kConnecting] = false + + assert(socket) + + const isH2 = socket.alpnProtocol === 'h2' + if (isH2) { + if (!h2ExperimentalWarned) { + h2ExperimentalWarned = true + process.emitWarning('H2 support is experimental, expect them to change at any time.', { + code: 'UNDICI-H2' + }) + } + + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kHTTP2SessionState].maxConcurrentStreams + }) + + client[kHTTPConnVersion] = 'h2' + session[kClient] = client + session[kSocket] = socket + session.on('error', onHttp2SessionError) + session.on('frameError', onHttp2FrameError) + session.on('end', onHttp2SessionEnd) + session.on('goaway', onHTTP2GoAway) + session.on('close', onSocketClose) + session.unref() + + client[kHTTP2Session] = session + socket[kHTTP2Session] = session + } else { + if (!llhttpInstance) { + llhttpInstance = await llhttpPromise + llhttpPromise = null + } + + socket[kNoRef] = false + socket[kWriting] = false + socket[kReset] = false + socket[kBlocking] = false + socket[kParser] = new Parser(client, socket, llhttpInstance) + } + + socket[kCounter] = 0 + socket[kMaxRequests] = client[kMaxRequests] + socket[kClient] = client + socket[kError] = null + + socket + .on('error', onSocketError) + .on('readable', onSocketReadable) + .on('end', onSocketEnd) + .on('close', onSocketClose) + + client[kSocket] = socket + + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }) + } + client.emit('connect', client[kUrl], [client]) + } catch (err) { + if (client.destroyed) { + return + } + + client[kConnecting] = false + + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }) + } + + if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') { + assert(client[kRunning] === 0) + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue][client[kPendingIdx]++] + errorRequest(client, request, err) + } + } else { + onError(client, err) + } + + client.emit('connectionError', client[kUrl], [client], err) + } + + resume(client) +} + +function emitDrain (client) { + client[kNeedDrain] = 0 + client.emit('drain', client[kUrl], [client]) +} + +function resume (client, sync) { + if (client[kResuming] === 2) { + return + } + + client[kResuming] = 2 + + _resume(client, sync) + client[kResuming] = 0 + + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]) + client[kPendingIdx] -= client[kRunningIdx] + client[kRunningIdx] = 0 + } +} + +function _resume (client, sync) { + while (true) { + if (client.destroyed) { + assert(client[kPending] === 0) + return + } + + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve]() + client[kClosedResolve] = null + return + } + + const socket = client[kSocket] + + if (socket && !socket.destroyed && socket.alpnProtocol !== 'h2') { + if (client[kSize] === 0) { + if (!socket[kNoRef] && socket.unref) { + socket.unref() + socket[kNoRef] = true + } + } else if (socket[kNoRef] && socket.ref) { + socket.ref() + socket[kNoRef] = false + } + + if (client[kSize] === 0) { + if (socket[kParser].timeoutType !== TIMEOUT_IDLE) { + socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_IDLE) + } + } else if (client[kRunning] > 0 && socket[kParser].statusCode < 200) { + if (socket[kParser].timeoutType !== TIMEOUT_HEADERS) { + const request = client[kQueue][client[kRunningIdx]] + const headersTimeout = request.headersTimeout != null + ? request.headersTimeout + : client[kHeadersTimeout] + socket[kParser].setTimeout(headersTimeout, TIMEOUT_HEADERS) + } + } + } + + if (client[kBusy]) { + client[kNeedDrain] = 2 + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1 + process.nextTick(emitDrain, client) + } else { + emitDrain(client) + } + continue + } + + if (client[kPending] === 0) { + return + } + + if (client[kRunning] >= (client[kPipelining] || 1)) { + return + } + + const request = client[kQueue][client[kPendingIdx]] + + if (client[kUrl].protocol === 'https:' && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { + return + } + + client[kServerName] = request.servername + + if (socket && socket.servername !== request.servername) { + util.destroy(socket, new InformationalError('servername changed')) + return + } + } + + if (client[kConnecting]) { + return + } + + if (!socket && !client[kHTTP2Session]) { + connect(client) + return + } + + if (socket.destroyed || socket[kWriting] || socket[kReset] || socket[kBlocking]) { + return + } + + if (client[kRunning] > 0 && !request.idempotent) { + // Non-idempotent request cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return + } + + if (client[kRunning] > 0 && (request.upgrade || request.method === 'CONNECT')) { + // Don't dispatch an upgrade until all preceding requests have completed. + // A misbehaving server might upgrade the connection before all pipelined + // request has completed. + return + } + + if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 && + (util.isStream(request.body) || util.isAsyncIterable(request.body))) { + // Request with stream or iterator body can error while other requests + // are inflight and indirectly error those as well. + // Ensure this doesn't happen by waiting for inflight + // to complete before dispatching. + + // Request with stream or iterator body cannot be retried. + // Ensure that no other requests are inflight and + // could cause failure. + return + } + + if (!request.aborted && write(client, request)) { + client[kPendingIdx]++ + } else { + client[kQueue].splice(client[kPendingIdx], 1) + } + } +} + +// https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2 +function shouldSendContentLength (method) { + return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' +} + +function write (client, request) { + if (client[kHTTPConnVersion] === 'h2') { + writeH2(client, client[kHTTP2Session], request) + return + } + + const { body, method, path, host, upgrade, headers, blocking, reset } = request + + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 + + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. + + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) + + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } + + const bodyLength = util.bodyLength(body) + + let contentLength = bodyLength + + if (contentLength === null) { + contentLength = request.contentLength + } + + if (contentLength === 0 && !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + + contentLength = null + } + + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()) + return false + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + const socket = client[kSocket] + + try { + request.onConnect((err) => { + if (request.aborted || request.completed) { + return + } + + errorRequest(client, request, err || new RequestAbortedError()) + + util.destroy(socket, new InformationalError('aborted')) + }) + } catch (err) { + errorRequest(client, request, err) + } + + if (request.aborted) { + return false + } + + if (method === 'HEAD') { + // https://github.com/mcollina/undici/issues/258 + // Close after a HEAD request to interop with misbehaving servers + // that may send a body in the response. + + socket[kReset] = true + } + + if (upgrade || method === 'CONNECT') { + // On CONNECT or upgrade, block pipeline from dispatching further + // requests on this connection. + + socket[kReset] = true + } + + if (reset != null) { + socket[kReset] = reset + } + + if (client[kMaxRequests] && socket[kCounter]++ >= client[kMaxRequests]) { + socket[kReset] = true + } + + if (blocking) { + socket[kBlocking] = true + } + + let header = `${method} ${path} HTTP/1.1\r\n` + + if (typeof host === 'string') { + header += `host: ${host}\r\n` + } else { + header += client[kHostHeader] + } + + if (upgrade) { + header += `connection: upgrade\r\nupgrade: ${upgrade}\r\n` + } else if (client[kPipelining] && !socket[kReset]) { + header += 'connection: keep-alive\r\n' + } else { + header += 'connection: close\r\n' + } + + if (headers) { + header += headers + } + + if (channels.sendHeaders.hasSubscribers) { + channels.sendHeaders.publish({ request, headers: header, socket }) + } + + /* istanbul ignore else: assertion */ + if (!body || bodyLength === 0) { + if (contentLength === 0) { + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + assert(contentLength === null, 'no body must not have content length') + socket.write(`${header}\r\n`, 'latin1') + } + request.onRequestSent() + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(body) + socket.uncork() + request.onBodySent(body) + request.onRequestSent() + if (!expectsPayload) { + socket[kReset] = true + } + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable({ body: body.stream(), client, request, socket, contentLength, header, expectsPayload }) + } else { + writeBlob({ body, client, request, socket, contentLength, header, expectsPayload }) + } + } else if (util.isStream(body)) { + writeStream({ body, client, request, socket, contentLength, header, expectsPayload }) + } else if (util.isIterable(body)) { + writeIterable({ body, client, request, socket, contentLength, header, expectsPayload }) + } else { + assert(false) + } + + return true +} + +function writeH2 (client, session, request) { + const { body, method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request + + let headers + if (typeof reqHeaders === 'string') headers = Request[kHTTP2CopyHeaders](reqHeaders.trim()) + else headers = reqHeaders + + if (upgrade) { + errorRequest(client, request, new Error('Upgrade not supported for H2')) + return false + } + + try { + // TODO(HTTP/2): Should we call onConnect immediately or on stream ready event? + request.onConnect((err) => { + if (request.aborted || request.completed) { + return + } + + errorRequest(client, request, err || new RequestAbortedError()) + }) + } catch (err) { + errorRequest(client, request, err) + } + + if (request.aborted) { + return false + } + + /** @type {import('node:http2').ClientHttp2Stream} */ + let stream + const h2State = client[kHTTP2SessionState] + + headers[HTTP2_HEADER_AUTHORITY] = host || client[kHost] + headers[HTTP2_HEADER_METHOD] = method + + if (method === 'CONNECT') { + session.ref() + // we are already connected, streams are pending, first request + // will create a new stream. We trigger a request to create the stream and wait until + // `ready` event is triggered + // We disabled endStream to allow the user to write to the stream + stream = session.request(headers, { endStream: false, signal }) + + if (stream.id && !stream.pending) { + request.onUpgrade(null, null, stream) + ++h2State.openStreams + } else { + stream.once('ready', () => { + request.onUpgrade(null, null, stream) + ++h2State.openStreams + }) + } + + stream.once('close', () => { + h2State.openStreams -= 1 + // TODO(HTTP/2): unref only if current streams count is 0 + if (h2State.openStreams === 0) session.unref() + }) + + return true + } + + // https://tools.ietf.org/html/rfc7540#section-8.3 + // :path and :scheme headers must be omited when sending CONNECT + + headers[HTTP2_HEADER_PATH] = path + headers[HTTP2_HEADER_SCHEME] = 'https' + + // https://tools.ietf.org/html/rfc7231#section-4.3.1 + // https://tools.ietf.org/html/rfc7231#section-4.3.2 + // https://tools.ietf.org/html/rfc7231#section-4.3.5 + + // Sending a payload body on a request that does not + // expect it can cause undefined behavior on some + // servers and corrupt connection state. Do not + // re-use the connection for further requests. + + const expectsPayload = ( + method === 'PUT' || + method === 'POST' || + method === 'PATCH' + ) + + if (body && typeof body.read === 'function') { + // Try to read EOF in order to get length. + body.read(0) + } + + let contentLength = util.bodyLength(body) + + if (contentLength == null) { + contentLength = request.contentLength + } + + if (contentLength === 0 || !expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD NOT send a Content-Length header field when + // the request message does not contain a payload body and the method + // semantics do not anticipate such a body. + + contentLength = null + } + + // https://github.com/nodejs/undici/issues/2046 + // A user agent may send a Content-Length header with 0 value, this should be allowed. + if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) { + if (client[kStrictContentLength]) { + errorRequest(client, request, new RequestContentLengthMismatchError()) + return false + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + if (contentLength != null) { + assert(body, 'no body must not have content length') + headers[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength}` + } + + session.ref() + + const shouldEndStream = method === 'GET' || method === 'HEAD' + if (expectContinue) { + headers[HTTP2_HEADER_EXPECT] = '100-continue' + stream = session.request(headers, { endStream: shouldEndStream, signal }) + + stream.once('continue', writeBodyH2) + } else { + stream = session.request(headers, { + endStream: shouldEndStream, + signal + }) + writeBodyH2() + } + + // Increment counter as we have new several streams open + ++h2State.openStreams + + stream.once('response', headers => { + const { [HTTP2_HEADER_STATUS]: statusCode, ...realHeaders } = headers + + if (request.onHeaders(Number(statusCode), realHeaders, stream.resume.bind(stream), '') === false) { + stream.pause() + } + }) + + stream.once('end', () => { + request.onComplete([]) + }) + + stream.on('data', (chunk) => { + if (request.onData(chunk) === false) { + stream.pause() + } + }) + + stream.once('close', () => { + h2State.openStreams -= 1 + // TODO(HTTP/2): unref only if current streams count is 0 + if (h2State.openStreams === 0) { + session.unref() + } + }) + + stream.once('error', function (err) { + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1 + util.destroy(stream, err) + } + }) + + stream.once('frameError', (type, code) => { + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type}, code ${code}`) + errorRequest(client, request, err) + + if (client[kHTTP2Session] && !client[kHTTP2Session].destroyed && !this.closed && !this.destroyed) { + h2State.streams -= 1 + util.destroy(stream, err) + } + }) + + // stream.on('aborted', () => { + // // TODO(HTTP/2): Support aborted + // }) + + // stream.on('timeout', () => { + // // TODO(HTTP/2): Support timeout + // }) + + // stream.on('push', headers => { + // // TODO(HTTP/2): Suppor push + // }) + + // stream.on('trailers', headers => { + // // TODO(HTTP/2): Support trailers + // }) + + return true + + function writeBodyH2 () { + /* istanbul ignore else: assertion */ + if (!body) { + request.onRequestSent() + } else if (util.isBuffer(body)) { + assert(contentLength === body.byteLength, 'buffer body must have content length') + stream.cork() + stream.write(body) + stream.uncork() + stream.end() + request.onBodySent(body) + request.onRequestSent() + } else if (util.isBlobLike(body)) { + if (typeof body.stream === 'function') { + writeIterable({ + client, + request, + contentLength, + h2stream: stream, + expectsPayload, + body: body.stream(), + socket: client[kSocket], + header: '' + }) + } else { + writeBlob({ + body, + client, + request, + contentLength, + expectsPayload, + h2stream: stream, + header: '', + socket: client[kSocket] + }) + } + } else if (util.isStream(body)) { + writeStream({ + body, + client, + request, + contentLength, + expectsPayload, + socket: client[kSocket], + h2stream: stream, + header: '' + }) + } else if (util.isIterable(body)) { + writeIterable({ + body, + client, + request, + contentLength, + expectsPayload, + header: '', + h2stream: stream, + socket: client[kSocket] + }) + } else { + assert(false) + } + } +} + +function writeStream ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, 'stream body cannot be pipelined') + + if (client[kHTTPConnVersion] === 'h2') { + // For HTTP/2, is enough to pipe the stream + const pipe = pipeline( + body, + h2stream, + (err) => { + if (err) { + util.destroy(body, err) + util.destroy(h2stream, err) + } else { + request.onRequestSent() + } + } + ) + + pipe.on('data', onPipeData) + pipe.once('end', () => { + pipe.removeListener('data', onPipeData) + util.destroy(pipe) + }) + + function onPipeData (chunk) { + request.onBodySent(chunk) + } + + return + } + + let finished = false + + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) + + const onData = function (chunk) { + if (finished) { + return + } + + try { + if (!writer.write(chunk) && this.pause) { + this.pause() + } + } catch (err) { + util.destroy(this, err) + } + } + const onDrain = function () { + if (finished) { + return + } + + if (body.resume) { + body.resume() + } + } + const onAbort = function () { + if (finished) { + return + } + const err = new RequestAbortedError() + queueMicrotask(() => onFinished(err)) + } + const onFinished = function (err) { + if (finished) { + return + } + + finished = true + + assert(socket.destroyed || (socket[kWriting] && client[kRunning] <= 1)) + + socket + .off('drain', onDrain) + .off('error', onFinished) + + body + .removeListener('data', onData) + .removeListener('end', onFinished) + .removeListener('error', onFinished) + .removeListener('close', onAbort) + + if (!err) { + try { + writer.end() + } catch (er) { + err = er + } + } + + writer.destroy(err) + + if (err && (err.code !== 'UND_ERR_INFO' || err.message !== 'reset')) { + util.destroy(body, err) + } else { + util.destroy(body) + } + } + + body + .on('data', onData) + .on('end', onFinished) + .on('error', onFinished) + .on('close', onAbort) + + if (body.resume) { + body.resume() + } + + socket + .on('drain', onDrain) + .on('error', onFinished) +} + +async function writeBlob ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength === body.size, 'blob body must have content length') + + const isH2 = client[kHTTPConnVersion] === 'h2' + try { + if (contentLength != null && contentLength !== body.size) { + throw new RequestContentLengthMismatchError() + } + + const buffer = Buffer.from(await body.arrayBuffer()) + + if (isH2) { + h2stream.cork() + h2stream.write(buffer) + h2stream.uncork() + } else { + socket.cork() + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + socket.write(buffer) + socket.uncork() + } + + request.onBodySent(buffer) + request.onRequestSent() + + if (!expectsPayload) { + socket[kReset] = true + } + + resume(client) + } catch (err) { + util.destroy(isH2 ? h2stream : socket, err) + } +} + +async function writeIterable ({ h2stream, body, client, request, socket, contentLength, header, expectsPayload }) { + assert(contentLength !== 0 || client[kRunning] === 0, 'iterator body cannot be pipelined') + + let callback = null + function onDrain () { + if (callback) { + const cb = callback + callback = null + cb() + } + } + + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null) + + if (socket[kError]) { + reject(socket[kError]) + } else { + callback = resolve + } + }) + + if (client[kHTTPConnVersion] === 'h2') { + h2stream + .on('close', onDrain) + .on('drain', onDrain) + + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } + + const res = h2stream.write(chunk) + request.onBodySent(chunk) + if (!res) { + await waitForDrain() + } + } + } catch (err) { + h2stream.destroy(err) + } finally { + request.onRequestSent() + h2stream.end() + h2stream + .off('close', onDrain) + .off('drain', onDrain) + } + + return + } + + socket + .on('close', onDrain) + .on('drain', onDrain) + + const writer = new AsyncWriter({ socket, request, contentLength, client, expectsPayload, header }) + try { + // It's up to the user to somehow abort the async iterable. + for await (const chunk of body) { + if (socket[kError]) { + throw socket[kError] + } + + if (!writer.write(chunk)) { + await waitForDrain() + } + } + + writer.end() + } catch (err) { + writer.destroy(err) + } finally { + socket + .off('close', onDrain) + .off('drain', onDrain) + } +} + +class AsyncWriter { + constructor ({ socket, request, contentLength, client, expectsPayload, header }) { + this.socket = socket + this.request = request + this.contentLength = contentLength + this.client = client + this.bytesWritten = 0 + this.expectsPayload = expectsPayload + this.header = header + + socket[kWriting] = true + } + + write (chunk) { + const { socket, request, contentLength, client, bytesWritten, expectsPayload, header } = this + + if (socket[kError]) { + throw socket[kError] + } + + if (socket.destroyed) { + return false + } + + const len = Buffer.byteLength(chunk) + if (!len) { + return true + } + + // We should defer writing chunks. + if (contentLength !== null && bytesWritten + len > contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } + + process.emitWarning(new RequestContentLengthMismatchError()) + } + + socket.cork() + + if (bytesWritten === 0) { + if (!expectsPayload) { + socket[kReset] = true + } + + if (contentLength === null) { + socket.write(`${header}transfer-encoding: chunked\r\n`, 'latin1') + } else { + socket.write(`${header}content-length: ${contentLength}\r\n\r\n`, 'latin1') + } + } + + if (contentLength === null) { + socket.write(`\r\n${len.toString(16)}\r\n`, 'latin1') + } + + this.bytesWritten += len + + const ret = socket.write(chunk) + + socket.uncork() + + request.onBodySent(chunk) + + if (!ret) { + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } + } + + return ret + } + + end () { + const { socket, contentLength, client, bytesWritten, expectsPayload, header, request } = this + request.onRequestSent() + + socket[kWriting] = false + + if (socket[kError]) { + throw socket[kError] + } + + if (socket.destroyed) { + return + } + + if (bytesWritten === 0) { + if (expectsPayload) { + // https://tools.ietf.org/html/rfc7230#section-3.3.2 + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. + + socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1') + } else { + socket.write(`${header}\r\n`, 'latin1') + } + } else if (contentLength === null) { + socket.write('\r\n0\r\n\r\n', 'latin1') + } + + if (contentLength !== null && bytesWritten !== contentLength) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError() + } else { + process.emitWarning(new RequestContentLengthMismatchError()) + } + } + + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + // istanbul ignore else: only for jest + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh() + } + } + + resume(client) + } + + destroy (err) { + const { socket, client } = this + + socket[kWriting] = false + + if (err) { + assert(client[kRunning] <= 1, 'pipeline should only contain this request') + util.destroy(socket, err) + } + } +} + +function errorRequest (client, request, err) { + try { + request.onError(err) + assert(request.aborted) + } catch (err) { + client.emit('error', err) + } +} + +module.exports = Client + + +/***/ }), + +/***/ 13194: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +/* istanbul ignore file: only for Node 12 */ + +const { kConnected, kSize } = __nccwpck_require__(36443) + +class CompatWeakRef { + constructor (value) { + this.value = value + } + + deref () { + return this.value[kConnected] === 0 && this.value[kSize] === 0 + ? undefined + : this.value + } +} + +class CompatFinalizer { + constructor (finalizer) { + this.finalizer = finalizer + } + + register (dispatcher, key) { + if (dispatcher.on) { + dispatcher.on('disconnect', () => { + if (dispatcher[kConnected] === 0 && dispatcher[kSize] === 0) { + this.finalizer(key) + } + }) + } + } +} + +module.exports = function () { + // FIXME: remove workaround when the Node bug is fixed + // https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 + if (process.env.NODE_V8_COVERAGE) { + return { + WeakRef: CompatWeakRef, + FinalizationRegistry: CompatFinalizer + } + } + return { + WeakRef: global.WeakRef || CompatWeakRef, + FinalizationRegistry: global.FinalizationRegistry || CompatFinalizer + } +} + + +/***/ }), + +/***/ 19237: +/***/ ((module) => { + +"use strict"; + + +// https://wicg.github.io/cookie-store/#cookie-maximum-attribute-value-size +const maxAttributeValueSize = 1024 + +// https://wicg.github.io/cookie-store/#cookie-maximum-name-value-pair-size +const maxNameValuePairSize = 4096 + +module.exports = { + maxAttributeValueSize, + maxNameValuePairSize +} + + +/***/ }), + +/***/ 53168: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { parseSetCookie } = __nccwpck_require__(8915) +const { stringify } = __nccwpck_require__(3834) +const { webidl } = __nccwpck_require__(74222) +const { Headers } = __nccwpck_require__(26349) + +/** + * @typedef {Object} Cookie + * @property {string} name + * @property {string} value + * @property {Date|number|undefined} expires + * @property {number|undefined} maxAge + * @property {string|undefined} domain + * @property {string|undefined} path + * @property {boolean|undefined} secure + * @property {boolean|undefined} httpOnly + * @property {'Strict'|'Lax'|'None'} sameSite + * @property {string[]} unparsed + */ + +/** + * @param {Headers} headers + * @returns {Record} + */ +function getCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, { header: 'getCookies' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + const cookie = headers.get('cookie') + const out = {} + + if (!cookie) { + return out + } + + for (const piece of cookie.split(';')) { + const [name, ...value] = piece.split('=') + + out[name.trim()] = value.join('=') + } + + return out +} + +/** + * @param {Headers} headers + * @param {string} name + * @param {{ path?: string, domain?: string }|undefined} attributes + * @returns {void} + */ +function deleteCookie (headers, name, attributes) { + webidl.argumentLengthCheck(arguments, 2, { header: 'deleteCookie' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + name = webidl.converters.DOMString(name) + attributes = webidl.converters.DeleteCookieAttributes(attributes) + + // Matches behavior of + // https://github.com/denoland/deno_std/blob/63827b16330b82489a04614027c33b7904e08be5/http/cookie.ts#L278 + setCookie(headers, { + name, + value: '', + expires: new Date(0), + ...attributes + }) +} + +/** + * @param {Headers} headers + * @returns {Cookie[]} + */ +function getSetCookies (headers) { + webidl.argumentLengthCheck(arguments, 1, { header: 'getSetCookies' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + const cookies = headers.getSetCookie() + + if (!cookies) { + return [] + } + + return cookies.map((pair) => parseSetCookie(pair)) +} + +/** + * @param {Headers} headers + * @param {Cookie} cookie + * @returns {void} + */ +function setCookie (headers, cookie) { + webidl.argumentLengthCheck(arguments, 2, { header: 'setCookie' }) + + webidl.brandCheck(headers, Headers, { strict: false }) + + cookie = webidl.converters.Cookie(cookie) + + const str = stringify(cookie) + + if (str) { + headers.append('Set-Cookie', stringify(cookie)) + } +} + +webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: null + } +]) + +webidl.converters.Cookie = webidl.dictionaryConverter([ + { + converter: webidl.converters.DOMString, + key: 'name' + }, + { + converter: webidl.converters.DOMString, + key: 'value' + }, + { + converter: webidl.nullableConverter((value) => { + if (typeof value === 'number') { + return webidl.converters['unsigned long long'](value) + } + + return new Date(value) + }), + key: 'expires', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters['long long']), + key: 'maxAge', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'domain', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: 'path', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'secure', + defaultValue: null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: 'httpOnly', + defaultValue: null + }, + { + converter: webidl.converters.USVString, + key: 'sameSite', + allowedValues: ['Strict', 'Lax', 'None'] + }, + { + converter: webidl.sequenceConverter(webidl.converters.DOMString), + key: 'unparsed', + defaultValue: [] + } +]) + +module.exports = { + getCookies, + deleteCookie, + getSetCookies, + setCookie +} + + +/***/ }), + +/***/ 8915: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { maxNameValuePairSize, maxAttributeValueSize } = __nccwpck_require__(19237) +const { isCTLExcludingHtab } = __nccwpck_require__(3834) +const { collectASequenceOfCodePointsFast } = __nccwpck_require__(94322) +const assert = __nccwpck_require__(42613) + +/** + * @description Parses the field-value attributes of a set-cookie header string. + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} header + * @returns if the header is invalid, null will be returned + */ +function parseSetCookie (header) { + // 1. If the set-cookie-string contains a %x00-08 / %x0A-1F / %x7F + // character (CTL characters excluding HTAB): Abort these steps and + // ignore the set-cookie-string entirely. + if (isCTLExcludingHtab(header)) { + return null + } + + let nameValuePair = '' + let unparsedAttributes = '' + let name = '' + let value = '' + + // 2. If the set-cookie-string contains a %x3B (";") character: + if (header.includes(';')) { + // 1. The name-value-pair string consists of the characters up to, + // but not including, the first %x3B (";"), and the unparsed- + // attributes consist of the remainder of the set-cookie-string + // (including the %x3B (";") in question). + const position = { position: 0 } + + nameValuePair = collectASequenceOfCodePointsFast(';', header, position) + unparsedAttributes = header.slice(position.position) + } else { + // Otherwise: + + // 1. The name-value-pair string consists of all the characters + // contained in the set-cookie-string, and the unparsed- + // attributes is the empty string. + nameValuePair = header + } + + // 3. If the name-value-pair string lacks a %x3D ("=") character, then + // the name string is empty, and the value string is the value of + // name-value-pair. + if (!nameValuePair.includes('=')) { + value = nameValuePair + } else { + // Otherwise, the name string consists of the characters up to, but + // not including, the first %x3D ("=") character, and the (possibly + // empty) value string consists of the characters after the first + // %x3D ("=") character. + const position = { position: 0 } + name = collectASequenceOfCodePointsFast( + '=', + nameValuePair, + position + ) + value = nameValuePair.slice(position.position + 1) + } + + // 4. Remove any leading or trailing WSP characters from the name + // string and the value string. + name = name.trim() + value = value.trim() + + // 5. If the sum of the lengths of the name string and the value string + // is more than 4096 octets, abort these steps and ignore the set- + // cookie-string entirely. + if (name.length + value.length > maxNameValuePairSize) { + return null + } + + // 6. The cookie-name is the name string, and the cookie-value is the + // value string. + return { + name, value, ...parseUnparsedAttributes(unparsedAttributes) + } +} + +/** + * Parses the remaining attributes of a set-cookie header + * @see https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4 + * @param {string} unparsedAttributes + * @param {[Object.]={}} cookieAttributeList + */ +function parseUnparsedAttributes (unparsedAttributes, cookieAttributeList = {}) { + // 1. If the unparsed-attributes string is empty, skip the rest of + // these steps. + if (unparsedAttributes.length === 0) { + return cookieAttributeList + } + + // 2. Discard the first character of the unparsed-attributes (which + // will be a %x3B (";") character). + assert(unparsedAttributes[0] === ';') + unparsedAttributes = unparsedAttributes.slice(1) + + let cookieAv = '' + + // 3. If the remaining unparsed-attributes contains a %x3B (";") + // character: + if (unparsedAttributes.includes(';')) { + // 1. Consume the characters of the unparsed-attributes up to, but + // not including, the first %x3B (";") character. + cookieAv = collectASequenceOfCodePointsFast( + ';', + unparsedAttributes, + { position: 0 } + ) + unparsedAttributes = unparsedAttributes.slice(cookieAv.length) + } else { + // Otherwise: + + // 1. Consume the remainder of the unparsed-attributes. + cookieAv = unparsedAttributes + unparsedAttributes = '' + } + + // Let the cookie-av string be the characters consumed in this step. + + let attributeName = '' + let attributeValue = '' + + // 4. If the cookie-av string contains a %x3D ("=") character: + if (cookieAv.includes('=')) { + // 1. The (possibly empty) attribute-name string consists of the + // characters up to, but not including, the first %x3D ("=") + // character, and the (possibly empty) attribute-value string + // consists of the characters after the first %x3D ("=") + // character. + const position = { position: 0 } + + attributeName = collectASequenceOfCodePointsFast( + '=', + cookieAv, + position + ) + attributeValue = cookieAv.slice(position.position + 1) + } else { + // Otherwise: + + // 1. The attribute-name string consists of the entire cookie-av + // string, and the attribute-value string is empty. + attributeName = cookieAv + } + + // 5. Remove any leading or trailing WSP characters from the attribute- + // name string and the attribute-value string. + attributeName = attributeName.trim() + attributeValue = attributeValue.trim() + + // 6. If the attribute-value is longer than 1024 octets, ignore the + // cookie-av string and return to Step 1 of this algorithm. + if (attributeValue.length > maxAttributeValueSize) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 7. Process the attribute-name and attribute-value according to the + // requirements in the following subsections. (Notice that + // attributes with unrecognized attribute-names are ignored.) + const attributeNameLowercase = attributeName.toLowerCase() + + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.1 + // If the attribute-name case-insensitively matches the string + // "Expires", the user agent MUST process the cookie-av as follows. + if (attributeNameLowercase === 'expires') { + // 1. Let the expiry-time be the result of parsing the attribute-value + // as cookie-date (see Section 5.1.1). + const expiryTime = new Date(attributeValue) + + // 2. If the attribute-value failed to parse as a cookie date, ignore + // the cookie-av. + + cookieAttributeList.expires = expiryTime + } else if (attributeNameLowercase === 'max-age') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.2 + // If the attribute-name case-insensitively matches the string "Max- + // Age", the user agent MUST process the cookie-av as follows. + + // 1. If the first character of the attribute-value is not a DIGIT or a + // "-" character, ignore the cookie-av. + const charCode = attributeValue.charCodeAt(0) + + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== '-') { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 2. If the remainder of attribute-value contains a non-DIGIT + // character, ignore the cookie-av. + if (!/^\d+$/.test(attributeValue)) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) + } + + // 3. Let delta-seconds be the attribute-value converted to an integer. + const deltaSeconds = Number(attributeValue) + + // 4. Let cookie-age-limit be the maximum age of the cookie (which + // SHOULD be 400 days or less, see Section 4.1.2.2). + + // 5. Set delta-seconds to the smaller of its present value and cookie- + // age-limit. + // deltaSeconds = Math.min(deltaSeconds * 1000, maxExpiresMs) + + // 6. If delta-seconds is less than or equal to zero (0), let expiry- + // time be the earliest representable date and time. Otherwise, let + // the expiry-time be the current date and time plus delta-seconds + // seconds. + // const expiryTime = deltaSeconds <= 0 ? Date.now() : Date.now() + deltaSeconds + + // 7. Append an attribute to the cookie-attribute-list with an + // attribute-name of Max-Age and an attribute-value of expiry-time. + cookieAttributeList.maxAge = deltaSeconds + } else if (attributeNameLowercase === 'domain') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.3 + // If the attribute-name case-insensitively matches the string "Domain", + // the user agent MUST process the cookie-av as follows. + + // 1. Let cookie-domain be the attribute-value. + let cookieDomain = attributeValue + + // 2. If cookie-domain starts with %x2E ("."), let cookie-domain be + // cookie-domain without its leading %x2E ("."). + if (cookieDomain[0] === '.') { + cookieDomain = cookieDomain.slice(1) + } + + // 3. Convert the cookie-domain to lower case. + cookieDomain = cookieDomain.toLowerCase() + + // 4. Append an attribute to the cookie-attribute-list with an + // attribute-name of Domain and an attribute-value of cookie-domain. + cookieAttributeList.domain = cookieDomain + } else if (attributeNameLowercase === 'path') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.4 + // If the attribute-name case-insensitively matches the string "Path", + // the user agent MUST process the cookie-av as follows. + + // 1. If the attribute-value is empty or if the first character of the + // attribute-value is not %x2F ("/"): + let cookiePath = '' + if (attributeValue.length === 0 || attributeValue[0] !== '/') { + // 1. Let cookie-path be the default-path. + cookiePath = '/' + } else { + // Otherwise: + + // 1. Let cookie-path be the attribute-value. + cookiePath = attributeValue + } + + // 2. Append an attribute to the cookie-attribute-list with an + // attribute-name of Path and an attribute-value of cookie-path. + cookieAttributeList.path = cookiePath + } else if (attributeNameLowercase === 'secure') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.5 + // If the attribute-name case-insensitively matches the string "Secure", + // the user agent MUST append an attribute to the cookie-attribute-list + // with an attribute-name of Secure and an empty attribute-value. + + cookieAttributeList.secure = true + } else if (attributeNameLowercase === 'httponly') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.6 + // If the attribute-name case-insensitively matches the string + // "HttpOnly", the user agent MUST append an attribute to the cookie- + // attribute-list with an attribute-name of HttpOnly and an empty + // attribute-value. + + cookieAttributeList.httpOnly = true + } else if (attributeNameLowercase === 'samesite') { + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis#section-5.4.7 + // If the attribute-name case-insensitively matches the string + // "SameSite", the user agent MUST process the cookie-av as follows: + + // 1. Let enforcement be "Default". + let enforcement = 'Default' + + const attributeValueLowercase = attributeValue.toLowerCase() + // 2. If cookie-av's attribute-value is a case-insensitive match for + // "None", set enforcement to "None". + if (attributeValueLowercase.includes('none')) { + enforcement = 'None' + } + + // 3. If cookie-av's attribute-value is a case-insensitive match for + // "Strict", set enforcement to "Strict". + if (attributeValueLowercase.includes('strict')) { + enforcement = 'Strict' + } + + // 4. If cookie-av's attribute-value is a case-insensitive match for + // "Lax", set enforcement to "Lax". + if (attributeValueLowercase.includes('lax')) { + enforcement = 'Lax' + } + + // 5. Append an attribute to the cookie-attribute-list with an + // attribute-name of "SameSite" and an attribute-value of + // enforcement. + cookieAttributeList.sameSite = enforcement + } else { + cookieAttributeList.unparsed ??= [] + + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`) + } + + // 8. Return to Step 1 of this algorithm. + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList) +} + +module.exports = { + parseSetCookie, + parseUnparsedAttributes +} + + +/***/ }), + +/***/ 3834: +/***/ ((module) => { + +"use strict"; + + +/** + * @param {string} value + * @returns {boolean} + */ +function isCTLExcludingHtab (value) { + if (value.length === 0) { + return false + } + + for (const char of value) { + const code = char.charCodeAt(0) + + if ( + (code >= 0x00 || code <= 0x08) || + (code >= 0x0A || code <= 0x1F) || + code === 0x7F + ) { + return false + } + } +} + +/** + CHAR = + token = 1* + separators = "(" | ")" | "<" | ">" | "@" + | "," | ";" | ":" | "\" | <"> + | "/" | "[" | "]" | "?" | "=" + | "{" | "}" | SP | HT + * @param {string} name + */ +function validateCookieName (name) { + for (const char of name) { + const code = char.charCodeAt(0) + + if ( + (code <= 0x20 || code > 0x7F) || + char === '(' || + char === ')' || + char === '>' || + char === '<' || + char === '@' || + char === ',' || + char === ';' || + char === ':' || + char === '\\' || + char === '"' || + char === '/' || + char === '[' || + char === ']' || + char === '?' || + char === '=' || + char === '{' || + char === '}' + ) { + throw new Error('Invalid cookie name') + } + } +} + +/** + cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) + cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E + ; US-ASCII characters excluding CTLs, + ; whitespace DQUOTE, comma, semicolon, + ; and backslash + * @param {string} value + */ +function validateCookieValue (value) { + for (const char of value) { + const code = char.charCodeAt(0) + + if ( + code < 0x21 || // exclude CTLs (0-31) + code === 0x22 || + code === 0x2C || + code === 0x3B || + code === 0x5C || + code > 0x7E // non-ascii + ) { + throw new Error('Invalid header value') + } + } +} + +/** + * path-value = + * @param {string} path + */ +function validateCookiePath (path) { + for (const char of path) { + const code = char.charCodeAt(0) + + if (code < 0x21 || char === ';') { + throw new Error('Invalid cookie path') + } + } +} + +/** + * I have no idea why these values aren't allowed to be honest, + * but Deno tests these. - Khafra + * @param {string} domain + */ +function validateCookieDomain (domain) { + if ( + domain.startsWith('-') || + domain.endsWith('.') || + domain.endsWith('-') + ) { + throw new Error('Invalid cookie domain') + } +} + +/** + * @see https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1 + * @param {number|Date} date + IMF-fixdate = day-name "," SP date1 SP time-of-day SP GMT + ; fixed length/zone/capitalization subset of the format + ; see Section 3.3 of [RFC5322] + + day-name = %x4D.6F.6E ; "Mon", case-sensitive + / %x54.75.65 ; "Tue", case-sensitive + / %x57.65.64 ; "Wed", case-sensitive + / %x54.68.75 ; "Thu", case-sensitive + / %x46.72.69 ; "Fri", case-sensitive + / %x53.61.74 ; "Sat", case-sensitive + / %x53.75.6E ; "Sun", case-sensitive + date1 = day SP month SP year + ; e.g., 02 Jun 1982 + + day = 2DIGIT + month = %x4A.61.6E ; "Jan", case-sensitive + / %x46.65.62 ; "Feb", case-sensitive + / %x4D.61.72 ; "Mar", case-sensitive + / %x41.70.72 ; "Apr", case-sensitive + / %x4D.61.79 ; "May", case-sensitive + / %x4A.75.6E ; "Jun", case-sensitive + / %x4A.75.6C ; "Jul", case-sensitive + / %x41.75.67 ; "Aug", case-sensitive + / %x53.65.70 ; "Sep", case-sensitive + / %x4F.63.74 ; "Oct", case-sensitive + / %x4E.6F.76 ; "Nov", case-sensitive + / %x44.65.63 ; "Dec", case-sensitive + year = 4DIGIT + + GMT = %x47.4D.54 ; "GMT", case-sensitive + + time-of-day = hour ":" minute ":" second + ; 00:00:00 - 23:59:60 (leap second) + + hour = 2DIGIT + minute = 2DIGIT + second = 2DIGIT + */ +function toIMFDate (date) { + if (typeof date === 'number') { + date = new Date(date) + } + + const days = [ + 'Sun', 'Mon', 'Tue', 'Wed', + 'Thu', 'Fri', 'Sat' + ] + + const months = [ + 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' + ] + + const dayName = days[date.getUTCDay()] + const day = date.getUTCDate().toString().padStart(2, '0') + const month = months[date.getUTCMonth()] + const year = date.getUTCFullYear() + const hour = date.getUTCHours().toString().padStart(2, '0') + const minute = date.getUTCMinutes().toString().padStart(2, '0') + const second = date.getUTCSeconds().toString().padStart(2, '0') + + return `${dayName}, ${day} ${month} ${year} ${hour}:${minute}:${second} GMT` +} + +/** + max-age-av = "Max-Age=" non-zero-digit *DIGIT + ; In practice, both expires-av and max-age-av + ; are limited to dates representable by the + ; user agent. + * @param {number} maxAge + */ +function validateCookieMaxAge (maxAge) { + if (maxAge < 0) { + throw new Error('Invalid cookie max-age') + } +} + +/** + * @see https://www.rfc-editor.org/rfc/rfc6265#section-4.1.1 + * @param {import('./index').Cookie} cookie + */ +function stringify (cookie) { + if (cookie.name.length === 0) { + return null + } + + validateCookieName(cookie.name) + validateCookieValue(cookie.value) + + const out = [`${cookie.name}=${cookie.value}`] + + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.1 + // https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-cookie-prefixes-00#section-3.2 + if (cookie.name.startsWith('__Secure-')) { + cookie.secure = true + } + + if (cookie.name.startsWith('__Host-')) { + cookie.secure = true + cookie.domain = null + cookie.path = '/' + } + + if (cookie.secure) { + out.push('Secure') + } + + if (cookie.httpOnly) { + out.push('HttpOnly') + } + + if (typeof cookie.maxAge === 'number') { + validateCookieMaxAge(cookie.maxAge) + out.push(`Max-Age=${cookie.maxAge}`) + } + + if (cookie.domain) { + validateCookieDomain(cookie.domain) + out.push(`Domain=${cookie.domain}`) + } + + if (cookie.path) { + validateCookiePath(cookie.path) + out.push(`Path=${cookie.path}`) + } + + if (cookie.expires && cookie.expires.toString() !== 'Invalid Date') { + out.push(`Expires=${toIMFDate(cookie.expires)}`) + } + + if (cookie.sameSite) { + out.push(`SameSite=${cookie.sameSite}`) + } + + for (const part of cookie.unparsed) { + if (!part.includes('=')) { + throw new Error('Invalid unparsed') + } + + const [key, ...value] = part.split('=') + + out.push(`${key.trim()}=${value.join('=')}`) + } + + return out.join('; ') +} + +module.exports = { + isCTLExcludingHtab, + validateCookieName, + validateCookiePath, + validateCookieValue, + toIMFDate, + stringify +} + + +/***/ }), + +/***/ 59136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const net = __nccwpck_require__(69278) +const assert = __nccwpck_require__(42613) +const util = __nccwpck_require__(3440) +const { InvalidArgumentError, ConnectTimeoutError } = __nccwpck_require__(68707) + +let tls // include tls conditionally since it is not always available + +// TODO: session re-use does not wait for the first +// connection to resolve the session and might therefore +// resolve the same servername multiple times even when +// re-use is enabled. + +let SessionCache +// FIXME: remove workaround when the Node bug is fixed +// https://github.com/nodejs/node/issues/49344#issuecomment-1741776308 +if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) { + SessionCache = class WeakSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + this._sessionRegistry = new global.FinalizationRegistry((key) => { + if (this._sessionCache.size < this._maxCachedSessions) { + return + } + + const ref = this._sessionCache.get(key) + if (ref !== undefined && ref.deref() === undefined) { + this._sessionCache.delete(key) + } + }) + } + + get (sessionKey) { + const ref = this._sessionCache.get(sessionKey) + return ref ? ref.deref() : null + } + + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } + + this._sessionCache.set(sessionKey, new WeakRef(session)) + this._sessionRegistry.register(session, sessionKey) + } + } +} else { + SessionCache = class SimpleSessionCache { + constructor (maxCachedSessions) { + this._maxCachedSessions = maxCachedSessions + this._sessionCache = new Map() + } + + get (sessionKey) { + return this._sessionCache.get(sessionKey) + } + + set (sessionKey, session) { + if (this._maxCachedSessions === 0) { + return + } + + if (this._sessionCache.size >= this._maxCachedSessions) { + // remove the oldest session + const { value: oldestKey } = this._sessionCache.keys().next() + this._sessionCache.delete(oldestKey) + } + + this._sessionCache.set(sessionKey, session) + } + } +} + +function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) { + if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) { + throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero') + } + + const options = { path: socketPath, ...opts } + const sessionCache = new SessionCache(maxCachedSessions == null ? 100 : maxCachedSessions) + timeout = timeout == null ? 10e3 : timeout + allowH2 = allowH2 != null ? allowH2 : false + return function connect ({ hostname, host, protocol, port, servername, localAddress, httpSocket }, callback) { + let socket + if (protocol === 'https:') { + if (!tls) { + tls = __nccwpck_require__(64756) + } + servername = servername || options.servername || util.getServerName(host) || null + + const sessionKey = servername || hostname + const session = sessionCache.get(sessionKey) || null + + assert(sessionKey) + + socket = tls.connect({ + highWaterMark: 16384, // TLS in node can't have bigger HWM anyway... + ...options, + servername, + session, + localAddress, + // TODO(HTTP/2): Add support for h2c + ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'], + socket: httpSocket, // upgrade socket connection + port: port || 443, + host: hostname + }) + + socket + .on('session', function (session) { + // TODO (fix): Can a session become invalid once established? Don't think so? + sessionCache.set(sessionKey, session) + }) + } else { + assert(!httpSocket, 'httpSocket can only be sent on TLS update') + socket = net.connect({ + highWaterMark: 64 * 1024, // Same as nodejs fs streams. + ...options, + localAddress, + port: port || 80, + host: hostname + }) + } + + // Set TCP keep alive options on the socket here instead of in connect() for the case of assigning the socket + if (options.keepAlive == null || options.keepAlive) { + const keepAliveInitialDelay = options.keepAliveInitialDelay === undefined ? 60e3 : options.keepAliveInitialDelay + socket.setKeepAlive(true, keepAliveInitialDelay) + } + + const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout) + + socket + .setNoDelay(true) + .once(protocol === 'https:' ? 'secureConnect' : 'connect', function () { + cancelTimeout() + + if (callback) { + const cb = callback + callback = null + cb(null, this) + } + }) + .on('error', function (err) { + cancelTimeout() + + if (callback) { + const cb = callback + callback = null + cb(err) + } + }) + + return socket + } +} + +function setupTimeout (onConnectTimeout, timeout) { + if (!timeout) { + return () => {} + } + + let s1 = null + let s2 = null + const timeoutId = setTimeout(() => { + // setImmediate is added to make sure that we priotorise socket error events over timeouts + s1 = setImmediate(() => { + if (process.platform === 'win32') { + // Windows needs an extra setImmediate probably due to implementation differences in the socket logic + s2 = setImmediate(() => onConnectTimeout()) + } else { + onConnectTimeout() + } + }) + }, timeout) + return () => { + clearTimeout(timeoutId) + clearImmediate(s1) + clearImmediate(s2) + } +} + +function onConnectTimeout (socket) { + util.destroy(socket, new ConnectTimeoutError()) +} + +module.exports = buildConnector + + +/***/ }), + +/***/ 10735: +/***/ ((module) => { + +"use strict"; + + +/** @type {Record} */ +const headerNameLowerCasedRecord = {} + +// https://developer.mozilla.org/docs/Web/HTTP/Headers +const wellknownHeaderNames = [ + 'Accept', + 'Accept-Encoding', + 'Accept-Language', + 'Accept-Ranges', + 'Access-Control-Allow-Credentials', + 'Access-Control-Allow-Headers', + 'Access-Control-Allow-Methods', + 'Access-Control-Allow-Origin', + 'Access-Control-Expose-Headers', + 'Access-Control-Max-Age', + 'Access-Control-Request-Headers', + 'Access-Control-Request-Method', + 'Age', + 'Allow', + 'Alt-Svc', + 'Alt-Used', + 'Authorization', + 'Cache-Control', + 'Clear-Site-Data', + 'Connection', + 'Content-Disposition', + 'Content-Encoding', + 'Content-Language', + 'Content-Length', + 'Content-Location', + 'Content-Range', + 'Content-Security-Policy', + 'Content-Security-Policy-Report-Only', + 'Content-Type', + 'Cookie', + 'Cross-Origin-Embedder-Policy', + 'Cross-Origin-Opener-Policy', + 'Cross-Origin-Resource-Policy', + 'Date', + 'Device-Memory', + 'Downlink', + 'ECT', + 'ETag', + 'Expect', + 'Expect-CT', + 'Expires', + 'Forwarded', + 'From', + 'Host', + 'If-Match', + 'If-Modified-Since', + 'If-None-Match', + 'If-Range', + 'If-Unmodified-Since', + 'Keep-Alive', + 'Last-Modified', + 'Link', + 'Location', + 'Max-Forwards', + 'Origin', + 'Permissions-Policy', + 'Pragma', + 'Proxy-Authenticate', + 'Proxy-Authorization', + 'RTT', + 'Range', + 'Referer', + 'Referrer-Policy', + 'Refresh', + 'Retry-After', + 'Sec-WebSocket-Accept', + 'Sec-WebSocket-Extensions', + 'Sec-WebSocket-Key', + 'Sec-WebSocket-Protocol', + 'Sec-WebSocket-Version', + 'Server', + 'Server-Timing', + 'Service-Worker-Allowed', + 'Service-Worker-Navigation-Preload', + 'Set-Cookie', + 'SourceMap', + 'Strict-Transport-Security', + 'Supports-Loading-Mode', + 'TE', + 'Timing-Allow-Origin', + 'Trailer', + 'Transfer-Encoding', + 'Upgrade', + 'Upgrade-Insecure-Requests', + 'User-Agent', + 'Vary', + 'Via', + 'WWW-Authenticate', + 'X-Content-Type-Options', + 'X-DNS-Prefetch-Control', + 'X-Frame-Options', + 'X-Permitted-Cross-Domain-Policies', + 'X-Powered-By', + 'X-Requested-With', + 'X-XSS-Protection' +] + +for (let i = 0; i < wellknownHeaderNames.length; ++i) { + const key = wellknownHeaderNames[i] + const lowerCasedKey = key.toLowerCase() + headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] = + lowerCasedKey +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(headerNameLowerCasedRecord, null) + +module.exports = { + wellknownHeaderNames, + headerNameLowerCasedRecord +} + + +/***/ }), + +/***/ 68707: +/***/ ((module) => { + +"use strict"; + + +class UndiciError extends Error { + constructor (message) { + super(message) + this.name = 'UndiciError' + this.code = 'UND_ERR' + } +} + +class ConnectTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ConnectTimeoutError) + this.name = 'ConnectTimeoutError' + this.message = message || 'Connect Timeout Error' + this.code = 'UND_ERR_CONNECT_TIMEOUT' + } +} + +class HeadersTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, HeadersTimeoutError) + this.name = 'HeadersTimeoutError' + this.message = message || 'Headers Timeout Error' + this.code = 'UND_ERR_HEADERS_TIMEOUT' + } +} + +class HeadersOverflowError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, HeadersOverflowError) + this.name = 'HeadersOverflowError' + this.message = message || 'Headers Overflow Error' + this.code = 'UND_ERR_HEADERS_OVERFLOW' + } +} + +class BodyTimeoutError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, BodyTimeoutError) + this.name = 'BodyTimeoutError' + this.message = message || 'Body Timeout Error' + this.code = 'UND_ERR_BODY_TIMEOUT' + } +} + +class ResponseStatusCodeError extends UndiciError { + constructor (message, statusCode, headers, body) { + super(message) + Error.captureStackTrace(this, ResponseStatusCodeError) + this.name = 'ResponseStatusCodeError' + this.message = message || 'Response Status Code Error' + this.code = 'UND_ERR_RESPONSE_STATUS_CODE' + this.body = body + this.status = statusCode + this.statusCode = statusCode + this.headers = headers + } +} + +class InvalidArgumentError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InvalidArgumentError) + this.name = 'InvalidArgumentError' + this.message = message || 'Invalid Argument Error' + this.code = 'UND_ERR_INVALID_ARG' + } +} + +class InvalidReturnValueError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InvalidReturnValueError) + this.name = 'InvalidReturnValueError' + this.message = message || 'Invalid Return Value Error' + this.code = 'UND_ERR_INVALID_RETURN_VALUE' + } +} + +class RequestAbortedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, RequestAbortedError) + this.name = 'AbortError' + this.message = message || 'Request aborted' + this.code = 'UND_ERR_ABORTED' + } +} + +class InformationalError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, InformationalError) + this.name = 'InformationalError' + this.message = message || 'Request information' + this.code = 'UND_ERR_INFO' + } +} + +class RequestContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, RequestContentLengthMismatchError) + this.name = 'RequestContentLengthMismatchError' + this.message = message || 'Request body length does not match content-length header' + this.code = 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH' + } +} + +class ResponseContentLengthMismatchError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ResponseContentLengthMismatchError) + this.name = 'ResponseContentLengthMismatchError' + this.message = message || 'Response body length does not match content-length header' + this.code = 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH' + } +} + +class ClientDestroyedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ClientDestroyedError) + this.name = 'ClientDestroyedError' + this.message = message || 'The client is destroyed' + this.code = 'UND_ERR_DESTROYED' + } +} + +class ClientClosedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ClientClosedError) + this.name = 'ClientClosedError' + this.message = message || 'The client is closed' + this.code = 'UND_ERR_CLOSED' + } +} + +class SocketError extends UndiciError { + constructor (message, socket) { + super(message) + Error.captureStackTrace(this, SocketError) + this.name = 'SocketError' + this.message = message || 'Socket error' + this.code = 'UND_ERR_SOCKET' + this.socket = socket + } +} + +class NotSupportedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, NotSupportedError) + this.name = 'NotSupportedError' + this.message = message || 'Not supported error' + this.code = 'UND_ERR_NOT_SUPPORTED' + } +} + +class BalancedPoolMissingUpstreamError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, NotSupportedError) + this.name = 'MissingUpstreamError' + this.message = message || 'No upstream has been added to the BalancedPool' + this.code = 'UND_ERR_BPL_MISSING_UPSTREAM' + } +} + +class HTTPParserError extends Error { + constructor (message, code, data) { + super(message) + Error.captureStackTrace(this, HTTPParserError) + this.name = 'HTTPParserError' + this.code = code ? `HPE_${code}` : undefined + this.data = data ? data.toString() : undefined + } +} + +class ResponseExceededMaxSizeError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, ResponseExceededMaxSizeError) + this.name = 'ResponseExceededMaxSizeError' + this.message = message || 'Response content exceeded max size' + this.code = 'UND_ERR_RES_EXCEEDED_MAX_SIZE' + } +} + +class RequestRetryError extends UndiciError { + constructor (message, code, { headers, data }) { + super(message) + Error.captureStackTrace(this, RequestRetryError) + this.name = 'RequestRetryError' + this.message = message || 'Request retry error' + this.code = 'UND_ERR_REQ_RETRY' + this.statusCode = code + this.data = data + this.headers = headers + } +} + +module.exports = { + HTTPParserError, + UndiciError, + HeadersTimeoutError, + HeadersOverflowError, + BodyTimeoutError, + RequestContentLengthMismatchError, + ConnectTimeoutError, + ResponseStatusCodeError, + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError, + ClientDestroyedError, + ClientClosedError, + InformationalError, + SocketError, + NotSupportedError, + ResponseContentLengthMismatchError, + BalancedPoolMissingUpstreamError, + ResponseExceededMaxSizeError, + RequestRetryError +} + + +/***/ }), + +/***/ 44655: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + InvalidArgumentError, + NotSupportedError +} = __nccwpck_require__(68707) +const assert = __nccwpck_require__(42613) +const { kHTTP2BuildRequest, kHTTP2CopyHeaders, kHTTP1BuildRequest } = __nccwpck_require__(36443) +const util = __nccwpck_require__(3440) + +// tokenRegExp and headerCharRegex have been lifted from +// https://github.com/nodejs/node/blob/main/lib/_http_common.js + +/** + * Verifies that the given val is a valid HTTP token + * per the rules defined in RFC 7230 + * See https://tools.ietf.org/html/rfc7230#section-3.2.6 + */ +const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/ + +/** + * Matches if val contains an invalid field-vchar + * field-value = *( field-content / obs-fold ) + * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] + * field-vchar = VCHAR / obs-text + */ +const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/ + +// Verifies that a given path is valid does not contain control chars \x00 to \x20 +const invalidPathRegex = /[^\u0021-\u00ff]/ + +const kHandler = Symbol('handler') + +const channels = {} + +let extractBody + +try { + const diagnosticsChannel = __nccwpck_require__(31637) + channels.create = diagnosticsChannel.channel('undici:request:create') + channels.bodySent = diagnosticsChannel.channel('undici:request:bodySent') + channels.headers = diagnosticsChannel.channel('undici:request:headers') + channels.trailers = diagnosticsChannel.channel('undici:request:trailers') + channels.error = diagnosticsChannel.channel('undici:request:error') +} catch { + channels.create = { hasSubscribers: false } + channels.bodySent = { hasSubscribers: false } + channels.headers = { hasSubscribers: false } + channels.trailers = { hasSubscribers: false } + channels.error = { hasSubscribers: false } +} + +class Request { + constructor (origin, { + path, + method, + body, + headers, + query, + idempotent, + blocking, + upgrade, + headersTimeout, + bodyTimeout, + reset, + throwOnError, + expectContinue + }, handler) { + if (typeof path !== 'string') { + throw new InvalidArgumentError('path must be a string') + } else if ( + path[0] !== '/' && + !(path.startsWith('http://') || path.startsWith('https://')) && + method !== 'CONNECT' + ) { + throw new InvalidArgumentError('path must be an absolute URL or start with a slash') + } else if (invalidPathRegex.exec(path) !== null) { + throw new InvalidArgumentError('invalid request path') + } + + if (typeof method !== 'string') { + throw new InvalidArgumentError('method must be a string') + } else if (tokenRegExp.exec(method) === null) { + throw new InvalidArgumentError('invalid request method') + } + + if (upgrade && typeof upgrade !== 'string') { + throw new InvalidArgumentError('upgrade must be a string') + } + + if (headersTimeout != null && (!Number.isFinite(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError('invalid headersTimeout') + } + + if (bodyTimeout != null && (!Number.isFinite(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError('invalid bodyTimeout') + } + + if (reset != null && typeof reset !== 'boolean') { + throw new InvalidArgumentError('invalid reset') + } + + if (expectContinue != null && typeof expectContinue !== 'boolean') { + throw new InvalidArgumentError('invalid expectContinue') + } + + this.headersTimeout = headersTimeout + + this.bodyTimeout = bodyTimeout + + this.throwOnError = throwOnError === true + + this.method = method + + this.abort = null + + if (body == null) { + this.body = null + } else if (util.isStream(body)) { + this.body = body + + const rState = this.body._readableState + if (!rState || !rState.autoDestroy) { + this.endHandler = function autoDestroy () { + util.destroy(this) + } + this.body.on('end', this.endHandler) + } + + this.errorHandler = err => { + if (this.abort) { + this.abort(err) + } else { + this.error = err + } + } + this.body.on('error', this.errorHandler) + } else if (util.isBuffer(body)) { + this.body = body.byteLength ? body : null + } else if (ArrayBuffer.isView(body)) { + this.body = body.buffer.byteLength ? Buffer.from(body.buffer, body.byteOffset, body.byteLength) : null + } else if (body instanceof ArrayBuffer) { + this.body = body.byteLength ? Buffer.from(body) : null + } else if (typeof body === 'string') { + this.body = body.length ? Buffer.from(body) : null + } else if (util.isFormDataLike(body) || util.isIterable(body) || util.isBlobLike(body)) { + this.body = body + } else { + throw new InvalidArgumentError('body must be a string, a Buffer, a Readable stream, an iterable, or an async iterable') + } + + this.completed = false + + this.aborted = false + + this.upgrade = upgrade || null + + this.path = query ? util.buildURL(path, query) : path + + this.origin = origin + + this.idempotent = idempotent == null + ? method === 'HEAD' || method === 'GET' + : idempotent + + this.blocking = blocking == null ? false : blocking + + this.reset = reset == null ? null : reset + + this.host = null + + this.contentLength = null + + this.contentType = null + + this.headers = '' + + // Only for H2 + this.expectContinue = expectContinue != null ? expectContinue : false + + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(this, headers[i], headers[i + 1]) + } + } else if (headers && typeof headers === 'object') { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + processHeader(this, key, headers[key]) + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') + } + + if (util.isFormDataLike(this.body)) { + if (util.nodeMajor < 16 || (util.nodeMajor === 16 && util.nodeMinor < 8)) { + throw new InvalidArgumentError('Form-Data bodies are only supported in node v16.8 and newer.') + } + + if (!extractBody) { + extractBody = (__nccwpck_require__(8923).extractBody) + } + + const [bodyStream, contentType] = extractBody(body) + if (this.contentType == null) { + this.contentType = contentType + this.headers += `content-type: ${contentType}\r\n` + } + this.body = bodyStream.stream + this.contentLength = bodyStream.length + } else if (util.isBlobLike(body) && this.contentType == null && body.type) { + this.contentType = body.type + this.headers += `content-type: ${body.type}\r\n` + } + + util.validateHandler(handler, method, upgrade) + + this.servername = util.getServerName(this.host) + + this[kHandler] = handler + + if (channels.create.hasSubscribers) { + channels.create.publish({ request: this }) + } + } + + onBodySent (chunk) { + if (this[kHandler].onBodySent) { + try { + return this[kHandler].onBodySent(chunk) + } catch (err) { + this.abort(err) + } + } + } + + onRequestSent () { + if (channels.bodySent.hasSubscribers) { + channels.bodySent.publish({ request: this }) + } + + if (this[kHandler].onRequestSent) { + try { + return this[kHandler].onRequestSent() + } catch (err) { + this.abort(err) + } + } + } + + onConnect (abort) { + assert(!this.aborted) + assert(!this.completed) + + if (this.error) { + abort(this.error) + } else { + this.abort = abort + return this[kHandler].onConnect(abort) + } + } + + onHeaders (statusCode, headers, resume, statusText) { + assert(!this.aborted) + assert(!this.completed) + + if (channels.headers.hasSubscribers) { + channels.headers.publish({ request: this, response: { statusCode, headers, statusText } }) + } + + try { + return this[kHandler].onHeaders(statusCode, headers, resume, statusText) + } catch (err) { + this.abort(err) + } + } + + onData (chunk) { + assert(!this.aborted) + assert(!this.completed) + + try { + return this[kHandler].onData(chunk) + } catch (err) { + this.abort(err) + return false + } + } + + onUpgrade (statusCode, headers, socket) { + assert(!this.aborted) + assert(!this.completed) + + return this[kHandler].onUpgrade(statusCode, headers, socket) + } + + onComplete (trailers) { + this.onFinally() + + assert(!this.aborted) + + this.completed = true + if (channels.trailers.hasSubscribers) { + channels.trailers.publish({ request: this, trailers }) + } + + try { + return this[kHandler].onComplete(trailers) + } catch (err) { + // TODO (fix): This might be a bad idea? + this.onError(err) + } + } + + onError (error) { + this.onFinally() + + if (channels.error.hasSubscribers) { + channels.error.publish({ request: this, error }) + } + + if (this.aborted) { + return + } + this.aborted = true + + return this[kHandler].onError(error) + } + + onFinally () { + if (this.errorHandler) { + this.body.off('error', this.errorHandler) + this.errorHandler = null + } + + if (this.endHandler) { + this.body.off('end', this.endHandler) + this.endHandler = null + } + } + + // TODO: adjust to support H2 + addHeader (key, value) { + processHeader(this, key, value) + return this + } + + static [kHTTP1BuildRequest] (origin, opts, handler) { + // TODO: Migrate header parsing here, to make Requests + // HTTP agnostic + return new Request(origin, opts, handler) + } + + static [kHTTP2BuildRequest] (origin, opts, handler) { + const headers = opts.headers + opts = { ...opts, headers: null } + + const request = new Request(origin, opts, handler) + + request.headers = {} + + if (Array.isArray(headers)) { + if (headers.length % 2 !== 0) { + throw new InvalidArgumentError('headers array must be even') + } + for (let i = 0; i < headers.length; i += 2) { + processHeader(request, headers[i], headers[i + 1], true) + } + } else if (headers && typeof headers === 'object') { + const keys = Object.keys(headers) + for (let i = 0; i < keys.length; i++) { + const key = keys[i] + processHeader(request, key, headers[key], true) + } + } else if (headers != null) { + throw new InvalidArgumentError('headers must be an object or an array') + } + + return request + } + + static [kHTTP2CopyHeaders] (raw) { + const rawHeaders = raw.split('\r\n') + const headers = {} + + for (const header of rawHeaders) { + const [key, value] = header.split(': ') + + if (value == null || value.length === 0) continue + + if (headers[key]) headers[key] += `,${value}` + else headers[key] = value + } + + return headers + } +} + +function processHeaderValue (key, val, skipAppend) { + if (val && typeof val === 'object') { + throw new InvalidArgumentError(`invalid ${key} header`) + } + + val = val != null ? `${val}` : '' + + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + + return skipAppend ? val : `${key}: ${val}\r\n` +} + +function processHeader (request, key, val, skipAppend = false) { + if (val && (typeof val === 'object' && !Array.isArray(val))) { + throw new InvalidArgumentError(`invalid ${key} header`) + } else if (val === undefined) { + return + } + + if ( + request.host === null && + key.length === 4 && + key.toLowerCase() === 'host' + ) { + if (headerCharRegex.exec(val) !== null) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + // Consumed by Client + request.host = val + } else if ( + request.contentLength === null && + key.length === 14 && + key.toLowerCase() === 'content-length' + ) { + request.contentLength = parseInt(val, 10) + if (!Number.isFinite(request.contentLength)) { + throw new InvalidArgumentError('invalid content-length header') + } + } else if ( + request.contentType === null && + key.length === 12 && + key.toLowerCase() === 'content-type' + ) { + request.contentType = val + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) + else request.headers += processHeaderValue(key, val) + } else if ( + key.length === 17 && + key.toLowerCase() === 'transfer-encoding' + ) { + throw new InvalidArgumentError('invalid transfer-encoding header') + } else if ( + key.length === 10 && + key.toLowerCase() === 'connection' + ) { + const value = typeof val === 'string' ? val.toLowerCase() : null + if (value !== 'close' && value !== 'keep-alive') { + throw new InvalidArgumentError('invalid connection header') + } else if (value === 'close') { + request.reset = true + } + } else if ( + key.length === 10 && + key.toLowerCase() === 'keep-alive' + ) { + throw new InvalidArgumentError('invalid keep-alive header') + } else if ( + key.length === 7 && + key.toLowerCase() === 'upgrade' + ) { + throw new InvalidArgumentError('invalid upgrade header') + } else if ( + key.length === 6 && + key.toLowerCase() === 'expect' + ) { + throw new NotSupportedError('expect header not supported') + } else if (tokenRegExp.exec(key) === null) { + throw new InvalidArgumentError('invalid header key') + } else { + if (Array.isArray(val)) { + for (let i = 0; i < val.length; i++) { + if (skipAppend) { + if (request.headers[key]) request.headers[key] += `,${processHeaderValue(key, val[i], skipAppend)}` + else request.headers[key] = processHeaderValue(key, val[i], skipAppend) + } else { + request.headers += processHeaderValue(key, val[i]) + } + } + } else { + if (skipAppend) request.headers[key] = processHeaderValue(key, val, skipAppend) + else request.headers += processHeaderValue(key, val) + } + } +} + +module.exports = Request + + +/***/ }), + +/***/ 36443: +/***/ ((module) => { + +module.exports = { + kClose: Symbol('close'), + kDestroy: Symbol('destroy'), + kDispatch: Symbol('dispatch'), + kUrl: Symbol('url'), + kWriting: Symbol('writing'), + kResuming: Symbol('resuming'), + kQueue: Symbol('queue'), + kConnect: Symbol('connect'), + kConnecting: Symbol('connecting'), + kHeadersList: Symbol('headers list'), + kKeepAliveDefaultTimeout: Symbol('default keep alive timeout'), + kKeepAliveMaxTimeout: Symbol('max keep alive timeout'), + kKeepAliveTimeoutThreshold: Symbol('keep alive timeout threshold'), + kKeepAliveTimeoutValue: Symbol('keep alive timeout'), + kKeepAlive: Symbol('keep alive'), + kHeadersTimeout: Symbol('headers timeout'), + kBodyTimeout: Symbol('body timeout'), + kServerName: Symbol('server name'), + kLocalAddress: Symbol('local address'), + kHost: Symbol('host'), + kNoRef: Symbol('no ref'), + kBodyUsed: Symbol('used'), + kRunning: Symbol('running'), + kBlocking: Symbol('blocking'), + kPending: Symbol('pending'), + kSize: Symbol('size'), + kBusy: Symbol('busy'), + kQueued: Symbol('queued'), + kFree: Symbol('free'), + kConnected: Symbol('connected'), + kClosed: Symbol('closed'), + kNeedDrain: Symbol('need drain'), + kReset: Symbol('reset'), + kDestroyed: Symbol.for('nodejs.stream.destroyed'), + kMaxHeadersSize: Symbol('max headers size'), + kRunningIdx: Symbol('running index'), + kPendingIdx: Symbol('pending index'), + kError: Symbol('error'), + kClients: Symbol('clients'), + kClient: Symbol('client'), + kParser: Symbol('parser'), + kOnDestroyed: Symbol('destroy callbacks'), + kPipelining: Symbol('pipelining'), + kSocket: Symbol('socket'), + kHostHeader: Symbol('host header'), + kConnector: Symbol('connector'), + kStrictContentLength: Symbol('strict content length'), + kMaxRedirections: Symbol('maxRedirections'), + kMaxRequests: Symbol('maxRequestsPerClient'), + kProxy: Symbol('proxy agent options'), + kCounter: Symbol('socket request counter'), + kInterceptors: Symbol('dispatch interceptors'), + kMaxResponseSize: Symbol('max response size'), + kHTTP2Session: Symbol('http2Session'), + kHTTP2SessionState: Symbol('http2Session state'), + kHTTP2BuildRequest: Symbol('http2 build request'), + kHTTP1BuildRequest: Symbol('http1 build request'), + kHTTP2CopyHeaders: Symbol('http2 copy headers'), + kHTTPConnVersion: Symbol('http connection version'), + kRetryHandlerDefaultRetry: Symbol('retry agent default retry'), + kConstruct: Symbol('constructable') +} + + +/***/ }), + +/***/ 3440: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const assert = __nccwpck_require__(42613) +const { kDestroyed, kBodyUsed } = __nccwpck_require__(36443) +const { IncomingMessage } = __nccwpck_require__(58611) +const stream = __nccwpck_require__(2203) +const net = __nccwpck_require__(69278) +const { InvalidArgumentError } = __nccwpck_require__(68707) +const { Blob } = __nccwpck_require__(20181) +const nodeUtil = __nccwpck_require__(39023) +const { stringify } = __nccwpck_require__(83480) +const { headerNameLowerCasedRecord } = __nccwpck_require__(10735) + +const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v)) + +function nop () {} + +function isStream (obj) { + return obj && typeof obj === 'object' && typeof obj.pipe === 'function' && typeof obj.on === 'function' +} + +// based on https://github.com/node-fetch/fetch-blob/blob/8ab587d34080de94140b54f07168451e7d0b655e/index.js#L229-L241 (MIT License) +function isBlobLike (object) { + return (Blob && object instanceof Blob) || ( + object && + typeof object === 'object' && + (typeof object.stream === 'function' || + typeof object.arrayBuffer === 'function') && + /^(Blob|File)$/.test(object[Symbol.toStringTag]) + ) +} + +function buildURL (url, queryParams) { + if (url.includes('?') || url.includes('#')) { + throw new Error('Query params cannot be passed when url already contains "?" or "#".') + } + + const stringified = stringify(queryParams) + + if (stringified) { + url += '?' + stringified + } + + return url +} + +function parseURL (url) { + if (typeof url === 'string') { + url = new URL(url) + + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } + + return url + } + + if (!url || typeof url !== 'object') { + throw new InvalidArgumentError('Invalid URL: The URL argument must be a non-null object.') + } + + if (!/^https?:/.test(url.origin || url.protocol)) { + throw new InvalidArgumentError('Invalid URL protocol: the URL must start with `http:` or `https:`.') + } + + if (!(url instanceof URL)) { + if (url.port != null && url.port !== '' && !Number.isFinite(parseInt(url.port))) { + throw new InvalidArgumentError('Invalid URL: port must be a valid integer or a string representation of an integer.') + } + + if (url.path != null && typeof url.path !== 'string') { + throw new InvalidArgumentError('Invalid URL path: the path must be a string or null/undefined.') + } + + if (url.pathname != null && typeof url.pathname !== 'string') { + throw new InvalidArgumentError('Invalid URL pathname: the pathname must be a string or null/undefined.') + } + + if (url.hostname != null && typeof url.hostname !== 'string') { + throw new InvalidArgumentError('Invalid URL hostname: the hostname must be a string or null/undefined.') + } + + if (url.origin != null && typeof url.origin !== 'string') { + throw new InvalidArgumentError('Invalid URL origin: the origin must be a string or null/undefined.') + } + + const port = url.port != null + ? url.port + : (url.protocol === 'https:' ? 443 : 80) + let origin = url.origin != null + ? url.origin + : `${url.protocol}//${url.hostname}:${port}` + let path = url.path != null + ? url.path + : `${url.pathname || ''}${url.search || ''}` + + if (origin.endsWith('/')) { + origin = origin.substring(0, origin.length - 1) + } + + if (path && !path.startsWith('/')) { + path = `/${path}` + } + // new URL(path, origin) is unsafe when `path` contains an absolute URL + // From https://developer.mozilla.org/en-US/docs/Web/API/URL/URL: + // If first parameter is a relative URL, second param is required, and will be used as the base URL. + // If first parameter is an absolute URL, a given second param will be ignored. + url = new URL(origin + path) + } + + return url +} + +function parseOrigin (url) { + url = parseURL(url) + + if (url.pathname !== '/' || url.search || url.hash) { + throw new InvalidArgumentError('invalid url') + } + + return url +} + +function getHostname (host) { + if (host[0] === '[') { + const idx = host.indexOf(']') + + assert(idx !== -1) + return host.substring(1, idx) + } + + const idx = host.indexOf(':') + if (idx === -1) return host + + return host.substring(0, idx) +} + +// IP addresses are not valid server names per RFC6066 +// > Currently, the only server names supported are DNS hostnames +function getServerName (host) { + if (!host) { + return null + } + + assert.strictEqual(typeof host, 'string') + + const servername = getHostname(host) + if (net.isIP(servername)) { + return '' + } + + return servername +} + +function deepClone (obj) { + return JSON.parse(JSON.stringify(obj)) +} + +function isAsyncIterable (obj) { + return !!(obj != null && typeof obj[Symbol.asyncIterator] === 'function') +} + +function isIterable (obj) { + return !!(obj != null && (typeof obj[Symbol.iterator] === 'function' || typeof obj[Symbol.asyncIterator] === 'function')) +} + +function bodyLength (body) { + if (body == null) { + return 0 + } else if (isStream(body)) { + const state = body._readableState + return state && state.objectMode === false && state.ended === true && Number.isFinite(state.length) + ? state.length + : null + } else if (isBlobLike(body)) { + return body.size != null ? body.size : null + } else if (isBuffer(body)) { + return body.byteLength + } + + return null +} + +function isDestroyed (stream) { + return !stream || !!(stream.destroyed || stream[kDestroyed]) +} + +function isReadableAborted (stream) { + const state = stream && stream._readableState + return isDestroyed(stream) && state && !state.endEmitted +} + +function destroy (stream, err) { + if (stream == null || !isStream(stream) || isDestroyed(stream)) { + return + } + + if (typeof stream.destroy === 'function') { + if (Object.getPrototypeOf(stream).constructor === IncomingMessage) { + // See: https://github.com/nodejs/node/pull/38505/files + stream.socket = null + } + + stream.destroy(err) + } else if (err) { + process.nextTick((stream, err) => { + stream.emit('error', err) + }, stream, err) + } + + if (stream.destroyed !== true) { + stream[kDestroyed] = true + } +} + +const KEEPALIVE_TIMEOUT_EXPR = /timeout=(\d+)/ +function parseKeepAliveTimeout (val) { + const m = val.toString().match(KEEPALIVE_TIMEOUT_EXPR) + return m ? parseInt(m[1], 10) * 1000 : null +} + +/** + * Retrieves a header name and returns its lowercase value. + * @param {string | Buffer} value Header name + * @returns {string} + */ +function headerNameToString (value) { + return headerNameLowerCasedRecord[value] || value.toLowerCase() +} + +function parseHeaders (headers, obj = {}) { + // For H2 support + if (!Array.isArray(headers)) return headers + + for (let i = 0; i < headers.length; i += 2) { + const key = headers[i].toString().toLowerCase() + let val = obj[key] + + if (!val) { + if (Array.isArray(headers[i + 1])) { + obj[key] = headers[i + 1].map(x => x.toString('utf8')) + } else { + obj[key] = headers[i + 1].toString('utf8') + } + } else { + if (!Array.isArray(val)) { + val = [val] + obj[key] = val + } + val.push(headers[i + 1].toString('utf8')) + } + } + + // See https://github.com/nodejs/node/pull/46528 + if ('content-length' in obj && 'content-disposition' in obj) { + obj['content-disposition'] = Buffer.from(obj['content-disposition']).toString('latin1') + } + + return obj +} + +function parseRawHeaders (headers) { + const ret = [] + let hasContentLength = false + let contentDispositionIdx = -1 + + for (let n = 0; n < headers.length; n += 2) { + const key = headers[n + 0].toString() + const val = headers[n + 1].toString('utf8') + + if (key.length === 14 && (key === 'content-length' || key.toLowerCase() === 'content-length')) { + ret.push(key, val) + hasContentLength = true + } else if (key.length === 19 && (key === 'content-disposition' || key.toLowerCase() === 'content-disposition')) { + contentDispositionIdx = ret.push(key, val) - 1 + } else { + ret.push(key, val) + } + } + + // See https://github.com/nodejs/node/pull/46528 + if (hasContentLength && contentDispositionIdx !== -1) { + ret[contentDispositionIdx] = Buffer.from(ret[contentDispositionIdx]).toString('latin1') + } + + return ret +} + +function isBuffer (buffer) { + // See, https://github.com/mcollina/undici/pull/319 + return buffer instanceof Uint8Array || Buffer.isBuffer(buffer) +} + +function validateHandler (handler, method, upgrade) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } + + if (typeof handler.onConnect !== 'function') { + throw new InvalidArgumentError('invalid onConnect method') + } + + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') + } + + if (typeof handler.onBodySent !== 'function' && handler.onBodySent !== undefined) { + throw new InvalidArgumentError('invalid onBodySent method') + } + + if (upgrade || method === 'CONNECT') { + if (typeof handler.onUpgrade !== 'function') { + throw new InvalidArgumentError('invalid onUpgrade method') + } + } else { + if (typeof handler.onHeaders !== 'function') { + throw new InvalidArgumentError('invalid onHeaders method') + } + + if (typeof handler.onData !== 'function') { + throw new InvalidArgumentError('invalid onData method') + } + + if (typeof handler.onComplete !== 'function') { + throw new InvalidArgumentError('invalid onComplete method') + } + } +} + +// A body is disturbed if it has been read from and it cannot +// be re-used without losing state or data. +function isDisturbed (body) { + return !!(body && ( + stream.isDisturbed + ? stream.isDisturbed(body) || body[kBodyUsed] // TODO (fix): Why is body[kBodyUsed] needed? + : body[kBodyUsed] || + body.readableDidRead || + (body._readableState && body._readableState.dataEmitted) || + isReadableAborted(body) + )) +} + +function isErrored (body) { + return !!(body && ( + stream.isErrored + ? stream.isErrored(body) + : /state: 'errored'/.test(nodeUtil.inspect(body) + ))) +} + +function isReadable (body) { + return !!(body && ( + stream.isReadable + ? stream.isReadable(body) + : /state: 'readable'/.test(nodeUtil.inspect(body) + ))) +} + +function getSocketInfo (socket) { + return { + localAddress: socket.localAddress, + localPort: socket.localPort, + remoteAddress: socket.remoteAddress, + remotePort: socket.remotePort, + remoteFamily: socket.remoteFamily, + timeout: socket.timeout, + bytesWritten: socket.bytesWritten, + bytesRead: socket.bytesRead + } +} + +async function * convertIterableToBuffer (iterable) { + for await (const chunk of iterable) { + yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk) + } +} + +let ReadableStream +function ReadableStreamFrom (iterable) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + if (ReadableStream.from) { + return ReadableStream.from(convertIterableToBuffer(iterable)) + } + + let iterator + return new ReadableStream( + { + async start () { + iterator = iterable[Symbol.asyncIterator]() + }, + async pull (controller) { + const { done, value } = await iterator.next() + if (done) { + queueMicrotask(() => { + controller.close() + }) + } else { + const buf = Buffer.isBuffer(value) ? value : Buffer.from(value) + controller.enqueue(new Uint8Array(buf)) + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + } + }, + 0 + ) +} + +// The chunk should be a FormData instance and contains +// all the required methods. +function isFormDataLike (object) { + return ( + object && + typeof object === 'object' && + typeof object.append === 'function' && + typeof object.delete === 'function' && + typeof object.get === 'function' && + typeof object.getAll === 'function' && + typeof object.has === 'function' && + typeof object.set === 'function' && + object[Symbol.toStringTag] === 'FormData' + ) +} + +function throwIfAborted (signal) { + if (!signal) { return } + if (typeof signal.throwIfAborted === 'function') { + signal.throwIfAborted() + } else { + if (signal.aborted) { + // DOMException not available < v17.0.0 + const err = new Error('The operation was aborted') + err.name = 'AbortError' + throw err + } + } +} + +function addAbortListener (signal, listener) { + if ('addEventListener' in signal) { + signal.addEventListener('abort', listener, { once: true }) + return () => signal.removeEventListener('abort', listener) + } + signal.addListener('abort', listener) + return () => signal.removeListener('abort', listener) +} + +const hasToWellFormed = !!String.prototype.toWellFormed + +/** + * @param {string} val + */ +function toUSVString (val) { + if (hasToWellFormed) { + return `${val}`.toWellFormed() + } else if (nodeUtil.toUSVString) { + return nodeUtil.toUSVString(val) + } + + return `${val}` +} + +// Parsed accordingly to RFC 9110 +// https://www.rfc-editor.org/rfc/rfc9110#field.content-range +function parseRangeHeader (range) { + if (range == null || range === '') return { start: 0, end: null, size: null } + + const m = range ? range.match(/^bytes (\d+)-(\d+)\/(\d+)?$/) : null + return m + ? { + start: parseInt(m[1]), + end: m[2] ? parseInt(m[2]) : null, + size: m[3] ? parseInt(m[3]) : null + } + : null +} + +const kEnumerableProperty = Object.create(null) +kEnumerableProperty.enumerable = true + +module.exports = { + kEnumerableProperty, + nop, + isDisturbed, + isErrored, + isReadable, + toUSVString, + isReadableAborted, + isBlobLike, + parseOrigin, + parseURL, + getServerName, + isStream, + isIterable, + isAsyncIterable, + isDestroyed, + headerNameToString, + parseRawHeaders, + parseHeaders, + parseKeepAliveTimeout, + destroy, + bodyLength, + deepClone, + ReadableStreamFrom, + isBuffer, + validateHandler, + getSocketInfo, + isFormDataLike, + buildURL, + throwIfAborted, + addAbortListener, + parseRangeHeader, + nodeMajor, + nodeMinor, + nodeHasAutoSelectFamily: nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 13), + safeHTTPMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'] +} + + +/***/ }), + +/***/ 50001: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Dispatcher = __nccwpck_require__(28611) +const { + ClientDestroyedError, + ClientClosedError, + InvalidArgumentError +} = __nccwpck_require__(68707) +const { kDestroy, kClose, kDispatch, kInterceptors } = __nccwpck_require__(36443) + +const kDestroyed = Symbol('destroyed') +const kClosed = Symbol('closed') +const kOnDestroyed = Symbol('onDestroyed') +const kOnClosed = Symbol('onClosed') +const kInterceptedDispatch = Symbol('Intercepted Dispatch') + +class DispatcherBase extends Dispatcher { + constructor () { + super() + + this[kDestroyed] = false + this[kOnDestroyed] = null + this[kClosed] = false + this[kOnClosed] = [] + } + + get destroyed () { + return this[kDestroyed] + } + + get closed () { + return this[kClosed] + } + + get interceptors () { + return this[kInterceptors] + } + + set interceptors (newInterceptors) { + if (newInterceptors) { + for (let i = newInterceptors.length - 1; i >= 0; i--) { + const interceptor = this[kInterceptors][i] + if (typeof interceptor !== 'function') { + throw new InvalidArgumentError('interceptor must be an function') + } + } + } + + this[kInterceptors] = newInterceptors + } + + close (callback) { + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.close((err, data) => { + return err ? reject(err) : resolve(data) + }) + }) + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (this[kDestroyed]) { + queueMicrotask(() => callback(new ClientDestroyedError(), null)) + return + } + + if (this[kClosed]) { + if (this[kOnClosed]) { + this[kOnClosed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } + + this[kClosed] = true + this[kOnClosed].push(callback) + + const onClosed = () => { + const callbacks = this[kOnClosed] + this[kOnClosed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } + + // Should not error. + this[kClose]() + .then(() => this.destroy()) + .then(() => { + queueMicrotask(onClosed) + }) + } + + destroy (err, callback) { + if (typeof err === 'function') { + callback = err + err = null + } + + if (callback === undefined) { + return new Promise((resolve, reject) => { + this.destroy(err, (err, data) => { + return err ? /* istanbul ignore next: should never error */ reject(err) : resolve(data) + }) + }) + } + + if (typeof callback !== 'function') { + throw new InvalidArgumentError('invalid callback') + } + + if (this[kDestroyed]) { + if (this[kOnDestroyed]) { + this[kOnDestroyed].push(callback) + } else { + queueMicrotask(() => callback(null, null)) + } + return + } + + if (!err) { + err = new ClientDestroyedError() + } + + this[kDestroyed] = true + this[kOnDestroyed] = this[kOnDestroyed] || [] + this[kOnDestroyed].push(callback) + + const onDestroyed = () => { + const callbacks = this[kOnDestroyed] + this[kOnDestroyed] = null + for (let i = 0; i < callbacks.length; i++) { + callbacks[i](null, null) + } + } + + // Should not error. + this[kDestroy](err).then(() => { + queueMicrotask(onDestroyed) + }) + } + + [kInterceptedDispatch] (opts, handler) { + if (!this[kInterceptors] || this[kInterceptors].length === 0) { + this[kInterceptedDispatch] = this[kDispatch] + return this[kDispatch](opts, handler) + } + + let dispatch = this[kDispatch].bind(this) + for (let i = this[kInterceptors].length - 1; i >= 0; i--) { + dispatch = this[kInterceptors][i](dispatch) + } + this[kInterceptedDispatch] = dispatch + return dispatch(opts, handler) + } + + dispatch (opts, handler) { + if (!handler || typeof handler !== 'object') { + throw new InvalidArgumentError('handler must be an object') + } + + try { + if (!opts || typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object.') + } + + if (this[kDestroyed] || this[kOnDestroyed]) { + throw new ClientDestroyedError() + } + + if (this[kClosed]) { + throw new ClientClosedError() + } + + return this[kInterceptedDispatch](opts, handler) + } catch (err) { + if (typeof handler.onError !== 'function') { + throw new InvalidArgumentError('invalid onError method') + } + + handler.onError(err) + + return false + } + } +} + +module.exports = DispatcherBase + + +/***/ }), + +/***/ 28611: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const EventEmitter = __nccwpck_require__(24434) + +class Dispatcher extends EventEmitter { + dispatch () { + throw new Error('not implemented') + } + + close () { + throw new Error('not implemented') + } + + destroy () { + throw new Error('not implemented') + } +} + +module.exports = Dispatcher + + +/***/ }), + +/***/ 8923: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Busboy = __nccwpck_require__(89581) +const util = __nccwpck_require__(3440) +const { + ReadableStreamFrom, + isBlobLike, + isReadableStreamLike, + readableStreamClose, + createDeferredPromise, + fullyReadBody +} = __nccwpck_require__(15523) +const { FormData } = __nccwpck_require__(43073) +const { kState } = __nccwpck_require__(89710) +const { webidl } = __nccwpck_require__(74222) +const { DOMException, structuredClone } = __nccwpck_require__(87326) +const { Blob, File: NativeFile } = __nccwpck_require__(20181) +const { kBodyUsed } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { isErrored } = __nccwpck_require__(3440) +const { isUint8Array, isArrayBuffer } = __nccwpck_require__(98253) +const { File: UndiciFile } = __nccwpck_require__(63041) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(94322) + +let random +try { + const crypto = __nccwpck_require__(77598) + random = (max) => crypto.randomInt(0, max) +} catch { + random = (max) => Math.floor(Math.random(max)) +} + +let ReadableStream = globalThis.ReadableStream + +/** @type {globalThis['File']} */ +const File = NativeFile ?? UndiciFile +const textEncoder = new TextEncoder() +const textDecoder = new TextDecoder() + +// https://fetch.spec.whatwg.org/#concept-bodyinit-extract +function extractBody (object, keepalive = false) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + // 1. Let stream be null. + let stream = null + + // 2. If object is a ReadableStream object, then set stream to object. + if (object instanceof ReadableStream) { + stream = object + } else if (isBlobLike(object)) { + // 3. Otherwise, if object is a Blob object, set stream to the + // result of running object’s get stream. + stream = object.stream() + } else { + // 4. Otherwise, set stream to a new ReadableStream object, and set + // up stream. + stream = new ReadableStream({ + async pull (controller) { + controller.enqueue( + typeof source === 'string' ? textEncoder.encode(source) : source + ) + queueMicrotask(() => readableStreamClose(controller)) + }, + start () {}, + type: undefined + }) + } + + // 5. Assert: stream is a ReadableStream object. + assert(isReadableStreamLike(stream)) + + // 6. Let action be null. + let action = null + + // 7. Let source be null. + let source = null + + // 8. Let length be null. + let length = null + + // 9. Let type be null. + let type = null + + // 10. Switch on object: + if (typeof object === 'string') { + // Set source to the UTF-8 encoding of object. + // Note: setting source to a Uint8Array here breaks some mocking assumptions. + source = object + + // Set type to `text/plain;charset=UTF-8`. + type = 'text/plain;charset=UTF-8' + } else if (object instanceof URLSearchParams) { + // URLSearchParams + + // spec says to run application/x-www-form-urlencoded on body.list + // this is implemented in Node.js as apart of an URLSearchParams instance toString method + // See: https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L490 + // and https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/lib/internal/url.js#L1100 + + // Set source to the result of running the application/x-www-form-urlencoded serializer with object’s list. + source = object.toString() + + // Set type to `application/x-www-form-urlencoded;charset=UTF-8`. + type = 'application/x-www-form-urlencoded;charset=UTF-8' + } else if (isArrayBuffer(object)) { + // BufferSource/ArrayBuffer + + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.slice()) + } else if (ArrayBuffer.isView(object)) { + // BufferSource/ArrayBufferView + + // Set source to a copy of the bytes held by object. + source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) + } else if (util.isFormDataLike(object)) { + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` + const prefix = `--${boundary}\r\nContent-Disposition: form-data` + + /*! formdata-polyfill. MIT License. Jimmy Wärting */ + const escape = (str) => + str.replace(/\n/g, '%0A').replace(/\r/g, '%0D').replace(/"/g, '%22') + const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, '\r\n') + + // Set action to this step: run the multipart/form-data + // encoding algorithm, with object’s entry list and UTF-8. + // - This ensures that the body is immutable and can't be changed afterwords + // - That the content-length is calculated in advance. + // - And that all parts are pre-encoded and ready to be sent. + + const blobParts = [] + const rn = new Uint8Array([13, 10]) // '\r\n' + length = 0 + let hasUnknownSizeValue = false + + for (const [name, value] of object) { + if (typeof value === 'string') { + const chunk = textEncoder.encode(prefix + + `; name="${escape(normalizeLinefeeds(name))}"` + + `\r\n\r\n${normalizeLinefeeds(value)}\r\n`) + blobParts.push(chunk) + length += chunk.byteLength + } else { + const chunk = textEncoder.encode(`${prefix}; name="${escape(normalizeLinefeeds(name))}"` + + (value.name ? `; filename="${escape(value.name)}"` : '') + '\r\n' + + `Content-Type: ${ + value.type || 'application/octet-stream' + }\r\n\r\n`) + blobParts.push(chunk, value, rn) + if (typeof value.size === 'number') { + length += chunk.byteLength + value.size + rn.byteLength + } else { + hasUnknownSizeValue = true + } + } + } + + const chunk = textEncoder.encode(`--${boundary}--`) + blobParts.push(chunk) + length += chunk.byteLength + if (hasUnknownSizeValue) { + length = null + } + + // Set source to object. + source = object + + action = async function * () { + for (const part of blobParts) { + if (part.stream) { + yield * part.stream() + } else { + yield part + } + } + } + + // Set type to `multipart/form-data; boundary=`, + // followed by the multipart/form-data boundary string generated + // by the multipart/form-data encoding algorithm. + type = 'multipart/form-data; boundary=' + boundary + } else if (isBlobLike(object)) { + // Blob + + // Set source to object. + source = object + + // Set length to object’s size. + length = object.size + + // If object’s type attribute is not the empty byte sequence, set + // type to its value. + if (object.type) { + type = object.type + } + } else if (typeof object[Symbol.asyncIterator] === 'function') { + // If keepalive is true, then throw a TypeError. + if (keepalive) { + throw new TypeError('keepalive') + } + + // If object is disturbed or locked, then throw a TypeError. + if (util.isDisturbed(object) || object.locked) { + throw new TypeError( + 'Response body object should not be disturbed or locked' + ) + } + + stream = + object instanceof ReadableStream ? object : ReadableStreamFrom(object) + } + + // 11. If source is a byte sequence, then set action to a + // step that returns source and length to source’s length. + if (typeof source === 'string' || util.isBuffer(source)) { + length = Buffer.byteLength(source) + } + + // 12. If action is non-null, then run these steps in in parallel: + if (action != null) { + // Run action. + let iterator + stream = new ReadableStream({ + async start () { + iterator = action(object)[Symbol.asyncIterator]() + }, + async pull (controller) { + const { value, done } = await iterator.next() + if (done) { + // When running action is done, close stream. + queueMicrotask(() => { + controller.close() + }) + } else { + // Whenever one or more bytes are available and stream is not errored, + // enqueue a Uint8Array wrapping an ArrayBuffer containing the available + // bytes into stream. + if (!isErrored(stream)) { + controller.enqueue(new Uint8Array(value)) + } + } + return controller.desiredSize > 0 + }, + async cancel (reason) { + await iterator.return() + }, + type: undefined + }) + } + + // 13. Let body be a body whose stream is stream, source is source, + // and length is length. + const body = { stream, source, length } + + // 14. Return (body, type). + return [body, type] +} + +// https://fetch.spec.whatwg.org/#bodyinit-safely-extract +function safelyExtractBody (object, keepalive = false) { + if (!ReadableStream) { + // istanbul ignore next + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + // To safely extract a body and a `Content-Type` value from + // a byte sequence or BodyInit object object, run these steps: + + // 1. If object is a ReadableStream object, then: + if (object instanceof ReadableStream) { + // Assert: object is neither disturbed nor locked. + // istanbul ignore next + assert(!util.isDisturbed(object), 'The body has already been consumed.') + // istanbul ignore next + assert(!object.locked, 'The stream is locked.') + } + + // 2. Return the results of extracting object. + return extractBody(object, keepalive) +} + +function cloneBody (body) { + // To clone a body body, run these steps: + + // https://fetch.spec.whatwg.org/#concept-body-clone + + // 1. Let « out1, out2 » be the result of teeing body’s stream. + const [out1, out2] = body.stream.tee() + const out2Clone = structuredClone(out2, { transfer: [out2] }) + // This, for whatever reasons, unrefs out2Clone which allows + // the process to exit by itself. + const [, finalClone] = out2Clone.tee() + + // 2. Set body’s stream to out1. + body.stream = out1 + + // 3. Return a body whose stream is out2 and other members are copied from body. + return { + stream: finalClone, + length: body.length, + source: body.source + } +} + +async function * consumeBody (body) { + if (body) { + if (isUint8Array(body)) { + yield body + } else { + const stream = body.stream + + if (util.isDisturbed(stream)) { + throw new TypeError('The body has already been consumed.') + } + + if (stream.locked) { + throw new TypeError('The stream is locked.') + } + + // Compat. + stream[kBodyUsed] = true + + yield * stream + } + } +} + +function throwIfAborted (state) { + if (state.aborted) { + throw new DOMException('The operation was aborted.', 'AbortError') + } +} + +function bodyMixinMethods (instance) { + const methods = { + blob () { + // The blob() method steps are to return the result of + // running consume body with this and the following step + // given a byte sequence bytes: return a Blob whose + // contents are bytes and whose type attribute is this’s + // MIME type. + return specConsumeBody(this, (bytes) => { + let mimeType = bodyMimeType(this) + + if (mimeType === 'failure') { + mimeType = '' + } else if (mimeType) { + mimeType = serializeAMimeType(mimeType) + } + + // Return a Blob whose contents are bytes and type attribute + // is mimeType. + return new Blob([bytes], { type: mimeType }) + }, instance) + }, + + arrayBuffer () { + // The arrayBuffer() method steps are to return the result + // of running consume body with this and the following step + // given a byte sequence bytes: return a new ArrayBuffer + // whose contents are bytes. + return specConsumeBody(this, (bytes) => { + return new Uint8Array(bytes).buffer + }, instance) + }, + + text () { + // The text() method steps are to return the result of running + // consume body with this and UTF-8 decode. + return specConsumeBody(this, utf8DecodeBytes, instance) + }, + + json () { + // The json() method steps are to return the result of running + // consume body with this and parse JSON from bytes. + return specConsumeBody(this, parseJSONFromBytes, instance) + }, + + async formData () { + webidl.brandCheck(this, instance) + + throwIfAborted(this[kState]) + + const contentType = this.headers.get('Content-Type') + + // If mimeType’s essence is "multipart/form-data", then: + if (/multipart\/form-data/.test(contentType)) { + const headers = {} + for (const [key, value] of this.headers) headers[key.toLowerCase()] = value + + const responseFormData = new FormData() + + let busboy + + try { + busboy = new Busboy({ + headers, + preservePath: true + }) + } catch (err) { + throw new DOMException(`${err}`, 'AbortError') + } + + busboy.on('field', (name, value) => { + responseFormData.append(name, value) + }) + busboy.on('file', (name, value, filename, encoding, mimeType) => { + const chunks = [] + + if (encoding === 'base64' || encoding.toLowerCase() === 'base64') { + let base64chunk = '' + + value.on('data', (chunk) => { + base64chunk += chunk.toString().replace(/[\r\n]/gm, '') + + const end = base64chunk.length - base64chunk.length % 4 + chunks.push(Buffer.from(base64chunk.slice(0, end), 'base64')) + + base64chunk = base64chunk.slice(end) + }) + value.on('end', () => { + chunks.push(Buffer.from(base64chunk, 'base64')) + responseFormData.append(name, new File(chunks, filename, { type: mimeType })) + }) + } else { + value.on('data', (chunk) => { + chunks.push(chunk) + }) + value.on('end', () => { + responseFormData.append(name, new File(chunks, filename, { type: mimeType })) + }) + } + }) + + const busboyResolve = new Promise((resolve, reject) => { + busboy.on('finish', resolve) + busboy.on('error', (err) => reject(new TypeError(err))) + }) + + if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk) + busboy.end() + await busboyResolve + + return responseFormData + } else if (/application\/x-www-form-urlencoded/.test(contentType)) { + // Otherwise, if mimeType’s essence is "application/x-www-form-urlencoded", then: + + // 1. Let entries be the result of parsing bytes. + let entries + try { + let text = '' + // application/x-www-form-urlencoded parser will keep the BOM. + // https://url.spec.whatwg.org/#concept-urlencoded-parser + // Note that streaming decoder is stateful and cannot be reused + const streamingDecoder = new TextDecoder('utf-8', { ignoreBOM: true }) + + for await (const chunk of consumeBody(this[kState].body)) { + if (!isUint8Array(chunk)) { + throw new TypeError('Expected Uint8Array chunk') + } + text += streamingDecoder.decode(chunk, { stream: true }) + } + text += streamingDecoder.decode() + entries = new URLSearchParams(text) + } catch (err) { + // istanbul ignore next: Unclear when new URLSearchParams can fail on a string. + // 2. If entries is failure, then throw a TypeError. + throw Object.assign(new TypeError(), { cause: err }) + } + + // 3. Return a new FormData object whose entries are entries. + const formData = new FormData() + for (const [name, value] of entries) { + formData.append(name, value) + } + return formData + } else { + // Wait a tick before checking if the request has been aborted. + // Otherwise, a TypeError can be thrown when an AbortError should. + await Promise.resolve() + + throwIfAborted(this[kState]) + + // Otherwise, throw a TypeError. + throw webidl.errors.exception({ + header: `${instance.name}.formData`, + message: 'Could not parse content as FormData.' + }) + } + } + } + + return methods +} + +function mixinBody (prototype) { + Object.assign(prototype.prototype, bodyMixinMethods(prototype)) +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-body-consume-body + * @param {Response|Request} object + * @param {(value: unknown) => unknown} convertBytesToJSValue + * @param {Response|Request} instance + */ +async function specConsumeBody (object, convertBytesToJSValue, instance) { + webidl.brandCheck(object, instance) + + throwIfAborted(object[kState]) + + // 1. If object is unusable, then return a promise rejected + // with a TypeError. + if (bodyUnusable(object[kState].body)) { + throw new TypeError('Body is unusable') + } + + // 2. Let promise be a new promise. + const promise = createDeferredPromise() + + // 3. Let errorSteps given error be to reject promise with error. + const errorSteps = (error) => promise.reject(error) + + // 4. Let successSteps given a byte sequence data be to resolve + // promise with the result of running convertBytesToJSValue + // with data. If that threw an exception, then run errorSteps + // with that exception. + const successSteps = (data) => { + try { + promise.resolve(convertBytesToJSValue(data)) + } catch (e) { + errorSteps(e) + } + } + + // 5. If object’s body is null, then run successSteps with an + // empty byte sequence. + if (object[kState].body == null) { + successSteps(new Uint8Array()) + return promise.promise + } + + // 6. Otherwise, fully read object’s body given successSteps, + // errorSteps, and object’s relevant global object. + await fullyReadBody(object[kState].body, successSteps, errorSteps) + + // 7. Return promise. + return promise.promise +} + +// https://fetch.spec.whatwg.org/#body-unusable +function bodyUnusable (body) { + // An object including the Body interface mixin is + // said to be unusable if its body is non-null and + // its body’s stream is disturbed or locked. + return body != null && (body.stream.locked || util.isDisturbed(body.stream)) +} + +/** + * @see https://encoding.spec.whatwg.org/#utf-8-decode + * @param {Buffer} buffer + */ +function utf8DecodeBytes (buffer) { + if (buffer.length === 0) { + return '' + } + + // 1. Let buffer be the result of peeking three bytes from + // ioQueue, converted to a byte sequence. + + // 2. If buffer is 0xEF 0xBB 0xBF, then read three + // bytes from ioQueue. (Do nothing with those bytes.) + if (buffer[0] === 0xEF && buffer[1] === 0xBB && buffer[2] === 0xBF) { + buffer = buffer.subarray(3) + } + + // 3. Process a queue with an instance of UTF-8’s + // decoder, ioQueue, output, and "replacement". + const output = textDecoder.decode(buffer) + + // 4. Return output. + return output +} + +/** + * @see https://infra.spec.whatwg.org/#parse-json-bytes-to-a-javascript-value + * @param {Uint8Array} bytes + */ +function parseJSONFromBytes (bytes) { + return JSON.parse(utf8DecodeBytes(bytes)) +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-body-mime-type + * @param {import('./response').Response|import('./request').Request} object + */ +function bodyMimeType (object) { + const { headersList } = object[kState] + const contentType = headersList.get('content-type') + + if (contentType === null) { + return 'failure' + } + + return parseMIMEType(contentType) +} + +module.exports = { + extractBody, + safelyExtractBody, + cloneBody, + mixinBody +} + + +/***/ }), + +/***/ 87326: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { MessageChannel, receiveMessageOnPort } = __nccwpck_require__(28167) + +const corsSafeListedMethods = ['GET', 'HEAD', 'POST'] +const corsSafeListedMethodsSet = new Set(corsSafeListedMethods) + +const nullBodyStatus = [101, 204, 205, 304] + +const redirectStatus = [301, 302, 303, 307, 308] +const redirectStatusSet = new Set(redirectStatus) + +// https://fetch.spec.whatwg.org/#block-bad-port +const badPorts = [ + '1', '7', '9', '11', '13', '15', '17', '19', '20', '21', '22', '23', '25', '37', '42', '43', '53', '69', '77', '79', + '87', '95', '101', '102', '103', '104', '109', '110', '111', '113', '115', '117', '119', '123', '135', '137', + '139', '143', '161', '179', '389', '427', '465', '512', '513', '514', '515', '526', '530', '531', '532', + '540', '548', '554', '556', '563', '587', '601', '636', '989', '990', '993', '995', '1719', '1720', '1723', + '2049', '3659', '4045', '5060', '5061', '6000', '6566', '6665', '6666', '6667', '6668', '6669', '6697', + '10080' +] + +const badPortsSet = new Set(badPorts) + +// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies +const referrerPolicy = [ + '', + 'no-referrer', + 'no-referrer-when-downgrade', + 'same-origin', + 'origin', + 'strict-origin', + 'origin-when-cross-origin', + 'strict-origin-when-cross-origin', + 'unsafe-url' +] +const referrerPolicySet = new Set(referrerPolicy) + +const requestRedirect = ['follow', 'manual', 'error'] + +const safeMethods = ['GET', 'HEAD', 'OPTIONS', 'TRACE'] +const safeMethodsSet = new Set(safeMethods) + +const requestMode = ['navigate', 'same-origin', 'no-cors', 'cors'] + +const requestCredentials = ['omit', 'same-origin', 'include'] + +const requestCache = [ + 'default', + 'no-store', + 'reload', + 'no-cache', + 'force-cache', + 'only-if-cached' +] + +// https://fetch.spec.whatwg.org/#request-body-header-name +const requestBodyHeader = [ + 'content-encoding', + 'content-language', + 'content-location', + 'content-type', + // See https://github.com/nodejs/undici/issues/2021 + // 'Content-Length' is a forbidden header name, which is typically + // removed in the Headers implementation. However, undici doesn't + // filter out headers, so we add it here. + 'content-length' +] + +// https://fetch.spec.whatwg.org/#enumdef-requestduplex +const requestDuplex = [ + 'half' +] + +// http://fetch.spec.whatwg.org/#forbidden-method +const forbiddenMethods = ['CONNECT', 'TRACE', 'TRACK'] +const forbiddenMethodsSet = new Set(forbiddenMethods) + +const subresource = [ + 'audio', + 'audioworklet', + 'font', + 'image', + 'manifest', + 'paintworklet', + 'script', + 'style', + 'track', + 'video', + 'xslt', + '' +] +const subresourceSet = new Set(subresource) + +/** @type {globalThis['DOMException']} */ +const DOMException = globalThis.DOMException ?? (() => { + // DOMException was only made a global in Node v17.0.0, + // but fetch supports >= v16.8. + try { + atob('~') + } catch (err) { + return Object.getPrototypeOf(err).constructor + } +})() + +let channel + +/** @type {globalThis['structuredClone']} */ +const structuredClone = + globalThis.structuredClone ?? + // https://github.com/nodejs/node/blob/b27ae24dcc4251bad726d9d84baf678d1f707fed/lib/internal/structured_clone.js + // structuredClone was added in v17.0.0, but fetch supports v16.8 + function structuredClone (value, options = undefined) { + if (arguments.length === 0) { + throw new TypeError('missing argument') + } + + if (!channel) { + channel = new MessageChannel() + } + channel.port1.unref() + channel.port2.unref() + channel.port1.postMessage(value, options?.transfer) + return receiveMessageOnPort(channel.port2).message + } + +module.exports = { + DOMException, + structuredClone, + subresource, + forbiddenMethods, + requestBodyHeader, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + redirectStatus, + corsSafeListedMethods, + nullBodyStatus, + safeMethods, + badPorts, + requestDuplex, + subresourceSet, + badPortsSet, + redirectStatusSet, + corsSafeListedMethodsSet, + safeMethodsSet, + forbiddenMethodsSet, + referrerPolicySet +} + + +/***/ }), + +/***/ 94322: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(42613) +const { atob } = __nccwpck_require__(20181) +const { isomorphicDecode } = __nccwpck_require__(15523) + +const encoder = new TextEncoder() + +/** + * @see https://mimesniff.spec.whatwg.org/#http-token-code-point + */ +const HTTP_TOKEN_CODEPOINTS = /^[!#$%&'*+-.^_|~A-Za-z0-9]+$/ +const HTTP_WHITESPACE_REGEX = /(\u000A|\u000D|\u0009|\u0020)/ // eslint-disable-line +/** + * @see https://mimesniff.spec.whatwg.org/#http-quoted-string-token-code-point + */ +const HTTP_QUOTED_STRING_TOKENS = /[\u0009|\u0020-\u007E|\u0080-\u00FF]/ // eslint-disable-line + +// https://fetch.spec.whatwg.org/#data-url-processor +/** @param {URL} dataURL */ +function dataURLProcessor (dataURL) { + // 1. Assert: dataURL’s scheme is "data". + assert(dataURL.protocol === 'data:') + + // 2. Let input be the result of running the URL + // serializer on dataURL with exclude fragment + // set to true. + let input = URLSerializer(dataURL, true) + + // 3. Remove the leading "data:" string from input. + input = input.slice(5) + + // 4. Let position point at the start of input. + const position = { position: 0 } + + // 5. Let mimeType be the result of collecting a + // sequence of code points that are not equal + // to U+002C (,), given position. + let mimeType = collectASequenceOfCodePointsFast( + ',', + input, + position + ) + + // 6. Strip leading and trailing ASCII whitespace + // from mimeType. + // Undici implementation note: we need to store the + // length because if the mimetype has spaces removed, + // the wrong amount will be sliced from the input in + // step #9 + const mimeTypeLength = mimeType.length + mimeType = removeASCIIWhitespace(mimeType, true, true) + + // 7. If position is past the end of input, then + // return failure + if (position.position >= input.length) { + return 'failure' + } + + // 8. Advance position by 1. + position.position++ + + // 9. Let encodedBody be the remainder of input. + const encodedBody = input.slice(mimeTypeLength + 1) + + // 10. Let body be the percent-decoding of encodedBody. + let body = stringPercentDecode(encodedBody) + + // 11. If mimeType ends with U+003B (;), followed by + // zero or more U+0020 SPACE, followed by an ASCII + // case-insensitive match for "base64", then: + if (/;(\u0020){0,}base64$/i.test(mimeType)) { + // 1. Let stringBody be the isomorphic decode of body. + const stringBody = isomorphicDecode(body) + + // 2. Set body to the forgiving-base64 decode of + // stringBody. + body = forgivingBase64(stringBody) + + // 3. If body is failure, then return failure. + if (body === 'failure') { + return 'failure' + } + + // 4. Remove the last 6 code points from mimeType. + mimeType = mimeType.slice(0, -6) + + // 5. Remove trailing U+0020 SPACE code points from mimeType, + // if any. + mimeType = mimeType.replace(/(\u0020)+$/, '') + + // 6. Remove the last U+003B (;) code point from mimeType. + mimeType = mimeType.slice(0, -1) + } + + // 12. If mimeType starts with U+003B (;), then prepend + // "text/plain" to mimeType. + if (mimeType.startsWith(';')) { + mimeType = 'text/plain' + mimeType + } + + // 13. Let mimeTypeRecord be the result of parsing + // mimeType. + let mimeTypeRecord = parseMIMEType(mimeType) + + // 14. If mimeTypeRecord is failure, then set + // mimeTypeRecord to text/plain;charset=US-ASCII. + if (mimeTypeRecord === 'failure') { + mimeTypeRecord = parseMIMEType('text/plain;charset=US-ASCII') + } + + // 15. Return a new data: URL struct whose MIME + // type is mimeTypeRecord and body is body. + // https://fetch.spec.whatwg.org/#data-url-struct + return { mimeType: mimeTypeRecord, body } +} + +// https://url.spec.whatwg.org/#concept-url-serializer +/** + * @param {URL} url + * @param {boolean} excludeFragment + */ +function URLSerializer (url, excludeFragment = false) { + if (!excludeFragment) { + return url.href + } + + const href = url.href + const hashLength = url.hash.length + + return hashLength === 0 ? href : href.substring(0, href.length - hashLength) +} + +// https://infra.spec.whatwg.org/#collect-a-sequence-of-code-points +/** + * @param {(char: string) => boolean} condition + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePoints (condition, input, position) { + // 1. Let result be the empty string. + let result = '' + + // 2. While position doesn’t point past the end of input and the + // code point at position within input meets the condition condition: + while (position.position < input.length && condition(input[position.position])) { + // 1. Append that code point to the end of result. + result += input[position.position] + + // 2. Advance position by 1. + position.position++ + } + + // 3. Return result. + return result +} + +/** + * A faster collectASequenceOfCodePoints that only works when comparing a single character. + * @param {string} char + * @param {string} input + * @param {{ position: number }} position + */ +function collectASequenceOfCodePointsFast (char, input, position) { + const idx = input.indexOf(char, position.position) + const start = position.position + + if (idx === -1) { + position.position = input.length + return input.slice(start) + } + + position.position = idx + return input.slice(start, position.position) +} + +// https://url.spec.whatwg.org/#string-percent-decode +/** @param {string} input */ +function stringPercentDecode (input) { + // 1. Let bytes be the UTF-8 encoding of input. + const bytes = encoder.encode(input) + + // 2. Return the percent-decoding of bytes. + return percentDecode(bytes) +} + +// https://url.spec.whatwg.org/#percent-decode +/** @param {Uint8Array} input */ +function percentDecode (input) { + // 1. Let output be an empty byte sequence. + /** @type {number[]} */ + const output = [] + + // 2. For each byte byte in input: + for (let i = 0; i < input.length; i++) { + const byte = input[i] + + // 1. If byte is not 0x25 (%), then append byte to output. + if (byte !== 0x25) { + output.push(byte) + + // 2. Otherwise, if byte is 0x25 (%) and the next two bytes + // after byte in input are not in the ranges + // 0x30 (0) to 0x39 (9), 0x41 (A) to 0x46 (F), + // and 0x61 (a) to 0x66 (f), all inclusive, append byte + // to output. + } else if ( + byte === 0x25 && + !/^[0-9A-Fa-f]{2}$/i.test(String.fromCharCode(input[i + 1], input[i + 2])) + ) { + output.push(0x25) + + // 3. Otherwise: + } else { + // 1. Let bytePoint be the two bytes after byte in input, + // decoded, and then interpreted as hexadecimal number. + const nextTwoBytes = String.fromCharCode(input[i + 1], input[i + 2]) + const bytePoint = Number.parseInt(nextTwoBytes, 16) + + // 2. Append a byte whose value is bytePoint to output. + output.push(bytePoint) + + // 3. Skip the next two bytes in input. + i += 2 + } + } + + // 3. Return output. + return Uint8Array.from(output) +} + +// https://mimesniff.spec.whatwg.org/#parse-a-mime-type +/** @param {string} input */ +function parseMIMEType (input) { + // 1. Remove any leading and trailing HTTP whitespace + // from input. + input = removeHTTPWhitespace(input, true, true) + + // 2. Let position be a position variable for input, + // initially pointing at the start of input. + const position = { position: 0 } + + // 3. Let type be the result of collecting a sequence + // of code points that are not U+002F (/) from + // input, given position. + const type = collectASequenceOfCodePointsFast( + '/', + input, + position + ) + + // 4. If type is the empty string or does not solely + // contain HTTP token code points, then return failure. + // https://mimesniff.spec.whatwg.org/#http-token-code-point + if (type.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(type)) { + return 'failure' + } + + // 5. If position is past the end of input, then return + // failure + if (position.position > input.length) { + return 'failure' + } + + // 6. Advance position by 1. (This skips past U+002F (/).) + position.position++ + + // 7. Let subtype be the result of collecting a sequence of + // code points that are not U+003B (;) from input, given + // position. + let subtype = collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 8. Remove any trailing HTTP whitespace from subtype. + subtype = removeHTTPWhitespace(subtype, false, true) + + // 9. If subtype is the empty string or does not solely + // contain HTTP token code points, then return failure. + if (subtype.length === 0 || !HTTP_TOKEN_CODEPOINTS.test(subtype)) { + return 'failure' + } + + const typeLowercase = type.toLowerCase() + const subtypeLowercase = subtype.toLowerCase() + + // 10. Let mimeType be a new MIME type record whose type + // is type, in ASCII lowercase, and subtype is subtype, + // in ASCII lowercase. + // https://mimesniff.spec.whatwg.org/#mime-type + const mimeType = { + type: typeLowercase, + subtype: subtypeLowercase, + /** @type {Map} */ + parameters: new Map(), + // https://mimesniff.spec.whatwg.org/#mime-type-essence + essence: `${typeLowercase}/${subtypeLowercase}` + } + + // 11. While position is not past the end of input: + while (position.position < input.length) { + // 1. Advance position by 1. (This skips past U+003B (;).) + position.position++ + + // 2. Collect a sequence of code points that are HTTP + // whitespace from input given position. + collectASequenceOfCodePoints( + // https://fetch.spec.whatwg.org/#http-whitespace + char => HTTP_WHITESPACE_REGEX.test(char), + input, + position + ) + + // 3. Let parameterName be the result of collecting a + // sequence of code points that are not U+003B (;) + // or U+003D (=) from input, given position. + let parameterName = collectASequenceOfCodePoints( + (char) => char !== ';' && char !== '=', + input, + position + ) + + // 4. Set parameterName to parameterName, in ASCII + // lowercase. + parameterName = parameterName.toLowerCase() + + // 5. If position is not past the end of input, then: + if (position.position < input.length) { + // 1. If the code point at position within input is + // U+003B (;), then continue. + if (input[position.position] === ';') { + continue + } + + // 2. Advance position by 1. (This skips past U+003D (=).) + position.position++ + } + + // 6. If position is past the end of input, then break. + if (position.position > input.length) { + break + } + + // 7. Let parameterValue be null. + let parameterValue = null + + // 8. If the code point at position within input is + // U+0022 ("), then: + if (input[position.position] === '"') { + // 1. Set parameterValue to the result of collecting + // an HTTP quoted string from input, given position + // and the extract-value flag. + parameterValue = collectAnHTTPQuotedString(input, position, true) + + // 2. Collect a sequence of code points that are not + // U+003B (;) from input, given position. + collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 9. Otherwise: + } else { + // 1. Set parameterValue to the result of collecting + // a sequence of code points that are not U+003B (;) + // from input, given position. + parameterValue = collectASequenceOfCodePointsFast( + ';', + input, + position + ) + + // 2. Remove any trailing HTTP whitespace from parameterValue. + parameterValue = removeHTTPWhitespace(parameterValue, false, true) + + // 3. If parameterValue is the empty string, then continue. + if (parameterValue.length === 0) { + continue + } + } + + // 10. If all of the following are true + // - parameterName is not the empty string + // - parameterName solely contains HTTP token code points + // - parameterValue solely contains HTTP quoted-string token code points + // - mimeType’s parameters[parameterName] does not exist + // then set mimeType’s parameters[parameterName] to parameterValue. + if ( + parameterName.length !== 0 && + HTTP_TOKEN_CODEPOINTS.test(parameterName) && + (parameterValue.length === 0 || HTTP_QUOTED_STRING_TOKENS.test(parameterValue)) && + !mimeType.parameters.has(parameterName) + ) { + mimeType.parameters.set(parameterName, parameterValue) + } + } + + // 12. Return mimeType. + return mimeType +} + +// https://infra.spec.whatwg.org/#forgiving-base64-decode +/** @param {string} data */ +function forgivingBase64 (data) { + // 1. Remove all ASCII whitespace from data. + data = data.replace(/[\u0009\u000A\u000C\u000D\u0020]/g, '') // eslint-disable-line + + // 2. If data’s code point length divides by 4 leaving + // no remainder, then: + if (data.length % 4 === 0) { + // 1. If data ends with one or two U+003D (=) code points, + // then remove them from data. + data = data.replace(/=?=$/, '') + } + + // 3. If data’s code point length divides by 4 leaving + // a remainder of 1, then return failure. + if (data.length % 4 === 1) { + return 'failure' + } + + // 4. If data contains a code point that is not one of + // U+002B (+) + // U+002F (/) + // ASCII alphanumeric + // then return failure. + if (/[^+/0-9A-Za-z]/.test(data)) { + return 'failure' + } + + const binary = atob(data) + const bytes = new Uint8Array(binary.length) + + for (let byte = 0; byte < binary.length; byte++) { + bytes[byte] = binary.charCodeAt(byte) + } + + return bytes +} + +// https://fetch.spec.whatwg.org/#collect-an-http-quoted-string +// tests: https://fetch.spec.whatwg.org/#example-http-quoted-string +/** + * @param {string} input + * @param {{ position: number }} position + * @param {boolean?} extractValue + */ +function collectAnHTTPQuotedString (input, position, extractValue) { + // 1. Let positionStart be position. + const positionStart = position.position + + // 2. Let value be the empty string. + let value = '' + + // 3. Assert: the code point at position within input + // is U+0022 ("). + assert(input[position.position] === '"') + + // 4. Advance position by 1. + position.position++ + + // 5. While true: + while (true) { + // 1. Append the result of collecting a sequence of code points + // that are not U+0022 (") or U+005C (\) from input, given + // position, to value. + value += collectASequenceOfCodePoints( + (char) => char !== '"' && char !== '\\', + input, + position + ) + + // 2. If position is past the end of input, then break. + if (position.position >= input.length) { + break + } + + // 3. Let quoteOrBackslash be the code point at position within + // input. + const quoteOrBackslash = input[position.position] + + // 4. Advance position by 1. + position.position++ + + // 5. If quoteOrBackslash is U+005C (\), then: + if (quoteOrBackslash === '\\') { + // 1. If position is past the end of input, then append + // U+005C (\) to value and break. + if (position.position >= input.length) { + value += '\\' + break + } + + // 2. Append the code point at position within input to value. + value += input[position.position] + + // 3. Advance position by 1. + position.position++ + + // 6. Otherwise: + } else { + // 1. Assert: quoteOrBackslash is U+0022 ("). + assert(quoteOrBackslash === '"') + + // 2. Break. + break + } + } + + // 6. If the extract-value flag is set, then return value. + if (extractValue) { + return value + } + + // 7. Return the code points from positionStart to position, + // inclusive, within input. + return input.slice(positionStart, position.position) +} + +/** + * @see https://mimesniff.spec.whatwg.org/#serialize-a-mime-type + */ +function serializeAMimeType (mimeType) { + assert(mimeType !== 'failure') + const { parameters, essence } = mimeType + + // 1. Let serialization be the concatenation of mimeType’s + // type, U+002F (/), and mimeType’s subtype. + let serialization = essence + + // 2. For each name → value of mimeType’s parameters: + for (let [name, value] of parameters.entries()) { + // 1. Append U+003B (;) to serialization. + serialization += ';' + + // 2. Append name to serialization. + serialization += name + + // 3. Append U+003D (=) to serialization. + serialization += '=' + + // 4. If value does not solely contain HTTP token code + // points or value is the empty string, then: + if (!HTTP_TOKEN_CODEPOINTS.test(value)) { + // 1. Precede each occurence of U+0022 (") or + // U+005C (\) in value with U+005C (\). + value = value.replace(/(\\|")/g, '\\$1') + + // 2. Prepend U+0022 (") to value. + value = '"' + value + + // 3. Append U+0022 (") to value. + value += '"' + } + + // 5. Append value to serialization. + serialization += value + } + + // 3. Return serialization. + return serialization +} + +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} char + */ +function isHTTPWhiteSpace (char) { + return char === '\r' || char === '\n' || char === '\t' || char === ' ' +} + +/** + * @see https://fetch.spec.whatwg.org/#http-whitespace + * @param {string} str + */ +function removeHTTPWhitespace (str, leading = true, trailing = true) { + let lead = 0 + let trail = str.length - 1 + + if (leading) { + for (; lead < str.length && isHTTPWhiteSpace(str[lead]); lead++); + } + + if (trailing) { + for (; trail > 0 && isHTTPWhiteSpace(str[trail]); trail--); + } + + return str.slice(lead, trail + 1) +} + +/** + * @see https://infra.spec.whatwg.org/#ascii-whitespace + * @param {string} char + */ +function isASCIIWhitespace (char) { + return char === '\r' || char === '\n' || char === '\t' || char === '\f' || char === ' ' +} + +/** + * @see https://infra.spec.whatwg.org/#strip-leading-and-trailing-ascii-whitespace + */ +function removeASCIIWhitespace (str, leading = true, trailing = true) { + let lead = 0 + let trail = str.length - 1 + + if (leading) { + for (; lead < str.length && isASCIIWhitespace(str[lead]); lead++); + } + + if (trailing) { + for (; trail > 0 && isASCIIWhitespace(str[trail]); trail--); + } + + return str.slice(lead, trail + 1) +} + +module.exports = { + dataURLProcessor, + URLSerializer, + collectASequenceOfCodePoints, + collectASequenceOfCodePointsFast, + stringPercentDecode, + parseMIMEType, + collectAnHTTPQuotedString, + serializeAMimeType +} + + +/***/ }), + +/***/ 63041: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Blob, File: NativeFile } = __nccwpck_require__(20181) +const { types } = __nccwpck_require__(39023) +const { kState } = __nccwpck_require__(89710) +const { isBlobLike } = __nccwpck_require__(15523) +const { webidl } = __nccwpck_require__(74222) +const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(94322) +const { kEnumerableProperty } = __nccwpck_require__(3440) +const encoder = new TextEncoder() + +class File extends Blob { + constructor (fileBits, fileName, options = {}) { + // The File constructor is invoked with two or three parameters, depending + // on whether the optional dictionary parameter is used. When the File() + // constructor is invoked, user agents must run the following steps: + webidl.argumentLengthCheck(arguments, 2, { header: 'File constructor' }) + + fileBits = webidl.converters['sequence'](fileBits) + fileName = webidl.converters.USVString(fileName) + options = webidl.converters.FilePropertyBag(options) + + // 1. Let bytes be the result of processing blob parts given fileBits and + // options. + // Note: Blob handles this for us + + // 2. Let n be the fileName argument to the constructor. + const n = fileName + + // 3. Process FilePropertyBag dictionary argument by running the following + // substeps: + + // 1. If the type member is provided and is not the empty string, let t + // be set to the type dictionary member. If t contains any characters + // outside the range U+0020 to U+007E, then set t to the empty string + // and return from these substeps. + // 2. Convert every character in t to ASCII lowercase. + let t = options.type + let d + + // eslint-disable-next-line no-labels + substep: { + if (t) { + t = parseMIMEType(t) + + if (t === 'failure') { + t = '' + // eslint-disable-next-line no-labels + break substep + } + + t = serializeAMimeType(t).toLowerCase() + } + + // 3. If the lastModified member is provided, let d be set to the + // lastModified dictionary member. If it is not provided, set d to the + // current date and time represented as the number of milliseconds since + // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). + d = options.lastModified + } + + // 4. Return a new File object F such that: + // F refers to the bytes byte sequence. + // F.size is set to the number of total bytes in bytes. + // F.name is set to n. + // F.type is set to t. + // F.lastModified is set to d. + + super(processBlobParts(fileBits, options), { type: t }) + this[kState] = { + name: n, + lastModified: d, + type: t + } + } + + get name () { + webidl.brandCheck(this, File) + + return this[kState].name + } + + get lastModified () { + webidl.brandCheck(this, File) + + return this[kState].lastModified + } + + get type () { + webidl.brandCheck(this, File) + + return this[kState].type + } +} + +class FileLike { + constructor (blobLike, fileName, options = {}) { + // TODO: argument idl type check + + // The File constructor is invoked with two or three parameters, depending + // on whether the optional dictionary parameter is used. When the File() + // constructor is invoked, user agents must run the following steps: + + // 1. Let bytes be the result of processing blob parts given fileBits and + // options. + + // 2. Let n be the fileName argument to the constructor. + const n = fileName + + // 3. Process FilePropertyBag dictionary argument by running the following + // substeps: + + // 1. If the type member is provided and is not the empty string, let t + // be set to the type dictionary member. If t contains any characters + // outside the range U+0020 to U+007E, then set t to the empty string + // and return from these substeps. + // TODO + const t = options.type + + // 2. Convert every character in t to ASCII lowercase. + // TODO + + // 3. If the lastModified member is provided, let d be set to the + // lastModified dictionary member. If it is not provided, set d to the + // current date and time represented as the number of milliseconds since + // the Unix Epoch (which is the equivalent of Date.now() [ECMA-262]). + const d = options.lastModified ?? Date.now() + + // 4. Return a new File object F such that: + // F refers to the bytes byte sequence. + // F.size is set to the number of total bytes in bytes. + // F.name is set to n. + // F.type is set to t. + // F.lastModified is set to d. + + this[kState] = { + blobLike, + name: n, + type: t, + lastModified: d + } + } + + stream (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.stream(...args) + } + + arrayBuffer (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.arrayBuffer(...args) + } + + slice (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.slice(...args) + } + + text (...args) { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.text(...args) + } + + get size () { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.size + } + + get type () { + webidl.brandCheck(this, FileLike) + + return this[kState].blobLike.type + } + + get name () { + webidl.brandCheck(this, FileLike) + + return this[kState].name + } + + get lastModified () { + webidl.brandCheck(this, FileLike) + + return this[kState].lastModified + } + + get [Symbol.toStringTag] () { + return 'File' + } +} + +Object.defineProperties(File.prototype, { + [Symbol.toStringTag]: { + value: 'File', + configurable: true + }, + name: kEnumerableProperty, + lastModified: kEnumerableProperty +}) + +webidl.converters.Blob = webidl.interfaceConverter(Blob) + +webidl.converters.BlobPart = function (V, opts) { + if (webidl.util.Type(V) === 'Object') { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if ( + ArrayBuffer.isView(V) || + types.isAnyArrayBuffer(V) + ) { + return webidl.converters.BufferSource(V, opts) + } + } + + return webidl.converters.USVString(V, opts) +} + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.BlobPart +) + +// https://www.w3.org/TR/FileAPI/#dfn-FilePropertyBag +webidl.converters.FilePropertyBag = webidl.dictionaryConverter([ + { + key: 'lastModified', + converter: webidl.converters['long long'], + get defaultValue () { + return Date.now() + } + }, + { + key: 'type', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'endings', + converter: (value) => { + value = webidl.converters.DOMString(value) + value = value.toLowerCase() + + if (value !== 'native') { + value = 'transparent' + } + + return value + }, + defaultValue: 'transparent' + } +]) + +/** + * @see https://www.w3.org/TR/FileAPI/#process-blob-parts + * @param {(NodeJS.TypedArray|Blob|string)[]} parts + * @param {{ type: string, endings: string }} options + */ +function processBlobParts (parts, options) { + // 1. Let bytes be an empty sequence of bytes. + /** @type {NodeJS.TypedArray[]} */ + const bytes = [] + + // 2. For each element in parts: + for (const element of parts) { + // 1. If element is a USVString, run the following substeps: + if (typeof element === 'string') { + // 1. Let s be element. + let s = element + + // 2. If the endings member of options is "native", set s + // to the result of converting line endings to native + // of element. + if (options.endings === 'native') { + s = convertLineEndingsNative(s) + } + + // 3. Append the result of UTF-8 encoding s to bytes. + bytes.push(encoder.encode(s)) + } else if ( + types.isAnyArrayBuffer(element) || + types.isTypedArray(element) + ) { + // 2. If element is a BufferSource, get a copy of the + // bytes held by the buffer source, and append those + // bytes to bytes. + if (!element.buffer) { // ArrayBuffer + bytes.push(new Uint8Array(element)) + } else { + bytes.push( + new Uint8Array(element.buffer, element.byteOffset, element.byteLength) + ) + } + } else if (isBlobLike(element)) { + // 3. If element is a Blob, append the bytes it represents + // to bytes. + bytes.push(element) + } + } + + // 3. Return bytes. + return bytes +} + +/** + * @see https://www.w3.org/TR/FileAPI/#convert-line-endings-to-native + * @param {string} s + */ +function convertLineEndingsNative (s) { + // 1. Let native line ending be be the code point U+000A LF. + let nativeLineEnding = '\n' + + // 2. If the underlying platform’s conventions are to + // represent newlines as a carriage return and line feed + // sequence, set native line ending to the code point + // U+000D CR followed by the code point U+000A LF. + if (process.platform === 'win32') { + nativeLineEnding = '\r\n' + } + + return s.replace(/\r?\n/g, nativeLineEnding) +} + +// If this function is moved to ./util.js, some tools (such as +// rollup) will warn about circular dependencies. See: +// https://github.com/nodejs/undici/issues/1629 +function isFileLike (object) { + return ( + (NativeFile && object instanceof NativeFile) || + object instanceof File || ( + object && + (typeof object.stream === 'function' || + typeof object.arrayBuffer === 'function') && + object[Symbol.toStringTag] === 'File' + ) + ) +} + +module.exports = { File, FileLike, isFileLike } + + +/***/ }), + +/***/ 43073: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { isBlobLike, toUSVString, makeIterator } = __nccwpck_require__(15523) +const { kState } = __nccwpck_require__(89710) +const { File: UndiciFile, FileLike, isFileLike } = __nccwpck_require__(63041) +const { webidl } = __nccwpck_require__(74222) +const { Blob, File: NativeFile } = __nccwpck_require__(20181) + +/** @type {globalThis['File']} */ +const File = NativeFile ?? UndiciFile + +// https://xhr.spec.whatwg.org/#formdata +class FormData { + constructor (form) { + if (form !== undefined) { + throw webidl.errors.conversionFailed({ + prefix: 'FormData constructor', + argument: 'Argument 1', + types: ['undefined'] + }) + } + + this[kState] = [] + } + + append (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.append' }) + + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } + + // 1. Let value be value if given; otherwise blobValue. + + name = webidl.converters.USVString(name) + value = isBlobLike(value) + ? webidl.converters.Blob(value, { strict: false }) + : webidl.converters.USVString(value) + filename = arguments.length === 3 + ? webidl.converters.USVString(filename) + : undefined + + // 2. Let entry be the result of creating an entry with + // name, value, and filename if given. + const entry = makeEntry(name, value, filename) + + // 3. Append entry to this’s entry list. + this[kState].push(entry) + } + + delete (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.delete' }) + + name = webidl.converters.USVString(name) + + // The delete(name) method steps are to remove all entries whose name + // is name from this’s entry list. + this[kState] = this[kState].filter(entry => entry.name !== name) + } + + get (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.get' }) + + name = webidl.converters.USVString(name) + + // 1. If there is no entry whose name is name in this’s entry list, + // then return null. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx === -1) { + return null + } + + // 2. Return the value of the first entry whose name is name from + // this’s entry list. + return this[kState][idx].value + } + + getAll (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.getAll' }) + + name = webidl.converters.USVString(name) + + // 1. If there is no entry whose name is name in this’s entry list, + // then return the empty list. + // 2. Return the values of all entries whose name is name, in order, + // from this’s entry list. + return this[kState] + .filter((entry) => entry.name === name) + .map((entry) => entry.value) + } + + has (name) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.has' }) + + name = webidl.converters.USVString(name) + + // The has(name) method steps are to return true if there is an entry + // whose name is name in this’s entry list; otherwise false. + return this[kState].findIndex((entry) => entry.name === name) !== -1 + } + + set (name, value, filename = undefined) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 2, { header: 'FormData.set' }) + + if (arguments.length === 3 && !isBlobLike(value)) { + throw new TypeError( + "Failed to execute 'set' on 'FormData': parameter 2 is not of type 'Blob'" + ) + } + + // The set(name, value) and set(name, blobValue, filename) method steps + // are: + + // 1. Let value be value if given; otherwise blobValue. + + name = webidl.converters.USVString(name) + value = isBlobLike(value) + ? webidl.converters.Blob(value, { strict: false }) + : webidl.converters.USVString(value) + filename = arguments.length === 3 + ? toUSVString(filename) + : undefined + + // 2. Let entry be the result of creating an entry with name, value, and + // filename if given. + const entry = makeEntry(name, value, filename) + + // 3. If there are entries in this’s entry list whose name is name, then + // replace the first such entry with entry and remove the others. + const idx = this[kState].findIndex((entry) => entry.name === name) + if (idx !== -1) { + this[kState] = [ + ...this[kState].slice(0, idx), + entry, + ...this[kState].slice(idx + 1).filter((entry) => entry.name !== name) + ] + } else { + // 4. Otherwise, append entry to this’s entry list. + this[kState].push(entry) + } + } + + entries () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'key+value' + ) + } + + keys () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'key' + ) + } + + values () { + webidl.brandCheck(this, FormData) + + return makeIterator( + () => this[kState].map(pair => [pair.name, pair.value]), + 'FormData', + 'value' + ) + } + + /** + * @param {(value: string, key: string, self: FormData) => void} callbackFn + * @param {unknown} thisArg + */ + forEach (callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, FormData) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FormData.forEach' }) + + if (typeof callbackFn !== 'function') { + throw new TypeError( + "Failed to execute 'forEach' on 'FormData': parameter 1 is not of type 'Function'." + ) + } + + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]) + } + } +} + +FormData.prototype[Symbol.iterator] = FormData.prototype.entries + +Object.defineProperties(FormData.prototype, { + [Symbol.toStringTag]: { + value: 'FormData', + configurable: true + } +}) + +/** + * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#create-an-entry + * @param {string} name + * @param {string|Blob} value + * @param {?string} filename + * @returns + */ +function makeEntry (name, value, filename) { + // 1. Set name to the result of converting name into a scalar value string. + // "To convert a string into a scalar value string, replace any surrogates + // with U+FFFD." + // see: https://nodejs.org/dist/latest-v18.x/docs/api/buffer.html#buftostringencoding-start-end + name = Buffer.from(name).toString('utf8') + + // 2. If value is a string, then set value to the result of converting + // value into a scalar value string. + if (typeof value === 'string') { + value = Buffer.from(value).toString('utf8') + } else { + // 3. Otherwise: + + // 1. If value is not a File object, then set value to a new File object, + // representing the same bytes, whose name attribute value is "blob" + if (!isFileLike(value)) { + value = value instanceof Blob + ? new File([value], 'blob', { type: value.type }) + : new FileLike(value, 'blob', { type: value.type }) + } + + // 2. If filename is given, then set value to a new File object, + // representing the same bytes, whose name attribute is filename. + if (filename !== undefined) { + /** @type {FilePropertyBag} */ + const options = { + type: value.type, + lastModified: value.lastModified + } + + value = (NativeFile && value instanceof NativeFile) || value instanceof UndiciFile + ? new File([value], filename, options) + : new FileLike(value, filename, options) + } + } + + // 4. Return an entry whose name is name and whose value is value. + return { name, value } +} + +module.exports = { FormData } + + +/***/ }), + +/***/ 75628: +/***/ ((module) => { + +"use strict"; + + +// In case of breaking changes, increase the version +// number to avoid conflicts. +const globalOrigin = Symbol.for('undici.globalOrigin.1') + +function getGlobalOrigin () { + return globalThis[globalOrigin] +} + +function setGlobalOrigin (newOrigin) { + if (newOrigin === undefined) { + Object.defineProperty(globalThis, globalOrigin, { + value: undefined, + writable: true, + enumerable: false, + configurable: false + }) + + return + } + + const parsedURL = new URL(newOrigin) + + if (parsedURL.protocol !== 'http:' && parsedURL.protocol !== 'https:') { + throw new TypeError(`Only http & https urls are allowed, received ${parsedURL.protocol}`) + } + + Object.defineProperty(globalThis, globalOrigin, { + value: parsedURL, + writable: true, + enumerable: false, + configurable: false + }) +} + +module.exports = { + getGlobalOrigin, + setGlobalOrigin +} + + +/***/ }), + +/***/ 26349: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch + + + +const { kHeadersList, kConstruct } = __nccwpck_require__(36443) +const { kGuard } = __nccwpck_require__(89710) +const { kEnumerableProperty } = __nccwpck_require__(3440) +const { + makeIterator, + isValidHeaderName, + isValidHeaderValue +} = __nccwpck_require__(15523) +const util = __nccwpck_require__(39023) +const { webidl } = __nccwpck_require__(74222) +const assert = __nccwpck_require__(42613) + +const kHeadersMap = Symbol('headers map') +const kHeadersSortedMap = Symbol('headers map sorted') + +/** + * @param {number} code + */ +function isHTTPWhiteSpaceCharCode (code) { + return code === 0x00a || code === 0x00d || code === 0x009 || code === 0x020 +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize + * @param {string} potentialValue + */ +function headerValueNormalize (potentialValue) { + // To normalize a byte sequence potentialValue, remove + // any leading and trailing HTTP whitespace bytes from + // potentialValue. + let i = 0; let j = potentialValue.length + + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i + + return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j) +} + +function fill (headers, object) { + // To fill a Headers object headers with a given object object, run these steps: + + // 1. If object is a sequence, then for each header in object: + // Note: webidl conversion to array has already been done. + if (Array.isArray(object)) { + for (let i = 0; i < object.length; ++i) { + const header = object[i] + // 1. If header does not contain exactly two items, then throw a TypeError. + if (header.length !== 2) { + throw webidl.errors.exception({ + header: 'Headers constructor', + message: `expected name/value pair to be length 2, found ${header.length}.` + }) + } + + // 2. Append (header’s first item, header’s second item) to headers. + appendHeader(headers, header[0], header[1]) + } + } else if (typeof object === 'object' && object !== null) { + // Note: null should throw + + // 2. Otherwise, object is a record, then for each key → value in object, + // append (key, value) to headers + const keys = Object.keys(object) + for (let i = 0; i < keys.length; ++i) { + appendHeader(headers, keys[i], object[keys[i]]) + } + } else { + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) + } +} + +/** + * @see https://fetch.spec.whatwg.org/#concept-headers-append + */ +function appendHeader (headers, name, value) { + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.append', + value, + type: 'header value' + }) + } + + // 3. If headers’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if headers’s guard is "request" and name is a + // forbidden header name, return. + // Note: undici does not implement forbidden header names + if (headers[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (headers[kGuard] === 'request-no-cors') { + // 5. Otherwise, if headers’s guard is "request-no-cors": + // TODO + } + + // 6. Otherwise, if headers’s guard is "response" and name is a + // forbidden response-header name, return. + + // 7. Append (name, value) to headers’s header list. + return headers[kHeadersList].append(name, value) + + // 8. If headers’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from headers +} + +class HeadersList { + /** @type {[string, string][]|null} */ + cookies = null + + constructor (init) { + if (init instanceof HeadersList) { + this[kHeadersMap] = new Map(init[kHeadersMap]) + this[kHeadersSortedMap] = init[kHeadersSortedMap] + this.cookies = init.cookies === null ? null : [...init.cookies] + } else { + this[kHeadersMap] = new Map(init) + this[kHeadersSortedMap] = null + } + } + + // https://fetch.spec.whatwg.org/#header-list-contains + contains (name) { + // A header list list contains a header name name if list + // contains a header whose name is a byte-case-insensitive + // match for name. + name = name.toLowerCase() + + return this[kHeadersMap].has(name) + } + + clear () { + this[kHeadersMap].clear() + this[kHeadersSortedMap] = null + this.cookies = null + } + + // https://fetch.spec.whatwg.org/#concept-header-list-append + append (name, value) { + this[kHeadersSortedMap] = null + + // 1. If list contains name, then set name to the first such + // header’s name. + const lowercaseName = name.toLowerCase() + const exists = this[kHeadersMap].get(lowercaseName) + + // 2. Append (name, value) to list. + if (exists) { + const delimiter = lowercaseName === 'cookie' ? '; ' : ', ' + this[kHeadersMap].set(lowercaseName, { + name: exists.name, + value: `${exists.value}${delimiter}${value}` + }) + } else { + this[kHeadersMap].set(lowercaseName, { name, value }) + } + + if (lowercaseName === 'set-cookie') { + this.cookies ??= [] + this.cookies.push(value) + } + } + + // https://fetch.spec.whatwg.org/#concept-header-list-set + set (name, value) { + this[kHeadersSortedMap] = null + const lowercaseName = name.toLowerCase() + + if (lowercaseName === 'set-cookie') { + this.cookies = [value] + } + + // 1. If list contains name, then set the value of + // the first such header to value and remove the + // others. + // 2. Otherwise, append header (name, value) to list. + this[kHeadersMap].set(lowercaseName, { name, value }) + } + + // https://fetch.spec.whatwg.org/#concept-header-list-delete + delete (name) { + this[kHeadersSortedMap] = null + + name = name.toLowerCase() + + if (name === 'set-cookie') { + this.cookies = null + } + + this[kHeadersMap].delete(name) + } + + // https://fetch.spec.whatwg.org/#concept-header-list-get + get (name) { + const value = this[kHeadersMap].get(name.toLowerCase()) + + // 1. If list does not contain name, then return null. + // 2. Return the values of all headers in list whose name + // is a byte-case-insensitive match for name, + // separated from each other by 0x2C 0x20, in order. + return value === undefined ? null : value.value + } + + * [Symbol.iterator] () { + // use the lowercased name + for (const [name, { value }] of this[kHeadersMap]) { + yield [name, value] + } + } + + get entries () { + const headers = {} + + if (this[kHeadersMap].size) { + for (const { name, value } of this[kHeadersMap].values()) { + headers[name] = value + } + } + + return headers + } +} + +// https://fetch.spec.whatwg.org/#headers-class +class Headers { + constructor (init = undefined) { + if (init === kConstruct) { + return + } + this[kHeadersList] = new HeadersList() + + // The new Headers(init) constructor steps are: + + // 1. Set this’s guard to "none". + this[kGuard] = 'none' + + // 2. If init is given, then fill this with init. + if (init !== undefined) { + init = webidl.converters.HeadersInit(init) + fill(this, init) + } + } + + // https://fetch.spec.whatwg.org/#dom-headers-append + append (name, value) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.append' }) + + name = webidl.converters.ByteString(name) + value = webidl.converters.ByteString(value) + + return appendHeader(this, name, value) + } + + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.delete' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.delete', + value: name, + type: 'header name' + }) + } + + // 2. If this’s guard is "immutable", then throw a TypeError. + // 3. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 4. Otherwise, if this’s guard is "request-no-cors", name + // is not a no-CORS-safelisted request-header name, and + // name is not a privileged no-CORS request-header name, + // return. + // 5. Otherwise, if this’s guard is "response" and name is + // a forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (this[kGuard] === 'request-no-cors') { + // TODO + } + + // 6. If this’s header list does not contain name, then + // return. + if (!this[kHeadersList].contains(name)) { + return + } + + // 7. Delete name from this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this. + this[kHeadersList].delete(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-get + get (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.get' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.get', + value: name, + type: 'header name' + }) + } + + // 2. Return the result of getting name from this’s header + // list. + return this[kHeadersList].get(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-has + has (name) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.has' }) + + name = webidl.converters.ByteString(name) + + // 1. If name is not a header name, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.has', + value: name, + type: 'header name' + }) + } + + // 2. Return true if this’s header list contains name; + // otherwise false. + return this[kHeadersList].contains(name) + } + + // https://fetch.spec.whatwg.org/#dom-headers-set + set (name, value) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 2, { header: 'Headers.set' }) + + name = webidl.converters.ByteString(name) + value = webidl.converters.ByteString(value) + + // 1. Normalize value. + value = headerValueNormalize(value) + + // 2. If name is not a header name or value is not a + // header value, then throw a TypeError. + if (!isValidHeaderName(name)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.set', + value: name, + type: 'header name' + }) + } else if (!isValidHeaderValue(value)) { + throw webidl.errors.invalidArgument({ + prefix: 'Headers.set', + value, + type: 'header value' + }) + } + + // 3. If this’s guard is "immutable", then throw a TypeError. + // 4. Otherwise, if this’s guard is "request" and name is a + // forbidden header name, return. + // 5. Otherwise, if this’s guard is "request-no-cors" and + // name/value is not a no-CORS-safelisted request-header, + // return. + // 6. Otherwise, if this’s guard is "response" and name is a + // forbidden response-header name, return. + // Note: undici does not implement forbidden header names + if (this[kGuard] === 'immutable') { + throw new TypeError('immutable') + } else if (this[kGuard] === 'request-no-cors') { + // TODO + } + + // 7. Set (name, value) in this’s header list. + // 8. If this’s guard is "request-no-cors", then remove + // privileged no-CORS request headers from this + this[kHeadersList].set(name, value) + } + + // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie + getSetCookie () { + webidl.brandCheck(this, Headers) + + // 1. If this’s header list does not contain `Set-Cookie`, then return « ». + // 2. Return the values of all headers in this’s header list whose name is + // a byte-case-insensitive match for `Set-Cookie`, in order. + + const list = this[kHeadersList].cookies + + if (list) { + return [...list] + } + + return [] + } + + // https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine + get [kHeadersSortedMap] () { + if (this[kHeadersList][kHeadersSortedMap]) { + return this[kHeadersList][kHeadersSortedMap] + } + + // 1. Let headers be an empty list of headers with the key being the name + // and value the value. + const headers = [] + + // 2. Let names be the result of convert header names to a sorted-lowercase + // set with all the names of the headers in list. + const names = [...this[kHeadersList]].sort((a, b) => a[0] < b[0] ? -1 : 1) + const cookies = this[kHeadersList].cookies + + // 3. For each name of names: + for (let i = 0; i < names.length; ++i) { + const [name, value] = names[i] + // 1. If name is `set-cookie`, then: + if (name === 'set-cookie') { + // 1. Let values be a list of all values of headers in list whose name + // is a byte-case-insensitive match for name, in order. + + // 2. For each value of values: + // 1. Append (name, value) to headers. + for (let j = 0; j < cookies.length; ++j) { + headers.push([name, cookies[j]]) + } + } else { + // 2. Otherwise: + + // 1. Let value be the result of getting name from list. + + // 2. Assert: value is non-null. + assert(value !== null) + + // 3. Append (name, value) to headers. + headers.push([name, value]) + } + } + + this[kHeadersList][kHeadersSortedMap] = headers + + // 4. Return headers. + return headers + } + + keys () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'key' + ) + } + + values () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'value') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'value' + ) + } + + entries () { + webidl.brandCheck(this, Headers) + + if (this[kGuard] === 'immutable') { + const value = this[kHeadersSortedMap] + return makeIterator(() => value, 'Headers', + 'key+value') + } + + return makeIterator( + () => [...this[kHeadersSortedMap].values()], + 'Headers', + 'key+value' + ) + } + + /** + * @param {(value: string, key: string, self: Headers) => void} callbackFn + * @param {unknown} thisArg + */ + forEach (callbackFn, thisArg = globalThis) { + webidl.brandCheck(this, Headers) + + webidl.argumentLengthCheck(arguments, 1, { header: 'Headers.forEach' }) + + if (typeof callbackFn !== 'function') { + throw new TypeError( + "Failed to execute 'forEach' on 'Headers': parameter 1 is not of type 'Function'." + ) + } + + for (const [key, value] of this) { + callbackFn.apply(thisArg, [value, key, this]) + } + } + + [Symbol.for('nodejs.util.inspect.custom')] () { + webidl.brandCheck(this, Headers) + + return this[kHeadersList] + } +} + +Headers.prototype[Symbol.iterator] = Headers.prototype.entries + +Object.defineProperties(Headers.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + getSetCookie: kEnumerableProperty, + keys: kEnumerableProperty, + values: kEnumerableProperty, + entries: kEnumerableProperty, + forEach: kEnumerableProperty, + [Symbol.iterator]: { enumerable: false }, + [Symbol.toStringTag]: { + value: 'Headers', + configurable: true + }, + [util.inspect.custom]: { + enumerable: false + } +}) + +webidl.converters.HeadersInit = function (V) { + if (webidl.util.Type(V) === 'Object') { + if (V[Symbol.iterator]) { + return webidl.converters['sequence>'](V) + } + + return webidl.converters['record'](V) + } + + throw webidl.errors.conversionFailed({ + prefix: 'Headers constructor', + argument: 'Argument 1', + types: ['sequence>', 'record'] + }) +} + +module.exports = { + fill, + Headers, + HeadersList +} + + +/***/ }), + +/***/ 12315: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +// https://github.com/Ethan-Arrowood/undici-fetch + + + +const { + Response, + makeNetworkError, + makeAppropriateNetworkError, + filterResponse, + makeResponse +} = __nccwpck_require__(48676) +const { Headers } = __nccwpck_require__(26349) +const { Request, makeRequest } = __nccwpck_require__(25194) +const zlib = __nccwpck_require__(43106) +const { + bytesMatch, + makePolicyContainer, + clonePolicyContainer, + requestBadPort, + TAOCheck, + appendRequestOriginHeader, + responseLocationURL, + requestCurrentURL, + setRequestReferrerPolicyOnRedirect, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + createOpaqueTimingInfo, + appendFetchMetadata, + corsCheck, + crossOriginResourcePolicyCheck, + determineRequestsReferrer, + coarsenedSharedCurrentTime, + createDeferredPromise, + isBlobLike, + sameOrigin, + isCancelled, + isAborted, + isErrorLike, + fullyReadBody, + readableStreamClose, + isomorphicEncode, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme +} = __nccwpck_require__(15523) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(89710) +const assert = __nccwpck_require__(42613) +const { safelyExtractBody } = __nccwpck_require__(8923) +const { + redirectStatusSet, + nullBodyStatus, + safeMethodsSet, + requestBodyHeader, + subresourceSet, + DOMException +} = __nccwpck_require__(87326) +const { kHeadersList } = __nccwpck_require__(36443) +const EE = __nccwpck_require__(24434) +const { Readable, pipeline } = __nccwpck_require__(2203) +const { addAbortListener, isErrored, isReadable, nodeMajor, nodeMinor } = __nccwpck_require__(3440) +const { dataURLProcessor, serializeAMimeType } = __nccwpck_require__(94322) +const { TransformStream } = __nccwpck_require__(63774) +const { getGlobalDispatcher } = __nccwpck_require__(32581) +const { webidl } = __nccwpck_require__(74222) +const { STATUS_CODES } = __nccwpck_require__(58611) +const GET_OR_HEAD = ['GET', 'HEAD'] + +/** @type {import('buffer').resolveObjectURL} */ +let resolveObjectURL +let ReadableStream = globalThis.ReadableStream + +class Fetch extends EE { + constructor (dispatcher) { + super() + + this.dispatcher = dispatcher + this.connection = null + this.dump = false + this.state = 'ongoing' + // 2 terminated listeners get added per request, + // but only 1 gets removed. If there are 20 redirects, + // 21 listeners will be added. + // See https://github.com/nodejs/undici/issues/1711 + // TODO (fix): Find and fix root cause for leaked listener. + this.setMaxListeners(21) + } + + terminate (reason) { + if (this.state !== 'ongoing') { + return + } + + this.state = 'terminated' + this.connection?.destroy(reason) + this.emit('terminated', reason) + } + + // https://fetch.spec.whatwg.org/#fetch-controller-abort + abort (error) { + if (this.state !== 'ongoing') { + return + } + + // 1. Set controller’s state to "aborted". + this.state = 'aborted' + + // 2. Let fallbackError be an "AbortError" DOMException. + // 3. Set error to fallbackError if it is not given. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') + } + + // 4. Let serializedError be StructuredSerialize(error). + // If that threw an exception, catch it, and let + // serializedError be StructuredSerialize(fallbackError). + + // 5. Set controller’s serialized abort reason to serializedError. + this.serializedAbortReason = error + + this.connection?.destroy(error) + this.emit('terminated', error) + } +} + +// https://fetch.spec.whatwg.org/#fetch-method +function fetch (input, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'globalThis.fetch' }) + + // 1. Let p be a new promise. + const p = createDeferredPromise() + + // 2. Let requestObject be the result of invoking the initial value of + // Request as constructor with input and init as arguments. If this throws + // an exception, reject p with it and return p. + let requestObject + + try { + requestObject = new Request(input, init) + } catch (e) { + p.reject(e) + return p.promise + } + + // 3. Let request be requestObject’s request. + const request = requestObject[kState] + + // 4. If requestObject’s signal’s aborted flag is set, then: + if (requestObject.signal.aborted) { + // 1. Abort the fetch() call with p, request, null, and + // requestObject’s signal’s abort reason. + abortFetch(p, request, null, requestObject.signal.reason) + + // 2. Return p. + return p.promise + } + + // 5. Let globalObject be request’s client’s global object. + const globalObject = request.client.globalObject + + // 6. If globalObject is a ServiceWorkerGlobalScope object, then set + // request’s service-workers mode to "none". + if (globalObject?.constructor?.name === 'ServiceWorkerGlobalScope') { + request.serviceWorkers = 'none' + } + + // 7. Let responseObject be null. + let responseObject = null + + // 8. Let relevantRealm be this’s relevant Realm. + const relevantRealm = null + + // 9. Let locallyAborted be false. + let locallyAborted = false + + // 10. Let controller be null. + let controller = null + + // 11. Add the following abort steps to requestObject’s signal: + addAbortListener( + requestObject.signal, + () => { + // 1. Set locallyAborted to true. + locallyAborted = true + + // 2. Assert: controller is non-null. + assert(controller != null) + + // 3. Abort controller with requestObject’s signal’s abort reason. + controller.abort(requestObject.signal.reason) + + // 4. Abort the fetch() call with p, request, responseObject, + // and requestObject’s signal’s abort reason. + abortFetch(p, request, responseObject, requestObject.signal.reason) + } + ) + + // 12. Let handleFetchDone given response response be to finalize and + // report timing with response, globalObject, and "fetch". + const handleFetchDone = (response) => + finalizeAndReportTiming(response, 'fetch') + + // 13. Set controller to the result of calling fetch given request, + // with processResponseEndOfBody set to handleFetchDone, and processResponse + // given response being these substeps: + + const processResponse = (response) => { + // 1. If locallyAborted is true, terminate these substeps. + if (locallyAborted) { + return Promise.resolve() + } + + // 2. If response’s aborted flag is set, then: + if (response.aborted) { + // 1. Let deserializedError be the result of deserialize a serialized + // abort reason given controller’s serialized abort reason and + // relevantRealm. + + // 2. Abort the fetch() call with p, request, responseObject, and + // deserializedError. + + abortFetch(p, request, responseObject, controller.serializedAbortReason) + return Promise.resolve() + } + + // 3. If response is a network error, then reject p with a TypeError + // and terminate these substeps. + if (response.type === 'error') { + p.reject( + Object.assign(new TypeError('fetch failed'), { cause: response.error }) + ) + return Promise.resolve() + } + + // 4. Set responseObject to the result of creating a Response object, + // given response, "immutable", and relevantRealm. + responseObject = new Response() + responseObject[kState] = response + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kHeadersList] = response.headersList + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + + // 5. Resolve p with responseObject. + p.resolve(responseObject) + } + + controller = fetching({ + request, + processResponseEndOfBody: handleFetchDone, + processResponse, + dispatcher: init.dispatcher ?? getGlobalDispatcher() // undici + }) + + // 14. Return p. + return p.promise +} + +// https://fetch.spec.whatwg.org/#finalize-and-report-timing +function finalizeAndReportTiming (response, initiatorType = 'other') { + // 1. If response is an aborted network error, then return. + if (response.type === 'error' && response.aborted) { + return + } + + // 2. If response’s URL list is null or empty, then return. + if (!response.urlList?.length) { + return + } + + // 3. Let originalURL be response’s URL list[0]. + const originalURL = response.urlList[0] + + // 4. Let timingInfo be response’s timing info. + let timingInfo = response.timingInfo + + // 5. Let cacheState be response’s cache state. + let cacheState = response.cacheState + + // 6. If originalURL’s scheme is not an HTTP(S) scheme, then return. + if (!urlIsHttpHttpsScheme(originalURL)) { + return + } + + // 7. If timingInfo is null, then return. + if (timingInfo === null) { + return + } + + // 8. If response’s timing allow passed flag is not set, then: + if (!response.timingAllowPassed) { + // 1. Set timingInfo to a the result of creating an opaque timing info for timingInfo. + timingInfo = createOpaqueTimingInfo({ + startTime: timingInfo.startTime + }) + + // 2. Set cacheState to the empty string. + cacheState = '' + } + + // 9. Set timingInfo’s end time to the coarsened shared current time + // given global’s relevant settings object’s cross-origin isolated + // capability. + // TODO: given global’s relevant settings object’s cross-origin isolated + // capability? + timingInfo.endTime = coarsenedSharedCurrentTime() + + // 10. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo + + // 11. Mark resource timing for timingInfo, originalURL, initiatorType, + // global, and cacheState. + markResourceTiming( + timingInfo, + originalURL, + initiatorType, + globalThis, + cacheState + ) +} + +// https://w3c.github.io/resource-timing/#dfn-mark-resource-timing +function markResourceTiming (timingInfo, originalURL, initiatorType, globalThis, cacheState) { + if (nodeMajor > 18 || (nodeMajor === 18 && nodeMinor >= 2)) { + performance.markResourceTiming(timingInfo, originalURL.href, initiatorType, globalThis, cacheState) + } +} + +// https://fetch.spec.whatwg.org/#abort-fetch +function abortFetch (p, request, responseObject, error) { + // Note: AbortSignal.reason was added in node v17.2.0 + // which would give us an undefined error to reject with. + // Remove this once node v16 is no longer supported. + if (!error) { + error = new DOMException('The operation was aborted.', 'AbortError') + } + + // 1. Reject promise with error. + p.reject(error) + + // 2. If request’s body is not null and is readable, then cancel request’s + // body with error. + if (request.body != null && isReadable(request.body?.stream)) { + request.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) + } + + // 3. If responseObject is null, then return. + if (responseObject == null) { + return + } + + // 4. Let response be responseObject’s response. + const response = responseObject[kState] + + // 5. If response’s body is not null and is readable, then error response’s + // body with error. + if (response.body != null && isReadable(response.body?.stream)) { + response.body.stream.cancel(error).catch((err) => { + if (err.code === 'ERR_INVALID_STATE') { + // Node bug? + return + } + throw err + }) + } +} + +// https://fetch.spec.whatwg.org/#fetching +function fetching ({ + request, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseEndOfBody, + processResponseConsumeBody, + useParallelQueue = false, + dispatcher // undici +}) { + // 1. Let taskDestination be null. + let taskDestination = null + + // 2. Let crossOriginIsolatedCapability be false. + let crossOriginIsolatedCapability = false + + // 3. If request’s client is non-null, then: + if (request.client != null) { + // 1. Set taskDestination to request’s client’s global object. + taskDestination = request.client.globalObject + + // 2. Set crossOriginIsolatedCapability to request’s client’s cross-origin + // isolated capability. + crossOriginIsolatedCapability = + request.client.crossOriginIsolatedCapability + } + + // 4. If useParallelQueue is true, then set taskDestination to the result of + // starting a new parallel queue. + // TODO + + // 5. Let timingInfo be a new fetch timing info whose start time and + // post-redirect start time are the coarsened shared current time given + // crossOriginIsolatedCapability. + const currenTime = coarsenedSharedCurrentTime(crossOriginIsolatedCapability) + const timingInfo = createOpaqueTimingInfo({ + startTime: currenTime + }) + + // 6. Let fetchParams be a new fetch params whose + // request is request, + // timing info is timingInfo, + // process request body chunk length is processRequestBodyChunkLength, + // process request end-of-body is processRequestEndOfBody, + // process response is processResponse, + // process response consume body is processResponseConsumeBody, + // process response end-of-body is processResponseEndOfBody, + // task destination is taskDestination, + // and cross-origin isolated capability is crossOriginIsolatedCapability. + const fetchParams = { + controller: new Fetch(dispatcher), + request, + timingInfo, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseConsumeBody, + processResponseEndOfBody, + taskDestination, + crossOriginIsolatedCapability + } + + // 7. If request’s body is a byte sequence, then set request’s body to + // request’s body as a body. + // NOTE: Since fetching is only called from fetch, body should already be + // extracted. + assert(!request.body || request.body.stream) + + // 8. If request’s window is "client", then set request’s window to request’s + // client, if request’s client’s global object is a Window object; otherwise + // "no-window". + if (request.window === 'client') { + // TODO: What if request.client is null? + request.window = + request.client?.globalObject?.constructor?.name === 'Window' + ? request.client + : 'no-window' + } + + // 9. If request’s origin is "client", then set request’s origin to request’s + // client’s origin. + if (request.origin === 'client') { + // TODO: What if request.client is null? + request.origin = request.client?.origin + } + + // 10. If all of the following conditions are true: + // TODO + + // 11. If request’s policy container is "client", then: + if (request.policyContainer === 'client') { + // 1. If request’s client is non-null, then set request’s policy + // container to a clone of request’s client’s policy container. [HTML] + if (request.client != null) { + request.policyContainer = clonePolicyContainer( + request.client.policyContainer + ) + } else { + // 2. Otherwise, set request’s policy container to a new policy + // container. + request.policyContainer = makePolicyContainer() + } + } + + // 12. If request’s header list does not contain `Accept`, then: + if (!request.headersList.contains('accept')) { + // 1. Let value be `*/*`. + const value = '*/*' + + // 2. A user agent should set value to the first matching statement, if + // any, switching on request’s destination: + // "document" + // "frame" + // "iframe" + // `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8` + // "image" + // `image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` + // "style" + // `text/css,*/*;q=0.1` + // TODO + + // 3. Append `Accept`/value to request’s header list. + request.headersList.append('accept', value) + } + + // 13. If request’s header list does not contain `Accept-Language`, then + // user agents should append `Accept-Language`/an appropriate value to + // request’s header list. + if (!request.headersList.contains('accept-language')) { + request.headersList.append('accept-language', '*') + } + + // 14. If request’s priority is null, then use request’s initiator and + // destination appropriately in setting request’s priority to a + // user-agent-defined object. + if (request.priority === null) { + // TODO + } + + // 15. If request is a subresource request, then: + if (subresourceSet.has(request.destination)) { + // TODO + } + + // 16. Run main fetch given fetchParams. + mainFetch(fetchParams) + .catch(err => { + fetchParams.controller.terminate(err) + }) + + // 17. Return fetchParam's controller + return fetchParams.controller +} + +// https://fetch.spec.whatwg.org/#concept-main-fetch +async function mainFetch (fetchParams, recursive = false) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. If request’s local-URLs-only flag is set and request’s current URL is + // not local, then set response to a network error. + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { + response = makeNetworkError('local URLs only') + } + + // 4. Run report Content Security Policy violations for request. + // TODO + + // 5. Upgrade request to a potentially trustworthy URL, if appropriate. + tryUpgradeRequestToAPotentiallyTrustworthyURL(request) + + // 6. If should request be blocked due to a bad port, should fetching request + // be blocked as mixed content, or should request be blocked by Content + // Security Policy returns blocked, then set response to a network error. + if (requestBadPort(request) === 'blocked') { + response = makeNetworkError('bad port') + } + // TODO: should fetching request be blocked as mixed content? + // TODO: should request be blocked by Content Security Policy? + + // 7. If request’s referrer policy is the empty string, then set request’s + // referrer policy to request’s policy container’s referrer policy. + if (request.referrerPolicy === '') { + request.referrerPolicy = request.policyContainer.referrerPolicy + } + + // 8. If request’s referrer is not "no-referrer", then set request’s + // referrer to the result of invoking determine request’s referrer. + if (request.referrer !== 'no-referrer') { + request.referrer = determineRequestsReferrer(request) + } + + // 9. Set request’s current URL’s scheme to "https" if all of the following + // conditions are true: + // - request’s current URL’s scheme is "http" + // - request’s current URL’s host is a domain + // - Matching request’s current URL’s host per Known HSTS Host Domain Name + // Matching results in either a superdomain match with an asserted + // includeSubDomains directive or a congruent match (with or without an + // asserted includeSubDomains directive). [HSTS] + // TODO + + // 10. If recursive is false, then run the remaining steps in parallel. + // TODO + + // 11. If response is null, then set response to the result of running + // the steps corresponding to the first matching statement: + if (response === null) { + response = await (async () => { + const currentURL = requestCurrentURL(request) + + if ( + // - request’s current URL’s origin is same origin with request’s origin, + // and request’s response tainting is "basic" + (sameOrigin(currentURL, request.url) && request.responseTainting === 'basic') || + // request’s current URL’s scheme is "data" + (currentURL.protocol === 'data:') || + // - request’s mode is "navigate" or "websocket" + (request.mode === 'navigate' || request.mode === 'websocket') + ) { + // 1. Set request’s response tainting to "basic". + request.responseTainting = 'basic' + + // 2. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) + } + + // request’s mode is "same-origin" + if (request.mode === 'same-origin') { + // 1. Return a network error. + return makeNetworkError('request mode cannot be "same-origin"') + } + + // request’s mode is "no-cors" + if (request.mode === 'no-cors') { + // 1. If request’s redirect mode is not "follow", then return a network + // error. + if (request.redirect !== 'follow') { + return makeNetworkError( + 'redirect mode cannot be "follow" for "no-cors" request' + ) + } + + // 2. Set request’s response tainting to "opaque". + request.responseTainting = 'opaque' + + // 3. Return the result of running scheme fetch given fetchParams. + return await schemeFetch(fetchParams) + } + + // request’s current URL’s scheme is not an HTTP(S) scheme + if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { + // Return a network error. + return makeNetworkError('URL scheme must be a HTTP(S) scheme') + } + + // - request’s use-CORS-preflight flag is set + // - request’s unsafe-request flag is set and either request’s method is + // not a CORS-safelisted method or CORS-unsafe request-header names with + // request’s header list is not empty + // 1. Set request’s response tainting to "cors". + // 2. Let corsWithPreflightResponse be the result of running HTTP fetch + // given fetchParams and true. + // 3. If corsWithPreflightResponse is a network error, then clear cache + // entries using request. + // 4. Return corsWithPreflightResponse. + // TODO + + // Otherwise + // 1. Set request’s response tainting to "cors". + request.responseTainting = 'cors' + + // 2. Return the result of running HTTP fetch given fetchParams. + return await httpFetch(fetchParams) + })() + } + + // 12. If recursive is true, then return response. + if (recursive) { + return response + } + + // 13. If response is not a network error and response is not a filtered + // response, then: + if (response.status !== 0 && !response.internalResponse) { + // If request’s response tainting is "cors", then: + if (request.responseTainting === 'cors') { + // 1. Let headerNames be the result of extracting header list values + // given `Access-Control-Expose-Headers` and response’s header list. + // TODO + // 2. If request’s credentials mode is not "include" and headerNames + // contains `*`, then set response’s CORS-exposed header-name list to + // all unique header names in response’s header list. + // TODO + // 3. Otherwise, if headerNames is not null or failure, then set + // response’s CORS-exposed header-name list to headerNames. + // TODO + } + + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (request.responseTainting === 'basic') { + response = filterResponse(response, 'basic') + } else if (request.responseTainting === 'cors') { + response = filterResponse(response, 'cors') + } else if (request.responseTainting === 'opaque') { + response = filterResponse(response, 'opaque') + } else { + assert(false) + } + } + + // 14. Let internalResponse be response, if response is a network error, + // and response’s internal response otherwise. + let internalResponse = + response.status === 0 ? response : response.internalResponse + + // 15. If internalResponse’s URL list is empty, then set it to a clone of + // request’s URL list. + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request.urlList) + } + + // 16. If request’s timing allow failed flag is unset, then set + // internalResponse’s timing allow passed flag. + if (!request.timingAllowFailed) { + response.timingAllowPassed = true + } + + // 17. If response is not a network error and any of the following returns + // blocked + // - should internalResponse to request be blocked as mixed content + // - should internalResponse to request be blocked by Content Security Policy + // - should internalResponse to request be blocked due to its MIME type + // - should internalResponse to request be blocked due to nosniff + // TODO + + // 18. If response’s type is "opaque", internalResponse’s status is 206, + // internalResponse’s range-requested flag is set, and request’s header + // list does not contain `Range`, then set response and internalResponse + // to a network error. + if ( + response.type === 'opaque' && + internalResponse.status === 206 && + internalResponse.rangeRequested && + !request.headers.contains('range') + ) { + response = internalResponse = makeNetworkError() + } + + // 19. If response is not a network error and either request’s method is + // `HEAD` or `CONNECT`, or internalResponse’s status is a null body status, + // set internalResponse’s body to null and disregard any enqueuing toward + // it (if any). + if ( + response.status !== 0 && + (request.method === 'HEAD' || + request.method === 'CONNECT' || + nullBodyStatus.includes(internalResponse.status)) + ) { + internalResponse.body = null + fetchParams.controller.dump = true + } + + // 20. If request’s integrity metadata is not the empty string, then: + if (request.integrity) { + // 1. Let processBodyError be this step: run fetch finale given fetchParams + // and a network error. + const processBodyError = (reason) => + fetchFinale(fetchParams, makeNetworkError(reason)) + + // 2. If request’s response tainting is "opaque", or response’s body is null, + // then run processBodyError and abort these steps. + if (request.responseTainting === 'opaque' || response.body == null) { + processBodyError(response.error) + return + } + + // 3. Let processBody given bytes be these steps: + const processBody = (bytes) => { + // 1. If bytes do not match request’s integrity metadata, + // then run processBodyError and abort these steps. [SRI] + if (!bytesMatch(bytes, request.integrity)) { + processBodyError('integrity mismatch') + return + } + + // 2. Set response’s body to bytes as a body. + response.body = safelyExtractBody(bytes)[0] + + // 3. Run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } + + // 4. Fully read response’s body given processBody and processBodyError. + await fullyReadBody(response.body, processBody, processBodyError) + } else { + // 21. Otherwise, run fetch finale given fetchParams and response. + fetchFinale(fetchParams, response) + } +} + +// https://fetch.spec.whatwg.org/#concept-scheme-fetch +// given a fetch params fetchParams +function schemeFetch (fetchParams) { + // Note: since the connection is destroyed on redirect, which sets fetchParams to a + // cancelled state, we do not want this condition to trigger *unless* there have been + // no redirects. See https://github.com/nodejs/undici/issues/1776 + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { + return Promise.resolve(makeAppropriateNetworkError(fetchParams)) + } + + // 2. Let request be fetchParams’s request. + const { request } = fetchParams + + const { protocol: scheme } = requestCurrentURL(request) + + // 3. Switch on request’s current URL’s scheme and run the associated steps: + switch (scheme) { + case 'about:': { + // If request’s current URL’s path is the string "blank", then return a new response + // whose status message is `OK`, header list is « (`Content-Type`, `text/html;charset=utf-8`) », + // and body is the empty byte sequence as a body. + + // Otherwise, return a network error. + return Promise.resolve(makeNetworkError('about scheme is not supported')) + } + case 'blob:': { + if (!resolveObjectURL) { + resolveObjectURL = (__nccwpck_require__(20181).resolveObjectURL) + } + + // 1. Let blobURLEntry be request’s current URL’s blob URL entry. + const blobURLEntry = requestCurrentURL(request) + + // https://github.com/web-platform-tests/wpt/blob/7b0ebaccc62b566a1965396e5be7bb2bc06f841f/FileAPI/url/resources/fetch-tests.js#L52-L56 + // Buffer.resolveObjectURL does not ignore URL queries. + if (blobURLEntry.search.length !== 0) { + return Promise.resolve(makeNetworkError('NetworkError when attempting to fetch resource.')) + } + + const blobURLEntryObject = resolveObjectURL(blobURLEntry.toString()) + + // 2. If request’s method is not `GET`, blobURLEntry is null, or blobURLEntry’s + // object is not a Blob object, then return a network error. + if (request.method !== 'GET' || !isBlobLike(blobURLEntryObject)) { + return Promise.resolve(makeNetworkError('invalid method')) + } + + // 3. Let bodyWithType be the result of safely extracting blobURLEntry’s object. + const bodyWithType = safelyExtractBody(blobURLEntryObject) + + // 4. Let body be bodyWithType’s body. + const body = bodyWithType[0] + + // 5. Let length be body’s length, serialized and isomorphic encoded. + const length = isomorphicEncode(`${body.length}`) + + // 6. Let type be bodyWithType’s type if it is non-null; otherwise the empty byte sequence. + const type = bodyWithType[1] ?? '' + + // 7. Return a new response whose status message is `OK`, header list is + // « (`Content-Length`, length), (`Content-Type`, type) », and body is body. + const response = makeResponse({ + statusText: 'OK', + headersList: [ + ['content-length', { name: 'Content-Length', value: length }], + ['content-type', { name: 'Content-Type', value: type }] + ] + }) + + response.body = body + + return Promise.resolve(response) + } + case 'data:': { + // 1. Let dataURLStruct be the result of running the + // data: URL processor on request’s current URL. + const currentURL = requestCurrentURL(request) + const dataURLStruct = dataURLProcessor(currentURL) + + // 2. If dataURLStruct is failure, then return a + // network error. + if (dataURLStruct === 'failure') { + return Promise.resolve(makeNetworkError('failed to fetch the data URL')) + } + + // 3. Let mimeType be dataURLStruct’s MIME type, serialized. + const mimeType = serializeAMimeType(dataURLStruct.mimeType) + + // 4. Return a response whose status message is `OK`, + // header list is « (`Content-Type`, mimeType) », + // and body is dataURLStruct’s body as a body. + return Promise.resolve(makeResponse({ + statusText: 'OK', + headersList: [ + ['content-type', { name: 'Content-Type', value: mimeType }] + ], + body: safelyExtractBody(dataURLStruct.body)[0] + })) + } + case 'file:': { + // For now, unfortunate as it is, file URLs are left as an exercise for the reader. + // When in doubt, return a network error. + return Promise.resolve(makeNetworkError('not implemented... yet...')) + } + case 'http:': + case 'https:': { + // Return the result of running HTTP fetch given fetchParams. + + return httpFetch(fetchParams) + .catch((err) => makeNetworkError(err)) + } + default: { + return Promise.resolve(makeNetworkError('unknown scheme')) + } + } +} + +// https://fetch.spec.whatwg.org/#finalize-response +function finalizeResponse (fetchParams, response) { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true + + // 2, If fetchParams’s process response done is not null, then queue a fetch + // task to run fetchParams’s process response done given response, with + // fetchParams’s task destination. + if (fetchParams.processResponseDone != null) { + queueMicrotask(() => fetchParams.processResponseDone(response)) + } +} + +// https://fetch.spec.whatwg.org/#fetch-finale +function fetchFinale (fetchParams, response) { + // 1. If response is a network error, then: + if (response.type === 'error') { + // 1. Set response’s URL list to « fetchParams’s request’s URL list[0] ». + response.urlList = [fetchParams.request.urlList[0]] + + // 2. Set response’s timing info to the result of creating an opaque timing + // info for fetchParams’s timing info. + response.timingInfo = createOpaqueTimingInfo({ + startTime: fetchParams.timingInfo.startTime + }) + } + + // 2. Let processResponseEndOfBody be the following steps: + const processResponseEndOfBody = () => { + // 1. Set fetchParams’s request’s done flag. + fetchParams.request.done = true + + // If fetchParams’s process response end-of-body is not null, + // then queue a fetch task to run fetchParams’s process response + // end-of-body given response with fetchParams’s task destination. + if (fetchParams.processResponseEndOfBody != null) { + queueMicrotask(() => fetchParams.processResponseEndOfBody(response)) + } + } + + // 3. If fetchParams’s process response is non-null, then queue a fetch task + // to run fetchParams’s process response given response, with fetchParams’s + // task destination. + if (fetchParams.processResponse != null) { + queueMicrotask(() => fetchParams.processResponse(response)) + } + + // 4. If response’s body is null, then run processResponseEndOfBody. + if (response.body == null) { + processResponseEndOfBody() + } else { + // 5. Otherwise: + + // 1. Let transformStream be a new a TransformStream. + + // 2. Let identityTransformAlgorithm be an algorithm which, given chunk, + // enqueues chunk in transformStream. + const identityTransformAlgorithm = (chunk, controller) => { + controller.enqueue(chunk) + } + + // 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm + // and flushAlgorithm set to processResponseEndOfBody. + const transformStream = new TransformStream({ + start () {}, + transform: identityTransformAlgorithm, + flush: processResponseEndOfBody + }, { + size () { + return 1 + } + }, { + size () { + return 1 + } + }) + + // 4. Set response’s body to the result of piping response’s body through transformStream. + response.body = { stream: response.body.stream.pipeThrough(transformStream) } + } + + // 6. If fetchParams’s process response consume body is non-null, then: + if (fetchParams.processResponseConsumeBody != null) { + // 1. Let processBody given nullOrBytes be this step: run fetchParams’s + // process response consume body given response and nullOrBytes. + const processBody = (nullOrBytes) => fetchParams.processResponseConsumeBody(response, nullOrBytes) + + // 2. Let processBodyError be this step: run fetchParams’s process + // response consume body given response and failure. + const processBodyError = (failure) => fetchParams.processResponseConsumeBody(response, failure) + + // 3. If response’s body is null, then queue a fetch task to run processBody + // given null, with fetchParams’s task destination. + if (response.body == null) { + queueMicrotask(() => processBody(null)) + } else { + // 4. Otherwise, fully read response’s body given processBody, processBodyError, + // and fetchParams’s task destination. + return fullyReadBody(response.body, processBody, processBodyError) + } + return Promise.resolve() + } +} + +// https://fetch.spec.whatwg.org/#http-fetch +async function httpFetch (fetchParams) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. Let actualResponse be null. + let actualResponse = null + + // 4. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 5. If request’s service-workers mode is "all", then: + if (request.serviceWorkers === 'all') { + // TODO + } + + // 6. If response is null, then: + if (response === null) { + // 1. If makeCORSPreflight is true and one of these conditions is true: + // TODO + + // 2. If request’s redirect mode is "follow", then set request’s + // service-workers mode to "none". + if (request.redirect === 'follow') { + request.serviceWorkers = 'none' + } + + // 3. Set response and actualResponse to the result of running + // HTTP-network-or-cache fetch given fetchParams. + actualResponse = response = await httpNetworkOrCacheFetch(fetchParams) + + // 4. If request’s response tainting is "cors" and a CORS check + // for request and response returns failure, then return a network error. + if ( + request.responseTainting === 'cors' && + corsCheck(request, response) === 'failure' + ) { + return makeNetworkError('cors failure') + } + + // 5. If the TAO check for request and response returns failure, then set + // request’s timing allow failed flag. + if (TAOCheck(request, response) === 'failure') { + request.timingAllowFailed = true + } + } + + // 7. If either request’s response tainting or response’s type + // is "opaque", and the cross-origin resource policy check with + // request’s origin, request’s client, request’s destination, + // and actualResponse returns blocked, then return a network error. + if ( + (request.responseTainting === 'opaque' || response.type === 'opaque') && + crossOriginResourcePolicyCheck( + request.origin, + request.client, + request.destination, + actualResponse + ) === 'blocked' + ) { + return makeNetworkError('blocked') + } + + // 8. If actualResponse’s status is a redirect status, then: + if (redirectStatusSet.has(actualResponse.status)) { + // 1. If actualResponse’s status is not 303, request’s body is not null, + // and the connection uses HTTP/2, then user agents may, and are even + // encouraged to, transmit an RST_STREAM frame. + // See, https://github.com/whatwg/fetch/issues/1288 + if (request.redirect !== 'manual') { + fetchParams.controller.connection.destroy() + } + + // 2. Switch on request’s redirect mode: + if (request.redirect === 'error') { + // Set response to a network error. + response = makeNetworkError('unexpected redirect') + } else if (request.redirect === 'manual') { + // Set response to an opaque-redirect filtered response whose internal + // response is actualResponse. + // NOTE(spec): On the web this would return an `opaqueredirect` response, + // but that doesn't make sense server side. + // See https://github.com/nodejs/undici/issues/1193. + response = actualResponse + } else if (request.redirect === 'follow') { + // Set response to the result of running HTTP-redirect fetch given + // fetchParams and response. + response = await httpRedirectFetch(fetchParams, response) + } else { + assert(false) + } + } + + // 9. Set response’s timing info to timingInfo. + response.timingInfo = timingInfo + + // 10. Return response. + return response +} + +// https://fetch.spec.whatwg.org/#http-redirect-fetch +function httpRedirectFetch (fetchParams, response) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let actualResponse be response, if response is not a filtered response, + // and response’s internal response otherwise. + const actualResponse = response.internalResponse + ? response.internalResponse + : response + + // 3. Let locationURL be actualResponse’s location URL given request’s current + // URL’s fragment. + let locationURL + + try { + locationURL = responseLocationURL( + actualResponse, + requestCurrentURL(request).hash + ) + + // 4. If locationURL is null, then return response. + if (locationURL == null) { + return response + } + } catch (err) { + // 5. If locationURL is failure, then return a network error. + return Promise.resolve(makeNetworkError(err)) + } + + // 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network + // error. + if (!urlIsHttpHttpsScheme(locationURL)) { + return Promise.resolve(makeNetworkError('URL scheme must be a HTTP(S) scheme')) + } + + // 7. If request’s redirect count is 20, then return a network error. + if (request.redirectCount === 20) { + return Promise.resolve(makeNetworkError('redirect count exceeded')) + } + + // 8. Increase request’s redirect count by 1. + request.redirectCount += 1 + + // 9. If request’s mode is "cors", locationURL includes credentials, and + // request’s origin is not same origin with locationURL’s origin, then return + // a network error. + if ( + request.mode === 'cors' && + (locationURL.username || locationURL.password) && + !sameOrigin(request, locationURL) + ) { + return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')) + } + + // 10. If request’s response tainting is "cors" and locationURL includes + // credentials, then return a network error. + if ( + request.responseTainting === 'cors' && + (locationURL.username || locationURL.password) + ) { + return Promise.resolve(makeNetworkError( + 'URL cannot contain credentials for request mode "cors"' + )) + } + + // 11. If actualResponse’s status is not 303, request’s body is non-null, + // and request’s body’s source is null, then return a network error. + if ( + actualResponse.status !== 303 && + request.body != null && + request.body.source == null + ) { + return Promise.resolve(makeNetworkError()) + } + + // 12. If one of the following is true + // - actualResponse’s status is 301 or 302 and request’s method is `POST` + // - actualResponse’s status is 303 and request’s method is not `GET` or `HEAD` + if ( + ([301, 302].includes(actualResponse.status) && request.method === 'POST') || + (actualResponse.status === 303 && + !GET_OR_HEAD.includes(request.method)) + ) { + // then: + // 1. Set request’s method to `GET` and request’s body to null. + request.method = 'GET' + request.body = null + + // 2. For each headerName of request-body-header name, delete headerName from + // request’s header list. + for (const headerName of requestBodyHeader) { + request.headersList.delete(headerName) + } + } + + // 13. If request’s current URL’s origin is not same origin with locationURL’s + // origin, then for each headerName of CORS non-wildcard request-header name, + // delete headerName from request’s header list. + if (!sameOrigin(requestCurrentURL(request), locationURL)) { + // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name + request.headersList.delete('authorization') + + // https://fetch.spec.whatwg.org/#authentication-entries + request.headersList.delete('proxy-authorization', true) + + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. + request.headersList.delete('cookie') + request.headersList.delete('host') + } + + // 14. If request’s body is non-null, then set request’s body to the first return + // value of safely extracting request’s body’s source. + if (request.body != null) { + assert(request.body.source != null) + request.body = safelyExtractBody(request.body.source)[0] + } + + // 15. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 16. Set timingInfo’s redirect end time and post-redirect start time to the + // coarsened shared current time given fetchParams’s cross-origin isolated + // capability. + timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = + coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability) + + // 17. If timingInfo’s redirect start time is 0, then set timingInfo’s + // redirect start time to timingInfo’s start time. + if (timingInfo.redirectStartTime === 0) { + timingInfo.redirectStartTime = timingInfo.startTime + } + + // 18. Append locationURL to request’s URL list. + request.urlList.push(locationURL) + + // 19. Invoke set request’s referrer policy on redirect on request and + // actualResponse. + setRequestReferrerPolicyOnRedirect(request, actualResponse) + + // 20. Return the result of running main fetch given fetchParams and true. + return mainFetch(fetchParams, true) +} + +// https://fetch.spec.whatwg.org/#http-network-or-cache-fetch +async function httpNetworkOrCacheFetch ( + fetchParams, + isAuthenticationFetch = false, + isNewConnectionFetch = false +) { + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let httpFetchParams be null. + let httpFetchParams = null + + // 3. Let httpRequest be null. + let httpRequest = null + + // 4. Let response be null. + let response = null + + // 5. Let storedResponse be null. + // TODO: cache + + // 6. Let httpCache be null. + const httpCache = null + + // 7. Let the revalidatingFlag be unset. + const revalidatingFlag = false + + // 8. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. If request’s window is "no-window" and request’s redirect mode is + // "error", then set httpFetchParams to fetchParams and httpRequest to + // request. + if (request.window === 'no-window' && request.redirect === 'error') { + httpFetchParams = fetchParams + httpRequest = request + } else { + // Otherwise: + + // 1. Set httpRequest to a clone of request. + httpRequest = makeRequest(request) + + // 2. Set httpFetchParams to a copy of fetchParams. + httpFetchParams = { ...fetchParams } + + // 3. Set httpFetchParams’s request to httpRequest. + httpFetchParams.request = httpRequest + } + + // 3. Let includeCredentials be true if one of + const includeCredentials = + request.credentials === 'include' || + (request.credentials === 'same-origin' && + request.responseTainting === 'basic') + + // 4. Let contentLength be httpRequest’s body’s length, if httpRequest’s + // body is non-null; otherwise null. + const contentLength = httpRequest.body ? httpRequest.body.length : null + + // 5. Let contentLengthHeaderValue be null. + let contentLengthHeaderValue = null + + // 6. If httpRequest’s body is null and httpRequest’s method is `POST` or + // `PUT`, then set contentLengthHeaderValue to `0`. + if ( + httpRequest.body == null && + ['POST', 'PUT'].includes(httpRequest.method) + ) { + contentLengthHeaderValue = '0' + } + + // 7. If contentLength is non-null, then set contentLengthHeaderValue to + // contentLength, serialized and isomorphic encoded. + if (contentLength != null) { + contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) + } + + // 8. If contentLengthHeaderValue is non-null, then append + // `Content-Length`/contentLengthHeaderValue to httpRequest’s header + // list. + if (contentLengthHeaderValue != null) { + httpRequest.headersList.append('content-length', contentLengthHeaderValue) + } + + // 9. If contentLengthHeaderValue is non-null, then append (`Content-Length`, + // contentLengthHeaderValue) to httpRequest’s header list. + + // 10. If contentLength is non-null and httpRequest’s keepalive is true, + // then: + if (contentLength != null && httpRequest.keepalive) { + // NOTE: keepalive is a noop outside of browser context. + } + + // 11. If httpRequest’s referrer is a URL, then append + // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, + // to httpRequest’s header list. + if (httpRequest.referrer instanceof URL) { + httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href)) + } + + // 12. Append a request `Origin` header for httpRequest. + appendRequestOriginHeader(httpRequest) + + // 13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA] + appendFetchMetadata(httpRequest) + + // 14. If httpRequest’s header list does not contain `User-Agent`, then + // user agents should append `User-Agent`/default `User-Agent` value to + // httpRequest’s header list. + if (!httpRequest.headersList.contains('user-agent')) { + httpRequest.headersList.append('user-agent', typeof esbuildDetection === 'undefined' ? 'undici' : 'node') + } + + // 15. If httpRequest’s cache mode is "default" and httpRequest’s header + // list contains `If-Modified-Since`, `If-None-Match`, + // `If-Unmodified-Since`, `If-Match`, or `If-Range`, then set + // httpRequest’s cache mode to "no-store". + if ( + httpRequest.cache === 'default' && + (httpRequest.headersList.contains('if-modified-since') || + httpRequest.headersList.contains('if-none-match') || + httpRequest.headersList.contains('if-unmodified-since') || + httpRequest.headersList.contains('if-match') || + httpRequest.headersList.contains('if-range')) + ) { + httpRequest.cache = 'no-store' + } + + // 16. If httpRequest’s cache mode is "no-cache", httpRequest’s prevent + // no-cache cache-control header modification flag is unset, and + // httpRequest’s header list does not contain `Cache-Control`, then append + // `Cache-Control`/`max-age=0` to httpRequest’s header list. + if ( + httpRequest.cache === 'no-cache' && + !httpRequest.preventNoCacheCacheControlHeaderModification && + !httpRequest.headersList.contains('cache-control') + ) { + httpRequest.headersList.append('cache-control', 'max-age=0') + } + + // 17. If httpRequest’s cache mode is "no-store" or "reload", then: + if (httpRequest.cache === 'no-store' || httpRequest.cache === 'reload') { + // 1. If httpRequest’s header list does not contain `Pragma`, then append + // `Pragma`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('pragma')) { + httpRequest.headersList.append('pragma', 'no-cache') + } + + // 2. If httpRequest’s header list does not contain `Cache-Control`, + // then append `Cache-Control`/`no-cache` to httpRequest’s header list. + if (!httpRequest.headersList.contains('cache-control')) { + httpRequest.headersList.append('cache-control', 'no-cache') + } + } + + // 18. If httpRequest’s header list contains `Range`, then append + // `Accept-Encoding`/`identity` to httpRequest’s header list. + if (httpRequest.headersList.contains('range')) { + httpRequest.headersList.append('accept-encoding', 'identity') + } + + // 19. Modify httpRequest’s header list per HTTP. Do not append a given + // header if httpRequest’s header list contains that header’s name. + // TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129 + if (!httpRequest.headersList.contains('accept-encoding')) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { + httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate') + } else { + httpRequest.headersList.append('accept-encoding', 'gzip, deflate') + } + } + + httpRequest.headersList.delete('host') + + // 20. If includeCredentials is true, then: + if (includeCredentials) { + // 1. If the user agent is not configured to block cookies for httpRequest + // (see section 7 of [COOKIES]), then: + // TODO: credentials + // 2. If httpRequest’s header list does not contain `Authorization`, then: + // TODO: credentials + } + + // 21. If there’s a proxy-authentication entry, use it as appropriate. + // TODO: proxy-authentication + + // 22. Set httpCache to the result of determining the HTTP cache + // partition, given httpRequest. + // TODO: cache + + // 23. If httpCache is null, then set httpRequest’s cache mode to + // "no-store". + if (httpCache == null) { + httpRequest.cache = 'no-store' + } + + // 24. If httpRequest’s cache mode is neither "no-store" nor "reload", + // then: + if (httpRequest.mode !== 'no-store' && httpRequest.mode !== 'reload') { + // TODO: cache + } + + // 9. If aborted, then return the appropriate network error for fetchParams. + // TODO + + // 10. If response is null, then: + if (response == null) { + // 1. If httpRequest’s cache mode is "only-if-cached", then return a + // network error. + if (httpRequest.mode === 'only-if-cached') { + return makeNetworkError('only if cached') + } + + // 2. Let forwardResponse be the result of running HTTP-network fetch + // given httpFetchParams, includeCredentials, and isNewConnectionFetch. + const forwardResponse = await httpNetworkFetch( + httpFetchParams, + includeCredentials, + isNewConnectionFetch + ) + + // 3. If httpRequest’s method is unsafe and forwardResponse’s status is + // in the range 200 to 399, inclusive, invalidate appropriate stored + // responses in httpCache, as per the "Invalidation" chapter of HTTP + // Caching, and set storedResponse to null. [HTTP-CACHING] + if ( + !safeMethodsSet.has(httpRequest.method) && + forwardResponse.status >= 200 && + forwardResponse.status <= 399 + ) { + // TODO: cache + } + + // 4. If the revalidatingFlag is set and forwardResponse’s status is 304, + // then: + if (revalidatingFlag && forwardResponse.status === 304) { + // TODO: cache + } + + // 5. If response is null, then: + if (response == null) { + // 1. Set response to forwardResponse. + response = forwardResponse + + // 2. Store httpRequest and forwardResponse in httpCache, as per the + // "Storing Responses in Caches" chapter of HTTP Caching. [HTTP-CACHING] + // TODO: cache + } + } + + // 11. Set response’s URL list to a clone of httpRequest’s URL list. + response.urlList = [...httpRequest.urlList] + + // 12. If httpRequest’s header list contains `Range`, then set response’s + // range-requested flag. + if (httpRequest.headersList.contains('range')) { + response.rangeRequested = true + } + + // 13. Set response’s request-includes-credentials to includeCredentials. + response.requestIncludesCredentials = includeCredentials + + // 14. If response’s status is 401, httpRequest’s response tainting is not + // "cors", includeCredentials is true, and request’s window is an environment + // settings object, then: + // TODO + + // 15. If response’s status is 407, then: + if (response.status === 407) { + // 1. If request’s window is "no-window", then return a network error. + if (request.window === 'no-window') { + return makeNetworkError() + } + + // 2. ??? + + // 3. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } + + // 4. Prompt the end user as appropriate in request’s window and store + // the result as a proxy-authentication entry. [HTTP-AUTH] + // TODO: Invoke some kind of callback? + + // 5. Set response to the result of running HTTP-network-or-cache fetch given + // fetchParams. + // TODO + return makeNetworkError('proxy authentication required') + } + + // 16. If all of the following are true + if ( + // response’s status is 421 + response.status === 421 && + // isNewConnectionFetch is false + !isNewConnectionFetch && + // request’s body is null, or request’s body is non-null and request’s body’s source is non-null + (request.body == null || request.body.source != null) + ) { + // then: + + // 1. If fetchParams is canceled, then return the appropriate network error for fetchParams. + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams) + } + + // 2. Set response to the result of running HTTP-network-or-cache + // fetch given fetchParams, isAuthenticationFetch, and true. + + // TODO (spec): The spec doesn't specify this but we need to cancel + // the active response before we can start a new one. + // https://github.com/whatwg/fetch/issues/1293 + fetchParams.controller.connection.destroy() + + response = await httpNetworkOrCacheFetch( + fetchParams, + isAuthenticationFetch, + true + ) + } + + // 17. If isAuthenticationFetch is true, then create an authentication entry + if (isAuthenticationFetch) { + // TODO + } + + // 18. Return response. + return response +} + +// https://fetch.spec.whatwg.org/#http-network-fetch +async function httpNetworkFetch ( + fetchParams, + includeCredentials = false, + forceNewConnection = false +) { + assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed) + + fetchParams.controller.connection = { + abort: null, + destroyed: false, + destroy (err) { + if (!this.destroyed) { + this.destroyed = true + this.abort?.(err ?? new DOMException('The operation was aborted.', 'AbortError')) + } + } + } + + // 1. Let request be fetchParams’s request. + const request = fetchParams.request + + // 2. Let response be null. + let response = null + + // 3. Let timingInfo be fetchParams’s timing info. + const timingInfo = fetchParams.timingInfo + + // 4. Let httpCache be the result of determining the HTTP cache partition, + // given request. + // TODO: cache + const httpCache = null + + // 5. If httpCache is null, then set request’s cache mode to "no-store". + if (httpCache == null) { + request.cache = 'no-store' + } + + // 6. Let networkPartitionKey be the result of determining the network + // partition key given request. + // TODO + + // 7. Let newConnection be "yes" if forceNewConnection is true; otherwise + // "no". + const newConnection = forceNewConnection ? 'yes' : 'no' // eslint-disable-line no-unused-vars + + // 8. Switch on request’s mode: + if (request.mode === 'websocket') { + // Let connection be the result of obtaining a WebSocket connection, + // given request’s current URL. + // TODO + } else { + // Let connection be the result of obtaining a connection, given + // networkPartitionKey, request’s current URL’s origin, + // includeCredentials, and forceNewConnection. + // TODO + } + + // 9. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. If connection is failure, then return a network error. + + // 2. Set timingInfo’s final connection timing info to the result of + // calling clamp and coarsen connection timing info with connection’s + // timing info, timingInfo’s post-redirect start time, and fetchParams’s + // cross-origin isolated capability. + + // 3. If connection is not an HTTP/2 connection, request’s body is non-null, + // and request’s body’s source is null, then append (`Transfer-Encoding`, + // `chunked`) to request’s header list. + + // 4. Set timingInfo’s final network-request start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated + // capability. + + // 5. Set response to the result of making an HTTP request over connection + // using request with the following caveats: + + // - Follow the relevant requirements from HTTP. [HTTP] [HTTP-SEMANTICS] + // [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] + + // - If request’s body is non-null, and request’s body’s source is null, + // then the user agent may have a buffer of up to 64 kibibytes and store + // a part of request’s body in that buffer. If the user agent reads from + // request’s body beyond that buffer’s size and the user agent needs to + // resend request, then instead return a network error. + + // - Set timingInfo’s final network-response start time to the coarsened + // shared current time given fetchParams’s cross-origin isolated capability, + // immediately after the user agent’s HTTP parser receives the first byte + // of the response (e.g., frame header bytes for HTTP/2 or response status + // line for HTTP/1.x). + + // - Wait until all the headers are transmitted. + + // - Any responses whose status is in the range 100 to 199, inclusive, + // and is not 101, are to be ignored, except for the purposes of setting + // timingInfo’s final network-response start time above. + + // - If request’s header list contains `Transfer-Encoding`/`chunked` and + // response is transferred via HTTP/1.0 or older, then return a network + // error. + + // - If the HTTP request results in a TLS client certificate dialog, then: + + // 1. If request’s window is an environment settings object, make the + // dialog available in request’s window. + + // 2. Otherwise, return a network error. + + // To transmit request’s body body, run these steps: + let requestBody = null + // 1. If body is null and fetchParams’s process request end-of-body is + // non-null, then queue a fetch task given fetchParams’s process request + // end-of-body and fetchParams’s task destination. + if (request.body == null && fetchParams.processRequestEndOfBody) { + queueMicrotask(() => fetchParams.processRequestEndOfBody()) + } else if (request.body != null) { + // 2. Otherwise, if body is non-null: + + // 1. Let processBodyChunk given bytes be these steps: + const processBodyChunk = async function * (bytes) { + // 1. If the ongoing fetch is terminated, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. Run this step in parallel: transmit bytes. + yield bytes + + // 3. If fetchParams’s process request body is non-null, then run + // fetchParams’s process request body given bytes’s length. + fetchParams.processRequestBodyChunkLength?.(bytes.byteLength) + } + + // 2. Let processEndOfBody be these steps: + const processEndOfBody = () => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. If fetchParams’s process request end-of-body is non-null, + // then run fetchParams’s process request end-of-body. + if (fetchParams.processRequestEndOfBody) { + fetchParams.processRequestEndOfBody() + } + } + + // 3. Let processBodyError given e be these steps: + const processBodyError = (e) => { + // 1. If fetchParams is canceled, then abort these steps. + if (isCancelled(fetchParams)) { + return + } + + // 2. If e is an "AbortError" DOMException, then abort fetchParams’s controller. + if (e.name === 'AbortError') { + fetchParams.controller.abort() + } else { + fetchParams.controller.terminate(e) + } + } + + // 4. Incrementally read request’s body given processBodyChunk, processEndOfBody, + // processBodyError, and fetchParams’s task destination. + requestBody = (async function * () { + try { + for await (const bytes of request.body.stream) { + yield * processBodyChunk(bytes) + } + processEndOfBody() + } catch (err) { + processBodyError(err) + } + })() + } + + try { + // socket is only provided for websockets + const { body, status, statusText, headersList, socket } = await dispatch({ body: requestBody }) + + if (socket) { + response = makeResponse({ status, statusText, headersList, socket }) + } else { + const iterator = body[Symbol.asyncIterator]() + fetchParams.controller.next = () => iterator.next() + + response = makeResponse({ status, statusText, headersList }) + } + } catch (err) { + // 10. If aborted, then: + if (err.name === 'AbortError') { + // 1. If connection uses HTTP/2, then transmit an RST_STREAM frame. + fetchParams.controller.connection.destroy() + + // 2. Return the appropriate network error for fetchParams. + return makeAppropriateNetworkError(fetchParams, err) + } + + return makeNetworkError(err) + } + + // 11. Let pullAlgorithm be an action that resumes the ongoing fetch + // if it is suspended. + const pullAlgorithm = () => { + fetchParams.controller.resume() + } + + // 12. Let cancelAlgorithm be an algorithm that aborts fetchParams’s + // controller with reason, given reason. + const cancelAlgorithm = (reason) => { + fetchParams.controller.abort(reason) + } + + // 13. Let highWaterMark be a non-negative, non-NaN number, chosen by + // the user agent. + // TODO + + // 14. Let sizeAlgorithm be an algorithm that accepts a chunk object + // and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent. + // TODO + + // 15. Let stream be a new ReadableStream. + // 16. Set up stream with pullAlgorithm set to pullAlgorithm, + // cancelAlgorithm set to cancelAlgorithm, highWaterMark set to + // highWaterMark, and sizeAlgorithm set to sizeAlgorithm. + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + const stream = new ReadableStream( + { + async start (controller) { + fetchParams.controller.controller = controller + }, + async pull (controller) { + await pullAlgorithm(controller) + }, + async cancel (reason) { + await cancelAlgorithm(reason) + } + }, + { + highWaterMark: 0, + size () { + return 1 + } + } + ) + + // 17. Run these steps, but abort when the ongoing fetch is terminated: + + // 1. Set response’s body to a new body whose stream is stream. + response.body = { stream } + + // 2. If response is not a network error and request’s cache mode is + // not "no-store", then update response in httpCache for request. + // TODO + + // 3. If includeCredentials is true and the user agent is not configured + // to block cookies for request (see section 7 of [COOKIES]), then run the + // "set-cookie-string" parsing algorithm (see section 5.2 of [COOKIES]) on + // the value of each header whose name is a byte-case-insensitive match for + // `Set-Cookie` in response’s header list, if any, and request’s current URL. + // TODO + + // 18. If aborted, then: + // TODO + + // 19. Run these steps in parallel: + + // 1. Run these steps, but abort when fetchParams is canceled: + fetchParams.controller.on('terminated', onAborted) + fetchParams.controller.resume = async () => { + // 1. While true + while (true) { + // 1-3. See onData... + + // 4. Set bytes to the result of handling content codings given + // codings and bytes. + let bytes + let isFailure + try { + const { done, value } = await fetchParams.controller.next() + + if (isAborted(fetchParams)) { + break + } + + bytes = done ? undefined : value + } catch (err) { + if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { + // zlib doesn't like empty streams. + bytes = undefined + } else { + bytes = err + + // err may be propagated from the result of calling readablestream.cancel, + // which might not be an error. https://github.com/nodejs/undici/issues/2009 + isFailure = true + } + } + + if (bytes === undefined) { + // 2. Otherwise, if the bytes transmission for response’s message + // body is done normally and stream is readable, then close + // stream, finalize response for fetchParams and response, and + // abort these in-parallel steps. + readableStreamClose(fetchParams.controller.controller) + + finalizeResponse(fetchParams, response) + + return + } + + // 5. Increase timingInfo’s decoded body size by bytes’s length. + timingInfo.decodedBodySize += bytes?.byteLength ?? 0 + + // 6. If bytes is failure, then terminate fetchParams’s controller. + if (isFailure) { + fetchParams.controller.terminate(bytes) + return + } + + // 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes + // into stream. + fetchParams.controller.controller.enqueue(new Uint8Array(bytes)) + + // 8. If stream is errored, then terminate the ongoing fetch. + if (isErrored(stream)) { + fetchParams.controller.terminate() + return + } + + // 9. If stream doesn’t need more data ask the user agent to suspend + // the ongoing fetch. + if (!fetchParams.controller.controller.desiredSize) { + return + } + } + } + + // 2. If aborted, then: + function onAborted (reason) { + // 2. If fetchParams is aborted, then: + if (isAborted(fetchParams)) { + // 1. Set response’s aborted flag. + response.aborted = true + + // 2. If stream is readable, then error stream with the result of + // deserialize a serialized abort reason given fetchParams’s + // controller’s serialized abort reason and an + // implementation-defined realm. + if (isReadable(stream)) { + fetchParams.controller.controller.error( + fetchParams.controller.serializedAbortReason + ) + } + } else { + // 3. Otherwise, if stream is readable, error stream with a TypeError. + if (isReadable(stream)) { + fetchParams.controller.controller.error(new TypeError('terminated', { + cause: isErrorLike(reason) ? reason : undefined + })) + } + } + + // 4. If connection uses HTTP/2, then transmit an RST_STREAM frame. + // 5. Otherwise, the user agent should close connection unless it would be bad for performance to do so. + fetchParams.controller.connection.destroy() + } + + // 20. Return response. + return response + + async function dispatch ({ body }) { + const url = requestCurrentURL(request) + /** @type {import('../..').Agent} */ + const agent = fetchParams.controller.dispatcher + + return new Promise((resolve, reject) => agent.dispatch( + { + path: url.pathname + url.search, + origin: url.origin, + method: request.method, + body: fetchParams.controller.dispatcher.isMockActive ? request.body && (request.body.source || request.body.stream) : body, + headers: request.headersList.entries, + maxRedirections: 0, + upgrade: request.mode === 'websocket' ? 'websocket' : undefined + }, + { + body: null, + abort: null, + + onConnect (abort) { + // TODO (fix): Do we need connection here? + const { connection } = fetchParams.controller + + if (connection.destroyed) { + abort(new DOMException('The operation was aborted.', 'AbortError')) + } else { + fetchParams.controller.on('terminated', abort) + this.abort = connection.abort = abort + } + }, + + onHeaders (status, headersList, resume, statusText) { + if (status < 200) { + return + } + + let codings = [] + let location = '' + + const headers = new Headers() + + // For H2, the headers are a plain JS object + // We distinguish between them and iterate accordingly + if (Array.isArray(headersList)) { + for (let n = 0; n < headersList.length; n += 2) { + const key = headersList[n + 0].toString('latin1') + const val = headersList[n + 1].toString('latin1') + if (key.toLowerCase() === 'content-encoding') { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + // "All content-coding values are case-insensitive..." + codings = val.toLowerCase().split(',').map((x) => x.trim()) + } else if (key.toLowerCase() === 'location') { + location = val + } + + headers[kHeadersList].append(key, val) + } + } else { + const keys = Object.keys(headersList) + for (const key of keys) { + const val = headersList[key] + if (key.toLowerCase() === 'content-encoding') { + // https://www.rfc-editor.org/rfc/rfc7231#section-3.1.2.1 + // "All content-coding values are case-insensitive..." + codings = val.toLowerCase().split(',').map((x) => x.trim()).reverse() + } else if (key.toLowerCase() === 'location') { + location = val + } + + headers[kHeadersList].append(key, val) + } + } + + this.body = new Readable({ read: resume }) + + const decoders = [] + + const willFollow = request.redirect === 'follow' && + location && + redirectStatusSet.has(status) + + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + if (request.method !== 'HEAD' && request.method !== 'CONNECT' && !nullBodyStatus.includes(status) && !willFollow) { + for (const coding of codings) { + // https://www.rfc-editor.org/rfc/rfc9112.html#section-7.2 + if (coding === 'x-gzip' || coding === 'gzip') { + decoders.push(zlib.createGunzip({ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })) + } else if (coding === 'deflate') { + decoders.push(zlib.createInflate()) + } else if (coding === 'br') { + decoders.push(zlib.createBrotliDecompress()) + } else { + decoders.length = 0 + break + } + } + } + + resolve({ + status, + statusText, + headersList: headers[kHeadersList], + body: decoders.length + ? pipeline(this.body, ...decoders, () => { }) + : this.body.on('error', () => {}) + }) + + return true + }, + + onData (chunk) { + if (fetchParams.controller.dump) { + return + } + + // 1. If one or more bytes have been transmitted from response’s + // message body, then: + + // 1. Let bytes be the transmitted bytes. + const bytes = chunk + + // 2. Let codings be the result of extracting header list values + // given `Content-Encoding` and response’s header list. + // See pullAlgorithm. + + // 3. Increase timingInfo’s encoded body size by bytes’s length. + timingInfo.encodedBodySize += bytes.byteLength + + // 4. See pullAlgorithm... + + return this.body.push(bytes) + }, + + onComplete () { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } + + fetchParams.controller.ended = true + + this.body.push(null) + }, + + onError (error) { + if (this.abort) { + fetchParams.controller.off('terminated', this.abort) + } + + this.body?.destroy(error) + + fetchParams.controller.terminate(error) + + reject(error) + }, + + onUpgrade (status, headersList, socket) { + if (status !== 101) { + return + } + + const headers = new Headers() + + for (let n = 0; n < headersList.length; n += 2) { + const key = headersList[n + 0].toString('latin1') + const val = headersList[n + 1].toString('latin1') + + headers[kHeadersList].append(key, val) + } + + resolve({ + status, + statusText: STATUS_CODES[status], + headersList: headers[kHeadersList], + socket + }) + + return true + } + } + )) + } +} + +module.exports = { + fetch, + Fetch, + fetching, + finalizeAndReportTiming +} + + +/***/ }), + +/***/ 25194: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/* globals AbortController */ + + + +const { extractBody, mixinBody, cloneBody } = __nccwpck_require__(8923) +const { Headers, fill: fillHeaders, HeadersList } = __nccwpck_require__(26349) +const { FinalizationRegistry } = __nccwpck_require__(13194)() +const util = __nccwpck_require__(3440) +const { + isValidHTTPToken, + sameOrigin, + normalizeMethod, + makePolicyContainer, + normalizeMethodRecord +} = __nccwpck_require__(15523) +const { + forbiddenMethodsSet, + corsSafeListedMethodsSet, + referrerPolicy, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + requestDuplex +} = __nccwpck_require__(87326) +const { kEnumerableProperty } = util +const { kHeaders, kSignal, kState, kGuard, kRealm } = __nccwpck_require__(89710) +const { webidl } = __nccwpck_require__(74222) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { URLSerializer } = __nccwpck_require__(94322) +const { kHeadersList, kConstruct } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { getMaxListeners, setMaxListeners, getEventListeners, defaultMaxListeners } = __nccwpck_require__(24434) + +let TransformStream = globalThis.TransformStream + +const kAbortController = Symbol('abortController') + +const requestFinalizer = new FinalizationRegistry(({ signal, abort }) => { + signal.removeEventListener('abort', abort) +}) + +// https://fetch.spec.whatwg.org/#request-class +class Request { + // https://fetch.spec.whatwg.org/#dom-request + constructor (input, init = {}) { + if (input === kConstruct) { + return + } + + webidl.argumentLengthCheck(arguments, 1, { header: 'Request constructor' }) + + input = webidl.converters.RequestInfo(input) + init = webidl.converters.RequestInit(init) + + // https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object + this[kRealm] = { + settingsObject: { + baseUrl: getGlobalOrigin(), + get origin () { + return this.baseUrl?.origin + }, + policyContainer: makePolicyContainer() + } + } + + // 1. Let request be null. + let request = null + + // 2. Let fallbackMode be null. + let fallbackMode = null + + // 3. Let baseURL be this’s relevant settings object’s API base URL. + const baseUrl = this[kRealm].settingsObject.baseUrl + + // 4. Let signal be null. + let signal = null + + // 5. If input is a string, then: + if (typeof input === 'string') { + // 1. Let parsedURL be the result of parsing input with baseURL. + // 2. If parsedURL is failure, then throw a TypeError. + let parsedURL + try { + parsedURL = new URL(input, baseUrl) + } catch (err) { + throw new TypeError('Failed to parse URL from ' + input, { cause: err }) + } + + // 3. If parsedURL includes credentials, then throw a TypeError. + if (parsedURL.username || parsedURL.password) { + throw new TypeError( + 'Request cannot be constructed from a URL that includes credentials: ' + + input + ) + } + + // 4. Set request to a new request whose URL is parsedURL. + request = makeRequest({ urlList: [parsedURL] }) + + // 5. Set fallbackMode to "cors". + fallbackMode = 'cors' + } else { + // 6. Otherwise: + + // 7. Assert: input is a Request object. + assert(input instanceof Request) + + // 8. Set request to input’s request. + request = input[kState] + + // 9. Set signal to input’s signal. + signal = input[kSignal] + } + + // 7. Let origin be this’s relevant settings object’s origin. + const origin = this[kRealm].settingsObject.origin + + // 8. Let window be "client". + let window = 'client' + + // 9. If request’s window is an environment settings object and its origin + // is same origin with origin, then set window to request’s window. + if ( + request.window?.constructor?.name === 'EnvironmentSettingsObject' && + sameOrigin(request.window, origin) + ) { + window = request.window + } + + // 10. If init["window"] exists and is non-null, then throw a TypeError. + if (init.window != null) { + throw new TypeError(`'window' option '${window}' must be null`) + } + + // 11. If init["window"] exists, then set window to "no-window". + if ('window' in init) { + window = 'no-window' + } + + // 12. Set request to a new request with the following properties: + request = makeRequest({ + // URL request’s URL. + // undici implementation note: this is set as the first item in request's urlList in makeRequest + // method request’s method. + method: request.method, + // header list A copy of request’s header list. + // undici implementation note: headersList is cloned in makeRequest + headersList: request.headersList, + // unsafe-request flag Set. + unsafeRequest: request.unsafeRequest, + // client This’s relevant settings object. + client: this[kRealm].settingsObject, + // window window. + window, + // priority request’s priority. + priority: request.priority, + // origin request’s origin. The propagation of the origin is only significant for navigation requests + // being handled by a service worker. In this scenario a request can have an origin that is different + // from the current client. + origin: request.origin, + // referrer request’s referrer. + referrer: request.referrer, + // referrer policy request’s referrer policy. + referrerPolicy: request.referrerPolicy, + // mode request’s mode. + mode: request.mode, + // credentials mode request’s credentials mode. + credentials: request.credentials, + // cache mode request’s cache mode. + cache: request.cache, + // redirect mode request’s redirect mode. + redirect: request.redirect, + // integrity metadata request’s integrity metadata. + integrity: request.integrity, + // keepalive request’s keepalive. + keepalive: request.keepalive, + // reload-navigation flag request’s reload-navigation flag. + reloadNavigation: request.reloadNavigation, + // history-navigation flag request’s history-navigation flag. + historyNavigation: request.historyNavigation, + // URL list A clone of request’s URL list. + urlList: [...request.urlList] + }) + + const initHasKey = Object.keys(init).length !== 0 + + // 13. If init is not empty, then: + if (initHasKey) { + // 1. If request’s mode is "navigate", then set it to "same-origin". + if (request.mode === 'navigate') { + request.mode = 'same-origin' + } + + // 2. Unset request’s reload-navigation flag. + request.reloadNavigation = false + + // 3. Unset request’s history-navigation flag. + request.historyNavigation = false + + // 4. Set request’s origin to "client". + request.origin = 'client' + + // 5. Set request’s referrer to "client" + request.referrer = 'client' + + // 6. Set request’s referrer policy to the empty string. + request.referrerPolicy = '' + + // 7. Set request’s URL to request’s current URL. + request.url = request.urlList[request.urlList.length - 1] + + // 8. Set request’s URL list to « request’s URL ». + request.urlList = [request.url] + } + + // 14. If init["referrer"] exists, then: + if (init.referrer !== undefined) { + // 1. Let referrer be init["referrer"]. + const referrer = init.referrer + + // 2. If referrer is the empty string, then set request’s referrer to "no-referrer". + if (referrer === '') { + request.referrer = 'no-referrer' + } else { + // 1. Let parsedReferrer be the result of parsing referrer with + // baseURL. + // 2. If parsedReferrer is failure, then throw a TypeError. + let parsedReferrer + try { + parsedReferrer = new URL(referrer, baseUrl) + } catch (err) { + throw new TypeError(`Referrer "${referrer}" is not a valid URL.`, { cause: err }) + } + + // 3. If one of the following is true + // - parsedReferrer’s scheme is "about" and path is the string "client" + // - parsedReferrer’s origin is not same origin with origin + // then set request’s referrer to "client". + if ( + (parsedReferrer.protocol === 'about:' && parsedReferrer.hostname === 'client') || + (origin && !sameOrigin(parsedReferrer, this[kRealm].settingsObject.baseUrl)) + ) { + request.referrer = 'client' + } else { + // 4. Otherwise, set request’s referrer to parsedReferrer. + request.referrer = parsedReferrer + } + } + } + + // 15. If init["referrerPolicy"] exists, then set request’s referrer policy + // to it. + if (init.referrerPolicy !== undefined) { + request.referrerPolicy = init.referrerPolicy + } + + // 16. Let mode be init["mode"] if it exists, and fallbackMode otherwise. + let mode + if (init.mode !== undefined) { + mode = init.mode + } else { + mode = fallbackMode + } + + // 17. If mode is "navigate", then throw a TypeError. + if (mode === 'navigate') { + throw webidl.errors.exception({ + header: 'Request constructor', + message: 'invalid request mode navigate.' + }) + } + + // 18. If mode is non-null, set request’s mode to mode. + if (mode != null) { + request.mode = mode + } + + // 19. If init["credentials"] exists, then set request’s credentials mode + // to it. + if (init.credentials !== undefined) { + request.credentials = init.credentials + } + + // 18. If init["cache"] exists, then set request’s cache mode to it. + if (init.cache !== undefined) { + request.cache = init.cache + } + + // 21. If request’s cache mode is "only-if-cached" and request’s mode is + // not "same-origin", then throw a TypeError. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + throw new TypeError( + "'only-if-cached' can be set only with 'same-origin' mode" + ) + } + + // 22. If init["redirect"] exists, then set request’s redirect mode to it. + if (init.redirect !== undefined) { + request.redirect = init.redirect + } + + // 23. If init["integrity"] exists, then set request’s integrity metadata to it. + if (init.integrity != null) { + request.integrity = String(init.integrity) + } + + // 24. If init["keepalive"] exists, then set request’s keepalive to it. + if (init.keepalive !== undefined) { + request.keepalive = Boolean(init.keepalive) + } + + // 25. If init["method"] exists, then: + if (init.method !== undefined) { + // 1. Let method be init["method"]. + let method = init.method + + // 2. If method is not a method or method is a forbidden method, then + // throw a TypeError. + if (!isValidHTTPToken(method)) { + throw new TypeError(`'${method}' is not a valid HTTP method.`) + } + + if (forbiddenMethodsSet.has(method.toUpperCase())) { + throw new TypeError(`'${method}' HTTP method is unsupported.`) + } + + // 3. Normalize method. + method = normalizeMethodRecord[method] ?? normalizeMethod(method) + + // 4. Set request’s method to method. + request.method = method + } + + // 26. If init["signal"] exists, then set signal to it. + if (init.signal !== undefined) { + signal = init.signal + } + + // 27. Set this’s request to request. + this[kState] = request + + // 28. Set this’s signal to a new AbortSignal object with this’s relevant + // Realm. + // TODO: could this be simplified with AbortSignal.any + // (https://dom.spec.whatwg.org/#dom-abortsignal-any) + const ac = new AbortController() + this[kSignal] = ac.signal + this[kSignal][kRealm] = this[kRealm] + + // 29. If signal is not null, then make this’s signal follow signal. + if (signal != null) { + if ( + !signal || + typeof signal.aborted !== 'boolean' || + typeof signal.addEventListener !== 'function' + ) { + throw new TypeError( + "Failed to construct 'Request': member signal is not of type AbortSignal." + ) + } + + if (signal.aborted) { + ac.abort(signal.reason) + } else { + // Keep a strong ref to ac while request object + // is alive. This is needed to prevent AbortController + // from being prematurely garbage collected. + // See, https://github.com/nodejs/undici/issues/1926. + this[kAbortController] = ac + + const acRef = new WeakRef(ac) + const abort = function () { + const ac = acRef.deref() + if (ac !== undefined) { + ac.abort(this.reason) + } + } + + // Third-party AbortControllers may not work with these. + // See, https://github.com/nodejs/undici/pull/1910#issuecomment-1464495619. + try { + // If the max amount of listeners is equal to the default, increase it + // This is only available in node >= v19.9.0 + if (typeof getMaxListeners === 'function' && getMaxListeners(signal) === defaultMaxListeners) { + setMaxListeners(100, signal) + } else if (getEventListeners(signal, 'abort').length >= defaultMaxListeners) { + setMaxListeners(100, signal) + } + } catch {} + + util.addAbortListener(signal, abort) + requestFinalizer.register(ac, { signal, abort }) + } + } + + // 30. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is request’s header list and guard is + // "request". + this[kHeaders] = new Headers(kConstruct) + this[kHeaders][kHeadersList] = request.headersList + this[kHeaders][kGuard] = 'request' + this[kHeaders][kRealm] = this[kRealm] + + // 31. If this’s request’s mode is "no-cors", then: + if (mode === 'no-cors') { + // 1. If this’s request’s method is not a CORS-safelisted method, + // then throw a TypeError. + if (!corsSafeListedMethodsSet.has(request.method)) { + throw new TypeError( + `'${request.method} is unsupported in no-cors mode.` + ) + } + + // 2. Set this’s headers’s guard to "request-no-cors". + this[kHeaders][kGuard] = 'request-no-cors' + } + + // 32. If init is not empty, then: + if (initHasKey) { + /** @type {HeadersList} */ + const headersList = this[kHeaders][kHeadersList] + // 1. Let headers be a copy of this’s headers and its associated header + // list. + // 2. If init["headers"] exists, then set headers to init["headers"]. + const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList) + + // 3. Empty this’s headers’s header list. + headersList.clear() + + // 4. If headers is a Headers object, then for each header in its header + // list, append header’s name/header’s value to this’s headers. + if (headers instanceof HeadersList) { + for (const [key, val] of headers) { + headersList.append(key, val) + } + // Note: Copy the `set-cookie` meta-data. + headersList.cookies = headers.cookies + } else { + // 5. Otherwise, fill this’s headers with headers. + fillHeaders(this[kHeaders], headers) + } + } + + // 33. Let inputBody be input’s request’s body if input is a Request + // object; otherwise null. + const inputBody = input instanceof Request ? input[kState].body : null + + // 34. If either init["body"] exists and is non-null or inputBody is + // non-null, and request’s method is `GET` or `HEAD`, then throw a + // TypeError. + if ( + (init.body != null || inputBody != null) && + (request.method === 'GET' || request.method === 'HEAD') + ) { + throw new TypeError('Request with GET/HEAD method cannot have body.') + } + + // 35. Let initBody be null. + let initBody = null + + // 36. If init["body"] exists and is non-null, then: + if (init.body != null) { + // 1. Let Content-Type be null. + // 2. Set initBody and Content-Type to the result of extracting + // init["body"], with keepalive set to request’s keepalive. + const [extractedBody, contentType] = extractBody( + init.body, + request.keepalive + ) + initBody = extractedBody + + // 3, If Content-Type is non-null and this’s headers’s header list does + // not contain `Content-Type`, then append `Content-Type`/Content-Type to + // this’s headers. + if (contentType && !this[kHeaders][kHeadersList].contains('content-type')) { + this[kHeaders].append('content-type', contentType) + } + } + + // 37. Let inputOrInitBody be initBody if it is non-null; otherwise + // inputBody. + const inputOrInitBody = initBody ?? inputBody + + // 38. If inputOrInitBody is non-null and inputOrInitBody’s source is + // null, then: + if (inputOrInitBody != null && inputOrInitBody.source == null) { + // 1. If initBody is non-null and init["duplex"] does not exist, + // then throw a TypeError. + if (initBody != null && init.duplex == null) { + throw new TypeError('RequestInit: duplex option is required when sending a body.') + } + + // 2. If this’s request’s mode is neither "same-origin" nor "cors", + // then throw a TypeError. + if (request.mode !== 'same-origin' && request.mode !== 'cors') { + throw new TypeError( + 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' + ) + } + + // 3. Set this’s request’s use-CORS-preflight flag. + request.useCORSPreflightFlag = true + } + + // 39. Let finalBody be inputOrInitBody. + let finalBody = inputOrInitBody + + // 40. If initBody is null and inputBody is non-null, then: + if (initBody == null && inputBody != null) { + // 1. If input is unusable, then throw a TypeError. + if (util.isDisturbed(inputBody.stream) || inputBody.stream.locked) { + throw new TypeError( + 'Cannot construct a Request with a Request object that has already been used.' + ) + } + + // 2. Set finalBody to the result of creating a proxy for inputBody. + if (!TransformStream) { + TransformStream = (__nccwpck_require__(63774).TransformStream) + } + + // https://streams.spec.whatwg.org/#readablestream-create-a-proxy + const identityTransform = new TransformStream() + inputBody.stream.pipeThrough(identityTransform) + finalBody = { + source: inputBody.source, + length: inputBody.length, + stream: identityTransform.readable + } + } + + // 41. Set this’s request’s body to finalBody. + this[kState].body = finalBody + } + + // Returns request’s HTTP method, which is "GET" by default. + get method () { + webidl.brandCheck(this, Request) + + // The method getter steps are to return this’s request’s method. + return this[kState].method + } + + // Returns the URL of request as a string. + get url () { + webidl.brandCheck(this, Request) + + // The url getter steps are to return this’s request’s URL, serialized. + return URLSerializer(this[kState].url) + } + + // Returns a Headers object consisting of the headers associated with request. + // Note that headers added in the network layer by the user agent will not + // be accounted for in this object, e.g., the "Host" header. + get headers () { + webidl.brandCheck(this, Request) + + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } + + // Returns the kind of resource requested by request, e.g., "document" + // or "script". + get destination () { + webidl.brandCheck(this, Request) + + // The destination getter are to return this’s request’s destination. + return this[kState].destination + } + + // Returns the referrer of request. Its value can be a same-origin URL if + // explicitly set in init, the empty string to indicate no referrer, and + // "about:client" when defaulting to the global’s default. This is used + // during fetching to determine the value of the `Referer` header of the + // request being made. + get referrer () { + webidl.brandCheck(this, Request) + + // 1. If this’s request’s referrer is "no-referrer", then return the + // empty string. + if (this[kState].referrer === 'no-referrer') { + return '' + } + + // 2. If this’s request’s referrer is "client", then return + // "about:client". + if (this[kState].referrer === 'client') { + return 'about:client' + } + + // Return this’s request’s referrer, serialized. + return this[kState].referrer.toString() + } + + // Returns the referrer policy associated with request. + // This is used during fetching to compute the value of the request’s + // referrer. + get referrerPolicy () { + webidl.brandCheck(this, Request) + + // The referrerPolicy getter steps are to return this’s request’s referrer policy. + return this[kState].referrerPolicy + } + + // Returns the mode associated with request, which is a string indicating + // whether the request will use CORS, or will be restricted to same-origin + // URLs. + get mode () { + webidl.brandCheck(this, Request) + + // The mode getter steps are to return this’s request’s mode. + return this[kState].mode + } + + // Returns the credentials mode associated with request, + // which is a string indicating whether credentials will be sent with the + // request always, never, or only when sent to a same-origin URL. + get credentials () { + // The credentials getter steps are to return this’s request’s credentials mode. + return this[kState].credentials + } + + // Returns the cache mode associated with request, + // which is a string indicating how the request will + // interact with the browser’s cache when fetching. + get cache () { + webidl.brandCheck(this, Request) + + // The cache getter steps are to return this’s request’s cache mode. + return this[kState].cache + } + + // Returns the redirect mode associated with request, + // which is a string indicating how redirects for the + // request will be handled during fetching. A request + // will follow redirects by default. + get redirect () { + webidl.brandCheck(this, Request) + + // The redirect getter steps are to return this’s request’s redirect mode. + return this[kState].redirect + } + + // Returns request’s subresource integrity metadata, which is a + // cryptographic hash of the resource being fetched. Its value + // consists of multiple hashes separated by whitespace. [SRI] + get integrity () { + webidl.brandCheck(this, Request) + + // The integrity getter steps are to return this’s request’s integrity + // metadata. + return this[kState].integrity + } + + // Returns a boolean indicating whether or not request can outlive the + // global in which it was created. + get keepalive () { + webidl.brandCheck(this, Request) + + // The keepalive getter steps are to return this’s request’s keepalive. + return this[kState].keepalive + } + + // Returns a boolean indicating whether or not request is for a reload + // navigation. + get isReloadNavigation () { + webidl.brandCheck(this, Request) + + // The isReloadNavigation getter steps are to return true if this’s + // request’s reload-navigation flag is set; otherwise false. + return this[kState].reloadNavigation + } + + // Returns a boolean indicating whether or not request is for a history + // navigation (a.k.a. back-foward navigation). + get isHistoryNavigation () { + webidl.brandCheck(this, Request) + + // The isHistoryNavigation getter steps are to return true if this’s request’s + // history-navigation flag is set; otherwise false. + return this[kState].historyNavigation + } + + // Returns the signal associated with request, which is an AbortSignal + // object indicating whether or not request has been aborted, and its + // abort event handler. + get signal () { + webidl.brandCheck(this, Request) + + // The signal getter steps are to return this’s signal. + return this[kSignal] + } + + get body () { + webidl.brandCheck(this, Request) + + return this[kState].body ? this[kState].body.stream : null + } + + get bodyUsed () { + webidl.brandCheck(this, Request) + + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + } + + get duplex () { + webidl.brandCheck(this, Request) + + return 'half' + } + + // Returns a clone of request. + clone () { + webidl.brandCheck(this, Request) + + // 1. If this is unusable, then throw a TypeError. + if (this.bodyUsed || this.body?.locked) { + throw new TypeError('unusable') + } + + // 2. Let clonedRequest be the result of cloning this’s request. + const clonedRequest = cloneRequest(this[kState]) + + // 3. Let clonedRequestObject be the result of creating a Request object, + // given clonedRequest, this’s headers’s guard, and this’s relevant Realm. + const clonedRequestObject = new Request(kConstruct) + clonedRequestObject[kState] = clonedRequest + clonedRequestObject[kRealm] = this[kRealm] + clonedRequestObject[kHeaders] = new Headers(kConstruct) + clonedRequestObject[kHeaders][kHeadersList] = clonedRequest.headersList + clonedRequestObject[kHeaders][kGuard] = this[kHeaders][kGuard] + clonedRequestObject[kHeaders][kRealm] = this[kHeaders][kRealm] + + // 4. Make clonedRequestObject’s signal follow this’s signal. + const ac = new AbortController() + if (this.signal.aborted) { + ac.abort(this.signal.reason) + } else { + util.addAbortListener( + this.signal, + () => { + ac.abort(this.signal.reason) + } + ) + } + clonedRequestObject[kSignal] = ac.signal + + // 4. Return clonedRequestObject. + return clonedRequestObject + } +} + +mixinBody(Request) + +function makeRequest (init) { + // https://fetch.spec.whatwg.org/#requests + const request = { + method: 'GET', + localURLsOnly: false, + unsafeRequest: false, + body: null, + client: null, + reservedClient: null, + replacesClientId: '', + window: 'client', + keepalive: false, + serviceWorkers: 'all', + initiator: '', + destination: '', + priority: null, + origin: 'client', + policyContainer: 'client', + referrer: 'client', + referrerPolicy: '', + mode: 'no-cors', + useCORSPreflightFlag: false, + credentials: 'same-origin', + useCredentials: false, + cache: 'default', + redirect: 'follow', + integrity: '', + cryptoGraphicsNonceMetadata: '', + parserMetadata: '', + reloadNavigation: false, + historyNavigation: false, + userActivation: false, + taintedOrigin: false, + redirectCount: 0, + responseTainting: 'basic', + preventNoCacheCacheControlHeaderModification: false, + done: false, + timingAllowFailed: false, + ...init, + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList() + } + request.url = request.urlList[0] + return request +} + +// https://fetch.spec.whatwg.org/#concept-request-clone +function cloneRequest (request) { + // To clone a request request, run these steps: + + // 1. Let newRequest be a copy of request, except for its body. + const newRequest = makeRequest({ ...request, body: null }) + + // 2. If request’s body is non-null, set newRequest’s body to the + // result of cloning request’s body. + if (request.body != null) { + newRequest.body = cloneBody(request.body) + } + + // 3. Return newRequest. + return newRequest +} + +Object.defineProperties(Request.prototype, { + method: kEnumerableProperty, + url: kEnumerableProperty, + headers: kEnumerableProperty, + redirect: kEnumerableProperty, + clone: kEnumerableProperty, + signal: kEnumerableProperty, + duplex: kEnumerableProperty, + destination: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + isHistoryNavigation: kEnumerableProperty, + isReloadNavigation: kEnumerableProperty, + keepalive: kEnumerableProperty, + integrity: kEnumerableProperty, + cache: kEnumerableProperty, + credentials: kEnumerableProperty, + attribute: kEnumerableProperty, + referrerPolicy: kEnumerableProperty, + referrer: kEnumerableProperty, + mode: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Request', + configurable: true + } +}) + +webidl.converters.Request = webidl.interfaceConverter( + Request +) + +// https://fetch.spec.whatwg.org/#requestinfo +webidl.converters.RequestInfo = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) + } + + if (V instanceof Request) { + return webidl.converters.Request(V) + } + + return webidl.converters.USVString(V) +} + +webidl.converters.AbortSignal = webidl.interfaceConverter( + AbortSignal +) + +// https://fetch.spec.whatwg.org/#requestinit +webidl.converters.RequestInit = webidl.dictionaryConverter([ + { + key: 'method', + converter: webidl.converters.ByteString + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + }, + { + key: 'body', + converter: webidl.nullableConverter( + webidl.converters.BodyInit + ) + }, + { + key: 'referrer', + converter: webidl.converters.USVString + }, + { + key: 'referrerPolicy', + converter: webidl.converters.DOMString, + // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + allowedValues: referrerPolicy + }, + { + key: 'mode', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#concept-request-mode + allowedValues: requestMode + }, + { + key: 'credentials', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcredentials + allowedValues: requestCredentials + }, + { + key: 'cache', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcache + allowedValues: requestCache + }, + { + key: 'redirect', + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestredirect + allowedValues: requestRedirect + }, + { + key: 'integrity', + converter: webidl.converters.DOMString + }, + { + key: 'keepalive', + converter: webidl.converters.boolean + }, + { + key: 'signal', + converter: webidl.nullableConverter( + (signal) => webidl.converters.AbortSignal( + signal, + { strict: false } + ) + ) + }, + { + key: 'window', + converter: webidl.converters.any + }, + { + key: 'duplex', + converter: webidl.converters.DOMString, + allowedValues: requestDuplex + } +]) + +module.exports = { Request, makeRequest } + + +/***/ }), + +/***/ 48676: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Headers, HeadersList, fill } = __nccwpck_require__(26349) +const { extractBody, cloneBody, mixinBody } = __nccwpck_require__(8923) +const util = __nccwpck_require__(3440) +const { kEnumerableProperty } = util +const { + isValidReasonPhrase, + isCancelled, + isAborted, + isBlobLike, + serializeJavascriptValueToJSONString, + isErrorLike, + isomorphicEncode +} = __nccwpck_require__(15523) +const { + redirectStatusSet, + nullBodyStatus, + DOMException +} = __nccwpck_require__(87326) +const { kState, kHeaders, kGuard, kRealm } = __nccwpck_require__(89710) +const { webidl } = __nccwpck_require__(74222) +const { FormData } = __nccwpck_require__(43073) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { URLSerializer } = __nccwpck_require__(94322) +const { kHeadersList, kConstruct } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { types } = __nccwpck_require__(39023) + +const ReadableStream = globalThis.ReadableStream || (__nccwpck_require__(63774).ReadableStream) +const textEncoder = new TextEncoder('utf-8') + +// https://fetch.spec.whatwg.org/#response-class +class Response { + // Creates network error Response. + static error () { + // TODO + const relevantRealm = { settingsObject: {} } + + // The static error() method steps are to return the result of creating a + // Response object, given a new network error, "immutable", and this’s + // relevant Realm. + const responseObject = new Response() + responseObject[kState] = makeNetworkError() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kHeadersList] = responseObject[kState].headersList + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + return responseObject + } + + // https://fetch.spec.whatwg.org/#dom-response-json + static json (data, init = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'Response.json' }) + + if (init !== null) { + init = webidl.converters.ResponseInit(init) + } + + // 1. Let bytes the result of running serialize a JavaScript value to JSON bytes on data. + const bytes = textEncoder.encode( + serializeJavascriptValueToJSONString(data) + ) + + // 2. Let body be the result of extracting bytes. + const body = extractBody(bytes) + + // 3. Let responseObject be the result of creating a Response object, given a new response, + // "response", and this’s relevant Realm. + const relevantRealm = { settingsObject: {} } + const responseObject = new Response() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kGuard] = 'response' + responseObject[kHeaders][kRealm] = relevantRealm + + // 4. Perform initialize a response given responseObject, init, and (body, "application/json"). + initializeResponse(responseObject, init, { body: body[0], type: 'application/json' }) + + // 5. Return responseObject. + return responseObject + } + + // Creates a redirect Response that redirects to url with status status. + static redirect (url, status = 302) { + const relevantRealm = { settingsObject: {} } + + webidl.argumentLengthCheck(arguments, 1, { header: 'Response.redirect' }) + + url = webidl.converters.USVString(url) + status = webidl.converters['unsigned short'](status) + + // 1. Let parsedURL be the result of parsing url with current settings + // object’s API base URL. + // 2. If parsedURL is failure, then throw a TypeError. + // TODO: base-URL? + let parsedURL + try { + parsedURL = new URL(url, getGlobalOrigin()) + } catch (err) { + throw Object.assign(new TypeError('Failed to parse URL from ' + url), { + cause: err + }) + } + + // 3. If status is not a redirect status, then throw a RangeError. + if (!redirectStatusSet.has(status)) { + throw new RangeError('Invalid status code ' + status) + } + + // 4. Let responseObject be the result of creating a Response object, + // given a new response, "immutable", and this’s relevant Realm. + const responseObject = new Response() + responseObject[kRealm] = relevantRealm + responseObject[kHeaders][kGuard] = 'immutable' + responseObject[kHeaders][kRealm] = relevantRealm + + // 5. Set responseObject’s response’s status to status. + responseObject[kState].status = status + + // 6. Let value be parsedURL, serialized and isomorphic encoded. + const value = isomorphicEncode(URLSerializer(parsedURL)) + + // 7. Append `Location`/value to responseObject’s response’s header list. + responseObject[kState].headersList.append('location', value) + + // 8. Return responseObject. + return responseObject + } + + // https://fetch.spec.whatwg.org/#dom-response + constructor (body = null, init = {}) { + if (body !== null) { + body = webidl.converters.BodyInit(body) + } + + init = webidl.converters.ResponseInit(init) + + // TODO + this[kRealm] = { settingsObject: {} } + + // 1. Set this’s response to a new response. + this[kState] = makeResponse({}) + + // 2. Set this’s headers to a new Headers object with this’s relevant + // Realm, whose header list is this’s response’s header list and guard + // is "response". + this[kHeaders] = new Headers(kConstruct) + this[kHeaders][kGuard] = 'response' + this[kHeaders][kHeadersList] = this[kState].headersList + this[kHeaders][kRealm] = this[kRealm] + + // 3. Let bodyWithType be null. + let bodyWithType = null + + // 4. If body is non-null, then set bodyWithType to the result of extracting body. + if (body != null) { + const [extractedBody, type] = extractBody(body) + bodyWithType = { body: extractedBody, type } + } + + // 5. Perform initialize a response given this, init, and bodyWithType. + initializeResponse(this, init, bodyWithType) + } + + // Returns response’s type, e.g., "cors". + get type () { + webidl.brandCheck(this, Response) + + // The type getter steps are to return this’s response’s type. + return this[kState].type + } + + // Returns response’s URL, if it has one; otherwise the empty string. + get url () { + webidl.brandCheck(this, Response) + + const urlList = this[kState].urlList + + // The url getter steps are to return the empty string if this’s + // response’s URL is null; otherwise this’s response’s URL, + // serialized with exclude fragment set to true. + const url = urlList[urlList.length - 1] ?? null + + if (url === null) { + return '' + } + + return URLSerializer(url, true) + } + + // Returns whether response was obtained through a redirect. + get redirected () { + webidl.brandCheck(this, Response) + + // The redirected getter steps are to return true if this’s response’s URL + // list has more than one item; otherwise false. + return this[kState].urlList.length > 1 + } + + // Returns response’s status. + get status () { + webidl.brandCheck(this, Response) + + // The status getter steps are to return this’s response’s status. + return this[kState].status + } + + // Returns whether response’s status is an ok status. + get ok () { + webidl.brandCheck(this, Response) + + // The ok getter steps are to return true if this’s response’s status is an + // ok status; otherwise false. + return this[kState].status >= 200 && this[kState].status <= 299 + } + + // Returns response’s status message. + get statusText () { + webidl.brandCheck(this, Response) + + // The statusText getter steps are to return this’s response’s status + // message. + return this[kState].statusText + } + + // Returns response’s headers as Headers. + get headers () { + webidl.brandCheck(this, Response) + + // The headers getter steps are to return this’s headers. + return this[kHeaders] + } + + get body () { + webidl.brandCheck(this, Response) + + return this[kState].body ? this[kState].body.stream : null + } + + get bodyUsed () { + webidl.brandCheck(this, Response) + + return !!this[kState].body && util.isDisturbed(this[kState].body.stream) + } + + // Returns a clone of response. + clone () { + webidl.brandCheck(this, Response) + + // 1. If this is unusable, then throw a TypeError. + if (this.bodyUsed || (this.body && this.body.locked)) { + throw webidl.errors.exception({ + header: 'Response.clone', + message: 'Body has already been consumed.' + }) + } + + // 2. Let clonedResponse be the result of cloning this’s response. + const clonedResponse = cloneResponse(this[kState]) + + // 3. Return the result of creating a Response object, given + // clonedResponse, this’s headers’s guard, and this’s relevant Realm. + const clonedResponseObject = new Response() + clonedResponseObject[kState] = clonedResponse + clonedResponseObject[kRealm] = this[kRealm] + clonedResponseObject[kHeaders][kHeadersList] = clonedResponse.headersList + clonedResponseObject[kHeaders][kGuard] = this[kHeaders][kGuard] + clonedResponseObject[kHeaders][kRealm] = this[kHeaders][kRealm] + + return clonedResponseObject + } +} + +mixinBody(Response) + +Object.defineProperties(Response.prototype, { + type: kEnumerableProperty, + url: kEnumerableProperty, + status: kEnumerableProperty, + ok: kEnumerableProperty, + redirected: kEnumerableProperty, + statusText: kEnumerableProperty, + headers: kEnumerableProperty, + clone: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'Response', + configurable: true + } +}) + +Object.defineProperties(Response, { + json: kEnumerableProperty, + redirect: kEnumerableProperty, + error: kEnumerableProperty +}) + +// https://fetch.spec.whatwg.org/#concept-response-clone +function cloneResponse (response) { + // To clone a response response, run these steps: + + // 1. If response is a filtered response, then return a new identical + // filtered response whose internal response is a clone of response’s + // internal response. + if (response.internalResponse) { + return filterResponse( + cloneResponse(response.internalResponse), + response.type + ) + } + + // 2. Let newResponse be a copy of response, except for its body. + const newResponse = makeResponse({ ...response, body: null }) + + // 3. If response’s body is non-null, then set newResponse’s body to the + // result of cloning response’s body. + if (response.body != null) { + newResponse.body = cloneBody(response.body) + } + + // 4. Return newResponse. + return newResponse +} + +function makeResponse (init) { + return { + aborted: false, + rangeRequested: false, + timingAllowPassed: false, + requestIncludesCredentials: false, + type: 'default', + status: 200, + timingInfo: null, + cacheState: '', + statusText: '', + ...init, + headersList: init.headersList + ? new HeadersList(init.headersList) + : new HeadersList(), + urlList: init.urlList ? [...init.urlList] : [] + } +} + +function makeNetworkError (reason) { + const isError = isErrorLike(reason) + return makeResponse({ + type: 'error', + status: 0, + error: isError + ? reason + : new Error(reason ? String(reason) : reason), + aborted: reason && reason.name === 'AbortError' + }) +} + +function makeFilteredResponse (response, state) { + state = { + internalResponse: response, + ...state + } + + return new Proxy(response, { + get (target, p) { + return p in state ? state[p] : target[p] + }, + set (target, p, value) { + assert(!(p in state)) + target[p] = value + return true + } + }) +} + +// https://fetch.spec.whatwg.org/#concept-filtered-response +function filterResponse (response, type) { + // Set response to the following filtered response with response as its + // internal response, depending on request’s response tainting: + if (type === 'basic') { + // A basic filtered response is a filtered response whose type is "basic" + // and header list excludes any headers in internal response’s header list + // whose name is a forbidden response-header name. + + // Note: undici does not implement forbidden response-header names + return makeFilteredResponse(response, { + type: 'basic', + headersList: response.headersList + }) + } else if (type === 'cors') { + // A CORS filtered response is a filtered response whose type is "cors" + // and header list excludes any headers in internal response’s header + // list whose name is not a CORS-safelisted response-header name, given + // internal response’s CORS-exposed header-name list. + + // Note: undici does not implement CORS-safelisted response-header names + return makeFilteredResponse(response, { + type: 'cors', + headersList: response.headersList + }) + } else if (type === 'opaque') { + // An opaque filtered response is a filtered response whose type is + // "opaque", URL list is the empty list, status is 0, status message + // is the empty byte sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaque', + urlList: Object.freeze([]), + status: 0, + statusText: '', + body: null + }) + } else if (type === 'opaqueredirect') { + // An opaque-redirect filtered response is a filtered response whose type + // is "opaqueredirect", status is 0, status message is the empty byte + // sequence, header list is empty, and body is null. + + return makeFilteredResponse(response, { + type: 'opaqueredirect', + status: 0, + statusText: '', + headersList: [], + body: null + }) + } else { + assert(false) + } +} + +// https://fetch.spec.whatwg.org/#appropriate-network-error +function makeAppropriateNetworkError (fetchParams, err = null) { + // 1. Assert: fetchParams is canceled. + assert(isCancelled(fetchParams)) + + // 2. Return an aborted network error if fetchParams is aborted; + // otherwise return a network error. + return isAborted(fetchParams) + ? makeNetworkError(Object.assign(new DOMException('The operation was aborted.', 'AbortError'), { cause: err })) + : makeNetworkError(Object.assign(new DOMException('Request was cancelled.'), { cause: err })) +} + +// https://whatpr.org/fetch/1392.html#initialize-a-response +function initializeResponse (response, init, body) { + // 1. If init["status"] is not in the range 200 to 599, inclusive, then + // throw a RangeError. + if (init.status !== null && (init.status < 200 || init.status > 599)) { + throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.') + } + + // 2. If init["statusText"] does not match the reason-phrase token production, + // then throw a TypeError. + if ('statusText' in init && init.statusText != null) { + // See, https://datatracker.ietf.org/doc/html/rfc7230#section-3.1.2: + // reason-phrase = *( HTAB / SP / VCHAR / obs-text ) + if (!isValidReasonPhrase(String(init.statusText))) { + throw new TypeError('Invalid statusText') + } + } + + // 3. Set response’s response’s status to init["status"]. + if ('status' in init && init.status != null) { + response[kState].status = init.status + } + + // 4. Set response’s response’s status message to init["statusText"]. + if ('statusText' in init && init.statusText != null) { + response[kState].statusText = init.statusText + } + + // 5. If init["headers"] exists, then fill response’s headers with init["headers"]. + if ('headers' in init && init.headers != null) { + fill(response[kHeaders], init.headers) + } + + // 6. If body was given, then: + if (body) { + // 1. If response's status is a null body status, then throw a TypeError. + if (nullBodyStatus.includes(response.status)) { + throw webidl.errors.exception({ + header: 'Response constructor', + message: 'Invalid response status code ' + response.status + }) + } + + // 2. Set response's body to body's body. + response[kState].body = body.body + + // 3. If body's type is non-null and response's header list does not contain + // `Content-Type`, then append (`Content-Type`, body's type) to response's header list. + if (body.type != null && !response[kState].headersList.contains('Content-Type')) { + response[kState].headersList.append('content-type', body.type) + } + } +} + +webidl.converters.ReadableStream = webidl.interfaceConverter( + ReadableStream +) + +webidl.converters.FormData = webidl.interfaceConverter( + FormData +) + +webidl.converters.URLSearchParams = webidl.interfaceConverter( + URLSearchParams +) + +// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit +webidl.converters.XMLHttpRequestBodyInit = function (V) { + if (typeof V === 'string') { + return webidl.converters.USVString(V) + } + + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if (types.isArrayBuffer(V) || types.isTypedArray(V) || types.isDataView(V)) { + return webidl.converters.BufferSource(V) + } + + if (util.isFormDataLike(V)) { + return webidl.converters.FormData(V, { strict: false }) + } + + if (V instanceof URLSearchParams) { + return webidl.converters.URLSearchParams(V) + } + + return webidl.converters.DOMString(V) +} + +// https://fetch.spec.whatwg.org/#bodyinit +webidl.converters.BodyInit = function (V) { + if (V instanceof ReadableStream) { + return webidl.converters.ReadableStream(V) + } + + // Note: the spec doesn't include async iterables, + // this is an undici extension. + if (V?.[Symbol.asyncIterator]) { + return V + } + + return webidl.converters.XMLHttpRequestBodyInit(V) +} + +webidl.converters.ResponseInit = webidl.dictionaryConverter([ + { + key: 'status', + converter: webidl.converters['unsigned short'], + defaultValue: 200 + }, + { + key: 'statusText', + converter: webidl.converters.ByteString, + defaultValue: '' + }, + { + key: 'headers', + converter: webidl.converters.HeadersInit + } +]) + +module.exports = { + makeNetworkError, + makeResponse, + makeAppropriateNetworkError, + filterResponse, + Response, + cloneResponse +} + + +/***/ }), + +/***/ 89710: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kUrl: Symbol('url'), + kHeaders: Symbol('headers'), + kSignal: Symbol('signal'), + kState: Symbol('state'), + kGuard: Symbol('guard'), + kRealm: Symbol('realm') +} + + +/***/ }), + +/***/ 15523: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { redirectStatusSet, referrerPolicySet: referrerPolicyTokens, badPortsSet } = __nccwpck_require__(87326) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { performance } = __nccwpck_require__(82987) +const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(3440) +const assert = __nccwpck_require__(42613) +const { isUint8Array } = __nccwpck_require__(98253) + +let supportedHashes = [] + +// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable +/** @type {import('crypto')|undefined} */ +let crypto + +try { + crypto = __nccwpck_require__(76982) + const possibleRelevantHashes = ['sha256', 'sha384', 'sha512'] + supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash)) +/* c8 ignore next 3 */ +} catch { +} + +function responseURL (response) { + // https://fetch.spec.whatwg.org/#responses + // A response has an associated URL. It is a pointer to the last URL + // in response’s URL list and null if response’s URL list is empty. + const urlList = response.urlList + const length = urlList.length + return length === 0 ? null : urlList[length - 1].toString() +} + +// https://fetch.spec.whatwg.org/#concept-response-location-url +function responseLocationURL (response, requestFragment) { + // 1. If response’s status is not a redirect status, then return null. + if (!redirectStatusSet.has(response.status)) { + return null + } + + // 2. Let location be the result of extracting header list values given + // `Location` and response’s header list. + let location = response.headersList.get('location') + + // 3. If location is a header value, then set location to the result of + // parsing location with response’s URL. + if (location !== null && isValidHeaderValue(location)) { + location = new URL(location, responseURL(response)) + } + + // 4. If location is a URL whose fragment is null, then set location’s + // fragment to requestFragment. + if (location && !location.hash) { + location.hash = requestFragment + } + + // 5. Return location. + return location +} + +/** @returns {URL} */ +function requestCurrentURL (request) { + return request.urlList[request.urlList.length - 1] +} + +function requestBadPort (request) { + // 1. Let url be request’s current URL. + const url = requestCurrentURL(request) + + // 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port, + // then return blocked. + if (urlIsHttpHttpsScheme(url) && badPortsSet.has(url.port)) { + return 'blocked' + } + + // 3. Return allowed. + return 'allowed' +} + +function isErrorLike (object) { + return object instanceof Error || ( + object?.constructor?.name === 'Error' || + object?.constructor?.name === 'DOMException' + ) +} + +// Check whether |statusText| is a ByteString and +// matches the Reason-Phrase token production. +// RFC 2616: https://tools.ietf.org/html/rfc2616 +// RFC 7230: https://tools.ietf.org/html/rfc7230 +// "reason-phrase = *( HTAB / SP / VCHAR / obs-text )" +// https://github.com/chromium/chromium/blob/94.0.4604.1/third_party/blink/renderer/core/fetch/response.cc#L116 +function isValidReasonPhrase (statusText) { + for (let i = 0; i < statusText.length; ++i) { + const c = statusText.charCodeAt(i) + if ( + !( + ( + c === 0x09 || // HTAB + (c >= 0x20 && c <= 0x7e) || // SP / VCHAR + (c >= 0x80 && c <= 0xff) + ) // obs-text + ) + ) { + return false + } + } + return true +} + +/** + * @see https://tools.ietf.org/html/rfc7230#section-3.2.6 + * @param {number} c + */ +function isTokenCharCode (c) { + switch (c) { + case 0x22: + case 0x28: + case 0x29: + case 0x2c: + case 0x2f: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + case 0x40: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x7b: + case 0x7d: + // DQUOTE and "(),/:;<=>?@[\]{}" + return false + default: + // VCHAR %x21-7E + return c >= 0x21 && c <= 0x7e + } +} + +/** + * @param {string} characters + */ +function isValidHTTPToken (characters) { + if (characters.length === 0) { + return false + } + for (let i = 0; i < characters.length; ++i) { + if (!isTokenCharCode(characters.charCodeAt(i))) { + return false + } + } + return true +} + +/** + * @see https://fetch.spec.whatwg.org/#header-name + * @param {string} potentialValue + */ +function isValidHeaderName (potentialValue) { + return isValidHTTPToken(potentialValue) +} + +/** + * @see https://fetch.spec.whatwg.org/#header-value + * @param {string} potentialValue + */ +function isValidHeaderValue (potentialValue) { + // - Has no leading or trailing HTTP tab or space bytes. + // - Contains no 0x00 (NUL) or HTTP newline bytes. + if ( + potentialValue.startsWith('\t') || + potentialValue.startsWith(' ') || + potentialValue.endsWith('\t') || + potentialValue.endsWith(' ') + ) { + return false + } + + if ( + potentialValue.includes('\0') || + potentialValue.includes('\r') || + potentialValue.includes('\n') + ) { + return false + } + + return true +} + +// https://w3c.github.io/webappsec-referrer-policy/#set-requests-referrer-policy-on-redirect +function setRequestReferrerPolicyOnRedirect (request, actualResponse) { + // Given a request request and a response actualResponse, this algorithm + // updates request’s referrer policy according to the Referrer-Policy + // header (if any) in actualResponse. + + // 1. Let policy be the result of executing § 8.1 Parse a referrer policy + // from a Referrer-Policy header on actualResponse. + + // 8.1 Parse a referrer policy from a Referrer-Policy header + // 1. Let policy-tokens be the result of extracting header list values given `Referrer-Policy` and response’s header list. + const { headersList } = actualResponse + // 2. Let policy be the empty string. + // 3. For each token in policy-tokens, if token is a referrer policy and token is not the empty string, then set policy to token. + // 4. Return policy. + const policyHeader = (headersList.get('referrer-policy') ?? '').split(',') + + // Note: As the referrer-policy can contain multiple policies + // separated by comma, we need to loop through all of them + // and pick the first valid one. + // Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#specify_a_fallback_policy + let policy = '' + if (policyHeader.length > 0) { + // The right-most policy takes precedence. + // The left-most policy is the fallback. + for (let i = policyHeader.length; i !== 0; i--) { + const token = policyHeader[i - 1].trim() + if (referrerPolicyTokens.has(token)) { + policy = token + break + } + } + } + + // 2. If policy is not the empty string, then set request’s referrer policy to policy. + if (policy !== '') { + request.referrerPolicy = policy + } +} + +// https://fetch.spec.whatwg.org/#cross-origin-resource-policy-check +function crossOriginResourcePolicyCheck () { + // TODO + return 'allowed' +} + +// https://fetch.spec.whatwg.org/#concept-cors-check +function corsCheck () { + // TODO + return 'success' +} + +// https://fetch.spec.whatwg.org/#concept-tao-check +function TAOCheck () { + // TODO + return 'success' +} + +function appendFetchMetadata (httpRequest) { + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-dest-header + // TODO + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-mode-header + + // 1. Assert: r’s url is a potentially trustworthy URL. + // TODO + + // 2. Let header be a Structured Header whose value is a token. + let header = null + + // 3. Set header’s value to r’s mode. + header = httpRequest.mode + + // 4. Set a structured field value `Sec-Fetch-Mode`/header in r’s header list. + httpRequest.headersList.set('sec-fetch-mode', header) + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-site-header + // TODO + + // https://w3c.github.io/webappsec-fetch-metadata/#sec-fetch-user-header + // TODO +} + +// https://fetch.spec.whatwg.org/#append-a-request-origin-header +function appendRequestOriginHeader (request) { + // 1. Let serializedOrigin be the result of byte-serializing a request origin with request. + let serializedOrigin = request.origin + + // 2. If request’s response tainting is "cors" or request’s mode is "websocket", then append (`Origin`, serializedOrigin) to request’s header list. + if (request.responseTainting === 'cors' || request.mode === 'websocket') { + if (serializedOrigin) { + request.headersList.append('origin', serializedOrigin) + } + + // 3. Otherwise, if request’s method is neither `GET` nor `HEAD`, then: + } else if (request.method !== 'GET' && request.method !== 'HEAD') { + // 1. Switch on request’s referrer policy: + switch (request.referrerPolicy) { + case 'no-referrer': + // Set serializedOrigin to `null`. + serializedOrigin = null + break + case 'no-referrer-when-downgrade': + case 'strict-origin': + case 'strict-origin-when-cross-origin': + // If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`. + if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) { + serializedOrigin = null + } + break + case 'same-origin': + // If request’s origin is not same origin with request’s current URL’s origin, then set serializedOrigin to `null`. + if (!sameOrigin(request, requestCurrentURL(request))) { + serializedOrigin = null + } + break + default: + // Do nothing. + } + + if (serializedOrigin) { + // 2. Append (`Origin`, serializedOrigin) to request’s header list. + request.headersList.append('origin', serializedOrigin) + } + } +} + +function coarsenedSharedCurrentTime (crossOriginIsolatedCapability) { + // TODO + return performance.now() +} + +// https://fetch.spec.whatwg.org/#create-an-opaque-timing-info +function createOpaqueTimingInfo (timingInfo) { + return { + startTime: timingInfo.startTime ?? 0, + redirectStartTime: 0, + redirectEndTime: 0, + postRedirectStartTime: timingInfo.startTime ?? 0, + finalServiceWorkerStartTime: 0, + finalNetworkResponseStartTime: 0, + finalNetworkRequestStartTime: 0, + endTime: 0, + encodedBodySize: 0, + decodedBodySize: 0, + finalConnectionTimingInfo: null + } +} + +// https://html.spec.whatwg.org/multipage/origin.html#policy-container +function makePolicyContainer () { + // Note: the fetch spec doesn't make use of embedder policy or CSP list + return { + referrerPolicy: 'strict-origin-when-cross-origin' + } +} + +// https://html.spec.whatwg.org/multipage/origin.html#clone-a-policy-container +function clonePolicyContainer (policyContainer) { + return { + referrerPolicy: policyContainer.referrerPolicy + } +} + +// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer +function determineRequestsReferrer (request) { + // 1. Let policy be request's referrer policy. + const policy = request.referrerPolicy + + // Note: policy cannot (shouldn't) be null or an empty string. + assert(policy) + + // 2. Let environment be request’s client. + + let referrerSource = null + + // 3. Switch on request’s referrer: + if (request.referrer === 'client') { + // Note: node isn't a browser and doesn't implement document/iframes, + // so we bypass this step and replace it with our own. + + const globalOrigin = getGlobalOrigin() + + if (!globalOrigin || globalOrigin.origin === 'null') { + return 'no-referrer' + } + + // note: we need to clone it as it's mutated + referrerSource = new URL(globalOrigin) + } else if (request.referrer instanceof URL) { + // Let referrerSource be request’s referrer. + referrerSource = request.referrer + } + + // 4. Let request’s referrerURL be the result of stripping referrerSource for + // use as a referrer. + let referrerURL = stripURLForReferrer(referrerSource) + + // 5. Let referrerOrigin be the result of stripping referrerSource for use as + // a referrer, with the origin-only flag set to true. + const referrerOrigin = stripURLForReferrer(referrerSource, true) + + // 6. If the result of serializing referrerURL is a string whose length is + // greater than 4096, set referrerURL to referrerOrigin. + if (referrerURL.toString().length > 4096) { + referrerURL = referrerOrigin + } + + const areSameOrigin = sameOrigin(request, referrerURL) + const isNonPotentiallyTrustWorthy = isURLPotentiallyTrustworthy(referrerURL) && + !isURLPotentiallyTrustworthy(request.url) + + // 8. Execute the switch statements corresponding to the value of policy: + switch (policy) { + case 'origin': return referrerOrigin != null ? referrerOrigin : stripURLForReferrer(referrerSource, true) + case 'unsafe-url': return referrerURL + case 'same-origin': + return areSameOrigin ? referrerOrigin : 'no-referrer' + case 'origin-when-cross-origin': + return areSameOrigin ? referrerURL : referrerOrigin + case 'strict-origin-when-cross-origin': { + const currentURL = requestCurrentURL(request) + + // 1. If the origin of referrerURL and the origin of request’s current + // URL are the same, then return referrerURL. + if (sameOrigin(referrerURL, currentURL)) { + return referrerURL + } + + // 2. If referrerURL is a potentially trustworthy URL and request’s + // current URL is not a potentially trustworthy URL, then return no + // referrer. + if (isURLPotentiallyTrustworthy(referrerURL) && !isURLPotentiallyTrustworthy(currentURL)) { + return 'no-referrer' + } + + // 3. Return referrerOrigin. + return referrerOrigin + } + case 'strict-origin': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + case 'no-referrer-when-downgrade': // eslint-disable-line + /** + * 1. If referrerURL is a potentially trustworthy URL and + * request’s current URL is not a potentially trustworthy URL, + * then return no referrer. + * 2. Return referrerOrigin + */ + + default: // eslint-disable-line + return isNonPotentiallyTrustWorthy ? 'no-referrer' : referrerOrigin + } +} + +/** + * @see https://w3c.github.io/webappsec-referrer-policy/#strip-url + * @param {URL} url + * @param {boolean|undefined} originOnly + */ +function stripURLForReferrer (url, originOnly) { + // 1. Assert: url is a URL. + assert(url instanceof URL) + + // 2. If url’s scheme is a local scheme, then return no referrer. + if (url.protocol === 'file:' || url.protocol === 'about:' || url.protocol === 'blank:') { + return 'no-referrer' + } + + // 3. Set url’s username to the empty string. + url.username = '' + + // 4. Set url’s password to the empty string. + url.password = '' + + // 5. Set url’s fragment to null. + url.hash = '' + + // 6. If the origin-only flag is true, then: + if (originOnly) { + // 1. Set url’s path to « the empty string ». + url.pathname = '' + + // 2. Set url’s query to null. + url.search = '' + } + + // 7. Return url. + return url +} + +function isURLPotentiallyTrustworthy (url) { + if (!(url instanceof URL)) { + return false + } + + // If child of about, return true + if (url.href === 'about:blank' || url.href === 'about:srcdoc') { + return true + } + + // If scheme is data, return true + if (url.protocol === 'data:') return true + + // If file, return true + if (url.protocol === 'file:') return true + + return isOriginPotentiallyTrustworthy(url.origin) + + function isOriginPotentiallyTrustworthy (origin) { + // If origin is explicitly null, return false + if (origin == null || origin === 'null') return false + + const originAsURL = new URL(origin) + + // If secure, return true + if (originAsURL.protocol === 'https:' || originAsURL.protocol === 'wss:') { + return true + } + + // If localhost or variants, return true + if (/^127(?:\.[0-9]+){0,2}\.[0-9]+$|^\[(?:0*:)*?:?0*1\]$/.test(originAsURL.hostname) || + (originAsURL.hostname === 'localhost' || originAsURL.hostname.includes('localhost.')) || + (originAsURL.hostname.endsWith('.localhost'))) { + return true + } + + // If any other, return false + return false + } +} + +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#does-response-match-metadatalist + * @param {Uint8Array} bytes + * @param {string} metadataList + */ +function bytesMatch (bytes, metadataList) { + // If node is not built with OpenSSL support, we cannot check + // a request's integrity, so allow it by default (the spec will + // allow requests if an invalid hash is given, as precedence). + /* istanbul ignore if: only if node is built with --without-ssl */ + if (crypto === undefined) { + return true + } + + // 1. Let parsedMetadata be the result of parsing metadataList. + const parsedMetadata = parseMetadata(metadataList) + + // 2. If parsedMetadata is no metadata, return true. + if (parsedMetadata === 'no metadata') { + return true + } + + // 3. If response is not eligible for integrity validation, return false. + // TODO + + // 4. If parsedMetadata is the empty set, return true. + if (parsedMetadata.length === 0) { + return true + } + + // 5. Let metadata be the result of getting the strongest + // metadata from parsedMetadata. + const strongest = getStrongestMetadata(parsedMetadata) + const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest) + + // 6. For each item in metadata: + for (const item of metadata) { + // 1. Let algorithm be the alg component of item. + const algorithm = item.algo + + // 2. Let expectedValue be the val component of item. + const expectedValue = item.hash + + // See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e + // "be liberal with padding". This is annoying, and it's not even in the spec. + + // 3. Let actualValue be the result of applying algorithm to bytes. + let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64') + + if (actualValue[actualValue.length - 1] === '=') { + if (actualValue[actualValue.length - 2] === '=') { + actualValue = actualValue.slice(0, -2) + } else { + actualValue = actualValue.slice(0, -1) + } + } + + // 4. If actualValue is a case-sensitive match for expectedValue, + // return true. + if (compareBase64Mixed(actualValue, expectedValue)) { + return true + } + } + + // 7. Return false. + return false +} + +// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options +// https://www.w3.org/TR/CSP2/#source-list-syntax +// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1 +const parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i + +/** + * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata + * @param {string} metadata + */ +function parseMetadata (metadata) { + // 1. Let result be the empty set. + /** @type {{ algo: string, hash: string }[]} */ + const result = [] + + // 2. Let empty be equal to true. + let empty = true + + // 3. For each token returned by splitting metadata on spaces: + for (const token of metadata.split(' ')) { + // 1. Set empty to false. + empty = false + + // 2. Parse token as a hash-with-options. + const parsedToken = parseHashWithOptions.exec(token) + + // 3. If token does not parse, continue to the next token. + if ( + parsedToken === null || + parsedToken.groups === undefined || + parsedToken.groups.algo === undefined + ) { + // Note: Chromium blocks the request at this point, but Firefox + // gives a warning that an invalid integrity was given. The + // correct behavior is to ignore these, and subsequently not + // check the integrity of the resource. + continue + } + + // 4. Let algorithm be the hash-algo component of token. + const algorithm = parsedToken.groups.algo.toLowerCase() + + // 5. If algorithm is a hash function recognized by the user + // agent, add the parsed token to result. + if (supportedHashes.includes(algorithm)) { + result.push(parsedToken.groups) + } + } + + // 4. Return no metadata if empty is true, otherwise return result. + if (empty === true) { + return 'no metadata' + } + + return result +} + +/** + * @param {{ algo: 'sha256' | 'sha384' | 'sha512' }[]} metadataList + */ +function getStrongestMetadata (metadataList) { + // Let algorithm be the algo component of the first item in metadataList. + // Can be sha256 + let algorithm = metadataList[0].algo + // If the algorithm is sha512, then it is the strongest + // and we can return immediately + if (algorithm[3] === '5') { + return algorithm + } + + for (let i = 1; i < metadataList.length; ++i) { + const metadata = metadataList[i] + // If the algorithm is sha512, then it is the strongest + // and we can break the loop immediately + if (metadata.algo[3] === '5') { + algorithm = 'sha512' + break + // If the algorithm is sha384, then a potential sha256 or sha384 is ignored + } else if (algorithm[3] === '3') { + continue + // algorithm is sha256, check if algorithm is sha384 and if so, set it as + // the strongest + } else if (metadata.algo[3] === '3') { + algorithm = 'sha384' + } + } + return algorithm +} + +function filterMetadataListByAlgorithm (metadataList, algorithm) { + if (metadataList.length === 1) { + return metadataList + } + + let pos = 0 + for (let i = 0; i < metadataList.length; ++i) { + if (metadataList[i].algo === algorithm) { + metadataList[pos++] = metadataList[i] + } + } + + metadataList.length = pos + + return metadataList +} + +/** + * Compares two base64 strings, allowing for base64url + * in the second string. + * +* @param {string} actualValue always base64 + * @param {string} expectedValue base64 or base64url + * @returns {boolean} + */ +function compareBase64Mixed (actualValue, expectedValue) { + if (actualValue.length !== expectedValue.length) { + return false + } + for (let i = 0; i < actualValue.length; ++i) { + if (actualValue[i] !== expectedValue[i]) { + if ( + (actualValue[i] === '+' && expectedValue[i] === '-') || + (actualValue[i] === '/' && expectedValue[i] === '_') + ) { + continue + } + return false + } + } + + return true +} + +// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request +function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) { + // TODO +} + +/** + * @link {https://html.spec.whatwg.org/multipage/origin.html#same-origin} + * @param {URL} A + * @param {URL} B + */ +function sameOrigin (A, B) { + // 1. If A and B are the same opaque origin, then return true. + if (A.origin === B.origin && A.origin === 'null') { + return true + } + + // 2. If A and B are both tuple origins and their schemes, + // hosts, and port are identical, then return true. + if (A.protocol === B.protocol && A.hostname === B.hostname && A.port === B.port) { + return true + } + + // 3. Return false. + return false +} + +function createDeferredPromise () { + let res + let rej + const promise = new Promise((resolve, reject) => { + res = resolve + rej = reject + }) + + return { promise, resolve: res, reject: rej } +} + +function isAborted (fetchParams) { + return fetchParams.controller.state === 'aborted' +} + +function isCancelled (fetchParams) { + return fetchParams.controller.state === 'aborted' || + fetchParams.controller.state === 'terminated' +} + +const normalizeMethodRecord = { + delete: 'DELETE', + DELETE: 'DELETE', + get: 'GET', + GET: 'GET', + head: 'HEAD', + HEAD: 'HEAD', + options: 'OPTIONS', + OPTIONS: 'OPTIONS', + post: 'POST', + POST: 'POST', + put: 'PUT', + PUT: 'PUT' +} + +// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`. +Object.setPrototypeOf(normalizeMethodRecord, null) + +/** + * @see https://fetch.spec.whatwg.org/#concept-method-normalize + * @param {string} method + */ +function normalizeMethod (method) { + return normalizeMethodRecord[method.toLowerCase()] ?? method +} + +// https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string +function serializeJavascriptValueToJSONString (value) { + // 1. Let result be ? Call(%JSON.stringify%, undefined, « value »). + const result = JSON.stringify(value) + + // 2. If result is undefined, then throw a TypeError. + if (result === undefined) { + throw new TypeError('Value is not JSON serializable') + } + + // 3. Assert: result is a string. + assert(typeof result === 'string') + + // 4. Return result. + return result +} + +// https://tc39.es/ecma262/#sec-%25iteratorprototype%25-object +const esIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]())) + +/** + * @see https://webidl.spec.whatwg.org/#dfn-iterator-prototype-object + * @param {() => unknown[]} iterator + * @param {string} name name of the instance + * @param {'key'|'value'|'key+value'} kind + */ +function makeIterator (iterator, name, kind) { + const object = { + index: 0, + kind, + target: iterator + } + + const i = { + next () { + // 1. Let interface be the interface for which the iterator prototype object exists. + + // 2. Let thisValue be the this value. + + // 3. Let object be ? ToObject(thisValue). + + // 4. If object is a platform object, then perform a security + // check, passing: + + // 5. If object is not a default iterator object for interface, + // then throw a TypeError. + if (Object.getPrototypeOf(this) !== i) { + throw new TypeError( + `'next' called on an object that does not implement interface ${name} Iterator.` + ) + } + + // 6. Let index be object’s index. + // 7. Let kind be object’s kind. + // 8. Let values be object’s target's value pairs to iterate over. + const { index, kind, target } = object + const values = target() + + // 9. Let len be the length of values. + const len = values.length + + // 10. If index is greater than or equal to len, then return + // CreateIterResultObject(undefined, true). + if (index >= len) { + return { value: undefined, done: true } + } + + // 11. Let pair be the entry in values at index index. + const pair = values[index] + + // 12. Set object’s index to index + 1. + object.index = index + 1 + + // 13. Return the iterator result for pair and kind. + return iteratorResult(pair, kind) + }, + // The class string of an iterator prototype object for a given interface is the + // result of concatenating the identifier of the interface and the string " Iterator". + [Symbol.toStringTag]: `${name} Iterator` + } + + // The [[Prototype]] internal slot of an iterator prototype object must be %IteratorPrototype%. + Object.setPrototypeOf(i, esIteratorPrototype) + // esIteratorPrototype needs to be the prototype of i + // which is the prototype of an empty object. Yes, it's confusing. + return Object.setPrototypeOf({}, i) +} + +// https://webidl.spec.whatwg.org/#iterator-result +function iteratorResult (pair, kind) { + let result + + // 1. Let result be a value determined by the value of kind: + switch (kind) { + case 'key': { + // 1. Let idlKey be pair’s key. + // 2. Let key be the result of converting idlKey to an + // ECMAScript value. + // 3. result is key. + result = pair[0] + break + } + case 'value': { + // 1. Let idlValue be pair’s value. + // 2. Let value be the result of converting idlValue to + // an ECMAScript value. + // 3. result is value. + result = pair[1] + break + } + case 'key+value': { + // 1. Let idlKey be pair’s key. + // 2. Let idlValue be pair’s value. + // 3. Let key be the result of converting idlKey to an + // ECMAScript value. + // 4. Let value be the result of converting idlValue to + // an ECMAScript value. + // 5. Let array be ! ArrayCreate(2). + // 6. Call ! CreateDataProperty(array, "0", key). + // 7. Call ! CreateDataProperty(array, "1", value). + // 8. result is array. + result = pair + break + } + } + + // 2. Return CreateIterResultObject(result, false). + return { value: result, done: false } +} + +/** + * @see https://fetch.spec.whatwg.org/#body-fully-read + */ +async function fullyReadBody (body, processBody, processBodyError) { + // 1. If taskDestination is null, then set taskDestination to + // the result of starting a new parallel queue. + + // 2. Let successSteps given a byte sequence bytes be to queue a + // fetch task to run processBody given bytes, with taskDestination. + const successSteps = processBody + + // 3. Let errorSteps be to queue a fetch task to run processBodyError, + // with taskDestination. + const errorSteps = processBodyError + + // 4. Let reader be the result of getting a reader for body’s stream. + // If that threw an exception, then run errorSteps with that + // exception and return. + let reader + + try { + reader = body.stream.getReader() + } catch (e) { + errorSteps(e) + return + } + + // 5. Read all bytes from reader, given successSteps and errorSteps. + try { + const result = await readAllBytes(reader) + successSteps(result) + } catch (e) { + errorSteps(e) + } +} + +/** @type {ReadableStream} */ +let ReadableStream = globalThis.ReadableStream + +function isReadableStreamLike (stream) { + if (!ReadableStream) { + ReadableStream = (__nccwpck_require__(63774).ReadableStream) + } + + return stream instanceof ReadableStream || ( + stream[Symbol.toStringTag] === 'ReadableStream' && + typeof stream.tee === 'function' + ) +} + +const MAXIMUM_ARGUMENT_LENGTH = 65535 + +/** + * @see https://infra.spec.whatwg.org/#isomorphic-decode + * @param {number[]|Uint8Array} input + */ +function isomorphicDecode (input) { + // 1. To isomorphic decode a byte sequence input, return a string whose code point + // length is equal to input’s length and whose code points have the same values + // as the values of input’s bytes, in the same order. + + if (input.length < MAXIMUM_ARGUMENT_LENGTH) { + return String.fromCharCode(...input) + } + + return input.reduce((previous, current) => previous + String.fromCharCode(current), '') +} + +/** + * @param {ReadableStreamController} controller + */ +function readableStreamClose (controller) { + try { + controller.close() + } catch (err) { + // TODO: add comment explaining why this error occurs. + if (!err.message.includes('Controller is already closed')) { + throw err + } + } +} + +/** + * @see https://infra.spec.whatwg.org/#isomorphic-encode + * @param {string} input + */ +function isomorphicEncode (input) { + // 1. Assert: input contains no code points greater than U+00FF. + for (let i = 0; i < input.length; i++) { + assert(input.charCodeAt(i) <= 0xFF) + } + + // 2. Return a byte sequence whose length is equal to input’s code + // point length and whose bytes have the same values as the + // values of input’s code points, in the same order + return input +} + +/** + * @see https://streams.spec.whatwg.org/#readablestreamdefaultreader-read-all-bytes + * @see https://streams.spec.whatwg.org/#read-loop + * @param {ReadableStreamDefaultReader} reader + */ +async function readAllBytes (reader) { + const bytes = [] + let byteLength = 0 + + while (true) { + const { done, value: chunk } = await reader.read() + + if (done) { + // 1. Call successSteps with bytes. + return Buffer.concat(bytes, byteLength) + } + + // 1. If chunk is not a Uint8Array object, call failureSteps + // with a TypeError and abort these steps. + if (!isUint8Array(chunk)) { + throw new TypeError('Received non-Uint8Array chunk') + } + + // 2. Append the bytes represented by chunk to bytes. + bytes.push(chunk) + byteLength += chunk.length + + // 3. Read-loop given reader, bytes, successSteps, and failureSteps. + } +} + +/** + * @see https://fetch.spec.whatwg.org/#is-local + * @param {URL} url + */ +function urlIsLocal (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:' +} + +/** + * @param {string|URL} url + */ +function urlHasHttpsScheme (url) { + if (typeof url === 'string') { + return url.startsWith('https:') + } + + return url.protocol === 'https:' +} + +/** + * @see https://fetch.spec.whatwg.org/#http-scheme + * @param {URL} url + */ +function urlIsHttpHttpsScheme (url) { + assert('protocol' in url) // ensure it's a url object + + const protocol = url.protocol + + return protocol === 'http:' || protocol === 'https:' +} + +/** + * Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0. + */ +const hasOwn = Object.hasOwn || ((dict, key) => Object.prototype.hasOwnProperty.call(dict, key)) + +module.exports = { + isAborted, + isCancelled, + createDeferredPromise, + ReadableStreamFrom, + toUSVString, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + coarsenedSharedCurrentTime, + determineRequestsReferrer, + makePolicyContainer, + clonePolicyContainer, + appendFetchMetadata, + appendRequestOriginHeader, + TAOCheck, + corsCheck, + crossOriginResourcePolicyCheck, + createOpaqueTimingInfo, + setRequestReferrerPolicyOnRedirect, + isValidHTTPToken, + requestBadPort, + requestCurrentURL, + responseURL, + responseLocationURL, + isBlobLike, + isURLPotentiallyTrustworthy, + isValidReasonPhrase, + sameOrigin, + normalizeMethod, + serializeJavascriptValueToJSONString, + makeIterator, + isValidHeaderName, + isValidHeaderValue, + hasOwn, + isErrorLike, + fullyReadBody, + bytesMatch, + isReadableStreamLike, + readableStreamClose, + isomorphicEncode, + isomorphicDecode, + urlIsLocal, + urlHasHttpsScheme, + urlIsHttpHttpsScheme, + readAllBytes, + normalizeMethodRecord, + parseMetadata +} + + +/***/ }), + +/***/ 74222: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { types } = __nccwpck_require__(39023) +const { hasOwn, toUSVString } = __nccwpck_require__(15523) + +/** @type {import('../../types/webidl').Webidl} */ +const webidl = {} +webidl.converters = {} +webidl.util = {} +webidl.errors = {} + +webidl.errors.exception = function (message) { + return new TypeError(`${message.header}: ${message.message}`) +} + +webidl.errors.conversionFailed = function (context) { + const plural = context.types.length === 1 ? '' : ' one of' + const message = + `${context.argument} could not be converted to` + + `${plural}: ${context.types.join(', ')}.` + + return webidl.errors.exception({ + header: context.prefix, + message + }) +} + +webidl.errors.invalidArgument = function (context) { + return webidl.errors.exception({ + header: context.prefix, + message: `"${context.value}" is an invalid ${context.type}.` + }) +} + +// https://webidl.spec.whatwg.org/#implements +webidl.brandCheck = function (V, I, opts = undefined) { + if (opts?.strict !== false && !(V instanceof I)) { + throw new TypeError('Illegal invocation') + } else { + return V?.[Symbol.toStringTag] === I.prototype[Symbol.toStringTag] + } +} + +webidl.argumentLengthCheck = function ({ length }, min, ctx) { + if (length < min) { + throw webidl.errors.exception({ + message: `${min} argument${min !== 1 ? 's' : ''} required, ` + + `but${length ? ' only' : ''} ${length} found.`, + ...ctx + }) + } +} + +webidl.illegalConstructor = function () { + throw webidl.errors.exception({ + header: 'TypeError', + message: 'Illegal constructor' + }) +} + +// https://tc39.es/ecma262/#sec-ecmascript-data-types-and-values +webidl.util.Type = function (V) { + switch (typeof V) { + case 'undefined': return 'Undefined' + case 'boolean': return 'Boolean' + case 'string': return 'String' + case 'symbol': return 'Symbol' + case 'number': return 'Number' + case 'bigint': return 'BigInt' + case 'function': + case 'object': { + if (V === null) { + return 'Null' + } + + return 'Object' + } + } +} + +// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint +webidl.util.ConvertToInt = function (V, bitLength, signedness, opts = {}) { + let upperBound + let lowerBound + + // 1. If bitLength is 64, then: + if (bitLength === 64) { + // 1. Let upperBound be 2^53 − 1. + upperBound = Math.pow(2, 53) - 1 + + // 2. If signedness is "unsigned", then let lowerBound be 0. + if (signedness === 'unsigned') { + lowerBound = 0 + } else { + // 3. Otherwise let lowerBound be −2^53 + 1. + lowerBound = Math.pow(-2, 53) + 1 + } + } else if (signedness === 'unsigned') { + // 2. Otherwise, if signedness is "unsigned", then: + + // 1. Let lowerBound be 0. + lowerBound = 0 + + // 2. Let upperBound be 2^bitLength − 1. + upperBound = Math.pow(2, bitLength) - 1 + } else { + // 3. Otherwise: + + // 1. Let lowerBound be -2^bitLength − 1. + lowerBound = Math.pow(-2, bitLength) - 1 + + // 2. Let upperBound be 2^bitLength − 1 − 1. + upperBound = Math.pow(2, bitLength - 1) - 1 + } + + // 4. Let x be ? ToNumber(V). + let x = Number(V) + + // 5. If x is −0, then set x to +0. + if (x === 0) { + x = 0 + } + + // 6. If the conversion is to an IDL type associated + // with the [EnforceRange] extended attribute, then: + if (opts.enforceRange === true) { + // 1. If x is NaN, +∞, or −∞, then throw a TypeError. + if ( + Number.isNaN(x) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Could not convert ${V} to an integer.` + }) + } + + // 2. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) + + // 3. If x < lowerBound or x > upperBound, then + // throw a TypeError. + if (x < lowerBound || x > upperBound) { + throw webidl.errors.exception({ + header: 'Integer conversion', + message: `Value must be between ${lowerBound}-${upperBound}, got ${x}.` + }) + } + + // 4. Return x. + return x + } + + // 7. If x is not NaN and the conversion is to an IDL + // type associated with the [Clamp] extended + // attribute, then: + if (!Number.isNaN(x) && opts.clamp === true) { + // 1. Set x to min(max(x, lowerBound), upperBound). + x = Math.min(Math.max(x, lowerBound), upperBound) + + // 2. Round x to the nearest integer, choosing the + // even integer if it lies halfway between two, + // and choosing +0 rather than −0. + if (Math.floor(x) % 2 === 0) { + x = Math.floor(x) + } else { + x = Math.ceil(x) + } + + // 3. Return x. + return x + } + + // 8. If x is NaN, +0, +∞, or −∞, then return +0. + if ( + Number.isNaN(x) || + (x === 0 && Object.is(0, x)) || + x === Number.POSITIVE_INFINITY || + x === Number.NEGATIVE_INFINITY + ) { + return 0 + } + + // 9. Set x to IntegerPart(x). + x = webidl.util.IntegerPart(x) + + // 10. Set x to x modulo 2^bitLength. + x = x % Math.pow(2, bitLength) + + // 11. If signedness is "signed" and x ≥ 2^bitLength − 1, + // then return x − 2^bitLength. + if (signedness === 'signed' && x >= Math.pow(2, bitLength) - 1) { + return x - Math.pow(2, bitLength) + } + + // 12. Otherwise, return x. + return x +} + +// https://webidl.spec.whatwg.org/#abstract-opdef-integerpart +webidl.util.IntegerPart = function (n) { + // 1. Let r be floor(abs(n)). + const r = Math.floor(Math.abs(n)) + + // 2. If n < 0, then return -1 × r. + if (n < 0) { + return -1 * r + } + + // 3. Otherwise, return r. + return r +} + +// https://webidl.spec.whatwg.org/#es-sequence +webidl.sequenceConverter = function (converter) { + return (V) => { + // 1. If Type(V) is not Object, throw a TypeError. + if (webidl.util.Type(V) !== 'Object') { + throw webidl.errors.exception({ + header: 'Sequence', + message: `Value of type ${webidl.util.Type(V)} is not an Object.` + }) + } + + // 2. Let method be ? GetMethod(V, @@iterator). + /** @type {Generator} */ + const method = V?.[Symbol.iterator]?.() + const seq = [] + + // 3. If method is undefined, throw a TypeError. + if ( + method === undefined || + typeof method.next !== 'function' + ) { + throw webidl.errors.exception({ + header: 'Sequence', + message: 'Object is not an iterator.' + }) + } + + // https://webidl.spec.whatwg.org/#create-sequence-from-iterable + while (true) { + const { done, value } = method.next() + + if (done) { + break + } + + seq.push(converter(value)) + } + + return seq + } +} + +// https://webidl.spec.whatwg.org/#es-to-record +webidl.recordConverter = function (keyConverter, valueConverter) { + return (O) => { + // 1. If Type(O) is not Object, throw a TypeError. + if (webidl.util.Type(O) !== 'Object') { + throw webidl.errors.exception({ + header: 'Record', + message: `Value of type ${webidl.util.Type(O)} is not an Object.` + }) + } + + // 2. Let result be a new empty instance of record. + const result = {} + + if (!types.isProxy(O)) { + // Object.keys only returns enumerable properties + const keys = Object.keys(O) + + for (const key of keys) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key) + + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key]) + + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } + + // 5. Return result. + return result + } + + // 3. Let keys be ? O.[[OwnPropertyKeys]](). + const keys = Reflect.ownKeys(O) + + // 4. For each key of keys. + for (const key of keys) { + // 1. Let desc be ? O.[[GetOwnProperty]](key). + const desc = Reflect.getOwnPropertyDescriptor(O, key) + + // 2. If desc is not undefined and desc.[[Enumerable]] is true: + if (desc?.enumerable) { + // 1. Let typedKey be key converted to an IDL value of type K. + const typedKey = keyConverter(key) + + // 2. Let value be ? Get(O, key). + // 3. Let typedValue be value converted to an IDL value of type V. + const typedValue = valueConverter(O[key]) + + // 4. Set result[typedKey] to typedValue. + result[typedKey] = typedValue + } + } + + // 5. Return result. + return result + } +} + +webidl.interfaceConverter = function (i) { + return (V, opts = {}) => { + if (opts.strict !== false && !(V instanceof i)) { + throw webidl.errors.exception({ + header: i.name, + message: `Expected ${V} to be an instance of ${i.name}.` + }) + } + + return V + } +} + +webidl.dictionaryConverter = function (converters) { + return (dictionary) => { + const type = webidl.util.Type(dictionary) + const dict = {} + + if (type === 'Null' || type === 'Undefined') { + return dict + } else if (type !== 'Object') { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `Expected ${dictionary} to be one of: Null, Undefined, Object.` + }) + } + + for (const options of converters) { + const { key, defaultValue, required, converter } = options + + if (required === true) { + if (!hasOwn(dictionary, key)) { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `Missing required key "${key}".` + }) + } + } + + let value = dictionary[key] + const hasDefault = hasOwn(options, 'defaultValue') + + // Only use defaultValue if value is undefined and + // a defaultValue options was provided. + if (hasDefault && value !== null) { + value = value ?? defaultValue + } + + // A key can be optional and have no default value. + // When this happens, do not perform a conversion, + // and do not assign the key a value. + if (required || hasDefault || value !== undefined) { + value = converter(value) + + if ( + options.allowedValues && + !options.allowedValues.includes(value) + ) { + throw webidl.errors.exception({ + header: 'Dictionary', + message: `${value} is not an accepted type. Expected one of ${options.allowedValues.join(', ')}.` + }) + } + + dict[key] = value + } + } + + return dict + } +} + +webidl.nullableConverter = function (converter) { + return (V) => { + if (V === null) { + return V + } + + return converter(V) + } +} + +// https://webidl.spec.whatwg.org/#es-DOMString +webidl.converters.DOMString = function (V, opts = {}) { + // 1. If V is null and the conversion is to an IDL type + // associated with the [LegacyNullToEmptyString] + // extended attribute, then return the DOMString value + // that represents the empty string. + if (V === null && opts.legacyNullToEmptyString) { + return '' + } + + // 2. Let x be ? ToString(V). + if (typeof V === 'symbol') { + throw new TypeError('Could not convert argument of type symbol to string.') + } + + // 3. Return the IDL DOMString value that represents the + // same sequence of code units as the one the + // ECMAScript String value x represents. + return String(V) +} + +// https://webidl.spec.whatwg.org/#es-ByteString +webidl.converters.ByteString = function (V) { + // 1. Let x be ? ToString(V). + // Note: DOMString converter perform ? ToString(V) + const x = webidl.converters.DOMString(V) + + // 2. If the value of any element of x is greater than + // 255, then throw a TypeError. + for (let index = 0; index < x.length; index++) { + if (x.charCodeAt(index) > 255) { + throw new TypeError( + 'Cannot convert argument to a ByteString because the character at ' + + `index ${index} has a value of ${x.charCodeAt(index)} which is greater than 255.` + ) + } + } + + // 3. Return an IDL ByteString value whose length is the + // length of x, and where the value of each element is + // the value of the corresponding element of x. + return x +} + +// https://webidl.spec.whatwg.org/#es-USVString +webidl.converters.USVString = toUSVString + +// https://webidl.spec.whatwg.org/#es-boolean +webidl.converters.boolean = function (V) { + // 1. Let x be the result of computing ToBoolean(V). + const x = Boolean(V) + + // 2. Return the IDL boolean value that is the one that represents + // the same truth value as the ECMAScript Boolean value x. + return x +} + +// https://webidl.spec.whatwg.org/#es-any +webidl.converters.any = function (V) { + return V +} + +// https://webidl.spec.whatwg.org/#es-long-long +webidl.converters['long long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 64, "signed"). + const x = webidl.util.ConvertToInt(V, 64, 'signed') + + // 2. Return the IDL long long value that represents + // the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-long-long +webidl.converters['unsigned long long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 64, "unsigned"). + const x = webidl.util.ConvertToInt(V, 64, 'unsigned') + + // 2. Return the IDL unsigned long long value that + // represents the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-long +webidl.converters['unsigned long'] = function (V) { + // 1. Let x be ? ConvertToInt(V, 32, "unsigned"). + const x = webidl.util.ConvertToInt(V, 32, 'unsigned') + + // 2. Return the IDL unsigned long value that + // represents the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#es-unsigned-short +webidl.converters['unsigned short'] = function (V, opts) { + // 1. Let x be ? ConvertToInt(V, 16, "unsigned"). + const x = webidl.util.ConvertToInt(V, 16, 'unsigned', opts) + + // 2. Return the IDL unsigned short value that represents + // the same numeric value as x. + return x +} + +// https://webidl.spec.whatwg.org/#idl-ArrayBuffer +webidl.converters.ArrayBuffer = function (V, opts = {}) { + // 1. If Type(V) is not Object, or V does not have an + // [[ArrayBufferData]] internal slot, then throw a + // TypeError. + // see: https://tc39.es/ecma262/#sec-properties-of-the-arraybuffer-instances + // see: https://tc39.es/ecma262/#sec-properties-of-the-sharedarraybuffer-instances + if ( + webidl.util.Type(V) !== 'Object' || + !types.isAnyArrayBuffer(V) + ) { + throw webidl.errors.conversionFailed({ + prefix: `${V}`, + argument: `${V}`, + types: ['ArrayBuffer'] + }) + } + + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V) is true, then throw a + // TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V) is true, then throw a + // TypeError. + // Note: resizable ArrayBuffers are currently a proposal. + + // 4. Return the IDL ArrayBuffer value that is a + // reference to the same object as V. + return V +} + +webidl.converters.TypedArray = function (V, T, opts = {}) { + // 1. Let T be the IDL type V is being converted to. + + // 2. If Type(V) is not Object, or V does not have a + // [[TypedArrayName]] internal slot with a value + // equal to T’s name, then throw a TypeError. + if ( + webidl.util.Type(V) !== 'Object' || + !types.isTypedArray(V) || + V.constructor.name !== T.name + ) { + throw webidl.errors.conversionFailed({ + prefix: `${T.name}`, + argument: `${V}`, + types: [T.name] + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 4. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + // Note: resizable array buffers are currently a proposal + + // 5. Return the IDL value of type T that is a reference + // to the same object as V. + return V +} + +webidl.converters.DataView = function (V, opts = {}) { + // 1. If Type(V) is not Object, or V does not have a + // [[DataView]] internal slot, then throw a TypeError. + if (webidl.util.Type(V) !== 'Object' || !types.isDataView(V)) { + throw webidl.errors.exception({ + header: 'DataView', + message: 'Object is not a DataView.' + }) + } + + // 2. If the conversion is not to an IDL type associated + // with the [AllowShared] extended attribute, and + // IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, + // then throw a TypeError. + if (opts.allowShared === false && types.isSharedArrayBuffer(V.buffer)) { + throw webidl.errors.exception({ + header: 'ArrayBuffer', + message: 'SharedArrayBuffer is not allowed.' + }) + } + + // 3. If the conversion is not to an IDL type associated + // with the [AllowResizable] extended attribute, and + // IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is + // true, then throw a TypeError. + // Note: resizable ArrayBuffers are currently a proposal + + // 4. Return the IDL DataView value that is a reference + // to the same object as V. + return V +} + +// https://webidl.spec.whatwg.org/#BufferSource +webidl.converters.BufferSource = function (V, opts = {}) { + if (types.isAnyArrayBuffer(V)) { + return webidl.converters.ArrayBuffer(V, opts) + } + + if (types.isTypedArray(V)) { + return webidl.converters.TypedArray(V, V.constructor) + } + + if (types.isDataView(V)) { + return webidl.converters.DataView(V, opts) + } + + throw new TypeError(`Could not convert ${V} to a BufferSource.`) +} + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.ByteString +) + +webidl.converters['sequence>'] = webidl.sequenceConverter( + webidl.converters['sequence'] +) + +webidl.converters['record'] = webidl.recordConverter( + webidl.converters.ByteString, + webidl.converters.ByteString +) + +module.exports = { + webidl +} + + +/***/ }), + +/***/ 40396: +/***/ ((module) => { + +"use strict"; + + +/** + * @see https://encoding.spec.whatwg.org/#concept-encoding-get + * @param {string|undefined} label + */ +function getEncoding (label) { + if (!label) { + return 'failure' + } + + // 1. Remove any leading and trailing ASCII whitespace from label. + // 2. If label is an ASCII case-insensitive match for any of the + // labels listed in the table below, then return the + // corresponding encoding; otherwise return failure. + switch (label.trim().toLowerCase()) { + case 'unicode-1-1-utf-8': + case 'unicode11utf8': + case 'unicode20utf8': + case 'utf-8': + case 'utf8': + case 'x-unicode20utf8': + return 'UTF-8' + case '866': + case 'cp866': + case 'csibm866': + case 'ibm866': + return 'IBM866' + case 'csisolatin2': + case 'iso-8859-2': + case 'iso-ir-101': + case 'iso8859-2': + case 'iso88592': + case 'iso_8859-2': + case 'iso_8859-2:1987': + case 'l2': + case 'latin2': + return 'ISO-8859-2' + case 'csisolatin3': + case 'iso-8859-3': + case 'iso-ir-109': + case 'iso8859-3': + case 'iso88593': + case 'iso_8859-3': + case 'iso_8859-3:1988': + case 'l3': + case 'latin3': + return 'ISO-8859-3' + case 'csisolatin4': + case 'iso-8859-4': + case 'iso-ir-110': + case 'iso8859-4': + case 'iso88594': + case 'iso_8859-4': + case 'iso_8859-4:1988': + case 'l4': + case 'latin4': + return 'ISO-8859-4' + case 'csisolatincyrillic': + case 'cyrillic': + case 'iso-8859-5': + case 'iso-ir-144': + case 'iso8859-5': + case 'iso88595': + case 'iso_8859-5': + case 'iso_8859-5:1988': + return 'ISO-8859-5' + case 'arabic': + case 'asmo-708': + case 'csiso88596e': + case 'csiso88596i': + case 'csisolatinarabic': + case 'ecma-114': + case 'iso-8859-6': + case 'iso-8859-6-e': + case 'iso-8859-6-i': + case 'iso-ir-127': + case 'iso8859-6': + case 'iso88596': + case 'iso_8859-6': + case 'iso_8859-6:1987': + return 'ISO-8859-6' + case 'csisolatingreek': + case 'ecma-118': + case 'elot_928': + case 'greek': + case 'greek8': + case 'iso-8859-7': + case 'iso-ir-126': + case 'iso8859-7': + case 'iso88597': + case 'iso_8859-7': + case 'iso_8859-7:1987': + case 'sun_eu_greek': + return 'ISO-8859-7' + case 'csiso88598e': + case 'csisolatinhebrew': + case 'hebrew': + case 'iso-8859-8': + case 'iso-8859-8-e': + case 'iso-ir-138': + case 'iso8859-8': + case 'iso88598': + case 'iso_8859-8': + case 'iso_8859-8:1988': + case 'visual': + return 'ISO-8859-8' + case 'csiso88598i': + case 'iso-8859-8-i': + case 'logical': + return 'ISO-8859-8-I' + case 'csisolatin6': + case 'iso-8859-10': + case 'iso-ir-157': + case 'iso8859-10': + case 'iso885910': + case 'l6': + case 'latin6': + return 'ISO-8859-10' + case 'iso-8859-13': + case 'iso8859-13': + case 'iso885913': + return 'ISO-8859-13' + case 'iso-8859-14': + case 'iso8859-14': + case 'iso885914': + return 'ISO-8859-14' + case 'csisolatin9': + case 'iso-8859-15': + case 'iso8859-15': + case 'iso885915': + case 'iso_8859-15': + case 'l9': + return 'ISO-8859-15' + case 'iso-8859-16': + return 'ISO-8859-16' + case 'cskoi8r': + case 'koi': + case 'koi8': + case 'koi8-r': + case 'koi8_r': + return 'KOI8-R' + case 'koi8-ru': + case 'koi8-u': + return 'KOI8-U' + case 'csmacintosh': + case 'mac': + case 'macintosh': + case 'x-mac-roman': + return 'macintosh' + case 'iso-8859-11': + case 'iso8859-11': + case 'iso885911': + case 'tis-620': + case 'windows-874': + return 'windows-874' + case 'cp1250': + case 'windows-1250': + case 'x-cp1250': + return 'windows-1250' + case 'cp1251': + case 'windows-1251': + case 'x-cp1251': + return 'windows-1251' + case 'ansi_x3.4-1968': + case 'ascii': + case 'cp1252': + case 'cp819': + case 'csisolatin1': + case 'ibm819': + case 'iso-8859-1': + case 'iso-ir-100': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'iso_8859-1:1987': + case 'l1': + case 'latin1': + case 'us-ascii': + case 'windows-1252': + case 'x-cp1252': + return 'windows-1252' + case 'cp1253': + case 'windows-1253': + case 'x-cp1253': + return 'windows-1253' + case 'cp1254': + case 'csisolatin5': + case 'iso-8859-9': + case 'iso-ir-148': + case 'iso8859-9': + case 'iso88599': + case 'iso_8859-9': + case 'iso_8859-9:1989': + case 'l5': + case 'latin5': + case 'windows-1254': + case 'x-cp1254': + return 'windows-1254' + case 'cp1255': + case 'windows-1255': + case 'x-cp1255': + return 'windows-1255' + case 'cp1256': + case 'windows-1256': + case 'x-cp1256': + return 'windows-1256' + case 'cp1257': + case 'windows-1257': + case 'x-cp1257': + return 'windows-1257' + case 'cp1258': + case 'windows-1258': + case 'x-cp1258': + return 'windows-1258' + case 'x-mac-cyrillic': + case 'x-mac-ukrainian': + return 'x-mac-cyrillic' + case 'chinese': + case 'csgb2312': + case 'csiso58gb231280': + case 'gb2312': + case 'gb_2312': + case 'gb_2312-80': + case 'gbk': + case 'iso-ir-58': + case 'x-gbk': + return 'GBK' + case 'gb18030': + return 'gb18030' + case 'big5': + case 'big5-hkscs': + case 'cn-big5': + case 'csbig5': + case 'x-x-big5': + return 'Big5' + case 'cseucpkdfmtjapanese': + case 'euc-jp': + case 'x-euc-jp': + return 'EUC-JP' + case 'csiso2022jp': + case 'iso-2022-jp': + return 'ISO-2022-JP' + case 'csshiftjis': + case 'ms932': + case 'ms_kanji': + case 'shift-jis': + case 'shift_jis': + case 'sjis': + case 'windows-31j': + case 'x-sjis': + return 'Shift_JIS' + case 'cseuckr': + case 'csksc56011987': + case 'euc-kr': + case 'iso-ir-149': + case 'korean': + case 'ks_c_5601-1987': + case 'ks_c_5601-1989': + case 'ksc5601': + case 'ksc_5601': + case 'windows-949': + return 'EUC-KR' + case 'csiso2022kr': + case 'hz-gb-2312': + case 'iso-2022-cn': + case 'iso-2022-cn-ext': + case 'iso-2022-kr': + case 'replacement': + return 'replacement' + case 'unicodefffe': + case 'utf-16be': + return 'UTF-16BE' + case 'csunicode': + case 'iso-10646-ucs-2': + case 'ucs-2': + case 'unicode': + case 'unicodefeff': + case 'utf-16': + case 'utf-16le': + return 'UTF-16LE' + case 'x-user-defined': + return 'x-user-defined' + default: return 'failure' + } +} + +module.exports = { + getEncoding +} + + +/***/ }), + +/***/ 82160: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} = __nccwpck_require__(10165) +const { + kState, + kError, + kResult, + kEvents, + kAborted +} = __nccwpck_require__(86812) +const { webidl } = __nccwpck_require__(74222) +const { kEnumerableProperty } = __nccwpck_require__(3440) + +class FileReader extends EventTarget { + constructor () { + super() + + this[kState] = 'empty' + this[kResult] = null + this[kError] = null + this[kEvents] = { + loadend: null, + error: null, + abort: null, + load: null, + progress: null, + loadstart: null + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer + * @param {import('buffer').Blob} blob + */ + readAsArrayBuffer (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsArrayBuffer' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsArrayBuffer(blob) method, when invoked, + // must initiate a read operation for blob with ArrayBuffer. + readOperation(this, blob, 'ArrayBuffer') + } + + /** + * @see https://w3c.github.io/FileAPI/#readAsBinaryString + * @param {import('buffer').Blob} blob + */ + readAsBinaryString (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsBinaryString' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsBinaryString(blob) method, when invoked, + // must initiate a read operation for blob with BinaryString. + readOperation(this, blob, 'BinaryString') + } + + /** + * @see https://w3c.github.io/FileAPI/#readAsDataText + * @param {import('buffer').Blob} blob + * @param {string?} encoding + */ + readAsText (blob, encoding = undefined) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsText' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + if (encoding !== undefined) { + encoding = webidl.converters.DOMString(encoding) + } + + // The readAsText(blob, encoding) method, when invoked, + // must initiate a read operation for blob with Text and encoding. + readOperation(this, blob, 'Text', encoding) + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL + * @param {import('buffer').Blob} blob + */ + readAsDataURL (blob) { + webidl.brandCheck(this, FileReader) + + webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsDataURL' }) + + blob = webidl.converters.Blob(blob, { strict: false }) + + // The readAsDataURL(blob) method, when invoked, must + // initiate a read operation for blob with DataURL. + readOperation(this, blob, 'DataURL') + } + + /** + * @see https://w3c.github.io/FileAPI/#dfn-abort + */ + abort () { + // 1. If this's state is "empty" or if this's state is + // "done" set this's result to null and terminate + // this algorithm. + if (this[kState] === 'empty' || this[kState] === 'done') { + this[kResult] = null + return + } + + // 2. If this's state is "loading" set this's state to + // "done" and set this's result to null. + if (this[kState] === 'loading') { + this[kState] = 'done' + this[kResult] = null + } + + // 3. If there are any tasks from this on the file reading + // task source in an affiliated task queue, then remove + // those tasks from that task queue. + this[kAborted] = true + + // 4. Terminate the algorithm for the read method being processed. + // TODO + + // 5. Fire a progress event called abort at this. + fireAProgressEvent('abort', this) + + // 6. If this's state is not "loading", fire a progress + // event called loadend at this. + if (this[kState] !== 'loading') { + fireAProgressEvent('loadend', this) + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-readystate + */ + get readyState () { + webidl.brandCheck(this, FileReader) + + switch (this[kState]) { + case 'empty': return this.EMPTY + case 'loading': return this.LOADING + case 'done': return this.DONE + } + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-result + */ + get result () { + webidl.brandCheck(this, FileReader) + + // The result attribute’s getter, when invoked, must return + // this's result. + return this[kResult] + } + + /** + * @see https://w3c.github.io/FileAPI/#dom-filereader-error + */ + get error () { + webidl.brandCheck(this, FileReader) + + // The error attribute’s getter, when invoked, must return + // this's error. + return this[kError] + } + + get onloadend () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].loadend + } + + set onloadend (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].loadend) { + this.removeEventListener('loadend', this[kEvents].loadend) + } + + if (typeof fn === 'function') { + this[kEvents].loadend = fn + this.addEventListener('loadend', fn) + } else { + this[kEvents].loadend = null + } + } + + get onerror () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].error + } + + set onerror (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].error) { + this.removeEventListener('error', this[kEvents].error) + } + + if (typeof fn === 'function') { + this[kEvents].error = fn + this.addEventListener('error', fn) + } else { + this[kEvents].error = null + } + } + + get onloadstart () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].loadstart + } + + set onloadstart (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].loadstart) { + this.removeEventListener('loadstart', this[kEvents].loadstart) + } + + if (typeof fn === 'function') { + this[kEvents].loadstart = fn + this.addEventListener('loadstart', fn) + } else { + this[kEvents].loadstart = null + } + } + + get onprogress () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].progress + } + + set onprogress (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].progress) { + this.removeEventListener('progress', this[kEvents].progress) + } + + if (typeof fn === 'function') { + this[kEvents].progress = fn + this.addEventListener('progress', fn) + } else { + this[kEvents].progress = null + } + } + + get onload () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].load + } + + set onload (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].load) { + this.removeEventListener('load', this[kEvents].load) + } + + if (typeof fn === 'function') { + this[kEvents].load = fn + this.addEventListener('load', fn) + } else { + this[kEvents].load = null + } + } + + get onabort () { + webidl.brandCheck(this, FileReader) + + return this[kEvents].abort + } + + set onabort (fn) { + webidl.brandCheck(this, FileReader) + + if (this[kEvents].abort) { + this.removeEventListener('abort', this[kEvents].abort) + } + + if (typeof fn === 'function') { + this[kEvents].abort = fn + this.addEventListener('abort', fn) + } else { + this[kEvents].abort = null + } + } +} + +// https://w3c.github.io/FileAPI/#dom-filereader-empty +FileReader.EMPTY = FileReader.prototype.EMPTY = 0 +// https://w3c.github.io/FileAPI/#dom-filereader-loading +FileReader.LOADING = FileReader.prototype.LOADING = 1 +// https://w3c.github.io/FileAPI/#dom-filereader-done +FileReader.DONE = FileReader.prototype.DONE = 2 + +Object.defineProperties(FileReader.prototype, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors, + readAsArrayBuffer: kEnumerableProperty, + readAsBinaryString: kEnumerableProperty, + readAsText: kEnumerableProperty, + readAsDataURL: kEnumerableProperty, + abort: kEnumerableProperty, + readyState: kEnumerableProperty, + result: kEnumerableProperty, + error: kEnumerableProperty, + onloadstart: kEnumerableProperty, + onprogress: kEnumerableProperty, + onload: kEnumerableProperty, + onabort: kEnumerableProperty, + onerror: kEnumerableProperty, + onloadend: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'FileReader', + writable: false, + enumerable: false, + configurable: true + } +}) + +Object.defineProperties(FileReader, { + EMPTY: staticPropertyDescriptors, + LOADING: staticPropertyDescriptors, + DONE: staticPropertyDescriptors +}) + +module.exports = { + FileReader +} + + +/***/ }), + +/***/ 15976: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(74222) + +const kState = Symbol('ProgressEvent state') + +/** + * @see https://xhr.spec.whatwg.org/#progressevent + */ +class ProgressEvent extends Event { + constructor (type, eventInitDict = {}) { + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.ProgressEventInit(eventInitDict ?? {}) + + super(type, eventInitDict) + + this[kState] = { + lengthComputable: eventInitDict.lengthComputable, + loaded: eventInitDict.loaded, + total: eventInitDict.total + } + } + + get lengthComputable () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].lengthComputable + } + + get loaded () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].loaded + } + + get total () { + webidl.brandCheck(this, ProgressEvent) + + return this[kState].total + } +} + +webidl.converters.ProgressEventInit = webidl.dictionaryConverter([ + { + key: 'lengthComputable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'loaded', + converter: webidl.converters['unsigned long long'], + defaultValue: 0 + }, + { + key: 'total', + converter: webidl.converters['unsigned long long'], + defaultValue: 0 + }, + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: false + } +]) + +module.exports = { + ProgressEvent +} + + +/***/ }), + +/***/ 86812: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kState: Symbol('FileReader state'), + kResult: Symbol('FileReader result'), + kError: Symbol('FileReader error'), + kLastProgressEventFired: Symbol('FileReader last progress event fired timestamp'), + kEvents: Symbol('FileReader events'), + kAborted: Symbol('FileReader aborted') +} + + +/***/ }), + +/***/ 10165: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + kState, + kError, + kResult, + kAborted, + kLastProgressEventFired +} = __nccwpck_require__(86812) +const { ProgressEvent } = __nccwpck_require__(15976) +const { getEncoding } = __nccwpck_require__(40396) +const { DOMException } = __nccwpck_require__(87326) +const { serializeAMimeType, parseMIMEType } = __nccwpck_require__(94322) +const { types } = __nccwpck_require__(39023) +const { StringDecoder } = __nccwpck_require__(13193) +const { btoa } = __nccwpck_require__(20181) + +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} + +/** + * @see https://w3c.github.io/FileAPI/#readOperation + * @param {import('./filereader').FileReader} fr + * @param {import('buffer').Blob} blob + * @param {string} type + * @param {string?} encodingName + */ +function readOperation (fr, blob, type, encodingName) { + // 1. If fr’s state is "loading", throw an InvalidStateError + // DOMException. + if (fr[kState] === 'loading') { + throw new DOMException('Invalid state', 'InvalidStateError') + } + + // 2. Set fr’s state to "loading". + fr[kState] = 'loading' + + // 3. Set fr’s result to null. + fr[kResult] = null + + // 4. Set fr’s error to null. + fr[kError] = null + + // 5. Let stream be the result of calling get stream on blob. + /** @type {import('stream/web').ReadableStream} */ + const stream = blob.stream() + + // 6. Let reader be the result of getting a reader from stream. + const reader = stream.getReader() + + // 7. Let bytes be an empty byte sequence. + /** @type {Uint8Array[]} */ + const bytes = [] + + // 8. Let chunkPromise be the result of reading a chunk from + // stream with reader. + let chunkPromise = reader.read() + + // 9. Let isFirstChunk be true. + let isFirstChunk = true + + // 10. In parallel, while true: + // Note: "In parallel" just means non-blocking + // Note 2: readOperation itself cannot be async as double + // reading the body would then reject the promise, instead + // of throwing an error. + ;(async () => { + while (!fr[kAborted]) { + // 1. Wait for chunkPromise to be fulfilled or rejected. + try { + const { done, value } = await chunkPromise + + // 2. If chunkPromise is fulfilled, and isFirstChunk is + // true, queue a task to fire a progress event called + // loadstart at fr. + if (isFirstChunk && !fr[kAborted]) { + queueMicrotask(() => { + fireAProgressEvent('loadstart', fr) + }) + } + + // 3. Set isFirstChunk to false. + isFirstChunk = false + + // 4. If chunkPromise is fulfilled with an object whose + // done property is false and whose value property is + // a Uint8Array object, run these steps: + if (!done && types.isUint8Array(value)) { + // 1. Let bs be the byte sequence represented by the + // Uint8Array object. + + // 2. Append bs to bytes. + bytes.push(value) + + // 3. If roughly 50ms have passed since these steps + // were last invoked, queue a task to fire a + // progress event called progress at fr. + if ( + ( + fr[kLastProgressEventFired] === undefined || + Date.now() - fr[kLastProgressEventFired] >= 50 + ) && + !fr[kAborted] + ) { + fr[kLastProgressEventFired] = Date.now() + queueMicrotask(() => { + fireAProgressEvent('progress', fr) + }) + } + + // 4. Set chunkPromise to the result of reading a + // chunk from stream with reader. + chunkPromise = reader.read() + } else if (done) { + // 5. Otherwise, if chunkPromise is fulfilled with an + // object whose done property is true, queue a task + // to run the following steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' + + // 2. Let result be the result of package data given + // bytes, type, blob’s type, and encodingName. + try { + const result = packageData(bytes, type, blob.type, encodingName) + + // 4. Else: + + if (fr[kAborted]) { + return + } + + // 1. Set fr’s result to result. + fr[kResult] = result + + // 2. Fire a progress event called load at the fr. + fireAProgressEvent('load', fr) + } catch (error) { + // 3. If package data threw an exception error: + + // 1. Set fr’s error to error. + fr[kError] = error + + // 2. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) + } + + // 5. If fr’s state is not "loading", fire a progress + // event called loadend at the fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) + + break + } + } catch (error) { + if (fr[kAborted]) { + return + } + + // 6. Otherwise, if chunkPromise is rejected with an + // error error, queue a task to run the following + // steps and abort this algorithm: + queueMicrotask(() => { + // 1. Set fr’s state to "done". + fr[kState] = 'done' + + // 2. Set fr’s error to error. + fr[kError] = error + + // 3. Fire a progress event called error at fr. + fireAProgressEvent('error', fr) + + // 4. If fr’s state is not "loading", fire a progress + // event called loadend at fr. + if (fr[kState] !== 'loading') { + fireAProgressEvent('loadend', fr) + } + }) + + break + } + } + })() +} + +/** + * @see https://w3c.github.io/FileAPI/#fire-a-progress-event + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e The name of the event + * @param {import('./filereader').FileReader} reader + */ +function fireAProgressEvent (e, reader) { + // The progress event e does not bubble. e.bubbles must be false + // The progress event e is NOT cancelable. e.cancelable must be false + const event = new ProgressEvent(e, { + bubbles: false, + cancelable: false + }) + + reader.dispatchEvent(event) +} + +/** + * @see https://w3c.github.io/FileAPI/#blob-package-data + * @param {Uint8Array[]} bytes + * @param {string} type + * @param {string?} mimeType + * @param {string?} encodingName + */ +function packageData (bytes, type, mimeType, encodingName) { + // 1. A Blob has an associated package data algorithm, given + // bytes, a type, a optional mimeType, and a optional + // encodingName, which switches on type and runs the + // associated steps: + + switch (type) { + case 'DataURL': { + // 1. Return bytes as a DataURL [RFC2397] subject to + // the considerations below: + // * Use mimeType as part of the Data URL if it is + // available in keeping with the Data URL + // specification [RFC2397]. + // * If mimeType is not available return a Data URL + // without a media-type. [RFC2397]. + + // https://datatracker.ietf.org/doc/html/rfc2397#section-3 + // dataurl := "data:" [ mediatype ] [ ";base64" ] "," data + // mediatype := [ type "/" subtype ] *( ";" parameter ) + // data := *urlchar + // parameter := attribute "=" value + let dataURL = 'data:' + + const parsed = parseMIMEType(mimeType || 'application/octet-stream') + + if (parsed !== 'failure') { + dataURL += serializeAMimeType(parsed) + } + + dataURL += ';base64,' + + const decoder = new StringDecoder('latin1') + + for (const chunk of bytes) { + dataURL += btoa(decoder.write(chunk)) + } + + dataURL += btoa(decoder.end()) + + return dataURL + } + case 'Text': { + // 1. Let encoding be failure + let encoding = 'failure' + + // 2. If the encodingName is present, set encoding to the + // result of getting an encoding from encodingName. + if (encodingName) { + encoding = getEncoding(encodingName) + } + + // 3. If encoding is failure, and mimeType is present: + if (encoding === 'failure' && mimeType) { + // 1. Let type be the result of parse a MIME type + // given mimeType. + const type = parseMIMEType(mimeType) + + // 2. If type is not failure, set encoding to the result + // of getting an encoding from type’s parameters["charset"]. + if (type !== 'failure') { + encoding = getEncoding(type.parameters.get('charset')) + } + } + + // 4. If encoding is failure, then set encoding to UTF-8. + if (encoding === 'failure') { + encoding = 'UTF-8' + } + + // 5. Decode bytes using fallback encoding encoding, and + // return the result. + return decode(bytes, encoding) + } + case 'ArrayBuffer': { + // Return a new ArrayBuffer whose contents are bytes. + const sequence = combineByteSequences(bytes) + + return sequence.buffer + } + case 'BinaryString': { + // Return bytes as a binary string, in which every byte + // is represented by a code unit of equal value [0..255]. + let binaryString = '' + + const decoder = new StringDecoder('latin1') + + for (const chunk of bytes) { + binaryString += decoder.write(chunk) + } + + binaryString += decoder.end() + + return binaryString + } + } +} + +/** + * @see https://encoding.spec.whatwg.org/#decode + * @param {Uint8Array[]} ioQueue + * @param {string} encoding + */ +function decode (ioQueue, encoding) { + const bytes = combineByteSequences(ioQueue) + + // 1. Let BOMEncoding be the result of BOM sniffing ioQueue. + const BOMEncoding = BOMSniffing(bytes) + + let slice = 0 + + // 2. If BOMEncoding is non-null: + if (BOMEncoding !== null) { + // 1. Set encoding to BOMEncoding. + encoding = BOMEncoding + + // 2. Read three bytes from ioQueue, if BOMEncoding is + // UTF-8; otherwise read two bytes. + // (Do nothing with those bytes.) + slice = BOMEncoding === 'UTF-8' ? 3 : 2 + } + + // 3. Process a queue with an instance of encoding’s + // decoder, ioQueue, output, and "replacement". + + // 4. Return output. + + const sliced = bytes.slice(slice) + return new TextDecoder(encoding).decode(sliced) +} + +/** + * @see https://encoding.spec.whatwg.org/#bom-sniff + * @param {Uint8Array} ioQueue + */ +function BOMSniffing (ioQueue) { + // 1. Let BOM be the result of peeking 3 bytes from ioQueue, + // converted to a byte sequence. + const [a, b, c] = ioQueue + + // 2. For each of the rows in the table below, starting with + // the first one and going down, if BOM starts with the + // bytes given in the first column, then return the + // encoding given in the cell in the second column of that + // row. Otherwise, return null. + if (a === 0xEF && b === 0xBB && c === 0xBF) { + return 'UTF-8' + } else if (a === 0xFE && b === 0xFF) { + return 'UTF-16BE' + } else if (a === 0xFF && b === 0xFE) { + return 'UTF-16LE' + } + + return null +} + +/** + * @param {Uint8Array[]} sequences + */ +function combineByteSequences (sequences) { + const size = sequences.reduce((a, b) => { + return a + b.byteLength + }, 0) + + let offset = 0 + + return sequences.reduce((a, b) => { + a.set(b, offset) + offset += b.byteLength + return a + }, new Uint8Array(size)) +} + +module.exports = { + staticPropertyDescriptors, + readOperation, + fireAProgressEvent +} + + +/***/ }), + +/***/ 32581: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +// We include a version number for the Dispatcher API. In case of breaking changes, +// this version number must be increased to avoid conflicts. +const globalDispatcher = Symbol.for('undici.globalDispatcher.1') +const { InvalidArgumentError } = __nccwpck_require__(68707) +const Agent = __nccwpck_require__(59965) + +if (getGlobalDispatcher() === undefined) { + setGlobalDispatcher(new Agent()) +} + +function setGlobalDispatcher (agent) { + if (!agent || typeof agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument agent must implement Agent') + } + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }) +} + +function getGlobalDispatcher () { + return globalThis[globalDispatcher] +} + +module.exports = { + setGlobalDispatcher, + getGlobalDispatcher +} + + +/***/ }), + +/***/ 78840: +/***/ ((module) => { + +"use strict"; + + +module.exports = class DecoratorHandler { + constructor (handler) { + this.handler = handler + } + + onConnect (...args) { + return this.handler.onConnect(...args) + } + + onError (...args) { + return this.handler.onError(...args) + } + + onUpgrade (...args) { + return this.handler.onUpgrade(...args) + } + + onHeaders (...args) { + return this.handler.onHeaders(...args) + } + + onData (...args) { + return this.handler.onData(...args) + } + + onComplete (...args) { + return this.handler.onComplete(...args) + } + + onBodySent (...args) { + return this.handler.onBodySent(...args) + } +} + + +/***/ }), + +/***/ 48299: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const util = __nccwpck_require__(3440) +const { kBodyUsed } = __nccwpck_require__(36443) +const assert = __nccwpck_require__(42613) +const { InvalidArgumentError } = __nccwpck_require__(68707) +const EE = __nccwpck_require__(24434) + +const redirectableStatusCodes = [300, 301, 302, 303, 307, 308] + +const kBody = Symbol('body') + +class BodyAsyncIterable { + constructor (body) { + this[kBody] = body + this[kBodyUsed] = false + } + + async * [Symbol.asyncIterator] () { + assert(!this[kBodyUsed], 'disturbed') + this[kBodyUsed] = true + yield * this[kBody] + } +} + +class RedirectHandler { + constructor (dispatch, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError('maxRedirections must be a positive number') + } + + util.validateHandler(handler, opts.method, opts.upgrade) + + this.dispatch = dispatch + this.location = null + this.abort = null + this.opts = { ...opts, maxRedirections: 0 } // opts must be a copy + this.maxRedirections = maxRedirections + this.handler = handler + this.history = [] + + if (util.isStream(this.opts.body)) { + // TODO (fix): Provide some way for the user to cache the file to e.g. /tmp + // so that it can be dispatched again? + // TODO (fix): Do we need 100-expect support to provide a way to do this properly? + if (util.bodyLength(this.opts.body) === 0) { + this.opts.body + .on('data', function () { + assert(false) + }) + } + + if (typeof this.opts.body.readableDidRead !== 'boolean') { + this.opts.body[kBodyUsed] = false + EE.prototype.on.call(this.opts.body, 'data', function () { + this[kBodyUsed] = true + }) + } + } else if (this.opts.body && typeof this.opts.body.pipeTo === 'function') { + // TODO (fix): We can't access ReadableStream internal state + // to determine whether or not it has been disturbed. This is just + // a workaround. + this.opts.body = new BodyAsyncIterable(this.opts.body) + } else if ( + this.opts.body && + typeof this.opts.body !== 'string' && + !ArrayBuffer.isView(this.opts.body) && + util.isIterable(this.opts.body) + ) { + // TODO: Should we allow re-using iterable if !this.opts.idempotent + // or through some other flag? + this.opts.body = new BodyAsyncIterable(this.opts.body) + } + } + + onConnect (abort) { + this.abort = abort + this.handler.onConnect(abort, { history: this.history }) + } + + onUpgrade (statusCode, headers, socket) { + this.handler.onUpgrade(statusCode, headers, socket) + } + + onError (error) { + this.handler.onError(error) + } + + onHeaders (statusCode, headers, resume, statusText) { + this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) + ? null + : parseLocation(statusCode, headers) + + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)) + } + + if (!this.location) { + return this.handler.onHeaders(statusCode, headers, resume, statusText) + } + + const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) + const path = search ? `${pathname}${search}` : pathname + + // Remove headers referring to the original URL. + // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers. + // https://tools.ietf.org/html/rfc7231#section-6.4 + this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin) + this.opts.path = path + this.opts.origin = origin + this.opts.maxRedirections = 0 + this.opts.query = null + + // https://tools.ietf.org/html/rfc7231#section-6.4.4 + // In case of HTTP 303, always replace method to be either HEAD or GET + if (statusCode === 303 && this.opts.method !== 'HEAD') { + this.opts.method = 'GET' + this.opts.body = null + } + } + + onData (chunk) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 + + TLDR: undici always ignores 3xx response bodies. + + Redirection is used to serve the requested resource from another URL, so it is assumes that + no body is generated (and thus can be ignored). Even though generating a body is not prohibited. + + For status 301, 302, 303, 307 and 308 (the latter from RFC 7238), the specs mention that the body usually + (which means it's optional and not mandated) contain just an hyperlink to the value of + the Location response header, so the body can be ignored safely. + + For status 300, which is "Multiple Choices", the spec mentions both generating a Location + response header AND a response body with the other possible location to follow. + Since the spec explicitily chooses not to specify a format for such body and leave it to + servers and browsers implementors, we ignore the body as there is no specified way to eventually parse it. + */ + } else { + return this.handler.onData(chunk) + } + } + + onComplete (trailers) { + if (this.location) { + /* + https://tools.ietf.org/html/rfc7231#section-6.4 + + TLDR: undici always ignores 3xx response trailers as they are not expected in case of redirections + and neither are useful if present. + + See comment on onData method above for more detailed informations. + */ + + this.location = null + this.abort = null + + this.dispatch(this.opts, this) + } else { + this.handler.onComplete(trailers) + } + } + + onBodySent (chunk) { + if (this.handler.onBodySent) { + this.handler.onBodySent(chunk) + } + } +} + +function parseLocation (statusCode, headers) { + if (redirectableStatusCodes.indexOf(statusCode) === -1) { + return null + } + + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toString().toLowerCase() === 'location') { + return headers[i + 1] + } + } +} + +// https://tools.ietf.org/html/rfc7231#section-6.4.4 +function shouldRemoveHeader (header, removeContent, unknownOrigin) { + if (header.length === 4) { + return util.headerNameToString(header) === 'host' + } + if (removeContent && util.headerNameToString(header).startsWith('content-')) { + return true + } + if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) { + const name = util.headerNameToString(header) + return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization' + } + return false +} + +// https://tools.ietf.org/html/rfc7231#section-6.4 +function cleanRequestHeaders (headers, removeContent, unknownOrigin) { + const ret = [] + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]) + } + } + } else if (headers && typeof headers === 'object') { + for (const key of Object.keys(headers)) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, headers[key]) + } + } + } else { + assert(headers == null, 'headers must be an object or an array') + } + return ret +} + +module.exports = RedirectHandler + + +/***/ }), + +/***/ 53573: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const assert = __nccwpck_require__(42613) + +const { kRetryHandlerDefaultRetry } = __nccwpck_require__(36443) +const { RequestRetryError } = __nccwpck_require__(68707) +const { isDisturbed, parseHeaders, parseRangeHeader } = __nccwpck_require__(3440) + +function calculateRetryAfterHeader (retryAfter) { + const current = Date.now() + const diff = new Date(retryAfter).getTime() - current + + return diff +} + +class RetryHandler { + constructor (opts, handlers) { + const { retryOptions, ...dispatchOpts } = opts + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes + } = retryOptions ?? {} + + this.dispatch = handlers.dispatch + this.handler = handlers.handler + this.opts = dispatchOpts + this.abort = null + this.aborted = false + this.retryOpts = { + retry: retryFn ?? RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1000, // 30s, + timeout: minTimeout ?? 500, // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ['GET', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + 'ECONNRESET', + 'ECONNREFUSED', + 'ENOTFOUND', + 'ENETDOWN', + 'ENETUNREACH', + 'EHOSTDOWN', + 'EHOSTUNREACH', + 'EPIPE' + ] + } + + this.retryCount = 0 + this.start = 0 + this.end = null + this.etag = null + this.resume = null + + // Handle possible onConnect duplication + this.handler.onConnect(reason => { + this.aborted = true + if (this.abort) { + this.abort(reason) + } else { + this.reason = reason + } + }) + } + + onRequestSent () { + if (this.handler.onRequestSent) { + this.handler.onRequestSent() + } + } + + onUpgrade (statusCode, headers, socket) { + if (this.handler.onUpgrade) { + this.handler.onUpgrade(statusCode, headers, socket) + } + } + + onConnect (abort) { + if (this.aborted) { + abort(this.reason) + } else { + this.abort = abort + } + } + + onBodySent (chunk) { + if (this.handler.onBodySent) return this.handler.onBodySent(chunk) + } + + static [kRetryHandlerDefaultRetry] (err, { state, opts }, cb) { + const { statusCode, code, headers } = err + const { method, retryOptions } = opts + const { + maxRetries, + timeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions + let { counter, currentTimeout } = state + + currentTimeout = + currentTimeout != null && currentTimeout > 0 ? currentTimeout : timeout + + // Any code that is not a Undici's originated and allowed to retry + if ( + code && + code !== 'UND_ERR_REQ_RETRY' && + code !== 'UND_ERR_SOCKET' && + !errorCodes.includes(code) + ) { + cb(err) + return + } + + // If a set of method are provided and the current method is not in the list + if (Array.isArray(methods) && !methods.includes(method)) { + cb(err) + return + } + + // If a set of status code are provided and the current status code is not in the list + if ( + statusCode != null && + Array.isArray(statusCodes) && + !statusCodes.includes(statusCode) + ) { + cb(err) + return + } + + // If we reached the max number of retries + if (counter > maxRetries) { + cb(err) + return + } + + let retryAfterHeader = headers != null && headers['retry-after'] + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader) + retryAfterHeader = isNaN(retryAfterHeader) + ? calculateRetryAfterHeader(retryAfterHeader) + : retryAfterHeader * 1e3 // Retry-After is in seconds + } + + const retryTimeout = + retryAfterHeader > 0 + ? Math.min(retryAfterHeader, maxTimeout) + : Math.min(currentTimeout * timeoutFactor ** counter, maxTimeout) + + state.currentTimeout = retryTimeout + + setTimeout(() => cb(null), retryTimeout) + } + + onHeaders (statusCode, rawHeaders, resume, statusMessage) { + const headers = parseHeaders(rawHeaders) + + this.retryCount += 1 + + if (statusCode >= 300) { + this.abort( + new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Checkpoint for resume from where we left it + if (this.resume != null) { + this.resume = null + + if (statusCode !== 206) { + return true + } + + const contentRange = parseRangeHeader(headers['content-range']) + // If no content range + if (!contentRange) { + this.abort( + new RequestRetryError('Content-Range mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + // Let's start with a weak etag check + if (this.etag != null && this.etag !== headers.etag) { + this.abort( + new RequestRetryError('ETag mismatch', statusCode, { + headers, + count: this.retryCount + }) + ) + return false + } + + const { start, size, end = size } = contentRange + + assert(this.start === start, 'content-range mismatch') + assert(this.end == null || this.end === end, 'content-range mismatch') + + this.resume = resume + return true + } + + if (this.end == null) { + if (statusCode === 206) { + // First time we receive 206 + const range = parseRangeHeader(headers['content-range']) + + if (range == null) { + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const { start, size, end = size } = range + + assert( + start != null && Number.isFinite(start) && this.start !== start, + 'content-range mismatch' + ) + assert(Number.isFinite(start)) + assert( + end != null && Number.isFinite(end) && this.end !== end, + 'invalid content-length' + ) + + this.start = start + this.end = end + } + + // We make our best to checkpoint the body for further range headers + if (this.end == null) { + const contentLength = headers['content-length'] + this.end = contentLength != null ? Number(contentLength) : null + } + + assert(Number.isFinite(this.start)) + assert( + this.end == null || Number.isFinite(this.end), + 'invalid content-length' + ) + + this.resume = resume + this.etag = headers.etag != null ? headers.etag : null + + return this.handler.onHeaders( + statusCode, + rawHeaders, + resume, + statusMessage + ) + } + + const err = new RequestRetryError('Request failed', statusCode, { + headers, + count: this.retryCount + }) + + this.abort(err) + + return false + } + + onData (chunk) { + this.start += chunk.length + + return this.handler.onData(chunk) + } + + onComplete (rawTrailers) { + this.retryCount = 0 + return this.handler.onComplete(rawTrailers) + } + + onError (err) { + if (this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount++, currentTimeout: this.retryAfter }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + onRetry.bind(this) + ) + + function onRetry (err) { + if (err != null || this.aborted || isDisturbed(this.opts.body)) { + return this.handler.onError(err) + } + + if (this.start !== 0) { + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + range: `bytes=${this.start}-${this.end ?? ''}` + } + } + } + + try { + this.dispatch(this.opts, this) + } catch (err) { + this.handler.onError(err) + } + } + } +} + +module.exports = RetryHandler + + +/***/ }), + +/***/ 64415: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const RedirectHandler = __nccwpck_require__(48299) + +function createRedirectInterceptor ({ maxRedirections: defaultMaxRedirections }) { + return (dispatch) => { + return function Intercept (opts, handler) { + const { maxRedirections = defaultMaxRedirections } = opts + + if (!maxRedirections) { + return dispatch(opts, handler) + } + + const redirectHandler = new RedirectHandler(dispatch, maxRedirections, opts, handler) + opts = { ...opts, maxRedirections: 0 } // Stop sub dispatcher from also redirecting. + return dispatch(opts, redirectHandler) + } + } +} + +module.exports = createRedirectInterceptor + + +/***/ }), + +/***/ 52824: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SPECIAL_HEADERS = exports.HEADER_STATE = exports.MINOR = exports.MAJOR = exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS = exports.TOKEN = exports.STRICT_TOKEN = exports.HEX = exports.URL_CHAR = exports.STRICT_URL_CHAR = exports.USERINFO_CHARS = exports.MARK = exports.ALPHANUM = exports.NUM = exports.HEX_MAP = exports.NUM_MAP = exports.ALPHA = exports.FINISH = exports.H_METHOD_MAP = exports.METHOD_MAP = exports.METHODS_RTSP = exports.METHODS_ICE = exports.METHODS_HTTP = exports.METHODS = exports.LENIENT_FLAGS = exports.FLAGS = exports.TYPE = exports.ERROR = void 0; +const utils_1 = __nccwpck_require__(50172); +// C headers +var ERROR; +(function (ERROR) { + ERROR[ERROR["OK"] = 0] = "OK"; + ERROR[ERROR["INTERNAL"] = 1] = "INTERNAL"; + ERROR[ERROR["STRICT"] = 2] = "STRICT"; + ERROR[ERROR["LF_EXPECTED"] = 3] = "LF_EXPECTED"; + ERROR[ERROR["UNEXPECTED_CONTENT_LENGTH"] = 4] = "UNEXPECTED_CONTENT_LENGTH"; + ERROR[ERROR["CLOSED_CONNECTION"] = 5] = "CLOSED_CONNECTION"; + ERROR[ERROR["INVALID_METHOD"] = 6] = "INVALID_METHOD"; + ERROR[ERROR["INVALID_URL"] = 7] = "INVALID_URL"; + ERROR[ERROR["INVALID_CONSTANT"] = 8] = "INVALID_CONSTANT"; + ERROR[ERROR["INVALID_VERSION"] = 9] = "INVALID_VERSION"; + ERROR[ERROR["INVALID_HEADER_TOKEN"] = 10] = "INVALID_HEADER_TOKEN"; + ERROR[ERROR["INVALID_CONTENT_LENGTH"] = 11] = "INVALID_CONTENT_LENGTH"; + ERROR[ERROR["INVALID_CHUNK_SIZE"] = 12] = "INVALID_CHUNK_SIZE"; + ERROR[ERROR["INVALID_STATUS"] = 13] = "INVALID_STATUS"; + ERROR[ERROR["INVALID_EOF_STATE"] = 14] = "INVALID_EOF_STATE"; + ERROR[ERROR["INVALID_TRANSFER_ENCODING"] = 15] = "INVALID_TRANSFER_ENCODING"; + ERROR[ERROR["CB_MESSAGE_BEGIN"] = 16] = "CB_MESSAGE_BEGIN"; + ERROR[ERROR["CB_HEADERS_COMPLETE"] = 17] = "CB_HEADERS_COMPLETE"; + ERROR[ERROR["CB_MESSAGE_COMPLETE"] = 18] = "CB_MESSAGE_COMPLETE"; + ERROR[ERROR["CB_CHUNK_HEADER"] = 19] = "CB_CHUNK_HEADER"; + ERROR[ERROR["CB_CHUNK_COMPLETE"] = 20] = "CB_CHUNK_COMPLETE"; + ERROR[ERROR["PAUSED"] = 21] = "PAUSED"; + ERROR[ERROR["PAUSED_UPGRADE"] = 22] = "PAUSED_UPGRADE"; + ERROR[ERROR["PAUSED_H2_UPGRADE"] = 23] = "PAUSED_H2_UPGRADE"; + ERROR[ERROR["USER"] = 24] = "USER"; +})(ERROR = exports.ERROR || (exports.ERROR = {})); +var TYPE; +(function (TYPE) { + TYPE[TYPE["BOTH"] = 0] = "BOTH"; + TYPE[TYPE["REQUEST"] = 1] = "REQUEST"; + TYPE[TYPE["RESPONSE"] = 2] = "RESPONSE"; +})(TYPE = exports.TYPE || (exports.TYPE = {})); +var FLAGS; +(function (FLAGS) { + FLAGS[FLAGS["CONNECTION_KEEP_ALIVE"] = 1] = "CONNECTION_KEEP_ALIVE"; + FLAGS[FLAGS["CONNECTION_CLOSE"] = 2] = "CONNECTION_CLOSE"; + FLAGS[FLAGS["CONNECTION_UPGRADE"] = 4] = "CONNECTION_UPGRADE"; + FLAGS[FLAGS["CHUNKED"] = 8] = "CHUNKED"; + FLAGS[FLAGS["UPGRADE"] = 16] = "UPGRADE"; + FLAGS[FLAGS["CONTENT_LENGTH"] = 32] = "CONTENT_LENGTH"; + FLAGS[FLAGS["SKIPBODY"] = 64] = "SKIPBODY"; + FLAGS[FLAGS["TRAILING"] = 128] = "TRAILING"; + // 1 << 8 is unused + FLAGS[FLAGS["TRANSFER_ENCODING"] = 512] = "TRANSFER_ENCODING"; +})(FLAGS = exports.FLAGS || (exports.FLAGS = {})); +var LENIENT_FLAGS; +(function (LENIENT_FLAGS) { + LENIENT_FLAGS[LENIENT_FLAGS["HEADERS"] = 1] = "HEADERS"; + LENIENT_FLAGS[LENIENT_FLAGS["CHUNKED_LENGTH"] = 2] = "CHUNKED_LENGTH"; + LENIENT_FLAGS[LENIENT_FLAGS["KEEP_ALIVE"] = 4] = "KEEP_ALIVE"; +})(LENIENT_FLAGS = exports.LENIENT_FLAGS || (exports.LENIENT_FLAGS = {})); +var METHODS; +(function (METHODS) { + METHODS[METHODS["DELETE"] = 0] = "DELETE"; + METHODS[METHODS["GET"] = 1] = "GET"; + METHODS[METHODS["HEAD"] = 2] = "HEAD"; + METHODS[METHODS["POST"] = 3] = "POST"; + METHODS[METHODS["PUT"] = 4] = "PUT"; + /* pathological */ + METHODS[METHODS["CONNECT"] = 5] = "CONNECT"; + METHODS[METHODS["OPTIONS"] = 6] = "OPTIONS"; + METHODS[METHODS["TRACE"] = 7] = "TRACE"; + /* WebDAV */ + METHODS[METHODS["COPY"] = 8] = "COPY"; + METHODS[METHODS["LOCK"] = 9] = "LOCK"; + METHODS[METHODS["MKCOL"] = 10] = "MKCOL"; + METHODS[METHODS["MOVE"] = 11] = "MOVE"; + METHODS[METHODS["PROPFIND"] = 12] = "PROPFIND"; + METHODS[METHODS["PROPPATCH"] = 13] = "PROPPATCH"; + METHODS[METHODS["SEARCH"] = 14] = "SEARCH"; + METHODS[METHODS["UNLOCK"] = 15] = "UNLOCK"; + METHODS[METHODS["BIND"] = 16] = "BIND"; + METHODS[METHODS["REBIND"] = 17] = "REBIND"; + METHODS[METHODS["UNBIND"] = 18] = "UNBIND"; + METHODS[METHODS["ACL"] = 19] = "ACL"; + /* subversion */ + METHODS[METHODS["REPORT"] = 20] = "REPORT"; + METHODS[METHODS["MKACTIVITY"] = 21] = "MKACTIVITY"; + METHODS[METHODS["CHECKOUT"] = 22] = "CHECKOUT"; + METHODS[METHODS["MERGE"] = 23] = "MERGE"; + /* upnp */ + METHODS[METHODS["M-SEARCH"] = 24] = "M-SEARCH"; + METHODS[METHODS["NOTIFY"] = 25] = "NOTIFY"; + METHODS[METHODS["SUBSCRIBE"] = 26] = "SUBSCRIBE"; + METHODS[METHODS["UNSUBSCRIBE"] = 27] = "UNSUBSCRIBE"; + /* RFC-5789 */ + METHODS[METHODS["PATCH"] = 28] = "PATCH"; + METHODS[METHODS["PURGE"] = 29] = "PURGE"; + /* CalDAV */ + METHODS[METHODS["MKCALENDAR"] = 30] = "MKCALENDAR"; + /* RFC-2068, section 19.6.1.2 */ + METHODS[METHODS["LINK"] = 31] = "LINK"; + METHODS[METHODS["UNLINK"] = 32] = "UNLINK"; + /* icecast */ + METHODS[METHODS["SOURCE"] = 33] = "SOURCE"; + /* RFC-7540, section 11.6 */ + METHODS[METHODS["PRI"] = 34] = "PRI"; + /* RFC-2326 RTSP */ + METHODS[METHODS["DESCRIBE"] = 35] = "DESCRIBE"; + METHODS[METHODS["ANNOUNCE"] = 36] = "ANNOUNCE"; + METHODS[METHODS["SETUP"] = 37] = "SETUP"; + METHODS[METHODS["PLAY"] = 38] = "PLAY"; + METHODS[METHODS["PAUSE"] = 39] = "PAUSE"; + METHODS[METHODS["TEARDOWN"] = 40] = "TEARDOWN"; + METHODS[METHODS["GET_PARAMETER"] = 41] = "GET_PARAMETER"; + METHODS[METHODS["SET_PARAMETER"] = 42] = "SET_PARAMETER"; + METHODS[METHODS["REDIRECT"] = 43] = "REDIRECT"; + METHODS[METHODS["RECORD"] = 44] = "RECORD"; + /* RAOP */ + METHODS[METHODS["FLUSH"] = 45] = "FLUSH"; +})(METHODS = exports.METHODS || (exports.METHODS = {})); +exports.METHODS_HTTP = [ + METHODS.DELETE, + METHODS.GET, + METHODS.HEAD, + METHODS.POST, + METHODS.PUT, + METHODS.CONNECT, + METHODS.OPTIONS, + METHODS.TRACE, + METHODS.COPY, + METHODS.LOCK, + METHODS.MKCOL, + METHODS.MOVE, + METHODS.PROPFIND, + METHODS.PROPPATCH, + METHODS.SEARCH, + METHODS.UNLOCK, + METHODS.BIND, + METHODS.REBIND, + METHODS.UNBIND, + METHODS.ACL, + METHODS.REPORT, + METHODS.MKACTIVITY, + METHODS.CHECKOUT, + METHODS.MERGE, + METHODS['M-SEARCH'], + METHODS.NOTIFY, + METHODS.SUBSCRIBE, + METHODS.UNSUBSCRIBE, + METHODS.PATCH, + METHODS.PURGE, + METHODS.MKCALENDAR, + METHODS.LINK, + METHODS.UNLINK, + METHODS.PRI, + // TODO(indutny): should we allow it with HTTP? + METHODS.SOURCE, +]; +exports.METHODS_ICE = [ + METHODS.SOURCE, +]; +exports.METHODS_RTSP = [ + METHODS.OPTIONS, + METHODS.DESCRIBE, + METHODS.ANNOUNCE, + METHODS.SETUP, + METHODS.PLAY, + METHODS.PAUSE, + METHODS.TEARDOWN, + METHODS.GET_PARAMETER, + METHODS.SET_PARAMETER, + METHODS.REDIRECT, + METHODS.RECORD, + METHODS.FLUSH, + // For AirPlay + METHODS.GET, + METHODS.POST, +]; +exports.METHOD_MAP = utils_1.enumToMap(METHODS); +exports.H_METHOD_MAP = {}; +Object.keys(exports.METHOD_MAP).forEach((key) => { + if (/^H/.test(key)) { + exports.H_METHOD_MAP[key] = exports.METHOD_MAP[key]; + } +}); +var FINISH; +(function (FINISH) { + FINISH[FINISH["SAFE"] = 0] = "SAFE"; + FINISH[FINISH["SAFE_WITH_CB"] = 1] = "SAFE_WITH_CB"; + FINISH[FINISH["UNSAFE"] = 2] = "UNSAFE"; +})(FINISH = exports.FINISH || (exports.FINISH = {})); +exports.ALPHA = []; +for (let i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) { + // Upper case + exports.ALPHA.push(String.fromCharCode(i)); + // Lower case + exports.ALPHA.push(String.fromCharCode(i + 0x20)); +} +exports.NUM_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, +}; +exports.HEX_MAP = { + 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, + 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, + A: 0XA, B: 0XB, C: 0XC, D: 0XD, E: 0XE, F: 0XF, + a: 0xa, b: 0xb, c: 0xc, d: 0xd, e: 0xe, f: 0xf, +}; +exports.NUM = [ + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', +]; +exports.ALPHANUM = exports.ALPHA.concat(exports.NUM); +exports.MARK = ['-', '_', '.', '!', '~', '*', '\'', '(', ')']; +exports.USERINFO_CHARS = exports.ALPHANUM + .concat(exports.MARK) + .concat(['%', ';', ':', '&', '=', '+', '$', ',']); +// TODO(indutny): use RFC +exports.STRICT_URL_CHAR = [ + '!', '"', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + ':', ';', '<', '=', '>', + '@', '[', '\\', ']', '^', '_', + '`', + '{', '|', '}', '~', +].concat(exports.ALPHANUM); +exports.URL_CHAR = exports.STRICT_URL_CHAR + .concat(['\t', '\f']); +// All characters with 0x80 bit set to 1 +for (let i = 0x80; i <= 0xff; i++) { + exports.URL_CHAR.push(i); +} +exports.HEX = exports.NUM.concat(['a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']); +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +exports.STRICT_TOKEN = [ + '!', '#', '$', '%', '&', '\'', + '*', '+', '-', '.', + '^', '_', '`', + '|', '~', +].concat(exports.ALPHANUM); +exports.TOKEN = exports.STRICT_TOKEN.concat([' ']); +/* + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + */ +exports.HEADER_CHARS = ['\t']; +for (let i = 32; i <= 255; i++) { + if (i !== 127) { + exports.HEADER_CHARS.push(i); + } +} +// ',' = \x44 +exports.CONNECTION_TOKEN_CHARS = exports.HEADER_CHARS.filter((c) => c !== 44); +exports.MAJOR = exports.NUM_MAP; +exports.MINOR = exports.MAJOR; +var HEADER_STATE; +(function (HEADER_STATE) { + HEADER_STATE[HEADER_STATE["GENERAL"] = 0] = "GENERAL"; + HEADER_STATE[HEADER_STATE["CONNECTION"] = 1] = "CONNECTION"; + HEADER_STATE[HEADER_STATE["CONTENT_LENGTH"] = 2] = "CONTENT_LENGTH"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING"] = 3] = "TRANSFER_ENCODING"; + HEADER_STATE[HEADER_STATE["UPGRADE"] = 4] = "UPGRADE"; + HEADER_STATE[HEADER_STATE["CONNECTION_KEEP_ALIVE"] = 5] = "CONNECTION_KEEP_ALIVE"; + HEADER_STATE[HEADER_STATE["CONNECTION_CLOSE"] = 6] = "CONNECTION_CLOSE"; + HEADER_STATE[HEADER_STATE["CONNECTION_UPGRADE"] = 7] = "CONNECTION_UPGRADE"; + HEADER_STATE[HEADER_STATE["TRANSFER_ENCODING_CHUNKED"] = 8] = "TRANSFER_ENCODING_CHUNKED"; +})(HEADER_STATE = exports.HEADER_STATE || (exports.HEADER_STATE = {})); +exports.SPECIAL_HEADERS = { + 'connection': HEADER_STATE.CONNECTION, + 'content-length': HEADER_STATE.CONTENT_LENGTH, + 'proxy-connection': HEADER_STATE.CONNECTION, + 'transfer-encoding': HEADER_STATE.TRANSFER_ENCODING, + 'upgrade': HEADER_STATE.UPGRADE, +}; +//# sourceMappingURL=constants.js.map + +/***/ }), + +/***/ 63870: +/***/ ((module) => { + +module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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ADcDACAAQShqQgA3AwAgAEEgakIANwMAIABBEGpCADcDACAAQQhqQgA3AwAgAEHdATYCHEEAC3sBAX8CQCAAKAIMIgMNAAJAIAAoAgRFDQAgACABNgIECwJAIAAgASACEMSAgIAAIgMNACAAKAIMDwsgACADNgIcQQAhAyAAKAIEIgFFDQAgACABIAIgACgCCBGBgICAAAAiAUUNACAAIAI2AhQgACABNgIMIAEhAwsgAwvk8wEDDn8DfgR/I4CAgIAAQRBrIgMkgICAgAAgASEEIAEhBSABIQYgASEHIAEhCCABIQkgASEKIAEhCyABIQwgASENIAEhDiABIQ8CQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAgACgCHCIQQX9qDt0B2gEB2QECAwQFBgcICQoLDA0O2AEPENcBERLWARMUFRYXGBkaG+AB3wEcHR7VAR8gISIjJCXUASYnKCkqKyzTAdIBLS7RAdABLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVG2wFHSElKzwHOAUvNAUzMAU1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4ABgQGCAYMBhAGFAYYBhwGIAYkB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkAC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FCAAIBA2AgxBACEQDLIBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxNCyAAQdMANgIcIAAgATYCFCAAIBA2AgxBACEQDLEBCyAAKAIEIRAgAEEANgIEAkAgACAQIAEQp4CAgAAiEA0AIAEhAQxRCyAAQeUANgIcIAAgATYCFCAAIBA2AgxBACEQDLABCyAAQQA2AhwgACABNgIUIABBxoqAgAA2AhAgAEEHNgIMQQAhEAyvAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHSADYCHCAAIAE2AhQgACAQNgIMQQAhEAyuAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMSQsgAEHTADYCHCAAIAE2AhQgACAQNgIMQQAhEAytAQsgACgCBCEQIABBADYCBAJAIAAgECABEKeAgIAAIhANACABIQEMTQsgAEHlADYCHCAAIAE2AhQgACAQNgIMQQAhEAysAQsgAEEANgIcIAAgATYCFCAAQdyIgIAANgIQIABBBzYCDEEAIRAMqwELIBBBP0cNASABQQFqIQELQQUhEAyQAQtBACEQIABBADYCHCAAIAE2AhQgAEH9koCAADYCECAAQQc2AgwMqAELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0gA2AhwgACABNgIUIAAgEDYCDEEAIRAMpwELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEILIABB0wA2AhwgACABNgIUIAAgEDYCDEEAIRAMpgELIAAoAgQhECAAQQA2AgQCQCAAIBAgARCngICAACIQDQAgASEBDEYLIABB5QA2AhwgACABNgIUIAAgEDYCDEEAIRAMpQELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0gA2AhwgACAUNgIUIAAgATYCDEEAIRAMpAELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDD8LIABB0wA2AhwgACAUNgIUIAAgATYCDEEAIRAMowELIAAoAgQhASAAQQA2AgQCQCAAIAEgFBCngICAACIBDQAgFCEBDEMLIABB5QA2AhwgACAU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YWdlX2JlZ2luYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlYCBjYWxsYmFjayBlcnJvcgBgb25fc3RhdHVzX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdmVyc2lvbl9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX3VybF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWVzc2FnZV9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX21ldGhvZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZWAgY2FsbGJhY2sgZXJyb3IAYG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lYCBjYWxsYmFjayBlcnJvcgBVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNlcnZlcgBJbnZhbGlkIGhlYWRlciB2YWx1ZSBjaGFyAEludmFsaWQgaGVhZGVyIGZpZWxkIGNoYXIAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl92ZXJzaW9uAEludmFsaWQgbWlub3IgdmVyc2lvbgBJbnZhbGlkIG1ham9yIHZlcnNpb24ARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgdmVyc2lvbgBFeHBlY3RlZCBDUkxGIGFmdGVyIHZlcnNpb24ASW52YWxpZCBIVFRQIHZlcnNpb24ASW52YWxpZCBoZWFkZXIgdG9rZW4AU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl91cmwASW52YWxpZCBjaGFyYWN0ZXJzIGluIHVybABVbmV4cGVjdGVkIHN0YXJ0IGNoYXIgaW4gdXJsAERvdWJsZSBAIGluIHVybABFbXB0eSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXJhY3RlciBpbiBDb250ZW50LUxlbmd0aABEdXBsaWNhdGUgQ29udGVudC1MZW5ndGgASW52YWxpZCBjaGFyIGluIHVybCBwYXRoAENvbnRlbnQtTGVuZ3RoIGNhbid0IGJlIHByZXNlbnQgd2l0aCBUcmFuc2Zlci1FbmNvZGluZwBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBzaXplAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX3ZhbHVlAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgdmFsdWUATWlzc2luZyBleHBlY3RlZCBMRiBhZnRlciBoZWFkZXIgdmFsdWUASW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIHF1b3RlIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGVkIHZhbHVlAFBhdXNlZCBieSBvbl9oZWFkZXJzX2NvbXBsZXRlAEludmFsaWQgRU9GIHN0YXRlAG9uX3Jlc2V0IHBhdXNlAG9uX2NodW5rX2hlYWRlciBwYXVzZQBvbl9tZXNzYWdlX2JlZ2luIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl92YWx1ZSBwYXVzZQBvbl9zdGF0dXNfY29tcGxldGUgcGF1c2UAb25fdmVyc2lvbl9jb21wbGV0ZSBwYXVzZQBvbl91cmxfY29tcGxldGUgcGF1c2UAb25fY2h1bmtfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX3ZhbHVlX2NvbXBsZXRlIHBhdXNlAG9uX21lc3NhZ2VfY29tcGxldGUgcGF1c2UAb25fbWV0aG9kX2NvbXBsZXRlIHBhdXNlAG9uX2hlYWRlcl9maWVsZF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19leHRlbnNpb25fbmFtZSBwYXVzZQBVbmV4cGVjdGVkIHNwYWNlIGFmdGVyIHN0YXJ0IGxpbmUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fbmFtZQBJbnZhbGlkIGNoYXJhY3RlciBpbiBjaHVuayBleHRlbnNpb25zIG5hbWUAUGF1c2Ugb24gQ09OTkVDVC9VcGdyYWRlAFBhdXNlIG9uIFBSSS9VcGdyYWRlAEV4cGVjdGVkIEhUVFAvMiBDb25uZWN0aW9uIFByZWZhY2UAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9tZXRob2QARXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgbWV0aG9kAFNwYW4gY2FsbGJhY2sgZXJyb3IgaW4gb25faGVhZGVyX2ZpZWxkAFBhdXNlZABJbnZhbGlkIHdvcmQgZW5jb3VudGVyZWQASW52YWxpZCBtZXRob2QgZW5jb3VudGVyZWQAVW5leHBlY3RlZCBjaGFyIGluIHVybCBzY2hlbWEAUmVxdWVzdCBoYXMgaW52YWxpZCBgVHJhbnNmZXItRW5jb2RpbmdgAFNXSVRDSF9QUk9YWQBVU0VfUFJPWFkATUtBQ1RJVklUWQBVTlBST0NFU1NBQkxFX0VOVElUWQBDT1BZAE1PVkVEX1BFUk1BTkVOVExZAFRPT19FQVJMWQBOT1RJRlkARkFJTEVEX0RFUEVOREVOQ1kAQkFEX0dBVEVXQVkAUExBWQBQVVQAQ0hFQ0tPVVQAR0FURVdBWV9USU1FT1VUAFJFUVVFU1RfVElNRU9VVABORVRXT1JLX0NPTk5FQ1RfVElNRU9VVABDT05ORUNUSU9OX1RJTUVPVVQATE9HSU5fVElNRU9VVABORVRXT1JLX1JFQURfVElNRU9VVABQT1NUAE1JU0RJUkVDVEVEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9SRVFVRVNUAENMSUVOVF9DTE9TRURfTE9BRF9CQUxBTkNFRF9SRVFVRVNUAEJBRF9SRVFVRVNUAEhUVFBfUkVRVUVTVF9TRU5UX1RPX0hUVFBTX1BPUlQAUkVQT1JUAElNX0FfVEVBUE9UAFJFU0VUX0NPTlRFTlQATk9fQ09OVEVOVABQQVJUSUFMX0NPTlRFTlQASFBFX0lOVkFMSURfQ09OU1RBTlQASFBFX0NCX1JFU0VUAEdFVABIUEVfU1RSSUNUAENPTkZMSUNUAFRFTVBPUkFSWV9SRURJUkVDVABQRVJNQU5FTlRfUkVESVJFQ1QAQ09OTkVDVABNVUxUSV9TVEFUVVMASFBFX0lOVkFMSURfU1RBVFVTAFRPT19NQU5ZX1JFUVVFU1RTAEVBUkxZX0hJTlRTAFVOQVZBSUxBQkxFX0ZPUl9MRUdBTF9SRUFTT05TAE9QVElPTlMAU1dJVENISU5HX1BST1RPQ09MUwBWQVJJQU5UX0FMU09fTkVHT1RJQVRFUwBNVUxUSVBMRV9DSE9JQ0VTAElOVEVSTkFMX1NFUlZFUl9FUlJPUgBXRUJfU0VSVkVSX1VOS05PV05fRVJST1IAUkFJTEdVTl9FUlJPUgBJREVOVElUWV9QUk9WSURFUl9BVVRIRU5USUNBVElPTl9FUlJPUgBTU0xfQ0VSVElGSUNBVEVfRVJST1IASU5WQUxJRF9YX0ZPUldBUkRFRF9GT1IAU0VUX1BBUkFNRVRFUgBHRVRfUEFSQU1FVEVSAEhQRV9VU0VSAFNFRV9PVEhFUgBIUEVfQ0JfQ0hVTktfSEVBREVSAE1LQ0FMRU5EQVIAU0VUVVAAV0VCX1NFUlZFUl9JU19ET1dOAFRFQVJET1dOAEhQRV9DTE9TRURfQ09OTkVDVElPTgBIRVVSSVNUSUNfRVhQSVJBVElPTgBESVNDT05ORUNURURfT1BFUkFUSU9OAE5PTl9BVVRIT1JJVEFUSVZFX0lORk9STUFUSU9OAEhQRV9JTlZBTElEX1ZFUlNJT04ASFBFX0NCX01FU1NBR0VfQkVHSU4AU0lURV9JU19GUk9aRU4ASFBFX0lOVkFMSURfSEVBREVSX1RPS0VOAElOVkFMSURfVE9LRU4ARk9SQklEREVOAEVOSEFOQ0VfWU9VUl9DQUxNAEhQRV9JTlZBTElEX1VSTABCTE9DS0VEX0JZX1BBUkVOVEFMX0NPTlRST0wATUtDT0wAQUNMAEhQRV9JTlRFUk5BTABSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFX1VOT0ZGSUNJQUwASFBFX09LAFVOTElOSwBVTkxPQ0sAUFJJAFJFVFJZX1dJVEgASFBFX0lOVkFMSURfQ09OVEVOVF9MRU5HVEgASFBFX1VORVhQRUNURURfQ09OVEVOVF9MRU5HVEgARkxVU0gAUFJPUFBBVENIAE0tU0VBUkNIAFVSSV9UT09fTE9ORwBQUk9DRVNTSU5HAE1JU0NFTExBTkVPVVNfUEVSU0lTVEVOVF9XQVJOSU5HAE1JU0NFTExBTkVPVVNfV0FSTklORwBIUEVfSU5WQUxJRF9UUkFOU0ZFUl9FTkNPRElORwBFeHBlY3RlZCBDUkxGAEhQRV9JTlZBTElEX0NIVU5LX1NJWkUATU9WRQBDT05USU5VRQBIUEVfQ0JfU1RBVFVTX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJTX0NPTVBMRVRFAEhQRV9DQl9WRVJTSU9OX0NPTVBMRVRFAEhQRV9DQl9VUkxfQ09NUExFVEUASFBFX0NCX0NIVU5LX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfVkFMVUVfQ09NUExFVEUASFBFX0NCX0NIVU5LX0VYVEVOU0lPTl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX05BTUVfQ09NUExFVEUASFBFX0NCX01FU1NBR0VfQ09NUExFVEUASFBFX0NCX01FVEhPRF9DT01QTEVURQBIUEVfQ0JfSEVBREVSX0ZJRUxEX0NPTVBMRVRFAERFTEVURQBIUEVfSU5WQUxJRF9FT0ZfU1RBVEUASU5WQUxJRF9TU0xfQ0VSVElGSUNBVEUAUEFVU0UATk9fUkVTUE9OU0UAVU5TVVBQT1JURURfTUVESUFfVFlQRQBHT05FAE5PVF9BQ0NFUFRBQkxFAFNFUlZJQ0VfVU5BVkFJTEFCTEUAUkFOR0VfTk9UX1NBVElTRklBQkxFAE9SSUdJTl9JU19VTlJFQUNIQUJMRQBSRVNQT05TRV9JU19TVEFMRQBQVVJHRQBNRVJHRQBSRVFVRVNUX0hFQURFUl9GSUVMRFNfVE9PX0xBUkdFAFJFUVVFU1RfSEVBREVSX1RPT19MQVJHRQBQQVlMT0FEX1RPT19MQVJHRQBJTlNVRkZJQ0lFTlRfU1RPUkFHRQBIUEVfUEFVU0VEX1VQR1JBREUASFBFX1BBVVNFRF9IMl9VUEdSQURFAFNPVVJDRQBBTk5PVU5DRQBUUkFDRQBIUEVfVU5FWFBFQ1RFRF9TUEFDRQBERVNDUklCRQBVTlNVQlNDUklCRQBSRUNPUkQASFBFX0lOVkFMSURfTUVUSE9EAE5PVF9GT1VORABQUk9QRklORABVTkJJTkQAUkVCSU5EAFVOQVVUSE9SSVpFRABNRVRIT0RfTk9UX0FMTE9XRUQASFRUUF9WRVJTSU9OX05PVF9TVVBQT1JURUQAQUxSRUFEWV9SRVBPUlRFRABBQ0NFUFRFRABOT1RfSU1QTEVNRU5URUQATE9PUF9ERVRFQ1RFRABIUEVfQ1JfRVhQRUNURUQASFBFX0xGX0VYUEVDVEVEAENSRUFURUQASU1fVVNFRABIUEVfUEFVU0VEAFRJTUVPVVRfT0NDVVJFRABQQVlNRU5UX1JFUVVJUkVEAFBSRUNPTkRJVElPTl9SRVFVSVJFRABQUk9YWV9BVVRIRU5USUNBVElPTl9SRVFVSVJFRABORVRXT1JLX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAExFTkdUSF9SRVFVSVJFRABTU0xfQ0VSVElGSUNBVEVfUkVRVUlSRUQAVVBHUkFERV9SRVFVSVJFRABQQUdFX0VYUElSRUQAUFJFQ09ORElUSU9OX0ZBSUxFRABFWFBFQ1RBVElPTl9GQUlMRUQAUkVWQUxJREFUSU9OX0ZBSUxFRABTU0xfSEFORFNIQUtFX0ZBSUxFRABMT0NLRUQAVFJBTlNGT1JNQVRJT05fQVBQTElFRABOT1RfTU9ESUZJRUQATk9UX0VYVEVOREVEAEJBTkRXSURUSF9MSU1JVF9FWENFRURFRABTSVRFX0lTX09WRVJMT0FERUQASEVBRABFeHBlY3RlZCBIVFRQLwAAXhMAACYTAAAwEAAA8BcAAJ0TAAAVEgAAORcAAPASAAAKEAAAdRIAAK0SAACCEwAATxQAAH8QAACgFQAAIxQAAIkSAACLFAAATRUAANQRAADPFAAAEBgAAMkWAADcFgAAwREAAOAXAAC7FAAAdBQAAHwVAADlFAAACBcAAB8QAABlFQAAoxQAACgVAAACFQAAmRUAACwQAACLGQAATw8AANQOAABqEAAAzhAAAAIXAACJDgAAbhMAABwTAABmFAAAVhcAAMETAADNEwAAbBMAAGgXAABmFwAAXxcAACITAADODwAAaQ4AANgOAABjFgAAyxMAAKoOAAAoFwAAJhcAAMUTAABdFgAA6BEAAGcTAABlEwAA8hYAAHMTAAAdFwAA+RYAAPMRAADPDgAAzhUAAAwSAACzEQAApREAAGEQAAAyFwAAuxMAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIDAgICAgIAAAICAAICAAICAgICAgICAgIABAAAAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAICAgICAAACAgACAgACAgICAgICAgICAAMABAAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbG9zZWVlcC1hbGl2ZQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBY2h1bmtlZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEAAAEBAAEBAAEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlY3Rpb25lbnQtbGVuZ3Rob25yb3h5LWNvbm5lY3Rpb24AAAAAAAAAAAAAAAAAAAByYW5zZmVyLWVuY29kaW5ncGdyYWRlDQoNCg0KU00NCg0KVFRQL0NFL1RTUC8AAAAAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQIAAQMAAAAAAAAAAAAAAAAAAAAAAAAEAQEFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAAAAAAAAMEAAAEBAQEBAQEBAQEBAUEBAQEBAQEBAQEBAQABAAGBwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAIAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOT1VOQ0VFQ0tPVVRORUNURVRFQ1JJQkVMVVNIRVRFQURTRUFSQ0hSR0VDVElWSVRZTEVOREFSVkVPVElGWVBUSU9OU0NIU0VBWVNUQVRDSEdFT1JESVJFQ1RPUlRSQ0hQQVJBTUVURVJVUkNFQlNDUklCRUFSRE9XTkFDRUlORE5LQ0tVQlNDUklCRUhUVFAvQURUUC8=' + + +/***/ }), + +/***/ 53434: +/***/ ((module) => { + +module.exports = 'AGFzbQEAAAABMAhgAX8Bf2ADf39/AX9gBH9/f38Bf2AAAGADf39/AGABfwBgAn9/AGAGf39/f39/AALLAQgDZW52GHdhc21fb25faGVhZGVyc19jb21wbGV0ZQACA2VudhV3YXNtX29uX21lc3NhZ2VfYmVnaW4AAANlbnYLd2FzbV9vbl91cmwAAQNlbnYOd2FzbV9vbl9zdGF0dXMAAQNlbnYUd2FzbV9vbl9oZWFkZXJfZmllbGQAAQNlbnYUd2FzbV9vbl9oZWFkZXJfdmFsdWUAAQNlbnYMd2FzbV9vbl9ib2R5AAEDZW52GHdhc21fb25fbWVzc2FnZV9jb21wbGV0ZQAAA0ZFAwMEAAAFAAAAAAAABQEFAAUFBQAABgAAAAAGBgYGAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAAABAQcAAAUFAwABBAUBcAESEgUDAQACBggBfwFBgNQECwfRBSIGbWVtb3J5AgALX2luaXRpYWxpemUACRlfX2luZGlyZWN0X2Z1bmN0aW9uX3RhYmxlAQALbGxodHRwX2luaXQAChhsbGh0dHBfc2hvdWxkX2tlZXBfYWxpdmUAQQxsbGh0dHBfYWxsb2MADAZtYWxsb2MARgtsbGh0dHBfZnJlZQANBGZyZWUASA9sbGh0dHBfZ2V0X3R5cGUADhVsbGh0dHBfZ2V0X2h0dHBfbWFqb3IADxVsbGh0dHBfZ2V0X2h0dHBfbWlub3IAEBFsbGh0dHBfZ2V0X21ldGhvZAARFmxsaHR0cF9nZXRfc3RhdHVzX2NvZGUAEhJsbGh0dHBfZ2V0X3VwZ3JhZGUAEwxsbGh0dHBfcmVzZXQAFA5sbGh0dHBfZXhlY3V0ZQAVFGxsaHR0cF9zZXR0aW5nc19pbml0ABYNbGxodHRwX2ZpbmlzaAAXDGxsaHR0cF9wYXVzZQAYDWxsaHR0cF9yZXN1bWUAGRtsbGh0dHBfcmVzdW1lX2FmdGVyX3VwZ3JhZGUAGhBsbGh0dHBfZ2V0X2Vycm5vABsXbGxodHRwX2dldF9lcnJvcl9yZWFzb24AHBdsbGh0dHBfc2V0X2Vycm9yX3JlYXNvbgAdFGxsaHR0cF9nZXRfZXJyb3JfcG9zAB4RbGxodHRwX2Vycm5vX25hbWUAHxJsbGh0dHBfbWV0aG9kX25hbWUAIBJs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IAH9CwMAIABBMGogAf0LAwAgAEEgaiAB/QsDACAAQd0BNgIcQQALewEBfwJAIAAoAgwiAw0AAkAgACgCBEUNACAAIAE2AgQLAkAgACABIAIQxICAgAAiAw0AIAAoAgwPCyAAIAM2AhxBACEDIAAoAgQiAUUNACAAIAEgAiAAKAIIEYGAgIAAACIBRQ0AIAAgAjYCFCAAIAE2AgwgASEDCyADC+TzAQMOfwN+BH8jgICAgABBEGsiAySAgICAACABIQQgASEFIAEhBiABIQcgASEIIAEhCSABIQogASELIAEhDCABIQ0gASEOIAEhDwJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQCAAKAIcIhBBf2oO3QHaAQHZAQIDBAUGBwgJCgsMDQ7YAQ8Q1wEREtYBExQVFhcYGRob4AHfARwdHtUBHyAhIiMkJdQBJicoKSorLNMB0gEtLtEB0AEvMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUbbAUdISUrPAc4BS80BTMwBTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ent8fX5/gAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEB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QAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIBAOxwEAAQID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YWNrIGVycm9yAGBvbl9jaHVua19leHRlbnNpb25fdmFsdWVgIGNhbGxiYWNrIGVycm9yAGBvbl9zdGF0dXNfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl92ZXJzaW9uX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fdXJsX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGVgIGNhbGxiYWNrIGVycm9yAGBvbl9tZXNzYWdlX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fbWV0aG9kX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlYCBjYWxsYmFjayBlcnJvcgBgb25fY2h1bmtfZXh0ZW5zaW9uX25hbWVgIGNhbGxiYWNrIGVycm9yAFVuZXhwZWN0ZWQgY2hhciBpbiB1cmwgc2VydmVyAEludmFsaWQgaGVhZGVyIHZhbHVlIGNoYXIASW52YWxpZCBoZWFkZXIgZmllbGQgY2hhcgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3ZlcnNpb24ASW52YWxpZCBtaW5vciB2ZXJzaW9uAEludmFsaWQgbWFqb3IgdmVyc2lvbgBFeHBlY3RlZCBzcGFjZSBhZnRlciB2ZXJzaW9uAEV4cGVjdGVkIENSTEYgYWZ0ZXIgdmVyc2lvbgBJbnZhbGlkIEhUVFAgdmVyc2lvbgBJbnZhbGlkIGhlYWRlciB0b2tlbgBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX3VybABJbnZhbGlkIGNoYXJhY3RlcnMgaW4gdXJsAFVuZXhwZWN0ZWQgc3RhcnQgY2hhciBpbiB1cmwARG91YmxlIEAgaW4gdXJsAEVtcHR5IENvbnRlbnQtTGVuZ3RoAEludmFsaWQgY2hhcmFjdGVyIGluIENvbnRlbnQtTGVuZ3RoAER1cGxpY2F0ZSBDb250ZW50LUxlbmd0aABJbnZhbGlkIGNoYXIgaW4gdXJsIHBhdGgAQ29udGVudC1MZW5ndGggY2FuJ3QgYmUgcHJlc2VudCB3aXRoIFRyYW5zZmVyLUVuY29kaW5nAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIHNpemUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfdmFsdWUAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9jaHVua19leHRlbnNpb25fdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyB2YWx1ZQBNaXNzaW5nIGV4cGVjdGVkIExGIGFmdGVyIGhlYWRlciB2YWx1ZQBJbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AgaGVhZGVyIHZhbHVlAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgcXVvdGUgdmFsdWUASW52YWxpZCBjaGFyYWN0ZXIgaW4gY2h1bmsgZXh0ZW5zaW9ucyBxdW90ZWQgdmFsdWUAUGF1c2VkIGJ5IG9uX2hlYWRlcnNfY29tcGxldGUASW52YWxpZCBFT0Ygc3RhdGUAb25fcmVzZXQgcGF1c2UAb25fY2h1bmtfaGVhZGVyIHBhdXNlAG9uX21lc3NhZ2VfYmVnaW4gcGF1c2UAb25fY2h1bmtfZXh0ZW5zaW9uX3ZhbHVlIHBhdXNlAG9uX3N0YXR1c19jb21wbGV0ZSBwYXVzZQBvbl92ZXJzaW9uX2NvbXBsZXRlIHBhdXNlAG9uX3VybF9jb21wbGV0ZSBwYXVzZQBvbl9jaHVua19jb21wbGV0ZSBwYXVzZQBvbl9oZWFkZXJfdmFsdWVfY29tcGxldGUgcGF1c2UAb25fbWVzc2FnZV9jb21wbGV0ZSBwYXVzZQBvbl9tZXRob2RfY29tcGxldGUgcGF1c2UAb25faGVhZGVyX2ZpZWxkX2NvbXBsZXRlIHBhdXNlAG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lIHBhdXNlAFVuZXhwZWN0ZWQgc3BhY2UgYWZ0ZXIgc3RhcnQgbGluZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX2NodW5rX2V4dGVuc2lvbl9uYW1lAEludmFsaWQgY2hhcmFjdGVyIGluIGNodW5rIGV4dGVuc2lvbnMgbmFtZQBQYXVzZSBvbiBDT05ORUNUL1VwZ3JhZGUAUGF1c2Ugb24gUFJJL1VwZ3JhZGUARXhwZWN0ZWQgSFRUUC8yIENvbm5lY3Rpb24gUHJlZmFjZQBTcGFuIGNhbGxiYWNrIGVycm9yIGluIG9uX21ldGhvZABFeHBlY3RlZCBzcGFjZSBhZnRlciBtZXRob2QAU3BhbiBjYWxsYmFjayBlcnJvciBpbiBvbl9oZWFkZXJfZmllbGQAUGF1c2VkAEludmFsaWQgd29yZCBlbmNvdW50ZXJlZABJbnZhbGlkIG1ldGhvZCBlbmNvdW50ZXJlZABVbmV4cGVjdGVkIGNoYXIgaW4gdXJsIHNjaGVtYQBSZXF1ZXN0IGhhcyBpbnZhbGlkIGBUcmFuc2Zlci1FbmNvZGluZ2AAU1dJVENIX1BST1hZAFVTRV9QUk9YWQBNS0FDVElWSVRZAFVOUFJPQ0VTU0FCTEVfRU5USVRZAENPUFkATU9WRURfUEVSTUFORU5UTFkAVE9PX0VBUkxZAE5PVElGWQBGQUlMRURfREVQRU5ERU5DWQBCQURfR0FURVdBWQBQTEFZAFBVVABDSEVDS09VVABHQVRFV0FZX1RJTUVPVVQAUkVRVUVTVF9USU1FT1VUAE5FVFdPUktfQ09OTkVDVF9USU1FT1VUAENPTk5FQ1RJT05fVElNRU9VVABMT0dJTl9USU1FT1VUAE5FVFdPUktfUkVBRF9USU1FT1VUAFBPU1QATUlTRElSRUNURURfUkVRVUVTVABDTElFTlRfQ0xPU0VEX1JFUVVFU1QAQ0xJRU5UX0NMT1NFRF9MT0FEX0JBTEFOQ0VEX1JFUVVFU1QAQkFEX1JFUVVFU1QASFRUUF9SRVFVRVNUX1NFTlRfVE9fSFRUUFNfUE9SVABSRVBPUlQASU1fQV9URUFQT1QAUkVTRVRfQ09OVEVOVABOT19DT05URU5UAFBBUlRJQUxfQ09OVEVOVABIUEVfSU5WQUxJRF9DT05TVEFOVABIUEVfQ0JfUkVTRVQAR0VUAEhQRV9TVFJJQ1QAQ09ORkxJQ1QAVEVNUE9SQVJZX1JFRElSRUNUAFBFUk1BTkVOVF9SRURJUkVDVABDT05ORUNUAE1VTFRJX1NUQVRVUwBIUEVfSU5WQUxJRF9TVEFUVVMAVE9PX01BTllfUkVRVUVTVFMARUFSTFlfSElOVFMAVU5BVkFJTEFCTEVfRk9SX0xFR0FMX1JFQVNPTlMAT1BUSU9OUwBTV0lUQ0hJTkdfUFJPVE9DT0xTAFZBUklBTlRfQUxTT19ORUdPVElBVEVTAE1VTFRJUExFX0NIT0lDRVMASU5URVJOQUxfU0VSVkVSX0VSUk9SAFdFQl9TRVJWRVJfVU5LTk9XTl9FUlJPUgBSQUlMR1VOX0VSUk9SAElERU5USVRZX1BST1ZJREVSX0FVVEhFTlRJQ0FUSU9OX0VSUk9SAFNTTF9DRVJUSUZJQ0FURV9FUlJPUgBJTlZBTElEX1hfRk9SV0FSREVEX0ZPUgBTRVRfUEFSQU1FVEVSAEdFVF9QQVJBTUVURVIASFBFX1VTRVIAU0VFX09USEVSAEhQRV9DQl9DSFVOS19IRUFERVIATUtDQUxFTkRBUgBTRVRVUABXRUJfU0VSVkVSX0lTX0RPV04AVEVBUkRPV04ASFBFX0NMT1NFRF9DT05ORUNUSU9OAEhFVVJJU1RJQ19FWFBJUkFUSU9OAERJU0NPTk5FQ1RFRF9PUEVSQVRJT04ATk9OX0FVVEhPUklUQVRJVkVfSU5GT1JNQVRJT04ASFBFX0lOVkFMSURfVkVSU0lPTgBIUEVfQ0JfTUVTU0FHRV9CRUdJTgBTSVRFX0lTX0ZST1pFTgBIUEVfSU5WQUxJRF9IRUFERVJfVE9LRU4ASU5WQUxJRF9UT0tFTgBGT1JCSURERU4ARU5IQU5DRV9ZT1VSX0NBTE0ASFBFX0lOVkFMSURfVVJMAEJMT0NLRURfQllfUEFSRU5UQUxfQ09OVFJPTABNS0NPTABBQ0wASFBFX0lOVEVSTkFMAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0VfVU5PRkZJQ0lBTABIUEVfT0sAVU5MSU5LAFVOTE9DSwBQUkkAUkVUUllfV0lUSABIUEVfSU5WQUxJRF9DT05URU5UX0xFTkdUSABIUEVfVU5FWFBFQ1RFRF9DT05URU5UX0xFTkdUSABGTFVTSABQUk9QUEFUQ0gATS1TRUFSQ0gAVVJJX1RPT19MT05HAFBST0NFU1NJTkcATUlTQ0VMTEFORU9VU19QRVJTSVNURU5UX1dBUk5JTkcATUlTQ0VMTEFORU9VU19XQVJOSU5HAEhQRV9JTlZBTElEX1RSQU5TRkVSX0VOQ09ESU5HAEV4cGVjdGVkIENSTEYASFBFX0lOVkFMSURfQ0hVTktfU0laRQBNT1ZFAENPTlRJTlVFAEhQRV9DQl9TVEFUVVNfQ09NUExFVEUASFBFX0NCX0hFQURFUlNfQ09NUExFVEUASFBFX0NCX1ZFUlNJT05fQ09NUExFVEUASFBFX0NCX1VSTF9DT01QTEVURQBIUEVfQ0JfQ0hVTktfQ09NUExFVEUASFBFX0NCX0hFQURFUl9WQUxVRV9DT01QTEVURQBIUEVfQ0JfQ0hVTktfRVhURU5TSU9OX1ZBTFVFX0NPTVBMRVRFAEhQRV9DQl9DSFVOS19FWFRFTlNJT05fTkFNRV9DT01QTEVURQBIUEVfQ0JfTUVTU0FHRV9DT01QTEVURQBIUEVfQ0JfTUVUSE9EX0NPTVBMRVRFAEhQRV9DQl9IRUFERVJfRklFTERfQ09NUExFVEUAREVMRVRFAEhQRV9JTlZBTElEX0VPRl9TVEFURQBJTlZBTElEX1NTTF9DRVJUSUZJQ0FURQBQQVVTRQBOT19SRVNQT05TRQBVTlNVUFBPUlRFRF9NRURJQV9UWVBFAEdPTkUATk9UX0FDQ0VQVEFCTEUAU0VSVklDRV9VTkFWQUlMQUJMRQBSQU5HRV9OT1RfU0FUSVNGSUFCTEUAT1JJR0lOX0lTX1VOUkVBQ0hBQkxFAFJFU1BPTlNFX0lTX1NUQUxFAFBVUkdFAE1FUkdFAFJFUVVFU1RfSEVBREVSX0ZJRUxEU19UT09fTEFSR0UAUkVRVUVTVF9IRUFERVJfVE9PX0xBUkdFAFBBWUxPQURfVE9PX0xBUkdFAElOU1VGRklDSUVOVF9TVE9SQUdFAEhQRV9QQVVTRURfVVBHUkFERQBIUEVfUEFVU0VEX0gyX1VQR1JBREUAU09VUkNFAEFOTk9VTkNFAFRSQUNFAEhQRV9VTkVYUEVDVEVEX1NQQUNFAERFU0NSSUJFAFVOU1VCU0NSSUJFAFJFQ09SRABIUEVfSU5WQUxJRF9NRVRIT0QATk9UX0ZPVU5EAFBST1BGSU5EAFVOQklORABSRUJJTkQAVU5BVVRIT1JJWkVEAE1FVEhPRF9OT1RfQUxMT1dFRABIVFRQX1ZFUlNJT05fTk9UX1NVUFBPUlRFRABBTFJFQURZX1JFUE9SVEVEAEFDQ0VQVEVEAE5PVF9JTVBMRU1FTlRFRABMT09QX0RFVEVDVEVEAEhQRV9DUl9FWFBFQ1RFRABIUEVfTEZfRVhQRUNURUQAQ1JFQVRFRABJTV9VU0VEAEhQRV9QQVVTRUQAVElNRU9VVF9PQ0NVUkVEAFBBWU1FTlRfUkVRVUlSRUQAUFJFQ09ORElUSU9OX1JFUVVJUkVEAFBST1hZX0FVVEhFTlRJQ0FUSU9OX1JFUVVJUkVEAE5FVFdPUktfQVVUSEVOVElDQVRJT05fUkVRVUlSRUQATEVOR1RIX1JFUVVJUkVEAFNTTF9DRVJUSUZJQ0FURV9SRVFVSVJFRABVUEdSQURFX1JFUVVJUkVEAFBBR0VfRVhQSVJFRABQUkVDT05ESVRJT05fRkFJTEVEAEVYUEVDVEFUSU9OX0ZBSUxFRABSRVZBTElEQVRJT05fRkFJTEVEAFNTTF9IQU5EU0hBS0VfRkFJTEVEAExPQ0tFRABUUkFOU0ZPUk1BVElPTl9BUFBMSUVEAE5PVF9NT0RJRklFRABOT1RfRVhURU5ERUQAQkFORFdJRFRIX0xJTUlUX0VYQ0VFREVEAFNJVEVfSVNfT1ZFUkxPQURFRABIRUFEAEV4cGVjdGVkIEhUVFAvAABeEwAAJhMAADAQAADwFwAAnRMAABUSAAA5FwAA8BIAAAoQAAB1EgAArRIAAIITAABPFAAAfxAAAKAVAAAjFAAAiRIAAIsUAABNFQAA1BEAAM8UAAAQGAAAyRYAANwWAADBEQAA4BcAALsUAAB0FAAAfBUAAOUUAAAIFwAAHxAAAGUVAACjFAAAKBUAAAIVAACZFQAALBAAAIsZAABPDwAA1A4AAGoQAADOEAAAAhcAAIkOAABuEwAAHBMAAGYUAABWFwAAwRMAAM0TAABsEwAAaBcAAGYXAABfFwAAIhMAAM4PAABpDgAA2A4AAGMWAADLEwAAqg4AACgXAAAmFwAAxRMAAF0WAADoEQAAZxMAAGUTAADyFgAAcxMAAB0XAAD5FgAA8xEAAM8OAADOFQAADBIAALMRAAClEQAAYRAAADIXAAC7EwAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgMCAgICAgAAAgIAAgIAAgICAgICAgICAgAEAAAAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgICAgIAAAICAAICAAICAgICAgICAgIAAwAEAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgIAAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsb3NlZWVwLWFsaXZlAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFjaHVua2VkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQABAQEBAQAAAQEAAQEAAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGVjdGlvbmVudC1sZW5ndGhvbnJveHktY29ubmVjdGlvbgAAAAAAAAAAAAAAAAAAAHJhbnNmZXItZW5jb2RpbmdwZ3JhZGUNCg0KDQpTTQ0KDQpUVFAvQ0UvVFNQLwAAAAAAAAAAAAAAAAECAAEDAAAAAAAAAAAAAAAAAAAAAAAABAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAABAgABAwAAAAAAAAAAAAAAAAAAAAAAAAQBAQUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAAAAAABAAACAAAAAAAAAAAAAAAAAAAAAAAAAwQAAAQEBAQEBAQEBAQEBQQEBAQEBAQEBAQEBAAEAAYHBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQABAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAgAAAAACAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE5PVU5DRUVDS09VVE5FQ1RFVEVDUklCRUxVU0hFVEVBRFNFQVJDSFJHRUNUSVZJVFlMRU5EQVJWRU9USUZZUFRJT05TQ0hTRUFZU1RBVENIR0VPUkRJUkVDVE9SVFJDSFBBUkFNRVRFUlVSQ0VCU0NSSUJFQVJET1dOQUNFSU5ETktDS1VCU0NSSUJFSFRUUC9BRFRQLw==' + + +/***/ }), + +/***/ 50172: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.enumToMap = void 0; +function enumToMap(obj) { + const res = {}; + Object.keys(obj).forEach((key) => { + const value = obj[key]; + if (typeof value === 'number') { + res[key] = value; + } + }); + return res; +} +exports.enumToMap = enumToMap; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 47501: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kClients } = __nccwpck_require__(36443) +const Agent = __nccwpck_require__(59965) +const { + kAgent, + kMockAgentSet, + kMockAgentGet, + kDispatches, + kIsMockActive, + kNetConnect, + kGetNetConnect, + kOptions, + kFactory +} = __nccwpck_require__(91117) +const MockClient = __nccwpck_require__(47365) +const MockPool = __nccwpck_require__(94004) +const { matchValue, buildMockOptions } = __nccwpck_require__(53397) +const { InvalidArgumentError, UndiciError } = __nccwpck_require__(68707) +const Dispatcher = __nccwpck_require__(28611) +const Pluralizer = __nccwpck_require__(91529) +const PendingInterceptorsFormatter = __nccwpck_require__(56142) + +class FakeWeakRef { + constructor (value) { + this.value = value + } + + deref () { + return this.value + } +} + +class MockAgent extends Dispatcher { + constructor (opts) { + super(opts) + + this[kNetConnect] = true + this[kIsMockActive] = true + + // Instantiate Agent and encapsulate + if ((opts && opts.agent && typeof opts.agent.dispatch !== 'function')) { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + const agent = opts && opts.agent ? opts.agent : new Agent(opts) + this[kAgent] = agent + + this[kClients] = agent[kClients] + this[kOptions] = buildMockOptions(opts) + } + + get (origin) { + let dispatcher = this[kMockAgentGet](origin) + + if (!dispatcher) { + dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + } + return dispatcher + } + + dispatch (opts, handler) { + // Call MockAgent.get to perform additional setup before dispatching as normal + this.get(opts.origin) + return this[kAgent].dispatch(opts, handler) + } + + async close () { + await this[kAgent].close() + this[kClients].clear() + } + + deactivate () { + this[kIsMockActive] = false + } + + activate () { + this[kIsMockActive] = true + } + + enableNetConnect (matcher) { + if (typeof matcher === 'string' || typeof matcher === 'function' || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher) + } else { + this[kNetConnect] = [matcher] + } + } else if (typeof matcher === 'undefined') { + this[kNetConnect] = true + } else { + throw new InvalidArgumentError('Unsupported matcher. Must be one of String|Function|RegExp.') + } + } + + disableNetConnect () { + this[kNetConnect] = false + } + + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive () { + return this[kIsMockActive] + } + + [kMockAgentSet] (origin, dispatcher) { + this[kClients].set(origin, new FakeWeakRef(dispatcher)) + } + + [kFactory] (origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]) + return this[kOptions] && this[kOptions].connections === 1 + ? new MockClient(origin, mockOptions) + : new MockPool(origin, mockOptions) + } + + [kMockAgentGet] (origin) { + // First check if we can immediately find it + const ref = this[kClients].get(origin) + if (ref) { + return ref.deref() + } + + // If the origin is not a string create a dummy parent pool and return to user + if (typeof origin !== 'string') { + const dispatcher = this[kFactory]('http://localhost:9999') + this[kMockAgentSet](origin, dispatcher) + return dispatcher + } + + // If we match, create a pool and assign the same dispatches + for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) { + const nonExplicitDispatcher = nonExplicitRef.deref() + if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) { + const dispatcher = this[kFactory](origin) + this[kMockAgentSet](origin, dispatcher) + dispatcher[kDispatches] = nonExplicitDispatcher[kDispatches] + return dispatcher + } + } + } + + [kGetNetConnect] () { + return this[kNetConnect] + } + + pendingInterceptors () { + const mockAgentClients = this[kClients] + + return Array.from(mockAgentClients.entries()) + .flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin }))) + .filter(({ pending }) => pending) + } + + assertNoPendingInterceptors ({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors() + + if (pending.length === 0) { + return + } + + const pluralizer = new Pluralizer('interceptor', 'interceptors').pluralize(pending.length) + + throw new UndiciError(` +${pluralizer.count} ${pluralizer.noun} ${pluralizer.is} pending: + +${pendingInterceptorsFormatter.format(pending)} +`.trim()) + } +} + +module.exports = MockAgent + + +/***/ }), + +/***/ 47365: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { promisify } = __nccwpck_require__(39023) +const Client = __nccwpck_require__(86197) +const { buildMockDispatch } = __nccwpck_require__(53397) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(91117) +const { MockInterceptor } = __nccwpck_require__(31511) +const Symbols = __nccwpck_require__(36443) +const { InvalidArgumentError } = __nccwpck_require__(68707) + +/** + * MockClient provides an API that extends the Client to influence the mockDispatches. + */ +class MockClient extends Client { + constructor (origin, opts) { + super(origin, opts) + + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } + + get [Symbols.kConnected] () { + return this[kConnected] + } + + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } + + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + } +} + +module.exports = MockClient + + +/***/ }), + +/***/ 52429: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { UndiciError } = __nccwpck_require__(68707) + +class MockNotMatchedError extends UndiciError { + constructor (message) { + super(message) + Error.captureStackTrace(this, MockNotMatchedError) + this.name = 'MockNotMatchedError' + this.message = message || 'The request does not match any registered mock dispatches' + this.code = 'UND_MOCK_ERR_MOCK_NOT_MATCHED' + } +} + +module.exports = { + MockNotMatchedError +} + + +/***/ }), + +/***/ 31511: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { getResponseData, buildKey, addMockDispatch } = __nccwpck_require__(53397) +const { + kDispatches, + kDispatchKey, + kDefaultHeaders, + kDefaultTrailers, + kContentLength, + kMockDispatch +} = __nccwpck_require__(91117) +const { InvalidArgumentError } = __nccwpck_require__(68707) +const { buildURL } = __nccwpck_require__(3440) + +/** + * Defines the scope API for an interceptor reply + */ +class MockScope { + constructor (mockDispatch) { + this[kMockDispatch] = mockDispatch + } + + /** + * Delay a reply by a set amount in ms. + */ + delay (waitInMs) { + if (typeof waitInMs !== 'number' || !Number.isInteger(waitInMs) || waitInMs <= 0) { + throw new InvalidArgumentError('waitInMs must be a valid integer > 0') + } + + this[kMockDispatch].delay = waitInMs + return this + } + + /** + * For a defined reply, never mark as consumed. + */ + persist () { + this[kMockDispatch].persist = true + return this + } + + /** + * Allow one to define a reply for a set amount of matching requests. + */ + times (repeatTimes) { + if (typeof repeatTimes !== 'number' || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { + throw new InvalidArgumentError('repeatTimes must be a valid integer > 0') + } + + this[kMockDispatch].times = repeatTimes + return this + } +} + +/** + * Defines an interceptor for a Mock + */ +class MockInterceptor { + constructor (opts, mockDispatches) { + if (typeof opts !== 'object') { + throw new InvalidArgumentError('opts must be an object') + } + if (typeof opts.path === 'undefined') { + throw new InvalidArgumentError('opts.path must be defined') + } + if (typeof opts.method === 'undefined') { + opts.method = 'GET' + } + // See https://github.com/nodejs/undici/issues/1245 + // As per RFC 3986, clients are not supposed to send URI + // fragments to servers when they retrieve a document, + if (typeof opts.path === 'string') { + if (opts.query) { + opts.path = buildURL(opts.path, opts.query) + } else { + // Matches https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L1811 + const parsedURL = new URL(opts.path, 'data://') + opts.path = parsedURL.pathname + parsedURL.search + } + } + if (typeof opts.method === 'string') { + opts.method = opts.method.toUpperCase() + } + + this[kDispatchKey] = buildKey(opts) + this[kDispatches] = mockDispatches + this[kDefaultHeaders] = {} + this[kDefaultTrailers] = {} + this[kContentLength] = false + } + + createMockScopeDispatchData (statusCode, data, responseOptions = {}) { + const responseData = getResponseData(data) + const contentLength = this[kContentLength] ? { 'content-length': responseData.length } : {} + const headers = { ...this[kDefaultHeaders], ...contentLength, ...responseOptions.headers } + const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers } + + return { statusCode, data, headers, trailers } + } + + validateReplyParameters (statusCode, data, responseOptions) { + if (typeof statusCode === 'undefined') { + throw new InvalidArgumentError('statusCode must be defined') + } + if (typeof data === 'undefined') { + throw new InvalidArgumentError('data must be defined') + } + if (typeof responseOptions !== 'object') { + throw new InvalidArgumentError('responseOptions must be an object') + } + } + + /** + * Mock an undici request with a defined reply. + */ + reply (replyData) { + // Values of reply aren't available right now as they + // can only be available when the reply callback is invoked. + if (typeof replyData === 'function') { + // We'll first wrap the provided callback in another function, + // this function will properly resolve the data from the callback + // when invoked. + const wrappedDefaultsCallback = (opts) => { + // Our reply options callback contains the parameter for statusCode, data and options. + const resolvedData = replyData(opts) + + // Check if it is in the right format + if (typeof resolvedData !== 'object') { + throw new InvalidArgumentError('reply options callback must return an object') + } + + const { statusCode, data = '', responseOptions = {} } = resolvedData + this.validateReplyParameters(statusCode, data, responseOptions) + // Since the values can be obtained immediately we return them + // from this higher order function that will be resolved later. + return { + ...this.createMockScopeDispatchData(statusCode, data, responseOptions) + } + } + + // Add usual dispatch data, but this time set the data parameter to function that will eventually provide data. + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback) + return new MockScope(newMockDispatch) + } + + // We can have either one or three parameters, if we get here, + // we should have 1-3 parameters. So we spread the arguments of + // this function to obtain the parameters, since replyData will always + // just be the statusCode. + const [statusCode, data = '', responseOptions = {}] = [...arguments] + this.validateReplyParameters(statusCode, data, responseOptions) + + // Send in-already provided data like usual + const dispatchData = this.createMockScopeDispatchData(statusCode, data, responseOptions) + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData) + return new MockScope(newMockDispatch) + } + + /** + * Mock an undici request with a defined error. + */ + replyWithError (error) { + if (typeof error === 'undefined') { + throw new InvalidArgumentError('error must be defined') + } + + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error }) + return new MockScope(newMockDispatch) + } + + /** + * Set default reply headers on the interceptor for subsequent replies + */ + defaultReplyHeaders (headers) { + if (typeof headers === 'undefined') { + throw new InvalidArgumentError('headers must be defined') + } + + this[kDefaultHeaders] = headers + return this + } + + /** + * Set default reply trailers on the interceptor for subsequent replies + */ + defaultReplyTrailers (trailers) { + if (typeof trailers === 'undefined') { + throw new InvalidArgumentError('trailers must be defined') + } + + this[kDefaultTrailers] = trailers + return this + } + + /** + * Set reply content length header for replies on the interceptor + */ + replyContentLength () { + this[kContentLength] = true + return this + } +} + +module.exports.MockInterceptor = MockInterceptor +module.exports.MockScope = MockScope + + +/***/ }), + +/***/ 94004: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { promisify } = __nccwpck_require__(39023) +const Pool = __nccwpck_require__(35076) +const { buildMockDispatch } = __nccwpck_require__(53397) +const { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected +} = __nccwpck_require__(91117) +const { MockInterceptor } = __nccwpck_require__(31511) +const Symbols = __nccwpck_require__(36443) +const { InvalidArgumentError } = __nccwpck_require__(68707) + +/** + * MockPool provides an API that extends the Pool to influence the mockDispatches. + */ +class MockPool extends Pool { + constructor (origin, opts) { + super(origin, opts) + + if (!opts || !opts.agent || typeof opts.agent.dispatch !== 'function') { + throw new InvalidArgumentError('Argument opts.agent must implement Agent') + } + + this[kMockAgent] = opts.agent + this[kOrigin] = origin + this[kDispatches] = [] + this[kConnected] = 1 + this[kOriginalDispatch] = this.dispatch + this[kOriginalClose] = this.close.bind(this) + + this.dispatch = buildMockDispatch.call(this) + this.close = this[kClose] + } + + get [Symbols.kConnected] () { + return this[kConnected] + } + + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept (opts) { + return new MockInterceptor(opts, this[kDispatches]) + } + + async [kClose] () { + await promisify(this[kOriginalClose])() + this[kConnected] = 0 + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]) + } +} + +module.exports = MockPool + + +/***/ }), + +/***/ 91117: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kAgent: Symbol('agent'), + kOptions: Symbol('options'), + kFactory: Symbol('factory'), + kDispatches: Symbol('dispatches'), + kDispatchKey: Symbol('dispatch key'), + kDefaultHeaders: Symbol('default headers'), + kDefaultTrailers: Symbol('default trailers'), + kContentLength: Symbol('content length'), + kMockAgent: Symbol('mock agent'), + kMockAgentSet: Symbol('mock agent set'), + kMockAgentGet: Symbol('mock agent get'), + kMockDispatch: Symbol('mock dispatch'), + kClose: Symbol('close'), + kOriginalClose: Symbol('original agent close'), + kOrigin: Symbol('origin'), + kIsMockActive: Symbol('is mock active'), + kNetConnect: Symbol('net connect'), + kGetNetConnect: Symbol('get net connect'), + kConnected: Symbol('connected') +} + + +/***/ }), + +/***/ 53397: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { MockNotMatchedError } = __nccwpck_require__(52429) +const { + kDispatches, + kMockAgent, + kOriginalDispatch, + kOrigin, + kGetNetConnect +} = __nccwpck_require__(91117) +const { buildURL, nop } = __nccwpck_require__(3440) +const { STATUS_CODES } = __nccwpck_require__(58611) +const { + types: { + isPromise + } +} = __nccwpck_require__(39023) + +function matchValue (match, value) { + if (typeof match === 'string') { + return match === value + } + if (match instanceof RegExp) { + return match.test(value) + } + if (typeof match === 'function') { + return match(value) === true + } + return false +} + +function lowerCaseEntries (headers) { + return Object.fromEntries( + Object.entries(headers).map(([headerName, headerValue]) => { + return [headerName.toLocaleLowerCase(), headerValue] + }) + ) +} + +/** + * @param {import('../../index').Headers|string[]|Record} headers + * @param {string} key + */ +function getHeaderByName (headers, key) { + if (Array.isArray(headers)) { + for (let i = 0; i < headers.length; i += 2) { + if (headers[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { + return headers[i + 1] + } + } + + return undefined + } else if (typeof headers.get === 'function') { + return headers.get(key) + } else { + return lowerCaseEntries(headers)[key.toLocaleLowerCase()] + } +} + +/** @param {string[]} headers */ +function buildHeadersFromArray (headers) { // fetch HeadersList + const clone = headers.slice() + const entries = [] + for (let index = 0; index < clone.length; index += 2) { + entries.push([clone[index], clone[index + 1]]) + } + return Object.fromEntries(entries) +} + +function matchHeaders (mockDispatch, headers) { + if (typeof mockDispatch.headers === 'function') { + if (Array.isArray(headers)) { // fetch HeadersList + headers = buildHeadersFromArray(headers) + } + return mockDispatch.headers(headers ? lowerCaseEntries(headers) : {}) + } + if (typeof mockDispatch.headers === 'undefined') { + return true + } + if (typeof headers !== 'object' || typeof mockDispatch.headers !== 'object') { + return false + } + + for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch.headers)) { + const headerValue = getHeaderByName(headers, matchHeaderName) + + if (!matchValue(matchHeaderValue, headerValue)) { + return false + } + } + return true +} + +function safeUrl (path) { + if (typeof path !== 'string') { + return path + } + + const pathSegments = path.split('?') + + if (pathSegments.length !== 2) { + return path + } + + const qp = new URLSearchParams(pathSegments.pop()) + qp.sort() + return [...pathSegments, qp.toString()].join('?') +} + +function matchKey (mockDispatch, { path, method, body, headers }) { + const pathMatch = matchValue(mockDispatch.path, path) + const methodMatch = matchValue(mockDispatch.method, method) + const bodyMatch = typeof mockDispatch.body !== 'undefined' ? matchValue(mockDispatch.body, body) : true + const headersMatch = matchHeaders(mockDispatch, headers) + return pathMatch && methodMatch && bodyMatch && headersMatch +} + +function getResponseData (data) { + if (Buffer.isBuffer(data)) { + return data + } else if (typeof data === 'object') { + return JSON.stringify(data) + } else { + return data.toString() + } +} + +function getMockDispatch (mockDispatches, key) { + const basePath = key.query ? buildURL(key.path, key.query) : key.path + const resolvedPath = typeof basePath === 'string' ? safeUrl(basePath) : basePath + + // Match path + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(safeUrl(path), resolvedPath)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`) + } + + // Match method + matchedMockDispatches = matchedMockDispatches.filter(({ method }) => matchValue(method, key.method)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}'`) + } + + // Match body + matchedMockDispatches = matchedMockDispatches.filter(({ body }) => typeof body !== 'undefined' ? matchValue(body, key.body) : true) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}'`) + } + + // Match headers + matchedMockDispatches = matchedMockDispatches.filter((mockDispatch) => matchHeaders(mockDispatch, key.headers)) + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for headers '${typeof key.headers === 'object' ? JSON.stringify(key.headers) : key.headers}'`) + } + + return matchedMockDispatches[0] +} + +function addMockDispatch (mockDispatches, key, data) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false } + const replyData = typeof data === 'function' ? { callback: data } : { ...data } + const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } } + mockDispatches.push(newMockDispatch) + return newMockDispatch +} + +function deleteMockDispatch (mockDispatches, key) { + const index = mockDispatches.findIndex(dispatch => { + if (!dispatch.consumed) { + return false + } + return matchKey(dispatch, key) + }) + if (index !== -1) { + mockDispatches.splice(index, 1) + } +} + +function buildKey (opts) { + const { path, method, body, headers, query } = opts + return { + path, + method, + body, + headers, + query + } +} + +function generateKeyValues (data) { + return Object.entries(data).reduce((keyValuePairs, [key, value]) => [ + ...keyValuePairs, + Buffer.from(`${key}`), + Array.isArray(value) ? value.map(x => Buffer.from(`${x}`)) : Buffer.from(`${value}`) + ], []) +} + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Status + * @param {number} statusCode + */ +function getStatusText (statusCode) { + return STATUS_CODES[statusCode] || 'unknown' +} + +async function getResponse (body) { + const buffers = [] + for await (const data of body) { + buffers.push(data) + } + return Buffer.concat(buffers).toString('utf8') +} + +/** + * Mock dispatch function used to simulate undici dispatches + */ +function mockDispatch (opts, handler) { + // Get mock dispatch from built key + const key = buildKey(opts) + const mockDispatch = getMockDispatch(this[kDispatches], key) + + mockDispatch.timesInvoked++ + + // Here's where we resolve a callback if a callback is present for the dispatch data. + if (mockDispatch.data.callback) { + mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) } + } + + // Parse mockDispatch data + const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch + const { timesInvoked, times } = mockDispatch + + // If it's used up and not persistent, mark as consumed + mockDispatch.consumed = !persist && timesInvoked >= times + mockDispatch.pending = timesInvoked < times + + // If specified, trigger dispatch error + if (error !== null) { + deleteMockDispatch(this[kDispatches], key) + handler.onError(error) + return true + } + + // Handle the request with a delay if necessary + if (typeof delay === 'number' && delay > 0) { + setTimeout(() => { + handleReply(this[kDispatches]) + }, delay) + } else { + handleReply(this[kDispatches]) + } + + function handleReply (mockDispatches, _data = data) { + // fetch's HeadersList is a 1D string array + const optsHeaders = Array.isArray(opts.headers) + ? buildHeadersFromArray(opts.headers) + : opts.headers + const body = typeof _data === 'function' + ? _data({ ...opts, headers: optsHeaders }) + : _data + + // util.types.isPromise is likely needed for jest. + if (isPromise(body)) { + // If handleReply is asynchronous, throwing an error + // in the callback will reject the promise, rather than + // synchronously throw the error, which breaks some tests. + // Rather, we wait for the callback to resolve if it is a + // promise, and then re-run handleReply with the new body. + body.then((newData) => handleReply(mockDispatches, newData)) + return + } + + const responseData = getResponseData(body) + const responseHeaders = generateKeyValues(headers) + const responseTrailers = generateKeyValues(trailers) + + handler.abort = nop + handler.onHeaders(statusCode, responseHeaders, resume, getStatusText(statusCode)) + handler.onData(Buffer.from(responseData)) + handler.onComplete(responseTrailers) + deleteMockDispatch(mockDispatches, key) + } + + function resume () {} + + return true +} + +function buildMockDispatch () { + const agent = this[kMockAgent] + const origin = this[kOrigin] + const originalDispatch = this[kOriginalDispatch] + + return function dispatch (opts, handler) { + if (agent.isMockActive) { + try { + mockDispatch.call(this, opts, handler) + } catch (error) { + if (error instanceof MockNotMatchedError) { + const netConnect = agent[kGetNetConnect]() + if (netConnect === false) { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)`) + } + if (checkNetConnect(netConnect, origin)) { + originalDispatch.call(this, opts, handler) + } else { + throw new MockNotMatchedError(`${error.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)`) + } + } else { + throw error + } + } + } else { + originalDispatch.call(this, opts, handler) + } + } +} + +function checkNetConnect (netConnect, origin) { + const url = new URL(origin) + if (netConnect === true) { + return true + } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url.host))) { + return true + } + return false +} + +function buildMockOptions (opts) { + if (opts) { + const { agent, ...mockOptions } = opts + return mockOptions + } +} + +module.exports = { + getResponseData, + getMockDispatch, + addMockDispatch, + deleteMockDispatch, + buildKey, + generateKeyValues, + matchValue, + getResponse, + getStatusText, + mockDispatch, + buildMockDispatch, + checkNetConnect, + buildMockOptions, + getHeaderByName +} + + +/***/ }), + +/***/ 56142: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Transform } = __nccwpck_require__(2203) +const { Console } = __nccwpck_require__(64236) + +/** + * Gets the output of `console.table(…)` as a string. + */ +module.exports = class PendingInterceptorsFormatter { + constructor ({ disableColors } = {}) { + this.transform = new Transform({ + transform (chunk, _enc, cb) { + cb(null, chunk) + } + }) + + this.logger = new Console({ + stdout: this.transform, + inspectOptions: { + colors: !disableColors && !process.env.CI + } + }) + } + + format (pendingInterceptors) { + const withPrettyHeaders = pendingInterceptors.map( + ({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + Method: method, + Origin: origin, + Path: path, + 'Status code': statusCode, + Persistent: persist ? '✅' : '❌', + Invocations: timesInvoked, + Remaining: persist ? Infinity : times - timesInvoked + })) + + this.logger.table(withPrettyHeaders) + return this.transform.read().toString() + } +} + + +/***/ }), + +/***/ 91529: +/***/ ((module) => { + +"use strict"; + + +const singulars = { + pronoun: 'it', + is: 'is', + was: 'was', + this: 'this' +} + +const plurals = { + pronoun: 'they', + is: 'are', + was: 'were', + this: 'these' +} + +module.exports = class Pluralizer { + constructor (singular, plural) { + this.singular = singular + this.plural = plural + } + + pluralize (count) { + const one = count === 1 + const keys = one ? singulars : plurals + const noun = one ? this.singular : this.plural + return { ...keys, count, noun } + } +} + + +/***/ }), + +/***/ 34869: +/***/ ((module) => { + +"use strict"; +/* eslint-disable */ + + + +// Extracted from node/lib/internal/fixed_queue.js + +// Currently optimal queue size, tested on V8 6.0 - 6.6. Must be power of two. +const kSize = 2048; +const kMask = kSize - 1; + +// The FixedQueue is implemented as a singly-linked list of fixed-size +// circular buffers. It looks something like this: +// +// head tail +// | | +// v v +// +-----------+ <-----\ +-----------+ <------\ +-----------+ +// | [null] | \----- | next | \------- | next | +// +-----------+ +-----------+ +-----------+ +// | item | <-- bottom | item | <-- bottom | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | | [empty] | +// | item | | item | bottom --> | item | +// | item | | item | | item | +// | ... | | ... | | ... | +// | item | | item | | item | +// | item | | item | | item | +// | [empty] | <-- top | item | | item | +// | [empty] | | item | | item | +// | [empty] | | [empty] | <-- top top --> | [empty] | +// +-----------+ +-----------+ +-----------+ +// +// Or, if there is only one circular buffer, it looks something +// like either of these: +// +// head tail head tail +// | | | | +// v v v v +// +-----------+ +-----------+ +// | [null] | | [null] | +// +-----------+ +-----------+ +// | [empty] | | item | +// | [empty] | | item | +// | item | <-- bottom top --> | [empty] | +// | item | | [empty] | +// | [empty] | <-- top bottom --> | item | +// | [empty] | | item | +// +-----------+ +-----------+ +// +// Adding a value means moving `top` forward by one, removing means +// moving `bottom` forward by one. After reaching the end, the queue +// wraps around. +// +// When `top === bottom` the current queue is empty and when +// `top + 1 === bottom` it's full. This wastes a single space of storage +// but allows much quicker checks. + +class FixedCircularBuffer { + constructor() { + this.bottom = 0; + this.top = 0; + this.list = new Array(kSize); + this.next = null; + } + + isEmpty() { + return this.top === this.bottom; + } + + isFull() { + return ((this.top + 1) & kMask) === this.bottom; + } + + push(data) { + this.list[this.top] = data; + this.top = (this.top + 1) & kMask; + } + + shift() { + const nextItem = this.list[this.bottom]; + if (nextItem === undefined) + return null; + this.list[this.bottom] = undefined; + this.bottom = (this.bottom + 1) & kMask; + return nextItem; + } +} + +module.exports = class FixedQueue { + constructor() { + this.head = this.tail = new FixedCircularBuffer(); + } + + isEmpty() { + return this.head.isEmpty(); + } + + push(data) { + if (this.head.isFull()) { + // Head is full: Creates a new queue, sets the old queue's `.next` to it, + // and sets it as the new main queue. + this.head = this.head.next = new FixedCircularBuffer(); + } + this.head.push(data); + } + + shift() { + const tail = this.tail; + const next = tail.shift(); + if (tail.isEmpty() && tail.next !== null) { + // If there is another queue, it forms the new tail. + this.tail = tail.next; + } + return next; + } +}; + + +/***/ }), + +/***/ 58640: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const DispatcherBase = __nccwpck_require__(50001) +const FixedQueue = __nccwpck_require__(34869) +const { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = __nccwpck_require__(36443) +const PoolStats = __nccwpck_require__(24622) + +const kClients = Symbol('clients') +const kNeedDrain = Symbol('needDrain') +const kQueue = Symbol('queue') +const kClosedResolve = Symbol('closed resolve') +const kOnDrain = Symbol('onDrain') +const kOnConnect = Symbol('onConnect') +const kOnDisconnect = Symbol('onDisconnect') +const kOnConnectionError = Symbol('onConnectionError') +const kGetDispatcher = Symbol('get dispatcher') +const kAddClient = Symbol('add client') +const kRemoveClient = Symbol('remove client') +const kStats = Symbol('stats') + +class PoolBase extends DispatcherBase { + constructor () { + super() + + this[kQueue] = new FixedQueue() + this[kClients] = [] + this[kQueued] = 0 + + const pool = this + + this[kOnDrain] = function onDrain (origin, targets) { + const queue = pool[kQueue] + + let needDrain = false + + while (!needDrain) { + const item = queue.shift() + if (!item) { + break + } + pool[kQueued]-- + needDrain = !this.dispatch(item.opts, item.handler) + } + + this[kNeedDrain] = needDrain + + if (!this[kNeedDrain] && pool[kNeedDrain]) { + pool[kNeedDrain] = false + pool.emit('drain', origin, [pool, ...targets]) + } + + if (pool[kClosedResolve] && queue.isEmpty()) { + Promise + .all(pool[kClients].map(c => c.close())) + .then(pool[kClosedResolve]) + } + } + + this[kOnConnect] = (origin, targets) => { + pool.emit('connect', origin, [pool, ...targets]) + } + + this[kOnDisconnect] = (origin, targets, err) => { + pool.emit('disconnect', origin, [pool, ...targets], err) + } + + this[kOnConnectionError] = (origin, targets, err) => { + pool.emit('connectionError', origin, [pool, ...targets], err) + } + + this[kStats] = new PoolStats(this) + } + + get [kBusy] () { + return this[kNeedDrain] + } + + get [kConnected] () { + return this[kClients].filter(client => client[kConnected]).length + } + + get [kFree] () { + return this[kClients].filter(client => client[kConnected] && !client[kNeedDrain]).length + } + + get [kPending] () { + let ret = this[kQueued] + for (const { [kPending]: pending } of this[kClients]) { + ret += pending + } + return ret + } + + get [kRunning] () { + let ret = 0 + for (const { [kRunning]: running } of this[kClients]) { + ret += running + } + return ret + } + + get [kSize] () { + let ret = this[kQueued] + for (const { [kSize]: size } of this[kClients]) { + ret += size + } + return ret + } + + get stats () { + return this[kStats] + } + + async [kClose] () { + if (this[kQueue].isEmpty()) { + return Promise.all(this[kClients].map(c => c.close())) + } else { + return new Promise((resolve) => { + this[kClosedResolve] = resolve + }) + } + } + + async [kDestroy] (err) { + while (true) { + const item = this[kQueue].shift() + if (!item) { + break + } + item.handler.onError(err) + } + + return Promise.all(this[kClients].map(c => c.destroy(err))) + } + + [kDispatch] (opts, handler) { + const dispatcher = this[kGetDispatcher]() + + if (!dispatcher) { + this[kNeedDrain] = true + this[kQueue].push({ opts, handler }) + this[kQueued]++ + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true + this[kNeedDrain] = !this[kGetDispatcher]() + } + + return !this[kNeedDrain] + } + + [kAddClient] (client) { + client + .on('drain', this[kOnDrain]) + .on('connect', this[kOnConnect]) + .on('disconnect', this[kOnDisconnect]) + .on('connectionError', this[kOnConnectionError]) + + this[kClients].push(client) + + if (this[kNeedDrain]) { + process.nextTick(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client[kUrl], [this, client]) + } + }) + } + + return this + } + + [kRemoveClient] (client) { + client.close(() => { + const idx = this[kClients].indexOf(client) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + }) + + this[kNeedDrain] = this[kClients].some(dispatcher => ( + !dispatcher[kNeedDrain] && + dispatcher.closed !== true && + dispatcher.destroyed !== true + )) + } +} + +module.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher +} + + +/***/ }), + +/***/ 24622: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +const { kFree, kConnected, kPending, kQueued, kRunning, kSize } = __nccwpck_require__(36443) +const kPool = Symbol('pool') + +class PoolStats { + constructor (pool) { + this[kPool] = pool + } + + get connected () { + return this[kPool][kConnected] + } + + get free () { + return this[kPool][kFree] + } + + get pending () { + return this[kPool][kPending] + } + + get queued () { + return this[kPool][kQueued] + } + + get running () { + return this[kPool][kRunning] + } + + get size () { + return this[kPool][kSize] + } +} + +module.exports = PoolStats + + +/***/ }), + +/***/ 35076: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher +} = __nccwpck_require__(58640) +const Client = __nccwpck_require__(86197) +const { + InvalidArgumentError +} = __nccwpck_require__(68707) +const util = __nccwpck_require__(3440) +const { kUrl, kInterceptors } = __nccwpck_require__(36443) +const buildConnector = __nccwpck_require__(59136) + +const kOptions = Symbol('options') +const kConnections = Symbol('connections') +const kFactory = Symbol('factory') + +function defaultFactory (origin, opts) { + return new Client(origin, opts) +} + +class Pool extends PoolBase { + constructor (origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + ...options + } = {}) { + super() + + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError('invalid connections') + } + + if (typeof factory !== 'function') { + throw new InvalidArgumentError('factory must be a function.') + } + + if (connect != null && typeof connect !== 'function' && typeof connect !== 'object') { + throw new InvalidArgumentError('connect must be a function or an object') + } + + if (typeof connect !== 'function') { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined), + ...connect + }) + } + + this[kInterceptors] = options.interceptors && options.interceptors.Pool && Array.isArray(options.interceptors.Pool) + ? options.interceptors.Pool + : [] + this[kConnections] = connections || null + this[kUrl] = util.parseOrigin(origin) + this[kOptions] = { ...util.deepClone(options), connect, allowH2 } + this[kOptions].interceptors = options.interceptors + ? { ...options.interceptors } + : undefined + this[kFactory] = factory + + this.on('connectionError', (origin, targets, error) => { + // If a connection error occurs, we remove the client from the pool, + // and emit a connectionError event. They will not be re-used. + // Fixes https://github.com/nodejs/undici/issues/3895 + for (const target of targets) { + // Do not use kRemoveClient here, as it will close the client, + // but the client cannot be closed in this state. + const idx = this[kClients].indexOf(target) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + } + }) + } + + [kGetDispatcher] () { + let dispatcher = this[kClients].find(dispatcher => !dispatcher[kNeedDrain]) + + if (dispatcher) { + return dispatcher + } + + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + dispatcher = this[kFactory](this[kUrl], this[kOptions]) + this[kAddClient](dispatcher) + } + + return dispatcher + } +} + +module.exports = Pool + + +/***/ }), + +/***/ 22720: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kProxy, kClose, kDestroy, kInterceptors } = __nccwpck_require__(36443) +const { URL } = __nccwpck_require__(87016) +const Agent = __nccwpck_require__(59965) +const Pool = __nccwpck_require__(35076) +const DispatcherBase = __nccwpck_require__(50001) +const { InvalidArgumentError, RequestAbortedError } = __nccwpck_require__(68707) +const buildConnector = __nccwpck_require__(59136) + +const kAgent = Symbol('proxy agent') +const kClient = Symbol('proxy client') +const kProxyHeaders = Symbol('proxy headers') +const kRequestTls = Symbol('request tls settings') +const kProxyTls = Symbol('proxy tls settings') +const kConnectEndpoint = Symbol('connect endpoint function') + +function defaultProtocolPort (protocol) { + return protocol === 'https:' ? 443 : 80 +} + +function buildProxyOptions (opts) { + if (typeof opts === 'string') { + opts = { uri: opts } + } + + if (!opts || !opts.uri) { + throw new InvalidArgumentError('Proxy opts.uri is mandatory') + } + + return { + uri: opts.uri, + protocol: opts.protocol || 'https' + } +} + +function defaultFactory (origin, opts) { + return new Pool(origin, opts) +} + +class ProxyAgent extends DispatcherBase { + constructor (opts) { + super(opts) + this[kProxy] = buildProxyOptions(opts) + this[kAgent] = new Agent(opts) + this[kInterceptors] = opts.interceptors && opts.interceptors.ProxyAgent && Array.isArray(opts.interceptors.ProxyAgent) + ? opts.interceptors.ProxyAgent + : [] + + if (typeof opts === 'string') { + opts = { uri: opts } + } + + if (!opts || !opts.uri) { + throw new InvalidArgumentError('Proxy opts.uri is mandatory') + } + + const { clientFactory = defaultFactory } = opts + + if (typeof clientFactory !== 'function') { + throw new InvalidArgumentError('Proxy opts.clientFactory must be a function.') + } + + this[kRequestTls] = opts.requestTls + this[kProxyTls] = opts.proxyTls + this[kProxyHeaders] = opts.headers || {} + + const resolvedUrl = new URL(opts.uri) + const { origin, port, host, username, password } = resolvedUrl + + if (opts.auth && opts.token) { + throw new InvalidArgumentError('opts.auth cannot be used in combination with opts.token') + } else if (opts.auth) { + /* @deprecated in favour of opts.token */ + this[kProxyHeaders]['proxy-authorization'] = `Basic ${opts.auth}` + } else if (opts.token) { + this[kProxyHeaders]['proxy-authorization'] = opts.token + } else if (username && password) { + this[kProxyHeaders]['proxy-authorization'] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString('base64')}` + } + + const connect = buildConnector({ ...opts.proxyTls }) + this[kConnectEndpoint] = buildConnector({ ...opts.requestTls }) + this[kClient] = clientFactory(resolvedUrl, { connect }) + this[kAgent] = new Agent({ + ...opts, + connect: async (opts, callback) => { + let requestedHost = opts.host + if (!opts.port) { + requestedHost += `:${defaultProtocolPort(opts.protocol)}` + } + try { + const { socket, statusCode } = await this[kClient].connect({ + origin, + port, + path: requestedHost, + signal: opts.signal, + headers: { + ...this[kProxyHeaders], + host + } + }) + if (statusCode !== 200) { + socket.on('error', () => {}).destroy() + callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)) + } + if (opts.protocol !== 'https:') { + callback(null, socket) + return + } + let servername + if (this[kRequestTls]) { + servername = this[kRequestTls].servername + } else { + servername = opts.servername + } + this[kConnectEndpoint]({ ...opts, servername, httpSocket: socket }, callback) + } catch (err) { + callback(err) + } + } + }) + } + + dispatch (opts, handler) { + const { host } = new URL(opts.origin) + const headers = buildHeaders(opts.headers) + throwIfProxyAuthIsSent(headers) + return this[kAgent].dispatch( + { + ...opts, + headers: { + ...headers, + host + } + }, + handler + ) + } + + async [kClose] () { + await this[kAgent].close() + await this[kClient].close() + } + + async [kDestroy] () { + await this[kAgent].destroy() + await this[kClient].destroy() + } +} + +/** + * @param {string[] | Record} headers + * @returns {Record} + */ +function buildHeaders (headers) { + // When using undici.fetch, the headers list is stored + // as an array. + if (Array.isArray(headers)) { + /** @type {Record} */ + const headersPair = {} + + for (let i = 0; i < headers.length; i += 2) { + headersPair[headers[i]] = headers[i + 1] + } + + return headersPair + } + + return headers +} + +/** + * @param {Record} headers + * + * Previous versions of ProxyAgent suggests the Proxy-Authorization in request headers + * Nevertheless, it was changed and to avoid a security vulnerability by end users + * this check was created. + * It should be removed in the next major version for performance reasons + */ +function throwIfProxyAuthIsSent (headers) { + const existProxyAuth = headers && Object.keys(headers) + .find((key) => key.toLowerCase() === 'proxy-authorization') + if (existProxyAuth) { + throw new InvalidArgumentError('Proxy-Authorization should be sent in ProxyAgent constructor') + } +} + +module.exports = ProxyAgent + + +/***/ }), + +/***/ 28804: +/***/ ((module) => { + +"use strict"; + + +let fastNow = Date.now() +let fastNowTimeout + +const fastTimers = [] + +function onTimeout () { + fastNow = Date.now() + + let len = fastTimers.length + let idx = 0 + while (idx < len) { + const timer = fastTimers[idx] + + if (timer.state === 0) { + timer.state = fastNow + timer.delay + } else if (timer.state > 0 && fastNow >= timer.state) { + timer.state = -1 + timer.callback(timer.opaque) + } + + if (timer.state === -1) { + timer.state = -2 + if (idx !== len - 1) { + fastTimers[idx] = fastTimers.pop() + } else { + fastTimers.pop() + } + len -= 1 + } else { + idx += 1 + } + } + + if (fastTimers.length > 0) { + refreshTimeout() + } +} + +function refreshTimeout () { + if (fastNowTimeout && fastNowTimeout.refresh) { + fastNowTimeout.refresh() + } else { + clearTimeout(fastNowTimeout) + fastNowTimeout = setTimeout(onTimeout, 1e3) + if (fastNowTimeout.unref) { + fastNowTimeout.unref() + } + } +} + +class Timeout { + constructor (callback, delay, opaque) { + this.callback = callback + this.delay = delay + this.opaque = opaque + + // -2 not in timer list + // -1 in timer list but inactive + // 0 in timer list waiting for time + // > 0 in timer list waiting for time to expire + this.state = -2 + + this.refresh() + } + + refresh () { + if (this.state === -2) { + fastTimers.push(this) + if (!fastNowTimeout || fastTimers.length === 1) { + refreshTimeout() + } + } + + this.state = 0 + } + + clear () { + this.state = -1 + } +} + +module.exports = { + setTimeout (callback, delay, opaque) { + return delay < 1e3 + ? setTimeout(callback, delay, opaque) + : new Timeout(callback, delay, opaque) + }, + clearTimeout (timeout) { + if (timeout instanceof Timeout) { + timeout.clear() + } else { + clearTimeout(timeout) + } + } +} + + +/***/ }), + +/***/ 68550: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const diagnosticsChannel = __nccwpck_require__(31637) +const { uid, states } = __nccwpck_require__(45913) +const { + kReadyState, + kSentClose, + kByteParser, + kReceivedClose +} = __nccwpck_require__(62933) +const { fireEvent, failWebsocketConnection } = __nccwpck_require__(3574) +const { CloseEvent } = __nccwpck_require__(46255) +const { makeRequest } = __nccwpck_require__(25194) +const { fetching } = __nccwpck_require__(12315) +const { Headers } = __nccwpck_require__(26349) +const { getGlobalDispatcher } = __nccwpck_require__(32581) +const { kHeadersList } = __nccwpck_require__(36443) + +const channels = {} +channels.open = diagnosticsChannel.channel('undici:websocket:open') +channels.close = diagnosticsChannel.channel('undici:websocket:close') +channels.socketError = diagnosticsChannel.channel('undici:websocket:socket_error') + +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(76982) +} catch { + +} + +/** + * @see https://websockets.spec.whatwg.org/#concept-websocket-establish + * @param {URL} url + * @param {string|string[]} protocols + * @param {import('./websocket').WebSocket} ws + * @param {(response: any) => void} onEstablish + * @param {Partial} options + */ +function establishWebSocketConnection (url, protocols, ws, onEstablish, options) { + // 1. Let requestURL be a copy of url, with its scheme set to "http", if url’s + // scheme is "ws", and to "https" otherwise. + const requestURL = url + + requestURL.protocol = url.protocol === 'ws:' ? 'http:' : 'https:' + + // 2. Let request be a new request, whose URL is requestURL, client is client, + // service-workers mode is "none", referrer is "no-referrer", mode is + // "websocket", credentials mode is "include", cache mode is "no-store" , + // and redirect mode is "error". + const request = makeRequest({ + urlList: [requestURL], + serviceWorkers: 'none', + referrer: 'no-referrer', + mode: 'websocket', + credentials: 'include', + cache: 'no-store', + redirect: 'error' + }) + + // Note: undici extension, allow setting custom headers. + if (options.headers) { + const headersList = new Headers(options.headers)[kHeadersList] + + request.headersList = headersList + } + + // 3. Append (`Upgrade`, `websocket`) to request’s header list. + // 4. Append (`Connection`, `Upgrade`) to request’s header list. + // Note: both of these are handled by undici currently. + // https://github.com/nodejs/undici/blob/68c269c4144c446f3f1220951338daef4a6b5ec4/lib/client.js#L1397 + + // 5. Let keyValue be a nonce consisting of a randomly selected + // 16-byte value that has been forgiving-base64-encoded and + // isomorphic encoded. + const keyValue = crypto.randomBytes(16).toString('base64') + + // 6. Append (`Sec-WebSocket-Key`, keyValue) to request’s + // header list. + request.headersList.append('sec-websocket-key', keyValue) + + // 7. Append (`Sec-WebSocket-Version`, `13`) to request’s + // header list. + request.headersList.append('sec-websocket-version', '13') + + // 8. For each protocol in protocols, combine + // (`Sec-WebSocket-Protocol`, protocol) in request’s header + // list. + for (const protocol of protocols) { + request.headersList.append('sec-websocket-protocol', protocol) + } + + // 9. Let permessageDeflate be a user-agent defined + // "permessage-deflate" extension header value. + // https://github.com/mozilla/gecko-dev/blob/ce78234f5e653a5d3916813ff990f053510227bc/netwerk/protocol/websocket/WebSocketChannel.cpp#L2673 + // TODO: enable once permessage-deflate is supported + const permessageDeflate = '' // 'permessage-deflate; 15' + + // 10. Append (`Sec-WebSocket-Extensions`, permessageDeflate) to + // request’s header list. + // request.headersList.append('sec-websocket-extensions', permessageDeflate) + + // 11. Fetch request with useParallelQueue set to true, and + // processResponse given response being these steps: + const controller = fetching({ + request, + useParallelQueue: true, + dispatcher: options.dispatcher ?? getGlobalDispatcher(), + processResponse (response) { + // 1. If response is a network error or its status is not 101, + // fail the WebSocket connection. + if (response.type === 'error' || response.status !== 101) { + failWebsocketConnection(ws, 'Received network error or non-101 status code.') + return + } + + // 2. If protocols is not the empty list and extracting header + // list values given `Sec-WebSocket-Protocol` and response’s + // header list results in null, failure, or the empty byte + // sequence, then fail the WebSocket connection. + if (protocols.length !== 0 && !response.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(ws, 'Server did not respond with sent protocols.') + return + } + + // 3. Follow the requirements stated step 2 to step 6, inclusive, + // of the last set of steps in section 4.1 of The WebSocket + // Protocol to validate response. This either results in fail + // the WebSocket connection or the WebSocket connection is + // established. + + // 2. If the response lacks an |Upgrade| header field or the |Upgrade| + // header field contains a value that is not an ASCII case- + // insensitive match for the value "websocket", the client MUST + // _Fail the WebSocket Connection_. + if (response.headersList.get('Upgrade')?.toLowerCase() !== 'websocket') { + failWebsocketConnection(ws, 'Server did not set Upgrade header to "websocket".') + return + } + + // 3. If the response lacks a |Connection| header field or the + // |Connection| header field doesn't contain a token that is an + // ASCII case-insensitive match for the value "Upgrade", the client + // MUST _Fail the WebSocket Connection_. + if (response.headersList.get('Connection')?.toLowerCase() !== 'upgrade') { + failWebsocketConnection(ws, 'Server did not set Connection header to "upgrade".') + return + } + + // 4. If the response lacks a |Sec-WebSocket-Accept| header field or + // the |Sec-WebSocket-Accept| contains a value other than the + // base64-encoded SHA-1 of the concatenation of the |Sec-WebSocket- + // Key| (as a string, not base64-decoded) with the string "258EAFA5- + // E914-47DA-95CA-C5AB0DC85B11" but ignoring any leading and + // trailing whitespace, the client MUST _Fail the WebSocket + // Connection_. + const secWSAccept = response.headersList.get('Sec-WebSocket-Accept') + const digest = crypto.createHash('sha1').update(keyValue + uid).digest('base64') + if (secWSAccept !== digest) { + failWebsocketConnection(ws, 'Incorrect hash received in Sec-WebSocket-Accept header.') + return + } + + // 5. If the response includes a |Sec-WebSocket-Extensions| header + // field and this header field indicates the use of an extension + // that was not present in the client's handshake (the server has + // indicated an extension not requested by the client), the client + // MUST _Fail the WebSocket Connection_. (The parsing of this + // header field to determine which extensions are requested is + // discussed in Section 9.1.) + const secExtension = response.headersList.get('Sec-WebSocket-Extensions') + + if (secExtension !== null && secExtension !== permessageDeflate) { + failWebsocketConnection(ws, 'Received different permessage-deflate than the one set.') + return + } + + // 6. If the response includes a |Sec-WebSocket-Protocol| header field + // and this header field indicates the use of a subprotocol that was + // not present in the client's handshake (the server has indicated a + // subprotocol not requested by the client), the client MUST _Fail + // the WebSocket Connection_. + const secProtocol = response.headersList.get('Sec-WebSocket-Protocol') + + if (secProtocol !== null && secProtocol !== request.headersList.get('Sec-WebSocket-Protocol')) { + failWebsocketConnection(ws, 'Protocol was not set in the opening handshake.') + return + } + + response.socket.on('data', onSocketData) + response.socket.on('close', onSocketClose) + response.socket.on('error', onSocketError) + + if (channels.open.hasSubscribers) { + channels.open.publish({ + address: response.socket.address(), + protocol: secProtocol, + extensions: secExtension + }) + } + + onEstablish(response) + } + }) + + return controller +} + +/** + * @param {Buffer} chunk + */ +function onSocketData (chunk) { + if (!this.ws[kByteParser].write(chunk)) { + this.pause() + } +} + +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + */ +function onSocketClose () { + const { ws } = this + + // If the TCP connection was closed after the + // WebSocket closing handshake was completed, the WebSocket connection + // is said to have been closed _cleanly_. + const wasClean = ws[kSentClose] && ws[kReceivedClose] + + let code = 1005 + let reason = '' + + const result = ws[kByteParser].closingInfo + + if (result) { + code = result.code ?? 1005 + reason = result.reason + } else if (!ws[kSentClose]) { + // If _The WebSocket + // Connection is Closed_ and no Close control frame was received by the + // endpoint (such as could occur if the underlying transport connection + // is lost), _The WebSocket Connection Close Code_ is considered to be + // 1006. + code = 1006 + } + + // 1. Change the ready state to CLOSED (3). + ws[kReadyState] = states.CLOSED + + // 2. If the user agent was required to fail the WebSocket + // connection, or if the WebSocket connection was closed + // after being flagged as full, fire an event named error + // at the WebSocket object. + // TODO + + // 3. Fire an event named close at the WebSocket object, + // using CloseEvent, with the wasClean attribute + // initialized to true if the connection closed cleanly + // and false otherwise, the code attribute initialized to + // the WebSocket connection close code, and the reason + // attribute initialized to the result of applying UTF-8 + // decode without BOM to the WebSocket connection close + // reason. + fireEvent('close', ws, CloseEvent, { + wasClean, code, reason + }) + + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: ws, + code, + reason + }) + } +} + +function onSocketError (error) { + const { ws } = this + + ws[kReadyState] = states.CLOSING + + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(error) + } + + this.destroy() +} + +module.exports = { + establishWebSocketConnection +} + + +/***/ }), + +/***/ 45913: +/***/ ((module) => { + +"use strict"; + + +// This is a Globally Unique Identifier unique used +// to validate that the endpoint accepts websocket +// connections. +// See https://www.rfc-editor.org/rfc/rfc6455.html#section-1.3 +const uid = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' + +/** @type {PropertyDescriptor} */ +const staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false +} + +const states = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 +} + +const opcodes = { + CONTINUATION: 0x0, + TEXT: 0x1, + BINARY: 0x2, + CLOSE: 0x8, + PING: 0x9, + PONG: 0xA +} + +const maxUnsigned16Bit = 2 ** 16 - 1 // 65535 + +const parserStates = { + INFO: 0, + PAYLOADLENGTH_16: 2, + PAYLOADLENGTH_64: 3, + READ_DATA: 4 +} + +const emptyBuffer = Buffer.allocUnsafe(0) + +module.exports = { + uid, + staticPropertyDescriptors, + states, + opcodes, + maxUnsigned16Bit, + parserStates, + emptyBuffer +} + + +/***/ }), + +/***/ 46255: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(74222) +const { kEnumerableProperty } = __nccwpck_require__(3440) +const { MessagePort } = __nccwpck_require__(28167) + +/** + * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent + */ +class MessageEvent extends Event { + #eventInit + + constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent constructor' }) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.MessageEventInit(eventInitDict) + + super(type, eventInitDict) + + this.#eventInit = eventInitDict + } + + get data () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.data + } + + get origin () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.origin + } + + get lastEventId () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.lastEventId + } + + get source () { + webidl.brandCheck(this, MessageEvent) + + return this.#eventInit.source + } + + get ports () { + webidl.brandCheck(this, MessageEvent) + + if (!Object.isFrozen(this.#eventInit.ports)) { + Object.freeze(this.#eventInit.ports) + } + + return this.#eventInit.ports + } + + initMessageEvent ( + type, + bubbles = false, + cancelable = false, + data = null, + origin = '', + lastEventId = '', + source = null, + ports = [] + ) { + webidl.brandCheck(this, MessageEvent) + + webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent.initMessageEvent' }) + + return new MessageEvent(type, { + bubbles, cancelable, data, origin, lastEventId, source, ports + }) + } +} + +/** + * @see https://websockets.spec.whatwg.org/#the-closeevent-interface + */ +class CloseEvent extends Event { + #eventInit + + constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'CloseEvent constructor' }) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.CloseEventInit(eventInitDict) + + super(type, eventInitDict) + + this.#eventInit = eventInitDict + } + + get wasClean () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.wasClean + } + + get code () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.code + } + + get reason () { + webidl.brandCheck(this, CloseEvent) + + return this.#eventInit.reason + } +} + +// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface +class ErrorEvent extends Event { + #eventInit + + constructor (type, eventInitDict) { + webidl.argumentLengthCheck(arguments, 1, { header: 'ErrorEvent constructor' }) + + super(type, eventInitDict) + + type = webidl.converters.DOMString(type) + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) + + this.#eventInit = eventInitDict + } + + get message () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.message + } + + get filename () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.filename + } + + get lineno () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.lineno + } + + get colno () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.colno + } + + get error () { + webidl.brandCheck(this, ErrorEvent) + + return this.#eventInit.error + } +} + +Object.defineProperties(MessageEvent.prototype, { + [Symbol.toStringTag]: { + value: 'MessageEvent', + configurable: true + }, + data: kEnumerableProperty, + origin: kEnumerableProperty, + lastEventId: kEnumerableProperty, + source: kEnumerableProperty, + ports: kEnumerableProperty, + initMessageEvent: kEnumerableProperty +}) + +Object.defineProperties(CloseEvent.prototype, { + [Symbol.toStringTag]: { + value: 'CloseEvent', + configurable: true + }, + reason: kEnumerableProperty, + code: kEnumerableProperty, + wasClean: kEnumerableProperty +}) + +Object.defineProperties(ErrorEvent.prototype, { + [Symbol.toStringTag]: { + value: 'ErrorEvent', + configurable: true + }, + message: kEnumerableProperty, + filename: kEnumerableProperty, + lineno: kEnumerableProperty, + colno: kEnumerableProperty, + error: kEnumerableProperty +}) + +webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.MessagePort +) + +const eventInit = [ + { + key: 'bubbles', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'cancelable', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'composed', + converter: webidl.converters.boolean, + defaultValue: false + } +] + +webidl.converters.MessageEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'data', + converter: webidl.converters.any, + defaultValue: null + }, + { + key: 'origin', + converter: webidl.converters.USVString, + defaultValue: '' + }, + { + key: 'lastEventId', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'source', + // Node doesn't implement WindowProxy or ServiceWorker, so the only + // valid value for source is a MessagePort. + converter: webidl.nullableConverter(webidl.converters.MessagePort), + defaultValue: null + }, + { + key: 'ports', + converter: webidl.converters['sequence'], + get defaultValue () { + return [] + } + } +]) + +webidl.converters.CloseEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'wasClean', + converter: webidl.converters.boolean, + defaultValue: false + }, + { + key: 'code', + converter: webidl.converters['unsigned short'], + defaultValue: 0 + }, + { + key: 'reason', + converter: webidl.converters.USVString, + defaultValue: '' + } +]) + +webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: 'message', + converter: webidl.converters.DOMString, + defaultValue: '' + }, + { + key: 'filename', + converter: webidl.converters.USVString, + defaultValue: '' + }, + { + key: 'lineno', + converter: webidl.converters['unsigned long'], + defaultValue: 0 + }, + { + key: 'colno', + converter: webidl.converters['unsigned long'], + defaultValue: 0 + }, + { + key: 'error', + converter: webidl.converters.any + } +]) + +module.exports = { + MessageEvent, + CloseEvent, + ErrorEvent +} + + +/***/ }), + +/***/ 31237: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { maxUnsigned16Bit } = __nccwpck_require__(45913) + +/** @type {import('crypto')} */ +let crypto +try { + crypto = __nccwpck_require__(76982) +} catch { + +} + +class WebsocketFrameSend { + /** + * @param {Buffer|undefined} data + */ + constructor (data) { + this.frameData = data + this.maskKey = crypto.randomBytes(4) + } + + createFrame (opcode) { + const bodyLength = this.frameData?.byteLength ?? 0 + + /** @type {number} */ + let payloadLength = bodyLength // 0-125 + let offset = 6 + + if (bodyLength > maxUnsigned16Bit) { + offset += 8 // payload length is next 8 bytes + payloadLength = 127 + } else if (bodyLength > 125) { + offset += 2 // payload length is next 2 bytes + payloadLength = 126 + } + + const buffer = Buffer.allocUnsafe(bodyLength + offset) + + // Clear first 2 bytes, everything else is overwritten + buffer[0] = buffer[1] = 0 + buffer[0] |= 0x80 // FIN + buffer[0] = (buffer[0] & 0xF0) + opcode // opcode + + /*! ws. MIT License. Einar Otto Stangvik */ + buffer[offset - 4] = this.maskKey[0] + buffer[offset - 3] = this.maskKey[1] + buffer[offset - 2] = this.maskKey[2] + buffer[offset - 1] = this.maskKey[3] + + buffer[1] = payloadLength + + if (payloadLength === 126) { + buffer.writeUInt16BE(bodyLength, 2) + } else if (payloadLength === 127) { + // Clear extended payload length + buffer[2] = buffer[3] = 0 + buffer.writeUIntBE(bodyLength, 4, 6) + } + + buffer[1] |= 0x80 // MASK + + // mask body + for (let i = 0; i < bodyLength; i++) { + buffer[offset + i] = this.frameData[i] ^ this.maskKey[i % 4] + } + + return buffer + } +} + +module.exports = { + WebsocketFrameSend +} + + +/***/ }), + +/***/ 43171: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { Writable } = __nccwpck_require__(2203) +const diagnosticsChannel = __nccwpck_require__(31637) +const { parserStates, opcodes, states, emptyBuffer } = __nccwpck_require__(45913) +const { kReadyState, kSentClose, kResponse, kReceivedClose } = __nccwpck_require__(62933) +const { isValidStatusCode, failWebsocketConnection, websocketMessageReceived } = __nccwpck_require__(3574) +const { WebsocketFrameSend } = __nccwpck_require__(31237) + +// This code was influenced by ws released under the MIT license. +// Copyright (c) 2011 Einar Otto Stangvik +// Copyright (c) 2013 Arnout Kazemier and contributors +// Copyright (c) 2016 Luigi Pinca and contributors + +const channels = {} +channels.ping = diagnosticsChannel.channel('undici:websocket:ping') +channels.pong = diagnosticsChannel.channel('undici:websocket:pong') + +class ByteParser extends Writable { + #buffers = [] + #byteOffset = 0 + + #state = parserStates.INFO + + #info = {} + #fragments = [] + + constructor (ws) { + super() + + this.ws = ws + } + + /** + * @param {Buffer} chunk + * @param {() => void} callback + */ + _write (chunk, _, callback) { + this.#buffers.push(chunk) + this.#byteOffset += chunk.length + + this.run(callback) + } + + /** + * Runs whenever a new chunk is received. + * Callback is called whenever there are no more chunks buffering, + * or not enough bytes are buffered to parse. + */ + run (callback) { + while (true) { + if (this.#state === parserStates.INFO) { + // If there aren't enough bytes to parse the payload length, etc. + if (this.#byteOffset < 2) { + return callback() + } + + const buffer = this.consume(2) + + this.#info.fin = (buffer[0] & 0x80) !== 0 + this.#info.opcode = buffer[0] & 0x0F + + // If we receive a fragmented message, we use the type of the first + // frame to parse the full message as binary/text, when it's terminated + this.#info.originalOpcode ??= this.#info.opcode + + this.#info.fragmented = !this.#info.fin && this.#info.opcode !== opcodes.CONTINUATION + + if (this.#info.fragmented && this.#info.opcode !== opcodes.BINARY && this.#info.opcode !== opcodes.TEXT) { + // Only text and binary frames can be fragmented + failWebsocketConnection(this.ws, 'Invalid frame type was fragmented.') + return + } + + const payloadLength = buffer[1] & 0x7F + + if (payloadLength <= 125) { + this.#info.payloadLength = payloadLength + this.#state = parserStates.READ_DATA + } else if (payloadLength === 126) { + this.#state = parserStates.PAYLOADLENGTH_16 + } else if (payloadLength === 127) { + this.#state = parserStates.PAYLOADLENGTH_64 + } + + if (this.#info.fragmented && payloadLength > 125) { + // A fragmented frame can't be fragmented itself + failWebsocketConnection(this.ws, 'Fragmented frame exceeded 125 bytes.') + return + } else if ( + (this.#info.opcode === opcodes.PING || + this.#info.opcode === opcodes.PONG || + this.#info.opcode === opcodes.CLOSE) && + payloadLength > 125 + ) { + // Control frames can have a payload length of 125 bytes MAX + failWebsocketConnection(this.ws, 'Payload length for control frame exceeded 125 bytes.') + return + } else if (this.#info.opcode === opcodes.CLOSE) { + if (payloadLength === 1) { + failWebsocketConnection(this.ws, 'Received close frame with a 1-byte body.') + return + } + + const body = this.consume(payloadLength) + + this.#info.closeInfo = this.parseCloseBody(false, body) + + if (!this.ws[kSentClose]) { + // If an endpoint receives a Close frame and did not previously send a + // Close frame, the endpoint MUST send a Close frame in response. (When + // sending a Close frame in response, the endpoint typically echos the + // status code it received.) + const body = Buffer.allocUnsafe(2) + body.writeUInt16BE(this.#info.closeInfo.code, 0) + const closeFrame = new WebsocketFrameSend(body) + + this.ws[kResponse].socket.write( + closeFrame.createFrame(opcodes.CLOSE), + (err) => { + if (!err) { + this.ws[kSentClose] = true + } + } + ) + } + + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this.ws[kReadyState] = states.CLOSING + this.ws[kReceivedClose] = true + + this.end() + + return + } else if (this.#info.opcode === opcodes.PING) { + // Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in + // response, unless it already received a Close frame. + // A Pong frame sent in response to a Ping frame must have identical + // "Application data" + + const body = this.consume(payloadLength) + + if (!this.ws[kReceivedClose]) { + const frame = new WebsocketFrameSend(body) + + this.ws[kResponse].socket.write(frame.createFrame(opcodes.PONG)) + + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body + }) + } + } + + this.#state = parserStates.INFO + + if (this.#byteOffset > 0) { + continue + } else { + callback() + return + } + } else if (this.#info.opcode === opcodes.PONG) { + // A Pong frame MAY be sent unsolicited. This serves as a + // unidirectional heartbeat. A response to an unsolicited Pong frame is + // not expected. + + const body = this.consume(payloadLength) + + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body + }) + } + + if (this.#byteOffset > 0) { + continue + } else { + callback() + return + } + } + } else if (this.#state === parserStates.PAYLOADLENGTH_16) { + if (this.#byteOffset < 2) { + return callback() + } + + const buffer = this.consume(2) + + this.#info.payloadLength = buffer.readUInt16BE(0) + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.PAYLOADLENGTH_64) { + if (this.#byteOffset < 8) { + return callback() + } + + const buffer = this.consume(8) + const upper = buffer.readUInt32BE(0) + + // 2^31 is the maxinimum bytes an arraybuffer can contain + // on 32-bit systems. Although, on 64-bit systems, this is + // 2^53-1 bytes. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_array_length + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/common/globals.h;drc=1946212ac0100668f14eb9e2843bdd846e510a1e;bpv=1;bpt=1;l=1275 + // https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/js-array-buffer.h;l=34;drc=1946212ac0100668f14eb9e2843bdd846e510a1e + if (upper > 2 ** 31 - 1) { + failWebsocketConnection(this.ws, 'Received payload length > 2^31 bytes.') + return + } + + const lower = buffer.readUInt32BE(4) + + this.#info.payloadLength = (upper << 8) + lower + this.#state = parserStates.READ_DATA + } else if (this.#state === parserStates.READ_DATA) { + if (this.#byteOffset < this.#info.payloadLength) { + // If there is still more data in this chunk that needs to be read + return callback() + } else if (this.#byteOffset >= this.#info.payloadLength) { + // If the server sent multiple frames in a single chunk + + const body = this.consume(this.#info.payloadLength) + + this.#fragments.push(body) + + // If the frame is unfragmented, or a fragmented frame was terminated, + // a message was received + if (!this.#info.fragmented || (this.#info.fin && this.#info.opcode === opcodes.CONTINUATION)) { + const fullMessage = Buffer.concat(this.#fragments) + + websocketMessageReceived(this.ws, this.#info.originalOpcode, fullMessage) + + this.#info = {} + this.#fragments.length = 0 + } + + this.#state = parserStates.INFO + } + } + + if (this.#byteOffset > 0) { + continue + } else { + callback() + break + } + } + } + + /** + * Take n bytes from the buffered Buffers + * @param {number} n + * @returns {Buffer|null} + */ + consume (n) { + if (n > this.#byteOffset) { + return null + } else if (n === 0) { + return emptyBuffer + } + + if (this.#buffers[0].length === n) { + this.#byteOffset -= this.#buffers[0].length + return this.#buffers.shift() + } + + const buffer = Buffer.allocUnsafe(n) + let offset = 0 + + while (offset !== n) { + const next = this.#buffers[0] + const { length } = next + + if (length + offset === n) { + buffer.set(this.#buffers.shift(), offset) + break + } else if (length + offset > n) { + buffer.set(next.subarray(0, n - offset), offset) + this.#buffers[0] = next.subarray(n - offset) + break + } else { + buffer.set(this.#buffers.shift(), offset) + offset += next.length + } + } + + this.#byteOffset -= n + + return buffer + } + + parseCloseBody (onlyCode, data) { + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.5 + /** @type {number|undefined} */ + let code + + if (data.length >= 2) { + // _The WebSocket Connection Close Code_ is + // defined as the status code (Section 7.4) contained in the first Close + // control frame received by the application + code = data.readUInt16BE(0) + } + + if (onlyCode) { + if (!isValidStatusCode(code)) { + return null + } + + return { code } + } + + // https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.6 + /** @type {Buffer} */ + let reason = data.subarray(2) + + // Remove BOM + if (reason[0] === 0xEF && reason[1] === 0xBB && reason[2] === 0xBF) { + reason = reason.subarray(3) + } + + if (code !== undefined && !isValidStatusCode(code)) { + return null + } + + try { + // TODO: optimize this + reason = new TextDecoder('utf-8', { fatal: true }).decode(reason) + } catch { + return null + } + + return { code, reason } + } + + get closingInfo () { + return this.#info.closeInfo + } +} + +module.exports = { + ByteParser +} + + +/***/ }), + +/***/ 62933: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + kWebSocketURL: Symbol('url'), + kReadyState: Symbol('ready state'), + kController: Symbol('controller'), + kResponse: Symbol('response'), + kBinaryType: Symbol('binary type'), + kSentClose: Symbol('sent close'), + kReceivedClose: Symbol('received close'), + kByteParser: Symbol('byte parser') +} + + +/***/ }), + +/***/ 3574: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { kReadyState, kController, kResponse, kBinaryType, kWebSocketURL } = __nccwpck_require__(62933) +const { states, opcodes } = __nccwpck_require__(45913) +const { MessageEvent, ErrorEvent } = __nccwpck_require__(46255) + +/* globals Blob */ + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isEstablished (ws) { + // If the server's response is validated as provided for above, it is + // said that _The WebSocket Connection is Established_ and that the + // WebSocket Connection is in the OPEN state. + return ws[kReadyState] === states.OPEN +} + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isClosing (ws) { + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + return ws[kReadyState] === states.CLOSING +} + +/** + * @param {import('./websocket').WebSocket} ws + */ +function isClosed (ws) { + return ws[kReadyState] === states.CLOSED +} + +/** + * @see https://dom.spec.whatwg.org/#concept-event-fire + * @param {string} e + * @param {EventTarget} target + * @param {EventInit | undefined} eventInitDict + */ +function fireEvent (e, target, eventConstructor = Event, eventInitDict) { + // 1. If eventConstructor is not given, then let eventConstructor be Event. + + // 2. Let event be the result of creating an event given eventConstructor, + // in the relevant realm of target. + // 3. Initialize event’s type attribute to e. + const event = new eventConstructor(e, eventInitDict) // eslint-disable-line new-cap + + // 4. Initialize any other IDL attributes of event as described in the + // invocation of this algorithm. + + // 5. Return the result of dispatching event at target, with legacy target + // override flag set if set. + target.dispatchEvent(event) +} + +/** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @param {import('./websocket').WebSocket} ws + * @param {number} type Opcode + * @param {Buffer} data application data + */ +function websocketMessageReceived (ws, type, data) { + // 1. If ready state is not OPEN (1), then return. + if (ws[kReadyState] !== states.OPEN) { + return + } + + // 2. Let dataForEvent be determined by switching on type and binary type: + let dataForEvent + + if (type === opcodes.TEXT) { + // -> type indicates that the data is Text + // a new DOMString containing data + try { + dataForEvent = new TextDecoder('utf-8', { fatal: true }).decode(data) + } catch { + failWebsocketConnection(ws, 'Received invalid UTF-8 in text frame.') + return + } + } else if (type === opcodes.BINARY) { + if (ws[kBinaryType] === 'blob') { + // -> type indicates that the data is Binary and binary type is "blob" + // a new Blob object, created in the relevant Realm of the WebSocket + // object, that represents data as its raw data + dataForEvent = new Blob([data]) + } else { + // -> type indicates that the data is Binary and binary type is "arraybuffer" + // a new ArrayBuffer object, created in the relevant Realm of the + // WebSocket object, whose contents are data + dataForEvent = new Uint8Array(data).buffer + } + } + + // 3. Fire an event named message at the WebSocket object, using MessageEvent, + // with the origin attribute initialized to the serialization of the WebSocket + // object’s url's origin, and the data attribute initialized to dataForEvent. + fireEvent('message', ws, MessageEvent, { + origin: ws[kWebSocketURL].origin, + data: dataForEvent + }) +} + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455 + * @see https://datatracker.ietf.org/doc/html/rfc2616 + * @see https://bugs.chromium.org/p/chromium/issues/detail?id=398407 + * @param {string} protocol + */ +function isValidSubprotocol (protocol) { + // If present, this value indicates one + // or more comma-separated subprotocol the client wishes to speak, + // ordered by preference. The elements that comprise this value + // MUST be non-empty strings with characters in the range U+0021 to + // U+007E not including separator characters as defined in + // [RFC2616] and MUST all be unique strings. + if (protocol.length === 0) { + return false + } + + for (const char of protocol) { + const code = char.charCodeAt(0) + + if ( + code < 0x21 || + code > 0x7E || + char === '(' || + char === ')' || + char === '<' || + char === '>' || + char === '@' || + char === ',' || + char === ';' || + char === ':' || + char === '\\' || + char === '"' || + char === '/' || + char === '[' || + char === ']' || + char === '?' || + char === '=' || + char === '{' || + char === '}' || + code === 32 || // SP + code === 9 // HT + ) { + return false + } + } + + return true +} + +/** + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7-4 + * @param {number} code + */ +function isValidStatusCode (code) { + if (code >= 1000 && code < 1015) { + return ( + code !== 1004 && // reserved + code !== 1005 && // "MUST NOT be set as a status code" + code !== 1006 // "MUST NOT be set as a status code" + ) + } + + return code >= 3000 && code <= 4999 +} + +/** + * @param {import('./websocket').WebSocket} ws + * @param {string|undefined} reason + */ +function failWebsocketConnection (ws, reason) { + const { [kController]: controller, [kResponse]: response } = ws + + controller.abort() + + if (response?.socket && !response.socket.destroyed) { + response.socket.destroy() + } + + if (reason) { + fireEvent('error', ws, ErrorEvent, { + error: new Error(reason) + }) + } +} + +module.exports = { + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + failWebsocketConnection, + websocketMessageReceived +} + + +/***/ }), + +/***/ 55171: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const { webidl } = __nccwpck_require__(74222) +const { DOMException } = __nccwpck_require__(87326) +const { URLSerializer } = __nccwpck_require__(94322) +const { getGlobalOrigin } = __nccwpck_require__(75628) +const { staticPropertyDescriptors, states, opcodes, emptyBuffer } = __nccwpck_require__(45913) +const { + kWebSocketURL, + kReadyState, + kController, + kBinaryType, + kResponse, + kSentClose, + kByteParser +} = __nccwpck_require__(62933) +const { isEstablished, isClosing, isValidSubprotocol, failWebsocketConnection, fireEvent } = __nccwpck_require__(3574) +const { establishWebSocketConnection } = __nccwpck_require__(68550) +const { WebsocketFrameSend } = __nccwpck_require__(31237) +const { ByteParser } = __nccwpck_require__(43171) +const { kEnumerableProperty, isBlobLike } = __nccwpck_require__(3440) +const { getGlobalDispatcher } = __nccwpck_require__(32581) +const { types } = __nccwpck_require__(39023) + +let experimentalWarned = false + +// https://websockets.spec.whatwg.org/#interface-definition +class WebSocket extends EventTarget { + #events = { + open: null, + error: null, + close: null, + message: null + } + + #bufferedAmount = 0 + #protocol = '' + #extensions = '' + + /** + * @param {string} url + * @param {string|string[]} protocols + */ + constructor (url, protocols = []) { + super() + + webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket constructor' }) + + if (!experimentalWarned) { + experimentalWarned = true + process.emitWarning('WebSockets are experimental, expect them to change at any time.', { + code: 'UNDICI-WS' + }) + } + + const options = webidl.converters['DOMString or sequence or WebSocketInit'](protocols) + + url = webidl.converters.USVString(url) + protocols = options.protocols + + // 1. Let baseURL be this's relevant settings object's API base URL. + const baseURL = getGlobalOrigin() + + // 1. Let urlRecord be the result of applying the URL parser to url with baseURL. + let urlRecord + + try { + urlRecord = new URL(url, baseURL) + } catch (e) { + // 3. If urlRecord is failure, then throw a "SyntaxError" DOMException. + throw new DOMException(e, 'SyntaxError') + } + + // 4. If urlRecord’s scheme is "http", then set urlRecord’s scheme to "ws". + if (urlRecord.protocol === 'http:') { + urlRecord.protocol = 'ws:' + } else if (urlRecord.protocol === 'https:') { + // 5. Otherwise, if urlRecord’s scheme is "https", set urlRecord’s scheme to "wss". + urlRecord.protocol = 'wss:' + } + + // 6. If urlRecord’s scheme is not "ws" or "wss", then throw a "SyntaxError" DOMException. + if (urlRecord.protocol !== 'ws:' && urlRecord.protocol !== 'wss:') { + throw new DOMException( + `Expected a ws: or wss: protocol, got ${urlRecord.protocol}`, + 'SyntaxError' + ) + } + + // 7. If urlRecord’s fragment is non-null, then throw a "SyntaxError" + // DOMException. + if (urlRecord.hash || urlRecord.href.endsWith('#')) { + throw new DOMException('Got fragment', 'SyntaxError') + } + + // 8. If protocols is a string, set protocols to a sequence consisting + // of just that string. + if (typeof protocols === 'string') { + protocols = [protocols] + } + + // 9. If any of the values in protocols occur more than once or otherwise + // fail to match the requirements for elements that comprise the value + // of `Sec-WebSocket-Protocol` fields as defined by The WebSocket + // protocol, then throw a "SyntaxError" DOMException. + if (protocols.length !== new Set(protocols.map(p => p.toLowerCase())).size) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } + + if (protocols.length > 0 && !protocols.every(p => isValidSubprotocol(p))) { + throw new DOMException('Invalid Sec-WebSocket-Protocol value', 'SyntaxError') + } + + // 10. Set this's url to urlRecord. + this[kWebSocketURL] = new URL(urlRecord.href) + + // 11. Let client be this's relevant settings object. + + // 12. Run this step in parallel: + + // 1. Establish a WebSocket connection given urlRecord, protocols, + // and client. + this[kController] = establishWebSocketConnection( + urlRecord, + protocols, + this, + (response) => this.#onConnectionEstablished(response), + options + ) + + // Each WebSocket object has an associated ready state, which is a + // number representing the state of the connection. Initially it must + // be CONNECTING (0). + this[kReadyState] = WebSocket.CONNECTING + + // The extensions attribute must initially return the empty string. + + // The protocol attribute must initially return the empty string. + + // Each WebSocket object has an associated binary type, which is a + // BinaryType. Initially it must be "blob". + this[kBinaryType] = 'blob' + } + + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-close + * @param {number|undefined} code + * @param {string|undefined} reason + */ + close (code = undefined, reason = undefined) { + webidl.brandCheck(this, WebSocket) + + if (code !== undefined) { + code = webidl.converters['unsigned short'](code, { clamp: true }) + } + + if (reason !== undefined) { + reason = webidl.converters.USVString(reason) + } + + // 1. If code is present, but is neither an integer equal to 1000 nor an + // integer in the range 3000 to 4999, inclusive, throw an + // "InvalidAccessError" DOMException. + if (code !== undefined) { + if (code !== 1000 && (code < 3000 || code > 4999)) { + throw new DOMException('invalid code', 'InvalidAccessError') + } + } + + let reasonByteLength = 0 + + // 2. If reason is present, then run these substeps: + if (reason !== undefined) { + // 1. Let reasonBytes be the result of encoding reason. + // 2. If reasonBytes is longer than 123 bytes, then throw a + // "SyntaxError" DOMException. + reasonByteLength = Buffer.byteLength(reason) + + if (reasonByteLength > 123) { + throw new DOMException( + `Reason must be less than 123 bytes; received ${reasonByteLength}`, + 'SyntaxError' + ) + } + } + + // 3. Run the first matching steps from the following list: + if (this[kReadyState] === WebSocket.CLOSING || this[kReadyState] === WebSocket.CLOSED) { + // If this's ready state is CLOSING (2) or CLOSED (3) + // Do nothing. + } else if (!isEstablished(this)) { + // If the WebSocket connection is not yet established + // Fail the WebSocket connection and set this's ready state + // to CLOSING (2). + failWebsocketConnection(this, 'Connection was closed before it was established.') + this[kReadyState] = WebSocket.CLOSING + } else if (!isClosing(this)) { + // If the WebSocket closing handshake has not yet been started + // Start the WebSocket closing handshake and set this's ready + // state to CLOSING (2). + // - If neither code nor reason is present, the WebSocket Close + // message must not have a body. + // - If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + // - If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + + const frame = new WebsocketFrameSend() + + // If neither code nor reason is present, the WebSocket Close + // message must not have a body. + + // If code is present, then the status code to use in the + // WebSocket Close message must be the integer given by code. + if (code !== undefined && reason === undefined) { + frame.frameData = Buffer.allocUnsafe(2) + frame.frameData.writeUInt16BE(code, 0) + } else if (code !== undefined && reason !== undefined) { + // If reason is also present, then reasonBytes must be + // provided in the Close message after the status code. + frame.frameData = Buffer.allocUnsafe(2 + reasonByteLength) + frame.frameData.writeUInt16BE(code, 0) + // the body MAY contain UTF-8-encoded data with value /reason/ + frame.frameData.write(reason, 2, 'utf-8') + } else { + frame.frameData = emptyBuffer + } + + /** @type {import('stream').Duplex} */ + const socket = this[kResponse].socket + + socket.write(frame.createFrame(opcodes.CLOSE), (err) => { + if (!err) { + this[kSentClose] = true + } + }) + + // Upon either sending or receiving a Close control frame, it is said + // that _The WebSocket Closing Handshake is Started_ and that the + // WebSocket connection is in the CLOSING state. + this[kReadyState] = states.CLOSING + } else { + // Otherwise + // Set this's ready state to CLOSING (2). + this[kReadyState] = WebSocket.CLOSING + } + } + + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-send + * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + */ + send (data) { + webidl.brandCheck(this, WebSocket) + + webidl.argumentLengthCheck(arguments, 1, { header: 'WebSocket.send' }) + + data = webidl.converters.WebSocketSendData(data) + + // 1. If this's ready state is CONNECTING, then throw an + // "InvalidStateError" DOMException. + if (this[kReadyState] === WebSocket.CONNECTING) { + throw new DOMException('Sent before connected.', 'InvalidStateError') + } + + // 2. Run the appropriate set of steps from the following list: + // https://datatracker.ietf.org/doc/html/rfc6455#section-6.1 + // https://datatracker.ietf.org/doc/html/rfc6455#section-5.2 + + if (!isEstablished(this) || isClosing(this)) { + return + } + + /** @type {import('stream').Duplex} */ + const socket = this[kResponse].socket + + // If data is a string + if (typeof data === 'string') { + // If the WebSocket connection is established and the WebSocket + // closing handshake has not yet started, then the user agent + // must send a WebSocket Message comprised of the data argument + // using a text frame opcode; if the data cannot be sent, e.g. + // because it would need to be buffered but the buffer is full, + // the user agent must flag the WebSocket as full and then close + // the WebSocket connection. Any invocation of this method with a + // string argument that does not throw an exception must increase + // the bufferedAmount attribute by the number of bytes needed to + // express the argument as UTF-8. + + const value = Buffer.from(data) + const frame = new WebsocketFrameSend(value) + const buffer = frame.createFrame(opcodes.TEXT) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + } else if (types.isArrayBuffer(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need + // to be buffered but the buffer is full, the user agent must flag + // the WebSocket as full and then close the WebSocket connection. + // The data to be sent is the data stored in the buffer described + // by the ArrayBuffer object. Any invocation of this method with an + // ArrayBuffer argument that does not throw an exception must + // increase the bufferedAmount attribute by the length of the + // ArrayBuffer in bytes. + + const value = Buffer.from(data) + const frame = new WebsocketFrameSend(value) + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + } else if (ArrayBuffer.isView(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The + // data to be sent is the data stored in the section of the buffer + // described by the ArrayBuffer object that data references. Any + // invocation of this method with this kind of argument that does + // not throw an exception must increase the bufferedAmount attribute + // by the length of data’s buffer in bytes. + + const ab = Buffer.from(data, data.byteOffset, data.byteLength) + + const frame = new WebsocketFrameSend(ab) + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += ab.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= ab.byteLength + }) + } else if (isBlobLike(data)) { + // If the WebSocket connection is established, and the WebSocket + // closing handshake has not yet started, then the user agent must + // send a WebSocket Message comprised of data using a binary frame + // opcode; if the data cannot be sent, e.g. because it would need to + // be buffered but the buffer is full, the user agent must flag the + // WebSocket as full and then close the WebSocket connection. The data + // to be sent is the raw data represented by the Blob object. Any + // invocation of this method with a Blob argument that does not throw + // an exception must increase the bufferedAmount attribute by the size + // of the Blob object’s raw data, in bytes. + + const frame = new WebsocketFrameSend() + + data.arrayBuffer().then((ab) => { + const value = Buffer.from(ab) + frame.frameData = value + const buffer = frame.createFrame(opcodes.BINARY) + + this.#bufferedAmount += value.byteLength + socket.write(buffer, () => { + this.#bufferedAmount -= value.byteLength + }) + }) + } + } + + get readyState () { + webidl.brandCheck(this, WebSocket) + + // The readyState getter steps are to return this's ready state. + return this[kReadyState] + } + + get bufferedAmount () { + webidl.brandCheck(this, WebSocket) + + return this.#bufferedAmount + } + + get url () { + webidl.brandCheck(this, WebSocket) + + // The url getter steps are to return this's url, serialized. + return URLSerializer(this[kWebSocketURL]) + } + + get extensions () { + webidl.brandCheck(this, WebSocket) + + return this.#extensions + } + + get protocol () { + webidl.brandCheck(this, WebSocket) + + return this.#protocol + } + + get onopen () { + webidl.brandCheck(this, WebSocket) + + return this.#events.open + } + + set onopen (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.open) { + this.removeEventListener('open', this.#events.open) + } + + if (typeof fn === 'function') { + this.#events.open = fn + this.addEventListener('open', fn) + } else { + this.#events.open = null + } + } + + get onerror () { + webidl.brandCheck(this, WebSocket) + + return this.#events.error + } + + set onerror (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.error) { + this.removeEventListener('error', this.#events.error) + } + + if (typeof fn === 'function') { + this.#events.error = fn + this.addEventListener('error', fn) + } else { + this.#events.error = null + } + } + + get onclose () { + webidl.brandCheck(this, WebSocket) + + return this.#events.close + } + + set onclose (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.close) { + this.removeEventListener('close', this.#events.close) + } + + if (typeof fn === 'function') { + this.#events.close = fn + this.addEventListener('close', fn) + } else { + this.#events.close = null + } + } + + get onmessage () { + webidl.brandCheck(this, WebSocket) + + return this.#events.message + } + + set onmessage (fn) { + webidl.brandCheck(this, WebSocket) + + if (this.#events.message) { + this.removeEventListener('message', this.#events.message) + } + + if (typeof fn === 'function') { + this.#events.message = fn + this.addEventListener('message', fn) + } else { + this.#events.message = null + } + } + + get binaryType () { + webidl.brandCheck(this, WebSocket) + + return this[kBinaryType] + } + + set binaryType (type) { + webidl.brandCheck(this, WebSocket) + + if (type !== 'blob' && type !== 'arraybuffer') { + this[kBinaryType] = 'blob' + } else { + this[kBinaryType] = type + } + } + + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + */ + #onConnectionEstablished (response) { + // processResponse is called when the "response’s header list has been received and initialized." + // once this happens, the connection is open + this[kResponse] = response + + const parser = new ByteParser(this) + parser.on('drain', function onParserDrain () { + this.ws[kResponse].socket.resume() + }) + + response.socket.ws = this + this[kByteParser] = parser + + // 1. Change the ready state to OPEN (1). + this[kReadyState] = states.OPEN + + // 2. Change the extensions attribute’s value to the extensions in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-9.1 + const extensions = response.headersList.get('sec-websocket-extensions') + + if (extensions !== null) { + this.#extensions = extensions + } + + // 3. Change the protocol attribute’s value to the subprotocol in use, if + // it is not the null value. + // https://datatracker.ietf.org/doc/html/rfc6455#section-1.9 + const protocol = response.headersList.get('sec-websocket-protocol') + + if (protocol !== null) { + this.#protocol = protocol + } + + // 4. Fire an event named open at the WebSocket object. + fireEvent('open', this) + } +} + +// https://websockets.spec.whatwg.org/#dom-websocket-connecting +WebSocket.CONNECTING = WebSocket.prototype.CONNECTING = states.CONNECTING +// https://websockets.spec.whatwg.org/#dom-websocket-open +WebSocket.OPEN = WebSocket.prototype.OPEN = states.OPEN +// https://websockets.spec.whatwg.org/#dom-websocket-closing +WebSocket.CLOSING = WebSocket.prototype.CLOSING = states.CLOSING +// https://websockets.spec.whatwg.org/#dom-websocket-closed +WebSocket.CLOSED = WebSocket.prototype.CLOSED = states.CLOSED + +Object.defineProperties(WebSocket.prototype, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors, + url: kEnumerableProperty, + readyState: kEnumerableProperty, + bufferedAmount: kEnumerableProperty, + onopen: kEnumerableProperty, + onerror: kEnumerableProperty, + onclose: kEnumerableProperty, + close: kEnumerableProperty, + onmessage: kEnumerableProperty, + binaryType: kEnumerableProperty, + send: kEnumerableProperty, + extensions: kEnumerableProperty, + protocol: kEnumerableProperty, + [Symbol.toStringTag]: { + value: 'WebSocket', + writable: false, + enumerable: false, + configurable: true + } +}) + +Object.defineProperties(WebSocket, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors +}) + +webidl.converters['sequence'] = webidl.sequenceConverter( + webidl.converters.DOMString +) + +webidl.converters['DOMString or sequence'] = function (V) { + if (webidl.util.Type(V) === 'Object' && Symbol.iterator in V) { + return webidl.converters['sequence'](V) + } + + return webidl.converters.DOMString(V) +} + +// This implements the propsal made in https://github.com/whatwg/websockets/issues/42 +webidl.converters.WebSocketInit = webidl.dictionaryConverter([ + { + key: 'protocols', + converter: webidl.converters['DOMString or sequence'], + get defaultValue () { + return [] + } + }, + { + key: 'dispatcher', + converter: (V) => V, + get defaultValue () { + return getGlobalDispatcher() + } + }, + { + key: 'headers', + converter: webidl.nullableConverter(webidl.converters.HeadersInit) + } +]) + +webidl.converters['DOMString or sequence or WebSocketInit'] = function (V) { + if (webidl.util.Type(V) === 'Object' && !(Symbol.iterator in V)) { + return webidl.converters.WebSocketInit(V) + } + + return { protocols: webidl.converters['DOMString or sequence'](V) } +} + +webidl.converters.WebSocketSendData = function (V) { + if (webidl.util.Type(V) === 'Object') { + if (isBlobLike(V)) { + return webidl.converters.Blob(V, { strict: false }) + } + + if (ArrayBuffer.isView(V) || types.isAnyArrayBuffer(V)) { + return webidl.converters.BufferSource(V) + } + } + + return webidl.converters.USVString(V) +} + +module.exports = { + WebSocket +} + + +/***/ }), + +/***/ 24488: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + + +/** + * For Node.js, simply re-export the core `util.deprecate` function. + */ + +module.exports = __nccwpck_require__(39023).deprecate; + + +/***/ }), + +/***/ 12048: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(6415)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(51697)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(4676)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(69771)); + +var _nil = _interopRequireDefault(__nccwpck_require__(37723)); + +var _version = _interopRequireDefault(__nccwpck_require__(15868)); + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(37597)); + +var _parse = _interopRequireDefault(__nccwpck_require__(17267)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 10216: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 54221: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var _default = { + randomUUID: _crypto.default.randomUUID +}; +exports["default"] = _default; + +/***/ }), + +/***/ 37723: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 17267: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 67879: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 12973: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 507: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(76982)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 37597: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +exports.unsafeStringify = unsafeStringify; + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).slice(1)); +} + +function unsafeStringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]; +} + +function stringify(arr, offset = 0) { + const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 6415: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(12973)); + +var _stringify = __nccwpck_require__(37597); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.unsafeStringify)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 51697: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(92930)); + +var _md = _interopRequireDefault(__nccwpck_require__(10216)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 92930: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports.URL = exports.DNS = void 0; +exports["default"] = v35; + +var _stringify = __nccwpck_require__(37597); + +var _parse = _interopRequireDefault(__nccwpck_require__(17267)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function v35(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + var _namespace; + + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (((_namespace = namespace) === null || _namespace === void 0 ? void 0 : _namespace.length) !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.unsafeStringify)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 4676: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _native = _interopRequireDefault(__nccwpck_require__(54221)); + +var _rng = _interopRequireDefault(__nccwpck_require__(12973)); + +var _stringify = __nccwpck_require__(37597); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + if (_native.default.randomUUID && !buf && !options) { + return _native.default.randomUUID(); + } + + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.unsafeStringify)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 69771: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(92930)); + +var _sha = _interopRequireDefault(__nccwpck_require__(507)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 36200: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(67879)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 15868: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(36200)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.slice(14, 15), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 37125: +/***/ ((module) => { + +"use strict"; + + +var conversions = {}; +module.exports = conversions; + +function sign(x) { + return x < 0 ? -1 : 1; +} + +function evenRound(x) { + // Round x to the nearest integer, choosing the even integer if it lies halfway between two. + if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor) + return Math.floor(x); + } else { + return Math.round(x); + } +} + +function createNumberConversion(bitLength, typeOpts) { + if (!typeOpts.unsigned) { + --bitLength; + } + const lowerBound = typeOpts.unsigned ? 0 : -Math.pow(2, bitLength); + const upperBound = Math.pow(2, bitLength) - 1; + + const moduloVal = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength) : Math.pow(2, bitLength); + const moduloBound = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength - 1) : Math.pow(2, bitLength - 1); + + return function(V, opts) { + if (!opts) opts = {}; + + let x = +V; + + if (opts.enforceRange) { + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite number"); + } + + x = sign(x) * Math.floor(Math.abs(x)); + if (x < lowerBound || x > upperBound) { + throw new TypeError("Argument is not in byte range"); + } + + return x; + } + + if (!isNaN(x) && opts.clamp) { + x = evenRound(x); + + if (x < lowerBound) x = lowerBound; + if (x > upperBound) x = upperBound; + return x; + } + + if (!Number.isFinite(x) || x === 0) { + return 0; + } + + x = sign(x) * Math.floor(Math.abs(x)); + x = x % moduloVal; + + if (!typeOpts.unsigned && x >= moduloBound) { + return x - moduloVal; + } else if (typeOpts.unsigned) { + if (x < 0) { + x += moduloVal; + } else if (x === -0) { // don't return negative zero + return 0; + } + } + + return x; + } +} + +conversions["void"] = function () { + return undefined; +}; + +conversions["boolean"] = function (val) { + return !!val; +}; + +conversions["byte"] = createNumberConversion(8, { unsigned: false }); +conversions["octet"] = createNumberConversion(8, { unsigned: true }); + +conversions["short"] = createNumberConversion(16, { unsigned: false }); +conversions["unsigned short"] = createNumberConversion(16, { unsigned: true }); + +conversions["long"] = createNumberConversion(32, { unsigned: false }); +conversions["unsigned long"] = createNumberConversion(32, { unsigned: true }); + +conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 }); +conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 }); + +conversions["double"] = function (V) { + const x = +V; + + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite floating-point value"); + } + + return x; +}; + +conversions["unrestricted double"] = function (V) { + const x = +V; + + if (isNaN(x)) { + throw new TypeError("Argument is NaN"); + } + + return x; +}; + +// not quite valid, but good enough for JS +conversions["float"] = conversions["double"]; +conversions["unrestricted float"] = conversions["unrestricted double"]; + +conversions["DOMString"] = function (V, opts) { + if (!opts) opts = {}; + + if (opts.treatNullAsEmptyString && V === null) { + return ""; + } + + return String(V); +}; + +conversions["ByteString"] = function (V, opts) { + const x = String(V); + let c = undefined; + for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) { + if (c > 255) { + throw new TypeError("Argument is not a valid bytestring"); + } + } + + return x; +}; + +conversions["USVString"] = function (V) { + const S = String(V); + const n = S.length; + const U = []; + for (let i = 0; i < n; ++i) { + const c = S.charCodeAt(i); + if (c < 0xD800 || c > 0xDFFF) { + U.push(String.fromCodePoint(c)); + } else if (0xDC00 <= c && c <= 0xDFFF) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + if (i === n - 1) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + const d = S.charCodeAt(i + 1); + if (0xDC00 <= d && d <= 0xDFFF) { + const a = c & 0x3FF; + const b = d & 0x3FF; + U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b)); + ++i; + } else { + U.push(String.fromCodePoint(0xFFFD)); + } + } + } + } + + return U.join(''); +}; + +conversions["Date"] = function (V, opts) { + if (!(V instanceof Date)) { + throw new TypeError("Argument is not a Date object"); + } + if (isNaN(V)) { + return undefined; + } + + return V; +}; + +conversions["RegExp"] = function (V, opts) { + if (!(V instanceof RegExp)) { + V = new RegExp(V); + } + + return V; +}; + + +/***/ }), + +/***/ 23184: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +const usm = __nccwpck_require__(20905); + +exports.implementation = class URLImpl { + constructor(constructorArgs) { + const url = constructorArgs[0]; + const base = constructorArgs[1]; + + let parsedBase = null; + if (base !== undefined) { + parsedBase = usm.basicURLParse(base); + if (parsedBase === "failure") { + throw new TypeError("Invalid base URL"); + } + } + + const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase }); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + + // TODO: query stuff + } + + get href() { + return usm.serializeURL(this._url); + } + + set href(v) { + const parsedURL = usm.basicURLParse(v); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + } + + get origin() { + return usm.serializeURLOrigin(this._url); + } + + get protocol() { + return this._url.scheme + ":"; + } + + set protocol(v) { + usm.basicURLParse(v + ":", { url: this._url, stateOverride: "scheme start" }); + } + + get username() { + return this._url.username; + } + + set username(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setTheUsername(this._url, v); + } + + get password() { + return this._url.password; + } + + set password(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setThePassword(this._url, v); + } + + get host() { + const url = this._url; + + if (url.host === null) { + return ""; + } + + if (url.port === null) { + return usm.serializeHost(url.host); + } + + return usm.serializeHost(url.host) + ":" + usm.serializeInteger(url.port); + } + + set host(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "host" }); + } + + get hostname() { + if (this._url.host === null) { + return ""; + } + + return usm.serializeHost(this._url.host); + } + + set hostname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "hostname" }); + } + + get port() { + if (this._url.port === null) { + return ""; + } + + return usm.serializeInteger(this._url.port); + } + + set port(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + if (v === "") { + this._url.port = null; + } else { + usm.basicURLParse(v, { url: this._url, stateOverride: "port" }); + } + } + + get pathname() { + if (this._url.cannotBeABaseURL) { + return this._url.path[0]; + } + + if (this._url.path.length === 0) { + return ""; + } + + return "/" + this._url.path.join("/"); + } + + set pathname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + this._url.path = []; + usm.basicURLParse(v, { url: this._url, stateOverride: "path start" }); + } + + get search() { + if (this._url.query === null || this._url.query === "") { + return ""; + } + + return "?" + this._url.query; + } + + set search(v) { + // TODO: query stuff + + const url = this._url; + + if (v === "") { + url.query = null; + return; + } + + const input = v[0] === "?" ? v.substring(1) : v; + url.query = ""; + usm.basicURLParse(input, { url, stateOverride: "query" }); + } + + get hash() { + if (this._url.fragment === null || this._url.fragment === "") { + return ""; + } + + return "#" + this._url.fragment; + } + + set hash(v) { + if (v === "") { + this._url.fragment = null; + return; + } + + const input = v[0] === "#" ? v.substring(1) : v; + this._url.fragment = ""; + usm.basicURLParse(input, { url: this._url, stateOverride: "fragment" }); + } + + toJSON() { + return this.href; + } +}; + + +/***/ }), + +/***/ 66633: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const conversions = __nccwpck_require__(37125); +const utils = __nccwpck_require__(39857); +const Impl = __nccwpck_require__(23184); + +const impl = utils.implSymbol; + +function URL(url) { + if (!this || this[impl] || !(this instanceof URL)) { + throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function."); + } + if (arguments.length < 1) { + throw new TypeError("Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present."); + } + const args = []; + for (let i = 0; i < arguments.length && i < 2; ++i) { + args[i] = arguments[i]; + } + args[0] = conversions["USVString"](args[0]); + if (args[1] !== undefined) { + args[1] = conversions["USVString"](args[1]); + } + + module.exports.setup(this, args); +} + +URL.prototype.toJSON = function toJSON() { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + const args = []; + for (let i = 0; i < arguments.length && i < 0; ++i) { + args[i] = arguments[i]; + } + return this[impl].toJSON.apply(this[impl], args); +}; +Object.defineProperty(URL.prototype, "href", { + get() { + return this[impl].href; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].href = V; + }, + enumerable: true, + configurable: true +}); + +URL.prototype.toString = function () { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + return this.href; +}; + +Object.defineProperty(URL.prototype, "origin", { + get() { + return this[impl].origin; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "protocol", { + get() { + return this[impl].protocol; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].protocol = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "username", { + get() { + return this[impl].username; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].username = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "password", { + get() { + return this[impl].password; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].password = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "host", { + get() { + return this[impl].host; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].host = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hostname", { + get() { + return this[impl].hostname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hostname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "port", { + get() { + return this[impl].port; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].port = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "pathname", { + get() { + return this[impl].pathname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].pathname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "search", { + get() { + return this[impl].search; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].search = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hash", { + get() { + return this[impl].hash; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hash = V; + }, + enumerable: true, + configurable: true +}); + + +module.exports = { + is(obj) { + return !!obj && obj[impl] instanceof Impl.implementation; + }, + create(constructorArgs, privateData) { + let obj = Object.create(URL.prototype); + this.setup(obj, constructorArgs, privateData); + return obj; + }, + setup(obj, constructorArgs, privateData) { + if (!privateData) privateData = {}; + privateData.wrapper = obj; + + obj[impl] = new Impl.implementation(constructorArgs, privateData); + obj[impl][utils.wrapperSymbol] = obj; + }, + interface: URL, + expose: { + Window: { URL: URL }, + Worker: { URL: URL } + } +}; + + + +/***/ }), + +/***/ 62686: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +exports.URL = __nccwpck_require__(66633)["interface"]; +exports.serializeURL = __nccwpck_require__(20905).serializeURL; +exports.serializeURLOrigin = __nccwpck_require__(20905).serializeURLOrigin; +exports.basicURLParse = __nccwpck_require__(20905).basicURLParse; +exports.setTheUsername = __nccwpck_require__(20905).setTheUsername; +exports.setThePassword = __nccwpck_require__(20905).setThePassword; +exports.serializeHost = __nccwpck_require__(20905).serializeHost; +exports.serializeInteger = __nccwpck_require__(20905).serializeInteger; +exports.parseURL = __nccwpck_require__(20905).parseURL; + + +/***/ }), + +/***/ 20905: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const punycode = __nccwpck_require__(24876); +const tr46 = __nccwpck_require__(1552); + +const specialSchemes = { + ftp: 21, + file: null, + gopher: 70, + http: 80, + https: 443, + ws: 80, + wss: 443 +}; + +const failure = Symbol("failure"); + +function countSymbols(str) { + return punycode.ucs2.decode(str).length; +} + +function at(input, idx) { + const c = input[idx]; + return isNaN(c) ? undefined : String.fromCodePoint(c); +} + +function isASCIIDigit(c) { + return c >= 0x30 && c <= 0x39; +} + +function isASCIIAlpha(c) { + return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); +} + +function isASCIIAlphanumeric(c) { + return isASCIIAlpha(c) || isASCIIDigit(c); +} + +function isASCIIHex(c) { + return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); +} + +function isSingleDot(buffer) { + return buffer === "." || buffer.toLowerCase() === "%2e"; +} + +function isDoubleDot(buffer) { + buffer = buffer.toLowerCase(); + return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; +} + +function isWindowsDriveLetterCodePoints(cp1, cp2) { + return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124); +} + +function isWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|"); +} + +function isNormalizedWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":"; +} + +function containsForbiddenHostCodePoint(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function containsForbiddenHostCodePointExcludingPercent(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function isSpecialScheme(scheme) { + return specialSchemes[scheme] !== undefined; +} + +function isSpecial(url) { + return isSpecialScheme(url.scheme); +} + +function defaultPort(scheme) { + return specialSchemes[scheme]; +} + +function percentEncode(c) { + let hex = c.toString(16).toUpperCase(); + if (hex.length === 1) { + hex = "0" + hex; + } + + return "%" + hex; +} + +function utf8PercentEncode(c) { + const buf = new Buffer(c); + + let str = ""; + + for (let i = 0; i < buf.length; ++i) { + str += percentEncode(buf[i]); + } + + return str; +} + +function utf8PercentDecode(str) { + const input = new Buffer(str); + const output = []; + for (let i = 0; i < input.length; ++i) { + if (input[i] !== 37) { + output.push(input[i]); + } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { + output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); + i += 2; + } else { + output.push(input[i]); + } + } + return new Buffer(output).toString(); +} + +function isC0ControlPercentEncode(c) { + return c <= 0x1F || c > 0x7E; +} + +const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]); +function isPathPercentEncode(c) { + return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c); +} + +const extraUserinfoPercentEncodeSet = + new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]); +function isUserinfoPercentEncode(c) { + return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c); +} + +function percentEncodeChar(c, encodeSetPredicate) { + const cStr = String.fromCodePoint(c); + + if (encodeSetPredicate(c)) { + return utf8PercentEncode(cStr); + } + + return cStr; +} + +function parseIPv4Number(input) { + let R = 10; + + if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") { + input = input.substring(2); + R = 16; + } else if (input.length >= 2 && input.charAt(0) === "0") { + input = input.substring(1); + R = 8; + } + + if (input === "") { + return 0; + } + + const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/); + if (regex.test(input)) { + return failure; + } + + return parseInt(input, R); +} + +function parseIPv4(input) { + const parts = input.split("."); + if (parts[parts.length - 1] === "") { + if (parts.length > 1) { + parts.pop(); + } + } + + if (parts.length > 4) { + return input; + } + + const numbers = []; + for (const part of parts) { + if (part === "") { + return input; + } + const n = parseIPv4Number(part); + if (n === failure) { + return input; + } + + numbers.push(n); + } + + for (let i = 0; i < numbers.length - 1; ++i) { + if (numbers[i] > 255) { + return failure; + } + } + if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { + return failure; + } + + let ipv4 = numbers.pop(); + let counter = 0; + + for (const n of numbers) { + ipv4 += n * Math.pow(256, 3 - counter); + ++counter; + } + + return ipv4; +} + +function serializeIPv4(address) { + let output = ""; + let n = address; + + for (let i = 1; i <= 4; ++i) { + output = String(n % 256) + output; + if (i !== 4) { + output = "." + output; + } + n = Math.floor(n / 256); + } + + return output; +} + +function parseIPv6(input) { + const address = [0, 0, 0, 0, 0, 0, 0, 0]; + let pieceIndex = 0; + let compress = null; + let pointer = 0; + + input = punycode.ucs2.decode(input); + + if (input[pointer] === 58) { + if (input[pointer + 1] !== 58) { + return failure; + } + + pointer += 2; + ++pieceIndex; + compress = pieceIndex; + } + + while (pointer < input.length) { + if (pieceIndex === 8) { + return failure; + } + + if (input[pointer] === 58) { + if (compress !== null) { + return failure; + } + ++pointer; + ++pieceIndex; + compress = pieceIndex; + continue; + } + + let value = 0; + let length = 0; + + while (length < 4 && isASCIIHex(input[pointer])) { + value = value * 0x10 + parseInt(at(input, pointer), 16); + ++pointer; + ++length; + } + + if (input[pointer] === 46) { + if (length === 0) { + return failure; + } + + pointer -= length; + + if (pieceIndex > 6) { + return failure; + } + + let numbersSeen = 0; + + while (input[pointer] !== undefined) { + let ipv4Piece = null; + + if (numbersSeen > 0) { + if (input[pointer] === 46 && numbersSeen < 4) { + ++pointer; + } else { + return failure; + } + } + + if (!isASCIIDigit(input[pointer])) { + return failure; + } + + while (isASCIIDigit(input[pointer])) { + const number = parseInt(at(input, pointer)); + if (ipv4Piece === null) { + ipv4Piece = number; + } else if (ipv4Piece === 0) { + return failure; + } else { + ipv4Piece = ipv4Piece * 10 + number; + } + if (ipv4Piece > 255) { + return failure; + } + ++pointer; + } + + address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece; + + ++numbersSeen; + + if (numbersSeen === 2 || numbersSeen === 4) { + ++pieceIndex; + } + } + + if (numbersSeen !== 4) { + return failure; + } + + break; + } else if (input[pointer] === 58) { + ++pointer; + if (input[pointer] === undefined) { + return failure; + } + } else if (input[pointer] !== undefined) { + return failure; + } + + address[pieceIndex] = value; + ++pieceIndex; + } + + if (compress !== null) { + let swaps = pieceIndex - compress; + pieceIndex = 7; + while (pieceIndex !== 0 && swaps > 0) { + const temp = address[compress + swaps - 1]; + address[compress + swaps - 1] = address[pieceIndex]; + address[pieceIndex] = temp; + --pieceIndex; + --swaps; + } + } else if (compress === null && pieceIndex !== 8) { + return failure; + } + + return address; +} + +function serializeIPv6(address) { + let output = ""; + const seqResult = findLongestZeroSequence(address); + const compress = seqResult.idx; + let ignore0 = false; + + for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) { + if (ignore0 && address[pieceIndex] === 0) { + continue; + } else if (ignore0) { + ignore0 = false; + } + + if (compress === pieceIndex) { + const separator = pieceIndex === 0 ? "::" : ":"; + output += separator; + ignore0 = true; + continue; + } + + output += address[pieceIndex].toString(16); + + if (pieceIndex !== 7) { + output += ":"; + } + } + + return output; +} + +function parseHost(input, isSpecialArg) { + if (input[0] === "[") { + if (input[input.length - 1] !== "]") { + return failure; + } + + return parseIPv6(input.substring(1, input.length - 1)); + } + + if (!isSpecialArg) { + return parseOpaqueHost(input); + } + + const domain = utf8PercentDecode(input); + const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false); + if (asciiDomain === null) { + return failure; + } + + if (containsForbiddenHostCodePoint(asciiDomain)) { + return failure; + } + + const ipv4Host = parseIPv4(asciiDomain); + if (typeof ipv4Host === "number" || ipv4Host === failure) { + return ipv4Host; + } + + return asciiDomain; +} + +function parseOpaqueHost(input) { + if (containsForbiddenHostCodePointExcludingPercent(input)) { + return failure; + } + + let output = ""; + const decoded = punycode.ucs2.decode(input); + for (let i = 0; i < decoded.length; ++i) { + output += percentEncodeChar(decoded[i], isC0ControlPercentEncode); + } + return output; +} + +function findLongestZeroSequence(arr) { + let maxIdx = null; + let maxLen = 1; // only find elements > 1 + let currStart = null; + let currLen = 0; + + for (let i = 0; i < arr.length; ++i) { + if (arr[i] !== 0) { + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + currStart = null; + currLen = 0; + } else { + if (currStart === null) { + currStart = i; + } + ++currLen; + } + } + + // if trailing zeros + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + return { + idx: maxIdx, + len: maxLen + }; +} + +function serializeHost(host) { + if (typeof host === "number") { + return serializeIPv4(host); + } + + // IPv6 serializer + if (host instanceof Array) { + return "[" + serializeIPv6(host) + "]"; + } + + return host; +} + +function trimControlChars(url) { + return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, ""); +} + +function trimTabAndNewline(url) { + return url.replace(/\u0009|\u000A|\u000D/g, ""); +} + +function shortenPath(url) { + const path = url.path; + if (path.length === 0) { + return; + } + if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) { + return; + } + + path.pop(); +} + +function includesCredentials(url) { + return url.username !== "" || url.password !== ""; +} + +function cannotHaveAUsernamePasswordPort(url) { + return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file"; +} + +function isNormalizedWindowsDriveLetter(string) { + return /^[A-Za-z]:$/.test(string); +} + +function URLStateMachine(input, base, encodingOverride, url, stateOverride) { + this.pointer = 0; + this.input = input; + this.base = base || null; + this.encodingOverride = encodingOverride || "utf-8"; + this.stateOverride = stateOverride; + this.url = url; + this.failure = false; + this.parseError = false; + + if (!this.url) { + this.url = { + scheme: "", + username: "", + password: "", + host: null, + port: null, + path: [], + query: null, + fragment: null, + + cannotBeABaseURL: false + }; + + const res = trimControlChars(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + } + + const res = trimTabAndNewline(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + + this.state = stateOverride || "scheme start"; + + this.buffer = ""; + this.atFlag = false; + this.arrFlag = false; + this.passwordTokenSeenFlag = false; + + this.input = punycode.ucs2.decode(this.input); + + for (; this.pointer <= this.input.length; ++this.pointer) { + const c = this.input[this.pointer]; + const cStr = isNaN(c) ? undefined : String.fromCodePoint(c); + + // exec state machine + const ret = this["parse " + this.state](c, cStr); + if (!ret) { + break; // terminate algorithm + } else if (ret === failure) { + this.failure = true; + break; + } + } +} + +URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) { + if (isASCIIAlpha(c)) { + this.buffer += cStr.toLowerCase(); + this.state = "scheme"; + } else if (!this.stateOverride) { + this.state = "no scheme"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) { + if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) { + this.buffer += cStr.toLowerCase(); + } else if (c === 58) { + if (this.stateOverride) { + if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) { + return false; + } + + if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) { + return false; + } + + if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") { + return false; + } + + if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) { + return false; + } + } + this.url.scheme = this.buffer; + this.buffer = ""; + if (this.stateOverride) { + return false; + } + if (this.url.scheme === "file") { + if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) { + this.parseError = true; + } + this.state = "file"; + } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) { + this.state = "special relative or authority"; + } else if (isSpecial(this.url)) { + this.state = "special authority slashes"; + } else if (this.input[this.pointer + 1] === 47) { + this.state = "path or authority"; + ++this.pointer; + } else { + this.url.cannotBeABaseURL = true; + this.url.path.push(""); + this.state = "cannot-be-a-base-URL path"; + } + } else if (!this.stateOverride) { + this.buffer = ""; + this.state = "no scheme"; + this.pointer = -1; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) { + if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) { + return failure; + } else if (this.base.cannotBeABaseURL && c === 35) { + this.url.scheme = this.base.scheme; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.url.cannotBeABaseURL = true; + this.state = "fragment"; + } else if (this.base.scheme === "file") { + this.state = "file"; + --this.pointer; + } else { + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) { + if (c === 47) { + this.state = "authority"; + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative"] = function parseRelative(c) { + this.url.scheme = this.base.scheme; + if (isNaN(c)) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 47) { + this.state = "relative slash"; + } else if (c === 63) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else if (isSpecial(this.url) && c === 92) { + this.parseError = true; + this.state = "relative slash"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(0, this.base.path.length - 1); + + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) { + if (isSpecial(this.url) && (c === 47 || c === 92)) { + if (c === 92) { + this.parseError = true; + } + this.state = "special authority ignore slashes"; + } else if (c === 47) { + this.state = "authority"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "special authority ignore slashes"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) { + if (c !== 47 && c !== 92) { + this.state = "authority"; + --this.pointer; + } else { + this.parseError = true; + } + + return true; +}; + +URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) { + if (c === 64) { + this.parseError = true; + if (this.atFlag) { + this.buffer = "%40" + this.buffer; + } + this.atFlag = true; + + // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars + const len = countSymbols(this.buffer); + for (let pointer = 0; pointer < len; ++pointer) { + const codePoint = this.buffer.codePointAt(pointer); + + if (codePoint === 58 && !this.passwordTokenSeenFlag) { + this.passwordTokenSeenFlag = true; + continue; + } + const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode); + if (this.passwordTokenSeenFlag) { + this.url.password += encodedCodePoints; + } else { + this.url.username += encodedCodePoints; + } + } + this.buffer = ""; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + if (this.atFlag && this.buffer === "") { + this.parseError = true; + return failure; + } + this.pointer -= countSymbols(this.buffer) + 1; + this.buffer = ""; + this.state = "host"; + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse hostname"] = +URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { + if (this.stateOverride && this.url.scheme === "file") { + --this.pointer; + this.state = "file host"; + } else if (c === 58 && !this.arrFlag) { + if (this.buffer === "") { + this.parseError = true; + return failure; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "port"; + if (this.stateOverride === "hostname") { + return false; + } + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + --this.pointer; + if (isSpecial(this.url) && this.buffer === "") { + this.parseError = true; + return failure; + } else if (this.stateOverride && this.buffer === "" && + (includesCredentials(this.url) || this.url.port !== null)) { + this.parseError = true; + return false; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "path start"; + if (this.stateOverride) { + return false; + } + } else { + if (c === 91) { + this.arrFlag = true; + } else if (c === 93) { + this.arrFlag = false; + } + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) { + if (isASCIIDigit(c)) { + this.buffer += cStr; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92) || + this.stateOverride) { + if (this.buffer !== "") { + const port = parseInt(this.buffer); + if (port > Math.pow(2, 16) - 1) { + this.parseError = true; + return failure; + } + this.url.port = port === defaultPort(this.url.scheme) ? null : port; + this.buffer = ""; + } + if (this.stateOverride) { + return false; + } + this.state = "path start"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]); + +URLStateMachine.prototype["parse file"] = function parseFile(c) { + this.url.scheme = "file"; + + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file slash"; + } else if (this.base !== null && this.base.scheme === "file") { + if (isNaN(c)) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 63) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else { + if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points + !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) || + (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points + !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + shortenPath(this.url); + } else { + this.parseError = true; + } + + this.state = "path"; + --this.pointer; + } + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) { + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file host"; + } else { + if (this.base !== null && this.base.scheme === "file") { + if (isNormalizedWindowsDriveLetterString(this.base.path[0])) { + this.url.path.push(this.base.path[0]); + } else { + this.url.host = this.base.host; + } + } + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) { + if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { + --this.pointer; + if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) { + this.parseError = true; + this.state = "path"; + } else if (this.buffer === "") { + this.url.host = ""; + if (this.stateOverride) { + return false; + } + this.state = "path start"; + } else { + let host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + if (host === "localhost") { + host = ""; + } + this.url.host = host; + + if (this.stateOverride) { + return false; + } + + this.buffer = ""; + this.state = "path start"; + } + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse path start"] = function parsePathStart(c) { + if (isSpecial(this.url)) { + if (c === 92) { + this.parseError = true; + } + this.state = "path"; + + if (c !== 47 && c !== 92) { + --this.pointer; + } + } else if (!this.stateOverride && c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (!this.stateOverride && c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else if (c !== undefined) { + this.state = "path"; + if (c !== 47) { + --this.pointer; + } + } + + return true; +}; + +URLStateMachine.prototype["parse path"] = function parsePath(c) { + if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) || + (!this.stateOverride && (c === 63 || c === 35))) { + if (isSpecial(this.url) && c === 92) { + this.parseError = true; + } + + if (isDoubleDot(this.buffer)) { + shortenPath(this.url); + if (c !== 47 && !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } + } else if (isSingleDot(this.buffer) && c !== 47 && + !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } else if (!isSingleDot(this.buffer)) { + if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) { + if (this.url.host !== "" && this.url.host !== null) { + this.parseError = true; + this.url.host = ""; + } + this.buffer = this.buffer[0] + ":"; + } + this.url.path.push(this.buffer); + } + this.buffer = ""; + if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) { + while (this.url.path.length > 1 && this.url.path[0] === "") { + this.parseError = true; + this.url.path.shift(); + } + } + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += percentEncodeChar(c, isPathPercentEncode); + } + + return true; +}; + +URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) { + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else { + // TODO: Add: not a URL code point + if (!isNaN(c) && c !== 37) { + this.parseError = true; + } + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + if (!isNaN(c)) { + this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode); + } + } + + return true; +}; + +URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) { + if (isNaN(c) || (!this.stateOverride && c === 35)) { + if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") { + this.encodingOverride = "utf-8"; + } + + const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead + for (let i = 0; i < buffer.length; ++i) { + if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 || + buffer[i] === 0x3C || buffer[i] === 0x3E) { + this.url.query += percentEncode(buffer[i]); + } else { + this.url.query += String.fromCodePoint(buffer[i]); + } + } + + this.buffer = ""; + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse fragment"] = function parseFragment(c) { + if (isNaN(c)) { // do nothing + } else if (c === 0x0) { + this.parseError = true; + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode); + } + + return true; +}; + +function serializeURL(url, excludeFragment) { + let output = url.scheme + ":"; + if (url.host !== null) { + output += "//"; + + if (url.username !== "" || url.password !== "") { + output += url.username; + if (url.password !== "") { + output += ":" + url.password; + } + output += "@"; + } + + output += serializeHost(url.host); + + if (url.port !== null) { + output += ":" + url.port; + } + } else if (url.host === null && url.scheme === "file") { + output += "//"; + } + + if (url.cannotBeABaseURL) { + output += url.path[0]; + } else { + for (const string of url.path) { + output += "/" + string; + } + } + + if (url.query !== null) { + output += "?" + url.query; + } + + if (!excludeFragment && url.fragment !== null) { + output += "#" + url.fragment; + } + + return output; +} + +function serializeOrigin(tuple) { + let result = tuple.scheme + "://"; + result += serializeHost(tuple.host); + + if (tuple.port !== null) { + result += ":" + tuple.port; + } + + return result; +} + +module.exports.serializeURL = serializeURL; + +module.exports.serializeURLOrigin = function (url) { + // https://url.spec.whatwg.org/#concept-url-origin + switch (url.scheme) { + case "blob": + try { + return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0])); + } catch (e) { + // serializing an opaque origin returns "null" + return "null"; + } + case "ftp": + case "gopher": + case "http": + case "https": + case "ws": + case "wss": + return serializeOrigin({ + scheme: url.scheme, + host: url.host, + port: url.port + }); + case "file": + // spec says "exercise to the reader", chrome says "file://" + return "file://"; + default: + // serializing an opaque origin returns "null" + return "null"; + } +}; + +module.exports.basicURLParse = function (input, options) { + if (options === undefined) { + options = {}; + } + + const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride); + if (usm.failure) { + return "failure"; + } + + return usm.url; +}; + +module.exports.setTheUsername = function (url, username) { + url.username = ""; + const decoded = punycode.ucs2.decode(username); + for (let i = 0; i < decoded.length; ++i) { + url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.setThePassword = function (url, password) { + url.password = ""; + const decoded = punycode.ucs2.decode(password); + for (let i = 0; i < decoded.length; ++i) { + url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.serializeHost = serializeHost; + +module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort; + +module.exports.serializeInteger = function (integer) { + return String(integer); +}; + +module.exports.parseURL = function (input, options) { + if (options === undefined) { + options = {}; + } + + // We don't handle blobs, so this just delegates: + return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); +}; + + +/***/ }), + +/***/ 39857: +/***/ ((module) => { + +"use strict"; + + +module.exports.mixin = function mixin(target, source) { + const keys = Object.getOwnPropertyNames(source); + for (let i = 0; i < keys.length; ++i) { + Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i])); + } +}; + +module.exports.wrapperSymbol = Symbol("wrapper"); +module.exports.implSymbol = Symbol("impl"); + +module.exports.wrapperForImpl = function (impl) { + return impl[module.exports.wrapperSymbol]; +}; + +module.exports.implForWrapper = function (wrapper) { + return wrapper[module.exports.implSymbol]; +}; + + + +/***/ }), + +/***/ 58264: +/***/ ((module) => { + +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + + +/***/ }), + +/***/ 30538: +/***/ ((module) => { + +class Node { + /// value; + /// next; + + constructor(value) { + this.value = value; + + // TODO: Remove this when targeting Node.js 12. + this.next = undefined; + } +} + +class Queue { + // TODO: Use private class fields when targeting Node.js 12. + // #_head; + // #_tail; + // #_size; + + constructor() { + this.clear(); + } + + enqueue(value) { + const node = new Node(value); + + if (this._head) { + this._tail.next = node; + this._tail = node; + } else { + this._head = node; + this._tail = node; + } + + this._size++; + } + + dequeue() { + const current = this._head; + if (!current) { + return; + } + + this._head = this._head.next; + this._size--; + return current.value; + } + + clear() { + this._head = undefined; + this._tail = undefined; + this._size = 0; + } + + get size() { + return this._size; + } + + * [Symbol.iterator]() { + let current = this._head; + + while (current) { + yield current.value; + current = current.next; + } + } +} + +module.exports = Queue; + + +/***/ }), + +/***/ 42078: +/***/ ((module) => { + +module.exports = eval("require")("encoding"); + + +/***/ }), + +/***/ 60075: +/***/ ((module) => { + +module.exports = eval("require")("supports-color"); + + +/***/ }), + +/***/ 42613: +/***/ ((module) => { + +"use strict"; +module.exports = require("assert"); + +/***/ }), + +/***/ 90290: +/***/ ((module) => { + +"use strict"; +module.exports = require("async_hooks"); + +/***/ }), + +/***/ 20181: +/***/ ((module) => { + +"use strict"; +module.exports = require("buffer"); + +/***/ }), + +/***/ 35317: +/***/ ((module) => { + +"use strict"; +module.exports = require("child_process"); + +/***/ }), + +/***/ 64236: +/***/ ((module) => { + +"use strict"; +module.exports = require("console"); + +/***/ }), + +/***/ 76982: +/***/ ((module) => { + +"use strict"; +module.exports = require("crypto"); + +/***/ }), + +/***/ 31637: +/***/ ((module) => { + +"use strict"; +module.exports = require("diagnostics_channel"); + +/***/ }), + +/***/ 24434: +/***/ ((module) => { + +"use strict"; +module.exports = require("events"); + +/***/ }), + +/***/ 79896: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs"); + +/***/ }), + +/***/ 91943: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs/promises"); + +/***/ }), + +/***/ 58611: +/***/ ((module) => { + +"use strict"; +module.exports = require("http"); + +/***/ }), + +/***/ 85675: +/***/ ((module) => { + +"use strict"; +module.exports = require("http2"); + +/***/ }), + +/***/ 65692: +/***/ ((module) => { + +"use strict"; +module.exports = require("https"); + +/***/ }), + +/***/ 69278: +/***/ ((module) => { + +"use strict"; +module.exports = require("net"); + +/***/ }), + +/***/ 77598: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:crypto"); + +/***/ }), + +/***/ 78474: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:events"); + +/***/ }), + +/***/ 1708: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:process"); + +/***/ }), + +/***/ 57075: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:stream"); + +/***/ }), + +/***/ 57975: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:util"); + +/***/ }), + +/***/ 70857: +/***/ ((module) => { + +"use strict"; +module.exports = require("os"); + +/***/ }), + +/***/ 16928: +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ 82987: +/***/ ((module) => { + +"use strict"; +module.exports = require("perf_hooks"); + +/***/ }), + +/***/ 932: +/***/ ((module) => { + +"use strict"; +module.exports = require("process"); + +/***/ }), + +/***/ 24876: +/***/ ((module) => { + +"use strict"; +module.exports = require("punycode"); + +/***/ }), + +/***/ 83480: +/***/ ((module) => { + +"use strict"; +module.exports = require("querystring"); + +/***/ }), + +/***/ 2203: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream"); + +/***/ }), + +/***/ 63774: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream/web"); + +/***/ }), + +/***/ 13193: +/***/ ((module) => { + +"use strict"; +module.exports = require("string_decoder"); + +/***/ }), + +/***/ 53557: +/***/ ((module) => { + +"use strict"; +module.exports = require("timers"); + +/***/ }), + +/***/ 64756: +/***/ ((module) => { + +"use strict"; +module.exports = require("tls"); + +/***/ }), + +/***/ 52018: +/***/ ((module) => { + +"use strict"; +module.exports = require("tty"); + +/***/ }), + +/***/ 87016: +/***/ ((module) => { + +"use strict"; +module.exports = require("url"); + +/***/ }), + +/***/ 39023: +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }), + +/***/ 98253: +/***/ ((module) => { + +"use strict"; +module.exports = require("util/types"); + +/***/ }), + +/***/ 28167: +/***/ ((module) => { + +"use strict"; +module.exports = require("worker_threads"); + +/***/ }), + +/***/ 43106: +/***/ ((module) => { + +"use strict"; +module.exports = require("zlib"); + +/***/ }), + +/***/ 27182: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const WritableStream = (__nccwpck_require__(57075).Writable) +const inherits = (__nccwpck_require__(57975).inherits) + +const StreamSearch = __nccwpck_require__(84136) + +const PartStream = __nccwpck_require__(50612) +const HeaderParser = __nccwpck_require__(62271) + +const DASH = 45 +const B_ONEDASH = Buffer.from('-') +const B_CRLF = Buffer.from('\r\n') +const EMPTY_FN = function () {} + +function Dicer (cfg) { + if (!(this instanceof Dicer)) { return new Dicer(cfg) } + WritableStream.call(this, cfg) + + if (!cfg || (!cfg.headerFirst && typeof cfg.boundary !== 'string')) { throw new TypeError('Boundary required') } + + if (typeof cfg.boundary === 'string') { this.setBoundary(cfg.boundary) } else { this._bparser = undefined } + + this._headerFirst = cfg.headerFirst + + this._dashes = 0 + this._parts = 0 + this._finished = false + this._realFinish = false + this._isPreamble = true + this._justMatched = false + this._firstWrite = true + this._inHeader = true + this._part = undefined + this._cb = undefined + this._ignoreData = false + this._partOpts = { highWaterMark: cfg.partHwm } + this._pause = false + + const self = this + this._hparser = new HeaderParser(cfg) + this._hparser.on('header', function (header) { + self._inHeader = false + self._part.emit('header', header) + }) +} +inherits(Dicer, WritableStream) + +Dicer.prototype.emit = function (ev) { + if (ev === 'finish' && !this._realFinish) { + if (!this._finished) { + const self = this + process.nextTick(function () { + self.emit('error', new Error('Unexpected end of multipart data')) + if (self._part && !self._ignoreData) { + const type = (self._isPreamble ? 'Preamble' : 'Part') + self._part.emit('error', new Error(type + ' terminated early due to unexpected end of multipart data')) + self._part.push(null) + process.nextTick(function () { + self._realFinish = true + self.emit('finish') + self._realFinish = false + }) + return + } + self._realFinish = true + self.emit('finish') + self._realFinish = false + }) + } + } else { WritableStream.prototype.emit.apply(this, arguments) } +} + +Dicer.prototype._write = function (data, encoding, cb) { + // ignore unexpected data (e.g. extra trailer data after finished) + if (!this._hparser && !this._bparser) { return cb() } + + if (this._headerFirst && this._isPreamble) { + if (!this._part) { + this._part = new PartStream(this._partOpts) + if (this.listenerCount('preamble') !== 0) { this.emit('preamble', this._part) } else { this._ignore() } + } + const r = this._hparser.push(data) + if (!this._inHeader && r !== undefined && r < data.length) { data = data.slice(r) } else { return cb() } + } + + // allows for "easier" testing + if (this._firstWrite) { + this._bparser.push(B_CRLF) + this._firstWrite = false + } + + this._bparser.push(data) + + if (this._pause) { this._cb = cb } else { cb() } +} + +Dicer.prototype.reset = function () { + this._part = undefined + this._bparser = undefined + this._hparser = undefined +} + +Dicer.prototype.setBoundary = function (boundary) { + const self = this + this._bparser = new StreamSearch('\r\n--' + boundary) + this._bparser.on('info', function (isMatch, data, start, end) { + self._oninfo(isMatch, data, start, end) + }) +} + +Dicer.prototype._ignore = function () { + if (this._part && !this._ignoreData) { + this._ignoreData = true + this._part.on('error', EMPTY_FN) + // we must perform some kind of read on the stream even though we are + // ignoring the data, otherwise node's Readable stream will not emit 'end' + // after pushing null to the stream + this._part.resume() + } +} + +Dicer.prototype._oninfo = function (isMatch, data, start, end) { + let buf; const self = this; let i = 0; let r; let shouldWriteMore = true + + if (!this._part && this._justMatched && data) { + while (this._dashes < 2 && (start + i) < end) { + if (data[start + i] === DASH) { + ++i + ++this._dashes + } else { + if (this._dashes) { buf = B_ONEDASH } + this._dashes = 0 + break + } + } + if (this._dashes === 2) { + if ((start + i) < end && this.listenerCount('trailer') !== 0) { this.emit('trailer', data.slice(start + i, end)) } + this.reset() + this._finished = true + // no more parts will be added + if (self._parts === 0) { + self._realFinish = true + self.emit('finish') + self._realFinish = false + } + } + if (this._dashes) { return } + } + if (this._justMatched) { this._justMatched = false } + if (!this._part) { + this._part = new PartStream(this._partOpts) + this._part._read = function (n) { + self._unpause() + } + if (this._isPreamble && this.listenerCount('preamble') !== 0) { + this.emit('preamble', this._part) + } else if (this._isPreamble !== true && this.listenerCount('part') !== 0) { + this.emit('part', this._part) + } else { + this._ignore() + } + if (!this._isPreamble) { this._inHeader = true } + } + if (data && start < end && !this._ignoreData) { + if (this._isPreamble || !this._inHeader) { + if (buf) { shouldWriteMore = this._part.push(buf) } + shouldWriteMore = this._part.push(data.slice(start, end)) + if (!shouldWriteMore) { this._pause = true } + } else if (!this._isPreamble && this._inHeader) { + if (buf) { this._hparser.push(buf) } + r = this._hparser.push(data.slice(start, end)) + if (!this._inHeader && r !== undefined && r < end) { this._oninfo(false, data, start + r, end) } + } + } + if (isMatch) { + this._hparser.reset() + if (this._isPreamble) { this._isPreamble = false } else { + if (start !== end) { + ++this._parts + this._part.on('end', function () { + if (--self._parts === 0) { + if (self._finished) { + self._realFinish = true + self.emit('finish') + self._realFinish = false + } else { + self._unpause() + } + } + }) + } + } + this._part.push(null) + this._part = undefined + this._ignoreData = false + this._justMatched = true + this._dashes = 0 + } +} + +Dicer.prototype._unpause = function () { + if (!this._pause) { return } + + this._pause = false + if (this._cb) { + const cb = this._cb + this._cb = undefined + cb() + } +} + +module.exports = Dicer + + +/***/ }), + +/***/ 62271: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const EventEmitter = (__nccwpck_require__(78474).EventEmitter) +const inherits = (__nccwpck_require__(57975).inherits) +const getLimit = __nccwpck_require__(22393) + +const StreamSearch = __nccwpck_require__(84136) + +const B_DCRLF = Buffer.from('\r\n\r\n') +const RE_CRLF = /\r\n/g +const RE_HDR = /^([^:]+):[ \t]?([\x00-\xFF]+)?$/ // eslint-disable-line no-control-regex + +function HeaderParser (cfg) { + EventEmitter.call(this) + + cfg = cfg || {} + const self = this + this.nread = 0 + this.maxed = false + this.npairs = 0 + this.maxHeaderPairs = getLimit(cfg, 'maxHeaderPairs', 2000) + this.maxHeaderSize = getLimit(cfg, 'maxHeaderSize', 80 * 1024) + this.buffer = '' + this.header = {} + this.finished = false + this.ss = new StreamSearch(B_DCRLF) + this.ss.on('info', function (isMatch, data, start, end) { + if (data && !self.maxed) { + if (self.nread + end - start >= self.maxHeaderSize) { + end = self.maxHeaderSize - self.nread + start + self.nread = self.maxHeaderSize + self.maxed = true + } else { self.nread += (end - start) } + + self.buffer += data.toString('binary', start, end) + } + if (isMatch) { self._finish() } + }) +} +inherits(HeaderParser, EventEmitter) + +HeaderParser.prototype.push = function (data) { + const r = this.ss.push(data) + if (this.finished) { return r } +} + +HeaderParser.prototype.reset = function () { + this.finished = false + this.buffer = '' + this.header = {} + this.ss.reset() +} + +HeaderParser.prototype._finish = function () { + if (this.buffer) { this._parseHeader() } + this.ss.matches = this.ss.maxMatches + const header = this.header + this.header = {} + this.buffer = '' + this.finished = true + this.nread = this.npairs = 0 + this.maxed = false + this.emit('header', header) +} + +HeaderParser.prototype._parseHeader = function () { + if (this.npairs === this.maxHeaderPairs) { return } + + const lines = this.buffer.split(RE_CRLF) + const len = lines.length + let m, h + + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + if (lines[i].length === 0) { continue } + if (lines[i][0] === '\t' || lines[i][0] === ' ') { + // folded header content + // RFC2822 says to just remove the CRLF and not the whitespace following + // it, so we follow the RFC and include the leading whitespace ... + if (h) { + this.header[h][this.header[h].length - 1] += lines[i] + continue + } + } + + const posColon = lines[i].indexOf(':') + if ( + posColon === -1 || + posColon === 0 + ) { + return + } + m = RE_HDR.exec(lines[i]) + h = m[1].toLowerCase() + this.header[h] = this.header[h] || [] + this.header[h].push((m[2] || '')) + if (++this.npairs === this.maxHeaderPairs) { break } + } +} + +module.exports = HeaderParser + + +/***/ }), + +/***/ 50612: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const inherits = (__nccwpck_require__(57975).inherits) +const ReadableStream = (__nccwpck_require__(57075).Readable) + +function PartStream (opts) { + ReadableStream.call(this, opts) +} +inherits(PartStream, ReadableStream) + +PartStream.prototype._read = function (n) {} + +module.exports = PartStream + + +/***/ }), + +/***/ 84136: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +/** + * Copyright Brian White. All rights reserved. + * + * @see https://github.com/mscdex/streamsearch + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation + * by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool + */ +const EventEmitter = (__nccwpck_require__(78474).EventEmitter) +const inherits = (__nccwpck_require__(57975).inherits) + +function SBMH (needle) { + if (typeof needle === 'string') { + needle = Buffer.from(needle) + } + + if (!Buffer.isBuffer(needle)) { + throw new TypeError('The needle has to be a String or a Buffer.') + } + + const needleLength = needle.length + + if (needleLength === 0) { + throw new Error('The needle cannot be an empty String/Buffer.') + } + + if (needleLength > 256) { + throw new Error('The needle cannot have a length bigger than 256.') + } + + this.maxMatches = Infinity + this.matches = 0 + + this._occ = new Array(256) + .fill(needleLength) // Initialize occurrence table. + this._lookbehind_size = 0 + this._needle = needle + this._bufpos = 0 + + this._lookbehind = Buffer.alloc(needleLength) + + // Populate occurrence table with analysis of the needle, + // ignoring last letter. + for (var i = 0; i < needleLength - 1; ++i) { // eslint-disable-line no-var + this._occ[needle[i]] = needleLength - 1 - i + } +} +inherits(SBMH, EventEmitter) + +SBMH.prototype.reset = function () { + this._lookbehind_size = 0 + this.matches = 0 + this._bufpos = 0 +} + +SBMH.prototype.push = function (chunk, pos) { + if (!Buffer.isBuffer(chunk)) { + chunk = Buffer.from(chunk, 'binary') + } + const chlen = chunk.length + this._bufpos = pos || 0 + let r + while (r !== chlen && this.matches < this.maxMatches) { r = this._sbmh_feed(chunk) } + return r +} + +SBMH.prototype._sbmh_feed = function (data) { + const len = data.length + const needle = this._needle + const needleLength = needle.length + const lastNeedleChar = needle[needleLength - 1] + + // Positive: points to a position in `data` + // pos == 3 points to data[3] + // Negative: points to a position in the lookbehind buffer + // pos == -2 points to lookbehind[lookbehind_size - 2] + let pos = -this._lookbehind_size + let ch + + if (pos < 0) { + // Lookbehind buffer is not empty. Perform Boyer-Moore-Horspool + // search with character lookup code that considers both the + // lookbehind buffer and the current round's haystack data. + // + // Loop until + // there is a match. + // or until + // we've moved past the position that requires the + // lookbehind buffer. In this case we switch to the + // optimized loop. + // or until + // the character to look at lies outside the haystack. + while (pos < 0 && pos <= len - needleLength) { + ch = this._sbmh_lookup_char(data, pos + needleLength - 1) + + if ( + ch === lastNeedleChar && + this._sbmh_memcmp(data, pos, needleLength - 1) + ) { + this._lookbehind_size = 0 + ++this.matches + this.emit('info', true) + + return (this._bufpos = pos + needleLength) + } + pos += this._occ[ch] + } + + // No match. + + if (pos < 0) { + // There's too few data for Boyer-Moore-Horspool to run, + // so let's use a different algorithm to skip as much as + // we can. + // Forward pos until + // the trailing part of lookbehind + data + // looks like the beginning of the needle + // or until + // pos == 0 + while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) { ++pos } + } + + if (pos >= 0) { + // Discard lookbehind buffer. + this.emit('info', false, this._lookbehind, 0, this._lookbehind_size) + this._lookbehind_size = 0 + } else { + // Cut off part of the lookbehind buffer that has + // been processed and append the entire haystack + // into it. + const bytesToCutOff = this._lookbehind_size + pos + if (bytesToCutOff > 0) { + // The cut off data is guaranteed not to contain the needle. + this.emit('info', false, this._lookbehind, 0, bytesToCutOff) + } + + this._lookbehind.copy(this._lookbehind, 0, bytesToCutOff, + this._lookbehind_size - bytesToCutOff) + this._lookbehind_size -= bytesToCutOff + + data.copy(this._lookbehind, this._lookbehind_size) + this._lookbehind_size += len + + this._bufpos = len + return len + } + } + + pos += (pos >= 0) * this._bufpos + + // Lookbehind buffer is now empty. We only need to check if the + // needle is in the haystack. + if (data.indexOf(needle, pos) !== -1) { + pos = data.indexOf(needle, pos) + ++this.matches + if (pos > 0) { this.emit('info', true, data, this._bufpos, pos) } else { this.emit('info', true) } + + return (this._bufpos = pos + needleLength) + } else { + pos = len - needleLength + } + + // There was no match. If there's trailing haystack data that we cannot + // match yet using the Boyer-Moore-Horspool algorithm (because the trailing + // data is less than the needle size) then match using a modified + // algorithm that starts matching from the beginning instead of the end. + // Whatever trailing data is left after running this algorithm is added to + // the lookbehind buffer. + while ( + pos < len && + ( + data[pos] !== needle[0] || + ( + (Buffer.compare( + data.subarray(pos, pos + len - pos), + needle.subarray(0, len - pos) + ) !== 0) + ) + ) + ) { + ++pos + } + if (pos < len) { + data.copy(this._lookbehind, 0, pos, pos + (len - pos)) + this._lookbehind_size = len - pos + } + + // Everything until pos is guaranteed not to contain needle data. + if (pos > 0) { this.emit('info', false, data, this._bufpos, pos < len ? pos : len) } + + this._bufpos = len + return len +} + +SBMH.prototype._sbmh_lookup_char = function (data, pos) { + return (pos < 0) + ? this._lookbehind[this._lookbehind_size + pos] + : data[pos] +} + +SBMH.prototype._sbmh_memcmp = function (data, pos, len) { + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + if (this._sbmh_lookup_char(data, pos + i) !== this._needle[i]) { return false } + } + return true +} + +module.exports = SBMH + + +/***/ }), + +/***/ 89581: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const WritableStream = (__nccwpck_require__(57075).Writable) +const { inherits } = __nccwpck_require__(57975) +const Dicer = __nccwpck_require__(27182) + +const MultipartParser = __nccwpck_require__(41192) +const UrlencodedParser = __nccwpck_require__(80855) +const parseParams = __nccwpck_require__(8929) + +function Busboy (opts) { + if (!(this instanceof Busboy)) { return new Busboy(opts) } + + if (typeof opts !== 'object') { + throw new TypeError('Busboy expected an options-Object.') + } + if (typeof opts.headers !== 'object') { + throw new TypeError('Busboy expected an options-Object with headers-attribute.') + } + if (typeof opts.headers['content-type'] !== 'string') { + throw new TypeError('Missing Content-Type-header.') + } + + const { + headers, + ...streamOptions + } = opts + + this.opts = { + autoDestroy: false, + ...streamOptions + } + WritableStream.call(this, this.opts) + + this._done = false + this._parser = this.getParserByHeaders(headers) + this._finished = false +} +inherits(Busboy, WritableStream) + +Busboy.prototype.emit = function (ev) { + if (ev === 'finish') { + if (!this._done) { + this._parser?.end() + return + } else if (this._finished) { + return + } + this._finished = true + } + WritableStream.prototype.emit.apply(this, arguments) +} + +Busboy.prototype.getParserByHeaders = function (headers) { + const parsed = parseParams(headers['content-type']) + + const cfg = { + defCharset: this.opts.defCharset, + fileHwm: this.opts.fileHwm, + headers, + highWaterMark: this.opts.highWaterMark, + isPartAFile: this.opts.isPartAFile, + limits: this.opts.limits, + parsedConType: parsed, + preservePath: this.opts.preservePath + } + + if (MultipartParser.detect.test(parsed[0])) { + return new MultipartParser(this, cfg) + } + if (UrlencodedParser.detect.test(parsed[0])) { + return new UrlencodedParser(this, cfg) + } + throw new Error('Unsupported Content-Type.') +} + +Busboy.prototype._write = function (chunk, encoding, cb) { + this._parser.write(chunk, cb) +} + +module.exports = Busboy +module.exports["default"] = Busboy +module.exports.Busboy = Busboy + +module.exports.Dicer = Dicer + + +/***/ }), + +/***/ 41192: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +// TODO: +// * support 1 nested multipart level +// (see second multipart example here: +// http://www.w3.org/TR/html401/interact/forms.html#didx-multipartform-data) +// * support limits.fieldNameSize +// -- this will require modifications to utils.parseParams + +const { Readable } = __nccwpck_require__(57075) +const { inherits } = __nccwpck_require__(57975) + +const Dicer = __nccwpck_require__(27182) + +const parseParams = __nccwpck_require__(8929) +const decodeText = __nccwpck_require__(72747) +const basename = __nccwpck_require__(20692) +const getLimit = __nccwpck_require__(22393) + +const RE_BOUNDARY = /^boundary$/i +const RE_FIELD = /^form-data$/i +const RE_CHARSET = /^charset$/i +const RE_FILENAME = /^filename$/i +const RE_NAME = /^name$/i + +Multipart.detect = /^multipart\/form-data/i +function Multipart (boy, cfg) { + let i + let len + const self = this + let boundary + const limits = cfg.limits + const isPartAFile = cfg.isPartAFile || ((fieldName, contentType, fileName) => (contentType === 'application/octet-stream' || fileName !== undefined)) + const parsedConType = cfg.parsedConType || [] + const defCharset = cfg.defCharset || 'utf8' + const preservePath = cfg.preservePath + const fileOpts = { highWaterMark: cfg.fileHwm } + + for (i = 0, len = parsedConType.length; i < len; ++i) { + if (Array.isArray(parsedConType[i]) && + RE_BOUNDARY.test(parsedConType[i][0])) { + boundary = parsedConType[i][1] + break + } + } + + function checkFinished () { + if (nends === 0 && finished && !boy._done) { + finished = false + self.end() + } + } + + if (typeof boundary !== 'string') { throw new Error('Multipart: Boundary not found') } + + const fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) + const fileSizeLimit = getLimit(limits, 'fileSize', Infinity) + const filesLimit = getLimit(limits, 'files', Infinity) + const fieldsLimit = getLimit(limits, 'fields', Infinity) + const partsLimit = getLimit(limits, 'parts', Infinity) + const headerPairsLimit = getLimit(limits, 'headerPairs', 2000) + const headerSizeLimit = getLimit(limits, 'headerSize', 80 * 1024) + + let nfiles = 0 + let nfields = 0 + let nends = 0 + let curFile + let curField + let finished = false + + this._needDrain = false + this._pause = false + this._cb = undefined + this._nparts = 0 + this._boy = boy + + const parserCfg = { + boundary, + maxHeaderPairs: headerPairsLimit, + maxHeaderSize: headerSizeLimit, + partHwm: fileOpts.highWaterMark, + highWaterMark: cfg.highWaterMark + } + + this.parser = new Dicer(parserCfg) + this.parser.on('drain', function () { + self._needDrain = false + if (self._cb && !self._pause) { + const cb = self._cb + self._cb = undefined + cb() + } + }).on('part', function onPart (part) { + if (++self._nparts > partsLimit) { + self.parser.removeListener('part', onPart) + self.parser.on('part', skipPart) + boy.hitPartsLimit = true + boy.emit('partsLimit') + return skipPart(part) + } + + // hack because streams2 _always_ doesn't emit 'end' until nextTick, so let + // us emit 'end' early since we know the part has ended if we are already + // seeing the next part + if (curField) { + const field = curField + field.emit('end') + field.removeAllListeners('end') + } + + part.on('header', function (header) { + let contype + let fieldname + let parsed + let charset + let encoding + let filename + let nsize = 0 + + if (header['content-type']) { + parsed = parseParams(header['content-type'][0]) + if (parsed[0]) { + contype = parsed[0].toLowerCase() + for (i = 0, len = parsed.length; i < len; ++i) { + if (RE_CHARSET.test(parsed[i][0])) { + charset = parsed[i][1].toLowerCase() + break + } + } + } + } + + if (contype === undefined) { contype = 'text/plain' } + if (charset === undefined) { charset = defCharset } + + if (header['content-disposition']) { + parsed = parseParams(header['content-disposition'][0]) + if (!RE_FIELD.test(parsed[0])) { return skipPart(part) } + for (i = 0, len = parsed.length; i < len; ++i) { + if (RE_NAME.test(parsed[i][0])) { + fieldname = parsed[i][1] + } else if (RE_FILENAME.test(parsed[i][0])) { + filename = parsed[i][1] + if (!preservePath) { filename = basename(filename) } + } + } + } else { return skipPart(part) } + + if (header['content-transfer-encoding']) { encoding = header['content-transfer-encoding'][0].toLowerCase() } else { encoding = '7bit' } + + let onData, + onEnd + + if (isPartAFile(fieldname, contype, filename)) { + // file/binary field + if (nfiles === filesLimit) { + if (!boy.hitFilesLimit) { + boy.hitFilesLimit = true + boy.emit('filesLimit') + } + return skipPart(part) + } + + ++nfiles + + if (boy.listenerCount('file') === 0) { + self.parser._ignore() + return + } + + ++nends + const file = new FileStream(fileOpts) + curFile = file + file.on('end', function () { + --nends + self._pause = false + checkFinished() + if (self._cb && !self._needDrain) { + const cb = self._cb + self._cb = undefined + cb() + } + }) + file._read = function (n) { + if (!self._pause) { return } + self._pause = false + if (self._cb && !self._needDrain) { + const cb = self._cb + self._cb = undefined + cb() + } + } + boy.emit('file', fieldname, file, filename, encoding, contype) + + onData = function (data) { + if ((nsize += data.length) > fileSizeLimit) { + const extralen = fileSizeLimit - nsize + data.length + if (extralen > 0) { file.push(data.slice(0, extralen)) } + file.truncated = true + file.bytesRead = fileSizeLimit + part.removeAllListeners('data') + file.emit('limit') + return + } else if (!file.push(data)) { self._pause = true } + + file.bytesRead = nsize + } + + onEnd = function () { + curFile = undefined + file.push(null) + } + } else { + // non-file field + if (nfields === fieldsLimit) { + if (!boy.hitFieldsLimit) { + boy.hitFieldsLimit = true + boy.emit('fieldsLimit') + } + return skipPart(part) + } + + ++nfields + ++nends + let buffer = '' + let truncated = false + curField = part + + onData = function (data) { + if ((nsize += data.length) > fieldSizeLimit) { + const extralen = (fieldSizeLimit - (nsize - data.length)) + buffer += data.toString('binary', 0, extralen) + truncated = true + part.removeAllListeners('data') + } else { buffer += data.toString('binary') } + } + + onEnd = function () { + curField = undefined + if (buffer.length) { buffer = decodeText(buffer, 'binary', charset) } + boy.emit('field', fieldname, buffer, false, truncated, encoding, contype) + --nends + checkFinished() + } + } + + /* As of node@2efe4ab761666 (v0.10.29+/v0.11.14+), busboy had become + broken. Streams2/streams3 is a huge black box of confusion, but + somehow overriding the sync state seems to fix things again (and still + seems to work for previous node versions). + */ + part._readableState.sync = false + + part.on('data', onData) + part.on('end', onEnd) + }).on('error', function (err) { + if (curFile) { curFile.emit('error', err) } + }) + }).on('error', function (err) { + boy.emit('error', err) + }).on('finish', function () { + finished = true + checkFinished() + }) +} + +Multipart.prototype.write = function (chunk, cb) { + const r = this.parser.write(chunk) + if (r && !this._pause) { + cb() + } else { + this._needDrain = !r + this._cb = cb + } +} + +Multipart.prototype.end = function () { + const self = this + + if (self.parser.writable) { + self.parser.end() + } else if (!self._boy._done) { + process.nextTick(function () { + self._boy._done = true + self._boy.emit('finish') + }) + } +} + +function skipPart (part) { + part.resume() +} + +function FileStream (opts) { + Readable.call(this, opts) + + this.bytesRead = 0 + + this.truncated = false +} + +inherits(FileStream, Readable) + +FileStream.prototype._read = function (n) {} + +module.exports = Multipart + + +/***/ }), + +/***/ 80855: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const Decoder = __nccwpck_require__(11496) +const decodeText = __nccwpck_require__(72747) +const getLimit = __nccwpck_require__(22393) + +const RE_CHARSET = /^charset$/i + +UrlEncoded.detect = /^application\/x-www-form-urlencoded/i +function UrlEncoded (boy, cfg) { + const limits = cfg.limits + const parsedConType = cfg.parsedConType + this.boy = boy + + this.fieldSizeLimit = getLimit(limits, 'fieldSize', 1 * 1024 * 1024) + this.fieldNameSizeLimit = getLimit(limits, 'fieldNameSize', 100) + this.fieldsLimit = getLimit(limits, 'fields', Infinity) + + let charset + for (var i = 0, len = parsedConType.length; i < len; ++i) { // eslint-disable-line no-var + if (Array.isArray(parsedConType[i]) && + RE_CHARSET.test(parsedConType[i][0])) { + charset = parsedConType[i][1].toLowerCase() + break + } + } + + if (charset === undefined) { charset = cfg.defCharset || 'utf8' } + + this.decoder = new Decoder() + this.charset = charset + this._fields = 0 + this._state = 'key' + this._checkingBytes = true + this._bytesKey = 0 + this._bytesVal = 0 + this._key = '' + this._val = '' + this._keyTrunc = false + this._valTrunc = false + this._hitLimit = false +} + +UrlEncoded.prototype.write = function (data, cb) { + if (this._fields === this.fieldsLimit) { + if (!this.boy.hitFieldsLimit) { + this.boy.hitFieldsLimit = true + this.boy.emit('fieldsLimit') + } + return cb() + } + + let idxeq; let idxamp; let i; let p = 0; const len = data.length + + while (p < len) { + if (this._state === 'key') { + idxeq = idxamp = undefined + for (i = p; i < len; ++i) { + if (!this._checkingBytes) { ++p } + if (data[i] === 0x3D/* = */) { + idxeq = i + break + } else if (data[i] === 0x26/* & */) { + idxamp = i + break + } + if (this._checkingBytes && this._bytesKey === this.fieldNameSizeLimit) { + this._hitLimit = true + break + } else if (this._checkingBytes) { ++this._bytesKey } + } + + if (idxeq !== undefined) { + // key with assignment + if (idxeq > p) { this._key += this.decoder.write(data.toString('binary', p, idxeq)) } + this._state = 'val' + + this._hitLimit = false + this._checkingBytes = true + this._val = '' + this._bytesVal = 0 + this._valTrunc = false + this.decoder.reset() + + p = idxeq + 1 + } else if (idxamp !== undefined) { + // key with no assignment + ++this._fields + let key; const keyTrunc = this._keyTrunc + if (idxamp > p) { key = (this._key += this.decoder.write(data.toString('binary', p, idxamp))) } else { key = this._key } + + this._hitLimit = false + this._checkingBytes = true + this._key = '' + this._bytesKey = 0 + this._keyTrunc = false + this.decoder.reset() + + if (key.length) { + this.boy.emit('field', decodeText(key, 'binary', this.charset), + '', + keyTrunc, + false) + } + + p = idxamp + 1 + if (this._fields === this.fieldsLimit) { return cb() } + } else if (this._hitLimit) { + // we may not have hit the actual limit if there are encoded bytes... + if (i > p) { this._key += this.decoder.write(data.toString('binary', p, i)) } + p = i + if ((this._bytesKey = this._key.length) === this.fieldNameSizeLimit) { + // yep, we actually did hit the limit + this._checkingBytes = false + this._keyTrunc = true + } + } else { + if (p < len) { this._key += this.decoder.write(data.toString('binary', p)) } + p = len + } + } else { + idxamp = undefined + for (i = p; i < len; ++i) { + if (!this._checkingBytes) { ++p } + if (data[i] === 0x26/* & */) { + idxamp = i + break + } + if (this._checkingBytes && this._bytesVal === this.fieldSizeLimit) { + this._hitLimit = true + break + } else if (this._checkingBytes) { ++this._bytesVal } + } + + if (idxamp !== undefined) { + ++this._fields + if (idxamp > p) { this._val += this.decoder.write(data.toString('binary', p, idxamp)) } + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + decodeText(this._val, 'binary', this.charset), + this._keyTrunc, + this._valTrunc) + this._state = 'key' + + this._hitLimit = false + this._checkingBytes = true + this._key = '' + this._bytesKey = 0 + this._keyTrunc = false + this.decoder.reset() + + p = idxamp + 1 + if (this._fields === this.fieldsLimit) { return cb() } + } else if (this._hitLimit) { + // we may not have hit the actual limit if there are encoded bytes... + if (i > p) { this._val += this.decoder.write(data.toString('binary', p, i)) } + p = i + if ((this._val === '' && this.fieldSizeLimit === 0) || + (this._bytesVal = this._val.length) === this.fieldSizeLimit) { + // yep, we actually did hit the limit + this._checkingBytes = false + this._valTrunc = true + } + } else { + if (p < len) { this._val += this.decoder.write(data.toString('binary', p)) } + p = len + } + } + } + cb() +} + +UrlEncoded.prototype.end = function () { + if (this.boy._done) { return } + + if (this._state === 'key' && this._key.length > 0) { + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + '', + this._keyTrunc, + false) + } else if (this._state === 'val') { + this.boy.emit('field', decodeText(this._key, 'binary', this.charset), + decodeText(this._val, 'binary', this.charset), + this._keyTrunc, + this._valTrunc) + } + this.boy._done = true + this.boy.emit('finish') +} + +module.exports = UrlEncoded + + +/***/ }), + +/***/ 11496: +/***/ ((module) => { + +"use strict"; + + +const RE_PLUS = /\+/g + +const HEX = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +] + +function Decoder () { + this.buffer = undefined +} +Decoder.prototype.write = function (str) { + // Replace '+' with ' ' before decoding + str = str.replace(RE_PLUS, ' ') + let res = '' + let i = 0; let p = 0; const len = str.length + for (; i < len; ++i) { + if (this.buffer !== undefined) { + if (!HEX[str.charCodeAt(i)]) { + res += '%' + this.buffer + this.buffer = undefined + --i // retry character + } else { + this.buffer += str[i] + ++p + if (this.buffer.length === 2) { + res += String.fromCharCode(parseInt(this.buffer, 16)) + this.buffer = undefined + } + } + } else if (str[i] === '%') { + if (i > p) { + res += str.substring(p, i) + p = i + } + this.buffer = '' + ++p + } + } + if (p < len && this.buffer === undefined) { res += str.substring(p) } + return res +} +Decoder.prototype.reset = function () { + this.buffer = undefined +} + +module.exports = Decoder + + +/***/ }), + +/***/ 20692: +/***/ ((module) => { + +"use strict"; + + +module.exports = function basename (path) { + if (typeof path !== 'string') { return '' } + for (var i = path.length - 1; i >= 0; --i) { // eslint-disable-line no-var + switch (path.charCodeAt(i)) { + case 0x2F: // '/' + case 0x5C: // '\' + path = path.slice(i + 1) + return (path === '..' || path === '.' ? '' : path) + } + } + return (path === '..' || path === '.' ? '' : path) +} + + +/***/ }), + +/***/ 72747: +/***/ (function(module) { + +"use strict"; + + +// Node has always utf-8 +const utf8Decoder = new TextDecoder('utf-8') +const textDecoders = new Map([ + ['utf-8', utf8Decoder], + ['utf8', utf8Decoder] +]) + +function getDecoder (charset) { + let lc + while (true) { + switch (charset) { + case 'utf-8': + case 'utf8': + return decoders.utf8 + case 'latin1': + case 'ascii': // TODO: Make these a separate, strict decoder? + case 'us-ascii': + case 'iso-8859-1': + case 'iso8859-1': + case 'iso88591': + case 'iso_8859-1': + case 'windows-1252': + case 'iso_8859-1:1987': + case 'cp1252': + case 'x-cp1252': + return decoders.latin1 + case 'utf16le': + case 'utf-16le': + case 'ucs2': + case 'ucs-2': + return decoders.utf16le + case 'base64': + return decoders.base64 + default: + if (lc === undefined) { + lc = true + charset = charset.toLowerCase() + continue + } + return decoders.other.bind(charset) + } + } +} + +const decoders = { + utf8: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.utf8Slice(0, data.length) + }, + + latin1: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + return data + } + return data.latin1Slice(0, data.length) + }, + + utf16le: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.ucs2Slice(0, data.length) + }, + + base64: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + return data.base64Slice(0, data.length) + }, + + other: (data, sourceEncoding) => { + if (data.length === 0) { + return '' + } + if (typeof data === 'string') { + data = Buffer.from(data, sourceEncoding) + } + + if (textDecoders.has(this.toString())) { + try { + return textDecoders.get(this).decode(data) + } catch {} + } + return typeof data === 'string' + ? data + : data.toString() + } +} + +function decodeText (text, sourceEncoding, destEncoding) { + if (text) { + return getDecoder(destEncoding)(text, sourceEncoding) + } + return text +} + +module.exports = decodeText + + +/***/ }), + +/***/ 22393: +/***/ ((module) => { + +"use strict"; + + +module.exports = function getLimit (limits, name, defaultLimit) { + if ( + !limits || + limits[name] === undefined || + limits[name] === null + ) { return defaultLimit } + + if ( + typeof limits[name] !== 'number' || + isNaN(limits[name]) + ) { throw new TypeError('Limit ' + name + ' is not a valid number') } + + return limits[name] +} + + +/***/ }), + +/***/ 8929: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/* eslint-disable object-property-newline */ + + +const decodeText = __nccwpck_require__(72747) + +const RE_ENCODED = /%[a-fA-F0-9][a-fA-F0-9]/g + +const EncodedLookup = { + '%00': '\x00', '%01': '\x01', '%02': '\x02', '%03': '\x03', '%04': '\x04', + '%05': '\x05', '%06': '\x06', '%07': '\x07', '%08': '\x08', '%09': '\x09', + '%0a': '\x0a', '%0A': '\x0a', '%0b': '\x0b', '%0B': '\x0b', '%0c': '\x0c', + '%0C': '\x0c', '%0d': '\x0d', '%0D': '\x0d', '%0e': '\x0e', '%0E': '\x0e', + '%0f': '\x0f', '%0F': '\x0f', '%10': '\x10', '%11': '\x11', '%12': '\x12', + '%13': '\x13', '%14': '\x14', '%15': '\x15', '%16': '\x16', '%17': '\x17', + '%18': '\x18', '%19': '\x19', '%1a': '\x1a', '%1A': '\x1a', '%1b': '\x1b', + '%1B': '\x1b', '%1c': '\x1c', '%1C': '\x1c', '%1d': '\x1d', '%1D': '\x1d', + '%1e': '\x1e', '%1E': '\x1e', '%1f': '\x1f', '%1F': '\x1f', '%20': '\x20', + '%21': '\x21', '%22': '\x22', '%23': '\x23', '%24': '\x24', '%25': '\x25', + '%26': '\x26', '%27': '\x27', '%28': '\x28', '%29': '\x29', '%2a': '\x2a', + '%2A': '\x2a', '%2b': '\x2b', '%2B': '\x2b', '%2c': '\x2c', '%2C': '\x2c', + '%2d': '\x2d', '%2D': '\x2d', '%2e': '\x2e', '%2E': '\x2e', '%2f': '\x2f', + '%2F': '\x2f', '%30': '\x30', '%31': '\x31', '%32': '\x32', '%33': '\x33', + '%34': '\x34', '%35': '\x35', '%36': '\x36', '%37': '\x37', '%38': '\x38', + '%39': '\x39', '%3a': '\x3a', '%3A': '\x3a', '%3b': '\x3b', '%3B': '\x3b', + '%3c': '\x3c', '%3C': '\x3c', '%3d': '\x3d', '%3D': '\x3d', '%3e': '\x3e', + '%3E': '\x3e', '%3f': '\x3f', '%3F': '\x3f', '%40': '\x40', '%41': '\x41', + '%42': '\x42', '%43': '\x43', '%44': '\x44', '%45': '\x45', '%46': '\x46', + '%47': '\x47', '%48': '\x48', '%49': '\x49', '%4a': '\x4a', '%4A': '\x4a', + '%4b': '\x4b', '%4B': '\x4b', '%4c': '\x4c', '%4C': '\x4c', '%4d': '\x4d', + '%4D': '\x4d', '%4e': '\x4e', '%4E': '\x4e', '%4f': '\x4f', '%4F': '\x4f', + '%50': '\x50', '%51': '\x51', '%52': '\x52', '%53': '\x53', '%54': '\x54', + '%55': '\x55', '%56': '\x56', '%57': '\x57', '%58': '\x58', '%59': '\x59', + '%5a': '\x5a', '%5A': '\x5a', '%5b': '\x5b', '%5B': '\x5b', '%5c': '\x5c', + '%5C': '\x5c', '%5d': '\x5d', '%5D': '\x5d', '%5e': '\x5e', '%5E': '\x5e', + '%5f': '\x5f', '%5F': '\x5f', '%60': '\x60', '%61': '\x61', '%62': '\x62', + '%63': '\x63', '%64': '\x64', '%65': '\x65', '%66': '\x66', '%67': '\x67', + '%68': '\x68', '%69': '\x69', '%6a': '\x6a', '%6A': '\x6a', '%6b': '\x6b', + '%6B': '\x6b', '%6c': '\x6c', '%6C': '\x6c', '%6d': '\x6d', '%6D': '\x6d', + '%6e': '\x6e', '%6E': '\x6e', '%6f': '\x6f', '%6F': '\x6f', '%70': '\x70', + '%71': '\x71', '%72': '\x72', '%73': '\x73', '%74': '\x74', '%75': '\x75', + '%76': '\x76', '%77': '\x77', '%78': '\x78', '%79': '\x79', '%7a': '\x7a', + '%7A': '\x7a', '%7b': '\x7b', '%7B': '\x7b', '%7c': '\x7c', '%7C': '\x7c', + '%7d': '\x7d', '%7D': '\x7d', '%7e': '\x7e', '%7E': '\x7e', '%7f': '\x7f', + '%7F': '\x7f', '%80': '\x80', '%81': '\x81', '%82': '\x82', '%83': '\x83', + '%84': '\x84', '%85': '\x85', '%86': '\x86', '%87': '\x87', '%88': '\x88', + '%89': '\x89', '%8a': '\x8a', '%8A': '\x8a', '%8b': '\x8b', '%8B': '\x8b', + '%8c': '\x8c', '%8C': '\x8c', '%8d': '\x8d', '%8D': '\x8d', '%8e': '\x8e', + '%8E': '\x8e', '%8f': '\x8f', '%8F': '\x8f', '%90': '\x90', '%91': '\x91', + '%92': '\x92', '%93': '\x93', '%94': '\x94', '%95': '\x95', '%96': '\x96', + '%97': '\x97', '%98': '\x98', '%99': '\x99', '%9a': '\x9a', '%9A': '\x9a', + '%9b': '\x9b', '%9B': '\x9b', '%9c': '\x9c', '%9C': '\x9c', '%9d': '\x9d', + '%9D': '\x9d', '%9e': '\x9e', '%9E': '\x9e', '%9f': '\x9f', '%9F': '\x9f', + '%a0': '\xa0', '%A0': '\xa0', '%a1': '\xa1', '%A1': '\xa1', '%a2': '\xa2', + '%A2': '\xa2', '%a3': '\xa3', '%A3': '\xa3', '%a4': '\xa4', '%A4': '\xa4', + '%a5': '\xa5', '%A5': '\xa5', '%a6': '\xa6', '%A6': '\xa6', '%a7': '\xa7', + '%A7': '\xa7', '%a8': '\xa8', '%A8': '\xa8', '%a9': '\xa9', '%A9': '\xa9', + '%aa': '\xaa', '%Aa': '\xaa', '%aA': '\xaa', '%AA': '\xaa', '%ab': '\xab', + '%Ab': '\xab', '%aB': '\xab', '%AB': '\xab', '%ac': '\xac', '%Ac': '\xac', + '%aC': '\xac', '%AC': '\xac', '%ad': '\xad', '%Ad': '\xad', '%aD': '\xad', + '%AD': '\xad', '%ae': '\xae', '%Ae': '\xae', '%aE': '\xae', '%AE': '\xae', + '%af': '\xaf', '%Af': '\xaf', '%aF': '\xaf', '%AF': '\xaf', '%b0': '\xb0', + '%B0': '\xb0', '%b1': '\xb1', '%B1': '\xb1', '%b2': '\xb2', '%B2': '\xb2', + '%b3': '\xb3', '%B3': '\xb3', '%b4': '\xb4', '%B4': '\xb4', '%b5': '\xb5', + '%B5': '\xb5', '%b6': '\xb6', '%B6': '\xb6', '%b7': '\xb7', '%B7': '\xb7', + '%b8': '\xb8', '%B8': '\xb8', '%b9': '\xb9', '%B9': '\xb9', '%ba': '\xba', + '%Ba': '\xba', '%bA': '\xba', '%BA': '\xba', '%bb': '\xbb', '%Bb': '\xbb', + '%bB': '\xbb', '%BB': '\xbb', '%bc': '\xbc', '%Bc': '\xbc', '%bC': '\xbc', + '%BC': '\xbc', '%bd': '\xbd', '%Bd': '\xbd', '%bD': '\xbd', '%BD': '\xbd', + '%be': '\xbe', '%Be': '\xbe', '%bE': '\xbe', '%BE': '\xbe', '%bf': '\xbf', + '%Bf': '\xbf', '%bF': '\xbf', '%BF': '\xbf', '%c0': '\xc0', '%C0': '\xc0', + '%c1': '\xc1', '%C1': '\xc1', '%c2': '\xc2', '%C2': '\xc2', '%c3': '\xc3', + '%C3': '\xc3', '%c4': '\xc4', '%C4': '\xc4', '%c5': '\xc5', '%C5': '\xc5', + '%c6': '\xc6', '%C6': '\xc6', '%c7': '\xc7', '%C7': '\xc7', '%c8': '\xc8', + '%C8': '\xc8', '%c9': '\xc9', '%C9': '\xc9', '%ca': '\xca', '%Ca': '\xca', + '%cA': '\xca', '%CA': '\xca', '%cb': '\xcb', '%Cb': '\xcb', '%cB': '\xcb', + '%CB': '\xcb', '%cc': '\xcc', '%Cc': '\xcc', '%cC': '\xcc', '%CC': '\xcc', + '%cd': '\xcd', '%Cd': '\xcd', '%cD': '\xcd', '%CD': '\xcd', '%ce': '\xce', + '%Ce': '\xce', '%cE': '\xce', '%CE': '\xce', '%cf': '\xcf', '%Cf': '\xcf', + '%cF': '\xcf', '%CF': '\xcf', '%d0': '\xd0', '%D0': '\xd0', '%d1': '\xd1', + '%D1': '\xd1', '%d2': '\xd2', '%D2': '\xd2', '%d3': '\xd3', '%D3': '\xd3', + '%d4': '\xd4', '%D4': '\xd4', '%d5': '\xd5', '%D5': '\xd5', '%d6': '\xd6', + '%D6': '\xd6', '%d7': '\xd7', '%D7': '\xd7', '%d8': '\xd8', '%D8': '\xd8', + '%d9': '\xd9', '%D9': '\xd9', '%da': '\xda', '%Da': '\xda', '%dA': '\xda', + '%DA': '\xda', '%db': '\xdb', '%Db': '\xdb', '%dB': '\xdb', '%DB': '\xdb', + '%dc': '\xdc', '%Dc': '\xdc', '%dC': '\xdc', '%DC': '\xdc', '%dd': '\xdd', + '%Dd': '\xdd', '%dD': '\xdd', '%DD': '\xdd', '%de': '\xde', '%De': '\xde', + '%dE': '\xde', '%DE': '\xde', '%df': '\xdf', '%Df': '\xdf', '%dF': '\xdf', + '%DF': '\xdf', '%e0': '\xe0', '%E0': '\xe0', '%e1': '\xe1', '%E1': '\xe1', + '%e2': '\xe2', '%E2': '\xe2', '%e3': '\xe3', '%E3': '\xe3', '%e4': '\xe4', + '%E4': '\xe4', '%e5': '\xe5', '%E5': '\xe5', '%e6': '\xe6', '%E6': '\xe6', + '%e7': '\xe7', '%E7': '\xe7', '%e8': '\xe8', '%E8': '\xe8', '%e9': '\xe9', + '%E9': '\xe9', '%ea': '\xea', '%Ea': '\xea', '%eA': '\xea', '%EA': '\xea', + '%eb': '\xeb', '%Eb': '\xeb', '%eB': '\xeb', '%EB': '\xeb', '%ec': '\xec', + '%Ec': '\xec', '%eC': '\xec', '%EC': '\xec', '%ed': '\xed', '%Ed': '\xed', + '%eD': '\xed', '%ED': '\xed', '%ee': '\xee', '%Ee': '\xee', '%eE': '\xee', + '%EE': '\xee', '%ef': '\xef', '%Ef': '\xef', '%eF': '\xef', '%EF': '\xef', + '%f0': '\xf0', '%F0': '\xf0', '%f1': '\xf1', '%F1': '\xf1', '%f2': '\xf2', + '%F2': '\xf2', '%f3': '\xf3', '%F3': '\xf3', '%f4': '\xf4', '%F4': '\xf4', + '%f5': '\xf5', '%F5': '\xf5', '%f6': '\xf6', '%F6': '\xf6', '%f7': '\xf7', + '%F7': '\xf7', '%f8': '\xf8', '%F8': '\xf8', '%f9': '\xf9', '%F9': '\xf9', + '%fa': '\xfa', '%Fa': '\xfa', '%fA': '\xfa', '%FA': '\xfa', '%fb': '\xfb', + '%Fb': '\xfb', '%fB': '\xfb', '%FB': '\xfb', '%fc': '\xfc', '%Fc': '\xfc', + '%fC': '\xfc', '%FC': '\xfc', '%fd': '\xfd', '%Fd': '\xfd', '%fD': '\xfd', + '%FD': '\xfd', '%fe': '\xfe', '%Fe': '\xfe', '%fE': '\xfe', '%FE': '\xfe', + '%ff': '\xff', '%Ff': '\xff', '%fF': '\xff', '%FF': '\xff' +} + +function encodedReplacer (match) { + return EncodedLookup[match] +} + +const STATE_KEY = 0 +const STATE_VALUE = 1 +const STATE_CHARSET = 2 +const STATE_LANG = 3 + +function parseParams (str) { + const res = [] + let state = STATE_KEY + let charset = '' + let inquote = false + let escaping = false + let p = 0 + let tmp = '' + const len = str.length + + for (var i = 0; i < len; ++i) { // eslint-disable-line no-var + const char = str[i] + if (char === '\\' && inquote) { + if (escaping) { escaping = false } else { + escaping = true + continue + } + } else if (char === '"') { + if (!escaping) { + if (inquote) { + inquote = false + state = STATE_KEY + } else { inquote = true } + continue + } else { escaping = false } + } else { + if (escaping && inquote) { tmp += '\\' } + escaping = false + if ((state === STATE_CHARSET || state === STATE_LANG) && char === "'") { + if (state === STATE_CHARSET) { + state = STATE_LANG + charset = tmp.substring(1) + } else { state = STATE_VALUE } + tmp = '' + continue + } else if (state === STATE_KEY && + (char === '*' || char === '=') && + res.length) { + state = char === '*' + ? STATE_CHARSET + : STATE_VALUE + res[p] = [tmp, undefined] + tmp = '' + continue + } else if (!inquote && char === ';') { + state = STATE_KEY + if (charset) { + if (tmp.length) { + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), + 'binary', + charset) + } + charset = '' + } else if (tmp.length) { + tmp = decodeText(tmp, 'binary', 'utf8') + } + if (res[p] === undefined) { res[p] = tmp } else { res[p][1] = tmp } + tmp = '' + ++p + continue + } else if (!inquote && (char === ' ' || char === '\t')) { continue } + } + tmp += char + } + if (charset && tmp.length) { + tmp = decodeText(tmp.replace(RE_ENCODED, encodedReplacer), + 'binary', + charset) + } else if (tmp) { + tmp = decodeText(tmp, 'binary', 'utf8') + } + + if (res[p] === undefined) { + if (tmp) { res[p] = tmp } + } else { res[p][1] = tmp } + + return res +} + +module.exports = parseParams + + +/***/ }), + +/***/ 76637: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AclRoleAccessorMethods = exports.Acl = void 0; +const promisify_1 = __nccwpck_require__(60206); +/** + * Attach functionality to a {@link Storage.acl} instance. This will add an + * object for each role group (owners, readers, and writers), with each object + * containing methods to add or delete a type of entity. + * + * As an example, here are a few methods that are created. + * + * myBucket.acl.readers.deleteGroup('groupId', function(err) {}); + * + * myBucket.acl.owners.addUser('email@example.com', function(err, acl) {}); + * + * myBucket.acl.writers.addDomain('example.com', function(err, acl) {}); + * + * @private + */ +class AclRoleAccessorMethods { + constructor() { + this.owners = {}; + this.readers = {}; + this.writers = {}; + /** + * An object of convenience methods to add or delete owner ACL permissions + * for a given entity. + * + * The supported methods include: + * + * - `myFile.acl.owners.addAllAuthenticatedUsers` + * - `myFile.acl.owners.deleteAllAuthenticatedUsers` + * - `myFile.acl.owners.addAllUsers` + * - `myFile.acl.owners.deleteAllUsers` + * - `myFile.acl.owners.addDomain` + * - `myFile.acl.owners.deleteDomain` + * - `myFile.acl.owners.addGroup` + * - `myFile.acl.owners.deleteGroup` + * - `myFile.acl.owners.addProject` + * - `myFile.acl.owners.deleteProject` + * - `myFile.acl.owners.addUser` + * - `myFile.acl.owners.deleteUser` + * + * @name Acl#owners + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * //- + * // Add a user as an owner of a file. + * //- + * const myBucket = gcs.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * myFile.acl.owners.addUser('email@example.com', function(err, aclObject) + * {}); + * + * //- + * // For reference, the above command is the same as running the following. + * //- + * myFile.acl.add({ + * entity: 'user-email@example.com', + * role: gcs.acl.OWNER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.owners.addUser('email@example.com').then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + this.owners = {}; + /** + * An object of convenience methods to add or delete reader ACL permissions + * for a given entity. + * + * The supported methods include: + * + * - `myFile.acl.readers.addAllAuthenticatedUsers` + * - `myFile.acl.readers.deleteAllAuthenticatedUsers` + * - `myFile.acl.readers.addAllUsers` + * - `myFile.acl.readers.deleteAllUsers` + * - `myFile.acl.readers.addDomain` + * - `myFile.acl.readers.deleteDomain` + * - `myFile.acl.readers.addGroup` + * - `myFile.acl.readers.deleteGroup` + * - `myFile.acl.readers.addProject` + * - `myFile.acl.readers.deleteProject` + * - `myFile.acl.readers.addUser` + * - `myFile.acl.readers.deleteUser` + * + * @name Acl#readers + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * //- + * // Add a user as a reader of a file. + * //- + * myFile.acl.readers.addUser('email@example.com', function(err, aclObject) + * {}); + * + * //- + * // For reference, the above command is the same as running the following. + * //- + * myFile.acl.add({ + * entity: 'user-email@example.com', + * role: gcs.acl.READER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.readers.addUser('email@example.com').then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + this.readers = {}; + /** + * An object of convenience methods to add or delete writer ACL permissions + * for a given entity. + * + * The supported methods include: + * + * - `myFile.acl.writers.addAllAuthenticatedUsers` + * - `myFile.acl.writers.deleteAllAuthenticatedUsers` + * - `myFile.acl.writers.addAllUsers` + * - `myFile.acl.writers.deleteAllUsers` + * - `myFile.acl.writers.addDomain` + * - `myFile.acl.writers.deleteDomain` + * - `myFile.acl.writers.addGroup` + * - `myFile.acl.writers.deleteGroup` + * - `myFile.acl.writers.addProject` + * - `myFile.acl.writers.deleteProject` + * - `myFile.acl.writers.addUser` + * - `myFile.acl.writers.deleteUser` + * + * @name Acl#writers + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * //- + * // Add a user as a writer of a file. + * //- + * myFile.acl.writers.addUser('email@example.com', function(err, aclObject) + * {}); + * + * //- + * // For reference, the above command is the same as running the following. + * //- + * myFile.acl.add({ + * entity: 'user-email@example.com', + * role: gcs.acl.WRITER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.writers.addUser('email@example.com').then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + this.writers = {}; + AclRoleAccessorMethods.roles.forEach(this._assignAccessMethods.bind(this)); + } + _assignAccessMethods(role) { + const accessMethods = AclRoleAccessorMethods.accessMethods; + const entities = AclRoleAccessorMethods.entities; + const roleGroup = role.toLowerCase() + 's'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this[roleGroup] = entities.reduce((acc, entity) => { + const isPrefix = entity.charAt(entity.length - 1) === '-'; + accessMethods.forEach(accessMethod => { + let method = accessMethod + entity[0].toUpperCase() + entity.substring(1); + if (isPrefix) { + method = method.replace('-', ''); + } + // Wrap the parent accessor method (e.g. `add` or `delete`) to avoid the + // more complex API of specifying an `entity` and `role`. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + acc[method] = (entityId, options, callback) => { + let apiEntity; + if (typeof options === 'function') { + callback = options; + options = {}; + } + if (isPrefix) { + apiEntity = entity + entityId; + } + else { + // If the entity is not a prefix, it is a special entity group + // that does not require further details. The accessor methods + // only accept a callback. + apiEntity = entity; + callback = entityId; + } + options = Object.assign({ + entity: apiEntity, + role, + }, options); + const args = [options]; + if (typeof callback === 'function') { + args.push(callback); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return this[accessMethod].apply(this, args); + }; + }); + return acc; + }, {}); + } +} +exports.AclRoleAccessorMethods = AclRoleAccessorMethods; +AclRoleAccessorMethods.accessMethods = ['add', 'delete']; +AclRoleAccessorMethods.entities = [ + // Special entity groups that do not require further specification. + 'allAuthenticatedUsers', + 'allUsers', + // Entity groups that require specification, e.g. `user-email@example.com`. + 'domain-', + 'group-', + 'project-', + 'user-', +]; +AclRoleAccessorMethods.roles = ['OWNER', 'READER', 'WRITER']; +/** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * An ACL consists of one or more entries, where each entry grants permissions + * to an entity. Permissions define the actions that can be performed against an + * object or bucket (for example, `READ` or `WRITE`); the entity defines who the + * permission applies to (for example, a specific user or group of users). + * + * Where an `entity` value is accepted, we follow the format the Cloud Storage + * API expects. + * + * Refer to + * https://cloud.google.com/storage/docs/json_api/v1/defaultObjectAccessControls + * for the most up-to-date values. + * + * - `user-userId` + * - `user-email` + * - `group-groupId` + * - `group-email` + * - `domain-domain` + * - `project-team-projectId` + * - `allUsers` + * - `allAuthenticatedUsers` + * + * Examples: + * + * - The user "liz@example.com" would be `user-liz@example.com`. + * - The group "example@googlegroups.com" would be + * `group-example@googlegroups.com`. + * - To refer to all members of the Google Apps for Business domain + * "example.com", the entity would be `domain-example.com`. + * + * For more detailed information, see + * {@link http://goo.gl/6qBBPO| About Access Control Lists}. + * + * @constructor Acl + * @mixin + * @param {object} options Configuration options. + */ +class Acl extends AclRoleAccessorMethods { + constructor(options) { + super(); + this.pathPrefix = options.pathPrefix; + this.request_ = options.request; + } + /** + * @typedef {array} AddAclResponse + * @property {object} 0 The Acl Objects. + * @property {object} 1 The full API response. + */ + /** + * @callback AddAclCallback + * @param {?Error} err Request error, if any. + * @param {object} acl The Acl Objects. + * @param {object} apiResponse The full API response. + */ + /** + * Add access controls on a {@link Bucket} or {@link File}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/insert| BucketAccessControls: insert API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/insert| ObjectAccessControls: insert API Documentation} + * + * @param {object} options Configuration options. + * @param {string} options.entity Whose permissions will be added. + * @param {string} options.role Permissions allowed for the defined entity. + * See {@link https://cloud.google.com/storage/docs/access-control Access + * Control}. + * @param {number} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {AddAclCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * const options = { + * entity: 'user-useremail@example.com', + * role: gcs.acl.OWNER_ROLE + * }; + * + * myBucket.acl.add(options, function(err, aclObject, apiResponse) {}); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * // Here is how you would grant ownership permissions to a user on a + * specific + * // revision of a file. + * //- + * myFile.acl.add({ + * entity: 'user-useremail@example.com', + * role: gcs.acl.OWNER_ROLE, + * generation: 1 + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_add_file_owner + * Example of adding an owner to a file: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_owner + * Example of adding an owner to a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_default_owner + * Example of adding a default owner to a bucket: + */ + add(options, callback) { + const query = {}; + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + this.request({ + method: 'POST', + uri: '', + qs: query, + maxRetries: 0, //explicitly set this value since this is a non-idempotent function + json: { + entity: options.entity, + role: options.role.toUpperCase(), + }, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + callback(null, this.makeAclObject_(resp), resp); + }); + } + /** + * @typedef {array} RemoveAclResponse + * @property {object} 0 The full API response. + */ + /** + * @callback RemoveAclCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Delete access controls on a {@link Bucket} or {@link File}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/delete| BucketAccessControls: delete API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/delete| ObjectAccessControls: delete API Documentation} + * + * @param {object} options Configuration object. + * @param {string} options.entity Whose permissions will be revoked. + * @param {int} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {RemoveAclCallback} callback The callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * myBucket.acl.delete({ + * entity: 'user-useremail@example.com' + * }, function(err, apiResponse) {}); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * //- + * myFile.acl.delete({ + * entity: 'user-useremail@example.com', + * generation: 1 + * }, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_owner + * Example of removing an owner from a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_default_owner + * Example of removing a default owner from a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_file_owner + * Example of removing an owner from a bucket: + */ + delete(options, callback) { + const query = {}; + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + this.request({ + method: 'DELETE', + uri: '/' + encodeURIComponent(options.entity), + qs: query, + }, (err, resp) => { + callback(err, resp); + }); + } + /** + * @typedef {array} GetAclResponse + * @property {object|object[]} 0 Single or array of Acl Objects. + * @property {object} 1 The full API response. + */ + /** + * @callback GetAclCallback + * @param {?Error} err Request error, if any. + * @param {object|object[]} acl Single or array of Acl Objects. + * @param {object} apiResponse The full API response. + */ + /** + * Get access controls on a {@link Bucket} or {@link File}. If + * an entity is omitted, you will receive an array of all applicable access + * controls. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/get| BucketAccessControls: get API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/get| ObjectAccessControls: get API Documentation} + * + * @param {object|function} [options] Configuration options. If you want to + * receive a list of all access controls, pass the callback function as + * the only argument. + * @param {string} options.entity Whose permissions will be fetched. + * @param {number} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetAclCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * myBucket.acl.get({ + * entity: 'user-useremail@example.com' + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // Get all access controls. + * //- + * myBucket.acl.get(function(err, aclObjects, apiResponse) { + * // aclObjects = [ + * // { + * // entity: 'user-useremail@example.com', + * // role: 'owner' + * // } + * // ] + * }); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * //- + * myFile.acl.get({ + * entity: 'user-useremail@example.com', + * generation: 1 + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.acl.get().then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_print_file_acl + * Example of printing a file's ACL: + * + * @example include:samples/acl.js + * region_tag:storage_print_file_acl_for_user + * Example of printing a file's ACL for a specific user: + * + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl + * Example of printing a bucket's ACL: + * + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl_for_user + * Example of printing a bucket's ACL for a specific user: + */ + get(optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : null; + const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb; + let path = ''; + const query = {}; + if (options) { + path = '/' + encodeURIComponent(options.entity); + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + } + this.request({ + uri: path, + qs: query, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + let results; + if (resp.items) { + results = resp.items.map(this.makeAclObject_); + } + else { + results = this.makeAclObject_(resp); + } + callback(null, results, resp); + }); + } + /** + * @typedef {array} UpdateAclResponse + * @property {object} 0 The updated Acl Objects. + * @property {object} 1 The full API response. + */ + /** + * @callback UpdateAclCallback + * @param {?Error} err Request error, if any. + * @param {object} acl The updated Acl Objects. + * @param {object} apiResponse The full API response. + */ + /** + * Update access controls on a {@link Bucket} or {@link File}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/update| BucketAccessControls: update API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/update| ObjectAccessControls: update API Documentation} + * + * @param {object} options Configuration options. + * @param {string} options.entity Whose permissions will be updated. + * @param {string} options.role Permissions allowed for the defined entity. + * See {@link Storage.acl}. + * @param {number} [options.generation] **File Objects Only** Select a specific + * revision of this file (as opposed to the latest version, the default). + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {UpdateAclCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * const myFile = myBucket.file('my-file'); + * + * const options = { + * entity: 'user-useremail@example.com', + * role: gcs.acl.WRITER_ROLE + * }; + * + * myBucket.acl.update(options, function(err, aclObject, apiResponse) {}); + * + * //- + * // For file ACL operations, you can also specify a `generation` property. + * //- + * myFile.acl.update({ + * entity: 'user-useremail@example.com', + * role: gcs.acl.WRITER_ROLE, + * generation: 1 + * }, function(err, aclObject, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myFile.acl.update(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + update(options, callback) { + const query = {}; + if (options.generation) { + query.generation = options.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + this.request({ + method: 'PUT', + uri: '/' + encodeURIComponent(options.entity), + qs: query, + json: { + role: options.role.toUpperCase(), + }, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + callback(null, this.makeAclObject_(resp), resp); + }); + } + /** + * Transform API responses to a consistent object format. + * + * @private + */ + makeAclObject_(accessControlObject) { + const obj = { + entity: accessControlObject.entity, + role: accessControlObject.role, + }; + if (accessControlObject.projectTeam) { + obj.projectTeam = accessControlObject.projectTeam; + } + return obj; + } + /** + * Patch requests up to the bucket's request object. + * + * @private + * + * @param {string} method Action. + * @param {string} path Request path. + * @param {*} query Request query object. + * @param {*} body Request body contents. + * @param {function} callback Callback function. + */ + request(reqOpts, callback) { + reqOpts.uri = this.pathPrefix + reqOpts.uri; + this.request_(reqOpts, callback); + } +} +exports.Acl = Acl; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Acl, { + exclude: ['request'], +}); + + +/***/ }), + +/***/ 82887: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Bucket = exports.BucketExceptionMessages = exports.AvailableServiceObjectMethods = exports.BucketActionToHTTPMethod = void 0; +const index_js_1 = __nccwpck_require__(11325); +const paginator_1 = __nccwpck_require__(99469); +const promisify_1 = __nccwpck_require__(60206); +const fs = __importStar(__nccwpck_require__(79896)); +const mime_1 = __importDefault(__nccwpck_require__(94900)); +const path = __importStar(__nccwpck_require__(16928)); +const p_limit_1 = __importDefault(__nccwpck_require__(58890)); +const util_1 = __nccwpck_require__(39023); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +const util_js_1 = __nccwpck_require__(74557); +const acl_js_1 = __nccwpck_require__(76637); +const file_js_1 = __nccwpck_require__(69975); +const iam_js_1 = __nccwpck_require__(52880); +const notification_js_1 = __nccwpck_require__(18598); +const storage_js_1 = __nccwpck_require__(92848); +const signer_js_1 = __nccwpck_require__(7319); +const stream_1 = __nccwpck_require__(2203); +const url_1 = __nccwpck_require__(87016); +var BucketActionToHTTPMethod; +(function (BucketActionToHTTPMethod) { + BucketActionToHTTPMethod["list"] = "GET"; +})(BucketActionToHTTPMethod || (exports.BucketActionToHTTPMethod = BucketActionToHTTPMethod = {})); +var AvailableServiceObjectMethods; +(function (AvailableServiceObjectMethods) { + AvailableServiceObjectMethods[AvailableServiceObjectMethods["setMetadata"] = 0] = "setMetadata"; + AvailableServiceObjectMethods[AvailableServiceObjectMethods["delete"] = 1] = "delete"; +})(AvailableServiceObjectMethods || (exports.AvailableServiceObjectMethods = AvailableServiceObjectMethods = {})); +var BucketExceptionMessages; +(function (BucketExceptionMessages) { + BucketExceptionMessages["PROVIDE_SOURCE_FILE"] = "You must provide at least one source file."; + BucketExceptionMessages["DESTINATION_FILE_NOT_SPECIFIED"] = "A destination file must be specified."; + BucketExceptionMessages["CHANNEL_ID_REQUIRED"] = "An ID is required to create a channel."; + BucketExceptionMessages["TOPIC_NAME_REQUIRED"] = "A valid topic name is required."; + BucketExceptionMessages["CONFIGURATION_OBJECT_PREFIX_REQUIRED"] = "A configuration object with a prefix is required."; + BucketExceptionMessages["SPECIFY_FILE_NAME"] = "A file name must be specified."; + BucketExceptionMessages["METAGENERATION_NOT_PROVIDED"] = "A metageneration must be provided."; + BucketExceptionMessages["SUPPLY_NOTIFICATION_ID"] = "You must supply a notification ID."; +})(BucketExceptionMessages || (exports.BucketExceptionMessages = BucketExceptionMessages = {})); +/** + * @callback Crc32cGeneratorToStringCallback + * A method returning the CRC32C as a base64-encoded string. + * + * @returns {string} + * + * @example + * Hashing the string 'data' should return 'rth90Q==' + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.toString(); // 'rth90Q==' + * ``` + **/ +/** + * @callback Crc32cGeneratorValidateCallback + * A method validating a base64-encoded CRC32C string. + * + * @param {string} [value] base64-encoded CRC32C string to validate + * @returns {boolean} + * + * @example + * Should return `true` if the value matches, `false` otherwise + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.validate('DkjKuA=='); // false + * crc32c.validate('rth90Q=='); // true + * ``` + **/ +/** + * @callback Crc32cGeneratorUpdateCallback + * A method for passing `Buffer`s for CRC32C generation. + * + * @param {Buffer} [data] data to update CRC32C value with + * @returns {undefined} + * + * @example + * Hashing buffers from 'some ' and 'text\n' + * + * ```js + * const buffer1 = Buffer.from('some '); + * crc32c.update(buffer1); + * + * const buffer2 = Buffer.from('text\n'); + * crc32c.update(buffer2); + * + * crc32c.toString(); // 'DkjKuA==' + * ``` + **/ +/** + * @typedef {object} CRC32CValidator + * @property {Crc32cGeneratorToStringCallback} + * @property {Crc32cGeneratorValidateCallback} + * @property {Crc32cGeneratorUpdateCallback} + */ +/** + * A function that generates a CRC32C Validator. Defaults to {@link CRC32C} + * + * @name Bucket#crc32cGenerator + * @type {CRC32CValidator} + */ +/** + * Get and set IAM policies for your bucket. + * + * @name Bucket#iam + * @mixes Iam + * + * See {@link https://cloud.google.com/storage/docs/access-control/iam#short_title_iam_management| Cloud Storage IAM Management} + * See {@link https://cloud.google.com/iam/docs/granting-changing-revoking-access| Granting, Changing, and Revoking Access} + * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Get the IAM policy for your bucket. + * //- + * bucket.iam.getPolicy(function(err, policy) { + * console.log(policy); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.getPolicy().then(function(data) { + * const policy = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/iam.js + * region_tag:storage_view_bucket_iam_members + * Example of retrieving a bucket's IAM policy: + * + * @example include:samples/iam.js + * region_tag:storage_add_bucket_iam_member + * Example of adding to a bucket's IAM policy: + * + * @example include:samples/iam.js + * region_tag:storage_remove_bucket_iam_member + * Example of removing from a bucket's IAM policy: + */ +/** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * An ACL consists of one or more entries, where each entry grants permissions + * to an entity. Permissions define the actions that can be performed against + * an object or bucket (for example, `READ` or `WRITE`); the entity defines + * who the permission applies to (for example, a specific user or group of + * users). + * + * The `acl` object on a Bucket instance provides methods to get you a list of + * the ACLs defined on your bucket, as well as set, update, and delete them. + * + * Buckets also have + * {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs} + * for all created files. Default ACLs specify permissions that all new + * objects added to the bucket will inherit by default. You can add, delete, + * get, and update entities and permissions for these as well with + * {@link Bucket#acl.default}. + * + * See {@link http://goo.gl/6qBBPO| About Access Control Lists} + * See {@link https://cloud.google.com/storage/docs/access-control/lists#default| Default ACLs} + * + * @name Bucket#acl + * @mixes Acl + * @property {Acl} default Cloud Storage Buckets have + * {@link https://cloud.google.com/storage/docs/access-control/lists#default| default ACLs} + * for all created files. You can add, delete, get, and update entities and + * permissions for these as well. The method signatures and examples are all + * the same, after only prefixing the method call with `default`. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Make a bucket's contents publicly readable. + * //- + * const myBucket = storage.bucket('my-bucket'); + * + * const options = { + * entity: 'allUsers', + * role: storage.acl.READER_ROLE + * }; + * + * myBucket.acl.add(options, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl + * Example of printing a bucket's ACL: + * + * @example include:samples/acl.js + * region_tag:storage_print_bucket_acl_for_user + * Example of printing a bucket's ACL for a specific user: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_owner + * Example of adding an owner to a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_owner + * Example of removing an owner from a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_add_bucket_default_owner + * Example of adding a default owner to a bucket: + * + * @example include:samples/acl.js + * region_tag:storage_remove_bucket_default_owner + * Example of removing a default owner from a bucket: + */ +/** + * The API-formatted resource description of the bucket. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name Bucket#metadata + * @type {object} + */ +/** + * The bucket's name. + * @name Bucket#name + * @type {string} + */ +/** + * Get {@link File} objects for the files currently in the bucket as a + * readable object stream. + * + * @method Bucket#getFilesStream + * @param {GetFilesOptions} [query] Query object for listing files. + * @returns {ReadableStream} A readable stream that emits {@link File} instances. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getFilesStream() + * .on('error', console.error) + * .on('data', function(file) { + * // file is a File object. + * }) + * .on('end', function() { + * // All files retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * bucket.getFilesStream() + * .on('data', function(file) { + * this.end(); + * }); + * + * //- + * // If you're filtering files with a delimiter, you should use + * // {@link Bucket#getFiles} and set `autoPaginate: false` in order to + * // preserve the `apiResponse` argument. + * //- + * const prefixes = []; + * + * function callback(err, files, nextQuery, apiResponse) { + * prefixes = prefixes.concat(apiResponse.prefixes); + * + * if (nextQuery) { + * bucket.getFiles(nextQuery, callback); + * } else { + * // prefixes = The finished array of prefixes. + * } + * } + * + * bucket.getFiles({ + * autoPaginate: false, + * delimiter: '/' + * }, callback); + * ``` + */ +/** + * Create a Bucket object to interact with a Cloud Storage bucket. + * + * @class + * @hideconstructor + * + * @param {Storage} storage A {@link Storage} instance. + * @param {string} name The name of the bucket. + * @param {object} [options] Configuration object. + * @param {string} [options.userProject] User project. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * ``` + */ +class Bucket extends index_js_1.ServiceObject { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + getFilesStream(query) { + // placeholder body, overwritten in constructor + return new stream_1.Readable(); + } + constructor(storage, name, options) { + var _a, _b, _c, _d; + options = options || {}; + // Allow for "gs://"-style input, and strip any trailing slashes. + name = name.replace(/^gs:\/\//, '').replace(/\/+$/, ''); + const requestQueryObject = {}; + if ((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) { + requestQueryObject.ifGenerationMatch = + options.preconditionOpts.ifGenerationMatch; + } + if ((_b = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationNotMatch) { + requestQueryObject.ifGenerationNotMatch = + options.preconditionOpts.ifGenerationNotMatch; + } + if ((_c = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _c === void 0 ? void 0 : _c.ifMetagenerationMatch) { + requestQueryObject.ifMetagenerationMatch = + options.preconditionOpts.ifMetagenerationMatch; + } + if ((_d = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _d === void 0 ? void 0 : _d.ifMetagenerationNotMatch) { + requestQueryObject.ifMetagenerationNotMatch = + options.preconditionOpts.ifMetagenerationNotMatch; + } + const userProject = options.userProject; + if (typeof userProject === 'string') { + requestQueryObject.userProject = userProject; + } + const methods = { + /** + * Create a bucket. + * + * @method Bucket#create + * @param {CreateBucketRequest} [metadata] Metadata to set for the bucket. + * @param {CreateBucketCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * bucket.create(function(err, bucket, apiResponse) { + * if (!err) { + * // The bucket was created successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.create().then(function(data) { + * const bucket = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + create: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * IamDeleteBucketOptions Configuration options. + * @property {boolean} [ignoreNotFound = false] Ignore an error if + * the bucket does not exist. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} DeleteBucketResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DeleteBucketCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Delete the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/delete| Buckets: delete API Documentation} + * + * @method Bucket#delete + * @param {DeleteBucketOptions} [options] Configuration options. + * @param {boolean} [options.ignoreNotFound = false] Ignore an error if + * the bucket does not exist. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DeleteBucketCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * bucket.delete(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/buckets.js + * region_tag:storage_delete_bucket + * Another example: + */ + delete: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} BucketExistsOptions Configuration options for Bucket#exists(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} BucketExistsResponse + * @property {boolean} 0 Whether the {@link Bucket} exists. + */ + /** + * @callback BucketExistsCallback + * @param {?Error} err Request error, if any. + * @param {boolean} exists Whether the {@link Bucket} exists. + */ + /** + * Check if the bucket exists. + * + * @method Bucket#exists + * @param {BucketExistsOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {BucketExistsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.exists(function(err, exists) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.exists().then(function(data) { + * const exists = data[0]; + * }); + * ``` + */ + exists: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} [GetBucketOptions] Configuration options for Bucket#get() + * @property {boolean} [autoCreate] Automatically create the object if + * it does not exist. Default: `false` + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} GetBucketResponse + * @property {Bucket} 0 The {@link Bucket}. + * @property {object} 1 The full API response. + */ + /** + * @callback GetBucketCallback + * @param {?Error} err Request error, if any. + * @param {Bucket} bucket The {@link Bucket}. + * @param {object} apiResponse The full API response. + */ + /** + * Get a bucket if it exists. + * + * You may optionally use this to "get or create" an object by providing + * an object with `autoCreate` set to `true`. Any extra configuration that + * is normally required for the `create` method must be contained within + * this object as well. + * + * @method Bucket#get + * @param {GetBucketOptions} [options] Configuration options. + * @param {boolean} [options.autoCreate] Automatically create the object if + * it does not exist. Default: `false` + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetBucketCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.get(function(err, bucket, apiResponse) { + * // `bucket.metadata` has been populated. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.get().then(function(data) { + * const bucket = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + get: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} GetBucketMetadataResponse + * @property {object} 0 The bucket metadata. + * @property {object} 1 The full API response. + */ + /** + * @callback GetBucketMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The bucket metadata. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} GetBucketMetadataOptions Configuration options for Bucket#getMetadata(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Get the bucket's metadata. + * + * To set metadata, see {@link Bucket#setMetadata}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/get| Buckets: get API Documentation} + * + * @method Bucket#getMetadata + * @param {GetBucketMetadataOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getMetadata(function(err, metadata, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getMetadata().then(function(data) { + * const metadata = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/requesterPays.js + * region_tag:storage_get_requester_pays_status + * Example of retrieving the requester pays status of a bucket: + */ + getMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} SetBucketMetadataOptions Configuration options for Bucket#setMetadata(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} SetBucketMetadataResponse + * @property {object} apiResponse The full API response. + */ + /** + * @callback SetBucketMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The bucket metadata. + */ + /** + * Set the bucket's metadata. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @method Bucket#setMetadata + * @param {object} metadata The metadata you wish to set. + * @param {SetBucketMetadataOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Set website metadata field on the bucket. + * //- + * const metadata = { + * website: { + * mainPageSuffix: 'http://example.com', + * notFoundPage: 'http://example.com/404.html' + * } + * }; + * + * bucket.setMetadata(metadata, function(err, apiResponse) {}); + * + * //- + * // Enable versioning for your bucket. + * //- + * bucket.setMetadata({ + * versioning: { + * enabled: true + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Enable KMS encryption for objects within this bucket. + * //- + * bucket.setMetadata({ + * encryption: { + * defaultKmsKeyName: 'projects/grape-spaceship-123/...' + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Set the default event-based hold value for new objects in this + * // bucket. + * //- + * bucket.setMetadata({ + * defaultEventBasedHold: true + * }, function(err, apiResponse) {}); + * + * //- + * // Remove object lifecycle rules. + * //- + * bucket.setMetadata({ + * lifecycle: null + * }, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setMetadata(metadata).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + }; + super({ + parent: storage, + baseUrl: '/b', + id: name, + createMethod: storage.createBucket.bind(storage), + methods, + }); + this.name = name; + this.storage = storage; + this.userProject = options.userProject; + this.acl = new acl_js_1.Acl({ + request: this.request.bind(this), + pathPrefix: '/acl', + }); + this.acl.default = new acl_js_1.Acl({ + request: this.request.bind(this), + pathPrefix: '/defaultObjectAcl', + }); + this.crc32cGenerator = + options.crc32cGenerator || this.storage.crc32cGenerator; + this.iam = new iam_js_1.Iam(this); + this.getFilesStream = paginator_1.paginator.streamify('getFiles'); + this.instanceRetryValue = storage.retryOptions.autoRetry; + this.instancePreconditionOpts = options === null || options === void 0 ? void 0 : options.preconditionOpts; + } + /** + * The bucket's Cloud Storage URI (`gs://`) + * + * @example + * ```ts + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * // `gs://my-bucket` + * const href = bucket.cloudStorageURI.href; + * ``` + */ + get cloudStorageURI() { + const uri = new url_1.URL('gs://'); + uri.host = this.name; + return uri; + } + /** + * @typedef {object} AddLifecycleRuleOptions Configuration options for Bucket#addLifecycleRule(). + * @property {boolean} [append=true] The new rules will be appended to any + * pre-existing rules. + */ + /** + * + * @typedef {object} LifecycleRule The new lifecycle rule to be added to objects + * in this bucket. + * @property {string|object} action The action to be taken upon matching of + * all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'. + * **Note**: For configuring a raw-formatted rule object to be passed as `action` + * please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}. + * @property {object} condition Condition a bucket must meet before the + * action occurs on the bucket. Refer to following supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}. + * @property {string} [storageClass] When using the `setStorageClass` + * action, provide this option to dictate which storage class the object + * should update to. Please see + * [SetStorageClass option documentation]{@link https://cloud.google.com/storage/docs/lifecycle#setstorageclass} for supported transitions. + */ + /** + * Add an object lifecycle management rule to the bucket. + * + * By default, an Object Lifecycle Management rule provided to this method + * will be included to the existing policy. To replace all existing rules, + * supply the `options` argument, setting `append` to `false`. + * + * To add multiple rules, pass a list to the `rule` parameter. Calling this + * function multiple times asynchronously does not guarantee that all rules + * are added correctly. + * + * See {@link https://cloud.google.com/storage/docs/lifecycle| Object Lifecycle Management} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @param {LifecycleRule|LifecycleRule[]} rule The new lifecycle rule or rules to be added to objects + * in this bucket. + * @param {string|object} rule.action The action to be taken upon matching of + * all the conditions 'delete', 'setStorageClass', or 'AbortIncompleteMultipartUpload'. + * **Note**: For configuring a raw-formatted rule object to be passed as `action` + * please refer to the [examples]{@link https://cloud.google.com/storage/docs/managing-lifecycles#configexamples}. + * @param {object} rule.condition Condition a bucket must meet before the + * action occurson the bucket. Refer to followitn supported [conditions]{@link https://cloud.google.com/storage/docs/lifecycle#conditions}. + * @param {string} [rule.storageClass] When using the `setStorageClass` + * action, provide this option to dictate which storage class the object + * should update to. + * @param {AddLifecycleRuleOptions} [options] Configuration object. + * @param {boolean} [options.append=true] Append the new rule to the existing + * policy. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Automatically have an object deleted from this bucket once it is 3 years + * // of age. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * age: 365 * 3 // Specified in days. + * } + * }, function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * const lifecycleRules = bucket.metadata.lifecycle.rule; + * + * // Iterate over the Object Lifecycle Management rules on this bucket. + * lifecycleRules.forEach(lifecycleRule => {}); + * }); + * + * //- + * // By default, the rule you provide will be added to the existing policy. + * // Optionally, you can disable this behavior to replace all of the + * // pre-existing rules. + * //- + * const options = { + * append: false + * }; + * + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * age: 365 * 3 // Specified in days. + * } + * }, options, function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * // All rules have been replaced with the new "delete" rule. + * + * // Iterate over the Object Lifecycle Management rules on this bucket. + * lifecycleRules.forEach(lifecycleRule => {}); + * }); + * + * //- + * // For objects created before 2018, "downgrade" the storage class. + * //- + * bucket.addLifecycleRule({ + * action: 'setStorageClass', + * storageClass: 'COLDLINE', + * condition: { + * createdBefore: new Date('2018') + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete objects created before 2016 which have the Coldline storage + * // class. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * matchesStorageClass: [ + * 'COLDLINE' + * ], + * createdBefore: new Date('2016') + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete object that has a noncurrent timestamp that is at least 100 days. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * daysSinceNoncurrentTime: 100 + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete object that has a noncurrent timestamp before 2020-01-01. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * noncurrentTimeBefore: new Date('2020-01-01') + * } + * }, function(err, apiResponse) {}); + * + * //- + * // Delete object that has a customTime that is at least 100 days. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * daysSinceCustomTime: 100 + * } + * }, function(err, apiResponse) ()); + * + * //- + * // Delete object that has a customTime before 2020-01-01. + * //- + * bucket.addLifecycleRule({ + * action: 'delete', + * condition: { + * customTimeBefore: new Date('2020-01-01') + * } + * }, function(err, apiResponse) {}); + * ``` + */ + addLifecycleRule(rule, optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + options = options || {}; + const rules = Array.isArray(rule) ? rule : [rule]; + for (const curRule of rules) { + if (curRule.condition.createdBefore instanceof Date) { + curRule.condition.createdBefore = curRule.condition.createdBefore + .toISOString() + .replace(/T.+$/, ''); + } + if (curRule.condition.customTimeBefore instanceof Date) { + curRule.condition.customTimeBefore = curRule.condition.customTimeBefore + .toISOString() + .replace(/T.+$/, ''); + } + if (curRule.condition.noncurrentTimeBefore instanceof Date) { + curRule.condition.noncurrentTimeBefore = + curRule.condition.noncurrentTimeBefore + .toISOString() + .replace(/T.+$/, ''); + } + } + if (options.append === false) { + this.setMetadata({ lifecycle: { rule: rules } }, options, callback); + return; + } + // The default behavior appends the previously-defined lifecycle rules with + // the new ones just passed in by the user. + this.getMetadata((err, metadata) => { + var _a, _b; + if (err) { + callback(err); + return; + } + const currentLifecycleRules = Array.isArray((_a = metadata.lifecycle) === null || _a === void 0 ? void 0 : _a.rule) + ? (_b = metadata.lifecycle) === null || _b === void 0 ? void 0 : _b.rule + : []; + this.setMetadata({ + lifecycle: { rule: currentLifecycleRules.concat(rules) }, + }, options, callback); + }); + } + /** + * @typedef {object} CombineOptions + * @property {string} [kmsKeyName] Resource name of the Cloud KMS key, of + * the form + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`, + * that will be used to encrypt the object. Overwrites the object + * metadata's `kms_key_name` value, if any. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback CombineCallback + * @param {?Error} err Request error, if any. + * @param {File} newFile The new {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} CombineResponse + * @property {File} 0 The new {@link File}. + * @property {object} 1 The full API response. + */ + /** + * Combine multiple files into one new file. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/compose| Objects: compose API Documentation} + * + * @throws {Error} if a non-array is provided as sources argument. + * @throws {Error} if no sources are provided. + * @throws {Error} if no destination is provided. + * + * @param {string[]|File[]} sources The source files that will be + * combined. + * @param {string|File} destination The file you would like the + * source files combined into. + * @param {CombineOptions} [options] Configuration options. + * @param {string} [options.kmsKeyName] Resource name of the Cloud KMS key, of + * the form + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`, + * that will be used to encrypt the object. Overwrites the object + * metadata's `kms_key_name` value, if any. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + + * @param {CombineCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const logBucket = storage.bucket('log-bucket'); + * + * const sources = [ + * logBucket.file('2013-logs.txt'), + * logBucket.file('2014-logs.txt') + * ]; + * + * const allLogs = logBucket.file('all-logs.txt'); + * + * logBucket.combine(sources, allLogs, function(err, newFile, apiResponse) { + * // newFile === allLogs + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * logBucket.combine(sources, allLogs).then(function(data) { + * const newFile = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + combine(sources, destination, optionsOrCallback, callback) { + var _a; + if (!Array.isArray(sources) || sources.length === 0) { + throw new Error(BucketExceptionMessages.PROVIDE_SOURCE_FILE); + } + if (!destination) { + throw new Error(BucketExceptionMessages.DESTINATION_FILE_NOT_SPECIFIED); + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, // Not relevant but param is required + AvailableServiceObjectMethods.setMetadata, // Same as above + options); + const convertToFile = (file) => { + if (file instanceof file_js_1.File) { + return file; + } + return this.file(file); + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + sources = sources.map(convertToFile); + const destinationFile = convertToFile(destination); + callback = callback || index_js_1.util.noop; + if (!destinationFile.metadata.contentType) { + const destinationContentType = mime_1.default.getType(destinationFile.name) || undefined; + if (destinationContentType) { + destinationFile.metadata.contentType = destinationContentType; + } + } + let maxRetries = this.storage.retryOptions.maxRetries; + if ((((_a = destinationFile === null || destinationFile === void 0 ? void 0 : destinationFile.instancePreconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === + undefined && + options.ifGenerationMatch === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + maxRetries = 0; + } + if (options.ifGenerationMatch === undefined) { + Object.assign(options, destinationFile.instancePreconditionOpts, options); + } + // Make the request from the destination File object. + destinationFile.request({ + method: 'POST', + uri: '/compose', + maxRetries, + json: { + destination: { + contentType: destinationFile.metadata.contentType, + contentEncoding: destinationFile.metadata.contentEncoding, + }, + sourceObjects: sources.map(source => { + const sourceObject = { + name: source.name, + }; + if (source.metadata && source.metadata.generation) { + sourceObject.generation = parseInt(source.metadata.generation.toString()); + } + return sourceObject; + }), + }, + qs: options, + }, (err, resp) => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + if (err) { + callback(err, null, resp); + return; + } + callback(null, destinationFile, resp); + }); + } + /** + * See a {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll request body}. + * + * @typedef {object} CreateChannelConfig + * @property {string} address The address where notifications are + * delivered for this channel. + * @property {string} [delimiter] Returns results in a directory-like mode. + * @property {number} [maxResults] Maximum number of `items` plus `prefixes` + * to return in a single page of responses. + * @property {string} [pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @property {string} [prefix] Filter results to objects whose names begin + * with this prefix. + * @property {string} [projection=noAcl] Set of properties to return. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {boolean} [versions=false] If `true`, lists all versions of an object + * as distinct results. + */ + /** + * @typedef {object} CreateChannelOptions + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} CreateChannelResponse + * @property {Channel} 0 The new {@link Channel}. + * @property {object} 1 The full API response. + */ + /** + * @callback CreateChannelCallback + * @param {?Error} err Request error, if any. + * @param {Channel} channel The new {@link Channel}. + * @param {object} apiResponse The full API response. + */ + /** + * Create a channel that will be notified when objects in this bucket changes. + * + * @throws {Error} If an ID is not provided. + * @throws {Error} If an address is not provided. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/watchAll| Objects: watchAll API Documentation} + * + * @param {string} id The ID of the channel to create. + * @param {CreateChannelConfig} config Configuration for creating channel. + * @param {string} config.address The address where notifications are + * delivered for this channel. + * @param {string} [config.delimiter] Returns results in a directory-like mode. + * @param {number} [config.maxResults] Maximum number of `items` plus `prefixes` + * to return in a single page of responses. + * @param {string} [config.pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @param {string} [config.prefix] Filter results to objects whose names begin + * with this prefix. + * @param {string} [config.projection=noAcl] Set of properties to return. + * @param {string} [config.userProject] The ID of the project which will be + * billed for the request. + * @param {boolean} [config.versions=false] If `true`, lists all versions of an object + * as distinct results. + * @param {CreateChannelOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {CreateChannelCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const id = 'new-channel-id'; + * + * const config = { + * address: 'https://...' + * }; + * + * bucket.createChannel(id, config, function(err, channel, apiResponse) { + * if (!err) { + * // Channel created successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.createChannel(id, config).then(function(data) { + * const channel = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + createChannel(id, config, optionsOrCallback, callback) { + if (typeof id !== 'string') { + throw new Error(BucketExceptionMessages.CHANNEL_ID_REQUIRED); + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.request({ + method: 'POST', + uri: '/o/watch', + json: Object.assign({ + id, + type: 'web_hook', + }, config), + qs: options, + }, (err, apiResponse) => { + if (err) { + callback(err, null, apiResponse); + return; + } + const resourceId = apiResponse.resourceId; + const channel = this.storage.channel(id, resourceId); + channel.metadata = apiResponse; + callback(null, channel, apiResponse); + }); + } + /** + * Metadata to set for the Notification. + * + * @typedef {object} CreateNotificationOptions + * @property {object} [customAttributes] An optional list of additional + * attributes to attach to each Cloud PubSub message published for this + * notification subscription. + * @property {string[]} [eventTypes] If present, only send notifications about + * listed event types. If empty, sent notifications for all event types. + * @property {string} [objectNamePrefix] If present, only apply this + * notification configuration to object names that begin with this prefix. + * @property {string} [payloadFormat] The desired content of the Payload. + * Defaults to `JSON_API_V1`. + * + * Acceptable values are: + * - `JSON_API_V1` + * + * - `NONE` + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback CreateNotificationCallback + * @param {?Error} err Request error, if any. + * @param {Notification} notification The new {@link Notification}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} CreateNotificationResponse + * @property {Notification} 0 The new {@link Notification}. + * @property {object} 1 The full API response. + */ + /** + * Creates a notification subscription for the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/insert| Notifications: insert} + * + * @param {Topic|string} topic The Cloud PubSub topic to which this + * subscription publishes. If the project ID is omitted, the current + * project ID will be used. + * + * Acceptable formats are: + * - `projects/grape-spaceship-123/topics/my-topic` + * + * - `my-topic` + * @param {CreateNotificationOptions} [options] Metadata to set for the + * notification. + * @param {object} [options.customAttributes] An optional list of additional + * attributes to attach to each Cloud PubSub message published for this + * notification subscription. + * @param {string[]} [options.eventTypes] If present, only send notifications about + * listed event types. If empty, sent notifications for all event types. + * @param {string} [options.objectNamePrefix] If present, only apply this + * notification configuration to object names that begin with this prefix. + * @param {string} [options.payloadFormat] The desired content of the Payload. + * Defaults to `JSON_API_V1`. + * + * Acceptable values are: + * - `JSON_API_V1` + * + * - `NONE` + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {CreateNotificationCallback} [callback] Callback function. + * @returns {Promise} + * @throws {Error} If a valid topic is not provided. + * @see Notification#create + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const callback = function(err, notification, apiResponse) { + * if (!err) { + * // The notification was created successfully. + * } + * }; + * + * myBucket.createNotification('my-topic', callback); + * + * //- + * // Configure the nofiication by providing Notification metadata. + * //- + * const metadata = { + * objectNamePrefix: 'prefix-' + * }; + * + * myBucket.createNotification('my-topic', metadata, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * myBucket.createNotification('my-topic').then(function(data) { + * const notification = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/createNotification.js + * region_tag:storage_create_bucket_notifications + * Another example: + */ + createNotification(topic, optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + const topicIsObject = topic !== null && typeof topic === 'object'; + if (topicIsObject && index_js_1.util.isCustomType(topic, 'pubsub/topic')) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + topic = topic.name; + } + if (typeof topic !== 'string') { + throw new Error(BucketExceptionMessages.TOPIC_NAME_REQUIRED); + } + const body = Object.assign({ topic }, options); + if (body.topic.indexOf('projects') !== 0) { + body.topic = 'projects/{{projectId}}/topics/' + body.topic; + } + body.topic = `//pubsub.${this.storage.universeDomain}/` + body.topic; + if (!body.payloadFormat) { + body.payloadFormat = 'JSON_API_V1'; + } + const query = {}; + if (body.userProject) { + query.userProject = body.userProject; + delete body.userProject; + } + this.request({ + method: 'POST', + uri: '/notificationConfigs', + json: (0, util_js_1.convertObjKeysToSnakeCase)(body), + qs: query, + maxRetries: 0, //explicitly set this value since this is a non-idempotent function + }, (err, apiResponse) => { + if (err) { + callback(err, null, apiResponse); + return; + } + const notification = this.notification(apiResponse.id); + notification.metadata = apiResponse; + callback(null, notification, apiResponse); + }); + } + /** + * @typedef {object} DeleteFilesOptions Query object. See {@link Bucket#getFiles} + * for all of the supported properties. + * @property {boolean} [force] Suppress errors until all files have been + * processed. + */ + /** + * @callback DeleteFilesCallback + * @param {?Error|?Error[]} err Request error, if any, or array of errors from + * files that were not able to be deleted. + * @param {object} [apiResponse] The full API response. + */ + /** + * Iterate over the bucket's files, calling `file.delete()` on each. + * + * This is not an atomic request. A delete attempt will be + * made for each file individually. Any one can fail, in which case only a + * portion of the files you intended to be deleted would have. + * + * Operations are performed in parallel, up to 10 at once. The first error + * breaks the loop and will execute the provided callback with it. Specify + * `{ force: true }` to suppress the errors until all files have had a chance + * to be processed. + * + * File preconditions cannot be passed to this function. It will not retry unless + * the idempotency strategy is set to retry always. + * + * The `query` object passed as the first argument will also be passed to + * {@link Bucket#getFiles}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/delete| Objects: delete API Documentation} + * + * @param {DeleteFilesOptions} [query] Query object. See {@link Bucket#getFiles} + * @param {boolean} [query.force] Suppress errors until all files have been + * processed. + * @param {DeleteFilesCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Delete all of the files in the bucket. + * //- + * bucket.deleteFiles(function(err) {}); + * + * //- + * // By default, if a file cannot be deleted, this method will stop deleting + * // files from your bucket. You can override this setting with `force: + * // true`. + * //- + * bucket.deleteFiles({ + * force: true + * }, function(errors) { + * // `errors`: + * // Array of errors if any occurred, otherwise null. + * }); + * + * //- + * // The first argument to this method acts as a query to + * // {@link Bucket#getFiles}. As an example, you can delete files + * // which match a prefix. + * //- + * bucket.deleteFiles({ + * prefix: 'images/' + * }, function(err) { + * if (!err) { + * // All files in the `images` directory have been deleted. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.deleteFiles().then(function() {}); + * ``` + */ + deleteFiles(queryOrCallback, callback) { + let query = {}; + if (typeof queryOrCallback === 'function') { + callback = queryOrCallback; + } + else if (queryOrCallback) { + query = queryOrCallback; + } + const MAX_PARALLEL_LIMIT = 10; + const MAX_QUEUE_SIZE = 1000; + const errors = []; + const deleteFile = (file) => { + return file.delete(query).catch(err => { + if (!query.force) { + throw err; + } + errors.push(err); + }); + }; + (async () => { + try { + let promises = []; + const limit = (0, p_limit_1.default)(MAX_PARALLEL_LIMIT); + const filesStream = this.getFilesStream(query); + for await (const curFile of filesStream) { + if (promises.length >= MAX_QUEUE_SIZE) { + await Promise.all(promises); + promises = []; + } + promises.push(limit(() => deleteFile(curFile)).catch(e => { + filesStream.destroy(); + throw e; + })); + } + await Promise.all(promises); + callback(errors.length > 0 ? errors : null); + } + catch (e) { + callback(e); + return; + } + })(); + } + /** + * @deprecated + * @typedef {array} DeleteLabelsResponse + * @property {object} 0 The full API response. + */ + /** + * @deprecated + * @callback DeleteLabelsCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata Bucket's metadata. + */ + /** + * @deprecated Use setMetadata directly + * Delete one or more labels from this bucket. + * + * @param {string|string[]} [labels] The labels to delete. If no labels are + * provided, all of the labels are removed. + * @param {DeleteLabelsCallback} [callback] Callback function. + * @param {DeleteLabelsOptions} [options] Options, including precondition options + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Delete all of the labels from this bucket. + * //- + * bucket.deleteLabels(function(err, apiResponse) {}); + * + * //- + * // Delete a single label. + * //- + * bucket.deleteLabels('labelone', function(err, apiResponse) {}); + * + * //- + * // Delete a specific set of labels. + * //- + * bucket.deleteLabels([ + * 'labelone', + * 'labeltwo' + * ], function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.deleteLabels().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + deleteLabels(labelsOrCallbackOrOptions, optionsOrCallback, callback) { + let labels = new Array(); + let options = {}; + if (typeof labelsOrCallbackOrOptions === 'function') { + callback = labelsOrCallbackOrOptions; + } + else if (typeof labelsOrCallbackOrOptions === 'string') { + labels = [labelsOrCallbackOrOptions]; + } + else if (Array.isArray(labelsOrCallbackOrOptions)) { + labels = labelsOrCallbackOrOptions; + } + else if (labelsOrCallbackOrOptions) { + options = labelsOrCallbackOrOptions; + } + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + const deleteLabels = (labels) => { + const nullLabelMap = labels.reduce((nullLabelMap, labelKey) => { + nullLabelMap[labelKey] = null; + return nullLabelMap; + }, {}); + if ((options === null || options === void 0 ? void 0 : options.ifMetagenerationMatch) !== undefined) { + this.setLabels(nullLabelMap, options, callback); + } + else { + this.setLabels(nullLabelMap, callback); + } + }; + if (labels.length === 0) { + this.getLabels((err, labels) => { + if (err) { + callback(err); + return; + } + deleteLabels(Object.keys(labels)); + }); + } + else { + deleteLabels(labels); + } + } + /** + * @typedef {array} DisableRequesterPaysResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DisableRequesterPaysCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + *

+ * Early Access Testers Only + *

+ * This feature is not yet widely-available. + *

+ *
+ * + * Disable `requesterPays` functionality from this bucket. + * + * @param {DisableRequesterPaysCallback} [callback] Callback function. + * @param {DisableRequesterPaysOptions} [options] Options, including precondition options + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.disableRequesterPays(function(err, apiResponse) { + * if (!err) { + * // requesterPays functionality disabled successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.disableRequesterPays().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/requesterPays.js + * region_tag:storage_disable_requester_pays + * Example of disabling requester pays: + */ + disableRequesterPays(optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.setMetadata({ + billing: { + requesterPays: false, + }, + }, options, callback); + } + /** + * Configuration object for enabling logging. + * + * @typedef {object} EnableLoggingOptions + * @property {string|Bucket} [bucket] The bucket for the log entries. By + * default, the current bucket is used. + * @property {string} prefix A unique prefix for log object names. + */ + /** + * Enable logging functionality for this bucket. This will make two API + * requests, first to grant Cloud Storage WRITE permission to the bucket, then + * to set the appropriate configuration on the Bucket's metadata. + * + * @param {EnableLoggingOptions} config Configuration options. + * @param {string|Bucket} [config.bucket] The bucket for the log entries. By + * default, the current bucket is used. + * @param {string} config.prefix A unique prefix for log object names. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * const config = { + * prefix: 'log' + * }; + * + * bucket.enableLogging(config, function(err, apiResponse) { + * if (!err) { + * // Logging functionality enabled successfully. + * } + * }); + * + * ``` + * @example + * Optionally, provide a destination bucket. + * ``` + * const config = { + * prefix: 'log', + * bucket: 'destination-bucket' + * }; + * + * bucket.enableLogging(config, function(err, apiResponse) {}); + * ``` + * + * @example + * If the callback is omitted, we'll return a Promise. + * ``` + * bucket.enableLogging(config).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + enableLogging(config, callback) { + if (!config || + typeof config === 'function' || + typeof config.prefix === 'undefined') { + throw new Error(BucketExceptionMessages.CONFIGURATION_OBJECT_PREFIX_REQUIRED); + } + let logBucket = this.id; + if (config.bucket && config.bucket instanceof Bucket) { + logBucket = config.bucket.id; + } + else if (config.bucket && typeof config.bucket === 'string') { + logBucket = config.bucket; + } + const options = {}; + if (config === null || config === void 0 ? void 0 : config.ifMetagenerationMatch) { + options.ifMetagenerationMatch = config.ifMetagenerationMatch; + } + if (config === null || config === void 0 ? void 0 : config.ifMetagenerationNotMatch) { + options.ifMetagenerationNotMatch = config.ifMetagenerationNotMatch; + } + (async () => { + try { + const [policy] = await this.iam.getPolicy(); + policy.bindings.push({ + members: ['group:cloud-storage-analytics@google.com'], + role: 'roles/storage.objectCreator', + }); + await this.iam.setPolicy(policy); + this.setMetadata({ + logging: { + logBucket, + logObjectPrefix: config.prefix, + }, + }, options, callback); + } + catch (e) { + callback(e); + return; + } + })(); + } + /** + * @typedef {array} EnableRequesterPaysResponse + * @property {object} 0 The full API response. + */ + /** + * @callback EnableRequesterPaysCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + *
+ * Early Access Testers Only + *

+ * This feature is not yet widely-available. + *

+ *
+ * + * Enable `requesterPays` functionality for this bucket. This enables you, the + * bucket owner, to have the requesting user assume the charges for the access + * to your bucket and its contents. + * + * @param {EnableRequesterPaysCallback | EnableRequesterPaysOptions} [optionsOrCallback] + * Callback function or precondition options. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.enableRequesterPays(function(err, apiResponse) { + * if (!err) { + * // requesterPays functionality enabled successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.enableRequesterPays().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/requesterPays.js + * region_tag:storage_enable_requester_pays + * Example of enabling requester pays: + */ + enableRequesterPays(optionsOrCallback, cb) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + cb = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.setMetadata({ + billing: { + requesterPays: true, + }, + }, options, cb); + } + /** + * Create a {@link File} object. See {@link File} to see how to handle + * the different use cases you may have. + * + * @param {string} name The name of the file in this bucket. + * @param {FileOptions} [options] Configuration options. + * @param {string|number} [options.generation] Only use a specific revision of + * this file. + * @param {string} [options.encryptionKey] A custom encryption key. See + * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}. + * @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will + * be used to encrypt the object. Must be in the format: + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`. + * KMS key ring must use the same location as the bucket. + * @param {string} [options.userProject] The ID of the project which will be + * billed for all requests made from File object. + * @returns {File} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const file = bucket.file('my-existing-file.png'); + * ``` + */ + file(name, options) { + if (!name) { + throw Error(BucketExceptionMessages.SPECIFY_FILE_NAME); + } + return new file_js_1.File(this, name, options); + } + /** + * @typedef {array} GetFilesResponse + * @property {File[]} 0 Array of {@link File} instances. + * @param {object} nextQuery 1 A query object to receive more results. + * @param {object} apiResponse 2 The full API response. + */ + /** + * @callback GetFilesCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files Array of {@link File} instances. + * @param {object} nextQuery A query object to receive more results. + * @param {object} apiResponse The full API response. + */ + /** + * Query object for listing files. + * + * @typedef {object} GetFilesOptions + * @property {boolean} [autoPaginate=true] Have pagination handled + * automatically. + * @property {string} [delimiter] Results will contain only objects whose + * names, aside from the prefix, do not contain delimiter. Objects whose + * names, aside from the prefix, contain delimiter will have their name + * truncated after the delimiter, returned in `apiResponse.prefixes`. + * Duplicate prefixes are omitted. + * @property {string} [endOffset] Filter results to objects whose names are + * lexicographically before endOffset. If startOffset is also set, the objects + * listed have names between startOffset (inclusive) and endOffset (exclusive). + * @property {boolean} [includeFoldersAsPrefixes] If true, includes folders and + * managed folders in the set of prefixes returned by the query. Only applicable if + * delimiter is set to / and autoPaginate is set to false. + * See: https://cloud.google.com/storage/docs/managed-folders + * @property {boolean} [includeTrailingDelimiter] If true, objects that end in + * exactly one instance of delimiter have their metadata included in items[] + * in addition to the relevant part of the object name appearing in prefixes[]. + * @property {string} [prefix] Filter results to objects whose names begin + * with this prefix. + * @property {string} [matchGlob] A glob pattern used to filter results, + * for example foo*bar + * @property {number} [maxApiCalls] Maximum number of API calls to make. + * @property {number} [maxResults] Maximum number of items plus prefixes to + * return per call. + * Note: By default will handle pagination automatically + * if more than 1 page worth of results are requested per call. + * When `autoPaginate` is set to `false` the smaller of `maxResults` + * or 1 page of results will be returned per call. + * @property {string} [pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @property {boolean} [softDeleted] If true, only soft-deleted object versions will be + * listed as distinct results in order of generation number. Note `soft_deleted` and + * `versions` cannot be set to true simultaneously. + * @property {string} [startOffset] Filter results to objects whose names are + * lexicographically equal to or after startOffset. If endOffset is also set, + * the objects listed have names between startOffset (inclusive) and endOffset (exclusive). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {boolean} [versions] If true, returns File objects scoped to + * their versions. + */ + /** + * Get {@link File} objects for the files currently in the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/list| Objects: list API Documentation} + * + * @param {GetFilesOptions} [query] Query object for listing files. + * @param {boolean} [query.autoPaginate=true] Have pagination handled + * automatically. + * @param {string} [query.delimiter] Results will contain only objects whose + * names, aside from the prefix, do not contain delimiter. Objects whose + * names, aside from the prefix, contain delimiter will have their name + * truncated after the delimiter, returned in `apiResponse.prefixes`. + * Duplicate prefixes are omitted. + * @param {string} [query.endOffset] Filter results to objects whose names are + * lexicographically before endOffset. If startOffset is also set, the objects + * listed have names between startOffset (inclusive) and endOffset (exclusive). + * @param {boolean} [query.includeFoldersAsPrefixes] If true, includes folders and + * managed folders in the set of prefixes returned by the query. Only applicable if + * delimiter is set to / and autoPaginate is set to false. + * See: https://cloud.google.com/storage/docs/managed-folders + * @param {boolean} [query.includeTrailingDelimiter] If true, objects that end in + * exactly one instance of delimiter have their metadata included in items[] + * in addition to the relevant part of the object name appearing in prefixes[]. + * @param {string} [query.prefix] Filter results to objects whose names begin + * with this prefix. + * @param {number} [query.maxApiCalls] Maximum number of API calls to make. + * @param {number} [query.maxResults] Maximum number of items plus prefixes to + * return per call. + * Note: By default will handle pagination automatically + * if more than 1 page worth of results are requested per call. + * When `autoPaginate` is set to `false` the smaller of `maxResults` + * or 1 page of results will be returned per call. + * @param {string} [query.pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @param {boolean} [query.softDeleted] If true, only soft-deleted object versions will be + * listed as distinct results in order of generation number. Note `soft_deleted` and + * `versions` cannot be set to true simultaneously. + * @param {string} [query.startOffset] Filter results to objects whose names are + * lexicographically equal to or after startOffset. If endOffset is also set, + * the objects listed have names between startOffset (inclusive) and endOffset (exclusive). + * @param {string} [query.userProject] The ID of the project which will be + * billed for the request. + * @param {boolean} [query.versions] If true, returns File objects scoped to + * their versions. + * @param {GetFilesCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getFiles(function(err, files) { + * if (!err) { + * // files is an array of File objects. + * } + * }); + * + * //- + * // If your bucket has versioning enabled, you can get all of your files + * // scoped to their generation. + * //- + * bucket.getFiles({ + * versions: true + * }, function(err, files) { + * // Each file is scoped to its generation. + * }); + * + * //- + * // To control how many API requests are made and page through the results + * // manually, set `autoPaginate` to `false`. + * //- + * const callback = function(err, files, nextQuery, apiResponse) { + * if (nextQuery) { + * // More results exist. + * bucket.getFiles(nextQuery, callback); + * } + * + * // The `metadata` property is populated for you with the metadata at the + * // time of fetching. + * files[0].metadata; + * + * // However, in cases where you are concerned the metadata could have + * // changed, use the `getMetadata` method. + * files[0].getMetadata(function(err, metadata) {}); + * }; + * + * bucket.getFiles({ + * autoPaginate: false + * }, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getFiles().then(function(data) { + * const files = data[0]; + * }); + * + * ``` + * @example + *
Simulating a File System

With `autoPaginate: false`, it's possible to iterate over files which incorporate a common structure using a delimiter.

Consider the following remote objects:

  1. "a"
  2. "a/b/c/d"
  3. "b/d/e"

Using a delimiter of `/` will return a single file, "a".

`apiResponse.prefixes` will return the "sub-directories" that were found:

  1. "a/"
  2. "b/"
+ * ``` + * bucket.getFiles({ + * autoPaginate: false, + * delimiter: '/' + * }, function(err, files, nextQuery, apiResponse) { + * // files = [ + * // {File} // File object for file "a" + * // ] + * + * // apiResponse.prefixes = [ + * // 'a/', + * // 'b/' + * // ] + * }); + * ``` + * + * @example + * Using prefixes, it's now possible to simulate a file system with follow-up requests. + * ``` + * bucket.getFiles({ + * autoPaginate: false, + * delimiter: '/', + * prefix: 'a/' + * }, function(err, files, nextQuery, apiResponse) { + * // No files found within "directory" a. + * // files = [] + * + * // However, a "sub-directory" was found. + * // This prefix can be used to continue traversing the "file system". + * // apiResponse.prefixes = [ + * // 'a/b/' + * // ] + * }); + * ``` + * + * @example include:samples/files.js + * region_tag:storage_list_files + * Another example: + * + * @example include:samples/files.js + * region_tag:storage_list_files_with_prefix + * Example of listing files, filtered by a prefix: + */ + getFiles(queryOrCallback, callback) { + let query = typeof queryOrCallback === 'object' ? queryOrCallback : {}; + if (!callback) { + callback = queryOrCallback; + } + query = Object.assign({}, query); + if (query.fields && + query.autoPaginate && + !query.fields.includes('nextPageToken')) { + query.fields = `${query.fields},nextPageToken`; + } + this.request({ + uri: '/o', + qs: query, + }, (err, resp) => { + if (err) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback(err, null, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const files = itemsArray.map((file) => { + const options = {}; + if (query.fields) { + const fileInstance = file; + return fileInstance; + } + if (query.versions) { + options.generation = file.generation; + } + if (file.kmsKeyName) { + options.kmsKeyName = file.kmsKeyName; + } + const fileInstance = this.file(file.name, options); + fileInstance.metadata = file; + return fileInstance; + }); + let nextQuery = null; + if (resp.nextPageToken) { + nextQuery = Object.assign({}, query, { + pageToken: resp.nextPageToken, + }); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback(null, files, nextQuery, resp); + }); + } + /** + * @deprecated + * @typedef {object} GetLabelsOptions Configuration options for Bucket#getLabels(). + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @deprecated + * @typedef {array} GetLabelsResponse + * @property {object} 0 Object of labels currently set on this bucket. + */ + /** + * @deprecated + * @callback GetLabelsCallback + * @param {?Error} err Request error, if any. + * @param {object} labels Object of labels currently set on this bucket. + */ + /** + * @deprecated Use getMetadata directly. + * Get the labels currently set on this bucket. + * + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetLabelsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.getLabels(function(err, labels) { + * if (err) { + * // Error handling omitted. + * } + * + * // labels = { + * // label: 'labelValue', + * // ... + * // } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getLabels().then(function(data) { + * const labels = data[0]; + * }); + * ``` + */ + getLabels(optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.getMetadata(options, (err, metadata) => { + if (err) { + callback(err, null); + return; + } + callback(null, (metadata === null || metadata === void 0 ? void 0 : metadata.labels) || {}); + }); + } + /** + * @typedef {object} GetNotificationsOptions Configuration options for Bucket#getNotification(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback GetNotificationsCallback + * @param {?Error} err Request error, if any. + * @param {Notification[]} notifications Array of {@link Notification} + * instances. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} GetNotificationsResponse + * @property {Notification[]} 0 Array of {@link Notification} instances. + * @property {object} 1 The full API response. + */ + /** + * Retrieves a list of notification subscriptions for a given bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/list| Notifications: list} + * + * @param {GetNotificationsOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetNotificationsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * bucket.getNotifications(function(err, notifications, apiResponse) { + * if (!err) { + * // notifications is an array of Notification objects. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getNotifications().then(function(data) { + * const notifications = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/listNotifications.js + * region_tag:storage_list_bucket_notifications + * Another example: + */ + getNotifications(optionsOrCallback, callback) { + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = optionsOrCallback; + } + this.request({ + uri: '/notificationConfigs', + qs: options, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const notifications = itemsArray.map((notification) => { + const notificationInstance = this.notification(notification.id); + notificationInstance.metadata = notification; + return notificationInstance; + }); + callback(null, notifications, resp); + }); + } + /** + * @typedef {array} GetSignedUrlResponse + * @property {object} 0 The signed URL. + */ + /** + * @callback GetSignedUrlCallback + * @param {?Error} err Request error, if any. + * @param {object} url The signed URL. + */ + /** + * @typedef {object} GetBucketSignedUrlConfig + * @property {string} action Only listing objects within a bucket (HTTP: GET) is supported for bucket-level signed URLs. + * @property {*} expires A timestamp when this link will expire. Any value + * given is passed to `new Date()`. + * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now. + * @property {string} [version='v2'] The signing version to use, either + * 'v2' or 'v4'. + * @property {boolean} [virtualHostedStyle=false] Use virtual hosted-style + * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style + * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instaed of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @property {string} [cname] The cname for this bucket, i.e., + * "https://cdn.example.com". + * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example} + * @property {object} [extensionHeaders] If these headers are used, the + * server will check to make sure that the client provides matching + * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers} + * for the requirements of this feature, most notably: + * - The header name must be prefixed with `x-goog-` + * - The header name must be all lowercase + * + * Note: Multi-valued header passed as an array in the extensionHeaders + * object is converted into a string, delimited by `,` with + * no space. Requests made using the signed URL will need to + * delimit multi-valued headers using a single `,` as well, or + * else the server will report a mismatched signature. + * @property {object} [queryParams] Additional query parameters to include + * in the signed URL. + */ + /** + * Get a signed URL to allow limited time access to a bucket. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed URL. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/access-control/signed-urls| Signed URLs Reference} + * + * @throws {Error} if an expiration timestamp from the past is given. + * + * @param {GetBucketSignedUrlConfig} config Configuration object. + * @param {string} config.action Currently only supports "list" (HTTP: GET). + * @param {*} config.expires A timestamp when this link will expire. Any value + * given is passed to `new Date()`. + * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now. + * @param {string} [config.version='v2'] The signing version to use, either + * 'v2' or 'v4'. + * @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style + * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style + * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instaed of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @param {string} [config.cname] The cname for this bucket, i.e., + * "https://cdn.example.com". + * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example} + * @param {object} [config.extensionHeaders] If these headers are used, the + * server will check to make sure that the client provides matching + * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers} + * for the requirements of this feature, most notably: + * - The header name must be prefixed with `x-goog-` + * - The header name must be all lowercase + * + * Note: Multi-valued header passed as an array in the extensionHeaders + * object is converted into a string, delimited by `,` with + * no space. Requests made using the signed URL will need to + * delimit multi-valued headers using a single `,` as well, or + * else the server will report a mismatched signature. + * @property {object} [config.queryParams] Additional query parameters to include + * in the signed URL. + * @param {GetSignedUrlCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * //- + * // Generate a URL that allows temporary access to list files in a bucket. + * //- + * const request = require('request'); + * + * const config = { + * action: 'list', + * expires: '03-17-2025' + * }; + * + * bucket.getSignedUrl(config, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The bucket is now available to be listed from this URL. + * request(url, function(err, resp) { + * // resp.statusCode = 200 + * }); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.getSignedUrl(config).then(function(data) { + * const url = data[0]; + * }); + * ``` + */ + getSignedUrl(cfg, callback) { + const method = BucketActionToHTTPMethod[cfg.action]; + const signConfig = { + method, + expires: cfg.expires, + version: cfg.version, + cname: cfg.cname, + extensionHeaders: cfg.extensionHeaders || {}, + queryParams: cfg.queryParams || {}, + host: cfg.host, + signingEndpoint: cfg.signingEndpoint, + }; + if (!this.signer) { + this.signer = new signer_js_1.URLSigner(this.storage.authClient, this, undefined, this.storage); + } + this.signer + .getSignedUrl(signConfig) + .then(signedUrl => callback(null, signedUrl), callback); + } + /** + * @callback BucketLockCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Lock a previously-defined retention policy. This will prevent changes to + * the policy. + * + * @throws {Error} if a metageneration is not provided. + * + * @param {number|string} metageneration The bucket's metageneration. This is + * accesssible from calling {@link File#getMetadata}. + * @param {BucketLockCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * const metageneration = 2; + * + * bucket.lock(metageneration, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.lock(metageneration).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + lock(metageneration, callback) { + const metatype = typeof metageneration; + if (metatype !== 'number' && metatype !== 'string') { + throw new Error(BucketExceptionMessages.METAGENERATION_NOT_PROVIDED); + } + this.request({ + method: 'POST', + uri: '/lockRetentionPolicy', + qs: { + ifMetagenerationMatch: metageneration, + }, + }, callback); + } + /** + * @typedef {object} RestoreOptions Options for Bucket#restore(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/restore#resource| Object resource}. + * @param {number} [generation] If present, selects a specific revision of this object. + * @param {string} [projection] Specifies the set of properties to return. If used, must be 'full' or 'noAcl'. + */ + /** + * Restores a soft-deleted bucket + * @param {RestoreOptions} options Restore options. + * @returns {Promise} + */ + async restore(options) { + const [bucket] = await this.request({ + method: 'POST', + uri: '/restore', + qs: options, + }); + return bucket; + } + /** + * @typedef {array} MakeBucketPrivateResponse + * @property {File[]} 0 List of files made private. + */ + /** + * @callback MakeBucketPrivateCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files List of files made private. + */ + /** + * @typedef {object} MakeBucketPrivateOptions + * @property {boolean} [includeFiles=false] Make each file in the bucket + * private. + * @property {Metadata} [metadata] Define custom metadata properties to define + * along with the operation. + * @property {boolean} [force] Queue errors occurred while making files + * private until all files have been processed. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Make the bucket listing private. + * + * You may also choose to make the contents of the bucket private by + * specifying `includeFiles: true`. This will automatically run + * {@link File#makePrivate} for every file in the bucket. + * + * When specifying `includeFiles: true`, use `force: true` to delay execution + * of your callback until all files have been processed. By default, the + * callback is executed after the first error. Use `force` to queue such + * errors until all files have been processed, after which they will be + * returned as an array as the first argument to your callback. + * + * NOTE: This may cause the process to be long-running and use a high number + * of requests. Use with caution. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @param {MakeBucketPrivateOptions} [options] Configuration options. + * @param {boolean} [options.includeFiles=false] Make each file in the bucket + * private. + * @param {Metadata} [options.metadata] Define custom metadata properties to define + * along with the operation. + * @param {boolean} [options.force] Queue errors occurred while making files + * private until all files have been processed. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {MakeBucketPrivateCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Make the bucket private. + * //- + * bucket.makePrivate(function(err) {}); + * + * //- + * // Make the bucket and its contents private. + * //- + * const opts = { + * includeFiles: true + * }; + * + * bucket.makePrivate(opts, function(err, files) { + * // `err`: + * // The first error to occur, otherwise null. + * // + * // `files`: + * // Array of files successfully made private in the bucket. + * }); + * + * //- + * // Make the bucket and its contents private, using force to suppress errors + * // until all files have been processed. + * //- + * const opts = { + * includeFiles: true, + * force: true + * }; + * + * bucket.makePrivate(opts, function(errors, files) { + * // `errors`: + * // Array of errors if any occurred, otherwise null. + * // + * // `files`: + * // Array of files successfully made private in the bucket. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.makePrivate(opts).then(function(data) { + * const files = data[0]; + * }); + * ``` + */ + makePrivate(optionsOrCallback, callback) { + var _a, _b, _c, _d; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + options.private = true; + const query = { + predefinedAcl: 'projectPrivate', + }; + if (options.userProject) { + query.userProject = options.userProject; + } + if ((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) { + query.ifGenerationMatch = options.preconditionOpts.ifGenerationMatch; + } + if ((_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationNotMatch) { + query.ifGenerationNotMatch = + options.preconditionOpts.ifGenerationNotMatch; + } + if ((_c = options.preconditionOpts) === null || _c === void 0 ? void 0 : _c.ifMetagenerationMatch) { + query.ifMetagenerationMatch = + options.preconditionOpts.ifMetagenerationMatch; + } + if ((_d = options.preconditionOpts) === null || _d === void 0 ? void 0 : _d.ifMetagenerationNotMatch) { + query.ifMetagenerationNotMatch = + options.preconditionOpts.ifMetagenerationNotMatch; + } + // You aren't allowed to set both predefinedAcl & acl properties on a bucket + // so acl must explicitly be nullified. + const metadata = { ...options.metadata, acl: null }; + this.setMetadata(metadata, query, (err) => { + if (err) { + callback(err); + } + const internalCall = () => { + if (options.includeFiles) { + return (0, util_1.promisify)(this.makeAllFilesPublicPrivate_).call(this, options); + } + return Promise.resolve([]); + }; + internalCall() + .then(files => callback(null, files)) + .catch(callback); + }); + } + /** + * @typedef {object} MakeBucketPublicOptions + * @property {boolean} [includeFiles=false] Make each file in the bucket + * private. + * @property {boolean} [force] Queue errors occurred while making files + * private until all files have been processed. + */ + /** + * @callback MakeBucketPublicCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files List of files made public. + */ + /** + * @typedef {array} MakeBucketPublicResponse + * @property {File[]} 0 List of files made public. + */ + /** + * Make the bucket publicly readable. + * + * You may also choose to make the contents of the bucket publicly readable by + * specifying `includeFiles: true`. This will automatically run + * {@link File#makePublic} for every file in the bucket. + * + * When specifying `includeFiles: true`, use `force: true` to delay execution + * of your callback until all files have been processed. By default, the + * callback is executed after the first error. Use `force` to queue such + * errors until all files have been processed, after which they will be + * returned as an array as the first argument to your callback. + * + * NOTE: This may cause the process to be long-running and use a high number + * of requests. Use with caution. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/patch| Buckets: patch API Documentation} + * + * @param {MakeBucketPublicOptions} [options] Configuration options. + * @param {boolean} [options.includeFiles=false] Make each file in the bucket + * private. + * @param {boolean} [options.force] Queue errors occurred while making files + * private until all files have been processed. + * @param {MakeBucketPublicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Make the bucket publicly readable. + * //- + * bucket.makePublic(function(err) {}); + * + * //- + * // Make the bucket and its contents publicly readable. + * //- + * const opts = { + * includeFiles: true + * }; + * + * bucket.makePublic(opts, function(err, files) { + * // `err`: + * // The first error to occur, otherwise null. + * // + * // `files`: + * // Array of files successfully made public in the bucket. + * }); + * + * //- + * // Make the bucket and its contents publicly readable, using force to + * // suppress errors until all files have been processed. + * //- + * const opts = { + * includeFiles: true, + * force: true + * }; + * + * bucket.makePublic(opts, function(errors, files) { + * // `errors`: + * // Array of errors if any occurred, otherwise null. + * // + * // `files`: + * // Array of files successfully made public in the bucket. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.makePublic(opts).then(function(data) { + * const files = data[0]; + * }); + * ``` + */ + makePublic(optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const req = { public: true, ...options }; + this.acl + .add({ + entity: 'allUsers', + role: 'READER', + }) + .then(() => { + return this.acl.default.add({ + entity: 'allUsers', + role: 'READER', + }); + }) + .then(() => { + if (req.includeFiles) { + return (0, util_1.promisify)(this.makeAllFilesPublicPrivate_).call(this, req); + } + return []; + }) + .then(files => callback(null, files), callback); + } + /** + * Get a reference to a Cloud Pub/Sub Notification. + * + * @param {string} id ID of notification. + * @returns {Notification} + * @see Notification + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const notification = bucket.notification('1'); + * ``` + */ + notification(id) { + if (!id) { + throw new Error(BucketExceptionMessages.SUPPLY_NOTIFICATION_ID); + } + return new notification_js_1.Notification(this, id); + } + /** + * Remove an already-existing retention policy from this bucket, if it is not + * locked. + * + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @param {SetBucketMetadataOptions} [options] Options, including precondition options + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * bucket.removeRetentionPeriod(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.removeRetentionPeriod().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + removeRetentionPeriod(optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + this.setMetadata({ + retentionPolicy: null, + }, options, callback); + } + /** + * Makes request and applies userProject query parameter if necessary. + * + * @private + * + * @param {object} reqOpts - The request options. + * @param {function} callback - The callback function. + */ + request(reqOpts, callback) { + if (this.userProject && (!reqOpts.qs || !reqOpts.qs.userProject)) { + reqOpts.qs = { ...reqOpts.qs, userProject: this.userProject }; + } + return super.request(reqOpts, callback); + } + /** + * @deprecated + * @typedef {array} SetLabelsResponse + * @property {object} 0 The bucket metadata. + */ + /** + * @deprecated + * @callback SetLabelsCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The bucket metadata. + */ + /** + * @deprecated + * @typedef {object} SetLabelsOptions Configuration options for Bucket#setLabels(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @deprecated Use setMetadata directly. + * Set labels on the bucket. + * + * This makes an underlying call to {@link Bucket#setMetadata}, which + * is a PATCH request. This means an individual label can be overwritten, but + * unmentioned labels will not be touched. + * + * @param {object} labels Labels to set on the bucket. + * @param {SetLabelsOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {SetLabelsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * const labels = { + * labelone: 'labelonevalue', + * labeltwo: 'labeltwovalue' + * }; + * + * bucket.setLabels(labels, function(err, metadata) { + * if (!err) { + * // Labels set successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setLabels(labels).then(function(data) { + * const metadata = data[0]; + * }); + * ``` + */ + setLabels(labels, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + callback = callback || index_js_1.util.noop; + this.setMetadata({ labels }, options, callback); + } + setMetadata(metadata, optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, AvailableServiceObjectMethods.setMetadata, options); + super + .setMetadata(metadata, options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } + /** + * Lock all objects contained in the bucket, based on their creation time. Any + * attempt to overwrite or delete objects younger than the retention period + * will result in a `PERMISSION_DENIED` error. + * + * An unlocked retention policy can be modified or removed from the bucket via + * {@link File#removeRetentionPeriod} and {@link File#setRetentionPeriod}. A + * locked retention policy cannot be removed or shortened in duration for the + * lifetime of the bucket. Attempting to remove or decrease period of a locked + * retention policy will result in a `PERMISSION_DENIED` error. You can still + * increase the policy. + * + * @param {*} duration In seconds, the minimum retention time for all objects + * contained in this bucket. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @param {SetBucketMetadataCallback} [options] Options, including precondition options. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * const DURATION_SECONDS = 15780000; // 6 months. + * + * //- + * // Lock the objects in this bucket for 6 months. + * //- + * bucket.setRetentionPeriod(DURATION_SECONDS, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setRetentionPeriod(DURATION_SECONDS).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setRetentionPeriod(duration, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + this.setMetadata({ + retentionPolicy: { + retentionPeriod: duration.toString(), + }, + }, options, callback); + } + /** + * + * @typedef {object} Cors + * @property {number} [maxAgeSeconds] The number of seconds the browser is + * allowed to make requests before it must repeat the preflight request. + * @property {string[]} [method] HTTP method allowed for cross origin resource + * sharing with this bucket. + * @property {string[]} [origin] an origin allowed for cross origin resource + * sharing with this bucket. + * @property {string[]} [responseHeader] A header allowed for cross origin + * resource sharing with this bucket. + */ + /** + * This can be used to set the CORS configuration on the bucket. + * + * The configuration will be overwritten with the value passed into this. + * + * @param {Cors[]} corsConfiguration The new CORS configuration to set + * @param {number} [corsConfiguration.maxAgeSeconds] The number of seconds the browser is + * allowed to make requests before it must repeat the preflight request. + * @param {string[]} [corsConfiguration.method] HTTP method allowed for cross origin resource + * sharing with this bucket. + * @param {string[]} [corsConfiguration.origin] an origin allowed for cross origin resource + * sharing with this bucket. + * @param {string[]} [corsConfiguration.responseHeader] A header allowed for cross origin + * resource sharing with this bucket. + * @param {SetBucketMetadataCallback} [callback] Callback function. + * @param {SetBucketMetadataOptions} [options] Options, including precondition options. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const bucket = storage.bucket('albums'); + * + * const corsConfiguration = [{maxAgeSeconds: 3600}]; // 1 hour + * bucket.setCorsConfiguration(corsConfiguration); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setCorsConfiguration(corsConfiguration).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setCorsConfiguration(corsConfiguration, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + this.setMetadata({ + cors: corsConfiguration, + }, options, callback); + } + /** + * @typedef {object} SetBucketStorageClassOptions + * @property {string} [userProject] - The ID of the project which will be + * billed for the request. + */ + /** + * @callback SetBucketStorageClassCallback + * @param {?Error} err Request error, if any. + */ + /** + * Set the default storage class for new files in this bucket. + * + * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes} + * + * @param {string} storageClass The new storage class. (`standard`, + * `nearline`, `coldline`, or `archive`). + * **Note:** The storage classes `multi_regional`, `regional`, and + * `durable_reduced_availability` are now legacy and will be deprecated in + * the future. + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] - The ID of the project which will be + * billed for the request. + * @param {SetStorageClassCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.setStorageClass('nearline', function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * // The storage class was updated successfully. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.setStorageClass('nearline').then(function() {}); + * ``` + */ + setStorageClass(storageClass, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + // In case we get input like `storageClass`, convert to `storage_class`. + storageClass = storageClass + .replace(/-/g, '_') + .replace(/([a-z])([A-Z])/g, (_, low, up) => { + return low + '_' + up; + }) + .toUpperCase(); + this.setMetadata({ storageClass }, options, callback); + } + /** + * Set a user project to be billed for all requests made from this Bucket + * object and any files referenced from this Bucket object. + * + * @param {string} userProject The user project. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * bucket.setUserProject('grape-spaceship-123'); + * ``` + */ + setUserProject(userProject) { + this.userProject = userProject; + const methods = [ + 'create', + 'delete', + 'exists', + 'get', + 'getMetadata', + 'setMetadata', + ]; + methods.forEach(method => { + const methodConfig = this.methods[method]; + if (typeof methodConfig === 'object') { + if (typeof methodConfig.reqOpts === 'object') { + Object.assign(methodConfig.reqOpts.qs, { userProject }); + } + else { + methodConfig.reqOpts = { + qs: { userProject }, + }; + } + } + }); + } + /** + * @typedef {object} UploadOptions Configuration options for Bucket#upload(). + * @property {string|File} [destination] The place to save + * your file. If given a string, the file will be uploaded to the bucket + * using the string as a filename. When given a File object, your local + * file will be uploaded to the File object's bucket and under the File + * object's name. Lastly, when this argument is omitted, the file is uploaded + * to your bucket using the name of the local file. + * @property {string} [encryptionKey] A custom encryption key. See + * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}. + * @property {boolean} [gzip] Automatically gzip the file. This will set + * `options.metadata.contentEncoding` to `gzip`. + * @property {string} [kmsKeyName] The name of the Cloud KMS key that will + * be used to encrypt the object. Must be in the format: + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`. + * @property {object} [metadata] See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body}. + * @property {string} [offset] The starting byte of the upload stream, for + * resuming an interrupted upload. Defaults to 0. + * @property {string} [predefinedAcl] Apply a predefined set of access + * controls to this object. + * + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @property {boolean} [private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @property {boolean} [public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @property {boolean} [resumable=true] Resumable uploads are automatically + * enabled and must be shut off explicitly by setting to false. + * @property {number} [timeout=60000] Set the HTTP request timeout in + * milliseconds. This option is not available for resumable uploads. + * Default: `60000` + * @property {string} [uri] The URI for an already-created resumable + * upload. See {@link File#createResumableUpload}. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string|boolean} [validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with an + * MD5 checksum for maximum reliability. CRC32c will provide better + * performance with less reliability. You may also choose to skip + * validation completely, however this is **not recommended**. + */ + /** + * @typedef {array} UploadResponse + * @property {object} 0 The uploaded {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback UploadCallback + * @param {?Error} err Request error, if any. + * @param {object} file The uploaded {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * Upload a file to the bucket. This is a convenience method that wraps + * {@link File#createWriteStream}. + * + * Resumable uploads are enabled by default + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload#uploads| Upload Options (Simple or Resumable)} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert| Objects: insert API Documentation} + * + * @param {string} pathString The fully qualified path to the file you + * wish to upload to your bucket. + * @param {UploadOptions} [options] Configuration options. + * @param {string|File} [options.destination] The place to save + * your file. If given a string, the file will be uploaded to the bucket + * using the string as a filename. When given a File object, your local + * file will be uploaded to the File object's bucket and under the File + * object's name. Lastly, when this argument is omitted, the file is uploaded + * to your bucket using the name of the local file. + * @param {string} [options.encryptionKey] A custom encryption key. See + * {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys}. + * @param {boolean} [options.gzip] Automatically gzip the file. This will set + * `options.metadata.contentEncoding` to `gzip`. + * @param {string} [options.kmsKeyName] The name of the Cloud KMS key that will + * be used to encrypt the object. Must be in the format: + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`. + * @param {object} [options.metadata] See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body}. + * @param {string} [options.offset] The starting byte of the upload stream, for + * resuming an interrupted upload. Defaults to 0. + * @param {string} [options.predefinedAcl] Apply a predefined set of access + * controls to this object. + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @param {boolean} [options.private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @param {boolean} [options.public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @param {boolean} [options.resumable=true] Resumable uploads are automatically + * enabled and must be shut off explicitly by setting to false. + * @param {number} [options.timeout=60000] Set the HTTP request timeout in + * milliseconds. This option is not available for resumable uploads. + * Default: `60000` + * @param {string} [options.uri] The URI for an already-created resumable + * upload. See {@link File#createResumableUpload}. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {string|boolean} [options.validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with an + * MD5 checksum for maximum reliability. CRC32c will provide better + * performance with less reliability. You may also choose to skip + * validation completely, however this is **not recommended**. + * @param {UploadCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * + * //- + * // Upload a file from a local path. + * //- + * bucket.upload('/local/path/image.png', function(err, file, apiResponse) { + * // Your bucket now contains: + * // - "image.png" (with the contents of `/local/path/image.png') + * + * // `file` is an instance of a File object that refers to your new file. + * }); + * + * + * //- + * // It's not always that easy. You will likely want to specify the filename + * // used when your new file lands in your bucket. + * // + * // You may also want to set metadata or customize other options. + * //- + * const options = { + * destination: 'new-image.png', + * validation: 'crc32c', + * metadata: { + * metadata: { + * event: 'Fall trip to the zoo' + * } + * } + * }; + * + * bucket.upload('local-image.png', options, function(err, file) { + * // Your bucket now contains: + * // - "new-image.png" (with the contents of `local-image.png') + * + * // `file` is an instance of a File object that refers to your new file. + * }); + * + * //- + * // You can also have a file gzip'd on the fly. + * //- + * bucket.upload('index.html', { gzip: true }, function(err, file) { + * // Your bucket now contains: + * // - "index.html" (automatically compressed with gzip) + * + * // Downloading the file with `file.download` will automatically decode + * the + * // file. + * }); + * + * //- + * // You may also re-use a File object, {File}, that references + * // the file you wish to create or overwrite. + * //- + * const options = { + * destination: bucket.file('existing-file.png'), + * resumable: false + * }; + * + * bucket.upload('local-img.png', options, function(err, newFile) { + * // Your bucket now contains: + * // - "existing-file.png" (with the contents of `local-img.png') + * + * // Note: + * // The `newFile` parameter is equal to `file`. + * }); + * + * //- + * // To use + * // + * // Customer-supplied Encryption Keys, provide the `encryptionKey` + * option. + * //- + * const crypto = require('crypto'); + * const encryptionKey = crypto.randomBytes(32); + * + * bucket.upload('img.png', { + * encryptionKey: encryptionKey + * }, function(err, newFile) { + * // `img.png` was uploaded with your custom encryption key. + * + * // `newFile` is already configured to use the encryption key when making + * // operations on the remote object. + * + * // However, to use your encryption key later, you must create a `File` + * // instance with the `key` supplied: + * const file = bucket.file('img.png', { + * encryptionKey: encryptionKey + * }); + * + * // Or with `file#setEncryptionKey`: + * const file = bucket.file('img.png'); + * file.setEncryptionKey(encryptionKey); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.upload('local-image.png').then(function(data) { + * const file = data[0]; + * }); + * + * To upload a file from a URL, use {@link File#createWriteStream}. + * + * ``` + * @example include:samples/files.js + * region_tag:storage_upload_file + * Another example: + * + * @example include:samples/encryption.js + * region_tag:storage_upload_encrypted_file + * Example of uploading an encrypted file: + */ + upload(pathString, optionsOrCallback, callback) { + var _a, _b; + const upload = (numberOfRetries) => { + const returnValue = (0, async_retry_1.default)(async (bail) => { + await new Promise((resolve, reject) => { + var _a, _b; + if (numberOfRetries === 0 && + ((_b = (_a = newFile === null || newFile === void 0 ? void 0 : newFile.storage) === null || _a === void 0 ? void 0 : _a.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry)) { + newFile.storage.retryOptions.autoRetry = false; + } + const writable = newFile.createWriteStream(options); + if (options.onUploadProgress) { + writable.on('progress', options.onUploadProgress); + } + fs.createReadStream(pathString) + .on('error', bail) + .pipe(writable) + .on('error', err => { + if (this.storage.retryOptions.autoRetry && + this.storage.retryOptions.retryableErrorFn(err)) { + return reject(err); + } + else { + return bail(err); + } + }) + .on('finish', () => { + return resolve(); + }); + }); + }, { + retries: numberOfRetries, + factor: this.storage.retryOptions.retryDelayMultiplier, + maxTimeout: this.storage.retryOptions.maxRetryDelay * 1000, //convert to milliseconds + maxRetryTime: this.storage.retryOptions.totalTimeout * 1000, //convert to milliseconds + }); + if (!callback) { + return returnValue; + } + else { + return returnValue + .then(() => { + if (callback) { + return callback(null, newFile, newFile.metadata); + } + }) + .catch(callback); + } + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (global['GCLOUD_SANDBOX_ENV']) { + return; + } + let options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + options = Object.assign({ + metadata: {}, + }, options); + // Do not retry if precondition option ifGenerationMatch is not set + // because this is a file operation + let maxRetries = this.storage.retryOptions.maxRetries; + if ((((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === undefined && + ((_b = this.instancePreconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch) === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + maxRetries = 0; + } + let newFile; + if (options.destination instanceof file_js_1.File) { + newFile = options.destination; + } + else if (options.destination !== null && + typeof options.destination === 'string') { + // Use the string as the name of the file. + newFile = this.file(options.destination, { + encryptionKey: options.encryptionKey, + kmsKeyName: options.kmsKeyName, + preconditionOpts: this.instancePreconditionOpts, + }); + } + else { + // Resort to using the name of the incoming file. + const destination = path.basename(pathString); + newFile = this.file(destination, { + encryptionKey: options.encryptionKey, + kmsKeyName: options.kmsKeyName, + preconditionOpts: this.instancePreconditionOpts, + }); + } + upload(maxRetries); + } + /** + * @private + * + * @typedef {object} MakeAllFilesPublicPrivateOptions + * @property {boolean} [force] Suppress errors until all files have been + * processed. + * @property {boolean} [private] Make files private. + * @property {boolean} [public] Make files public. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @private + * + * @callback SetBucketMetadataCallback + * @param {?Error} err Request error, if any. + * @param {File[]} files Files that were updated. + */ + /** + * @typedef {array} MakeAllFilesPublicPrivateResponse + * @property {File[]} 0 List of files affected. + */ + /** + * Iterate over all of a bucket's files, calling `file.makePublic()` (public) + * or `file.makePrivate()` (private) on each. + * + * Operations are performed in parallel, up to 10 at once. The first error + * breaks the loop, and will execute the provided callback with it. Specify + * `{ force: true }` to suppress the errors. + * + * @private + * + * @param {MakeAllFilesPublicPrivateOptions} [options] Configuration options. + * @param {boolean} [options.force] Suppress errors until all files have been + * processed. + * @param {boolean} [options.private] Make files private. + * @param {boolean} [options.public] Make files public. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + + * @param {MakeAllFilesPublicPrivateCallback} callback Callback function. + * + * @return {Promise} + */ + makeAllFilesPublicPrivate_(optionsOrCallback, callback) { + const MAX_PARALLEL_LIMIT = 10; + const errors = []; + const updatedFiles = []; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const processFile = async (file) => { + try { + await (options.public ? file.makePublic() : file.makePrivate(options)); + updatedFiles.push(file); + } + catch (e) { + if (!options.force) { + throw e; + } + errors.push(e); + } + }; + this.getFiles(options) + .then(([files]) => { + const limit = (0, p_limit_1.default)(MAX_PARALLEL_LIMIT); + const promises = files.map(file => { + return limit(() => processFile(file)); + }); + return Promise.all(promises); + }) + .then(() => callback(errors.length > 0 ? errors : null, updatedFiles), err => callback(err, updatedFiles)); + } + getId() { + return this.id; + } + disableAutoRetryConditionallyIdempotent_( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + coreOpts, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + methodType, localPreconditionOptions) { + var _a, _b; + if (typeof coreOpts === 'object' && + ((_b = (_a = coreOpts === null || coreOpts === void 0 ? void 0 : coreOpts.reqOpts) === null || _a === void 0 ? void 0 : _a.qs) === null || _b === void 0 ? void 0 : _b.ifMetagenerationMatch) === undefined && + (localPreconditionOptions === null || localPreconditionOptions === void 0 ? void 0 : localPreconditionOptions.ifMetagenerationMatch) === undefined && + (methodType === AvailableServiceObjectMethods.setMetadata || + methodType === AvailableServiceObjectMethods.delete) && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) { + this.storage.retryOptions.autoRetry = false; + } + else if (this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + this.storage.retryOptions.autoRetry = false; + } + } +} +exports.Bucket = Bucket; +/*! Developer Documentation + * + * These methods can be auto-paginated. + */ +paginator_1.paginator.extend(Bucket, 'getFiles'); +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Bucket, { + exclude: ['cloudStorageURI', 'request', 'file', 'notification', 'restore'], +}); + + +/***/ }), + +/***/ 12658: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Channel = void 0; +const index_js_1 = __nccwpck_require__(11325); +const promisify_1 = __nccwpck_require__(60206); +/** + * Create a channel object to interact with a Cloud Storage channel. + * + * See {@link https://cloud.google.com/storage/docs/object-change-notification| Object Change Notification} + * + * @class + * + * @param {string} id The ID of the channel. + * @param {string} resourceId The resource ID of the channel. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const channel = storage.channel('id', 'resource-id'); + * ``` + */ +class Channel extends index_js_1.ServiceObject { + constructor(storage, id, resourceId) { + const config = { + parent: storage, + baseUrl: '/channels', + // An ID shouldn't be included in the API requests. + // RE: + // https://github.com/GoogleCloudPlatform/google-cloud-node/issues/1145 + id: '', + methods: { + // Only need `request`. + }, + }; + super(config); + this.metadata.id = id; + this.metadata.resourceId = resourceId; + } + /** + * @typedef {array} StopResponse + * @property {object} 0 The full API response. + */ + /** + * @callback StopCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Stop this channel. + * + * @param {StopCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const channel = storage.channel('id', 'resource-id'); + * channel.stop(function(err, apiResponse) { + * if (!err) { + * // Channel stopped successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * channel.stop().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + stop(callback) { + callback = callback || index_js_1.util.noop; + this.request({ + method: 'POST', + uri: '/stop', + json: this.metadata, + }, (err, apiResponse) => { + callback(err, apiResponse); + }); + } +} +exports.Channel = Channel; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Channel); + + +/***/ }), + +/***/ 34317: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _CRC32C_crc32c; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CRC32C_EXTENSION_TABLE = exports.CRC32C_EXTENSIONS = exports.CRC32C_EXCEPTION_MESSAGES = exports.CRC32C_DEFAULT_VALIDATOR_GENERATOR = exports.CRC32C = void 0; +const fs_1 = __nccwpck_require__(79896); +/** + * Ported from {@link https://github.com/google/crc32c/blob/21fc8ef30415a635e7351ffa0e5d5367943d4a94/src/crc32c_portable.cc#L16-L59 github.com/google/crc32c} + */ +const CRC32C_EXTENSIONS = [ + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, + 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c, + 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, + 0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512, + 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, + 0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf, + 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, + 0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f, + 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, + 0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e, + 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, + 0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4, + 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, + 0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5, + 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, + 0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905, + 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, + 0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8, + 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, + 0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6, + 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, + 0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351, +]; +exports.CRC32C_EXTENSIONS = CRC32C_EXTENSIONS; +const CRC32C_EXTENSION_TABLE = new Int32Array(CRC32C_EXTENSIONS); +exports.CRC32C_EXTENSION_TABLE = CRC32C_EXTENSION_TABLE; +const CRC32C_DEFAULT_VALIDATOR_GENERATOR = () => new CRC32C(); +exports.CRC32C_DEFAULT_VALIDATOR_GENERATOR = CRC32C_DEFAULT_VALIDATOR_GENERATOR; +const CRC32C_EXCEPTION_MESSAGES = { + INVALID_INIT_BASE64_RANGE: (l) => `base64-encoded data expected to equal 4 bytes, not ${l}`, + INVALID_INIT_BUFFER_LENGTH: (l) => `Buffer expected to equal 4 bytes, not ${l}`, + INVALID_INIT_INTEGER: (l) => `Number expected to be a safe, unsigned 32-bit integer, not ${l}`, +}; +exports.CRC32C_EXCEPTION_MESSAGES = CRC32C_EXCEPTION_MESSAGES; +class CRC32C { + /** + * Constructs a new `CRC32C` object. + * + * Reconstruction is recommended via the `CRC32C.from` static method. + * + * @param initialValue An initial CRC32C value - a signed 32-bit integer. + */ + constructor(initialValue = 0) { + /** Current CRC32C value */ + _CRC32C_crc32c.set(this, 0); + __classPrivateFieldSet(this, _CRC32C_crc32c, initialValue, "f"); + } + /** + * Calculates a CRC32C from a provided buffer. + * + * Implementation inspired from: + * - {@link https://github.com/google/crc32c/blob/21fc8ef30415a635e7351ffa0e5d5367943d4a94/src/crc32c_portable.cc github.com/google/crc32c} + * - {@link https://github.com/googleapis/python-crc32c/blob/a595e758c08df445a99c3bf132ee8e80a3ec4308/src/google_crc32c/python.py github.com/googleapis/python-crc32c} + * - {@link https://github.com/googleapis/java-storage/pull/1376/files github.com/googleapis/java-storage} + * + * @param data The `Buffer` to generate the CRC32C from + */ + update(data) { + let current = __classPrivateFieldGet(this, _CRC32C_crc32c, "f") ^ 0xffffffff; + for (const d of data) { + const tablePoly = CRC32C.CRC32C_EXTENSION_TABLE[(d ^ current) & 0xff]; + current = tablePoly ^ (current >>> 8); + } + __classPrivateFieldSet(this, _CRC32C_crc32c, current ^ 0xffffffff, "f"); + } + /** + * Validates a provided input to the current CRC32C value. + * + * @param input A Buffer, `CRC32C`-compatible object, base64-encoded data (string), or signed 32-bit integer + */ + validate(input) { + if (typeof input === 'number') { + return input === __classPrivateFieldGet(this, _CRC32C_crc32c, "f"); + } + else if (typeof input === 'string') { + return input === this.toString(); + } + else if (Buffer.isBuffer(input)) { + return Buffer.compare(input, this.toBuffer()) === 0; + } + else { + // `CRC32C`-like object + return input.toString() === this.toString(); + } + } + /** + * Returns a `Buffer` representation of the CRC32C value + */ + toBuffer() { + const buffer = Buffer.alloc(4); + buffer.writeInt32BE(__classPrivateFieldGet(this, _CRC32C_crc32c, "f")); + return buffer; + } + /** + * Returns a JSON-compatible, base64-encoded representation of the CRC32C value. + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify `JSON#stringify`} + */ + toJSON() { + return this.toString(); + } + /** + * Returns a base64-encoded representation of the CRC32C value. + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString `Object#toString`} + */ + toString() { + return this.toBuffer().toString('base64'); + } + /** + * Returns the `number` representation of the CRC32C value as a signed 32-bit integer + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf `Object#valueOf`} + */ + valueOf() { + return __classPrivateFieldGet(this, _CRC32C_crc32c, "f"); + } + /** + * Generates a `CRC32C` from a compatible buffer format. + * + * @param value 4-byte `ArrayBufferView`/`Buffer`/`TypedArray` + */ + static fromBuffer(value) { + let buffer; + if (Buffer.isBuffer(value)) { + buffer = value; + } + else if ('buffer' in value) { + // `ArrayBufferView` + buffer = Buffer.from(value.buffer); + } + else { + // `ArrayBuffer` + buffer = Buffer.from(value); + } + if (buffer.byteLength !== 4) { + throw new RangeError(CRC32C_EXCEPTION_MESSAGES.INVALID_INIT_BUFFER_LENGTH(buffer.byteLength)); + } + return new CRC32C(buffer.readInt32BE()); + } + static async fromFile(file) { + const crc32c = new CRC32C(); + await new Promise((resolve, reject) => { + (0, fs_1.createReadStream)(file) + .on('data', (d) => { + if (typeof d === 'string') { + crc32c.update(Buffer.from(d)); + } + else { + crc32c.update(d); + } + }) + .on('end', () => resolve()) + .on('error', reject); + }); + return crc32c; + } + /** + * Generates a `CRC32C` from 4-byte base64-encoded data (string). + * + * @param value 4-byte base64-encoded data (string) + */ + static fromString(value) { + const buffer = Buffer.from(value, 'base64'); + if (buffer.byteLength !== 4) { + throw new RangeError(CRC32C_EXCEPTION_MESSAGES.INVALID_INIT_BASE64_RANGE(buffer.byteLength)); + } + return this.fromBuffer(buffer); + } + /** + * Generates a `CRC32C` from a safe, unsigned 32-bit integer. + * + * @param value an unsigned 32-bit integer + */ + static fromNumber(value) { + if (!Number.isSafeInteger(value) || value > 2 ** 32 || value < -(2 ** 32)) { + throw new RangeError(CRC32C_EXCEPTION_MESSAGES.INVALID_INIT_INTEGER(value)); + } + return new CRC32C(value); + } + /** + * Generates a `CRC32C` from a variety of compatable types. + * Note: strings are treated as input, not as file paths to read from. + * + * @param value A number, 4-byte `ArrayBufferView`/`Buffer`/`TypedArray`, or 4-byte base64-encoded data (string) + */ + static from(value) { + if (typeof value === 'number') { + return this.fromNumber(value); + } + else if (typeof value === 'string') { + return this.fromString(value); + } + else if ('byteLength' in value) { + // `ArrayBuffer` | `Buffer` | `ArrayBufferView` + return this.fromBuffer(value); + } + else { + // `CRC32CValidator`/`CRC32C`-like + return this.fromString(value.toString()); + } + } +} +exports.CRC32C = CRC32C; +_CRC32C_crc32c = new WeakMap(); +CRC32C.CRC32C_EXTENSIONS = CRC32C_EXTENSIONS; +CRC32C.CRC32C_EXTENSION_TABLE = CRC32C_EXTENSION_TABLE; + + +/***/ }), + +/***/ 69975: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _File_instances, _File_validateIntegrity; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.File = exports.FileExceptionMessages = exports.RequestError = exports.STORAGE_POST_POLICY_BASE_URL = exports.ActionToHTTPMethod = void 0; +const index_js_1 = __nccwpck_require__(11325); +const promisify_1 = __nccwpck_require__(60206); +const crypto = __importStar(__nccwpck_require__(76982)); +const fs = __importStar(__nccwpck_require__(79896)); +const mime_1 = __importDefault(__nccwpck_require__(94900)); +const resumableUpload = __importStar(__nccwpck_require__(88043)); +const stream_1 = __nccwpck_require__(2203); +const zlib = __importStar(__nccwpck_require__(43106)); +const storage_js_1 = __nccwpck_require__(92848); +const bucket_js_1 = __nccwpck_require__(82887); +const acl_js_1 = __nccwpck_require__(76637); +const signer_js_1 = __nccwpck_require__(7319); +const util_js_1 = __nccwpck_require__(37325); +const duplexify_1 = __importDefault(__nccwpck_require__(29112)); +const util_js_2 = __nccwpck_require__(74557); +const crc32c_js_1 = __nccwpck_require__(34317); +const hash_stream_validator_js_1 = __nccwpck_require__(14873); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +var ActionToHTTPMethod; +(function (ActionToHTTPMethod) { + ActionToHTTPMethod["read"] = "GET"; + ActionToHTTPMethod["write"] = "PUT"; + ActionToHTTPMethod["delete"] = "DELETE"; + ActionToHTTPMethod["resumable"] = "POST"; +})(ActionToHTTPMethod || (exports.ActionToHTTPMethod = ActionToHTTPMethod = {})); +/** + * @deprecated - no longer used + */ +exports.STORAGE_POST_POLICY_BASE_URL = 'https://storage.googleapis.com'; +/** + * @private + */ +const GS_URL_REGEXP = /^gs:\/\/([a-z0-9_.-]+)\/(.+)$/; +/** + * @private + * This regex will match compressible content types. These are primarily text/*, +json, +text, +xml content types. + * This was based off of mime-db and may periodically need to be updated if new compressible content types become + * standards. + */ +const COMPRESSIBLE_MIME_REGEX = new RegExp([ + /^text\/|application\/ecmascript|application\/javascript|application\/json/, + /|application\/postscript|application\/rtf|application\/toml|application\/vnd.dart/, + /|application\/vnd.ms-fontobject|application\/wasm|application\/x-httpd-php|application\/x-ns-proxy-autoconfig/, + /|application\/x-sh(?!ockwave-flash)|application\/x-tar|application\/x-virtualbox-hdd|application\/x-virtualbox-ova|application\/x-virtualbox-ovf/, + /|^application\/x-virtualbox-vbox$|application\/x-virtualbox-vdi|application\/x-virtualbox-vhd|application\/x-virtualbox-vmdk/, + /|application\/xml|application\/xml-dtd|font\/otf|font\/ttf|image\/bmp|image\/vnd.adobe.photoshop|image\/vnd.microsoft.icon/, + /|image\/vnd.ms-dds|image\/x-icon|image\/x-ms-bmp|message\/rfc822|model\/gltf-binary|\+json|\+text|\+xml|\+yaml/, +] + .map(r => r.source) + .join(''), 'i'); +class RequestError extends Error { +} +exports.RequestError = RequestError; +const SEVEN_DAYS = 7 * 24 * 60 * 60; +const GS_UTIL_URL_REGEX = /(gs):\/\/([a-z0-9_.-]+)\/(.+)/g; +const HTTPS_PUBLIC_URL_REGEX = /(https):\/\/(storage\.googleapis\.com)\/([a-z0-9_.-]+)\/(.+)/g; +var FileExceptionMessages; +(function (FileExceptionMessages) { + FileExceptionMessages["EXPIRATION_TIME_NA"] = "An expiration time is not available."; + FileExceptionMessages["DESTINATION_NO_NAME"] = "Destination file should have a name."; + FileExceptionMessages["INVALID_VALIDATION_FILE_RANGE"] = "Cannot use validation with file ranges (start/end)."; + FileExceptionMessages["MD5_NOT_AVAILABLE"] = "MD5 verification was specified, but is not available for the requested object. MD5 is not available for composite objects."; + FileExceptionMessages["EQUALS_CONDITION_TWO_ELEMENTS"] = "Equals condition must be an array of 2 elements."; + FileExceptionMessages["STARTS_WITH_TWO_ELEMENTS"] = "StartsWith condition must be an array of 2 elements."; + FileExceptionMessages["CONTENT_LENGTH_RANGE_MIN_MAX"] = "ContentLengthRange must have numeric min & max fields."; + FileExceptionMessages["DOWNLOAD_MISMATCH"] = "The downloaded data did not match the data from the server. To be sure the content is the same, you should download the file again."; + FileExceptionMessages["UPLOAD_MISMATCH_DELETE_FAIL"] = "The uploaded data did not match the data from the server.\n As a precaution, we attempted to delete the file, but it was not successful.\n To be sure the content is the same, you should try removing the file manually,\n then uploading the file again.\n \n\nThe delete attempt failed with this message:\n\n "; + FileExceptionMessages["UPLOAD_MISMATCH"] = "The uploaded data did not match the data from the server.\n As a precaution, the file has been deleted.\n To be sure the content is the same, you should try uploading the file again."; + FileExceptionMessages["MD5_RESUMED_UPLOAD"] = "MD5 cannot be used with a continued resumable upload as MD5 cannot be extended from an existing value"; + FileExceptionMessages["MISSING_RESUME_CRC32C_FINAL_UPLOAD"] = "The CRC32C is missing for the final portion of a resumed upload, which is required for validation. Please provide `resumeCRC32C` if validation is required, or disable `validation`."; +})(FileExceptionMessages || (exports.FileExceptionMessages = FileExceptionMessages = {})); +/** + * A File object is created from your {@link Bucket} object using + * {@link Bucket#file}. + * + * @class + */ +class File extends index_js_1.ServiceObject { + /** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * An ACL consists of one or more entries, where each entry grants permissions + * to an entity. Permissions define the actions that can be performed against + * an object or bucket (for example, `READ` or `WRITE`); the entity defines + * who the permission applies to (for example, a specific user or group of + * users). + * + * The `acl` object on a File instance provides methods to get you a list of + * the ACLs defined on your bucket, as well as set, update, and delete them. + * + * See {@link http://goo.gl/6qBBPO| About Access Control lists} + * + * @name File#acl + * @mixes Acl + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * //- + * // Make a file publicly readable. + * //- + * const options = { + * entity: 'allUsers', + * role: storage.acl.READER_ROLE + * }; + * + * file.acl.add(options, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + /** + * The API-formatted resource description of the file. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name File#metadata + * @type {object} + */ + /** + * The file's name. + * @name File#name + * @type {string} + */ + /** + * @callback Crc32cGeneratorToStringCallback + * A method returning the CRC32C as a base64-encoded string. + * + * @returns {string} + * + * @example + * Hashing the string 'data' should return 'rth90Q==' + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.toString(); // 'rth90Q==' + * ``` + **/ + /** + * @callback Crc32cGeneratorValidateCallback + * A method validating a base64-encoded CRC32C string. + * + * @param {string} [value] base64-encoded CRC32C string to validate + * @returns {boolean} + * + * @example + * Should return `true` if the value matches, `false` otherwise + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.validate('DkjKuA=='); // false + * crc32c.validate('rth90Q=='); // true + * ``` + **/ + /** + * @callback Crc32cGeneratorUpdateCallback + * A method for passing `Buffer`s for CRC32C generation. + * + * @param {Buffer} [data] data to update CRC32C value with + * @returns {undefined} + * + * @example + * Hashing buffers from 'some ' and 'text\n' + * + * ```js + * const buffer1 = Buffer.from('some '); + * crc32c.update(buffer1); + * + * const buffer2 = Buffer.from('text\n'); + * crc32c.update(buffer2); + * + * crc32c.toString(); // 'DkjKuA==' + * ``` + **/ + /** + * @typedef {object} CRC32CValidator + * @property {Crc32cGeneratorToStringCallback} + * @property {Crc32cGeneratorValidateCallback} + * @property {Crc32cGeneratorUpdateCallback} + */ + /** + * @callback Crc32cGeneratorCallback + * @returns {CRC32CValidator} + */ + /** + * @typedef {object} FileOptions Options passed to the File constructor. + * @property {string} [encryptionKey] A custom encryption key. + * @property {number} [generation] Generation to scope the file to. + * @property {string} [kmsKeyName] Cloud KMS Key used to encrypt this + * object, if the object is encrypted by such a key. Limited availability; + * usable only by enabled projects. + * @property {string} [userProject] The ID of the project which will be + * billed for all requests made from File object. + * @property {Crc32cGeneratorCallback} [callback] A function that generates a CRC32C Validator. Defaults to {@link CRC32C} + */ + /** + * Constructs a file object. + * + * @param {Bucket} bucket The Bucket instance this file is + * attached to. + * @param {string} name The name of the remote file. + * @param {FileOptions} [options] Configuration options. + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * ``` + */ + constructor(bucket, name, options = {}) { + var _a, _b; + const requestQueryObject = {}; + let generation; + if (options.generation !== null) { + if (typeof options.generation === 'string') { + generation = Number(options.generation); + } + else { + generation = options.generation; + } + if (!isNaN(generation)) { + requestQueryObject.generation = generation; + } + } + Object.assign(requestQueryObject, options.preconditionOpts); + const userProject = options.userProject || bucket.userProject; + if (typeof userProject === 'string') { + requestQueryObject.userProject = userProject; + } + const methods = { + /** + * @typedef {array} DeleteFileResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DeleteFileCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Delete the file. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/delete| Objects: delete API Documentation} + * + * @method File#delete + * @param {object} [options] Configuration options. + * @param {boolean} [options.ignoreNotFound = false] Ignore an error if + * the file does not exist. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DeleteFileCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * file.delete(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_delete_file + * Another example: + */ + delete: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} FileExistsResponse + * @property {boolean} 0 Whether the {@link File} exists. + */ + /** + * @callback FileExistsCallback + * @param {?Error} err Request error, if any. + * @param {boolean} exists Whether the {@link File} exists. + */ + /** + * Check if the file exists. + * + * @method File#exists + * @param {options} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {FileExistsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.exists(function(err, exists) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.exists().then(function(data) { + * const exists = data[0]; + * }); + * ``` + */ + exists: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} GetFileResponse + * @property {File} 0 The {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback GetFileCallback + * @param {?Error} err Request error, if any. + * @param {File} file The {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * Get a file object and its metadata if it exists. + * + * @method File#get + * @param {options} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {number} [options.generation] The generation number to get + * @param {string} [options.restoreToken] If this is a soft-deleted object in an HNS-enabled bucket, returns the restore token which will + * be necessary to restore it if there's a name conflict with another object. + * @param {boolean} [options.softDeleted] If true, returns the soft-deleted object. + Object `generation` is required if `softDeleted` is set to True. + * @param {GetFileCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.get(function(err, file, apiResponse) { + * // file.metadata` has been populated. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.get().then(function(data) { + * const file = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + get: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} GetFileMetadataResponse + * @property {object} 0 The {@link File} metadata. + * @property {object} 1 The full API response. + */ + /** + * @callback GetFileMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} metadata The {@link File} metadata. + * @param {object} apiResponse The full API response. + */ + /** + * Get the file's metadata. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/get| Objects: get API Documentation} + * + * @method File#getMetadata + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetFileMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.getMetadata(function(err, metadata, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.getMetadata().then(function(data) { + * const metadata = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_get_metadata + * Another example: + */ + getMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {object} SetFileMetadataOptions Configuration options for File#setMetadata(). + * @param {string} [userProject] The ID of the project which will be billed for the request. + */ + /** + * @callback SetFileMetadataCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} SetFileMetadataResponse + * @property {object} 0 The full API response. + */ + /** + * Merge the given metadata with the current remote file's metadata. This + * will set metadata if it was previously unset or update previously set + * metadata. To unset previously set metadata, set its value to null. + * + * You can set custom key/value pairs in the metadata key of the given + * object, however the other properties outside of this object must adhere + * to the {@link https://goo.gl/BOnnCK| official API documentation}. + * + * + * See the examples below for more information. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/patch| Objects: patch API Documentation} + * + * @method File#setMetadata + * @param {object} [metadata] The metadata you wish to update. + * @param {SetFileMetadataOptions} [options] Configuration options. + * @param {SetFileMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * const metadata = { + * contentType: 'application/x-font-ttf', + * metadata: { + * my: 'custom', + * properties: 'go here' + * } + * }; + * + * file.setMetadata(metadata, function(err, apiResponse) {}); + * + * // Assuming current metadata = { hello: 'world', unsetMe: 'will do' } + * file.setMetadata({ + * metadata: { + * abc: '123', // will be set. + * unsetMe: null, // will be unset (deleted). + * hello: 'goodbye' // will be updated from 'world' to 'goodbye'. + * } + * }, function(err, apiResponse) { + * // metadata should now be { abc: '123', hello: 'goodbye' } + * }); + * + * //- + * // Set a temporary hold on this file from its bucket's retention period + * // configuration. + * // + * file.setMetadata({ + * temporaryHold: true + * }, function(err, apiResponse) {}); + * + * //- + * // Alternatively, you may set a temporary hold. This will follow the + * // same behavior as an event-based hold, with the exception that the + * // bucket's retention policy will not renew for this file from the time + * // the hold is released. + * //- + * file.setMetadata({ + * eventBasedHold: true + * }, function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.setMetadata(metadata).then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + setMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + }; + super({ + parent: bucket, + baseUrl: '/o', + id: encodeURIComponent(name), + methods, + }); + _File_instances.add(this); + this.bucket = bucket; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.storage = bucket.parent; + // @TODO Can this duplicate code from above be avoided? + if (options.generation !== null) { + let generation; + if (typeof options.generation === 'string') { + generation = Number(options.generation); + } + else { + generation = options.generation; + } + if (!isNaN(generation)) { + this.generation = generation; + } + } + this.kmsKeyName = options.kmsKeyName; + this.userProject = userProject; + this.name = name; + if (options.encryptionKey) { + this.setEncryptionKey(options.encryptionKey); + } + this.acl = new acl_js_1.Acl({ + request: this.request.bind(this), + pathPrefix: '/acl', + }); + this.crc32cGenerator = + options.crc32cGenerator || this.bucket.crc32cGenerator; + this.instanceRetryValue = (_b = (_a = this.storage) === null || _a === void 0 ? void 0 : _a.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry; + this.instancePreconditionOpts = options === null || options === void 0 ? void 0 : options.preconditionOpts; + } + /** + * The object's Cloud Storage URI (`gs://`) + * + * @example + * ```ts + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('image.png'); + * + * // `gs://my-bucket/image.png` + * const href = file.cloudStorageURI.href; + * ``` + */ + get cloudStorageURI() { + const uri = this.bucket.cloudStorageURI; + uri.pathname = this.name; + return uri; + } + /** + * A helper method for determining if a request should be retried based on preconditions. + * This should only be used for methods where the idempotency is determined by + * `ifGenerationMatch` + * @private + * + * A request should not be retried under the following conditions: + * - if precondition option `ifGenerationMatch` is not set OR + * - if `idempotencyStrategy` is set to `RetryNever` + */ + shouldRetryBasedOnPreconditionAndIdempotencyStrat(options) { + var _a; + return !(((options === null || options === void 0 ? void 0 : options.ifGenerationMatch) === undefined && + ((_a = this.instancePreconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever); + } + /** + * @typedef {array} CopyResponse + * @property {File} 0 The copied {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback CopyCallback + * @param {?Error} err Request error, if any. + * @param {File} copiedFile The copied {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} CopyOptions Configuration options for File#copy(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @property {string} [cacheControl] The cacheControl setting for the new file. + * @property {string} [contentEncoding] The contentEncoding setting for the new file. + * @property {string} [contentType] The contentType setting for the new file. + * @property {string} [destinationKmsKeyName] Resource name of the Cloud + * KMS key, of the form + * `projects/my-project/locations/location/keyRings/my-kr/cryptoKeys/my-key`, + * that will be used to encrypt the object. Overwrites the object + * metadata's `kms_key_name` value, if any. + * @property {Metadata} [metadata] Metadata to specify on the copied file. + * @property {string} [predefinedAcl] Set the ACL for the new file. + * @property {string} [token] A previously-returned `rewriteToken` from an + * unfinished rewrite request. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Copy this file to another file. By default, this will copy the file to the + * same bucket, but you can choose to copy it to another Bucket by providing + * a Bucket or File object or a URL starting with "gs://". + * The generation of the file will not be preserved. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite| Objects: rewrite API Documentation} + * + * @throws {Error} If the destination file is not provided. + * + * @param {string|Bucket|File} destination Destination file. + * @param {CopyOptions} [options] Configuration options. See an + * @param {CopyCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // You can pass in a variety of types for the destination. + * // + * // For all of the below examples, assume we are working with the following + * // Bucket and File objects. + * //- + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // If you pass in a string for the destination, the file is copied to its + * // current bucket, under the new name provided. + * //- + * file.copy('my-image-copy.png', function(err, copiedFile, apiResponse) { + * // `my-bucket` now contains: + * // - "my-image.png" + * // - "my-image-copy.png" + * + * // `copiedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // If you pass in a string starting with "gs://" for the destination, the + * // file is copied to the other bucket and under the new name provided. + * //- + * const newLocation = 'gs://another-bucket/my-image-copy.png'; + * file.copy(newLocation, function(err, copiedFile, apiResponse) { + * // `my-bucket` still contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image-copy.png" + * + * // `copiedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // If you pass in a Bucket object, the file will be copied to that bucket + * // using the same name. + * //- + * const anotherBucket = storage.bucket('another-bucket'); + * file.copy(anotherBucket, function(err, copiedFile, apiResponse) { + * // `my-bucket` still contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image.png" + * + * // `copiedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // If you pass in a File object, you have complete control over the new + * // bucket and filename. + * //- + * const anotherFile = anotherBucket.file('my-awesome-image.png'); + * file.copy(anotherFile, function(err, copiedFile, apiResponse) { + * // `my-bucket` still contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-awesome-image.png" + * + * // Note: + * // The `copiedFile` parameter is equal to `anotherFile`. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.copy(newLocation).then(function(data) { + * const newFile = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_copy_file + * Another example: + */ + copy(destination, optionsOrCallback, callback) { + var _a, _b; + const noDestinationError = new Error(FileExceptionMessages.DESTINATION_NO_NAME); + if (!destination) { + throw noDestinationError; + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = { ...optionsOrCallback }; + } + callback = callback || index_js_1.util.noop; + let destBucket; + let destName; + let newFile; + if (typeof destination === 'string') { + const parsedDestination = GS_URL_REGEXP.exec(destination); + if (parsedDestination !== null && parsedDestination.length === 3) { + destBucket = this.storage.bucket(parsedDestination[1]); + destName = parsedDestination[2]; + } + else { + destBucket = this.bucket; + destName = destination; + } + } + else if (destination instanceof bucket_js_1.Bucket) { + destBucket = destination; + destName = this.name; + } + else if (destination instanceof File) { + destBucket = destination.bucket; + destName = destination.name; + newFile = destination; + } + else { + throw noDestinationError; + } + const query = {}; + if (this.generation !== undefined) { + query.sourceGeneration = this.generation; + } + if (options.token !== undefined) { + query.rewriteToken = options.token; + } + if (options.userProject !== undefined) { + query.userProject = options.userProject; + delete options.userProject; + } + if (options.predefinedAcl !== undefined) { + query.destinationPredefinedAcl = options.predefinedAcl; + delete options.predefinedAcl; + } + newFile = newFile || destBucket.file(destName); + const headers = {}; + if (this.encryptionKey !== undefined) { + headers['x-goog-copy-source-encryption-algorithm'] = 'AES256'; + headers['x-goog-copy-source-encryption-key'] = this.encryptionKeyBase64; + headers['x-goog-copy-source-encryption-key-sha256'] = + this.encryptionKeyHash; + } + if (newFile.encryptionKey !== undefined) { + this.setEncryptionKey(newFile.encryptionKey); + } + else if (options.destinationKmsKeyName !== undefined) { + query.destinationKmsKeyName = options.destinationKmsKeyName; + delete options.destinationKmsKeyName; + } + else if (newFile.kmsKeyName !== undefined) { + query.destinationKmsKeyName = newFile.kmsKeyName; + } + if (query.destinationKmsKeyName) { + this.kmsKeyName = query.destinationKmsKeyName; + const keyIndex = this.interceptors.indexOf(this.encryptionKeyInterceptor); + if (keyIndex > -1) { + this.interceptors.splice(keyIndex, 1); + } + } + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options === null || options === void 0 ? void 0 : options.preconditionOpts)) { + this.storage.retryOptions.autoRetry = false; + } + if (((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) !== undefined) { + query.ifGenerationMatch = (_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch; + delete options.preconditionOpts; + } + this.request({ + method: 'POST', + uri: `/rewriteTo/b/${destBucket.name}/o/${encodeURIComponent(newFile.name)}`, + qs: query, + json: options, + headers, + }, (err, resp) => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + if (err) { + callback(err, null, resp); + return; + } + if (resp.rewriteToken) { + const options = { + token: resp.rewriteToken, + }; + if (query.userProject) { + options.userProject = query.userProject; + } + if (query.destinationKmsKeyName) { + options.destinationKmsKeyName = query.destinationKmsKeyName; + } + this.copy(newFile, options, callback); + return; + } + callback(null, newFile, resp); + }); + } + /** + * @typedef {object} CreateReadStreamOptions Configuration options for File#createReadStream. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string|boolean} [validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with a + * CRC32c checksum. You may use MD5 if preferred, but that hash is not + * supported for composite objects. An error will be raised if MD5 is + * specified but is not available. You may also choose to skip validation + * completely, however this is **not recommended**. + * @property {number} [start] A byte offset to begin the file's download + * from. Default is 0. NOTE: Byte ranges are inclusive; that is, + * `options.start = 0` and `options.end = 999` represent the first 1000 + * bytes in a file or object. NOTE: when specifying a byte range, data + * integrity is not available. + * @property {number} [end] A byte offset to stop reading the file at. + * NOTE: Byte ranges are inclusive; that is, `options.start = 0` and + * `options.end = 999` represent the first 1000 bytes in a file or object. + * NOTE: when specifying a byte range, data integrity is not available. + * @property {boolean} [decompress=true] Disable auto decompression of the + * received data. By default this option is set to `true`. + * Applicable in cases where the data was uploaded with + * `gzip: true` option. See {@link File#createWriteStream}. + */ + /** + * Create a readable stream to read the contents of the remote file. It can be + * piped to a writable stream or listened to for 'data' events to read a + * file's contents. + * + * In the unlikely event there is a mismatch between what you downloaded and + * the version in your Bucket, your error handler will receive an error with + * code "CONTENT_DOWNLOAD_MISMATCH". If you receive this error, the best + * recourse is to try downloading the file again. + * + * NOTE: Readable streams will emit the `end` event when the file is fully + * downloaded. + * + * @param {CreateReadStreamOptions} [options] Configuration options. + * @returns {ReadableStream} + * + * @example + * ``` + * //- + * //

Downloading a File

+ * // + * // The example below demonstrates how we can reference a remote file, then + * // pipe its contents to a local file. This is effectively creating a local + * // backup of your remote data. + * //- + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * const fs = require('fs'); + * const remoteFile = bucket.file('image.png'); + * const localFilename = '/Users/stephen/Photos/image.png'; + * + * remoteFile.createReadStream() + * .on('error', function(err) {}) + * .on('response', function(response) { + * // Server connected and responded with the specified status and headers. + * }) + * .on('end', function() { + * // The file is fully downloaded. + * }) + * .pipe(fs.createWriteStream(localFilename)); + * + * //- + * // To limit the downloaded data to only a byte range, pass an options + * // object. + * //- + * const logFile = myBucket.file('access_log'); + * logFile.createReadStream({ + * start: 10000, + * end: 20000 + * }) + * .on('error', function(err) {}) + * .pipe(fs.createWriteStream('/Users/stephen/logfile.txt')); + * + * //- + * // To read a tail byte range, specify only `options.end` as a negative + * // number. + * //- + * const logFile = myBucket.file('access_log'); + * logFile.createReadStream({ + * end: -100 + * }) + * .on('error', function(err) {}) + * .pipe(fs.createWriteStream('/Users/stephen/logfile.txt')); + * ``` + */ + createReadStream(options = {}) { + options = Object.assign({ decompress: true }, options); + const rangeRequest = typeof options.start === 'number' || typeof options.end === 'number'; + const tailRequest = options.end < 0; + let validateStream = undefined; + let request = undefined; + const throughStream = new util_js_2.PassThroughShim(); + let crc32c = true; + let md5 = false; + if (typeof options.validation === 'string') { + const value = options.validation.toLowerCase().trim(); + crc32c = value === 'crc32c'; + md5 = value === 'md5'; + } + else if (options.validation === false) { + crc32c = false; + } + const shouldRunValidation = !rangeRequest && (crc32c || md5); + if (rangeRequest) { + if (typeof options.validation === 'string' || + options.validation === true) { + throw new Error(FileExceptionMessages.INVALID_VALIDATION_FILE_RANGE); + } + // Range requests can't receive data integrity checks. + crc32c = false; + md5 = false; + } + const onComplete = (err) => { + if (err) { + // There is an issue with node-fetch 2.x that if the stream errors the underlying socket connection is not closed. + // This causes a memory leak, so cleanup the sockets manually here by destroying the agent. + if (request === null || request === void 0 ? void 0 : request.agent) { + request.agent.destroy(); + } + throughStream.destroy(err); + } + }; + // We listen to the response event from the request stream so that we + // can... + // + // 1) Intercept any data from going to the user if an error occurred. + // 2) Calculate the hashes from the http.IncomingMessage response + // stream, + // which will return the bytes from the source without decompressing + // gzip'd content. We then send it through decompressed, if + // applicable, to the user. + const onResponse = (err, _body, rawResponseStream) => { + if (err) { + // Get error message from the body. + this.getBufferFromReadable(rawResponseStream).then(body => { + err.message = body.toString('utf8'); + throughStream.destroy(err); + }); + return; + } + request = rawResponseStream.request; + const headers = rawResponseStream.toJSON().headers; + const isCompressed = headers['content-encoding'] === 'gzip'; + const hashes = {}; + // The object is safe to validate if: + // 1. It was stored gzip and returned to us gzip OR + // 2. It was never stored as gzip + const safeToValidate = (headers['x-goog-stored-content-encoding'] === 'gzip' && + isCompressed) || + headers['x-goog-stored-content-encoding'] === 'identity'; + const transformStreams = []; + if (shouldRunValidation) { + // The x-goog-hash header should be set with a crc32c and md5 hash. + // ex: headers['x-goog-hash'] = 'crc32c=xxxx,md5=xxxx' + if (typeof headers['x-goog-hash'] === 'string') { + headers['x-goog-hash'] + .split(',') + .forEach((hashKeyValPair) => { + const delimiterIndex = hashKeyValPair.indexOf('='); + const hashType = hashKeyValPair.substring(0, delimiterIndex); + const hashValue = hashKeyValPair.substring(delimiterIndex + 1); + hashes[hashType] = hashValue; + }); + } + validateStream = new hash_stream_validator_js_1.HashStreamValidator({ + crc32c, + md5, + crc32cGenerator: this.crc32cGenerator, + crc32cExpected: hashes.crc32c, + md5Expected: hashes.md5, + }); + } + if (md5 && !hashes.md5) { + const hashError = new RequestError(FileExceptionMessages.MD5_NOT_AVAILABLE); + hashError.code = 'MD5_NOT_AVAILABLE'; + throughStream.destroy(hashError); + return; + } + if (safeToValidate && shouldRunValidation && validateStream) { + transformStreams.push(validateStream); + } + if (isCompressed && options.decompress) { + transformStreams.push(zlib.createGunzip()); + } + (0, stream_1.pipeline)(rawResponseStream, ...transformStreams, throughStream, onComplete); + }; + // Authenticate the request, then pipe the remote API request to the stream + // returned to the user. + const makeRequest = () => { + const query = { alt: 'media' }; + if (this.generation) { + query.generation = this.generation; + } + if (options.userProject) { + query.userProject = options.userProject; + } + const headers = { + 'Accept-Encoding': 'gzip', + 'Cache-Control': 'no-store', + }; + if (rangeRequest) { + const start = typeof options.start === 'number' ? options.start : '0'; + const end = typeof options.end === 'number' ? options.end : ''; + headers.Range = `bytes=${tailRequest ? end : `${start}-${end}`}`; + } + const reqOpts = { + uri: '', + headers, + qs: query, + }; + if (options[util_js_1.GCCL_GCS_CMD_KEY]) { + reqOpts[util_js_1.GCCL_GCS_CMD_KEY] = options[util_js_1.GCCL_GCS_CMD_KEY]; + } + this.requestStream(reqOpts) + .on('error', err => { + throughStream.destroy(err); + }) + .on('response', res => { + throughStream.emit('response', res); + index_js_1.util.handleResp(null, res, null, onResponse); + }) + .resume(); + }; + throughStream.on('reading', makeRequest); + return throughStream; + } + /** + * @callback CreateResumableUploadCallback + * @param {?Error} err Request error, if any. + * @param {string} uri The resumable upload's unique session URI. + */ + /** + * @typedef {array} CreateResumableUploadResponse + * @property {string} 0 The resumable upload's unique session URI. + */ + /** + * @typedef {object} CreateResumableUploadOptions + * @property {object} [metadata] Metadata to set on the file. + * @property {number} [offset] The starting byte of the upload stream for resuming an interrupted upload. + * @property {string} [origin] Origin header to set for the upload. + * @property {string} [predefinedAcl] Apply a predefined set of access + * controls to this object. + * + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @property {boolean} [private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @property {boolean} [public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string} [chunkSize] Create a separate request per chunk. This + * value is in bytes and should be a multiple of 256 KiB (2^18). + * {@link https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload| We recommend using at least 8 MiB for the chunk size.} + */ + /** + * Create a unique resumable upload session URI. This is the first step when + * performing a resumable upload. + * + * See the {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload| Resumable upload guide} + * for more on how the entire process works. + * + *

Note

+ * + * If you are just looking to perform a resumable upload without worrying + * about any of the details, see {@link File#createWriteStream}. Resumable + * uploads are performed by default. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload| Resumable upload guide} + * + * @param {CreateResumableUploadOptions} [options] Configuration options. + * @param {CreateResumableUploadCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * file.createResumableUpload(function(err, uri) { + * if (!err) { + * // `uri` can be used to PUT data to. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.createResumableUpload().then(function(data) { + * const uri = data[0]; + * }); + * ``` + */ + createResumableUpload(optionsOrCallback, callback) { + var _a, _b; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const retryOptions = this.storage.retryOptions; + if ((((_a = options === null || options === void 0 ? void 0 : options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) === undefined && + ((_b = this.instancePreconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch) === undefined && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + retryOptions.autoRetry = false; + } + resumableUpload.createURI({ + authClient: this.storage.authClient, + apiEndpoint: this.storage.apiEndpoint, + bucket: this.bucket.name, + customRequestOptions: this.getRequestInterceptors().reduce((reqOpts, interceptorFn) => interceptorFn(reqOpts), {}), + file: this.name, + generation: this.generation, + key: this.encryptionKey, + kmsKeyName: this.kmsKeyName, + metadata: options.metadata, + offset: options.offset, + origin: options.origin, + predefinedAcl: options.predefinedAcl, + private: options.private, + public: options.public, + userProject: options.userProject || this.userProject, + retryOptions: retryOptions, + params: (options === null || options === void 0 ? void 0 : options.preconditionOpts) || this.instancePreconditionOpts, + universeDomain: this.bucket.storage.universeDomain, + [util_js_1.GCCL_GCS_CMD_KEY]: options[util_js_1.GCCL_GCS_CMD_KEY], + }, callback); + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + } + /** + * @typedef {object} CreateWriteStreamOptions Configuration options for File#createWriteStream(). + * @property {string} [contentType] Alias for + * `options.metadata.contentType`. If set to `auto`, the file name is used + * to determine the contentType. + * @property {string|boolean} [gzip] If true, automatically gzip the file. + * If set to `auto`, the contentType is used to determine if the file + * should be gzipped. This will set `options.metadata.contentEncoding` to + * `gzip` if necessary. + * @property {object} [metadata] See the examples below or + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert#request_properties_JSON| Objects: insert request body} + * for more details. + * @property {number} [offset] The starting byte of the upload stream, for + * resuming an interrupted upload. Defaults to 0. + * @property {string} [predefinedAcl] Apply a predefined set of access + * controls to this object. + * + * Acceptable values are: + * - **`authenticatedRead`** - Object owner gets `OWNER` access, and + * `allAuthenticatedUsers` get `READER` access. + * + * - **`bucketOwnerFullControl`** - Object owner gets `OWNER` access, and + * project team owners get `OWNER` access. + * + * - **`bucketOwnerRead`** - Object owner gets `OWNER` access, and project + * team owners get `READER` access. + * + * - **`private`** - Object owner gets `OWNER` access. + * + * - **`projectPrivate`** - Object owner gets `OWNER` access, and project + * team members get access according to their roles. + * + * - **`publicRead`** - Object owner gets `OWNER` access, and `allUsers` + * get `READER` access. + * @property {boolean} [private] Make the uploaded file private. (Alias for + * `options.predefinedAcl = 'private'`) + * @property {boolean} [public] Make the uploaded file public. (Alias for + * `options.predefinedAcl = 'publicRead'`) + * @property {boolean} [resumable] Force a resumable upload. NOTE: When + * working with streams, the file format and size is unknown until it's + * completely consumed. Because of this, it's best for you to be explicit + * for what makes sense given your input. + * @property {number} [timeout=60000] Set the HTTP request timeout in + * milliseconds. This option is not available for resumable uploads. + * Default: `60000` + * @property {string} [uri] The URI for an already-created resumable + * upload. See {@link File#createResumableUpload}. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {string|boolean} [validation] Possible values: `"md5"`, + * `"crc32c"`, or `false`. By default, data integrity is validated with a + * CRC32c checksum. You may use MD5 if preferred, but that hash is not + * supported for composite objects. An error will be raised if MD5 is + * specified but is not available. You may also choose to skip validation + * completely, however this is **not recommended**. In addition to specifying + * validation type, providing `metadata.crc32c` or `metadata.md5Hash` will + * cause the server to perform validation in addition to client validation. + * NOTE: Validation is automatically skipped for objects that were + * uploaded using the `gzip` option and have already compressed content. + */ + /** + * Create a writable stream to overwrite the contents of the file in your + * bucket. + * + * A File object can also be used to create files for the first time. + * + * Resumable uploads are automatically enabled and must be shut off explicitly + * by setting `options.resumable` to `false`. + * + * + *

+ * There is some overhead when using a resumable upload that can cause + * noticeable performance degradation while uploading a series of small + * files. When uploading files less than 10MB, it is recommended that the + * resumable feature is disabled. + *

+ * + * NOTE: Writable streams will emit the `finish` event when the file is fully + * uploaded. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/how-tos/upload Upload Options (Simple or Resumable)} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/insert Objects: insert API Documentation} + * + * @param {CreateWriteStreamOptions} [options] Configuration options. + * @returns {WritableStream} + * + * @example + * ``` + * const fs = require('fs'); + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * //

Uploading a File

+ * // + * // Now, consider a case where we want to upload a file to your bucket. You + * // have the option of using {@link Bucket#upload}, but that is just + * // a convenience method which will do the following. + * //- + * fs.createReadStream('/Users/stephen/Photos/birthday-at-the-zoo/panda.jpg') + * .pipe(file.createWriteStream()) + * .on('error', function(err) {}) + * .on('finish', function() { + * // The file upload is complete. + * }); + * + * //- + * //

Uploading a File with gzip compression

+ * //- + * fs.createReadStream('/Users/stephen/site/index.html') + * .pipe(file.createWriteStream({ gzip: true })) + * .on('error', function(err) {}) + * .on('finish', function() { + * // The file upload is complete. + * }); + * + * //- + * // Downloading the file with `createReadStream` will automatically decode + * // the file. + * //- + * + * //- + * //

Uploading a File with Metadata

+ * // + * // One last case you may run into is when you want to upload a file to your + * // bucket and set its metadata at the same time. Like above, you can use + * // {@link Bucket#upload} to do this, which is just a wrapper around + * // the following. + * //- + * fs.createReadStream('/Users/stephen/Photos/birthday-at-the-zoo/panda.jpg') + * .pipe(file.createWriteStream({ + * metadata: { + * contentType: 'image/jpeg', + * metadata: { + * custom: 'metadata' + * } + * } + * })) + * .on('error', function(err) {}) + * .on('finish', function() { + * // The file upload is complete. + * }); + * ``` + * + * //- + * //

Continuing a Resumable Upload

+ * // + * // One can capture a `uri` from a resumable upload to reuse later. + * // Additionally, for validation, one can also capture and pass `crc32c`. + * //- + * let uri: string | undefined = undefined; + * let resumeCRC32C: string | undefined = undefined; + * + * fs.createWriteStream() + * .on('uri', link => {uri = link}) + * .on('crc32', crc32c => {resumeCRC32C = crc32c}); + * + * // later... + * fs.createWriteStream({uri, resumeCRC32C}); + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + createWriteStream(options = {}) { + var _a; + (_a = options.metadata) !== null && _a !== void 0 ? _a : (options.metadata = {}); + if (options.contentType) { + options.metadata.contentType = options.contentType; + } + if (!options.metadata.contentType || + options.metadata.contentType === 'auto') { + const detectedContentType = mime_1.default.getType(this.name); + if (detectedContentType) { + options.metadata.contentType = detectedContentType; + } + } + let gzip = options.gzip; + if (gzip === 'auto') { + gzip = COMPRESSIBLE_MIME_REGEX.test(options.metadata.contentType || ''); + } + if (gzip) { + options.metadata.contentEncoding = 'gzip'; + } + let crc32c = true; + let md5 = false; + if (typeof options.validation === 'string') { + options.validation = options.validation.toLowerCase(); + crc32c = options.validation === 'crc32c'; + md5 = options.validation === 'md5'; + } + else if (options.validation === false) { + crc32c = false; + md5 = false; + } + if (options.offset) { + if (md5) { + throw new RangeError(FileExceptionMessages.MD5_RESUMED_UPLOAD); + } + if (crc32c && !options.isPartialUpload && !options.resumeCRC32C) { + throw new RangeError(FileExceptionMessages.MISSING_RESUME_CRC32C_FINAL_UPLOAD); + } + } + /** + * A callback for determining when the underlying pipeline is complete. + * It's possible the pipeline callback could error before the write stream + * calls `final` so by default this will destroy the write stream unless the + * write stream sets this callback via its `final` handler. + * @param error An optional error + */ + let pipelineCallback = error => { + writeStream.destroy(error || undefined); + }; + // A stream for consumer to write to + const writeStream = new stream_1.Writable({ + final(cb) { + // Set the pipeline callback to this callback so the pipeline's results + // can be populated to the consumer + pipelineCallback = cb; + emitStream.end(); + }, + write(chunk, encoding, cb) { + emitStream.write(chunk, encoding, cb); + }, + }); + // If the write stream, which is returned to the caller, catches an error we need to make sure that + // at least one of the streams in the pipeline below gets notified so that they + // all get cleaned up / destroyed. + writeStream.once('error', e => { + emitStream.destroy(e); + }); + // If the write stream is closed, cleanup the pipeline below by calling destroy on one of the streams. + writeStream.once('close', () => { + emitStream.destroy(); + }); + const transformStreams = []; + if (gzip) { + transformStreams.push(zlib.createGzip()); + } + const emitStream = new util_js_2.PassThroughShim(); + let hashCalculatingStream = null; + if (crc32c || md5) { + const crc32cInstance = options.resumeCRC32C + ? crc32c_js_1.CRC32C.from(options.resumeCRC32C) + : undefined; + hashCalculatingStream = new hash_stream_validator_js_1.HashStreamValidator({ + crc32c, + crc32cInstance, + md5, + crc32cGenerator: this.crc32cGenerator, + updateHashesOnly: true, + }); + transformStreams.push(hashCalculatingStream); + } + const fileWriteStream = (0, duplexify_1.default)(); + let fileWriteStreamMetadataReceived = false; + // Handing off emitted events to users + emitStream.on('reading', () => writeStream.emit('reading')); + emitStream.on('writing', () => writeStream.emit('writing')); + fileWriteStream.on('uri', evt => writeStream.emit('uri', evt)); + fileWriteStream.on('progress', evt => writeStream.emit('progress', evt)); + fileWriteStream.on('response', resp => writeStream.emit('response', resp)); + fileWriteStream.once('metadata', () => { + fileWriteStreamMetadataReceived = true; + }); + writeStream.once('writing', () => { + if (options.resumable === false) { + this.startSimpleUpload_(fileWriteStream, options); + } + else { + this.startResumableUpload_(fileWriteStream, options); + } + (0, stream_1.pipeline)(emitStream, ...transformStreams, fileWriteStream, async (e) => { + if (e) { + return pipelineCallback(e); + } + // We want to make sure we've received the metadata from the server in order + // to properly validate the object's integrity. Depending on the type of upload, + // the stream could close before the response is returned. + if (!fileWriteStreamMetadataReceived) { + try { + await new Promise((resolve, reject) => { + fileWriteStream.once('metadata', resolve); + fileWriteStream.once('error', reject); + }); + } + catch (e) { + return pipelineCallback(e); + } + } + // Emit the local CRC32C value for future validation, if validation is enabled. + if (hashCalculatingStream === null || hashCalculatingStream === void 0 ? void 0 : hashCalculatingStream.crc32c) { + writeStream.emit('crc32c', hashCalculatingStream.crc32c); + } + try { + // Metadata may not be ready if the upload is a partial upload, + // nothing to validate yet. + const metadataNotReady = options.isPartialUpload && !this.metadata; + if (hashCalculatingStream && !metadataNotReady) { + await __classPrivateFieldGet(this, _File_instances, "m", _File_validateIntegrity).call(this, hashCalculatingStream, { + crc32c, + md5, + }); + } + pipelineCallback(); + } + catch (e) { + pipelineCallback(e); + } + }); + }); + return writeStream; + } + delete(optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb; + this.disableAutoRetryConditionallyIdempotent_(this.methods.delete, bucket_js_1.AvailableServiceObjectMethods.delete, options); + super + .delete(options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } + /** + * @typedef {array} DownloadResponse + * @property [0] The contents of a File. + */ + /** + * @callback DownloadCallback + * @param err Request error, if any. + * @param contents The contents of a File. + */ + /** + * Convenience method to download a file into memory or to a local + * destination. + * + * @param {object} [options] Configuration options. The arguments match those + * passed to {@link File#createReadStream}. + * @param {string} [options.destination] Local file path to write the file's + * contents to. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DownloadCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Download a file into memory. The contents will be available as the + * second + * // argument in the demonstration below, `contents`. + * //- + * file.download(function(err, contents) {}); + * + * //- + * // Download a file to a local destination. + * //- + * file.download({ + * destination: '/Users/me/Desktop/file-backup.txt' + * }, function(err) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.download().then(function(data) { + * const contents = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_download_file + * Another example: + * + * @example include:samples/encryption.js + * region_tag:storage_download_encrypted_file + * Example of downloading an encrypted file: + * + * @example include:samples/requesterPays.js + * region_tag:storage_download_file_requester_pays + * Example of downloading a file where the requester pays: + */ + download(optionsOrCallback, cb) { + let options; + if (typeof optionsOrCallback === 'function') { + cb = optionsOrCallback; + options = {}; + } + else { + options = optionsOrCallback; + } + let called = false; + const callback = ((...args) => { + if (!called) + cb(...args); + called = true; + }); + const destination = options.destination; + delete options.destination; + const fileStream = this.createReadStream(options); + let receivedData = false; + if (destination) { + fileStream + .on('error', callback) + .once('data', data => { + receivedData = true; + // We know that the file exists the server - now we can truncate/write to a file + const writable = fs.createWriteStream(destination); + writable.write(data); + fileStream + .pipe(writable) + .on('error', (err) => { + callback(err, Buffer.from('')); + }) + .on('finish', () => { + callback(null, data); + }); + }) + .on('end', () => { + // In the case of an empty file no data will be received before the end event fires + if (!receivedData) { + const data = Buffer.alloc(0); + try { + fs.writeFileSync(destination, data); + callback(null, data); + } + catch (e) { + callback(e, data); + } + } + }); + } + else { + this.getBufferFromReadable(fileStream) + .then(contents => callback === null || callback === void 0 ? void 0 : callback(null, contents)) + .catch(callback); + } + } + /** + * The Storage API allows you to use a custom key for server-side encryption. + * + * See {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys} + * + * @param {string|buffer} encryptionKey An AES-256 encryption key. + * @returns {File} + * + * @example + * ``` + * const crypto = require('crypto'); + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const encryptionKey = crypto.randomBytes(32); + * + * const fileWithCustomEncryption = myBucket.file('my-file'); + * fileWithCustomEncryption.setEncryptionKey(encryptionKey); + * + * const fileWithoutCustomEncryption = myBucket.file('my-file'); + * + * fileWithCustomEncryption.save('data', function(err) { + * // Try to download with the File object that hasn't had + * // `setEncryptionKey()` called: + * fileWithoutCustomEncryption.download(function(err) { + * // We will receive an error: + * // err.message === 'Bad Request' + * + * // Try again with the File object we called `setEncryptionKey()` on: + * fileWithCustomEncryption.download(function(err, contents) { + * // contents.toString() === 'data' + * }); + * }); + * }); + * + * ``` + * @example include:samples/encryption.js + * region_tag:storage_upload_encrypted_file + * Example of uploading an encrypted file: + * + * @example include:samples/encryption.js + * region_tag:storage_download_encrypted_file + * Example of downloading an encrypted file: + */ + setEncryptionKey(encryptionKey) { + this.encryptionKey = encryptionKey; + this.encryptionKeyBase64 = Buffer.from(encryptionKey).toString('base64'); + this.encryptionKeyHash = crypto + .createHash('sha256') + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .update(this.encryptionKeyBase64, 'base64') + .digest('base64'); + this.encryptionKeyInterceptor = { + request: reqOpts => { + reqOpts.headers = reqOpts.headers || {}; + reqOpts.headers['x-goog-encryption-algorithm'] = 'AES256'; + reqOpts.headers['x-goog-encryption-key'] = this.encryptionKeyBase64; + reqOpts.headers['x-goog-encryption-key-sha256'] = + this.encryptionKeyHash; + return reqOpts; + }, + }; + this.interceptors.push(this.encryptionKeyInterceptor); + return this; + } + /** + * Gets a reference to a Cloud Storage {@link File} file from the provided URL in string format. + * @param {string} publicUrlOrGsUrl the URL as a string. Must be of the format gs://bucket/file + * or https://storage.googleapis.com/bucket/file. + * @param {Storage} storageInstance an instance of a Storage object. + * @param {FileOptions} [options] Configuration options + * @returns {File} + */ + static from(publicUrlOrGsUrl, storageInstance, options) { + const gsMatches = [...publicUrlOrGsUrl.matchAll(GS_UTIL_URL_REGEX)]; + const httpsMatches = [...publicUrlOrGsUrl.matchAll(HTTPS_PUBLIC_URL_REGEX)]; + if (gsMatches.length > 0) { + const bucket = new bucket_js_1.Bucket(storageInstance, gsMatches[0][2]); + return new File(bucket, gsMatches[0][3], options); + } + else if (httpsMatches.length > 0) { + const bucket = new bucket_js_1.Bucket(storageInstance, httpsMatches[0][3]); + return new File(bucket, httpsMatches[0][4], options); + } + else { + throw new Error('URL string must be of format gs://bucket/file or https://storage.googleapis.com/bucket/file'); + } + } + get(optionsOrCallback, cb) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + super + .get(options) + .then(resp => cb(null, ...resp)) + .catch(cb); + } + /** + * @typedef {array} GetExpirationDateResponse + * @property {date} 0 A Date object representing the earliest time this file's + * retention policy will expire. + */ + /** + * @callback GetExpirationDateCallback + * @param {?Error} err Request error, if any. + * @param {date} expirationDate A Date object representing the earliest time + * this file's retention policy will expire. + */ + /** + * If this bucket has a retention policy defined, use this method to get a + * Date object representing the earliest time this file will expire. + * + * @param {GetExpirationDateCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const storage = require('@google-cloud/storage')(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.getExpirationDate(function(err, expirationDate) { + * // expirationDate is a Date object. + * }); + * ``` + */ + getExpirationDate(callback) { + this.getMetadata((err, metadata, apiResponse) => { + if (err) { + callback(err, null, apiResponse); + return; + } + if (!metadata.retentionExpirationTime) { + const error = new Error(FileExceptionMessages.EXPIRATION_TIME_NA); + callback(error, null, apiResponse); + return; + } + callback(null, new Date(metadata.retentionExpirationTime), apiResponse); + }); + } + /** + * @typedef {array} GenerateSignedPostPolicyV2Response + * @property {object} 0 The document policy. + */ + /** + * @callback GenerateSignedPostPolicyV2Callback + * @param {?Error} err Request error, if any. + * @param {object} policy The document policy. + */ + /** + * Get a signed policy document to allow a user to upload data with a POST + * request. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed policy. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/xml-api/post-object-v2| POST Object with the V2 signing process} + * + * @throws {Error} If an expiration timestamp from the past is given. + * @throws {Error} If options.equals has an array with less or more than two + * members. + * @throws {Error} If options.startsWith has an array with less or more than two + * members. + * + * @param {object} options Configuration options. + * @param {array|array[]} [options.equals] Array of request parameters and + * their expected value (e.g. [['$', '']]). Values are + * translated into equality constraints in the conditions field of the + * policy document (e.g. ['eq', '$', '']). If only one + * equality condition is to be specified, options.equals can be a one- + * dimensional array (e.g. ['$', '']). + * @param {*} options.expires - A timestamp when this policy will expire. Any + * value given is passed to `new Date()`. + * @param {array|array[]} [options.startsWith] Array of request parameters and + * their expected prefixes (e.g. [['$', '']). Values are + * translated into starts-with constraints in the conditions field of the + * policy document (e.g. ['starts-with', '$', '']). If only + * one prefix condition is to be specified, options.startsWith can be a + * one- dimensional array (e.g. ['$', '']). + * @param {string} [options.acl] ACL for the object from possibly predefined + * ACLs. + * @param {string} [options.successRedirect] The URL to which the user client + * is redirected if the upload is successful. + * @param {string} [options.successStatus] - The status of the Google Storage + * response if the upload is successful (must be string). + * @param {object} [options.contentLengthRange] + * @param {number} [options.contentLengthRange.min] Minimum value for the + * request's content length. + * @param {number} [options.contentLengthRange.max] Maximum value for the + * request's content length. + * @param {GenerateSignedPostPolicyV2Callback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * const options = { + * equals: ['$Content-Type', 'image/jpeg'], + * expires: '10-25-2022', + * contentLengthRange: { + * min: 0, + * max: 1024 + * } + * }; + * + * file.generateSignedPostPolicyV2(options, function(err, policy) { + * // policy.string: the policy document in plain text. + * // policy.base64: the policy document in base64. + * // policy.signature: the policy signature in base64. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.generateSignedPostPolicyV2(options).then(function(data) { + * const policy = data[0]; + * }); + * ``` + */ + generateSignedPostPolicyV2(optionsOrCallback, cb) { + const args = (0, util_js_2.normalize)(optionsOrCallback, cb); + let options = args.options; + const callback = args.callback; + const expires = new Date(options.expires); + if (isNaN(expires.getTime())) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_INVALID); + } + if (expires.valueOf() < Date.now()) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_PAST); + } + options = Object.assign({}, options); + const conditions = [ + ['eq', '$key', this.name], + { + bucket: this.bucket.name, + }, + ]; + if (Array.isArray(options.equals)) { + if (!Array.isArray(options.equals[0])) { + options.equals = [options.equals]; + } + options.equals.forEach(condition => { + if (!Array.isArray(condition) || condition.length !== 2) { + throw new Error(FileExceptionMessages.EQUALS_CONDITION_TWO_ELEMENTS); + } + conditions.push(['eq', condition[0], condition[1]]); + }); + } + if (Array.isArray(options.startsWith)) { + if (!Array.isArray(options.startsWith[0])) { + options.startsWith = [options.startsWith]; + } + options.startsWith.forEach(condition => { + if (!Array.isArray(condition) || condition.length !== 2) { + throw new Error(FileExceptionMessages.STARTS_WITH_TWO_ELEMENTS); + } + conditions.push(['starts-with', condition[0], condition[1]]); + }); + } + if (options.acl) { + conditions.push({ + acl: options.acl, + }); + } + if (options.successRedirect) { + conditions.push({ + success_action_redirect: options.successRedirect, + }); + } + if (options.successStatus) { + conditions.push({ + success_action_status: options.successStatus, + }); + } + if (options.contentLengthRange) { + const min = options.contentLengthRange.min; + const max = options.contentLengthRange.max; + if (typeof min !== 'number' || typeof max !== 'number') { + throw new Error(FileExceptionMessages.CONTENT_LENGTH_RANGE_MIN_MAX); + } + conditions.push(['content-length-range', min, max]); + } + const policy = { + expiration: expires.toISOString(), + conditions, + }; + const policyString = JSON.stringify(policy); + const policyBase64 = Buffer.from(policyString).toString('base64'); + this.storage.authClient.sign(policyBase64, options.signingEndpoint).then(signature => { + callback(null, { + string: policyString, + base64: policyBase64, + signature, + }); + }, err => { + callback(new signer_js_1.SigningError(err.message)); + }); + } + /** + * @typedef {object} SignedPostPolicyV4Output + * @property {string} url The request URL. + * @property {object} fields The form fields to include in the POST request. + */ + /** + * @typedef {array} GenerateSignedPostPolicyV4Response + * @property {SignedPostPolicyV4Output} 0 An object containing the request URL and form fields. + */ + /** + * @callback GenerateSignedPostPolicyV4Callback + * @param {?Error} err Request error, if any. + * @param {SignedPostPolicyV4Output} output An object containing the request URL and form fields. + */ + /** + * Get a v4 signed policy document to allow a user to upload data with a POST + * request. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed policy. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/xml-api/post-object#policydocument| Policy Document Reference} + * + * @param {object} options Configuration options. + * @param {Date|number|string} options.expires - A timestamp when this policy will expire. Any + * value given is passed to `new Date()`. + * @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style + * URLs ('https://mybucket.storage.googleapis.com/...') instead of path-style + * ('https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instead of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @param {string} [config.bucketBoundHostname] The bucket-bound hostname to return in + * the result, e.g. "https://cdn.example.com". + * @param {object} [config.fields] [Form fields]{@link https://cloud.google.com/storage/docs/xml-api/post-object#policydocument} + * to include in the signed policy. Any fields with key beginning with 'x-ignore-' + * will not be included in the policy to be signed. + * @param {object[]} [config.conditions] [Conditions]{@link https://cloud.google.com/storage/docs/authentication/signatures#policy-document} + * to include in the signed policy. All fields given in `config.fields` are + * automatically included in the conditions array, adding the same entry + * in both `fields` and `conditions` will result in duplicate entries. + * + * @param {GenerateSignedPostPolicyV4Callback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * const options = { + * expires: '10-25-2022', + * conditions: [ + * ['eq', '$Content-Type', 'image/jpeg'], + * ['content-length-range', 0, 1024], + * ], + * fields: { + * acl: 'public-read', + * 'x-goog-meta-foo': 'bar', + * 'x-ignore-mykey': 'data' + * } + * }; + * + * file.generateSignedPostPolicyV4(options, function(err, response) { + * // response.url The request URL + * // response.fields The form fields (including the signature) to include + * // to be used to upload objects by HTML forms. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.generateSignedPostPolicyV4(options).then(function(data) { + * const response = data[0]; + * // response.url The request URL + * // response.fields The form fields (including the signature) to include + * // to be used to upload objects by HTML forms. + * }); + * ``` + */ + generateSignedPostPolicyV4(optionsOrCallback, cb) { + const args = (0, util_js_2.normalize)(optionsOrCallback, cb); + let options = args.options; + const callback = args.callback; + const expires = new Date(options.expires); + if (isNaN(expires.getTime())) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_INVALID); + } + if (expires.valueOf() < Date.now()) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_PAST); + } + if (expires.valueOf() - Date.now() > SEVEN_DAYS * 1000) { + throw new Error(`Max allowed expiration is seven days (${SEVEN_DAYS} seconds).`); + } + options = Object.assign({}, options); + let fields = Object.assign({}, options.fields); + const now = new Date(); + const nowISO = (0, util_js_2.formatAsUTCISO)(now, true); + const todayISO = (0, util_js_2.formatAsUTCISO)(now); + const sign = async () => { + const { client_email } = await this.storage.authClient.getCredentials(); + const credential = `${client_email}/${todayISO}/auto/storage/goog4_request`; + fields = { + ...fields, + bucket: this.bucket.name, + key: this.name, + 'x-goog-date': nowISO, + 'x-goog-credential': credential, + 'x-goog-algorithm': 'GOOG4-RSA-SHA256', + }; + const conditions = options.conditions || []; + Object.entries(fields).forEach(([key, value]) => { + if (!key.startsWith('x-ignore-')) { + conditions.push({ [key]: value }); + } + }); + delete fields.bucket; + const expiration = (0, util_js_2.formatAsUTCISO)(expires, true, '-', ':'); + const policy = { + conditions, + expiration, + }; + const policyString = (0, util_js_2.unicodeJSONStringify)(policy); + const policyBase64 = Buffer.from(policyString).toString('base64'); + try { + const signature = await this.storage.authClient.sign(policyBase64, options.signingEndpoint); + const signatureHex = Buffer.from(signature, 'base64').toString('hex'); + const universe = this.parent.storage.universeDomain; + fields['policy'] = policyBase64; + fields['x-goog-signature'] = signatureHex; + let url; + if (this.storage.customEndpoint) { + url = this.storage.apiEndpoint; + } + else if (options.virtualHostedStyle) { + url = `https://${this.bucket.name}.storage.${universe}/`; + } + else if (options.bucketBoundHostname) { + url = `${options.bucketBoundHostname}/`; + } + else { + url = `https://storage.${universe}/${this.bucket.name}/`; + } + return { + url, + fields, + }; + } + catch (err) { + throw new signer_js_1.SigningError(err.message); + } + }; + sign().then(res => callback(null, res), callback); + } + /** + * @typedef {array} GetSignedUrlResponse + * @property {object} 0 The signed URL. + */ + /** + * @callback GetSignedUrlCallback + * @param {?Error} err Request error, if any. + * @param {object} url The signed URL. + */ + /** + * Get a signed URL to allow limited time access to the file. + * + * In Google Cloud Platform environments, such as Cloud Functions and App + * Engine, you usually don't provide a `keyFilename` or `credentials` during + * instantiation. In those environments, we call the + * {@link https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob| signBlob API} + * to create a signed URL. That API requires either the + * `https://www.googleapis.com/auth/iam` or + * `https://www.googleapis.com/auth/cloud-platform` scope, so be sure they are + * enabled. + * + * See {@link https://cloud.google.com/storage/docs/access-control/signed-urls| Signed URLs Reference} + * + * @throws {Error} if an expiration timestamp from the past is given. + * + * @param {object} config Configuration object. + * @param {string} config.action "read" (HTTP: GET), "write" (HTTP: PUT), or + * "delete" (HTTP: DELETE), "resumable" (HTTP: POST). + * When using "resumable", the header `X-Goog-Resumable: start` has + * to be sent when making a request with the signed URL. + * @param {*} config.expires A timestamp when this link will expire. Any value + * given is passed to `new Date()`. + * Note: 'v4' supports maximum duration of 7 days (604800 seconds) from now. + * See [reference]{@link https://cloud.google.com/storage/docs/access-control/signed-urls#example} + * @param {string} [config.version='v2'] The signing version to use, either + * 'v2' or 'v4'. + * @param {boolean} [config.virtualHostedStyle=false] Use virtual hosted-style + * URLs (e.g. 'https://mybucket.storage.googleapis.com/...') instead of path-style + * (e.g. 'https://storage.googleapis.com/mybucket/...'). Virtual hosted-style URLs + * should generally be preferred instaed of path-style URL. + * Currently defaults to `false` for path-style, although this may change in a + * future major-version release. + * @param {string} [config.cname] The cname for this bucket, i.e., + * "https://cdn.example.com". + * @param {string} [config.contentMd5] The MD5 digest value in base64. Just like + * if you provide this, the client must provide this HTTP header with this same + * value in its request, so to if this parameter is not provided here, + * the client must not provide any value for this HTTP header in its request. + * @param {string} [config.contentType] Just like if you provide this, the client + * must provide this HTTP header with this same value in its request, so to if + * this parameter is not provided here, the client must not provide any value + * for this HTTP header in its request. + * @param {object} [config.extensionHeaders] If these headers are used, the + * server will check to make sure that the client provides matching + * values. See {@link https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers| Canonical extension headers} + * for the requirements of this feature, most notably: + * - The header name must be prefixed with `x-goog-` + * - The header name must be all lowercase + * + * Note: Multi-valued header passed as an array in the extensionHeaders + * object is converted into a string, delimited by `,` with + * no space. Requests made using the signed URL will need to + * delimit multi-valued headers using a single `,` as well, or + * else the server will report a mismatched signature. + * @param {object} [config.queryParams] Additional query parameters to include + * in the signed URL. + * @param {string} [config.promptSaveAs] The filename to prompt the user to + * save the file as when the signed url is accessed. This is ignored if + * `config.responseDisposition` is set. + * @param {string} [config.responseDisposition] The + * {@link http://goo.gl/yMWxQV| response-content-disposition parameter} of the + * signed url. + * @param {*} [config.accessibleAt=Date.now()] A timestamp when this link became usable. Any value + * given is passed to `new Date()`. + * Note: Use for 'v4' only. + * @param {string} [config.responseType] The response-content-type parameter + * of the signed url. + * @param {GetSignedUrlCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Generate a URL that allows temporary access to download your file. + * //- + * const request = require('request'); + * + * const config = { + * action: 'read', + * expires: '03-17-2025', + * }; + * + * file.getSignedUrl(config, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The file is now available to read from this URL. + * request(url, function(err, resp) { + * // resp.statusCode = 200 + * }); + * }); + * + * //- + * // Generate a URL that allows temporary access to download your file. + * // Access will begin at accessibleAt and end at expires. + * //- + * const request = require('request'); + * + * const config = { + * action: 'read', + * expires: '03-17-2025', + * accessibleAt: '03-13-2025' + * }; + * + * file.getSignedUrl(config, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The file will be available to read from this URL from 03-13-2025 to 03-17-2025. + * request(url, function(err, resp) { + * // resp.statusCode = 200 + * }); + * }); + * + * //- + * // Generate a URL to allow write permissions. This means anyone with this + * URL + * // can send a POST request with new data that will overwrite the file. + * //- + * file.getSignedUrl({ + * action: 'write', + * expires: '03-17-2025' + * }, function(err, url) { + * if (err) { + * console.error(err); + * return; + * } + * + * // The file is now available to be written to. + * const writeStream = request.put(url); + * writeStream.end('New data'); + * + * writeStream.on('complete', function(resp) { + * // Confirm the new content was saved. + * file.download(function(err, fileContents) { + * console.log('Contents:', fileContents.toString()); + * // Contents: New data + * }); + * }); + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.getSignedUrl(config).then(function(data) { + * const url = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_generate_signed_url + * Another example: + */ + getSignedUrl(cfg, callback) { + const method = ActionToHTTPMethod[cfg.action]; + const extensionHeaders = (0, util_js_2.objectKeyToLowercase)(cfg.extensionHeaders || {}); + if (cfg.action === 'resumable') { + extensionHeaders['x-goog-resumable'] = 'start'; + } + const queryParams = Object.assign({}, cfg.queryParams); + if (typeof cfg.responseType === 'string') { + queryParams['response-content-type'] = cfg.responseType; + } + if (typeof cfg.promptSaveAs === 'string') { + queryParams['response-content-disposition'] = + 'attachment; filename="' + cfg.promptSaveAs + '"'; + } + if (typeof cfg.responseDisposition === 'string') { + queryParams['response-content-disposition'] = cfg.responseDisposition; + } + if (this.generation) { + queryParams['generation'] = this.generation.toString(); + } + const signConfig = { + method, + expires: cfg.expires, + accessibleAt: cfg.accessibleAt, + extensionHeaders, + queryParams, + contentMd5: cfg.contentMd5, + contentType: cfg.contentType, + host: cfg.host, + }; + if (cfg.cname) { + signConfig.cname = cfg.cname; + } + if (cfg.version) { + signConfig.version = cfg.version; + } + if (cfg.virtualHostedStyle) { + signConfig.virtualHostedStyle = cfg.virtualHostedStyle; + } + if (!this.signer) { + this.signer = new signer_js_1.URLSigner(this.storage.authClient, this.bucket, this, this.storage); + } + this.signer + .getSignedUrl(signConfig) + .then(signedUrl => callback(null, signedUrl), callback); + } + /** + * @callback IsPublicCallback + * @param {?Error} err Request error, if any. + * @param {boolean} resp Whether file is public or not. + */ + /** + * @typedef {array} IsPublicResponse + * @property {boolean} 0 Whether file is public or not. + */ + /** + * Check whether this file is public or not by sending + * a HEAD request without credentials. + * No errors from the server indicates that the current + * file is public. + * A 403-Forbidden error {@link https://cloud.google.com/storage/docs/json_api/v1/status-codes#403_Forbidden} + * indicates that file is private. + * Any other non 403 error is propagated to user. + * + * @param {IsPublicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Check whether the file is publicly accessible. + * //- + * file.isPublic(function(err, resp) { + * if (err) { + * console.error(err); + * return; + * } + * console.log(`the file ${file.id} is public: ${resp}`) ; + * }) + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.isPublic().then(function(data) { + * const resp = data[0]; + * }); + * ``` + */ + isPublic(callback) { + var _a; + // Build any custom headers based on the defined interceptors on the parent + // storage object and this object + const storageInterceptors = ((_a = this.storage) === null || _a === void 0 ? void 0 : _a.interceptors) || []; + const fileInterceptors = this.interceptors || []; + const allInterceptors = storageInterceptors.concat(fileInterceptors); + const headers = allInterceptors.reduce((acc, curInterceptor) => { + const currentHeaders = curInterceptor.request({ + uri: `${this.storage.apiEndpoint}/${this.bucket.name}/${encodeURIComponent(this.name)}`, + }); + Object.assign(acc, currentHeaders.headers); + return acc; + }, {}); + index_js_1.util.makeRequest({ + method: 'GET', + uri: `${this.storage.apiEndpoint}/${this.bucket.name}/${encodeURIComponent(this.name)}`, + headers, + }, { + retryOptions: this.storage.retryOptions, + }, (err) => { + if (err) { + const apiError = err; + if (apiError.code === 403) { + callback(null, false); + } + else { + callback(err); + } + } + else { + callback(null, true); + } + }); + } + /** + * @typedef {object} MakeFilePrivateOptions Configuration options for File#makePrivate(). + * @property {Metadata} [metadata] Define custom metadata properties to define + * along with the operation. + * @property {boolean} [strict] If true, set the file to be private to + * only the owner user. Otherwise, it will be private to the project. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback MakeFilePrivateCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} MakeFilePrivateResponse + * @property {object} 0 The full API response. + */ + /** + * Make a file private to the project and remove all other permissions. + * Set `options.strict` to true to make the file private to only the owner. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/patch| Objects: patch API Documentation} + * + * @param {MakeFilePrivateOptions} [options] Configuration options. + * @param {MakeFilePrivateCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * //- + * // Set the file private so only project maintainers can see and modify it. + * //- + * file.makePrivate(function(err) {}); + * + * //- + * // Set the file private so only the owner can see and modify it. + * //- + * file.makePrivate({ strict: true }, function(err) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.makePrivate().then(function(data) { + * const apiResponse = data[0]; + * }); + * ``` + */ + makePrivate(optionsOrCallback, callback) { + var _a, _b; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const query = { + predefinedAcl: options.strict ? 'private' : 'projectPrivate', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + }; + if (((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifMetagenerationMatch) !== undefined) { + query.ifMetagenerationMatch = + (_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifMetagenerationMatch; + delete options.preconditionOpts; + } + if (options.userProject) { + query.userProject = options.userProject; + } + // You aren't allowed to set both predefinedAcl & acl properties on a file, + // so acl must explicitly be nullified, destroying all previous acls on the + // file. + const metadata = { ...options.metadata, acl: null }; + this.setMetadata(metadata, query, callback); + } + /** + * @typedef {array} MakeFilePublicResponse + * @property {object} 0 The full API response. + */ + /** + * @callback MakeFilePublicCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Set a file to be publicly readable and maintain all previous permissions. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objectAccessControls/insert| ObjectAccessControls: insert API Documentation} + * + * @param {MakeFilePublicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * + * file.makePublic(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.makePublic().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_make_public + * Another example: + */ + makePublic(callback) { + callback = callback || index_js_1.util.noop; + this.acl.add({ + entity: 'allUsers', + role: 'READER', + }, (err, acl, resp) => { + callback(err, resp); + }); + } + /** + * The public URL of this File + * Use {@link File#makePublic} to enable anonymous access via the returned URL. + * + * @returns {string} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const file = bucket.file('my-file'); + * + * // publicUrl will be "https://storage.googleapis.com/albums/my-file" + * const publicUrl = file.publicUrl(); + * ``` + */ + publicUrl() { + return `${this.storage.apiEndpoint}/${this.bucket.name}/${encodeURIComponent(this.name)}`; + } + /** + * @typedef {array} MoveFileAtomicResponse + * @property {File} 0 The moved {@link File}. + * @property {object} 1 The full API response. + */ + /** + * @callback MoveFileAtomicCallback + * @param {?Error} err Request error, if any. + * @param {File} movedFile The moved {@link File}. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} MoveFileAtomicOptions Configuration options for File#moveFileAtomic(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + * @property {object} [preconditionOpts] Precondition options. + * @property {number} [preconditionOpts.ifGenerationMatch] Makes the operation conditional on whether the object's current generation matches the given value. + */ + /** + * Move this file within the same HNS-enabled bucket. + * The source object must exist and be a live object. + * The source and destination object IDs must be different. + * Overwriting the destination object is allowed by default, but can be prevented + * using preconditions. + * If the destination path includes non-existent parent folders, they will be created. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/move| Objects: move API Documentation} + * + * @throws {Error} If the destination file is not provided. + * + * @param {string|File} destination Destination file name or File object within the same bucket.. + * @param {MoveFileAtomicOptions} [options] Configuration options. See an + * @param {MoveFileAtomicCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Assume 'my-hns-bucket' is an HNS-enabled bucket. + * //- + * const bucket = storage.bucket('my-hns-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // If you pass in a string for the destination, the file is copied to its + * // current bucket, under the new name provided. + * //- + * file.moveFileAtomic('moved-image.png', function(err, movedFile, apiResponse) { + * // `my-hns-bucket` now contains: + * // - "moved-image.png" + * + * // `movedFile` is an instance of a File object that refers to your new + * // file. + * }); + * + * //- + * // Move the file to a subdirectory, creating parent folders if necessary. + * //- + * file.moveFileAtomic('new-folder/subfolder/moved-image.png', function(err, movedFile, apiResponse) { + * // `my-hns-bucket` now contains: + * // - "new-folder/subfolder/moved-image.png" + * }); + * + * //- + * // Prevent overwriting an existing destination object using preconditions. + * //- + * file.moveFileAtomic('existing-destination.png', { + * preconditionOpts: { + * ifGenerationMatch: 0 // Fails if the destination object exists. + * } + * }, function(err, movedFile, apiResponse) { + * if (err) { + * // Handle the error (e.g., the destination object already exists). + * } else { + * // Move successful. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.moveFileAtomic('moved-image.png).then(function(data) { + * const newFile = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_move_file_hns + * Another example: + */ + moveFileAtomic(destination, optionsOrCallback, callback) { + var _a, _b; + const noDestinationError = new Error(FileExceptionMessages.DESTINATION_NO_NAME); + if (!destination) { + throw noDestinationError; + } + let options = {}; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + else if (optionsOrCallback) { + options = { ...optionsOrCallback }; + } + callback = callback || index_js_1.util.noop; + let destName; + let newFile; + if (typeof destination === 'string') { + const parsedDestination = GS_URL_REGEXP.exec(destination); + if (parsedDestination !== null && parsedDestination.length === 3) { + destName = parsedDestination[2]; + } + else { + destName = destination; + } + } + else if (destination instanceof File) { + destName = destination.name; + newFile = destination; + } + else { + throw noDestinationError; + } + newFile = newFile || this.bucket.file(destName); + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options === null || options === void 0 ? void 0 : options.preconditionOpts)) { + this.storage.retryOptions.autoRetry = false; + } + const query = {}; + if (options.userProject !== undefined) { + query.userProject = options.userProject; + delete options.userProject; + } + if (((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) !== undefined) { + query.ifGenerationMatch = (_b = options.preconditionOpts) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch; + delete options.preconditionOpts; + } + this.request({ + method: 'POST', + uri: `/moveTo/o/${encodeURIComponent(newFile.name)}`, + qs: query, + json: options, + }, (err, resp) => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + if (err) { + callback(err, null, resp); + return; + } + callback(null, newFile, resp); + }); + } + /** + * @typedef {array} MoveResponse + * @property {File} 0 The destination File. + * @property {object} 1 The full API response. + */ + /** + * @callback MoveCallback + * @param {?Error} err Request error, if any. + * @param {?File} destinationFile The destination File. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} MoveOptions Configuration options for File#move(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Move this file to another location. By default, this will rename the file + * and keep it in the same bucket, but you can choose to move it to another + * Bucket by providing a Bucket or File object or a URL beginning with + * "gs://". + * + * **Warning**: + * There is currently no atomic `move` method in the Cloud Storage API, + * so this method is a composition of {@link File#copy} (to the new + * location) and {@link File#delete} (from the old location). While + * unlikely, it is possible that an error returned to your callback could be + * triggered from either one of these API calls failing, which could leave a + * duplicate file lingering. The error message will indicate what operation + * has failed. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/objects/copy| Objects: copy API Documentation} + * + * @throws {Error} If the destination file is not provided. + * + * @param {string|Bucket|File} destination Destination file. + * @param {MoveCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * //- + * // You can pass in a variety of types for the destination. + * // + * // For all of the below examples, assume we are working with the following + * // Bucket and File objects. + * //- + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // If you pass in a string for the destination, the file is moved to its + * // current bucket, under the new name provided. + * //- + * file.move('my-image-new.png', function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // but contains instead: + * // - "my-image-new.png" + * + * // `destinationFile` is an instance of a File object that refers to your + * // new file. + * }); + * + * //- + * // If you pass in a string starting with "gs://" for the destination, the + * // file is copied to the other bucket and under the new name provided. + * //- + * const newLocation = 'gs://another-bucket/my-image-new.png'; + * file.move(newLocation, function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image-new.png" + * + * // `destinationFile` is an instance of a File object that refers to your + * // new file. + * }); + * + * //- + * // If you pass in a Bucket object, the file will be moved to that bucket + * // using the same name. + * //- + * const anotherBucket = gcs.bucket('another-bucket'); + * + * file.move(anotherBucket, function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-image.png" + * + * // `destinationFile` is an instance of a File object that refers to your + * // new file. + * }); + * + * //- + * // If you pass in a File object, you have complete control over the new + * // bucket and filename. + * //- + * const anotherFile = anotherBucket.file('my-awesome-image.png'); + * + * file.move(anotherFile, function(err, destinationFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // + * // `another-bucket` now contains: + * // - "my-awesome-image.png" + * + * // Note: + * // The `destinationFile` parameter is equal to `anotherFile`. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.move('my-image-new.png').then(function(data) { + * const destinationFile = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/files.js + * region_tag:storage_move_file + * Another example: + */ + move(destination, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + callback = callback || index_js_1.util.noop; + this.copy(destination, options, (err, destinationFile, copyApiResponse) => { + if (err) { + err.message = 'file#copy failed with an error - ' + err.message; + callback(err, null, copyApiResponse); + return; + } + if (this.name !== destinationFile.name || + this.bucket.name !== destinationFile.bucket.name) { + this.delete(options, (err, apiResponse) => { + if (err) { + err.message = 'file#delete failed with an error - ' + err.message; + callback(err, destinationFile, apiResponse); + return; + } + callback(null, destinationFile, copyApiResponse); + }); + } + else { + callback(null, destinationFile, copyApiResponse); + } + }); + } + /** + * @typedef {array} RenameResponse + * @property {File} 0 The destination File. + * @property {object} 1 The full API response. + */ + /** + * @callback RenameCallback + * @param {?Error} err Request error, if any. + * @param {?File} destinationFile The destination File. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {object} RenameOptions Configuration options for File#move(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * Rename this file. + * + * **Warning**: + * There is currently no atomic `rename` method in the Cloud Storage API, + * so this method is an alias of {@link File#move}, which in turn is a + * composition of {@link File#copy} (to the new location) and + * {@link File#delete} (from the old location). While + * unlikely, it is possible that an error returned to your callback could be + * triggered from either one of these API calls failing, which could leave a + * duplicate file lingering. The error message will indicate what operation + * has failed. + * + * @param {string|File} destinationFile Destination file. + * @param {RenameCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // You can pass in a string or a File object. + * // + * // For all of the below examples, assume we are working with the following + * // Bucket and File objects. + * //- + * + * const bucket = storage.bucket('my-bucket'); + * const file = bucket.file('my-image.png'); + * + * //- + * // You can pass in a string for the destinationFile. + * //- + * file.rename('renamed-image.png', function(err, renamedFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * // but contains instead: + * // - "renamed-image.png" + * + * // `renamedFile` is an instance of a File object that refers to your + * // renamed file. + * }); + * + * //- + * // You can pass in a File object. + * //- + * const anotherFile = anotherBucket.file('my-awesome-image.png'); + * + * file.rename(anotherFile, function(err, renamedFile, apiResponse) { + * // `my-bucket` no longer contains: + * // - "my-image.png" + * + * // Note: + * // The `renamedFile` parameter is equal to `anotherFile`. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.rename('my-renamed-image.png').then(function(data) { + * const renamedFile = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + rename(destinationFile, optionsOrCallback, callback) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + callback = callback || index_js_1.util.noop; + this.move(destinationFile, options, callback); + } + /** + * @typedef {object} RestoreOptions Options for File#restore(). See an + * {@link https://cloud.google.com/storage/docs/json_api/v1/objects#resource| Object resource}. + * @param {string} [userProject] The ID of the project which will be + * billed for the request. + * @param {number} [generation] If present, selects a specific revision of this object. + * @param {string} [restoreToken] Returns an option that must be specified when getting a soft-deleted object from an HNS-enabled + * bucket that has a naming and generation conflict with another object in the same bucket. + * @param {string} [projection] Specifies the set of properties to return. If used, must be 'full' or 'noAcl'. + * @param {string | number} [ifGenerationMatch] Request proceeds if the generation of the target resource + * matches the value used in the precondition. + * If the values don't match, the request fails with a 412 Precondition Failed response. + * @param {string | number} [ifGenerationNotMatch] Request proceeds if the generation of the target resource does + * not match the value used in the precondition. If the values match, the request fails with a 304 Not Modified response. + * @param {string | number} [ifMetagenerationMatch] Request proceeds if the meta-generation of the target resource + * matches the value used in the precondition. + * If the values don't match, the request fails with a 412 Precondition Failed response. + * @param {string | number} [ifMetagenerationNotMatch] Request proceeds if the meta-generation of the target resource does + * not match the value used in the precondition. If the values match, the request fails with a 304 Not Modified response. + */ + /** + * Restores a soft-deleted file + * @param {RestoreOptions} options Restore options. + * @returns {Promise} + */ + async restore(options) { + const [file] = await this.request({ + method: 'POST', + uri: '/restore', + qs: options, + }); + return file; + } + /** + * Makes request and applies userProject query parameter if necessary. + * + * @private + * + * @param {object} reqOpts - The request options. + * @param {function} callback - The callback function. + */ + request(reqOpts, callback) { + return this.parent.request.call(this, reqOpts, callback); + } + /** + * @callback RotateEncryptionKeyCallback + * @extends CopyCallback + */ + /** + * @typedef RotateEncryptionKeyResponse + * @extends CopyResponse + */ + /** + * @param {string|buffer|object} RotateEncryptionKeyOptions Configuration options + * for File#rotateEncryptionKey(). + * If a string or Buffer is provided, it is interpreted as an AES-256, + * customer-supplied encryption key. If you'd like to use a Cloud KMS key + * name, you must specify an options object with the property name: + * `kmsKeyName`. + * @param {string|buffer} [options.encryptionKey] An AES-256 encryption key. + * @param {string} [options.kmsKeyName] A Cloud KMS key name. + */ + /** + * This method allows you to update the encryption key associated with this + * file. + * + * See {@link https://cloud.google.com/storage/docs/encryption#customer-supplied| Customer-supplied Encryption Keys} + * + * @param {RotateEncryptionKeyOptions} [options] - Configuration options. + * @param {RotateEncryptionKeyCallback} [callback] + * @returns {Promise} + * + * @example include:samples/encryption.js + * region_tag:storage_rotate_encryption_key + * Example of rotating the encryption key for this file: + */ + rotateEncryptionKey(optionsOrCallback, callback) { + var _a; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + let options = {}; + if (typeof optionsOrCallback === 'string' || + optionsOrCallback instanceof Buffer) { + options = { + encryptionKey: optionsOrCallback, + }; + } + else if (typeof optionsOrCallback === 'object') { + options = optionsOrCallback; + } + const newFile = this.bucket.file(this.id, options); + const copyOptions = ((_a = options.preconditionOpts) === null || _a === void 0 ? void 0 : _a.ifGenerationMatch) !== undefined + ? { preconditionOpts: options.preconditionOpts } + : {}; + this.copy(newFile, copyOptions, callback); + } + /** + * @typedef {object} SaveOptions + * @extends CreateWriteStreamOptions + */ + /** + * @callback SaveCallback + * @param {?Error} err Request error, if any. + */ + /** + * Write strings or buffers to a file. + * + * *This is a convenience method which wraps {@link File#createWriteStream}.* + * To upload arbitrary data to a file, please use {@link File#createWriteStream} directly. + * + * Resumable uploads are automatically enabled and must be shut off explicitly + * by setting `options.resumable` to `false`. + * + * Multipart uploads with retryable error codes will be retried 3 times with exponential backoff. + * + *

+ * There is some overhead when using a resumable upload that can cause + * noticeable performance degradation while uploading a series of small + * files. When uploading files less than 10MB, it is recommended that the + * resumable feature is disabled. + *

+ * + * @param {SaveData} data The data to write to a file. + * @param {SaveOptions} [options] See {@link File#createWriteStream}'s `options` + * parameter. + * @param {SaveCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const file = myBucket.file('my-file'); + * const contents = 'This is the contents of the file.'; + * + * file.save(contents, function(err) { + * if (!err) { + * // File written successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.save(contents).then(function() {}); + * ``` + */ + save(data, optionsOrCallback, callback) { + // tslint:enable:no-any + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + let maxRetries = this.storage.retryOptions.maxRetries; + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options === null || options === void 0 ? void 0 : options.preconditionOpts)) { + maxRetries = 0; + } + const returnValue = (0, async_retry_1.default)(async (bail) => { + return new Promise((resolve, reject) => { + if (maxRetries === 0) { + this.storage.retryOptions.autoRetry = false; + } + const writable = this.createWriteStream(options); + if (options.onUploadProgress) { + writable.on('progress', options.onUploadProgress); + } + const handleError = (err) => { + if (this.storage.retryOptions.autoRetry && + this.storage.retryOptions.retryableErrorFn(err)) { + return reject(err); + } + return bail(err); + }; + if (typeof data === 'string' || + Buffer.isBuffer(data) || + data instanceof Uint8Array) { + writable + .on('error', handleError) + .on('finish', () => resolve()) + .end(data); + } + else { + (0, stream_1.pipeline)(data, writable, err => { + if (err) { + if (typeof data !== 'function') { + // Only PipelineSourceFunction can be retried. Async-iterables + // and Readable streams can only be consumed once. + return bail(err); + } + handleError(err); + } + else { + resolve(); + } + }); + } + }); + }, { + retries: maxRetries, + factor: this.storage.retryOptions.retryDelayMultiplier, + maxTimeout: this.storage.retryOptions.maxRetryDelay * 1000, //convert to milliseconds + maxRetryTime: this.storage.retryOptions.totalTimeout * 1000, //convert to milliseconds + }); + if (!callback) { + return returnValue; + } + else { + return returnValue + .then(() => { + if (callback) { + return callback(); + } + }) + .catch(callback); + } + } + setMetadata(metadata, optionsOrCallback, cb) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + this.disableAutoRetryConditionallyIdempotent_(this.methods.setMetadata, bucket_js_1.AvailableServiceObjectMethods.setMetadata, options); + super + .setMetadata(metadata, options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } + /** + * @typedef {array} SetStorageClassResponse + * @property {object} 0 The full API response. + */ + /** + * @typedef {object} SetStorageClassOptions Configuration options for File#setStorageClass(). + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @callback SetStorageClassCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Set the storage class for this file. + * + * See {@link https://cloud.google.com/storage/docs/per-object-storage-class| Per-Object Storage Class} + * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes} + * + * @param {string} storageClass The new storage class. (`standard`, + * `nearline`, `coldline`, or `archive`) + * **Note:** The storage classes `multi_regional` and `regional` + * are now legacy and will be deprecated in the future. + * @param {SetStorageClassOptions} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {SetStorageClassCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * file.setStorageClass('nearline', function(err, apiResponse) { + * if (err) { + * // Error handling omitted. + * } + * + * // The storage class was updated successfully. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * file.setStorageClass('nearline').then(function() {}); + * ``` + */ + setStorageClass(storageClass, optionsOrCallback, callback) { + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + const req = { + ...options, + // In case we get input like `storageClass`, convert to `storage_class`. + storageClass: storageClass + .replace(/-/g, '_') + .replace(/([a-z])([A-Z])/g, (_, low, up) => { + return low + '_' + up; + }) + .toUpperCase(), + }; + this.copy(this, req, (err, file, apiResponse) => { + if (err) { + callback(err, apiResponse); + return; + } + this.metadata = file.metadata; + callback(null, apiResponse); + }); + } + /** + * Set a user project to be billed for all requests made from this File + * object. + * + * @param {string} userProject The user project. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('albums'); + * const file = bucket.file('my-file'); + * + * file.setUserProject('grape-spaceship-123'); + * ``` + */ + setUserProject(userProject) { + this.bucket.setUserProject.call(this, userProject); + } + /** + * This creates a resumable-upload upload stream. + * + * @param {Duplexify} stream - Duplexify stream of data to pipe to the file. + * @param {object=} options - Configuration object. + * + * @private + */ + startResumableUpload_(dup, options = {}) { + var _a; + (_a = options.metadata) !== null && _a !== void 0 ? _a : (options.metadata = {}); + const retryOptions = this.storage.retryOptions; + if (!this.shouldRetryBasedOnPreconditionAndIdempotencyStrat(options.preconditionOpts)) { + retryOptions.autoRetry = false; + } + const cfg = { + authClient: this.storage.authClient, + apiEndpoint: this.storage.apiEndpoint, + bucket: this.bucket.name, + customRequestOptions: this.getRequestInterceptors().reduce((reqOpts, interceptorFn) => interceptorFn(reqOpts), {}), + file: this.name, + generation: this.generation, + isPartialUpload: options.isPartialUpload, + key: this.encryptionKey, + kmsKeyName: this.kmsKeyName, + metadata: options.metadata, + offset: options.offset, + predefinedAcl: options.predefinedAcl, + private: options.private, + public: options.public, + uri: options.uri, + userProject: options.userProject || this.userProject, + retryOptions: { ...retryOptions }, + params: (options === null || options === void 0 ? void 0 : options.preconditionOpts) || this.instancePreconditionOpts, + chunkSize: options === null || options === void 0 ? void 0 : options.chunkSize, + highWaterMark: options === null || options === void 0 ? void 0 : options.highWaterMark, + universeDomain: this.bucket.storage.universeDomain, + [util_js_1.GCCL_GCS_CMD_KEY]: options[util_js_1.GCCL_GCS_CMD_KEY], + }; + let uploadStream; + try { + uploadStream = resumableUpload.upload(cfg); + } + catch (error) { + dup.destroy(error); + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + return; + } + uploadStream + .on('response', resp => { + dup.emit('response', resp); + }) + .on('uri', uri => { + dup.emit('uri', uri); + }) + .on('metadata', metadata => { + this.metadata = metadata; + dup.emit('metadata'); + }) + .on('finish', () => { + dup.emit('complete'); + }) + .on('progress', evt => dup.emit('progress', evt)); + dup.setWritable(uploadStream); + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + } + /** + * Takes a readable stream and pipes it to a remote file. Unlike + * `startResumableUpload_`, which uses the resumable upload technique, this + * method uses a simple upload (all or nothing). + * + * @param {Duplexify} dup - Duplexify stream of data to pipe to the file. + * @param {object=} options - Configuration object. + * + * @private + */ + startSimpleUpload_(dup, options = {}) { + var _a; + (_a = options.metadata) !== null && _a !== void 0 ? _a : (options.metadata = {}); + const apiEndpoint = this.storage.apiEndpoint; + const bucketName = this.bucket.name; + const uri = `${apiEndpoint}/upload/storage/v1/b/${bucketName}/o`; + const reqOpts = { + qs: { + name: this.name, + }, + uri: uri, + [util_js_1.GCCL_GCS_CMD_KEY]: options[util_js_1.GCCL_GCS_CMD_KEY], + }; + if (this.generation !== undefined) { + reqOpts.qs.ifGenerationMatch = this.generation; + } + if (this.kmsKeyName !== undefined) { + reqOpts.qs.kmsKeyName = this.kmsKeyName; + } + if (typeof options.timeout === 'number') { + reqOpts.timeout = options.timeout; + } + if (options.userProject || this.userProject) { + reqOpts.qs.userProject = options.userProject || this.userProject; + } + if (options.predefinedAcl) { + reqOpts.qs.predefinedAcl = options.predefinedAcl; + } + else if (options.private) { + reqOpts.qs.predefinedAcl = 'private'; + } + else if (options.public) { + reqOpts.qs.predefinedAcl = 'publicRead'; + } + Object.assign(reqOpts.qs, this.instancePreconditionOpts, options.preconditionOpts); + index_js_1.util.makeWritableStream(dup, { + makeAuthenticatedRequest: (reqOpts) => { + this.request(reqOpts, (err, body, resp) => { + if (err) { + dup.destroy(err); + return; + } + this.metadata = body; + dup.emit('metadata', body); + dup.emit('response', resp); + dup.emit('complete'); + }); + }, + metadata: options.metadata, + request: reqOpts, + }); + } + disableAutoRetryConditionallyIdempotent_( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + coreOpts, methodType, localPreconditionOptions) { + var _a, _b, _c, _d; + if ((typeof coreOpts === 'object' && + ((_b = (_a = coreOpts === null || coreOpts === void 0 ? void 0 : coreOpts.reqOpts) === null || _a === void 0 ? void 0 : _a.qs) === null || _b === void 0 ? void 0 : _b.ifGenerationMatch) === undefined && + (localPreconditionOptions === null || localPreconditionOptions === void 0 ? void 0 : localPreconditionOptions.ifGenerationMatch) === undefined && + methodType === bucket_js_1.AvailableServiceObjectMethods.delete && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + this.storage.retryOptions.autoRetry = false; + } + if ((typeof coreOpts === 'object' && + ((_d = (_c = coreOpts === null || coreOpts === void 0 ? void 0 : coreOpts.reqOpts) === null || _c === void 0 ? void 0 : _c.qs) === null || _d === void 0 ? void 0 : _d.ifMetagenerationMatch) === undefined && + (localPreconditionOptions === null || localPreconditionOptions === void 0 ? void 0 : localPreconditionOptions.ifMetagenerationMatch) === undefined && + methodType === bucket_js_1.AvailableServiceObjectMethods.setMetadata && + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryConditional) || + this.storage.retryOptions.idempotencyStrategy === + storage_js_1.IdempotencyStrategy.RetryNever) { + this.storage.retryOptions.autoRetry = false; + } + } + async getBufferFromReadable(readable) { + const buf = []; + for await (const chunk of readable) { + buf.push(chunk); + } + return Buffer.concat(buf); + } +} +exports.File = File; +_File_instances = new WeakSet(), _File_validateIntegrity = +/** + * + * @param hashCalculatingStream + * @param verify + * @returns {boolean} Returns `true` if valid, throws with error otherwise + */ +async function _File_validateIntegrity(hashCalculatingStream, verify = {}) { + const metadata = this.metadata; + // If we're doing validation, assume the worst + let dataMismatch = !!(verify.crc32c || verify.md5); + if (verify.crc32c && metadata.crc32c) { + dataMismatch = !hashCalculatingStream.test('crc32c', metadata.crc32c); + } + if (verify.md5 && metadata.md5Hash) { + dataMismatch = !hashCalculatingStream.test('md5', metadata.md5Hash); + } + if (dataMismatch) { + const errors = []; + let code = ''; + let message = ''; + try { + await this.delete(); + if (verify.md5 && !metadata.md5Hash) { + code = 'MD5_NOT_AVAILABLE'; + message = FileExceptionMessages.MD5_NOT_AVAILABLE; + } + else { + code = 'FILE_NO_UPLOAD'; + message = FileExceptionMessages.UPLOAD_MISMATCH; + } + } + catch (e) { + const error = e; + code = 'FILE_NO_UPLOAD_DELETE'; + message = `${FileExceptionMessages.UPLOAD_MISMATCH_DELETE_FAIL}${error.message}`; + errors.push(error); + } + const error = new RequestError(message); + error.code = code; + error.errors = errors; + throw error; + } + return true; +}; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(File, { + exclude: [ + 'cloudStorageURI', + 'publicUrl', + 'request', + 'save', + 'setEncryptionKey', + 'shouldRetryBasedOnPreconditionAndIdempotencyStrat', + 'getBufferFromReadable', + 'restore', + ], +}); + + +/***/ }), + +/***/ 14873: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _HashStreamValidator_crc32cHash, _HashStreamValidator_md5Hash, _HashStreamValidator_md5Digest; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HashStreamValidator = void 0; +const crypto_1 = __nccwpck_require__(76982); +const stream_1 = __nccwpck_require__(2203); +const crc32c_js_1 = __nccwpck_require__(34317); +const file_js_1 = __nccwpck_require__(69975); +class HashStreamValidator extends stream_1.Transform { + constructor(options = {}) { + super(); + this.updateHashesOnly = false; + _HashStreamValidator_crc32cHash.set(this, undefined); + _HashStreamValidator_md5Hash.set(this, undefined); + _HashStreamValidator_md5Digest.set(this, ''); + this.crc32cEnabled = !!options.crc32c; + this.md5Enabled = !!options.md5; + this.updateHashesOnly = !!options.updateHashesOnly; + this.crc32cExpected = options.crc32cExpected; + this.md5Expected = options.md5Expected; + if (this.crc32cEnabled) { + if (options.crc32cInstance) { + __classPrivateFieldSet(this, _HashStreamValidator_crc32cHash, options.crc32cInstance, "f"); + } + else { + const crc32cGenerator = options.crc32cGenerator || crc32c_js_1.CRC32C_DEFAULT_VALIDATOR_GENERATOR; + __classPrivateFieldSet(this, _HashStreamValidator_crc32cHash, crc32cGenerator(), "f"); + } + } + if (this.md5Enabled) { + __classPrivateFieldSet(this, _HashStreamValidator_md5Hash, (0, crypto_1.createHash)('md5'), "f"); + } + } + /** + * Return the current CRC32C value, if available. + */ + get crc32c() { + var _a; + return (_a = __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f")) === null || _a === void 0 ? void 0 : _a.toString(); + } + _flush(callback) { + if (__classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f")) { + __classPrivateFieldSet(this, _HashStreamValidator_md5Digest, __classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f").digest('base64'), "f"); + } + if (this.updateHashesOnly) { + callback(); + return; + } + // If we're doing validation, assume the worst-- a data integrity + // mismatch. If not, these tests won't be performed, and we can assume + // the best. + // We must check if the server decompressed the data on serve because hash + // validation is not possible in this case. + let failed = this.crc32cEnabled || this.md5Enabled; + if (this.crc32cEnabled && this.crc32cExpected) { + failed = !this.test('crc32c', this.crc32cExpected); + } + if (this.md5Enabled && this.md5Expected) { + failed = !this.test('md5', this.md5Expected); + } + if (failed) { + const mismatchError = new file_js_1.RequestError(file_js_1.FileExceptionMessages.DOWNLOAD_MISMATCH); + mismatchError.code = 'CONTENT_DOWNLOAD_MISMATCH'; + callback(mismatchError); + } + else { + callback(); + } + } + _transform(chunk, encoding, callback) { + this.push(chunk, encoding); + try { + if (__classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f")) + __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f").update(chunk); + if (__classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f")) + __classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f").update(chunk); + callback(); + } + catch (e) { + callback(e); + } + } + test(hash, sum) { + const check = Buffer.isBuffer(sum) ? sum.toString('base64') : sum; + if (hash === 'crc32c' && __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f")) { + return __classPrivateFieldGet(this, _HashStreamValidator_crc32cHash, "f").validate(check); + } + if (hash === 'md5' && __classPrivateFieldGet(this, _HashStreamValidator_md5Hash, "f")) { + return __classPrivateFieldGet(this, _HashStreamValidator_md5Digest, "f") === check; + } + return false; + } +} +exports.HashStreamValidator = HashStreamValidator; +_HashStreamValidator_crc32cHash = new WeakMap(), _HashStreamValidator_md5Hash = new WeakMap(), _HashStreamValidator_md5Digest = new WeakMap(); + + +/***/ }), + +/***/ 45891: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HmacKey = void 0; +const index_js_1 = __nccwpck_require__(11325); +const storage_js_1 = __nccwpck_require__(92848); +const promisify_1 = __nccwpck_require__(60206); +/** + * The API-formatted resource description of the HMAC key. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name HmacKey#metadata + * @type {object} + */ +/** + * An HmacKey object contains metadata of an HMAC key created from a + * service account through the {@link Storage} client using + * {@link Storage#createHmacKey}. + * + * See {@link https://cloud.google.com/storage/docs/authentication/hmackeys| HMAC keys documentation} + * + * @class + */ +class HmacKey extends index_js_1.ServiceObject { + /** + * @typedef {object} HmacKeyOptions + * @property {string} [projectId] The project ID of the project that owns + * the service account of the requested HMAC key. If not provided, + * the project ID used to instantiate the Storage client will be used. + */ + /** + * Constructs an HmacKey object. + * + * Note: this only create a local reference to an HMAC key, to create + * an HMAC key, use {@link Storage#createHmacKey}. + * + * @param {Storage} storage The Storage instance this HMAC key is + * attached to. + * @param {string} accessId The unique accessId for this HMAC key. + * @param {HmacKeyOptions} options Constructor configurations. + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const hmacKey = storage.hmacKey('access-id'); + * ``` + */ + constructor(storage, accessId, options) { + const methods = { + /** + * @typedef {object} DeleteHmacKeyOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * @typedef {array} DeleteHmacKeyResponse + * @property {object} 0 The full API response. + */ + /** + * @callback DeleteHmacKeyCallback + * @param {?Error} err Request error, if any. + * @param {object} apiResponse The full API response. + */ + /** + * Deletes an HMAC key. + * Key state must be set to `INACTIVE` prior to deletion. + * Caution: HMAC keys cannot be recovered once you delete them. + * + * The authenticated user must have `storage.hmacKeys.delete` permission for the project in which the key exists. + * + * @method HmacKey#delete + * @param {DeleteHmacKeyOptions} [options] Configuration options. + * @param {DeleteHmacKeyCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Delete HMAC key after making the key inactive. + * //- + * const hmacKey = storage.hmacKey('ACCESS_ID'); + * hmacKey.setMetadata({state: 'INACTIVE'}, (err, hmacKeyMetadata) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * hmacKey.delete((err) => { + * if (err) { + * console.error(err); + * return; + * } + * // The HMAC key is deleted. + * }); + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * const hmacKey = storage.hmacKey('ACCESS_ID'); + * hmacKey + * .setMetadata({state: 'INACTIVE'}) + * .then(() => { + * return hmacKey.delete(); + * }); + * ``` + */ + delete: true, + /** + * @callback GetHmacKeyCallback + * @param {?Error} err Request error, if any. + * @param {HmacKey} hmacKey this {@link HmacKey} instance. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} GetHmacKeyResponse + * @property {HmacKey} 0 This {@link HmacKey} instance. + * @property {object} 1 The full API response. + */ + /** + * @typedef {object} GetHmacKeyOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * Retrieves and populate an HMAC key's metadata, and return + * this {@link HmacKey} instance. + * + * HmacKey.get() does not give the HMAC key secret, as + * it is only returned on creation. + * + * The authenticated user must have `storage.hmacKeys.get` permission + * for the project in which the key exists. + * + * @method HmacKey#get + * @param {GetHmacKeyOptions} [options] Configuration options. + * @param {GetHmacKeyCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Get the HmacKey's Metadata. + * //- + * storage.hmacKey('ACCESS_ID') + * .get((err, hmacKey) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * // do something with the returned HmacKey object. + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * storage.hmacKey('ACCESS_ID') + * .get() + * .then((data) => { + * const hmacKey = data[0]; + * }); + * ``` + */ + get: true, + /** + * @typedef {object} GetHmacKeyMetadataOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * Retrieves and populate an HMAC key's metadata, and return + * the HMAC key's metadata as an object. + * + * HmacKey.getMetadata() does not give the HMAC key secret, as + * it is only returned on creation. + * + * The authenticated user must have `storage.hmacKeys.get` permission + * for the project in which the key exists. + * + * @method HmacKey#getMetadata + * @param {GetHmacKeyMetadataOptions} [options] Configuration options. + * @param {HmacKeyMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * //- + * // Get the HmacKey's metadata and populate to the metadata property. + * //- + * storage.hmacKey('ACCESS_ID') + * .getMetadata((err, hmacKeyMetadata) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * console.log(hmacKeyMetadata); + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * storage.hmacKey('ACCESS_ID') + * .getMetadata() + * .then((data) => { + * const hmacKeyMetadata = data[0]; + * console.log(hmacKeyMetadata); + * }); + * ``` + */ + getMetadata: true, + /** + * @typedef {object} SetHmacKeyMetadata Subset of {@link HmacKeyMetadata} to update. + * @property {string} state New state of the HmacKey. Either 'ACTIVE' or 'INACTIVE'. + * @property {string} [etag] Include an etag from a previous get HMAC key request + * to perform safe read-modify-write. + */ + /** + * @typedef {object} SetHmacKeyMetadataOptions + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * @callback HmacKeyMetadataCallback + * @param {?Error} err Request error, if any. + * @param {HmacKeyMetadata} metadata The updated {@link HmacKeyMetadata} object. + * @param {object} apiResponse The full API response. + */ + /** + * @typedef {array} HmacKeyMetadataResponse + * @property {HmacKeyMetadata} 0 The updated {@link HmacKeyMetadata} object. + * @property {object} 1 The full API response. + */ + /** + * Updates the state of an HMAC key. See {@link SetHmacKeyMetadata} for + * valid states. + * + * @method HmacKey#setMetadata + * @param {SetHmacKeyMetadata} metadata The new metadata. + * @param {SetHmacKeyMetadataOptions} [options] Configuration options. + * @param {HmacKeyMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * const metadata = { + * state: 'INACTIVE', + * }; + * + * storage.hmacKey('ACCESS_ID') + * .setMetadata(metadata, (err, hmacKeyMetadata) => { + * if (err) { + * // The request was an error. + * console.error(err); + * return; + * } + * console.log(hmacKeyMetadata); + * }); + * + * //- + * // If the callback is omitted, a promise is returned. + * //- + * storage.hmacKey('ACCESS_ID') + * .setMetadata(metadata) + * .then((data) => { + * const hmacKeyMetadata = data[0]; + * console.log(hmacKeyMetadata); + * }); + * ``` + */ + setMetadata: { + reqOpts: { + method: 'PUT', + }, + }, + }; + const projectId = (options && options.projectId) || storage.projectId; + super({ + parent: storage, + id: accessId, + baseUrl: `/projects/${projectId}/hmacKeys`, + methods, + }); + this.storage = storage; + this.instanceRetryValue = storage.retryOptions.autoRetry; + } + setMetadata(metadata, optionsOrCallback, cb) { + // ETag preconditions are not currently supported. Retries should be disabled if the idempotency strategy is not set to RetryAlways + if (this.storage.retryOptions.idempotencyStrategy !== + storage_js_1.IdempotencyStrategy.RetryAlways) { + this.storage.retryOptions.autoRetry = false; + } + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + cb = + typeof optionsOrCallback === 'function' + ? optionsOrCallback + : cb; + super + .setMetadata(metadata, options) + .then(resp => cb(null, ...resp)) + .catch(cb) + .finally(() => { + this.storage.retryOptions.autoRetry = this.instanceRetryValue; + }); + } +} +exports.HmacKey = HmacKey; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(HmacKey); + + +/***/ }), + +/***/ 52880: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Iam = exports.IAMExceptionMessages = void 0; +const promisify_1 = __nccwpck_require__(60206); +const util_js_1 = __nccwpck_require__(74557); +var IAMExceptionMessages; +(function (IAMExceptionMessages) { + IAMExceptionMessages["POLICY_OBJECT_REQUIRED"] = "A policy object is required."; + IAMExceptionMessages["PERMISSIONS_REQUIRED"] = "Permissions are required."; +})(IAMExceptionMessages || (exports.IAMExceptionMessages = IAMExceptionMessages = {})); +/** + * Get and set IAM policies for your Cloud Storage bucket. + * + * See {@link https://cloud.google.com/storage/docs/access-control/iam#short_title_iam_management| Cloud Storage IAM Management} + * See {@link https://cloud.google.com/iam/docs/granting-changing-revoking-access| Granting, Changing, and Revoking Access} + * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles} + * + * @constructor Iam + * + * @param {Bucket} bucket The parent instance. + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * // bucket.iam + * ``` + */ +class Iam { + constructor(bucket) { + this.request_ = bucket.request.bind(bucket); + this.resourceId_ = 'buckets/' + bucket.getId(); + } + /** + * @typedef {object} GetPolicyOptions Requested options for IAM#getPolicy(). + * @property {number} [requestedPolicyVersion] The version of IAM policies to + * request. If a policy with a condition is requested without setting + * this, the server will return an error. This must be set to a value + * of 3 to retrieve IAM policies containing conditions. This is to + * prevent client code that isn't aware of IAM conditions from + * interpreting and modifying policies incorrectly. The service might + * return a policy with version lower than the one that was requested, + * based on the feature syntax in the policy fetched. + * See {@link https://cloud.google.com/iam/docs/policies#versions| IAM Policy versions} + * @property {string} [userProject] The ID of the project which will be + * billed for the request. + */ + /** + * @typedef {array} GetPolicyResponse + * @property {Policy} 0 The policy. + * @property {object} 1 The full API response. + */ + /** + * @typedef {object} Policy + * @property {PolicyBinding[]} policy.bindings Bindings associate members with roles. + * @property {string} [policy.etag] Etags are used to perform a read-modify-write. + * @property {number} [policy.version] The syntax schema version of the Policy. + * To set an IAM policy with conditional binding, this field must be set to + * 3 or greater. + * See {@link https://cloud.google.com/iam/docs/policies#versions| IAM Policy versions} + */ + /** + * @typedef {object} PolicyBinding + * @property {string} role Role that is assigned to members. + * @property {string[]} members Specifies the identities requesting access for the bucket. + * @property {Expr} [condition] The condition that is associated with this binding. + */ + /** + * @typedef {object} Expr + * @property {string} [title] An optional title for the expression, i.e. a + * short string describing its purpose. This can be used e.g. in UIs + * which allow to enter the expression. + * @property {string} [description] An optional description of the + * expression. This is a longer text which describes the expression, + * e.g. when hovered over it in a UI. + * @property {string} expression Textual representation of an expression in + * Common Expression Language syntax. The application context of the + * containing message determines which well-known feature set of CEL + * is supported.The condition that is associated with this binding. + * + * @see [Condition] https://cloud.google.com/storage/docs/access-control/iam#conditions + */ + /** + * Get the IAM policy. + * + * @param {GetPolicyOptions} [options] Request options. + * @param {GetPolicyCallback} [callback] Callback function. + * @returns {Promise} + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/getIamPolicy| Buckets: setIamPolicy API Documentation} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * bucket.iam.getPolicy( + * {requestedPolicyVersion: 3}, + * function(err, policy, apiResponse) { + * + * }, + * ); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.getPolicy({requestedPolicyVersion: 3}) + * .then(function(data) { + * const policy = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/iam.js + * region_tag:storage_view_bucket_iam_members + * Example of retrieving a bucket's IAM policy: + */ + getPolicy(optionsOrCallback, callback) { + const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback); + const qs = {}; + if (options.userProject) { + qs.userProject = options.userProject; + } + if (options.requestedPolicyVersion !== null && + options.requestedPolicyVersion !== undefined) { + qs.optionsRequestedPolicyVersion = options.requestedPolicyVersion; + } + this.request_({ + uri: '/iam', + qs, + }, cb); + } + /** + * Set the IAM policy. + * + * @throws {Error} If no policy is provided. + * + * @param {Policy} policy The policy. + * @param {SetPolicyOptions} [options] Configuration options. + * @param {SetPolicyCallback} callback Callback function. + * @returns {Promise} + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/setIamPolicy| Buckets: setIamPolicy API Documentation} + * See {@link https://cloud.google.com/iam/docs/understanding-roles| IAM Roles} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * const myPolicy = { + * bindings: [ + * { + * role: 'roles/storage.admin', + * members: + * ['serviceAccount:myotherproject@appspot.gserviceaccount.com'] + * } + * ] + * }; + * + * bucket.iam.setPolicy(myPolicy, function(err, policy, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.setPolicy(myPolicy).then(function(data) { + * const policy = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/iam.js + * region_tag:storage_add_bucket_iam_member + * Example of adding to a bucket's IAM policy: + * + * @example include:samples/iam.js + * region_tag:storage_remove_bucket_iam_member + * Example of removing from a bucket's IAM policy: + */ + setPolicy(policy, optionsOrCallback, callback) { + if (policy === null || typeof policy !== 'object') { + throw new Error(IAMExceptionMessages.POLICY_OBJECT_REQUIRED); + } + const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback); + let maxRetries; + if (policy.etag === undefined) { + maxRetries = 0; + } + this.request_({ + method: 'PUT', + uri: '/iam', + maxRetries, + json: Object.assign({ + resourceId: this.resourceId_, + }, policy), + qs: options, + }, cb); + } + /** + * Test a set of permissions for a resource. + * + * @throws {Error} If permissions are not provided. + * + * @param {string|string[]} permissions The permission(s) to test for. + * @param {TestIamPermissionsOptions} [options] Configuration object. + * @param {TestIamPermissionsCallback} [callback] Callback function. + * @returns {Promise} + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/testIamPermissions| Buckets: testIamPermissions API Documentation} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * + * //- + * // Test a single permission. + * //- + * const test = 'storage.buckets.delete'; + * + * bucket.iam.testPermissions(test, function(err, permissions, apiResponse) { + * console.log(permissions); + * // { + * // "storage.buckets.delete": true + * // } + * }); + * + * //- + * // Test several permissions at once. + * //- + * const tests = [ + * 'storage.buckets.delete', + * 'storage.buckets.get' + * ]; + * + * bucket.iam.testPermissions(tests, function(err, permissions) { + * console.log(permissions); + * // { + * // "storage.buckets.delete": false, + * // "storage.buckets.get": true + * // } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * bucket.iam.testPermissions(test).then(function(data) { + * const permissions = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + testPermissions(permissions, optionsOrCallback, callback) { + if (!Array.isArray(permissions) && typeof permissions !== 'string') { + throw new Error(IAMExceptionMessages.PERMISSIONS_REQUIRED); + } + const { options, callback: cb } = (0, util_js_1.normalize)(optionsOrCallback, callback); + const permissionsArray = Array.isArray(permissions) + ? permissions + : [permissions]; + const req = Object.assign({ + permissions: permissionsArray, + }, options); + this.request_({ + uri: '/iam/testPermissions', + qs: req, + useQuerystring: true, + }, (err, resp) => { + if (err) { + cb(err, null, resp); + return; + } + const availablePermissions = Array.isArray(resp.permissions) + ? resp.permissions + : []; + const permissionsHash = permissionsArray.reduce((acc, permission) => { + acc[permission] = availablePermissions.indexOf(permission) > -1; + return acc; + }, {}); + cb(null, permissionsHash, resp); + }); + } +} +exports.Iam = Iam; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Iam); + + +/***/ }), + +/***/ 28525: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Notification = exports.Iam = exports.HmacKey = exports.File = exports.Channel = exports.Bucket = exports.Storage = exports.RETRYABLE_ERR_FN_DEFAULT = exports.IdempotencyStrategy = exports.ApiError = void 0; +/** + * The `@google-cloud/storage` package has a single named export which is the + * {@link Storage} (ES6) class, which should be instantiated with `new`. + * + * See {@link Storage} and {@link ClientConfig} for client methods and + * configuration options. + * + * @module {Storage} @google-cloud/storage + * @alias nodejs-storage + * + * @example + * Install the client library with npm: + * ``` + * npm install --save @google-cloud/storage + * ``` + * + * @example + * Import the client library + * ``` + * const {Storage} = require('@google-cloud/storage'); + * ``` + * + * @example + * Create a client that uses Application + * Default Credentials (ADC): + * ``` + * const storage = new Storage(); + * ``` + * + * @example + * Create a client with explicit + * credentials: + * ``` + * const storage = new Storage({ projectId: + * 'your-project-id', keyFilename: '/path/to/keyfile.json' + * }); + * ``` + * + * @example include:samples/quickstart.js + * region_tag:storage_quickstart + * Full quickstart example: + */ +var index_js_1 = __nccwpck_require__(11325); +Object.defineProperty(exports, "ApiError", ({ enumerable: true, get: function () { return index_js_1.ApiError; } })); +var storage_js_1 = __nccwpck_require__(92848); +Object.defineProperty(exports, "IdempotencyStrategy", ({ enumerable: true, get: function () { return storage_js_1.IdempotencyStrategy; } })); +Object.defineProperty(exports, "RETRYABLE_ERR_FN_DEFAULT", ({ enumerable: true, get: function () { return storage_js_1.RETRYABLE_ERR_FN_DEFAULT; } })); +Object.defineProperty(exports, "Storage", ({ enumerable: true, get: function () { return storage_js_1.Storage; } })); +var bucket_js_1 = __nccwpck_require__(82887); +Object.defineProperty(exports, "Bucket", ({ enumerable: true, get: function () { return bucket_js_1.Bucket; } })); +__exportStar(__nccwpck_require__(34317), exports); +var channel_js_1 = __nccwpck_require__(12658); +Object.defineProperty(exports, "Channel", ({ enumerable: true, get: function () { return channel_js_1.Channel; } })); +var file_js_1 = __nccwpck_require__(69975); +Object.defineProperty(exports, "File", ({ enumerable: true, get: function () { return file_js_1.File; } })); +__exportStar(__nccwpck_require__(14873), exports); +var hmacKey_js_1 = __nccwpck_require__(45891); +Object.defineProperty(exports, "HmacKey", ({ enumerable: true, get: function () { return hmacKey_js_1.HmacKey; } })); +var iam_js_1 = __nccwpck_require__(52880); +Object.defineProperty(exports, "Iam", ({ enumerable: true, get: function () { return iam_js_1.Iam; } })); +var notification_js_1 = __nccwpck_require__(18598); +Object.defineProperty(exports, "Notification", ({ enumerable: true, get: function () { return notification_js_1.Notification; } })); +__exportStar(__nccwpck_require__(30004), exports); + + +/***/ }), + +/***/ 11325: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.util = exports.ApiError = exports.ServiceObject = exports.Service = void 0; +var service_js_1 = __nccwpck_require__(8542); +Object.defineProperty(exports, "Service", ({ enumerable: true, get: function () { return service_js_1.Service; } })); +var service_object_js_1 = __nccwpck_require__(72908); +Object.defineProperty(exports, "ServiceObject", ({ enumerable: true, get: function () { return service_object_js_1.ServiceObject; } })); +var util_js_1 = __nccwpck_require__(37325); +Object.defineProperty(exports, "ApiError", ({ enumerable: true, get: function () { return util_js_1.ApiError; } })); +Object.defineProperty(exports, "util", ({ enumerable: true, get: function () { return util_js_1.util; } })); + + +/***/ }), + +/***/ 72908: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ServiceObject = void 0; +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const promisify_1 = __nccwpck_require__(60206); +const events_1 = __nccwpck_require__(24434); +const util_js_1 = __nccwpck_require__(37325); +/** + * ServiceObject is a base class, meant to be inherited from by a "service + * object," like a BigQuery dataset or Storage bucket. + * + * Most of the time, these objects share common functionality; they can be + * created or deleted, and you can get or set their metadata. + * + * By inheriting from this class, a service object will be extended with these + * shared behaviors. Note that any method can be overridden when the service + * object requires specific behavior. + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +class ServiceObject extends events_1.EventEmitter { + /* + * @constructor + * @alias module:common/service-object + * + * @private + * + * @param {object} config - Configuration object. + * @param {string} config.baseUrl - The base URL to make API requests to. + * @param {string} config.createMethod - The method which creates this object. + * @param {string=} config.id - The identifier of the object. For example, the + * name of a Storage bucket or Pub/Sub topic. + * @param {object=} config.methods - A map of each method name that should be inherited. + * @param {object} config.methods[].reqOpts - Default request options for this + * particular method. A common use case is when `setMetadata` requires a + * `PUT` method to override the default `PATCH`. + * @param {object} config.parent - The parent service instance. For example, an + * instance of Storage if the object is Bucket. + */ + constructor(config) { + super(); + this.metadata = {}; + this.baseUrl = config.baseUrl; + this.parent = config.parent; // Parent class. + this.id = config.id; // Name or ID (e.g. dataset ID, bucket name, etc). + this.createMethod = config.createMethod; + this.methods = config.methods || {}; + this.interceptors = []; + this.projectId = config.projectId; + if (config.methods) { + // This filters the ServiceObject instance (e.g. a "File") to only have + // the configured methods. We make a couple of exceptions for core- + // functionality ("request()" and "getRequestInterceptors()") + Object.getOwnPropertyNames(ServiceObject.prototype) + .filter(methodName => { + return ( + // All ServiceObjects need `request` and `getRequestInterceptors`. + // clang-format off + !/^request/.test(methodName) && + !/^getRequestInterceptors/.test(methodName) && + // clang-format on + // The ServiceObject didn't redefine the method. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this[methodName] === + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ServiceObject.prototype[methodName] && + // This method isn't wanted. + !config.methods[methodName]); + }) + .forEach(methodName => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this[methodName] = undefined; + }); + } + } + create(optionsOrCallback, callback) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const self = this; + const args = [this.id]; + if (typeof optionsOrCallback === 'function') { + callback = optionsOrCallback; + } + if (typeof optionsOrCallback === 'object') { + args.push(optionsOrCallback); + } + // Wrap the callback to return *this* instance of the object, not the + // newly-created one. + // tslint: disable-next-line no-any + function onCreate(...args) { + const [err, instance] = args; + if (!err) { + self.metadata = instance.metadata; + if (self.id && instance.metadata) { + self.id = instance.metadata.id; + } + args[1] = self; // replace the created `instance` with this one. + } + callback(...args); + } + args.push(onCreate); + // eslint-disable-next-line prefer-spread + this.createMethod.apply(null, args); + } + delete(optionsOrCallback, cb) { + var _a; + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const ignoreNotFound = options.ignoreNotFound; + delete options.ignoreNotFound; + const methodConfig = (typeof this.methods.delete === 'object' && this.methods.delete) || {}; + const reqOpts = { + method: 'DELETE', + uri: '', + ...methodConfig.reqOpts, + qs: { + ...(_a = methodConfig.reqOpts) === null || _a === void 0 ? void 0 : _a.qs, + ...options, + }, + }; + // The `request` method may have been overridden to hold any special + // behavior. Ensure we call the original `request` method. + ServiceObject.prototype.request.call(this, reqOpts, (err, body, res) => { + if (err) { + if (err.code === 404 && ignoreNotFound) { + err = null; + } + } + callback(err, res); + }); + } + exists(optionsOrCallback, cb) { + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + this.get(options, err => { + if (err) { + if (err.code === 404) { + callback(null, false); + } + else { + callback(err); + } + return; + } + callback(null, true); + }); + } + get(optionsOrCallback, cb) { + // eslint-disable-next-line @typescript-eslint/no-this-alias + const self = this; + const [opts, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const options = Object.assign({}, opts); + const autoCreate = options.autoCreate && typeof this.create === 'function'; + delete options.autoCreate; + function onCreate(err, instance, apiResponse) { + if (err) { + if (err.code === 409) { + self.get(options, callback); + return; + } + callback(err, null, apiResponse); + return; + } + callback(null, instance, apiResponse); + } + this.getMetadata(options, (err, metadata) => { + if (err) { + if (err.code === 404 && autoCreate) { + const args = []; + if (Object.keys(options).length > 0) { + args.push(options); + } + args.push(onCreate); + self.create(...args); + return; + } + callback(err, null, metadata); + return; + } + callback(null, self, metadata); + }); + } + getMetadata(optionsOrCallback, cb) { + var _a; + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const methodConfig = (typeof this.methods.getMetadata === 'object' && + this.methods.getMetadata) || + {}; + const reqOpts = { + uri: '', + ...methodConfig.reqOpts, + qs: { + ...(_a = methodConfig.reqOpts) === null || _a === void 0 ? void 0 : _a.qs, + ...options, + }, + }; + // The `request` method may have been overridden to hold any special + // behavior. Ensure we call the original `request` method. + ServiceObject.prototype.request.call(this, reqOpts, (err, body, res) => { + this.metadata = body; + callback(err, this.metadata, res); + }); + } + /** + * Return the user's custom request interceptors. + */ + getRequestInterceptors() { + // Interceptors should be returned in the order they were assigned. + const localInterceptors = this.interceptors + .filter(interceptor => typeof interceptor.request === 'function') + .map(interceptor => interceptor.request); + return this.parent.getRequestInterceptors().concat(localInterceptors); + } + setMetadata(metadata, optionsOrCallback, cb) { + var _a, _b; + const [options, callback] = util_js_1.util.maybeOptionsOrCallback(optionsOrCallback, cb); + const methodConfig = (typeof this.methods.setMetadata === 'object' && + this.methods.setMetadata) || + {}; + const reqOpts = { + method: 'PATCH', + uri: '', + ...methodConfig.reqOpts, + json: { + ...(_a = methodConfig.reqOpts) === null || _a === void 0 ? void 0 : _a.json, + ...metadata, + }, + qs: { + ...(_b = methodConfig.reqOpts) === null || _b === void 0 ? void 0 : _b.qs, + ...options, + }, + }; + // The `request` method may have been overridden to hold any special + // behavior. Ensure we call the original `request` method. + ServiceObject.prototype.request.call(this, reqOpts, (err, body, res) => { + this.metadata = body; + callback(err, this.metadata, res); + }); + } + request_(reqOpts, callback) { + reqOpts = { ...reqOpts }; + if (this.projectId) { + reqOpts.projectId = this.projectId; + } + const isAbsoluteUrl = reqOpts.uri.indexOf('http') === 0; + const uriComponents = [this.baseUrl, this.id || '', reqOpts.uri]; + if (isAbsoluteUrl) { + uriComponents.splice(0, uriComponents.indexOf(reqOpts.uri)); + } + reqOpts.uri = uriComponents + .filter(x => x.trim()) // Limit to non-empty strings. + .map(uriComponent => { + const trimSlashesRegex = /^\/*|\/*$/g; + return uriComponent.replace(trimSlashesRegex, ''); + }) + .join('/'); + const childInterceptors = Array.isArray(reqOpts.interceptors_) + ? reqOpts.interceptors_ + : []; + const localInterceptors = [].slice.call(this.interceptors); + reqOpts.interceptors_ = childInterceptors.concat(localInterceptors); + if (reqOpts.shouldReturnStream) { + return this.parent.requestStream(reqOpts); + } + this.parent.request(reqOpts, callback); + } + request(reqOpts, callback) { + this.request_(reqOpts, callback); + } + /** + * Make an authenticated API request. + * + * @param {object} reqOpts - Request options that are passed to `request`. + * @param {string} reqOpts.uri - A URI relative to the baseUrl. + */ + requestStream(reqOpts) { + const opts = { ...reqOpts, shouldReturnStream: true }; + return this.request_(opts); + } +} +exports.ServiceObject = ServiceObject; +(0, promisify_1.promisifyAll)(ServiceObject, { exclude: ['getRequestInterceptors'] }); + + +/***/ }), + +/***/ 8542: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Service = exports.DEFAULT_PROJECT_ID_TOKEN = void 0; +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const google_auth_library_1 = __nccwpck_require__(492); +const uuid = __importStar(__nccwpck_require__(20607)); +const util_js_1 = __nccwpck_require__(37325); +const util_js_2 = __nccwpck_require__(74557); +exports.DEFAULT_PROJECT_ID_TOKEN = '{{projectId}}'; +class Service { + /** + * Service is a base class, meant to be inherited from by a "service," like + * BigQuery or Storage. + * + * This handles making authenticated requests by exposing a `makeReq_` + * function. + * + * @constructor + * @alias module:common/service + * + * @param {object} config - Configuration object. + * @param {string} config.baseUrl - The base URL to make API requests to. + * @param {string[]} config.scopes - The scopes required for the request. + * @param {object=} options - [Configuration object](#/docs). + */ + constructor(config, options = {}) { + this.baseUrl = config.baseUrl; + this.apiEndpoint = config.apiEndpoint; + this.timeout = options.timeout; + this.globalInterceptors = Array.isArray(options.interceptors_) + ? options.interceptors_ + : []; + this.interceptors = []; + this.packageJson = config.packageJson; + this.projectId = options.projectId || exports.DEFAULT_PROJECT_ID_TOKEN; + this.projectIdRequired = config.projectIdRequired !== false; + this.providedUserAgent = options.userAgent; + this.universeDomain = options.universeDomain || google_auth_library_1.DEFAULT_UNIVERSE; + this.customEndpoint = config.customEndpoint || false; + this.makeAuthenticatedRequest = util_js_1.util.makeAuthenticatedRequestFactory({ + ...config, + projectIdRequired: this.projectIdRequired, + projectId: this.projectId, + authClient: options.authClient || config.authClient, + credentials: options.credentials, + keyFile: options.keyFilename, + email: options.email, + clientOptions: { + universeDomain: options.universeDomain, + ...options.clientOptions, + }, + }); + this.authClient = this.makeAuthenticatedRequest.authClient; + const isCloudFunctionEnv = !!process.env.FUNCTION_NAME; + if (isCloudFunctionEnv) { + this.interceptors.push({ + request(reqOpts) { + reqOpts.forever = false; + return reqOpts; + }, + }); + } + } + /** + * Return the user's custom request interceptors. + */ + getRequestInterceptors() { + // Interceptors should be returned in the order they were assigned. + return [].slice + .call(this.globalInterceptors) + .concat(this.interceptors) + .filter(interceptor => typeof interceptor.request === 'function') + .map(interceptor => interceptor.request); + } + getProjectId(callback) { + if (!callback) { + return this.getProjectIdAsync(); + } + this.getProjectIdAsync().then(p => callback(null, p), callback); + } + async getProjectIdAsync() { + const projectId = await this.authClient.getProjectId(); + if (this.projectId === exports.DEFAULT_PROJECT_ID_TOKEN && projectId) { + this.projectId = projectId; + } + return this.projectId; + } + request_(reqOpts, callback) { + reqOpts = { ...reqOpts, timeout: this.timeout }; + const isAbsoluteUrl = reqOpts.uri.indexOf('http') === 0; + const uriComponents = [this.baseUrl]; + if (this.projectIdRequired) { + if (reqOpts.projectId) { + uriComponents.push('projects'); + uriComponents.push(reqOpts.projectId); + } + else { + uriComponents.push('projects'); + uriComponents.push(this.projectId); + } + } + uriComponents.push(reqOpts.uri); + if (isAbsoluteUrl) { + uriComponents.splice(0, uriComponents.indexOf(reqOpts.uri)); + } + reqOpts.uri = uriComponents + .map(uriComponent => { + const trimSlashesRegex = /^\/*|\/*$/g; + return uriComponent.replace(trimSlashesRegex, ''); + }) + .join('/') + // Some URIs have colon separators. + // Bad: https://.../projects/:list + // Good: https://.../projects:list + .replace(/\/:/g, ':'); + const requestInterceptors = this.getRequestInterceptors(); + const interceptorArray = Array.isArray(reqOpts.interceptors_) + ? reqOpts.interceptors_ + : []; + interceptorArray.forEach(interceptor => { + if (typeof interceptor.request === 'function') { + requestInterceptors.push(interceptor.request); + } + }); + requestInterceptors.forEach(requestInterceptor => { + reqOpts = requestInterceptor(reqOpts); + }); + delete reqOpts.interceptors_; + const pkg = this.packageJson; + let userAgent = (0, util_js_2.getUserAgentString)(); + if (this.providedUserAgent) { + userAgent = `${this.providedUserAgent} ${userAgent}`; + } + reqOpts.headers = { + ...reqOpts.headers, + 'User-Agent': userAgent, + 'x-goog-api-client': `${(0, util_js_2.getRuntimeTrackingString)()} gccl/${pkg.version}-${(0, util_js_2.getModuleFormat)()} gccl-invocation-id/${uuid.v4()}`, + }; + if (reqOpts[util_js_1.GCCL_GCS_CMD_KEY]) { + reqOpts.headers['x-goog-api-client'] += + ` gccl-gcs-cmd/${reqOpts[util_js_1.GCCL_GCS_CMD_KEY]}`; + } + if (reqOpts.shouldReturnStream) { + return this.makeAuthenticatedRequest(reqOpts); + } + else { + this.makeAuthenticatedRequest(reqOpts, callback); + } + } + /** + * Make an authenticated API request. + * + * @param {object} reqOpts - Request options that are passed to `request`. + * @param {string} reqOpts.uri - A URI relative to the baseUrl. + * @param {function} callback - The callback function passed to `request`. + */ + request(reqOpts, callback) { + Service.prototype.request_.call(this, reqOpts, callback); + } + /** + * Make an authenticated API request. + * + * @param {object} reqOpts - Request options that are passed to `request`. + * @param {string} reqOpts.uri - A URI relative to the baseUrl. + */ + requestStream(reqOpts) { + const opts = { ...reqOpts, shouldReturnStream: true }; + return Service.prototype.request_.call(this, opts); + } +} +exports.Service = Service; + + +/***/ }), + +/***/ 37325: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.util = exports.Util = exports.PartialFailureError = exports.ApiError = exports.GCCL_GCS_CMD_KEY = void 0; +/*! + * @module common/util + */ +const projectify_1 = __nccwpck_require__(87635); +const htmlEntities = __importStar(__nccwpck_require__(13660)); +const google_auth_library_1 = __nccwpck_require__(492); +const retry_request_1 = __importDefault(__nccwpck_require__(67842)); +const stream_1 = __nccwpck_require__(2203); +const teeny_request_1 = __nccwpck_require__(80321); +const uuid = __importStar(__nccwpck_require__(20607)); +const service_js_1 = __nccwpck_require__(8542); +const util_js_1 = __nccwpck_require__(74557); +const duplexify_1 = __importDefault(__nccwpck_require__(29112)); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const packageJson = (0, package_json_helper_cjs_1.getPackageJSON)(); +/** + * A unique symbol for providing a `gccl-gcs-cmd` value + * for the `X-Goog-API-Client` header. + * + * E.g. the `V` in `X-Goog-API-Client: gccl-gcs-cmd/V` + **/ +exports.GCCL_GCS_CMD_KEY = Symbol.for('GCCL_GCS_CMD'); +const requestDefaults = { + timeout: 60000, + gzip: true, + forever: true, + pool: { + maxSockets: Infinity, + }, +}; +/** + * Default behavior: Automatically retry retriable server errors. + * + * @const {boolean} + * @private + */ +const AUTO_RETRY_DEFAULT = true; +/** + * Default behavior: Only attempt to retry retriable errors 3 times. + * + * @const {number} + * @private + */ +const MAX_RETRY_DEFAULT = 3; +/** + * Custom error type for API errors. + * + * @param {object} errorBody - Error object. + */ +class ApiError extends Error { + constructor(errorBodyOrMessage) { + super(); + if (typeof errorBodyOrMessage !== 'object') { + this.message = errorBodyOrMessage || ''; + return; + } + const errorBody = errorBodyOrMessage; + this.code = errorBody.code; + this.errors = errorBody.errors; + this.response = errorBody.response; + try { + this.errors = JSON.parse(this.response.body).error.errors; + } + catch (e) { + this.errors = errorBody.errors; + } + this.message = ApiError.createMultiErrorMessage(errorBody, this.errors); + Error.captureStackTrace(this); + } + /** + * Pieces together an error message by combining all unique error messages + * returned from a single GoogleError + * + * @private + * + * @param {GoogleErrorBody} err The original error. + * @param {GoogleInnerError[]} [errors] Inner errors, if any. + * @returns {string} + */ + static createMultiErrorMessage(err, errors) { + const messages = new Set(); + if (err.message) { + messages.add(err.message); + } + if (errors && errors.length) { + errors.forEach(({ message }) => messages.add(message)); + } + else if (err.response && err.response.body) { + messages.add(htmlEntities.decode(err.response.body.toString())); + } + else if (!err.message) { + messages.add('A failure occurred during this request.'); + } + let messageArr = Array.from(messages); + if (messageArr.length > 1) { + messageArr = messageArr.map((message, i) => ` ${i + 1}. ${message}`); + messageArr.unshift('Multiple errors occurred during the request. Please see the `errors` array for complete details.\n'); + messageArr.push('\n'); + } + return messageArr.join('\n'); + } +} +exports.ApiError = ApiError; +/** + * Custom error type for partial errors returned from the API. + * + * @param {object} b - Error object. + */ +class PartialFailureError extends Error { + constructor(b) { + super(); + const errorObject = b; + this.errors = errorObject.errors; + this.name = 'PartialFailureError'; + this.response = errorObject.response; + this.message = ApiError.createMultiErrorMessage(errorObject, this.errors); + } +} +exports.PartialFailureError = PartialFailureError; +class Util { + constructor() { + this.ApiError = ApiError; + this.PartialFailureError = PartialFailureError; + } + /** + * No op. + * + * @example + * function doSomething(callback) { + * callback = callback || noop; + * } + */ + noop() { } + /** + * Uniformly process an API response. + * + * @param {*} err - Error value. + * @param {*} resp - Response value. + * @param {*} body - Body value. + * @param {function} callback - The callback function. + */ + handleResp(err, resp, body, callback) { + callback = callback || util.noop; + const parsedResp = { + err: err || null, + ...(resp && util.parseHttpRespMessage(resp)), + ...(body && util.parseHttpRespBody(body)), + }; + // Assign the parsed body to resp.body, even if { json: false } was passed + // as a request option. + // We assume that nobody uses the previously unparsed value of resp.body. + if (!parsedResp.err && resp && typeof parsedResp.body === 'object') { + parsedResp.resp.body = parsedResp.body; + } + if (parsedResp.err && resp) { + parsedResp.err.response = resp; + } + callback(parsedResp.err, parsedResp.body, parsedResp.resp); + } + /** + * Sniff an incoming HTTP response message for errors. + * + * @param {object} httpRespMessage - An incoming HTTP response message from `request`. + * @return {object} parsedHttpRespMessage - The parsed response. + * @param {?error} parsedHttpRespMessage.err - An error detected. + * @param {object} parsedHttpRespMessage.resp - The original response object. + */ + parseHttpRespMessage(httpRespMessage) { + const parsedHttpRespMessage = { + resp: httpRespMessage, + }; + if (httpRespMessage.statusCode < 200 || httpRespMessage.statusCode > 299) { + // Unknown error. Format according to ApiError standard. + parsedHttpRespMessage.err = new ApiError({ + errors: new Array(), + code: httpRespMessage.statusCode, + message: httpRespMessage.statusMessage, + response: httpRespMessage, + }); + } + return parsedHttpRespMessage; + } + /** + * Parse the response body from an HTTP request. + * + * @param {object} body - The response body. + * @return {object} parsedHttpRespMessage - The parsed response. + * @param {?error} parsedHttpRespMessage.err - An error detected. + * @param {object} parsedHttpRespMessage.body - The original body value provided + * will try to be JSON.parse'd. If it's successful, the parsed value will + * be returned here, otherwise the original value and an error will be returned. + */ + parseHttpRespBody(body) { + const parsedHttpRespBody = { + body, + }; + if (typeof body === 'string') { + try { + parsedHttpRespBody.body = JSON.parse(body); + } + catch (err) { + parsedHttpRespBody.body = body; + } + } + if (parsedHttpRespBody.body && parsedHttpRespBody.body.error) { + // Error from JSON API. + parsedHttpRespBody.err = new ApiError(parsedHttpRespBody.body.error); + } + return parsedHttpRespBody; + } + /** + * Take a Duplexify stream, fetch an authenticated connection header, and + * create an outgoing writable stream. + * + * @param {Duplexify} dup - Duplexify stream. + * @param {object} options - Configuration object. + * @param {module:common/connection} options.connection - A connection instance used to get a token with and send the request through. + * @param {object} options.metadata - Metadata to send at the head of the request. + * @param {object} options.request - Request object, in the format of a standard Node.js http.request() object. + * @param {string=} options.request.method - Default: "POST". + * @param {string=} options.request.qs.uploadType - Default: "multipart". + * @param {string=} options.streamContentType - Default: "application/octet-stream". + * @param {function} onComplete - Callback, executed after the writable Request stream has completed. + */ + makeWritableStream(dup, options, onComplete) { + var _a; + onComplete = onComplete || util.noop; + const writeStream = new ProgressStream(); + writeStream.on('progress', evt => dup.emit('progress', evt)); + dup.setWritable(writeStream); + const defaultReqOpts = { + method: 'POST', + qs: { + uploadType: 'multipart', + }, + timeout: 0, + maxRetries: 0, + }; + const metadata = options.metadata || {}; + const reqOpts = { + ...defaultReqOpts, + ...options.request, + qs: { + ...defaultReqOpts.qs, + ...(_a = options.request) === null || _a === void 0 ? void 0 : _a.qs, + }, + multipart: [ + { + 'Content-Type': 'application/json', + body: JSON.stringify(metadata), + }, + { + 'Content-Type': metadata.contentType || 'application/octet-stream', + body: writeStream, + }, + ], + }; + options.makeAuthenticatedRequest(reqOpts, { + onAuthenticated(err, authenticatedReqOpts) { + if (err) { + dup.destroy(err); + return; + } + requestDefaults.headers = util._getDefaultHeaders(reqOpts[exports.GCCL_GCS_CMD_KEY]); + const request = teeny_request_1.teenyRequest.defaults(requestDefaults); + request(authenticatedReqOpts, (err, resp, body) => { + util.handleResp(err, resp, body, (err, data) => { + if (err) { + dup.destroy(err); + return; + } + dup.emit('response', resp); + onComplete(data); + }); + }); + }, + }); + } + /** + * Returns true if the API request should be retried, given the error that was + * given the first time the request was attempted. This is used for rate limit + * related errors as well as intermittent server errors. + * + * @param {error} err - The API error to check if it is appropriate to retry. + * @return {boolean} True if the API request should be retried, false otherwise. + */ + shouldRetryRequest(err) { + if (err) { + if ([408, 429, 500, 502, 503, 504].indexOf(err.code) !== -1) { + return true; + } + if (err.errors) { + for (const e of err.errors) { + const reason = e.reason; + if (reason === 'rateLimitExceeded') { + return true; + } + if (reason === 'userRateLimitExceeded') { + return true; + } + if (reason && reason.includes('EAI_AGAIN')) { + return true; + } + } + } + } + return false; + } + /** + * Get a function for making authenticated requests. + * + * @param {object} config - Configuration object. + * @param {boolean=} config.autoRetry - Automatically retry requests if the + * response is related to rate limits or certain intermittent server + * errors. We will exponentially backoff subsequent requests by default. + * (default: true) + * @param {object=} config.credentials - Credentials object. + * @param {boolean=} config.customEndpoint - If true, just return the provided request options. Default: false. + * @param {boolean=} config.useAuthWithCustomEndpoint - If true, will authenticate when using a custom endpoint. Default: false. + * @param {string=} config.email - Account email address, required for PEM/P12 usage. + * @param {number=} config.maxRetries - Maximum number of automatic retries attempted before returning the error. (default: 3) + * @param {string=} config.keyFile - Path to a .json, .pem, or .p12 keyfile. + * @param {array} config.scopes - Array of scopes required for the API. + */ + makeAuthenticatedRequestFactory(config) { + const googleAutoAuthConfig = { ...config }; + if (googleAutoAuthConfig.projectId === service_js_1.DEFAULT_PROJECT_ID_TOKEN) { + delete googleAutoAuthConfig.projectId; + } + let authClient; + if (googleAutoAuthConfig.authClient instanceof google_auth_library_1.GoogleAuth) { + // Use an existing `GoogleAuth` + authClient = googleAutoAuthConfig.authClient; + } + else { + // Pass an `AuthClient` & `clientOptions` to `GoogleAuth`, if available + authClient = new google_auth_library_1.GoogleAuth({ + ...googleAutoAuthConfig, + authClient: googleAutoAuthConfig.authClient, + clientOptions: googleAutoAuthConfig.clientOptions, + }); + } + function makeAuthenticatedRequest(reqOpts, optionsOrCallback) { + let stream; + let projectId; + const reqConfig = { ...config }; + let activeRequest_; + if (!optionsOrCallback) { + stream = (0, duplexify_1.default)(); + reqConfig.stream = stream; + } + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : undefined; + const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : undefined; + async function setProjectId() { + projectId = await authClient.getProjectId(); + } + const onAuthenticated = async (err, authenticatedReqOpts) => { + const authLibraryError = err; + const autoAuthFailed = err && + typeof err.message === 'string' && + err.message.indexOf('Could not load the default credentials') > -1; + if (autoAuthFailed) { + // Even though authentication failed, the API might not actually + // care. + authenticatedReqOpts = reqOpts; + } + if (!err || autoAuthFailed) { + try { + // Try with existing `projectId` value + authenticatedReqOpts = util.decorateRequest(authenticatedReqOpts, projectId); + err = null; + } + catch (e) { + if (e instanceof projectify_1.MissingProjectIdError) { + // A `projectId` was required, but we don't have one. + try { + // Attempt to get the `projectId` + await setProjectId(); + authenticatedReqOpts = util.decorateRequest(authenticatedReqOpts, projectId); + err = null; + } + catch (e) { + // Re-use the "Could not load the default credentials error" if + // auto auth failed. + err = err || e; + } + } + else { + // Some other error unrelated to missing `projectId` + err = err || e; + } + } + } + if (err) { + if (stream) { + stream.destroy(err); + } + else { + const fn = options && options.onAuthenticated + ? options.onAuthenticated + : callback; + fn(err); + } + return; + } + if (options && options.onAuthenticated) { + options.onAuthenticated(null, authenticatedReqOpts); + } + else { + activeRequest_ = util.makeRequest(authenticatedReqOpts, reqConfig, (apiResponseError, ...params) => { + if (apiResponseError && + apiResponseError.code === 401 && + authLibraryError) { + // Re-use the "Could not load the default credentials error" if + // the API request failed due to missing credentials. + apiResponseError = authLibraryError; + } + callback(apiResponseError, ...params); + }); + } + }; + const prepareRequest = async () => { + try { + const getProjectId = async () => { + if (config.projectId && + config.projectId !== service_js_1.DEFAULT_PROJECT_ID_TOKEN) { + // The user provided a project ID. We don't need to check with the + // auth client, it could be incorrect. + return config.projectId; + } + if (config.projectIdRequired === false) { + // A projectId is not required. Return the default. + return service_js_1.DEFAULT_PROJECT_ID_TOKEN; + } + return setProjectId(); + }; + const authorizeRequest = async () => { + if (reqConfig.customEndpoint && + !reqConfig.useAuthWithCustomEndpoint) { + // Using a custom API override. Do not use `google-auth-library` for + // authentication. (ex: connecting to a local Datastore server) + return reqOpts; + } + else { + return authClient.authorizeRequest(reqOpts); + } + }; + const [_projectId, authorizedReqOpts] = await Promise.all([ + getProjectId(), + authorizeRequest(), + ]); + if (_projectId) { + projectId = _projectId; + } + return onAuthenticated(null, authorizedReqOpts); + } + catch (e) { + return onAuthenticated(e); + } + }; + prepareRequest(); + if (stream) { + return stream; + } + return { + abort() { + setImmediate(() => { + if (activeRequest_) { + activeRequest_.abort(); + activeRequest_ = null; + } + }); + }, + }; + } + const mar = makeAuthenticatedRequest; + mar.getCredentials = authClient.getCredentials.bind(authClient); + mar.authClient = authClient; + return mar; + } + /** + * Make a request through the `retryRequest` module with built-in error + * handling and exponential back off. + * + * @param {object} reqOpts - Request options in the format `request` expects. + * @param {object=} config - Configuration object. + * @param {boolean=} config.autoRetry - Automatically retry requests if the + * response is related to rate limits or certain intermittent server + * errors. We will exponentially backoff subsequent requests by default. + * (default: true) + * @param {number=} config.maxRetries - Maximum number of automatic retries + * attempted before returning the error. (default: 3) + * @param {object=} config.request - HTTP module for request calls. + * @param {function} callback - The callback function. + */ + makeRequest(reqOpts, config, callback) { + var _a, _b, _c, _d, _e; + let autoRetryValue = AUTO_RETRY_DEFAULT; + if (config.autoRetry !== undefined) { + autoRetryValue = config.autoRetry; + } + else if (((_a = config.retryOptions) === null || _a === void 0 ? void 0 : _a.autoRetry) !== undefined) { + autoRetryValue = config.retryOptions.autoRetry; + } + let maxRetryValue = MAX_RETRY_DEFAULT; + if (config.maxRetries !== undefined) { + maxRetryValue = config.maxRetries; + } + else if (((_b = config.retryOptions) === null || _b === void 0 ? void 0 : _b.maxRetries) !== undefined) { + maxRetryValue = config.retryOptions.maxRetries; + } + requestDefaults.headers = this._getDefaultHeaders(reqOpts[exports.GCCL_GCS_CMD_KEY]); + const options = { + request: teeny_request_1.teenyRequest.defaults(requestDefaults), + retries: autoRetryValue !== false ? maxRetryValue : 0, + noResponseRetries: autoRetryValue !== false ? maxRetryValue : 0, + shouldRetryFn(httpRespMessage) { + var _a, _b; + const err = util.parseHttpRespMessage(httpRespMessage).err; + if ((_a = config.retryOptions) === null || _a === void 0 ? void 0 : _a.retryableErrorFn) { + return err && ((_b = config.retryOptions) === null || _b === void 0 ? void 0 : _b.retryableErrorFn(err)); + } + return err && util.shouldRetryRequest(err); + }, + maxRetryDelay: (_c = config.retryOptions) === null || _c === void 0 ? void 0 : _c.maxRetryDelay, + retryDelayMultiplier: (_d = config.retryOptions) === null || _d === void 0 ? void 0 : _d.retryDelayMultiplier, + totalTimeout: (_e = config.retryOptions) === null || _e === void 0 ? void 0 : _e.totalTimeout, + }; + if (typeof reqOpts.maxRetries === 'number') { + options.retries = reqOpts.maxRetries; + options.noResponseRetries = reqOpts.maxRetries; + } + if (!config.stream) { + return (0, retry_request_1.default)(reqOpts, options, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (err, response, body) => { + util.handleResp(err, response, body, callback); + }); + } + const dup = config.stream; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let requestStream; + const isGetRequest = (reqOpts.method || 'GET').toUpperCase() === 'GET'; + if (isGetRequest) { + requestStream = (0, retry_request_1.default)(reqOpts, options); + dup.setReadable(requestStream); + } + else { + // Streaming writable HTTP requests cannot be retried. + requestStream = options.request(reqOpts); + dup.setWritable(requestStream); + } + // Replay the Request events back to the stream. + requestStream + .on('error', dup.destroy.bind(dup)) + .on('response', dup.emit.bind(dup, 'response')) + .on('complete', dup.emit.bind(dup, 'complete')); + dup.abort = requestStream.abort; + return dup; + } + /** + * Decorate the options about to be made in a request. + * + * @param {object} reqOpts - The options to be passed to `request`. + * @param {string} projectId - The project ID. + * @return {object} reqOpts - The decorated reqOpts. + */ + decorateRequest(reqOpts, projectId) { + delete reqOpts.autoPaginate; + delete reqOpts.autoPaginateVal; + delete reqOpts.objectMode; + if (reqOpts.qs !== null && typeof reqOpts.qs === 'object') { + delete reqOpts.qs.autoPaginate; + delete reqOpts.qs.autoPaginateVal; + reqOpts.qs = (0, projectify_1.replaceProjectIdToken)(reqOpts.qs, projectId); + } + if (Array.isArray(reqOpts.multipart)) { + reqOpts.multipart = reqOpts.multipart.map(part => { + return (0, projectify_1.replaceProjectIdToken)(part, projectId); + }); + } + if (reqOpts.json !== null && typeof reqOpts.json === 'object') { + delete reqOpts.json.autoPaginate; + delete reqOpts.json.autoPaginateVal; + reqOpts.json = (0, projectify_1.replaceProjectIdToken)(reqOpts.json, projectId); + } + reqOpts.uri = (0, projectify_1.replaceProjectIdToken)(reqOpts.uri, projectId); + return reqOpts; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + isCustomType(unknown, module) { + function getConstructorName(obj) { + return obj.constructor && obj.constructor.name.toLowerCase(); + } + const moduleNameParts = module.split('/'); + const parentModuleName = moduleNameParts[0] && moduleNameParts[0].toLowerCase(); + const subModuleName = moduleNameParts[1] && moduleNameParts[1].toLowerCase(); + if (subModuleName && getConstructorName(unknown) !== subModuleName) { + return false; + } + let walkingModule = unknown; + // eslint-disable-next-line no-constant-condition + while (true) { + if (getConstructorName(walkingModule) === parentModuleName) { + return true; + } + walkingModule = walkingModule.parent; + if (!walkingModule) { + return false; + } + } + } + /** + * Given two parameters, figure out if this is either: + * - Just a callback function + * - An options object, and then a callback function + * @param optionsOrCallback An options object or callback. + * @param cb A potentially undefined callback. + */ + maybeOptionsOrCallback(optionsOrCallback, cb) { + return typeof optionsOrCallback === 'function' + ? [{}, optionsOrCallback] + : [optionsOrCallback, cb]; + } + _getDefaultHeaders(gcclGcsCmd) { + const headers = { + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${uuid.v4()}`, + }; + if (gcclGcsCmd) { + headers['x-goog-api-client'] += ` gccl-gcs-cmd/${gcclGcsCmd}`; + } + return headers; + } +} +exports.Util = Util; +/** + * Basic Passthrough Stream that records the number of bytes read + * every time the cursor is moved. + */ +class ProgressStream extends stream_1.Transform { + constructor() { + super(...arguments); + this.bytesRead = 0; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + _transform(chunk, encoding, callback) { + this.bytesRead += chunk.length; + this.emit('progress', { bytesWritten: this.bytesRead, contentLength: '*' }); + this.push(chunk); + callback(); + } +} +const util = new Util(); +exports.util = util; + + +/***/ }), + +/***/ 18598: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Notification = void 0; +const index_js_1 = __nccwpck_require__(11325); +const promisify_1 = __nccwpck_require__(60206); +/** + * The API-formatted resource description of the notification. + * + * Note: This is not guaranteed to be up-to-date when accessed. To get the + * latest record, call the `getMetadata()` method. + * + * @name Notification#metadata + * @type {object} + */ +/** + * A Notification object is created from your {@link Bucket} object using + * {@link Bucket#notification}. Use it to interact with Cloud Pub/Sub + * notifications. + * + * See {@link https://cloud.google.com/storage/docs/pubsub-notifications| Cloud Pub/Sub Notifications for Google Cloud Storage} + * + * @class + * @hideconstructor + * + * @param {Bucket} bucket The bucket instance this notification is attached to. + * @param {string} id The ID of the notification. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * + * const notification = myBucket.notification('1'); + * ``` + */ +class Notification extends index_js_1.ServiceObject { + constructor(bucket, id) { + const requestQueryObject = {}; + const methods = { + /** + * Creates a notification subscription for the bucket. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/insert| Notifications: insert} + * @method Notification#create + * + * @param {Topic|string} topic The Cloud PubSub topic to which this + * subscription publishes. If the project ID is omitted, the current + * project ID will be used. + * + * Acceptable formats are: + * - `projects/grape-spaceship-123/topics/my-topic` + * + * - `my-topic` + * @param {CreateNotificationRequest} [options] Metadata to set for + * the notification. + * @param {CreateNotificationCallback} [callback] Callback function. + * @returns {Promise} + * @throws {Error} If a valid topic is not provided. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.create(function(err, notification, apiResponse) { + * if (!err) { + * // The notification was created successfully. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.create().then(function(data) { + * const notification = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + create: true, + /** + * @typedef {array} DeleteNotificationResponse + * @property {object} 0 The full API response. + */ + /** + * Permanently deletes a notification subscription. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/delete| Notifications: delete API Documentation} + * + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {DeleteNotificationCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.delete(function(err, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.delete().then(function(data) { + * const apiResponse = data[0]; + * }); + * + * ``` + * @example include:samples/deleteNotification.js + * region_tag:storage_delete_bucket_notification + * Another example: + */ + delete: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * Get a notification and its metadata if it exists. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/get| Notifications: get API Documentation} + * + * @param {object} [options] Configuration options. + * See {@link Bucket#createNotification} for create options. + * @param {boolean} [options.autoCreate] Automatically create the object if + * it does not exist. Default: `false`. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetNotificationCallback} [callback] Callback function. + * @return {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.get(function(err, notification, apiResponse) { + * // `notification.metadata` has been populated. + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.get().then(function(data) { + * const notification = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ + get: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * Get the notification's metadata. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/notifications/get| Notifications: get API Documentation} + * + * @param {object} [options] Configuration options. + * @param {string} [options.userProject] The ID of the project which will be + * billed for the request. + * @param {GetNotificationMetadataCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.getMetadata(function(err, metadata, apiResponse) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.getMetadata().then(function(data) { + * const metadata = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/getMetadataNotifications.js + * region_tag:storage_print_pubsub_bucket_notification + * Another example: + */ + getMetadata: { + reqOpts: { + qs: requestQueryObject, + }, + }, + /** + * @typedef {array} NotificationExistsResponse + * @property {boolean} 0 Whether the notification exists or not. + */ + /** + * @callback NotificationExistsCallback + * @param {?Error} err Request error, if any. + * @param {boolean} exists Whether the notification exists or not. + */ + /** + * Check if the notification exists. + * + * @method Notification#exists + * @param {NotificationExistsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const myBucket = storage.bucket('my-bucket'); + * const notification = myBucket.notification('1'); + * + * notification.exists(function(err, exists) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * notification.exists().then(function(data) { + * const exists = data[0]; + * }); + * ``` + */ + exists: true, + }; + super({ + parent: bucket, + baseUrl: '/notificationConfigs', + id: id.toString(), + createMethod: bucket.createNotification.bind(bucket), + methods, + }); + } +} +exports.Notification = Notification; +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Notification); + + +/***/ }), + +/***/ 88043: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _Upload_instances, _Upload_gcclGcsCmd, _Upload_resetLocalBuffersCache, _Upload_addLocalBufferCache; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Upload = exports.PROTOCOL_REGEX = void 0; +exports.upload = upload; +exports.createURI = createURI; +exports.checkUploadStatus = checkUploadStatus; +const abort_controller_1 = __importDefault(__nccwpck_require__(17413)); +const crypto_1 = __nccwpck_require__(76982); +const gaxios = __importStar(__nccwpck_require__(97003)); +const google_auth_library_1 = __nccwpck_require__(492); +const stream_1 = __nccwpck_require__(2203); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +const uuid = __importStar(__nccwpck_require__(20607)); +const util_js_1 = __nccwpck_require__(74557); +const util_js_2 = __nccwpck_require__(37325); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const NOT_FOUND_STATUS_CODE = 404; +const RESUMABLE_INCOMPLETE_STATUS_CODE = 308; +const packageJson = (0, package_json_helper_cjs_1.getPackageJSON)(); +exports.PROTOCOL_REGEX = /^(\w*):\/\//; +class Upload extends stream_1.Writable { + constructor(cfg) { + var _a; + super(cfg); + _Upload_instances.add(this); + this.numBytesWritten = 0; + this.numRetries = 0; + this.currentInvocationId = { + checkUploadStatus: uuid.v4(), + chunk: uuid.v4(), + uri: uuid.v4(), + }; + /** + * A cache of buffers written to this instance, ready for consuming + */ + this.writeBuffers = []; + this.numChunksReadInRequest = 0; + /** + * An array of buffers used for caching the most recent upload chunk. + * We should not assume that the server received all bytes sent in the request. + * - https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + */ + this.localWriteCache = []; + this.localWriteCacheByteLength = 0; + this.upstreamEnded = false; + _Upload_gcclGcsCmd.set(this, void 0); + cfg = cfg || {}; + if (!cfg.bucket || !cfg.file) { + throw new Error('A bucket and file name are required'); + } + if (cfg.offset && !cfg.uri) { + throw new RangeError('Cannot provide an `offset` without providing a `uri`'); + } + if (cfg.isPartialUpload && !cfg.chunkSize) { + throw new RangeError('Cannot set `isPartialUpload` without providing a `chunkSize`'); + } + cfg.authConfig = cfg.authConfig || {}; + cfg.authConfig.scopes = [ + 'https://www.googleapis.com/auth/devstorage.full_control', + ]; + this.authClient = cfg.authClient || new google_auth_library_1.GoogleAuth(cfg.authConfig); + const universe = cfg.universeDomain || google_auth_library_1.DEFAULT_UNIVERSE; + this.apiEndpoint = `https://storage.${universe}`; + if (cfg.apiEndpoint && cfg.apiEndpoint !== this.apiEndpoint) { + this.apiEndpoint = this.sanitizeEndpoint(cfg.apiEndpoint); + const hostname = new URL(this.apiEndpoint).hostname; + // check if it is a domain of a known universe + const isDomain = hostname === universe; + const isDefaultUniverseDomain = hostname === google_auth_library_1.DEFAULT_UNIVERSE; + // check if it is a subdomain of a known universe + // by checking a last (universe's length + 1) of a hostname + const isSubDomainOfUniverse = hostname.slice(-(universe.length + 1)) === `.${universe}`; + const isSubDomainOfDefaultUniverse = hostname.slice(-(google_auth_library_1.DEFAULT_UNIVERSE.length + 1)) === + `.${google_auth_library_1.DEFAULT_UNIVERSE}`; + if (!isDomain && + !isDefaultUniverseDomain && + !isSubDomainOfUniverse && + !isSubDomainOfDefaultUniverse) { + // a custom, non-universe domain, + // use gaxios + this.authClient = gaxios; + } + } + this.baseURI = `${this.apiEndpoint}/upload/storage/v1/b`; + this.bucket = cfg.bucket; + const cacheKeyElements = [cfg.bucket, cfg.file]; + if (typeof cfg.generation === 'number') { + cacheKeyElements.push(`${cfg.generation}`); + } + this.cacheKey = cacheKeyElements.join('/'); + this.customRequestOptions = cfg.customRequestOptions || {}; + this.file = cfg.file; + this.generation = cfg.generation; + this.kmsKeyName = cfg.kmsKeyName; + this.metadata = cfg.metadata || {}; + this.offset = cfg.offset; + this.origin = cfg.origin; + this.params = cfg.params || {}; + this.userProject = cfg.userProject; + this.chunkSize = cfg.chunkSize; + this.retryOptions = cfg.retryOptions; + this.isPartialUpload = (_a = cfg.isPartialUpload) !== null && _a !== void 0 ? _a : false; + if (cfg.key) { + if (typeof cfg.key === 'string') { + const base64Key = Buffer.from(cfg.key).toString('base64'); + this.encryption = { + key: base64Key, + hash: (0, crypto_1.createHash)('sha256').update(cfg.key).digest('base64'), + }; + } + else { + const base64Key = cfg.key.toString('base64'); + this.encryption = { + key: base64Key, + hash: (0, crypto_1.createHash)('sha256').update(cfg.key).digest('base64'), + }; + } + } + this.predefinedAcl = cfg.predefinedAcl; + if (cfg.private) + this.predefinedAcl = 'private'; + if (cfg.public) + this.predefinedAcl = 'publicRead'; + const autoRetry = cfg.retryOptions.autoRetry; + this.uriProvidedManually = !!cfg.uri; + this.uri = cfg.uri; + if (this.offset) { + // we're resuming an incomplete upload + this.numBytesWritten = this.offset; + } + this.numRetries = 0; // counter for number of retries currently executed + if (!autoRetry) { + cfg.retryOptions.maxRetries = 0; + } + this.timeOfFirstRequest = Date.now(); + const contentLength = cfg.metadata + ? Number(cfg.metadata.contentLength) + : NaN; + this.contentLength = isNaN(contentLength) ? '*' : contentLength; + __classPrivateFieldSet(this, _Upload_gcclGcsCmd, cfg[util_js_2.GCCL_GCS_CMD_KEY], "f"); + this.once('writing', () => { + if (this.uri) { + this.continueUploading(); + } + else { + this.createURI(err => { + if (err) { + return this.destroy(err); + } + this.startUploading(); + return; + }); + } + }); + } + /** + * Prevent 'finish' event until the upload has succeeded. + * + * @param fireFinishEvent The finish callback + */ + _final(fireFinishEvent = () => { }) { + this.upstreamEnded = true; + this.once('uploadFinished', fireFinishEvent); + process.nextTick(() => { + this.emit('upstreamFinished'); + // it's possible `_write` may not be called - namely for empty object uploads + this.emit('writing'); + }); + } + /** + * Handles incoming data from upstream + * + * @param chunk The chunk to append to the buffer + * @param encoding The encoding of the chunk + * @param readCallback A callback for when the buffer has been read downstream + */ + _write(chunk, encoding, readCallback = () => { }) { + // Backwards-compatible event + this.emit('writing'); + this.writeBuffers.push(typeof chunk === 'string' ? Buffer.from(chunk, encoding) : chunk); + this.once('readFromChunkBuffer', readCallback); + process.nextTick(() => this.emit('wroteToChunkBuffer')); + } + /** + * Prepends the local buffer to write buffer and resets it. + * + * @param keepLastBytes number of bytes to keep from the end of the local buffer. + */ + prependLocalBufferToUpstream(keepLastBytes) { + // Typically, the upstream write buffers should be smaller than the local + // cache, so we can save time by setting the local cache as the new + // upstream write buffer array and appending the old array to it + let initialBuffers = []; + if (keepLastBytes) { + // we only want the last X bytes + let bytesKept = 0; + while (keepLastBytes > bytesKept) { + // load backwards because we want the last X bytes + // note: `localWriteCacheByteLength` is reset below + let buf = this.localWriteCache.pop(); + if (!buf) + break; + bytesKept += buf.byteLength; + if (bytesKept > keepLastBytes) { + // we have gone over the amount desired, let's keep the last X bytes + // of this buffer + const diff = bytesKept - keepLastBytes; + buf = buf.subarray(diff); + bytesKept -= diff; + } + initialBuffers.unshift(buf); + } + } + else { + // we're keeping all of the local cache, simply use it as the initial buffer + initialBuffers = this.localWriteCache; + } + // Append the old upstream to the new + const append = this.writeBuffers; + this.writeBuffers = initialBuffers; + for (const buf of append) { + this.writeBuffers.push(buf); + } + // reset last buffers sent + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + } + /** + * Retrieves data from upstream's buffer. + * + * @param limit The maximum amount to return from the buffer. + */ + *pullFromChunkBuffer(limit) { + while (limit) { + const buf = this.writeBuffers.shift(); + if (!buf) + break; + let bufToYield = buf; + if (buf.byteLength > limit) { + bufToYield = buf.subarray(0, limit); + this.writeBuffers.unshift(buf.subarray(limit)); + limit = 0; + } + else { + limit -= buf.byteLength; + } + yield bufToYield; + // Notify upstream we've read from the buffer and we're able to consume + // more. It can also potentially send more data down as we're currently + // iterating. + this.emit('readFromChunkBuffer'); + } + } + /** + * A handler for determining if data is ready to be read from upstream. + * + * @returns If there will be more chunks to read in the future + */ + async waitForNextChunk() { + const willBeMoreChunks = await new Promise(resolve => { + // There's data available - it should be digested + if (this.writeBuffers.length) { + return resolve(true); + } + // The upstream writable ended, we shouldn't expect any more data. + if (this.upstreamEnded) { + return resolve(false); + } + // Nothing immediate seems to be determined. We need to prepare some + // listeners to determine next steps... + const wroteToChunkBufferCallback = () => { + removeListeners(); + return resolve(true); + }; + const upstreamFinishedCallback = () => { + removeListeners(); + // this should be the last chunk, if there's anything there + if (this.writeBuffers.length) + return resolve(true); + return resolve(false); + }; + // Remove listeners when we're ready to callback. + const removeListeners = () => { + this.removeListener('wroteToChunkBuffer', wroteToChunkBufferCallback); + this.removeListener('upstreamFinished', upstreamFinishedCallback); + }; + // If there's data recently written it should be digested + this.once('wroteToChunkBuffer', wroteToChunkBufferCallback); + // If the upstream finishes let's see if there's anything to grab + this.once('upstreamFinished', upstreamFinishedCallback); + }); + return willBeMoreChunks; + } + /** + * Reads data from upstream up to the provided `limit`. + * Ends when the limit has reached or no data is expected to be pushed from upstream. + * + * @param limit The most amount of data this iterator should return. `Infinity` by default. + */ + async *upstreamIterator(limit = Infinity) { + // read from upstream chunk buffer + while (limit && (await this.waitForNextChunk())) { + // read until end or limit has been reached + for (const chunk of this.pullFromChunkBuffer(limit)) { + limit -= chunk.byteLength; + yield chunk; + } + } + } + createURI(callback) { + if (!callback) { + return this.createURIAsync(); + } + this.createURIAsync().then(r => callback(null, r), callback); + } + async createURIAsync() { + const metadata = { ...this.metadata }; + const headers = {}; + // Delete content length and content type from metadata if they exist. + // These are headers and should not be sent as part of the metadata. + if (metadata.contentLength) { + headers['X-Upload-Content-Length'] = metadata.contentLength.toString(); + delete metadata.contentLength; + } + if (metadata.contentType) { + headers['X-Upload-Content-Type'] = metadata.contentType; + delete metadata.contentType; + } + let googAPIClient = `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${this.currentInvocationId.uri}`; + if (__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")) { + googAPIClient += ` gccl-gcs-cmd/${__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")}`; + } + // Check if headers already exist before creating new ones + const reqOpts = { + method: 'POST', + url: [this.baseURI, this.bucket, 'o'].join('/'), + params: Object.assign({ + name: this.file, + uploadType: 'resumable', + }, this.params), + data: metadata, + headers: { + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': googAPIClient, + ...headers, + }, + }; + if (metadata.contentLength) { + reqOpts.headers['X-Upload-Content-Length'] = + metadata.contentLength.toString(); + } + if (metadata.contentType) { + reqOpts.headers['X-Upload-Content-Type'] = metadata.contentType; + } + if (typeof this.generation !== 'undefined') { + reqOpts.params.ifGenerationMatch = this.generation; + } + if (this.kmsKeyName) { + reqOpts.params.kmsKeyName = this.kmsKeyName; + } + if (this.predefinedAcl) { + reqOpts.params.predefinedAcl = this.predefinedAcl; + } + if (this.origin) { + reqOpts.headers.Origin = this.origin; + } + const uri = await (0, async_retry_1.default)(async (bail) => { + var _a, _b, _c; + try { + const res = await this.makeRequest(reqOpts); + // We have successfully got a URI we can now create a new invocation id + this.currentInvocationId.uri = uuid.v4(); + return res.headers.location; + } + catch (err) { + const e = err; + const apiError = { + code: (_a = e.response) === null || _a === void 0 ? void 0 : _a.status, + name: (_b = e.response) === null || _b === void 0 ? void 0 : _b.statusText, + message: (_c = e.response) === null || _c === void 0 ? void 0 : _c.statusText, + errors: [ + { + reason: e.code, + }, + ], + }; + if (this.retryOptions.maxRetries > 0 && + this.retryOptions.retryableErrorFn(apiError)) { + throw e; + } + else { + return bail(e); + } + } + }, { + retries: this.retryOptions.maxRetries, + factor: this.retryOptions.retryDelayMultiplier, + maxTimeout: this.retryOptions.maxRetryDelay * 1000, //convert to milliseconds + maxRetryTime: this.retryOptions.totalTimeout * 1000, //convert to milliseconds + }); + this.uri = uri; + this.offset = 0; + // emit the newly generated URI for future reuse, if necessary. + this.emit('uri', uri); + return uri; + } + async continueUploading() { + var _a; + (_a = this.offset) !== null && _a !== void 0 ? _a : (await this.getAndSetOffset()); + return this.startUploading(); + } + async startUploading() { + const multiChunkMode = !!this.chunkSize; + let responseReceived = false; + this.numChunksReadInRequest = 0; + if (!this.offset) { + this.offset = 0; + } + // Check if the offset (server) is too far behind the current stream + if (this.offset < this.numBytesWritten) { + const delta = this.numBytesWritten - this.offset; + const message = `The offset is lower than the number of bytes written. The server has ${this.offset} bytes and while ${this.numBytesWritten} bytes has been uploaded - thus ${delta} bytes are missing. Stopping as this could result in data loss. Initiate a new upload to continue.`; + this.emit('error', new RangeError(message)); + return; + } + // Check if we should 'fast-forward' to the relevant data to upload + if (this.numBytesWritten < this.offset) { + // 'fast-forward' to the byte where we need to upload. + // only push data from the byte after the one we left off on + const fastForwardBytes = this.offset - this.numBytesWritten; + for await (const _chunk of this.upstreamIterator(fastForwardBytes)) { + _chunk; // discard the data up until the point we want + } + this.numBytesWritten = this.offset; + } + let expectedUploadSize = undefined; + // Set `expectedUploadSize` to `contentLength - this.numBytesWritten`, if available + if (typeof this.contentLength === 'number') { + expectedUploadSize = this.contentLength - this.numBytesWritten; + } + // `expectedUploadSize` should be no more than the `chunkSize`. + // It's possible this is the last chunk request for a multiple + // chunk upload, thus smaller than the chunk size. + if (this.chunkSize) { + expectedUploadSize = expectedUploadSize + ? Math.min(this.chunkSize, expectedUploadSize) + : this.chunkSize; + } + // A queue for the upstream data + const upstreamQueue = this.upstreamIterator(expectedUploadSize); + // The primary read stream for this request. This stream retrieves no more + // than the exact requested amount from upstream. + const requestStream = new stream_1.Readable({ + read: async () => { + // Don't attempt to retrieve data upstream if we already have a response + if (responseReceived) + requestStream.push(null); + const result = await upstreamQueue.next(); + if (result.value) { + this.numChunksReadInRequest++; + if (multiChunkMode) { + // save ever buffer used in the request in multi-chunk mode + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_addLocalBufferCache).call(this, result.value); + } + else { + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_addLocalBufferCache).call(this, result.value); + } + this.numBytesWritten += result.value.byteLength; + this.emit('progress', { + bytesWritten: this.numBytesWritten, + contentLength: this.contentLength, + }); + requestStream.push(result.value); + } + if (result.done) { + requestStream.push(null); + } + }, + }); + let googAPIClient = `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${this.currentInvocationId.chunk}`; + if (__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")) { + googAPIClient += ` gccl-gcs-cmd/${__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")}`; + } + const headers = { + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': googAPIClient, + }; + // If using multiple chunk upload, set appropriate header + if (multiChunkMode) { + // We need to know how much data is available upstream to set the `Content-Range` header. + // https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + for await (const chunk of this.upstreamIterator(expectedUploadSize)) { + // This will conveniently track and keep the size of the buffers. + // We will reach either the expected upload size or the remainder of the stream. + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_addLocalBufferCache).call(this, chunk); + } + // This is the sum from the `#addLocalBufferCache` calls + const bytesToUpload = this.localWriteCacheByteLength; + // Important: we want to know if the upstream has ended and the queue is empty before + // unshifting data back into the queue. This way we will know if this is the last request or not. + const isLastChunkOfUpload = !(await this.waitForNextChunk()); + // Important: put the data back in the queue for the actual upload + this.prependLocalBufferToUpstream(); + let totalObjectSize = this.contentLength; + if (typeof this.contentLength !== 'number' && + isLastChunkOfUpload && + !this.isPartialUpload) { + // Let's let the server know this is the last chunk of the object since we didn't set it before. + totalObjectSize = bytesToUpload + this.numBytesWritten; + } + // `- 1` as the ending byte is inclusive in the request. + const endingByte = bytesToUpload + this.numBytesWritten - 1; + // `Content-Length` for multiple chunk uploads is the size of the chunk, + // not the overall object + headers['Content-Length'] = bytesToUpload; + headers['Content-Range'] = + `bytes ${this.offset}-${endingByte}/${totalObjectSize}`; + } + else { + headers['Content-Range'] = `bytes ${this.offset}-*/${this.contentLength}`; + } + const reqOpts = { + method: 'PUT', + url: this.uri, + headers, + body: requestStream, + }; + try { + const resp = await this.makeRequestStream(reqOpts); + if (resp) { + responseReceived = true; + await this.responseHandler(resp); + } + } + catch (e) { + const err = e; + if (this.retryOptions.retryableErrorFn(err)) { + this.attemptDelayedRetry({ + status: NaN, + data: err, + }); + return; + } + this.destroy(err); + } + } + // Process the API response to look for errors that came in + // the response body. + async responseHandler(resp) { + if (resp.data.error) { + this.destroy(resp.data.error); + return; + } + // At this point we can safely create a new id for the chunk + this.currentInvocationId.chunk = uuid.v4(); + const moreDataToUpload = await this.waitForNextChunk(); + const shouldContinueWithNextMultiChunkRequest = this.chunkSize && + resp.status === RESUMABLE_INCOMPLETE_STATUS_CODE && + resp.headers.range && + moreDataToUpload; + /** + * This is true when we're expecting to upload more data in a future request, + * yet the upstream for the upload session has been exhausted. + */ + const shouldContinueUploadInAnotherRequest = this.isPartialUpload && + resp.status === RESUMABLE_INCOMPLETE_STATUS_CODE && + !moreDataToUpload; + if (shouldContinueWithNextMultiChunkRequest) { + // Use the upper value in this header to determine where to start the next chunk. + // We should not assume that the server received all bytes sent in the request. + // https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + const range = resp.headers.range; + this.offset = Number(range.split('-')[1]) + 1; + // We should not assume that the server received all bytes sent in the request. + // - https://cloud.google.com/storage/docs/performing-resumable-uploads#chunked-upload + const missingBytes = this.numBytesWritten - this.offset; + if (missingBytes) { + // As multi-chunk uploads send one chunk per request and pulls one + // chunk into the pipeline, prepending the missing bytes back should + // be fine for the next request. + this.prependLocalBufferToUpstream(missingBytes); + this.numBytesWritten -= missingBytes; + } + else { + // No bytes missing - no need to keep the local cache + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + } + // continue uploading next chunk + this.continueUploading(); + } + else if (!this.isSuccessfulResponse(resp.status) && + !shouldContinueUploadInAnotherRequest) { + const err = new Error('Upload failed'); + err.code = resp.status; + err.name = 'Upload failed'; + if (resp === null || resp === void 0 ? void 0 : resp.data) { + err.errors = [resp === null || resp === void 0 ? void 0 : resp.data]; + } + this.destroy(err); + } + else { + // no need to keep the cache + __classPrivateFieldGet(this, _Upload_instances, "m", _Upload_resetLocalBuffersCache).call(this); + if (resp && resp.data) { + resp.data.size = Number(resp.data.size); + } + this.emit('metadata', resp.data); + // Allow the object (Upload) to continue naturally so the user's + // "finish" event fires. + this.emit('uploadFinished'); + } + } + /** + * Check the status of an existing resumable upload. + * + * @param cfg A configuration to use. `uri` is required. + * @returns the current upload status + */ + async checkUploadStatus(config = {}) { + let googAPIClient = `${(0, util_js_1.getRuntimeTrackingString)()} gccl/${packageJson.version}-${(0, util_js_1.getModuleFormat)()} gccl-invocation-id/${this.currentInvocationId.checkUploadStatus}`; + if (__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")) { + googAPIClient += ` gccl-gcs-cmd/${__classPrivateFieldGet(this, _Upload_gcclGcsCmd, "f")}`; + } + const opts = { + method: 'PUT', + url: this.uri, + headers: { + 'Content-Length': 0, + 'Content-Range': 'bytes */*', + 'User-Agent': (0, util_js_1.getUserAgentString)(), + 'x-goog-api-client': googAPIClient, + }, + }; + try { + const resp = await this.makeRequest(opts); + // Successfully got the offset we can now create a new offset invocation id + this.currentInvocationId.checkUploadStatus = uuid.v4(); + return resp; + } + catch (e) { + if (config.retry === false || + !(e instanceof Error) || + !this.retryOptions.retryableErrorFn(e)) { + throw e; + } + const retryDelay = this.getRetryDelay(); + if (retryDelay <= 0) { + throw e; + } + await new Promise(res => setTimeout(res, retryDelay)); + return this.checkUploadStatus(config); + } + } + async getAndSetOffset() { + try { + // we want to handle retries in this method. + const resp = await this.checkUploadStatus({ retry: false }); + if (resp.status === RESUMABLE_INCOMPLETE_STATUS_CODE) { + if (typeof resp.headers.range === 'string') { + this.offset = Number(resp.headers.range.split('-')[1]) + 1; + return; + } + } + this.offset = 0; + } + catch (e) { + const err = e; + if (this.retryOptions.retryableErrorFn(err)) { + this.attemptDelayedRetry({ + status: NaN, + data: err, + }); + return; + } + this.destroy(err); + } + } + async makeRequest(reqOpts) { + if (this.encryption) { + reqOpts.headers = reqOpts.headers || {}; + reqOpts.headers['x-goog-encryption-algorithm'] = 'AES256'; + reqOpts.headers['x-goog-encryption-key'] = this.encryption.key.toString(); + reqOpts.headers['x-goog-encryption-key-sha256'] = + this.encryption.hash.toString(); + } + if (this.userProject) { + reqOpts.params = reqOpts.params || {}; + reqOpts.params.userProject = this.userProject; + } + // Let gaxios know we will handle a 308 error code ourselves. + reqOpts.validateStatus = (status) => { + return (this.isSuccessfulResponse(status) || + status === RESUMABLE_INCOMPLETE_STATUS_CODE); + }; + const combinedReqOpts = { + ...this.customRequestOptions, + ...reqOpts, + headers: { + ...this.customRequestOptions.headers, + ...reqOpts.headers, + }, + }; + const res = await this.authClient.request(combinedReqOpts); + if (res.data && res.data.error) { + throw res.data.error; + } + return res; + } + async makeRequestStream(reqOpts) { + const controller = new abort_controller_1.default(); + const errorCallback = () => controller.abort(); + this.once('error', errorCallback); + if (this.userProject) { + reqOpts.params = reqOpts.params || {}; + reqOpts.params.userProject = this.userProject; + } + reqOpts.signal = controller.signal; + reqOpts.validateStatus = () => true; + const combinedReqOpts = { + ...this.customRequestOptions, + ...reqOpts, + headers: { + ...this.customRequestOptions.headers, + ...reqOpts.headers, + }, + }; + const res = await this.authClient.request(combinedReqOpts); + const successfulRequest = this.onResponse(res); + this.removeListener('error', errorCallback); + return successfulRequest ? res : null; + } + /** + * @return {bool} is the request good? + */ + onResponse(resp) { + if (resp.status !== 200 && + this.retryOptions.retryableErrorFn({ + code: resp.status, + message: resp.statusText, + name: resp.statusText, + })) { + this.attemptDelayedRetry(resp); + return false; + } + this.emit('response', resp); + return true; + } + /** + * @param resp GaxiosResponse object from previous attempt + */ + attemptDelayedRetry(resp) { + if (this.numRetries < this.retryOptions.maxRetries) { + if (resp.status === NOT_FOUND_STATUS_CODE && + this.numChunksReadInRequest === 0) { + this.startUploading(); + } + else { + const retryDelay = this.getRetryDelay(); + if (retryDelay <= 0) { + this.destroy(new Error(`Retry total time limit exceeded - ${JSON.stringify(resp.data)}`)); + return; + } + // Unshift the local cache back in case it's needed for the next request. + this.numBytesWritten -= this.localWriteCacheByteLength; + this.prependLocalBufferToUpstream(); + // We don't know how much data has been received by the server. + // `continueUploading` will recheck the offset via `getAndSetOffset`. + // If `offset` < `numberBytesReceived` then we will raise a RangeError + // as we've streamed too much data that has been missed - this should + // not be the case for multi-chunk uploads as `lastChunkSent` is the + // body of the entire request. + this.offset = undefined; + setTimeout(this.continueUploading.bind(this), retryDelay); + } + this.numRetries++; + } + else { + this.destroy(new Error(`Retry limit exceeded - ${JSON.stringify(resp.data)}`)); + } + } + /** + * The amount of time to wait before retrying the request, in milliseconds. + * If negative, do not retry. + * + * @returns the amount of time to wait, in milliseconds. + */ + getRetryDelay() { + const randomMs = Math.round(Math.random() * 1000); + const waitTime = Math.pow(this.retryOptions.retryDelayMultiplier, this.numRetries) * + 1000 + + randomMs; + const maxAllowableDelayMs = this.retryOptions.totalTimeout * 1000 - + (Date.now() - this.timeOfFirstRequest); + const maxRetryDelayMs = this.retryOptions.maxRetryDelay * 1000; + return Math.min(waitTime, maxRetryDelayMs, maxAllowableDelayMs); + } + /* + * Prepare user-defined API endpoint for compatibility with our API. + */ + sanitizeEndpoint(url) { + if (!exports.PROTOCOL_REGEX.test(url)) { + url = `https://${url}`; + } + return url.replace(/\/+$/, ''); // Remove trailing slashes + } + /** + * Check if a given status code is 2xx + * + * @param status The status code to check + * @returns if the status is 2xx + */ + isSuccessfulResponse(status) { + return status >= 200 && status < 300; + } +} +exports.Upload = Upload; +_Upload_gcclGcsCmd = new WeakMap(), _Upload_instances = new WeakSet(), _Upload_resetLocalBuffersCache = function _Upload_resetLocalBuffersCache() { + this.localWriteCache = []; + this.localWriteCacheByteLength = 0; +}, _Upload_addLocalBufferCache = function _Upload_addLocalBufferCache(buf) { + this.localWriteCache.push(buf); + this.localWriteCacheByteLength += buf.byteLength; +}; +function upload(cfg) { + return new Upload(cfg); +} +function createURI(cfg, callback) { + const up = new Upload(cfg); + if (!callback) { + return up.createURI(); + } + up.createURI().then(r => callback(null, r), callback); +} +/** + * Check the status of an existing resumable upload. + * + * @param cfg A configuration to use. `uri` is required. + * @returns the current upload status + */ +function checkUploadStatus(cfg) { + const up = new Upload(cfg); + return up.checkUploadStatus(); +} + + +/***/ }), + +/***/ 7319: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.SigningError = exports.URLSigner = exports.PATH_STYLED_HOST = exports.SignerExceptionMessages = void 0; +const crypto = __importStar(__nccwpck_require__(76982)); +const url = __importStar(__nccwpck_require__(87016)); +const storage_js_1 = __nccwpck_require__(92848); +const util_js_1 = __nccwpck_require__(74557); +var SignerExceptionMessages; +(function (SignerExceptionMessages) { + SignerExceptionMessages["ACCESSIBLE_DATE_INVALID"] = "The accessible at date provided was invalid."; + SignerExceptionMessages["EXPIRATION_BEFORE_ACCESSIBLE_DATE"] = "An expiration date cannot be before accessible date."; + SignerExceptionMessages["X_GOOG_CONTENT_SHA256"] = "The header X-Goog-Content-SHA256 must be a hexadecimal string."; +})(SignerExceptionMessages || (exports.SignerExceptionMessages = SignerExceptionMessages = {})); +/* + * Default signing version for getSignedUrl is 'v2'. + */ +const DEFAULT_SIGNING_VERSION = 'v2'; +const SEVEN_DAYS = 7 * 24 * 60 * 60; +/** + * @const {string} + * @deprecated - unused + */ +exports.PATH_STYLED_HOST = 'https://storage.googleapis.com'; +class URLSigner { + constructor(auth, bucket, file, + /** + * A {@link Storage} object. + * + * @privateRemarks + * + * Technically this is a required field, however it would be a breaking change to + * move it before optional properties. In the next major we should refactor the + * constructor of this class to only accept a config object. + */ + storage = new storage_js_1.Storage()) { + this.auth = auth; + this.bucket = bucket; + this.file = file; + this.storage = storage; + } + getSignedUrl(cfg) { + const expiresInSeconds = this.parseExpires(cfg.expires); + const method = cfg.method; + const accessibleAtInSeconds = this.parseAccessibleAt(cfg.accessibleAt); + if (expiresInSeconds < accessibleAtInSeconds) { + throw new Error(SignerExceptionMessages.EXPIRATION_BEFORE_ACCESSIBLE_DATE); + } + let customHost; + // Default style is `path`. + const isVirtualHostedStyle = cfg.virtualHostedStyle || false; + if (cfg.cname) { + customHost = cfg.cname; + } + else if (isVirtualHostedStyle) { + customHost = `https://${this.bucket.name}.storage.${this.storage.universeDomain}`; + } + const secondsToMilliseconds = 1000; + const config = Object.assign({}, cfg, { + method, + expiration: expiresInSeconds, + accessibleAt: new Date(secondsToMilliseconds * accessibleAtInSeconds), + bucket: this.bucket.name, + file: this.file ? (0, util_js_1.encodeURI)(this.file.name, false) : undefined, + }); + if (customHost) { + config.cname = customHost; + } + const version = cfg.version || DEFAULT_SIGNING_VERSION; + let promise; + if (version === 'v2') { + promise = this.getSignedUrlV2(config); + } + else if (version === 'v4') { + promise = this.getSignedUrlV4(config); + } + else { + throw new Error(`Invalid signed URL version: ${version}. Supported versions are 'v2' and 'v4'.`); + } + return promise.then(query => { + var _a; + query = Object.assign(query, cfg.queryParams); + const signedUrl = new url.URL(((_a = cfg.host) === null || _a === void 0 ? void 0 : _a.toString()) || config.cname || this.storage.apiEndpoint); + signedUrl.pathname = this.getResourcePath(!!config.cname, this.bucket.name, config.file); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + signedUrl.search = (0, util_js_1.qsStringify)(query); + return signedUrl.href; + }); + } + getSignedUrlV2(config) { + const canonicalHeadersString = this.getCanonicalHeaders(config.extensionHeaders || {}); + const resourcePath = this.getResourcePath(false, config.bucket, config.file); + const blobToSign = [ + config.method, + config.contentMd5 || '', + config.contentType || '', + config.expiration, + canonicalHeadersString + resourcePath, + ].join('\n'); + const sign = async () => { + var _a; + const auth = this.auth; + try { + const signature = await auth.sign(blobToSign, (_a = config.signingEndpoint) === null || _a === void 0 ? void 0 : _a.toString()); + const credentials = await auth.getCredentials(); + return { + GoogleAccessId: credentials.client_email, + Expires: config.expiration, + Signature: signature, + }; + } + catch (err) { + const error = err; + const signingErr = new SigningError(error.message); + signingErr.stack = error.stack; + throw signingErr; + } + }; + return sign(); + } + getSignedUrlV4(config) { + var _a; + config.accessibleAt = config.accessibleAt + ? config.accessibleAt + : new Date(); + const millisecondsToSeconds = 1.0 / 1000.0; + const expiresPeriodInSeconds = config.expiration - config.accessibleAt.valueOf() * millisecondsToSeconds; + // v4 limit expiration to be 7 days maximum + if (expiresPeriodInSeconds > SEVEN_DAYS) { + throw new Error(`Max allowed expiration is seven days (${SEVEN_DAYS} seconds).`); + } + const extensionHeaders = Object.assign({}, config.extensionHeaders); + const fqdn = new url.URL(((_a = config.host) === null || _a === void 0 ? void 0 : _a.toString()) || config.cname || this.storage.apiEndpoint); + extensionHeaders.host = fqdn.hostname; + if (config.contentMd5) { + extensionHeaders['content-md5'] = config.contentMd5; + } + if (config.contentType) { + extensionHeaders['content-type'] = config.contentType; + } + let contentSha256; + const sha256Header = extensionHeaders['x-goog-content-sha256']; + if (sha256Header) { + if (typeof sha256Header !== 'string' || + !/[A-Fa-f0-9]{40}/.test(sha256Header)) { + throw new Error(SignerExceptionMessages.X_GOOG_CONTENT_SHA256); + } + contentSha256 = sha256Header; + } + const signedHeaders = Object.keys(extensionHeaders) + .map(header => header.toLowerCase()) + .sort() + .join(';'); + const extensionHeadersString = this.getCanonicalHeaders(extensionHeaders); + const datestamp = (0, util_js_1.formatAsUTCISO)(config.accessibleAt); + const credentialScope = `${datestamp}/auto/storage/goog4_request`; + const sign = async () => { + var _a; + const credentials = await this.auth.getCredentials(); + const credential = `${credentials.client_email}/${credentialScope}`; + const dateISO = (0, util_js_1.formatAsUTCISO)(config.accessibleAt ? config.accessibleAt : new Date(), true); + const queryParams = { + 'X-Goog-Algorithm': 'GOOG4-RSA-SHA256', + 'X-Goog-Credential': credential, + 'X-Goog-Date': dateISO, + 'X-Goog-Expires': expiresPeriodInSeconds.toString(10), + 'X-Goog-SignedHeaders': signedHeaders, + ...(config.queryParams || {}), + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const canonicalQueryParams = this.getCanonicalQueryParams(queryParams); + const canonicalRequest = this.getCanonicalRequest(config.method, this.getResourcePath(!!config.cname, config.bucket, config.file), canonicalQueryParams, extensionHeadersString, signedHeaders, contentSha256); + const hash = crypto + .createHash('sha256') + .update(canonicalRequest) + .digest('hex'); + const blobToSign = [ + 'GOOG4-RSA-SHA256', + dateISO, + credentialScope, + hash, + ].join('\n'); + try { + const signature = await this.auth.sign(blobToSign, (_a = config.signingEndpoint) === null || _a === void 0 ? void 0 : _a.toString()); + const signatureHex = Buffer.from(signature, 'base64').toString('hex'); + const signedQuery = Object.assign({}, queryParams, { + 'X-Goog-Signature': signatureHex, + }); + return signedQuery; + } + catch (err) { + const error = err; + const signingErr = new SigningError(error.message); + signingErr.stack = error.stack; + throw signingErr; + } + }; + return sign(); + } + /** + * Create canonical headers for signing v4 url. + * + * The canonical headers for v4-signing a request demands header names are + * first lowercased, followed by sorting the header names. + * Then, construct the canonical headers part of the request: + * + ":" + Trim() + "\n" + * .. + * + ":" + Trim() + "\n" + * + * @param headers + * @private + */ + getCanonicalHeaders(headers) { + // Sort headers by their lowercased names + const sortedHeaders = (0, util_js_1.objectEntries)(headers) + // Convert header names to lowercase + .map(([headerName, value]) => [ + headerName.toLowerCase(), + value, + ]) + .sort((a, b) => a[0].localeCompare(b[0])); + return sortedHeaders + .filter(([, value]) => value !== undefined) + .map(([headerName, value]) => { + // - Convert Array (multi-valued header) into string, delimited by + // ',' (no space). + // - Trim leading and trailing spaces. + // - Convert sequential (2+) spaces into a single space + const canonicalValue = `${value}`.trim().replace(/\s{2,}/g, ' '); + return `${headerName}:${canonicalValue}\n`; + }) + .join(''); + } + getCanonicalRequest(method, path, query, headers, signedHeaders, contentSha256) { + return [ + method, + path, + query, + headers, + signedHeaders, + contentSha256 || 'UNSIGNED-PAYLOAD', + ].join('\n'); + } + getCanonicalQueryParams(query) { + return (0, util_js_1.objectEntries)(query) + .map(([key, value]) => [(0, util_js_1.encodeURI)(key, true), (0, util_js_1.encodeURI)(value, true)]) + .sort((a, b) => (a[0] < b[0] ? -1 : 1)) + .map(([key, value]) => `${key}=${value}`) + .join('&'); + } + getResourcePath(cname, bucket, file) { + if (cname) { + return '/' + (file || ''); + } + else if (file) { + return `/${bucket}/${file}`; + } + else { + return `/${bucket}`; + } + } + parseExpires(expires, current = new Date()) { + const expiresInMSeconds = new Date(expires).valueOf(); + if (isNaN(expiresInMSeconds)) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_INVALID); + } + if (expiresInMSeconds < current.valueOf()) { + throw new Error(storage_js_1.ExceptionMessages.EXPIRATION_DATE_PAST); + } + return Math.floor(expiresInMSeconds / 1000); // The API expects seconds. + } + parseAccessibleAt(accessibleAt) { + const accessibleAtInMSeconds = new Date(accessibleAt || new Date()).valueOf(); + if (isNaN(accessibleAtInMSeconds)) { + throw new Error(SignerExceptionMessages.ACCESSIBLE_DATE_INVALID); + } + return Math.floor(accessibleAtInMSeconds / 1000); // The API expects seconds. + } +} +exports.URLSigner = URLSigner; +/** + * Custom error type for errors related to getting signed errors and policies. + * + * @private + */ +class SigningError extends Error { + constructor() { + super(...arguments); + this.name = 'SigningError'; + } +} +exports.SigningError = SigningError; + + +/***/ }), + +/***/ 92848: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Storage = exports.RETRYABLE_ERR_FN_DEFAULT = exports.MAX_RETRY_DELAY_DEFAULT = exports.TOTAL_TIMEOUT_DEFAULT = exports.RETRY_DELAY_MULTIPLIER_DEFAULT = exports.MAX_RETRY_DEFAULT = exports.AUTO_RETRY_DEFAULT = exports.PROTOCOL_REGEX = exports.StorageExceptionMessages = exports.ExceptionMessages = exports.IdempotencyStrategy = void 0; +const index_js_1 = __nccwpck_require__(11325); +const paginator_1 = __nccwpck_require__(99469); +const promisify_1 = __nccwpck_require__(60206); +const stream_1 = __nccwpck_require__(2203); +const bucket_js_1 = __nccwpck_require__(82887); +const channel_js_1 = __nccwpck_require__(12658); +const file_js_1 = __nccwpck_require__(69975); +const util_js_1 = __nccwpck_require__(74557); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const hmacKey_js_1 = __nccwpck_require__(45891); +const crc32c_js_1 = __nccwpck_require__(34317); +const google_auth_library_1 = __nccwpck_require__(492); +var IdempotencyStrategy; +(function (IdempotencyStrategy) { + IdempotencyStrategy[IdempotencyStrategy["RetryAlways"] = 0] = "RetryAlways"; + IdempotencyStrategy[IdempotencyStrategy["RetryConditional"] = 1] = "RetryConditional"; + IdempotencyStrategy[IdempotencyStrategy["RetryNever"] = 2] = "RetryNever"; +})(IdempotencyStrategy || (exports.IdempotencyStrategy = IdempotencyStrategy = {})); +var ExceptionMessages; +(function (ExceptionMessages) { + ExceptionMessages["EXPIRATION_DATE_INVALID"] = "The expiration date provided was invalid."; + ExceptionMessages["EXPIRATION_DATE_PAST"] = "An expiration date cannot be in the past."; +})(ExceptionMessages || (exports.ExceptionMessages = ExceptionMessages = {})); +var StorageExceptionMessages; +(function (StorageExceptionMessages) { + StorageExceptionMessages["BUCKET_NAME_REQUIRED"] = "A bucket name is needed to use Cloud Storage."; + StorageExceptionMessages["BUCKET_NAME_REQUIRED_CREATE"] = "A name is required to create a bucket."; + StorageExceptionMessages["HMAC_SERVICE_ACCOUNT"] = "The first argument must be a service account email to create an HMAC key."; + StorageExceptionMessages["HMAC_ACCESS_ID"] = "An access ID is needed to create an HmacKey object."; +})(StorageExceptionMessages || (exports.StorageExceptionMessages = StorageExceptionMessages = {})); +exports.PROTOCOL_REGEX = /^(\w*):\/\//; +/** + * Default behavior: Automatically retry retriable server errors. + * + * @const {boolean} + */ +exports.AUTO_RETRY_DEFAULT = true; +/** + * Default behavior: Only attempt to retry retriable errors 3 times. + * + * @const {number} + */ +exports.MAX_RETRY_DEFAULT = 3; +/** + * Default behavior: Wait twice as long as previous retry before retrying. + * + * @const {number} + */ +exports.RETRY_DELAY_MULTIPLIER_DEFAULT = 2; +/** + * Default behavior: If the operation doesn't succeed after 600 seconds, + * stop retrying. + * + * @const {number} + */ +exports.TOTAL_TIMEOUT_DEFAULT = 600; +/** + * Default behavior: Wait no more than 64 seconds between retries. + * + * @const {number} + */ +exports.MAX_RETRY_DELAY_DEFAULT = 64; +/** + * Default behavior: Retry conditionally idempotent operations if correct preconditions are set. + * + * @const {enum} + * @private + */ +const IDEMPOTENCY_STRATEGY_DEFAULT = IdempotencyStrategy.RetryConditional; +/** + * Returns true if the API request should be retried, given the error that was + * given the first time the request was attempted. + * @const + * @param {error} err - The API error to check if it is appropriate to retry. + * @return {boolean} True if the API request should be retried, false otherwise. + */ +const RETRYABLE_ERR_FN_DEFAULT = function (err) { + var _a; + const isConnectionProblem = (reason) => { + return (reason.includes('eai_again') || // DNS lookup error + reason === 'econnreset' || + reason === 'unexpected connection closure' || + reason === 'epipe' || + reason === 'socket connection timeout'); + }; + if (err) { + if ([408, 429, 500, 502, 503, 504].indexOf(err.code) !== -1) { + return true; + } + if (typeof err.code === 'string') { + if (['408', '429', '500', '502', '503', '504'].indexOf(err.code) !== -1) { + return true; + } + const reason = err.code.toLowerCase(); + if (isConnectionProblem(reason)) { + return true; + } + } + if (err.errors) { + for (const e of err.errors) { + const reason = (_a = e === null || e === void 0 ? void 0 : e.reason) === null || _a === void 0 ? void 0 : _a.toString().toLowerCase(); + if (reason && isConnectionProblem(reason)) { + return true; + } + } + } + } + return false; +}; +exports.RETRYABLE_ERR_FN_DEFAULT = RETRYABLE_ERR_FN_DEFAULT; +/*! Developer Documentation + * + * Invoke this method to create a new Storage object bound with pre-determined + * configuration options. For each object that can be created (e.g., a bucket), + * there is an equivalent static and instance method. While they are classes, + * they can be instantiated without use of the `new` keyword. + */ +/** + * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share objects with other + * users and allow other users to access your buckets and objects. + * + * This object provides constants to refer to the three permission levels that + * can be granted to an entity: + * + * - `gcs.acl.OWNER_ROLE` - ("OWNER") + * - `gcs.acl.READER_ROLE` - ("READER") + * - `gcs.acl.WRITER_ROLE` - ("WRITER") + * + * See {@link https://cloud.google.com/storage/docs/access-control/lists| About Access Control Lists} + * + * @name Storage#acl + * @type {object} + * @property {string} OWNER_ROLE + * @property {string} READER_ROLE + * @property {string} WRITER_ROLE + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const albums = storage.bucket('albums'); + * + * //- + * // Make all of the files currently in a bucket publicly readable. + * //- + * const options = { + * entity: 'allUsers', + * role: storage.acl.READER_ROLE + * }; + * + * albums.acl.add(options, function(err, aclObject) {}); + * + * //- + * // Make any new objects added to a bucket publicly readable. + * //- + * albums.acl.default.add(options, function(err, aclObject) {}); + * + * //- + * // Grant a user ownership permissions to a bucket. + * //- + * albums.acl.add({ + * entity: 'user-useremail@example.com', + * role: storage.acl.OWNER_ROLE + * }, function(err, aclObject) {}); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * albums.acl.add(options).then(function(data) { + * const aclObject = data[0]; + * const apiResponse = data[1]; + * }); + * ``` + */ +/** + * Get {@link Bucket} objects for all of the buckets in your project as + * a readable object stream. + * + * @method Storage#getBucketsStream + * @param {GetBucketsRequest} [query] Query object for listing buckets. + * @returns {ReadableStream} A readable stream that emits {@link Bucket} + * instances. + * + * @example + * ``` + * storage.getBucketsStream() + * .on('error', console.error) + * .on('data', function(bucket) { + * // bucket is a Bucket object. + * }) + * .on('end', function() { + * // All buckets retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * storage.getBucketsStream() + * .on('data', function(bucket) { + * this.end(); + * }); + * ``` + */ +/** + * Get {@link HmacKey} objects for all of the HMAC keys in the project in a + * readable object stream. + * + * @method Storage#getHmacKeysStream + * @param {GetHmacKeysOptions} [options] Configuration options. + * @returns {ReadableStream} A readable stream that emits {@link HmacKey} + * instances. + * + * @example + * ``` + * storage.getHmacKeysStream() + * .on('error', console.error) + * .on('data', function(hmacKey) { + * // hmacKey is an HmacKey object. + * }) + * .on('end', function() { + * // All HmacKey retrieved. + * }); + * + * //- + * // If you anticipate many results, you can end a stream early to prevent + * // unnecessary processing and API requests. + * //- + * storage.getHmacKeysStream() + * .on('data', function(bucket) { + * this.end(); + * }); + * ``` + */ +/** + *

ACLs

+ * Cloud Storage uses access control lists (ACLs) to manage object and + * bucket access. ACLs are the mechanism you use to share files with other users + * and allow other users to access your buckets and files. + * + * To learn more about ACLs, read this overview on + * {@link https://cloud.google.com/storage/docs/access-control| Access Control}. + * + * See {@link https://cloud.google.com/storage/docs/overview| Cloud Storage overview} + * See {@link https://cloud.google.com/storage/docs/access-control| Access Control} + * + * @class + */ +class Storage extends index_js_1.Service { + getBucketsStream() { + // placeholder body, overwritten in constructor + return new stream_1.Readable(); + } + getHmacKeysStream() { + // placeholder body, overwritten in constructor + return new stream_1.Readable(); + } + /** + * @callback Crc32cGeneratorToStringCallback + * A method returning the CRC32C as a base64-encoded string. + * + * @returns {string} + * + * @example + * Hashing the string 'data' should return 'rth90Q==' + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.toString(); // 'rth90Q==' + * ``` + **/ + /** + * @callback Crc32cGeneratorValidateCallback + * A method validating a base64-encoded CRC32C string. + * + * @param {string} [value] base64-encoded CRC32C string to validate + * @returns {boolean} + * + * @example + * Should return `true` if the value matches, `false` otherwise + * + * ```js + * const buffer = Buffer.from('data'); + * crc32c.update(buffer); + * crc32c.validate('DkjKuA=='); // false + * crc32c.validate('rth90Q=='); // true + * ``` + **/ + /** + * @callback Crc32cGeneratorUpdateCallback + * A method for passing `Buffer`s for CRC32C generation. + * + * @param {Buffer} [data] data to update CRC32C value with + * @returns {undefined} + * + * @example + * Hashing buffers from 'some ' and 'text\n' + * + * ```js + * const buffer1 = Buffer.from('some '); + * crc32c.update(buffer1); + * + * const buffer2 = Buffer.from('text\n'); + * crc32c.update(buffer2); + * + * crc32c.toString(); // 'DkjKuA==' + * ``` + **/ + /** + * @typedef {object} CRC32CValidator + * @property {Crc32cGeneratorToStringCallback} + * @property {Crc32cGeneratorValidateCallback} + * @property {Crc32cGeneratorUpdateCallback} + */ + /** + * @callback Crc32cGeneratorCallback + * @returns {CRC32CValidator} + */ + /** + * @typedef {object} StorageOptions + * @property {string} [projectId] The project ID from the Google Developer's + * Console, e.g. 'grape-spaceship-123'. We will also check the environment + * variable `GCLOUD_PROJECT` for your project ID. If your app is running + * in an environment which supports {@link + * https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application + * Application Default Credentials}, your project ID will be detected + * automatically. + * @property {string} [keyFilename] Full path to the a .json, .pem, or .p12 key + * downloaded from the Google Developers Console. If you provide a path to + * a JSON file, the `projectId` option above is not necessary. NOTE: .pem and + * .p12 require you to specify the `email` option as well. + * @property {string} [email] Account email address. Required when using a .pem + * or .p12 keyFilename. + * @property {object} [credentials] Credentials object. + * @property {string} [credentials.client_email] + * @property {string} [credentials.private_key] + * @property {object} [retryOptions] Options for customizing retries. Retriable server errors + * will be retried with exponential delay between them dictated by the formula + * max(maxRetryDelay, retryDelayMultiplier*retryNumber) until maxRetries or totalTimeout + * has been reached. Retries will only happen if autoRetry is set to true. + * @property {boolean} [retryOptions.autoRetry=true] Automatically retry requests if the + * response is related to rate limits or certain intermittent server + * errors. We will exponentially backoff subsequent requests by default. + * @property {number} [retryOptions.retryDelayMultiplier = 2] the multiplier by which to + * increase the delay time between the completion of failed requests, and the + * initiation of the subsequent retrying request. + * @property {number} [retryOptions.totalTimeout = 600] The total time, starting from + * when the initial request is sent, after which an error will + * be returned, regardless of the retrying attempts made meanwhile. + * @property {number} [retryOptions.maxRetryDelay = 64] The maximum delay time between requests. + * When this value is reached, ``retryDelayMultiplier`` will no longer be used to + * increase delay time. + * @property {number} [retryOptions.maxRetries=3] Maximum number of automatic retries + * attempted before returning the error. + * @property {function} [retryOptions.retryableErrorFn] Function that returns true if a given + * error should be retried and false otherwise. + * @property {enum} [retryOptions.idempotencyStrategy=IdempotencyStrategy.RetryConditional] Enumeration + * controls how conditionally idempotent operations are retried. Possible values are: RetryAlways - + * will respect other retry settings and attempt to retry conditionally idempotent operations. RetryConditional - + * will retry conditionally idempotent operations if the correct preconditions are set. RetryNever - never + * retry a conditionally idempotent operation. + * @property {string} [userAgent] The value to be prepended to the User-Agent + * header in API requests. + * @property {object} [authClient] `AuthClient` or `GoogleAuth` client to reuse instead of creating a new one. + * @property {number} [timeout] The amount of time in milliseconds to wait per http request before timing out. + * @property {object[]} [interceptors_] Array of custom request interceptors to be returned in the order they were assigned. + * @property {string} [apiEndpoint = storage.google.com] The API endpoint of the service used to make requests. + * @property {boolean} [useAuthWithCustomEndpoint = false] Controls whether or not to use authentication when using a custom endpoint. + * @property {Crc32cGeneratorCallback} [callback] A function that generates a CRC32C Validator. Defaults to {@link CRC32C} + */ + /** + * Constructs the Storage client. + * + * @example + * Create a client that uses Application Default Credentials + * (ADC) + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * ``` + * + * @example + * Create a client with explicit credentials + * ``` + * const storage = new Storage({ + * projectId: 'your-project-id', + * keyFilename: '/path/to/keyfile.json' + * }); + * ``` + * + * @example + * Create a client with credentials passed + * by value as a JavaScript object + * ``` + * const storage = new Storage({ + * projectId: 'your-project-id', + * credentials: { + * type: 'service_account', + * project_id: 'xxxxxxx', + * private_key_id: 'xxxx', + * private_key:'-----BEGIN PRIVATE KEY-----xxxxxxx\n-----END PRIVATE KEY-----\n', + * client_email: 'xxxx', + * client_id: 'xxx', + * auth_uri: 'https://accounts.google.com/o/oauth2/auth', + * token_uri: 'https://oauth2.googleapis.com/token', + * auth_provider_x509_cert_url: 'https://www.googleapis.com/oauth2/v1/certs', + * client_x509_cert_url: 'xxx', + * } + * }); + * ``` + * + * @example + * Create a client with credentials passed + * by loading a JSON file directly from disk + * ``` + * const storage = new Storage({ + * projectId: 'your-project-id', + * credentials: require('/path/to-keyfile.json') + * }); + * ``` + * + * @example + * Create a client with an `AuthClient` (e.g. `DownscopedClient`) + * ``` + * const {DownscopedClient} = require('google-auth-library'); + * const authClient = new DownscopedClient({...}); + * + * const storage = new Storage({authClient}); + * ``` + * + * Additional samples: + * - https://github.com/googleapis/google-auth-library-nodejs#sample-usage-1 + * - https://github.com/googleapis/google-auth-library-nodejs/blob/main/samples/downscopedclient.js + * + * @param {StorageOptions} [options] Configuration options. + */ + constructor(options = {}) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; + const universe = options.universeDomain || google_auth_library_1.DEFAULT_UNIVERSE; + let apiEndpoint = `https://storage.${universe}`; + let customEndpoint = false; + // Note: EMULATOR_HOST is an experimental configuration variable. Use apiEndpoint instead. + const EMULATOR_HOST = process.env.STORAGE_EMULATOR_HOST; + if (typeof EMULATOR_HOST === 'string') { + apiEndpoint = Storage.sanitizeEndpoint(EMULATOR_HOST); + customEndpoint = true; + } + if (options.apiEndpoint && options.apiEndpoint !== apiEndpoint) { + apiEndpoint = Storage.sanitizeEndpoint(options.apiEndpoint); + customEndpoint = true; + } + options = Object.assign({}, options, { apiEndpoint }); + // Note: EMULATOR_HOST is an experimental configuration variable. Use apiEndpoint instead. + const baseUrl = EMULATOR_HOST || `${options.apiEndpoint}/storage/v1`; + const config = { + apiEndpoint: options.apiEndpoint, + retryOptions: { + autoRetry: ((_a = options.retryOptions) === null || _a === void 0 ? void 0 : _a.autoRetry) !== undefined + ? (_b = options.retryOptions) === null || _b === void 0 ? void 0 : _b.autoRetry + : exports.AUTO_RETRY_DEFAULT, + maxRetries: ((_c = options.retryOptions) === null || _c === void 0 ? void 0 : _c.maxRetries) + ? (_d = options.retryOptions) === null || _d === void 0 ? void 0 : _d.maxRetries + : exports.MAX_RETRY_DEFAULT, + retryDelayMultiplier: ((_e = options.retryOptions) === null || _e === void 0 ? void 0 : _e.retryDelayMultiplier) + ? (_f = options.retryOptions) === null || _f === void 0 ? void 0 : _f.retryDelayMultiplier + : exports.RETRY_DELAY_MULTIPLIER_DEFAULT, + totalTimeout: ((_g = options.retryOptions) === null || _g === void 0 ? void 0 : _g.totalTimeout) + ? (_h = options.retryOptions) === null || _h === void 0 ? void 0 : _h.totalTimeout + : exports.TOTAL_TIMEOUT_DEFAULT, + maxRetryDelay: ((_j = options.retryOptions) === null || _j === void 0 ? void 0 : _j.maxRetryDelay) + ? (_k = options.retryOptions) === null || _k === void 0 ? void 0 : _k.maxRetryDelay + : exports.MAX_RETRY_DELAY_DEFAULT, + retryableErrorFn: ((_l = options.retryOptions) === null || _l === void 0 ? void 0 : _l.retryableErrorFn) + ? (_m = options.retryOptions) === null || _m === void 0 ? void 0 : _m.retryableErrorFn + : exports.RETRYABLE_ERR_FN_DEFAULT, + idempotencyStrategy: ((_o = options.retryOptions) === null || _o === void 0 ? void 0 : _o.idempotencyStrategy) !== undefined + ? (_p = options.retryOptions) === null || _p === void 0 ? void 0 : _p.idempotencyStrategy + : IDEMPOTENCY_STRATEGY_DEFAULT, + }, + baseUrl, + customEndpoint, + useAuthWithCustomEndpoint: options === null || options === void 0 ? void 0 : options.useAuthWithCustomEndpoint, + projectIdRequired: false, + scopes: [ + 'https://www.googleapis.com/auth/iam', + 'https://www.googleapis.com/auth/cloud-platform', + 'https://www.googleapis.com/auth/devstorage.full_control', + ], + packageJson: (0, package_json_helper_cjs_1.getPackageJSON)(), + }; + super(config, options); + /** + * Reference to {@link Storage.acl}. + * + * @name Storage#acl + * @see Storage.acl + */ + this.acl = Storage.acl; + this.crc32cGenerator = + options.crc32cGenerator || crc32c_js_1.CRC32C_DEFAULT_VALIDATOR_GENERATOR; + this.retryOptions = config.retryOptions; + this.getBucketsStream = paginator_1.paginator.streamify('getBuckets'); + this.getHmacKeysStream = paginator_1.paginator.streamify('getHmacKeys'); + } + static sanitizeEndpoint(url) { + if (!exports.PROTOCOL_REGEX.test(url)) { + url = `https://${url}`; + } + return url.replace(/\/+$/, ''); // Remove trailing slashes + } + /** + * Get a reference to a Cloud Storage bucket. + * + * @param {string} name Name of the bucket. + * @param {object} [options] Configuration object. + * @param {string} [options.kmsKeyName] A Cloud KMS key that will be used to + * encrypt objects inserted into this bucket, if no encryption method is + * specified. + * @param {string} [options.userProject] User project to be billed for all + * requests made from this Bucket object. + * @returns {Bucket} + * @see Bucket + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const albums = storage.bucket('albums'); + * const photos = storage.bucket('photos'); + * ``` + */ + bucket(name, options) { + if (!name) { + throw new Error(StorageExceptionMessages.BUCKET_NAME_REQUIRED); + } + return new bucket_js_1.Bucket(this, name, options); + } + /** + * Reference a channel to receive notifications about changes to your bucket. + * + * @param {string} id The ID of the channel. + * @param {string} resourceId The resource ID of the channel. + * @returns {Channel} + * @see Channel + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const channel = storage.channel('id', 'resource-id'); + * ``` + */ + channel(id, resourceId) { + return new channel_js_1.Channel(this, id, resourceId); + } + /** + * @typedef {array} CreateBucketResponse + * @property {Bucket} 0 The new {@link Bucket}. + * @property {object} 1 The full API response. + */ + /** + * @callback CreateBucketCallback + * @param {?Error} err Request error, if any. + * @param {Bucket} bucket The new {@link Bucket}. + * @param {object} apiResponse The full API response. + */ + /** + * Metadata to set for the bucket. + * + * @typedef {object} CreateBucketRequest + * @property {boolean} [archive=false] Specify the storage class as Archive. + * @property {object} [autoclass.enabled=false] Specify whether Autoclass is + * enabled for the bucket. + * @property {object} [autoclass.terminalStorageClass='NEARLINE'] The storage class that objects in an Autoclass bucket eventually transition to if + * they are not read for a certain length of time. Valid values are NEARLINE and ARCHIVE. + * @property {boolean} [coldline=false] Specify the storage class as Coldline. + * @property {Cors[]} [cors=[]] Specify the CORS configuration to use. + * @property {CustomPlacementConfig} [customPlacementConfig={}] Specify the bucket's regions for dual-region buckets. + * For more information, see {@link https://cloud.google.com/storage/docs/locations| Bucket Locations}. + * @property {boolean} [dra=false] Specify the storage class as Durable Reduced + * Availability. + * @property {boolean} [enableObjectRetention=false] Specifiy whether or not object retention should be enabled on this bucket. + * @property {object} [hierarchicalNamespace.enabled=false] Specify whether or not to enable hierarchical namespace on this bucket. + * @property {string} [location] Specify the bucket's location. If specifying + * a dual-region, the `customPlacementConfig` property should be set in conjunction. + * For more information, see {@link https://cloud.google.com/storage/docs/locations| Bucket Locations}. + * @property {boolean} [multiRegional=false] Specify the storage class as + * Multi-Regional. + * @property {boolean} [nearline=false] Specify the storage class as Nearline. + * @property {boolean} [regional=false] Specify the storage class as Regional. + * @property {boolean} [requesterPays=false] Force the use of the User Project metadata field to assign operational + * costs when an operation is made on a Bucket and its objects. + * @property {string} [rpo] For dual-region buckets, controls whether turbo + * replication is enabled (`ASYNC_TURBO`) or disabled (`DEFAULT`). + * @property {boolean} [standard=true] Specify the storage class as Standard. + * @property {string} [storageClass] The new storage class. (`standard`, + * `nearline`, `coldline`, or `archive`). + * **Note:** The storage classes `multi_regional`, `regional`, and + * `durable_reduced_availability` are now legacy and will be deprecated in + * the future. + * @property {Versioning} [versioning=undefined] Specify the versioning status. + * @property {string} [userProject] The ID of the project which will be billed + * for the request. + */ + /** + * Create a bucket. + * + * Cloud Storage uses a flat namespace, so you can't create a bucket with + * a name that is already in use. For more information, see + * {@link https://cloud.google.com/storage/docs/bucketnaming.html#requirements| Bucket Naming Guidelines}. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/insert| Buckets: insert API Documentation} + * See {@link https://cloud.google.com/storage/docs/storage-classes| Storage Classes} + * + * @param {string} name Name of the bucket to create. + * @param {CreateBucketRequest} [metadata] Metadata to set for the bucket. + * @param {CreateBucketCallback} [callback] Callback function. + * @returns {Promise} + * @throws {Error} If a name is not provided. + * @see Bucket#create + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const callback = function(err, bucket, apiResponse) { + * // `bucket` is a Bucket object. + * }; + * + * storage.createBucket('new-bucket', callback); + * + * //- + * // Create a bucket in a specific location and region. See the + * // Official JSON API docs for complete details on the `location` + * option. + * // + * //- + * const metadata = { + * location: 'US-CENTRAL1', + * regional: true + * }; + * + * storage.createBucket('new-bucket', metadata, callback); + * + * //- + * // Create a bucket with a retention policy of 6 months. + * //- + * const metadata = { + * retentionPolicy: { + * retentionPeriod: 15780000 // 6 months in seconds. + * } + * }; + * + * storage.createBucket('new-bucket', metadata, callback); + * + * //- + * // Enable versioning on a new bucket. + * //- + * const metadata = { + * versioning: { + * enabled: true + * } + * }; + * + * storage.createBucket('new-bucket', metadata, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.createBucket('new-bucket').then(function(data) { + * const bucket = data[0]; + * const apiResponse = data[1]; + * }); + * + * ``` + * @example include:samples/buckets.js + * region_tag:storage_create_bucket + * Another example: + */ + createBucket(name, metadataOrCallback, callback) { + if (!name) { + throw new Error(StorageExceptionMessages.BUCKET_NAME_REQUIRED_CREATE); + } + let metadata; + if (!callback) { + callback = metadataOrCallback; + metadata = {}; + } + else { + metadata = metadataOrCallback; + } + const body = { + ...metadata, + name, + }; + const storageClasses = { + archive: 'ARCHIVE', + coldline: 'COLDLINE', + dra: 'DURABLE_REDUCED_AVAILABILITY', + multiRegional: 'MULTI_REGIONAL', + nearline: 'NEARLINE', + regional: 'REGIONAL', + standard: 'STANDARD', + }; + const storageClassKeys = Object.keys(storageClasses); + for (const storageClass of storageClassKeys) { + if (body[storageClass]) { + if (metadata.storageClass && metadata.storageClass !== storageClass) { + throw new Error(`Both \`${storageClass}\` and \`storageClass\` were provided.`); + } + body.storageClass = storageClasses[storageClass]; + delete body[storageClass]; + } + } + if (body.requesterPays) { + body.billing = { + requesterPays: body.requesterPays, + }; + delete body.requesterPays; + } + const query = { + project: this.projectId, + }; + if (body.userProject) { + query.userProject = body.userProject; + delete body.userProject; + } + if (body.enableObjectRetention) { + query.enableObjectRetention = body.enableObjectRetention; + delete body.enableObjectRetention; + } + if (body.predefinedAcl) { + query.predefinedAcl = body.predefinedAcl; + delete body.predefinedAcl; + } + if (body.predefinedDefaultObjectAcl) { + query.predefinedDefaultObjectAcl = body.predefinedDefaultObjectAcl; + delete body.predefinedDefaultObjectAcl; + } + if (body.projection) { + query.projection = body.projection; + delete body.projection; + } + this.request({ + method: 'POST', + uri: '/b', + qs: query, + json: body, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + const bucket = this.bucket(name); + bucket.metadata = resp; + callback(null, bucket, resp); + }); + } + /** + * @typedef {object} CreateHmacKeyOptions + * @property {string} [projectId] The project ID of the project that owns + * the service account of the requested HMAC key. If not provided, + * the project ID used to instantiate the Storage client will be used. + * @property {string} [userProject] This parameter is currently ignored. + */ + /** + * @typedef {object} HmacKeyMetadata + * @property {string} accessId The access id identifies which HMAC key was + * used to sign a request when authenticating with HMAC. + * @property {string} etag Used to perform a read-modify-write of the key. + * @property {string} id The resource name of the HMAC key. + * @property {string} projectId The project ID. + * @property {string} serviceAccountEmail The service account's email this + * HMAC key is created for. + * @property {string} state The state of this HMAC key. One of "ACTIVE", + * "INACTIVE" or "DELETED". + * @property {string} timeCreated The creation time of the HMAC key in + * RFC 3339 format. + * @property {string} [updated] The time this HMAC key was last updated in + * RFC 3339 format. + */ + /** + * @typedef {array} CreateHmacKeyResponse + * @property {HmacKey} 0 The HmacKey instance created from API response. + * @property {string} 1 The HMAC key's secret used to access the XML API. + * @property {object} 3 The raw API response. + */ + /** + * @callback CreateHmacKeyCallback Callback function. + * @param {?Error} err Request error, if any. + * @param {HmacKey} hmacKey The HmacKey instance created from API response. + * @param {string} secret The HMAC key's secret used to access the XML API. + * @param {object} apiResponse The raw API response. + */ + /** + * Create an HMAC key associated with an service account to authenticate + * requests to the Cloud Storage XML API. + * + * See {@link https://cloud.google.com/storage/docs/authentication/hmackeys| HMAC keys documentation} + * + * @param {string} serviceAccountEmail The service account's email address + * with which the HMAC key is created for. + * @param {CreateHmacKeyCallback} [callback] Callback function. + * @return {Promise} + * + * @example + * ``` + * const {Storage} = require('google-cloud/storage'); + * const storage = new Storage(); + * + * // Replace with your service account's email address + * const serviceAccountEmail = + * 'my-service-account@appspot.gserviceaccount.com'; + * + * storage.createHmacKey(serviceAccountEmail, function(err, hmacKey, secret) { + * if (!err) { + * // Securely store the secret for use with the XML API. + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.createHmacKey(serviceAccountEmail) + * .then((response) => { + * const hmacKey = response[0]; + * const secret = response[1]; + * // Securely store the secret for use with the XML API. + * }); + * ``` + */ + createHmacKey(serviceAccountEmail, optionsOrCb, cb) { + if (typeof serviceAccountEmail !== 'string') { + throw new Error(StorageExceptionMessages.HMAC_SERVICE_ACCOUNT); + } + const { options, callback } = (0, util_js_1.normalize)(optionsOrCb, cb); + const query = Object.assign({}, options, { serviceAccountEmail }); + const projectId = query.projectId || this.projectId; + delete query.projectId; + this.request({ + method: 'POST', + uri: `/projects/${projectId}/hmacKeys`, + qs: query, + maxRetries: 0, //explicitly set this value since this is a non-idempotent function + }, (err, resp) => { + if (err) { + callback(err, null, null, resp); + return; + } + const metadata = resp.metadata; + const hmacKey = this.hmacKey(metadata.accessId, { + projectId: metadata.projectId, + }); + hmacKey.metadata = resp.metadata; + callback(null, hmacKey, resp.secret, resp); + }); + } + /** + * Query object for listing buckets. + * + * @typedef {object} GetBucketsRequest + * @property {boolean} [autoPaginate=true] Have pagination handled + * automatically. + * @property {number} [maxApiCalls] Maximum number of API calls to make. + * @property {number} [maxResults] Maximum number of items plus prefixes to + * return per call. + * Note: By default will handle pagination automatically + * if more than 1 page worth of results are requested per call. + * When `autoPaginate` is set to `false` the smaller of `maxResults` + * or 1 page of results will be returned per call. + * @property {string} [pageToken] A previously-returned page token + * representing part of the larger set of results to view. + * @property {string} [userProject] The ID of the project which will be billed + * for the request. + * @param {boolean} [softDeleted] If true, returns the soft-deleted object. + * Object `generation` is required if `softDeleted` is set to True. + */ + /** + * @typedef {array} GetBucketsResponse + * @property {Bucket[]} 0 Array of {@link Bucket} instances. + * @property {object} 1 nextQuery A query object to receive more results. + * @property {object} 2 The full API response. + */ + /** + * @callback GetBucketsCallback + * @param {?Error} err Request error, if any. + * @param {Bucket[]} buckets Array of {@link Bucket} instances. + * @param {object} nextQuery A query object to receive more results. + * @param {object} apiResponse The full API response. + */ + /** + * Get Bucket objects for all of the buckets in your project. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/buckets/list| Buckets: list API Documentation} + * + * @param {GetBucketsRequest} [query] Query object for listing buckets. + * @param {GetBucketsCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * storage.getBuckets(function(err, buckets) { + * if (!err) { + * // buckets is an array of Bucket objects. + * } + * }); + * + * //- + * // To control how many API requests are made and page through the results + * // manually, set `autoPaginate` to `false`. + * //- + * const callback = function(err, buckets, nextQuery, apiResponse) { + * if (nextQuery) { + * // More results exist. + * storage.getBuckets(nextQuery, callback); + * } + * + * // The `metadata` property is populated for you with the metadata at the + * // time of fetching. + * buckets[0].metadata; + * + * // However, in cases where you are concerned the metadata could have + * // changed, use the `getMetadata` method. + * buckets[0].getMetadata(function(err, metadata, apiResponse) {}); + * }; + * + * storage.getBuckets({ + * autoPaginate: false + * }, callback); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.getBuckets().then(function(data) { + * const buckets = data[0]; + * }); + * + * ``` + * @example include:samples/buckets.js + * region_tag:storage_list_buckets + * Another example: + */ + getBuckets(optionsOrCallback, cb) { + const { options, callback } = (0, util_js_1.normalize)(optionsOrCallback, cb); + options.project = options.project || this.projectId; + this.request({ + uri: '/b', + qs: options, + }, (err, resp) => { + if (err) { + callback(err, null, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const buckets = itemsArray.map((bucket) => { + const bucketInstance = this.bucket(bucket.id); + bucketInstance.metadata = bucket; + return bucketInstance; + }); + const nextQuery = resp.nextPageToken + ? Object.assign({}, options, { pageToken: resp.nextPageToken }) + : null; + callback(null, buckets, nextQuery, resp); + }); + } + getHmacKeys(optionsOrCb, cb) { + const { options, callback } = (0, util_js_1.normalize)(optionsOrCb, cb); + const query = Object.assign({}, options); + const projectId = query.projectId || this.projectId; + delete query.projectId; + this.request({ + uri: `/projects/${projectId}/hmacKeys`, + qs: query, + }, (err, resp) => { + if (err) { + callback(err, null, null, resp); + return; + } + const itemsArray = resp.items ? resp.items : []; + const hmacKeys = itemsArray.map((hmacKey) => { + const hmacKeyInstance = this.hmacKey(hmacKey.accessId, { + projectId: hmacKey.projectId, + }); + hmacKeyInstance.metadata = hmacKey; + return hmacKeyInstance; + }); + const nextQuery = resp.nextPageToken + ? Object.assign({}, options, { pageToken: resp.nextPageToken }) + : null; + callback(null, hmacKeys, nextQuery, resp); + }); + } + /** + * @typedef {array} GetServiceAccountResponse + * @property {object} 0 The service account resource. + * @property {object} 1 The full + * {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| API response}. + */ + /** + * @callback GetServiceAccountCallback + * @param {?Error} err Request error, if any. + * @param {object} serviceAccount The serviceAccount resource. + * @param {string} serviceAccount.emailAddress The service account email + * address. + * @param {object} apiResponse The full + * {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| API response}. + */ + /** + * Get the email address of this project's Google Cloud Storage service + * account. + * + * See {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount/get| Projects.serviceAccount: get API Documentation} + * See {@link https://cloud.google.com/storage/docs/json_api/v1/projects/serviceAccount#resource| Projects.serviceAccount Resource} + * + * @param {object} [options] Configuration object. + * @param {string} [options.userProject] User project to be billed for this + * request. + * @param {GetServiceAccountCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * + * storage.getServiceAccount(function(err, serviceAccount, apiResponse) { + * if (!err) { + * const serviceAccountEmail = serviceAccount.emailAddress; + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * storage.getServiceAccount().then(function(data) { + * const serviceAccountEmail = data[0].emailAddress; + * const apiResponse = data[1]; + * }); + * ``` + */ + getServiceAccount(optionsOrCallback, cb) { + const { options, callback } = (0, util_js_1.normalize)(optionsOrCallback, cb); + this.request({ + uri: `/projects/${this.projectId}/serviceAccount`, + qs: options, + }, (err, resp) => { + if (err) { + callback(err, null, resp); + return; + } + const camelCaseResponse = {}; + for (const prop in resp) { + // eslint-disable-next-line no-prototype-builtins + if (resp.hasOwnProperty(prop)) { + const camelCaseProp = prop.replace(/_(\w)/g, (_, match) => match.toUpperCase()); + camelCaseResponse[camelCaseProp] = resp[prop]; + } + } + callback(null, camelCaseResponse, resp); + }); + } + /** + * Get a reference to an HmacKey object. + * Note: this does not fetch the HMAC key's metadata. Use HmacKey#get() to + * retrieve and populate the metadata. + * + * To get a reference to an HMAC key that's not created for a service + * account in the same project used to instantiate the Storage client, + * supply the project's ID as `projectId` in the `options` argument. + * + * @param {string} accessId The HMAC key's access ID. + * @param {HmacKeyOptions} options HmacKey constructor options. + * @returns {HmacKey} + * @see HmacKey + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const hmacKey = storage.hmacKey('ACCESS_ID'); + * ``` + */ + hmacKey(accessId, options) { + if (!accessId) { + throw new Error(StorageExceptionMessages.HMAC_ACCESS_ID); + } + return new hmacKey_js_1.HmacKey(this, accessId, options); + } +} +exports.Storage = Storage; +/** + * {@link Bucket} class. + * + * @name Storage.Bucket + * @see Bucket + * @type {Constructor} + */ +Storage.Bucket = bucket_js_1.Bucket; +/** + * {@link Channel} class. + * + * @name Storage.Channel + * @see Channel + * @type {Constructor} + */ +Storage.Channel = channel_js_1.Channel; +/** + * {@link File} class. + * + * @name Storage.File + * @see File + * @type {Constructor} + */ +Storage.File = file_js_1.File; +/** + * {@link HmacKey} class. + * + * @name Storage.HmacKey + * @see HmacKey + * @type {Constructor} + */ +Storage.HmacKey = hmacKey_js_1.HmacKey; +Storage.acl = { + OWNER_ROLE: 'OWNER', + READER_ROLE: 'READER', + WRITER_ROLE: 'WRITER', +}; +/*! Developer Documentation + * + * These methods can be auto-paginated. + */ +paginator_1.paginator.extend(Storage, ['getBuckets', 'getHmacKeys']); +/*! Developer Documentation + * + * All async methods (except for streams) will return a Promise in the event + * that a callback is omitted. + */ +(0, promisify_1.promisifyAll)(Storage, { + exclude: ['bucket', 'channel', 'hmacKey'], +}); + + +/***/ }), + +/***/ 30004: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/*! + * Copyright 2022 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _XMLMultiPartUploadHelper_instances, _XMLMultiPartUploadHelper_setGoogApiClientHeaders, _XMLMultiPartUploadHelper_handleErrorResponse; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.TransferManager = exports.MultiPartUploadError = void 0; +const file_js_1 = __nccwpck_require__(69975); +const p_limit_1 = __importDefault(__nccwpck_require__(58890)); +const path = __importStar(__nccwpck_require__(16928)); +const fs_1 = __nccwpck_require__(79896); +const crc32c_js_1 = __nccwpck_require__(34317); +const google_auth_library_1 = __nccwpck_require__(492); +const fast_xml_parser_1 = __nccwpck_require__(1290); +const async_retry_1 = __importDefault(__nccwpck_require__(45195)); +const crypto_1 = __nccwpck_require__(76982); +const util_js_1 = __nccwpck_require__(37325); +const util_js_2 = __nccwpck_require__(74557); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +const packageJson = (0, package_json_helper_cjs_1.getPackageJSON)(); +/** + * Default number of concurrently executing promises to use when calling uploadManyFiles. + * + */ +const DEFAULT_PARALLEL_UPLOAD_LIMIT = 5; +/** + * Default number of concurrently executing promises to use when calling downloadManyFiles. + * + */ +const DEFAULT_PARALLEL_DOWNLOAD_LIMIT = 5; +/** + * Default number of concurrently executing promises to use when calling downloadFileInChunks. + * + */ +const DEFAULT_PARALLEL_CHUNKED_DOWNLOAD_LIMIT = 5; +/** + * The minimum size threshold in bytes at which to apply a chunked download strategy when calling downloadFileInChunks. + * + */ +const DOWNLOAD_IN_CHUNKS_FILE_SIZE_THRESHOLD = 32 * 1024 * 1024; +/** + * The chunk size in bytes to use when calling downloadFileInChunks. + * + */ +const DOWNLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE = 32 * 1024 * 1024; +/** + * The chunk size in bytes to use when calling uploadFileInChunks. + * + */ +const UPLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE = 32 * 1024 * 1024; +/** + * Default number of concurrently executing promises to use when calling uploadFileInChunks. + * + */ +const DEFAULT_PARALLEL_CHUNKED_UPLOAD_LIMIT = 5; +const EMPTY_REGEX = '(?:)'; +/** + * The `gccl-gcs-cmd` value for the `X-Goog-API-Client` header. + * Example: `gccl-gcs-cmd/tm.upload_many` + * + * @see {@link GCCL_GCS_CMD}. + * @see {@link GCCL_GCS_CMD_KEY}. + */ +const GCCL_GCS_CMD_FEATURE = { + UPLOAD_MANY: 'tm.upload_many', + DOWNLOAD_MANY: 'tm.download_many', + UPLOAD_SHARDED: 'tm.upload_sharded', + DOWNLOAD_SHARDED: 'tm.download_sharded', +}; +const defaultMultiPartGenerator = (bucket, fileName, uploadId, partsMap) => { + return new XMLMultiPartUploadHelper(bucket, fileName, uploadId, partsMap); +}; +class MultiPartUploadError extends Error { + constructor(message, uploadId, partsMap) { + super(message); + this.uploadId = uploadId; + this.partsMap = partsMap; + } +} +exports.MultiPartUploadError = MultiPartUploadError; +/** + * Class representing an implementation of MPU in the XML API. This class is not meant for public usage. + * + * @private + * + */ +class XMLMultiPartUploadHelper { + constructor(bucket, fileName, uploadId, partsMap) { + _XMLMultiPartUploadHelper_instances.add(this); + this.authClient = bucket.storage.authClient || new google_auth_library_1.GoogleAuth(); + this.uploadId = uploadId || ''; + this.bucket = bucket; + this.fileName = fileName; + this.baseUrl = `https://${bucket.name}.${new URL(this.bucket.storage.apiEndpoint).hostname}/${fileName}`; + this.xmlBuilder = new fast_xml_parser_1.XMLBuilder({ arrayNodeName: 'Part' }); + this.xmlParser = new fast_xml_parser_1.XMLParser(); + this.partsMap = partsMap || new Map(); + this.retryOptions = { + retries: this.bucket.storage.retryOptions.maxRetries, + factor: this.bucket.storage.retryOptions.retryDelayMultiplier, + maxTimeout: this.bucket.storage.retryOptions.maxRetryDelay * 1000, + maxRetryTime: this.bucket.storage.retryOptions.totalTimeout * 1000, + }; + } + /** + * Initiates a multipart upload (MPU) to the XML API and stores the resultant upload id. + * + * @returns {Promise} + */ + async initiateUpload(headers = {}) { + const url = `${this.baseUrl}?uploads`; + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + headers: __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_setGoogApiClientHeaders).call(this, headers), + method: 'POST', + url, + }); + if (res.data && res.data.error) { + throw res.data.error; + } + const parsedXML = this.xmlParser.parse(res.data); + this.uploadId = parsedXML.InitiateMultipartUploadResult.UploadId; + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + } + }, this.retryOptions); + } + /** + * Uploads the provided chunk of data to the XML API using the previously created upload id. + * + * @param {number} partNumber the sequence number of this chunk. + * @param {Buffer} chunk the chunk of data to be uploaded. + * @param {string | false} validation whether or not to include the md5 hash in the headers to cause the server + * to validate the chunk was not corrupted. + * @returns {Promise} + */ + async uploadPart(partNumber, chunk, validation) { + const url = `${this.baseUrl}?partNumber=${partNumber}&uploadId=${this.uploadId}`; + let headers = __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_setGoogApiClientHeaders).call(this); + if (validation === 'md5') { + const hash = (0, crypto_1.createHash)('md5').update(chunk).digest('base64'); + headers = { + 'Content-MD5': hash, + }; + } + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + url, + method: 'PUT', + body: chunk, + headers, + }); + if (res.data && res.data.error) { + throw res.data.error; + } + this.partsMap.set(partNumber, res.headers['etag']); + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + } + }, this.retryOptions); + } + /** + * Sends the final request of the MPU to tell GCS the upload is now complete. + * + * @returns {Promise} + */ + async completeUpload() { + const url = `${this.baseUrl}?uploadId=${this.uploadId}`; + const sortedMap = new Map([...this.partsMap.entries()].sort((a, b) => a[0] - b[0])); + const parts = []; + for (const entry of sortedMap.entries()) { + parts.push({ PartNumber: entry[0], ETag: entry[1] }); + } + const body = `${this.xmlBuilder.build(parts)}`; + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + headers: __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_setGoogApiClientHeaders).call(this), + url, + method: 'POST', + body, + }); + if (res.data && res.data.error) { + throw res.data.error; + } + return res; + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + return; + } + }, this.retryOptions); + } + /** + * Aborts an multipart upload that is in progress. Once aborted, any parts in the process of being uploaded fail, + * and future requests using the upload ID fail. + * + * @returns {Promise} + */ + async abortUpload() { + const url = `${this.baseUrl}?uploadId=${this.uploadId}`; + return (0, async_retry_1.default)(async (bail) => { + try { + const res = await this.authClient.request({ + url, + method: 'DELETE', + }); + if (res.data && res.data.error) { + throw res.data.error; + } + } + catch (e) { + __classPrivateFieldGet(this, _XMLMultiPartUploadHelper_instances, "m", _XMLMultiPartUploadHelper_handleErrorResponse).call(this, e, bail); + return; + } + }, this.retryOptions); + } +} +_XMLMultiPartUploadHelper_instances = new WeakSet(), _XMLMultiPartUploadHelper_setGoogApiClientHeaders = function _XMLMultiPartUploadHelper_setGoogApiClientHeaders(headers = {}) { + let headerFound = false; + let userAgentFound = false; + for (const [key, value] of Object.entries(headers)) { + if (key.toLocaleLowerCase().trim() === 'x-goog-api-client') { + headerFound = true; + // Prepend command feature to value, if not already there + if (!value.includes(GCCL_GCS_CMD_FEATURE.UPLOAD_SHARDED)) { + headers[key] = + `${value} gccl-gcs-cmd/${GCCL_GCS_CMD_FEATURE.UPLOAD_SHARDED}`; + } + } + else if (key.toLocaleLowerCase().trim() === 'user-agent') { + userAgentFound = true; + } + } + // If the header isn't present, add it + if (!headerFound) { + headers['x-goog-api-client'] = `${(0, util_js_2.getRuntimeTrackingString)()} gccl/${packageJson.version} gccl-gcs-cmd/${GCCL_GCS_CMD_FEATURE.UPLOAD_SHARDED}`; + } + // If the User-Agent isn't present, add it + if (!userAgentFound) { + headers['User-Agent'] = (0, util_js_2.getUserAgentString)(); + } + return headers; +}, _XMLMultiPartUploadHelper_handleErrorResponse = function _XMLMultiPartUploadHelper_handleErrorResponse(err, bail) { + if (this.bucket.storage.retryOptions.autoRetry && + this.bucket.storage.retryOptions.retryableErrorFn(err)) { + throw err; + } + else { + bail(err); + } +}; +/** + * Create a TransferManager object to perform parallel transfer operations on a Cloud Storage bucket. + * + * @class + * @hideconstructor + * + * @param {Bucket} bucket A {@link Bucket} instance + * + */ +class TransferManager { + constructor(bucket) { + this.bucket = bucket; + } + /** + * @typedef {object} UploadManyFilesOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when uploading the files. + * @property {Function} [customDestinationBuilder] A fuction that will take the current path of a local file + * and return a string representing a custom path to be used to upload the file to GCS. + * @property {boolean} [skipIfExists] Do not upload the file if it already exists in + * the bucket. This will set the precondition ifGenerationMatch = 0. + * @property {string} [prefix] A prefix to append to all of the uploaded files. + * @property {object} [passthroughOptions] {@link UploadOptions} Options to be passed through + * to each individual upload operation. + * + */ + /** + * Upload multiple files in parallel to the bucket. This is a convenience method + * that utilizes {@link Bucket#upload} to perform the upload. + * + * @param {array | string} [filePathsOrDirectory] An array of fully qualified paths to the files or a directory name. + * If a directory name is provided, the directory will be recursively walked and all files will be added to the upload list. + * to be uploaded to the bucket + * @param {UploadManyFilesOptions} [options] Configuration options. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Upload multiple files in parallel. + * //- + * const response = await transferManager.uploadManyFiles(['/local/path/file1.txt, 'local/path/file2.txt']); + * // Your bucket now contains: + * // - "local/path/file1.txt" (with the contents of '/local/path/file1.txt') + * // - "local/path/file2.txt" (with the contents of '/local/path/file2.txt') + * const response = await transferManager.uploadManyFiles('/local/directory'); + * // Your bucket will now contain all files contained in '/local/directory' maintaining the subdirectory structure. + * ``` + * + */ + async uploadManyFiles(filePathsOrDirectory, options = {}) { + var _a; + if (options.skipIfExists && ((_a = options.passthroughOptions) === null || _a === void 0 ? void 0 : _a.preconditionOpts)) { + options.passthroughOptions.preconditionOpts.ifGenerationMatch = 0; + } + else if (options.skipIfExists && + options.passthroughOptions === undefined) { + options.passthroughOptions = { + preconditionOpts: { + ifGenerationMatch: 0, + }, + }; + } + const limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_UPLOAD_LIMIT); + const promises = []; + let allPaths = []; + if (!Array.isArray(filePathsOrDirectory)) { + for await (const curPath of this.getPathsFromDirectory(filePathsOrDirectory)) { + allPaths.push(curPath); + } + } + else { + allPaths = filePathsOrDirectory; + } + for (const filePath of allPaths) { + const stat = await fs_1.promises.lstat(filePath); + if (stat.isDirectory()) { + continue; + } + const passThroughOptionsCopy = { + ...options.passthroughOptions, + [util_js_1.GCCL_GCS_CMD_KEY]: GCCL_GCS_CMD_FEATURE.UPLOAD_MANY, + }; + passThroughOptionsCopy.destination = options.customDestinationBuilder + ? options.customDestinationBuilder(filePath, options) + : filePath.split(path.sep).join(path.posix.sep); + if (options.prefix) { + passThroughOptionsCopy.destination = path.posix.join(...options.prefix.split(path.sep), passThroughOptionsCopy.destination); + } + promises.push(limit(() => this.bucket.upload(filePath, passThroughOptionsCopy))); + } + return Promise.all(promises); + } + /** + * @typedef {object} DownloadManyFilesOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when downloading the files. + * @property {string} [prefix] A prefix to append to all of the downloaded files. + * @property {string} [stripPrefix] A prefix to remove from all of the downloaded files. + * @property {object} [passthroughOptions] {@link DownloadOptions} Options to be passed through + * to each individual download operation. + * @property {boolean} [skipIfExists] Do not download the file if it already exists in + * the destination. + * + */ + /** + * Download multiple files in parallel to the local filesystem. This is a convenience method + * that utilizes {@link File#download} to perform the download. + * + * @param {array | string} [filesOrFolder] An array of file name strings or file objects to be downloaded. If + * a string is provided this will be treated as a GCS prefix and all files with that prefix will be downloaded. + * @param {DownloadManyFilesOptions} [options] Configuration options. Setting options.prefix or options.stripPrefix + * or options.passthroughOptions.destination will cause the downloaded files to be written to the file system + * instead of being returned as a buffer. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Download multiple files in parallel. + * //- + * const response = await transferManager.downloadManyFiles(['file1.txt', 'file2.txt']); + * // The following files have been downloaded: + * // - "file1.txt" (with the contents from my-bucket.file1.txt) + * // - "file2.txt" (with the contents from my-bucket.file2.txt) + * const response = await transferManager.downloadManyFiles([bucket.File('file1.txt'), bucket.File('file2.txt')]); + * // The following files have been downloaded: + * // - "file1.txt" (with the contents from my-bucket.file1.txt) + * // - "file2.txt" (with the contents from my-bucket.file2.txt) + * const response = await transferManager.downloadManyFiles('test-folder'); + * // All files with GCS prefix of 'test-folder' have been downloaded. + * ``` + * + */ + async downloadManyFiles(filesOrFolder, options = {}) { + const limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_DOWNLOAD_LIMIT); + const promises = []; + let files = []; + if (!Array.isArray(filesOrFolder)) { + const directoryFiles = await this.bucket.getFiles({ + prefix: filesOrFolder, + }); + files = directoryFiles[0]; + } + else { + files = filesOrFolder.map(curFile => { + if (typeof curFile === 'string') { + return this.bucket.file(curFile); + } + return curFile; + }); + } + const stripRegexString = options.stripPrefix + ? `^${options.stripPrefix}` + : EMPTY_REGEX; + const regex = new RegExp(stripRegexString, 'g'); + for (const file of files) { + const passThroughOptionsCopy = { + ...options.passthroughOptions, + [util_js_1.GCCL_GCS_CMD_KEY]: GCCL_GCS_CMD_FEATURE.DOWNLOAD_MANY, + }; + if (options.prefix || passThroughOptionsCopy.destination) { + passThroughOptionsCopy.destination = path.join(options.prefix || '', passThroughOptionsCopy.destination || '', file.name); + } + if (options.stripPrefix) { + passThroughOptionsCopy.destination = file.name.replace(regex, ''); + } + if (options.skipIfExists && + (0, fs_1.existsSync)(passThroughOptionsCopy.destination || '')) { + continue; + } + promises.push(limit(async () => { + const destination = passThroughOptionsCopy.destination; + if (destination && destination.endsWith(path.sep)) { + await fs_1.promises.mkdir(destination, { recursive: true }); + return Promise.resolve([ + Buffer.alloc(0), + ]); + } + return file.download(passThroughOptionsCopy); + })); + } + return Promise.all(promises); + } + /** + * @typedef {object} DownloadFileInChunksOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when downloading the file. + * @property {number} [chunkSizeBytes] The size in bytes of each chunk to be downloaded. + * @property {string | boolean} [validation] Whether or not to perform a CRC32C validation check when download is complete. + * @property {boolean} [noReturnData] Whether or not to return the downloaded data. A `true` value here would be useful for files with a size that will not fit into memory. + * + */ + /** + * Download a large file in chunks utilizing parallel download operations. This is a convenience method + * that utilizes {@link File#download} to perform the download. + * + * @param {File | string} fileOrName {@link File} to download. + * @param {DownloadFileInChunksOptions} [options] Configuration options. + * @returns {Promise} + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Download a large file in chunks utilizing parallel operations. + * //- + * const response = await transferManager.downloadFileInChunks(bucket.file('large-file.txt'); + * // Your local directory now contains: + * // - "large-file.txt" (with the contents from my-bucket.large-file.txt) + * ``` + * + */ + async downloadFileInChunks(fileOrName, options = {}) { + let chunkSize = options.chunkSizeBytes || DOWNLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE; + let limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_CHUNKED_DOWNLOAD_LIMIT); + const noReturnData = Boolean(options.noReturnData); + const promises = []; + const file = typeof fileOrName === 'string' + ? this.bucket.file(fileOrName) + : fileOrName; + const fileInfo = await file.get(); + const size = parseInt(fileInfo[0].metadata.size.toString()); + // If the file size does not meet the threshold download it as a single chunk. + if (size < DOWNLOAD_IN_CHUNKS_FILE_SIZE_THRESHOLD) { + limit = (0, p_limit_1.default)(1); + chunkSize = size; + } + let start = 0; + const filePath = options.destination || path.basename(file.name); + const fileToWrite = await fs_1.promises.open(filePath, 'w'); + while (start < size) { + const chunkStart = start; + let chunkEnd = start + chunkSize - 1; + chunkEnd = chunkEnd > size ? size : chunkEnd; + promises.push(limit(async () => { + const resp = await file.download({ + start: chunkStart, + end: chunkEnd, + [util_js_1.GCCL_GCS_CMD_KEY]: GCCL_GCS_CMD_FEATURE.DOWNLOAD_SHARDED, + }); + const result = await fileToWrite.write(resp[0], 0, resp[0].length, chunkStart); + if (noReturnData) + return; + return result.buffer; + })); + start += chunkSize; + } + let chunks; + try { + chunks = await Promise.all(promises); + } + finally { + await fileToWrite.close(); + } + if (options.validation === 'crc32c' && fileInfo[0].metadata.crc32c) { + const downloadedCrc32C = await crc32c_js_1.CRC32C.fromFile(filePath); + if (!downloadedCrc32C.validate(fileInfo[0].metadata.crc32c)) { + const mismatchError = new file_js_1.RequestError(file_js_1.FileExceptionMessages.DOWNLOAD_MISMATCH); + mismatchError.code = 'CONTENT_DOWNLOAD_MISMATCH'; + throw mismatchError; + } + } + if (noReturnData) + return; + return [Buffer.concat(chunks, size)]; + } + /** + * @typedef {object} UploadFileInChunksOptions + * @property {number} [concurrencyLimit] The number of concurrently executing promises + * to use when uploading the file. + * @property {number} [chunkSizeBytes] The size in bytes of each chunk to be uploaded. + * @property {string} [uploadName] Name of the file when saving to GCS. If ommitted the name is taken from the file path. + * @property {number} [maxQueueSize] The number of chunks to be uploaded to hold in memory concurrently. If not specified + * defaults to the specified concurrency limit. + * @property {string} [uploadId] If specified attempts to resume a previous upload. + * @property {Map} [partsMap] If specified alongside uploadId, attempts to resume a previous upload from the last chunk + * specified in partsMap + * @property {object} [headers] headers to be sent when initiating the multipart upload. + * See {@link https://cloud.google.com/storage/docs/xml-api/post-object-multipart#request_headers| Request Headers: Initiate a Multipart Upload} + * @property {boolean} [autoAbortFailure] boolean to indicate if an in progress upload session will be automatically aborted upon failure. If not set, + * failures will be automatically aborted. + * + */ + /** + * Upload a large file in chunks utilizing parallel upload opertions. If the upload fails, an uploadId and + * map containing all the successfully uploaded parts will be returned to the caller. These arguments can be used to + * resume the upload. + * + * @param {string} [filePath] The path of the file to be uploaded + * @param {UploadFileInChunksOptions} [options] Configuration options. + * @param {MultiPartHelperGenerator} [generator] A function that will return a type that implements the MPU interface. Most users will not need to use this. + * @returns {Promise} If successful a promise resolving to void, otherwise a error containing the message, uploadid, and parts map. + * + * @example + * ``` + * const {Storage} = require('@google-cloud/storage'); + * const storage = new Storage(); + * const bucket = storage.bucket('my-bucket'); + * const transferManager = new TransferManager(bucket); + * + * //- + * // Upload a large file in chunks utilizing parallel operations. + * //- + * const response = await transferManager.uploadFileInChunks('large-file.txt'); + * // Your bucket now contains: + * // - "large-file.txt" + * ``` + * + * + */ + async uploadFileInChunks(filePath, options = {}, generator = defaultMultiPartGenerator) { + const chunkSize = options.chunkSizeBytes || UPLOAD_IN_CHUNKS_DEFAULT_CHUNK_SIZE; + const limit = (0, p_limit_1.default)(options.concurrencyLimit || DEFAULT_PARALLEL_CHUNKED_UPLOAD_LIMIT); + const maxQueueSize = options.maxQueueSize || + options.concurrencyLimit || + DEFAULT_PARALLEL_CHUNKED_UPLOAD_LIMIT; + const fileName = options.uploadName || path.basename(filePath); + const mpuHelper = generator(this.bucket, fileName, options.uploadId, options.partsMap); + let partNumber = 1; + let promises = []; + try { + if (options.uploadId === undefined) { + await mpuHelper.initiateUpload(options.headers); + } + const startOrResumptionByte = mpuHelper.partsMap.size * chunkSize; + const readStream = (0, fs_1.createReadStream)(filePath, { + highWaterMark: chunkSize, + start: startOrResumptionByte, + }); + // p-limit only limits the number of running promises. We do not want to hold an entire + // large file in memory at once so promises acts a queue that will hold only maxQueueSize in memory. + for await (const curChunk of readStream) { + if (promises.length >= maxQueueSize) { + await Promise.all(promises); + promises = []; + } + promises.push(limit(() => mpuHelper.uploadPart(partNumber++, curChunk, options.validation))); + } + await Promise.all(promises); + return await mpuHelper.completeUpload(); + } + catch (e) { + if ((options.autoAbortFailure === undefined || options.autoAbortFailure) && + mpuHelper.uploadId) { + try { + await mpuHelper.abortUpload(); + return; + } + catch (e) { + throw new MultiPartUploadError(e.message, mpuHelper.uploadId, mpuHelper.partsMap); + } + } + throw new MultiPartUploadError(e.message, mpuHelper.uploadId, mpuHelper.partsMap); + } + } + async *getPathsFromDirectory(directory) { + const filesAndSubdirectories = await fs_1.promises.readdir(directory, { + withFileTypes: true, + }); + for (const curFileOrDirectory of filesAndSubdirectories) { + const fullPath = path.join(directory, curFileOrDirectory.name); + curFileOrDirectory.isDirectory() + ? yield* this.getPathsFromDirectory(fullPath) + : yield fullPath; + } + } +} +exports.TransferManager = TransferManager; + + +/***/ }), + +/***/ 74557: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + + +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +var __createBinding = this && this.__createBinding || (Object.create ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + } + }; + } + Object.defineProperty(o, k2, desc); +} : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +}); +var __setModuleDefault = this && this.__setModuleDefault || (Object.create ? function (o, v) { + Object.defineProperty(o, "default", { + enumerable: true, + value: v + }); +} : function (o, v) { + o["default"] = v; +}); +var __importStar = this && this.__importStar || function () { + var ownKeys = function (o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +}(); +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports.PassThroughShim = void 0; +exports.normalize = normalize; +exports.objectEntries = objectEntries; +exports.fixedEncodeURIComponent = fixedEncodeURIComponent; +exports.encodeURI = encodeURI; +exports.qsStringify = qsStringify; +exports.objectKeyToLowercase = objectKeyToLowercase; +exports.unicodeJSONStringify = unicodeJSONStringify; +exports.convertObjKeysToSnakeCase = convertObjKeysToSnakeCase; +exports.formatAsUTCISO = formatAsUTCISO; +exports.getRuntimeTrackingString = getRuntimeTrackingString; +exports.getUserAgentString = getUserAgentString; +exports.getDirName = getDirName; +exports.getModuleFormat = getModuleFormat; +const path = __importStar(__nccwpck_require__(16928)); +const querystring = __importStar(__nccwpck_require__(83480)); +const stream_1 = __nccwpck_require__(2203); +const url = __importStar(__nccwpck_require__(87016)); +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +const package_json_helper_cjs_1 = __nccwpck_require__(41969); +// Done to avoid a problem with mangling of identifiers when using esModuleInterop +const fileURLToPath = url.fileURLToPath; +const isEsm = false; +function normalize(optionsOrCallback, cb) { + const options = typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + const callback = typeof optionsOrCallback === 'function' ? optionsOrCallback : cb; + return { + options, + callback + }; +} +/** + * Flatten an object into an Array of arrays, [[key, value], ..]. + * Implements Object.entries() for Node.js <8 + * @internal + */ +function objectEntries(obj) { + return Object.keys(obj).map(key => [key, obj[key]]); +} +/** + * Encode `str` with encodeURIComponent, plus these + * reserved characters: `! * ' ( )`. + * + * See {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent| MDN: fixedEncodeURIComponent} + * + * @param {string} str The URI component to encode. + * @return {string} The encoded string. + */ +function fixedEncodeURIComponent(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, c => '%' + c.charCodeAt(0).toString(16).toUpperCase()); +} +/** + * URI encode `uri` for generating signed URLs, using fixedEncodeURIComponent. + * + * Encode every byte except `A-Z a-Z 0-9 ~ - . _`. + * + * @param {string} uri The URI to encode. + * @param [boolean=false] encodeSlash If `true`, the "/" character is not encoded. + * @return {string} The encoded string. + */ +function encodeURI(uri, encodeSlash) { + // Split the string by `/`, and conditionally rejoin them with either + // %2F if encodeSlash is `true`, or '/' if `false`. + return uri.split('/').map(fixedEncodeURIComponent).join(encodeSlash ? '%2F' : '/'); +} +/** + * Serialize an object to a URL query string using util.encodeURI(uri, true). + * @param {string} url The object to serialize. + * @return {string} Serialized string. + */ +function qsStringify(qs) { + return querystring.stringify(qs, '&', '=', { + encodeURIComponent: component => encodeURI(component, true) + }); +} +function objectKeyToLowercase(object) { + const newObj = {}; + for (let key of Object.keys(object)) { + const value = object[key]; + key = key.toLowerCase(); + newObj[key] = value; + } + return newObj; +} +/** + * JSON encode str, with unicode \u+ representation. + * @param {object} obj The object to encode. + * @return {string} Serialized string. + */ +function unicodeJSONStringify(obj) { + return JSON.stringify(obj).replace(/[\u0080-\uFFFF]/g, char => '\\u' + ('0000' + char.charCodeAt(0).toString(16)).slice(-4)); +} +/** + * Converts the given objects keys to snake_case + * @param {object} obj object to convert keys to snake case. + * @returns {object} object with keys converted to snake case. + */ +function convertObjKeysToSnakeCase(obj) { + if (obj instanceof Date || obj instanceof RegExp) { + return obj; + } + if (Array.isArray(obj)) { + return obj.map(convertObjKeysToSnakeCase); + } + if (obj instanceof Object) { + return Object.keys(obj).reduce((acc, cur) => { + const s = cur[0].toLocaleLowerCase() + cur.slice(1).replace(/([A-Z]+)/g, (match, p1) => { + return `_${p1.toLowerCase()}`; + }); + acc[s] = convertObjKeysToSnakeCase(obj[cur]); + return acc; + }, Object()); + } + return obj; +} +/** + * Formats the provided date object as a UTC ISO string. + * @param {Date} dateTimeToFormat date object to be formatted. + * @param {boolean} includeTime flag to include hours, minutes, seconds in output. + * @param {string} dateDelimiter delimiter between date components. + * @param {string} timeDelimiter delimiter between time components. + * @returns {string} UTC ISO format of provided date obect. + */ +function formatAsUTCISO(dateTimeToFormat, includeTime = false, dateDelimiter = '', timeDelimiter = '') { + const year = dateTimeToFormat.getUTCFullYear(); + const month = dateTimeToFormat.getUTCMonth() + 1; + const day = dateTimeToFormat.getUTCDate(); + const hour = dateTimeToFormat.getUTCHours(); + const minute = dateTimeToFormat.getUTCMinutes(); + const second = dateTimeToFormat.getUTCSeconds(); + let resultString = `${year.toString().padStart(4, '0')}${dateDelimiter}${month.toString().padStart(2, '0')}${dateDelimiter}${day.toString().padStart(2, '0')}`; + if (includeTime) { + resultString = `${resultString}T${hour.toString().padStart(2, '0')}${timeDelimiter}${minute.toString().padStart(2, '0')}${timeDelimiter}${second.toString().padStart(2, '0')}Z`; + } + return resultString; +} +/** + * Examines the runtime environment and returns the appropriate tracking string. + * @returns {string} metrics tracking string based on the current runtime environment. + */ +function getRuntimeTrackingString() { + if ( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno && + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno.version && + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + globalThis.Deno.version.deno) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + return `gl-deno/${globalThis.Deno.version.deno}`; + } else { + return `gl-node/${process.versions.node}`; + } +} +/** + * Looks at package.json and creates the user-agent string to be applied to request headers. + * @returns {string} user agent string. + */ +function getUserAgentString() { + const pkg = (0, package_json_helper_cjs_1.getPackageJSON)(); + const hyphenatedPackageName = pkg.name.replace('@google-cloud', 'gcloud-node') // For legacy purposes. + .replace('/', '-'); // For UA spec-compliance purposes. + return hyphenatedPackageName + '/' + pkg.version; +} +function getDirName() { + let dirToUse = ''; + try { + dirToUse = __dirname; + } catch (e) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + dirToUse = __dirname; + } + return dirToUse; +} +function getModuleFormat() { + return isEsm ? 'ESM' : 'CJS'; +} +class PassThroughShim extends stream_1.PassThrough { + constructor() { + super(...arguments); + this.shouldEmitReading = true; + this.shouldEmitWriting = true; + } + _read(size) { + if (this.shouldEmitReading) { + this.emit('reading'); + this.shouldEmitReading = false; + } + super._read(size); + } + _write(chunk, encoding, callback) { + if (this.shouldEmitWriting) { + this.emit('writing'); + this.shouldEmitWriting = false; + } + // Per the nodejs documention, callback must be invoked on the next tick + process.nextTick(() => { + super._write(chunk, encoding, callback); + }); + } + _final(callback) { + // If the stream is empty (i.e. empty file) final will be invoked before _read / _write + // and we should still emit the proper events. + if (this.shouldEmitReading) { + this.emit('reading'); + this.shouldEmitReading = false; + } + if (this.shouldEmitWriting) { + this.emit('writing'); + this.shouldEmitWriting = false; + } + callback(null); + } +} +exports.PassThroughShim = PassThroughShim; + + +/***/ }), + +/***/ 13660: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.encode = encode; +exports.decodeEntity = decodeEntity; +exports.decode = decode; +var named_references_js_1 = __nccwpck_require__(56000); +var numeric_unicode_map_js_1 = __nccwpck_require__(53438); +var surrogate_pairs_js_1 = __nccwpck_require__(69718); +var allNamedReferences = __assign(__assign({}, named_references_js_1.namedReferences), { all: named_references_js_1.namedReferences.html5 }); +var encodeRegExps = { + specialChars: /[<>'"&]/g, + nonAscii: /[<>'"&\u0080-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, + nonAsciiPrintable: /[<>'"&\x01-\x08\x11-\x15\x17-\x1F\x7f-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, + nonAsciiPrintableOnly: /[\x01-\x08\x11-\x15\x17-\x1F\x7f-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g, + extensive: /[\x01-\x0c\x0e-\x1f\x21-\x2c\x2e-\x2f\x3a-\x40\x5b-\x60\x7b-\x7d\x7f-\uD7FF\uE000-\uFFFF\uDC00-\uDFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]?/g +}; +var defaultEncodeOptions = { + mode: 'specialChars', + level: 'all', + numeric: 'decimal' +}; +/** Encodes all the necessary (specified by `level`) characters in the text */ +function encode(text, _a) { + var _b = _a === void 0 ? defaultEncodeOptions : _a, _c = _b.mode, mode = _c === void 0 ? 'specialChars' : _c, _d = _b.numeric, numeric = _d === void 0 ? 'decimal' : _d, _e = _b.level, level = _e === void 0 ? 'all' : _e; + if (!text) { + return ''; + } + var encodeRegExp = encodeRegExps[mode]; + var references = allNamedReferences[level].characters; + var isHex = numeric === 'hexadecimal'; + return String.prototype.replace.call(text, encodeRegExp, function (input) { + var result = references[input]; + if (!result) { + var code = input.length > 1 ? (0, surrogate_pairs_js_1.getCodePoint)(input, 0) : input.charCodeAt(0); + result = (isHex ? '&#x' + code.toString(16) : '&#' + code) + ';'; + } + return result; + }); +} +var defaultDecodeOptions = { + scope: 'body', + level: 'all' +}; +var strict = /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);/g; +var attribute = /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+)[;=]?/g; +var baseDecodeRegExps = { + xml: { + strict: strict, + attribute: attribute, + body: named_references_js_1.bodyRegExps.xml + }, + html4: { + strict: strict, + attribute: attribute, + body: named_references_js_1.bodyRegExps.html4 + }, + html5: { + strict: strict, + attribute: attribute, + body: named_references_js_1.bodyRegExps.html5 + } +}; +var decodeRegExps = __assign(__assign({}, baseDecodeRegExps), { all: baseDecodeRegExps.html5 }); +var fromCharCode = String.fromCharCode; +var outOfBoundsChar = fromCharCode(65533); +var defaultDecodeEntityOptions = { + level: 'all' +}; +function getDecodedEntity(entity, references, isAttribute, isStrict) { + var decodeResult = entity; + var decodeEntityLastChar = entity[entity.length - 1]; + if (isAttribute && decodeEntityLastChar === '=') { + decodeResult = entity; + } + else if (isStrict && decodeEntityLastChar !== ';') { + decodeResult = entity; + } + else { + var decodeResultByReference = references[entity]; + if (decodeResultByReference) { + decodeResult = decodeResultByReference; + } + else if (entity[0] === '&' && entity[1] === '#') { + var decodeSecondChar = entity[2]; + var decodeCode = decodeSecondChar == 'x' || decodeSecondChar == 'X' + ? parseInt(entity.substr(3), 16) + : parseInt(entity.substr(2)); + decodeResult = + decodeCode >= 0x10ffff + ? outOfBoundsChar + : decodeCode > 65535 + ? (0, surrogate_pairs_js_1.fromCodePoint)(decodeCode) + : fromCharCode(numeric_unicode_map_js_1.numericUnicodeMap[decodeCode] || decodeCode); + } + } + return decodeResult; +} +/** Decodes a single entity */ +function decodeEntity(entity, _a) { + var _b = _a === void 0 ? defaultDecodeEntityOptions : _a, _c = _b.level, level = _c === void 0 ? 'all' : _c; + if (!entity) { + return ''; + } + return getDecodedEntity(entity, allNamedReferences[level].entities, false, false); +} +/** Decodes all entities in the text */ +function decode(text, _a) { + var _b = _a === void 0 ? defaultDecodeOptions : _a, _c = _b.level, level = _c === void 0 ? 'all' : _c, _d = _b.scope, scope = _d === void 0 ? level === 'xml' ? 'strict' : 'body' : _d; + if (!text) { + return ''; + } + var decodeRegExp = decodeRegExps[level][scope]; + var references = allNamedReferences[level].entities; + var isAttribute = scope === 'attribute'; + var isStrict = scope === 'strict'; + return text.replace(decodeRegExp, function (entity) { return getDecodedEntity(entity, references, isAttribute, isStrict); }); +} +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 56000: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.namedReferences = exports.bodyRegExps = void 0; +// This file is autogenerated by tools/process-named-references.ts +var pairDivider = "~"; +var blockDivider = "~~"; +function generateNamedReferences(input, prev) { + var entities = {}; + var characters = {}; + var blocks = input.split(blockDivider); + var isOptionalBlock = false; + for (var i = 0; blocks.length > i; i++) { + var entries = blocks[i].split(pairDivider); + for (var j = 0; j < entries.length; j += 2) { + var entity = entries[j]; + var character = entries[j + 1]; + var fullEntity = '&' + entity + ';'; + entities[fullEntity] = character; + if (isOptionalBlock) { + entities['&' + entity] = character; + } + characters[character] = fullEntity; + } + isOptionalBlock = true; + } + return prev ? + { entities: __assign(__assign({}, entities), prev.entities), characters: __assign(__assign({}, characters), prev.characters) } : + { entities: entities, characters: characters }; +} +exports.bodyRegExps = { + xml: /&(?:#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g, + html4: /∉|&(?:nbsp|iexcl|cent|pound|curren|yen|brvbar|sect|uml|copy|ordf|laquo|not|shy|reg|macr|deg|plusmn|sup2|sup3|acute|micro|para|middot|cedil|sup1|ordm|raquo|frac14|frac12|frac34|iquest|Agrave|Aacute|Acirc|Atilde|Auml|Aring|AElig|Ccedil|Egrave|Eacute|Ecirc|Euml|Igrave|Iacute|Icirc|Iuml|ETH|Ntilde|Ograve|Oacute|Ocirc|Otilde|Ouml|times|Oslash|Ugrave|Uacute|Ucirc|Uuml|Yacute|THORN|szlig|agrave|aacute|acirc|atilde|auml|aring|aelig|ccedil|egrave|eacute|ecirc|euml|igrave|iacute|icirc|iuml|eth|ntilde|ograve|oacute|ocirc|otilde|ouml|divide|oslash|ugrave|uacute|ucirc|uuml|yacute|thorn|yuml|quot|amp|lt|gt|#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g, + html5: /·|℗|⋇|⪧|⩺|⋗|⦕|⩼|⪆|⥸|⋗|⋛|⪌|≷|≳|⪦|⩹|⋖|⋋|⋉|⥶|⩻|⦖|◃|⊴|◂|∉|⋹̸|⋵̸|∉|⋷|⋶|∌|∌|⋾|⋽|∥|⊠|⨱|⨰|&(?:AElig|AMP|Aacute|Acirc|Agrave|Aring|Atilde|Auml|COPY|Ccedil|ETH|Eacute|Ecirc|Egrave|Euml|GT|Iacute|Icirc|Igrave|Iuml|LT|Ntilde|Oacute|Ocirc|Ograve|Oslash|Otilde|Ouml|QUOT|REG|THORN|Uacute|Ucirc|Ugrave|Uuml|Yacute|aacute|acirc|acute|aelig|agrave|amp|aring|atilde|auml|brvbar|ccedil|cedil|cent|copy|curren|deg|divide|eacute|ecirc|egrave|eth|euml|frac12|frac14|frac34|gt|iacute|icirc|iexcl|igrave|iquest|iuml|laquo|lt|macr|micro|middot|nbsp|not|ntilde|oacute|ocirc|ograve|ordf|ordm|oslash|otilde|ouml|para|plusmn|pound|quot|raquo|reg|sect|shy|sup1|sup2|sup3|szlig|thorn|times|uacute|ucirc|ugrave|uml|uuml|yacute|yen|yuml|#\d+|#[xX][\da-fA-F]+|[0-9a-zA-Z]+);?/g +}; +exports.namedReferences = {}; +exports.namedReferences.xml = generateNamedReferences("lt~<~gt~>~quot~\"~apos~'~amp~&"); +exports.namedReferences.html4 = generateNamedReferences("apos~'~OElig~Œ~oelig~œ~Scaron~Š~scaron~š~Yuml~Ÿ~circ~ˆ~tilde~˜~ensp~ ~emsp~ ~thinsp~ ~zwnj~‌~zwj~‍~lrm~‎~rlm~‏~ndash~–~mdash~—~lsquo~‘~rsquo~’~sbquo~‚~ldquo~“~rdquo~”~bdquo~„~dagger~†~Dagger~‡~permil~‰~lsaquo~‹~rsaquo~›~euro~€~fnof~ƒ~Alpha~Α~Beta~Β~Gamma~Γ~Delta~Δ~Epsilon~Ε~Zeta~Ζ~Eta~Η~Theta~Θ~Iota~Ι~Kappa~Κ~Lambda~Λ~Mu~Μ~Nu~Ν~Xi~Ξ~Omicron~Ο~Pi~Π~Rho~Ρ~Sigma~Σ~Tau~Τ~Upsilon~Υ~Phi~Φ~Chi~Χ~Psi~Ψ~Omega~Ω~alpha~α~beta~β~gamma~γ~delta~δ~epsilon~ε~zeta~ζ~eta~η~theta~θ~iota~ι~kappa~κ~lambda~λ~mu~μ~nu~ν~xi~ξ~omicron~ο~pi~π~rho~ρ~sigmaf~ς~sigma~σ~tau~τ~upsilon~υ~phi~φ~chi~χ~psi~ψ~omega~ω~thetasym~ϑ~upsih~ϒ~piv~ϖ~bull~•~hellip~…~prime~′~Prime~″~oline~‾~frasl~⁄~weierp~℘~image~ℑ~real~ℜ~trade~™~alefsym~ℵ~larr~←~uarr~↑~rarr~→~darr~↓~harr~↔~crarr~↵~lArr~⇐~uArr~⇑~rArr~⇒~dArr~⇓~hArr~⇔~forall~∀~part~∂~exist~∃~empty~∅~nabla~∇~isin~∈~notin~∉~ni~∋~prod~∏~sum~∑~minus~−~lowast~∗~radic~√~prop~∝~infin~∞~ang~∠~and~∧~or~∨~cap~∩~cup~∪~int~∫~there4~∴~sim~∼~cong~≅~asymp~≈~ne~≠~equiv~≡~le~≤~ge~≥~sub~⊂~sup~⊃~nsub~⊄~sube~⊆~supe~⊇~oplus~⊕~otimes~⊗~perp~⊥~sdot~⋅~lceil~⌈~rceil~⌉~lfloor~⌊~rfloor~⌋~lang~〈~rang~〉~loz~◊~spades~♠~clubs~♣~hearts~♥~diams~♦~~nbsp~ ~iexcl~¡~cent~¢~pound~£~curren~¤~yen~¥~brvbar~¦~sect~§~uml~¨~copy~©~ordf~ª~laquo~«~not~¬~shy~­~reg~®~macr~¯~deg~°~plusmn~±~sup2~²~sup3~³~acute~´~micro~µ~para~¶~middot~·~cedil~¸~sup1~¹~ordm~º~raquo~»~frac14~¼~frac12~½~frac34~¾~iquest~¿~Agrave~À~Aacute~Á~Acirc~Â~Atilde~Ã~Auml~Ä~Aring~Å~AElig~Æ~Ccedil~Ç~Egrave~È~Eacute~É~Ecirc~Ê~Euml~Ë~Igrave~Ì~Iacute~Í~Icirc~Î~Iuml~Ï~ETH~Ð~Ntilde~Ñ~Ograve~Ò~Oacute~Ó~Ocirc~Ô~Otilde~Õ~Ouml~Ö~times~×~Oslash~Ø~Ugrave~Ù~Uacute~Ú~Ucirc~Û~Uuml~Ü~Yacute~Ý~THORN~Þ~szlig~ß~agrave~à~aacute~á~acirc~â~atilde~ã~auml~ä~aring~å~aelig~æ~ccedil~ç~egrave~è~eacute~é~ecirc~ê~euml~ë~igrave~ì~iacute~í~icirc~î~iuml~ï~eth~ð~ntilde~ñ~ograve~ò~oacute~ó~ocirc~ô~otilde~õ~ouml~ö~divide~÷~oslash~ø~ugrave~ù~uacute~ú~ucirc~û~uuml~ü~yacute~ý~thorn~þ~yuml~ÿ~quot~\"~amp~&~lt~<~gt~>"); +exports.namedReferences.html5 = generateNamedReferences("Abreve~Ă~Acy~А~Afr~𝔄~Amacr~Ā~And~⩓~Aogon~Ą~Aopf~𝔸~ApplyFunction~⁡~Ascr~𝒜~Assign~≔~Backslash~∖~Barv~⫧~Barwed~⌆~Bcy~Б~Because~∵~Bernoullis~ℬ~Bfr~𝔅~Bopf~𝔹~Breve~˘~Bscr~ℬ~Bumpeq~≎~CHcy~Ч~Cacute~Ć~Cap~⋒~CapitalDifferentialD~ⅅ~Cayleys~ℭ~Ccaron~Č~Ccirc~Ĉ~Cconint~∰~Cdot~Ċ~Cedilla~¸~CenterDot~·~Cfr~ℭ~CircleDot~⊙~CircleMinus~⊖~CirclePlus~⊕~CircleTimes~⊗~ClockwiseContourIntegral~∲~CloseCurlyDoubleQuote~”~CloseCurlyQuote~’~Colon~∷~Colone~⩴~Congruent~≡~Conint~∯~ContourIntegral~∮~Copf~ℂ~Coproduct~∐~CounterClockwiseContourIntegral~∳~Cross~⨯~Cscr~𝒞~Cup~⋓~CupCap~≍~DD~ⅅ~DDotrahd~⤑~DJcy~Ђ~DScy~Ѕ~DZcy~Џ~Darr~↡~Dashv~⫤~Dcaron~Ď~Dcy~Д~Del~∇~Dfr~𝔇~DiacriticalAcute~´~DiacriticalDot~˙~DiacriticalDoubleAcute~˝~DiacriticalGrave~`~DiacriticalTilde~˜~Diamond~⋄~DifferentialD~ⅆ~Dopf~𝔻~Dot~¨~DotDot~⃜~DotEqual~≐~DoubleContourIntegral~∯~DoubleDot~¨~DoubleDownArrow~⇓~DoubleLeftArrow~⇐~DoubleLeftRightArrow~⇔~DoubleLeftTee~⫤~DoubleLongLeftArrow~⟸~DoubleLongLeftRightArrow~⟺~DoubleLongRightArrow~⟹~DoubleRightArrow~⇒~DoubleRightTee~⊨~DoubleUpArrow~⇑~DoubleUpDownArrow~⇕~DoubleVerticalBar~∥~DownArrow~↓~DownArrowBar~⤓~DownArrowUpArrow~⇵~DownBreve~̑~DownLeftRightVector~⥐~DownLeftTeeVector~⥞~DownLeftVector~↽~DownLeftVectorBar~⥖~DownRightTeeVector~⥟~DownRightVector~⇁~DownRightVectorBar~⥗~DownTee~⊤~DownTeeArrow~↧~Downarrow~⇓~Dscr~𝒟~Dstrok~Đ~ENG~Ŋ~Ecaron~Ě~Ecy~Э~Edot~Ė~Efr~𝔈~Element~∈~Emacr~Ē~EmptySmallSquare~◻~EmptyVerySmallSquare~▫~Eogon~Ę~Eopf~𝔼~Equal~⩵~EqualTilde~≂~Equilibrium~⇌~Escr~ℰ~Esim~⩳~Exists~∃~ExponentialE~ⅇ~Fcy~Ф~Ffr~𝔉~FilledSmallSquare~◼~FilledVerySmallSquare~▪~Fopf~𝔽~ForAll~∀~Fouriertrf~ℱ~Fscr~ℱ~GJcy~Ѓ~Gammad~Ϝ~Gbreve~Ğ~Gcedil~Ģ~Gcirc~Ĝ~Gcy~Г~Gdot~Ġ~Gfr~𝔊~Gg~⋙~Gopf~𝔾~GreaterEqual~≥~GreaterEqualLess~⋛~GreaterFullEqual~≧~GreaterGreater~⪢~GreaterLess~≷~GreaterSlantEqual~⩾~GreaterTilde~≳~Gscr~𝒢~Gt~≫~HARDcy~Ъ~Hacek~ˇ~Hat~^~Hcirc~Ĥ~Hfr~ℌ~HilbertSpace~ℋ~Hopf~ℍ~HorizontalLine~─~Hscr~ℋ~Hstrok~Ħ~HumpDownHump~≎~HumpEqual~≏~IEcy~Е~IJlig~IJ~IOcy~Ё~Icy~И~Idot~İ~Ifr~ℑ~Im~ℑ~Imacr~Ī~ImaginaryI~ⅈ~Implies~⇒~Int~∬~Integral~∫~Intersection~⋂~InvisibleComma~⁣~InvisibleTimes~⁢~Iogon~Į~Iopf~𝕀~Iscr~ℐ~Itilde~Ĩ~Iukcy~І~Jcirc~Ĵ~Jcy~Й~Jfr~𝔍~Jopf~𝕁~Jscr~𝒥~Jsercy~Ј~Jukcy~Є~KHcy~Х~KJcy~Ќ~Kcedil~Ķ~Kcy~К~Kfr~𝔎~Kopf~𝕂~Kscr~𝒦~LJcy~Љ~Lacute~Ĺ~Lang~⟪~Laplacetrf~ℒ~Larr~↞~Lcaron~Ľ~Lcedil~Ļ~Lcy~Л~LeftAngleBracket~⟨~LeftArrow~←~LeftArrowBar~⇤~LeftArrowRightArrow~⇆~LeftCeiling~⌈~LeftDoubleBracket~⟦~LeftDownTeeVector~⥡~LeftDownVector~⇃~LeftDownVectorBar~⥙~LeftFloor~⌊~LeftRightArrow~↔~LeftRightVector~⥎~LeftTee~⊣~LeftTeeArrow~↤~LeftTeeVector~⥚~LeftTriangle~⊲~LeftTriangleBar~⧏~LeftTriangleEqual~⊴~LeftUpDownVector~⥑~LeftUpTeeVector~⥠~LeftUpVector~↿~LeftUpVectorBar~⥘~LeftVector~↼~LeftVectorBar~⥒~Leftarrow~⇐~Leftrightarrow~⇔~LessEqualGreater~⋚~LessFullEqual~≦~LessGreater~≶~LessLess~⪡~LessSlantEqual~⩽~LessTilde~≲~Lfr~𝔏~Ll~⋘~Lleftarrow~⇚~Lmidot~Ŀ~LongLeftArrow~⟵~LongLeftRightArrow~⟷~LongRightArrow~⟶~Longleftarrow~⟸~Longleftrightarrow~⟺~Longrightarrow~⟹~Lopf~𝕃~LowerLeftArrow~↙~LowerRightArrow~↘~Lscr~ℒ~Lsh~↰~Lstrok~Ł~Lt~≪~Map~⤅~Mcy~М~MediumSpace~ ~Mellintrf~ℳ~Mfr~𝔐~MinusPlus~∓~Mopf~𝕄~Mscr~ℳ~NJcy~Њ~Nacute~Ń~Ncaron~Ň~Ncedil~Ņ~Ncy~Н~NegativeMediumSpace~​~NegativeThickSpace~​~NegativeThinSpace~​~NegativeVeryThinSpace~​~NestedGreaterGreater~≫~NestedLessLess~≪~NewLine~\n~Nfr~𝔑~NoBreak~⁠~NonBreakingSpace~ ~Nopf~ℕ~Not~⫬~NotCongruent~≢~NotCupCap~≭~NotDoubleVerticalBar~∦~NotElement~∉~NotEqual~≠~NotEqualTilde~≂̸~NotExists~∄~NotGreater~≯~NotGreaterEqual~≱~NotGreaterFullEqual~≧̸~NotGreaterGreater~≫̸~NotGreaterLess~≹~NotGreaterSlantEqual~⩾̸~NotGreaterTilde~≵~NotHumpDownHump~≎̸~NotHumpEqual~≏̸~NotLeftTriangle~⋪~NotLeftTriangleBar~⧏̸~NotLeftTriangleEqual~⋬~NotLess~≮~NotLessEqual~≰~NotLessGreater~≸~NotLessLess~≪̸~NotLessSlantEqual~⩽̸~NotLessTilde~≴~NotNestedGreaterGreater~⪢̸~NotNestedLessLess~⪡̸~NotPrecedes~⊀~NotPrecedesEqual~⪯̸~NotPrecedesSlantEqual~⋠~NotReverseElement~∌~NotRightTriangle~⋫~NotRightTriangleBar~⧐̸~NotRightTriangleEqual~⋭~NotSquareSubset~⊏̸~NotSquareSubsetEqual~⋢~NotSquareSuperset~⊐̸~NotSquareSupersetEqual~⋣~NotSubset~⊂⃒~NotSubsetEqual~⊈~NotSucceeds~⊁~NotSucceedsEqual~⪰̸~NotSucceedsSlantEqual~⋡~NotSucceedsTilde~≿̸~NotSuperset~⊃⃒~NotSupersetEqual~⊉~NotTilde~≁~NotTildeEqual~≄~NotTildeFullEqual~≇~NotTildeTilde~≉~NotVerticalBar~∤~Nscr~𝒩~Ocy~О~Odblac~Ő~Ofr~𝔒~Omacr~Ō~Oopf~𝕆~OpenCurlyDoubleQuote~“~OpenCurlyQuote~‘~Or~⩔~Oscr~𝒪~Otimes~⨷~OverBar~‾~OverBrace~⏞~OverBracket~⎴~OverParenthesis~⏜~PartialD~∂~Pcy~П~Pfr~𝔓~PlusMinus~±~Poincareplane~ℌ~Popf~ℙ~Pr~⪻~Precedes~≺~PrecedesEqual~⪯~PrecedesSlantEqual~≼~PrecedesTilde~≾~Product~∏~Proportion~∷~Proportional~∝~Pscr~𝒫~Qfr~𝔔~Qopf~ℚ~Qscr~𝒬~RBarr~⤐~Racute~Ŕ~Rang~⟫~Rarr~↠~Rarrtl~⤖~Rcaron~Ř~Rcedil~Ŗ~Rcy~Р~Re~ℜ~ReverseElement~∋~ReverseEquilibrium~⇋~ReverseUpEquilibrium~⥯~Rfr~ℜ~RightAngleBracket~⟩~RightArrow~→~RightArrowBar~⇥~RightArrowLeftArrow~⇄~RightCeiling~⌉~RightDoubleBracket~⟧~RightDownTeeVector~⥝~RightDownVector~⇂~RightDownVectorBar~⥕~RightFloor~⌋~RightTee~⊢~RightTeeArrow~↦~RightTeeVector~⥛~RightTriangle~⊳~RightTriangleBar~⧐~RightTriangleEqual~⊵~RightUpDownVector~⥏~RightUpTeeVector~⥜~RightUpVector~↾~RightUpVectorBar~⥔~RightVector~⇀~RightVectorBar~⥓~Rightarrow~⇒~Ropf~ℝ~RoundImplies~⥰~Rrightarrow~⇛~Rscr~ℛ~Rsh~↱~RuleDelayed~⧴~SHCHcy~Щ~SHcy~Ш~SOFTcy~Ь~Sacute~Ś~Sc~⪼~Scedil~Ş~Scirc~Ŝ~Scy~С~Sfr~𝔖~ShortDownArrow~↓~ShortLeftArrow~←~ShortRightArrow~→~ShortUpArrow~↑~SmallCircle~∘~Sopf~𝕊~Sqrt~√~Square~□~SquareIntersection~⊓~SquareSubset~⊏~SquareSubsetEqual~⊑~SquareSuperset~⊐~SquareSupersetEqual~⊒~SquareUnion~⊔~Sscr~𝒮~Star~⋆~Sub~⋐~Subset~⋐~SubsetEqual~⊆~Succeeds~≻~SucceedsEqual~⪰~SucceedsSlantEqual~≽~SucceedsTilde~≿~SuchThat~∋~Sum~∑~Sup~⋑~Superset~⊃~SupersetEqual~⊇~Supset~⋑~TRADE~™~TSHcy~Ћ~TScy~Ц~Tab~\t~Tcaron~Ť~Tcedil~Ţ~Tcy~Т~Tfr~𝔗~Therefore~∴~ThickSpace~  ~ThinSpace~ ~Tilde~∼~TildeEqual~≃~TildeFullEqual~≅~TildeTilde~≈~Topf~𝕋~TripleDot~⃛~Tscr~𝒯~Tstrok~Ŧ~Uarr~↟~Uarrocir~⥉~Ubrcy~Ў~Ubreve~Ŭ~Ucy~У~Udblac~Ű~Ufr~𝔘~Umacr~Ū~UnderBar~_~UnderBrace~⏟~UnderBracket~⎵~UnderParenthesis~⏝~Union~⋃~UnionPlus~⊎~Uogon~Ų~Uopf~𝕌~UpArrow~↑~UpArrowBar~⤒~UpArrowDownArrow~⇅~UpDownArrow~↕~UpEquilibrium~⥮~UpTee~⊥~UpTeeArrow~↥~Uparrow~⇑~Updownarrow~⇕~UpperLeftArrow~↖~UpperRightArrow~↗~Upsi~ϒ~Uring~Ů~Uscr~𝒰~Utilde~Ũ~VDash~⊫~Vbar~⫫~Vcy~В~Vdash~⊩~Vdashl~⫦~Vee~⋁~Verbar~‖~Vert~‖~VerticalBar~∣~VerticalLine~|~VerticalSeparator~❘~VerticalTilde~≀~VeryThinSpace~ ~Vfr~𝔙~Vopf~𝕍~Vscr~𝒱~Vvdash~⊪~Wcirc~Ŵ~Wedge~⋀~Wfr~𝔚~Wopf~𝕎~Wscr~𝒲~Xfr~𝔛~Xopf~𝕏~Xscr~𝒳~YAcy~Я~YIcy~Ї~YUcy~Ю~Ycirc~Ŷ~Ycy~Ы~Yfr~𝔜~Yopf~𝕐~Yscr~𝒴~ZHcy~Ж~Zacute~Ź~Zcaron~Ž~Zcy~З~Zdot~Ż~ZeroWidthSpace~​~Zfr~ℨ~Zopf~ℤ~Zscr~𝒵~abreve~ă~ac~∾~acE~∾̳~acd~∿~acy~а~af~⁡~afr~𝔞~aleph~ℵ~amacr~ā~amalg~⨿~andand~⩕~andd~⩜~andslope~⩘~andv~⩚~ange~⦤~angle~∠~angmsd~∡~angmsdaa~⦨~angmsdab~⦩~angmsdac~⦪~angmsdad~⦫~angmsdae~⦬~angmsdaf~⦭~angmsdag~⦮~angmsdah~⦯~angrt~∟~angrtvb~⊾~angrtvbd~⦝~angsph~∢~angst~Å~angzarr~⍼~aogon~ą~aopf~𝕒~ap~≈~apE~⩰~apacir~⩯~ape~≊~apid~≋~approx~≈~approxeq~≊~ascr~𝒶~ast~*~asympeq~≍~awconint~∳~awint~⨑~bNot~⫭~backcong~≌~backepsilon~϶~backprime~‵~backsim~∽~backsimeq~⋍~barvee~⊽~barwed~⌅~barwedge~⌅~bbrk~⎵~bbrktbrk~⎶~bcong~≌~bcy~б~becaus~∵~because~∵~bemptyv~⦰~bepsi~϶~bernou~ℬ~beth~ℶ~between~≬~bfr~𝔟~bigcap~⋂~bigcirc~◯~bigcup~⋃~bigodot~⨀~bigoplus~⨁~bigotimes~⨂~bigsqcup~⨆~bigstar~★~bigtriangledown~▽~bigtriangleup~△~biguplus~⨄~bigvee~⋁~bigwedge~⋀~bkarow~⤍~blacklozenge~⧫~blacksquare~▪~blacktriangle~▴~blacktriangledown~▾~blacktriangleleft~◂~blacktriangleright~▸~blank~␣~blk12~▒~blk14~░~blk34~▓~block~█~bne~=⃥~bnequiv~≡⃥~bnot~⌐~bopf~𝕓~bot~⊥~bottom~⊥~bowtie~⋈~boxDL~╗~boxDR~╔~boxDl~╖~boxDr~╓~boxH~═~boxHD~╦~boxHU~╩~boxHd~╤~boxHu~╧~boxUL~╝~boxUR~╚~boxUl~╜~boxUr~╙~boxV~║~boxVH~╬~boxVL~╣~boxVR~╠~boxVh~╫~boxVl~╢~boxVr~╟~boxbox~⧉~boxdL~╕~boxdR~╒~boxdl~┐~boxdr~┌~boxh~─~boxhD~╥~boxhU~╨~boxhd~┬~boxhu~┴~boxminus~⊟~boxplus~⊞~boxtimes~⊠~boxuL~╛~boxuR~╘~boxul~┘~boxur~└~boxv~│~boxvH~╪~boxvL~╡~boxvR~╞~boxvh~┼~boxvl~┤~boxvr~├~bprime~‵~breve~˘~bscr~𝒷~bsemi~⁏~bsim~∽~bsime~⋍~bsol~\\~bsolb~⧅~bsolhsub~⟈~bullet~•~bump~≎~bumpE~⪮~bumpe~≏~bumpeq~≏~cacute~ć~capand~⩄~capbrcup~⩉~capcap~⩋~capcup~⩇~capdot~⩀~caps~∩︀~caret~⁁~caron~ˇ~ccaps~⩍~ccaron~č~ccirc~ĉ~ccups~⩌~ccupssm~⩐~cdot~ċ~cemptyv~⦲~centerdot~·~cfr~𝔠~chcy~ч~check~✓~checkmark~✓~cir~○~cirE~⧃~circeq~≗~circlearrowleft~↺~circlearrowright~↻~circledR~®~circledS~Ⓢ~circledast~⊛~circledcirc~⊚~circleddash~⊝~cire~≗~cirfnint~⨐~cirmid~⫯~cirscir~⧂~clubsuit~♣~colon~:~colone~≔~coloneq~≔~comma~,~commat~@~comp~∁~compfn~∘~complement~∁~complexes~ℂ~congdot~⩭~conint~∮~copf~𝕔~coprod~∐~copysr~℗~cross~✗~cscr~𝒸~csub~⫏~csube~⫑~csup~⫐~csupe~⫒~ctdot~⋯~cudarrl~⤸~cudarrr~⤵~cuepr~⋞~cuesc~⋟~cularr~↶~cularrp~⤽~cupbrcap~⩈~cupcap~⩆~cupcup~⩊~cupdot~⊍~cupor~⩅~cups~∪︀~curarr~↷~curarrm~⤼~curlyeqprec~⋞~curlyeqsucc~⋟~curlyvee~⋎~curlywedge~⋏~curvearrowleft~↶~curvearrowright~↷~cuvee~⋎~cuwed~⋏~cwconint~∲~cwint~∱~cylcty~⌭~dHar~⥥~daleth~ℸ~dash~‐~dashv~⊣~dbkarow~⤏~dblac~˝~dcaron~ď~dcy~д~dd~ⅆ~ddagger~‡~ddarr~⇊~ddotseq~⩷~demptyv~⦱~dfisht~⥿~dfr~𝔡~dharl~⇃~dharr~⇂~diam~⋄~diamond~⋄~diamondsuit~♦~die~¨~digamma~ϝ~disin~⋲~div~÷~divideontimes~⋇~divonx~⋇~djcy~ђ~dlcorn~⌞~dlcrop~⌍~dollar~$~dopf~𝕕~dot~˙~doteq~≐~doteqdot~≑~dotminus~∸~dotplus~∔~dotsquare~⊡~doublebarwedge~⌆~downarrow~↓~downdownarrows~⇊~downharpoonleft~⇃~downharpoonright~⇂~drbkarow~⤐~drcorn~⌟~drcrop~⌌~dscr~𝒹~dscy~ѕ~dsol~⧶~dstrok~đ~dtdot~⋱~dtri~▿~dtrif~▾~duarr~⇵~duhar~⥯~dwangle~⦦~dzcy~џ~dzigrarr~⟿~eDDot~⩷~eDot~≑~easter~⩮~ecaron~ě~ecir~≖~ecolon~≕~ecy~э~edot~ė~ee~ⅇ~efDot~≒~efr~𝔢~eg~⪚~egs~⪖~egsdot~⪘~el~⪙~elinters~⏧~ell~ℓ~els~⪕~elsdot~⪗~emacr~ē~emptyset~∅~emptyv~∅~emsp13~ ~emsp14~ ~eng~ŋ~eogon~ę~eopf~𝕖~epar~⋕~eparsl~⧣~eplus~⩱~epsi~ε~epsiv~ϵ~eqcirc~≖~eqcolon~≕~eqsim~≂~eqslantgtr~⪖~eqslantless~⪕~equals~=~equest~≟~equivDD~⩸~eqvparsl~⧥~erDot~≓~erarr~⥱~escr~ℯ~esdot~≐~esim~≂~excl~!~expectation~ℰ~exponentiale~ⅇ~fallingdotseq~≒~fcy~ф~female~♀~ffilig~ffi~fflig~ff~ffllig~ffl~ffr~𝔣~filig~fi~fjlig~fj~flat~♭~fllig~fl~fltns~▱~fopf~𝕗~fork~⋔~forkv~⫙~fpartint~⨍~frac13~⅓~frac15~⅕~frac16~⅙~frac18~⅛~frac23~⅔~frac25~⅖~frac35~⅗~frac38~⅜~frac45~⅘~frac56~⅚~frac58~⅝~frac78~⅞~frown~⌢~fscr~𝒻~gE~≧~gEl~⪌~gacute~ǵ~gammad~ϝ~gap~⪆~gbreve~ğ~gcirc~ĝ~gcy~г~gdot~ġ~gel~⋛~geq~≥~geqq~≧~geqslant~⩾~ges~⩾~gescc~⪩~gesdot~⪀~gesdoto~⪂~gesdotol~⪄~gesl~⋛︀~gesles~⪔~gfr~𝔤~gg~≫~ggg~⋙~gimel~ℷ~gjcy~ѓ~gl~≷~glE~⪒~gla~⪥~glj~⪤~gnE~≩~gnap~⪊~gnapprox~⪊~gne~⪈~gneq~⪈~gneqq~≩~gnsim~⋧~gopf~𝕘~grave~`~gscr~ℊ~gsim~≳~gsime~⪎~gsiml~⪐~gtcc~⪧~gtcir~⩺~gtdot~⋗~gtlPar~⦕~gtquest~⩼~gtrapprox~⪆~gtrarr~⥸~gtrdot~⋗~gtreqless~⋛~gtreqqless~⪌~gtrless~≷~gtrsim~≳~gvertneqq~≩︀~gvnE~≩︀~hairsp~ ~half~½~hamilt~ℋ~hardcy~ъ~harrcir~⥈~harrw~↭~hbar~ℏ~hcirc~ĥ~heartsuit~♥~hercon~⊹~hfr~𝔥~hksearow~⤥~hkswarow~⤦~hoarr~⇿~homtht~∻~hookleftarrow~↩~hookrightarrow~↪~hopf~𝕙~horbar~―~hscr~𝒽~hslash~ℏ~hstrok~ħ~hybull~⁃~hyphen~‐~ic~⁣~icy~и~iecy~е~iff~⇔~ifr~𝔦~ii~ⅈ~iiiint~⨌~iiint~∭~iinfin~⧜~iiota~℩~ijlig~ij~imacr~ī~imagline~ℐ~imagpart~ℑ~imath~ı~imof~⊷~imped~Ƶ~in~∈~incare~℅~infintie~⧝~inodot~ı~intcal~⊺~integers~ℤ~intercal~⊺~intlarhk~⨗~intprod~⨼~iocy~ё~iogon~į~iopf~𝕚~iprod~⨼~iscr~𝒾~isinE~⋹~isindot~⋵~isins~⋴~isinsv~⋳~isinv~∈~it~⁢~itilde~ĩ~iukcy~і~jcirc~ĵ~jcy~й~jfr~𝔧~jmath~ȷ~jopf~𝕛~jscr~𝒿~jsercy~ј~jukcy~є~kappav~ϰ~kcedil~ķ~kcy~к~kfr~𝔨~kgreen~ĸ~khcy~х~kjcy~ќ~kopf~𝕜~kscr~𝓀~lAarr~⇚~lAtail~⤛~lBarr~⤎~lE~≦~lEg~⪋~lHar~⥢~lacute~ĺ~laemptyv~⦴~lagran~ℒ~langd~⦑~langle~⟨~lap~⪅~larrb~⇤~larrbfs~⤟~larrfs~⤝~larrhk~↩~larrlp~↫~larrpl~⤹~larrsim~⥳~larrtl~↢~lat~⪫~latail~⤙~late~⪭~lates~⪭︀~lbarr~⤌~lbbrk~❲~lbrace~{~lbrack~[~lbrke~⦋~lbrksld~⦏~lbrkslu~⦍~lcaron~ľ~lcedil~ļ~lcub~{~lcy~л~ldca~⤶~ldquor~„~ldrdhar~⥧~ldrushar~⥋~ldsh~↲~leftarrow~←~leftarrowtail~↢~leftharpoondown~↽~leftharpoonup~↼~leftleftarrows~⇇~leftrightarrow~↔~leftrightarrows~⇆~leftrightharpoons~⇋~leftrightsquigarrow~↭~leftthreetimes~⋋~leg~⋚~leq~≤~leqq~≦~leqslant~⩽~les~⩽~lescc~⪨~lesdot~⩿~lesdoto~⪁~lesdotor~⪃~lesg~⋚︀~lesges~⪓~lessapprox~⪅~lessdot~⋖~lesseqgtr~⋚~lesseqqgtr~⪋~lessgtr~≶~lesssim~≲~lfisht~⥼~lfr~𝔩~lg~≶~lgE~⪑~lhard~↽~lharu~↼~lharul~⥪~lhblk~▄~ljcy~љ~ll~≪~llarr~⇇~llcorner~⌞~llhard~⥫~lltri~◺~lmidot~ŀ~lmoust~⎰~lmoustache~⎰~lnE~≨~lnap~⪉~lnapprox~⪉~lne~⪇~lneq~⪇~lneqq~≨~lnsim~⋦~loang~⟬~loarr~⇽~lobrk~⟦~longleftarrow~⟵~longleftrightarrow~⟷~longmapsto~⟼~longrightarrow~⟶~looparrowleft~↫~looparrowright~↬~lopar~⦅~lopf~𝕝~loplus~⨭~lotimes~⨴~lowbar~_~lozenge~◊~lozf~⧫~lpar~(~lparlt~⦓~lrarr~⇆~lrcorner~⌟~lrhar~⇋~lrhard~⥭~lrtri~⊿~lscr~𝓁~lsh~↰~lsim~≲~lsime~⪍~lsimg~⪏~lsqb~[~lsquor~‚~lstrok~ł~ltcc~⪦~ltcir~⩹~ltdot~⋖~lthree~⋋~ltimes~⋉~ltlarr~⥶~ltquest~⩻~ltrPar~⦖~ltri~◃~ltrie~⊴~ltrif~◂~lurdshar~⥊~luruhar~⥦~lvertneqq~≨︀~lvnE~≨︀~mDDot~∺~male~♂~malt~✠~maltese~✠~map~↦~mapsto~↦~mapstodown~↧~mapstoleft~↤~mapstoup~↥~marker~▮~mcomma~⨩~mcy~м~measuredangle~∡~mfr~𝔪~mho~℧~mid~∣~midast~*~midcir~⫰~minusb~⊟~minusd~∸~minusdu~⨪~mlcp~⫛~mldr~…~mnplus~∓~models~⊧~mopf~𝕞~mp~∓~mscr~𝓂~mstpos~∾~multimap~⊸~mumap~⊸~nGg~⋙̸~nGt~≫⃒~nGtv~≫̸~nLeftarrow~⇍~nLeftrightarrow~⇎~nLl~⋘̸~nLt~≪⃒~nLtv~≪̸~nRightarrow~⇏~nVDash~⊯~nVdash~⊮~nacute~ń~nang~∠⃒~nap~≉~napE~⩰̸~napid~≋̸~napos~ʼn~napprox~≉~natur~♮~natural~♮~naturals~ℕ~nbump~≎̸~nbumpe~≏̸~ncap~⩃~ncaron~ň~ncedil~ņ~ncong~≇~ncongdot~⩭̸~ncup~⩂~ncy~н~neArr~⇗~nearhk~⤤~nearr~↗~nearrow~↗~nedot~≐̸~nequiv~≢~nesear~⤨~nesim~≂̸~nexist~∄~nexists~∄~nfr~𝔫~ngE~≧̸~nge~≱~ngeq~≱~ngeqq~≧̸~ngeqslant~⩾̸~nges~⩾̸~ngsim~≵~ngt~≯~ngtr~≯~nhArr~⇎~nharr~↮~nhpar~⫲~nis~⋼~nisd~⋺~niv~∋~njcy~њ~nlArr~⇍~nlE~≦̸~nlarr~↚~nldr~‥~nle~≰~nleftarrow~↚~nleftrightarrow~↮~nleq~≰~nleqq~≦̸~nleqslant~⩽̸~nles~⩽̸~nless~≮~nlsim~≴~nlt~≮~nltri~⋪~nltrie~⋬~nmid~∤~nopf~𝕟~notinE~⋹̸~notindot~⋵̸~notinva~∉~notinvb~⋷~notinvc~⋶~notni~∌~notniva~∌~notnivb~⋾~notnivc~⋽~npar~∦~nparallel~∦~nparsl~⫽⃥~npart~∂̸~npolint~⨔~npr~⊀~nprcue~⋠~npre~⪯̸~nprec~⊀~npreceq~⪯̸~nrArr~⇏~nrarr~↛~nrarrc~⤳̸~nrarrw~↝̸~nrightarrow~↛~nrtri~⋫~nrtrie~⋭~nsc~⊁~nsccue~⋡~nsce~⪰̸~nscr~𝓃~nshortmid~∤~nshortparallel~∦~nsim~≁~nsime~≄~nsimeq~≄~nsmid~∤~nspar~∦~nsqsube~⋢~nsqsupe~⋣~nsubE~⫅̸~nsube~⊈~nsubset~⊂⃒~nsubseteq~⊈~nsubseteqq~⫅̸~nsucc~⊁~nsucceq~⪰̸~nsup~⊅~nsupE~⫆̸~nsupe~⊉~nsupset~⊃⃒~nsupseteq~⊉~nsupseteqq~⫆̸~ntgl~≹~ntlg~≸~ntriangleleft~⋪~ntrianglelefteq~⋬~ntriangleright~⋫~ntrianglerighteq~⋭~num~#~numero~№~numsp~ ~nvDash~⊭~nvHarr~⤄~nvap~≍⃒~nvdash~⊬~nvge~≥⃒~nvgt~>⃒~nvinfin~⧞~nvlArr~⤂~nvle~≤⃒~nvlt~<⃒~nvltrie~⊴⃒~nvrArr~⤃~nvrtrie~⊵⃒~nvsim~∼⃒~nwArr~⇖~nwarhk~⤣~nwarr~↖~nwarrow~↖~nwnear~⤧~oS~Ⓢ~oast~⊛~ocir~⊚~ocy~о~odash~⊝~odblac~ő~odiv~⨸~odot~⊙~odsold~⦼~ofcir~⦿~ofr~𝔬~ogon~˛~ogt~⧁~ohbar~⦵~ohm~Ω~oint~∮~olarr~↺~olcir~⦾~olcross~⦻~olt~⧀~omacr~ō~omid~⦶~ominus~⊖~oopf~𝕠~opar~⦷~operp~⦹~orarr~↻~ord~⩝~order~ℴ~orderof~ℴ~origof~⊶~oror~⩖~orslope~⩗~orv~⩛~oscr~ℴ~osol~⊘~otimesas~⨶~ovbar~⌽~par~∥~parallel~∥~parsim~⫳~parsl~⫽~pcy~п~percnt~%~period~.~pertenk~‱~pfr~𝔭~phiv~ϕ~phmmat~ℳ~phone~☎~pitchfork~⋔~planck~ℏ~planckh~ℎ~plankv~ℏ~plus~+~plusacir~⨣~plusb~⊞~pluscir~⨢~plusdo~∔~plusdu~⨥~pluse~⩲~plussim~⨦~plustwo~⨧~pm~±~pointint~⨕~popf~𝕡~pr~≺~prE~⪳~prap~⪷~prcue~≼~pre~⪯~prec~≺~precapprox~⪷~preccurlyeq~≼~preceq~⪯~precnapprox~⪹~precneqq~⪵~precnsim~⋨~precsim~≾~primes~ℙ~prnE~⪵~prnap~⪹~prnsim~⋨~profalar~⌮~profline~⌒~profsurf~⌓~propto~∝~prsim~≾~prurel~⊰~pscr~𝓅~puncsp~ ~qfr~𝔮~qint~⨌~qopf~𝕢~qprime~⁗~qscr~𝓆~quaternions~ℍ~quatint~⨖~quest~?~questeq~≟~rAarr~⇛~rAtail~⤜~rBarr~⤏~rHar~⥤~race~∽̱~racute~ŕ~raemptyv~⦳~rangd~⦒~range~⦥~rangle~⟩~rarrap~⥵~rarrb~⇥~rarrbfs~⤠~rarrc~⤳~rarrfs~⤞~rarrhk~↪~rarrlp~↬~rarrpl~⥅~rarrsim~⥴~rarrtl~↣~rarrw~↝~ratail~⤚~ratio~∶~rationals~ℚ~rbarr~⤍~rbbrk~❳~rbrace~}~rbrack~]~rbrke~⦌~rbrksld~⦎~rbrkslu~⦐~rcaron~ř~rcedil~ŗ~rcub~}~rcy~р~rdca~⤷~rdldhar~⥩~rdquor~”~rdsh~↳~realine~ℛ~realpart~ℜ~reals~ℝ~rect~▭~rfisht~⥽~rfr~𝔯~rhard~⇁~rharu~⇀~rharul~⥬~rhov~ϱ~rightarrow~→~rightarrowtail~↣~rightharpoondown~⇁~rightharpoonup~⇀~rightleftarrows~⇄~rightleftharpoons~⇌~rightrightarrows~⇉~rightsquigarrow~↝~rightthreetimes~⋌~ring~˚~risingdotseq~≓~rlarr~⇄~rlhar~⇌~rmoust~⎱~rmoustache~⎱~rnmid~⫮~roang~⟭~roarr~⇾~robrk~⟧~ropar~⦆~ropf~𝕣~roplus~⨮~rotimes~⨵~rpar~)~rpargt~⦔~rppolint~⨒~rrarr~⇉~rscr~𝓇~rsh~↱~rsqb~]~rsquor~’~rthree~⋌~rtimes~⋊~rtri~▹~rtrie~⊵~rtrif~▸~rtriltri~⧎~ruluhar~⥨~rx~℞~sacute~ś~sc~≻~scE~⪴~scap~⪸~sccue~≽~sce~⪰~scedil~ş~scirc~ŝ~scnE~⪶~scnap~⪺~scnsim~⋩~scpolint~⨓~scsim~≿~scy~с~sdotb~⊡~sdote~⩦~seArr~⇘~searhk~⤥~searr~↘~searrow~↘~semi~;~seswar~⤩~setminus~∖~setmn~∖~sext~✶~sfr~𝔰~sfrown~⌢~sharp~♯~shchcy~щ~shcy~ш~shortmid~∣~shortparallel~∥~sigmav~ς~simdot~⩪~sime~≃~simeq~≃~simg~⪞~simgE~⪠~siml~⪝~simlE~⪟~simne~≆~simplus~⨤~simrarr~⥲~slarr~←~smallsetminus~∖~smashp~⨳~smeparsl~⧤~smid~∣~smile~⌣~smt~⪪~smte~⪬~smtes~⪬︀~softcy~ь~sol~/~solb~⧄~solbar~⌿~sopf~𝕤~spadesuit~♠~spar~∥~sqcap~⊓~sqcaps~⊓︀~sqcup~⊔~sqcups~⊔︀~sqsub~⊏~sqsube~⊑~sqsubset~⊏~sqsubseteq~⊑~sqsup~⊐~sqsupe~⊒~sqsupset~⊐~sqsupseteq~⊒~squ~□~square~□~squarf~▪~squf~▪~srarr~→~sscr~𝓈~ssetmn~∖~ssmile~⌣~sstarf~⋆~star~☆~starf~★~straightepsilon~ϵ~straightphi~ϕ~strns~¯~subE~⫅~subdot~⪽~subedot~⫃~submult~⫁~subnE~⫋~subne~⊊~subplus~⪿~subrarr~⥹~subset~⊂~subseteq~⊆~subseteqq~⫅~subsetneq~⊊~subsetneqq~⫋~subsim~⫇~subsub~⫕~subsup~⫓~succ~≻~succapprox~⪸~succcurlyeq~≽~succeq~⪰~succnapprox~⪺~succneqq~⪶~succnsim~⋩~succsim~≿~sung~♪~supE~⫆~supdot~⪾~supdsub~⫘~supedot~⫄~suphsol~⟉~suphsub~⫗~suplarr~⥻~supmult~⫂~supnE~⫌~supne~⊋~supplus~⫀~supset~⊃~supseteq~⊇~supseteqq~⫆~supsetneq~⊋~supsetneqq~⫌~supsim~⫈~supsub~⫔~supsup~⫖~swArr~⇙~swarhk~⤦~swarr~↙~swarrow~↙~swnwar~⤪~target~⌖~tbrk~⎴~tcaron~ť~tcedil~ţ~tcy~т~tdot~⃛~telrec~⌕~tfr~𝔱~therefore~∴~thetav~ϑ~thickapprox~≈~thicksim~∼~thkap~≈~thksim~∼~timesb~⊠~timesbar~⨱~timesd~⨰~tint~∭~toea~⤨~top~⊤~topbot~⌶~topcir~⫱~topf~𝕥~topfork~⫚~tosa~⤩~tprime~‴~triangle~▵~triangledown~▿~triangleleft~◃~trianglelefteq~⊴~triangleq~≜~triangleright~▹~trianglerighteq~⊵~tridot~◬~trie~≜~triminus~⨺~triplus~⨹~trisb~⧍~tritime~⨻~trpezium~⏢~tscr~𝓉~tscy~ц~tshcy~ћ~tstrok~ŧ~twixt~≬~twoheadleftarrow~↞~twoheadrightarrow~↠~uHar~⥣~ubrcy~ў~ubreve~ŭ~ucy~у~udarr~⇅~udblac~ű~udhar~⥮~ufisht~⥾~ufr~𝔲~uharl~↿~uharr~↾~uhblk~▀~ulcorn~⌜~ulcorner~⌜~ulcrop~⌏~ultri~◸~umacr~ū~uogon~ų~uopf~𝕦~uparrow~↑~updownarrow~↕~upharpoonleft~↿~upharpoonright~↾~uplus~⊎~upsi~υ~upuparrows~⇈~urcorn~⌝~urcorner~⌝~urcrop~⌎~uring~ů~urtri~◹~uscr~𝓊~utdot~⋰~utilde~ũ~utri~▵~utrif~▴~uuarr~⇈~uwangle~⦧~vArr~⇕~vBar~⫨~vBarv~⫩~vDash~⊨~vangrt~⦜~varepsilon~ϵ~varkappa~ϰ~varnothing~∅~varphi~ϕ~varpi~ϖ~varpropto~∝~varr~↕~varrho~ϱ~varsigma~ς~varsubsetneq~⊊︀~varsubsetneqq~⫋︀~varsupsetneq~⊋︀~varsupsetneqq~⫌︀~vartheta~ϑ~vartriangleleft~⊲~vartriangleright~⊳~vcy~в~vdash~⊢~vee~∨~veebar~⊻~veeeq~≚~vellip~⋮~verbar~|~vert~|~vfr~𝔳~vltri~⊲~vnsub~⊂⃒~vnsup~⊃⃒~vopf~𝕧~vprop~∝~vrtri~⊳~vscr~𝓋~vsubnE~⫋︀~vsubne~⊊︀~vsupnE~⫌︀~vsupne~⊋︀~vzigzag~⦚~wcirc~ŵ~wedbar~⩟~wedge~∧~wedgeq~≙~wfr~𝔴~wopf~𝕨~wp~℘~wr~≀~wreath~≀~wscr~𝓌~xcap~⋂~xcirc~◯~xcup~⋃~xdtri~▽~xfr~𝔵~xhArr~⟺~xharr~⟷~xlArr~⟸~xlarr~⟵~xmap~⟼~xnis~⋻~xodot~⨀~xopf~𝕩~xoplus~⨁~xotime~⨂~xrArr~⟹~xrarr~⟶~xscr~𝓍~xsqcup~⨆~xuplus~⨄~xutri~△~xvee~⋁~xwedge~⋀~yacy~я~ycirc~ŷ~ycy~ы~yfr~𝔶~yicy~ї~yopf~𝕪~yscr~𝓎~yucy~ю~zacute~ź~zcaron~ž~zcy~з~zdot~ż~zeetrf~ℨ~zfr~𝔷~zhcy~ж~zigrarr~⇝~zopf~𝕫~zscr~𝓏~~AMP~&~COPY~©~GT~>~LT~<~QUOT~\"~REG~®", exports.namedReferences['html4']); +//# sourceMappingURL=named-references.js.map + +/***/ }), + +/***/ 53438: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.numericUnicodeMap = void 0; +exports.numericUnicodeMap = { + 0: 65533, + 128: 8364, + 130: 8218, + 131: 402, + 132: 8222, + 133: 8230, + 134: 8224, + 135: 8225, + 136: 710, + 137: 8240, + 138: 352, + 139: 8249, + 140: 338, + 142: 381, + 145: 8216, + 146: 8217, + 147: 8220, + 148: 8221, + 149: 8226, + 150: 8211, + 151: 8212, + 152: 732, + 153: 8482, + 154: 353, + 155: 8250, + 156: 339, + 158: 382, + 159: 376 +}; +//# sourceMappingURL=numeric-unicode-map.js.map + +/***/ }), + +/***/ 69718: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.highSurrogateTo = exports.highSurrogateFrom = exports.getCodePoint = exports.fromCodePoint = void 0; +exports.fromCodePoint = String.fromCodePoint || + function (astralCodePoint) { + return String.fromCharCode(Math.floor((astralCodePoint - 0x10000) / 0x400) + 0xd800, ((astralCodePoint - 0x10000) % 0x400) + 0xdc00); + }; +// @ts-expect-error - String.prototype.codePointAt might not exist in older node versions +exports.getCodePoint = String.prototype.codePointAt + ? function (input, position) { + return input.codePointAt(position); + } + : function (input, position) { + return (input.charCodeAt(position) - 0xd800) * 0x400 + input.charCodeAt(position + 1) - 0xdc00 + 0x10000; + }; +exports.highSurrogateFrom = 0xd800; +exports.highSurrogateTo = 0xdbff; +//# sourceMappingURL=surrogate-pairs.js.map + +/***/ }), + +/***/ 41969: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* eslint-disable node/no-missing-require */ + +function getPackageJSON() { + return __nccwpck_require__(72721); +} + +exports.getPackageJSON = getPackageJSON; + + +/***/ }), + +/***/ 50591: +/***/ ((module) => { + +(()=>{"use strict";var t={d:(e,n)=>{for(var i in n)t.o(n,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:n[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{XMLBuilder:()=>ft,XMLParser:()=>st,XMLValidator:()=>mt});const n=":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",i=new RegExp("^["+n+"]["+n+"\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$");function s(t,e){const n=[];let i=e.exec(t);for(;i;){const s=[];s.startIndex=e.lastIndex-i[0].length;const r=i.length;for(let t=0;t"!==t[o]&&" "!==t[o]&&"\t"!==t[o]&&"\n"!==t[o]&&"\r"!==t[o];o++)f+=t[o];if(f=f.trim(),"/"===f[f.length-1]&&(f=f.substring(0,f.length-1),o--),!r(f)){let e;return e=0===f.trim().length?"Invalid space after '<'.":"Tag '"+f+"' is an invalid name.",x("InvalidTag",e,N(t,o))}const p=c(t,o);if(!1===p)return x("InvalidAttr","Attributes for '"+f+"' have open quote.",N(t,o));let b=p.value;if(o=p.index,"/"===b[b.length-1]){const n=o-b.length;b=b.substring(0,b.length-1);const s=g(b,e);if(!0!==s)return x(s.err.code,s.err.msg,N(t,n+s.err.line));i=!0}else if(d){if(!p.tagClosed)return x("InvalidTag","Closing tag '"+f+"' doesn't have proper closing.",N(t,o));if(b.trim().length>0)return x("InvalidTag","Closing tag '"+f+"' can't have attributes or invalid starting.",N(t,a));if(0===n.length)return x("InvalidTag","Closing tag '"+f+"' has not been opened.",N(t,a));{const e=n.pop();if(f!==e.tagName){let n=N(t,e.tagStartPos);return x("InvalidTag","Expected closing tag '"+e.tagName+"' (opened in line "+n.line+", col "+n.col+") instead of closing tag '"+f+"'.",N(t,a))}0==n.length&&(s=!0)}}else{const r=g(b,e);if(!0!==r)return x(r.err.code,r.err.msg,N(t,o-b.length+r.err.line));if(!0===s)return x("InvalidXml","Multiple possible root nodes found.",N(t,o));-1!==e.unpairedTags.indexOf(f)||n.push({tagName:f,tagStartPos:a}),i=!0}for(o++;o0)||x("InvalidXml","Invalid '"+JSON.stringify(n.map((t=>t.tagName)),null,4).replace(/\r?\n/g,"")+"' found.",{line:1,col:1}):x("InvalidXml","Start tag expected.",1)}function l(t){return" "===t||"\t"===t||"\n"===t||"\r"===t}function u(t,e){const n=e;for(;e5&&"xml"===i)return x("InvalidXml","XML declaration allowed only at the start of the document.",N(t,e));if("?"==t[e]&&">"==t[e+1]){e++;break}}return e}function h(t,e){if(t.length>e+5&&"-"===t[e+1]&&"-"===t[e+2]){for(e+=3;e"===t[e+2]){e+=2;break}}else if(t.length>e+8&&"D"===t[e+1]&&"O"===t[e+2]&&"C"===t[e+3]&&"T"===t[e+4]&&"Y"===t[e+5]&&"P"===t[e+6]&&"E"===t[e+7]){let n=1;for(e+=8;e"===t[e]&&(n--,0===n))break}else if(t.length>e+9&&"["===t[e+1]&&"C"===t[e+2]&&"D"===t[e+3]&&"A"===t[e+4]&&"T"===t[e+5]&&"A"===t[e+6]&&"["===t[e+7])for(e+=8;e"===t[e+2]){e+=2;break}return e}const d='"',f="'";function c(t,e){let n="",i="",s=!1;for(;e"===t[e]&&""===i){s=!0;break}n+=t[e]}return""===i&&{value:n,index:e,tagClosed:s}}const p=new RegExp("(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['\"])(([\\s\\S])*?)\\5)?","g");function g(t,e){const n=s(t,p),i={};for(let t=0;t!1,commentPropName:!1,unpairedTags:[],processEntities:!0,htmlEntities:!1,ignoreDeclaration:!1,ignorePiTags:!1,transformTagName:!1,transformAttributeName:!1,updateTag:function(t,e,n){return t},captureMetaData:!1};let y;y="function"!=typeof Symbol?"@@xmlMetadata":Symbol("XML Node Metadata");class T{constructor(t){this.tagname=t,this.child=[],this[":@"]={}}add(t,e){"__proto__"===t&&(t="#__proto__"),this.child.push({[t]:e})}addChild(t,e){"__proto__"===t.tagname&&(t.tagname="#__proto__"),t[":@"]&&Object.keys(t[":@"]).length>0?this.child.push({[t.tagname]:t.child,":@":t[":@"]}):this.child.push({[t.tagname]:t.child}),void 0!==e&&(this.child[this.child.length-1][y]={startIndex:e})}static getMetaDataSymbol(){return y}}function w(t,e){const n={};if("O"!==t[e+3]||"C"!==t[e+4]||"T"!==t[e+5]||"Y"!==t[e+6]||"P"!==t[e+7]||"E"!==t[e+8])throw new Error("Invalid Tag instead of DOCTYPE");{e+=9;let i=1,s=!1,r=!1,o="";for(;e"===t[e]){if(r?"-"===t[e-1]&&"-"===t[e-2]&&(r=!1,i--):i--,0===i)break}else"["===t[e]?s=!0:o+=t[e];else{if(s&&C(t,"!ENTITY",e)){let i,s;e+=7,[i,s,e]=O(t,e+1),-1===s.indexOf("&")&&(n[i]={regx:RegExp(`&${i};`,"g"),val:s})}else if(s&&C(t,"!ELEMENT",e)){e+=8;const{index:n}=S(t,e+1);e=n}else if(s&&C(t,"!ATTLIST",e))e+=8;else if(s&&C(t,"!NOTATION",e)){e+=9;const{index:n}=A(t,e+1);e=n}else{if(!C(t,"!--",e))throw new Error("Invalid DOCTYPE");r=!0}i++,o=""}if(0!==i)throw new Error("Unclosed DOCTYPE")}return{entities:n,i:e}}const P=(t,e)=>{for(;e{for(const n of t){if("string"==typeof n&&e===n)return!0;if(n instanceof RegExp&&n.test(e))return!0}}:()=>!1}class k{constructor(t){this.options=t,this.currentNode=null,this.tagsNodeStack=[],this.docTypeEntities={},this.lastEntities={apos:{regex:/&(apos|#39|#x27);/g,val:"'"},gt:{regex:/&(gt|#62|#x3E);/g,val:">"},lt:{regex:/&(lt|#60|#x3C);/g,val:"<"},quot:{regex:/&(quot|#34|#x22);/g,val:'"'}},this.ampEntity={regex:/&(amp|#38|#x26);/g,val:"&"},this.htmlEntities={space:{regex:/&(nbsp|#160);/g,val:" "},cent:{regex:/&(cent|#162);/g,val:"¢"},pound:{regex:/&(pound|#163);/g,val:"£"},yen:{regex:/&(yen|#165);/g,val:"¥"},euro:{regex:/&(euro|#8364);/g,val:"€"},copyright:{regex:/&(copy|#169);/g,val:"©"},reg:{regex:/&(reg|#174);/g,val:"®"},inr:{regex:/&(inr|#8377);/g,val:"₹"},num_dec:{regex:/&#([0-9]{1,7});/g,val:(t,e)=>String.fromCodePoint(Number.parseInt(e,10))},num_hex:{regex:/&#x([0-9a-fA-F]{1,6});/g,val:(t,e)=>String.fromCodePoint(Number.parseInt(e,16))}},this.addExternalEntities=F,this.parseXml=X,this.parseTextData=L,this.resolveNameSpace=B,this.buildAttributesMap=G,this.isItStopNode=Z,this.replaceEntitiesValue=R,this.readStopNodeData=J,this.saveTextToParentTag=q,this.addChild=Y,this.ignoreAttributesFn=_(this.options.ignoreAttributes)}}function F(t){const e=Object.keys(t);for(let n=0;n0)){o||(t=this.replaceEntitiesValue(t));const i=this.options.tagValueProcessor(e,t,n,s,r);return null==i?t:typeof i!=typeof t||i!==t?i:this.options.trimValues||t.trim()===t?H(t,this.options.parseTagValue,this.options.numberParseOptions):t}}function B(t){if(this.options.removeNSPrefix){const e=t.split(":"),n="/"===t.charAt(0)?"/":"";if("xmlns"===e[0])return"";2===e.length&&(t=n+e[1])}return t}const U=new RegExp("([^\\s=]+)\\s*(=\\s*(['\"])([\\s\\S]*?)\\3)?","gm");function G(t,e,n){if(!0!==this.options.ignoreAttributes&&"string"==typeof t){const n=s(t,U),i=n.length,r={};for(let t=0;t",r,"Closing Tag is not closed.");let o=t.substring(r+2,e).trim();if(this.options.removeNSPrefix){const t=o.indexOf(":");-1!==t&&(o=o.substr(t+1))}this.options.transformTagName&&(o=this.options.transformTagName(o)),n&&(i=this.saveTextToParentTag(i,n,s));const a=s.substring(s.lastIndexOf(".")+1);if(o&&-1!==this.options.unpairedTags.indexOf(o))throw new Error(`Unpaired tag can not be used as closing tag: `);let l=0;a&&-1!==this.options.unpairedTags.indexOf(a)?(l=s.lastIndexOf(".",s.lastIndexOf(".")-1),this.tagsNodeStack.pop()):l=s.lastIndexOf("."),s=s.substring(0,l),n=this.tagsNodeStack.pop(),i="",r=e}else if("?"===t[r+1]){let e=z(t,r,!1,"?>");if(!e)throw new Error("Pi Tag is not closed.");if(i=this.saveTextToParentTag(i,n,s),this.options.ignoreDeclaration&&"?xml"===e.tagName||this.options.ignorePiTags);else{const t=new T(e.tagName);t.add(this.options.textNodeName,""),e.tagName!==e.tagExp&&e.attrExpPresent&&(t[":@"]=this.buildAttributesMap(e.tagExp,s,e.tagName)),this.addChild(n,t,s,r)}r=e.closeIndex+1}else if("!--"===t.substr(r+1,3)){const e=W(t,"--\x3e",r+4,"Comment is not closed.");if(this.options.commentPropName){const o=t.substring(r+4,e-2);i=this.saveTextToParentTag(i,n,s),n.add(this.options.commentPropName,[{[this.options.textNodeName]:o}])}r=e}else if("!D"===t.substr(r+1,2)){const e=w(t,r);this.docTypeEntities=e.entities,r=e.i}else if("!["===t.substr(r+1,2)){const e=W(t,"]]>",r,"CDATA is not closed.")-2,o=t.substring(r+9,e);i=this.saveTextToParentTag(i,n,s);let a=this.parseTextData(o,n.tagname,s,!0,!1,!0,!0);null==a&&(a=""),this.options.cdataPropName?n.add(this.options.cdataPropName,[{[this.options.textNodeName]:o}]):n.add(this.options.textNodeName,a),r=e+2}else{let o=z(t,r,this.options.removeNSPrefix),a=o.tagName;const l=o.rawTagName;let u=o.tagExp,h=o.attrExpPresent,d=o.closeIndex;this.options.transformTagName&&(a=this.options.transformTagName(a)),n&&i&&"!xml"!==n.tagname&&(i=this.saveTextToParentTag(i,n,s,!1));const f=n;f&&-1!==this.options.unpairedTags.indexOf(f.tagname)&&(n=this.tagsNodeStack.pop(),s=s.substring(0,s.lastIndexOf("."))),a!==e.tagname&&(s+=s?"."+a:a);const c=r;if(this.isItStopNode(this.options.stopNodes,s,a)){let e="";if(u.length>0&&u.lastIndexOf("/")===u.length-1)"/"===a[a.length-1]?(a=a.substr(0,a.length-1),s=s.substr(0,s.length-1),u=a):u=u.substr(0,u.length-1),r=o.closeIndex;else if(-1!==this.options.unpairedTags.indexOf(a))r=o.closeIndex;else{const n=this.readStopNodeData(t,l,d+1);if(!n)throw new Error(`Unexpected end of ${l}`);r=n.i,e=n.tagContent}const i=new T(a);a!==u&&h&&(i[":@"]=this.buildAttributesMap(u,s,a)),e&&(e=this.parseTextData(e,a,s,!0,h,!0,!0)),s=s.substr(0,s.lastIndexOf(".")),i.add(this.options.textNodeName,e),this.addChild(n,i,s,c)}else{if(u.length>0&&u.lastIndexOf("/")===u.length-1){"/"===a[a.length-1]?(a=a.substr(0,a.length-1),s=s.substr(0,s.length-1),u=a):u=u.substr(0,u.length-1),this.options.transformTagName&&(a=this.options.transformTagName(a));const t=new T(a);a!==u&&h&&(t[":@"]=this.buildAttributesMap(u,s,a)),this.addChild(n,t,s,c),s=s.substr(0,s.lastIndexOf("."))}else{const t=new T(a);this.tagsNodeStack.push(n),a!==u&&h&&(t[":@"]=this.buildAttributesMap(u,s,a)),this.addChild(n,t,s,c),n=t}i="",r=d}}else i+=t[r];return e.child};function Y(t,e,n,i){this.options.captureMetaData||(i=void 0);const s=this.options.updateTag(e.tagname,n,e[":@"]);!1===s||("string"==typeof s?(e.tagname=s,t.addChild(e,i)):t.addChild(e,i))}const R=function(t){if(this.options.processEntities){for(let e in this.docTypeEntities){const n=this.docTypeEntities[e];t=t.replace(n.regx,n.val)}for(let e in this.lastEntities){const n=this.lastEntities[e];t=t.replace(n.regex,n.val)}if(this.options.htmlEntities)for(let e in this.htmlEntities){const n=this.htmlEntities[e];t=t.replace(n.regex,n.val)}t=t.replace(this.ampEntity.regex,this.ampEntity.val)}return t};function q(t,e,n,i){return t&&(void 0===i&&(i=0===e.child.length),void 0!==(t=this.parseTextData(t,e.tagname,n,!1,!!e[":@"]&&0!==Object.keys(e[":@"]).length,i))&&""!==t&&e.add(this.options.textNodeName,t),t=""),t}function Z(t,e,n){const i="*."+n;for(const n in t){const s=t[n];if(i===s||e===s)return!0}return!1}function W(t,e,n,i){const s=t.indexOf(e,n);if(-1===s)throw new Error(i);return s+e.length-1}function z(t,e,n,i=">"){const s=function(t,e,n=">"){let i,s="";for(let r=e;r",n,`${e} is not closed`);if(t.substring(n+2,r).trim()===e&&(s--,0===s))return{tagContent:t.substring(i,n),i:r};n=r}else if("?"===t[n+1])n=W(t,"?>",n+1,"StopNode is not closed.");else if("!--"===t.substr(n+1,3))n=W(t,"--\x3e",n+3,"StopNode is not closed.");else if("!["===t.substr(n+1,2))n=W(t,"]]>",n,"StopNode is not closed.")-2;else{const i=z(t,n,">");i&&((i&&i.tagName)===e&&"/"!==i.tagExp[i.tagExp.length-1]&&s++,n=i.closeIndex)}}function H(t,e,n){if(e&&"string"==typeof t){const e=t.trim();return"true"===e||"false"!==e&&function(t,e={}){if(e=Object.assign({},V,e),!t||"string"!=typeof t)return t;let n=t.trim();if(void 0!==e.skipLike&&e.skipLike.test(n))return t;if("0"===t)return 0;if(e.hex&&j.test(n))return function(t){if(parseInt)return parseInt(t,16);if(Number.parseInt)return Number.parseInt(t,16);if(window&&window.parseInt)return window.parseInt(t,16);throw new Error("parseInt, Number.parseInt, window.parseInt are not supported")}(n);if(-1!==n.search(/.+[eE].+/))return function(t,e,n){if(!n.eNotation)return t;const i=e.match(M);if(i){let s=i[1]||"";const r=-1===i[3].indexOf("e")?"E":"e",o=i[2],a=s?t[o.length+1]===r:t[o.length]===r;return o.length>1&&a?t:1!==o.length||!i[3].startsWith(`.${r}`)&&i[3][0]!==r?n.leadingZeros&&!a?(e=(i[1]||"")+i[3],Number(e)):t:Number(e)}return t}(t,n,e);{const s=D.exec(n);if(s){const r=s[1]||"",o=s[2];let a=(i=s[3])&&-1!==i.indexOf(".")?("."===(i=i.replace(/0+$/,""))?i="0":"."===i[0]?i="0"+i:"."===i[i.length-1]&&(i=i.substring(0,i.length-1)),i):i;const l=r?"."===t[o.length+1]:"."===t[o.length];if(!e.leadingZeros&&(o.length>1||1===o.length&&!l))return t;{const i=Number(n),s=String(i);if(0===i||-0===i)return i;if(-1!==s.search(/[eE]/))return e.eNotation?i:t;if(-1!==n.indexOf("."))return"0"===s||s===a||s===`${r}${a}`?i:t;let l=o?a:n;return o?l===s||r+l===s?i:t:l===s||l===r+s?i:t}}return t}var i}(t,n)}return void 0!==t?t:""}const K=T.getMetaDataSymbol();function Q(t,e){return tt(t,e)}function tt(t,e,n){let i;const s={};for(let r=0;r0&&(s[e.textNodeName]=i):void 0!==i&&(s[e.textNodeName]=i),s}function et(t){const e=Object.keys(t);for(let t=0;t0&&(n="\n"),ot(t,e,"",n)}function ot(t,e,n,i){let s="",r=!1;for(let o=0;o`,r=!1;continue}if(l===e.commentPropName){s+=i+`\x3c!--${a[l][0][e.textNodeName]}--\x3e`,r=!0;continue}if("?"===l[0]){const t=lt(a[":@"],e),n="?xml"===l?"":i;let o=a[l][0][e.textNodeName];o=0!==o.length?" "+o:"",s+=n+`<${l}${o}${t}?>`,r=!0;continue}let h=i;""!==h&&(h+=e.indentBy);const d=i+`<${l}${lt(a[":@"],e)}`,f=ot(a[l],e,u,h);-1!==e.unpairedTags.indexOf(l)?e.suppressUnpairedNode?s+=d+">":s+=d+"/>":f&&0!==f.length||!e.suppressEmptyNode?f&&f.endsWith(">")?s+=d+`>${f}${i}`:(s+=d+">",f&&""!==i&&(f.includes("/>")||f.includes("`):s+=d+"/>",r=!0}return s}function at(t){const e=Object.keys(t);for(let n=0;n0&&e.processEntities)for(let n=0;n","g"),val:">"},{regex:new RegExp("<","g"),val:"<"},{regex:new RegExp("'","g"),val:"'"},{regex:new RegExp('"',"g"),val:"""}],processEntities:!0,stopNodes:[],oneListGroup:!1};function ft(t){this.options=Object.assign({},dt,t),!0===this.options.ignoreAttributes||this.options.attributesGroupName?this.isAttribute=function(){return!1}:(this.ignoreAttributesFn=_(this.options.ignoreAttributes),this.attrPrefixLen=this.options.attributeNamePrefix.length,this.isAttribute=gt),this.processTextOrObjNode=ct,this.options.format?(this.indentate=pt,this.tagEndChar=">\n",this.newLine="\n"):(this.indentate=function(){return""},this.tagEndChar=">",this.newLine="")}function ct(t,e,n,i){const s=this.j2x(t,n+1,i.concat(e));return void 0!==t[this.options.textNodeName]&&1===Object.keys(t).length?this.buildTextValNode(t[this.options.textNodeName],e,s.attrStr,n):this.buildObjectNode(s.val,e,s.attrStr,n)}function pt(t){return this.options.indentBy.repeat(t)}function gt(t){return!(!t.startsWith(this.options.attributeNamePrefix)||t===this.options.textNodeName)&&t.substr(this.attrPrefixLen)}ft.prototype.build=function(t){return this.options.preserveOrder?rt(t,this.options):(Array.isArray(t)&&this.options.arrayNodeName&&this.options.arrayNodeName.length>1&&(t={[this.options.arrayNodeName]:t}),this.j2x(t,0,[]).val)},ft.prototype.j2x=function(t,e,n){let i="",s="";const r=n.join(".");for(let o in t)if(Object.prototype.hasOwnProperty.call(t,o))if(void 0===t[o])this.isAttribute(o)&&(s+="");else if(null===t[o])this.isAttribute(o)||o===this.options.cdataPropName?s+="":"?"===o[0]?s+=this.indentate(e)+"<"+o+"?"+this.tagEndChar:s+=this.indentate(e)+"<"+o+"/"+this.tagEndChar;else if(t[o]instanceof Date)s+=this.buildTextValNode(t[o],o,"",e);else if("object"!=typeof t[o]){const n=this.isAttribute(o);if(n&&!this.ignoreAttributesFn(n,r))i+=this.buildAttrPairStr(n,""+t[o]);else if(!n)if(o===this.options.textNodeName){let e=this.options.tagValueProcessor(o,""+t[o]);s+=this.replaceEntitiesValue(e)}else s+=this.buildTextValNode(t[o],o,"",e)}else if(Array.isArray(t[o])){const i=t[o].length;let r="",a="";for(let l=0;l"+t+s}},ft.prototype.closeTag=function(t){let e="";return-1!==this.options.unpairedTags.indexOf(t)?this.options.suppressUnpairedNode||(e="/"):e=this.options.suppressEmptyNode?"/":`>`+this.newLine;if(!1!==this.options.commentPropName&&e===this.options.commentPropName)return this.indentate(i)+`\x3c!--${t}--\x3e`+this.newLine;if("?"===e[0])return this.indentate(i)+"<"+e+n+"?"+this.tagEndChar;{let s=this.options.tagValueProcessor(e,t);return s=this.replaceEntitiesValue(s),""===s?this.indentate(i)+"<"+e+n+this.closeTag(e)+this.tagEndChar:this.indentate(i)+"<"+e+n+">"+s+"0&&this.options.processEntities)for(let e=0;e { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/client-s3","description":"AWS SDK for JavaScript S3 Client for Node.js, Browser and React Native","version":"3.859.0","scripts":{"build":"concurrently \'yarn:build:cjs\' \'yarn:build:es\' \'yarn:build:types\'","build:cjs":"node ../../scripts/compilation/inline client-s3","build:es":"tsc -p tsconfig.es.json","build:include:deps":"lerna run --scope $npm_package_name --include-dependencies build","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"rimraf ./dist-* && rimraf *.tsbuildinfo","extract:docs":"api-extractor run --local","generate:client":"node ../../scripts/generate-clients/single-service --solo s3","test":"yarn g:vitest run","test:browser":"node ./test/browser-build/esbuild && yarn g:vitest run -c vitest.config.browser.ts","test:browser:watch":"node ./test/browser-build/esbuild && yarn g:vitest watch -c vitest.config.browser.ts","test:e2e":"yarn g:vitest run -c vitest.config.e2e.ts && yarn test:browser","test:e2e:watch":"yarn g:vitest watch -c vitest.config.e2e.ts","test:integration":"yarn g:vitest run -c vitest.config.integ.ts","test:integration:watch":"yarn g:vitest watch -c vitest.config.integ.ts","test:watch":"yarn g:vitest watch"},"main":"./dist-cjs/index.js","types":"./dist-types/index.d.ts","module":"./dist-es/index.js","sideEffects":false,"dependencies":{"@aws-crypto/sha1-browser":"5.2.0","@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"3.858.0","@aws-sdk/credential-provider-node":"3.859.0","@aws-sdk/middleware-bucket-endpoint":"3.840.0","@aws-sdk/middleware-expect-continue":"3.840.0","@aws-sdk/middleware-flexible-checksums":"3.858.0","@aws-sdk/middleware-host-header":"3.840.0","@aws-sdk/middleware-location-constraint":"3.840.0","@aws-sdk/middleware-logger":"3.840.0","@aws-sdk/middleware-recursion-detection":"3.840.0","@aws-sdk/middleware-sdk-s3":"3.858.0","@aws-sdk/middleware-ssec":"3.840.0","@aws-sdk/middleware-user-agent":"3.858.0","@aws-sdk/region-config-resolver":"3.840.0","@aws-sdk/signature-v4-multi-region":"3.858.0","@aws-sdk/types":"3.840.0","@aws-sdk/util-endpoints":"3.848.0","@aws-sdk/util-user-agent-browser":"3.840.0","@aws-sdk/util-user-agent-node":"3.858.0","@aws-sdk/xml-builder":"3.821.0","@smithy/config-resolver":"^4.1.4","@smithy/core":"^3.7.2","@smithy/eventstream-serde-browser":"^4.0.4","@smithy/eventstream-serde-config-resolver":"^4.1.2","@smithy/eventstream-serde-node":"^4.0.4","@smithy/fetch-http-handler":"^5.1.0","@smithy/hash-blob-browser":"^4.0.4","@smithy/hash-node":"^4.0.4","@smithy/hash-stream-node":"^4.0.4","@smithy/invalid-dependency":"^4.0.4","@smithy/md5-js":"^4.0.4","@smithy/middleware-content-length":"^4.0.4","@smithy/middleware-endpoint":"^4.1.17","@smithy/middleware-retry":"^4.1.18","@smithy/middleware-serde":"^4.0.8","@smithy/middleware-stack":"^4.0.4","@smithy/node-config-provider":"^4.1.3","@smithy/node-http-handler":"^4.1.0","@smithy/protocol-http":"^5.1.2","@smithy/smithy-client":"^4.4.9","@smithy/types":"^4.3.1","@smithy/url-parser":"^4.0.4","@smithy/util-base64":"^4.0.0","@smithy/util-body-length-browser":"^4.0.0","@smithy/util-body-length-node":"^4.0.0","@smithy/util-defaults-mode-browser":"^4.0.25","@smithy/util-defaults-mode-node":"^4.0.25","@smithy/util-endpoints":"^3.0.6","@smithy/util-middleware":"^4.0.4","@smithy/util-retry":"^4.0.6","@smithy/util-stream":"^4.2.3","@smithy/util-utf8":"^4.0.0","@smithy/util-waiter":"^4.0.6","@types/uuid":"^9.0.1","tslib":"^2.6.2","uuid":"^9.0.1"},"devDependencies":{"@aws-sdk/signature-v4-crt":"3.858.0","@tsconfig/node18":"18.2.4","@types/node":"^18.19.69","concurrently":"7.0.0","downlevel-dts":"0.10.1","rimraf":"3.0.2","typescript":"~5.8.3"},"engines":{"node":">=18.0.0"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["dist-*/**"],"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","browser":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.browser"},"react-native":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.native"},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-s3","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-s3"}}'); + +/***/ }), + +/***/ 45188: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/client-sso","description":"AWS SDK for JavaScript Sso Client for Node.js, Browser and React Native","version":"3.858.0","scripts":{"build":"concurrently \'yarn:build:cjs\' \'yarn:build:es\' \'yarn:build:types\'","build:cjs":"node ../../scripts/compilation/inline client-sso","build:es":"tsc -p tsconfig.es.json","build:include:deps":"lerna run --scope $npm_package_name --include-dependencies build","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"rimraf ./dist-* && rimraf *.tsbuildinfo","extract:docs":"api-extractor run --local","generate:client":"node ../../scripts/generate-clients/single-service --solo sso"},"main":"./dist-cjs/index.js","types":"./dist-types/index.d.ts","module":"./dist-es/index.js","sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"3.858.0","@aws-sdk/middleware-host-header":"3.840.0","@aws-sdk/middleware-logger":"3.840.0","@aws-sdk/middleware-recursion-detection":"3.840.0","@aws-sdk/middleware-user-agent":"3.858.0","@aws-sdk/region-config-resolver":"3.840.0","@aws-sdk/types":"3.840.0","@aws-sdk/util-endpoints":"3.848.0","@aws-sdk/util-user-agent-browser":"3.840.0","@aws-sdk/util-user-agent-node":"3.858.0","@smithy/config-resolver":"^4.1.4","@smithy/core":"^3.7.2","@smithy/fetch-http-handler":"^5.1.0","@smithy/hash-node":"^4.0.4","@smithy/invalid-dependency":"^4.0.4","@smithy/middleware-content-length":"^4.0.4","@smithy/middleware-endpoint":"^4.1.17","@smithy/middleware-retry":"^4.1.18","@smithy/middleware-serde":"^4.0.8","@smithy/middleware-stack":"^4.0.4","@smithy/node-config-provider":"^4.1.3","@smithy/node-http-handler":"^4.1.0","@smithy/protocol-http":"^5.1.2","@smithy/smithy-client":"^4.4.9","@smithy/types":"^4.3.1","@smithy/url-parser":"^4.0.4","@smithy/util-base64":"^4.0.0","@smithy/util-body-length-browser":"^4.0.0","@smithy/util-body-length-node":"^4.0.0","@smithy/util-defaults-mode-browser":"^4.0.25","@smithy/util-defaults-mode-node":"^4.0.25","@smithy/util-endpoints":"^3.0.6","@smithy/util-middleware":"^4.0.4","@smithy/util-retry":"^4.0.6","@smithy/util-utf8":"^4.0.0","tslib":"^2.6.2"},"devDependencies":{"@tsconfig/node18":"18.2.4","@types/node":"^18.19.69","concurrently":"7.0.0","downlevel-dts":"0.10.1","rimraf":"3.0.2","typescript":"~5.8.3"},"engines":{"node":">=18.0.0"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["dist-*/**"],"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","browser":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.browser"},"react-native":{"./dist-es/runtimeConfig":"./dist-es/runtimeConfig.native"},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/clients/client-sso","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-sso"}}'); + +/***/ }), + +/***/ 39955: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@aws-sdk/nested-clients","version":"3.858.0","description":"Nested clients for AWS SDK packages.","main":"./dist-cjs/index.js","module":"./dist-es/index.js","types":"./dist-types/index.d.ts","scripts":{"build":"yarn lint && concurrently \'yarn:build:cjs\' \'yarn:build:es\' \'yarn:build:types\'","build:cjs":"node ../../scripts/compilation/inline nested-clients","build:es":"tsc -p tsconfig.es.json","build:include:deps":"lerna run --scope $npm_package_name --include-dependencies build","build:types":"tsc -p tsconfig.types.json","build:types:downlevel":"downlevel-dts dist-types dist-types/ts3.4","clean":"rimraf ./dist-* && rimraf *.tsbuildinfo","lint":"node ../../scripts/validation/submodules-linter.js --pkg nested-clients","test":"yarn g:vitest run","test:watch":"yarn g:vitest watch"},"engines":{"node":">=18.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","dependencies":{"@aws-crypto/sha256-browser":"5.2.0","@aws-crypto/sha256-js":"5.2.0","@aws-sdk/core":"3.858.0","@aws-sdk/middleware-host-header":"3.840.0","@aws-sdk/middleware-logger":"3.840.0","@aws-sdk/middleware-recursion-detection":"3.840.0","@aws-sdk/middleware-user-agent":"3.858.0","@aws-sdk/region-config-resolver":"3.840.0","@aws-sdk/types":"3.840.0","@aws-sdk/util-endpoints":"3.848.0","@aws-sdk/util-user-agent-browser":"3.840.0","@aws-sdk/util-user-agent-node":"3.858.0","@smithy/config-resolver":"^4.1.4","@smithy/core":"^3.7.2","@smithy/fetch-http-handler":"^5.1.0","@smithy/hash-node":"^4.0.4","@smithy/invalid-dependency":"^4.0.4","@smithy/middleware-content-length":"^4.0.4","@smithy/middleware-endpoint":"^4.1.17","@smithy/middleware-retry":"^4.1.18","@smithy/middleware-serde":"^4.0.8","@smithy/middleware-stack":"^4.0.4","@smithy/node-config-provider":"^4.1.3","@smithy/node-http-handler":"^4.1.0","@smithy/protocol-http":"^5.1.2","@smithy/smithy-client":"^4.4.9","@smithy/types":"^4.3.1","@smithy/url-parser":"^4.0.4","@smithy/util-base64":"^4.0.0","@smithy/util-body-length-browser":"^4.0.0","@smithy/util-body-length-node":"^4.0.0","@smithy/util-defaults-mode-browser":"^4.0.25","@smithy/util-defaults-mode-node":"^4.0.25","@smithy/util-endpoints":"^3.0.6","@smithy/util-middleware":"^4.0.4","@smithy/util-retry":"^4.0.6","@smithy/util-utf8":"^4.0.0","tslib":"^2.6.2"},"devDependencies":{"concurrently":"7.0.0","downlevel-dts":"0.10.1","rimraf":"3.0.2","typescript":"~5.8.3"},"typesVersions":{"<4.0":{"dist-types/*":["dist-types/ts3.4/*"]}},"files":["./sso-oidc.d.ts","./sso-oidc.js","./sts.d.ts","./sts.js","dist-*/**"],"browser":{"./dist-es/submodules/sso-oidc/runtimeConfig":"./dist-es/submodules/sso-oidc/runtimeConfig.browser","./dist-es/submodules/sts/runtimeConfig":"./dist-es/submodules/sts/runtimeConfig.browser"},"react-native":{},"homepage":"https://github.com/aws/aws-sdk-js-v3/tree/main/packages/nested-clients","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"packages/nested-clients"},"exports":{"./sso-oidc":{"types":"./dist-types/submodules/sso-oidc/index.d.ts","module":"./dist-es/submodules/sso-oidc/index.js","node":"./dist-cjs/submodules/sso-oidc/index.js","import":"./dist-es/submodules/sso-oidc/index.js","require":"./dist-cjs/submodules/sso-oidc/index.js"},"./sts":{"types":"./dist-types/submodules/sts/index.d.ts","module":"./dist-es/submodules/sts/index.js","node":"./dist-cjs/submodules/sts/index.js","import":"./dist-es/submodules/sts/index.js","require":"./dist-cjs/submodules/sts/index.js"}}}'); + +/***/ }), + +/***/ 72721: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"@google-cloud/storage","description":"Cloud Storage Client Library for Node.js","version":"7.16.0","license":"Apache-2.0","author":"Google Inc.","engines":{"node":">=14"},"repository":"googleapis/nodejs-storage","main":"./build/cjs/src/index.js","types":"./build/cjs/src/index.d.ts","type":"module","exports":{".":{"import":{"types":"./build/esm/src/index.d.ts","default":"./build/esm/src/index.js"},"require":{"types":"./build/cjs/src/index.d.ts","default":"./build/cjs/src/index.js"}}},"files":["build/cjs/src","build/cjs/package.json","!build/cjs/src/**/*.map","build/esm/src","!build/esm/src/**/*.map"],"keywords":["google apis client","google api client","google apis","google api","google","google cloud platform","google cloud","cloud","google storage","storage"],"scripts":{"all-test":"npm test && npm run system-test && npm run samples-test","benchwrapper":"node bin/benchwrapper.js","check":"gts check","clean":"rm -rf build/","compile:cjs":"tsc -p ./tsconfig.cjs.json","compile:esm":"tsc -p .","compile":"npm run compile:cjs && npm run compile:esm","conformance-test":"mocha --parallel build/cjs/conformance-test/ --require build/cjs/conformance-test/globalHooks.js","docs-test":"linkinator docs","docs":"jsdoc -c .jsdoc.json","fix":"gts fix","lint":"gts check","postcompile":"cp ./src/package-json-helper.cjs ./build/cjs/src && cp ./src/package-json-helper.cjs ./build/esm/src","postcompile:cjs":"babel --plugins gapic-tools/build/src/replaceImportMetaUrl,gapic-tools/build/src/toggleESMFlagVariable build/cjs/src/util.js -o build/cjs/src/util.js && cp internal-tooling/helpers/package.cjs.json build/cjs/package.json","precompile":"rm -rf build/","preconformance-test":"npm run compile:cjs -- --sourceMap","predocs-test":"npm run docs","predocs":"npm run compile:cjs -- --sourceMap","prelint":"cd samples; npm link ../; npm install","prepare":"npm run compile","presystem-test:esm":"npm run compile:esm","presystem-test":"npm run compile -- --sourceMap","pretest":"npm run compile -- --sourceMap","samples-test":"npm link && cd samples/ && npm link ../ && npm test && cd ../","system-test:esm":"mocha build/esm/system-test --timeout 600000 --exit","system-test":"mocha build/cjs/system-test --timeout 600000 --exit","test":"c8 mocha build/cjs/test"},"dependencies":{"@google-cloud/paginator":"^5.0.0","@google-cloud/projectify":"^4.0.0","@google-cloud/promisify":"<4.1.0","abort-controller":"^3.0.0","async-retry":"^1.3.3","duplexify":"^4.1.3","fast-xml-parser":"^4.4.1","gaxios":"^6.0.2","google-auth-library":"^9.6.3","html-entities":"^2.5.2","mime":"^3.0.0","p-limit":"^3.0.1","retry-request":"^7.0.0","teeny-request":"^9.0.0","uuid":"^8.0.0"},"devDependencies":{"@babel/cli":"^7.22.10","@babel/core":"^7.22.11","@google-cloud/pubsub":"^4.0.0","@grpc/grpc-js":"^1.0.3","@grpc/proto-loader":"^0.7.0","@types/async-retry":"^1.4.3","@types/duplexify":"^3.6.4","@types/mime":"^3.0.0","@types/mocha":"^9.1.1","@types/mockery":"^1.4.29","@types/node":"^22.0.0","@types/node-fetch":"^2.1.3","@types/proxyquire":"^1.3.28","@types/request":"^2.48.4","@types/sinon":"^17.0.0","@types/tmp":"0.2.6","@types/uuid":"^8.0.0","@types/yargs":"^17.0.10","c8":"^9.0.0","form-data":"^4.0.0","gapic-tools":"^0.4.0","gts":"^5.0.0","jsdoc":"^4.0.0","jsdoc-fresh":"^3.0.0","jsdoc-region-tag":"^3.0.0","linkinator":"^3.0.0","mocha":"^9.2.2","mockery":"^2.1.0","nock":"~13.5.0","node-fetch":"^2.6.7","pack-n-play":"^2.0.0","proxyquire":"^2.1.3","sinon":"^18.0.0","nise":"6.0.0","path-to-regexp":"6.3.0","tmp":"^0.2.0","typescript":"^5.1.6","yargs":"^17.3.1"}}'); + +/***/ }), + +/***/ 66495: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"gaxios","version":"6.7.1","description":"A simple common HTTP client specifically for Google APIs and services.","main":"build/src/index.js","types":"build/src/index.d.ts","files":["build/src"],"scripts":{"lint":"gts check","test":"c8 mocha build/test","presystem-test":"npm run compile","system-test":"mocha build/system-test --timeout 80000","compile":"tsc -p .","fix":"gts fix","prepare":"npm run compile","pretest":"npm run compile","webpack":"webpack","prebrowser-test":"npm run compile","browser-test":"node build/browser-test/browser-test-runner.js","docs":"compodoc src/","docs-test":"linkinator docs","predocs-test":"npm run docs","samples-test":"cd samples/ && npm link ../ && npm test && cd ../","prelint":"cd samples; npm link ../; npm install","clean":"gts clean","precompile":"gts clean"},"repository":"googleapis/gaxios","keywords":["google"],"engines":{"node":">=14"},"author":"Google, LLC","license":"Apache-2.0","devDependencies":{"@babel/plugin-proposal-private-methods":"^7.18.6","@compodoc/compodoc":"1.1.19","@types/cors":"^2.8.6","@types/express":"^4.16.1","@types/extend":"^3.0.1","@types/mocha":"^9.0.0","@types/multiparty":"0.0.36","@types/mv":"^2.1.0","@types/ncp":"^2.0.1","@types/node":"^20.0.0","@types/node-fetch":"^2.5.7","@types/sinon":"^17.0.0","@types/tmp":"0.2.6","@types/uuid":"^10.0.0","abort-controller":"^3.0.0","assert":"^2.0.0","browserify":"^17.0.0","c8":"^8.0.0","cheerio":"1.0.0-rc.10","cors":"^2.8.5","execa":"^5.0.0","express":"^4.16.4","form-data":"^4.0.0","gts":"^5.0.0","is-docker":"^2.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-coverage":"^2.0.0","karma-firefox-launcher":"^2.0.0","karma-mocha":"^2.0.0","karma-remap-coverage":"^0.1.5","karma-sourcemap-loader":"^0.4.0","karma-webpack":"5.0.0","linkinator":"^3.0.0","mocha":"^8.0.0","multiparty":"^4.2.1","mv":"^2.1.1","ncp":"^2.0.0","nock":"^13.0.0","null-loader":"^4.0.0","puppeteer":"^19.0.0","sinon":"^18.0.0","stream-browserify":"^3.0.0","tmp":"0.2.3","ts-loader":"^8.0.0","typescript":"^5.1.6","webpack":"^5.35.0","webpack-cli":"^4.0.0"},"dependencies":{"extend":"^3.0.2","https-proxy-agent":"^7.0.1","is-stream":"^2.0.0","node-fetch":"^2.6.9","uuid":"^9.0.1"}}'); + +/***/ }), + +/***/ 96066: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('{"name":"google-auth-library","version":"9.15.1","author":"Google Inc.","description":"Google APIs Authentication Client Library for Node.js","engines":{"node":">=14"},"main":"./build/src/index.js","types":"./build/src/index.d.ts","repository":"googleapis/google-auth-library-nodejs.git","keywords":["google","api","google apis","client","client library"],"dependencies":{"base64-js":"^1.3.0","ecdsa-sig-formatter":"^1.0.11","gaxios":"^6.1.1","gcp-metadata":"^6.1.0","gtoken":"^7.0.0","jws":"^4.0.0"},"devDependencies":{"@types/base64-js":"^1.2.5","@types/chai":"^4.1.7","@types/jws":"^3.1.0","@types/mocha":"^9.0.0","@types/mv":"^2.1.0","@types/ncp":"^2.0.1","@types/node":"^20.4.2","@types/sinon":"^17.0.0","assert-rejects":"^1.0.0","c8":"^8.0.0","chai":"^4.2.0","cheerio":"1.0.0-rc.12","codecov":"^3.0.2","engine.io":"6.6.2","gts":"^5.0.0","is-docker":"^2.0.0","jsdoc":"^4.0.0","jsdoc-fresh":"^3.0.0","jsdoc-region-tag":"^3.0.0","karma":"^6.0.0","karma-chrome-launcher":"^3.0.0","karma-coverage":"^2.0.0","karma-firefox-launcher":"^2.0.0","karma-mocha":"^2.0.0","karma-sourcemap-loader":"^0.4.0","karma-webpack":"5.0.0","keypair":"^1.0.4","linkinator":"^4.0.0","mocha":"^9.2.2","mv":"^2.1.1","ncp":"^2.0.0","nock":"^13.0.0","null-loader":"^4.0.0","pdfmake":"0.2.12","puppeteer":"^21.0.0","sinon":"^18.0.0","ts-loader":"^8.0.0","typescript":"^5.1.6","webpack":"^5.21.2","webpack-cli":"^4.0.0"},"files":["build/src","!build/src/**/*.map"],"scripts":{"test":"c8 mocha build/test","clean":"gts clean","prepare":"npm run compile","lint":"gts check","compile":"tsc -p .","fix":"gts fix","pretest":"npm run compile -- --sourceMap","docs":"jsdoc -c .jsdoc.json","samples-setup":"cd samples/ && npm link ../ && npm run setup && cd ../","samples-test":"cd samples/ && npm link ../ && npm test && cd ../","system-test":"mocha build/system-test --timeout 60000","presystem-test":"npm run compile -- --sourceMap","webpack":"webpack","browser-test":"karma start","docs-test":"linkinator docs","predocs-test":"npm run docs","prelint":"cd samples; npm link ../; npm install","precompile":"gts clean"},"license":"Apache-2.0"}'); + +/***/ }), + +/***/ 92472: +/***/ ((module) => { + +"use strict"; +module.exports = /*#__PURE__*/JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"],[[47,47],"disallowed_STD3_valid"],[[48,57],"valid"],[[58,64],"disallowed_STD3_valid"],[[65,65],"mapped",[97]],[[66,66],"mapped",[98]],[[67,67],"mapped",[99]],[[68,68],"mapped",[100]],[[69,69],"mapped",[101]],[[70,70],"mapped",[102]],[[71,71],"mapped",[103]],[[72,72],"mapped",[104]],[[73,73],"mapped",[105]],[[74,74],"mapped",[106]],[[75,75],"mapped",[107]],[[76,76],"mapped",[108]],[[77,77],"mapped",[109]],[[78,78],"mapped",[110]],[[79,79],"mapped",[111]],[[80,80],"mapped",[112]],[[81,81],"mapped",[113]],[[82,82],"mapped",[114]],[[83,83],"mapped",[115]],[[84,84],"mapped",[116]],[[85,85],"mapped",[117]],[[86,86],"mapped",[118]],[[87,87],"mapped",[119]],[[88,88],"mapped",[120]],[[89,89],"mapped",[121]],[[90,90],"mapped",[122]],[[91,96],"disallowed_STD3_valid"],[[97,122],"valid"],[[123,127],"disallowed_STD3_valid"],[[128,159],"disallowed"],[[160,160],"disallowed_STD3_mapped",[32]],[[161,167],"valid",[],"NV8"],[[168,168],"disallowed_STD3_mapped",[32,776]],[[169,169],"valid",[],"NV8"],[[170,170],"mapped",[97]],[[171,172],"valid",[],"NV8"],[[173,173],"ignored"],[[174,174],"valid",[],"NV8"],[[175,175],"disallowed_STD3_mapped",[32,772]],[[176,177],"valid",[],"NV8"],[[178,178],"mapped",[50]],[[179,179],"mapped",[51]],[[180,180],"disallowed_STD3_mapped",[32,769]],[[181,181],"mapped",[956]],[[182,182],"valid",[],"NV8"],[[183,183],"valid"],[[184,184],"disallowed_STD3_mapped",[32,807]],[[185,185],"mapped",[49]],[[186,186],"mapped",[111]],[[187,187],"valid",[],"NV8"],[[188,188],"mapped",[49,8260,52]],[[189,189],"mapped",[49,8260,50]],[[190,190],"mapped",[51,8260,52]],[[191,191],"valid",[],"NV8"],[[192,192],"mapped",[224]],[[193,193],"mapped",[225]],[[194,194],"mapped",[226]],[[195,195],"mapped",[227]],[[196,196],"mapped",[228]],[[197,197],"mapped",[229]],[[198,198],"mapped",[230]],[[199,199],"mapped",[231]],[[200,200],"mapped",[232]],[[201,201],"mapped",[233]],[[202,202],"mapped",[234]],[[203,203],"mapped",[235]],[[204,204],"mapped",[236]],[[205,205],"mapped",[237]],[[206,206],"mapped",[238]],[[207,207],"mapped",[239]],[[208,208],"mapped",[240]],[[209,209],"mapped",[241]],[[210,210],"mapped",[242]],[[211,211],"mapped",[243]],[[212,212],"mapped",[244]],[[213,213],"mapped",[245]],[[214,214],"mapped",[246]],[[215,215],"valid",[],"NV8"],[[216,216],"mapped",[248]],[[217,217],"mapped",[249]],[[218,218],"mapped",[250]],[[219,219],"mapped",[251]],[[220,220],"mapped",[252]],[[221,221],"mapped",[253]],[[222,222],"mapped",[254]],[[223,223],"deviation",[115,115]],[[224,246],"valid"],[[247,247],"valid",[],"NV8"],[[248,255],"valid"],[[256,256],"mapped",[257]],[[257,257],"valid"],[[258,258],"mapped",[259]],[[259,259],"valid"],[[260,260],"mapped",[261]],[[261,261],"valid"],[[262,262],"mapped",[263]],[[263,263],"valid"],[[264,264],"mapped",[265]],[[265,265],"valid"],[[266,266],"mapped",[267]],[[267,267],"valid"],[[268,268],"mapped",[269]],[[269,269],"valid"],[[270,270],"mapped",[271]],[[271,271],"valid"],[[272,272],"mapped",[273]],[[273,273],"valid"],[[274,274],"mapped",[275]],[[275,275],"valid"],[[276,276],"mapped",[277]],[[277,277],"valid"],[[278,278],"mapped",[279]],[[279,279],"valid"],[[280,280],"mapped",[281]],[[281,281],"valid"],[[282,282],"mapped",[283]],[[283,283],"valid"],[[284,284],"mapped",[285]],[[285,285],"valid"],[[286,286],"mapped",[287]],[[287,287],"valid"],[[288,288],"mapped",[289]],[[289,289],"valid"],[[290,290],"mapped",[291]],[[291,291],"valid"],[[292,292],"mapped",[293]],[[293,293],"valid"],[[294,294],"mapped",[295]],[[295,295],"valid"],[[296,296],"mapped",[297]],[[297,297],"valid"],[[298,298],"mapped",[299]],[[299,299],"valid"],[[300,300],"mapped",[301]],[[301,301],"valid"],[[302,302],"mapped",[303]],[[303,303],"valid"],[[304,304],"mapped",[105,775]],[[305,305],"valid"],[[306,307],"mapped",[105,106]],[[308,308],"mapped",[309]],[[309,309],"valid"],[[310,310],"mapped",[311]],[[311,312],"valid"],[[313,313],"mapped",[314]],[[314,314],"valid"],[[315,315],"mapped",[316]],[[316,316],"valid"],[[317,317],"mapped",[318]],[[318,318],"valid"],[[319,320],"mapped",[108,183]],[[321,321],"mapped",[322]],[[322,322],"valid"],[[323,323],"mapped",[324]],[[324,324],"valid"],[[325,325],"mapped",[326]],[[326,326],"valid"],[[327,327],"mapped",[328]],[[328,328],"valid"],[[329,329],"mapped",[700,110]],[[330,330],"mapped",[331]],[[331,331],"valid"],[[332,332],"mapped",[333]],[[333,333],"valid"],[[334,334],"mapped",[335]],[[335,335],"valid"],[[336,336],"mapped",[337]],[[337,337],"valid"],[[338,338],"mapped",[339]],[[339,339],"valid"],[[340,340],"mapped",[341]],[[341,341],"valid"],[[342,342],"mapped",[343]],[[343,343],"valid"],[[344,344],"mapped",[345]],[[345,345],"valid"],[[346,346],"mapped",[347]],[[347,347],"valid"],[[348,348],"mapped",[349]],[[349,349],"valid"],[[350,350],"mapped",[351]],[[351,351],"valid"],[[352,352],"mapped",[353]],[[353,353],"valid"],[[354,354],"mapped",[355]],[[355,355],"valid"],[[356,356],"mapped",[357]],[[357,357],"valid"],[[358,358],"mapped",[359]],[[359,359],"valid"],[[360,360],"mapped",[361]],[[361,361],"valid"],[[362,362],"mapped",[363]],[[363,363],"valid"],[[364,364],"mapped",[365]],[[365,365],"valid"],[[366,366],"mapped",[367]],[[367,367],"valid"],[[368,368],"mapped",[369]],[[369,369],"valid"],[[370,370],"mapped",[371]],[[371,371],"valid"],[[372,372],"mapped",[373]],[[373,373],"valid"],[[374,374],"mapped",[375]],[[375,375],"valid"],[[376,376],"mapped",[255]],[[377,377],"mapped",[378]],[[378,378],"valid"],[[379,379],"mapped",[380]],[[380,380],"valid"],[[381,381],"mapped",[382]],[[382,382],"valid"],[[383,383],"mapped",[115]],[[384,384],"valid"],[[385,385],"mapped",[595]],[[386,386],"mapped",[387]],[[387,387],"valid"],[[388,388],"mapped",[389]],[[389,389],"valid"],[[390,390],"mapped",[596]],[[391,391],"mapped",[392]],[[392,392],"valid"],[[393,393],"mapped",[598]],[[394,394],"mapped",[599]],[[395,395],"mapped",[396]],[[396,397],"valid"],[[398,398],"mapped",[477]],[[399,399],"mapped",[601]],[[400,400],"mapped",[603]],[[401,401],"mapped",[402]],[[402,402],"valid"],[[403,403],"mapped",[608]],[[404,404],"mapped",[611]],[[405,405],"valid"],[[406,406],"mapped",[617]],[[407,407],"mapped",[616]],[[408,408],"mapped",[409]],[[409,411],"valid"],[[412,412],"mapped",[623]],[[413,413],"mapped",[626]],[[414,414],"valid"],[[415,415],"mapped",[629]],[[416,416],"mapped",[417]],[[417,417],"valid"],[[418,418],"mapped",[419]],[[419,419],"valid"],[[420,420],"mapped",[421]],[[421,421],"valid"],[[422,422],"mapped",[640]],[[423,423],"mapped",[424]],[[424,424],"valid"],[[425,425],"mapped",[643]],[[426,427],"valid"],[[428,428],"mapped",[429]],[[429,429],"valid"],[[430,430],"mapped",[648]],[[431,431],"mapped",[432]],[[432,432],"valid"],[[433,433],"mapped",[650]],[[434,434],"mapped",[651]],[[435,435],"mapped",[436]],[[436,436],"valid"],[[437,437],"mapped",[438]],[[438,438],"valid"],[[439,439],"mapped",[658]],[[440,440],"mapped",[441]],[[441,443],"valid"],[[444,444],"mapped",[445]],[[445,451],"valid"],[[452,454],"mapped",[100,382]],[[455,457],"mapped",[108,106]],[[458,460],"mapped",[110,106]],[[461,461],"mapped",[462]],[[462,462],"valid"],[[463,463],"mapped",[464]],[[464,464],"valid"],[[465,465],"mapped",[466]],[[466,466],"valid"],[[467,467],"mapped",[468]],[[468,468],"valid"],[[469,469],"mapped",[470]],[[470,470],"valid"],[[471,471],"mapped",[472]],[[472,472],"valid"],[[473,473],"mapped",[474]],[[474,474],"valid"],[[475,475],"mapped",[476]],[[476,477],"valid"],[[478,478],"mapped",[479]],[[479,479],"valid"],[[480,480],"mapped",[481]],[[481,481],"valid"],[[482,482],"mapped",[483]],[[483,483],"valid"],[[484,484],"mapped",[485]],[[485,485],"valid"],[[486,486],"mapped",[487]],[[487,487],"valid"],[[488,488],"mapped",[489]],[[489,489],"valid"],[[490,490],"mapped",[491]],[[491,491],"valid"],[[492,492],"mapped",[493]],[[493,493],"valid"],[[494,494],"mapped",[495]],[[495,496],"valid"],[[497,499],"mapped",[100,122]],[[500,500],"mapped",[501]],[[501,501],"valid"],[[502,502],"mapped",[405]],[[503,503],"mapped",[447]],[[504,504],"mapped",[505]],[[505,505],"valid"],[[506,506],"mapped",[507]],[[507,507],"valid"],[[508,508],"mapped",[509]],[[509,509],"valid"],[[510,510],"mapped",[511]],[[511,511],"valid"],[[512,512],"mapped",[513]],[[513,513],"valid"],[[514,514],"mapped",[515]],[[515,515],"valid"],[[516,516],"mapped",[517]],[[517,517],"valid"],[[518,518],"mapped",[519]],[[519,519],"valid"],[[520,520],"mapped",[521]],[[521,521],"valid"],[[522,522],"mapped",[523]],[[523,523],"valid"],[[524,524],"mapped",[525]],[[525,525],"valid"],[[526,526],"mapped",[527]],[[527,527],"valid"],[[528,528],"mapped",[529]],[[529,529],"valid"],[[530,530],"mapped",[531]],[[531,531],"valid"],[[532,532],"mapped",[533]],[[533,533],"valid"],[[534,534],"mapped",[535]],[[535,535],"valid"],[[536,536],"mapped",[537]],[[537,537],"valid"],[[538,538],"mapped",[539]],[[539,539],"valid"],[[540,540],"mapped",[541]],[[541,541],"valid"],[[542,542],"mapped",[543]],[[543,543],"valid"],[[544,544],"mapped",[414]],[[545,545],"valid"],[[546,546],"mapped",[547]],[[547,547],"valid"],[[548,548],"mapped",[549]],[[549,549],"valid"],[[550,550],"mapped",[551]],[[551,551],"valid"],[[552,552],"mapped",[553]],[[553,553],"valid"],[[554,554],"mapped",[555]],[[555,555],"valid"],[[556,556],"mapped",[557]],[[557,557],"valid"],[[558,558],"mapped",[559]],[[559,559],"valid"],[[560,560],"mapped",[561]],[[561,561],"valid"],[[562,562],"mapped",[563]],[[563,563],"valid"],[[564,566],"valid"],[[567,569],"valid"],[[570,570],"mapped",[11365]],[[571,571],"mapped",[572]],[[572,572],"valid"],[[573,573],"mapped",[410]],[[574,574],"mapped",[11366]],[[575,576],"valid"],[[577,577],"mapped",[578]],[[578,578],"valid"],[[579,579],"mapped",[384]],[[580,580],"mapped",[649]],[[581,581],"mapped",[652]],[[582,582],"mapped",[583]],[[583,583],"valid"],[[584,584],"mapped",[585]],[[585,585],"valid"],[[586,586],"mapped",[587]],[[587,587],"valid"],[[588,588],"mapped",[589]],[[589,589],"valid"],[[590,590],"mapped",[591]],[[591,591],"valid"],[[592,680],"valid"],[[681,685],"valid"],[[686,687],"valid"],[[688,688],"mapped",[104]],[[689,689],"mapped",[614]],[[690,690],"mapped",[106]],[[691,691],"mapped",[114]],[[692,692],"mapped",[633]],[[693,693],"mapped",[635]],[[694,694],"mapped",[641]],[[695,695],"mapped",[119]],[[696,696],"mapped",[121]],[[697,705],"valid"],[[706,709],"valid",[],"NV8"],[[710,721],"valid"],[[722,727],"valid",[],"NV8"],[[728,728],"disallowed_STD3_mapped",[32,774]],[[729,729],"disallowed_STD3_mapped",[32,775]],[[730,730],"disallowed_STD3_mapped",[32,778]],[[731,731],"disallowed_STD3_mapped",[32,808]],[[732,732],"disallowed_STD3_mapped",[32,771]],[[733,733],"disallowed_STD3_mapped",[32,779]],[[734,734],"valid",[],"NV8"],[[735,735],"valid",[],"NV8"],[[736,736],"mapped",[611]],[[737,737],"mapped",[108]],[[738,738],"mapped",[115]],[[739,739],"mapped",[120]],[[740,740],"mapped",[661]],[[741,745],"valid",[],"NV8"],[[746,747],"valid",[],"NV8"],[[748,748],"valid"],[[749,749],"valid",[],"NV8"],[[750,750],"valid"],[[751,767],"valid",[],"NV8"],[[768,831],"valid"],[[832,832],"mapped",[768]],[[833,833],"mapped",[769]],[[834,834],"valid"],[[835,835],"mapped",[787]],[[836,836],"mapped",[776,769]],[[837,837],"mapped",[953]],[[838,846],"valid"],[[847,847],"ignored"],[[848,855],"valid"],[[856,860],"valid"],[[861,863],"valid"],[[864,865],"valid"],[[866,866],"valid"],[[867,879],"valid"],[[880,880],"mapped",[881]],[[881,881],"valid"],[[882,882],"mapped",[883]],[[883,883],"valid"],[[884,884],"mapped",[697]],[[885,885],"valid"],[[886,886],"mapped",[887]],[[887,887],"valid"],[[888,889],"disallowed"],[[890,890],"disallowed_STD3_mapped",[32,953]],[[891,893],"valid"],[[894,894],"disallowed_STD3_mapped",[59]],[[895,895],"mapped",[1011]],[[896,899],"disallowed"],[[900,900],"disallowed_STD3_mapped",[32,769]],[[901,901],"disallowed_STD3_mapped",[32,776,769]],[[902,902],"mapped",[940]],[[903,903],"mapped",[183]],[[904,904],"mapped",[941]],[[905,905],"mapped",[942]],[[906,906],"mapped",[943]],[[907,907],"disallowed"],[[908,908],"mapped",[972]],[[909,909],"disallowed"],[[910,910],"mapped",[973]],[[911,911],"mapped",[974]],[[912,912],"valid"],[[913,913],"mapped",[945]],[[914,914],"mapped",[946]],[[915,915],"mapped",[947]],[[916,916],"mapped",[948]],[[917,917],"mapped",[949]],[[918,918],"mapped",[950]],[[919,919],"mapped",[951]],[[920,920],"mapped",[952]],[[921,921],"mapped",[953]],[[922,922],"mapped",[954]],[[923,923],"mapped",[955]],[[924,924],"mapped",[956]],[[925,925],"mapped",[957]],[[926,926],"mapped",[958]],[[927,927],"mapped",[959]],[[928,928],"mapped",[960]],[[929,929],"mapped",[961]],[[930,930],"disallowed"],[[931,931],"mapped",[963]],[[932,932],"mapped",[964]],[[933,933],"mapped",[965]],[[934,934],"mapped",[966]],[[935,935],"mapped",[967]],[[936,936],"mapped",[968]],[[937,937],"mapped",[969]],[[938,938],"mapped",[970]],[[939,939],"mapped",[971]],[[940,961],"valid"],[[962,962],"deviation",[963]],[[963,974],"valid"],[[975,975],"mapped",[983]],[[976,976],"mapped",[946]],[[977,977],"mapped",[952]],[[978,978],"mapped",[965]],[[979,979],"mapped",[973]],[[980,980],"mapped",[971]],[[981,981],"mapped",[966]],[[982,982],"mapped",[960]],[[983,983],"valid"],[[984,984],"mapped",[985]],[[985,985],"valid"],[[986,986],"mapped",[987]],[[987,987],"valid"],[[988,988],"mapped",[989]],[[989,989],"valid"],[[990,990],"mapped",[991]],[[991,991],"valid"],[[992,992],"mapped",[993]],[[993,993],"valid"],[[994,994],"mapped",[995]],[[995,995],"valid"],[[996,996],"mapped",[997]],[[997,997],"valid"],[[998,998],"mapped",[999]],[[999,999],"valid"],[[1000,1000],"mapped",[1001]],[[1001,1001],"valid"],[[1002,1002],"mapped",[1003]],[[1003,1003],"valid"],[[1004,1004],"mapped",[1005]],[[1005,1005],"valid"],[[1006,1006],"mapped",[1007]],[[1007,1007],"valid"],[[1008,1008],"mapped",[954]],[[1009,1009],"mapped",[961]],[[1010,1010],"mapped",[963]],[[1011,1011],"valid"],[[1012,1012],"mapped",[952]],[[1013,1013],"mapped",[949]],[[1014,1014],"valid",[],"NV8"],[[1015,1015],"mapped",[1016]],[[1016,1016],"valid"],[[1017,1017],"mapped",[963]],[[1018,1018],"mapped",[1019]],[[1019,1019],"valid"],[[1020,1020],"valid"],[[1021,1021],"mapped",[891]],[[1022,1022],"mapped",[892]],[[1023,1023],"mapped",[893]],[[1024,1024],"mapped",[1104]],[[1025,1025],"mapped",[1105]],[[1026,1026],"mapped",[1106]],[[1027,1027],"mapped",[1107]],[[1028,1028],"mapped",[1108]],[[1029,1029],"mapped",[1109]],[[1030,1030],"mapped",[1110]],[[1031,1031],"mapped",[1111]],[[1032,1032],"mapped",[1112]],[[1033,1033],"mapped",[1113]],[[1034,1034],"mapped",[1114]],[[1035,1035],"mapped",[1115]],[[1036,1036],"mapped",[1116]],[[1037,1037],"mapped",[1117]],[[1038,1038],"mapped",[1118]],[[1039,1039],"mapped",[1119]],[[1040,1040],"mapped",[1072]],[[1041,1041],"mapped",[1073]],[[1042,1042],"mapped",[1074]],[[1043,1043],"mapped",[1075]],[[1044,1044],"mapped",[1076]],[[1045,1045],"mapped",[1077]],[[1046,1046],"mapped",[1078]],[[1047,1047],"mapped",[1079]],[[1048,1048],"mapped",[1080]],[[1049,1049],"mapped",[1081]],[[1050,1050],"mapped",[1082]],[[1051,1051],"mapped",[1083]],[[1052,1052],"mapped",[1084]],[[1053,1053],"mapped",[1085]],[[1054,1054],"mapped",[1086]],[[1055,1055],"mapped",[1087]],[[1056,1056],"mapped",[1088]],[[1057,1057],"mapped",[1089]],[[1058,1058],"mapped",[1090]],[[1059,1059],"mapped",[1091]],[[1060,1060],"mapped",[1092]],[[1061,1061],"mapped",[1093]],[[1062,1062],"mapped",[1094]],[[1063,1063],"mapped",[1095]],[[1064,1064],"mapped",[1096]],[[1065,1065],"mapped",[1097]],[[1066,1066],"mapped",[1098]],[[1067,1067],"mapped",[1099]],[[1068,1068],"mapped",[1100]],[[1069,1069],"mapped",[1101]],[[1070,1070],"mapped",[1102]],[[1071,1071],"mapped",[1103]],[[1072,1103],"valid"],[[1104,1104],"valid"],[[1105,1116],"valid"],[[1117,1117],"valid"],[[1118,1119],"valid"],[[1120,1120],"mapped",[1121]],[[1121,1121],"valid"],[[1122,1122],"mapped",[1123]],[[1123,1123],"valid"],[[1124,1124],"mapped",[1125]],[[1125,1125],"valid"],[[1126,1126],"mapped",[1127]],[[1127,1127],"valid"],[[1128,1128],"mapped",[1129]],[[1129,1129],"valid"],[[1130,1130],"mapped",[1131]],[[1131,1131],"valid"],[[1132,1132],"mapped",[1133]],[[1133,1133],"valid"],[[1134,1134],"mapped",[1135]],[[1135,1135],"valid"],[[1136,1136],"mapped",[1137]],[[1137,1137],"valid"],[[1138,1138],"mapped",[1139]],[[1139,1139],"valid"],[[1140,1140],"mapped",[1141]],[[1141,1141],"valid"],[[1142,1142],"mapped",[1143]],[[1143,1143],"valid"],[[1144,1144],"mapped",[1145]],[[1145,1145],"valid"],[[1146,1146],"mapped",[1147]],[[1147,1147],"valid"],[[1148,1148],"mapped",[1149]],[[1149,1149],"valid"],[[1150,1150],"mapped",[1151]],[[1151,1151],"valid"],[[1152,1152],"mapped",[1153]],[[1153,1153],"valid"],[[1154,1154],"valid",[],"NV8"],[[1155,1158],"valid"],[[1159,1159],"valid"],[[1160,1161],"valid",[],"NV8"],[[1162,1162],"mapped",[1163]],[[1163,1163],"valid"],[[1164,1164],"mapped",[1165]],[[1165,1165],"valid"],[[1166,1166],"mapped",[1167]],[[1167,1167],"valid"],[[1168,1168],"mapped",[1169]],[[1169,1169],"valid"],[[1170,1170],"mapped",[1171]],[[1171,1171],"valid"],[[1172,1172],"mapped",[1173]],[[1173,1173],"valid"],[[1174,1174],"mapped",[1175]],[[1175,1175],"valid"],[[1176,1176],"mapped",[1177]],[[1177,1177],"valid"],[[1178,1178],"mapped",[1179]],[[1179,1179],"valid"],[[1180,1180],"mapped",[1181]],[[1181,1181],"valid"],[[1182,1182],"mapped",[1183]],[[1183,1183],"valid"],[[1184,1184],"mapped",[1185]],[[1185,1185],"valid"],[[1186,1186],"mapped",[1187]],[[1187,1187],"valid"],[[1188,1188],"mapped",[1189]],[[1189,1189],"valid"],[[1190,1190],"mapped",[1191]],[[1191,1191],"valid"],[[1192,1192],"mapped",[1193]],[[1193,1193],"valid"],[[1194,1194],"mapped",[1195]],[[1195,1195],"valid"],[[1196,1196],"mapped",[1197]],[[1197,1197],"valid"],[[1198,1198],"mapped",[1199]],[[1199,1199],"valid"],[[1200,1200],"mapped",[1201]],[[1201,1201],"valid"],[[1202,1202],"mapped",[1203]],[[1203,1203],"valid"],[[1204,1204],"mapped",[1205]],[[1205,1205],"valid"],[[1206,1206],"mapped",[1207]],[[1207,1207],"valid"],[[1208,1208],"mapped",[1209]],[[1209,1209],"valid"],[[1210,1210],"mapped",[1211]],[[1211,1211],"valid"],[[1212,1212],"mapped",[1213]],[[1213,1213],"valid"],[[1214,1214],"mapped",[1215]],[[1215,1215],"valid"],[[1216,1216],"disallowed"],[[1217,1217],"mapped",[1218]],[[1218,1218],"valid"],[[1219,1219],"mapped",[1220]],[[1220,1220],"valid"],[[1221,1221],"mapped",[1222]],[[1222,1222],"valid"],[[1223,1223],"mapped",[1224]],[[1224,1224],"valid"],[[1225,1225],"mapped",[1226]],[[1226,1226],"valid"],[[1227,1227],"mapped",[1228]],[[1228,1228],"valid"],[[1229,1229],"mapped",[1230]],[[1230,1230],"valid"],[[1231,1231],"valid"],[[1232,1232],"mapped",[1233]],[[1233,1233],"valid"],[[1234,1234],"mapped",[1235]],[[1235,1235],"valid"],[[1236,1236],"mapped",[1237]],[[1237,1237],"valid"],[[1238,1238],"mapped",[1239]],[[1239,1239],"valid"],[[1240,1240],"mapped",[1241]],[[1241,1241],"valid"],[[1242,1242],"mapped",[1243]],[[1243,1243],"valid"],[[1244,1244],"mapped",[1245]],[[1245,1245],"valid"],[[1246,1246],"mapped",[1247]],[[1247,1247],"valid"],[[1248,1248],"mapped",[1249]],[[1249,1249],"valid"],[[1250,1250],"mapped",[1251]],[[1251,1251],"valid"],[[1252,1252],"mapped",[1253]],[[1253,1253],"valid"],[[1254,1254],"mapped",[1255]],[[1255,1255],"valid"],[[1256,1256],"mapped",[1257]],[[1257,1257],"valid"],[[1258,1258],"mapped",[1259]],[[1259,1259],"valid"],[[1260,1260],"mapped",[1261]],[[1261,1261],"valid"],[[1262,1262],"mapped",[1263]],[[1263,1263],"valid"],[[1264,1264],"mapped",[1265]],[[1265,1265],"valid"],[[1266,1266],"mapped",[1267]],[[1267,1267],"valid"],[[1268,1268],"mapped",[1269]],[[1269,1269],"valid"],[[1270,1270],"mapped",[1271]],[[1271,1271],"valid"],[[1272,1272],"mapped",[1273]],[[1273,1273],"valid"],[[1274,1274],"mapped",[1275]],[[1275,1275],"valid"],[[1276,1276],"mapped",[1277]],[[1277,1277],"valid"],[[1278,1278],"mapped",[1279]],[[1279,1279],"valid"],[[1280,1280],"mapped",[1281]],[[1281,1281],"valid"],[[1282,1282],"mapped",[1283]],[[1283,1283],"valid"],[[1284,1284],"mapped",[1285]],[[1285,1285],"valid"],[[1286,1286],"mapped",[1287]],[[1287,1287],"valid"],[[1288,1288],"mapped",[1289]],[[1289,1289],"valid"],[[1290,1290],"mapped",[1291]],[[1291,1291],"valid"],[[1292,1292],"mapped",[1293]],[[1293,1293],"valid"],[[1294,1294],"mapped",[1295]],[[1295,1295],"valid"],[[1296,1296],"mapped",[1297]],[[1297,1297],"valid"],[[1298,1298],"mapped",[1299]],[[1299,1299],"valid"],[[1300,1300],"mapped",[1301]],[[1301,1301],"valid"],[[1302,1302],"mapped",[1303]],[[1303,1303],"valid"],[[1304,1304],"mapped",[1305]],[[1305,1305],"valid"],[[1306,1306],"mapped",[1307]],[[1307,1307],"valid"],[[1308,1308],"mapped",[1309]],[[1309,1309],"valid"],[[1310,1310],"mapped",[1311]],[[1311,1311],"valid"],[[1312,1312],"mapped",[1313]],[[1313,1313],"valid"],[[1314,1314],"mapped",[1315]],[[1315,1315],"valid"],[[1316,1316],"mapped",[1317]],[[1317,1317],"valid"],[[1318,1318],"mapped",[1319]],[[1319,1319],"valid"],[[1320,1320],"mapped",[1321]],[[1321,1321],"valid"],[[1322,1322],"mapped",[1323]],[[1323,1323],"valid"],[[1324,1324],"mapped",[1325]],[[1325,1325],"valid"],[[1326,1326],"mapped",[1327]],[[1327,1327],"valid"],[[1328,1328],"disallowed"],[[1329,1329],"mapped",[1377]],[[1330,1330],"mapped",[1378]],[[1331,1331],"mapped",[1379]],[[1332,1332],"mapped",[1380]],[[1333,1333],"mapped",[1381]],[[1334,1334],"mapped",[1382]],[[1335,1335],"mapped",[1383]],[[1336,1336],"mapped",[1384]],[[1337,1337],"mapped",[1385]],[[1338,1338],"mapped",[1386]],[[1339,1339],"mapped",[1387]],[[1340,1340],"mapped",[1388]],[[1341,1341],"mapped",[1389]],[[1342,1342],"mapped",[1390]],[[1343,1343],"mapped",[1391]],[[1344,1344],"mapped",[1392]],[[1345,1345],"mapped",[1393]],[[1346,1346],"mapped",[1394]],[[1347,1347],"mapped",[1395]],[[1348,1348],"mapped",[1396]],[[1349,1349],"mapped",[1397]],[[1350,1350],"mapped",[1398]],[[1351,1351],"mapped",[1399]],[[1352,1352],"mapped",[1400]],[[1353,1353],"mapped",[1401]],[[1354,1354],"mapped",[1402]],[[1355,1355],"mapped",[1403]],[[1356,1356],"mapped",[1404]],[[1357,1357],"mapped",[1405]],[[1358,1358],"mapped",[1406]],[[1359,1359],"mapped",[1407]],[[1360,1360],"mapped",[1408]],[[1361,1361],"mapped",[1409]],[[1362,1362],"mapped",[1410]],[[1363,1363],"mapped",[1411]],[[1364,1364],"mapped",[1412]],[[1365,1365],"mapped",[1413]],[[1366,1366],"mapped",[1414]],[[1367,1368],"disallowed"],[[1369,1369],"valid"],[[1370,1375],"valid",[],"NV8"],[[1376,1376],"disallowed"],[[1377,1414],"valid"],[[1415,1415],"mapped",[1381,1410]],[[1416,1416],"disallowed"],[[1417,1417],"valid",[],"NV8"],[[1418,1418],"valid",[],"NV8"],[[1419,1420],"disallowed"],[[1421,1422],"valid",[],"NV8"],[[1423,1423],"valid",[],"NV8"],[[1424,1424],"disallowed"],[[1425,1441],"valid"],[[1442,1442],"valid"],[[1443,1455],"valid"],[[1456,1465],"valid"],[[1466,1466],"valid"],[[1467,1469],"valid"],[[1470,1470],"valid",[],"NV8"],[[1471,1471],"valid"],[[1472,1472],"valid",[],"NV8"],[[1473,1474],"valid"],[[1475,1475],"valid",[],"NV8"],[[1476,1476],"valid"],[[1477,1477],"valid"],[[1478,1478],"valid",[],"NV8"],[[1479,1479],"valid"],[[1480,1487],"disallowed"],[[1488,1514],"valid"],[[1515,1519],"disallowed"],[[1520,1524],"valid"],[[1525,1535],"disallowed"],[[1536,1539],"disallowed"],[[1540,1540],"disallowed"],[[1541,1541],"disallowed"],[[1542,1546],"valid",[],"NV8"],[[1547,1547],"valid",[],"NV8"],[[1548,1548],"valid",[],"NV8"],[[1549,1551],"valid",[],"NV8"],[[1552,1557],"valid"],[[1558,1562],"valid"],[[1563,1563],"valid",[],"NV8"],[[1564,1564],"disallowed"],[[1565,1565],"disallowed"],[[1566,1566],"valid",[],"NV8"],[[1567,1567],"valid",[],"NV8"],[[1568,1568],"valid"],[[1569,1594],"valid"],[[1595,1599],"valid"],[[1600,1600],"valid",[],"NV8"],[[1601,1618],"valid"],[[1619,1621],"valid"],[[1622,1624],"valid"],[[1625,1630],"valid"],[[1631,1631],"valid"],[[1632,1641],"valid"],[[1642,1645],"valid",[],"NV8"],[[1646,1647],"valid"],[[1648,1652],"valid"],[[1653,1653],"mapped",[1575,1652]],[[1654,1654],"mapped",[1608,1652]],[[1655,1655],"mapped",[1735,1652]],[[1656,1656],"mapped",[1610,1652]],[[1657,1719],"valid"],[[1720,1721],"valid"],[[1722,1726],"valid"],[[1727,1727],"valid"],[[1728,1742],"valid"],[[1743,1743],"valid"],[[1744,1747],"valid"],[[1748,1748],"valid",[],"NV8"],[[1749,1756],"valid"],[[1757,1757],"disallowed"],[[1758,1758],"valid",[],"NV8"],[[1759,1768],"valid"],[[1769,1769],"valid",[],"NV8"],[[1770,1773],"valid"],[[1774,1775],"valid"],[[1776,1785],"valid"],[[1786,1790],"valid"],[[1791,1791],"valid"],[[1792,1805],"valid",[],"NV8"],[[1806,1806],"disallowed"],[[1807,1807],"disallowed"],[[1808,1836],"valid"],[[1837,1839],"valid"],[[1840,1866],"valid"],[[1867,1868],"disallowed"],[[1869,1871],"valid"],[[1872,1901],"valid"],[[1902,1919],"valid"],[[1920,1968],"valid"],[[1969,1969],"valid"],[[1970,1983],"disallowed"],[[1984,2037],"valid"],[[2038,2042],"valid",[],"NV8"],[[2043,2047],"disallowed"],[[2048,2093],"valid"],[[2094,2095],"disallowed"],[[2096,2110],"valid",[],"NV8"],[[2111,2111],"disallowed"],[[2112,2139],"valid"],[[2140,2141],"disallowed"],[[2142,2142],"valid",[],"NV8"],[[2143,2207],"disallowed"],[[2208,2208],"valid"],[[2209,2209],"valid"],[[2210,2220],"valid"],[[2221,2226],"valid"],[[2227,2228],"valid"],[[2229,2274],"disallowed"],[[2275,2275],"valid"],[[2276,2302],"valid"],[[2303,2303],"valid"],[[2304,2304],"valid"],[[2305,2307],"valid"],[[2308,2308],"valid"],[[2309,2361],"valid"],[[2362,2363],"valid"],[[2364,2381],"valid"],[[2382,2382],"valid"],[[2383,2383],"valid"],[[2384,2388],"valid"],[[2389,2389],"valid"],[[2390,2391],"valid"],[[2392,2392],"mapped",[2325,2364]],[[2393,2393],"mapped",[2326,2364]],[[2394,2394],"mapped",[2327,2364]],[[2395,2395],"mapped",[2332,2364]],[[2396,2396],"mapped",[2337,2364]],[[2397,2397],"mapped",[2338,2364]],[[2398,2398],"mapped",[2347,2364]],[[2399,2399],"mapped",[2351,2364]],[[2400,2403],"valid"],[[2404,2405],"valid",[],"NV8"],[[2406,2415],"valid"],[[2416,2416],"valid",[],"NV8"],[[2417,2418],"valid"],[[2419,2423],"valid"],[[2424,2424],"valid"],[[2425,2426],"valid"],[[2427,2428],"valid"],[[2429,2429],"valid"],[[2430,2431],"valid"],[[2432,2432],"valid"],[[2433,2435],"valid"],[[2436,2436],"disallowed"],[[2437,2444],"valid"],[[2445,2446],"disallowed"],[[2447,2448],"valid"],[[2449,2450],"disallowed"],[[2451,2472],"valid"],[[2473,2473],"disallowed"],[[2474,2480],"valid"],[[2481,2481],"disallowed"],[[2482,2482],"valid"],[[2483,2485],"disallowed"],[[2486,2489],"valid"],[[2490,2491],"disallowed"],[[2492,2492],"valid"],[[2493,2493],"valid"],[[2494,2500],"valid"],[[2501,2502],"disallowed"],[[2503,2504],"valid"],[[2505,2506],"disallowed"],[[2507,2509],"valid"],[[2510,2510],"valid"],[[2511,2518],"disallowed"],[[2519,2519],"valid"],[[2520,2523],"disallowed"],[[2524,2524],"mapped",[2465,2492]],[[2525,2525],"mapped",[2466,2492]],[[2526,2526],"disallowed"],[[2527,2527],"mapped",[2479,2492]],[[2528,2531],"valid"],[[2532,2533],"disallowed"],[[2534,2545],"valid"],[[2546,2554],"valid",[],"NV8"],[[2555,2555],"valid",[],"NV8"],[[2556,2560],"disallowed"],[[2561,2561],"valid"],[[2562,2562],"valid"],[[2563,2563],"valid"],[[2564,2564],"disallowed"],[[2565,2570],"valid"],[[2571,2574],"disallowed"],[[2575,2576],"valid"],[[2577,2578],"disallowed"],[[2579,2600],"valid"],[[2601,2601],"disallowed"],[[2602,2608],"valid"],[[2609,2609],"disallowed"],[[2610,2610],"valid"],[[2611,2611],"mapped",[2610,2620]],[[2612,2612],"disallowed"],[[2613,2613],"valid"],[[2614,2614],"mapped",[2616,2620]],[[2615,2615],"disallowed"],[[2616,2617],"valid"],[[2618,2619],"disallowed"],[[2620,2620],"valid"],[[2621,2621],"disallowed"],[[2622,2626],"valid"],[[2627,2630],"disallowed"],[[2631,2632],"valid"],[[2633,2634],"disallowed"],[[2635,2637],"valid"],[[2638,2640],"disallowed"],[[2641,2641],"valid"],[[2642,2648],"disallowed"],[[2649,2649],"mapped",[2582,2620]],[[2650,2650],"mapped",[2583,2620]],[[2651,2651],"mapped",[2588,2620]],[[2652,2652],"valid"],[[2653,2653],"disallowed"],[[2654,2654],"mapped",[2603,2620]],[[2655,2661],"disallowed"],[[2662,2676],"valid"],[[2677,2677],"valid"],[[2678,2688],"disallowed"],[[2689,2691],"valid"],[[2692,2692],"disallowed"],[[2693,2699],"valid"],[[2700,2700],"valid"],[[2701,2701],"valid"],[[2702,2702],"disallowed"],[[2703,2705],"valid"],[[2706,2706],"disallowed"],[[2707,2728],"valid"],[[2729,2729],"disallowed"],[[2730,2736],"valid"],[[2737,2737],"disallowed"],[[2738,2739],"valid"],[[2740,2740],"disallowed"],[[2741,2745],"valid"],[[2746,2747],"disallowed"],[[2748,2757],"valid"],[[2758,2758],"disallowed"],[[2759,2761],"valid"],[[2762,2762],"disallowed"],[[2763,2765],"valid"],[[2766,2767],"disallowed"],[[2768,2768],"valid"],[[2769,2783],"disallowed"],[[2784,2784],"valid"],[[2785,2787],"valid"],[[2788,2789],"disallowed"],[[2790,2799],"valid"],[[2800,2800],"valid",[],"NV8"],[[2801,2801],"valid",[],"NV8"],[[2802,2808],"disallowed"],[[2809,2809],"valid"],[[2810,2816],"disallowed"],[[2817,2819],"valid"],[[2820,2820],"disallowed"],[[2821,2828],"valid"],[[2829,2830],"disallowed"],[[2831,2832],"valid"],[[2833,2834],"disallowed"],[[2835,2856],"valid"],[[2857,2857],"disallowed"],[[2858,2864],"valid"],[[2865,2865],"disallowed"],[[2866,2867],"valid"],[[2868,2868],"disallowed"],[[2869,2869],"valid"],[[2870,2873],"valid"],[[2874,2875],"disallowed"],[[2876,2883],"valid"],[[2884,2884],"valid"],[[2885,2886],"disallowed"],[[2887,2888],"valid"],[[2889,2890],"disallowed"],[[2891,2893],"valid"],[[2894,2901],"disallowed"],[[2902,2903],"valid"],[[2904,2907],"disallowed"],[[2908,2908],"mapped",[2849,2876]],[[2909,2909],"mapped",[2850,2876]],[[2910,2910],"disallowed"],[[2911,2913],"valid"],[[2914,2915],"valid"],[[2916,2917],"disallowed"],[[2918,2927],"valid"],[[2928,2928],"valid",[],"NV8"],[[2929,2929],"valid"],[[2930,2935],"valid",[],"NV8"],[[2936,2945],"disallowed"],[[2946,2947],"valid"],[[2948,2948],"disallowed"],[[2949,2954],"valid"],[[2955,2957],"disallowed"],[[2958,2960],"valid"],[[2961,2961],"disallowed"],[[2962,2965],"valid"],[[2966,2968],"disallowed"],[[2969,2970],"valid"],[[2971,2971],"disallowed"],[[2972,2972],"valid"],[[2973,2973],"disallowed"],[[2974,2975],"valid"],[[2976,2978],"disallowed"],[[2979,2980],"valid"],[[2981,2983],"disallowed"],[[2984,2986],"valid"],[[2987,2989],"disallowed"],[[2990,2997],"valid"],[[2998,2998],"valid"],[[2999,3001],"valid"],[[3002,3005],"disallowed"],[[3006,3010],"valid"],[[3011,3013],"disallowed"],[[3014,3016],"valid"],[[3017,3017],"disallowed"],[[3018,3021],"valid"],[[3022,3023],"disallowed"],[[3024,3024],"valid"],[[3025,3030],"disallowed"],[[3031,3031],"valid"],[[3032,3045],"disallowed"],[[3046,3046],"valid"],[[3047,3055],"valid"],[[3056,3058],"valid",[],"NV8"],[[3059,3066],"valid",[],"NV8"],[[3067,3071],"disallowed"],[[3072,3072],"valid"],[[3073,3075],"valid"],[[3076,3076],"disallowed"],[[3077,3084],"valid"],[[3085,3085],"disallowed"],[[3086,3088],"valid"],[[3089,3089],"disallowed"],[[3090,3112],"valid"],[[3113,3113],"disallowed"],[[3114,3123],"valid"],[[3124,3124],"valid"],[[3125,3129],"valid"],[[3130,3132],"disallowed"],[[3133,3133],"valid"],[[3134,3140],"valid"],[[3141,3141],"disallowed"],[[3142,3144],"valid"],[[3145,3145],"disallowed"],[[3146,3149],"valid"],[[3150,3156],"disallowed"],[[3157,3158],"valid"],[[3159,3159],"disallowed"],[[3160,3161],"valid"],[[3162,3162],"valid"],[[3163,3167],"disallowed"],[[3168,3169],"valid"],[[3170,3171],"valid"],[[3172,3173],"disallowed"],[[3174,3183],"valid"],[[3184,3191],"disallowed"],[[3192,3199],"valid",[],"NV8"],[[3200,3200],"disallowed"],[[3201,3201],"valid"],[[3202,3203],"valid"],[[3204,3204],"disallowed"],[[3205,3212],"valid"],[[3213,3213],"disallowed"],[[3214,3216],"valid"],[[3217,3217],"disallowed"],[[3218,3240],"valid"],[[3241,3241],"disallowed"],[[3242,3251],"valid"],[[3252,3252],"disallowed"],[[3253,3257],"valid"],[[3258,3259],"disallowed"],[[3260,3261],"valid"],[[3262,3268],"valid"],[[3269,3269],"disallowed"],[[3270,3272],"valid"],[[3273,3273],"disallowed"],[[3274,3277],"valid"],[[3278,3284],"disallowed"],[[3285,3286],"valid"],[[3287,3293],"disallowed"],[[3294,3294],"valid"],[[3295,3295],"disallowed"],[[3296,3297],"valid"],[[3298,3299],"valid"],[[3300,3301],"disallowed"],[[3302,3311],"valid"],[[3312,3312],"disallowed"],[[3313,3314],"valid"],[[3315,3328],"disallowed"],[[3329,3329],"valid"],[[3330,3331],"valid"],[[3332,3332],"disallowed"],[[3333,3340],"valid"],[[3341,3341],"disallowed"],[[3342,3344],"valid"],[[3345,3345],"disallowed"],[[3346,3368],"valid"],[[3369,3369],"valid"],[[3370,3385],"valid"],[[3386,3386],"valid"],[[3387,3388],"disallowed"],[[3389,3389],"valid"],[[3390,3395],"valid"],[[3396,3396],"valid"],[[3397,3397],"disallowed"],[[3398,3400],"valid"],[[3401,3401],"disallowed"],[[3402,3405],"valid"],[[3406,3406],"valid"],[[3407,3414],"disallowed"],[[3415,3415],"valid"],[[3416,3422],"disallowed"],[[3423,3423],"valid"],[[3424,3425],"valid"],[[3426,3427],"valid"],[[3428,3429],"disallowed"],[[3430,3439],"valid"],[[3440,3445],"valid",[],"NV8"],[[3446,3448],"disallowed"],[[3449,3449],"valid",[],"NV8"],[[3450,3455],"valid"],[[3456,3457],"disallowed"],[[3458,3459],"valid"],[[3460,3460],"disallowed"],[[3461,3478],"valid"],[[3479,3481],"disallowed"],[[3482,3505],"valid"],[[3506,3506],"disallowed"],[[3507,3515],"valid"],[[3516,3516],"disallowed"],[[3517,3517],"valid"],[[3518,3519],"disallowed"],[[3520,3526],"valid"],[[3527,3529],"disallowed"],[[3530,3530],"valid"],[[3531,3534],"disallowed"],[[3535,3540],"valid"],[[3541,3541],"disallowed"],[[3542,3542],"valid"],[[3543,3543],"disallowed"],[[3544,3551],"valid"],[[3552,3557],"disallowed"],[[3558,3567],"valid"],[[3568,3569],"disallowed"],[[3570,3571],"valid"],[[3572,3572],"valid",[],"NV8"],[[3573,3584],"disallowed"],[[3585,3634],"valid"],[[3635,3635],"mapped",[3661,3634]],[[3636,3642],"valid"],[[3643,3646],"disallowed"],[[3647,3647],"valid",[],"NV8"],[[3648,3662],"valid"],[[3663,3663],"valid",[],"NV8"],[[3664,3673],"valid"],[[3674,3675],"valid",[],"NV8"],[[3676,3712],"disallowed"],[[3713,3714],"valid"],[[3715,3715],"disallowed"],[[3716,3716],"valid"],[[3717,3718],"disallowed"],[[3719,3720],"valid"],[[3721,3721],"disallowed"],[[3722,3722],"valid"],[[3723,3724],"disallowed"],[[3725,3725],"valid"],[[3726,3731],"disallowed"],[[3732,3735],"valid"],[[3736,3736],"disallowed"],[[3737,3743],"valid"],[[3744,3744],"disallowed"],[[3745,3747],"valid"],[[3748,3748],"disallowed"],[[3749,3749],"valid"],[[3750,3750],"disallowed"],[[3751,3751],"valid"],[[3752,3753],"disallowed"],[[3754,3755],"valid"],[[3756,3756],"disallowed"],[[3757,3762],"valid"],[[3763,3763],"mapped",[3789,3762]],[[3764,3769],"valid"],[[3770,3770],"disallowed"],[[3771,3773],"valid"],[[3774,3775],"disallowed"],[[3776,3780],"valid"],[[3781,3781],"disallowed"],[[3782,3782],"valid"],[[3783,3783],"disallowed"],[[3784,3789],"valid"],[[3790,3791],"disallowed"],[[3792,3801],"valid"],[[3802,3803],"disallowed"],[[3804,3804],"mapped",[3755,3737]],[[3805,3805],"mapped",[3755,3745]],[[3806,3807],"valid"],[[3808,3839],"disallowed"],[[3840,3840],"valid"],[[3841,3850],"valid",[],"NV8"],[[3851,3851],"valid"],[[3852,3852],"mapped",[3851]],[[3853,3863],"valid",[],"NV8"],[[3864,3865],"valid"],[[3866,3871],"valid",[],"NV8"],[[3872,3881],"valid"],[[3882,3892],"valid",[],"NV8"],[[3893,3893],"valid"],[[3894,3894],"valid",[],"NV8"],[[3895,3895],"valid"],[[3896,3896],"valid",[],"NV8"],[[3897,3897],"valid"],[[3898,3901],"valid",[],"NV8"],[[3902,3906],"valid"],[[3907,3907],"mapped",[3906,4023]],[[3908,3911],"valid"],[[3912,3912],"disallowed"],[[3913,3916],"valid"],[[3917,3917],"mapped",[3916,4023]],[[3918,3921],"valid"],[[3922,3922],"mapped",[3921,4023]],[[3923,3926],"valid"],[[3927,3927],"mapped",[3926,4023]],[[3928,3931],"valid"],[[3932,3932],"mapped",[3931,4023]],[[3933,3944],"valid"],[[3945,3945],"mapped",[3904,4021]],[[3946,3946],"valid"],[[3947,3948],"valid"],[[3949,3952],"disallowed"],[[3953,3954],"valid"],[[3955,3955],"mapped",[3953,3954]],[[3956,3956],"valid"],[[3957,3957],"mapped",[3953,3956]],[[3958,3958],"mapped",[4018,3968]],[[3959,3959],"mapped",[4018,3953,3968]],[[3960,3960],"mapped",[4019,3968]],[[3961,3961],"mapped",[4019,3953,3968]],[[3962,3968],"valid"],[[3969,3969],"mapped",[3953,3968]],[[3970,3972],"valid"],[[3973,3973],"valid",[],"NV8"],[[3974,3979],"valid"],[[3980,3983],"valid"],[[3984,3986],"valid"],[[3987,3987],"mapped",[3986,4023]],[[3988,3989],"valid"],[[3990,3990],"valid"],[[3991,3991],"valid"],[[3992,3992],"disallowed"],[[3993,3996],"valid"],[[3997,3997],"mapped",[3996,4023]],[[3998,4001],"valid"],[[4002,4002],"mapped",[4001,4023]],[[4003,4006],"valid"],[[4007,4007],"mapped",[4006,4023]],[[4008,4011],"valid"],[[4012,4012],"mapped",[4011,4023]],[[4013,4013],"valid"],[[4014,4016],"valid"],[[4017,4023],"valid"],[[4024,4024],"valid"],[[4025,4025],"mapped",[3984,4021]],[[4026,4028],"valid"],[[4029,4029],"disallowed"],[[4030,4037],"valid",[],"NV8"],[[4038,4038],"valid"],[[4039,4044],"valid",[],"NV8"],[[4045,4045],"disallowed"],[[4046,4046],"valid",[],"NV8"],[[4047,4047],"valid",[],"NV8"],[[4048,4049],"valid",[],"NV8"],[[4050,4052],"valid",[],"NV8"],[[4053,4056],"valid",[],"NV8"],[[4057,4058],"valid",[],"NV8"],[[4059,4095],"disallowed"],[[4096,4129],"valid"],[[4130,4130],"valid"],[[4131,4135],"valid"],[[4136,4136],"valid"],[[4137,4138],"valid"],[[4139,4139],"valid"],[[4140,4146],"valid"],[[4147,4149],"valid"],[[4150,4153],"valid"],[[4154,4159],"valid"],[[4160,4169],"valid"],[[4170,4175],"valid",[],"NV8"],[[4176,4185],"valid"],[[4186,4249],"valid"],[[4250,4253],"valid"],[[4254,4255],"valid",[],"NV8"],[[4256,4293],"disallowed"],[[4294,4294],"disallowed"],[[4295,4295],"mapped",[11559]],[[4296,4300],"disallowed"],[[4301,4301],"mapped",[11565]],[[4302,4303],"disallowed"],[[4304,4342],"valid"],[[4343,4344],"valid"],[[4345,4346],"valid"],[[4347,4347],"valid",[],"NV8"],[[4348,4348],"mapped",[4316]],[[4349,4351],"valid"],[[4352,4441],"valid",[],"NV8"],[[4442,4446],"valid",[],"NV8"],[[4447,4448],"disallowed"],[[4449,4514],"valid",[],"NV8"],[[4515,4519],"valid",[],"NV8"],[[4520,4601],"valid",[],"NV8"],[[4602,4607],"valid",[],"NV8"],[[4608,4614],"valid"],[[4615,4615],"valid"],[[4616,4678],"valid"],[[4679,4679],"valid"],[[4680,4680],"valid"],[[4681,4681],"disallowed"],[[4682,4685],"valid"],[[4686,4687],"disallowed"],[[4688,4694],"valid"],[[4695,4695],"disallowed"],[[4696,4696],"valid"],[[4697,4697],"disallowed"],[[4698,4701],"valid"],[[4702,4703],"disallowed"],[[4704,4742],"valid"],[[4743,4743],"valid"],[[4744,4744],"valid"],[[4745,4745],"disallowed"],[[4746,4749],"valid"],[[4750,4751],"disallowed"],[[4752,4782],"valid"],[[4783,4783],"valid"],[[4784,4784],"valid"],[[4785,4785],"disallowed"],[[4786,4789],"valid"],[[4790,4791],"disallowed"],[[4792,4798],"valid"],[[4799,4799],"disallowed"],[[4800,4800],"valid"],[[4801,4801],"disallowed"],[[4802,4805],"valid"],[[4806,4807],"disallowed"],[[4808,4814],"valid"],[[4815,4815],"valid"],[[4816,4822],"valid"],[[4823,4823],"disallowed"],[[4824,4846],"valid"],[[4847,4847],"valid"],[[4848,4878],"valid"],[[4879,4879],"valid"],[[4880,4880],"valid"],[[4881,4881],"disallowed"],[[4882,4885],"valid"],[[4886,4887],"disallowed"],[[4888,4894],"valid"],[[4895,4895],"valid"],[[4896,4934],"valid"],[[4935,4935],"valid"],[[4936,4954],"valid"],[[4955,4956],"disallowed"],[[4957,4958],"valid"],[[4959,4959],"valid"],[[4960,4960],"valid",[],"NV8"],[[4961,4988],"valid",[],"NV8"],[[4989,4991],"disallowed"],[[4992,5007],"valid"],[[5008,5017],"valid",[],"NV8"],[[5018,5023],"disallowed"],[[5024,5108],"valid"],[[5109,5109],"valid"],[[5110,5111],"disallowed"],[[5112,5112],"mapped",[5104]],[[5113,5113],"mapped",[5105]],[[5114,5114],"mapped",[5106]],[[5115,5115],"mapped",[5107]],[[5116,5116],"mapped",[5108]],[[5117,5117],"mapped",[5109]],[[5118,5119],"disallowed"],[[5120,5120],"valid",[],"NV8"],[[5121,5740],"valid"],[[5741,5742],"valid",[],"NV8"],[[5743,5750],"valid"],[[5751,5759],"valid"],[[5760,5760],"disallowed"],[[5761,5786],"valid"],[[5787,5788],"valid",[],"NV8"],[[5789,5791],"disallowed"],[[5792,5866],"valid"],[[5867,5872],"valid",[],"NV8"],[[5873,5880],"valid"],[[5881,5887],"disallowed"],[[5888,5900],"valid"],[[5901,5901],"disallowed"],[[5902,5908],"valid"],[[5909,5919],"disallowed"],[[5920,5940],"valid"],[[5941,5942],"valid",[],"NV8"],[[5943,5951],"disallowed"],[[5952,5971],"valid"],[[5972,5983],"disallowed"],[[5984,5996],"valid"],[[5997,5997],"disallowed"],[[5998,6000],"valid"],[[6001,6001],"disallowed"],[[6002,6003],"valid"],[[6004,6015],"disallowed"],[[6016,6067],"valid"],[[6068,6069],"disallowed"],[[6070,6099],"valid"],[[6100,6102],"valid",[],"NV8"],[[6103,6103],"valid"],[[6104,6107],"valid",[],"NV8"],[[6108,6108],"valid"],[[6109,6109],"valid"],[[6110,6111],"disallowed"],[[6112,6121],"valid"],[[6122,6127],"disallowed"],[[6128,6137],"valid",[],"NV8"],[[6138,6143],"disallowed"],[[6144,6149],"valid",[],"NV8"],[[6150,6150],"disallowed"],[[6151,6154],"valid",[],"NV8"],[[6155,6157],"ignored"],[[6158,6158],"disallowed"],[[6159,6159],"disallowed"],[[6160,6169],"valid"],[[6170,6175],"disallowed"],[[6176,6263],"valid"],[[6264,6271],"disallowed"],[[6272,6313],"valid"],[[6314,6314],"valid"],[[6315,6319],"disallowed"],[[6320,6389],"valid"],[[6390,6399],"disallowed"],[[6400,6428],"valid"],[[6429,6430],"valid"],[[6431,6431],"disallowed"],[[6432,6443],"valid"],[[6444,6447],"disallowed"],[[6448,6459],"valid"],[[6460,6463],"disallowed"],[[6464,6464],"valid",[],"NV8"],[[6465,6467],"disallowed"],[[6468,6469],"valid",[],"NV8"],[[6470,6509],"valid"],[[6510,6511],"disallowed"],[[6512,6516],"valid"],[[6517,6527],"disallowed"],[[6528,6569],"valid"],[[6570,6571],"valid"],[[6572,6575],"disallowed"],[[6576,6601],"valid"],[[6602,6607],"disallowed"],[[6608,6617],"valid"],[[6618,6618],"valid",[],"XV8"],[[6619,6621],"disallowed"],[[6622,6623],"valid",[],"NV8"],[[6624,6655],"valid",[],"NV8"],[[6656,6683],"valid"],[[6684,6685],"disallowed"],[[6686,6687],"valid",[],"NV8"],[[6688,6750],"valid"],[[6751,6751],"disallowed"],[[6752,6780],"valid"],[[6781,6782],"disallowed"],[[6783,6793],"valid"],[[6794,6799],"disallowed"],[[6800,6809],"valid"],[[6810,6815],"disallowed"],[[6816,6822],"valid",[],"NV8"],[[6823,6823],"valid"],[[6824,6829],"valid",[],"NV8"],[[6830,6831],"disallowed"],[[6832,6845],"valid"],[[6846,6846],"valid",[],"NV8"],[[6847,6911],"disallowed"],[[6912,6987],"valid"],[[6988,6991],"disallowed"],[[6992,7001],"valid"],[[7002,7018],"valid",[],"NV8"],[[7019,7027],"valid"],[[7028,7036],"valid",[],"NV8"],[[7037,7039],"disallowed"],[[7040,7082],"valid"],[[7083,7085],"valid"],[[7086,7097],"valid"],[[7098,7103],"valid"],[[7104,7155],"valid"],[[7156,7163],"disallowed"],[[7164,7167],"valid",[],"NV8"],[[7168,7223],"valid"],[[7224,7226],"disallowed"],[[7227,7231],"valid",[],"NV8"],[[7232,7241],"valid"],[[7242,7244],"disallowed"],[[7245,7293],"valid"],[[7294,7295],"valid",[],"NV8"],[[7296,7359],"disallowed"],[[7360,7367],"valid",[],"NV8"],[[7368,7375],"disallowed"],[[7376,7378],"valid"],[[7379,7379],"valid",[],"NV8"],[[7380,7410],"valid"],[[7411,7414],"valid"],[[7415,7415],"disallowed"],[[7416,7417],"valid"],[[7418,7423],"disallowed"],[[7424,7467],"valid"],[[7468,7468],"mapped",[97]],[[7469,7469],"mapped",[230]],[[7470,7470],"mapped",[98]],[[7471,7471],"valid"],[[7472,7472],"mapped",[100]],[[7473,7473],"mapped",[101]],[[7474,7474],"mapped",[477]],[[7475,7475],"mapped",[103]],[[7476,7476],"mapped",[104]],[[7477,7477],"mapped",[105]],[[7478,7478],"mapped",[106]],[[7479,7479],"mapped",[107]],[[7480,7480],"mapped",[108]],[[7481,7481],"mapped",[109]],[[7482,7482],"mapped",[110]],[[7483,7483],"valid"],[[7484,7484],"mapped",[111]],[[7485,7485],"mapped",[547]],[[7486,7486],"mapped",[112]],[[7487,7487],"mapped",[114]],[[7488,7488],"mapped",[116]],[[7489,7489],"mapped",[117]],[[7490,7490],"mapped",[119]],[[7491,7491],"mapped",[97]],[[7492,7492],"mapped",[592]],[[7493,7493],"mapped",[593]],[[7494,7494],"mapped",[7426]],[[7495,7495],"mapped",[98]],[[7496,7496],"mapped",[100]],[[7497,7497],"mapped",[101]],[[7498,7498],"mapped",[601]],[[7499,7499],"mapped",[603]],[[7500,7500],"mapped",[604]],[[7501,7501],"mapped",[103]],[[7502,7502],"valid"],[[7503,7503],"mapped",[107]],[[7504,7504],"mapped",[109]],[[7505,7505],"mapped",[331]],[[7506,7506],"mapped",[111]],[[7507,7507],"mapped",[596]],[[7508,7508],"mapped",[7446]],[[7509,7509],"mapped",[7447]],[[7510,7510],"mapped",[112]],[[7511,7511],"mapped",[116]],[[7512,7512],"mapped",[117]],[[7513,7513],"mapped",[7453]],[[7514,7514],"mapped",[623]],[[7515,7515],"mapped",[118]],[[7516,7516],"mapped",[7461]],[[7517,7517],"mapped",[946]],[[7518,7518],"mapped",[947]],[[7519,7519],"mapped",[948]],[[7520,7520],"mapped",[966]],[[7521,7521],"mapped",[967]],[[7522,7522],"mapped",[105]],[[7523,7523],"mapped",[114]],[[7524,7524],"mapped",[117]],[[7525,7525],"mapped",[118]],[[7526,7526],"mapped",[946]],[[7527,7527],"mapped",[947]],[[7528,7528],"mapped",[961]],[[7529,7529],"mapped",[966]],[[7530,7530],"mapped",[967]],[[7531,7531],"valid"],[[7532,7543],"valid"],[[7544,7544],"mapped",[1085]],[[7545,7578],"valid"],[[7579,7579],"mapped",[594]],[[7580,7580],"mapped",[99]],[[7581,7581],"mapped",[597]],[[7582,7582],"mapped",[240]],[[7583,7583],"mapped",[604]],[[7584,7584],"mapped",[102]],[[7585,7585],"mapped",[607]],[[7586,7586],"mapped",[609]],[[7587,7587],"mapped",[613]],[[7588,7588],"mapped",[616]],[[7589,7589],"mapped",[617]],[[7590,7590],"mapped",[618]],[[7591,7591],"mapped",[7547]],[[7592,7592],"mapped",[669]],[[7593,7593],"mapped",[621]],[[7594,7594],"mapped",[7557]],[[7595,7595],"mapped",[671]],[[7596,7596],"mapped",[625]],[[7597,7597],"mapped",[624]],[[7598,7598],"mapped",[626]],[[7599,7599],"mapped",[627]],[[7600,7600],"mapped",[628]],[[7601,7601],"mapped",[629]],[[7602,7602],"mapped",[632]],[[7603,7603],"mapped",[642]],[[7604,7604],"mapped",[643]],[[7605,7605],"mapped",[427]],[[7606,7606],"mapped",[649]],[[7607,7607],"mapped",[650]],[[7608,7608],"mapped",[7452]],[[7609,7609],"mapped",[651]],[[7610,7610],"mapped",[652]],[[7611,7611],"mapped",[122]],[[7612,7612],"mapped",[656]],[[7613,7613],"mapped",[657]],[[7614,7614],"mapped",[658]],[[7615,7615],"mapped",[952]],[[7616,7619],"valid"],[[7620,7626],"valid"],[[7627,7654],"valid"],[[7655,7669],"valid"],[[7670,7675],"disallowed"],[[7676,7676],"valid"],[[7677,7677],"valid"],[[7678,7679],"valid"],[[7680,7680],"mapped",[7681]],[[7681,7681],"valid"],[[7682,7682],"mapped",[7683]],[[7683,7683],"valid"],[[7684,7684],"mapped",[7685]],[[7685,7685],"valid"],[[7686,7686],"mapped",[7687]],[[7687,7687],"valid"],[[7688,7688],"mapped",[7689]],[[7689,7689],"valid"],[[7690,7690],"mapped",[7691]],[[7691,7691],"valid"],[[7692,7692],"mapped",[7693]],[[7693,7693],"valid"],[[7694,7694],"mapped",[7695]],[[7695,7695],"valid"],[[7696,7696],"mapped",[7697]],[[7697,7697],"valid"],[[7698,7698],"mapped",[7699]],[[7699,7699],"valid"],[[7700,7700],"mapped",[7701]],[[7701,7701],"valid"],[[7702,7702],"mapped",[7703]],[[7703,7703],"valid"],[[7704,7704],"mapped",[7705]],[[7705,7705],"valid"],[[7706,7706],"mapped",[7707]],[[7707,7707],"valid"],[[7708,7708],"mapped",[7709]],[[7709,7709],"valid"],[[7710,7710],"mapped",[7711]],[[7711,7711],"valid"],[[7712,7712],"mapped",[7713]],[[7713,7713],"valid"],[[7714,7714],"mapped",[7715]],[[7715,7715],"valid"],[[7716,7716],"mapped",[7717]],[[7717,7717],"valid"],[[7718,7718],"mapped",[7719]],[[7719,7719],"valid"],[[7720,7720],"mapped",[7721]],[[7721,7721],"valid"],[[7722,7722],"mapped",[7723]],[[7723,7723],"valid"],[[7724,7724],"mapped",[7725]],[[7725,7725],"valid"],[[7726,7726],"mapped",[7727]],[[7727,7727],"valid"],[[7728,7728],"mapped",[7729]],[[7729,7729],"valid"],[[7730,7730],"mapped",[7731]],[[7731,7731],"valid"],[[7732,7732],"mapped",[7733]],[[7733,7733],"valid"],[[7734,7734],"mapped",[7735]],[[7735,7735],"valid"],[[7736,7736],"mapped",[7737]],[[7737,7737],"valid"],[[7738,7738],"mapped",[7739]],[[7739,7739],"valid"],[[7740,7740],"mapped",[7741]],[[7741,7741],"valid"],[[7742,7742],"mapped",[7743]],[[7743,7743],"valid"],[[7744,7744],"mapped",[7745]],[[7745,7745],"valid"],[[7746,7746],"mapped",[7747]],[[7747,7747],"valid"],[[7748,7748],"mapped",[7749]],[[7749,7749],"valid"],[[7750,7750],"mapped",[7751]],[[7751,7751],"valid"],[[7752,7752],"mapped",[7753]],[[7753,7753],"valid"],[[7754,7754],"mapped",[7755]],[[7755,7755],"valid"],[[7756,7756],"mapped",[7757]],[[7757,7757],"valid"],[[7758,7758],"mapped",[7759]],[[7759,7759],"valid"],[[7760,7760],"mapped",[7761]],[[7761,7761],"valid"],[[7762,7762],"mapped",[7763]],[[7763,7763],"valid"],[[7764,7764],"mapped",[7765]],[[7765,7765],"valid"],[[7766,7766],"mapped",[7767]],[[7767,7767],"valid"],[[7768,7768],"mapped",[7769]],[[7769,7769],"valid"],[[7770,7770],"mapped",[7771]],[[7771,7771],"valid"],[[7772,7772],"mapped",[7773]],[[7773,7773],"valid"],[[7774,7774],"mapped",[7775]],[[7775,7775],"valid"],[[7776,7776],"mapped",[7777]],[[7777,7777],"valid"],[[7778,7778],"mapped",[7779]],[[7779,7779],"valid"],[[7780,7780],"mapped",[7781]],[[7781,7781],"valid"],[[7782,7782],"mapped",[7783]],[[7783,7783],"valid"],[[7784,7784],"mapped",[7785]],[[7785,7785],"valid"],[[7786,7786],"mapped",[7787]],[[7787,7787],"valid"],[[7788,7788],"mapped",[7789]],[[7789,7789],"valid"],[[7790,7790],"mapped",[7791]],[[7791,7791],"valid"],[[7792,7792],"mapped",[7793]],[[7793,7793],"valid"],[[7794,7794],"mapped",[7795]],[[7795,7795],"valid"],[[7796,7796],"mapped",[7797]],[[7797,7797],"valid"],[[7798,7798],"mapped",[7799]],[[7799,7799],"valid"],[[7800,7800],"mapped",[7801]],[[7801,7801],"valid"],[[7802,7802],"mapped",[7803]],[[7803,7803],"valid"],[[7804,7804],"mapped",[7805]],[[7805,7805],"valid"],[[7806,7806],"mapped",[7807]],[[7807,7807],"valid"],[[7808,7808],"mapped",[7809]],[[7809,7809],"valid"],[[7810,7810],"mapped",[7811]],[[7811,7811],"valid"],[[7812,7812],"mapped",[7813]],[[7813,7813],"valid"],[[7814,7814],"mapped",[7815]],[[7815,7815],"valid"],[[7816,7816],"mapped",[7817]],[[7817,7817],"valid"],[[7818,7818],"mapped",[7819]],[[7819,7819],"valid"],[[7820,7820],"mapped",[7821]],[[7821,7821],"valid"],[[7822,7822],"mapped",[7823]],[[7823,7823],"valid"],[[7824,7824],"mapped",[7825]],[[7825,7825],"valid"],[[7826,7826],"mapped",[7827]],[[7827,7827],"valid"],[[7828,7828],"mapped",[7829]],[[7829,7833],"valid"],[[7834,7834],"mapped",[97,702]],[[7835,7835],"mapped",[7777]],[[7836,7837],"valid"],[[7838,7838],"mapped",[115,115]],[[7839,7839],"valid"],[[7840,7840],"mapped",[7841]],[[7841,7841],"valid"],[[7842,7842],"mapped",[7843]],[[7843,7843],"valid"],[[7844,7844],"mapped",[7845]],[[7845,7845],"valid"],[[7846,7846],"mapped",[7847]],[[7847,7847],"valid"],[[7848,7848],"mapped",[7849]],[[7849,7849],"valid"],[[7850,7850],"mapped",[7851]],[[7851,7851],"valid"],[[7852,7852],"mapped",[7853]],[[7853,7853],"valid"],[[7854,7854],"mapped",[7855]],[[7855,7855],"valid"],[[7856,7856],"mapped",[7857]],[[7857,7857],"valid"],[[7858,7858],"mapped",[7859]],[[7859,7859],"valid"],[[7860,7860],"mapped",[7861]],[[7861,7861],"valid"],[[7862,7862],"mapped",[7863]],[[7863,7863],"valid"],[[7864,7864],"mapped",[7865]],[[7865,7865],"valid"],[[7866,7866],"mapped",[7867]],[[7867,7867],"valid"],[[7868,7868],"mapped",[7869]],[[7869,7869],"valid"],[[7870,7870],"mapped",[7871]],[[7871,7871],"valid"],[[7872,7872],"mapped",[7873]],[[7873,7873],"valid"],[[7874,7874],"mapped",[7875]],[[7875,7875],"valid"],[[7876,7876],"mapped",[7877]],[[7877,7877],"valid"],[[7878,7878],"mapped",[7879]],[[7879,7879],"valid"],[[7880,7880],"mapped",[7881]],[[7881,7881],"valid"],[[7882,7882],"mapped",[7883]],[[7883,7883],"valid"],[[7884,7884],"mapped",[7885]],[[7885,7885],"valid"],[[7886,7886],"mapped",[7887]],[[7887,7887],"valid"],[[7888,7888],"mapped",[7889]],[[7889,7889],"valid"],[[7890,7890],"mapped",[7891]],[[7891,7891],"valid"],[[7892,7892],"mapped",[7893]],[[7893,7893],"valid"],[[7894,7894],"mapped",[7895]],[[7895,7895],"valid"],[[7896,7896],"mapped",[7897]],[[7897,7897],"valid"],[[7898,7898],"mapped",[7899]],[[7899,7899],"valid"],[[7900,7900],"mapped",[7901]],[[7901,7901],"valid"],[[7902,7902],"mapped",[7903]],[[7903,7903],"valid"],[[7904,7904],"mapped",[7905]],[[7905,7905],"valid"],[[7906,7906],"mapped",[7907]],[[7907,7907],"valid"],[[7908,7908],"mapped",[7909]],[[7909,7909],"valid"],[[7910,7910],"mapped",[7911]],[[7911,7911],"valid"],[[7912,7912],"mapped",[7913]],[[7913,7913],"valid"],[[7914,7914],"mapped",[7915]],[[7915,7915],"valid"],[[7916,7916],"mapped",[7917]],[[7917,7917],"valid"],[[7918,7918],"mapped",[7919]],[[7919,7919],"valid"],[[7920,7920],"mapped",[7921]],[[7921,7921],"valid"],[[7922,7922],"mapped",[7923]],[[7923,7923],"valid"],[[7924,7924],"mapped",[7925]],[[7925,7925],"valid"],[[7926,7926],"mapped",[7927]],[[7927,7927],"valid"],[[7928,7928],"mapped",[7929]],[[7929,7929],"valid"],[[7930,7930],"mapped",[7931]],[[7931,7931],"valid"],[[7932,7932],"mapped",[7933]],[[7933,7933],"valid"],[[7934,7934],"mapped",[7935]],[[7935,7935],"valid"],[[7936,7943],"valid"],[[7944,7944],"mapped",[7936]],[[7945,7945],"mapped",[7937]],[[7946,7946],"mapped",[7938]],[[7947,7947],"mapped",[7939]],[[7948,7948],"mapped",[7940]],[[7949,7949],"mapped",[7941]],[[7950,7950],"mapped",[7942]],[[7951,7951],"mapped",[7943]],[[7952,7957],"valid"],[[7958,7959],"disallowed"],[[7960,7960],"mapped",[7952]],[[7961,7961],"mapped",[7953]],[[7962,7962],"mapped",[7954]],[[7963,7963],"mapped",[7955]],[[7964,7964],"mapped",[7956]],[[7965,7965],"mapped",[7957]],[[7966,7967],"disallowed"],[[7968,7975],"valid"],[[7976,7976],"mapped",[7968]],[[7977,7977],"mapped",[7969]],[[7978,7978],"mapped",[7970]],[[7979,7979],"mapped",[7971]],[[7980,7980],"mapped",[7972]],[[7981,7981],"mapped",[7973]],[[7982,7982],"mapped",[7974]],[[7983,7983],"mapped",[7975]],[[7984,7991],"valid"],[[7992,7992],"mapped",[7984]],[[7993,7993],"mapped",[7985]],[[7994,7994],"mapped",[7986]],[[7995,7995],"mapped",[7987]],[[7996,7996],"mapped",[7988]],[[7997,7997],"mapped",[7989]],[[7998,7998],"mapped",[7990]],[[7999,7999],"mapped",[7991]],[[8000,8005],"valid"],[[8006,8007],"disallowed"],[[8008,8008],"mapped",[8000]],[[8009,8009],"mapped",[8001]],[[8010,8010],"mapped",[8002]],[[8011,8011],"mapped",[8003]],[[8012,8012],"mapped",[8004]],[[8013,8013],"mapped",[8005]],[[8014,8015],"disallowed"],[[8016,8023],"valid"],[[8024,8024],"disallowed"],[[8025,8025],"mapped",[8017]],[[8026,8026],"disallowed"],[[8027,8027],"mapped",[8019]],[[8028,8028],"disallowed"],[[8029,8029],"mapped",[8021]],[[8030,8030],"disallowed"],[[8031,8031],"mapped",[8023]],[[8032,8039],"valid"],[[8040,8040],"mapped",[8032]],[[8041,8041],"mapped",[8033]],[[8042,8042],"mapped",[8034]],[[8043,8043],"mapped",[8035]],[[8044,8044],"mapped",[8036]],[[8045,8045],"mapped",[8037]],[[8046,8046],"mapped",[8038]],[[8047,8047],"mapped",[8039]],[[8048,8048],"valid"],[[8049,8049],"mapped",[940]],[[8050,8050],"valid"],[[8051,8051],"mapped",[941]],[[8052,8052],"valid"],[[8053,8053],"mapped",[942]],[[8054,8054],"valid"],[[8055,8055],"mapped",[943]],[[8056,8056],"valid"],[[8057,8057],"mapped",[972]],[[8058,8058],"valid"],[[8059,8059],"mapped",[973]],[[8060,8060],"valid"],[[8061,8061],"mapped",[974]],[[8062,8063],"disallowed"],[[8064,8064],"mapped",[7936,953]],[[8065,8065],"mapped",[7937,953]],[[8066,8066],"mapped",[7938,953]],[[8067,8067],"mapped",[7939,953]],[[8068,8068],"mapped",[7940,953]],[[8069,8069],"mapped",[7941,953]],[[8070,8070],"mapped",[7942,953]],[[8071,8071],"mapped",[7943,953]],[[8072,8072],"mapped",[7936,953]],[[8073,8073],"mapped",[7937,953]],[[8074,8074],"mapped",[7938,953]],[[8075,8075],"mapped",[7939,953]],[[8076,8076],"mapped",[7940,953]],[[8077,8077],"mapped",[7941,953]],[[8078,8078],"mapped",[7942,953]],[[8079,8079],"mapped",[7943,953]],[[8080,8080],"mapped",[7968,953]],[[8081,8081],"mapped",[7969,953]],[[8082,8082],"mapped",[7970,953]],[[8083,8083],"mapped",[7971,953]],[[8084,8084],"mapped",[7972,953]],[[8085,8085],"mapped",[7973,953]],[[8086,8086],"mapped",[7974,953]],[[8087,8087],"mapped",[7975,953]],[[8088,8088],"mapped",[7968,953]],[[8089,8089],"mapped",[7969,953]],[[8090,8090],"mapped",[7970,953]],[[8091,8091],"mapped",[7971,953]],[[8092,8092],"mapped",[7972,953]],[[8093,8093],"mapped",[7973,953]],[[8094,8094],"mapped",[7974,953]],[[8095,8095],"mapped",[7975,953]],[[8096,8096],"mapped",[8032,953]],[[8097,8097],"mapped",[8033,953]],[[8098,8098],"mapped",[8034,953]],[[8099,8099],"mapped",[8035,953]],[[8100,8100],"mapped",[8036,953]],[[8101,8101],"mapped",[8037,953]],[[8102,8102],"mapped",[8038,953]],[[8103,8103],"mapped",[8039,953]],[[8104,8104],"mapped",[8032,953]],[[8105,8105],"mapped",[8033,953]],[[8106,8106],"mapped",[8034,953]],[[8107,8107],"mapped",[8035,953]],[[8108,8108],"mapped",[8036,953]],[[8109,8109],"mapped",[8037,953]],[[8110,8110],"mapped",[8038,953]],[[8111,8111],"mapped",[8039,953]],[[8112,8113],"valid"],[[8114,8114],"mapped",[8048,953]],[[8115,8115],"mapped",[945,953]],[[8116,8116],"mapped",[940,953]],[[8117,8117],"disallowed"],[[8118,8118],"valid"],[[8119,8119],"mapped",[8118,953]],[[8120,8120],"mapped",[8112]],[[8121,8121],"mapped",[8113]],[[8122,8122],"mapped",[8048]],[[8123,8123],"mapped",[940]],[[8124,8124],"mapped",[945,953]],[[8125,8125],"disallowed_STD3_mapped",[32,787]],[[8126,8126],"mapped",[953]],[[8127,8127],"disallowed_STD3_mapped",[32,787]],[[8128,8128],"disallowed_STD3_mapped",[32,834]],[[8129,8129],"disallowed_STD3_mapped",[32,776,834]],[[8130,8130],"mapped",[8052,953]],[[8131,8131],"mapped",[951,953]],[[8132,8132],"mapped",[942,953]],[[8133,8133],"disallowed"],[[8134,8134],"valid"],[[8135,8135],"mapped",[8134,953]],[[8136,8136],"mapped",[8050]],[[8137,8137],"mapped",[941]],[[8138,8138],"mapped",[8052]],[[8139,8139],"mapped",[942]],[[8140,8140],"mapped",[951,953]],[[8141,8141],"disallowed_STD3_mapped",[32,787,768]],[[8142,8142],"disallowed_STD3_mapped",[32,787,769]],[[8143,8143],"disallowed_STD3_mapped",[32,787,834]],[[8144,8146],"valid"],[[8147,8147],"mapped",[912]],[[8148,8149],"disallowed"],[[8150,8151],"valid"],[[8152,8152],"mapped",[8144]],[[8153,8153],"mapped",[8145]],[[8154,8154],"mapped",[8054]],[[8155,8155],"mapped",[943]],[[8156,8156],"disallowed"],[[8157,8157],"disallowed_STD3_mapped",[32,788,768]],[[8158,8158],"disallowed_STD3_mapped",[32,788,769]],[[8159,8159],"disallowed_STD3_mapped",[32,788,834]],[[8160,8162],"valid"],[[8163,8163],"mapped",[944]],[[8164,8167],"valid"],[[8168,8168],"mapped",[8160]],[[8169,8169],"mapped",[8161]],[[8170,8170],"mapped",[8058]],[[8171,8171],"mapped",[973]],[[8172,8172],"mapped",[8165]],[[8173,8173],"disallowed_STD3_mapped",[32,776,768]],[[8174,8174],"disallowed_STD3_mapped",[32,776,769]],[[8175,8175],"disallowed_STD3_mapped",[96]],[[8176,8177],"disallowed"],[[8178,8178],"mapped",[8060,953]],[[8179,8179],"mapped",[969,953]],[[8180,8180],"mapped",[974,953]],[[8181,8181],"disallowed"],[[8182,8182],"valid"],[[8183,8183],"mapped",[8182,953]],[[8184,8184],"mapped",[8056]],[[8185,8185],"mapped",[972]],[[8186,8186],"mapped",[8060]],[[8187,8187],"mapped",[974]],[[8188,8188],"mapped",[969,953]],[[8189,8189],"disallowed_STD3_mapped",[32,769]],[[8190,8190],"disallowed_STD3_mapped",[32,788]],[[8191,8191],"disallowed"],[[8192,8202],"disallowed_STD3_mapped",[32]],[[8203,8203],"ignored"],[[8204,8205],"deviation",[]],[[8206,8207],"disallowed"],[[8208,8208],"valid",[],"NV8"],[[8209,8209],"mapped",[8208]],[[8210,8214],"valid",[],"NV8"],[[8215,8215],"disallowed_STD3_mapped",[32,819]],[[8216,8227],"valid",[],"NV8"],[[8228,8230],"disallowed"],[[8231,8231],"valid",[],"NV8"],[[8232,8238],"disallowed"],[[8239,8239],"disallowed_STD3_mapped",[32]],[[8240,8242],"valid",[],"NV8"],[[8243,8243],"mapped",[8242,8242]],[[8244,8244],"mapped",[8242,8242,8242]],[[8245,8245],"valid",[],"NV8"],[[8246,8246],"mapped",[8245,8245]],[[8247,8247],"mapped",[8245,8245,8245]],[[8248,8251],"valid",[],"NV8"],[[8252,8252],"disallowed_STD3_mapped",[33,33]],[[8253,8253],"valid",[],"NV8"],[[8254,8254],"disallowed_STD3_mapped",[32,773]],[[8255,8262],"valid",[],"NV8"],[[8263,8263],"disallowed_STD3_mapped",[63,63]],[[8264,8264],"disallowed_STD3_mapped",[63,33]],[[8265,8265],"disallowed_STD3_mapped",[33,63]],[[8266,8269],"valid",[],"NV8"],[[8270,8274],"valid",[],"NV8"],[[8275,8276],"valid",[],"NV8"],[[8277,8278],"valid",[],"NV8"],[[8279,8279],"mapped",[8242,8242,8242,8242]],[[8280,8286],"valid",[],"NV8"],[[8287,8287],"disallowed_STD3_mapped",[32]],[[8288,8288],"ignored"],[[8289,8291],"disallowed"],[[8292,8292],"ignored"],[[8293,8293],"disallowed"],[[8294,8297],"disallowed"],[[8298,8303],"disallowed"],[[8304,8304],"mapped",[48]],[[8305,8305],"mapped",[105]],[[8306,8307],"disallowed"],[[8308,8308],"mapped",[52]],[[8309,8309],"mapped",[53]],[[8310,8310],"mapped",[54]],[[8311,8311],"mapped",[55]],[[8312,8312],"mapped",[56]],[[8313,8313],"mapped",[57]],[[8314,8314],"disallowed_STD3_mapped",[43]],[[8315,8315],"mapped",[8722]],[[8316,8316],"disallowed_STD3_mapped",[61]],[[8317,8317],"disallowed_STD3_mapped",[40]],[[8318,8318],"disallowed_STD3_mapped",[41]],[[8319,8319],"mapped",[110]],[[8320,8320],"mapped",[48]],[[8321,8321],"mapped",[49]],[[8322,8322],"mapped",[50]],[[8323,8323],"mapped",[51]],[[8324,8324],"mapped",[52]],[[8325,8325],"mapped",[53]],[[8326,8326],"mapped",[54]],[[8327,8327],"mapped",[55]],[[8328,8328],"mapped",[56]],[[8329,8329],"mapped",[57]],[[8330,8330],"disallowed_STD3_mapped",[43]],[[8331,8331],"mapped",[8722]],[[8332,8332],"disallowed_STD3_mapped",[61]],[[8333,8333],"disallowed_STD3_mapped",[40]],[[8334,8334],"disallowed_STD3_mapped",[41]],[[8335,8335],"disallowed"],[[8336,8336],"mapped",[97]],[[8337,8337],"mapped",[101]],[[8338,8338],"mapped",[111]],[[8339,8339],"mapped",[120]],[[8340,8340],"mapped",[601]],[[8341,8341],"mapped",[104]],[[8342,8342],"mapped",[107]],[[8343,8343],"mapped",[108]],[[8344,8344],"mapped",[109]],[[8345,8345],"mapped",[110]],[[8346,8346],"mapped",[112]],[[8347,8347],"mapped",[115]],[[8348,8348],"mapped",[116]],[[8349,8351],"disallowed"],[[8352,8359],"valid",[],"NV8"],[[8360,8360],"mapped",[114,115]],[[8361,8362],"valid",[],"NV8"],[[8363,8363],"valid",[],"NV8"],[[8364,8364],"valid",[],"NV8"],[[8365,8367],"valid",[],"NV8"],[[8368,8369],"valid",[],"NV8"],[[8370,8373],"valid",[],"NV8"],[[8374,8376],"valid",[],"NV8"],[[8377,8377],"valid",[],"NV8"],[[8378,8378],"valid",[],"NV8"],[[8379,8381],"valid",[],"NV8"],[[8382,8382],"valid",[],"NV8"],[[8383,8399],"disallowed"],[[8400,8417],"valid",[],"NV8"],[[8418,8419],"valid",[],"NV8"],[[8420,8426],"valid",[],"NV8"],[[8427,8427],"valid",[],"NV8"],[[8428,8431],"valid",[],"NV8"],[[8432,8432],"valid",[],"NV8"],[[8433,8447],"disallowed"],[[8448,8448],"disallowed_STD3_mapped",[97,47,99]],[[8449,8449],"disallowed_STD3_mapped",[97,47,115]],[[8450,8450],"mapped",[99]],[[8451,8451],"mapped",[176,99]],[[8452,8452],"valid",[],"NV8"],[[8453,8453],"disallowed_STD3_mapped",[99,47,111]],[[8454,8454],"disallowed_STD3_mapped",[99,47,117]],[[8455,8455],"mapped",[603]],[[8456,8456],"valid",[],"NV8"],[[8457,8457],"mapped",[176,102]],[[8458,8458],"mapped",[103]],[[8459,8462],"mapped",[104]],[[8463,8463],"mapped",[295]],[[8464,8465],"mapped",[105]],[[8466,8467],"mapped",[108]],[[8468,8468],"valid",[],"NV8"],[[8469,8469],"mapped",[110]],[[8470,8470],"mapped",[110,111]],[[8471,8472],"valid",[],"NV8"],[[8473,8473],"mapped",[112]],[[8474,8474],"mapped",[113]],[[8475,8477],"mapped",[114]],[[8478,8479],"valid",[],"NV8"],[[8480,8480],"mapped",[115,109]],[[8481,8481],"mapped",[116,101,108]],[[8482,8482],"mapped",[116,109]],[[8483,8483],"valid",[],"NV8"],[[8484,8484],"mapped",[122]],[[8485,8485],"valid",[],"NV8"],[[8486,8486],"mapped",[969]],[[8487,8487],"valid",[],"NV8"],[[8488,8488],"mapped",[122]],[[8489,8489],"valid",[],"NV8"],[[8490,8490],"mapped",[107]],[[8491,8491],"mapped",[229]],[[8492,8492],"mapped",[98]],[[8493,8493],"mapped",[99]],[[8494,8494],"valid",[],"NV8"],[[8495,8496],"mapped",[101]],[[8497,8497],"mapped",[102]],[[8498,8498],"disallowed"],[[8499,8499],"mapped",[109]],[[8500,8500],"mapped",[111]],[[8501,8501],"mapped",[1488]],[[8502,8502],"mapped",[1489]],[[8503,8503],"mapped",[1490]],[[8504,8504],"mapped",[1491]],[[8505,8505],"mapped",[105]],[[8506,8506],"valid",[],"NV8"],[[8507,8507],"mapped",[102,97,120]],[[8508,8508],"mapped",[960]],[[8509,8510],"mapped",[947]],[[8511,8511],"mapped",[960]],[[8512,8512],"mapped",[8721]],[[8513,8516],"valid",[],"NV8"],[[8517,8518],"mapped",[100]],[[8519,8519],"mapped",[101]],[[8520,8520],"mapped",[105]],[[8521,8521],"mapped",[106]],[[8522,8523],"valid",[],"NV8"],[[8524,8524],"valid",[],"NV8"],[[8525,8525],"valid",[],"NV8"],[[8526,8526],"valid"],[[8527,8527],"valid",[],"NV8"],[[8528,8528],"mapped",[49,8260,55]],[[8529,8529],"mapped",[49,8260,57]],[[8530,8530],"mapped",[49,8260,49,48]],[[8531,8531],"mapped",[49,8260,51]],[[8532,8532],"mapped",[50,8260,51]],[[8533,8533],"mapped",[49,8260,53]],[[8534,8534],"mapped",[50,8260,53]],[[8535,8535],"mapped",[51,8260,53]],[[8536,8536],"mapped",[52,8260,53]],[[8537,8537],"mapped",[49,8260,54]],[[8538,8538],"mapped",[53,8260,54]],[[8539,8539],"mapped",[49,8260,56]],[[8540,8540],"mapped",[51,8260,56]],[[8541,8541],"mapped",[53,8260,56]],[[8542,8542],"mapped",[55,8260,56]],[[8543,8543],"mapped",[49,8260]],[[8544,8544],"mapped",[105]],[[8545,8545],"mapped",[105,105]],[[8546,8546],"mapped",[105,105,105]],[[8547,8547],"mapped",[105,118]],[[8548,8548],"mapped",[118]],[[8549,8549],"mapped",[118,105]],[[8550,8550],"mapped",[118,105,105]],[[8551,8551],"mapped",[118,105,105,105]],[[8552,8552],"mapped",[105,120]],[[8553,8553],"mapped",[120]],[[8554,8554],"mapped",[120,105]],[[8555,8555],"mapped",[120,105,105]],[[8556,8556],"mapped",[108]],[[8557,8557],"mapped",[99]],[[8558,8558],"mapped",[100]],[[8559,8559],"mapped",[109]],[[8560,8560],"mapped",[105]],[[8561,8561],"mapped",[105,105]],[[8562,8562],"mapped",[105,105,105]],[[8563,8563],"mapped",[105,118]],[[8564,8564],"mapped",[118]],[[8565,8565],"mapped",[118,105]],[[8566,8566],"mapped",[118,105,105]],[[8567,8567],"mapped",[118,105,105,105]],[[8568,8568],"mapped",[105,120]],[[8569,8569],"mapped",[120]],[[8570,8570],"mapped",[120,105]],[[8571,8571],"mapped",[120,105,105]],[[8572,8572],"mapped",[108]],[[8573,8573],"mapped",[99]],[[8574,8574],"mapped",[100]],[[8575,8575],"mapped",[109]],[[8576,8578],"valid",[],"NV8"],[[8579,8579],"disallowed"],[[8580,8580],"valid"],[[8581,8584],"valid",[],"NV8"],[[8585,8585],"mapped",[48,8260,51]],[[8586,8587],"valid",[],"NV8"],[[8588,8591],"disallowed"],[[8592,8682],"valid",[],"NV8"],[[8683,8691],"valid",[],"NV8"],[[8692,8703],"valid",[],"NV8"],[[8704,8747],"valid",[],"NV8"],[[8748,8748],"mapped",[8747,8747]],[[8749,8749],"mapped",[8747,8747,8747]],[[8750,8750],"valid",[],"NV8"],[[8751,8751],"mapped",[8750,8750]],[[8752,8752],"mapped",[8750,8750,8750]],[[8753,8799],"valid",[],"NV8"],[[8800,8800],"disallowed_STD3_valid"],[[8801,8813],"valid",[],"NV8"],[[8814,8815],"disallowed_STD3_valid"],[[8816,8945],"valid",[],"NV8"],[[8946,8959],"valid",[],"NV8"],[[8960,8960],"valid",[],"NV8"],[[8961,8961],"valid",[],"NV8"],[[8962,9000],"valid",[],"NV8"],[[9001,9001],"mapped",[12296]],[[9002,9002],"mapped",[12297]],[[9003,9082],"valid",[],"NV8"],[[9083,9083],"valid",[],"NV8"],[[9084,9084],"valid",[],"NV8"],[[9085,9114],"valid",[],"NV8"],[[9115,9166],"valid",[],"NV8"],[[9167,9168],"valid",[],"NV8"],[[9169,9179],"valid",[],"NV8"],[[9180,9191],"valid",[],"NV8"],[[9192,9192],"valid",[],"NV8"],[[9193,9203],"valid",[],"NV8"],[[9204,9210],"valid",[],"NV8"],[[9211,9215],"disallowed"],[[9216,9252],"valid",[],"NV8"],[[9253,9254],"valid",[],"NV8"],[[9255,9279],"disallowed"],[[9280,9290],"valid",[],"NV8"],[[9291,9311],"disallowed"],[[9312,9312],"mapped",[49]],[[9313,9313],"mapped",[50]],[[9314,9314],"mapped",[51]],[[9315,9315],"mapped",[52]],[[9316,9316],"mapped",[53]],[[9317,9317],"mapped",[54]],[[9318,9318],"mapped",[55]],[[9319,9319],"mapped",[56]],[[9320,9320],"mapped",[57]],[[9321,9321],"mapped",[49,48]],[[9322,9322],"mapped",[49,49]],[[9323,9323],"mapped",[49,50]],[[9324,9324],"mapped",[49,51]],[[9325,9325],"mapped",[49,52]],[[9326,9326],"mapped",[49,53]],[[9327,9327],"mapped",[49,54]],[[9328,9328],"mapped",[49,55]],[[9329,9329],"mapped",[49,56]],[[9330,9330],"mapped",[49,57]],[[9331,9331],"mapped",[50,48]],[[9332,9332],"disallowed_STD3_mapped",[40,49,41]],[[9333,9333],"disallowed_STD3_mapped",[40,50,41]],[[9334,9334],"disallowed_STD3_mapped",[40,51,41]],[[9335,9335],"disallowed_STD3_mapped",[40,52,41]],[[9336,9336],"disallowed_STD3_mapped",[40,53,41]],[[9337,9337],"disallowed_STD3_mapped",[40,54,41]],[[9338,9338],"disallowed_STD3_mapped",[40,55,41]],[[9339,9339],"disallowed_STD3_mapped",[40,56,41]],[[9340,9340],"disallowed_STD3_mapped",[40,57,41]],[[9341,9341],"disallowed_STD3_mapped",[40,49,48,41]],[[9342,9342],"disallowed_STD3_mapped",[40,49,49,41]],[[9343,9343],"disallowed_STD3_mapped",[40,49,50,41]],[[9344,9344],"disallowed_STD3_mapped",[40,49,51,41]],[[9345,9345],"disallowed_STD3_mapped",[40,49,52,41]],[[9346,9346],"disallowed_STD3_mapped",[40,49,53,41]],[[9347,9347],"disallowed_STD3_mapped",[40,49,54,41]],[[9348,9348],"disallowed_STD3_mapped",[40,49,55,41]],[[9349,9349],"disallowed_STD3_mapped",[40,49,56,41]],[[9350,9350],"disallowed_STD3_mapped",[40,49,57,41]],[[9351,9351],"disallowed_STD3_mapped",[40,50,48,41]],[[9352,9371],"disallowed"],[[9372,9372],"disallowed_STD3_mapped",[40,97,41]],[[9373,9373],"disallowed_STD3_mapped",[40,98,41]],[[9374,9374],"disallowed_STD3_mapped",[40,99,41]],[[9375,9375],"disallowed_STD3_mapped",[40,100,41]],[[9376,9376],"disallowed_STD3_mapped",[40,101,41]],[[9377,9377],"disallowed_STD3_mapped",[40,102,41]],[[9378,9378],"disallowed_STD3_mapped",[40,103,41]],[[9379,9379],"disallowed_STD3_mapped",[40,104,41]],[[9380,9380],"disallowed_STD3_mapped",[40,105,41]],[[9381,9381],"disallowed_STD3_mapped",[40,106,41]],[[9382,9382],"disallowed_STD3_mapped",[40,107,41]],[[9383,9383],"disallowed_STD3_mapped",[40,108,41]],[[9384,9384],"disallowed_STD3_mapped",[40,109,41]],[[9385,9385],"disallowed_STD3_mapped",[40,110,41]],[[9386,9386],"disallowed_STD3_mapped",[40,111,41]],[[9387,9387],"disallowed_STD3_mapped",[40,112,41]],[[9388,9388],"disallowed_STD3_mapped",[40,113,41]],[[9389,9389],"disallowed_STD3_mapped",[40,114,41]],[[9390,9390],"disallowed_STD3_mapped",[40,115,41]],[[9391,9391],"disallowed_STD3_mapped",[40,116,41]],[[9392,9392],"disallowed_STD3_mapped",[40,117,41]],[[9393,9393],"disallowed_STD3_mapped",[40,118,41]],[[9394,9394],"disallowed_STD3_mapped",[40,119,41]],[[9395,9395],"disallowed_STD3_mapped",[40,120,41]],[[9396,9396],"disallowed_STD3_mapped",[40,121,41]],[[9397,9397],"disallowed_STD3_mapped",[40,122,41]],[[9398,9398],"mapped",[97]],[[9399,9399],"mapped",[98]],[[9400,9400],"mapped",[99]],[[9401,9401],"mapped",[100]],[[9402,9402],"mapped",[101]],[[9403,9403],"mapped",[102]],[[9404,9404],"mapped",[103]],[[9405,9405],"mapped",[104]],[[9406,9406],"mapped",[105]],[[9407,9407],"mapped",[106]],[[9408,9408],"mapped",[107]],[[9409,9409],"mapped",[108]],[[9410,9410],"mapped",[109]],[[9411,9411],"mapped",[110]],[[9412,9412],"mapped",[111]],[[9413,9413],"mapped",[112]],[[9414,9414],"mapped",[113]],[[9415,9415],"mapped",[114]],[[9416,9416],"mapped",[115]],[[9417,9417],"mapped",[116]],[[9418,9418],"mapped",[117]],[[9419,9419],"mapped",[118]],[[9420,9420],"mapped",[119]],[[9421,9421],"mapped",[120]],[[9422,9422],"mapped",[121]],[[9423,9423],"mapped",[122]],[[9424,9424],"mapped",[97]],[[9425,9425],"mapped",[98]],[[9426,9426],"mapped",[99]],[[9427,9427],"mapped",[100]],[[9428,9428],"mapped",[101]],[[9429,9429],"mapped",[102]],[[9430,9430],"mapped",[103]],[[9431,9431],"mapped",[104]],[[9432,9432],"mapped",[105]],[[9433,9433],"mapped",[106]],[[9434,9434],"mapped",[107]],[[9435,9435],"mapped",[108]],[[9436,9436],"mapped",[109]],[[9437,9437],"mapped",[110]],[[9438,9438],"mapped",[111]],[[9439,9439],"mapped",[112]],[[9440,9440],"mapped",[113]],[[9441,9441],"mapped",[114]],[[9442,9442],"mapped",[115]],[[9443,9443],"mapped",[116]],[[9444,9444],"mapped",[117]],[[9445,9445],"mapped",[118]],[[9446,9446],"mapped",[119]],[[9447,9447],"mapped",[120]],[[9448,9448],"mapped",[121]],[[9449,9449],"mapped",[122]],[[9450,9450],"mapped",[48]],[[9451,9470],"valid",[],"NV8"],[[9471,9471],"valid",[],"NV8"],[[9472,9621],"valid",[],"NV8"],[[9622,9631],"valid",[],"NV8"],[[9632,9711],"valid",[],"NV8"],[[9712,9719],"valid",[],"NV8"],[[9720,9727],"valid",[],"NV8"],[[9728,9747],"valid",[],"NV8"],[[9748,9749],"valid",[],"NV8"],[[9750,9751],"valid",[],"NV8"],[[9752,9752],"valid",[],"NV8"],[[9753,9753],"valid",[],"NV8"],[[9754,9839],"valid",[],"NV8"],[[9840,9841],"valid",[],"NV8"],[[9842,9853],"valid",[],"NV8"],[[9854,9855],"valid",[],"NV8"],[[9856,9865],"valid",[],"NV8"],[[9866,9873],"valid",[],"NV8"],[[9874,9884],"valid",[],"NV8"],[[9885,9885],"valid",[],"NV8"],[[9886,9887],"valid",[],"NV8"],[[9888,9889],"valid",[],"NV8"],[[9890,9905],"valid",[],"NV8"],[[9906,9906],"valid",[],"NV8"],[[9907,9916],"valid",[],"NV8"],[[9917,9919],"valid",[],"NV8"],[[9920,9923],"valid",[],"NV8"],[[9924,9933],"valid",[],"NV8"],[[9934,9934],"valid",[],"NV8"],[[9935,9953],"valid",[],"NV8"],[[9954,9954],"valid",[],"NV8"],[[9955,9955],"valid",[],"NV8"],[[9956,9959],"valid",[],"NV8"],[[9960,9983],"valid",[],"NV8"],[[9984,9984],"valid",[],"NV8"],[[9985,9988],"valid",[],"NV8"],[[9989,9989],"valid",[],"NV8"],[[9990,9993],"valid",[],"NV8"],[[9994,9995],"valid",[],"NV8"],[[9996,10023],"valid",[],"NV8"],[[10024,10024],"valid",[],"NV8"],[[10025,10059],"valid",[],"NV8"],[[10060,10060],"valid",[],"NV8"],[[10061,10061],"valid",[],"NV8"],[[10062,10062],"valid",[],"NV8"],[[10063,10066],"valid",[],"NV8"],[[10067,10069],"valid",[],"NV8"],[[10070,10070],"valid",[],"NV8"],[[10071,10071],"valid",[],"NV8"],[[10072,10078],"valid",[],"NV8"],[[10079,10080],"valid",[],"NV8"],[[10081,10087],"valid",[],"NV8"],[[10088,10101],"valid",[],"NV8"],[[10102,10132],"valid",[],"NV8"],[[10133,10135],"valid",[],"NV8"],[[10136,10159],"valid",[],"NV8"],[[10160,10160],"valid",[],"NV8"],[[10161,10174],"valid",[],"NV8"],[[10175,10175],"valid",[],"NV8"],[[10176,10182],"valid",[],"NV8"],[[10183,10186],"valid",[],"NV8"],[[10187,10187],"valid",[],"NV8"],[[10188,10188],"valid",[],"NV8"],[[10189,10189],"valid",[],"NV8"],[[10190,10191],"valid",[],"NV8"],[[10192,10219],"valid",[],"NV8"],[[10220,10223],"valid",[],"NV8"],[[10224,10239],"valid",[],"NV8"],[[10240,10495],"valid",[],"NV8"],[[10496,10763],"valid",[],"NV8"],[[10764,10764],"mapped",[8747,8747,8747,8747]],[[10765,10867],"valid",[],"NV8"],[[10868,10868],"disallowed_STD3_mapped",[58,58,61]],[[10869,10869],"disallowed_STD3_mapped",[61,61]],[[10870,10870],"disallowed_STD3_mapped",[61,61,61]],[[10871,10971],"valid",[],"NV8"],[[10972,10972],"mapped",[10973,824]],[[10973,11007],"valid",[],"NV8"],[[11008,11021],"valid",[],"NV8"],[[11022,11027],"valid",[],"NV8"],[[11028,11034],"valid",[],"NV8"],[[11035,11039],"valid",[],"NV8"],[[11040,11043],"valid",[],"NV8"],[[11044,11084],"valid",[],"NV8"],[[11085,11087],"valid",[],"NV8"],[[11088,11092],"valid",[],"NV8"],[[11093,11097],"valid",[],"NV8"],[[11098,11123],"valid",[],"NV8"],[[11124,11125],"disallowed"],[[11126,11157],"valid",[],"NV8"],[[11158,11159],"disallowed"],[[11160,11193],"valid",[],"NV8"],[[11194,11196],"disallowed"],[[11197,11208],"valid",[],"NV8"],[[11209,11209],"disallowed"],[[11210,11217],"valid",[],"NV8"],[[11218,11243],"disallowed"],[[11244,11247],"valid",[],"NV8"],[[11248,11263],"disallowed"],[[11264,11264],"mapped",[11312]],[[11265,11265],"mapped",[11313]],[[11266,11266],"mapped",[11314]],[[11267,11267],"mapped",[11315]],[[11268,11268],"mapped",[11316]],[[11269,11269],"mapped",[11317]],[[11270,11270],"mapped",[11318]],[[11271,11271],"mapped",[11319]],[[11272,11272],"mapped",[11320]],[[11273,11273],"mapped",[11321]],[[11274,11274],"mapped",[11322]],[[11275,11275],"mapped",[11323]],[[11276,11276],"mapped",[11324]],[[11277,11277],"mapped",[11325]],[[11278,11278],"mapped",[11326]],[[11279,11279],"mapped",[11327]],[[11280,11280],"mapped",[11328]],[[11281,11281],"mapped",[11329]],[[11282,11282],"mapped",[11330]],[[11283,11283],"mapped",[11331]],[[11284,11284],"mapped",[11332]],[[11285,11285],"mapped",[11333]],[[11286,11286],"mapped",[11334]],[[11287,11287],"mapped",[11335]],[[11288,11288],"mapped",[11336]],[[11289,11289],"mapped",[11337]],[[11290,11290],"mapped",[11338]],[[11291,11291],"mapped",[11339]],[[11292,11292],"mapped",[11340]],[[11293,11293],"mapped",[11341]],[[11294,11294],"mapped",[11342]],[[11295,11295],"mapped",[11343]],[[11296,11296],"mapped",[11344]],[[11297,11297],"mapped",[11345]],[[11298,11298],"mapped",[11346]],[[11299,11299],"mapped",[11347]],[[11300,11300],"mapped",[11348]],[[11301,11301],"mapped",[11349]],[[11302,11302],"mapped",[11350]],[[11303,11303],"mapped",[11351]],[[11304,11304],"mapped",[11352]],[[11305,11305],"mapped",[11353]],[[11306,11306],"mapped",[11354]],[[11307,11307],"mapped",[11355]],[[11308,11308],"mapped",[11356]],[[11309,11309],"mapped",[11357]],[[11310,11310],"mapped",[11358]],[[11311,11311],"disallowed"],[[11312,11358],"valid"],[[11359,11359],"disallowed"],[[11360,11360],"mapped",[11361]],[[11361,11361],"valid"],[[11362,11362],"mapped",[619]],[[11363,11363],"mapped",[7549]],[[11364,11364],"mapped",[637]],[[11365,11366],"valid"],[[11367,11367],"mapped",[11368]],[[11368,11368],"valid"],[[11369,11369],"mapped",[11370]],[[11370,11370],"valid"],[[11371,11371],"mapped",[11372]],[[11372,11372],"valid"],[[11373,11373],"mapped",[593]],[[11374,11374],"mapped",[625]],[[11375,11375],"mapped",[592]],[[11376,11376],"mapped",[594]],[[11377,11377],"valid"],[[11378,11378],"mapped",[11379]],[[11379,11379],"valid"],[[11380,11380],"valid"],[[11381,11381],"mapped",[11382]],[[11382,11383],"valid"],[[11384,11387],"valid"],[[11388,11388],"mapped",[106]],[[11389,11389],"mapped",[118]],[[11390,11390],"mapped",[575]],[[11391,11391],"mapped",[576]],[[11392,11392],"mapped",[11393]],[[11393,11393],"valid"],[[11394,11394],"mapped",[11395]],[[11395,11395],"valid"],[[11396,11396],"mapped",[11397]],[[11397,11397],"valid"],[[11398,11398],"mapped",[11399]],[[11399,11399],"valid"],[[11400,11400],"mapped",[11401]],[[11401,11401],"valid"],[[11402,11402],"mapped",[11403]],[[11403,11403],"valid"],[[11404,11404],"mapped",[11405]],[[11405,11405],"valid"],[[11406,11406],"mapped",[11407]],[[11407,11407],"valid"],[[11408,11408],"mapped",[11409]],[[11409,11409],"valid"],[[11410,11410],"mapped",[11411]],[[11411,11411],"valid"],[[11412,11412],"mapped",[11413]],[[11413,11413],"valid"],[[11414,11414],"mapped",[11415]],[[11415,11415],"valid"],[[11416,11416],"mapped",[11417]],[[11417,11417],"valid"],[[11418,11418],"mapped",[11419]],[[11419,11419],"valid"],[[11420,11420],"mapped",[11421]],[[11421,11421],"valid"],[[11422,11422],"mapped",[11423]],[[11423,11423],"valid"],[[11424,11424],"mapped",[11425]],[[11425,11425],"valid"],[[11426,11426],"mapped",[11427]],[[11427,11427],"valid"],[[11428,11428],"mapped",[11429]],[[11429,11429],"valid"],[[11430,11430],"mapped",[11431]],[[11431,11431],"valid"],[[11432,11432],"mapped",[11433]],[[11433,11433],"valid"],[[11434,11434],"mapped",[11435]],[[11435,11435],"valid"],[[11436,11436],"mapped",[11437]],[[11437,11437],"valid"],[[11438,11438],"mapped",[11439]],[[11439,11439],"valid"],[[11440,11440],"mapped",[11441]],[[11441,11441],"valid"],[[11442,11442],"mapped",[11443]],[[11443,11443],"valid"],[[11444,11444],"mapped",[11445]],[[11445,11445],"valid"],[[11446,11446],"mapped",[11447]],[[11447,11447],"valid"],[[11448,11448],"mapped",[11449]],[[11449,11449],"valid"],[[11450,11450],"mapped",[11451]],[[11451,11451],"valid"],[[11452,11452],"mapped",[11453]],[[11453,11453],"valid"],[[11454,11454],"mapped",[11455]],[[11455,11455],"valid"],[[11456,11456],"mapped",[11457]],[[11457,11457],"valid"],[[11458,11458],"mapped",[11459]],[[11459,11459],"valid"],[[11460,11460],"mapped",[11461]],[[11461,11461],"valid"],[[11462,11462],"mapped",[11463]],[[11463,11463],"valid"],[[11464,11464],"mapped",[11465]],[[11465,11465],"valid"],[[11466,11466],"mapped",[11467]],[[11467,11467],"valid"],[[11468,11468],"mapped",[11469]],[[11469,11469],"valid"],[[11470,11470],"mapped",[11471]],[[11471,11471],"valid"],[[11472,11472],"mapped",[11473]],[[11473,11473],"valid"],[[11474,11474],"mapped",[11475]],[[11475,11475],"valid"],[[11476,11476],"mapped",[11477]],[[11477,11477],"valid"],[[11478,11478],"mapped",[11479]],[[11479,11479],"valid"],[[11480,11480],"mapped",[11481]],[[11481,11481],"valid"],[[11482,11482],"mapped",[11483]],[[11483,11483],"valid"],[[11484,11484],"mapped",[11485]],[[11485,11485],"valid"],[[11486,11486],"mapped",[11487]],[[11487,11487],"valid"],[[11488,11488],"mapped",[11489]],[[11489,11489],"valid"],[[11490,11490],"mapped",[11491]],[[11491,11492],"valid"],[[11493,11498],"valid",[],"NV8"],[[11499,11499],"mapped",[11500]],[[11500,11500],"valid"],[[11501,11501],"mapped",[11502]],[[11502,11505],"valid"],[[11506,11506],"mapped",[11507]],[[11507,11507],"valid"],[[11508,11512],"disallowed"],[[11513,11519],"valid",[],"NV8"],[[11520,11557],"valid"],[[11558,11558],"disallowed"],[[11559,11559],"valid"],[[11560,11564],"disallowed"],[[11565,11565],"valid"],[[11566,11567],"disallowed"],[[11568,11621],"valid"],[[11622,11623],"valid"],[[11624,11630],"disallowed"],[[11631,11631],"mapped",[11617]],[[11632,11632],"valid",[],"NV8"],[[11633,11646],"disallowed"],[[11647,11647],"valid"],[[11648,11670],"valid"],[[11671,11679],"disallowed"],[[11680,11686],"valid"],[[11687,11687],"disallowed"],[[11688,11694],"valid"],[[11695,11695],"disallowed"],[[11696,11702],"valid"],[[11703,11703],"disallowed"],[[11704,11710],"valid"],[[11711,11711],"disallowed"],[[11712,11718],"valid"],[[11719,11719],"disallowed"],[[11720,11726],"valid"],[[11727,11727],"disallowed"],[[11728,11734],"valid"],[[11735,11735],"disallowed"],[[11736,11742],"valid"],[[11743,11743],"disallowed"],[[11744,11775],"valid"],[[11776,11799],"valid",[],"NV8"],[[11800,11803],"valid",[],"NV8"],[[11804,11805],"valid",[],"NV8"],[[11806,11822],"valid",[],"NV8"],[[11823,11823],"valid"],[[11824,11824],"valid",[],"NV8"],[[11825,11825],"valid",[],"NV8"],[[11826,11835],"valid",[],"NV8"],[[11836,11842],"valid",[],"NV8"],[[11843,11903],"disallowed"],[[11904,11929],"valid",[],"NV8"],[[11930,11930],"disallowed"],[[11931,11934],"valid",[],"NV8"],[[11935,11935],"mapped",[27597]],[[11936,12018],"valid",[],"NV8"],[[12019,12019],"mapped",[40863]],[[12020,12031],"disallowed"],[[12032,12032],"mapped",[19968]],[[12033,12033],"mapped",[20008]],[[12034,12034],"mapped",[20022]],[[12035,12035],"mapped",[20031]],[[12036,12036],"mapped",[20057]],[[12037,12037],"mapped",[20101]],[[12038,12038],"mapped",[20108]],[[12039,12039],"mapped",[20128]],[[12040,12040],"mapped",[20154]],[[12041,12041],"mapped",[20799]],[[12042,12042],"mapped",[20837]],[[12043,12043],"mapped",[20843]],[[12044,12044],"mapped",[20866]],[[12045,12045],"mapped",[20886]],[[12046,12046],"mapped",[20907]],[[12047,12047],"mapped",[20960]],[[12048,12048],"mapped",[20981]],[[12049,12049],"mapped",[20992]],[[12050,12050],"mapped",[21147]],[[12051,12051],"mapped",[21241]],[[12052,12052],"mapped",[21269]],[[12053,12053],"mapped",[21274]],[[12054,12054],"mapped",[21304]],[[12055,12055],"mapped",[21313]],[[12056,12056],"mapped",[21340]],[[12057,12057],"mapped",[21353]],[[12058,12058],"mapped",[21378]],[[12059,12059],"mapped",[21430]],[[12060,12060],"mapped",[21448]],[[12061,12061],"mapped",[21475]],[[12062,12062],"mapped",[22231]],[[12063,12063],"mapped",[22303]],[[12064,12064],"mapped",[22763]],[[12065,12065],"mapped",[22786]],[[12066,12066],"mapped",[22794]],[[12067,12067],"mapped",[22805]],[[12068,12068],"mapped",[22823]],[[12069,12069],"mapped",[22899]],[[12070,12070],"mapped",[23376]],[[12071,12071],"mapped",[23424]],[[12072,12072],"mapped",[23544]],[[12073,12073],"mapped",[23567]],[[12074,12074],"mapped",[23586]],[[12075,12075],"mapped",[23608]],[[12076,12076],"mapped",[23662]],[[12077,12077],"mapped",[23665]],[[12078,12078],"mapped",[24027]],[[12079,12079],"mapped",[24037]],[[12080,12080],"mapped",[24049]],[[12081,12081],"mapped",[24062]],[[12082,12082],"mapped",[24178]],[[12083,12083],"mapped",[24186]],[[12084,12084],"mapped",[24191]],[[12085,12085],"mapped",[24308]],[[12086,12086],"mapped",[24318]],[[12087,12087],"mapped",[24331]],[[12088,12088],"mapped",[24339]],[[12089,12089],"mapped",[24400]],[[12090,12090],"mapped",[24417]],[[12091,12091],"mapped",[24435]],[[12092,12092],"mapped",[24515]],[[12093,12093],"mapped",[25096]],[[12094,12094],"mapped",[25142]],[[12095,12095],"mapped",[25163]],[[12096,12096],"mapped",[25903]],[[12097,12097],"mapped",[25908]],[[12098,12098],"mapped",[25991]],[[12099,12099],"mapped",[26007]],[[12100,12100],"mapped",[26020]],[[12101,12101],"mapped",[26041]],[[12102,12102],"mapped",[26080]],[[12103,12103],"mapped",[26085]],[[12104,12104],"mapped",[26352]],[[12105,12105],"mapped",[26376]],[[12106,12106],"mapped",[26408]],[[12107,12107],"mapped",[27424]],[[12108,12108],"mapped",[27490]],[[12109,12109],"mapped",[27513]],[[12110,12110],"mapped",[27571]],[[12111,12111],"mapped",[27595]],[[12112,12112],"mapped",[27604]],[[12113,12113],"mapped",[27611]],[[12114,12114],"mapped",[27663]],[[12115,12115],"mapped",[27668]],[[12116,12116],"mapped",[27700]],[[12117,12117],"mapped",[28779]],[[12118,12118],"mapped",[29226]],[[12119,12119],"mapped",[29238]],[[12120,12120],"mapped",[29243]],[[12121,12121],"mapped",[29247]],[[12122,12122],"mapped",[29255]],[[12123,12123],"mapped",[29273]],[[12124,12124],"mapped",[29275]],[[12125,12125],"mapped",[29356]],[[12126,12126],"mapped",[29572]],[[12127,12127],"mapped",[29577]],[[12128,12128],"mapped",[29916]],[[12129,12129],"mapped",[29926]],[[12130,12130],"mapped",[29976]],[[12131,12131],"mapped",[29983]],[[12132,12132],"mapped",[29992]],[[12133,12133],"mapped",[30000]],[[12134,12134],"mapped",[30091]],[[12135,12135],"mapped",[30098]],[[12136,12136],"mapped",[30326]],[[12137,12137],"mapped",[30333]],[[12138,12138],"mapped",[30382]],[[12139,12139],"mapped",[30399]],[[12140,12140],"mapped",[30446]],[[12141,12141],"mapped",[30683]],[[12142,12142],"mapped",[30690]],[[12143,12143],"mapped",[30707]],[[12144,12144],"mapped",[31034]],[[12145,12145],"mapped",[31160]],[[12146,12146],"mapped",[31166]],[[12147,12147],"mapped",[31348]],[[12148,12148],"mapped",[31435]],[[12149,12149],"mapped",[31481]],[[12150,12150],"mapped",[31859]],[[12151,12151],"mapped",[31992]],[[12152,12152],"mapped",[32566]],[[12153,12153],"mapped",[32593]],[[12154,12154],"mapped",[32650]],[[12155,12155],"mapped",[32701]],[[12156,12156],"mapped",[32769]],[[12157,12157],"mapped",[32780]],[[12158,12158],"mapped",[32786]],[[12159,12159],"mapped",[32819]],[[12160,12160],"mapped",[32895]],[[12161,12161],"mapped",[32905]],[[12162,12162],"mapped",[33251]],[[12163,12163],"mapped",[33258]],[[12164,12164],"mapped",[33267]],[[12165,12165],"mapped",[33276]],[[12166,12166],"mapped",[33292]],[[12167,12167],"mapped",[33307]],[[12168,12168],"mapped",[33311]],[[12169,12169],"mapped",[33390]],[[12170,12170],"mapped",[33394]],[[12171,12171],"mapped",[33400]],[[12172,12172],"mapped",[34381]],[[12173,12173],"mapped",[34411]],[[12174,12174],"mapped",[34880]],[[12175,12175],"mapped",[34892]],[[12176,12176],"mapped",[34915]],[[12177,12177],"mapped",[35198]],[[12178,12178],"mapped",[35211]],[[12179,12179],"mapped",[35282]],[[12180,12180],"mapped",[35328]],[[12181,12181],"mapped",[35895]],[[12182,12182],"mapped",[35910]],[[12183,12183],"mapped",[35925]],[[12184,12184],"mapped",[35960]],[[12185,12185],"mapped",[35997]],[[12186,12186],"mapped",[36196]],[[12187,12187],"mapped",[36208]],[[12188,12188],"mapped",[36275]],[[12189,12189],"mapped",[36523]],[[12190,12190],"mapped",[36554]],[[12191,12191],"mapped",[36763]],[[12192,12192],"mapped",[36784]],[[12193,12193],"mapped",[36789]],[[12194,12194],"mapped",[37009]],[[12195,12195],"mapped",[37193]],[[12196,12196],"mapped",[37318]],[[12197,12197],"mapped",[37324]],[[12198,12198],"mapped",[37329]],[[12199,12199],"mapped",[38263]],[[12200,12200],"mapped",[38272]],[[12201,12201],"mapped",[38428]],[[12202,12202],"mapped",[38582]],[[12203,12203],"mapped",[38585]],[[12204,12204],"mapped",[38632]],[[12205,12205],"mapped",[38737]],[[12206,12206],"mapped",[38750]],[[12207,12207],"mapped",[38754]],[[12208,12208],"mapped",[38761]],[[12209,12209],"mapped",[38859]],[[12210,12210],"mapped",[38893]],[[12211,12211],"mapped",[38899]],[[12212,12212],"mapped",[38913]],[[12213,12213],"mapped",[39080]],[[12214,12214],"mapped",[39131]],[[12215,12215],"mapped",[39135]],[[12216,12216],"mapped",[39318]],[[12217,12217],"mapped",[39321]],[[12218,12218],"mapped",[39340]],[[12219,12219],"mapped",[39592]],[[12220,12220],"mapped",[39640]],[[12221,12221],"mapped",[39647]],[[12222,12222],"mapped",[39717]],[[12223,12223],"mapped",[39727]],[[12224,12224],"mapped",[39730]],[[12225,12225],"mapped",[39740]],[[12226,12226],"mapped",[39770]],[[12227,12227],"mapped",[40165]],[[12228,12228],"mapped",[40565]],[[12229,12229],"mapped",[40575]],[[12230,12230],"mapped",[40613]],[[12231,12231],"mapped",[40635]],[[12232,12232],"mapped",[40643]],[[12233,12233],"mapped",[40653]],[[12234,12234],"mapped",[40657]],[[12235,12235],"mapped",[40697]],[[12236,12236],"mapped",[40701]],[[12237,12237],"mapped",[40718]],[[12238,12238],"mapped",[40723]],[[12239,12239],"mapped",[40736]],[[12240,12240],"mapped",[40763]],[[12241,12241],"mapped",[40778]],[[12242,12242],"mapped",[40786]],[[12243,12243],"mapped",[40845]],[[12244,12244],"mapped",[40860]],[[12245,12245],"mapped",[40864]],[[12246,12271],"disallowed"],[[12272,12283],"disallowed"],[[12284,12287],"disallowed"],[[12288,12288],"disallowed_STD3_mapped",[32]],[[12289,12289],"valid",[],"NV8"],[[12290,12290],"mapped",[46]],[[12291,12292],"valid",[],"NV8"],[[12293,12295],"valid"],[[12296,12329],"valid",[],"NV8"],[[12330,12333],"valid"],[[12334,12341],"valid",[],"NV8"],[[12342,12342],"mapped",[12306]],[[12343,12343],"valid",[],"NV8"],[[12344,12344],"mapped",[21313]],[[12345,12345],"mapped",[21316]],[[12346,12346],"mapped",[21317]],[[12347,12347],"valid",[],"NV8"],[[12348,12348],"valid"],[[12349,12349],"valid",[],"NV8"],[[12350,12350],"valid",[],"NV8"],[[12351,12351],"valid",[],"NV8"],[[12352,12352],"disallowed"],[[12353,12436],"valid"],[[12437,12438],"valid"],[[12439,12440],"disallowed"],[[12441,12442],"valid"],[[12443,12443],"disallowed_STD3_mapped",[32,12441]],[[12444,12444],"disallowed_STD3_mapped",[32,12442]],[[12445,12446],"valid"],[[12447,12447],"mapped",[12424,12426]],[[12448,12448],"valid",[],"NV8"],[[12449,12542],"valid"],[[12543,12543],"mapped",[12467,12488]],[[12544,12548],"disallowed"],[[12549,12588],"valid"],[[12589,12589],"valid"],[[12590,12592],"disallowed"],[[12593,12593],"mapped",[4352]],[[12594,12594],"mapped",[4353]],[[12595,12595],"mapped",[4522]],[[12596,12596],"mapped",[4354]],[[12597,12597],"mapped",[4524]],[[12598,12598],"mapped",[4525]],[[12599,12599],"mapped",[4355]],[[12600,12600],"mapped",[4356]],[[12601,12601],"mapped",[4357]],[[12602,12602],"mapped",[4528]],[[12603,12603],"mapped",[4529]],[[12604,12604],"mapped",[4530]],[[12605,12605],"mapped",[4531]],[[12606,12606],"mapped",[4532]],[[12607,12607],"mapped",[4533]],[[12608,12608],"mapped",[4378]],[[12609,12609],"mapped",[4358]],[[12610,12610],"mapped",[4359]],[[12611,12611],"mapped",[4360]],[[12612,12612],"mapped",[4385]],[[12613,12613],"mapped",[4361]],[[12614,12614],"mapped",[4362]],[[12615,12615],"mapped",[4363]],[[12616,12616],"mapped",[4364]],[[12617,12617],"mapped",[4365]],[[12618,12618],"mapped",[4366]],[[12619,12619],"mapped",[4367]],[[12620,12620],"mapped",[4368]],[[12621,12621],"mapped",[4369]],[[12622,12622],"mapped",[4370]],[[12623,12623],"mapped",[4449]],[[12624,12624],"mapped",[4450]],[[12625,12625],"mapped",[4451]],[[12626,12626],"mapped",[4452]],[[12627,12627],"mapped",[4453]],[[12628,12628],"mapped",[4454]],[[12629,12629],"mapped",[4455]],[[12630,12630],"mapped",[4456]],[[12631,12631],"mapped",[4457]],[[12632,12632],"mapped",[4458]],[[12633,12633],"mapped",[4459]],[[12634,12634],"mapped",[4460]],[[12635,12635],"mapped",[4461]],[[12636,12636],"mapped",[4462]],[[12637,12637],"mapped",[4463]],[[12638,12638],"mapped",[4464]],[[12639,12639],"mapped",[4465]],[[12640,12640],"mapped",[4466]],[[12641,12641],"mapped",[4467]],[[12642,12642],"mapped",[4468]],[[12643,12643],"mapped",[4469]],[[12644,12644],"disallowed"],[[12645,12645],"mapped",[4372]],[[12646,12646],"mapped",[4373]],[[12647,12647],"mapped",[4551]],[[12648,12648],"mapped",[4552]],[[12649,12649],"mapped",[4556]],[[12650,12650],"mapped",[4558]],[[12651,12651],"mapped",[4563]],[[12652,12652],"mapped",[4567]],[[12653,12653],"mapped",[4569]],[[12654,12654],"mapped",[4380]],[[12655,12655],"mapped",[4573]],[[12656,12656],"mapped",[4575]],[[12657,12657],"mapped",[4381]],[[12658,12658],"mapped",[4382]],[[12659,12659],"mapped",[4384]],[[12660,12660],"mapped",[4386]],[[12661,12661],"mapped",[4387]],[[12662,12662],"mapped",[4391]],[[12663,12663],"mapped",[4393]],[[12664,12664],"mapped",[4395]],[[12665,12665],"mapped",[4396]],[[12666,12666],"mapped",[4397]],[[12667,12667],"mapped",[4398]],[[12668,12668],"mapped",[4399]],[[12669,12669],"mapped",[4402]],[[12670,12670],"mapped",[4406]],[[12671,12671],"mapped",[4416]],[[12672,12672],"mapped",[4423]],[[12673,12673],"mapped",[4428]],[[12674,12674],"mapped",[4593]],[[12675,12675],"mapped",[4594]],[[12676,12676],"mapped",[4439]],[[12677,12677],"mapped",[4440]],[[12678,12678],"mapped",[4441]],[[12679,12679],"mapped",[4484]],[[12680,12680],"mapped",[4485]],[[12681,12681],"mapped",[4488]],[[12682,12682],"mapped",[4497]],[[12683,12683],"mapped",[4498]],[[12684,12684],"mapped",[4500]],[[12685,12685],"mapped",[4510]],[[12686,12686],"mapped",[4513]],[[12687,12687],"disallowed"],[[12688,12689],"valid",[],"NV8"],[[12690,12690],"mapped",[19968]],[[12691,12691],"mapped",[20108]],[[12692,12692],"mapped",[19977]],[[12693,12693],"mapped",[22235]],[[12694,12694],"mapped",[19978]],[[12695,12695],"mapped",[20013]],[[12696,12696],"mapped",[19979]],[[12697,12697],"mapped",[30002]],[[12698,12698],"mapped",[20057]],[[12699,12699],"mapped",[19993]],[[12700,12700],"mapped",[19969]],[[12701,12701],"mapped",[22825]],[[12702,12702],"mapped",[22320]],[[12703,12703],"mapped",[20154]],[[12704,12727],"valid"],[[12728,12730],"valid"],[[12731,12735],"disallowed"],[[12736,12751],"valid",[],"NV8"],[[12752,12771],"valid",[],"NV8"],[[12772,12783],"disallowed"],[[12784,12799],"valid"],[[12800,12800],"disallowed_STD3_mapped",[40,4352,41]],[[12801,12801],"disallowed_STD3_mapped",[40,4354,41]],[[12802,12802],"disallowed_STD3_mapped",[40,4355,41]],[[12803,12803],"disallowed_STD3_mapped",[40,4357,41]],[[12804,12804],"disallowed_STD3_mapped",[40,4358,41]],[[12805,12805],"disallowed_STD3_mapped",[40,4359,41]],[[12806,12806],"disallowed_STD3_mapped",[40,4361,41]],[[12807,12807],"disallowed_STD3_mapped",[40,4363,41]],[[12808,12808],"disallowed_STD3_mapped",[40,4364,41]],[[12809,12809],"disallowed_STD3_mapped",[40,4366,41]],[[12810,12810],"disallowed_STD3_mapped",[40,4367,41]],[[12811,12811],"disallowed_STD3_mapped",[40,4368,41]],[[12812,12812],"disallowed_STD3_mapped",[40,4369,41]],[[12813,12813],"disallowed_STD3_mapped",[40,4370,41]],[[12814,12814],"disallowed_STD3_mapped",[40,44032,41]],[[12815,12815],"disallowed_STD3_mapped",[40,45208,41]],[[12816,12816],"disallowed_STD3_mapped",[40,45796,41]],[[12817,12817],"disallowed_STD3_mapped",[40,46972,41]],[[12818,12818],"disallowed_STD3_mapped",[40,47560,41]],[[12819,12819],"disallowed_STD3_mapped",[40,48148,41]],[[12820,12820],"disallowed_STD3_mapped",[40,49324,41]],[[12821,12821],"disallowed_STD3_mapped",[40,50500,41]],[[12822,12822],"disallowed_STD3_mapped",[40,51088,41]],[[12823,12823],"disallowed_STD3_mapped",[40,52264,41]],[[12824,12824],"disallowed_STD3_mapped",[40,52852,41]],[[12825,12825],"disallowed_STD3_mapped",[40,53440,41]],[[12826,12826],"disallowed_STD3_mapped",[40,54028,41]],[[12827,12827],"disallowed_STD3_mapped",[40,54616,41]],[[12828,12828],"disallowed_STD3_mapped",[40,51452,41]],[[12829,12829],"disallowed_STD3_mapped",[40,50724,51204,41]],[[12830,12830],"disallowed_STD3_mapped",[40,50724,54980,41]],[[12831,12831],"disallowed"],[[12832,12832],"disallowed_STD3_mapped",[40,19968,41]],[[12833,12833],"disallowed_STD3_mapped",[40,20108,41]],[[12834,12834],"disallowed_STD3_mapped",[40,19977,41]],[[12835,12835],"disallowed_STD3_mapped",[40,22235,41]],[[12836,12836],"disallowed_STD3_mapped",[40,20116,41]],[[12837,12837],"disallowed_STD3_mapped",[40,20845,41]],[[12838,12838],"disallowed_STD3_mapped",[40,19971,41]],[[12839,12839],"disallowed_STD3_mapped",[40,20843,41]],[[12840,12840],"disallowed_STD3_mapped",[40,20061,41]],[[12841,12841],"disallowed_STD3_mapped",[40,21313,41]],[[12842,12842],"disallowed_STD3_mapped",[40,26376,41]],[[12843,12843],"disallowed_STD3_mapped",[40,28779,41]],[[12844,12844],"disallowed_STD3_mapped",[40,27700,41]],[[12845,12845],"disallowed_STD3_mapped",[40,26408,41]],[[12846,12846],"disallowed_STD3_mapped",[40,37329,41]],[[12847,12847],"disallowed_STD3_mapped",[40,22303,41]],[[12848,12848],"disallowed_STD3_mapped",[40,26085,41]],[[12849,12849],"disallowed_STD3_mapped",[40,26666,41]],[[12850,12850],"disallowed_STD3_mapped",[40,26377,41]],[[12851,12851],"disallowed_STD3_mapped",[40,31038,41]],[[12852,12852],"disallowed_STD3_mapped",[40,21517,41]],[[12853,12853],"disallowed_STD3_mapped",[40,29305,41]],[[12854,12854],"disallowed_STD3_mapped",[40,36001,41]],[[12855,12855],"disallowed_STD3_mapped",[40,31069,41]],[[12856,12856],"disallowed_STD3_mapped",[40,21172,41]],[[12857,12857],"disallowed_STD3_mapped",[40,20195,41]],[[12858,12858],"disallowed_STD3_mapped",[40,21628,41]],[[12859,12859],"disallowed_STD3_mapped",[40,23398,41]],[[12860,12860],"disallowed_STD3_mapped",[40,30435,41]],[[12861,12861],"disallowed_STD3_mapped",[40,20225,41]],[[12862,12862],"disallowed_STD3_mapped",[40,36039,41]],[[12863,12863],"disallowed_STD3_mapped",[40,21332,41]],[[12864,12864],"disallowed_STD3_mapped",[40,31085,41]],[[12865,12865],"disallowed_STD3_mapped",[40,20241,41]],[[12866,12866],"disallowed_STD3_mapped",[40,33258,41]],[[12867,12867],"disallowed_STD3_mapped",[40,33267,41]],[[12868,12868],"mapped",[21839]],[[12869,12869],"mapped",[24188]],[[12870,12870],"mapped",[25991]],[[12871,12871],"mapped",[31631]],[[12872,12879],"valid",[],"NV8"],[[12880,12880],"mapped",[112,116,101]],[[12881,12881],"mapped",[50,49]],[[12882,12882],"mapped",[50,50]],[[12883,12883],"mapped",[50,51]],[[12884,12884],"mapped",[50,52]],[[12885,12885],"mapped",[50,53]],[[12886,12886],"mapped",[50,54]],[[12887,12887],"mapped",[50,55]],[[12888,12888],"mapped",[50,56]],[[12889,12889],"mapped",[50,57]],[[12890,12890],"mapped",[51,48]],[[12891,12891],"mapped",[51,49]],[[12892,12892],"mapped",[51,50]],[[12893,12893],"mapped",[51,51]],[[12894,12894],"mapped",[51,52]],[[12895,12895],"mapped",[51,53]],[[12896,12896],"mapped",[4352]],[[12897,12897],"mapped",[4354]],[[12898,12898],"mapped",[4355]],[[12899,12899],"mapped",[4357]],[[12900,12900],"mapped",[4358]],[[12901,12901],"mapped",[4359]],[[12902,12902],"mapped",[4361]],[[12903,12903],"mapped",[4363]],[[12904,12904],"mapped",[4364]],[[12905,12905],"mapped",[4366]],[[12906,12906],"mapped",[4367]],[[12907,12907],"mapped",[4368]],[[12908,12908],"mapped",[4369]],[[12909,12909],"mapped",[4370]],[[12910,12910],"mapped",[44032]],[[12911,12911],"mapped",[45208]],[[12912,12912],"mapped",[45796]],[[12913,12913],"mapped",[46972]],[[12914,12914],"mapped",[47560]],[[12915,12915],"mapped",[48148]],[[12916,12916],"mapped",[49324]],[[12917,12917],"mapped",[50500]],[[12918,12918],"mapped",[51088]],[[12919,12919],"mapped",[52264]],[[12920,12920],"mapped",[52852]],[[12921,12921],"mapped",[53440]],[[12922,12922],"mapped",[54028]],[[12923,12923],"mapped",[54616]],[[12924,12924],"mapped",[52280,44256]],[[12925,12925],"mapped",[51452,51032]],[[12926,12926],"mapped",[50864]],[[12927,12927],"valid",[],"NV8"],[[12928,12928],"mapped",[19968]],[[12929,12929],"mapped",[20108]],[[12930,12930],"mapped",[19977]],[[12931,12931],"mapped",[22235]],[[12932,12932],"mapped",[20116]],[[12933,12933],"mapped",[20845]],[[12934,12934],"mapped",[19971]],[[12935,12935],"mapped",[20843]],[[12936,12936],"mapped",[20061]],[[12937,12937],"mapped",[21313]],[[12938,12938],"mapped",[26376]],[[12939,12939],"mapped",[28779]],[[12940,12940],"mapped",[27700]],[[12941,12941],"mapped",[26408]],[[12942,12942],"mapped",[37329]],[[12943,12943],"mapped",[22303]],[[12944,12944],"mapped",[26085]],[[12945,12945],"mapped",[26666]],[[12946,12946],"mapped",[26377]],[[12947,12947],"mapped",[31038]],[[12948,12948],"mapped",[21517]],[[12949,12949],"mapped",[29305]],[[12950,12950],"mapped",[36001]],[[12951,12951],"mapped",[31069]],[[12952,12952],"mapped",[21172]],[[12953,12953],"mapped",[31192]],[[12954,12954],"mapped",[30007]],[[12955,12955],"mapped",[22899]],[[12956,12956],"mapped",[36969]],[[12957,12957],"mapped",[20778]],[[12958,12958],"mapped",[21360]],[[12959,12959],"mapped",[27880]],[[12960,12960],"mapped",[38917]],[[12961,12961],"mapped",[20241]],[[12962,12962],"mapped",[20889]],[[12963,12963],"mapped",[27491]],[[12964,12964],"mapped",[19978]],[[12965,12965],"mapped",[20013]],[[12966,12966],"mapped",[19979]],[[12967,12967],"mapped",[24038]],[[12968,12968],"mapped",[21491]],[[12969,12969],"mapped",[21307]],[[12970,12970],"mapped",[23447]],[[12971,12971],"mapped",[23398]],[[12972,12972],"mapped",[30435]],[[12973,12973],"mapped",[20225]],[[12974,12974],"mapped",[36039]],[[12975,12975],"mapped",[21332]],[[12976,12976],"mapped",[22812]],[[12977,12977],"mapped",[51,54]],[[12978,12978],"mapped",[51,55]],[[12979,12979],"mapped",[51,56]],[[12980,12980],"mapped",[51,57]],[[12981,12981],"mapped",[52,48]],[[12982,12982],"mapped",[52,49]],[[12983,12983],"mapped",[52,50]],[[12984,12984],"mapped",[52,51]],[[12985,12985],"mapped",[52,52]],[[12986,12986],"mapped",[52,53]],[[12987,12987],"mapped",[52,54]],[[12988,12988],"mapped",[52,55]],[[12989,12989],"mapped",[52,56]],[[12990,12990],"mapped",[52,57]],[[12991,12991],"mapped",[53,48]],[[12992,12992],"mapped",[49,26376]],[[12993,12993],"mapped",[50,26376]],[[12994,12994],"mapped",[51,26376]],[[12995,12995],"mapped",[52,26376]],[[12996,12996],"mapped",[53,26376]],[[12997,12997],"mapped",[54,26376]],[[12998,12998],"mapped",[55,26376]],[[12999,12999],"mapped",[56,26376]],[[13000,13000],"mapped",[57,26376]],[[13001,13001],"mapped",[49,48,26376]],[[13002,13002],"mapped",[49,49,26376]],[[13003,13003],"mapped",[49,50,26376]],[[13004,13004],"mapped",[104,103]],[[13005,13005],"mapped",[101,114,103]],[[13006,13006],"mapped",[101,118]],[[13007,13007],"mapped",[108,116,100]],[[13008,13008],"mapped",[12450]],[[13009,13009],"mapped",[12452]],[[13010,13010],"mapped",[12454]],[[13011,13011],"mapped",[12456]],[[13012,13012],"mapped",[12458]],[[13013,13013],"mapped",[12459]],[[13014,13014],"mapped",[12461]],[[13015,13015],"mapped",[12463]],[[13016,13016],"mapped",[12465]],[[13017,13017],"mapped",[12467]],[[13018,13018],"mapped",[12469]],[[13019,13019],"mapped",[12471]],[[13020,13020],"mapped",[12473]],[[13021,13021],"mapped",[12475]],[[13022,13022],"mapped",[12477]],[[13023,13023],"mapped",[12479]],[[13024,13024],"mapped",[12481]],[[13025,13025],"mapped",[12484]],[[13026,13026],"mapped",[12486]],[[13027,13027],"mapped",[12488]],[[13028,13028],"mapped",[12490]],[[13029,13029],"mapped",[12491]],[[13030,13030],"mapped",[12492]],[[13031,13031],"mapped",[12493]],[[13032,13032],"mapped",[12494]],[[13033,13033],"mapped",[12495]],[[13034,13034],"mapped",[12498]],[[13035,13035],"mapped",[12501]],[[13036,13036],"mapped",[12504]],[[13037,13037],"mapped",[12507]],[[13038,13038],"mapped",[12510]],[[13039,13039],"mapped",[12511]],[[13040,13040],"mapped",[12512]],[[13041,13041],"mapped",[12513]],[[13042,13042],"mapped",[12514]],[[13043,13043],"mapped",[12516]],[[13044,13044],"mapped",[12518]],[[13045,13045],"mapped",[12520]],[[13046,13046],"mapped",[12521]],[[13047,13047],"mapped",[12522]],[[13048,13048],"mapped",[12523]],[[13049,13049],"mapped",[12524]],[[13050,13050],"mapped",[12525]],[[13051,13051],"mapped",[12527]],[[13052,13052],"mapped",[12528]],[[13053,13053],"mapped",[12529]],[[13054,13054],"mapped",[12530]],[[13055,13055],"disallowed"],[[13056,13056],"mapped",[12450,12497,12540,12488]],[[13057,13057],"mapped",[12450,12523,12501,12449]],[[13058,13058],"mapped",[12450,12531,12506,12450]],[[13059,13059],"mapped",[12450,12540,12523]],[[13060,13060],"mapped",[12452,12491,12531,12464]],[[13061,13061],"mapped",[12452,12531,12481]],[[13062,13062],"mapped",[12454,12457,12531]],[[13063,13063],"mapped",[12456,12473,12463,12540,12489]],[[13064,13064],"mapped",[12456,12540,12459,12540]],[[13065,13065],"mapped",[12458,12531,12473]],[[13066,13066],"mapped",[12458,12540,12512]],[[13067,13067],"mapped",[12459,12452,12522]],[[13068,13068],"mapped",[12459,12521,12483,12488]],[[13069,13069],"mapped",[12459,12525,12522,12540]],[[13070,13070],"mapped",[12460,12525,12531]],[[13071,13071],"mapped",[12460,12531,12510]],[[13072,13072],"mapped",[12462,12460]],[[13073,13073],"mapped",[12462,12491,12540]],[[13074,13074],"mapped",[12461,12517,12522,12540]],[[13075,13075],"mapped",[12462,12523,12480,12540]],[[13076,13076],"mapped",[12461,12525]],[[13077,13077],"mapped",[12461,12525,12464,12521,12512]],[[13078,13078],"mapped",[12461,12525,12513,12540,12488,12523]],[[13079,13079],"mapped",[12461,12525,12527,12483,12488]],[[13080,13080],"mapped",[12464,12521,12512]],[[13081,13081],"mapped",[12464,12521,12512,12488,12531]],[[13082,13082],"mapped",[12463,12523,12476,12452,12525]],[[13083,13083],"mapped",[12463,12525,12540,12493]],[[13084,13084],"mapped",[12465,12540,12473]],[[13085,13085],"mapped",[12467,12523,12490]],[[13086,13086],"mapped",[12467,12540,12509]],[[13087,13087],"mapped",[12469,12452,12463,12523]],[[13088,13088],"mapped",[12469,12531,12481,12540,12512]],[[13089,13089],"mapped",[12471,12522,12531,12464]],[[13090,13090],"mapped",[12475,12531,12481]],[[13091,13091],"mapped",[12475,12531,12488]],[[13092,13092],"mapped",[12480,12540,12473]],[[13093,13093],"mapped",[12487,12471]],[[13094,13094],"mapped",[12489,12523]],[[13095,13095],"mapped",[12488,12531]],[[13096,13096],"mapped",[12490,12494]],[[13097,13097],"mapped",[12494,12483,12488]],[[13098,13098],"mapped",[12495,12452,12484]],[[13099,13099],"mapped",[12497,12540,12475,12531,12488]],[[13100,13100],"mapped",[12497,12540,12484]],[[13101,13101],"mapped",[12496,12540,12524,12523]],[[13102,13102],"mapped",[12500,12450,12473,12488,12523]],[[13103,13103],"mapped",[12500,12463,12523]],[[13104,13104],"mapped",[12500,12467]],[[13105,13105],"mapped",[12499,12523]],[[13106,13106],"mapped",[12501,12449,12521,12483,12489]],[[13107,13107],"mapped",[12501,12451,12540,12488]],[[13108,13108],"mapped",[12502,12483,12471,12455,12523]],[[13109,13109],"mapped",[12501,12521,12531]],[[13110,13110],"mapped",[12504,12463,12479,12540,12523]],[[13111,13111],"mapped",[12506,12477]],[[13112,13112],"mapped",[12506,12491,12498]],[[13113,13113],"mapped",[12504,12523,12484]],[[13114,13114],"mapped",[12506,12531,12473]],[[13115,13115],"mapped",[12506,12540,12472]],[[13116,13116],"mapped",[12505,12540,12479]],[[13117,13117],"mapped",[12509,12452,12531,12488]],[[13118,13118],"mapped",[12508,12523,12488]],[[13119,13119],"mapped",[12507,12531]],[[13120,13120],"mapped",[12509,12531,12489]],[[13121,13121],"mapped",[12507,12540,12523]],[[13122,13122],"mapped",[12507,12540,12531]],[[13123,13123],"mapped",[12510,12452,12463,12525]],[[13124,13124],"mapped",[12510,12452,12523]],[[13125,13125],"mapped",[12510,12483,12495]],[[13126,13126],"mapped",[12510,12523,12463]],[[13127,13127],"mapped",[12510,12531,12471,12519,12531]],[[13128,13128],"mapped",[12511,12463,12525,12531]],[[13129,13129],"mapped",[12511,12522]],[[13130,13130],"mapped",[12511,12522,12496,12540,12523]],[[13131,13131],"mapped",[12513,12460]],[[13132,13132],"mapped",[12513,12460,12488,12531]],[[13133,13133],"mapped",[12513,12540,12488,12523]],[[13134,13134],"mapped",[12516,12540,12489]],[[13135,13135],"mapped",[12516,12540,12523]],[[13136,13136],"mapped",[12518,12450,12531]],[[13137,13137],"mapped",[12522,12483,12488,12523]],[[13138,13138],"mapped",[12522,12521]],[[13139,13139],"mapped",[12523,12500,12540]],[[13140,13140],"mapped",[12523,12540,12502,12523]],[[13141,13141],"mapped",[12524,12512]],[[13142,13142],"mapped",[12524,12531,12488,12466,12531]],[[13143,13143],"mapped",[12527,12483,12488]],[[13144,13144],"mapped",[48,28857]],[[13145,13145],"mapped",[49,28857]],[[13146,13146],"mapped",[50,28857]],[[13147,13147],"mapped",[51,28857]],[[13148,13148],"mapped",[52,28857]],[[13149,13149],"mapped",[53,28857]],[[13150,13150],"mapped",[54,28857]],[[13151,13151],"mapped",[55,28857]],[[13152,13152],"mapped",[56,28857]],[[13153,13153],"mapped",[57,28857]],[[13154,13154],"mapped",[49,48,28857]],[[13155,13155],"mapped",[49,49,28857]],[[13156,13156],"mapped",[49,50,28857]],[[13157,13157],"mapped",[49,51,28857]],[[13158,13158],"mapped",[49,52,28857]],[[13159,13159],"mapped",[49,53,28857]],[[13160,13160],"mapped",[49,54,28857]],[[13161,13161],"mapped",[49,55,28857]],[[13162,13162],"mapped",[49,56,28857]],[[13163,13163],"mapped",[49,57,28857]],[[13164,13164],"mapped",[50,48,28857]],[[13165,13165],"mapped",[50,49,28857]],[[13166,13166],"mapped",[50,50,28857]],[[13167,13167],"mapped",[50,51,28857]],[[13168,13168],"mapped",[50,52,28857]],[[13169,13169],"mapped",[104,112,97]],[[13170,13170],"mapped",[100,97]],[[13171,13171],"mapped",[97,117]],[[13172,13172],"mapped",[98,97,114]],[[13173,13173],"mapped",[111,118]],[[13174,13174],"mapped",[112,99]],[[13175,13175],"mapped",[100,109]],[[13176,13176],"mapped",[100,109,50]],[[13177,13177],"mapped",[100,109,51]],[[13178,13178],"mapped",[105,117]],[[13179,13179],"mapped",[24179,25104]],[[13180,13180],"mapped",[26157,21644]],[[13181,13181],"mapped",[22823,27491]],[[13182,13182],"mapped",[26126,27835]],[[13183,13183],"mapped",[26666,24335,20250,31038]],[[13184,13184],"mapped",[112,97]],[[13185,13185],"mapped",[110,97]],[[13186,13186],"mapped",[956,97]],[[13187,13187],"mapped",[109,97]],[[13188,13188],"mapped",[107,97]],[[13189,13189],"mapped",[107,98]],[[13190,13190],"mapped",[109,98]],[[13191,13191],"mapped",[103,98]],[[13192,13192],"mapped",[99,97,108]],[[13193,13193],"mapped",[107,99,97,108]],[[13194,13194],"mapped",[112,102]],[[13195,13195],"mapped",[110,102]],[[13196,13196],"mapped",[956,102]],[[13197,13197],"mapped",[956,103]],[[13198,13198],"mapped",[109,103]],[[13199,13199],"mapped",[107,103]],[[13200,13200],"mapped",[104,122]],[[13201,13201],"mapped",[107,104,122]],[[13202,13202],"mapped",[109,104,122]],[[13203,13203],"mapped",[103,104,122]],[[13204,13204],"mapped",[116,104,122]],[[13205,13205],"mapped",[956,108]],[[13206,13206],"mapped",[109,108]],[[13207,13207],"mapped",[100,108]],[[13208,13208],"mapped",[107,108]],[[13209,13209],"mapped",[102,109]],[[13210,13210],"mapped",[110,109]],[[13211,13211],"mapped",[956,109]],[[13212,13212],"mapped",[109,109]],[[13213,13213],"mapped",[99,109]],[[13214,13214],"mapped",[107,109]],[[13215,13215],"mapped",[109,109,50]],[[13216,13216],"mapped",[99,109,50]],[[13217,13217],"mapped",[109,50]],[[13218,13218],"mapped",[107,109,50]],[[13219,13219],"mapped",[109,109,51]],[[13220,13220],"mapped",[99,109,51]],[[13221,13221],"mapped",[109,51]],[[13222,13222],"mapped",[107,109,51]],[[13223,13223],"mapped",[109,8725,115]],[[13224,13224],"mapped",[109,8725,115,50]],[[13225,13225],"mapped",[112,97]],[[13226,13226],"mapped",[107,112,97]],[[13227,13227],"mapped",[109,112,97]],[[13228,13228],"mapped",[103,112,97]],[[13229,13229],"mapped",[114,97,100]],[[13230,13230],"mapped",[114,97,100,8725,115]],[[13231,13231],"mapped",[114,97,100,8725,115,50]],[[13232,13232],"mapped",[112,115]],[[13233,13233],"mapped",[110,115]],[[13234,13234],"mapped",[956,115]],[[13235,13235],"mapped",[109,115]],[[13236,13236],"mapped",[112,118]],[[13237,13237],"mapped",[110,118]],[[13238,13238],"mapped",[956,118]],[[13239,13239],"mapped",[109,118]],[[13240,13240],"mapped",[107,118]],[[13241,13241],"mapped",[109,118]],[[13242,13242],"mapped",[112,119]],[[13243,13243],"mapped",[110,119]],[[13244,13244],"mapped",[956,119]],[[13245,13245],"mapped",[109,119]],[[13246,13246],"mapped",[107,119]],[[13247,13247],"mapped",[109,119]],[[13248,13248],"mapped",[107,969]],[[13249,13249],"mapped",[109,969]],[[13250,13250],"disallowed"],[[13251,13251],"mapped",[98,113]],[[13252,13252],"mapped",[99,99]],[[13253,13253],"mapped",[99,100]],[[13254,13254],"mapped",[99,8725,107,103]],[[13255,13255],"disallowed"],[[13256,13256],"mapped",[100,98]],[[13257,13257],"mapped",[103,121]],[[13258,13258],"mapped",[104,97]],[[13259,13259],"mapped",[104,112]],[[13260,13260],"mapped",[105,110]],[[13261,13261],"mapped",[107,107]],[[13262,13262],"mapped",[107,109]],[[13263,13263],"mapped",[107,116]],[[13264,13264],"mapped",[108,109]],[[13265,13265],"mapped",[108,110]],[[13266,13266],"mapped",[108,111,103]],[[13267,13267],"mapped",[108,120]],[[13268,13268],"mapped",[109,98]],[[13269,13269],"mapped",[109,105,108]],[[13270,13270],"mapped",[109,111,108]],[[13271,13271],"mapped",[112,104]],[[13272,13272],"disallowed"],[[13273,13273],"mapped",[112,112,109]],[[13274,13274],"mapped",[112,114]],[[13275,13275],"mapped",[115,114]],[[13276,13276],"mapped",[115,118]],[[13277,13277],"mapped",[119,98]],[[13278,13278],"mapped",[118,8725,109]],[[13279,13279],"mapped",[97,8725,109]],[[13280,13280],"mapped",[49,26085]],[[13281,13281],"mapped",[50,26085]],[[13282,13282],"mapped",[51,26085]],[[13283,13283],"mapped",[52,26085]],[[13284,13284],"mapped",[53,26085]],[[13285,13285],"mapped",[54,26085]],[[13286,13286],"mapped",[55,26085]],[[13287,13287],"mapped",[56,26085]],[[13288,13288],"mapped",[57,26085]],[[13289,13289],"mapped",[49,48,26085]],[[13290,13290],"mapped",[49,49,26085]],[[13291,13291],"mapped",[49,50,26085]],[[13292,13292],"mapped",[49,51,26085]],[[13293,13293],"mapped",[49,52,26085]],[[13294,13294],"mapped",[49,53,26085]],[[13295,13295],"mapped",[49,54,26085]],[[13296,13296],"mapped",[49,55,26085]],[[13297,13297],"mapped",[49,56,26085]],[[13298,13298],"mapped",[49,57,26085]],[[13299,13299],"mapped",[50,48,26085]],[[13300,13300],"mapped",[50,49,26085]],[[13301,13301],"mapped",[50,50,26085]],[[13302,13302],"mapped",[50,51,26085]],[[13303,13303],"mapped",[50,52,26085]],[[13304,13304],"mapped",[50,53,26085]],[[13305,13305],"mapped",[50,54,26085]],[[13306,13306],"mapped",[50,55,26085]],[[13307,13307],"mapped",[50,56,26085]],[[13308,13308],"mapped",[50,57,26085]],[[13309,13309],"mapped",[51,48,26085]],[[13310,13310],"mapped",[51,49,26085]],[[13311,13311],"mapped",[103,97,108]],[[13312,19893],"valid"],[[19894,19903],"disallowed"],[[19904,19967],"valid",[],"NV8"],[[19968,40869],"valid"],[[40870,40891],"valid"],[[40892,40899],"valid"],[[40900,40907],"valid"],[[40908,40908],"valid"],[[40909,40917],"valid"],[[40918,40959],"disallowed"],[[40960,42124],"valid"],[[42125,42127],"disallowed"],[[42128,42145],"valid",[],"NV8"],[[42146,42147],"valid",[],"NV8"],[[42148,42163],"valid",[],"NV8"],[[42164,42164],"valid",[],"NV8"],[[42165,42176],"valid",[],"NV8"],[[42177,42177],"valid",[],"NV8"],[[42178,42180],"valid",[],"NV8"],[[42181,42181],"valid",[],"NV8"],[[42182,42182],"valid",[],"NV8"],[[42183,42191],"disallowed"],[[42192,42237],"valid"],[[42238,42239],"valid",[],"NV8"],[[42240,42508],"valid"],[[42509,42511],"valid",[],"NV8"],[[42512,42539],"valid"],[[42540,42559],"disallowed"],[[42560,42560],"mapped",[42561]],[[42561,42561],"valid"],[[42562,42562],"mapped",[42563]],[[42563,42563],"valid"],[[42564,42564],"mapped",[42565]],[[42565,42565],"valid"],[[42566,42566],"mapped",[42567]],[[42567,42567],"valid"],[[42568,42568],"mapped",[42569]],[[42569,42569],"valid"],[[42570,42570],"mapped",[42571]],[[42571,42571],"valid"],[[42572,42572],"mapped",[42573]],[[42573,42573],"valid"],[[42574,42574],"mapped",[42575]],[[42575,42575],"valid"],[[42576,42576],"mapped",[42577]],[[42577,42577],"valid"],[[42578,42578],"mapped",[42579]],[[42579,42579],"valid"],[[42580,42580],"mapped",[42581]],[[42581,42581],"valid"],[[42582,42582],"mapped",[42583]],[[42583,42583],"valid"],[[42584,42584],"mapped",[42585]],[[42585,42585],"valid"],[[42586,42586],"mapped",[42587]],[[42587,42587],"valid"],[[42588,42588],"mapped",[42589]],[[42589,42589],"valid"],[[42590,42590],"mapped",[42591]],[[42591,42591],"valid"],[[42592,42592],"mapped",[42593]],[[42593,42593],"valid"],[[42594,42594],"mapped",[42595]],[[42595,42595],"valid"],[[42596,42596],"mapped",[42597]],[[42597,42597],"valid"],[[42598,42598],"mapped",[42599]],[[42599,42599],"valid"],[[42600,42600],"mapped",[42601]],[[42601,42601],"valid"],[[42602,42602],"mapped",[42603]],[[42603,42603],"valid"],[[42604,42604],"mapped",[42605]],[[42605,42607],"valid"],[[42608,42611],"valid",[],"NV8"],[[42612,42619],"valid"],[[42620,42621],"valid"],[[42622,42622],"valid",[],"NV8"],[[42623,42623],"valid"],[[42624,42624],"mapped",[42625]],[[42625,42625],"valid"],[[42626,42626],"mapped",[42627]],[[42627,42627],"valid"],[[42628,42628],"mapped",[42629]],[[42629,42629],"valid"],[[42630,42630],"mapped",[42631]],[[42631,42631],"valid"],[[42632,42632],"mapped",[42633]],[[42633,42633],"valid"],[[42634,42634],"mapped",[42635]],[[42635,42635],"valid"],[[42636,42636],"mapped",[42637]],[[42637,42637],"valid"],[[42638,42638],"mapped",[42639]],[[42639,42639],"valid"],[[42640,42640],"mapped",[42641]],[[42641,42641],"valid"],[[42642,42642],"mapped",[42643]],[[42643,42643],"valid"],[[42644,42644],"mapped",[42645]],[[42645,42645],"valid"],[[42646,42646],"mapped",[42647]],[[42647,42647],"valid"],[[42648,42648],"mapped",[42649]],[[42649,42649],"valid"],[[42650,42650],"mapped",[42651]],[[42651,42651],"valid"],[[42652,42652],"mapped",[1098]],[[42653,42653],"mapped",[1100]],[[42654,42654],"valid"],[[42655,42655],"valid"],[[42656,42725],"valid"],[[42726,42735],"valid",[],"NV8"],[[42736,42737],"valid"],[[42738,42743],"valid",[],"NV8"],[[42744,42751],"disallowed"],[[42752,42774],"valid",[],"NV8"],[[42775,42778],"valid"],[[42779,42783],"valid"],[[42784,42785],"valid",[],"NV8"],[[42786,42786],"mapped",[42787]],[[42787,42787],"valid"],[[42788,42788],"mapped",[42789]],[[42789,42789],"valid"],[[42790,42790],"mapped",[42791]],[[42791,42791],"valid"],[[42792,42792],"mapped",[42793]],[[42793,42793],"valid"],[[42794,42794],"mapped",[42795]],[[42795,42795],"valid"],[[42796,42796],"mapped",[42797]],[[42797,42797],"valid"],[[42798,42798],"mapped",[42799]],[[42799,42801],"valid"],[[42802,42802],"mapped",[42803]],[[42803,42803],"valid"],[[42804,42804],"mapped",[42805]],[[42805,42805],"valid"],[[42806,42806],"mapped",[42807]],[[42807,42807],"valid"],[[42808,42808],"mapped",[42809]],[[42809,42809],"valid"],[[42810,42810],"mapped",[42811]],[[42811,42811],"valid"],[[42812,42812],"mapped",[42813]],[[42813,42813],"valid"],[[42814,42814],"mapped",[42815]],[[42815,42815],"valid"],[[42816,42816],"mapped",[42817]],[[42817,42817],"valid"],[[42818,42818],"mapped",[42819]],[[42819,42819],"valid"],[[42820,42820],"mapped",[42821]],[[42821,42821],"valid"],[[42822,42822],"mapped",[42823]],[[42823,42823],"valid"],[[42824,42824],"mapped",[42825]],[[42825,42825],"valid"],[[42826,42826],"mapped",[42827]],[[42827,42827],"valid"],[[42828,42828],"mapped",[42829]],[[42829,42829],"valid"],[[42830,42830],"mapped",[42831]],[[42831,42831],"valid"],[[42832,42832],"mapped",[42833]],[[42833,42833],"valid"],[[42834,42834],"mapped",[42835]],[[42835,42835],"valid"],[[42836,42836],"mapped",[42837]],[[42837,42837],"valid"],[[42838,42838],"mapped",[42839]],[[42839,42839],"valid"],[[42840,42840],"mapped",[42841]],[[42841,42841],"valid"],[[42842,42842],"mapped",[42843]],[[42843,42843],"valid"],[[42844,42844],"mapped",[42845]],[[42845,42845],"valid"],[[42846,42846],"mapped",[42847]],[[42847,42847],"valid"],[[42848,42848],"mapped",[42849]],[[42849,42849],"valid"],[[42850,42850],"mapped",[42851]],[[42851,42851],"valid"],[[42852,42852],"mapped",[42853]],[[42853,42853],"valid"],[[42854,42854],"mapped",[42855]],[[42855,42855],"valid"],[[42856,42856],"mapped",[42857]],[[42857,42857],"valid"],[[42858,42858],"mapped",[42859]],[[42859,42859],"valid"],[[42860,42860],"mapped",[42861]],[[42861,42861],"valid"],[[42862,42862],"mapped",[42863]],[[42863,42863],"valid"],[[42864,42864],"mapped",[42863]],[[42865,42872],"valid"],[[42873,42873],"mapped",[42874]],[[42874,42874],"valid"],[[42875,42875],"mapped",[42876]],[[42876,42876],"valid"],[[42877,42877],"mapped",[7545]],[[42878,42878],"mapped",[42879]],[[42879,42879],"valid"],[[42880,42880],"mapped",[42881]],[[42881,42881],"valid"],[[42882,42882],"mapped",[42883]],[[42883,42883],"valid"],[[42884,42884],"mapped",[42885]],[[42885,42885],"valid"],[[42886,42886],"mapped",[42887]],[[42887,42888],"valid"],[[42889,42890],"valid",[],"NV8"],[[42891,42891],"mapped",[42892]],[[42892,42892],"valid"],[[42893,42893],"mapped",[613]],[[42894,42894],"valid"],[[42895,42895],"valid"],[[42896,42896],"mapped",[42897]],[[42897,42897],"valid"],[[42898,42898],"mapped",[42899]],[[42899,42899],"valid"],[[42900,42901],"valid"],[[42902,42902],"mapped",[42903]],[[42903,42903],"valid"],[[42904,42904],"mapped",[42905]],[[42905,42905],"valid"],[[42906,42906],"mapped",[42907]],[[42907,42907],"valid"],[[42908,42908],"mapped",[42909]],[[42909,42909],"valid"],[[42910,42910],"mapped",[42911]],[[42911,42911],"valid"],[[42912,42912],"mapped",[42913]],[[42913,42913],"valid"],[[42914,42914],"mapped",[42915]],[[42915,42915],"valid"],[[42916,42916],"mapped",[42917]],[[42917,42917],"valid"],[[42918,42918],"mapped",[42919]],[[42919,42919],"valid"],[[42920,42920],"mapped",[42921]],[[42921,42921],"valid"],[[42922,42922],"mapped",[614]],[[42923,42923],"mapped",[604]],[[42924,42924],"mapped",[609]],[[42925,42925],"mapped",[620]],[[42926,42927],"disallowed"],[[42928,42928],"mapped",[670]],[[42929,42929],"mapped",[647]],[[42930,42930],"mapped",[669]],[[42931,42931],"mapped",[43859]],[[42932,42932],"mapped",[42933]],[[42933,42933],"valid"],[[42934,42934],"mapped",[42935]],[[42935,42935],"valid"],[[42936,42998],"disallowed"],[[42999,42999],"valid"],[[43000,43000],"mapped",[295]],[[43001,43001],"mapped",[339]],[[43002,43002],"valid"],[[43003,43007],"valid"],[[43008,43047],"valid"],[[43048,43051],"valid",[],"NV8"],[[43052,43055],"disallowed"],[[43056,43065],"valid",[],"NV8"],[[43066,43071],"disallowed"],[[43072,43123],"valid"],[[43124,43127],"valid",[],"NV8"],[[43128,43135],"disallowed"],[[43136,43204],"valid"],[[43205,43213],"disallowed"],[[43214,43215],"valid",[],"NV8"],[[43216,43225],"valid"],[[43226,43231],"disallowed"],[[43232,43255],"valid"],[[43256,43258],"valid",[],"NV8"],[[43259,43259],"valid"],[[43260,43260],"valid",[],"NV8"],[[43261,43261],"valid"],[[43262,43263],"disallowed"],[[43264,43309],"valid"],[[43310,43311],"valid",[],"NV8"],[[43312,43347],"valid"],[[43348,43358],"disallowed"],[[43359,43359],"valid",[],"NV8"],[[43360,43388],"valid",[],"NV8"],[[43389,43391],"disallowed"],[[43392,43456],"valid"],[[43457,43469],"valid",[],"NV8"],[[43470,43470],"disallowed"],[[43471,43481],"valid"],[[43482,43485],"disallowed"],[[43486,43487],"valid",[],"NV8"],[[43488,43518],"valid"],[[43519,43519],"disallowed"],[[43520,43574],"valid"],[[43575,43583],"disallowed"],[[43584,43597],"valid"],[[43598,43599],"disallowed"],[[43600,43609],"valid"],[[43610,43611],"disallowed"],[[43612,43615],"valid",[],"NV8"],[[43616,43638],"valid"],[[43639,43641],"valid",[],"NV8"],[[43642,43643],"valid"],[[43644,43647],"valid"],[[43648,43714],"valid"],[[43715,43738],"disallowed"],[[43739,43741],"valid"],[[43742,43743],"valid",[],"NV8"],[[43744,43759],"valid"],[[43760,43761],"valid",[],"NV8"],[[43762,43766],"valid"],[[43767,43776],"disallowed"],[[43777,43782],"valid"],[[43783,43784],"disallowed"],[[43785,43790],"valid"],[[43791,43792],"disallowed"],[[43793,43798],"valid"],[[43799,43807],"disallowed"],[[43808,43814],"valid"],[[43815,43815],"disallowed"],[[43816,43822],"valid"],[[43823,43823],"disallowed"],[[43824,43866],"valid"],[[43867,43867],"valid",[],"NV8"],[[43868,43868],"mapped",[42791]],[[43869,43869],"mapped",[43831]],[[43870,43870],"mapped",[619]],[[43871,43871],"mapped",[43858]],[[43872,43875],"valid"],[[43876,43877],"valid"],[[43878,43887],"disallowed"],[[43888,43888],"mapped",[5024]],[[43889,43889],"mapped",[5025]],[[43890,43890],"mapped",[5026]],[[43891,43891],"mapped",[5027]],[[43892,43892],"mapped",[5028]],[[43893,43893],"mapped",[5029]],[[43894,43894],"mapped",[5030]],[[43895,43895],"mapped",[5031]],[[43896,43896],"mapped",[5032]],[[43897,43897],"mapped",[5033]],[[43898,43898],"mapped",[5034]],[[43899,43899],"mapped",[5035]],[[43900,43900],"mapped",[5036]],[[43901,43901],"mapped",[5037]],[[43902,43902],"mapped",[5038]],[[43903,43903],"mapped",[5039]],[[43904,43904],"mapped",[5040]],[[43905,43905],"mapped",[5041]],[[43906,43906],"mapped",[5042]],[[43907,43907],"mapped",[5043]],[[43908,43908],"mapped",[5044]],[[43909,43909],"mapped",[5045]],[[43910,43910],"mapped",[5046]],[[43911,43911],"mapped",[5047]],[[43912,43912],"mapped",[5048]],[[43913,43913],"mapped",[5049]],[[43914,43914],"mapped",[5050]],[[43915,43915],"mapped",[5051]],[[43916,43916],"mapped",[5052]],[[43917,43917],"mapped",[5053]],[[43918,43918],"mapped",[5054]],[[43919,43919],"mapped",[5055]],[[43920,43920],"mapped",[5056]],[[43921,43921],"mapped",[5057]],[[43922,43922],"mapped",[5058]],[[43923,43923],"mapped",[5059]],[[43924,43924],"mapped",[5060]],[[43925,43925],"mapped",[5061]],[[43926,43926],"mapped",[5062]],[[43927,43927],"mapped",[5063]],[[43928,43928],"mapped",[5064]],[[43929,43929],"mapped",[5065]],[[43930,43930],"mapped",[5066]],[[43931,43931],"mapped",[5067]],[[43932,43932],"mapped",[5068]],[[43933,43933],"mapped",[5069]],[[43934,43934],"mapped",[5070]],[[43935,43935],"mapped",[5071]],[[43936,43936],"mapped",[5072]],[[43937,43937],"mapped",[5073]],[[43938,43938],"mapped",[5074]],[[43939,43939],"mapped",[5075]],[[43940,43940],"mapped",[5076]],[[43941,43941],"mapped",[5077]],[[43942,43942],"mapped",[5078]],[[43943,43943],"mapped",[5079]],[[43944,43944],"mapped",[5080]],[[43945,43945],"mapped",[5081]],[[43946,43946],"mapped",[5082]],[[43947,43947],"mapped",[5083]],[[43948,43948],"mapped",[5084]],[[43949,43949],"mapped",[5085]],[[43950,43950],"mapped",[5086]],[[43951,43951],"mapped",[5087]],[[43952,43952],"mapped",[5088]],[[43953,43953],"mapped",[5089]],[[43954,43954],"mapped",[5090]],[[43955,43955],"mapped",[5091]],[[43956,43956],"mapped",[5092]],[[43957,43957],"mapped",[5093]],[[43958,43958],"mapped",[5094]],[[43959,43959],"mapped",[5095]],[[43960,43960],"mapped",[5096]],[[43961,43961],"mapped",[5097]],[[43962,43962],"mapped",[5098]],[[43963,43963],"mapped",[5099]],[[43964,43964],"mapped",[5100]],[[43965,43965],"mapped",[5101]],[[43966,43966],"mapped",[5102]],[[43967,43967],"mapped",[5103]],[[43968,44010],"valid"],[[44011,44011],"valid",[],"NV8"],[[44012,44013],"valid"],[[44014,44015],"disallowed"],[[44016,44025],"valid"],[[44026,44031],"disallowed"],[[44032,55203],"valid"],[[55204,55215],"disallowed"],[[55216,55238],"valid",[],"NV8"],[[55239,55242],"disallowed"],[[55243,55291],"valid",[],"NV8"],[[55292,55295],"disallowed"],[[55296,57343],"disallowed"],[[57344,63743],"disallowed"],[[63744,63744],"mapped",[35912]],[[63745,63745],"mapped",[26356]],[[63746,63746],"mapped",[36554]],[[63747,63747],"mapped",[36040]],[[63748,63748],"mapped",[28369]],[[63749,63749],"mapped",[20018]],[[63750,63750],"mapped",[21477]],[[63751,63752],"mapped",[40860]],[[63753,63753],"mapped",[22865]],[[63754,63754],"mapped",[37329]],[[63755,63755],"mapped",[21895]],[[63756,63756],"mapped",[22856]],[[63757,63757],"mapped",[25078]],[[63758,63758],"mapped",[30313]],[[63759,63759],"mapped",[32645]],[[63760,63760],"mapped",[34367]],[[63761,63761],"mapped",[34746]],[[63762,63762],"mapped",[35064]],[[63763,63763],"mapped",[37007]],[[63764,63764],"mapped",[27138]],[[63765,63765],"mapped",[27931]],[[63766,63766],"mapped",[28889]],[[63767,63767],"mapped",[29662]],[[63768,63768],"mapped",[33853]],[[63769,63769],"mapped",[37226]],[[63770,63770],"mapped",[39409]],[[63771,63771],"mapped",[20098]],[[63772,63772],"mapped",[21365]],[[63773,63773],"mapped",[27396]],[[63774,63774],"mapped",[29211]],[[63775,63775],"mapped",[34349]],[[63776,63776],"mapped",[40478]],[[63777,63777],"mapped",[23888]],[[63778,63778],"mapped",[28651]],[[63779,63779],"mapped",[34253]],[[63780,63780],"mapped",[35172]],[[63781,63781],"mapped",[25289]],[[63782,63782],"mapped",[33240]],[[63783,63783],"mapped",[34847]],[[63784,63784],"mapped",[24266]],[[63785,63785],"mapped",[26391]],[[63786,63786],"mapped",[28010]],[[63787,63787],"mapped",[29436]],[[63788,63788],"mapped",[37070]],[[63789,63789],"mapped",[20358]],[[63790,63790],"mapped",[20919]],[[63791,63791],"mapped",[21214]],[[63792,63792],"mapped",[25796]],[[63793,63793],"mapped",[27347]],[[63794,63794],"mapped",[29200]],[[63795,63795],"mapped",[30439]],[[63796,63796],"mapped",[32769]],[[63797,63797],"mapped",[34310]],[[63798,63798],"mapped",[34396]],[[63799,63799],"mapped",[36335]],[[63800,63800],"mapped",[38706]],[[63801,63801],"mapped",[39791]],[[63802,63802],"mapped",[40442]],[[63803,63803],"mapped",[30860]],[[63804,63804],"mapped",[31103]],[[63805,63805],"mapped",[32160]],[[63806,63806],"mapped",[33737]],[[63807,63807],"mapped",[37636]],[[63808,63808],"mapped",[40575]],[[63809,63809],"mapped",[35542]],[[63810,63810],"mapped",[22751]],[[63811,63811],"mapped",[24324]],[[63812,63812],"mapped",[31840]],[[63813,63813],"mapped",[32894]],[[63814,63814],"mapped",[29282]],[[63815,63815],"mapped",[30922]],[[63816,63816],"mapped",[36034]],[[63817,63817],"mapped",[38647]],[[63818,63818],"mapped",[22744]],[[63819,63819],"mapped",[23650]],[[63820,63820],"mapped",[27155]],[[63821,63821],"mapped",[28122]],[[63822,63822],"mapped",[28431]],[[63823,63823],"mapped",[32047]],[[63824,63824],"mapped",[32311]],[[63825,63825],"mapped",[38475]],[[63826,63826],"mapped",[21202]],[[63827,63827],"mapped",[32907]],[[63828,63828],"mapped",[20956]],[[63829,63829],"mapped",[20940]],[[63830,63830],"mapped",[31260]],[[63831,63831],"mapped",[32190]],[[63832,63832],"mapped",[33777]],[[63833,63833],"mapped",[38517]],[[63834,63834],"mapped",[35712]],[[63835,63835],"mapped",[25295]],[[63836,63836],"mapped",[27138]],[[63837,63837],"mapped",[35582]],[[63838,63838],"mapped",[20025]],[[63839,63839],"mapped",[23527]],[[63840,63840],"mapped",[24594]],[[63841,63841],"mapped",[29575]],[[63842,63842],"mapped",[30064]],[[63843,63843],"mapped",[21271]],[[63844,63844],"mapped",[30971]],[[63845,63845],"mapped",[20415]],[[63846,63846],"mapped",[24489]],[[63847,63847],"mapped",[19981]],[[63848,63848],"mapped",[27852]],[[63849,63849],"mapped",[25976]],[[63850,63850],"mapped",[32034]],[[63851,63851],"mapped",[21443]],[[63852,63852],"mapped",[22622]],[[63853,63853],"mapped",[30465]],[[63854,63854],"mapped",[33865]],[[63855,63855],"mapped",[35498]],[[63856,63856],"mapped",[27578]],[[63857,63857],"mapped",[36784]],[[63858,63858],"mapped",[27784]],[[63859,63859],"mapped",[25342]],[[63860,63860],"mapped",[33509]],[[63861,63861],"mapped",[25504]],[[63862,63862],"mapped",[30053]],[[63863,63863],"mapped",[20142]],[[63864,63864],"mapped",[20841]],[[63865,63865],"mapped",[20937]],[[63866,63866],"mapped",[26753]],[[63867,63867],"mapped",[31975]],[[63868,63868],"mapped",[33391]],[[63869,63869],"mapped",[35538]],[[63870,63870],"mapped",[37327]],[[63871,63871],"mapped",[21237]],[[63872,63872],"mapped",[21570]],[[63873,63873],"mapped",[22899]],[[63874,63874],"mapped",[24300]],[[63875,63875],"mapped",[26053]],[[63876,63876],"mapped",[28670]],[[63877,63877],"mapped",[31018]],[[63878,63878],"mapped",[38317]],[[63879,63879],"mapped",[39530]],[[63880,63880],"mapped",[40599]],[[63881,63881],"mapped",[40654]],[[63882,63882],"mapped",[21147]],[[63883,63883],"mapped",[26310]],[[63884,63884],"mapped",[27511]],[[63885,63885],"mapped",[36706]],[[63886,63886],"mapped",[24180]],[[63887,63887],"mapped",[24976]],[[63888,63888],"mapped",[25088]],[[63889,63889],"mapped",[25754]],[[63890,63890],"mapped",[28451]],[[63891,63891],"mapped",[29001]],[[63892,63892],"mapped",[29833]],[[63893,63893],"mapped",[31178]],[[63894,63894],"mapped",[32244]],[[63895,63895],"mapped",[32879]],[[63896,63896],"mapped",[36646]],[[63897,63897],"mapped",[34030]],[[63898,63898],"mapped",[36899]],[[63899,63899],"mapped",[37706]],[[63900,63900],"mapped",[21015]],[[63901,63901],"mapped",[21155]],[[63902,63902],"mapped",[21693]],[[63903,63903],"mapped",[28872]],[[63904,63904],"mapped",[35010]],[[63905,63905],"mapped",[35498]],[[63906,63906],"mapped",[24265]],[[63907,63907],"mapped",[24565]],[[63908,63908],"mapped",[25467]],[[63909,63909],"mapped",[27566]],[[63910,63910],"mapped",[31806]],[[63911,63911],"mapped",[29557]],[[63912,63912],"mapped",[20196]],[[63913,63913],"mapped",[22265]],[[63914,63914],"mapped",[23527]],[[63915,63915],"mapped",[23994]],[[63916,63916],"mapped",[24604]],[[63917,63917],"mapped",[29618]],[[63918,63918],"mapped",[29801]],[[63919,63919],"mapped",[32666]],[[63920,63920],"mapped",[32838]],[[63921,63921],"mapped",[37428]],[[63922,63922],"mapped",[38646]],[[63923,63923],"mapped",[38728]],[[63924,63924],"mapped",[38936]],[[63925,63925],"mapped",[20363]],[[63926,63926],"mapped",[31150]],[[63927,63927],"mapped",[37300]],[[63928,63928],"mapped",[38584]],[[63929,63929],"mapped",[24801]],[[63930,63930],"mapped",[20102]],[[63931,63931],"mapped",[20698]],[[63932,63932],"mapped",[23534]],[[63933,63933],"mapped",[23615]],[[63934,63934],"mapped",[26009]],[[63935,63935],"mapped",[27138]],[[63936,63936],"mapped",[29134]],[[63937,63937],"mapped",[30274]],[[63938,63938],"mapped",[34044]],[[63939,63939],"mapped",[36988]],[[63940,63940],"mapped",[40845]],[[63941,63941],"mapped",[26248]],[[63942,63942],"mapped",[38446]],[[63943,63943],"mapped",[21129]],[[63944,63944],"mapped",[26491]],[[63945,63945],"mapped",[26611]],[[63946,63946],"mapped",[27969]],[[63947,63947],"mapped",[28316]],[[63948,63948],"mapped",[29705]],[[63949,63949],"mapped",[30041]],[[63950,63950],"mapped",[30827]],[[63951,63951],"mapped",[32016]],[[63952,63952],"mapped",[39006]],[[63953,63953],"mapped",[20845]],[[63954,63954],"mapped",[25134]],[[63955,63955],"mapped",[38520]],[[63956,63956],"mapped",[20523]],[[63957,63957],"mapped",[23833]],[[63958,63958],"mapped",[28138]],[[63959,63959],"mapped",[36650]],[[63960,63960],"mapped",[24459]],[[63961,63961],"mapped",[24900]],[[63962,63962],"mapped",[26647]],[[63963,63963],"mapped",[29575]],[[63964,63964],"mapped",[38534]],[[63965,63965],"mapped",[21033]],[[63966,63966],"mapped",[21519]],[[63967,63967],"mapped",[23653]],[[63968,63968],"mapped",[26131]],[[63969,63969],"mapped",[26446]],[[63970,63970],"mapped",[26792]],[[63971,63971],"mapped",[27877]],[[63972,63972],"mapped",[29702]],[[63973,63973],"mapped",[30178]],[[63974,63974],"mapped",[32633]],[[63975,63975],"mapped",[35023]],[[63976,63976],"mapped",[35041]],[[63977,63977],"mapped",[37324]],[[63978,63978],"mapped",[38626]],[[63979,63979],"mapped",[21311]],[[63980,63980],"mapped",[28346]],[[63981,63981],"mapped",[21533]],[[63982,63982],"mapped",[29136]],[[63983,63983],"mapped",[29848]],[[63984,63984],"mapped",[34298]],[[63985,63985],"mapped",[38563]],[[63986,63986],"mapped",[40023]],[[63987,63987],"mapped",[40607]],[[63988,63988],"mapped",[26519]],[[63989,63989],"mapped",[28107]],[[63990,63990],"mapped",[33256]],[[63991,63991],"mapped",[31435]],[[63992,63992],"mapped",[31520]],[[63993,63993],"mapped",[31890]],[[63994,63994],"mapped",[29376]],[[63995,63995],"mapped",[28825]],[[63996,63996],"mapped",[35672]],[[63997,63997],"mapped",[20160]],[[63998,63998],"mapped",[33590]],[[63999,63999],"mapped",[21050]],[[64000,64000],"mapped",[20999]],[[64001,64001],"mapped",[24230]],[[64002,64002],"mapped",[25299]],[[64003,64003],"mapped",[31958]],[[64004,64004],"mapped",[23429]],[[64005,64005],"mapped",[27934]],[[64006,64006],"mapped",[26292]],[[64007,64007],"mapped",[36667]],[[64008,64008],"mapped",[34892]],[[64009,64009],"mapped",[38477]],[[64010,64010],"mapped",[35211]],[[64011,64011],"mapped",[24275]],[[64012,64012],"mapped",[20800]],[[64013,64013],"mapped",[21952]],[[64014,64015],"valid"],[[64016,64016],"mapped",[22618]],[[64017,64017],"valid"],[[64018,64018],"mapped",[26228]],[[64019,64020],"valid"],[[64021,64021],"mapped",[20958]],[[64022,64022],"mapped",[29482]],[[64023,64023],"mapped",[30410]],[[64024,64024],"mapped",[31036]],[[64025,64025],"mapped",[31070]],[[64026,64026],"mapped",[31077]],[[64027,64027],"mapped",[31119]],[[64028,64028],"mapped",[38742]],[[64029,64029],"mapped",[31934]],[[64030,64030],"mapped",[32701]],[[64031,64031],"valid"],[[64032,64032],"mapped",[34322]],[[64033,64033],"valid"],[[64034,64034],"mapped",[35576]],[[64035,64036],"valid"],[[64037,64037],"mapped",[36920]],[[64038,64038],"mapped",[37117]],[[64039,64041],"valid"],[[64042,64042],"mapped",[39151]],[[64043,64043],"mapped",[39164]],[[64044,64044],"mapped",[39208]],[[64045,64045],"mapped",[40372]],[[64046,64046],"mapped",[37086]],[[64047,64047],"mapped",[38583]],[[64048,64048],"mapped",[20398]],[[64049,64049],"mapped",[20711]],[[64050,64050],"mapped",[20813]],[[64051,64051],"mapped",[21193]],[[64052,64052],"mapped",[21220]],[[64053,64053],"mapped",[21329]],[[64054,64054],"mapped",[21917]],[[64055,64055],"mapped",[22022]],[[64056,64056],"mapped",[22120]],[[64057,64057],"mapped",[22592]],[[64058,64058],"mapped",[22696]],[[64059,64059],"mapped",[23652]],[[64060,64060],"mapped",[23662]],[[64061,64061],"mapped",[24724]],[[64062,64062],"mapped",[24936]],[[64063,64063],"mapped",[24974]],[[64064,64064],"mapped",[25074]],[[64065,64065],"mapped",[25935]],[[64066,64066],"mapped",[26082]],[[64067,64067],"mapped",[26257]],[[64068,64068],"mapped",[26757]],[[64069,64069],"mapped",[28023]],[[64070,64070],"mapped",[28186]],[[64071,64071],"mapped",[28450]],[[64072,64072],"mapped",[29038]],[[64073,64073],"mapped",[29227]],[[64074,64074],"mapped",[29730]],[[64075,64075],"mapped",[30865]],[[64076,64076],"mapped",[31038]],[[64077,64077],"mapped",[31049]],[[64078,64078],"mapped",[31048]],[[64079,64079],"mapped",[31056]],[[64080,64080],"mapped",[31062]],[[64081,64081],"mapped",[31069]],[[64082,64082],"mapped",[31117]],[[64083,64083],"mapped",[31118]],[[64084,64084],"mapped",[31296]],[[64085,64085],"mapped",[31361]],[[64086,64086],"mapped",[31680]],[[64087,64087],"mapped",[32244]],[[64088,64088],"mapped",[32265]],[[64089,64089],"mapped",[32321]],[[64090,64090],"mapped",[32626]],[[64091,64091],"mapped",[32773]],[[64092,64092],"mapped",[33261]],[[64093,64094],"mapped",[33401]],[[64095,64095],"mapped",[33879]],[[64096,64096],"mapped",[35088]],[[64097,64097],"mapped",[35222]],[[64098,64098],"mapped",[35585]],[[64099,64099],"mapped",[35641]],[[64100,64100],"mapped",[36051]],[[64101,64101],"mapped",[36104]],[[64102,64102],"mapped",[36790]],[[64103,64103],"mapped",[36920]],[[64104,64104],"mapped",[38627]],[[64105,64105],"mapped",[38911]],[[64106,64106],"mapped",[38971]],[[64107,64107],"mapped",[24693]],[[64108,64108],"mapped",[148206]],[[64109,64109],"mapped",[33304]],[[64110,64111],"disallowed"],[[64112,64112],"mapped",[20006]],[[64113,64113],"mapped",[20917]],[[64114,64114],"mapped",[20840]],[[64115,64115],"mapped",[20352]],[[64116,64116],"mapped",[20805]],[[64117,64117],"mapped",[20864]],[[64118,64118],"mapped",[21191]],[[64119,64119],"mapped",[21242]],[[64120,64120],"mapped",[21917]],[[64121,64121],"mapped",[21845]],[[64122,64122],"mapped",[21913]],[[64123,64123],"mapped",[21986]],[[64124,64124],"mapped",[22618]],[[64125,64125],"mapped",[22707]],[[64126,64126],"mapped",[22852]],[[64127,64127],"mapped",[22868]],[[64128,64128],"mapped",[23138]],[[64129,64129],"mapped",[23336]],[[64130,64130],"mapped",[24274]],[[64131,64131],"mapped",[24281]],[[64132,64132],"mapped",[24425]],[[64133,64133],"mapped",[24493]],[[64134,64134],"mapped",[24792]],[[64135,64135],"mapped",[24910]],[[64136,64136],"mapped",[24840]],[[64137,64137],"mapped",[24974]],[[64138,64138],"mapped",[24928]],[[64139,64139],"mapped",[25074]],[[64140,64140],"mapped",[25140]],[[64141,64141],"mapped",[25540]],[[64142,64142],"mapped",[25628]],[[64143,64143],"mapped",[25682]],[[64144,64144],"mapped",[25942]],[[64145,64145],"mapped",[26228]],[[64146,64146],"mapped",[26391]],[[64147,64147],"mapped",[26395]],[[64148,64148],"mapped",[26454]],[[64149,64149],"mapped",[27513]],[[64150,64150],"mapped",[27578]],[[64151,64151],"mapped",[27969]],[[64152,64152],"mapped",[28379]],[[64153,64153],"mapped",[28363]],[[64154,64154],"mapped",[28450]],[[64155,64155],"mapped",[28702]],[[64156,64156],"mapped",[29038]],[[64157,64157],"mapped",[30631]],[[64158,64158],"mapped",[29237]],[[64159,64159],"mapped",[29359]],[[64160,64160],"mapped",[29482]],[[64161,64161],"mapped",[29809]],[[64162,64162],"mapped",[29958]],[[64163,64163],"mapped",[30011]],[[64164,64164],"mapped",[30237]],[[64165,64165],"mapped",[30239]],[[64166,64166],"mapped",[30410]],[[64167,64167],"mapped",[30427]],[[64168,64168],"mapped",[30452]],[[64169,64169],"mapped",[30538]],[[64170,64170],"mapped",[30528]],[[64171,64171],"mapped",[30924]],[[64172,64172],"mapped",[31409]],[[64173,64173],"mapped",[31680]],[[64174,64174],"mapped",[31867]],[[64175,64175],"mapped",[32091]],[[64176,64176],"mapped",[32244]],[[64177,64177],"mapped",[32574]],[[64178,64178],"mapped",[32773]],[[64179,64179],"mapped",[33618]],[[64180,64180],"mapped",[33775]],[[64181,64181],"mapped",[34681]],[[64182,64182],"mapped",[35137]],[[64183,64183],"mapped",[35206]],[[64184,64184],"mapped",[35222]],[[64185,64185],"mapped",[35519]],[[64186,64186],"mapped",[35576]],[[64187,64187],"mapped",[35531]],[[64188,64188],"mapped",[35585]],[[64189,64189],"mapped",[35582]],[[64190,64190],"mapped",[35565]],[[64191,64191],"mapped",[35641]],[[64192,64192],"mapped",[35722]],[[64193,64193],"mapped",[36104]],[[64194,64194],"mapped",[36664]],[[64195,64195],"mapped",[36978]],[[64196,64196],"mapped",[37273]],[[64197,64197],"mapped",[37494]],[[64198,64198],"mapped",[38524]],[[64199,64199],"mapped",[38627]],[[64200,64200],"mapped",[38742]],[[64201,64201],"mapped",[38875]],[[64202,64202],"mapped",[38911]],[[64203,64203],"mapped",[38923]],[[64204,64204],"mapped",[38971]],[[64205,64205],"mapped",[39698]],[[64206,64206],"mapped",[40860]],[[64207,64207],"mapped",[141386]],[[64208,64208],"mapped",[141380]],[[64209,64209],"mapped",[144341]],[[64210,64210],"mapped",[15261]],[[64211,64211],"mapped",[16408]],[[64212,64212],"mapped",[16441]],[[64213,64213],"mapped",[152137]],[[64214,64214],"mapped",[154832]],[[64215,64215],"mapped",[163539]],[[64216,64216],"mapped",[40771]],[[64217,64217],"mapped",[40846]],[[64218,64255],"disallowed"],[[64256,64256],"mapped",[102,102]],[[64257,64257],"mapped",[102,105]],[[64258,64258],"mapped",[102,108]],[[64259,64259],"mapped",[102,102,105]],[[64260,64260],"mapped",[102,102,108]],[[64261,64262],"mapped",[115,116]],[[64263,64274],"disallowed"],[[64275,64275],"mapped",[1396,1398]],[[64276,64276],"mapped",[1396,1381]],[[64277,64277],"mapped",[1396,1387]],[[64278,64278],"mapped",[1406,1398]],[[64279,64279],"mapped",[1396,1389]],[[64280,64284],"disallowed"],[[64285,64285],"mapped",[1497,1460]],[[64286,64286],"valid"],[[64287,64287],"mapped",[1522,1463]],[[64288,64288],"mapped",[1506]],[[64289,64289],"mapped",[1488]],[[64290,64290],"mapped",[1491]],[[64291,64291],"mapped",[1492]],[[64292,64292],"mapped",[1499]],[[64293,64293],"mapped",[1500]],[[64294,64294],"mapped",[1501]],[[64295,64295],"mapped",[1512]],[[64296,64296],"mapped",[1514]],[[64297,64297],"disallowed_STD3_mapped",[43]],[[64298,64298],"mapped",[1513,1473]],[[64299,64299],"mapped",[1513,1474]],[[64300,64300],"mapped",[1513,1468,1473]],[[64301,64301],"mapped",[1513,1468,1474]],[[64302,64302],"mapped",[1488,1463]],[[64303,64303],"mapped",[1488,1464]],[[64304,64304],"mapped",[1488,1468]],[[64305,64305],"mapped",[1489,1468]],[[64306,64306],"mapped",[1490,1468]],[[64307,64307],"mapped",[1491,1468]],[[64308,64308],"mapped",[1492,1468]],[[64309,64309],"mapped",[1493,1468]],[[64310,64310],"mapped",[1494,1468]],[[64311,64311],"disallowed"],[[64312,64312],"mapped",[1496,1468]],[[64313,64313],"mapped",[1497,1468]],[[64314,64314],"mapped",[1498,1468]],[[64315,64315],"mapped",[1499,1468]],[[64316,64316],"mapped",[1500,1468]],[[64317,64317],"disallowed"],[[64318,64318],"mapped",[1502,1468]],[[64319,64319],"disallowed"],[[64320,64320],"mapped",[1504,1468]],[[64321,64321],"mapped",[1505,1468]],[[64322,64322],"disallowed"],[[64323,64323],"mapped",[1507,1468]],[[64324,64324],"mapped",[1508,1468]],[[64325,64325],"disallowed"],[[64326,64326],"mapped",[1510,1468]],[[64327,64327],"mapped",[1511,1468]],[[64328,64328],"mapped",[1512,1468]],[[64329,64329],"mapped",[1513,1468]],[[64330,64330],"mapped",[1514,1468]],[[64331,64331],"mapped",[1493,1465]],[[64332,64332],"mapped",[1489,1471]],[[64333,64333],"mapped",[1499,1471]],[[64334,64334],"mapped",[1508,1471]],[[64335,64335],"mapped",[1488,1500]],[[64336,64337],"mapped",[1649]],[[64338,64341],"mapped",[1659]],[[64342,64345],"mapped",[1662]],[[64346,64349],"mapped",[1664]],[[64350,64353],"mapped",[1658]],[[64354,64357],"mapped",[1663]],[[64358,64361],"mapped",[1657]],[[64362,64365],"mapped",[1700]],[[64366,64369],"mapped",[1702]],[[64370,64373],"mapped",[1668]],[[64374,64377],"mapped",[1667]],[[64378,64381],"mapped",[1670]],[[64382,64385],"mapped",[1671]],[[64386,64387],"mapped",[1677]],[[64388,64389],"mapped",[1676]],[[64390,64391],"mapped",[1678]],[[64392,64393],"mapped",[1672]],[[64394,64395],"mapped",[1688]],[[64396,64397],"mapped",[1681]],[[64398,64401],"mapped",[1705]],[[64402,64405],"mapped",[1711]],[[64406,64409],"mapped",[1715]],[[64410,64413],"mapped",[1713]],[[64414,64415],"mapped",[1722]],[[64416,64419],"mapped",[1723]],[[64420,64421],"mapped",[1728]],[[64422,64425],"mapped",[1729]],[[64426,64429],"mapped",[1726]],[[64430,64431],"mapped",[1746]],[[64432,64433],"mapped",[1747]],[[64434,64449],"valid",[],"NV8"],[[64450,64466],"disallowed"],[[64467,64470],"mapped",[1709]],[[64471,64472],"mapped",[1735]],[[64473,64474],"mapped",[1734]],[[64475,64476],"mapped",[1736]],[[64477,64477],"mapped",[1735,1652]],[[64478,64479],"mapped",[1739]],[[64480,64481],"mapped",[1733]],[[64482,64483],"mapped",[1737]],[[64484,64487],"mapped",[1744]],[[64488,64489],"mapped",[1609]],[[64490,64491],"mapped",[1574,1575]],[[64492,64493],"mapped",[1574,1749]],[[64494,64495],"mapped",[1574,1608]],[[64496,64497],"mapped",[1574,1735]],[[64498,64499],"mapped",[1574,1734]],[[64500,64501],"mapped",[1574,1736]],[[64502,64504],"mapped",[1574,1744]],[[64505,64507],"mapped",[1574,1609]],[[64508,64511],"mapped",[1740]],[[64512,64512],"mapped",[1574,1580]],[[64513,64513],"mapped",[1574,1581]],[[64514,64514],"mapped",[1574,1605]],[[64515,64515],"mapped",[1574,1609]],[[64516,64516],"mapped",[1574,1610]],[[64517,64517],"mapped",[1576,1580]],[[64518,64518],"mapped",[1576,1581]],[[64519,64519],"mapped",[1576,1582]],[[64520,64520],"mapped",[1576,1605]],[[64521,64521],"mapped",[1576,1609]],[[64522,64522],"mapped",[1576,1610]],[[64523,64523],"mapped",[1578,1580]],[[64524,64524],"mapped",[1578,1581]],[[64525,64525],"mapped",[1578,1582]],[[64526,64526],"mapped",[1578,1605]],[[64527,64527],"mapped",[1578,1609]],[[64528,64528],"mapped",[1578,1610]],[[64529,64529],"mapped",[1579,1580]],[[64530,64530],"mapped",[1579,1605]],[[64531,64531],"mapped",[1579,1609]],[[64532,64532],"mapped",[1579,1610]],[[64533,64533],"mapped",[1580,1581]],[[64534,64534],"mapped",[1580,1605]],[[64535,64535],"mapped",[1581,1580]],[[64536,64536],"mapped",[1581,1605]],[[64537,64537],"mapped",[1582,1580]],[[64538,64538],"mapped",[1582,1581]],[[64539,64539],"mapped",[1582,1605]],[[64540,64540],"mapped",[1587,1580]],[[64541,64541],"mapped",[1587,1581]],[[64542,64542],"mapped",[1587,1582]],[[64543,64543],"mapped",[1587,1605]],[[64544,64544],"mapped",[1589,1581]],[[64545,64545],"mapped",[1589,1605]],[[64546,64546],"mapped",[1590,1580]],[[64547,64547],"mapped",[1590,1581]],[[64548,64548],"mapped",[1590,1582]],[[64549,64549],"mapped",[1590,1605]],[[64550,64550],"mapped",[1591,1581]],[[64551,64551],"mapped",[1591,1605]],[[64552,64552],"mapped",[1592,1605]],[[64553,64553],"mapped",[1593,1580]],[[64554,64554],"mapped",[1593,1605]],[[64555,64555],"mapped",[1594,1580]],[[64556,64556],"mapped",[1594,1605]],[[64557,64557],"mapped",[1601,1580]],[[64558,64558],"mapped",[1601,1581]],[[64559,64559],"mapped",[1601,1582]],[[64560,64560],"mapped",[1601,1605]],[[64561,64561],"mapped",[1601,1609]],[[64562,64562],"mapped",[1601,1610]],[[64563,64563],"mapped",[1602,1581]],[[64564,64564],"mapped",[1602,1605]],[[64565,64565],"mapped",[1602,1609]],[[64566,64566],"mapped",[1602,1610]],[[64567,64567],"mapped",[1603,1575]],[[64568,64568],"mapped",[1603,1580]],[[64569,64569],"mapped",[1603,1581]],[[64570,64570],"mapped",[1603,1582]],[[64571,64571],"mapped",[1603,1604]],[[64572,64572],"mapped",[1603,1605]],[[64573,64573],"mapped",[1603,1609]],[[64574,64574],"mapped",[1603,1610]],[[64575,64575],"mapped",[1604,1580]],[[64576,64576],"mapped",[1604,1581]],[[64577,64577],"mapped",[1604,1582]],[[64578,64578],"mapped",[1604,1605]],[[64579,64579],"mapped",[1604,1609]],[[64580,64580],"mapped",[1604,1610]],[[64581,64581],"mapped",[1605,1580]],[[64582,64582],"mapped",[1605,1581]],[[64583,64583],"mapped",[1605,1582]],[[64584,64584],"mapped",[1605,1605]],[[64585,64585],"mapped",[1605,1609]],[[64586,64586],"mapped",[1605,1610]],[[64587,64587],"mapped",[1606,1580]],[[64588,64588],"mapped",[1606,1581]],[[64589,64589],"mapped",[1606,1582]],[[64590,64590],"mapped",[1606,1605]],[[64591,64591],"mapped",[1606,1609]],[[64592,64592],"mapped",[1606,1610]],[[64593,64593],"mapped",[1607,1580]],[[64594,64594],"mapped",[1607,1605]],[[64595,64595],"mapped",[1607,1609]],[[64596,64596],"mapped",[1607,1610]],[[64597,64597],"mapped",[1610,1580]],[[64598,64598],"mapped",[1610,1581]],[[64599,64599],"mapped",[1610,1582]],[[64600,64600],"mapped",[1610,1605]],[[64601,64601],"mapped",[1610,1609]],[[64602,64602],"mapped",[1610,1610]],[[64603,64603],"mapped",[1584,1648]],[[64604,64604],"mapped",[1585,1648]],[[64605,64605],"mapped",[1609,1648]],[[64606,64606],"disallowed_STD3_mapped",[32,1612,1617]],[[64607,64607],"disallowed_STD3_mapped",[32,1613,1617]],[[64608,64608],"disallowed_STD3_mapped",[32,1614,1617]],[[64609,64609],"disallowed_STD3_mapped",[32,1615,1617]],[[64610,64610],"disallowed_STD3_mapped",[32,1616,1617]],[[64611,64611],"disallowed_STD3_mapped",[32,1617,1648]],[[64612,64612],"mapped",[1574,1585]],[[64613,64613],"mapped",[1574,1586]],[[64614,64614],"mapped",[1574,1605]],[[64615,64615],"mapped",[1574,1606]],[[64616,64616],"mapped",[1574,1609]],[[64617,64617],"mapped",[1574,1610]],[[64618,64618],"mapped",[1576,1585]],[[64619,64619],"mapped",[1576,1586]],[[64620,64620],"mapped",[1576,1605]],[[64621,64621],"mapped",[1576,1606]],[[64622,64622],"mapped",[1576,1609]],[[64623,64623],"mapped",[1576,1610]],[[64624,64624],"mapped",[1578,1585]],[[64625,64625],"mapped",[1578,1586]],[[64626,64626],"mapped",[1578,1605]],[[64627,64627],"mapped",[1578,1606]],[[64628,64628],"mapped",[1578,1609]],[[64629,64629],"mapped",[1578,1610]],[[64630,64630],"mapped",[1579,1585]],[[64631,64631],"mapped",[1579,1586]],[[64632,64632],"mapped",[1579,1605]],[[64633,64633],"mapped",[1579,1606]],[[64634,64634],"mapped",[1579,1609]],[[64635,64635],"mapped",[1579,1610]],[[64636,64636],"mapped",[1601,1609]],[[64637,64637],"mapped",[1601,1610]],[[64638,64638],"mapped",[1602,1609]],[[64639,64639],"mapped",[1602,1610]],[[64640,64640],"mapped",[1603,1575]],[[64641,64641],"mapped",[1603,1604]],[[64642,64642],"mapped",[1603,1605]],[[64643,64643],"mapped",[1603,1609]],[[64644,64644],"mapped",[1603,1610]],[[64645,64645],"mapped",[1604,1605]],[[64646,64646],"mapped",[1604,1609]],[[64647,64647],"mapped",[1604,1610]],[[64648,64648],"mapped",[1605,1575]],[[64649,64649],"mapped",[1605,1605]],[[64650,64650],"mapped",[1606,1585]],[[64651,64651],"mapped",[1606,1586]],[[64652,64652],"mapped",[1606,1605]],[[64653,64653],"mapped",[1606,1606]],[[64654,64654],"mapped",[1606,1609]],[[64655,64655],"mapped",[1606,1610]],[[64656,64656],"mapped",[1609,1648]],[[64657,64657],"mapped",[1610,1585]],[[64658,64658],"mapped",[1610,1586]],[[64659,64659],"mapped",[1610,1605]],[[64660,64660],"mapped",[1610,1606]],[[64661,64661],"mapped",[1610,1609]],[[64662,64662],"mapped",[1610,1610]],[[64663,64663],"mapped",[1574,1580]],[[64664,64664],"mapped",[1574,1581]],[[64665,64665],"mapped",[1574,1582]],[[64666,64666],"mapped",[1574,1605]],[[64667,64667],"mapped",[1574,1607]],[[64668,64668],"mapped",[1576,1580]],[[64669,64669],"mapped",[1576,1581]],[[64670,64670],"mapped",[1576,1582]],[[64671,64671],"mapped",[1576,1605]],[[64672,64672],"mapped",[1576,1607]],[[64673,64673],"mapped",[1578,1580]],[[64674,64674],"mapped",[1578,1581]],[[64675,64675],"mapped",[1578,1582]],[[64676,64676],"mapped",[1578,1605]],[[64677,64677],"mapped",[1578,1607]],[[64678,64678],"mapped",[1579,1605]],[[64679,64679],"mapped",[1580,1581]],[[64680,64680],"mapped",[1580,1605]],[[64681,64681],"mapped",[1581,1580]],[[64682,64682],"mapped",[1581,1605]],[[64683,64683],"mapped",[1582,1580]],[[64684,64684],"mapped",[1582,1605]],[[64685,64685],"mapped",[1587,1580]],[[64686,64686],"mapped",[1587,1581]],[[64687,64687],"mapped",[1587,1582]],[[64688,64688],"mapped",[1587,1605]],[[64689,64689],"mapped",[1589,1581]],[[64690,64690],"mapped",[1589,1582]],[[64691,64691],"mapped",[1589,1605]],[[64692,64692],"mapped",[1590,1580]],[[64693,64693],"mapped",[1590,1581]],[[64694,64694],"mapped",[1590,1582]],[[64695,64695],"mapped",[1590,1605]],[[64696,64696],"mapped",[1591,1581]],[[64697,64697],"mapped",[1592,1605]],[[64698,64698],"mapped",[1593,1580]],[[64699,64699],"mapped",[1593,1605]],[[64700,64700],"mapped",[1594,1580]],[[64701,64701],"mapped",[1594,1605]],[[64702,64702],"mapped",[1601,1580]],[[64703,64703],"mapped",[1601,1581]],[[64704,64704],"mapped",[1601,1582]],[[64705,64705],"mapped",[1601,1605]],[[64706,64706],"mapped",[1602,1581]],[[64707,64707],"mapped",[1602,1605]],[[64708,64708],"mapped",[1603,1580]],[[64709,64709],"mapped",[1603,1581]],[[64710,64710],"mapped",[1603,1582]],[[64711,64711],"mapped",[1603,1604]],[[64712,64712],"mapped",[1603,1605]],[[64713,64713],"mapped",[1604,1580]],[[64714,64714],"mapped",[1604,1581]],[[64715,64715],"mapped",[1604,1582]],[[64716,64716],"mapped",[1604,1605]],[[64717,64717],"mapped",[1604,1607]],[[64718,64718],"mapped",[1605,1580]],[[64719,64719],"mapped",[1605,1581]],[[64720,64720],"mapped",[1605,1582]],[[64721,64721],"mapped",[1605,1605]],[[64722,64722],"mapped",[1606,1580]],[[64723,64723],"mapped",[1606,1581]],[[64724,64724],"mapped",[1606,1582]],[[64725,64725],"mapped",[1606,1605]],[[64726,64726],"mapped",[1606,1607]],[[64727,64727],"mapped",[1607,1580]],[[64728,64728],"mapped",[1607,1605]],[[64729,64729],"mapped",[1607,1648]],[[64730,64730],"mapped",[1610,1580]],[[64731,64731],"mapped",[1610,1581]],[[64732,64732],"mapped",[1610,1582]],[[64733,64733],"mapped",[1610,1605]],[[64734,64734],"mapped",[1610,1607]],[[64735,64735],"mapped",[1574,1605]],[[64736,64736],"mapped",[1574,1607]],[[64737,64737],"mapped",[1576,1605]],[[64738,64738],"mapped",[1576,1607]],[[64739,64739],"mapped",[1578,1605]],[[64740,64740],"mapped",[1578,1607]],[[64741,64741],"mapped",[1579,1605]],[[64742,64742],"mapped",[1579,1607]],[[64743,64743],"mapped",[1587,1605]],[[64744,64744],"mapped",[1587,1607]],[[64745,64745],"mapped",[1588,1605]],[[64746,64746],"mapped",[1588,1607]],[[64747,64747],"mapped",[1603,1604]],[[64748,64748],"mapped",[1603,1605]],[[64749,64749],"mapped",[1604,1605]],[[64750,64750],"mapped",[1606,1605]],[[64751,64751],"mapped",[1606,1607]],[[64752,64752],"mapped",[1610,1605]],[[64753,64753],"mapped",[1610,1607]],[[64754,64754],"mapped",[1600,1614,1617]],[[64755,64755],"mapped",[1600,1615,1617]],[[64756,64756],"mapped",[1600,1616,1617]],[[64757,64757],"mapped",[1591,1609]],[[64758,64758],"mapped",[1591,1610]],[[64759,64759],"mapped",[1593,1609]],[[64760,64760],"mapped",[1593,1610]],[[64761,64761],"mapped",[1594,1609]],[[64762,64762],"mapped",[1594,1610]],[[64763,64763],"mapped",[1587,1609]],[[64764,64764],"mapped",[1587,1610]],[[64765,64765],"mapped",[1588,1609]],[[64766,64766],"mapped",[1588,1610]],[[64767,64767],"mapped",[1581,1609]],[[64768,64768],"mapped",[1581,1610]],[[64769,64769],"mapped",[1580,1609]],[[64770,64770],"mapped",[1580,1610]],[[64771,64771],"mapped",[1582,1609]],[[64772,64772],"mapped",[1582,1610]],[[64773,64773],"mapped",[1589,1609]],[[64774,64774],"mapped",[1589,1610]],[[64775,64775],"mapped",[1590,1609]],[[64776,64776],"mapped",[1590,1610]],[[64777,64777],"mapped",[1588,1580]],[[64778,64778],"mapped",[1588,1581]],[[64779,64779],"mapped",[1588,1582]],[[64780,64780],"mapped",[1588,1605]],[[64781,64781],"mapped",[1588,1585]],[[64782,64782],"mapped",[1587,1585]],[[64783,64783],"mapped",[1589,1585]],[[64784,64784],"mapped",[1590,1585]],[[64785,64785],"mapped",[1591,1609]],[[64786,64786],"mapped",[1591,1610]],[[64787,64787],"mapped",[1593,1609]],[[64788,64788],"mapped",[1593,1610]],[[64789,64789],"mapped",[1594,1609]],[[64790,64790],"mapped",[1594,1610]],[[64791,64791],"mapped",[1587,1609]],[[64792,64792],"mapped",[1587,1610]],[[64793,64793],"mapped",[1588,1609]],[[64794,64794],"mapped",[1588,1610]],[[64795,64795],"mapped",[1581,1609]],[[64796,64796],"mapped",[1581,1610]],[[64797,64797],"mapped",[1580,1609]],[[64798,64798],"mapped",[1580,1610]],[[64799,64799],"mapped",[1582,1609]],[[64800,64800],"mapped",[1582,1610]],[[64801,64801],"mapped",[1589,1609]],[[64802,64802],"mapped",[1589,1610]],[[64803,64803],"mapped",[1590,1609]],[[64804,64804],"mapped",[1590,1610]],[[64805,64805],"mapped",[1588,1580]],[[64806,64806],"mapped",[1588,1581]],[[64807,64807],"mapped",[1588,1582]],[[64808,64808],"mapped",[1588,1605]],[[64809,64809],"mapped",[1588,1585]],[[64810,64810],"mapped",[1587,1585]],[[64811,64811],"mapped",[1589,1585]],[[64812,64812],"mapped",[1590,1585]],[[64813,64813],"mapped",[1588,1580]],[[64814,64814],"mapped",[1588,1581]],[[64815,64815],"mapped",[1588,1582]],[[64816,64816],"mapped",[1588,1605]],[[64817,64817],"mapped",[1587,1607]],[[64818,64818],"mapped",[1588,1607]],[[64819,64819],"mapped",[1591,1605]],[[64820,64820],"mapped",[1587,1580]],[[64821,64821],"mapped",[1587,1581]],[[64822,64822],"mapped",[1587,1582]],[[64823,64823],"mapped",[1588,1580]],[[64824,64824],"mapped",[1588,1581]],[[64825,64825],"mapped",[1588,1582]],[[64826,64826],"mapped",[1591,1605]],[[64827,64827],"mapped",[1592,1605]],[[64828,64829],"mapped",[1575,1611]],[[64830,64831],"valid",[],"NV8"],[[64832,64847],"disallowed"],[[64848,64848],"mapped",[1578,1580,1605]],[[64849,64850],"mapped",[1578,1581,1580]],[[64851,64851],"mapped",[1578,1581,1605]],[[64852,64852],"mapped",[1578,1582,1605]],[[64853,64853],"mapped",[1578,1605,1580]],[[64854,64854],"mapped",[1578,1605,1581]],[[64855,64855],"mapped",[1578,1605,1582]],[[64856,64857],"mapped",[1580,1605,1581]],[[64858,64858],"mapped",[1581,1605,1610]],[[64859,64859],"mapped",[1581,1605,1609]],[[64860,64860],"mapped",[1587,1581,1580]],[[64861,64861],"mapped",[1587,1580,1581]],[[64862,64862],"mapped",[1587,1580,1609]],[[64863,64864],"mapped",[1587,1605,1581]],[[64865,64865],"mapped",[1587,1605,1580]],[[64866,64867],"mapped",[1587,1605,1605]],[[64868,64869],"mapped",[1589,1581,1581]],[[64870,64870],"mapped",[1589,1605,1605]],[[64871,64872],"mapped",[1588,1581,1605]],[[64873,64873],"mapped",[1588,1580,1610]],[[64874,64875],"mapped",[1588,1605,1582]],[[64876,64877],"mapped",[1588,1605,1605]],[[64878,64878],"mapped",[1590,1581,1609]],[[64879,64880],"mapped",[1590,1582,1605]],[[64881,64882],"mapped",[1591,1605,1581]],[[64883,64883],"mapped",[1591,1605,1605]],[[64884,64884],"mapped",[1591,1605,1610]],[[64885,64885],"mapped",[1593,1580,1605]],[[64886,64887],"mapped",[1593,1605,1605]],[[64888,64888],"mapped",[1593,1605,1609]],[[64889,64889],"mapped",[1594,1605,1605]],[[64890,64890],"mapped",[1594,1605,1610]],[[64891,64891],"mapped",[1594,1605,1609]],[[64892,64893],"mapped",[1601,1582,1605]],[[64894,64894],"mapped",[1602,1605,1581]],[[64895,64895],"mapped",[1602,1605,1605]],[[64896,64896],"mapped",[1604,1581,1605]],[[64897,64897],"mapped",[1604,1581,1610]],[[64898,64898],"mapped",[1604,1581,1609]],[[64899,64900],"mapped",[1604,1580,1580]],[[64901,64902],"mapped",[1604,1582,1605]],[[64903,64904],"mapped",[1604,1605,1581]],[[64905,64905],"mapped",[1605,1581,1580]],[[64906,64906],"mapped",[1605,1581,1605]],[[64907,64907],"mapped",[1605,1581,1610]],[[64908,64908],"mapped",[1605,1580,1581]],[[64909,64909],"mapped",[1605,1580,1605]],[[64910,64910],"mapped",[1605,1582,1580]],[[64911,64911],"mapped",[1605,1582,1605]],[[64912,64913],"disallowed"],[[64914,64914],"mapped",[1605,1580,1582]],[[64915,64915],"mapped",[1607,1605,1580]],[[64916,64916],"mapped",[1607,1605,1605]],[[64917,64917],"mapped",[1606,1581,1605]],[[64918,64918],"mapped",[1606,1581,1609]],[[64919,64920],"mapped",[1606,1580,1605]],[[64921,64921],"mapped",[1606,1580,1609]],[[64922,64922],"mapped",[1606,1605,1610]],[[64923,64923],"mapped",[1606,1605,1609]],[[64924,64925],"mapped",[1610,1605,1605]],[[64926,64926],"mapped",[1576,1582,1610]],[[64927,64927],"mapped",[1578,1580,1610]],[[64928,64928],"mapped",[1578,1580,1609]],[[64929,64929],"mapped",[1578,1582,1610]],[[64930,64930],"mapped",[1578,1582,1609]],[[64931,64931],"mapped",[1578,1605,1610]],[[64932,64932],"mapped",[1578,1605,1609]],[[64933,64933],"mapped",[1580,1605,1610]],[[64934,64934],"mapped",[1580,1581,1609]],[[64935,64935],"mapped",[1580,1605,1609]],[[64936,64936],"mapped",[1587,1582,1609]],[[64937,64937],"mapped",[1589,1581,1610]],[[64938,64938],"mapped",[1588,1581,1610]],[[64939,64939],"mapped",[1590,1581,1610]],[[64940,64940],"mapped",[1604,1580,1610]],[[64941,64941],"mapped",[1604,1605,1610]],[[64942,64942],"mapped",[1610,1581,1610]],[[64943,64943],"mapped",[1610,1580,1610]],[[64944,64944],"mapped",[1610,1605,1610]],[[64945,64945],"mapped",[1605,1605,1610]],[[64946,64946],"mapped",[1602,1605,1610]],[[64947,64947],"mapped",[1606,1581,1610]],[[64948,64948],"mapped",[1602,1605,1581]],[[64949,64949],"mapped",[1604,1581,1605]],[[64950,64950],"mapped",[1593,1605,1610]],[[64951,64951],"mapped",[1603,1605,1610]],[[64952,64952],"mapped",[1606,1580,1581]],[[64953,64953],"mapped",[1605,1582,1610]],[[64954,64954],"mapped",[1604,1580,1605]],[[64955,64955],"mapped",[1603,1605,1605]],[[64956,64956],"mapped",[1604,1580,1605]],[[64957,64957],"mapped",[1606,1580,1581]],[[64958,64958],"mapped",[1580,1581,1610]],[[64959,64959],"mapped",[1581,1580,1610]],[[64960,64960],"mapped",[1605,1580,1610]],[[64961,64961],"mapped",[1601,1605,1610]],[[64962,64962],"mapped",[1576,1581,1610]],[[64963,64963],"mapped",[1603,1605,1605]],[[64964,64964],"mapped",[1593,1580,1605]],[[64965,64965],"mapped",[1589,1605,1605]],[[64966,64966],"mapped",[1587,1582,1610]],[[64967,64967],"mapped",[1606,1580,1610]],[[64968,64975],"disallowed"],[[64976,65007],"disallowed"],[[65008,65008],"mapped",[1589,1604,1746]],[[65009,65009],"mapped",[1602,1604,1746]],[[65010,65010],"mapped",[1575,1604,1604,1607]],[[65011,65011],"mapped",[1575,1603,1576,1585]],[[65012,65012],"mapped",[1605,1581,1605,1583]],[[65013,65013],"mapped",[1589,1604,1593,1605]],[[65014,65014],"mapped",[1585,1587,1608,1604]],[[65015,65015],"mapped",[1593,1604,1610,1607]],[[65016,65016],"mapped",[1608,1587,1604,1605]],[[65017,65017],"mapped",[1589,1604,1609]],[[65018,65018],"disallowed_STD3_mapped",[1589,1604,1609,32,1575,1604,1604,1607,32,1593,1604,1610,1607,32,1608,1587,1604,1605]],[[65019,65019],"disallowed_STD3_mapped",[1580,1604,32,1580,1604,1575,1604,1607]],[[65020,65020],"mapped",[1585,1740,1575,1604]],[[65021,65021],"valid",[],"NV8"],[[65022,65023],"disallowed"],[[65024,65039],"ignored"],[[65040,65040],"disallowed_STD3_mapped",[44]],[[65041,65041],"mapped",[12289]],[[65042,65042],"disallowed"],[[65043,65043],"disallowed_STD3_mapped",[58]],[[65044,65044],"disallowed_STD3_mapped",[59]],[[65045,65045],"disallowed_STD3_mapped",[33]],[[65046,65046],"disallowed_STD3_mapped",[63]],[[65047,65047],"mapped",[12310]],[[65048,65048],"mapped",[12311]],[[65049,65049],"disallowed"],[[65050,65055],"disallowed"],[[65056,65059],"valid"],[[65060,65062],"valid"],[[65063,65069],"valid"],[[65070,65071],"valid"],[[65072,65072],"disallowed"],[[65073,65073],"mapped",[8212]],[[65074,65074],"mapped",[8211]],[[65075,65076],"disallowed_STD3_mapped",[95]],[[65077,65077],"disallowed_STD3_mapped",[40]],[[65078,65078],"disallowed_STD3_mapped",[41]],[[65079,65079],"disallowed_STD3_mapped",[123]],[[65080,65080],"disallowed_STD3_mapped",[125]],[[65081,65081],"mapped",[12308]],[[65082,65082],"mapped",[12309]],[[65083,65083],"mapped",[12304]],[[65084,65084],"mapped",[12305]],[[65085,65085],"mapped",[12298]],[[65086,65086],"mapped",[12299]],[[65087,65087],"mapped",[12296]],[[65088,65088],"mapped",[12297]],[[65089,65089],"mapped",[12300]],[[65090,65090],"mapped",[12301]],[[65091,65091],"mapped",[12302]],[[65092,65092],"mapped",[12303]],[[65093,65094],"valid",[],"NV8"],[[65095,65095],"disallowed_STD3_mapped",[91]],[[65096,65096],"disallowed_STD3_mapped",[93]],[[65097,65100],"disallowed_STD3_mapped",[32,773]],[[65101,65103],"disallowed_STD3_mapped",[95]],[[65104,65104],"disallowed_STD3_mapped",[44]],[[65105,65105],"mapped",[12289]],[[65106,65106],"disallowed"],[[65107,65107],"disallowed"],[[65108,65108],"disallowed_STD3_mapped",[59]],[[65109,65109],"disallowed_STD3_mapped",[58]],[[65110,65110],"disallowed_STD3_mapped",[63]],[[65111,65111],"disallowed_STD3_mapped",[33]],[[65112,65112],"mapped",[8212]],[[65113,65113],"disallowed_STD3_mapped",[40]],[[65114,65114],"disallowed_STD3_mapped",[41]],[[65115,65115],"disallowed_STD3_mapped",[123]],[[65116,65116],"disallowed_STD3_mapped",[125]],[[65117,65117],"mapped",[12308]],[[65118,65118],"mapped",[12309]],[[65119,65119],"disallowed_STD3_mapped",[35]],[[65120,65120],"disallowed_STD3_mapped",[38]],[[65121,65121],"disallowed_STD3_mapped",[42]],[[65122,65122],"disallowed_STD3_mapped",[43]],[[65123,65123],"mapped",[45]],[[65124,65124],"disallowed_STD3_mapped",[60]],[[65125,65125],"disallowed_STD3_mapped",[62]],[[65126,65126],"disallowed_STD3_mapped",[61]],[[65127,65127],"disallowed"],[[65128,65128],"disallowed_STD3_mapped",[92]],[[65129,65129],"disallowed_STD3_mapped",[36]],[[65130,65130],"disallowed_STD3_mapped",[37]],[[65131,65131],"disallowed_STD3_mapped",[64]],[[65132,65135],"disallowed"],[[65136,65136],"disallowed_STD3_mapped",[32,1611]],[[65137,65137],"mapped",[1600,1611]],[[65138,65138],"disallowed_STD3_mapped",[32,1612]],[[65139,65139],"valid"],[[65140,65140],"disallowed_STD3_mapped",[32,1613]],[[65141,65141],"disallowed"],[[65142,65142],"disallowed_STD3_mapped",[32,1614]],[[65143,65143],"mapped",[1600,1614]],[[65144,65144],"disallowed_STD3_mapped",[32,1615]],[[65145,65145],"mapped",[1600,1615]],[[65146,65146],"disallowed_STD3_mapped",[32,1616]],[[65147,65147],"mapped",[1600,1616]],[[65148,65148],"disallowed_STD3_mapped",[32,1617]],[[65149,65149],"mapped",[1600,1617]],[[65150,65150],"disallowed_STD3_mapped",[32,1618]],[[65151,65151],"mapped",[1600,1618]],[[65152,65152],"mapped",[1569]],[[65153,65154],"mapped",[1570]],[[65155,65156],"mapped",[1571]],[[65157,65158],"mapped",[1572]],[[65159,65160],"mapped",[1573]],[[65161,65164],"mapped",[1574]],[[65165,65166],"mapped",[1575]],[[65167,65170],"mapped",[1576]],[[65171,65172],"mapped",[1577]],[[65173,65176],"mapped",[1578]],[[65177,65180],"mapped",[1579]],[[65181,65184],"mapped",[1580]],[[65185,65188],"mapped",[1581]],[[65189,65192],"mapped",[1582]],[[65193,65194],"mapped",[1583]],[[65195,65196],"mapped",[1584]],[[65197,65198],"mapped",[1585]],[[65199,65200],"mapped",[1586]],[[65201,65204],"mapped",[1587]],[[65205,65208],"mapped",[1588]],[[65209,65212],"mapped",[1589]],[[65213,65216],"mapped",[1590]],[[65217,65220],"mapped",[1591]],[[65221,65224],"mapped",[1592]],[[65225,65228],"mapped",[1593]],[[65229,65232],"mapped",[1594]],[[65233,65236],"mapped",[1601]],[[65237,65240],"mapped",[1602]],[[65241,65244],"mapped",[1603]],[[65245,65248],"mapped",[1604]],[[65249,65252],"mapped",[1605]],[[65253,65256],"mapped",[1606]],[[65257,65260],"mapped",[1607]],[[65261,65262],"mapped",[1608]],[[65263,65264],"mapped",[1609]],[[65265,65268],"mapped",[1610]],[[65269,65270],"mapped",[1604,1570]],[[65271,65272],"mapped",[1604,1571]],[[65273,65274],"mapped",[1604,1573]],[[65275,65276],"mapped",[1604,1575]],[[65277,65278],"disallowed"],[[65279,65279],"ignored"],[[65280,65280],"disallowed"],[[65281,65281],"disallowed_STD3_mapped",[33]],[[65282,65282],"disallowed_STD3_mapped",[34]],[[65283,65283],"disallowed_STD3_mapped",[35]],[[65284,65284],"disallowed_STD3_mapped",[36]],[[65285,65285],"disallowed_STD3_mapped",[37]],[[65286,65286],"disallowed_STD3_mapped",[38]],[[65287,65287],"disallowed_STD3_mapped",[39]],[[65288,65288],"disallowed_STD3_mapped",[40]],[[65289,65289],"disallowed_STD3_mapped",[41]],[[65290,65290],"disallowed_STD3_mapped",[42]],[[65291,65291],"disallowed_STD3_mapped",[43]],[[65292,65292],"disallowed_STD3_mapped",[44]],[[65293,65293],"mapped",[45]],[[65294,65294],"mapped",[46]],[[65295,65295],"disallowed_STD3_mapped",[47]],[[65296,65296],"mapped",[48]],[[65297,65297],"mapped",[49]],[[65298,65298],"mapped",[50]],[[65299,65299],"mapped",[51]],[[65300,65300],"mapped",[52]],[[65301,65301],"mapped",[53]],[[65302,65302],"mapped",[54]],[[65303,65303],"mapped",[55]],[[65304,65304],"mapped",[56]],[[65305,65305],"mapped",[57]],[[65306,65306],"disallowed_STD3_mapped",[58]],[[65307,65307],"disallowed_STD3_mapped",[59]],[[65308,65308],"disallowed_STD3_mapped",[60]],[[65309,65309],"disallowed_STD3_mapped",[61]],[[65310,65310],"disallowed_STD3_mapped",[62]],[[65311,65311],"disallowed_STD3_mapped",[63]],[[65312,65312],"disallowed_STD3_mapped",[64]],[[65313,65313],"mapped",[97]],[[65314,65314],"mapped",[98]],[[65315,65315],"mapped",[99]],[[65316,65316],"mapped",[100]],[[65317,65317],"mapped",[101]],[[65318,65318],"mapped",[102]],[[65319,65319],"mapped",[103]],[[65320,65320],"mapped",[104]],[[65321,65321],"mapped",[105]],[[65322,65322],"mapped",[106]],[[65323,65323],"mapped",[107]],[[65324,65324],"mapped",[108]],[[65325,65325],"mapped",[109]],[[65326,65326],"mapped",[110]],[[65327,65327],"mapped",[111]],[[65328,65328],"mapped",[112]],[[65329,65329],"mapped",[113]],[[65330,65330],"mapped",[114]],[[65331,65331],"mapped",[115]],[[65332,65332],"mapped",[116]],[[65333,65333],"mapped",[117]],[[65334,65334],"mapped",[118]],[[65335,65335],"mapped",[119]],[[65336,65336],"mapped",[120]],[[65337,65337],"mapped",[121]],[[65338,65338],"mapped",[122]],[[65339,65339],"disallowed_STD3_mapped",[91]],[[65340,65340],"disallowed_STD3_mapped",[92]],[[65341,65341],"disallowed_STD3_mapped",[93]],[[65342,65342],"disallowed_STD3_mapped",[94]],[[65343,65343],"disallowed_STD3_mapped",[95]],[[65344,65344],"disallowed_STD3_mapped",[96]],[[65345,65345],"mapped",[97]],[[65346,65346],"mapped",[98]],[[65347,65347],"mapped",[99]],[[65348,65348],"mapped",[100]],[[65349,65349],"mapped",[101]],[[65350,65350],"mapped",[102]],[[65351,65351],"mapped",[103]],[[65352,65352],"mapped",[104]],[[65353,65353],"mapped",[105]],[[65354,65354],"mapped",[106]],[[65355,65355],"mapped",[107]],[[65356,65356],"mapped",[108]],[[65357,65357],"mapped",[109]],[[65358,65358],"mapped",[110]],[[65359,65359],"mapped",[111]],[[65360,65360],"mapped",[112]],[[65361,65361],"mapped",[113]],[[65362,65362],"mapped",[114]],[[65363,65363],"mapped",[115]],[[65364,65364],"mapped",[116]],[[65365,65365],"mapped",[117]],[[65366,65366],"mapped",[118]],[[65367,65367],"mapped",[119]],[[65368,65368],"mapped",[120]],[[65369,65369],"mapped",[121]],[[65370,65370],"mapped",[122]],[[65371,65371],"disallowed_STD3_mapped",[123]],[[65372,65372],"disallowed_STD3_mapped",[124]],[[65373,65373],"disallowed_STD3_mapped",[125]],[[65374,65374],"disallowed_STD3_mapped",[126]],[[65375,65375],"mapped",[10629]],[[65376,65376],"mapped",[10630]],[[65377,65377],"mapped",[46]],[[65378,65378],"mapped",[12300]],[[65379,65379],"mapped",[12301]],[[65380,65380],"mapped",[12289]],[[65381,65381],"mapped",[12539]],[[65382,65382],"mapped",[12530]],[[65383,65383],"mapped",[12449]],[[65384,65384],"mapped",[12451]],[[65385,65385],"mapped",[12453]],[[65386,65386],"mapped",[12455]],[[65387,65387],"mapped",[12457]],[[65388,65388],"mapped",[12515]],[[65389,65389],"mapped",[12517]],[[65390,65390],"mapped",[12519]],[[65391,65391],"mapped",[12483]],[[65392,65392],"mapped",[12540]],[[65393,65393],"mapped",[12450]],[[65394,65394],"mapped",[12452]],[[65395,65395],"mapped",[12454]],[[65396,65396],"mapped",[12456]],[[65397,65397],"mapped",[12458]],[[65398,65398],"mapped",[12459]],[[65399,65399],"mapped",[12461]],[[65400,65400],"mapped",[12463]],[[65401,65401],"mapped",[12465]],[[65402,65402],"mapped",[12467]],[[65403,65403],"mapped",[12469]],[[65404,65404],"mapped",[12471]],[[65405,65405],"mapped",[12473]],[[65406,65406],"mapped",[12475]],[[65407,65407],"mapped",[12477]],[[65408,65408],"mapped",[12479]],[[65409,65409],"mapped",[12481]],[[65410,65410],"mapped",[12484]],[[65411,65411],"mapped",[12486]],[[65412,65412],"mapped",[12488]],[[65413,65413],"mapped",[12490]],[[65414,65414],"mapped",[12491]],[[65415,65415],"mapped",[12492]],[[65416,65416],"mapped",[12493]],[[65417,65417],"mapped",[12494]],[[65418,65418],"mapped",[12495]],[[65419,65419],"mapped",[12498]],[[65420,65420],"mapped",[12501]],[[65421,65421],"mapped",[12504]],[[65422,65422],"mapped",[12507]],[[65423,65423],"mapped",[12510]],[[65424,65424],"mapped",[12511]],[[65425,65425],"mapped",[12512]],[[65426,65426],"mapped",[12513]],[[65427,65427],"mapped",[12514]],[[65428,65428],"mapped",[12516]],[[65429,65429],"mapped",[12518]],[[65430,65430],"mapped",[12520]],[[65431,65431],"mapped",[12521]],[[65432,65432],"mapped",[12522]],[[65433,65433],"mapped",[12523]],[[65434,65434],"mapped",[12524]],[[65435,65435],"mapped",[12525]],[[65436,65436],"mapped",[12527]],[[65437,65437],"mapped",[12531]],[[65438,65438],"mapped",[12441]],[[65439,65439],"mapped",[12442]],[[65440,65440],"disallowed"],[[65441,65441],"mapped",[4352]],[[65442,65442],"mapped",[4353]],[[65443,65443],"mapped",[4522]],[[65444,65444],"mapped",[4354]],[[65445,65445],"mapped",[4524]],[[65446,65446],"mapped",[4525]],[[65447,65447],"mapped",[4355]],[[65448,65448],"mapped",[4356]],[[65449,65449],"mapped",[4357]],[[65450,65450],"mapped",[4528]],[[65451,65451],"mapped",[4529]],[[65452,65452],"mapped",[4530]],[[65453,65453],"mapped",[4531]],[[65454,65454],"mapped",[4532]],[[65455,65455],"mapped",[4533]],[[65456,65456],"mapped",[4378]],[[65457,65457],"mapped",[4358]],[[65458,65458],"mapped",[4359]],[[65459,65459],"mapped",[4360]],[[65460,65460],"mapped",[4385]],[[65461,65461],"mapped",[4361]],[[65462,65462],"mapped",[4362]],[[65463,65463],"mapped",[4363]],[[65464,65464],"mapped",[4364]],[[65465,65465],"mapped",[4365]],[[65466,65466],"mapped",[4366]],[[65467,65467],"mapped",[4367]],[[65468,65468],"mapped",[4368]],[[65469,65469],"mapped",[4369]],[[65470,65470],"mapped",[4370]],[[65471,65473],"disallowed"],[[65474,65474],"mapped",[4449]],[[65475,65475],"mapped",[4450]],[[65476,65476],"mapped",[4451]],[[65477,65477],"mapped",[4452]],[[65478,65478],"mapped",[4453]],[[65479,65479],"mapped",[4454]],[[65480,65481],"disallowed"],[[65482,65482],"mapped",[4455]],[[65483,65483],"mapped",[4456]],[[65484,65484],"mapped",[4457]],[[65485,65485],"mapped",[4458]],[[65486,65486],"mapped",[4459]],[[65487,65487],"mapped",[4460]],[[65488,65489],"disallowed"],[[65490,65490],"mapped",[4461]],[[65491,65491],"mapped",[4462]],[[65492,65492],"mapped",[4463]],[[65493,65493],"mapped",[4464]],[[65494,65494],"mapped",[4465]],[[65495,65495],"mapped",[4466]],[[65496,65497],"disallowed"],[[65498,65498],"mapped",[4467]],[[65499,65499],"mapped",[4468]],[[65500,65500],"mapped",[4469]],[[65501,65503],"disallowed"],[[65504,65504],"mapped",[162]],[[65505,65505],"mapped",[163]],[[65506,65506],"mapped",[172]],[[65507,65507],"disallowed_STD3_mapped",[32,772]],[[65508,65508],"mapped",[166]],[[65509,65509],"mapped",[165]],[[65510,65510],"mapped",[8361]],[[65511,65511],"disallowed"],[[65512,65512],"mapped",[9474]],[[65513,65513],"mapped",[8592]],[[65514,65514],"mapped",[8593]],[[65515,65515],"mapped",[8594]],[[65516,65516],"mapped",[8595]],[[65517,65517],"mapped",[9632]],[[65518,65518],"mapped",[9675]],[[65519,65528],"disallowed"],[[65529,65531],"disallowed"],[[65532,65532],"disallowed"],[[65533,65533],"disallowed"],[[65534,65535],"disallowed"],[[65536,65547],"valid"],[[65548,65548],"disallowed"],[[65549,65574],"valid"],[[65575,65575],"disallowed"],[[65576,65594],"valid"],[[65595,65595],"disallowed"],[[65596,65597],"valid"],[[65598,65598],"disallowed"],[[65599,65613],"valid"],[[65614,65615],"disallowed"],[[65616,65629],"valid"],[[65630,65663],"disallowed"],[[65664,65786],"valid"],[[65787,65791],"disallowed"],[[65792,65794],"valid",[],"NV8"],[[65795,65798],"disallowed"],[[65799,65843],"valid",[],"NV8"],[[65844,65846],"disallowed"],[[65847,65855],"valid",[],"NV8"],[[65856,65930],"valid",[],"NV8"],[[65931,65932],"valid",[],"NV8"],[[65933,65935],"disallowed"],[[65936,65947],"valid",[],"NV8"],[[65948,65951],"disallowed"],[[65952,65952],"valid",[],"NV8"],[[65953,65999],"disallowed"],[[66000,66044],"valid",[],"NV8"],[[66045,66045],"valid"],[[66046,66175],"disallowed"],[[66176,66204],"valid"],[[66205,66207],"disallowed"],[[66208,66256],"valid"],[[66257,66271],"disallowed"],[[66272,66272],"valid"],[[66273,66299],"valid",[],"NV8"],[[66300,66303],"disallowed"],[[66304,66334],"valid"],[[66335,66335],"valid"],[[66336,66339],"valid",[],"NV8"],[[66340,66351],"disallowed"],[[66352,66368],"valid"],[[66369,66369],"valid",[],"NV8"],[[66370,66377],"valid"],[[66378,66378],"valid",[],"NV8"],[[66379,66383],"disallowed"],[[66384,66426],"valid"],[[66427,66431],"disallowed"],[[66432,66461],"valid"],[[66462,66462],"disallowed"],[[66463,66463],"valid",[],"NV8"],[[66464,66499],"valid"],[[66500,66503],"disallowed"],[[66504,66511],"valid"],[[66512,66517],"valid",[],"NV8"],[[66518,66559],"disallowed"],[[66560,66560],"mapped",[66600]],[[66561,66561],"mapped",[66601]],[[66562,66562],"mapped",[66602]],[[66563,66563],"mapped",[66603]],[[66564,66564],"mapped",[66604]],[[66565,66565],"mapped",[66605]],[[66566,66566],"mapped",[66606]],[[66567,66567],"mapped",[66607]],[[66568,66568],"mapped",[66608]],[[66569,66569],"mapped",[66609]],[[66570,66570],"mapped",[66610]],[[66571,66571],"mapped",[66611]],[[66572,66572],"mapped",[66612]],[[66573,66573],"mapped",[66613]],[[66574,66574],"mapped",[66614]],[[66575,66575],"mapped",[66615]],[[66576,66576],"mapped",[66616]],[[66577,66577],"mapped",[66617]],[[66578,66578],"mapped",[66618]],[[66579,66579],"mapped",[66619]],[[66580,66580],"mapped",[66620]],[[66581,66581],"mapped",[66621]],[[66582,66582],"mapped",[66622]],[[66583,66583],"mapped",[66623]],[[66584,66584],"mapped",[66624]],[[66585,66585],"mapped",[66625]],[[66586,66586],"mapped",[66626]],[[66587,66587],"mapped",[66627]],[[66588,66588],"mapped",[66628]],[[66589,66589],"mapped",[66629]],[[66590,66590],"mapped",[66630]],[[66591,66591],"mapped",[66631]],[[66592,66592],"mapped",[66632]],[[66593,66593],"mapped",[66633]],[[66594,66594],"mapped",[66634]],[[66595,66595],"mapped",[66635]],[[66596,66596],"mapped",[66636]],[[66597,66597],"mapped",[66637]],[[66598,66598],"mapped",[66638]],[[66599,66599],"mapped",[66639]],[[66600,66637],"valid"],[[66638,66717],"valid"],[[66718,66719],"disallowed"],[[66720,66729],"valid"],[[66730,66815],"disallowed"],[[66816,66855],"valid"],[[66856,66863],"disallowed"],[[66864,66915],"valid"],[[66916,66926],"disallowed"],[[66927,66927],"valid",[],"NV8"],[[66928,67071],"disallowed"],[[67072,67382],"valid"],[[67383,67391],"disallowed"],[[67392,67413],"valid"],[[67414,67423],"disallowed"],[[67424,67431],"valid"],[[67432,67583],"disallowed"],[[67584,67589],"valid"],[[67590,67591],"disallowed"],[[67592,67592],"valid"],[[67593,67593],"disallowed"],[[67594,67637],"valid"],[[67638,67638],"disallowed"],[[67639,67640],"valid"],[[67641,67643],"disallowed"],[[67644,67644],"valid"],[[67645,67646],"disallowed"],[[67647,67647],"valid"],[[67648,67669],"valid"],[[67670,67670],"disallowed"],[[67671,67679],"valid",[],"NV8"],[[67680,67702],"valid"],[[67703,67711],"valid",[],"NV8"],[[67712,67742],"valid"],[[67743,67750],"disallowed"],[[67751,67759],"valid",[],"NV8"],[[67760,67807],"disallowed"],[[67808,67826],"valid"],[[67827,67827],"disallowed"],[[67828,67829],"valid"],[[67830,67834],"disallowed"],[[67835,67839],"valid",[],"NV8"],[[67840,67861],"valid"],[[67862,67865],"valid",[],"NV8"],[[67866,67867],"valid",[],"NV8"],[[67868,67870],"disallowed"],[[67871,67871],"valid",[],"NV8"],[[67872,67897],"valid"],[[67898,67902],"disallowed"],[[67903,67903],"valid",[],"NV8"],[[67904,67967],"disallowed"],[[67968,68023],"valid"],[[68024,68027],"disallowed"],[[68028,68029],"valid",[],"NV8"],[[68030,68031],"valid"],[[68032,68047],"valid",[],"NV8"],[[68048,68049],"disallowed"],[[68050,68095],"valid",[],"NV8"],[[68096,68099],"valid"],[[68100,68100],"disallowed"],[[68101,68102],"valid"],[[68103,68107],"disallowed"],[[68108,68115],"valid"],[[68116,68116],"disallowed"],[[68117,68119],"valid"],[[68120,68120],"disallowed"],[[68121,68147],"valid"],[[68148,68151],"disallowed"],[[68152,68154],"valid"],[[68155,68158],"disallowed"],[[68159,68159],"valid"],[[68160,68167],"valid",[],"NV8"],[[68168,68175],"disallowed"],[[68176,68184],"valid",[],"NV8"],[[68185,68191],"disallowed"],[[68192,68220],"valid"],[[68221,68223],"valid",[],"NV8"],[[68224,68252],"valid"],[[68253,68255],"valid",[],"NV8"],[[68256,68287],"disallowed"],[[68288,68295],"valid"],[[68296,68296],"valid",[],"NV8"],[[68297,68326],"valid"],[[68327,68330],"disallowed"],[[68331,68342],"valid",[],"NV8"],[[68343,68351],"disallowed"],[[68352,68405],"valid"],[[68406,68408],"disallowed"],[[68409,68415],"valid",[],"NV8"],[[68416,68437],"valid"],[[68438,68439],"disallowed"],[[68440,68447],"valid",[],"NV8"],[[68448,68466],"valid"],[[68467,68471],"disallowed"],[[68472,68479],"valid",[],"NV8"],[[68480,68497],"valid"],[[68498,68504],"disallowed"],[[68505,68508],"valid",[],"NV8"],[[68509,68520],"disallowed"],[[68521,68527],"valid",[],"NV8"],[[68528,68607],"disallowed"],[[68608,68680],"valid"],[[68681,68735],"disallowed"],[[68736,68736],"mapped",[68800]],[[68737,68737],"mapped",[68801]],[[68738,68738],"mapped",[68802]],[[68739,68739],"mapped",[68803]],[[68740,68740],"mapped",[68804]],[[68741,68741],"mapped",[68805]],[[68742,68742],"mapped",[68806]],[[68743,68743],"mapped",[68807]],[[68744,68744],"mapped",[68808]],[[68745,68745],"mapped",[68809]],[[68746,68746],"mapped",[68810]],[[68747,68747],"mapped",[68811]],[[68748,68748],"mapped",[68812]],[[68749,68749],"mapped",[68813]],[[68750,68750],"mapped",[68814]],[[68751,68751],"mapped",[68815]],[[68752,68752],"mapped",[68816]],[[68753,68753],"mapped",[68817]],[[68754,68754],"mapped",[68818]],[[68755,68755],"mapped",[68819]],[[68756,68756],"mapped",[68820]],[[68757,68757],"mapped",[68821]],[[68758,68758],"mapped",[68822]],[[68759,68759],"mapped",[68823]],[[68760,68760],"mapped",[68824]],[[68761,68761],"mapped",[68825]],[[68762,68762],"mapped",[68826]],[[68763,68763],"mapped",[68827]],[[68764,68764],"mapped",[68828]],[[68765,68765],"mapped",[68829]],[[68766,68766],"mapped",[68830]],[[68767,68767],"mapped",[68831]],[[68768,68768],"mapped",[68832]],[[68769,68769],"mapped",[68833]],[[68770,68770],"mapped",[68834]],[[68771,68771],"mapped",[68835]],[[68772,68772],"mapped",[68836]],[[68773,68773],"mapped",[68837]],[[68774,68774],"mapped",[68838]],[[68775,68775],"mapped",[68839]],[[68776,68776],"mapped",[68840]],[[68777,68777],"mapped",[68841]],[[68778,68778],"mapped",[68842]],[[68779,68779],"mapped",[68843]],[[68780,68780],"mapped",[68844]],[[68781,68781],"mapped",[68845]],[[68782,68782],"mapped",[68846]],[[68783,68783],"mapped",[68847]],[[68784,68784],"mapped",[68848]],[[68785,68785],"mapped",[68849]],[[68786,68786],"mapped",[68850]],[[68787,68799],"disallowed"],[[68800,68850],"valid"],[[68851,68857],"disallowed"],[[68858,68863],"valid",[],"NV8"],[[68864,69215],"disallowed"],[[69216,69246],"valid",[],"NV8"],[[69247,69631],"disallowed"],[[69632,69702],"valid"],[[69703,69709],"valid",[],"NV8"],[[69710,69713],"disallowed"],[[69714,69733],"valid",[],"NV8"],[[69734,69743],"valid"],[[69744,69758],"disallowed"],[[69759,69759],"valid"],[[69760,69818],"valid"],[[69819,69820],"valid",[],"NV8"],[[69821,69821],"disallowed"],[[69822,69825],"valid",[],"NV8"],[[69826,69839],"disallowed"],[[69840,69864],"valid"],[[69865,69871],"disallowed"],[[69872,69881],"valid"],[[69882,69887],"disallowed"],[[69888,69940],"valid"],[[69941,69941],"disallowed"],[[69942,69951],"valid"],[[69952,69955],"valid",[],"NV8"],[[69956,69967],"disallowed"],[[69968,70003],"valid"],[[70004,70005],"valid",[],"NV8"],[[70006,70006],"valid"],[[70007,70015],"disallowed"],[[70016,70084],"valid"],[[70085,70088],"valid",[],"NV8"],[[70089,70089],"valid",[],"NV8"],[[70090,70092],"valid"],[[70093,70093],"valid",[],"NV8"],[[70094,70095],"disallowed"],[[70096,70105],"valid"],[[70106,70106],"valid"],[[70107,70107],"valid",[],"NV8"],[[70108,70108],"valid"],[[70109,70111],"valid",[],"NV8"],[[70112,70112],"disallowed"],[[70113,70132],"valid",[],"NV8"],[[70133,70143],"disallowed"],[[70144,70161],"valid"],[[70162,70162],"disallowed"],[[70163,70199],"valid"],[[70200,70205],"valid",[],"NV8"],[[70206,70271],"disallowed"],[[70272,70278],"valid"],[[70279,70279],"disallowed"],[[70280,70280],"valid"],[[70281,70281],"disallowed"],[[70282,70285],"valid"],[[70286,70286],"disallowed"],[[70287,70301],"valid"],[[70302,70302],"disallowed"],[[70303,70312],"valid"],[[70313,70313],"valid",[],"NV8"],[[70314,70319],"disallowed"],[[70320,70378],"valid"],[[70379,70383],"disallowed"],[[70384,70393],"valid"],[[70394,70399],"disallowed"],[[70400,70400],"valid"],[[70401,70403],"valid"],[[70404,70404],"disallowed"],[[70405,70412],"valid"],[[70413,70414],"disallowed"],[[70415,70416],"valid"],[[70417,70418],"disallowed"],[[70419,70440],"valid"],[[70441,70441],"disallowed"],[[70442,70448],"valid"],[[70449,70449],"disallowed"],[[70450,70451],"valid"],[[70452,70452],"disallowed"],[[70453,70457],"valid"],[[70458,70459],"disallowed"],[[70460,70468],"valid"],[[70469,70470],"disallowed"],[[70471,70472],"valid"],[[70473,70474],"disallowed"],[[70475,70477],"valid"],[[70478,70479],"disallowed"],[[70480,70480],"valid"],[[70481,70486],"disallowed"],[[70487,70487],"valid"],[[70488,70492],"disallowed"],[[70493,70499],"valid"],[[70500,70501],"disallowed"],[[70502,70508],"valid"],[[70509,70511],"disallowed"],[[70512,70516],"valid"],[[70517,70783],"disallowed"],[[70784,70853],"valid"],[[70854,70854],"valid",[],"NV8"],[[70855,70855],"valid"],[[70856,70863],"disallowed"],[[70864,70873],"valid"],[[70874,71039],"disallowed"],[[71040,71093],"valid"],[[71094,71095],"disallowed"],[[71096,71104],"valid"],[[71105,71113],"valid",[],"NV8"],[[71114,71127],"valid",[],"NV8"],[[71128,71133],"valid"],[[71134,71167],"disallowed"],[[71168,71232],"valid"],[[71233,71235],"valid",[],"NV8"],[[71236,71236],"valid"],[[71237,71247],"disallowed"],[[71248,71257],"valid"],[[71258,71295],"disallowed"],[[71296,71351],"valid"],[[71352,71359],"disallowed"],[[71360,71369],"valid"],[[71370,71423],"disallowed"],[[71424,71449],"valid"],[[71450,71452],"disallowed"],[[71453,71467],"valid"],[[71468,71471],"disallowed"],[[71472,71481],"valid"],[[71482,71487],"valid",[],"NV8"],[[71488,71839],"disallowed"],[[71840,71840],"mapped",[71872]],[[71841,71841],"mapped",[71873]],[[71842,71842],"mapped",[71874]],[[71843,71843],"mapped",[71875]],[[71844,71844],"mapped",[71876]],[[71845,71845],"mapped",[71877]],[[71846,71846],"mapped",[71878]],[[71847,71847],"mapped",[71879]],[[71848,71848],"mapped",[71880]],[[71849,71849],"mapped",[71881]],[[71850,71850],"mapped",[71882]],[[71851,71851],"mapped",[71883]],[[71852,71852],"mapped",[71884]],[[71853,71853],"mapped",[71885]],[[71854,71854],"mapped",[71886]],[[71855,71855],"mapped",[71887]],[[71856,71856],"mapped",[71888]],[[71857,71857],"mapped",[71889]],[[71858,71858],"mapped",[71890]],[[71859,71859],"mapped",[71891]],[[71860,71860],"mapped",[71892]],[[71861,71861],"mapped",[71893]],[[71862,71862],"mapped",[71894]],[[71863,71863],"mapped",[71895]],[[71864,71864],"mapped",[71896]],[[71865,71865],"mapped",[71897]],[[71866,71866],"mapped",[71898]],[[71867,71867],"mapped",[71899]],[[71868,71868],"mapped",[71900]],[[71869,71869],"mapped",[71901]],[[71870,71870],"mapped",[71902]],[[71871,71871],"mapped",[71903]],[[71872,71913],"valid"],[[71914,71922],"valid",[],"NV8"],[[71923,71934],"disallowed"],[[71935,71935],"valid"],[[71936,72383],"disallowed"],[[72384,72440],"valid"],[[72441,73727],"disallowed"],[[73728,74606],"valid"],[[74607,74648],"valid"],[[74649,74649],"valid"],[[74650,74751],"disallowed"],[[74752,74850],"valid",[],"NV8"],[[74851,74862],"valid",[],"NV8"],[[74863,74863],"disallowed"],[[74864,74867],"valid",[],"NV8"],[[74868,74868],"valid",[],"NV8"],[[74869,74879],"disallowed"],[[74880,75075],"valid"],[[75076,77823],"disallowed"],[[77824,78894],"valid"],[[78895,82943],"disallowed"],[[82944,83526],"valid"],[[83527,92159],"disallowed"],[[92160,92728],"valid"],[[92729,92735],"disallowed"],[[92736,92766],"valid"],[[92767,92767],"disallowed"],[[92768,92777],"valid"],[[92778,92781],"disallowed"],[[92782,92783],"valid",[],"NV8"],[[92784,92879],"disallowed"],[[92880,92909],"valid"],[[92910,92911],"disallowed"],[[92912,92916],"valid"],[[92917,92917],"valid",[],"NV8"],[[92918,92927],"disallowed"],[[92928,92982],"valid"],[[92983,92991],"valid",[],"NV8"],[[92992,92995],"valid"],[[92996,92997],"valid",[],"NV8"],[[92998,93007],"disallowed"],[[93008,93017],"valid"],[[93018,93018],"disallowed"],[[93019,93025],"valid",[],"NV8"],[[93026,93026],"disallowed"],[[93027,93047],"valid"],[[93048,93052],"disallowed"],[[93053,93071],"valid"],[[93072,93951],"disallowed"],[[93952,94020],"valid"],[[94021,94031],"disallowed"],[[94032,94078],"valid"],[[94079,94094],"disallowed"],[[94095,94111],"valid"],[[94112,110591],"disallowed"],[[110592,110593],"valid"],[[110594,113663],"disallowed"],[[113664,113770],"valid"],[[113771,113775],"disallowed"],[[113776,113788],"valid"],[[113789,113791],"disallowed"],[[113792,113800],"valid"],[[113801,113807],"disallowed"],[[113808,113817],"valid"],[[113818,113819],"disallowed"],[[113820,113820],"valid",[],"NV8"],[[113821,113822],"valid"],[[113823,113823],"valid",[],"NV8"],[[113824,113827],"ignored"],[[113828,118783],"disallowed"],[[118784,119029],"valid",[],"NV8"],[[119030,119039],"disallowed"],[[119040,119078],"valid",[],"NV8"],[[119079,119080],"disallowed"],[[119081,119081],"valid",[],"NV8"],[[119082,119133],"valid",[],"NV8"],[[119134,119134],"mapped",[119127,119141]],[[119135,119135],"mapped",[119128,119141]],[[119136,119136],"mapped",[119128,119141,119150]],[[119137,119137],"mapped",[119128,119141,119151]],[[119138,119138],"mapped",[119128,119141,119152]],[[119139,119139],"mapped",[119128,119141,119153]],[[119140,119140],"mapped",[119128,119141,119154]],[[119141,119154],"valid",[],"NV8"],[[119155,119162],"disallowed"],[[119163,119226],"valid",[],"NV8"],[[119227,119227],"mapped",[119225,119141]],[[119228,119228],"mapped",[119226,119141]],[[119229,119229],"mapped",[119225,119141,119150]],[[119230,119230],"mapped",[119226,119141,119150]],[[119231,119231],"mapped",[119225,119141,119151]],[[119232,119232],"mapped",[119226,119141,119151]],[[119233,119261],"valid",[],"NV8"],[[119262,119272],"valid",[],"NV8"],[[119273,119295],"disallowed"],[[119296,119365],"valid",[],"NV8"],[[119366,119551],"disallowed"],[[119552,119638],"valid",[],"NV8"],[[119639,119647],"disallowed"],[[119648,119665],"valid",[],"NV8"],[[119666,119807],"disallowed"],[[119808,119808],"mapped",[97]],[[119809,119809],"mapped",[98]],[[119810,119810],"mapped",[99]],[[119811,119811],"mapped",[100]],[[119812,119812],"mapped",[101]],[[119813,119813],"mapped",[102]],[[119814,119814],"mapped",[103]],[[119815,119815],"mapped",[104]],[[119816,119816],"mapped",[105]],[[119817,119817],"mapped",[106]],[[119818,119818],"mapped",[107]],[[119819,119819],"mapped",[108]],[[119820,119820],"mapped",[109]],[[119821,119821],"mapped",[110]],[[119822,119822],"mapped",[111]],[[119823,119823],"mapped",[112]],[[119824,119824],"mapped",[113]],[[119825,119825],"mapped",[114]],[[119826,119826],"mapped",[115]],[[119827,119827],"mapped",[116]],[[119828,119828],"mapped",[117]],[[119829,119829],"mapped",[118]],[[119830,119830],"mapped",[119]],[[119831,119831],"mapped",[120]],[[119832,119832],"mapped",[121]],[[119833,119833],"mapped",[122]],[[119834,119834],"mapped",[97]],[[119835,119835],"mapped",[98]],[[119836,119836],"mapped",[99]],[[119837,119837],"mapped",[100]],[[119838,119838],"mapped",[101]],[[119839,119839],"mapped",[102]],[[119840,119840],"mapped",[103]],[[119841,119841],"mapped",[104]],[[119842,119842],"mapped",[105]],[[119843,119843],"mapped",[106]],[[119844,119844],"mapped",[107]],[[119845,119845],"mapped",[108]],[[119846,119846],"mapped",[109]],[[119847,119847],"mapped",[110]],[[119848,119848],"mapped",[111]],[[119849,119849],"mapped",[112]],[[119850,119850],"mapped",[113]],[[119851,119851],"mapped",[114]],[[119852,119852],"mapped",[115]],[[119853,119853],"mapped",[116]],[[119854,119854],"mapped",[117]],[[119855,119855],"mapped",[118]],[[119856,119856],"mapped",[119]],[[119857,119857],"mapped",[120]],[[119858,119858],"mapped",[121]],[[119859,119859],"mapped",[122]],[[119860,119860],"mapped",[97]],[[119861,119861],"mapped",[98]],[[119862,119862],"mapped",[99]],[[119863,119863],"mapped",[100]],[[119864,119864],"mapped",[101]],[[119865,119865],"mapped",[102]],[[119866,119866],"mapped",[103]],[[119867,119867],"mapped",[104]],[[119868,119868],"mapped",[105]],[[119869,119869],"mapped",[106]],[[119870,119870],"mapped",[107]],[[119871,119871],"mapped",[108]],[[119872,119872],"mapped",[109]],[[119873,119873],"mapped",[110]],[[119874,119874],"mapped",[111]],[[119875,119875],"mapped",[112]],[[119876,119876],"mapped",[113]],[[119877,119877],"mapped",[114]],[[119878,119878],"mapped",[115]],[[119879,119879],"mapped",[116]],[[119880,119880],"mapped",[117]],[[119881,119881],"mapped",[118]],[[119882,119882],"mapped",[119]],[[119883,119883],"mapped",[120]],[[119884,119884],"mapped",[121]],[[119885,119885],"mapped",[122]],[[119886,119886],"mapped",[97]],[[119887,119887],"mapped",[98]],[[119888,119888],"mapped",[99]],[[119889,119889],"mapped",[100]],[[119890,119890],"mapped",[101]],[[119891,119891],"mapped",[102]],[[119892,119892],"mapped",[103]],[[119893,119893],"disallowed"],[[119894,119894],"mapped",[105]],[[119895,119895],"mapped",[106]],[[119896,119896],"mapped",[107]],[[119897,119897],"mapped",[108]],[[119898,119898],"mapped",[109]],[[119899,119899],"mapped",[110]],[[119900,119900],"mapped",[111]],[[119901,119901],"mapped",[112]],[[119902,119902],"mapped",[113]],[[119903,119903],"mapped",[114]],[[119904,119904],"mapped",[115]],[[119905,119905],"mapped",[116]],[[119906,119906],"mapped",[117]],[[119907,119907],"mapped",[118]],[[119908,119908],"mapped",[119]],[[119909,119909],"mapped",[120]],[[119910,119910],"mapped",[121]],[[119911,119911],"mapped",[122]],[[119912,119912],"mapped",[97]],[[119913,119913],"mapped",[98]],[[119914,119914],"mapped",[99]],[[119915,119915],"mapped",[100]],[[119916,119916],"mapped",[101]],[[119917,119917],"mapped",[102]],[[119918,119918],"mapped",[103]],[[119919,119919],"mapped",[104]],[[119920,119920],"mapped",[105]],[[119921,119921],"mapped",[106]],[[119922,119922],"mapped",[107]],[[119923,119923],"mapped",[108]],[[119924,119924],"mapped",[109]],[[119925,119925],"mapped",[110]],[[119926,119926],"mapped",[111]],[[119927,119927],"mapped",[112]],[[119928,119928],"mapped",[113]],[[119929,119929],"mapped",[114]],[[119930,119930],"mapped",[115]],[[119931,119931],"mapped",[116]],[[119932,119932],"mapped",[117]],[[119933,119933],"mapped",[118]],[[119934,119934],"mapped",[119]],[[119935,119935],"mapped",[120]],[[119936,119936],"mapped",[121]],[[119937,119937],"mapped",[122]],[[119938,119938],"mapped",[97]],[[119939,119939],"mapped",[98]],[[119940,119940],"mapped",[99]],[[119941,119941],"mapped",[100]],[[119942,119942],"mapped",[101]],[[119943,119943],"mapped",[102]],[[119944,119944],"mapped",[103]],[[119945,119945],"mapped",[104]],[[119946,119946],"mapped",[105]],[[119947,119947],"mapped",[106]],[[119948,119948],"mapped",[107]],[[119949,119949],"mapped",[108]],[[119950,119950],"mapped",[109]],[[119951,119951],"mapped",[110]],[[119952,119952],"mapped",[111]],[[119953,119953],"mapped",[112]],[[119954,119954],"mapped",[113]],[[119955,119955],"mapped",[114]],[[119956,119956],"mapped",[115]],[[119957,119957],"mapped",[116]],[[119958,119958],"mapped",[117]],[[119959,119959],"mapped",[118]],[[119960,119960],"mapped",[119]],[[119961,119961],"mapped",[120]],[[119962,119962],"mapped",[121]],[[119963,119963],"mapped",[122]],[[119964,119964],"mapped",[97]],[[119965,119965],"disallowed"],[[119966,119966],"mapped",[99]],[[119967,119967],"mapped",[100]],[[119968,119969],"disallowed"],[[119970,119970],"mapped",[103]],[[119971,119972],"disallowed"],[[119973,119973],"mapped",[106]],[[119974,119974],"mapped",[107]],[[119975,119976],"disallowed"],[[119977,119977],"mapped",[110]],[[119978,119978],"mapped",[111]],[[119979,119979],"mapped",[112]],[[119980,119980],"mapped",[113]],[[119981,119981],"disallowed"],[[119982,119982],"mapped",[115]],[[119983,119983],"mapped",[116]],[[119984,119984],"mapped",[117]],[[119985,119985],"mapped",[118]],[[119986,119986],"mapped",[119]],[[119987,119987],"mapped",[120]],[[119988,119988],"mapped",[121]],[[119989,119989],"mapped",[122]],[[119990,119990],"mapped",[97]],[[119991,119991],"mapped",[98]],[[119992,119992],"mapped",[99]],[[119993,119993],"mapped",[100]],[[119994,119994],"disallowed"],[[119995,119995],"mapped",[102]],[[119996,119996],"disallowed"],[[119997,119997],"mapped",[104]],[[119998,119998],"mapped",[105]],[[119999,119999],"mapped",[106]],[[120000,120000],"mapped",[107]],[[120001,120001],"mapped",[108]],[[120002,120002],"mapped",[109]],[[120003,120003],"mapped",[110]],[[120004,120004],"disallowed"],[[120005,120005],"mapped",[112]],[[120006,120006],"mapped",[113]],[[120007,120007],"mapped",[114]],[[120008,120008],"mapped",[115]],[[120009,120009],"mapped",[116]],[[120010,120010],"mapped",[117]],[[120011,120011],"mapped",[118]],[[120012,120012],"mapped",[119]],[[120013,120013],"mapped",[120]],[[120014,120014],"mapped",[121]],[[120015,120015],"mapped",[122]],[[120016,120016],"mapped",[97]],[[120017,120017],"mapped",[98]],[[120018,120018],"mapped",[99]],[[120019,120019],"mapped",[100]],[[120020,120020],"mapped",[101]],[[120021,120021],"mapped",[102]],[[120022,120022],"mapped",[103]],[[120023,120023],"mapped",[104]],[[120024,120024],"mapped",[105]],[[120025,120025],"mapped",[106]],[[120026,120026],"mapped",[107]],[[120027,120027],"mapped",[108]],[[120028,120028],"mapped",[109]],[[120029,120029],"mapped",[110]],[[120030,120030],"mapped",[111]],[[120031,120031],"mapped",[112]],[[120032,120032],"mapped",[113]],[[120033,120033],"mapped",[114]],[[120034,120034],"mapped",[115]],[[120035,120035],"mapped",[116]],[[120036,120036],"mapped",[117]],[[120037,120037],"mapped",[118]],[[120038,120038],"mapped",[119]],[[120039,120039],"mapped",[120]],[[120040,120040],"mapped",[121]],[[120041,120041],"mapped",[122]],[[120042,120042],"mapped",[97]],[[120043,120043],"mapped",[98]],[[120044,120044],"mapped",[99]],[[120045,120045],"mapped",[100]],[[120046,120046],"mapped",[101]],[[120047,120047],"mapped",[102]],[[120048,120048],"mapped",[103]],[[120049,120049],"mapped",[104]],[[120050,120050],"mapped",[105]],[[120051,120051],"mapped",[106]],[[120052,120052],"mapped",[107]],[[120053,120053],"mapped",[108]],[[120054,120054],"mapped",[109]],[[120055,120055],"mapped",[110]],[[120056,120056],"mapped",[111]],[[120057,120057],"mapped",[112]],[[120058,120058],"mapped",[113]],[[120059,120059],"mapped",[114]],[[120060,120060],"mapped",[115]],[[120061,120061],"mapped",[116]],[[120062,120062],"mapped",[117]],[[120063,120063],"mapped",[118]],[[120064,120064],"mapped",[119]],[[120065,120065],"mapped",[120]],[[120066,120066],"mapped",[121]],[[120067,120067],"mapped",[122]],[[120068,120068],"mapped",[97]],[[120069,120069],"mapped",[98]],[[120070,120070],"disallowed"],[[120071,120071],"mapped",[100]],[[120072,120072],"mapped",[101]],[[120073,120073],"mapped",[102]],[[120074,120074],"mapped",[103]],[[120075,120076],"disallowed"],[[120077,120077],"mapped",[106]],[[120078,120078],"mapped",[107]],[[120079,120079],"mapped",[108]],[[120080,120080],"mapped",[109]],[[120081,120081],"mapped",[110]],[[120082,120082],"mapped",[111]],[[120083,120083],"mapped",[112]],[[120084,120084],"mapped",[113]],[[120085,120085],"disallowed"],[[120086,120086],"mapped",[115]],[[120087,120087],"mapped",[116]],[[120088,120088],"mapped",[117]],[[120089,120089],"mapped",[118]],[[120090,120090],"mapped",[119]],[[120091,120091],"mapped",[120]],[[120092,120092],"mapped",[121]],[[120093,120093],"disallowed"],[[120094,120094],"mapped",[97]],[[120095,120095],"mapped",[98]],[[120096,120096],"mapped",[99]],[[120097,120097],"mapped",[100]],[[120098,120098],"mapped",[101]],[[120099,120099],"mapped",[102]],[[120100,120100],"mapped",[103]],[[120101,120101],"mapped",[104]],[[120102,120102],"mapped",[105]],[[120103,120103],"mapped",[106]],[[120104,120104],"mapped",[107]],[[120105,120105],"mapped",[108]],[[120106,120106],"mapped",[109]],[[120107,120107],"mapped",[110]],[[120108,120108],"mapped",[111]],[[120109,120109],"mapped",[112]],[[120110,120110],"mapped",[113]],[[120111,120111],"mapped",[114]],[[120112,120112],"mapped",[115]],[[120113,120113],"mapped",[116]],[[120114,120114],"mapped",[117]],[[120115,120115],"mapped",[118]],[[120116,120116],"mapped",[119]],[[120117,120117],"mapped",[120]],[[120118,120118],"mapped",[121]],[[120119,120119],"mapped",[122]],[[120120,120120],"mapped",[97]],[[120121,120121],"mapped",[98]],[[120122,120122],"disallowed"],[[120123,120123],"mapped",[100]],[[120124,120124],"mapped",[101]],[[120125,120125],"mapped",[102]],[[120126,120126],"mapped",[103]],[[120127,120127],"disallowed"],[[120128,120128],"mapped",[105]],[[120129,120129],"mapped",[106]],[[120130,120130],"mapped",[107]],[[120131,120131],"mapped",[108]],[[120132,120132],"mapped",[109]],[[120133,120133],"disallowed"],[[120134,120134],"mapped",[111]],[[120135,120137],"disallowed"],[[120138,120138],"mapped",[115]],[[120139,120139],"mapped",[116]],[[120140,120140],"mapped",[117]],[[120141,120141],"mapped",[118]],[[120142,120142],"mapped",[119]],[[120143,120143],"mapped",[120]],[[120144,120144],"mapped",[121]],[[120145,120145],"disallowed"],[[120146,120146],"mapped",[97]],[[120147,120147],"mapped",[98]],[[120148,120148],"mapped",[99]],[[120149,120149],"mapped",[100]],[[120150,120150],"mapped",[101]],[[120151,120151],"mapped",[102]],[[120152,120152],"mapped",[103]],[[120153,120153],"mapped",[104]],[[120154,120154],"mapped",[105]],[[120155,120155],"mapped",[106]],[[120156,120156],"mapped",[107]],[[120157,120157],"mapped",[108]],[[120158,120158],"mapped",[109]],[[120159,120159],"mapped",[110]],[[120160,120160],"mapped",[111]],[[120161,120161],"mapped",[112]],[[120162,120162],"mapped",[113]],[[120163,120163],"mapped",[114]],[[120164,120164],"mapped",[115]],[[120165,120165],"mapped",[116]],[[120166,120166],"mapped",[117]],[[120167,120167],"mapped",[118]],[[120168,120168],"mapped",[119]],[[120169,120169],"mapped",[120]],[[120170,120170],"mapped",[121]],[[120171,120171],"mapped",[122]],[[120172,120172],"mapped",[97]],[[120173,120173],"mapped",[98]],[[120174,120174],"mapped",[99]],[[120175,120175],"mapped",[100]],[[120176,120176],"mapped",[101]],[[120177,120177],"mapped",[102]],[[120178,120178],"mapped",[103]],[[120179,120179],"mapped",[104]],[[120180,120180],"mapped",[105]],[[120181,120181],"mapped",[106]],[[120182,120182],"mapped",[107]],[[120183,120183],"mapped",[108]],[[120184,120184],"mapped",[109]],[[120185,120185],"mapped",[110]],[[120186,120186],"mapped",[111]],[[120187,120187],"mapped",[112]],[[120188,120188],"mapped",[113]],[[120189,120189],"mapped",[114]],[[120190,120190],"mapped",[115]],[[120191,120191],"mapped",[116]],[[120192,120192],"mapped",[117]],[[120193,120193],"mapped",[118]],[[120194,120194],"mapped",[119]],[[120195,120195],"mapped",[120]],[[120196,120196],"mapped",[121]],[[120197,120197],"mapped",[122]],[[120198,120198],"mapped",[97]],[[120199,120199],"mapped",[98]],[[120200,120200],"mapped",[99]],[[120201,120201],"mapped",[100]],[[120202,120202],"mapped",[101]],[[120203,120203],"mapped",[102]],[[120204,120204],"mapped",[103]],[[120205,120205],"mapped",[104]],[[120206,120206],"mapped",[105]],[[120207,120207],"mapped",[106]],[[120208,120208],"mapped",[107]],[[120209,120209],"mapped",[108]],[[120210,120210],"mapped",[109]],[[120211,120211],"mapped",[110]],[[120212,120212],"mapped",[111]],[[120213,120213],"mapped",[112]],[[120214,120214],"mapped",[113]],[[120215,120215],"mapped",[114]],[[120216,120216],"mapped",[115]],[[120217,120217],"mapped",[116]],[[120218,120218],"mapped",[117]],[[120219,120219],"mapped",[118]],[[120220,120220],"mapped",[119]],[[120221,120221],"mapped",[120]],[[120222,120222],"mapped",[121]],[[120223,120223],"mapped",[122]],[[120224,120224],"mapped",[97]],[[120225,120225],"mapped",[98]],[[120226,120226],"mapped",[99]],[[120227,120227],"mapped",[100]],[[120228,120228],"mapped",[101]],[[120229,120229],"mapped",[102]],[[120230,120230],"mapped",[103]],[[120231,120231],"mapped",[104]],[[120232,120232],"mapped",[105]],[[120233,120233],"mapped",[106]],[[120234,120234],"mapped",[107]],[[120235,120235],"mapped",[108]],[[120236,120236],"mapped",[109]],[[120237,120237],"mapped",[110]],[[120238,120238],"mapped",[111]],[[120239,120239],"mapped",[112]],[[120240,120240],"mapped",[113]],[[120241,120241],"mapped",[114]],[[120242,120242],"mapped",[115]],[[120243,120243],"mapped",[116]],[[120244,120244],"mapped",[117]],[[120245,120245],"mapped",[118]],[[120246,120246],"mapped",[119]],[[120247,120247],"mapped",[120]],[[120248,120248],"mapped",[121]],[[120249,120249],"mapped",[122]],[[120250,120250],"mapped",[97]],[[120251,120251],"mapped",[98]],[[120252,120252],"mapped",[99]],[[120253,120253],"mapped",[100]],[[120254,120254],"mapped",[101]],[[120255,120255],"mapped",[102]],[[120256,120256],"mapped",[103]],[[120257,120257],"mapped",[104]],[[120258,120258],"mapped",[105]],[[120259,120259],"mapped",[106]],[[120260,120260],"mapped",[107]],[[120261,120261],"mapped",[108]],[[120262,120262],"mapped",[109]],[[120263,120263],"mapped",[110]],[[120264,120264],"mapped",[111]],[[120265,120265],"mapped",[112]],[[120266,120266],"mapped",[113]],[[120267,120267],"mapped",[114]],[[120268,120268],"mapped",[115]],[[120269,120269],"mapped",[116]],[[120270,120270],"mapped",[117]],[[120271,120271],"mapped",[118]],[[120272,120272],"mapped",[119]],[[120273,120273],"mapped",[120]],[[120274,120274],"mapped",[121]],[[120275,120275],"mapped",[122]],[[120276,120276],"mapped",[97]],[[120277,120277],"mapped",[98]],[[120278,120278],"mapped",[99]],[[120279,120279],"mapped",[100]],[[120280,120280],"mapped",[101]],[[120281,120281],"mapped",[102]],[[120282,120282],"mapped",[103]],[[120283,120283],"mapped",[104]],[[120284,120284],"mapped",[105]],[[120285,120285],"mapped",[106]],[[120286,120286],"mapped",[107]],[[120287,120287],"mapped",[108]],[[120288,120288],"mapped",[109]],[[120289,120289],"mapped",[110]],[[120290,120290],"mapped",[111]],[[120291,120291],"mapped",[112]],[[120292,120292],"mapped",[113]],[[120293,120293],"mapped",[114]],[[120294,120294],"mapped",[115]],[[120295,120295],"mapped",[116]],[[120296,120296],"mapped",[117]],[[120297,120297],"mapped",[118]],[[120298,120298],"mapped",[119]],[[120299,120299],"mapped",[120]],[[120300,120300],"mapped",[121]],[[120301,120301],"mapped",[122]],[[120302,120302],"mapped",[97]],[[120303,120303],"mapped",[98]],[[120304,120304],"mapped",[99]],[[120305,120305],"mapped",[100]],[[120306,120306],"mapped",[101]],[[120307,120307],"mapped",[102]],[[120308,120308],"mapped",[103]],[[120309,120309],"mapped",[104]],[[120310,120310],"mapped",[105]],[[120311,120311],"mapped",[106]],[[120312,120312],"mapped",[107]],[[120313,120313],"mapped",[108]],[[120314,120314],"mapped",[109]],[[120315,120315],"mapped",[110]],[[120316,120316],"mapped",[111]],[[120317,120317],"mapped",[112]],[[120318,120318],"mapped",[113]],[[120319,120319],"mapped",[114]],[[120320,120320],"mapped",[115]],[[120321,120321],"mapped",[116]],[[120322,120322],"mapped",[117]],[[120323,120323],"mapped",[118]],[[120324,120324],"mapped",[119]],[[120325,120325],"mapped",[120]],[[120326,120326],"mapped",[121]],[[120327,120327],"mapped",[122]],[[120328,120328],"mapped",[97]],[[120329,120329],"mapped",[98]],[[120330,120330],"mapped",[99]],[[120331,120331],"mapped",[100]],[[120332,120332],"mapped",[101]],[[120333,120333],"mapped",[102]],[[120334,120334],"mapped",[103]],[[120335,120335],"mapped",[104]],[[120336,120336],"mapped",[105]],[[120337,120337],"mapped",[106]],[[120338,120338],"mapped",[107]],[[120339,120339],"mapped",[108]],[[120340,120340],"mapped",[109]],[[120341,120341],"mapped",[110]],[[120342,120342],"mapped",[111]],[[120343,120343],"mapped",[112]],[[120344,120344],"mapped",[113]],[[120345,120345],"mapped",[114]],[[120346,120346],"mapped",[115]],[[120347,120347],"mapped",[116]],[[120348,120348],"mapped",[117]],[[120349,120349],"mapped",[118]],[[120350,120350],"mapped",[119]],[[120351,120351],"mapped",[120]],[[120352,120352],"mapped",[121]],[[120353,120353],"mapped",[122]],[[120354,120354],"mapped",[97]],[[120355,120355],"mapped",[98]],[[120356,120356],"mapped",[99]],[[120357,120357],"mapped",[100]],[[120358,120358],"mapped",[101]],[[120359,120359],"mapped",[102]],[[120360,120360],"mapped",[103]],[[120361,120361],"mapped",[104]],[[120362,120362],"mapped",[105]],[[120363,120363],"mapped",[106]],[[120364,120364],"mapped",[107]],[[120365,120365],"mapped",[108]],[[120366,120366],"mapped",[109]],[[120367,120367],"mapped",[110]],[[120368,120368],"mapped",[111]],[[120369,120369],"mapped",[112]],[[120370,120370],"mapped",[113]],[[120371,120371],"mapped",[114]],[[120372,120372],"mapped",[115]],[[120373,120373],"mapped",[116]],[[120374,120374],"mapped",[117]],[[120375,120375],"mapped",[118]],[[120376,120376],"mapped",[119]],[[120377,120377],"mapped",[120]],[[120378,120378],"mapped",[121]],[[120379,120379],"mapped",[122]],[[120380,120380],"mapped",[97]],[[120381,120381],"mapped",[98]],[[120382,120382],"mapped",[99]],[[120383,120383],"mapped",[100]],[[120384,120384],"mapped",[101]],[[120385,120385],"mapped",[102]],[[120386,120386],"mapped",[103]],[[120387,120387],"mapped",[104]],[[120388,120388],"mapped",[105]],[[120389,120389],"mapped",[106]],[[120390,120390],"mapped",[107]],[[120391,120391],"mapped",[108]],[[120392,120392],"mapped",[109]],[[120393,120393],"mapped",[110]],[[120394,120394],"mapped",[111]],[[120395,120395],"mapped",[112]],[[120396,120396],"mapped",[113]],[[120397,120397],"mapped",[114]],[[120398,120398],"mapped",[115]],[[120399,120399],"mapped",[116]],[[120400,120400],"mapped",[117]],[[120401,120401],"mapped",[118]],[[120402,120402],"mapped",[119]],[[120403,120403],"mapped",[120]],[[120404,120404],"mapped",[121]],[[120405,120405],"mapped",[122]],[[120406,120406],"mapped",[97]],[[120407,120407],"mapped",[98]],[[120408,120408],"mapped",[99]],[[120409,120409],"mapped",[100]],[[120410,120410],"mapped",[101]],[[120411,120411],"mapped",[102]],[[120412,120412],"mapped",[103]],[[120413,120413],"mapped",[104]],[[120414,120414],"mapped",[105]],[[120415,120415],"mapped",[106]],[[120416,120416],"mapped",[107]],[[120417,120417],"mapped",[108]],[[120418,120418],"mapped",[109]],[[120419,120419],"mapped",[110]],[[120420,120420],"mapped",[111]],[[120421,120421],"mapped",[112]],[[120422,120422],"mapped",[113]],[[120423,120423],"mapped",[114]],[[120424,120424],"mapped",[115]],[[120425,120425],"mapped",[116]],[[120426,120426],"mapped",[117]],[[120427,120427],"mapped",[118]],[[120428,120428],"mapped",[119]],[[120429,120429],"mapped",[120]],[[120430,120430],"mapped",[121]],[[120431,120431],"mapped",[122]],[[120432,120432],"mapped",[97]],[[120433,120433],"mapped",[98]],[[120434,120434],"mapped",[99]],[[120435,120435],"mapped",[100]],[[120436,120436],"mapped",[101]],[[120437,120437],"mapped",[102]],[[120438,120438],"mapped",[103]],[[120439,120439],"mapped",[104]],[[120440,120440],"mapped",[105]],[[120441,120441],"mapped",[106]],[[120442,120442],"mapped",[107]],[[120443,120443],"mapped",[108]],[[120444,120444],"mapped",[109]],[[120445,120445],"mapped",[110]],[[120446,120446],"mapped",[111]],[[120447,120447],"mapped",[112]],[[120448,120448],"mapped",[113]],[[120449,120449],"mapped",[114]],[[120450,120450],"mapped",[115]],[[120451,120451],"mapped",[116]],[[120452,120452],"mapped",[117]],[[120453,120453],"mapped",[118]],[[120454,120454],"mapped",[119]],[[120455,120455],"mapped",[120]],[[120456,120456],"mapped",[121]],[[120457,120457],"mapped",[122]],[[120458,120458],"mapped",[97]],[[120459,120459],"mapped",[98]],[[120460,120460],"mapped",[99]],[[120461,120461],"mapped",[100]],[[120462,120462],"mapped",[101]],[[120463,120463],"mapped",[102]],[[120464,120464],"mapped",[103]],[[120465,120465],"mapped",[104]],[[120466,120466],"mapped",[105]],[[120467,120467],"mapped",[106]],[[120468,120468],"mapped",[107]],[[120469,120469],"mapped",[108]],[[120470,120470],"mapped",[109]],[[120471,120471],"mapped",[110]],[[120472,120472],"mapped",[111]],[[120473,120473],"mapped",[112]],[[120474,120474],"mapped",[113]],[[120475,120475],"mapped",[114]],[[120476,120476],"mapped",[115]],[[120477,120477],"mapped",[116]],[[120478,120478],"mapped",[117]],[[120479,120479],"mapped",[118]],[[120480,120480],"mapped",[119]],[[120481,120481],"mapped",[120]],[[120482,120482],"mapped",[121]],[[120483,120483],"mapped",[122]],[[120484,120484],"mapped",[305]],[[120485,120485],"mapped",[567]],[[120486,120487],"disallowed"],[[120488,120488],"mapped",[945]],[[120489,120489],"mapped",[946]],[[120490,120490],"mapped",[947]],[[120491,120491],"mapped",[948]],[[120492,120492],"mapped",[949]],[[120493,120493],"mapped",[950]],[[120494,120494],"mapped",[951]],[[120495,120495],"mapped",[952]],[[120496,120496],"mapped",[953]],[[120497,120497],"mapped",[954]],[[120498,120498],"mapped",[955]],[[120499,120499],"mapped",[956]],[[120500,120500],"mapped",[957]],[[120501,120501],"mapped",[958]],[[120502,120502],"mapped",[959]],[[120503,120503],"mapped",[960]],[[120504,120504],"mapped",[961]],[[120505,120505],"mapped",[952]],[[120506,120506],"mapped",[963]],[[120507,120507],"mapped",[964]],[[120508,120508],"mapped",[965]],[[120509,120509],"mapped",[966]],[[120510,120510],"mapped",[967]],[[120511,120511],"mapped",[968]],[[120512,120512],"mapped",[969]],[[120513,120513],"mapped",[8711]],[[120514,120514],"mapped",[945]],[[120515,120515],"mapped",[946]],[[120516,120516],"mapped",[947]],[[120517,120517],"mapped",[948]],[[120518,120518],"mapped",[949]],[[120519,120519],"mapped",[950]],[[120520,120520],"mapped",[951]],[[120521,120521],"mapped",[952]],[[120522,120522],"mapped",[953]],[[120523,120523],"mapped",[954]],[[120524,120524],"mapped",[955]],[[120525,120525],"mapped",[956]],[[120526,120526],"mapped",[957]],[[120527,120527],"mapped",[958]],[[120528,120528],"mapped",[959]],[[120529,120529],"mapped",[960]],[[120530,120530],"mapped",[961]],[[120531,120532],"mapped",[963]],[[120533,120533],"mapped",[964]],[[120534,120534],"mapped",[965]],[[120535,120535],"mapped",[966]],[[120536,120536],"mapped",[967]],[[120537,120537],"mapped",[968]],[[120538,120538],"mapped",[969]],[[120539,120539],"mapped",[8706]],[[120540,120540],"mapped",[949]],[[120541,120541],"mapped",[952]],[[120542,120542],"mapped",[954]],[[120543,120543],"mapped",[966]],[[120544,120544],"mapped",[961]],[[120545,120545],"mapped",[960]],[[120546,120546],"mapped",[945]],[[120547,120547],"mapped",[946]],[[120548,120548],"mapped",[947]],[[120549,120549],"mapped",[948]],[[120550,120550],"mapped",[949]],[[120551,120551],"mapped",[950]],[[120552,120552],"mapped",[951]],[[120553,120553],"mapped",[952]],[[120554,120554],"mapped",[953]],[[120555,120555],"mapped",[954]],[[120556,120556],"mapped",[955]],[[120557,120557],"mapped",[956]],[[120558,120558],"mapped",[957]],[[120559,120559],"mapped",[958]],[[120560,120560],"mapped",[959]],[[120561,120561],"mapped",[960]],[[120562,120562],"mapped",[961]],[[120563,120563],"mapped",[952]],[[120564,120564],"mapped",[963]],[[120565,120565],"mapped",[964]],[[120566,120566],"mapped",[965]],[[120567,120567],"mapped",[966]],[[120568,120568],"mapped",[967]],[[120569,120569],"mapped",[968]],[[120570,120570],"mapped",[969]],[[120571,120571],"mapped",[8711]],[[120572,120572],"mapped",[945]],[[120573,120573],"mapped",[946]],[[120574,120574],"mapped",[947]],[[120575,120575],"mapped",[948]],[[120576,120576],"mapped",[949]],[[120577,120577],"mapped",[950]],[[120578,120578],"mapped",[951]],[[120579,120579],"mapped",[952]],[[120580,120580],"mapped",[953]],[[120581,120581],"mapped",[954]],[[120582,120582],"mapped",[955]],[[120583,120583],"mapped",[956]],[[120584,120584],"mapped",[957]],[[120585,120585],"mapped",[958]],[[120586,120586],"mapped",[959]],[[120587,120587],"mapped",[960]],[[120588,120588],"mapped",[961]],[[120589,120590],"mapped",[963]],[[120591,120591],"mapped",[964]],[[120592,120592],"mapped",[965]],[[120593,120593],"mapped",[966]],[[120594,120594],"mapped",[967]],[[120595,120595],"mapped",[968]],[[120596,120596],"mapped",[969]],[[120597,120597],"mapped",[8706]],[[120598,120598],"mapped",[949]],[[120599,120599],"mapped",[952]],[[120600,120600],"mapped",[954]],[[120601,120601],"mapped",[966]],[[120602,120602],"mapped",[961]],[[120603,120603],"mapped",[960]],[[120604,120604],"mapped",[945]],[[120605,120605],"mapped",[946]],[[120606,120606],"mapped",[947]],[[120607,120607],"mapped",[948]],[[120608,120608],"mapped",[949]],[[120609,120609],"mapped",[950]],[[120610,120610],"mapped",[951]],[[120611,120611],"mapped",[952]],[[120612,120612],"mapped",[953]],[[120613,120613],"mapped",[954]],[[120614,120614],"mapped",[955]],[[120615,120615],"mapped",[956]],[[120616,120616],"mapped",[957]],[[120617,120617],"mapped",[958]],[[120618,120618],"mapped",[959]],[[120619,120619],"mapped",[960]],[[120620,120620],"mapped",[961]],[[120621,120621],"mapped",[952]],[[120622,120622],"mapped",[963]],[[120623,120623],"mapped",[964]],[[120624,120624],"mapped",[965]],[[120625,120625],"mapped",[966]],[[120626,120626],"mapped",[967]],[[120627,120627],"mapped",[968]],[[120628,120628],"mapped",[969]],[[120629,120629],"mapped",[8711]],[[120630,120630],"mapped",[945]],[[120631,120631],"mapped",[946]],[[120632,120632],"mapped",[947]],[[120633,120633],"mapped",[948]],[[120634,120634],"mapped",[949]],[[120635,120635],"mapped",[950]],[[120636,120636],"mapped",[951]],[[120637,120637],"mapped",[952]],[[120638,120638],"mapped",[953]],[[120639,120639],"mapped",[954]],[[120640,120640],"mapped",[955]],[[120641,120641],"mapped",[956]],[[120642,120642],"mapped",[957]],[[120643,120643],"mapped",[958]],[[120644,120644],"mapped",[959]],[[120645,120645],"mapped",[960]],[[120646,120646],"mapped",[961]],[[120647,120648],"mapped",[963]],[[120649,120649],"mapped",[964]],[[120650,120650],"mapped",[965]],[[120651,120651],"mapped",[966]],[[120652,120652],"mapped",[967]],[[120653,120653],"mapped",[968]],[[120654,120654],"mapped",[969]],[[120655,120655],"mapped",[8706]],[[120656,120656],"mapped",[949]],[[120657,120657],"mapped",[952]],[[120658,120658],"mapped",[954]],[[120659,120659],"mapped",[966]],[[120660,120660],"mapped",[961]],[[120661,120661],"mapped",[960]],[[120662,120662],"mapped",[945]],[[120663,120663],"mapped",[946]],[[120664,120664],"mapped",[947]],[[120665,120665],"mapped",[948]],[[120666,120666],"mapped",[949]],[[120667,120667],"mapped",[950]],[[120668,120668],"mapped",[951]],[[120669,120669],"mapped",[952]],[[120670,120670],"mapped",[953]],[[120671,120671],"mapped",[954]],[[120672,120672],"mapped",[955]],[[120673,120673],"mapped",[956]],[[120674,120674],"mapped",[957]],[[120675,120675],"mapped",[958]],[[120676,120676],"mapped",[959]],[[120677,120677],"mapped",[960]],[[120678,120678],"mapped",[961]],[[120679,120679],"mapped",[952]],[[120680,120680],"mapped",[963]],[[120681,120681],"mapped",[964]],[[120682,120682],"mapped",[965]],[[120683,120683],"mapped",[966]],[[120684,120684],"mapped",[967]],[[120685,120685],"mapped",[968]],[[120686,120686],"mapped",[969]],[[120687,120687],"mapped",[8711]],[[120688,120688],"mapped",[945]],[[120689,120689],"mapped",[946]],[[120690,120690],"mapped",[947]],[[120691,120691],"mapped",[948]],[[120692,120692],"mapped",[949]],[[120693,120693],"mapped",[950]],[[120694,120694],"mapped",[951]],[[120695,120695],"mapped",[952]],[[120696,120696],"mapped",[953]],[[120697,120697],"mapped",[954]],[[120698,120698],"mapped",[955]],[[120699,120699],"mapped",[956]],[[120700,120700],"mapped",[957]],[[120701,120701],"mapped",[958]],[[120702,120702],"mapped",[959]],[[120703,120703],"mapped",[960]],[[120704,120704],"mapped",[961]],[[120705,120706],"mapped",[963]],[[120707,120707],"mapped",[964]],[[120708,120708],"mapped",[965]],[[120709,120709],"mapped",[966]],[[120710,120710],"mapped",[967]],[[120711,120711],"mapped",[968]],[[120712,120712],"mapped",[969]],[[120713,120713],"mapped",[8706]],[[120714,120714],"mapped",[949]],[[120715,120715],"mapped",[952]],[[120716,120716],"mapped",[954]],[[120717,120717],"mapped",[966]],[[120718,120718],"mapped",[961]],[[120719,120719],"mapped",[960]],[[120720,120720],"mapped",[945]],[[120721,120721],"mapped",[946]],[[120722,120722],"mapped",[947]],[[120723,120723],"mapped",[948]],[[120724,120724],"mapped",[949]],[[120725,120725],"mapped",[950]],[[120726,120726],"mapped",[951]],[[120727,120727],"mapped",[952]],[[120728,120728],"mapped",[953]],[[120729,120729],"mapped",[954]],[[120730,120730],"mapped",[955]],[[120731,120731],"mapped",[956]],[[120732,120732],"mapped",[957]],[[120733,120733],"mapped",[958]],[[120734,120734],"mapped",[959]],[[120735,120735],"mapped",[960]],[[120736,120736],"mapped",[961]],[[120737,120737],"mapped",[952]],[[120738,120738],"mapped",[963]],[[120739,120739],"mapped",[964]],[[120740,120740],"mapped",[965]],[[120741,120741],"mapped",[966]],[[120742,120742],"mapped",[967]],[[120743,120743],"mapped",[968]],[[120744,120744],"mapped",[969]],[[120745,120745],"mapped",[8711]],[[120746,120746],"mapped",[945]],[[120747,120747],"mapped",[946]],[[120748,120748],"mapped",[947]],[[120749,120749],"mapped",[948]],[[120750,120750],"mapped",[949]],[[120751,120751],"mapped",[950]],[[120752,120752],"mapped",[951]],[[120753,120753],"mapped",[952]],[[120754,120754],"mapped",[953]],[[120755,120755],"mapped",[954]],[[120756,120756],"mapped",[955]],[[120757,120757],"mapped",[956]],[[120758,120758],"mapped",[957]],[[120759,120759],"mapped",[958]],[[120760,120760],"mapped",[959]],[[120761,120761],"mapped",[960]],[[120762,120762],"mapped",[961]],[[120763,120764],"mapped",[963]],[[120765,120765],"mapped",[964]],[[120766,120766],"mapped",[965]],[[120767,120767],"mapped",[966]],[[120768,120768],"mapped",[967]],[[120769,120769],"mapped",[968]],[[120770,120770],"mapped",[969]],[[120771,120771],"mapped",[8706]],[[120772,120772],"mapped",[949]],[[120773,120773],"mapped",[952]],[[120774,120774],"mapped",[954]],[[120775,120775],"mapped",[966]],[[120776,120776],"mapped",[961]],[[120777,120777],"mapped",[960]],[[120778,120779],"mapped",[989]],[[120780,120781],"disallowed"],[[120782,120782],"mapped",[48]],[[120783,120783],"mapped",[49]],[[120784,120784],"mapped",[50]],[[120785,120785],"mapped",[51]],[[120786,120786],"mapped",[52]],[[120787,120787],"mapped",[53]],[[120788,120788],"mapped",[54]],[[120789,120789],"mapped",[55]],[[120790,120790],"mapped",[56]],[[120791,120791],"mapped",[57]],[[120792,120792],"mapped",[48]],[[120793,120793],"mapped",[49]],[[120794,120794],"mapped",[50]],[[120795,120795],"mapped",[51]],[[120796,120796],"mapped",[52]],[[120797,120797],"mapped",[53]],[[120798,120798],"mapped",[54]],[[120799,120799],"mapped",[55]],[[120800,120800],"mapped",[56]],[[120801,120801],"mapped",[57]],[[120802,120802],"mapped",[48]],[[120803,120803],"mapped",[49]],[[120804,120804],"mapped",[50]],[[120805,120805],"mapped",[51]],[[120806,120806],"mapped",[52]],[[120807,120807],"mapped",[53]],[[120808,120808],"mapped",[54]],[[120809,120809],"mapped",[55]],[[120810,120810],"mapped",[56]],[[120811,120811],"mapped",[57]],[[120812,120812],"mapped",[48]],[[120813,120813],"mapped",[49]],[[120814,120814],"mapped",[50]],[[120815,120815],"mapped",[51]],[[120816,120816],"mapped",[52]],[[120817,120817],"mapped",[53]],[[120818,120818],"mapped",[54]],[[120819,120819],"mapped",[55]],[[120820,120820],"mapped",[56]],[[120821,120821],"mapped",[57]],[[120822,120822],"mapped",[48]],[[120823,120823],"mapped",[49]],[[120824,120824],"mapped",[50]],[[120825,120825],"mapped",[51]],[[120826,120826],"mapped",[52]],[[120827,120827],"mapped",[53]],[[120828,120828],"mapped",[54]],[[120829,120829],"mapped",[55]],[[120830,120830],"mapped",[56]],[[120831,120831],"mapped",[57]],[[120832,121343],"valid",[],"NV8"],[[121344,121398],"valid"],[[121399,121402],"valid",[],"NV8"],[[121403,121452],"valid"],[[121453,121460],"valid",[],"NV8"],[[121461,121461],"valid"],[[121462,121475],"valid",[],"NV8"],[[121476,121476],"valid"],[[121477,121483],"valid",[],"NV8"],[[121484,121498],"disallowed"],[[121499,121503],"valid"],[[121504,121504],"disallowed"],[[121505,121519],"valid"],[[121520,124927],"disallowed"],[[124928,125124],"valid"],[[125125,125126],"disallowed"],[[125127,125135],"valid",[],"NV8"],[[125136,125142],"valid"],[[125143,126463],"disallowed"],[[126464,126464],"mapped",[1575]],[[126465,126465],"mapped",[1576]],[[126466,126466],"mapped",[1580]],[[126467,126467],"mapped",[1583]],[[126468,126468],"disallowed"],[[126469,126469],"mapped",[1608]],[[126470,126470],"mapped",[1586]],[[126471,126471],"mapped",[1581]],[[126472,126472],"mapped",[1591]],[[126473,126473],"mapped",[1610]],[[126474,126474],"mapped",[1603]],[[126475,126475],"mapped",[1604]],[[126476,126476],"mapped",[1605]],[[126477,126477],"mapped",[1606]],[[126478,126478],"mapped",[1587]],[[126479,126479],"mapped",[1593]],[[126480,126480],"mapped",[1601]],[[126481,126481],"mapped",[1589]],[[126482,126482],"mapped",[1602]],[[126483,126483],"mapped",[1585]],[[126484,126484],"mapped",[1588]],[[126485,126485],"mapped",[1578]],[[126486,126486],"mapped",[1579]],[[126487,126487],"mapped",[1582]],[[126488,126488],"mapped",[1584]],[[126489,126489],"mapped",[1590]],[[126490,126490],"mapped",[1592]],[[126491,126491],"mapped",[1594]],[[126492,126492],"mapped",[1646]],[[126493,126493],"mapped",[1722]],[[126494,126494],"mapped",[1697]],[[126495,126495],"mapped",[1647]],[[126496,126496],"disallowed"],[[126497,126497],"mapped",[1576]],[[126498,126498],"mapped",[1580]],[[126499,126499],"disallowed"],[[126500,126500],"mapped",[1607]],[[126501,126502],"disallowed"],[[126503,126503],"mapped",[1581]],[[126504,126504],"disallowed"],[[126505,126505],"mapped",[1610]],[[126506,126506],"mapped",[1603]],[[126507,126507],"mapped",[1604]],[[126508,126508],"mapped",[1605]],[[126509,126509],"mapped",[1606]],[[126510,126510],"mapped",[1587]],[[126511,126511],"mapped",[1593]],[[126512,126512],"mapped",[1601]],[[126513,126513],"mapped",[1589]],[[126514,126514],"mapped",[1602]],[[126515,126515],"disallowed"],[[126516,126516],"mapped",[1588]],[[126517,126517],"mapped",[1578]],[[126518,126518],"mapped",[1579]],[[126519,126519],"mapped",[1582]],[[126520,126520],"disallowed"],[[126521,126521],"mapped",[1590]],[[126522,126522],"disallowed"],[[126523,126523],"mapped",[1594]],[[126524,126529],"disallowed"],[[126530,126530],"mapped",[1580]],[[126531,126534],"disallowed"],[[126535,126535],"mapped",[1581]],[[126536,126536],"disallowed"],[[126537,126537],"mapped",[1610]],[[126538,126538],"disallowed"],[[126539,126539],"mapped",[1604]],[[126540,126540],"disallowed"],[[126541,126541],"mapped",[1606]],[[126542,126542],"mapped",[1587]],[[126543,126543],"mapped",[1593]],[[126544,126544],"disallowed"],[[126545,126545],"mapped",[1589]],[[126546,126546],"mapped",[1602]],[[126547,126547],"disallowed"],[[126548,126548],"mapped",[1588]],[[126549,126550],"disallowed"],[[126551,126551],"mapped",[1582]],[[126552,126552],"disallowed"],[[126553,126553],"mapped",[1590]],[[126554,126554],"disallowed"],[[126555,126555],"mapped",[1594]],[[126556,126556],"disallowed"],[[126557,126557],"mapped",[1722]],[[126558,126558],"disallowed"],[[126559,126559],"mapped",[1647]],[[126560,126560],"disallowed"],[[126561,126561],"mapped",[1576]],[[126562,126562],"mapped",[1580]],[[126563,126563],"disallowed"],[[126564,126564],"mapped",[1607]],[[126565,126566],"disallowed"],[[126567,126567],"mapped",[1581]],[[126568,126568],"mapped",[1591]],[[126569,126569],"mapped",[1610]],[[126570,126570],"mapped",[1603]],[[126571,126571],"disallowed"],[[126572,126572],"mapped",[1605]],[[126573,126573],"mapped",[1606]],[[126574,126574],"mapped",[1587]],[[126575,126575],"mapped",[1593]],[[126576,126576],"mapped",[1601]],[[126577,126577],"mapped",[1589]],[[126578,126578],"mapped",[1602]],[[126579,126579],"disallowed"],[[126580,126580],"mapped",[1588]],[[126581,126581],"mapped",[1578]],[[126582,126582],"mapped",[1579]],[[126583,126583],"mapped",[1582]],[[126584,126584],"disallowed"],[[126585,126585],"mapped",[1590]],[[126586,126586],"mapped",[1592]],[[126587,126587],"mapped",[1594]],[[126588,126588],"mapped",[1646]],[[126589,126589],"disallowed"],[[126590,126590],"mapped",[1697]],[[126591,126591],"disallowed"],[[126592,126592],"mapped",[1575]],[[126593,126593],"mapped",[1576]],[[126594,126594],"mapped",[1580]],[[126595,126595],"mapped",[1583]],[[126596,126596],"mapped",[1607]],[[126597,126597],"mapped",[1608]],[[126598,126598],"mapped",[1586]],[[126599,126599],"mapped",[1581]],[[126600,126600],"mapped",[1591]],[[126601,126601],"mapped",[1610]],[[126602,126602],"disallowed"],[[126603,126603],"mapped",[1604]],[[126604,126604],"mapped",[1605]],[[126605,126605],"mapped",[1606]],[[126606,126606],"mapped",[1587]],[[126607,126607],"mapped",[1593]],[[126608,126608],"mapped",[1601]],[[126609,126609],"mapped",[1589]],[[126610,126610],"mapped",[1602]],[[126611,126611],"mapped",[1585]],[[126612,126612],"mapped",[1588]],[[126613,126613],"mapped",[1578]],[[126614,126614],"mapped",[1579]],[[126615,126615],"mapped",[1582]],[[126616,126616],"mapped",[1584]],[[126617,126617],"mapped",[1590]],[[126618,126618],"mapped",[1592]],[[126619,126619],"mapped",[1594]],[[126620,126624],"disallowed"],[[126625,126625],"mapped",[1576]],[[126626,126626],"mapped",[1580]],[[126627,126627],"mapped",[1583]],[[126628,126628],"disallowed"],[[126629,126629],"mapped",[1608]],[[126630,126630],"mapped",[1586]],[[126631,126631],"mapped",[1581]],[[126632,126632],"mapped",[1591]],[[126633,126633],"mapped",[1610]],[[126634,126634],"disallowed"],[[126635,126635],"mapped",[1604]],[[126636,126636],"mapped",[1605]],[[126637,126637],"mapped",[1606]],[[126638,126638],"mapped",[1587]],[[126639,126639],"mapped",[1593]],[[126640,126640],"mapped",[1601]],[[126641,126641],"mapped",[1589]],[[126642,126642],"mapped",[1602]],[[126643,126643],"mapped",[1585]],[[126644,126644],"mapped",[1588]],[[126645,126645],"mapped",[1578]],[[126646,126646],"mapped",[1579]],[[126647,126647],"mapped",[1582]],[[126648,126648],"mapped",[1584]],[[126649,126649],"mapped",[1590]],[[126650,126650],"mapped",[1592]],[[126651,126651],"mapped",[1594]],[[126652,126703],"disallowed"],[[126704,126705],"valid",[],"NV8"],[[126706,126975],"disallowed"],[[126976,127019],"valid",[],"NV8"],[[127020,127023],"disallowed"],[[127024,127123],"valid",[],"NV8"],[[127124,127135],"disallowed"],[[127136,127150],"valid",[],"NV8"],[[127151,127152],"disallowed"],[[127153,127166],"valid",[],"NV8"],[[127167,127167],"valid",[],"NV8"],[[127168,127168],"disallowed"],[[127169,127183],"valid",[],"NV8"],[[127184,127184],"disallowed"],[[127185,127199],"valid",[],"NV8"],[[127200,127221],"valid",[],"NV8"],[[127222,127231],"disallowed"],[[127232,127232],"disallowed"],[[127233,127233],"disallowed_STD3_mapped",[48,44]],[[127234,127234],"disallowed_STD3_mapped",[49,44]],[[127235,127235],"disallowed_STD3_mapped",[50,44]],[[127236,127236],"disallowed_STD3_mapped",[51,44]],[[127237,127237],"disallowed_STD3_mapped",[52,44]],[[127238,127238],"disallowed_STD3_mapped",[53,44]],[[127239,127239],"disallowed_STD3_mapped",[54,44]],[[127240,127240],"disallowed_STD3_mapped",[55,44]],[[127241,127241],"disallowed_STD3_mapped",[56,44]],[[127242,127242],"disallowed_STD3_mapped",[57,44]],[[127243,127244],"valid",[],"NV8"],[[127245,127247],"disallowed"],[[127248,127248],"disallowed_STD3_mapped",[40,97,41]],[[127249,127249],"disallowed_STD3_mapped",[40,98,41]],[[127250,127250],"disallowed_STD3_mapped",[40,99,41]],[[127251,127251],"disallowed_STD3_mapped",[40,100,41]],[[127252,127252],"disallowed_STD3_mapped",[40,101,41]],[[127253,127253],"disallowed_STD3_mapped",[40,102,41]],[[127254,127254],"disallowed_STD3_mapped",[40,103,41]],[[127255,127255],"disallowed_STD3_mapped",[40,104,41]],[[127256,127256],"disallowed_STD3_mapped",[40,105,41]],[[127257,127257],"disallowed_STD3_mapped",[40,106,41]],[[127258,127258],"disallowed_STD3_mapped",[40,107,41]],[[127259,127259],"disallowed_STD3_mapped",[40,108,41]],[[127260,127260],"disallowed_STD3_mapped",[40,109,41]],[[127261,127261],"disallowed_STD3_mapped",[40,110,41]],[[127262,127262],"disallowed_STD3_mapped",[40,111,41]],[[127263,127263],"disallowed_STD3_mapped",[40,112,41]],[[127264,127264],"disallowed_STD3_mapped",[40,113,41]],[[127265,127265],"disallowed_STD3_mapped",[40,114,41]],[[127266,127266],"disallowed_STD3_mapped",[40,115,41]],[[127267,127267],"disallowed_STD3_mapped",[40,116,41]],[[127268,127268],"disallowed_STD3_mapped",[40,117,41]],[[127269,127269],"disallowed_STD3_mapped",[40,118,41]],[[127270,127270],"disallowed_STD3_mapped",[40,119,41]],[[127271,127271],"disallowed_STD3_mapped",[40,120,41]],[[127272,127272],"disallowed_STD3_mapped",[40,121,41]],[[127273,127273],"disallowed_STD3_mapped",[40,122,41]],[[127274,127274],"mapped",[12308,115,12309]],[[127275,127275],"mapped",[99]],[[127276,127276],"mapped",[114]],[[127277,127277],"mapped",[99,100]],[[127278,127278],"mapped",[119,122]],[[127279,127279],"disallowed"],[[127280,127280],"mapped",[97]],[[127281,127281],"mapped",[98]],[[127282,127282],"mapped",[99]],[[127283,127283],"mapped",[100]],[[127284,127284],"mapped",[101]],[[127285,127285],"mapped",[102]],[[127286,127286],"mapped",[103]],[[127287,127287],"mapped",[104]],[[127288,127288],"mapped",[105]],[[127289,127289],"mapped",[106]],[[127290,127290],"mapped",[107]],[[127291,127291],"mapped",[108]],[[127292,127292],"mapped",[109]],[[127293,127293],"mapped",[110]],[[127294,127294],"mapped",[111]],[[127295,127295],"mapped",[112]],[[127296,127296],"mapped",[113]],[[127297,127297],"mapped",[114]],[[127298,127298],"mapped",[115]],[[127299,127299],"mapped",[116]],[[127300,127300],"mapped",[117]],[[127301,127301],"mapped",[118]],[[127302,127302],"mapped",[119]],[[127303,127303],"mapped",[120]],[[127304,127304],"mapped",[121]],[[127305,127305],"mapped",[122]],[[127306,127306],"mapped",[104,118]],[[127307,127307],"mapped",[109,118]],[[127308,127308],"mapped",[115,100]],[[127309,127309],"mapped",[115,115]],[[127310,127310],"mapped",[112,112,118]],[[127311,127311],"mapped",[119,99]],[[127312,127318],"valid",[],"NV8"],[[127319,127319],"valid",[],"NV8"],[[127320,127326],"valid",[],"NV8"],[[127327,127327],"valid",[],"NV8"],[[127328,127337],"valid",[],"NV8"],[[127338,127338],"mapped",[109,99]],[[127339,127339],"mapped",[109,100]],[[127340,127343],"disallowed"],[[127344,127352],"valid",[],"NV8"],[[127353,127353],"valid",[],"NV8"],[[127354,127354],"valid",[],"NV8"],[[127355,127356],"valid",[],"NV8"],[[127357,127358],"valid",[],"NV8"],[[127359,127359],"valid",[],"NV8"],[[127360,127369],"valid",[],"NV8"],[[127370,127373],"valid",[],"NV8"],[[127374,127375],"valid",[],"NV8"],[[127376,127376],"mapped",[100,106]],[[127377,127386],"valid",[],"NV8"],[[127387,127461],"disallowed"],[[127462,127487],"valid",[],"NV8"],[[127488,127488],"mapped",[12411,12363]],[[127489,127489],"mapped",[12467,12467]],[[127490,127490],"mapped",[12469]],[[127491,127503],"disallowed"],[[127504,127504],"mapped",[25163]],[[127505,127505],"mapped",[23383]],[[127506,127506],"mapped",[21452]],[[127507,127507],"mapped",[12487]],[[127508,127508],"mapped",[20108]],[[127509,127509],"mapped",[22810]],[[127510,127510],"mapped",[35299]],[[127511,127511],"mapped",[22825]],[[127512,127512],"mapped",[20132]],[[127513,127513],"mapped",[26144]],[[127514,127514],"mapped",[28961]],[[127515,127515],"mapped",[26009]],[[127516,127516],"mapped",[21069]],[[127517,127517],"mapped",[24460]],[[127518,127518],"mapped",[20877]],[[127519,127519],"mapped",[26032]],[[127520,127520],"mapped",[21021]],[[127521,127521],"mapped",[32066]],[[127522,127522],"mapped",[29983]],[[127523,127523],"mapped",[36009]],[[127524,127524],"mapped",[22768]],[[127525,127525],"mapped",[21561]],[[127526,127526],"mapped",[28436]],[[127527,127527],"mapped",[25237]],[[127528,127528],"mapped",[25429]],[[127529,127529],"mapped",[19968]],[[127530,127530],"mapped",[19977]],[[127531,127531],"mapped",[36938]],[[127532,127532],"mapped",[24038]],[[127533,127533],"mapped",[20013]],[[127534,127534],"mapped",[21491]],[[127535,127535],"mapped",[25351]],[[127536,127536],"mapped",[36208]],[[127537,127537],"mapped",[25171]],[[127538,127538],"mapped",[31105]],[[127539,127539],"mapped",[31354]],[[127540,127540],"mapped",[21512]],[[127541,127541],"mapped",[28288]],[[127542,127542],"mapped",[26377]],[[127543,127543],"mapped",[26376]],[[127544,127544],"mapped",[30003]],[[127545,127545],"mapped",[21106]],[[127546,127546],"mapped",[21942]],[[127547,127551],"disallowed"],[[127552,127552],"mapped",[12308,26412,12309]],[[127553,127553],"mapped",[12308,19977,12309]],[[127554,127554],"mapped",[12308,20108,12309]],[[127555,127555],"mapped",[12308,23433,12309]],[[127556,127556],"mapped",[12308,28857,12309]],[[127557,127557],"mapped",[12308,25171,12309]],[[127558,127558],"mapped",[12308,30423,12309]],[[127559,127559],"mapped",[12308,21213,12309]],[[127560,127560],"mapped",[12308,25943,12309]],[[127561,127567],"disallowed"],[[127568,127568],"mapped",[24471]],[[127569,127569],"mapped",[21487]],[[127570,127743],"disallowed"],[[127744,127776],"valid",[],"NV8"],[[127777,127788],"valid",[],"NV8"],[[127789,127791],"valid",[],"NV8"],[[127792,127797],"valid",[],"NV8"],[[127798,127798],"valid",[],"NV8"],[[127799,127868],"valid",[],"NV8"],[[127869,127869],"valid",[],"NV8"],[[127870,127871],"valid",[],"NV8"],[[127872,127891],"valid",[],"NV8"],[[127892,127903],"valid",[],"NV8"],[[127904,127940],"valid",[],"NV8"],[[127941,127941],"valid",[],"NV8"],[[127942,127946],"valid",[],"NV8"],[[127947,127950],"valid",[],"NV8"],[[127951,127955],"valid",[],"NV8"],[[127956,127967],"valid",[],"NV8"],[[127968,127984],"valid",[],"NV8"],[[127985,127991],"valid",[],"NV8"],[[127992,127999],"valid",[],"NV8"],[[128000,128062],"valid",[],"NV8"],[[128063,128063],"valid",[],"NV8"],[[128064,128064],"valid",[],"NV8"],[[128065,128065],"valid",[],"NV8"],[[128066,128247],"valid",[],"NV8"],[[128248,128248],"valid",[],"NV8"],[[128249,128252],"valid",[],"NV8"],[[128253,128254],"valid",[],"NV8"],[[128255,128255],"valid",[],"NV8"],[[128256,128317],"valid",[],"NV8"],[[128318,128319],"valid",[],"NV8"],[[128320,128323],"valid",[],"NV8"],[[128324,128330],"valid",[],"NV8"],[[128331,128335],"valid",[],"NV8"],[[128336,128359],"valid",[],"NV8"],[[128360,128377],"valid",[],"NV8"],[[128378,128378],"disallowed"],[[128379,128419],"valid",[],"NV8"],[[128420,128420],"disallowed"],[[128421,128506],"valid",[],"NV8"],[[128507,128511],"valid",[],"NV8"],[[128512,128512],"valid",[],"NV8"],[[128513,128528],"valid",[],"NV8"],[[128529,128529],"valid",[],"NV8"],[[128530,128532],"valid",[],"NV8"],[[128533,128533],"valid",[],"NV8"],[[128534,128534],"valid",[],"NV8"],[[128535,128535],"valid",[],"NV8"],[[128536,128536],"valid",[],"NV8"],[[128537,128537],"valid",[],"NV8"],[[128538,128538],"valid",[],"NV8"],[[128539,128539],"valid",[],"NV8"],[[128540,128542],"valid",[],"NV8"],[[128543,128543],"valid",[],"NV8"],[[128544,128549],"valid",[],"NV8"],[[128550,128551],"valid",[],"NV8"],[[128552,128555],"valid",[],"NV8"],[[128556,128556],"valid",[],"NV8"],[[128557,128557],"valid",[],"NV8"],[[128558,128559],"valid",[],"NV8"],[[128560,128563],"valid",[],"NV8"],[[128564,128564],"valid",[],"NV8"],[[128565,128576],"valid",[],"NV8"],[[128577,128578],"valid",[],"NV8"],[[128579,128580],"valid",[],"NV8"],[[128581,128591],"valid",[],"NV8"],[[128592,128639],"valid",[],"NV8"],[[128640,128709],"valid",[],"NV8"],[[128710,128719],"valid",[],"NV8"],[[128720,128720],"valid",[],"NV8"],[[128721,128735],"disallowed"],[[128736,128748],"valid",[],"NV8"],[[128749,128751],"disallowed"],[[128752,128755],"valid",[],"NV8"],[[128756,128767],"disallowed"],[[128768,128883],"valid",[],"NV8"],[[128884,128895],"disallowed"],[[128896,128980],"valid",[],"NV8"],[[128981,129023],"disallowed"],[[129024,129035],"valid",[],"NV8"],[[129036,129039],"disallowed"],[[129040,129095],"valid",[],"NV8"],[[129096,129103],"disallowed"],[[129104,129113],"valid",[],"NV8"],[[129114,129119],"disallowed"],[[129120,129159],"valid",[],"NV8"],[[129160,129167],"disallowed"],[[129168,129197],"valid",[],"NV8"],[[129198,129295],"disallowed"],[[129296,129304],"valid",[],"NV8"],[[129305,129407],"disallowed"],[[129408,129412],"valid",[],"NV8"],[[129413,129471],"disallowed"],[[129472,129472],"valid",[],"NV8"],[[129473,131069],"disallowed"],[[131070,131071],"disallowed"],[[131072,173782],"valid"],[[173783,173823],"disallowed"],[[173824,177972],"valid"],[[177973,177983],"disallowed"],[[177984,178205],"valid"],[[178206,178207],"disallowed"],[[178208,183969],"valid"],[[183970,194559],"disallowed"],[[194560,194560],"mapped",[20029]],[[194561,194561],"mapped",[20024]],[[194562,194562],"mapped",[20033]],[[194563,194563],"mapped",[131362]],[[194564,194564],"mapped",[20320]],[[194565,194565],"mapped",[20398]],[[194566,194566],"mapped",[20411]],[[194567,194567],"mapped",[20482]],[[194568,194568],"mapped",[20602]],[[194569,194569],"mapped",[20633]],[[194570,194570],"mapped",[20711]],[[194571,194571],"mapped",[20687]],[[194572,194572],"mapped",[13470]],[[194573,194573],"mapped",[132666]],[[194574,194574],"mapped",[20813]],[[194575,194575],"mapped",[20820]],[[194576,194576],"mapped",[20836]],[[194577,194577],"mapped",[20855]],[[194578,194578],"mapped",[132380]],[[194579,194579],"mapped",[13497]],[[194580,194580],"mapped",[20839]],[[194581,194581],"mapped",[20877]],[[194582,194582],"mapped",[132427]],[[194583,194583],"mapped",[20887]],[[194584,194584],"mapped",[20900]],[[194585,194585],"mapped",[20172]],[[194586,194586],"mapped",[20908]],[[194587,194587],"mapped",[20917]],[[194588,194588],"mapped",[168415]],[[194589,194589],"mapped",[20981]],[[194590,194590],"mapped",[20995]],[[194591,194591],"mapped",[13535]],[[194592,194592],"mapped",[21051]],[[194593,194593],"mapped",[21062]],[[194594,194594],"mapped",[21106]],[[194595,194595],"mapped",[21111]],[[194596,194596],"mapped",[13589]],[[194597,194597],"mapped",[21191]],[[194598,194598],"mapped",[21193]],[[194599,194599],"mapped",[21220]],[[194600,194600],"mapped",[21242]],[[194601,194601],"mapped",[21253]],[[194602,194602],"mapped",[21254]],[[194603,194603],"mapped",[21271]],[[194604,194604],"mapped",[21321]],[[194605,194605],"mapped",[21329]],[[194606,194606],"mapped",[21338]],[[194607,194607],"mapped",[21363]],[[194608,194608],"mapped",[21373]],[[194609,194611],"mapped",[21375]],[[194612,194612],"mapped",[133676]],[[194613,194613],"mapped",[28784]],[[194614,194614],"mapped",[21450]],[[194615,194615],"mapped",[21471]],[[194616,194616],"mapped",[133987]],[[194617,194617],"mapped",[21483]],[[194618,194618],"mapped",[21489]],[[194619,194619],"mapped",[21510]],[[194620,194620],"mapped",[21662]],[[194621,194621],"mapped",[21560]],[[194622,194622],"mapped",[21576]],[[194623,194623],"mapped",[21608]],[[194624,194624],"mapped",[21666]],[[194625,194625],"mapped",[21750]],[[194626,194626],"mapped",[21776]],[[194627,194627],"mapped",[21843]],[[194628,194628],"mapped",[21859]],[[194629,194630],"mapped",[21892]],[[194631,194631],"mapped",[21913]],[[194632,194632],"mapped",[21931]],[[194633,194633],"mapped",[21939]],[[194634,194634],"mapped",[21954]],[[194635,194635],"mapped",[22294]],[[194636,194636],"mapped",[22022]],[[194637,194637],"mapped",[22295]],[[194638,194638],"mapped",[22097]],[[194639,194639],"mapped",[22132]],[[194640,194640],"mapped",[20999]],[[194641,194641],"mapped",[22766]],[[194642,194642],"mapped",[22478]],[[194643,194643],"mapped",[22516]],[[194644,194644],"mapped",[22541]],[[194645,194645],"mapped",[22411]],[[194646,194646],"mapped",[22578]],[[194647,194647],"mapped",[22577]],[[194648,194648],"mapped",[22700]],[[194649,194649],"mapped",[136420]],[[194650,194650],"mapped",[22770]],[[194651,194651],"mapped",[22775]],[[194652,194652],"mapped",[22790]],[[194653,194653],"mapped",[22810]],[[194654,194654],"mapped",[22818]],[[194655,194655],"mapped",[22882]],[[194656,194656],"mapped",[136872]],[[194657,194657],"mapped",[136938]],[[194658,194658],"mapped",[23020]],[[194659,194659],"mapped",[23067]],[[194660,194660],"mapped",[23079]],[[194661,194661],"mapped",[23000]],[[194662,194662],"mapped",[23142]],[[194663,194663],"mapped",[14062]],[[194664,194664],"disallowed"],[[194665,194665],"mapped",[23304]],[[194666,194667],"mapped",[23358]],[[194668,194668],"mapped",[137672]],[[194669,194669],"mapped",[23491]],[[194670,194670],"mapped",[23512]],[[194671,194671],"mapped",[23527]],[[194672,194672],"mapped",[23539]],[[194673,194673],"mapped",[138008]],[[194674,194674],"mapped",[23551]],[[194675,194675],"mapped",[23558]],[[194676,194676],"disallowed"],[[194677,194677],"mapped",[23586]],[[194678,194678],"mapped",[14209]],[[194679,194679],"mapped",[23648]],[[194680,194680],"mapped",[23662]],[[194681,194681],"mapped",[23744]],[[194682,194682],"mapped",[23693]],[[194683,194683],"mapped",[138724]],[[194684,194684],"mapped",[23875]],[[194685,194685],"mapped",[138726]],[[194686,194686],"mapped",[23918]],[[194687,194687],"mapped",[23915]],[[194688,194688],"mapped",[23932]],[[194689,194689],"mapped",[24033]],[[194690,194690],"mapped",[24034]],[[194691,194691],"mapped",[14383]],[[194692,194692],"mapped",[24061]],[[194693,194693],"mapped",[24104]],[[194694,194694],"mapped",[24125]],[[194695,194695],"mapped",[24169]],[[194696,194696],"mapped",[14434]],[[194697,194697],"mapped",[139651]],[[194698,194698],"mapped",[14460]],[[194699,194699],"mapped",[24240]],[[194700,194700],"mapped",[24243]],[[194701,194701],"mapped",[24246]],[[194702,194702],"mapped",[24266]],[[194703,194703],"mapped",[172946]],[[194704,194704],"mapped",[24318]],[[194705,194706],"mapped",[140081]],[[194707,194707],"mapped",[33281]],[[194708,194709],"mapped",[24354]],[[194710,194710],"mapped",[14535]],[[194711,194711],"mapped",[144056]],[[194712,194712],"mapped",[156122]],[[194713,194713],"mapped",[24418]],[[194714,194714],"mapped",[24427]],[[194715,194715],"mapped",[14563]],[[194716,194716],"mapped",[24474]],[[194717,194717],"mapped",[24525]],[[194718,194718],"mapped",[24535]],[[194719,194719],"mapped",[24569]],[[194720,194720],"mapped",[24705]],[[194721,194721],"mapped",[14650]],[[194722,194722],"mapped",[14620]],[[194723,194723],"mapped",[24724]],[[194724,194724],"mapped",[141012]],[[194725,194725],"mapped",[24775]],[[194726,194726],"mapped",[24904]],[[194727,194727],"mapped",[24908]],[[194728,194728],"mapped",[24910]],[[194729,194729],"mapped",[24908]],[[194730,194730],"mapped",[24954]],[[194731,194731],"mapped",[24974]],[[194732,194732],"mapped",[25010]],[[194733,194733],"mapped",[24996]],[[194734,194734],"mapped",[25007]],[[194735,194735],"mapped",[25054]],[[194736,194736],"mapped",[25074]],[[194737,194737],"mapped",[25078]],[[194738,194738],"mapped",[25104]],[[194739,194739],"mapped",[25115]],[[194740,194740],"mapped",[25181]],[[194741,194741],"mapped",[25265]],[[194742,194742],"mapped",[25300]],[[194743,194743],"mapped",[25424]],[[194744,194744],"mapped",[142092]],[[194745,194745],"mapped",[25405]],[[194746,194746],"mapped",[25340]],[[194747,194747],"mapped",[25448]],[[194748,194748],"mapped",[25475]],[[194749,194749],"mapped",[25572]],[[194750,194750],"mapped",[142321]],[[194751,194751],"mapped",[25634]],[[194752,194752],"mapped",[25541]],[[194753,194753],"mapped",[25513]],[[194754,194754],"mapped",[14894]],[[194755,194755],"mapped",[25705]],[[194756,194756],"mapped",[25726]],[[194757,194757],"mapped",[25757]],[[194758,194758],"mapped",[25719]],[[194759,194759],"mapped",[14956]],[[194760,194760],"mapped",[25935]],[[194761,194761],"mapped",[25964]],[[194762,194762],"mapped",[143370]],[[194763,194763],"mapped",[26083]],[[194764,194764],"mapped",[26360]],[[194765,194765],"mapped",[26185]],[[194766,194766],"mapped",[15129]],[[194767,194767],"mapped",[26257]],[[194768,194768],"mapped",[15112]],[[194769,194769],"mapped",[15076]],[[194770,194770],"mapped",[20882]],[[194771,194771],"mapped",[20885]],[[194772,194772],"mapped",[26368]],[[194773,194773],"mapped",[26268]],[[194774,194774],"mapped",[32941]],[[194775,194775],"mapped",[17369]],[[194776,194776],"mapped",[26391]],[[194777,194777],"mapped",[26395]],[[194778,194778],"mapped",[26401]],[[194779,194779],"mapped",[26462]],[[194780,194780],"mapped",[26451]],[[194781,194781],"mapped",[144323]],[[194782,194782],"mapped",[15177]],[[194783,194783],"mapped",[26618]],[[194784,194784],"mapped",[26501]],[[194785,194785],"mapped",[26706]],[[194786,194786],"mapped",[26757]],[[194787,194787],"mapped",[144493]],[[194788,194788],"mapped",[26766]],[[194789,194789],"mapped",[26655]],[[194790,194790],"mapped",[26900]],[[194791,194791],"mapped",[15261]],[[194792,194792],"mapped",[26946]],[[194793,194793],"mapped",[27043]],[[194794,194794],"mapped",[27114]],[[194795,194795],"mapped",[27304]],[[194796,194796],"mapped",[145059]],[[194797,194797],"mapped",[27355]],[[194798,194798],"mapped",[15384]],[[194799,194799],"mapped",[27425]],[[194800,194800],"mapped",[145575]],[[194801,194801],"mapped",[27476]],[[194802,194802],"mapped",[15438]],[[194803,194803],"mapped",[27506]],[[194804,194804],"mapped",[27551]],[[194805,194805],"mapped",[27578]],[[194806,194806],"mapped",[27579]],[[194807,194807],"mapped",[146061]],[[194808,194808],"mapped",[138507]],[[194809,194809],"mapped",[146170]],[[194810,194810],"mapped",[27726]],[[194811,194811],"mapped",[146620]],[[194812,194812],"mapped",[27839]],[[194813,194813],"mapped",[27853]],[[194814,194814],"mapped",[27751]],[[194815,194815],"mapped",[27926]],[[194816,194816],"mapped",[27966]],[[194817,194817],"mapped",[28023]],[[194818,194818],"mapped",[27969]],[[194819,194819],"mapped",[28009]],[[194820,194820],"mapped",[28024]],[[194821,194821],"mapped",[28037]],[[194822,194822],"mapped",[146718]],[[194823,194823],"mapped",[27956]],[[194824,194824],"mapped",[28207]],[[194825,194825],"mapped",[28270]],[[194826,194826],"mapped",[15667]],[[194827,194827],"mapped",[28363]],[[194828,194828],"mapped",[28359]],[[194829,194829],"mapped",[147153]],[[194830,194830],"mapped",[28153]],[[194831,194831],"mapped",[28526]],[[194832,194832],"mapped",[147294]],[[194833,194833],"mapped",[147342]],[[194834,194834],"mapped",[28614]],[[194835,194835],"mapped",[28729]],[[194836,194836],"mapped",[28702]],[[194837,194837],"mapped",[28699]],[[194838,194838],"mapped",[15766]],[[194839,194839],"mapped",[28746]],[[194840,194840],"mapped",[28797]],[[194841,194841],"mapped",[28791]],[[194842,194842],"mapped",[28845]],[[194843,194843],"mapped",[132389]],[[194844,194844],"mapped",[28997]],[[194845,194845],"mapped",[148067]],[[194846,194846],"mapped",[29084]],[[194847,194847],"disallowed"],[[194848,194848],"mapped",[29224]],[[194849,194849],"mapped",[29237]],[[194850,194850],"mapped",[29264]],[[194851,194851],"mapped",[149000]],[[194852,194852],"mapped",[29312]],[[194853,194853],"mapped",[29333]],[[194854,194854],"mapped",[149301]],[[194855,194855],"mapped",[149524]],[[194856,194856],"mapped",[29562]],[[194857,194857],"mapped",[29579]],[[194858,194858],"mapped",[16044]],[[194859,194859],"mapped",[29605]],[[194860,194861],"mapped",[16056]],[[194862,194862],"mapped",[29767]],[[194863,194863],"mapped",[29788]],[[194864,194864],"mapped",[29809]],[[194865,194865],"mapped",[29829]],[[194866,194866],"mapped",[29898]],[[194867,194867],"mapped",[16155]],[[194868,194868],"mapped",[29988]],[[194869,194869],"mapped",[150582]],[[194870,194870],"mapped",[30014]],[[194871,194871],"mapped",[150674]],[[194872,194872],"mapped",[30064]],[[194873,194873],"mapped",[139679]],[[194874,194874],"mapped",[30224]],[[194875,194875],"mapped",[151457]],[[194876,194876],"mapped",[151480]],[[194877,194877],"mapped",[151620]],[[194878,194878],"mapped",[16380]],[[194879,194879],"mapped",[16392]],[[194880,194880],"mapped",[30452]],[[194881,194881],"mapped",[151795]],[[194882,194882],"mapped",[151794]],[[194883,194883],"mapped",[151833]],[[194884,194884],"mapped",[151859]],[[194885,194885],"mapped",[30494]],[[194886,194887],"mapped",[30495]],[[194888,194888],"mapped",[30538]],[[194889,194889],"mapped",[16441]],[[194890,194890],"mapped",[30603]],[[194891,194891],"mapped",[16454]],[[194892,194892],"mapped",[16534]],[[194893,194893],"mapped",[152605]],[[194894,194894],"mapped",[30798]],[[194895,194895],"mapped",[30860]],[[194896,194896],"mapped",[30924]],[[194897,194897],"mapped",[16611]],[[194898,194898],"mapped",[153126]],[[194899,194899],"mapped",[31062]],[[194900,194900],"mapped",[153242]],[[194901,194901],"mapped",[153285]],[[194902,194902],"mapped",[31119]],[[194903,194903],"mapped",[31211]],[[194904,194904],"mapped",[16687]],[[194905,194905],"mapped",[31296]],[[194906,194906],"mapped",[31306]],[[194907,194907],"mapped",[31311]],[[194908,194908],"mapped",[153980]],[[194909,194910],"mapped",[154279]],[[194911,194911],"disallowed"],[[194912,194912],"mapped",[16898]],[[194913,194913],"mapped",[154539]],[[194914,194914],"mapped",[31686]],[[194915,194915],"mapped",[31689]],[[194916,194916],"mapped",[16935]],[[194917,194917],"mapped",[154752]],[[194918,194918],"mapped",[31954]],[[194919,194919],"mapped",[17056]],[[194920,194920],"mapped",[31976]],[[194921,194921],"mapped",[31971]],[[194922,194922],"mapped",[32000]],[[194923,194923],"mapped",[155526]],[[194924,194924],"mapped",[32099]],[[194925,194925],"mapped",[17153]],[[194926,194926],"mapped",[32199]],[[194927,194927],"mapped",[32258]],[[194928,194928],"mapped",[32325]],[[194929,194929],"mapped",[17204]],[[194930,194930],"mapped",[156200]],[[194931,194931],"mapped",[156231]],[[194932,194932],"mapped",[17241]],[[194933,194933],"mapped",[156377]],[[194934,194934],"mapped",[32634]],[[194935,194935],"mapped",[156478]],[[194936,194936],"mapped",[32661]],[[194937,194937],"mapped",[32762]],[[194938,194938],"mapped",[32773]],[[194939,194939],"mapped",[156890]],[[194940,194940],"mapped",[156963]],[[194941,194941],"mapped",[32864]],[[194942,194942],"mapped",[157096]],[[194943,194943],"mapped",[32880]],[[194944,194944],"mapped",[144223]],[[194945,194945],"mapped",[17365]],[[194946,194946],"mapped",[32946]],[[194947,194947],"mapped",[33027]],[[194948,194948],"mapped",[17419]],[[194949,194949],"mapped",[33086]],[[194950,194950],"mapped",[23221]],[[194951,194951],"mapped",[157607]],[[194952,194952],"mapped",[157621]],[[194953,194953],"mapped",[144275]],[[194954,194954],"mapped",[144284]],[[194955,194955],"mapped",[33281]],[[194956,194956],"mapped",[33284]],[[194957,194957],"mapped",[36766]],[[194958,194958],"mapped",[17515]],[[194959,194959],"mapped",[33425]],[[194960,194960],"mapped",[33419]],[[194961,194961],"mapped",[33437]],[[194962,194962],"mapped",[21171]],[[194963,194963],"mapped",[33457]],[[194964,194964],"mapped",[33459]],[[194965,194965],"mapped",[33469]],[[194966,194966],"mapped",[33510]],[[194967,194967],"mapped",[158524]],[[194968,194968],"mapped",[33509]],[[194969,194969],"mapped",[33565]],[[194970,194970],"mapped",[33635]],[[194971,194971],"mapped",[33709]],[[194972,194972],"mapped",[33571]],[[194973,194973],"mapped",[33725]],[[194974,194974],"mapped",[33767]],[[194975,194975],"mapped",[33879]],[[194976,194976],"mapped",[33619]],[[194977,194977],"mapped",[33738]],[[194978,194978],"mapped",[33740]],[[194979,194979],"mapped",[33756]],[[194980,194980],"mapped",[158774]],[[194981,194981],"mapped",[159083]],[[194982,194982],"mapped",[158933]],[[194983,194983],"mapped",[17707]],[[194984,194984],"mapped",[34033]],[[194985,194985],"mapped",[34035]],[[194986,194986],"mapped",[34070]],[[194987,194987],"mapped",[160714]],[[194988,194988],"mapped",[34148]],[[194989,194989],"mapped",[159532]],[[194990,194990],"mapped",[17757]],[[194991,194991],"mapped",[17761]],[[194992,194992],"mapped",[159665]],[[194993,194993],"mapped",[159954]],[[194994,194994],"mapped",[17771]],[[194995,194995],"mapped",[34384]],[[194996,194996],"mapped",[34396]],[[194997,194997],"mapped",[34407]],[[194998,194998],"mapped",[34409]],[[194999,194999],"mapped",[34473]],[[195000,195000],"mapped",[34440]],[[195001,195001],"mapped",[34574]],[[195002,195002],"mapped",[34530]],[[195003,195003],"mapped",[34681]],[[195004,195004],"mapped",[34600]],[[195005,195005],"mapped",[34667]],[[195006,195006],"mapped",[34694]],[[195007,195007],"disallowed"],[[195008,195008],"mapped",[34785]],[[195009,195009],"mapped",[34817]],[[195010,195010],"mapped",[17913]],[[195011,195011],"mapped",[34912]],[[195012,195012],"mapped",[34915]],[[195013,195013],"mapped",[161383]],[[195014,195014],"mapped",[35031]],[[195015,195015],"mapped",[35038]],[[195016,195016],"mapped",[17973]],[[195017,195017],"mapped",[35066]],[[195018,195018],"mapped",[13499]],[[195019,195019],"mapped",[161966]],[[195020,195020],"mapped",[162150]],[[195021,195021],"mapped",[18110]],[[195022,195022],"mapped",[18119]],[[195023,195023],"mapped",[35488]],[[195024,195024],"mapped",[35565]],[[195025,195025],"mapped",[35722]],[[195026,195026],"mapped",[35925]],[[195027,195027],"mapped",[162984]],[[195028,195028],"mapped",[36011]],[[195029,195029],"mapped",[36033]],[[195030,195030],"mapped",[36123]],[[195031,195031],"mapped",[36215]],[[195032,195032],"mapped",[163631]],[[195033,195033],"mapped",[133124]],[[195034,195034],"mapped",[36299]],[[195035,195035],"mapped",[36284]],[[195036,195036],"mapped",[36336]],[[195037,195037],"mapped",[133342]],[[195038,195038],"mapped",[36564]],[[195039,195039],"mapped",[36664]],[[195040,195040],"mapped",[165330]],[[195041,195041],"mapped",[165357]],[[195042,195042],"mapped",[37012]],[[195043,195043],"mapped",[37105]],[[195044,195044],"mapped",[37137]],[[195045,195045],"mapped",[165678]],[[195046,195046],"mapped",[37147]],[[195047,195047],"mapped",[37432]],[[195048,195048],"mapped",[37591]],[[195049,195049],"mapped",[37592]],[[195050,195050],"mapped",[37500]],[[195051,195051],"mapped",[37881]],[[195052,195052],"mapped",[37909]],[[195053,195053],"mapped",[166906]],[[195054,195054],"mapped",[38283]],[[195055,195055],"mapped",[18837]],[[195056,195056],"mapped",[38327]],[[195057,195057],"mapped",[167287]],[[195058,195058],"mapped",[18918]],[[195059,195059],"mapped",[38595]],[[195060,195060],"mapped",[23986]],[[195061,195061],"mapped",[38691]],[[195062,195062],"mapped",[168261]],[[195063,195063],"mapped",[168474]],[[195064,195064],"mapped",[19054]],[[195065,195065],"mapped",[19062]],[[195066,195066],"mapped",[38880]],[[195067,195067],"mapped",[168970]],[[195068,195068],"mapped",[19122]],[[195069,195069],"mapped",[169110]],[[195070,195071],"mapped",[38923]],[[195072,195072],"mapped",[38953]],[[195073,195073],"mapped",[169398]],[[195074,195074],"mapped",[39138]],[[195075,195075],"mapped",[19251]],[[195076,195076],"mapped",[39209]],[[195077,195077],"mapped",[39335]],[[195078,195078],"mapped",[39362]],[[195079,195079],"mapped",[39422]],[[195080,195080],"mapped",[19406]],[[195081,195081],"mapped",[170800]],[[195082,195082],"mapped",[39698]],[[195083,195083],"mapped",[40000]],[[195084,195084],"mapped",[40189]],[[195085,195085],"mapped",[19662]],[[195086,195086],"mapped",[19693]],[[195087,195087],"mapped",[40295]],[[195088,195088],"mapped",[172238]],[[195089,195089],"mapped",[19704]],[[195090,195090],"mapped",[172293]],[[195091,195091],"mapped",[172558]],[[195092,195092],"mapped",[172689]],[[195093,195093],"mapped",[40635]],[[195094,195094],"mapped",[19798]],[[195095,195095],"mapped",[40697]],[[195096,195096],"mapped",[40702]],[[195097,195097],"mapped",[40709]],[[195098,195098],"mapped",[40719]],[[195099,195099],"mapped",[40726]],[[195100,195100],"mapped",[40763]],[[195101,195101],"mapped",[173568]],[[195102,196605],"disallowed"],[[196606,196607],"disallowed"],[[196608,262141],"disallowed"],[[262142,262143],"disallowed"],[[262144,327677],"disallowed"],[[327678,327679],"disallowed"],[[327680,393213],"disallowed"],[[393214,393215],"disallowed"],[[393216,458749],"disallowed"],[[458750,458751],"disallowed"],[[458752,524285],"disallowed"],[[524286,524287],"disallowed"],[[524288,589821],"disallowed"],[[589822,589823],"disallowed"],[[589824,655357],"disallowed"],[[655358,655359],"disallowed"],[[655360,720893],"disallowed"],[[720894,720895],"disallowed"],[[720896,786429],"disallowed"],[[786430,786431],"disallowed"],[[786432,851965],"disallowed"],[[851966,851967],"disallowed"],[[851968,917501],"disallowed"],[[917502,917503],"disallowed"],[[917504,917504],"disallowed"],[[917505,917505],"disallowed"],[[917506,917535],"disallowed"],[[917536,917631],"disallowed"],[[917632,917759],"disallowed"],[[917760,917999],"ignored"],[[918000,983037],"disallowed"],[[983038,983039],"disallowed"],[[983040,1048573],"disallowed"],[[1048574,1048575],"disallowed"],[[1048576,1114109],"disallowed"],[[1114110,1114111],"disallowed"]]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +const core = __nccwpck_require__(37484); +const { Storage } = __nccwpck_require__(28525); +const { + S3Client, + PutObjectCommand, + CreateMultipartUploadCommand, + UploadPartCommand, + CompleteMultipartUploadCommand, + AbortMultipartUploadCommand, +} = __nccwpck_require__(53711); +const fs = (__nccwpck_require__(79896).promises); +const rawFs = __nccwpck_require__(79896); +const path = __nccwpck_require__(16928); +const cp = __nccwpck_require__(35317); +const os = __nccwpck_require__(70857); +const util = __nccwpck_require__(39023); +const exec = util.promisify(cp.exec); +function sleep(ms) { + return new Promise((res) => setTimeout(res, ms)); +} +async function run() { + try { + const skipUpload = core.getInput("skip-upload") === "true"; + if (skipUpload) { + console.log("skip-upload parameter is true, skipping cache upload"); + return; + } + const cacheHit = core.getState("cacheHit") === "true"; + if (cacheHit) { + console.log("Exact cache hit on primary key, skipping upload"); + return; + } + const localPath = core.getState("local-path"); + // Check if directory exists and is not empty + let dirExists = false; + let isNotEmpty = false; + try { + await fs.access(localPath); + dirExists = true; + const files = await fs.readdir(localPath); + isNotEmpty = files.length > 0; + } catch { + // Dir doesn't exist or error + } + if (!dirExists || !isNotEmpty) { + console.log( + "Local directory does not exist or is empty, skipping upload" + ); + return; + } + const primaryKey = core.getState("primaryKey"); + const prefix = core.getState("prefix"); + const bucketName = core.getState("bucketName"); + const provider = core.getState("provider"); + const retryAttempts = parseInt(core.getInput("retries") || "3", 10); + const retryBaseDelayMs = parseInt( + core.getInput("retry-delay-ms") || "1000", + 10 + ); + const uploadConcurrencyInput = parseInt( + core.getInput("upload-concurrency") || "32", + 10 + ); + let gcsStorage, gcsBucket, s3Client; + if (provider === "gcs") { + const base64Key = core.getState("base64Key"); + if (!base64Key) { + console.log("GCS key not available, skipping cache upload"); + return; + } + // Decode base64 key to JSON + const jsonKeyString = Buffer.from(base64Key, "base64").toString("utf-8"); + let credentials; + try { + credentials = JSON.parse(jsonKeyString); + } catch (err) { + throw new Error("Invalid base64 encoded JSON key"); + } + // Initialize GCS client + gcsStorage = new Storage({ credentials }); + gcsBucket = gcsStorage.bucket(bucketName); + } else if (provider === "s3") { + const s3AccessKey = core.getState("s3AccessKey"); + const s3SecretKey = core.getState("s3SecretKey"); + if (!s3AccessKey || !s3SecretKey) { + console.log("S3 credentials not available, skipping cache upload"); + return; + } + const s3Endpoint = core.getState("s3Endpoint"); + const s3Region = core.getState("s3Region"); + // Initialize S3 client + const s3Config = { + region: s3Region || "auto", + credentials: { + accessKeyId: s3AccessKey, + secretAccessKey: s3SecretKey, + }, + forcePathStyle: true, + }; + if (s3Endpoint) { + s3Config.endpoint = s3Endpoint; + } + s3Client = new S3Client(s3Config); + } + const primaryWithExt = primaryKey + ".tar.zst"; + const fullPath = prefix + primaryWithExt; + const tempDir = os.tmpdir(); + const tempTar = path.join(tempDir, `cache_${process.pid}.tar`); + const tempArchive = path.join(tempDir, `cache_${process.pid}.tar.zst`); + // Pack directory + await exec(`tar -cf ${tempTar} -C ${localPath} .`); + // Compress with fast preset + await exec(`zstd --long ${tempTar} -o ${tempArchive}`); + // Upload + const stats = await fs.stat(tempArchive); + const fileSize = stats.size; + if (provider === "gcs") { + // google-cloud/storage uses resumable uploads by default and has built-in retry. + // We call once; internal logic will resume on transient failures. + await gcsBucket.upload(tempArchive, { destination: fullPath, resumable: true }); + } else if (provider === "s3") { + if (fileSize < 5 * 1024 * 1024) { + // Use single PutObject for small files (<5MB) + for (let attempt = 1; attempt <= retryAttempts; attempt++) { + try { + await s3Client.send( + new PutObjectCommand({ + Bucket: bucketName, + Key: fullPath, + Body: rawFs.createReadStream(tempArchive), + }) + ); + break; // success + } catch (err) { + if (attempt >= retryAttempts) { + core.error( + `PutObject failed after ${attempt} attempts: ${err.message}` + ); + throw err; + } + const backoff = + retryBaseDelayMs * Math.pow(2, attempt - 1) + + Math.floor(Math.random() * retryBaseDelayMs); + core.warning( + `PutObject attempt ${attempt} failed: ${err.message}. Retrying in ${backoff}ms` + ); + await sleep(backoff); + } + } + } else { + // Use multipart for larger files + const PART_SIZE = 200 * 1024 * 1024; // 100MB parts for parallelism (<<5GB) + const createRes = await s3Client.send( + new CreateMultipartUploadCommand({ + Bucket: bucketName, + Key: fullPath, + }) + ); + const uploadId = createRes.UploadId; + try { + const numParts = Math.ceil(fileSize / PART_SIZE); + const uploadConcurrency = Math.max( + 1, + Math.min(uploadConcurrencyInput, numParts) + ); + const results = new Array(numParts); + async function uploadPartWithRetry(partNumber, start, end) { + for (let attempt = 1; attempt <= retryAttempts; attempt++) { + try { + const partStream = rawFs.createReadStream(tempArchive, { + start, + end: end - 1, + }); + const res = await s3Client.send( + new UploadPartCommand({ + Bucket: bucketName, + Key: fullPath, + PartNumber: partNumber, + UploadId: uploadId, + Body: partStream, + }) + ); + return { ETag: res.ETag, PartNumber: partNumber }; + } catch (err) { + if (attempt >= retryAttempts) { + core.error( + `Upload part #${partNumber} failed after ${attempt} attempts: ${err.message}` + ); + throw err; + } + const backoff = + retryBaseDelayMs * Math.pow(2, attempt - 1) + + Math.floor(Math.random() * retryBaseDelayMs); + core.warning( + `Upload part #${partNumber} attempt ${attempt} failed: ${err.message}. Retrying in ${backoff}ms` + ); + await sleep(backoff); + } + } + } + let nextIndex = 0; + async function worker() { + while (true) { + const i = nextIndex++; + if (i >= numParts) return; + const start = i * PART_SIZE; + const end = Math.min(start + PART_SIZE, fileSize); + const res = await uploadPartWithRetry(i + 1, start, end); + results[i] = res; + } + } + const workers = []; + for (let w = 0; w < uploadConcurrency; w++) { + workers.push(worker()); + } + await Promise.all(workers); + const uploadedParts = results.filter(Boolean).sort((a, b) => a.PartNumber - b.PartNumber); + await s3Client.send( + new CompleteMultipartUploadCommand({ + Bucket: bucketName, + Key: fullPath, + UploadId: uploadId, + MultipartUpload: { + Parts: uploadedParts, + }, + }) + ); + } catch (err) { + // Abort on error + await s3Client.send( + new AbortMultipartUploadCommand({ + Bucket: bucketName, + Key: fullPath, + UploadId: uploadId, + }) + ); + throw err; + } + } + } + // Clean up temps + await fs.unlink(tempTar).catch(() => {}); + await fs.unlink(tempArchive).catch(() => {}); + console.log(`Saved cache from ${localPath} to ${fullPath}`); + } catch (error) { + core.setFailed(error.message); + } +} +run(); + +module.exports = __webpack_exports__; +/******/ })() +; \ No newline at end of file diff --git a/.github/actions/cloud-cache/index.js b/.github/actions/cloud-cache/index.js new file mode 100644 index 0000000..6ad9e13 --- /dev/null +++ b/.github/actions/cloud-cache/index.js @@ -0,0 +1,440 @@ +const core = require("@actions/core"); +const { Storage } = require("@google-cloud/storage"); +const { + S3Client, + HeadObjectCommand, + GetObjectCommand, +} = require("@aws-sdk/client-s3"); +const fs = require("fs").promises; +const rawFs = require("fs"); +const path = require("path"); +const cp = require("child_process"); +const os = require("os"); +const util = require("util"); +const exec = util.promisify(cp.exec); +function sleep(ms) { + return new Promise((res) => setTimeout(res, ms)); +} +function expandTilde(inputPath) { + if (inputPath.charAt(0) === "~") { + const home = os.homedir(); + return home + inputPath.slice(1); + } + return inputPath; +} +async function run() { + try { + // Get inputs + const provider = core.getInput("provider").toLowerCase(); + const bucketName = core.getInput("bucket"); + let prefix = core.getInput("prefix"); + const primaryKeyInput = core.getInput("primary-key"); + const primaryKeyGenerator = core.getInput("primary-key-generator"); + const fallbackKeysInput = core.getInput("fallback-keys"); + const fallbackKeyGenerator = core.getInput("fallback-key-generator"); + const localPathInput = core.getInput("local-path"); + const skipDownload = core.getInput("skip-download") === "true"; + const localPath = path.resolve(process.cwd(), expandTilde(localPathInput)); + if (!primaryKeyInput && !primaryKeyGenerator) { + throw new Error( + 'Either "primary-key" or "primary-key-generator" must be provided' + ); + } + const retryAttempts = parseInt(core.getInput("retries") || "3", 10); + const retryBaseDelayMs = parseInt( + core.getInput("retry-delay-ms") || "1000", + 10 + ); + const downloadPartCount = Math.max( + 1, + parseInt(core.getInput("download-part-count") || "128", 10) + ); + const downloadConcurrencyInput = parseInt( + core.getInput("download-concurrency") || "32", + 10 + ); + // Save state for post + core.saveState("provider", provider); + core.saveState("bucketName", bucketName); + core.saveState("local-path", localPath); + let gcsStorage, gcsBucket, s3Client; + + // Only initialize storage clients if we're actually going to use them + // When skip-download is true, we don't need credentials for downloading + const needsCredentials = !skipDownload; + + if (provider === "gcs") { + const base64Key = core.getInput("gcs-key"); + if (!base64Key) { + if (needsCredentials) { + throw new Error("gcs-key is required when skip-download is false"); + } + core.warning("GCS key not provided. Cache operations will be skipped."); + core.setOutput("cache-hit", "false"); + core.setOutput("restored", "false"); + core.setOutput("path", localPath); + return; + } + core.saveState("base64Key", base64Key); + // Decode base64 key to JSON + const jsonKeyString = Buffer.from(base64Key, "base64").toString("utf-8"); + let credentials; + try { + credentials = JSON.parse(jsonKeyString); + } catch (err) { + throw new Error("Invalid base64 encoded JSON key"); + } + // Initialize GCS client + gcsStorage = new Storage({ credentials }); + gcsBucket = gcsStorage.bucket(bucketName); + } else if (provider === "s3") { + const s3AccessKey = core.getInput("s3-access-key"); + const s3SecretKey = core.getInput("s3-secret-key"); + const s3Endpoint = core.getInput("s3-endpoint"); + const s3Region = core.getInput("s3-region"); + + if (!s3AccessKey || !s3SecretKey) { + if (needsCredentials) { + throw new Error("s3-access-key and s3-secret-key are required when skip-download is false"); + } + core.warning("S3 credentials not provided. Cache operations will be skipped."); + core.setOutput("cache-hit", "false"); + core.setOutput("restored", "false"); + core.setOutput("path", localPath); + return; + } + + core.saveState("s3AccessKey", s3AccessKey); + core.saveState("s3SecretKey", s3SecretKey); + core.saveState("s3Endpoint", s3Endpoint); + core.saveState("s3Region", s3Region); + // Initialize S3 client + const s3Config = { + region: s3Region || "auto", + credentials: { + accessKeyId: s3AccessKey, + secretAccessKey: s3SecretKey, + }, + forcePathStyle: true, + }; + if (s3Endpoint) { + s3Config.endpoint = s3Endpoint; + } + s3Client = new S3Client(s3Config); + } else { + throw new Error(`Unsupported provider: ${provider}`); + } + // Normalize prefix + if (prefix && !prefix.endsWith("/")) { + prefix += "/"; + } + if (!prefix) { + prefix = ""; + } + core.saveState("prefix", prefix); + // Determine primary key (without extension) + let primary = ""; + if (primaryKeyGenerator) { + // Create temp file for PRIMARY_KEY + const primaryKeyPath = path.join( + os.tmpdir(), + `primary_key_${process.pid}.txt` + ); + await fs.writeFile(primaryKeyPath, ""); + // Create temp script file + const scriptPath = path.join( + os.tmpdir(), + `primary_gen_${process.pid}.sh` + ); + const scriptContent = `#!/bin/bash\n${primaryKeyGenerator}`; + await fs.writeFile(scriptPath, scriptContent); + await fs.chmod(scriptPath, 0o755); + // Execute the script + await new Promise((resolve, reject) => { + const child = cp.execFile(scriptPath, { + env: { ...process.env, PRIMARY_KEY: primaryKeyPath }, + }); + let stdout = ""; + let stderr = ""; + child.stdout.on("data", (data) => { + stdout += data; + }); + child.stderr.on("data", (data) => { + stderr += data; + }); + child.on("close", (code) => { + if (code !== 0) { + reject( + new Error( + `Primary script exited with code ${code}. Stderr: ${stderr}` + ) + ); + } else { + core.info(`Primary script output: ${stdout}`); + if (stderr) core.warning(`Primary script stderr: ${stderr}`); + resolve(); + } + }); + }); + // Read generated primary key + const primaryContent = await fs.readFile(primaryKeyPath, "utf-8"); + const primaryLines = primaryContent + .split("\n") + .map((k) => k.trim()) + .filter((k) => k.length > 0); + if (primaryLines.length !== 1) { + throw new Error("Primary key generator must produce exactly one key"); + } + primary = primaryLines[0]; + // Clean up temp files + await fs.unlink(scriptPath).catch(() => {}); + await fs.unlink(primaryKeyPath).catch(() => {}); + } else { + primary = primaryKeyInput.trim(); + if (!primary) { + throw new Error("Primary key is empty"); + } + } + core.saveState("primaryKey", primary); + // Optionally skip restore phase + if (skipDownload) { + core.setOutput("cache-hit", false); + core.saveState("cacheHit", false); + core.setOutput("path", localPath); + core.setOutput("restored", false); + console.log("skip-download parameter is true, skipping cache restore"); + return; + } + // Determine fallback keys (without extension) + let fallbacks = []; + if (fallbackKeyGenerator) { + // Create temp file for FALLBACK_KEYS + const fallbackKeysPath = path.join( + os.tmpdir(), + `fallback_keys_${process.pid}.txt` + ); + await fs.writeFile(fallbackKeysPath, ""); + // Create temp script file + const scriptPath = path.join( + os.tmpdir(), + `fallback_gen_${process.pid}.sh` + ); + const scriptContent = `#!/bin/bash\n${fallbackKeyGenerator}`; + await fs.writeFile(scriptPath, scriptContent); + await fs.chmod(scriptPath, 0o755); + // Execute the script + await new Promise((resolve, reject) => { + const child = cp.execFile(scriptPath, { + env: { ...process.env, FALLBACK_KEYS: fallbackKeysPath }, + }); + let stdout = ""; + let stderr = ""; + child.stdout.on("data", (data) => { + stdout += data; + }); + child.stderr.on("data", (data) => { + stderr += data; + }); + child.on("close", (code) => { + if (code !== 0) { + reject( + new Error( + `Fallback script exited with code ${code}. Stderr: ${stderr}` + ) + ); + } else { + core.info(`Fallback script output: ${stdout}`); + if (stderr) core.warning(`Fallback script stderr: ${stderr}`); + resolve(); + } + }); + }); + // Read generated fallback keys + const fallbacksContent = await fs.readFile(fallbackKeysPath, "utf-8"); + fallbacks = fallbacksContent + .split("\n") + .map((k) => k.trim()) + .filter((k) => k.length > 0); + // Clean up temp files + await fs.unlink(scriptPath).catch(() => {}); + await fs.unlink(fallbackKeysPath).catch(() => {}); + } else if (fallbackKeysInput) { + fallbacks = fallbackKeysInput + .split(",") + .map((k) => k.trim()) + .filter((k) => k.length > 0); + } + // Add extension to all keys + const primaryWithExt = primary + ".tar.zst"; + const fallbacksWithExt = fallbacks.map((k) => k + ".tar.zst"); + const keys = [primaryWithExt, ...fallbacksWithExt]; + if (keys.length === 0) { + throw new Error("No keys provided or generated"); + } + // Check existence in parallel + const existsPromises = keys.map(async (key) => { + const fullPath = prefix + key; + if (provider === "gcs") { + const [exists] = await gcsBucket.file(fullPath).exists(); + return exists; + } else if (provider === "s3") { + try { + await s3Client.send( + new HeadObjectCommand({ Bucket: bucketName, Key: fullPath }) + ); + return true; + } catch (err) { + if (err.name === "NotFound") { + return false; + } + throw err; + } + } + }); + const existsResults = await Promise.all(existsPromises); + // Find the first existing key in order + let selectedIndex = -1; + for (let i = 0; i < existsResults.length; i++) { + if (existsResults[i]) { + selectedIndex = i; + break; + } + } + const cacheHit = selectedIndex === 0; + core.setOutput("cache-hit", cacheHit); + core.saveState("cacheHit", cacheHit); + let restored = false; + if (selectedIndex !== -1) { + // Download and extract the selected archive + const selectedKey = keys[selectedIndex]; + const fullPath = prefix + selectedKey; + const tempDir = os.tmpdir(); + const tempArchive = path.join(tempDir, `cache_${process.pid}.tar.zst`); + const tempTar = path.join(tempDir, `cache_${process.pid}.tar`); + let fileSize = 0; + if (provider === "gcs") { + const file = gcsBucket.file(fullPath); + const [metadata] = await file.getMetadata(); + fileSize = Number(metadata.size); + } else if (provider === "s3") { + const head = await s3Client.send( + new HeadObjectCommand({ Bucket: bucketName, Key: fullPath }) + ); + fileSize = head.ContentLength; + } + if (fileSize === 0) { + await fs.writeFile(tempArchive, ""); + } else { + await fs.writeFile(tempArchive, ""); + await fs.truncate(tempArchive, fileSize); + // Derive part size from desired part count + const partSize = Math.max(1, Math.ceil(fileSize / downloadPartCount)); + const numParts = Math.max(1, Math.ceil(fileSize / partSize)); + const downloadConcurrency = Math.max( + 1, + Math.min(downloadConcurrencyInput, numParts) + ); + console.log( + `Downloading ${fileSize} bytes in ${numParts} parts (concurrency=${downloadConcurrency})` + ); + async function downloadPart(start, end) { + for (let attempt = 1; attempt <= retryAttempts; attempt++) { + let readStream; + let writeStream; + try { + if (provider === "gcs") { + const file = gcsBucket.file(fullPath); + readStream = file.createReadStream({ start, end }); + } else if (provider === "s3") { + const getCommand = new GetObjectCommand({ + Bucket: bucketName, + Key: fullPath, + Range: `bytes=${start}-${end}`, + }); + const response = await s3Client.send(getCommand); + readStream = response.Body; + } + writeStream = rawFs.createWriteStream(tempArchive, { + flags: "r+", + start, + }); + await new Promise((resolve, reject) => { + const onError = async (err) => { + cleanup(); + reject(err); + }; + const onFinish = () => { + cleanup(); + resolve(); + }; + const cleanup = () => { + if (readStream) { + readStream.removeListener("error", onError); + } + if (writeStream) { + writeStream.removeListener("error", onError); + writeStream.removeListener("finish", onFinish); + } + }; + writeStream.on("finish", onFinish); + writeStream.on("error", onError); + readStream.on("error", onError); + readStream.pipe(writeStream); + }); + return; // success + } catch (err) { + if (attempt >= retryAttempts) { + core.error( + `Download part ${start}-${end} failed after ${attempt} attempts: ${err.message}` + ); + throw err; + } + const backoff = + retryBaseDelayMs * Math.pow(2, attempt - 1) + + Math.floor(Math.random() * retryBaseDelayMs); + core.warning( + `Download part ${start}-${end} attempt ${attempt} failed: ${err.message}. Retrying in ${backoff}ms` + ); + await sleep(backoff); + } + } + } + let nextIndex = 0; + async function worker() { + while (true) { + const i = nextIndex++; + if (i >= numParts) return; + const start = i * partSize; + const end = Math.min(start + partSize - 1, fileSize - 1); + if (start > end) continue; + await downloadPart(start, end); + } + } + const workers = []; + for (let w = 0; w < downloadConcurrency; w++) { + workers.push(worker()); + } + await Promise.all(workers); + } + // Decompress + await exec(`zstd -d ${tempArchive} -o ${tempTar}`); + // Create local directory if needed + await fs.mkdir(localPath, { recursive: true }); + // Extract + await exec(`tar -xf ${tempTar} -C ${localPath}`); + // Clean up temps + await fs.unlink(tempArchive).catch(() => {}); + await fs.unlink(tempTar).catch(() => {}); + restored = true; + console.log(`Restored cache from ${fullPath} to ${localPath}`); + } else { + console.log("Cache miss: no matching keys found"); + } + // Set outputs + core.setOutput("path", localPath); + core.setOutput("restored", restored); + } catch (error) { + core.setFailed(error.message); + } +} +run(); diff --git a/.github/actions/cloud-cache/package-lock.json b/.github/actions/cloud-cache/package-lock.json new file mode 100644 index 0000000..fcaa083 --- /dev/null +++ b/.github/actions/cloud-cache/package-lock.json @@ -0,0 +1,2473 @@ +{ + "name": "cloud-cache", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "cloud-cache", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@actions/core": "^1.10.1", + "@aws-sdk/client-s3": "^3.650.1", + "@google-cloud/storage": "^7.12.1" + }, + "devDependencies": { + "@vercel/ncc": "^0.38.3" + } + }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" + }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.859.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.859.0.tgz", + "integrity": "sha512-oFLHZX1X6o54ZlweubtSVvQDz15JiNrgDD7KeMZT2MwxiI3axPcHzTo2uizjj5mgNapmYjRmQS5c1c63dvruVA==", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.858.0", + "@aws-sdk/credential-provider-node": "3.859.0", + "@aws-sdk/middleware-bucket-endpoint": "3.840.0", + "@aws-sdk/middleware-expect-continue": "3.840.0", + "@aws-sdk/middleware-flexible-checksums": "3.858.0", + "@aws-sdk/middleware-host-header": "3.840.0", + "@aws-sdk/middleware-location-constraint": "3.840.0", + "@aws-sdk/middleware-logger": "3.840.0", + "@aws-sdk/middleware-recursion-detection": "3.840.0", + "@aws-sdk/middleware-sdk-s3": "3.858.0", + "@aws-sdk/middleware-ssec": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.858.0", + "@aws-sdk/region-config-resolver": "3.840.0", + "@aws-sdk/signature-v4-multi-region": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.848.0", + "@aws-sdk/util-user-agent-browser": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.858.0", + "@aws-sdk/xml-builder": "3.821.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.7.2", + "@smithy/eventstream-serde-browser": "^4.0.4", + "@smithy/eventstream-serde-config-resolver": "^4.1.2", + "@smithy/eventstream-serde-node": "^4.0.4", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/hash-blob-browser": "^4.0.4", + "@smithy/hash-node": "^4.0.4", + "@smithy/hash-stream-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/md5-js": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.17", + "@smithy/middleware-retry": "^4.1.18", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.1.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.25", + "@smithy/util-defaults-mode-node": "^4.0.25", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", + "@smithy/util-stream": "^4.2.3", + "@smithy/util-utf8": "^4.0.0", + "@smithy/util-waiter": "^4.0.6", + "@types/uuid": "^9.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.858.0.tgz", + "integrity": "sha512-iXuZQs4KH6a3Pwnt0uORalzAZ5EXRPr3lBYAsdNwkP8OYyoUz5/TE3BLyw7ceEh0rj4QKGNnNALYo1cDm0EV8w==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.858.0", + "@aws-sdk/middleware-host-header": "3.840.0", + "@aws-sdk/middleware-logger": "3.840.0", + "@aws-sdk/middleware-recursion-detection": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.858.0", + "@aws-sdk/region-config-resolver": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.848.0", + "@aws-sdk/util-user-agent-browser": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.858.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.7.2", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/hash-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.17", + "@smithy/middleware-retry": "^4.1.18", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.1.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.25", + "@smithy/util-defaults-mode-node": "^4.0.25", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.858.0.tgz", + "integrity": "sha512-iWm4QLAS+/XMlnecIU1Y33qbBr1Ju+pmWam3xVCPlY4CSptKpVY+2hXOnmg9SbHAX9C005fWhrIn51oDd00c9A==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@aws-sdk/xml-builder": "3.821.0", + "@smithy/core": "^3.7.2", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/signature-v4": "^5.1.2", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-utf8": "^4.0.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.858.0.tgz", + "integrity": "sha512-kZsGyh2BoSRguzlcGtzdLhw/l/n3KYAC+/l/H0SlsOq3RLHF6tO/cRdsLnwoix2bObChHUp03cex63o1gzdx/Q==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.858.0.tgz", + "integrity": "sha512-GDnfYl3+NPJQ7WQQYOXEA489B212NinpcIDD7rpsB6IWUPo8yDjT5NceK4uUkIR3MFpNCGt9zd/z6NNLdB2fuQ==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/node-http-handler": "^4.1.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "@smithy/util-stream": "^4.2.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.859.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.859.0.tgz", + "integrity": "sha512-KsccE1T88ZDNhsABnqbQj014n5JMDilAroUErFbGqu5/B3sXqUsYmG54C/BjvGTRUFfzyttK9lB9P9h6ddQ8Cw==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/credential-provider-env": "3.858.0", + "@aws-sdk/credential-provider-http": "3.858.0", + "@aws-sdk/credential-provider-process": "3.858.0", + "@aws-sdk/credential-provider-sso": "3.859.0", + "@aws-sdk/credential-provider-web-identity": "3.858.0", + "@aws-sdk/nested-clients": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.859.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.859.0.tgz", + "integrity": "sha512-ZRDB2xU5aSyTR/jDcli30tlycu6RFvQngkZhBs9Zoh2BiYXrfh2MMuoYuZk+7uD6D53Q2RIEldDHR9A/TPlRuA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.858.0", + "@aws-sdk/credential-provider-http": "3.858.0", + "@aws-sdk/credential-provider-ini": "3.859.0", + "@aws-sdk/credential-provider-process": "3.858.0", + "@aws-sdk/credential-provider-sso": "3.859.0", + "@aws-sdk/credential-provider-web-identity": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.858.0.tgz", + "integrity": "sha512-l5LJWZJMRaZ+LhDjtupFUKEC5hAjgvCRrOvV5T60NCUBOy0Ozxa7Sgx3x+EOwiruuoh3Cn9O+RlbQlJX6IfZIw==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.859.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.859.0.tgz", + "integrity": "sha512-BwAqmWIivhox5YlFRjManFF8GoTvEySPk6vsJNxDsmGsabY+OQovYxFIYxRCYiHzH7SFjd4Lcd+riJOiXNsvRw==", + "dependencies": { + "@aws-sdk/client-sso": "3.858.0", + "@aws-sdk/core": "3.858.0", + "@aws-sdk/token-providers": "3.859.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.858.0.tgz", + "integrity": "sha512-8iULWsH83iZDdUuiDsRb83M0NqIlXjlDbJUIddVsIrfWp4NmanKw77SV6yOZ66nuJjPsn9j7RDb9bfEPCy5SWA==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/nested-clients": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.840.0.tgz", + "integrity": "sha512-+gkQNtPwcSMmlwBHFd4saVVS11In6ID1HczNzpM3MXKXRBfSlbZJbCt6wN//AZ8HMklZEik4tcEOG0qa9UY8SQ==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-arn-parser": "3.804.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-config-provider": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.840.0.tgz", + "integrity": "sha512-iJg2r6FKsKKvdiU4oCOuCf7Ro/YE0Q2BT/QyEZN3/Rt8Nr4SAZiQOlcBXOCpGvuIKOEAhvDOUnW3aDHL01PdVw==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.858.0.tgz", + "integrity": "sha512-/GBerFXab3Mk5zkkTaOR1drR1IWMShiUbcEocCPig068/HnpjVSd9SP4+ro/ivG+zLOtxJdpjBcBKxCwQmefMA==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/is-array-buffer": "^4.0.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-stream": "^4.2.3", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.840.0.tgz", + "integrity": "sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.840.0.tgz", + "integrity": "sha512-KVLD0u0YMF3aQkVF8bdyHAGWSUY6N1Du89htTLgqCcIhSxxAJ9qifrosVZ9jkAzqRW99hcufyt2LylcVU2yoKQ==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.840.0.tgz", + "integrity": "sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.840.0.tgz", + "integrity": "sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.858.0.tgz", + "integrity": "sha512-g1LBHK9iAAMnh4rRX4/cGBuICH5R9boHUw4X9FkMC+ROAH9z1A2uy6bE55sg5guheAmVTQ5sOsVZb8QPEQbIUA==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-arn-parser": "3.804.0", + "@smithy/core": "^3.7.2", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/protocol-http": "^5.1.2", + "@smithy/signature-v4": "^5.1.2", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-stream": "^4.2.3", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.840.0.tgz", + "integrity": "sha512-CBZP9t1QbjDFGOrtnUEHL1oAvmnCUUm7p0aPNbIdSzNtH42TNKjPRN3TuEIJDGjkrqpL3MXyDSmNayDcw/XW7Q==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.858.0.tgz", + "integrity": "sha512-pC3FT/sRZ6n5NyXiTVu9dpf1D9j3YbJz3XmeOOwJqO/Mib2PZyIQktvNMPgwaC5KMVB1zWqS5bmCwxpMOnq0UQ==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.848.0", + "@smithy/core": "^3.7.2", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.858.0.tgz", + "integrity": "sha512-ChdIj80T2whoWbovmO7o8ICmhEB2S9q4Jes9MBnKAPm69PexcJAK2dQC8yI4/iUP8b3+BHZoUPrYLWjBxIProQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.858.0", + "@aws-sdk/middleware-host-header": "3.840.0", + "@aws-sdk/middleware-logger": "3.840.0", + "@aws-sdk/middleware-recursion-detection": "3.840.0", + "@aws-sdk/middleware-user-agent": "3.858.0", + "@aws-sdk/region-config-resolver": "3.840.0", + "@aws-sdk/types": "3.840.0", + "@aws-sdk/util-endpoints": "3.848.0", + "@aws-sdk/util-user-agent-browser": "3.840.0", + "@aws-sdk/util-user-agent-node": "3.858.0", + "@smithy/config-resolver": "^4.1.4", + "@smithy/core": "^3.7.2", + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/hash-node": "^4.0.4", + "@smithy/invalid-dependency": "^4.0.4", + "@smithy/middleware-content-length": "^4.0.4", + "@smithy/middleware-endpoint": "^4.1.17", + "@smithy/middleware-retry": "^4.1.18", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/node-http-handler": "^4.1.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-body-length-node": "^4.0.0", + "@smithy/util-defaults-mode-browser": "^4.0.25", + "@smithy/util-defaults-mode-node": "^4.0.25", + "@smithy/util-endpoints": "^3.0.6", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.840.0.tgz", + "integrity": "sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.858.0.tgz", + "integrity": "sha512-WtQvCtIz8KzTqd/OhjziWb5nAFDEZ0pE1KJsWBZ0j6Ngvp17ORSY37U96buU0SlNNflloGT7ZIlDkdFh73YktA==", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/signature-v4": "^5.1.2", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.859.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.859.0.tgz", + "integrity": "sha512-6P2wlvm9KBWOvRNn0Pt8RntnXg8fzOb5kEShvWsOsAocZeqKNaYbihum5/Onq1ZPoVtkdb++8eWDocDnM4k85Q==", + "dependencies": { + "@aws-sdk/core": "3.858.0", + "@aws-sdk/nested-clients": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.840.0.tgz", + "integrity": "sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.804.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.804.0.tgz", + "integrity": "sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.848.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.848.0.tgz", + "integrity": "sha512-fY/NuFFCq/78liHvRyFKr+aqq1aA/uuVSANjzr5Ym8c+9Z3HRPE9OrExAHoMrZ6zC8tHerQwlsXYYH5XZ7H+ww==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", + "@smithy/util-endpoints": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.804.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz", + "integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.840.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.840.0.tgz", + "integrity": "sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ==", + "dependencies": { + "@aws-sdk/types": "3.840.0", + "@smithy/types": "^4.3.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.858.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.858.0.tgz", + "integrity": "sha512-T1m05QlN8hFpx5/5duMjS8uFSK5e6EXP45HQRkZULVkL3DK+jMaxsnh3KLl5LjUoHn/19M4HM0wNUBhYp4Y2Yw==", + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.858.0", + "@aws-sdk/types": "3.840.0", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.821.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.821.0.tgz", + "integrity": "sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/paginator": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz", + "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==", + "dependencies": { + "arrify": "^2.0.0", + "extend": "^3.0.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/projectify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz", + "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@google-cloud/promisify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz", + "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.16.0.tgz", + "integrity": "sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw==", + "dependencies": { + "@google-cloud/paginator": "^5.0.0", + "@google-cloud/projectify": "^4.0.0", + "@google-cloud/promisify": "<4.1.0", + "abort-controller": "^3.0.0", + "async-retry": "^1.3.3", + "duplexify": "^4.1.3", + "fast-xml-parser": "^4.4.1", + "gaxios": "^6.0.2", + "google-auth-library": "^9.6.3", + "html-entities": "^2.5.2", + "mime": "^3.0.0", + "p-limit": "^3.0.1", + "retry-request": "^7.0.0", + "teeny-request": "^9.0.0", + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@google-cloud/storage/node_modules/fast-xml-parser": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.1.1" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@google-cloud/storage/node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ] + }, + "node_modules/@google-cloud/storage/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==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz", + "integrity": "sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz", + "integrity": "sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz", + "integrity": "sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==", + "dependencies": { + "@smithy/util-base64": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz", + "integrity": "sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w==", + "dependencies": { + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.7.2.tgz", + "integrity": "sha512-JoLw59sT5Bm8SAjFCYZyuCGxK8y3vovmoVbZWLDPTH5XpPEIwpFd9m90jjVMwoypDuB/SdVgje5Y4T7w50lJaw==", + "dependencies": { + "@smithy/middleware-serde": "^4.0.8", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-stream": "^4.2.3", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz", + "integrity": "sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw==", + "dependencies": { + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.4.tgz", + "integrity": "sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.3.1", + "@smithy/util-hex-encoding": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.4.tgz", + "integrity": "sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.2.tgz", + "integrity": "sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.4.tgz", + "integrity": "sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.4.tgz", + "integrity": "sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA==", + "dependencies": { + "@smithy/eventstream-codec": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz", + "integrity": "sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ==", + "dependencies": { + "@smithy/protocol-http": "^5.1.2", + "@smithy/querystring-builder": "^4.0.4", + "@smithy/types": "^4.3.1", + "@smithy/util-base64": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.4.tgz", + "integrity": "sha512-WszRiACJiQV3QG6XMV44i5YWlkrlsM5Yxgz4jvsksuu7LDXA6wAtypfPajtNTadzpJy3KyJPoWehYpmZGKUFIQ==", + "dependencies": { + "@smithy/chunked-blob-reader": "^5.0.0", + "@smithy/chunked-blob-reader-native": "^4.0.0", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz", + "integrity": "sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ==", + "dependencies": { + "@smithy/types": "^4.3.1", + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.4.tgz", + "integrity": "sha512-wHo0d8GXyVmpmMh/qOR0R7Y46/G1y6OR8U+bSTB4ppEzRxd1xVAQ9xOE9hOc0bSjhz0ujCPAbfNLkLrpa6cevg==", + "dependencies": { + "@smithy/types": "^4.3.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz", + "integrity": "sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", + "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.4.tgz", + "integrity": "sha512-uGLBVqcOwrLvGh/v/jw423yWHq/ofUGK1W31M2TNspLQbUV1Va0F5kTxtirkoHawODAZcjXTSGi7JwbnPcDPJg==", + "dependencies": { + "@smithy/types": "^4.3.1", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz", + "integrity": "sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w==", + "dependencies": { + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "4.1.17", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.17.tgz", + "integrity": "sha512-S3hSGLKmHG1m35p/MObQCBCdRsrpbPU8B129BVzRqRfDvQqPMQ14iO4LyRw+7LNizYc605COYAcjqgawqi+6jA==", + "dependencies": { + "@smithy/core": "^3.7.2", + "@smithy/middleware-serde": "^4.0.8", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "@smithy/url-parser": "^4.0.4", + "@smithy/util-middleware": "^4.0.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.18.tgz", + "integrity": "sha512-bYLZ4DkoxSsPxpdmeapvAKy7rM5+25gR7PGxq2iMiecmbrRGBHj9s75N74Ylg+aBiw9i5jIowC/cLU2NR0qH8w==", + "dependencies": { + "@smithy/node-config-provider": "^4.1.3", + "@smithy/protocol-http": "^5.1.2", + "@smithy/service-error-classification": "^4.0.6", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-retry": "^4.0.6", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz", + "integrity": "sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw==", + "dependencies": { + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz", + "integrity": "sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz", + "integrity": "sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw==", + "dependencies": { + "@smithy/property-provider": "^4.0.4", + "@smithy/shared-ini-file-loader": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz", + "integrity": "sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg==", + "dependencies": { + "@smithy/abort-controller": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/querystring-builder": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz", + "integrity": "sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz", + "integrity": "sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz", + "integrity": "sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w==", + "dependencies": { + "@smithy/types": "^4.3.1", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz", + "integrity": "sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.6.tgz", + "integrity": "sha512-RRoTDL//7xi4tn5FrN2NzH17jbgmnKidUqd4KvquT0954/i6CXXkh1884jBiunq24g9cGtPBEXlU40W6EpNOOg==", + "dependencies": { + "@smithy/types": "^4.3.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz", + "integrity": "sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz", + "integrity": "sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ==", + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-middleware": "^4.0.4", + "@smithy/util-uri-escape": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.9.tgz", + "integrity": "sha512-mbMg8mIUAWwMmb74LoYiArP04zWElPzDoA1jVOp3or0cjlDMgoS6WTC3QXK0Vxoc9I4zdrX0tq6qsOmaIoTWEQ==", + "dependencies": { + "@smithy/core": "^3.7.2", + "@smithy/middleware-endpoint": "^4.1.17", + "@smithy/middleware-stack": "^4.0.4", + "@smithy/protocol-http": "^5.1.2", + "@smithy/types": "^4.3.1", + "@smithy/util-stream": "^4.2.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz", + "integrity": "sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz", + "integrity": "sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ==", + "dependencies": { + "@smithy/querystring-parser": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", + "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", + "dependencies": { + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", + "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", + "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", + "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", + "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.0.25", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.25.tgz", + "integrity": "sha512-pxEWsxIsOPLfKNXvpgFHBGFC3pKYKUFhrud1kyooO9CJai6aaKDHfT10Mi5iiipPXN/JhKAu3qX9o75+X85OdQ==", + "dependencies": { + "@smithy/property-provider": "^4.0.4", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "4.0.25", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.25.tgz", + "integrity": "sha512-+w4n4hKFayeCyELZLfsSQG5mCC3TwSkmRHv4+el5CzFU8ToQpYGhpV7mrRzqlwKkntlPilT1HJy1TVeEvEjWOQ==", + "dependencies": { + "@smithy/config-resolver": "^4.1.4", + "@smithy/credential-provider-imds": "^4.0.6", + "@smithy/node-config-provider": "^4.1.3", + "@smithy/property-provider": "^4.0.4", + "@smithy/smithy-client": "^4.4.9", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz", + "integrity": "sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA==", + "dependencies": { + "@smithy/node-config-provider": "^4.1.3", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", + "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz", + "integrity": "sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ==", + "dependencies": { + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.6.tgz", + "integrity": "sha512-+YekoF2CaSMv6zKrA6iI/N9yva3Gzn4L6n35Luydweu5MMPYpiGZlWqehPHDHyNbnyaYlz/WJyYAZnC+loBDZg==", + "dependencies": { + "@smithy/service-error-classification": "^4.0.6", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.3.tgz", + "integrity": "sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg==", + "dependencies": { + "@smithy/fetch-http-handler": "^5.1.0", + "@smithy/node-http-handler": "^4.1.0", + "@smithy/types": "^4.3.1", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", + "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "dependencies": { + "@smithy/util-buffer-from": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.6.tgz", + "integrity": "sha512-slcr1wdRbX7NFphXZOxtxRNA7hXAAtJAXJDE/wdoMAos27SIquVCKiSqfB6/28YzQ8FCsB5NKkhdM5gMADbqxg==", + "dependencies": { + "@smithy/abort-controller": "^4.0.4", + "@smithy/types": "^4.3.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/caseless": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz", + "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==" + }, + "node_modules/@types/node": { + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz", + "integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/request": { + "version": "2.48.13", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz", + "integrity": "sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg==", + "dependencies": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.5" + } + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==" + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==" + }, + "node_modules/@vercel/ncc": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.3.tgz", + "integrity": "sha512-rnK6hJBS6mwc+Bkab+PGPs9OiS0i/3kdTO+CkI8V0/VrW3vmz7O2Pxjw/owOlmo6PKEIxRSeZKv/kuL9itnpYA==", + "dev": true, + "license": "MIT", + "bin": { + "ncc": "dist/ncc/cli.js" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "engines": { + "node": "*" + } + }, + "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==" + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/fast-xml-parser": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz", + "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^2.1.0" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/form-data": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz", + "integrity": "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gaxios": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", + "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/gcp-metadata": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz", + "integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==", + "dependencies": { + "gaxios": "^6.1.1", + "google-logging-utils": "^0.0.2", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/google-auth-library": { + "version": "9.15.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz", + "integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^6.1.1", + "gcp-metadata": "^6.1.0", + "gtoken": "^7.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/google-logging-utils": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz", + "integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==", + "engines": { + "node": ">=14" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gtoken": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", + "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", + "dependencies": { + "gaxios": "^6.0.0", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/retry-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz", + "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==", + "dependencies": { + "@types/request": "^2.48.8", + "extend": "^3.0.2", + "teeny-request": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "dependencies": { + "stubs": "^3.0.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strnum": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", + "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ] + }, + "node_modules/stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" + }, + "node_modules/teeny-request": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz", + "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==", + "dependencies": { + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.9", + "stream-events": "^1.0.5", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/teeny-request/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/teeny-request/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/.github/actions/cloud-cache/package.json b/.github/actions/cloud-cache/package.json new file mode 100644 index 0000000..db0949c --- /dev/null +++ b/.github/actions/cloud-cache/package.json @@ -0,0 +1,19 @@ +{ + "name": "cloud-cache", + "version": "1.0.0", + "description": "GitHub Action to restore and save a cache directory from/to cloud storage (GCS or S3)", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "dependencies": { + "@actions/core": "^1.10.1", + "@aws-sdk/client-s3": "^3.650.1", + "@google-cloud/storage": "^7.12.1" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@vercel/ncc": "^0.38.3" + } +} diff --git a/.github/actions/cloud-cache/post.js b/.github/actions/cloud-cache/post.js new file mode 100644 index 0000000..0c6dc66 --- /dev/null +++ b/.github/actions/cloud-cache/post.js @@ -0,0 +1,249 @@ +const core = require("@actions/core"); +const { Storage } = require("@google-cloud/storage"); +const { + S3Client, + PutObjectCommand, + CreateMultipartUploadCommand, + UploadPartCommand, + CompleteMultipartUploadCommand, + AbortMultipartUploadCommand, +} = require("@aws-sdk/client-s3"); +const fs = require("fs").promises; +const rawFs = require("fs"); +const path = require("path"); +const cp = require("child_process"); +const os = require("os"); +const util = require("util"); +const exec = util.promisify(cp.exec); +function sleep(ms) { + return new Promise((res) => setTimeout(res, ms)); +} +async function run() { + try { + const skipUpload = core.getInput("skip-upload") === "true"; + if (skipUpload) { + console.log("skip-upload parameter is true, skipping cache upload"); + return; + } + const cacheHit = core.getState("cacheHit") === "true"; + if (cacheHit) { + console.log("Exact cache hit on primary key, skipping upload"); + return; + } + const localPath = core.getState("local-path"); + // Check if directory exists and is not empty + let dirExists = false; + let isNotEmpty = false; + try { + await fs.access(localPath); + dirExists = true; + const files = await fs.readdir(localPath); + isNotEmpty = files.length > 0; + } catch { + // Dir doesn't exist or error + } + if (!dirExists || !isNotEmpty) { + console.log( + "Local directory does not exist or is empty, skipping upload" + ); + return; + } + const primaryKey = core.getState("primaryKey"); + const prefix = core.getState("prefix"); + const bucketName = core.getState("bucketName"); + const provider = core.getState("provider"); + const retryAttempts = parseInt(core.getInput("retries") || "3", 10); + const retryBaseDelayMs = parseInt( + core.getInput("retry-delay-ms") || "1000", + 10 + ); + const uploadConcurrencyInput = parseInt( + core.getInput("upload-concurrency") || "32", + 10 + ); + let gcsStorage, gcsBucket, s3Client; + if (provider === "gcs") { + const base64Key = core.getState("base64Key"); + if (!base64Key) { + console.log("GCS key not available, skipping cache upload"); + return; + } + // Decode base64 key to JSON + const jsonKeyString = Buffer.from(base64Key, "base64").toString("utf-8"); + let credentials; + try { + credentials = JSON.parse(jsonKeyString); + } catch (err) { + throw new Error("Invalid base64 encoded JSON key"); + } + // Initialize GCS client + gcsStorage = new Storage({ credentials }); + gcsBucket = gcsStorage.bucket(bucketName); + } else if (provider === "s3") { + const s3AccessKey = core.getState("s3AccessKey"); + const s3SecretKey = core.getState("s3SecretKey"); + if (!s3AccessKey || !s3SecretKey) { + console.log("S3 credentials not available, skipping cache upload"); + return; + } + const s3Endpoint = core.getState("s3Endpoint"); + const s3Region = core.getState("s3Region"); + // Initialize S3 client + const s3Config = { + region: s3Region || "auto", + credentials: { + accessKeyId: s3AccessKey, + secretAccessKey: s3SecretKey, + }, + forcePathStyle: true, + }; + if (s3Endpoint) { + s3Config.endpoint = s3Endpoint; + } + s3Client = new S3Client(s3Config); + } + const primaryWithExt = primaryKey + ".tar.zst"; + const fullPath = prefix + primaryWithExt; + const tempDir = os.tmpdir(); + const tempTar = path.join(tempDir, `cache_${process.pid}.tar`); + const tempArchive = path.join(tempDir, `cache_${process.pid}.tar.zst`); + // Pack directory + await exec(`tar -cf ${tempTar} -C ${localPath} .`); + // Compress with fast preset + await exec(`zstd --long ${tempTar} -o ${tempArchive}`); + // Upload + const stats = await fs.stat(tempArchive); + const fileSize = stats.size; + if (provider === "gcs") { + // google-cloud/storage uses resumable uploads by default and has built-in retry. + // We call once; internal logic will resume on transient failures. + await gcsBucket.upload(tempArchive, { destination: fullPath, resumable: true }); + } else if (provider === "s3") { + if (fileSize < 5 * 1024 * 1024) { + // Use single PutObject for small files (<5MB) + for (let attempt = 1; attempt <= retryAttempts; attempt++) { + try { + await s3Client.send( + new PutObjectCommand({ + Bucket: bucketName, + Key: fullPath, + Body: rawFs.createReadStream(tempArchive), + }) + ); + break; // success + } catch (err) { + if (attempt >= retryAttempts) { + core.error( + `PutObject failed after ${attempt} attempts: ${err.message}` + ); + throw err; + } + const backoff = + retryBaseDelayMs * Math.pow(2, attempt - 1) + + Math.floor(Math.random() * retryBaseDelayMs); + core.warning( + `PutObject attempt ${attempt} failed: ${err.message}. Retrying in ${backoff}ms` + ); + await sleep(backoff); + } + } + } else { + // Use multipart for larger files + const PART_SIZE = 200 * 1024 * 1024; // 100MB parts for parallelism (<<5GB) + const createRes = await s3Client.send( + new CreateMultipartUploadCommand({ + Bucket: bucketName, + Key: fullPath, + }) + ); + const uploadId = createRes.UploadId; + try { + const numParts = Math.ceil(fileSize / PART_SIZE); + const uploadConcurrency = Math.max( + 1, + Math.min(uploadConcurrencyInput, numParts) + ); + const results = new Array(numParts); + async function uploadPartWithRetry(partNumber, start, end) { + for (let attempt = 1; attempt <= retryAttempts; attempt++) { + try { + const partStream = rawFs.createReadStream(tempArchive, { + start, + end: end - 1, + }); + const res = await s3Client.send( + new UploadPartCommand({ + Bucket: bucketName, + Key: fullPath, + PartNumber: partNumber, + UploadId: uploadId, + Body: partStream, + }) + ); + return { ETag: res.ETag, PartNumber: partNumber }; + } catch (err) { + if (attempt >= retryAttempts) { + core.error( + `Upload part #${partNumber} failed after ${attempt} attempts: ${err.message}` + ); + throw err; + } + const backoff = + retryBaseDelayMs * Math.pow(2, attempt - 1) + + Math.floor(Math.random() * retryBaseDelayMs); + core.warning( + `Upload part #${partNumber} attempt ${attempt} failed: ${err.message}. Retrying in ${backoff}ms` + ); + await sleep(backoff); + } + } + } + let nextIndex = 0; + async function worker() { + while (true) { + const i = nextIndex++; + if (i >= numParts) return; + const start = i * PART_SIZE; + const end = Math.min(start + PART_SIZE, fileSize); + const res = await uploadPartWithRetry(i + 1, start, end); + results[i] = res; + } + } + const workers = []; + for (let w = 0; w < uploadConcurrency; w++) { + workers.push(worker()); + } + await Promise.all(workers); + const uploadedParts = results.filter(Boolean).sort((a, b) => a.PartNumber - b.PartNumber); + await s3Client.send( + new CompleteMultipartUploadCommand({ + Bucket: bucketName, + Key: fullPath, + UploadId: uploadId, + MultipartUpload: { + Parts: uploadedParts, + }, + }) + ); + } catch (err) { + // Abort on error + await s3Client.send( + new AbortMultipartUploadCommand({ + Bucket: bucketName, + Key: fullPath, + UploadId: uploadId, + }) + ); + throw err; + } + } + } + // Clean up temps + await fs.unlink(tempTar).catch(() => {}); + await fs.unlink(tempArchive).catch(() => {}); + console.log(`Saved cache from ${localPath} to ${fullPath}`); + } catch (error) { + core.setFailed(error.message); + } +} +run(); diff --git a/.github/actions/cloud-cache/yarn.lock b/.github/actions/cloud-cache/yarn.lock new file mode 100644 index 0000000..fd0207b --- /dev/null +++ b/.github/actions/cloud-cache/yarn.lock @@ -0,0 +1,1700 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@actions/core@^1.10.1": + version "1.11.1" + resolved "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz" + integrity sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A== + dependencies: + "@actions/exec" "^1.1.1" + "@actions/http-client" "^2.0.1" + +"@actions/exec@^1.1.1": + version "1.1.1" + resolved "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz" + integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== + dependencies: + "@actions/io" "^1.0.1" + +"@actions/http-client@^2.0.1": + version "2.2.3" + resolved "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz" + integrity sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA== + dependencies: + tunnel "^0.0.6" + undici "^5.25.4" + +"@actions/io@^1.0.1": + version "1.1.3" + resolved "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz" + integrity sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q== + +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-browser@5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@^5.2.0", "@aws-crypto/sha256-js@5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@^5.2.0", "@aws-crypto/util@5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.650.1": + version "3.859.0" + resolved "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.859.0.tgz" + integrity sha512-oFLHZX1X6o54ZlweubtSVvQDz15JiNrgDD7KeMZT2MwxiI3axPcHzTo2uizjj5mgNapmYjRmQS5c1c63dvruVA== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.858.0" + "@aws-sdk/credential-provider-node" "3.859.0" + "@aws-sdk/middleware-bucket-endpoint" "3.840.0" + "@aws-sdk/middleware-expect-continue" "3.840.0" + "@aws-sdk/middleware-flexible-checksums" "3.858.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-location-constraint" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-sdk-s3" "3.858.0" + "@aws-sdk/middleware-ssec" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.858.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/signature-v4-multi-region" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.848.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.858.0" + "@aws-sdk/xml-builder" "3.821.0" + "@smithy/config-resolver" "^4.1.4" + "@smithy/core" "^3.7.2" + "@smithy/eventstream-serde-browser" "^4.0.4" + "@smithy/eventstream-serde-config-resolver" "^4.1.2" + "@smithy/eventstream-serde-node" "^4.0.4" + "@smithy/fetch-http-handler" "^5.1.0" + "@smithy/hash-blob-browser" "^4.0.4" + "@smithy/hash-node" "^4.0.4" + "@smithy/hash-stream-node" "^4.0.4" + "@smithy/invalid-dependency" "^4.0.4" + "@smithy/md5-js" "^4.0.4" + "@smithy/middleware-content-length" "^4.0.4" + "@smithy/middleware-endpoint" "^4.1.17" + "@smithy/middleware-retry" "^4.1.18" + "@smithy/middleware-serde" "^4.0.8" + "@smithy/middleware-stack" "^4.0.4" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/node-http-handler" "^4.1.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + "@smithy/url-parser" "^4.0.4" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.25" + "@smithy/util-defaults-mode-node" "^4.0.25" + "@smithy/util-endpoints" "^3.0.6" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-retry" "^4.0.6" + "@smithy/util-stream" "^4.2.3" + "@smithy/util-utf8" "^4.0.0" + "@smithy/util-waiter" "^4.0.6" + "@types/uuid" "^9.0.1" + tslib "^2.6.2" + uuid "^9.0.1" + +"@aws-sdk/client-sso@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.858.0.tgz" + integrity sha512-iXuZQs4KH6a3Pwnt0uORalzAZ5EXRPr3lBYAsdNwkP8OYyoUz5/TE3BLyw7ceEh0rj4QKGNnNALYo1cDm0EV8w== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.858.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.858.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.848.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.858.0" + "@smithy/config-resolver" "^4.1.4" + "@smithy/core" "^3.7.2" + "@smithy/fetch-http-handler" "^5.1.0" + "@smithy/hash-node" "^4.0.4" + "@smithy/invalid-dependency" "^4.0.4" + "@smithy/middleware-content-length" "^4.0.4" + "@smithy/middleware-endpoint" "^4.1.17" + "@smithy/middleware-retry" "^4.1.18" + "@smithy/middleware-serde" "^4.0.8" + "@smithy/middleware-stack" "^4.0.4" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/node-http-handler" "^4.1.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + "@smithy/url-parser" "^4.0.4" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.25" + "@smithy/util-defaults-mode-node" "^4.0.25" + "@smithy/util-endpoints" "^3.0.6" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-retry" "^4.0.6" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/core/-/core-3.858.0.tgz" + integrity sha512-iWm4QLAS+/XMlnecIU1Y33qbBr1Ju+pmWam3xVCPlY4CSptKpVY+2hXOnmg9SbHAX9C005fWhrIn51oDd00c9A== + dependencies: + "@aws-sdk/types" "3.840.0" + "@aws-sdk/xml-builder" "3.821.0" + "@smithy/core" "^3.7.2" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/property-provider" "^4.0.4" + "@smithy/protocol-http" "^5.1.2" + "@smithy/signature-v4" "^5.1.2" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-utf8" "^4.0.0" + fast-xml-parser "5.2.5" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.858.0.tgz" + integrity sha512-kZsGyh2BoSRguzlcGtzdLhw/l/n3KYAC+/l/H0SlsOq3RLHF6tO/cRdsLnwoix2bObChHUp03cex63o1gzdx/Q== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/property-provider" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.858.0.tgz" + integrity sha512-GDnfYl3+NPJQ7WQQYOXEA489B212NinpcIDD7rpsB6IWUPo8yDjT5NceK4uUkIR3MFpNCGt9zd/z6NNLdB2fuQ== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/fetch-http-handler" "^5.1.0" + "@smithy/node-http-handler" "^4.1.0" + "@smithy/property-provider" "^4.0.4" + "@smithy/protocol-http" "^5.1.2" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + "@smithy/util-stream" "^4.2.3" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.859.0": + version "3.859.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.859.0.tgz" + integrity sha512-KsccE1T88ZDNhsABnqbQj014n5JMDilAroUErFbGqu5/B3sXqUsYmG54C/BjvGTRUFfzyttK9lB9P9h6ddQ8Cw== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/credential-provider-env" "3.858.0" + "@aws-sdk/credential-provider-http" "3.858.0" + "@aws-sdk/credential-provider-process" "3.858.0" + "@aws-sdk/credential-provider-sso" "3.859.0" + "@aws-sdk/credential-provider-web-identity" "3.858.0" + "@aws-sdk/nested-clients" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/credential-provider-imds" "^4.0.6" + "@smithy/property-provider" "^4.0.4" + "@smithy/shared-ini-file-loader" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.859.0": + version "3.859.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.859.0.tgz" + integrity sha512-ZRDB2xU5aSyTR/jDcli30tlycu6RFvQngkZhBs9Zoh2BiYXrfh2MMuoYuZk+7uD6D53Q2RIEldDHR9A/TPlRuA== + dependencies: + "@aws-sdk/credential-provider-env" "3.858.0" + "@aws-sdk/credential-provider-http" "3.858.0" + "@aws-sdk/credential-provider-ini" "3.859.0" + "@aws-sdk/credential-provider-process" "3.858.0" + "@aws-sdk/credential-provider-sso" "3.859.0" + "@aws-sdk/credential-provider-web-identity" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/credential-provider-imds" "^4.0.6" + "@smithy/property-provider" "^4.0.4" + "@smithy/shared-ini-file-loader" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.858.0.tgz" + integrity sha512-l5LJWZJMRaZ+LhDjtupFUKEC5hAjgvCRrOvV5T60NCUBOy0Ozxa7Sgx3x+EOwiruuoh3Cn9O+RlbQlJX6IfZIw== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/property-provider" "^4.0.4" + "@smithy/shared-ini-file-loader" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.859.0": + version "3.859.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.859.0.tgz" + integrity sha512-BwAqmWIivhox5YlFRjManFF8GoTvEySPk6vsJNxDsmGsabY+OQovYxFIYxRCYiHzH7SFjd4Lcd+riJOiXNsvRw== + dependencies: + "@aws-sdk/client-sso" "3.858.0" + "@aws-sdk/core" "3.858.0" + "@aws-sdk/token-providers" "3.859.0" + "@aws-sdk/types" "3.840.0" + "@smithy/property-provider" "^4.0.4" + "@smithy/shared-ini-file-loader" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.858.0.tgz" + integrity sha512-8iULWsH83iZDdUuiDsRb83M0NqIlXjlDbJUIddVsIrfWp4NmanKw77SV6yOZ66nuJjPsn9j7RDb9bfEPCy5SWA== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/nested-clients" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/property-provider" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.840.0.tgz" + integrity sha512-+gkQNtPwcSMmlwBHFd4saVVS11In6ID1HczNzpM3MXKXRBfSlbZJbCt6wN//AZ8HMklZEik4tcEOG0qa9UY8SQ== + dependencies: + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-arn-parser" "3.804.0" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + "@smithy/util-config-provider" "^4.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.840.0.tgz" + integrity sha512-iJg2r6FKsKKvdiU4oCOuCf7Ro/YE0Q2BT/QyEZN3/Rt8Nr4SAZiQOlcBXOCpGvuIKOEAhvDOUnW3aDHL01PdVw== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.858.0.tgz" + integrity sha512-/GBerFXab3Mk5zkkTaOR1drR1IWMShiUbcEocCPig068/HnpjVSd9SP4+ro/ivG+zLOtxJdpjBcBKxCwQmefMA== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-crypto/util" "5.2.0" + "@aws-sdk/core" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/is-array-buffer" "^4.0.0" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-stream" "^4.2.3" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.840.0.tgz" + integrity sha512-ub+hXJAbAje94+Ya6c6eL7sYujoE8D4Bumu1NUI8TXjUhVVn0HzVWQjpRLshdLsUp1AW7XyeJaxyajRaJQ8+Xg== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.840.0.tgz" + integrity sha512-KVLD0u0YMF3aQkVF8bdyHAGWSUY6N1Du89htTLgqCcIhSxxAJ9qifrosVZ9jkAzqRW99hcufyt2LylcVU2yoKQ== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.840.0.tgz" + integrity sha512-lSV8FvjpdllpGaRspywss4CtXV8M7NNNH+2/j86vMH+YCOZ6fu2T/TyFd/tHwZ92vDfHctWkRbQxg0bagqwovA== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.840.0.tgz" + integrity sha512-Gu7lGDyfddyhIkj1Z1JtrY5NHb5+x/CRiB87GjaSrKxkDaydtX2CU977JIABtt69l9wLbcGDIQ+W0uJ5xPof7g== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.858.0.tgz" + integrity sha512-g1LBHK9iAAMnh4rRX4/cGBuICH5R9boHUw4X9FkMC+ROAH9z1A2uy6bE55sg5guheAmVTQ5sOsVZb8QPEQbIUA== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-arn-parser" "3.804.0" + "@smithy/core" "^3.7.2" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/protocol-http" "^5.1.2" + "@smithy/signature-v4" "^5.1.2" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-stream" "^4.2.3" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.840.0.tgz" + integrity sha512-CBZP9t1QbjDFGOrtnUEHL1oAvmnCUUm7p0aPNbIdSzNtH42TNKjPRN3TuEIJDGjkrqpL3MXyDSmNayDcw/XW7Q== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.858.0.tgz" + integrity sha512-pC3FT/sRZ6n5NyXiTVu9dpf1D9j3YbJz3XmeOOwJqO/Mib2PZyIQktvNMPgwaC5KMVB1zWqS5bmCwxpMOnq0UQ== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.848.0" + "@smithy/core" "^3.7.2" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/nested-clients@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.858.0.tgz" + integrity sha512-ChdIj80T2whoWbovmO7o8ICmhEB2S9q4Jes9MBnKAPm69PexcJAK2dQC8yI4/iUP8b3+BHZoUPrYLWjBxIProQ== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.858.0" + "@aws-sdk/middleware-host-header" "3.840.0" + "@aws-sdk/middleware-logger" "3.840.0" + "@aws-sdk/middleware-recursion-detection" "3.840.0" + "@aws-sdk/middleware-user-agent" "3.858.0" + "@aws-sdk/region-config-resolver" "3.840.0" + "@aws-sdk/types" "3.840.0" + "@aws-sdk/util-endpoints" "3.848.0" + "@aws-sdk/util-user-agent-browser" "3.840.0" + "@aws-sdk/util-user-agent-node" "3.858.0" + "@smithy/config-resolver" "^4.1.4" + "@smithy/core" "^3.7.2" + "@smithy/fetch-http-handler" "^5.1.0" + "@smithy/hash-node" "^4.0.4" + "@smithy/invalid-dependency" "^4.0.4" + "@smithy/middleware-content-length" "^4.0.4" + "@smithy/middleware-endpoint" "^4.1.17" + "@smithy/middleware-retry" "^4.1.18" + "@smithy/middleware-serde" "^4.0.8" + "@smithy/middleware-stack" "^4.0.4" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/node-http-handler" "^4.1.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + "@smithy/url-parser" "^4.0.4" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-body-length-node" "^4.0.0" + "@smithy/util-defaults-mode-browser" "^4.0.25" + "@smithy/util-defaults-mode-node" "^4.0.25" + "@smithy/util-endpoints" "^3.0.6" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-retry" "^4.0.6" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.840.0.tgz" + integrity sha512-Qjnxd/yDv9KpIMWr90ZDPtRj0v75AqGC92Lm9+oHXZ8p1MjG5JE2CW0HL8JRgK9iKzgKBL7pPQRXI8FkvEVfrA== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/types" "^4.3.1" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.0.4" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.858.0.tgz" + integrity sha512-WtQvCtIz8KzTqd/OhjziWb5nAFDEZ0pE1KJsWBZ0j6Ngvp17ORSY37U96buU0SlNNflloGT7ZIlDkdFh73YktA== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/signature-v4" "^5.1.2" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.859.0": + version "3.859.0" + resolved "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.859.0.tgz" + integrity sha512-6P2wlvm9KBWOvRNn0Pt8RntnXg8fzOb5kEShvWsOsAocZeqKNaYbihum5/Onq1ZPoVtkdb++8eWDocDnM4k85Q== + dependencies: + "@aws-sdk/core" "3.858.0" + "@aws-sdk/nested-clients" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/property-provider" "^4.0.4" + "@smithy/shared-ini-file-loader" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/types@^3.222.0", "@aws-sdk/types@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.840.0.tgz" + integrity sha512-xliuHaUFZxEx1NSXeLLZ9Dyu6+EJVQKEoD+yM+zqUo3YDZ7medKJWY6fIOKiPX/N7XbLdBYwajb15Q7IL8KkeA== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@3.804.0": + version "3.804.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.804.0.tgz" + integrity sha512-wmBJqn1DRXnZu3b4EkE6CWnoWMo1ZMvlfkqU5zPz67xx1GMaXlDCchFvKAXMjk4jn/L1O3tKnoFDNsoLV1kgNQ== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.848.0": + version "3.848.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.848.0.tgz" + integrity sha512-fY/NuFFCq/78liHvRyFKr+aqq1aA/uuVSANjzr5Ym8c+9Z3HRPE9OrExAHoMrZ6zC8tHerQwlsXYYH5XZ7H+ww== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/types" "^4.3.1" + "@smithy/url-parser" "^4.0.4" + "@smithy/util-endpoints" "^3.0.6" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.804.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz" + integrity sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.840.0": + version "3.840.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.840.0.tgz" + integrity sha512-JdyZM3EhhL4PqwFpttZu1afDpPJCCc3eyZOLi+srpX11LsGj6sThf47TYQN75HT1CarZ7cCdQHGzP2uy3/xHfQ== + dependencies: + "@aws-sdk/types" "3.840.0" + "@smithy/types" "^4.3.1" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.858.0": + version "3.858.0" + resolved "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.858.0.tgz" + integrity sha512-T1m05QlN8hFpx5/5duMjS8uFSK5e6EXP45HQRkZULVkL3DK+jMaxsnh3KLl5LjUoHn/19M4HM0wNUBhYp4Y2Yw== + dependencies: + "@aws-sdk/middleware-user-agent" "3.858.0" + "@aws-sdk/types" "3.840.0" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@3.821.0": + version "3.821.0" + resolved "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.821.0.tgz" + integrity sha512-DIIotRnefVL6DiaHtO6/21DhJ4JZnnIwdNbpwiAhdt/AVbttcE4yw925gsjur0OGv5BTYXQXU3YnANBYnZjuQA== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@fastify/busboy@^2.0.0": + version "2.1.1" + resolved "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz" + integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== + +"@google-cloud/paginator@^5.0.0": + version "5.0.2" + resolved "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz" + integrity sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz" + integrity sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA== + +"@google-cloud/promisify@<4.1.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz" + integrity sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g== + +"@google-cloud/storage@^7.12.1": + version "7.16.0" + resolved "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.16.0.tgz" + integrity sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw== + dependencies: + "@google-cloud/paginator" "^5.0.0" + "@google-cloud/projectify" "^4.0.0" + "@google-cloud/promisify" "<4.1.0" + abort-controller "^3.0.0" + async-retry "^1.3.3" + duplexify "^4.1.3" + fast-xml-parser "^4.4.1" + gaxios "^6.0.2" + google-auth-library "^9.6.3" + html-entities "^2.5.2" + mime "^3.0.0" + p-limit "^3.0.1" + retry-request "^7.0.0" + teeny-request "^9.0.0" + uuid "^8.0.0" + +"@smithy/abort-controller@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.4.tgz" + integrity sha512-gJnEjZMvigPDQWHrW3oPrFhQtkrgqBkyjj3pCIdF3A5M6vsZODG93KNlfJprv6bp4245bdT32fsHK4kkH3KYDA== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz" + integrity sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig== + dependencies: + "@smithy/util-base64" "^4.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^5.0.0": + version "5.0.0" + resolved "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz" + integrity sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^4.1.4": + version "4.1.4" + resolved "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.4.tgz" + integrity sha512-prmU+rDddxHOH0oNcwemL+SwnzcG65sBF2yXRO7aeXIn/xTlq2pX7JLVbkBnVLowHLg4/OL4+jBmv9hVrVGS+w== + dependencies: + "@smithy/node-config-provider" "^4.1.3" + "@smithy/types" "^4.3.1" + "@smithy/util-config-provider" "^4.0.0" + "@smithy/util-middleware" "^4.0.4" + tslib "^2.6.2" + +"@smithy/core@^3.7.2": + version "3.7.2" + resolved "https://registry.npmjs.org/@smithy/core/-/core-3.7.2.tgz" + integrity sha512-JoLw59sT5Bm8SAjFCYZyuCGxK8y3vovmoVbZWLDPTH5XpPEIwpFd9m90jjVMwoypDuB/SdVgje5Y4T7w50lJaw== + dependencies: + "@smithy/middleware-serde" "^4.0.8" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-body-length-browser" "^4.0.0" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-stream" "^4.2.3" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^4.0.6": + version "4.0.6" + resolved "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.6.tgz" + integrity sha512-hKMWcANhUiNbCJouYkZ9V3+/Qf9pteR1dnwgdyzR09R4ODEYx8BbUysHwRSyex4rZ9zapddZhLFTnT4ZijR4pw== + dependencies: + "@smithy/node-config-provider" "^4.1.3" + "@smithy/property-provider" "^4.0.4" + "@smithy/types" "^4.3.1" + "@smithy/url-parser" "^4.0.4" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.4.tgz" + integrity sha512-7XoWfZqWb/QoR/rAU4VSi0mWnO2vu9/ltS6JZ5ZSZv0eovLVfDfu0/AX4ub33RsJTOth3TiFWSHS5YdztvFnig== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^4.3.1" + "@smithy/util-hex-encoding" "^4.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.4.tgz" + integrity sha512-3fb/9SYaYqbpy/z/H3yIi0bYKyAa89y6xPmIqwr2vQiUT2St+avRt8UKwsWt9fEdEasc5d/V+QjrviRaX1JRFA== + dependencies: + "@smithy/eventstream-serde-universal" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^4.1.2": + version "4.1.2" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.1.2.tgz" + integrity sha512-JGtambizrWP50xHgbzZI04IWU7LdI0nh/wGbqH3sJesYToMi2j/DcoElqyOcqEIG/D4tNyxgRuaqBXWE3zOFhQ== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.4.tgz" + integrity sha512-RD6UwNZ5zISpOWPuhVgRz60GkSIp0dy1fuZmj4RYmqLVRtejFqQ16WmfYDdoSoAjlp1LX+FnZo+/hkdmyyGZ1w== + dependencies: + "@smithy/eventstream-serde-universal" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.4.tgz" + integrity sha512-UeJpOmLGhq1SLox79QWw/0n2PFX+oPRE1ZyRMxPIaFEfCqWaqpB7BU9C8kpPOGEhLF7AwEqfFbtwNxGy4ReENA== + dependencies: + "@smithy/eventstream-codec" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^5.1.0": + version "5.1.0" + resolved "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.1.0.tgz" + integrity sha512-mADw7MS0bYe2OGKkHYMaqarOXuDwRbO6ArD91XhHcl2ynjGCFF+hvqf0LyQcYxkA1zaWjefSkU7Ne9mqgApSgQ== + dependencies: + "@smithy/protocol-http" "^5.1.2" + "@smithy/querystring-builder" "^4.0.4" + "@smithy/types" "^4.3.1" + "@smithy/util-base64" "^4.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.4.tgz" + integrity sha512-WszRiACJiQV3QG6XMV44i5YWlkrlsM5Yxgz4jvsksuu7LDXA6wAtypfPajtNTadzpJy3KyJPoWehYpmZGKUFIQ== + dependencies: + "@smithy/chunked-blob-reader" "^5.0.0" + "@smithy/chunked-blob-reader-native" "^4.0.0" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/hash-node@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.4.tgz" + integrity sha512-qnbTPUhCVnCgBp4z4BUJUhOEkVwxiEi1cyFM+Zj6o+aY8OFGxUQleKWq8ltgp3dujuhXojIvJWdoqpm6dVO3lQ== + dependencies: + "@smithy/types" "^4.3.1" + "@smithy/util-buffer-from" "^4.0.0" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.4.tgz" + integrity sha512-wHo0d8GXyVmpmMh/qOR0R7Y46/G1y6OR8U+bSTB4ppEzRxd1xVAQ9xOE9hOc0bSjhz0ujCPAbfNLkLrpa6cevg== + dependencies: + "@smithy/types" "^4.3.1" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.4.tgz" + integrity sha512-bNYMi7WKTJHu0gn26wg8OscncTt1t2b8KcsZxvOv56XA6cyXtOAAAaNP7+m45xfppXfOatXF3Sb1MNsLUgVLTw== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz" + integrity sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.4.tgz" + integrity sha512-uGLBVqcOwrLvGh/v/jw423yWHq/ofUGK1W31M2TNspLQbUV1Va0F5kTxtirkoHawODAZcjXTSGi7JwbnPcDPJg== + dependencies: + "@smithy/types" "^4.3.1" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.4.tgz" + integrity sha512-F7gDyfI2BB1Kc+4M6rpuOLne5LOcEknH1n6UQB69qv+HucXBR1rkzXBnQTB2q46sFy1PM/zuSJOB532yc8bg3w== + dependencies: + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^4.1.17": + version "4.1.17" + resolved "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.17.tgz" + integrity sha512-S3hSGLKmHG1m35p/MObQCBCdRsrpbPU8B129BVzRqRfDvQqPMQ14iO4LyRw+7LNizYc605COYAcjqgawqi+6jA== + dependencies: + "@smithy/core" "^3.7.2" + "@smithy/middleware-serde" "^4.0.8" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/shared-ini-file-loader" "^4.0.4" + "@smithy/types" "^4.3.1" + "@smithy/url-parser" "^4.0.4" + "@smithy/util-middleware" "^4.0.4" + tslib "^2.6.2" + +"@smithy/middleware-retry@^4.1.18": + version "4.1.18" + resolved "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.18.tgz" + integrity sha512-bYLZ4DkoxSsPxpdmeapvAKy7rM5+25gR7PGxq2iMiecmbrRGBHj9s75N74Ylg+aBiw9i5jIowC/cLU2NR0qH8w== + dependencies: + "@smithy/node-config-provider" "^4.1.3" + "@smithy/protocol-http" "^5.1.2" + "@smithy/service-error-classification" "^4.0.6" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-retry" "^4.0.6" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^4.0.8": + version "4.0.8" + resolved "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.8.tgz" + integrity sha512-iSSl7HJoJaGyMIoNn2B7czghOVwJ9nD7TMvLhMWeSB5vt0TnEYyRRqPJu/TqW76WScaNvYYB8nRoiBHR9S1Ddw== + dependencies: + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/middleware-stack@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.4.tgz" + integrity sha512-kagK5ggDrBUCCzI93ft6DjteNSfY8Ulr83UtySog/h09lTIOAJ/xUSObutanlPT0nhoHAkpmW9V5K8oPyLh+QA== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/node-config-provider@^4.1.3": + version "4.1.3" + resolved "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.1.3.tgz" + integrity sha512-HGHQr2s59qaU1lrVH6MbLlmOBxadtzTsoO4c+bF5asdgVik3I8o7JIOzoeqWc5MjVa+vD36/LWE0iXKpNqooRw== + dependencies: + "@smithy/property-provider" "^4.0.4" + "@smithy/shared-ini-file-loader" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/node-http-handler@^4.1.0": + version "4.1.0" + resolved "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.1.0.tgz" + integrity sha512-vqfSiHz2v8b3TTTrdXi03vNz1KLYYS3bhHCDv36FYDqxT7jvTll1mMnCrkD+gOvgwybuunh/2VmvOMqwBegxEg== + dependencies: + "@smithy/abort-controller" "^4.0.4" + "@smithy/protocol-http" "^5.1.2" + "@smithy/querystring-builder" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/property-provider@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.4.tgz" + integrity sha512-qHJ2sSgu4FqF4U/5UUp4DhXNmdTrgmoAai6oQiM+c5RZ/sbDwJ12qxB1M6FnP+Tn/ggkPZf9ccn4jqKSINaquw== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/protocol-http@^5.1.2": + version "5.1.2" + resolved "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.2.tgz" + integrity sha512-rOG5cNLBXovxIrICSBm95dLqzfvxjEmuZx4KK3hWwPFHGdW3lxY0fZNXfv2zebfRO7sJZ5pKJYHScsqopeIWtQ== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/querystring-builder@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.4.tgz" + integrity sha512-SwREZcDnEYoh9tLNgMbpop+UTGq44Hl9tdj3rf+yeLcfH7+J8OXEBaMc2kDxtyRHu8BhSg9ADEx0gFHvpJgU8w== + dependencies: + "@smithy/types" "^4.3.1" + "@smithy/util-uri-escape" "^4.0.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.4.tgz" + integrity sha512-6yZf53i/qB8gRHH/l2ZwUG5xgkPgQF15/KxH0DdXMDHjesA9MeZje/853ifkSY0x4m5S+dfDZ+c4x439PF0M2w== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/service-error-classification@^4.0.6": + version "4.0.6" + resolved "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.6.tgz" + integrity sha512-RRoTDL//7xi4tn5FrN2NzH17jbgmnKidUqd4KvquT0954/i6CXXkh1884jBiunq24g9cGtPBEXlU40W6EpNOOg== + dependencies: + "@smithy/types" "^4.3.1" + +"@smithy/shared-ini-file-loader@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.4.tgz" + integrity sha512-63X0260LoFBjrHifPDs+nM9tV0VMkOTl4JRMYNuKh/f5PauSjowTfvF3LogfkWdcPoxsA9UjqEOgjeYIbhb7Nw== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/signature-v4@^5.1.2": + version "5.1.2" + resolved "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.1.2.tgz" + integrity sha512-d3+U/VpX7a60seHziWnVZOHuEgJlclufjkS6zhXvxcJgkJq4UWdH5eOBLzHRMx6gXjsdT9h6lfpmLzbrdupHgQ== + dependencies: + "@smithy/is-array-buffer" "^4.0.0" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + "@smithy/util-hex-encoding" "^4.0.0" + "@smithy/util-middleware" "^4.0.4" + "@smithy/util-uri-escape" "^4.0.0" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^4.4.9": + version "4.4.9" + resolved "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.4.9.tgz" + integrity sha512-mbMg8mIUAWwMmb74LoYiArP04zWElPzDoA1jVOp3or0cjlDMgoS6WTC3QXK0Vxoc9I4zdrX0tq6qsOmaIoTWEQ== + dependencies: + "@smithy/core" "^3.7.2" + "@smithy/middleware-endpoint" "^4.1.17" + "@smithy/middleware-stack" "^4.0.4" + "@smithy/protocol-http" "^5.1.2" + "@smithy/types" "^4.3.1" + "@smithy/util-stream" "^4.2.3" + tslib "^2.6.2" + +"@smithy/types@^4.3.1": + version "4.3.1" + resolved "https://registry.npmjs.org/@smithy/types/-/types-4.3.1.tgz" + integrity sha512-UqKOQBL2x6+HWl3P+3QqFD4ncKq0I8Nuz9QItGv5WuKuMHuuwlhvqcZCoXGfc+P1QmfJE7VieykoYYmrOoFJxA== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.4.tgz" + integrity sha512-eMkc144MuN7B0TDA4U2fKs+BqczVbk3W+qIvcoCY6D1JY3hnAdCuhCZODC+GAeaxj0p6Jroz4+XMUn3PCxQQeQ== + dependencies: + "@smithy/querystring-parser" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/util-base64@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz" + integrity sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg== + dependencies: + "@smithy/util-buffer-from" "^4.0.0" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz" + integrity sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz" + integrity sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz" + integrity sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug== + dependencies: + "@smithy/is-array-buffer" "^4.0.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz" + integrity sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^4.0.25": + version "4.0.25" + resolved "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.25.tgz" + integrity sha512-pxEWsxIsOPLfKNXvpgFHBGFC3pKYKUFhrud1kyooO9CJai6aaKDHfT10Mi5iiipPXN/JhKAu3qX9o75+X85OdQ== + dependencies: + "@smithy/property-provider" "^4.0.4" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^4.0.25": + version "4.0.25" + resolved "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.25.tgz" + integrity sha512-+w4n4hKFayeCyELZLfsSQG5mCC3TwSkmRHv4+el5CzFU8ToQpYGhpV7mrRzqlwKkntlPilT1HJy1TVeEvEjWOQ== + dependencies: + "@smithy/config-resolver" "^4.1.4" + "@smithy/credential-provider-imds" "^4.0.6" + "@smithy/node-config-provider" "^4.1.3" + "@smithy/property-provider" "^4.0.4" + "@smithy/smithy-client" "^4.4.9" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/util-endpoints@^3.0.6": + version "3.0.6" + resolved "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.6.tgz" + integrity sha512-YARl3tFL3WgPuLzljRUnrS2ngLiUtkwhQtj8PAL13XZSyUiNLQxwG3fBBq3QXFqGFUXepIN73pINp3y8c2nBmA== + dependencies: + "@smithy/node-config-provider" "^4.1.3" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz" + integrity sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^4.0.4": + version "4.0.4" + resolved "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.4.tgz" + integrity sha512-9MLKmkBmf4PRb0ONJikCbCwORACcil6gUWojwARCClT7RmLzF04hUR4WdRprIXal7XVyrddadYNfp2eF3nrvtQ== + dependencies: + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/util-retry@^4.0.6": + version "4.0.6" + resolved "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.6.tgz" + integrity sha512-+YekoF2CaSMv6zKrA6iI/N9yva3Gzn4L6n35Luydweu5MMPYpiGZlWqehPHDHyNbnyaYlz/WJyYAZnC+loBDZg== + dependencies: + "@smithy/service-error-classification" "^4.0.6" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@smithy/util-stream@^4.2.3": + version "4.2.3" + resolved "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.3.tgz" + integrity sha512-cQn412DWHHFNKrQfbHY8vSFI3nTROY1aIKji9N0tpp8gUABRilr7wdf8fqBbSlXresobM+tQFNk6I+0LXK/YZg== + dependencies: + "@smithy/fetch-http-handler" "^5.1.0" + "@smithy/node-http-handler" "^4.1.0" + "@smithy/types" "^4.3.1" + "@smithy/util-base64" "^4.0.0" + "@smithy/util-buffer-from" "^4.0.0" + "@smithy/util-hex-encoding" "^4.0.0" + "@smithy/util-utf8" "^4.0.0" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz" + integrity sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^4.0.0": + version "4.0.0" + resolved "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz" + integrity sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow== + dependencies: + "@smithy/util-buffer-from" "^4.0.0" + tslib "^2.6.2" + +"@smithy/util-waiter@^4.0.6": + version "4.0.6" + resolved "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.6.tgz" + integrity sha512-slcr1wdRbX7NFphXZOxtxRNA7hXAAtJAXJDE/wdoMAos27SIquVCKiSqfB6/28YzQ8FCsB5NKkhdM5gMADbqxg== + dependencies: + "@smithy/abort-controller" "^4.0.4" + "@smithy/types" "^4.3.1" + tslib "^2.6.2" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@types/caseless@*": + version "0.12.5" + resolved "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz" + integrity sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg== + +"@types/node@*": + version "24.1.0" + resolved "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz" + integrity sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w== + dependencies: + undici-types "~7.8.0" + +"@types/request@^2.48.8": + version "2.48.13" + resolved "https://registry.npmjs.org/@types/request/-/request-2.48.13.tgz" + integrity sha512-FGJ6udDNUCjd19pp0Q3iTiDkwhYup7J8hpMW9c4k53NrccQFFWKRho6hvtPPEhnXWKvukfwAlB6DbDz4yhH5Gg== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.5" + +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + +"@types/uuid@^9.0.1": + version "9.0.8" + resolved "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz" + integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== + +"@vercel/ncc@^0.38.3": + version "0.38.3" + resolved "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.3.tgz" + integrity sha512-rnK6hJBS6mwc+Bkab+PGPs9OiS0i/3kdTO+CkI8V0/VrW3vmz7O2Pxjw/owOlmo6PKEIxRSeZKv/kuL9itnpYA== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + +agent-base@6: + version "6.0.2" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +base64-js@^1.3.0: + version "1.5.1" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +bignumber.js@^9.0.0: + version "9.3.1" + resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz" + integrity sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ== + +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + +buffer-equal-constant-time@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +debug@4: + version "4.4.1" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +duplexify@^4.1.3: + version "4.1.3" + resolved "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + +ecdsa-sig-formatter@^1.0.11, ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +end-of-stream@^1.4.1: + version "1.4.5" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +extend@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +fast-xml-parser@^4.4.1: + version "4.5.3" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz" + integrity sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig== + dependencies: + strnum "^1.1.1" + +fast-xml-parser@5.2.5: + version "5.2.5" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz" + integrity sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ== + dependencies: + strnum "^2.1.0" + +form-data@^2.5.5: + version "2.5.5" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.5.tgz" + integrity sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.35" + safe-buffer "^5.2.1" + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gaxios@^6.0.0, gaxios@^6.0.2, gaxios@^6.1.1: + version "6.7.1" + resolved "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz" + integrity sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ== + dependencies: + extend "^3.0.2" + https-proxy-agent "^7.0.1" + is-stream "^2.0.0" + node-fetch "^2.6.9" + uuid "^9.0.1" + +gcp-metadata@^6.1.0: + version "6.1.1" + resolved "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz" + integrity sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A== + dependencies: + gaxios "^6.1.1" + google-logging-utils "^0.0.2" + json-bigint "^1.0.0" + +get-intrinsic@^1.2.6: + version "1.3.0" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +google-auth-library@^9.6.3: + version "9.15.1" + resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz" + integrity sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng== + dependencies: + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + gaxios "^6.1.1" + gcp-metadata "^6.1.0" + gtoken "^7.0.0" + jws "^4.0.0" + +google-logging-utils@^0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz" + integrity sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ== + +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +gtoken@^7.0.0: + version "7.1.0" + resolved "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz" + integrity sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw== + dependencies: + gaxios "^6.0.0" + jws "^4.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +html-entities@^2.5.2: + version "2.6.0" + resolved "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz" + integrity sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ== + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +https-proxy-agent@^7.0.1: + version "7.0.6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + +inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + +jwa@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz" + integrity sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg== + dependencies: + buffer-equal-constant-time "^1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz" + integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg== + dependencies: + jwa "^2.0.0" + safe-buffer "^5.0.1" + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.35: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +node-fetch@^2.6.9: + version "2.7.0" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^3.0.1: + version "3.1.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +readable-stream@^3.1.1: + version "3.6.2" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +retry-request@^7.0.0: + version "7.0.2" + resolved "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz" + integrity sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w== + dependencies: + "@types/request" "^2.48.8" + extend "^3.0.2" + teeny-request "^9.0.0" + +retry@0.13.1: + version "0.13.1" + resolved "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +safe-buffer@^5.0.1, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strnum@^1.1.1: + version "1.1.2" + resolved "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz" + integrity sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA== + +strnum@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz" + integrity sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw== + +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz" + integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== + +teeny-request@^9.0.0: + version "9.0.0" + resolved "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz" + integrity sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g== + dependencies: + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.9" + stream-events "^1.0.5" + uuid "^9.0.0" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tslib@^2.6.2: + version "2.8.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + +undici-types@~7.8.0: + version "7.8.0" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz" + integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== + +undici@^5.25.4: + version "5.29.0" + resolved "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz" + integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg== + dependencies: + "@fastify/busboy" "^2.0.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^8.0.0: + version "8.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +uuid@^9.0.0, uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/.github/actions/install-sccache/action.yml b/.github/actions/install-sccache/action.yml new file mode 100644 index 0000000..984caf0 --- /dev/null +++ b/.github/actions/install-sccache/action.yml @@ -0,0 +1,53 @@ +name: Install sccache +description: Installs sccache binary from release + +runs: + using: composite + steps: + - name: Install sccache + shell: bash + env: + SCCACHE_VERSION: 0.10.0 + run: | + if command -v sccache >/dev/null 2>&1; then + sccache --version + exit 0 + fi + + case "$(uname -m)" in + x86_64|amd64) + sccache_arch="x86_64" + ;; + aarch64|arm64) + sccache_arch="aarch64" + ;; + *) + echo "Unsupported architecture: $(uname -m)" >&2 + exit 1 + ;; + esac + + sccache_archive="sccache-v${SCCACHE_VERSION}-${sccache_arch}-unknown-linux-musl.tar.gz" + sccache_dir="sccache-v${SCCACHE_VERSION}-${sccache_arch}-unknown-linux-musl" + sccache_url="https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/${sccache_archive}" + tmp_dir="$(mktemp -d)" + + cleanup() { + rm -rf "$tmp_dir" + } + + trap cleanup EXIT + + curl \ + --fail \ + --location \ + --retry 5 \ + --retry-all-errors \ + --retry-delay 2 \ + --retry-max-time 120 \ + --output "$tmp_dir/$sccache_archive" \ + "$sccache_url" + + tar -xzf "$tmp_dir/$sccache_archive" -C "$tmp_dir" + install -m 755 "$tmp_dir/$sccache_dir/sccache" /usr/local/bin/sccache + sccache --version diff --git a/.github/actions/setup-sccache/action.yml b/.github/actions/setup-sccache/action.yml new file mode 100644 index 0000000..1c081bd --- /dev/null +++ b/.github/actions/setup-sccache/action.yml @@ -0,0 +1,107 @@ +name: Setup sccache +description: Authenticates to GCS or S3, installs sccache, and sets environment variables for sccache + +inputs: + backend: + description: 'The backend to use: gcs or s3' + required: true + default: 'gcs' + sccache_bucket: + description: 'The bucket name for GCS or S3' + required: false + default: 'polybase-sccache-eu' + sccache_key_prefix: + description: 'The key prefix' + required: false + default: 'rust-cache/' + sccache_gcs_sa_key_base64: + description: 'The GCS service account key in base64, required for GCS backend' + required: false + sccache_s3_region: + description: 'The S3 region, required for S3 backend (or auto if endpoint is set)' + required: false + sccache_s3_access_key_id: + description: 'The S3 access key ID, required for S3 backend' + required: false + sccache_s3_secret_access_key: + description: 'The S3 secret access key, required for S3 backend' + required: false + sccache_s3_endpoint: + description: 'The S3 endpoint URL for generic S3 (e.g., https://s3.example.com or minio:9000)' + required: false + sccache_s3_use_ssl: + description: 'Use SSL for S3 endpoint (true/false)' + required: false + default: 'true' + +runs: + using: composite + steps: + - name: Install sccache + uses: ./.github/actions/install-sccache + + - name: Set sccache env vars + shell: bash + run: | + echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV + backend="${{ inputs.backend }}" + bucket="${{ inputs.sccache_bucket }}" + prefix="${{ inputs.sccache_key_prefix }}" + if [ "$backend" = "gcs" ]; then + echo "SCCACHE_GCS_BUCKET=$bucket" >> $GITHUB_ENV + echo "SCCACHE_GCS_KEY_PREFIX=$prefix" >> $GITHUB_ENV + echo "SCCACHE_GCS_RW_MODE=READ_WRITE" >> $GITHUB_ENV + base64 -d <<< "${{ inputs.sccache_gcs_sa_key_base64 }}" > /tmp/sccache-gcs-sa-key.json + chmod 660 /tmp/sccache-gcs-sa-key.json + echo "SCCACHE_GCS_KEY_PATH=/tmp/sccache-gcs-sa-key.json" >> $GITHUB_ENV + elif [ "$backend" = "s3" ]; then + echo "SCCACHE_BUCKET=$bucket" >> $GITHUB_ENV + echo "SCCACHE_S3_KEY_PREFIX=$prefix" >> $GITHUB_ENV + region="${{ inputs.sccache_s3_region }}" + if [ -n "${{ inputs.sccache_s3_endpoint }}" ] && [ -z "$region" ]; then + region="auto" + fi + echo "SCCACHE_REGION=$region" >> $GITHUB_ENV + if [ -n "${{ inputs.sccache_s3_endpoint }}" ]; then + echo "SCCACHE_ENDPOINT=${{ inputs.sccache_s3_endpoint }}" >> $GITHUB_ENV + fi + echo "SCCACHE_S3_USE_SSL=${{ inputs.sccache_s3_use_ssl }}" >> $GITHUB_ENV + echo "AWS_ACCESS_KEY_ID=${{ inputs.sccache_s3_access_key_id }}" >> $GITHUB_ENV + echo "AWS_SECRET_ACCESS_KEY=${{ inputs.sccache_s3_secret_access_key }}" >> $GITHUB_ENV + else + echo "Unsupported backend: $backend" >&2 + exit 1 + fi + + - name: Set docker vars + shell: bash + run: | + backend="${{ inputs.backend }}" + bucket="${{ inputs.sccache_bucket }}" + prefix="${{ inputs.sccache_key_prefix }}" + echo "SCCACHE_BUILD_ARGS<> $GITHUB_ENV + if [ "$backend" = "gcs" ]; then + echo "SCCACHE_GCS_BUCKET=$bucket" >> $GITHUB_ENV + echo "SCCACHE_GCS_KEY_PREFIX=$prefix" >> $GITHUB_ENV + elif [ "$backend" = "s3" ]; then + echo "SCCACHE_BUCKET=$bucket" >> $GITHUB_ENV + echo "SCCACHE_S3_KEY_PREFIX=$prefix" >> $GITHUB_ENV + region="${{ inputs.sccache_s3_region }}" + if [ -n "${{ inputs.sccache_s3_endpoint }}" ] && [ -z "$region" ]; then + region="auto" + fi + echo "SCCACHE_REGION=$region" >> $GITHUB_ENV + if [ -n "${{ inputs.sccache_s3_endpoint }}" ]; then + echo "SCCACHE_ENDPOINT=${{ inputs.sccache_s3_endpoint }}" >> $GITHUB_ENV + fi + echo "SCCACHE_S3_USE_SSL=${{ inputs.sccache_s3_use_ssl }}" >> $GITHUB_ENV + fi + echo "EOF" >> $GITHUB_ENV + echo "SCCACHE_BUILD_SECRETS<> $GITHUB_ENV + if [ "$backend" = "gcs" ]; then + echo "gcs_sa_key_base64=${{ inputs.sccache_gcs_sa_key_base64 }}" >> $GITHUB_ENV + elif [ "$backend" = "s3" ]; then + echo "aws_access_key_id=${{ inputs.sccache_s3_access_key_id }}" >> $GITHUB_ENV + echo "aws_secret_access_key=${{ inputs.sccache_s3_secret_access_key }}" >> $GITHUB_ENV + fi + echo "EOF" >> $GITHUB_ENV diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..8261a22 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,313 @@ +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] + paths: + - ".github/workflows/test.yml" + - "pkg/**" + - "eth/**" + - "flake.lock" + - "flake.nix" + - "Cargo.lock" + - "Cargo.toml" + - "clippy.toml" + - "rust-toolchain.toml" + - "docker/*" + push: + branches: + - main + +name: Test + +env: + CARGO_INCREMENTAL: "0" + RUSTFLAGS: "-Dwarnings --cfg tracing_unstable" + RUSTDOCFLAGS: "-Dwarnings" + RUST_BACKTRACE: "1" + GITHUB_TOKEN: ${{ secrets.CLAUDE_GITHUB_PAT }} + SKIP_UPLOAD: ${{ github.event_name == 'pull_request' && 'true' || 'false' }} + # Main branch pushes should rebuild the canonical cache, so skip downloads + # when creating the fresh artifacts. Dependabot PRs do not receive repository + # secrets, so default to skipping cache downloads when the GCS key is + # unavailable. GitHub expressions treat missing secrets as null, so guard on + # both existence and non-emptiness. + SKIP_DOWNLOAD: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') || !(secrets.SCCACHE_GCS_SA_KEY_BASE64 && secrets.SCCACHE_GCS_SA_KEY_BASE64 != '') && 'true' || 'false' }} + +permissions: + contents: read + +jobs: + docker-build: + name: Docker Build + runs-on: ${{ vars.RUNNER_LABELS}} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + sccache_gcs_sa_key_base64: "${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }}" + + - name: Log in to Docker Hub + env: + DOCKER_PAT_ZKCAL: ${{ secrets.DOCKER_PAT_ZKCAL }} + if: ${{ env.DOCKER_PAT_ZKCAL != '' }} + uses: docker/login-action@v3 + with: + username: zkcal + password: ${{ env.DOCKER_PAT_ZKCAL }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile.node + push: false + no-cache: true + outputs: type=cacheonly + build-args: ${{ env.SCCACHE_BUILD_ARGS }} + secrets: ${{ env.SCCACHE_BUILD_SECRETS }} + + cargo-test: + name: Cargo Test in Docker + runs-on: ${{ vars.RUNNER_LABELS}} + timeout-minutes: 80 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + sccache_gcs_sa_key_base64: "${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }}" + sccache_bucket: ${{ vars.SCCACHE_GCS_BUCKET }} + backend: gcs + + - name: Log in to Docker Hub + env: + DOCKER_PAT_ZKCAL: ${{ secrets.DOCKER_PAT_ZKCAL }} + if: ${{ env.DOCKER_PAT_ZKCAL != '' }} + uses: docker/login-action@v3 + with: + username: zkcal + password: ${{ env.DOCKER_PAT_ZKCAL }} + + - name: Test + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile.node + target: tester + push: false + no-cache: true + outputs: type=cacheonly + build-args: ${{ env.SCCACHE_BUILD_ARGS }} + secrets: ${{ env.SCCACHE_BUILD_SECRETS }} + + cargo-doc: + name: Cargo Doc + runs-on: ${{ vars.RUNNER_LABELS}} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 # Need at least 2 commits for diff + + - name: Check for doc comment changes + id: check-docs + run: | + if git diff HEAD^ HEAD -U0 | grep -q '^\+\s*///\|^\+\s*//!\|^\+\s*#\[doc'; then + echo "has_doc_changes=true" >> $GITHUB_OUTPUT + else + echo "has_doc_changes=false" >> $GITHUB_OUTPUT + fi + + - name: Setup sccache + if: steps.check-docs.outputs.has_doc_changes == 'true' + uses: ./.github/actions/setup-sccache + with: + sccache_gcs_sa_key_base64: "${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }}" + sccache_bucket: ${{ vars.SCCACHE_GCS_BUCKET }} + backend: gcs + + - name: Compile eth contracts + if: steps.check-docs.outputs.has_doc_changes == 'true' + working-directory: eth + run: npm install && npm run compile + + - name: Install protoc + if: steps.check-docs.outputs.has_doc_changes == 'true' + run: | + PROTOC_VERSION="32.1" + curl -LO "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" + unzip -o protoc-*.zip -d $HOME/.local + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Run cargo doc + if: steps.check-docs.outputs.has_doc_changes == 'true' + run: cargo doc --no-deps + + clippy: + name: Clippy Check + runs-on: ${{ vars.RUNNER_LABELS}} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 5 + + - name: Set PATH for Cargo + run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + + - name: Set PATH for Cargo + run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH + + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + backend: gcs + sccache_bucket: ${{ vars.SCCACHE_GCS_BUCKET }} + sccache_key_prefix: testing-sccache + sccache_gcs_sa_key_base64: "${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }}" + + - name: Install zstd + run: sudo apt-get update && sudo apt-get install -y zstd + + - name: Install npm modules + run: cd .github/actions/cloud-cache && npm install + + - name: Get cache from bucket + id: cloud-cache + uses: ./.github/actions/cloud-cache + with: + gcs-key: ${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }} + bucket: ${{ vars.TARGET_CACHE_GCS_BUCKET }} + prefix: testing-cache + local-path: target + skip-upload: ${{ env.SKIP_UPLOAD }} + skip-download: ${{ env.SKIP_DOWNLOAD }} + primary-key-generator: | + echo "cargo-clippy-target-$(git rev-parse HEAD)" >> $PRIMARY_KEY + fallback-key-generator: | + commits=$(git log --pretty=format:%H -n 5 --skip=1) + for commit in $commits; do + echo "cargo-clippy-target-$commit" + echo "cargo-clippy-target-$commit" >> $FALLBACK_KEYS + done + + - name: Get ~/.cargo cache from bucket + id: cloud-cache-home-cargo + uses: ./.github/actions/cloud-cache + with: + gcs-key: ${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }} + bucket: ${{ vars.TARGET_CACHE_GCS_BUCKET }} + prefix: testing-cache + local-path: ~/.cargo + skip-upload: ${{ env.SKIP_UPLOAD }} + skip-download: ${{ env.SKIP_DOWNLOAD }} + primary-key-generator: | + echo "cargo-clippy-home-cargo-$(git rev-parse HEAD)" >> $PRIMARY_KEY + fallback-key-generator: | + commits=$(git log --pretty=format:%H -n 5 --skip=1) + for commit in $commits; do + echo "cargo-clippy-home-cargo-$commit" + echo "cargo-clippy-home-cargo-$commit" >> $FALLBACK_KEYS + done + + - name: Compile eth contracts + working-directory: eth + run: npm install && npm run compile + + - name: Install protoc + run: | + PROTOC_VERSION="32.1" + curl -LO "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" + unzip -o protoc-*.zip -d $HOME/.local + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Install cargo hack + run: cargo install cargo-hack + + - name: Install cargo-i18n + run: cargo install rust-i18n-cli + + - name: Ensure clippy is available + run: rustup component add clippy + + - name: Run Clippy + run: | + cargo hack clippy \ + --workspace --all-targets \ + --feature-powerset \ + --exclude-features bb_rs,bb_utxo + + - name: Verify rust-i18n translations + run: cargo i18n + + rust-ts-type-sync: + name: Rust/TypeScript Type Sync Check + runs-on: ${{ vars.RUNNER_LABELS}} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 5 + + - name: Setup sccache + uses: ./.github/actions/setup-sccache + with: + backend: gcs + sccache_gcs_sa_key_base64: "${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }}" + sccache_bucket: ${{ vars.SCCACHE_GCS_BUCKET }} + + - name: Install npm modules + run: cd .github/actions/cloud-cache && npm install + + - name: Get cache from bucket + id: cloud-cache + uses: ./.github/actions/cloud-cache + with: + gcs-key: ${{ secrets.SCCACHE_GCS_SA_KEY_BASE64 }} + bucket: ${{ vars.TARGET_CACHE_GCS_BUCKET }} + prefix: testing-cache + local-path: target + skip-upload: ${{ env.SKIP_UPLOAD }} + skip-download: ${{ env.SKIP_DOWNLOAD }} + primary-key-generator: | + echo "cargo-target-$(git rev-parse HEAD)" >> $PRIMARY_KEY + fallback-key-generator: | + commits=$(git log --pretty=format:%H -n 5 --skip=1) + for commit in $commits; do + echo "cargo-target-$commit" + echo "cargo-target-$commit" >> $FALLBACK_KEYS + done + + - name: Make scripts executable + run: chmod +x app/packages/payy/scripts/*.sh + + - name: Ensure jq is available + run: | + if command -v jq >/dev/null 2>&1; then + jq --version + exit 0 + fi + + if command -v apt-get >/dev/null 2>&1; then + (sudo apt-get update && sudo apt-get install -y jq) || (apt-get update && apt-get install -y jq) + jq --version + exit 0 + fi + + echo "jq is required but no apt-get package manager was found on this runner." + exit 1 + + - name: Install protobuf compiler + run: | + PROTOC_VERSION="32.1" + curl -LO "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" + unzip -o protoc-*.zip -d $HOME/.local + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Check Rust/TypeScript type sync + run: app/packages/payy/scripts/check-ts-types.sh diff --git a/.gitignore b/.gitignore index 6981f29..05d6f44 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,32 @@ target/ .DS_Store /.direnv/ node_modules -pkg/zk-circuits/params pkg/**/params -dist +dist/ *.service-account.json .env.local + +# json-store test data +pkg/json-store/test_fixtures/ + +# for Vim editor using CoC, for instance +temp_fixtures +*.vim +*.env.* +!.env.development + +.claude/settings.local.json +# Keep the dist for cloud-cache as it's required by github actions +!.github/actions/cloud-cache/dist/ + +# Hardhat debug files +*.dbg.json + +# Claude Code completion markers +.done + +# Symlink to GENERATED_AI_GUIDANCE.md (canonical file) +CLAUDE.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index da53a1a..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,25 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -- Focusing on what is best not just for us as individuals, but for the overall community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or advances of any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email address, without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a professional setting \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 8a39b23..1c37f1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -12,13 +12,54 @@ dependencies = [ "regex", ] +[[package]] +name = "acir" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acir_field", + "base64 0.22.1", + "bincode 2.0.1", + "brillig", + "color-eyre", + "flate2", + "noir_protobuf", + "noirc_span", + "num-bigint", + "num-traits", + "num_enum", + "prost 0.13.5", + "prost-build", + "protoc-bin-vendored", + "rmp-serde", + "serde", + "serde-big-array", + "strum 0.24.1", + "strum_macros 0.24.3", + "thiserror 1.0.69", +] + +[[package]] +name = "acir_field" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "ark-bn254", + "ark-ff 0.5.0", + "ark-std 0.5.0", + "cfg-if", + "hex", + "num-bigint", + "serde", +] + [[package]] name = "actix-codec" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.10.0", "bytes", "futures-core", "futures-sink", @@ -37,7 +78,7 @@ checksum = "0346d8c1f762b41b458ed3145eea914966bb9ad20b9be0d6d463b20d45586370" dependencies = [ "actix-utils", "actix-web", - "derive_more", + "derive_more 0.99.20", "futures-util", "log", "once_cell", @@ -46,41 +87,41 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.4.0" +version = "3.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92ef85799cba03f76e4f7c10f533e66d87c9a7e7055f3391f09000ad8351bc9" +checksum = "7926860314cbe2fb5d1f13731e387ab43bd32bca224e82e6e2db85de0a3dba49" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", - "ahash", - "base64 0.21.5", - "bitflags 2.4.1", + "base64 0.22.1", + "bitflags 2.10.0", "brotli", "bytes", "bytestring", - "derive_more", + "derive_more 2.1.1", "encoding_rs", "flate2", + "foldhash 0.1.5", "futures-core", - "h2", - "http", + "h2 0.3.27", + "http 0.2.12", "httparse", "httpdate", - "itoa", + "itoa 1.0.17", "language-tags", "local-channel", "mime", "percent-encoding", "pin-project-lite", - "rand 0.8.5", + "rand 0.9.2", "sha1", "smallvec", "tokio", "tokio-util", "tracing", - "zstd", + "zstd 0.13.3", ] [[package]] @@ -90,27 +131,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.40", + "syn 2.0.112", +] + +[[package]] +name = "actix-multipart" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5118a26dee7e34e894f7e85aa0ee5080ae4c18bf03c0e30d49a80e418f00a53" +dependencies = [ + "actix-multipart-derive", + "actix-utils", + "actix-web", + "derive_more 0.99.20", + "futures-core", + "futures-util", + "httparse", + "local-waker", + "log", + "memchr", + "mime", + "rand 0.8.5", + "serde", + "serde_json", + "serde_plain", + "tempfile", + "tokio", +] + +[[package]] +name = "actix-multipart-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e11eb847f49a700678ea2fa73daeb3208061afa2b9d1a8527c03390f4c4a1c6b" +dependencies = [ + "darling 0.20.11", + "parse-size", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] name = "actix-router" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" +checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", - "http", + "cfg-if", + "http 0.2.12", "regex", + "regex-lite", "serde", "tracing", ] [[package]] name = "actix-rt" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63" dependencies = [ "futures-core", "tokio", @@ -118,9 +199,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.3.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" dependencies = [ "actix-rt", "actix-service", @@ -128,19 +209,18 @@ dependencies = [ "futures-core", "futures-util", "mio", - "socket2 0.5.5", + "socket2 0.5.10", "tokio", "tracing", ] [[package]] name = "actix-service" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" +checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" dependencies = [ "futures-core", - "paste", "pin-project-lite", ] @@ -156,9 +236,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.4.0" +version = "4.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e4a5b5e29603ca8c94a77c65cf874718ceb60292c5a5c3e5f4ace041af462b9" +checksum = "1654a77ba142e37f049637a3e5685f864514af11fcbc51cb51eb6596afe5b8d6" dependencies = [ "actix-codec", "actix-http", @@ -169,57 +249,92 @@ dependencies = [ "actix-service", "actix-utils", "actix-web-codegen", - "ahash", "bytes", "bytestring", - "cfg-if 1.0.0", + "cfg-if", "cookie", - "derive_more", + "derive_more 2.1.1", "encoding_rs", + "foldhash 0.1.5", "futures-core", "futures-util", - "itoa", + "impl-more", + "itoa 1.0.17", "language-tags", "log", "mime", "once_cell", "pin-project-lite", "regex", + "regex-lite", "serde", "serde_json", - "serde_urlencoded", + "serde_urlencoded 0.7.1", "smallvec", - "socket2 0.5.5", + "socket2 0.6.1", "time", + "tracing", "url", ] [[package]] name = "actix-web-codegen" -version = "4.2.2" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", +] + +[[package]] +name = "acvm" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acir", + "acvm_blackbox_solver", + "brillig_vm", + "indexmap 2.13.0", + "rustc-hash 2.1.1", + "serde", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "acvm_blackbox_solver" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acir", + "blake2", + "blake3", + "k256", + "keccak", + "libaes", + "log", + "p256", + "sha2", + "thiserror 1.0.69", ] [[package]] name = "addr2line" -version = "0.21.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -233,11 +348,11 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher", "cpufeatures", ] @@ -256,14 +371,87 @@ dependencies = [ "subtle", ] +[[package]] +name = "aggregator" +version = "0.1.0" +dependencies = [ + "aggregator-interface", + "async-trait", + "barretenberg-interface", + "borsh", + "contextful", + "contracts", + "element", + "futures", + "hash", + "node-interface", + "primitives", + "prover", + "sha3", + "smirk", + "thiserror 1.0.69", + "tokio", + "tracing", + "unimock", + "web3", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "aggregator-cli" +version = "0.1.0" +dependencies = [ + "aggregator", + "aggregator-interface", + "async-fn-stream", + "async-trait", + "barretenberg-api-client", + "barretenberg-cli", + "barretenberg-interface", + "clap", + "contextful", + "contracts", + "element", + "futures", + "node-client-http", + "node-interface", + "primitives", + "rpc", + "thiserror 1.0.69", + "tokio", + "tracing", + "unimock", + "url", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "aggregator-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "barretenberg-interface", + "contextful", + "element", + "node-interface", + "thiserror 1.0.69", + "unimock", + "workspace-hack", + "zk-primitives", +] + [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "cfg-if 1.0.0", - "getrandom 0.2.11", + "cfg-if", + "getrandom 0.3.4", "once_cell", "version_check", "zerocopy", @@ -271,13 +459,75 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] +[[package]] +name = "alfred-http" +version = "0.1.0" +dependencies = [ + "alfred-interface", + "async-trait", + "chrono", + "contextful", + "currency", + "element", + "kyc", + "network", + "reqwest 0.12.28", + "serde", + "serde_json", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "alfred-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "currency", + "element", + "kyc", + "network", + "reqwest 0.12.28", + "serde", + "serde_json", + "strum 0.27.2", + "strum_macros 0.27.2", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "alfred-provider" +version = "0.1.0" +dependencies = [ + "alfred-http", + "alfred-interface", + "async-trait", + "contextful", + "currency", + "eth-util", + "kyc", + "network", + "providers-interface", + "ramps-interface", + "serde_json", + "thiserror 1.0.69", + "tokio", + "uuid 1.19.0", + "workspace-hack", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -294,6841 +544,16883 @@ dependencies = [ ] [[package]] -name = "alloy-rlp" -version = "0.3.3" +name = "allocator-api2" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0fac0fc16baf1f63f78b47c3d24718f3619b0714076f6a02957d808d52cbef" -dependencies = [ - "arrayvec", - "bytes", - "smol_str", -] +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] -name = "android-tzdata" -version = "0.1.1" +name = "alloy" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" +checksum = "f609fb6392508278b276906d6247ea44f5777e448db95444fa39e89b7aee896a" +dependencies = [ + "alloy-consensus", + "alloy-contract", + "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-network", + "alloy-provider", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "alloy-transport", + "alloy-transport-http", + "alloy-trie", +] [[package]] -name = "android_system_properties" -version = "0.1.5" +name = "alloy-chains" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "b163ff4acf0eac29af05a911397cc418a76e153467b859398adc26cb9335a611" dependencies = [ - "libc", + "alloy-primitives", + "alloy-rlp", + "num_enum", + "serde", + "strum 0.27.2", ] [[package]] -name = "anyhow" -version = "1.0.75" +name = "alloy-consensus" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "b0c0dc44157867da82c469c13186015b86abef209bf0e41625e4b68bac61d728" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "alloy-tx-macros", + "auto_impl", + "borsh", + "c-kzg", + "derive_more 2.1.1", + "either", + "k256", + "once_cell", + "rand 0.8.5", + "secp256k1 0.30.0", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.17", +] [[package]] -name = "ark-ff" -version = "0.3.0" +name = "alloy-consensus-any" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +checksum = "ba4cdb42df3871cd6b346d6a938ec2ba69a9a0f49d1f82714bc5c48349268434" dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "serde", ] [[package]] -name = "ark-ff" -version = "0.4.2" +name = "alloy-contract" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +checksum = "7f01b6d8e5b4f3222aaf7f18613a7292e2fbc9163fe120649cd1b078ca534349" dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.0", - "zeroize", + "alloy-consensus", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "futures", + "futures-util", + "serde_json", + "thiserror 2.0.17", ] [[package]] -name = "ark-ff-asm" -version = "0.3.0" +name = "alloy-core" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +checksum = "dcfbc46fa201350bf859add798d818bbe68b84882a8af832e4433791d28a975d" dependencies = [ - "quote", - "syn 1.0.109", + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-rlp", + "alloy-sol-types", ] [[package]] -name = "ark-ff-asm" -version = "0.4.2" +name = "alloy-dyn-abi" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +checksum = "e6ab1b2f1b48a7e6b3597cb2afae04f93879fb69d71e39736b5663d7366b23f2" dependencies = [ - "quote", - "syn 1.0.109", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-type-parser", + "alloy-sol-types", + "derive_more 2.1.1", + "itoa 1.0.17", + "serde", + "serde_json", + "winnow 0.7.14", ] [[package]] -name = "ark-ff-macros" -version = "0.3.0" +name = "alloy-eip2124" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", + "alloy-primitives", + "alloy-rlp", + "crc", + "serde", + "thiserror 2.0.17", ] [[package]] -name = "ark-ff-macros" -version = "0.4.2" +name = "alloy-eip2930" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", ] [[package]] -name = "ark-serialize" -version = "0.3.0" +name = "alloy-eip7702" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", + "alloy-primitives", + "alloy-rlp", + "borsh", + "k256", + "serde", + "serde_with", + "thiserror 2.0.17", ] [[package]] -name = "ark-serialize" -version = "0.4.2" +name = "alloy-eip7928" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +checksum = "d3231de68d5d6e75332b7489cfcc7f4dfabeba94d990a10e4b923af0e6623540" dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", ] [[package]] -name = "ark-std" -version = "0.3.0" +name = "alloy-eips" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +checksum = "b9f7ef09f21bd1e9cb8a686f168cb4a206646804567f0889eadb8dcc4c9288c8" dependencies = [ - "num-traits", - "rand 0.8.5", + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-eip7928", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "borsh", + "c-kzg", + "derive_more 2.1.1", + "either", + "ethereum_ssz", + "ethereum_ssz_derive", + "serde", + "serde_with", + "sha2", + "thiserror 2.0.17", ] [[package]] -name = "ark-std" -version = "0.4.0" +name = "alloy-evm" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +checksum = "7b99ba7b74a87176f31ee1cd26768f7155b0eeff61ed925f59b13085ffe5f891" dependencies = [ - "num-traits", - "rand 0.8.5", + "alloy-consensus", + "alloy-eips", + "alloy-hardforks", + "alloy-primitives", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-sol-types", + "auto_impl", + "derive_more 2.1.1", + "op-alloy", + "op-revm", + "revm", + "thiserror 2.0.17", ] [[package]] -name = "array-init" -version = "2.1.0" +name = "alloy-genesis" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" +checksum = "55d9d1aba3f914f0e8db9e4616ae37f3d811426d95bdccf44e47d0605ab202f6" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "alloy-trie", + "borsh", + "serde", + "serde_with", +] [[package]] -name = "arrayref" -version = "0.3.7" +name = "alloy-hardforks" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "83ba208044232d14d4adbfa77e57d6329f51bc1acc21f5667bb7db72d88a0831" +dependencies = [ + "alloy-chains", + "alloy-eip2124", + "alloy-primitives", + "auto_impl", + "dyn-clone", + "serde", +] [[package]] -name = "arrayvec" -version = "0.7.4" +name = "alloy-json-abi" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "e9dbe713da0c737d9e5e387b0ba790eb98b14dd207fe53eef50e19a5a8ec3dac" +dependencies = [ + "alloy-primitives", + "alloy-sol-type-parser", + "serde", + "serde_json", +] [[package]] -name = "asn1-rs" -version = "0.5.2" +name = "alloy-json-rpc" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +checksum = "ff42cd777eea61f370c0b10f2648a1c81e0b783066cd7269228aa993afd487f7" dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror", - "time", + "alloy-primitives", + "alloy-sol-types", + "http 1.4.0", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", ] [[package]] -name = "asn1-rs-derive" -version = "0.4.0" +name = "alloy-network" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +checksum = "8cbca04f9b410fdc51aaaf88433cbac761213905a65fe832058bcf6690585762" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-json-rpc", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-any", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-signer", + "alloy-sol-types", + "async-trait", + "auto_impl", + "derive_more 2.1.1", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror 2.0.17", ] [[package]] -name = "asn1-rs-impl" -version = "0.1.0" +name = "alloy-network-primitives" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +checksum = "42d6d15e069a8b11f56bef2eccbad2a873c6dd4d4c81d04dda29710f5ea52f04" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-serde", + "serde", ] [[package]] -name = "async-io" -version = "2.2.2" +name = "alloy-primitives" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7" +checksum = "de3b431b4e72cd8bd0ec7a50b4be18e73dab74de0dba180eef171055e5d5926e" dependencies = [ - "async-lock", - "cfg-if 1.0.0", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 2.1.1", + "foldhash 0.2.0", + "getrandom 0.4.1", + "hashbrown 0.16.1", + "indexmap 2.13.0", + "itoa 1.0.17", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.9.2", + "rapidhash", + "ruint", + "rustc-hash 2.1.1", + "serde", + "sha3", +] + +[[package]] +name = "alloy-provider" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d181c8cc7cf4805d7e589bf4074d56d55064fa1a979f005a45a62b047616d870" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-network-primitives", + "alloy-primitives", + "alloy-pubsub", + "alloy-rpc-client", + "alloy-rpc-types-debug", + "alloy-rpc-types-eth", + "alloy-rpc-types-trace", + "alloy-signer", + "alloy-sol-types", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ipc", + "alloy-transport-ws", + "async-stream", + "async-trait", + "auto_impl", + "dashmap 6.1.0", + "either", + "futures", + "futures-utils-wasm", + "lru 0.16.3", + "parking_lot 0.12.5", + "pin-project", + "reqwest 0.12.28", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", "tracing", - "windows-sys 0.52.0", + "url", + "wasmtimer", ] [[package]] -name = "async-lock" -version = "3.2.0" +name = "alloy-pubsub" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +checksum = "e8bd82953194dec221aa4cbbbb0b1e2df46066fe9d0333ac25b43a311e122d13" dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", + "alloy-json-rpc", + "alloy-primitives", + "alloy-transport", + "auto_impl", + "bimap", + "futures", + "parking_lot 0.12.5", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "wasmtimer", ] [[package]] -name = "async-trait" -version = "0.1.74" +name = "alloy-rlp" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "e93e50f64a77ad9c5470bf2ad0ca02f228da70c792a8f06634801e202579f35e" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "alloy-rlp-derive", + "arrayvec", + "bytes", ] [[package]] -name = "async_io_stream" -version = "0.3.3" +name = "alloy-rlp-derive" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +checksum = "ce8849c74c9ca0f5a03da1c865e3eb6f768df816e67dd3721a398a8a7e398011" dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "asynchronous-codec" -version = "0.6.2" +name = "alloy-rpc-client" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" +checksum = "f2792758a93ae32a32e9047c843d536e1448044f78422d71bf7d7c05149e103f" dependencies = [ - "bytes", - "futures-sink", - "futures-util", - "memchr", - "pin-project-lite", + "alloy-json-rpc", + "alloy-primitives", + "alloy-pubsub", + "alloy-transport", + "alloy-transport-http", + "alloy-transport-ipc", + "alloy-transport-ws", + "futures", + "pin-project", + "reqwest 0.12.28", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", + "wasmtimer", ] [[package]] -name = "atomic" -version = "0.6.0" +name = "alloy-rpc-types" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994" +checksum = "79cff039bf01a17d76c0aace3a3a773d5f895eb4c68baaae729ec9da9e86c99c" dependencies = [ - "bytemuck", + "alloy-primitives", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", ] [[package]] -name = "atty" -version = "0.2.14" +name = "alloy-rpc-types-admin" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "564afceae126df73b95f78c81eb46e2ef689a45ace0fcdaf5c9a178693a5ccca" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "alloy-genesis", + "alloy-primitives", + "serde", + "serde_json", ] [[package]] -name = "auto_impl" -version = "1.1.0" +name = "alloy-rpc-types-anvil" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "d22250cf438b6a3926de67683c08163bfa1fd1efa47ee9512cbcd631b6b0243c" dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "alloy-rpc-types-any" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "dd720b63f82b457610f2eaaf1f32edf44efffe03ae25d537632e7d23e7929e1a" +dependencies = [ + "alloy-consensus-any", + "alloy-rpc-types-eth", + "alloy-serde", +] [[package]] -name = "axum" -version = "0.6.20" +name = "alloy-rpc-types-beacon" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "625af0c3ebd3c31322edb1fb6b8e3e518acc39e164ed07e422eaff05310ff2fa" dependencies = [ - "async-trait", - "axum-core", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http", - "http-body", - "hyper", - "itoa", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "derive_more 2.1.1", + "ethereum_ssz", + "ethereum_ssz_derive", "serde", - "sync_wrapper", - "tower", - "tower-layer", - "tower-service", + "serde_json", + "serde_with", + "thiserror 2.0.17", + "tree_hash", + "tree_hash_derive", ] [[package]] -name = "axum-core" -version = "0.3.4" +name = "alloy-rpc-types-debug" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "e1b21e1ad18ff1b31ff1030e046462ab8168cf8894e6778cd805c8bdfe2bd649" dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "mime", - "rustversion", - "tower-layer", - "tower-service", + "alloy-primitives", + "derive_more 2.1.1", + "serde", + "serde_with", ] [[package]] -name = "backtrace" -version = "0.3.69" +name = "alloy-rpc-types-engine" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "10620d600cc46538f613c561ac9a923843c6c74c61f054828dcdb8dd18c72ec4" dependencies = [ - "addr2line", - "cc", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "derive_more 2.1.1", + "ethereum_ssz", + "ethereum_ssz_derive", + "jsonwebtoken 9.3.1", + "rand 0.8.5", + "serde", + "strum 0.27.2", ] [[package]] -name = "base-x" -version = "0.2.11" +name = "alloy-rpc-types-eth" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" +checksum = "9b2dc411f13092f237d2bf6918caf80977fc2f51485f9b90cb2a2f956912c8c9" +dependencies = [ + "alloy-consensus", + "alloy-consensus-any", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "alloy-sol-types", + "itertools 0.14.0", + "serde", + "serde_json", + "serde_with", + "thiserror 2.0.17", +] [[package]] -name = "base16ct" -version = "0.1.1" +name = "alloy-rpc-types-mev" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" +checksum = "375e4bf001135fe4f344db6197fafed8c2b61e99fa14d3597f44cd413f79e45b" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", + "serde_json", +] [[package]] -name = "base16ct" -version = "0.2.0" +name = "alloy-rpc-types-trace" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "1ad79f1e27e161943b5a4f99fe5534ef0849876214be411e0032c12f38e94daa" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", + "serde_json", + "thiserror 2.0.17", +] [[package]] -name = "base64" -version = "0.13.1" +name = "alloy-rpc-types-txpool" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +checksum = "14ab75189fbc29c5dd6f0bc1529bccef7b00773b458763f4d9d81a77ae4a1a2d" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "serde", +] [[package]] -name = "base64" -version = "0.21.5" +name = "alloy-serde" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "e2ce1e0dbf7720eee747700e300c99aac01b1a95bb93f493a01e78ee28bb1a37" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] [[package]] -name = "base64" -version = "0.22.1" +name = "alloy-signer" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "2425c6f314522c78e8198979c8cbf6769362be4da381d4152ea8eefce383535d" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "either", + "elliptic-curve", + "k256", + "thiserror 2.0.17", +] [[package]] -name = "base64ct" -version = "1.6.0" +name = "alloy-signer-local" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "9c4ec1cc27473819399a3f0da83bc1cef0ceaac8c1c93997696e46dc74377a58" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-signer", + "async-trait", + "coins-bip32", + "coins-bip39", + "k256", + "rand 0.8.5", + "thiserror 2.0.17", + "zeroize", +] [[package]] -name = "bech32" -version = "0.9.1" +name = "alloy-sol-macro" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +checksum = "ab81bab693da9bb79f7a95b64b394718259fdd7e41dceeced4cad57cb71c4f6a" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.112", +] [[package]] -name = "benchy" -version = "0.1.1" +name = "alloy-sol-macro-expander" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a02b4df38b8de5ea77a5caee888d4dfaa50044b01ad3609f14bcbe93d4d609f3" +checksum = "489f1620bb7e2483fb5819ed01ab6edc1d2f93939dce35a5695085a1afd1d699" dependencies = [ - "benchy-macros", - "memory-stats", - "nix 0.27.1", - "serde", - "serde_json", + "alloy-json-abi", + "alloy-sol-macro-input", + "const-hex", + "heck 0.5.0", + "indexmap 2.13.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "sha3", + "syn 2.0.112", + "syn-solidity", ] [[package]] -name = "benchy-macros" -version = "0.1.1" +name = "alloy-sol-macro-input" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c27b215b0291aee9ce4167bca78bf1ecbaea93dae3020b9542c45843f0eda4" +checksum = "56cef806ad22d4392c5fc83cf8f2089f988eb99c7067b4e0c6f1971fc1cca318" dependencies = [ + "alloy-json-abi", + "const-hex", + "dunce", + "heck 0.5.0", + "macro-string", "proc-macro2", "quote", - "syn 2.0.40", + "serde_json", + "syn 2.0.112", + "syn-solidity", ] [[package]] -name = "bincode" -version = "1.3.3" +name = "alloy-sol-type-parser" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +checksum = "a6df77fea9d6a2a75c0ef8d2acbdfd92286cc599983d3175ccdc170d3433d249" dependencies = [ "serde", + "winnow 0.7.14", ] [[package]] -name = "bindgen" -version = "0.65.1" +name = "alloy-sol-types" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" +checksum = "64612d29379782a5dde6f4b6570d9c756d734d760c0c94c254d361e678a6591f" dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.40", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-macro", + "serde", ] [[package]] -name = "bit-set" -version = "0.5.3" +name = "alloy-transport" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "fa186e560d523d196580c48bf00f1bf62e63041f28ecf276acc22f8b27bb9f53" dependencies = [ - "bit-vec", + "alloy-json-rpc", + "auto_impl", + "base64 0.22.1", + "derive_more 2.1.1", + "futures", + "futures-utils-wasm", + "parking_lot 0.12.5", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tower", + "tracing", + "url", + "wasmtimer", ] [[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" +name = "alloy-transport-http" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "aa501ad58dd20acddbfebc65b52e60f05ebf97c52fa40d1b35e91f5e2da0ad0e" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "itertools 0.14.0", + "reqwest 0.12.28", + "serde_json", + "tower", + "tracing", + "url", +] [[package]] -name = "bitvec" -version = "1.0.1" +name = "alloy-transport-ipc" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +checksum = "c2ef85688e5ac2da72afc804e0a1f153a1f309f05a864b1998bbbed7804dbaab" dependencies = [ - "funty", - "radium", - "tap", - "wyz", + "alloy-json-rpc", + "alloy-pubsub", + "alloy-transport", + "bytes", + "futures", + "interprocess", + "pin-project", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tracing", ] [[package]] -name = "blake2" -version = "0.10.6" +name = "alloy-transport-ws" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +checksum = "b9f00445db69d63298e2b00a0ea1d859f00e6424a3144ffc5eba9c31da995e16" dependencies = [ - "digest 0.10.7", + "alloy-pubsub", + "alloy-transport", + "futures", + "http 1.4.0", + "serde_json", + "tokio", + "tokio-tungstenite", + "tracing", + "ws_stream_wasm", ] [[package]] -name = "blake2b_simd" -version = "1.0.2" +name = "alloy-trie" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +checksum = "4d7fd448ab0a017de542de1dcca7a58e7019fe0e7a34ed3f9543ebddf6aceffa" dependencies = [ - "arrayref", + "alloy-primitives", + "alloy-rlp", "arrayvec", - "constant_time_eq", + "derive_more 2.1.1", + "nybbles", + "serde", + "smallvec", + "thiserror 2.0.17", + "tracing", ] [[package]] -name = "block-buffer" -version = "0.9.0" +name = "alloy-tx-macros" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "6fa0c53e8c1e1ef4d01066b01c737fb62fc9397ab52c6e7bb5669f97d281b9bc" dependencies = [ - "block-padding", - "generic-array", + "darling 0.21.3", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "block-buffer" -version = "0.10.4" +name = "android_system_properties" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ - "generic-array", + "libc", ] [[package]] -name = "block-padding" -version = "0.2.1" +name = "anstream" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "block-store" -version = "1.3.0" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ - "primitives", - "rocksdb", - "tempdir", - "thiserror", - "tracing", - "wire-message", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", ] [[package]] -name = "borsh" -version = "1.3.1" +name = "anstyle" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" -dependencies = [ - "borsh-derive", - "cfg_aliases", -] +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] -name = "borsh-derive" -version = "1.3.1" +name = "anstyle-parse" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ - "once_cell", - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.40", - "syn_derive", + "utf8parse", ] [[package]] -name = "brotli" -version = "3.4.0" +name = "anstyle-query" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", + "windows-sys 0.61.2", ] [[package]] -name = "brotli-decompressor" -version = "2.5.1" +name = "anstyle-wincon" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", ] [[package]] -name = "bs58" -version = "0.4.0" +name = "anyhow" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] -name = "bs58" -version = "0.5.0" +name = "aquamarine" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "0f50776554130342de4836ba542aa85a4ddb361690d7e8df13774d7284c3d5c2" dependencies = [ - "sha2 0.10.8", - "tinyvec", + "include_dir", + "itertools 0.10.5", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "bumpalo" -version = "3.14.0" +name = "ar_archive_writer" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "burn-substitutor" -version = "1.3.0" +checksum = "f0c269894b6fe5e9d7ada0cf69b5bf847ff35bc25fc271f08e1d080fce80339a" dependencies = [ - "clap", - "contracts", - "eyre", - "primitives", - "reqwest", - "rpc", - "serde", - "serde_json", - "tokio", - "tracing", - "zk-circuits", - "zk-primitives", + "object 0.32.2", ] [[package]] -name = "bus-mapping" -version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" -dependencies = [ - "eth-types", - "ethers-core 2.0.7", - "ethers-providers", - "ethers-signers", - "gadgets", - "halo2_proofs 0.2.0", - "hex", - "itertools 0.10.5", - "keccak256", - "lazy_static", - "log", - "mock", - "mpt-zktrie", - "num", - "once_cell", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit.git?branch=scroll-dev-0901)", - "rand 0.8.5", - "revm-precompile", - "serde", - "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", +name = "arc-swap" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" +dependencies = [ + "rustversion", ] [[package]] -name = "byte-slice-cast" -version = "1.2.2" +name = "ark-bls12-381" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "3df4dcc01ff89867cd86b0da835f23c3f02738353aaee7dde7495af71363b8d5" +dependencies = [ + "ark-ec", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", +] [[package]] -name = "bytemuck" -version = "1.14.0" +name = "ark-bn254" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff 0.5.0", + "ark-r1cs-std", + "ark-std 0.5.0", +] [[package]] -name = "byteorder" -version = "1.5.0" +name = "ark-ec" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-poly", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] [[package]] -name = "bytes" -version = "1.5.0" +name = "ark-ff" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" dependencies = [ - "serde", + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", ] [[package]] -name = "bytestring" -version = "1.3.1" +name = "ark-ff" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" dependencies = [ - "bytes", + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.1", + "zeroize", ] [[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" +name = "ark-ff" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" dependencies = [ - "cc", - "libc", - "pkg-config", + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "zeroize", ] [[package]] -name = "cc" -version = "1.0.83" +name = "ark-ff-asm" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "jobserver", - "libc", + "quote", + "syn 1.0.109", ] [[package]] -name = "cexpr" -version = "0.6.0" +name = "ark-ff-asm" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" dependencies = [ - "nom", + "quote", + "syn 1.0.109", ] [[package]] -name = "cfg-if" -version = "0.1.10" +name = "ark-ff-asm" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.112", +] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "ark-ff-macros" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] [[package]] -name = "cfg_aliases" -version = "0.1.1" +name = "ark-ff-macros" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] -name = "chacha20" -version = "0.9.1" +name = "ark-ff-macros" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" dependencies = [ - "cfg-if 1.0.0", - "cipher", - "cpufeatures", + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "chacha20poly1305" -version = "0.10.1" +name = "ark-grumpkin" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +checksum = "ef677b59f5aff4123207c4dceb1c0ec8fdde2d4af7886f48be42ad864bfa0352" dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", + "ark-bn254", + "ark-ec", + "ark-ff 0.5.0", + "ark-std 0.5.0", ] [[package]] -name = "chrono" -version = "0.4.38" +name = "ark-poly" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-targets 0.52.0", + "ahash", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.5", ] [[package]] -name = "cipher" -version = "0.4.4" +name = "ark-r1cs-std" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" dependencies = [ - "crypto-common", - "inout", - "zeroize", + "ark-ec", + "ark-ff 0.5.0", + "ark-relations", + "ark-std 0.5.0", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", ] [[package]] -name = "clang-sys" -version = "1.6.1" +name = "ark-relations" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" dependencies = [ - "glob", - "libc", - "libloading", + "ark-ff 0.5.0", + "ark-std 0.5.0", + "tracing", + "tracing-subscriber 0.2.25", ] [[package]] -name = "clap" -version = "4.1.1" +name = "ark-serialize" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" dependencies = [ - "bitflags 1.3.2", - "clap_derive", - "clap_lex", - "is-terminal", - "once_cell", - "strsim", - "termcolor", + "ark-std 0.3.0", + "digest 0.9.0", ] [[package]] -name = "clap_derive" -version = "4.1.0" +name = "ark-serialize" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", ] [[package]] -name = "clap_lex" -version = "0.3.3" +name = "ark-serialize" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" dependencies = [ - "os_str_bytes", + "ark-serialize-derive", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint", ] [[package]] -name = "coins-bip32" -version = "0.8.7" +name = "ark-serialize-derive" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ - "bs58 0.5.0", - "coins-core", - "digest 0.10.7", - "hmac 0.12.1", - "k256 0.13.2", - "serde", - "sha2 0.10.8", - "thiserror", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "coins-bip39" -version = "0.8.7" +name = "ark-std" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" dependencies = [ - "bitvec", - "coins-bip32", - "hmac 0.12.1", - "once_cell", - "pbkdf2 0.12.2", + "num-traits", "rand 0.8.5", - "sha2 0.10.8", - "thiserror", ] [[package]] -name = "coins-core" -version = "0.8.7" +name = "ark-std" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ - "base64 0.21.5", - "bech32", - "bs58 0.5.0", - "digest 0.10.7", - "generic-array", - "hex", - "ripemd", - "serde", - "serde_derive", - "sha2 0.10.8", - "sha3 0.10.8", - "thiserror", + "num-traits", + "rand 0.8.5", ] [[package]] -name = "color-eyre" -version = "0.6.2" +name = "ark-std" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error", + "num-traits", + "rand 0.8.5", ] [[package]] -name = "color-spantrace" -version = "0.2.1" +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" dependencies = [ - "once_cell", - "owo-colors", - "tracing-core", - "tracing-error", + "serde", ] [[package]] -name = "concurrent-queue" -version = "2.4.0" +name = "ascii-canvas" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" dependencies = [ - "crossbeam-utils", + "term", ] [[package]] -name = "console" -version = "0.15.7" +name = "asn1-rs" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "windows-sys 0.45.0", + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 1.0.69", + "time", ] [[package]] -name = "const-hex" -version = "1.10.0" +name = "asn1-rs-derive" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5104de16b218eddf8e34ffe2f86f74bfa4e61e95a1b89732fccf6325efd0557" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "hex", - "proptest", - "serde", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", ] [[package]] -name = "const-oid" -version = "0.9.5" +name = "asn1-rs-impl" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] -name = "constant_time_eq" -version = "0.3.0" +name = "asn1_der" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "155a5a185e42c6b77ac7b88a15143d930a9e9727a5b7b77eed417404ab15c247" [[package]] -name = "contracts" -version = "1.3.0" +name = "assert-json-diff" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4259cbe96513d2f1073027a259fc2ca917feb3026a5a8d984e3628e490255cc0" dependencies = [ - "clap", - "color-eyre", - "ethereum-types", - "expect-test", - "eyre", - "hex", - "parking_lot 0.12.1", - "rand 0.8.5", - "rustc-hex", - "secp256k1 0.28.1", + "extend", "serde", "serde_json", - "serial_test", - "sha3 0.10.8", - "smirk", - "testutil", - "thiserror", - "tokio", - "tracing", - "web3", - "zk-circuits", - "zk-primitives", ] [[package]] -name = "convert_case" -version = "0.4.0" +name = "assert-json-diff" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" dependencies = [ - "percent-encoding", - "time", - "version_check", + "serde", + "serde_json", ] [[package]] -name = "core-foundation" -version = "0.9.3" +name = "ast_node" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "2eb025ef00a6da925cf40870b9c8d008526b6004ece399cb0974209720f0b194" dependencies = [ - "core-foundation-sys", - "libc", + "quote", + "swc_macros_common", + "syn 2.0.112", ] [[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "core2" -version = "0.4.0" +name = "async-channel" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ - "memchr", + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", ] [[package]] -name = "cpufeatures" -version = "0.2.11" +name = "async-compression" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" dependencies = [ - "libc", + "compression-codecs", + "compression-core", + "futures-core", + "pin-project-lite", + "tokio", ] [[package]] -name = "crc32fast" -version = "1.3.2" +name = "async-fn-stream" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "d4ba0c4baf81a0d8ab31618ffa3ae29ceeb970a6d0d82f76130753462e39d0ea" dependencies = [ - "cfg-if 1.0.0", + "futures-util", + "pin-project-lite", + "smallvec", ] [[package]] -name = "crossbeam" -version = "0.8.2" +name = "async-io" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.6.1", + "parking", + "polling", + "rustix 1.1.3", + "slab", + "windows-sys 0.61.2", ] [[package]] -name = "crossbeam-channel" -version = "0.5.8" +name = "async-lock" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", + "event-listener 5.4.1", + "event-listener-strategy", + "pin-project-lite", ] [[package]] -name = "crossbeam-deque" -version = "0.8.3" +name = "async-object-pool" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "e1ac0219111eb7bb7cb76d4cf2cb50c598e7ae549091d3616f9e95442c18486f" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-epoch", - "crossbeam-utils", + "async-lock", + "event-listener 5.4.1", ] [[package]] -name = "crossbeam-epoch" -version = "0.9.15" +name = "async-recursion" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "crossbeam-utils", - "memoffset", - "scopeguard", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "crossbeam-queue" -version = "0.3.8" +name = "async-stream" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", + "async-stream-impl", + "futures-core", + "pin-project-lite", ] [[package]] -name = "crossbeam-utils" -version = "0.8.16" +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ - "cfg-if 1.0.0", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.4.9" +name = "async-stripe" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +checksum = "cecbddf002ad7a13d2041eadf1b234cb3f57653ffdd901a01bc3f1c65aa77440" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", + "chrono", + "futures-util", + "hex", + "hmac", + "http-types", + "hyper 0.14.32", + "hyper-tls 0.5.0", + "serde", + "serde_json", + "serde_path_to_error", + "serde_qs 0.10.1", + "sha2", + "smart-default", + "smol_str 0.1.24", + "thiserror 1.0.69", + "tokio", + "uuid 0.8.2", ] [[package]] -name = "crypto-bigint" -version = "0.5.5" +name = "async-trait" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "crypto-common" -version = "0.1.6" +name = "async_io_stream" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "typenum", + "futures", + "pharos", + "rustc_version 0.4.1", ] [[package]] -name = "crypto-mac" -version = "0.8.0" +name = "asynchronous-codec" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" dependencies = [ - "generic-array", - "subtle", + "bytes", + "futures-sink", + "futures-util", + "memchr", + "pin-project-lite", ] [[package]] -name = "ctr" -version = "0.9.2" +name = "atomic" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" dependencies = [ - "cipher", + "bytemuck", ] [[package]] -name = "curve25519-dalek" -version = "3.2.0" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "curve25519-dalek" -version = "4.1.1" +name = "aurora-engine-modexp" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "518bc5745a6264b5fd7b09dffb9667e400ee9e2bbe18555fac75e1fe9afa0df9" dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "curve25519-dalek-derive", - "digest 0.10.7", - "fiat-crypto", - "platforms", - "rustc_version 0.4.0", - "subtle", - "zeroize", + "hex", + "num", ] [[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" +name = "auto_impl" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] -name = "darling" -version = "0.13.4" +name = "autocfg" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core", - "darling_macro", -] +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "darling_core" -version = "0.13.4" +name = "aws-lc-rs" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +checksum = "6a88aab2464f1f25453baa7a07c84c5b7684e274054ba06817f382357f77a288" dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", + "aws-lc-sys", + "zeroize", ] [[package]] -name = "darling_macro" -version = "0.13.4" +name = "aws-lc-sys" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +checksum = "b45afffdee1e7c9126814751f88dddc747f41d91da16c9551a0f1e8a11e788a1" dependencies = [ - "darling_core", - "quote", - "syn 1.0.109", + "cc", + "cmake", + "dunce", + "fs_extra", ] [[package]] -name = "dashmap" -version = "5.5.3" +name = "axum" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.2", - "lock_api", - "once_cell", - "parking_lot_core 0.9.9", + "async-trait", + "axum-core", + "axum-macros", + "bytes", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "itoa 1.0.17", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded 0.7.1", + "sync_wrapper 1.0.2", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", ] [[package]] -name = "data-encoding" -version = "2.5.0" +name = "axum-core" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.2", + "tower-layer", + "tower-service", + "tracing", +] [[package]] -name = "data-encoding-macro" -version = "0.1.14" +name = "axum-macros" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ - "data-encoding", - "data-encoding-macro-internal", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "data-encoding-macro-internal" -version = "0.1.12" +name = "backtrace" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ - "data-encoding", - "syn 1.0.109", + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object 0.37.3", + "rustc-demangle", + "windows-link", ] [[package]] -name = "debugid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +name = "barretenberg-api-bin" +version = "0.1.0" dependencies = [ - "serde", - "uuid 1.7.0", + "axum", + "barretenberg-api-server", + "barretenberg-cli", + "barretenberg-interface", + "clap", + "rpc", + "tokio", + "tracing", + "workspace-hack", ] [[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +name = "barretenberg-api-client" +version = "0.1.0" dependencies = [ - "const-oid", + "async-trait", + "barretenberg-api-interface", + "barretenberg-interface", + "contextful", + "httparse", + "rustls 0.23.35", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tokio-rustls 0.26.4", + "tracing", + "url", + "webpki-roots 0.26.11", + "workspace-hack", ] [[package]] -name = "der" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - -[[package]] -name = "deranged" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +name = "barretenberg-api-interface" +version = "0.1.0" dependencies = [ - "powerfmt", + "barretenberg-interface", + "http 1.4.0", + "primitives", + "serde", + "thiserror 1.0.69", + "workspace-hack", ] [[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +name = "barretenberg-api-server" +version = "0.1.0" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "axum", + "barretenberg-api-interface", + "barretenberg-interface", + "contextful", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "workspace-hack", ] [[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +name = "barretenberg-api-tests" +version = "0.1.0" dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 1.0.109", + "async-trait", + "axum", + "barretenberg-api-client", + "barretenberg-api-interface", + "barretenberg-api-server", + "barretenberg-interface", + "contextful", + "http-body-util", + "serde", + "serde_json", + "tokio", + "tower", + "unimock", + "url", + "workspace-hack", ] [[package]] -name = "diesel" -version = "2.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff236accb9a5069572099f0b350a92e9560e8e63a9b8d546162f4a5e03026bb2" +name = "barretenberg-cli" +version = "0.1.0" dependencies = [ - "bitflags 2.4.1", - "byteorder", - "chrono", - "diesel_derives", - "itoa", - "pq-sys", - "r2d2", - "serde_json", - "uuid 1.7.0", + "async-trait", + "barretenberg-interface", + "flate2", + "tempfile", + "tokio", + "tracing", + "workspace-hack", ] [[package]] -name = "diesel_derives" -version = "2.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14701062d6bed917b5c7103bdffaee1e4609279e240488ad24e7bd979ca6866c" +name = "barretenberg-interface" +version = "0.1.0" dependencies = [ - "diesel_table_macro_syntax", - "proc-macro2", - "quote", - "syn 2.0.40", + "async-trait", + "thiserror 1.0.69", + "unimock", + "workspace-hack", ] [[package]] -name = "diesel_table_macro_syntax" +name = "barretenberg-rs" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.40", + "async-trait", + "barretenberg-interface", + "contextful", + "lazy_static", + "polybase_bb_rs", + "tokio", + "workspace-hack", ] [[package]] -name = "digest" -version = "0.9.0" +name = "base-x" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array", -] +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] -name = "digest" -version = "0.10.7" +name = "base16ct" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid", - "crypto-common", - "subtle", -] +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] -name = "dirs" -version = "5.0.1" +name = "base256emoji" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c" dependencies = [ - "dirs-sys", + "const-str", + "match-lookup", ] [[package]] -name = "dirs-sys" -version = "0.4.1" +name = "base62" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] +checksum = "1adf9755786e27479693dedd3271691a92b5e242ab139cacb9fb8e7fb5381111" [[package]] -name = "displaydoc" -version = "0.2.4" +name = "base64" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", -] +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] -name = "dissimilar" -version = "1.0.7" +name = "base64" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] -name = "doomslug" -version = "1.3.0" -dependencies = [ - "borsh", - "chrono", - "hex", - "once_cell", - "primitives", - "rand 0.8.5", - "serde", - "sha2 0.10.8", - "sha3 0.10.8", - "thiserror", - "tracing", - "uint", -] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] -name = "dotenvy" -version = "0.15.7" +name = "base64ct" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" [[package]] -name = "dtoa" -version = "1.0.9" +name = "bech32" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" [[package]] -name = "ecdsa" -version = "0.14.8" +name = "benchy" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +checksum = "a02b4df38b8de5ea77a5caee888d4dfaa50044b01ad3609f14bcbe93d4d609f3" dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", + "benchy-macros", + "memory-stats", + "nix 0.27.1", + "serde", + "serde_json", ] [[package]] -name = "ecdsa" -version = "0.16.9" +name = "benchy-macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +checksum = "24c27b215b0291aee9ce4167bca78bf1ecbaea93dae3020b9542c45843f0eda4" dependencies = [ - "der 0.7.8", - "digest 0.10.7", - "elliptic-curve 0.13.8", - "rfc6979 0.4.0", - "signature 2.2.0", - "spki", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "ed25519" -version = "2.2.3" +name = "better_scoped_tls" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +checksum = "7cd228125315b132eed175bf47619ac79b945b26e56b848ba203ae4ea8603609" dependencies = [ - "pkcs8", - "signature 2.2.0", + "scoped-tls", ] [[package]] -name = "ed25519-dalek" -version = "2.1.0" +name = "bigdecimal" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4d6867f1565b3aad85681f1015055b087fcfd840d6aeee6eee7f2da317603695" dependencies = [ - "curve25519-dalek 4.1.1", - "ed25519", - "rand_core 0.6.4", + "autocfg", + "libm", + "num-bigint", + "num-integer", + "num-traits", "serde", - "sha2 0.10.8", - "subtle", - "zeroize", ] [[package]] -name = "either" -version = "1.11.0" +name = "bimap" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" [[package]] -name = "elliptic-curve" -version = "0.12.3" +name = "binary-merge" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", - "digest 0.10.7", - "ff 0.12.1", - "generic-array", - "group 0.12.1", - "rand_core 0.6.4", - "sec1 0.3.0", - "subtle", - "zeroize", -] +checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" [[package]] -name = "elliptic-curve" -version = "0.13.8" +name = "bincode" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.5", - "digest 0.10.7", - "ff 0.13.0", - "generic-array", - "group 0.13.0", - "pkcs8", - "rand_core 0.6.4", - "sec1 0.7.3", - "subtle", - "zeroize", + "serde", ] [[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding_rs" -version = "0.8.33" +name = "bincode" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" dependencies = [ - "cfg-if 1.0.0", + "bincode_derive", + "serde", + "unty", ] [[package]] -name = "enr" -version = "0.8.1" +name = "bincode_derive" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf56acd72bb22d2824e66ae8e9e5ada4d0de17a69c7fd35569dde2ada8ec9116" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" dependencies = [ - "base64 0.13.1", - "bytes", - "hex", - "k256 0.13.2", - "log", - "rand 0.8.5", - "rlp", - "serde", - "sha3 0.10.8", - "zeroize", + "virtue", ] [[package]] -name = "enum-as-inner" -version = "0.5.1" +name = "bindgen" +version = "0.65.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" +checksum = "cfdf7b466f9a4903edc73f95d6d2bcd5baf8ae620638762244d3f60143643cc5" dependencies = [ - "heck 0.4.1", + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "lazy_static", + "lazycell", + "peeking_take_while", + "prettyplease", "proc-macro2", "quote", - "syn 1.0.109", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.112", ] [[package]] -name = "enumn" -version = "0.1.12" +name = "bindgen" +version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", "proc-macro2", "quote", - "syn 2.0.40", + "regex", + "rustc-hash 2.1.1", + "shlex", + "syn 2.0.112", ] [[package]] -name = "env_logger" -version = "0.8.4" +name = "bindgen" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "atty", - "humantime", - "log", + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "proc-macro2", + "quote", "regex", - "termcolor", + "rustc-hash 2.1.1", + "shlex", + "syn 2.0.112", ] [[package]] -name = "env_logger" -version = "0.10.0" +name = "bit-set" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", + "bit-vec 0.6.3", ] [[package]] -name = "equivalent" -version = "1.0.1" +name = "bit-set" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec 0.8.0", +] [[package]] -name = "errno" -version = "0.3.5" +name = "bit-vec" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitcoin-io" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" dependencies = [ - "libc", - "windows-sys 0.48.0", + "bitcoin-io", + "hex-conservative", ] [[package]] -name = "eth-keystore" -version = "0.5.0" +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ - "aes", - "ctr", - "digest 0.10.7", - "hex", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "rand 0.8.5", - "scrypt", - "serde", - "serde_json", - "sha2 0.10.8", - "sha3 0.10.8", - "thiserror", - "uuid 0.8.2", + "serde_core", ] [[package]] -name = "eth-types" -version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" dependencies = [ - "ethers-core 2.0.7", - "ethers-signers", - "halo2_proofs 0.2.0", - "hex", - "itertools 0.10.5", - "lazy_static", - "libsecp256k1", - "num", - "num-bigint", - "once_cell", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit.git?branch=scroll-dev-0901)", - "regex", - "serde", - "serde_json", - "serde_with", - "sha3 0.10.8", - "strum 0.24.1", - "strum_macros 0.24.3", - "subtle", - "uint", + "typenum", ] [[package]] -name = "ethabi" -version = "18.0.0" +name = "bitvec" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", + "funty", + "radium", "serde", - "serde_json", - "sha3 0.10.8", - "thiserror", - "uint", + "tap", + "wyz", ] [[package]] -name = "ethbloom" -version = "0.13.0" +name = "blake2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", + "digest 0.10.7", ] [[package]] -name = "ethereum-types" -version = "0.14.1" +name = "blake2b_simd" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +checksum = "b79834656f71332577234b50bfc009996f7449e0c056884e6a02492ded0ca2f3" dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", + "arrayref", + "arrayvec", + "constant_time_eq 0.4.2", ] [[package]] -name = "ethers-core" -version = "2.0.7" -source = "git+https://github.com/scroll-tech/ethers-rs.git?branch=v2.0.7#e32dfd62e7cdec31160b91c5a646883594a586ba" +name = "blake3" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" dependencies = [ + "arrayref", "arrayvec", - "bytes", - "chrono", - "elliptic-curve 0.13.8", - "ethabi", + "cc", + "cfg-if", + "constant_time_eq 0.3.1", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ "generic-array", - "hex", - "k256 0.13.2", - "num_enum 0.6.1", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum 0.24.1", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", ] [[package]] -name = "ethers-core" -version = "2.0.11" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "arrayvec", - "bytes", - "chrono", - "const-hex", - "elliptic-curve 0.13.8", - "ethabi", "generic-array", - "k256 0.13.2", - "num_enum 0.7.1", - "open-fastrlp", - "rand 0.8.5", - "rlp", - "serde", - "serde_json", - "strum 0.25.0", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", ] [[package]] -name = "ethers-providers" -version = "2.0.7" -source = "git+https://github.com/scroll-tech/ethers-rs.git?branch=v2.0.7#e32dfd62e7cdec31160b91c5a646883594a586ba" +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ - "async-trait", - "auto_impl", - "base64 0.21.5", - "bytes", - "enr", - "ethers-core 2.0.7", - "futures-channel", - "futures-core", - "futures-timer", - "futures-util", - "hashers", - "hex", - "http", - "instant", - "once_cell", - "pin-project", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-tungstenite", - "tracing", - "tracing-futures", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "ws_stream_wasm", + "generic-array", ] [[package]] -name = "ethers-signers" -version = "2.0.7" -source = "git+https://github.com/scroll-tech/ethers-rs.git?branch=v2.0.7#e32dfd62e7cdec31160b91c5a646883594a586ba" +name = "block-store" +version = "1.3.0" dependencies = [ - "async-trait", - "coins-bip32", - "coins-bip39", - "elliptic-curve 0.13.8", - "eth-keystore", - "ethers-core 2.0.7", - "hex", - "rand 0.8.5", - "sha2 0.10.8", - "thiserror", + "borsh", + "element", + "primitives", + "rocksdb", + "strum 0.27.2", + "tempdir", + "thiserror 1.0.69", "tracing", + "wire-message", + "workspace-hack", ] [[package]] -name = "ethnum" -version = "1.5.0" +name = "block2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] [[package]] -name = "event-listener" -version = "4.0.0" +name = "blst" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", + "cc", + "glob", + "threadpool", + "zeroize", ] [[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +name = "bn254_blackbox_solver" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" dependencies = [ - "event-listener", - "pin-project-lite", + "acir", + "acvm_blackbox_solver", + "ark-bn254", + "ark-ec", + "ark-ff 0.5.0", + "ark-grumpkin", + "hex", + "lazy_static", + "num-bigint", ] [[package]] -name = "expect-test" -version = "1.4.1" +name = "borsh" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" dependencies = [ - "dissimilar", - "once_cell", + "borsh-derive", + "cfg_aliases", ] [[package]] -name = "external-tracer" -version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" +name = "borsh-derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" dependencies = [ - "eth-types", - "geth-utils", - "log", - "serde", - "serde_json", + "once_cell", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "eyre" -version = "0.6.10" +name = "boyer-moore-magiclen" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bbb8258be8305fb0237d7b295f47bb24ff1b136a535f473baf40e70468515aa" +checksum = "7441b4796eb8a7107d4cd99d829810be75f5573e1081c37faa0e8094169ea0d6" dependencies = [ - "indenter", - "once_cell", + "debug-helper", ] [[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +name = "brillig" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acir_field", + "serde", +] [[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +name = "brillig_vm" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" dependencies = [ - "arrayvec", - "auto_impl", - "bytes", + "acir", + "acvm_blackbox_solver", + "num-bigint", + "num-traits", + "thiserror 1.0.69", ] [[package]] -name = "ff" -version = "0.12.1" +name = "brotli" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ - "bitvec", - "rand_core 0.6.4", - "subtle", + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", ] [[package]] -name = "ff" -version = "0.13.0" +name = "brotli-decompressor" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" dependencies = [ - "bitvec", - "rand_core 0.6.4", - "subtle", + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] -name = "fiat-crypto" -version = "0.2.5" +name = "bs58" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] -name = "figment" -version = "0.10.12" +name = "bs58" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "649f3e5d826594057e9a519626304d8da859ea8a0b18ce99500c586b8d45faee" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "atomic", - "pear", - "serde", - "toml 0.8.2", - "uncased", - "version_check", + "sha2", + "tinyvec", ] [[package]] -name = "findshlibs" -version = "0.10.2" +name = "bstr" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ - "cc", - "lazy_static", - "libc", - "winapi", + "memchr", + "serde", ] [[package]] -name = "fixed-hash" -version = "0.8.0" +name = "build-data" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +checksum = "22e6d5ca7a4989b90a9fafea85ce3c8bc9f0e0a76edcdcb330fe0c4fda92251f" dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", + "chrono", + "safe-regex", ] [[package]] -name = "fixedbitset" -version = "0.4.2" +name = "bumpalo" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +dependencies = [ + "allocator-api2", +] [[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +name = "bungee-client-http" +version = "0.1.0" dependencies = [ - "crc32fast", - "miniz_oxide", + "async-trait", + "bungee-interface", + "contracts", + "guild-interface", + "hex", + "rand 0.8.5", + "reqwest 0.12.28", + "serde_json", + "tokio", + "tracing", + "workspace-hack", ] [[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +name = "bungee-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "guild-interface", + "reqwest 0.12.28", + "serde", + "thiserror 1.0.69", + "workspace-hack", +] [[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +name = "burn-substitutor" +version = "1.3.0" dependencies = [ - "foreign-types-shared", + "clap", + "contextful", + "contracts", + "element", + "eth-util", + "node-client-http", + "node-interface", + "primitives", + "rpc", + "serde", + "thiserror 1.0.69", + "tokio", + "tracing", + "url", + "workspace-hack", + "zk-primitives", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "byte-slice-cast" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] -name = "form_urlencoded" -version = "1.2.0" +name = "bytecount" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "bytemuck" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" [[package]] -name = "funty" -version = "2.0.0" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "futures" -version = "0.3.29" +name = "bytes" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "serde", ] [[package]] -name = "futures-channel" -version = "0.3.29" +name = "bytes-str" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "7c60b5ce37e0b883c37eb89f79a1e26fbe9c1081945d024eee93e8d91a7e18b3" dependencies = [ - "futures-core", - "futures-sink", + "bytes", + "serde", ] [[package]] -name = "futures-core" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" - -[[package]] -name = "futures-executor" -version = "0.3.29" +name = "bytestring" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "113b4343b5f6617e7ad401ced8de3cc8b012e73a594347c307b90db3e9271289" dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", + "bytes", ] [[package]] -name = "futures-io" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" - -[[package]] -name = "futures-lite" -version = "2.1.0" +name = "bzip2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ - "futures-core", - "pin-project-lite", + "bzip2-sys", + "libc", ] [[package]] -name = "futures-macro" -version = "0.3.29" +name = "bzip2-sys" +version = "0.1.13+1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "cc", + "pkg-config", ] [[package]] -name = "futures-rustls" -version = "0.22.2" +name = "c-kzg" +version = "2.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" +checksum = "e00bf4b112b07b505472dbefd19e37e53307e2bfed5a79e0cc161d58ccd0e687" dependencies = [ - "futures-io", - "rustls 0.20.9", - "webpki", + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", ] [[package]] -name = "futures-sink" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" - -[[package]] -name = "futures-task" -version = "0.3.29" +name = "camino" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] [[package]] -name = "futures-timer" -version = "3.0.2" +name = "capacity_builder" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "8f2d24a6dcf0cd402a21b65d35340f3a49ff3475dc5fdac91d22d2733e6641c6" dependencies = [ - "gloo-timers", - "send_wrapper 0.4.0", + "capacity_builder_macros", + "itoa 1.0.17", ] [[package]] -name = "futures-util" -version = "0.3.29" +name = "capacity_builder_macros" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3b4a6cae9efc04cc6cbb8faf338d2c497c165c83e74509cf4dbedea948bbf6e5" dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", + "quote", + "syn 2.0.112", ] [[package]] -name = "fxhash" -version = "0.2.1" +name = "cargo-platform" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" dependencies = [ - "byteorder", + "serde", ] [[package]] -name = "gadgets" -version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" +name = "cargo-platform" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87a0c0e6148f11f01f32650a2ea02d532b2ad4e81d8bd41e6e565b5adc5e6082" dependencies = [ - "eth-types", - "halo2_proofs 0.2.0", - "sha3 0.10.8", - "strum 0.24.1", + "serde", + "serde_core", ] [[package]] -name = "generic-array" -version = "0.14.7" +name = "cargo_metadata" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" dependencies = [ - "typenum", - "version_check", - "zeroize", + "camino", + "cargo-platform 0.1.9", + "semver 1.0.27", + "serde", + "serde_json", ] [[package]] -name = "geth-utils" -version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" dependencies = [ - "env_logger 0.10.0", - "gobuild 0.1.0-alpha.2 (git+https://github.com/scroll-tech/gobuild.git)", - "log", + "camino", + "cargo-platform 0.3.2", + "semver 1.0.27", + "serde", + "serde_json", + "thiserror 2.0.17", ] [[package]] -name = "getrandom" -version = "0.1.16" +name = "cc" +version = "1.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" dependencies = [ - "cfg-if 1.0.0", + "find-msvc-tools", + "jobserver", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "shlex", ] [[package]] -name = "getrandom" -version = "0.2.11" +name = "cesu8" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" -dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] -name = "ghash" -version = "0.5.0" +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "opaque-debug", - "polyval", + "nom", ] [[package]] -name = "gimli" -version = "0.28.0" +name = "cfg-if" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] -name = "glob" -version = "0.3.1" +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "gloo-timers" -version = "0.2.6" +name = "chacha20" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", + "cfg-if", + "cipher", + "cpufeatures", ] [[package]] -name = "gobuild" -version = "0.1.0-alpha.2" +name = "chacha20poly1305" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e156a4ddbf3deb5e8116946c111413bd9a5679bdc1536c78a60618a7a9ac9e" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ - "cc", + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", ] [[package]] -name = "gobuild" -version = "0.1.0-alpha.2" -source = "git+https://github.com/scroll-tech/gobuild.git#8b84111fc3b58e2134e4794a06d1f199412cf2b0" +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "cc", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", ] [[package]] -name = "group" -version = "0.12.1" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", + "crypto-common", + "inout", + "zeroize", ] [[package]] -name = "group" -version = "0.13.0" +name = "clang-sys" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ - "ff 0.13.0", - "rand_core 0.6.4", - "subtle", + "glob", + "libc", + "libloading", ] [[package]] -name = "h2" -version = "0.3.24" +name = "clap" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 2.0.2", - "slab", - "tokio", - "tokio-util", - "tracing", + "clap_builder", + "clap_derive", ] [[package]] -name = "halo2-base" -version = "0.2.2" -source = "git+https://github.com/scroll-tech/halo2-lib?tag=v0.1.5#70588177930400361c731659b15b2ab3f29f7784" +name = "clap_builder" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ - "ff 0.12.1", - "halo2_proofs 0.2.0", - "itertools 0.10.5", - "num-bigint", - "num-integer", - "num-traits", - "rand_chacha", - "rustc-hash", + "anstream", + "anstyle", + "clap_lex", + "strsim", ] [[package]] -name = "halo2-ecc" -version = "0.2.2" -source = "git+https://github.com/scroll-tech/halo2-lib?tag=v0.1.5#70588177930400361c731659b15b2ab3f29f7784" +name = "clap_derive" +version = "4.5.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ - "ff 0.12.1", - "group 0.12.1", - "halo2-base", - "itertools 0.10.5", - "num-bigint", - "num-integer", - "num-traits", - "rand 0.8.5", - "rand_chacha", - "rand_core 0.6.4", - "serde", - "serde_json", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "halo2-gate-generator" +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "client-http" version = "0.1.0" -source = "git+https://github.com/scroll-tech/halo2gategen.git#35b137de2f71c37dfbd236842b868013c46739d1" dependencies = [ - "halo2_proofs 0.2.0", - "lazy_static", - "num-bigint", - "rand 0.8.5", + "async-trait", + "http-interface", + "reqwest 0.12.28", + "rpc", "serde", "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", - "subtle", + "tokio", + "tracing", + "workspace-hack", ] [[package]] -name = "halo2-mpt-circuits" +name = "client-http-longpoll" version = "0.1.0" -source = "git+https://github.com/scroll-tech/mpt-circuit.git?tag=v0.7.0#578c210ceb88d3c143ee2a013ad836d19285d9c1" dependencies = [ - "ethers-core 2.0.11", - "halo2_proofs 0.2.0", - "hex", - "itertools 0.10.5", - "lazy_static", - "log", - "num-bigint", - "num-traits", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit.git?branch=scroll-dev-0901)", - "rand 0.8.5", - "serde", - "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", - "thiserror", + "async-stream", + "async-trait", + "chrono", + "futures", + "parking_lot 0.12.5", + "rpc", + "tokio", + "workspace-hack", ] [[package]] -name = "halo2_gadgets" -version = "0.2.0" -source = "git+https://github.com/scroll-tech/halo2.git?branch=develop#5cf9a3726525810af41ef416e0292ec999b34030" +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" dependencies = [ - "arrayvec", - "bitvec", - "ff 0.12.1", - "group 0.12.1", - "halo2_proofs 0.2.0", - "halo2curves 0.3.1", - "lazy_static", - "rand 0.8.5", - "subtle", - "uint", + "cc", ] [[package]] -name = "halo2_proofs" -version = "0.2.0" -source = "git+https://github.com/scroll-tech/halo2.git?branch=develop#92fe9b3e2420ee51336b39513e397df7c8175cf9" +name = "codespan" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3362992a0d9f1dd7c3d0e89e0ab2bb540b7a95fea8cd798090e758fda2899b5e" dependencies = [ - "ark-std 0.3.0", - "blake2b_simd", - "cfg-if 0.1.10", - "crossbeam", - "env_logger 0.8.4", - "ff 0.12.1", - "group 0.12.1", - "halo2curves 0.3.1", - "log", - "num-bigint", - "num-integer", - "poseidon", - "rand_core 0.6.4", - "rayon", - "sha3 0.9.1", - "subtle", - "tracing", + "codespan-reporting", + "serde", ] [[package]] -name = "halo2_proofs" -version = "0.3.0" +name = "codespan-reporting" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b867a8d9bbb85fca76fff60652b5cd19b853a1c4d0665cb89bee68b18d2caf0" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ - "blake2b_simd", - "ff 0.13.0", - "group 0.13.0", - "maybe-rayon", - "pasta_curves 0.5.1", - "rand_core 0.6.4", - "tracing", + "serde", + "termcolor", + "unicode-width 0.1.14", ] [[package]] -name = "halo2curves" -version = "0.1.0" +name = "coins-bip32" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b1142bd1059aacde1b477e0c80c142910f1ceae67fc619311d6a17428007ab" +checksum = "2073678591747aed4000dd468b97b14d7007f7936851d3f2f01846899f5ebf08" dependencies = [ - "blake2b_simd", - "ff 0.13.0", - "group 0.13.0", - "lazy_static", - "num-bigint", - "num-traits", - "pasta_curves 0.5.1", - "paste", - "rand 0.8.5", - "rand_core 0.6.4", - "static_assertions", - "subtle", + "bs58 0.5.1", + "coins-core", + "digest 0.10.7", + "hmac", + "k256", + "serde", + "sha2", + "thiserror 1.0.69", ] [[package]] -name = "halo2curves" -version = "0.3.1" -source = "git+https://github.com/scroll-tech/halo2curves.git?branch=0.3.1-derive-serde#969f1e44d9713ee4cd552563bd0c762c5d53b56e" +name = "coins-bip39" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74b169b26623ff17e9db37a539fe4f15342080df39f129ef7631df7683d6d9d4" dependencies = [ - "ff 0.12.1", - "group 0.12.1", - "lazy_static", - "num-bigint", - "num-traits", - "pasta_curves 0.4.1", - "paste", + "bitvec", + "coins-bip32", + "hmac", + "once_cell", + "pbkdf2 0.12.2", "rand 0.8.5", - "rand_core 0.6.4", - "serde", - "static_assertions", - "subtle", + "sha2", + "thiserror 1.0.69", ] [[package]] -name = "halo2wrong" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" +name = "coins-core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b962ad8545e43a28e14e87377812ba9ae748dd4fd963f4c10e9fcc6d13475b" dependencies = [ - "group 0.12.1", - "halo2_proofs 0.2.0", - "num-bigint", - "num-integer", - "num-traits", + "base64 0.21.7", + "bech32", + "bs58 0.5.1", + "const-hex", + "digest 0.10.7", + "generic-array", + "ripemd", + "serde", + "sha2", + "sha3", + "thiserror 1.0.69", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "color-eyre" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" +dependencies = [ + "backtrace", + "color-spantrace", + "eyre", + "indenter", + "once_cell", + "owo-colors", + "tracing-error", +] [[package]] -name = "hashbrown" -version = "0.13.2" +name = "color-spantrace" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" dependencies = [ - "ahash", + "once_cell", + "owo-colors", + "tracing-core", + "tracing-error", ] [[package]] -name = "hashbrown" -version = "0.14.2" +name = "colorchoice" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] -name = "hashers" -version = "1.0.1" +name = "colored" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +checksum = "5a5f741c91823341bebf717d4c71bda820630ce065443b58bd1b7451af008355" dependencies = [ - "fxhash", + "is-terminal", + "lazy_static", + "winapi", ] [[package]] -name = "headers" -version = "0.3.9" +name = "combine" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "base64 0.21.5", "bytes", - "headers-core", - "http", - "httpdate", - "mime", - "sha1", + "memchr", ] [[package]] -name = "headers-core" -version = "0.2.0" +name = "compression-codecs" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" dependencies = [ - "http", + "brotli", + "compression-core", + "flate2", + "memchr", + "zstd 0.13.3", + "zstd-safe 7.2.4", ] [[package]] -name = "heck" -version = "0.4.1" +name = "compression-core" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" [[package]] -name = "heck" -version = "0.5.0" +name = "concat-kdf" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "2d72c1252426a83be2092dd5884a5f6e3b8e7180f6891b6263d2c21b92ec8816" +dependencies = [ + "digest 0.10.7", +] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "concurrent-queue" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ - "libc", + "crossbeam-utils", ] [[package]] -name = "hermit-abi" -version = "0.3.3" +name = "console" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hex" -version = "0.4.3" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "windows-sys 0.59.0", +] + +[[package]] +name = "const-hex" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" dependencies = [ - "serde", + "cfg-if", + "cpufeatures", + "proptest", + "serde_core", ] [[package]] -name = "hex-literal" -version = "0.3.4" +name = "const-oid" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] -name = "hex_fmt" -version = "0.3.0" +name = "const-str" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" +checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" [[package]] -name = "hmac" -version = "0.8.1" +name = "const_format" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ - "crypto-mac", - "digest 0.9.0", + "const_format_proc_macros", ] [[package]] -name = "hmac" -version = "0.12.1" +name = "const_format_proc_macros" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ - "digest 0.10.7", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] -name = "hmac-drbg" -version = "0.3.0" +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array", - "hmac 0.8.1", -] +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] -name = "hostname" +name = "constant_time_eq" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" -dependencies = [ - "libc", - "match_cfg", - "winapi", -] +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] -name = "http" -version = "0.2.10" +name = "constant_time_eq" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" -dependencies = [ - "bytes", - "fnv", - "itoa", -] +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +name = "constants" +version = "0.1.0" dependencies = [ - "bytes", - "http", - "pin-project-lite", + "workspace-hack", ] [[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +name = "contextful" +version = "0.1.0" +dependencies = [ + "contextful-macros", + "serde", + "serde_json", + "thiserror 1.0.69", + "workspace-hack", +] [[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +name = "contextful-macros" +version = "0.1.0" +dependencies = [ + "quote", + "syn 2.0.112", + "workspace-hack", +] [[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +name = "contracts" +version = "1.3.0" dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.10", + "barretenberg-cli", + "contextful", + "element", + "eth-util", + "ethereum-types", + "expect-test", + "hash", + "hex", + "parking_lot 0.12.5", + "rand 0.8.5", + "reqwest 0.12.28", + "rustc-hex", + "secp256k1 0.28.2", + "serde_json", + "sha3", + "smirk", + "testutil", + "thiserror 1.0.69", "tokio", - "tower-service", "tracing", - "want", + "web3", + "workspace-hack", + "zk-circuits", + "zk-primitives", ] [[package]] -name = "hyper-rustls" -version = "0.24.2" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls 0.21.9", - "tokio", - "tokio-rustls", -] +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] -name = "hyper-timeout" -version = "0.4.1" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ - "hyper", - "pin-project-lite", - "tokio", - "tokio-io-timeout", + "unicode-segmentation", ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "cookie" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", + "percent-encoding", + "time", + "version_check", ] [[package]] -name = "iana-time-zone" -version = "0.1.58" +name = "core-foundation" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "android_system_properties", "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", + "libc", ] [[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" +name = "core-foundation" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ - "cc", + "core-foundation-sys", + "libc", ] [[package]] -name = "ident_case" -version = "1.0.1" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "idna" -version = "0.2.3" +name = "core2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "memchr", ] [[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +name = "country" +version = "0.1.0" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "diesel", + "serde", + "strum 0.27.2", + "strum_macros 0.27.2", + "workspace-hack", ] [[package]] -name = "if-addrs" -version = "0.10.2" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", - "windows-sys 0.48.0", ] [[package]] -name = "if-watch" -version = "3.2.0" +name = "crc" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" dependencies = [ - "async-io", - "core-foundation", - "fnv", - "futures", - "if-addrs", - "ipnet", - "log", - "rtnetlink", - "system-configuration", - "tokio", - "windows", + "crc-catalog", ] [[package]] -name = "impl-codec" -version = "0.6.0" +name = "crc-catalog" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] -name = "impl-rlp" -version = "0.3.0" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "rlp", + "cfg-if", ] [[package]] -name = "impl-serde" -version = "0.4.0" +name = "critical-section" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -dependencies = [ - "serde", -] +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "crossbeam-utils", ] [[package]] -name = "indenter" -version = "0.3.3" +name = "crossbeam-deque" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] [[package]] -name = "indexmap" -version = "1.9.3" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "crossbeam-utils", ] [[package]] -name = "indexmap" -version = "2.0.2" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" -dependencies = [ - "equivalent", - "hashbrown 0.14.2", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "inlinable_string" -version = "0.1.15" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "inout" -version = "0.1.3" +name = "crypto-bigint" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", ] [[package]] -name = "insta" -version = "1.34.0" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "console", - "lazy_static", - "linked-hash-map", - "serde", - "similar", - "yaml-rust", + "generic-array", + "rand_core 0.6.4", + "typenum", ] [[package]] -name = "instant" -version = "0.1.12" +name = "crypto_secretbox" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" dependencies = [ - "cfg-if 1.0.0", + "aead", + "cipher", + "generic-array", + "poly1305", + "salsa20", + "subtle", + "zeroize", ] [[package]] -name = "ipconfig" -version = "0.3.2" +name = "ctr" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "socket2 0.5.5", - "widestring", - "windows-sys 0.48.0", - "winreg", + "cipher", ] [[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +name = "currency" +version = "0.1.0" +dependencies = [ + "country", + "diesel", + "element", + "serde", + "serde_json", + "strum 0.27.2", + "strum_macros 0.27.2", + "thiserror 1.0.69", + "ts-rs", + "workspace-hack", +] [[package]] -name = "is-terminal" -version = "0.4.9" +name = "curve25519-dalek" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ - "hermit-abi 0.3.3", - "rustix", - "windows-sys 0.48.0", + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", ] [[package]] -name = "itertools" -version = "0.10.5" +name = "curve25519-dalek" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "either", + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rustc_version 0.4.1", + "subtle", + "zeroize", ] [[package]] -name = "itertools" -version = "0.11.0" +name = "curve25519-dalek-derive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ - "either", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "itoa" -version = "1.0.9" +name = "darling" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] [[package]] -name = "jobserver" -version = "0.1.27" +name = "darling" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "libc", + "darling_core 0.21.3", + "darling_macro 0.21.3", ] [[package]] -name = "js-sys" -version = "0.3.65" +name = "darling_core" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ - "wasm-bindgen", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.112", ] [[package]] -name = "jsonrpc-core" -version = "18.0.0" +name = "darling_core" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ - "futures", - "futures-executor", - "futures-util", - "log", + "fnv", + "ident_case", + "proc-macro2", + "quote", "serde", - "serde_derive", - "serde_json", + "strsim", + "syn 2.0.112", ] [[package]] -name = "k256" -version = "0.11.6" +name = "darling_macro" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "cfg-if 1.0.0", - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", - "sha2 0.10.8", - "sha3 0.10.8", + "darling_core 0.20.11", + "quote", + "syn 2.0.112", ] [[package]] -name = "k256" -version = "0.13.2" +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "dashmap" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", - "ecdsa 0.16.9", - "elliptic-curve 0.13.8", + "cfg-if", + "hashbrown 0.14.5", + "lock_api", "once_cell", - "sha2 0.10.8", - "signature 2.2.0", + "parking_lot_core 0.9.12", ] [[package]] -name = "keccak" -version = "0.1.4" +name = "dashmap" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "cpufeatures", + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core 0.9.12", ] [[package]] -name = "keccak256" +name = "data" version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" dependencies = [ - "env_logger 0.10.0", - "eth-types", - "halo2_proofs 0.2.0", - "itertools 0.10.5", - "lazy_static", - "log", - "num-bigint", - "num-traits", + "async-stripe", + "chrono", + "database", + "diesel", + "diesel-util", + "element", + "kyc", + "primitives", + "serde", + "serde_json", + "strum 0.27.2", + "ts-rs", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "language-tags" -version = "0.3.2" +name = "data-encoding" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] -name = "lazy_static" -version = "1.4.0" +name = "data-encoding-macro" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d" dependencies = [ - "spin 0.5.2", + "data-encoding", + "data-encoding-macro-internal", ] [[package]] -name = "lazycell" -version = "1.3.0" +name = "data-encoding-macro-internal" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976" +dependencies = [ + "data-encoding", + "syn 2.0.112", +] [[package]] -name = "libc" -version = "0.2.149" +name = "data-url" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" [[package]] -name = "libloading" -version = "0.7.4" +name = "database" +version = "0.1.0" +dependencies = [ + "contextful", + "diesel", + "serial_test", + "tokio", + "tokio-postgres", + "workspace-hack", +] + +[[package]] +name = "deadpool" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "0be2b1d1d6ec8d846f05e137292d0b89133caf95ef33695424c09568bdd39b1b" dependencies = [ - "cfg-if 1.0.0", - "winapi", + "deadpool-runtime", + "lazy_static", + "num_cpus", + "tokio", ] [[package]] -name = "libm" -version = "0.2.8" +name = "deadpool-runtime" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +dependencies = [ + "tokio", +] [[package]] -name = "libp2p" -version = "0.51.4" +name = "debug-helper" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f35eae38201a993ece6bdc823292d6abd1bffed1c4d0f4a3517d2bd8e1d917fe" +checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e" + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" dependencies = [ - "bytes", - "futures", - "futures-timer", - "getrandom 0.2.11", - "instant", - "libp2p-allow-block-list", - "libp2p-connection-limits", - "libp2p-core", - "libp2p-dns", - "libp2p-gossipsub", - "libp2p-identify", - "libp2p-identity", - "libp2p-mdns", - "libp2p-metrics", - "libp2p-noise", - "libp2p-ping", - "libp2p-quic", - "libp2p-request-response", - "libp2p-swarm", - "libp2p-tcp", - "libp2p-yamux", - "multiaddr", - "pin-project", + "serde", + "uuid 1.19.0", ] [[package]] -name = "libp2p-allow-block-list" -version = "0.1.1" +name = "delay_map" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "510daa05efbc25184458db837f6f9a5143888f1caa742426d92e1833ddd38a50" +checksum = "88e365f083a5cb5972d50ce8b1b2c9f125dc5ec0f50c0248cfb568ae59efcf0b" dependencies = [ - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "void", + "futures", + "tokio", + "tokio-util", ] [[package]] -name = "libp2p-connection-limits" -version = "0.1.0" +name = "deno_ast" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4caa33f1d26ed664c4fe2cca81a08c8e07d4c1c04f2f4ac7655c2dd85467fda0" +checksum = "30c2f6f65154faed61e45d6578566f9fab9d2a330c35c87366706883701cce51" dependencies = [ - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "void", + "capacity_builder", + "deno_error", + "deno_media_type", + "deno_terminal", + "dprint-swc-ext", + "percent-encoding", + "serde", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_lexer", + "swc_ecma_parser", + "swc_eq_ignore_macros", + "text_lines", + "thiserror 2.0.17", + "unicode-width 0.2.2", + "url", ] [[package]] -name = "libp2p-core" -version = "0.39.2" +name = "deno_error" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" +checksum = "3007d3f1ea92ea503324ae15883aac0c2de2b8cf6fead62203ff6a67161007ab" dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-identity", - "log", - "multiaddr", - "multihash", - "multistream-select", - "once_cell", - "parking_lot 0.12.1", - "pin-project", - "quick-protobuf", - "rand 0.8.5", - "rw-stream-sink", - "smallvec", - "thiserror", - "unsigned-varint", - "void", + "deno_error_macro", + "libc", ] [[package]] -name = "libp2p-dns" -version = "0.39.0" +name = "deno_error_macro" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146ff7034daae62077c415c2376b8057368042df6ab95f5432ad5e88568b1554" +checksum = "9b565e60a9685cdf312c888665b5f8647ac692a7da7e058a5e2268a466da8eaf" dependencies = [ - "futures", - "libp2p-core", - "log", - "parking_lot 0.12.1", - "smallvec", - "trust-dns-resolver", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "libp2p-gossipsub" -version = "0.44.4" +name = "deno_media_type" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70b34b6da8165c0bde35c82db8efda39b824776537e73973549e76cadb3a77c5" +checksum = "9fd0af4161f90b092feb363864a64d7c74e0efc13a15905d0d09df73bb72a123" dependencies = [ - "asynchronous-codec", - "base64 0.21.5", - "byteorder", - "bytes", - "either", - "fnv", - "futures", - "hex_fmt", - "instant", - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "log", - "prometheus-client", - "quick-protobuf", - "quick-protobuf-codec", - "rand 0.8.5", - "regex", - "sha2 0.10.8", - "smallvec", - "thiserror", - "unsigned-varint", - "void", - "wasm-timer", + "data-url", + "serde", + "url", ] [[package]] -name = "libp2p-identify" -version = "0.42.2" +name = "deno_terminal" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5455f472243e63b9c497ff320ded0314254a9eb751799a39c283c6f20b793f3c" +checksum = "f3ba8041ae7319b3ca6a64c399df4112badcbbe0868b4517637647614bede4be" dependencies = [ - "asynchronous-codec", - "either", - "futures", - "futures-timer", - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "log", - "lru", - "quick-protobuf", - "quick-protobuf-codec", - "smallvec", - "thiserror", - "void", + "once_cell", + "termcolor", ] [[package]] -name = "libp2p-identity" -version = "0.1.3" +name = "der" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ - "bs58 0.4.0", - "ed25519-dalek", - "log", - "multiaddr", - "multihash", - "quick-protobuf", - "rand 0.8.5", - "sha2 0.10.8", - "thiserror", + "const-oid", + "pem-rfc7468", "zeroize", ] [[package]] -name = "libp2p-mdns" -version = "0.43.1" +name = "der-parser" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19983e1f949f979a928f2c603de1cf180cc0dc23e4ac93a62651ccb18341460b" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" dependencies = [ - "data-encoding", - "futures", - "if-watch", - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "log", - "rand 0.8.5", - "smallvec", - "socket2 0.4.10", - "tokio", - "trust-dns-proto", - "void", + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", ] [[package]] -name = "libp2p-metrics" -version = "0.12.0" +name = "deranged" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a42ec91e227d7d0dafa4ce88b333cdf5f277253873ab087555c92798db2ddd46" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ - "libp2p-core", - "libp2p-gossipsub", - "libp2p-identify", - "libp2p-ping", - "libp2p-swarm", - "prometheus-client", + "powerfmt", + "serde_core", ] [[package]] -name = "libp2p-noise" -version = "0.42.2" +name = "derivative" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3673da89d29936bc6435bafc638e2f184180d554ce844db65915113f86ec5e" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "bytes", - "curve25519-dalek 3.2.0", - "futures", - "libp2p-core", - "libp2p-identity", - "log", - "once_cell", - "quick-protobuf", - "rand 0.8.5", - "sha2 0.10.8", - "snow", - "static_assertions", - "thiserror", - "x25519-dalek", - "zeroize", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "libp2p-ping" -version = "0.42.0" +name = "derive-where" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e57759c19c28a73ef1eb3585ca410cefb72c1a709fcf6de1612a378e4219202" +checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ - "either", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-swarm", - "log", - "rand 0.8.5", - "void", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "libp2p-quic" -version = "0.7.0-alpha.3" +name = "derive_builder" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b26abd81cd2398382a1edfe739b539775be8a90fa6914f39b2ab49571ec735" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ - "bytes", - "futures", - "futures-timer", - "if-watch", - "libp2p-core", - "libp2p-identity", - "libp2p-tls", - "log", - "parking_lot 0.12.1", - "quinn-proto", - "rand 0.8.5", - "rustls 0.20.9", - "thiserror", - "tokio", + "derive_builder_macro", ] [[package]] -name = "libp2p-request-response" -version = "0.24.1" +name = "derive_builder_core" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffdb374267d42dc5ed5bc53f6e601d4a64ac5964779c6e40bb9e4f14c1e30d5" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "async-trait", - "futures", - "instant", - "libp2p-core", - "libp2p-identity", - "libp2p-swarm", - "rand 0.8.5", - "smallvec", + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "libp2p-swarm" -version = "0.42.2" +name = "derive_builder_macro" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903b3d592d7694e56204d211f29d31bc004be99386644ba8731fc3e3ef27b296" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ - "either", - "fnv", - "futures", - "futures-timer", - "instant", - "libp2p-core", - "libp2p-identity", - "libp2p-swarm-derive", - "log", - "rand 0.8.5", - "smallvec", - "tokio", - "void", + "derive_builder_core", + "syn 2.0.112", ] [[package]] -name = "libp2p-swarm-derive" -version = "0.32.0" +name = "derive_more" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fba456131824ab6acd4c7bf61e9c0f0a3014b5fc9868ccb8e10d344594cdc4f" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ - "heck 0.4.1", + "convert_case 0.4.0", + "proc-macro2", "quote", - "syn 1.0.109", + "rustc_version 0.4.1", + "syn 2.0.112", ] [[package]] -name = "libp2p-tcp" -version = "0.39.0" +name = "derive_more" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d33698596d7722d85d3ab0c86c2c322254fce1241e91208e3679b4eb3026cf" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" dependencies = [ - "futures", - "futures-timer", - "if-watch", - "libc", - "libp2p-core", - "log", - "socket2 0.4.10", - "tokio", + "derive_more-impl 1.0.0", ] [[package]] -name = "libp2p-tls" -version = "0.1.0" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ - "futures", - "futures-rustls", - "libp2p-core", - "libp2p-identity", - "rcgen", - "ring 0.16.20", - "rustls 0.20.9", - "thiserror", - "webpki", - "x509-parser", - "yasna", + "derive_more-impl 2.1.1", ] [[package]] -name = "libp2p-yamux" -version = "0.43.1" +name = "derive_more-impl" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd21d950662700a385d4c6d68e2f5f54d778e97068cdd718522222ef513bda" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "futures", - "libp2p-core", - "log", - "thiserror", - "yamux", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "libredox" -version = "0.0.1" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "bitflags 2.4.1", - "libc", - "redox_syscall 0.4.1", + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "syn 2.0.112", + "unicode-xid", ] [[package]] -name = "librocksdb-sys" -version = "0.11.0+8.1.1" +name = "diesel" +version = "2.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" +checksum = "f4ae09a41a4b89f94ec1e053623da8340d996bc32c6517d325a9daad9b239358" dependencies = [ - "bindgen", - "bzip2-sys", - "cc", - "glob", - "libc", - "libz-sys", - "lz4-sys", - "zstd-sys", + "bigdecimal", + "bitflags 2.10.0", + "byteorder", + "chrono", + "diesel_derives", + "downcast-rs", + "itoa 1.0.17", + "num-bigint", + "num-integer", + "num-traits", + "pq-sys", + "serde_json", + "uuid 1.19.0", ] [[package]] -name = "libsecp256k1" -version = "0.7.1" +name = "diesel-async" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" +checksum = "13096fb8dae53f2d411c4b523bec85f45552ed3044a2ab4d85fb2092d9cb4f34" dependencies = [ - "arrayref", - "base64 0.13.1", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand 0.8.5", - "serde", - "sha2 0.9.9", - "typenum", + "deadpool", + "diesel", + "futures-core", + "futures-util", + "scoped-futures", + "tokio", + "tokio-postgres", ] [[package]] -name = "libsecp256k1-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +name = "diesel-util" +version = "0.1.0" dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", + "diesel", + "workspace-hack", ] [[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.3.0" +name = "diesel_derives" +version = "2.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +checksum = "c30b2969f923fa1f73744b92bb7df60b858df8832742d9a3aceb79236c0be1d2" dependencies = [ - "libsecp256k1-core", + "diesel_table_macro_syntax", + "dsl_auto_type", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "libsecp256k1-gen-genmult" +name = "diesel_table_macro_syntax" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c" dependencies = [ - "libsecp256k1-core", + "syn 2.0.112", ] [[package]] -name = "libz-sys" -version = "1.1.12" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" -dependencies = [ - "cc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] -name = "linux-raw-sys" -version = "0.4.10" +name = "difference" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" [[package]] -name = "local-channel" -version = "0.1.5" +name = "digest" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "futures-core", - "futures-sink", - "local-waker", + "generic-array", ] [[package]] -name = "local-waker" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" - -[[package]] -name = "lock_api" -version = "0.4.11" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "autocfg", - "scopeguard", + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", ] [[package]] -name = "log" -version = "0.4.20" +name = "dirs" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] [[package]] -name = "lru" -version = "0.10.1" +name = "dirs-next" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "hashbrown 0.13.2", + "cfg-if", + "dirs-sys-next", ] [[package]] -name = "lru-cache" -version = "0.1.2" +name = "dirs-sys" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ - "linked-hash-map", + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", ] [[package]] -name = "lz4-sys" -version = "1.9.4" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ - "cc", "libc", + "redox_users", + "winapi", ] [[package]] -name = "maingate" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" +name = "discv5" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f170f4f6ed0e1df52bf43b403899f0081917ecf1500bfe312505cc3b515a8899" dependencies = [ - "group 0.12.1", - "halo2wrong", - "num-bigint", - "num-integer", - "num-traits", + "aes", + "aes-gcm", + "alloy-rlp", + "arrayvec", + "ctr", + "delay_map", + "enr", + "fnv", + "futures", + "hashlink", + "hex", + "hkdf", + "lazy_static", + "libp2p-identity 0.2.13", + "lru 0.12.5", + "more-asserts", + "multiaddr 0.18.2", + "parking_lot 0.12.5", "rand 0.8.5", - "subtle", + "smallvec", + "socket2 0.5.10", + "tokio", + "tracing", + "uint 0.10.0", + "zeroize", ] [[package]] -name = "match_cfg" -version = "0.1.0" +name = "dispatch2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.10.0", + "objc2", +] [[package]] -name = "matchers" -version = "0.1.0" +name = "displaydoc" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ - "regex-automata 0.1.10", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "matches" -version = "0.1.10" +name = "dissimilar" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" [[package]] -name = "matchit" -version = "0.7.3" +name = "doc-comment" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +checksum = "780955b8b195a21ab8e4ac6b60dd1dbdcec1dc6c51c0617964b08c81785e12c9" [[package]] -name = "maybe-rayon" -version = "0.1.1" +name = "doctest-file" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +checksum = "aac81fa3e28d21450aa4d2ac065992ba96a1d7303efbce51a95f4fd175b67562" + +[[package]] +name = "document-ai-google" +version = "0.1.0" dependencies = [ - "cfg-if 1.0.0", - "rayon", + "async-trait", + "base64 0.22.1", + "chrono", + "contextful", + "country", + "document-ai-interface", + "reqwest 0.12.28", + "serde", + "serde_json", + "tracing", + "workspace-hack", ] [[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +name = "document-ai-interface" +version = "0.1.0" dependencies = [ - "cfg-if 1.0.0", - "digest 0.10.7", + "async-trait", + "chrono", + "contextful", + "country", + "reqwest 0.12.28", + "serde", + "serde_json", + "thiserror 1.0.69", + "workspace-hack", ] [[package]] -name = "memchr" -version = "2.6.4" +name = "doomslug" +version = "1.3.0" +dependencies = [ + "borsh", + "chrono", + "primitives", + "serde", + "sha3", + "thiserror 1.0.69", + "tracing", + "workspace-hack", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" [[package]] -name = "memoffset" -version = "0.9.0" +name = "downcast-rs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" + +[[package]] +name = "dprint-core" +version = "0.67.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "2c1d827947704a9495f705d6aeed270fa21a67f825f22902c28f38dc3af7a9ae" dependencies = [ - "autocfg", + "anyhow", + "bumpalo", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "rustc-hash 2.1.1", + "serde", + "unicode-width 0.2.2", ] [[package]] -name = "memory-stats" -version = "1.1.0" +name = "dprint-core-macros" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34f79cf9964c5c9545493acda1263f1912f8d2c56c8a2ffee2606cb960acaacc" +checksum = "1675ad2b358481f3cc46202040d64ac7a36c4ade414a696df32e0e45421a6e9f" dependencies = [ - "libc", - "winapi", + "quote", + "syn 1.0.109", ] [[package]] -name = "microtype" -version = "0.7.6" +name = "dprint-plugin-typescript" +version = "0.95.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91051219f867e549222950d8509b98c4168ee2eada13aa81331c34cbc0b7916d" +checksum = "f8c3e39abf274d7f85a017691da2d4c78db0141425d05201b7249de4a48cabd1" dependencies = [ - "microtype-macro", - "secrecy", + "anyhow", + "capacity_builder", + "deno_ast", + "dprint-core", + "dprint-core-macros", + "percent-encoding", + "rustc-hash 2.1.1", + "serde", ] [[package]] -name = "microtype-macro" -version = "0.2.6" +name = "dprint-swc-ext" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f65cf1066f1a4836a0a93493938af5a93c686e430c34b57fcbb1f6854f93f5" +checksum = "33175ddb7a6d418589cab2966bd14a710b3b1139459d3d5ca9edf783c4833f4c" +dependencies = [ + "allocator-api2", + "bumpalo", + "num-bigint", + "rustc-hash 2.1.1", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_lexer", + "swc_ecma_parser", + "text_lines", +] + +[[package]] +name = "dsl_auto_type" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e" dependencies = [ + "darling 0.21.3", + "either", + "heck 0.5.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.112", ] [[package]] -name = "mime" -version = "0.3.17" +name = "dtoa" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" [[package]] -name = "mime_guess" -version = "2.0.5" +name = "dtoa" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "duct" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e66e9c0c03d094e1a0ba1be130b849034aa80c3a2ab8ee94316bc809f3fa684" dependencies = [ - "mime", - "unicase", + "libc", + "os_pipe", + "shared_child", + "shared_thread", ] [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "dunce" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] -name = "miniz_oxide" -version = "0.7.1" +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "ecdsa" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ - "adler", + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", ] [[package]] -name = "mio" -version = "0.8.9" +name = "ed25519" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "pkcs8", + "signature", ] [[package]] -name = "misc-precompiled-circuit" -version = "0.1.0" -source = "git+https://github.com/scroll-tech/misc-precompiled-circuit.git?tag=v0.1.0#f647341f9951f5c2399035728d4f6765564e2e02" +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ - "halo2-gate-generator", - "halo2_proofs 0.2.0", - "lazy_static", - "num-bigint", - "rand 0.8.5", + "curve25519-dalek 4.1.3", + "ed25519", + "rand_core 0.6.4", "serde", - "serde_json", - "strum 0.24.1", - "strum_macros 0.24.3", + "sha2", "subtle", + "zeroize", ] [[package]] -name = "mock" -version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" dependencies = [ - "eth-types", - "ethers-core 2.0.7", - "ethers-signers", - "external-tracer", - "itertools 0.10.5", - "lazy_static", - "log", - "rand 0.8.5", - "rand_chacha", + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "mpt-zktrie" +name = "eip7702" version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" dependencies = [ - "eth-types", - "halo2-mpt-circuits", - "halo2_proofs 0.2.0", + "async-trait", + "client-http", + "contextful", + "eth-util", + "ethereum-types", "hex", - "lazy_static", - "log", - "num-bigint", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit.git?branch=scroll-dev-0901)", - "zktrie", + "reqwest 0.12.28", + "rlp 0.6.1", + "secp256k1 0.28.2", + "serde_json", + "sha3", + "test-spy", + "testutil", + "thiserror 1.0.69", + "tokio", + "tracing", + "web3", + "workspace-hack", ] [[package]] -name = "multiaddr" -version = "0.17.1" +name = "either" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b36f567c7099511fa8612bbbb52dda2419ce0bdbacf31714e3a5ffdb766d3bd" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" dependencies = [ - "arrayref", - "byteorder", - "data-encoding", - "log", - "multibase", - "multihash", - "percent-encoding", "serde", - "static_assertions", - "unsigned-varint", - "url", ] [[package]] -name = "multibase" -version = "0.9.1" +name = "element" +version = "0.1.0" +dependencies = [ + "acvm", + "bitvec", + "borsh", + "diesel", + "ethnum", + "hex", + "insta", + "proptest", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift 0.3.0", + "serde", + "serde_json", + "test-strategy", + "ts-rs", + "workspace-hack", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base-x", - "data-encoding", - "data-encoding-macro", + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "serdect", + "subtle", + "zeroize", ] [[package]] -name = "multihash" -version = "0.17.0" +name = "ena" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ - "core2", - "multihash-derive", - "unsigned-varint", + "log", ] [[package]] -name = "multihash-derive" -version = "0.8.1" +name = "encode_unicode" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure", + "cfg-if", ] [[package]] -name = "multistream-select" -version = "0.12.1" +name = "encrypt" +version = "0.1.0" +dependencies = [ + "crypto_secretbox", + "thiserror 1.0.69", + "workspace-hack", + "x25519-dalek 2.0.1", +] + +[[package]] +name = "enr" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" +checksum = "851bd664a3d3a3c175cff92b2f0df02df3c541b4895d0ae307611827aae46152" dependencies = [ + "alloy-rlp", + "base64 0.22.1", "bytes", - "futures", + "ed25519-dalek", + "hex", + "k256", "log", - "pin-project", - "smallvec", - "unsigned-varint", + "rand 0.8.5", + "secp256k1 0.30.0", + "serde", + "sha3", + "zeroize", ] [[package]] -name = "native-tls" -version = "0.2.12" +name = "enum-as-inner" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "netlink-packet-core" -version = "0.4.2" +name = "enum-as-inner" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345b8ab5bd4e71a2986663e88c56856699d060e78e152e6e9d7966fcd5491297" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "anyhow", - "byteorder", - "libc", - "netlink-packet-utils", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "netlink-packet-route" -version = "0.12.0" +name = "enum-ordinalize" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" dependencies = [ - "anyhow", - "bitflags 1.3.2", - "byteorder", - "libc", - "netlink-packet-core", - "netlink-packet-utils", + "enum-ordinalize-derive", ] [[package]] -name = "netlink-packet-utils" -version = "0.5.2" +name = "enum-ordinalize-derive" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "netlink-proto" -version = "0.10.0" +name = "env_logger" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65b4b14489ab424703c092062176d52ba55485a89c076b4f9db05092b7223aa6" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ - "bytes", - "futures", "log", - "netlink-packet-core", - "netlink-sys", - "thiserror", - "tokio", + "regex", ] [[package]] -name = "netlink-sys" -version = "0.8.5" +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6471bf08e7ac0135876a9581bf3217ef0333c191c128d34878079f42ee150411" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "bytes", - "futures", "libc", - "log", - "tokio", + "windows-sys 0.61.2", ] [[package]] -name = "nix" -version = "0.24.3" +name = "error-chain" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ - "bitflags 1.3.2", - "cfg-if 1.0.0", - "libc", + "version_check", ] [[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +name = "eth-util" +version = "0.1.0" dependencies = [ - "bitflags 2.4.1", - "cfg-if 1.0.0", - "libc", + "element", + "ethereum-types", + "secp256k1 0.28.2", + "sha3", + "workspace-hack", ] [[package]] -name = "node" -version = "1.3.0" +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" dependencies = [ - "actix-cors", - "actix-server", - "actix-web", - "async-trait", - "base64 0.21.5", - "block-store", - "borsh", - "burn-substitutor", - "chrono", - "clap", - "color-eyre", - "contracts", - "derivative", - "dirs", - "doomslug", - "dotenvy", - "either", "ethereum-types", - "expect-test", - "eyre", - "figment", - "futures", "hex", - "itertools 0.11.0", - "libp2p", - "microtype", - "native-tls", "once_cell", - "p2p2", - "parking_lot 0.12.1", - "postgres-native-tls", - "primitives", - "prover", - "rand 0.8.5", - "rand_derive2", - "reqwest", - "rocksdb", - "rpc", - "rustc-hex", - "scopeguard", - "secp256k1 0.28.1", - "sentry", + "regex", "serde", "serde_json", - "serial_test", - "sha3 0.10.8", - "smirk", - "strum 0.26.3", - "tempdir", - "testutil", - "thiserror", - "tiny-keccak", - "tokio", - "tokio-postgres", - "tokio-stream", - "tracing", - "tracing-stackdriver", - "tracing-subscriber", - "web3", - "wire-message", - "zk-circuits", - "zk-primitives", + "sha3", + "thiserror 1.0.69", + "uint 0.9.5", ] [[package]] -name = "nohash-hasher" -version = "0.2.0" +name = "ethbloom" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] [[package]] -name = "nom" -version = "7.1.3" +name = "ethereum-types" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ - "memchr", - "minimal-lexical", + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "primitive-types", + "scale-info", + "uint 0.9.5", ] [[package]] -name = "nu-ansi-term" -version = "0.46.0" +name = "ethereum_hashing" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "c853bd72c9e5787f8aafc3df2907c2ed03cff3150c3acd94e2e53a98ab70a8ab" dependencies = [ - "overload", - "winapi", + "cpufeatures", + "ring 0.17.14", + "sha2", ] [[package]] -name = "num" -version = "0.4.1" +name = "ethereum_serde_utils" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "3dc1355dbb41fbbd34ec28d4fb2a57d9a70c67ac3c19f6a5ca4d4a176b9e997a" dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", + "alloy-primitives", + "hex", + "serde", + "serde_derive", + "serde_json", ] [[package]] -name = "num-bigint" -version = "0.4.6" +name = "ethereum_ssz" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "0dcddb2554d19cde19b099fadddde576929d7a4d0c1cd3512d1fd95cf174375c" dependencies = [ - "num-integer", - "num-traits", - "rand 0.8.5", + "alloy-primitives", + "ethereum_serde_utils", + "itertools 0.13.0", + "serde", + "serde_derive", + "smallvec", + "typenum", ] [[package]] -name = "num-complex" -version = "0.4.4" +name = "ethereum_ssz_derive" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "a657b6b3b7e153637dc6bdc6566ad9279d9ee11a15b12cfb24a2e04360637e9f" dependencies = [ - "num-traits", + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" +name = "ethers-core" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" dependencies = [ - "num-traits", + "arrayvec", + "bytes", + "chrono", + "const-hex", + "elliptic-curve", + "ethabi", + "generic-array", + "k256", + "num_enum", + "open-fastrlp", + "rand 0.8.5", + "rlp 0.5.2", + "serde", + "serde_json", + "strum 0.26.3", + "tempfile", + "thiserror 1.0.69", + "tiny-keccak", + "unicode-xid", ] [[package]] -name = "num-iter" -version = "0.1.43" +name = "ethers-solc" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "66244a771d9163282646dbeffe0e6eca4dda4146b6498644e678ac6089b11edd" dependencies = [ - "autocfg", - "num-integer", - "num-traits", + "cfg-if", + "const-hex", + "dirs", + "dunce", + "ethers-core", + "glob", + "home", + "md-5", + "num_cpus", + "once_cell", + "path-slash", + "rayon", + "regex", + "semver 1.0.27", + "serde", + "serde_json", + "solang-parser", + "svm-rs", + "thiserror 1.0.69", + "tiny-keccak", + "tokio", + "tracing", + "walkdir", + "yansi 0.5.1", ] [[package]] -name = "num-rational" -version = "0.4.1" +name = "ethnum" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] +checksum = "ca81e6b4777c89fd810c25a4be2b1bd93ea034fbe58e6a75216a34c6b82c539b" [[package]] -name = "num-traits" -version = "0.2.19" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] -name = "num_cpus" -version = "1.16.0" +name = "event-listener" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ - "hermit-abi 0.3.3", - "libc", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] -name = "num_enum" -version = "0.5.11" +name = "event-listener-strategy" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "num_enum_derive 0.5.11", + "event-listener 5.4.1", + "pin-project-lite", ] [[package]] -name = "num_enum" -version = "0.6.1" +name = "expect-test" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" dependencies = [ - "num_enum_derive 0.6.1", + "dissimilar", + "once_cell", ] [[package]] -name = "num_enum" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +name = "expo_push_notification_client" +version = "0.5.1" +source = "git+https://github.com/polybase/expo-push-notification-client-rust.git?branch=rustc-1_68_nightly#a9d250842b0cc4fe94023ff70838ead56c141221" dependencies = [ - "num_enum_derive 0.7.1", + "async-compression", + "regex", + "reqwest 0.11.27", + "serde", + "serde_json", + "serde_with", + "thiserror 1.0.69", + "tokio", ] [[package]] -name = "num_enum_derive" -version = "0.5.11" +name = "extend" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "f47da3a72ec598d9c8937a7ebca8962a5c7a1f28444e38c2b33c771ba3f55f05" dependencies = [ - "proc-macro-crate 1.1.3", + "proc-macro-error", "proc-macro2", "quote", "syn 1.0.109", ] [[package]] -name = "num_enum_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" -dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro2", - "quote", - "syn 2.0.40", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.1" +name = "eyre" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro2", - "quote", - "syn 2.0.40", + "indenter", + "once_cell", ] [[package]] -name = "object" -version = "0.32.1" +name = "fallible-iterator" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] -name = "oid-registry" -version = "0.6.1" +name = "fastrand" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ - "asn1-rs", + "instant", ] [[package]] -name = "once_cell" -version = "1.19.0" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] -name = "opaque-debug" -version = "0.3.0" +name = "fastrlp" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] [[package]] -name = "open-fastrlp" -version = "0.1.4" +name = "fastrlp" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" dependencies = [ "arrayvec", "auto_impl", "bytes", - "ethereum-types", - "open-fastrlp-derive", ] [[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +name = "faucet" +version = "0.1.0" dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", + "actix-cors", + "actix-web", + "async-trait", + "clap", + "contextful", + "contracts", + "dashmap 6.1.0", + "parking_lot 0.12.5", + "rpc", + "serde", + "serde_json", + "testutil", + "thiserror 1.0.69", + "tokio", + "tracing", + "unimock", + "web3", + "workspace-hack", ] [[package]] -name = "openssl" -version = "0.10.59" +name = "fdlimit" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" +checksum = "e182f7dbc2ef73d9ef67351c5fbbea084729c48362d3ce9dd44c28e32e277fe5" dependencies = [ - "bitflags 2.4.1", - "cfg-if 1.0.0", - "foreign-types", "libc", - "once_cell", - "openssl-macros", - "openssl-sys", + "thiserror 1.0.69", ] [[package]] -name = "openssl-macros" -version = "0.1.1" +name = "ff" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "bitvec", + "rand_core 0.6.4", + "subtle", ] [[package]] -name = "openssl-probe" -version = "0.1.5" +name = "fiat-crypto" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] -name = "openssl-sys" -version = "0.9.95" +name = "figment" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" +checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", + "atomic", + "parking_lot 0.12.5", + "pear", + "serde", + "tempfile", + "toml 0.8.23", + "uncased", + "version_check", ] [[package]] -name = "opentelemetry" -version = "0.21.0" +name = "file-lock" +version = "2.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" +checksum = "040b48f80a749da50292d0f47a1e2d5bf1d772f52836c07f64bfccc62ba6e664" dependencies = [ - "futures-core", - "futures-sink", - "indexmap 2.0.2", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", + "cc", + "libc", ] [[package]] -name = "opentelemetry-otlp" -version = "0.14.0" +name = "find-msvc-tools" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" + +[[package]] +name = "findshlibs" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f24cda83b20ed2433c68241f918d0f6fdec8b1d43b7a9590ab4420c5095ca930" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" dependencies = [ - "async-trait", - "futures-core", - "http", - "opentelemetry", - "opentelemetry-proto", - "opentelemetry-semantic-conventions", - "opentelemetry_sdk", - "prost", - "thiserror", - "tokio", - "tonic", + "cc", + "lazy_static", + "libc", + "winapi", ] [[package]] -name = "opentelemetry-proto" -version = "0.4.0" +name = "fixed-hash" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e155ce5cc812ea3d1dffbd1539aed653de4bf4882d60e6e04dcf0901d674e1" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ - "opentelemetry", - "opentelemetry_sdk", - "prost", - "tonic", + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fixed-map" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ed19add84e8cb9e8cc5f7074de0324247149ffef0b851e215fb0edc50c229b" +dependencies = [ + "fixed-map-derive", + "serde", +] + +[[package]] +name = "fixed-map-derive" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dc7a9cb3326bafb80642c5ce99b39a2c0702d4bfa8ee8a3e773791a6cbe2407" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fm" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "codespan-reporting", + "iter-extended", + "serde", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "from_variant" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5ff35a391aef949120a0340d690269b3d9f63460a6106e99bd07b961f345ea9" +dependencies = [ + "swc_macros_common", + "syn 2.0.112", +] + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "fslock" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04412b8935272e3a9bae6f48c7bfff74c2911f60525404edfdd28e49884c3bfb" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", + "num_cpus", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "futures-rustls" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" +dependencies = [ + "futures-io", + "rustls 0.20.9", + "webpki", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +dependencies = [ + "gloo-timers", + "send_wrapper 0.4.0", +] + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "git2" +version = "0.20.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b88256088d75a56f8ecfa070513a775dd9107f6530ef14919dac831af9cfe2b" +dependencies = [ + "bitflags 2.10.0", + "libc", + "libgit2-sys", + "log", + "url", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "globset" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax 0.8.8", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + +[[package]] +name = "gloo-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http 1.4.0", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "guild" +version = "2.0.0" +dependencies = [ + "actix-cors", + "actix-server", + "actix-web", + "alfred-http", + "alfred-provider", + "async-stripe", + "async-trait", + "barretenberg-cli", + "base64 0.22.1", + "bungee-client-http", + "bungee-interface", + "chrono", + "clap", + "contextful", + "contracts", + "country", + "currency", + "data", + "database", + "deadpool", + "diesel", + "diesel-async", + "dirs", + "document-ai-google", + "document-ai-interface", + "dotenvy", + "eip7702", + "element", + "eth-util", + "ethereum-types", + "eyre", + "futures", + "futures-util", + "guild-interface", + "hash", + "hash-poseidon", + "hex", + "hmac", + "httpmock", + "json-with-logging", + "jsonwebtoken 10.2.0", + "kyc", + "lazy_static", + "manteca-provider", + "network", + "node-client-http", + "notes", + "notes-interface", + "notes-rpc", + "notes-storage-pg", + "object_store", + "paste", + "posthog", + "posthog-interface", + "primitives", + "providers-interface", + "push-notification-expo", + "push-notification-interface", + "rain-http", + "rain-provider", + "ramps", + "ramps-interface", + "ramps-notification", + "ramps-providers-interface", + "ramps-rpc", + "ramps-storage-interface", + "ramps-storage-pg", + "rand 0.8.5", + "reqwest 0.12.28", + "rewards", + "rewards-interface", + "rewards-rpc", + "rewards-storage-pg", + "rpc", + "rustc-hex", + "secp256k1 0.28.2", + "serde", + "serde_json", + "serial_test", + "sha2", + "sha3", + "slack-client-http", + "slack-client-interface", + "strum 0.27.2", + "sumsub-http", + "sumsub-provider", + "support", + "support-interface", + "support-rpc", + "support-storage-interface", + "support-storage-pg", + "tempfile", + "testutil", + "thiserror 1.0.69", + "tokio", + "tokio-postgres", + "tracing", + "unimock", + "uuid 1.19.0", + "valuable", + "web3", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "guild-client-http" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "client-http", + "client-http-longpoll", + "contextful", + "element", + "guild-interface", + "http-interface", + "parking_lot 0.12.5", + "ramps-interface", + "reqwest 0.12.28", + "rpc", + "thiserror 1.0.69", + "tokio", + "uuid 1.19.0", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "guild-interface" +version = "0.1.0" +dependencies = [ + "chrono", + "contextful", + "contracts", + "currency", + "data", + "element", + "ethereum-types", + "kyc", + "notes-interface", + "primitives", + "ramps-interface", + "rpc", + "rpc-error-convert", + "serde", + "serde_json", + "thiserror 1.0.69", + "uuid 1.19.0", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.13.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.4.0", + "indexmap 2.13.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "halo2curves" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b1142bd1059aacde1b477e0c80c142910f1ceae67fc619311d6a17428007ab" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "lazy_static", + "num-bigint", + "num-traits", + "pasta_curves", + "paste", + "rand 0.8.5", + "rand_core 0.6.4", + "serde", + "serde_arrays", + "static_assertions", + "subtle", +] + +[[package]] +name = "hash" +version = "0.1.0" +dependencies = [ + "bn254_blackbox_solver", + "element", + "hex", + "insta", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift 0.3.0", + "serde", + "workspace-hack", +] + +[[package]] +name = "hash-poseidon" +version = "0.1.0" +dependencies = [ + "element", + "hex", + "insta", + "minimal-poseidon", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_xorshift 0.3.0", + "serde", + "workspace-hack", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "byteorder", + "num-traits", +] + +[[package]] +name = "headers" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +dependencies = [ + "base64 0.21.7", + "bytes", + "headers-core 0.2.0", + "http 0.2.12", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64 0.22.1", + "bytes", + "headers-core 0.3.0", + "http 1.4.0", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http 0.2.12", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http 1.4.0", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_fmt" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" + +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner 0.6.1", + "futures-channel", + "futures-io", + "futures-util", + "idna 1.1.0", + "ipnet", + "once_cell", + "rand 0.9.2", + "ring 0.17.14", + "serde", + "thiserror 2.0.17", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "moka", + "once_cell", + "parking_lot 0.12.5", + "rand 0.9.2", + "resolv-conf", + "serde", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "higher-kinded-types" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e690f8474c6c5d8ff99656fcbc195a215acc3949481a8b0b3351c838972dc776" +dependencies = [ + "macro_rules_attribute", + "never-say-never", + "paste", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-sha256-json" +version = "0.1.0" +dependencies = [ + "actix-web", + "base64 0.22.1", + "bytes", + "hex", + "hmac", + "serde", + "serde_json", + "sha2", + "thiserror 1.0.69", + "tracing", + "workspace-hack", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "hostname" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" +dependencies = [ + "cfg-if", + "libc", + "windows-link", +] + +[[package]] +name = "hstr" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c43c0a9e8fbdb3bb9dc8eee85e1e2ac81605418b4c83b6b7413cbf14d56ca5c" +dependencies = [ + "hashbrown 0.14.5", + "new_debug_unreachable", + "once_cell", + "rustc-hash 2.1.1", + "serde", + "triomphe", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.17", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa 1.0.17", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.4.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.4.0", + "http-body 1.0.1", + "pin-project-lite", +] + +[[package]] +name = "http-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "reqwest 0.12.28", + "rpc", + "serde", + "serde_json", + "thiserror 1.0.69", + "unimock", + "workspace-hack", +] + +[[package]] +name = "http-range-header" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + +[[package]] +name = "http-types" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +dependencies = [ + "anyhow", + "async-channel", + "base64 0.13.1", + "futures-lite 1.13.0", + "http 0.2.12", + "infer", + "pin-project-lite", + "rand 0.7.3", + "serde", + "serde_json", + "serde_qs 0.8.5", + "serde_urlencoded 0.7.1", + "url", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "httpmock" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511f510e9b1888d67f10bab4397f8b019d2a9b249a2c10acbce2d705b1b32e26" +dependencies = [ + "assert-json-diff 2.0.2", + "async-object-pool", + "async-trait", + "base64 0.22.1", + "bytes", + "crossbeam-utils", + "form_urlencoded", + "futures-timer", + "futures-util", + "headers 0.4.1", + "http 1.4.0", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "path-tree", + "regex", + "serde", + "serde_json", + "serde_regex", + "similar", + "stringmetrics", + "tabwriter", + "thiserror 2.0.17", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "humantime" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" + +[[package]] +name = "humantime-serde" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" +dependencies = [ + "humantime", + "serde", +] + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa 1.0.17", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2 0.4.12", + "http 1.4.0", + "http-body 1.0.1", + "httparse", + "httpdate", + "itoa 1.0.17", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.32", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http 1.4.0", + "hyper 1.8.1", + "hyper-util", + "log", + "rustls 0.23.35", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.4", + "tower-service", + "webpki-roots 1.0.4", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper 1.8.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.32", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.1", + "system-configuration 0.7.0", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "if-addrs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "if-addrs" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf39cc0423ee66021dc5eccface85580e4a001e0c5288bae8bea7ecb69225e90" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "if-watch" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf9d64cfcf380606e64f9a0bcf493616b65331199f984151a6fa11a7b3cde38" +dependencies = [ + "async-io", + "core-foundation 0.9.4", + "fnv", + "futures", + "if-addrs 0.10.2", + "ipnet", + "log", + "netlink-packet-core", + "netlink-packet-route", + "netlink-proto", + "netlink-sys", + "rtnetlink", + "system-configuration 0.6.1", + "tokio", + "windows 0.53.0", +] + +[[package]] +name = "ignore" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d782a365a015e0f5c04902246139249abf769125006fbe7649e2ee88169b4a" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro 0.6.0", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-more" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp 0.5.2", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + +[[package]] +name = "infer" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" + +[[package]] +name = "inlinable_string" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" + +[[package]] +name = "inotify" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +dependencies = [ + "bitflags 2.10.0", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "inplace-vec-builder" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf64c2edc8226891a71f127587a2861b132d2b942310843814d5001d99a1d307" +dependencies = [ + "smallvec", +] + +[[package]] +name = "insta" +version = "1.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "983e3b24350c84ab8a65151f537d67afbbf7153bb9f1110e03e9fa9b07f67a5c" +dependencies = [ + "console", + "once_cell", + "pest", + "pest_derive", + "serde", + "similar", + "tempfile", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "interprocess" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53bf2b0e0785c5394a7392f66d7c4fb9c653633c29b27a932280da3cb344c66a" +dependencies = [ + "doctest-file", + "futures-core", + "libc", + "recvmsg", + "tokio", + "widestring", + "windows-sys 0.52.0", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.10", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is-macro" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57a3e447e24c22647738e4607f1df1e0ec6f72e16182c4cd199f647cdfb0e4" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "iter-extended" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json-store" +version = "0.1.0" +dependencies = [ + "serde", + "serde_json", + "tempdir", + "thiserror 1.0.69", + "tokio", + "tracing", + "workspace-hack", +] + +[[package]] +name = "json-with-logging" +version = "0.1.0" +dependencies = [ + "actix-web", + "serde", + "serde_json", + "tracing", + "workspace-hack", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "jsonrpsee" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16" +dependencies = [ + "jsonrpsee-core 0.25.1", +] + +[[package]] +name = "jsonrpsee" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f3f48dc3e6b8bd21e15436c1ddd0bc22a6a54e8ec46fedd6adf3425f396ec6a" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core 0.26.0", + "jsonrpsee-http-client", + "jsonrpsee-proc-macros", + "jsonrpsee-server", + "jsonrpsee-types 0.26.0", + "jsonrpsee-wasm-client", + "jsonrpsee-ws-client", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf36eb27f8e13fa93dcb50ccb44c417e25b818cfa1a481b5470cd07b19c60b98" +dependencies = [ + "base64 0.22.1", + "futures-channel", + "futures-util", + "gloo-net", + "http 1.4.0", + "jsonrpsee-core 0.26.0", + "pin-project", + "rustls 0.23.35", + "rustls-pki-types", + "rustls-platform-verifier", + "soketto 0.8.1", + "thiserror 2.0.17", + "tokio", + "tokio-rustls 0.26.4", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693c93cbb7db25f4108ed121304b671a36002c2db67dff2ee4391a688c738547" +dependencies = [ + "async-trait", + "futures-util", + "http 1.4.0", + "jsonrpsee-types 0.25.1", + "pin-project", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "316c96719901f05d1137f19ba598b5fe9c9bc39f4335f67f6be8613921946480" +dependencies = [ + "async-trait", + "bytes", + "futures-timer", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "jsonrpsee-types 0.26.0", + "parking_lot 0.12.5", + "pin-project", + "rand 0.9.2", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tower", + "tracing", + "wasm-bindgen-futures", +] + +[[package]] +name = "jsonrpsee-http-client" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790bedefcec85321e007ff3af84b4e417540d5c87b3c9779b9e247d1bcc3dab8" +dependencies = [ + "base64 0.22.1", + "http-body 1.0.1", + "hyper 1.8.1", + "hyper-rustls 0.27.7", + "hyper-util", + "jsonrpsee-core 0.26.0", + "jsonrpsee-types 0.26.0", + "rustls 0.23.35", + "rustls-platform-verifier", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tower", + "url", +] + +[[package]] +name = "jsonrpsee-proc-macros" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da3f8ab5ce1bb124b6d082e62dffe997578ceaf0aeb9f3174a214589dc00f07" +dependencies = [ + "heck 0.5.0", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c51b7c290bb68ce3af2d029648148403863b982f138484a73f02a9dd52dbd7f" +dependencies = [ + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-util", + "jsonrpsee-core 0.26.0", + "jsonrpsee-types 0.26.0", + "pin-project", + "route-recognizer", + "serde", + "serde_json", + "soketto 0.8.1", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca" +dependencies = [ + "http 1.4.0", + "serde", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc88ff4688e43cc3fa9883a8a95c6fa27aa2e76c96e610b737b6554d650d7fd5" +dependencies = [ + "http 1.4.0", + "serde", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "jsonrpsee-wasm-client" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7902885de4779f711a95d82c8da2d7e5f9f3a7c7cfa44d51c067fd1c29d72a3c" +dependencies = [ + "jsonrpsee-client-transport", + "jsonrpsee-core 0.26.0", + "jsonrpsee-types 0.26.0", + "tower", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6fceceeb05301cc4c065ab3bd2fa990d41ff4eb44e4ca1b30fa99c057c3e79" +dependencies = [ + "http 1.4.0", + "jsonrpsee-client-transport", + "jsonrpsee-core 0.26.0", + "jsonrpsee-types 0.26.0", + "tower", + "url", +] + +[[package]] +name = "jsonwebtoken" +version = "9.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" +dependencies = [ + "base64 0.22.1", + "js-sys", + "pem 3.0.6", + "ring 0.17.14", + "serde", + "serde_json", + "simple_asn1", +] + +[[package]] +name = "jsonwebtoken" +version = "10.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c76e1c7d7df3e34443b3621b459b066a7b79644f059fc8b2db7070c825fd417e" +dependencies = [ + "base64 0.22.1", + "ed25519-dalek", + "getrandom 0.2.16", + "hmac", + "js-sys", + "p256", + "p384", + "pem 3.0.6", + "rand 0.8.5", + "rsa", + "serde", + "serde_json", + "sha2", + "signature", + "simple_asn1", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2", + "signature", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak-asm" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b646a74e746cd25045aa0fd42f4f7f78aa6d119380182c7e63a5593c4ab8df6f" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "kqueue" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "kyc" +version = "0.1.0" +dependencies = [ + "base64 0.22.1", + "chrono", + "currency", + "diesel", + "phonenumber", + "serde", + "serde_json", + "strum 0.27.2", + "thiserror 1.0.69", + "tokio", + "ts-rs", + "workspace-hack", +] + +[[package]] +name = "lalrpop" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" +dependencies = [ + "ascii-canvas", + "bit-set 0.5.3", + "ena", + "itertools 0.11.0", + "lalrpop-util", + "petgraph 0.6.5", + "regex", + "regex-syntax 0.8.8", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", + "walkdir", +] + +[[package]] +name = "lalrpop-util" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin 0.9.8", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libaes" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82903360c009b816f5ab72a9b68158c27c301ee2c3f20655b55c5e589e7d3bb7" + +[[package]] +name = "libc" +version = "0.2.178" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" + +[[package]] +name = "libgit2-sys" +version = "0.18.3+1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9b3acc4b91781bb0b3386669d325163746af5f6e4f73e6d2d630e09a35f3487" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libp2p" +version = "0.51.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f35eae38201a993ece6bdc823292d6abd1bffed1c4d0f4a3517d2bd8e1d917fe" +dependencies = [ + "bytes", + "futures", + "futures-timer", + "getrandom 0.2.16", + "instant", + "libp2p-allow-block-list", + "libp2p-connection-limits", + "libp2p-core", + "libp2p-dns", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-identity 0.1.3", + "libp2p-mdns", + "libp2p-metrics", + "libp2p-noise", + "libp2p-ping", + "libp2p-quic", + "libp2p-request-response", + "libp2p-swarm", + "libp2p-tcp", + "libp2p-yamux", + "multiaddr 0.17.1", + "pin-project", +] + +[[package]] +name = "libp2p-allow-block-list" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510daa05efbc25184458db837f6f9a5143888f1caa742426d92e1833ddd38a50" +dependencies = [ + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-swarm", + "void", +] + +[[package]] +name = "libp2p-connection-limits" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4caa33f1d26ed664c4fe2cca81a08c8e07d4c1c04f2f4ac7655c2dd85467fda0" +dependencies = [ + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-swarm", + "void", +] + +[[package]] +name = "libp2p-core" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-identity 0.1.3", + "log", + "multiaddr 0.17.1", + "multihash 0.17.0", + "multistream-select", + "once_cell", + "parking_lot 0.12.5", + "pin-project", + "quick-protobuf", + "rand 0.8.5", + "rw-stream-sink", + "smallvec", + "thiserror 1.0.69", + "unsigned-varint 0.7.2", + "void", +] + +[[package]] +name = "libp2p-dns" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146ff7034daae62077c415c2376b8057368042df6ab95f5432ad5e88568b1554" +dependencies = [ + "futures", + "libp2p-core", + "log", + "parking_lot 0.12.5", + "smallvec", + "trust-dns-resolver", +] + +[[package]] +name = "libp2p-gossipsub" +version = "0.44.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70b34b6da8165c0bde35c82db8efda39b824776537e73973549e76cadb3a77c5" +dependencies = [ + "asynchronous-codec", + "base64 0.21.7", + "byteorder", + "bytes", + "either", + "fnv", + "futures", + "hex_fmt", + "instant", + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-swarm", + "log", + "prometheus-client", + "quick-protobuf", + "quick-protobuf-codec", + "rand 0.8.5", + "regex", + "sha2", + "smallvec", + "thiserror 1.0.69", + "unsigned-varint 0.7.2", + "void", + "wasm-timer", +] + +[[package]] +name = "libp2p-identify" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5455f472243e63b9c497ff320ded0314254a9eb751799a39c283c6f20b793f3c" +dependencies = [ + "asynchronous-codec", + "either", + "futures", + "futures-timer", + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-swarm", + "log", + "lru 0.10.1", + "quick-protobuf", + "quick-protobuf-codec", + "smallvec", + "thiserror 1.0.69", + "void", +] + +[[package]] +name = "libp2p-identity" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" +dependencies = [ + "bs58 0.4.0", + "ed25519-dalek", + "log", + "multiaddr 0.17.1", + "multihash 0.17.0", + "quick-protobuf", + "rand 0.8.5", + "sha2", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "libp2p-identity" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c7892c221730ba55f7196e98b0b8ba5e04b4155651736036628e9f73ed6fc3" +dependencies = [ + "asn1_der", + "bs58 0.5.1", + "ed25519-dalek", + "hkdf", + "k256", + "multihash 0.19.3", + "quick-protobuf", + "sha2", + "thiserror 2.0.17", + "tracing", + "zeroize", +] + +[[package]] +name = "libp2p-mdns" +version = "0.43.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19983e1f949f979a928f2c603de1cf180cc0dc23e4ac93a62651ccb18341460b" +dependencies = [ + "data-encoding", + "futures", + "if-watch", + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-swarm", + "log", + "rand 0.8.5", + "smallvec", + "socket2 0.4.10", + "tokio", + "trust-dns-proto", + "void", +] + +[[package]] +name = "libp2p-metrics" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42ec91e227d7d0dafa4ce88b333cdf5f277253873ab087555c92798db2ddd46" +dependencies = [ + "libp2p-core", + "libp2p-gossipsub", + "libp2p-identify", + "libp2p-ping", + "libp2p-swarm", + "prometheus-client", +] + +[[package]] +name = "libp2p-noise" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3673da89d29936bc6435bafc638e2f184180d554ce844db65915113f86ec5e" +dependencies = [ + "bytes", + "curve25519-dalek 3.2.0", + "futures", + "libp2p-core", + "libp2p-identity 0.1.3", + "log", + "once_cell", + "quick-protobuf", + "rand 0.8.5", + "sha2", + "snow", + "static_assertions", + "thiserror 1.0.69", + "x25519-dalek 1.1.1", + "zeroize", +] + +[[package]] +name = "libp2p-ping" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e57759c19c28a73ef1eb3585ca410cefb72c1a709fcf6de1612a378e4219202" +dependencies = [ + "either", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-swarm", + "log", + "rand 0.8.5", + "void", +] + +[[package]] +name = "libp2p-quic" +version = "0.7.0-alpha.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6b26abd81cd2398382a1edfe739b539775be8a90fa6914f39b2ab49571ec735" +dependencies = [ + "bytes", + "futures", + "futures-timer", + "if-watch", + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-tls", + "log", + "parking_lot 0.12.5", + "quinn-proto 0.9.6", + "rand 0.8.5", + "rustls 0.20.9", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "libp2p-request-response" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffdb374267d42dc5ed5bc53f6e601d4a64ac5964779c6e40bb9e4f14c1e30d5" +dependencies = [ + "async-trait", + "futures", + "instant", + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-swarm", + "rand 0.8.5", + "smallvec", +] + +[[package]] +name = "libp2p-swarm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "903b3d592d7694e56204d211f29d31bc004be99386644ba8731fc3e3ef27b296" +dependencies = [ + "either", + "fnv", + "futures", + "futures-timer", + "instant", + "libp2p-core", + "libp2p-identity 0.1.3", + "libp2p-swarm-derive", + "log", + "rand 0.8.5", + "smallvec", + "tokio", + "void", +] + +[[package]] +name = "libp2p-swarm-derive" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fba456131824ab6acd4c7bf61e9c0f0a3014b5fc9868ccb8e10d344594cdc4f" +dependencies = [ + "heck 0.4.1", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "libp2p-tcp" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d33698596d7722d85d3ab0c86c2c322254fce1241e91208e3679b4eb3026cf" +dependencies = [ + "futures", + "futures-timer", + "if-watch", + "libc", + "libp2p-core", + "log", + "socket2 0.4.10", + "tokio", +] + +[[package]] +name = "libp2p-tls" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" +dependencies = [ + "futures", + "futures-rustls", + "libp2p-core", + "libp2p-identity 0.1.3", + "rcgen", + "ring 0.16.20", + "rustls 0.20.9", + "thiserror 1.0.69", + "webpki", + "x509-parser", + "yasna", +] + +[[package]] +name = "libp2p-yamux" +version = "0.43.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd21d950662700a385d4c6d68e2f5f54d778e97068cdd718522222ef513bda" +dependencies = [ + "futures", + "libp2p-core", + "log", + "thiserror 1.0.69", + "yamux", +] + +[[package]] +name = "libproc" +version = "0.14.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a54ad7278b8bc5301d5ffd2a94251c004feb971feba96c971ea4063645990757" +dependencies = [ + "bindgen 0.72.1", + "errno", + "libc", +] + +[[package]] +name = "libredox" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +dependencies = [ + "bitflags 2.10.0", + "libc", +] + +[[package]] +name = "librocksdb-sys" +version = "0.11.0+8.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3386f101bcb4bd252d8e9d2fb41ec3b0862a15a62b478c355b2982efa469e3e" +dependencies = [ + "bindgen 0.65.1", + "bzip2-sys", + "cc", + "glob", + "libc", + "libz-sys", + "lz4-sys", + "zstd-sys", +] + +[[package]] +name = "libz-sys" +version = "1.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15d118bbf3771060e7311cc7bb0545b01d08a8b4a7de949198dec1fa0ca1c0f7" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linked_hash_set" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "984fb35d06508d1e69fc91050cceba9c0b748f983e6739fa2c7a9237154c52c8" +dependencies = [ + "linked-hash-map", + "serde_core", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", + "serde", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "lru" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" +dependencies = [ + "hashbrown 0.13.2", +] + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "lru" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f8cc7106155f10bdf99a6f379688f543ad6596a415375b36a59a054ceda1198" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "lru" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "lz4-sys" +version = "1.11.1+lz4-1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "lz4_flex" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" + +[[package]] +name = "mach2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" +dependencies = [ + "libc", +] + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "macro_rules_attribute" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520" +dependencies = [ + "macro_rules_attribute-proc_macro", + "paste", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" + +[[package]] +name = "manteca-http" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "currency", + "manteca-interface", + "mockito", + "ramps-interface", + "reqwest 0.12.28", + "serde", + "serde_json", + "serial_test", + "tokio", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "manteca-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "currency", + "reqwest 0.12.28", + "serde", + "serde_json", + "strum 0.27.2", + "strum_macros 0.27.2", + "thiserror 1.0.69", + "unimock", + "workspace-hack", +] + +[[package]] +name = "manteca-provider" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "currency", + "element", + "eth-util", + "kyc", + "manteca-http", + "manteca-interface", + "network", + "providers-interface", + "ramps-interface", + "serde", + "serde_json", + "strum 0.27.2", + "strum_macros 0.27.2", + "thiserror 1.0.69", + "tokio", + "unimock", + "workspace-hack", +] + +[[package]] +name = "match-lookup" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "memory-stats" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c73f5c649995a115e1a0220b35e4df0a1294500477f97a91d0660fb5abeb574a" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "merge-cli" +version = "0.1.0" +dependencies = [ + "barretenberg-cli", + "chrono", + "clap", + "contextful", + "database", + "deadpool", + "diesel", + "diesel-async", + "element", + "eth-util", + "ethereum-types", + "futures", + "hex", + "itertools 0.14.0", + "node-client-http", + "node-interface", + "notes-interface", + "ramps-interface", + "serde", + "thiserror 1.0.69", + "tokio", + "url", + "uuid 1.19.0", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "metrics" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5312e9ba3771cfa961b585728215e3d972c950a3eed9252aa093d6301277e8" +dependencies = [ + "ahash", + "portable-atomic", +] + +[[package]] +name = "metrics-derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "161ab904c2c62e7bda0f7562bf22f96440ca35ff79e66c800cbac298f2f4f5ec" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "metrics-exporter-prometheus" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3589659543c04c7dc5526ec858591015b87cd8746583b51b48ef4353f99dbcda" +dependencies = [ + "base64 0.22.1", + "indexmap 2.13.0", + "metrics", + "metrics-util", + "quanta", + "thiserror 2.0.17", +] + +[[package]] +name = "metrics-process" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f615e08e049bd14a44c4425415782efb9bcd479fc1e19ddeb971509074c060d0" +dependencies = [ + "libc", + "libproc", + "mach2", + "metrics", + "once_cell", + "procfs 0.18.0", + "rlimit", + "windows 0.62.2", +] + +[[package]] +name = "metrics-util" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdfb1365fea27e6dd9dc1dbc19f570198bc86914533ad639dae939635f096be4" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.16.1", + "metrics", + "quanta", + "rand 0.9.2", + "rand_xoshiro 0.7.0", + "sketches-ddsketch", +] + +[[package]] +name = "microtype" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91051219f867e549222950d8509b98c4168ee2eada13aa81331c34cbc0b7916d" +dependencies = [ + "microtype-macro", + "secrecy", +] + +[[package]] +name = "microtype-macro" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f65cf1066f1a4836a0a93493938af5a93c686e430c34b57fcbb1f6854f93f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "mini-moka" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803" +dependencies = [ + "crossbeam-channel", + "crossbeam-utils", + "dashmap 5.5.3", + "skeptic", + "smallvec", + "tagptr", + "triomphe", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "minimal-poseidon" +version = "0.1.0" +dependencies = [ + "ff", + "halo2curves", + "lazy_static", + "workspace-hack", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "log", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", +] + +[[package]] +name = "mockito" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3ae325bcceb48a24302ac57e1055f9173f5fd53be535603ea0ed41dea92db5" +dependencies = [ + "assert-json-diff 1.1.0", + "colored", + "difference", + "httparse", + "lazy_static", + "log", + "rand 0.7.3", + "regex", + "serde_json", + "serde_urlencoded 0.6.1", +] + +[[package]] +name = "modular-bitfield" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74" +dependencies = [ + "modular-bitfield-impl", + "static_assertions", +] + +[[package]] +name = "modular-bitfield-impl" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "moka" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot 0.12.5", + "portable-atomic", + "smallvec", + "tagptr", + "uuid 1.19.0", +] + +[[package]] +name = "more-asserts" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fafa6961cabd9c63bcd77a45d7e3b7f3b552b70417831fb0f56db717e72407e" + +[[package]] +name = "multiaddr" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b36f567c7099511fa8612bbbb52dda2419ce0bdbacf31714e3a5ffdb766d3bd" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "log", + "multibase", + "multihash 0.17.0", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint 0.7.2", + "url", +] + +[[package]] +name = "multiaddr" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6351f60b488e04c1d21bc69e56b89cb3f5e8f5d22557d6e8031bdfd79b6961" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "libp2p-identity 0.2.13", + "multibase", + "multihash 0.19.3", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint 0.8.0", + "url", +] + +[[package]] +name = "multibase" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77" +dependencies = [ + "base-x", + "base256emoji", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835d6ff01d610179fbce3de1694d007e500bf33a7f29689838941d6bf783ae40" +dependencies = [ + "core2", + "multihash-derive", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "multihash" +version = "0.19.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d" +dependencies = [ + "core2", + "unsigned-varint 0.8.0", +] + +[[package]] +name = "multihash-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" +dependencies = [ + "proc-macro-crate 1.1.3", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "multistream-select" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" +dependencies = [ + "bytes", + "futures", + "log", + "pin-project", + "smallvec", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "nargo" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "brillig", + "fm", + "iter-extended", + "jsonrpsee 0.25.1", + "noir_greybox_fuzzer", + "noirc_abi", + "noirc_driver", + "noirc_errors", + "noirc_frontend", + "noirc_printable_type", + "rayon", + "serde", + "serde_json", + "tempfile", + "thiserror 1.0.69", + "tracing", + "walkdir", +] + +[[package]] +name = "native-tls" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cdede44f9a69cab2899a2049e2c3bd49bf911a157f6a3353d4a91c61abbce44" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe 0.1.6", + "openssl-sys", + "schannel", + "security-framework 2.11.1", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror 1.0.69", +] + +[[package]] +name = "netlink-proto" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72452e012c2f8d612410d89eea01e2d9b56205274abb35d53f60200b2ec41d60" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core", + "netlink-sys", + "thiserror 2.0.17", +] + +[[package]] +name = "netlink-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" +dependencies = [ + "bytes", + "futures", + "libc", + "log", + "tokio", +] + +[[package]] +name = "network" +version = "0.1.0" +dependencies = [ + "diesel", + "serde", + "serde_json", + "strum 0.27.2", + "strum_macros 0.27.2", + "thiserror 1.0.69", + "ts-rs", + "uuid 1.19.0", + "veil", + "workspace-hack", +] + +[[package]] +name = "never-say-never" +version = "6.6.666" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf5a574dadd7941adeaa71823ecba5e28331b8313fb2e1c6a5c7e5981ea53ad6" + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "libc", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "node" +version = "1.3.0" +dependencies = [ + "actix-cors", + "actix-server", + "actix-web", + "aggregator", + "aggregator-interface", + "async-trait", + "barretenberg-cli", + "barretenberg-interface", + "block-store", + "borsh", + "burn-substitutor", + "chrono", + "clap", + "constants", + "contextful", + "contracts", + "derivative", + "dirs", + "doomslug", + "dotenvy", + "either", + "element", + "ethereum-types", + "expect-test", + "figment", + "futures", + "hash", + "hex", + "itertools 0.14.0", + "json-with-logging", + "libp2p", + "microtype", + "native-tls", + "node-client-http", + "node-interface", + "once_cell", + "p2p2", + "parking_lot 0.12.5", + "postgres-native-tls", + "primitives", + "prover", + "rand 0.8.5", + "rand_derive2", + "reqwest 0.12.28", + "rocksdb", + "rpc", + "rustc-hex", + "scopeguard", + "secp256k1 0.28.2", + "serde", + "serde_json", + "serial_test", + "sha3", + "smirk", + "strum 0.27.2", + "tempdir", + "tempfile", + "testutil", + "thiserror 1.0.69", + "tokio", + "tokio-postgres", + "tokio-stream", + "tracing", + "tracing-subscriber 0.3.22", + "web3", + "wire-message", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "node-client-http" +version = "0.1.0" +dependencies = [ + "async-trait", + "client-http", + "element", + "http-interface", + "node-interface", + "primitives", + "reqwest 0.12.28", + "serde", + "tokio", + "unimock", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "node-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "element", + "primitives", + "rpc", + "rpc-error-convert", + "serde", + "serde_json", + "thiserror 1.0.69", + "ts-rs", + "unimock", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "noir-abi-inputs-macro" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.112", + "workspace-hack", +] + +[[package]] +name = "noir_greybox_fuzzer" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "build-data", + "fm", + "noirc_abi", + "noirc_artifacts", + "num-traits", + "proptest", + "rand 0.8.5", + "rand_xorshift 0.3.0", + "rayon", + "sha256", + "termcolor", + "walkdir", +] + +[[package]] +name = "noir_protobuf" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "color-eyre", + "prost 0.13.5", +] + +[[package]] +name = "noirc_abi" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "iter-extended", + "noirc_printable_type", + "num-bigint", + "num-traits", + "serde", + "serde_json", + "thiserror 1.0.69", + "toml 0.7.8", +] + +[[package]] +name = "noirc_arena" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" + +[[package]] +name = "noirc_artifacts" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "codespan-reporting", + "fm", + "noirc_abi", + "noirc_driver", + "noirc_errors", + "noirc_printable_type", + "serde", +] + +[[package]] +name = "noirc_driver" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "build-data", + "clap", + "fm", + "iter-extended", + "noirc_abi", + "noirc_errors", + "noirc_evaluator", + "noirc_frontend", + "rust-embed", + "rustc-hash 2.1.1", + "serde", + "tracing", +] + +[[package]] +name = "noirc_errors" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "base64 0.22.1", + "codespan-reporting", + "flate2", + "fm", + "noirc_printable_type", + "noirc_span", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "tracing", +] + +[[package]] +name = "noirc_evaluator" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "bn254_blackbox_solver", + "cfg-if", + "chrono", + "fm", + "im", + "indexmap 2.13.0", + "iter-extended", + "noirc_errors", + "noirc_frontend", + "noirc_printable_type", + "num-bigint", + "num-integer", + "num-traits", + "petgraph 0.8.3", + "rayon", + "rustc-hash 2.1.1", + "rustc-stable-hash", + "serde", + "serde_json", + "serde_with", + "smallvec", + "thiserror 1.0.69", + "tracing", + "vec-collections", +] + +[[package]] +name = "noirc_frontend" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "bn254_blackbox_solver", + "cfg-if", + "fm", + "im", + "iter-extended", + "noirc_arena", + "noirc_errors", + "noirc_printable_type", + "num-bigint", + "num-traits", + "petgraph 0.8.3", + "rangemap", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "small-ord-set", + "smol_str 0.3.4", + "strum 0.24.1", + "strum_macros 0.24.3", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "noirc_printable_type" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "acvm", + "iter-extended", + "serde", + "serde_json", +] + +[[package]] +name = "noirc_span" +version = "1.0.0-beta.14" +source = "git+https://github.com/noir-lang/noir?tag=v1.0.0-beta.14#60ccd48e18ad8ce50d5ecda9baf813b712145051" +dependencies = [ + "codespan", + "serde", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "normpath" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf23ab2b905654b4cb177e30b629937b3868311d4e1cba859f899c041046e69b" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "notes" +version = "0.1.0" +dependencies = [ + "async-trait", + "barretenberg-interface", + "chrono", + "contextful", + "element", + "hash", + "node-interface", + "notes-interface", + "notes-storage-interface", + "ramps-interface", + "ramps-storage-interface", + "thiserror 1.0.69", + "tokio", + "tracing", + "unimock", + "uuid 1.19.0", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "notes-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "database", + "diesel", + "element", + "hash", + "rand 0.8.5", + "rpc", + "serde", + "serde_json", + "strum 0.27.2", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "notes-rpc" +version = "0.1.0" +dependencies = [ + "actix-web", + "async-trait", + "chrono", + "contextful", + "element", + "json-with-logging", + "notes-interface", + "rpc", + "serde", + "serde_json", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "notes-storage-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "element", + "notes-interface", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "notes-storage-pg" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "database", + "diesel", + "diesel-async", + "element", + "notes-interface", + "notes-storage-interface", + "thiserror 1.0.69", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "notify" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" +dependencies = [ + "bitflags 2.10.0", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio", + "notify-types", + "walkdir", + "windows-sys 0.60.2", +] + +[[package]] +name = "notify-types" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "nybbles" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d49ff0c0d00d4a502b39df9af3a525e1efeb14b9dabb5bb83335284c1309210" +dependencies = [ + "alloy-rlp", + "cfg-if", + "proptest", + "ruint", + "serde", + "smallvec", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +dependencies = [ + "bitflags 2.10.0", + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac0f75792558aa9d618443bbb5db7426a7a0b6fddf96903f86ef9ad02e135740" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "bitflags 2.10.0", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" +dependencies = [ + "bitflags 2.10.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" +dependencies = [ + "bitflags 2.10.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3f5ec77a81d9e0c5a0b32159b0cb143d7086165e79708351e02bf37dfc65cd" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "object_store" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6da452820c715ce78221e8202ccc599b4a52f3e1eb3eedb487b680c81a8e3f3" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "chrono", + "futures", + "humantime", + "hyper 1.8.1", + "itertools 0.13.0", + "parking_lot 0.12.5", + "percent-encoding", + "quick-xml 0.36.2", + "rand 0.8.5", + "reqwest 0.12.28", + "ring 0.17.14", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "snafu", + "tokio", + "tracing", + "url", + "walkdir", +] + +[[package]] +name = "observer" +version = "1.3.0" +dependencies = [ + "clap", + "contextful", + "contracts", + "eyre", + "opentelemetry", + "primitives", + "reqwest 0.12.28", + "rpc", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "oncemutex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2" + +[[package]] +name = "op-alloy" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9b8fee21003dd4f076563de9b9d26f8c97840157ef78593cd7f262c5ca99848" +dependencies = [ + "op-alloy-consensus", + "op-alloy-network", + "op-alloy-provider", + "op-alloy-rpc-types", + "op-alloy-rpc-types-engine", +] + +[[package]] +name = "op-alloy-consensus" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736381a95471d23e267263cfcee9e1d96d30b9754a94a2819148f83379de8a86" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth", + "alloy-serde", + "derive_more 2.1.1", + "serde", + "serde_with", + "thiserror 2.0.17", +] + +[[package]] +name = "op-alloy-network" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4034183dca6bff6632e7c24c92e75ff5f0eabb58144edb4d8241814851334d47" +dependencies = [ + "alloy-consensus", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-eth", + "alloy-signer", + "op-alloy-consensus", + "op-alloy-rpc-types", +] + +[[package]] +name = "op-alloy-provider" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6753d90efbaa8ea8bcb89c1737408ca85fa60d7adb875049d3f382c063666f86" +dependencies = [ + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-engine", + "alloy-transport", + "async-trait", + "op-alloy-rpc-types-engine", +] + +[[package]] +name = "op-alloy-rpc-types" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd87c6b9e5b6eee8d6b76f41b04368dca0e9f38d83338e5b00e730c282098a4" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network-primitives", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-serde", + "derive_more 2.1.1", + "op-alloy-consensus", + "serde", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "op-alloy-rpc-types-engine" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77727699310a18cdeed32da3928c709e2704043b6584ed416397d5da65694efc" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-engine", + "alloy-serde", + "derive_more 2.1.1", + "ethereum_ssz", + "ethereum_ssz_derive", + "op-alloy-consensus", + "serde", + "sha2", + "snap", + "thiserror 2.0.17", +] + +[[package]] +name = "op-revm" +version = "15.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79c92b75162c2ed1661849fa51683b11254a5b661798360a2c24be918edafd40" +dependencies = [ + "auto_impl", + "revm", + "serde", +] + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-probe" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" + +[[package]] +name = "openssl-src" +version = "300.5.5+3.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f1787d533e03597a7934fd0a765f0d28e94ecc5fb7789f8053b1e699a56f709" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "opentelemetry" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "opentelemetry-http" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +dependencies = [ + "async-trait", + "bytes", + "http 1.4.0", + "opentelemetry", + "reqwest 0.12.28", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf" +dependencies = [ + "http 1.4.0", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost 0.14.1", + "reqwest 0.12.28", + "thiserror 2.0.17", + "tokio", + "tonic", + "tracing", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost 0.14.1", + "tonic", + "tonic-prost", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e62e29dfe041afb8ed2a6c9737ab57db4907285d999ef8ad3a59092a36bdc846" + +[[package]] +name = "opentelemetry_sdk" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "rand 0.9.2", + "thiserror 2.0.17", + "tokio", + "tokio-stream", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "os_info" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" +dependencies = [ + "android_system_properties", + "log", + "nix 0.30.1", + "objc2", + "objc2-foundation", + "objc2-ui-kit", + "serde", + "windows-sys 0.61.2", +] + +[[package]] +name = "os_pipe" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "owo-colors" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p2p" +version = "1.3.0" +dependencies = [ + "async-trait", + "borsh", + "clap", + "color-eyre", + "dashmap 6.1.0", + "figment", + "file-lock", + "futures", + "libp2p", + "serde", + "serde_json", + "sha3", + "strum 0.27.2", + "tempdir", + "thiserror 1.0.69", + "tokio", + "toml 0.9.11+spec-1.1.0", + "tracing", + "tracing-subscriber 0.3.22", + "wire-message", + "workspace-hack", +] + +[[package]] +name = "p2p2" +version = "1.3.0" +dependencies = [ + "async-trait", + "borsh", + "figment", + "futures", + "futures-util", + "libp2p", + "parking_lot 0.12.5", + "serde", + "strum 0.27.2", + "thiserror 1.0.69", + "tokio", + "toml 0.9.11+spec-1.1.0", + "tracing", + "whitelist-ips", + "wire-message", + "workspace-hack", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "bytes", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.12", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.18", + "smallvec", + "windows-link", +] + +[[package]] +name = "parse-link" +version = "0.1.0" +dependencies = [ + "bs58 0.5.1", + "element", + "ethnum", + "hash", + "hex", + "serde", + "serde_json", + "sha3", + "thiserror 1.0.69", + "ts-rs", + "web3", + "workspace-hack", +] + +[[package]] +name = "parse-size" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b" + +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "pasta_curves" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +dependencies = [ + "blake2b_simd", + "ff", + "group", + "lazy_static", + "rand 0.8.5", + "static_assertions", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + +[[package]] +name = "path-tree" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a97453bc21a968f722df730bfe11bd08745cb50d1300b0df2bda131dece136" +dependencies = [ + "smallvec", +] + +[[package]] +name = "payy-evm" +version = "0.1.0" +dependencies = [ + "alloy", + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-genesis", + "alloy-primitives", + "alloy-rpc-types-engine", + "barretenberg-cli", + "barretenberg-interface", + "bn254_blackbox_solver", + "chrono", + "clap", + "constants", + "contextful", + "element", + "ethers-solc", + "hash", + "indexmap 2.13.0", + "reqwest 0.12.28", + "reth-chainspec", + "reth-db", + "reth-db-common", + "reth-ethereum", + "reth-ethereum-primitives", + "reth-evm", + "reth-node-builder", + "reth-primitives", + "reth-primitives-traits", + "reth-provider", + "reth-tasks", + "reth-transaction-pool", + "rpc", + "serde", + "serde_json", + "serde_yaml", + "serial_test", + "smirk", + "solc-tooling", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tracing", + "tracing-subscriber 0.3.22", + "unimock", + "workspace-hack", + "zk-circuits", +] + +[[package]] +name = "payy-note" +version = "0.1.0" +dependencies = [ + "element", + "serde", + "serde_json", + "unimock", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "payy_core" +version = "0.1.0" +dependencies = [ + "chrono", + "element", + "parking_lot 0.12.5", + "payy_core_types", + "serde_json", + "tokio", + "wallet-core", + "wallet-mobile", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "payy_core_types" +version = "0.1.0" +dependencies = [ + "data", + "kyc", + "network", + "serde", + "serde_json", + "thiserror 1.0.69", + "ts-rs", + "wallet-core", + "workspace-hack", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", + "hmac", + "password-hash", + "sha2", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "hmac", +] + +[[package]] +name = "pear" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" +dependencies = [ + "inlinable_string", + "pear_codegen", + "yansi 1.0.1", +] + +[[package]] +name = "pear_codegen" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64 0.22.1", + "serde_core", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "pest_meta" +version = "2.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" +dependencies = [ + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset 0.4.2", + "indexmap 2.13.0", +] + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset 0.5.7", + "indexmap 2.13.0", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "serde", +] + +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.1", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros 0.13.1", + "phf_shared 0.13.1", + "serde", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand 2.3.0", + "phf_shared 0.13.1", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.1", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher 1.0.1", +] + +[[package]] +name = "phonenumber" +version = "0.3.7+8.13.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2247167dc3741816fdd4d3690e97f56a892a264b44f4c702078b72d1f8b6bd40" +dependencies = [ + "bincode 1.3.3", + "either", + "fnv", + "nom", + "once_cell", + "quick-xml 0.37.5", + "regex", + "regex-cache", + "serde", + "serde_derive", + "strum 0.26.3", + "thiserror 1.0.69", +] + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 1.1.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "polonius-the-crab" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec242d7eccbb2fd8b3b5b6e3cf89f94a91a800f469005b44d154359609f8af72" +dependencies = [ + "higher-kinded-types", + "never-say-never", +] + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polybase_bb_rs" +version = "3.0.0-manual.20251030" +source = "git+https://github.com/polybase/aztec-packages?rev=7ad5d5c892f1396ca572da4b2e29a761d1f11f1f#7ad5d5c892f1396ca572da4b2e29a761d1f11f1f" +dependencies = [ + "bindgen 0.71.1", + "cmake", + "num-bigint", + "thiserror 1.0.69", + "tracing", + "tracing-subscriber 0.3.22", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "postgres-native-tls" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac73153d92e4bde922bd6f1dfba7f1ab8132266c031153b55e20a1521cd36d49" +dependencies = [ + "native-tls", + "tokio", + "tokio-native-tls", + "tokio-postgres", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbef655056b916eb868048276cfd5d6a7dea4f81560dfd047f97c8c6fe3fcfd4" +dependencies = [ + "base64 0.22.1", + "byteorder", + "bytes", + "fallible-iterator", + "hmac", + "md-5", + "memchr", + "rand 0.9.2", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef4605b7c057056dd35baeb6ac0c0338e4975b1f2bef0f65da953285eb007095" +dependencies = [ + "bytes", + "fallible-iterator", + "postgres-protocol", + "uuid 1.19.0", +] + +[[package]] +name = "posthog" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "posthog-interface", + "reqwest 0.12.28", + "serde", + "serde_json", + "thiserror 1.0.69", + "tokio", + "tracing", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "posthog-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "serde", + "serde_json", + "strum 0.27.2", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "pq-sys" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "574ddd6a267294433f140b02a726b0640c43cf7c6f717084684aaa3b285aba61" +dependencies = [ + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi 1.0.1", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.112", +] + +[[package]] +name = "price-cache" +version = "0.1.0" +dependencies = [ + "actix-web", + "bigdecimal", + "chrono", + "clap", + "contextful", + "currency", + "database", + "deadpool", + "diesel", + "diesel-async", + "reqwest 0.12.28", + "rpc", + "serde", + "serde_json", + "serial_test", + "thiserror 1.0.69", + "tokio", + "tokio-postgres", + "tracing", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint 0.9.5", +] + +[[package]] +name = "primitives" +version = "1.3.0" +dependencies = [ + "async-trait", + "base64 0.22.1", + "borsh", + "diesel", + "futures", + "hex", + "microtype", + "parking_lot 0.12.5", + "rand 0.8.5", + "rand_derive2", + "secp256k1 0.28.2", + "serde", + "serde_json", + "sha2", + "sha3", + "thiserror 1.0.69", + "tokio", + "ts-rs", + "uint 0.10.0", + "web3", + "workspace-hack", +] + +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror 1.0.69", + "toml 0.5.11", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit 0.23.10+spec-1.0.0", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "proc-macro2" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", + "version_check", + "yansi 1.0.1", +] + +[[package]] +name = "proc_macro2_helper" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79528bef70da112116feb5ecb6b64f1394e5360660d6474a760789ea07885501" +dependencies = [ + "proc-macro2", + "syn 2.0.112", +] + +[[package]] +name = "procfs" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5b72d8145275d844d4b5f6d4e1eef00c8cd889edb6035c21675d1bb1f45c9f" +dependencies = [ + "bitflags 2.10.0", + "chrono", + "flate2", + "hex", + "procfs-core 0.17.0", + "rustix 0.38.44", +] + +[[package]] +name = "procfs" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25485360a54d6861439d60facef26de713b1e126bf015ec8f98239467a2b82f7" +dependencies = [ + "bitflags 2.10.0", + "procfs-core 0.18.0", + "rustix 1.1.3", +] + +[[package]] +name = "procfs-core" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "239df02d8349b06fc07398a3a1697b06418223b1c7725085e801e7c0fc6a12ec" +dependencies = [ + "bitflags 2.10.0", + "chrono", + "hex", +] + +[[package]] +name = "procfs-core" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6401bf7b6af22f78b563665d15a22e9aef27775b79b149a66ca022468a4e405" +dependencies = [ + "bitflags 2.10.0", + "hex", +] + +[[package]] +name = "prometheus-client" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" +dependencies = [ + "dtoa 1.0.11", + "itoa 1.0.17", + "parking_lot 0.12.5", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "proptest" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +dependencies = [ + "bit-set 0.8.0", + "bit-vec 0.8.0", + "bitflags 2.10.0", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift 0.4.0", + "regex-syntax 0.8.8", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive 0.13.5", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive 0.14.1", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck 0.5.0", + "itertools 0.14.0", + "log", + "multimap", + "once_cell", + "petgraph 0.7.1", + "prettyplease", + "prost 0.13.5", + "prost-types", + "regex", + "syn 2.0.112", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost 0.13.5", +] + +[[package]] +name = "protoc-bin-vendored" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1c381df33c98266b5f08186583660090a4ffa0889e76c7e9a5e175f645a67fa" +dependencies = [ + "protoc-bin-vendored-linux-aarch_64", + "protoc-bin-vendored-linux-ppcle_64", + "protoc-bin-vendored-linux-s390_64", + "protoc-bin-vendored-linux-x86_32", + "protoc-bin-vendored-linux-x86_64", + "protoc-bin-vendored-macos-aarch_64", + "protoc-bin-vendored-macos-x86_64", + "protoc-bin-vendored-win32", +] + +[[package]] +name = "protoc-bin-vendored-linux-aarch_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c350df4d49b5b9e3ca79f7e646fde2377b199e13cfa87320308397e1f37e1a4c" + +[[package]] +name = "protoc-bin-vendored-linux-ppcle_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55a63e6c7244f19b5c6393f025017eb5d793fd5467823a099740a7a4222440c" + +[[package]] +name = "protoc-bin-vendored-linux-s390_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dba5565db4288e935d5330a07c264a4ee8e4a5b4a4e6f4e83fad824cc32f3b0" + +[[package]] +name = "protoc-bin-vendored-linux-x86_32" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8854774b24ee28b7868cd71dccaae8e02a2365e67a4a87a6cd11ee6cdbdf9cf5" + +[[package]] +name = "protoc-bin-vendored-linux-x86_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38b07546580df720fa464ce124c4b03630a6fb83e05c336fea2a241df7e5d78" + +[[package]] +name = "protoc-bin-vendored-macos-aarch_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89278a9926ce312e51f1d999fee8825d324d603213344a9a706daa009f1d8092" + +[[package]] +name = "protoc-bin-vendored-macos-x86_64" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81745feda7ccfb9471d7a4de888f0652e806d5795b61480605d4943176299756" + +[[package]] +name = "protoc-bin-vendored-win32" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95067976aca6421a523e491fce939a3e65249bac4b977adee0ee9771568e8aa3" + +[[package]] +name = "prover" +version = "1.3.0" +dependencies = [ + "borsh", + "contracts", + "element", + "ethereum-types", + "expect-test", + "primitives", + "rustc-hex", + "secp256k1 0.28.2", + "serde_json", + "smirk", + "thiserror 1.0.69", + "tokio", + "tracing", + "web3", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "providers-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "currency", + "element", + "kyc", + "network", + "ramps-interface", + "reqwest 0.12.28", + "rpc", + "serde", + "serde_json", + "strum 0.27.2", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "veil", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "providers-mock-cli" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-multipart", + "actix-server", + "actix-web", + "aes-gcm", + "alfred-interface", + "alfred-provider", + "base64 0.22.1", + "chrono", + "clap", + "contextful", + "currency", + "futures", + "hex", + "json-with-logging", + "kyc", + "manteca-provider", + "once_cell", + "providers-interface", + "rain-http", + "rain-interface", + "rand 0.8.5", + "reqwest 0.12.28", + "rsa", + "serde", + "serde_json", + "serial_test", + "sha1", + "sha2", + "strum 0.27.2", + "strum_macros 0.27.2", + "sumsub-provider", + "tracing", + "tracing-subscriber 0.3.22", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "psm" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11f2fedc3b7dafdc2851bc52f277377c5473d378859be234bc7ebb593144d01" +dependencies = [ + "ar_archive_writer", + "cc", +] + +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.10.0", + "memchr", + "unicase", +] + +[[package]] +name = "push-notification-expo" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "expo_push_notification_client", + "push-notification-interface", + "serde_json", + "tokio", + "tracing", + "workspace-hack", +] + +[[package]] +name = "push-notification-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "serde_json", + "thiserror 1.0.69", + "tokio", + "unimock", + "workspace-hack", +] + +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi 0.11.1+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quick-protobuf" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +dependencies = [ + "byteorder", +] + +[[package]] +name = "quick-protobuf-codec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1693116345026436eb2f10b677806169c1a1260c1c60eaaffe3fb5a29ae23d8b" +dependencies = [ + "asynchronous-codec", + "bytes", + "quick-protobuf", + "thiserror 1.0.69", + "unsigned-varint 0.7.2", +] + +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quick-xml" +version = "0.37.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +dependencies = [ + "memchr", +] + +[[package]] +name = "quickcheck" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" +dependencies = [ + "env_logger", + "log", + "rand 0.8.5", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto 0.11.13", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls 0.23.35", + "socket2 0.6.1", + "thiserror 2.0.17", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" +dependencies = [ + "bytes", + "rand 0.8.5", + "ring 0.16.20", + "rustc-hash 1.1.0", + "rustls 0.20.9", + "slab", + "thiserror 1.0.69", + "tinyvec", + "tracing", + "webpki", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring 0.17.14", + "rustc-hash 2.1.1", + "rustls 0.23.35", + "rustls-pki-types", + "slab", + "thiserror 2.0.17", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.1", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rain-http" +version = "0.1.0" +dependencies = [ + "aes-gcm", + "async-trait", + "base64 0.22.1", + "chrono", + "contextful", + "currency", + "hex", + "kyc", + "mockito", + "rain-interface", + "rand 0.8.5", + "reqwest 0.12.28", + "rsa", + "serde", + "serde_json", + "serial_test", + "sha1", + "tokio", + "typenum", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "rain-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "currency", + "http 1.4.0", + "kyc", + "rpc", + "rsa", + "serde", + "serde_json", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "rain-provider" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "currency", + "kyc", + "network", + "providers-interface", + "rain-http", + "rain-interface", + "ramps-interface", + "thiserror 1.0.69", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "ramps" +version = "0.1.0" +dependencies = [ + "aes-gcm", + "alfred-interface", + "alfred-provider", + "async-recursion", + "async-trait", + "chrono", + "contextful", + "country", + "currency", + "data", + "document-ai-interface", + "element", + "hex", + "kyc", + "manteca-provider", + "network", + "notes-interface", + "object_store", + "primitives", + "providers-interface", + "rain-interface", + "ramps-interface", + "ramps-notification-interface", + "ramps-providers-interface", + "ramps-storage-interface", + "rand 0.8.5", + "rewards-interface", + "serde", + "serde_json", + "sha1", + "sha3", + "sumsub-interface", + "thiserror 1.0.69", + "tokio", + "tracing", + "unimock", + "uuid 1.19.0", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "ramps-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "currency", + "database", + "diesel", + "diesel-util", + "element", + "ethereum-types", + "kyc", + "network", + "primitives", + "rand 0.8.5", + "rpc", + "serde", + "serde_json", + "strum 0.27.2", + "strum_macros 0.27.2", + "test-spy", + "thiserror 1.0.69", + "ts-rs", + "uuid 1.19.0", + "veil", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "ramps-notification" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "currency", + "element", + "kyc", + "posthog-interface", + "push-notification-interface", + "ramps-interface", + "ramps-notification-interface", + "serde_json", + "slack-client-interface", + "thiserror 1.0.69", + "tokio", + "tracing", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "ramps-notification-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "currency", + "element", + "kyc", + "ramps-interface", + "serde", + "serde_json", + "strum 0.27.2", + "thiserror 1.0.69", + "tokio", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "ramps-providers-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "providers-interface", + "ramps-interface", + "thiserror 1.0.69", + "unimock", + "workspace-hack", +] + +[[package]] +name = "ramps-rpc" +version = "0.1.0" +dependencies = [ + "actix-web", + "async-trait", + "contextful", + "currency", + "hmac-sha256-json", + "json-with-logging", + "ramps-interface", + "rpc", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "ramps-storage-interface" +version = "0.1.0" +dependencies = [ + "async-trait", + "currency", + "data", + "element", + "kyc", + "network", + "ramps-interface", + "serde_json", + "unimock", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "ramps-storage-pg" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "currency", + "data", + "database", + "diesel", + "diesel-async", + "element", + "kyc", + "network", + "ramps-interface", + "ramps-storage-interface", + "serde_json", + "thiserror 1.0.69", + "uuid 1.19.0", + "workspace-hack", +] + +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", + "serde", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "serde", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", + "serde", +] + +[[package]] +name = "rand_derive2" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e07d80c051ce2007c5cbb87ae0a6be7c5e5345cb03e06717b64ed5c426cbfb3" +dependencies = [ + "proc-macro2", + "proc_macro2_helper", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rangemap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973443cf09a9c8656b574a866ab68dfa19f0867d0340648c7d2f6a71b8a8ea68" + +[[package]] +name = "rapidhash" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2988730ee014541157f48ce4dcc603940e00915edc3c7f9a8d78092256bb2493" +dependencies = [ + "rand 0.9.2", + "rustversion", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rcgen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +dependencies = [ + "pem 1.1.1", + "ring 0.16.20", + "time", + "yasna", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "recvmsg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax 0.8.8", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.8", +] + +[[package]] +name = "regex-cache" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f7b62d69743b8b94f353b6b7c3deb4c5582828328bcb8d5fedf214373808793" +dependencies = [ + "lru-cache", + "oncemutex", + "regex", + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-lite" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "async-compression", + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-rustls 0.24.2", + "hyper-tls 0.5.0", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded 0.7.1", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.24.1", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.4", + "winreg", +] + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.12", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", + "hyper-rustls 0.27.7", + "hyper-tls 0.6.0", + "hyper-util", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls 0.23.35", + "rustls-native-certs", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded 0.7.1", + "sync_wrapper 1.0.2", + "tokio", + "tokio-native-tls", + "tokio-rustls 0.26.4", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots 1.0.4", +] + +[[package]] +name = "resolv-conf" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" + +[[package]] +name = "reth-basic-payload-builder" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "futures-core", + "futures-util", + "metrics", + "reth-chain-state", + "reth-metrics", + "reth-payload-builder", + "reth-payload-builder-primitives", + "reth-payload-primitives", + "reth-primitives-traits", + "reth-revm", + "reth-storage-api", + "reth-tasks", + "tokio", + "tracing", +] + +[[package]] +name = "reth-chain-state" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "derive_more 2.1.1", + "metrics", + "parking_lot 0.12.5", + "pin-project", + "rand 0.9.2", + "reth-chainspec", + "reth-errors", + "reth-ethereum-primitives", + "reth-execution-types", + "reth-metrics", + "reth-primitives-traits", + "reth-storage-api", + "reth-trie", + "revm-database", + "revm-state", + "serde", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-chainspec" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-genesis", + "alloy-primitives", + "alloy-trie", + "auto_impl", + "derive_more 2.1.1", + "reth-ethereum-forks", + "reth-network-peers", + "reth-primitives-traits", + "serde_json", +] + +[[package]] +name = "reth-cli-util" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "cfg-if", + "eyre", + "libc", + "rand 0.8.5", + "reth-fs-util", + "secp256k1 0.30.0", + "serde", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-codecs" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives", + "alloy-trie", + "bytes", + "modular-bitfield", + "op-alloy-consensus", + "reth-codecs-derive", + "reth-zstd-compressors", + "serde", +] + +[[package]] +name = "reth-codecs-derive" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "reth-config" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "eyre", + "humantime-serde", + "reth-network-types", + "reth-prune-types", + "reth-stages-types", + "reth-static-file-types", + "serde", + "toml 0.8.23", + "url", +] + +[[package]] +name = "reth-consensus" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "auto_impl", + "reth-execution-types", + "reth-primitives-traits", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-consensus-common" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "reth-chainspec", + "reth-consensus", + "reth-primitives-traits", +] + +[[package]] +name = "reth-consensus-debug-client" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types-engine", + "alloy-transport", + "auto_impl", + "derive_more 2.1.1", + "eyre", + "futures", + "reqwest 0.12.28", + "reth-node-api", + "reth-primitives-traits", + "reth-tracing", + "ringbuffer", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "reth-db" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "derive_more 2.1.1", + "eyre", + "metrics", + "page_size", + "reth-db-api", + "reth-fs-util", + "reth-libmdbx", + "reth-metrics", + "reth-nippy-jar", + "reth-static-file-types", + "reth-storage-errors", + "reth-tracing", + "rustc-hash 2.1.1", + "strum 0.27.2", + "sysinfo", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-db-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-genesis", + "alloy-primitives", + "bytes", + "derive_more 2.1.1", + "metrics", + "modular-bitfield", + "parity-scale-codec", + "reth-codecs", + "reth-db-models", + "reth-ethereum-primitives", + "reth-primitives-traits", + "reth-prune-types", + "reth-stages-types", + "reth-storage-errors", + "reth-trie-common", + "roaring", + "serde", +] + +[[package]] +name = "reth-db-common" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-genesis", + "alloy-primitives", + "boyer-moore-magiclen", + "eyre", + "reth-chainspec", + "reth-codecs", + "reth-config", + "reth-db-api", + "reth-etl", + "reth-execution-errors", + "reth-fs-util", + "reth-node-types", + "reth-primitives-traits", + "reth-provider", + "reth-stages-types", + "reth-static-file-types", + "reth-trie", + "reth-trie-db", + "serde", + "serde_json", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "reth-db-models" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "bytes", + "modular-bitfield", + "reth-codecs", + "reth-primitives-traits", + "serde", +] + +[[package]] +name = "reth-discv4" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "discv5", + "enr", + "itertools 0.14.0", + "parking_lot 0.12.5", + "rand 0.8.5", + "reth-ethereum-forks", + "reth-net-banlist", + "reth-net-nat", + "reth-network-peers", + "schnellru", + "secp256k1 0.30.0", + "serde", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-discv5" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "derive_more 2.1.1", + "discv5", + "enr", + "futures", + "itertools 0.14.0", + "metrics", + "rand 0.9.2", + "reth-chainspec", + "reth-ethereum-forks", + "reth-metrics", + "reth-network-peers", + "secp256k1 0.30.0", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "reth-dns-discovery" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "data-encoding", + "enr", + "hickory-resolver", + "linked_hash_set", + "parking_lot 0.12.5", + "reth-ethereum-forks", + "reth-network-peers", + "reth-tokio-util", + "schnellru", + "secp256k1 0.30.0", + "serde", + "serde_with", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-downloaders" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "futures", + "futures-util", + "metrics", + "pin-project", + "rayon", + "reth-config", + "reth-consensus", + "reth-metrics", + "reth-network-p2p", + "reth-network-peers", + "reth-primitives-traits", + "reth-storage-api", + "reth-tasks", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "reth-ecies" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "aes", + "alloy-primitives", + "alloy-rlp", + "block-padding", + "byteorder", + "cipher", + "concat-kdf", + "ctr", + "digest 0.10.7", + "futures", + "hmac", + "pin-project", + "rand 0.8.5", + "reth-network-peers", + "secp256k1 0.30.0", + "sha2", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "reth-engine-local" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "alloy-rpc-types-engine", + "eyre", + "futures-util", + "reth-chainspec", + "reth-engine-primitives", + "reth-ethereum-engine-primitives", + "reth-payload-builder", + "reth-payload-primitives", + "reth-primitives-traits", + "reth-storage-api", + "reth-transaction-pool", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-engine-primitives" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "auto_impl", + "futures", + "reth-chain-state", + "reth-errors", + "reth-ethereum-primitives", + "reth-evm", + "reth-execution-types", + "reth-payload-builder-primitives", + "reth-payload-primitives", + "reth-primitives-traits", + "reth-trie-common", + "serde", + "thiserror 2.0.17", + "tokio", +] + +[[package]] +name = "reth-engine-service" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "futures", + "pin-project", + "reth-chainspec", + "reth-consensus", + "reth-engine-primitives", + "reth-engine-tree", + "reth-ethereum-primitives", + "reth-evm", + "reth-network-p2p", + "reth-node-types", + "reth-payload-builder", + "reth-provider", + "reth-prune", + "reth-stages-api", + "reth-tasks", + "reth-trie-db", +] + +[[package]] +name = "reth-engine-tree" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eip7928", + "alloy-eips", + "alloy-evm", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-engine", + "crossbeam-channel", + "dashmap 6.1.0", + "derive_more 2.1.1", + "futures", + "metrics", + "mini-moka", + "moka", + "parking_lot 0.12.5", + "rayon", + "reth-chain-state", + "reth-consensus", + "reth-db", + "reth-engine-primitives", + "reth-errors", + "reth-ethereum-primitives", + "reth-evm", + "reth-execution-types", + "reth-metrics", + "reth-network-p2p", + "reth-payload-builder", + "reth-payload-primitives", + "reth-primitives-traits", + "reth-provider", + "reth-prune", + "reth-revm", + "reth-stages-api", + "reth-tasks", + "reth-trie", + "reth-trie-common", + "reth-trie-db", + "reth-trie-parallel", + "reth-trie-sparse", + "reth-trie-sparse-parallel", + "revm", + "revm-primitives", + "schnellru", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "reth-engine-util" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-rpc-types-engine", + "eyre", + "futures", + "itertools 0.14.0", + "pin-project", + "reth-chainspec", + "reth-engine-primitives", + "reth-engine-tree", + "reth-errors", + "reth-evm", + "reth-fs-util", + "reth-payload-primitives", + "reth-primitives-traits", + "reth-revm", + "reth-storage-api", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "reth-era" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "ethereum_ssz", + "ethereum_ssz_derive", + "snap", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-era-downloader" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "bytes", + "eyre", + "futures-util", + "reqwest 0.12.28", + "reth-era", + "reth-fs-util", + "sha2", + "tokio", +] + +[[package]] +name = "reth-era-utils" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "eyre", + "futures-util", + "reth-db-api", + "reth-era", + "reth-era-downloader", + "reth-etl", + "reth-fs-util", + "reth-primitives-traits", + "reth-provider", + "reth-stages-types", + "reth-storage-api", + "tokio", + "tracing", +] + +[[package]] +name = "reth-errors" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "reth-consensus", + "reth-execution-errors", + "reth-storage-errors", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-eth-wire" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-chains", + "alloy-primitives", + "alloy-rlp", + "bytes", + "derive_more 2.1.1", + "futures", + "pin-project", + "reth-codecs", + "reth-ecies", + "reth-eth-wire-types", + "reth-ethereum-forks", + "reth-metrics", + "reth-network-peers", + "reth-primitives-traits", + "serde", + "snap", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "reth-eth-wire-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-chains", + "alloy-consensus", + "alloy-eips", + "alloy-hardforks", + "alloy-primitives", + "alloy-rlp", + "bytes", + "derive_more 2.1.1", + "reth-chainspec", + "reth-codecs-derive", + "reth-ethereum-primitives", + "reth-primitives-traits", + "serde", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-ethereum" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "reth-chainspec", + "reth-codecs", + "reth-consensus", + "reth-consensus-common", + "reth-db", + "reth-engine-local", + "reth-eth-wire", + "reth-ethereum-consensus", + "reth-ethereum-primitives", + "reth-evm", + "reth-evm-ethereum", + "reth-network", + "reth-network-api", + "reth-node-api", + "reth-node-builder", + "reth-node-core", + "reth-node-ethereum", + "reth-primitives-traits", + "reth-provider", + "reth-revm", + "reth-rpc", + "reth-rpc-api", + "reth-rpc-builder", + "reth-rpc-eth-types", + "reth-storage-api", + "reth-tasks", + "reth-transaction-pool", + "reth-trie", + "reth-trie-db", +] + +[[package]] +name = "reth-ethereum-consensus" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "reth-chainspec", + "reth-consensus", + "reth-consensus-common", + "reth-execution-types", + "reth-primitives-traits", + "tracing", +] + +[[package]] +name = "reth-ethereum-engine-primitives" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-engine", + "reth-engine-primitives", + "reth-ethereum-primitives", + "reth-payload-primitives", + "reth-primitives-traits", + "serde", + "sha2", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-ethereum-forks" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eip2124", + "alloy-hardforks", + "alloy-primitives", + "auto_impl", + "once_cell", + "rustc-hash 2.1.1", +] + +[[package]] +name = "reth-ethereum-payload-builder" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-engine", + "reth-basic-payload-builder", + "reth-chainspec", + "reth-consensus-common", + "reth-errors", + "reth-ethereum-primitives", + "reth-evm", + "reth-evm-ethereum", + "reth-payload-builder", + "reth-payload-builder-primitives", + "reth-payload-primitives", + "reth-payload-validator", + "reth-primitives-traits", + "reth-revm", + "reth-storage-api", + "reth-transaction-pool", + "revm", + "tracing", +] + +[[package]] +name = "reth-ethereum-primitives" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth", + "alloy-serde", + "modular-bitfield", + "reth-codecs", + "reth-primitives-traits", + "reth-zstd-compressors", + "serde", + "serde_with", +] + +[[package]] +name = "reth-etl" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "rayon", + "reth-db-api", + "tempfile", +] + +[[package]] +name = "reth-evm" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-primitives", + "auto_impl", + "derive_more 2.1.1", + "futures-util", + "metrics", + "rayon", + "reth-execution-errors", + "reth-execution-types", + "reth-metrics", + "reth-primitives-traits", + "reth-storage-api", + "reth-storage-errors", + "reth-trie-common", + "revm", +] + +[[package]] +name = "reth-evm-ethereum" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-primitives", + "alloy-rpc-types-engine", + "derive_more 2.1.1", + "reth-chainspec", + "reth-ethereum-forks", + "reth-ethereum-primitives", + "reth-evm", + "reth-execution-types", + "reth-primitives-traits", + "reth-storage-errors", + "revm", +] + +[[package]] +name = "reth-execution-errors" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-evm", + "alloy-primitives", + "alloy-rlp", + "nybbles", + "reth-storage-errors", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-execution-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-primitives", + "derive_more 2.1.1", + "reth-ethereum-primitives", + "reth-primitives-traits", + "reth-trie-common", + "revm", + "serde", + "serde_with", +] + +[[package]] +name = "reth-exex" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "eyre", + "futures", + "itertools 0.14.0", + "metrics", + "parking_lot 0.12.5", + "reth-chain-state", + "reth-chainspec", + "reth-config", + "reth-ethereum-primitives", + "reth-evm", + "reth-exex-types", + "reth-fs-util", + "reth-metrics", + "reth-node-api", + "reth-node-core", + "reth-payload-builder", + "reth-primitives-traits", + "reth-provider", + "reth-prune-types", + "reth-revm", + "reth-stages-api", + "reth-tasks", + "reth-tracing", + "rmp-serde", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "reth-exex-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "reth-chain-state", + "reth-execution-types", + "reth-primitives-traits", + "serde", + "serde_with", +] + +[[package]] +name = "reth-fs-util" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "serde", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-invalid-block-hooks" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-debug", + "eyre", + "futures", + "jsonrpsee 0.26.0", + "pretty_assertions", + "reth-engine-primitives", + "reth-evm", + "reth-primitives-traits", + "reth-provider", + "reth-revm", + "reth-rpc-api", + "reth-tracing", + "reth-trie", + "revm", + "revm-bytecode", + "revm-database", + "serde", + "serde_json", +] + +[[package]] +name = "reth-ipc" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "bytes", + "futures", + "futures-util", + "interprocess", + "jsonrpsee 0.26.0", + "pin-project", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "reth-libmdbx" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "bitflags 2.10.0", + "byteorder", + "dashmap 6.1.0", + "derive_more 2.1.1", + "parking_lot 0.12.5", + "reth-mdbx-sys", + "smallvec", + "thiserror 2.0.17", + "tracing", +] + +[[package]] +name = "reth-mdbx-sys" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "bindgen 0.71.1", + "cc", +] + +[[package]] +name = "reth-metrics" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "futures", + "metrics", + "metrics-derive", + "tokio", + "tokio-util", +] + +[[package]] +name = "reth-net-banlist" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "ipnet", +] + +[[package]] +name = "reth-net-nat" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "futures-util", + "if-addrs 0.14.0", + "reqwest 0.12.28", + "serde_with", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "reth-network" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "aquamarine", + "auto_impl", + "derive_more 2.1.1", + "discv5", + "enr", + "futures", + "itertools 0.14.0", + "metrics", + "parking_lot 0.12.5", + "pin-project", + "rand 0.8.5", + "rand 0.9.2", + "rayon", + "reth-chainspec", + "reth-consensus", + "reth-discv4", + "reth-discv5", + "reth-dns-discovery", + "reth-ecies", + "reth-eth-wire", + "reth-eth-wire-types", + "reth-ethereum-forks", + "reth-ethereum-primitives", + "reth-fs-util", + "reth-metrics", + "reth-net-banlist", + "reth-network-api", + "reth-network-p2p", + "reth-network-peers", + "reth-network-types", + "reth-primitives-traits", + "reth-storage-api", + "reth-tasks", + "reth-tokio-util", + "reth-transaction-pool", + "rustc-hash 2.1.1", + "schnellru", + "secp256k1 0.30.0", + "serde", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "reth-network-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "alloy-rpc-types-admin", + "alloy-rpc-types-eth", + "auto_impl", + "derive_more 2.1.1", + "enr", + "futures", + "reth-eth-wire-types", + "reth-ethereum-forks", + "reth-network-p2p", + "reth-network-peers", + "reth-network-types", + "reth-tokio-util", + "serde", + "thiserror 2.0.17", + "tokio", + "tokio-stream", +] + +[[package]] +name = "reth-network-p2p" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "auto_impl", + "derive_more 2.1.1", + "futures", + "reth-consensus", + "reth-eth-wire-types", + "reth-ethereum-primitives", + "reth-network-peers", + "reth-network-types", + "reth-primitives-traits", + "reth-storage-errors", + "tokio", + "tracing", +] + +[[package]] +name = "reth-network-peers" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "enr", + "secp256k1 0.30.0", + "serde_with", + "thiserror 2.0.17", + "tokio", + "url", +] + +[[package]] +name = "reth-network-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eip2124", + "humantime-serde", + "reth-net-banlist", + "reth-network-peers", + "serde", + "serde_json", + "tracing", +] + +[[package]] +name = "reth-nippy-jar" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "anyhow", + "bincode 1.3.3", + "derive_more 2.1.1", + "lz4_flex", + "memmap2", + "reth-fs-util", + "serde", + "thiserror 2.0.17", + "tracing", + "zstd 0.13.3", +] + +[[package]] +name = "reth-node-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-rpc-types-engine", + "eyre", + "reth-basic-payload-builder", + "reth-consensus", + "reth-db-api", + "reth-engine-primitives", + "reth-evm", + "reth-network-api", + "reth-node-core", + "reth-node-types", + "reth-payload-builder", + "reth-payload-builder-primitives", + "reth-payload-primitives", + "reth-provider", + "reth-tasks", + "reth-tokio-util", + "reth-transaction-pool", +] + +[[package]] +name = "reth-node-builder" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-provider", + "alloy-rpc-types", + "alloy-rpc-types-engine", + "aquamarine", + "eyre", + "fdlimit", + "futures", + "jsonrpsee 0.26.0", + "parking_lot 0.12.5", + "rayon", + "reth-basic-payload-builder", + "reth-chain-state", + "reth-chainspec", + "reth-config", + "reth-consensus", + "reth-consensus-debug-client", + "reth-db", + "reth-db-api", + "reth-db-common", + "reth-downloaders", + "reth-engine-local", + "reth-engine-primitives", + "reth-engine-service", + "reth-engine-tree", + "reth-engine-util", + "reth-evm", + "reth-exex", + "reth-fs-util", + "reth-invalid-block-hooks", + "reth-network", + "reth-network-api", + "reth-network-p2p", + "reth-node-api", + "reth-node-core", + "reth-node-ethstats", + "reth-node-events", + "reth-node-metrics", + "reth-payload-builder", + "reth-primitives-traits", + "reth-provider", + "reth-prune", + "reth-rpc", + "reth-rpc-api", + "reth-rpc-builder", + "reth-rpc-engine-api", + "reth-rpc-eth-types", + "reth-rpc-layer", + "reth-stages", + "reth-static-file", + "reth-tasks", + "reth-tokio-util", + "reth-tracing", + "reth-transaction-pool", + "reth-trie-db", + "secp256k1 0.30.0", + "serde_json", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-node-core" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "clap", + "derive_more 2.1.1", + "dirs-next", + "eyre", + "futures", + "humantime", + "ipnet", + "rand 0.9.2", + "reth-chainspec", + "reth-cli-util", + "reth-config", + "reth-consensus", + "reth-db", + "reth-discv4", + "reth-discv5", + "reth-engine-local", + "reth-engine-primitives", + "reth-ethereum-forks", + "reth-net-banlist", + "reth-net-nat", + "reth-network", + "reth-network-p2p", + "reth-network-peers", + "reth-primitives-traits", + "reth-provider", + "reth-prune-types", + "reth-rpc-convert", + "reth-rpc-eth-types", + "reth-rpc-server-types", + "reth-stages-types", + "reth-storage-api", + "reth-storage-errors", + "reth-tracing", + "reth-tracing-otlp", + "reth-transaction-pool", + "secp256k1 0.30.0", + "serde", + "shellexpand", + "strum 0.27.2", + "thiserror 2.0.17", + "toml 0.8.23", + "tracing", + "url", + "vergen", + "vergen-git2", +] + +[[package]] +name = "reth-node-ethereum" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-network", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "eyre", + "reth-chainspec", + "reth-engine-local", + "reth-engine-primitives", + "reth-ethereum-consensus", + "reth-ethereum-engine-primitives", + "reth-ethereum-payload-builder", + "reth-ethereum-primitives", + "reth-evm", + "reth-evm-ethereum", + "reth-network", + "reth-node-api", + "reth-node-builder", + "reth-payload-primitives", + "reth-primitives-traits", + "reth-provider", + "reth-revm", + "reth-rpc", + "reth-rpc-api", + "reth-rpc-builder", + "reth-rpc-eth-api", + "reth-rpc-eth-types", + "reth-rpc-server-types", + "reth-tracing", + "reth-transaction-pool", + "revm", + "tokio", +] + +[[package]] +name = "reth-node-ethstats" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "chrono", + "futures-util", + "reth-chain-state", + "reth-network-api", + "reth-primitives-traits", + "reth-storage-api", + "reth-transaction-pool", + "serde", + "serde_json", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tracing", + "url", +] + +[[package]] +name = "reth-node-events" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "derive_more 2.1.1", + "futures", + "humantime", + "pin-project", + "reth-engine-primitives", + "reth-network-api", + "reth-primitives-traits", + "reth-prune-types", + "reth-stages", + "reth-static-file-types", + "reth-storage-api", + "tokio", + "tracing", +] + +[[package]] +name = "reth-node-metrics" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "bytes", + "eyre", + "http 1.4.0", + "http-body-util", + "jsonrpsee-server", + "metrics", + "metrics-exporter-prometheus", + "metrics-process", + "metrics-util", + "procfs 0.17.0", + "reqwest 0.12.28", + "reth-metrics", + "reth-tasks", + "tokio", + "tower", + "tracing", +] + +[[package]] +name = "reth-node-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "reth-chainspec", + "reth-db-api", + "reth-engine-primitives", + "reth-payload-primitives", + "reth-primitives-traits", +] + +[[package]] +name = "reth-payload-builder" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "alloy-rpc-types", + "futures-util", + "metrics", + "reth-chain-state", + "reth-ethereum-engine-primitives", + "reth-metrics", + "reth-payload-builder-primitives", + "reth-payload-primitives", + "reth-primitives-traits", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-payload-builder-primitives" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "pin-project", + "reth-payload-primitives", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-payload-primitives" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "auto_impl", + "either", + "op-alloy-rpc-types-engine", + "reth-chain-state", + "reth-chainspec", + "reth-errors", + "reth-execution-types", + "reth-primitives-traits", + "reth-trie-common", + "serde", + "thiserror 2.0.17", + "tokio", +] + +[[package]] +name = "reth-payload-validator" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-rpc-types-engine", + "reth-primitives-traits", +] + +[[package]] +name = "reth-primitives" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "c-kzg", + "once_cell", + "reth-ethereum-forks", + "reth-ethereum-primitives", + "reth-primitives-traits", + "reth-static-file-types", +] + +[[package]] +name = "reth-primitives-traits" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-genesis", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth", + "alloy-trie", + "auto_impl", + "byteorder", + "bytes", + "derive_more 2.1.1", + "modular-bitfield", + "once_cell", + "op-alloy-consensus", + "rayon", + "reth-codecs", + "revm-bytecode", + "revm-primitives", + "revm-state", + "secp256k1 0.30.0", + "serde", + "serde_with", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-provider" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "dashmap 6.1.0", + "eyre", + "itertools 0.14.0", + "metrics", + "notify", + "parking_lot 0.12.5", + "rayon", + "reth-chain-state", + "reth-chainspec", + "reth-codecs", + "reth-db", + "reth-db-api", + "reth-errors", + "reth-ethereum-primitives", + "reth-execution-types", + "reth-metrics", + "reth-nippy-jar", + "reth-node-types", + "reth-primitives-traits", + "reth-prune-types", + "reth-stages-types", + "reth-static-file-types", + "reth-storage-api", + "reth-storage-errors", + "reth-trie", + "reth-trie-db", + "revm-database", + "strum 0.27.2", + "tracing", +] + +[[package]] +name = "reth-prune" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "itertools 0.14.0", + "metrics", + "rayon", + "reth-config", + "reth-db-api", + "reth-errors", + "reth-exex-types", + "reth-metrics", + "reth-primitives-traits", + "reth-provider", + "reth-prune-types", + "reth-stages-types", + "reth-static-file-types", + "reth-tokio-util", + "rustc-hash 2.1.1", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "reth-prune-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "derive_more 2.1.1", + "modular-bitfield", + "reth-codecs", + "serde", + "strum 0.27.2", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-revm" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "reth-primitives-traits", + "reth-storage-api", + "reth-storage-errors", + "reth-trie", + "revm", +] + +[[package]] +name = "reth-rpc" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-eip7928", + "alloy-eips", + "alloy-evm", + "alloy-genesis", + "alloy-network", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-rpc-types-admin", + "alloy-rpc-types-beacon", + "alloy-rpc-types-debug", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-rpc-types-mev", + "alloy-rpc-types-trace", + "alloy-rpc-types-txpool", + "alloy-serde", + "alloy-signer", + "alloy-signer-local", + "async-trait", + "derive_more 2.1.1", + "dyn-clone", + "futures", + "http 1.4.0", + "http-body 1.0.1", + "hyper 1.8.1", + "itertools 0.14.0", + "jsonrpsee 0.26.0", + "jsonrpsee-types 0.26.0", + "jsonwebtoken 9.3.1", + "parking_lot 0.12.5", + "pin-project", + "reth-chain-state", + "reth-chainspec", + "reth-consensus", + "reth-consensus-common", + "reth-engine-primitives", + "reth-errors", + "reth-ethereum-engine-primitives", + "reth-ethereum-primitives", + "reth-evm", + "reth-evm-ethereum", + "reth-execution-types", + "reth-metrics", + "reth-network-api", + "reth-network-peers", + "reth-network-types", + "reth-node-api", + "reth-primitives-traits", + "reth-revm", + "reth-rpc-api", + "reth-rpc-convert", + "reth-rpc-engine-api", + "reth-rpc-eth-api", + "reth-rpc-eth-types", + "reth-rpc-server-types", + "reth-storage-api", + "reth-tasks", + "reth-transaction-pool", + "reth-trie-common", + "revm", + "revm-inspectors", + "revm-primitives", + "serde", + "serde_json", + "sha2", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tower", + "tracing", + "tracing-futures", +] + +[[package]] +name = "reth-rpc-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eip7928", + "alloy-eips", + "alloy-genesis", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-rpc-types-admin", + "alloy-rpc-types-anvil", + "alloy-rpc-types-beacon", + "alloy-rpc-types-debug", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-rpc-types-mev", + "alloy-rpc-types-trace", + "alloy-rpc-types-txpool", + "alloy-serde", + "jsonrpsee 0.26.0", + "reth-chain-state", + "reth-engine-primitives", + "reth-network-peers", + "reth-rpc-eth-api", + "reth-trie-common", + "serde_json", +] + +[[package]] +name = "reth-rpc-builder" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-network", + "alloy-provider", + "dyn-clone", + "http 1.4.0", + "jsonrpsee 0.26.0", + "metrics", + "pin-project", + "reth-chain-state", + "reth-chainspec", + "reth-consensus", + "reth-engine-primitives", + "reth-evm", + "reth-ipc", + "reth-metrics", + "reth-network-api", + "reth-node-core", + "reth-primitives-traits", + "reth-rpc", + "reth-rpc-api", + "reth-rpc-eth-api", + "reth-rpc-eth-types", + "reth-rpc-layer", + "reth-rpc-server-types", + "reth-storage-api", + "reth-tasks", + "reth-tokio-util", + "reth-transaction-pool", + "serde", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tracing", +] + +[[package]] +name = "reth-rpc-convert" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-evm", + "alloy-json-rpc", + "alloy-network", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-signer", + "auto_impl", + "dyn-clone", + "jsonrpsee-types 0.26.0", + "reth-ethereum-primitives", + "reth-evm", + "reth-primitives-traits", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-rpc-engine-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "async-trait", + "jsonrpsee-core 0.26.0", + "jsonrpsee-types 0.26.0", + "metrics", + "reth-chainspec", + "reth-engine-primitives", + "reth-metrics", + "reth-network-api", + "reth-payload-builder", + "reth-payload-builder-primitives", + "reth-payload-primitives", + "reth-primitives-traits", + "reth-rpc-api", + "reth-storage-api", + "reth-tasks", + "reth-transaction-pool", + "serde", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "reth-rpc-eth-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-dyn-abi", + "alloy-eips", + "alloy-evm", + "alloy-json-rpc", + "alloy-network", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth", + "alloy-rpc-types-mev", + "alloy-serde", + "async-trait", + "auto_impl", + "dyn-clone", + "futures", + "jsonrpsee 0.26.0", + "jsonrpsee-types 0.26.0", + "parking_lot 0.12.5", + "reth-chain-state", + "reth-chainspec", + "reth-errors", + "reth-evm", + "reth-network-api", + "reth-node-api", + "reth-primitives-traits", + "reth-revm", + "reth-rpc-convert", + "reth-rpc-eth-types", + "reth-rpc-server-types", + "reth-storage-api", + "reth-tasks", + "reth-transaction-pool", + "reth-trie-common", + "revm", + "revm-inspectors", + "tokio", + "tracing", +] + +[[package]] +name = "reth-rpc-eth-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-network", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-types-eth", + "alloy-sol-types", + "alloy-transport", + "derive_more 2.1.1", + "futures", + "itertools 0.14.0", + "jsonrpsee-core 0.26.0", + "jsonrpsee-types 0.26.0", + "metrics", + "rand 0.9.2", + "reqwest 0.12.28", + "reth-chain-state", + "reth-chainspec", + "reth-errors", + "reth-ethereum-primitives", + "reth-evm", + "reth-execution-types", + "reth-metrics", + "reth-primitives-traits", + "reth-revm", + "reth-rpc-convert", + "reth-rpc-server-types", + "reth-storage-api", + "reth-tasks", + "reth-transaction-pool", + "reth-trie", + "revm", + "revm-inspectors", + "schnellru", + "serde", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "reth-rpc-layer" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-rpc-types-engine", + "http 1.4.0", + "jsonrpsee-http-client", + "pin-project", + "tower", + "tower-http", + "tracing", +] + +[[package]] +name = "reth-rpc-server-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "jsonrpsee-core 0.26.0", + "jsonrpsee-types 0.26.0", + "reth-errors", + "reth-network-api", + "serde", + "strum 0.27.2", +] + +[[package]] +name = "reth-stages" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "bincode 1.3.3", + "eyre", + "futures-util", + "itertools 0.14.0", + "num-traits", + "rayon", + "reqwest 0.12.28", + "reth-codecs", + "reth-config", + "reth-consensus", + "reth-db", + "reth-db-api", + "reth-era", + "reth-era-downloader", + "reth-era-utils", + "reth-etl", + "reth-evm", + "reth-execution-types", + "reth-exex", + "reth-fs-util", + "reth-network-p2p", + "reth-primitives-traits", + "reth-provider", + "reth-prune", + "reth-prune-types", + "reth-revm", + "reth-stages-api", + "reth-static-file-types", + "reth-storage-api", + "reth-storage-errors", + "reth-trie", + "reth-trie-db", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "reth-stages-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "aquamarine", + "auto_impl", + "futures-util", + "metrics", + "reth-consensus", + "reth-errors", + "reth-metrics", + "reth-network-p2p", + "reth-primitives-traits", + "reth-provider", + "reth-prune", + "reth-stages-types", + "reth-static-file", + "reth-static-file-types", + "reth-tokio-util", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "reth-stages-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "bytes", + "modular-bitfield", + "reth-codecs", + "reth-trie-common", + "serde", +] + +[[package]] +name = "reth-static-file" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "parking_lot 0.12.5", + "rayon", + "reth-codecs", + "reth-db-api", + "reth-primitives-traits", + "reth-provider", + "reth-prune-types", + "reth-stages-types", + "reth-static-file-types", + "reth-storage-errors", + "reth-tokio-util", + "tracing", +] + +[[package]] +name = "reth-static-file-types" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "derive_more 2.1.1", + "fixed-map", + "serde", + "strum 0.27.2", +] + +[[package]] +name = "reth-storage-api" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rpc-types-engine", + "auto_impl", + "reth-chainspec", + "reth-db-api", + "reth-db-models", + "reth-ethereum-primitives", + "reth-execution-types", + "reth-primitives-traits", + "reth-prune-types", + "reth-stages-types", + "reth-storage-errors", + "reth-trie-common", + "revm-database", + "serde_json", +] + +[[package]] +name = "reth-storage-errors" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "derive_more 2.1.1", + "reth-primitives-traits", + "reth-prune-types", + "reth-static-file-types", + "revm-database-interface", + "revm-state", + "thiserror 2.0.17", +] + +[[package]] +name = "reth-tasks" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "auto_impl", + "dyn-clone", + "futures-util", + "metrics", + "pin-project", + "rayon", + "reth-metrics", + "thiserror 2.0.17", + "tokio", + "tracing", + "tracing-futures", +] + +[[package]] +name = "reth-tokio-util" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-tracing" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "clap", + "eyre", + "rolling-file", + "tracing", + "tracing-appender", + "tracing-journald", + "tracing-logfmt", + "tracing-samply", + "tracing-subscriber 0.3.22", +] + +[[package]] +name = "reth-tracing-otlp" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "clap", + "eyre", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber 0.3.22", + "url", +] + +[[package]] +name = "reth-transaction-pool" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "aquamarine", + "auto_impl", + "bitflags 2.10.0", + "futures-util", + "metrics", + "parking_lot 0.12.5", + "pin-project", + "rand 0.9.2", + "reth-chain-state", + "reth-chainspec", + "reth-eth-wire-types", + "reth-ethereum-primitives", + "reth-execution-types", + "reth-fs-util", + "reth-metrics", + "reth-primitives-traits", + "reth-storage-api", + "reth-tasks", + "revm-interpreter", + "revm-primitives", + "rustc-hash 2.1.1", + "schnellru", + "serde", + "serde_json", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tokio-stream", + "tracing", +] + +[[package]] +name = "reth-trie" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-primitives", + "alloy-rlp", + "alloy-trie", + "auto_impl", + "itertools 0.14.0", + "metrics", + "parking_lot 0.12.5", + "reth-execution-errors", + "reth-metrics", + "reth-primitives-traits", + "reth-stages-types", + "reth-storage-errors", + "reth-trie-common", + "reth-trie-sparse", + "revm-database", + "tracing", +] + +[[package]] +name = "reth-trie-common" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "alloy-rlp", + "alloy-rpc-types-eth", + "alloy-serde", + "alloy-trie", + "arrayvec", + "bytes", + "derive_more 2.1.1", + "itertools 0.14.0", + "nybbles", + "rayon", + "reth-codecs", + "reth-primitives-traits", + "revm-database", + "serde", + "serde_with", ] [[package]] -name = "opentelemetry-semantic-conventions" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5774f1ef1f982ef2a447f6ee04ec383981a3ab99c8e77a1a7b30182e65bbc84" -dependencies = [ - "opentelemetry", +name = "reth-trie-db" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "metrics", + "parking_lot 0.12.5", + "reth-db-api", + "reth-execution-errors", + "reth-metrics", + "reth-primitives-traits", + "reth-stages-types", + "reth-storage-api", + "reth-storage-errors", + "reth-trie", + "reth-trie-common", + "tracing", ] [[package]] -name = "opentelemetry_sdk" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f16aec8a98a457a52664d69e0091bac3a0abd18ead9b641cb00202ba4e0efe4" +name = "reth-trie-parallel" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" dependencies = [ - "async-trait", + "alloy-primitives", + "alloy-rlp", "crossbeam-channel", - "futures-channel", - "futures-executor", - "futures-util", - "glob", - "once_cell", - "opentelemetry", - "ordered-float", - "percent-encoding", - "rand 0.8.5", - "thiserror", + "dashmap 6.1.0", + "derive_more 2.1.1", + "itertools 0.14.0", + "metrics", + "rayon", + "reth-execution-errors", + "reth-metrics", + "reth-provider", + "reth-storage-errors", + "reth-trie", + "reth-trie-common", + "reth-trie-sparse", + "thiserror 2.0.17", "tokio", - "tokio-stream", + "tracing", ] [[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +name = "reth-trie-sparse" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-trie", + "auto_impl", + "metrics", + "rayon", + "reth-execution-errors", + "reth-metrics", + "reth-primitives-traits", + "reth-trie-common", + "smallvec", + "tracing", +] [[package]] -name = "ordered-float" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +name = "reth-trie-sparse-parallel" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" dependencies = [ - "num-traits", + "alloy-primitives", + "alloy-rlp", + "alloy-trie", + "metrics", + "rayon", + "reth-execution-errors", + "reth-metrics", + "reth-trie-common", + "reth-trie-sparse", + "smallvec", + "tracing", ] [[package]] -name = "os_info" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +name = "reth-zstd-compressors" +version = "1.10.2" +source = "git+https://github.com/paradigmxyz/reth?tag=v1.10.2#8e3b5e6a99439561b73c5dd31bd3eced2e994d60" dependencies = [ - "log", - "serde", - "winapi", + "zstd 0.13.3", ] [[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +name = "revm" +version = "34.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2aabdebaa535b3575231a88d72b642897ae8106cf6b0d12eafc6bfdf50abfc7" +dependencies = [ + "revm-bytecode", + "revm-context", + "revm-context-interface", + "revm-database", + "revm-database-interface", + "revm-handler", + "revm-inspector", + "revm-interpreter", + "revm-precompile", + "revm-primitives", + "revm-state", +] [[package]] -name = "overload" -version = "0.1.1" +name = "revm-bytecode" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +checksum = "74d1e5c1eaa44d39d537f668bc5c3409dc01e5c8be954da6c83370bbdf006457" +dependencies = [ + "bitvec", + "phf 0.13.1", + "revm-primitives", + "serde", +] [[package]] -name = "owo-colors" -version = "3.5.0" +name = "revm-context" +version = "13.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" - -[[package]] -name = "p2p2" -version = "1.3.0" +checksum = "892ff3e6a566cf8d72ffb627fdced3becebbd9ba64089c25975b9b028af326a5" dependencies = [ - "async-trait", - "borsh", - "figment", - "futures", - "futures-util", - "libp2p", - "parking_lot 0.12.1", + "bitvec", + "cfg-if", + "derive-where", + "revm-bytecode", + "revm-context-interface", + "revm-database-interface", + "revm-primitives", + "revm-state", "serde", - "serde_json", - "strum 0.26.3", - "thiserror", - "tokio", - "toml 0.8.2", - "tracing", - "tracing-subscriber", - "whitelist-ips", - "wire-message", ] [[package]] -name = "parity-scale-codec" -version = "3.6.5" +name = "revm-context-interface" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "57f61cc6d23678c4840af895b19f8acfbbd546142ec8028b6526c53cc1c16c98" dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", + "alloy-eip2930", + "alloy-eip7702", + "auto_impl", + "either", + "revm-database-interface", + "revm-primitives", + "revm-state", "serde", ] [[package]] -name = "parity-scale-codec-derive" -version = "3.6.5" +name = "revm-database" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "529528d0b05fe646be86223032c3e77aa8b05caa2a35447d538c55965956a511" dependencies = [ - "proc-macro-crate 1.1.3", - "proc-macro2", - "quote", - "syn 1.0.109", + "alloy-eips", + "revm-bytecode", + "revm-database-interface", + "revm-primitives", + "revm-state", + "serde", ] [[package]] -name = "parking" -version = "2.2.0" +name = "revm-database-interface" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "b7bf93ac5b91347c057610c0d96e923db8c62807e03f036762d03e981feddc1d" +dependencies = [ + "auto_impl", + "either", + "revm-primitives", + "revm-state", + "serde", + "thiserror 2.0.17", +] [[package]] -name = "parking_lot" -version = "0.11.2" +name = "revm-handler" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +checksum = "0cd0e43e815a85eded249df886c4badec869195e70cdd808a13cfca2794622d2" dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", + "auto_impl", + "derive-where", + "revm-bytecode", + "revm-context", + "revm-context-interface", + "revm-database-interface", + "revm-interpreter", + "revm-precompile", + "revm-primitives", + "revm-state", + "serde", ] [[package]] -name = "parking_lot" -version = "0.12.1" +name = "revm-inspector" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "4f3ccad59db91ef93696536a0dbaf2f6f17cfe20d4d8843ae118edb7e97947ef" dependencies = [ - "lock_api", - "parking_lot_core 0.9.9", + "auto_impl", + "either", + "revm-context", + "revm-database-interface", + "revm-handler", + "revm-interpreter", + "revm-primitives", + "revm-state", + "serde", + "serde_json", ] [[package]] -name = "parking_lot_core" -version = "0.8.6" +name = "revm-inspectors" +version = "0.34.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +checksum = "6e435414e9de50a1b930da602067c76365fea2fea11e80ceb50783c94ddd127f" dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", + "alloy-primitives", + "alloy-rpc-types-eth", + "alloy-rpc-types-trace", + "alloy-sol-types", + "anstyle", + "colorchoice", + "revm", + "serde", + "serde_json", + "thiserror 2.0.17", ] [[package]] -name = "parking_lot_core" -version = "0.9.9" +name = "revm-interpreter" +version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "11406408597bc249392d39295831c4b641b3a6f5c471a7c41104a7a1e3564c07" dependencies = [ - "backtrace", - "cfg-if 1.0.0", - "libc", - "petgraph", - "redox_syscall 0.4.1", - "smallvec", - "thread-id", - "windows-targets 0.48.5", + "revm-bytecode", + "revm-context-interface", + "revm-primitives", + "revm-state", + "serde", ] [[package]] -name = "pasta_curves" -version = "0.4.1" +name = "revm-precompile" +version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc65faf8e7313b4b1fbaa9f7ca917a0eed499a9663be71477f87993604341d8" +checksum = "50c1285c848d240678bf69cb0f6179ff5a4aee6fc8e921d89708087197a0aff3" dependencies = [ - "blake2b_simd", - "ff 0.12.1", - "group 0.12.1", - "lazy_static", - "rand 0.8.5", - "static_assertions", - "subtle", + "ark-bls12-381", + "ark-bn254", + "ark-ec", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "arrayref", + "aurora-engine-modexp", + "blst", + "c-kzg", + "cfg-if", + "k256", + "p256", + "revm-primitives", + "ripemd", + "secp256k1 0.31.1", + "sha2", ] [[package]] -name = "pasta_curves" -version = "0.5.1" +name = "revm-primitives" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +checksum = "ba580c56a8ec824a64f8a1683577876c2e1dbe5247044199e9b881421ad5dcf9" dependencies = [ - "blake2b_simd", - "ff 0.13.0", - "group 0.13.0", - "lazy_static", - "rand 0.8.5", - "static_assertions", - "subtle", + "alloy-primitives", + "num_enum", + "once_cell", + "serde", ] [[package]] -name = "paste" -version = "1.0.14" +name = "revm-state" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "311720d4f0f239b041375e7ddafdbd20032a33b7bae718562ea188e188ed9fd3" +dependencies = [ + "alloy-eip7928", + "bitflags 2.10.0", + "revm-bytecode", + "revm-primitives", + "serde", +] [[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +name = "rewards" +version = "0.1.0" dependencies = [ - "digest 0.10.7", + "async-trait", + "chrono", + "contextful", + "rewards-interface", + "rewards-storage-interface", + "serde_json", + "thiserror 1.0.69", + "tokio", + "unimock", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +name = "rewards-interface" +version = "0.1.0" dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", + "async-trait", + "chrono", + "contextful", + "database", + "diesel", + "rand 0.8.5", + "rpc", + "serde", + "serde_json", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "pear" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a386cd715229d399604b50d1361683fe687066f42d56f54be995bc6868f71c" +name = "rewards-rpc" +version = "0.1.0" dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", + "actix-web", + "async-trait", + "chrono", + "contextful", + "element", + "json-with-logging", + "rewards-interface", + "rpc", + "serde", + "serde_json", + "thiserror 1.0.69", + "tracing", + "uuid 1.19.0", + "workspace-hack", + "zk-circuits", + "zk-primitives", ] [[package]] -name = "pear_codegen" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f0f13dac8069c139e8300a6510e3f4143ecf5259c60b116a9b271b4ca0d54" +name = "rewards-storage-interface" +version = "0.1.0" dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.40", + "async-trait", + "rewards-interface", + "serde_json", + "unimock", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +name = "rewards-storage-pg" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "database", + "diesel", + "diesel-async", + "kyc", + "rewards-interface", + "rewards-storage-interface", + "serde_json", + "thiserror 1.0.69", + "uuid 1.19.0", + "workspace-hack", +] [[package]] -name = "pem" -version = "1.1.1" +name = "rfc6979" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" dependencies = [ - "base64 0.13.1", + "hmac", + "subtle", ] [[package]] -name = "percent-encoding" -version = "2.3.0" +name = "ring" +version = "0.16.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted 0.7.1", + "web-sys", + "winapi", +] [[package]] -name = "pest" -version = "2.7.5" +name = "ring" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ - "memchr", - "thiserror", - "ucd-trie", + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted 0.9.0", + "windows-sys 0.52.0", ] [[package]] -name = "petgraph" -version = "0.6.4" +name = "ringbuffer" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap 2.0.2", -] +checksum = "3df6368f71f205ff9c33c076d170dd56ebf68e8161c733c0caa07a7a5509ed53" [[package]] -name = "pharos" -version = "0.5.3" +name = "ripemd" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "futures", - "rustc_version 0.4.0", + "digest 0.10.7", ] [[package]] -name = "phf" -version = "0.11.2" +name = "rlimit" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "7043b63bd0cd1aaa628e476b80e6d4023a3b50eb32789f2728908107bd0c793a" dependencies = [ - "phf_shared", + "libc", ] [[package]] -name = "phf_shared" -version = "0.11.2" +name = "rlp" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ - "siphasher", + "bytes", + "rlp-derive", + "rustc-hex", ] [[package]] -name = "pin-project" -version = "1.1.3" +name = "rlp" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3" dependencies = [ - "pin-project-internal", + "bytes", + "rustc-hex", ] [[package]] -name = "pin-project-internal" -version = "1.1.3" +name = "rlp-derive" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 1.0.109", ] [[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.10.2" +name = "rmp" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" dependencies = [ - "der 0.7.8", - "spki", + "num-traits", ] [[package]] -name = "pkg-config" -version = "0.3.27" +name = "rmp-serde" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" +dependencies = [ + "rmp", + "serde", +] [[package]] -name = "platforms" -version = "3.2.0" +name = "roaring" +version = "0.10.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "19e8d2cfa184d94d0726d650a9f4a1be7f9b76ac9fdb954219878dc00c1c1e7b" +dependencies = [ + "bytemuck", + "byteorder", +] [[package]] -name = "polling" -version = "3.3.1" +name = "rocksdb" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" +checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" dependencies = [ - "cfg-if 1.0.0", - "concurrent-queue", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.52.0", + "libc", + "librocksdb-sys", ] [[package]] -name = "poly1305" -version = "0.8.0" +name = "rolling-file" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +checksum = "8395b4f860856b740f20a296ea2cd4d823e81a2658cf05ef61be22916026a906" dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", + "chrono", ] [[package]] -name = "polyval" -version = "0.6.1" +name = "route-recognizer" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "opaque-debug", - "universal-hash", -] +checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] -name = "poseidon" -version = "0.2.0" -source = "git+https://github.com/scroll-tech/poseidon.git?branch=scroll-dev-0220#2fb4a2385bada39b50dce12fe50cb80d2fd33476" +name = "rpc" +version = "1.3.0" dependencies = [ - "group 0.12.1", - "halo2curves 0.3.1", - "subtle", + "actix-web", + "chrono", + "clap", + "contextful", + "eyre", + "futures-util", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry_sdk", + "rpc-error-convert", + "sentry", + "sentry-tracing", + "serde", + "serde_json", + "strum 0.27.2", + "strum_macros 0.27.2", + "thiserror 1.0.69", + "tokio", + "tracing", + "tracing-opentelemetry", + "tracing-stackdriver", + "tracing-subscriber 0.3.22", + "workspace-hack", ] [[package]] -name = "poseidon-circuit" +name = "rpc-error-convert" version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit?branch=main#69524f42bdc55c581088c2fe64c2ab9a2921146b" dependencies = [ - "bitvec", - "halo2_proofs 0.2.0", - "lazy_static", - "log", - "rand 0.8.5", - "rand_xorshift", - "thiserror", + "proc-macro2", + "quote", + "serde_json", + "syn 2.0.112", + "workspace-hack", ] [[package]] -name = "poseidon-circuit" -version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git?branch=scroll-dev-0901#69524f42bdc55c581088c2fe64c2ab9a2921146b" +name = "rsa" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ - "bitvec", - "halo2_proofs 0.2.0", - "lazy_static", - "log", - "rand 0.8.5", - "rand_xorshift", - "thiserror", + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "sha1", + "signature", + "spki", + "subtle", + "zeroize", ] [[package]] -name = "postgres-native-tls" -version = "0.5.0" +name = "rtnetlink" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d442770e2b1e244bb5eb03b31c79b65bb2568f413b899eaba850fa945a65954" +checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" dependencies = [ "futures", - "native-tls", + "log", + "netlink-packet-core", + "netlink-packet-route", + "netlink-packet-utils", + "netlink-proto", + "netlink-sys", + "nix 0.26.4", + "thiserror 1.0.69", "tokio", - "tokio-native-tls", - "tokio-postgres", ] [[package]] -name = "postgres-protocol" -version = "0.6.7" +name = "ruint" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23" +checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" dependencies = [ - "base64 0.22.1", - "byteorder", + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "ark-ff 0.5.0", "bytes", - "fallible-iterator", - "hmac 0.12.1", - "md-5", - "memchr", + "fastrlp 0.3.1", + "fastrlp 0.4.0", + "num-bigint", + "num-integer", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", "rand 0.8.5", - "sha2 0.10.8", - "stringprep", + "rand 0.9.2", + "rlp 0.5.2", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", ] [[package]] -name = "postgres-types" -version = "0.2.8" +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rust-embed" +version = "8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66ea23a2d0e5734297357705193335e0a957696f34bed2f2faefacb2fec336f" +checksum = "947d7f3fad52b283d261c4c99a084937e2fe492248cb9a68a8435a861b8798ca" dependencies = [ - "bytes", - "fallible-iterator", - "postgres-protocol", + "rust-embed-impl", + "rust-embed-utils", + "walkdir", ] [[package]] -name = "powerfmt" -version = "0.2.0" +name = "rust-embed-impl" +version = "8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "5fa2c8c9e8711e10f9c4fd2d64317ef13feaab820a4c51541f1a8c8e2e851ab2" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.112", + "walkdir", +] [[package]] -name = "ppv-lite86" -version = "0.2.17" +name = "rust-embed-utils" +version = "8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "60b161f275cb337fe0a44d924a5f4df0ed69c2c39519858f931ce61c779d3475" +dependencies = [ + "sha2", + "walkdir", +] [[package]] -name = "pq-sys" -version = "0.4.8" +name = "rust-i18n" +version = "3.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0052426df997c0cbd30789eb44ca097e3541717a7b8fa36b1c464ee7edebd" +checksum = "fda2551fdfaf6cc5ee283adc15e157047b92ae6535cf80f6d4962d05717dc332" dependencies = [ - "vcpkg", + "globwalk", + "once_cell", + "regex", + "rust-i18n-macro", + "rust-i18n-support", + "smallvec", ] [[package]] -name = "prettyplease" -version = "0.2.15" +name = "rust-i18n-macro" +version = "3.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "22baf7d7f56656d23ebe24f6bb57a5d40d2bce2a5f1c503e692b5b2fa450f965" dependencies = [ + "glob", + "once_cell", "proc-macro2", - "syn 2.0.40", + "quote", + "rust-i18n-support", + "serde", + "serde_json", + "serde_yaml", + "syn 2.0.112", ] [[package]] -name = "primitive-types" -version = "0.12.2" +name = "rust-i18n-support" +version = "3.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +checksum = "940ed4f52bba4c0152056d771e563b7133ad9607d4384af016a134b58d758f19" dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", + "arc-swap", + "base62", + "globwalk", + "itertools 0.11.0", + "lazy_static", + "normpath", + "once_cell", + "proc-macro2", + "regex", + "serde", + "serde_json", + "serde_yaml", + "siphasher 1.0.1", + "toml 0.8.23", + "triomphe", ] [[package]] -name = "primitives" +name = "rustbridge" version = "1.3.0" dependencies = [ - "async-trait", - "base64 0.21.5", - "borsh", + "barretenberg-cli", + "barretenberg-rs", + "base64 0.22.1", "chrono", - "hex", - "microtype", - "parking_lot 0.12.1", - "rand 0.8.5", - "rand_derive2", - "secp256k1 0.28.1", + "contextful", + "contracts", + "element", + "eyre", + "flate2", + "hash", + "hash-poseidon", + "lazy_static", + "num_cpus", + "openssl", + "parse-link", + "payy_core", + "payy_core_types", + "rayon", + "sentry", "serde", - "serde_bytes", "serde_json", - "sha2 0.10.8", - "sha3 0.10.8", + "thiserror 1.0.69", "tokio", "tracing", - "uint", - "web3", + "tracing-subscriber 0.3.22", + "ts-rs", + "uuid 1.19.0", + "wallet-core", + "wallet-mobile", + "workspace-hack", + "zk-circuits", + "zk-primitives", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +dependencies = [ + "rand 0.8.5", ] [[package]] -name = "proc-macro-crate" -version = "1.1.3" +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc-stable-hash" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "781442f29170c5c93b7185ad559492601acdc71d5bb0706f5868094f45cfcd08" + +[[package]] +name = "rustc_version" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ - "thiserror", - "toml 0.5.11", + "semver 0.11.0", ] [[package]] -name = "proc-macro-crate" -version = "3.1.0" +name = "rustc_version" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "toml_edit 0.21.0", + "semver 1.0.27", ] [[package]] -name = "proc-macro-error" -version = "1.0.4" +name = "rusticata-macros" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", + "nom", ] [[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +name = "rustix" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "proc-macro2", - "quote", - "version_check", + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] -name = "proc-macro2" -version = "1.0.69" +name = "rustix" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "unicode-ident", + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" +name = "rustls" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", - "version_check", - "yansi", + "log", + "ring 0.16.20", + "sct", + "webpki", ] [[package]] -name = "proc_macro2_helper" -version = "0.2.10" +name = "rustls" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79528bef70da112116feb5ecb6b64f1394e5360660d6474a760789ea07885501" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ - "proc-macro2", - "syn 2.0.40", + "log", + "ring 0.17.14", + "rustls-webpki 0.101.7", + "sct", ] [[package]] -name = "prometheus-client" -version = "0.19.0" +name = "rustls" +version = "0.23.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" dependencies = [ - "dtoa", - "itoa", - "parking_lot 0.12.1", - "prometheus-client-derive-encode", + "aws-lc-rs", + "log", + "once_cell", + "ring 0.17.14", + "rustls-pki-types", + "rustls-webpki 0.103.8", + "subtle", + "zeroize", ] [[package]] -name = "prometheus-client-derive-encode" -version = "0.4.2" +name = "rustls-native-certs" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "openssl-probe 0.2.0", + "rustls-pki-types", + "schannel", + "security-framework 3.5.1", ] [[package]] -name = "proptest" -version = "1.3.1" +name = "rustls-pemfile" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c003ac8c77cb07bb74f5f198bce836a689bcd5a42574612bf14d17bfd08c20e" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.4.1", - "lazy_static", - "num-traits", - "rand 0.8.5", - "rand_chacha", - "rand_xorshift", - "regex-syntax 0.7.5", - "rusty-fork", - "tempfile", - "unarray", + "base64 0.21.7", ] [[package]] -name = "prost" -version = "0.11.9" +name = "rustls-pemfile" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "bytes", - "prost-derive", + "rustls-pki-types", ] [[package]] -name = "prost-derive" -version = "0.11.9" +name = "rustls-pki-types" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", + "web-time", + "zeroize", ] [[package]] -name = "prover" -version = "1.3.0" +name = "rustls-platform-verifier" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" dependencies = [ - "borsh", - "contracts", - "ethereum-types", - "expect-test", - "lazy_static", - "parking_lot 0.12.1", - "primitives", - "rand 0.8.5", - "rustc-hex", - "secp256k1 0.28.1", - "serde_json", - "smirk", - "thiserror", - "tokio", - "tokio-postgres", - "tracing", - "web3", - "zk-circuits", + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.35", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.8", + "security-framework 3.5.1", + "security-framework-sys", + "webpki-root-certs 0.26.11", + "windows-sys 0.59.0", ] [[package]] -name = "quick-error" -version = "1.2.3" +name = "rustls-platform-verifier-android" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] -name = "quick-protobuf" -version = "0.8.1" +name = "rustls-webpki" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6da84cc204722a989e01ba2f6e1e276e190f22263d0cb6ce8526fcdb0d2e1f" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "byteorder", + "ring 0.17.14", + "untrusted 0.9.0", ] [[package]] -name = "quick-protobuf-codec" -version = "0.1.0" +name = "rustls-webpki" +version = "0.103.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1693116345026436eb2f10b677806169c1a1260c1c60eaaffe3fb5a29ae23d8b" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" dependencies = [ - "asynchronous-codec", - "bytes", - "quick-protobuf", - "thiserror", - "unsigned-varint", + "aws-lc-rs", + "ring 0.17.14", + "rustls-pki-types", + "untrusted 0.9.0", ] [[package]] -name = "quinn-proto" -version = "0.9.6" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" -dependencies = [ - "bytes", - "rand 0.8.5", - "ring 0.16.20", - "rustc-hash", - "rustls 0.20.9", - "slab", - "thiserror", - "tinyvec", - "tracing", - "webpki", -] +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] -name = "quote" -version = "1.0.33" +name = "rusty-fork" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" dependencies = [ - "proc-macro2", + "fnv", + "quick-error", + "tempfile", + "wait-timeout", ] [[package]] -name = "r2d2" -version = "0.8.10" +name = "rw-stream-sink" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" dependencies = [ - "log", - "parking_lot 0.12.1", - "scheduled-thread-pool", + "futures", + "pin-project", + "static_assertions", ] [[package]] -name = "radium" -version = "0.7.0" +name = "ryu" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] -name = "rand" -version = "0.4.6" +name = "safe-proc-macro2" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +checksum = "492d1a72624b0bd5b7f0193ea5834a1905534a517573a117e949e895f342906c" dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", + "unicode-xid", ] [[package]] -name = "rand" -version = "0.8.5" +name = "safe-quote" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "bcaa9a650f2f98ba4da0190623210c85945cb78b262709f606c57655eda173e1" dependencies = [ - "libc", - "rand_chacha", - "rand_core 0.6.4", + "safe-proc-macro2", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "safe-regex" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "5194fafa3cb9da89e0cab6dffa1f3fdded586bd6396d12be11b4cae0c7ee45c2" dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", + "safe-regex-macro", ] [[package]] -name = "rand_core" -version = "0.3.1" +name = "safe-regex-compiler" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "e822ae1e61251bcfd698317c237cf83f7c57161a5dc24ee609a85697f1ed15b3" dependencies = [ - "rand_core 0.4.2", + "safe-proc-macro2", + "safe-quote", ] [[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rand_core" -version = "0.5.1" +name = "safe-regex-macro" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "2768de7e6ef19f59c5fd3c3ac207ef12b68a49f95e3172d67e4a04cfd992ca06" dependencies = [ - "getrandom 0.1.16", + "safe-proc-macro2", + "safe-regex-compiler", ] [[package]] -name = "rand_core" -version = "0.6.4" +name = "salsa20" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" dependencies = [ - "getrandom 0.2.11", + "cipher", ] [[package]] -name = "rand_derive2" -version = "0.1.21" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e07d80c051ce2007c5cbb87ae0a6be7c5e5345cb03e06717b64ed5c426cbfb3" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "proc-macro2", - "proc_macro2_helper", - "quote", - "syn 2.0.40", + "winapi-util", ] [[package]] -name = "rand_xorshift" -version = "0.3.0" +name = "scale-info" +version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" dependencies = [ - "rand_core 0.6.4", + "cfg-if", + "derive_more 1.0.0", + "parity-scale-codec", + "scale-info-derive", ] [[package]] -name = "rayon" -version = "1.8.0" +name = "scale-info-derive" +version = "2.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" dependencies = [ - "either", - "rayon-core", + "proc-macro-crate 3.4.0", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "rayon-core" -version = "1.12.0" +name = "scc" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" dependencies = [ - "crossbeam-deque", - "crossbeam-utils", + "sdd", ] [[package]] -name = "rcgen" -version = "0.10.0" +name = "schannel" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "pem", - "ring 0.16.20", - "time", - "yasna", + "windows-sys 0.61.2", ] [[package]] -name = "rdrand" -version = "0.4.0" +name = "schemars" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" dependencies = [ - "rand_core 0.3.1", + "dyn-clone", + "ref-cast", + "serde", + "serde_json", ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "schemars" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" dependencies = [ - "bitflags 1.3.2", + "dyn-clone", + "ref-cast", + "serde", + "serde_json", ] [[package]] -name = "redox_syscall" -version = "0.4.1" +name = "schnellru" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "356285bbf17bea63d9e52e96bd18f039672ac92b55b8cb997d6162a2a37d1649" dependencies = [ - "bitflags 1.3.2", + "ahash", + "cfg-if", + "hashbrown 0.13.2", ] [[package]] -name = "redox_syscall" -version = "0.5.7" +name = "scoped-futures" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "1b24aae2d0636530f359e9d5ef0c04669d11c5e756699b27a6a6d845d8329091" dependencies = [ - "bitflags 2.4.1", + "pin-project-lite", ] [[package]] -name = "redox_users" -version = "0.4.4" +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "getrandom 0.2.11", - "libredox", - "thiserror", + "ring 0.17.14", + "untrusted 0.9.0", ] [[package]] -name = "regex" -version = "1.10.2" +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + +[[package]] +name = "sec1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", + "base16ct", + "der", + "generic-array", + "pkcs8", + "serdect", + "subtle", + "zeroize", ] [[package]] -name = "regex-automata" -version = "0.1.10" +name = "secp256k1" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" dependencies = [ - "regex-syntax 0.6.29", + "secp256k1-sys 0.8.2", ] [[package]] -name = "regex-automata" -version = "0.4.3" +name = "secp256k1" +version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.2", + "rand 0.8.5", + "secp256k1-sys 0.9.2", ] [[package]] -name = "regex-syntax" -version = "0.6.29" +name = "secp256k1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes", + "rand 0.8.5", + "secp256k1-sys 0.10.1", + "serde", +] [[package]] -name = "regex-syntax" -version = "0.7.5" +name = "secp256k1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "2c3c81b43dc2d8877c216a3fccf76677ee1ebccd429566d3e67447290d0c42b2" +dependencies = [ + "bitcoin_hashes", + "rand 0.9.2", + "secp256k1-sys 0.11.0", +] [[package]] -name = "regex-syntax" +name = "secp256k1-sys" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" +dependencies = [ + "cc", +] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "secp256k1-sys" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" dependencies = [ - "winapi", + "cc", ] [[package]] -name = "reqwest" -version = "0.11.22" +name = "secp256k1-sys" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" dependencies = [ - "base64 0.21.5", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "mime_guess", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.9", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.25.3", - "winreg", + "cc", ] [[package]] -name = "resolv-conf" -version = "0.7.0" +name = "secp256k1-sys" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +checksum = "dcb913707158fadaf0d8702c2db0e857de66eb003ccfdda5924b5f5ac98efb38" dependencies = [ - "hostname", - "quick-error", + "cc", ] [[package]] -name = "revm" -version = "2.3.1" +name = "secrecy" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73d84c8f9836efb0f5f5f8de4700a953c4e1f3119e5cfcb0aad8e5be73daf991" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" dependencies = [ - "arrayref", - "auto_impl", - "bytes", - "hashbrown 0.13.2", - "num_enum 0.5.11", - "primitive-types", - "revm_precompiles", - "rlp", - "sha3 0.10.8", + "zeroize", ] [[package]] -name = "revm-precompile" -version = "2.0.0" -source = "git+https://github.com/scroll-tech/revm?branch=scroll-fix#aebf2e591e622e6bcce2c5d4bf3336935a68cf11" +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "k256 0.11.6", - "num", - "once_cell", - "revm-primitives", - "ripemd", - "secp256k1 0.26.0", - "sha2 0.10.8", - "sha3 0.10.8", - "substrate-bn", + "bitflags 2.10.0", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", ] [[package]] -name = "revm-primitives" -version = "1.0.0" -source = "git+https://github.com/scroll-tech/revm?branch=scroll-fix#aebf2e591e622e6bcce2c5d4bf3336935a68cf11" +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" dependencies = [ - "auto_impl", - "bytes", - "derive_more", - "enumn", - "fixed-hash", - "hashbrown 0.13.2", - "hex", - "hex-literal", - "rlp", - "ruint", - "sha3 0.10.8", + "bitflags 2.10.0", + "core-foundation 0.10.1", + "core-foundation-sys", + "libc", + "security-framework-sys", ] [[package]] -name = "revm_precompiles" -version = "1.1.2" +name = "security-framework-sys" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0353d456ef3e989dc9190f42c6020f09bc2025930c37895826029304413204b5" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ - "bytes", - "hashbrown 0.13.2", - "num", - "once_cell", - "primitive-types", - "ripemd", - "secp256k1 0.24.3", - "sha2 0.10.8", - "sha3 0.10.8", - "substrate-bn", + "core-foundation-sys", + "libc", ] [[package]] -name = "rfc6979" -version = "0.3.1" +name = "semver" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "crypto-bigint 0.4.9", - "hmac 0.12.1", - "zeroize", + "semver-parser", ] [[package]] -name = "rfc6979" -version = "0.4.0" +name = "semver" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ - "hmac 0.12.1", - "subtle", + "serde", + "serde_core", ] [[package]] -name = "ring" -version = "0.16.20" +name = "semver-parser" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "9900206b54a3527fdc7b8a938bffd94a568bac4f4aa8113b209df75a09c0dec2" dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", + "pest", ] [[package]] -name = "ring" -version = "0.17.5" +name = "send_wrapper" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" -dependencies = [ - "cc", - "getrandom 0.2.11", - "libc", - "spin 0.9.8", - "untrusted 0.9.0", - "windows-sys 0.48.0", -] +checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" [[package]] -name = "ripemd" -version = "0.1.3" +name = "send_wrapper" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + +[[package]] +name = "sentry" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9794f69ad475e76c057e326175d3088509649e3aed98473106b9fe94ba59424" dependencies = [ - "digest 0.10.7", + "httpdate", + "native-tls", + "reqwest 0.12.28", + "sentry-actix", + "sentry-backtrace", + "sentry-contexts", + "sentry-core", + "sentry-debug-images", + "sentry-panic", + "sentry-tracing", + "tokio", + "ureq", ] [[package]] -name = "rlp" -version = "0.5.2" +name = "sentry-actix" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +checksum = "e0fee202934063ace4f1d1d063113b8982293762628e563a2d2fba08fb20b110" dependencies = [ + "actix-http", + "actix-web", "bytes", - "rlp-derive", - "rustc-hex", + "futures-util", + "sentry-core", ] [[package]] -name = "rlp-derive" -version = "0.1.0" +name = "sentry-backtrace" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +checksum = "5f8784d0a27b5cd4b5f75769ffc84f0b7580e3c35e1af9cd83cb90b612d769cc" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "backtrace", + "regex", + "sentry-core", ] [[package]] -name = "rocksdb" -version = "0.21.0" +name = "sentry-contexts" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6f170a4041d50a0ce04b0d2e14916d6ca863ea2e422689a5b694395d299ffe" +checksum = "cfb403c66cc2651a01b9bacda2e7c22cd51f7e8f56f206aa4310147eb3259282" dependencies = [ + "hostname", "libc", - "librocksdb-sys", + "os_info", + "rustc_version 0.4.1", + "sentry-core", + "uname", ] [[package]] -name = "rpc" -version = "1.3.0" +name = "sentry-core" +version = "0.46.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b1e7ca40f965db239da279bf278d87b7407469b98835f27f0c8e59ed189b06" dependencies = [ - "actix-cors", - "actix-server", - "actix-web", - "base64 0.21.5", - "chrono", - "clap", - "derive_more", - "eyre", - "futures", - "futures-util", - "hex", - "lazy_static", - "opentelemetry", - "opentelemetry-otlp", - "opentelemetry_sdk", - "prover", - "sentry", - "sentry-tracing", + "rand 0.9.2", + "sentry-types", "serde", "serde_json", - "tokio", - "tracing", - "tracing-opentelemetry", - "tracing-stackdriver", - "tracing-subscriber", - "zk-circuits", + "url", ] [[package]] -name = "rtnetlink" -version = "0.10.1" +name = "sentry-debug-images" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322c53fd76a18698f1c27381d58091de3a043d356aa5bd0d510608b565f469a0" +checksum = "06a2778a222fd90ebb01027c341a72f8e24b0c604c6126504a4fe34e5500e646" dependencies = [ - "futures", - "log", - "netlink-packet-route", - "netlink-proto", - "nix 0.24.3", - "thiserror", - "tokio", + "findshlibs", + "sentry-core", ] [[package]] -name = "ruint" -version = "1.11.1" +name = "sentry-panic" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" +checksum = "3df79f4e1e72b2a8b75a0ebf49e78709ceb9b3f0b451f13adc92a0361b0aaabe" dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp", - "num-bigint", - "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", - "rand 0.8.5", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", + "sentry-backtrace", + "sentry-core", ] [[package]] -name = "ruint-macro" -version = "1.1.0" +name = "sentry-tracing" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" +checksum = "5b07eefe04486316c57aba08ab53dd44753c25102d1d3fe05775cc93a13262d9" +dependencies = [ + "bitflags 2.10.0", + "sentry-backtrace", + "sentry-core", + "tracing-core", + "tracing-subscriber 0.3.22", +] [[package]] -name = "rustc-demangle" -version = "0.1.23" +name = "sentry-types" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "567711f01f86a842057e1fc17779eba33a336004227e1a1e7e6cc2599e22e259" +dependencies = [ + "debugid", + "hex", + "rand 0.9.2", + "serde", + "serde_json", + "thiserror 2.0.17", + "time", + "url", + "uuid 1.19.0", +] [[package]] -name = "rustc-hash" -version = "1.1.0" +name = "seq-macro" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" [[package]] -name = "rustc-hex" -version = "2.1.0" +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] [[package]] -name = "rustc_version" -version = "0.3.3" +name = "serde-big-array" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" dependencies = [ - "semver 0.11.0", + "serde", ] [[package]] -name = "rustc_version" -version = "0.4.0" +name = "serde_arrays" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "38636132857f68ec3d5f3eb121166d2af33cb55174c4d5ff645db6165cbef0fd" dependencies = [ - "semver 1.0.20", + "serde", ] [[package]] -name = "rusticata-macros" -version = "4.1.0" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "nom", + "serde_derive", ] [[package]] -name = "rustix" -version = "0.38.21" +name = "serde_derive" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "rustls" -version = "0.20.9" +name = "serde_json" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ - "log", - "ring 0.16.20", - "sct", - "webpki", + "indexmap 2.13.0", + "itoa 1.0.17", + "memchr", + "serde", + "serde_core", + "zmij", ] [[package]] -name = "rustls" -version = "0.21.9" +name = "serde_path_to_error" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ - "log", - "ring 0.17.5", - "rustls-webpki 0.101.7", - "sct", + "itoa 1.0.17", + "serde", + "serde_core", ] [[package]] -name = "rustls-pemfile" -version = "1.0.4" +name = "serde_plain" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" dependencies = [ - "base64 0.21.5", + "serde", ] [[package]] -name = "rustls-webpki" -version = "0.100.3" +name = "serde_qs" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6a5fc258f1c1276dfe3016516945546e2d5383911efc0fc4f1cdc5df3a4ae3" +checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "percent-encoding", + "serde", + "thiserror 1.0.69", ] [[package]] -name = "rustls-webpki" -version = "0.101.7" +name = "serde_qs" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "8cac3f1e2ca2fe333923a1ae72caca910b98ed0630bb35ef6f8c8517d6e81afa" dependencies = [ - "ring 0.17.5", - "untrusted 0.9.0", + "percent-encoding", + "serde", + "thiserror 1.0.69", ] [[package]] -name = "rustversion" -version = "1.0.14" +name = "serde_regex" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf" +dependencies = [ + "regex", + "serde", +] [[package]] -name = "rusty-fork" -version = "0.3.0" +name = "serde_spanned" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", + "serde", ] [[package]] -name = "rw-stream-sink" -version = "0.3.0" +name = "serde_spanned" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" dependencies = [ - "futures", - "pin-project", - "static_assertions", + "serde_core", ] [[package]] -name = "ryu" -version = "1.0.15" +name = "serde_urlencoded" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" +dependencies = [ + "dtoa 0.4.8", + "itoa 0.4.8", + "serde", + "url", +] [[package]] -name = "salsa20" -version = "0.10.2" +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "cipher", + "form_urlencoded", + "itoa 1.0.17", + "ryu", + "serde", ] [[package]] -name = "scale-info" -version = "2.10.0" +name = "serde_with" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ - "cfg-if 1.0.0", - "derive_more", - "parity-scale-codec", - "scale-info-derive", + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.13.0", + "schemars 0.9.0", + "schemars 1.2.0", + "serde_core", + "serde_json", + "serde_with_macros", + "time", ] [[package]] -name = "scale-info-derive" -version = "2.10.0" +name = "serde_with_macros" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ - "proc-macro-crate 1.1.3", + "darling 0.21.3", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.112", ] [[package]] -name = "schannel" -version = "0.1.22" +name = "serde_yaml" +version = "0.9.36" +dependencies = [ + "serde_yaml_ng", + "workspace-hack", +] + +[[package]] +name = "serde_yaml_ng" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f" dependencies = [ - "windows-sys 0.48.0", + "indexmap 2.13.0", + "itoa 1.0.17", + "ryu", + "serde", + "unsafe-libyaml", ] [[package]] -name = "scheduled-thread-pool" -version = "0.2.7" +name = "serdect" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ - "parking_lot 0.12.1", + "base16ct", + "serde", ] [[package]] -name = "scopeguard" -version = "1.2.0" +name = "serial_test" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +dependencies = [ + "fslock", + "futures", + "log", + "once_cell", + "parking_lot 0.12.5", + "scc", + "serial_test_derive", +] [[package]] -name = "scrypt" -version = "0.10.0" +name = "serial_test_derive" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ - "hmac 0.12.1", - "pbkdf2 0.11.0", - "salsa20", - "sha2 0.10.8", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "sct" -version = "0.7.1" +name = "sha-1" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" dependencies = [ - "ring 0.17.5", - "untrusted 0.9.0", + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", ] [[package]] -name = "sec1" -version = "0.3.0" +name = "sha1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", - "generic-array", - "subtle", - "zeroize", + "cfg-if", + "cpufeatures", + "digest 0.10.7", ] [[package]] -name = "sec1" -version = "0.7.3" +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "base16ct 0.2.0", - "der 0.7.8", - "generic-array", - "pkcs8", - "subtle", - "zeroize", + "cfg-if", + "cpufeatures", + "digest 0.10.7", ] [[package]] -name = "secp256k1" -version = "0.24.3" +name = "sha256" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +checksum = "f880fc8562bdeb709793f00eb42a2ad0e672c4f883bbe59122b926eca935c8f6" dependencies = [ - "secp256k1-sys 0.6.1", + "async-trait", + "bytes", + "hex", + "sha2", ] [[package]] -name = "secp256k1" -version = "0.26.0" +name = "sha3" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4124a35fe33ae14259c490fd70fa199a32b9ce9502f2ee6bc4f81ec06fa65894" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "secp256k1-sys 0.8.1", + "digest 0.10.7", + "keccak", ] [[package]] -name = "secp256k1" -version = "0.27.0" +name = "sha3-asm" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "b31139435f327c93c6038ed350ae4588e2c70a13d50599509fee6349967ba35a" dependencies = [ - "secp256k1-sys 0.8.1", + "cc", + "cfg-if", ] [[package]] -name = "secp256k1" -version = "0.28.1" +name = "sharded-slab" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f622567e3b4b38154fb8190bcf6b160d7a4301d70595a49195b48c116007a27" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ - "rand 0.8.5", - "secp256k1-sys 0.9.2", + "lazy_static", ] [[package]] -name = "secp256k1-sys" -version = "0.6.1" +name = "shared_child" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +checksum = "1e362d9935bc50f019969e2f9ecd66786612daae13e8f277be7bfb66e8bed3f7" dependencies = [ - "cc", + "libc", + "sigchld", + "windows-sys 0.60.2", ] [[package]] -name = "secp256k1-sys" -version = "0.8.1" +name = "shared_thread" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" -dependencies = [ - "cc", -] +checksum = "52b86057fcb5423f5018e331ac04623e32d6b5ce85e33300f92c79a1973928b0" [[package]] -name = "secp256k1-sys" -version = "0.9.2" +name = "shellexpand" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" dependencies = [ - "cc", + "dirs", ] [[package]] -name = "secrecy" -version = "0.8.0" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sigchld" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47106eded3c154e70176fc83df9737335c94ce22f821c32d17ed1db1f83badb1" dependencies = [ - "zeroize", + "libc", + "os_pipe", + "signal-hook", ] [[package]] -name = "security-framework" -version = "2.9.2" +name = "signal-hook" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", "libc", - "security-framework-sys", + "signal-hook-registry", ] [[package]] -name = "security-framework-sys" -version = "2.9.1" +name = "signal-hook-registry" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ - "core-foundation-sys", + "errno", "libc", ] [[package]] -name = "semver" -version = "0.11.0" +name = "signature" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ - "semver-parser", + "digest 0.10.7", + "rand_core 0.6.4", ] [[package]] -name = "semver" -version = "1.0.20" +name = "simd-adler32" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] -name = "semver-parser" -version = "0.10.2" +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + +[[package]] +name = "simple_asn1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ - "pest", + "num-bigint", + "num-traits", + "thiserror 2.0.17", + "time", ] [[package]] -name = "send_wrapper" -version = "0.4.0" +name = "siphasher" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] -name = "send_wrapper" -version = "0.6.0" +name = "siphasher" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] -name = "sentry" -version = "0.32.1" +name = "sized-chunks" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab18211f62fb890f27c9bb04861f76e4be35e4c2fcbfc2d98afa37aadebb16f1" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" dependencies = [ - "httpdate", - "native-tls", - "reqwest", - "sentry-backtrace", - "sentry-contexts", - "sentry-core", - "sentry-debug-images", - "sentry-panic", - "sentry-tracing", - "tokio", - "ureq", + "bitmaps", + "typenum", ] [[package]] -name = "sentry-backtrace" -version = "0.32.1" +name = "skeptic" +version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf018ff7d5ce5b23165a9cbfee60b270a55ae219bc9eebef2a3b6039356dd7e5" +checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" dependencies = [ - "backtrace", - "once_cell", - "regex", - "sentry-core", + "bytecount", + "cargo_metadata 0.14.2", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", ] [[package]] -name = "sentry-contexts" -version = "0.32.1" +name = "sketches-ddsketch" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d934df6f9a17b8c15b829860d9d6d39e78126b5b970b365ccbd817bc0fe82c9" +checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "slack-client-http" +version = "0.1.0" dependencies = [ - "hostname", - "libc", - "os_info", - "rustc_version 0.4.0", - "sentry-core", - "uname", + "async-trait", + "contextful", + "reqwest 0.12.28", + "slack-client-interface", + "workspace-hack", ] [[package]] -name = "sentry-core" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e362d3fb1c5de5124bf1681086eaca7adf6a8c4283a7e1545359c729f9128ff" +name = "slack-client-interface" +version = "0.1.0" dependencies = [ - "once_cell", - "rand 0.8.5", - "sentry-types", + "async-trait", + "contextful", "serde", - "serde_json", + "thiserror 1.0.69", + "unimock", + "workspace-hack", ] [[package]] -name = "sentry-debug-images" -version = "0.32.1" +name = "small-ord-set" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bca420d75d9e7a8e54a4806bf4fa8a7e9a804e8f2ff05c7c80234168c6ca66" +checksum = "cf7035a2b2268a5be8c1395738565b06beda836097e12021cdefc06b127a0e7e" dependencies = [ - "findshlibs", - "once_cell", - "sentry-core", + "smallvec", ] [[package]] -name = "sentry-panic" -version = "0.32.1" +name = "smallvec" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0224e7a8e2bd8a32d96804acb8243d6d6e073fed55618afbdabae8249a964d8" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ - "sentry-backtrace", - "sentry-core", + "serde", ] [[package]] -name = "sentry-tracing" -version = "0.32.1" +name = "smart-default" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "087bed8c616d176a9c6b662a8155e5f23b40dc9e1fa96d0bd5fb56e8636a9275" +checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6" dependencies = [ - "sentry-backtrace", - "sentry-core", - "tracing-core", - "tracing-subscriber", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "sentry-types" -version = "0.32.1" +name = "smartstring" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4f0e37945b7a8ce7faebc310af92442e2d7c5aa7ef5b42fe6daa98ee133f65" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" dependencies = [ - "debugid", - "hex", + "autocfg", + "static_assertions", + "version_check", +] + +[[package]] +name = "smirk" +version = "1.3.0" +dependencies = [ + "benchy", + "bitvec", + "borsh", + "dashmap 6.1.0", + "element", + "expect-test", + "hash", + "node-client-http", + "primitives", + "proptest", "rand 0.8.5", - "serde", + "rayon", + "reqwest 0.12.28", + "rocksdb", "serde_json", - "thiserror", - "time", - "url", - "uuid 1.7.0", + "strum 0.27.2", + "tempdir", + "test-strategy", + "thiserror 1.0.69", + "tokio", + "tracing", + "wire-message", + "workspace-hack", ] [[package]] -name = "serde" -version = "1.0.193" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +name = "smirk-cli" +version = "1.3.0" dependencies = [ - "serde_derive", + "clap", + "contextful", + "element", + "prover", + "smirk", + "thiserror 1.0.69", + "tracing-subscriber 0.3.22", + "workspace-hack", ] [[package]] -name = "serde_bytes" -version = "0.11.15" +name = "smol_str" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" dependencies = [ "serde", ] [[package]] -name = "serde_derive" -version = "1.0.193" +name = "smol_str" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "3498b0a27f93ef1402f20eefacfaa1691272ac4eca1cdc8c596cb0a245d6cbf5" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "borsh", + "serde_core", ] [[package]] -name = "serde_json" -version = "1.0.108" +name = "snafu" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6" dependencies = [ - "itoa", - "ryu", - "serde", + "doc-comment", + "snafu-derive", ] [[package]] -name = "serde_spanned" -version = "0.6.4" +name = "snafu-derive" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" dependencies = [ - "serde", + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "snap" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" + +[[package]] +name = "snow" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "850948bee068e713b8ab860fe1adc4d109676ab4c3b621fd8147f06b261f2f85" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", + "aes-gcm", + "blake2", + "chacha20poly1305", + "curve25519-dalek 4.1.3", + "rand_core 0.6.4", + "ring 0.17.14", + "rustc_version 0.4.1", + "sha2", + "subtle", ] [[package]] -name = "serde_with" -version = "1.14.0" +name = "socket2" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ - "serde", - "serde_with_macros", + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", ] [[package]] -name = "serde_with_macros" -version = "1.5.2" +name = "socket2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 1.0.109", + "libc", + "windows-sys 0.60.2", ] [[package]] -name = "serial_test" -version = "3.0.0" +name = "soketto" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ad9342b3aaca7cb43c45c097dd008d4907070394bd0751a0aa8817e5a018d" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ - "dashmap", + "base64 0.13.1", + "bytes", "futures", - "lazy_static", + "httparse", "log", - "parking_lot 0.12.1", - "serial_test_derive", + "rand 0.8.5", + "sha-1", ] [[package]] -name = "serial_test_derive" -version = "3.0.0" +name = "soketto" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212" +checksum = "2e859df029d160cb88608f5d7df7fb4753fd20fdfb4de5644f3d8b8440841721" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "base64 0.22.1", + "bytes", + "futures", + "http 1.4.0", + "httparse", + "log", + "rand 0.8.5", + "sha1", ] [[package]] -name = "sha-1" -version = "0.9.8" +name = "solang-parser" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "itertools 0.11.0", + "lalrpop", + "lalrpop-util", + "phf 0.11.3", + "thiserror 1.0.69", + "unicode-xid", ] [[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +name = "solc-tooling" +version = "0.1.0" dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.7", + "contextful", + "hex", + "home", + "reqwest 0.12.28", + "sha2", + "thiserror 1.0.69", + "workspace-hack", ] [[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +name = "solid" +version = "1.3.0" dependencies = [ - "block-buffer 0.9.0", - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", + "borsh", + "bs58 0.5.1", + "chrono", + "futures", + "hex", + "parking_lot 0.12.5", + "proptest", + "quickcheck", + "rand 0.8.5", + "sha2", + "sha3", + "test-strategy", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tracing", + "tracing-subscriber 0.3.22", + "uint 0.10.0", + "workspace-hack", ] [[package]] -name = "sha2" -version = "0.10.8" +name = "sorted-iter" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest 0.10.7", -] +checksum = "bceb57dc07c92cdae60f5b27b3fa92ecaaa42fe36c55e22dbfb0b44893e0b1f7" [[package]] -name = "sha3" -version = "0.9.1" +name = "spin" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", -] +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "sha3" -version = "0.10.8" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "sharded-slab" -version = "0.1.7" +name = "spki" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ - "lazy_static", + "base64ct", + "der", ] [[package]] -name = "shlex" -version = "1.2.0" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "signal-hook-registry" -version = "1.4.1" +name = "stacker" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "e1f8b29fb42aafcea4edeeb6b2f2d7ecd0d969c48b4cf0d2e64aafc471dd6e59" dependencies = [ + "cc", + "cfg-if", "libc", + "psm", + "windows-sys 0.59.0", ] [[package]] -name = "signature" -version = "1.6.4" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "signature" -version = "2.2.0" +name = "string_cache" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", + "new_debug_unreachable", + "parking_lot 0.12.5", + "phf_shared 0.11.3", + "precomputed-hash", ] [[package]] -name = "similar" -version = "2.3.0" +name = "string_enum" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597" +checksum = "ae36a4951ca7bd1cfd991c241584a9824a70f6aff1e7d4f693fb3f2465e4030e" +dependencies = [ + "quote", + "swc_macros_common", + "syn 2.0.112", +] [[package]] -name = "siphasher" -version = "0.3.11" +name = "stringmetrics" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "7b3c8667cd96245cbb600b8dec5680a7319edd719c5aa2b5d23c6bff94f39765" [[package]] -name = "slab" -version = "0.4.9" +name = "stringprep" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "autocfg", + "unicode-bidi", + "unicode-normalization", + "unicode-properties", ] [[package]] -name = "smallvec" -version = "1.13.2" +name = "strsim" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "smirk" -version = "1.3.0" +name = "structmeta" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ad9e09554f0456d67a69c1584c9798ba733a5b50349a6c0d0948710523922d" dependencies = [ - "benchy", - "bitvec", - "borsh", - "dashmap", - "ethnum", - "expect-test", - "ff 0.12.1", - "halo2_gadgets", - "halo2_proofs 0.3.0", - "halo2curves 0.1.0", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit?branch=main)", - "proptest", - "rand 0.8.5", - "rand_chacha", - "rayon", - "rocksdb", - "serde", - "serde_json", - "strum 0.26.3", - "tempdir", - "test-strategy", - "thiserror", - "tracing", - "wire-message", - "zk-primitives", + "proc-macro2", + "quote", + "structmeta-derive", + "syn 2.0.112", ] [[package]] -name = "smol_str" +name = "structmeta-derive" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" dependencies = [ - "serde", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "snark-verifier" -version = "0.1.0" -source = "git+https://github.com/scroll-tech/snark-verifier?tag=v0.1.5#bc1d39ae31f3fe520c51dd150f0fefaf9653c465" +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "bytes", - "ethereum-types", - "halo2-base", - "halo2-ecc", - "hex", - "itertools 0.10.5", - "lazy_static", - "num-bigint", - "num-integer", - "num-traits", - "poseidon", - "rand 0.8.5", - "revm", - "rlp", - "rustc-hash", - "serde", - "sha3 0.10.8", + "strum_macros 0.26.4", ] [[package]] -name = "snark-verifier-sdk" -version = "0.0.1" -source = "git+https://github.com/scroll-tech/snark-verifier?tag=v0.1.5#bc1d39ae31f3fe520c51dd150f0fefaf9653c465" +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ - "bincode", - "env_logger 0.10.0", - "ethereum-types", - "halo2-base", - "hex", - "itertools 0.10.5", - "lazy_static", - "log", - "num-bigint", - "num-integer", - "num-traits", - "rand 0.8.5", - "rand_chacha", - "serde", - "serde_json", - "snark-verifier", + "strum_macros 0.27.2", ] [[package]] -name = "snow" -version = "0.9.4" +name = "strum_macros" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58021967fd0a5eeeb23b08df6cc244a4d4a5b4aec1d27c9e02fad1a58b4cd74e" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "aes-gcm", - "blake2", - "chacha20poly1305", - "curve25519-dalek 4.1.1", - "rand_core 0.6.4", - "ring 0.17.5", - "rustc_version 0.4.0", - "sha2 0.10.8", - "subtle", + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.109", ] [[package]] -name = "socket2" -version = "0.4.10" +name = "strum_macros" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "libc", - "winapi", + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.112", ] [[package]] -name = "socket2" -version = "0.5.5" +name = "strum_macros" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "libc", - "windows-sys 0.48.0", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "sumsub-http" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "hex", + "hmac", + "reqwest 0.12.28", + "serde", + "serde_json", + "sha2", + "sumsub-interface", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "soketto" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" +name = "sumsub-interface" +version = "0.1.0" dependencies = [ - "base64 0.13.1", - "bytes", - "futures", - "httparse", - "log", - "rand 0.8.5", - "sha-1", + "async-trait", + "chrono", + "contextful", + "hmac", + "kyc", + "reqwest 0.12.28", + "serde", + "serde_json", + "strum 0.27.2", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +name = "sumsub-provider" +version = "0.1.0" +dependencies = [ + "async-trait", + "contextful", + "kyc", + "network", + "providers-interface", + "ramps-interface", + "serde", + "sumsub-http", + "sumsub-interface", + "thiserror 1.0.69", + "uuid 1.19.0", + "workspace-hack", +] [[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +name = "support" +version = "0.1.0" +dependencies = [ + "async-trait", + "base64 0.22.1", + "chrono", + "contextful", + "hex", + "mime", + "object_store", + "push-notification-interface", + "serde", + "serde_json", + "sha2", + "support-interface", + "support-storage-interface", + "thiserror 1.0.69", + "tokio", + "tracing", + "uuid 1.19.0", + "workspace-hack", +] [[package]] -name = "spki" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +name = "support-interface" +version = "0.1.0" dependencies = [ - "base64ct", - "der 0.7.8", + "async-trait", + "chrono", + "contextful", + "data", + "guild-interface", + "rpc", + "serde", + "serde_json", + "strum 0.27.2", + "thiserror 1.0.69", + "unimock", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +name = "support-rpc" +version = "0.1.0" +dependencies = [ + "actix-web", + "async-trait", + "chrono", + "json-with-logging", + "rpc", + "serde", + "serde_json", + "support-interface", + "thiserror 1.0.69", + "tokio", + "tracing", + "uuid 1.19.0", + "workspace-hack", +] [[package]] -name = "stringprep" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +name = "support-storage-interface" +version = "0.1.0" dependencies = [ - "unicode-bidi", - "unicode-normalization", - "unicode-properties", + "async-trait", + "chrono", + "serde_json", + "support-interface", + "unimock", + "uuid 1.19.0", + "workspace-hack", ] [[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +name = "support-storage-pg" +version = "0.1.0" +dependencies = [ + "async-trait", + "chrono", + "contextful", + "data", + "database", + "diesel", + "diesel-async", + "guild-interface", + "serde_json", + "support-interface", + "support-storage-interface", + "thiserror 1.0.69", + "uuid 1.19.0", + "workspace-hack", +] [[package]] -name = "structmeta" -version = "0.2.0" +name = "svm-rs" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ad9e09554f0456d67a69c1584c9798ba733a5b50349a6c0d0948710523922d" +checksum = "11297baafe5fa0c99d5722458eac6a5e25c01eb1b8e5cd137f54079093daa7a4" dependencies = [ - "proc-macro2", - "quote", - "structmeta-derive", - "syn 2.0.40", + "dirs", + "fs2", + "hex", + "once_cell", + "reqwest 0.11.27", + "semver 1.0.27", + "serde", + "serde_json", + "sha2", + "thiserror 1.0.69", + "url", + "zip", ] [[package]] -name = "structmeta-derive" -version = "0.2.0" +name = "swc_atoms" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" +checksum = "d4ccbe2ecad10ad7432100f878a107b1d972a8aee83ca53184d00c23a078bb8a" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", + "hstr", + "once_cell", + "serde", ] [[package]] -name = "strum" -version = "0.24.1" +name = "swc_common" +version = "17.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +checksum = "259b675d633a26d24efe3802a9d88858c918e6e8f062d3222d3aa02d56a2cf4c" dependencies = [ - "strum_macros 0.24.3", + "anyhow", + "ast_node", + "better_scoped_tls", + "bytes-str", + "either", + "from_variant", + "new_debug_unreachable", + "num-bigint", + "once_cell", + "rustc-hash 2.1.1", + "serde", + "siphasher 0.3.11", + "swc_atoms", + "swc_eq_ignore_macros", + "swc_visit", + "tracing", + "unicode-width 0.2.2", + "url", ] [[package]] -name = "strum" -version = "0.25.0" +name = "swc_ecma_ast" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "a573a0c72850dec8d4d8085f152d5778af35a2520c3093b242d2d1d50776da7c" dependencies = [ - "strum_macros 0.25.3", + "bitflags 2.10.0", + "is-macro", + "num-bigint", + "once_cell", + "phf 0.11.3", + "rustc-hash 2.1.1", + "serde", + "string_enum", + "swc_atoms", + "swc_common", + "swc_visit", + "unicode-id-start", ] [[package]] -name = "strum" -version = "0.26.3" +name = "swc_ecma_lexer" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "5e82f7747e052c6ff6e111fa4adeb14e33b46ee6e94fe5ef717601f651db48fc" +dependencies = [ + "bitflags 2.10.0", + "either", + "num-bigint", + "rustc-hash 2.1.1", + "seq-macro", + "serde", + "smallvec", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "swc_ecma_parser", + "tracing", +] [[package]] -name = "strum_macros" -version = "0.24.3" +name = "swc_ecma_parser" +version = "27.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +checksum = "7f1a51af1a92cd4904c073b293e491bbc0918400a45d58227b34c961dd6f52d7" dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", + "bitflags 2.10.0", + "either", + "num-bigint", + "phf 0.11.3", + "rustc-hash 2.1.1", + "seq-macro", + "serde", + "smartstring", + "stacker", + "swc_atoms", + "swc_common", + "swc_ecma_ast", + "tracing", ] [[package]] -name = "strum_macros" -version = "0.25.3" +name = "swc_eq_ignore_macros" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "c16ce73424a6316e95e09065ba6a207eba7765496fed113702278b7711d4b632" dependencies = [ - "heck 0.4.1", "proc-macro2", "quote", - "rustversion", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] -name = "strum_macros" -version = "0.26.4" +name = "swc_macros_common" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "aae1efbaa74943dc5ad2a2fb16cbd78b77d7e4d63188f3c5b4df2b4dcd2faaae" dependencies = [ - "heck 0.5.0", "proc-macro2", "quote", - "rustversion", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] -name = "substrate-bn" -version = "0.6.0" +name = "swc_visit" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +checksum = "62fb71484b486c185e34d2172f0eabe7f4722742aad700f426a494bb2de232a2" dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand 0.8.5", - "rustc-hex", + "either", + "new_debug_unreachable", ] -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - [[package]] name = "syn" version = "1.0.109" @@ -7142,9 +17434,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.40" +version = "2.0.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" dependencies = [ "proc-macro2", "quote", @@ -7152,15 +17444,15 @@ dependencies = [ ] [[package]] -name = "syn_derive" -version = "0.1.8" +name = "syn-solidity" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +checksum = "53f425ae0b12e2f5ae65542e00898d500d4d318b4baf09f40fd0d410454e9947" dependencies = [ - "proc-macro-error", + "paste", "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] @@ -7169,6 +17461,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -7181,6 +17482,30 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "sysinfo" +version = "0.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "windows 0.57.0", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -7188,8 +17513,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", + "core-foundation 0.9.4", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.10.0", + "core-foundation 0.9.4", + "system-configuration-sys 0.6.0", ] [[package]] @@ -7202,6 +17549,31 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tabwriter" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce91f2f0ec87dff7e6bcbbeb267439aa1188703003c6055193c821487400432" +dependencies = [ + "unicode-width 0.2.2", +] + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -7212,32 +17584,65 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand 0.4.6", + "remove_dir_all", +] + +[[package]] +name = "tempfile" +version = "3.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +dependencies = [ + "fastrand 2.3.0", + "getrandom 0.3.4", + "once_cell", + "rustix 1.1.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ - "rand 0.4.6", - "remove_dir_all", + "winapi-util", ] [[package]] -name = "tempfile" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +name = "test-spy" +version = "1.0.0" dependencies = [ - "cfg-if 1.0.0", - "fastrand", - "redox_syscall 0.4.1", - "rustix", - "windows-sys 0.48.0", + "async-trait", + "parking_lot 0.12.5", + "serde", + "test-spy-macros", + "tokio", + "workspace-hack", ] [[package]] -name = "termcolor" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +name = "test-spy-macros" +version = "1.0.0" dependencies = [ - "winapi-util", + "proc-macro2", + "quote", + "syn 2.0.112", + "workspace-hack", ] [[package]] @@ -7249,7 +17654,7 @@ dependencies = [ "proc-macro2", "quote", "structmeta", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] @@ -7257,76 +17662,106 @@ name = "testutil" version = "1.3.0" dependencies = [ "once_cell", - "reqwest", + "reqwest 0.12.28", "tokio", + "workspace-hack", +] + +[[package]] +name = "text_lines" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd5828de7deaa782e1dd713006ae96b3bee32d3279b79eb67ecf8072c059bcf" +dependencies = [ + "serde", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.17", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] -name = "thread-id" -version = "4.2.1" +name = "thiserror-impl" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0ec81c46e9eb50deaa257be2f148adf052d1fb7701cfd55ccfab2525280b70b" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ - "libc", - "winapi", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ - "cfg-if 1.0.0", - "once_cell", + "cfg-if", +] + +[[package]] +name = "threadpool" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +dependencies = [ + "num_cpus", ] [[package]] name = "time" -version = "0.3.37" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", - "itoa", + "itoa 1.0.17", + "libc", "num-conv", + "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.2" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.19" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -7341,11 +17776,21 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" dependencies = [ "tinyvec_macros", ] @@ -7358,42 +17803,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes", "libc", "mio", - "num_cpus", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2 0.6.1", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] @@ -7408,9 +17841,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.12" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5d3742945bc7d7f210693b0c58ae542c6fd47b17adbbda0885f3dcb34a6bdb" +checksum = "dcea47c8f71744367793f16c2db1f11cb859d28f436bdb4ca9193eb1f787ee42" dependencies = [ "async-trait", "byteorder", @@ -7419,14 +17852,14 @@ dependencies = [ "futures-channel", "futures-util", "log", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "percent-encoding", - "phf", + "phf 0.13.1", "pin-project-lite", "postgres-protocol", "postgres-types", - "rand 0.8.5", - "socket2 0.5.5", + "rand 0.9.2", + "socket2 0.6.1", "tokio", "tokio-util", "whoami", @@ -7438,15 +17871,25 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.9", + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls 0.23.35", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -7456,32 +17899,34 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.19.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec509ac96e9a0c43427c74f003127d953a265737636129424288d27cb5c4b12c" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" dependencies = [ "futures-util", "log", - "rustls 0.21.9", + "rustls 0.23.35", + "rustls-native-certs", + "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.4", "tungstenite", - "webpki-roots 0.23.1", + "webpki-roots 0.26.11", ] [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", "pin-project-lite", + "slab", "tokio", - "tracing", ] [[package]] @@ -7495,69 +17940,139 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.2" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.20.2", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", +] + +[[package]] +name = "toml" +version = "0.9.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +dependencies = [ + "indexmap 2.13.0", + "serde_core", + "serde_spanned 1.0.4", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 0.7.14", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.13.0", "serde", - "serde_spanned", - "toml_datetime", - "winnow", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.0.2", - "toml_datetime", - "winnow", + "indexmap 2.13.0", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow 0.7.14", +] + +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap 2.13.0", + "toml_datetime 0.7.5+spec-1.1.0", + "toml_parser", + "winnow 0.7.14", +] + +[[package]] +name = "toml_parser" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +dependencies = [ + "winnow 0.7.14", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "toml_writer" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" + [[package]] name = "tonic" -version = "0.9.2" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a" +checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" dependencies = [ "async-trait", - "axum", - "base64 0.21.5", + "base64 0.22.1", "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.8.1", "hyper-timeout", + "hyper-util", "percent-encoding", "pin-project", - "prost", + "sync_wrapper 1.0.2", "tokio", "tokio-stream", "tower", @@ -7566,43 +18081,85 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic-prost" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +dependencies = [ + "bytes", + "prost 0.14.1", + "tonic", +] + [[package]] name = "tower" -version = "0.4.13" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", - "indexmap 1.9.3", - "pin-project", + "hdrhistogram", + "indexmap 2.13.0", "pin-project-lite", - "rand 0.8.5", "slab", + "sync_wrapper 1.0.2", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "async-compression", + "base64 0.22.1", + "bitflags 2.10.0", + "bytes", + "futures-core", + "futures-util", + "http 1.4.0", + "http-body 1.0.1", + "http-body-util", + "http-range-header", + "httpdate", + "iri-string", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", "tokio", "tokio-util", + "tower", "tower-layer", "tower-service", "tracing", + "uuid 1.19.0", ] [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -7610,22 +18167,34 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-appender" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" +dependencies = [ + "crossbeam-channel", + "thiserror 2.0.17", + "time", + "tracing-subscriber 0.3.22", +] + [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -7633,12 +18202,12 @@ dependencies = [ [[package]] name = "tracing-error" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" +checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.22", ] [[package]] @@ -7652,14 +18221,14 @@ dependencies = [ ] [[package]] -name = "tracing-log" -version = "0.1.4" +name = "tracing-journald" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" +checksum = "2d3a81ed245bfb62592b1e2bc153e77656d94ee6a0497683a65a12ccaf2438d0" dependencies = [ - "log", - "once_cell", + "libc", "tracing-core", + "tracing-subscriber 0.3.22", ] [[package]] @@ -7673,29 +18242,58 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-logfmt" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1f47d22deb79c3f59fcf2a1f00f60cbdc05462bf17d1cd356c1fefa3f444bd" +dependencies = [ + "time", + "tracing", + "tracing-core", + "tracing-subscriber 0.3.22", +] + [[package]] name = "tracing-opentelemetry" -version = "0.22.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c67ac25c5407e7b961fafc6f7e9aa5958fd297aada2d20fa2ae1737357e55596" +checksum = "1e6e5658463dd88089aba75c7791e1d3120633b1bfde22478b28f625a9bb1b8e" dependencies = [ "js-sys", - "once_cell", "opentelemetry", "opentelemetry_sdk", + "rustversion", "smallvec", + "thiserror 2.0.17", "tracing", "tracing-core", - "tracing-log 0.2.0", - "tracing-subscriber", + "tracing-log", + "tracing-subscriber 0.3.22", "web-time", ] +[[package]] +name = "tracing-samply" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c175f7ecc002b6ef04776a39f440503e4e788790ddbdbfac8259b7a069526334" +dependencies = [ + "cfg-if", + "itoa 1.0.17", + "libc", + "mach2", + "memmap2", + "smallvec", + "tracing-core", + "tracing-subscriber 0.3.22", +] + [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -7708,13 +18306,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac98e757a488cc11d6a84a52d223b970e11c99e5158cc2ff07b8544ccc260078" dependencies = [ "Inflector", - "http", + "http 0.2.12", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "time", "tracing-core", - "tracing-subscriber", + "tracing-subscriber 0.3.22", "url", "valuable", "valuable-serde", @@ -7722,14 +18320,23 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "serde", "serde_json", "sharded-slab", @@ -7737,10 +18344,46 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log 0.1.4", + "tracing-log", "tracing-serde", ] +[[package]] +name = "tree_hash" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee44f4cef85f88b4dea21c0b1f58320bdf35715cf56d840969487cff00613321" +dependencies = [ + "alloy-primitives", + "ethereum_hashing", + "ethereum_ssz", + "smallvec", + "typenum", +] + +[[package]] +name = "tree_hash_derive" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bee2ea1551f90040ab0e34b6fb7f2fa3bad8acc925837ac654f2c78a13e3089" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "triomphe" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" +dependencies = [ + "arc-swap", + "serde", + "stable_deref_trait", +] + [[package]] name = "trust-dns-proto" version = "0.22.0" @@ -7748,9 +18391,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" dependencies = [ "async-trait", - "cfg-if 1.0.0", + "cfg-if", "data-encoding", - "enum-as-inner", + "enum-as-inner 0.5.1", "futures-channel", "futures-io", "futures-util", @@ -7760,7 +18403,7 @@ dependencies = [ "rand 0.8.5", "smallvec", "socket2 0.4.10", - "thiserror", + "thiserror 1.0.69", "tinyvec", "tokio", "tracing", @@ -7773,58 +18416,81 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "futures-util", "ipconfig", "lazy_static", "lru-cache", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "resolv-conf", "smallvec", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "trust-dns-proto", ] [[package]] -name = "try-lock" -version = "0.2.4" +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ts-rs" +version = "11.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4994acea2522cd2b3b85c1d9529a55991e3ad5e25cdcd3de9d505972c4379424" +dependencies = [ + "chrono", + "dprint-plugin-typescript", + "thiserror 2.0.17", + "ts-rs-macros", + "uuid 1.19.0", +] + +[[package]] +name = "ts-rs-macros" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "ee6ff59666c9cbaec3533964505d39154dc4e0a56151fdea30a09ed0301f62e2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", + "termcolor", +] [[package]] name = "tungstenite" -version = "0.19.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" dependencies = [ - "byteorder", "bytes", "data-encoding", - "http", + "http 1.4.0", "httparse", "log", - "rand 0.8.5", - "rustls 0.21.9", + "rand 0.9.2", + "rustls 0.23.35", + "rustls-pki-types", "sha1", - "thiserror", - "url", + "thiserror 2.0.17", "utf-8", - "webpki", ] [[package]] name = "typenum" -version = "1.17.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uint" @@ -7838,6 +18504,18 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + [[package]] name = "uname" version = "0.1.1" @@ -7855,51 +18533,98 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "uncased" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b9bc53168a4be7402ab86c3aad243a84dd7381d09be0eddc81280c1da95ca68" +checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697" dependencies = [ "version_check", ] [[package]] name = "unicase" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-id-start" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "81b79ad29b5e19de4260020f8919b443b2ef0277d242ce532ec7b7a2cc8b6007" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unimock" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24974669dee059fed1ff4de91b007939fd28e9e1ecefe53f1ab3aea9e7b95977" +dependencies = [ + "once_cell", + "polonius-the-crab", + "pretty_assertions", + "unimock_macros", +] + +[[package]] +name = "unimock_macros" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "41cf1727a558d3708e0e733b7e6833930876a2358c7e250c70d8a303d36a0694" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] [[package]] name = "universal-hash" @@ -7911,6 +18636,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "unsigned-varint" version = "0.7.2" @@ -7921,6 +18652,12 @@ dependencies = [ "bytes", ] +[[package]] +name = "unsigned-varint" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" + [[package]] name = "untrusted" version = "0.7.1" @@ -7933,188 +18670,486 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "ureq" -version = "2.9.1" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdd25c339e200129fe4de81451814e5228c9b771d57378817d6117cc2b3f97" +checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" dependencies = [ - "base64 0.21.5", + "base64 0.22.1", + "der", "log", "native-tls", - "once_cell", - "url", + "percent-encoding", + "rustls-pki-types", + "ureq-proto", + "utf-8", + "webpki-root-certs 1.0.4", +] + +[[package]] +name = "ureq-proto" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" +dependencies = [ + "base64 0.22.1", + "http 1.4.0", + "httparse", + "log", ] [[package]] name = "url" -version = "2.4.1" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 1.1.0", "percent-encoding", "serde", + "serde_derive", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "utf-8" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.11", - "serde", + "getrandom 0.2.16", ] [[package]] name = "uuid" -version = "1.7.0" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +dependencies = [ + "getrandom 0.3.4", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +dependencies = [ + "valuable-derive", +] + +[[package]] +name = "valuable-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3a32a9bcc0f6c6ccfd5b27bcf298c58e753bcc9eeff268157a303393183a6d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "valuable-serde" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee0548edecd1b907be7e67789923b7d02275b9ba4a33ebc33300e2c947a8cb1" +dependencies = [ + "serde", + "valuable", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vec-collections" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c9965c8f2ffed1dbcd16cafe18a009642f540fa22661c6cfd6309ddb02e4982" +dependencies = [ + "binary-merge", + "inplace-vec-builder", + "lazy_static", + "num-traits", + "serde", + "smallvec", + "sorted-iter", +] + +[[package]] +name = "veil" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f00796f9c5969da55497f5c8802c2e69eaf21c0166fe28b6006c7c4699f4d0e" +dependencies = [ + "once_cell", + "veil-macros", +] + +[[package]] +name = "veil-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b2d5567b6fbd34e8f0488d56b648e67c0d999535f4af2060d14f9074b43e833" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "vergen" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b849a1f6d8639e8de261e81ee0fc881e3e3620db1af9f2e0da015d4382ceaf75" +dependencies = [ + "anyhow", + "cargo_metadata 0.23.1", + "derive_builder", + "regex", + "rustversion", + "time", + "vergen-lib", +] + +[[package]] +name = "vergen-git2" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51ab55ddf1188c8d679f349775362b0fa9e90bd7a4ac69838b2a087623f0d57" +dependencies = [ + "anyhow", + "derive_builder", + "git2", + "rustversion", + "time", + "vergen", + "vergen-lib", +] + +[[package]] +name = "vergen-lib" +version = "9.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b34a29ba7e9c59e62f229ae1932fb1b8fb8a6fdcc99215a641913f5f5a59a569" +dependencies = [ + "anyhow", + "derive_builder", + "rustversion", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "wait-timeout" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wallet" +version = "1.3.0" +dependencies = [ + "clap", + "color-eyre", + "contracts", + "element", + "ethereum-types", + "eyre", + "hash-poseidon", + "serde", + "serde_json", + "tokio", + "web3", + "workspace-hack", + "zk-primitives", +] + +[[package]] +name = "wallet-core" +version = "0.1.0" dependencies = [ + "async-trait", + "barretenberg-cli", + "chrono", + "contextful", + "currency", + "data", + "eip7702", + "element", + "eth-util", + "ethereum-types", + "eyre", + "futures", + "guild-client-http", + "guild-interface", + "hash", + "insta", + "kyc", + "lru 0.14.0", + "network", + "node-interface", + "once_cell", + "parking_lot 0.12.5", + "payy-note", + "primitives", + "ramps-interface", + "rand 0.8.5", + "rust-i18n", + "secp256k1 0.28.2", + "sentry", "serde", + "serde_json", + "sha3", + "test-spy", + "testutil", + "thiserror 1.0.69", + "tokio", + "tracing", + "ts-rs", + "uuid 1.19.0", + "wallet-data-dep", + "wallet-primitives", + "web3", + "workspace-hack", + "zk-circuits", + "zk-primitives", ] [[package]] -name = "valuable" +name = "wallet-data-dep" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" dependencies = [ - "valuable-derive", + "chrono", + "element", + "ethereum-types", + "hash-poseidon", + "indexmap 2.13.0", + "insta", + "serde", + "serde_json", + "ts-rs", + "uuid 1.19.0", + "wallet-primitives", + "workspace-hack", + "zk-primitives", ] [[package]] -name = "valuable-derive" +name = "wallet-mobile" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d44690c645190cfce32f91a1582281654b2338c6073fa250b0949fd25c55b32" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "async-trait", + "barretenberg-cli", + "chrono", + "contextful", + "contracts", + "element", + "encrypt", + "eth-util", + "ethereum-types", + "eyre", + "futures", + "guild-client-http", + "guild-interface", + "hex", + "json-store", + "node-client-http", + "node-interface", + "parking_lot 0.12.5", + "payy-note", + "primitives", + "rand 0.8.5", + "reqwest 0.12.28", + "secp256k1 0.28.2", + "serde", + "serde_json", + "sha3", + "tempfile", + "test-spy", + "thiserror 1.0.69", + "tokio", + "tracing", + "ts-rs", + "url", + "uuid 1.19.0", + "wallet-core", + "wallet-primitives", + "web3", + "workspace-hack", + "zk-circuits", + "zk-primitives", ] [[package]] -name = "valuable-serde" +name = "wallet-primitives" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5285cfff30cdabe26626736a54d989687dd9cab84f51f4048b61d6d0ae8b0907" dependencies = [ + "element", + "encrypt", "serde", - "valuable", + "serde_json", + "sha3", + "thiserror 1.0.69", + "workspace-hack", + "zk-primitives", ] [[package]] -name = "vcpkg" -version = "0.2.15" +name = "want" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] [[package]] -name = "version_check" -version = "0.9.4" +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] -name = "void" -version = "1.0.2" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wait-timeout" -version = "0.2.0" +name = "wasi" +version = "0.14.7+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" dependencies = [ - "libc", + "wasip2", ] [[package]] -name = "want" -version = "0.3.1" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "try-lock", + "wit-bindgen 0.46.0", ] [[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] [[package]] name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - -[[package]] -name = "wasm-bindgen" -version = "0.2.88" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "66fe902b4a6b8028a753d5424909b764ccf79b7a209eac9bf97e59cda9f71a42" dependencies = [ - "cfg-if 1.0.0", - "wasm-bindgen-macro", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.88" +name = "wasm-bindgen" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ - "bumpalo", - "log", + "cfg-if", "once_cell", - "proc-macro2", - "quote", - "syn 2.0.40", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.38" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8122,22 +19157,60 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.40", - "wasm-bindgen-backend", + "syn 2.0.112", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] [[package]] name = "wasm-timer" @@ -8154,11 +19227,37 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.10.0", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver 1.0.27", +] + +[[package]] +name = "wasmtimer" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" +dependencies = [ + "futures", + "js-sys", + "parking_lot 0.12.5", + "pin-utils", + "slab", + "wasm-bindgen", +] + [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -8166,9 +19265,9 @@ dependencies = [ [[package]] name = "web-time" -version = "0.2.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -8181,27 +19280,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5388522c899d1e1c96a4c307e3797e0f697ba7c77dd8e0e625ecba9dd0342937" dependencies = [ "arrayvec", - "base64 0.21.5", + "base64 0.21.7", "bytes", - "derive_more", + "derive_more 0.99.20", "ethabi", "ethereum-types", "futures", "futures-timer", - "headers", + "headers 0.3.9", "hex", "idna 0.4.0", "jsonrpc-core", "log", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "pin-project", - "reqwest", - "rlp", + "reqwest 0.11.27", + "rlp 0.5.2", "secp256k1 0.27.0", "serde", "serde_json", - "soketto", + "soketto 0.7.1", "tiny-keccak", "tokio", "tokio-stream", @@ -8217,110 +19316,315 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f6d8d1636b2627fe63518d5a9b38a569405d9c9bc665c43c9c341de57227ebb" dependencies = [ "native-tls", - "thiserror", + "thiserror 1.0.69", "tokio", "url", ] [[package]] -name = "webpki" -version = "0.22.4" +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.14", + "untrusted 0.9.0", +] + +[[package]] +name = "webpki-root-certs" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" +dependencies = [ + "webpki-root-certs 1.0.4", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.4", +] + +[[package]] +name = "webpki-roots" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "whitelist-ips" +version = "1.3.0" +dependencies = [ + "libp2p", + "tracing", + "workspace-hack", +] + +[[package]] +name = "whoami" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace4d5c7b5ab3d99629156d4e0997edbe98a4beb6d5ba99e2cae830207a81983" +dependencies = [ + "libredox", + "wasite", + "web-sys", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efc5cf48f83140dcaab716eeaea345f9e93d0018fb81162753a3f76c3397b538" +dependencies = [ + "windows-core 0.53.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core 0.62.2", +] + +[[package]] +name = "windows-core" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcc5b895a6377f1ab9fa55acedab1fd5ac0db66ad1e6c7f47e28a22e446a5dd" +dependencies = [ + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" dependencies = [ - "ring 0.17.5", - "untrusted 0.9.0", + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets 0.52.6", ] [[package]] -name = "webpki-roots" -version = "0.23.1" +name = "windows-core" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "rustls-webpki 0.100.3", + "windows-implement 0.60.2", + "windows-interface 0.59.3", + "windows-link", + "windows-result 0.4.1", + "windows-strings", ] [[package]] -name = "webpki-roots" -version = "0.25.3" +name = "windows-future" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core 0.62.2", + "windows-link", + "windows-threading", +] [[package]] -name = "whitelist-ips" -version = "1.3.0" +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ - "libp2p", - "tokio", - "tracing", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "whoami" -version = "1.5.2" +name = "windows-implement" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ - "redox_syscall 0.5.7", - "wasite", - "web-sys", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "widestring" -version = "1.0.2" +name = "windows-interface" +version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-interface" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "proc-macro2", + "quote", + "syn 2.0.112", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "winapi-util" -version = "0.1.6" +name = "windows-numerics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "winapi", + "windows-core 0.62.2", + "windows-link", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-registry" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result 0.4.1", + "windows-strings", +] [[package]] -name = "windows" -version = "0.51.1" +name = "windows-result" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-core", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] -name = "windows-core" -version = "0.51.1" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-targets 0.48.5", + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", ] [[package]] @@ -8347,7 +19651,34 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] [[package]] @@ -8382,17 +19713,44 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows-link", ] [[package]] @@ -8409,9 +19767,15 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -8427,9 +19791,15 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -8445,9 +19815,27 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -8463,9 +19851,15 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -8481,9 +19875,15 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -8499,9 +19899,15 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -8517,63 +19923,399 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "winnow" -version = "0.5.17" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wire-message" +version = "1.3.0" +dependencies = [ + "borsh", + "static_assertions", + "strum 0.27.2", + "strum_macros 0.27.2", + "wire-message-macro", + "workspace-hack", +] + +[[package]] +name = "wire-message-macro" +version = "1.3.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", + "workspace-hack", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap 2.13.0", + "prettyplease", + "syn 2.0.112", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.112", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.10.0", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver 1.0.27", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "workspace-hack" +version = "0.1.0" dependencies = [ + "actix-router", + "ahash", + "aho-corasick", + "allocator-api2", + "alloy-chains", + "alloy-consensus", + "alloy-dyn-abi", + "alloy-eip7702", + "alloy-eips", + "alloy-json-abi", + "alloy-primitives", + "alloy-provider", + "alloy-rlp", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-rpc-types-engine", + "alloy-rpc-types-eth", + "alloy-signer-local", + "alloy-sol-macro", + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "alloy-sol-type-parser", + "alloy-sol-types", + "alloy-transport-http", + "ark-bn254", + "ark-ec", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "async-compression", + "base64 0.13.1", + "bindgen 0.71.1", + "bitflags 2.10.0", + "bitvec", + "blst", + "bs58 0.5.1", + "bumpalo", + "byteorder", + "bytes", + "c-kzg", + "cc", + "chrono", + "cipher", + "clang-sys", + "clap", + "clap_builder", + "compression-codecs", + "const-hex", + "crossbeam-epoch", + "crossbeam-utils", + "crunchy", + "crypto-common", + "curve25519-dalek 4.1.3", + "darling 0.21.3", + "darling_core 0.21.3", + "dashmap 6.1.0", + "data-encoding", + "derive_more 2.1.1", + "derive_more-impl 2.1.1", + "digest 0.10.7", + "ecdsa", + "ed25519", + "ed25519-dalek", + "either", + "elliptic-curve", + "errno", + "ethbloom", + "ethereum-types", + "ff", + "figment", + "foldhash 0.1.5", + "form_urlencoded", + "futures", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-timer", + "futures-util", + "generic-array", + "getrandom 0.2.16", + "getrandom 0.3.4", + "group", + "hashbrown 0.13.2", + "hashbrown 0.14.5", + "hashbrown 0.15.5", + "hashbrown 0.16.1", + "hex", + "hmac", + "httparse", + "hyper 1.8.1", + "hyper-rustls 0.27.7", + "hyper-util", + "idna 1.1.0", + "indexmap 2.13.0", + "inout", + "insta", + "itertools 0.11.0", + "itertools 0.13.0", + "itertools 0.14.0", + "k256", + "keccak", + "lalrpop-util", + "lazy_static", + "libc", + "libz-sys", + "linux-raw-sys 0.11.0", + "linux-raw-sys 0.4.15", + "lock_api", + "log", "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if 1.0.0", + "miniz_oxide", + "mio", + "native-tls", + "nom", + "num-bigint", + "num-integer", + "num-iter", + "num-traits", + "num_enum", + "num_enum_derive", + "nybbles", + "once_cell", + "openssl", + "openssl-sys", + "parity-scale-codec", + "parking_lot 0.12.5", + "percent-encoding", + "phf_shared 0.11.3", + "portable-atomic", + "postgres-types", + "ppv-lite86", + "prettyplease", + "primitive-types", + "proc-macro2", + "prost 0.13.5", + "quote", + "rand 0.8.5", + "rand 0.9.2", + "rand_chacha 0.3.1", + "rand_chacha 0.9.0", + "rand_core 0.6.4", + "rand_core 0.9.3", + "regex", + "regex-automata", + "regex-syntax 0.8.8", + "reqwest 0.11.27", + "reqwest 0.12.28", + "ring 0.17.14", + "rlp 0.5.2", + "ruint", + "rustc-hash 2.1.1", + "rustc-hex", + "rustix 0.38.44", + "rustix 1.1.3", + "rustls 0.23.35", + "rustls-webpki 0.103.8", + "scopeguard", + "sec1", + "security-framework 2.11.1", + "security-framework 3.5.1", + "security-framework-sys", + "semver 1.0.27", + "serde", + "serde_core", + "serde_json", + "serde_with", + "sha1", + "sha2", + "sha3", + "signature", + "similar", + "smallvec", + "socket2 0.5.10", + "socket2 0.6.1", + "strum 0.27.2", + "subtle", + "syn 1.0.109", + "syn 2.0.112", + "sync_wrapper 1.0.2", + "thiserror 2.0.17", + "time", + "tiny-keccak", + "tokio", + "tokio-postgres", + "tokio-rustls 0.26.4", + "tokio-stream", + "tokio-tungstenite", + "tokio-util", + "tower", + "tower-http", + "tracing", + "tracing-core", + "tracing-subscriber 0.3.22", + "triomphe", + "unicode-bidi", + "unicode-normalization", + "url", + "uuid 1.19.0", + "winapi", "windows-sys 0.48.0", + "windows-sys 0.52.0", + "windows-sys 0.59.0", + "windows-sys 0.60.2", + "windows-sys 0.61.2", + "winnow 0.7.14", + "zeroize", + "zstd 0.13.3", + "zstd-safe 7.2.4", + "zstd-sys", ] [[package]] -name = "wire-message" -version = "1.3.0" -dependencies = [ - "borsh", - "static_assertions", - "strum 0.26.3", - "strum_macros 0.26.4", - "wire-message-macro", -] - -[[package]] -name = "wire-message-macro" -version = "1.3.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.40", -] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "ws_stream_wasm" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +checksum = "6c173014acad22e83f16403ee360115b38846fe754e735c5d9d3803fe70c6abc" dependencies = [ "async_io_stream", "futures", "js-sys", "log", "pharos", - "rustc_version 0.4.0", + "rustc_version 0.4.1", "send_wrapper 0.6.0", - "thiserror", + "thiserror 2.0.17", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -8599,6 +20341,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "x25519-dalek" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" +dependencies = [ + "curve25519-dalek 4.1.3", + "rand_core 0.6.4", + "serde", + "zeroize", +] + [[package]] name = "x509-parser" version = "0.14.0" @@ -8613,17 +20367,30 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror", + "thiserror 1.0.69", "time", ] [[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +name = "xtask" +version = "0.1.0" dependencies = [ - "linked-hash-map", + "clap", + "contextful", + "duct", + "hex", + "home", + "indoc", + "reqwest 0.12.28", + "serde", + "serde_json", + "sha2", + "solc-tooling", + "tempfile", + "thiserror 1.0.69", + "toml 0.9.11+spec-1.1.0", + "which", + "workspace-hack", ] [[package]] @@ -8635,16 +20402,22 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot 0.12.1", + "parking_lot 0.12.5", "rand 0.8.5", "static_assertions", ] [[package]] name = "yansi" -version = "1.0.0-rc.1" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + +[[package]] +name = "yansi" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yasna" @@ -8655,183 +20428,250 @@ dependencies = [ "time", ] +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", + "synstructure 0.13.2", +] + [[package]] name = "zerocopy" -version = "0.7.20" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd66a62464e3ffd4e37bd09950c2b9dd6c4f8767380fabba0d523f9a775bc85a" +checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.20" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255c4596d41e6916ced49cfafea18727b24d67878fa180ddfd69b9df34fd1726" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", + "synstructure 0.13.2", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.112", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.112", +] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq 0.1.5", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2 0.11.0", + "sha1", + "time", + "zstd 0.11.2+zstd.1.5.2", ] [[package]] name = "zk-circuits" -version = "1.3.0" +version = "0.1.0" dependencies = [ - "base64 0.21.5", - "benchy", + "acvm", + "alloy", + "async-trait", + "barretenberg-api-client", + "barretenberg-cli", + "barretenberg-interface", + "barretenberg-rs", + "base64 0.22.1", + "bincode 2.0.1", "bitvec", - "blake2b_simd", - "borsh", - "bs58 0.5.0", - "eth-types", - "ethereum-types", - "expect-test", - "halo2-base", - "halo2-ecc", - "halo2_gadgets", - "hex", - "itertools 0.11.0", - "num-bigint", - "once_cell", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit?branch=main)", - "primitives", - "rand 0.8.5", - "secp256k1 0.28.1", - "serde", + "bn254_blackbox_solver", + "element", + "flate2", + "hash", + "hash-poseidon", + "lazy_static", + "nargo", + "noir-abi-inputs-macro", + "noirc_abi", + "noirc_artifacts", + "noirc_driver", + "paste", "serde_json", - "sha3 0.10.8", + "sha3", "smirk", - "snark-verifier", - "snark-verifier-sdk", - "strum 0.26.3", - "strum_macros 0.26.4", - "thiserror", - "uint", - "wire-message", + "tempfile", + "tokio", + "unimock", + "url", + "workspace-hack", "zk-primitives", - "zkevm-circuits", ] [[package]] name = "zk-primitives" version = "1.3.0" dependencies = [ - "bitvec", "borsh", - "diesel", + "element", "ethnum", - "ff 0.12.1", + "hash", "hex", - "insta", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit?branch=main)", - "proptest", + "noirc_abi", + "parse-link", + "primitives", "rand 0.8.5", - "rand_chacha", - "rand_xorshift", "serde", - "serde_json", - "test-strategy", + "sha3", + "ts-rs", + "web3", + "workspace-hack", ] [[package]] -name = "zkevm-circuits" -version = "0.1.0" -source = "git+https://github.com/polybase/zkevm-circuits?branch=develop-polybase#047b8ca02427fb524717705caaa46a29a7b6a1cf" -dependencies = [ - "array-init", - "bus-mapping", - "either", - "env_logger 0.10.0", - "eth-types", - "ethers-core 2.0.7", - "ethers-signers", - "gadgets", - "halo2-base", - "halo2-ecc", - "halo2_proofs 0.2.0", - "hex", - "itertools 0.10.5", - "keccak256", - "lazy_static", - "libsecp256k1", - "log", - "maingate", - "misc-precompiled-circuit", - "mock", - "mpt-zktrie", - "num", - "num-bigint", - "once_cell", - "poseidon-circuit 0.1.0 (git+https://github.com/scroll-tech/poseidon-circuit.git?branch=scroll-dev-0901)", - "rand 0.8.5", - "rand_chacha", - "rand_xorshift", - "rayon", - "serde", - "serde_json", - "sha3 0.10.8", - "snark-verifier", - "snark-verifier-sdk", - "strum 0.24.1", - "strum_macros 0.24.3", - "subtle", -] +name = "zmij" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3280a1b827474fcd5dbef4b35a674deb52ba5c312363aef9135317df179d81b" [[package]] -name = "zktrie" -version = "0.2.0" -source = "git+https://github.com/polybase/zktrie/?branch=bypass-builds-on-android-and-ios#47c4fbc019e5d5271a40ca358650916e0723cb70" +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ - "gobuild 0.1.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zstd-safe 5.0.2+zstd.1.5.2", ] [[package]] name = "zstd" -version = "0.12.4" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" dependencies = [ - "zstd-safe", + "zstd-safe 7.2.4", ] [[package]] name = "zstd-safe" -version = "6.0.6" +version = "5.0.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" dependencies = [ "libc", "zstd-sys", ] +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.16+zstd.1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ + "bindgen 0.72.1", "cc", "pkg-config", ] diff --git a/Cargo.toml b/Cargo.toml index 3fc10da..282bc67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,207 +1,345 @@ [workspace] resolver = "2" +members = ["pkg/*", "app/packages/react-native-rust-bridge/cpp/rustbridge"] -members = ["pkg/*"] +[workspace.metadata.cargo-machete] +ignored = ["workspace-hack"] + +[workspace.metadata.cargo-machete.renamed] +async-stripe = "stripe" # `opt-level = 1` has a decent impact on perf, and doesn't impact compile times much [profile.dev] opt-level = 1 -# `opt-level = 3` has a large impact on perf, but does impact compile times. However, we only apply it to dependencies, -# so incremental compilation makes this choice essentially "free" after the first compile -[profile.dev.package."*"] -opt-level = 3 +[profile.dev.package.workspace-hack] +# Fixes some spurious rebuilds of workspace-hack +incremental = false -[patch."https://github.com/privacy-scaling-explorations/halo2.git"] -halo2_proofs = { git = "https://github.com/scroll-tech/halo2.git", branch = "develop" } -[patch."https://github.com/privacy-scaling-explorations/poseidon.git"] -poseidon = { git = "https://github.com/scroll-tech/poseidon.git", branch = "scroll-dev-0220" } -[patch."https://github.com/privacy-scaling-explorations/halo2curves.git"] -halo2curves = { git = "https://github.com/scroll-tech/halo2curves.git", branch = "0.3.1-derive-serde" } +# `opt-level = 3` has a large impact on perf, but does impact compile times. However, we only apply it to dependencies, +# so incremental compilation makes this choice essentially "free" after the first compile +#[profile.dev.package."*"] +#opt-level = 3 -[patch.crates-io] -ethers-core = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v2.0.7" } -ethers-providers = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v2.0.7" } -ethers-signers = { git = "https://github.com/scroll-tech/ethers-rs.git", branch = "v2.0.7" } +# Note: halo2 related patches have been removed as part of migration [workspace.dependencies] -block-store = { path = "./pkg/block-store" } +aggregator-interface = { path = "./pkg/aggregator-interface" } +aggregator = { path = "./pkg/aggregator" } +alfred-http = { path = "./pkg/alfred-http" } +alfred-interface = { path = "./pkg/alfred-interface" } +alfred-provider = { path = "./pkg/alfred-provider" } burn-substitutor = { path = "./pkg/burn-substitutor" } +barretenberg-interface = { path = "./pkg/barretenberg-interface" } +barretenberg-cli = { path = "./pkg/barretenberg-cli" } +barretenberg-api-interface = { path = "./pkg/barretenberg-api-interface" } +barretenberg-api-server = { path = "./pkg/barretenberg-api-server" } +barretenberg-api-bin = { path = "./pkg/barretenberg-api-bin" } +barretenberg-api-client = { path = "./pkg/barretenberg-api-client" } +barretenberg-api-tests = { path = "./pkg/barretenberg-api-tests" } +barretenberg-rs = { path = "./pkg/barretenberg-rs" } +zk-circuits = { path = "./pkg/zk-circuits" } +contextful = { path = "./pkg/contextful" } +contextful-macros = { path = "./pkg/contextful-macros" } +test-spy = { path = "./pkg/test-spy" } +test-spy-macros = { path = "./pkg/test-spy-macros" } +block-store = { path = "./pkg/block-store" } contracts = { path = "./pkg/contracts" } +constants = { path = "./pkg/constants" } +country = { path = "./pkg/country" } +client-http = { path = "./pkg/client-http" } +client-http-longpoll = { path = "./pkg/client-http-longpoll" } +http-interface = { path = "./pkg/http-interface" } +currency = { path = "./pkg/currency" } +database = { path = "./pkg/database", default-features = false } +data = { path = "./pkg/data" } +diesel-util = { path = "./pkg/diesel-util" } doomslug = { path = "./pkg/doomslug" } +document-ai-google = { path = "./pkg/document-ai-google" } +document-ai-interface = { path = "./pkg/document-ai-interface" } +element = { path = "./pkg/element" } +encrypt = { path = "./pkg/encrypt" } +eth-util = { path = "./pkg/eth-util" } +faucet = { path = "./pkg/faucet" } +guild-client-http = { path = "./pkg/guild-client-http" } +guild-interface = { path = "./pkg/guild-interface" } +hash = { path = "./pkg/hash" } +hash-poseidon = { path = "./pkg/hash-poseidon" } +hmac-sha256-json = { path = "./pkg/hmac-sha256-json" } +json-store = { path = "./pkg/json-store" } +json-with-logging = { path = "./pkg/json-with-logging" } +serde_yaml = { path = "./pkg/serde_yaml" } node = { path = "./pkg/node" } +node-client-http = { path = "./pkg/node-client-http" } +node-interface = { path = "./pkg/node-interface" } +network = { path = "./pkg/network" } +notes-interface = { path = "./pkg/notes-interface" } +notes-rpc = { path = "./pkg/notes-rpc" } +notes-storage-interface = { path = "./pkg/notes-storage-interface" } +notes-storage-pg = { path = "./pkg/notes-storage-pg" } +notes = { path = "./pkg/notes" } +rewards-interface = { path = "./pkg/rewards-interface" } +rewards-rpc = { path = "./pkg/rewards-rpc" } +rewards-storage-interface = { path = "./pkg/rewards-storage-interface" } +rewards-storage-pg = { path = "./pkg/rewards-storage-pg" } +rewards = { path = "./pkg/rewards" } +support-interface = { path = "./pkg/support-interface" } +support-rpc = { path = "./pkg/support-rpc" } +support-storage-interface = { path = "./pkg/support-storage-interface" } +support-storage-pg = { path = "./pkg/support-storage-pg" } +support = { path = "./pkg/support" } +p2p = { path = "./pkg/p2p" } p2p2 = { path = "./pkg/p2p2" } +parse-link = { path = "./pkg/parse-link" } +posthog-interface = { path = "./pkg/posthog-interface" } +posthog = { path = "./pkg/posthog" } +kyc = { path = "./pkg/kyc" } primitives = { path = "./pkg/primitives" } prover = { path = "./pkg/prover" } +providers-interface = { path = "./pkg/providers-interface" } rpc = { path = "./pkg/rpc" } +rpc-error-convert = { path = "./pkg/rpc-error-convert" } smirk = { path = "./pkg/smirk" } -whitelist-ips = { path = "./pkg/whitelist-ips" } +solid = { path = "./pkg/solid" } +solc-tooling = { path = "./pkg/solc-tooling" } +wallet-core = { path = "./pkg/wallet-core" } +wallet-data-dep = { path = "./pkg/wallet-data-dep" } +wallet-mobile = { path = "./pkg/wallet-mobile" } +wallet-primitives = { path = "./pkg/wallet-primitives" } wire-message = { path = "./pkg/wire-message" } -zk-circuits = { path = "./pkg/zk-circuits" } -zk-primitives = { path = "./pkg/zk-primitives" } +wire-message-macro = { path = "./pkg/wire-message-macro" } +whitelist-ips = { path = "./pkg/whitelist-ips" } testutil = { path = "./pkg/testutil" } +zk-primitives = { path = "./pkg/zk-primitives" } +minimal-poseidon = { path = "./pkg/minimal-poseidon" } +eip7702 = { path = "./pkg/eip7702" } +payy_core = { path = "./pkg/payy_core" } +payy_core_types = { path = "./pkg/payy_core_types" } +payy-note = { path = "./pkg/payy-note" } +noir-abi-inputs-macro = { path = "./pkg/noir-abi-inputs-macro" } +bungee-interface = { path = "./pkg/bungee-interface" } +bungee-client-http = { path = "./pkg/bungee-client-http" } +slack-client-interface = { path = "./pkg/slack-client-interface" } +slack-client-http = { path = "./pkg/slack-client-http" } +ramps-interface = { path = "./pkg/ramps-interface" } +ramps-providers-interface = { path = "./pkg/ramps-providers-interface" } +ramps-storage-interface = { path = "./pkg/ramps-storage-interface" } +ramps-storage-pg = { path = "./pkg/ramps-storage-pg" } +ramps = { path = "./pkg/ramps" } +ramps-rpc = { path = "./pkg/ramps-rpc" } +ramps-notification-interface = { path = "./pkg/ramps-notification-interface" } +ramps-notification = { path = "./pkg/ramps-notification" } +push-notification-interface = { path = "./pkg/push-notification-interface" } +push-notification-expo = { path = "./pkg/push-notification-expo" } +rain-http = { path = "./pkg/rain-http" } +rain-interface = { path = "./pkg/rain-interface" } +rain-provider = { path = "./pkg/rain-provider" } +sumsub-http = { path = "./pkg/sumsub-http" } +sumsub-interface = { path = "./pkg/sumsub-interface" } +sumsub-provider = { path = "./pkg/sumsub-provider" } +manteca-interface = { path = "./pkg/manteca-interface" } +manteca-http = { path = "./pkg/manteca-http" } +manteca-provider = { path = "./pkg/manteca-provider" } +# Reth dependencies (git-based, aligned with reth.rs docs) +reth-ethereum = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2", features = [ + "node", +] } +reth-chainspec = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-db = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2", features = ["mdbx"] } +reth-db-common = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-evm = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-tasks = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-ethereum-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-provider = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-primitives = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-primitives-traits = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-transaction-pool = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } +reth-node-builder = { git = "https://github.com/paradigmxyz/reth", tag = "v1.10.2" } + +workspace-hack = "0.1" +ts-rs = { version = "^11.1.0", features = ["format", "chrono-impl", "uuid-impl"] } actix-cors = "0.6.4" actix-server = "2.3.0" -actix-web = "4.4.0" +actix-web = "4.12.1" +axum = "0.7" +tower = "0.5" +tower-http = "0.6" +http-body-util = "0.1" +hyper = "1" +veil = "0.2.0" +alloy = { version = "1.0.24", features = ["std", "essentials", "reqwest-rustls-tls", "signers"] } +alloy-consensus = "1.4.3" +alloy-eips = "1.4.3" +alloy-evm = "0.26.3" +alloy-genesis = "1.4.3" +alloy-primitives = "1.5.0" +alloy-rpc-types-engine = "1.4.3" +httpmock = "0.8.2" +mime = "0.3.17" +acvm = { git = "https://github.com/noir-lang/noir", tag = "v1.0.0-beta.14" } +noirc_abi = { git = "https://github.com/noir-lang/noir", tag = "v1.0.0-beta.14" } +noirc_driver = { git = "https://github.com/noir-lang/noir", tag = "v1.0.0-beta.14" } +noirc_artifacts = { git = "https://github.com/noir-lang/noir", tag = "v1.0.0-beta.14" } +bn254_blackbox_solver = { git = "https://github.com/noir-lang/noir", tag = "v1.0.0-beta.14" } +nargo = { git = "https://github.com/noir-lang/noir", tag = "v1.0.0-beta.14" } +actix-multipart = "0.7.2" aes-gcm = "0.10.3" -async-stripe = { version = "0.31", features = ["runtime-tokio-hyper"] } +async-stripe = { version = "0.41", default-features = false, features = [ + "full", + "webhook-events", + "stream", + "runtime-tokio-hyper", + "uuid", +] } async-trait = "0.1" -base64 = "0.21.5" +async-recursion = "1.1.1" +async-stream = "0.3.6" +async-fn-stream = "0.3.2" +base64 = "0.22.1" +bb_rs = { package = "polybase_bb_rs", git = "https://github.com/polybase/aztec-packages", rev = "7ad5d5c892f1396ca572da4b2e29a761d1f11f1f" } # v3.0.0-manual.20251030-polybase benchy = "0.1.1" +bigdecimal = { version = "0.4.8", features = ["serde"] } bitvec = "1.0.1" blake2b_simd = "1.0" -bs58 = "0.5.0" -bytes = "1.0" +bs58 = "0.5.1" +bytes = "1.11" chrono = { version = "0.4", features = ["serde"] } -clap = { version = "=4.1.1", features = ["env", "derive"] } -colored = "2.0.4" +clap = { version = "4.5.60", features = ["env", "derive"] } +colored = "3.0.0" color-eyre = "0.6" -dashmap = "5" -diesel = { version = "2.1.0", features = [ - "postgres", - "uuid", - "chrono", - "r2d2", - "serde_json", +crypto_secretbox = "0.1.1" +dashmap = "6" +deadpool = "0.12" +diesel = { version = "2.3.7", features = [ + "postgres_backend", + "uuid", + "chrono", + "serde_json", + "64-column-tables", ] } -tokio-postgres = "0.7.2" +diesel-async = "0.7.4" +tokio-postgres = { version = "0.7.16" } postgres-native-tls = "0.5.0" -native-tls = "0.2.12" +native-tls = "0.2.15" derive_more = "0.99.17" dirs = "5.0.1" dotenvy = "0.15.7" -eth-types = { git = "https://github.com/polybase/zkevm-circuits", branch = "develop-polybase" } +duct = "1.1" ethereum-types = "0.14.1" +ethers-solc = "2.0.14" ethnum = "1.5.0" -expect-test = "1.4.1" +expect-test = "1.5.1" eyre = "0.6" -ff = "0.12.1" +ff = "0.13.1" figment = { version = "0.10", features = ["env", "toml"] } file-lock = "2" futures = "0.3.26" futures-timer = "3.0.2" futures-util = "0.3.29" -halo2-base = { git = "https://github.com/scroll-tech/halo2-lib", tag = "v0.1.5", default-features = false, features = [ - "halo2-pse", - "display", -] } -halo2-ecc = { git = "https://github.com/scroll-tech/halo2-lib", tag = "v0.1.5", default-features = false, features = [ - "halo2-pse", - "display", -] } -halo2_gadgets = { git = "https://github.com/scroll-tech/halo2.git", branch = "develop" } -halo2_proofs = "0.3" -halo2curves = { version = "0.1.0" } +halo2curves = "0.1.0" hex = { version = "0.4", features = ["serde"] } hmac = "0.12" +home = "0.5.11" +indoc = "2" +indexmap = { version = "2.13", features = ["serde"] } insta = { version = "1", features = ["json"] } -itertools = "0.11.0" -jsonwebtoken = "7" -lazy_static = "1.4.0" +itertools = "0.14.0" +jsonwebtoken = { version = "10", features = ["rust_crypto"] } +lazy_static = "1.5" libp2p = { version = "0.51", default-features = false, features = [ - "ping", - "request-response", - "identify", - "gossipsub", - "macros", - "tokio", - "noise", - "dns", - "yamux", - "tcp", + "ping", + "request-response", + "identify", + "gossipsub", + "macros", + "tokio", + "noise", + "dns", + "yamux", + "tcp", ] } -libp2p-core = { version = "0.38.0" } +libp2p-core = { version = "0.39.2" } notify = "6" num-bigint = "0.4.6" +openssl = { version = "0.10.75", default-features = false } once_cell = "1.19.0" -parking_lot = { version = "0.12.1", features = ["deadlock_detection"] } +parking_lot = "0.12.1" phonenumber = "0.3" -poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit", branch = "main" } pretty-hex = "0.3.0" -proptest = "1" +proptest = "1.6.0" +proc-macro2 = "1.0" +quote = "1.0" quickcheck = "1.0.3" rand = "0.8.5" rand_chacha = "0.3.1" rand_xorshift = "0.3" -reqwest = { version = "0.11.22", features = ["json", "multipart"] } +reqwest = { version = "0.12", features = ["json", "multipart"] } +rlp = "0.6.1" rocksdb = "0.21" rustc-hex = "2.1.0" -sentry = "0.32.1" -sentry-tracing = "0.32.1" -serde = { version = "1", features = ["derive"] } -serde_json = "1.0.108" -serde_qs = "0.12.0" -serde_yaml = "0.9.27" -serde_bytes = "0.11.14" -bincode = "1.3.3" +rust-i18n = "3" +rsa = { version = "0.9", features = ["sha1"] } +sentry = "0.46.0" +sentry-tracing = "0.46.2" +serde = { version = "1.0.221", features = ["derive"] } +serde_json = "1.0.145" +serde_qs = "0.15.0" +serde_bytes = "0.11.19" +serde_yaml_ng = "0.10.0" +bincode = { version = "2.0.1", default-features = false, features = ["derive", "std", "serde"] } scopeguard = "1.2.0" -secp256k1 = { version = "0.28.0", features = [ - "rand", - "global-context", - "recovery", -] } +unimock = "0.6.8" +secp256k1 = { version = "0.28.0", features = ["rand", "global-context", "recovery"] } +url = { version = "2.5.8" } +semver = "1.0.15" +sha1 = "0.10.1" sha2 = "0.10.6" sha3 = "0.10.1" -snark-verifier = { git = "https://github.com/scroll-tech/snark-verifier", tag = "v0.1.5" } -snark-verifier-sdk = { git = "https://github.com/scroll-tech/snark-verifier", tag = "v0.1.5", default-features = false, features = [ - "loader_halo2", - "loader_evm", - "halo2-pse", -] } spinoff = "0.8.0" +syn = { version = "2.0", features = ["full", "extra-traits"] } tracing-stackdriver = { version = "0.7.2", features = ["valuable"] } static_assertions = "1" tabular = "0.2.0" tempdir = "0.3" +tempfile = "3.23.0" test-strategy = "0.3.1" thiserror = "1" tiny-keccak = { version = "2.0.2", features = ["keccak"] } -toml = "0.8" +toml = { version = "0.9" } tokio = { version = "1", features = ["full"] } -tokio-stream = { version = "0.1.12", features = ["sync"] } +tokio-stream = { version = "0.1.18", features = ["sync"] } tracing = { version = "0.1.37", features = ["valuable"] } -tracing-subscriber = { version = "0.3.17", features = [ - "env-filter", - "fmt", - "std", - "registry", - "ansi", - "json", +valuable = "0.1" +tracing-subscriber = { version = "0.3.18", features = [ + "env-filter", + "fmt", + "std", + "registry", + "ansi", + "json", ] } -uint = "0.9.1" +typenum = "1.18" +uint = "0.10.0" unarray = "0.1.4" +urlencoding = "2.1.3" user-error = "1.2.8" -uuid = { version = "1.7.0", features = ["v4"] } +uuid = { version = "1.18.1", features = ["v4", "serde"] } web3 = "0.19.0" -zkevm-circuits = { git = "https://github.com/polybase/zkevm-circuits", branch = "develop-polybase", default-features = false, features = [ - "parallel_syn", - "scroll", - "shanghai", - "test", - "debug-annotations", -] } -serial_test = "3.0.0" +which = "4.4" +serial_test = { version = "3.0.0", features = ["file_locks"] } # the `de_strict_order` flag is important for maintaining bijection borsh = { version = "1", features = ["derive", "de_strict_order", "rc"] } -opentelemetry = { version = "0.21.0", features = ["metrics", "trace"] } -opentelemetry_sdk = { version = "0.21.2", features = [ - "rt-tokio", - "metrics", - "trace", -] } -opentelemetry-otlp = { version = "0.14.0", features = [ - "tokio", - "tonic", - "trace", - "metrics", -] } -tracing-opentelemetry = "0.22.0" +opentelemetry = { version = "0.31.0", features = ["metrics", "trace"] } +opentelemetry_sdk = { version = "0.31.0", features = ["rt-tokio", "metrics", "trace"] } +opentelemetry-otlp = { version = "0.31.0", features = ["grpc-tonic", "trace", "metrics"] } +tracing-opentelemetry = "0.32.0" +x25519-dalek = { version = "2.0.1", features = ["static_secrets"] } # utilities for deriving stuff on macros -strum = "0.26" -strum_macros = "0.26" +strum = "0.27" +strum_macros = "0.27.2" rayon = "1" derivative = "2" microtype = "0.7" @@ -209,5 +347,23 @@ rand_derive2 = "0.1" either = "1.9.0" flate2 = "1.0.28" object_store = { version = "0.10.0", features = ["gcp"] } +regex = "1.11.1" expo_push_notification_client = { git = "https://github.com/polybase/expo-push-notification-client-rust.git", branch = "rustc-1_68_nightly" } num_cpus = "1.16.0" +mockito = "0.25" +lru = "0.14.0" +paste = "1" +tokio-test = "0.4" +rustls = "0.23" +tokio-rustls = "0.26" +webpki-roots = "0.26" +httparse = "1.9" +http = "1.4" + +[patch.crates-io] +# rust-i18n uses a deprecated serde_yaml dependency, so we use our shim instead +serde_yaml = { path = "pkg/serde_yaml" } +workspace-hack = { path = "pkg/workspace-hack" } + +[workspace.metadata.i18n] +load-path = "./pkg/wallet-core/locales" diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8bb25e3..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022-2024 Polybase Labs - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 6466f0b..0000000 --- a/README.md +++ /dev/null @@ -1,89 +0,0 @@ -Payy Logo - -# Payy - ZK Rollup - -An Ethereum L2 ZK rollup for privacy preserving and regulatory compliant transactions. - -Here are some highlights: - - - 🚀 Fast - runs in under 3 seconds on an iPhone - - 🪄 Tiny - UTXO proofs are under 2.8KB - - ✅ EVM - proofs are compatible with Ethereum - -For a detailed description of our architecture, please [download our whitepaper](https://polybase.github.io/zk-rollup/whitepaper.pdf) or visit our [docs](https://payy.network/docs). - - -| Module | Path | Desc | -|--------------------|-----------------------------------------|-----------------------------------------------------------------| -| Ethereum Contracts | [eth](/eth) | Ethereum smart contracts to verify state transitions and proofs | -| Contracts | [pkg/prover](/pkg/prover) | Rust interface to Ethereum smart contracts | -| RPC | [pkg/rpc](/pkg/rpc-server) | RPC common utilities shared across all RPC services | -| Smirk | [pkg/smirk](/pkg/smirk) | Sparse merkle tree | -| ZK-Circuits | [pkg/zk-circuits](/pkg/zk-circuits) | Halo2 + KZG ZK circuits for proving UTXO, merkle and state transitions | -| ZK-Primitives | [pkg/zk-primitives](/pkg/zk-primitives) | ZK primitives used across multiple modules | - - -## Tests - -``` -cargo test -``` - -Note: these tests can take a while to run on your laptop (e.g. more than 20 minutes) - - -## Audit - -The ZK-Circuits and Ethereum Contracts have been audited by KALOS. All report findings have been fixed and resolved. - -[KALOS Audit Report 2024-02-23](audits/kalos_2024_02_23.pdf) - - -## Git LFS - -We use [Git LFS](https://git-lfs.com/) for storing large files (e.g. srs params). - -A one-time setup needs to be done for local development: - - 1. Install `git lfs` following the instructions at https://git-lfs.com/ - 2. Inside the `zk-rollup` root directory, run the following commands: - - ```bash - $ git lfs install - $ git lfs pull - ``` - - -## Contributing - -We appreciate your interest in contributing to our open-source project. Your contributions help improve the project for everyone. - -### Code of Conduct - -This project adheres to the Contributor Covenant [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [hello@polybaselabs.com](mailto:hello@polybaselabs.com). - -### Security vulnerabilities - -We take security issues seriously. If you discover a security vulnerability, we appreciate your assistance in disclosing it to us in a responsible manner. Do not report security vulnerabilities through public issues or forums. Instead, send a full report to [hello@polybaselabs.com](mailto:hello@polybaselabs.com). We do not have an official bug bounty program but will reward responsibly disclosed vulnerabilities at our discretion. - - -### Reporting Bugs - -If you find a bug, please report it by [opening an issue](https://github.com/polybase/payy/issues). Include as much detail as possible, including steps to reproduce the issue, the environment in which it occurs, and any relevant screenshots or code snippets. - -### Suggesting Enhancements - -We appreciate enhancements! To suggest a feature or enhancement, please [open an issue](https://github.com/polybase/payy/issues) with a detailed description of your proposal. Explain why it is needed and how it would benefit the project. - -### Submitting Pull Requests - -1. Fork the repository -2. Create a new branch (`git checkout -b feature/YourFeature`) -3. Make your changes -4. Commit your changes (`git commit -m 'Add some feature'`) -5. Push to the branch (`git push origin feature/YourFeature`) -6. Open a pull request - -### License - -By contributing, you agree that your contributions will be licensed under the same license as the project. For more details, see [LICENSE](LICENSE). diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..6503543 --- /dev/null +++ b/app/package.json @@ -0,0 +1,45 @@ +{ + "private": "true", + "name": "app", + "version": "1.3.0", + "scripts": { + "lint": "yarn workspaces -p run lint --max-warnings=0", + "lint:types": "tsc --noEmit", + "test": "yarn workspaces -p run test", + "postinstall": "patch-package", + "format": "prettier \"**/*.{js,jsx,ts,tsx,json}\" --write", + "format:check": "prettier \"**/*.{js,jsx,ts,tsx,json}\" --check" + }, + "workspaces": [ + "packages/*" + ], + "devDependencies": { + "@eslint/compat": "^1.3.1", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "^9.18.0", + "@types/jest": "^29.5.14", + "@types/react": "~19.1.0", + "@typescript-eslint/eslint-plugin": "^8.20.0", + "@typescript-eslint/parser": "^8.20.0", + "eslint": "^9.18.0", + "eslint-config-standard": "^17.1.0", + "eslint-import-resolver-typescript": "^3.7.0", + "eslint-plugin-import-x": "4.6.1", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-n": "^17.15.1", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-promise": "^7.2.1", + "globals": "^15.14.0", + "prettier": "3.5.3", + "typescript": "^5.9.2" + }, + "resolutions": { + "@babel/core": "^7.26.0", + "react": "19.1.0", + "react-dom": "19.1.0", + "@types/react": "19.1.0", + "@types/react-dom": "19.1.0", + "@solana/wallet-adapter-base": "0.9.23", + "jest-snapshot-prettier": "npm:prettier@3.5.3" + } +} diff --git a/app/packages/link/.gitignore b/app/packages/link/.gitignore new file mode 100644 index 0000000..fd3dbb5 --- /dev/null +++ b/app/packages/link/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/app/packages/link/README.md b/app/packages/link/README.md new file mode 100644 index 0000000..c403366 --- /dev/null +++ b/app/packages/link/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/app/packages/link/next.config.js b/app/packages/link/next.config.js new file mode 100644 index 0000000..20f448c --- /dev/null +++ b/app/packages/link/next.config.js @@ -0,0 +1,18 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + async headers() { + return [ + { + source: '/.well-known/apple-app-site-association', + headers: [ + { + key: 'Content-Type', + value: 'application/json' + } + ] + } + ] + } +} + +module.exports = nextConfig diff --git a/app/packages/link/package.json b/app/packages/link/package.json new file mode 100644 index 0000000..430e8a1 --- /dev/null +++ b/app/packages/link/package.json @@ -0,0 +1,25 @@ +{ + "name": "link", + "version": "1.3.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint 'src/**/*.{ts,tsx}'", + "test": "echo 'No tests specified for link'" + }, + "dependencies": { + "next": "14.2.35", + "posthog-js": "^1.256.0", + "react": "^18", + "react-dom": "^18", + "ua-parser-js": "^2.0.4" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "18.3.1", + "@types/react-dom": "18.3.1", + "typescript": "^5" + } +} diff --git a/app/packages/link/public/.well-known/apple-app-site-association b/app/packages/link/public/.well-known/apple-app-site-association new file mode 100644 index 0000000..99cf5d1 --- /dev/null +++ b/app/packages/link/public/.well-known/apple-app-site-association @@ -0,0 +1,33 @@ +{ + "applinks": { + "apps": [], + "details": [ + { + "appID": "M3K9QT3D4W.com.polybaselabs.wallet", + "paths": [ + "/r/*", + "/s/*", + "/s", + "/invite/*", + "/connect/*", + "/app*" + ] + } + ] + }, + "appclips": { + "apps": [ + "M3K9QT3D4W.com.polybaselabs.wallet.Clip" + ] + }, + "activitycontinuation": { + "apps": [ + "M3K9QT3D4W.com.polybaselabs.wallet" + ] + }, + "webcredentials": { + "apps": [ + "M3K9QT3D4W.com.polybaselabs.wallet" + ] + } +} \ No newline at end of file diff --git a/app/packages/link/public/.well-known/apple-developer-merchantid-domain-association.txt b/app/packages/link/public/.well-known/apple-developer-merchantid-domain-association.txt new file mode 100644 index 0000000..85a57f1 --- /dev/null +++ b/app/packages/link/public/.well-known/apple-developer-merchantid-domain-association.txt @@ -0,0 +1,74 @@ +MIIQXAYJKoZIhvcNAQcCoIIQTTCCEEkCAQExCzAJBgUrDgMCGgUAMGsGCSqGSIb3DQEHAaBeBFx7 +InRlYW1JZCI6Ik0zSzlRVDNENFciLCJkb21haW4iOiJwYXl5LmxpbmsiLCJkYXRlQ3JlYXRlZCI6 +IjIwMjQtMDctMTAsMTE6MDQ6NDMiLCJ2ZXJzaW9uIjoxfaCCDT8wggQ0MIIDHKADAgECAghj8Fby +zyJX8zANBgkqhkiG9w0BAQsFADBzMS0wKwYDVQQDDCRBcHBsZSBpUGhvbmUgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApB +cHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0yNDAxMzAxODMyMDVaFw0yOTAxMjgxODMyMDRaMFkx +NTAzBgNVBAMMLEFwcGxlIGlQaG9uZSBPUyBQcm92aXNpb25pbmcgUHJvZmlsZSBTaWduaW5nMRMw +EQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALUVf-QlDVyFc-LKrtxt6o0Yaf6m_9z9zCkuTapwFYkPv0ffWM5YWUoIHbGhDbb2IHFS +dwd9ZH9CaYsoe_LDQD2zcIEXyeSGLZlXN3XA1OO2NxzYNybuQCyLcfDvFGNM5L_RL4dQRR2nEnGR +tBf2w0lAcG3rj3bctfPBYfkkrDFZvlf-SpbFigCWx7kKOZhR6oBOAoYR6O147UfGZXr4sAvVhyl- +ZpvtPb3oObp9SGQ754gHX558IZaQFABXQGUmrtujg7yNG_ejhWM6N_Su0M4UbxFUJ1KwaMu0az7S +AMQ5FOisR3BSVjZfnis-U5mm44DSU3g3u3PfmQy3HJKar2UCAwEAAaOB5TCB4jAMBgNVHRMBAf8E +AjAAMB8GA1UdIwQYMBaAFG_xlRhiXODI8cXtbBjJ4NNkUpggMEAGCCsGAQUFBwEBBDQwMjAwBggr +BgEFBQcwAYYkaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwMy1haXBjYTA3MC8GA1UdHwQoMCYw +JKAioCCGHmh0dHA6Ly9jcmwuYXBwbGUuY29tL2FpcGNhLmNybDAdBgNVHQ4EFgQUKQBD4MaTBfTi +e_810nkG-lSXdiMwDgYDVR0PAQH_BAQDAgeAMA8GCSqGSIb3Y2QGOgQCBQAwDQYJKoZIhvcNAQEL +BQADggEBAEDnU1sA0pYC76dgPtbbuKU1j1hHOy2YgLn-c7PWj9FNBH9lumyzUbxvMz7ncXo6Avww +Uja6aZald9IvaT9tfpj8W0JiSjJZ0X6tV7HLRZ4KSN5GBzUbXgMbLmie29qobMQ3CIWgQJijEjhw +EA1INWSFk1YHN9naVjhwJajhT2hXLFgMGhZJ3j8lNnNY3OVfeSiPuQsDu-Gc9RbneGwST8GwfnHX +SrL-0QE04o9uHi8LerTBsTKGTr9bmIRoT2eHT8CeurQx9Am0ij3W3hAqS8SNw03U6sVimZgZ693R +fcf32em9p3heJhRfY-Z_RGjwKGG9wOEV4ECr_2Hoe8A5SgwwggREMIIDLKADAgECAghcY8rkSjdT +yTANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5jLjEmMCQG +A1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxlIFJvb3Qg +Q0EwHhcNMTcwNTEwMjEyNzMwWhcNMzAxMjMxMDAwMDAwWjBzMS0wKwYDVQQDDCRBcHBsZSBpUGhv +bmUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMlFagEPPoMEhsf8v9xe8B6B7hcwc2MmLt49eiTNkz5POUe6db7zwNLxWaKr +H_4KhjzZLZoH8g5ruSmRGl8iCovxclgFrkxLRMV5p4A8sIjgjAwnhF0Z5YcZNsvjxXa3sPRBclH0 +BVyDS6JtplG48Sbfe16tZQzGsphRjLt9G0zBTsgIx9LtZAu03RuNT0B9G49IlpJb89CYftm8pBkO +mWG7QV0BzFt3en0k0NzTU__D3MWULLZaTY4YIzm92cZSPtHy9CWKoSqH_dgMRilR_-0XbIkla4e_ +imkUn3efwxW3aLOIRb2E5gYCQWQPrSoouBXJ4KynirpyBDSyeIz4soUCAwEAAaOB7DCB6TAPBgNV +HRMBAf8EBTADAQH_MB8GA1UdIwQYMBaAFCvQaUeUdgn-9GuNLkCm90dNfwheMEQGCCsGAQUFBwEB +BDgwNjA0BggrBgEFBQcwAYYoaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwMy1hcHBsZXJvb3Rj +YTAuBgNVHR8EJzAlMCOgIaAfhh1odHRwOi8vY3JsLmFwcGxlLmNvbS9yb290LmNybDAdBgNVHQ4E +FgQUb_GVGGJc4Mjxxe1sGMng02RSmCAwDgYDVR0PAQH_BAQDAgEGMBAGCiqGSIb3Y2QGAhIEAgUA +MA0GCSqGSIb3DQEBCwUAA4IBAQA6z6yYjb6SICEJrZXzsVwh-jYtVyBEdHNkkgizlqz3bZf6WzQ4 +J88SRtM8EfAHyZmQsdHoEQml46VrbGMIP54l-tWZnEzm5c6Osk1o7Iuro6JPihEVPtwUKxzGRLZv +Z8VbT5UpLYdcP9yDHndP7dpUpy3nE4HBY8RUCxtLCmooIgjUN5J8f2coX689P7esWR04NGRa7jNK +GUJEKcTKGGvhwVMtLfRNwhX2MzIYePEmb4pN65RMo-j_D7MDi2Xa6y7YZVCf3J-K3zGohFTcUlJB +0rITHTFGR4hfPu7D8owjBJXrrIo-gmwGny7ji0OaYls0DfSZzyzuunKGGSOl_I61MIIEuzCCA6Og +AwIBAgIBAjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5j +LjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNVBAMTDUFwcGxl +IFJvb3QgQ0EwHhcNMDYwNDI1MjE0MDM2WhcNMzUwMjA5MjE0MDM2WjBiMQswCQYDVQQGEwJVUzET +MBEGA1UEChMKQXBwbGUgSW5jLjEmMCQGA1UECxMdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkxFjAUBgNVBAMTDUFwcGxlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDkkakJH5HbHkdQ6wXtXnmELes2oldMVeyLGYne-Uts9QerIjAC6Bg--FAJ039BqJj50cpmnCRr +EdCju-QbKsMflZ56DKRHi1vUFjczy8QPTc4UadHJGXL1XQ7Vf1-b8iUDulWPTV0N8WQ1IxVLFVkd +s5T39pyez1C6wVhQZ48ItCD3y6wsIG9wtj8BMIy3Q88PnT3zK0koGsj-zrW5DtleHNbLPbU6rfQP +DgCSC7EhFi501TwN22IWq6NxkkdTVcGvL0Gz-PvjcM3mo0xFfh9Ma1CWQYnEdGILEINBhzOKgbEw +WOxaBDKMaLOPHd5lc_9nXmW8Sdh2nzMUZaF3lMktAgMBAAGjggF6MIIBdjAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH_BAUwAwEB_zAdBgNVHQ4EFgQUK9BpR5R2Cf70a40uQKb3R01_CF4wHwYDVR0j +BBgwFoAUK9BpR5R2Cf70a40uQKb3R01_CF4wggERBgNVHSAEggEIMIIBBDCCAQAGCSqGSIb3Y2QF +ATCB8jAqBggrBgEFBQcCARYeaHR0cHM6Ly93d3cuYXBwbGUuY29tL2FwcGxlY2EvMIHDBggrBgEF +BQcCAjCBthqBs1JlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3Vt +ZXMgYWNjZXB0YW5jZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBj +b25kaXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0aW9uIHBy +YWN0aWNlIHN0YXRlbWVudHMuMA0GCSqGSIb3DQEBBQUAA4IBAQBcNplMLXi37Yyb3PN3m_J20ncw +T8EfhYOFG5k9RzfyqZtAjizUsZAS2L70c5vu0mQPy3lPNNiiPvl4_2vIB-x9OYOLUyDTOMSxv5pP +Cmv_K_xZpwUJfBdAVhEedNO3iyM7R6PVbyTi69G3cN8PReEnyvFteO3ntRcXqNx-IjXKJdXZD9Zr +1KIkIxH3oayPc4FgxhtbCS-SsvhESPBgOJ4V9T0mZyCKM2r3DYLP3uujL_lTaltkwGMzd_c6ByxW +69oPIQ7aunMZT7XZNn_Bh1XZp5m5MkL72NVxnn6hUrcbvZNCJBIqxw8dtk2cXmPIS4AXUKqK1drk +_NAJBzewdXUhMYIChTCCAoECAQEwfzBzMS0wKwYDVQQDDCRBcHBsZSBpUGhvbmUgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQK +DApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUwIIY_BW8s8iV_MwCQYFKw4DAhoFAKCB3DAYBgkqhkiG +9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNDA3MTAxMTA0NDNaMCMGCSqGSIb3 +DQEJBDEWBBSZVNhqLBD9YT6uFG7vwrz22Ju6CjApBgkqhkiG9w0BCTQxHDAaMAkGBSsOAwIaBQCh +DQYJKoZIhvcNAQEBBQAwUgYJKoZIhvcNAQkPMUUwQzAKBggqhkiG9w0DBzAOBggqhkiG9w0DAgIC +AIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwDQYJKoZIhvcNAQEBBQAE +ggEANLE4PXE3HF0XCoB3I29dQjz9pNF9XxDwujzOYzs1OCWXYL6hlKFsXotSLZXCOdBFOtS2KfXz +3rsqnVqQ2aYFXhZw3gkR3A6rcyOUQnsNDhxBb4VPuRM43heuXc1hDN-v8I83Zb5FGcJN6bzjt8ib +ZL1PvvSoDBljz_sdUdrShYeNNMWeSlD3DMPTKwvmyQ9lc1Syrq7i-zGum9FH6-w-e9g38r0bFMHN +R9yhF4e3e2DDKffD8fvhUkKm5cDZGWseD_fx9tduLUSPtiwv-OOM9OIbSsJewQoFsqFC50W8-Nju +Fq58rwSbmoKJdMdDHHPooFzvt90yaV3B_jtp4tMInw diff --git a/app/packages/link/public/.well-known/assetlinks.json b/app/packages/link/public/.well-known/assetlinks.json new file mode 100644 index 0000000..3e90585 --- /dev/null +++ b/app/packages/link/public/.well-known/assetlinks.json @@ -0,0 +1,12 @@ +[ + { + "relation": ["delegate_permission/common.handle_all_urls"], + "target": { + "namespace": "android_app", + "package_name": "com.polybaselabs.wallet", + "sha256_cert_fingerprints": [ + "58:C0:A6:E3:99:D2:31:1C:76:C3:87:9D:E4:70:B4:18:6B:19:94:BA:2D:23:D3:F2:34:A4:D2:F9:88:B3:B1:CC" + ] + } + } +] diff --git a/app/packages/link/public/assets/crypto/large/1sol.png b/app/packages/link/public/assets/crypto/large/1sol.png new file mode 100644 index 0000000..4fa0c74 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/1sol.png differ diff --git a/app/packages/link/public/assets/crypto/large/CTI.png b/app/packages/link/public/assets/crypto/large/CTI.png new file mode 100644 index 0000000..828b827 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/CTI.png differ diff --git a/app/packages/link/public/assets/crypto/large/aave.png b/app/packages/link/public/assets/crypto/large/aave.png new file mode 100644 index 0000000..299c7ca Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/aave.png differ diff --git a/app/packages/link/public/assets/crypto/large/aptos.png b/app/packages/link/public/assets/crypto/large/aptos.png new file mode 100644 index 0000000..c617a41 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/aptos.png differ diff --git a/app/packages/link/public/assets/crypto/large/arbitrum.png b/app/packages/link/public/assets/crypto/large/arbitrum.png new file mode 100644 index 0000000..a7ee462 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/arbitrum.png differ diff --git a/app/packages/link/public/assets/crypto/large/avalanche.png b/app/packages/link/public/assets/crypto/large/avalanche.png new file mode 100644 index 0000000..73ff507 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/avalanche.png differ diff --git a/app/packages/link/public/assets/crypto/large/axie.png b/app/packages/link/public/assets/crypto/large/axie.png new file mode 100644 index 0000000..e210547 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/axie.png differ diff --git a/app/packages/link/public/assets/crypto/large/base.png b/app/packages/link/public/assets/crypto/large/base.png new file mode 100644 index 0000000..f90fe30 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/base.png differ diff --git a/app/packages/link/public/assets/crypto/large/bonk.png b/app/packages/link/public/assets/crypto/large/bonk.png new file mode 100644 index 0000000..6f25d87 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/bonk.png differ diff --git a/app/packages/link/public/assets/crypto/large/bsc.png b/app/packages/link/public/assets/crypto/large/bsc.png new file mode 100644 index 0000000..6700cd8 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/bsc.png differ diff --git a/app/packages/link/public/assets/crypto/large/celsius.png b/app/packages/link/public/assets/crypto/large/celsius.png new file mode 100644 index 0000000..edd67f4 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/celsius.png differ diff --git a/app/packages/link/public/assets/crypto/large/chainlink.png b/app/packages/link/public/assets/crypto/large/chainlink.png new file mode 100644 index 0000000..63a1f35 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/chainlink.png differ diff --git a/app/packages/link/public/assets/crypto/large/dai.png b/app/packages/link/public/assets/crypto/large/dai.png new file mode 100644 index 0000000..698ffc4 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/dai.png differ diff --git a/app/packages/link/public/assets/crypto/large/decentraland.png b/app/packages/link/public/assets/crypto/large/decentraland.png new file mode 100644 index 0000000..ad9d7b1 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/decentraland.png differ diff --git a/app/packages/link/public/assets/crypto/large/drift.png b/app/packages/link/public/assets/crypto/large/drift.png new file mode 100644 index 0000000..5066cfc Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/drift.png differ diff --git a/app/packages/link/public/assets/crypto/large/dydx.png b/app/packages/link/public/assets/crypto/large/dydx.png new file mode 100644 index 0000000..5dfe136 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/dydx.png differ diff --git a/app/packages/link/public/assets/crypto/large/ethereum.png b/app/packages/link/public/assets/crypto/large/ethereum.png new file mode 100644 index 0000000..c8ac5ec Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/ethereum.png differ diff --git a/app/packages/link/public/assets/crypto/large/frax.png b/app/packages/link/public/assets/crypto/large/frax.png new file mode 100644 index 0000000..d128dbf Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/frax.png differ diff --git a/app/packages/link/public/assets/crypto/large/ftt.png b/app/packages/link/public/assets/crypto/large/ftt.png new file mode 100644 index 0000000..266202a Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/ftt.png differ diff --git a/app/packages/link/public/assets/crypto/large/jupiter.png b/app/packages/link/public/assets/crypto/large/jupiter.png new file mode 100644 index 0000000..9383f3e Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/jupiter.png differ diff --git a/app/packages/link/public/assets/crypto/large/lido.png b/app/packages/link/public/assets/crypto/large/lido.png new file mode 100644 index 0000000..b0800b6 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/lido.png differ diff --git a/app/packages/link/public/assets/crypto/large/optimism.png b/app/packages/link/public/assets/crypto/large/optimism.png new file mode 100644 index 0000000..3270b54 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/optimism.png differ diff --git a/app/packages/link/public/assets/crypto/large/polygon.png b/app/packages/link/public/assets/crypto/large/polygon.png new file mode 100644 index 0000000..7f54933 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/polygon.png differ diff --git a/app/packages/link/public/assets/crypto/large/sand.png b/app/packages/link/public/assets/crypto/large/sand.png new file mode 100644 index 0000000..de7ce70 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/sand.png differ diff --git a/app/packages/link/public/assets/crypto/large/scroll.png b/app/packages/link/public/assets/crypto/large/scroll.png new file mode 100644 index 0000000..63012a0 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/scroll.png differ diff --git a/app/packages/link/public/assets/crypto/large/serum.png b/app/packages/link/public/assets/crypto/large/serum.png new file mode 100644 index 0000000..ed64393 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/serum.png differ diff --git a/app/packages/link/public/assets/crypto/large/shiba.png b/app/packages/link/public/assets/crypto/large/shiba.png new file mode 100644 index 0000000..3666e52 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/shiba.png differ diff --git a/app/packages/link/public/assets/crypto/large/sol.png b/app/packages/link/public/assets/crypto/large/sol.png new file mode 100644 index 0000000..bef8cfd Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/sol.png differ diff --git a/app/packages/link/public/assets/crypto/large/solana.png b/app/packages/link/public/assets/crypto/large/solana.png new file mode 100644 index 0000000..bef8cfd Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/solana.png differ diff --git a/app/packages/link/public/assets/crypto/large/sushiswap.png b/app/packages/link/public/assets/crypto/large/sushiswap.png new file mode 100644 index 0000000..16d322a Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/sushiswap.png differ diff --git a/app/packages/link/public/assets/crypto/large/tether.png b/app/packages/link/public/assets/crypto/large/tether.png new file mode 100644 index 0000000..212b301 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/tether.png differ diff --git a/app/packages/link/public/assets/crypto/large/uniswap.png b/app/packages/link/public/assets/crypto/large/uniswap.png new file mode 100644 index 0000000..01ffcf7 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/uniswap.png differ diff --git a/app/packages/link/public/assets/crypto/large/usdc.png b/app/packages/link/public/assets/crypto/large/usdc.png new file mode 100644 index 0000000..fb2bc48 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/usdc.png differ diff --git a/app/packages/link/public/assets/crypto/large/wbtc.png b/app/packages/link/public/assets/crypto/large/wbtc.png new file mode 100644 index 0000000..6a1ea55 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/wbtc.png differ diff --git a/app/packages/link/public/assets/crypto/large/weth.png b/app/packages/link/public/assets/crypto/large/weth.png new file mode 100644 index 0000000..a7a970c Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/weth.png differ diff --git a/app/packages/link/public/assets/crypto/large/wormhole.png b/app/packages/link/public/assets/crypto/large/wormhole.png new file mode 100644 index 0000000..85da1a2 Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/wormhole.png differ diff --git a/app/packages/link/public/assets/crypto/large/zksync.png b/app/packages/link/public/assets/crypto/large/zksync.png new file mode 100644 index 0000000..c589e8b Binary files /dev/null and b/app/packages/link/public/assets/crypto/large/zksync.png differ diff --git a/app/packages/link/public/assets/crypto/small/1sol.png b/app/packages/link/public/assets/crypto/small/1sol.png new file mode 100644 index 0000000..003eeb0 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/1sol.png differ diff --git a/app/packages/link/public/assets/crypto/small/CTI.png b/app/packages/link/public/assets/crypto/small/CTI.png new file mode 100644 index 0000000..b2b0f7b Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/CTI.png differ diff --git a/app/packages/link/public/assets/crypto/small/aave.png b/app/packages/link/public/assets/crypto/small/aave.png new file mode 100644 index 0000000..ce97de2 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/aave.png differ diff --git a/app/packages/link/public/assets/crypto/small/aptos.png b/app/packages/link/public/assets/crypto/small/aptos.png new file mode 100644 index 0000000..e82daec Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/aptos.png differ diff --git a/app/packages/link/public/assets/crypto/small/arbitrum.png b/app/packages/link/public/assets/crypto/small/arbitrum.png new file mode 100644 index 0000000..620cae1 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/arbitrum.png differ diff --git a/app/packages/link/public/assets/crypto/small/avalanche.png b/app/packages/link/public/assets/crypto/small/avalanche.png new file mode 100644 index 0000000..d1d0509 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/avalanche.png differ diff --git a/app/packages/link/public/assets/crypto/small/axie.png b/app/packages/link/public/assets/crypto/small/axie.png new file mode 100644 index 0000000..6d25e04 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/axie.png differ diff --git a/app/packages/link/public/assets/crypto/small/base.png b/app/packages/link/public/assets/crypto/small/base.png new file mode 100644 index 0000000..cba701b Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/base.png differ diff --git a/app/packages/link/public/assets/crypto/small/bonk.png b/app/packages/link/public/assets/crypto/small/bonk.png new file mode 100644 index 0000000..34994e8 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/bonk.png differ diff --git a/app/packages/link/public/assets/crypto/small/bsc.png b/app/packages/link/public/assets/crypto/small/bsc.png new file mode 100644 index 0000000..c0aafbc Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/bsc.png differ diff --git a/app/packages/link/public/assets/crypto/small/celsius.png b/app/packages/link/public/assets/crypto/small/celsius.png new file mode 100644 index 0000000..8e20c59 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/celsius.png differ diff --git a/app/packages/link/public/assets/crypto/small/chainlink.png b/app/packages/link/public/assets/crypto/small/chainlink.png new file mode 100644 index 0000000..2baf4d4 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/chainlink.png differ diff --git a/app/packages/link/public/assets/crypto/small/dai.png b/app/packages/link/public/assets/crypto/small/dai.png new file mode 100644 index 0000000..427f742 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/dai.png differ diff --git a/app/packages/link/public/assets/crypto/small/decentraland.png b/app/packages/link/public/assets/crypto/small/decentraland.png new file mode 100644 index 0000000..399e5b7 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/decentraland.png differ diff --git a/app/packages/link/public/assets/crypto/small/drift.png b/app/packages/link/public/assets/crypto/small/drift.png new file mode 100644 index 0000000..bcd590a Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/drift.png differ diff --git a/app/packages/link/public/assets/crypto/small/dydx.png b/app/packages/link/public/assets/crypto/small/dydx.png new file mode 100644 index 0000000..501bd24 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/dydx.png differ diff --git a/app/packages/link/public/assets/crypto/small/ethereum.png b/app/packages/link/public/assets/crypto/small/ethereum.png new file mode 100644 index 0000000..e5e3c9a Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/ethereum.png differ diff --git a/app/packages/link/public/assets/crypto/small/frax.png b/app/packages/link/public/assets/crypto/small/frax.png new file mode 100644 index 0000000..79159cb Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/frax.png differ diff --git a/app/packages/link/public/assets/crypto/small/ftt.png b/app/packages/link/public/assets/crypto/small/ftt.png new file mode 100644 index 0000000..e16990b Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/ftt.png differ diff --git a/app/packages/link/public/assets/crypto/small/jupiter.png b/app/packages/link/public/assets/crypto/small/jupiter.png new file mode 100644 index 0000000..5b38f5a Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/jupiter.png differ diff --git a/app/packages/link/public/assets/crypto/small/lido.png b/app/packages/link/public/assets/crypto/small/lido.png new file mode 100644 index 0000000..65fa4e0 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/lido.png differ diff --git a/app/packages/link/public/assets/crypto/small/optimism.png b/app/packages/link/public/assets/crypto/small/optimism.png new file mode 100644 index 0000000..3dbd9dc Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/optimism.png differ diff --git a/app/packages/link/public/assets/crypto/small/polygon.png b/app/packages/link/public/assets/crypto/small/polygon.png new file mode 100644 index 0000000..05de274 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/polygon.png differ diff --git a/app/packages/link/public/assets/crypto/small/sand.png b/app/packages/link/public/assets/crypto/small/sand.png new file mode 100644 index 0000000..253bf37 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/sand.png differ diff --git a/app/packages/link/public/assets/crypto/small/scroll.png b/app/packages/link/public/assets/crypto/small/scroll.png new file mode 100644 index 0000000..33a783d Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/scroll.png differ diff --git a/app/packages/link/public/assets/crypto/small/serum.png b/app/packages/link/public/assets/crypto/small/serum.png new file mode 100644 index 0000000..ebb811c Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/serum.png differ diff --git a/app/packages/link/public/assets/crypto/small/shiba.png b/app/packages/link/public/assets/crypto/small/shiba.png new file mode 100644 index 0000000..feb4664 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/shiba.png differ diff --git a/app/packages/link/public/assets/crypto/small/sol.png b/app/packages/link/public/assets/crypto/small/sol.png new file mode 100644 index 0000000..72e951f Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/sol.png differ diff --git a/app/packages/link/public/assets/crypto/small/solana.png b/app/packages/link/public/assets/crypto/small/solana.png new file mode 100644 index 0000000..72e951f Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/solana.png differ diff --git a/app/packages/link/public/assets/crypto/small/sushiswap.png b/app/packages/link/public/assets/crypto/small/sushiswap.png new file mode 100644 index 0000000..1af06d2 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/sushiswap.png differ diff --git a/app/packages/link/public/assets/crypto/small/tether.png b/app/packages/link/public/assets/crypto/small/tether.png new file mode 100644 index 0000000..3d4c092 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/tether.png differ diff --git a/app/packages/link/public/assets/crypto/small/uniswap.png b/app/packages/link/public/assets/crypto/small/uniswap.png new file mode 100644 index 0000000..d25a632 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/uniswap.png differ diff --git a/app/packages/link/public/assets/crypto/small/usdc.png b/app/packages/link/public/assets/crypto/small/usdc.png new file mode 100644 index 0000000..df764d1 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/usdc.png differ diff --git a/app/packages/link/public/assets/crypto/small/wbtc.png b/app/packages/link/public/assets/crypto/small/wbtc.png new file mode 100644 index 0000000..f8d9d0d Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/wbtc.png differ diff --git a/app/packages/link/public/assets/crypto/small/weth.png b/app/packages/link/public/assets/crypto/small/weth.png new file mode 100644 index 0000000..9707eef Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/weth.png differ diff --git a/app/packages/link/public/assets/crypto/small/wormhole.png b/app/packages/link/public/assets/crypto/small/wormhole.png new file mode 100644 index 0000000..adba7cc Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/wormhole.png differ diff --git a/app/packages/link/public/assets/crypto/small/zksync.png b/app/packages/link/public/assets/crypto/small/zksync.png new file mode 100644 index 0000000..4503695 Binary files /dev/null and b/app/packages/link/public/assets/crypto/small/zksync.png differ diff --git a/app/packages/link/public/assets/flags/png/ab.png b/app/packages/link/public/assets/flags/png/ab.png new file mode 100644 index 0000000..6dd3a91 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ab.png differ diff --git a/app/packages/link/public/assets/flags/png/ad.png b/app/packages/link/public/assets/flags/png/ad.png new file mode 100644 index 0000000..83a26fa Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ad.png differ diff --git a/app/packages/link/public/assets/flags/png/ae.png b/app/packages/link/public/assets/flags/png/ae.png new file mode 100644 index 0000000..c857f83 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ae.png differ diff --git a/app/packages/link/public/assets/flags/png/af.png b/app/packages/link/public/assets/flags/png/af.png new file mode 100644 index 0000000..6bcd8d5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/af.png differ diff --git a/app/packages/link/public/assets/flags/png/ag.png b/app/packages/link/public/assets/flags/png/ag.png new file mode 100644 index 0000000..1022983 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ag.png differ diff --git a/app/packages/link/public/assets/flags/png/ai.png b/app/packages/link/public/assets/flags/png/ai.png new file mode 100644 index 0000000..c30a0c9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ai.png differ diff --git a/app/packages/link/public/assets/flags/png/al.png b/app/packages/link/public/assets/flags/png/al.png new file mode 100644 index 0000000..74cd36f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/al.png differ diff --git a/app/packages/link/public/assets/flags/png/am.png b/app/packages/link/public/assets/flags/png/am.png new file mode 100644 index 0000000..89f7ed5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/am.png differ diff --git a/app/packages/link/public/assets/flags/png/ao.png b/app/packages/link/public/assets/flags/png/ao.png new file mode 100644 index 0000000..03bd47e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ao.png differ diff --git a/app/packages/link/public/assets/flags/png/aq.png b/app/packages/link/public/assets/flags/png/aq.png new file mode 100644 index 0000000..ef7a504 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/aq.png differ diff --git a/app/packages/link/public/assets/flags/png/ar.png b/app/packages/link/public/assets/flags/png/ar.png new file mode 100644 index 0000000..b8249d1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ar.png differ diff --git a/app/packages/link/public/assets/flags/png/as.png b/app/packages/link/public/assets/flags/png/as.png new file mode 100644 index 0000000..8c587fc Binary files /dev/null and b/app/packages/link/public/assets/flags/png/as.png differ diff --git a/app/packages/link/public/assets/flags/png/at.png b/app/packages/link/public/assets/flags/png/at.png new file mode 100644 index 0000000..0ac0dd4 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/at.png differ diff --git a/app/packages/link/public/assets/flags/png/au.png b/app/packages/link/public/assets/flags/png/au.png new file mode 100644 index 0000000..ed5feca Binary files /dev/null and b/app/packages/link/public/assets/flags/png/au.png differ diff --git a/app/packages/link/public/assets/flags/png/aw.png b/app/packages/link/public/assets/flags/png/aw.png new file mode 100644 index 0000000..991bb24 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/aw.png differ diff --git a/app/packages/link/public/assets/flags/png/ax.png b/app/packages/link/public/assets/flags/png/ax.png new file mode 100644 index 0000000..43d6e7f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ax.png differ diff --git a/app/packages/link/public/assets/flags/png/az.png b/app/packages/link/public/assets/flags/png/az.png new file mode 100644 index 0000000..4356b5d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/az.png differ diff --git a/app/packages/link/public/assets/flags/png/ba.png b/app/packages/link/public/assets/flags/png/ba.png new file mode 100644 index 0000000..de95795 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ba.png differ diff --git a/app/packages/link/public/assets/flags/png/bb.png b/app/packages/link/public/assets/flags/png/bb.png new file mode 100644 index 0000000..ab62f7f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bb.png differ diff --git a/app/packages/link/public/assets/flags/png/bd.png b/app/packages/link/public/assets/flags/png/bd.png new file mode 100644 index 0000000..faa0e09 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bd.png differ diff --git a/app/packages/link/public/assets/flags/png/be.png b/app/packages/link/public/assets/flags/png/be.png new file mode 100644 index 0000000..41d2de7 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/be.png differ diff --git a/app/packages/link/public/assets/flags/png/bf.png b/app/packages/link/public/assets/flags/png/bf.png new file mode 100644 index 0000000..ec539e4 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bf.png differ diff --git a/app/packages/link/public/assets/flags/png/bg.png b/app/packages/link/public/assets/flags/png/bg.png new file mode 100644 index 0000000..a345dfe Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bg.png differ diff --git a/app/packages/link/public/assets/flags/png/bh.png b/app/packages/link/public/assets/flags/png/bh.png new file mode 100644 index 0000000..15fc8eb Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bh.png differ diff --git a/app/packages/link/public/assets/flags/png/bi.png b/app/packages/link/public/assets/flags/png/bi.png new file mode 100644 index 0000000..4b5f8d4 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bi.png differ diff --git a/app/packages/link/public/assets/flags/png/bj.png b/app/packages/link/public/assets/flags/png/bj.png new file mode 100644 index 0000000..9f0d94d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bj.png differ diff --git a/app/packages/link/public/assets/flags/png/bl.png b/app/packages/link/public/assets/flags/png/bl.png new file mode 100644 index 0000000..a1a9a92 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bl.png differ diff --git a/app/packages/link/public/assets/flags/png/bm.png b/app/packages/link/public/assets/flags/png/bm.png new file mode 100644 index 0000000..73cebdd Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bm.png differ diff --git a/app/packages/link/public/assets/flags/png/bn.png b/app/packages/link/public/assets/flags/png/bn.png new file mode 100644 index 0000000..d68bb2a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bn.png differ diff --git a/app/packages/link/public/assets/flags/png/bo.png b/app/packages/link/public/assets/flags/png/bo.png new file mode 100644 index 0000000..9a90364 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bo.png differ diff --git a/app/packages/link/public/assets/flags/png/bq.png b/app/packages/link/public/assets/flags/png/bq.png new file mode 100644 index 0000000..665c65f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bq.png differ diff --git a/app/packages/link/public/assets/flags/png/br.png b/app/packages/link/public/assets/flags/png/br.png new file mode 100644 index 0000000..b9a003e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/br.png differ diff --git a/app/packages/link/public/assets/flags/png/bs.png b/app/packages/link/public/assets/flags/png/bs.png new file mode 100644 index 0000000..eac1585 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bs.png differ diff --git a/app/packages/link/public/assets/flags/png/bt.png b/app/packages/link/public/assets/flags/png/bt.png new file mode 100644 index 0000000..82b5c24 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bt.png differ diff --git a/app/packages/link/public/assets/flags/png/bv.png b/app/packages/link/public/assets/flags/png/bv.png new file mode 100644 index 0000000..4d1bc43 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bv.png differ diff --git a/app/packages/link/public/assets/flags/png/bw.png b/app/packages/link/public/assets/flags/png/bw.png new file mode 100644 index 0000000..613184d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bw.png differ diff --git a/app/packages/link/public/assets/flags/png/by.png b/app/packages/link/public/assets/flags/png/by.png new file mode 100644 index 0000000..b5dde30 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/by.png differ diff --git a/app/packages/link/public/assets/flags/png/bz.png b/app/packages/link/public/assets/flags/png/bz.png new file mode 100644 index 0000000..9e99bf0 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/bz.png differ diff --git a/app/packages/link/public/assets/flags/png/ca.png b/app/packages/link/public/assets/flags/png/ca.png new file mode 100644 index 0000000..21164dc Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ca.png differ diff --git a/app/packages/link/public/assets/flags/png/cc.png b/app/packages/link/public/assets/flags/png/cc.png new file mode 100644 index 0000000..1b4259b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cc.png differ diff --git a/app/packages/link/public/assets/flags/png/cd.png b/app/packages/link/public/assets/flags/png/cd.png new file mode 100644 index 0000000..3052b79 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cd.png differ diff --git a/app/packages/link/public/assets/flags/png/cf.png b/app/packages/link/public/assets/flags/png/cf.png new file mode 100644 index 0000000..eea8ceb Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cf.png differ diff --git a/app/packages/link/public/assets/flags/png/cg.png b/app/packages/link/public/assets/flags/png/cg.png new file mode 100644 index 0000000..83616aa Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cg.png differ diff --git a/app/packages/link/public/assets/flags/png/ch.png b/app/packages/link/public/assets/flags/png/ch.png new file mode 100644 index 0000000..b5b5b6b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ch.png differ diff --git a/app/packages/link/public/assets/flags/png/ci.png b/app/packages/link/public/assets/flags/png/ci.png new file mode 100644 index 0000000..be12bf4 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ci.png differ diff --git a/app/packages/link/public/assets/flags/png/ck.png b/app/packages/link/public/assets/flags/png/ck.png new file mode 100644 index 0000000..fc2b801 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ck.png differ diff --git a/app/packages/link/public/assets/flags/png/cl.png b/app/packages/link/public/assets/flags/png/cl.png new file mode 100644 index 0000000..3f64f14 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cl.png differ diff --git a/app/packages/link/public/assets/flags/png/cm.png b/app/packages/link/public/assets/flags/png/cm.png new file mode 100644 index 0000000..0e08c11 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cm.png differ diff --git a/app/packages/link/public/assets/flags/png/cn.png b/app/packages/link/public/assets/flags/png/cn.png new file mode 100644 index 0000000..9eabc74 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cn.png differ diff --git a/app/packages/link/public/assets/flags/png/co.png b/app/packages/link/public/assets/flags/png/co.png new file mode 100644 index 0000000..ec91565 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/co.png differ diff --git a/app/packages/link/public/assets/flags/png/cr.png b/app/packages/link/public/assets/flags/png/cr.png new file mode 100644 index 0000000..4b28b26 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cr.png differ diff --git a/app/packages/link/public/assets/flags/png/cu.png b/app/packages/link/public/assets/flags/png/cu.png new file mode 100644 index 0000000..4849993 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cu.png differ diff --git a/app/packages/link/public/assets/flags/png/cv.png b/app/packages/link/public/assets/flags/png/cv.png new file mode 100644 index 0000000..9808523 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cv.png differ diff --git a/app/packages/link/public/assets/flags/png/cw.png b/app/packages/link/public/assets/flags/png/cw.png new file mode 100644 index 0000000..9ccd52c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cw.png differ diff --git a/app/packages/link/public/assets/flags/png/cx.png b/app/packages/link/public/assets/flags/png/cx.png new file mode 100644 index 0000000..efd6d2a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cx.png differ diff --git a/app/packages/link/public/assets/flags/png/cy.png b/app/packages/link/public/assets/flags/png/cy.png new file mode 100644 index 0000000..1a23c85 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cy.png differ diff --git a/app/packages/link/public/assets/flags/png/cz.png b/app/packages/link/public/assets/flags/png/cz.png new file mode 100644 index 0000000..ab26ce1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/cz.png differ diff --git a/app/packages/link/public/assets/flags/png/de.png b/app/packages/link/public/assets/flags/png/de.png new file mode 100644 index 0000000..3b42557 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/de.png differ diff --git a/app/packages/link/public/assets/flags/png/dj.png b/app/packages/link/public/assets/flags/png/dj.png new file mode 100644 index 0000000..dd97cb2 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/dj.png differ diff --git a/app/packages/link/public/assets/flags/png/dk.png b/app/packages/link/public/assets/flags/png/dk.png new file mode 100644 index 0000000..9c312fe Binary files /dev/null and b/app/packages/link/public/assets/flags/png/dk.png differ diff --git a/app/packages/link/public/assets/flags/png/dm.png b/app/packages/link/public/assets/flags/png/dm.png new file mode 100644 index 0000000..4e9c18f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/dm.png differ diff --git a/app/packages/link/public/assets/flags/png/do.png b/app/packages/link/public/assets/flags/png/do.png new file mode 100644 index 0000000..51cecc1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/do.png differ diff --git a/app/packages/link/public/assets/flags/png/dz.png b/app/packages/link/public/assets/flags/png/dz.png new file mode 100644 index 0000000..e151aac Binary files /dev/null and b/app/packages/link/public/assets/flags/png/dz.png differ diff --git a/app/packages/link/public/assets/flags/png/ec.png b/app/packages/link/public/assets/flags/png/ec.png new file mode 100644 index 0000000..4e425a0 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ec.png differ diff --git a/app/packages/link/public/assets/flags/png/ee.png b/app/packages/link/public/assets/flags/png/ee.png new file mode 100644 index 0000000..9ef090b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ee.png differ diff --git a/app/packages/link/public/assets/flags/png/eg.png b/app/packages/link/public/assets/flags/png/eg.png new file mode 100644 index 0000000..9f0d5da Binary files /dev/null and b/app/packages/link/public/assets/flags/png/eg.png differ diff --git a/app/packages/link/public/assets/flags/png/eh.png b/app/packages/link/public/assets/flags/png/eh.png new file mode 100644 index 0000000..6e9bd2d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/eh.png differ diff --git a/app/packages/link/public/assets/flags/png/england.png b/app/packages/link/public/assets/flags/png/england.png new file mode 100644 index 0000000..3b08820 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/england.png differ diff --git a/app/packages/link/public/assets/flags/png/er.png b/app/packages/link/public/assets/flags/png/er.png new file mode 100644 index 0000000..5e2db16 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/er.png differ diff --git a/app/packages/link/public/assets/flags/png/es.png b/app/packages/link/public/assets/flags/png/es.png new file mode 100644 index 0000000..622b66e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/es.png differ diff --git a/app/packages/link/public/assets/flags/png/et.png b/app/packages/link/public/assets/flags/png/et.png new file mode 100644 index 0000000..f39dc15 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/et.png differ diff --git a/app/packages/link/public/assets/flags/png/europeanunion.png b/app/packages/link/public/assets/flags/png/europeanunion.png new file mode 100644 index 0000000..4fb2a4b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/europeanunion.png differ diff --git a/app/packages/link/public/assets/flags/png/fi.png b/app/packages/link/public/assets/flags/png/fi.png new file mode 100644 index 0000000..2e8f68c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/fi.png differ diff --git a/app/packages/link/public/assets/flags/png/fj.png b/app/packages/link/public/assets/flags/png/fj.png new file mode 100644 index 0000000..f4efb7a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/fj.png differ diff --git a/app/packages/link/public/assets/flags/png/fk.png b/app/packages/link/public/assets/flags/png/fk.png new file mode 100644 index 0000000..e06f916 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/fk.png differ diff --git a/app/packages/link/public/assets/flags/png/fm.png b/app/packages/link/public/assets/flags/png/fm.png new file mode 100644 index 0000000..3320cd5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/fm.png differ diff --git a/app/packages/link/public/assets/flags/png/fo.png b/app/packages/link/public/assets/flags/png/fo.png new file mode 100644 index 0000000..975e738 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/fo.png differ diff --git a/app/packages/link/public/assets/flags/png/fr.png b/app/packages/link/public/assets/flags/png/fr.png new file mode 100644 index 0000000..4d2ade1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/fr.png differ diff --git a/app/packages/link/public/assets/flags/png/ga.png b/app/packages/link/public/assets/flags/png/ga.png new file mode 100644 index 0000000..90437a8 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ga.png differ diff --git a/app/packages/link/public/assets/flags/png/gb.png b/app/packages/link/public/assets/flags/png/gb.png new file mode 100644 index 0000000..474a7ad Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gb.png differ diff --git a/app/packages/link/public/assets/flags/png/gd.png b/app/packages/link/public/assets/flags/png/gd.png new file mode 100644 index 0000000..6ac8277 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gd.png differ diff --git a/app/packages/link/public/assets/flags/png/ge.png b/app/packages/link/public/assets/flags/png/ge.png new file mode 100644 index 0000000..e228a7d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ge.png differ diff --git a/app/packages/link/public/assets/flags/png/gf.png b/app/packages/link/public/assets/flags/png/gf.png new file mode 100644 index 0000000..4b07ec5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gf.png differ diff --git a/app/packages/link/public/assets/flags/png/gg.png b/app/packages/link/public/assets/flags/png/gg.png new file mode 100644 index 0000000..0e21b6f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gg.png differ diff --git a/app/packages/link/public/assets/flags/png/gh.png b/app/packages/link/public/assets/flags/png/gh.png new file mode 100644 index 0000000..0b1bd3a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gh.png differ diff --git a/app/packages/link/public/assets/flags/png/gi.png b/app/packages/link/public/assets/flags/png/gi.png new file mode 100644 index 0000000..c10ea18 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gi.png differ diff --git a/app/packages/link/public/assets/flags/png/gl.png b/app/packages/link/public/assets/flags/png/gl.png new file mode 100644 index 0000000..a80c938 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gl.png differ diff --git a/app/packages/link/public/assets/flags/png/gm.png b/app/packages/link/public/assets/flags/png/gm.png new file mode 100644 index 0000000..6e78ce0 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gm.png differ diff --git a/app/packages/link/public/assets/flags/png/gn.png b/app/packages/link/public/assets/flags/png/gn.png new file mode 100644 index 0000000..6d4d53d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gn.png differ diff --git a/app/packages/link/public/assets/flags/png/gp.png b/app/packages/link/public/assets/flags/png/gp.png new file mode 100644 index 0000000..99ecbf0 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gp.png differ diff --git a/app/packages/link/public/assets/flags/png/gq.png b/app/packages/link/public/assets/flags/png/gq.png new file mode 100644 index 0000000..9103934 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gq.png differ diff --git a/app/packages/link/public/assets/flags/png/gr.png b/app/packages/link/public/assets/flags/png/gr.png new file mode 100644 index 0000000..d6914f7 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gr.png differ diff --git a/app/packages/link/public/assets/flags/png/gs.png b/app/packages/link/public/assets/flags/png/gs.png new file mode 100644 index 0000000..6fb20ec Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gs.png differ diff --git a/app/packages/link/public/assets/flags/png/gt.png b/app/packages/link/public/assets/flags/png/gt.png new file mode 100644 index 0000000..50748b9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gt.png differ diff --git a/app/packages/link/public/assets/flags/png/gu.png b/app/packages/link/public/assets/flags/png/gu.png new file mode 100644 index 0000000..7e51f95 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gu.png differ diff --git a/app/packages/link/public/assets/flags/png/gw.png b/app/packages/link/public/assets/flags/png/gw.png new file mode 100644 index 0000000..b2951cd Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gw.png differ diff --git a/app/packages/link/public/assets/flags/png/gy.png b/app/packages/link/public/assets/flags/png/gy.png new file mode 100644 index 0000000..2d71c44 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/gy.png differ diff --git a/app/packages/link/public/assets/flags/png/hk.png b/app/packages/link/public/assets/flags/png/hk.png new file mode 100644 index 0000000..14357c0 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/hk.png differ diff --git a/app/packages/link/public/assets/flags/png/hm.png b/app/packages/link/public/assets/flags/png/hm.png new file mode 100644 index 0000000..11f268d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/hm.png differ diff --git a/app/packages/link/public/assets/flags/png/hn.png b/app/packages/link/public/assets/flags/png/hn.png new file mode 100644 index 0000000..1fdd573 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/hn.png differ diff --git a/app/packages/link/public/assets/flags/png/hr.png b/app/packages/link/public/assets/flags/png/hr.png new file mode 100644 index 0000000..0633e33 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/hr.png differ diff --git a/app/packages/link/public/assets/flags/png/ht.png b/app/packages/link/public/assets/flags/png/ht.png new file mode 100644 index 0000000..060b45f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ht.png differ diff --git a/app/packages/link/public/assets/flags/png/hu.png b/app/packages/link/public/assets/flags/png/hu.png new file mode 100644 index 0000000..18d26d4 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/hu.png differ diff --git a/app/packages/link/public/assets/flags/png/id.png b/app/packages/link/public/assets/flags/png/id.png new file mode 100644 index 0000000..6ff5fa1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/id.png differ diff --git a/app/packages/link/public/assets/flags/png/ie.png b/app/packages/link/public/assets/flags/png/ie.png new file mode 100644 index 0000000..7a77163 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ie.png differ diff --git a/app/packages/link/public/assets/flags/png/il.png b/app/packages/link/public/assets/flags/png/il.png new file mode 100644 index 0000000..d88cee9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/il.png differ diff --git a/app/packages/link/public/assets/flags/png/im.png b/app/packages/link/public/assets/flags/png/im.png new file mode 100644 index 0000000..2d7097d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/im.png differ diff --git a/app/packages/link/public/assets/flags/png/in.png b/app/packages/link/public/assets/flags/png/in.png new file mode 100644 index 0000000..86dee95 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/in.png differ diff --git a/app/packages/link/public/assets/flags/png/io.png b/app/packages/link/public/assets/flags/png/io.png new file mode 100644 index 0000000..6c4cece Binary files /dev/null and b/app/packages/link/public/assets/flags/png/io.png differ diff --git a/app/packages/link/public/assets/flags/png/iq.png b/app/packages/link/public/assets/flags/png/iq.png new file mode 100644 index 0000000..6fa0a84 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/iq.png differ diff --git a/app/packages/link/public/assets/flags/png/ir.png b/app/packages/link/public/assets/flags/png/ir.png new file mode 100644 index 0000000..d0fdcc6 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ir.png differ diff --git a/app/packages/link/public/assets/flags/png/is.png b/app/packages/link/public/assets/flags/png/is.png new file mode 100644 index 0000000..0bf68a3 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/is.png differ diff --git a/app/packages/link/public/assets/flags/png/it.png b/app/packages/link/public/assets/flags/png/it.png new file mode 100644 index 0000000..41410e9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/it.png differ diff --git a/app/packages/link/public/assets/flags/png/je.png b/app/packages/link/public/assets/flags/png/je.png new file mode 100644 index 0000000..d16a0d5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/je.png differ diff --git a/app/packages/link/public/assets/flags/png/jm.png b/app/packages/link/public/assets/flags/png/jm.png new file mode 100644 index 0000000..885309a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/jm.png differ diff --git a/app/packages/link/public/assets/flags/png/jo.png b/app/packages/link/public/assets/flags/png/jo.png new file mode 100644 index 0000000..e40e328 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/jo.png differ diff --git a/app/packages/link/public/assets/flags/png/jp.png b/app/packages/link/public/assets/flags/png/jp.png new file mode 100644 index 0000000..82a9241 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/jp.png differ diff --git a/app/packages/link/public/assets/flags/png/ke.png b/app/packages/link/public/assets/flags/png/ke.png new file mode 100644 index 0000000..e3b26c2 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ke.png differ diff --git a/app/packages/link/public/assets/flags/png/kg.png b/app/packages/link/public/assets/flags/png/kg.png new file mode 100644 index 0000000..30b9e40 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/kg.png differ diff --git a/app/packages/link/public/assets/flags/png/kh.png b/app/packages/link/public/assets/flags/png/kh.png new file mode 100644 index 0000000..8611a0f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/kh.png differ diff --git a/app/packages/link/public/assets/flags/png/ki.png b/app/packages/link/public/assets/flags/png/ki.png new file mode 100644 index 0000000..c4ef73f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ki.png differ diff --git a/app/packages/link/public/assets/flags/png/km.png b/app/packages/link/public/assets/flags/png/km.png new file mode 100644 index 0000000..be1d580 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/km.png differ diff --git a/app/packages/link/public/assets/flags/png/kn.png b/app/packages/link/public/assets/flags/png/kn.png new file mode 100644 index 0000000..e20dc1c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/kn.png differ diff --git a/app/packages/link/public/assets/flags/png/kp.png b/app/packages/link/public/assets/flags/png/kp.png new file mode 100644 index 0000000..01332b7 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/kp.png differ diff --git a/app/packages/link/public/assets/flags/png/kr.png b/app/packages/link/public/assets/flags/png/kr.png new file mode 100644 index 0000000..b080793 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/kr.png differ diff --git a/app/packages/link/public/assets/flags/png/kw.png b/app/packages/link/public/assets/flags/png/kw.png new file mode 100644 index 0000000..0e9cdc1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/kw.png differ diff --git a/app/packages/link/public/assets/flags/png/ky.png b/app/packages/link/public/assets/flags/png/ky.png new file mode 100644 index 0000000..108b01c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ky.png differ diff --git a/app/packages/link/public/assets/flags/png/kz.png b/app/packages/link/public/assets/flags/png/kz.png new file mode 100644 index 0000000..f568d63 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/kz.png differ diff --git a/app/packages/link/public/assets/flags/png/la.png b/app/packages/link/public/assets/flags/png/la.png new file mode 100644 index 0000000..ea1cc9f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/la.png differ diff --git a/app/packages/link/public/assets/flags/png/lb.png b/app/packages/link/public/assets/flags/png/lb.png new file mode 100644 index 0000000..90d6264 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/lb.png differ diff --git a/app/packages/link/public/assets/flags/png/lc.png b/app/packages/link/public/assets/flags/png/lc.png new file mode 100644 index 0000000..35e7180 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/lc.png differ diff --git a/app/packages/link/public/assets/flags/png/li.png b/app/packages/link/public/assets/flags/png/li.png new file mode 100644 index 0000000..5a81c2f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/li.png differ diff --git a/app/packages/link/public/assets/flags/png/lk.png b/app/packages/link/public/assets/flags/png/lk.png new file mode 100644 index 0000000..6028bd9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/lk.png differ diff --git a/app/packages/link/public/assets/flags/png/lr.png b/app/packages/link/public/assets/flags/png/lr.png new file mode 100644 index 0000000..5706363 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/lr.png differ diff --git a/app/packages/link/public/assets/flags/png/ls.png b/app/packages/link/public/assets/flags/png/ls.png new file mode 100644 index 0000000..39cca6e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ls.png differ diff --git a/app/packages/link/public/assets/flags/png/lt.png b/app/packages/link/public/assets/flags/png/lt.png new file mode 100644 index 0000000..751a449 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/lt.png differ diff --git a/app/packages/link/public/assets/flags/png/lu.png b/app/packages/link/public/assets/flags/png/lu.png new file mode 100644 index 0000000..db84921 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/lu.png differ diff --git a/app/packages/link/public/assets/flags/png/lv.png b/app/packages/link/public/assets/flags/png/lv.png new file mode 100644 index 0000000..d5cafeb Binary files /dev/null and b/app/packages/link/public/assets/flags/png/lv.png differ diff --git a/app/packages/link/public/assets/flags/png/ly.png b/app/packages/link/public/assets/flags/png/ly.png new file mode 100644 index 0000000..06e62ec Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ly.png differ diff --git a/app/packages/link/public/assets/flags/png/ma.png b/app/packages/link/public/assets/flags/png/ma.png new file mode 100644 index 0000000..e31a28c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ma.png differ diff --git a/app/packages/link/public/assets/flags/png/mc.png b/app/packages/link/public/assets/flags/png/mc.png new file mode 100644 index 0000000..5cd9c66 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mc.png differ diff --git a/app/packages/link/public/assets/flags/png/md.png b/app/packages/link/public/assets/flags/png/md.png new file mode 100644 index 0000000..f9eb0c1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/md.png differ diff --git a/app/packages/link/public/assets/flags/png/me.png b/app/packages/link/public/assets/flags/png/me.png new file mode 100644 index 0000000..a0172cc Binary files /dev/null and b/app/packages/link/public/assets/flags/png/me.png differ diff --git a/app/packages/link/public/assets/flags/png/mf.png b/app/packages/link/public/assets/flags/png/mf.png new file mode 100644 index 0000000..72d97e8 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mf.png differ diff --git a/app/packages/link/public/assets/flags/png/mg.png b/app/packages/link/public/assets/flags/png/mg.png new file mode 100644 index 0000000..cadd5ac Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mg.png differ diff --git a/app/packages/link/public/assets/flags/png/mh.png b/app/packages/link/public/assets/flags/png/mh.png new file mode 100644 index 0000000..e2da726 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mh.png differ diff --git a/app/packages/link/public/assets/flags/png/mk.png b/app/packages/link/public/assets/flags/png/mk.png new file mode 100644 index 0000000..6f8def0 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mk.png differ diff --git a/app/packages/link/public/assets/flags/png/ml.png b/app/packages/link/public/assets/flags/png/ml.png new file mode 100644 index 0000000..b9d44e3 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ml.png differ diff --git a/app/packages/link/public/assets/flags/png/mm.png b/app/packages/link/public/assets/flags/png/mm.png new file mode 100644 index 0000000..c589588 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mm.png differ diff --git a/app/packages/link/public/assets/flags/png/mn.png b/app/packages/link/public/assets/flags/png/mn.png new file mode 100644 index 0000000..de9f7cc Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mn.png differ diff --git a/app/packages/link/public/assets/flags/png/mo.png b/app/packages/link/public/assets/flags/png/mo.png new file mode 100644 index 0000000..07e62bc Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mo.png differ diff --git a/app/packages/link/public/assets/flags/png/mp.png b/app/packages/link/public/assets/flags/png/mp.png new file mode 100644 index 0000000..2f15ad2 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mp.png differ diff --git a/app/packages/link/public/assets/flags/png/mq.png b/app/packages/link/public/assets/flags/png/mq.png new file mode 100644 index 0000000..1c6e9ad Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mq.png differ diff --git a/app/packages/link/public/assets/flags/png/mr.png b/app/packages/link/public/assets/flags/png/mr.png new file mode 100644 index 0000000..a8af956 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mr.png differ diff --git a/app/packages/link/public/assets/flags/png/ms.png b/app/packages/link/public/assets/flags/png/ms.png new file mode 100644 index 0000000..50c5eaf Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ms.png differ diff --git a/app/packages/link/public/assets/flags/png/mt.png b/app/packages/link/public/assets/flags/png/mt.png new file mode 100644 index 0000000..651108f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mt.png differ diff --git a/app/packages/link/public/assets/flags/png/mu.png b/app/packages/link/public/assets/flags/png/mu.png new file mode 100644 index 0000000..ef2c58e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mu.png differ diff --git a/app/packages/link/public/assets/flags/png/mv.png b/app/packages/link/public/assets/flags/png/mv.png new file mode 100644 index 0000000..25a0999 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mv.png differ diff --git a/app/packages/link/public/assets/flags/png/mw.png b/app/packages/link/public/assets/flags/png/mw.png new file mode 100644 index 0000000..3072262 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mw.png differ diff --git a/app/packages/link/public/assets/flags/png/mx.png b/app/packages/link/public/assets/flags/png/mx.png new file mode 100644 index 0000000..a4dd507 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mx.png differ diff --git a/app/packages/link/public/assets/flags/png/my.png b/app/packages/link/public/assets/flags/png/my.png new file mode 100644 index 0000000..827d19e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/my.png differ diff --git a/app/packages/link/public/assets/flags/png/mz.png b/app/packages/link/public/assets/flags/png/mz.png new file mode 100644 index 0000000..ee6a34f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/mz.png differ diff --git a/app/packages/link/public/assets/flags/png/na.png b/app/packages/link/public/assets/flags/png/na.png new file mode 100644 index 0000000..85362e4 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/na.png differ diff --git a/app/packages/link/public/assets/flags/png/nc.png b/app/packages/link/public/assets/flags/png/nc.png new file mode 100644 index 0000000..b29da12 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/nc.png differ diff --git a/app/packages/link/public/assets/flags/png/ne.png b/app/packages/link/public/assets/flags/png/ne.png new file mode 100644 index 0000000..f616641 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ne.png differ diff --git a/app/packages/link/public/assets/flags/png/nf.png b/app/packages/link/public/assets/flags/png/nf.png new file mode 100644 index 0000000..22ba718 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/nf.png differ diff --git a/app/packages/link/public/assets/flags/png/ng.png b/app/packages/link/public/assets/flags/png/ng.png new file mode 100644 index 0000000..c0117c9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ng.png differ diff --git a/app/packages/link/public/assets/flags/png/ni.png b/app/packages/link/public/assets/flags/png/ni.png new file mode 100644 index 0000000..14d677f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ni.png differ diff --git a/app/packages/link/public/assets/flags/png/nl.png b/app/packages/link/public/assets/flags/png/nl.png new file mode 100644 index 0000000..3b5dba2 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/nl.png differ diff --git a/app/packages/link/public/assets/flags/png/no.png b/app/packages/link/public/assets/flags/png/no.png new file mode 100644 index 0000000..a0d1537 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/no.png differ diff --git a/app/packages/link/public/assets/flags/png/northerncyprus.png b/app/packages/link/public/assets/flags/png/northerncyprus.png new file mode 100644 index 0000000..33b16ff Binary files /dev/null and b/app/packages/link/public/assets/flags/png/northerncyprus.png differ diff --git a/app/packages/link/public/assets/flags/png/np.png b/app/packages/link/public/assets/flags/png/np.png new file mode 100644 index 0000000..86cc5ff Binary files /dev/null and b/app/packages/link/public/assets/flags/png/np.png differ diff --git a/app/packages/link/public/assets/flags/png/nr.png b/app/packages/link/public/assets/flags/png/nr.png new file mode 100644 index 0000000..2d401f3 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/nr.png differ diff --git a/app/packages/link/public/assets/flags/png/nu.png b/app/packages/link/public/assets/flags/png/nu.png new file mode 100644 index 0000000..7c0915f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/nu.png differ diff --git a/app/packages/link/public/assets/flags/png/nz.png b/app/packages/link/public/assets/flags/png/nz.png new file mode 100644 index 0000000..cf3101b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/nz.png differ diff --git a/app/packages/link/public/assets/flags/png/om.png b/app/packages/link/public/assets/flags/png/om.png new file mode 100644 index 0000000..b4814ca Binary files /dev/null and b/app/packages/link/public/assets/flags/png/om.png differ diff --git a/app/packages/link/public/assets/flags/png/pa.png b/app/packages/link/public/assets/flags/png/pa.png new file mode 100644 index 0000000..90ae3b1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pa.png differ diff --git a/app/packages/link/public/assets/flags/png/pe.png b/app/packages/link/public/assets/flags/png/pe.png new file mode 100644 index 0000000..3fedaaa Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pe.png differ diff --git a/app/packages/link/public/assets/flags/png/pf.png b/app/packages/link/public/assets/flags/png/pf.png new file mode 100644 index 0000000..27ac8a9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pf.png differ diff --git a/app/packages/link/public/assets/flags/png/pg.png b/app/packages/link/public/assets/flags/png/pg.png new file mode 100644 index 0000000..4dc1f15 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pg.png differ diff --git a/app/packages/link/public/assets/flags/png/ph.png b/app/packages/link/public/assets/flags/png/ph.png new file mode 100644 index 0000000..73bfc84 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ph.png differ diff --git a/app/packages/link/public/assets/flags/png/pk.png b/app/packages/link/public/assets/flags/png/pk.png new file mode 100644 index 0000000..898b32c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pk.png differ diff --git a/app/packages/link/public/assets/flags/png/pl.png b/app/packages/link/public/assets/flags/png/pl.png new file mode 100644 index 0000000..fe4051a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pl.png differ diff --git a/app/packages/link/public/assets/flags/png/pm.png b/app/packages/link/public/assets/flags/png/pm.png new file mode 100644 index 0000000..3d7d272 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pm.png differ diff --git a/app/packages/link/public/assets/flags/png/pn.png b/app/packages/link/public/assets/flags/png/pn.png new file mode 100644 index 0000000..ae722f3 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pn.png differ diff --git a/app/packages/link/public/assets/flags/png/pr.png b/app/packages/link/public/assets/flags/png/pr.png new file mode 100644 index 0000000..3d36362 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pr.png differ diff --git a/app/packages/link/public/assets/flags/png/ps.png b/app/packages/link/public/assets/flags/png/ps.png new file mode 100644 index 0000000..17fea63 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ps.png differ diff --git a/app/packages/link/public/assets/flags/png/pt.png b/app/packages/link/public/assets/flags/png/pt.png new file mode 100644 index 0000000..eff4b22 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pt.png differ diff --git a/app/packages/link/public/assets/flags/png/pw.png b/app/packages/link/public/assets/flags/png/pw.png new file mode 100644 index 0000000..b72696e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/pw.png differ diff --git a/app/packages/link/public/assets/flags/png/py.png b/app/packages/link/public/assets/flags/png/py.png new file mode 100644 index 0000000..d8fde78 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/py.png differ diff --git a/app/packages/link/public/assets/flags/png/qa.png b/app/packages/link/public/assets/flags/png/qa.png new file mode 100644 index 0000000..eba961c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/qa.png differ diff --git a/app/packages/link/public/assets/flags/png/re.png b/app/packages/link/public/assets/flags/png/re.png new file mode 100644 index 0000000..4d2ade1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/re.png differ diff --git a/app/packages/link/public/assets/flags/png/ro.png b/app/packages/link/public/assets/flags/png/ro.png new file mode 100644 index 0000000..e4c7a7e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ro.png differ diff --git a/app/packages/link/public/assets/flags/png/rs.png b/app/packages/link/public/assets/flags/png/rs.png new file mode 100644 index 0000000..fd7900b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/rs.png differ diff --git a/app/packages/link/public/assets/flags/png/ru.png b/app/packages/link/public/assets/flags/png/ru.png new file mode 100644 index 0000000..02b6557 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ru.png differ diff --git a/app/packages/link/public/assets/flags/png/rw.png b/app/packages/link/public/assets/flags/png/rw.png new file mode 100644 index 0000000..ebe652b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/rw.png differ diff --git a/app/packages/link/public/assets/flags/png/sa.png b/app/packages/link/public/assets/flags/png/sa.png new file mode 100644 index 0000000..414f6a8 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sa.png differ diff --git a/app/packages/link/public/assets/flags/png/sb.png b/app/packages/link/public/assets/flags/png/sb.png new file mode 100644 index 0000000..b26138e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sb.png differ diff --git a/app/packages/link/public/assets/flags/png/sc.png b/app/packages/link/public/assets/flags/png/sc.png new file mode 100644 index 0000000..1787a83 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sc.png differ diff --git a/app/packages/link/public/assets/flags/png/scotland.png b/app/packages/link/public/assets/flags/png/scotland.png new file mode 100644 index 0000000..3155f5d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/scotland.png differ diff --git a/app/packages/link/public/assets/flags/png/sd.png b/app/packages/link/public/assets/flags/png/sd.png new file mode 100644 index 0000000..3716c26 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sd.png differ diff --git a/app/packages/link/public/assets/flags/png/se.png b/app/packages/link/public/assets/flags/png/se.png new file mode 100644 index 0000000..bd27bdd Binary files /dev/null and b/app/packages/link/public/assets/flags/png/se.png differ diff --git a/app/packages/link/public/assets/flags/png/sg.png b/app/packages/link/public/assets/flags/png/sg.png new file mode 100644 index 0000000..0023603 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sg.png differ diff --git a/app/packages/link/public/assets/flags/png/sh.png b/app/packages/link/public/assets/flags/png/sh.png new file mode 100644 index 0000000..0981bbd Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sh.png differ diff --git a/app/packages/link/public/assets/flags/png/si.png b/app/packages/link/public/assets/flags/png/si.png new file mode 100644 index 0000000..dfa04d7 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/si.png differ diff --git a/app/packages/link/public/assets/flags/png/sj.png b/app/packages/link/public/assets/flags/png/sj.png new file mode 100644 index 0000000..c51f0df Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sj.png differ diff --git a/app/packages/link/public/assets/flags/png/sk.png b/app/packages/link/public/assets/flags/png/sk.png new file mode 100644 index 0000000..4c4f35b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sk.png differ diff --git a/app/packages/link/public/assets/flags/png/sl.png b/app/packages/link/public/assets/flags/png/sl.png new file mode 100644 index 0000000..5813a8b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sl.png differ diff --git a/app/packages/link/public/assets/flags/png/sm.png b/app/packages/link/public/assets/flags/png/sm.png new file mode 100644 index 0000000..1134333 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sm.png differ diff --git a/app/packages/link/public/assets/flags/png/sn.png b/app/packages/link/public/assets/flags/png/sn.png new file mode 100644 index 0000000..377c388 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sn.png differ diff --git a/app/packages/link/public/assets/flags/png/so.png b/app/packages/link/public/assets/flags/png/so.png new file mode 100644 index 0000000..680da5e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/so.png differ diff --git a/app/packages/link/public/assets/flags/png/southossetia.png b/app/packages/link/public/assets/flags/png/southossetia.png new file mode 100644 index 0000000..7d1f7a0 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/southossetia.png differ diff --git a/app/packages/link/public/assets/flags/png/sr.png b/app/packages/link/public/assets/flags/png/sr.png new file mode 100644 index 0000000..af1ac09 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sr.png differ diff --git a/app/packages/link/public/assets/flags/png/ss.png b/app/packages/link/public/assets/flags/png/ss.png new file mode 100644 index 0000000..06725d3 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ss.png differ diff --git a/app/packages/link/public/assets/flags/png/st.png b/app/packages/link/public/assets/flags/png/st.png new file mode 100644 index 0000000..d9c7793 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/st.png differ diff --git a/app/packages/link/public/assets/flags/png/sv.png b/app/packages/link/public/assets/flags/png/sv.png new file mode 100644 index 0000000..d68e3b3 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sv.png differ diff --git a/app/packages/link/public/assets/flags/png/sx.png b/app/packages/link/public/assets/flags/png/sx.png new file mode 100644 index 0000000..65c5f5d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sx.png differ diff --git a/app/packages/link/public/assets/flags/png/sy.png b/app/packages/link/public/assets/flags/png/sy.png new file mode 100644 index 0000000..d101de5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sy.png differ diff --git a/app/packages/link/public/assets/flags/png/sz.png b/app/packages/link/public/assets/flags/png/sz.png new file mode 100644 index 0000000..3a1add7 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/sz.png differ diff --git a/app/packages/link/public/assets/flags/png/tc.png b/app/packages/link/public/assets/flags/png/tc.png new file mode 100644 index 0000000..22281d9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tc.png differ diff --git a/app/packages/link/public/assets/flags/png/td.png b/app/packages/link/public/assets/flags/png/td.png new file mode 100644 index 0000000..cb8e8ad Binary files /dev/null and b/app/packages/link/public/assets/flags/png/td.png differ diff --git a/app/packages/link/public/assets/flags/png/tf.png b/app/packages/link/public/assets/flags/png/tf.png new file mode 100644 index 0000000..d95911a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tf.png differ diff --git a/app/packages/link/public/assets/flags/png/tg.png b/app/packages/link/public/assets/flags/png/tg.png new file mode 100644 index 0000000..beabe7b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tg.png differ diff --git a/app/packages/link/public/assets/flags/png/th.png b/app/packages/link/public/assets/flags/png/th.png new file mode 100644 index 0000000..2167086 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/th.png differ diff --git a/app/packages/link/public/assets/flags/png/tj.png b/app/packages/link/public/assets/flags/png/tj.png new file mode 100644 index 0000000..272271f Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tj.png differ diff --git a/app/packages/link/public/assets/flags/png/tk.png b/app/packages/link/public/assets/flags/png/tk.png new file mode 100644 index 0000000..ff29009 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tk.png differ diff --git a/app/packages/link/public/assets/flags/png/tl.png b/app/packages/link/public/assets/flags/png/tl.png new file mode 100644 index 0000000..043e99c Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tl.png differ diff --git a/app/packages/link/public/assets/flags/png/tm.png b/app/packages/link/public/assets/flags/png/tm.png new file mode 100644 index 0000000..6a75880 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tm.png differ diff --git a/app/packages/link/public/assets/flags/png/tn.png b/app/packages/link/public/assets/flags/png/tn.png new file mode 100644 index 0000000..e927ee5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tn.png differ diff --git a/app/packages/link/public/assets/flags/png/to.png b/app/packages/link/public/assets/flags/png/to.png new file mode 100644 index 0000000..b3eab79 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/to.png differ diff --git a/app/packages/link/public/assets/flags/png/tr.png b/app/packages/link/public/assets/flags/png/tr.png new file mode 100644 index 0000000..3290b94 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tr.png differ diff --git a/app/packages/link/public/assets/flags/png/tt.png b/app/packages/link/public/assets/flags/png/tt.png new file mode 100644 index 0000000..ff2500e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tt.png differ diff --git a/app/packages/link/public/assets/flags/png/tv.png b/app/packages/link/public/assets/flags/png/tv.png new file mode 100644 index 0000000..ad367f5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tv.png differ diff --git a/app/packages/link/public/assets/flags/png/tw.png b/app/packages/link/public/assets/flags/png/tw.png new file mode 100644 index 0000000..587f509 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tw.png differ diff --git a/app/packages/link/public/assets/flags/png/tz.png b/app/packages/link/public/assets/flags/png/tz.png new file mode 100644 index 0000000..236dbeb Binary files /dev/null and b/app/packages/link/public/assets/flags/png/tz.png differ diff --git a/app/packages/link/public/assets/flags/png/ua.png b/app/packages/link/public/assets/flags/png/ua.png new file mode 100644 index 0000000..2e0030d Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ua.png differ diff --git a/app/packages/link/public/assets/flags/png/ug.png b/app/packages/link/public/assets/flags/png/ug.png new file mode 100644 index 0000000..ee2e4d1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ug.png differ diff --git a/app/packages/link/public/assets/flags/png/um.png b/app/packages/link/public/assets/flags/png/um.png new file mode 100644 index 0000000..d9c63a1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/um.png differ diff --git a/app/packages/link/public/assets/flags/png/unitednations.png b/app/packages/link/public/assets/flags/png/unitednations.png new file mode 100644 index 0000000..f804997 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/unitednations.png differ diff --git a/app/packages/link/public/assets/flags/png/us.png b/app/packages/link/public/assets/flags/png/us.png new file mode 100644 index 0000000..d9c63a1 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/us.png differ diff --git a/app/packages/link/public/assets/flags/png/uy.png b/app/packages/link/public/assets/flags/png/uy.png new file mode 100644 index 0000000..c0d0703 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/uy.png differ diff --git a/app/packages/link/public/assets/flags/png/uz.png b/app/packages/link/public/assets/flags/png/uz.png new file mode 100644 index 0000000..9247ebd Binary files /dev/null and b/app/packages/link/public/assets/flags/png/uz.png differ diff --git a/app/packages/link/public/assets/flags/png/va.png b/app/packages/link/public/assets/flags/png/va.png new file mode 100644 index 0000000..32f1a38 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/va.png differ diff --git a/app/packages/link/public/assets/flags/png/vc.png b/app/packages/link/public/assets/flags/png/vc.png new file mode 100644 index 0000000..7ba9ee9 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/vc.png differ diff --git a/app/packages/link/public/assets/flags/png/ve.png b/app/packages/link/public/assets/flags/png/ve.png new file mode 100644 index 0000000..15a47f4 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ve.png differ diff --git a/app/packages/link/public/assets/flags/png/vg.png b/app/packages/link/public/assets/flags/png/vg.png new file mode 100644 index 0000000..860f694 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/vg.png differ diff --git a/app/packages/link/public/assets/flags/png/vi.png b/app/packages/link/public/assets/flags/png/vi.png new file mode 100644 index 0000000..2675ade Binary files /dev/null and b/app/packages/link/public/assets/flags/png/vi.png differ diff --git a/app/packages/link/public/assets/flags/png/vn.png b/app/packages/link/public/assets/flags/png/vn.png new file mode 100644 index 0000000..dbc1270 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/vn.png differ diff --git a/app/packages/link/public/assets/flags/png/vu.png b/app/packages/link/public/assets/flags/png/vu.png new file mode 100644 index 0000000..713f2b5 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/vu.png differ diff --git a/app/packages/link/public/assets/flags/png/wales.png b/app/packages/link/public/assets/flags/png/wales.png new file mode 100644 index 0000000..ca585cf Binary files /dev/null and b/app/packages/link/public/assets/flags/png/wales.png differ diff --git a/app/packages/link/public/assets/flags/png/wf.png b/app/packages/link/public/assets/flags/png/wf.png new file mode 100644 index 0000000..57a1e6e Binary files /dev/null and b/app/packages/link/public/assets/flags/png/wf.png differ diff --git a/app/packages/link/public/assets/flags/png/ws.png b/app/packages/link/public/assets/flags/png/ws.png new file mode 100644 index 0000000..f3375b7 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ws.png differ diff --git a/app/packages/link/public/assets/flags/png/xk.png b/app/packages/link/public/assets/flags/png/xk.png new file mode 100644 index 0000000..461e57a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/xk.png differ diff --git a/app/packages/link/public/assets/flags/png/ye.png b/app/packages/link/public/assets/flags/png/ye.png new file mode 100644 index 0000000..09d52f6 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/ye.png differ diff --git a/app/packages/link/public/assets/flags/png/yt.png b/app/packages/link/public/assets/flags/png/yt.png new file mode 100644 index 0000000..9aae53b Binary files /dev/null and b/app/packages/link/public/assets/flags/png/yt.png differ diff --git a/app/packages/link/public/assets/flags/png/za.png b/app/packages/link/public/assets/flags/png/za.png new file mode 100644 index 0000000..11886f3 Binary files /dev/null and b/app/packages/link/public/assets/flags/png/za.png differ diff --git a/app/packages/link/public/assets/flags/png/zm.png b/app/packages/link/public/assets/flags/png/zm.png new file mode 100644 index 0000000..a27c7fd Binary files /dev/null and b/app/packages/link/public/assets/flags/png/zm.png differ diff --git a/app/packages/link/public/assets/flags/png/zw.png b/app/packages/link/public/assets/flags/png/zw.png new file mode 100644 index 0000000..0bbf08a Binary files /dev/null and b/app/packages/link/public/assets/flags/png/zw.png differ diff --git a/app/packages/link/public/assets/flags/svg/LICENSE.txt b/app/packages/link/public/assets/flags/svg/LICENSE.txt new file mode 100644 index 0000000..1a86627 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Steven Skelton + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/app/packages/link/public/assets/flags/svg/ObtainedFrom.txt b/app/packages/link/public/assets/flags/svg/ObtainedFrom.txt new file mode 100644 index 0000000..23ab8c0 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ObtainedFrom.txt @@ -0,0 +1,5 @@ +This folder was obtained from and included as part of: + +https://github.com/stevenrskelton/flag-icon + +MIT License : http://opensource.org/licenses/MIT \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/ab.svg b/app/packages/link/public/assets/flags/svg/ab.svg new file mode 100644 index 0000000..a39478d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ab.svg @@ -0,0 +1,195 @@ + + + + + + image/svg+xml + + + + + + + Flag of Abkhazia + hand shape probably wrong + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ad.svg b/app/packages/link/public/assets/flags/svg/ad.svg new file mode 100644 index 0000000..9190d9e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ad.svg @@ -0,0 +1,152 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ae.svg b/app/packages/link/public/assets/flags/svg/ae.svg new file mode 100644 index 0000000..e634982 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ae.svg @@ -0,0 +1,44 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/af.svg b/app/packages/link/public/assets/flags/svg/af.svg new file mode 100644 index 0000000..937edca --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/af.svg @@ -0,0 +1,779 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ag.svg b/app/packages/link/public/assets/flags/svg/ag.svg new file mode 100644 index 0000000..c7450f0 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ag.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ai.svg b/app/packages/link/public/assets/flags/svg/ai.svg new file mode 100644 index 0000000..69c5041 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ai.svg @@ -0,0 +1,791 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/al.svg b/app/packages/link/public/assets/flags/svg/al.svg new file mode 100644 index 0000000..e9709cc --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/al.svg @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/am.svg b/app/packages/link/public/assets/flags/svg/am.svg new file mode 100644 index 0000000..03054df --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/am.svg @@ -0,0 +1,16 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ao.svg b/app/packages/link/public/assets/flags/svg/ao.svg new file mode 100644 index 0000000..2e5ca47 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ao.svg @@ -0,0 +1,39 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/aq.svg b/app/packages/link/public/assets/flags/svg/aq.svg new file mode 100644 index 0000000..40dec47 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/aq.svg @@ -0,0 +1,20 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ar.svg b/app/packages/link/public/assets/flags/svg/ar.svg new file mode 100644 index 0000000..c36b65a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ar.svg @@ -0,0 +1,160 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/as.svg b/app/packages/link/public/assets/flags/svg/as.svg new file mode 100644 index 0000000..b3585f3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/as.svg @@ -0,0 +1,120 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/at.svg b/app/packages/link/public/assets/flags/svg/at.svg new file mode 100644 index 0000000..388a6b8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/at.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/au.svg b/app/packages/link/public/assets/flags/svg/au.svg new file mode 100644 index 0000000..c064c74 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/au.svg @@ -0,0 +1,31 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/aw.svg b/app/packages/link/public/assets/flags/svg/aw.svg new file mode 100644 index 0000000..ac8440a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/aw.svg @@ -0,0 +1,210 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ax.svg b/app/packages/link/public/assets/flags/svg/ax.svg new file mode 100644 index 0000000..fd17f0b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ax.svg @@ -0,0 +1,27 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/az.svg b/app/packages/link/public/assets/flags/svg/az.svg new file mode 100644 index 0000000..d77a2f5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/az.svg @@ -0,0 +1,49 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ba.svg b/app/packages/link/public/assets/flags/svg/ba.svg new file mode 100644 index 0000000..4336c07 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ba.svg @@ -0,0 +1,53 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bb.svg b/app/packages/link/public/assets/flags/svg/bb.svg new file mode 100644 index 0000000..2bf861d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bb.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bd.svg b/app/packages/link/public/assets/flags/svg/bd.svg new file mode 100644 index 0000000..4b9d0c0 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bd.svg @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/be.svg b/app/packages/link/public/assets/flags/svg/be.svg new file mode 100644 index 0000000..891501c --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/be.svg @@ -0,0 +1,40 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bf.svg b/app/packages/link/public/assets/flags/svg/bf.svg new file mode 100644 index 0000000..6d354c6 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bf.svg @@ -0,0 +1,19 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bg.svg b/app/packages/link/public/assets/flags/svg/bg.svg new file mode 100644 index 0000000..2cf07bf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bg.svg @@ -0,0 +1,19 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bh.svg b/app/packages/link/public/assets/flags/svg/bh.svg new file mode 100644 index 0000000..a73eb8d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bh.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bi.svg b/app/packages/link/public/assets/flags/svg/bi.svg new file mode 100644 index 0000000..20a3533 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bi.svg @@ -0,0 +1,29 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bj.svg b/app/packages/link/public/assets/flags/svg/bj.svg new file mode 100644 index 0000000..132f9b5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bj.svg @@ -0,0 +1,47 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bl.svg b/app/packages/link/public/assets/flags/svg/bl.svg new file mode 100644 index 0000000..8b6f589 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bl.svg @@ -0,0 +1,4204 @@ + + + + + + image/svg+xml + + Blason de corcieux + 26-11-2006 + + + Antoine Fabrice (Darkbob) + + + + + + + blason corcieux + + + + + + + + + + + + Flag of Canton of Valais (Wallis) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bm.svg b/app/packages/link/public/assets/flags/svg/bm.svg new file mode 100644 index 0000000..b2d83f5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bm.svg @@ -0,0 +1,363 @@ + + + + + + + Bermuda + + + + + caribbean + america + flag + sign + + + + + Caleb Moore + + + + + Caleb Moore + + + + + Caleb Moore + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bn.svg b/app/packages/link/public/assets/flags/svg/bn.svg new file mode 100644 index 0000000..2cb386e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bn.svg @@ -0,0 +1,137 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bo.svg b/app/packages/link/public/assets/flags/svg/bo.svg new file mode 100644 index 0000000..5952c30 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bo.svg @@ -0,0 +1,37 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bq.svg b/app/packages/link/public/assets/flags/svg/bq.svg new file mode 100644 index 0000000..5da2132 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bq.svg @@ -0,0 +1,17 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/br.svg b/app/packages/link/public/assets/flags/svg/br.svg new file mode 100644 index 0000000..df11320 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/br.svg @@ -0,0 +1,88 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bs.svg b/app/packages/link/public/assets/flags/svg/bs.svg new file mode 100644 index 0000000..570d7a5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bs.svg @@ -0,0 +1,24 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bt.svg b/app/packages/link/public/assets/flags/svg/bt.svg new file mode 100644 index 0000000..fada20a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bt.svg @@ -0,0 +1,217 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bv.svg b/app/packages/link/public/assets/flags/svg/bv.svg new file mode 100644 index 0000000..104b29b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bv.svg @@ -0,0 +1,26 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bw.svg b/app/packages/link/public/assets/flags/svg/bw.svg new file mode 100644 index 0000000..d7f0c92 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bw.svg @@ -0,0 +1,39 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/by.svg b/app/packages/link/public/assets/flags/svg/by.svg new file mode 100644 index 0000000..2601680 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/by.svg @@ -0,0 +1,266 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/bz.svg b/app/packages/link/public/assets/flags/svg/bz.svg new file mode 100644 index 0000000..d352f9a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/bz.svg @@ -0,0 +1,302 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ca.svg b/app/packages/link/public/assets/flags/svg/ca.svg new file mode 100644 index 0000000..eb528d9 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ca.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cc.svg b/app/packages/link/public/assets/flags/svg/cc.svg new file mode 100644 index 0000000..d250b05 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cc.svg @@ -0,0 +1,29 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cd.svg b/app/packages/link/public/assets/flags/svg/cd.svg new file mode 100644 index 0000000..0bc7936 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cd.svg @@ -0,0 +1,16 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cf.svg b/app/packages/link/public/assets/flags/svg/cf.svg new file mode 100644 index 0000000..ee8a291 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cf.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cg.svg b/app/packages/link/public/assets/flags/svg/cg.svg new file mode 100644 index 0000000..76cd8ea --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cg.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ch.svg b/app/packages/link/public/assets/flags/svg/ch.svg new file mode 100644 index 0000000..3648330 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ch.svg @@ -0,0 +1,20 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ci.svg b/app/packages/link/public/assets/flags/svg/ci.svg new file mode 100644 index 0000000..4a6fc7f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ci.svg @@ -0,0 +1,39 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ck.svg b/app/packages/link/public/assets/flags/svg/ck.svg new file mode 100644 index 0000000..57efc07 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ck.svg @@ -0,0 +1,38 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cl.svg b/app/packages/link/public/assets/flags/svg/cl.svg new file mode 100644 index 0000000..ffa1d20 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cl.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cm.svg b/app/packages/link/public/assets/flags/svg/cm.svg new file mode 100644 index 0000000..a1186c3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cm.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cn.svg b/app/packages/link/public/assets/flags/svg/cn.svg new file mode 100644 index 0000000..c7bc4b1 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cn.svg @@ -0,0 +1,20 @@ + + + + Flag of the People's Republic of China + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/co.svg b/app/packages/link/public/assets/flags/svg/co.svg new file mode 100644 index 0000000..9a220d1 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/co.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cr.svg b/app/packages/link/public/assets/flags/svg/cr.svg new file mode 100644 index 0000000..79e5dd2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cr.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cu.svg b/app/packages/link/public/assets/flags/svg/cu.svg new file mode 100644 index 0000000..897fa77 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cu.svg @@ -0,0 +1,24 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cv.svg b/app/packages/link/public/assets/flags/svg/cv.svg new file mode 100644 index 0000000..1a65d04 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cv.svg @@ -0,0 +1,34 @@ + + + + + + + image/svg+xml + + + + + The United States of America flag, produced by Daniel McRae + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cw.svg b/app/packages/link/public/assets/flags/svg/cw.svg new file mode 100644 index 0000000..f4cd92b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cw.svg @@ -0,0 +1,29 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cx.svg b/app/packages/link/public/assets/flags/svg/cx.svg new file mode 100644 index 0000000..70f8b8b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cx.svg @@ -0,0 +1,30 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cy.svg b/app/packages/link/public/assets/flags/svg/cy.svg new file mode 100644 index 0000000..e6cc05d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cy.svg @@ -0,0 +1,47 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/cz.svg b/app/packages/link/public/assets/flags/svg/cz.svg new file mode 100644 index 0000000..ee59f94 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/cz.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/de.svg b/app/packages/link/public/assets/flags/svg/de.svg new file mode 100644 index 0000000..aa101a3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/de.svg @@ -0,0 +1,37 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/dj.svg b/app/packages/link/public/assets/flags/svg/dj.svg new file mode 100644 index 0000000..a5621c5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/dj.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/dk.svg b/app/packages/link/public/assets/flags/svg/dk.svg new file mode 100644 index 0000000..c916593 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/dk.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/dm.svg b/app/packages/link/public/assets/flags/svg/dm.svg new file mode 100644 index 0000000..82fa18a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/dm.svg @@ -0,0 +1,192 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/do.svg b/app/packages/link/public/assets/flags/svg/do.svg new file mode 100644 index 0000000..22ff464 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/do.svg @@ -0,0 +1,6801 @@ + + + + + + + image/svg+xml + + + + + The United States of America flag, produced by Daniel McRae + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/dz.svg b/app/packages/link/public/assets/flags/svg/dz.svg new file mode 100644 index 0000000..e05bd11 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/dz.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ec.svg b/app/packages/link/public/assets/flags/svg/ec.svg new file mode 100644 index 0000000..0116d37 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ec.svg @@ -0,0 +1,184 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ee.svg b/app/packages/link/public/assets/flags/svg/ee.svg new file mode 100644 index 0000000..cb04c4d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ee.svg @@ -0,0 +1,39 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/eg.svg b/app/packages/link/public/assets/flags/svg/eg.svg new file mode 100644 index 0000000..e6b608a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/eg.svg @@ -0,0 +1,81 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/eh.svg b/app/packages/link/public/assets/flags/svg/eh.svg new file mode 100644 index 0000000..68d82c7 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/eh.svg @@ -0,0 +1,48 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/england.svg b/app/packages/link/public/assets/flags/svg/england.svg new file mode 100644 index 0000000..981808e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/england.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/er.svg b/app/packages/link/public/assets/flags/svg/er.svg new file mode 100644 index 0000000..9c5ebcf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/er.svg @@ -0,0 +1,42 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/es.svg b/app/packages/link/public/assets/flags/svg/es.svg new file mode 100644 index 0000000..506b28b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/es.svg @@ -0,0 +1,705 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/et.svg b/app/packages/link/public/assets/flags/svg/et.svg new file mode 100644 index 0000000..f81a16a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/et.svg @@ -0,0 +1,24 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/europeanunion.svg b/app/packages/link/public/assets/flags/svg/europeanunion.svg new file mode 100644 index 0000000..0f22db6 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/europeanunion.svg @@ -0,0 +1,4 @@ +European flag + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/fi.svg b/app/packages/link/public/assets/flags/svg/fi.svg new file mode 100644 index 0000000..f0d3c8e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/fi.svg @@ -0,0 +1,53 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/filelist.txt b/app/packages/link/public/assets/flags/svg/filelist.txt new file mode 100644 index 0000000..130ad38 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/filelist.txt @@ -0,0 +1,262 @@ +ab.svg +ad.svg +ae.svg +af.svg +ag.svg +ai.svg +al.svg +am.svg +ao.svg +aq.svg +ar.svg +as.svg +at.svg +au.svg +aw.svg +ax.svg +az.svg +ba.svg +bb.svg +bd.svg +be.svg +bf.svg +bg.svg +bh.svg +bi.svg +bj.svg +bl.svg +bm.svg +bn.svg +bo.svg +bq.svg +br.svg +bs.svg +bt.svg +bv.svg +bw.svg +by.svg +bz.svg +ca.svg +cc.svg +cd.svg +cf.svg +cg.svg +ch.svg +ci.svg +ck.svg +cl.svg +cm.svg +cn.svg +co.svg +cr.svg +cu.svg +cv.svg +cw.svg +cx.svg +cy.svg +cz.svg +de.svg +dj.svg +dk.svg +dm.svg +do.svg +dz.svg +ec.svg +ee.svg +eg.svg +eh.svg +england.svg +er.svg +es.svg +et.svg +europeanunion.svg +fi.svg +filelist.txt +fj.svg +fk.svg +fm.svg +fo.svg +fr.svg +ga.svg +gb.svg +gd.svg +ge.svg +gf.svg +gg.svg +gh.svg +gi.svg +gl.svg +gm.svg +gn.svg +gp.svg +gq.svg +gr.svg +gs.svg +gt.svg +gu.svg +gw.svg +gy.svg +hk.svg +hm.svg +hn.svg +hr.svg +ht.svg +hu.svg +id.svg +ie.svg +il.svg +im.svg +in.svg +io.svg +iq.svg +ir.svg +is.svg +it.svg +je.svg +jm.svg +jo.svg +jp.svg +ke.svg +kg.svg +kh.svg +ki.svg +km.svg +kn.svg +kp.svg +kr.svg +kw.svg +ky.svg +kz.svg +la.svg +lb.svg +lc.svg +li.svg +LICENSE.txt +lk.svg +lr.svg +ls.svg +lt.svg +lu.svg +lv.svg +ly.svg +ma.svg +mc.svg +md.svg +me.svg +mf.svg +mg.svg +mh.svg +mk.svg +ml.svg +mm.svg +mn.svg +mo.svg +mp.svg +mq.svg +mr.svg +ms.svg +mt.svg +mu.svg +mv.svg +mw.svg +mx.svg +my.svg +mz.svg +na.svg +nc.svg +ne.svg +nf.svg +ng.svg +ni.svg +nl.svg +no.svg +northerncyprus.svg +np.svg +nr.svg +nu.svg +nz.svg +ObtainedFrom.txt +om.svg +pa.svg +pe.svg +pf.svg +pg.svg +ph.svg +pk.svg +pl.svg +pm.svg +pn.svg +pr.svg +ps.svg +pt.svg +pw.svg +py.svg +qa.svg +re.svg +ro.svg +rs.svg +ru.svg +rw.svg +sa.svg +sb.svg +sc.svg +scotland.svg +sd.svg +se.svg +sg.svg +sh.svg +si.svg +sj.svg +sk.svg +sl.svg +sm.svg +sn.svg +so.svg +southossetia.svg +sr.svg +ss.svg +st.svg +sv.svg +sx.svg +sy.svg +sz.svg +tc.svg +td.svg +tf.svg +tg.svg +th.svg +tj.svg +tk.svg +tl.svg +tm.svg +tn.svg +to.svg +tr.svg +tt.svg +tv.svg +tw.svg +tz.svg +ua.svg +ug.svg +um.svg +unitednations.svg +us.svg +uy.svg +uz.svg +va.svg +vc.svg +ve.svg +vg.svg +vi.svg +vn.svg +vu.svg +wales.svg +wf.svg +ws.svg +xk.svg +ye.svg +yt.svg +za.svg +zm.svg +zw.svg +zz.svg diff --git a/app/packages/link/public/assets/flags/svg/fj.svg b/app/packages/link/public/assets/flags/svg/fj.svg new file mode 100644 index 0000000..0f2ea3c --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/fj.svg @@ -0,0 +1,154 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/fk.svg b/app/packages/link/public/assets/flags/svg/fk.svg new file mode 100644 index 0000000..9044006 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/fk.svg @@ -0,0 +1,215 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/fm.svg b/app/packages/link/public/assets/flags/svg/fm.svg new file mode 100644 index 0000000..1b57bbf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/fm.svg @@ -0,0 +1,24 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/fo.svg b/app/packages/link/public/assets/flags/svg/fo.svg new file mode 100644 index 0000000..37211be --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/fo.svg @@ -0,0 +1,42 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/fr.svg b/app/packages/link/public/assets/flags/svg/fr.svg new file mode 100644 index 0000000..7e0bdb8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/fr.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ga.svg b/app/packages/link/public/assets/flags/svg/ga.svg new file mode 100644 index 0000000..74be350 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ga.svg @@ -0,0 +1,40 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gb.svg b/app/packages/link/public/assets/flags/svg/gb.svg new file mode 100644 index 0000000..5389a49 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gb.svg @@ -0,0 +1,52 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gd.svg b/app/packages/link/public/assets/flags/svg/gd.svg new file mode 100644 index 0000000..44c61b1 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gd.svg @@ -0,0 +1,32 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ge.svg b/app/packages/link/public/assets/flags/svg/ge.svg new file mode 100644 index 0000000..a508b2b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ge.svg @@ -0,0 +1,31 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gf.svg b/app/packages/link/public/assets/flags/svg/gf.svg new file mode 100644 index 0000000..664c1c4 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gf.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/gg.svg b/app/packages/link/public/assets/flags/svg/gg.svg new file mode 100644 index 0000000..1144540 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gg.svg @@ -0,0 +1,29 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gh.svg b/app/packages/link/public/assets/flags/svg/gh.svg new file mode 100644 index 0000000..b6fa30d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gh.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gi.svg b/app/packages/link/public/assets/flags/svg/gi.svg new file mode 100644 index 0000000..e40d6e7 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gi.svg @@ -0,0 +1,347 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gl.svg b/app/packages/link/public/assets/flags/svg/gl.svg new file mode 100644 index 0000000..37aaccf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gl.svg @@ -0,0 +1,46 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gm.svg b/app/packages/link/public/assets/flags/svg/gm.svg new file mode 100644 index 0000000..d4409b2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gm.svg @@ -0,0 +1,47 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gn.svg b/app/packages/link/public/assets/flags/svg/gn.svg new file mode 100644 index 0000000..23ce5b3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gn.svg @@ -0,0 +1,42 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gp.svg b/app/packages/link/public/assets/flags/svg/gp.svg new file mode 100644 index 0000000..526e9c6 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gp.svg @@ -0,0 +1,345 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gq.svg b/app/packages/link/public/assets/flags/svg/gq.svg new file mode 100644 index 0000000..4e878cc --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gq.svg @@ -0,0 +1,86 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gr.svg b/app/packages/link/public/assets/flags/svg/gr.svg new file mode 100644 index 0000000..4bff36c --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gr.svg @@ -0,0 +1,60 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gs.svg b/app/packages/link/public/assets/flags/svg/gs.svg new file mode 100644 index 0000000..18c6dbd --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gs.svg @@ -0,0 +1,346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + L + + + E + + + O + + + T + + + E + + + R + + + R + + + R + + + R + + + R + + + E + + + O + + + O + + + A + + + A + + + A + + + M + + + P + + + P + + + P + + + I + + + T + + + T + + + M + + + G + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + South Georgia and South Sandwich Islands + + + + united_kingdom + flags + antarctic + sign + signs_and_symbols + + europe + + + + + Tobias Jakobs + + + + + Tobias Jakobs + + + + + Tobias Jakobs + + + + image/svg+xml + + + + + en + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gt.svg b/app/packages/link/public/assets/flags/svg/gt.svg new file mode 100644 index 0000000..9ae0d79 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gt.svg @@ -0,0 +1,139 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gu.svg b/app/packages/link/public/assets/flags/svg/gu.svg new file mode 100644 index 0000000..797b88d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gu.svg @@ -0,0 +1,75 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + G + + + U + + + A + + + M + + + + + + + + G + + + U + + + A + + + M + + + + diff --git a/app/packages/link/public/assets/flags/svg/gw.svg b/app/packages/link/public/assets/flags/svg/gw.svg new file mode 100644 index 0000000..277f3a1 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gw.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/gy.svg b/app/packages/link/public/assets/flags/svg/gy.svg new file mode 100644 index 0000000..626eff8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/gy.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/hk.svg b/app/packages/link/public/assets/flags/svg/hk.svg new file mode 100644 index 0000000..7ad03f3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/hk.svg @@ -0,0 +1,52 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/hm.svg b/app/packages/link/public/assets/flags/svg/hm.svg new file mode 100644 index 0000000..a3cd071 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/hm.svg @@ -0,0 +1,29 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/hn.svg b/app/packages/link/public/assets/flags/svg/hn.svg new file mode 100644 index 0000000..7e79933 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/hn.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/hr.svg b/app/packages/link/public/assets/flags/svg/hr.svg new file mode 100644 index 0000000..4ba52b0 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/hr.svg @@ -0,0 +1,144 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ht.svg b/app/packages/link/public/assets/flags/svg/ht.svg new file mode 100644 index 0000000..53475ab --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ht.svg @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/hu.svg b/app/packages/link/public/assets/flags/svg/hu.svg new file mode 100644 index 0000000..8ab9d1b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/hu.svg @@ -0,0 +1,19 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/id.svg b/app/packages/link/public/assets/flags/svg/id.svg new file mode 100644 index 0000000..ba4f958 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/id.svg @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ie.svg b/app/packages/link/public/assets/flags/svg/ie.svg new file mode 100644 index 0000000..f10a9c5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ie.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/il.svg b/app/packages/link/public/assets/flags/svg/il.svg new file mode 100644 index 0000000..518a2bc --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/il.svg @@ -0,0 +1,31 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/im.svg b/app/packages/link/public/assets/flags/svg/im.svg new file mode 100644 index 0000000..275cf86 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/im.svg @@ -0,0 +1,71 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/in.svg b/app/packages/link/public/assets/flags/svg/in.svg new file mode 100644 index 0000000..3265f8f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/in.svg @@ -0,0 +1,47 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/io.svg b/app/packages/link/public/assets/flags/svg/io.svg new file mode 100644 index 0000000..6051b09 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/io.svg @@ -0,0 +1,187 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/iq.svg b/app/packages/link/public/assets/flags/svg/iq.svg new file mode 100644 index 0000000..e0dd0b9 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/iq.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ir.svg b/app/packages/link/public/assets/flags/svg/ir.svg new file mode 100644 index 0000000..9779aea --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ir.svg @@ -0,0 +1,522 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/is.svg b/app/packages/link/public/assets/flags/svg/is.svg new file mode 100644 index 0000000..046ffd0 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/is.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/it.svg b/app/packages/link/public/assets/flags/svg/it.svg new file mode 100644 index 0000000..1a9f297 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/it.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/je.svg b/app/packages/link/public/assets/flags/svg/je.svg new file mode 100644 index 0000000..4dd97f1 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/je.svg @@ -0,0 +1,67 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/jm.svg b/app/packages/link/public/assets/flags/svg/jm.svg new file mode 100644 index 0000000..5ccd524 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/jm.svg @@ -0,0 +1,45 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/jo.svg b/app/packages/link/public/assets/flags/svg/jo.svg new file mode 100644 index 0000000..152749e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/jo.svg @@ -0,0 +1,49 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/jp.svg b/app/packages/link/public/assets/flags/svg/jp.svg new file mode 100644 index 0000000..f36071b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/jp.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ke.svg b/app/packages/link/public/assets/flags/svg/ke.svg new file mode 100644 index 0000000..79d223f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ke.svg @@ -0,0 +1,33 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/kg.svg b/app/packages/link/public/assets/flags/svg/kg.svg new file mode 100644 index 0000000..e560aef --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/kg.svg @@ -0,0 +1,47 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/kh.svg b/app/packages/link/public/assets/flags/svg/kh.svg new file mode 100644 index 0000000..48e782e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/kh.svg @@ -0,0 +1,156 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ki.svg b/app/packages/link/public/assets/flags/svg/ki.svg new file mode 100644 index 0000000..c145dd3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ki.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/km.svg b/app/packages/link/public/assets/flags/svg/km.svg new file mode 100644 index 0000000..235ec02 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/km.svg @@ -0,0 +1,51 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/kn.svg b/app/packages/link/public/assets/flags/svg/kn.svg new file mode 100644 index 0000000..d60ae2e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/kn.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/kp.svg b/app/packages/link/public/assets/flags/svg/kp.svg new file mode 100644 index 0000000..6ce531d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/kp.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/kr.svg b/app/packages/link/public/assets/flags/svg/kr.svg new file mode 100644 index 0000000..a0b266d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/kr.svg @@ -0,0 +1,42 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/kw.svg b/app/packages/link/public/assets/flags/svg/kw.svg new file mode 100644 index 0000000..5822eb6 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/kw.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ky.svg b/app/packages/link/public/assets/flags/svg/ky.svg new file mode 100644 index 0000000..fb5e915 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ky.svg @@ -0,0 +1,123 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/kz.svg b/app/packages/link/public/assets/flags/svg/kz.svg new file mode 100644 index 0000000..bd7130a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/kz.svg @@ -0,0 +1,67 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/la.svg b/app/packages/link/public/assets/flags/svg/la.svg new file mode 100644 index 0000000..fe009db --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/la.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/lb.svg b/app/packages/link/public/assets/flags/svg/lb.svg new file mode 100644 index 0000000..433b2c2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/lb.svg @@ -0,0 +1,45 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/lc.svg b/app/packages/link/public/assets/flags/svg/lc.svg new file mode 100644 index 0000000..ab006b5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/lc.svg @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/li.svg b/app/packages/link/public/assets/flags/svg/li.svg new file mode 100644 index 0000000..78d5325 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/li.svg @@ -0,0 +1,195 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/lk.svg b/app/packages/link/public/assets/flags/svg/lk.svg new file mode 100644 index 0000000..e28985d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/lk.svg @@ -0,0 +1,44 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/lr.svg b/app/packages/link/public/assets/flags/svg/lr.svg new file mode 100644 index 0000000..f9d3939 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/lr.svg @@ -0,0 +1,29 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ls.svg b/app/packages/link/public/assets/flags/svg/ls.svg new file mode 100644 index 0000000..d5836fa --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ls.svg @@ -0,0 +1,173 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/lt.svg b/app/packages/link/public/assets/flags/svg/lt.svg new file mode 100644 index 0000000..b67359b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/lt.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/lu.svg b/app/packages/link/public/assets/flags/svg/lu.svg new file mode 100644 index 0000000..1f6fe91 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/lu.svg @@ -0,0 +1,36 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/lv.svg b/app/packages/link/public/assets/flags/svg/lv.svg new file mode 100644 index 0000000..a2fbe75 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/lv.svg @@ -0,0 +1,37 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ly.svg b/app/packages/link/public/assets/flags/svg/ly.svg new file mode 100644 index 0000000..0922752 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ly.svg @@ -0,0 +1,23 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ma.svg b/app/packages/link/public/assets/flags/svg/ma.svg new file mode 100644 index 0000000..457afd2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ma.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mc.svg b/app/packages/link/public/assets/flags/svg/mc.svg new file mode 100644 index 0000000..9bd4ab1 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mc.svg @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/md.svg b/app/packages/link/public/assets/flags/svg/md.svg new file mode 100644 index 0000000..27729f5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/md.svg @@ -0,0 +1,101 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/me.svg b/app/packages/link/public/assets/flags/svg/me.svg new file mode 100644 index 0000000..473f640 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/me.svg @@ -0,0 +1,5 @@ + + +image/svg+xml + + diff --git a/app/packages/link/public/assets/flags/svg/mf.svg b/app/packages/link/public/assets/flags/svg/mf.svg new file mode 100644 index 0000000..24f58b7 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mf.svg @@ -0,0 +1,106 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mg.svg b/app/packages/link/public/assets/flags/svg/mg.svg new file mode 100644 index 0000000..05bd5b9 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mg.svg @@ -0,0 +1,38 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mh.svg b/app/packages/link/public/assets/flags/svg/mh.svg new file mode 100644 index 0000000..df29219 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mh.svg @@ -0,0 +1,42 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mk.svg b/app/packages/link/public/assets/flags/svg/mk.svg new file mode 100644 index 0000000..62e5e37 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mk.svg @@ -0,0 +1,30 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ml.svg b/app/packages/link/public/assets/flags/svg/ml.svg new file mode 100644 index 0000000..dc71966 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ml.svg @@ -0,0 +1,38 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mm.svg b/app/packages/link/public/assets/flags/svg/mm.svg new file mode 100644 index 0000000..add89f8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mm.svg @@ -0,0 +1,146 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mn.svg b/app/packages/link/public/assets/flags/svg/mn.svg new file mode 100644 index 0000000..819ce2f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mn.svg @@ -0,0 +1,26 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mo.svg b/app/packages/link/public/assets/flags/svg/mo.svg new file mode 100644 index 0000000..769e94a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mo.svg @@ -0,0 +1,31 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mp.svg b/app/packages/link/public/assets/flags/svg/mp.svg new file mode 100644 index 0000000..93ca168 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mp.svg @@ -0,0 +1,268 @@ + + + + + + + + + + + micronesia + + oceania + flag + sign + + + + + + + + + + + + + + + + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mq.svg b/app/packages/link/public/assets/flags/svg/mq.svg new file mode 100644 index 0000000..950c26e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mq.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/mr.svg b/app/packages/link/public/assets/flags/svg/mr.svg new file mode 100644 index 0000000..0066c90 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mr.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ms.svg b/app/packages/link/public/assets/flags/svg/ms.svg new file mode 100644 index 0000000..c9ef72b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ms.svg @@ -0,0 +1,76 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mt.svg b/app/packages/link/public/assets/flags/svg/mt.svg new file mode 100644 index 0000000..b14194b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mt.svg @@ -0,0 +1,82 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mu.svg b/app/packages/link/public/assets/flags/svg/mu.svg new file mode 100644 index 0000000..6ae235d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mu.svg @@ -0,0 +1,40 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mv.svg b/app/packages/link/public/assets/flags/svg/mv.svg new file mode 100644 index 0000000..eb20d9e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mv.svg @@ -0,0 +1,20 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mw.svg b/app/packages/link/public/assets/flags/svg/mw.svg new file mode 100644 index 0000000..cf3922b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mw.svg @@ -0,0 +1,55 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mx.svg b/app/packages/link/public/assets/flags/svg/mx.svg new file mode 100644 index 0000000..7fc1393 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mx.svg @@ -0,0 +1,349 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/my.svg b/app/packages/link/public/assets/flags/svg/my.svg new file mode 100644 index 0000000..2654cef --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/my.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/mz.svg b/app/packages/link/public/assets/flags/svg/mz.svg new file mode 100644 index 0000000..605a9d5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/mz.svg @@ -0,0 +1,34 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/na.svg b/app/packages/link/public/assets/flags/svg/na.svg new file mode 100644 index 0000000..af51637 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/na.svg @@ -0,0 +1,30 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/nc.svg b/app/packages/link/public/assets/flags/svg/nc.svg new file mode 100644 index 0000000..d0262cf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/nc.svg @@ -0,0 +1,39 @@ + + +Flag of New Caledonia + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/ne.svg b/app/packages/link/public/assets/flags/svg/ne.svg new file mode 100644 index 0000000..e6a7781 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ne.svg @@ -0,0 +1,20 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/nf.svg b/app/packages/link/public/assets/flags/svg/nf.svg new file mode 100644 index 0000000..84f84ec --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/nf.svg @@ -0,0 +1,46 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ng.svg b/app/packages/link/public/assets/flags/svg/ng.svg new file mode 100644 index 0000000..4eccb54 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ng.svg @@ -0,0 +1,19 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ni.svg b/app/packages/link/public/assets/flags/svg/ni.svg new file mode 100644 index 0000000..2fe085a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ni.svg @@ -0,0 +1,122 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/nl.svg b/app/packages/link/public/assets/flags/svg/nl.svg new file mode 100644 index 0000000..be962d3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/nl.svg @@ -0,0 +1,37 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/no.svg b/app/packages/link/public/assets/flags/svg/no.svg new file mode 100644 index 0000000..699ed31 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/no.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/northerncyprus.svg b/app/packages/link/public/assets/flags/svg/northerncyprus.svg new file mode 100644 index 0000000..a91b313 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/northerncyprus.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/np.svg b/app/packages/link/public/assets/flags/svg/np.svg new file mode 100644 index 0000000..373225e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/np.svg @@ -0,0 +1,47 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/nr.svg b/app/packages/link/public/assets/flags/svg/nr.svg new file mode 100644 index 0000000..78a65e0 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/nr.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/nu.svg b/app/packages/link/public/assets/flags/svg/nu.svg new file mode 100644 index 0000000..645a66e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/nu.svg @@ -0,0 +1,40 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/nz.svg b/app/packages/link/public/assets/flags/svg/nz.svg new file mode 100644 index 0000000..0f7cf2f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/nz.svg @@ -0,0 +1,69 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/om.svg b/app/packages/link/public/assets/flags/svg/om.svg new file mode 100644 index 0000000..f28f32d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/om.svg @@ -0,0 +1,349 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pa.svg b/app/packages/link/public/assets/flags/svg/pa.svg new file mode 100644 index 0000000..c1368b2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pa.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pe.svg b/app/packages/link/public/assets/flags/svg/pe.svg new file mode 100644 index 0000000..ebd2e5f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pe.svg @@ -0,0 +1,40 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pf.svg b/app/packages/link/public/assets/flags/svg/pf.svg new file mode 100644 index 0000000..63f056e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pf.svg @@ -0,0 +1,77 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pg.svg b/app/packages/link/public/assets/flags/svg/pg.svg new file mode 100644 index 0000000..fd1fe93 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pg.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ph.svg b/app/packages/link/public/assets/flags/svg/ph.svg new file mode 100644 index 0000000..95f9d37 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ph.svg @@ -0,0 +1,36 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pk.svg b/app/packages/link/public/assets/flags/svg/pk.svg new file mode 100644 index 0000000..1c33e67 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pk.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pl.svg b/app/packages/link/public/assets/flags/svg/pl.svg new file mode 100644 index 0000000..a8d406a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pl.svg @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pm.svg b/app/packages/link/public/assets/flags/svg/pm.svg new file mode 100644 index 0000000..b7555b0 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pm.svg @@ -0,0 +1,2651 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pn.svg b/app/packages/link/public/assets/flags/svg/pn.svg new file mode 100644 index 0000000..d310c31 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pn.svg @@ -0,0 +1,146 @@ + + + + + + + image/svg+xml + + + + + + + + + + The above line is the ensign field color: #CF142B red and #00247D blue + + + + + + + + + I think the above two lines give the simplest way to make the diagonals + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pr.svg b/app/packages/link/public/assets/flags/svg/pr.svg new file mode 100644 index 0000000..771c304 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pr.svg @@ -0,0 +1,45 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ps.svg b/app/packages/link/public/assets/flags/svg/ps.svg new file mode 100644 index 0000000..e960374 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ps.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pt.svg b/app/packages/link/public/assets/flags/svg/pt.svg new file mode 100644 index 0000000..752ea64 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pt.svg @@ -0,0 +1,526 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/pw.svg b/app/packages/link/public/assets/flags/svg/pw.svg new file mode 100644 index 0000000..222f3c2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/pw.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/py.svg b/app/packages/link/public/assets/flags/svg/py.svg new file mode 100644 index 0000000..80d30bf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/py.svg @@ -0,0 +1,242 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/qa.svg b/app/packages/link/public/assets/flags/svg/qa.svg new file mode 100644 index 0000000..099b508 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/qa.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/re.svg b/app/packages/link/public/assets/flags/svg/re.svg new file mode 100644 index 0000000..d5a5e21 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/re.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ro.svg b/app/packages/link/public/assets/flags/svg/ro.svg new file mode 100644 index 0000000..311c372 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ro.svg @@ -0,0 +1,42 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/rs.svg b/app/packages/link/public/assets/flags/svg/rs.svg new file mode 100644 index 0000000..21e21c2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/rs.svg @@ -0,0 +1,1562 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ru.svg b/app/packages/link/public/assets/flags/svg/ru.svg new file mode 100644 index 0000000..e931a6b --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ru.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/rw.svg b/app/packages/link/public/assets/flags/svg/rw.svg new file mode 100644 index 0000000..2822882 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/rw.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sa.svg b/app/packages/link/public/assets/flags/svg/sa.svg new file mode 100644 index 0000000..f2bacbb --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sa.svg @@ -0,0 +1,56 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sb.svg b/app/packages/link/public/assets/flags/svg/sb.svg new file mode 100644 index 0000000..334ae64 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sb.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sc.svg b/app/packages/link/public/assets/flags/svg/sc.svg new file mode 100644 index 0000000..a4841f8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sc.svg @@ -0,0 +1,45 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/scotland.svg b/app/packages/link/public/assets/flags/svg/scotland.svg new file mode 100644 index 0000000..066ee5d --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/scotland.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sd.svg b/app/packages/link/public/assets/flags/svg/sd.svg new file mode 100644 index 0000000..bbfac97 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sd.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/se.svg b/app/packages/link/public/assets/flags/svg/se.svg new file mode 100644 index 0000000..913d8a8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/se.svg @@ -0,0 +1,28 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sg.svg b/app/packages/link/public/assets/flags/svg/sg.svg new file mode 100644 index 0000000..7a85ef5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sg.svg @@ -0,0 +1,29 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sh.svg b/app/packages/link/public/assets/flags/svg/sh.svg new file mode 100644 index 0000000..21cf488 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sh.svg @@ -0,0 +1,795 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/si.svg b/app/packages/link/public/assets/flags/svg/si.svg new file mode 100644 index 0000000..7461f63 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/si.svg @@ -0,0 +1,30 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sj.svg b/app/packages/link/public/assets/flags/svg/sj.svg new file mode 100644 index 0000000..7550d89 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sj.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sk.svg b/app/packages/link/public/assets/flags/svg/sk.svg new file mode 100644 index 0000000..84c09e8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sk.svg @@ -0,0 +1,26 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sl.svg b/app/packages/link/public/assets/flags/svg/sl.svg new file mode 100644 index 0000000..662d1d7 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sl.svg @@ -0,0 +1,43 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sm.svg b/app/packages/link/public/assets/flags/svg/sm.svg new file mode 100644 index 0000000..88284d4 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sm.svg @@ -0,0 +1,209 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + L + + + I + + + B + + + E + + + R + + + T + + + A + + + S + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sn.svg b/app/packages/link/public/assets/flags/svg/sn.svg new file mode 100644 index 0000000..a3fa37a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sn.svg @@ -0,0 +1,20 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/so.svg b/app/packages/link/public/assets/flags/svg/so.svg new file mode 100644 index 0000000..534c6ab --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/so.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/southossetia.svg b/app/packages/link/public/assets/flags/svg/southossetia.svg new file mode 100644 index 0000000..101efdf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/southossetia.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/sr.svg b/app/packages/link/public/assets/flags/svg/sr.svg new file mode 100644 index 0000000..99514a9 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sr.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ss.svg b/app/packages/link/public/assets/flags/svg/ss.svg new file mode 100644 index 0000000..56aff05 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ss.svg @@ -0,0 +1,21 @@ + + + + + + image/svg+xml + + Flag of South Sudan + + + + Flag of South Sudan + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/st.svg b/app/packages/link/public/assets/flags/svg/st.svg new file mode 100644 index 0000000..8f09d11 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/st.svg @@ -0,0 +1,27 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sv.svg b/app/packages/link/public/assets/flags/svg/sv.svg new file mode 100644 index 0000000..0fcd4f4 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sv.svg @@ -0,0 +1,301 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sx.svg b/app/packages/link/public/assets/flags/svg/sx.svg new file mode 100644 index 0000000..142b30f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sx.svg @@ -0,0 +1,106 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sy.svg b/app/packages/link/public/assets/flags/svg/sy.svg new file mode 100644 index 0000000..d85aadf --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sy.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/sz.svg b/app/packages/link/public/assets/flags/svg/sz.svg new file mode 100644 index 0000000..c92e597 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/sz.svg @@ -0,0 +1,93 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tc.svg b/app/packages/link/public/assets/flags/svg/tc.svg new file mode 100644 index 0000000..865b4ad --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tc.svg @@ -0,0 +1,102 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/td.svg b/app/packages/link/public/assets/flags/svg/td.svg new file mode 100644 index 0000000..1d01cdc --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/td.svg @@ -0,0 +1,41 @@ + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tf.svg b/app/packages/link/public/assets/flags/svg/tf.svg new file mode 100644 index 0000000..c485953 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tf.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/tg.svg b/app/packages/link/public/assets/flags/svg/tg.svg new file mode 100644 index 0000000..20dbfa3 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tg.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/th.svg b/app/packages/link/public/assets/flags/svg/th.svg new file mode 100644 index 0000000..a539e38 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/th.svg @@ -0,0 +1,20 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tj.svg b/app/packages/link/public/assets/flags/svg/tj.svg new file mode 100644 index 0000000..c1b0a89 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tj.svg @@ -0,0 +1,37 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tk.svg b/app/packages/link/public/assets/flags/svg/tk.svg new file mode 100644 index 0000000..3327e06 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tk.svg @@ -0,0 +1,139 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tl.svg b/app/packages/link/public/assets/flags/svg/tl.svg new file mode 100644 index 0000000..3b56c52 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tl.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tm.svg b/app/packages/link/public/assets/flags/svg/tm.svg new file mode 100644 index 0000000..83cd9aa --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tm.svg @@ -0,0 +1,325 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tn.svg b/app/packages/link/public/assets/flags/svg/tn.svg new file mode 100644 index 0000000..ef0d0b7 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tn.svg @@ -0,0 +1,23 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/to.svg b/app/packages/link/public/assets/flags/svg/to.svg new file mode 100644 index 0000000..f51522f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/to.svg @@ -0,0 +1,22 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tr.svg b/app/packages/link/public/assets/flags/svg/tr.svg new file mode 100644 index 0000000..779779e --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tr.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tt.svg b/app/packages/link/public/assets/flags/svg/tt.svg new file mode 100644 index 0000000..46e5547 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tt.svg @@ -0,0 +1,18 @@ + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tv.svg b/app/packages/link/public/assets/flags/svg/tv.svg new file mode 100644 index 0000000..d83f0d2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tv.svg @@ -0,0 +1,49 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tw.svg b/app/packages/link/public/assets/flags/svg/tw.svg new file mode 100644 index 0000000..e9fb0c2 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tw.svg @@ -0,0 +1,24 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/tz.svg b/app/packages/link/public/assets/flags/svg/tz.svg new file mode 100644 index 0000000..85179d6 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/tz.svg @@ -0,0 +1,45 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ua.svg b/app/packages/link/public/assets/flags/svg/ua.svg new file mode 100644 index 0000000..6a8cf87 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ua.svg @@ -0,0 +1,16 @@ + + + + + + + image/svg+xml + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ug.svg b/app/packages/link/public/assets/flags/svg/ug.svg new file mode 100644 index 0000000..7facab4 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ug.svg @@ -0,0 +1,42 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/um.svg b/app/packages/link/public/assets/flags/svg/um.svg new file mode 100644 index 0000000..88b7f77 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/um.svg @@ -0,0 +1,141 @@ + + + + + + + + + image/svg+xml + + + + + The United States of America flag, produced by Daniel McRae + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/unitednations.svg b/app/packages/link/public/assets/flags/svg/unitednations.svg new file mode 100644 index 0000000..c47f9fe --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/unitednations.svg @@ -0,0 +1,594 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/us.svg b/app/packages/link/public/assets/flags/svg/us.svg new file mode 100644 index 0000000..b6516b4 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/us.svg @@ -0,0 +1,141 @@ + + + + + + + + + image/svg+xml + + + + + The United States of America flag, produced by Daniel McRae + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/uy.svg b/app/packages/link/public/assets/flags/svg/uy.svg new file mode 100644 index 0000000..4a29ce5 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/uy.svg @@ -0,0 +1,63 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/uz.svg b/app/packages/link/public/assets/flags/svg/uz.svg new file mode 100644 index 0000000..97468a7 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/uz.svg @@ -0,0 +1,37 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/va.svg b/app/packages/link/public/assets/flags/svg/va.svg new file mode 100644 index 0000000..097e3b4 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/va.svg @@ -0,0 +1,501 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/vc.svg b/app/packages/link/public/assets/flags/svg/vc.svg new file mode 100644 index 0000000..de35200 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/vc.svg @@ -0,0 +1,20 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ve.svg b/app/packages/link/public/assets/flags/svg/ve.svg new file mode 100644 index 0000000..c65fe82 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ve.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/vg.svg b/app/packages/link/public/assets/flags/svg/vg.svg new file mode 100644 index 0000000..fe88d47 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/vg.svg @@ -0,0 +1,249 @@ + + + + + + + British Virgin Islands + + + + + united_kingdom + flags + caribbean + america + signs_and_symbols + sign + + + + + Tobias Jakobs + + + + + Tobias Jakobs + + + + + Tobias Jakobs + + + + image/svg+xml + + + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/vi.svg b/app/packages/link/public/assets/flags/svg/vi.svg new file mode 100644 index 0000000..f525b81 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/vi.svg @@ -0,0 +1,449 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/vn.svg b/app/packages/link/public/assets/flags/svg/vn.svg new file mode 100644 index 0000000..ee7ab4f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/vn.svg @@ -0,0 +1,21 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/vu.svg b/app/packages/link/public/assets/flags/svg/vu.svg new file mode 100644 index 0000000..bdea587 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/vu.svg @@ -0,0 +1,28 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/wales.svg b/app/packages/link/public/assets/flags/svg/wales.svg new file mode 100644 index 0000000..2520c1a --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/wales.svg @@ -0,0 +1,505 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/wf.svg b/app/packages/link/public/assets/flags/svg/wf.svg new file mode 100644 index 0000000..b54835f --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/wf.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/ws.svg b/app/packages/link/public/assets/flags/svg/ws.svg new file mode 100644 index 0000000..e799dd1 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ws.svg @@ -0,0 +1,25 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/xk.svg b/app/packages/link/public/assets/flags/svg/xk.svg new file mode 100644 index 0000000..4afbc18 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/xk.svg @@ -0,0 +1,17 @@ + + + +Flag of Kosovo + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/ye.svg b/app/packages/link/public/assets/flags/svg/ye.svg new file mode 100644 index 0000000..1d68b82 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/ye.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/yt.svg b/app/packages/link/public/assets/flags/svg/yt.svg new file mode 100644 index 0000000..2591a29 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/yt.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/packages/link/public/assets/flags/svg/za.svg b/app/packages/link/public/assets/flags/svg/za.svg new file mode 100644 index 0000000..d7a1187 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/za.svg @@ -0,0 +1,58 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/zm.svg b/app/packages/link/public/assets/flags/svg/zm.svg new file mode 100644 index 0000000..bc16746 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/zm.svg @@ -0,0 +1,40 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/public/assets/flags/svg/zw.svg b/app/packages/link/public/assets/flags/svg/zw.svg new file mode 100644 index 0000000..1227ba8 --- /dev/null +++ b/app/packages/link/public/assets/flags/svg/zw.svg @@ -0,0 +1,52 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/payy.png b/app/packages/link/public/assets/payy-logo.png similarity index 100% rename from payy.png rename to app/packages/link/public/assets/payy-logo.png diff --git a/app/packages/link/src/app/globals.css b/app/packages/link/src/app/globals.css new file mode 100644 index 0000000..ed116ee --- /dev/null +++ b/app/packages/link/src/app/globals.css @@ -0,0 +1,21 @@ +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; +} + +body { + color: #242424; + background: #E3E3E3; +} + +a { + color: inherit; + text-decoration: none; +} \ No newline at end of file diff --git a/app/packages/link/src/app/icon.png b/app/packages/link/src/app/icon.png new file mode 100644 index 0000000..09e68d9 Binary files /dev/null and b/app/packages/link/src/app/icon.png differ diff --git a/app/packages/link/src/app/img/logo.png b/app/packages/link/src/app/img/logo.png new file mode 100644 index 0000000..54d7288 Binary files /dev/null and b/app/packages/link/src/app/img/logo.png differ diff --git a/app/packages/link/src/app/img/note-request.png b/app/packages/link/src/app/img/note-request.png new file mode 100644 index 0000000..cb49687 Binary files /dev/null and b/app/packages/link/src/app/img/note-request.png differ diff --git a/app/packages/link/src/app/img/note-send.png b/app/packages/link/src/app/img/note-send.png new file mode 100644 index 0000000..9e07849 Binary files /dev/null and b/app/packages/link/src/app/img/note-send.png differ diff --git a/app/packages/link/src/app/img/note.png b/app/packages/link/src/app/img/note.png new file mode 100644 index 0000000..2c04ab6 Binary files /dev/null and b/app/packages/link/src/app/img/note.png differ diff --git a/app/packages/link/src/app/img/note.svg b/app/packages/link/src/app/img/note.svg new file mode 100644 index 0000000..6827bf9 --- /dev/null +++ b/app/packages/link/src/app/img/note.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/link/src/app/img/payment-request.svg b/app/packages/link/src/app/img/payment-request.svg new file mode 100644 index 0000000..481dbd6 --- /dev/null +++ b/app/packages/link/src/app/img/payment-request.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/packages/link/src/app/img/payy-invite.svg b/app/packages/link/src/app/img/payy-invite.svg new file mode 100644 index 0000000..40f802e --- /dev/null +++ b/app/packages/link/src/app/img/payy-invite.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/packages/link/src/app/img/payy-note-received.svg b/app/packages/link/src/app/img/payy-note-received.svg new file mode 100644 index 0000000..63352dd --- /dev/null +++ b/app/packages/link/src/app/img/payy-note-received.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/packages/link/src/app/invite/[code]/InvitePageClient.tsx b/app/packages/link/src/app/invite/[code]/InvitePageClient.tsx new file mode 100644 index 0000000..659bc4d --- /dev/null +++ b/app/packages/link/src/app/invite/[code]/InvitePageClient.tsx @@ -0,0 +1,41 @@ +'use client' + +import Image from 'next/image' +import styles from '../../page.module.css' +import logo from '../../img/logo.png' +import payyInviteText from '../../img/payy-invite.svg' +import { Button } from '../../../components/buttons/Button' +import { + PAYY_BASE_URL, + PAYY_REFERRER_BASE_URL +} from '../../../config/constants' +import { useStoreRedirect } from '@/hooks/useStoreRedirect' + +export default function InvitePageClient({ code }: { code: string }) { + const baseReferrerUrl = `${PAYY_REFERRER_BASE_URL}/invite/${code}` + const handleRedirectToStore = useStoreRedirect({ baseReferrerUrl }) + + return ( + <> +
+
+
+ Payy +
+
+ Payy Invite +
+ + +
+
+ + ) +} diff --git a/app/packages/link/src/app/invite/[code]/page.tsx b/app/packages/link/src/app/invite/[code]/page.tsx new file mode 100644 index 0000000..fe0bc5e --- /dev/null +++ b/app/packages/link/src/app/invite/[code]/page.tsx @@ -0,0 +1,17 @@ +import type { Metadata } from 'next' +import InvitePageClient from './InvitePageClient' + +export const metadata: Metadata = { + title: "You've been invited to Payy", + description: 'Payy is crypto venmo. Fast, private, global payments.' +} + +export interface InvitePageParams { + params: { + code: string + } +} + +export default function InvitePage({ params }: InvitePageParams) { + return +} diff --git a/app/packages/link/src/app/layout.tsx b/app/packages/link/src/app/layout.tsx new file mode 100644 index 0000000..680eefe --- /dev/null +++ b/app/packages/link/src/app/layout.tsx @@ -0,0 +1,33 @@ +import { ReactNode } from 'react' +import type { Metadata } from 'next' +import './globals.css' +import { steradian } from './steradian' +import PosthogInit from '@/components/PosthogInit' + +export const metadata: Metadata = { + metadataBase: new URL( + process.env.NODE_ENV === 'production' + ? 'https://payy.link' + : 'http://localhost:3000' + ), + title: 'USD Payment - Payy', + description: "You've been sent a payment in USD. Redeem it now for free." +} + +export default function RootLayout({ children }: { children: ReactNode }) { + return ( + + + + + + + + {children} + + + ) +} diff --git a/app/packages/link/src/app/opengraph-image.png b/app/packages/link/src/app/opengraph-image.png new file mode 100644 index 0000000..77d1d83 Binary files /dev/null and b/app/packages/link/src/app/opengraph-image.png differ diff --git a/app/packages/link/src/app/page.module.css b/app/packages/link/src/app/page.module.css new file mode 100644 index 0000000..09322b4 --- /dev/null +++ b/app/packages/link/src/app/page.module.css @@ -0,0 +1,73 @@ +.main { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + /* padding: 6rem; */ + height: 100vh; + padding: 1rem; + text-align: center; + overflow-x: hidden; + box-sizing: border-box; + width: 100%; + max-width: 100vw; + min-width: 0; +} + +.note_container { + width: 100%; + max-width: 100%; + min-width: 0; + overflow-x: hidden; + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; +} + +.note { + position: relative; + display: flex; + justify-content: center; +} + +.value { + font-weight: 700; + position: absolute; + top: 155px; + left: 60px; + font-size: 41px; + letter-spacing: -3px; +} + +.title { + max-width: 100%; + flex-shrink: 0; +} + +.memo_container { + width: 100%; + max-width: 100%; + min-width: 0; + overflow-x: hidden; + box-sizing: border-box; + padding: 0 1rem; + flex-shrink: 0; +} + +.memo { + font-size: 20px; + font-weight: 400; + color: #000000; + text-align: center; + margin-block: 10px; + max-width: 100%; + width: 100%; + min-width: 0; + box-sizing: border-box; + line-height: 1.4; + overflow-wrap: anywhere !important; + word-break: break-all !important; + white-space: normal !important; + overflow: hidden; +} \ No newline at end of file diff --git a/app/packages/link/src/app/r/[...slug]/RequestPayment.tsx b/app/packages/link/src/app/r/[...slug]/RequestPayment.tsx new file mode 100644 index 0000000..aa216d3 --- /dev/null +++ b/app/packages/link/src/app/r/[...slug]/RequestPayment.tsx @@ -0,0 +1,97 @@ +'use client' + +import Image from 'next/image' +import styles from '../../page.module.css' +import note from '../../img/note-request.png' +import paymentRequestText from '../../img/payment-request.svg' +import { Button } from '../../../components/buttons/Button' +import { PAYY_BASE_URL } from '../../../config/constants' +import shortcodeToEmoji from 'emoji-shortcode-mapping/shortcode-to-emoji.json' +import { useStoreRedirect } from '@/hooks/useStoreRedirect' + +export interface RequestPaymentParams { + params: { + slug: string[] + } +} + +// Add emoji handling +const emojiShortcodeRegex = /~[a-z_ ]+~/g + +function decodeMemo(memo: string) { + // First handle URL encoding + memo = memo.replaceAll('_', '%20') + memo = memo.replaceAll('%255F', '%5F') + memo = decodeURIComponent(memo) + + // Handle emoji variant selector + memo = memo.replaceAll('~ee~', '~e~') + memo = memo.replaceAll(/~e~/g, '\uFE0F') + + // Convert emoji shortcodes to actual emojis + let match + while ((match = emojiShortcodeRegex.exec(memo)) !== null) { + const emoji = shortcodeToEmoji[match[0] as keyof typeof shortcodeToEmoji] + if (!emoji) continue + memo = memo.replace(match[0], emoji) + } + + return memo +} + +export default function RequestPayment({ params }: RequestPaymentParams) { + const referrerUrlPayyBaseUrl = 'https://payy.link' + const hash = window?.location.hash + const referrerUrl = `${referrerUrlPayyBaseUrl}/r/${params.slug?.join('/') || ''}${hash}` + + const handleRedirectToStore = useStoreRedirect({ + baseReferrerUrl: referrerUrl + }) + + return ( + <> +
+
+
+
+ {fromBigIntToCurrency(BigInt(params.slug[1]))} +
+ Payy note +
+
+ Payment Request +
+
+ {params.slug[2] && ( +

+ {decodeMemo(params.slug[2])} +

+ )} +
+ + +
+
+ + ) +} + +function fromBigIntToCurrency(balance: bigint): string { + const balanceString = balance.toString().padStart(6, '0') + const whole = balanceString.slice(0, -6) + const decimal = balanceString.slice(-6).slice(0, 2).padStart(2, '0') + return `${whole === '0' || whole === '' ? '0' : whole}.${decimal}` +} diff --git a/app/packages/link/src/app/r/[...slug]/page.tsx b/app/packages/link/src/app/r/[...slug]/page.tsx new file mode 100644 index 0000000..e256c1b --- /dev/null +++ b/app/packages/link/src/app/r/[...slug]/page.tsx @@ -0,0 +1,12 @@ +import type { Metadata } from 'next' +import RequestPayment from './RequestPayment' + +export const metadata: Metadata = { + title: 'Payment Request - Payy', + description: + 'Request for payment in USD. Payments will be sent privately using Payy.' +} + +export default function Page({ params }: { params: { slug: string[] } }) { + return +} diff --git a/app/packages/link/src/app/s/[[...slug]]/page.tsx b/app/packages/link/src/app/s/[[...slug]]/page.tsx new file mode 100644 index 0000000..8feee04 --- /dev/null +++ b/app/packages/link/src/app/s/[[...slug]]/page.tsx @@ -0,0 +1,47 @@ +'use client' + +import Image from 'next/image' +import styles from '../../page.module.css' +import note from '../../img/note-send.png' +import send from '../../img/payy-note-received.svg' +import { Button } from '../../../components/buttons/Button' +import { ClaimButton } from '@/components/buttons/claim-button' +import { useStoreRedirect } from '@/hooks/useStoreRedirect' + +export interface SendPaymentParams { + params: { + slug: string[] + } +} + +export default function SendPayment({ params }: SendPaymentParams) { + const referrerUrlPayyBaseUrl = 'https://payy.link' + const hash = typeof window !== 'undefined' ? window.location.hash : '' + const referrerUrl = `${referrerUrlPayyBaseUrl}/s/${params.slug?.join('/') || ''}${hash}` + + const handleRedirectToStore = useStoreRedirect({ + baseReferrerUrl: referrerUrl + }) + + return ( + <> +
+
+
+ Payy note +
+
+ Payy note received +
+ + +
+
+ + ) +} diff --git a/app/packages/link/src/app/steradian.ts b/app/packages/link/src/app/steradian.ts new file mode 100644 index 0000000..dcab823 --- /dev/null +++ b/app/packages/link/src/app/steradian.ts @@ -0,0 +1,26 @@ +import localFont from 'next/font/local' + +export const steradian = localFont({ + src: [ + { + path: '../fonts/Steradian-Rg.otf', + weight: '400', + style: 'normal' + }, + { + path: '../fonts/Steradian-Md.otf', + weight: '600', + style: 'normal' + }, + { + path: '../fonts/Steradian-Bd.otf', + weight: '700', + style: 'normal' + }, + { + path: '../fonts/Steradian-Blk.otf', + weight: '800', + style: 'normal' + } + ] +}) diff --git a/app/packages/link/src/app/twitter-image.png b/app/packages/link/src/app/twitter-image.png new file mode 100644 index 0000000..9e580a7 Binary files /dev/null and b/app/packages/link/src/app/twitter-image.png differ diff --git a/app/packages/link/src/components/PosthogInit.ts b/app/packages/link/src/components/PosthogInit.ts new file mode 100644 index 0000000..cd6a852 --- /dev/null +++ b/app/packages/link/src/components/PosthogInit.ts @@ -0,0 +1,12 @@ +'use client' + +import { initPosthog } from '@/config/posthog' +import { useEffect } from 'react' + +export default function PosthogInit() { + useEffect(() => { + initPosthog() + }, []) + + return null +} diff --git a/app/packages/link/src/components/buttons/Button.tsx b/app/packages/link/src/components/buttons/Button.tsx new file mode 100644 index 0000000..c23614c --- /dev/null +++ b/app/packages/link/src/components/buttons/Button.tsx @@ -0,0 +1,38 @@ +'use client' + +import styles from './component.module.css' +import { ReactNode } from 'react' +import { steradian } from '../../app/steradian' + +export interface ButtonProps { + url?: string + children: ReactNode + outline?: boolean + onClick?: () => void +} + +export function Button({ url, children, outline, onClick }: ButtonProps) { + const className = [ + steradian.className, + styles.btn, + outline ? styles.btn_outline : styles.btn_solid + ].join(' ') + + if (url && !onClick) { + return ( + + ) + } + + return ( +
+ +
+ ) +} diff --git a/app/packages/link/src/components/buttons/claim-button.tsx b/app/packages/link/src/components/buttons/claim-button.tsx new file mode 100644 index 0000000..f6e0275 --- /dev/null +++ b/app/packages/link/src/components/buttons/claim-button.tsx @@ -0,0 +1,15 @@ +'use client' + +import { PAYY_BASE_URL } from '../../config/constants' +import { Button } from './Button' + +export function ClaimButton(params: { slug?: string[] }) { + return ( + + ) +} diff --git a/app/packages/link/src/components/buttons/component.module.css b/app/packages/link/src/components/buttons/component.module.css new file mode 100644 index 0000000..459f6d9 --- /dev/null +++ b/app/packages/link/src/components/buttons/component.module.css @@ -0,0 +1,47 @@ +.btn_container { + display: flex; + justify-content: center; + align-items: center; + margin-top: 20px; +} + +.btn { + padding: 20px 50px; + width: 300px; + background-color: #242424; + border: none; + border-radius: 68px; + color: white; + font-size: 20px; + cursor: pointer; + transition: background-color 0.3s ease; + outline: none; + font-weight: 500; + letter-spacing: -0.05em; + border: 3px solid #242424; +} + +.btn_solid { + background-color: #242424; +} + +.btn_outline { + background-color: transparent; + border: 3px solid #242424; + color: #242424; + font-weight: 600; +} + +.btn_outline:hover { + color: #444; + border-color: #444; +} + +.btn_solid:hover { + background-color: #333333; +} + +.btn_solid:active { + background-color: #111; + outline: none; +} \ No newline at end of file diff --git a/app/packages/link/src/config/constants.ts b/app/packages/link/src/config/constants.ts new file mode 100644 index 0000000..fb574ad --- /dev/null +++ b/app/packages/link/src/config/constants.ts @@ -0,0 +1,3 @@ +export const PAYY_BASE_URL = 'payy://' +export const PAYY_REFERRER_BASE_URL = 'https://payy.link' +export const GUILD_URL = 'https://api.mainnet.payy.link/v2' diff --git a/app/packages/link/src/config/posthog.ts b/app/packages/link/src/config/posthog.ts new file mode 100644 index 0000000..774823b --- /dev/null +++ b/app/packages/link/src/config/posthog.ts @@ -0,0 +1,27 @@ +import posthog, { PostHog } from 'posthog-js' + +declare global { + interface Window { + posthogInitialized?: boolean + posthog: PostHog + } +} + +export const initPosthog = () => { + if (typeof window === 'undefined') return + + if (!window.posthogInitialized) { + posthog.init('phc_2WvD3IJabsDhmHALah3v5VA20yvEptB357mxuARI3b5', { + api_host: 'https://us.i.posthog.com', + defaults: '2025-05-24' + }) + + window.posthogInitialized = true + window.posthog = posthog + } +} + +export const getPosthogDistinctId = (): string | undefined => { + if (typeof window === 'undefined') return + return posthog.get_distinct_id() +} diff --git a/app/packages/link/src/fonts/Steradian-Bd.otf b/app/packages/link/src/fonts/Steradian-Bd.otf new file mode 100644 index 0000000..d6f208c Binary files /dev/null and b/app/packages/link/src/fonts/Steradian-Bd.otf differ diff --git a/app/packages/link/src/fonts/Steradian-Blk.otf b/app/packages/link/src/fonts/Steradian-Blk.otf new file mode 100644 index 0000000..8eb8380 Binary files /dev/null and b/app/packages/link/src/fonts/Steradian-Blk.otf differ diff --git a/app/packages/link/src/fonts/Steradian-Md.otf b/app/packages/link/src/fonts/Steradian-Md.otf new file mode 100644 index 0000000..ac3a773 Binary files /dev/null and b/app/packages/link/src/fonts/Steradian-Md.otf differ diff --git a/app/packages/link/src/fonts/Steradian-Rg.otf b/app/packages/link/src/fonts/Steradian-Rg.otf new file mode 100644 index 0000000..3cee8e9 Binary files /dev/null and b/app/packages/link/src/fonts/Steradian-Rg.otf differ diff --git a/app/packages/link/src/hooks/useFingerprint.ts b/app/packages/link/src/hooks/useFingerprint.ts new file mode 100644 index 0000000..9f97039 --- /dev/null +++ b/app/packages/link/src/hooks/useFingerprint.ts @@ -0,0 +1,64 @@ +'use client' + +import { useEffect, useState } from 'react' +import { UAParser } from 'ua-parser-js' + +// Properties common to, and with values +// the same for - Linky(Safari), Linky(Chrome), App (React Native) +export type MatchingUserAgent = { + device: { + type?: string + model?: string + vendor?: string + } + engine: { + name?: string + version?: string + } + os: { + name?: string + version?: string + } +} + +export type Fingerprint = { + user_agent: MatchingUserAgent + language: string + // timezone: string + screen: { + height: number + width: number + } +} + +export const useFingerprint = (): Fingerprint | null => { + const [fingerprint, setFingerprint] = useState(null) + + useEffect(() => { + if (typeof window === 'undefined') return + + const uaParser = new UAParser() + uaParser.setUA(navigator.userAgent) + const res = uaParser.getResult() + + const matchingUserAgent = { + device: res.device, + engine: res.engine, + os: res.os + } + + const data: Fingerprint = { + user_agent: matchingUserAgent, + language: navigator.language, + // timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + screen: { + height: window.screen.height, + width: window.screen.width + } + } + + setFingerprint(data) + }, []) + + return fingerprint +} diff --git a/app/packages/link/src/hooks/usePosthogDistinctId.ts b/app/packages/link/src/hooks/usePosthogDistinctId.ts new file mode 100644 index 0000000..93ed1eb --- /dev/null +++ b/app/packages/link/src/hooks/usePosthogDistinctId.ts @@ -0,0 +1,27 @@ +import { getPosthogDistinctId } from '@/config/posthog' +import { useEffect, useState } from 'react' + +export const usePosthogDistinctId = () => { + const [distinctId, setDistinctId] = useState(undefined) + + useEffect(() => { + let attempts = 0 + const maxAttempts = 10 + + const interval = setInterval(() => { + const id = getPosthogDistinctId() + + if (id) { + setDistinctId(id) + clearInterval(interval) + } else if (++attempts >= maxAttempts) { + console.warn('Posthog Distinct Id not available after retries') + clearInterval(interval) + } + }, 100) + + return () => clearInterval(interval) + }, []) + + return distinctId +} diff --git a/app/packages/link/src/hooks/useStoreRedirect.ts b/app/packages/link/src/hooks/useStoreRedirect.ts new file mode 100644 index 0000000..ad6c011 --- /dev/null +++ b/app/packages/link/src/hooks/useStoreRedirect.ts @@ -0,0 +1,71 @@ +'use client' + +import { GUILD_URL } from '@/config/constants' +import { useFingerprint } from '@/hooks/useFingerprint' +import { usePosthogDistinctId } from '@/hooks/usePosthogDistinctId' +import { detectBrowser } from '@/util/detectBrowser' +import { useCallback } from 'react' + +export interface StoreRedirectProps { + baseReferrerUrl: string +} + +export function useStoreRedirect({ baseReferrerUrl }: StoreRedirectProps) { + const fingerprint = useFingerprint() + const posthogDistinctId = usePosthogDistinctId() + const isIos = detectBrowser() === 'ios' + + const fullReferrerUrlIos = `${baseReferrerUrl}${baseReferrerUrl.includes('?') ? '&' : '?'}posthog_id=${posthogDistinctId}` + const encodedReferrerUrl = encodeURIComponent( + isIos ? fullReferrerUrlIos : baseReferrerUrl + ) + const storeUrl = `https://payy.link/download?referrer=${encodedReferrerUrl}` + + const redirectToStore = useCallback(async () => { + if (typeof window === 'undefined') return + + if (!isIos || !fingerprint || !posthogDistinctId) { + window.location.href = storeUrl + return + } + + // only for iOS + try { + const udhUrl = `${GUILD_URL}/udh` + + const payload = { + properties: fingerprint, + posthog_id: posthogDistinctId, + referrer_url: fullReferrerUrlIos + } + + const res = await fetch(udhUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }) + + const resData = await res.json() + const userDeviceHash = resData?.user_device_hash + + if (userDeviceHash) { + // identify with PostHog + window.posthog?.identify?.(posthogDistinctId) + window.posthog?.group?.('device', userDeviceHash) + // add the user device hash as an attribute + window.posthog?.setPersonProperties?.({ + user_device_hash: userDeviceHash + }) + } + } catch (err: any) { + console.error(`Failed to contact the /udh endpoint: ${err}`) + } finally { + // redirect to the app store + window.location.href = storeUrl + } + }, [fingerprint, fullReferrerUrlIos, isIos, posthogDistinctId, storeUrl]) + + return redirectToStore +} diff --git a/app/packages/link/src/util/appStoreUrl.tsx b/app/packages/link/src/util/appStoreUrl.tsx new file mode 100644 index 0000000..64bacf6 --- /dev/null +++ b/app/packages/link/src/util/appStoreUrl.tsx @@ -0,0 +1,10 @@ +// import { detectBrowser } from "./detectBrowser"; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function appStoreUrl(agent?: string) { + // const browser = detectBrowser(agent) + + // if (browser === 'android') return 'https://play.google.com/store/apps/details?id=com.polybaselabs.wallet' + + return 'https://testflight.apple.com/join/rKCavMy1' +} diff --git a/app/packages/link/src/util/detectBrowser.tsx b/app/packages/link/src/util/detectBrowser.tsx new file mode 100644 index 0000000..e7bbe0f --- /dev/null +++ b/app/packages/link/src/util/detectBrowser.tsx @@ -0,0 +1,21 @@ +export function detectBrowser( + agent?: string +): 'ios' | 'android' | 'blackberry' | null { + if (!agent) agent = navigator.userAgent + + // iPhone Version: + if (/iPhone|iPod|iPad/i.test(agent)) { + return 'ios' + } + + // Android Version: + if (agent.match(/android/i)) { + return 'android' + } + // Blackberry Version: + if (agent.match(/blackberry/i)) { + return 'blackberry' + } + + return null +} diff --git a/app/packages/link/tsconfig.eslint.json b/app/packages/link/tsconfig.eslint.json new file mode 100644 index 0000000..2d6724e --- /dev/null +++ b/app/packages/link/tsconfig.eslint.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts", "src/**/*.tsx"] +} diff --git a/app/packages/link/tsconfig.json b/app/packages/link/tsconfig.json new file mode 100644 index 0000000..e59724b --- /dev/null +++ b/app/packages/link/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/app/packages/link/types.d.ts b/app/packages/link/types.d.ts new file mode 100644 index 0000000..a8a10f1 --- /dev/null +++ b/app/packages/link/types.d.ts @@ -0,0 +1,9 @@ +declare module '*.png' { + const content: string + export default content +} + +declare module '*.svg' { + const content: string + export default content +} diff --git a/app/packages/network/.gitignore b/app/packages/network/.gitignore new file mode 100644 index 0000000..fd3dbb5 --- /dev/null +++ b/app/packages/network/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/app/packages/network/README.md b/app/packages/network/README.md new file mode 100644 index 0000000..5d589de --- /dev/null +++ b/app/packages/network/README.md @@ -0,0 +1,142 @@ +# Payy Network - ZK-Rollup Blockchain Explorer + +A Next.js application that serves as the blockchain explorer and network monitoring dashboard for Payy Network, the first mainnet ZK-ZK rollup. + +🌐 **Live Site**: [https://payy.network](https://payy.network) + +## Overview + +Payy Network is a zero-knowledge rollup blockchain explorer that provides real-time network statistics, transaction monitoring, and diagnostic tools for the ZK-rollup infrastructure. The application serves as the public-facing interface for monitoring network health, transaction activity, and blockchain data. + +## Key Features + +### 🏠 **Landing Page** (`/`) +- Network branding: "THE FIRST MAINNET ZK-ZK ROLLUP" +- Real-time network statistics display +- Average block time monitoring +- Sequencer and rollup height tracking + +### 🔍 **Blockchain Explorer** (`/explorer`) +- Interactive network statistics dashboard +- Transaction activity charts and visualizations +- Block and transaction monitoring panels +- Real-time data updates with Chart.js integration + +### 🔧 **Diagnostics** (`/diagnostics`) +- Detailed transaction analysis tools +- Wallet activity monitoring +- Note reconstruction and difference analysis +- Advanced network diagnostic capabilities +- CodeMirror-based code editors for transaction inspection + +## Technology Stack + +- **Framework**: Next.js 15.x with React 19 and TypeScript +- **UI Library**: Chakra UI v2 (React 19 compatible) with Framer Motion animations +- **Data Visualization**: Chart.js with React bindings +- **Data Fetching**: TanStack Query for API state management +- **HTTP Client**: Axios for API communications +- **Code Editor**: CodeMirror for transaction inspection + +## Internal Dependencies + +The Network application depends on two core services from the ZK-rollup infrastructure: + +### 📦 **pkg/guild** +The Guild service provides API endpoints for additional services above the protocol layer, including: +- Contract status and blockchain data +- User rewards and points system +- Wallet management and authentication +- Registry and note operations + +### 🔗 **pkg/node** +The Node service is the primary blockchain client that provides: +- Real-time network health metrics +- Transaction and block data +- Rollup height and sequencer information +- Network performance statistics + +## API Integration + +The application communicates with these internal services through their API endpoints: + +- **Guild API** (`NEXT_PUBLIC_GUILD_URL`): Connects to the `pkg/guild` service for contract status, blockchain data, and additional services +- **Rollup API** (`NEXT_PUBLIC_ROLLUP_URL`): Connects to the `pkg/node` service for network health and performance metrics + +## Getting Started + +### Prerequisites + +- Node.js 18+ +- Yarn (workspace manager) + +### Installation + +```bash +# From the app/ directory +yarn install +``` + +### Development + +```bash +# From the app/ directory +yarn workspace network dev +``` + +Open [http://localhost:3000](http://localhost:3000) to view the application. + +### Building + +```bash +# From the app/ directory +yarn workspace network build +``` + +## Code Quality + +This package follows the workspace ESLint configuration and TypeScript standards. Always run these commands after making changes: + +```bash +cd app +yarn lint +yarn lint:types +yarn test +``` + +## Environment Variables + +Configure the following environment variables to connect to the internal services: + +```bash +# Guild API endpoint - connects to pkg/guild service +# Provides contract status, blockchain data, and user services +NEXT_PUBLIC_GUILD_URL=your_guild_api_url + +# Rollup API endpoint - connects to pkg/node service +# Provides network health metrics and blockchain performance data +NEXT_PUBLIC_ROLLUP_URL=your_rollup_api_url +``` + +### Local Development + +For local development, you typically run these services separately: + +1. Start the Guild service: See [pkg/guild/README.md](../../../pkg/guild/README.md) +2. Start the Node service: See [pkg/node/README.md](../../../pkg/node/README.md) +3. Configure the environment variables to point to your local instances + +## Network Statistics + +The explorer displays key network metrics: + +- **Average Block Time**: Real-time block production rate +- **Sequencer Height**: Current sequencer block height +- **Rollup Height**: Current rollup block height +- **Transaction Volume**: Charts showing transaction activity over time + +## Deployment + +The application is deployed on Vercel and accessible at [https://payy.network](https://payy.network). + +For deployment configuration, see the Next.js deployment documentation. diff --git a/app/packages/network/next.config.mjs b/app/packages/network/next.config.mjs new file mode 100644 index 0000000..b1ece8f --- /dev/null +++ b/app/packages/network/next.config.mjs @@ -0,0 +1,32 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + webpack(config) { + // Grab the existing rule that handles SVG imports + const fileLoaderRule = config.module.rules.find((rule) => + rule.test?.test?.('.svg') + ) + + config.module.rules.push( + // Reapply the existing rule, but only for svg imports ending in ?url + { + ...fileLoaderRule, + test: /\.svg$/i, + resourceQuery: /url/ // *.svg?url + }, + // Convert all other *.svg imports to React components + { + test: /\.svg$/i, + issuer: fileLoaderRule.issuer, + resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url + use: ['@svgr/webpack'] + } + ) + + // Modify the file loader rule to ignore *.svg, since we have it handled now. + fileLoaderRule.exclude = /\.svg$/i + + return config + } +} + +export default nextConfig diff --git a/app/packages/network/package.json b/app/packages/network/package.json new file mode 100644 index 0000000..224436b --- /dev/null +++ b/app/packages/network/package.json @@ -0,0 +1,49 @@ +{ + "name": "network", + "version": "1.3.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint 'src/**/*.{ts,tsx}'", + "test": "echo 'No tests specified for network'" + }, + "dependencies": { + "@chakra-ui/icons": "^2.2.6", + "@chakra-ui/next-js": "^2.4.4", + "@chakra-ui/react": "^2.10.9", + "@codemirror/lang-javascript": "^6.2.2", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.0", + "@tanstack/react-query": "^5.32.1", + "@uiw/codemirror-theme-atomone": "^4.21.24", + "@uiw/codemirror-theme-tokyo-night": "^4.21.24", + "@uiw/codemirror-theme-vscode": "^4.21.24", + "@uiw/react-codemirror": "^4.21.24", + "axios": "^1.6.8", + "chart.js": "^4.4.2", + "framer-motion": "^11.0.8", + "json-diff-ts": "^4.0.1", + "lodash": "^4.17.21", + "next": "15.5.9", + "qrcode.react": "^3.1.0", + "react": "^19.1.0", + "react-async-hook": "^4.0.0", + "react-chartjs-2": "^5.2.0", + "react-dom": "^19.1.0", + "react-resizable": "^3.0.5", + "yarn": "^1.22.22" + }, + "devDependencies": { + "@svgr/webpack": "^8.1.0", + "@tanstack/react-query-devtools": "^5.32.1", + "@types/node": "^20", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.0", + "@types/react-resizable": "^3.0.7", + "eslint": "^9.18.0", + "eslint-config-next": "15.5.7", + "typescript": "^5" + } +} diff --git a/app/packages/network/public/icon.svg b/app/packages/network/public/icon.svg new file mode 100644 index 0000000..76977b8 --- /dev/null +++ b/app/packages/network/public/icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/packages/network/src/api.ts b/app/packages/network/src/api.ts new file mode 100644 index 0000000..473f128 --- /dev/null +++ b/app/packages/network/src/api.ts @@ -0,0 +1,116 @@ +import axios from 'axios' + +export interface Block { + hash: string + block: { + content: BlockContent + signature: number[] + } + time: number +} + +export interface BlockContent { + header: { + height: number + } + state: { + root_hash: string + txns: Txn[] + } + last_block_hash: number[] +} + +export interface Txn { + block_height: number + time: number + hash: string + proof: TxnProof + index_in_block: number +} + +export interface TxnProof { + proof: string + public_inputs: { + input_commitments: [string, string] + output_commitments: [string, string] + messages: string[] + } +} + +export interface BlocksResponse { + blocks: Block[] + cursor: { + before: string | null + after: string | null + } +} + +export interface TxnsResponse { + txns: Txn[] + cursor: { + before: string | null + after: string | null + } +} + +export interface StatsResponse { + last_7_days_txns: StatsDay[] +} + +export interface StatsDay { + date: string + count: number +} + +export interface TxnResponse { + txn: Txn +} + +export interface ElementRepsonse { + height: number + element: string +} + +export async function getBlocks(): Promise { + const res = await axios.get( + `${process.env.NEXT_PUBLIC_ROLLUP_URL}/blocks?limit=10&skip_empty=true` + ) + return res.data +} + +export async function getBlock(hash: string): Promise { + const res = await axios.get( + `${process.env.NEXT_PUBLIC_ROLLUP_URL}/blocks/${hash}` + ) + return res.data +} + +export interface ListTxnParams { + limit: number +} + +export async function getTxn(hash: string): Promise { + const res = await axios.get( + `${process.env.NEXT_PUBLIC_ROLLUP_URL}/transactions/${hash}` + ) + return res.data +} + +export async function getTxns(): Promise { + const res = await axios.get( + `${process.env.NEXT_PUBLIC_ROLLUP_URL}/transactions?limit=10` + ) + return res.data +} + +export async function getStats(): Promise { + const res = await axios.get(`${process.env.NEXT_PUBLIC_ROLLUP_URL}/stats`) + return res.data +} + +export async function getElement(hash: string): Promise { + const res = await axios.get( + `${process.env.NEXT_PUBLIC_ROLLUP_URL}/elements/${hash}` + ) + return res.data +} diff --git a/app/packages/network/src/app/diagnostics/Activity.tsx b/app/packages/network/src/app/diagnostics/Activity.tsx new file mode 100644 index 0000000..19707ad --- /dev/null +++ b/app/packages/network/src/app/diagnostics/Activity.tsx @@ -0,0 +1,112 @@ +'use client' + +import * as React from 'react' +import { + Box, + Heading, + Text, + Stack, + Spacer, + HStack, + Tag +} from '@chakra-ui/react' +import { useState } from 'react' +import { fromBigIntToCurrency } from './util' +import { map } from 'lodash' +import { WalletActivity, WalletActivityTxn } from '../../types' +import { resultColours } from './colors' +import { Txn } from './Txn' + +export interface ActivityListProps { + activities: Record +} + +export function ActivityList({ activities }: ActivityListProps) { + const activitiesArray = map( + activities, + (activity: WalletActivity, id: string) => ({ + id, + activity + }) + ) + + // Parent activities + const parentActivities = activitiesArray.filter((a) => !a.activity.parentId) + + return ( + + {map(parentActivities, ({ id, activity }) => { + const children = activitiesArray.filter( + (a) => a.activity.parentId === id + ) + return ( + + ) + })} + + ) +} + +export interface ActivityProps { + id: string + activity: WalletActivity + subActivities: { id: string; activity: WalletActivity }[] +} + +export function Activity({ activity, subActivities }: ActivityProps) { + const [isOpen, setIsOpen] = useState(false) + const value = + activity?.data?.value + ?? activity?.data?.note?.note?.value + ?? activity?.data?.outputs?.[0]?.note?.value + return ( + + + { + setIsOpen(!isOpen) + }} + > + {activity?.kind} + + + + {activity?.result ?? 'active'} + + + + {new Date(activity?.timestamp).toLocaleString()} + + {activity?.error && ( + + {activity?.error} ({activity?.errorCycles ?? 0}) + + )} + + + ${value ? fromBigIntToCurrency(BigInt(`0x${value}`)) : ''} + + + {isOpen && ( + + {map(subActivities, ({ id, activity }) => { + return + })} + + )} + + ) +} diff --git a/app/packages/network/src/app/diagnostics/DiffsPanel.tsx b/app/packages/network/src/app/diagnostics/DiffsPanel.tsx new file mode 100644 index 0000000..4d7fc1a --- /dev/null +++ b/app/packages/network/src/app/diagnostics/DiffsPanel.tsx @@ -0,0 +1,49 @@ +import { FC } from 'react' +import Panel from './Panel' + +const LS_DIFFS_KEY = 'diffs' +const LS_DIFFS_PANEL_WIDTH_KEY = 'diagnostics.diffs.panel.width' + +interface DiffsPanelProps { + diffs: string + setDiffs: (diff: string) => void + diffsPanelWidth: number + setDiffsPanelWidth: (width: number) => void + showToast: (description: string, success: boolean) => void + clearLocalStorage: () => void +} + +const DiffsPanel: FC = ({ + diffs, + setDiffs, + diffsPanelWidth, + setDiffsPanelWidth, + showToast, + clearLocalStorage +}: DiffsPanelProps) => { + const onDiffsChange = (value: string) => { + try { + JSON.parse(value) + localStorage.setItem(LS_DIFFS_KEY, value) + setDiffs(value) + showToast('Wallet backup diffs parsed successfully', true) + } catch (err) { + console.error(err) + showToast(`While parsing wallet state backup diffs: ${err}`, false) + } + } + + return ( + + ) +} + +export default DiffsPanel diff --git a/app/packages/network/src/app/diagnostics/LatestPanel.tsx b/app/packages/network/src/app/diagnostics/LatestPanel.tsx new file mode 100644 index 0000000..4807e2d --- /dev/null +++ b/app/packages/network/src/app/diagnostics/LatestPanel.tsx @@ -0,0 +1,49 @@ +import { FC } from 'react' +import Panel from './Panel' + +const LS_LATEST_KEY = 'latest' +const LS_LATEST_PANEL_WIDTH_KEY = 'diagnostics.latest.panel.width' + +interface LatestPanelProps { + latest: string + setLatest: (latest: string) => void + latestPanelWidth: number + setLatestPanelWidth: (width: number) => void + showToast: (description: string, success: boolean) => void + clearLocalStorage: () => void +} + +const LatestPanel: FC = ({ + latest, + setLatest, + latestPanelWidth, + setLatestPanelWidth, + showToast, + clearLocalStorage +}: LatestPanelProps) => { + const onLatestChange = (value: string) => { + try { + JSON.parse(value) + localStorage.setItem(LS_LATEST_KEY, value) + setLatest(value) + showToast('Latest wallet state parsed successfully', true) + } catch (err) { + console.error(err) + showToast(`While parsing latest wallet state: ${err}`, false) + } + } + + return ( + + ) +} + +export default LatestPanel diff --git a/app/packages/network/src/app/diagnostics/Note.tsx b/app/packages/network/src/app/diagnostics/Note.tsx new file mode 100644 index 0000000..e2e7562 --- /dev/null +++ b/app/packages/network/src/app/diagnostics/Note.tsx @@ -0,0 +1,60 @@ +'use client' + +import * as React from 'react' +import { Heading, Text, Stack, Spacer, HStack, Spinner } from '@chakra-ui/react' +import { CheckCircleIcon, WarningIcon } from '@chakra-ui/icons' +import { fromBigIntToCurrency } from './util' +import { StoredNote, Element } from '../../types' +import { useAsync } from 'react-async-hook' +import axios from 'axios' + +export interface NoteProps { + note: StoredNote + checkCommitment?: boolean + ownAddress?: Element +} + +export function Note({ note, ownAddress, checkCommitment }: NoteProps) { + const commitment = useAsync(async () => { + if (!checkCommitment) return + try { + const res = await axios.get( + `${process.env.NEXT_PUBLIC_ROLLUP_URL}/elements/${note.commitment}` + ) + return res.data + } catch (e: any) { + if (e?.response?.status === 404) { + throw new Error('Commitment not in tree') + } + throw e + } + }, []) + + return ( + + + {commitment.loading ? ( + + ) : commitment.error ? ( + + ) : ( + + )} + + {note?.commitment}{' '} + {commitment.result?.height ? `(${commitment.result?.height})` : ''} + {ownAddress && ( + + {note?.note?.address === ownAddress ? 'Internal' : 'External'} + + )} + + + + ${fromBigIntToCurrency(BigInt(`0x${note?.note?.value}`))} + + + {commitment.error && {commitment.error.message}} + + ) +} diff --git a/app/packages/network/src/app/diagnostics/Panel.tsx b/app/packages/network/src/app/diagnostics/Panel.tsx new file mode 100644 index 0000000..0999d6c --- /dev/null +++ b/app/packages/network/src/app/diagnostics/Panel.tsx @@ -0,0 +1,63 @@ +import { FC } from 'react' +import { Box } from '@chakra-ui/react' +import CodeMirror from '@uiw/react-codemirror' +import { javascript } from '@codemirror/lang-javascript' +import { codemirrorTheme } from '../../components/codemirror.theme' +import { debounce } from 'lodash' +import { ResizableBox } from 'react-resizable' +import '../../components/resize.styles.css' + +interface PanelProps { + title: string + localStoragePanelWidthKey: string + state: string + panelWidth: number + setPanelWidth: (width: number) => void + onChange: (value: string) => void + clearLocalStorage: () => void +} + +const Panel: FC = ({ + title, + localStoragePanelWidthKey, + state, + panelWidth, + setPanelWidth, + onChange +}: PanelProps) => { + const onPanelChange = debounce((_: any, data: any) => { + localStorage.setItem(localStoragePanelWidthKey, data.size.width) + setPanelWidth(data.size.width) + }, 400) + + return ( + + + + {title} + + + + + + + ) +} + +export default Panel diff --git a/app/packages/network/src/app/diagnostics/Section.tsx b/app/packages/network/src/app/diagnostics/Section.tsx new file mode 100644 index 0000000..7b22adb --- /dev/null +++ b/app/packages/network/src/app/diagnostics/Section.tsx @@ -0,0 +1,36 @@ +'use client' + +import * as React from 'react' +import { Box, Heading, Stack } from '@chakra-ui/react' +import { useState } from 'react' + +export function Section({ + title, + children +}: { + title: string + children: React.ReactNode +}) { + const [showSection, setShowSection] = useState( + typeof window !== 'undefined' + ? localStorage?.getItem(`diagnostics.section.show.${title}`) !== 'false' + : false + ) + + const onToggle = () => { + localStorage.setItem( + `diagnostics.section.show.${title}`, + (!showSection).toString() + ) + setShowSection(!showSection) + } + + return ( + + + {title} + + {showSection && {children}} + + ) +} diff --git a/app/packages/network/src/app/diagnostics/Txn.tsx b/app/packages/network/src/app/diagnostics/Txn.tsx new file mode 100644 index 0000000..1bad788 --- /dev/null +++ b/app/packages/network/src/app/diagnostics/Txn.tsx @@ -0,0 +1,107 @@ +'use client' + +import * as React from 'react' +import { + Box, + Heading, + Text, + Stack, + Spacer, + HStack, + Tag +} from '@chakra-ui/react' +import { fromBigIntToCurrency } from './util' +import { map } from 'lodash' +import { StoredNote, WalletActivityTxn } from '../../types' +import { Note } from './Note' +import { resultColours } from './colors' + +export interface TxnProps { + id: string + txn: WalletActivityTxn +} + +export function Txn({ txn }: TxnProps) { + const ownAddress = txn?.data?.inputs?.[0]?.note?.address + return ( + + + {txn?.kind} + + + {txn?.result ?? 'active'} + + + {new Date(txn?.timestamp).toLocaleString()} + {txn?.error && ( + + {txn?.error} ({txn?.errorCycles ?? 0}) + + )} + + + $ + {fromBigIntToCurrency( + BigInt(`0x${txn?.data?.outputs?.[0]?.note?.value}`) + )} + + + {txn?.data?.error && ( + + {txn?.data?.error.substring(0, 100)} + + )} + + + Root + {txn?.data?.root} + + + + + Inputs + + {map(txn?.data?.inputs, (input: StoredNote) => { + return ( + + ) + })} + + + + + Outputs + + {map(txn?.data?.outputs, (output: StoredNote) => { + return ( + + ) + })} + + + + + + ) +} diff --git a/app/packages/network/src/app/diagnostics/Wallet.tsx b/app/packages/network/src/app/diagnostics/Wallet.tsx new file mode 100644 index 0000000..1d2124f --- /dev/null +++ b/app/packages/network/src/app/diagnostics/Wallet.tsx @@ -0,0 +1,57 @@ +import { Box, Stack, Text } from '@chakra-ui/react' +import { Section } from './Section' +import { ActivityList } from './Activity' +import { calculateBalanceBigInt, fromBigIntToCurrency } from './util' +import { map, size } from 'lodash' +import { StoredNote, WalletState } from '@/types' +import { Note } from './Note' + +interface WalletProps { + wallet: WalletState +} + +const Wallet = ({ wallet }: WalletProps) => { + return ( + + +
+ + $ + {fromBigIntToCurrency( + calculateBalanceBigInt(wallet?.unspent_notes) + )} + +
+
+ + {map(wallet?.unspent_notes, (note: StoredNote) => { + return + })} + +
+ +
+ + {map(wallet?.spent_notes, (note: StoredNote) => { + return + })} + +
+ +
+ + {map(wallet?.invalid_notes, (note: StoredNote) => { + return + })} + +
+ +
+ +
+
+
+ ) +} + +export default Wallet diff --git a/app/packages/network/src/app/diagnostics/colors.ts b/app/packages/network/src/app/diagnostics/colors.ts new file mode 100644 index 0000000..90bfa35 --- /dev/null +++ b/app/packages/network/src/app/diagnostics/colors.ts @@ -0,0 +1,10 @@ +import { WalletActivityResultStatus } from '../../types' + +export type Status = Exclude | 'active' + +export const resultColours: Record = { + success: 'green', + error: 'red', + cancelled: 'gray', + active: 'blue' +} diff --git a/app/packages/network/src/app/diagnostics/page.tsx b/app/packages/network/src/app/diagnostics/page.tsx new file mode 100644 index 0000000..8c2e1f9 --- /dev/null +++ b/app/packages/network/src/app/diagnostics/page.tsx @@ -0,0 +1,102 @@ +'use client' + +import { Layout } from '../../components/Layout' +import { Box, useToast } from '@chakra-ui/react' +import { Dispatch, SetStateAction, useState } from 'react' +import '../../components/resize.styles.css' +import Wallet from './Wallet' +import { WalletState } from '@/types' +import { reconstructWalletsFromDiffs } from './reconstruct' +import LatestPanel from './LatestPanel' +import DiffsPanel from './DiffsPanel' + +const LS_LATEST_KEY = 'latest' +const LS_LATEST_PANEL_WIDTH_KEY = 'diagnostics.latest.panel.width' + +const LS_DIFFS_KEY = 'diffs' +const LS_DIFFS_PANEL_WIDTH_KEY = 'diagnostics.diffs.panel.width' + +export default function Home() { + const [latest, setLatest] = useState( + typeof window !== 'undefined' + ? (localStorage.getItem(LS_LATEST_KEY) ?? '{}') + : '{}' + ) + const storedLatestPanelWidth = + typeof window !== 'undefined' + ? localStorage.getItem(LS_LATEST_PANEL_WIDTH_KEY) + : undefined + const [latestPanelWidth, setLatestPanelWidth] = useState( + storedLatestPanelWidth ? parseInt(storedLatestPanelWidth, 10) : 300 + ) + const parsedLatest = JSON.parse(latest) + const wallet = parsedLatest?.wallet ?? (parsedLatest as WalletState) + + const [diffs, setDiffs] = useState( + typeof window !== 'undefined' + ? (localStorage.getItem('diffs') ?? '[]') + : '[]' + ) + const storedDiffsPanelWidth = + typeof window !== 'undefined' + ? localStorage.getItem(LS_DIFFS_PANEL_WIDTH_KEY) + : undefined + const [diffsPanelWidth, setDiffsPanelWidth] = useState( + storedDiffsPanelWidth ? parseInt(storedDiffsPanelWidth, 10) : 300 + ) + const parsedDiffs = JSON.parse(diffs) + + // the first entry in `walletStates` is the latest wallet state + const walletWithDiff = parsedDiffs.length + ? reconstructWalletsFromDiffs(wallet, parsedDiffs) + : {} + + const toast = useToast() + + const clearLocalStorage = ( + storageKey: string, + setState: Dispatch>, + defaultValue: string + ) => { + localStorage.removeItem(storageKey) + setState(defaultValue) + } + + const showToast = (description: string, success: boolean) => { + toast({ + title: success ? 'Parsed JSON' : 'Error parsing JSON', + description, + status: success ? 'success' : 'error', + duration: 3000, + isClosable: true + }) + } + + return ( + + + + clearLocalStorage(LS_LATEST_KEY, setLatest, '{}') + } + showToast={showToast} + /> + + clearLocalStorage(LS_DIFFS_KEY, setDiffs, '[]') + } + showToast={showToast} + /> + + + + ) +} diff --git a/app/packages/network/src/app/diagnostics/reconstruct.ts b/app/packages/network/src/app/diagnostics/reconstruct.ts new file mode 100644 index 0000000..943a31b --- /dev/null +++ b/app/packages/network/src/app/diagnostics/reconstruct.ts @@ -0,0 +1,26 @@ +import { WalletState } from '@/types' +import { applyChangeset } from 'json-diff-ts' +import { cloneDeep } from 'lodash' + +/** + * Reconstruct the wallet state from the currently available latest backup and a wallet backup as a diff. + * + * @param latestBackup + * @param diffs + */ +export const reconstructWalletsFromDiffs = ( + latestBackup: any, + diffs: any[] +): WalletState => { + if (!diffs.length) return latestBackup + + // clone to avoid mutation to the original state + const currBackup = cloneDeep(latestBackup) + + try { + return applyChangeset(currBackup, diffs) + } catch (err) { + console.error('Error while reconstructing state from backup: ', err) + throw err + } +} diff --git a/app/packages/network/src/app/diagnostics/util.ts b/app/packages/network/src/app/diagnostics/util.ts new file mode 100644 index 0000000..8b71958 --- /dev/null +++ b/app/packages/network/src/app/diagnostics/util.ts @@ -0,0 +1,58 @@ +import { Element, StoredNote } from '../../types' + +export function calculateBalanceBigInt( + notes?: Record +): bigint { + if (!notes) return BigInt(0) + return Object.values(notes).reduce((total, note) => { + return total + BigInt(`0x${note.note.value}`) + }, BigInt(0)) +} + +export function fromElementToBigInt(element?: Element | null): bigint { + if (!element) return BigInt(0) + return BigInt(`0x${element}`) +} + +export function parseCurrencyToBigInt(currencyString: string): bigint { + // Remove the dollar sign and other non-numeric characters + const numericString = currencyString.replace(/[^0-9.]/g, '') + + // Split the string into whole and decimal parts + const [whole, decimalRaw] = numericString.split('.') + + // Ensure the decimal part has 6 digits (USDC has 6 decimal places) + const decimal = ((decimalRaw ?? '') + '000000').slice(0, 6) + + // Combine the whole and decimal parts + const combined = whole + decimal + + // Convert to BigInt + return BigInt(combined) +} + +export function fromBigIntToCurrency(balance: bigint): string { + const balanceString = balance.toString().padStart(6, '0') + const whole = balanceString.slice(0, -6) ?? '0' + const decimal = balanceString.slice(-6).slice(0, 2).padStart(2, '0') + const wholeWithComma = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + const wholeWithDefault = wholeWithComma === '' ? '0' : wholeWithComma + if (decimal === '00') return wholeWithDefault + return `${wholeWithDefault}.${decimal}` +} + +export function toElement(number: number | bigint): Element { + const hex = number.toString(16) + if (hex.length > 64) throw new Error('Number is too large') + return hex.padStart(64, '0') +} + +export function toElementFromHex(hex: string): Element { + if (hex.startsWith('0x')) hex = hex.slice(2) + if (hex.length > 64) throw new Error('Hex is too large') + return hex.padStart(64, '0') +} + +export function toBigInt(number: number | bigint): bigint { + return BigInt(number) +} diff --git a/app/packages/network/src/app/explorer/blocks/[hash]/page.tsx b/app/packages/network/src/app/explorer/blocks/[hash]/page.tsx new file mode 100644 index 0000000..2ad8b53 --- /dev/null +++ b/app/packages/network/src/app/explorer/blocks/[hash]/page.tsx @@ -0,0 +1,73 @@ +'use client' + +import { use } from 'react' +import { SimpleGrid, Stack, Heading, Text } from '@chakra-ui/react' +import { useQuery } from '@tanstack/react-query' +import { getBlock } from '../../../../api' +import { BlockPanel } from '../../../../components/BlockPanel' +import { HashLinkPanel } from '../../../../components/HashLinkPanel' +import { HashPanel } from '../../../../components/HashPanel' +import { PageDetail } from '../../../../components/PageDetail' +import { StatusPanel } from '../../../../components/StatusPanel' +import { TimePanel } from '../../../../components/TimePanel' + +type BlockPageProps = { params: Promise<{ hash: string }> } + +export default function Block({ params }: BlockPageProps) { + const { hash } = use(params) + + const query = useQuery({ + queryKey: ['blocks', hash], + queryFn: async () => { + const data = await getBlock(hash) + return data + } + }) + + const txns = query.data?.block.content.state.txns + + return ( + + + + + + + + + + + + + + + + + + Transactions ({query.data?.block.content.state.txns.length ?? 0}) + + + {txns?.length ? ( + txns.map((txn, i) => { + return ( + + + + ) + }) + ) : ( + No transactions in this block + )} + + + + ) +} diff --git a/app/packages/network/src/app/explorer/elements/[hash]/page.tsx b/app/packages/network/src/app/explorer/elements/[hash]/page.tsx new file mode 100644 index 0000000..0b36776 --- /dev/null +++ b/app/packages/network/src/app/explorer/elements/[hash]/page.tsx @@ -0,0 +1,42 @@ +'use client' + +import { use } from 'react' +import { SimpleGrid, Stack } from '@chakra-ui/react' +import { useQuery } from '@tanstack/react-query' +import { getElement } from '../../../../api' +import { HashPanel } from '../../../../components/HashPanel' +import { PageDetail } from '../../../../components/PageDetail' +import { StatusPanel } from '../../../../components/StatusPanel' + +type ElementPageProps = { params: Promise<{ hash: string }> } + +export default function Element({ params }: ElementPageProps) { + const { hash } = use(params) + + const query = useQuery({ + queryKey: ['elements', hash], + queryFn: async () => { + const data = await getElement(hash) + return data + } + }) + + return ( + + + + + + + + + + + + + ) +} diff --git a/app/packages/network/src/app/explorer/page.tsx b/app/packages/network/src/app/explorer/page.tsx new file mode 100644 index 0000000..06a05d0 --- /dev/null +++ b/app/packages/network/src/app/explorer/page.tsx @@ -0,0 +1,62 @@ +'use client' + +import { Panel } from '../../components/Panel' +import { Layout } from '../../components/Layout' +import { SimpleGrid, Center, Stack, Box, Heading } from '@chakra-ui/react' +import { useNetworkData } from '../../components/useNetworkData' +import { BlocksPanel } from '../../components/BlocksPanel' +import { TxnChart } from '../../components/TxnChart' +import { TxnsPanel } from '../../components/TxnsPanel' + +export default function Explorer() { + const { rollupHeight, avgTime, contractHeight } = useNetworkData() + + return ( + + + + + + +
+ + {avgTime}s + +
+
+
+ + +
+ + {rollupHeight?.toLocaleString()} + +
+
+
+ + +
+ + {contractHeight?.toLocaleString()} + +
+
+
+
+ + + + + + + + + + + +
+
+
+ ) +} diff --git a/app/packages/network/src/app/explorer/transactions/[hash]/page.tsx b/app/packages/network/src/app/explorer/transactions/[hash]/page.tsx new file mode 100644 index 0000000..81be099 --- /dev/null +++ b/app/packages/network/src/app/explorer/transactions/[hash]/page.tsx @@ -0,0 +1,113 @@ +'use client' + +import { use } from 'react' +import { Heading, SimpleGrid, Stack } from '@chakra-ui/react' +import { useQuery } from '@tanstack/react-query' +import { getBlock, getTxn } from '../../../../api' +import { BlockPanel } from '../../../../components/BlockPanel' +import { HashLinkPanel } from '../../../../components/HashLinkPanel' +import { HashPanel } from '../../../../components/HashPanel' +import { PageDetail } from '../../../../components/PageDetail' +import { Panel } from '../../../..//components/Panel' +import { StatusPanel } from '../../../../components/StatusPanel' +import { TimePanel } from '../../../../components/TimePanel' + +const NULL_LEAF = + '0000000000000000000000000000000000000000000000000000000000000000' + +type TxnPageProps = { params: Promise<{ hash: string }> } + +export default function Txn({ params }: TxnPageProps) { + const { hash } = use(params) + + const query = useQuery({ + queryKey: ['txns', hash], + queryFn: async () => { + const data = await getTxn(hash) + return data + } + }) + + const height = query.data?.txn.block_height + + const blockQuery = useQuery({ + queryKey: ['block', query.data?.txn.block_height], + queryFn: async () => { + if (!height) return + const data = await getBlock(`${height}`) + return data + } + }) + + return ( + + + + + + + + + + {blockQuery.data?.hash ? ( + + ) : null} + + + + + + Inputs/Outputs + + + {query.data?.txn.proof.public_inputs.input_commitments + ?.filter((leaf) => leaf !== NULL_LEAF) + .map((input) => ( + + ))} + + + {query.data?.txn.proof.public_inputs.output_commitments + ?.filter((leaf) => leaf !== NULL_LEAF) + .map((input) => ( + + ))} + + + + + + Proof + + + {query.data?.txn.proof.proof} + + + + + ) +} diff --git a/app/packages/network/src/app/icon.png b/app/packages/network/src/app/icon.png new file mode 100644 index 0000000..09e68d9 Binary files /dev/null and b/app/packages/network/src/app/icon.png differ diff --git a/app/packages/network/src/app/layout.tsx b/app/packages/network/src/app/layout.tsx new file mode 100644 index 0000000..9e7af8a --- /dev/null +++ b/app/packages/network/src/app/layout.tsx @@ -0,0 +1,35 @@ +import * as React from 'react' +import type { Metadata, Viewport } from 'next' +import { Providers } from './providers' +import { steradian } from './steradian' + +export const metadata: Metadata = { + metadataBase: new URL( + process.env.NODE_ENV === 'production' + ? 'https://payy.network' + : 'http://localhost:3000' + ), + title: 'Payy Network', + description: 'Payy Network powers Payy, a new way to pay for things.' +} + +export const viewport: Viewport = { + width: 'device-width', + initialScale: 1, + maximumScale: 1, + userScalable: false +} + +export default function RootLayout({ + children +}: Readonly<{ + children: React.ReactNode +}>) { + return ( + + + {children} + + + ) +} diff --git a/app/packages/network/src/app/opengraph-image.png b/app/packages/network/src/app/opengraph-image.png new file mode 100644 index 0000000..522271d Binary files /dev/null and b/app/packages/network/src/app/opengraph-image.png differ diff --git a/app/packages/network/src/app/page.module.css b/app/packages/network/src/app/page.module.css new file mode 100644 index 0000000..7ca5ca9 --- /dev/null +++ b/app/packages/network/src/app/page.module.css @@ -0,0 +1,5 @@ +.main { + font-weight: bold; + padding: 100px; + font-size: 50px; +} \ No newline at end of file diff --git a/app/packages/network/src/app/page.tsx b/app/packages/network/src/app/page.tsx new file mode 100644 index 0000000..b2bb303 --- /dev/null +++ b/app/packages/network/src/app/page.tsx @@ -0,0 +1,125 @@ +'use client' + +import { + Center, + Heading, + Box, + Stack, + HStack, + Button, + Text +} from '@chakra-ui/react' +import Image from 'next/image' +import { Layout } from '../components/Layout' +import { Logo } from '../components/Logo' +import { useIsMobile } from '../components/useIsMobile' +import Link from 'next/link' +import { useNetworkData } from '../components/useNetworkData' + +export default function Home() { + const isMobile = useIsMobile() + const { rollupHeight, avgTime, contractHeight } = useNetworkData() + + return ( + + + +
+ + The end-game for stablecoins + +
+
+ + + Payy Network is the first vertically integrated stablecoin + payments network that enables onchain finance for all of + humanity. + + +
+
+ +
+ +
+ + + Powering + + + + + +
+
+
+ {rollupHeight && ( + + + + + + )} +
+ + + globe + + +
+
+
+ ) +} + +interface StatProps { + title: string + value?: string | number | null +} + +function Stat({ title, value }: StatProps) { + return ( + + + {title} + + + {value} + + + ) +} diff --git a/app/packages/network/src/app/providers.tsx b/app/packages/network/src/app/providers.tsx new file mode 100644 index 0000000..9cccbeb --- /dev/null +++ b/app/packages/network/src/app/providers.tsx @@ -0,0 +1,28 @@ +'use client' + +import * as React from 'react' +import { theme } from './theme' +import { ChakraProvider } from '@chakra-ui/react' +// import { ReactQueryDevtools } from '@tanstack/react-query-devtools' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' + +// const queryClient = new QueryClient() + +export function Providers({ children }: { children: React.ReactNode }) { + const [queryClient] = React.useState( + () => + new QueryClient({ + defaultOptions: { + queries: { + staleTime: 5 * 1000 + } + } + }) + ) + return ( + + {children} + {/* */} + + ) +} diff --git a/app/packages/network/src/app/steradian.ts b/app/packages/network/src/app/steradian.ts new file mode 100644 index 0000000..dcab823 --- /dev/null +++ b/app/packages/network/src/app/steradian.ts @@ -0,0 +1,26 @@ +import localFont from 'next/font/local' + +export const steradian = localFont({ + src: [ + { + path: '../fonts/Steradian-Rg.otf', + weight: '400', + style: 'normal' + }, + { + path: '../fonts/Steradian-Md.otf', + weight: '600', + style: 'normal' + }, + { + path: '../fonts/Steradian-Bd.otf', + weight: '700', + style: 'normal' + }, + { + path: '../fonts/Steradian-Blk.otf', + weight: '800', + style: 'normal' + } + ] +}) diff --git a/app/packages/network/src/app/theme.ts b/app/packages/network/src/app/theme.ts new file mode 100644 index 0000000..55b9d1e --- /dev/null +++ b/app/packages/network/src/app/theme.ts @@ -0,0 +1,106 @@ +import { extendTheme } from '@chakra-ui/react' +import { steradian } from './steradian' + +const mode = (light: any, _dark: any) => ({ default: light, _dark }) + +export const theme = extendTheme({ + fonts: { + heading: + steradian.style.fontFamily + + ', Steradian, "Open Sans", "Source Sans Pro", Arial, Helvetica, sans-serif', + body: + steradian.style.fontFamily + + ', Steradian, "Open Sans", "Source Sans Pro", Arial, Helvetica, sans-serif' + }, + styles: { + global: () => ({ + '*': { + margin: 0, + padding: 0, + boxSizing: 'border-box', + letterSpacing: '-1px' + }, + '.reset > *': { + letterSpacing: 0 + }, + 'html, body, #root': { + height: '100%', + fontSize: '16px', + color: '#fff' + }, + body: { + borderTop: '2px solid #E0FF32', + fontFamily: + steradian.style.fontFamily + + ', Steradian, "Open Sans", "Source Sans Pro", Arial, Helvetica, sans-serif', + backgroundColor: '#111', + color: '#fff' + } + }) + }, + colors: { + white: '#111', + black: '#fff', + primary: '#E0FF32', + brand: { + 0: '#FBFFEC', + 50: '#FBFFE5', + 100: '#F4FFB8', + 200: '#EDFF8A', + 300: '#E6FF5C', + 400: '#DFFF2E', + 500: '#E0FF32', // D8FF00 + 600: '#ADCC00', + 700: '#829900', + 800: '#576600', + 900: '#2B3300', + 950: '#151b00' + }, + gray: { + 0: '#FCFCFC', + 50: '#F5F5F5', + 100: '#E5E5E5', + 200: '#DBDBDB', + 300: '#D4D4D4', + 400: '#A3A3A3', + 500: '#8C8C8C', + 600: '#737373', + 700: '#525252', + 800: '#404040', + 850: '#2D2D2D', + 900: '#242424', + 950: '#161616' + }, + blue: { + 50: '#E5E6FF', + 100: '#B8B9FF', + 200: '#8A8DFF', + 300: '#5C60FF', + 400: '#2E33FF', + 500: '#1D23FF', + 600: '#0005CC', + 700: '#000499', + 800: '#000366', + 900: '#000133' + } + }, + semanticTokens: { + colors: { + error: 'red.500', + warning: mode('#ca4b03c7', '#cc630887'), + bws: mode('rgba(255, 255, 255)', 'rgba(15, 17, 22)'), + 'bws.100': mode('rgba(240, 240, 240)', 'rgba(29, 31, 36)'), + 'bw.10': mode('rgba(0, 0, 0, 0.01)', 'rgba(255, 255, 255, 0.01)'), + 'bw.50': mode('rgba(0, 0, 0, 0.04)', 'rgba(255, 255, 255, 0.04)'), + 'bw.100': mode('rgba(0, 0, 0, 0.06)', 'rgba(255, 255, 255, 0.06)'), + 'bw.200': mode('rgba(0, 0, 0, 0.08)', 'rgba(255, 255, 255, 0.08)'), + 'bw.300': mode('rgba(0, 0, 0, 0.16)', 'rgba(255, 255, 255, 0.16)'), + 'bw.400': mode('rgba(0, 0, 0, 0.24)', 'rgba(255, 255, 255, 0.24)'), + 'bw.500': mode('rgba(0, 0, 0, 0.36)', 'rgba(255, 255, 255, 0.36)'), + 'bw.600': mode('rgba(0, 0, 0, 0.48)', 'rgba(255, 255, 255, 0.48)'), + 'bw.700': mode('rgba(0, 0, 0, 0.64)', 'rgba(255, 255, 255, 0.64)'), + 'bw.800': mode('rgba(0, 0, 0, 0.80)', 'rgba(255, 255, 255, 0.80)'), + 'bw.900': mode('rgba(0, 0, 0, 0.92)', 'rgba(255, 255, 255, 0.92)') + } + } +}) diff --git a/app/packages/network/src/app/twitter-image.png b/app/packages/network/src/app/twitter-image.png new file mode 100644 index 0000000..9e580a7 Binary files /dev/null and b/app/packages/network/src/app/twitter-image.png differ diff --git a/app/packages/network/src/components/BlockPanel.tsx b/app/packages/network/src/components/BlockPanel.tsx new file mode 100644 index 0000000..59af0ae --- /dev/null +++ b/app/packages/network/src/components/BlockPanel.tsx @@ -0,0 +1,16 @@ +import { Heading } from '@chakra-ui/react' +import { Panel } from './Panel' + +export interface BlockPanelProps { + height?: number +} + +export function BlockPanel({ height }: BlockPanelProps) { + return ( + + + {height ?? '-'} + + + ) +} diff --git a/app/packages/network/src/components/BlocksPanel.tsx b/app/packages/network/src/components/BlocksPanel.tsx new file mode 100644 index 0000000..ec5ba18 --- /dev/null +++ b/app/packages/network/src/components/BlocksPanel.tsx @@ -0,0 +1,38 @@ +'use client' + +import { useQuery } from '@tanstack/react-query' +import { getBlocks } from '../api' +import { Stack, Text, Divider, HStack } from '@chakra-ui/react' +import { Panel } from './Panel' +import { timeSince } from './date' +import { LinkBox } from './LinkBox' + +export function BlocksPanel() { + const query = useQuery({ + queryKey: ['blocks'], + queryFn: getBlocks, + refetchInterval: 1000 + }) + + return ( + + }> + {query.data?.blocks.map((block) => { + return ( + + {block.hash} + + + {block.block.content.header.height} + + + {timeSince(block.time * 1000, true)} + + + + ) + })} + + + ) +} diff --git a/app/packages/network/src/components/HashLinkPanel.tsx b/app/packages/network/src/components/HashLinkPanel.tsx new file mode 100644 index 0000000..01684dc --- /dev/null +++ b/app/packages/network/src/components/HashLinkPanel.tsx @@ -0,0 +1,21 @@ +import { Heading } from '@chakra-ui/react' +import { Panel } from './Panel' +import { LinkBox } from './LinkBox' + +export interface HashLinkPanelProps { + title: string + hash: string + base: 'blocks' | 'elements' | 'transactions' +} + +export function HashLinkPanel({ title, hash, base }: HashLinkPanelProps) { + return ( + + + + {hash} + + + + ) +} diff --git a/app/packages/network/src/components/HashPanel.tsx b/app/packages/network/src/components/HashPanel.tsx new file mode 100644 index 0000000..b19101c --- /dev/null +++ b/app/packages/network/src/components/HashPanel.tsx @@ -0,0 +1,48 @@ +'use client' + +import { Heading, Stack, useBreakpoint } from '@chakra-ui/react' +import { Panel } from './Panel' +// import QRCode from 'react-qr-code' +import { QRCodeSVG } from 'qrcode.react' + +export interface HashPanelProps { + hash: string + base: 'blocks' | 'elements' | 'transactions' +} + +export function HashPanel({ hash, base }: HashPanelProps) { + const breakpoint = useBreakpoint() + const qrCodeValue = `${window.location.origin ?? ''}/explorer/${base}/${hash}` + + return ( + + + + {hash} + + {breakpoint === 'xs' + || breakpoint === 'sm' + || breakpoint === 'base' ? null : ( + + // + )} + + + ) +} diff --git a/app/packages/network/src/components/Layout.tsx b/app/packages/network/src/components/Layout.tsx new file mode 100644 index 0000000..510ab3a --- /dev/null +++ b/app/packages/network/src/components/Layout.tsx @@ -0,0 +1,95 @@ +'use client' + +import { + Box, + HStack, + Heading, + Spacer, + DrawerOverlay, + Drawer, + DrawerContent +} from '@chakra-ui/react' +import { HamburgerIcon } from '@chakra-ui/icons' +import { ReactNode, useState } from 'react' +import Link from 'next/link' +import { Logo } from './Logo' +import { Menu } from './Menu' +import { useIsMobile } from './useIsMobile' + +export interface LayoutProps { + line?: boolean + children: ReactNode +} + +export function Layout({ children, line }: LayoutProps) { + const [isOpen, setIsOpen] = useState(false) + + const sm = useIsMobile() + + return ( + <> + + + + + + + NETWORK + + + + + + {sm ? ( + { + setIsOpen(true) + }} + > + + + ) : ( + + )} + + + + {children} + + + {sm && ( + { + setIsOpen(false) + }} + > + + + + { + setIsOpen(false) + }} + /> + + + + )} + + ) +} diff --git a/app/packages/network/src/components/LinkBox.tsx b/app/packages/network/src/components/LinkBox.tsx new file mode 100644 index 0000000..2c07f96 --- /dev/null +++ b/app/packages/network/src/components/LinkBox.tsx @@ -0,0 +1,23 @@ +import { ReactNode } from 'react' +import { Box } from '@chakra-ui/react' +import Link from 'next/link' +import { Url } from 'next/dist/shared/lib/router/router' + +export interface LinkBoxProps { + children: ReactNode + href: Url +} + +export function LinkBox({ children, href }: LinkBoxProps) { + return ( + + + {children} + + + ) +} diff --git a/app/packages/network/src/components/Logo.tsx b/app/packages/network/src/components/Logo.tsx new file mode 100644 index 0000000..29f4fb4 --- /dev/null +++ b/app/packages/network/src/components/Logo.tsx @@ -0,0 +1,21 @@ +import * as React from 'react' + +export interface LogoProps { + color?: string + style?: React.CSSProperties + className?: string + width?: string | number + height?: string | number + fill?: string +} + +export const Logo = (props: LogoProps) => ( + + + +) diff --git a/app/packages/network/src/components/Menu.tsx b/app/packages/network/src/components/Menu.tsx new file mode 100644 index 0000000..98a03df --- /dev/null +++ b/app/packages/network/src/components/Menu.tsx @@ -0,0 +1,48 @@ +import { Box, Button, Heading } from '@chakra-ui/react' +import Link from 'next/link' + +export const MENU = [ + { + title: 'Docs', + href: 'https://payy.network/docs', + target: '_blank' + }, + { + title: 'Explorer', + href: '/explorer' + } +] + +export interface MenuProps { + vertical?: boolean + onClick?: () => void +} + +export function Menu({ vertical, onClick }: MenuProps) { + return ( + + {MENU.map(({ title, href, target }) => ( + + + {title} + + + ))} + + + ) +} diff --git a/app/packages/network/src/components/PageDetail.tsx b/app/packages/network/src/components/PageDetail.tsx new file mode 100644 index 0000000..fc5187d --- /dev/null +++ b/app/packages/network/src/components/PageDetail.tsx @@ -0,0 +1,35 @@ +import { ReactNode } from 'react' +import { Layout } from './Layout' +import { Stack, Box, Heading } from '@chakra-ui/react' + +export interface PageDetailProps { + title: string + children: ReactNode + loading?: boolean + notFound?: boolean +} + +export function PageDetail({ + title, + children, + loading, + notFound +}: PageDetailProps) { + const status = notFound ? 'Not found' : loading ? 'Loading...' : undefined + return ( + + + {title} + + {status ? ( + + {status} + + ) : ( + children + )} + + + + ) +} diff --git a/app/packages/network/src/components/Panel.tsx b/app/packages/network/src/components/Panel.tsx new file mode 100644 index 0000000..b972d1e --- /dev/null +++ b/app/packages/network/src/components/Panel.tsx @@ -0,0 +1,49 @@ +import { ExternalLinkIcon } from '@chakra-ui/icons' +import { Box, Heading } from '@chakra-ui/react' +import { ReactNode } from 'react' + +export interface PanelProps { + title: string + titleLink?: string + children: ReactNode +} + +export function Panel({ title, titleLink, children }: PanelProps) { + const titleContent = titleLink ? ( + + {title} + + ) : ( + title + ) + + return ( + + + + {titleContent} + + + {children} + + ) +} diff --git a/app/packages/network/src/components/StatusPanel.tsx b/app/packages/network/src/components/StatusPanel.tsx new file mode 100644 index 0000000..77e69c1 --- /dev/null +++ b/app/packages/network/src/components/StatusPanel.tsx @@ -0,0 +1,45 @@ +import { HStack, Heading, Stack, Text, Box } from '@chakra-ui/react' +import { Panel } from './Panel' +import { useNetworkData } from './useNetworkData' +import TickIcon from '../img/tick.svg' + +export interface StatusPanelProps { + height?: number + type?: 'Element' | 'Block' | 'Transaction' +} + +export function StatusPanel({ height, type }: StatusPanelProps) { + const { contractHeight } = useNetworkData() + const isHard = contractHeight && height && contractHeight >= height + + const STATUSES = { + soft: { + title: 'Soft confirmation', + desc: `${type ?? 'Block'} has been included in a sequenced block, but has not been rolled up to the L1 chain.`, + color: 'green' + }, + hard: { + title: 'Hard confirmation', + desc: `${type ?? 'Block'} has been rolled up to base layer (Polygon) and now has the full security of the base layer`, + color: 'green' + } + } + + const status = isHard ? STATUSES.hard : STATUSES.soft + + return ( + + + + + + + + {status.title} + + + {status.desc} + + + ) +} diff --git a/app/packages/network/src/components/TimePanel.tsx b/app/packages/network/src/components/TimePanel.tsx new file mode 100644 index 0000000..ace99a4 --- /dev/null +++ b/app/packages/network/src/components/TimePanel.tsx @@ -0,0 +1,22 @@ +import { Heading, Stack, Text } from '@chakra-ui/react' +import { Panel } from './Panel' +import { timeSince } from './date' + +export interface TimePanelProps { + timestamp?: number +} + +export function TimePanel({ timestamp }: TimePanelProps) { + return ( + + + + {timestamp ? new Date(timestamp * 1000).toISOString() : 'Loading...'} + + + {timestamp ? timeSince(timestamp * 1000) : '-'} + + + + ) +} diff --git a/app/packages/network/src/components/TxnChart.tsx b/app/packages/network/src/components/TxnChart.tsx new file mode 100644 index 0000000..51f1a76 --- /dev/null +++ b/app/packages/network/src/components/TxnChart.tsx @@ -0,0 +1,124 @@ +'use client' + +import { Box } from '@chakra-ui/react' +import { getStats } from '../api' +import { useMemo } from 'react' +import { useQuery } from '@tanstack/react-query' +import { Line } from 'react-chartjs-2' +import { + Chart as ChartJS, + CategoryScale, + LinearScale, + PointElement, + LineElement, + Title, + Filler, + Tooltip, + Legend +} from 'chart.js' + +ChartJS.register( + CategoryScale, + LinearScale, + PointElement, + LineElement, + Title, + Filler, + Tooltip, + Legend +) + +export const options = { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + display: false + }, + title: { + display: false + } + }, + elements: { + point: { + radius: 0 + }, + line: { + tension: 0.4 + } + }, + scales: { + x: { + grid: { + lineWidth: 0, + display: false + }, + border: { + display: false + } + }, + y: { + border: { + display: false + }, + beginAtZero: true, + position: 'right', + ticks: { + maxTicksLimit: 5, + color: '#ffffff44' + }, + grid: { + color: '#ffffff05' + } + } + } +} + +export function TxnChart() { + const query = useQuery({ queryKey: ['stats'], queryFn: getStats }) + const txns = query.data?.last_7_days_txns + + const gradient = useMemo(() => { + if (typeof window === 'undefined') return + const canvas = document?.createElement('canvas') + const ctx = canvas?.getContext('2d') + const gradient = ctx?.createLinearGradient(0, 0, 0, 200) + gradient?.addColorStop(0, 'rgba(224, 255, 50, 0.2)') // the start color with 50% opacity + gradient?.addColorStop(1, 'rgba(224, 255, 50, 0)') + return gradient + }, []) + + const dates = useMemo(() => { + return txns?.map((txn) => new Date(txn.date)) ?? [] + // const now = new Date() + // const start = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())) + // return Array.from({ length: 7 }, (_, i) => new Date(+start - i * 24 * 60 * 60 * 1000)).reverse() + }, [txns]) + + const labels = useMemo(() => { + return dates.map((date) => + date.toLocaleDateString('en-US', { day: '2-digit', month: '2-digit' }) + ) + }, [dates]) + + const data = useMemo(() => { + return { + labels, + datasets: [ + { + label: 'Txns', + fill: 'origin', + data: txns?.map((txn) => txn.count) ?? [], + borderColor: 'rgb(224, 255, 50)', + backgroundColor: gradient ?? 'rgba(224, 255, 50, 0.2)' + } + ] + } + }, [labels, txns, gradient]) + + return ( + + + + ) +} diff --git a/app/packages/network/src/components/TxnsPanel.tsx b/app/packages/network/src/components/TxnsPanel.tsx new file mode 100644 index 0000000..9b6f0c4 --- /dev/null +++ b/app/packages/network/src/components/TxnsPanel.tsx @@ -0,0 +1,38 @@ +'use client' + +import { useQuery } from '@tanstack/react-query' +import { getTxns } from '../api' +import { Stack, Text, Divider, HStack } from '@chakra-ui/react' +import { Panel } from './Panel' +import { timeSince } from './date' +import { LinkBox } from './LinkBox' + +export function TxnsPanel() { + const query = useQuery({ + queryKey: ['txns'], + queryFn: getTxns, + refetchInterval: 1000 + }) + + return ( + + }> + {query.data?.txns?.map((txn) => { + return ( + + {txn.hash} + + + {txn.block_height} + + + {timeSince(txn.time * 1000)} + + + + ) + })} + + + ) +} diff --git a/app/packages/network/src/components/codemirror.theme.tsx b/app/packages/network/src/components/codemirror.theme.tsx new file mode 100644 index 0000000..9ce66ad --- /dev/null +++ b/app/packages/network/src/components/codemirror.theme.tsx @@ -0,0 +1,16 @@ +import { tokyoNightInit } from '@uiw/codemirror-theme-tokyo-night' +import { CreateThemeOptions } from '@uiw/codemirror-themes' + +export const settings: CreateThemeOptions['settings'] = { + background: '#161616', + foreground: '#787c99', + caret: '#c0caf5', + selection: '#515c7e40', + selectionMatch: '#16161e', + gutterBackground: '#161616', + gutterForeground: '#787c99', + gutterBorder: 'transparent', + lineHighlight: '#474b6611' +} + +export const codemirrorTheme = tokyoNightInit({ settings }) diff --git a/app/packages/network/src/components/date.ts b/app/packages/network/src/components/date.ts new file mode 100644 index 0000000..b87beef --- /dev/null +++ b/app/packages/network/src/components/date.ts @@ -0,0 +1,29 @@ +export function timeSince(timestamp: number, exact?: boolean) { + const now = +new Date() + const past = timestamp + + // Calculate the time difference in milliseconds + const timeDifference = now - past + + // Calculate time difference in minutes, hours, and days + const seconds = Math.floor(timeDifference / 1000) + const minutes = Math.floor(timeDifference / (1000 * 60)) + const hours = Math.floor(timeDifference / (1000 * 60 * 60)) + const days = Math.floor(timeDifference / (1000 * 60 * 60 * 24)) + + if (minutes < 1) { + return exact + ? `${seconds} second${seconds === 1 ? '' : 's'} ago` + : 'Just now' + } + + if (minutes < 60) { + return `${minutes} min${minutes === 1 ? '' : 's'} ago` + } + + if (hours < 24) { + return `${hours} hour${hours === 1 ? '' : 's'} ago` + } + + return `${days} day${days === 1 ? '' : 's'} ago` +} diff --git a/app/packages/network/src/components/resize.styles.css b/app/packages/network/src/components/resize.styles.css new file mode 100644 index 0000000..64bddc3 --- /dev/null +++ b/app/packages/network/src/components/resize.styles.css @@ -0,0 +1,77 @@ +.react-resizable { + position: relative; +} + +.react-resizable-handle { + position: absolute; + width: 3px; + height: 20px; + background-repeat: no-repeat; + background-origin: content-box; + box-sizing: border-box; + background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2IDYiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iNnB4Ij48ZyBvcGFjaXR5PSIwLjMwMiI+PHBhdGggZD0iTSA2IDYgTCAwIDYgTCAwIDQuMiBMIDQgNC4yIEwgNC4yIDQuMiBMIDQuMiAwIEwgNiAwIEwgNiA2IEwgNiA2IFoiIGZpbGw9IiMwMDAwMDAiLz48L2c+PC9zdmc+'); + background-position: bottom right; + padding: 0 3px 3px 0; +} + +.react-resizable-handle-sw { + bottom: 0; + left: 0; + cursor: sw-resize; + transform: rotate(90deg); +} + +.react-resizable-handle-se { + bottom: 0; + right: 0; + cursor: se-resize; +} + +.react-resizable-handle-nw { + top: 0; + left: 0; + cursor: nw-resize; + transform: rotate(180deg); +} + +.react-resizable-handle-ne { + top: 0; + right: 0; + cursor: ne-resize; + transform: rotate(270deg); +} + +.react-resizable-handle-w, +.react-resizable-handle-e { + top: 0; + height: 100%; + /* margin-top: -10px; */ + cursor: ew-resize; +} + +.react-resizable-handle-w { + left: 0; + transform: rotate(135deg); +} + +.react-resizable-handle-e { + right: 0; + /* transform: rotate(315deg); */ +} + +.react-resizable-handle-n, +.react-resizable-handle-s { + left: 50%; + margin-left: -10px; + cursor: ns-resize; +} + +.react-resizable-handle-n { + top: 0; + transform: rotate(225deg); +} + +.react-resizable-handle-s { + bottom: 0; + transform: rotate(45deg); +} \ No newline at end of file diff --git a/app/packages/network/src/components/useIsMobile.ts b/app/packages/network/src/components/useIsMobile.ts new file mode 100644 index 0000000..6d04e76 --- /dev/null +++ b/app/packages/network/src/components/useIsMobile.ts @@ -0,0 +1,8 @@ +'use client' + +import { useBreakpoint } from '@chakra-ui/react' + +export function useIsMobile() { + const breakpoint = useBreakpoint() + return breakpoint === 'xs' || breakpoint === 'sm' || breakpoint === 'base' +} diff --git a/app/packages/network/src/components/useNetworkData.tsx b/app/packages/network/src/components/useNetworkData.tsx new file mode 100644 index 0000000..d5e7cd5 --- /dev/null +++ b/app/packages/network/src/components/useNetworkData.tsx @@ -0,0 +1,39 @@ +'use client' + +import axios from 'axios' +import { useInterval } from '@chakra-ui/react' +import { useMemo, useRef, useState } from 'react' + +export function useNetworkData() { + const startRollup = useRef(0) + const startDate = useRef(Date.now()) + const [rollupHeight, setRollupHeight] = useState(null) + const [contractHeight, setContractHeight] = useState(null) + const [avgTime, setAvgTime] = useState(1) + + useInterval(async () => { + const [contract, rollup] = await Promise.all([ + axios.get(`${process.env.NEXT_PUBLIC_GUILD_URL}/rollup/contract/status`), + axios.get(`${process.env.NEXT_PUBLIC_ROLLUP_URL}/health`) + ]) + setContractHeight(contract.data.height) + setRollupHeight(rollup.data.height) + + const timeDiff = Date.now() - startDate.current + const blockDiff = startRollup.current + ? rollup.data.height - startRollup.current + : 1 + + if (!startRollup.current) { + startRollup.current = rollup.data.height + startDate.current = Date.now() + } + + setAvgTime(Math.floor(timeDiff / (blockDiff > 0 ? blockDiff : 1)) / 1000) + }, 1000) + + return useMemo( + () => ({ rollupHeight, contractHeight, avgTime }), + [rollupHeight, contractHeight, avgTime] + ) +} diff --git a/app/packages/network/src/fonts/Steradian-Bd.otf b/app/packages/network/src/fonts/Steradian-Bd.otf new file mode 100644 index 0000000..d6f208c Binary files /dev/null and b/app/packages/network/src/fonts/Steradian-Bd.otf differ diff --git a/app/packages/network/src/fonts/Steradian-Blk.otf b/app/packages/network/src/fonts/Steradian-Blk.otf new file mode 100644 index 0000000..8eb8380 Binary files /dev/null and b/app/packages/network/src/fonts/Steradian-Blk.otf differ diff --git a/app/packages/network/src/fonts/Steradian-Md.otf b/app/packages/network/src/fonts/Steradian-Md.otf new file mode 100644 index 0000000..ac3a773 Binary files /dev/null and b/app/packages/network/src/fonts/Steradian-Md.otf differ diff --git a/app/packages/network/src/fonts/Steradian-Rg.otf b/app/packages/network/src/fonts/Steradian-Rg.otf new file mode 100644 index 0000000..3cee8e9 Binary files /dev/null and b/app/packages/network/src/fonts/Steradian-Rg.otf differ diff --git a/app/packages/network/src/img/globe.png b/app/packages/network/src/img/globe.png new file mode 100644 index 0000000..9ef6325 Binary files /dev/null and b/app/packages/network/src/img/globe.png differ diff --git a/app/packages/network/src/img/globe.svg b/app/packages/network/src/img/globe.svg new file mode 100644 index 0000000..3292711 --- /dev/null +++ b/app/packages/network/src/img/globe.svg @@ -0,0 +1,1700 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/packages/network/src/img/logo-icon.png b/app/packages/network/src/img/logo-icon.png new file mode 100644 index 0000000..46c0ce5 Binary files /dev/null and b/app/packages/network/src/img/logo-icon.png differ diff --git a/app/packages/network/src/img/menu.svg b/app/packages/network/src/img/menu.svg new file mode 100644 index 0000000..4d8fc85 --- /dev/null +++ b/app/packages/network/src/img/menu.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/app/packages/network/src/img/payy-logo-white.png b/app/packages/network/src/img/payy-logo-white.png new file mode 100644 index 0000000..7046e90 Binary files /dev/null and b/app/packages/network/src/img/payy-logo-white.png differ diff --git a/app/packages/network/src/img/payy-logo-wordmark.svg b/app/packages/network/src/img/payy-logo-wordmark.svg new file mode 100644 index 0000000..0dc4958 --- /dev/null +++ b/app/packages/network/src/img/payy-logo-wordmark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/packages/network/src/img/tick.svg b/app/packages/network/src/img/tick.svg new file mode 100644 index 0000000..8168751 --- /dev/null +++ b/app/packages/network/src/img/tick.svg @@ -0,0 +1,4 @@ + + + + diff --git a/app/packages/network/src/types.ts b/app/packages/network/src/types.ts new file mode 100644 index 0000000..2f1b289 --- /dev/null +++ b/app/packages/network/src/types.ts @@ -0,0 +1,72 @@ +export type Element = string + +export interface MerklePath { + siblings: Element[] +} + +export interface Note { + address: Element + psi: Element + value: Element + source: Element + token: string +} + +export interface StoredNote { + note: Note + commitment: Element +} + +export interface InputNote { + note: Note + secret_key: Element + merkle_path: MerklePath +} + +export interface SnarkWitness { + V1: { + proof: string + instances: Element[][] + } +} + +export type WalletActivityResultStatus = + | null + | 'success' + | 'error' + | 'cancelled' + +export interface WalletActivity { + parentId?: string + kind: string + stage: string + result: WalletActivityResultStatus + timestamp: number + userCancel: boolean + error: string | null + errorCycles: number + attempts: number + okCycles: number + data: any +} + +export interface WalletState { + version: string + last_update: string | null + address: Element | null + invalid_notes: Record + unspent_notes: Record + spent_notes: Record + activity: Record +} + +export interface WalletActivityTxn extends WalletActivity { + data: { + snark: SnarkWitness | null + root: Element + nullifiers: Element[] + outputs: StoredNote[] + inputs: StoredNote[] + error: string | null + } +} diff --git a/app/packages/network/tsconfig.eslint.json b/app/packages/network/tsconfig.eslint.json new file mode 100644 index 0000000..2d6724e --- /dev/null +++ b/app/packages/network/tsconfig.eslint.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "include": ["src/**/*.ts", "src/**/*.tsx"] +} diff --git a/app/packages/network/tsconfig.json b/app/packages/network/tsconfig.json new file mode 100644 index 0000000..fb289b5 --- /dev/null +++ b/app/packages/network/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + }, + "target": "esnext" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/app/packages/payy/scripts/check-ts-collisions.sh b/app/packages/payy/scripts/check-ts-collisions.sh new file mode 100644 index 0000000..7f3b9ed --- /dev/null +++ b/app/packages/payy/scripts/check-ts-collisions.sh @@ -0,0 +1,146 @@ +#!/bin/bash +set -euo pipefail + +# This script detects ts-rs output collisions before we export into the shared +# app `ts-rs-bindings` directory. A collision means two packages generate the +# same relative output path (for example `Status.ts`) with different content. +# +# Why this approach: +# - We export each package into an isolated temporary directory. +# - We compare generated files by relative path + content hash. +# - We fail only when the same relative path has different hashes. +# (Same file content from multiple packages is allowed.) +# +# Optional output: +# - Set `TS_RS_MERGE_EXPORT_DIR` to materialize the collision-checked output +# into a directory (for example, the app ts-rs bindings folder). + +workspace_root="$(git rev-parse --show-toplevel)" + +if ! command -v jq >/dev/null 2>&1; then + echo "❌ jq is required to discover ts-rs workspace packages." + echo " Install with: brew install jq (macOS) or sudo apt-get install -y jq (Debian/Ubuntu)" + exit 1 +fi + +if command -v sha256sum >/dev/null 2>&1; then + hash_file() { + sha256sum "$1" | awk '{print $1}' + } +elif command -v shasum >/dev/null 2>&1; then + hash_file() { + shasum -a 256 "$1" | awk '{print $1}' + } +else + echo "❌ A SHA-256 tool is required (sha256sum or shasum)." + exit 1 +fi + +TS_RS_PACKAGES=() +while IFS= read -r pkg; do + TS_RS_PACKAGES+=("$pkg") +done < <( + cargo metadata \ + --manifest-path "${workspace_root}/Cargo.toml" \ + --no-deps \ + --format-version 1 \ + | jq -r ' + .packages[] + | select( + (.features | has("ts-rs")) + and ( + [.targets[].kind[]] + | map(select(. == "lib" or . == "staticlib" or . == "cdylib")) + | length > 0 + ) + ) + | .name + ' \ + | sort -u +) + +if [ "${#TS_RS_PACKAGES[@]}" -eq 0 ]; then + echo "❌ No workspace lib packages with a ts-rs feature were found." + exit 1 +fi + +echo "🔎 Checking ts-rs output collisions across packages..." +echo "📦 Packages: ${TS_RS_PACKAGES[*]}" + +tmp_dir="$(mktemp -d)" +trap 'rm -rf "${tmp_dir}"' EXIT + +per_pkg_root="${tmp_dir}/per-package" +mkdir -p "${per_pkg_root}" + +exports_manifest="${tmp_dir}/exports.tsv" +touch "${exports_manifest}" + +for pkg in "${TS_RS_PACKAGES[@]}"; do + pkg_export_dir="${per_pkg_root}/${pkg}" + mkdir -p "${pkg_export_dir}" + + echo " • Exporting ${pkg}" + TS_RS_EXPORT_DIR="${pkg_export_dir}" \ + cargo test \ + --manifest-path "${workspace_root}/Cargo.toml" \ + --features ts-rs \ + -p "${pkg}" \ + --lib \ + -- \ + export_bindings_ >/dev/null + + # Record: \t\t\t + while IFS= read -r -d '' file_path; do + relative_path="${file_path#${pkg_export_dir}/}" + file_hash="$(hash_file "${file_path}")" + printf '%s\t%s\t%s\t%s\n' "${relative_path}" "${file_hash}" "${pkg}" "${file_path}" >>"${exports_manifest}" + done < <(find "${pkg_export_dir}" -type f -name '*.ts' -print0) +done + +if [ ! -s "${exports_manifest}" ]; then + echo "❌ No TypeScript files were produced during isolated exports." + exit 1 +fi + +key_hash_manifest="${tmp_dir}/key-hash.tsv" +cut -f1,2 "${exports_manifest}" | sort -u >"${key_hash_manifest}" + +collision_paths="${tmp_dir}/collision-paths.txt" +cut -f1 "${key_hash_manifest}" | sort | uniq -d >"${collision_paths}" + +if [ -s "${collision_paths}" ]; then + echo "❌ ts-rs name collisions detected." + echo " The same output path is generated with different type content:" + while IFS= read -r relative_path; do + echo " - ${relative_path}" + awk -F '\t' -v rel="${relative_path}" '$1 == rel { printf " - %s (%s)\n", $3, substr($2, 1, 12) }' "${exports_manifest}" | sort -u + done <"${collision_paths}" + + echo + echo "Resolve by renaming one type (#[ts(rename = \"...\")])" + echo "or by namespacing output paths (#[ts(export_to = \"crate_name/\")])." + exit 1 +fi + +echo "✅ No ts-rs output collisions found." + +if [ -n "${TS_RS_MERGE_EXPORT_DIR:-}" ]; then + merge_dir="${TS_RS_MERGE_EXPORT_DIR}" + echo "📁 Writing merged, collision-checked output to: ${merge_dir}" + + mkdir -p "${merge_dir}" + # Keep non-generated files (for example tsconfig.tsrs.json), replace only + # generated TypeScript binding files. + find "${merge_dir}" -type f -name '*.ts' -delete + + for pkg in "${TS_RS_PACKAGES[@]}"; do + pkg_export_dir="${per_pkg_root}/${pkg}" + while IFS= read -r -d '' file_path; do + relative_path="${file_path#${pkg_export_dir}/}" + destination_path="${merge_dir}/${relative_path}" + mkdir -p "$(dirname "${destination_path}")" + cp "${file_path}" "${destination_path}" + done < <(find "${pkg_export_dir}" -type f -name '*.ts' -print0) + done +fi diff --git a/app/packages/payy/scripts/check-ts-types.sh b/app/packages/payy/scripts/check-ts-types.sh new file mode 100755 index 0000000..be72d09 --- /dev/null +++ b/app/packages/payy/scripts/check-ts-types.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -euo pipefail + +# Run the export script +workspace_root="$(git rev-parse --show-toplevel)" +script_dir="$(cd "$(dirname "$0")" && pwd)" +bash "${script_dir}/export-ts-types.sh" + +# Check for any changes in generated TypeScript files, including untracked. +# We intentionally validate the entire bindings directory, not just tracked +# files, so newly generated files cannot slip through unnoticed. +bindings_status="$(git -C "${workspace_root}" status --porcelain --untracked-files=all -- app/packages/payy/src/ts-rs-bindings)" +non_delete_status="$(printf '%s\n' "$bindings_status" | grep -Ev '^( D|D |DD) ' || true)" +if [ -n "$non_delete_status" ]; then + echo "❌ Rust and TypeScript types are out of sync!" + echo "$non_delete_status" + echo "Please run: scripts/export-ts-types.sh and commit all changes under app/packages/payy/src/ts-rs-bindings." + exit 1 +else + echo "✅ Rust and TypeScript types are in sync." +fi diff --git a/app/packages/payy/scripts/export-ts-types.sh b/app/packages/payy/scripts/export-ts-types.sh new file mode 100755 index 0000000..81a581e --- /dev/null +++ b/app/packages/payy/scripts/export-ts-types.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -euo pipefail + +workspace_root="$(git rev-parse --show-toplevel)" +script_dir="$(dirname "$0")" +bindings_dir="${workspace_root}/app/packages/payy/src/ts-rs-bindings" + +echo "🔄 Exporting TypeScript bindings from Rust crates..." + +echo "🧪 Running collision check + per-package export..." +TS_RS_MERGE_EXPORT_DIR="${bindings_dir}" bash "${script_dir}/check-ts-collisions.sh" + +echo "✅ TypeScript bindings exported from all crates." +echo "📋 Checking generated types ..." + +# Type-check only the generated TypeScript types using the custom tsconfig +cd "${workspace_root}/app/packages/payy" +# Note: this expects at least one top-level `src/ts-rs-bindings/*.ts` file. +# If we adopt namespaced exports via `#[ts(export_to = ".../")]`, revisit this +# check and `src/ts-rs-bindings/tsconfig.tsrs.json` include patterns. +if ls src/ts-rs-bindings/*.ts && npx tsc --project src/ts-rs-bindings/tsconfig.tsrs.json; then + echo "✅ TypeScript type check passed for generated bindings." +else + echo "❌ TypeScript type check failed for generated bindings!" + exit 1 +fi diff --git a/app/packages/payy/scripts/fix-android-fonts.sh b/app/packages/payy/scripts/fix-android-fonts.sh new file mode 100644 index 0000000..9de0f8f --- /dev/null +++ b/app/packages/payy/scripts/fix-android-fonts.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# create the xml font direcory +ANDROID_FONTS_DIR=./android/app/src/main/res/font +echo "Copying fonts to Android xml fonts directory..." +mkdir -p ${ANDROID_FONTS_DIR} +cp ./assets/fonts/*.otf ${ANDROID_FONTS_DIR} + +# rename the fonts as per Android's assets naming requirements +# Adapted from: https://github.com/jsamr/react-native-font-demo?tab=readme-ov-file#1-copy-and-rename-assets-to-the-resource-font-folder +echo "Fixing fonts names to conform to Android's assets naming requirements..." +if [[ -d "${ANDROID_FONTS_DIR}" && ! -z "${ANDROID_FONTS_DIR}" ]]; then + pushd "${ANDROID_FONTS_DIR}"; + for file in *.otf; do + typeset normalized="${file//-/_}"; + normalized=$(echo "$normalized" | tr '[:upper:]' '[:lower:]') + mv "$file" "$normalized" + done + popd +fi + +# copy steradian.xml to the xml fonts directory +FONTS_XML_FILE="./assets/fonts/android/steradian.xml" +echo "Copying ${FONTS_XML_FILE} to the Android xml fonts directory..." +cp ${FONTS_XML_FILE} ${ANDROID_FONTS_DIR} diff --git a/app/packages/payy/scripts/retry_yarn.sh b/app/packages/payy/scripts/retry_yarn.sh new file mode 100644 index 0000000..c423c26 --- /dev/null +++ b/app/packages/payy/scripts/retry_yarn.sh @@ -0,0 +1,26 @@ +# Retry `yarn install` with exponential backoff during eas build pre-install +try_yarn_install() { + local ATTEMPT=1 + local MAX_ATTEMPTS=5 + local DELAY=5 # Delays - 5, 10, 20, 40, 80 seconds max + local EXP_BACKOFF=2 + + until yarn install --network-timeout 1000000000; do + echo "yarn install failed: ${ATTEMPT} of ${MAX_ATTEMPTS} attempts" + + if [[ "${ATTEMPT}" -gt "${MAX_ATTEMPTS}" ]]; then + echo "yarn install still failing after ${MAX_ATTEMPTS} attempts. Aborting..." + exit 1 + fi + + echo "Sleeping for ${DELAY} second(s) before retrying..." + sleep ${DELAY} + ATTEMPT=$(( ATTEMPT + 1 )) + DELAY=$(( DELAY * EXP_BACKOFF )) + # cap max limit (extra safety - `ATTEMPTS` should ensure that the delay doesn't grow + # indefinitely) + DELAY=$(( DELAY > 80 ? 80 : DELAY )) + done + + echo "yarn install succeeded in ${ATTEMPT} attempt(s)" +} \ No newline at end of file diff --git a/app/packages/payy/scripts/setup.sh b/app/packages/payy/scripts/setup.sh new file mode 100644 index 0000000..a8cb6bf --- /dev/null +++ b/app/packages/payy/scripts/setup.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash + +set -euxo pipefail + +# Determines if we are building using `yarn` or `eas` cli +EAS_BUILD=${EAS_BUILD:-""} +APP_VARIANT=${APP_VARIANT:-""} + +echo "EAS_BUILD = ${EAS_BUILD}" +echo "APP_VARIANT = ${APP_VARIANT}" +echo "DEV_BUILD = ${DEV_BUILD:-}" + +ANDROID_PREBUILD_DIR="android" +IOS_PREBUILD_DIR="ios" + +# for the `try_yarn_install function` +echo "Sourcing retry_yarn.sh" +source "$(dirname "$0")/retry_yarn.sh" + +if [[ -z "$EAS_BUILD" ]]; then + # Clean up `app/node_modules`, `payy/ios`, and `payy/android` + # as part of build + if [[ "$@" == *"--clean"* || "$@" == *"--full-clean"* ]] + then + ( + echo "Cleaning up app artifacts" + set +e + set -x + echo "Cleaning app/node_modules..." + rm -rf ../../node_modules + echo "Cleaning payy/ios and payy/android directories..." + rm -rf ios android + set -e + ) + fi + +# Trigger yarn install for `expo` to be available for prebuild +try_yarn_install +fi + +# prepare the android backup config plugin +echo "Preparing the Android Key-Value Backup Agent plugin..." +yarn workspace android-kv-backup-agent clean +yarn workspace android-kv-backup-agent prepare + +# prepare the ios userdefaults (suite) config plugin +echo "Preparing the UserDefaults native module..." +yarn workspace user-defaults-suite-ios clean +yarn workspace user-defaults-suite-ios prepare + +# prepare the call detection native module +echo "Preparing the Call Detection native module..." +yarn workspace call-detection clean +yarn workspace call-detection prepare + +# Function to check if cargo is installed +function check_cargo() { + command -v cargo >/dev/null 2>&1 +} + +# Check if cargo is installed. If not, install it. +if ! check_cargo; then + echo "Cargo is not installed. Installing now..." + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + source $HOME/.cargo/env +else + echo "Cargo is already installed." +fi + +if [[ -z "$EAS_BUILD" ]]; then + # run `prebuild` iff the `android` and `iOS` directories do not exist + if [[ ! -d ${ANDROID_PREBUILD_DIR} ]] || [[ ! -d ${IOS_PREBUILD_DIR} ]] + then + echo "Missing android and/or iOS directories, running expo prebuild..." + npx expo prebuild + fi +fi + +# link the font assets (only for `iOS`) +npx -y react-native-asset -y --ios-assets ./assets/fonts + +# link the font assets (only for `Android`) +bash scripts/fix-android-fonts.sh + +# Don't build it again during eas build +if [[ -z "$EAS_BUILD" ]]; then + if [[ "$APP_VARIANT" == "storybook" ]]; then + echo "Storybook variant detected; skipping react-native-rust-bridge build." + else + # run setup for the react-native-rust-bridge dependency + yarn workspace react-native-rust-bridge clean + yarn workspace react-native-rust-bridge setup + yarn workspace react-native-rust-bridge build "$@" # pass any flags such as `--clean` to the build script + yarn workspace react-native-rust-bridge prepare + fi +fi diff --git a/app/packages/payy/src/ts-rs-bindings/AcrossDepositExternal.ts b/app/packages/payy/src/ts-rs-bindings/AcrossDepositExternal.ts new file mode 100644 index 0000000..363c68b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AcrossDepositExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AcrossDepositExternal = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityDetailEvent.ts b/app/packages/payy/src/ts-rs-bindings/ActivityDetailEvent.ts new file mode 100644 index 0000000..ab54060 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityDetailEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ActivityDetailEvent = + | { "type": "onContactSupport"; "payload": Record } + | { "type": "onCancelSendLink"; "payload": Record } + | { "type": "onShowQr"; "payload": { url: string } } + | { "type": "onShareLink"; "payload": { url: string } } + | { "type": "onCancelBurn"; "payload": Record } + | { "type": "onRetry"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityDetailViewModel.ts b/app/packages/payy/src/ts-rs-bindings/ActivityDetailViewModel.ts new file mode 100644 index 0000000..583fed9 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityDetailViewModel.ts @@ -0,0 +1,37 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityExternalData } from "./ActivityExternalData"; + +export type ActivityDetailViewModel = { + /** + * Activity data (null when loading or not found) + */ + activity: ActivityExternalData | null; + /** + * Main chain explorer URL (e.g., polygonscan.com) + */ + mainChainExplorerUrl: string | null; + /** + * Main chain display name (e.g., "Polygon") + */ + mainChainName: string | null; + /** + * Whether the activity is retryable + */ + isRetryable: boolean; + /** + * Whether balance values are visible + */ + isBalanceVisible: boolean; + /** + * Loading state for cancel send link action + */ + cancelSendLinkLoading: boolean; + /** + * Loading state for cancel burn action + */ + cancelBurnLoading: boolean; + /** + * Loading state for retry action + */ + retryLoading: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityExternalData.ts b/app/packages/payy/src/ts-rs-bindings/ActivityExternalData.ts new file mode 100644 index 0000000..f850947 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityExternalData.ts @@ -0,0 +1,81 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BalanceMovement } from "./BalanceMovement"; +import type { BungeeDepositExternal } from "./BungeeDepositExternal"; +import type { BurnExternal } from "./BurnExternal"; +import type { CardExternal } from "./CardExternal"; +import type { ClaimLinkExternal } from "./ClaimLinkExternal"; +import type { MintExternal } from "./MintExternal"; +import type { NoExternalData } from "./NoExternalData"; +import type { RampDepositExternal } from "./RampDepositExternal"; +import type { RampWithdrawExternal } from "./RampWithdrawExternal"; +import type { SendLinkExternal } from "./SendLinkExternal"; +import type { SendRegistryExternal } from "./SendRegistryExternal"; +import type { SupportExternal } from "./SupportExternal"; +import type { WorkerStatus } from "./WorkerStatus"; + +export type ActivityExternalData = + & { + /** + * ID of the activity + */ + id: string; + /** + * Title for the activity + */ + title: string; + /** + * Secondary info + */ + subtitle: string | null; + /** + * Display amount + */ + display_amount: string | null; + /** + * Display status, status infomation to display to the user + */ + display_status: string; + /** + * Strikethrough + */ + strikethrough: boolean; + /** + * Balance movement (affect on the balance of a given token) + */ + balance_movement: BalanceMovement | null; + /** + * Is the activity in a CTA (call to action) state, that means it should + * be highlighted and pinned + */ + is_cta: boolean; + /** + * Worker status + */ + worker_status: WorkerStatus; + /** + * The alert count number to show for the activity item to signify + * new events have occured + */ + alert_count: number; + /** + * Added at date + */ + timestamp: string; + } + & ( + | { "kind": "KYC_V1"; "data": NoExternalData } + | { "kind": "SEND_LINK_V1"; "data": SendLinkExternal } + | { "kind": "CLAIM_LINK_V1"; "data": ClaimLinkExternal } + | { "kind": "SEND_REGISTRY_V1"; "data": SendRegistryExternal } + | { "kind": "CARD_V1"; "data": CardExternal } + | { "kind": "MINT_V1"; "data": MintExternal } + | { "kind": "BURN_V1"; "data": BurnExternal } + | { "kind": "RAMP_DEPOSIT_V1"; "data": RampDepositExternal } + | { "kind": "RAMP_DEPOSIT_LINK_V1"; "data": NoExternalData } + | { "kind": "RAMP_WITHDRAW_V1"; "data": RampWithdrawExternal } + | { "kind": "SUPPORT_V1"; "data": SupportExternal } + | { "kind": "MIGRATE_V0"; "data": NoExternalData } + | { "kind": "WALLET_V0"; "data": NoExternalData } + | { "kind": "ACROSS_DEPOSIT"; "data": NoExternalData } + | { "kind": "BUNGEE_DEPOSIT_V1"; "data": BungeeDepositExternal } + ); diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityIdOutput.ts b/app/packages/payy/src/ts-rs-bindings/ActivityIdOutput.ts new file mode 100644 index 0000000..10fb43d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityIdOutput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ActivityIdOutput = { id: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityListEvent.ts b/app/packages/payy/src/ts-rs-bindings/ActivityListEvent.ts new file mode 100644 index 0000000..322fcf5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityListEvent.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityStoreListQueryFilter } from "./ActivityStoreListQueryFilter"; + +export type ActivityListEvent = + | { "type": "onActivityPress"; "payload": { id: string } } + | { "type": "onNotificationRequest"; "payload": Record } + | { "type": "onEndReached"; "payload": Record } + | { + "type": "onSelectFilter"; + "payload": { filter: ActivityStoreListQueryFilter }; + } + | { "type": "onClearFilter"; "payload": Record } + | { "type": "onOpenFilterMenu"; "payload": Record } + | { "type": "onCloseFilterMenu"; "payload": Record } + | { "type": "onExportCardTransactions"; "payload": Record } + | { "type": "onScrollToTopHandled"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityListViewModel.ts b/app/packages/payy/src/ts-rs-bindings/ActivityListViewModel.ts new file mode 100644 index 0000000..54ccab1 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityListViewModel.ts @@ -0,0 +1,58 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityExternalData } from "./ActivityExternalData"; +import type { ActivityStoreListQueryFilter } from "./ActivityStoreListQueryFilter"; +import type { LoadingResult } from "./LoadingResult"; + +export type ActivityListViewModel = { + /** + * Whether the app/wallet is ready (gates all loading states). + * When false, screen must show loading spinner regardless of activities state. + */ + isReady: boolean; + /** + * Activity data with loading/error state. Uses LoadingResult from pkg/payy_core_types/src/loadable.rs. + * - Loading: initial load in progress (or app not ready) + * - Ok(vec): activities loaded (empty vec = no activities) + * - Err(string): **UNUSED in this migration** - kept for forward compatibility only + * + * NOTE: Current source (useActivitiesListLongPoll) does not expose a typed error channel. + * Container must never emit Err variant in this migration. + */ + activities: LoadingResult, string>; + /** + * Whether more activities are loading remotely (pagination footer spinner) + */ + activitiesRemoteLoading: boolean; + /** + * Whether to show notification request banner + */ + shouldShowNotification: boolean; + /** + * Whether notification request is in progress + */ + notificationLoading: boolean; + /** + * Current filter selection + */ + filter: ActivityStoreListQueryFilter; + /** + * Whether filter menu is open + */ + filterMenuOpen: boolean; + /** + * Whether card transaction export is in progress + */ + isExportingCardTransactions: boolean; + /** + * Whether user has card transactions (for export option) + */ + hasCardTransactions: boolean; + /** + * Whether balance values are visible (for ActivityItem rendering) + */ + isBalanceVisible: boolean; + /** + * One-shot signal: when true, screen scrolls list to top and dispatches OnScrollToTopHandled + */ + scrollToTop: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityStoreListQuery.ts b/app/packages/payy/src/ts-rs-bindings/ActivityStoreListQuery.ts new file mode 100644 index 0000000..4a0a675 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityStoreListQuery.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityStoreListQueryFilter } from "./ActivityStoreListQueryFilter"; + +export type ActivityStoreListQuery = { + /** + * Offset from the first item + */ + offset: number; + /** + * Maximum activity items to return (defaults to 100, no maximum) + */ + limit: number; + /** + * Activity filters + */ + filter: ActivityStoreListQueryFilter; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ActivityStoreListQueryFilter.ts b/app/packages/payy/src/ts-rs-bindings/ActivityStoreListQueryFilter.ts new file mode 100644 index 0000000..7979683 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ActivityStoreListQueryFilter.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ActivityStoreListQueryFilter = "ALL" | "CARD" | "SUPPORT"; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressCityEvent.ts b/app/packages/payy/src/ts-rs-bindings/AddressCityEvent.ts new file mode 100644 index 0000000..d302f3a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressCityEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AddressCityEvent = { + "type": "onSubmit"; + "payload": { city: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressCityViewModel.ts b/app/packages/payy/src/ts-rs-bindings/AddressCityViewModel.ts new file mode 100644 index 0000000..86b151a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressCityViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type AddressCityViewModel = { + initialValue: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressCountryEvent.ts b/app/packages/payy/src/ts-rs-bindings/AddressCountryEvent.ts new file mode 100644 index 0000000..4310163 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressCountryEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AddressCountryEvent = { + "type": "onSubmit"; + "payload": { country: string }; +} | { "type": "onCountryPress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressCountryViewModel.ts b/app/packages/payy/src/ts-rs-bindings/AddressCountryViewModel.ts new file mode 100644 index 0000000..708e407 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressCountryViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type AddressCountryViewModel = { + initialValue: string | null; + allowedCountries: Array | null; + helperText: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressInput.ts b/app/packages/payy/src/ts-rs-bindings/AddressInput.ts new file mode 100644 index 0000000..e733c79 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AddressInput = { pk: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressPostalCodeEvent.ts b/app/packages/payy/src/ts-rs-bindings/AddressPostalCodeEvent.ts new file mode 100644 index 0000000..40f7a46 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressPostalCodeEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AddressPostalCodeEvent = { + "type": "onSubmit"; + "payload": { postalCode: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressPostalCodeViewModel.ts b/app/packages/payy/src/ts-rs-bindings/AddressPostalCodeViewModel.ts new file mode 100644 index 0000000..1a8e349 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressPostalCodeViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type AddressPostalCodeViewModel = { + initialValue: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressStateEvent.ts b/app/packages/payy/src/ts-rs-bindings/AddressStateEvent.ts new file mode 100644 index 0000000..9b8e73a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressStateEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AddressStateEvent = { + "type": "onSubmit"; + "payload": { state: string }; +} | { "type": "onStatePress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressStateOption.ts b/app/packages/payy/src/ts-rs-bindings/AddressStateOption.ts new file mode 100644 index 0000000..60964d7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressStateOption.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AddressStateOption = { id: string; name: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressStateViewModel.ts b/app/packages/payy/src/ts-rs-bindings/AddressStateViewModel.ts new file mode 100644 index 0000000..397f5b8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressStateViewModel.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AddressStateOption } from "./AddressStateOption"; +import type { KycState } from "./KycState"; + +export type AddressStateViewModel = { + states: Array; + label: string | null; + initialValue: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressStreetEvent.ts b/app/packages/payy/src/ts-rs-bindings/AddressStreetEvent.ts new file mode 100644 index 0000000..20952d5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressStreetEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AddressStreetEvent = { + "type": "onSubmit"; + "payload": { street: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AddressStreetViewModel.ts b/app/packages/payy/src/ts-rs-bindings/AddressStreetViewModel.ts new file mode 100644 index 0000000..d49353f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AddressStreetViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type AddressStreetViewModel = { + initialValue: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/AdvancedEvent.ts b/app/packages/payy/src/ts-rs-bindings/AdvancedEvent.ts new file mode 100644 index 0000000..7972c43 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AdvancedEvent.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AdvancedEvent = + | { "type": "onShareDiagnostics"; "payload": Record } + | { "type": "onNavigateToTerms"; "payload": Record } + | { "type": "onCopyDepositKey"; "payload": Record } + | { "type": "onToggleFraudWarnings"; "payload": { value: boolean } } + | { "type": "onDeleteAllData"; "payload": Record } + | { "type": "onCopyAddress"; "payload": Record } + | { "type": "onDiagnosticsDialogClose"; "payload": Record } + | { "type": "onDiagnosticsDialogSubmit"; "payload": { message: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/AdvancedViewModel.ts b/app/packages/payy/src/ts-rs-bindings/AdvancedViewModel.ts new file mode 100644 index 0000000..392c00b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/AdvancedViewModel.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type AdvancedViewModel = { + shareDiagnosticsLoading: boolean; + copyDepositKeyLoading: boolean; + fraudWarningsEnabled: boolean; + mainChainName: string; + showDeleteAllData: boolean; + deleteAllDataLoading: boolean; + address: string | null; + diagnosticsDialogVisible: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BalanceAction.ts b/app/packages/payy/src/ts-rs-bindings/BalanceAction.ts new file mode 100644 index 0000000..6883f18 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BalanceAction.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BalanceAction = "CREDIT" | "DEBIT"; diff --git a/app/packages/payy/src/ts-rs-bindings/BalanceMovement.ts b/app/packages/payy/src/ts-rs-bindings/BalanceMovement.ts new file mode 100644 index 0000000..c6f1859 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BalanceMovement.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BalanceAction } from "./BalanceAction"; +import type { Element } from "./Element"; + +export type BalanceMovement = { + action: BalanceAction; + value: Element; + note_kind: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BalanceOutput.ts b/app/packages/payy/src/ts-rs-bindings/BalanceOutput.ts new file mode 100644 index 0000000..8726a73 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BalanceOutput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type BalanceOutput = { value: Element; is_negative: boolean }; diff --git a/app/packages/payy/src/ts-rs-bindings/Base64Bytes.ts b/app/packages/payy/src/ts-rs-bindings/Base64Bytes.ts new file mode 100644 index 0000000..53f29d4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Base64Bytes.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Wrapper for `Vec` that (de)serializes to/from base64 strings. + * + * Using this type instead of raw `Vec` avoids sprinkling `#[serde(serialize_with = ...)]` + * attributes throughout the codebase while preserving the JSON contract. + */ +export type Base64Bytes = string; diff --git a/app/packages/payy/src/ts-rs-bindings/Block.ts b/app/packages/payy/src/ts-rs-bindings/Block.ts new file mode 100644 index 0000000..f9d32bf --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Block.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockContent } from "./BlockContent"; + +/** + * High-level block representation exposed over HTTP. + */ +export type Block = { + /** + * Content of the block. + */ + content: BlockContent; + /** + * Validator signature for the block. + */ + signature: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockChainsChainName.ts b/app/packages/payy/src/ts-rs-bindings/BlockChainsChainName.ts new file mode 100644 index 0000000..b7965cc --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockChainsChainName.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BlockChainsChainName = + | "Ethereum" + | "Base" + | "Polygon" + | "Optimism" + | "Arbitrum"; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockChainsEvent.ts b/app/packages/payy/src/ts-rs-bindings/BlockChainsEvent.ts new file mode 100644 index 0000000..ef7f86e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockChainsEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockChainsChainName } from "./BlockChainsChainName"; + +export type BlockChainsEvent = { + "type": "onSelectChain"; + "payload": { chain: BlockChainsChainName }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockChainsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/BlockChainsViewModel.ts new file mode 100644 index 0000000..382eed0 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockChainsViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BlockChainsViewModel = { heading: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockContent.ts b/app/packages/payy/src/ts-rs-bindings/BlockContent.ts new file mode 100644 index 0000000..bbdab79 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockContent.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockHeader } from "./BlockHeader"; +import type { BlockState } from "./BlockState"; + +/** + * Block content containing the header and state. + */ +export type BlockContent = { + /** + * Block header metadata. + */ + header: BlockHeader; + /** + * Block state describing the transactions. + */ + state: BlockState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockHeader.ts b/app/packages/payy/src/ts-rs-bindings/BlockHeader.ts new file mode 100644 index 0000000..6a1ba9c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockHeader.ts @@ -0,0 +1,28 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockHeight } from "./BlockHeight"; + +/** + * Header information for a block. + */ +export type BlockHeader = { + /** + * Height of the block. + */ + height: BlockHeight; + /** + * Hash of the previous block. + */ + last_block_hash: string; + /** + * Epoch identifier. + */ + epoch_id: bigint; + /** + * Hash of the last finalized block. + */ + last_final_block_hash: string; + /** + * Approvals collected for the block. + */ + approvals: string[]; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockHeight.ts b/app/packages/payy/src/ts-rs-bindings/BlockHeight.ts new file mode 100644 index 0000000..7ed237b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockHeight.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BlockHeight = bigint; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockState.ts b/app/packages/payy/src/ts-rs-bindings/BlockState.ts new file mode 100644 index 0000000..252b466 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockState.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { TxnWithInfo } from "./TxnWithInfo"; + +/** + * State payload for the block. + */ +export type BlockState = { + /** + * Merkle root hash after executing this block. + */ + root_hash: Element; + /** + * Transactions included in the block. + */ + txns: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BlockWithInfo.ts b/app/packages/payy/src/ts-rs-bindings/BlockWithInfo.ts new file mode 100644 index 0000000..a44436a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BlockWithInfo.ts @@ -0,0 +1,20 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Block } from "./Block"; + +/** + * Block bundle with metadata returned by the node. + */ +export type BlockWithInfo = { + /** + * Block payload. + */ + block: Block; + /** + * Hash of the block. + */ + hash: string; + /** + * Timestamp provided by the node. + */ + time: bigint; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BungeeDepositExternal.ts b/app/packages/payy/src/ts-rs-bindings/BungeeDepositExternal.ts new file mode 100644 index 0000000..589c36a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BungeeDepositExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BungeeDepositExternal = { source_token: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/BungeeToken.ts b/app/packages/payy/src/ts-rs-bindings/BungeeToken.ts new file mode 100644 index 0000000..d7b0544 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BungeeToken.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BungeeToken = { + address: string; + name: string; + symbol: string; + decimals: number; + logo_uri?: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BungeeTokenListEntry.ts b/app/packages/payy/src/ts-rs-bindings/BungeeTokenListEntry.ts new file mode 100644 index 0000000..c1c9970 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BungeeTokenListEntry.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BungeeToken } from "./BungeeToken"; + +export type BungeeTokenListEntry = { + chain_id: number; + tokens: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/BungeeTokenListOutput.ts b/app/packages/payy/src/ts-rs-bindings/BungeeTokenListOutput.ts new file mode 100644 index 0000000..6d746e6 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BungeeTokenListOutput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BungeeTokenListEntry } from "./BungeeTokenListEntry"; + +export type BungeeTokenListOutput = { tokens: Array }; diff --git a/app/packages/payy/src/ts-rs-bindings/BurnExternal.ts b/app/packages/payy/src/ts-rs-bindings/BurnExternal.ts new file mode 100644 index 0000000..cc07057 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BurnExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BurnExternal = { can_cancel: boolean }; diff --git a/app/packages/payy/src/ts-rs-bindings/BurnInput.ts b/app/packages/payy/src/ts-rs-bindings/BurnInput.ts new file mode 100644 index 0000000..ddb7c02 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BurnInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BurnInput = { value: string; eth_address: String }; diff --git a/app/packages/payy/src/ts-rs-bindings/BurnOutput.ts b/app/packages/payy/src/ts-rs-bindings/BurnOutput.ts new file mode 100644 index 0000000..f57a4f5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BurnOutput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BurnOutput = { id: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/BuyNftEvent.ts b/app/packages/payy/src/ts-rs-bindings/BuyNftEvent.ts new file mode 100644 index 0000000..0a4ff80 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BuyNftEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BuyNftEvent = { + "type": "onSelectAmount"; + "payload": { amount: number }; +} | { "type": "onCancelProcessing"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/BuyNftViewModel.ts b/app/packages/payy/src/ts-rs-bindings/BuyNftViewModel.ts new file mode 100644 index 0000000..8894876 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/BuyNftViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type BuyNftViewModel = { + selectStickerLabel: string; + pickupAtEventsLabel: string; + payWithLabel: string; + processingLabel: string; + isProcessing: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CancelActivityInput.ts b/app/packages/payy/src/ts-rs-bindings/CancelActivityInput.ts new file mode 100644 index 0000000..3baa607 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CancelActivityInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CancelActivityInput = { id: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/CardDetailItemViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardDetailItemViewModel.ts new file mode 100644 index 0000000..f1fc2ee --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardDetailItemViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardDetailItemViewModel = { label: string; value: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/CardEntryColorScheme.ts b/app/packages/payy/src/ts-rs-bindings/CardEntryColorScheme.ts new file mode 100644 index 0000000..69396bd --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardEntryColorScheme.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardEntryColorScheme = "black" | "dark" | "light" | "brand"; diff --git a/app/packages/payy/src/ts-rs-bindings/CardEntryEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardEntryEvent.ts new file mode 100644 index 0000000..0be5c2f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardEntryEvent.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardEntryEvent = never; diff --git a/app/packages/payy/src/ts-rs-bindings/CardEntryViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardEntryViewModel.ts new file mode 100644 index 0000000..eb9a15f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardEntryViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardEntryColorScheme } from "./CardEntryColorScheme"; + +export type CardEntryViewModel = { + title: string; + colorScheme: CardEntryColorScheme; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardEvent.ts new file mode 100644 index 0000000..6255ccc --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardEvent.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardEvent = + | { "type": "onToggleHidden"; "payload": Record } + | { "type": "onFreezeAction"; "payload": Record } + | { "type": "onCopyDetail"; "payload": { index: number } } + | { "type": "onChangePin"; "payload": Record } + | { "type": "onWaitListButtonPress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/CardExternal.ts b/app/packages/payy/src/ts-rs-bindings/CardExternal.ts new file mode 100644 index 0000000..27693e2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardExternal = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/CardFreezeActionViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardFreezeActionViewModel.ts new file mode 100644 index 0000000..3187125 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardFreezeActionViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardFreezeActionViewModel = { + loading: boolean; + label: string; + showIcon: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardInstructionIconType.ts b/app/packages/payy/src/ts-rs-bindings/CardInstructionIconType.ts new file mode 100644 index 0000000..69ec14d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardInstructionIconType.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardInstructionIconType = "globe" | "currency"; diff --git a/app/packages/payy/src/ts-rs-bindings/CardKycSubmitEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardKycSubmitEvent.ts new file mode 100644 index 0000000..f50f1af --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardKycSubmitEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardKycSubmitEvent = { + "type": "onProgressComplete"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardKycSubmitViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardKycSubmitViewModel.ts new file mode 100644 index 0000000..724b03f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardKycSubmitViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardKycSubmitViewModel = { + title: string; + description: string; + progressValue: number; + progressDuration: number; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardOnboardingEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardOnboardingEvent.ts new file mode 100644 index 0000000..709d928 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardOnboardingEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardOnboardingEvent = { + "type": "onApplyPress"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardOnboardingViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardOnboardingViewModel.ts new file mode 100644 index 0000000..a73157f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardOnboardingViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardOnboardingWaitListVariant } from "./CardOnboardingWaitListVariant"; + +export type CardOnboardingViewModel = { + applyButtonLabel: string; + applyButtonSubLabel: string; + isArgentina: boolean; + waitlistVariant: CardOnboardingWaitListVariant; + waitlistTitle: string; + waitlistDescription: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardOnboardingWaitListVariant.ts b/app/packages/payy/src/ts-rs-bindings/CardOnboardingWaitListVariant.ts new file mode 100644 index 0000000..ef4b03d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardOnboardingWaitListVariant.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardOnboardingWaitListVariant = "noCard" | "hidden"; diff --git a/app/packages/payy/src/ts-rs-bindings/CardPinEntryEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardPinEntryEvent.ts new file mode 100644 index 0000000..022785b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardPinEntryEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardPinEntryEvent = { + "type": "onKeyboardChange"; + "payload": { value: string }; +} | { "type": "onPrimaryAction"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/CardPinEntryViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardPinEntryViewModel.ts new file mode 100644 index 0000000..3a58414 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardPinEntryViewModel.ts @@ -0,0 +1,14 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardPinEntryViewModel = { + title: string; + instruction: string; + pinLength: number; + currentPin: string; + errorMessage: string | null; + keyboardKey: number; + primaryActionLabel: string; + primaryActionLoading: boolean; + primaryActionDisabled: boolean; + pinSymbol: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardPinViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardPinViewModel.ts new file mode 100644 index 0000000..f35b5c8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardPinViewModel.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardPinViewModel = { + label: string; + display: string; + changeLabel: string; + canChange: boolean; + errorMessage: string | null; + showError: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardPromoCardViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardPromoCardViewModel.ts new file mode 100644 index 0000000..682bf1f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardPromoCardViewModel.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { NetworkIdentifier } from "./NetworkIdentifier"; + +/** + * PromoCard domain state (excludes layout-derived width) + */ +export type CardPromoCardViewModel = { + hidden: boolean; + frozen: boolean; + secrets: NetworkIdentifier | null; + backgroundColor: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardShippingDetailsEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardShippingDetailsEvent.ts new file mode 100644 index 0000000..00c112e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardShippingDetailsEvent.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardShippingDetailsEvent = + | { "type": "onChangeName"; "payload": { value: string } } + | { "type": "onChangeAddressStreet"; "payload": { value: string } } + | { "type": "onChangeAddressCity"; "payload": { value: string } } + | { "type": "onChangeAddressPostalCode"; "payload": { value: string } } + | { "type": "onChangeAddressCountry"; "payload": { value: string } } + | { "type": "onPressAddressCountry"; "payload": Record } + | { "type": "onSubmit"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/CardShippingDetailsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardShippingDetailsViewModel.ts new file mode 100644 index 0000000..87b08b1 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardShippingDetailsViewModel.ts @@ -0,0 +1,18 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardShippingDetailsViewModel = { + heading: string; + nameLabel: string; + streetLabel: string; + cityLabel: string; + postalCodeLabel: string; + countryLabel: string; + name: string; + addressStreet: string; + addressCity: string; + addressPostalCode: string; + addressCountry: string; + submitLabel: string; + isSubmitDisabled: boolean; + isSubmitLoading: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardStatus.ts b/app/packages/payy/src/ts-rs-bindings/CardStatus.ts new file mode 100644 index 0000000..812f1ce --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardStatus.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardStatus = "PENDING" | "COMPLETE" | "DECLINED" | "REFUNDED"; diff --git a/app/packages/payy/src/ts-rs-bindings/CardTermsButtonColorScheme.ts b/app/packages/payy/src/ts-rs-bindings/CardTermsButtonColorScheme.ts new file mode 100644 index 0000000..a823ccd --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardTermsButtonColorScheme.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardTermsButtonColorScheme = "brand" | "light"; diff --git a/app/packages/payy/src/ts-rs-bindings/CardTermsCheckboxItem.ts b/app/packages/payy/src/ts-rs-bindings/CardTermsCheckboxItem.ts new file mode 100644 index 0000000..769eb65 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardTermsCheckboxItem.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardTermsCheckboxItem = { + id: string; + title: string; + linkUrl: string | null; + linkLabel: string | null; + acknowledgementText: string | null; + checked: boolean; + showGlbaDisclosure: boolean | null; + glbaDisclosureUrl: string | null; + glbaDisclosureLabel: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardTermsEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardTermsEvent.ts new file mode 100644 index 0000000..9df8989 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardTermsEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardTermsEvent = + | { "type": "onCheckboxToggle"; "payload": { id: string } } + | { "type": "onLinkPress"; "payload": { url: string } } + | { "type": "onAccept"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/CardTermsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardTermsViewModel.ts new file mode 100644 index 0000000..de63cf8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardTermsViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardTermsButtonColorScheme } from "./CardTermsButtonColorScheme"; +import type { CardTermsCheckboxItem } from "./CardTermsCheckboxItem"; + +export type CardTermsViewModel = { + title: string; + checkboxes: Array; + buttonLabel: string; + buttonColorScheme: CardTermsButtonColorScheme; + showArrow: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardUsageInstructionStepViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardUsageInstructionStepViewModel.ts new file mode 100644 index 0000000..1e25a02 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardUsageInstructionStepViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardInstructionIconType } from "./CardInstructionIconType"; + +export type CardUsageInstructionStepViewModel = { + text: string; + iconType: CardInstructionIconType; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardUsageInstructionsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardUsageInstructionsViewModel.ts new file mode 100644 index 0000000..f16eb9c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardUsageInstructionsViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardUsageInstructionStepViewModel } from "./CardUsageInstructionStepViewModel"; + +export type CardUsageInstructionsViewModel = { + title: string; + steps: Array; + show: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardViewModel.ts new file mode 100644 index 0000000..4eeb20d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardViewModel.ts @@ -0,0 +1,22 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardDetailItemViewModel } from "./CardDetailItemViewModel"; +import type { CardFreezeActionViewModel } from "./CardFreezeActionViewModel"; +import type { CardPinViewModel } from "./CardPinViewModel"; +import type { CardPromoCardViewModel } from "./CardPromoCardViewModel"; +import type { CardUsageInstructionsViewModel } from "./CardUsageInstructionsViewModel"; +import type { CardWaitListViewModel } from "./CardWaitListViewModel"; + +export type CardViewModel = { + promoCard: CardPromoCardViewModel; + hidden: boolean; + viewLabel: string; + hideLabel: string; + toggleHiddenLoading: boolean; + freezeAction: CardFreezeActionViewModel; + hasBalance: boolean; + details: Array; + pin: CardPinViewModel; + usageInstructions: CardUsageInstructionsViewModel; + isArgentina: boolean; + waitList: CardWaitListViewModel | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardWaitListEvent.ts b/app/packages/payy/src/ts-rs-bindings/CardWaitListEvent.ts new file mode 100644 index 0000000..0ba46dc --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardWaitListEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardWaitListEvent = { + "type": "onButtonPress"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardWaitListProgress.ts b/app/packages/payy/src/ts-rs-bindings/CardWaitListProgress.ts new file mode 100644 index 0000000..cd78509 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardWaitListProgress.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardWaitListProgress = { + current: number; + total: number; + percentage: number; + formattedCurrent: string; + formattedTotal: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CardWaitListVariant.ts b/app/packages/payy/src/ts-rs-bindings/CardWaitListVariant.ts new file mode 100644 index 0000000..b071582 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardWaitListVariant.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CardWaitListVariant = "hasCard" | "noCard" | "hidden"; diff --git a/app/packages/payy/src/ts-rs-bindings/CardWaitListViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CardWaitListViewModel.ts new file mode 100644 index 0000000..a8d141a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CardWaitListViewModel.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardWaitListProgress } from "./CardWaitListProgress"; +import type { CardWaitListVariant } from "./CardWaitListVariant"; + +export type CardWaitListViewModel = { + variant: CardWaitListVariant; + title: string; + description: string; + buttonText: string | null; + showProgress: boolean; + progress: CardWaitListProgress | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/Category.ts b/app/packages/payy/src/ts-rs-bindings/Category.ts new file mode 100644 index 0000000..9ddd189 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Category.ts @@ -0,0 +1,21 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Category = + | "BILLS" + | "CHARITY" + | "EATING_OUT" + | "ENTERTAINMENT" + | "EXPENSES" + | "FAMILY" + | "FINANCES" + | "GENERAL" + | "GIFTS" + | "GROCERIES" + | "HOLIDAYS" + | "INCOME" + | "PERSONAL_CARE" + | "SAVINGS" + | "SHOPPING" + | "TRANSFER" + | "TRANSPORT" + | "PET_CARE"; diff --git a/app/packages/payy/src/ts-rs-bindings/ChainConfig.ts b/app/packages/payy/src/ts-rs-bindings/ChainConfig.ts new file mode 100644 index 0000000..97df9e8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ChainConfig.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ChainConfig = { + chain_id: number; + rpc_url: string; + usdc_address: string; + across_address: string; + eip7702_simple_account_address: string; + rollup_contract_address?: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimLinkExternal.ts b/app/packages/payy/src/ts-rs-bindings/ClaimLinkExternal.ts new file mode 100644 index 0000000..0e47d82 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimLinkExternal.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ClaimSource } from "./ClaimSource"; + +export type ClaimLinkExternal = { + /** + * Memo (optional) + */ + memo: string | null; + /** + * Source of the claim (Link = claimed, Registry = received) + */ + source: ClaimSource; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimLinkInput.ts b/app/packages/payy/src/ts-rs-bindings/ClaimLinkInput.ts new file mode 100644 index 0000000..5ef7e86 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimLinkInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ClaimLinkInput = { link: string; memo: string | null }; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimPaymentColorScheme.ts b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentColorScheme.ts new file mode 100644 index 0000000..aa79358 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentColorScheme.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ClaimPaymentColorScheme = "brand" | "dark"; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimPaymentEvent.ts b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentEvent.ts new file mode 100644 index 0000000..22ca946 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ClaimPaymentEvent = + | { "type": "onSwipeUp"; "payload": Record } + | { "type": "onDone"; "payload": Record } + | { "type": "onClose"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimPaymentNoteTitle.ts b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentNoteTitle.ts new file mode 100644 index 0000000..9d802a2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentNoteTitle.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ClaimPaymentNoteTitleSize } from "./ClaimPaymentNoteTitleSize"; + +export type ClaimPaymentNoteTitle = { + lines: Array | null; + size: ClaimPaymentNoteTitleSize | null; + color: string | null; + subtitle: string | null; + subtitleColor: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimPaymentNoteTitleSize.ts b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentNoteTitleSize.ts new file mode 100644 index 0000000..de2f961 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentNoteTitleSize.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ClaimPaymentNoteTitleSize = "xl" | "4xl"; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimPaymentViewModel.ts b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentViewModel.ts new file mode 100644 index 0000000..ca38f28 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimPaymentViewModel.ts @@ -0,0 +1,23 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ClaimPaymentColorScheme } from "./ClaimPaymentColorScheme"; +import type { ClaimPaymentNoteTitle } from "./ClaimPaymentNoteTitle"; + +export type ClaimPaymentViewModel = { + canClaim: boolean; + disabled: boolean; + swipeTitle: string; + swipeLabel: string; + loadingLabel: string; + doneLabel: string; + swipeColorScheme: ClaimPaymentColorScheme; + fallbackColorScheme: ClaimPaymentColorScheme; + noteTitle: ClaimPaymentNoteTitle | null; + fallbackTitle: ClaimPaymentNoteTitle | null; + memoTextColor: string | null; + /** + * Serialized as string to support bigint; null when not available. + */ + noteValue: string | null; + memo: string | null; + showInternetBanner: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimRegistryNoteInput.ts b/app/packages/payy/src/ts-rs-bindings/ClaimRegistryNoteInput.ts new file mode 100644 index 0000000..8e93e5b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimRegistryNoteInput.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Note } from "./Note"; +import type { WalletPrivateKeyKind } from "./WalletPrivateKeyKind"; + +export type ClaimRegistryNoteInput = { + note: Note; + private_key_kind: WalletPrivateKeyKind; + memo: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimSource.ts b/app/packages/payy/src/ts-rs-bindings/ClaimSource.ts new file mode 100644 index 0000000..d0d3c5e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimSource.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ClaimSource = "REGISTRY" | "LINK"; diff --git a/app/packages/payy/src/ts-rs-bindings/ClaimableNote.ts b/app/packages/payy/src/ts-rs-bindings/ClaimableNote.ts new file mode 100644 index 0000000..82775f5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ClaimableNote.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { StoredNote } from "./StoredNote"; + +export type ClaimableNote = { note: StoredNote; secret_key: Element }; diff --git a/app/packages/payy/src/ts-rs-bindings/Command.ts b/app/packages/payy/src/ts-rs-bindings/Command.ts new file mode 100644 index 0000000..7f48b18 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Command.ts @@ -0,0 +1,80 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { AddressInput } from "./AddressInput"; +import type { BurnInput } from "./BurnInput"; +import type { CancelActivityInput } from "./CancelActivityInput"; +import type { ClaimLinkInput } from "./ClaimLinkInput"; +import type { ClaimRegistryNoteInput } from "./ClaimRegistryNoteInput"; +import type { CommitmentInput } from "./CommitmentInput"; +import type { CompressInput } from "./CompressInput"; +import type { DecompressInput } from "./DecompressInput"; +import type { GetActivityInput } from "./GetActivityInput"; +import type { GetBalanceLongPollInput } from "./GetBalanceLongPollInput"; +import type { GetBungeeTokenListInput } from "./GetBungeeTokenListInput"; +import type { GetDepositPendingBalanceLongPollInput } from "./GetDepositPendingBalanceLongPollInput"; +import type { GetMintBalanceInput } from "./GetMintBalanceInput"; +import type { GetUnclaimedBalanceLongPollInput } from "./GetUnclaimedBalanceLongPollInput"; +import type { ListActivityInput } from "./ListActivityInput"; +import type { ListActivityLongPollInput } from "./ListActivityLongPollInput"; +import type { LoadWalletInput } from "./LoadWalletInput"; +import type { MigrateInput } from "./MigrateInput"; +import type { MigrateProofInput } from "./MigrateProofInput"; +import type { MintInput } from "./MintInput"; +import type { OldAddressInput } from "./OldAddressInput"; +import type { ParseLinkInput } from "./ParseLinkInput"; +import type { ParseLinkSecretInput } from "./ParseLinkSecretInput"; +import type { PayyCoreProcessEventInput } from "./PayyCoreProcessEventInput"; +import type { PayyCoreViewModelLongPollInput } from "./PayyCoreViewModelLongPollInput"; +import type { RetryActivityInput } from "./RetryActivityInput"; +import type { SendLinkInput } from "./SendLinkInput"; +import type { SendRegistryInput } from "./SendRegistryInput"; +import type { SignInput } from "./SignInput"; + +export type Command = + | { "cmd": "logs" } + | { "cmd": "diagnostics" } + | { "cmd": "load_wallet"; "params": LoadWalletInput } + | { "cmd": "mint"; "params": MintInput } + | { "cmd": "burn"; "params": BurnInput } + | { "cmd": "send_link"; "params": SendLinkInput } + | { "cmd": "send_registry"; "params": SendRegistryInput } + | { "cmd": "claim_link"; "params": ClaimLinkInput } + | { "cmd": "claim_registry_note"; "params": ClaimRegistryNoteInput } + | { "cmd": "parse_link"; "params": ParseLinkInput } + | { "cmd": "parse_link_secret"; "params": ParseLinkSecretInput } + | { "cmd": "get_activity_alert_count" } + | { "cmd": "get_activity"; "params": GetActivityInput } + | { "cmd": "list_activity"; "params": ListActivityInput } + | { "cmd": "list_activity_long_poll"; "params": ListActivityLongPollInput } + | { "cmd": "cancel_activity"; "params": CancelActivityInput } + | { "cmd": "retry_activity"; "params": RetryActivityInput } + | { "cmd": "get_balance" } + | { "cmd": "get_balance_long_poll"; "params": GetBalanceLongPollInput } + | { "cmd": "get_deposit_pending_balance" } + | { + "cmd": "get_deposit_pending_balance_long_poll"; + "params": GetDepositPendingBalanceLongPollInput; + } + | { "cmd": "get_unclaimed_balance" } + | { + "cmd": "get_unclaimed_balance_long_poll"; + "params": GetUnclaimedBalanceLongPollInput; + } + | { "cmd": "get_mint_balance"; "params": GetMintBalanceInput } + | { "cmd": "sign"; "params": SignInput } + | { "cmd": "address"; "params": AddressInput } + | { "cmd": "old_address"; "params": OldAddressInput } + | { "cmd": "commitment"; "params": CommitmentInput } + | { "cmd": "points" } + | { "cmd": "compress"; "params": CompressInput } + | { "cmd": "decompress"; "params": DecompressInput } + | { "cmd": "migrate"; "params": MigrateInput } + | { "cmd": "migrate_proof"; "params": MigrateProofInput } + | { "cmd": "get_bungee_token_list"; "params": GetBungeeTokenListInput } + | { "cmd": "payy_core_initialize" } + | { "cmd": "payy_core_view_model" } + | { "cmd": "payy_core_process_event"; "params": PayyCoreProcessEventInput } + | { "cmd": "payy_core_reset" } + | { + "cmd": "payy_core_view_model_long_poll"; + "params": PayyCoreViewModelLongPollInput; + }; diff --git a/app/packages/payy/src/ts-rs-bindings/CommitmentInput.ts b/app/packages/payy/src/ts-rs-bindings/CommitmentInput.ts new file mode 100644 index 0000000..687832c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CommitmentInput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Note } from "./Note"; + +export type CommitmentInput = { note: Note }; diff --git a/app/packages/payy/src/ts-rs-bindings/CompressInput.ts b/app/packages/payy/src/ts-rs-bindings/CompressInput.ts new file mode 100644 index 0000000..f152deb --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CompressInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CompressInput = { data: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/CountryEvent.ts b/app/packages/payy/src/ts-rs-bindings/CountryEvent.ts new file mode 100644 index 0000000..b57be2b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CountryEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CountryEvent = + | { "type": "onCountryChange"; "payload": { country: string } } + | { "type": "onSubmit"; "payload": Record } + | { "type": "onCountryPress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/CountryViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CountryViewModel.ts new file mode 100644 index 0000000..9d1eb5c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CountryViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type CountryViewModel = { + title: string; + country: string; + allowedCountries: Array | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CryptoExchangeKey.ts b/app/packages/payy/src/ts-rs-bindings/CryptoExchangeKey.ts new file mode 100644 index 0000000..85abcea --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CryptoExchangeKey.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Wire-format: variants serialize as exact PascalCase values to match existing runtime. + * Do NOT use rename_all = "camelCase" on this enum - values must remain: + * Binance, Robinhood, Coinbase, ByBit, Other + */ +export type CryptoExchangeKey = + | "Binance" + | "Robinhood" + | "Coinbase" + | "ByBit" + | "Other"; diff --git a/app/packages/payy/src/ts-rs-bindings/CryptoExchangesEvent.ts b/app/packages/payy/src/ts-rs-bindings/CryptoExchangesEvent.ts new file mode 100644 index 0000000..0094a63 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CryptoExchangesEvent.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CryptoExchangeKey } from "./CryptoExchangeKey"; + +/** + * Event contract: tagged union with { type, payload } format. + * TS dispatch must always include payload: update({ type: 'onSelectExchange', payload: { key } }) + */ +export type CryptoExchangesEvent = { + "type": "onSelectExchange"; + "payload": { key: CryptoExchangeKey }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/CryptoExchangesViewModel.ts b/app/packages/payy/src/ts-rs-bindings/CryptoExchangesViewModel.ts new file mode 100644 index 0000000..77571b2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/CryptoExchangesViewModel.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type CryptoExchangesViewModel = { + heading: string; + robinhoodDisabled: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/Currency.ts b/app/packages/payy/src/ts-rs-bindings/Currency.ts new file mode 100644 index 0000000..e2dd944 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Currency.ts @@ -0,0 +1,161 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Currency = + | "AED" + | "AFN" + | "ALL" + | "AMD" + | "ANG" + | "AOA" + | "ARS" + | "AUD" + | "AWG" + | "AZN" + | "BAM" + | "BBD" + | "BDT" + | "BGN" + | "BHD" + | "BIF" + | "BMD" + | "BND" + | "BOB" + | "BRL" + | "BSD" + | "BTN" + | "BWP" + | "BYN" + | "BZD" + | "CAD" + | "CDF" + | "CHF" + | "CLP" + | "CNY" + | "COP" + | "CRC" + | "CUP" + | "CVE" + | "CZK" + | "DJF" + | "DKK" + | "DOP" + | "DZD" + | "EGP" + | "ERN" + | "ETB" + | "EUR" + | "FJD" + | "FKP" + | "GBP" + | "GEL" + | "GHS" + | "GIP" + | "GMD" + | "GNF" + | "GTQ" + | "GYD" + | "HKD" + | "HNL" + | "HRK" + | "HTG" + | "HUF" + | "IDR" + | "ILS" + | "INR" + | "IQD" + | "IRR" + | "ISK" + | "JMD" + | "JOD" + | "JPY" + | "KES" + | "KGS" + | "KHR" + | "KMF" + | "KPW" + | "KRW" + | "KWD" + | "KYD" + | "KZT" + | "LAK" + | "LBP" + | "LKR" + | "LRD" + | "LSL" + | "LYD" + | "MAD" + | "MDL" + | "MGA" + | "MKD" + | "MMK" + | "MNT" + | "MOP" + | "MRU" + | "MUR" + | "MVR" + | "MWK" + | "MXN" + | "MYR" + | "MZN" + | "NAD" + | "NGN" + | "NIO" + | "NOK" + | "NPR" + | "NZD" + | "OMR" + | "PAB" + | "PEN" + | "PGK" + | "PHP" + | "PKR" + | "PLN" + | "PYG" + | "QAR" + | "RON" + | "RSD" + | "RUB" + | "RWF" + | "SAR" + | "SBD" + | "SCR" + | "SDG" + | "SEK" + | "SGD" + | "SHP" + | "SLL" + | "SOS" + | "SRD" + | "SSP" + | "STN" + | "SVC" + | "SYP" + | "SZL" + | "THB" + | "TJS" + | "TMT" + | "TND" + | "TOP" + | "TRY" + | "TTD" + | "TWD" + | "TZS" + | "UAH" + | "UGX" + | "USD" + | "UYU" + | "UZS" + | "VES" + | "VND" + | "VUV" + | "WST" + | "XAF" + | "XCD" + | "XOF" + | "XPF" + | "YER" + | "ZAR" + | "ZMW" + | "ZWL" + | "USDC" + | "ETH"; diff --git a/app/packages/payy/src/ts-rs-bindings/DecompressInput.ts b/app/packages/payy/src/ts-rs-bindings/DecompressInput.ts new file mode 100644 index 0000000..3eba809 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DecompressInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DecompressInput = { data: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/DepositAddressEvent.ts b/app/packages/payy/src/ts-rs-bindings/DepositAddressEvent.ts new file mode 100644 index 0000000..f36fb9e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DepositAddressEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DepositAddressEvent = { + "type": "onCopyPress"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/DepositAddressViewModel.ts b/app/packages/payy/src/ts-rs-bindings/DepositAddressViewModel.ts new file mode 100644 index 0000000..0aa6551 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DepositAddressViewModel.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DepositAddressViewModel = { + heading: string; + depositAddress: string | null; + breakpoint: string; + showMinDepositNotice: boolean; + minDepositText: string; + copyLabel: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/DepositEvent.ts b/app/packages/payy/src/ts-rs-bindings/DepositEvent.ts new file mode 100644 index 0000000..d97c482 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DepositEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { DepositOptionKey } from "./DepositOptionKey"; + +export type DepositEvent = { + "type": "onOptionPress"; + "payload": { key: DepositOptionKey }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/DepositOptionItemViewModel.ts b/app/packages/payy/src/ts-rs-bindings/DepositOptionItemViewModel.ts new file mode 100644 index 0000000..274940c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DepositOptionItemViewModel.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { DepositOptionKey } from "./DepositOptionKey"; + +/** + * Individual deposit option item (serializable only) + * Note: Icon rendering happens in the screen based on `key` + */ +export type DepositOptionItemViewModel = { + key: DepositOptionKey; + title: string; + description: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/DepositOptionKey.ts b/app/packages/payy/src/ts-rs-bindings/DepositOptionKey.ts new file mode 100644 index 0000000..5b6cc0d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DepositOptionKey.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DepositOptionKey = + | "platformPay" + | "bankTransfer" + | "cryptoExchanges" + | "blockchains"; diff --git a/app/packages/payy/src/ts-rs-bindings/DepositPendingBalanceOutput.ts b/app/packages/payy/src/ts-rs-bindings/DepositPendingBalanceOutput.ts new file mode 100644 index 0000000..b70a605 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DepositPendingBalanceOutput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type DepositPendingBalanceOutput = { value: Element }; diff --git a/app/packages/payy/src/ts-rs-bindings/DepositViewModel.ts b/app/packages/payy/src/ts-rs-bindings/DepositViewModel.ts new file mode 100644 index 0000000..0d7d904 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DepositViewModel.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { DepositOptionItemViewModel } from "./DepositOptionItemViewModel"; + +export type DepositViewModel = { options: Array }; diff --git a/app/packages/payy/src/ts-rs-bindings/DobEvent.ts b/app/packages/payy/src/ts-rs-bindings/DobEvent.ts new file mode 100644 index 0000000..4034991 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DobEvent.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DobEvent = { "type": "onSubmit"; "payload": { dob: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/DobViewModel.ts b/app/packages/payy/src/ts-rs-bindings/DobViewModel.ts new file mode 100644 index 0000000..2491362 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DobViewModel.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type DobViewModel = { kycState: KycState }; diff --git a/app/packages/payy/src/ts-rs-bindings/DocKindEvent.ts b/app/packages/payy/src/ts-rs-bindings/DocKindEvent.ts new file mode 100644 index 0000000..55235b3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DocKindEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DocKindEvent = { "type": "onSelect"; "payload": { id: string } } | { + "type": "onSubmit"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/DocKindOption.ts b/app/packages/payy/src/ts-rs-bindings/DocKindOption.ts new file mode 100644 index 0000000..d01c124 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DocKindOption.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DocKindOption = { id: string; label: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/DocKindViewModel.ts b/app/packages/payy/src/ts-rs-bindings/DocKindViewModel.ts new file mode 100644 index 0000000..a8ce014 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DocKindViewModel.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { DocKindOption } from "./DocKindOption"; +import type { KycState } from "./KycState"; + +export type DocKindViewModel = { + title: string; + options: Array; + selectedKind: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/DocScanEvent.ts b/app/packages/payy/src/ts-rs-bindings/DocScanEvent.ts new file mode 100644 index 0000000..9aed724 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DocScanEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DocScanEvent = + | { "type": "onCapturePress"; "payload": Record } + | { "type": "onRequestCameraPermission"; "payload": Record } + | { "type": "onSubmit"; "payload": { imagePath: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/DocScanSide.ts b/app/packages/payy/src/ts-rs-bindings/DocScanSide.ts new file mode 100644 index 0000000..ec36947 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DocScanSide.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type DocScanSide = "front" | "back"; diff --git a/app/packages/payy/src/ts-rs-bindings/DocScanViewModel.ts b/app/packages/payy/src/ts-rs-bindings/DocScanViewModel.ts new file mode 100644 index 0000000..3fd4f64 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/DocScanViewModel.ts @@ -0,0 +1,5 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { DocScanSide } from "./DocScanSide"; +import type { KycState } from "./KycState"; + +export type DocScanViewModel = { side: DocScanSide; kycState: KycState }; diff --git a/app/packages/payy/src/ts-rs-bindings/Element.ts b/app/packages/payy/src/ts-rs-bindings/Element.ts new file mode 100644 index 0000000..34afd49 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Element.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * A 256-bit unsigned integer + * + * This type is a wrapper around a [`U256`], so can represent any value in the range `0..=(2^256 - + * 1)`. + * However, in a ZK context, it is usually converted to a [`Base`], which is an integer modulo + * "some large prime". This restricts the set of usable values to something approximating a `u254` + * + * [`Base`]: crate::Base + */ +export type Element = string; diff --git a/app/packages/payy/src/ts-rs-bindings/ElementsVecData.ts b/app/packages/payy/src/ts-rs-bindings/ElementsVecData.ts new file mode 100644 index 0000000..3d0832e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ElementsVecData.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +/** + * Error data detailed the element related to the error + */ +export type ElementsVecData = { + /** + * Element related to error + */ + elements: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FaceEvent.ts b/app/packages/payy/src/ts-rs-bindings/FaceEvent.ts new file mode 100644 index 0000000..bac89d5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FaceEvent.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FaceEvent = { + "type": "onSubmit"; + "payload": { + selfiefront: string | null; + selfieleft: string | null; + selfieright: string | null; + }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FaceRequiredField.ts b/app/packages/payy/src/ts-rs-bindings/FaceRequiredField.ts new file mode 100644 index 0000000..2519086 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FaceRequiredField.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FaceRequiredField = "selfiefront" | "selfieleft" | "selfieright"; diff --git a/app/packages/payy/src/ts-rs-bindings/FaceViewModel.ts b/app/packages/payy/src/ts-rs-bindings/FaceViewModel.ts new file mode 100644 index 0000000..a2a320b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FaceViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { FaceRequiredField } from "./FaceRequiredField"; +import type { KycState } from "./KycState"; + +export type FaceViewModel = { + requiredFields: Array; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FirstNameEvent.ts b/app/packages/payy/src/ts-rs-bindings/FirstNameEvent.ts new file mode 100644 index 0000000..2998e80 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FirstNameEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FirstNameEvent = { + "type": "onSubmit"; + "payload": { firstname: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FirstNameViewModel.ts b/app/packages/payy/src/ts-rs-bindings/FirstNameViewModel.ts new file mode 100644 index 0000000..1037e91 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FirstNameViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type FirstNameViewModel = { + initialValue: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FlagsEvent.ts b/app/packages/payy/src/ts-rs-bindings/FlagsEvent.ts new file mode 100644 index 0000000..425b592 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FlagsEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FlagsEvent = { + "type": "onToggle"; + "payload": { id: string; value: boolean }; +} | { "type": "onSubmit"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/FlagsOption.ts b/app/packages/payy/src/ts-rs-bindings/FlagsOption.ts new file mode 100644 index 0000000..7c87d00 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FlagsOption.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FlagsOption = { id: string; label: string; value: boolean }; diff --git a/app/packages/payy/src/ts-rs-bindings/FlagsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/FlagsViewModel.ts new file mode 100644 index 0000000..c8c38f7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FlagsViewModel.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { FlagsOption } from "./FlagsOption"; +import type { KycState } from "./KycState"; + +export type FlagsViewModel = { + flags: Array; + submitDisabled: boolean; + warningMessage: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FraudWarningEvent.ts b/app/packages/payy/src/ts-rs-bindings/FraudWarningEvent.ts new file mode 100644 index 0000000..f54ebdd --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FraudWarningEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FraudWarningEvent = { + "type": "onAcknowledge"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FraudWarningViewModel.ts b/app/packages/payy/src/ts-rs-bindings/FraudWarningViewModel.ts new file mode 100644 index 0000000..3e8b599 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FraudWarningViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FraudWarningViewModel = { + title: string; + titleHighlight: string | null; + calloutText: string; + description: string; + buttonLabel: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FulfillRequestEvent.ts b/app/packages/payy/src/ts-rs-bindings/FulfillRequestEvent.ts new file mode 100644 index 0000000..0fea690 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FulfillRequestEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Event variants for FulfillRequestScreen actions. + */ +export type FulfillRequestEvent = + | { "type": "onSwipeUp"; "payload": Record } + | { "type": "onDone"; "payload": Record } + | { "type": "onClose"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/FulfillRequestSwipeColorScheme.ts b/app/packages/payy/src/ts-rs-bindings/FulfillRequestSwipeColorScheme.ts new file mode 100644 index 0000000..e6609c2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FulfillRequestSwipeColorScheme.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Color scheme for the swipe component. + */ +export type FulfillRequestSwipeColorScheme = "brand" | "dark"; diff --git a/app/packages/payy/src/ts-rs-bindings/FulfillRequestViewModel.ts b/app/packages/payy/src/ts-rs-bindings/FulfillRequestViewModel.ts new file mode 100644 index 0000000..25a3c77 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FulfillRequestViewModel.ts @@ -0,0 +1,20 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { FulfillRequestSwipeColorScheme } from "./FulfillRequestSwipeColorScheme"; + +/** + * ViewModel for FulfillRequestScreen. + */ +export type FulfillRequestViewModel = { + /** + * Value as string to support bigint serialization. + */ + value: string; + memo: string | null; + title: string; + swipeLabel: string | null; + loadingLabel: string; + doneLabel: string; + swipeColorScheme: FulfillRequestSwipeColorScheme; + disabled: boolean; + showInternetBanner: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/FundingStatus.ts b/app/packages/payy/src/ts-rs-bindings/FundingStatus.ts new file mode 100644 index 0000000..7bbca9e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/FundingStatus.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type FundingStatus = + | "PENDING_DEBIT" + | "PENDING_CREDIT" + | "INSUFFICIENT_FUNDS" + | "SETTLED"; diff --git a/app/packages/payy/src/ts-rs-bindings/GetActivityAlertCountOutput.ts b/app/packages/payy/src/ts-rs-bindings/GetActivityAlertCountOutput.ts new file mode 100644 index 0000000..0f47d17 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetActivityAlertCountOutput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GetActivityAlertCountOutput = { count: number }; diff --git a/app/packages/payy/src/ts-rs-bindings/GetActivityInput.ts b/app/packages/payy/src/ts-rs-bindings/GetActivityInput.ts new file mode 100644 index 0000000..863256b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetActivityInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GetActivityInput = { id: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/GetBalanceLongPollInput.ts b/app/packages/payy/src/ts-rs-bindings/GetBalanceLongPollInput.ts new file mode 100644 index 0000000..0c75ac6 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetBalanceLongPollInput.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GetBalanceLongPollInput = { + last_modified: string | null; + timeout_secs: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GetBalanceLongPollOutput.ts b/app/packages/payy/src/ts-rs-bindings/GetBalanceLongPollOutput.ts new file mode 100644 index 0000000..a10a09b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetBalanceLongPollOutput.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type GetBalanceLongPollOutput = { + value: Element; + is_negative: boolean; + last_modified: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GetBungeeTokenListInput.ts b/app/packages/payy/src/ts-rs-bindings/GetBungeeTokenListInput.ts new file mode 100644 index 0000000..a65d88f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetBungeeTokenListInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GetBungeeTokenListInput = { chain_ids: Array | null }; diff --git a/app/packages/payy/src/ts-rs-bindings/GetDepositPendingBalanceLongPollInput.ts b/app/packages/payy/src/ts-rs-bindings/GetDepositPendingBalanceLongPollInput.ts new file mode 100644 index 0000000..d46b67a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetDepositPendingBalanceLongPollInput.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GetDepositPendingBalanceLongPollInput = { + last_modified: string | null; + timeout_secs: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GetDepositPendingBalanceLongPollOutput.ts b/app/packages/payy/src/ts-rs-bindings/GetDepositPendingBalanceLongPollOutput.ts new file mode 100644 index 0000000..ca5e15a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetDepositPendingBalanceLongPollOutput.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type GetDepositPendingBalanceLongPollOutput = { + value: Element; + last_modified: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GetMintBalanceInput.ts b/app/packages/payy/src/ts-rs-bindings/GetMintBalanceInput.ts new file mode 100644 index 0000000..3224b75 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetMintBalanceInput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WalletPrivateKeyKind } from "./WalletPrivateKeyKind"; + +export type GetMintBalanceInput = { private_key_kind: WalletPrivateKeyKind }; diff --git a/app/packages/payy/src/ts-rs-bindings/GetMintBalanceOutput.ts b/app/packages/payy/src/ts-rs-bindings/GetMintBalanceOutput.ts new file mode 100644 index 0000000..d6a3e34 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetMintBalanceOutput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type GetMintBalanceOutput = { value: Element }; diff --git a/app/packages/payy/src/ts-rs-bindings/GetUnclaimedBalanceLongPollInput.ts b/app/packages/payy/src/ts-rs-bindings/GetUnclaimedBalanceLongPollInput.ts new file mode 100644 index 0000000..f2eb5db --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetUnclaimedBalanceLongPollInput.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GetUnclaimedBalanceLongPollInput = { + last_modified: string | null; + timeout_secs: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GetUnclaimedBalanceLongPollOutput.ts b/app/packages/payy/src/ts-rs-bindings/GetUnclaimedBalanceLongPollOutput.ts new file mode 100644 index 0000000..20b6d6b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GetUnclaimedBalanceLongPollOutput.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type GetUnclaimedBalanceLongPollOutput = { + value: Element; + last_modified: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianBackupEvent.ts b/app/packages/payy/src/ts-rs-bindings/GuardianBackupEvent.ts new file mode 100644 index 0000000..d834d45 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianBackupEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Events emitted by the GuardianBackupScreen + */ +export type GuardianBackupEvent = + | { "type": "onSelectEmptySlot"; "payload": Record } + | { "type": "onPressAddGuardian"; "payload": Record } + | { "type": "onPressGuardian"; "payload": { guardianId: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianBackupIntroEvent.ts b/app/packages/payy/src/ts-rs-bindings/GuardianBackupIntroEvent.ts new file mode 100644 index 0000000..4689f2a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianBackupIntroEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GuardianBackupIntroEvent = { + "type": "onSelectCreate"; + "payload": Record; +} | { "type": "onSelectRecover"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianBackupIntroViewModel.ts b/app/packages/payy/src/ts-rs-bindings/GuardianBackupIntroViewModel.ts new file mode 100644 index 0000000..3bf71b0 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianBackupIntroViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GuardianBackupIntroViewModel = { + description: string; + createTitle: string; + createSubtitle: string; + recoverTitle: string; + recoverSubtitle: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianBackupSlot.ts b/app/packages/payy/src/ts-rs-bindings/GuardianBackupSlot.ts new file mode 100644 index 0000000..fedd945 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianBackupSlot.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Represents a single guardian slot in the backup screen UI + */ +export type GuardianBackupSlot = { + id: string; + displayName: string; + iconName: string; + number: number; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianBackupViewModel.ts b/app/packages/payy/src/ts-rs-bindings/GuardianBackupViewModel.ts new file mode 100644 index 0000000..6b11526 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianBackupViewModel.ts @@ -0,0 +1,14 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { GuardianBackupSlot } from "./GuardianBackupSlot"; + +/** + * ViewModel for the GuardianBackupScreen + */ +export type GuardianBackupViewModel = { + guardians: Array; + placeholderName: string; + remainingSlots: number; + filledStrengthCount: number; + requiredGuardians: number; + addGuardianLabel: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianLoginEvent.ts b/app/packages/payy/src/ts-rs-bindings/GuardianLoginEvent.ts new file mode 100644 index 0000000..6684e17 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianLoginEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GuardianLoginEvent = { + "type": "onGuardianPress"; + "payload": { guardianId: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianLoginItem.ts b/app/packages/payy/src/ts-rs-bindings/GuardianLoginItem.ts new file mode 100644 index 0000000..52919a4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianLoginItem.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type GuardianLoginItem = { + id: string; + displayName: string; + iconName: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/GuardianLoginViewModel.ts b/app/packages/payy/src/ts-rs-bindings/GuardianLoginViewModel.ts new file mode 100644 index 0000000..f6be096 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/GuardianLoginViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { GuardianLoginItem } from "./GuardianLoginItem"; + +export type GuardianLoginViewModel = { + title: string; + guardians: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeEvent.ts b/app/packages/payy/src/ts-rs-bindings/HomeEvent.ts new file mode 100644 index 0000000..0be1e79 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeEvent.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HomeEvent = never; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeTabIconKind.ts b/app/packages/payy/src/ts-rs-bindings/HomeTabIconKind.ts new file mode 100644 index 0000000..9fa74d8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeTabIconKind.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HomeTabIconKind = "qr" | "menu"; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeTabItemViewModel.ts b/app/packages/payy/src/ts-rs-bindings/HomeTabItemViewModel.ts new file mode 100644 index 0000000..1431292 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeTabItemViewModel.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { HomeTabIconKind } from "./HomeTabIconKind"; +import type { HomeTabKey } from "./HomeTabKey"; +import type { HomeTabsStatusBarStyle } from "./HomeTabsStatusBarStyle"; + +export type HomeTabItemViewModel = { + key: HomeTabKey; + titleKey: string; + bg: string; + text: string; + tabBg: string; + tabText: string; + statusBarStyle: HomeTabsStatusBarStyle; + icon: HomeTabIconKind | null; + tabFlex: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeTabKey.ts b/app/packages/payy/src/ts-rs-bindings/HomeTabKey.ts new file mode 100644 index 0000000..657a253 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeTabKey.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HomeTabKey = "qr" | "wallet" | "activity" | "invest" | "menu"; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeTabsEvent.ts b/app/packages/payy/src/ts-rs-bindings/HomeTabsEvent.ts new file mode 100644 index 0000000..39ec5ef --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeTabsEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HomeTabsEvent = + | { "type": "onTabPress"; "payload": { index: number } } + | { "type": "onPageSelected"; "payload": { index: number } } + | { "type": "onRewardsPress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeTabsRewardsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/HomeTabsRewardsViewModel.ts new file mode 100644 index 0000000..c70f4d2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeTabsRewardsViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HomeTabsRewardsViewModel = { + totalPoints: string; + isLoading: boolean; + isVisible: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeTabsStatusBarStyle.ts b/app/packages/payy/src/ts-rs-bindings/HomeTabsStatusBarStyle.ts new file mode 100644 index 0000000..8a6a4da --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeTabsStatusBarStyle.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HomeTabsStatusBarStyle = "light" | "dark"; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeTabsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/HomeTabsViewModel.ts new file mode 100644 index 0000000..590b386 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeTabsViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { HomeTabItemViewModel } from "./HomeTabItemViewModel"; +import type { HomeTabsRewardsViewModel } from "./HomeTabsRewardsViewModel"; + +export type HomeTabsViewModel = { + selectedIndex: number; + tabs: Array; + activityAlertCount: number; + scrollToTop: boolean; + rewards: HomeTabsRewardsViewModel; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/HomeViewModel.ts b/app/packages/payy/src/ts-rs-bindings/HomeViewModel.ts new file mode 100644 index 0000000..9b008a5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/HomeViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type HomeViewModel = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/InputNote.ts b/app/packages/payy/src/ts-rs-bindings/InputNote.ts new file mode 100644 index 0000000..838116b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/InputNote.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { MerklePath } from "./MerklePath"; +import type { WalletDataNote } from "./WalletDataNote"; + +export type InputNote = { + note: WalletDataNote; + secret_key: Element; + merkle_path: MerklePath; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/InvestEvent.ts b/app/packages/payy/src/ts-rs-bindings/InvestEvent.ts new file mode 100644 index 0000000..5c214c7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/InvestEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { InvestOptionKey } from "./InvestOptionKey"; + +export type InvestEvent = { + "type": "onPressInvestOption"; + "payload": { key: InvestOptionKey }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/InvestOptionKey.ts b/app/packages/payy/src/ts-rs-bindings/InvestOptionKey.ts new file mode 100644 index 0000000..baa2076 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/InvestOptionKey.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type InvestOptionKey = "treasuries" | "defiVaults"; diff --git a/app/packages/payy/src/ts-rs-bindings/InvestViewModel.ts b/app/packages/payy/src/ts-rs-bindings/InvestViewModel.ts new file mode 100644 index 0000000..b19d0be --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/InvestViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type InvestViewModel = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/InviteLink.ts b/app/packages/payy/src/ts-rs-bindings/InviteLink.ts new file mode 100644 index 0000000..8c4c1c9 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/InviteLink.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * `/invite/` links for onboarding flows. + */ +export type InviteLink = { code: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/KycField.ts b/app/packages/payy/src/ts-rs-bindings/KycField.ts new file mode 100644 index 0000000..35f05eb --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycField.ts @@ -0,0 +1,24 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type KycField = + | "firstname" + | "middlename" + | "lastname" + | "dob" + | "occupation" + | "addressstreet" + | "addresscity" + | "addressstate" + | "addresscountry" + | "addresspostalcode" + | "nationalities" + | "documents" + | "phone" + | "phoneverified" + | "email" + | "emailverified" + | "nationalid" + | "civilstate" + | "pep" + | "fatca" + | "uif"; diff --git a/app/packages/payy/src/ts-rs-bindings/KycReviewStackEvent.ts b/app/packages/payy/src/ts-rs-bindings/KycReviewStackEvent.ts new file mode 100644 index 0000000..45654d7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycReviewStackEvent.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type KycReviewStackEvent = + | { "type": "onDone"; "payload": Record } + | { "type": "onRejectedDone"; "payload": Record } + | { "type": "onRestartKyc"; "payload": Record } + | { "type": "onFixKyc"; "payload": Record } + | { + "type": "onSupportPress"; + "payload": { meta: Record | null }; + } + | { "type": "onNotificationToggle"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/KycReviewStackNotificationBanner.ts b/app/packages/payy/src/ts-rs-bindings/KycReviewStackNotificationBanner.ts new file mode 100644 index 0000000..45f6e62 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycReviewStackNotificationBanner.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type KycReviewStackNotificationBanner = { + text: string; + additionalText: string | null; + isEnabled: boolean; + shouldShow: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/KycReviewStackViewModel.ts b/app/packages/payy/src/ts-rs-bindings/KycReviewStackViewModel.ts new file mode 100644 index 0000000..d5a974d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycReviewStackViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycReviewStackNotificationBanner } from "./KycReviewStackNotificationBanner"; +import type { KycReviewStatus } from "./KycReviewStatus"; +import type { KycUpdateRequired } from "./KycUpdateRequired"; + +export type KycReviewStackViewModel = { + status: KycReviewStatus; + updateRequired: KycUpdateRequired | null; + notificationBanner: KycReviewStackNotificationBanner | null; + showApprovedButton: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/KycReviewStatus.ts b/app/packages/payy/src/ts-rs-bindings/KycReviewStatus.ts new file mode 100644 index 0000000..b0760e3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycReviewStatus.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type KycReviewStatus = + | "rejected" + | "update_required" + | "approved" + | "in_review"; diff --git a/app/packages/payy/src/ts-rs-bindings/KycState.ts b/app/packages/payy/src/ts-rs-bindings/KycState.ts new file mode 100644 index 0000000..d6a8481 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycState.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type KycState = { isSubmitting: boolean; progressValue: number | null }; diff --git a/app/packages/payy/src/ts-rs-bindings/KycStatus.ts b/app/packages/payy/src/ts-rs-bindings/KycStatus.ts new file mode 100644 index 0000000..4de8e12 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycStatus.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type KycStatus = + | "NOT_STARTED" + | "PENDING" + | "APPROVED" + | "UPDATE_REQUIRED" + | "REJECTED"; diff --git a/app/packages/payy/src/ts-rs-bindings/KycUpdateRequired.ts b/app/packages/payy/src/ts-rs-bindings/KycUpdateRequired.ts new file mode 100644 index 0000000..c05778a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycUpdateRequired.ts @@ -0,0 +1,14 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycUpdateRequiredInvalidFields } from "./KycUpdateRequiredInvalidFields"; + +export type KycUpdateRequired = + | { "error": "NONE" } + | { "error": "UNSUPPORTED_COUNTRY" } + | { "error": "INVALID_FIELDS"; "data": KycUpdateRequiredInvalidFields } + | { "error": "USER_REQUESTED_DELETE" } + | { "error": "PAYY_COMPLIANCE_VIOLATION" } + | { "error": "DUPLICATE" } + | { "error": "AGE_RESTRICTION" } + | { "error": "DOCUMENT_FORGERY" } + | { "error": "INVALID_DOCUMENT_PHOTO" } + | { "error": "INCONSISTENT_DOCUMENTS" }; diff --git a/app/packages/payy/src/ts-rs-bindings/KycUpdateRequiredInvalidFields.ts b/app/packages/payy/src/ts-rs-bindings/KycUpdateRequiredInvalidFields.ts new file mode 100644 index 0000000..ce64ecd --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycUpdateRequiredInvalidFields.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycField } from "./KycField"; +import type { KycUpdateRequiredInvalidFieldsReason } from "./KycUpdateRequiredInvalidFieldsReason"; + +export type KycUpdateRequiredInvalidFields = { + fields: { [key in KycField]?: KycUpdateRequiredInvalidFieldsReason }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/KycUpdateRequiredInvalidFieldsReason.ts b/app/packages/payy/src/ts-rs-bindings/KycUpdateRequiredInvalidFieldsReason.ts new file mode 100644 index 0000000..3a81c9b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/KycUpdateRequiredInvalidFieldsReason.ts @@ -0,0 +1,50 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type KycUpdateRequiredInvalidFieldsReason = + | { "reason": "UNSPECIFIED" } + | { "reason": "NAME_MISMATCH" } + | { "reason": "DOCUMENT_KYC_MISMATCH" } + | { "reason": "DOCUMENT_PHOTO_BLURRY" } + | { "reason": "DOCUMENT_PHOTO_NOT_CENTERED" } + | { "reason": "DOCUMENT_PHOTO_DAMAGED" } + | { "reason": "DOCUMENT_PHOTO_NOT_ORIGINAL" } + | { "reason": "DOCUMENT_EXPIRES_SOON" } + | { "reason": "DOCUMENT_IS_EXPIRED" } + | { "reason": "DOCUMENT_KIND_NOT_ALLOWED" } + | { "reason": "ADVERSE_MEDIA" } + | { "reason": "AGE_REQUIREMENT_MISMATCH" } + | { "reason": "BLACKLIST" } + | { "reason": "BLOCKLIST" } + | { "reason": "CHECK_UNAVAILABLE" } + | { "reason": "COMPROMISED_PERSONS" } + | { "reason": "CRIMINAL" } + | { "reason": "DB_DATA_MISMATCH" } + | { "reason": "DB_DATA_NOT_FOUND" } + | { "reason": "DOCUMENT_TEMPLATE" } + | { "reason": "DUPLICATE" } + | { "reason": "EXPERIENCE_REQUIREMENT_MISMATCH" } + | { "reason": "FORGERY" } + | { "reason": "FRAUDULENT_LIVENESS" } + | { "reason": "FRAUDULENT_PATTERNS" } + | { "reason": "INCONSISTENT_PROFILE" } + | { "reason": "PEP" } + | { "reason": "REGULATIONS_VIOLATIONS" } + | { "reason": "SANCTIONS" } + | { "reason": "SELFIE_MISMATCH" } + | { "reason": "SPAM" } + | { "reason": "NOT_DOCUMENT" } + | { "reason": "THIRD_PARTY_INVOLVED" } + | { "reason": "UNSUPPORTED_LANGUAGE" } + | { "reason": "WRONG_USER_REGION" } + | { "reason": "INVALID_PHONE_NUMBER" } + | { "reason": "INVALID_EMAIL" } + | { "reason": "INVALID_FORMAT" } + | { "reason": "INVALID_POSTAL_CODE" } + | { "reason": "INVALID_NATIONAL_ID" } + | { "reason": "NAME_TOO_LONG" } + | { "reason": "ADDRESS_STREET_TOO_LONG" } + | { "reason": "ADDRESS_CITY_TOO_LONG" } + | { "reason": "ADDRESS_STATE_TOO_LONG" } + | { "reason": "COMPLIANCE" } + | { "reason": "SANCTIONED" } + | { "reason": "POLITICALLY_EXPOSED_PERSON" }; diff --git a/app/packages/payy/src/ts-rs-bindings/LastNameEvent.ts b/app/packages/payy/src/ts-rs-bindings/LastNameEvent.ts new file mode 100644 index 0000000..60142f4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/LastNameEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type LastNameEvent = { + "type": "onSubmit"; + "payload": { lastname: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/LastNameViewModel.ts b/app/packages/payy/src/ts-rs-bindings/LastNameViewModel.ts new file mode 100644 index 0000000..ed35067 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/LastNameViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type LastNameViewModel = { + initialValue: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/LinkStatusExternal.ts b/app/packages/payy/src/ts-rs-bindings/LinkStatusExternal.ts new file mode 100644 index 0000000..d699714 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/LinkStatusExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type LinkStatusExternal = "PENDING" | "READY" | "CANCELLED" | "CLAIMED"; diff --git a/app/packages/payy/src/ts-rs-bindings/ListActivityInput.ts b/app/packages/payy/src/ts-rs-bindings/ListActivityInput.ts new file mode 100644 index 0000000..979f01d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListActivityInput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityStoreListQuery } from "./ActivityStoreListQuery"; + +export type ListActivityInput = { query: ActivityStoreListQuery }; diff --git a/app/packages/payy/src/ts-rs-bindings/ListActivityLongPollInput.ts b/app/packages/payy/src/ts-rs-bindings/ListActivityLongPollInput.ts new file mode 100644 index 0000000..6eb28f2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListActivityLongPollInput.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityStoreListQuery } from "./ActivityStoreListQuery"; + +export type ListActivityLongPollInput = { + query: ActivityStoreListQuery; + last_modified: string | null; + timeout_secs: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ListActivityLongPollOutput.ts b/app/packages/payy/src/ts-rs-bindings/ListActivityLongPollOutput.ts new file mode 100644 index 0000000..4c9922e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListActivityLongPollOutput.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityExternalData } from "./ActivityExternalData"; + +export type ListActivityLongPollOutput = { + data: Array; + loading: boolean; + last_modified: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ListActivityOutput.ts b/app/packages/payy/src/ts-rs-bindings/ListActivityOutput.ts new file mode 100644 index 0000000..21f927c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListActivityOutput.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ActivityExternalData } from "./ActivityExternalData"; + +export type ListActivityOutput = { + data: Array; + loading: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ListBlocksOrder.ts b/app/packages/payy/src/ts-rs-bindings/ListBlocksOrder.ts new file mode 100644 index 0000000..2ed32f5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListBlocksOrder.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Ordering options for listing blocks. + */ +export type ListBlocksOrder = "LowestToHighest" | "HighestToLowest"; diff --git a/app/packages/payy/src/ts-rs-bindings/ListBlocksResponse.ts b/app/packages/payy/src/ts-rs-bindings/ListBlocksResponse.ts new file mode 100644 index 0000000..461507a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListBlocksResponse.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockWithInfo } from "./BlockWithInfo"; + +/** + * Response structure for listing blocks. + */ +export type ListBlocksResponse = { + /** + * Blocks returned by the node. + */ + blocks: Array; + /** + * Pagination cursor for fetching additional blocks. + */ + cursor: import("./OpaqueClientCursor").OpaqueClientCursor; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ListTxnsOrder.ts b/app/packages/payy/src/ts-rs-bindings/ListTxnsOrder.ts new file mode 100644 index 0000000..c4c8e5c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListTxnsOrder.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Ordering options for listing transactions. + */ +export type ListTxnsOrder = "NewestToOldest" | "OldestToNewest"; diff --git a/app/packages/payy/src/ts-rs-bindings/ListTxnsParams.ts b/app/packages/payy/src/ts-rs-bindings/ListTxnsParams.ts new file mode 100644 index 0000000..c62d154 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListTxnsParams.ts @@ -0,0 +1,24 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ListTxnsOrder } from "./ListTxnsOrder"; + +/** + * Parameters for listing transactions. + */ +export type ListTxnsParams = { + /** + * Maximum number of transactions to return. + */ + limit: number; + /** + * Pagination cursor for fetching additional transactions. + */ + cursor?: string; + /** + * Ordering for the listed transactions. + */ + order: ListTxnsOrder; + /** + * Whether to wait for a new transaction when none are available. + */ + poll: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ListTxnsPosition.ts b/app/packages/payy/src/ts-rs-bindings/ListTxnsPosition.ts new file mode 100644 index 0000000..86e4de1 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListTxnsPosition.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockHeight } from "./BlockHeight"; + +/** + * Cursor position for listing transactions. + */ +export type ListTxnsPosition = { + /** + * Block height for the transaction. + */ + block: BlockHeight; + /** + * Transaction index within the block. + */ + txn: bigint; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ListTxnsResponse.ts b/app/packages/payy/src/ts-rs-bindings/ListTxnsResponse.ts new file mode 100644 index 0000000..7eab0d9 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ListTxnsResponse.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { TxnWithInfo } from "./TxnWithInfo"; + +/** + * Response structure for listing transactions. + */ +export type ListTxnsResponse = { + /** + * Transactions returned by the node. + */ + txns: Array; + /** + * Pagination cursor for fetching additional transactions. + */ + cursor: import("./OpaqueClientCursor").OpaqueClientCursor; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/LoadWalletInput.ts b/app/packages/payy/src/ts-rs-bindings/LoadWalletInput.ts new file mode 100644 index 0000000..c348852 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/LoadWalletInput.ts @@ -0,0 +1,15 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { MigrateInput } from "./MigrateInput"; +import type { WalletMobileConfig } from "./WalletMobileConfig"; + +export type LoadWalletInput = { + private_key: Element; + config: WalletMobileConfig; + force: boolean; + locale: string | null; + dsn: string; + env_name: string; + sentry_app_version: string; + migration_data: MigrateInput | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/LoadingResult.ts b/app/packages/payy/src/ts-rs-bindings/LoadingResult.ts new file mode 100644 index 0000000..010445c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/LoadingResult.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type LoadingResult = { "type": "loading" } | { + "type": "ok"; + "payload": T; +} | { "type": "err"; "payload": E }; diff --git a/app/packages/payy/src/ts-rs-bindings/MenuEvent.ts b/app/packages/payy/src/ts-rs-bindings/MenuEvent.ts new file mode 100644 index 0000000..1532d42 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MenuEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { MenuItemKey } from "./MenuItemKey"; + +export type MenuEvent = { + "type": "onItemPress"; + "payload": { key: MenuItemKey }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/MenuItemKey.ts b/app/packages/payy/src/ts-rs-bindings/MenuItemKey.ts new file mode 100644 index 0000000..abdb9eb --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MenuItemKey.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type MenuItemKey = "deposit" | "withdraw" | "rewards" | "settings"; diff --git a/app/packages/payy/src/ts-rs-bindings/MenuViewModel.ts b/app/packages/payy/src/ts-rs-bindings/MenuViewModel.ts new file mode 100644 index 0000000..0c5a970 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MenuViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type MenuViewModel = { bottomInset: number }; diff --git a/app/packages/payy/src/ts-rs-bindings/MerklePath.ts b/app/packages/payy/src/ts-rs-bindings/MerklePath.ts new file mode 100644 index 0000000..60c37e4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MerklePath.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type MerklePath = { siblings: Array }; diff --git a/app/packages/payy/src/ts-rs-bindings/MigrateInput.ts b/app/packages/payy/src/ts-rs-bindings/MigrateInput.ts new file mode 100644 index 0000000..1f30141 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MigrateInput.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { MigrateInputNote } from "./MigrateInputNote"; + +export type MigrateInput = { + migration_id?: string; + old_wallet_state?: string; + notes?: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/MigrateInputNote.ts b/app/packages/payy/src/ts-rs-bindings/MigrateInputNote.ts new file mode 100644 index 0000000..b0297a2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MigrateInputNote.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type MigrateInputNote = { + value: Element; + address: Element; + psi: Element; + private_key: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/MigrateProof.ts b/app/packages/payy/src/ts-rs-bindings/MigrateProof.ts new file mode 100644 index 0000000..91519ab --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MigrateProof.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { MigratePublicInput } from "./MigratePublicInput"; +import type { ProofBytes } from "./ProofBytes"; + +/** + * Migration proof output + */ +export type MigrateProof = { + /** + * The proof bytes (without public inputs) + */ + proof: ProofBytes; + /** + * The public inputs + */ + public_inputs: MigratePublicInput; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/MigrateProofInput.ts b/app/packages/payy/src/ts-rs-bindings/MigrateProofInput.ts new file mode 100644 index 0000000..4cc98c6 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MigrateProofInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type MigrateProofInput = { owner_pk: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/MigratePublicInput.ts b/app/packages/payy/src/ts-rs-bindings/MigratePublicInput.ts new file mode 100644 index 0000000..2b536a1 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MigratePublicInput.ts @@ -0,0 +1,15 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Migration public inputs + */ +export type MigratePublicInput = { + /** + * The old address being migrated from + */ + old_address: string; + /** + * The new address being migrated to + */ + new_address: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/MintExternal.ts b/app/packages/payy/src/ts-rs-bindings/MintExternal.ts new file mode 100644 index 0000000..a408884 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MintExternal.ts @@ -0,0 +1,20 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { TransactionResponse } from "./TransactionResponse"; + +/** + * External mint data + */ +export type MintExternal = { + /** + * Hex address the mint was deposited from + */ + evm_deposit_addr: string; + /** + * Evm txn hash where the deposit was sent + */ + evm_txn_hash: string; + /** + * Payy txn receipt + */ + txn_receipt: TransactionResponse | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/MintInput.ts b/app/packages/payy/src/ts-rs-bindings/MintInput.ts new file mode 100644 index 0000000..f15019f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/MintInput.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WalletPrivateKeyKind } from "./WalletPrivateKeyKind"; + +export type MintInput = { + value: string; + private_key_kind: WalletPrivateKeyKind; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/NationalIdEvent.ts b/app/packages/payy/src/ts-rs-bindings/NationalIdEvent.ts new file mode 100644 index 0000000..82f49c8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/NationalIdEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type NationalIdEvent = { + "type": "onSubmit"; + "payload": { nationalId: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/NationalIdInputConfig.ts b/app/packages/payy/src/ts-rs-bindings/NationalIdInputConfig.ts new file mode 100644 index 0000000..9d39588 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/NationalIdInputConfig.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { NationalIdInputRule } from "./NationalIdInputRule"; + +export type NationalIdInputConfig = { + label: string | null; + placeholder: string | null; + helper: string | null; + rules: Array | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/NationalIdInputRule.ts b/app/packages/payy/src/ts-rs-bindings/NationalIdInputRule.ts new file mode 100644 index 0000000..ebd3c31 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/NationalIdInputRule.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type NationalIdInputRule = { pattern: string; message: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/NationalIdViewModel.ts b/app/packages/payy/src/ts-rs-bindings/NationalIdViewModel.ts new file mode 100644 index 0000000..c2d6d7a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/NationalIdViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; +import type { NationalIdInputConfig } from "./NationalIdInputConfig"; + +export type NationalIdViewModel = { + initialValue: string | null; + inputConfig: NationalIdInputConfig | null; + titleOverride: string | null; + descriptionOverride: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/Network.ts b/app/packages/payy/src/ts-rs-bindings/Network.ts new file mode 100644 index 0000000..f9f6c88 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Network.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Network = + | "PAYY" + | "POLYGON" + | "ETHEREUM" + | "SPEI" + | "PIX" + | "COELSA" + | "CARD" + | "EXTERNAL_CARD" + | "US_BANK" + | "PLAID"; diff --git a/app/packages/payy/src/ts-rs-bindings/NetworkIdentifier.ts b/app/packages/payy/src/ts-rs-bindings/NetworkIdentifier.ts new file mode 100644 index 0000000..9f0075c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/NetworkIdentifier.ts @@ -0,0 +1,30 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Provides normalized options to identify an account + * on a network. A network may support multiple ways + * to identify an account, and each way may require multiple + * fields. + */ +export type NetworkIdentifier = { + accountnumber?: string; + routingnumber?: string; + cardnumber?: string; + cardexpiration?: string; + cardcvv?: string; + pin?: string; + phonenumber?: string; + email?: string; + address?: string; + methodid?: string; + reference?: string; + accountid?: string; + qrcode?: string; + plaid_public_token?: string; + plaid_account_id?: string; + plaid_institution_id?: string; + bank_name?: string; + plaid_mask?: string; + plaid_account_name?: string; + external_bank_guid?: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/NoExternalData.ts b/app/packages/payy/src/ts-rs-bindings/NoExternalData.ts new file mode 100644 index 0000000..b453b37 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/NoExternalData.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type NoExternalData = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/Note.ts b/app/packages/payy/src/ts-rs-bindings/Note.ts new file mode 100644 index 0000000..f767d4f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Note.ts @@ -0,0 +1,31 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +/** + * A note is used in zk circuits to represent some kind of token (e.g. USDC) on + * the Payy Network. + * + * This is used to create notes in the zk-rollup + */ +export type Note = { + /** + * The kind of note + */ + kind: Element; + /** + * The contract of note + */ + contract: Element; + /** + * The address of the note + */ + address: Element; + /** + * The psi adds additional entropy to the note, to ensure uniqueness + */ + psi: Element; + /** + * The value of the note (dependent on the token) + */ + value: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/OccupationEvent.ts b/app/packages/payy/src/ts-rs-bindings/OccupationEvent.ts new file mode 100644 index 0000000..c82e027 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/OccupationEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type OccupationEvent = { + "type": "onSubmit"; + "payload": { occupation: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/OccupationViewModel.ts b/app/packages/payy/src/ts-rs-bindings/OccupationViewModel.ts new file mode 100644 index 0000000..6258ec7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/OccupationViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type OccupationViewModel = { + initialValue: string | null; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/OldAddressInput.ts b/app/packages/payy/src/ts-rs-bindings/OldAddressInput.ts new file mode 100644 index 0000000..89f0a1b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/OldAddressInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type OldAddressInput = { pks: Array }; diff --git a/app/packages/payy/src/ts-rs-bindings/OpaqueClientCursor.ts b/app/packages/payy/src/ts-rs-bindings/OpaqueClientCursor.ts new file mode 100644 index 0000000..3381b84 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/OpaqueClientCursor.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * This type is meant to be used in client code, + * where the actual cursor types are not needed. + */ +export type OpaqueClientCursor = { + after: string | null; + before: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ParseLinkInput.ts b/app/packages/payy/src/ts-rs-bindings/ParseLinkInput.ts new file mode 100644 index 0000000..57b3f4f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ParseLinkInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ParseLinkInput = { link: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/ParseLinkOutput.ts b/app/packages/payy/src/ts-rs-bindings/ParseLinkOutput.ts new file mode 100644 index 0000000..5480303 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ParseLinkOutput.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ParseLinkOutput = { + link: import("../ts-rs-bindings/PaymentLink").PaymentLink | null; + error: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ParseLinkSecretInput.ts b/app/packages/payy/src/ts-rs-bindings/ParseLinkSecretInput.ts new file mode 100644 index 0000000..d508836 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ParseLinkSecretInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ParseLinkSecretInput = { secret_hash: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/ParseLinkSecretOutput.ts b/app/packages/payy/src/ts-rs-bindings/ParseLinkSecretOutput.ts new file mode 100644 index 0000000..141a132 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ParseLinkSecretOutput.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type ParseLinkSecretOutput = { + note: import("./Note").Note | null; + private_key: import("./Element").Element | null; + is_spent: boolean; + error: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PasswordEvent.ts b/app/packages/payy/src/ts-rs-bindings/PasswordEvent.ts new file mode 100644 index 0000000..ee32ad3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PasswordEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PasswordEvent = { + "type": "onSetValue"; + "payload": { value: string }; +} | { "type": "onPress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/PasswordViewModel.ts b/app/packages/payy/src/ts-rs-bindings/PasswordViewModel.ts new file mode 100644 index 0000000..9e2c694 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PasswordViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PasswordViewModel = { + value: string; + /** + * Numeric strength value: 20 | 60 | 80 | 100 | null + */ + passwordStrength: 20 | 60 | 80 | 100 | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PaymentLink.ts b/app/packages/payy/src/ts-rs-bindings/PaymentLink.ts new file mode 100644 index 0000000..6ac6959 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PaymentLink.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { InviteLink } from "./InviteLink"; +import type { RequestLink } from "./RequestLink"; +import type { SendLinkHash } from "./SendLinkHash"; + +/** + * Represents any supported Payy link. + */ +export type PaymentLink = + | { "kind": "request" } & RequestLink + | { "kind": "send" } & SendLinkHash + | { "kind": "invite" } & InviteLink; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyCoreDevEvent.ts b/app/packages/payy/src/ts-rs-bindings/PayyCoreDevEvent.ts new file mode 100644 index 0000000..0ca4aa8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyCoreDevEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PayyCoreDevEvent = + | { "type": "Increment" } + | { "type": "Decrement" } + | { "type": "SetName"; "payload": { name: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyCoreDevViewModel.ts b/app/packages/payy/src/ts-rs-bindings/PayyCoreDevViewModel.ts new file mode 100644 index 0000000..dddc0c5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyCoreDevViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PayyCoreDevViewModel = { + countText: string; + minusDisabled: boolean; + greeting: string; + walletBalance: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyCoreProcessEventInput.ts b/app/packages/payy/src/ts-rs-bindings/PayyCoreProcessEventInput.ts new file mode 100644 index 0000000..eff86f4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyCoreProcessEventInput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PayyUiEvent } from "./PayyUiEvent"; + +export type PayyCoreProcessEventInput = { event: PayyUiEvent }; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyCoreViewModelLongPollInput.ts b/app/packages/payy/src/ts-rs-bindings/PayyCoreViewModelLongPollInput.ts new file mode 100644 index 0000000..5f450ad --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyCoreViewModelLongPollInput.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type PayyCoreViewModelLongPollInput = { + sinceVersion: number | null; + timeoutSecs: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyCoreViewModelLongPollOutput.ts b/app/packages/payy/src/ts-rs-bindings/PayyCoreViewModelLongPollOutput.ts new file mode 100644 index 0000000..c908ac3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyCoreViewModelLongPollOutput.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PayyViewModel } from "./PayyViewModel"; + +export type PayyCoreViewModelLongPollOutput = { + version: number; + viewModel: PayyViewModel; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyNavigationRoute.ts b/app/packages/payy/src/ts-rs-bindings/PayyNavigationRoute.ts new file mode 100644 index 0000000..2590df7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyNavigationRoute.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PayyNavigationState } from "./PayyNavigationState"; + +export type PayyNavigationRoute = { + name: string; + params?: Record | null; + state?: PayyNavigationState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyNavigationState.ts b/app/packages/payy/src/ts-rs-bindings/PayyNavigationState.ts new file mode 100644 index 0000000..d4a9922 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyNavigationState.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PayyNavigationRoute } from "./PayyNavigationRoute"; + +export type PayyNavigationState = { + index: number; + routes: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyUiEvent.ts b/app/packages/payy/src/ts-rs-bindings/PayyUiEvent.ts new file mode 100644 index 0000000..445e231 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyUiEvent.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { HomeEvent } from "./HomeEvent"; +import type { PayyCoreDevEvent } from "./PayyCoreDevEvent"; +import type { PayyNavigationState } from "./PayyNavigationState"; + +export type PayyUiEvent = + | { "type": "Home"; "payload": HomeEvent } + | { "type": "PayyCoreDev"; "payload": PayyCoreDevEvent } + | { "type": "SetRoute"; "payload": { route: string } } + | { "type": "SetNavigationStack"; "payload": { state: PayyNavigationState } }; diff --git a/app/packages/payy/src/ts-rs-bindings/PayyViewModel.ts b/app/packages/payy/src/ts-rs-bindings/PayyViewModel.ts new file mode 100644 index 0000000..a5549b5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PayyViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { HomeViewModel } from "./HomeViewModel"; +import type { PayyCoreDevViewModel } from "./PayyCoreDevViewModel"; +import type { PayyNavigationState } from "./PayyNavigationState"; + +export type PayyViewModel = { + route: string; + navigationState: PayyNavigationState; + home: HomeViewModel; + payyCoreDev: PayyCoreDevViewModel; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PointsOutput.ts b/app/packages/payy/src/ts-rs-bindings/PointsOutput.ts new file mode 100644 index 0000000..827b867 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PointsOutput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PointsProof } from "./PointsProof"; + +export type PointsOutput = { proof: PointsProof }; diff --git a/app/packages/payy/src/ts-rs-bindings/PointsProof.ts b/app/packages/payy/src/ts-rs-bindings/PointsProof.ts new file mode 100644 index 0000000..5667f3d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PointsProof.ts @@ -0,0 +1,18 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { PointsPublicInput } from "./PointsPublicInput"; +import type { ProofBytes } from "./ProofBytes"; + +/** + * Bundle of a proof and its public inputs for points. This can be used + * verify the proof. + */ +export type PointsProof = { + /** + * Proof + */ + proof: ProofBytes; + /** + * Public inputs + */ + public_inputs: PointsPublicInput; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/PointsPublicInput.ts b/app/packages/payy/src/ts-rs-bindings/PointsPublicInput.ts new file mode 100644 index 0000000..6ee06dd --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/PointsPublicInput.ts @@ -0,0 +1,35 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +/** + * Public input for the points circuit + */ +export type PointsPublicInput = { + /** + * Value of the points + */ + value: Element; + /** + * Timestamp (points proofs are valid for 1 day) + */ + timestamp: Element; + /** + * Hash of address and timestamp + */ + hash: Element; + /** + * Commitments to check that are in the tree and so points can be claimed + */ + commitments: [ + Element, + Element, + Element, + Element, + Element, + Element, + Element, + Element, + Element, + Element, + ]; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/ProofBytes.ts b/app/packages/payy/src/ts-rs-bindings/ProofBytes.ts new file mode 100644 index 0000000..6cd4a49 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ProofBytes.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Raw proof bytes for zk circuit proofs (without public inputs). + */ +export type ProofBytes = string; diff --git a/app/packages/payy/src/ts-rs-bindings/Provider.ts b/app/packages/payy/src/ts-rs-bindings/Provider.ts new file mode 100644 index 0000000..c07b0b8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Provider.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Provider = + | "ALFRED" + | "MANTECA" + | "RAIN" + | "SUMSUB" + | "CYBRID" + | "STRIPE"; diff --git a/app/packages/payy/src/ts-rs-bindings/ProviderTermsGroup.ts b/app/packages/payy/src/ts-rs-bindings/ProviderTermsGroup.ts new file mode 100644 index 0000000..254be15 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/ProviderTermsGroup.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { TermsLinkItem } from "./TermsLinkItem"; + +export type ProviderTermsGroup = { + providerId: string; + entries: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampBankTransferCountry.ts b/app/packages/payy/src/ts-rs-bindings/RampBankTransferCountry.ts new file mode 100644 index 0000000..5c56636 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampBankTransferCountry.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampBankTransferCountry = { id: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/RampBankTransferCurrency.ts b/app/packages/payy/src/ts-rs-bindings/RampBankTransferCurrency.ts new file mode 100644 index 0000000..3a78273 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampBankTransferCurrency.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampBankTransferCountry } from "./RampBankTransferCountry"; + +export type RampBankTransferCurrency = { + code: string; + name: string; + country: RampBankTransferCountry; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampBankTransferEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampBankTransferEvent.ts new file mode 100644 index 0000000..7a16b93 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampBankTransferEvent.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampBankTransferCurrency } from "./RampBankTransferCurrency"; + +export type RampBankTransferEvent = { + "type": "onSearchTermChange"; + "payload": { value: string }; +} | { + "type": "onSelectCurrency"; + "payload": { currency: RampBankTransferCurrency }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampBankTransferViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampBankTransferViewModel.ts new file mode 100644 index 0000000..fe472e4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampBankTransferViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampBankTransferCurrency } from "./RampBankTransferCurrency"; + +export type RampBankTransferViewModel = { + currencies: Array; + searchTerm: string; + showSearch: boolean; + searchPlaceholder: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampCardTransaction.ts b/app/packages/payy/src/ts-rs-bindings/RampCardTransaction.ts new file mode 100644 index 0000000..ca6c5ef --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampCardTransaction.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { CardStatus } from "./CardStatus"; +import type { Category } from "./Category"; +import type { Element } from "./Element"; +import type { FundingStatus } from "./FundingStatus"; + +export type RampCardTransaction = { + status: CardStatus; + name: string; + desc: string | null; + icon: string | null; + category: Category; + pending_refund_amount: Element | null; + funding_status: FundingStatus | null; + funding_due_amount: Element | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampConfirmAction.ts b/app/packages/payy/src/ts-rs-bindings/RampConfirmAction.ts new file mode 100644 index 0000000..ccc8918 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampConfirmAction.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Action type for ramp operations + */ +export type RampConfirmAction = "deposit" | "withdraw"; diff --git a/app/packages/payy/src/ts-rs-bindings/RampConfirmEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampConfirmEvent.ts new file mode 100644 index 0000000..a2d8178 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampConfirmEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Events emitted by RampConfirmScreen + */ +export type RampConfirmEvent = { + "type": "onCancel"; + "payload": Record; +} | { "type": "onConfirm"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/RampConfirmQuote.ts b/app/packages/payy/src/ts-rs-bindings/RampConfirmQuote.ts new file mode 100644 index 0000000..4fcc9a4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampConfirmQuote.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Screen-local quote (serializable subset of ramps-interface Quote) + */ +export type RampConfirmQuote = { + id: string; + fromCurrency: string; + fromAmount: string; + fromNetwork: string; + toCurrency: string; + toAmount: string; + toNetwork: string; + expiresAt: string | null; + addedAt: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampConfirmViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampConfirmViewModel.ts new file mode 100644 index 0000000..8eca001 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampConfirmViewModel.ts @@ -0,0 +1,22 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampConfirmAction } from "./RampConfirmAction"; +import type { RampConfirmQuote } from "./RampConfirmQuote"; +import type { RampStaticIdentifierPreviewItem } from "./RampStaticIdentifierPreviewItem"; + +/** + * ViewModel for RampConfirmScreen + */ +export type RampConfirmViewModel = { + action: RampConfirmAction; + actionTitle: string; + quote: RampConfirmQuote | null; + fromAmount: string | null; + toAmount: string | null; + showWarningBox: boolean; + showUsdBanner: boolean; + identifierPreviewItems: Array | null; + errorKey: string | null; + errorMessage: string | null; + confirmDisabled: boolean; + confirmLoading: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampDepositExternal.ts b/app/packages/payy/src/ts-rs-bindings/RampDepositExternal.ts new file mode 100644 index 0000000..784fdf4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampDepositExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampDepositExternal = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/RampDepositLinkTransaction.ts b/app/packages/payy/src/ts-rs-bindings/RampDepositLinkTransaction.ts new file mode 100644 index 0000000..8fe267c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampDepositLinkTransaction.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { RampStatus } from "./RampStatus"; + +export type RampDepositLinkTransaction = { + status: RampStatus; + note_kind: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampDepositTransaction.ts b/app/packages/payy/src/ts-rs-bindings/RampDepositTransaction.ts new file mode 100644 index 0000000..e89523e --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampDepositTransaction.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { RampStatus } from "./RampStatus"; + +export type RampDepositTransaction = { + status: RampStatus; + private_key: Element; + note_kind: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampKycReviewEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampKycReviewEvent.ts new file mode 100644 index 0000000..71f784b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampKycReviewEvent.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampKycReviewEvent = + | { "type": "onDone"; "payload": Record } + | { "type": "onRejectedDone"; "payload": Record } + | { "type": "onRestartKyc"; "payload": Record } + | { "type": "onFixKyc"; "payload": Record } + | { + "type": "onSupportPress"; + "payload": { meta: Record | null }; + } + | { "type": "onNotificationToggle"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/RampKycReviewNotificationBanner.ts b/app/packages/payy/src/ts-rs-bindings/RampKycReviewNotificationBanner.ts new file mode 100644 index 0000000..8bf5a08 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampKycReviewNotificationBanner.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampKycReviewNotificationBanner = { + text: string; + additionalText: string | null; + isEnabled: boolean; + shouldShow: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampKycReviewViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampKycReviewViewModel.ts new file mode 100644 index 0000000..23bba6d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampKycReviewViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycReviewStatus } from "./KycReviewStatus"; +import type { KycUpdateRequired } from "./KycUpdateRequired"; +import type { LoadingResult } from "./LoadingResult"; +import type { RampKycReviewNotificationBanner } from "./RampKycReviewNotificationBanner"; + +export type RampKycReviewViewModel = { + status: LoadingResult; + updateRequired: KycUpdateRequired | null; + notificationBanner: RampKycReviewNotificationBanner | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampKycSubmitEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampKycSubmitEvent.ts new file mode 100644 index 0000000..c05dad3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampKycSubmitEvent.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampKycSubmitEvent = + | { "type": "onProgressComplete"; "payload": Record } + | { "type": "onDone"; "payload": Record } + | { "type": "onRejectedDone"; "payload": Record } + | { "type": "onRestartKyc"; "payload": Record } + | { "type": "onFixKyc"; "payload": Record } + | { + "type": "onSupportPress"; + "payload": { meta: Record | null }; + } + | { "type": "onNotificationToggle"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/RampKycSubmitStatus.ts b/app/packages/payy/src/ts-rs-bindings/RampKycSubmitStatus.ts new file mode 100644 index 0000000..58f8034 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampKycSubmitStatus.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampKycSubmitStatus = "submitting" | "loading" | "review"; diff --git a/app/packages/payy/src/ts-rs-bindings/RampKycSubmitViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampKycSubmitViewModel.ts new file mode 100644 index 0000000..2ddaa3c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampKycSubmitViewModel.ts @@ -0,0 +1,14 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycReviewStatus } from "./KycReviewStatus"; +import type { KycUpdateRequired } from "./KycUpdateRequired"; +import type { RampKycReviewNotificationBanner } from "./RampKycReviewNotificationBanner"; +import type { RampKycSubmitStatus } from "./RampKycSubmitStatus"; + +export type RampKycSubmitViewModel = { + status: RampKycSubmitStatus; + progress: number; + timer: number; + reviewStatus: KycReviewStatus | null; + updateRequired: KycUpdateRequired | null; + notificationBanner: RampKycReviewNotificationBanner | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodCreateEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateEvent.ts new file mode 100644 index 0000000..e25e6a8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateEvent.ts @@ -0,0 +1,15 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Events emitted by RampMethodCreateScreen + */ +export type RampMethodCreateEvent = + | { "type": "onSelectGroup"; "payload": { index: number } } + | { "type": "onFieldChange"; "payload": { field: string; value: string } } + | { + "type": "onFieldError"; + "payload": { index: number; error: string | null }; + } + | { "type": "onSelectAnotherAccount"; "payload": Record } + | { "type": "onSubmit"; "payload": Record } + | { "type": "onCloseKycMismatchAlert"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodCreateFieldConfig.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateFieldConfig.ts new file mode 100644 index 0000000..5b81b2b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateFieldConfig.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampMethodCreateFieldRule } from "./RampMethodCreateFieldRule"; + +/** + * Field configuration for dynamic forms + */ +export type RampMethodCreateFieldConfig = { + identifier: string; + required: boolean; + label: string; + placeholder: string | null; + rules: Array | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodCreateFieldRule.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateFieldRule.ts new file mode 100644 index 0000000..0e8e8c6 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateFieldRule.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Validation rule for form fields + */ +export type RampMethodCreateFieldRule = { pattern: string; message: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodCreateViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateViewModel.ts new file mode 100644 index 0000000..6ebe125 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodCreateViewModel.ts @@ -0,0 +1,23 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { NetworkIdentifier } from "./NetworkIdentifier"; +import type { RampMethodCreateFieldConfig } from "./RampMethodCreateFieldConfig"; + +/** + * ViewModel for RampMethodCreateScreen + */ +export type RampMethodCreateViewModel = { + network: string; + networkTitleKey: string | null; + groupTitles: Array; + groupDescriptions: Array; + selectedGroupIndex: number; + fields: Array; + networkIdentifier: NetworkIdentifier; + methodDeleted: boolean; + isPlaid: boolean; + hasOtherBankAccounts: boolean; + submitDisabled: boolean; + submitLoading: boolean; + showKycMismatchAlert: boolean; + showSubmitButton: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodListEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodListEvent.ts new file mode 100644 index 0000000..2104753 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodListEvent.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampMethodListMethod } from "./RampMethodListMethod"; + +/** + * Events emitted by RampMethodListScreen + */ +export type RampMethodListEvent = { + "type": "onSelectMethod"; + "payload": { method: RampMethodListMethod }; +} | { "type": "onCreateMethod"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodListItem.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodListItem.ts new file mode 100644 index 0000000..fcb4ecf --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodListItem.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampMethodListMethod } from "./RampMethodListMethod"; +import type { RampStaticIdentifierPreviewItem } from "./RampStaticIdentifierPreviewItem"; + +/** + * Method item with preview data + */ +export type RampMethodListItem = { + method: RampMethodListMethod; + previewItems: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodListMethod.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodListMethod.ts new file mode 100644 index 0000000..e56e3b3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodListMethod.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { NetworkIdentifier } from "./NetworkIdentifier"; + +/** + * Screen-local method type (simplified from hook RampMethod) + */ +export type RampMethodListMethod = { + localId: string | null; + methodId: string | null; + network: string; + identifier: NetworkIdentifier; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampMethodListViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampMethodListViewModel.ts new file mode 100644 index 0000000..eb37434 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampMethodListViewModel.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampMethodListItem } from "./RampMethodListItem"; + +/** + * ViewModel for RampMethodListScreen + */ +export type RampMethodListViewModel = { + methodItems: Array; + loading: boolean; + alertMessage: string | null; + network: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampNetworkAmountEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampNetworkAmountEvent.ts new file mode 100644 index 0000000..0cf565c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampNetworkAmountEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Event variants for ramp network amount screen actions. + */ +export type RampNetworkAmountEvent = { + "type": "onSubmit"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampNetworkAmountViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampNetworkAmountViewModel.ts new file mode 100644 index 0000000..5845eec --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampNetworkAmountViewModel.ts @@ -0,0 +1,22 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * View model for ramp network amount screen. + */ +export type RampNetworkAmountViewModel = { + fromCurrency: string; + toCurrency: string; + amountDisplay: string; + isZeroAmount: boolean; + quoteLoading: boolean; + quoteError: string | null; + quoteResultDisplay: string | null; + showBalance: boolean; + isBalanceVisible: boolean; + diffDisplay: string; + overLimit: boolean; + limitErrorMessage: string | null; + isAmountInvalid: boolean; + submitDisabled: boolean; + submitLoading: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierAmountSummary.ts b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierAmountSummary.ts new file mode 100644 index 0000000..e2bbe32 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierAmountSummary.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Amount conversion summary for the ramp + */ +export type RampStaticIdentifierAmountSummary = { + fromAmount: string; + fromCurrency: string; + toAmount: string; + toCurrency: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierEvent.ts b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierEvent.ts new file mode 100644 index 0000000..499c9da --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Events emitted by RampStaticIdentifierScreen + */ +export type RampStaticIdentifierEvent = { + "type": "onDone"; + "payload": Record; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierPreviewItem.ts b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierPreviewItem.ts new file mode 100644 index 0000000..439c699 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierPreviewItem.ts @@ -0,0 +1,18 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampStaticIdentifierPreviewItemSize } from "./RampStaticIdentifierPreviewItemSize"; + +/** + * Individual preview item for network identifier display + */ +export type RampStaticIdentifierPreviewItem = { + /** + * Key identifying the type (e.g., "accountnumber", "qrcode") + */ + identifier: string; + label: string; + showLabel: boolean; + value: string; + size: RampStaticIdentifierPreviewItemSize; + showCopy: boolean | null; + copiedLabel: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierPreviewItemSize.ts b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierPreviewItemSize.ts new file mode 100644 index 0000000..5eb94db --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierPreviewItemSize.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Size options for identifier preview items + */ +export type RampStaticIdentifierPreviewItemSize = "md" | "lg"; diff --git a/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierViewModel.ts new file mode 100644 index 0000000..3766831 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampStaticIdentifierViewModel.ts @@ -0,0 +1,14 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RampStaticIdentifierAmountSummary } from "./RampStaticIdentifierAmountSummary"; +import type { RampStaticIdentifierPreviewItem } from "./RampStaticIdentifierPreviewItem"; + +/** + * ViewModel for RampStaticIdentifierScreen + */ +export type RampStaticIdentifierViewModel = { + headingLines: Array; + identifierPreviewItems: Array | null; + amountSummary: RampStaticIdentifierAmountSummary | null; + minimumSourceAmountMessage: string | null; + doneLabel: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampStatus.ts b/app/packages/payy/src/ts-rs-bindings/RampStatus.ts new file mode 100644 index 0000000..cabc4f7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampStatus.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampStatus = + | "PENDING" + | "COMPLETE" + | "CANCELLED" + | "REFUNDED" + | "FUNDED" + | "WITHDRAW"; diff --git a/app/packages/payy/src/ts-rs-bindings/RampTransactionBase.ts b/app/packages/payy/src/ts-rs-bindings/RampTransactionBase.ts new file mode 100644 index 0000000..453529f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampTransactionBase.ts @@ -0,0 +1,22 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Currency } from "./Currency"; +import type { Element } from "./Element"; +import type { Network } from "./Network"; +import type { NetworkIdentifier } from "./NetworkIdentifier"; +import type { Provider } from "./Provider"; + +export type RampTransactionBase = { + id: string; + account_id: string; + provider: Provider; + from_currency: Currency; + from_amount: Element; + from_network: Network; + from_network_identifier: NetworkIdentifier | null; + to_currency: Currency; + to_amount: Element; + to_network: Network; + to_network_identifier: NetworkIdentifier | null; + updated_at: string; + added_at: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampWithdrawExternal.ts b/app/packages/payy/src/ts-rs-bindings/RampWithdrawExternal.ts new file mode 100644 index 0000000..6c931a8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampWithdrawExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampWithdrawExternal = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/RampWithdrawTransaction.ts b/app/packages/payy/src/ts-rs-bindings/RampWithdrawTransaction.ts new file mode 100644 index 0000000..525a4b9 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampWithdrawTransaction.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { RampStatus } from "./RampStatus"; + +export type RampWithdrawTransaction = { + status: RampStatus; + evm_address: string; + note_kind: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RampsTransactionStatus.ts b/app/packages/payy/src/ts-rs-bindings/RampsTransactionStatus.ts new file mode 100644 index 0000000..9e3d8b4 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RampsTransactionStatus.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RampsTransactionStatus = + | "PENDING" + | "COMPLETE" + | "CANCELLED" + | "REFUNDED" + | "DECLINED" + | "FAILED" + | "FUNDED" + | "WITHDRAW"; diff --git a/app/packages/payy/src/ts-rs-bindings/RequestAmountEvent.ts b/app/packages/payy/src/ts-rs-bindings/RequestAmountEvent.ts new file mode 100644 index 0000000..f823ed3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RequestAmountEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RequestAmountEvent = { + "type": "onValueChange"; + "payload": { value: string }; +} | { "type": "onSubmit"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/RequestAmountViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RequestAmountViewModel.ts new file mode 100644 index 0000000..7c10441 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RequestAmountViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RequestAmountViewModel = { value: string; buttonLabel: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/RequestLink.ts b/app/packages/payy/src/ts-rs-bindings/RequestLink.ts new file mode 100644 index 0000000..05378f1 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RequestLink.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +/** + * Request links generated by the v1 format `/r/1//#/`. + */ +export type RequestLink = { + value: Element; + public_key: Element; + invite_code: string | null; + memo: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RequestQREvent.ts b/app/packages/payy/src/ts-rs-bindings/RequestQREvent.ts new file mode 100644 index 0000000..db57124 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RequestQREvent.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RequestQREvent = never; diff --git a/app/packages/payy/src/ts-rs-bindings/RequestQRViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RequestQRViewModel.ts new file mode 100644 index 0000000..ab49527 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RequestQRViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RequestQRViewModel = { requestLink: string | null }; diff --git a/app/packages/payy/src/ts-rs-bindings/RequestShareEvent.ts b/app/packages/payy/src/ts-rs-bindings/RequestShareEvent.ts new file mode 100644 index 0000000..06305fd --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RequestShareEvent.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RequestShareEvent = + | { "type": "onPressLinkedDone"; "payload": Record } + | { "type": "onPressQr"; "payload": Record } + | { "type": "onPressLink"; "payload": Record } + | { "type": "onMemoChange"; "payload": { memo: string } } + | { "type": "onMemoErrorChange"; "payload": { hasError: boolean } }; diff --git a/app/packages/payy/src/ts-rs-bindings/RequestShareViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RequestShareViewModel.ts new file mode 100644 index 0000000..7128f4d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RequestShareViewModel.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RequestShareViewModel = { + /** + * The payment amount value as a string (bigint serialization) + */ + value: string | null; + memoLabel: string; + sharedLabel: string; + containerSpacing: number; + buttonContainerHeight: number; + shareButtonsDisabled: boolean; + shared: boolean; + disableMemo: boolean; + showNoAmountSpecifiedForZeroValue: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RetryActivityInput.ts b/app/packages/payy/src/ts-rs-bindings/RetryActivityInput.ts new file mode 100644 index 0000000..d1ffc27 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RetryActivityInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RetryActivityInput = { id: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/RewardsCodeEvent.ts b/app/packages/payy/src/ts-rs-bindings/RewardsCodeEvent.ts new file mode 100644 index 0000000..6015066 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RewardsCodeEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RewardsCodeEvent = + | { "type": "onChange"; "payload": { code: string } } + | { "type": "onSubmit"; "payload": Record } + | { "type": "onPaste"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/RewardsCodeViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RewardsCodeViewModel.ts new file mode 100644 index 0000000..263c1a3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RewardsCodeViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RewardsCodeViewModel = { + value: string; + submitting: boolean; + errorMessage: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RewardsEvent.ts b/app/packages/payy/src/ts-rs-bindings/RewardsEvent.ts new file mode 100644 index 0000000..658f7cf --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RewardsEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RewardsEvent = { + "type": "onTaskAction"; + "payload": { taskId: string }; +} | { "type": "onTaskDepositMore"; "payload": { taskId: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/RewardsTaskViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RewardsTaskViewModel.ts new file mode 100644 index 0000000..f997345 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RewardsTaskViewModel.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type RewardsTaskViewModel = { + id: string; + title: string; + desc: string | null; + points: string; + pointsLabel: string; + earned: string | null; + earnedLabel: string | null; + btnTitle: string | null; + persisted: boolean | null; + disabled: boolean | null; + depositMore: boolean | null; + hasAction: boolean; + hasDepositMoreAction: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/RewardsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/RewardsViewModel.ts new file mode 100644 index 0000000..b2eaa89 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/RewardsViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { RewardsTaskViewModel } from "./RewardsTaskViewModel"; + +export type RewardsViewModel = { + loading: boolean; + totalPoints: number; + tasks: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/Role.ts b/app/packages/payy/src/ts-rs-bindings/Role.ts new file mode 100644 index 0000000..a18d5e6 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Role.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Role = "USER" | "AGENT"; diff --git a/app/packages/payy/src/ts-rs-bindings/SelectTokenEvent.ts b/app/packages/payy/src/ts-rs-bindings/SelectTokenEvent.ts new file mode 100644 index 0000000..1be3c60 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SelectTokenEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SelectTokenId } from "./SelectTokenId"; + +export type SelectTokenEvent = { + "type": "onTokenPress"; + "payload": { tokenId: SelectTokenId }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SelectTokenId.ts b/app/packages/payy/src/ts-rs-bindings/SelectTokenId.ts new file mode 100644 index 0000000..f84845b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SelectTokenId.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SelectTokenId = "USDC" | "USDT" | "USDC.e"; diff --git a/app/packages/payy/src/ts-rs-bindings/SelectTokenOptionViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SelectTokenOptionViewModel.ts new file mode 100644 index 0000000..adab9af --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SelectTokenOptionViewModel.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SelectTokenId } from "./SelectTokenId"; + +export type SelectTokenOptionViewModel = { id: SelectTokenId; label: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/SelectTokenViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SelectTokenViewModel.ts new file mode 100644 index 0000000..eb6f1b9 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SelectTokenViewModel.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SelectTokenOptionViewModel } from "./SelectTokenOptionViewModel"; + +export type SelectTokenViewModel = { + heading: string; + tokens: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SendAmountEvent.ts b/app/packages/payy/src/ts-rs-bindings/SendAmountEvent.ts new file mode 100644 index 0000000..4a4869b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendAmountEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Event variants for send amount screen actions. + */ +export type SendAmountEvent = { + "type": "onValueChange"; + "payload": { value: string }; +} | { "type": "onNext"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/SendAmountViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SendAmountViewModel.ts new file mode 100644 index 0000000..94d8631 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendAmountViewModel.ts @@ -0,0 +1,15 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendAmountViewModel = { + value: string; + /** + * Balance as string to support bigint serialization (null if not loaded). + */ + balance: string | null; + isBalanceVisible: boolean; + isBalanceLoading: boolean; + marginTop: number; + nextLabel: string; + nextDisabled: boolean; + showNextButton: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SendLink.ts b/app/packages/payy/src/ts-rs-bindings/SendLink.ts new file mode 100644 index 0000000..1445231 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendLink.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SendLinkHash } from "./SendLinkHash"; + +/** + * Convenience enum for send-only link parsing operations. + */ +export type SendLink = { "kind": "send" } & SendLinkHash; diff --git a/app/packages/payy/src/ts-rs-bindings/SendLinkExternal.ts b/app/packages/payy/src/ts-rs-bindings/SendLinkExternal.ts new file mode 100644 index 0000000..24dfc20 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendLinkExternal.ts @@ -0,0 +1,17 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { LinkStatusExternal } from "./LinkStatusExternal"; + +export type SendLinkExternal = { + /** + * Link string + */ + link: string; + /** + * Link status + */ + link_status: LinkStatusExternal; + /** + * Memo (optional) + */ + memo: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SendLinkHash.ts b/app/packages/payy/src/ts-rs-bindings/SendLinkHash.ts new file mode 100644 index 0000000..a525499 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendLinkHash.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * `/s/#` links containing a base58-encoded payload. + */ +export type SendLinkHash = { secret_hash: string; memo: string | null }; diff --git a/app/packages/payy/src/ts-rs-bindings/SendLinkInput.ts b/app/packages/payy/src/ts-rs-bindings/SendLinkInput.ts new file mode 100644 index 0000000..2b7051a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendLinkInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendLinkInput = { value: string; memo?: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/SendLinkOutput.ts b/app/packages/payy/src/ts-rs-bindings/SendLinkOutput.ts new file mode 100644 index 0000000..4daf2a3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendLinkOutput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendLinkOutput = { id: string; link: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/SendQREvent.ts b/app/packages/payy/src/ts-rs-bindings/SendQREvent.ts new file mode 100644 index 0000000..0e425e6 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendQREvent.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Empty event enum for standardized screen contract. + * This screen has no user interactions, but we include the enum + * to maintain consistency with other screens. + */ +export type SendQREvent = never; diff --git a/app/packages/payy/src/ts-rs-bindings/SendQRViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SendQRViewModel.ts new file mode 100644 index 0000000..9f5a8a7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendQRViewModel.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendQRViewModel = { url: string; message: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/SendRegistryExternal.ts b/app/packages/payy/src/ts-rs-bindings/SendRegistryExternal.ts new file mode 100644 index 0000000..3d91ea7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendRegistryExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendRegistryExternal = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/SendRegistryInput.ts b/app/packages/payy/src/ts-rs-bindings/SendRegistryInput.ts new file mode 100644 index 0000000..6427189 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendRegistryInput.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type SendRegistryInput = { + value: Element; + memo?: string | null; + to_public_key: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SendRegistryOutput.ts b/app/packages/payy/src/ts-rs-bindings/SendRegistryOutput.ts new file mode 100644 index 0000000..744af9a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendRegistryOutput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendRegistryOutput = { id: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/SendShareEvent.ts b/app/packages/payy/src/ts-rs-bindings/SendShareEvent.ts new file mode 100644 index 0000000..6f31148 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendShareEvent.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendShareEvent = + | { "type": "onCloseShareWarning"; "payload": Record } + | { "type": "onPressDone"; "payload": Record } + | { "type": "onPressShareAgain"; "payload": Record } + | { "type": "onPressQr"; "payload": Record } + | { "type": "onPressLink"; "payload": Record } + | { "type": "onMemoChange"; "payload": { memo: string } } + | { "type": "onMemoErrorChange"; "payload": { hasError: boolean } }; diff --git a/app/packages/payy/src/ts-rs-bindings/SendShareViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SendShareViewModel.ts new file mode 100644 index 0000000..62ca278 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SendShareViewModel.ts @@ -0,0 +1,21 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SendShareViewModel = { + /** + * The payment amount value as a string (bigint serialization) + */ + value: string; + memoLabel: string; + shareAgainLabel: string; + doneLabel: string; + loadingLabel: string | null; + shareButtonsDisabled: boolean; + shareLoading: boolean; + shareResultReady: boolean; + shareAgainVisible: boolean; + shareAgainDisabled: boolean | null; + showShareWarning: boolean; + shareWarningMessages: Array; + disableMemo: boolean | null; + showNoAmountSpecifiedForZeroValue: boolean | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SettingsScreenEvent.ts b/app/packages/payy/src/ts-rs-bindings/SettingsScreenEvent.ts new file mode 100644 index 0000000..75c1910 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SettingsScreenEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SettingsScreenItemKey } from "./SettingsScreenItemKey"; + +export type SettingsScreenEvent = { + "type": "onItemPress"; + "payload": { key: SettingsScreenItemKey }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SettingsScreenItem.ts b/app/packages/payy/src/ts-rs-bindings/SettingsScreenItem.ts new file mode 100644 index 0000000..048f216 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SettingsScreenItem.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SettingsScreenItemKey } from "./SettingsScreenItemKey"; + +export type SettingsScreenItem = { + key: SettingsScreenItemKey; + title: string; + secondary: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SettingsScreenItemKey.ts b/app/packages/payy/src/ts-rs-bindings/SettingsScreenItemKey.ts new file mode 100644 index 0000000..19443f8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SettingsScreenItemKey.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SettingsScreenItemKey = + | "backup" + | "recoverWallet" + | "advanced" + | "stickers" + | "faq" + | "community" + | "help"; diff --git a/app/packages/payy/src/ts-rs-bindings/SettingsScreenViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SettingsScreenViewModel.ts new file mode 100644 index 0000000..133e5c3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SettingsScreenViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SettingsScreenItem } from "./SettingsScreenItem"; + +export type SettingsScreenViewModel = { + items: Array; + showVersion: boolean; + versionLabel: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SignInput.ts b/app/packages/payy/src/ts-rs-bindings/SignInput.ts new file mode 100644 index 0000000..6e3c6a5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SignInput.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SignInput = { pk: string }; diff --git a/app/packages/payy/src/ts-rs-bindings/SignedElement.ts b/app/packages/payy/src/ts-rs-bindings/SignedElement.ts new file mode 100644 index 0000000..7f1d5d9 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SignedElement.ts @@ -0,0 +1,19 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +/** + * A signed 256-bit integer that wraps an `Element` with a sign bit + * + * This type allows performing arithmetic operations with signed numbers, + * while the underlying `Element` remains unsigned. + */ +export type SignedElement = { + /** + * The absolute value stored as an Element + */ + value: Element; + /** + * The sign: true for negative, false for positive or zero + */ + negative: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SnarkWitness.ts b/app/packages/payy/src/ts-rs-bindings/SnarkWitness.ts new file mode 100644 index 0000000..e9bb3c7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SnarkWitness.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SnarkWitnessV1 } from "./SnarkWitnessV1"; + +export type SnarkWitness = { V1: SnarkWitnessV1 }; diff --git a/app/packages/payy/src/ts-rs-bindings/SnarkWitnessV1.ts b/app/packages/payy/src/ts-rs-bindings/SnarkWitnessV1.ts new file mode 100644 index 0000000..6976141 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SnarkWitnessV1.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type SnarkWitnessV1 = { + proof: string; + instances: Array>; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/Status.ts b/app/packages/payy/src/ts-rs-bindings/Status.ts new file mode 100644 index 0000000..c60a35b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/Status.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type Status = "OPEN" | "CLOSED" | "ON_HOLD"; diff --git a/app/packages/payy/src/ts-rs-bindings/StoredNote.ts b/app/packages/payy/src/ts-rs-bindings/StoredNote.ts new file mode 100644 index 0000000..5dd4bbc --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/StoredNote.ts @@ -0,0 +1,15 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; +import type { WalletDataNote } from "./WalletDataNote"; + +export type StoredNote = { + note: WalletDataNote; + commitment: Element; + timestamp?: number; + received?: number; + spent?: number; + owner?: Element; + remote?: boolean; + private_key?: Element; + invalidreason?: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportChatAttachment.ts b/app/packages/payy/src/ts-rs-bindings/SupportChatAttachment.ts new file mode 100644 index 0000000..2dfcfd7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportChatAttachment.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SupportChatAttachment = { + filename: string; + contentType: string; + width: number | null; + height: number | null; + /** + * Base64 content only for inline/local attachments. + */ + content: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportChatDraftAttachment.ts b/app/packages/payy/src/ts-rs-bindings/SupportChatDraftAttachment.ts new file mode 100644 index 0000000..2036f19 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportChatDraftAttachment.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SupportChatDraftAttachment = { + uri: string; + filename: string; + contentType: string; + width: number | null; + height: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportChatEvent.ts b/app/packages/payy/src/ts-rs-bindings/SupportChatEvent.ts new file mode 100644 index 0000000..85a1356 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportChatEvent.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SupportChatEvent = + | { "type": "onMessageChange"; "payload": { value: string } } + | { "type": "onSend"; "payload": Record } + | { "type": "onAddAttachmentPress"; "payload": Record } + | { "type": "onLinkPress"; "payload": { url: string } } + | { "type": "onNotificationToggle"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportChatMessageItem.ts b/app/packages/payy/src/ts-rs-bindings/SupportChatMessageItem.ts new file mode 100644 index 0000000..c4ebe39 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportChatMessageItem.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Role } from "./Role"; +import type { SupportChatAttachment } from "./SupportChatAttachment"; + +export type SupportChatMessageItem = { + id: string; + role: Role; + isBot: boolean; + message: string; + attachment: SupportChatAttachment | null; + localOnly: boolean; + addedAt: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportChatNotificationBanner.ts b/app/packages/payy/src/ts-rs-bindings/SupportChatNotificationBanner.ts new file mode 100644 index 0000000..04f9bc5 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportChatNotificationBanner.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SupportChatNotificationBanner = { + text: string; + additionalText: string; + isEnabled: boolean; + shouldShow: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportChatViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SupportChatViewModel.ts new file mode 100644 index 0000000..657e9c9 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportChatViewModel.ts @@ -0,0 +1,14 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SupportChatDraftAttachment } from "./SupportChatDraftAttachment"; +import type { SupportChatMessageItem } from "./SupportChatMessageItem"; +import type { SupportChatNotificationBanner } from "./SupportChatNotificationBanner"; + +export type SupportChatViewModel = { + messages: Array; + updateDisabled: boolean; + message: string; + draftAttachment: SupportChatDraftAttachment | null; + isSending: boolean; + isSendDisabled: boolean; + notificationBanner: SupportChatNotificationBanner | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportExternal.ts b/app/packages/payy/src/ts-rs-bindings/SupportExternal.ts new file mode 100644 index 0000000..ffc6ded --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportExternal.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SupportExternal = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportIssue.ts b/app/packages/payy/src/ts-rs-bindings/SupportIssue.ts new file mode 100644 index 0000000..a734cd3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportIssue.ts @@ -0,0 +1,22 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Status } from "./Status"; + +export type SupportIssue = { + id: string; + wallet_id: string; + external_id: string; + status: Status; + channel: string; + subject: string | null; + unread_count: number; + last_message: string; + last_message_at: string; + last_read_at: string | null; + closed_at: string | null; + updated_at: string; + added_at: string; + metadata: unknown | null; + auto_close_at: string | null; + auto_close_minutes: number | null; + last_ai_support_bot_processed_at: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportIssuesListEvent.ts b/app/packages/payy/src/ts-rs-bindings/SupportIssuesListEvent.ts new file mode 100644 index 0000000..4391a15 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportIssuesListEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type SupportIssuesListEvent = + | { "type": "onRefresh"; "payload": Record } + | { "type": "onNewChat"; "payload": Record } + | { "type": "onNewChatDisabledPress"; "payload": Record } + | { "type": "onOpenIssue"; "payload": { issueId: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportIssuesListViewModel.ts b/app/packages/payy/src/ts-rs-bindings/SupportIssuesListViewModel.ts new file mode 100644 index 0000000..16e79cb --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportIssuesListViewModel.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { SupportIssue } from "./SupportIssue"; + +export type SupportIssuesListViewModel = { + issues: Array; + showLoader: boolean; + remoteHasLoaded: boolean; + isNewChatDisabled: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/SupportMessage.ts b/app/packages/payy/src/ts-rs-bindings/SupportMessage.ts new file mode 100644 index 0000000..ee908e6 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/SupportMessage.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Role } from "./Role"; + +export type SupportMessage = { + id: string; + support_issue_id: string; + external_id: string; + emoji: string | null; + role: Role; + message: string; + attachment: {}; + added_at: string; + is_bot: boolean; + is_internal: boolean; + agent_id: number | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/TermsEvent.ts b/app/packages/payy/src/ts-rs-bindings/TermsEvent.ts new file mode 100644 index 0000000..6a114ab --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/TermsEvent.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type TermsEvent = { "type": "onOpenLink"; "payload": { link: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/TermsLinkItem.ts b/app/packages/payy/src/ts-rs-bindings/TermsLinkItem.ts new file mode 100644 index 0000000..1e6dfb2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/TermsLinkItem.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type TermsLinkItem = { + title: string; + link: string; + countries: Array | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/TermsViewModel.ts b/app/packages/payy/src/ts-rs-bindings/TermsViewModel.ts new file mode 100644 index 0000000..7d6f669 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/TermsViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ProviderTermsGroup } from "./ProviderTermsGroup"; +import type { TermsLinkItem } from "./TermsLinkItem"; + +export type TermsViewModel = { + providerTerms: Array; + appTerms: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/TransactionRequest.ts b/app/packages/payy/src/ts-rs-bindings/TransactionRequest.ts new file mode 100644 index 0000000..8dfc177 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/TransactionRequest.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { UtxoProof } from "./UtxoProof"; + +/** + * Request for submit transaction + */ +export type TransactionRequest = { + /** + * Utxo proof to be verified and applied + */ + proof: UtxoProof; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/TransactionResponse.ts b/app/packages/payy/src/ts-rs-bindings/TransactionResponse.ts new file mode 100644 index 0000000..badf4b3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/TransactionResponse.ts @@ -0,0 +1,21 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockHeight } from "./BlockHeight"; +import type { Element } from "./Element"; + +/** + * Response for submit transaction + */ +export type TransactionResponse = { + /** + * Height of the block the transaction was included in + */ + height: BlockHeight; + /** + * Root hash of the merkle tree for the block + */ + root_hash: Element; + /** + * Transaction hash of submitted transaction + */ + txn_hash: Element; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/TransferOutput.ts b/app/packages/payy/src/ts-rs-bindings/TransferOutput.ts new file mode 100644 index 0000000..026707f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/TransferOutput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { UtxoProof } from "./UtxoProof"; + +export type TransferOutput = { utxo_proof: UtxoProof }; diff --git a/app/packages/payy/src/ts-rs-bindings/TxnWithInfo.ts b/app/packages/payy/src/ts-rs-bindings/TxnWithInfo.ts new file mode 100644 index 0000000..4298df0 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/TxnWithInfo.ts @@ -0,0 +1,30 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { BlockHeight } from "./BlockHeight"; +import type { Element } from "./Element"; +import type { UtxoProof } from "./UtxoProof"; + +/** + * Transaction data with additional metadata. + */ +export type TxnWithInfo = { + /** + * Transaction proof. + */ + proof: UtxoProof; + /** + * Hash of the transaction. + */ + hash: Element; + /** + * Index of the transaction inside the block. + */ + index_in_block: bigint; + /** + * Height of the block that included the transaction. + */ + block_height: BlockHeight; + /** + * Timestamp assigned to the transaction. + */ + time: bigint; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/UnclaimedBalanceOutput.ts b/app/packages/payy/src/ts-rs-bindings/UnclaimedBalanceOutput.ts new file mode 100644 index 0000000..2acfb86 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/UnclaimedBalanceOutput.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type UnclaimedBalanceOutput = { value: Element }; diff --git a/app/packages/payy/src/ts-rs-bindings/UtxoKind.ts b/app/packages/payy/src/ts-rs-bindings/UtxoKind.ts new file mode 100644 index 0000000..ca1a344 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/UtxoKind.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * The kind of Utxo transaction + */ +export type UtxoKind = "NULL" | "SEND" | "MINT" | "BURN"; diff --git a/app/packages/payy/src/ts-rs-bindings/UtxoProof.ts b/app/packages/payy/src/ts-rs-bindings/UtxoProof.ts new file mode 100644 index 0000000..cd05daa --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/UtxoProof.ts @@ -0,0 +1,16 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { UtxoPublicInput } from "./UtxoPublicInput"; + +/** + * The output proof for a Utxo transaction + */ +export type UtxoProof = { + /** + * The proof for the Utxo transaction + */ + proof: string; + /** + * The public input for the Utxo transaction + */ + public_inputs: UtxoPublicInput; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/UtxoPublicInput.ts b/app/packages/payy/src/ts-rs-bindings/UtxoPublicInput.ts new file mode 100644 index 0000000..eca52a7 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/UtxoPublicInput.ts @@ -0,0 +1,19 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * The public input for a Utxo transaction + */ +export type UtxoPublicInput = { + /** + * The input commitments + */ + input_commitments: [string, string]; + /** + * The output commitments + */ + output_commitments: [string, string]; + /** + * The message of the transaction + */ + messages: [string, string, string, string, string]; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/VerifyCodeEvent.ts b/app/packages/payy/src/ts-rs-bindings/VerifyCodeEvent.ts new file mode 100644 index 0000000..5133ab8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/VerifyCodeEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type VerifyCodeEvent = + | { "type": "onSubmit"; "payload": { code: string } } + | { "type": "onResend"; "payload": Record } + | { "type": "onEditPhone"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/VerifyCodeViewModel.ts b/app/packages/payy/src/ts-rs-bindings/VerifyCodeViewModel.ts new file mode 100644 index 0000000..038beb8 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/VerifyCodeViewModel.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type VerifyCodeViewModel = { phoneNumber: string; kycState: KycState }; diff --git a/app/packages/payy/src/ts-rs-bindings/VerifyEmailEvent.ts b/app/packages/payy/src/ts-rs-bindings/VerifyEmailEvent.ts new file mode 100644 index 0000000..aed08e0 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/VerifyEmailEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type VerifyEmailEvent = { + "type": "onSubmit"; + "payload": { email: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/VerifyEmailViewModel.ts b/app/packages/payy/src/ts-rs-bindings/VerifyEmailViewModel.ts new file mode 100644 index 0000000..01db97a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/VerifyEmailViewModel.ts @@ -0,0 +1,4 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type VerifyEmailViewModel = { initialValue: string; kycState: KycState }; diff --git a/app/packages/payy/src/ts-rs-bindings/VerifyPhoneEvent.ts b/app/packages/payy/src/ts-rs-bindings/VerifyPhoneEvent.ts new file mode 100644 index 0000000..13e459d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/VerifyPhoneEvent.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type VerifyPhoneEvent = { + "type": "onSubmit"; + "payload": { phone: string }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/VerifyPhoneViewModel.ts b/app/packages/payy/src/ts-rs-bindings/VerifyPhoneViewModel.ts new file mode 100644 index 0000000..951c97f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/VerifyPhoneViewModel.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycState } from "./KycState"; + +export type VerifyPhoneViewModel = { + initialValue: string; + isPrefilled: boolean; + kycState: KycState; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletBackupEvent.ts b/app/packages/payy/src/ts-rs-bindings/WalletBackupEvent.ts new file mode 100644 index 0000000..5831818 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletBackupEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Events emitted by the WalletBackupScreen + */ +export type WalletBackupEvent = { + "type": "onDownloadRecoveryPhrase"; + "payload": Record; +} | { "type": "onGuardianBackupPress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletBackupViewModel.ts b/app/packages/payy/src/ts-rs-bindings/WalletBackupViewModel.ts new file mode 100644 index 0000000..be1c362 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletBackupViewModel.ts @@ -0,0 +1,20 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * ViewModel for the WalletBackupScreen + */ +export type WalletBackupViewModel = { + backupWarning: boolean; + hasTappedDownloadRecoveryPhrase: boolean; + isGuardianBackupEnabled: boolean; + backupDescription: string; + backupSecondaryDescription: string; + optionsTitle: string; + seedPhraseWarning: string; + seedPhraseOptionHeading: string; + seedPhraseOptionDescription: string; + socialRecoveryHeading: string; + socialRecoveryDescription: string; + systemBackupHeading: string; + systemBackupDescription: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletCardBanner.ts b/app/packages/payy/src/ts-rs-bindings/WalletCardBanner.ts new file mode 100644 index 0000000..787604a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletCardBanner.ts @@ -0,0 +1,20 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { KycStatus } from "./KycStatus"; + +export type WalletCardBanner = + | { "type": "none"; "payload": Record } + | { "type": "promo"; "payload": { title: string; subtitle: string } } + | { + "type": "countdown"; + "payload": { + status: KycStatus; + /** + * Unix epoch timestamp in milliseconds (JS Date.now() compatible). + */ + addedAt: number; + showCountdown: boolean; + }; + } + | { "type": "pending"; "payload": Record } + | { "type": "active"; "payload": { last4: string } } + | { "type": "frozen"; "payload": { last4: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletDataNote.ts b/app/packages/payy/src/ts-rs-bindings/WalletDataNote.ts new file mode 100644 index 0000000..91517ba --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletDataNote.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +export type WalletDataNote = { + address: Element; + psi: Element; + value: Element; + source: Element | null; + token: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletEvent.ts b/app/packages/payy/src/ts-rs-bindings/WalletEvent.ts new file mode 100644 index 0000000..a36ecd3 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletEvent.ts @@ -0,0 +1,10 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type WalletEvent = + | { "type": "onToggleBalance"; "payload": Record } + | { "type": "onPendingDepositPress"; "payload": Record } + | { "type": "onUnclaimedPress"; "payload": Record } + | { "type": "onBackupPress"; "payload": Record } + | { "type": "onSendPress"; "payload": Record } + | { "type": "onRequestPress"; "payload": Record } + | { "type": "onCardBannerPress"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletMobileConfig.ts b/app/packages/payy/src/ts-rs-bindings/WalletMobileConfig.ts new file mode 100644 index 0000000..1bed50a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletMobileConfig.ts @@ -0,0 +1,13 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ChainConfig } from "./ChainConfig"; + +export type WalletMobileConfig = { + guild_rpc_url: string; + node_rpc_url: string; + social_recovery_contract_address: string; + primary_rollup_chain_id: number; + minimum_gas_price_gwei: bigint | null; + dev: boolean; + data_dir?: string; + chains: { [key in number]?: ChainConfig }; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletMobileMigrateInput.ts b/app/packages/payy/src/ts-rs-bindings/WalletMobileMigrateInput.ts new file mode 100644 index 0000000..7905a06 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletMobileMigrateInput.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { MigrateInputNote } from "./MigrateInputNote"; + +export type WalletMobileMigrateInput = { + migration_id: string | null; + old_wallet_state?: string; + notes?: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletNote.ts b/app/packages/payy/src/ts-rs-bindings/WalletNote.ts new file mode 100644 index 0000000..9c9b109 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletNote.ts @@ -0,0 +1,15 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Note } from "./Note"; +import type { WalletPrivateKeyKind } from "./WalletPrivateKeyKind"; + +/** + * For the wallet, we use a wrapper struct around Note, as this may be + * serialized and stored and we don't want to store the private key. The private key + * may be derived differntly depending on how its generated. + */ +export type WalletNote = { + note: Note; + private_key: WalletPrivateKeyKind; + added_at: string; + updated_at: string; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletNoteSet.ts b/app/packages/payy/src/ts-rs-bindings/WalletNoteSet.ts new file mode 100644 index 0000000..54b5093 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletNoteSet.ts @@ -0,0 +1,8 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WalletNote } from "./WalletNote"; + +/** + * A set of notes, prevents duplicats from being added. Similar to a Vec but the order + * of notes in the set is not guarenteed. + */ +export type WalletNoteSet = Array; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletPrivateKeyKind.ts b/app/packages/payy/src/ts-rs-bindings/WalletPrivateKeyKind.ts new file mode 100644 index 0000000..98a24d2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletPrivateKeyKind.ts @@ -0,0 +1,12 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { Element } from "./Element"; + +/** + * The kind of private key used for the note + */ +export type WalletPrivateKeyKind = + | { "kind": "PROVIDED"; "data": Element } + | { "kind": "WALLET" } + | { "kind": "DERIVED"; "data": Array } + | { "kind": "PADDING" } + | { "kind": "EXTERNAL_NO_PRIVATE_KEY" }; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletRecoveryEvent.ts b/app/packages/payy/src/ts-rs-bindings/WalletRecoveryEvent.ts new file mode 100644 index 0000000..08aed6f --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletRecoveryEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Events emitted by the WalletRecoveryScreen + */ +export type WalletRecoveryEvent = { + "type": "onMnemonicChange"; + "payload": { value: string }; +} | { "type": "onRecover"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletRecoveryViewModel.ts b/app/packages/payy/src/ts-rs-bindings/WalletRecoveryViewModel.ts new file mode 100644 index 0000000..c5297d2 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletRecoveryViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * ViewModel for the WalletRecoveryScreen + */ +export type WalletRecoveryViewModel = { + mnemonic: string; + recovering: boolean; + errorMessage: string | null; + balanceNotice: string | null; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletV0External.ts b/app/packages/payy/src/ts-rs-bindings/WalletV0External.ts new file mode 100644 index 0000000..e52971d --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletV0External.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type WalletV0External = Record; diff --git a/app/packages/payy/src/ts-rs-bindings/WalletViewModel.ts b/app/packages/payy/src/ts-rs-bindings/WalletViewModel.ts new file mode 100644 index 0000000..705d62b --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WalletViewModel.ts @@ -0,0 +1,18 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { LoadingResult } from "./LoadingResult"; +import type { WalletCardBanner } from "./WalletCardBanner"; + +export type WalletViewModel = { + isBalanceVisible: boolean; + showMigrationMessage: boolean; + showBackupCallout: boolean; + backupTitle: string; + /** + * Balance as LoadingResult with optional atomic micro-unit amount as decimal string (bigint-safe in TS). + * None represents unknown/uninitialized balance, preserving Send/Deposit label semantics. + */ + balance: LoadingResult; + depositPendingBalance: LoadingResult; + unclaimedLinksBalance: LoadingResult; + cardBanner: WalletCardBanner; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WithdrawEvent.ts b/app/packages/payy/src/ts-rs-bindings/WithdrawEvent.ts new file mode 100644 index 0000000..bdbd3db --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WithdrawEvent.ts @@ -0,0 +1,9 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +/** + * Event variants for withdraw screen actions + */ +export type WithdrawEvent = { + "type": "onBankTransferPress"; + "payload": Record; +} | { "type": "onCryptoPress"; "payload": { chainKey: string } }; diff --git a/app/packages/payy/src/ts-rs-bindings/WithdrawOptionGroupViewModel.ts b/app/packages/payy/src/ts-rs-bindings/WithdrawOptionGroupViewModel.ts new file mode 100644 index 0000000..a3c6020 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WithdrawOptionGroupViewModel.ts @@ -0,0 +1,11 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WithdrawOptionItemViewModel } from "./WithdrawOptionItemViewModel"; + +/** + * Group of withdraw options + */ +export type WithdrawOptionGroupViewModel = { + title: string; + subtitle: string | null; + options: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WithdrawOptionItemViewModel.ts b/app/packages/payy/src/ts-rs-bindings/WithdrawOptionItemViewModel.ts new file mode 100644 index 0000000..1ab4b71 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WithdrawOptionItemViewModel.ts @@ -0,0 +1,15 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WithdrawEvent } from "./WithdrawEvent"; + +/** + * Individual withdraw option item (without callbacks or non-serializable types) + * Note: Only include enabled/visible options in the ViewModel - disabled options are hidden, not shown disabled + * Each option embeds its event directly for type-safe dispatch + */ +export type WithdrawOptionItemViewModel = { + title: string; + description: string | null; + iconId: string; + comingSoon: boolean; + event: WithdrawEvent; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WithdrawViewModel.ts b/app/packages/payy/src/ts-rs-bindings/WithdrawViewModel.ts new file mode 100644 index 0000000..4609b45 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WithdrawViewModel.ts @@ -0,0 +1,6 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { WithdrawOptionGroupViewModel } from "./WithdrawOptionGroupViewModel"; + +export type WithdrawViewModel = { + optionGroups: Array; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WithdrawWalletEvent.ts b/app/packages/payy/src/ts-rs-bindings/WithdrawWalletEvent.ts new file mode 100644 index 0000000..504235a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WithdrawWalletEvent.ts @@ -0,0 +1,7 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type WithdrawWalletEvent = + | { "type": "onAddressChange"; "payload": { value: string } } + | { "type": "onPasteAddress"; "payload": Record } + | { "type": "onAmountChange"; "payload": { value: string } } + | { "type": "onSubmit"; "payload": Record }; diff --git a/app/packages/payy/src/ts-rs-bindings/WithdrawWalletViewModel.ts b/app/packages/payy/src/ts-rs-bindings/WithdrawWalletViewModel.ts new file mode 100644 index 0000000..d2def5a --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WithdrawWalletViewModel.ts @@ -0,0 +1,19 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type WithdrawWalletViewModel = { + chainKey: string; + chainName: string; + chainIconFallbackUri: string | null; + showMainChainEta: boolean; + address: string; + amount: string; + shouldShowBalanceRemaining: boolean; + balanceDiff: string; + balanceOverLimit: boolean; + isBalanceVisible: boolean; + isBalanceLoading: boolean; + submitButtonVisible: boolean; + submitButtonEnabled: boolean; + submitAmountLabel: string | null; + isFormValid: boolean; +}; diff --git a/app/packages/payy/src/ts-rs-bindings/WorkerStatus.ts b/app/packages/payy/src/ts-rs-bindings/WorkerStatus.ts new file mode 100644 index 0000000..14ce267 --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/WorkerStatus.ts @@ -0,0 +1,3 @@ +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. + +export type WorkerStatus = "PENDING" | "SUCCESS" | "FAILED" | "CANCELLED"; diff --git a/app/packages/payy/src/ts-rs-bindings/tsconfig.tsrs.json b/app/packages/payy/src/ts-rs-bindings/tsconfig.tsrs.json new file mode 100644 index 0000000..30b282c --- /dev/null +++ b/app/packages/payy/src/ts-rs-bindings/tsconfig.tsrs.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true + }, + "include": ["*.ts"] +} \ No newline at end of file diff --git a/app/packages/privacy-vault/README.md b/app/packages/privacy-vault/README.md new file mode 100644 index 0000000..9b76b3d --- /dev/null +++ b/app/packages/privacy-vault/README.md @@ -0,0 +1,49 @@ +# Privacy Vault + +Frontend for the Payy Privacy Vault onboarding flow. + +## Live Site + +- Production: https://payy-privacy-vault.vercel.app + +## Features + +- Wallet authentication via EIP-712 typed signature +- Add Payy Testnet to MetaMask +- Request testnet funds from the faucet + +## Development + +```bash +# From the app/ directory +cd packages/privacy-vault + +yarn dev +``` + +## Build + +```bash +# From the app/ directory +cd packages/privacy-vault + +yarn build +``` + +## Deployment + +- Hosting: Vercel +- Team: `polybase` +- Project: `payy-privacy-vault` +- Project ID: `prj_n953NkFqyTVQqx8mQWHOvGf2yHkg` + +### CI Auto Deploy (Main) + +Deploys are automated via: + +- `.github/workflows/privacy-vault.release.mainnet.yml` + +Trigger: + +- Pushes to `main` that change `app/packages/privacy-vault/**` +- Manual `workflow_dispatch` diff --git a/app/packages/privacy-vault/index.html b/app/packages/privacy-vault/index.html new file mode 100644 index 0000000..48d6f0b --- /dev/null +++ b/app/packages/privacy-vault/index.html @@ -0,0 +1,13 @@ + + + + + + + Payy Privacy Vault + + +
+ + + diff --git a/app/packages/privacy-vault/package.json b/app/packages/privacy-vault/package.json new file mode 100644 index 0000000..8f871b5 --- /dev/null +++ b/app/packages/privacy-vault/package.json @@ -0,0 +1,30 @@ +{ + "name": "privacy-vault", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "lint": "eslint 'src/**/*.{ts,tsx}'", + "test": "echo 'No tests specified for privacy-vault'" + }, + "dependencies": { + "@tanstack/react-query": "^5.32.1", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "viem": "^2.21.0", + "wagmi": "^2.15.0" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^19.1.0", + "@types/react-dom": "^19.1.0", + "@vitejs/plugin-react": "^4.3.0", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.47", + "tailwindcss": "^3.4.12", + "typescript": "^5.9.2", + "vite": "^5.4.8" + } +} diff --git a/app/packages/privacy-vault/postcss.config.js b/app/packages/privacy-vault/postcss.config.js new file mode 100644 index 0000000..85f717c --- /dev/null +++ b/app/packages/privacy-vault/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {} + } +} diff --git a/app/packages/privacy-vault/src/App.tsx b/app/packages/privacy-vault/src/App.tsx new file mode 100644 index 0000000..6dcc9dd --- /dev/null +++ b/app/packages/privacy-vault/src/App.tsx @@ -0,0 +1,110 @@ +import { useEffect, useMemo, useState } from 'react' + +import { Layout } from './components/Layout' +import { StepCard } from './components/StepCard' +import type { StepStatus } from './components/StatusIndicator' +import { FaucetStep } from './features/faucet/FaucetStep' +import { useFaucet } from './features/faucet/useFaucet' +import { AuthStep } from './features/auth/AuthStep' +import { useWalletAuth } from './features/auth/useWalletAuth' +import { NetworkStep } from './features/network/NetworkStep' +import { useAddNetwork } from './features/network/useAddNetwork' +import { useTheme } from './hooks/useTheme' +import { IS_TESTNET } from './lib/config' + +const computeStatus = ( + isPending: boolean, + isComplete: boolean, + hasError: boolean +): StepStatus => { + if (isComplete) { + return 'complete' + } + if (isPending) { + return 'pending' + } + if (hasError) { + return 'error' + } + return 'idle' +} + +const App = () => { + useTheme() + + const auth = useWalletAuth() + const network = useAddNetwork() + const faucet = useFaucet() + + const [openStep, setOpenStep] = useState(1) + + const authStatus = auth.status + const networkStatus = network.status + + const faucetStatus = useMemo( + () => + computeStatus(faucet.isPending, faucet.isSuccess, Boolean(faucet.error)), + [faucet.error, faucet.isPending, faucet.isSuccess] + ) + + useEffect(() => { + if (authStatus === 'complete' && networkStatus !== 'complete') { + setOpenStep(2) + } + }, [authStatus, networkStatus]) + + useEffect(() => { + if ( + authStatus === 'complete' + && networkStatus === 'complete' + && faucetStatus !== 'complete' + ) { + setOpenStep(3) + } + }, [authStatus, networkStatus, faucetStatus]) + + return ( + + setOpenStep(1)} + > + + + + setOpenStep(2)} + > + + + + {IS_TESTNET && ( + setOpenStep(3)} + > + + + )} + + ) +} + +export default App diff --git a/app/packages/privacy-vault/src/assets/fonts/Steradian-Bd.otf b/app/packages/privacy-vault/src/assets/fonts/Steradian-Bd.otf new file mode 100644 index 0000000..d6f208c Binary files /dev/null and b/app/packages/privacy-vault/src/assets/fonts/Steradian-Bd.otf differ diff --git a/app/packages/privacy-vault/src/assets/fonts/Steradian-Blk.otf b/app/packages/privacy-vault/src/assets/fonts/Steradian-Blk.otf new file mode 100644 index 0000000..8eb8380 Binary files /dev/null and b/app/packages/privacy-vault/src/assets/fonts/Steradian-Blk.otf differ diff --git a/app/packages/privacy-vault/src/assets/fonts/Steradian-Md.otf b/app/packages/privacy-vault/src/assets/fonts/Steradian-Md.otf new file mode 100644 index 0000000..ac3a773 Binary files /dev/null and b/app/packages/privacy-vault/src/assets/fonts/Steradian-Md.otf differ diff --git a/app/packages/privacy-vault/src/assets/fonts/Steradian-Rg.otf b/app/packages/privacy-vault/src/assets/fonts/Steradian-Rg.otf new file mode 100644 index 0000000..3cee8e9 Binary files /dev/null and b/app/packages/privacy-vault/src/assets/fonts/Steradian-Rg.otf differ diff --git a/app/packages/privacy-vault/src/components/Button.tsx b/app/packages/privacy-vault/src/components/Button.tsx new file mode 100644 index 0000000..d333658 --- /dev/null +++ b/app/packages/privacy-vault/src/components/Button.tsx @@ -0,0 +1,31 @@ +import type { ButtonHTMLAttributes, ReactNode } from 'react' + +interface ButtonProps extends ButtonHTMLAttributes { + variant?: 'primary' | 'secondary' | 'ghost' + children: ReactNode +} + +const baseClasses = + 'inline-flex items-center justify-center rounded-full px-5 py-2 text-sm font-semibold transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-60' + +const variantClasses: Record, string> = { + primary: 'bg-primary text-black hover:brightness-105', + secondary: + 'border border-gray-800 bg-transparent text-text hover:border-primary hover:text-primary', + ghost: 'text-text/70 hover:text-text' +} + +export const Button = ({ + variant = 'primary', + className, + children, + ...props +}: ButtonProps) => ( + +) diff --git a/app/packages/privacy-vault/src/components/Layout.tsx b/app/packages/privacy-vault/src/components/Layout.tsx new file mode 100644 index 0000000..4301253 --- /dev/null +++ b/app/packages/privacy-vault/src/components/Layout.tsx @@ -0,0 +1,29 @@ +import type { ReactNode } from 'react' + +import { Logo } from './Logo' + +interface LayoutProps { + children: ReactNode +} + +export const Layout = ({ children }: LayoutProps) => ( +
+
+
+
+ +
+
+

+ Setup your Privacy Vault +

+

+ The privacy vault protects your privacy, its authenticated so that + only you can see your private balances. +

+
+
+
{children}
+
+
+) diff --git a/app/packages/privacy-vault/src/components/Logo.tsx b/app/packages/privacy-vault/src/components/Logo.tsx new file mode 100644 index 0000000..29f4fb4 --- /dev/null +++ b/app/packages/privacy-vault/src/components/Logo.tsx @@ -0,0 +1,21 @@ +import * as React from 'react' + +export interface LogoProps { + color?: string + style?: React.CSSProperties + className?: string + width?: string | number + height?: string | number + fill?: string +} + +export const Logo = (props: LogoProps) => ( + + + +) diff --git a/app/packages/privacy-vault/src/components/StatusIndicator.tsx b/app/packages/privacy-vault/src/components/StatusIndicator.tsx new file mode 100644 index 0000000..ac4da1e --- /dev/null +++ b/app/packages/privacy-vault/src/components/StatusIndicator.tsx @@ -0,0 +1,51 @@ +import type { ReactNode } from 'react' + +export type StepStatus = 'idle' | 'pending' | 'complete' | 'error' + +interface StatusIndicatorProps { + status: StepStatus + label?: string +} + +const iconMap: Record = { + idle: null, + pending: ( + + ), + complete: ( + + + + + + ), + error: ( + + + + + + ) +} + +export const StatusIndicator = ({ status, label }: StatusIndicatorProps) => ( +
+ {iconMap[status]} + {label} +
+) diff --git a/app/packages/privacy-vault/src/components/StepCard.tsx b/app/packages/privacy-vault/src/components/StepCard.tsx new file mode 100644 index 0000000..ed32852 --- /dev/null +++ b/app/packages/privacy-vault/src/components/StepCard.tsx @@ -0,0 +1,65 @@ +import type { ReactNode } from 'react' + +import { StatusIndicator, type StepStatus } from './StatusIndicator' + +interface StepCardProps { + step: number + title: string + description?: string + status: StepStatus + isOpen: boolean + onToggle: () => void + children: ReactNode +} + +const statusLabel: Record = { + idle: 'Not started', + pending: 'In progress', + complete: 'Complete', + error: 'Action needed' +} + +export const StepCard = ({ + step, + title, + description, + status, + isOpen, + onToggle, + children +}: StepCardProps) => ( +
+ +
+
+
{children}
+
+
+
+) diff --git a/app/packages/privacy-vault/src/features/auth/AuthStep.tsx b/app/packages/privacy-vault/src/features/auth/AuthStep.tsx new file mode 100644 index 0000000..dcf3fd8 --- /dev/null +++ b/app/packages/privacy-vault/src/features/auth/AuthStep.tsx @@ -0,0 +1,78 @@ +import { Button } from '../../components/Button' +import type { WalletAuthState } from './useWalletAuth' + +const shortenAddress = (address: string) => + `${address.slice(0, 6)}...${address.slice(address.length - 4)}` + +interface AuthStepProps { + auth: WalletAuthState +} + +export const AuthStep = ({ auth }: AuthStepProps) => { + const { + address, + isConnected, + isConnecting, + isSigning, + isAuthenticated, + error, + connectWallet, + authenticate, + disconnect, + resetAuth + } = auth + + return ( +
+
+

+ Wallet authentication +

+

+ We use an EIP-712 typed signature to confirm ownership of your wallet + before enabling the faucet. +

+
+ +
+ {isConnected ? ( +
+
Connected wallet
+
+ {address ? shortenAddress(address) : 'Unknown address'} +
+
+ ) : ( +
No wallet connected yet.
+ )} +
+ + {error &&
{error}
} + +
+ {!isConnected && ( + + )} + + {isConnected && !isAuthenticated && ( + + )} + + {isAuthenticated && ( + <> + + + + )} +
+
+ ) +} diff --git a/app/packages/privacy-vault/src/features/auth/useWalletAuth.ts b/app/packages/privacy-vault/src/features/auth/useWalletAuth.ts new file mode 100644 index 0000000..005bbc0 --- /dev/null +++ b/app/packages/privacy-vault/src/features/auth/useWalletAuth.ts @@ -0,0 +1,154 @@ +import { useCallback, useEffect, useMemo, useState } from 'react' +import { useAccount, useConnect, useDisconnect, useSignTypedData } from 'wagmi' + +type AuthState = { + signature: string + issuedAt: string + nonce: string + address: `0x${string}` +} + +const storageKey = (address: string) => + `privacy-vault-auth:${address.toLowerCase()}` + +const createNonce = () => { + if (typeof crypto !== 'undefined' && 'randomUUID' in crypto) { + return crypto.randomUUID() + } + + return Math.random().toString(36).slice(2) +} + +export const useWalletAuth = () => { + const { address, isConnected } = useAccount() + const { connectAsync, connectors, isPending: isConnecting } = useConnect() + const { disconnect } = useDisconnect() + const { signTypedDataAsync, isPending: isSigning } = useSignTypedData() + const [authState, setAuthState] = useState(null) + const [error, setError] = useState(null) + + useEffect(() => { + if (!address) { + setAuthState(null) + return + } + + const stored = localStorage.getItem(storageKey(address)) + if (!stored) { + setAuthState(null) + return + } + + try { + const parsed = JSON.parse(stored) as AuthState + if (parsed.address?.toLowerCase() === address.toLowerCase()) { + setAuthState(parsed) + } else { + setAuthState(null) + } + } catch { + setAuthState(null) + } + }, [address]) + + const connectWallet = useCallback(async () => { + setError(null) + const connector = connectors.find((item) => item.ready) ?? connectors[0] + + if (!connector) { + setError('No wallet connector available.') + return + } + + try { + await connectAsync({ connector }) + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to connect wallet') + } + }, [connectAsync, connectors]) + + const authenticate = useCallback(async () => { + if (!address) { + setError('Connect a wallet to continue.') + return + } + + setError(null) + + const issuedAt = new Date().toISOString() + const nonce = createNonce() + const message = { + address, + statement: 'Sign in to Payy Privacy Vault', + nonce, + issuedAt + } + + try { + const signature = await signTypedDataAsync({ + domain: { + name: 'Payy Privacy Vault', + version: '1' + }, + types: { + Auth: [ + { name: 'address', type: 'address' }, + { name: 'statement', type: 'string' }, + { name: 'nonce', type: 'string' }, + { name: 'issuedAt', type: 'string' } + ] + }, + primaryType: 'Auth', + message + }) + + const payload: AuthState = { + signature, + issuedAt, + nonce, + address + } + + localStorage.setItem(storageKey(address), JSON.stringify(payload)) + setAuthState(payload) + } catch (err) { + setError(err instanceof Error ? err.message : 'Signature rejected') + } + }, [address, signTypedDataAsync]) + + const resetAuth = useCallback(() => { + if (address) { + localStorage.removeItem(storageKey(address)) + } + setAuthState(null) + }, [address]) + + const status = useMemo(() => { + if (authState) { + return 'complete' + } + if (isSigning || isConnecting) { + return 'pending' + } + if (error) { + return 'error' + } + return 'idle' + }, [authState, error, isConnecting, isSigning]) + + return { + address, + isConnected, + isConnecting, + isSigning, + isAuthenticated: Boolean(authState), + status, + error, + connectWallet, + authenticate, + disconnect, + resetAuth + } +} + +export type WalletAuthState = ReturnType diff --git a/app/packages/privacy-vault/src/features/faucet/FaucetStep.tsx b/app/packages/privacy-vault/src/features/faucet/FaucetStep.tsx new file mode 100644 index 0000000..c7307ad --- /dev/null +++ b/app/packages/privacy-vault/src/features/faucet/FaucetStep.tsx @@ -0,0 +1,106 @@ +import { useMemo } from 'react' +import type { UseMutationResult } from '@tanstack/react-query' + +import { Button } from '../../components/Button' +import { FaucetApiError, type FaucetResponse } from '../../lib/api' +import { buildExplorerTxUrl } from '../../lib/config' + +interface FaucetStepProps { + faucet: UseMutationResult + address?: `0x${string}` + isConnected: boolean +} + +export const FaucetStep = ({ + faucet, + address, + isConnected +}: FaucetStepProps) => { + const { mutateAsync, data, error, isPending, isSuccess, reset } = faucet + + const apiError = error instanceof FaucetApiError ? error : null + const retryAfter = + apiError?.reason === 'rate-limited' ? apiError.data?.retry_after_secs : null + + const statusMessage = useMemo(() => { + if (isPending) { + return 'Requesting faucet transfer...' + } + if (isSuccess) { + return 'Faucet request completed. Transactions are broadcasting.' + } + return null + }, [isPending, isSuccess]) + + const onMint = async () => { + if (!address) { + return + } + reset() + await mutateAsync(address) + } + + return ( +
+
+

+ Mint testnet funds +

+

+ Request PUSD on Payy Testnet to explore the Privacy Vault without real + funds. +

+
+ +
+ {isConnected ? ( +
+
Destination
+
{address}
+
+ ) : ( +
+ Connect your wallet first to request faucet funds. +
+ )} +
+ + {statusMessage && ( +
{statusMessage}
+ )} + + {error && ( +
+ {retryAfter + ? `Rate limit reached. Try again in ${retryAfter} seconds.` + : apiError?.message || 'Faucet request failed. Please try again.'} +
+ )} + + {data && ( +
+
Transaction hashes
+
    + {data.tx_hashes.map((hash) => ( +
  • + + {hash} + +
  • + ))} +
+
+ )} + +
+ +
+
+ ) +} diff --git a/app/packages/privacy-vault/src/features/faucet/useFaucet.ts b/app/packages/privacy-vault/src/features/faucet/useFaucet.ts new file mode 100644 index 0000000..04e5ecb --- /dev/null +++ b/app/packages/privacy-vault/src/features/faucet/useFaucet.ts @@ -0,0 +1,9 @@ +import { useMutation } from '@tanstack/react-query' + +import { claimFaucet, type FaucetResponse } from '../../lib/api' + +export const useFaucet = () => { + return useMutation({ + mutationFn: async (address: string) => claimFaucet({ address }) + }) +} diff --git a/app/packages/privacy-vault/src/features/network/NetworkStep.tsx b/app/packages/privacy-vault/src/features/network/NetworkStep.tsx new file mode 100644 index 0000000..5c19a16 --- /dev/null +++ b/app/packages/privacy-vault/src/features/network/NetworkStep.tsx @@ -0,0 +1,50 @@ +import { Button } from '../../components/Button' +import { EXPLORER_URL, payyTestnet, RPC_URL } from '../../lib/config' +import type { AddNetworkState } from './useAddNetwork' + +interface NetworkStepProps { + network: AddNetworkState +} + +export const NetworkStep = ({ network }: NetworkStepProps) => { + const { status, error, isAdded, addNetwork } = network + + return ( +
+
+

Add Payy Testnet

+

+ Add the Payy Testnet network to your wallet so it can interact with + testnet assets. +

+
+ +
+
+
Network
+
+ {payyTestnet.name} +
+
Chain ID: {payyTestnet.id}
+
RPC: {RPC_URL}
+
Block Explorer: {EXPLORER_URL}
+
+ Currency: {payyTestnet.nativeCurrency.symbol} +
+
+
+ + {error &&
{error}
} + +
+ +
+
+ ) +} diff --git a/app/packages/privacy-vault/src/features/network/useAddNetwork.ts b/app/packages/privacy-vault/src/features/network/useAddNetwork.ts new file mode 100644 index 0000000..cae833c --- /dev/null +++ b/app/packages/privacy-vault/src/features/network/useAddNetwork.ts @@ -0,0 +1,82 @@ +import { useCallback, useMemo, useState } from 'react' +import { useAccount, useChainId } from 'wagmi' +import { toHex } from 'viem' + +import { payyTestnet } from '../../lib/config' + +type NetworkStatus = 'idle' | 'pending' | 'complete' | 'error' + +type EthereumProvider = { + request: (args: { method: string; params?: unknown[] }) => Promise +} + +const getEthereum = (): EthereumProvider | undefined => + (window as Window & { ethereum?: EthereumProvider }).ethereum + +export const useAddNetwork = () => { + const { isConnected } = useAccount() + const chainId = useChainId() + const [isPending, setIsPending] = useState(false) + const [error, setError] = useState(null) + + const isAdded = useMemo( + () => isConnected && chainId === payyTestnet.id, + [isConnected, chainId] + ) + + const status = useMemo(() => { + if (isAdded) { + return 'complete' + } + if (isPending) { + return 'pending' + } + if (error) { + return 'error' + } + return 'idle' + }, [isAdded, isPending, error]) + + const addNetwork = useCallback(async () => { + const ethereum = getEthereum() + if (!ethereum) { + setError('No wallet detected. Please install a wallet extension.') + return + } + + setError(null) + setIsPending(true) + + try { + await ethereum.request({ + method: 'wallet_addEthereumChain', + params: [ + { + chainId: toHex(payyTestnet.id), + chainName: payyTestnet.name, + nativeCurrency: payyTestnet.nativeCurrency, + rpcUrls: payyTestnet.rpcUrls.default.http, + blockExplorerUrls: [payyTestnet.blockExplorers.default.url] + } + ] + }) + + setError(null) + } catch (err) { + setError( + err instanceof Error ? err.message : 'Failed to add Payy Testnet' + ) + } finally { + setIsPending(false) + } + }, []) + + return { + status, + error, + isAdded, + addNetwork + } +} + +export type AddNetworkState = ReturnType diff --git a/app/packages/privacy-vault/src/hooks/useTheme.ts b/app/packages/privacy-vault/src/hooks/useTheme.ts new file mode 100644 index 0000000..52d02c4 --- /dev/null +++ b/app/packages/privacy-vault/src/hooks/useTheme.ts @@ -0,0 +1,12 @@ +import { useEffect } from 'react' + +type ThemeMode = 'dark' | 'light' + +export const useTheme = (): ThemeMode => { + useEffect(() => { + document.documentElement.setAttribute('data-theme', 'dark') + document.documentElement.style.colorScheme = 'dark' + }, []) + + return 'dark' +} diff --git a/app/packages/privacy-vault/src/lib/api.ts b/app/packages/privacy-vault/src/lib/api.ts new file mode 100644 index 0000000..bc34e40 --- /dev/null +++ b/app/packages/privacy-vault/src/lib/api.ts @@ -0,0 +1,77 @@ +import { FAUCET_URL } from './config' + +export interface FaucetRequest { + address: string + token?: string +} + +export interface FaucetResponse { + address: string + tx_hashes: string[] +} + +export interface FaucetErrorData { + address?: string + retry_after_secs?: number + token?: string +} + +export class FaucetApiError extends Error { + reason?: string + data?: FaucetErrorData + status?: number + + constructor( + message: string, + options?: { reason?: string; data?: FaucetErrorData; status?: number } + ) { + super(message) + this.name = 'FaucetApiError' + this.reason = options?.reason + this.data = options?.data + this.status = options?.status + } +} + +interface ErrorResponse { + error?: { + reason?: string + message?: string + data?: FaucetErrorData + } +} + +const parseErrorResponse = async ( + response: Response +): Promise => { + try { + return await response.json() + } catch { + return null + } +} + +export const claimFaucet = async ( + payload: FaucetRequest +): Promise => { + const response = await fetch(`${FAUCET_URL}/faucet/claim`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }) + + if (!response.ok) { + const errorPayload = await parseErrorResponse(response) + const reason = errorPayload?.error?.reason + const message = errorPayload?.error?.message || 'Faucet request failed' + throw new FaucetApiError(message, { + reason, + data: errorPayload?.error?.data, + status: response.status + }) + } + + return response.json() +} diff --git a/app/packages/privacy-vault/src/lib/config.ts b/app/packages/privacy-vault/src/lib/config.ts new file mode 100644 index 0000000..0d37120 --- /dev/null +++ b/app/packages/privacy-vault/src/lib/config.ts @@ -0,0 +1,27 @@ +import { defineChain } from 'viem' + +export const PAYY_TESTNET_CHAIN_ID = 7298 +export const RPC_URL = 'https://rpc.testnet.payy.network' +export const EXPLORER_URL = 'https://blockscout.testnet.payy.network' +export const FAUCET_URL = 'https://faucet.testnet.payy.network' +export const IS_TESTNET = true + +export const payyTestnet = defineChain({ + id: PAYY_TESTNET_CHAIN_ID, + name: 'Payy Testnet', + nativeCurrency: { + name: 'PUSD', + symbol: 'PUSD', + decimals: 16 + }, + rpcUrls: { + default: { + http: [RPC_URL] + } + }, + blockExplorers: { + default: { name: 'Payy Blockscout', url: EXPLORER_URL } + } +}) + +export const buildExplorerTxUrl = (hash: string) => `${EXPLORER_URL}/tx/${hash}` diff --git a/app/packages/privacy-vault/src/lib/wagmi.ts b/app/packages/privacy-vault/src/lib/wagmi.ts new file mode 100644 index 0000000..95c3ef7 --- /dev/null +++ b/app/packages/privacy-vault/src/lib/wagmi.ts @@ -0,0 +1,12 @@ +import { createConfig, http } from 'wagmi' +import { injected } from 'wagmi/connectors' + +import { payyTestnet, RPC_URL } from './config' + +export const wagmiConfig = createConfig({ + chains: [payyTestnet], + connectors: [injected()], + transports: { + [payyTestnet.id]: http(RPC_URL) + } +}) diff --git a/app/packages/privacy-vault/src/main.tsx b/app/packages/privacy-vault/src/main.tsx new file mode 100644 index 0000000..1a17794 --- /dev/null +++ b/app/packages/privacy-vault/src/main.tsx @@ -0,0 +1,26 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { WagmiProvider } from 'wagmi' + +import App from './App' +import { wagmiConfig } from './lib/wagmi' +import './styles/globals.css' + +const queryClient = new QueryClient() + +const root = document.getElementById('root') + +if (!root) { + throw new Error('Root element not found') +} + +ReactDOM.createRoot(root).render( + + + + + + + +) diff --git a/app/packages/privacy-vault/src/styles/globals.css b/app/packages/privacy-vault/src/styles/globals.css new file mode 100644 index 0000000..dfdb01b --- /dev/null +++ b/app/packages/privacy-vault/src/styles/globals.css @@ -0,0 +1,74 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@font-face { + font-family: 'Steradian'; + src: url('../assets/fonts/Steradian-Rg.otf') format('opentype'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Steradian'; + src: url('../assets/fonts/Steradian-Md.otf') format('opentype'); + font-weight: 600; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Steradian'; + src: url('../assets/fonts/Steradian-Bd.otf') format('opentype'); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Steradian'; + src: url('../assets/fonts/Steradian-Blk.otf') format('opentype'); + font-weight: 800; + font-style: normal; + font-display: swap; +} + +:root { + --primary: 224 255 50; + --background: 17 17 17; + --text: 255 255 255; + --border-accent: 224 255 50; + --gray-900: 36 36 36; + --gray-800: 64 64 64; + --surface: #171717; + --surface-strong: #1f1f1f; + --text-muted: #b5b5b5; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-height: 100vh; + font-family: 'Steradian', 'Open Sans', 'Source Sans Pro', Arial, Helvetica, sans-serif; + background-color: rgb(var(--background)); + color: rgb(var(--text)); + border-top: 2px solid rgb(var(--border-accent)); + letter-spacing: -0.01em; +} + +#root { + min-height: 100vh; +} + +a { + color: inherit; + text-decoration: none; +} + +button { + font-family: inherit; +} diff --git a/app/packages/privacy-vault/tailwind.config.js b/app/packages/privacy-vault/tailwind.config.js new file mode 100644 index 0000000..8e3c769 --- /dev/null +++ b/app/packages/privacy-vault/tailwind.config.js @@ -0,0 +1,23 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./index.html', './src/**/*.{ts,tsx}'], + theme: { + extend: { + colors: { + primary: 'rgb(var(--primary) / )', + background: 'rgb(var(--background) / )', + text: 'rgb(var(--text) / )', + 'border-accent': 'rgb(var(--border-accent) / )', + 'gray-900': 'rgb(var(--gray-900) / )', + 'gray-800': 'rgb(var(--gray-800) / )' + }, + fontFamily: { + sans: ['Steradian', 'system-ui', 'sans-serif'] + }, + boxShadow: { + glow: '0 0 0 1px rgba(224, 255, 50, 0.35), 0 8px 30px rgba(0, 0, 0, 0.35)' + } + } + }, + plugins: [] +} diff --git a/app/packages/privacy-vault/tsconfig.json b/app/packages/privacy-vault/tsconfig.json new file mode 100644 index 0000000..01f01a7 --- /dev/null +++ b/app/packages/privacy-vault/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2021", + "lib": ["DOM", "DOM.Iterable", "ES2021"], + "module": "ESNext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "skipLibCheck": true, + "types": ["vite/client"] + }, + "include": ["src", "vite.config.ts"] +} diff --git a/app/packages/privacy-vault/vite.config.ts b/app/packages/privacy-vault/vite.config.ts new file mode 100644 index 0000000..eca6e2f --- /dev/null +++ b/app/packages/privacy-vault/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()] +}) diff --git a/app/packages/react-native-rust-bridge/cpp/rustbridge/Cargo.toml b/app/packages/react-native-rust-bridge/cpp/rustbridge/Cargo.toml new file mode 100644 index 0000000..c160b8a --- /dev/null +++ b/app/packages/react-native-rust-bridge/cpp/rustbridge/Cargo.toml @@ -0,0 +1,11 @@ +# Destination-only placeholder for Cargo tooling in the synced repo. +[package] +name = "rustbridge" +version = "0.0.0" +edition = "2021" + +[lib] +path = "src/lib.rs" + +[features] +ts-rs = [] diff --git a/app/packages/react-native-rust-bridge/cpp/rustbridge/src/lib.rs b/app/packages/react-native-rust-bridge/cpp/rustbridge/src/lib.rs new file mode 100644 index 0000000..e69de29 diff --git a/app/tsconfig.json b/app/tsconfig.json new file mode 100644 index 0000000..ded86e1 --- /dev/null +++ b/app/tsconfig.json @@ -0,0 +1,50 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "strict": true, + "jsx": "react-native", + "skipLibCheck": true, + "target": "es2021", + "lib": ["es2021"], + "module": "commonjs", + "moduleResolution": "node", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "noEmit": true, + "types": ["node"], + "typeRoots": ["./node_modules/@types", "./types"], + "paths": { + "@/*": ["packages/payy/src/*", "packages/link/src/*"], + "@/components/*": [ + "packages/payy/src/components/*", + "packages/link/src/components/*" + ], + "@/hooks/*": ["packages/payy/src/hooks/*", "packages/link/src/hooks/*"] + } + }, + "include": [ + "types/**/*.d.ts", + "packages/payy/types.d.ts", + "packages/payy/types/**/*.d.ts", + "packages/payy/**/*", + "packages/commentator-mcp/src/types/env.d.ts", + "src", + "tests", + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "packages/link", + "packages/network", + "packages/privacy-vault", + "packages/commentator-mcp", + "node_modules", + "**/*.test.ts", + "**/*.test.tsx", + "**/*.spec.ts", + "**/*.spec.tsx", + "**/tests/**", + "**/__tests__/**" + ] +} diff --git a/app/yarn.lock b/app/yarn.lock new file mode 100644 index 0000000..b2d5a94 --- /dev/null +++ b/app/yarn.lock @@ -0,0 +1,20626 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@0no-co/graphql.web@^1.0.13", "@0no-co/graphql.web@^1.0.8": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@0no-co/graphql.web/-/graphql.web-1.2.0.tgz#296d00581bfaaabfda1e976849d927824aaea81b" + integrity sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw== + +"@adobe/css-tools@^4.4.0": + version "4.4.4" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.4.tgz#2856c55443d3d461693f32d2b96fb6ea92e1ffa9" + integrity sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg== + +"@adraffy/ens-normalize@1.10.1": + version "1.10.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz#63430d04bd8c5e74f8d7d049338f1cd9d4f02069" + integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== + +"@adraffy/ens-normalize@^1.10.1", "@adraffy/ens-normalize@^1.11.0": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz#6c2d657d4b2dfb37f8ea811dcb3e60843d4ac24a" + integrity sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ== + +"@alloc/quick-lru@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" + integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== + +"@babel/cli@^7.23.4": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.28.3.tgz#f33693753bc103ab0084a5776ccf8ab8a140038b" + integrity sha512-n1RU5vuCX0CsaqaXm9I0KUCNKNQMy5epmzl/xdSSm70bSqhg9GWhgeosypyQLc0bK24+Xpk1WGzZlI9pJtkZdg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.28" + commander "^6.2.0" + convert-source-map "^2.0.0" + fs-readdir-recursive "^1.1.0" + glob "^7.2.0" + make-dir "^2.1.0" + slash "^2.0.0" + optionalDependencies: + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" + chokidar "^3.6.0" + +"@babel/code-frame@7.10.4", "@babel/code-frame@~7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.20.0", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/code-frame@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.28.6.tgz#72499312ec58b1e2245ba4a4f550c132be4982f7" + integrity sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q== + dependencies: + "@babel/helper-validator-identifier" "^7.28.5" + js-tokens "^4.0.0" + picocolors "^1.1.1" + +"@babel/compat-data@^7.27.2", "@babel/compat-data@^7.27.7", "@babel/compat-data@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.5.tgz#a8a4962e1567121ac0b3b487f52107443b455c7f" + integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA== + +"@babel/compat-data@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.6.tgz#103f466803fa0f059e82ccac271475470570d74c" + integrity sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.20.0", "@babel/core@^7.21.3", "@babel/core@^7.23.9", "@babel/core@^7.24.0", "@babel/core@^7.25.2", "@babel/core@^7.26.0", "@babel/core@^7.27.4", "@babel/core@^7.28.0": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.6.tgz#531bf883a1126e53501ba46eb3bb414047af507f" + integrity sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-compilation-targets" "^7.28.6" + "@babel/helper-module-transforms" "^7.28.6" + "@babel/helpers" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/remapping" "^2.3.5" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.20.0", "@babel/generator@^7.20.5", "@babel/generator@^7.25.0", "@babel/generator@^7.27.5", "@babel/generator@^7.28.5", "@babel/generator@^7.7.2": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.5.tgz#712722d5e50f44d07bc7ac9fe84438742dd61298" + integrity sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ== + dependencies: + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/generator@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.6.tgz#48dcc65d98fcc8626a48f72b62e263d25fc3c3f1" + integrity sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw== + dependencies: + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/helper-annotate-as-pure@^7.27.1", "@babel/helper-annotate-as-pure@^7.27.3": + version "7.27.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5" + integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== + dependencies: + "@babel/types" "^7.27.3" + +"@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.27.2": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" + integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== + dependencies: + "@babel/compat-data" "^7.27.2" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-compilation-targets@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz#32c4a3f41f12ed1532179b108a4d746e105c2b25" + integrity sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA== + dependencies: + "@babel/compat-data" "^7.28.6" + "@babel/helper-validator-option" "^7.27.1" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.27.1", "@babel/helper-create-class-features-plugin@^7.28.3", "@babel/helper-create-class-features-plugin@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz#472d0c28028850968979ad89f173594a6995da46" + integrity sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-member-expression-to-functions" "^7.28.5" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.28.5" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.27.1": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz#7c1ddd64b2065c7f78034b25b43346a7e19ed997" + integrity sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + regexpu-core "^6.3.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.5": + version "0.6.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz#742ccf1cb003c07b48859fc9fa2c1bbe40e5f753" + integrity sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg== + dependencies: + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + debug "^4.4.1" + lodash.debounce "^4.0.8" + resolve "^1.22.10" + +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + +"@babel/helper-member-expression-to-functions@^7.27.1", "@babel/helper-member-expression-to-functions@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz#f3e07a10be37ed7a63461c63e6929575945a6150" + integrity sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg== + dependencies: + "@babel/traverse" "^7.28.5" + "@babel/types" "^7.28.5" + +"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.25.9", "@babel/helper-module-imports@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" + integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-module-imports@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz#60632cbd6ffb70b22823187201116762a03e2d5c" + integrity sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw== + dependencies: + "@babel/traverse" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/helper-module-transforms@^7.27.1", "@babel/helper-module-transforms@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" + integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.28.3" + +"@babel/helper-module-transforms@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz#9312d9d9e56edc35aeb6e95c25d4106b50b9eb1e" + integrity sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA== + dependencies: + "@babel/helper-module-imports" "^7.28.6" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.6" + +"@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== + dependencies: + "@babel/types" "^7.27.1" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.0": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" + integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== + +"@babel/helper-remap-async-to-generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz#4601d5c7ce2eb2aea58328d43725523fcd362ce6" + integrity sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-wrap-function" "^7.27.1" + "@babel/traverse" "^7.27.1" + +"@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" + +"@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-string-parser@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" + integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== + +"@babel/helper-validator-identifier@^7.25.9", "@babel/helper-validator-identifier@^7.27.1", "@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + +"@babel/helper-validator-option@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" + integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== + +"@babel/helper-wrap-function@^7.27.1": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz#fe4872092bc1438ffd0ce579e6f699609f9d0a7a" + integrity sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g== + dependencies: + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.3" + "@babel/types" "^7.28.2" + +"@babel/helpers@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7" + integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw== + dependencies: + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/highlight@^7.10.4": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.9.tgz#8141ce68fc73757946f983b343f1231f4691acc6" + integrity sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.25.3", "@babel/parser@^7.27.2", "@babel/parser@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" + integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== + dependencies: + "@babel/types" "^7.28.5" + +"@babel/parser@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.6.tgz#f01a8885b7fa1e56dd8a155130226cd698ef13fd" + integrity sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ== + dependencies: + "@babel/types" "^7.28.6" + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz#fbde57974707bbfa0376d34d425ff4fa6c732421" + integrity sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.28.5" + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz#43f70a6d7efd52370eefbdf55ae03d91b293856d" + integrity sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz#beb623bd573b8b6f3047bd04c32506adc3e58a72" + integrity sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz#e134a5479eb2ba9c02714e8c1ebf1ec9076124fd" + integrity sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/plugin-transform-optional-chaining" "^7.27.1" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz#373f6e2de0016f73caf8f27004f61d167743742a" + integrity sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.28.3" + +"@babel/plugin-proposal-decorators@^7.12.9": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz#419c8acc31088e05a774344c021800f7ddc39bf0" + integrity sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-decorators" "^7.27.1" + +"@babel/plugin-proposal-export-default-from@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.27.1.tgz#59b050b0e5fdc366162ab01af4fcbac06ea40919" + integrity sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-decorators@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz#ee7dd9590aeebc05f9d4c8c0560007b05979a63d" + integrity sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-default-from@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.27.1.tgz#8efed172e79ab657c7fa4d599224798212fb7e18" + integrity sha512-eBC/3KSekshx19+N40MzjWqJd7KTEdOoLesAfa4IDFI8eRz5a47i5Oszus6zG/cwIXN63YhgLOMSSNJx49sENg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-flow@^7.12.1", "@babel/plugin-syntax-flow@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.27.1.tgz#6c83cf0d7d635b716827284b7ecd5aead9237662" + integrity sha512-p9OkPbZ5G7UT1MofwYFigGebnrzGJacoBSQM0/6bi/PUMVE+qlWDD/OalvQKbwgQzU6dl0xAv6r4X7Jme0RYxA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-assertions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz#88894aefd2b03b5ee6ad1562a7c8e1587496aecd" + integrity sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-attributes@^7.24.7", "@babel/plugin-syntax-import-attributes@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-import-meta@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.27.1", "@babel/plugin-syntax-jsx@^7.7.2": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz#2f9beb5eff30fa507c5532d107daac7b888fa34c" + integrity sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.27.1", "@babel/plugin-syntax-typescript@^7.7.2": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz#5147d29066a793450f220c63fa3a9431b7e6dd18" + integrity sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.0.0-0", "@babel/plugin-transform-arrow-functions@^7.24.7", "@babel/plugin-transform-arrow-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz#6e2061067ba3ab0266d834a9f94811196f2aba9a" + integrity sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-async-generator-functions@^7.25.4", "@babel/plugin-transform-async-generator-functions@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz#1276e6c7285ab2cd1eccb0bc7356b7a69ff842c2" + integrity sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" + "@babel/traverse" "^7.28.0" + +"@babel/plugin-transform-async-to-generator@^7.24.7", "@babel/plugin-transform-async-to-generator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz#9a93893b9379b39466c74474f55af03de78c66e7" + integrity sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-remap-async-to-generator" "^7.27.1" + +"@babel/plugin-transform-block-scoped-functions@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz#558a9d6e24cf72802dd3b62a4b51e0d62c0f57f9" + integrity sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-block-scoping@^7.25.0", "@babel/plugin-transform-block-scoping@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz#e0d3af63bd8c80de2e567e690a54e84d85eb16f6" + integrity sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-class-properties@^7.0.0-0", "@babel/plugin-transform-class-properties@^7.25.4", "@babel/plugin-transform-class-properties@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz#dd40a6a370dfd49d32362ae206ddaf2bb082a925" + integrity sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-class-static-block@^7.27.1", "@babel/plugin-transform-class-static-block@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz#d1b8e69b54c9993bc558203e1f49bfc979bfd852" + integrity sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.28.3" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-classes@^7.0.0-0", "@babel/plugin-transform-classes@^7.25.4", "@babel/plugin-transform-classes@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz#75d66175486788c56728a73424d67cbc7473495c" + integrity sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-globals" "^7.28.0" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/traverse" "^7.28.4" + +"@babel/plugin-transform-computed-properties@^7.24.7", "@babel/plugin-transform-computed-properties@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz#81662e78bf5e734a97982c2b7f0a793288ef3caa" + integrity sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/template" "^7.27.1" + +"@babel/plugin-transform-destructuring@^7.24.8", "@babel/plugin-transform-destructuring@^7.28.0", "@babel/plugin-transform-destructuring@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz#b8402764df96179a2070bb7b501a1586cf8ad7a7" + integrity sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.28.5" + +"@babel/plugin-transform-dotall-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz#aa6821de864c528b1fecf286f0a174e38e826f4d" + integrity sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-duplicate-keys@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz#f1fbf628ece18e12e7b32b175940e68358f546d1" + integrity sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz#5043854ca620a94149372e69030ff8cb6a9eb0ec" + integrity sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-dynamic-import@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz#4c78f35552ac0e06aa1f6e3c573d67695e8af5a4" + integrity sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-explicit-resource-management@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz#45be6211b778dbf4b9d54c4e8a2b42fa72e09a1a" + integrity sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.0" + +"@babel/plugin-transform-exponentiation-operator@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz#7cc90a8170e83532676cfa505278e147056e94fe" + integrity sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-export-namespace-from@^7.23.4", "@babel/plugin-transform-export-namespace-from@^7.25.9", "@babel/plugin-transform-export-namespace-from@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz#71ca69d3471edd6daa711cf4dfc3400415df9c23" + integrity sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-flow-strip-types@^7.25.2", "@babel/plugin-transform-flow-strip-types@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.27.1.tgz#5def3e1e7730f008d683144fb79b724f92c5cdf9" + integrity sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-flow" "^7.27.1" + +"@babel/plugin-transform-for-of@^7.24.7", "@babel/plugin-transform-for-of@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz#bc24f7080e9ff721b63a70ac7b2564ca15b6c40a" + integrity sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + +"@babel/plugin-transform-function-name@^7.25.1", "@babel/plugin-transform-function-name@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz#4d0bf307720e4dce6d7c30fcb1fd6ca77bdeb3a7" + integrity sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ== + dependencies: + "@babel/helper-compilation-targets" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/traverse" "^7.27.1" + +"@babel/plugin-transform-json-strings@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz#a2e0ce6ef256376bd527f290da023983527a4f4c" + integrity sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-literals@^7.25.2", "@babel/plugin-transform-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz#baaefa4d10a1d4206f9dcdda50d7d5827bb70b24" + integrity sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-logical-assignment-operators@^7.24.7", "@babel/plugin-transform-logical-assignment-operators@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz#d028fd6db8c081dee4abebc812c2325e24a85b0e" + integrity sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-member-expression-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz#37b88ba594d852418e99536f5612f795f23aeaf9" + integrity sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-modules-amd@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz#a4145f9d87c2291fe2d05f994b65dba4e3e7196f" + integrity sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA== + dependencies: + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-modules-commonjs@^7.24.8", "@babel/plugin-transform-modules-commonjs@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz#8e44ed37c2787ecc23bdc367f49977476614e832" + integrity sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw== + dependencies: + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-modules-systemjs@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz#7439e592a92d7670dfcb95d0cbc04bd3e64801d2" + integrity sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew== + dependencies: + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + "@babel/traverse" "^7.28.5" + +"@babel/plugin-transform-modules-umd@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz#63f2cf4f6dc15debc12f694e44714863d34cd334" + integrity sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w== + dependencies: + "@babel/helper-module-transforms" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7", "@babel/plugin-transform-named-capturing-groups-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz#f32b8f7818d8fc0cc46ee20a8ef75f071af976e1" + integrity sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-new-target@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz#259c43939728cad1706ac17351b7e6a7bea1abeb" + integrity sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.0.0-0", "@babel/plugin-transform-nullish-coalescing-operator@^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz#4f9d3153bf6782d73dd42785a9d22d03197bc91d" + integrity sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-numeric-separator@^7.24.7", "@babel/plugin-transform-numeric-separator@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz#614e0b15cc800e5997dadd9bd6ea524ed6c819c6" + integrity sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-object-rest-spread@^7.24.7", "@babel/plugin-transform-object-rest-spread@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz#9ee1ceca80b3e6c4bac9247b2149e36958f7f98d" + integrity sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew== + dependencies: + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.0" + "@babel/plugin-transform-parameters" "^7.27.7" + "@babel/traverse" "^7.28.4" + +"@babel/plugin-transform-object-super@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz#1c932cd27bf3874c43a5cac4f43ebf970c9871b5" + integrity sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + +"@babel/plugin-transform-optional-catch-binding@^7.24.7", "@babel/plugin-transform-optional-catch-binding@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz#84c7341ebde35ccd36b137e9e45866825072a30c" + integrity sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-optional-chaining@^7.0.0-0", "@babel/plugin-transform-optional-chaining@^7.24.8", "@babel/plugin-transform-optional-chaining@^7.27.1", "@babel/plugin-transform-optional-chaining@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz#8238c785f9d5c1c515a90bf196efb50d075a4b26" + integrity sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + +"@babel/plugin-transform-parameters@^7.24.7", "@babel/plugin-transform-parameters@^7.27.7": + version "7.27.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz#1fd2febb7c74e7d21cf3b05f7aebc907940af53a" + integrity sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-private-methods@^7.24.7", "@babel/plugin-transform-private-methods@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz#fdacbab1c5ed81ec70dfdbb8b213d65da148b6af" + integrity sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-private-property-in-object@^7.24.7", "@babel/plugin-transform-private-property-in-object@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz#4dbbef283b5b2f01a21e81e299f76e35f900fb11" + integrity sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-create-class-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-property-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz#07eafd618800591e88073a0af1b940d9a42c6424" + integrity sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-constant-elements@^7.21.3": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.27.1.tgz#6c6b50424e749a6e48afd14cf7b92f98cb9383f9" + integrity sha512-edoidOjl/ZxvYo4lSBOQGDSyToYVkTAwyVoa2tkuYTSmjrB1+uAedoL5iROVLXkxH+vRgA7uP4tMg2pUJpZ3Ug== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-display-name@^7.24.7", "@babel/plugin-transform-react-display-name@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.28.0.tgz#6f20a7295fea7df42eb42fed8f896813f5b934de" + integrity sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-jsx-development@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz#47ff95940e20a3a70e68ad3d4fcb657b647f6c98" + integrity sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.27.1" + +"@babel/plugin-transform-react-jsx-self@^7.24.7", "@babel/plugin-transform-react-jsx-self@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz#af678d8506acf52c577cac73ff7fe6615c85fc92" + integrity sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-jsx-source@^7.24.7", "@babel/plugin-transform-react-jsx-source@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz#dcfe2c24094bb757bf73960374e7c55e434f19f0" + integrity sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-jsx@^7.25.2", "@babel/plugin-transform-react-jsx@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz#1023bc94b78b0a2d68c82b5e96aed573bcfb9db0" + integrity sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/plugin-transform-react-pure-annotations@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz#339f1ce355eae242e0649f232b1c68907c02e879" + integrity sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-regenerator@^7.24.7", "@babel/plugin-transform-regenerator@^7.28.4": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz#9d3fa3bebb48ddd0091ce5729139cd99c67cea51" + integrity sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-regexp-modifiers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz#df9ba5577c974e3f1449888b70b76169998a6d09" + integrity sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-reserved-words@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz#40fba4878ccbd1c56605a4479a3a891ac0274bb4" + integrity sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-runtime@^7.24.7": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.5.tgz#ae3e21fbefe2831ebac04dfa6b463691696afe17" + integrity sha512-20NUVgOrinudkIBzQ2bNxP08YpKprUkRTiRSd2/Z5GOdPImJGkoN4Z7IQe1T5AdyKI1i5L6RBmluqdSzvaq9/w== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + babel-plugin-polyfill-corejs2 "^0.4.14" + babel-plugin-polyfill-corejs3 "^0.13.0" + babel-plugin-polyfill-regenerator "^0.6.5" + semver "^6.3.1" + +"@babel/plugin-transform-shorthand-properties@^7.0.0-0", "@babel/plugin-transform-shorthand-properties@^7.24.7", "@babel/plugin-transform-shorthand-properties@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz#532abdacdec87bfee1e0ef8e2fcdee543fe32b90" + integrity sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-spread@^7.24.7", "@babel/plugin-transform-spread@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz#1a264d5fc12750918f50e3fe3e24e437178abb08" + integrity sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + +"@babel/plugin-transform-sticky-regex@^7.24.7", "@babel/plugin-transform-sticky-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz#18984935d9d2296843a491d78a014939f7dcd280" + integrity sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-strict-mode@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-strict-mode/-/plugin-transform-strict-mode-7.27.1.tgz#6273e02e054ec9e29c2e1a79354744f3582a5ec5" + integrity sha512-cdA1TyX9NfOaV8PILyNSrzJxXnjk4UeAgSwSLDCepfOg9AlxCg5al0KWsFh0ZJRzp6k5gwpSlJ4auWT+gx46ig== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-template-literals@^7.0.0-0", "@babel/plugin-transform-template-literals@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz#1a0eb35d8bb3e6efc06c9fd40eb0bcef548328b8" + integrity sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-typeof-symbol@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz#70e966bb492e03509cf37eafa6dcc3051f844369" + integrity sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-typescript@^7.25.2", "@babel/plugin-transform-typescript@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz#441c5f9a4a1315039516c6c612fc66d5f4594e72" + integrity sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-create-class-features-plugin" "^7.28.5" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/plugin-syntax-typescript" "^7.27.1" + +"@babel/plugin-transform-unicode-escapes@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz#3e3143f8438aef842de28816ece58780190cf806" + integrity sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-unicode-property-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz#bdfe2d3170c78c5691a3c3be934c8c0087525956" + integrity sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-unicode-regex@^7.0.0-0", "@babel/plugin-transform-unicode-regex@^7.24.7", "@babel/plugin-transform-unicode-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz#25948f5c395db15f609028e370667ed8bae9af97" + integrity sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-unicode-sets-regex@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz#6ab706d10f801b5c72da8bb2548561fa04193cd1" + integrity sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.27.1" + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/preset-env@^7.20.2", "@babel/preset-env@^7.23.8", "@babel/preset-env@^7.25.2": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.28.5.tgz#82dd159d1563f219a1ce94324b3071eb89e280b0" + integrity sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg== + dependencies: + "@babel/compat-data" "^7.28.5" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-option" "^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.28.5" + "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.27.1" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.27.1" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.27.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.28.3" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions" "^7.27.1" + "@babel/plugin-syntax-import-attributes" "^7.27.1" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.27.1" + "@babel/plugin-transform-async-generator-functions" "^7.28.0" + "@babel/plugin-transform-async-to-generator" "^7.27.1" + "@babel/plugin-transform-block-scoped-functions" "^7.27.1" + "@babel/plugin-transform-block-scoping" "^7.28.5" + "@babel/plugin-transform-class-properties" "^7.27.1" + "@babel/plugin-transform-class-static-block" "^7.28.3" + "@babel/plugin-transform-classes" "^7.28.4" + "@babel/plugin-transform-computed-properties" "^7.27.1" + "@babel/plugin-transform-destructuring" "^7.28.5" + "@babel/plugin-transform-dotall-regex" "^7.27.1" + "@babel/plugin-transform-duplicate-keys" "^7.27.1" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.27.1" + "@babel/plugin-transform-dynamic-import" "^7.27.1" + "@babel/plugin-transform-explicit-resource-management" "^7.28.0" + "@babel/plugin-transform-exponentiation-operator" "^7.28.5" + "@babel/plugin-transform-export-namespace-from" "^7.27.1" + "@babel/plugin-transform-for-of" "^7.27.1" + "@babel/plugin-transform-function-name" "^7.27.1" + "@babel/plugin-transform-json-strings" "^7.27.1" + "@babel/plugin-transform-literals" "^7.27.1" + "@babel/plugin-transform-logical-assignment-operators" "^7.28.5" + "@babel/plugin-transform-member-expression-literals" "^7.27.1" + "@babel/plugin-transform-modules-amd" "^7.27.1" + "@babel/plugin-transform-modules-commonjs" "^7.27.1" + "@babel/plugin-transform-modules-systemjs" "^7.28.5" + "@babel/plugin-transform-modules-umd" "^7.27.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.27.1" + "@babel/plugin-transform-new-target" "^7.27.1" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.27.1" + "@babel/plugin-transform-numeric-separator" "^7.27.1" + "@babel/plugin-transform-object-rest-spread" "^7.28.4" + "@babel/plugin-transform-object-super" "^7.27.1" + "@babel/plugin-transform-optional-catch-binding" "^7.27.1" + "@babel/plugin-transform-optional-chaining" "^7.28.5" + "@babel/plugin-transform-parameters" "^7.27.7" + "@babel/plugin-transform-private-methods" "^7.27.1" + "@babel/plugin-transform-private-property-in-object" "^7.27.1" + "@babel/plugin-transform-property-literals" "^7.27.1" + "@babel/plugin-transform-regenerator" "^7.28.4" + "@babel/plugin-transform-regexp-modifiers" "^7.27.1" + "@babel/plugin-transform-reserved-words" "^7.27.1" + "@babel/plugin-transform-shorthand-properties" "^7.27.1" + "@babel/plugin-transform-spread" "^7.27.1" + "@babel/plugin-transform-sticky-regex" "^7.27.1" + "@babel/plugin-transform-template-literals" "^7.27.1" + "@babel/plugin-transform-typeof-symbol" "^7.27.1" + "@babel/plugin-transform-unicode-escapes" "^7.27.1" + "@babel/plugin-transform-unicode-property-regex" "^7.27.1" + "@babel/plugin-transform-unicode-regex" "^7.27.1" + "@babel/plugin-transform-unicode-sets-regex" "^7.27.1" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.14" + babel-plugin-polyfill-corejs3 "^0.13.0" + babel-plugin-polyfill-regenerator "^0.6.5" + core-js-compat "^3.43.0" + semver "^6.3.1" + +"@babel/preset-flow@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.27.1.tgz#3050ed7c619e8c4bfd0e0eeee87a2fa86a4bb1c6" + integrity sha512-ez3a2it5Fn6P54W8QkbfIyyIbxlXvcxyWHHvno1Wg0Ej5eiJY5hBb8ExttoIOJJk7V2dZE6prP7iby5q2aQ0Lg== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-option" "^7.27.1" + "@babel/plugin-transform-flow-strip-types" "^7.27.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.18.6", "@babel/preset-react@^7.22.15", "@babel/preset-react@^7.24.7": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.28.5.tgz#6fcc0400fa79698433d653092c3919bb4b0878d9" + integrity sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-option" "^7.27.1" + "@babel/plugin-transform-react-display-name" "^7.28.0" + "@babel/plugin-transform-react-jsx" "^7.27.1" + "@babel/plugin-transform-react-jsx-development" "^7.27.1" + "@babel/plugin-transform-react-pure-annotations" "^7.27.1" + +"@babel/preset-typescript@^7.16.7", "@babel/preset-typescript@^7.21.0", "@babel/preset-typescript@^7.23.0", "@babel/preset-typescript@^7.23.3", "@babel/preset-typescript@^7.24.7": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.28.5.tgz#540359efa3028236958466342967522fd8f2a60c" + integrity sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/helper-validator-option" "^7.27.1" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/plugin-transform-modules-commonjs" "^7.27.1" + "@babel/plugin-transform-typescript" "^7.28.5" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.25.0", "@babel/runtime@^7.26.10", "@babel/runtime@^7.26.9", "@babel/runtime@^7.27.6", "@babel/runtime@^7.6.2", "@babel/runtime@^7.8.7": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" + integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + +"@babel/runtime@^7.21.0", "@babel/runtime@^7.26.0": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.6.tgz#d267a43cb1836dc4d182cce93ae75ba954ef6d2b" + integrity sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA== + +"@babel/template@^7.0.0", "@babel/template@^7.25.0", "@babel/template@^7.27.1", "@babel/template@^7.27.2", "@babel/template@^7.3.3": + version "7.27.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" + integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/parser" "^7.27.2" + "@babel/types" "^7.27.1" + +"@babel/template@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57" + integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/parser" "^7.28.6" + "@babel/types" "^7.28.6" + +"@babel/traverse--for-generate-function-map@npm:@babel/traverse@^7.25.3": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.5.tgz#450cab9135d21a7a2ca9d2d35aa05c20e68c360b" + integrity sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.5" + debug "^4.3.1" + +"@babel/traverse@^7.20.0", "@babel/traverse@^7.25.3", "@babel/traverse@^7.27.1", "@babel/traverse@^7.28.0", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.4", "@babel/traverse@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.5.tgz#450cab9135d21a7a2ca9d2d35aa05c20e68c360b" + integrity sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.5" + debug "^4.3.1" + +"@babel/traverse@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.6.tgz#871ddc79a80599a5030c53b1cc48cbe3a5583c2e" + integrity sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg== + dependencies: + "@babel/code-frame" "^7.28.6" + "@babel/generator" "^7.28.6" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.6" + "@babel/template" "^7.28.6" + "@babel/types" "^7.28.6" + debug "^4.3.1" + +"@babel/types@^7.0.0", "@babel/types@^7.20.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.25.2", "@babel/types@^7.26.0", "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" + integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + +"@babel/types@^7.28.6": + version "7.28.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.6.tgz#c3e9377f1b155005bcc4c46020e7e394e13089df" + integrity sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" + +"@bam.tech/react-native-image-resizer@=3.0.11": + version "3.0.11" + resolved "https://registry.yarnpkg.com/@bam.tech/react-native-image-resizer/-/react-native-image-resizer-3.0.11.tgz#b9dc0f155b1293fe6d04944e45b6e3252ca2dea3" + integrity sha512-J/vAe51uPhJafT0uAIQI3gziqVs4Tnw32bHau/+I7AukSs4YxLXIaOVF6EChZ9ZFu+fLxvVrRTbHKDf+1YoXag== + +"@base-org/account@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@base-org/account/-/account-2.4.0.tgz#fb4ac1d1f7fed221de356a319d2eccf1c0a0cea4" + integrity sha512-A4Umpi8B9/pqR78D1Yoze4xHyQaujioVRqqO3d6xuDFw9VRtjg6tK3bPlwE0aW+nVH/ntllCpPa2PbI8Rnjcug== + dependencies: + "@coinbase/cdp-sdk" "^1.0.0" + "@noble/hashes" "1.4.0" + clsx "1.2.1" + eventemitter3 "5.0.1" + idb-keyval "6.2.1" + ox "0.6.9" + preact "10.24.2" + viem "^2.31.7" + zustand "5.0.3" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@chakra-ui/anatomy@2.3.6": + version "2.3.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/anatomy/-/anatomy-2.3.6.tgz#6913b95f1c65e234477ce924718aa191e69f4e46" + integrity sha512-TjmjyQouIZzha/l8JxdBZN1pKZTj7sLpJ0YkFnQFyqHcbfWggW9jKWzY1E0VBnhtFz/xF3KC6UAVuZVSJx+y0g== + +"@chakra-ui/hooks@2.4.5": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-2.4.5.tgz#3616e765117240286f073c3c543255a1e34c00a6" + integrity sha512-601fWfHE2i7UjaxK/9lDLlOni6vk/I+04YDbM0BrelJy+eqxdlOmoN8Z6MZ3PzFh7ofERUASor+vL+/HaCaZ7w== + dependencies: + "@chakra-ui/utils" "2.2.5" + "@zag-js/element-size" "0.31.1" + copy-to-clipboard "3.3.3" + framesync "6.1.2" + +"@chakra-ui/icons@^2.2.6": + version "2.2.6" + resolved "https://registry.yarnpkg.com/@chakra-ui/icons/-/icons-2.2.6.tgz#04e815ad344052e334866bc42ecf14b3705e73cf" + integrity sha512-WhNdb4hWMOhSGtgknV6INILg/sZDHFRJVwNRwO5B2JO4bPr+/9NPEf8jZuvcx5xMFi00qAC4qIvbMoN4ID0XDQ== + +"@chakra-ui/next-js@^2.4.4": + version "2.4.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/next-js/-/next-js-2.4.4.tgz#9b3b764e037c1687363f17afb57e07134d07f8a6" + integrity sha512-I7mDRaLQ98TZocjO6w9IRio8BDowNbTeR8/+ciRVr8xJy7UQBOpOHOhIUuzu2KyQ2RHKj/lA4vjHkdxlU6sHjw== + dependencies: + "@emotion/cache" "^11.14.0" + +"@chakra-ui/react@^2.10.9": + version "2.10.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-2.10.9.tgz#f268c83c435df09c96a8eafb066e76641057c24b" + integrity sha512-lhdcgoocOiURwBNR3L8OioCNIaGCZqRfuKioLyaQLjOanl4jr0PQclsGb+w0cmito252vEWpsz2xRqF7y+Flrw== + dependencies: + "@chakra-ui/hooks" "2.4.5" + "@chakra-ui/styled-system" "2.12.4" + "@chakra-ui/theme" "3.4.9" + "@chakra-ui/utils" "2.2.5" + "@popperjs/core" "^2.11.8" + "@zag-js/focus-visible" "^0.31.1" + aria-hidden "^1.2.3" + react-fast-compare "3.2.2" + react-focus-lock "^2.9.6" + react-remove-scroll "^2.5.7" + +"@chakra-ui/styled-system@2.12.4": + version "2.12.4" + resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.12.4.tgz#b6593a4e69809eb40bda7f6b37c1da23378b843b" + integrity sha512-oa07UG7Lic5hHSQtGRiMEnYjuhIa8lszyuVhZjZqR2Ap3VMF688y1MVPJ1pK+8OwY5uhXBgVd5c0+rI8aBZlwg== + dependencies: + "@chakra-ui/utils" "2.2.5" + csstype "^3.1.2" + +"@chakra-ui/theme-tools@2.2.9": + version "2.2.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-2.2.9.tgz#a74202d6f86239eaa208094800f9ff68efece8cb" + integrity sha512-PcbYL19lrVvEc7Oydy//jsy/MO/rZz1DvLyO6AoI+bI/+Kwz9WfOKsspbulEhRg5COayE0R/IZPsskXZ7Mp4bA== + dependencies: + "@chakra-ui/anatomy" "2.3.6" + "@chakra-ui/utils" "2.2.5" + color2k "^2.0.2" + +"@chakra-ui/theme@3.4.9": + version "3.4.9" + resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-3.4.9.tgz#eb678bfb3ddbde043fec5e929d081d6512c724eb" + integrity sha512-GAom2SjSdRWTcX76/2yJOFJsOWHQeBgaynCUNBsHq62OafzvELrsSHDUw0bBqBb1c2ww0CclIvGilPup8kXBFA== + dependencies: + "@chakra-ui/anatomy" "2.3.6" + "@chakra-ui/theme-tools" "2.2.9" + "@chakra-ui/utils" "2.2.5" + +"@chakra-ui/utils@2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-2.2.5.tgz#aa381aa7ad8e99fa2843e9602d06f6ad65befe6a" + integrity sha512-KTBCK+M5KtXH6p54XS39ImQUMVtAx65BoZDoEms3LuObyTo1+civ1sMm4h3nRT320U6H5H7D35WnABVQjqU/4g== + dependencies: + "@types/lodash.mergewith" "4.6.9" + lodash.mergewith "4.6.2" + +"@codemirror/autocomplete@^6.0.0": + version "6.19.1" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.19.1.tgz#355e49c9fd275b42a6e16e9ea0cf4361f67a3ec4" + integrity sha512-q6NenYkEy2fn9+JyjIxMWcNjzTL/IhwqfzOut1/G3PrIFkrbl4AL7Wkse5tLrQUUyqGoAKU5+Pi5jnnXxH5HGw== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + +"@codemirror/commands@^6.0.0", "@codemirror/commands@^6.1.0": + version "6.10.0" + resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.10.0.tgz#b3206984fec8443c4d910565eb2e9d591c7d80b2" + integrity sha512-2xUIc5mHXQzT16JnyOFkh8PvfeXuIut3pslWGfsGOhxP/lpgRm9HOl/mpzLErgt5mXDovqA0d11P21gofRLb9w== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.4.0" + "@codemirror/view" "^6.27.0" + "@lezer/common" "^1.1.0" + +"@codemirror/lang-javascript@^6.2.2": + version "6.2.4" + resolved "https://registry.yarnpkg.com/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz#eef2227d1892aae762f3a0f212f72bec868a02c5" + integrity sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/language" "^6.6.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + "@lezer/javascript" "^1.0.0" + +"@codemirror/language@^6.0.0", "@codemirror/language@^6.6.0": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.3.tgz#8e6632df566a7ed13a1bd307f9837765bb1abfdd" + integrity sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.23.0" + "@lezer/common" "^1.1.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + style-mod "^4.0.0" + +"@codemirror/lint@^6.0.0": + version "6.9.2" + resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.9.2.tgz#09ed0aedec13381c9e36e1ac5d126027740c3ef4" + integrity sha512-sv3DylBiIyi+xKwRCJAAsBZZZWo82shJ/RTMymLabAdtbkV5cSKwWDeCgtUq3v8flTaXS2y1kKkICuRYtUswyQ== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.35.0" + crelt "^1.0.5" + +"@codemirror/search@^6.0.0": + version "6.5.11" + resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.11.tgz#a324ffee36e032b7f67aa31c4fb9f3e6f9f3ed63" + integrity sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + crelt "^1.0.5" + +"@codemirror/state@^6.0.0", "@codemirror/state@^6.1.1", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" + integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== + dependencies: + "@marijn/find-cluster-break" "^1.0.0" + +"@codemirror/theme-one-dark@^6.0.0": + version "6.1.3" + resolved "https://registry.yarnpkg.com/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz#1dbb73f6e73c53c12ad2aed9f48c263c4e63ea37" + integrity sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + "@lezer/highlight" "^1.0.0" + +"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0": + version "6.38.6" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.38.6.tgz#25d9df071393801196c311025d2caa7a5523c26c" + integrity sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw== + dependencies: + "@codemirror/state" "^6.5.0" + crelt "^1.0.6" + style-mod "^4.1.0" + w3c-keyname "^2.2.4" + +"@coinbase/cdp-sdk@^1.0.0": + version "1.44.1" + resolved "https://registry.yarnpkg.com/@coinbase/cdp-sdk/-/cdp-sdk-1.44.1.tgz#a6acbfabfea2cfae854cbe4479c2dab559b35f6b" + integrity sha512-O7sikX7gTZdF4xy9b0xAMPOKWk8z6E7an4EGVBukPdfChooBL15Zt6B8Wn5th/LC1V1nIf3J/tlTTQCJLkKZ6A== + dependencies: + "@solana-program/system" "^0.10.0" + "@solana-program/token" "^0.9.0" + "@solana/kit" "^5.1.0" + "@solana/web3.js" "^1.98.1" + abitype "1.0.6" + axios "^1.12.2" + axios-retry "^4.5.0" + jose "^6.0.8" + md5 "^2.3.0" + uncrypto "^0.1.3" + viem "^2.21.26" + zod "^3.24.4" + +"@coinbase/wallet-mobile-sdk@polybase/wallet-mobile-sdk#react-native-npm": + version "1.1.2" + resolved "https://codeload.github.com/polybase/wallet-mobile-sdk/tar.gz/dfe2bfddce4bb7a6e379dbaac6a7628de6c77191" + dependencies: + "@metamask/safe-event-emitter" "2.0.0" + bn.js "5.2.1" + buffer "6.0.3" + eth-rpc-errors "4.0.3" + events "^3.0.0" + react-native-mmkv "^2.11.0" + +"@coinbase/wallet-sdk@4.3.6": + version "4.3.6" + resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-4.3.6.tgz#bf9935fea404ecaa4aa5f00ea508fa01c007b3a8" + integrity sha512-4q8BNG1ViL4mSAAvPAtpwlOs1gpC+67eQtgIwNvT3xyeyFFd+guwkc8bcX5rTmQhXpqnhzC4f0obACbP9CqMSA== + dependencies: + "@noble/hashes" "1.4.0" + clsx "1.2.1" + eventemitter3 "5.0.1" + idb-keyval "6.2.1" + ox "0.6.9" + preact "10.24.2" + viem "^2.27.2" + zustand "5.0.3" + +"@craftzdog/react-native-buffer@6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@craftzdog/react-native-buffer/-/react-native-buffer-6.1.0.tgz#101d09d4eb5fa06b12453313b173d5036d96462f" + integrity sha512-lJXdjZ7fTllLbzDrwg/FrJLjQ5sBcAgwcqgAB6OPpXTHdCenEhHZblQpfmBLLe7/S7m0yKXL3kN3jpwOEkpjGg== + dependencies: + ieee754 "^1.2.1" + react-native-quick-base64 "^2.0.5" + +"@ecies/ciphers@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@ecies/ciphers/-/ciphers-0.2.5.tgz#754ff2f821645f0465d18a1a68198eb15d16c2a0" + integrity sha512-GalEZH4JgOMHYYcYmVqnFirFsjZHeoGMDt9IxEnM9F7GRUUyUksJ7Ou53L83WHJq3RWKD3AcBpo0iQh0oMpf8A== + +"@egjs/hammerjs@^2.0.17": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@egjs/hammerjs/-/hammerjs-2.0.17.tgz#5dc02af75a6a06e4c2db0202cae38c9263895124" + integrity sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A== + dependencies: + "@types/hammerjs" "^2.0.36" + +"@emnapi/core@^1.4.3": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.7.0.tgz#135de4e8858763989112281bdf38ca02439db7c3" + integrity sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw== + dependencies: + "@emnapi/wasi-threads" "1.1.0" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.7.0.tgz#d7ef3832df8564fe5903bf0567aedbd19538ecbe" + integrity sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q== + dependencies: + tslib "^2.4.0" + +"@emnapi/runtime@^1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.7.1.tgz#a73784e23f5d57287369c808197288b52276b791" + integrity sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + +"@emotion/babel-plugin@^11.13.5": + version "11.13.5" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz#eab8d65dbded74e0ecfd28dc218e75607c4e7bc0" + integrity sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ== + dependencies: + "@babel/helper-module-imports" "^7.16.7" + "@babel/runtime" "^7.18.3" + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/serialize" "^1.3.3" + babel-plugin-macros "^3.1.0" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.2.0" + +"@emotion/cache@^11.14.0": + version "11.14.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.14.0.tgz#ee44b26986eeb93c8be82bb92f1f7a9b21b2ed76" + integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA== + dependencies: + "@emotion/memoize" "^0.9.0" + "@emotion/sheet" "^1.4.0" + "@emotion/utils" "^1.4.2" + "@emotion/weak-memoize" "^0.4.0" + stylis "4.2.0" + +"@emotion/hash@^0.9.2": + version "0.9.2" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b" + integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g== + +"@emotion/is-prop-valid@^1.3.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz#e9ad47adff0b5c94c72db3669ce46de33edf28c0" + integrity sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw== + dependencies: + "@emotion/memoize" "^0.9.0" + +"@emotion/memoize@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102" + integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ== + +"@emotion/react@^11.11.4": + version "11.14.0" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.14.0.tgz#cfaae35ebc67dd9ef4ea2e9acc6cd29e157dd05d" + integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.13.5" + "@emotion/cache" "^11.14.0" + "@emotion/serialize" "^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0" + "@emotion/utils" "^1.4.2" + "@emotion/weak-memoize" "^0.4.0" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.3.tgz#d291531005f17d704d0463a032fe679f376509e8" + integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA== + dependencies: + "@emotion/hash" "^0.9.2" + "@emotion/memoize" "^0.9.0" + "@emotion/unitless" "^0.10.0" + "@emotion/utils" "^1.4.2" + csstype "^3.0.2" + +"@emotion/sheet@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c" + integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg== + +"@emotion/styled@^11.11.0": + version "11.14.1" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.14.1.tgz#8c34bed2948e83e1980370305614c20955aacd1c" + integrity sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw== + dependencies: + "@babel/runtime" "^7.18.3" + "@emotion/babel-plugin" "^11.13.5" + "@emotion/is-prop-valid" "^1.3.0" + "@emotion/serialize" "^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.2.0" + "@emotion/utils" "^1.4.2" + +"@emotion/unitless@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745" + integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg== + +"@emotion/use-insertion-effect-with-fallbacks@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz#8a8cb77b590e09affb960f4ff1e9a89e532738bf" + integrity sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg== + +"@emotion/utils@^1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.2.tgz#6df6c45881fcb1c412d6688a311a98b7f59c1b52" + integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA== + +"@emotion/weak-memoize@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6" + integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg== + +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/aix-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz#80fcbe36130e58b7670511e888b8e88a259ed76c" + integrity sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz#8aa4965f8d0a7982dc21734bf6601323a66da752" + integrity sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.12.tgz#300712101f7f50f1d2627a162e6e09b109b6767a" + integrity sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/android-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.12.tgz#87dfb27161202bdc958ef48bb61b09c758faee16" + integrity sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz#79197898ec1ff745d21c071e1c7cc3c802f0c1fd" + integrity sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/darwin-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz#146400a8562133f45c4d2eadcf37ddd09718079e" + integrity sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz#1c5f9ba7206e158fd2b24c59fa2d2c8bb47ca0fe" + integrity sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/freebsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz#ea631f4a36beaac4b9279fa0fcc6ca29eaeeb2b3" + integrity sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz#e1066bce58394f1b1141deec8557a5f0a22f5977" + integrity sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-arm@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz#452cd66b20932d08bdc53a8b61c0e30baf4348b9" + integrity sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz#b24f8acc45bcf54192c7f2f3be1b53e6551eafe0" + integrity sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-loong64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz#f9cfffa7fc8322571fbc4c8b3268caf15bd81ad0" + integrity sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-mips64el@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz#575a14bd74644ffab891adc7d7e60d275296f2cd" + integrity sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-ppc64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz#75b99c70a95fbd5f7739d7692befe60601591869" + integrity sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-riscv64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz#2e3259440321a44e79ddf7535c325057da875cd6" + integrity sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-s390x@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz#17676cabbfe5928da5b2a0d6df5d58cd08db2663" + integrity sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz#0583775685ca82066d04c3507f09524d3cd7a306" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@esbuild/netbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz#f04c4049cb2e252fe96b16fed90f70746b13f4a4" + integrity sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/netbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz#77da0d0a0d826d7c921eea3d40292548b258a076" + integrity sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ== + +"@esbuild/openbsd-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz#6296f5867aedef28a81b22ab2009c786a952dccd" + integrity sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/openbsd-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz#f8d23303360e27b16cf065b23bbff43c14142679" + integrity sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw== + +"@esbuild/openharmony-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz#49e0b768744a3924be0d7fd97dd6ce9b2923d88d" + integrity sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/sunos-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz#a6ed7d6778d67e528c81fb165b23f4911b9b13d6" + integrity sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-arm64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz#9ac14c378e1b653af17d08e7d3ce34caef587323" + integrity sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-ia32@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz#918942dcbbb35cc14fca39afb91b5e6a3d127267" + integrity sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + +"@esbuild/win32-x64@0.25.12": + version "0.25.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz#9bdad8176be7811ad148d1f8772359041f46c6c5" + integrity sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA== + +"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.5.0", "@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.8.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0", "@eslint-community/regexpp@^4.12.1": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== + +"@eslint/compat@^1.3.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@eslint/compat/-/compat-1.4.1.tgz#81eaabb3e0b080350582c1a8092a2d355fabf03e" + integrity sha512-cfO82V9zxxGBxcQDr1lfaYB7wykTa0b00mGa36FrJl7iTFd0Z2cHfEYuxcBRP/iNijCsWsEkA+jzT8hGYmv33w== + dependencies: + "@eslint/core" "^0.17.0" + +"@eslint/config-array@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" + integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== + dependencies: + "@eslint/object-schema" "^2.1.7" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== + dependencies: + "@eslint/core" "^0.17.0" + +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.2.0", "@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.39.1", "@eslint/js@^9.18.0": + version "9.39.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.1.tgz#0dd59c3a9f40e3f1882975c321470969243e0164" + integrity sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw== + +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== + +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== + dependencies: + "@eslint/core" "^0.17.0" + levn "^0.4.1" + +"@ethereumjs/common@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-3.2.0.tgz#b71df25845caf5456449163012074a55f048e0a0" + integrity sha512-pksvzI0VyLgmuEF2FA/JR/4/y6hcPq8OUail3/AvycBaW1d5VSauOZzqGvJ3RTmR4MU35lWE8KseKOsEhrFRBA== + dependencies: + "@ethereumjs/util" "^8.1.0" + crc-32 "^1.2.0" + +"@ethereumjs/rlp@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-4.0.1.tgz#626fabfd9081baab3d0a3074b0c7ecaf674aaa41" + integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== + +"@ethereumjs/tx@^4.1.2", "@ethereumjs/tx@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-4.2.0.tgz#5988ae15daf5a3b3c815493bc6b495e76009e853" + integrity sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw== + dependencies: + "@ethereumjs/common" "^3.2.0" + "@ethereumjs/rlp" "^4.0.1" + "@ethereumjs/util" "^8.1.0" + ethereum-cryptography "^2.0.0" + +"@ethereumjs/util@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-8.1.0.tgz#299df97fb6b034e0577ce9f94c7d9d1004409ed4" + integrity sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA== + dependencies: + "@ethereumjs/rlp" "^4.0.1" + ethereum-cryptography "^2.0.0" + micro-ftch "^0.3.1" + +"@ethersproject/abstract-provider@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz#7581f9be601afa1d02b95d26b9d9840926a35b0c" + integrity sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/networks" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/web" "^5.8.0" + +"@ethersproject/abstract-signer@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz#8d7417e95e4094c1797a9762e6789c7356db0754" + integrity sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA== + dependencies: + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + +"@ethersproject/address@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.8.0.tgz#3007a2c352eee566ad745dca1dbbebdb50a6a983" + integrity sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + +"@ethersproject/base64@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.8.0.tgz#61c669c648f6e6aad002c228465d52ac93ee83eb" + integrity sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ== + dependencies: + "@ethersproject/bytes" "^5.8.0" + +"@ethersproject/basex@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.8.0.tgz#1d279a90c4be84d1c1139114a1f844869e57d03a" + integrity sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + +"@ethersproject/bignumber@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.8.0.tgz#c381d178f9eeb370923d389284efa19f69efa5d7" + integrity sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + bn.js "^5.2.1" + +"@ethersproject/bytes@^5.7.0", "@ethersproject/bytes@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.8.0.tgz#9074820e1cac7507a34372cadeb035461463be34" + integrity sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/constants@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.8.0.tgz#12f31c2f4317b113a4c19de94e50933648c90704" + integrity sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + +"@ethersproject/hash@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.8.0.tgz#b8893d4629b7f8462a90102572f8cd65a0192b4c" + integrity sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/hdnode@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.8.0.tgz#a51ae2a50bcd48ef6fd108c64cbae5e6ff34a761" + integrity sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/basex" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/pbkdf2" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/wordlists" "^5.8.0" + +"@ethersproject/json-wallets@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz#d18de0a4cf0f185f232eb3c17d5e0744d97eb8c9" + integrity sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w== + dependencies: + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/hdnode" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/pbkdf2" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/random" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@^5.7.0", "@ethersproject/keccak256@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.8.0.tgz#d2123a379567faf2d75d2aaea074ffd4df349e6a" + integrity sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng== + dependencies: + "@ethersproject/bytes" "^5.8.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.8.0.tgz#f0232968a4f87d29623a0481690a2732662713d6" + integrity sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA== + +"@ethersproject/networks@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.8.0.tgz#8b4517a3139380cba9fb00b63ffad0a979671fde" + integrity sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/pbkdf2@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz#cd2621130e5dd51f6a0172e63a6e4a0c0a0ec37e" + integrity sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/sha2" "^5.8.0" + +"@ethersproject/properties@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.8.0.tgz#405a8affb6311a49a91dabd96aeeae24f477020e" + integrity sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw== + dependencies: + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/random@^5.7.0", "@ethersproject/random@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.8.0.tgz#1bced04d49449f37c6437c701735a1a022f0057a" + integrity sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/rlp@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.8.0.tgz#5a0d49f61bc53e051532a5179472779141451de5" + integrity sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/sha2@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.8.0.tgz#8954a613bb78dac9b46829c0a95de561ef74e5e1" + integrity sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@^5.7.0", "@ethersproject/signing-key@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.8.0.tgz#9797e02c717b68239c6349394ea85febf8893119" + integrity sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + bn.js "^5.2.1" + elliptic "6.6.1" + hash.js "1.1.7" + +"@ethersproject/strings@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.8.0.tgz#ad79fafbf0bd272d9765603215ac74fd7953908f" + integrity sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/transactions@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.8.0.tgz#1e518822403abc99def5a043d1c6f6fe0007e46b" + integrity sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg== + dependencies: + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/rlp" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + +"@ethersproject/units@^5.7.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.8.0.tgz#c12f34ba7c3a2de0e9fa0ed0ee32f3e46c5c2c6a" + integrity sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ== + dependencies: + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/constants" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + +"@ethersproject/wallet@^5.7.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.8.0.tgz#49c300d10872e6986d953e8310dc33d440da8127" + integrity sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA== + dependencies: + "@ethersproject/abstract-provider" "^5.8.0" + "@ethersproject/abstract-signer" "^5.8.0" + "@ethersproject/address" "^5.8.0" + "@ethersproject/bignumber" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/hdnode" "^5.8.0" + "@ethersproject/json-wallets" "^5.8.0" + "@ethersproject/keccak256" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/random" "^5.8.0" + "@ethersproject/signing-key" "^5.8.0" + "@ethersproject/transactions" "^5.8.0" + "@ethersproject/wordlists" "^5.8.0" + +"@ethersproject/web@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.8.0.tgz#3e54badc0013b7a801463a7008a87988efce8a37" + integrity sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw== + dependencies: + "@ethersproject/base64" "^5.8.0" + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@ethersproject/wordlists@^5.8.0": + version "5.8.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.8.0.tgz#7a5654ee8d1bb1f4dbe43f91d217356d650ad821" + integrity sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg== + dependencies: + "@ethersproject/bytes" "^5.8.0" + "@ethersproject/hash" "^5.8.0" + "@ethersproject/logger" "^5.8.0" + "@ethersproject/properties" "^5.8.0" + "@ethersproject/strings" "^5.8.0" + +"@expo/cli@54.0.16": + version "54.0.16" + resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-54.0.16.tgz#62e49a7a2f790cdd412731dab980b38bf69f21db" + integrity sha512-hY/OdRaJMs5WsVPuVSZ+RLH3VObJmL/pv5CGCHEZHN2PxZjSZSdctyKV8UcFBXTF0yIKNAJ9XLs1dlNYXHh4Cw== + dependencies: + "@0no-co/graphql.web" "^1.0.8" + "@expo/code-signing-certificates" "^0.0.5" + "@expo/config" "~12.0.10" + "@expo/config-plugins" "~54.0.2" + "@expo/devcert" "^1.1.2" + "@expo/env" "~2.0.7" + "@expo/image-utils" "^0.8.7" + "@expo/json-file" "^10.0.7" + "@expo/mcp-tunnel" "~0.1.0" + "@expo/metro" "~54.1.0" + "@expo/metro-config" "~54.0.9" + "@expo/osascript" "^2.3.7" + "@expo/package-manager" "^1.9.8" + "@expo/plist" "^0.4.7" + "@expo/prebuild-config" "^54.0.6" + "@expo/schema-utils" "^0.1.7" + "@expo/spawn-async" "^1.7.2" + "@expo/ws-tunnel" "^1.0.1" + "@expo/xcpretty" "^4.3.0" + "@react-native/dev-middleware" "0.81.5" + "@urql/core" "^5.0.6" + "@urql/exchange-retry" "^1.3.0" + accepts "^1.3.8" + arg "^5.0.2" + better-opn "~3.0.2" + bplist-creator "0.1.0" + bplist-parser "^0.3.1" + chalk "^4.0.0" + ci-info "^3.3.0" + compression "^1.7.4" + connect "^3.7.0" + debug "^4.3.4" + env-editor "^0.4.1" + expo-server "^1.0.4" + freeport-async "^2.0.0" + getenv "^2.0.0" + glob "^10.4.2" + lan-network "^0.1.6" + minimatch "^9.0.0" + node-forge "^1.3.1" + npm-package-arg "^11.0.0" + ora "^3.4.0" + picomatch "^3.0.1" + pretty-bytes "^5.6.0" + pretty-format "^29.7.0" + progress "^2.0.3" + prompts "^2.3.2" + qrcode-terminal "0.11.0" + require-from-string "^2.0.2" + requireg "^0.2.2" + resolve "^1.22.2" + resolve-from "^5.0.0" + resolve.exports "^2.0.3" + semver "^7.6.0" + send "^0.19.0" + slugify "^1.3.4" + source-map-support "~0.5.21" + stacktrace-parser "^0.1.10" + structured-headers "^0.4.1" + tar "^7.4.3" + terminal-link "^2.1.1" + undici "^6.18.2" + wrap-ansi "^7.0.0" + ws "^8.12.1" + +"@expo/code-signing-certificates@0.0.5", "@expo/code-signing-certificates@^0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@expo/code-signing-certificates/-/code-signing-certificates-0.0.5.tgz#a693ff684fb20c4725dade4b88a6a9f96b02496c" + integrity sha512-BNhXkY1bblxKZpltzAx98G2Egj9g1Q+JRcvR7E99DOj862FTCX+ZPsAUtPTr7aHxwtrL7+fL3r0JSmM9kBm+Bw== + dependencies: + node-forge "^1.2.1" + nullthrows "^1.1.1" + +"@expo/config-plugins@~10.1.2": + version "10.1.2" + resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-10.1.2.tgz#6efa256a3fa2fca116eeb5bef8b22b089e287282" + integrity sha512-IMYCxBOcnuFStuK0Ay+FzEIBKrwW8OVUMc65+v0+i7YFIIe8aL342l7T4F8lR4oCfhXn7d6M5QPgXvjtc/gAcw== + dependencies: + "@expo/config-types" "^53.0.5" + "@expo/json-file" "~9.1.5" + "@expo/plist" "^0.3.5" + "@expo/sdk-runtime-versions" "^1.0.0" + chalk "^4.1.2" + debug "^4.3.5" + getenv "^2.0.0" + glob "^10.4.2" + resolve-from "^5.0.0" + semver "^7.5.4" + slash "^3.0.0" + slugify "^1.6.6" + xcode "^3.0.1" + xml2js "0.6.0" + +"@expo/config-plugins@~54.0.2": + version "54.0.2" + resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-54.0.2.tgz#4760319898e1a55c0d039adaee1360cff147d454" + integrity sha512-jD4qxFcURQUVsUFGMcbo63a/AnviK8WUGard+yrdQE3ZrB/aurn68SlApjirQQLEizhjI5Ar2ufqflOBlNpyPg== + dependencies: + "@expo/config-types" "^54.0.8" + "@expo/json-file" "~10.0.7" + "@expo/plist" "^0.4.7" + "@expo/sdk-runtime-versions" "^1.0.0" + chalk "^4.1.2" + debug "^4.3.5" + getenv "^2.0.0" + glob "^10.4.2" + resolve-from "^5.0.0" + semver "^7.5.4" + slash "^3.0.0" + slugify "^1.6.6" + xcode "^3.0.1" + xml2js "0.6.0" + +"@expo/config-plugins@~7.2.5": + version "7.2.5" + resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-7.2.5.tgz#b15f22878975fdc4ddcfa8cdc971937ddc4c0249" + integrity sha512-w+5ccu1IxBHgyQk9CPFKLZOk8yZQEyTjbJwOzESK1eR7QwosbcsLkN1c1WWUZYiCXwORu3UTwJYll4+X2xxJhQ== + dependencies: + "@expo/config-types" "^49.0.0-alpha.1" + "@expo/json-file" "~8.2.37" + "@expo/plist" "^0.0.20" + "@expo/sdk-runtime-versions" "^1.0.0" + "@react-native/normalize-color" "^2.0.0" + chalk "^4.1.2" + debug "^4.3.1" + find-up "~5.0.0" + getenv "^1.0.0" + glob "7.1.6" + resolve-from "^5.0.0" + semver "^7.5.3" + slash "^3.0.0" + xcode "^3.0.1" + xml2js "0.6.0" + +"@expo/config-types@^49.0.0-alpha.1": + version "49.0.0" + resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-49.0.0.tgz#15ffef715285c06703f6fb7ec0cda853f645cc09" + integrity sha512-8eyREVi+K2acnMBe/rTIu1dOfyR2+AMnTLHlut+YpMV9OZPdeKV0Bs9BxAewGqBA2slslbQ9N39IS2CuTKpXkA== + +"@expo/config-types@^53.0.5": + version "53.0.5" + resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-53.0.5.tgz#bba7e0712c2c5b1d8963348d68ea96339f858db4" + integrity sha512-kqZ0w44E+HEGBjy+Lpyn0BVL5UANg/tmNixxaRMLS6nf37YsDrLk2VMAmeKMMk5CKG0NmOdVv3ngeUjRQMsy9g== + +"@expo/config-types@^54.0.8": + version "54.0.8" + resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-54.0.8.tgz#2aa1f96e0abad6a125d0ff1092b303280f7962e9" + integrity sha512-lyIn/x/Yz0SgHL7IGWtgTLg6TJWC9vL7489++0hzCHZ4iGjVcfZmPTUfiragZ3HycFFj899qN0jlhl49IHa94A== + +"@expo/config@~11.0.13": + version "11.0.13" + resolved "https://registry.yarnpkg.com/@expo/config/-/config-11.0.13.tgz#1cc490a5f667e0129db5f98755f6bc4d8921edb2" + integrity sha512-TnGb4u/zUZetpav9sx/3fWK71oCPaOjZHoVED9NaEncktAd0Eonhq5NUghiJmkUGt3gGSjRAEBXiBbbY9/B1LA== + dependencies: + "@babel/code-frame" "~7.10.4" + "@expo/config-plugins" "~10.1.2" + "@expo/config-types" "^53.0.5" + "@expo/json-file" "^9.1.5" + deepmerge "^4.3.1" + getenv "^2.0.0" + glob "^10.4.2" + require-from-string "^2.0.2" + resolve-from "^5.0.0" + resolve-workspace-root "^2.0.0" + semver "^7.6.0" + slugify "^1.3.4" + sucrase "3.35.0" + +"@expo/config@~12.0.10", "@expo/config@~12.0.8": + version "12.0.10" + resolved "https://registry.yarnpkg.com/@expo/config/-/config-12.0.10.tgz#18acc0a2d5994dc167d1d4faca3e939de2bb95de" + integrity sha512-lJMof5Nqakq1DxGYlghYB/ogSBjmv4Fxn1ovyDmcjlRsQdFCXgu06gEUogkhPtc9wBt9WlTTfqENln5HHyLW6w== + dependencies: + "@babel/code-frame" "~7.10.4" + "@expo/config-plugins" "~54.0.2" + "@expo/config-types" "^54.0.8" + "@expo/json-file" "^10.0.7" + deepmerge "^4.3.1" + getenv "^2.0.0" + glob "^10.4.2" + require-from-string "^2.0.2" + resolve-from "^5.0.0" + resolve-workspace-root "^2.0.0" + semver "^7.6.0" + slugify "^1.3.4" + sucrase "3.35.0" + +"@expo/devcert@^1.1.2": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@expo/devcert/-/devcert-1.2.0.tgz#7b32c2d959e36baaa0649433395e5170c808b44f" + integrity sha512-Uilcv3xGELD5t/b0eM4cxBFEKQRIivB3v7i+VhWLV/gL98aw810unLKKJbGAxAIhY6Ipyz8ChWibFsKFXYwstA== + dependencies: + "@expo/sudo-prompt" "^9.3.1" + debug "^3.1.0" + glob "^10.4.2" + +"@expo/devtools@0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@expo/devtools/-/devtools-0.1.7.tgz#bf4f552168ebd44c9fe63941bc4806fe2d222899" + integrity sha512-dfIa9qMyXN+0RfU6SN4rKeXZyzKWsnz6xBSDccjL4IRiE+fQ0t84zg0yxgN4t/WK2JU5v6v4fby7W7Crv9gJvA== + dependencies: + chalk "^4.1.2" + +"@expo/env@~2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@expo/env/-/env-2.0.7.tgz#7b30d3ef9f262c131ac01d8e539e37dd04b8f4bd" + integrity sha512-BNETbLEohk3HQ2LxwwezpG8pq+h7Fs7/vAMP3eAtFT1BCpprLYoBBFZH7gW4aqGfqOcVP4Lc91j014verrYNGg== + dependencies: + chalk "^4.0.0" + debug "^4.3.4" + dotenv "~16.4.5" + dotenv-expand "~11.0.6" + getenv "^2.0.0" + +"@expo/fingerprint@0.15.3": + version "0.15.3" + resolved "https://registry.yarnpkg.com/@expo/fingerprint/-/fingerprint-0.15.3.tgz#26e7231d1ebd69a375c02ba595bba7b06fe882bb" + integrity sha512-8YPJpEYlmV171fi+t+cSLMX1nC5ngY9j2FiN70dHldLpd6Ct6ouGhk96svJ4BQZwsqwII2pokwzrDAwqo4Z0FQ== + dependencies: + "@expo/spawn-async" "^1.7.2" + arg "^5.0.2" + chalk "^4.1.2" + debug "^4.3.4" + getenv "^2.0.0" + glob "^10.4.2" + ignore "^5.3.1" + minimatch "^9.0.0" + p-limit "^3.1.0" + resolve-from "^5.0.0" + semver "^7.6.0" + +"@expo/html-elements@latest": + version "0.13.7" + resolved "https://registry.yarnpkg.com/@expo/html-elements/-/html-elements-0.13.7.tgz#c88d958f03c2b1e44a74891962761878fc7f6592" + integrity sha512-VsKHJV4ZP3aFIHprzMhh+8DpKv999k9BZTyj/NbzOQY7sDdw/XfhsYM1mdJZdjbxHbecbl7oCw+LE4O9kaA3BQ== + +"@expo/image-utils@^0.8.7": + version "0.8.7" + resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.8.7.tgz#3e765005def8a4e5533155b0042e053ebfafc9d2" + integrity sha512-SXOww4Wq3RVXLyOaXiCCuQFguCDh8mmaHBv54h/R29wGl4jRY8GEyQEx8SypV/iHt1FbzsU/X3Qbcd9afm2W2w== + dependencies: + "@expo/spawn-async" "^1.7.2" + chalk "^4.0.0" + getenv "^2.0.0" + jimp-compact "0.16.1" + parse-png "^2.1.0" + resolve-from "^5.0.0" + resolve-global "^1.0.0" + semver "^7.6.0" + temp-dir "~2.0.0" + unique-string "~2.0.0" + +"@expo/json-file@^10.0.7", "@expo/json-file@~10.0.7": + version "10.0.7" + resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-10.0.7.tgz#e4f58fdc03fc62f13610eeafe086d84e6e44fe01" + integrity sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw== + dependencies: + "@babel/code-frame" "~7.10.4" + json5 "^2.2.3" + +"@expo/json-file@^9.1.5", "@expo/json-file@~9.1.5": + version "9.1.5" + resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-9.1.5.tgz#7d7b2dc4990dc2c2de69a571191aba984b7fb7ed" + integrity sha512-prWBhLUlmcQtvN6Y7BpW2k9zXGd3ySa3R6rAguMJkp1z22nunLN64KYTUWfijFlprFoxm9r2VNnGkcbndAlgKA== + dependencies: + "@babel/code-frame" "~7.10.4" + json5 "^2.2.3" + +"@expo/json-file@~8.2.37": + version "8.2.37" + resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.37.tgz#9c02d3b42134907c69cc0a027b18671b69344049" + integrity sha512-YaH6rVg11JoTS2P6LsW7ybS2CULjf40AbnAHw2F1eDPuheprNjARZMnyHFPkKv7GuxCy+B9GPcbOKgc4cgA80Q== + dependencies: + "@babel/code-frame" "~7.10.4" + json5 "^2.2.2" + write-file-atomic "^2.3.0" + +"@expo/mcp-tunnel@~0.1.0": + version "0.1.0" + resolved "https://registry.yarnpkg.com/@expo/mcp-tunnel/-/mcp-tunnel-0.1.0.tgz#ae4ce4320b2f97a9891783c2316f9936c912d126" + integrity sha512-rJ6hl0GnIZj9+ssaJvFsC7fwyrmndcGz+RGFzu+0gnlm78X01957yjtHgjcmnQAgL5hWEOR6pkT0ijY5nU5AWw== + dependencies: + ws "^8.18.3" + zod "^3.25.76" + zod-to-json-schema "^3.24.6" + +"@expo/metro-config@54.0.9", "@expo/metro-config@~54.0.9": + version "54.0.9" + resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-54.0.9.tgz#e3d8cecb803d536ee80de0e844a5768773d34b0f" + integrity sha512-CRI4WgFXrQ2Owyr8q0liEBJveUIF9DcYAKadMRsJV7NxGNBdrIIKzKvqreDfsGiRqivbLsw6UoNb3UE7/SvPfg== + dependencies: + "@babel/code-frame" "^7.20.0" + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.5" + "@expo/config" "~12.0.10" + "@expo/env" "~2.0.7" + "@expo/json-file" "~10.0.7" + "@expo/metro" "~54.1.0" + "@expo/spawn-async" "^1.7.2" + browserslist "^4.25.0" + chalk "^4.1.0" + debug "^4.3.2" + dotenv "~16.4.5" + dotenv-expand "~11.0.6" + getenv "^2.0.0" + glob "^10.4.2" + hermes-parser "^0.29.1" + jsc-safe-url "^0.2.4" + lightningcss "^1.30.1" + minimatch "^9.0.0" + postcss "~8.4.32" + resolve-from "^5.0.0" + +"@expo/metro@~54.1.0": + version "54.1.0" + resolved "https://registry.yarnpkg.com/@expo/metro/-/metro-54.1.0.tgz#27765ef2c342c39086a2f5c9f932a375dc2ccad3" + integrity sha512-MgdeRNT/LH0v1wcO0TZp9Qn8zEF0X2ACI0wliPtv5kXVbXWI+yK9GyrstwLAiTXlULKVIg3HVSCCvmLu0M3tnw== + dependencies: + metro "0.83.2" + metro-babel-transformer "0.83.2" + metro-cache "0.83.2" + metro-cache-key "0.83.2" + metro-config "0.83.2" + metro-core "0.83.2" + metro-file-map "0.83.2" + metro-resolver "0.83.2" + metro-runtime "0.83.2" + metro-source-map "0.83.2" + metro-transform-plugins "0.83.2" + metro-transform-worker "0.83.2" + +"@expo/npm-proofread@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@expo/npm-proofread/-/npm-proofread-1.0.1.tgz#8450f71cea47dd9864d61a1a105931dc7ea2209a" + integrity sha512-yDyBlNIgg+rKoKCOVM9ZyAtgqRx6gHw+JtmZTrYYW4auAfwS6kE/iInmCpVXPqRy0OhJHgXj6q5PCgWELLVMeg== + dependencies: + semver "^5.3.0" + +"@expo/osascript@^2.3.7": + version "2.3.7" + resolved "https://registry.yarnpkg.com/@expo/osascript/-/osascript-2.3.7.tgz#2d53ef06733593405c83767de7420510736e0fa9" + integrity sha512-IClSOXxR0YUFxIriUJVqyYki7lLMIHrrzOaP01yxAL1G8pj2DWV5eW1y5jSzIcIfSCNhtGsshGd1tU/AYup5iQ== + dependencies: + "@expo/spawn-async" "^1.7.2" + exec-async "^2.2.0" + +"@expo/package-manager@^1.9.8": + version "1.9.8" + resolved "https://registry.yarnpkg.com/@expo/package-manager/-/package-manager-1.9.8.tgz#8f6b46a2f5f4bf4f2c78507b1a7a368e0c2e2126" + integrity sha512-4/I6OWquKXYnzo38pkISHCOCOXxfeEmu4uDoERq1Ei/9Ur/s9y3kLbAamEkitUkDC7gHk1INxRWEfFNzGbmOrA== + dependencies: + "@expo/json-file" "^10.0.7" + "@expo/spawn-async" "^1.7.2" + chalk "^4.0.0" + npm-package-arg "^11.0.0" + ora "^3.4.0" + resolve-workspace-root "^2.0.0" + +"@expo/plist@^0.0.20": + version "0.0.20" + resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.0.20.tgz#a6b3124438031c02b762bad5a47b70584d3c0072" + integrity sha512-UXQ4LXCfTZ580LDHGJ5q62jSTwJFFJ1GqBu8duQMThiHKWbMJ+gajJh6rsB6EJ3aLUr9wcauxneL5LVRFxwBEA== + dependencies: + "@xmldom/xmldom" "~0.7.7" + base64-js "^1.2.3" + xmlbuilder "^14.0.0" + +"@expo/plist@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.3.5.tgz#11913c64951936101529cb26d7260ef16970fc31" + integrity sha512-9RYVU1iGyCJ7vWfg3e7c/NVyMFs8wbl+dMWZphtFtsqyN9zppGREU3ctlD3i8KUE0sCUTVnLjCWr+VeUIDep2g== + dependencies: + "@xmldom/xmldom" "^0.8.8" + base64-js "^1.2.3" + xmlbuilder "^15.1.1" + +"@expo/plist@^0.4.7": + version "0.4.7" + resolved "https://registry.yarnpkg.com/@expo/plist/-/plist-0.4.7.tgz#40fa796e93d5be0452ce72e5110e69c8ac915403" + integrity sha512-dGxqHPvCZKeRKDU1sJZMmuyVtcASuSYh1LPFVaM1DuffqPL36n6FMEL0iUqq2Tx3xhWk8wCnWl34IKplUjJDdA== + dependencies: + "@xmldom/xmldom" "^0.8.8" + base64-js "^1.2.3" + xmlbuilder "^15.1.1" + +"@expo/prebuild-config@^54.0.3", "@expo/prebuild-config@^54.0.6": + version "54.0.6" + resolved "https://registry.yarnpkg.com/@expo/prebuild-config/-/prebuild-config-54.0.6.tgz#0f0daed0195efbb33d91a730052b208507f94eed" + integrity sha512-xowuMmyPNy+WTNq+YX0m0EFO/Knc68swjThk4dKivgZa8zI1UjvFXOBIOp8RX4ljCXLzwxQJM5oBBTvyn+59ZA== + dependencies: + "@expo/config" "~12.0.10" + "@expo/config-plugins" "~54.0.2" + "@expo/config-types" "^54.0.8" + "@expo/image-utils" "^0.8.7" + "@expo/json-file" "^10.0.7" + "@react-native/normalize-colors" "0.81.5" + debug "^4.3.1" + resolve-from "^5.0.0" + semver "^7.6.0" + xml2js "0.6.0" + +"@expo/schema-utils@^0.1.7": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@expo/schema-utils/-/schema-utils-0.1.7.tgz#38baa0effa0823cd4eca3f05e5eee3bde311da12" + integrity sha512-jWHoSuwRb5ZczjahrychMJ3GWZu54jK9ulNdh1d4OzAEq672K9E5yOlnlBsfIHWHGzUAT+0CL7Yt1INiXTz68g== + +"@expo/sdk-runtime-versions@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@expo/sdk-runtime-versions/-/sdk-runtime-versions-1.0.0.tgz#d7ebd21b19f1c6b0395e50d78da4416941c57f7c" + integrity sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ== + +"@expo/spawn-async@^1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@expo/spawn-async/-/spawn-async-1.7.2.tgz#fcfe66c3e387245e72154b1a7eae8cada6a47f58" + integrity sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew== + dependencies: + cross-spawn "^7.0.3" + +"@expo/sudo-prompt@^9.3.1": + version "9.3.2" + resolved "https://registry.yarnpkg.com/@expo/sudo-prompt/-/sudo-prompt-9.3.2.tgz#0fd2813402a42988e49145cab220e25bea74b308" + integrity sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw== + +"@expo/vector-icons@^15.0.3": + version "15.0.3" + resolved "https://registry.yarnpkg.com/@expo/vector-icons/-/vector-icons-15.0.3.tgz#12c38d4e6cc927dd0500e4591ac00672a8909748" + integrity sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA== + +"@expo/ws-tunnel@^1.0.1": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@expo/ws-tunnel/-/ws-tunnel-1.0.6.tgz#92b70e7264ad42ea07f28a20f2f540b91d07bdd9" + integrity sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q== + +"@expo/xcpretty@^4.3.0": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@expo/xcpretty/-/xcpretty-4.3.2.tgz#12dba1295167a9c8dde4be783d74f7e81648ca5d" + integrity sha512-ReZxZ8pdnoI3tP/dNnJdnmAk7uLT4FjsKDGW7YeDdvdOMz2XCQSmSCM9IWlrXuWtMF9zeSB6WJtEhCQ41gQOfw== + dependencies: + "@babel/code-frame" "7.10.4" + chalk "^4.1.0" + find-up "^5.0.0" + js-yaml "^4.1.0" + +"@firebase/ai@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@firebase/ai/-/ai-2.4.0.tgz#fe67130f8b8770aa74c028f511dc61b67440a30a" + integrity sha512-YilG6AJ/nYpCKtxZyvEzBRAQv5bU+2tBOKX4Ps0rNNSdxN39aT37kGhjATbk1kq1z5Lq7mkWglw/ajAF3lOWUg== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/ai@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@firebase/ai/-/ai-2.5.0.tgz#ef1bba9b23828753b494d773fd885dc77f022dba" + integrity sha512-OXv/jZLRjV9jTejWA4KOvW8gM1hNsLvQSCPwKhi2CEfe0Nap3rM6z+Ial0PGqXga0WgzhpypEvJOFvaAUFX3kg== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/analytics-compat@0.2.25": + version "0.2.25" + resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.25.tgz#1f48bb6237bed7d6a3cf8136957aa5ceb245507b" + integrity sha512-fdzoaG0BEKbqksRDhmf4JoyZf16Wosrl0Y7tbZtJyVDOOwziE0vrFjmZuTdviL0yhak+Nco6rMsUUbkbD+qb6Q== + dependencies: + "@firebase/analytics" "0.10.19" + "@firebase/analytics-types" "0.8.3" + "@firebase/component" "0.7.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/analytics-types@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.3.tgz#d08cd39a6209693ca2039ba7a81570dfa6c1518f" + integrity sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg== + +"@firebase/analytics@0.10.19": + version "0.10.19" + resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.10.19.tgz#6bddeb9db287fa2367066855b12ec514e2914697" + integrity sha512-3wU676fh60gaiVYQEEXsbGS4HbF2XsiBphyvvqDbtC1U4/dO4coshbYktcCHq+HFaGIK07iHOh4pME0hEq1fcg== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/installations" "0.6.19" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/app-check-compat@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.4.0.tgz#94ac0cf9f66cab1d81a7b14e0c151dcc2684bc95" + integrity sha512-UfK2Q8RJNjYM/8MFORltZRG9lJj11k0nW84rrffiKvcJxLf1jf6IEjCIkCamykHE73C6BwqhVfhIBs69GXQV0g== + dependencies: + "@firebase/app-check" "0.11.0" + "@firebase/app-check-types" "0.5.3" + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/app-check-interop-types@0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz#ed9c4a4f48d1395ef378f007476db3940aa5351a" + integrity sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A== + +"@firebase/app-check-types@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.3.tgz#38ba954acf4bffe451581a32fffa20337f11d8e5" + integrity sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng== + +"@firebase/app-check@0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.11.0.tgz#a7e1d1e3f5ae36eabed1455db937114fe869ce8f" + integrity sha512-XAvALQayUMBJo58U/rxW02IhsesaxxfWVmVkauZvGEz3vOAjMEQnzFlyblqkc2iAaO82uJ2ZVyZv9XzPfxjJ6w== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/app-compat@0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.5.4.tgz#eb8f47d51c57887c9979279d4d39e4ee85270fe4" + integrity sha512-T7ifGmb+awJEcp542Ek4HtNfBxcBrnuk1ggUdqyFEdsXHdq7+wVlhvE6YukTL7NS8hIkEfL7TMAPx/uCNqt30g== + dependencies: + "@firebase/app" "0.14.4" + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/app-compat@0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.5.5.tgz#ff3cab5fef0db1bc9d8b19e8e6aedc8e27661441" + integrity sha512-lVG/nRnXaot0rQSZazmTNqy83ti9O3+kdwoaE0d5wahRIWNoDirbIMcGVjDDgdmf4IE6FYreWOMh0L3DV1475w== + dependencies: + "@firebase/app" "0.14.5" + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/app-types@0.9.3": + version "0.9.3" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.3.tgz#8408219eae9b1fb74f86c24e7150a148460414ad" + integrity sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw== + +"@firebase/app@0.14.4": + version "0.14.4" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.14.4.tgz#1d2ce74c09752dec9664e2f981b20335c4efbec1" + integrity sha512-pUxEGmR+uu21OG/icAovjlu1fcYJzyVhhT0rsCrn+zi+nHtrS43Bp9KPn9KGa4NMspCUE++nkyiqziuIvJdwzw== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/app@0.14.5": + version "0.14.5" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.14.5.tgz#cfd2c37432628d835d2c68aedbf9bc946e5ccebe" + integrity sha512-zyNY77xJOGwcuB+xCxF8z8lSiHvD4ox7BCsqLEHEvgqQoRjxFZ0fkROR6NV5QyXmCqRLodMM8J5d2EStOocWIw== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/auth-compat@0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.6.0.tgz#1464ea6049b2ad0aae83b4fdcd5e5e5aba6b1c50" + integrity sha512-J0lGSxXlG/lYVi45wbpPhcWiWUMXevY4fvLZsN1GHh+po7TZVng+figdHBVhFheaiipU8HZyc7ljw1jNojM2nw== + dependencies: + "@firebase/auth" "1.11.0" + "@firebase/auth-types" "0.13.0" + "@firebase/component" "0.7.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/auth-compat@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.6.1.tgz#e54a66186cf5f6fa015427996f460bd7be37cfc2" + integrity sha512-I0o2ZiZMnMTOQfqT22ur+zcGDVSAfdNZBHo26/Tfi8EllfR1BO7aTVo2rt/ts8o/FWsK8pOALLeVBGhZt8w/vg== + dependencies: + "@firebase/auth" "1.11.1" + "@firebase/auth-types" "0.13.0" + "@firebase/component" "0.7.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/auth-interop-types@0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz#176a08686b0685596ff03d7879b7e4115af53de0" + integrity sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA== + +"@firebase/auth-types@0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.13.0.tgz#ae6e0015e3bd4bfe18edd0942b48a0a118a098d9" + integrity sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg== + +"@firebase/auth@1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-1.11.0.tgz#81a4f77b16d97c502e493b2a14a97443e243a2a0" + integrity sha512-5j7+ua93X+IRcJ1oMDTClTo85l7Xe40WSkoJ+shzPrX7OISlVWLdE1mKC57PSD+/LfAbdhJmvKixINBw2ESK6w== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/auth@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-1.11.1.tgz#5cec47abdb805a6a30f5e4042ddb632f76ad777e" + integrity sha512-Mea0G/BwC1D0voSG+60Ylu3KZchXAFilXQ/hJXWCw3gebAu+RDINZA0dJMNeym7HFxBaBaByX8jSa7ys5+F2VA== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/component@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.7.0.tgz#3736644fdb6d3572dceae7fdc1c35a8bd3819adc" + integrity sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg== + dependencies: + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/data-connect@0.3.11": + version "0.3.11" + resolved "https://registry.yarnpkg.com/@firebase/data-connect/-/data-connect-0.3.11.tgz#60a7a9649e4aedd005546032466ef9abc0a544c1" + integrity sha512-G258eLzAD6im9Bsw+Qm1Z+P4x0PGNQ45yeUuuqe5M9B1rn0RJvvsQCRHXgE52Z+n9+WX1OJd/crcuunvOGc7Vw== + dependencies: + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/database-compat@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-2.1.0.tgz#c64488d741c6da2ed8dcf02f2e433089dae2f590" + integrity sha512-8nYc43RqxScsePVd1qe1xxvWNf0OBnbwHxmXJ7MHSuuTVYFO3eLyLW3PiCKJ9fHnmIz4p4LbieXwz+qtr9PZDg== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/database" "1.1.0" + "@firebase/database-types" "1.0.16" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/database-types@1.0.16": + version "1.0.16" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-1.0.16.tgz#262f54b8dbebbc46259757b3ba384224fb2ede48" + integrity sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw== + dependencies: + "@firebase/app-types" "0.9.3" + "@firebase/util" "1.13.0" + +"@firebase/database@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-1.1.0.tgz#bdf60f1605079a87ceb2b5e30d90846e0bde294b" + integrity sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + faye-websocket "0.11.4" + tslib "^2.1.0" + +"@firebase/firestore-compat@0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.4.2.tgz#2c9f5bef1dff004ae2db5759608f17d7973da78c" + integrity sha512-cy7ov6SpFBx+PHwFdOOjbI7kH00uNKmIFurAn560WiPCZXy9EMnil1SOG7VF4hHZKdenC+AHtL4r3fNpirpm0w== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/firestore" "4.9.2" + "@firebase/firestore-types" "3.0.3" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/firestore-types@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.3.tgz#7d0c3dd8850c0193d8f5ee0cc8f11961407742c1" + integrity sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q== + +"@firebase/firestore@4.9.2": + version "4.9.2" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.9.2.tgz#0c65203f9754d5aa801ec31c6f885445cfb346f4" + integrity sha512-iuA5+nVr/IV/Thm0Luoqf2mERUvK9g791FZpUJV1ZGXO6RL2/i/WFJUj5ZTVXy5pRjpWYO+ZzPcReNrlilmztA== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + "@firebase/webchannel-wrapper" "1.0.5" + "@grpc/grpc-js" "~1.9.0" + "@grpc/proto-loader" "^0.7.8" + tslib "^2.1.0" + +"@firebase/functions-compat@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.4.1.tgz#b253b761845f0c82bbdf76ef59975978ed84eb65" + integrity sha512-AxxUBXKuPrWaVNQ8o1cG1GaCAtXT8a0eaTDfqgS5VsRYLAR0ALcfqDLwo/QyijZj1w8Qf8n3Qrfy/+Im245hOQ== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/functions" "0.13.1" + "@firebase/functions-types" "0.6.3" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/functions-types@0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.3.tgz#f5faf770248b13f45d256f614230da6a11bfb654" + integrity sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg== + +"@firebase/functions@0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.13.1.tgz#472e8456568689154b87a494ee8c10ee2e610d94" + integrity sha512-sUeWSb0rw5T+6wuV2o9XNmh9yHxjFI9zVGFnjFi+n7drTEWpl7ZTz1nROgGrSu472r+LAaj+2YaSicD4R8wfbw== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.7.0" + "@firebase/messaging-interop-types" "0.2.3" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/installations-compat@0.2.19": + version "0.2.19" + resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.19.tgz#4bc57c8c57d241eeca95900ff3033d6ec3dbcc7c" + integrity sha512-khfzIY3EI5LePePo7vT19/VEIH1E3iYsHknI/6ek9T8QCozAZshWT9CjlwOzZrKvTHMeNcbpo/VSOSIWDSjWdQ== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/installations" "0.6.19" + "@firebase/installations-types" "0.5.3" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/installations-types@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.3.tgz#cac8a14dd49f09174da9df8ae453f9b359c3ef2f" + integrity sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA== + +"@firebase/installations@0.6.19": + version "0.6.19" + resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.19.tgz#93c569321f6fb399f4f1a197efc0053ce6452c7c" + integrity sha512-nGDmiwKLI1lerhwfwSHvMR9RZuIH5/8E3kgUWnVRqqL7kGVSktjLTWEMva7oh5yxQ3zXfIlIwJwMcaM5bK5j8Q== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/util" "1.13.0" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/logger@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.5.0.tgz#a9e55b1c669a0983dc67127fa4a5964ce8ed5e1b" + integrity sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g== + dependencies: + tslib "^2.1.0" + +"@firebase/messaging-compat@0.2.23": + version "0.2.23" + resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.23.tgz#2ca6b36ea238fae4dff53bf85442c4a2af516224" + integrity sha512-SN857v/kBUvlQ9X/UjAqBoQ2FEaL1ZozpnmL1ByTe57iXkmnVVFm9KqAsTfmf+OEwWI4kJJe9NObtN/w22lUgg== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/messaging" "0.12.23" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/messaging-interop-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz#e647c9cd1beecfe6a6e82018a6eec37555e4da3e" + integrity sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q== + +"@firebase/messaging@0.12.23": + version "0.12.23" + resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.23.tgz#71f932a521ac39d9f036175672e37897531010eb" + integrity sha512-cfuzv47XxqW4HH/OcR5rM+AlQd1xL/VhuaeW/wzMW1LFrsFcTn0GND/hak1vkQc2th8UisBcrkVcQAnOnKwYxg== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/installations" "0.6.19" + "@firebase/messaging-interop-types" "0.2.3" + "@firebase/util" "1.13.0" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/performance-compat@0.2.22": + version "0.2.22" + resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.22.tgz#1c24ea360b03cfef831bdf379b4fc7080f412741" + integrity sha512-xLKxaSAl/FVi10wDX/CHIYEUP13jXUjinL+UaNXT9ByIvxII5Ne5150mx6IgM8G6Q3V+sPiw9C8/kygkyHUVxg== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/performance" "0.7.9" + "@firebase/performance-types" "0.2.3" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/performance-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.3.tgz#5ce64e90fa20ab5561f8b62a305010cf9fab86fb" + integrity sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ== + +"@firebase/performance@0.7.9": + version "0.7.9" + resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.7.9.tgz#7e3a072b1542f0df3f502684a38a0516b0d72cab" + integrity sha512-UzybENl1EdM2I1sjYm74xGt/0JzRnU/0VmfMAKo2LSpHJzaj77FCLZXmYQ4oOuE+Pxtt8Wy2BVJEENiZkaZAzQ== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/installations" "0.6.19" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + web-vitals "^4.2.4" + +"@firebase/remote-config-compat@0.2.20": + version "0.2.20" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.20.tgz#4bca09b1361867d0c882411970486ee06622e071" + integrity sha512-P/ULS9vU35EL9maG7xp66uljkZgcPMQOxLj3Zx2F289baTKSInE6+YIkgHEi1TwHoddC/AFePXPpshPlEFkbgg== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/logger" "0.5.0" + "@firebase/remote-config" "0.7.0" + "@firebase/remote-config-types" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/remote-config-types@0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.5.0.tgz#f0f503b32edda3384f5252f9900cd9613adbb99c" + integrity sha512-vI3bqLoF14L/GchtgayMiFpZJF+Ao3uR8WCde0XpYNkSokDpAKca2DxvcfeZv7lZUqkUwQPL2wD83d3vQ4vvrg== + +"@firebase/remote-config@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.7.0.tgz#0e5e5879a7a9121c9da55606be8fa40ff70ddae1" + integrity sha512-dX95X6WlW7QlgNd7aaGdjAIZUiQkgWgNS+aKNu4Wv92H1T8Ue/NDUjZHd9xb8fHxLXIHNZeco9/qbZzr500MjQ== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/installations" "0.6.19" + "@firebase/logger" "0.5.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/storage-compat@0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.4.0.tgz#a09bd33c262123e7e3ed0cd590b4c6e2ce4a8902" + integrity sha512-vDzhgGczr1OfcOy285YAPur5pWDEvD67w4thyeCUh6Ys0izN9fNYtA1MJERmNBfqjqu0lg0FM5GLbw0Il21M+g== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/storage" "0.14.0" + "@firebase/storage-types" "0.8.3" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/storage-types@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.3.tgz#2531ef593a3452fc12c59117195d6485c6632d3d" + integrity sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg== + +"@firebase/storage@0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.14.0.tgz#01acb97d413ada7c91de860fb260623468baa25d" + integrity sha512-xWWbb15o6/pWEw8H01UQ1dC5U3rf8QTAzOChYyCpafV6Xki7KVp3Yaw2nSklUwHEziSWE9KoZJS7iYeyqWnYFA== + dependencies: + "@firebase/component" "0.7.0" + "@firebase/util" "1.13.0" + tslib "^2.1.0" + +"@firebase/util@1.13.0": + version "1.13.0" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.13.0.tgz#2e9e7569722a1e3fc86b1b4076d5cbfbfa7265d6" + integrity sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ== + dependencies: + tslib "^2.1.0" + +"@firebase/webchannel-wrapper@1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.5.tgz#39cf5a600450cb42f1f0b507cc385459bf103b27" + integrity sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw== + +"@formatjs/ecma402-abstract@2.3.6": + version "2.3.6" + resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz#d6ca9d3579054fe1e1a0a0b5e872e0d64922e4e1" + integrity sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw== + dependencies: + "@formatjs/fast-memoize" "2.2.7" + "@formatjs/intl-localematcher" "0.6.2" + decimal.js "^10.4.3" + tslib "^2.8.0" + +"@formatjs/fast-memoize@2.2.7": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz#707f9ddaeb522a32f6715bb7950b0831f4cc7b15" + integrity sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ== + dependencies: + tslib "^2.8.0" + +"@formatjs/icu-messageformat-parser@2.11.4": + version "2.11.4" + resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz#63bd2cd82d08ae2bef55adeeb86486df68826f32" + integrity sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + "@formatjs/icu-skeleton-parser" "1.8.16" + tslib "^2.8.0" + +"@formatjs/icu-skeleton-parser@1.8.16": + version "1.8.16" + resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz#13f81f6845c7cf6599623006aacaf7d6b4ad2970" + integrity sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + tslib "^2.8.0" + +"@formatjs/intl-enumerator@1.8.12": + version "1.8.12" + resolved "https://registry.yarnpkg.com/@formatjs/intl-enumerator/-/intl-enumerator-1.8.12.tgz#8c94a9bff855fb942a95a4c93b5bdeb1a8f54007" + integrity sha512-rT2hnyQ0q6RDG1jISMH+MP6wlHQLUC81C0BeYEzabJb48S4tU2HGCPUxsOqMa3vDAUmpnz9Kw5vYTD5hTkOVgg== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + tslib "^2.8.0" + +"@formatjs/intl-getcanonicallocales@2.5.6", "@formatjs/intl-getcanonicallocales@^2.5.3": + version "2.5.6" + resolved "https://registry.yarnpkg.com/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-2.5.6.tgz#d4a8e13dad31f83c142746b423462dcbdf839503" + integrity sha512-CnBbc4St61RL06gDXlCZG08Gt41uiySgsdZNBExh8/c0FBONJCrAlQ9FsyalUdq9ze0nCeknJtMmO8JnB9xHgQ== + dependencies: + tslib "^2.8.0" + +"@formatjs/intl-locale@^4.2.5": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@formatjs/intl-locale/-/intl-locale-4.2.13.tgz#21d4b54ee03b75a7b7384a122510be7ee080a9c5" + integrity sha512-Qcs0mP9JhEPCinPfpZ5JKzOa+VYDg94TQSFZozYuqG8R+hEGUTKyoyMqB5xi5QZT/hlB0CSgeNc/0fWMGtTFXA== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + "@formatjs/intl-enumerator" "1.8.12" + "@formatjs/intl-getcanonicallocales" "2.5.6" + tslib "^2.8.0" + +"@formatjs/intl-localematcher@0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz#e9ebe0b4082d7d48e5b2d753579fb7ece4eaefea" + integrity sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA== + dependencies: + tslib "^2.8.0" + +"@formatjs/intl-pluralrules@^5.3.5": + version "5.4.6" + resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-5.4.6.tgz#4bd73c4e87974265a7962b6caf0d146e3310f3ad" + integrity sha512-2HlOq+c7KsSps829SJ3B5987coX5mzKx9NbPcNwQ07eq8FBHgB3HfMoxt5HvLsdk4oQwCjAEnocbtd+wVwZ2Kg== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + "@formatjs/intl-localematcher" "0.6.2" + decimal.js "^10.4.3" + tslib "^2.8.0" + +"@formatjs/intl-relativetimeformat@^11.4.5": + version "11.4.13" + resolved "https://registry.yarnpkg.com/@formatjs/intl-relativetimeformat/-/intl-relativetimeformat-11.4.13.tgz#f77839f2e87b1b0641e8ed72e673b9386f5df79a" + integrity sha512-fNs6cpz9zIUEgTlE3kPSEyRfslxeMG19dT7sLz2C6U7Jxkx8xK/IH1ImZzCeqd6JlqE81O7uNW4oZTb1pz8lUw== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + "@formatjs/intl-localematcher" "0.6.2" + tslib "^2.8.0" + +"@gemini-wallet/core@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@gemini-wallet/core/-/core-0.3.2.tgz#fd6fd2df91d50be6c1a832c46379453e933a352e" + integrity sha512-Z4aHi3ECFf5oWYWM3F1rW83GJfB9OvhBYPTmb5q+VyK3uvzvS48lwo+jwh2eOoCRWEuT/crpb9Vwp2QaS5JqgQ== + dependencies: + "@metamask/rpc-errors" "7.0.2" + eventemitter3 "5.0.1" + +"@gluestack-style/animation-resolver@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@gluestack-style/animation-resolver/-/animation-resolver-1.0.4.tgz#93be3e67221ccb0ce064ddd260852bcc13612240" + integrity sha512-AeAQ61u41j9F2fxWTGiR6C7G3KG7qSCAYVi3jCE+aUiOEPEctfurUCT70DnrKp1Tg/Bl29a+OUwutaW/3YKvQw== + +"@gluestack-style/legend-motion-animation-driver@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@gluestack-style/legend-motion-animation-driver/-/legend-motion-animation-driver-1.0.3.tgz#e2408ff8515ced92cb75f096f5eeff1f9636a0da" + integrity sha512-sD6aFS6Tq5XpyjrboFEIc8LrRY4TA4kodFYHzk6mDchvbkdLODijtjnaDQB1UqihOkMRg49e7ANRAOzc7eymaQ== + +"@gluestack-style/react@^1.0.31": + version "1.0.57" + resolved "https://registry.yarnpkg.com/@gluestack-style/react/-/react-1.0.57.tgz#96dbf667e373c5eed9f2314e7885a9a5b5df6775" + integrity sha512-jaG78zurLNiZyJleZnCbgugTpL6OWtBkE7XKur9C9FYUicekMh11RY++2gyN4T7GJx80v5S/NHIwm/GxAAxtRw== + dependencies: + inline-style-prefixer "^6.0.1" + normalize-css-color "^1.0.2" + +"@gluestack-ui/accordion@1.0.14": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@gluestack-ui/accordion/-/accordion-1.0.14.tgz#22c1192557c9fcf958daf7a63fa17d35bbc6cbfe" + integrity sha512-dpqlSnIZk1grZOPtLoMYh08OGmRgl/Sjpv1KltPdpjNaG2Gt7DPAmT/8l9wVuJYMOfdsLOsBOfzGo5eECZ9WFg== + dependencies: + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/accordion" "^0.0.2" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/actionsheet@0.2.53": + version "0.2.53" + resolved "https://registry.yarnpkg.com/@gluestack-ui/actionsheet/-/actionsheet-0.2.53.tgz#09608d32f373f99c0dff9fb62856895a843f1a05" + integrity sha512-93qHvq6BHezJ7wt2lce4OQ38wXCGsDtglj5nlmwo2T41vj4ubOtDVoSUhXT+hfH0EmRr0TxFNeFqIgesO46qVw== + dependencies: + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/overlay" "^0.1.22" + "@gluestack-ui/transitions" "^0.1.11" + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/dialog" "^0.0.5" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/alert-dialog@0.1.38": + version "0.1.38" + resolved "https://registry.yarnpkg.com/@gluestack-ui/alert-dialog/-/alert-dialog-0.1.38.tgz#fd63bdbdf2ddd627aa3e55e4758a2c0be61b411c" + integrity sha512-qarZlXlmGHwjfOFaEJgLpNstDd38b7TBMdYtpb6xXIvOA6W6IyNnnKYPNasOiUlNrW8qvqrZrZc+xJfK5USr0w== + dependencies: + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/overlay" "^0.1.22" + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/dialog" "^0.0.5" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/alert@0.1.16": + version "0.1.16" + resolved "https://registry.yarnpkg.com/@gluestack-ui/alert/-/alert-0.1.16.tgz#cede162e04c3dcb07a3da797221852bb7c127311" + integrity sha512-vE0litmicuKFJFp9TY3mRuZmyH/E24IdHlC0f3FZjfa+AzeOS+bZdKMRix2EYkvBGrA6uNffWUuHeXWQGMRVJQ== + +"@gluestack-ui/avatar@0.1.18": + version "0.1.18" + resolved "https://registry.yarnpkg.com/@gluestack-ui/avatar/-/avatar-0.1.18.tgz#bb890a7b889060e01faf549f59a47d11c04ada1c" + integrity sha512-VA9XwtavYLYCWrjxHc2u9gRpV97cPRcr/6KJ4tLiMiQbiRL1b4zckiL+/F39fB6xjUOUQHl3Fjo/Yd8swa0MBg== + dependencies: + "@gluestack-ui/utils" "^0.1.14" + +"@gluestack-ui/button@1.0.14": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@gluestack-ui/button/-/button-1.0.14.tgz#c8c2d60888df7aa472485792a6c848a194a933e0" + integrity sha512-Rqv5PY18jzeVACBwsVxXlyDbHjBiSXGVqY29VO6KHZGMMokCPW6MXYXT8ZpriLxMc1DRkgTtpTVYZCJBFaYTbg== + dependencies: + "@gluestack-ui/utils" "0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/checkbox@0.1.39": + version "0.1.39" + resolved "https://registry.yarnpkg.com/@gluestack-ui/checkbox/-/checkbox-0.1.39.tgz#1c84a3a19120b9ab9ea1c9c6ac7e8771902bd194" + integrity sha512-CPL9+g9qIFuGGQAQuFySATTxrqGMhIx/ASpBdl/YC50Ec/d7gMZlnKww3N1og3a6JqMG8yeWwbH+GH3z07XsfA== + dependencies: + "@gluestack-ui/form-control" "^0.1.19" + "@gluestack-ui/utils" "^0.1.15" + "@react-aria/visually-hidden" "^3.8.6" + "@react-native-aria/checkbox" "^0.2.10" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/utils" "0.2.12" + "@react-stately/checkbox" "^3.4.2" + +"@gluestack-ui/config@^1.0.11": + version "1.1.20" + resolved "https://registry.yarnpkg.com/@gluestack-ui/config/-/config-1.1.20.tgz#d1dcdde67fc91ff3217638b6faa24c04ba7a5c9e" + integrity sha512-kgIzcRZfrzdNiKry7TcgsS85SgACxSRxaLTWdxoNPB/WaJ+XrCbKbaBuQOiELW33dgl2IdyUw60V8XlsLM+f2A== + +"@gluestack-ui/divider@0.1.10": + version "0.1.10" + resolved "https://registry.yarnpkg.com/@gluestack-ui/divider/-/divider-0.1.10.tgz#506ec45f9b5183a0e3b293dbff7b7da19edcfda8" + integrity sha512-/hZx1Rmy4Pgln9AwAprAEQcxYPEHjHSNF4xCUWlK/q0peyiMT5Nagt54VnxykVn5A0b2zg5QKP0pOqOF9xeE6w== + +"@gluestack-ui/fab@0.1.28": + version "0.1.28" + resolved "https://registry.yarnpkg.com/@gluestack-ui/fab/-/fab-0.1.28.tgz#603da60deabea09e71baddb82a4abe61262b9d7d" + integrity sha512-NTzTN08KyX3iqcC5LiRqymrO+TlCzfcjDS5GeO0Y+1AiH7loKwWwDm0PFn3TbflfycRTG0jw8RkUqs2Ckov/mg== + dependencies: + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/form-control@0.1.19", "@gluestack-ui/form-control@^0.1.19": + version "0.1.19" + resolved "https://registry.yarnpkg.com/@gluestack-ui/form-control/-/form-control-0.1.19.tgz#7a75b65f5ec89da95c30442750d6f7af71db6868" + integrity sha512-6YbPbi/RZrXc5DyVPbxPV17FYaBoEl1yAdSwut8iE6n+yQekjluINrh2q5ZPWF2SGmyo7VSNcL85yeU5I97xHg== + dependencies: + "@gluestack-ui/utils" "^0.1.14" + "@react-native-aria/focus" "^0.2.9" + +"@gluestack-ui/hooks@0.1.13": + version "0.1.13" + resolved "https://registry.yarnpkg.com/@gluestack-ui/hooks/-/hooks-0.1.13.tgz#4f1494850bb6e95a1eaeef10c724c83adfe6954f" + integrity sha512-2x5EGcAuvdWFoOaqBRJsilR9Nx07tDvuAr3MI5SOmDdn7Bjzi+3CVAZwwDE2nGwAL3ldJvbAlzVkiNCw4TsSeA== + +"@gluestack-ui/icon@0.1.27": + version "0.1.27" + resolved "https://registry.yarnpkg.com/@gluestack-ui/icon/-/icon-0.1.27.tgz#6a2241bcdf3d15e53e7d191922792b634e290b52" + integrity sha512-mIsfgdVUihtRORoeDxn3kMFph5XOXK+Scnj1JXLufbt7h9kbfaZLGhYDc9cp2zpPc1Xki9SC1yXYfw8y4FAAdA== + dependencies: + "@gluestack-ui/provider" "^0.1.19" + "@gluestack-ui/utils" "^0.1.14" + "@react-native-aria/focus" "^0.2.9" + +"@gluestack-ui/image@0.1.17": + version "0.1.17" + resolved "https://registry.yarnpkg.com/@gluestack-ui/image/-/image-0.1.17.tgz#b92c788bea557c5a4e34231c5430398cc1220011" + integrity sha512-hcyTVBUw55bSjEpyynIZJVm3Ff6lcjKXFT55f890oy2PNGyFdsKr6V+t/jy5n/2fwbv1eR2KU0uDDiI2vmBh+A== + dependencies: + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/input@0.1.38": + version "0.1.38" + resolved "https://registry.yarnpkg.com/@gluestack-ui/input/-/input-0.1.38.tgz#8430b5f4901e59475a99d5e3f473bd5b0d248a19" + integrity sha512-NzwDOXkkMYzBQ0h7UnhKA2h54/qlxDxMFGXykkmYOl7mc7QJc1aJaveo4yMHtpYvcQG17xLyD+Z+5CQYA76nvw== + dependencies: + "@gluestack-ui/form-control" "^0.1.19" + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/link@0.1.29": + version "0.1.29" + resolved "https://registry.yarnpkg.com/@gluestack-ui/link/-/link-0.1.29.tgz#5dcba644772570dc9165e8b36862c70bd49ea8fb" + integrity sha512-7rNx0puyHr+LG4moy/OfMybwVIxQ/ES4H/xyskvcvylCtbxPqN+0oSQ9WA4CISeipwK4x+2aQQRvjasYt9rXgA== + dependencies: + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/menu@0.2.43": + version "0.2.43" + resolved "https://registry.yarnpkg.com/@gluestack-ui/menu/-/menu-0.2.43.tgz#54cbaef5d9f4e1c1a9d5b1e809023d1e8b20cebd" + integrity sha512-RjThV7nqGOFnsdCMG/JHs2qrVvtjw3MwKJJPD0bAJa+rhBEk2n9tbEFHPR6KWWNUmSnP3aWSZldT5Y87JiVKNA== + dependencies: + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/overlay" "^0.1.22" + "@gluestack-ui/utils" "^0.1.15" + "@react-aria/menu" "^3.14.1" + "@react-aria/overlays" "^3.19.0" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/menu" "0.2.15" + "@react-native-aria/overlays" "^0.3.15" + "@react-stately/utils" "^3.6.0" + react-stately "^3.21.0" + +"@gluestack-ui/modal@0.1.41": + version "0.1.41" + resolved "https://registry.yarnpkg.com/@gluestack-ui/modal/-/modal-0.1.41.tgz#e8c04fd9ac7598dd0f2a2ff15f8526b9cceab2d2" + integrity sha512-pEO5h6TxEpYyU/CEhRD/pAkuBsDfqnFUe51AxK7w6FLjBuTKA5P0wsQ1pfcovJeykkpreG+MiUvNPIo3MW/Lfw== + dependencies: + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/overlay" "^0.1.22" + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/dialog" "^0.0.5" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/overlays" "^0.3.15" + +"@gluestack-ui/overlay@0.1.22", "@gluestack-ui/overlay@^0.1.16", "@gluestack-ui/overlay@^0.1.20", "@gluestack-ui/overlay@^0.1.22": + version "0.1.22" + resolved "https://registry.yarnpkg.com/@gluestack-ui/overlay/-/overlay-0.1.22.tgz#b0c03eb88f37e1564b6522f3d021052dcce86f4a" + integrity sha512-ttlSjO/ysN9NuTq5JPoVwOAU8aKMaj738xTCxOVgBRr1+kbBUVpmBnygVlC6PvHvJF1A00a0ZTzw48CIVL5aNw== + dependencies: + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/overlays" "^0.3.15" + +"@gluestack-ui/popover@0.1.49": + version "0.1.49" + resolved "https://registry.yarnpkg.com/@gluestack-ui/popover/-/popover-0.1.49.tgz#38fa4971938d5a84c74fab9e305c0293dc7c36c5" + integrity sha512-AI73AXEPoIPGpwhQICn9BiQIJzCDGSb4RT6OQI2V3TKlBYM+RodZvK0RKMipEsROBQwNWbcJoPJRkH9jwDVrBA== + dependencies: + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/overlay" "0.1.22" + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/dialog" "^0.0.5" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/overlays" "0.3.15" + +"@gluestack-ui/pressable@0.1.23": + version "0.1.23" + resolved "https://registry.yarnpkg.com/@gluestack-ui/pressable/-/pressable-0.1.23.tgz#4324aa4bdbb6e5844416d7cdcc7f62f9f6956c89" + integrity sha512-y7Sqwwe4+nIM5pECr3UT9qx7MMyuJHt1od6dfB/K+S2X91uZgTJEw7PUQgvOW6Jr8dBrStxFiTWfHmDqX/FVOQ== + dependencies: + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/progress@0.1.18": + version "0.1.18" + resolved "https://registry.yarnpkg.com/@gluestack-ui/progress/-/progress-0.1.18.tgz#9a659115b4579fee057c2d13bbc52e9e080a6958" + integrity sha512-WQCLdvqoiIIQnLBXG7+HDTREMbUfEy9rV7FuBMcBBqEFILuVT1W4hyuXLz/CPrUoCWZJ8OUKvLZvaWWzW8pA9Q== + dependencies: + "@gluestack-ui/utils" "^0.1.14" + +"@gluestack-ui/provider@0.1.19", "@gluestack-ui/provider@^0.1.19": + version "0.1.19" + resolved "https://registry.yarnpkg.com/@gluestack-ui/provider/-/provider-0.1.19.tgz#145c038c401ce250274c384e69a91f78ee1ff73c" + integrity sha512-+MbL2VpGK7kkSNccgNeMay/nslDA4BzgjHFWwnys+dSvyCMgt7yfSxrfWziTvAyaQ4cRkq/lXCfJK0B1nuCZ4A== + dependencies: + "@react-native-aria/interactions" "0.2.16" + tsconfig "7" + typescript "^5.6.3" + +"@gluestack-ui/radio@0.1.40": + version "0.1.40" + resolved "https://registry.yarnpkg.com/@gluestack-ui/radio/-/radio-0.1.40.tgz#cfbb709db8170d9a7dc70decdb7a3522fb0e9e67" + integrity sha512-UJ6i3qpbBVsSWrxQi889yXczPjmfhfHCplMK2n4xkEfsYcjDVKpronVfqbJ41gf27fBzyLJFnCec3uPL4+obSA== + dependencies: + "@gluestack-ui/form-control" "^0.1.19" + "@gluestack-ui/utils" "^0.1.15" + "@react-aria/visually-hidden" "^3.7.0" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/radio" "^0.2.13" + "@react-stately/radio" "^3.8.1" + +"@gluestack-ui/react-native-aria@^0.1.6": + version "0.1.7" + resolved "https://registry.yarnpkg.com/@gluestack-ui/react-native-aria/-/react-native-aria-0.1.7.tgz#f982cbb071fa844afcf3816873dce300dc754843" + integrity sha512-mdK/M6RQafAYiHyJnDNjaE9+ttr9eg48f2InmO3rvcrjsdaLcu/vwHlwrO9N3xYcb3wb9z2+YZ4OIgtymFNTOw== + dependencies: + "@react-native-aria/focus" "^0.2.9" + +"@gluestack-ui/select@0.1.31": + version "0.1.31" + resolved "https://registry.yarnpkg.com/@gluestack-ui/select/-/select-0.1.31.tgz#b0f91fdaf0124db5fa3cdd0e3a7460db9406eff0" + integrity sha512-d8vfdCK4VFBYEDYMCTRYcZCWvYaf7UWMJGg2uMnutHA8Y4sDXjKR5P821xKdh75QVkmZRZm1MdzSWFvXUzAlgg== + dependencies: + "@gluestack-ui/form-control" "^0.1.19" + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/utils" "^0.1.14" + "@react-native-aria/focus" "^0.2.9" + +"@gluestack-ui/slider@0.1.32": + version "0.1.32" + resolved "https://registry.yarnpkg.com/@gluestack-ui/slider/-/slider-0.1.32.tgz#65d166ff51a5a94c27a68fc1ccf2d4d373bd1824" + integrity sha512-g0e7dAGOYYARlL3cdHe3mhN71j85TnqUgK/xOYWjVDE0U+atIXxxTVEXeO0ZPGJ3YUOUUAInIVGaa0xvnjEkYg== + dependencies: + "@gluestack-ui/form-control" "^0.1.19" + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/utils" "^0.1.15" + "@react-aria/visually-hidden" "^3.8.1" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/slider" "^0.2.12" + "@react-stately/slider" "^3.2.4" + +"@gluestack-ui/spinner@0.1.15": + version "0.1.15" + resolved "https://registry.yarnpkg.com/@gluestack-ui/spinner/-/spinner-0.1.15.tgz#712276227568476f55672b7bbe0082478c0c0a65" + integrity sha512-jkXOGhna05HM2tcPKbA+t+vqcVRgRowwC6ES0A9kY5fcuURH1V41UFx/YWyHdSsHwmWlIoCCdWycF78UbNVdPg== + +"@gluestack-ui/switch@0.1.29": + version "0.1.29" + resolved "https://registry.yarnpkg.com/@gluestack-ui/switch/-/switch-0.1.29.tgz#d2a26f66cfc3065f27ea4af0206f4cb0ef34f5ca" + integrity sha512-swx0J20ULpN+pkHg8KioWibZETWE/6XvCBckmApNZf9RO2MiHHkNMw4Txne4u1z0OyLKGzBW1dbmkhLIOObaXg== + dependencies: + "@gluestack-ui/form-control" "^0.1.19" + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-stately/toggle" "^3.4.4" + +"@gluestack-ui/tabs@0.1.24": + version "0.1.24" + resolved "https://registry.yarnpkg.com/@gluestack-ui/tabs/-/tabs-0.1.24.tgz#35f1d8c0f82457a4f81b7451d09618489ecd036c" + integrity sha512-vzuwtb89WeonRvEJmy0zGJnqYDXLBcWMOh2OzX3ktOMtSvWgBLZxh2Ie+QABEYcoOVSKN8Lx+C3HnggtBpFEpA== + dependencies: + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + +"@gluestack-ui/textarea@0.1.25": + version "0.1.25" + resolved "https://registry.yarnpkg.com/@gluestack-ui/textarea/-/textarea-0.1.25.tgz#203f3e60c0177ad3b722f0d2745db5ae7fbcd3d8" + integrity sha512-hXJx9LYSfrx7/Lrh2D2cTjr7PqvdkxJXBv2VydcR01X4WEN34DZkik+at/qk5FBw+p4t0vE+BTAK3IoMJwWvGg== + dependencies: + "@gluestack-ui/form-control" "^0.1.19" + "@gluestack-ui/utils" "^0.1.14" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "^0.2.16" + +"@gluestack-ui/themed@^1.0.34": + version "1.1.73" + resolved "https://registry.yarnpkg.com/@gluestack-ui/themed/-/themed-1.1.73.tgz#eee5877f25b0b7a39d8c9b9268878a0cb17c731e" + integrity sha512-Gx1vTRzP05liSn6qRJ4Kk/OoZUm5A19VjkcFQTtOplldMqmcfj83+cfY2Be+8goqWJD9MXk0kBineE15QeqZtg== + dependencies: + "@expo/html-elements" latest + "@gluestack-style/animation-resolver" "1.0.4" + "@gluestack-style/legend-motion-animation-driver" "1.0.3" + "@gluestack-ui/accordion" "1.0.14" + "@gluestack-ui/actionsheet" "0.2.53" + "@gluestack-ui/alert" "0.1.16" + "@gluestack-ui/alert-dialog" "0.1.38" + "@gluestack-ui/avatar" "0.1.18" + "@gluestack-ui/button" "1.0.14" + "@gluestack-ui/checkbox" "0.1.39" + "@gluestack-ui/divider" "0.1.10" + "@gluestack-ui/fab" "0.1.28" + "@gluestack-ui/form-control" "0.1.19" + "@gluestack-ui/icon" "0.1.27" + "@gluestack-ui/image" "0.1.17" + "@gluestack-ui/input" "0.1.38" + "@gluestack-ui/link" "0.1.29" + "@gluestack-ui/menu" "0.2.43" + "@gluestack-ui/modal" "0.1.41" + "@gluestack-ui/overlay" "0.1.22" + "@gluestack-ui/popover" "0.1.49" + "@gluestack-ui/pressable" "0.1.23" + "@gluestack-ui/progress" "0.1.18" + "@gluestack-ui/provider" "0.1.19" + "@gluestack-ui/radio" "0.1.40" + "@gluestack-ui/select" "0.1.31" + "@gluestack-ui/slider" "0.1.32" + "@gluestack-ui/spinner" "0.1.15" + "@gluestack-ui/switch" "0.1.29" + "@gluestack-ui/tabs" "0.1.24" + "@gluestack-ui/textarea" "0.1.25" + "@gluestack-ui/toast" "1.0.9" + "@gluestack-ui/tooltip" "0.1.44" + "@legendapp/motion" latest + +"@gluestack-ui/toast@1.0.9": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@gluestack-ui/toast/-/toast-1.0.9.tgz#6ee18051e7af0459fbb3ede4cc4bf1a9ec1719a0" + integrity sha512-aMlPczeoH/PZTMnhV29fqqW1Xc/9QmYEsR0bU9BfLyAGM9UMjW3vGe4yZSgxX7xjQ9C7+KO5WnTH0FmPoAbVtg== + dependencies: + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/overlay" "^0.1.20" + "@gluestack-ui/transitions" "^0.1.11" + "@gluestack-ui/utils" "^0.1.14" + "@react-native-aria/focus" "^0.2.9" + +"@gluestack-ui/tooltip@0.1.44": + version "0.1.44" + resolved "https://registry.yarnpkg.com/@gluestack-ui/tooltip/-/tooltip-0.1.44.tgz#bc682f046573001a8c611f04991ab6ed3200e76f" + integrity sha512-gHVOYwjQK41ofM+D7131miNobbBAr0fuxr/52x3EJJpntqItF5u35ikj8XKy1T7nrOb0iZaYh7C0W08if1Skgg== + dependencies: + "@gluestack-ui/hooks" "0.1.13" + "@gluestack-ui/overlay" "^0.1.22" + "@gluestack-ui/utils" "^0.1.15" + "@react-native-aria/focus" "^0.2.9" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/overlays" "^0.3.15" + +"@gluestack-ui/transitions@^0.1.11": + version "0.1.11" + resolved "https://registry.yarnpkg.com/@gluestack-ui/transitions/-/transitions-0.1.11.tgz#e84a9841fabb8e67ce17cea979a1cd77b5edac56" + integrity sha512-GuCprzasuU8GKXm1GUmaVJ1Njiq72pQ4Ni0g+rg6kRQ7hyR0K4d0wdHRyFldHKmfLcQkM3i70rvYq/468hLKLw== + dependencies: + "@gluestack-ui/overlay" "^0.1.16" + "@gluestack-ui/react-native-aria" "^0.1.6" + "@gluestack-ui/utils" "^0.1.14" + "@react-native-aria/focus" "^0.2.9" + +"@gluestack-ui/utils@0.1.15", "@gluestack-ui/utils@^0.1.14", "@gluestack-ui/utils@^0.1.15": + version "0.1.15" + resolved "https://registry.yarnpkg.com/@gluestack-ui/utils/-/utils-0.1.15.tgz#55f318d81d230daca40b498039eb4680600faa90" + integrity sha512-LRBMv+tr+bV4falMYS2zSt94PxL0vpvUN6F9d6oTqOYKhkiAkU6k2ROfNlT323m0CoTQto1LkJhPxULisQ2oeQ== + dependencies: + "@react-native-aria/focus" "^0.2.9" + +"@gorhom/bottom-sheet@^5.1.1": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@gorhom/bottom-sheet/-/bottom-sheet-5.2.6.tgz#5f2045f6ca965383afe39f7dfa3afad1502b7467" + integrity sha512-vmruJxdiUGDg+ZYcDmS30XDhq/h/+QkINOI5LY/uGjx8cPGwgJW0H6AB902gNTKtccbiKe/rr94EwdmIEz+LAQ== + dependencies: + "@gorhom/portal" "1.0.14" + invariant "^2.2.4" + +"@gorhom/portal@1.0.14": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@gorhom/portal/-/portal-1.0.14.tgz#1953edb76aaba80fb24021dc774550194a18e111" + integrity sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A== + dependencies: + nanoid "^3.3.1" + +"@graphql-typed-document-node/core@^3.1.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861" + integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== + +"@grpc/grpc-js@~1.9.0": + version "1.9.15" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" + integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== + dependencies: + "@grpc/proto-loader" "^0.7.8" + "@types/node" ">=12.12.47" + +"@grpc/proto-loader@^0.7.8": + version "0.7.15" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.15.tgz#4cdfbf35a35461fc843abe8b9e2c0770b5095e60" + integrity sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ== + dependencies: + lodash.camelcase "^4.3.0" + long "^5.0.0" + protobufjs "^7.2.5" + yargs "^17.7.2" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" + integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.4.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== + +"@ide/backoff@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@ide/backoff/-/backoff-1.0.0.tgz#466842c25bd4a4833e0642fab41ccff064010176" + integrity sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g== + +"@img/colour@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@img/colour/-/colour-1.0.0.tgz#d2fabb223455a793bf3bf9c70de3d28526aa8311" + integrity sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw== + +"@img/sharp-darwin-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz#6e0732dcade126b6670af7aa17060b926835ea86" + integrity sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w== + optionalDependencies: + "@img/sharp-libvips-darwin-arm64" "1.2.4" + +"@img/sharp-darwin-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz#19bc1dd6eba6d5a96283498b9c9f401180ee9c7b" + integrity sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw== + optionalDependencies: + "@img/sharp-libvips-darwin-x64" "1.2.4" + +"@img/sharp-libvips-darwin-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz#2894c0cb87d42276c3889942e8e2db517a492c43" + integrity sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g== + +"@img/sharp-libvips-darwin-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz#e63681f4539a94af9cd17246ed8881734386f8cc" + integrity sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg== + +"@img/sharp-libvips-linux-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz#b1b288b36864b3bce545ad91fa6dadcf1a4ad318" + integrity sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw== + +"@img/sharp-libvips-linux-arm@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz#b9260dd1ebe6f9e3bdbcbdcac9d2ac125f35852d" + integrity sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A== + +"@img/sharp-libvips-linux-ppc64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz#4b83ecf2a829057222b38848c7b022e7b4d07aa7" + integrity sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA== + +"@img/sharp-libvips-linux-riscv64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz#880b4678009e5a2080af192332b00b0aaf8a48de" + integrity sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA== + +"@img/sharp-libvips-linux-s390x@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz#74f343c8e10fad821b38f75ced30488939dc59ec" + integrity sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ== + +"@img/sharp-libvips-linux-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz#df4183e8bd8410f7d61b66859a35edeab0a531ce" + integrity sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw== + +"@img/sharp-libvips-linuxmusl-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz#c8d6b48211df67137541007ee8d1b7b1f8ca8e06" + integrity sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw== + +"@img/sharp-libvips-linuxmusl-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz#be11c75bee5b080cbee31a153a8779448f919f75" + integrity sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg== + +"@img/sharp-linux-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz#7aa7764ef9c001f15e610546d42fce56911790cc" + integrity sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg== + optionalDependencies: + "@img/sharp-libvips-linux-arm64" "1.2.4" + +"@img/sharp-linux-arm@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz#5fb0c3695dd12522d39c3ff7a6bc816461780a0d" + integrity sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw== + optionalDependencies: + "@img/sharp-libvips-linux-arm" "1.2.4" + +"@img/sharp-linux-ppc64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz#9c213a81520a20caf66978f3d4c07456ff2e0813" + integrity sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA== + optionalDependencies: + "@img/sharp-libvips-linux-ppc64" "1.2.4" + +"@img/sharp-linux-riscv64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz#cdd28182774eadbe04f62675a16aabbccb833f60" + integrity sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw== + optionalDependencies: + "@img/sharp-libvips-linux-riscv64" "1.2.4" + +"@img/sharp-linux-s390x@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz#93eac601b9f329bb27917e0e19098c722d630df7" + integrity sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg== + optionalDependencies: + "@img/sharp-libvips-linux-s390x" "1.2.4" + +"@img/sharp-linux-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz#55abc7cd754ffca5002b6c2b719abdfc846819a8" + integrity sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ== + optionalDependencies: + "@img/sharp-libvips-linux-x64" "1.2.4" + +"@img/sharp-linuxmusl-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz#d6515ee971bb62f73001a4829b9d865a11b77086" + integrity sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-arm64" "1.2.4" + +"@img/sharp-linuxmusl-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz#d97978aec7c5212f999714f2f5b736457e12ee9f" + integrity sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q== + optionalDependencies: + "@img/sharp-libvips-linuxmusl-x64" "1.2.4" + +"@img/sharp-wasm32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz#2f15803aa626f8c59dd7c9d0bbc766f1ab52cfa0" + integrity sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw== + dependencies: + "@emnapi/runtime" "^1.7.0" + +"@img/sharp-win32-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz#3706e9e3ac35fddfc1c87f94e849f1b75307ce0a" + integrity sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g== + +"@img/sharp-win32-ia32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz#0b71166599b049e032f085fb9263e02f4e4788de" + integrity sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg== + +"@img/sharp-win32-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz#a81ffb00e69267cd0a1d626eaedb8a8430b2b2f8" + integrity sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw== + +"@internationalized/date@^3.10.0": + version "3.10.0" + resolved "https://registry.yarnpkg.com/@internationalized/date/-/date-3.10.0.tgz#056db64a4facdf48c6937ad498a882a8151d640a" + integrity sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw== + dependencies: + "@swc/helpers" "^0.5.0" + +"@internationalized/message@^3.1.8": + version "3.1.8" + resolved "https://registry.yarnpkg.com/@internationalized/message/-/message-3.1.8.tgz#7181e8178f0868535f4507a573bf285e925832cb" + integrity sha512-Rwk3j/TlYZhn3HQ6PyXUV0XP9Uv42jqZGNegt0BXlxjE6G3+LwHjbQZAGHhCnCPdaA6Tvd3ma/7QzLlLkJxAWA== + dependencies: + "@swc/helpers" "^0.5.0" + intl-messageformat "^10.1.0" + +"@internationalized/number@^3.6.5": + version "3.6.5" + resolved "https://registry.yarnpkg.com/@internationalized/number/-/number-3.6.5.tgz#1103f2832ca8d9dd3e4eecf95733d497791dbbbe" + integrity sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g== + dependencies: + "@swc/helpers" "^0.5.0" + +"@internationalized/string@^3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@internationalized/string/-/string-3.2.7.tgz#76ae10f1e6e1fdaec7d0028a3f807d37a71bd2dd" + integrity sha512-D4OHBjrinH+PFZPvfCXvG28n2LSykWcJ7GIioQL+ok0LON15SdfoUssoHzzOUmVZLbRoREsQXVzA6r8JKsbP6A== + dependencies: + "@swc/helpers" "^0.5.0" + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@isaacs/fs-minipass@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" + integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + dependencies: + minipass "^7.0.4" + +"@isaacs/ttlcache@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz#21fb23db34e9b6220c6ba023a0118a2dd3461ea2" + integrity sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-30.2.0.tgz#c52fcd5b58fdd2e8eb66b2fd8ae56f2f64d05b28" + integrity sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + jest-message-util "30.2.0" + jest-util "30.2.0" + slash "^3.0.0" + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-30.2.0.tgz#813d59faa5abd5510964a8b3a7b17cc77b775275" + integrity sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ== + dependencies: + "@jest/console" "30.2.0" + "@jest/pattern" "30.0.1" + "@jest/reporters" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + ci-info "^4.2.0" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-changed-files "30.2.0" + jest-config "30.2.0" + jest-haste-map "30.2.0" + jest-message-util "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-resolve-dependencies "30.2.0" + jest-runner "30.2.0" + jest-runtime "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + jest-watcher "30.2.0" + micromatch "^4.0.8" + pretty-format "30.2.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/create-cache-key-function@^29.2.1", "@jest/create-cache-key-function@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" + integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== + dependencies: + "@jest/types" "^29.6.3" + +"@jest/diff-sequences@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz#0ededeae4d071f5c8ffe3678d15f3a1be09156be" + integrity sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw== + +"@jest/environment@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-30.2.0.tgz#1e673cdb8b93ded707cf6631b8353011460831fa" + integrity sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g== + dependencies: + "@jest/fake-timers" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + jest-mock "30.2.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-30.2.0.tgz#4f95413d4748454fdb17404bf1141827d15e6011" + integrity sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA== + dependencies: + "@jest/get-type" "30.1.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-30.2.0.tgz#9a5968499bb8add2bbb09136f69f7df5ddbf3185" + integrity sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA== + dependencies: + expect "30.2.0" + jest-snapshot "30.2.0" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-30.2.0.tgz#0941ddc28a339b9819542495b5408622dc9e94ec" + integrity sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw== + dependencies: + "@jest/types" "30.2.0" + "@sinonjs/fake-timers" "^13.0.0" + "@types/node" "*" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-util "30.2.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/get-type@30.1.0": + version "30.1.0" + resolved "https://registry.yarnpkg.com/@jest/get-type/-/get-type-30.1.0.tgz#4fcb4dc2ebcf0811be1c04fd1cb79c2dba431cbc" + integrity sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA== + +"@jest/globals@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-30.2.0.tgz#2f4b696d5862664b89c4ee2e49ae24d2bb7e0988" + integrity sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw== + dependencies: + "@jest/environment" "30.2.0" + "@jest/expect" "30.2.0" + "@jest/types" "30.2.0" + jest-mock "30.2.0" + +"@jest/globals@^29.2.1", "@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/pattern@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/pattern/-/pattern-30.0.1.tgz#d5304147f49a052900b4b853dedb111d080e199f" + integrity sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA== + dependencies: + "@types/node" "*" + jest-regex-util "30.0.1" + +"@jest/reporters@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-30.2.0.tgz#a36b28fcbaf0c4595250b108e6f20e363348fd91" + integrity sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@jridgewell/trace-mapping" "^0.3.25" + "@types/node" "*" + chalk "^4.1.2" + collect-v8-coverage "^1.0.2" + exit-x "^0.2.2" + glob "^10.3.10" + graceful-fs "^4.2.11" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^5.0.0" + istanbul-reports "^3.1.3" + jest-message-util "30.2.0" + jest-util "30.2.0" + jest-worker "30.2.0" + slash "^3.0.0" + string-length "^4.0.2" + v8-to-istanbul "^9.0.1" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@30.0.5": + version "30.0.5" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-30.0.5.tgz#7bdf69fc5a368a5abdb49fd91036c55225846473" + integrity sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA== + dependencies: + "@sinclair/typebox" "^0.34.0" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/snapshot-utils@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz#387858eb90c2f98f67bff327435a532ac5309fbe" + integrity sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug== + dependencies: + "@jest/types" "30.2.0" + chalk "^4.1.2" + graceful-fs "^4.2.11" + natural-compare "^1.4.0" + +"@jest/source-map@30.0.1": + version "30.0.1" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-30.0.1.tgz#305ebec50468f13e658b3d5c26f85107a5620aaa" + integrity sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg== + dependencies: + "@jridgewell/trace-mapping" "^0.3.25" + callsites "^3.1.0" + graceful-fs "^4.2.11" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-30.2.0.tgz#9c0124377fb7996cdffb86eda3dbc56eacab363d" + integrity sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg== + dependencies: + "@jest/console" "30.2.0" + "@jest/types" "30.2.0" + "@types/istanbul-lib-coverage" "^2.0.6" + collect-v8-coverage "^1.0.2" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz#bf0066bc72e176d58f5dfa7f212b6e7eee44f221" + integrity sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q== + dependencies: + "@jest/test-result" "30.2.0" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + slash "^3.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-30.2.0.tgz#54bef1a4510dcbd58d5d4de4fe2980a63077ef2a" + integrity sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA== + dependencies: + "@babel/core" "^7.27.4" + "@jest/types" "30.2.0" + "@jridgewell/trace-mapping" "^0.3.25" + babel-plugin-istanbul "^7.0.1" + chalk "^4.1.2" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-regex-util "30.0.1" + jest-util "30.2.0" + micromatch "^4.0.8" + pirates "^4.0.7" + slash "^3.0.0" + write-file-atomic "^5.0.1" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@30.2.0": + version "30.2.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-30.2.0.tgz#1c678a7924b8f59eafd4c77d56b6d0ba976d62b8" + integrity sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg== + dependencies: + "@jest/pattern" "30.0.1" + "@jest/schemas" "30.0.5" + "@types/istanbul-lib-coverage" "^2.0.6" + "@types/istanbul-reports" "^3.0.4" + "@types/node" "*" + "@types/yargs" "^17.0.33" + chalk "^4.1.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.5": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/source-map@^0.3.3": + version "0.3.11" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.11.tgz#b21835cbd36db656b857c2ad02ebd413cc13a9ba" + integrity sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25", "@jridgewell/trace-mapping@^0.3.28": + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@kurkle/color@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.4.tgz#4d4ff677e1609214fc71c580125ddddd86abcabf" + integrity sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w== + +"@legendapp/motion@latest": + version "2.5.3" + resolved "https://registry.yarnpkg.com/@legendapp/motion/-/motion-2.5.3.tgz#f9a4c07c76eee757c5ca206085440d14cc28001b" + integrity sha512-IcNiStiK3qG5LaIPLC8fVV0BHIrkf7EY5HfOv3xbuMH0z4D945yaaEDafP5bboHf/uj9XRjTQHVTtZgwpMNlHw== + dependencies: + "@legendapp/tools" "2.0.1" + +"@legendapp/tools@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@legendapp/tools/-/tools-2.0.1.tgz#995fe6cb3e2398b939f645505aa8e1abc84bd07f" + integrity sha512-Kxt0HWvWElRK6oybHRzcYxdgaKGwuaiRNreS7usW7QuHXRIHaH4yMcW2YNRG4DHE5fpefv+Bno/BohQcCE4FaA== + +"@lezer/common@^1.0.0", "@lezer/common@^1.1.0", "@lezer/common@^1.2.0", "@lezer/common@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.3.0.tgz#123427ec4c53c2c8367415b4441e555b4f85c696" + integrity sha512-L9X8uHCYU310o99L3/MpJKYxPzXPOS7S0NmBaM7UO/x2Kb2WbmMLSkfvdr1KxRIFYOpbY0Jhn7CfLSUDzL8arQ== + +"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.3.tgz#a20f324b71148a2ea9ba6ff42e58bbfaec702857" + integrity sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g== + dependencies: + "@lezer/common" "^1.3.0" + +"@lezer/javascript@^1.0.0": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.5.4.tgz#11746955f957d33c0933f17d7594db54a8b4beea" + integrity sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA== + dependencies: + "@lezer/common" "^1.2.0" + "@lezer/highlight" "^1.1.3" + "@lezer/lr" "^1.3.0" + +"@lezer/lr@^1.0.0", "@lezer/lr@^1.3.0": + version "1.4.3" + resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.3.tgz#51b252ff8ff9fea863819de7f4b6501ccf69d403" + integrity sha512-yenN5SqAxAPv/qMnpWW0AT7l+SxVrgG+u0tNsRQWqbrz66HIl8DnEbBObvy21J5K7+I1v7gsAnlE2VQ5yYVSeA== + dependencies: + "@lezer/common" "^1.0.0" + +"@linear/sdk@52.0.0": + version "52.0.0" + resolved "https://registry.yarnpkg.com/@linear/sdk/-/sdk-52.0.0.tgz#9fc579e436b11b59db295d9887dbe37fceb6c7ba" + integrity sha512-Dd8fPBcMa0E3Az8v2mICyAjCMF5169dx1TDhF6LrWZbQCeg3xXkL7uZUuvljC79XmK1cG/IRj+iHE0ekepMkUw== + dependencies: + "@graphql-typed-document-node/core" "^3.1.0" + graphql "^15.4.0" + isomorphic-unfetch "^3.1.0" + +"@linear/sdk@^52.0.0": + version "52.1.0" + resolved "https://registry.yarnpkg.com/@linear/sdk/-/sdk-52.1.0.tgz#644a1deba9cf6f7995ea39b1fa682892057bcaeb" + integrity sha512-7YEoF2ZhX02omUiGQWeDf4YYxdDVz73MF1N5GuiF1pLBYxSgkBSo1H63qwYpeht1/os7RIa2kY4Bu8M4dD0d8g== + dependencies: + "@graphql-typed-document-node/core" "^3.1.0" + graphql "^15.4.0" + isomorphic-unfetch "^3.1.0" + +"@lit-labs/ssr-dom-shim@^1.5.0": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.5.1.tgz#3166900c0d481f03d6d4133686e0febf760d521d" + integrity sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA== + +"@lit/reactive-element@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-2.1.2.tgz#4c6af9042603c98e61ba90b294607904d51b61cb" + integrity sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.5.0" + +"@marijn/find-cluster-break@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" + integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== + +"@mayanfinance/swap-sdk@^9.3.0": + version "9.8.0" + resolved "https://registry.yarnpkg.com/@mayanfinance/swap-sdk/-/swap-sdk-9.8.0.tgz#cb53b3713d020470bbbdb7053ef71a743fb2aefe" + integrity sha512-K+xuK+Ot5u1olFRHhSIi28zCMIMrolxdy/sGcJFCQz3kfCkULIBtp6+oWZ5dhHc1RJ3J+VQUEmX476GkDYRh7A== + dependencies: + "@solana/buffer-layout" "^4 || ^3" + "@solana/web3.js" "^1.87.6" + bs58 "^6.0.0" + cross-fetch "^3.1.5" + ethers "^6" + js-sha256 "^0.9.0" + js-sha3 "^0.8.0" + +"@metamask/eth-json-rpc-provider@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@metamask/eth-json-rpc-provider/-/eth-json-rpc-provider-1.0.1.tgz#3fd5316c767847f4ca107518b611b15396a5a32c" + integrity sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA== + dependencies: + "@metamask/json-rpc-engine" "^7.0.0" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^5.0.1" + +"@metamask/json-rpc-engine@^7.0.0": + version "7.3.3" + resolved "https://registry.yarnpkg.com/@metamask/json-rpc-engine/-/json-rpc-engine-7.3.3.tgz#f2b30a2164558014bfcca45db10f5af291d989af" + integrity sha512-dwZPq8wx9yV3IX2caLi9q9xZBw2XeIoYqdyihDDDpuHVCEiqadJLwqM3zy+uwf6F1QYQ65A8aOMQg1Uw7LMLNg== + dependencies: + "@metamask/rpc-errors" "^6.2.1" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^8.3.0" + +"@metamask/json-rpc-engine@^8.0.1", "@metamask/json-rpc-engine@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@metamask/json-rpc-engine/-/json-rpc-engine-8.0.2.tgz#29510a871a8edef892f838ee854db18de0bf0d14" + integrity sha512-IoQPmql8q7ABLruW7i4EYVHWUbF74yrp63bRuXV5Zf9BQwcn5H9Ww1eLtROYvI1bUXwOiHZ6qT5CWTrDc/t/AA== + dependencies: + "@metamask/rpc-errors" "^6.2.1" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^8.3.0" + +"@metamask/json-rpc-middleware-stream@^7.0.1": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@metamask/json-rpc-middleware-stream/-/json-rpc-middleware-stream-7.0.2.tgz#2e8b2cbc38968e3c6239a9144c35bbb08a8fb57d" + integrity sha512-yUdzsJK04Ev98Ck4D7lmRNQ8FPioXYhEUZOMS01LXW8qTvPGiRVXmVltj2p4wrLkh0vW7u6nv0mNl5xzC5Qmfg== + dependencies: + "@metamask/json-rpc-engine" "^8.0.2" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^8.3.0" + readable-stream "^3.6.2" + +"@metamask/object-multiplex@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@metamask/object-multiplex/-/object-multiplex-2.1.0.tgz#5e2e908fc46aee581cbba809870eeee0e571cbb6" + integrity sha512-4vKIiv0DQxljcXwfpnbsXcfa5glMj5Zg9mqn4xpIWqkv6uJ2ma5/GtUfLFSxhlxnR8asRMv8dDmWya1Tc1sDFA== + dependencies: + once "^1.4.0" + readable-stream "^3.6.2" + +"@metamask/onboarding@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@metamask/onboarding/-/onboarding-1.0.1.tgz#14a36e1e175e2f69f09598e2008ab6dc1b3297e6" + integrity sha512-FqHhAsCI+Vacx2qa5mAFcWNSrTcVGMNjzxVgaX8ECSny/BJ9/vgXP9V7WF/8vb9DltPeQkxr+Fnfmm6GHfmdTQ== + dependencies: + bowser "^2.9.0" + +"@metamask/providers@16.1.0": + version "16.1.0" + resolved "https://registry.yarnpkg.com/@metamask/providers/-/providers-16.1.0.tgz#7da593d17c541580fa3beab8d9d8a9b9ce19ea07" + integrity sha512-znVCvux30+3SaUwcUGaSf+pUckzT5ukPRpcBmy+muBLC0yaWnBcvDqGfcsw6CBIenUdFrVoAFa8B6jsuCY/a+g== + dependencies: + "@metamask/json-rpc-engine" "^8.0.1" + "@metamask/json-rpc-middleware-stream" "^7.0.1" + "@metamask/object-multiplex" "^2.0.0" + "@metamask/rpc-errors" "^6.2.1" + "@metamask/safe-event-emitter" "^3.1.1" + "@metamask/utils" "^8.3.0" + detect-browser "^5.2.0" + extension-port-stream "^3.0.0" + fast-deep-equal "^3.1.3" + is-stream "^2.0.0" + readable-stream "^3.6.2" + webextension-polyfill "^0.10.0" + +"@metamask/rpc-errors@7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@metamask/rpc-errors/-/rpc-errors-7.0.2.tgz#d07b2ebfcf111556dfe93dc78699742ebe755359" + integrity sha512-YYYHsVYd46XwY2QZzpGeU4PSdRhHdxnzkB8piWGvJW2xbikZ3R+epAYEL4q/K8bh9JPTucsUdwRFnACor1aOYw== + dependencies: + "@metamask/utils" "^11.0.1" + fast-safe-stringify "^2.0.6" + +"@metamask/rpc-errors@^6.2.1": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@metamask/rpc-errors/-/rpc-errors-6.4.0.tgz#a7ce01c06c9a347ab853e55818ac5654a73bd006" + integrity sha512-1ugFO1UoirU2esS3juZanS/Fo8C8XYocCuBpfZI5N7ECtoG+zu0wF+uWZASik6CkO6w9n/Iebt4iI4pT0vptpg== + dependencies: + "@metamask/utils" "^9.0.0" + fast-safe-stringify "^2.0.6" + +"@metamask/safe-event-emitter@2.0.0", "@metamask/safe-event-emitter@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" + integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q== + +"@metamask/safe-event-emitter@^3.0.0", "@metamask/safe-event-emitter@^3.1.1": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-3.1.2.tgz#bfac8c7a1a149b5bbfe98f59fbfea512dfa3bad4" + integrity sha512-5yb2gMI1BDm0JybZezeoX/3XhPDOtTbcFvpTXM9kxsoZjPZFh4XciqRbpD6N86HYZqWDhEaKUDuOyR0sQHEjMA== + +"@metamask/sdk-analytics@0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@metamask/sdk-analytics/-/sdk-analytics-0.0.5.tgz#ea10b15730d015af1da2225c8fe4fcf85b3fa77b" + integrity sha512-fDah+keS1RjSUlC8GmYXvx6Y26s3Ax1U9hGpWb6GSY5SAdmTSIqp2CvYy6yW0WgLhnYhW+6xERuD0eVqV63QIQ== + dependencies: + openapi-fetch "^0.13.5" + +"@metamask/sdk-communication-layer@0.33.1": + version "0.33.1" + resolved "https://registry.yarnpkg.com/@metamask/sdk-communication-layer/-/sdk-communication-layer-0.33.1.tgz#53311c448bfcc08275f03630811fb3de8356d389" + integrity sha512-0bI9hkysxcfbZ/lk0T2+aKVo1j0ynQVTuB3sJ5ssPWlz+Z3VwveCkP1O7EVu1tsVVCb0YV5WxK9zmURu2FIiaA== + dependencies: + "@metamask/sdk-analytics" "0.0.5" + bufferutil "^4.0.8" + date-fns "^2.29.3" + debug "4.3.4" + utf-8-validate "^5.0.2" + uuid "^8.3.2" + +"@metamask/sdk-install-modal-web@0.32.1": + version "0.32.1" + resolved "https://registry.yarnpkg.com/@metamask/sdk-install-modal-web/-/sdk-install-modal-web-0.32.1.tgz#bc837136b19c261835a5907f9b504c059ee64875" + integrity sha512-MGmAo6qSjf1tuYXhCu2EZLftq+DSt5Z7fsIKr2P+lDgdTPWgLfZB1tJKzNcwKKOdf6q9Qmmxn7lJuI/gq5LrKw== + dependencies: + "@paulmillr/qr" "^0.2.1" + +"@metamask/sdk@0.33.1": + version "0.33.1" + resolved "https://registry.yarnpkg.com/@metamask/sdk/-/sdk-0.33.1.tgz#c3376444b9c5b42fbfd434edf414db613ab68c42" + integrity sha512-1mcOQVGr9rSrVcbKPNVzbZ8eCl1K0FATsYH3WJ/MH4WcZDWGECWrXJPNMZoEAkLxWiMe8jOQBumg2pmcDa9zpQ== + dependencies: + "@babel/runtime" "^7.26.0" + "@metamask/onboarding" "^1.0.1" + "@metamask/providers" "16.1.0" + "@metamask/sdk-analytics" "0.0.5" + "@metamask/sdk-communication-layer" "0.33.1" + "@metamask/sdk-install-modal-web" "0.32.1" + "@paulmillr/qr" "^0.2.1" + bowser "^2.9.0" + cross-fetch "^4.0.0" + debug "4.3.4" + eciesjs "^0.4.11" + eth-rpc-errors "^4.0.3" + eventemitter2 "^6.4.9" + obj-multiplex "^1.0.0" + pump "^3.0.0" + readable-stream "^3.6.2" + socket.io-client "^4.5.1" + tslib "^2.6.0" + util "^0.12.4" + uuid "^8.3.2" + +"@metamask/superstruct@^3.0.0", "@metamask/superstruct@^3.1.0": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@metamask/superstruct/-/superstruct-3.2.1.tgz#fca933017c5b78529f8f525560cef32c57e889d2" + integrity sha512-fLgJnDOXFmuVlB38rUN5SmU7hAFQcCjrg3Vrxz67KTY7YHFnSNEKvX4avmEBdOI0yTCxZjwMCFEqsC8k2+Wd3g== + +"@metamask/utils@^11.0.1": + version "11.10.0" + resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-11.10.0.tgz#2efd5aa14f3535d43a4b709a37ad349b571252f1" + integrity sha512-+bWmTOANx1MbBW6RFM8Se4ZoigFYGXiuIrkhjj4XnG5Aez8uWaTSZ76yn9srKKClv+PoEVoAuVtcUOogFEMUNA== + dependencies: + "@ethereumjs/tx" "^4.2.0" + "@metamask/superstruct" "^3.1.0" + "@noble/hashes" "^1.3.1" + "@scure/base" "^1.1.3" + "@types/debug" "^4.1.7" + "@types/lodash" "^4.17.20" + debug "^4.3.4" + lodash "^4.17.21" + pony-cause "^2.1.10" + semver "^7.5.4" + uuid "^9.0.1" + +"@metamask/utils@^5.0.1": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-5.0.2.tgz#140ba5061d90d9dac0280c19cab101bc18c8857c" + integrity sha512-yfmE79bRQtnMzarnKfX7AEJBwFTxvTyw3nBQlu/5rmGXrjAeAMltoGxO62TFurxrQAFMNa/fEjIHNvungZp0+g== + dependencies: + "@ethereumjs/tx" "^4.1.2" + "@types/debug" "^4.1.7" + debug "^4.3.4" + semver "^7.3.8" + superstruct "^1.0.3" + +"@metamask/utils@^8.3.0": + version "8.5.0" + resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-8.5.0.tgz#ddd0d4012d5191809404c97648a837ea9962cceb" + integrity sha512-I6bkduevXb72TIM9q2LRO63JSsF9EXduh3sBr9oybNX2hNNpr/j1tEjXrsG0Uabm4MJ1xkGAQEMwifvKZIkyxQ== + dependencies: + "@ethereumjs/tx" "^4.2.0" + "@metamask/superstruct" "^3.0.0" + "@noble/hashes" "^1.3.1" + "@scure/base" "^1.1.3" + "@types/debug" "^4.1.7" + debug "^4.3.4" + pony-cause "^2.1.10" + semver "^7.5.4" + uuid "^9.0.1" + +"@metamask/utils@^9.0.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-9.3.0.tgz#4726bd7f5d6a43ea8425b6d663ab9207f617c2d1" + integrity sha512-w8CVbdkDrVXFJbfBSlDfafDR6BAkpDmv1bC1UJVCoVny5tW2RKAdn9i68Xf7asYT4TnUhl/hN4zfUiKQq9II4g== + dependencies: + "@ethereumjs/tx" "^4.2.0" + "@metamask/superstruct" "^3.1.0" + "@noble/hashes" "^1.3.1" + "@scure/base" "^1.1.3" + "@types/debug" "^4.1.7" + debug "^4.3.4" + pony-cause "^2.1.10" + semver "^7.5.4" + uuid "^9.0.1" + +"@modelcontextprotocol/sdk@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.3.1.tgz#a5d34a7a815a56a47d6de252a6f72707fc1d26b8" + integrity sha512-Fu3HstNO03/S5nvwh3KjRfP5JOSMl6IbOBxRl6JBDXMFRHPSJ4kiiV7n5yJjY51GtrFw3Y+V/vdsweN5bxULWQ== + dependencies: + content-type "^1.0.5" + raw-body "^3.0.0" + zod "^3.23.8" + zod-to-json-schema "^3.24.1" + +"@modelcontextprotocol/sdk@^1.0.0": + version "1.21.1" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.21.1.tgz#8fba02e7581d49cc9b047aab0cfd334043321fe5" + integrity sha512-UyLFcJLDvUuZbGnaQqXFT32CpPpGj7VS19roLut6gkQVhb439xUzYWbsUvdI3ZPL+2hnFosuugtYWE0Mcs1rmQ== + dependencies: + ajv "^8.17.1" + ajv-formats "^3.0.1" + content-type "^1.0.5" + cors "^2.8.5" + cross-spawn "^7.0.5" + eventsource "^3.0.2" + eventsource-parser "^3.0.0" + express "^5.0.1" + express-rate-limit "^7.5.0" + pkce-challenge "^5.0.0" + raw-body "^3.0.0" + zod "^3.23.8" + zod-to-json-schema "^3.24.1" + +"@napi-rs/wasm-runtime@^0.2.11": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + +"@next/env@14.2.35": + version "14.2.35" + resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.35.tgz#e979016d0ca8500a47d41ffd02625fe29b8df35a" + integrity sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ== + +"@next/env@15.5.9": + version "15.5.9" + resolved "https://registry.yarnpkg.com/@next/env/-/env-15.5.9.tgz#53c2c34dc17cd87b61f70c6cc211e303123b2ab8" + integrity sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg== + +"@next/eslint-plugin-next@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.7.tgz#69ab374b5f4a8a19a7cc1e2b89e5d50035cfb02d" + integrity sha512-DtRU2N7BkGr8r+pExfuWHwMEPX5SD57FeA6pxdgCHODo+b/UgIgjE+rgWKtJAbEbGhVZ2jtHn4g3wNhWFoNBQQ== + dependencies: + fast-glob "3.3.1" + +"@next/swc-darwin-arm64@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz#9e74a4223f1e5e39ca4f9f85709e0d95b869b298" + integrity sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA== + +"@next/swc-darwin-arm64@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.7.tgz#f0c9ccfec2cd87cbd4b241ce4c779a7017aed958" + integrity sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw== + +"@next/swc-darwin-x64@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz#fcf0c45938da9b0cc2ec86357d6aefca90bd17f3" + integrity sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA== + +"@next/swc-darwin-x64@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.7.tgz#18009e9fcffc5c0687cc9db24182ddeac56280d9" + integrity sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg== + +"@next/swc-linux-arm64-gnu@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz#837f91a740eb4420c06f34c4677645315479d9be" + integrity sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw== + +"@next/swc-linux-arm64-gnu@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.7.tgz#fe7c7e08264cf522d4e524299f6d3e63d68d579a" + integrity sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA== + +"@next/swc-linux-arm64-musl@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz#dc8903469e5c887b25e3c2217a048bd30c58d3d4" + integrity sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg== + +"@next/swc-linux-arm64-musl@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.7.tgz#94228fe293475ec34a5a54284e1056876f43a3cf" + integrity sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw== + +"@next/swc-linux-x64-gnu@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz#344438be592b6b28cc540194274561e41f9933e5" + integrity sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg== + +"@next/swc-linux-x64-gnu@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.7.tgz#078c71201dfe7fcfb8fa6dc92aae6c94bc011cdc" + integrity sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw== + +"@next/swc-linux-x64-musl@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz#3379fad5e0181000b2a4fac0b80f7ca4ffe795c8" + integrity sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA== + +"@next/swc-linux-x64-musl@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.7.tgz#72947f5357f9226292353e0bb775643da3c7a182" + integrity sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA== + +"@next/swc-win32-arm64-msvc@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz#bca8f4dde34656aef8e99f1e5696de255c2f00e5" + integrity sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ== + +"@next/swc-win32-arm64-msvc@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.7.tgz#397b912cd51c6a80e32b9c0507ecd82514353941" + integrity sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ== + +"@next/swc-win32-ia32-msvc@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz#a69c581483ea51dd3b8907ce33bb101fe07ec1df" + integrity sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q== + +"@next/swc-win32-x64-msvc@14.2.33": + version "14.2.33" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz#f1a40062530c17c35a86d8c430b3ae465eb7cea1" + integrity sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg== + +"@next/swc-win32-x64-msvc@15.5.7": + version "15.5.7" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.7.tgz#e02b543d9dc6c1631d4ac239cb1177245dfedfe4" + integrity sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw== + +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": + version "2.1.8-no-fsevents.3" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" + integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== + +"@noble/ciphers@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.2.1.tgz#3812b72c057a28b44ff0ad4aff5ca846e5b9cdc9" + integrity sha512-rONPWMC7PeExE077uLE4oqWrZ1IvAfz3oH9LibVAcVCopJiA9R62uavnbEzdkVmJYI6M6Zgkbeb07+tWjlq2XA== + +"@noble/ciphers@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.3.0.tgz#f64b8ff886c240e644e5573c097f86e5b43676dc" + integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== + +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.0.tgz#fe035a23959e6aeadf695851b51a87465b5ba8f7" + integrity sha512-j84kjAbzEnQHaSIhRPUmB3/eVXu2k3dKPl2LOrR8fSOIL+89U+7lV117EWHtq/GHM3ReGHM46iRBdZfpc4HRUQ== + dependencies: + "@noble/hashes" "1.7.0" + +"@noble/curves@1.8.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.1.tgz#19bc3970e205c99e4bdb1c64a4785706bce497ff" + integrity sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ== + dependencies: + "@noble/hashes" "1.7.1" + +"@noble/curves@1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.1.tgz#9654a0bc6c13420ae252ddcf975eaf0f58f0a35c" + integrity sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@^1.4.2", "@noble/curves@^1.6.0", "@noble/curves@^1.8.0", "@noble/curves@^1.9.7", "@noble/curves@~1.9.0": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@~1.8.1": + version "1.8.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7" + integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== + dependencies: + "@noble/hashes" "1.7.2" + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/hashes@1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.0.tgz#5d9e33af2c7d04fee35de1519b80c958b2e35e39" + integrity sha512-HXydb0DgzTpDPwbVeDGCG1gIu7X6+AuU6Zl6av/E/KG8LMsvPntvq+w17CHRpKBmN6Ybdrt1eP3k4cj8DJa78w== + +"@noble/hashes@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.1.tgz#5738f6d765710921e7a751e00c20ae091ed8db0f" + integrity sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ== + +"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.2.tgz#d53c65a21658fb02f3303e7ee3ba89d6754c64b4" + integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== + +"@noble/hashes@1.8.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0", "@noble/hashes@^1.5.0", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@nolyfill/is-core-module@1.0.39": + version "1.0.39" + resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e" + integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA== + +"@notifee/react-native@=7.8.2": + version "7.8.2" + resolved "https://registry.yarnpkg.com/@notifee/react-native/-/react-native-7.8.2.tgz#72d3199ae830b4128ddaef3c1c2f11604759c9c4" + integrity sha512-VG4IkWJIlOKqXwa3aExC3WFCVCGCC9BA55Ivg0SMRfEs+ruvYy/zlLANcrVGiPtgkUEryXDhA8SXx9+JcO8oLA== + +"@octokit/auth-token@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-6.0.0.tgz#b02e9c08a2d8937df09a2a981f226ad219174c53" + integrity sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w== + +"@octokit/core@^7.0.6": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-7.0.6.tgz#0d58704391c6b681dec1117240ea4d2a98ac3916" + integrity sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q== + dependencies: + "@octokit/auth-token" "^6.0.0" + "@octokit/graphql" "^9.0.3" + "@octokit/request" "^10.0.6" + "@octokit/request-error" "^7.0.2" + "@octokit/types" "^16.0.0" + before-after-hook "^4.0.0" + universal-user-agent "^7.0.0" + +"@octokit/endpoint@^11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-11.0.2.tgz#a8d955e053a244938b81d86cd73efd2dcb5ef5af" + integrity sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ== + dependencies: + "@octokit/types" "^16.0.0" + universal-user-agent "^7.0.2" + +"@octokit/graphql@^9.0.3": + version "9.0.3" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-9.0.3.tgz#5b8341c225909e924b466705c13477face869456" + integrity sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA== + dependencies: + "@octokit/request" "^10.0.6" + "@octokit/types" "^16.0.0" + universal-user-agent "^7.0.0" + +"@octokit/openapi-types@^27.0.0": + version "27.0.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-27.0.0.tgz#374ea53781965fd02a9d36cacb97e152cefff12d" + integrity sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA== + +"@octokit/plugin-paginate-rest@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz#44dc9fff2dacb148d4c5c788b573ddc044503026" + integrity sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw== + dependencies: + "@octokit/types" "^16.0.0" + +"@octokit/plugin-request-log@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz#de1c1e557df6c08adb631bf78264fa741e01b317" + integrity sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q== + +"@octokit/plugin-rest-endpoint-methods@^17.0.0": + version "17.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz#8c54397d3a4060356a1c8a974191ebf945924105" + integrity sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw== + dependencies: + "@octokit/types" "^16.0.0" + +"@octokit/request-error@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-7.0.2.tgz#2455f45385fdec0867fad39ee78dd7461cbd4dac" + integrity sha512-U8piOROoQQUyExw5c6dTkU3GKxts5/ERRThIauNL7yaRoeXW0q/5bgHWT7JfWBw1UyrbK8ERId2wVkcB32n0uQ== + dependencies: + "@octokit/types" "^16.0.0" + +"@octokit/request@^10.0.6": + version "10.0.6" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-10.0.6.tgz#c12214f86b1e01fb0915c4f3bcbe076433ba975d" + integrity sha512-FO+UgZCUu+pPnZAR+iKdUt64kPE7QW7ciqpldaMXaNzixz5Jld8dJ31LAUewk0cfSRkNSRKyqG438ba9c/qDlQ== + dependencies: + "@octokit/endpoint" "^11.0.2" + "@octokit/request-error" "^7.0.2" + "@octokit/types" "^16.0.0" + fast-content-type-parse "^3.0.0" + universal-user-agent "^7.0.2" + +"@octokit/rest@^22.0.0": + version "22.0.1" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-22.0.1.tgz#4d866c32b76b711d3f736f91992e2b534163b416" + integrity sha512-Jzbhzl3CEexhnivb1iQ0KJ7s5vvjMWcmRtq5aUsKmKDrRW6z3r84ngmiFKFvpZjpiU/9/S6ITPFRpn5s/3uQJw== + dependencies: + "@octokit/core" "^7.0.6" + "@octokit/plugin-paginate-rest" "^14.0.0" + "@octokit/plugin-request-log" "^6.0.0" + "@octokit/plugin-rest-endpoint-methods" "^17.0.0" + +"@octokit/types@^16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-16.0.0.tgz#fbd7fa590c2ef22af881b1d79758bfaa234dbb7c" + integrity sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg== + dependencies: + "@octokit/openapi-types" "^27.0.0" + +"@paulmillr/qr@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@paulmillr/qr/-/qr-0.2.1.tgz#76ade7080be4ac4824f638146fd8b6db1805eeca" + integrity sha512-IHnV6A+zxU7XwmKFinmYjUcwlyK9+xkG3/s9KcQhI9BjQKycrJ1JRO+FbNYPwZiPKW3je/DR0k7w8/gLa5eaxQ== + +"@pdf-lib/standard-fonts@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz#8ba691c4421f71662ed07c9a0294b44528af2d7f" + integrity sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA== + dependencies: + pako "^1.0.6" + +"@pdf-lib/upng@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@pdf-lib/upng/-/upng-1.0.1.tgz#7dc9c636271aca007a9df4deaf2dd7e7960280cb" + integrity sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ== + dependencies: + pako "^1.0.10" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== + +"@polybase/util@^0.6.6": + version "0.6.6" + resolved "https://registry.yarnpkg.com/@polybase/util/-/util-0.6.6.tgz#b133c2406b0e017232a9e427d9a09318cf08860d" + integrity sha512-4DiFpJZX/5A/zlPEVVlwvI5U7S5h3jJX9qUU3oOAUuehf+CZijoIfztj264SZHQya8nWr5qeTOraogC8Mcfq6A== + dependencies: + "@ethersproject/bytes" "^5.7.0" + "@ethersproject/signing-key" "^5.7.0" + elliptic "^6.5.4" + process "^0.11.10" + secp256k1 "^4.0.3" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + +"@popperjs/core@^2.11.8": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== + +"@posthog/core@1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@posthog/core/-/core-1.5.2.tgz#06f1277c5ac9a3d5a17bc3800172a392e594f44c" + integrity sha512-iedUP3EnOPPxTA2VaIrsrd29lSZnUV+ZrMnvY56timRVeZAXoYCkmjfIs3KBAsF8OUT5h1GXLSkoQdrV0r31OQ== + dependencies: + cross-spawn "^7.0.6" + +"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf" + integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== + +"@protobufjs/base64@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/base64/-/base64-1.1.2.tgz#4c85730e59b9a1f1f349047dbf24296034bb2735" + integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg== + +"@protobufjs/codegen@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@protobufjs/codegen/-/codegen-2.0.4.tgz#7ef37f0d010fb028ad1ad59722e506d9262815cb" + integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg== + +"@protobufjs/eventemitter@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz#355cbc98bafad5978f9ed095f397621f1d066b70" + integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q== + +"@protobufjs/fetch@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/fetch/-/fetch-1.1.0.tgz#ba99fb598614af65700c1619ff06d454b0d84c45" + integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ== + dependencies: + "@protobufjs/aspromise" "^1.1.1" + "@protobufjs/inquire" "^1.1.0" + +"@protobufjs/float@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@protobufjs/float/-/float-1.0.2.tgz#5e9e1abdcb73fc0a7cb8b291df78c8cbd97b87d1" + integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ== + +"@protobufjs/inquire@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/inquire/-/inquire-1.1.0.tgz#ff200e3e7cf2429e2dcafc1140828e8cc638f089" + integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q== + +"@protobufjs/path@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@protobufjs/path/-/path-1.1.2.tgz#6cc2b20c5c9ad6ad0dccfd21ca7673d8d7fbf68d" + integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA== + +"@protobufjs/pool@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/pool/-/pool-1.1.0.tgz#09fd15f2d6d3abfa9b65bc366506d6ad7846ff54" + integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw== + +"@protobufjs/utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" + integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== + +"@react-aria/checkbox@3.2.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@react-aria/checkbox/-/checkbox-3.2.1.tgz#493d9d584b4db474645a4565c4f899ee3a579f07" + integrity sha512-XnypnlVIfhB3CD7eSjSds8hNkzHgnhu0t48I1D0jYdL1O6tQC4UytPdIqlemRYBVHDloZkWerbjenpHnxhv8iA== + dependencies: + "@babel/runtime" "^7.6.2" + "@react-aria/label" "^3.1.1" + "@react-aria/toggle" "^3.1.1" + "@react-aria/utils" "^3.3.0" + "@react-stately/checkbox" "^3.0.1" + "@react-stately/toggle" "^3.2.1" + "@react-types/checkbox" "^3.2.1" + +"@react-aria/dialog@*": + version "3.5.31" + resolved "https://registry.yarnpkg.com/@react-aria/dialog/-/dialog-3.5.31.tgz#1c1682a89dd6a4c6bc7bb0e58ea78eb6f2750a65" + integrity sha512-inxQMyrzX0UBW9Mhraq0nZ4HjHdygQvllzloT1E/RlDd61lr3RbmJR6pLsrbKOTtSvDIBJpCso1xEdHCFNmA0Q== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/overlays" "^3.30.0" + "@react-aria/utils" "^3.31.0" + "@react-types/dialog" "^3.5.22" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/focus@^3.2.3", "@react-aria/focus@^3.21.2": + version "3.21.2" + resolved "https://registry.yarnpkg.com/@react-aria/focus/-/focus-3.21.2.tgz#3ce90450c3ee69f11c0647b4717c26d10941231c" + integrity sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-aria/form@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-aria/form/-/form-3.1.2.tgz#e0aeb608d309594a59f12a7b05eb7374f2033a07" + integrity sha512-R3i7L7Ci61PqZQvOrnL9xJeWEbh28UkTVgkj72EvBBn39y4h7ReH++0stv7rRs8p5ozETSKezBbGfu4UsBewWw== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/form" "^3.2.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/i18n@^3.12.13": + version "3.12.13" + resolved "https://registry.yarnpkg.com/@react-aria/i18n/-/i18n-3.12.13.tgz#7c920d131cd07d4d5af21bd33ea7a5da0ce2ad11" + integrity sha512-YTM2BPg0v1RvmP8keHenJBmlx8FXUKsdYIEX7x6QWRd1hKlcDwphfjzvt0InX9wiLiPHsT5EoBTpuUk8SXc0Mg== + dependencies: + "@internationalized/date" "^3.10.0" + "@internationalized/message" "^3.1.8" + "@internationalized/number" "^3.6.5" + "@internationalized/string" "^3.2.7" + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/interactions@^3.25.6", "@react-aria/interactions@^3.3.2": + version "3.25.6" + resolved "https://registry.yarnpkg.com/@react-aria/interactions/-/interactions-3.25.6.tgz#6fdf287337c5e4285045c35cf94b2ec8ae3b3a49" + integrity sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-stately/flags" "^3.1.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/label@^3.1.1", "@react-aria/label@^3.7.22": + version "3.7.22" + resolved "https://registry.yarnpkg.com/@react-aria/label/-/label-3.7.22.tgz#13fbf1d568c37becca4652e5c5d0b490c29e5e52" + integrity sha512-jLquJeA5ZNqDT64UpTc9XJ7kQYltUlNcgxZ37/v4mHe0UZ7QohCKdKQhXHONb0h2jjNUpp2HOZI8J9++jOpzxA== + dependencies: + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/menu@^3.1.3", "@react-aria/menu@^3.14.1": + version "3.19.3" + resolved "https://registry.yarnpkg.com/@react-aria/menu/-/menu-3.19.3.tgz#65a6dc14b27648be611bf28ab4bbcd2823b612a8" + integrity sha512-52fh8y8b2776R2VrfZPpUBJYC9oTP7XDy+zZuZTxPEd7Ywk0JNUl5F92y6ru22yPkS13sdhrNM/Op+V/KulmAg== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/overlays" "^3.30.0" + "@react-aria/selection" "^3.26.0" + "@react-aria/utils" "^3.31.0" + "@react-stately/collections" "^3.12.8" + "@react-stately/menu" "^3.9.8" + "@react-stately/selection" "^3.20.6" + "@react-stately/tree" "^3.9.3" + "@react-types/button" "^3.14.1" + "@react-types/menu" "^3.10.5" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/overlays@^3.19.0", "@react-aria/overlays@^3.30.0", "@react-aria/overlays@^3.7.0": + version "3.30.0" + resolved "https://registry.yarnpkg.com/@react-aria/overlays/-/overlays-3.30.0.tgz#e19f804c7fb9d99b25e33230cc3c155ed0b3cefb" + integrity sha512-UpjqSjYZx5FAhceWCRVsW6fX1sEwya1fQ/TKkL53FAlLFR8QKuoKqFlmiL43YUFTcGK3UdEOy3cWTleLQwdSmQ== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-aria/visually-hidden" "^3.8.28" + "@react-stately/overlays" "^3.6.20" + "@react-types/button" "^3.14.1" + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/radio@^3.1.2": + version "3.12.2" + resolved "https://registry.yarnpkg.com/@react-aria/radio/-/radio-3.12.2.tgz#48ae0e9ba93e5c29e998fa3b64155a324a87f63e" + integrity sha512-I11f6I90neCh56rT/6ieAs3XyDKvEfbj/QmbU5cX3p+SJpRRPN0vxQi5D1hkh0uxDpeClxygSr31NmZsd4sqfg== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/form" "^3.1.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/utils" "^3.31.0" + "@react-stately/radio" "^3.11.2" + "@react-types/radio" "^3.9.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/selection@^3.26.0", "@react-aria/selection@^3.3.1": + version "3.26.0" + resolved "https://registry.yarnpkg.com/@react-aria/selection/-/selection-3.26.0.tgz#dc5906aa732b0dbd54d26dd6a5f1dc793055e29c" + integrity sha512-ZBH3EfWZ+RfhTj01dH8L17uT7iNbXWS8u77/fUpHgtrm0pwNVhx0TYVnLU1YpazQ/3WVpvWhmBB8sWwD1FlD/g== + dependencies: + "@react-aria/focus" "^3.21.2" + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/selection" "^3.20.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/slider@^3.0.1": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@react-aria/slider/-/slider-3.8.2.tgz#a075205b06fa714733e3aabfdbc63d11f5c67be7" + integrity sha512-6KyUGaVzRE4xAz1LKHbNh1q5wzxe58pdTHFSnxNe6nk1SCoHw7NfI4h2s2m6LgJ0megFxsT0Ir8aHaFyyxmbgg== + dependencies: + "@react-aria/i18n" "^3.12.13" + "@react-aria/interactions" "^3.25.6" + "@react-aria/label" "^3.7.22" + "@react-aria/utils" "^3.31.0" + "@react-stately/slider" "^3.7.2" + "@react-types/shared" "^3.32.1" + "@react-types/slider" "^3.8.2" + "@swc/helpers" "^0.5.0" + +"@react-aria/ssr@^3.0.1", "@react-aria/ssr@^3.9.10": + version "3.9.10" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.9.10.tgz#7fdc09e811944ce0df1d7e713de1449abd7435e6" + integrity sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-aria/toggle@^3.1.1": + version "3.12.2" + resolved "https://registry.yarnpkg.com/@react-aria/toggle/-/toggle-3.12.2.tgz#909c7c8b9bbeb2cc93a18297363eebb46354b0d4" + integrity sha512-g25XLYqJuJpt0/YoYz2Rab8ax+hBfbssllcEFh0v0jiwfk2gwTWfRU9KAZUvxIqbV8Nm8EBmrYychDpDcvW1kw== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-stately/toggle" "^3.9.2" + "@react-types/checkbox" "^3.10.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/utils@^3.3.0", "@react-aria/utils@^3.31.0", "@react-aria/utils@^3.6.0": + version "3.31.0" + resolved "https://registry.yarnpkg.com/@react-aria/utils/-/utils-3.31.0.tgz#4710e35bf658234cf4b53eec9742f25e51637b12" + integrity sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-stately/flags" "^3.1.2" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-aria/visually-hidden@^3.7.0", "@react-aria/visually-hidden@^3.8.1", "@react-aria/visually-hidden@^3.8.28", "@react-aria/visually-hidden@^3.8.6": + version "3.8.28" + resolved "https://registry.yarnpkg.com/@react-aria/visually-hidden/-/visually-hidden-3.8.28.tgz#61fc99c2d2662e7347abe25a421d138a3a81db46" + integrity sha512-KRRjbVVob2CeBidF24dzufMxBveEUtUu7IM+hpdZKB+gxVROoh4XRLPv9SFmaH89Z7D9To3QoykVZoWD0lan6Q== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-native-aria/accordion@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@react-native-aria/accordion/-/accordion-0.0.2.tgz#28e57f5c3690b2b33f36acd6aff7d91a75fbf384" + integrity sha512-2Wa/YDBc2aCunTLpqwxTfCwn1t63KSAIoXd0hqrUGJJF+N2bEs2Hqs9ZgyKJ/hzFxCknVPMqo0fEVE1H23Z5+g== + +"@react-native-aria/checkbox@^0.2.10": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@react-native-aria/checkbox/-/checkbox-0.2.10.tgz#04a35ee9c969456083467d613aedead2eb6d07b8" + integrity sha512-SpjAHmu+NmoztkHggtlBsygOapszjomjo8PtbGxP7rV+3b5iWhmrD2Ztf3Vc4tZMBl/GFslLA3NXp5h47T9Utg== + dependencies: + "@react-aria/checkbox" "3.2.1" + "@react-aria/utils" "^3.6.0" + "@react-native-aria/toggle" "^0.2.11" + "@react-native-aria/utils" "0.2.12" + "@react-stately/toggle" "^3.2.1" + +"@react-native-aria/dialog@^0.0.5": + version "0.0.5" + resolved "https://registry.yarnpkg.com/@react-native-aria/dialog/-/dialog-0.0.5.tgz#aa8d1901cb9e132f0c750adfa2e8091c3aefc28d" + integrity sha512-ZThiWyymf3WiA2EdjStV32pTL3RjAb7H/CL0Zsd1wKNuw1lU9HX6h4UIUpt0MZhcFCUnZjCovNtU9IRwbbdj/Q== + dependencies: + "@react-aria/dialog" "*" + "@react-native-aria/utils" "0.2.12" + "@react-types/dialog" "*" + "@react-types/shared" "*" + +"@react-native-aria/focus@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@react-native-aria/focus/-/focus-0.2.9.tgz#bdfa84f9711843df771877ac436ee3b4f8878b74" + integrity sha512-zVgOIzKwnsyyurUxlZnzUKB2ekK/cmK64sQJIKKUlkJKVxd2EAFf7Sjz/NVEoMhTODN3qGRASTv9bMk/pBzzVA== + dependencies: + "@react-aria/focus" "^3.2.3" + +"@react-native-aria/interactions@0.2.16", "@react-native-aria/interactions@^0.2.16": + version "0.2.16" + resolved "https://registry.yarnpkg.com/@react-native-aria/interactions/-/interactions-0.2.16.tgz#fcb5745a5f87f60089717f578dcf085655bee79a" + integrity sha512-tJ7mhG0P6cElLTcL4yfV3HSfqdD8tpAwHKjtamyeua8i6tsu7BOxGmfGmPQ5ueJl7/mHqf8xyTv1xGW288CKXQ== + dependencies: + "@react-aria/interactions" "^3.3.2" + "@react-aria/utils" "^3.6.0" + "@react-native-aria/utils" "0.2.12" + +"@react-native-aria/menu@0.2.15": + version "0.2.15" + resolved "https://registry.yarnpkg.com/@react-native-aria/menu/-/menu-0.2.15.tgz#fa5193f180c98cfa26ea71625fbea352e786b7f4" + integrity sha512-ezuz3EAPVERL5YPut0wQmcRwIyWNoAMkA9ItVI9mFWhyvUJRt1rNNA0sG580KzTwAx/1vezJmCMBhkDLeTDYjg== + dependencies: + "@react-aria/interactions" "^3.3.2" + "@react-aria/menu" "^3.1.3" + "@react-aria/selection" "^3.3.1" + "@react-aria/utils" "^3.6.0" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/overlays" "^0.3.15" + "@react-native-aria/utils" "0.2.12" + "@react-stately/collections" "^3.3.0" + "@react-stately/menu" "^3.2.1" + "@react-stately/tree" "^3.1.2" + "@react-types/menu" "^3.1.1" + +"@react-native-aria/overlays@0.3.15", "@react-native-aria/overlays@^0.3.15": + version "0.3.15" + resolved "https://registry.yarnpkg.com/@react-native-aria/overlays/-/overlays-0.3.15.tgz#42aab9b0475dea34c488857da257e2dc3e941893" + integrity sha512-ialIMsXmiQe6A2cWv4O62nJs8raAEkC27BYUu0Z6BEWbhYn+3MhrujxFzsozJ6bwDZgsfNOqtfwk1ScXJxXjkQ== + dependencies: + "@react-aria/interactions" "^3.3.2" + "@react-aria/overlays" "^3.7.0" + "@react-native-aria/utils" "0.2.12" + "@react-stately/overlays" "^3.1.1" + "@react-types/overlays" "^3.4.0" + dom-helpers "^5.0.0" + +"@react-native-aria/radio@^0.2.13": + version "0.2.13" + resolved "https://registry.yarnpkg.com/@react-native-aria/radio/-/radio-0.2.13.tgz#a39229bfcb5c4f19917321ae75c40c48a3f83a0b" + integrity sha512-80FQ+k10738MOnFwOyP3RvAGUAdozYY54vUZNNg2z7MH6GaKyok538cDIzVa9p4cCL58CU8Te8vnd+ItOR3nBg== + dependencies: + "@react-aria/radio" "^3.1.2" + "@react-aria/utils" "^3.6.0" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/utils" "0.2.12" + "@react-stately/radio" "^3.2.1" + "@react-types/radio" "^3.1.1" + +"@react-native-aria/slider@^0.2.12": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@react-native-aria/slider/-/slider-0.2.12.tgz#4ab6a547149b64d53cc274efb6199c05174feddd" + integrity sha512-xh528Ddwyyl7MbTNGkTlQnzLId6xZ3mLPyT9bM/oQ2rGCFufL7cznKYk41QGBLaMBJ4n2ig0MAVIijoJU+/HkQ== + dependencies: + "@react-aria/focus" "^3.2.3" + "@react-aria/interactions" "^3.3.2" + "@react-aria/label" "^3.1.1" + "@react-aria/slider" "^3.0.1" + "@react-aria/utils" "^3.6.0" + "@react-native-aria/utils" "0.2.12" + "@react-stately/slider" "^3.0.1" + +"@react-native-aria/toggle@^0.2.11": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@react-native-aria/toggle/-/toggle-0.2.11.tgz#52dc530ac6e3b5af52f5f89bd58bf988d52b4a63" + integrity sha512-oEmcHDp9dXJ8QM8BYILmvry9m1OB9prsIJJnmRjedSVMHRgeuH7CCPcJ1PUIsy56EvtAo6JbKvLTX5HUTQ/RHg== + dependencies: + "@react-aria/focus" "^3.2.3" + "@react-aria/utils" "^3.6.0" + "@react-native-aria/interactions" "0.2.16" + "@react-native-aria/utils" "0.2.12" + "@react-stately/toggle" "^3.2.1" + "@react-types/checkbox" "^3.2.1" + +"@react-native-aria/utils@0.2.12": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@react-native-aria/utils/-/utils-0.2.12.tgz#3ee1c3bf97ff3b08d7e8f49cad2ffba3d5d7227d" + integrity sha512-752/tQ5fjDdc/3Gw8cKqml4NucfiFrO8wPmlg0bBgaCvfQDJaUMi4grme3/fBPCUoK2wk9/yJHfwkv45Gi5Eew== + dependencies: + "@react-aria/ssr" "^3.0.1" + "@react-aria/utils" "^3.3.0" + +"@react-native-async-storage/async-storage@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-2.2.0.tgz#a3aa565253e46286655560172f4e366e8969f5ad" + integrity sha512-gvRvjR5JAaUZF8tv2Kcq/Gbt3JHwbKFYfmb445rhOj6NUMx3qPLixmDx5pZAyb9at1bYvJ4/eTUipU5aki45xw== + dependencies: + merge-options "^3.0.4" + +"@react-native-community/datetimepicker@^8.3.0": + version "8.5.0" + resolved "https://registry.yarnpkg.com/@react-native-community/datetimepicker/-/datetimepicker-8.5.0.tgz#8de2d2ab18584d03e161ceb4250216564a4deda0" + integrity sha512-RMWll1aPppMtzdJz4we4poNzVj9WUw5URHID7D2ICjGZq3KjrwwexvBnzp75EIYE/ihHXCn/OvYKe73fws9Y/g== + dependencies: + invariant "^2.2.4" + +"@react-native-community/netinfo@11.4.1": + version "11.4.1" + resolved "https://registry.yarnpkg.com/@react-native-community/netinfo/-/netinfo-11.4.1.tgz#a3c247aceab35f75dd0aa4bfa85d2be5a4508688" + integrity sha512-B0BYAkghz3Q2V09BF88RA601XursIEA111tnc2JOaN7axJWmNefmfjZqw/KdSxKZp7CZUuPpjBmz/WCR9uaHYg== + +"@react-native-community/slider@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-5.1.1.tgz#321c37da565b264fd8f96a4edcb55d3fe78f26aa" + integrity sha512-W98If/LnTaziU3/0h5+G1LvJaRhMc6iLQBte6UWa4WBIHDMaDPglNBIFKcCXc9Dxp83W+f+5Wv22Olq9M2HJYA== + +"@react-native-firebase/app@^23.5.0": + version "23.5.0" + resolved "https://registry.yarnpkg.com/@react-native-firebase/app/-/app-23.5.0.tgz#b84540b1822e510dfd3c3890e8ca10b2655759fe" + integrity sha512-TOlm6V6fbILwgFP37QZM9Y0nfAW6zqNGVIWlMlepQB6b/BzzFMrCl1FiyknqD5l7i1jgdFQrqX1WH6ZO4ePa/g== + dependencies: + firebase "12.4.0" + +"@react-native-google-signin/google-signin@^16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@react-native-google-signin/google-signin/-/google-signin-16.0.0.tgz#05af652e16f7dab745907db06edc74c007c0e670" + integrity sha512-jVuzPo8odREekFc0b4RK3YsqCvedtLIM2P6NSszFr9cYyhKrUNikffPapL6LmkL9qkb8K6pDeb5CXg4qALOc0g== + +"@react-native-masked-view/masked-view@0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.3.2.tgz#7064533a573e3539ec912f59c1f457371bf49dd9" + integrity sha512-XwuQoW7/GEgWRMovOQtX3A4PrXhyaZm0lVUiY8qJDvdngjLms9Cpdck6SmGAUNqQwcj2EadHC1HwL0bEyoa/SQ== + +"@react-native/assets-registry@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/assets-registry/-/assets-registry-0.81.5.tgz#d22c924fa6f6d4a463c5af34ce91f38756c0fa7d" + integrity sha512-705B6x/5Kxm1RKRvSv0ADYWm5JOnoiQ1ufW7h8uu2E6G9Of/eE6hP/Ivw3U5jI16ERqZxiKQwk34VJbB0niX9w== + +"@react-native/babel-plugin-codegen@0.79.6": + version "0.79.6" + resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.79.6.tgz#2e86024a649072268b03b28da8555f9c81bdb51b" + integrity sha512-CS5OrgcMPixOyUJ/Sk/HSsKsKgyKT5P7y3CojimOQzWqRZBmoQfxdST4ugj7n1H+ebM2IKqbgovApFbqXsoX0g== + dependencies: + "@babel/traverse" "^7.25.3" + "@react-native/codegen" "0.79.6" + +"@react-native/babel-plugin-codegen@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.5.tgz#328d03f42c32b5a8cc2dee1aa84a7c48dddc5f18" + integrity sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ== + dependencies: + "@babel/traverse" "^7.25.3" + "@react-native/codegen" "0.81.5" + +"@react-native/babel-preset@0.79.6": + version "0.79.6" + resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.79.6.tgz#bc0e94a0b3403d237a60902161587ff90205835c" + integrity sha512-H+FRO+r2Ql6b5IwfE0E7D52JhkxjeGSBSUpCXAI5zQ60zSBJ54Hwh2bBJOohXWl4J+C7gKYSAd2JHMUETu+c/A== + dependencies: + "@babel/core" "^7.25.2" + "@babel/plugin-proposal-export-default-from" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-default-from" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.25.4" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.25.0" + "@babel/plugin-transform-class-properties" "^7.25.4" + "@babel/plugin-transform-classes" "^7.25.4" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.8" + "@babel/plugin-transform-flow-strip-types" "^7.25.2" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.25.1" + "@babel/plugin-transform-literals" "^7.25.2" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.8" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.25.2" + "@babel/plugin-transform-react-jsx-self" "^7.24.7" + "@babel/plugin-transform-react-jsx-source" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-runtime" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-typescript" "^7.25.2" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/template" "^7.25.0" + "@react-native/babel-plugin-codegen" "0.79.6" + babel-plugin-syntax-hermes-parser "0.25.1" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.14.0" + +"@react-native/babel-preset@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/babel-preset/-/babel-preset-0.81.5.tgz#e8b7969d21f87ef4e41e603248e8a70c44b4a5bb" + integrity sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA== + dependencies: + "@babel/core" "^7.25.2" + "@babel/plugin-proposal-export-default-from" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-default-from" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.25.4" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.25.0" + "@babel/plugin-transform-class-properties" "^7.25.4" + "@babel/plugin-transform-classes" "^7.25.4" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.8" + "@babel/plugin-transform-flow-strip-types" "^7.25.2" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.25.1" + "@babel/plugin-transform-literals" "^7.25.2" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.8" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.25.2" + "@babel/plugin-transform-react-jsx-self" "^7.24.7" + "@babel/plugin-transform-react-jsx-source" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-runtime" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-typescript" "^7.25.2" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/template" "^7.25.0" + "@react-native/babel-plugin-codegen" "0.81.5" + babel-plugin-syntax-hermes-parser "0.29.1" + babel-plugin-transform-flow-enums "^0.0.2" + react-refresh "^0.14.0" + +"@react-native/codegen@0.79.6": + version "0.79.6" + resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.79.6.tgz#25e9bb68ce02afcdb01b9b2b0bf8a3a7fd99bf8b" + integrity sha512-iRBX8Lgbqypwnfba7s6opeUwVyaR23mowh9ILw7EcT2oLz3RqMmjJdrbVpWhGSMGq2qkPfqAH7bhO8C7O+xfjQ== + dependencies: + "@babel/core" "^7.25.2" + "@babel/parser" "^7.25.3" + glob "^7.1.1" + hermes-parser "0.25.1" + invariant "^2.2.4" + nullthrows "^1.1.1" + yargs "^17.6.2" + +"@react-native/codegen@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/codegen/-/codegen-0.81.5.tgz#d4dec668c94b9d58a5c2dbdbf026db331e1b6b27" + integrity sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g== + dependencies: + "@babel/core" "^7.25.2" + "@babel/parser" "^7.25.3" + glob "^7.1.1" + hermes-parser "0.29.1" + invariant "^2.2.4" + nullthrows "^1.1.1" + yargs "^17.6.2" + +"@react-native/community-cli-plugin@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.5.tgz#617789cda4da419d03dda00e2a78c36188b4391e" + integrity sha512-yWRlmEOtcyvSZ4+OvqPabt+NS36vg0K/WADTQLhrYrm9qdZSuXmq8PmdJWz/68wAqKQ+4KTILiq2kjRQwnyhQw== + dependencies: + "@react-native/dev-middleware" "0.81.5" + debug "^4.4.0" + invariant "^2.2.4" + metro "^0.83.1" + metro-config "^0.83.1" + metro-core "^0.83.1" + semver "^7.1.3" + +"@react-native/debugger-frontend@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/debugger-frontend/-/debugger-frontend-0.81.5.tgz#82ece0181e9a7a3dcbdfa86cf9decd654e13f81f" + integrity sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w== + +"@react-native/dev-middleware@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/dev-middleware/-/dev-middleware-0.81.5.tgz#81e8ac545d7736ef6ebb2e59fdbaebc5cf9aedec" + integrity sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA== + dependencies: + "@isaacs/ttlcache" "^1.4.1" + "@react-native/debugger-frontend" "0.81.5" + chrome-launcher "^0.15.2" + chromium-edge-launcher "^0.2.0" + connect "^3.6.5" + debug "^4.4.0" + invariant "^2.2.4" + nullthrows "^1.1.1" + open "^7.0.3" + serve-static "^1.16.2" + ws "^6.2.3" + +"@react-native/gradle-plugin@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/gradle-plugin/-/gradle-plugin-0.81.5.tgz#a58830f38789f6254b64449a17fe57455b589d00" + integrity sha512-hORRlNBj+ReNMLo9jme3yQ6JQf4GZpVEBLxmTXGGlIL78MAezDZr5/uq9dwElSbcGmLEgeiax6e174Fie6qPLg== + +"@react-native/js-polyfills@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/js-polyfills/-/js-polyfills-0.81.5.tgz#2ca68188c8fff9b951f507b1dec7efe928848274" + integrity sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w== + +"@react-native/normalize-color@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.1.0.tgz#939b87a9849e81687d3640c5efa2a486ac266f91" + integrity sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA== + +"@react-native/normalize-colors@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/normalize-colors/-/normalize-colors-0.81.5.tgz#1ca6cb6772bb7324df2b11aab35227eacd6bdfe7" + integrity sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g== + +"@react-native/virtualized-lists@0.81.5": + version "0.81.5" + resolved "https://registry.yarnpkg.com/@react-native/virtualized-lists/-/virtualized-lists-0.81.5.tgz#24123fded16992d7e46ecc4ccd473be939ea8c1b" + integrity sha512-UVXgV/db25OPIvwZySeToXD/9sKKhOdkcWmmf4Jh8iBZuyfML+/5CasaZ1E7Lqg6g3uqVQq75NqIwkYmORJMPw== + dependencies: + invariant "^2.2.4" + nullthrows "^1.1.1" + +"@react-navigation/core@^6.4.17": + version "6.4.17" + resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.17.tgz#f277a196b578c8a456efcc563d1c9bd87eb4ab04" + integrity sha512-Nd76EpomzChWAosGqWOYE3ItayhDzIEzzZsT7PfGcRFDgW5miHV2t4MZcq9YIK4tzxZjVVpYbIynOOQQd1e0Cg== + dependencies: + "@react-navigation/routers" "^6.1.9" + escape-string-regexp "^4.0.0" + nanoid "^3.1.23" + query-string "^7.1.3" + react-is "^16.13.0" + use-latest-callback "^0.2.1" + +"@react-navigation/elements@^1.3.31": + version "1.3.31" + resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.31.tgz#28dd802a0787bb03fc0e5be296daf1804dbebbcf" + integrity sha512-bUzP4Awlljx5RKEExw8WYtif8EuQni2glDaieYROKTnaxsu9kEIA515sXQgUDZU4Ob12VoL7+z70uO3qrlfXcQ== + +"@react-navigation/native-stack@^6.9.17": + version "6.11.0" + resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.11.0.tgz#a33f92cbd55dfe28fb0ba67df99aaa95240eb87c" + integrity sha512-U5EcUB9Q2NQspCFwYGGNJm0h6wBCOv7T30QjndmvlawLkNt7S7KWbpWyxS9XBHSIKF57RgWjfxuJNTgTstpXxw== + dependencies: + "@react-navigation/elements" "^1.3.31" + warn-once "^0.1.0" + +"@react-navigation/native@^6.1.9": + version "6.1.18" + resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.18.tgz#338fa9afa2c89feec1d3eac41c963840d8d6f106" + integrity sha512-mIT9MiL/vMm4eirLcmw2h6h/Nm5FICtnYSdohq4vTLA2FF/6PNhByM7s8ffqoVfE5L0uAa6Xda1B7oddolUiGg== + dependencies: + "@react-navigation/core" "^6.4.17" + escape-string-regexp "^4.0.0" + fast-deep-equal "^3.1.3" + nanoid "^3.1.23" + +"@react-navigation/routers@^6.1.9": + version "6.1.9" + resolved "https://registry.yarnpkg.com/@react-navigation/routers/-/routers-6.1.9.tgz#73f5481a15a38e36592a0afa13c3c064b9f90bed" + integrity sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA== + dependencies: + nanoid "^3.1.23" + +"@react-stately/calendar@^3.9.0": + version "3.9.0" + resolved "https://registry.yarnpkg.com/@react-stately/calendar/-/calendar-3.9.0.tgz#22da3b99692eabf53f94a58df7768d2135664c91" + integrity sha512-U5Nf2kx9gDhJRxdDUm5gjfyUlt/uUfOvM1vDW2UA62cA6+2k2cavMLc2wNlXOb/twFtl6p0joYKHG7T4xnEFkg== + dependencies: + "@internationalized/date" "^3.10.0" + "@react-stately/utils" "^3.10.8" + "@react-types/calendar" "^3.8.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/checkbox@^3.0.1", "@react-stately/checkbox@^3.4.2", "@react-stately/checkbox@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@react-stately/checkbox/-/checkbox-3.7.2.tgz#0a2293e7b97a366f94b7830d3deb2c0e9876c829" + integrity sha512-j1ycUVz5JmqhaL6mDZgDNZqBilOB8PBW096sDPFaTtuYreDx2HOd1igxiIvwlvPESZwsJP7FVM3mYnaoXtpKPA== + dependencies: + "@react-stately/form" "^3.2.2" + "@react-stately/utils" "^3.10.8" + "@react-types/checkbox" "^3.10.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/collections@^3.12.8", "@react-stately/collections@^3.3.0": + version "3.12.8" + resolved "https://registry.yarnpkg.com/@react-stately/collections/-/collections-3.12.8.tgz#f38692fb9c6384fb91d1c50052a40e595d3efa2c" + integrity sha512-AceJYLLXt1Y2XIcOPi6LEJSs4G/ubeYW3LqOCQbhfIgMaNqKfQMIfagDnPeJX9FVmPFSlgoCBxb1pTJW2vjCAQ== + dependencies: + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/color@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-stately/color/-/color-3.9.2.tgz#87ac8461a01478208c302efa47582e872ff78c65" + integrity sha512-F+6Do8W3yu/4n7MpzZtbXwVukcLTFYYDIUtpoR+Jl52UmAr9Hf1CQgkyTI2azv1ZMzj1mVrTBhpBL0q27kFZig== + dependencies: + "@internationalized/number" "^3.6.5" + "@internationalized/string" "^3.2.7" + "@react-stately/form" "^3.2.2" + "@react-stately/numberfield" "^3.10.2" + "@react-stately/slider" "^3.7.2" + "@react-stately/utils" "^3.10.8" + "@react-types/color" "^3.1.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/combobox@^3.12.0": + version "3.12.0" + resolved "https://registry.yarnpkg.com/@react-stately/combobox/-/combobox-3.12.0.tgz#71e6c9a8ee2f75edc1d233df7b6d7a0b7aeb6fbe" + integrity sha512-A6q9R/7cEa/qoQsBkdslXWvD7ztNLLQ9AhBhVN9QvzrmrH5B4ymUwcTU8lWl22ykH7RRwfonLeLXJL4C+/L2oQ== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/form" "^3.2.2" + "@react-stately/list" "^3.13.1" + "@react-stately/overlays" "^3.6.20" + "@react-stately/utils" "^3.10.8" + "@react-types/combobox" "^3.13.9" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/data@^3.14.1": + version "3.14.1" + resolved "https://registry.yarnpkg.com/@react-stately/data/-/data-3.14.1.tgz#ba5550dee9d0d8ba10a4f6c763c3251631f73582" + integrity sha512-lDNc4gZ6kVZcrABeeQZPTTnP+1ykNylSvFzAC/Hq1fs8+s54xLRvoENWIyG+yK19N9TIGEoA0AOFG8PoAun43g== + dependencies: + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/datepicker@^3.15.2": + version "3.15.2" + resolved "https://registry.yarnpkg.com/@react-stately/datepicker/-/datepicker-3.15.2.tgz#e873aecb5ec037b2da21b267c365c52443437dcb" + integrity sha512-S5GL+W37chvV8knv9v0JRv0L6hKo732qqabCCHXzOpYxkLIkV4f/y3cHdEzFWzpZ0O0Gkg7WgeYo160xOdBKYg== + dependencies: + "@internationalized/date" "^3.10.0" + "@internationalized/string" "^3.2.7" + "@react-stately/form" "^3.2.2" + "@react-stately/overlays" "^3.6.20" + "@react-stately/utils" "^3.10.8" + "@react-types/datepicker" "^3.13.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/disclosure@^3.0.8": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@react-stately/disclosure/-/disclosure-3.0.8.tgz#ff6a3cc61993d25881cb8d6a82fcf829f139e02a" + integrity sha512-/Ce/Z76y85eSBZiemfU/uEyXkBBa1RdfLRaKD13rnfUV7/nS3ae1VtNlsXgmwQjWv2pmAiSuEKYMbZfVL7q/lQ== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/dnd@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@react-stately/dnd/-/dnd-3.7.1.tgz#23b2425553fc1cbc76821c96b30ecca1c9d16013" + integrity sha512-O1JBJ4HI1rVNKuoa5NXiC5FCrCEkr9KVBoKNlTZU8/cnQselhbEsUfMglAakO2EuwIaM1tIXoNF5J/N5P+6lTA== + dependencies: + "@react-stately/selection" "^3.20.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/flags@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-stately/flags/-/flags-3.1.2.tgz#5c8e5ae416d37d37e2e583d2fcb3a046293504f2" + integrity sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-stately/form@^3.2.2": + version "3.2.2" + resolved "https://registry.yarnpkg.com/@react-stately/form/-/form-3.2.2.tgz#c1ae1264a414dd5e3e8ae0f21baf4814588d8c53" + integrity sha512-soAheOd7oaTO6eNs6LXnfn0tTqvOoe3zN9FvtIhhrErKz9XPc5sUmh3QWwR45+zKbitOi1HOjfA/gifKhZcfWw== + dependencies: + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/grid@^3.11.6": + version "3.11.6" + resolved "https://registry.yarnpkg.com/@react-stately/grid/-/grid-3.11.6.tgz#2993450ec5d0602e794f731fd49b3475f57e5547" + integrity sha512-vWPAkzpeTIsrurHfMubzMuqEw7vKzFhIJeEK5sEcLunyr1rlADwTzeWrHNbPMl66NAIAi70Dr1yNq+kahQyvMA== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/selection" "^3.20.6" + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/list@^3.13.1": + version "3.13.1" + resolved "https://registry.yarnpkg.com/@react-stately/list/-/list-3.13.1.tgz#4afd36a87c8fd991a4447d28cc76d51fffddb837" + integrity sha512-eHaoauh21twbcl0kkwULhVJ+CzYcy1jUjMikNVMHOQdhr4WIBdExf7PmSgKHKqsSPhpGg6IpTCY2dUX3RycjDg== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/selection" "^3.20.6" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/menu@^3.2.1", "@react-stately/menu@^3.9.8": + version "3.9.8" + resolved "https://registry.yarnpkg.com/@react-stately/menu/-/menu-3.9.8.tgz#5c2e781dadc3331bc5b3735fe30bf62616f9145f" + integrity sha512-bo0NOhofnTHLESiYfsSSw6gyXiPVJJ0UlN2igUXtJk5PmyhWjFzUzTzcnd7B028OB0si9w3LIWM3stqz5271Eg== + dependencies: + "@react-stately/overlays" "^3.6.20" + "@react-types/menu" "^3.10.5" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/numberfield@^3.10.2": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@react-stately/numberfield/-/numberfield-3.10.2.tgz#aa1fcaec84cd441ea5e847dd3e9eca784045be21" + integrity sha512-jlKVFYaH3RX5KvQ7a+SAMQuPccZCzxLkeYkBE64u1Zvi7YhJ8hkTMHG/fmZMbk1rHlseE2wfBdk0Rlya3MvoNQ== + dependencies: + "@internationalized/number" "^3.6.5" + "@react-stately/form" "^3.2.2" + "@react-stately/utils" "^3.10.8" + "@react-types/numberfield" "^3.8.15" + "@swc/helpers" "^0.5.0" + +"@react-stately/overlays@^3.1.1", "@react-stately/overlays@^3.6.20": + version "3.6.20" + resolved "https://registry.yarnpkg.com/@react-stately/overlays/-/overlays-3.6.20.tgz#e638ad0e073b6cf1d27f018aa41a4ce0fbae5f5b" + integrity sha512-YAIe+uI8GUXX8F/0Pzr53YeC5c/bjqbzDFlV8NKfdlCPa6+Jp4B/IlYVjIooBj9+94QvbQdjylegvYWK/iPwlg== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/overlays" "^3.9.2" + "@swc/helpers" "^0.5.0" + +"@react-stately/radio@^3.11.2", "@react-stately/radio@^3.2.1", "@react-stately/radio@^3.8.1": + version "3.11.2" + resolved "https://registry.yarnpkg.com/@react-stately/radio/-/radio-3.11.2.tgz#a149fb9448dc258441662893f83a70e88e4d4aea" + integrity sha512-UM7L6AW+k8edhSBUEPZAqiWNRNadfOKK7BrCXyBiG79zTz0zPcXRR+N+gzkDn7EMSawDeyK1SHYUuoSltTactg== + dependencies: + "@react-stately/form" "^3.2.2" + "@react-stately/utils" "^3.10.8" + "@react-types/radio" "^3.9.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/searchfield@^3.5.16": + version "3.5.16" + resolved "https://registry.yarnpkg.com/@react-stately/searchfield/-/searchfield-3.5.16.tgz#3b768870d08fa2ef7747513d02d167717961d548" + integrity sha512-MRfqT1lZ24r94GuFNcGJXsfijZoWjSMySCT60T6NXtbOzVPuAF3K+pL70Rayq/EWLJjS2NPHND11VTs0VdcE0Q== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/searchfield" "^3.6.6" + "@swc/helpers" "^0.5.0" + +"@react-stately/select@^3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@react-stately/select/-/select-3.8.0.tgz#ccb1b7d6d0f40b166444f3df27273892854ff23e" + integrity sha512-A721nlt0DSCDit0wKvhcrXFTG5Vv1qkEVkeKvobmETZy6piKvwh0aaN8iQno5AFuZaj1iOZeNjZ/20TsDJR/4A== + dependencies: + "@react-stately/form" "^3.2.2" + "@react-stately/list" "^3.13.1" + "@react-stately/overlays" "^3.6.20" + "@react-stately/utils" "^3.10.8" + "@react-types/select" "^3.11.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/selection@^3.20.6": + version "3.20.6" + resolved "https://registry.yarnpkg.com/@react-stately/selection/-/selection-3.20.6.tgz#17d4d4553403de6ab690172a8d36e0423a5173fb" + integrity sha512-a0bjuP2pJYPKEiedz2Us1W1aSz0iHRuyeQEdBOyL6Z6VUa6hIMq9H60kvseir2T85cOa4QggizuRV7mcO6bU5w== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/slider@^3.0.1", "@react-stately/slider@^3.2.4", "@react-stately/slider@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@react-stately/slider/-/slider-3.7.2.tgz#9dfe6f7e74397f717b1623bc06ba8e375510d056" + integrity sha512-EVBHUdUYwj++XqAEiQg2fGi8Reccznba0uyQ3gPejF0pAc390Q/J5aqiTEDfiCM7uJ6WHxTM6lcCqHQBISk2dQ== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@react-types/slider" "^3.8.2" + "@swc/helpers" "^0.5.0" + +"@react-stately/table@^3.15.1": + version "3.15.1" + resolved "https://registry.yarnpkg.com/@react-stately/table/-/table-3.15.1.tgz#3a2f5ca0788cea200c4c96858604fb4c0139f8b0" + integrity sha512-MhMAgE/LgAzHcAn1P3p/nQErzJ6DiixSJ1AOt2JlnAKEb5YJg4ATKWCb2IjBLwywt9ZCzfm3KMUzkctZqAoxwA== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/flags" "^3.1.2" + "@react-stately/grid" "^3.11.6" + "@react-stately/selection" "^3.20.6" + "@react-stately/utils" "^3.10.8" + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + "@react-types/table" "^3.13.4" + "@swc/helpers" "^0.5.0" + +"@react-stately/tabs@^3.8.6": + version "3.8.6" + resolved "https://registry.yarnpkg.com/@react-stately/tabs/-/tabs-3.8.6.tgz#c71e3ed2462d89ad9c06fb78c69b2069625c68fd" + integrity sha512-9RYxmgjVIxUpIsGKPIF7uRoHWOEz8muwaYiStCVeyiYBPmarvZoIYtTXcwSMN/vEs7heVN5uGCL6/bfdY4+WiA== + dependencies: + "@react-stately/list" "^3.13.1" + "@react-types/shared" "^3.32.1" + "@react-types/tabs" "^3.3.19" + "@swc/helpers" "^0.5.0" + +"@react-stately/toast@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-stately/toast/-/toast-3.1.2.tgz#0502040b6bd57479eaba1bca2f4c66e9e957e55a" + integrity sha512-HiInm7bck32khFBHZThTQaAF6e6/qm57F4mYRWdTq8IVeGDzpkbUYibnLxRhk0UZ5ybc6me+nqqPkG/lVmM42Q== + dependencies: + "@swc/helpers" "^0.5.0" + use-sync-external-store "^1.4.0" + +"@react-stately/toggle@^3.2.1", "@react-stately/toggle@^3.4.4", "@react-stately/toggle@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-stately/toggle/-/toggle-3.9.2.tgz#8a50def68efdcefa268a870deda8bb65e5f054a8" + integrity sha512-dOxs9wrVXHUmA7lc8l+N9NbTJMAaXcYsnNGsMwfXIXQ3rdq+IjWGNYJ52UmNQyRYFcg0jrzRrU16TyGbNjOdNQ== + dependencies: + "@react-stately/utils" "^3.10.8" + "@react-types/checkbox" "^3.10.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/tooltip@^3.5.8": + version "3.5.8" + resolved "https://registry.yarnpkg.com/@react-stately/tooltip/-/tooltip-3.5.8.tgz#c4a329c63294e8ccae3d9ee7853d40c2fb93ce73" + integrity sha512-gkcUx2ROhCiGNAYd2BaTejakXUUNLPnnoJ5+V/mN480pN+OrO8/2V9pqb/IQmpqxLsso93zkM3A4wFHHLBBmPQ== + dependencies: + "@react-stately/overlays" "^3.6.20" + "@react-types/tooltip" "^3.4.21" + "@swc/helpers" "^0.5.0" + +"@react-stately/tree@^3.1.2", "@react-stately/tree@^3.9.3": + version "3.9.3" + resolved "https://registry.yarnpkg.com/@react-stately/tree/-/tree-3.9.3.tgz#398de3406d2a06477bb0af2bdb2a0021265eeade" + integrity sha512-ZngG79nLFxE/GYmpwX6E/Rma2MMkzdoJPRI3iWk3dgqnGMMzpPnUp/cvjDsU3UHF7xDVusC5BT6pjWN0uxCIFQ== + dependencies: + "@react-stately/collections" "^3.12.8" + "@react-stately/selection" "^3.20.6" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-stately/utils@^3.10.8", "@react-stately/utils@^3.6.0": + version "3.10.8" + resolved "https://registry.yarnpkg.com/@react-stately/utils/-/utils-3.10.8.tgz#fdb9d172f7bbc2d083e69190f5ef0edfa4b4392f" + integrity sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-types/button@^3.14.1": + version "3.14.1" + resolved "https://registry.yarnpkg.com/@react-types/button/-/button-3.14.1.tgz#41c25f7c7dd1b31a359a6af9cbec5bed5dbb5aa1" + integrity sha512-D8C4IEwKB7zEtiWYVJ3WE/5HDcWlze9mLWQ5hfsBfpePyWCgO3bT/+wjb/7pJvcAocrkXo90QrMm85LcpBtrpg== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/calendar@^3.8.0": + version "3.8.0" + resolved "https://registry.yarnpkg.com/@react-types/calendar/-/calendar-3.8.0.tgz#51dad3445586f1c22886c35499cfcc872462a30f" + integrity sha512-ZDZgfZgbz1ydWOFs1mH7QFfX3ioJrmb3Y/lkoubQE0HWXLZzyYNvhhKyFJRS1QJ40IofLSBHriwbQb/tsUnGlw== + dependencies: + "@internationalized/date" "^3.10.0" + "@react-types/shared" "^3.32.1" + +"@react-types/checkbox@^3.10.2", "@react-types/checkbox@^3.2.1": + version "3.10.2" + resolved "https://registry.yarnpkg.com/@react-types/checkbox/-/checkbox-3.10.2.tgz#0190c9690e3649348a4d7045b168cbda657ce9de" + integrity sha512-ktPkl6ZfIdGS1tIaGSU/2S5Agf2NvXI9qAgtdMDNva0oLyAZ4RLQb6WecPvofw1J7YKXu0VA5Mu7nlX+FM2weQ== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/color@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-types/color/-/color-3.1.2.tgz#06a0e81b463f3a8d4553e7cd535b2881d721e231" + integrity sha512-NP0TAY3j4tlMztOp/bBfMlPwC9AQKTjSiTFmc2oQNkx5M4sl3QpPqFPosdt7jZ8M4nItvfCWZrlZGjST4SB83A== + dependencies: + "@react-types/shared" "^3.32.1" + "@react-types/slider" "^3.8.2" + +"@react-types/combobox@^3.13.9": + version "3.13.9" + resolved "https://registry.yarnpkg.com/@react-types/combobox/-/combobox-3.13.9.tgz#58bc5c39ca1d7bdbb4beebf79d2ba11b337e927f" + integrity sha512-G6GmLbzVkLW6VScxPAr/RtliEyPhBClfYaIllK1IZv+Z42SVnOpKzhnoe79BpmiFqy1AaC3+LjZX783mrsHCwA== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/datepicker@^3.13.2": + version "3.13.2" + resolved "https://registry.yarnpkg.com/@react-types/datepicker/-/datepicker-3.13.2.tgz#775e43b6edcb8d3d5968e0a35cfacd14be3c847c" + integrity sha512-+M6UZxJnejYY8kz0spbY/hP08QJ5rsZ3aNarRQQHc48xV2oelFLX5MhAqizfLEsvyfb0JYrhWoh4z1xZtAmYCg== + dependencies: + "@internationalized/date" "^3.10.0" + "@react-types/calendar" "^3.8.0" + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@react-types/dialog@*", "@react-types/dialog@^3.5.22": + version "3.5.22" + resolved "https://registry.yarnpkg.com/@react-types/dialog/-/dialog-3.5.22.tgz#ed772c303042c6ee5e8a9bc9e58b5b9d08ed634b" + integrity sha512-smSvzOcqKE196rWk0oqJDnz+ox5JM5+OT0PmmJXiUD4q7P5g32O6W5Bg7hMIFUI9clBtngo8kLaX2iMg+GqAzg== + dependencies: + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@react-types/grid@^3.3.6": + version "3.3.6" + resolved "https://registry.yarnpkg.com/@react-types/grid/-/grid-3.3.6.tgz#9fc60f5baa8a1668bb2257a981dd514dd64706c3" + integrity sha512-vIZJlYTii2n1We9nAugXwM2wpcpsC6JigJFBd6vGhStRdRWRoU4yv1Gc98Usbx0FQ/J7GLVIgeG8+1VMTKBdxw== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/menu@^3.1.1", "@react-types/menu@^3.10.5": + version "3.10.5" + resolved "https://registry.yarnpkg.com/@react-types/menu/-/menu-3.10.5.tgz#0e3a66aab3c636dc3ef965529640bb678b13a431" + integrity sha512-HBTrKll2hm0VKJNM4ubIv1L9MNo8JuOnm2G3M+wXvb6EYIyDNxxJkhjsqsGpUXJdAOSkacHBDcNh2HsZABNX4A== + dependencies: + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@react-types/numberfield@^3.8.15": + version "3.8.15" + resolved "https://registry.yarnpkg.com/@react-types/numberfield/-/numberfield-3.8.15.tgz#0fcd77217bae5d7a2bf35d41c7eb61d8ae52bc03" + integrity sha512-97r92D23GKCOjGIGMeW9nt+/KlfM3GeWH39Czcmd2/D5y3k6z4j0avbsfx2OttCtJszrnENjw3GraYGYI2KosQ== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/overlays@^3.4.0", "@react-types/overlays@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-types/overlays/-/overlays-3.9.2.tgz#721dc248afcb42db988391037a6386bb61556cd4" + integrity sha512-Q0cRPcBGzNGmC8dBuHyoPR7N3057KTS5g+vZfQ53k8WwmilXBtemFJPLsogJbspuewQ/QJ3o2HYsp2pne7/iNw== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/radio@^3.1.1", "@react-types/radio@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@react-types/radio/-/radio-3.9.2.tgz#c6ac396b49cc03334e4bb63a96f366effce3a615" + integrity sha512-3UcJXu37JrTkRyP4GJPDBU7NmDTInrEdOe+bVzA1j4EegzdkJmLBkLg5cLDAbpiEHB+xIsvbJdx6dxeMuc+H3g== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/searchfield@^3.6.6": + version "3.6.6" + resolved "https://registry.yarnpkg.com/@react-types/searchfield/-/searchfield-3.6.6.tgz#fd41bd78246789ac4284462abe222b6f85d191b2" + integrity sha512-cl3itr/fk7wbIQc2Gz5Ie8aVeUmPjVX/mRGS5/EXlmzycAKNYTvqf2mlxwObLndtLISmt7IgNjRRhbUUDI8Ang== + dependencies: + "@react-types/shared" "^3.32.1" + "@react-types/textfield" "^3.12.6" + +"@react-types/select@^3.11.0": + version "3.11.0" + resolved "https://registry.yarnpkg.com/@react-types/select/-/select-3.11.0.tgz#808aec480f0cc20075953af9717ca38d1eb15b8d" + integrity sha512-SzIsMFVPCbXE1Z1TLfpdfiwJ1xnIkcL1/CjGilmUKkNk5uT7rYX1xCJqWCjXI0vAU1xM4Qn+T3n8de4fw6HRBg== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/shared@*", "@react-types/shared@^3.32.1": + version "3.32.1" + resolved "https://registry.yarnpkg.com/@react-types/shared/-/shared-3.32.1.tgz#abfeb839d65d0abe923576f34ac08342c25dfa55" + integrity sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w== + +"@react-types/slider@^3.8.2": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@react-types/slider/-/slider-3.8.2.tgz#37e02c42514aca842954c715082d1ae06a661ee4" + integrity sha512-MQYZP76OEOYe7/yA2To+Dl0LNb0cKKnvh5JtvNvDnAvEprn1RuLiay8Oi/rTtXmc2KmBa4VdTcsXsmkbbkeN2Q== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/table@^3.13.4": + version "3.13.4" + resolved "https://registry.yarnpkg.com/@react-types/table/-/table-3.13.4.tgz#c3d5952d4bd2a04992255850538856829b12c99a" + integrity sha512-I/DYiZQl6aNbMmjk90J9SOhkzVDZvyA3Vn3wMWCiajkMNjvubFhTfda5DDf2SgFP5l0Yh6TGGH5XumRv9LqL5Q== + dependencies: + "@react-types/grid" "^3.3.6" + "@react-types/shared" "^3.32.1" + +"@react-types/tabs@^3.3.19": + version "3.3.19" + resolved "https://registry.yarnpkg.com/@react-types/tabs/-/tabs-3.3.19.tgz#344a22bd15400b738aebc26918cf96dacde1ffef" + integrity sha512-fE+qI43yR5pAMpeqPxGqQq9jDHXEPqXskuxNHERMW0PYMdPyem2Cw6goc5F4qeZO3Hf6uPZgHkvJz2OAq7TbBw== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/textfield@^3.12.6": + version "3.12.6" + resolved "https://registry.yarnpkg.com/@react-types/textfield/-/textfield-3.12.6.tgz#0f90a4108c8d75e7c2c26753e760cd580339be12" + integrity sha512-hpEVKE+M3uUkTjw2WrX1NrH/B3rqDJFUa+ViNK2eVranLY4ZwFqbqaYXSzHupOF3ecSjJJv2C103JrwFvx6TPQ== + dependencies: + "@react-types/shared" "^3.32.1" + +"@react-types/tooltip@^3.4.21": + version "3.4.21" + resolved "https://registry.yarnpkg.com/@react-types/tooltip/-/tooltip-3.4.21.tgz#63596cf87d7166499656bc15f212c75c9ffa8991" + integrity sha512-ugGHOZU6WbOdeTdbjnaEc+Ms7/WhsUCg+T3PCOIeOT9FG02Ce189yJ/+hd7oqL/tVwIhEMYJIqSCgSELFox+QA== + dependencies: + "@react-types/overlays" "^3.9.2" + "@react-types/shared" "^3.32.1" + +"@redux-devtools/core@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@redux-devtools/core/-/core-4.1.1.tgz#4e0d6fe7d250f10d927872448f0085b6c48cd933" + integrity sha512-ZyyJwiHX4DFDU0llk45tYSFPoIMekdoKLz0Q7soowpNOtchvTxruQx4Xy//Cohkwsw+DH8W1amdo4C/NYT6ARA== + dependencies: + "@babel/runtime" "^7.26.9" + "@redux-devtools/instrument" "^2.2.0" + +"@redux-devtools/instrument@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@redux-devtools/instrument/-/instrument-2.2.0.tgz#bc9d015da693aa9fabdb32f4fd07ee4c1328eb95" + integrity sha512-HKaL+ghBQ4ZQkM/kEQIKx8dNwz4E1oeiCDfdQlpPXxEi/BrisyrFFncAXb1y2HIJsLV9zSvQUR2jRtMDWgfi8w== + dependencies: + "@babel/runtime" "^7.23.2" + lodash "^4.17.21" + +"@redux-devtools/remote@^0.9.1": + version "0.9.5" + resolved "https://registry.yarnpkg.com/@redux-devtools/remote/-/remote-0.9.5.tgz#e0553026ea2d2f132246991c68dad57ac4d034e1" + integrity sha512-ETOUWgB5n6yopU4xH6wSwwmcVQT6liGBJbrWHkJkXCbCq9j/VqXHQ7spNN398p59vDseFZWOPo8KXNI0Mvo1RQ== + dependencies: + "@babel/runtime" "^7.26.9" + "@redux-devtools/instrument" "^2.2.0" + "@redux-devtools/utils" "^3.1.1" + jsan "^3.1.14" + rn-host-detect "^1.2.0" + socketcluster-client "^19.2.3" + +"@redux-devtools/serialize@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@redux-devtools/serialize/-/serialize-0.4.2.tgz#564c0cf2e5cb119a1884b1994a51f6d2e138b9a5" + integrity sha512-YVqZCChJld5l3Ni2psEZ5loe9x5xpf9J4ckz+7OJdzCNsplC7vzjnkQbFxE6+ULZbywRVp+nSBslTXmaXqAw4A== + dependencies: + "@babel/runtime" "^7.23.2" + jsan "^3.1.14" + +"@redux-devtools/utils@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@redux-devtools/utils/-/utils-3.1.1.tgz#a0c0aecf2c2e0f02518d48450dda90b9fe6eeb11" + integrity sha512-l+m3/8a7lcxULInBADIqE/3Tt2DkTJm5MAGVA/4czMCXW0VE+gdjkoRFqgZhTBoDJW1fi1z8pdL+4G/+R1rDJw== + dependencies: + "@babel/runtime" "^7.26.9" + "@redux-devtools/core" "^4.1.1" + "@redux-devtools/serialize" "^0.4.2" + "@types/get-params" "^0.1.2" + get-params "^0.1.2" + immutable "^4.3.7" + jsan "^3.1.14" + nanoid "^5.1.2" + redux "^5.0.1" + +"@reduxjs/toolkit@^2.0.1": + version "2.10.1" + resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-2.10.1.tgz#b3b9da21335eea409d3498544bcaf83b481a0195" + integrity sha512-/U17EXQ9Do9Yx4DlNGU6eVNfZvFJfYpUtRRdLf19PbPjdWBxNlxGZXywQZ1p1Nz8nMkWplTI7iD/23m07nolDA== + dependencies: + "@standard-schema/spec" "^1.0.0" + "@standard-schema/utils" "^0.3.0" + immer "^10.2.0" + redux "^5.0.1" + redux-thunk "^3.1.0" + reselect "^5.1.0" + +"@reown/appkit-common@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-common/-/appkit-common-1.7.8.tgz#6fc29db977b7325e8170b1fd08176fe15ea0b39c" + integrity sha512-ridIhc/x6JOp7KbDdwGKY4zwf8/iK8EYBl+HtWrruutSLwZyVi5P8WaZa+8iajL6LcDcDF7LoyLwMTym7SRuwQ== + dependencies: + big.js "6.2.2" + dayjs "1.11.13" + viem ">=2.29.0" + +"@reown/appkit-controllers@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-controllers/-/appkit-controllers-1.7.8.tgz#0e4c24afaacca2251745c8844463589dda6d9e66" + integrity sha512-IdXlJlivrlj6m63VsGLsjtPHHsTWvKGVzWIP1fXZHVqmK+rZCBDjCi9j267Rb9/nYRGHWBtlFQhO8dK35WfeDA== + dependencies: + "@reown/appkit-common" "1.7.8" + "@reown/appkit-wallet" "1.7.8" + "@walletconnect/universal-provider" "2.21.0" + valtio "1.13.2" + viem ">=2.29.0" + +"@reown/appkit-pay@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-pay/-/appkit-pay-1.7.8.tgz#c1ff423635869578f6ad12e6c08180c0532bf8ab" + integrity sha512-OSGQ+QJkXx0FEEjlpQqIhT8zGJKOoHzVnyy/0QFrl3WrQTjCzg0L6+i91Ad5Iy1zb6V5JjqtfIFpRVRWN4M3pw== + dependencies: + "@reown/appkit-common" "1.7.8" + "@reown/appkit-controllers" "1.7.8" + "@reown/appkit-ui" "1.7.8" + "@reown/appkit-utils" "1.7.8" + lit "3.3.0" + valtio "1.13.2" + +"@reown/appkit-polyfills@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-polyfills/-/appkit-polyfills-1.7.8.tgz#a0d362df8479cc66b7c6aa89e696f30783a3d21b" + integrity sha512-W/kq786dcHHAuJ3IV2prRLEgD/2iOey4ueMHf1sIFjhhCGMynMkhsOhQMUH0tzodPqUgAC494z4bpIDYjwWXaA== + dependencies: + buffer "6.0.3" + +"@reown/appkit-scaffold-ui@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-scaffold-ui/-/appkit-scaffold-ui-1.7.8.tgz#36b5eb71b2e4d6525fa9a696af5c4ae83ae17f63" + integrity sha512-RCeHhAwOrIgcvHwYlNWMcIDibdI91waaoEYBGw71inE0kDB8uZbE7tE6DAXJmDkvl0qPh+DqlC4QbJLF1FVYdQ== + dependencies: + "@reown/appkit-common" "1.7.8" + "@reown/appkit-controllers" "1.7.8" + "@reown/appkit-ui" "1.7.8" + "@reown/appkit-utils" "1.7.8" + "@reown/appkit-wallet" "1.7.8" + lit "3.3.0" + +"@reown/appkit-ui@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-ui/-/appkit-ui-1.7.8.tgz#014b30a7378cfc685aa1d5a543d59ac5a9dd8ed2" + integrity sha512-1hjCKjf6FLMFzrulhl0Y9Vb9Fu4royE+SXCPSWh4VhZhWqlzUFc7kutnZKx8XZFVQH4pbBvY62SpRC93gqoHow== + dependencies: + "@reown/appkit-common" "1.7.8" + "@reown/appkit-controllers" "1.7.8" + "@reown/appkit-wallet" "1.7.8" + lit "3.3.0" + qrcode "1.5.3" + +"@reown/appkit-utils@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-utils/-/appkit-utils-1.7.8.tgz#86a35184976a9ba8a935ba44ca68567eea10fba0" + integrity sha512-8X7UvmE8GiaoitCwNoB86pttHgQtzy4ryHZM9kQpvjQ0ULpiER44t1qpVLXNM4X35O0v18W0Dk60DnYRMH2WRw== + dependencies: + "@reown/appkit-common" "1.7.8" + "@reown/appkit-controllers" "1.7.8" + "@reown/appkit-polyfills" "1.7.8" + "@reown/appkit-wallet" "1.7.8" + "@walletconnect/logger" "2.1.2" + "@walletconnect/universal-provider" "2.21.0" + valtio "1.13.2" + viem ">=2.29.0" + +"@reown/appkit-wallet@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit-wallet/-/appkit-wallet-1.7.8.tgz#291b8c225fd3c2585d1f3e65c689a791d5ce3e5d" + integrity sha512-kspz32EwHIOT/eg/ZQbFPxgXq0B/olDOj3YMu7gvLEFz4xyOFd/wgzxxAXkp5LbG4Cp++s/elh79rVNmVFdB9A== + dependencies: + "@reown/appkit-common" "1.7.8" + "@reown/appkit-polyfills" "1.7.8" + "@walletconnect/logger" "2.1.2" + zod "3.22.4" + +"@reown/appkit@1.7.8": + version "1.7.8" + resolved "https://registry.yarnpkg.com/@reown/appkit/-/appkit-1.7.8.tgz#6174bca032a4a2bf4fcfc78969e09210dff85214" + integrity sha512-51kTleozhA618T1UvMghkhKfaPcc9JlKwLJ5uV+riHyvSoWPKPRIa5A6M1Wano5puNyW0s3fwywhyqTHSilkaA== + dependencies: + "@reown/appkit-common" "1.7.8" + "@reown/appkit-controllers" "1.7.8" + "@reown/appkit-pay" "1.7.8" + "@reown/appkit-polyfills" "1.7.8" + "@reown/appkit-scaffold-ui" "1.7.8" + "@reown/appkit-ui" "1.7.8" + "@reown/appkit-utils" "1.7.8" + "@reown/appkit-wallet" "1.7.8" + "@walletconnect/types" "2.21.0" + "@walletconnect/universal-provider" "2.21.0" + bs58 "6.0.0" + valtio "1.13.2" + viem ">=2.29.0" + +"@rolldown/pluginutils@1.0.0-beta.27": + version "1.0.0-beta.27" + resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz#47d2bf4cef6d470b22f5831b420f8964e0bf755f" + integrity sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA== + +"@rollup/rollup-android-arm-eabi@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz#a6742c74c7d9d6d604ef8a48f99326b4ecda3d82" + integrity sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg== + +"@rollup/rollup-android-arm64@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz#97247be098de4df0c11971089fd2edf80a5da8cf" + integrity sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q== + +"@rollup/rollup-darwin-arm64@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz#674852cf14cf11b8056e0b1a2f4e872b523576cf" + integrity sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg== + +"@rollup/rollup-darwin-x64@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz#36dfd7ed0aaf4d9d89d9ef983af72632455b0246" + integrity sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w== + +"@rollup/rollup-freebsd-arm64@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz#2f87c2074b4220260fdb52a9996246edfc633c22" + integrity sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA== + +"@rollup/rollup-freebsd-x64@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz#9b5a26522a38a95dc06616d1939d4d9a76937803" + integrity sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg== + +"@rollup/rollup-linux-arm-gnueabihf@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz#86aa4859385a8734235b5e40a48e52d770758c3a" + integrity sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw== + +"@rollup/rollup-linux-arm-musleabihf@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz#cbe70e56e6ece8dac83eb773b624fc9e5a460976" + integrity sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA== + +"@rollup/rollup-linux-arm64-gnu@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz#d14992a2e653bc3263d284bc6579b7a2890e1c45" + integrity sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA== + +"@rollup/rollup-linux-arm64-musl@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz#2fdd1ddc434ea90aeaa0851d2044789b4d07f6da" + integrity sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA== + +"@rollup/rollup-linux-loong64-gnu@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz#8a181e6f89f969f21666a743cd411416c80099e7" + integrity sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg== + +"@rollup/rollup-linux-loong64-musl@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz#904125af2babc395f8061daa27b5af1f4e3f2f78" + integrity sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q== + +"@rollup/rollup-linux-ppc64-gnu@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz#a57970ac6864c9a3447411a658224bdcf948be22" + integrity sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA== + +"@rollup/rollup-linux-ppc64-musl@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz#bb84de5b26870567a4267666e08891e80bb56a63" + integrity sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA== + +"@rollup/rollup-linux-riscv64-gnu@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz#72d00d2c7fb375ce3564e759db33f17a35bffab9" + integrity sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg== + +"@rollup/rollup-linux-riscv64-musl@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz#4c166ef58e718f9245bd31873384ba15a5c1a883" + integrity sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg== + +"@rollup/rollup-linux-s390x-gnu@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz#bb5025cde9a61db478c2ca7215808ad3bce73a09" + integrity sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w== + +"@rollup/rollup-linux-x64-gnu@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz#9b66b1f9cd95c6624c788f021c756269ffed1552" + integrity sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg== + +"@rollup/rollup-linux-x64-musl@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz#b007ca255dc7166017d57d7d2451963f0bd23fd9" + integrity sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg== + +"@rollup/rollup-openbsd-x64@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz#e8b357b2d1aa2c8d76a98f5f0d889eabe93f4ef9" + integrity sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ== + +"@rollup/rollup-openharmony-arm64@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz#96c2e3f4aacd3d921981329831ff8dde492204dc" + integrity sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA== + +"@rollup/rollup-win32-arm64-msvc@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz#2d865149d706d938df8b4b8f117e69a77646d581" + integrity sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A== + +"@rollup/rollup-win32-ia32-msvc@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz#abe1593be0fa92325e9971c8da429c5e05b92c36" + integrity sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA== + +"@rollup/rollup-win32-x64-gnu@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz#c4af3e9518c9a5cd4b1c163dc81d0ad4d82e7eab" + integrity sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA== + +"@rollup/rollup-win32-x64-msvc@4.59.0": + version "4.59.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz#4584a8a87b29188a4c1fe987a9fcf701e256d86c" + integrity sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA== + +"@rtsao/scc@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" + integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== + +"@rushstack/eslint-patch@^1.10.3": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz#8184bcb37791e6d3c3c13a9bfbe4af263f66665f" + integrity sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw== + +"@safe-global/safe-apps-provider@0.18.6": + version "0.18.6" + resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-provider/-/safe-apps-provider-0.18.6.tgz#b5756176549e35350b7e090824b71507a0d1f749" + integrity sha512-4LhMmjPWlIO8TTDC2AwLk44XKXaK6hfBTWyljDm0HQ6TWlOEijVWNrt2s3OCVMSxlXAcEzYfqyu1daHZooTC2Q== + dependencies: + "@safe-global/safe-apps-sdk" "^9.1.0" + events "^3.3.0" + +"@safe-global/safe-apps-sdk@9.1.0", "@safe-global/safe-apps-sdk@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz#0e65913e0f202e529ed3c846e0f5a98c2d35aa98" + integrity sha512-N5p/ulfnnA2Pi2M3YeWjULeWbjo7ei22JwU/IXnhoHzKq3pYCN6ynL9mJBOlvDVv892EgLPCWCOwQk/uBT2v0Q== + dependencies: + "@safe-global/safe-gateway-typescript-sdk" "^3.5.3" + viem "^2.1.1" + +"@safe-global/safe-gateway-typescript-sdk@^3.5.3": + version "3.23.1" + resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.23.1.tgz#1e86d471bcd2adb0f777246ccbea6fa39618e02c" + integrity sha512-6ORQfwtEJYpalCeVO21L4XXGSdbEMfyp2hEv6cP82afKXSwvse6d3sdelgaPWUxHIsFRkWvHDdzh8IyyKHZKxw== + +"@scure/base@^1.1.3", "@scure/base@~1.2.2", "@scure/base@~1.2.4", "@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + +"@scure/base@~1.1.6": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@scure/bip32@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.6.2.tgz#093caa94961619927659ed0e711a6e4bf35bffd0" + integrity sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw== + dependencies: + "@noble/curves" "~1.8.1" + "@noble/hashes" "~1.7.1" + "@scure/base" "~1.2.2" + +"@scure/bip32@1.7.0", "@scure/bip32@^1.5.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.7.0.tgz#b8683bab172369f988f1589640e53c4606984219" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== + dependencies: + "@noble/curves" "~1.9.0" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + +"@scure/bip39@1.5.4": + version "1.5.4" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.5.4.tgz#07fd920423aa671be4540d59bdd344cc1461db51" + integrity sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA== + dependencies: + "@noble/hashes" "~1.7.1" + "@scure/base" "~1.2.4" + +"@scure/bip39@1.6.0", "@scure/bip39@^1.4.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.6.0.tgz#475970ace440d7be87a6086cbee77cb8f1a684f9" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== + dependencies: + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + +"@sentry-internal/browser-utils@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-10.12.0.tgz#aa3a05653e530d2693e307c0131571ee8a97b60d" + integrity sha512-dozbx389jhKynj0d657FsgbBVOar7pX3mb6GjqCxslXF0VKpZH2Xks0U32RgDY/nK27O+o095IWz7YvjVmPkDw== + dependencies: + "@sentry/core" "10.12.0" + +"@sentry-internal/feedback@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-10.12.0.tgz#a48039507f37fe62e19566128a894661a724ef0d" + integrity sha512-0+7ceO6yQPPqfxRc9ue/xoPHKcnB917ezPaehGQNfAFNQB9PNTG1y55+8mRu0Fw+ANbZeCt/HyoCmXuRdxmkpg== + dependencies: + "@sentry/core" "10.12.0" + +"@sentry-internal/replay-canvas@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-10.12.0.tgz#f79dde92bcba67b4f706db6c217467e14d6348c5" + integrity sha512-W/z1/+69i3INNfPjD1KuinSNaRQaApjzwb37IFmiyF440F93hxmEYgXHk3poOlYYaigl2JMYbysGPWOiXnqUXA== + dependencies: + "@sentry-internal/replay" "10.12.0" + "@sentry/core" "10.12.0" + +"@sentry-internal/replay@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-10.12.0.tgz#47ca89acdc621217991c7ed1d133fd37915a512d" + integrity sha512-/1093gSNGN5KlOBsuyAl33JkzGiG38kCnxswQLZWpPpR6LBbR1Ddb18HjhDpoQNNEZybJBgJC3a5NKl43C2TSQ== + dependencies: + "@sentry-internal/browser-utils" "10.12.0" + "@sentry/core" "10.12.0" + +"@sentry/babel-plugin-component-annotate@4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.3.0.tgz#c5b6cbb986952596d3ad233540a90a1fd18bad80" + integrity sha512-OuxqBprXRyhe8Pkfyz/4yHQJc5c3lm+TmYWSSx8u48g5yKewSQDOxkiLU5pAk3WnbLPy8XwU/PN+2BG0YFU9Nw== + +"@sentry/browser@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-10.12.0.tgz#79dffc88e1f9241b9fdb5def5a7c6809f41230b3" + integrity sha512-lKyaB2NFmr7SxPjmMTLLhQ7xfxaY3kdkMhpzuRI5qwOngtKt4+FtvNYHRuz+PTtEFv4OaHhNNbRn6r91gWguQg== + dependencies: + "@sentry-internal/browser-utils" "10.12.0" + "@sentry-internal/feedback" "10.12.0" + "@sentry-internal/replay" "10.12.0" + "@sentry-internal/replay-canvas" "10.12.0" + "@sentry/core" "10.12.0" + +"@sentry/cli-darwin@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.55.0.tgz#79513547d15223d51905e94d8c1e2bc7377cfdf1" + integrity sha512-jGHE7SHHzqXUmnsmRLgorVH6nmMmTjQQXdPZbSL5tRtH8d3OIYrVNr5D72DSgD26XAPBDMV0ibqOQ9NKoiSpfA== + +"@sentry/cli-linux-arm64@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.55.0.tgz#5a2e8ea6e088f4884cbe272525f0781f8c748ff3" + integrity sha512-jNB/0/gFcOuDCaY/TqeuEpsy/k52dwyk1SOV3s1ku4DUsln6govTppeAGRewY3T1Rj9B2vgIWTrnB8KVh9+Rgg== + +"@sentry/cli-linux-arm@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.55.0.tgz#54c330471c4b23ff6769bfd886f092afba3380ce" + integrity sha512-ATjU0PsiWADSPLF/kZroLZ7FPKd5W9TDWHVkKNwIUNTei702LFgTjNeRwOIzTgSvG3yTmVEqtwFQfFN/7hnVXQ== + +"@sentry/cli-linux-i686@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.55.0.tgz#12c64453ef7014ba89c885497e3c9764a5f3e0a0" + integrity sha512-8LZjo6PncTM6bWdaggscNOi5r7F/fqRREsCwvd51dcjGj7Kp1plqo9feEzYQ+jq+KUzVCiWfHrUjddFmYyZJrg== + +"@sentry/cli-linux-x64@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.55.0.tgz#c640464fe533fe87e57d0ca5585e0c504e0ef5b3" + integrity sha512-5LUVvq74Yj2cZZy5g5o/54dcWEaX4rf3myTHy73AKhRj1PABtOkfexOLbF9xSrZy95WXWaXyeH+k5n5z/vtHfA== + +"@sentry/cli-win32-arm64@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.55.0.tgz#da1e8ba13083c281fcdf72d1dd35255df7fdb5c5" + integrity sha512-cWIQdzm1pfLwPARsV6dUb8TVd6Y3V1A2VWxjTons3Ift6GvtVmiAe0OWL8t2Yt95i8v61kTD/6Tq21OAaogqzA== + +"@sentry/cli-win32-i686@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.55.0.tgz#c2eae0a75fc55f101c31de0999214d7e613d65c4" + integrity sha512-ldepCn2t9r4I0wvgk7NRaA7coJyy4rTQAzM66u9j5nTEsUldf66xym6esd5ZZRAaJUjffqvHqUIr/lrieTIrVg== + +"@sentry/cli-win32-x64@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.55.0.tgz#499e6697663a3e1453ff2e921bf3876f774520b5" + integrity sha512-4hPc/I/9tXx+HLTdTGwlagtAfDSIa2AoTUP30tl32NAYQhx9a6niUbPAemK2qfxesiufJ7D2djX83rCw6WnJVA== + +"@sentry/cli@2.55.0": + version "2.55.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.55.0.tgz#c22d2edbd320242e7881c15ecf89649378c05387" + integrity sha512-cynvcIM2xL8ddwELyFRSpZQw4UtFZzoM2rId2l9vg7+wDREPDocMJB9lEQpBIo3eqhp9JswqUT037yjO6iJ5Sw== + dependencies: + https-proxy-agent "^5.0.0" + node-fetch "^2.6.7" + progress "^2.0.3" + proxy-from-env "^1.1.0" + which "^2.0.2" + optionalDependencies: + "@sentry/cli-darwin" "2.55.0" + "@sentry/cli-linux-arm" "2.55.0" + "@sentry/cli-linux-arm64" "2.55.0" + "@sentry/cli-linux-i686" "2.55.0" + "@sentry/cli-linux-x64" "2.55.0" + "@sentry/cli-win32-arm64" "2.55.0" + "@sentry/cli-win32-i686" "2.55.0" + "@sentry/cli-win32-x64" "2.55.0" + +"@sentry/core@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.12.0.tgz#3f6a0f5c2f63f2c1761e3cf442a986d74adf6403" + integrity sha512-Jrf0Yo7DvmI/ZQcvBnA0xKNAFkJlVC/fMlvcin+5IrFNRcqOToZ2vtF+XqTgjRZymXQNE8s1QTD7IomPHk0TAw== + +"@sentry/react-native@~7.2.0": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-7.2.0.tgz#d29deacc36fd55fc52119ffcf53f61c21cab3600" + integrity sha512-rjqYgEjntPz1sPysud78wi4B9ui7LBVPsG6qr8s/htLMYho9GPGFA5dF+eqsQWqMX8NDReAxNkLTC4+gCNklLQ== + dependencies: + "@sentry/babel-plugin-component-annotate" "4.3.0" + "@sentry/browser" "10.12.0" + "@sentry/cli" "2.55.0" + "@sentry/core" "10.12.0" + "@sentry/react" "10.12.0" + "@sentry/types" "10.12.0" + +"@sentry/react@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-10.12.0.tgz#c121f37bf582f4851108f67ef492de6a4c8f7a8d" + integrity sha512-TpqgdoYbkf5JynmmW2oQhHQ/h5w+XPYk0cEb/UrsGlvJvnBSR+5tgh0AqxCSi3gvtp82rAXI5w1TyRPBbhLDBw== + dependencies: + "@sentry/browser" "10.12.0" + "@sentry/core" "10.12.0" + hoist-non-react-statics "^3.3.2" + +"@sentry/types@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-10.12.0.tgz#86d24346efde7b0757474537af7ae4b3d931d6a8" + integrity sha512-sKGj3l3V8ZKISh2Tu88bHfnm5ztkRtSLdmpZ6TmCeJdSM9pV+RRd6CMJ0RnSEXmYHselPNUod521t2NQFd4W1w== + dependencies: + "@sentry/core" "10.12.0" + +"@sherlo/react-native-storybook@^1.3.5": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@sherlo/react-native-storybook/-/react-native-storybook-1.5.1.tgz#8e917580b505e8c6fbadf20f9e6588b85ca5cbff" + integrity sha512-gUpam5CFBm+jt6oayhXeaUHtzYmI6uIcAoJzGrjFgGO9bb1dRiGw31XfQHRwccn+IYj4aT8RdVVRNRcvUszYdQ== + dependencies: + base-64 "1.0.0" + deepmerge "4.3.1" + its-fine "2.0.0" + sherlo "^1.5.1" + utf8 "3.0.0" + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinclair/typebox@^0.34.0": + version "0.34.41" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.34.41.tgz#aa51a6c1946df2c5a11494a2cdb9318e026db16c" + integrity sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g== + +"@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@sinonjs/fake-timers@^13.0.0": + version "13.0.5" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz#36b9dbc21ad5546486ea9173d6bea063eb1717d5" + integrity sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw== + dependencies: + "@sinonjs/commons" "^3.0.1" + +"@socket.io/component-emitter@~3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" + integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA== + +"@solana-mobile/mobile-wallet-adapter-protocol-web3js@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol-web3js/-/mobile-wallet-adapter-protocol-web3js-2.1.3.tgz#34da335bc69b6fb0abeadee3f0672841d4f9d688" + integrity sha512-IEvPzp4m39sWTS3gybbVfk1WQ5Bx9TrGlthtRlVw1BJPvjbmT6lTcnndgXp7HmMkz5e6cc8fwJWp3EKx5upAug== + dependencies: + "@solana-mobile/mobile-wallet-adapter-protocol" "^2.1.2" + bs58 "^5.0.0" + js-base64 "^3.7.5" + +"@solana-mobile/mobile-wallet-adapter-protocol@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol/-/mobile-wallet-adapter-protocol-2.1.3.tgz#6c87c98f7afec698e14f42726a8b7a161d9e0c78" + integrity sha512-rj1/cSQVjPYdQjHsJDxmlpgRjI9jly/0Md3bEeqCan2sLXPf5F6+TiVlAg9+Hxg+uVWd1peUrepFUdOykbklSw== + dependencies: + "@solana/wallet-standard" "^1.1.2" + "@solana/wallet-standard-util" "^1.1.1" + "@wallet-standard/core" "^1.0.3" + js-base64 "^3.7.5" + +"@solana-mobile/mobile-wallet-adapter-protocol@^2.1.2": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@solana-mobile/mobile-wallet-adapter-protocol/-/mobile-wallet-adapter-protocol-2.2.5.tgz#93ce6a0a0f99b7dd9a18eda28664a3d1336798b5" + integrity sha512-kCI+0/umWm98M9g12ndpS56U6wBzq4XdhobCkDPF8qRDYX/iTU8CD+QMcalh7VgRT7GWEmySQvQdaugM0Chf0g== + dependencies: + "@solana/codecs-strings" "^4.0.0" + "@solana/wallet-standard" "^1.1.2" + "@solana/wallet-standard-util" "^1.1.1" + "@wallet-standard/core" "^1.0.3" + js-base64 "^3.7.5" + +"@solana-program/system@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@solana-program/system/-/system-0.10.0.tgz#f68ffb0a3e1c1d5e68ecfe111fbbe729f95a582a" + integrity sha512-Go+LOEZmqmNlfr+Gjy5ZWAdY5HbYzk2RBewD9QinEU/bBSzpFfzqDRT55JjFRBGJUvMgf3C2vfXEGT4i8DSI4g== + +"@solana-program/token@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@solana-program/token/-/token-0.9.0.tgz#9582068c6053b1600472eedb3fe084b262cbc1c7" + integrity sha512-vnZxndd4ED4Fc56sw93cWZ2djEeeOFxtaPS8SPf5+a+JZjKA/EnKqzbE1y04FuMhIVrLERQ8uR8H2h72eZzlsA== + +"@solana/accounts@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/accounts/-/accounts-5.5.1.tgz#5a86ecf221dc9c4ad317f5816179a0616a0376fb" + integrity sha512-TfOY9xixg5rizABuLVuZ9XI2x2tmWUC/OoN556xwfDlhBHBjKfszicYYOyD6nbFmwTGYarCmyGIdteXxTXIdhQ== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/rpc-spec" "5.5.1" + "@solana/rpc-types" "5.5.1" + +"@solana/addresses@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/addresses/-/addresses-5.5.1.tgz#7137c6af545724f19116f3631baa49b501e0253d" + integrity sha512-5xoah3Q9G30HQghu/9BiHLb5pzlPKRC3zydQDmE3O9H//WfayxTFppsUDCL6FjYUHqj/wzK6CWHySglc2RkpdA== + dependencies: + "@solana/assertions" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/nominal-types" "5.5.1" + +"@solana/assertions@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/assertions/-/assertions-5.5.1.tgz#4ffece2a6a30c951d0d9ff96bfc26f9f75c6e2be" + integrity sha512-YTCSWAlGwSlVPnWtWLm3ukz81wH4j2YaCveK+TjpvUU88hTy6fmUqxi0+hvAMAe4zKXpJyj3Az7BrLJRxbIm4Q== + dependencies: + "@solana/errors" "5.5.1" + +"@solana/buffer-layout@^4 || ^3", "@solana/buffer-layout@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" + integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== + dependencies: + buffer "~6.0.3" + +"@solana/codecs-core@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-2.3.0.tgz#6bf2bb565cb1ae880f8018635c92f751465d8695" + integrity sha512-oG+VZzN6YhBHIoSKgS5ESM9VIGzhWjEHEGNPSibiDTxFhsFWxNaz8LbMDPjBUE69r9wmdGLkrQ+wVPbnJcZPvw== + dependencies: + "@solana/errors" "2.3.0" + +"@solana/codecs-core@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-4.0.0.tgz#0668b964df5a3e278ff276b5aa812bd739e29510" + integrity sha512-28kNUsyIlhU3MO3/7ZLDqeJf2YAm32B4tnTjl5A9HrbBqsTZ+upT/RzxZGP1MMm7jnPuIKCMwmTpsyqyR6IUpw== + dependencies: + "@solana/errors" "4.0.0" + +"@solana/codecs-core@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-core/-/codecs-core-5.5.1.tgz#1b2619c697ad04c99f98cc468135d584b7e2b16d" + integrity sha512-TgBt//bbKBct0t6/MpA8ElaOA3sa8eYVvR7LGslCZ84WiAwwjCY0lW/lOYsFHJQzwREMdUyuEyy5YWBKtdh8Rw== + dependencies: + "@solana/errors" "5.5.1" + +"@solana/codecs-data-structures@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-data-structures/-/codecs-data-structures-5.5.1.tgz#4ebadc8feaa5cc30c95a485c5b34c5175245e4b2" + integrity sha512-97bJWGyUY9WvBz3mX1UV3YPWGDTez6btCfD0ip3UVEXJbItVuUiOkzcO5iFDUtQT5riKT6xC+Mzl+0nO76gd0w== + dependencies: + "@solana/codecs-core" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/errors" "5.5.1" + +"@solana/codecs-numbers@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-4.0.0.tgz#fc5c451ff2f1ca1e3a13cf85230e768a47b9a788" + integrity sha512-z9zpjtcwzqT9rbkKVZpkWB5/0V7+6YRKs6BccHkGJlaDx8Pe/+XOvPi2rEdXPqrPd9QWb5Xp1iBfcgaDMyiOiA== + dependencies: + "@solana/codecs-core" "4.0.0" + "@solana/errors" "4.0.0" + +"@solana/codecs-numbers@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-5.5.1.tgz#6ebc43250133ceb7836f1ac5780a7767e383efde" + integrity sha512-rllMIZAHqmtvC0HO/dc/21wDuWaD0B8Ryv8o+YtsICQBuiL/0U4AGwH7Pi5GNFySYk0/crSuwfIqQFtmxNSPFw== + dependencies: + "@solana/codecs-core" "5.5.1" + "@solana/errors" "5.5.1" + +"@solana/codecs-numbers@^2.1.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@solana/codecs-numbers/-/codecs-numbers-2.3.0.tgz#ac7e7f38aaf7fcd22ce2061fbdcd625e73828dc6" + integrity sha512-jFvvwKJKffvG7Iz9dmN51OGB7JBcy2CJ6Xf3NqD/VP90xak66m/Lg48T01u5IQ/hc15mChVHiBm+HHuOFDUrQg== + dependencies: + "@solana/codecs-core" "2.3.0" + "@solana/errors" "2.3.0" + +"@solana/codecs-strings@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-5.5.1.tgz#3849b188bf4a262f63957b69071e945fb82b445d" + integrity sha512-7klX4AhfHYA+uKKC/nxRGP2MntbYQCR3N6+v7bk1W/rSxYuhNmt+FN8aoThSZtWIKwN6BEyR1167ka8Co1+E7A== + dependencies: + "@solana/codecs-core" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/errors" "5.5.1" + +"@solana/codecs-strings@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@solana/codecs-strings/-/codecs-strings-4.0.0.tgz#b4c77d6ff6eeec868a71e5b0cb42bdb9f0c6b500" + integrity sha512-XvyD+sQ1zyA0amfxbpoFZsucLoe+yASQtDiLUGMDg5TZ82IHE3B7n82jE8d8cTAqi0HgqQiwU13snPhvg1O0Ow== + dependencies: + "@solana/codecs-core" "4.0.0" + "@solana/codecs-numbers" "4.0.0" + "@solana/errors" "4.0.0" + +"@solana/codecs@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/codecs/-/codecs-5.5.1.tgz#9e56d1caec5195ebaaee3e635ee6ab2c3a5a697b" + integrity sha512-Vea29nJub/bXjfzEV7ZZQ/PWr1pYLZo3z0qW0LQL37uKKVzVFRQlwetd7INk3YtTD3xm9WUYr7bCvYUk3uKy2g== + dependencies: + "@solana/codecs-core" "5.5.1" + "@solana/codecs-data-structures" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/options" "5.5.1" + +"@solana/errors@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-2.3.0.tgz#4ac9380343dbeffb9dffbcb77c28d0e457c5fa31" + integrity sha512-66RI9MAbwYV0UtP7kGcTBVLxJgUxoZGm8Fbc0ah+lGiAw17Gugco6+9GrJCV83VyF2mDWyYnYM9qdI3yjgpnaQ== + dependencies: + chalk "^5.4.1" + commander "^14.0.0" + +"@solana/errors@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-4.0.0.tgz#7fa9e8b69c4a199acab1b863b234be69772b1914" + integrity sha512-3YEtvcMvtcnTl4HahqLt0VnaGVf7vVWOnt6/uPky5e0qV6BlxDSbGkbBzttNjxLXHognV0AQi3pjvrtfUnZmbg== + dependencies: + chalk "5.6.2" + commander "14.0.1" + +"@solana/errors@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/errors/-/errors-5.5.1.tgz#1c17bc822264fd5a6305d8bfb9d597858e4ce17b" + integrity sha512-vFO3p+S7HoyyrcAectnXbdsMfwUzY2zYFUc2DEe5BwpiE9J1IAxPBGjOWO6hL1bbYdBrlmjNx8DXCslqS+Kcmg== + dependencies: + chalk "5.6.2" + commander "14.0.2" + +"@solana/fast-stable-stringify@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/fast-stable-stringify/-/fast-stable-stringify-5.5.1.tgz#3c9507eb881f1eac7a22ce52c845175a7857b10d" + integrity sha512-Ni7s2FN33zTzhTFgRjEbOVFO+UAmK8qi3Iu0/GRFYK4jN696OjKHnboSQH/EacQ+yGqS54bfxf409wU5dsLLCw== + +"@solana/functional@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/functional/-/functional-5.5.1.tgz#b23437d15a20ac2faa50bb516911baab5f6c33bf" + integrity sha512-tTHoJcEQq3gQx5qsdsDJ0LEJeFzwNpXD80xApW9o/PPoCNimI3SALkZl+zNW8VnxRrV3l3yYvfHWBKe/X3WG3w== + +"@solana/instruction-plans@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/instruction-plans/-/instruction-plans-5.5.1.tgz#df347bbbc77d9380a9486dfedbae5e858ef47ea6" + integrity sha512-7z3CB7YMcFKuVvgcnNY8bY6IsZ8LG61Iytbz7HpNVGX2u1RthOs1tRW8luTzSG1MPL0Ox7afyAVMYeFqSPHnaQ== + dependencies: + "@solana/errors" "5.5.1" + "@solana/instructions" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/promises" "5.5.1" + "@solana/transaction-messages" "5.5.1" + "@solana/transactions" "5.5.1" + +"@solana/instructions@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/instructions/-/instructions-5.5.1.tgz#864a9f2ebd4911379b56a9e01ecfa6d52bbf5173" + integrity sha512-h0G1CG6S+gUUSt0eo6rOtsaXRBwCq1+Js2a+Ps9Bzk9q7YHNFA75/X0NWugWLgC92waRp66hrjMTiYYnLBoWOQ== + dependencies: + "@solana/codecs-core" "5.5.1" + "@solana/errors" "5.5.1" + +"@solana/keys@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/keys/-/keys-5.5.1.tgz#62405c5b25f72add88bc3af63cca66739526f429" + integrity sha512-KRD61cL7CRL+b4r/eB9dEoVxIf/2EJ1Pm1DmRYhtSUAJD2dJ5Xw8QFuehobOGm9URqQ7gaQl+Fkc1qvDlsWqKg== + dependencies: + "@solana/assertions" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/nominal-types" "5.5.1" + +"@solana/kit@^5.1.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/kit/-/kit-5.5.1.tgz#5baf7def33dcd5673fc86f8af9c7f326faa01959" + integrity sha512-irKUGiV2yRoyf+4eGQ/ZeCRxa43yjFEL1DUI5B0DkcfZw3cr0VJtVJnrG8OtVF01vT0OUfYOcUn6zJW5TROHvQ== + dependencies: + "@solana/accounts" "5.5.1" + "@solana/addresses" "5.5.1" + "@solana/codecs" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/functional" "5.5.1" + "@solana/instruction-plans" "5.5.1" + "@solana/instructions" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/offchain-messages" "5.5.1" + "@solana/plugin-core" "5.5.1" + "@solana/programs" "5.5.1" + "@solana/rpc" "5.5.1" + "@solana/rpc-api" "5.5.1" + "@solana/rpc-parsed-types" "5.5.1" + "@solana/rpc-spec-types" "5.5.1" + "@solana/rpc-subscriptions" "5.5.1" + "@solana/rpc-types" "5.5.1" + "@solana/signers" "5.5.1" + "@solana/sysvars" "5.5.1" + "@solana/transaction-confirmation" "5.5.1" + "@solana/transaction-messages" "5.5.1" + "@solana/transactions" "5.5.1" + +"@solana/nominal-types@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/nominal-types/-/nominal-types-5.5.1.tgz#61a06d88b463889add17656ac33734e074505af5" + integrity sha512-I1ImR+kfrLFxN5z22UDiTWLdRZeKtU0J/pkWkO8qm/8WxveiwdIv4hooi8pb6JnlR4mSrWhq0pCIOxDYrL9GIQ== + +"@solana/offchain-messages@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/offchain-messages/-/offchain-messages-5.5.1.tgz#0faae304d37a4bf5562b69400a67f5b900e5b877" + integrity sha512-g+xHH95prTU+KujtbOzj8wn+C7ZNoiLhf3hj6nYq3MTyxOXtBEysguc97jJveUZG0K97aIKG6xVUlMutg5yxhw== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-data-structures" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/nominal-types" "5.5.1" + +"@solana/options@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/options/-/options-5.5.1.tgz#ee0f1e29bdb7595d3c57bb1932a439ea9055de26" + integrity sha512-eo971c9iLNLmk+yOFyo7yKIJzJ/zou6uKpy6mBuyb/thKtS/haiKIc3VLhyTXty3OH2PW8yOlORJnv4DexJB8A== + dependencies: + "@solana/codecs-core" "5.5.1" + "@solana/codecs-data-structures" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + +"@solana/plugin-core@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/plugin-core/-/plugin-core-5.5.1.tgz#cfd39b3a6231b662b1079f4b7561e5bf25f3f63b" + integrity sha512-VUZl30lDQFJeiSyNfzU1EjYt2QZvoBFKEwjn1lilUJw7KgqD5z7mbV7diJhT+dLFs36i0OsjXvq5kSygn8YJ3A== + +"@solana/programs@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/programs/-/programs-5.5.1.tgz#211ea9cb1811f441146539a1ad1f88622400fdbd" + integrity sha512-7U9kn0Jsx1NuBLn5HRTFYh78MV4XN145Yc3WP/q5BlqAVNlMoU9coG5IUTJIG847TUqC1lRto3Dnpwm6T4YRpA== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/errors" "5.5.1" + +"@solana/promises@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/promises/-/promises-5.5.1.tgz#4dbdea765fe20fe81e92c47d72010e2ff4f35893" + integrity sha512-T9lfuUYkGykJmppEcssNiCf6yiYQxJkhiLPP+pyAc2z84/7r3UVIb2tNJk4A9sucS66pzJnVHZKcZVGUUp6wzA== + +"@solana/rpc-api@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-api/-/rpc-api-5.5.1.tgz#1214e1ddc24793c101dc9a6dc2098c554a0fd327" + integrity sha512-XWOQQPhKl06Vj0xi3RYHAc6oEQd8B82okYJ04K7N0Vvy3J4PN2cxeK7klwkjgavdcN9EVkYCChm2ADAtnztKnA== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/rpc-parsed-types" "5.5.1" + "@solana/rpc-spec" "5.5.1" + "@solana/rpc-transformers" "5.5.1" + "@solana/rpc-types" "5.5.1" + "@solana/transaction-messages" "5.5.1" + "@solana/transactions" "5.5.1" + +"@solana/rpc-parsed-types@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-parsed-types/-/rpc-parsed-types-5.5.1.tgz#329ff94a5e3661c59167b58de4a55b390a9e24f8" + integrity sha512-HEi3G2nZqGEsa3vX6U0FrXLaqnUCg4SKIUrOe8CezD+cSFbRTOn3rCLrUmJrhVyXlHoQVaRO9mmeovk31jWxJg== + +"@solana/rpc-spec-types@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-spec-types/-/rpc-spec-types-5.5.1.tgz#6e9a9d8e6856273ee76bf23fe635a0aaac202e54" + integrity sha512-6OFKtRpIEJQs8Jb2C4OO8KyP2h2Hy1MFhatMAoXA+0Ik8S3H+CicIuMZvGZ91mIu/tXicuOOsNNLu3HAkrakrw== + +"@solana/rpc-spec@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-spec/-/rpc-spec-5.5.1.tgz#3fe48f458c10df76da0f05436cba1117e955af79" + integrity sha512-m3LX2bChm3E3by4mQrH4YwCAFY57QBzuUSWqlUw7ChuZ+oLLOq7b2czi4i6L4Vna67j3eCmB3e+4tqy1j5wy7Q== + dependencies: + "@solana/errors" "5.5.1" + "@solana/rpc-spec-types" "5.5.1" + +"@solana/rpc-subscriptions-api@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-subscriptions-api/-/rpc-subscriptions-api-5.5.1.tgz#138d73745c7736ec3c78bd4ca9b3d621d16c4cce" + integrity sha512-5Oi7k+GdeS8xR2ly1iuSFkAv6CZqwG0Z6b1QZKbEgxadE1XGSDrhM2cn59l+bqCozUWCqh4c/A2znU/qQjROlw== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/rpc-subscriptions-spec" "5.5.1" + "@solana/rpc-transformers" "5.5.1" + "@solana/rpc-types" "5.5.1" + "@solana/transaction-messages" "5.5.1" + "@solana/transactions" "5.5.1" + +"@solana/rpc-subscriptions-channel-websocket@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-subscriptions-channel-websocket/-/rpc-subscriptions-channel-websocket-5.5.1.tgz#ebfa937d12c3629762a256e699342b3ce2d9c940" + integrity sha512-7tGfBBrYY8TrngOyxSHoCU5shy86iA9SRMRrPSyBhEaZRAk6dnbdpmUTez7gtdVo0BCvh9nzQtUycKWSS7PnFQ== + dependencies: + "@solana/errors" "5.5.1" + "@solana/functional" "5.5.1" + "@solana/rpc-subscriptions-spec" "5.5.1" + "@solana/subscribable" "5.5.1" + ws "^8.19.0" + +"@solana/rpc-subscriptions-spec@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-5.5.1.tgz#dd7859dedcb5ca531e7c20901172c5ec1c2fa5b9" + integrity sha512-iq+rGq5fMKP3/mKHPNB6MC8IbVW41KGZg83Us/+LE3AWOTWV1WT20KT2iH1F1ik9roi42COv/TpoZZvhKj45XQ== + dependencies: + "@solana/errors" "5.5.1" + "@solana/promises" "5.5.1" + "@solana/rpc-spec-types" "5.5.1" + "@solana/subscribable" "5.5.1" + +"@solana/rpc-subscriptions@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-subscriptions/-/rpc-subscriptions-5.5.1.tgz#a35e84b934a3a18efa1f815844f639223c4e7d88" + integrity sha512-CTMy5bt/6mDh4tc6vUJms9EcuZj3xvK0/xq8IQ90rhkpYvate91RjBP+egvjgSayUg9yucU9vNuUpEjz4spM7w== + dependencies: + "@solana/errors" "5.5.1" + "@solana/fast-stable-stringify" "5.5.1" + "@solana/functional" "5.5.1" + "@solana/promises" "5.5.1" + "@solana/rpc-spec-types" "5.5.1" + "@solana/rpc-subscriptions-api" "5.5.1" + "@solana/rpc-subscriptions-channel-websocket" "5.5.1" + "@solana/rpc-subscriptions-spec" "5.5.1" + "@solana/rpc-transformers" "5.5.1" + "@solana/rpc-types" "5.5.1" + "@solana/subscribable" "5.5.1" + +"@solana/rpc-transformers@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-transformers/-/rpc-transformers-5.5.1.tgz#632295520087b5935770af1da8329e97e3181bc3" + integrity sha512-OsWqLCQdcrRJKvHiMmwFhp9noNZ4FARuMkHT5us3ustDLXaxOjF0gfqZLnMkulSLcKt7TGXqMhBV+HCo7z5M8Q== + dependencies: + "@solana/errors" "5.5.1" + "@solana/functional" "5.5.1" + "@solana/nominal-types" "5.5.1" + "@solana/rpc-spec-types" "5.5.1" + "@solana/rpc-types" "5.5.1" + +"@solana/rpc-transport-http@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-transport-http/-/rpc-transport-http-5.5.1.tgz#27f3fbdef6dd99e2507ae2b996107960454c62a3" + integrity sha512-yv8GoVSHqEV0kUJEIhkdOVkR2SvJ6yoWC51cJn2rSV7plr6huLGe0JgujCmB7uZhhaLbcbP3zxXxu9sOjsi7Fg== + dependencies: + "@solana/errors" "5.5.1" + "@solana/rpc-spec" "5.5.1" + "@solana/rpc-spec-types" "5.5.1" + undici-types "^7.19.2" + +"@solana/rpc-types@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc-types/-/rpc-types-5.5.1.tgz#ec16170f2470ece5de7154e920842125b7059cb5" + integrity sha512-bibTFQ7PbHJJjGJPmfYC2I+/5CRFS4O2p9WwbFraX1Keeel+nRrt/NBXIy8veP5AEn2sVJIyJPpWBRpCx1oATA== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/nominal-types" "5.5.1" + +"@solana/rpc@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/rpc/-/rpc-5.5.1.tgz#933a20f5bfcf005e0b4082746d2f48203a3832ee" + integrity sha512-ku8zTUMrkCWci66PRIBC+1mXepEnZH/q1f3ck0kJZ95a06bOTl5KU7HeXWtskkyefzARJ5zvCs54AD5nxjQJ+A== + dependencies: + "@solana/errors" "5.5.1" + "@solana/fast-stable-stringify" "5.5.1" + "@solana/functional" "5.5.1" + "@solana/rpc-api" "5.5.1" + "@solana/rpc-spec" "5.5.1" + "@solana/rpc-spec-types" "5.5.1" + "@solana/rpc-transformers" "5.5.1" + "@solana/rpc-transport-http" "5.5.1" + "@solana/rpc-types" "5.5.1" + +"@solana/signers@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/signers/-/signers-5.5.1.tgz#21cdc65ed007e8173043af9db44d8adc2fb9c054" + integrity sha512-FY0IVaBT2kCAze55vEieR6hag4coqcuJ31Aw3hqRH7mv6sV8oqwuJmUrx+uFwOp1gwd5OEAzlv6N4hOOple4sQ== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/instructions" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/nominal-types" "5.5.1" + "@solana/offchain-messages" "5.5.1" + "@solana/transaction-messages" "5.5.1" + "@solana/transactions" "5.5.1" + +"@solana/subscribable@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/subscribable/-/subscribable-5.5.1.tgz#4321a5b8d1e9de7f94745708213f4b437e6ec70b" + integrity sha512-9K0PsynFq0CsmK1CDi5Y2vUIJpCqkgSS5yfDN0eKPgHqEptLEaia09Kaxc90cSZDZU5mKY/zv1NBmB6Aro9zQQ== + dependencies: + "@solana/errors" "5.5.1" + +"@solana/sysvars@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/sysvars/-/sysvars-5.5.1.tgz#804cbb993343d31e86a23b071a76710e3c236aca" + integrity sha512-k3Quq87Mm+geGUu1GWv6knPk0ALsfY6EKSJGw9xUJDHzY/RkYSBnh0RiOrUhtFm2TDNjOailg8/m0VHmi3reFA== + dependencies: + "@solana/accounts" "5.5.1" + "@solana/codecs" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/rpc-types" "5.5.1" + +"@solana/transaction-confirmation@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/transaction-confirmation/-/transaction-confirmation-5.5.1.tgz#7fd150846dac1cf177223331f0089f94516752ca" + integrity sha512-j4mKlYPHEyu+OD7MBt3jRoX4ScFgkhZC6H65on4Fux6LMScgivPJlwnKoZMnsgxFgWds0pl+BYzSiALDsXlYtw== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/promises" "5.5.1" + "@solana/rpc" "5.5.1" + "@solana/rpc-subscriptions" "5.5.1" + "@solana/rpc-types" "5.5.1" + "@solana/transaction-messages" "5.5.1" + "@solana/transactions" "5.5.1" + +"@solana/transaction-messages@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/transaction-messages/-/transaction-messages-5.5.1.tgz#1fc965274ddae9fe39bf44cb6005469faf99fc02" + integrity sha512-aXyhMCEaAp3M/4fP0akwBBQkFPr4pfwoC5CLDq999r/FUwDax2RE/h4Ic7h2Xk+JdcUwsb+rLq85Y52hq84XvQ== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-data-structures" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/functional" "5.5.1" + "@solana/instructions" "5.5.1" + "@solana/nominal-types" "5.5.1" + "@solana/rpc-types" "5.5.1" + +"@solana/transactions@5.5.1": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@solana/transactions/-/transactions-5.5.1.tgz#78aee76dccc6486bd6f8be89bb4369b99d9bdba0" + integrity sha512-8hHtDxtqalZ157pnx6p8k10D7J/KY/biLzfgh9R09VNLLY3Fqi7kJvJCr7M2ik3oRll56pxhraAGCC9yIT6eOA== + dependencies: + "@solana/addresses" "5.5.1" + "@solana/codecs-core" "5.5.1" + "@solana/codecs-data-structures" "5.5.1" + "@solana/codecs-numbers" "5.5.1" + "@solana/codecs-strings" "5.5.1" + "@solana/errors" "5.5.1" + "@solana/functional" "5.5.1" + "@solana/instructions" "5.5.1" + "@solana/keys" "5.5.1" + "@solana/nominal-types" "5.5.1" + "@solana/rpc-types" "5.5.1" + "@solana/transaction-messages" "5.5.1" + +"@solana/wallet-adapter-base@0.9.23", "@solana/wallet-adapter-base@^0.9.23": + version "0.9.23" + resolved "https://registry.yarnpkg.com/@solana/wallet-adapter-base/-/wallet-adapter-base-0.9.23.tgz#3b17c28afd44e173f44f658bf9700fd637e12a11" + integrity sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw== + dependencies: + "@solana/wallet-standard-features" "^1.1.0" + "@wallet-standard/base" "^1.0.1" + "@wallet-standard/features" "^1.0.3" + eventemitter3 "^4.0.7" + +"@solana/wallet-standard-chains@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-chains/-/wallet-standard-chains-1.1.1.tgz#bbab9f3836006e9e4722afc408ca323df9623657" + integrity sha512-Us3TgL4eMVoVWhuC4UrePlYnpWN+lwteCBlhZDUhFZBJ5UMGh94mYPXno3Ho7+iHPYRtuCi/ePvPcYBqCGuBOw== + dependencies: + "@wallet-standard/base" "^1.1.0" + +"@solana/wallet-standard-core@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-core/-/wallet-standard-core-1.1.2.tgz#86512ae188450d70ff5d1ee0f58b5c29b83226c6" + integrity sha512-FaSmnVsIHkHhYlH8XX0Y4TYS+ebM+scW7ZeDkdXo3GiKge61Z34MfBPinZSUMV08hCtzxxqH2ydeU9+q/KDrLA== + dependencies: + "@solana/wallet-standard-chains" "^1.1.1" + "@solana/wallet-standard-features" "^1.3.0" + "@solana/wallet-standard-util" "^1.1.2" + +"@solana/wallet-standard-features@^1.1.0", "@solana/wallet-standard-features@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-features/-/wallet-standard-features-1.3.0.tgz#c489eca9d0c78f97084b4af6ca8ad8c1ca197de5" + integrity sha512-ZhpZtD+4VArf6RPitsVExvgkF+nGghd1rzPjd97GmBximpnt1rsUxMOEyoIEuH3XBxPyNB6Us7ha7RHWQR+abg== + dependencies: + "@wallet-standard/base" "^1.1.0" + "@wallet-standard/features" "^1.1.0" + +"@solana/wallet-standard-util@^1.1.1", "@solana/wallet-standard-util@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-util/-/wallet-standard-util-1.1.2.tgz#1e281178c04b52923ea530799c589ed64e5526bc" + integrity sha512-rUXFNP4OY81Ddq7qOjQV4Kmkozx4wjYAxljvyrqPx8Ycz0FYChG/hQVWqvgpK3sPsEaO/7ABG1NOACsyAKWNOA== + dependencies: + "@noble/curves" "^1.8.0" + "@solana/wallet-standard-chains" "^1.1.1" + "@solana/wallet-standard-features" "^1.3.0" + +"@solana/wallet-standard-wallet-adapter-base@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-base/-/wallet-standard-wallet-adapter-base-1.1.4.tgz#fc05b153674e29839eee49b30d05106bd42dd789" + integrity sha512-Q2Rie9YaidyFA4UxcUIxUsvynW+/gE2noj/Wmk+IOwDwlVrJUAXCvFaCNsPDSyKoiYEKxkSnlG13OA1v08G4iw== + dependencies: + "@solana/wallet-adapter-base" "^0.9.23" + "@solana/wallet-standard-chains" "^1.1.1" + "@solana/wallet-standard-features" "^1.3.0" + "@solana/wallet-standard-util" "^1.1.2" + "@wallet-standard/app" "^1.1.0" + "@wallet-standard/base" "^1.1.0" + "@wallet-standard/features" "^1.1.0" + "@wallet-standard/wallet" "^1.1.0" + +"@solana/wallet-standard-wallet-adapter-react@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter-react/-/wallet-standard-wallet-adapter-react-1.1.4.tgz#5f48a68bea19fe570e1741d0e26f98c6d8ad0628" + integrity sha512-xa4KVmPgB7bTiWo4U7lg0N6dVUtt2I2WhEnKlIv0jdihNvtyhOjCKMjucWet6KAVhir6I/mSWrJk1U9SvVvhCg== + dependencies: + "@solana/wallet-standard-wallet-adapter-base" "^1.1.4" + "@wallet-standard/app" "^1.1.0" + "@wallet-standard/base" "^1.1.0" + +"@solana/wallet-standard-wallet-adapter@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard-wallet-adapter/-/wallet-standard-wallet-adapter-1.1.4.tgz#fd4f9d1b61e85daa6d940618854528945cacdfa7" + integrity sha512-YSBrxwov4irg2hx9gcmM4VTew3ofNnkqsXQ42JwcS6ykF1P1ecVY8JCbrv75Nwe6UodnqeoZRbN7n/p3awtjNQ== + dependencies: + "@solana/wallet-standard-wallet-adapter-base" "^1.1.4" + "@solana/wallet-standard-wallet-adapter-react" "^1.1.4" + +"@solana/wallet-standard@^1.1.2": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@solana/wallet-standard/-/wallet-standard-1.1.4.tgz#afe6d8a6d6ea04acd9bb4a92bef6bb93e08c81f3" + integrity sha512-NF+MI5tOxyvfTU4A+O5idh/gJFmjm52bMwsPpFGRSL79GECSN0XLmpVOO/jqTKJgac2uIeYDpQw/eMaQuWuUXw== + dependencies: + "@solana/wallet-standard-core" "^1.1.2" + "@solana/wallet-standard-wallet-adapter" "^1.1.4" + +"@solana/web3.js@^1.87.6", "@solana/web3.js@^1.95.1", "@solana/web3.js@^1.98.1": + version "1.98.4" + resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.98.4.tgz#df51d78be9d865181ec5138b4e699d48e6895bbe" + integrity sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw== + dependencies: + "@babel/runtime" "^7.25.0" + "@noble/curves" "^1.4.2" + "@noble/hashes" "^1.4.0" + "@solana/buffer-layout" "^4.0.1" + "@solana/codecs-numbers" "^2.1.0" + agentkeepalive "^4.5.0" + bn.js "^5.2.1" + borsh "^0.7.0" + bs58 "^4.0.1" + buffer "6.0.3" + fast-stable-stringify "^1.0.0" + jayson "^4.1.1" + node-fetch "^2.7.0" + rpc-websockets "^9.0.2" + superstruct "^2.0.2" + +"@standard-schema/spec@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" + integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== + +"@standard-schema/utils@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@standard-schema/utils/-/utils-0.3.0.tgz#3d5e608f16c2390c10528e98e59aef6bf73cae7b" + integrity sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g== + +"@storybook/addon-ondevice-actions@^9.0.18": + version "9.1.4" + resolved "https://registry.yarnpkg.com/@storybook/addon-ondevice-actions/-/addon-ondevice-actions-9.1.4.tgz#d5020ffb561085222059785c82924ef7f9d7871f" + integrity sha512-W68LZu/M+7LpFmAuqkrYAW6UyfczvucbH6b0jNORz8jno63qLO1R8hsTLJnnz9FFLWoAR6njuUX4gPgSy1Xtkw== + dependencies: + "@storybook/global" "^5.0.0" + fast-deep-equal "^2.0.1" + +"@storybook/addon-ondevice-controls@^9.0.18": + version "9.1.4" + resolved "https://registry.yarnpkg.com/@storybook/addon-ondevice-controls/-/addon-ondevice-controls-9.1.4.tgz#2e2fc15d496be4ac1601966628138f3eeb34d498" + integrity sha512-oj+Ga41RSYMUOwgrMPaLG5fTI2puGmrTuxHGNN+Up1Lxqs5mr2fzWDO10TEspZtAg/ETVZqtNKhW166wQoCBTA== + dependencies: + "@storybook/react-native-theming" "^9.1.4" + "@storybook/react-native-ui-common" "^9.1.4" + deep-equal "^1.0.1" + prop-types "^15.7.2" + react-native-modal-datetime-picker "^18.0.0" + tinycolor2 "^1.4.1" + +"@storybook/global@^5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@storybook/global/-/global-5.0.0.tgz#b793d34b94f572c1d7d9e0f44fac4e0dbc9572ed" + integrity sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ== + +"@storybook/react-dom-shim@9.1.16": + version "9.1.16" + resolved "https://registry.yarnpkg.com/@storybook/react-dom-shim/-/react-dom-shim-9.1.16.tgz#c98298b1f08e699f1a06483c42fdfc4864cf4493" + integrity sha512-MsI4qTxdT6lMXQmo3IXhw3EaCC+vsZboyEZBx4pOJ+K/5cDJ6ZoQ3f0d4yGpVhumDxaxlnNAg954+f8WWXE1rQ== + +"@storybook/react-native-theming@^9.1.4": + version "9.1.4" + resolved "https://registry.yarnpkg.com/@storybook/react-native-theming/-/react-native-theming-9.1.4.tgz#3621d66e0819b435ef2f0583e7866873be592c3d" + integrity sha512-gUo9ziv5YIYlgU5b9BpkUcMHyV4uJ/gmb8LWZpROx150HBavmX2IVd8IwBiJkPNuWrTFlTMPW9ytU740rp+GPQ== + dependencies: + polished "^4.3.1" + +"@storybook/react-native-ui-common@^9.1.4": + version "9.1.4" + resolved "https://registry.yarnpkg.com/@storybook/react-native-ui-common/-/react-native-ui-common-9.1.4.tgz#d328002bf78149557cc495327260fc9f25b6930b" + integrity sha512-BfLxoGrVoWZkaeZrqf1cXjnXVZup1knguGNBHFKtWRQLAZqmxEGEYM6l1hzODXvhnsD+2eX+KHQ5DU5CnMiPiw== + dependencies: + "@storybook/react" "^9.1.8" + "@storybook/react-native-theming" "^9.1.4" + es-toolkit "^1.38.0" + fuse.js "^7.0.0" + memoizerific "^1.11.3" + polished "^4.3.1" + store2 "^2.14.3" + ts-dedent "^2.2.0" + +"@storybook/react-native-ui@^9.1.4": + version "9.1.4" + resolved "https://registry.yarnpkg.com/@storybook/react-native-ui/-/react-native-ui-9.1.4.tgz#855c430ed6cea10b326c983afa3e6ab62e21edab" + integrity sha512-fBCDfSLkEqgXpAzVdmJMdAxMCkgAhDVVvxvJrtegjOFLE8o9d3PxfFjJkVbZntKmWVU7XlVn0NFuzC0e+5hHIQ== + dependencies: + "@storybook/react" "^9.1.8" + "@storybook/react-native-theming" "^9.1.4" + "@storybook/react-native-ui-common" "^9.1.4" + es-toolkit "^1.38.0" + fuse.js "^7.0.0" + memoizerific "^1.11.3" + polished "^4.3.1" + store2 "^2.14.3" + +"@storybook/react-native@^9.0.18": + version "9.1.4" + resolved "https://registry.yarnpkg.com/@storybook/react-native/-/react-native-9.1.4.tgz#f82c10434631903c73b9aa399be27178feb1792d" + integrity sha512-OjR/1rPQZ2SMBU4+tlgAsF2ooPI1rVadf8DfCH3kC0K4dSfEI+ocqTVzv7p4N3W2ZyTaxgJKJoAxA/Ohw+cSbA== + dependencies: + "@storybook/global" "^5.0.0" + "@storybook/react" "^9.1.8" + "@storybook/react-native-theming" "^9.1.4" + "@storybook/react-native-ui" "^9.1.4" + "@storybook/react-native-ui-common" "^9.1.4" + commander "^8.2.0" + dedent "^1.5.1" + deepmerge "^4.3.0" + react-native-url-polyfill "^2.0.0" + setimmediate "^1.0.5" + type-fest "~2.19" + util "^0.12.4" + ws "^8.18.0" + +"@storybook/react@^9.1.8": + version "9.1.16" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-9.1.16.tgz#38f8b4bdb7060575171183af2737198fe03aa2b6" + integrity sha512-M/SkHJJdtiGpodBJq9+DYmSkEOD+VqlPxKI+FvbHESTNs//1IgqFIjEWetd8quhd9oj/gvo4ICBAPu+UmD6M9w== + dependencies: + "@storybook/global" "^5.0.0" + "@storybook/react-dom-shim" "9.1.16" + +"@stripe/stripe-react-native@0.50.3": + version "0.50.3" + resolved "https://registry.yarnpkg.com/@stripe/stripe-react-native/-/stripe-react-native-0.50.3.tgz#4b80e55807a297127d8bd109c304309bbf179cf1" + integrity sha512-nzOjqZXQKdM7y33Em2JZxCTAgf/q/J51IJQ50XtwIL0QT6Jt5WSmfKm9rGmBhoXxxG4DcXu/qxJeAHlhcPDGQg== + +"@svgr/babel-plugin-add-jsx-attribute@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz#4001f5d5dd87fa13303e36ee106e3ff3a7eb8b22" + integrity sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g== + +"@svgr/babel-plugin-remove-jsx-attribute@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz#69177f7937233caca3a1afb051906698f2f59186" + integrity sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA== + +"@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz#c2c48104cfd7dcd557f373b70a56e9e3bdae1d44" + integrity sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA== + +"@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz#8fbb6b2e91fa26ac5d4aa25c6b6e4f20f9c0ae27" + integrity sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ== + +"@svgr/babel-plugin-svg-dynamic-title@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz#1d5ba1d281363fc0f2f29a60d6d936f9bbc657b0" + integrity sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og== + +"@svgr/babel-plugin-svg-em-dimensions@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz#35e08df300ea8b1d41cb8f62309c241b0369e501" + integrity sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g== + +"@svgr/babel-plugin-transform-react-native-svg@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz#90a8b63998b688b284f255c6a5248abd5b28d754" + integrity sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q== + +"@svgr/babel-plugin-transform-svg-component@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz#013b4bfca88779711f0ed2739f3f7efcefcf4f7e" + integrity sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw== + +"@svgr/babel-preset@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-8.1.0.tgz#0e87119aecdf1c424840b9d4565b7137cabf9ece" + integrity sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "8.0.0" + "@svgr/babel-plugin-remove-jsx-attribute" "8.0.0" + "@svgr/babel-plugin-remove-jsx-empty-expression" "8.0.0" + "@svgr/babel-plugin-replace-jsx-attribute-value" "8.0.0" + "@svgr/babel-plugin-svg-dynamic-title" "8.0.0" + "@svgr/babel-plugin-svg-em-dimensions" "8.0.0" + "@svgr/babel-plugin-transform-react-native-svg" "8.1.0" + "@svgr/babel-plugin-transform-svg-component" "8.0.0" + +"@svgr/core@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-8.1.0.tgz#41146f9b40b1a10beaf5cc4f361a16a3c1885e88" + integrity sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA== + dependencies: + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "8.1.0" + camelcase "^6.2.0" + cosmiconfig "^8.1.3" + snake-case "^3.0.4" + +"@svgr/hast-util-to-babel-ast@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz#6952fd9ce0f470e1aded293b792a2705faf4ffd4" + integrity sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q== + dependencies: + "@babel/types" "^7.21.3" + entities "^4.4.0" + +"@svgr/plugin-jsx@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz#96969f04a24b58b174ee4cd974c60475acbd6928" + integrity sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA== + dependencies: + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "8.1.0" + "@svgr/hast-util-to-babel-ast" "8.0.0" + svg-parser "^2.0.4" + +"@svgr/plugin-svgo@8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz#b115b7b967b564f89ac58feae89b88c3decd0f00" + integrity sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA== + dependencies: + cosmiconfig "^8.1.3" + deepmerge "^4.3.1" + svgo "^3.0.2" + +"@svgr/webpack@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-8.1.0.tgz#16f1b5346f102f89fda6ec7338b96a701d8be0c2" + integrity sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA== + dependencies: + "@babel/core" "^7.21.3" + "@babel/plugin-transform-react-constant-elements" "^7.21.3" + "@babel/preset-env" "^7.20.2" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.21.0" + "@svgr/core" "8.1.0" + "@svgr/plugin-jsx" "8.1.0" + "@svgr/plugin-svgo" "8.1.0" + +"@swc/counter@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== + +"@swc/helpers@0.5.15": + version "0.5.15" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.15.tgz#79efab344c5819ecf83a43f3f9f811fc84b516d7" + integrity sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g== + dependencies: + tslib "^2.8.0" + +"@swc/helpers@0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0" + integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A== + dependencies: + "@swc/counter" "^0.1.3" + tslib "^2.4.0" + +"@swc/helpers@^0.5.0", "@swc/helpers@^0.5.11": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971" + integrity sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A== + dependencies: + tslib "^2.8.0" + +"@tanstack/query-core@5.90.7": + version "5.90.7" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-5.90.7.tgz#ebe0d692e83bd76bde36a371955b0944a204f10c" + integrity sha512-6PN65csiuTNfBMXqQUxQhCNdtm1rV+9kC9YwWAIKcaxAauq3Wu7p18j3gQY3YIBJU70jT/wzCCZ2uqto/vQgiQ== + +"@tanstack/query-devtools@5.90.1": + version "5.90.1" + resolved "https://registry.yarnpkg.com/@tanstack/query-devtools/-/query-devtools-5.90.1.tgz#c57a739a5293f4960a4a6b6fb4b7e4a56e6bd932" + integrity sha512-GtINOPjPUH0OegJExZ70UahT9ykmAhmtNVcmtdnOZbxLwT7R5OmRztR5Ahe3/Cu7LArEmR6/588tAycuaWb1xQ== + +"@tanstack/react-query-devtools@^5.32.1": + version "5.90.2" + resolved "https://registry.yarnpkg.com/@tanstack/react-query-devtools/-/react-query-devtools-5.90.2.tgz#248d6ae89ace7dc2da816fa95cdc2b4f63c9e4d2" + integrity sha512-vAXJzZuBXtCQtrY3F/yUNJCV4obT/A/n81kb3+YqLbro5Z2+phdAbceO+deU3ywPw8B42oyJlp4FhO0SoivDFQ== + dependencies: + "@tanstack/query-devtools" "5.90.1" + +"@tanstack/react-query@^5.32.1": + version "5.90.7" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-5.90.7.tgz#68a32e9fc2bf8fa8c7890177f5ec35653731a1dd" + integrity sha512-wAHc/cgKzW7LZNFloThyHnV/AX9gTg3w5yAv0gvQHPZoCnepwqCMtzbuPbb2UvfvO32XZ46e8bPOYbfZhzVnnQ== + dependencies: + "@tanstack/query-core" "5.90.7" + +"@testing-library/dom@^10.4.0": + version "10.4.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.1.tgz#d444f8a889e9a46e9a3b4f3b88e0fcb3efb6cf95" + integrity sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^5.0.1" + aria-query "5.3.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.5.0" + picocolors "1.1.1" + pretty-format "^27.0.2" + +"@testing-library/jest-dom@^6.6.3": + version "6.9.1" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz#7613a04e146dd2976d24ddf019730d57a89d56c2" + integrity sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA== + dependencies: + "@adobe/css-tools" "^4.4.0" + aria-query "^5.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + picocolors "^1.1.1" + redent "^3.0.0" + +"@testing-library/react-native@^13.1.0": + version "13.3.3" + resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-13.3.3.tgz#4bf02911c4e18075df40b5de0e029c209fb45bda" + integrity sha512-k6Mjsd9dbZgvY4Bl7P1NIpePQNi+dfYtlJ5voi9KQlynxSyQkfOgJmYGCYmw/aSgH/rUcFvG8u5gd4npzgRDyg== + dependencies: + jest-matcher-utils "^30.0.5" + picocolors "^1.1.1" + pretty-format "^30.0.5" + redent "^3.0.0" + +"@testing-library/react@^16.2.0": + version "16.3.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.3.0.tgz#3a85bb9bdebf180cd76dba16454e242564d598a6" + integrity sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw== + dependencies: + "@babel/runtime" "^7.12.5" + +"@testing-library/user-event@^14.6.1": + version "14.6.1" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.6.1.tgz#13e09a32d7a8b7060fe38304788ebf4197cd2149" + integrity sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw== + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + +"@trysound/sax@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" + integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== + +"@tsconfig/node18@^18.2.2": + version "18.2.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-18.2.4.tgz#094efbdd70f697d37c09f34067bf41bc4a828ae3" + integrity sha512-5xxU8vVs9/FNcvm3gE07fPbn9tl6tqGGWA9tSlwsUEkBxtRnTsNmwrV8gasZ9F/EobaSv9+nu8AxUKccw77JpQ== + +"@tybys/wasm-util@^0.10.0": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + +"@types/aria-query@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== + +"@types/babel__core@^7.1.14", "@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74" + integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q== + dependencies: + "@babel/types" "^7.28.2" + +"@types/base-64@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/base-64/-/base-64-1.0.2.tgz#f7bc80d242306f20c57f076d79d1efe2d31032ca" + integrity sha512-uPgKMmM9fmn7I+Zi6YBqctOye4SlJsHKcisjHIMWpb2YKZRc36GpKyNuQ03JcT+oNXg1m7Uv4wU94EVltn8/cw== + +"@types/chai@^5.2.2": + version "5.2.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.3.tgz#8e9cd9e1c3581fa6b341a5aed5588eb285be0b4a" + integrity sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA== + dependencies: + "@types/deep-eql" "*" + assertion-error "^2.0.1" + +"@types/connect@^3.4.33": + version "3.4.38" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" + integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== + dependencies: + "@types/node" "*" + +"@types/debug@^4.1.7": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== + dependencies: + "@types/ms" "*" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + +"@types/doctrine@^0.0.9": + version "0.0.9" + resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.9.tgz#d86a5f452a15e3e3113b99e39616a9baa0f9863f" + integrity sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA== + +"@types/estree@1.0.8", "@types/estree@^1.0.0", "@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/get-params@^0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@types/get-params/-/get-params-0.1.2.tgz#815f80eceb0f0e2f0bb00a2527c9d2e6e57e2a52" + integrity sha512-ujqPyr1UDsOTDngJPV+WFbR0iHT5AfZKlNPMX6XOCnQcMhEqR+r64dVC/nwYCitqjR3DcpWofnOEAInUQmI/eA== + +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/hammerjs@^2.0.36": + version "2.0.46" + resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.46.tgz#381daaca1360ff8a7c8dff63f32e69745b9fb1e1" + integrity sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw== + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1", "@types/istanbul-lib-coverage@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0", "@types/istanbul-reports@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.2.1", "@types/jest@^29.5.11", "@types/jest@^29.5.14": + version "29.5.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.14.tgz#2b910912fa1d6856cadcd0c1f95af7df1d6049e5" + integrity sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + +"@types/jest@^30.0.0": + version "30.0.0" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-30.0.0.tgz#5e85ae568006712e4ad66f25433e9bdac8801f1d" + integrity sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA== + dependencies: + expect "^30.0.0" + pretty-format "^30.0.0" + +"@types/jsdom@^20.0.0": + version "20.0.1" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" + integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" + +"@types/json-schema@^7.0.15", "@types/json-schema@^7.0.5": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/lodash.mergewith@4.6.9": + version "4.6.9" + resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.9.tgz#7093028a36de3cae4495d03b9d92c351cab1f8bf" + integrity sha512-fgkoCAOF47K7sxrQ7Mlud2TH023itugZs2bUg8h/KzT+BnZNrR2jAOmaokbLunHNnobXVWOezAeNn/lZqwxkcw== + dependencies: + "@types/lodash" "*" + +"@types/lodash@*", "@types/lodash@^4.14.202": + version "4.17.20" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.20.tgz#1ca77361d7363432d29f5e55950d9ec1e1c6ea93" + integrity sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA== + +"@types/lodash@^4.17.20": + version "4.17.24" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.24.tgz#4ae334fc62c0e915ca8ed8e35dcc6d4eeb29215f" + integrity sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ== + +"@types/ms@*": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== + +"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": + version "24.10.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.1.tgz#91e92182c93db8bd6224fca031e2370cef9a8f01" + integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ== + dependencies: + undici-types "~7.16.0" + +"@types/node@22.7.5": + version "22.7.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.7.5.tgz#cfde981727a7ab3611a481510b473ae54442b92b" + integrity sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ== + dependencies: + undici-types "~6.19.2" + +"@types/node@^12.12.54": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/node@^20", "@types/node@^20.11.5": + version "20.19.25" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.25.tgz#467da94a2fd966b57cc39c357247d68047611190" + integrity sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ== + dependencies: + undici-types "~6.21.0" + +"@types/node@^22": + version "22.19.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.1.tgz#1188f1ddc9f46b4cc3aec76749050b4e1f459b7b" + integrity sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ== + dependencies: + undici-types "~6.21.0" + +"@types/parse-json@^4.0.0": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239" + integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw== + +"@types/react-dom@18.3.1", "@types/react-dom@19.1.0", "@types/react-dom@^19.1.0": + version "19.1.0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.0.tgz#29f4b0400edbef5166359cec39dca9ffd4f7ad51" + integrity sha512-21E2zejNNRtjG4hKIyJz4aWswGEcNFTgttA0bZIRGjj1HA/tbSUxIJnIcYbn98pwJck0cS1bsQhn6eaKqbcFWw== + +"@types/react-reconciler@^0.28.9": + version "0.28.9" + resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.28.9.tgz#d24b4864c384e770c83275b3fe73fba00269c83b" + integrity sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg== + +"@types/react-resizable@^3.0.7": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@types/react-resizable/-/react-resizable-3.0.8.tgz#b27001b4d262c82cc076272df4b8ef91d9487918" + integrity sha512-Pcvt2eGA7KNXldt1hkhVhAgZ8hK41m0mp89mFgQi7LAAEZiaLgm4fHJ5zbJZ/4m2LVaAyYrrRRv1LHDcrGQanA== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@18.3.1", "@types/react@19.1.0", "@types/react@^18.0.25", "@types/react@^19.1.0", "@types/react@~19.1.0": + version "19.1.0" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.0.tgz#73c43ad9bc43496ca8184332b111e2aef63fc9da" + integrity sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w== + dependencies: + csstype "^3.0.2" + +"@types/redux-logger@^3.0.13": + version "3.0.13" + resolved "https://registry.yarnpkg.com/@types/redux-logger/-/redux-logger-3.0.13.tgz#473e98428cdcc6dc93c908de66732bf932e36bc8" + integrity sha512-jylqZXQfMxahkuPcO8J12AKSSCQngdEWQrw7UiLUJzMBcv1r4Qg77P6mjGLjM27e5gFQDPD8vwUMJ9AyVxFSsg== + dependencies: + redux "^5.0.0" + +"@types/secp256k1@^4.0.6": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.7.tgz#534c9814eb80964962108ad45d549d1555c75fa0" + integrity sha512-Rcvjl6vARGAKRO6jHeKMatGrvOMGrR/AR11N1x2LqintPCyDZ7NBhrh238Z2VZc7aM7KIwnFpFQ7fnfK4H/9Qw== + dependencies: + "@types/node" "*" + +"@types/semver@^7.5.8": + version "7.7.1" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.1.tgz#3ce3af1a5524ef327d2da9e4fd8b6d95c8d70528" + integrity sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA== + +"@types/stack-utils@^2.0.0", "@types/stack-utils@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + +"@types/strip-bom@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" + integrity sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ== + +"@types/strip-json-comments@0.0.30": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" + integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== + +"@types/text-encoding@^0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/text-encoding/-/text-encoding-0.0.39.tgz#6f6436ceb843d96a2306a87dc7e2286e62c2177c" + integrity sha512-gRPvgL1aMgP6Pv92Rs310cJvVQ86DSF62E7K30g1FoGmmYWXoNuXT8PV835iAVeiAZkRwr2IW37KuyDn9ljmeA== + +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + +"@types/trusted-types@^2.0.2": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" + integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== + +"@types/use-sync-external-store@^0.0.6": + version "0.0.6" + resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc" + integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg== + +"@types/uuid@^8.3.4": + version "8.3.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== + +"@types/ws@^7.4.4": + version "7.4.7" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" + integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== + dependencies: + "@types/node" "*" + +"@types/ws@^8.2.2": + version "8.18.1" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" + integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.33", "@types/yargs@^17.0.8": + version "17.0.34" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.34.tgz#1c2f9635b71d5401827373a01ce2e8a7670ea839" + integrity sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz#c772d1dbdd97cfddf85f5a161a97783233643631" + integrity sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.48.1" + "@typescript-eslint/type-utils" "8.48.1" + "@typescript-eslint/utils" "8.48.1" + "@typescript-eslint/visitor-keys" "8.48.1" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/eslint-plugin@^8.20.0", "@typescript-eslint/eslint-plugin@^8.29.1": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.4.tgz#005dc4eebcb27462f20de3afe888065f65cec100" + integrity sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.46.4" + "@typescript-eslint/type-utils" "8.46.4" + "@typescript-eslint/utils" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.48.1.tgz#4e3c66d9ec20683ec142417fafeadab61c479c3f" + integrity sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA== + dependencies: + "@typescript-eslint/scope-manager" "8.48.1" + "@typescript-eslint/types" "8.48.1" + "@typescript-eslint/typescript-estree" "8.48.1" + "@typescript-eslint/visitor-keys" "8.48.1" + debug "^4.3.4" + +"@typescript-eslint/parser@^8.20.0", "@typescript-eslint/parser@^8.29.1": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.46.4.tgz#1a5bfd48be57bc07eec64e090ac46e89f47ade31" + integrity sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w== + dependencies: + "@typescript-eslint/scope-manager" "8.46.4" + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/typescript-estree" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.46.4.tgz#fa9872673b51fb57e5d5da034edbe17424ddd185" + integrity sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.46.4" + "@typescript-eslint/types" "^8.46.4" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.48.1.tgz#cfe1741613b9112d85ae766de9e09b27a7d3f2f1" + integrity sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.48.1" + "@typescript-eslint/types" "^8.48.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.46.4", "@typescript-eslint/scope-manager@^8.1.0": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.4.tgz#78c9b4856c0094def64ffa53ea955b46bec13304" + integrity sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA== + dependencies: + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + +"@typescript-eslint/scope-manager@8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz#8bc70643e7cca57864b1ff95dd350fc27756bec0" + integrity sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w== + dependencies: + "@typescript-eslint/types" "8.48.1" + "@typescript-eslint/visitor-keys" "8.48.1" + +"@typescript-eslint/tsconfig-utils@8.46.4", "@typescript-eslint/tsconfig-utils@^8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.4.tgz#989a338093b6b91b0552f1f51331d89ec6980382" + integrity sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A== + +"@typescript-eslint/tsconfig-utils@8.48.1", "@typescript-eslint/tsconfig-utils@^8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz#68139ce2d258f984e2b33a95389158f1212af646" + integrity sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw== + +"@typescript-eslint/type-utils@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.46.4.tgz#ae71b428a3c138b5084affe47893c129949171e0" + integrity sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ== + dependencies: + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/typescript-estree" "8.46.4" + "@typescript-eslint/utils" "8.46.4" + debug "^4.3.4" + ts-api-utils "^2.1.0" + +"@typescript-eslint/type-utils@8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz#955bd3ddd648450f0a627925ff12ade63fb7516d" + integrity sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg== + dependencies: + "@typescript-eslint/types" "8.48.1" + "@typescript-eslint/typescript-estree" "8.48.1" + "@typescript-eslint/utils" "8.48.1" + debug "^4.3.4" + ts-api-utils "^2.1.0" + +"@typescript-eslint/types@8.46.4", "@typescript-eslint/types@^8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.4.tgz#38022bfda051be80e4120eeefcd2b6e3e630a69b" + integrity sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w== + +"@typescript-eslint/types@8.48.1", "@typescript-eslint/types@^8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.48.1.tgz#a9ff808f5f798f28767d5c0b015a88fa7ce46bd7" + integrity sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q== + +"@typescript-eslint/typescript-estree@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.4.tgz#6a9eeab0da45bf400f22c818e0f47102a980ceaa" + integrity sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA== + dependencies: + "@typescript-eslint/project-service" "8.46.4" + "@typescript-eslint/tsconfig-utils" "8.46.4" + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/visitor-keys" "8.46.4" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/typescript-estree@8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz#0d0e31fc47c5796c6463ab50cde19e1718d465b1" + integrity sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg== + dependencies: + "@typescript-eslint/project-service" "8.48.1" + "@typescript-eslint/tsconfig-utils" "8.48.1" + "@typescript-eslint/types" "8.48.1" + "@typescript-eslint/visitor-keys" "8.48.1" + debug "^4.3.4" + minimatch "^9.0.4" + semver "^7.6.0" + tinyglobby "^0.2.15" + ts-api-utils "^2.1.0" + +"@typescript-eslint/utils@8.46.4", "@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/utils@^8.1.0": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.4.tgz#ea7878ddd625948cad4424dc2752b1be236556f5" + integrity sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.46.4" + "@typescript-eslint/types" "8.46.4" + "@typescript-eslint/typescript-estree" "8.46.4" + +"@typescript-eslint/utils@8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.48.1.tgz#6cf7b99e0943b33a983ef687b9a86b65578b5c32" + integrity sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.48.1" + "@typescript-eslint/types" "8.48.1" + "@typescript-eslint/typescript-estree" "8.48.1" + +"@typescript-eslint/visitor-keys@8.46.4": + version "8.46.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.4.tgz#07031bd8d3ca6474e121221dae1055daead888f1" + integrity sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw== + dependencies: + "@typescript-eslint/types" "8.46.4" + eslint-visitor-keys "^4.2.1" + +"@typescript-eslint/visitor-keys@8.48.1": + version "8.48.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz#247d4fe6dcc044f45b7f1c15110bf95e5d73b334" + integrity sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q== + dependencies: + "@typescript-eslint/types" "8.48.1" + eslint-visitor-keys "^4.2.1" + +"@uiw/codemirror-extensions-basic-setup@4.25.3": + version "4.25.3" + resolved "https://registry.yarnpkg.com/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.25.3.tgz#6fb28745e7012bfcad0dc5103119487e40a744bc" + integrity sha512-F1doRyD50CWScwGHG2bBUtUpwnOv/zqSnzkZqJcX5YAHQx6Z1CuX8jdnFMH6qktRrPU1tfpNYftTWu3QIoHiMA== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/commands" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/search" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + +"@uiw/codemirror-theme-atomone@^4.21.24": + version "4.25.3" + resolved "https://registry.yarnpkg.com/@uiw/codemirror-theme-atomone/-/codemirror-theme-atomone-4.25.3.tgz#e984339c2d40cde2c4b1e2598f6600f8b5ef630a" + integrity sha512-4ZVHm1sQ+R5y4pnUMGccd8kGZYTzg1Nb6ZwGaMtOadpCQlbIjH9+P9dDdHmWrRcW+HOelzgDu+XNzr35ZZpmNQ== + dependencies: + "@uiw/codemirror-themes" "4.25.3" + +"@uiw/codemirror-theme-tokyo-night@^4.21.24": + version "4.25.3" + resolved "https://registry.yarnpkg.com/@uiw/codemirror-theme-tokyo-night/-/codemirror-theme-tokyo-night-4.25.3.tgz#305c7ccca1234cdfcdd5d547d0ef4b65b4942fa9" + integrity sha512-vqmw52WBUhC/wRZRmNIwEAm9GpFU+HIK+TMGt4BHdtbPhPV5LensZZA9HY/ORLT1169+/ufk7rX/C4jkAM9DYA== + dependencies: + "@uiw/codemirror-themes" "4.25.3" + +"@uiw/codemirror-theme-vscode@^4.21.24": + version "4.25.3" + resolved "https://registry.yarnpkg.com/@uiw/codemirror-theme-vscode/-/codemirror-theme-vscode-4.25.3.tgz#2488d75786b2601b684150205f964d27308165ad" + integrity sha512-4bKsR1P3Lit/ycJKIOeK1/w28Y8oxhGekLxQw93/2CYXH/B/MyUs1y1vmGCCL5Cq1qIZ+w2nFvXbZYELKFiwXw== + dependencies: + "@uiw/codemirror-themes" "4.25.3" + +"@uiw/codemirror-themes@4.25.3": + version "4.25.3" + resolved "https://registry.yarnpkg.com/@uiw/codemirror-themes/-/codemirror-themes-4.25.3.tgz#2990b0fc396574914e8bf87e54464079d71b009c" + integrity sha512-k7/B7Vf4jU/WcdewgJWP9tMFxbjB6UpUymZ3fx/TsbGwt2JXAouw0uyqCn1RlYBfr7YQnvEs3Ju9ECkd2sKzdg== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + +"@uiw/react-codemirror@^4.21.24": + version "4.25.3" + resolved "https://registry.yarnpkg.com/@uiw/react-codemirror/-/react-codemirror-4.25.3.tgz#dd61549051d4398068f087858b39f3fc988c7537" + integrity sha512-1wtBZTXPIp8u6F/xjHvsUAYlEeF5Dic4xZBnqJyLzv7o7GjGYEUfSz9Z7bo9aK9GAx2uojG/AuBMfhA4uhvIVQ== + dependencies: + "@babel/runtime" "^7.18.6" + "@codemirror/commands" "^6.1.0" + "@codemirror/state" "^6.1.1" + "@codemirror/theme-one-dark" "^6.0.0" + "@uiw/codemirror-extensions-basic-setup" "4.25.3" + codemirror "^6.0.0" + +"@ungap/structured-clone@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" + integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== + +"@unrs/resolver-binding-android-arm-eabi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz#9f5b04503088e6a354295e8ea8fe3cb99e43af81" + integrity sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw== + +"@unrs/resolver-binding-android-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz#7414885431bd7178b989aedc4d25cccb3865bc9f" + integrity sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g== + +"@unrs/resolver-binding-darwin-arm64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz#b4a8556f42171fb9c9f7bac8235045e82aa0cbdf" + integrity sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g== + +"@unrs/resolver-binding-darwin-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz#fd4d81257b13f4d1a083890a6a17c00de571f0dc" + integrity sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ== + +"@unrs/resolver-binding-freebsd-x64@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz#d2513084d0f37c407757e22f32bd924a78cfd99b" + integrity sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw== + +"@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz#844d2605d057488d77fab09705f2866b86164e0a" + integrity sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw== + +"@unrs/resolver-binding-linux-arm-musleabihf@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz#204892995cefb6bd1d017d52d097193bc61ddad3" + integrity sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw== + +"@unrs/resolver-binding-linux-arm64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz#023eb0c3aac46066a10be7a3f362e7b34f3bdf9d" + integrity sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ== + +"@unrs/resolver-binding-linux-arm64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz#9e6f9abb06424e3140a60ac996139786f5d99be0" + integrity sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w== + +"@unrs/resolver-binding-linux-ppc64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz#b111417f17c9d1b02efbec8e08398f0c5527bb44" + integrity sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA== + +"@unrs/resolver-binding-linux-riscv64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz#92ffbf02748af3e99873945c9a8a5ead01d508a9" + integrity sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ== + +"@unrs/resolver-binding-linux-riscv64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz#0bec6f1258fc390e6b305e9ff44256cb207de165" + integrity sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew== + +"@unrs/resolver-binding-linux-s390x-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz#577843a084c5952f5906770633ccfb89dac9bc94" + integrity sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg== + +"@unrs/resolver-binding-linux-x64-gnu@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz#36fb318eebdd690f6da32ac5e0499a76fa881935" + integrity sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w== + +"@unrs/resolver-binding-linux-x64-musl@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz#bfb9af75f783f98f6a22c4244214efe4df1853d6" + integrity sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA== + +"@unrs/resolver-binding-wasm32-wasi@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz#752c359dd875684b27429500d88226d7cc72f71d" + integrity sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ== + dependencies: + "@napi-rs/wasm-runtime" "^0.2.11" + +"@unrs/resolver-binding-win32-arm64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz#ce5735e600e4c2fbb409cd051b3b7da4a399af35" + integrity sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw== + +"@unrs/resolver-binding-win32-ia32-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz#72fc57bc7c64ec5c3de0d64ee0d1810317bc60a6" + integrity sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ== + +"@unrs/resolver-binding-win32-x64-msvc@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz#538b1e103bf8d9864e7b85cc96fa8d6fb6c40777" + integrity sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g== + +"@urql/core@^5.0.6", "@urql/core@^5.1.2": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@urql/core/-/core-5.2.0.tgz#77ee41e192e261fea30c2ca6c2f340410b45d214" + integrity sha512-/n0ieD0mvvDnVAXEQgX/7qJiVcvYvNkOHeBvkwtylfjydar123caCXcl58PXFY11oU1oquJocVXHxLAbtv4x1A== + dependencies: + "@0no-co/graphql.web" "^1.0.13" + wonka "^6.3.2" + +"@urql/exchange-retry@^1.3.0": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@urql/exchange-retry/-/exchange-retry-1.3.2.tgz#042ff5f3512a062651ec7257f1b07f9db2f6fefd" + integrity sha512-TQMCz2pFJMfpNxmSfX1VSfTjwUIFx/mL+p1bnfM1xjjdla7Z+KnGMW/EhFbpckp3LyWAH4PgOsMwOMnIN+MBFg== + dependencies: + "@urql/core" "^5.1.2" + wonka "^6.3.2" + +"@vitejs/plugin-react@^4.3.0": + version "4.7.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz#647af4e7bb75ad3add578e762ad984b90f4a24b9" + integrity sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA== + dependencies: + "@babel/core" "^7.28.0" + "@babel/plugin-transform-react-jsx-self" "^7.27.1" + "@babel/plugin-transform-react-jsx-source" "^7.27.1" + "@rolldown/pluginutils" "1.0.0-beta.27" + "@types/babel__core" "^7.20.5" + react-refresh "^0.17.0" + +"@vitest/expect@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.2.4.tgz#8362124cd811a5ee11c5768207b9df53d34f2433" + integrity sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig== + dependencies: + "@types/chai" "^5.2.2" + "@vitest/spy" "3.2.4" + "@vitest/utils" "3.2.4" + chai "^5.2.0" + tinyrainbow "^2.0.0" + +"@vitest/mocker@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.2.4.tgz#4471c4efbd62db0d4fa203e65cc6b058a85cabd3" + integrity sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ== + dependencies: + "@vitest/spy" "3.2.4" + estree-walker "^3.0.3" + magic-string "^0.30.17" + +"@vitest/pretty-format@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.2.4.tgz#3c102f79e82b204a26c7a5921bf47d534919d3b4" + integrity sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA== + dependencies: + tinyrainbow "^2.0.0" + +"@vitest/spy@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.2.4.tgz#cc18f26f40f3f028da6620046881f4e4518c2599" + integrity sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw== + dependencies: + tinyspy "^4.0.3" + +"@vitest/utils@3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.2.4.tgz#c0813bc42d99527fb8c5b138c7a88516bca46fea" + integrity sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA== + dependencies: + "@vitest/pretty-format" "3.2.4" + loupe "^3.1.4" + tinyrainbow "^2.0.0" + +"@wagmi/connectors@6.2.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/@wagmi/connectors/-/connectors-6.2.0.tgz#b90bb85c59305d36f4ca3247fe31c148db5d110b" + integrity sha512-2NfkbqhNWdjfibb4abRMrn7u6rPjEGolMfApXss6HCDVt9AW2oVC6k8Q5FouzpJezElxLJSagWz9FW1zaRlanA== + dependencies: + "@base-org/account" "2.4.0" + "@coinbase/wallet-sdk" "4.3.6" + "@gemini-wallet/core" "0.3.2" + "@metamask/sdk" "0.33.1" + "@safe-global/safe-apps-provider" "0.18.6" + "@safe-global/safe-apps-sdk" "9.1.0" + "@walletconnect/ethereum-provider" "2.21.1" + cbw-sdk "npm:@coinbase/wallet-sdk@3.9.3" + porto "0.2.35" + +"@wagmi/core@2.22.1": + version "2.22.1" + resolved "https://registry.yarnpkg.com/@wagmi/core/-/core-2.22.1.tgz#de4b5019971dcf033ea5f7484add66900da7897c" + integrity sha512-cG/xwQWsBEcKgRTkQVhH29cbpbs/TdcUJVFXCyri3ZknxhMyGv0YEjTcrNpRgt2SaswL1KrvslSNYKKo+5YEAg== + dependencies: + eventemitter3 "5.0.1" + mipd "0.0.7" + zustand "5.0.0" + +"@wallet-standard/app@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@wallet-standard/app/-/app-1.1.0.tgz#2ca32e4675536224ebe55a00ad533b7923d7380a" + integrity sha512-3CijvrO9utx598kjr45hTbbeeykQrQfKmSnxeWOgU25TOEpvcipD/bYDQWIqUv1Oc6KK4YStokSMu/FBNecGUQ== + dependencies: + "@wallet-standard/base" "^1.1.0" + +"@wallet-standard/base@^1.0.1", "@wallet-standard/base@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@wallet-standard/base/-/base-1.1.0.tgz#214093c0597a1e724ee6dbacd84191dfec62bb33" + integrity sha512-DJDQhjKmSNVLKWItoKThJS+CsJQjR9AOBOirBVT1F9YpRyC9oYHE+ZnSf8y8bxUphtKqdQMPVQ2mHohYdRvDVQ== + +"@wallet-standard/core@^1.0.3": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@wallet-standard/core/-/core-1.1.1.tgz#432e10420dc8892a63224d4863f8304fa01b4ea1" + integrity sha512-5Xmjc6+Oe0hcPfVc5n8F77NVLwx1JVAoCVgQpLyv/43/bhtIif+Gx3WUrDlaSDoM8i2kA2xd6YoFbHCxs+e0zA== + dependencies: + "@wallet-standard/app" "^1.1.0" + "@wallet-standard/base" "^1.1.0" + "@wallet-standard/errors" "^0.1.1" + "@wallet-standard/features" "^1.1.0" + "@wallet-standard/wallet" "^1.1.0" + +"@wallet-standard/errors@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@wallet-standard/errors/-/errors-0.1.1.tgz#e745c5925276c0ac6d02f0d489888c171f5e4680" + integrity sha512-V8Ju1Wvol8i/VDyQOHhjhxmMVwmKiwyxUZBnHhtiPZJTWY0U/Shb2iEWyGngYEbAkp2sGTmEeNX1tVyGR7PqNw== + dependencies: + chalk "^5.4.1" + commander "^13.1.0" + +"@wallet-standard/features@^1.0.3", "@wallet-standard/features@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@wallet-standard/features/-/features-1.1.0.tgz#f256d7b18940c8d134f66164330db358a8f5200e" + integrity sha512-hiEivWNztx73s+7iLxsuD1sOJ28xtRix58W7Xnz4XzzA/pF0+aicnWgjOdA10doVDEDZdUuZCIIqG96SFNlDUg== + dependencies: + "@wallet-standard/base" "^1.1.0" + +"@wallet-standard/wallet@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@wallet-standard/wallet/-/wallet-1.1.0.tgz#a1e46a3f1b2d06a0206058562169b1f0e9652d0f" + integrity sha512-Gt8TnSlDZpAl+RWOOAB/kuvC7RpcdWAlFbHNoi4gsXsfaWa1QCT6LBcfIYTPdOZC9OVZUDwqGuGAcqZejDmHjg== + dependencies: + "@wallet-standard/base" "^1.1.0" + +"@walletconnect/core@2.21.0": + version "2.21.0" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.21.0.tgz#a8927c79cd5ff47a2eaa8dd6a8e8f0060619393d" + integrity sha512-o6R7Ua4myxR8aRUAJ1z3gT9nM+jd2B2mfamu6arzy1Cc6vi10fIwFWb6vg3bC8xJ6o9H3n/cN5TOW3aA9Y1XVw== + dependencies: + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "1.0.16" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + "@walletconnect/relay-api" "1.0.11" + "@walletconnect/relay-auth" "1.1.0" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.21.0" + "@walletconnect/utils" "2.21.0" + "@walletconnect/window-getters" "1.0.1" + es-toolkit "1.33.0" + events "3.3.0" + uint8arrays "3.1.0" + +"@walletconnect/core@2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.21.1.tgz#fb5ba547acb2b297a8b29b4f972167886374c9dc" + integrity sha512-Tp4MHJYcdWD846PH//2r+Mu4wz1/ZU/fr9av1UWFiaYQ2t2TPLDiZxjLw54AAEpMqlEHemwCgiRiAmjR1NDdTQ== + dependencies: + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "1.0.16" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + "@walletconnect/relay-api" "1.0.11" + "@walletconnect/relay-auth" "1.1.0" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.21.1" + "@walletconnect/utils" "2.21.1" + "@walletconnect/window-getters" "1.0.1" + es-toolkit "1.33.0" + events "3.3.0" + uint8arrays "3.1.0" + +"@walletconnect/environment@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" + integrity sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg== + dependencies: + tslib "1.14.1" + +"@walletconnect/ethereum-provider@2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.21.1.tgz#b1e3cdcf4894613b11353bd702c019027e5a2cde" + integrity sha512-SSlIG6QEVxClgl1s0LMk4xr2wg4eT3Zn/Hb81IocyqNSGfXpjtawWxKxiC5/9Z95f1INyBD6MctJbL/R1oBwIw== + dependencies: + "@reown/appkit" "1.7.8" + "@walletconnect/jsonrpc-http-connection" "1.0.8" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/sign-client" "2.21.1" + "@walletconnect/types" "2.21.1" + "@walletconnect/universal-provider" "2.21.1" + "@walletconnect/utils" "2.21.1" + events "3.3.0" + +"@walletconnect/events@1.0.1", "@walletconnect/events@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/events/-/events-1.0.1.tgz#2b5f9c7202019e229d7ccae1369a9e86bda7816c" + integrity sha512-NPTqaoi0oPBVNuLv7qPaJazmGHs5JGyO8eEAk5VGKmJzDR7AHzD4k6ilox5kxk1iwiOnFopBOOMLs86Oa76HpQ== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/heartbeat@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@walletconnect/heartbeat/-/heartbeat-1.2.2.tgz#e8dc5179db7769950c6f9cf59b23516d9b95227d" + integrity sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/time" "^1.0.2" + events "^3.3.0" + +"@walletconnect/jsonrpc-http-connection@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.8.tgz#2f4c3948f074960a3edd07909560f3be13e2c7ae" + integrity sha512-+B7cRuaxijLeFDJUq5hAzNyef3e3tBDIxyaCNmFtjwnod5AGis3RToNqzFU33vpVcxFhofkpE7Cx+5MYejbMGw== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.1" + cross-fetch "^3.1.4" + events "^3.3.0" + +"@walletconnect/jsonrpc-provider@1.0.14": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz#696f3e3b6d728b361f2e8b853cfc6afbdf2e4e3e" + integrity sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.8" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + +"@walletconnect/jsonrpc-types@1.0.4", "@walletconnect/jsonrpc-types@^1.0.2", "@walletconnect/jsonrpc-types@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.4.tgz#ce1a667d79eadf2a2d9d002c152ceb68739c230c" + integrity sha512-P6679fG/M+wuWg9TY8mh6xFSdYnFyFjwFelxyISxMDrlbXokorEVXYOxiqEbrU3x1BmBoCAJJ+vtEaEoMlpCBQ== + dependencies: + events "^3.3.0" + keyvaluestorage-interface "^1.0.0" + +"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72" + integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw== + dependencies: + "@walletconnect/environment" "^1.0.1" + "@walletconnect/jsonrpc-types" "^1.0.3" + tslib "1.14.1" + +"@walletconnect/jsonrpc-ws-connection@1.0.16": + version "1.0.16" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.16.tgz#666bb13fbf32a2d4f7912d5b4d0bdef26a1d057b" + integrity sha512-G81JmsMqh5nJheE1mPst1W0WfVv0SG3N7JggwLLGnI7iuDZJq8cRJvQwLGKHn5H1WTW7DEPCo00zz5w62AbL3Q== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + ws "^7.5.1" + +"@walletconnect/keyvaluestorage@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842" + integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA== + dependencies: + "@walletconnect/safe-json" "^1.0.1" + idb-keyval "^6.2.1" + unstorage "^1.9.0" + +"@walletconnect/logger@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.1.2.tgz#813c9af61b96323a99f16c10089bfeb525e2a272" + integrity sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw== + dependencies: + "@walletconnect/safe-json" "^1.0.2" + pino "7.11.0" + +"@walletconnect/react-native-compat@^2.13.3": + version "2.23.0" + resolved "https://registry.yarnpkg.com/@walletconnect/react-native-compat/-/react-native-compat-2.23.0.tgz#1802968e0fd5e1b71e5fd49fbfdb10b75ffe3990" + integrity sha512-FwYrhoD/JGiVNOcj4OIFntRBs35fbLcGgZBUCiwNcWBZH0XfIfZL9BcAn9TCqsCb5d7j/W3prdQt0f3P8qTsKw== + dependencies: + events "3.3.0" + fast-text-encoding "1.0.6" + react-native-url-polyfill "2.0.0" + +"@walletconnect/relay-api@1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.11.tgz#80ab7ef2e83c6c173be1a59756f95e515fb63224" + integrity sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q== + dependencies: + "@walletconnect/jsonrpc-types" "^1.0.2" + +"@walletconnect/relay-auth@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@walletconnect/relay-auth/-/relay-auth-1.1.0.tgz#c3c5f54abd44a5138ea7d4fe77970597ba66c077" + integrity sha512-qFw+a9uRz26jRCDgL7Q5TA9qYIgcNY8jpJzI1zAWNZ8i7mQjaijRnWFKsCHAU9CyGjvt6RKrRXyFtFOpWTVmCQ== + dependencies: + "@noble/curves" "1.8.0" + "@noble/hashes" "1.7.0" + "@walletconnect/safe-json" "^1.0.1" + "@walletconnect/time" "^1.0.2" + uint8arrays "^3.0.0" + +"@walletconnect/safe-json@1.0.2", "@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77" + integrity sha512-Ogb7I27kZ3LPC3ibn8ldyUr5544t3/STow9+lzz7Sfo808YD7SBWk7SAsdBFlYgP2zDRy2hS3sKRcuSRM0OTmA== + dependencies: + tslib "1.14.1" + +"@walletconnect/sign-client@2.21.0": + version "2.21.0" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.21.0.tgz#3dc3be83be58ad9a9fb53d0fd8fa5e571cfdd046" + integrity sha512-z7h+PeLa5Au2R591d/8ZlziE0stJvdzP9jNFzFolf2RG/OiXulgFKum8PrIyXy+Rg2q95U9nRVUF9fWcn78yBA== + dependencies: + "@walletconnect/core" "2.21.0" + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "2.1.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.21.0" + "@walletconnect/utils" "2.21.0" + events "3.3.0" + +"@walletconnect/sign-client@2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.21.1.tgz#a0d42ae44f801d131208df7216a0326a9fad61bb" + integrity sha512-QaXzmPsMnKGV6tc4UcdnQVNOz4zyXgarvdIQibJ4L3EmLat73r5ZVl4c0cCOcoaV7rgM9Wbphgu5E/7jNcd3Zg== + dependencies: + "@walletconnect/core" "2.21.1" + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "2.1.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.21.1" + "@walletconnect/utils" "2.21.1" + events "3.3.0" + +"@walletconnect/time@1.0.2", "@walletconnect/time@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/time/-/time-1.0.2.tgz#6c5888b835750ecb4299d28eecc5e72c6d336523" + integrity sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g== + dependencies: + tslib "1.14.1" + +"@walletconnect/types@2.21.0": + version "2.21.0" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.21.0.tgz#afb47ff5966d57f97dd955dc3fa4817c616b9c24" + integrity sha512-ll+9upzqt95ZBWcfkOszXZkfnpbJJ2CmxMfGgE5GmhdxxxCcO5bGhXkI+x8OpiS555RJ/v/sXJYMSOLkmu4fFw== + dependencies: + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + events "3.3.0" + +"@walletconnect/types@2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.21.1.tgz#258c1b94eac20f20896b7998a76ff4f18c935983" + integrity sha512-UeefNadqP6IyfwWC1Yi7ux+ljbP2R66PLfDrDm8izmvlPmYlqRerJWJvYO4t0Vvr9wrG4Ko7E0c4M7FaPKT/sQ== + dependencies: + "@walletconnect/events" "1.0.1" + "@walletconnect/heartbeat" "1.2.2" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + events "3.3.0" + +"@walletconnect/universal-provider@2.21.0": + version "2.21.0" + resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.21.0.tgz#fb21e9726a8eb983df70cf2b304b110b6a0b1354" + integrity sha512-mtUQvewt+X0VBQay/xOJBvxsB3Xsm1lTwFjZ6WUwSOTR1X+FNb71hSApnV5kbsdDIpYPXeQUbGt2se1n5E5UBg== + dependencies: + "@walletconnect/events" "1.0.1" + "@walletconnect/jsonrpc-http-connection" "1.0.8" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + "@walletconnect/sign-client" "2.21.0" + "@walletconnect/types" "2.21.0" + "@walletconnect/utils" "2.21.0" + es-toolkit "1.33.0" + events "3.3.0" + +"@walletconnect/universal-provider@2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.21.1.tgz#e6047b89454c64ee0766595b36ec308fba3b55e2" + integrity sha512-Wjx9G8gUHVMnYfxtasC9poGm8QMiPCpXpbbLFT+iPoQskDDly8BwueWnqKs4Mx2SdIAWAwuXeZ5ojk5qQOxJJg== + dependencies: + "@walletconnect/events" "1.0.1" + "@walletconnect/jsonrpc-http-connection" "1.0.8" + "@walletconnect/jsonrpc-provider" "1.0.14" + "@walletconnect/jsonrpc-types" "1.0.4" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/logger" "2.1.2" + "@walletconnect/sign-client" "2.21.1" + "@walletconnect/types" "2.21.1" + "@walletconnect/utils" "2.21.1" + es-toolkit "1.33.0" + events "3.3.0" + +"@walletconnect/utils@2.21.0": + version "2.21.0" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.21.0.tgz#53517aab2ba456b9765b8ab064c7f721acfc4626" + integrity sha512-zfHLiUoBrQ8rP57HTPXW7rQMnYxYI4gT9yTACxVW6LhIFROTF6/ytm5SKNoIvi4a5nX5dfXG4D9XwQUCu8Ilig== + dependencies: + "@noble/ciphers" "1.2.1" + "@noble/curves" "1.8.1" + "@noble/hashes" "1.7.1" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/relay-api" "1.0.11" + "@walletconnect/relay-auth" "1.1.0" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.21.0" + "@walletconnect/window-getters" "1.0.1" + "@walletconnect/window-metadata" "1.0.1" + bs58 "6.0.0" + detect-browser "5.3.0" + query-string "7.1.3" + uint8arrays "3.1.0" + viem "2.23.2" + +"@walletconnect/utils@2.21.1": + version "2.21.1" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.21.1.tgz#acdadc38685cefbc6b49b7d7853893dfcb8ee044" + integrity sha512-VPZvTcrNQCkbGOjFRbC24mm/pzbRMUq2DSQoiHlhh0X1U7ZhuIrzVtAoKsrzu6rqjz0EEtGxCr3K1TGRqDG4NA== + dependencies: + "@noble/ciphers" "1.2.1" + "@noble/curves" "1.8.1" + "@noble/hashes" "1.7.1" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/keyvaluestorage" "1.1.1" + "@walletconnect/relay-api" "1.0.11" + "@walletconnect/relay-auth" "1.1.0" + "@walletconnect/safe-json" "1.0.2" + "@walletconnect/time" "1.0.2" + "@walletconnect/types" "2.21.1" + "@walletconnect/window-getters" "1.0.1" + "@walletconnect/window-metadata" "1.0.1" + bs58 "6.0.0" + detect-browser "5.3.0" + query-string "7.1.3" + uint8arrays "3.1.0" + viem "2.23.2" + +"@walletconnect/window-getters@1.0.1", "@walletconnect/window-getters@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" + integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== + dependencies: + tslib "1.14.1" + +"@walletconnect/window-metadata@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz#2124f75447b7e989e4e4e1581d55d25bc75f7be5" + integrity sha512-9koTqyGrM2cqFRW517BPY/iEtUDx2r1+Pwwu5m7sJ7ka79wi3EyqhqcICk/yDmv6jAS1rjKgTKXlEhanYjijcA== + dependencies: + "@walletconnect/window-getters" "^1.0.1" + tslib "1.14.1" + +"@welldone-software/why-did-you-render@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-10.0.1.tgz#4513c1883add0496b98bcdcdcd243ff10c0f5ece" + integrity sha512-tMgGkt30iVYeLMUKExNmtm019QgyjLtA7lwB0QAizYNEuihlCG2eoAWBBaz/bDeI7LeqAJ9msC6hY3vX+JB97g== + dependencies: + lodash "^4" + +"@xmldom/xmldom@^0.8.8": + version "0.8.11" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz#b79de2d67389734c57c52595f7a7305e30c2d608" + integrity sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw== + +"@xmldom/xmldom@~0.7.7": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.13.tgz#ff34942667a4e19a9f4a0996a76814daac364cf3" + integrity sha512-lm2GW5PkosIzccsaZIz7tp8cPADSIlIHWDFTR1N0SzfinhhYgeIQjFMz4rYzanCScr3DqQLeomUDArp6MWKm+g== + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +"@zag-js/dom-query@0.31.1": + version "0.31.1" + resolved "https://registry.yarnpkg.com/@zag-js/dom-query/-/dom-query-0.31.1.tgz#f40be43d0eb1eabdf51538abeeccad46c5b88ed6" + integrity sha512-oiuohEXAXhBxpzzNm9k2VHGEOLC1SXlXSbRPcfBZ9so5NRQUA++zCE7cyQJqGLTZR0t3itFLlZqDbYEXRrefwg== + +"@zag-js/element-size@0.31.1": + version "0.31.1" + resolved "https://registry.yarnpkg.com/@zag-js/element-size/-/element-size-0.31.1.tgz#1b3d237618d12b00c0a7dd8e33e29fb8f8cd4f0c" + integrity sha512-4T3yvn5NqqAjhlP326Fv+w9RqMIBbNN9H72g5q2ohwzhSgSfZzrKtjL4rs9axY/cw9UfMfXjRjEE98e5CMq7WQ== + +"@zag-js/focus-visible@^0.31.1": + version "0.31.1" + resolved "https://registry.yarnpkg.com/@zag-js/focus-visible/-/focus-visible-0.31.1.tgz#bd6b94e48eff0566c047b55a3c9ccd9890f5eaaa" + integrity sha512-dbLksz7FEwyFoANbpIlNnd3bVm0clQSUsnP8yUVQucStZPsuWjCrhL2jlAbGNrTrahX96ntUMXHb/sM68TibFg== + dependencies: + "@zag-js/dom-query" "0.31.1" + +abab@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + +abitype@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.6.tgz#76410903e1d88e34f1362746e2d407513c38565b" + integrity sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A== + +abitype@1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.0.8.tgz#3554f28b2e9d6e9f35eb59878193eabd1b9f46ba" + integrity sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg== + +abitype@1.2.3, abitype@^1.0.6, abitype@^1.0.9, abitype@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.2.3.tgz#bec3e09dea97d99ef6c719140bee663a329ad1f4" + integrity sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +accepts@^1.3.7, accepts@^1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +accepts@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" + integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== + dependencies: + mime-types "^3.0.0" + negotiator "^1.0.0" + +acorn-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" + integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== + dependencies: + acorn "^8.1.0" + acorn-walk "^8.0.2" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-loose@^8.3.0: + version "8.5.2" + resolved "https://registry.yarnpkg.com/acorn-loose/-/acorn-loose-8.5.2.tgz#a7cc7dfbb7c8f3c2e55b055db640dc657e278d26" + integrity sha512-PPvV6g8UGMGgjrMu+n/f9E/tCSkNQ2Y97eFvuVdJfG11+xdIeDcLyNdC8SHcrHbRqkfwLASdplyR6B6sKM1U4A== + dependencies: + acorn "^8.15.0" + +acorn-walk@^8.0.2: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.1.0, acorn@^8.11.0, acorn@^8.15.0, acorn@^8.8.1: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +add@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/add/-/add-2.0.6.tgz#248f0a9f6e5a528ef2295dbeec30532130ae2235" + integrity sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== + +aes-js@4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.5.tgz#8d2452c52adedebc3a3e28465d858c11ca315873" + integrity sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q== + +ag-auth@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ag-auth/-/ag-auth-2.1.0.tgz#e6f9ecabbf23352456bd1e51ada4d6cf2382198d" + integrity sha512-M4l+IErFmYPk0HAvolaPyvCMyn3oJ4aPHVMeVqlxJIynkHGhyTFiT+LX+jYY34pEdwM03TLkQUMHxpXBMuNmZg== + dependencies: + jsonwebtoken "^9.0.0" + sc-errors "^3.0.0" + +ag-channel@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ag-channel/-/ag-channel-5.0.0.tgz#c2c00dfbe372ae43e0466ec89e29aca1bbb2fb3e" + integrity sha512-bArHkdqQxynim981t8FLZM5TfA0v7p081OlFdOxs6clB79GSGcGlOQMDa31DT9F5VMjzqNiJmhfGwinvfU/3Zg== + dependencies: + consumable-stream "^2.0.0" + +ag-request@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ag-request/-/ag-request-1.1.0.tgz#62ef63c572510bbce34993a5d47e467d0040a17f" + integrity sha512-d4K7QC1KnIpzcnUNNOeh1ddxmYMLiIdhdc1M8osxiHbZP/uoia4IINhhf2+1CrlnNJEPUoUH0Y58Sx0qeqoIvg== + dependencies: + sc-errors "^3.0.0" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + +agentkeepalive@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a" + integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ== + dependencies: + humanize-ms "^1.2.1" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv-formats@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-3.0.1.tgz#3d5dc762bca17679c3c2ea7e90ad6b7532309578" + integrity sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.11.0, ajv@^8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + +anser@^1.4.9: + version "1.4.10" + resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.10.tgz#befa3eddf282684bd03b63dcda3927aef8c2e35b" + integrity sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww== + +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-escapes@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f" + integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-regex@^5.0.0, ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0, ansi-styles@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +ansi-styles@^6.1.0: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== + +anymatch@^3.0.3, anymatch@^3.1.3, anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0" + integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg== + +arg@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-hidden@^1.2.3: + version "1.2.6" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.6.tgz#73051c9b088114c795b1ea414e9c0fff874ffc1a" + integrity sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA== + dependencies: + tslib "^2.0.0" + +aria-query@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + +aria-query@^5.0.0, aria-query@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== + dependencies: + call-bound "^1.0.3" + is-array-buffer "^3.0.5" + +array-includes@^3.1.6, array-includes@^3.1.8, array-includes@^3.1.9: + version "3.1.9" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.9.tgz#1f0ccaa08e90cdbc3eb433210f903ad0f17c3f3a" + integrity sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-abstract "^1.24.0" + es-object-atoms "^1.1.1" + get-intrinsic "^1.3.0" + is-string "^1.1.1" + math-intrinsics "^1.1.0" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.findlastindex@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz#cfa1065c81dcb64e34557c9b81d012f6a421c564" + integrity sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-abstract "^1.23.9" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + es-shim-unscopables "^1.1.0" + +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + is-array-buffer "^3.0.4" + +asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +assert@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.1.0.tgz#6d92a238d05dc02e7427c881fb8be81c8448b2dd" + integrity sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw== + dependencies: + call-bind "^1.0.2" + is-nan "^1.3.2" + object-is "^1.1.5" + object.assign "^4.1.4" + util "^0.12.5" + +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + +ast-types-flow@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" + integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== + +ast-types@^0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.16.1.tgz#7a9da1617c9081bc121faafe91711b4c8bb81da2" + integrity sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg== + dependencies: + tslib "^2.0.1" + +async-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" + integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async-mutex@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.2.6.tgz#0d7a3deb978bc2b984d5908a2038e1ae2e54ff40" + integrity sha512-Hs4R+4SPgamu6rSGW8C7cV9gaWUKEHykfzCCvIRuaVv636Ju10ZdeUbvb4TBEW0INuq2DHZqXbK4Nd3yG4RaRw== + dependencies: + tslib "^2.0.0" + +async-stream-emitter@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/async-stream-emitter/-/async-stream-emitter-7.0.1.tgz#c01832cddcc8f07d8ed528347803ec1517f8886d" + integrity sha512-1bgA3iZ80rCBX2LocvsyZPy0QB3/xM+CsXBze2HDHLmshOqx2JlAANGq23djaJ48e9fpcKzTzS1QM0hAKKI0UQ== + dependencies: + stream-demux "^10.0.1" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + +autoprefixer@^10.4.20: + version "10.4.27" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.27.tgz#51ea301a5c3c5f8642f8e564759c4f573be486f2" + integrity sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA== + dependencies: + browserslist "^4.28.1" + caniuse-lite "^1.0.30001774" + fraction.js "^5.3.4" + picocolors "^1.1.1" + postcss-value-parser "^4.2.0" + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +axe-core@^4.10.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.11.0.tgz#16f74d6482e343ff263d4f4503829e9ee91a86b6" + integrity sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ== + +axios-retry@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-4.5.0.tgz#441fdc32cedf63d6abd5de5d53db3667afd4c39b" + integrity sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ== + dependencies: + is-retry-allowed "^2.2.0" + +axios@^1.12.2: + version "1.13.6" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.6.tgz#c3f92da917dc209a15dd29936d20d5089b6b6c98" + integrity sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ== + dependencies: + follow-redirects "^1.15.11" + form-data "^4.0.5" + proxy-from-env "^1.1.0" + +axios@^1.6.2, axios@^1.6.8: + version "1.13.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.2.tgz#9ada120b7b5ab24509553ec3e40123521117f687" + integrity sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.4" + proxy-from-env "^1.1.0" + +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== + +babel-jest@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-30.2.0.tgz#fd44a1ec9552be35ead881f7381faa7d8f3b95ac" + integrity sha512-0YiBEOxWqKkSQWL9nNGGEgndoeL0ZpWrbLMNL5u/Kaxrli3Eaxlt3ZtIDktEvXt4L/R9r3ODr2zKwGM/2BjxVw== + dependencies: + "@jest/transform" "30.2.0" + "@types/babel__core" "^7.20.5" + babel-plugin-istanbul "^7.0.1" + babel-preset-jest "30.2.0" + chalk "^4.1.2" + graceful-fs "^4.2.11" + slash "^3.0.0" + +babel-jest@^29.2.1, babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-loader@^8.4.1: + version "8.4.1" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.4.1.tgz#6ccb75c66e62c3b144e1c5f2eaec5b8f6c08c675" + integrity sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^2.0.4" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-istanbul@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.1.tgz#d8b518c8ea199364cf84ccc82de89740236daf92" + integrity sha512-D8Z6Qm8jCvVXtIRkBnqNHX0zJ37rQcFJ9u8WOS6tkYOsRdHBzypCstaxWiu5ZIlqQtviRYbgnRLSoCEvjqcqbA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-instrument "^6.0.2" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.2.0.tgz#94c250d36b43f95900f3a219241e0f4648191ce2" + integrity sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA== + dependencies: + "@types/babel__core" "^7.20.5" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-macros@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + +babel-plugin-module-resolver@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-5.0.2.tgz#cdeac5d4aaa3b08dd1ac23ddbf516660ed2d293e" + integrity sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg== + dependencies: + find-babel-config "^2.1.1" + glob "^9.3.3" + pkg-up "^3.1.0" + reselect "^4.1.7" + resolve "^1.22.8" + +babel-plugin-polyfill-corejs2@^0.4.14: + version "0.4.14" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz#8101b82b769c568835611542488d463395c2ef8f" + integrity sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg== + dependencies: + "@babel/compat-data" "^7.27.7" + "@babel/helper-define-polyfill-provider" "^0.6.5" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz#bb7f6aeef7addff17f7602a08a6d19a128c30164" + integrity sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.5" + core-js-compat "^3.43.0" + +babel-plugin-polyfill-regenerator@^0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz#32752e38ab6f6767b92650347bf26a31b16ae8c5" + integrity sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.5" + +babel-plugin-react-compiler@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz#bdf7360a23a4d5ebfca090255da3893efd07425f" + integrity sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw== + dependencies: + "@babel/types" "^7.26.0" + +babel-plugin-react-native-web@~0.19.13: + version "0.19.13" + resolved "https://registry.yarnpkg.com/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.19.13.tgz#bf919bd6f18c4689dd1a528a82bda507363b953d" + integrity sha512-4hHoto6xaN23LCyZgL9LJZc3olmAxd7b6jDzlZnKXAh4rRAbZRKNBJoOOdp46OBqgy+K0t0guTj5/mhA8inymQ== + +babel-plugin-react-native-web@~0.21.0: + version "0.21.2" + resolved "https://registry.yarnpkg.com/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz#d2f7fd673278da82577aa583457edb55d9cccbe0" + integrity sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA== + +babel-plugin-syntax-hermes-parser@0.25.1, babel-plugin-syntax-hermes-parser@^0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz#58b539df973427fcfbb5176a3aec7e5dee793cb0" + integrity sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ== + dependencies: + hermes-parser "0.25.1" + +babel-plugin-syntax-hermes-parser@0.29.1, babel-plugin-syntax-hermes-parser@^0.29.1: + version "0.29.1" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz#09ca9ecb0330eba1ef939b6d3f1f55bb06a9dc33" + integrity sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA== + dependencies: + hermes-parser "0.29.1" + +babel-plugin-transform-flow-enums@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz#d1d0cc9bdc799c850ca110d0ddc9f21b9ec3ef25" + integrity sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ== + dependencies: + "@babel/plugin-syntax-flow" "^7.12.1" + +babel-preset-current-node-syntax@^1.0.0, babel-preset-current-node-syntax@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz#20730d6cdc7dda5d89401cab10ac6a32067acde6" + integrity sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + +babel-preset-expo@~13.2.3: + version "13.2.4" + resolved "https://registry.yarnpkg.com/babel-preset-expo/-/babel-preset-expo-13.2.4.tgz#ad31bbfc8b3169a5a61108cebdee5350feebc071" + integrity sha512-3IKORo3KR+4qtLdCkZNDj8KeA43oBn7RRQejFGWfiZgu/NeaRUSri8YwYjZqybm7hn3nmMv9OLahlvXBX23o5Q== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/plugin-proposal-decorators" "^7.12.9" + "@babel/plugin-proposal-export-default-from" "^7.24.7" + "@babel/plugin-syntax-export-default-from" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.25.9" + "@babel/plugin-transform-flow-strip-types" "^7.25.2" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-runtime" "^7.24.7" + "@babel/preset-react" "^7.22.15" + "@babel/preset-typescript" "^7.23.0" + "@react-native/babel-preset" "0.79.6" + babel-plugin-react-native-web "~0.19.13" + babel-plugin-syntax-hermes-parser "^0.25.1" + babel-plugin-transform-flow-enums "^0.0.2" + debug "^4.3.4" + react-refresh "^0.14.2" + resolve-from "^5.0.0" + +babel-preset-expo@~54.0.7: + version "54.0.7" + resolved "https://registry.yarnpkg.com/babel-preset-expo/-/babel-preset-expo-54.0.7.tgz#451e5860ed13bc2496ad0acd9aa3bd1b8ea5f17b" + integrity sha512-JENWk0bvxW4I1ftveO8GRtX2t2TH6N4Z0TPvIHxroZ/4SswUfyNsUNbbP7Fm4erj3ar/JHGri5kTZ+s3xdjHZw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/plugin-proposal-decorators" "^7.12.9" + "@babel/plugin-proposal-export-default-from" "^7.24.7" + "@babel/plugin-syntax-export-default-from" "^7.24.7" + "@babel/plugin-transform-class-static-block" "^7.27.1" + "@babel/plugin-transform-export-namespace-from" "^7.25.9" + "@babel/plugin-transform-flow-strip-types" "^7.25.2" + "@babel/plugin-transform-modules-commonjs" "^7.24.8" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-runtime" "^7.24.7" + "@babel/preset-react" "^7.22.15" + "@babel/preset-typescript" "^7.23.0" + "@react-native/babel-preset" "0.81.5" + babel-plugin-react-compiler "^1.0.0" + babel-plugin-react-native-web "~0.21.0" + babel-plugin-syntax-hermes-parser "^0.29.1" + babel-plugin-transform-flow-enums "^0.0.2" + debug "^4.3.4" + resolve-from "^5.0.0" + +babel-preset-jest@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-30.2.0.tgz#04717843e561347781d6d7f69c81e6bcc3ed11ce" + integrity sha512-US4Z3NOieAQumwFnYdUWKvUKh8+YSnS/gB3t6YBiz0bskpu7Pine8pPCheNxlPEW4wnUkma2a94YuW2q3guvCQ== + dependencies: + babel-plugin-jest-hoist "30.2.0" + babel-preset-current-node-syntax "^1.2.0" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +badgin@^1.1.5: + version "1.2.3" + resolved "https://registry.yarnpkg.com/badgin/-/badgin-1.2.3.tgz#994b5f519827d7d5422224825b2c8faea2bc43ad" + integrity sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-64@0.1.0, base-64@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb" + integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA== + +base-64@1.0.0, base-64@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a" + integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg== + +base-x@^3.0.2: + version "3.0.11" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.11.tgz#40d80e2a1aeacba29792ccc6c5354806421287ff" + integrity sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA== + dependencies: + safe-buffer "^5.0.1" + +base-x@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.1.tgz#817fb7b57143c501f649805cb247617ad016a885" + integrity sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw== + +base-x@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.1.tgz#16bf35254be1df8aca15e36b7c1dda74b2aa6b03" + integrity sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg== + +base64-js@^1.2.3, base64-js@^1.3.0, base64-js@^1.3.1, base64-js@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +baseline-browser-mapping@^2.8.25: + version "2.8.26" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.26.tgz#2c7e2f840f0ae4d83782bdfe795229a43dfc3e59" + integrity sha512-73lC1ugzwoaWCLJ1LvOgrR5xsMLTqSKIEoMHVtL9E/HNk0PXtTM76ZIm84856/SF7Nv8mPZxKoBsgpm0tR1u1Q== + +baseline-browser-mapping@^2.9.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz#5b09935025bf8a80e29130251e337c6a7fc8cbb9" + integrity sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA== + +before-after-hook@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-4.0.0.tgz#cf1447ab9160df6a40f3621da64d6ffc36050cb9" + integrity sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ== + +better-opn@^3.0.2, better-opn@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817" + integrity sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ== + dependencies: + open "^8.0.4" + +big-integer@1.6.x: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + +big.js@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.2.2.tgz#be3bb9ac834558b53b099deef2a1d06ac6368e1a" + integrity sha512-y/ie+Faknx7sZA5MfGA2xKlu0GDv8RWrXGsmlteyJQ2lvoKv9GBK/fpRMc2qlSoBAgNxrixICFCBefIq8WCQpQ== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bip39@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" + integrity sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A== + dependencies: + "@noble/hashes" "^1.2.0" + +bl@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bn.js@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +bn.js@^4.11.9: + version "4.12.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.2.tgz#3d8fed6796c24e177737f7cc5172ee04ef39ec99" + integrity sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw== + +bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" + integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== + +body-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa" + integrity sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg== + dependencies: + bytes "^3.1.2" + content-type "^1.0.5" + debug "^4.4.0" + http-errors "^2.0.0" + iconv-lite "^0.6.3" + on-finished "^2.4.1" + qs "^6.14.0" + raw-body "^3.0.0" + type-is "^2.0.0" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +borsh@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" + integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== + dependencies: + bn.js "^5.2.0" + bs58 "^4.0.0" + text-encoding-utf-8 "^1.0.2" + +bowser@^2.9.0: + version "2.14.1" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.14.1.tgz#4ea39bf31e305184522d7ad7bfd91389e4f0cb79" + integrity sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg== + +bplist-creator@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/bplist-creator/-/bplist-creator-0.1.0.tgz#018a2d1b587f769e379ef5519103730f8963ba1e" + integrity sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg== + dependencies: + stream-buffers "2.2.x" + +bplist-parser@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.1.tgz#e1c90b2ca2a9f9474cc72f6862bbf3fee8341fd1" + integrity sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA== + dependencies: + big-integer "1.6.x" + +bplist-parser@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.2.tgz#3ac79d67ec52c4c107893e0237eb787cbacbced7" + integrity sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ== + dependencies: + big-integer "1.6.x" + +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browserslist@^4.20.4, browserslist@^4.24.0, browserslist@^4.25.0, browserslist@^4.26.3: + version "4.28.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.0.tgz#9cefece0a386a17a3cd3d22ebf67b9deca1b5929" + integrity sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ== + dependencies: + baseline-browser-mapping "^2.8.25" + caniuse-lite "^1.0.30001754" + electron-to-chromium "^1.5.249" + node-releases "^2.0.27" + update-browserslist-db "^1.1.4" + +browserslist@^4.28.1: + version "4.28.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" + integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== + dependencies: + baseline-browser-mapping "^2.9.0" + caniuse-lite "^1.0.30001759" + electron-to-chromium "^1.5.263" + node-releases "^2.0.27" + update-browserslist-db "^1.2.0" + +bs-logger@0.x, bs-logger@^0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bs58@6.0.0, bs58@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" + integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw== + dependencies: + base-x "^5.0.0" + +bs58@^4.0.0, bs58@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== + dependencies: + base-x "^3.0.2" + +bs58@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" + integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== + dependencies: + base-x "^4.0.0" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-equal-constant-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +buffer@^5.2.1, buffer@^5.4.3: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bufferutil@^4.0.1: + version "4.0.9" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.9.tgz#6e81739ad48a95cad45a279588e13e95e24a800a" + integrity sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw== + dependencies: + node-gyp-build "^4.3.0" + +bufferutil@^4.0.8: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.1.0.tgz#a4623541dd23867626bb08a051ec0d2ec0b70294" + integrity sha512-ZMANVnAixE6AWWnPzlW2KpUrxhm9woycYvPOo67jWHyFowASTEd9s+QN1EIMsSDtwhIxN4sWE1jotpuDUIgyIw== + dependencies: + node-gyp-build "^4.3.0" + +busboy@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +bytes@3.1.2, bytes@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" + get-intrinsic "^1.2.4" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3, call-bound@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ== + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A== + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ== + +callsites@^3.0.0, callsites@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0, camelcase@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +camelize@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" + integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== + +caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001754: + version "1.0.30001754" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz#7758299d9a72cce4e6b038788a15b12b44002759" + integrity sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg== + +caniuse-lite@^1.0.30001759, caniuse-lite@^1.0.30001774: + version "1.0.30001775" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz#9572266e3f7f77efee5deac1efeb4795879d1b7f" + integrity sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A== + +"cbw-sdk@npm:@coinbase/wallet-sdk@3.9.3": + version "3.9.3" + resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.9.3.tgz#daf10cb0c85d0363315b7270cb3f02bedc408aab" + integrity sha512-N/A2DRIf0Y3PHc1XAMvbBUu4zisna6qAdqABMZwBMNEfWrXpAwx16pZGkYCLGE+Rvv1edbcB2LYDRnACNcmCiw== + dependencies: + bn.js "^5.2.1" + buffer "^6.0.3" + clsx "^1.2.1" + eth-block-tracker "^7.1.0" + eth-json-rpc-filters "^6.0.0" + eventemitter3 "^5.0.1" + keccak "^3.0.3" + preact "^10.16.0" + sha.js "^2.4.11" + +chai@^5.2.0: + version "5.3.3" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.3.3.tgz#dd3da955e270916a4bd3f625f4b919996ada7e06" + integrity sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + +chalk@5.6.2, chalk@^5.4.1: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + +chalk@^2.0.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +char-regex@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.2.tgz#81385bb071af4df774bff8721d0ca15ef29ea0bb" + integrity sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg== + +charenc@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== + +chart.js@^4.4.2: + version "4.5.1" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.5.1.tgz#19dd1a9a386a3f6397691672231cb5fc9c052c35" + integrity sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw== + dependencies: + "@kurkle/color" "^0.3.0" + +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + +chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-5.0.0.tgz#949c126a9238a80792be9a0265934f098af369a5" + integrity sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw== + dependencies: + readdirp "^5.0.0" + +chownr@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" + integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + +chrome-launcher@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.15.2.tgz#4e6404e32200095fdce7f6a1e1004f9bd36fa5da" + integrity sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + +chromium-edge-launcher@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/chromium-edge-launcher/-/chromium-edge-launcher-0.2.0.tgz#0c378f28c99aefc360705fa155de0113997f62fc" + integrity sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg== + dependencies: + "@types/node" "*" + escape-string-regexp "^4.0.0" + is-wsl "^2.2.0" + lighthouse-logger "^1.0.0" + mkdirp "^1.0.4" + rimraf "^3.0.2" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0, ci-info@^3.3.0, ci-info@^3.7.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +ci-info@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.3.1.tgz#355ad571920810b5623e11d40232f443f16f1daa" + integrity sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA== + +cjs-module-lexer@^1.0.0: + version "1.4.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" + integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== + +cjs-module-lexer@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.1.1.tgz#bff23b0609cc9afa428bd35f1918f7d03b448562" + integrity sha512-+CmxIZ/L2vNcEfvNtLdU0ZQ6mbq3FZnwAP2PPTiKP+1QOoKwlKlPgb8UKV0Dds7QVaMnHm+FwSft2VB0s/SLjQ== + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw== + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^2.0.0: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + +client-only@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +clsx@1.2.1, clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + +clsx@^2.0.0, clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +codemirror@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.2.tgz#4d3fea1ad60b6753f97ca835f2f48c6936a8946e" + integrity sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/commands" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/search" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + +collect-v8-coverage@^1.0.0, collect-v8-coverage@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz#cc1f01eb8d02298cbc9a437c74c70ab4e5210b80" + integrity sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color2k@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/color2k/-/color2k-2.0.3.tgz#a771244f6b6285541c82aa65ff0a0c624046e533" + integrity sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.1.tgz#2f9225c19e6ebd0dc4404dd45821b2caa17ea09b" + integrity sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A== + +commander@14.0.2, commander@^14.0.0: + version "14.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.2.tgz#b71fd37fe4069e4c3c7c13925252ada4eba14e8e" + integrity sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ== + +commander@^12.0.0, commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + +commander@^13.1.0: + version "13.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" + integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== + +commander@^2.20.0, commander@^2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +commander@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + +commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^8.2.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +compressible@~2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.8.1" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.1.tgz#4a45d909ac16509195a9a28bd91094889c180d79" + integrity sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w== + dependencies: + bytes "3.1.2" + compressible "~2.0.18" + debug "2.6.9" + negotiator "~0.6.4" + on-headers "~1.1.0" + safe-buffer "5.2.1" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +connect@^3.6.5, connect@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" + integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== + dependencies: + debug "2.6.9" + finalhandler "1.1.2" + parseurl "~1.3.3" + utils-merge "1.0.1" + +consumable-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/consumable-stream/-/consumable-stream-2.0.0.tgz#11d3c7281b747eb9efd31c199b3a8b1711bec654" + integrity sha512-I6WA2JVYXs/68rEvi1ie3rZjP6qusTVFEQkbzR+WC+fY56TpwiGTIDJETsrnlxv5CsnmK69ps6CkYvIbpEEqBA== + +consumable-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/consumable-stream/-/consumable-stream-3.0.0.tgz#2bf140e0c5f9b63d6fa116ac6b05e53713d3cb41" + integrity sha512-CnnsJ9OG9ouxAjt3pc63/DaerezRo/WudqU71pc5epaIUi7NHu2T4v+3f0nKbbCY7icS/TfQ1Satr9rwZ7Jwsg== + +content-disposition@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.0.tgz#844426cb398f934caefcbb172200126bc7ceace2" + integrity sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg== + dependencies: + safe-buffer "5.2.1" + +content-type@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +convert-source-map@^1.5.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cookie-es@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.2.2.tgz#18ceef9eb513cac1cb6c14bcbf8bdb2679b34821" + integrity sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg== + +cookie-signature@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" + integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== + +cookie@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== + +copy-to-clipboard@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" + integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== + dependencies: + toggle-selection "^1.0.6" + +core-js-compat@^3.43.0: + version "3.46.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.46.0.tgz#0c87126a19a1af00371e12b02a2b088a40f3c6f7" + integrity sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law== + dependencies: + browserslist "^4.26.3" + +core-js@^3.38.1: + version "3.46.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.46.0.tgz#323a092b96381a9184d0cd49ee9083b2f93373bb" + integrity sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cosmiconfig@^5.0.5: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cosmiconfig@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +cosmiconfig@^8.1.3: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + +cosmiconfig@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== + dependencies: + env-paths "^2.2.1" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +crelt@^1.0.5, crelt@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" + integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g== + +cross-fetch@^3.1.4, cross-fetch@^3.1.5: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.2.0.tgz#34e9192f53bc757d6614304d9e5e6fb4edb782e3" + integrity sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q== + dependencies: + node-fetch "^2.7.0" + +cross-fetch@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.1.0.tgz#8f69355007ee182e47fa692ecbaa37a52e43c3d2" + integrity sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw== + dependencies: + node-fetch "^2.7.0" + +cross-spawn@^7.0.0, cross-spawn@^7.0.3, cross-spawn@^7.0.5, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crossws@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/crossws/-/crossws-0.3.5.tgz#daad331d44148ea6500098bc858869f3a5ab81a6" + integrity sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA== + dependencies: + uncrypto "^0.1.3" + +crypt@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + integrity sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg== + +css-in-js-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz#640ae6a33646d401fc720c54fc61c42cd76ae2bb" + integrity sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A== + dependencies: + hyphenate-style-name "^1.0.3" + +css-select@^5.1.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.2.2.tgz#01b6e8d163637bb2dd6c982ca4ed65863682786e" + integrity sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-to-react-native@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.2.0.tgz#cdd8099f71024e149e4f6fe17a7d46ecd55f1e32" + integrity sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + +css-tree@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" + integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== + dependencies: + mdn-data "2.0.14" + source-map "^0.6.1" + +css-tree@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.3.1.tgz#10264ce1e5442e8572fc82fbe490644ff54b5c20" + integrity sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw== + dependencies: + mdn-data "2.0.30" + source-map-js "^1.0.1" + +css-tree@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-2.2.1.tgz#36115d382d60afd271e377f9c5f67d02bd48c032" + integrity sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA== + dependencies: + mdn-data "2.0.28" + source-map-js "^1.0.1" + +css-what@^6.1.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.2.2.tgz#cdcc8f9b6977719fdfbd1de7aec24abf756b9dea" + integrity sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA== + +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csso@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/csso/-/csso-5.0.5.tgz#f9b7fe6cc6ac0b7d90781bb16d5e9874303e2ca6" + integrity sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ== + dependencies: + css-tree "~2.2.0" + +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +csstype@^3.0.2, csstype@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +damerau-levenshtein@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== + +data-urls@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== + dependencies: + abab "^2.0.6" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-data-view "^1.0.2" + +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +date-fns@^2.29.3: + version "2.30.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0" + integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw== + dependencies: + "@babel/runtime" "^7.21.0" + +dayjs@1.11.13: + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + +debug@2.6.9, debug@^2.2.0, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.4.0, debug@^4.4.1, debug@~4.4.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +debug@4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^3.1.0, debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decimal.js@^10.4.2, decimal.js@^10.4.3: + version "10.6.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== + +decode-uri-component@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" + integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + +dedent@^1.0.0, dedent@^1.5.1, dedent@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.0.tgz#c1f9445335f0175a96587be245a282ff451446ca" + integrity sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ== + +deep-diff@^0.3.5: + version "0.3.8" + resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84" + integrity sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug== + +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + +deep-equal@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.2.tgz#78a561b7830eef3134c7f6f3a3d6af272a678761" + integrity sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg== + dependencies: + is-arguments "^1.1.1" + is-date-object "^1.0.5" + is-regex "^1.1.4" + object-is "^1.1.5" + object-keys "^1.1.1" + regexp.prototype.flags "^1.5.1" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@4.3.1, deepmerge@^4.2.2, deepmerge@^4.3.0, deepmerge@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.3, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +defu@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" + integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== + +del@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" + integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" + +delay@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" + integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +denodeify@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631" + integrity sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg== + +depd@2.0.0, depd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +derive-valtio@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/derive-valtio/-/derive-valtio-0.1.0.tgz#4b9fb393dfefccfef15fcbbddd745dd22d5d63d7" + integrity sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A== + +destr@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.5.tgz#7d112ff1b925fb8d2079fac5bdb4a90973b51fdb" + integrity sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-browser@5.3.0, detect-browser@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" + integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== + +detect-europe-js@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/detect-europe-js/-/detect-europe-js-0.1.2.tgz#aa76642e05dae786efc2e01a23d4792cd24c7b88" + integrity sha512-lgdERlL3u0aUdHocoouzT10d9I89VVhk0qNRmll7mXdGfJT1/wqZ2ZLA4oJAjeACPY5fT1wsbq2AT+GkuInsow== + +detect-libc@^2.0.3, detect-libc@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + +detect-newline@^3.0.0, detect-newline@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + +didyoumean@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" + integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +dijkstrajs@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" + integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dlv@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" + integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-accessibility-api@^0.5.9: + version "0.5.16" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== + +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + +dom-helpers@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" + integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== + dependencies: + "@babel/runtime" "^7.8.7" + csstype "^3.0.2" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== + dependencies: + webidl-conversions "^7.0.0" + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^3.0.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78" + integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dotenv-expand@~11.0.6: + version "11.0.7" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-11.0.7.tgz#af695aea007d6fdc84c86cd8d0ad7beb40a0bd08" + integrity sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA== + dependencies: + dotenv "^16.4.5" + +dotenv@^16.4.5: + version "16.6.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" + integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== + +dotenv@~16.4.5: + version "16.4.7" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" + integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + +duplexify@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +eciesjs@^0.4.11: + version "0.4.17" + resolved "https://registry.yarnpkg.com/eciesjs/-/eciesjs-0.4.17.tgz#5aca58bf8c794ec6cf971ce51b10c8d21292189a" + integrity sha512-TOOURki4G7sD1wDCjj7NfLaXZZ49dFOeEb5y39IXpb8p0hRzVvfvzZHOi5JcT+PpyAbi/Y+lxPb8eTag2WYH8w== + dependencies: + "@ecies/ciphers" "^0.2.5" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "^1.9.7" + "@noble/hashes" "^1.8.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.5.249: + version "1.5.250" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.250.tgz#0b40436fa41ae7cbac3d2f60ef0411a698eb72a7" + integrity sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw== + +electron-to-chromium@^1.5.263: + version "1.5.302" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz#032a5802b31f7119269959c69fe2015d8dad5edb" + integrity sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg== + +elliptic@6.6.1, elliptic@^6.5.4, elliptic@^6.5.7: + version "6.6.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" + integrity sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encode-utf8@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + +encodeurl@^2.0.0, encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + +engine.io-client@~6.6.1: + version "6.6.4" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.6.4.tgz#a04998787dd342b543eec5d4452da7bb540e7ff8" + integrity sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.4.1" + engine.io-parser "~5.2.1" + ws "~8.18.3" + xmlhttprequest-ssl "~2.1.1" + +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + +enhanced-resolve@^5.17.1: + version "5.18.3" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz#9b5f4c5c076b8787c78fe540392ce76a88855b44" + integrity sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +entities@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" + integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== + +entities@~2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== + +env-editor@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/env-editor/-/env-editor-0.4.2.tgz#4e76568d0bd8f5c2b6d314a9412c8fe9aa3ae861" + integrity sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA== + +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +error-ex@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + +es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9, es-abstract@^1.24.0: + version "1.24.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.24.0.tgz#c44732d2beb0acc1ed60df840869e3106e7af328" + integrity sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg== + dependencies: + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.3.0" + get-proto "^1.0.1" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" + is-callable "^1.2.7" + is-data-view "^1.0.2" + is-negative-zero "^2.0.3" + is-regex "^1.2.1" + is-set "^2.0.3" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.1" + math-intrinsics "^1.1.0" + object-inspect "^1.13.4" + object-keys "^1.1.1" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.4" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.0" + stop-iteration-iterator "^1.1.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.19" + +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-iterator-helpers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" + integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.6" + globalthis "^1.0.4" + gopd "^1.2.0" + has-property-descriptors "^1.0.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + iterator.prototype "^1.1.4" + safe-array-concat "^1.1.3" + +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +es-shim-unscopables@^1.0.2, es-shim-unscopables@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" + integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== + dependencies: + hasown "^2.0.2" + +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== + dependencies: + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" + +es-toolkit@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.33.0.tgz#bcc9d92ef2e1ed4618c00dd30dfda9faddf4a0b7" + integrity sha512-X13Q/ZSc+vsO1q600bvNK4bxgXMkHcf//RxCmYDaRY5DAcT+eoXjY5hoAPGMdRnWQjvyLEcyauG3b6hz76LNqg== + +es-toolkit@^1.38.0: + version "1.41.0" + resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.41.0.tgz#84eacd54dcc88261d78005fde7a01c2291b90628" + integrity sha512-bDd3oRmbVgqZCJS6WmeQieOrzpl3URcWBUVDXxOELlUW2FuW+0glPOz1n0KnRie+PdyvUZcXz2sOn00c6pPRIA== + +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== + dependencies: + es6-promise "^4.0.3" + +esbuild-register@^3.5.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/esbuild-register/-/esbuild-register-3.6.0.tgz#cf270cfa677baebbc0010ac024b823cbf723a36d" + integrity sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg== + dependencies: + debug "^4.3.4" + +"esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", esbuild@~0.25.0: + version "0.25.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.12.tgz#97a1d041f4ab00c2fce2f838d2b9969a2d2a97a5" + integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.12" + "@esbuild/android-arm" "0.25.12" + "@esbuild/android-arm64" "0.25.12" + "@esbuild/android-x64" "0.25.12" + "@esbuild/darwin-arm64" "0.25.12" + "@esbuild/darwin-x64" "0.25.12" + "@esbuild/freebsd-arm64" "0.25.12" + "@esbuild/freebsd-x64" "0.25.12" + "@esbuild/linux-arm" "0.25.12" + "@esbuild/linux-arm64" "0.25.12" + "@esbuild/linux-ia32" "0.25.12" + "@esbuild/linux-loong64" "0.25.12" + "@esbuild/linux-mips64el" "0.25.12" + "@esbuild/linux-ppc64" "0.25.12" + "@esbuild/linux-riscv64" "0.25.12" + "@esbuild/linux-s390x" "0.25.12" + "@esbuild/linux-x64" "0.25.12" + "@esbuild/netbsd-arm64" "0.25.12" + "@esbuild/netbsd-x64" "0.25.12" + "@esbuild/openbsd-arm64" "0.25.12" + "@esbuild/openbsd-x64" "0.25.12" + "@esbuild/openharmony-arm64" "0.25.12" + "@esbuild/sunos-x64" "0.25.12" + "@esbuild/win32-arm64" "0.25.12" + "@esbuild/win32-ia32" "0.25.12" + "@esbuild/win32-x64" "0.25.12" + +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-html@^1.0.3, escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + +eslint-compat-utils@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz#7fc92b776d185a70c4070d03fd26fde3d59652e4" + integrity sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q== + dependencies: + semver "^7.5.4" + +eslint-config-next@15.5.7: + version "15.5.7" + resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-15.5.7.tgz#c0e8cfab54bbc85a0e339a9747da69136c065b60" + integrity sha512-nU/TRGHHeG81NeLW5DeQT5t6BDUqbpsNQTvef1ld/tqHT+/zTx60/TIhKnmPISTTe++DVo+DLxDmk4rnwHaZVw== + dependencies: + "@next/eslint-plugin-next" "15.5.7" + "@rushstack/eslint-patch" "^1.10.3" + "@typescript-eslint/eslint-plugin" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" + eslint-import-resolver-node "^0.3.6" + eslint-import-resolver-typescript "^3.5.2" + eslint-plugin-import "^2.31.0" + eslint-plugin-jsx-a11y "^6.10.0" + eslint-plugin-react "^7.37.0" + eslint-plugin-react-hooks "^5.0.0" + +eslint-config-prettier@^9.1.0: + version "9.1.2" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz#90deb4fa0259592df774b600dbd1d2249a78ce91" + integrity sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ== + +eslint-config-standard@^17.1.0: + version "17.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz#40ffb8595d47a6b242e07cbfd49dc211ed128975" + integrity sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q== + +eslint-config-universe@^15.0.3: + version "15.0.3" + resolved "https://registry.yarnpkg.com/eslint-config-universe/-/eslint-config-universe-15.0.3.tgz#4a2c6099a028f86f863542c8e60ac36f504bbb11" + integrity sha512-fUMsNXp7GJBu7Sz9PXFBbXhkiixdQ5sbnViFIBbk6ORAfeokczJ+eVv5HQ2gwxPQdbfJarpkO9WZDtxIvJnEGw== + dependencies: + "@typescript-eslint/eslint-plugin" "^8.29.1" + "@typescript-eslint/parser" "^8.29.1" + eslint-config-prettier "^9.1.0" + eslint-plugin-import "^2.31.0" + eslint-plugin-n "^17.17.0" + eslint-plugin-node "^11.1.0" + eslint-plugin-prettier "^5.2.6" + eslint-plugin-react "^7.37.5" + eslint-plugin-react-hooks "^5.2.0" + globals "^16.0.0" + +eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-import-resolver-typescript@^3.5.2, eslint-import-resolver-typescript@^3.7.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz#23dac32efa86a88e2b8232eb244ac499ad636db2" + integrity sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ== + dependencies: + "@nolyfill/is-core-module" "1.0.39" + debug "^4.4.0" + get-tsconfig "^4.10.0" + is-bun-module "^2.0.0" + stable-hash "^0.0.5" + tinyglobby "^0.2.13" + unrs-resolver "^1.6.2" + +eslint-module-utils@^2.12.1: + version "2.12.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz#f76d3220bfb83c057651359295ab5854eaad75ff" + integrity sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw== + dependencies: + debug "^3.2.7" + +eslint-plugin-es-x@^7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz#a207aa08da37a7923f2a9599e6d3eb73f3f92b74" + integrity sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ== + dependencies: + "@eslint-community/eslint-utils" "^4.1.2" + "@eslint-community/regexpp" "^4.11.0" + eslint-compat-utils "^0.5.1" + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-import-x@4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import-x/-/eslint-plugin-import-x-4.6.1.tgz#2fdb9a25addd92247f5d9b198bfa654eeaea2f52" + integrity sha512-wluSUifMIb7UfwWXqx7Yx0lE/SGCcGXECLx/9bCmbY2nneLwvAZ4vkd1IXDjPKFvdcdUgr1BaRnaRpx3k2+Pfw== + dependencies: + "@types/doctrine" "^0.0.9" + "@typescript-eslint/scope-manager" "^8.1.0" + "@typescript-eslint/utils" "^8.1.0" + debug "^4.3.4" + doctrine "^3.0.0" + enhanced-resolve "^5.17.1" + eslint-import-resolver-node "^0.3.9" + get-tsconfig "^4.7.3" + is-glob "^4.0.3" + minimatch "^9.0.3" + semver "^7.6.3" + stable-hash "^0.0.4" + tslib "^2.6.3" + +eslint-plugin-import@^2.31.0: + version "2.32.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz#602b55faa6e4caeaa5e970c198b5c00a37708980" + integrity sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA== + dependencies: + "@rtsao/scc" "^1.1.0" + array-includes "^3.1.9" + array.prototype.findlastindex "^1.2.6" + array.prototype.flat "^1.3.3" + array.prototype.flatmap "^1.3.3" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.12.1" + hasown "^2.0.2" + is-core-module "^2.16.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + object.groupby "^1.0.3" + object.values "^1.2.1" + semver "^6.3.1" + string.prototype.trimend "^1.0.9" + tsconfig-paths "^3.15.0" + +eslint-plugin-jest@^28.11.0: + version "28.14.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.14.0.tgz#02da77dc27d7b4c5480df3552ea26de056857b36" + integrity sha512-P9s/qXSMTpRTerE2FQ0qJet2gKbcGyFTPAJipoKxmWqR6uuFqIqk8FuEfg5yBieOezVrEfAMZrEwJ6yEp+1MFQ== + dependencies: + "@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0" + +eslint-plugin-jsx-a11y@^6.10.0: + version "6.10.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz#d2812bb23bf1ab4665f1718ea442e8372e638483" + integrity sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q== + dependencies: + aria-query "^5.3.2" + array-includes "^3.1.8" + array.prototype.flatmap "^1.3.2" + ast-types-flow "^0.0.8" + axe-core "^4.10.0" + axobject-query "^4.1.0" + damerau-levenshtein "^1.0.8" + emoji-regex "^9.2.2" + hasown "^2.0.2" + jsx-ast-utils "^3.3.5" + language-tags "^1.0.9" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + safe-regex-test "^1.0.3" + string.prototype.includes "^2.0.1" + +eslint-plugin-n@^17.15.1, eslint-plugin-n@^17.17.0: + version "17.23.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-17.23.1.tgz#467db2aba0ead574ea6150143d079d544c11cf48" + integrity sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A== + dependencies: + "@eslint-community/eslint-utils" "^4.5.0" + enhanced-resolve "^5.17.1" + eslint-plugin-es-x "^7.8.0" + get-tsconfig "^4.8.1" + globals "^15.11.0" + globrex "^0.1.2" + ignore "^5.3.2" + semver "^7.6.3" + ts-declaration-location "^1.0.6" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-prettier@^5.2.1, eslint-plugin-prettier@^5.2.6: + version "5.5.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz#9d61c4ea11de5af704d4edf108c82ccfa7f2e61c" + integrity sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.11.7" + +eslint-plugin-promise@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz#a0652195700aea40b926dc3c74b38e373377bfb0" + integrity sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + +eslint-plugin-react-hooks@^5.0.0, eslint-plugin-react-hooks@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz#1be0080901e6ac31ce7971beed3d3ec0a423d9e3" + integrity sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg== + +eslint-plugin-react@^7.37.0, eslint-plugin-react@^7.37.5: + version "7.37.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz#2975511472bdda1b272b34d779335c9b0e877065" + integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA== + dependencies: + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.3" + array.prototype.tosorted "^1.1.4" + doctrine "^2.1.0" + es-iterator-helpers "^1.2.1" + estraverse "^5.3.0" + hasown "^2.0.2" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.9" + object.fromentries "^2.0.8" + object.values "^1.2.1" + prop-types "^15.8.1" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.12" + string.prototype.repeat "^1.0.0" + +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + +eslint@^9.18.0, eslint@^9.31.0: + version "9.39.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.1.tgz#be8bf7c6de77dcc4252b5a8dcb31c2efff74a6e5" + integrity sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.1" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.39.1" + "@eslint/plugin-kit" "^0.4.1" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + +esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@^1.8.1, etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eth-block-tracker@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-7.1.0.tgz#dfc16085c6817cc30caabba381deb8d204c1c766" + integrity sha512-8YdplnuE1IK4xfqpf4iU7oBxnOYAc35934o083G8ao+8WM8QQtt/mVlAY6yIAdY1eMeLqg4Z//PZjJGmWGPMRg== + dependencies: + "@metamask/eth-json-rpc-provider" "^1.0.0" + "@metamask/safe-event-emitter" "^3.0.0" + "@metamask/utils" "^5.0.1" + json-rpc-random-id "^1.0.1" + pify "^3.0.0" + +eth-json-rpc-filters@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-6.0.1.tgz#0b3e370f017f5c6f58d3e7bd0756d8099ed85c56" + integrity sha512-ITJTvqoCw6OVMLs7pI8f4gG92n/St6x80ACtHodeS+IXmO0w+t1T5OOzfSt7KLSMLRkVUoexV7tztLgDxg+iig== + dependencies: + "@metamask/safe-event-emitter" "^3.0.0" + async-mutex "^0.2.6" + eth-query "^2.1.2" + json-rpc-engine "^6.1.0" + pify "^5.0.0" + +eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha512-srES0ZcvwkR/wd5OQBRA1bIJMww1skfGS0s8wlwK3/oNP4+wnds60krvu5R1QbpRQjMmpG5OMIWro5s7gvDPsA== + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-rpc-errors@4.0.3, eth-rpc-errors@^4.0.2, eth-rpc-errors@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.3.tgz#6ddb6190a4bf360afda82790bb7d9d5e724f423a" + integrity sha512-Z3ymjopaoft7JDoxZcEb3pwdGh7yiYMhOwm2doUt6ASXlMavpNlK6Cre0+IMl2VSGyEU9rkiperQhp5iRxn5Pg== + dependencies: + fast-safe-stringify "^2.0.6" + +ethereum-cryptography@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== + dependencies: + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" + +ethers@^6, ethers@^6.13.1: + version "6.15.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.15.0.tgz#2980f2a3baf0509749b7e21f8692fa8a8349c0e3" + integrity sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ== + dependencies: + "@adraffy/ens-normalize" "1.10.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@types/node" "22.7.5" + aes-js "4.0.0-beta.5" + tslib "2.7.0" + ws "8.17.1" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter2@^6.4.9: + version "6.4.9" + resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.9.tgz#41f2750781b4230ed58827bc119d293471ecb125" + integrity sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg== + +eventemitter3@5.0.1, eventemitter3@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +eventemitter3@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@3.3.0, events@^3.0.0, events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +eventsource-parser@^3.0.0, eventsource-parser@^3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.6.tgz#292e165e34cacbc936c3c92719ef326d4aeb4e90" + integrity sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg== + +eventsource@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.7.tgz#1157622e2f5377bb6aef2114372728ba0c156989" + integrity sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA== + dependencies: + eventsource-parser "^3.0.1" + +exec-async@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/exec-async/-/exec-async-2.2.0.tgz#c7c5ad2eef3478d38390c6dd3acfe8af0efc8301" + integrity sha512-87OpwcEiMia/DeiKFzaQNBNFeN3XkkpYIh9FyOqq5mS2oKv3CBE67PXoEKcr6nodWdXNogTiQ0jE2NGuoffXPw== + +execa@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +execa@^5.0.0, execa@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit-x@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/exit-x/-/exit-x-0.2.2.tgz#1f9052de3b8d99a696b10dad5bced9bdd5c3aa64" + integrity sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ== + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@30.2.0, expect@^30.0.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-30.2.0.tgz#d4013bed267013c14bc1199cec8aa57cee9b5869" + integrity sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw== + dependencies: + "@jest/expect-utils" "30.2.0" + "@jest/get-type" "30.1.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-util "30.2.0" + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +expo-application@~7.0.7: + version "7.0.7" + resolved "https://registry.yarnpkg.com/expo-application/-/expo-application-7.0.7.tgz#8b2802650381042baa3b74297cdeb5f9628b7c6c" + integrity sha512-Jt1/qqnoDUbZ+bK91+dHaZ1vrPDtRBOltRa681EeedkisqguuEeUx4UHqwVyDK2oHWsK6lO3ojetoA4h8OmNcg== + +expo-asset@~12.0.9: + version "12.0.9" + resolved "https://registry.yarnpkg.com/expo-asset/-/expo-asset-12.0.9.tgz#e5b06b793bfc45a76b70a2253862351effa42e73" + integrity sha512-vrdRoyhGhBmd0nJcssTSk1Ypx3Mbn/eXaaBCQVkL0MJ8IOZpAObAjfD5CTy8+8RofcHEQdh3wwZVCs7crvfOeg== + dependencies: + "@expo/image-utils" "^0.8.7" + expo-constants "~18.0.9" + +expo-auth-session@~7.0.8: + version "7.0.8" + resolved "https://registry.yarnpkg.com/expo-auth-session/-/expo-auth-session-7.0.8.tgz#a6b82c7e0bf2ac18e56d815c7d84c0d86fa8477b" + integrity sha512-kpo2Jva+6uVjk6TmNqWAoqTnULXZaEVa9l4uf8JH32uDMt/iZQhM0fauy7Ww+y910Euhv5djCP7cPj8KWv6cmQ== + dependencies: + expo-application "~7.0.7" + expo-constants "~18.0.8" + expo-crypto "~15.0.7" + expo-linking "~8.0.8" + expo-web-browser "~15.0.7" + invariant "^2.2.4" + +expo-background-fetch@~14.0.7: + version "14.0.7" + resolved "https://registry.yarnpkg.com/expo-background-fetch/-/expo-background-fetch-14.0.7.tgz#20888ae997ce9d62896370b8a01a4f28d1dd625c" + integrity sha512-vq/2w/I9OYkYbKn2YmMTzWEZm+Ddl8ObRtKR8s5kpfyGEIHz4rsIuHF1kpqHXuxI/DNZEhAN8fIO2nh+jNW5uQ== + dependencies: + expo-task-manager "~14.0.7" + +expo-build-properties@~1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/expo-build-properties/-/expo-build-properties-1.0.9.tgz#71f0ce813a8431937a3db25a91f1bb4b1a6214ae" + integrity sha512-2icttCy3OPTk/GWIFt+vwA+0hup53jnmYb7JKRbvNvrrOrz+WblzpeoiaOleI2dYG/vjwpNO8to8qVyKhYJtrQ== + dependencies: + ajv "^8.11.0" + semver "^7.6.0" + +expo-camera@~17.0.9: + version "17.0.9" + resolved "https://registry.yarnpkg.com/expo-camera/-/expo-camera-17.0.9.tgz#4447e63960c9b4485869e2f1fac0ef083c38669a" + integrity sha512-KgticPGurqEsaPBIwbG0T6mzAVnqZasDdM/6OoJt5zPh6tWB09+th6cBF1WafIBMPy8AWbfyUQSqQXqOrNJClg== + dependencies: + invariant "^2.2.4" + +expo-clipboard@~8.0.7: + version "8.0.7" + resolved "https://registry.yarnpkg.com/expo-clipboard/-/expo-clipboard-8.0.7.tgz#f81d279036408bbe074ef748623e1ae6f170d391" + integrity sha512-zvlfFV+wB2QQrQnHWlo0EKHAkdi2tycLtE+EXFUWTPZYkgu1XcH+aiKfd4ul7Z0SDF+1IuwoiW9AA9eO35aj3Q== + +expo-constants@~18.0.10, expo-constants@~18.0.8, expo-constants@~18.0.9: + version "18.0.10" + resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-18.0.10.tgz#92d4490d51193fc94bd40590453ce9cab4faf6fb" + integrity sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw== + dependencies: + "@expo/config" "~12.0.10" + "@expo/env" "~2.0.7" + +expo-crypto@~15.0.7: + version "15.0.7" + resolved "https://registry.yarnpkg.com/expo-crypto/-/expo-crypto-15.0.7.tgz#0d06a621ddbcfdcfbcb9961462ee227b52a4f73b" + integrity sha512-FUo41TwwGT2e5rA45PsjezI868Ch3M6wbCZsmqTWdF/hr+HyPcrp1L//dsh/hsrsyrQdpY/U96Lu71/wXePJeg== + dependencies: + base64-js "^1.3.0" + +expo-dev-client@~6.0.17: + version "6.0.17" + resolved "https://registry.yarnpkg.com/expo-dev-client/-/expo-dev-client-6.0.17.tgz#f1157bb2c2389c8f59f673d259aaa01cf25ec99d" + integrity sha512-zVilIum3sqXFbhYhPT6TuxR3ddH/IfHL82FiOTqJUiYaTQqun1I6ogSvU1djhY1eXUYhfYIBieQNWMVjXPxMvw== + dependencies: + expo-dev-launcher "6.0.17" + expo-dev-menu "7.0.16" + expo-dev-menu-interface "2.0.0" + expo-manifests "~1.0.8" + expo-updates-interface "~2.0.0" + +expo-dev-launcher@6.0.17: + version "6.0.17" + resolved "https://registry.yarnpkg.com/expo-dev-launcher/-/expo-dev-launcher-6.0.17.tgz#d7f39a4fd4738e171c4422c1ddc256844699c2a0" + integrity sha512-riLxFXaw6Nvgb27TiQtUvoHkW/zTz0aO7M+qxDBBaEbJMJSFl51KSwOJJBTItVQIE9f9jB8x5L1CfLw81/McZw== + dependencies: + expo-dev-menu "7.0.16" + expo-manifests "~1.0.8" + +expo-dev-menu-interface@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/expo-dev-menu-interface/-/expo-dev-menu-interface-2.0.0.tgz#c0d6db65eb4abc44a2701bc2303744619ad05ca6" + integrity sha512-BvAMPt6x+vyXpThsyjjOYyjwfjREV4OOpQkZ0tNl+nGpsPfcY9mc6DRACoWnH9KpLzyIt3BOgh3cuy/h/OxQjw== + +expo-dev-menu@7.0.16: + version "7.0.16" + resolved "https://registry.yarnpkg.com/expo-dev-menu/-/expo-dev-menu-7.0.16.tgz#1c2f91caca14c22341525e7ac72cf4b33dcf727d" + integrity sha512-/kjTjk5tcZV0ixYnV3JyzPXKlMimpBNYaDo4XxBbRFIkTf/vmb/9e1BTR2nALnoa/D3MRwtR43gZYT+W/wfKXw== + dependencies: + expo-dev-menu-interface "2.0.0" + +expo-device@~8.0.9: + version "8.0.9" + resolved "https://registry.yarnpkg.com/expo-device/-/expo-device-8.0.9.tgz#def4fcc2f2bd99c2f009424610c298acc1c01eb6" + integrity sha512-XqRpaljDNAYZGZzMpC+b9KZfzfydtkwx3pJAp6ODDH+O/5wjAw+mLc5wQMGJCx8/aqVmMsAokec7iebxDPFZDA== + dependencies: + ua-parser-js "^0.7.33" + +expo-eas-client@~1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/expo-eas-client/-/expo-eas-client-1.0.7.tgz#9c9c7909d7bb9b6ceb4bef6875f1b9119ef22a8c" + integrity sha512-Q/b1X0fM+3beqqvffok14pjxMF600NxopdSr9WJY61fF4xllcVnALS0kEudffp9ihMOfcb5xWYqzKj6jMqYDIw== + +expo-file-system@~19.0.17: + version "19.0.17" + resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-19.0.17.tgz#2555c05c26a19038d005f281b11dbda9722d0c0d" + integrity sha512-WwaS01SUFrxBnExn87pg0sCTJjZpf2KAOzfImG0o8yhkU7fbYpihpl/oocXBEsNbj58a8hVt1Y4CVV5c1tzu/g== + +expo-font@~14.0.9: + version "14.0.9" + resolved "https://registry.yarnpkg.com/expo-font/-/expo-font-14.0.9.tgz#552d66afc8c6efa8839f5f4063c2e0226b3edad1" + integrity sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg== + dependencies: + fontfaceobserver "^2.1.0" + +expo-image-loader@~6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/expo-image-loader/-/expo-image-loader-6.0.0.tgz#15230442cbb90e101c080a4c81e37d974e43e072" + integrity sha512-nKs/xnOGw6ACb4g26xceBD57FKLFkSwEUTDXEDF3Gtcu3MqF3ZIYd3YM+sSb1/z9AKV1dYT7rMSGVNgsveXLIQ== + +expo-image-picker@~17.0.8: + version "17.0.8" + resolved "https://registry.yarnpkg.com/expo-image-picker/-/expo-image-picker-17.0.8.tgz#c4430994de81f3e9995c9ce77cb76403213b17d7" + integrity sha512-489ByhVs2XPoAu9zodivAKLv7hG4S/FOe8hO/C2U6jVxmRjpAKakKNjMml0IwWjf1+c/RYBqm1XxKaZ+vq/fDQ== + dependencies: + expo-image-loader "~6.0.0" + +expo-json-utils@~0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-0.15.0.tgz#6723574814b9e6b0a90e4e23662be76123ab6ae9" + integrity sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ== + +expo-keep-awake@~15.0.7: + version "15.0.7" + resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-15.0.7.tgz#4eada556e1cca6c9c2e5aa39478fd01816cd0bc9" + integrity sha512-CgBNcWVPnrIVII5G54QDqoE125l+zmqR4HR8q+MQaCfHet+dYpS5vX5zii/RMayzGN4jPgA4XYIQ28ePKFjHoA== + +expo-linking@~8.0.8: + version "8.0.8" + resolved "https://registry.yarnpkg.com/expo-linking/-/expo-linking-8.0.8.tgz#ad348c133d048043990177f67dfb6a89bf628a6e" + integrity sha512-MyeMcbFDKhXh4sDD1EHwd0uxFQNAc6VCrwBkNvvvufUsTYFq3glTA9Y8a+x78CPpjNqwNAamu74yIaIz7IEJyg== + dependencies: + expo-constants "~18.0.8" + invariant "^2.2.4" + +expo-local-authentication@~17.0.7: + version "17.0.7" + resolved "https://registry.yarnpkg.com/expo-local-authentication/-/expo-local-authentication-17.0.7.tgz#799239fc817cf8a16ea047c96425ff05ed1e502a" + integrity sha512-yRWcgYn/OIwxEDEk7cM7tRjQSHaTp5hpKwzq+g9NmSMJ1etzUzt0yGzkDiOjObj3YqFo0ucyDJ8WfanLhZDtMw== + dependencies: + invariant "^2.2.4" + +expo-localization@~17.0.7: + version "17.0.7" + resolved "https://registry.yarnpkg.com/expo-localization/-/expo-localization-17.0.7.tgz#24559be23cb7d9757fd8f8c88380d7b4ee2339a2" + integrity sha512-ACg1B0tJLNa+f8mZfAaNrMyNzrrzHAARVH1sHHvh+LolKdQpgSKX69Uroz1Llv4C71furpwBklVStbNcEwVVVA== + dependencies: + rtl-detect "^1.0.2" + +expo-manifests@~1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/expo-manifests/-/expo-manifests-1.0.8.tgz#2ee1b33f974481d8cc5fc76352e0c78de5ff74d6" + integrity sha512-nA5PwU2uiUd+2nkDWf9e71AuFAtbrb330g/ecvuu52bmaXtN8J8oiilc9BDvAX0gg2fbtOaZdEdjBYopt1jdlQ== + dependencies: + "@expo/config" "~12.0.8" + expo-json-utils "~0.15.0" + +expo-module-scripts@^4.0.2: + version "4.1.10" + resolved "https://registry.yarnpkg.com/expo-module-scripts/-/expo-module-scripts-4.1.10.tgz#5f711f7e13ef9c56334b71975796548279bff9a6" + integrity sha512-fQVXVgxqUOz1cnnNumNLm0eI+Y8IhYNa056ad0vxEhcMui6FjS1+beZNHiaClGwd/NQb5RjlT48ABL3XSGHwxQ== + dependencies: + "@babel/cli" "^7.23.4" + "@babel/plugin-transform-export-namespace-from" "^7.23.4" + "@babel/preset-env" "^7.23.8" + "@babel/preset-typescript" "^7.23.3" + "@expo/npm-proofread" "^1.0.1" + "@testing-library/react-native" "^13.1.0" + "@tsconfig/node18" "^18.2.2" + "@types/jest" "^29.2.1" + babel-plugin-dynamic-import-node "^2.3.3" + babel-preset-expo "~13.2.3" + commander "^12.1.0" + eslint-config-universe "^15.0.3" + glob "^10.4.2" + jest-expo "~53.0.9" + jest-snapshot-prettier "npm:prettier@^2" + jest-watch-typeahead "2.2.1" + resolve-workspace-root "^2.0.0" + ts-jest "~29.0.4" + typescript "^5.8.3" + +expo-modules-autolinking@3.0.21: + version "3.0.21" + resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-3.0.21.tgz#a516453184c284f94aaec48cd5d9b0123a914701" + integrity sha512-pOtPDLln3Ju8DW1zRW4OwZ702YqZ8g+kM/tEY1sWfv22kWUtxkvK+ytRDRpRdnKEnC28okbhWqeMnmVkSFzP6Q== + dependencies: + "@expo/spawn-async" "^1.7.2" + chalk "^4.1.0" + commander "^7.2.0" + require-from-string "^2.0.2" + resolve-from "^5.0.0" + +expo-modules-core@3.0.25: + version "3.0.25" + resolved "https://registry.yarnpkg.com/expo-modules-core/-/expo-modules-core-3.0.25.tgz#5fc7c748fbba3d21b8b790144987074f89a2ee48" + integrity sha512-0P8PT8UV6c5/+p8zeVM/FXvBgn/ErtGcMaasqUgbzzBUg94ktbkIrij9t9reGCrir03BYt/Bcpv+EQtYC8JOug== + dependencies: + invariant "^2.2.4" + +expo-modules-core@^2.1.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/expo-modules-core/-/expo-modules-core-2.5.0.tgz#cc098607c9b0665e0cbd0a423c9542253caab58a" + integrity sha512-aIbQxZE2vdCKsolQUl6Q9Farlf8tjh/ROR4hfN1qT7QBGPl1XrJGnaOKkcgYaGrlzCPg/7IBe0Np67GzKMZKKQ== + dependencies: + invariant "^2.2.4" + +expo-notifications@~0.32.12: + version "0.32.12" + resolved "https://registry.yarnpkg.com/expo-notifications/-/expo-notifications-0.32.12.tgz#a21415153674a1116fa488100ef482960d67e9dd" + integrity sha512-FVJ5W4rOpKvmrLJ1Sd5pxiVTV4a7ApgTlKro+E5X8M2TBbXmEVOjs09klzdalXTjlzmU/Gu8aRw9xr7Ea/gZdw== + dependencies: + "@expo/image-utils" "^0.8.7" + "@ide/backoff" "^1.0.0" + abort-controller "^3.0.0" + assert "^2.0.0" + badgin "^1.1.5" + expo-application "~7.0.7" + expo-constants "~18.0.9" + +expo-secure-store@~15.0.7: + version "15.0.7" + resolved "https://registry.yarnpkg.com/expo-secure-store/-/expo-secure-store-15.0.7.tgz#f74f928029889b8a32c0eafc2a214abee1e8b71e" + integrity sha512-9q7+G1Zxr5P6J5NRIlm86KulvmYwc6UnQlYPjQLDu1drDnerz6AT6l884dPu29HgtDTn4rR0heYeeGFhMKM7/Q== + +expo-server@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/expo-server/-/expo-server-1.0.4.tgz#cb90f23272257f8cb0c9dceaade26bb169d8a3f7" + integrity sha512-IN06r3oPxFh3plSXdvBL7dx0x6k+0/g0bgxJlNISs6qL5Z+gyPuWS750dpTzOeu37KyBG0RcyO9cXUKzjYgd4A== + +expo-sharing@~14.0.7: + version "14.0.7" + resolved "https://registry.yarnpkg.com/expo-sharing/-/expo-sharing-14.0.7.tgz#64845ea569c725a9a32705be7ef772e556134e1c" + integrity sha512-t/5tR8ZJNH6tMkHXlF7453UafNIfrpfTG+THN9EMLC4Wsi4bJuESPm3NdmWDg2D4LDALJI/LQo0iEnLAd5Sp4g== + +expo-splash-screen@~31.0.10: + version "31.0.10" + resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-31.0.10.tgz#e0edd9782715b82a8eed34d5ebde778b79f850b4" + integrity sha512-i6g9IK798mae4yvflstQ1HkgahIJ6exzTCTw4vEdxV0J2SwiW3Tj+CwRjf0te7Zsb+7dDQhBTmGZwdv00VER2A== + dependencies: + "@expo/prebuild-config" "^54.0.3" + +expo-status-bar@~3.0.8: + version "3.0.8" + resolved "https://registry.yarnpkg.com/expo-status-bar/-/expo-status-bar-3.0.8.tgz#ada8b863a405f1619cd87a4b2b874d84e7d21ce5" + integrity sha512-L248XKPhum7tvREoS1VfE0H6dPCaGtoUWzRsUv7hGKdiB4cus33Rc0sxkWkoQ77wE8stlnUlL5lvmT0oqZ3ZBw== + dependencies: + react-native-is-edge-to-edge "^1.2.1" + +expo-structured-headers@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/expo-structured-headers/-/expo-structured-headers-5.0.0.tgz#b3cc223a7a58964652093f088a8988316db9ed9d" + integrity sha512-RmrBtnSphk5REmZGV+lcdgdpxyzio5rJw8CXviHE6qH5pKQQ83fhMEcigvrkBdsn2Efw2EODp4Yxl1/fqMvOZw== + +expo-task-manager@~14.0.7, expo-task-manager@~14.0.8: + version "14.0.8" + resolved "https://registry.yarnpkg.com/expo-task-manager/-/expo-task-manager-14.0.8.tgz#8cd14c638a5c2544e8dd1a438431bfa44196d378" + integrity sha512-HxhyvmulM8px+LQvqIKS85KVx2UodZf5RO+FE2ltpC4mQ5IFkX/ESqiK0grzDa4pVFLyxvs8LjuUKsfB5c39PQ== + dependencies: + unimodules-app-loader "~6.0.7" + +expo-testflight@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/expo-testflight/-/expo-testflight-0.3.0.tgz#b106e3d326d87a2ff9247af20979fef58109ad5a" + integrity sha512-wnAPyQKr8EVkoMK/CQYLcmWbD5dPJM0ZcuOq8AZmfzPzP5HfX3lH3iiLcOdoM2K8x7RbXdp/5iGvEmISIljaEw== + +expo-updates-interface@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/expo-updates-interface/-/expo-updates-interface-2.0.0.tgz#7721cb64c37bcb46b23827b2717ef451a9378749" + integrity sha512-pTzAIufEZdVPKql6iMi5ylVSPqV1qbEopz9G6TSECQmnNde2nwq42PxdFBaUEd8IZJ/fdJLQnOT3m6+XJ5s7jg== + +expo-updates@~29.0.12: + version "29.0.12" + resolved "https://registry.yarnpkg.com/expo-updates/-/expo-updates-29.0.12.tgz#cb43a20a6d32426694d414a2551f7300a4f75631" + integrity sha512-gE3bU6qi5g8Y1TtBzoeHac3utR0i1Wj1ufThh+zpDyFjFbegFm+gwvNLVCBagZUClYKk/4CKxh5ytnwZmPzH+g== + dependencies: + "@expo/code-signing-certificates" "0.0.5" + "@expo/plist" "^0.4.7" + "@expo/spawn-async" "^1.7.2" + arg "4.1.0" + chalk "^4.1.2" + debug "^4.3.4" + expo-eas-client "~1.0.7" + expo-manifests "~1.0.8" + expo-structured-headers "~5.0.0" + expo-updates-interface "~2.0.0" + getenv "^2.0.0" + glob "^10.4.2" + ignore "^5.3.1" + resolve-from "^5.0.0" + +expo-web-browser@~15.0.7, expo-web-browser@~15.0.9: + version "15.0.9" + resolved "https://registry.yarnpkg.com/expo-web-browser/-/expo-web-browser-15.0.9.tgz#248b8de8f901e68e89944c85a46ee40205190f59" + integrity sha512-Dj8kNFO+oXsxqCDNlUT/GhOrJnm10kAElH++3RplLydogFm5jTzXYWDEeNIDmV+F+BzGYs+sIhxiBf7RyaxXZg== + +expo@^54.0.0: + version "54.0.23" + resolved "https://registry.yarnpkg.com/expo/-/expo-54.0.23.tgz#6364f0c75221d13a75b83b3fa9cb301ed4a482b0" + integrity sha512-b4uQoiRwQ6nwqsT2709RS15CWYNGF3eJtyr1KyLw9WuMAK7u4jjofkhRiO0+3o1C2NbV+WooyYTOZGubQQMBaQ== + dependencies: + "@babel/runtime" "^7.20.0" + "@expo/cli" "54.0.16" + "@expo/config" "~12.0.10" + "@expo/config-plugins" "~54.0.2" + "@expo/devtools" "0.1.7" + "@expo/fingerprint" "0.15.3" + "@expo/metro" "~54.1.0" + "@expo/metro-config" "54.0.9" + "@expo/vector-icons" "^15.0.3" + "@ungap/structured-clone" "^1.3.0" + babel-preset-expo "~54.0.7" + expo-asset "~12.0.9" + expo-constants "~18.0.10" + expo-file-system "~19.0.17" + expo-font "~14.0.9" + expo-keep-awake "~15.0.7" + expo-modules-autolinking "3.0.21" + expo-modules-core "3.0.25" + pretty-format "^29.7.0" + react-refresh "^0.14.2" + whatwg-url-without-unicode "8.0.0-3" + +exponential-backoff@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz#51cf92c1c0493c766053f9d3abee4434c244d2f6" + integrity sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA== + +express-rate-limit@^7.5.0: + version "7.5.1" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.1.tgz#8c3a42f69209a3a1c969890070ece9e20a879dec" + integrity sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw== + +express@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" + integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== + dependencies: + accepts "^2.0.0" + body-parser "^2.2.0" + content-disposition "^1.0.0" + content-type "^1.0.5" + cookie "^0.7.1" + cookie-signature "^1.2.1" + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + finalhandler "^2.1.0" + fresh "^2.0.0" + http-errors "^2.0.0" + merge-descriptors "^2.0.0" + mime-types "^3.0.0" + on-finished "^2.4.1" + once "^1.4.0" + parseurl "^1.3.3" + proxy-addr "^2.0.7" + qs "^6.14.0" + range-parser "^1.2.1" + router "^2.2.0" + send "^1.1.0" + serve-static "^2.2.0" + statuses "^2.0.1" + type-is "^2.0.1" + vary "^1.1.2" + +extension-port-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extension-port-stream/-/extension-port-stream-3.0.0.tgz#00a7185fe2322708a36ed24843c81bd754925fef" + integrity sha512-an2S5quJMiy5bnZKEf6AkfH/7r8CzHvhchU40gxN+OM6HPhe7Z9T1FUychcf2M9PpPOO0Hf7BAEfJkw2TDIBDw== + dependencies: + readable-stream "^3.6.2 || ^4.4.2" + webextension-polyfill ">=0.10.0 <1.0" + +eyes@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" + integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== + +fast-base64-decode@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz#b434a0dd7d92b12b43f26819300d2dafb83ee418" + integrity sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q== + +fast-content-type-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz#5590b6c807cc598be125e6740a9fde589d2b7afb" + integrity sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg== + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" + integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-glob@^3.2.9, fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-loops@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/fast-loops/-/fast-loops-1.1.4.tgz#61bc77d518c0af5073a638c6d9d5c7683f069ce2" + integrity sha512-8dbd3XWoKCTms18ize6JmQF1SFnnfj5s0B7rRry22EofgMu7B6LKHVh+XfFqFGsqnbH54xgeO83PzpKI+ODhlg== + +fast-redact@^3.0.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== + +fast-safe-stringify@^2.0.6: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fast-stable-stringify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" + integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== + +fast-text-encoding@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" + integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== + +fast-uri@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" + integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +faye-websocket@0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fb-watchman@^2.0.0, fb-watchman@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +fflate@^0.4.8: + version "0.4.8" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" + integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + +finalhandler@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +finalhandler@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.0.tgz#72306373aa89d05a8242ed569ed86a1bff7c561f" + integrity sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q== + dependencies: + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + on-finished "^2.4.1" + parseurl "^1.3.3" + statuses "^2.0.1" + +find-babel-config@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-2.1.2.tgz#2841b1bfbbbcdb971e1e39df8cbc43dafa901716" + integrity sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg== + dependencies: + json5 "^2.2.3" + +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0, find-up@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +firebase@12.4.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-12.4.0.tgz#c9de52c23e707d90aa43343ab3ad1c1ce6b71301" + integrity sha512-/chNgDQ6ppPPGOQO4jctxOa/5JeQxuhaxA7Y90K0I+n/wPfoO8mRveedhVUdo7ExLcWUivnnow/ouSLYSI5Icw== + dependencies: + "@firebase/ai" "2.4.0" + "@firebase/analytics" "0.10.19" + "@firebase/analytics-compat" "0.2.25" + "@firebase/app" "0.14.4" + "@firebase/app-check" "0.11.0" + "@firebase/app-check-compat" "0.4.0" + "@firebase/app-compat" "0.5.4" + "@firebase/app-types" "0.9.3" + "@firebase/auth" "1.11.0" + "@firebase/auth-compat" "0.6.0" + "@firebase/data-connect" "0.3.11" + "@firebase/database" "1.1.0" + "@firebase/database-compat" "2.1.0" + "@firebase/firestore" "4.9.2" + "@firebase/firestore-compat" "0.4.2" + "@firebase/functions" "0.13.1" + "@firebase/functions-compat" "0.4.1" + "@firebase/installations" "0.6.19" + "@firebase/installations-compat" "0.2.19" + "@firebase/messaging" "0.12.23" + "@firebase/messaging-compat" "0.2.23" + "@firebase/performance" "0.7.9" + "@firebase/performance-compat" "0.2.22" + "@firebase/remote-config" "0.7.0" + "@firebase/remote-config-compat" "0.2.20" + "@firebase/storage" "0.14.0" + "@firebase/storage-compat" "0.4.0" + "@firebase/util" "1.13.0" + +firebase@^12.5.0: + version "12.5.0" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-12.5.0.tgz#a0268f8303778c4a1766a8590e412c8b290dcfaa" + integrity sha512-Ak8JcpH7FL6kiv0STwkv5+3CYEROO9iFWSx7OCZVvc4kIIABAIyAGs1mPGaHRxGUIApFZdMCXA7baq17uS6Mow== + dependencies: + "@firebase/ai" "2.5.0" + "@firebase/analytics" "0.10.19" + "@firebase/analytics-compat" "0.2.25" + "@firebase/app" "0.14.5" + "@firebase/app-check" "0.11.0" + "@firebase/app-check-compat" "0.4.0" + "@firebase/app-compat" "0.5.5" + "@firebase/app-types" "0.9.3" + "@firebase/auth" "1.11.1" + "@firebase/auth-compat" "0.6.1" + "@firebase/data-connect" "0.3.11" + "@firebase/database" "1.1.0" + "@firebase/database-compat" "2.1.0" + "@firebase/firestore" "4.9.2" + "@firebase/firestore-compat" "0.4.2" + "@firebase/functions" "0.13.1" + "@firebase/functions-compat" "0.4.1" + "@firebase/installations" "0.6.19" + "@firebase/installations-compat" "0.2.19" + "@firebase/messaging" "0.12.23" + "@firebase/messaging-compat" "0.2.23" + "@firebase/performance" "0.7.9" + "@firebase/performance-compat" "0.2.22" + "@firebase/remote-config" "0.7.0" + "@firebase/remote-config-compat" "0.2.20" + "@firebase/storage" "0.14.0" + "@firebase/storage-compat" "0.4.0" + "@firebase/util" "1.13.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + +flow-enums-runtime@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz#5bb0cd1b0a3e471330f4d109039b7eba5cb3e787" + integrity sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw== + +focus-lock@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-1.3.6.tgz#955eec1e10591d56f679258edb94aedb11d691cd" + integrity sha512-Ik/6OCk9RQQ0T5Xw+hKNLWrjSMtv51dD4GRmJjbD5a58TIEpI5a5iXagKVl3Z5UuyslMCA8Xwnu76jQob62Yhg== + dependencies: + tslib "^2.0.3" + +follow-redirects@^1.15.11, follow-redirects@^1.15.6: + version "1.15.11" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.11.tgz#777d73d72a92f8ec4d2e410eb47352a56b8e8340" + integrity sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ== + +fontfaceobserver@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz#5fb392116e75d5024b7ec8e4f2ce92106d1488c8" + integrity sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg== + +for-each@^0.3.3, for-each@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== + dependencies: + is-callable "^1.2.7" + +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +form-data@^4.0.0, form-data@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.4.tgz#784cdcce0669a9d68e94d11ac4eea98088edd2c4" + integrity sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.12" + +form-data@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" + integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + hasown "^2.0.2" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fraction.js@^5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-5.3.4.tgz#8c0fcc6a9908262df4ed197427bdeef563e0699a" + integrity sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ== + +framer-motion@^11.0.8: + version "11.18.2" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-11.18.2.tgz#0c6bd05677f4cfd3b3bdead4eb5ecdd5ed245718" + integrity sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w== + dependencies: + motion-dom "^11.18.1" + motion-utils "^11.18.1" + tslib "^2.4.0" + +framesync@6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.1.2.tgz#755eff2fb5b8f3b4d2b266dd18121b300aefea27" + integrity sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g== + dependencies: + tslib "2.4.0" + +freeport-async@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/freeport-async/-/freeport-async-2.0.0.tgz#6adf2ec0c629d11abff92836acd04b399135bab4" + integrity sha512-K7od3Uw45AJg00XUmy15+Hae2hOcgKcmN3/EF6Y7i01O0gaqiRx8sUSpsb9+BRNL8RPBrhzPsVfy8q9ADlJuWQ== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" + integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== + +fs-extra@^10.0.0, fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2, fsevents@^2.3.3, fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +fuse.js@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-7.1.0.tgz#306228b4befeee11e05b027087c2744158527d09" + integrity sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ== + +generator-function@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/generator-function/-/generator-function-2.0.1.tgz#0e75dd410d1243687a0ba2e951b94eedb8f737a2" + integrity sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-params@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/get-params/-/get-params-0.1.2.tgz#bae0dfaba588a0c60d7834c0d8dc2ff60eeef2fe" + integrity sha512-41eOxtlGgHQRbFyA8KTH+w+32Em3cRdfBud7j67ulzmIfmaHX9doq47s0fa4P5o9H64BZX9nrYI6sJvk46Op+Q== + +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-stream@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + +get-tsconfig@^4.10.0, get-tsconfig@^4.7.3, get-tsconfig@^4.7.5, get-tsconfig@^4.8.1: + version "4.13.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz#fcdd991e6d22ab9a600f00e91c318707a5d9a0d7" + integrity sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ== + dependencies: + resolve-pkg-maps "^1.0.0" + +getenv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/getenv/-/getenv-1.0.0.tgz#874f2e7544fbca53c7a4738f37de8605c3fcfc31" + integrity sha512-7yetJWqbS9sbn0vIfliPsFgoXMKn/YMF+Wuiog97x+urnSRRRZ7xB+uVkwGKzRgq9CDFfMQnE9ruL5DHv9c6Xg== + +getenv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/getenv/-/getenv-2.0.0.tgz#b1698c7b0f29588f4577d06c42c73a5b475c69e0" + integrity sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^10.3.10, glob@^10.4.2: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0, glob@^7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^8.0.3: + version "8.1.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^5.0.1" + once "^1.3.0" + +glob@^9.3.3: + version "9.3.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" + integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== + dependencies: + fs.realpath "^1.0.0" + minimatch "^8.0.2" + minipass "^4.2.4" + path-scurry "^1.6.1" + +global-dirs@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg== + dependencies: + ini "^1.3.4" + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globals@^15.11.0, globals@^15.14.0: + version "15.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" + integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== + +globals@^16.0.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-16.5.0.tgz#ccf1594a437b97653b2be13ed4d8f5c9f850cac1" + integrity sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ== + +globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + +globby@^11.0.1: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +globrex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" + integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== + +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + +graceful-fs@^4.1.11, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +graphql@^15.4.0: + version "15.10.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.10.1.tgz#e9ff3bb928749275477f748b14aa5c30dcad6f2f" + integrity sha512-BL/Xd/T9baO6NFzoMpiMD7YUZ62R6viR5tp/MULVEnbYJXZA//kRNW7J0j1w/wXArgL0sCxhDfK5dczSKn3+cg== + +h3@^1.15.5: + version "1.15.5" + resolved "https://registry.yarnpkg.com/h3/-/h3-1.15.5.tgz#e2f28d4a66a249973bb050eaddb06b9ab55506f8" + integrity sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg== + dependencies: + cookie-es "^1.2.2" + crossws "^0.3.5" + defu "^6.1.4" + destr "^2.0.5" + iron-webcrypto "^1.2.1" + node-mock-http "^1.0.4" + radix3 "^1.1.2" + ufo "^1.6.3" + uncrypto "^0.1.3" + +handlebars@^4.7.8: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" + +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + +has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +hermes-estree@0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.23.1.tgz#d0bac369a030188120ee7024926aabe5a9f84fdb" + integrity sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg== + +hermes-estree@0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.25.1.tgz#6aeec17d1983b4eabf69721f3aa3eb705b17f480" + integrity sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw== + +hermes-estree@0.29.1: + version "0.29.1" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.29.1.tgz#043c7db076e0e8ef8c5f6ed23828d1ba463ebcc5" + integrity sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ== + +hermes-estree@0.32.0: + version "0.32.0" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.32.0.tgz#bb7da6613ab8e67e334a1854ea1e209f487d307b" + integrity sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ== + +hermes-parser@0.23.1: + version "0.23.1" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.23.1.tgz#e5de648e664f3b3d84d01b48fc7ab164f4b68205" + integrity sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA== + dependencies: + hermes-estree "0.23.1" + +hermes-parser@0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.25.1.tgz#5be0e487b2090886c62bd8a11724cd766d5f54d1" + integrity sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA== + dependencies: + hermes-estree "0.25.1" + +hermes-parser@0.29.1, hermes-parser@^0.29.1: + version "0.29.1" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.29.1.tgz#436b24bcd7bb1e71f92a04c396ccc0716c288d56" + integrity sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA== + dependencies: + hermes-estree "0.29.1" + +hermes-parser@0.32.0: + version "0.32.0" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.32.0.tgz#7916984ef6fdce62e7415d354cf35392061cd303" + integrity sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw== + dependencies: + hermes-estree "0.32.0" + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hono@^4.10.3: + version "4.12.3" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.12.3.tgz#fd8dd1127c30956a9d58c1b0c4535d21c1ef3e16" + integrity sha512-SFsVSjp8sj5UumXOOFlkZOG6XS9SJDKw0TbwFeV+AJ8xlST8kxK5Z/5EYa111UY8732lK2S/xB653ceuaoGwpg== + +hosted-git-info@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-7.0.2.tgz#9b751acac097757667f30114607ef7b661ff4f17" + integrity sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w== + dependencies: + lru-cache "^10.0.1" + +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +html-parse-stringify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2" + integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg== + dependencies: + void-elements "3.1.0" + +http-errors@2.0.0, http-errors@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-parser-js@>=0.5.1: + version "0.5.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.10.tgz#b3277bd6d7ed5588e20ea73bf724fcbe44609075" + integrity sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA== + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +https-proxy-agent@^7.0.5: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ== + dependencies: + ms "^2.0.0" + +hyphenate-style-name@^1.0.3: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz#1797bf50369588b47b72ca6d5e65374607cf4436" + integrity sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw== + +i18next@^24.0.2: + version "24.2.3" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-24.2.3.tgz#3a05f72615cbd7c00d7e348667e2aabef1df753b" + integrity sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A== + dependencies: + "@babel/runtime" "^7.26.10" + +iconv-lite@0.6.3, iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +iconv-lite@0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.0.tgz#c50cd80e6746ca8115eb98743afa81aa0e147a3e" + integrity sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +idb-keyval@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.1.tgz#94516d625346d16f56f3b33855da11bfded2db33" + integrity sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg== + +idb-keyval@^6.2.1: + version "6.2.2" + resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.2.tgz#b0171b5f73944854a3291a5cdba8e12768c4854a" + integrity sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg== + +idb@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" + integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== + +ieee754@^1.1.13, ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.1.1, ignore@^5.2.0, ignore@^5.3.1, ignore@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + +ignore@^7.0.0: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + +image-size@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.2.1.tgz#ee118aedfe666db1a6ee12bed5821cde3740276d" + integrity sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw== + dependencies: + queue "6.0.2" + +immer@^10.0.3, immer@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/immer/-/immer-10.2.0.tgz#88a4ce06a1af64172d254b70f7cb04df51c871b1" + integrity sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw== + +immutable@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg== + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.2.1, import-fresh@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2, import-local@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^1.3.4, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +inline-style-prefixer@^6.0.1: + version "6.0.4" + resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-6.0.4.tgz#4290ed453ab0e4441583284ad86e41ad88384f44" + integrity sha512-FwXmZC2zbeeS7NzGjJ6pAiqRhXR0ugUShSNb6GApMl6da0/XGc4MOJsoWAywia52EEWbXNSy0pzkwz/+Y+swSg== + dependencies: + css-in-js-utils "^3.1.0" + fast-loops "^1.1.3" + +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.2" + side-channel "^1.1.0" + +intl-messageformat@^10.1.0: + version "10.7.18" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.7.18.tgz#51a6f387afbca9b0f881b2ec081566db8c540b0d" + integrity sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g== + dependencies: + "@formatjs/ecma402-abstract" "2.3.6" + "@formatjs/fast-memoize" "2.2.7" + "@formatjs/icu-messageformat-parser" "2.11.4" + tslib "^2.8.0" + +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +iron-webcrypto@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz#aa60ff2aa10550630f4c0b11fd2442becdb35a6f" + integrity sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg== + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + +is-arguments@^1.0.4, is-arguments@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.2.0.tgz#ad58c6aecf563b78ef2bf04df540da8f5d7d8e1b" + integrity sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-async-function@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" + integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== + dependencies: + async-function "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== + dependencies: + has-bigints "^1.0.2" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-buffer@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-bun-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-2.0.0.tgz#4d7859a87c0fcac950c95e666730e745eae8bddd" + integrity sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ== + dependencies: + semver "^7.7.1" + +is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0, is-core-module@^2.16.1: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== + dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + is-typed-array "^1.1.13" + +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== + dependencies: + call-bound "^1.0.2" + has-tostringtag "^1.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== + dependencies: + call-bound "^1.0.3" + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0, is-generator-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-generator-function@^1.0.10, is-generator-function@^1.0.7: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.2.tgz#ae3b61e3d5ea4e4839b90bad22b02335051a17d5" + integrity sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA== + dependencies: + call-bound "^1.0.4" + generator-function "^2.0.0" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" + +is-git-dirty@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-git-dirty/-/is-git-dirty-2.0.2.tgz#696fe5a7e60710de75a1b7d2ae8c7ee9cc0bc57b" + integrity sha512-U3YCo+GKR/rDsY7r0v/LBICbQwsx859tDQnAT+v0E/zCDeWbQ1TUt1FtyExeyik7VIJlYOLHCIifLdz71HDalg== + dependencies: + execa "^4.0.3" + is-git-repository "^2.0.0" + +is-git-repository@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-git-repository/-/is-git-repository-2.0.0.tgz#fa036007fe9697198c2c89dac4dd8304a6101e1c" + integrity sha512-HDO50CG5suIAcmqG4F1buqVXEZRPn+RaXIn9pFKq/947FBo2bCRwK7ZluEVZOy99a4IQyqsjbKEpAiOXCccOHQ== + dependencies: + execa "^4.0.3" + is-absolute "^1.0.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-nan@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + +is-promise@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" + integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== + +is-regex@^1.1.4, is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== + dependencies: + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + +is-retry-allowed@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz#88f34cbd236e043e71b6932d09b0c65fb7b4d71d" + integrity sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg== + +is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== + dependencies: + call-bound "^1.0.3" + +is-standalone-pwa@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-standalone-pwa/-/is-standalone-pwa-0.1.1.tgz#7a1b0459471a95378aa0764d5dc0a9cec95f2871" + integrity sha512-9Cbovsa52vNQCjdXOzeQq5CnCbAcRk05aU62K20WO372NrTv0NxibLFCK6lQ4/iZEFdEA3p3t2VNOn8AJ53F5g== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== + dependencies: + call-bound "^1.0.3" + has-tostringtag "^1.0.2" + +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== + dependencies: + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" + +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15, is-typed-array@^1.1.3: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== + dependencies: + which-typed-array "^1.1.16" + +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + +is-weakref@^1.0.2, is-weakref@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== + dependencies: + call-bound "^1.0.3" + +is-weakset@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== + dependencies: + call-bound "^1.0.3" + get-intrinsic "^1.2.6" + +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1, is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +isomorphic-unfetch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" + integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== + dependencies: + node-fetch "^2.6.1" + unfetch "^4.2.0" + +isomorphic-ws@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== + +isows@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.6.tgz#0da29d706fa51551c663c627ace42769850f86e7" + integrity sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw== + +isows@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" + integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0, istanbul-lib-instrument@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-lib-source-maps@^5.0.0: + version "5.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== + dependencies: + "@jridgewell/trace-mapping" "^0.3.23" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + +istanbul-reports@^3.1.3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93" + integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +iterator.prototype@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" + integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== + dependencies: + define-data-property "^1.1.4" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + get-proto "^1.0.0" + has-symbols "^1.1.0" + set-function-name "^2.0.2" + +its-fine@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-2.0.0.tgz#a90b18a3ee4c211a1fb6faac2abcc2b682ce1f21" + integrity sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng== + dependencies: + "@types/react-reconciler" "^0.28.9" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jayson@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.2.0.tgz#b71762393fa40bc9637eaf734ca6f40d3b8c0c93" + integrity sha512-VfJ9t1YLwacIubLhONk0KFeosUBwstRWQ0IRT1KDjEjnVnSOVHC3uwugyV7L0c7R9lpVyrUGT2XWiBA1UTtpyg== + dependencies: + "@types/connect" "^3.4.33" + "@types/node" "^12.12.54" + "@types/ws" "^7.4.4" + commander "^2.20.3" + delay "^5.0.0" + es6-promisify "^5.0.0" + eyes "^0.1.8" + isomorphic-ws "^4.0.1" + json-stringify-safe "^5.0.1" + stream-json "^1.9.1" + uuid "^8.3.2" + ws "^7.5.10" + +jest-changed-files@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-30.2.0.tgz#602266e478ed554e1e1469944faa7efd37cee61c" + integrity sha512-L8lR1ChrRnSdfeOvTrwZMlnWV8G/LLjQ0nG9MBclwWZidA2N5FviRki0Bvh20WRMOX31/JYvzdqTJrk5oBdydQ== + dependencies: + execa "^5.1.1" + jest-util "30.2.0" + p-limit "^3.1.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-30.2.0.tgz#98b8198b958748a2f322354311023d1d02e7603f" + integrity sha512-Fh0096NC3ZkFx05EP2OXCxJAREVxj1BcW/i6EWqqymcgYKWjyyDpral3fMxVcHXg6oZM7iULer9wGRFvfpl+Tg== + dependencies: + "@jest/environment" "30.2.0" + "@jest/expect" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + co "^4.6.0" + dedent "^1.6.0" + is-generator-fn "^2.1.0" + jest-each "30.2.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-runtime "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" + p-limit "^3.1.0" + pretty-format "30.2.0" + pure-rand "^7.0.0" + slash "^3.0.0" + stack-utils "^2.0.6" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-30.2.0.tgz#1780f8e9d66bf84a10b369aea60aeda7697dcc67" + integrity sha512-Os9ukIvADX/A9sLt6Zse3+nmHtHaE6hqOsjQtNiugFTbKRHYIYtZXNGNK9NChseXy7djFPjndX1tL0sCTlfpAA== + dependencies: + "@jest/core" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" + chalk "^4.1.2" + exit-x "^0.2.2" + import-local "^3.2.0" + jest-config "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + yargs "^17.7.2" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-30.2.0.tgz#29df8c50e2ad801cc59c406b50176c18c362a90b" + integrity sha512-g4WkyzFQVWHtu6uqGmQR4CQxz/CH3yDSlhzXMWzNjDx843gYjReZnMRanjRCq5XZFuQrGDxgUaiYWE8BRfVckA== + dependencies: + "@babel/core" "^7.27.4" + "@jest/get-type" "30.1.0" + "@jest/pattern" "30.0.1" + "@jest/test-sequencer" "30.2.0" + "@jest/types" "30.2.0" + babel-jest "30.2.0" + chalk "^4.1.2" + ci-info "^4.2.0" + deepmerge "^4.3.1" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-circus "30.2.0" + jest-docblock "30.2.0" + jest-environment-node "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-runner "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + micromatch "^4.0.8" + parse-json "^5.2.0" + pretty-format "30.2.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-30.2.0.tgz#e3ec3a6ea5c5747f605c9e874f83d756cba36825" + integrity sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A== + dependencies: + "@jest/diff-sequences" "30.0.1" + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + pretty-format "30.2.0" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-30.2.0.tgz#42cd98d69f887e531c7352309542b1ce4ee10256" + integrity sha512-tR/FFgZKS1CXluOQzZvNH3+0z9jXr3ldGSD8bhyuxvlVUwbeLOGynkunvlTMxchC5urrKndYiwCFC0DLVjpOCA== + dependencies: + detect-newline "^3.1.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-30.2.0.tgz#39e623ae71641c2ac3ee69b3ba3d258fce8e768d" + integrity sha512-lpWlJlM7bCUf1mfmuqTA8+j2lNURW9eNafOy99knBM01i5CQeY5UH1vZjgT9071nDJac1M4XsbyI44oNOdhlDQ== + dependencies: + "@jest/get-type" "30.1.0" + "@jest/types" "30.2.0" + chalk "^4.1.2" + jest-util "30.2.0" + pretty-format "30.2.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-jsdom@^29.2.1: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f" + integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/jsdom" "^20.0.0" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + jsdom "^20.0.0" + +jest-environment-node@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-30.2.0.tgz#3def7980ebd2fd86e74efd4d2e681f55ab38da0f" + integrity sha512-ElU8v92QJ9UrYsKrxDIKCxu6PfNj4Hdcktcn0JX12zqNdqWHB0N+hwOnnBBXvjLd2vApZtuLUGs1QSY+MsXoNA== + dependencies: + "@jest/environment" "30.2.0" + "@jest/fake-timers" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + jest-mock "30.2.0" + jest-util "30.2.0" + jest-validate "30.2.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-expo@~53.0.9: + version "53.0.10" + resolved "https://registry.yarnpkg.com/jest-expo/-/jest-expo-53.0.10.tgz#52dc368b3a54f431acbb1aaf298f20196732df4a" + integrity sha512-J6vGCNOImXxUXv0c70J2hMlGSHTIyVwCviezMtnZeg966lzshESJhLxQatuvA8r7nJ2riffQgM3cWvL+/Hdewg== + dependencies: + "@expo/config" "~11.0.13" + "@expo/json-file" "^9.1.5" + "@jest/create-cache-key-function" "^29.2.1" + "@jest/globals" "^29.2.1" + babel-jest "^29.2.1" + find-up "^5.0.0" + jest-environment-jsdom "^29.2.1" + jest-snapshot "^29.2.1" + jest-watch-select-projects "^2.0.0" + jest-watch-typeahead "2.2.1" + json5 "^2.2.3" + lodash "^4.17.19" + react-server-dom-webpack "~19.0.0" + react-test-renderer "19.0.0" + server-only "^0.0.1" + stacktrace-js "^2.0.2" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-30.2.0.tgz#808e3889f288603ac70ff0ac047598345a66022e" + integrity sha512-sQA/jCb9kNt+neM0anSj6eZhLZUIhQgwDt7cPGjumgLM4rXsfb9kpnlacmvZz3Q5tb80nS+oG/if+NBKrHC+Xw== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + anymatch "^3.1.3" + fb-watchman "^2.0.2" + graceful-fs "^4.2.11" + jest-regex-util "30.0.1" + jest-util "30.2.0" + jest-worker "30.2.0" + micromatch "^4.0.8" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.3" + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-30.2.0.tgz#292fdca7b7c9cf594e1e570ace140b01d8beb736" + integrity sha512-M6jKAjyzjHG0SrQgwhgZGy9hFazcudwCNovY/9HPIicmNSBuockPSedAP9vlPK6ONFJ1zfyH/M2/YYJxOz5cdQ== + dependencies: + "@jest/get-type" "30.1.0" + pretty-format "30.2.0" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@30.2.0, jest-matcher-utils@^30.0.5: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz#69a0d4c271066559ec8b0d8174829adc3f23a783" + integrity sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg== + dependencies: + "@jest/get-type" "30.1.0" + chalk "^4.1.2" + jest-diff "30.2.0" + pretty-format "30.2.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-30.2.0.tgz#fc97bf90d11f118b31e6131e2b67fc4f39f92152" + integrity sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@jest/types" "30.2.0" + "@types/stack-utils" "^2.0.3" + chalk "^4.1.2" + graceful-fs "^4.2.11" + micromatch "^4.0.8" + pretty-format "30.2.0" + slash "^3.0.0" + stack-utils "^2.0.6" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-30.2.0.tgz#69f991614eeb4060189459d3584f710845bff45e" + integrity sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + jest-util "30.2.0" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2, jest-pnp-resolver@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@30.0.1: + version "30.0.1" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-30.0.1.tgz#f17c1de3958b67dfe485354f5a10093298f2a49b" + integrity sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA== + +jest-regex-util@^29.0.0, jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-30.2.0.tgz#3370e2c0b49cc560f6a7e8ec3a59dd99525e1a55" + integrity sha512-xTOIGug/0RmIe3mmCqCT95yO0vj6JURrn1TKWlNbhiAefJRWINNPgwVkrVgt/YaerPzY3iItufd80v3lOrFJ2w== + dependencies: + jest-regex-util "30.0.1" + jest-snapshot "30.2.0" + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-30.2.0.tgz#2e2009cbd61e8f1f003355d5ec87225412cebcd7" + integrity sha512-TCrHSxPlx3tBY3hWNtRQKbtgLhsXa1WmbJEqBlTBrGafd5fiQFByy2GNCEoGR+Tns8d15GaL9cxEzKOO3GEb2A== + dependencies: + chalk "^4.1.2" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-pnp-resolver "^1.2.3" + jest-util "30.2.0" + jest-validate "30.2.0" + slash "^3.0.0" + unrs-resolver "^1.7.11" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-30.2.0.tgz#c62b4c3130afa661789705e13a07bdbcec26a114" + integrity sha512-PqvZ2B2XEyPEbclp+gV6KO/F1FIFSbIwewRgmROCMBo/aZ6J1w8Qypoj2pEOcg3G2HzLlaP6VUtvwCI8dM3oqQ== + dependencies: + "@jest/console" "30.2.0" + "@jest/environment" "30.2.0" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + emittery "^0.13.1" + exit-x "^0.2.2" + graceful-fs "^4.2.11" + jest-docblock "30.2.0" + jest-environment-node "30.2.0" + jest-haste-map "30.2.0" + jest-leak-detector "30.2.0" + jest-message-util "30.2.0" + jest-resolve "30.2.0" + jest-runtime "30.2.0" + jest-util "30.2.0" + jest-watcher "30.2.0" + jest-worker "30.2.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-30.2.0.tgz#395ea792cde048db1b0cd1a92dc9cb9f1921bf8a" + integrity sha512-p1+GVX/PJqTucvsmERPMgCPvQJpFt4hFbM+VN3n8TMo47decMUcJbt+rgzwrEme0MQUA/R+1de2axftTHkKckg== + dependencies: + "@jest/environment" "30.2.0" + "@jest/fake-timers" "30.2.0" + "@jest/globals" "30.2.0" + "@jest/source-map" "30.0.1" + "@jest/test-result" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + cjs-module-lexer "^2.1.0" + collect-v8-coverage "^1.0.2" + glob "^10.3.10" + graceful-fs "^4.2.11" + jest-haste-map "30.2.0" + jest-message-util "30.2.0" + jest-mock "30.2.0" + jest-regex-util "30.0.1" + jest-resolve "30.2.0" + jest-snapshot "30.2.0" + jest-util "30.2.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +"jest-snapshot-prettier@npm:prettier@3.5.3", "jest-snapshot-prettier@npm:prettier@^2": + version "3.5.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" + integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== + +jest-snapshot@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-30.2.0.tgz#266fbbb4b95fc4665ce6f32f1f38eeb39f4e26d0" + integrity sha512-5WEtTy2jXPFypadKNpbNkZ72puZCa6UjSr/7djeecHWOu7iYhSXSnHScT8wBz3Rn8Ena5d5RYRcsyKIeqG1IyA== + dependencies: + "@babel/core" "^7.27.4" + "@babel/generator" "^7.27.5" + "@babel/plugin-syntax-jsx" "^7.27.1" + "@babel/plugin-syntax-typescript" "^7.27.1" + "@babel/types" "^7.27.3" + "@jest/expect-utils" "30.2.0" + "@jest/get-type" "30.1.0" + "@jest/snapshot-utils" "30.2.0" + "@jest/transform" "30.2.0" + "@jest/types" "30.2.0" + babel-preset-current-node-syntax "^1.2.0" + chalk "^4.1.2" + expect "30.2.0" + graceful-fs "^4.2.11" + jest-diff "30.2.0" + jest-matcher-utils "30.2.0" + jest-message-util "30.2.0" + jest-util "30.2.0" + pretty-format "30.2.0" + semver "^7.7.2" + synckit "^0.11.8" + +jest-snapshot@^29.2.1, jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-30.2.0.tgz#5142adbcad6f4e53c2776c067a4db3c14f913705" + integrity sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA== + dependencies: + "@jest/types" "30.2.0" + "@types/node" "*" + chalk "^4.1.2" + ci-info "^4.2.0" + graceful-fs "^4.2.11" + picomatch "^4.0.2" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-30.2.0.tgz#273eaaed4c0963b934b5b31e96289edda6e0a2ef" + integrity sha512-FBGWi7dP2hpdi8nBoWxSsLvBFewKAg0+uSQwBaof4Y4DPgBabXgpSYC5/lR7VmnIlSpASmCi/ntRWPbv7089Pw== + dependencies: + "@jest/get-type" "30.1.0" + "@jest/types" "30.2.0" + camelcase "^6.3.0" + chalk "^4.1.2" + leven "^3.1.0" + pretty-format "30.2.0" + +jest-validate@^29.6.3, jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watch-select-projects@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jest-watch-select-projects/-/jest-watch-select-projects-2.0.0.tgz#4373d7e4de862aae28b46e036b669a4c913ea867" + integrity sha512-j00nW4dXc2NiCW6znXgFLF9g8PJ0zP25cpQ1xRro/HU2GBfZQFZD0SoXnAlaoKkIY4MlfTMkKGbNXFpvCdjl1w== + dependencies: + ansi-escapes "^4.3.0" + chalk "^3.0.0" + prompts "^2.2.1" + +jest-watch-typeahead@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-2.2.1.tgz#36601520a2a30fd561788552dbda9c76bb44814a" + integrity sha512-jYpYmUnTzysmVnwq49TAxlmtOAwp8QIqvZyoofQFn8fiWhEDZj33ZXzg3JA4nGnzWFm1hbWf3ADpteUokvXgFA== + dependencies: + ansi-escapes "^6.0.0" + chalk "^4.0.0" + jest-regex-util "^29.0.0" + jest-watcher "^29.0.0" + slash "^5.0.0" + string-length "^5.0.1" + strip-ansi "^7.0.1" + +jest-watcher@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-30.2.0.tgz#f9c055de48e18c979e7756a3917e596e2d69b07b" + integrity sha512-PYxa28dxJ9g777pGm/7PrbnMeA0Jr7osHP9bS7eJy9DuAjMgdGtxgf0uKMyoIsTWAkIbUW5hSDdJ3urmgXBqxg== + dependencies: + "@jest/test-result" "30.2.0" + "@jest/types" "30.2.0" + "@types/node" "*" + ansi-escapes "^4.3.2" + chalk "^4.1.2" + emittery "^0.13.1" + jest-util "30.2.0" + string-length "^4.0.2" + +jest-watcher@^29.0.0, jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@30.2.0: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-30.2.0.tgz#fd5c2a36ff6058ec8f74366ec89538cc99539d26" + integrity sha512-0Q4Uk8WF7BUwqXHuAjc23vmopWJw5WH7w2tqBoUOZpOjW/ZnR44GXXd1r82RvnmI2GZge3ivrYXk/BE2+VtW2g== + dependencies: + "@types/node" "*" + "@ungap/structured-clone" "^1.3.0" + jest-util "30.2.0" + merge-stream "^2.0.0" + supports-color "^8.1.1" + +jest-worker@^29.6.3, jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +jest@^30.0.5: + version "30.2.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-30.2.0.tgz#9f0a71e734af968f26952b5ae4b724af82681630" + integrity sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A== + dependencies: + "@jest/core" "30.2.0" + "@jest/types" "30.2.0" + import-local "^3.2.0" + jest-cli "30.2.0" + +jimp-compact@0.16.1: + version "0.16.1" + resolved "https://registry.yarnpkg.com/jimp-compact/-/jimp-compact-0.16.1.tgz#9582aea06548a2c1e04dd148d7c3ab92075aefa3" + integrity sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww== + +jiti@^1.21.7: + version "1.21.7" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9" + integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== + +jose@^6.0.8: + version "6.1.3" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5" + integrity sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ== + +js-base64@^3.7.5: + version "3.7.8" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.8.tgz#af44496bc09fa178ed9c4adf67eb2b46f5c6d2a4" + integrity sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow== + +js-sha256@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" + integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsan@^3.1.14: + version "3.1.14" + resolved "https://registry.yarnpkg.com/jsan/-/jsan-3.1.14.tgz#197fee2d260b85acacb049c1ffa41bd09fb1f213" + integrity sha512-wStfgOJqMv4QKktuH273f5fyi3D3vy2pHOiSDGPvpcS/q+wb/M7AK3vkCcaHbkZxDOlDU/lDJgccygKSG2OhtA== + +jsc-safe-url@^0.2.2, jsc-safe-url@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz#141c14fbb43791e88d5dc64e85a374575a83477a" + integrity sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q== + +jsdom@^20.0.0: + version "20.0.3" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db" + integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== + dependencies: + abab "^2.0.6" + acorn "^8.8.1" + acorn-globals "^7.0.0" + cssom "^0.5.0" + cssstyle "^2.3.0" + data-urls "^3.0.2" + decimal.js "^10.4.2" + domexception "^4.0.0" + escodegen "^2.0.0" + form-data "^4.0.0" + html-encoding-sniffer "^3.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.2" + parse5 "^7.1.1" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^4.1.2" + w3c-xmlserializer "^4.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^2.0.0" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + ws "^8.11.0" + xml-name-validator "^4.0.0" + +jsesc@^3.0.2, jsesc@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-diff-ts@^4.0.1: + version "4.8.2" + resolved "https://registry.yarnpkg.com/json-diff-ts/-/json-diff-ts-4.8.2.tgz#9b95bc556c2f5acb2f15fd535e63bbe447bd242c" + integrity sha512-7LgOTnfK5XnBs0o0AtHTkry5QGZT7cSlAgu5GtiomUeoHqOavAUDcONNm/bCe4Lapt0AHnaidD5iSE+ItvxKkA== + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-rpc-engine@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-6.1.0.tgz#bf5ff7d029e1c1bf20cb6c0e9f348dcd8be5a393" + integrity sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ== + dependencies: + "@metamask/safe-event-emitter" "^2.0.0" + eth-rpc-errors "^4.0.2" + +json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-stable-stringify@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz#8903cfac42ea1a0f97f35d63a4ce0518f0cc6a70" + integrity sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + isarray "^2.0.5" + jsonify "^0.0.1" + object-keys "^1.1.1" + +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2, json5@^2.2.1, json5@^2.2.2, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsonfile@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62" + integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + +jwa@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.2.tgz#16011ac6db48de7b102777e57897901520eec7b9" + integrity sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw== + dependencies: + buffer-equal-constant-time "^1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +keccak@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.4.tgz#edc09b89e633c0549da444432ecf062ffadee86d" + integrity sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +keyvaluestorage-interface@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" + integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +kleur@^4.1.4: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + +lan-network@^0.1.6: + version "0.1.7" + resolved "https://registry.yarnpkg.com/lan-network/-/lan-network-0.1.7.tgz#9fcb9967c6d951f10b2f9a9ffabe4a312d63f69d" + integrity sha512-mnIlAEMu4OyEvUNdzco9xpuB9YVcPkQec+QsgycBCtPZvEqWPCDPfbAE4OJMdBBWpZWtpCn1xw9jJYlwjWI5zQ== + +language-subtag-registry@^0.3.20: + version "0.3.23" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== + +language-tags@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" + integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== + dependencies: + language-subtag-registry "^0.3.20" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +libphonenumber-js@^1.12.8: + version "1.12.26" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.12.26.tgz#f8f5df8d9884a87d39f2a999e3cc8cb735df9dd3" + integrity sha512-MagMOuqEXB2Pa90cWE+BoCmcKJx+de5uBIicaUkQ+uiEslZ0OBMNOkSZT/36syXNHu68UeayTxPm3DYM2IHoLQ== + +lighthouse-logger@^1.0.0: + version "1.4.2" + resolved "https://registry.yarnpkg.com/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz#aef90f9e97cd81db367c7634292ee22079280aaa" + integrity sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g== + dependencies: + debug "^2.6.9" + marky "^1.2.2" + +lightningcss-android-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz#6966b7024d39c94994008b548b71ab360eb3a307" + integrity sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A== + +lightningcss-darwin-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz#a5fa946d27c029e48c7ff929e6e724a7de46eb2c" + integrity sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA== + +lightningcss-darwin-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz#5ce87e9cd7c4f2dcc1b713f5e8ee185c88d9b7cd" + integrity sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ== + +lightningcss-freebsd-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz#6ae1d5e773c97961df5cff57b851807ef33692a5" + integrity sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA== + +lightningcss-linux-arm-gnueabihf@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz#62c489610c0424151a6121fa99d77731536cdaeb" + integrity sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA== + +lightningcss-linux-arm64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz#2a3661b56fe95a0cafae90be026fe0590d089298" + integrity sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A== + +lightningcss-linux-arm64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz#d7ddd6b26959245e026bc1ad9eb6aa983aa90e6b" + integrity sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA== + +lightningcss-linux-x64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz#5a89814c8e63213a5965c3d166dff83c36152b1a" + integrity sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w== + +lightningcss-linux-x64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz#808c2e91ce0bf5d0af0e867c6152e5378c049728" + integrity sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA== + +lightningcss-win32-arm64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz#ab4a8a8a2e6a82a4531e8bbb6bf0ff161ee6625a" + integrity sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ== + +lightningcss-win32-x64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz#f01f382c8e0a27e1c018b0bee316d210eac43b6e" + integrity sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw== + +lightningcss@^1.30.1: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.30.2.tgz#4ade295f25d140f487d37256f4cd40dc607696d0" + integrity sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.30.2" + lightningcss-darwin-arm64 "1.30.2" + lightningcss-darwin-x64 "1.30.2" + lightningcss-freebsd-x64 "1.30.2" + lightningcss-linux-arm-gnueabihf "1.30.2" + lightningcss-linux-arm64-gnu "1.30.2" + lightningcss-linux-arm64-musl "1.30.2" + lightningcss-linux-x64-gnu "1.30.2" + lightningcss-linux-x64-musl "1.30.2" + lightningcss-win32-arm64-msvc "1.30.2" + lightningcss-win32-x64-msvc "1.30.2" + +lilconfig@^3.1.1, lilconfig@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +linked-list@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-2.1.0.tgz#fa7b63a6caf4b17862a1eb90d14ead4ee57649f2" + integrity sha512-0GK/ylO6e5cv1PCOIdTRHxOaCgQ+0jKwHt+cHzkiCAZlx0KM5Id1bBAPad6g2mkvBNp1pNdmG0cohFGfqjkv9A== + +linkify-it@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== + dependencies: + uc.micro "^1.0.1" + +lit-element@^4.2.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.2.2.tgz#f74fcbfbea945eae5614ece22a674fa52ca3365b" + integrity sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.5.0" + "@lit/reactive-element" "^2.1.0" + lit-html "^3.3.0" + +lit-html@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.3.2.tgz#4db11fdbf98fc8a0c5eabd9b1e7d088d3bb201a2" + integrity sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw== + dependencies: + "@types/trusted-types" "^2.0.2" + +lit@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lit/-/lit-3.3.0.tgz#b3037ea94676fb89c3dde9951914efefd0441f17" + integrity sha512-DGVsqsOIHBww2DqnuZzW7QsuCdahp50ojuDaBPC7jUDRpYoH0z7kHBBYZewRzer75FwtrkmkKk7iOAwSaWdBmw== + dependencies: + "@lit/reactive-element" "^2.1.0" + lit-element "^4.2.0" + lit-html "^3.3.0" + +loader-utils@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + +lodash.memoize@4.x, lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.mergewith@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + +lodash@^4, lodash@^4.17.19, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + +long@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" + integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== + +loose-envify@^1.0.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loupe@^3.1.0, loupe@^3.1.4: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" + integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lru-cache@^10.0.1, lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-cache@^11.2.0: + version "11.2.6" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.2.6.tgz#356bf8a29e88a7a2945507b31f6429a65a192c58" + integrity sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lz-string@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + +magic-string@^0.30.17: + version "0.30.21" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@1.x, make-error@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +map-or-similar@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" + integrity sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg== + +markdown-it@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" + integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== + dependencies: + argparse "^1.0.7" + entities "~2.0.0" + linkify-it "^2.0.0" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +marky@^1.2.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/marky/-/marky-1.3.0.tgz#422b63b0baf65022f02eda61a238eccdbbc14997" + integrity sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ== + +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + +md5@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" + integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== + dependencies: + charenc "0.0.2" + crypt "0.0.2" + is-buffer "~1.1.6" + +mdn-data@2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" + integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== + +mdn-data@2.0.28: + version "2.0.28" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.28.tgz#5ec48e7bef120654539069e1ae4ddc81ca490eba" + integrity sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g== + +mdn-data@2.0.30: + version "2.0.30" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.30.tgz#ce4df6f80af6cfbe218ecd5c552ba13c4dfa08cc" + integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +media-typer@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" + integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== + +memoize-one@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e" + integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q== + +memoizerific@^1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" + integrity sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog== + dependencies: + map-or-similar "^1.5.0" + +merge-descriptors@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" + integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== + +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-3.0.4.tgz#84709c2aa2a4b24c1981f66c179fe5565cc6dbb7" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +metro-babel-transformer@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz#ad02ade921dd4ced27b26b18ff31eb60608e3f56" + integrity sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg== + dependencies: + "@babel/core" "^7.20.0" + flow-enums-runtime "^0.0.6" + hermes-parser "0.23.1" + nullthrows "^1.1.1" + +metro-babel-transformer@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.83.2.tgz#d3885f2a266f01e43f16bdcfb786b1d8f1598f56" + integrity sha512-rirY1QMFlA1uxH3ZiNauBninwTioOgwChnRdDcbB4tgRZ+bGX9DiXoh9QdpppiaVKXdJsII932OwWXGGV4+Nlw== + dependencies: + "@babel/core" "^7.25.2" + flow-enums-runtime "^0.0.6" + hermes-parser "0.32.0" + nullthrows "^1.1.1" + +metro-babel-transformer@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-babel-transformer/-/metro-babel-transformer-0.83.3.tgz#d8c134615530c9ee61364526d44ca4bb0c5343ea" + integrity sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g== + dependencies: + "@babel/core" "^7.25.2" + flow-enums-runtime "^0.0.6" + hermes-parser "0.32.0" + nullthrows "^1.1.1" + +metro-cache-key@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.80.12.tgz#52f5de698b85866503ace45d0ad76f75aaec92a4" + integrity sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA== + dependencies: + flow-enums-runtime "^0.0.6" + +metro-cache-key@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.83.2.tgz#b34427fdafe551d567ac312f8a3c7e334a20f796" + integrity sha512-3EMG/GkGKYoTaf5RqguGLSWRqGTwO7NQ0qXKmNBjr0y6qD9s3VBXYlwB+MszGtmOKsqE9q3FPrE5Nd9Ipv7rZw== + dependencies: + flow-enums-runtime "^0.0.6" + +metro-cache-key@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-cache-key/-/metro-cache-key-0.83.3.tgz#ae6c5d4eb1ad8d06a92bf7294ca730a8d880b573" + integrity sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw== + dependencies: + flow-enums-runtime "^0.0.6" + +metro-cache@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.80.12.tgz#bd81af02c4f17b5aeab19bb030566b14147cee8b" + integrity sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA== + dependencies: + exponential-backoff "^3.1.1" + flow-enums-runtime "^0.0.6" + metro-core "0.80.12" + +metro-cache@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.83.2.tgz#d647d9253312801b19c4930be586c60976244540" + integrity sha512-Z43IodutUZeIS7OTH+yQFjc59QlFJ6s5OvM8p2AP9alr0+F8UKr8ADzFzoGKoHefZSKGa4bJx7MZJLF6GwPDHQ== + dependencies: + exponential-backoff "^3.1.1" + flow-enums-runtime "^0.0.6" + https-proxy-agent "^7.0.5" + metro-core "0.83.2" + +metro-cache@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-cache/-/metro-cache-0.83.3.tgz#f1245cc48570c47d8944495e61d67f0228f10172" + integrity sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q== + dependencies: + exponential-backoff "^3.1.1" + flow-enums-runtime "^0.0.6" + https-proxy-agent "^7.0.5" + metro-core "0.83.3" + +metro-config@0.80.12, metro-config@^0.80.9: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.80.12.tgz#1543009f37f7ad26352ffc493fc6305d38bdf1c0" + integrity sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ== + dependencies: + connect "^3.6.5" + cosmiconfig "^5.0.5" + flow-enums-runtime "^0.0.6" + jest-validate "^29.6.3" + metro "0.80.12" + metro-cache "0.80.12" + metro-core "0.80.12" + metro-runtime "0.80.12" + +metro-config@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.83.2.tgz#5ab5eba754c7affd0f3e44be98543aea37c9fab7" + integrity sha512-1FjCcdBe3e3D08gSSiU9u3Vtxd7alGH3x/DNFqWDFf5NouX4kLgbVloDDClr1UrLz62c0fHh2Vfr9ecmrOZp+g== + dependencies: + connect "^3.6.5" + flow-enums-runtime "^0.0.6" + jest-validate "^29.7.0" + metro "0.83.2" + metro-cache "0.83.2" + metro-core "0.83.2" + metro-runtime "0.83.2" + yaml "^2.6.1" + +metro-config@0.83.3, metro-config@^0.83.1: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-config/-/metro-config-0.83.3.tgz#a30e7a69b5cf8c4ac4c4b68b1b4c33649ae129a2" + integrity sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA== + dependencies: + connect "^3.6.5" + flow-enums-runtime "^0.0.6" + jest-validate "^29.7.0" + metro "0.83.3" + metro-cache "0.83.3" + metro-core "0.83.3" + metro-runtime "0.83.3" + yaml "^2.6.1" + +metro-core@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.80.12.tgz#5ae337923ab19ff524077efa1aeacdf4480cfa28" + integrity sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw== + dependencies: + flow-enums-runtime "^0.0.6" + lodash.throttle "^4.1.1" + metro-resolver "0.80.12" + +metro-core@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.83.2.tgz#8b6292482c8cd88bae5f56c5f4903ef7ee292631" + integrity sha512-8DRb0O82Br0IW77cNgKMLYWUkx48lWxUkvNUxVISyMkcNwE/9ywf1MYQUE88HaKwSrqne6kFgCSA/UWZoUT0Iw== + dependencies: + flow-enums-runtime "^0.0.6" + lodash.throttle "^4.1.1" + metro-resolver "0.83.2" + +metro-core@0.83.3, metro-core@^0.83.1: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-core/-/metro-core-0.83.3.tgz#007e93f7d1983777da8988dfb103ad897c9835b8" + integrity sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw== + dependencies: + flow-enums-runtime "^0.0.6" + lodash.throttle "^4.1.1" + metro-resolver "0.83.3" + +metro-file-map@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.80.12.tgz#b03240166a68aa16c5a168c26e190d9da547eefb" + integrity sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw== + dependencies: + anymatch "^3.0.3" + debug "^2.2.0" + fb-watchman "^2.0.0" + flow-enums-runtime "^0.0.6" + graceful-fs "^4.2.4" + invariant "^2.2.4" + jest-worker "^29.6.3" + micromatch "^4.0.4" + node-abort-controller "^3.1.1" + nullthrows "^1.1.1" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +metro-file-map@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.83.2.tgz#8f943d608f27216fde8dd91787294b5a9409752e" + integrity sha512-cMSWnEqZrp/dzZIEd7DEDdk72PXz6w5NOKriJoDN9p1TDQ5nAYrY2lHi8d6mwbcGLoSlWmpPyny9HZYFfPWcGQ== + dependencies: + debug "^4.4.0" + fb-watchman "^2.0.0" + flow-enums-runtime "^0.0.6" + graceful-fs "^4.2.4" + invariant "^2.2.4" + jest-worker "^29.7.0" + micromatch "^4.0.4" + nullthrows "^1.1.1" + walker "^1.0.7" + +metro-file-map@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-file-map/-/metro-file-map-0.83.3.tgz#3d79fbb1d379ab178dd895ce54cb5ecb183d74a2" + integrity sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA== + dependencies: + debug "^4.4.0" + fb-watchman "^2.0.0" + flow-enums-runtime "^0.0.6" + graceful-fs "^4.2.4" + invariant "^2.2.4" + jest-worker "^29.7.0" + micromatch "^4.0.4" + nullthrows "^1.1.1" + walker "^1.0.7" + +metro-minify-terser@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz#9951030e3bc52d7f3ac8664ce5862401c673e3c6" + integrity sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ== + dependencies: + flow-enums-runtime "^0.0.6" + terser "^5.15.0" + +metro-minify-terser@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.83.2.tgz#17ea8aef987970f8505ed8f890ab00c47c419608" + integrity sha512-zvIxnh7U0JQ7vT4quasKsijId3dOAWgq+ip2jF/8TMrPUqQabGrs04L2dd0haQJ+PA+d4VvK/bPOY8X/vL2PWw== + dependencies: + flow-enums-runtime "^0.0.6" + terser "^5.15.0" + +metro-minify-terser@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-minify-terser/-/metro-minify-terser-0.83.3.tgz#c1c70929c86b14c8bf03e6321b4f9310bc8dbe87" + integrity sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ== + dependencies: + flow-enums-runtime "^0.0.6" + terser "^5.15.0" + +metro-resolver@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.80.12.tgz#e3815914c21315b04db200032c3243a4cc22dfb6" + integrity sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw== + dependencies: + flow-enums-runtime "^0.0.6" + +metro-resolver@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.83.2.tgz#d4a40a602615baacfb94d8a773e8b93eaac70d0f" + integrity sha512-Yf5mjyuiRE/Y+KvqfsZxrbHDA15NZxyfg8pIk0qg47LfAJhpMVEX+36e6ZRBq7KVBqy6VDX5Sq55iHGM4xSm7Q== + dependencies: + flow-enums-runtime "^0.0.6" + +metro-resolver@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-resolver/-/metro-resolver-0.83.3.tgz#06207bdddc280b9335722a8c992aeec017413942" + integrity sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ== + dependencies: + flow-enums-runtime "^0.0.6" + +metro-runtime@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.80.12.tgz#a68af3a2a013f5372d3b8cee234fdd467455550b" + integrity sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw== + dependencies: + "@babel/runtime" "^7.25.0" + flow-enums-runtime "^0.0.6" + +metro-runtime@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.83.2.tgz#77c9715483fd3d449407435c1c160f7410c588d7" + integrity sha512-nnsPtgRvFbNKwemqs0FuyFDzXLl+ezuFsUXDbX8o0SXOfsOPijqiQrf3kuafO1Zx1aUWf4NOrKJMAQP5EEHg9A== + dependencies: + "@babel/runtime" "^7.25.0" + flow-enums-runtime "^0.0.6" + +metro-runtime@0.83.3, metro-runtime@^0.83.1: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-runtime/-/metro-runtime-0.83.3.tgz#ff504df5d93f38b1af396715b327e589ba8d184d" + integrity sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw== + dependencies: + "@babel/runtime" "^7.25.0" + flow-enums-runtime "^0.0.6" + +metro-source-map@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.80.12.tgz#36a2768c880f8c459d6d758e2d0975e36479f49c" + integrity sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw== + dependencies: + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" + flow-enums-runtime "^0.0.6" + invariant "^2.2.4" + metro-symbolicate "0.80.12" + nullthrows "^1.1.1" + ob1 "0.80.12" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-source-map@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.83.2.tgz#5688eeb3fc85a1ca0f5f5efede2257a872e2b9fe" + integrity sha512-5FL/6BSQvshIKjXOennt9upFngq2lFvDakZn5LfauIVq8+L4sxXewIlSTcxAtzbtjAIaXeOSVMtCJ5DdfCt9AA== + dependencies: + "@babel/traverse" "^7.25.3" + "@babel/traverse--for-generate-function-map" "npm:@babel/traverse@^7.25.3" + "@babel/types" "^7.25.2" + flow-enums-runtime "^0.0.6" + invariant "^2.2.4" + metro-symbolicate "0.83.2" + nullthrows "^1.1.1" + ob1 "0.83.2" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-source-map@0.83.3, metro-source-map@^0.83.1: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-source-map/-/metro-source-map-0.83.3.tgz#04bb464f7928ea48bcdfd18912c8607cf317c898" + integrity sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg== + dependencies: + "@babel/traverse" "^7.25.3" + "@babel/traverse--for-generate-function-map" "npm:@babel/traverse@^7.25.3" + "@babel/types" "^7.25.2" + flow-enums-runtime "^0.0.6" + invariant "^2.2.4" + metro-symbolicate "0.83.3" + nullthrows "^1.1.1" + ob1 "0.83.3" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-symbolicate@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz#3a6aa783c6e494e2879342d88d5379fab69d1ed2" + integrity sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw== + dependencies: + flow-enums-runtime "^0.0.6" + invariant "^2.2.4" + metro-source-map "0.80.12" + nullthrows "^1.1.1" + source-map "^0.5.6" + through2 "^2.0.1" + vlq "^1.0.0" + +metro-symbolicate@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.83.2.tgz#63a5f31cdb6db17371a00d259890643d84a75549" + integrity sha512-KoU9BLwxxED6n33KYuQQuc5bXkIxF3fSwlc3ouxrrdLWwhu64muYZNQrukkWzhVKRNFIXW7X2iM8JXpi2heIPw== + dependencies: + flow-enums-runtime "^0.0.6" + invariant "^2.2.4" + metro-source-map "0.83.2" + nullthrows "^1.1.1" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-symbolicate@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-symbolicate/-/metro-symbolicate-0.83.3.tgz#67af03950f0dfe19a7c059e3983e39a31e95d03a" + integrity sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw== + dependencies: + flow-enums-runtime "^0.0.6" + invariant "^2.2.4" + metro-source-map "0.83.3" + nullthrows "^1.1.1" + source-map "^0.5.6" + vlq "^1.0.0" + +metro-transform-plugins@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz#4a3853630ad0f36cc2bffd53bae659ee171a389c" + integrity sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA== + dependencies: + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.20.0" + flow-enums-runtime "^0.0.6" + nullthrows "^1.1.1" + +metro-transform-plugins@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.83.2.tgz#c4353147212cad1c76dcea8fd93c7f0c7b09b3a4" + integrity sha512-5WlW25WKPkiJk2yA9d8bMuZrgW7vfA4f4MBb9ZeHbTB3eIAoNN8vS8NENgG/X/90vpTB06X66OBvxhT3nHwP6A== + dependencies: + "@babel/core" "^7.25.2" + "@babel/generator" "^7.25.0" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.3" + flow-enums-runtime "^0.0.6" + nullthrows "^1.1.1" + +metro-transform-plugins@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-transform-plugins/-/metro-transform-plugins-0.83.3.tgz#2c59ba841e269363cf3acb13138cb992f0c75013" + integrity sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A== + dependencies: + "@babel/core" "^7.25.2" + "@babel/generator" "^7.25.0" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.3" + flow-enums-runtime "^0.0.6" + nullthrows "^1.1.1" + +metro-transform-worker@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz#80be8a185b7deb93402b682f58a1dd6724317ad1" + integrity sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA== + dependencies: + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" + "@babel/types" "^7.20.0" + flow-enums-runtime "^0.0.6" + metro "0.80.12" + metro-babel-transformer "0.80.12" + metro-cache "0.80.12" + metro-cache-key "0.80.12" + metro-minify-terser "0.80.12" + metro-source-map "0.80.12" + metro-transform-plugins "0.80.12" + nullthrows "^1.1.1" + +metro-transform-worker@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.83.2.tgz#f97367b6384be87ea216a97072810705c19c3775" + integrity sha512-G5DsIg+cMZ2KNfrdLnWMvtppb3+Rp1GMyj7Bvd9GgYc/8gRmvq1XVEF9XuO87Shhb03kFhGqMTgZerz3hZ1v4Q== + dependencies: + "@babel/core" "^7.25.2" + "@babel/generator" "^7.25.0" + "@babel/parser" "^7.25.3" + "@babel/types" "^7.25.2" + flow-enums-runtime "^0.0.6" + metro "0.83.2" + metro-babel-transformer "0.83.2" + metro-cache "0.83.2" + metro-cache-key "0.83.2" + metro-minify-terser "0.83.2" + metro-source-map "0.83.2" + metro-transform-plugins "0.83.2" + nullthrows "^1.1.1" + +metro-transform-worker@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro-transform-worker/-/metro-transform-worker-0.83.3.tgz#ca6ae4a02b0f61b33299e6e56bacaba32dcd607f" + integrity sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA== + dependencies: + "@babel/core" "^7.25.2" + "@babel/generator" "^7.25.0" + "@babel/parser" "^7.25.3" + "@babel/types" "^7.25.2" + flow-enums-runtime "^0.0.6" + metro "0.83.3" + metro-babel-transformer "0.83.3" + metro-cache "0.83.3" + metro-cache-key "0.83.3" + metro-minify-terser "0.83.3" + metro-source-map "0.83.3" + metro-transform-plugins "0.83.3" + nullthrows "^1.1.1" + +metro@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.80.12.tgz#29a61fb83581a71e50c4d8d5d8458270edfe34cc" + integrity sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/core" "^7.20.0" + "@babel/generator" "^7.20.0" + "@babel/parser" "^7.20.0" + "@babel/template" "^7.0.0" + "@babel/traverse" "^7.20.0" + "@babel/types" "^7.20.0" + accepts "^1.3.7" + chalk "^4.0.0" + ci-info "^2.0.0" + connect "^3.6.5" + debug "^2.2.0" + denodeify "^1.2.1" + error-stack-parser "^2.0.6" + flow-enums-runtime "^0.0.6" + graceful-fs "^4.2.4" + hermes-parser "0.23.1" + image-size "^1.0.2" + invariant "^2.2.4" + jest-worker "^29.6.3" + jsc-safe-url "^0.2.2" + lodash.throttle "^4.1.1" + metro-babel-transformer "0.80.12" + metro-cache "0.80.12" + metro-cache-key "0.80.12" + metro-config "0.80.12" + metro-core "0.80.12" + metro-file-map "0.80.12" + metro-resolver "0.80.12" + metro-runtime "0.80.12" + metro-source-map "0.80.12" + metro-symbolicate "0.80.12" + metro-transform-plugins "0.80.12" + metro-transform-worker "0.80.12" + mime-types "^2.1.27" + nullthrows "^1.1.1" + serialize-error "^2.1.0" + source-map "^0.5.6" + strip-ansi "^6.0.0" + throat "^5.0.0" + ws "^7.5.10" + yargs "^17.6.2" + +metro@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.83.2.tgz#a56d31a604819951c8b9cf19d570897341e29b07" + integrity sha512-HQgs9H1FyVbRptNSMy/ImchTTE5vS2MSqLoOo7hbDoBq6hPPZokwJvBMwrYSxdjQZmLXz2JFZtdvS+ZfgTc9yw== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/core" "^7.25.2" + "@babel/generator" "^7.25.0" + "@babel/parser" "^7.25.3" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.3" + "@babel/types" "^7.25.2" + accepts "^1.3.7" + chalk "^4.0.0" + ci-info "^2.0.0" + connect "^3.6.5" + debug "^4.4.0" + error-stack-parser "^2.0.6" + flow-enums-runtime "^0.0.6" + graceful-fs "^4.2.4" + hermes-parser "0.32.0" + image-size "^1.0.2" + invariant "^2.2.4" + jest-worker "^29.7.0" + jsc-safe-url "^0.2.2" + lodash.throttle "^4.1.1" + metro-babel-transformer "0.83.2" + metro-cache "0.83.2" + metro-cache-key "0.83.2" + metro-config "0.83.2" + metro-core "0.83.2" + metro-file-map "0.83.2" + metro-resolver "0.83.2" + metro-runtime "0.83.2" + metro-source-map "0.83.2" + metro-symbolicate "0.83.2" + metro-transform-plugins "0.83.2" + metro-transform-worker "0.83.2" + mime-types "^2.1.27" + nullthrows "^1.1.1" + serialize-error "^2.1.0" + source-map "^0.5.6" + throat "^5.0.0" + ws "^7.5.10" + yargs "^17.6.2" + +metro@0.83.3, metro@^0.83.1: + version "0.83.3" + resolved "https://registry.yarnpkg.com/metro/-/metro-0.83.3.tgz#1e7e04c15519af746f8932c7f9c553d92c39e922" + integrity sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/core" "^7.25.2" + "@babel/generator" "^7.25.0" + "@babel/parser" "^7.25.3" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.3" + "@babel/types" "^7.25.2" + accepts "^1.3.7" + chalk "^4.0.0" + ci-info "^2.0.0" + connect "^3.6.5" + debug "^4.4.0" + error-stack-parser "^2.0.6" + flow-enums-runtime "^0.0.6" + graceful-fs "^4.2.4" + hermes-parser "0.32.0" + image-size "^1.0.2" + invariant "^2.2.4" + jest-worker "^29.7.0" + jsc-safe-url "^0.2.2" + lodash.throttle "^4.1.1" + metro-babel-transformer "0.83.3" + metro-cache "0.83.3" + metro-cache-key "0.83.3" + metro-config "0.83.3" + metro-core "0.83.3" + metro-file-map "0.83.3" + metro-resolver "0.83.3" + metro-runtime "0.83.3" + metro-source-map "0.83.3" + metro-symbolicate "0.83.3" + metro-transform-plugins "0.83.3" + metro-transform-worker "0.83.3" + mime-types "^2.1.27" + nullthrows "^1.1.1" + serialize-error "^2.1.0" + source-map "^0.5.6" + throat "^5.0.0" + ws "^7.5.10" + yargs "^17.6.2" + +micro-ftch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" + integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== + +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +"mime-db@>= 1.43.0 < 2", mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime-types@^3.0.0, mime-types@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.1.tgz#b1d94d6997a9b32fd69ebaed0db73de8acb519ce" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^8.0.2: + version "8.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" + integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.0, minimatch@^9.0.3, minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^4.2.4: + version "4.2.8" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" + integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +minizlib@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.1.0.tgz#6ad76c3a8f10227c9b51d1c9ac8e30b27f5a251c" + integrity sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw== + dependencies: + minipass "^7.1.2" + +mipd@0.0.7, mipd@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mipd/-/mipd-0.0.7.tgz#bb5559e21fa18dc3d9fe1c08902ef14b7ce32fd9" + integrity sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg== + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +motion-dom@^11.18.1: + version "11.18.1" + resolved "https://registry.yarnpkg.com/motion-dom/-/motion-dom-11.18.1.tgz#e7fed7b7dc6ae1223ef1cce29ee54bec826dc3f2" + integrity sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw== + dependencies: + motion-utils "^11.18.1" + +motion-utils@^11.18.1: + version "11.18.1" + resolved "https://registry.yarnpkg.com/motion-utils/-/motion-utils-11.18.1.tgz#671227669833e991c55813cf337899f41327db5b" + integrity sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multiformats@^9.4.2: + version "9.9.0" + resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" + integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== + +mz@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanoid@^3.1.23, nanoid@^3.3.1, nanoid@^3.3.11, nanoid@^3.3.6, nanoid@^3.3.7: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +nanoid@^5.1.2: + version "5.1.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-5.1.6.tgz#30363f664797e7d40429f6c16946d6bd7a3f26c9" + integrity sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg== + +napi-postinstall@^0.3.0: + version "0.3.4" + resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.4.tgz#7af256d6588b5f8e952b9190965d6b019653bbb9" + integrity sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + +negotiator@~0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + +neo-async@^2.6.1, neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nested-error-stacks@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.0.1.tgz#d2cc9fc5235ddb371fc44d506234339c8e4b0a4b" + integrity sha512-SrQrok4CATudVzBS7coSz26QRSmlK9TzzoFbeKfcPBUFPjcQM9Rqvr/DlJkOrwI/0KcgvMub1n1g5Jt9EgRn4A== + +next@14.2.35: + version "14.2.35" + resolved "https://registry.yarnpkg.com/next/-/next-14.2.35.tgz#7c68873a15fe5a19401f2f993fea535be3366ee9" + integrity sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig== + dependencies: + "@next/env" "14.2.35" + "@swc/helpers" "0.5.5" + busboy "1.6.0" + caniuse-lite "^1.0.30001579" + graceful-fs "^4.2.11" + postcss "8.4.31" + styled-jsx "5.1.1" + optionalDependencies: + "@next/swc-darwin-arm64" "14.2.33" + "@next/swc-darwin-x64" "14.2.33" + "@next/swc-linux-arm64-gnu" "14.2.33" + "@next/swc-linux-arm64-musl" "14.2.33" + "@next/swc-linux-x64-gnu" "14.2.33" + "@next/swc-linux-x64-musl" "14.2.33" + "@next/swc-win32-arm64-msvc" "14.2.33" + "@next/swc-win32-ia32-msvc" "14.2.33" + "@next/swc-win32-x64-msvc" "14.2.33" + +next@15.5.9: + version "15.5.9" + resolved "https://registry.yarnpkg.com/next/-/next-15.5.9.tgz#1b80d05865cc27e710fb4dcfc6fd9e726ed12ad4" + integrity sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg== + dependencies: + "@next/env" "15.5.9" + "@swc/helpers" "0.5.15" + caniuse-lite "^1.0.30001579" + postcss "8.4.31" + styled-jsx "5.1.6" + optionalDependencies: + "@next/swc-darwin-arm64" "15.5.7" + "@next/swc-darwin-x64" "15.5.7" + "@next/swc-linux-arm64-gnu" "15.5.7" + "@next/swc-linux-arm64-musl" "15.5.7" + "@next/swc-linux-x64-gnu" "15.5.7" + "@next/swc-linux-x64-musl" "15.5.7" + "@next/swc-win32-arm64-msvc" "15.5.7" + "@next/swc-win32-x64-msvc" "15.5.7" + sharp "^0.34.3" + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-abort-controller@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" + integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + +node-fetch-native@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.7.tgz#9d09ca63066cc48423211ed4caf5d70075d76a71" + integrity sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q== + +node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1.2.1, node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.8.4" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" + integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-mock-http@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/node-mock-http/-/node-mock-http-1.0.4.tgz#21f2ab4ce2fe4fbe8a660d7c5195a1db85e042a4" + integrity sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ== + +node-releases@^2.0.27: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== + +normalize-css-color@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/normalize-css-color/-/normalize-css-color-1.0.2.tgz#02991e97cccec6623fe573afbbf0de6a1f3e9f8d" + integrity sha512-jPJ/V7Cp1UytdidsPqviKEElFQJs22hUUgK5BOPHTwOonNCk7/2qOxhhqzEajmFrWJowADFfOFh1V+aWkRfy+w== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-package-arg@^11.0.0: + version "11.0.3" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-11.0.3.tgz#dae0c21199a99feca39ee4bfb074df3adac87e2d" + integrity sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw== + dependencies: + hosted-git-info "^7.0.0" + proc-log "^4.0.0" + semver "^7.3.5" + validate-npm-package-name "^5.0.0" + +npm-run-path@^4.0.0, npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +nwsapi@^2.2.2: + version "2.2.22" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.22.tgz#109f9530cda6c156d6a713cdf5939e9f0de98b9d" + integrity sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ== + +ob1@0.80.12: + version "0.80.12" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.80.12.tgz#0451944ba6e5be225cc9751d8cd0d7309d2d1537" + integrity sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw== + dependencies: + flow-enums-runtime "^0.0.6" + +ob1@0.83.2: + version "0.83.2" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.83.2.tgz#23c2e58b7d542fb01e627049710334d14c287cf8" + integrity sha512-XlK3w4M+dwd1g1gvHzVbxiXEbUllRONEgcF2uEO0zm4nxa0eKlh41c6N65q1xbiDOeKKda1tvNOAD33fNjyvCg== + dependencies: + flow-enums-runtime "^0.0.6" + +ob1@0.83.3: + version "0.83.3" + resolved "https://registry.yarnpkg.com/ob1/-/ob1-0.83.3.tgz#2208e20c9070e9beff3ad067f2db458fa6b07014" + integrity sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA== + dependencies: + flow-enums-runtime "^0.0.6" + +obj-multiplex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/obj-multiplex/-/obj-multiplex-1.0.0.tgz#2f2ae6bfd4ae11befe742ea9ea5b36636eabffc1" + integrity sha512-0GNJAOsHoBHeNTvl5Vt6IWnpUEcc3uSRxzBri7EDyIcMgYvnY2JL2qdeV5zTMjWQX5OHcD5amcW2HFfDh0gjIA== + dependencies: + end-of-stream "^1.4.0" + once "^1.4.0" + readable-stream "^2.3.3" + +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" + integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== + +object-inspect@^1.13.3, object-inspect@^1.13.4: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.0, object.assign@^4.1.4, object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" + object-keys "^1.1.1" + +object.entries@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.9.tgz#e4770a6a1444afb61bd39f984018b5bede25f8b3" + integrity sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.4" + define-properties "^1.2.1" + es-object-atoms "^1.1.1" + +object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.groupby@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" + integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + +object.values@^1.1.6, object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +ofetch@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.5.1.tgz#5c43cc56e03398b273014957060344254505c5c7" + integrity sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA== + dependencies: + destr "^2.0.5" + node-fetch-native "^1.6.7" + ufo "^1.6.1" + +on-exit-leak-free@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" + integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== + +on-finished@2.4.1, on-finished@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== + dependencies: + ee-first "1.1.1" + +on-headers@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65" + integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ== + dependencies: + mimic-fn "^1.0.0" + +onetime@^5.1.0, onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^7.0.3, open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +open@^8.0.4: + version "8.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +openapi-fetch@^0.13.5: + version "0.13.8" + resolved "https://registry.yarnpkg.com/openapi-fetch/-/openapi-fetch-0.13.8.tgz#1769da06e30d19f7568cd0e60db8ca61ea83a2fa" + integrity sha512-yJ4QKRyNxE44baQ9mY5+r/kAzZ8yXMemtNAOFwOzRXJscdjSxxzWSNlyBAr+o5JjkUw9Lc3W7OIoca0cY3PYnQ== + dependencies: + openapi-typescript-helpers "^0.0.15" + +openapi-typescript-helpers@^0.0.15: + version "0.0.15" + resolved "https://registry.yarnpkg.com/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.15.tgz#96ffa762a5e01ef66a661b163d5f1109ed1967ed" + integrity sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw== + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +ora@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-3.4.0.tgz#bf0752491059a3ef3ed4c85097531de9fdbcd318" + integrity sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg== + dependencies: + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-spinners "^2.0.0" + log-symbols "^2.2.0" + strip-ansi "^5.2.0" + wcwidth "^1.0.1" + +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + +ox@0.12.4: + version "0.12.4" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.12.4.tgz#469a1b3cfb033d92bc615567875942173a2ddeb5" + integrity sha512-+P+C7QzuwPV8lu79dOwjBKfB2CbnbEXe/hfyyrff1drrO1nOOj3Hc87svHfcW1yneRr3WXaKr6nz11nq+/DF9Q== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.2.3" + eventemitter3 "5.0.1" + +ox@0.6.7: + version "0.6.7" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.7.tgz#afd53f2ecef68b8526660e9d29dee6e6b599a832" + integrity sha512-17Gk/eFsFRAZ80p5eKqv89a57uXjd3NgIf1CaXojATPBuujVc/fQSVhBeAU9JCRB+k7J50WQAyWTxK19T9GgbA== + dependencies: + "@adraffy/ens-normalize" "^1.10.1" + "@noble/curves" "^1.6.0" + "@noble/hashes" "^1.5.0" + "@scure/bip32" "^1.5.0" + "@scure/bip39" "^1.4.0" + abitype "^1.0.6" + eventemitter3 "5.0.1" + +ox@0.6.9: + version "0.6.9" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.6.9.tgz#da1ee04fa10de30c8d04c15bfb80fe58b1f554bd" + integrity sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug== + dependencies: + "@adraffy/ens-normalize" "^1.10.1" + "@noble/curves" "^1.6.0" + "@noble/hashes" "^1.5.0" + "@scure/bip32" "^1.5.0" + "@scure/bip39" "^1.4.0" + abitype "^1.0.6" + eventemitter3 "5.0.1" + +ox@^0.9.6: + version "0.9.17" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.9.17.tgz#2397301db419664602853ca292524805ec0df5c3" + integrity sha512-rKAnhzhRU3Xh3hiko+i1ZxywZ55eWQzeS/Q4HRKLx2PqfHOolisZHErSsJVipGlmQKHW5qwOED/GighEw9dbLg== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.0.9" + eventemitter3 "5.0.1" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +pako@^1.0.10, pako@^1.0.11, pako@^1.0.6: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw== + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-json@^5.0.0, parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-png@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/parse-png/-/parse-png-2.1.0.tgz#2a42ad719fedf90f81c59ebee7ae59b280d6b338" + integrity sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ== + dependencies: + pngjs "^3.3.0" + +parse5@^7.0.0, parse5@^7.1.1: + version "7.3.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" + integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== + dependencies: + entities "^6.0.0" + +parseurl@^1.3.3, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +patch-package@^8.0.0: + version "8.0.1" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.1.tgz#79d02f953f711e06d1f8949c8a13e5d3d7ba1a60" + integrity sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^4.1.2" + ci-info "^3.7.0" + cross-spawn "^7.0.3" + find-yarn-workspace-root "^2.0.0" + fs-extra "^10.0.0" + json-stable-stringify "^1.0.2" + klaw-sync "^6.0.0" + minimist "^1.2.6" + open "^7.4.2" + semver "^7.5.3" + slash "^2.0.0" + tmp "^0.2.4" + yaml "^2.2.2" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.5, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^1.11.1, path-scurry@^1.6.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +path-to-regexp@^8.0.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f" + integrity sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathval@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d" + integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ== + +pdf-lib@^1.17.1: + version "1.17.1" + resolved "https://registry.yarnpkg.com/pdf-lib/-/pdf-lib-1.17.1.tgz#9e7dd21261a0c1fb17992580885b39e7d08f451f" + integrity sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw== + dependencies: + "@pdf-lib/standard-fonts" "^1.0.0" + "@pdf-lib/upng" "^1.0.1" + pako "^1.0.11" + tslib "^1.11.1" + +picocolors@1.1.1, picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-3.0.1.tgz#817033161def55ec9638567a2f3bbc876b3e7516" + integrity sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag== + +picomatch@^4.0.2, picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" + integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA== + +pino-abstract-transport@v0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0" + integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ== + dependencies: + duplexify "^4.1.2" + split2 "^4.0.0" + +pino-std-serializers@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2" + integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q== + +pino@7.11.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6" + integrity sha512-dMACeu63HtRLmCG8VKdy4cShCPKaYDR4youZqoSWLxl5Gu99HUw8bw75thbPv9Nip+H+QYX8o3ZJbTdVZZ2TVg== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.0.0" + on-exit-leak-free "^0.2.0" + pino-abstract-transport v0.5.0 + pino-std-serializers "^4.0.0" + process-warning "^1.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.1.0" + safe-stable-stringify "^2.1.0" + sonic-boom "^2.2.1" + thread-stream "^0.15.1" + +pirates@^4.0.1, pirates@^4.0.4, pirates@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" + integrity sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA== + +pkce-challenge@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkce-challenge/-/pkce-challenge-5.0.0.tgz#c3a405cb49e272094a38e890a2b51da0228c4d97" + integrity sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ== + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + +plist@^3.0.5: + version "3.1.0" + resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9" + integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== + dependencies: + "@xmldom/xmldom" "^0.8.8" + base64-js "^1.5.1" + xmlbuilder "^15.1.1" + +pngjs@^3.3.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== + +pngjs@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" + integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== + +polished@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.3.1.tgz#5a00ae32715609f83d89f6f31d0f0261c6170548" + integrity sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA== + dependencies: + "@babel/runtime" "^7.17.8" + +pony-cause@^2.1.10: + version "2.1.11" + resolved "https://registry.yarnpkg.com/pony-cause/-/pony-cause-2.1.11.tgz#d69a20aaccdb3bdb8f74dd59e5c68d8e6772e4bd" + integrity sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg== + +porto@0.2.35: + version "0.2.35" + resolved "https://registry.yarnpkg.com/porto/-/porto-0.2.35.tgz#7e926bf1434283fda9581cc10ed203b16b41d175" + integrity sha512-gu9FfjjvvYBgQXUHWTp6n3wkTxVtEcqFotM7i3GEZeoQbvLGbssAicCz6hFZ8+xggrJWwi/RLmbwNra50SMmUQ== + dependencies: + hono "^4.10.3" + idb-keyval "^6.2.1" + mipd "^0.0.7" + ox "^0.9.6" + zod "^4.1.5" + zustand "^5.0.1" + +possible-typed-array-names@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== + +postcss-import@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70" + integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew== + dependencies: + postcss-value-parser "^4.0.0" + read-cache "^1.0.0" + resolve "^1.1.7" + +postcss-js@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.1.0.tgz#003b63c6edde948766e40f3daf7e997ae43a5ce6" + integrity sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw== + dependencies: + camelcase-css "^2.0.1" + +"postcss-load-config@^4.0.2 || ^5.0 || ^6.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz#6fd7dcd8ae89badcf1b2d644489cbabf83aa8096" + integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== + dependencies: + lilconfig "^3.1.1" + +postcss-nested@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.2.0.tgz#4c2d22ab5f20b9cb61e2c5c5915950784d068131" + integrity sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ== + dependencies: + postcss-selector-parser "^6.1.1" + +postcss-selector-parser@^6.1.1, postcss-selector-parser@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz#27ecb41fb0e3b6ba7a1ec84fff347f734c7929de" + integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@8.4.31: + version "8.4.31" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d" + integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +postcss@^8.4.43, postcss@^8.4.47: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +postcss@~8.4.32: + version "8.4.49" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.49.tgz#4ea479048ab059ab3ae61d082190fabfd994fe19" + integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== + dependencies: + nanoid "^3.3.7" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +posthog-js@^1.256.0: + version "1.290.0" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.290.0.tgz#4181f0a56e7f4f0150d56bc8c783aaabb5297aa9" + integrity sha512-zavBwZkf+3JeiSDVE7ZDXBfzva/iOljicdhdJH+cZoqp0LsxjKxjnNhGOd3KpAhw0wqdwjhd7Lp1aJuI7DXyaw== + dependencies: + "@posthog/core" "1.5.2" + core-js "^3.38.1" + fflate "^0.4.8" + preact "^10.19.3" + web-vitals "^4.2.4" + +posthog-react-native-session-replay@^1.0.5: + version "1.2.1" + resolved "https://registry.yarnpkg.com/posthog-react-native-session-replay/-/posthog-react-native-session-replay-1.2.1.tgz#ab5d4f198a6307242ac6e11c179cd155b6473bb7" + integrity sha512-PGWeBPmHoBtiWWmHQzbPuCrp8JWJOXJSq3NfFTHZe/eabdgAc8wOvsn7APMFBbVAk7l5HglPuhwYMB3oHWzzEg== + +posthog-react-native@^3.12.0: + version "3.16.1" + resolved "https://registry.yarnpkg.com/posthog-react-native/-/posthog-react-native-3.16.1.tgz#6f346295e68582b670ef0722014e935cfd9013a0" + integrity sha512-qrsQC552nY9emZbv2HmnPfckS1waFf5kG1LLGF1noUhgXWzNfLfwK20FIypjRR50O+j/vCFIzQBmoy4Sv/U2RA== + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +preact@10.24.2: + version "10.24.2" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.24.2.tgz#42179771d3b06e7adb884e3f8127ddd3d99b78f6" + integrity sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q== + +preact@^10.16.0: + version "10.28.4" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.28.4.tgz#8ffab01c5c0590535bdaecdd548801f44c6e483a" + integrity sha512-uKFfOHWuSNpRFVTnljsCluEFq57OKT+0QdOiQo8XWnQ/pSvg7OpX5eNOejELXJMWy+BwM2nobz0FkvzmnpCNsQ== + +preact@^10.19.3: + version "10.27.2" + resolved "https://registry.yarnpkg.com/preact/-/preact-10.27.2.tgz#19b9009c1be801a76a0aaf0fe5ba665985a09312" + integrity sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" + integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== + +pretty-bytes@^5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" + integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== + +pretty-format@30.2.0, pretty-format@^30.0.0, pretty-format@^30.0.5: + version "30.2.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-30.2.0.tgz#2d44fe6134529aed18506f6d11509d8a62775ebe" + integrity sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA== + dependencies: + "@jest/schemas" "30.0.5" + ansi-styles "^5.2.0" + react-is "^18.3.1" + +pretty-format@^27.0.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +proc-log@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-4.2.0.tgz#b6f461e4026e75fdfe228b265e9f7a00779d7034" + integrity sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-warning@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +progress@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a" + integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg== + dependencies: + asap "~2.0.6" + +prompts@^2.0.1, prompts@^2.2.1, prompts@^2.3.2, prompts@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@15.x, prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +protobufjs@^7.2.5: + version "7.5.4" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.5.4.tgz#885d31fe9c4b37f25d1bb600da30b1c5b37d286a" + integrity sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + +proxy-addr@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +proxy-compare@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.6.0.tgz#5e8c8b5c3af7e7f17e839bf6cf1435bcc4d315b0" + integrity sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +psl@^1.1.33: + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" + +pump@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" + integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +pure-rand@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== + +pure-rand@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-7.0.1.tgz#6f53a5a9e3e4a47445822af96821ca509ed37566" + integrity sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ== + +qr.js@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" + integrity sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ== + +qrcode-terminal@0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.11.0.tgz#ffc6c28a2fc0bfb47052b47e23f4f446a5fbdb9e" + integrity sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ== + +qrcode.react@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-3.2.0.tgz#97daabd4ff641a3f3c678f87be106ebc55f9cd07" + integrity sha512-YietHHltOHA4+l5na1srdaMx4sVSOjV9tamHs+mwiLWAMr6QVACRUw1Neax5CptFILcNoITctJY0Ipyn5enQ8g== + +qrcode@1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" + integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== + dependencies: + dijkstrajs "^1.0.1" + encode-utf8 "^1.0.3" + pngjs "^5.0.0" + yargs "^15.3.1" + +qs@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + +query-string@7.1.3, query-string@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" + integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +queue@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" + integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== + dependencies: + inherits "~2.0.3" + +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +radix3@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.2.tgz#fd27d2af3896c6bf4bcdfab6427c69c2afc69ec0" + integrity sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.1.tgz#ced5cd79a77bbb0496d707f2a0f9e1ae3aecdcb1" + integrity sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.7.0" + unpipe "1.0.0" + +rc@~1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-async-hook@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/react-async-hook/-/react-async-hook-4.0.0.tgz#1f0467586654e1f33b7433bd98c300a0c5f9b3d0" + integrity sha512-97lgjFkOcHCTYSrsKBpsXg3iVWM0LnzedB749iP76sb3/8Ouu4nHIkCLEOrQWHVYqrYxjF05NN6GHoXWFkB3Kw== + +react-chartjs-2@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-5.3.1.tgz#2b29995ce8b07f5c95c6ea3696838569e88453aa" + integrity sha512-h5IPXKg9EXpjoBzUfyWJvllMjG2mQ4EiuHQFhms/AjUm0XSZHhyRy2xVmLXHKrtcdrPO4mnGqRtYoD0vp95A0A== + +react-clientside-effect@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.8.tgz#0b90a9d7b2a1823a3a10ed1ea3f651f7e0301cb7" + integrity sha512-ma2FePH0z3px2+WOu6h+YycZcEvFmmxIlAb62cF52bG86eMySciO/EQZeQMXd07kPCYB0a1dWDT5J+KE9mCDUw== + dependencies: + "@babel/runtime" "^7.12.13" + +react-devtools-core@^6.1.5: + version "6.1.5" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-6.1.5.tgz#c5eca79209dab853a03b2158c034c5166975feee" + integrity sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA== + dependencies: + shell-quote "^1.6.1" + ws "^7" + +react-dom@19.1.0, react-dom@^18, react-dom@^19.1.0: + version "19.1.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623" + integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g== + dependencies: + scheduler "^0.26.0" + +react-draggable@^4.0.3: + version "4.5.0" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.5.0.tgz#0b274ccb6965fcf97ed38fcf7e3cc223bc48cdf5" + integrity sha512-VC+HBLEZ0XJxnOxVAZsdRi8rD04Iz3SiiKOoYzamjylUcju/hP9np/aZdLHf/7WOD268WMoNJMvYfB5yAK45cw== + dependencies: + clsx "^2.1.1" + prop-types "^15.8.1" + +react-fast-compare@3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49" + integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ== + +react-firebase-hooks@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/react-firebase-hooks/-/react-firebase-hooks-5.1.1.tgz#fc92bb4b860c6753c806583f64d7f069b6ee6785" + integrity sha512-y2UpWs82xs+39q5Rc/wq316ca52QsC0n8m801V+yM4IC4hbfOL4yQPVSh7w+ydstdvjN9F+lvs1WrO2VYxpmdA== + +react-focus-lock@^2.9.6: + version "2.13.6" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.13.6.tgz#29751bf2e4e30f6248673cd87a347c74ff2af672" + integrity sha512-ehylFFWyYtBKXjAO9+3v8d0i+cnc1trGS0vlTGhzFW1vbFXVUTmR8s2tt/ZQG8x5hElg6rhENlLG1H3EZK0Llg== + dependencies: + "@babel/runtime" "^7.0.0" + focus-lock "^1.3.6" + prop-types "^15.6.2" + react-clientside-effect "^1.2.7" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" + +react-freeze@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/react-freeze/-/react-freeze-1.0.4.tgz#cbbea2762b0368b05cbe407ddc9d518c57c6f3ad" + integrity sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA== + +react-i18next@^15.1.2: + version "15.7.4" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.7.4.tgz#146e50f220d204b842e22c75d1a3d23c6c589a30" + integrity sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw== + dependencies: + "@babel/runtime" "^7.27.6" + html-parse-stringify "^3.0.1" + +react-is@^16.13.0, react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^18.0.0, react-is@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" + integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== + +react-is@^19.0.0: + version "19.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.2.0.tgz#ddc3b4a4e0f3336c3847f18b806506388d7b9973" + integrity sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA== + +react-native-animatable@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/react-native-animatable/-/react-native-animatable-1.4.0.tgz#05a259e1566081ce7d3f6fba1e92edc65f5c6160" + integrity sha512-DZwaDVWm2NBvBxf7I0wXKXLKb/TxDnkV53sWhCvei1pRyTX3MVFpkvdYBknNBqPrxYuAIlPxEp7gJOidIauUkw== + dependencies: + prop-types "^15.8.1" + +react-native-animated-spinkit@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/react-native-animated-spinkit/-/react-native-animated-spinkit-1.5.2.tgz#b1c00ecbadf48634273e6a843f8dfbcb7c006186" + integrity sha512-YCQGR3HzEQvyaAnepiyf/hv88Sta3UIZ2CFZPtFqwu+VbFJfMgjJZniOx4157TuR5AAYajEJP9Fgy+JLIU3jzQ== + +"react-native-app-clip@https://github.com/polybase/react-native-app-clip#v4.0": + version "0.3.1" + resolved "https://github.com/polybase/react-native-app-clip#bc17d0aa7e682e8f2485a43ce9c54d0888396641" + dependencies: + "@expo/config-plugins" "~7.2.5" + "@expo/plist" "^0.0.20" + +react-native-blob-util@^0.18.0: + version "0.18.6" + resolved "https://registry.yarnpkg.com/react-native-blob-util/-/react-native-blob-util-0.18.6.tgz#641bcee9e6cc4abb0b02d5c22345b9ff7e280443" + integrity sha512-KLc2TvWlD4r/3h1t+NWgL2dDKW8j1TSAP0cFSf4n6GJS/89odHQhYW95SL9YOZd8J58/ZOOaI8qn6JAGDTJChg== + dependencies: + base-64 "0.1.0" + glob "^7.2.3" + +react-native-blob-util@^0.19.11: + version "0.19.11" + resolved "https://registry.yarnpkg.com/react-native-blob-util/-/react-native-blob-util-0.19.11.tgz#20c0ca589e975fee849cba1cdba712cc6adb4f59" + integrity sha512-lxaeDzFLYffR6lbRiOce0oTYO6pE3/PyT8Sa7qiz8B+IT9oe4G85SlVCdl5F9xMJh/Zer2onBLw7u+B1AS+GFA== + dependencies: + base-64 "0.1.0" + glob "^10.3.10" + +react-native-builder-bob@^0.35.2: + version "0.35.3" + resolved "https://registry.yarnpkg.com/react-native-builder-bob/-/react-native-builder-bob-0.35.3.tgz#921edf910023758326a8d25e238e305041e387a6" + integrity sha512-GtlRXJ9SL2oQw2KiHDCaHlk3mYkbDjYxMMoYVnj0+EIs0nuGFxG58NO6T1Mn2c6xYoVmSIg2RXFIFexsjHPRBQ== + dependencies: + "@babel/core" "^7.25.2" + "@babel/plugin-transform-strict-mode" "^7.24.7" + "@babel/preset-env" "^7.25.2" + "@babel/preset-flow" "^7.24.7" + "@babel/preset-react" "^7.24.7" + "@babel/preset-typescript" "^7.24.7" + babel-plugin-module-resolver "^5.0.2" + browserslist "^4.20.4" + cosmiconfig "^9.0.0" + cross-spawn "^7.0.3" + dedent "^0.7.0" + del "^6.1.1" + escape-string-regexp "^4.0.0" + fs-extra "^10.1.0" + glob "^8.0.3" + is-git-dirty "^2.0.1" + json5 "^2.2.1" + kleur "^4.1.4" + metro-config "^0.80.9" + prompts "^2.4.2" + which "^2.0.2" + yargs "^17.5.1" + +react-native-cloud-storage@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/react-native-cloud-storage/-/react-native-cloud-storage-2.3.0.tgz#caa9953061865b0ca5750aef1de1d7258c7fc12a" + integrity sha512-Bt+vnHO5Ae/ITMpZfySOxSVQckPKMb8ZQ0IXsSR7+y+AnShtlTbQ08qEYlHCXOp6+NGAhGD5ushqYO4nrd18tg== + +react-native-device-info@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-11.1.0.tgz#7db5c4e5a179dce761efac155a493aa0956a40ab" + integrity sha512-hzXJSObJdezEz0hF7MAJ3tGeoesuQWenXXt9mrQR9Mjb8kXpZ09rqSsZ/quNpJdZpQ3rYiFa3/0GFG5KNn9PBg== + +react-native-dialog@^9.3.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/react-native-dialog/-/react-native-dialog-9.3.0.tgz#9d745cc51653a1e2ae08076b46f11d99723c47f6" + integrity sha512-JEOJY/0AzTM9grIl0BL8o/IJPIJru7k5MPj9POTE9RRezUEtgn0YSvCpTlBtG0obWgOdzg2otMz1OQvMXS0wMQ== + +react-native-fit-image@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/react-native-fit-image/-/react-native-fit-image-1.5.5.tgz#c660d1ad74b9dcaa1cba27a0d9c23837e000226c" + integrity sha512-Wl3Vq2DQzxgsWKuW4USfck9zS7YzhvLNPpkwUUCF90bL32e1a0zOVQ3WsJILJOwzmPdHfzZmWasiiAUNBkhNkg== + dependencies: + prop-types "^15.5.10" + +react-native-fs@^2.20.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/react-native-fs/-/react-native-fs-2.20.0.tgz#05a9362b473bfc0910772c0acbb73a78dbc810f6" + integrity sha512-VkTBzs7fIDUiy/XajOSNk0XazFE9l+QlMAce7lGuebZcag5CnjszB+u4BdqzwaQOdcYb5wsJIsqq4kxInIRpJQ== + dependencies: + base-64 "^0.1.0" + utf8 "^3.0.0" + +react-native-gesture-handler@~2.28.0: + version "2.28.0" + resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-2.28.0.tgz#07fb4f5eae72f810aac3019b060d26c1835bfd0c" + integrity sha512-0msfJ1vRxXKVgTgvL+1ZOoYw3/0z1R+Ked0+udoJhyplC2jbVKIJ8Z1bzWdpQRCV3QcQ87Op0zJVE5DhKK2A0A== + dependencies: + "@egjs/hammerjs" "^2.0.17" + hoist-non-react-statics "^3.3.0" + invariant "^2.2.4" + +react-native-get-random-values@~1.11.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/react-native-get-random-values/-/react-native-get-random-values-1.11.0.tgz#1ca70d1271f4b08af92958803b89dccbda78728d" + integrity sha512-4BTbDbRmS7iPdhYLRcz3PGFIpFJBwNZg9g42iwa2P6FOv9vZj/xJc678RZXnLNZzd0qd7Q3CCF6Yd+CU2eoXKQ== + dependencies: + fast-base64-decode "^1.0.0" + +react-native-in-app-review@^4.3.3: + version "4.4.2" + resolved "https://registry.yarnpkg.com/react-native-in-app-review/-/react-native-in-app-review-4.4.2.tgz#eaa908cdc7adee26158903a0e6f22ca6af415f7b" + integrity sha512-iUoZnP4cgpbiNMLpqPgK40AcT7xluJhlwEPKFEfcCZsWT4MzGygS8p1dxf6e1NH/LUgUEtjsZQ8ka/SbF1pE8Q== + +react-native-is-edge-to-edge@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz#64e10851abd9d176cbf2b40562f751622bde3358" + integrity sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q== + +react-native-linear-gradient@^2.8.3: + version "2.8.3" + resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz#9a116649f86d74747304ee13db325e20b21e564f" + integrity sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA== + +react-native-localize@^3.2.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/react-native-localize/-/react-native-localize-3.6.0.tgz#2927c7f8e77339c2201581f6d99eb78fa5c48121" + integrity sha512-CByn67b9dPDBA7qvAx18PpXhuLqBbdTpedobGOUcjqiGuSAEXZzwas9ziMYSShAR2AvX2Cl7ePErCpj9V39Ctw== + +react-native-markdown-display@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/react-native-markdown-display/-/react-native-markdown-display-7.0.2.tgz#b6584cec8d6670c0141fb8780bc2f0710188a4c2" + integrity sha512-Mn4wotMvMfLAwbX/huMLt202W5DsdpMO/kblk+6eUs55S57VVNni1gzZCh5qpznYLjIQELNh50VIozEfY6fvaQ== + dependencies: + css-to-react-native "^3.0.0" + markdown-it "^10.0.0" + prop-types "^15.7.2" + react-native-fit-image "^1.5.5" + +react-native-mmkv@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/react-native-mmkv/-/react-native-mmkv-4.0.0.tgz#ef04726ec4af074d349de286036607d05a98e9f5" + integrity sha512-Osoy8as2ZLzO1TTsKxc4tX14Qk19qRVMWnS4ZVBwxie9Re5cjt7rqlpDkJczK3H/y3z70EQ6rmKI/cNMCLGAYQ== + +react-native-mmkv@^2.11.0: + version "2.12.2" + resolved "https://registry.yarnpkg.com/react-native-mmkv/-/react-native-mmkv-2.12.2.tgz#4bba0f5f04e2cf222494cce3a9794ba6a4894dee" + integrity sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg== + +react-native-modal-datetime-picker@^18.0.0: + version "18.0.0" + resolved "https://registry.yarnpkg.com/react-native-modal-datetime-picker/-/react-native-modal-datetime-picker-18.0.0.tgz#0555b2c9ab34318629a251f250de68a0e3b3980d" + integrity sha512-0jdvhhraZQlRACwr7pM6vmZ2kxgzJ4CpnmV6J3TVA6MrXMXK6Zo/upRBKkRp0+fTOiKuNblzesA2U59rYo6SGA== + dependencies: + prop-types "^15.7.2" + +react-native-modal@^13.0.1: + version "13.0.2" + resolved "https://registry.yarnpkg.com/react-native-modal/-/react-native-modal-13.0.2.tgz#4e4d777fdb0f5af5a50003a53eebc4de9ead5695" + integrity sha512-jCUR2DAskuZtVIbnt2ZssX70DCbTLydkL1Glv1Fc/fqVIhq1LpwBK2hKgSf9VIINXFnDjjGIMIC9HhDXnW7Enw== + dependencies: + react-native-animatable "1.4.0" + +react-native-nitro-modules@0.31.6: + version "0.31.6" + resolved "https://registry.yarnpkg.com/react-native-nitro-modules/-/react-native-nitro-modules-0.31.6.tgz#b5804be14a2fa0253c2fef607d594c3d53379389" + integrity sha512-EcKuLgYwOPrWSGC0VqxqTXjxsQBLCjl/1+ryuKwKDA4iyLr9C/8CBCn6sDS3wbmZDlNl+EPWTPU+VWC6SnPW8Q== + +react-native-outside-press@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/react-native-outside-press/-/react-native-outside-press-1.2.2.tgz#a869ce9e025d112581f05bc6a7ef86fc0c83f4b7" + integrity sha512-TkLB6KefjSXAPMHl2CQBpGnLQHT1wJp455k3vdhTRiT72llIyXrDDLp/gDhgQNNJAd3+XUEO5F+TZr882t8sYw== + +react-native-pager-view@6.9.1: + version "6.9.1" + resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.9.1.tgz#a9e6d9323935cc2ae1d46d7816b66f76dc3eff8e" + integrity sha512-uUT0MMMbNtoSbxe9pRvdJJKEi9snjuJ3fXlZhG8F2vVMOBJVt/AFtqMPUHu9yMflmqOr08PewKzj9EPl/Yj+Gw== + +react-native-plaid-link-sdk@=12.7.0: + version "12.7.0" + resolved "https://registry.yarnpkg.com/react-native-plaid-link-sdk/-/react-native-plaid-link-sdk-12.7.0.tgz#0726765662cff989a217d0faaf40a93e151afc37" + integrity sha512-sqzrnqqwQeB2KAgOuRp6GZS2HZqHfOyxj6hUW4LqZaK/Q4xI31+uVot3JR1HAP+GZoAo4uHZ8BSBTftWVv7bIA== + +react-native-play-install-referrer@^1.1.8: + version "1.1.9" + resolved "https://registry.yarnpkg.com/react-native-play-install-referrer/-/react-native-play-install-referrer-1.1.9.tgz#369952c317714c090da48096d16ad68fc2c2b7a5" + integrity sha512-COKQA/eS2I9NigxZDVZuLFzGNLBXF4+o3o9EIgULx+aagjVQexlPBh4g9fdnhiSvZk1rzq/asVwIJKRPc9Cy7A== + +react-native-quick-base64@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/react-native-quick-base64/-/react-native-quick-base64-2.2.0.tgz#fa417d1339a6df0bfa103b45b7e8a3dc73adc999" + integrity sha512-r7/BRsRl8QKEhS0JsHW6QX9+8LrC6NNWlwNnBnZ69h2kbcfABYsUILT71obrs9fqElEIMzuYSI5aHID955akyQ== + +react-native-quick-base64@^2.0.5, react-native-quick-base64@^2.1.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-native-quick-base64/-/react-native-quick-base64-2.2.2.tgz#52005a0b455b04acc1c6ff3eb8fa220401656aae" + integrity sha512-WLHSifHLoamr2kF00Gov0W9ud6CfPshe1rmqWTquVIi9c62qxOaJCFVDrXFZhEBU8B8PvGLVuOlVKH78yhY0Fg== + +react-native-quick-crypto@1.0.0-beta.20: + version "1.0.0-beta.20" + resolved "https://registry.yarnpkg.com/react-native-quick-crypto/-/react-native-quick-crypto-1.0.0-beta.20.tgz#35402e419252c5966cb308cf68b41b2f41de4228" + integrity sha512-/9lYyD18y3zkQO9kNKIbPDaLRBRQUquijWgMnnBkPjjffMqkVr0qYHQqOOj3WUn2j5b4RIaD2nPW6YkEiDFZtg== + dependencies: + "@craftzdog/react-native-buffer" "6.1.0" + events "3.3.0" + react-native-quick-base64 "2.2.0" + readable-stream "4.5.2" + util "0.12.5" + +react-native-reanimated@^4.1.3: + version "4.1.5" + resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-4.1.5.tgz#5106f9d5dc61f06ca54b9813f280bbfde7785987" + integrity sha512-UA6VUbxwhRjEw2gSNrvhkusUq3upfD3Cv+AnB07V+kC8kpvwRVI+ivwY95ePbWNFkFpP+Y2Sdw1WHpHWEV+P2Q== + dependencies: + react-native-is-edge-to-edge "^1.2.1" + semver "7.7.2" + +react-native-safe-area-context@~5.6.0: + version "5.6.2" + resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz#283e006f5b434fb247fcb4be0971ad7473d5c560" + integrity sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg== + +react-native-screens@~4.16.0: + version "4.16.0" + resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-4.16.0.tgz#efa42e77a092aa0b5277c9ae41391ea0240e0870" + integrity sha512-yIAyh7F/9uWkOzCi1/2FqvNvK6Wb9Y1+Kzn16SuGfN9YFJDTbwlzGRvePCNTOX0recpLQF3kc2FmvMUhyTCH1Q== + dependencies: + react-freeze "^1.0.0" + react-native-is-edge-to-edge "^1.2.1" + warn-once "^0.1.0" + +react-native-svg@15.12.1: + version "15.12.1" + resolved "https://registry.yarnpkg.com/react-native-svg/-/react-native-svg-15.12.1.tgz#7ba756dd6a235f86a2c312a1e7911f9b0d18ad3a" + integrity sha512-vCuZJDf8a5aNC2dlMovEv4Z0jjEUET53lm/iILFnFewa15b4atjVxU6Wirm6O9y6dEsdjDZVD7Q3QM4T1wlI8g== + dependencies: + css-select "^5.1.0" + css-tree "^1.1.3" + warn-once "0.1.1" + +react-native-swiper@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/react-native-swiper/-/react-native-swiper-1.6.0.tgz#59fdbdf95addee49630312f27077622c27776819" + integrity sha512-OnkTTZi+9uZUgy0uz1I9oYDhCU3z36lZn+LFsk9FXPRelxb/KeABzvPs3r3SrHWy1aA67KGtSFj0xNK2QD0NJQ== + dependencies: + prop-types "^15.5.10" + +react-native-toast-message@^2.1.7: + version "2.3.3" + resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-2.3.3.tgz#e301508d386a9902ff6b4559ecc6674f8cfdf97a" + integrity sha512-4IIUHwUPvKHu4gjD0Vj2aGQzqPATiblL1ey8tOqsxOWRPGGu52iIbL8M/mCz4uyqecvPdIcMY38AfwRuUADfQQ== + +react-native-url-polyfill@2.0.0, react-native-url-polyfill@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz#db714520a2985cff1d50ab2e66279b9f91ffd589" + integrity sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA== + dependencies: + whatwg-url-without-unicode "8.0.0-3" + +react-native-vision-camera-face-detector@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/react-native-vision-camera-face-detector/-/react-native-vision-camera-face-detector-1.9.1.tgz#0429e84a24b145fdabdd88be364e223b30e440eb" + integrity sha512-OsTe61R1+CyzZLp3xLI3PBMBGd3zEWbeHPgqZPOSbB0gEKWyIaTahBUCft47pVdi72onDlke//hPM+xyFOYBjQ== + +react-native-vision-camera@^4.7.3: + version "4.7.3" + resolved "https://registry.yarnpkg.com/react-native-vision-camera/-/react-native-vision-camera-4.7.3.tgz#ed03cedabcaec54774f5aa40e69afa30069924d4" + integrity sha512-g1/neOyjSqn1kaAa2FxI/qp5KzNvPcF0bnQw6NntfbxH6tm0+8WFZszlgb5OV+iYlB6lFUztCbDtyz5IpL47OA== + +react-native-worklets-core@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/react-native-worklets-core/-/react-native-worklets-core-1.6.2.tgz#5270097812b5f6668ca818dfa0a60078d74b9352" + integrity sha512-zw73JfL40ZL/OD2TOil1El4D9ZwS3l6AFPeFfUWXh+V2/dHN8i28jHX8QXlz5DYtAkR+Ju3U1h4yiaODi/igZw== + dependencies: + string-hash-64 "^1.0.3" + +react-native-worklets@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/react-native-worklets/-/react-native-worklets-0.6.1.tgz#daa56dea896c7bdcead064b675ef341ac1f41029" + integrity sha512-URca8l7c7Uog7gv4mcg9KILdJlnbvwdS5yfXQYf5TDkD2W1VY1sduEKrD+sA3lUPXH/TG1vmXAvNxCNwPMYgGg== + dependencies: + "@babel/plugin-transform-arrow-functions" "^7.0.0-0" + "@babel/plugin-transform-class-properties" "^7.0.0-0" + "@babel/plugin-transform-classes" "^7.0.0-0" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.0.0-0" + "@babel/plugin-transform-optional-chaining" "^7.0.0-0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0-0" + "@babel/plugin-transform-template-literals" "^7.0.0-0" + "@babel/plugin-transform-unicode-regex" "^7.0.0-0" + "@babel/preset-typescript" "^7.16.7" + convert-source-map "^2.0.0" + semver "7.7.2" + +react-native@=0.81.5: + version "0.81.5" + resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.81.5.tgz#6c963f137d3979b22aef2d8482067775c8fe2fed" + integrity sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw== + dependencies: + "@jest/create-cache-key-function" "^29.7.0" + "@react-native/assets-registry" "0.81.5" + "@react-native/codegen" "0.81.5" + "@react-native/community-cli-plugin" "0.81.5" + "@react-native/gradle-plugin" "0.81.5" + "@react-native/js-polyfills" "0.81.5" + "@react-native/normalize-colors" "0.81.5" + "@react-native/virtualized-lists" "0.81.5" + abort-controller "^3.0.0" + anser "^1.4.9" + ansi-regex "^5.0.0" + babel-jest "^29.7.0" + babel-plugin-syntax-hermes-parser "0.29.1" + base64-js "^1.5.1" + commander "^12.0.0" + flow-enums-runtime "^0.0.6" + glob "^7.1.1" + invariant "^2.2.4" + jest-environment-node "^29.7.0" + memoize-one "^5.0.0" + metro-runtime "^0.83.1" + metro-source-map "^0.83.1" + nullthrows "^1.1.1" + pretty-format "^29.7.0" + promise "^8.3.0" + react-devtools-core "^6.1.5" + react-refresh "^0.14.0" + regenerator-runtime "^0.13.2" + scheduler "0.26.0" + semver "^7.1.3" + stacktrace-parser "^0.1.10" + whatwg-fetch "^3.0.0" + ws "^6.2.3" + yargs "^17.6.2" + +react-qr-code@^2.0.12: + version "2.0.18" + resolved "https://registry.yarnpkg.com/react-qr-code/-/react-qr-code-2.0.18.tgz#237de8fbab537885d6b2b10f4fd5318b371e3b17" + integrity sha512-v1Jqz7urLMhkO6jkgJuBYhnqvXagzceg3qJUWayuCK/c6LTIonpWbwxR1f1APGd4xrW/QcQEovNrAojbUz65Tg== + dependencies: + prop-types "^15.8.1" + qr.js "0.0.0" + +react-redux@^9.1.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.2.0.tgz#96c3ab23fb9a3af2cb4654be4b51c989e32366f5" + integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g== + dependencies: + "@types/use-sync-external-store" "^0.0.6" + use-sync-external-store "^1.4.0" + +react-refresh@^0.14.0, react-refresh@^0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== + +react-refresh@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53" + integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ== + +react-remove-scroll-bar@^2.3.7: + version "2.3.8" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" + integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== + dependencies: + react-style-singleton "^2.2.2" + tslib "^2.0.0" + +react-remove-scroll@^2.5.7: + version "2.7.1" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz#d2101d414f6d81d7d3bf033f3c1cb4785789f753" + integrity sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA== + dependencies: + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.3" + tslib "^2.1.0" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" + +react-resizable@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.0.5.tgz#362721f2efbd094976f1780ae13f1ad7739786c1" + integrity sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w== + dependencies: + prop-types "15.x" + react-draggable "^4.0.3" + +react-server-dom-webpack@~19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/react-server-dom-webpack/-/react-server-dom-webpack-19.0.0.tgz#c60819b6cb54e317e675ddc0c5959ff915b789d0" + integrity sha512-hLug9KEXLc8vnU9lDNe2b2rKKDaqrp5gNiES4uyu2Up3FZfZJZmdwLFXlWzdA9gTB/6/cWduSB2K1Lfag2pSvw== + dependencies: + acorn-loose "^8.3.0" + neo-async "^2.6.1" + webpack-sources "^3.2.0" + +react-stately@^3.21.0: + version "3.42.0" + resolved "https://registry.yarnpkg.com/react-stately/-/react-stately-3.42.0.tgz#f309e9cb729374cc187c688529a2aa0572ab9408" + integrity sha512-lYt2o1dd6dK8Bb4GRh08RG/2u64bSA1cqtRqtw4jEMgxC7Q17RFcIumBbChErndSdLzafEG/UBwV6shOfig6yw== + dependencies: + "@react-stately/calendar" "^3.9.0" + "@react-stately/checkbox" "^3.7.2" + "@react-stately/collections" "^3.12.8" + "@react-stately/color" "^3.9.2" + "@react-stately/combobox" "^3.12.0" + "@react-stately/data" "^3.14.1" + "@react-stately/datepicker" "^3.15.2" + "@react-stately/disclosure" "^3.0.8" + "@react-stately/dnd" "^3.7.1" + "@react-stately/form" "^3.2.2" + "@react-stately/list" "^3.13.1" + "@react-stately/menu" "^3.9.8" + "@react-stately/numberfield" "^3.10.2" + "@react-stately/overlays" "^3.6.20" + "@react-stately/radio" "^3.11.2" + "@react-stately/searchfield" "^3.5.16" + "@react-stately/select" "^3.8.0" + "@react-stately/selection" "^3.20.6" + "@react-stately/slider" "^3.7.2" + "@react-stately/table" "^3.15.1" + "@react-stately/tabs" "^3.8.6" + "@react-stately/toast" "^3.1.2" + "@react-stately/toggle" "^3.9.2" + "@react-stately/tooltip" "^3.5.8" + "@react-stately/tree" "^3.9.3" + "@react-types/shared" "^3.32.1" + +react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" + integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== + dependencies: + get-nonce "^1.0.0" + tslib "^2.0.0" + +react-test-renderer@19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-19.0.0.tgz#ca6fa322c58d4bfa34635788fe242a8c3daa4c7d" + integrity sha512-oX5u9rOQlHzqrE/64CNr0HB0uWxkCQmZNSfozlYvwE71TLVgeZxVf0IjouGEr1v7r1kcDifdAJBeOhdhxsG/DA== + dependencies: + react-is "^19.0.0" + scheduler "^0.25.0" + +react@19.1.0, react@^18, react@^19.1.0: + version "19.1.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75" + integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== + +read-cache@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" + integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== + dependencies: + pify "^2.3.0" + +readable-stream@4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" + integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + +readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.6.0, readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +"readable-stream@^3.6.2 || ^4.4.2": + version "4.7.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91" + integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + +readdirp@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-5.0.0.tgz#fbf1f71a727891d685bb1786f9ba74084f6e2f91" + integrity sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +real-require@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" + integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== + +recast@^0.23.5: + version "0.23.11" + resolved "https://registry.yarnpkg.com/recast/-/recast-0.23.11.tgz#8885570bb28cf773ba1dc600da7f502f7883f73f" + integrity sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA== + dependencies: + ast-types "^0.16.1" + esprima "~4.0.0" + source-map "~0.6.1" + tiny-invariant "^1.3.3" + tslib "^2.0.1" + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + +redux-logger@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/redux-logger/-/redux-logger-3.0.6.tgz#f7555966f3098f3c88604c449cf0baf5778274bf" + integrity sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg== + dependencies: + deep-diff "^0.3.5" + +redux-persist-filesystem-storage@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/redux-persist-filesystem-storage/-/redux-persist-filesystem-storage-4.2.0.tgz#8e55e338b8acf70a88499c77869c7cbe4679bf2f" + integrity sha512-H3INMw64atSRF5aukTtk9BLKuhTT+DZ2vIy3+dog5pfXtUJTF5u/N7HcEd2TECAncffrYeeAnMGVCqKxW8zecA== + dependencies: + react-native-blob-util "^0.18.0" + +redux-persist@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" + integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ== + +redux-thunk@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-3.1.0.tgz#94aa6e04977c30e14e892eae84978c1af6058ff3" + integrity sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw== + +redux@^5.0.0, redux@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b" + integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== + +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.9" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.7" + get-proto "^1.0.1" + which-builtin-type "^1.2.1" + +regenerate-unicode-properties@^10.2.2: + version "10.2.2" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz#aa113812ba899b630658c7623466be71e1f86f66" + integrity sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.2: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.3, regexp.prototype.flags@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-errors "^1.3.0" + get-proto "^1.0.1" + gopd "^1.2.0" + set-function-name "^2.0.2" + +regexpp@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^6.3.1: + version "6.4.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.4.0.tgz#3580ce0c4faedef599eccb146612436b62a176e5" + integrity sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.2.2" + regjsgen "^0.8.0" + regjsparser "^0.13.0" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.2.1" + +regjsgen@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" + integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== + +regjsparser@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.13.0.tgz#01f8351335cf7898d43686bc74d2dd71c847ecc0" + integrity sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q== + dependencies: + jsesc "~3.1.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +requireg@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/requireg/-/requireg-0.2.2.tgz#437e77a5316a54c9bcdbbf5d1f755fe093089830" + integrity sha512-nYzyjnFcPNGR3lx9lwPPPnuQxv6JWEZd2Ci0u9opN7N5zUEPIhY/GbL3vMGOr2UXwEg9WwSyV9X9Y/kLFgPsOg== + dependencies: + nested-error-stacks "~2.0.1" + rc "~1.2.7" + resolve "~1.7.1" + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +reselect@^4.1.7: + version "4.1.8" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" + integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== + +reselect@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e" + integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-global@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-global/-/resolve-global-1.0.0.tgz#a2a79df4af2ca3f49bf77ef9ddacd322dad19255" + integrity sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw== + dependencies: + global-dirs "^0.1.1" + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-workspace-root/-/resolve-workspace-root-2.0.0.tgz#a0098daa0067cd0efa6eb525c57c8fb4a61e78f8" + integrity sha512-IsaBUZETJD5WsI11Wt8PKHwaIe45or6pwNc8yflvLJ4DWtImK9kuLoH5kUva/2Mmx/RdIyr4aONNSa2v9LTJsw== + +resolve.exports@^2.0.0, resolve.exports@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.3.tgz#41955e6f1b4013b7586f873749a635dea07ebe3f" + integrity sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A== + +resolve@^1.1.7, resolve@^1.10.1, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.10, resolve@^1.22.2, resolve@^1.22.4, resolve@^1.22.8: + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== + dependencies: + is-core-module "^2.16.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@~1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + integrity sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw== + dependencies: + path-parse "^1.0.5" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q== + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rn-host-detect@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/rn-host-detect/-/rn-host-detect-1.2.0.tgz#8b0396fc05631ec60c1cb8789e5070cdb04d0da0" + integrity sha512-btNg5kzHcjZZ7t7mvvV/4wNJ9e3MPgrWivkRgWURzXL0JJ0pwWlU4zrbmdlz3HHzHOxhBhHB4D+/dbMFfu4/4A== + +rollup@^4.20.0: + version "4.59.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.59.0.tgz#cf74edac17c1486f562d728a4d923a694abdf06f" + integrity sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.59.0" + "@rollup/rollup-android-arm64" "4.59.0" + "@rollup/rollup-darwin-arm64" "4.59.0" + "@rollup/rollup-darwin-x64" "4.59.0" + "@rollup/rollup-freebsd-arm64" "4.59.0" + "@rollup/rollup-freebsd-x64" "4.59.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.59.0" + "@rollup/rollup-linux-arm-musleabihf" "4.59.0" + "@rollup/rollup-linux-arm64-gnu" "4.59.0" + "@rollup/rollup-linux-arm64-musl" "4.59.0" + "@rollup/rollup-linux-loong64-gnu" "4.59.0" + "@rollup/rollup-linux-loong64-musl" "4.59.0" + "@rollup/rollup-linux-ppc64-gnu" "4.59.0" + "@rollup/rollup-linux-ppc64-musl" "4.59.0" + "@rollup/rollup-linux-riscv64-gnu" "4.59.0" + "@rollup/rollup-linux-riscv64-musl" "4.59.0" + "@rollup/rollup-linux-s390x-gnu" "4.59.0" + "@rollup/rollup-linux-x64-gnu" "4.59.0" + "@rollup/rollup-linux-x64-musl" "4.59.0" + "@rollup/rollup-openbsd-x64" "4.59.0" + "@rollup/rollup-openharmony-arm64" "4.59.0" + "@rollup/rollup-win32-arm64-msvc" "4.59.0" + "@rollup/rollup-win32-ia32-msvc" "4.59.0" + "@rollup/rollup-win32-x64-gnu" "4.59.0" + "@rollup/rollup-win32-x64-msvc" "4.59.0" + fsevents "~2.3.2" + +router@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" + integrity sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ== + dependencies: + debug "^4.4.0" + depd "^2.0.0" + is-promise "^4.0.0" + parseurl "^1.3.3" + path-to-regexp "^8.0.0" + +rpc-websockets@^9.0.2: + version "9.3.1" + resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.3.1.tgz#d817a59d812f68bae1215740a3f78fcdd3813698" + integrity sha512-bY6a+i/lEtBJ/mUxwsCTgevoV1P0foXTVA7UoThzaIWbM+3NDqorf8NBWs5DmqKTFeA1IoNzgvkWjFCPgnzUiQ== + dependencies: + "@swc/helpers" "^0.5.11" + "@types/uuid" "^8.3.4" + "@types/ws" "^8.2.2" + buffer "^6.0.3" + eventemitter3 "^5.0.1" + uuid "^8.3.2" + ws "^8.5.0" + optionalDependencies: + bufferutil "^4.0.1" + utf-8-validate "^5.0.2" + +rtl-detect@^1.0.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.1.2.tgz#ca7f0330af5c6bb626c15675c642ba85ad6273c6" + integrity sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" + isarray "^2.0.5" + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== + dependencies: + es-errors "^1.3.0" + isarray "^2.0.5" + +safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" + +safe-stable-stringify@^2.1.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@>=0.6.0: + version "1.4.3" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.3.tgz#fcebae3b756cdc8428321805f4b70f16ec0ab5db" + integrity sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ== + +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + +sc-errors@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/sc-errors/-/sc-errors-3.0.0.tgz#df2e124f011be5fdd633e92d1de5ce6a6b4c1b85" + integrity sha512-rIqv2HTPb9DVreZwK/DV0ytRUqyw2DbDcoB9XTKjEQL7oMEQKsfPA8V8dGGr7p8ZYfmvaRIGZ4Wu5qwvs/hGDA== + +sc-formatter@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/sc-formatter/-/sc-formatter-4.0.0.tgz#2dda494a08e9d4cb069cbc9238a9f670adb3e7a6" + integrity sha512-MgUIvuca+90fBrCWY5LdlU9YUWjlkPFwdpvmomcwQEu3t2id/6YHdG2nhB6o7nhRp4ocfmcXQTh00r/tJtynSg== + +scheduler@0.26.0, scheduler@^0.26.0: + version "0.26.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337" + integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA== + +scheduler@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" + integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== + +schema-utils@^2.6.5: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +scrypt-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +secp256k1@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.4.tgz#58f0bfe1830fe777d9ca1ffc7574962a8189f8ab" + integrity sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw== + dependencies: + elliptic "^6.5.7" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + +secp256k1@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-5.0.1.tgz#dc2c86187d48ff2da756f0f7e96417ee03c414b1" + integrity sha512-lDFs9AAIaWP9UCdtWrotXWWF9t8PWgQDcxqgAnpM9rMqxb3Oaq2J0thzPVSxBwdJgyQtkU/sYtFtbM1RSt/iYA== + dependencies: + elliptic "^6.5.7" + node-addon-api "^5.0.0" + node-gyp-build "^4.2.0" + +semver@7.7.2: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + +semver@7.x, semver@^7.1.3, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.6.3, semver@^7.7.1, semver@^7.7.2, semver@^7.7.3: + version "7.7.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" + integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== + +semver@^5.3.0, semver@^5.6.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.8: + version "7.7.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" + integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== + +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +send@^0.19.0: + version "0.19.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.1.tgz#1c2563b2ee4fe510b806b21ec46f355005a369f9" + integrity sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~2.0.0" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +send@^1.1.0, send@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/send/-/send-1.2.0.tgz#32a7554fb777b831dfa828370f773a3808d37212" + integrity sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw== + dependencies: + debug "^4.3.5" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + fresh "^2.0.0" + http-errors "^2.0.0" + mime-types "^3.0.1" + ms "^2.1.3" + on-finished "^2.4.1" + range-parser "^1.2.1" + statuses "^2.0.1" + +serialize-error@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a" + integrity sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw== + +serve-static@^1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== + dependencies: + encodeurl "~2.0.0" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.19.0" + +serve-static@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.0.tgz#9c02564ee259bdd2251b82d659a2e7e1938d66f9" + integrity sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ== + dependencies: + encodeurl "^2.0.0" + escape-html "^1.0.3" + parseurl "^1.3.3" + send "^1.2.0" + +server-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/server-only/-/server-only-0.0.1.tgz#0f366bb6afb618c37c9255a314535dc412cd1c9e" + integrity sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-function-length@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +set-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.11: + version "2.4.12" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.12.tgz#eb8b568bf383dfd1867a32c3f2b74eb52bdbf23f" + integrity sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w== + dependencies: + inherits "^2.0.4" + safe-buffer "^5.2.1" + to-buffer "^1.2.0" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +sharp@^0.34.3: + version "0.34.5" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.34.5.tgz#b6f148e4b8c61f1797bde11a9d1cfebbae2c57b0" + integrity sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg== + dependencies: + "@img/colour" "^1.0.0" + detect-libc "^2.1.2" + semver "^7.7.3" + optionalDependencies: + "@img/sharp-darwin-arm64" "0.34.5" + "@img/sharp-darwin-x64" "0.34.5" + "@img/sharp-libvips-darwin-arm64" "1.2.4" + "@img/sharp-libvips-darwin-x64" "1.2.4" + "@img/sharp-libvips-linux-arm" "1.2.4" + "@img/sharp-libvips-linux-arm64" "1.2.4" + "@img/sharp-libvips-linux-ppc64" "1.2.4" + "@img/sharp-libvips-linux-riscv64" "1.2.4" + "@img/sharp-libvips-linux-s390x" "1.2.4" + "@img/sharp-libvips-linux-x64" "1.2.4" + "@img/sharp-libvips-linuxmusl-arm64" "1.2.4" + "@img/sharp-libvips-linuxmusl-x64" "1.2.4" + "@img/sharp-linux-arm" "0.34.5" + "@img/sharp-linux-arm64" "0.34.5" + "@img/sharp-linux-ppc64" "0.34.5" + "@img/sharp-linux-riscv64" "0.34.5" + "@img/sharp-linux-s390x" "0.34.5" + "@img/sharp-linux-x64" "0.34.5" + "@img/sharp-linuxmusl-arm64" "0.34.5" + "@img/sharp-linuxmusl-x64" "0.34.5" + "@img/sharp-wasm32" "0.34.5" + "@img/sharp-win32-arm64" "0.34.5" + "@img/sharp-win32-ia32" "0.34.5" + "@img/sharp-win32-x64" "0.34.5" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@^1.6.1: + version "1.8.3" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.3.tgz#55e40ef33cf5c689902353a3d8cd1a6725f08b4b" + integrity sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw== + +sherlo@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/sherlo/-/sherlo-1.5.1.tgz#8fbc10087eb97644dfd0a03d2c2ab2bf0f6b67eb" + integrity sha512-z2SNVVzRP74N1I7OYAOOwXd5JCVmySn7bjxzXRhy1XFp2ve9nRElY3IttNj6JndeeEg+8CG+5bDvwb3Raojrzg== + +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + +signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +simple-plist@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.3.1.tgz#16e1d8f62c6c9b691b8383127663d834112fb017" + integrity sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw== + dependencies: + bplist-creator "0.1.0" + bplist-parser "0.3.1" + plist "^3.0.5" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slash@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-5.1.0.tgz#be3adddcdf09ac38eebe8dcdc7b1a57a75b095ce" + integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg== + +slugify@^1.3.4, slugify@^1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.6.6.tgz#2d4ac0eacb47add6af9e04d3be79319cbcc7924b" + integrity sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw== + +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +socket.io-client@^4.5.1: + version "4.8.3" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.8.3.tgz#62717edd46a318c918125b57e92dc7f8bb71c34c" + integrity sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.4.1" + engine.io-client "~6.6.1" + socket.io-parser "~4.2.4" + +socket.io-parser@~4.2.4: + version "4.2.5" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.5.tgz#3f41b8d369129a93268f2abecba94b5292850099" + integrity sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.4.1" + +socketcluster-client@^19.2.3: + version "19.2.7" + resolved "https://registry.yarnpkg.com/socketcluster-client/-/socketcluster-client-19.2.7.tgz#70d96a491323cc044d1171efabc3aa05023d959a" + integrity sha512-c6caNOr/49FUjlVnQfXb0TasMnrqY1uN/uevT99xicF+7NkvGSNwjP6rlMP0v1ZZjz+MosT2/qJNDDc2b3v/Jw== + dependencies: + ag-auth "^2.1.0" + ag-channel "^5.0.0" + ag-request "^1.1.0" + async-stream-emitter "^7.0.1" + buffer "^5.2.1" + clone-deep "^4.0.1" + linked-list "^2.1.0" + sc-errors "^3.0.0" + sc-formatter "^4.0.0" + stream-demux "^10.0.1" + uuid "^8.3.2" + vinyl-buffer "^1.0.1" + ws "^8.18.0" + +sonic-boom@^2.2.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" + integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== + dependencies: + atomic-sleep "^1.0.0" + +source-map-js@^1.0.1, source-map-js@^1.0.2, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@~0.5.20, source-map-support@~0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + integrity sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA== + +source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stable-hash@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stable-hash/-/stable-hash-0.0.4.tgz#55ae7dadc13e4b3faed13601587cec41859b42f7" + integrity sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g== + +stable-hash@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stable-hash/-/stable-hash-0.0.5.tgz#94e8837aaeac5b4d0f631d2972adef2924b40269" + integrity sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA== + +stack-generator@^2.0.5: + version "2.0.10" + resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.10.tgz#8ae171e985ed62287d4f1ed55a1633b3fb53bb4d" + integrity sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ== + dependencies: + stackframe "^1.3.4" + +stack-utils@^2.0.3, stack-utils@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +stacktrace-gps@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz#0c40b24a9b119b20da4525c398795338966a2fb0" + integrity sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ== + dependencies: + source-map "0.5.6" + stackframe "^1.3.4" + +stacktrace-js@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stacktrace-js/-/stacktrace-js-2.0.2.tgz#4ca93ea9f494752d55709a081d400fdaebee897b" + integrity sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg== + dependencies: + error-stack-parser "^2.0.6" + stack-generator "^2.0.5" + stacktrace-gps "^3.0.4" + +stacktrace-parser@^0.1.10: + version "0.1.11" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz#c7c08f9b29ef566b9a6f7b255d7db572f66fabc4" + integrity sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg== + dependencies: + type-fest "^0.7.1" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +statuses@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" + integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== + +statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +stop-iteration-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz#f481ff70a548f6124d0312c3aa14cbfa7aa542ad" + integrity sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ== + dependencies: + es-errors "^1.3.0" + internal-slot "^1.1.0" + +store2@^2.14.3: + version "2.14.4" + resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.4.tgz#81b313abaddade4dcd7570c5cc0e3264a8f7a242" + integrity sha512-srTItn1GOvyvOycgxjAnPA63FZNwy0PTyUBFMHRM+hVFltAeoh0LmNBz9SZqUS9mMqGk8rfyWyXn3GH5ReJ8Zw== + +storybook@^9.1.1: + version "9.1.16" + resolved "https://registry.yarnpkg.com/storybook/-/storybook-9.1.16.tgz#fe92ac733781aa919104ecf090fd6615deaa6c69" + integrity sha512-339U14K6l46EFyRvaPS2ZlL7v7Pb+LlcXT8KAETrGPxq8v1sAjj2HAOB6zrlAK3M+0+ricssfAwsLCwt7Eg8TQ== + dependencies: + "@storybook/global" "^5.0.0" + "@testing-library/jest-dom" "^6.6.3" + "@testing-library/user-event" "^14.6.1" + "@vitest/expect" "3.2.4" + "@vitest/mocker" "3.2.4" + "@vitest/spy" "3.2.4" + better-opn "^3.0.2" + esbuild "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0" + esbuild-register "^3.5.0" + recast "^0.23.5" + semver "^7.6.2" + ws "^8.18.0" + +stream-buffers@2.2.x: + version "2.2.0" + resolved "https://registry.yarnpkg.com/stream-buffers/-/stream-buffers-2.2.0.tgz#91d5f5130d1cef96dcfa7f726945188741d09ee4" + integrity sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg== + +stream-chain@^2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09" + integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA== + +stream-demux@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/stream-demux/-/stream-demux-10.0.1.tgz#204b65fb8973c87cea65119e99622405b3dbcc10" + integrity sha512-QjTYLJWpZxZ6uL5R1JzgOzjvao8zDx78ec+uOjHNeVc/9TuasYLldoVrYARZeT1xI1hFYuiKf13IM8b4wamhHg== + dependencies: + consumable-stream "^3.0.0" + writable-consumable-stream "^4.1.0" + +stream-json@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.1.tgz#e3fec03e984a503718946c170db7d74556c2a187" + integrity sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw== + dependencies: + stream-chain "^2.2.5" + +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + +string-hash-64@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322" + integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw== + +string-length@^4.0.1, string-length@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-length@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-5.0.1.tgz#3d647f497b6e8e8d41e422f7e0b23bc536c8381e" + integrity sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow== + dependencies: + char-regex "^2.0.0" + strip-ansi "^7.0.1" + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string.prototype.includes@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" + integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + +string.prototype.matchall@^4.0.12: + version "4.0.12" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" + integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + regexp.prototype.flags "^1.5.3" + set-function-name "^2.0.2" + side-channel "^1.1.0" + +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" + +string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string_decoder@^1.1.1, string_decoder@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +structured-headers@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/structured-headers/-/structured-headers-0.4.1.tgz#77abd9410622c6926261c09b9d16cf10592694d1" + integrity sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg== + +style-mod@^4.0.0, style-mod@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.3.tgz#6e9012255bb799bdac37e288f7671b5d71bf9f73" + integrity sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ== + +styled-jsx@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" + integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw== + dependencies: + client-only "0.0.1" + +styled-jsx@5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.6.tgz#83b90c077e6c6a80f7f5e8781d0f311b2fe41499" + integrity sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA== + dependencies: + client-only "0.0.1" + +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== + +sucrase@3.35.0: + version "3.35.0" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" + integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + glob "^10.3.10" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + ts-interface-checker "^0.1.9" + +sucrase@^3.35.0: + version "3.35.1" + resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.1.tgz#4619ea50393fe8bd0ae5071c26abd9b2e346bfe1" + integrity sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.2" + commander "^4.0.0" + lines-and-columns "^1.1.6" + mz "^2.7.0" + pirates "^4.0.1" + tinyglobby "^0.2.11" + ts-interface-checker "^0.1.9" + +superstruct@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== + +superstruct@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" + integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0, supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-hyperlinks@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +svg-parser@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" + integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== + +svgo@^3.0.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-3.3.2.tgz#ad58002652dffbb5986fc9716afe52d869ecbda8" + integrity sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw== + dependencies: + "@trysound/sax" "0.2.0" + commander "^7.2.0" + css-select "^5.1.0" + css-tree "^2.3.1" + css-what "^6.1.0" + csso "^5.0.5" + picocolors "^1.0.0" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + +synckit@^0.11.7, synckit@^0.11.8: + version "0.11.11" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0" + integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw== + dependencies: + "@pkgr/core" "^0.2.9" + +tailwindcss@^3.4.12: + version "3.4.19" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.19.tgz#af2a0a4ae302d52ebe078b6775e799e132500ee2" + integrity sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.6.0" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.2" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.7" + lilconfig "^3.1.3" + micromatch "^4.0.8" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.1.1" + postcss "^8.4.47" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.2 || ^5.0 || ^6.0" + postcss-nested "^6.2.0" + postcss-selector-parser "^6.1.2" + resolve "^1.22.8" + sucrase "^3.35.0" + +tapable@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6" + integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg== + +tar@^7.4.3: + version "7.5.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-7.5.2.tgz#115c061495ec51ff3c6745ff8f6d0871c5b1dedc" + integrity sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg== + dependencies: + "@isaacs/fs-minipass" "^4.0.0" + chownr "^3.0.0" + minipass "^7.1.2" + minizlib "^3.1.0" + yallist "^5.0.0" + +temp-dir@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + +terminal-link@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +terser@^5.15.0: + version "5.44.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.44.1.tgz#e391e92175c299b8c284ad6ded609e37303b0a9c" + integrity sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.15.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-encoding-utf-8@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" + integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== + +text-encoding@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.7.0.tgz#f895e836e45990624086601798ea98e8f36ee643" + integrity sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA== + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== + dependencies: + any-promise "^1.0.0" + +thread-stream@^0.15.1: + version "0.15.2" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.15.2.tgz#fb95ad87d2f1e28f07116eb23d85aba3bc0425f4" + integrity sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA== + dependencies: + real-require "^0.1.0" + +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" + integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== + +through2@^2.0.1, through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +tiny-invariant@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" + integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== + +tinycolor2@^1.4.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" + integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw== + +tinyglobby@^0.2.11, tinyglobby@^0.2.13, tinyglobby@^0.2.15: + version "0.2.15" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" + integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.3" + +tinyrainbow@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" + integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== + +tinyspy@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-4.0.4.tgz#d77a002fb53a88aa1429b419c1c92492e0c81f78" + integrity sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q== + +tmp@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8" + integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow== + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-buffer@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.2.2.tgz#ffe59ef7522ada0a2d1cb5dfe03bb8abc3cdc133" + integrity sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw== + dependencies: + isarray "^2.0.5" + safe-buffer "^5.2.1" + typed-array-buffer "^1.0.3" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toggle-selection@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@^4.1.2: + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +ts-api-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + +ts-declaration-location@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz#d4068fe9975828b3b453b3ab112b4711d8267688" + integrity sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA== + dependencies: + picomatch "^4.0.2" + +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + +ts-interface-checker@^0.1.9: + version "0.1.13" + resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" + integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== + +ts-jest@^29.1.2, ts-jest@^29.4.0: + version "29.4.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.4.5.tgz#a6b0dc401e521515d5342234be87f1ca96390a6f" + integrity sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q== + dependencies: + bs-logger "^0.2.6" + fast-json-stable-stringify "^2.1.0" + handlebars "^4.7.8" + json5 "^2.2.3" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.7.3" + type-fest "^4.41.0" + yargs-parser "^21.1.1" + +ts-jest@~29.0.4: + version "29.0.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.0.5.tgz#c5557dcec8fe434fcb8b70c3e21c6b143bfce066" + integrity sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "7.x" + yargs-parser "^21.0.1" + +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tsconfig@7: + version "7.0.0" + resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" + integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== + dependencies: + "@types/strip-bom" "^3.0.0" + "@types/strip-json-comments" "0.0.30" + strip-bom "^3.0.0" + strip-json-comments "^2.0.0" + +tslib@1.14.1, tslib@^1.11.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tslib@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.0, tslib@^2.6.3, tslib@^2.8.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsx@^4.20.3: + version "4.20.6" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.20.6.tgz#8fb803fd9c1f70e8ccc93b5d7c5e03c3979ccb2e" + integrity sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg== + dependencies: + esbuild "~0.25.0" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + +tweetnacl-util@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-fest@^4.41.0: + version "4.41.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58" + integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA== + +type-fest@~2.19: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + +type-is@^2.0.0, type-is@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" + integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== + dependencies: + content-type "^1.0.5" + media-typer "^1.1.0" + mime-types "^3.0.0" + +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== + dependencies: + call-bound "^1.0.3" + es-errors "^1.3.0" + is-typed-array "^1.1.14" + +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== + dependencies: + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" + +typed-array-byte-offset@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + for-each "^0.3.3" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" + +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" + +typescript@^5, typescript@^5.1.3, typescript@^5.6.3, typescript@^5.8.3, typescript@^5.9.2: + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + +ua-is-frozen@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ua-is-frozen/-/ua-is-frozen-0.1.2.tgz#bfbc5f06336e379590e36beca444188c7dc3a7f3" + integrity sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw== + +ua-parser-js@^0.7.33: + version "0.7.41" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.41.tgz#9f6dee58c389e8afababa62a4a2dc22edb69a452" + integrity sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg== + +ua-parser-js@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-2.0.6.tgz#1dd221f7f2a27357c6a342296852f6391d77d4f0" + integrity sha512-EmaxXfltJaDW75SokrY4/lXMrVyXomE/0FpIIqP2Ctic93gK7rlme55Cwkz8l3YZ6gqf94fCU7AnIkidd/KXPg== + dependencies: + detect-europe-js "^0.1.2" + is-standalone-pwa "^0.1.1" + ua-is-frozen "^0.1.2" + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +ufo@^1.6.1, ufo@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.3.tgz#799666e4e88c122a9659805e30b9dc071c3aed4f" + integrity sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q== + +uglify-js@^3.1.4: + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== + +uint8arrays@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.0.tgz#8186b8eafce68f28bd29bd29d683a311778901e2" + integrity sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog== + dependencies: + multiformats "^9.4.2" + +uint8arrays@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" + integrity sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg== + dependencies: + multiformats "^9.4.2" + +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== + dependencies: + call-bound "^1.0.3" + has-bigints "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" + +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg== + +uncrypto@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" + integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== + +undici-types@^7.19.2: + version "7.22.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.22.0.tgz#f1f394e65ae60c18b4d4a7681fec11361d2e5ae5" + integrity sha512-RKZvifiL60xdsIuC80UY0dq8Z7DbJUV8/l2hOVbyZAxBzEeQU4Z58+4ZzJ6WN2Lidi9KzT5EbiGX+PI/UGYuRw== + +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== + +undici@^6.18.2: + version "6.22.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.22.0.tgz#281adbc157af41da8e75393c9d75a1b788811bc3" + integrity sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw== + +unfetch@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" + integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" + integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz#65a7adfad8574c219890e219285ce4c64ed67eaa" + integrity sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz#301d4f8a43d2b75c97adfad87c9dd5350c9475d1" + integrity sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ== + +unimodules-app-loader@~6.0.7: + version "6.0.7" + resolved "https://registry.yarnpkg.com/unimodules-app-loader/-/unimodules-app-loader-6.0.7.tgz#d88db74075815bcdc088c6c6823a2b08394a1225" + integrity sha512-23iwxmh6/y54PRGJt/xjsOpPK8vlfusBisi3yaVSK22pxg5DmiL/+IHCtbb/crHC+gqdItcy1OoRsZQHfNSBaw== + +unique-string@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + +universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.3.tgz#c05870a58125a2dc00431f2df815a77fe69736be" + integrity sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unrs-resolver@^1.6.2, unrs-resolver@^1.7.11: + version "1.11.1" + resolved "https://registry.yarnpkg.com/unrs-resolver/-/unrs-resolver-1.11.1.tgz#be9cd8686c99ef53ecb96df2a473c64d304048a9" + integrity sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg== + dependencies: + napi-postinstall "^0.3.0" + optionalDependencies: + "@unrs/resolver-binding-android-arm-eabi" "1.11.1" + "@unrs/resolver-binding-android-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-arm64" "1.11.1" + "@unrs/resolver-binding-darwin-x64" "1.11.1" + "@unrs/resolver-binding-freebsd-x64" "1.11.1" + "@unrs/resolver-binding-linux-arm-gnueabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm-musleabihf" "1.11.1" + "@unrs/resolver-binding-linux-arm64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-arm64-musl" "1.11.1" + "@unrs/resolver-binding-linux-ppc64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-riscv64-musl" "1.11.1" + "@unrs/resolver-binding-linux-s390x-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-gnu" "1.11.1" + "@unrs/resolver-binding-linux-x64-musl" "1.11.1" + "@unrs/resolver-binding-wasm32-wasi" "1.11.1" + "@unrs/resolver-binding-win32-arm64-msvc" "1.11.1" + "@unrs/resolver-binding-win32-ia32-msvc" "1.11.1" + "@unrs/resolver-binding-win32-x64-msvc" "1.11.1" + +unstorage@^1.9.0: + version "1.17.4" + resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.17.4.tgz#92a0bca7ea3781ba80b492939c6bed17418b12f2" + integrity sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw== + dependencies: + anymatch "^3.1.3" + chokidar "^5.0.0" + destr "^2.0.5" + h3 "^1.15.5" + lru-cache "^11.2.0" + node-fetch-native "^1.6.7" + ofetch "^1.5.1" + ufo "^1.6.3" + +update-browserslist-db@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz#7802aa2ae91477f255b86e0e46dbc787a206ad4a" + integrity sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +update-browserslist-db@^1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz#64d76db58713136acbeb4c49114366cc6cc2e80d" + integrity sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +use-callback-ref@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== + dependencies: + tslib "^2.0.0" + +use-interval@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-interval/-/use-interval-1.4.0.tgz#d0d24a359664373c0ed3f64768c99022a59cfce3" + integrity sha512-1betIJun2rXKLxa30AFOBZCeZhsBJoJ/3+gkCeYbJ63lAR//EnAb1NjNeFqzgqeM7zQfR76rrCUaA8DvfgoOpA== + +use-latest-callback@^0.2.1: + version "0.2.6" + resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.2.6.tgz#e5ea752808c86219acc179ace0ae3c1203255e77" + integrity sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg== + +use-sidecar@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" + integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +use-sync-external-store@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" + integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== + +use-sync-external-store@^1.4.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" + integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== + +utf-8-validate@^5.0.2: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0, utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util@0.12.5, util@^0.12.4, util@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +v8-to-istanbul@^9.0.1: + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +validate-npm-package-name@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" + integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== + +valtio@1.13.2: + version "1.13.2" + resolved "https://registry.yarnpkg.com/valtio/-/valtio-1.13.2.tgz#e31d452d5da3550935417670aafd34d832dc7241" + integrity sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A== + dependencies: + derive-valtio "0.1.0" + proxy-compare "2.6.0" + use-sync-external-store "1.2.0" + +vary@^1, vary@^1.1.2, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +viem@2.23.2: + version "2.23.2" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.23.2.tgz#db395c8cf5f4fb5572914b962fb8ce5db09f681c" + integrity sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA== + dependencies: + "@noble/curves" "1.8.1" + "@noble/hashes" "1.7.1" + "@scure/bip32" "1.6.2" + "@scure/bip39" "1.5.4" + abitype "1.0.8" + isows "1.0.6" + ox "0.6.7" + ws "8.18.0" + +viem@>=2.29.0, viem@^2.1.1, viem@^2.21.0, viem@^2.21.26, viem@^2.27.2, viem@^2.31.7: + version "2.46.3" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.46.3.tgz#0927e4da4380d6c87c7506a7c6b14cbdc0f3802f" + integrity sha512-2LJS+Hyh2sYjHXQtzfv1kU9pZx9dxFzvoU/ZKIcn0FNtOU0HQuIICuYdWtUDFHaGXbAdVo8J1eCvmjkL9JVGwg== + dependencies: + "@noble/curves" "1.9.1" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" + abitype "1.2.3" + isows "1.0.7" + ox "0.12.4" + ws "8.18.3" + +vinyl-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz#96c1a3479b8c5392542c612029013b5b27f88bbf" + integrity sha512-LRBE2/g3C1hSHL2k/FynSZcVTRhEw8sb08oKGt/0hukZXwrh2m8nfy+r5yLhGEk7eFFuclhyIuPct/Bxlxk6rg== + dependencies: + bl "^1.2.1" + through2 "^2.0.3" + +vite@^5.4.8: + version "5.4.21" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.21.tgz#84a4f7c5d860b071676d39ba513c0d598fdc7027" + integrity sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.43" + rollup "^4.20.0" + optionalDependencies: + fsevents "~2.3.3" + +vlq@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.1.tgz#c003f6e7c0b4c1edd623fd6ee50bbc0d6a1de468" + integrity sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w== + +void-elements@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" + integrity sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w== + +w3c-keyname@^2.2.4: + version "2.2.8" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" + integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== + +w3c-xmlserializer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" + integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== + dependencies: + xml-name-validator "^4.0.0" + +wagmi@^2.15.0: + version "2.19.5" + resolved "https://registry.yarnpkg.com/wagmi/-/wagmi-2.19.5.tgz#72d1561f95be6cb50e13283397b4768eb6ffb9ac" + integrity sha512-RQUfKMv6U+EcSNNGiPbdkDtJwtuFxZWLmvDiQmjjBgkuPulUwDJsKhi7gjynzJdsx2yDqhHCXkKsbbfbIsHfcQ== + dependencies: + "@wagmi/connectors" "6.2.0" + "@wagmi/core" "2.22.1" + use-sync-external-store "1.4.0" + +walker@^1.0.7, walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +warn-once@0.1.1, warn-once@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/warn-once/-/warn-once-0.1.1.tgz#952088f4fb56896e73fd4e6a3767272a3fccce43" + integrity sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q== + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +web-vitals@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" + integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== + +"webextension-polyfill@>=0.10.0 <1.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.12.0.tgz#f62c57d2cd42524e9fbdcee494c034cae34a3d69" + integrity sha512-97TBmpoWJEE+3nFBQ4VocyCdLKfw54rFaJ6EVQYLBCXqCIpLSZkwGgASpv4oPt9gdKCJ80RJlcmNzNn008Ag6Q== + +webextension-polyfill@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz#ccb28101c910ba8cf955f7e6a263e662d744dbb8" + integrity sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +webpack-sources@^3.2.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.3.3.tgz#d4bf7f9909675d7a070ff14d0ef2a4f3c982c723" + integrity sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg== + +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + +whatwg-fetch@^3.0.0: + version "3.6.20" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" + integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== + +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== + +whatwg-url-without-unicode@8.0.0-3: + version "8.0.0-3" + resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b" + integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig== + dependencies: + buffer "^5.4.3" + punycode "^2.1.1" + webidl-conversions "^5.0.0" + +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== + dependencies: + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" + +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== + dependencies: + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" + is-generator-function "^1.0.10" + is-regex "^1.2.1" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" + +which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which-typed-array@^1.1.16, which-typed-array@^1.1.19, which-typed-array@^1.1.2: + version "1.1.19" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.19.tgz#df03842e870b6b88e117524a4b364b6fc689f956" + integrity sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.4" + for-each "^0.3.5" + get-proto "^1.0.1" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wonka@^6.3.2: + version "6.3.5" + resolved "https://registry.yarnpkg.com/wonka/-/wonka-6.3.5.tgz#33fa54ea700ff3e87b56fe32202112a9e8fea1a2" + integrity sha512-SSil+ecw6B4/Dm7Pf2sAshKQ5hWFvfyGlfPbEd6A14dOH6VDjrmbY86u6nZvy9omGwwIPFR8V41+of1EezgoUw== + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +writable-consumable-stream@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/writable-consumable-stream/-/writable-consumable-stream-4.2.0.tgz#731cb8bc7c16d5e120adfaddd7d41c52179934d7" + integrity sha512-A2g0/Xaq/I2DQlYofh7nvKaJYZ0v4UOKuNLePG/G1ylx7p8e904jMTKhS+cdHNO1OulZpP2ModXs37EkG6tqSQ== + dependencies: + consumable-stream "^3.0.0" + +write-file-atomic@^2.3.0: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +write-file-atomic@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + +ws@8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== + +ws@8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +ws@8.18.3, ws@^8.11.0, ws@^8.12.1, ws@^8.18.0, ws@^8.18.3, ws@^8.5.0, ws@~8.18.3: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +ws@^6.2.3: + version "6.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee" + integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA== + dependencies: + async-limiter "~1.0.0" + +ws@^7, ws@^7.5.1, ws@^7.5.10: + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== + +ws@^8.19.0: + version "8.19.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.19.0.tgz#ddc2bdfa5b9ad860204f5a72a4863a8895fd8c8b" + integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg== + +xcode@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/xcode/-/xcode-3.0.1.tgz#3efb62aac641ab2c702458f9a0302696146aa53c" + integrity sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA== + dependencies: + simple-plist "^1.1.0" + uuid "^7.0.3" + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +xml2js@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282" + integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-14.0.0.tgz#876b5aec4f05ffd5feb97b0a871c855d16fbeb8c" + integrity sha512-ts+B2rSe4fIckR6iquDjsKbQFK2NlUk6iG5nf14mDEyldgoc2nEKZ3jZWMPTxGQwVgToSjt6VGIho1H8/fNFTg== + +xmlbuilder@^15.1.1: + version "15.1.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" + integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + +xmlhttprequest-ssl@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz#e9e8023b3f29ef34b97a859f584c5e6c61418e23" + integrity sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ== + +xtend@^4.0.1, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" + integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== + +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yaml@^2.2.2, yaml@^2.6.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.1.tgz#1870aa02b631f7e8328b93f8bc574fac5d6c4d79" + integrity sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.3.1, yargs@^17.5.1, yargs@^17.6.2, yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yarn@^1.22.22: + version "1.22.22" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.22.tgz#ac34549e6aa8e7ead463a7407e1c7390f61a6610" + integrity sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zod-to-json-schema@^3.24.1, zod-to-json-schema@^3.24.6: + version "3.24.6" + resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz#5920f020c4d2647edfbb954fa036082b92c9e12d" + integrity sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg== + +zod@3.22.4: + version "3.22.4" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" + integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== + +zod@^3.23.8, zod@^3.24.4, zod@^3.25.76: + version "3.25.76" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34" + integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ== + +zod@^4.1.5: + version "4.3.6" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.3.6.tgz#89c56e0aa7d2b05107d894412227087885ab112a" + integrity sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg== + +zustand@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.0.tgz#71f8aaecf185592a3ba2743d7516607361899da9" + integrity sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ== + +zustand@5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.3.tgz#b323435b73d06b2512e93c77239634374b0e407f" + integrity sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg== + +zustand@^5.0.1: + version "5.0.11" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.11.tgz#99f912e590de1ca9ce6c6d1cab6cdb1f034ab494" + integrity sha512-fdZY+dk7zn/vbWNCYmzZULHRrss0jx5pPFiOuMZ/5HJN6Yv3u+1Wswy/4MpZEkEGhtNH+pwxZB8OKgUBPzYAGg== diff --git a/audits/2024_02_23-halo2-zk.pdf b/audits/2024_02_23-halo2-zk.pdf deleted file mode 100644 index cc42ac7..0000000 Binary files a/audits/2024_02_23-halo2-zk.pdf and /dev/null differ diff --git a/audits/2024_12_05-burn-replacement_.pdf b/audits/2024_12_05-burn-replacement_.pdf deleted file mode 100644 index de2de12..0000000 Binary files a/audits/2024_12_05-burn-replacement_.pdf and /dev/null differ diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000..0a03c0e --- /dev/null +++ b/clippy.toml @@ -0,0 +1,25 @@ +allow-unwrap-in-tests = true +allow-expect-in-tests = true + +# if you're seeing this message, you can opt out with `#[allow(clippy::disallowed_methods)]`, but only if you know what you're doing ^-^ +disallowed-methods = [ + + # we ban serialization/deserialization traits because we want to guarantee that any data which: + # - is written by one version of a crate + # - is read by another version of a crate + # is properly versioned. + # + # We use the `wire_message::WireMessage` trait for this, which provides `WireMessage::to_vec` and `WireMessage::from_bytes`, + # which allow for serialization, but require that the type implements this trait + { path = "borsh::to_vec", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, + { path = "borsh::to_writer", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, + { path = "borsh::from_slice", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, + + # we'll re-enable these when we have our own macro for borsh - we need to include `#[allow(clippy::disallowed_methods)]` in the output of the macro but I don't have time now + + # { path = "borsh::BorshSerialize::serialize", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, + # { path = "borsh::BorshDeserialize::deserialize", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, + # { path = "borsh::BorshDeserialize::deserialize_reader", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, + # { path = "borsh::BorshDeserialize::try_from_slice", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, + # { path = "borsh::BorshDeserialize::try_from_reader", reason = "all wire messages should go through the `wire_message::WireMessage` trait" }, +] diff --git a/docker/Dockerfile.node b/docker/Dockerfile.node new file mode 100644 index 0000000..e5a446d --- /dev/null +++ b/docker/Dockerfile.node @@ -0,0 +1,222 @@ +# Build binary +FROM rust:1-bookworm AS workspace + +ARG SCCACHE_GCS_BUCKET +ARG SCCACHE_GCS_KEY_PREFIX + +RUN rustup component add rustfmt && \ + apt update && apt install -y libglib2.0-dev libssl-dev libclang-dev libpq-dev pkg-config python3 protobuf-compiler libprotobuf-dev cmake ninja-build curl + +# Ensure the toolchain specified in rust-toolchain.toml is installed +RUN rustup show + +# Set `SYSROOT` to a dummy path (default is /usr) because pkg-config-rs *always* +# links those located in that path dynamically but we want static linking, c.f. +# https://github.com/rust-lang/pkg-config-rs/blob/54325785816695df031cef3b26b6a9a203bbc01b/src/lib.rs#L613 +ENV SYSROOT=/dummy + + +# Conditional sccache setup: Only if bucket and key are provided +RUN --mount=type=secret,id=gcs_sa_key_base64,required=false \ + if [ -n "$SCCACHE_GCS_BUCKET" ] && [ -f /run/secrets/gcs_sa_key_base64 ]; then \ + cat /run/secrets/gcs_sa_key_base64 | base64 -d > /gcs_key.json && \ + wget https://github.com/mozilla/sccache/releases/download/v0.10.0/sccache-v0.10.0-x86_64-unknown-linux-musl.tar.gz && \ + tar -xzf sccache-v0.10.0-x86_64-unknown-linux-musl.tar.gz && \ + mv sccache-v0.10.0-x86_64-unknown-linux-musl/sccache /usr/local/cargo/bin/sccache && \ + rm -rf sccache-v0.10.0-x86_64-unknown-linux-musl sccache-v0.10.0-x86_64-unknown-linux-musl.tar.gz && \ + chmod +x /usr/local/cargo/bin/sccache; \ + fi +ENV SCCACHE_GCS_KEY_PATH=/gcs_key.json +ENV SCCACHE_GCS_BUCKET=$SCCACHE_GCS_BUCKET +ENV SCCACHE_GCS_KEY_PREFIX=$SCCACHE_GCS_KEY_PREFIX +ENV SCCACHE_GCS_RW_MODE=READ_WRITE + + +WORKDIR /build + + +FROM workspace AS tester + +SHELL ["/bin/bash", "--login", "-c"] + +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +RUN nvm install 20 \ + && ln -s "$(which node)" /usr/bin/node \ + && ln -s "$(which npm)" /usr/bin/npm \ + && npm install --global yarn \ + && ln -s "$(which yarn)" /usr/bin/yarn + +# Keep in sync with the solc pin in pkg/xtask/src/noir_fixtures/runner.rs. +ARG SOLC_VERSION=0.8.29+commit.ab55807c +ARG SOLC_SHA256_LINUX=18d418a40dc04d17656b1b5c8a7b35cfbab8942b51f38d005d5b59e8aa6637e0 + +RUN curl -fsSL \ + "https://binaries.soliditylang.org/linux-amd64/solc-linux-amd64-v${SOLC_VERSION}" \ + -o /usr/local/bin/solc \ + && echo "${SOLC_SHA256_LINUX} /usr/local/bin/solc" | sha256sum -c - \ + && chmod +x /usr/local/bin/solc + +# Download and install barretenberg +RUN wget https://storage.googleapis.com/payy-public-fixtures/bb/v3.0.0-manual.20251030/barretenberg-amd64-linux.tar.gz -O barretenberg.tar.gz && \ + echo "88586691621fdbf6105e064aca1b6e4f1f5345f2e75560d1d385693019480697 barretenberg.tar.gz" | sha256sum -c - && \ + tar -xzf barretenberg.tar.gz && \ + mv bb /usr/local/bin/bb && \ + rm barretenberg.tar.gz + +# bb requires a recent glibcxx version +# Enable backports and pull libstdc++ 13.x (exports GLIBCXX_3.4.31) +# also installs jq, some bb commands require jq +RUN echo 'deb http://deb.debian.org/debian testing main' \ + > /etc/apt/sources.list.d/testing.list && \ + echo 'APT::Default-Release "stable";' \ + > /etc/apt/apt.conf.d/99defaultrelease && \ + apt-get update && \ + # pull only the two runtime libs from testing + DEBIAN_FRONTEND=noninteractive \ + apt-get install -y -t testing libc6 libstdc++6 jq + +SHELL ["sh", "-c"] + +ARG RELEASE=1 +ENV RELEASE=$RELEASE + +COPY rust-toolchain.toml ./ + +COPY . . + +RUN ./scripts/download-fixtures-params.sh + +# Run tests as part of RUN, not CMD, because prebuilding and running tests is tricky +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + chmod +x ./docker/test.sh && \ + if [ -f /gcs_key.json ]; then \ + echo "Using sccache with GCS for tests"; \ + RUSTC_WRAPPER=/usr/local/cargo/bin/sccache exec ./docker/test.sh && \ + sccache --show-stats && \ + sccache --stop-server; \ + else \ + echo "Skipping sccache for tests"; \ + exec ./docker/test.sh; \ + fi + +CMD ["sh", "-c", "echo 'This image is not meant to be run, only built.' && exit 1"] + + +# Build binary +FROM workspace AS builder + +ARG RELEASE=1 + +COPY rust-toolchain.toml ./ + + +COPY rust-toolchain.toml ./ +COPY .cargo/config.toml .cargo/config.toml +COPY Cargo.lock ./ +COPY Cargo.toml ./ +COPY scripts ./scripts +COPY pkg ./pkg +COPY noir ./noir + +# Remove app package as its not needed +RUN sed 's|, "app/packages/react-native-rust-bridge/cpp/rustbridge"||g' Cargo.toml > Cargo.toml.tmp \ + && mv Cargo.toml.tmp Cargo.toml + +# Add fixtures +COPY eth/artifacts/contracts ./eth/artifacts/contracts +COPY fixtures/circuits ./fixtures/circuits +COPY fixtures/params ./fixtures/params + +RUN --mount=type=cache,target=/usr/local/cargo/registry \ + build_flags=$([ "$RELEASE" = "1" ] && echo "--release"); \ + if [ -f /gcs_key.json ]; then \ + echo "Using sccache with GCS"; \ + if RUSTC_WRAPPER=/usr/local/cargo/bin/sccache cargo build --bin node ${build_flags}; then \ + sccache --show-stats && \ + sccache --stop-server; \ + else \ + status=$?; \ + echo "sccache-backed build failed (exit ${status}); retrying without sccache"; \ + sccache --stop-server || true; \ + cargo build --bin node ${build_flags}; \ + fi; \ + else \ + echo "Skipping sccache (missing required vars)"; \ + cargo build --bin node ${build_flags}; \ + fi + +RUN cp /build/target/$([ "$RELEASE" = "1" ] && echo "release" || echo "debug")/node /build/target + + +# Runtime stage - can be used for both node and prover mode +FROM debian:bookworm-slim as runtime + +ENV ROOT_DIR /polybase +WORKDIR $ROOT_DIR + +USER root + +RUN groupadd -g 1001 --system spaceman && \ + useradd -u 1001 --system --gid spaceman --home "$ROOT_DIR" spaceman && \ + chown -R spaceman:spaceman "$ROOT_DIR" + +RUN apt update && apt install -y curl nano libpq-dev postgresql wget tar curl + +# Download and install barretenberg +RUN wget https://storage.googleapis.com/payy-public-fixtures/bb/v3.0.0-manual.20251030/barretenberg-amd64-linux.tar.gz -O barretenberg.tar.gz && \ + echo "88586691621fdbf6105e064aca1b6e4f1f5345f2e75560d1d385693019480697 barretenberg.tar.gz" | sha256sum -c - && \ + tar -xzf barretenberg.tar.gz && \ + mv bb /usr/local/bin/bb && \ + rm barretenberg.tar.gz + +# Enable backports and pull libstdc++ 13.x (exports GLIBCXX_3.4.31) +# also installs jq, some bb commands require jq +RUN echo 'deb http://deb.debian.org/debian testing main' \ + > /etc/apt/sources.list.d/testing.list && \ + echo 'APT::Default-Release "stable";' \ + > /etc/apt/apt.conf.d/99defaultrelease && \ + apt-get update && \ + # pull only the two runtime libs from testing + DEBIAN_FRONTEND=noninteractive \ + apt-get install -y -t testing libc6 libstdc++6 jq + +# Create directories and set permissions for spaceman user +# Create directories for both node and prover modes +RUN mkdir -p /tmp /.bb-crs /polybase/.polybase-prover/db /polybase/.polybase-prover/smirk && \ + chown spaceman:spaceman /tmp /.bb-crs /polybase/.polybase-prover /polybase/.polybase-prover/db /polybase/.polybase-prover/smirk && \ + chmod 755 /tmp /.bb-crs /polybase/.polybase-prover /polybase/.polybase-prover/db /polybase/.polybase-prover/smirk + +COPY --from=builder /build/scripts/download-fixtures-params.sh /usr/local/bin/download-fixtures-params.sh +RUN chmod +x /usr/local/bin/download-fixtures-params.sh + +ARG WAIT_SECONDS=0 + +ENV WAIT_SECONDS=$WAIT_SECONDS + +RUN echo '#!/bin/bash\n\ + if [ "$WAIT_SECONDS" -gt 0 ]; then\n\ + echo "Waiting $WAIT_SECONDS seconds before starting..."\n\ + sleep $WAIT_SECONDS\n\ + fi\n\ + exec "$@"' > /entrypoint-wrapper.sh && chmod +x /entrypoint-wrapper.sh + +USER spaceman + +RUN /usr/local/bin/download-fixtures-params.sh + +COPY --from=builder /build/target/node /usr/bin/node + +STOPSIGNAL SIGTERM + +# Expose both potential ports (node and prover) +EXPOSE 8080 8091 8092 + +# TODO: re-enable healthcheck once we have RPC +# HEALTHCHECK --interval=5s --timeout=5s --retries=3 CMD \ +# curl -f http://localhost:8080/v0/health || exit 1 + +# Default entrypoint for node mode +# For prover mode, override CMD in docker-compose.yml +ENTRYPOINT ["/entrypoint-wrapper.sh", "/usr/bin/node"] + +VOLUME [ "$ROOT_DIR" ] diff --git a/docker/test.sh b/docker/test.sh new file mode 100755 index 0000000..bd5ab2b --- /dev/null +++ b/docker/test.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +set -euo pipefail + +cd eth +yarn +yarn compile +cd .. + +# Number of times to retry the test command +RETRIES=3 +# Delay in seconds between retries +DELAY=5 + +for i in $(seq 1 $RETRIES); do + echo "Running cargo test (attempt $i/$RETRIES)..." + # The `if` statement below is used to handle the exit code from `cargo test`. + # This prevents the script from exiting immediately if the test fails because of `set -e`. + # + # `${RELEASE:-0}` provides a default value for the RELEASE environment variable. + # This prevents an "unbound variable" error if it's not set when `set -u` is active. + if cargo test $(if [ "${RELEASE:-0}" = "1" ]; then echo "--release"; fi) \ + --features smirk/slow-storage-tests \ + -- \ + --skip generate_aggregate --skip generate_utxo --skip integration_test; then + echo "cargo test passed successfully on attempt $i." + exit 0 + fi + + # If this wasn't the last attempt, wait before trying again. + if [ $i -lt $RETRIES ]; then + echo "cargo test failed. Retrying in $DELAY seconds..." + sleep $DELAY + fi +done + +# If the loop completes without a successful run, exit with an error. +echo "cargo test failed after $RETRIES attempts." +exit 1 diff --git a/docs/public/.gitbook/assets/L2 Rollup-L2 Rollup.drawio.png b/docs/public/.gitbook/assets/L2 Rollup-L2 Rollup.drawio.png new file mode 100644 index 0000000..b8bd1bc Binary files /dev/null and b/docs/public/.gitbook/assets/L2 Rollup-L2 Rollup.drawio.png differ diff --git a/docs/public/.gitbook/assets/Levels of privacy (1).png b/docs/public/.gitbook/assets/Levels of privacy (1).png new file mode 100644 index 0000000..5216065 Binary files /dev/null and b/docs/public/.gitbook/assets/Levels of privacy (1).png differ diff --git a/docs/public/.gitbook/assets/Levels of privacy.png b/docs/public/.gitbook/assets/Levels of privacy.png new file mode 100644 index 0000000..b81fd07 Binary files /dev/null and b/docs/public/.gitbook/assets/Levels of privacy.png differ diff --git a/docs/public/.gitbook/assets/image (1).png b/docs/public/.gitbook/assets/image (1).png new file mode 100644 index 0000000..9af92b9 Binary files /dev/null and b/docs/public/.gitbook/assets/image (1).png differ diff --git a/docs/public/.gitbook/assets/image (10).png b/docs/public/.gitbook/assets/image (10).png new file mode 100644 index 0000000..627781f Binary files /dev/null and b/docs/public/.gitbook/assets/image (10).png differ diff --git a/docs/public/.gitbook/assets/image (11).png b/docs/public/.gitbook/assets/image (11).png new file mode 100644 index 0000000..1a3dd83 Binary files /dev/null and b/docs/public/.gitbook/assets/image (11).png differ diff --git a/docs/public/.gitbook/assets/image (12).png b/docs/public/.gitbook/assets/image (12).png new file mode 100644 index 0000000..824230a Binary files /dev/null and b/docs/public/.gitbook/assets/image (12).png differ diff --git a/docs/public/.gitbook/assets/image (13).png b/docs/public/.gitbook/assets/image (13).png new file mode 100644 index 0000000..9457ef2 Binary files /dev/null and b/docs/public/.gitbook/assets/image (13).png differ diff --git a/docs/public/.gitbook/assets/image (14).png b/docs/public/.gitbook/assets/image (14).png new file mode 100644 index 0000000..9457ef2 Binary files /dev/null and b/docs/public/.gitbook/assets/image (14).png differ diff --git a/docs/public/.gitbook/assets/image (15).png b/docs/public/.gitbook/assets/image (15).png new file mode 100644 index 0000000..2545384 Binary files /dev/null and b/docs/public/.gitbook/assets/image (15).png differ diff --git a/docs/public/.gitbook/assets/image (16).png b/docs/public/.gitbook/assets/image (16).png new file mode 100644 index 0000000..bca5b90 Binary files /dev/null and b/docs/public/.gitbook/assets/image (16).png differ diff --git a/docs/public/.gitbook/assets/image (2).png b/docs/public/.gitbook/assets/image (2).png new file mode 100644 index 0000000..5178603 Binary files /dev/null and b/docs/public/.gitbook/assets/image (2).png differ diff --git a/docs/public/.gitbook/assets/image (3).png b/docs/public/.gitbook/assets/image (3).png new file mode 100644 index 0000000..5d4b0d0 Binary files /dev/null and b/docs/public/.gitbook/assets/image (3).png differ diff --git a/docs/public/.gitbook/assets/image (4).png b/docs/public/.gitbook/assets/image (4).png new file mode 100644 index 0000000..15bb690 Binary files /dev/null and b/docs/public/.gitbook/assets/image (4).png differ diff --git a/docs/public/.gitbook/assets/image (5).png b/docs/public/.gitbook/assets/image (5).png new file mode 100644 index 0000000..5f20dbd Binary files /dev/null and b/docs/public/.gitbook/assets/image (5).png differ diff --git a/docs/public/.gitbook/assets/image (6).png b/docs/public/.gitbook/assets/image (6).png new file mode 100644 index 0000000..4754c1e Binary files /dev/null and b/docs/public/.gitbook/assets/image (6).png differ diff --git a/docs/public/.gitbook/assets/image (7).png b/docs/public/.gitbook/assets/image (7).png new file mode 100644 index 0000000..5ba3793 Binary files /dev/null and b/docs/public/.gitbook/assets/image (7).png differ diff --git a/docs/public/.gitbook/assets/image (8).png b/docs/public/.gitbook/assets/image (8).png new file mode 100644 index 0000000..2b32ac7 Binary files /dev/null and b/docs/public/.gitbook/assets/image (8).png differ diff --git a/docs/public/.gitbook/assets/image (9).png b/docs/public/.gitbook/assets/image (9).png new file mode 100644 index 0000000..85c97d0 Binary files /dev/null and b/docs/public/.gitbook/assets/image (9).png differ diff --git a/docs/public/.gitbook/assets/image.png b/docs/public/.gitbook/assets/image.png new file mode 100644 index 0000000..9af92b9 Binary files /dev/null and b/docs/public/.gitbook/assets/image.png differ diff --git a/docs/public/.gitbook/assets/levels-of-privacy2.png b/docs/public/.gitbook/assets/levels-of-privacy2.png new file mode 100644 index 0000000..3f83724 Binary files /dev/null and b/docs/public/.gitbook/assets/levels-of-privacy2.png differ diff --git a/docs/public/.gitbook/assets/network upgrade.png b/docs/public/.gitbook/assets/network upgrade.png new file mode 100644 index 0000000..01ab08a Binary files /dev/null and b/docs/public/.gitbook/assets/network upgrade.png differ diff --git a/docs/public/.gitbook/assets/network upgrade2.png b/docs/public/.gitbook/assets/network upgrade2.png new file mode 100644 index 0000000..0ce8c85 Binary files /dev/null and b/docs/public/.gitbook/assets/network upgrade2.png differ diff --git a/docs/public/.gitbook/assets/privacy arch.png b/docs/public/.gitbook/assets/privacy arch.png new file mode 100644 index 0000000..5bb858a Binary files /dev/null and b/docs/public/.gitbook/assets/privacy arch.png differ diff --git a/docs/public/.gitbook/assets/privacy vault + rpc.png b/docs/public/.gitbook/assets/privacy vault + rpc.png new file mode 100644 index 0000000..e0e8287 Binary files /dev/null and b/docs/public/.gitbook/assets/privacy vault + rpc.png differ diff --git a/docs/public/.gitbook/assets/privacy vault2.png b/docs/public/.gitbook/assets/privacy vault2.png new file mode 100644 index 0000000..36e60a9 Binary files /dev/null and b/docs/public/.gitbook/assets/privacy vault2.png differ diff --git a/docs/public/.gitbook/assets/privacy-vault-3.png b/docs/public/.gitbook/assets/privacy-vault-3.png new file mode 100644 index 0000000..4422295 Binary files /dev/null and b/docs/public/.gitbook/assets/privacy-vault-3.png differ diff --git a/docs/public/.gitbook/assets/stealth trans.png b/docs/public/.gitbook/assets/stealth trans.png new file mode 100644 index 0000000..c27bc58 Binary files /dev/null and b/docs/public/.gitbook/assets/stealth trans.png differ diff --git a/docs/public/.gitbook/assets/unknown.svg+xml b/docs/public/.gitbook/assets/unknown.svg+xml new file mode 100644 index 0000000..a93b4f5 --- /dev/null +++ b/docs/public/.gitbook/assets/unknown.svg+xml @@ -0,0 +1 @@ +
Aggregation
Circuit
Aggregation...
UTXO
Circuit
UTXO...
Inserts Leafs
(4 per UTXO)
Inserts Leafs...
Recent Root
(1 per UTXO)
(to verify Input Notes)
Recent Root...
UTXO Aggregation & Inclusion Circuit
UTXO Aggregation & Incl...
Client
Client
Privacy
Prover
PrivacyPro...
Proof
Proof
Mint+Burn Hash/Value
(2 per UTXO)
Mint+Burn Has...
Verify
Aggregation Circuit Proof
Verify...
Proof
Proof
Mint+Burn Hash/Value
(2 per UTXO)
Mint+Burn Hash/Value...
Recent Roots
(1 per UTXO)
Recent Roots...
Insert Leafs  (4 per UTXO)
Insert Leafs  (4 per...
(Input) Notes x2
(Input) Notes x2
(Output) Notes x 2
(Output) Notes x 2
Recent Root
(to verify Input Notes)
Recent Root...
per UTXO
per UTXO
New Root
New Root
Payy Prover
Payy Prover
Old Root
Old Root
Merkle Path
Merkle Path
Private Key
Private Key
New Root
New Root
Old Root
Old Root
Proof
Proof
Merkle Tree Path
(1 per Insert Leaf)
Merkle Tree Path...
Public Input
Public Input
Private Input
Private Input
Proof
Proof
ZK Circuit
ZK Circuit
Recent Roots
(1 per UTXO)
Recent Roots...
Inserts Leafs
(4 per UTXO)
Inserts Leafs...
Paths for each insert leaf
Paths for each insert leaf
Smirk Merkle Tree
Smirk Merkle Tree
Mint+Burn Hash/Value
(2 per UTXO)
Mint+Burn Hash/Value...
Verify
EVM Layer Proof
Verify...
Recursive
Recursive
Text is not SVG - cannot display
\ No newline at end of file diff --git a/docs/public/.gitbook/assets/zk-circuits-privacy-rollup.png b/docs/public/.gitbook/assets/zk-circuits-privacy-rollup.png new file mode 100644 index 0000000..0c5ff3c Binary files /dev/null and b/docs/public/.gitbook/assets/zk-circuits-privacy-rollup.png differ diff --git a/docs/public/README.md b/docs/public/README.md new file mode 100644 index 0000000..20c3fec --- /dev/null +++ b/docs/public/README.md @@ -0,0 +1,42 @@ +--- +metaLinks: + alternates: + - https://app.gitbook.com/s/yE16Xb3IemPxJWydtPOj/ +--- + +# Payy + +Payy is the first EVM compatible stablecoin chain with privacy at every layer. + +### Privacy-first + +Payy was purpose built for privacy. Privacy is not a feature that can be added as an afterthought. True usable privacy requires a holistic, thoughtful and complete approach. + +### Stablecoin native + +Stablecoins need dedicated features. Payy makes working with stables and payments seamless, unlocking wide adoption by consumers and business. + +### EVM compatible + +Every EVM opcode is supported. Ramps, wallets and application developers can build on Payy using their existing tooling. Privacy is transparently layered in without any breaking changes to the EVM protocol. + +### Key features + +Payy is purpose built to enable privacy for stablecoin payments and finance. + +| Feature | Payy | Ethereum | +| ----------------------- | ------------------------- | ----------- | +| EVM compatible | ✅ | ✅ | +| Finality | 300ms (deterministic) | 15 minutes | +| Throughput (tps) | Initially 10k, up to 100k | 12 | +| Avg ERC-20 transfer fee | $0 | $0.50 | +| Avg txn gas | $0.01 | $0.50 | +| Txn gas / fee | PUSD, PAYY | ETH | +| Privacy cryptography | Native ZK precompile | Unoptimised | + + + +### Jump right in + +

:hashtag-lock:

PrivacyPayy enables 3 native privacy flows.privacy-architecture.md

:dash:

StablecoinsFeatures to enable stablecoin use cases.Broken link

:trowel:

ArchitectureZK L2 rollup architecture.Broken link
+ diff --git a/docs/public/SUMMARY.md b/docs/public/SUMMARY.md new file mode 100644 index 0000000..07fc24b --- /dev/null +++ b/docs/public/SUMMARY.md @@ -0,0 +1,63 @@ +# Table of contents + +## Intro + +* [Payy](README.md) + +## Privacy + +* [Privacy Architecture](privacy/privacy-architecture.md) +* [Private Transfers](privacy/editor.md) +* [Stealth Transactions](privacy/stealth-transactions.md) +* [Native ZK](privacy/native-zk.md) + +## Stablecoins + +* [PUSD](stablecoins/pusd.md) +* [Stable Gas](stablecoins/stable-gas.md) +* [Zero Fee Payments](stablecoins/zero-fee-payments.md) +* [Payy Transactions](stablecoins/payy-transactions.md) + +## Build on Payy + +* [Get Started](build-on-payy/get-started.md) +* [Private Transfers](build-on-payy/private-transfers.md) +* [Payy Transactions](build-on-payy/payy-transactions/README.md) + * [Stealth](build-on-payy/payy-transactions/stealth.md) + * [Batch](build-on-payy/payy-transactions/batch.md) + * [Concurrency](build-on-payy/payy-transactions/concurrency.md) + * [Sponsor Gas](build-on-payy/payy-transactions/sponsor-gas.md) + * [Schedule](build-on-payy/payy-transactions/schedule.md) + * [Recurring](build-on-payy/payy-transactions/recurring.md) +* [Predeployed Contracts](build-on-payy/predeployed-contracts.md) +* [Wallet Compatibility](build-on-payy/wallet-compatibility.md) +* [Ethereum Compatibility](build-on-payy/ethereum-compatibility.md) + +## Tools + +* [Block Explorers](tools/block-explorers.md) +* [Compliance](tools/compliance.md) + +## Protocol + +* [Architecture](protocol/architecture.md) +* [Sequencers](protocol/sequencers.md) +* [Provers](protocol/provers.md) +* [Data Availability](protocol/data-availability.md) +* [EVM Layer](protocol/evm-layer.md) +* [Precompiles](protocol/precompiles.md) +* [Privacy Layer](protocol/privacy-layer/README.md) + * [Privacy Rollup](protocol/privacy-layer/privacy-rollup.md) + * [UTXO](protocol/privacy-layer/utxo.md) + * [Nullifiers](protocol/privacy-layer/nullifiers.md) + * [ZK Circuits](protocol/privacy-layer/zk-circuits.md) + * [Encrypted Lineage](protocol/privacy-layer/encrypted-lineage.md) +* [Privacy Vault](protocol/privacy-vault.md) +* [PrivacyVaultRegistry](protocol/privacyvaultregistry.md) +* [PrivacyBridge](protocol/privacybridge.md) +* [Rollup](protocol/rollup.md) +* [TransactionBridge](protocol/transactionbridge.md) + +## Tokenomics + +* [Tokenomics](tokenomics/tokenomics.md) diff --git a/docs/public/build-on-payy/ethereum-compatibility.md b/docs/public/build-on-payy/ethereum-compatibility.md new file mode 100644 index 0000000..ced28f9 --- /dev/null +++ b/docs/public/build-on-payy/ethereum-compatibility.md @@ -0,0 +1,47 @@ +# Ethereum Compatibility + +Payy is fully compatible with Ethereum and the EVM. All existing Ethereum tooling (such as Hardhat, Foundry, etc) will work seamlessly with Payy. + +Sequencers use the Reth execution environment, and Provers use a ZK implementation of the EVM execution environment - the Payy zkEVM. + +{% hint style="success" %} +Payy supports the Fusaka hard fork. +{% endhint %} + +### What's the same + +* Transaction construction is identical to Ethereum +* Address generation and signing work the same as Ethereum +* All EVM opcodes are supported +* All Ethereum precompiles are supported +* All Ethereum RPC endpoints are supported +* Tracing is supported +* Solidity and EVM bytecode will function identically + +### What's been changed/added + +Payy offers a superset of features to the Ethereum specification, designed to support privacy and stablecoin use cases. + +#### Precompiles + +Payy adds protocol-specific precompiles for proof verification, Poseidon hashing, sparse merkle tree maintenance, and millisecond timestamps. + +See [Precompiles](../protocol/precompiles.md) for the canonical address list, gas costs, calldata / return formats, and the distinction between public precompiles and internal-only protocol precompiles. + +#### Zero gas fees on private transfers + +Payy operates zero gas fees for `transfer` fn calls on the native [`PrivacyBridge`](../protocol/privacybridge.md) contract. This ensures that private ERC-20 transfers can be made for free. + +#### Consistent gas fee + +Gas fees remain consistent, a priority tip can be provided to prioritise transactions - see [Stable Gas](../stablecoins/stable-gas.md). + +#### Block times + +Payy produces blocks every 300ms. Ethereum `block.timestamp` only supports seconds granularity. To ensure compatibility `block.timestamp` remains unchanged. If sub-second granularity is required, then the `blockTimestampMs` pre-compile can be used. + +#### CodeSize + +`EXTCODESIZE` is expensive to calculate and verify in ZK, so we store the size on contract creation and use a storage proof instead. + + diff --git a/docs/public/build-on-payy/get-started.md b/docs/public/build-on-payy/get-started.md new file mode 100644 index 0000000..0842dd1 --- /dev/null +++ b/docs/public/build-on-payy/get-started.md @@ -0,0 +1,67 @@ +# Get Started + +{% hint style="warning" %} +Payy Testnet and NPM packages are currently invite only - reach out to hello@payy.link for access. +{% endhint %} + +Payy lets you authorise rich, wallet‑native transactions using typed signatures and execute them through the [TransactionBridge](../protocol/transactionbridge.md) with advanced features. + +You build Txn objects off‑chain with `@payy/viem`, sign them via EIP‑712, and send them through the bridge. After submission, inspect the transaction receipt and bridge status/events to confirm the outcome. Everything works with standard wallets and familiar viem primitives. + +### Install + +``` +npm install viem @payy/viem +# or +yarn add viem @payy/viem +``` + +### Minimal setup + +```typescript +import { createPublicClient, createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { createPayyClient, erc20 } from "@payy/viem"; +import { payy } from "@payy/viem/chains"; + +const account = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`); + +const publicClient = createPublicClient({ + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const walletClient = createWalletClient({ + account, + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const payyClient = createPayyClient(); +``` + +### Your first Txn: simple send + +```typescript +async function simpleSend() { + const txn = await payyClient.buildTxn + .from(account.address) + .calls([ + erc20.transfer({ + token: "0xYourERC20", + to: "0xRecipient", + amount: 1_000_000n, + gasLimit: 120_000n, + }), + ]); + + const { hash } = await payyClient.submitTxn({ txn, walletClient }); + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + + const txnHash = await payyClient.hashTxn({ txn, publicClient }); + + console.log("Sent on-chain tx:", hash); + console.log("Receipt status:", receipt.status); + console.log("Txn hash:", txnHash); +} +``` diff --git a/docs/public/build-on-payy/payy-transactions/README.md b/docs/public/build-on-payy/payy-transactions/README.md new file mode 100644 index 0000000..5c074dd --- /dev/null +++ b/docs/public/build-on-payy/payy-transactions/README.md @@ -0,0 +1,3 @@ +# Payy Transactions + +{% include "../../../../.gitbook/includes/toc-payy-transactions.md" %} diff --git a/docs/public/build-on-payy/payy-transactions/batch.md b/docs/public/build-on-payy/payy-transactions/batch.md new file mode 100644 index 0000000..35d877d --- /dev/null +++ b/docs/public/build-on-payy/payy-transactions/batch.md @@ -0,0 +1,80 @@ +# Batch + +Batch lets you make multiple calls to execute atomically in one Txn using the [TransactionBridge](../../protocol/transactionbridge.md). You sign a single Txn (EIP‑712 typed data) that includes an ordered array of calls. The bridge executes them in sequence within one transaction. + +You can choose: + +* `requireSuccess: true` - all calls must succeed or the whole batch reverts (i.e. atomic). +* `requireSuccess: false` - best‑effort, failing calls don’t revert the entire batch, and per‑call results are emitted in `TxnCallResult`. The transaction still finishes in the processed lifecycle state, while `TxnProcessed.success` flips to `false` if any subcall fails. + +This enables multi‑step workflows like approve + swap + transfer, complex settlements, multi‑recipient payouts, or protocol operations that must move together. + +### Example + +```typescript +import { createPublicClient, createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { + erc20, + createPayyClient, +} from "@payy/viem"; +import { payy } from "@payy/viem/chains"; + +const account = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`); + +const publicClient = createPublicClient({ + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const walletClient = createWalletClient({ + account, + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const payyClient = createPayyClient(); + +async function batchPayment() { + // Build a batch with three transfers, atomic by default (requireSuccess: true) + const txn = await payyClient.buildTxn + .calls([ + erc20.transfer({ + token: "0xYourERC20", + to: "0xAlice", + amount: 1_000_000n, + gasLimit: 80_000n, + }), + erc20.transfer({ + token: "0xYourERC20", + to: "0xBob", + amount: 2_500_000n, + gasLimit: 80_000n, + }), + erc20.transfer({ + token: "0xYourERC20", + to: "0xCarol", + amount: 750_000n, + gasLimit: 80_000n, + }), + ]) + .requireSuccess(true); // ensure all transfers succeed or all revert + + // Optional: best‑effort mode (partial success, emits per‑call results) + // .requireSuccess(false); + + // Send the batch on-chain + const { hash: txHash } = await payyClient.submitTxn({ + txn, + walletClient, + }); + const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + + const batchHash = await payyClient.hashTxn({ txn, publicClient }); + + console.log("Sent batch on-chain tx:", txHash); + // For best-effort batches, inspect receipt logs for TxnCallResult / TxnProcessed. + console.log("Batch receipt status:", receipt.status); + console.log("Batch Txn hash:", batchHash); +} +``` diff --git a/docs/public/build-on-payy/payy-transactions/concurrency.md b/docs/public/build-on-payy/payy-transactions/concurrency.md new file mode 100644 index 0000000..9484264 --- /dev/null +++ b/docs/public/build-on-payy/payy-transactions/concurrency.md @@ -0,0 +1,124 @@ +# Concurrency + +Concurrency runs multiple independent pipelines of transactions in parallel using distinct nonce spaces. Instead of a single, globally increasing nonce, you assign a logical key to each workflow (e.g., "payroll", "refunds", "ops"), so transactions in different streams don’t block each other. + +Each Txn includes a NonceSpace with: + +* key: bytes32 identifier for the stream (e.g., keccak256("payroll")) +* nonce: the expected next nonce for that key + +This enables: + +* Parallel workflows: submit/queue/execute across different keys without head-of-line blocking. +* Safer batching and retries: replays are scoped to a key; cancelling or failing one stream doesn’t affect others. +* Session keys: ephemeral domains for short-lived automations or per-device nonces. +* Cleaner integration with relayers: deterministic nextNonce(from, key) lookup per stream. + +### Best practices: + +* Choose human-meaningful keys off-chain and hash to bytes32. Example: `key = keccak256("payroll:2026-Q1")` . +* Increment nonce sequentially per key. Use `nextNonce(from, key)` to fetch the expected value before building a Txn. +* For scheduled or recurring Txns, you can keep the same key or dedicate keys per schedule/recurrence to avoid cross-interference. + +### Example + +```typescript +import { createPublicClient, createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { + erc20, + createPayyClient, +} from "@payy/viem"; +import { payy } from "@payy/viem/chains"; + +const account = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`); + +const publicClient = createPublicClient({ + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const walletClient = createWalletClient({ + account, + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const payyClient = createPayyClient(); + +async function concurrentPayments() { + // Two independent nonce spaces: "payroll" and "refunds" + const payrollKey = await payyClient.utils.keccak256Utf8("payroll:2026-Q1"); + const refundsKey = await payyClient.utils.keccak256Utf8("refunds"); + + // Look up expected nonces per key + const payrollNext = await payyClient.nextNonce({ + from: account.address, + key: payrollKey, + publicClient, + }); + + const refundsNext = await payyClient.nextNonce({ + from: account.address, + key: refundsKey, + publicClient, + }); + + // Build Txn in the payroll nonce space + const payrollTxn = await payyClient.buildTxn + .from(account.address) + .calls([ + erc20.transfer({ + token: "0xYourERC20", + to: "0xEmployeeA", + amount: 5_000_000n, + gasLimit: 120_000n, + }), + erc20.transfer({ + token: "0xYourERC20", + to: "0xEmployeeB", + amount: 4_500_000n, + gasLimit: 120_000n, + }), + ]) + .nonceSpace({ + key: payrollKey, // stream identifier + nonce: BigInt(payrollNext), // expected next nonce for this key + }); + + // Build Txn in the refunds nonce space (can proceed in parallel) + const refundTxn = await payyClient.buildTxn + .from(account.address) + .calls([ + erc20.transfer({ + token: "0xYourERC20", + to: "0xCustomerR", + amount: 250_000n, + gasLimit: 80_000n, + }), + ]) + .nonceSpace({ + key: refundsKey, + nonce: BigInt(refundsNext), + }); + + // Send independently; streams won't block each other + const { hash: payrollTxHash } = await payyClient.submitTxn({ + txn: payrollTxn, + walletClient, + }); + + const { hash: refundTxHash } = await payyClient.submitTxn({ + txn: refundTxn, + walletClient, + }); + + const payrollHash = await payyClient.hashTxn({ txn: payrollTxn, publicClient }); + const refundHash = await payyClient.hashTxn({ txn: refundTxn, publicClient }); + + console.log("Sent payroll on-chain tx:", payrollTxHash); + console.log("Sent refund on-chain tx:", refundTxHash); + console.log("Payroll Txn hash:", payrollHash); + console.log("Refund Txn hash:", refundHash); +} +``` diff --git a/docs/public/build-on-payy/payy-transactions/recurring.md b/docs/public/build-on-payy/payy-transactions/recurring.md new file mode 100644 index 0000000..b7a8afb --- /dev/null +++ b/docs/public/build-on-payy/payy-transactions/recurring.md @@ -0,0 +1,12 @@ +# Recurring + +Recurring schedules let users and dapps authorise a payment or batch of actions to execute repeatedly on a defined cadence (e.g., weekly, monthly), without staying online. You create a Recurrence (EIP‑712 typed data) that references a base Txn template and a cadence. The bridge materialises each occurrence into a concrete Txn with a derived schedule window and unique salt, then queues or submits it when due. + +This enables payroll cycles, streaming-like payouts, subscription charges with retries, periodic settlements, and routine maintenance tasks while retaining compatibility with existing wallets via typed signatures. + +### Key concepts: + +* Recurrence: a signed template containing the base Txn, cadence, bounds, and optional queue-ahead instructions. +* Occurrence: a concrete Txn derived from the template for a specific time window and index, with deterministic salt for replay safety. +* Keepers: anyone can call queueNextOccurrence or submitNextOccurrence when due. If queueAhead is enabled, fillQueueAhead can pre-queue several future occurrences. + diff --git a/docs/public/build-on-payy/payy-transactions/schedule.md b/docs/public/build-on-payy/payy-transactions/schedule.md new file mode 100644 index 0000000..24134cb --- /dev/null +++ b/docs/public/build-on-payy/payy-transactions/schedule.md @@ -0,0 +1,61 @@ +# Schedule + +Scheduled payments let users and dapps authorise a payment or batch of actions to execute at a specific time window in the future, without staying online. You sign a Txn (EIP‑712 typed data) that includes a schedule window and submit it to the `TransactionBridge` queue. + +This enables recurring payouts, delayed settlements, payroll cycles, subscription retries, and time-based automation while retaining compatibility with existing wallets via typed signatures. + +### Example + +```typescript +import { createPublicClient, createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { + erc20, + createPayyClient, +} from "@payy/viem"; +import { payy } from "@payy/viem/chains"; + +const account = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`); + +const publicClient = createPublicClient({ + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const walletClient = createWalletClient({ + account, + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const payyClient = createPayyClient(); + +async function schedulePayment() { + const now = Math.floor(Date.now() / 1000); + + // Build scheduled Txn with the schedule prop + const txn = await payyClient.buildTxn + .calls([ + erc20.transfer({ + token: "0xYourERC20", + to: "0xRecipient", + amount: 1_000_000n, + gasLimit: 120_000n, + }), + ]) + .schedule({ + notBefore: BigInt(now + 60 * 60), // earliest execution: +1 hour + notAfter: BigInt(now + 60 * 60 * 24), // latest execution: +24 hours + }); + + const { hash: queueTxHash } = await payyClient.submitTxn({ + txn, + walletClient, + }); + + const scheduledHash = await payyClient.hashTxn({ txn, publicClient }); + + console.log("Queued on-chain tx:", queueTxHash); + console.log("Scheduled Txn hash:", scheduledHash); +} +``` diff --git a/docs/public/build-on-payy/payy-transactions/sponsor-gas.md b/docs/public/build-on-payy/payy-transactions/sponsor-gas.md new file mode 100644 index 0000000..acae1a6 --- /dev/null +++ b/docs/public/build-on-payy/payy-transactions/sponsor-gas.md @@ -0,0 +1,67 @@ +# Sponsor Gas + +Sponsor Gas lets a third party (a sponsor/paymaster) cover the execution costs of a Txn so the sender doesn’t need to hold gas tokens. You sign a Txn (EIP‑712 typed data) with fee.model set to Sponsored and include sponsor information. The bridge validates the sponsor’s policy and settles fees accordingly. + +This enables: + +* Gasless onboarding and first‑use flows +* Subscriptions and dapps covering user gas +* Enterprise workflows with centralised gas budgets +* Promotional campaigns and fee rebates + +### Example + +```typescript +import { createPublicClient, createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { + erc20, + createPayyClient, +} from "@payy/viem"; +import { payy } from "@payy/viem/chains"; + +const account = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`); + +const publicClient = createPublicClient({ + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const walletClient = createWalletClient({ + account, + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const payyClient = createPayyClient(); + +async function gasSponsoredTransfer() { + // Build a Txn with fee.model = Sponsored (1) + const txn = await payyClient.buildTxn + .calls([ + erc20.transfer({ + token: "0xYourERC20", + to: "0xRecipient", + amount: 1_000_000n, + gasLimit: 120_000n, + }), + ]); + + // Fetch sponsor sig for the designated fee + const sponsorSig = await fetchSponsorSig(txn); // returns a signature approving fee sponsorship + + // Add the fee signature to the txn + const txnWithFeeSponsor = txn.withSponsor(sponsorSig); + + // Send the sponsored Txn on-chain (no native value needed from the user) + const { hash: txHash } = await payyClient.submitTxn({ + txn: txnWithFeeSponsor, + walletClient, + }); + + const txnHash = await payyClient.hashTxn({ txn: txnWithFeeSponsor, publicClient }); + + console.log("Sent sponsored on-chain tx:", txHash); + console.log("Txn hash:", txnHash); +} +``` diff --git a/docs/public/build-on-payy/payy-transactions/stealth.md b/docs/public/build-on-payy/payy-transactions/stealth.md new file mode 100644 index 0000000..c261d2d --- /dev/null +++ b/docs/public/build-on-payy/payy-transactions/stealth.md @@ -0,0 +1,163 @@ +# Stealth + +Stealth mode lets you execute calls on the [EVM Layer](../../protocol/evm-layer.md) without linking them to your public EOA. Instead of spending directly from your address, Payy temporarily funds a fresh, one-time address using private tokens from your [Privacy Vault](../../protocol/privacy-vault.md), executes your calls, then returns any remaining funds back to the [Privacy Layer](../../protocol/privacy-layer/) when finished. + +You can enable it with: + +* **`.stealth()`** — generate a new one-time address automatically. +* **`.stealthAs(pk: string)`** — use a specific private key for the one-time address (advanced / power-users). + +{% hint style="info" %} +Because Payy uses [zero rates all private transfers](../../stablecoins/zero-fee-payments.md), moving funds to the one-time address does not incur any gas fees. +{% endhint %} + +### Example + +```typescript +import { createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { + erc20, + createPayyClient, + // dex, // (placeholder) swap helper(s) depending on your SDK +} from "@payy/viem"; +import { payy } from "@payy/viem/chains"; + +const account = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`); + +const walletClient = createWalletClient({ + account, + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const payyClient = createPayyClient(); + +async function stealthSwap() { + const tokenIn = "0xTokenIn"; + const tokenOut = "0xTokenOut"; + const router = "0xDexRouter"; // e.g. UniswapV2/V3 router address + const amountIn = 1_000_000n; + const minAmountOut = 990_000n; // slippage protection + const recipient = "0xRecipient"; // could be your EOA or another address + + const txn = await payyClient.buildTxn + .stealth() + .calls([ + // 1) Approve router to spend tokenIn (from the stealth address’ balance) + erc20.approve({ + token: tokenIn, + spender: router, + amount: amountIn, + gasLimit: 60_000n, + }), + + // 2) Swap tokenIn -> tokenOut + // Replace this call with the swap helper your SDK exposes. + // The important part: it runs inside the same stealth-funded Txn. + { + to: router, + data: "0x...", // encoded swap calldata + value: 0n, + gasLimit: 250_000n, + }, + ]) + .requireSuccess(true); // atomic: approve+swap must both succeed + + const { hash: txHash } = await payyClient.submitTxn({ + txn, + walletClient, + }); + + console.log("Sent stealth swap tx:", txHash); +} +``` + +### Manual Stealth Transaction Example + +Using the [Payy Transaction](../../stablecoins/payy-transactions.md) primitives, you may construct a Stealth Transaction manually if you prefer more control over the movement of funds. + +```typescript +import { createWalletClient, http, createPublicClient } from "viem"; +import { privateKeyToAccount, generatePrivateKey, privateKeyToAddress } from "viem/accounts"; +import { + erc20, + privacyBridge, + createPayyClient, +} from "@payy/viem"; +import { payy } from "@payy/viem/chains"; + +// Origin (real) wallet +const originAccount = privateKeyToAccount(process.env.PRIV_KEY as `0x${string}`); + +const walletClient = createWalletClient({ + account: originAccount, + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const publicClient = createPublicClient({ + transport: http(payy.rpcUrls.default.http[0]), + chain: payy, +}); + +const payyClient = createPayyClient(); + +// Ephemeral (stealth) wallet +const ephemeralPrivKey = generatePrivateKey(); +const ephemeralAddress = privateKeyToAddress(ephemeralPrivKey); +const ephemeralAccount = privateKeyToAccount(ephemeralPrivKey); + +async function stealthTransactionSingleBatch() { + const TOKEN = "0xYourERC20" as `0x${string}`; + const GAS_LIMIT = 80_000n; + + // Plan: fund -> two transfers as ephemeral -> sweep back to origin + const txn = await payyClient.buildTxn + .calls([ + // 1) Fund ephemeral with ERC‑20 from origin + erc20.transfer({ + token: TOKEN, + to: ephemeralAddress, + amount: 3_500_000n, + gasLimit: GAS_LIMIT, + }).as(originAccount), + + // 2) Spend as the ephemeral wallet + erc20.transfer({ + token: TOKEN, + to: "0xAlice", + amount: 1_000_000n, + gasLimit: GAS_LIMIT, + }).as(ephemeralAccount), + + erc20.transfer({ + token: TOKEN, + to: "0xBob", + amount: 500_000n, + gasLimit: GAS_LIMIT, + }).as(ephemeralAccount), + + // 3) Sweep remaining funds back to origin from the ephemeral wallet + privacyBridge.sweep({ + token: TOKEN, + to: originAccount.address, + gasLimit: GAS_LIMIT, + }).as(ephemeralAccount), + ]) + // Atomic by default; if any step fails, everything reverts + .requireSuccess(true); + + // Submit the batch + const { hash: txHash } = await payyClient.submitTxn({ + txn, + walletClient, + }); + + const batchHash = await payyClient.hashTxn({ txn, publicClient }); + + console.log("Sent stealth batch on-chain tx:", txHash); + console.log("Batch Txn hash:", batchHash); +} + +``` diff --git a/docs/public/build-on-payy/predeployed-contracts.md b/docs/public/build-on-payy/predeployed-contracts.md new file mode 100644 index 0000000..4aa2250 --- /dev/null +++ b/docs/public/build-on-payy/predeployed-contracts.md @@ -0,0 +1,29 @@ +# Predeployed Contracts + +### System Contracts + +Native core protocol contracts that provide enhanced capabilities to Payy: + +| Contract | Address | Description | +| --------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------------- | +| **PUSD** | `0x0200000000000000000000000000000000000000` | Native ERC-20 view over Payy balances | +| [**PrivacyBridge**](../protocol/privacybridge.md) | `0x3100000000000000000000000000000000000000` | Bridge funds to and from the native ERC-20 privacy pools | +| [**PrivacyVaultRegistry**](../protocol/privacyvaultregistry.md) | `TBC` | Stores the registry of a given address | +| **Poseidon** | `0x3300000000000000000000000000000000000000` | Solidity wrapper around the public Poseidon precompile | +| [**Rollup**](../protocol/rollup.md) | `0x3200000000000000000000000000000000000000` | Sparse merkle rollup tree interface | +| **BlockTimestampMs** | `0x3400000000000000000000000000000000000000` | Solidity wrapper around the millisecond timestamp precompile | +| [**TransactionBridge**](../protocol/transactionbridge.md) | `0x3000000000000000000000000000000000000000` | Handle fee payments and conversions | + +Custom Payy precompiles are documented separately in [Precompiles](../protocol/precompiles.md). + +### Standard Utilities + +Popular Ethereum utility contracts: + +| Contract | Address | Description | +| ------------------------------------------------------------------------ | ------- | --------------------------------------- | +| [**Multicall3**](https://www.multicall3.com/) | `TBC` | Batch multiple calls in one transaction | +| [**Permit2**](https://docs.uniswap.org/contracts/permit2/overview) | `TBC` | Token approvals and transfers | +| [**CreateX**](https://github.com/pcaversaccio/createx) | `TBC` | Deterministic contract deployment | +| [**Safe Deployer**](https://github.com/safe-fndn/safe-singleton-factory) | `TBC` | Safe deployer contract | +| [**CREATE2 Factory (Arachnid)**](https://github.com/arachnid) | `TBC` | Deterministic deployment proxy contract | diff --git a/docs/public/build-on-payy/private-transfers.md b/docs/public/build-on-payy/private-transfers.md new file mode 100644 index 0000000..bc5974f --- /dev/null +++ b/docs/public/build-on-payy/private-transfers.md @@ -0,0 +1,45 @@ +# Private Transfers + +You don't need to make any modifications to make private native token or ERC-20 transfers. For details on how private transfers are enabled without any modifications, see [Private Transfers](../privacy/editor.md) overview. + +{% hint style="info" %} +All private token transfers are gas zero rated to enable [zero fee private payments](../stablecoins/zero-fee-payments.md). +{% endhint %} + +### Private native token transfer + +You'll notice that there are no changes required to send private native transfers, yet if you have tokens in your [Privacy Vault](../protocol/privacy-vault.md), they will be automatically pulled from the [Privacy Layer](../protocol/privacy-layer/) and used in the transfer. + +```typescript +import { createPublicClient, createWalletClient, http, parseEther } from "viem"; +import { payy } from "@payy/viem/chains"; +import { privateKeyToAccount } from "viem/accounts"; + +const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); + +const publicClient = createPublicClient({ + chain: payy, + transport: http(process.env.RPC_URL), +}); + +const walletClient = createWalletClient({ + account, + chain: payy, + transport: http(process.env.RPC_URL), +}); + +async function sendNative() { + const to = "0xRecipientAddressHere" as `0x${string}`; + const hash = await walletClient.sendTransaction({ + to, + value: parseEther("0.01"), + }); + + console.log("tx hash:", hash); + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + console.log("status:", receipt.status); +} + +sendNative().catch(console.error); +``` + diff --git a/docs/public/build-on-payy/wallet-compatibility.md b/docs/public/build-on-payy/wallet-compatibility.md new file mode 100644 index 0000000..fb3db3b --- /dev/null +++ b/docs/public/build-on-payy/wallet-compatibility.md @@ -0,0 +1,20 @@ +# Wallet Compatibility + +Payy is compatible with all existing wallets, like Metamask and Phantom. + +### Viewing private balances + +When `eth_getBalance` is called, the RPC node requests the Privacy for the user (as well as the public balance) to determine the complete balance for the user. + +### Sending a private transfer + +Many wallets have built-in capabilities to send ERC-20 directly from within the wallet. + +Sending an ERC-20 transfer `eth_sendRawTransaction()` can also transparently be upgraded. + +1. User sends the signed `transfer()` transaction to the RPC +2. RPC constructs ZK proof and submits the transaction to the native `PrivacyBridge` - privacy bridge will verify the zk proof and update the merkle tree +3. RPC will forward the private transaction data to the private storage of the receiving user. If the [`PrivacyVaultRegistry`](../protocol/privacyvaultregistry.md) contract contains a storage destination, then data will be sent there, otherwise it will be sent to the default Payy Network storage provider. + + + diff --git a/docs/public/privacy/editor.md b/docs/public/privacy/editor.md new file mode 100644 index 0000000..4f366c6 --- /dev/null +++ b/docs/public/privacy/editor.md @@ -0,0 +1,67 @@ +--- +metaLinks: + alternates: + - https://app.gitbook.com/s/yE16Xb3IemPxJWydtPOj/basics/editor +--- + +# Private Transfers + +There are two ways to perform private transfers on Payy: + +1. Directly calling the [PrivacyBridge](../protocol/privacybridge.md) with the ZK proof authorising transfer of funds +2. Transparent upgrade using [Privacy Vault](../protocol/privacy-vault.md) (no wallet changes required) + +### Transparent upgrade using Privacy Vault + +Private payments (ERC-20 and native tokens) are transparently upgraded using the RPC and [Privacy Vault](../protocol/privacy-vault.md), so existing wallets need no modification. Wallets can continue to call ERC-20 `transfer(address,uint256)` (or construct a native transfer) using `eth_submitRawTransaction()` without any awareness of the privacy orchestration happening underneath. When the RPC detects a transfer (i.e. transaction selector is `0xa9059cbb`), it requests a ZK proof from the [Privacy Vault](../protocol/privacy-vault.md). The ZK proof generated by the Privacy Vault validates the transfer signature and constructs the relevant transaction proof to be submitted to the [PrivacyBridge](../protocol/privacybridge.md). + +As the transaction data is private, the receiving party needs to receive the [Note](../protocol/privacy-layer/utxo.md) data for the transaction in order to access funds. The Privacy Vault uses the [`PrivacyVaultRegistry`](../protocol/privacyvaultregistry.md) to determine where to send the funds for a specific address, and receives signed confirmation from the receiver's Privacy Vault once it has been sent. + +
+ +The following describes the process flow: + +* Wallet signs a native or ERC-20 transfer and sends it to the RPC. +* RPC forwards the signed transfer signature to the sender’s Privacy Vault.
 +* Privacy Vault validates and generates a UTXO-style ZK proof asserting: + * The user’s transfer signature.
 + * The target contract/address. + * Consistency with existing stored notes.
 + * Privacy Vault constructs a transaction calling `PrivacyBridge.transfer(verificationKeyHash, proof, publicInputs)` using an ephemeral keypair. +* Privacy Vault returns the signed transaction (to PrivacyBridge) to the RPC. +* RPC forwards the transaction to the Sequencer. +* Sequencer executes the transaction, verifying the proof and updating the privacy pool state. +* Sender’s Privacy Vault notifies the recipient’s Privacy Vault with the transaction metadata (e.g., output commitments) for note detection and syncing. +* RPC returns the transaction receipt/logs to the Wallet. + +```mermaid +sequenceDiagram + autonumber + actor W as Wallet + participant R as RPC + participant V as Privacy Vault (Sender) + participant S as Sequencer + participant V2 as Privacy Vault (Recipient) + + Note over W: User initiates transfer (Native or ERC-20) + W->>R: 1) Signed transfer (tx + signature) + + R->>V: 2) Forward signed signature + + Note over V: Generate privacy UTXO ZK proof (asserts signature + contract address against stored notes) + V->>V: 3) Construct ZK proof + + Note over V: Build tx calling PrivacyBridge.transfer(verificationKeyHash, proof, publicInputs) using ephemeral keypair + V-->>R: 4) Signed transaction (to PrivacyBridge, from ephemeral key) + + R->>S: 5) Broadcast transaction to Sequencer + S-->>S: 6) Execute tx -> PrivacyBridge.transfer(...), verify proof, update state + + Note over V: After submission, sender vault notifies recipient vault directly + V->>V2: 7) Send recipient notification payload (output commitments, metadata) + + S-->>R: 8) Tx receipt / logs + R-->>W: 9) Finalize: tx receipt / status + +``` + diff --git a/docs/public/privacy/native-zk.md b/docs/public/privacy/native-zk.md new file mode 100644 index 0000000..0c1fa50 --- /dev/null +++ b/docs/public/privacy/native-zk.md @@ -0,0 +1,18 @@ +# Native ZK + +Payy natively supports ZK (zero knowledge) proofs, allowing application developers to build privacy preserving applications directly into Payy without sacrificing performance or incurring excessive cost. + +Verifying proofs on existing networks is expensive. Proof verification on existing unoptimised chains can take in excess of 5M gas (\~10% of the available blockspace). This makes it impractical for most privacy applications to rollup individual transactions, which means some form of rollup must be used to enable all privacy applications. + +Application developers can use the natively supported ZK proofs directly in their EVM smart contract code to validate trustlessly transactions that occur offchain. + +{% include "../../../.gitbook/includes/zk-framework.md" %} + +### Use cases + +Verifying proofs off chain allows developers to build applications like: + +* Offchain orderbooks like hyperliquid +* Dark pools +* Private RWA contracts + diff --git a/docs/public/privacy/privacy-architecture.md b/docs/public/privacy/privacy-architecture.md new file mode 100644 index 0000000..8881f77 --- /dev/null +++ b/docs/public/privacy/privacy-architecture.md @@ -0,0 +1,32 @@ +# Privacy Architecture + +Payy uses ZK (zero knowledge) cryptography to enable privacy whilst maintaining EVM compatibility. + +There are three core privacy enabling flows on Payy: + +1. [**Private Transfers**](../build-on-payy/private-transfers.md) - private ERC-20 and native token transfers, transparently upgraded +2. [**Stealth Transactions**](stealth-transactions.md) - private transactions on the EVM Layer using newly minted addresses for each transaction +3. [**Native ZK**](native-zk.md) - a ZK verification precompile reducing cost for custom privacy applications + +### Architecture + +The Payy Privacy architecture is composed of the following components: + +* [**Privacy Layer**](../protocol/privacy-layer/) - a high performance privacy rollup, creating a native privacy pool for every ERC-20 token. +* [**PrivacyBridge**](../protocol/privacybridge.md) - a predeployed bridge to the Privacy Layer accessible from the [EVM Layer](../protocol/evm-layer.md). +* [**Privacy Vault**](../protocol/privacy-vault.md) - stores private data, converts signed Ethereum transactions into private transactions using ZK proofs. + +
+ +### Levels of Privacy in Payy + +* [**Private Transfers**](editor.md) - occur entirely within the [Privacy Layer](../protocol/privacy-layer/). This ensures zero overhead on the [EVM Layer](../protocol/evm-layer.md), maximal privacy and massive throughput. Payments are fully private. That means the sender, receiver, amount and asset are all hidden. Total privacy. +* [**Stealth Transactions**](stealth-transactions.md) - transaction occurs on the EVM Layer, but with funds originating from the Privacy Layer, it's impossible to determine the true sender or receiver. +* [**Native ZK**](native-zk.md) - dependent on the privacy application + +
+ +### Encrypted Lineage + +Payy uses nullifiers to ensure that lineage of transactions cannot be tracked by external observers. This is critical to ensure that transactions moving in and out of the EVM Layer cannot be trivially exposed. To prevent actors using the privacy pools maliciously to move in toxic assets, the encrypted lineage can be decrypted in exceptional cases using an on-chain proposal. + diff --git a/docs/public/privacy/stealth-transactions.md b/docs/public/privacy/stealth-transactions.md new file mode 100644 index 0000000..0fe58b5 --- /dev/null +++ b/docs/public/privacy/stealth-transactions.md @@ -0,0 +1,52 @@ +# Stealth Transactions + +Payy enables privacy on the [EVM Layer](../protocol/evm-layer.md) by making it seamless to move funds in and out of the [Privacy Layer](../protocol/privacy-layer/) (native ERC-20 privacy pools), using a newly minted one-time stealth address for each transaction. For example, to perform a private swap from [PUSD](../stablecoins/pusd.md) to PAYY, private funds are pulled from the Privacy Layer to a new one-time address, the swap is performed on the [EVM Layer](../protocol/evm-layer.md) and PAYY tokens are returned to the Privacy Layer pool after the swap completes. + +
+ +{% hint style="info" %} +Moving funds in and out of the Privacy Layer [requires zero gas](../stablecoins/zero-fee-payments.md), so Stealth Transactions do not incur additional gas over normal EVM transactions. +{% endhint %} + +The following diagram describes the flow: + +```mermaid +sequenceDiagram + autonumber + actor Wallet as Wallet + participant Vault as Privacy Vault + participant RPC as RPC + participant Seq as Sequencer + + Note over Wallet,Vault: Stealth Txn using the Txn standard (single EIP-712 signature, ordered batch calls) + + Wallet->>Vault: Request .stealth() Txn
calls=[approve, swap, sweepBack]
requireSuccess=true, gasLimit, tip + activate Vault + + Note over Vault: Prepares a one-time stealth address and funds it privately + + Vault->>Vault: Calculate gas budget from gasLimit + tip
Withdraw gas from Privacy Layer pool + + Note over Vault: Authorisation + privacy bridge proofing + Vault->>Vault: Re-generate Txn signature (EIP-712)
Generate ZK proof for privacy bridge
(private withdraw + gas withdraw) + + Vault->>RPC: Submit single Txn (batched, atomic)
[1] PrivacyBridge.burn(tokenIn → stealth)
[2] PrivacyBridge.burn(gas → stealth)
[3] ERC20.approve(router, amountIn)
[4] DEX.swap(tokenIn→tokenOut, minOut, ...)
[5] PrivacyBridge.mint(tokenOut → vault)
[6] PrivacyBridge.mint(unusedGas → pool) + RPC->>Seq: Forward Txn to sequencer + Seq-->>RPC: Include Txn in block & execute calls in order + RPC-->>Vault: Receipt + per-call results (TxnCallResult) + + Note over Vault,Wallet: If requireSuccess=true, any failure reverts entire sequence
so funds never leave privacy in a partial state + + Vault-->>Wallet: Final result: swap completed privately
tokenOut returned to Privacy Vault
unused gas returned to Privacy Layer pool + deactivate Vault + +``` + +{% hint style="info" %} +See [Payy Transactions > Stealth](../build-on-payy/payy-transactions/stealth.md) for a guide on using Stealth Transactions. +{% endhint %} + +### Gas fees + +Moving funds in and out of the Privacy Layer [requires no gas](../stablecoins/zero-fee-payments.md), but stealth transactions themselves require gas for the one-time address that will be responsible for the transaction. The Privacy Vault automatically withdraws gas from the Privacy Layer based on gas limit and gas fee tip, any unused gas is returned to the Privacy Layer when the transaction completes. + diff --git a/docs/public/protocol/architecture.md b/docs/public/protocol/architecture.md new file mode 100644 index 0000000..a6b522c --- /dev/null +++ b/docs/public/protocol/architecture.md @@ -0,0 +1,15 @@ +# Architecture + +Payy Network is an L2 ZK rollup on Ethereum with the following architecture: + +
+ +### Roles + +Each node on the Payy Network protocol can perform one or more of the following distinct roles: + +* **Sequencer** - add pending unproven blocks to the L1, guaranteeing the order of transactions +* **Rollup Prover** - prove that an existing sequenced block is valid or invalid +* **Client** - proves valid UTXO transactions +* **Encrypted Registries (Optional)** - component to store transactions so that transactions can be made with offline users +* **Ethereum** - provides security and data availability for the network diff --git a/docs/public/protocol/data-availability.md b/docs/public/protocol/data-availability.md new file mode 100644 index 0000000..6b5367d --- /dev/null +++ b/docs/public/protocol/data-availability.md @@ -0,0 +1,8 @@ +# Data Availability + +The data availability on Ethereum serves two purposes: + +1. Availability of transaction data (UTXO proofs and EVM transactions), so all network participants can determine for themselves the full state of Smirk (our sparse merkle tree). Without this, colluding provers could submit a rollup to change the root hash on Ethereum without providing the txn data to other nodes, making it impossible for other nodes to know the current state of the merkle tree is (only that it is valid). Without the current state of the merkle tree, no other nodes would be able to create a proof, as the merkle tree is used in proof generation. +2. A commitment to a set of transactions and their order (so final state can be known before it is proved). This allows for optimistic protocols to pre-fill bridging activity. + +The batched transactions are ordered and stored on Ethereum, providing a definitive state of the network, even if the rollup root state hash has not yet been updated to reflect these transactions. Once the transactions have been finalised on Ethereum, the order of the transactions cannot change, and therefore the future state is predictable and fixed. diff --git a/docs/public/protocol/evm-layer.md b/docs/public/protocol/evm-layer.md new file mode 100644 index 0000000..2ff7f39 --- /dev/null +++ b/docs/public/protocol/evm-layer.md @@ -0,0 +1,5 @@ +# EVM Layer + +The EVM Layer is a Ethereum compatible interface for Payy that adheres to the Ethereum transaction model and EVM byte code. All transactions occur through the EVM Layer, including transactions which will only be processed on the Privacy Layer (i.e. for private transfers). + +See [Ethereum Compatibility](../build-on-payy/ethereum-compatibility.md). diff --git a/docs/public/protocol/precompiles.md b/docs/public/protocol/precompiles.md new file mode 100644 index 0000000..76fe634 --- /dev/null +++ b/docs/public/protocol/precompiles.md @@ -0,0 +1,116 @@ +# Precompiles + +Payy supports all standard Ethereum precompiles and adds a set of protocol-specific precompiles for privacy, proof verification, and sparse merkle tree operations. + +These addresses are fixed by the `payy-evm` implementation and are the canonical precompile endpoints used by the predeployed contracts documented in [Predeployed Contracts](../build-on-payy/predeployed-contracts.md). + +## Overview + +| Precompile | Address | Access | Gas | Purpose | +| --- | --- | --- | --- | --- | +| Poseidon | `0x0000000000000000000000000000000000000101` | Public | `10,000 + 1,000 × element_count` | Poseidon hash over one or more 32-byte field elements | +| BlockTimestampMs | `0x0000000000000000000000000000000000000999` | Public | `2` | Returns the current block timestamp in milliseconds | +| BB Verify | `0x0000000000000000000000000000000000000998` | Public | `50,000 + 10 × calldata_bytes` | Verifies a Barretenberg proof against supplied key and public inputs | +| Privacy Proof Verify | `0x0000000000000000000000000000000000000997` | Public | `0` | Verifies supported privacy proofs and decodes transfer / burn / mint outputs | +| Native Transfer | `0x0000000000000000000000000000000000000100` | Internal-only — `PUSD` predeploy `0x0200000000000000000000000000000000000000` | `2` | Moves native balances for `PUSD` without requiring `msg.value` | +| Smirk Add | `0x0000000000000000000000000000000000000102` | Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` | `170,000` | Inserts a leaf into the privacy layer sparse merkle tree | +| Smirk Remove | `0x0000000000000000000000000000000000000103` | Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` | `170,000` | Removes a leaf from the privacy layer sparse merkle tree | +| Smirk Get Path | `0x0000000000000000000000000000000000000104` | Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` | `170,000` | Returns the merkle sibling path for a leaf | +| Smirk Get Root | `0x0000000000000000000000000000000000000105` | Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` | `10,000` | Returns the current sparse merkle tree root | + +## Access model + +- **Public** precompiles can be called by any contract or externally owned account. +- **Internal-only** precompiles are scoped to specific protocol predeploys and are not stable public APIs. +- `Native Transfer` returns `false` (`0x00…00`) when called by any address other than the `PUSD` predeploy at `0x0200000000000000000000000000000000000000`. +- `Smirk Add`, `Smirk Remove`, `Smirk Get Path`, and `Smirk Get Root` revert with `unauthorized` when called by any address other than the `Rollup` predeploy at `0x3200000000000000000000000000000000000000`. + +## Poseidon + +- **Address:** `0x0000000000000000000000000000000000000101` +- **Access:** Public +- **Canonical calldata:** raw concatenation of one or more `bytes32` field elements; no function selector or ABI array head is expected. +- **Canonical return data:** a single `bytes32` Poseidon hash. +- **Gas:** `10,000 + 1,000 × element_count` +- **Notes:** empty calldata and any calldata whose length is not a multiple of 32 bytes are rejected. The repository includes a Solidity wrapper contract that calls this precompile via `abi.encodePacked(...)`. + +## BlockTimestampMs + +- **Address:** `0x0000000000000000000000000000000000000999` +- **Access:** Public +- **Canonical calldata:** empty calldata. The current implementation ignores calldata and always returns the current value. +- **Canonical return data:** a single `uint256` / `bytes32` containing the block timestamp in milliseconds. +- **Gas:** `2` +- **Notes:** this supplements Ethereum's second-granularity `block.timestamp` for applications that need sub-second timing. + +## BB Verify + +- **Address:** `0x0000000000000000000000000000000000000998` +- **Access:** Public +- **Canonical calldata:** `abi.encode(bytes verificationKey, bytes proof, bytes publicInputs)` with no function selector. +- **Canonical return data:** ABI-encoded `bool` (`true` on successful verification, `false` on verification failure or malformed calldata). +- **Gas:** `50,000 + 10 × calldata_bytes` +- **Notes:** `publicInputs` is passed through as raw bytes to the Barretenberg verifier backend. + +## Privacy Proof Verify + +- **Address:** `0x0000000000000000000000000000000000000997` +- **Access:** Public +- **Canonical calldata:** `abi.encodeWithSignature("verifyPrivacyProof(bytes32,bytes,bytes32[])", verificationKeyHash, proof, publicInputs)` +- **Canonical return data:** `(uint8 kind, bytes32[] elements, uint256 value, address burnAddress)` +- **Gas:** `0` +- **Notes:** `kind` is `1` for transfer proofs, `2` for burn proofs, and `3` for mint proofs. `elements` contains the non-zero note commitments / nullifiers returned by the verifier. `value` is populated for burn and mint proofs, while `burnAddress` is only populated for burn proofs. This is the precompile consumed by [PrivacyBridge](privacybridge.md). + +## Native Transfer + +- **Address:** `0x0000000000000000000000000000000000000100` +- **Access:** Internal-only — `PUSD` predeploy `0x0200000000000000000000000000000000000000` +- **Canonical calldata:** `abi.encodeWithSignature("transferFromNative(address,address,uint256)", from, to, value)` +- **Canonical return data:** ABI-encoded `bool` +- **Gas:** `2` +- **Notes:** this precompile is the balance-movement primitive used by the `PUSD` predeploy for `transfer` and `transferFrom`. Unauthorized callers do not get a revert; they receive `false`. + +## Smirk tree precompiles + +The Smirk precompiles back the [Rollup](rollup.md) predeploy and are intentionally internal-only. + +### Smirk Add + +- **Address:** `0x0000000000000000000000000000000000000102` +- **Access:** Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` +- **Canonical calldata:** either a raw `bytes32` element or `abi.encodeWithSignature("smirkAdd(bytes32)", element)`; the `Rollup` contract uses the selector-based form. +- **Canonical return data:** ABI-encoded `bool` +- **Gas:** `170,000` +- **Notes:** rejects `staticcall`, rejects the zero element, and rejects inserts for elements that already exist. + +### Smirk Remove + +- **Address:** `0x0000000000000000000000000000000000000103` +- **Access:** Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` +- **Canonical calldata:** either a raw `bytes32` element or `abi.encodeWithSignature("smirkRemove(bytes32)", element)`; the `Rollup` contract uses the selector-based form. +- **Canonical return data:** ABI-encoded `bool` +- **Gas:** `170,000` +- **Notes:** rejects `staticcall`, rejects the zero element, and rejects removes for elements that do not exist. + +### Smirk Get Path + +- **Address:** `0x0000000000000000000000000000000000000104` +- **Access:** Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` +- **Canonical calldata:** either a raw `bytes32` element or `abi.encodeWithSignature("smirkGetPath(bytes32)", element)`; the `Rollup` contract uses the selector-based form. +- **Canonical return data:** ABI-encoded `bytes32[]` merkle siblings. With the current tree depth of 161, the returned array contains 160 sibling hashes. +- **Gas:** `170,000` + +### Smirk Get Root + +- **Address:** `0x0000000000000000000000000000000000000105` +- **Access:** Internal-only — `Rollup` predeploy `0x3200000000000000000000000000000000000000` +- **Canonical calldata:** empty calldata or `abi.encodeWithSignature("smirkGetRoot()")` +- **Canonical return data:** a single `bytes32` sparse merkle tree root. +- **Gas:** `10,000` + +## Related docs + +- [Predeployed Contracts](../build-on-payy/predeployed-contracts.md) +- [PrivacyBridge](privacybridge.md) +- [Rollup](rollup.md) +- [EVM Layer](evm-layer.md) diff --git a/docs/public/protocol/privacy-layer/README.md b/docs/public/protocol/privacy-layer/README.md new file mode 100644 index 0000000..46250c5 --- /dev/null +++ b/docs/public/protocol/privacy-layer/README.md @@ -0,0 +1,13 @@ +# Privacy Layer + +The Payy Privacy Layer is a high performance privacy rollup that enables native privacy pools for all ERC-20 tokens. + +{% hint style="info" %} +The Privacy Layer inherits much of its design from Payy Network V1, as described in our original 2024 whitepaper - [L2 Ethereum ZK Rollup for Private and Compliant Transactions](https://polybase.github.io/zk-rollup/whitepaper.pdf) +{% endhint %} + +
+ +The Privacy Layer is comprised of the following components and is accessible to the [EVM Layer](../evm-layer.md) via the [PrivacyBridge](../privacybridge.md). + +
FeatureDescription
Privacy RollupRollup architecture and merkle tree.
UTXOData model for enabling privacy.
NullifiersPreventing transaction lineage through nullifiers.
ZK CircuitsPrivacy enabling ZK circuits and aggregation.
diff --git a/docs/public/protocol/privacy-layer/encrypted-lineage.md b/docs/public/protocol/privacy-layer/encrypted-lineage.md new file mode 100644 index 0000000..3f3a6eb --- /dev/null +++ b/docs/public/protocol/privacy-layer/encrypted-lineage.md @@ -0,0 +1,7 @@ +--- +hidden: true +--- + +# Encrypted Lineage + +Payy uses [Nullifiers](nullifiers.md) to prevent lineage of transactions being observed publicly. That means its impossible for outside observers to determine which notes were spent during a transaction. diff --git a/docs/public/protocol/privacy-layer/nullifiers.md b/docs/public/protocol/privacy-layer/nullifiers.md new file mode 100644 index 0000000..9d91d0f --- /dev/null +++ b/docs/public/protocol/privacy-layer/nullifiers.md @@ -0,0 +1,17 @@ +# Nullifiers + +As per the [UTXO](utxo.md) model, a note can be used only once. As such, the protocol must keep track of which notes have been used or spent, and which have not. Naively, this could be performed by marking or removing used notes in the merkle tree, however this would reveal to public observers when a note has been spent, reducing privacy by allowing transactions to be linked together. + +Instead, to enhance privacy, we use a deterministic nullifier record that for each spend must be inserted into the tree, and during spend of the original input not, must be proven not to exist in the tree via a non-inclusion proof. The presence of the nullifier represents the record being spent. The nullifier is constructed in such a way that it is impossible for an external party to determine which nullifier matches a spent record (or a record to be spent). + +The nullifier is calculated as follows: + +$$ +N = \text{Poseidon}(nk, \psi, cm) +$$ + +Where: + +* $$nk$$ is the Nullifier Key, a unique secret associated with each user (this is a auth commitment to the auth) +* $$\psi$$ (psi) sender controlled randomness, additional entropy provided by Blake2b \[Aumasson et al. 2013] hash. Blake2b provides additional entropy and privacy security. +* $$cm$$ is the note commitment, which is a Poseidon commitment to the note. diff --git a/docs/public/protocol/privacy-layer/privacy-rollup.md b/docs/public/protocol/privacy-layer/privacy-rollup.md new file mode 100644 index 0000000..4794a1f --- /dev/null +++ b/docs/public/protocol/privacy-layer/privacy-rollup.md @@ -0,0 +1,34 @@ +# Privacy Rollup + +The privacy rollup represents the entire state of the Privacy Layer, where each piece of state is referred to as a [Note](utxo.md#notes), is represented by a commitment hash \[Merkle87]. Hashes result in data loss, so the original messages can provably never be reconstructed, ensuring privacy of the protocol. Each note represents a balance of an ERC-20 token on Payy, which can thus be used to create a privacy pool for every ERC-20 contract. + +Each of the hash record states are stored in a merkle tree (our implementation is [Smirk](https://github.com/polybase/payy/tree/main/pkg/smirk)), enabling a single root hash to represent the entire state of the network. No underlying data is stored in the rollup, and therefore any required shared data must be stored in the users [Privacy Vault](../privacy-vault.md). In addition to privacy, an additional advantage of storing only hashes in the rollup is that the rollup on disk data size can be somewhat constrained and deterministic. This is a result of all hashes being a consistent size regardless of the size of the underlying data. This reduction in the disk size requirements for clients, improves the number of clients able to join the network, thereby helping to improve decentralisation. + +The merkle tree must enable the following operations: + +* Prove inclusion - prove a hash exists in the tree +* Prove non-inclusion - prove a hash does not exist in the tree +* Insert - insert a new hash into the tree if it does not already exist + +To satisfy these properties, Payy uses a sparse merkle tree \[DPP16]. A sparse merkle tree has a defined position for every possible value that can be inserted into the tree. Using a 256 bit hash for the tree, the maximum depth is $$2^{256}$$. However, given that all operations require traversal of the entire tree, it is inefficient to use a tree of such depth. Therefore, a tree depth of $$2^{160}$$ (equivalent entropy as Ethereum addresses) can be used, which provides sufficient entropy whilst minimising the operational overhead. + +In addition, further enhancements can be made to Smirk allowing for sharding the tree at different levels. + +### Merkle Proofs + +As every hash has a unique position in a sparse merkle tree, we can derive its position by decomposing each bit of the hash and traversing the tree based on whether the bit is 0 or 1. For 0, the tree is traversed to the left child, and for 1 the tree is traversed to the right child. + +

Fig 1: 4 bit tree, demonstrating bit decomposition and insertion

+ +For an inclusion or non-inclusion proof, we can simply check that each of the provided siblings combined with the the computed child results in the root hash. For non-inclusion we are proving that the leaf node is a null value, which does not need to be passed to the proof, as it is a static value. + +

Fig 2: non-inclusion and inclusion proofs

+ +Insertion proofs are a combination of a non-inclusion proof (existing position must be null) and inclusion proof (proving the new root based on the inserted hash). + +### References + +\[DPP16] Dahlberg, R., Pulls, T., and Peeters, R. 2016. _Efficient Sparse Merkle Trees_. In: Brumley, B., Röning, J. (eds) Secure IT Systems. NordSec 2016. Lecture Notes in Computer Science (vol 10014). Springer, Cham. [https://doi.org/10.1007/978-3-319-47560-8\_13](https://doi.org/10.1007/978-3-319-47560-8_13) + +\[Merkle87] Merkle, R. 1987. _A digital signature based on a conventional encryption function." Advances in Cryptology_ — CRYPTO ’87. Springer. + diff --git a/docs/public/protocol/privacy-layer/utxo.md b/docs/public/protocol/privacy-layer/utxo.md new file mode 100644 index 0000000..8c7911c --- /dev/null +++ b/docs/public/protocol/privacy-layer/utxo.md @@ -0,0 +1,49 @@ +# UTXO + +UTXO (Unspent Transaction Output) is a state model introduced by Bitcoin \[Nak08] and additionally used in Zcash \[GMRA13], and other blockchains to store the balances that can be spent. In this model, each store of value is a note that belongs to a specific authenticated account. Notes can be of any value, but can only be used once. If the note contains a value larger than you wish to transfer, you can create a new note with the output. You can use multiple input notes, so long as the total value of incoming notes is the same (or less) than the total value of outgoing notes. + +This model has a number of advantages: + +* **Scalability** - because a user can have multiple notes, multiple payments can be included in the same block (even in the case where the underlying data is hidden) +* **Privacy** - each transaction creates a new output record/hash. This prevents adversaries from looking for addresses with high activity or attempting to match accounts based on the source IP of the transaction, as is possible in account based models. + +The considered drawbacks for the UTXO model are: + +* **Increased tree utilisation** - UTXO transactions create one new insert hash for every incoming and outgoing note in a transaction. In contrast, an account based model (such as used in Ethereum) uses only a single hash insert per account, reducing the size of the tree. + +Due to the strict privacy constraints desired for the Payy Network, the UTXO model was selected. + +### Notes + +Each note has the following state properties: + +* **Application Type** - used to differentiate between different applications running on the Payy Network (each application type would have a different set of ZK circuit constraints) +* **Authentication** - used to verify which actor is allowed to “spend” a note +* **Value** - the balance of the note, balances between incoming and outgoing notes must match +* **Nullifier entropy** - additional nullifier entropy to increase security and privacy + +### Authentication + +Authentication identifies the user that is allowed to spend a note. The auth commitment is used in the Nullifer constraint to ensure that the user generating the nullifier (i.e. spending the note), knows the underlying secret key represented by the commitment. the Payy Network supports multiple authentication systems, denoted by a type enum, to provide flexible ownership over notes. Additional authentication types may be added over time. + +#### Poseidon + +Users can generate a random 32-byte secret key, and use the Poseidon commitment of the secret key as the authentication address for a note. This provides a highly performant authentication mechanism, but may not be well supported by existing wallets or tooling. + +#### Ethereum + +The Payy Network natively supports Ethereum addresses. In this case, the auth commitment would be the Ethereum address. To spend with the Ethereum address a proof must be generated that proves ownership of the underlying private key. This can be achieved in zero knowledge by passing the Ethereum private key as a private input and and deriving the address from the private key. + +### Minting and Burning + +Special transaction types will allow the UTXO model to be modified in order to allow bridging of assets to and from the Payy Network: + +* **Mint** - allows a note to be created without a corresponding input, minting will be further validated on Ethereum in the data availability layer before it will be accepted as a valid transaction +* **Burn** - allows a note to be used without a corresponding output, when this is proved on Ethereum, the funds will be released from the bridge contract + +### References + +\[Nak08] Nakamoto, S. 2008. Bitcoin: A Peer-to-Peer Electronic Cash System. + +\[GMRA13] Green, M., Miers, I., Rubin, A.D. and Garman, C. 2013. _Zerocoin: Anonymous Distributed E-Cash from Bitcoin._ + diff --git a/docs/public/protocol/privacy-layer/zk-circuits.md b/docs/public/protocol/privacy-layer/zk-circuits.md new file mode 100644 index 0000000..cb5b097 --- /dev/null +++ b/docs/public/protocol/privacy-layer/zk-circuits.md @@ -0,0 +1,15 @@ +# ZK Circuits + +There are three privacy ZK circuits: + +1. [**Utxo proof**](https://github.com/polybase/payy/tree/next/noir/utxo) (client/Privacy Vault) - runs on the client or [Privacy Vault](../privacy-vault.md) and proves that a user has permission to spend an input note and generate an output note. +2. [**Utxo aggregation and inclusion proof**](https://github.com/polybase/payy/tree/next/noir/agg_utxo) (prover) - aggregates Utxo proofs and verifies the new merkle root state +3. [**Aggregation proof**](https://github.com/polybase/payy/tree/next/noir/agg_agg) (prover) - aggregates Utxo aggregation and inclusion proofs recursively to the required depth to include all Utxo proofs from a single block + +The privacy aggregation proof is then combined with the EVM Layer ZK verifier proof, ready for rollup submission to Ethereum. + +{% include "../../../../.gitbook/includes/zk-framework.md" %} + +The following diagram shows the ZK circuits used by the Privacy Layer: + +
diff --git a/docs/public/protocol/privacy-vault.md b/docs/public/protocol/privacy-vault.md new file mode 100644 index 0000000..5f1f264 --- /dev/null +++ b/docs/public/protocol/privacy-vault.md @@ -0,0 +1,26 @@ +# Privacy Vault + +The Privacy Vault is a key component of Payy that enables privacy whilst maintaining compatibility with existing Ethereum infrastructure. + +{% hint style="info" %} +The Privacy Vault is an optional component. Users can directly call the PrivacyBridge to submit private transfers and transactions, but the Privacy Vault ensures compatibility with existing Ethereum wallets. +{% endhint %} + +The Privacy Vault has three responsibilities: + +1. Storing private data - private data cannot be stored onchain +2. ZK proving transactions - converts the private data and signed transactions into ZK proofs that can be used without revealing the underlying data +3. Data sharing - if you need to share data for compliance reasons, you can authorise others to access your data (this will always be opt-in - no data will be shared without your consent) + +You can configure your Privacy Vault by adding the `vault` parameter to your RPC URL. The vault has minimal system requirements, so can be run on micro commodity hardware. + +``` +https://rpc.payy.link?vault=102.10.0.69 +``` + +When you send a transaction to the RPC, the RPC checks if it needs to generate a proof to bridge your funds into the EVM layer or send a direct payment. The ZK proof ensures that the protocol rules are followed but hides the private data. + +
+ +If a private storage layer is configured, RPC requests to the node will use both the public and private data to respond to requests. That means, a user with both a public and private balance would see their full balance, whereas other external users would only see the public balance. + diff --git a/docs/public/protocol/privacybridge.md b/docs/public/protocol/privacybridge.md new file mode 100644 index 0000000..cd1a2cc --- /dev/null +++ b/docs/public/protocol/privacybridge.md @@ -0,0 +1,152 @@ +# PrivacyBridge + +The Privacy Bridge provides an EVM interface to the native ERC-20 privacy pools. Calls to the privacy bridge are zero rated, incentivising usage and enhancing usability for privacy flows. The privacy bridge maintains a virtual state representing the privacy layer sparse merkle tree. + +The bridge verifies privacy proofs through the [Privacy Proof Verify](precompiles.md#privacy-proof-verify) precompile and reads / updates sparse merkle tree state through the [Rollup](rollup.md) predeploy. + +{% hint style="info" %} +All calls to the PrivacyBridge are gas zero rated to enable [zero fee private payments](../stablecoins/zero-fee-payments.md). +{% endhint %} + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/// @title PrivacyBridge Interface +/// @notice Interface for moving funds into, within, and out of the Payy native privacy pool using ZK proofs. +/// @dev Merkle tree hashing uses Poseidon. Merkle path sibling order is left-to-right at each level. +/// All proof-verification functions expect the verifier to reconstruct and validate circuit public +/// inputs from `publicInputs`. +interface IPrivacyBridge { + // ---------------------------- + // Events + // ---------------------------- + + /// @notice Emitted when a transfer within the privacy pool is processed. + /// @param txHash Hash of the proof inputs for off-chain correlation (implementation-defined) + /// @param verificationKeyHash Hash of the verification key used + event TransferProcessed( + bytes32 indexed txHash, + bytes32 indexed verificationKeyHash + ); + + /// @notice Emitted when funds are burned (withdrawn) from the privacy pool. + /// @param txHash Hash of the proof inputs for off-chain correlation (implementation-defined) + /// @param verificationKeyHash Hash of the verification key used + event BurnProcessed( + bytes32 indexed txHash, + bytes32 indexed verificationKeyHash + ); + + /// @notice Emitted when funds are minted (deposited) into the privacy pool. + /// @param txHash Hash of the proof inputs for off-chain correlation (implementation-defined) + /// @param verificationKeyHash Hash of the verification key used + event MintProcessed( + bytes32 indexed txHash, + bytes32 indexed verificationKeyHash + ); + + /// @notice Emitted when ERC-20 funds are swept into bridge custody. + /// @param sweepHash Hash derived from keccak256(abi.encodePacked(to, nonce)) authorizing the sweep + /// @param token ERC-20 token address that was swept + /// @param from The visible ERC-20 account that funds were moved from (equals msg.sender) + /// @param amount The actual amount swept (<= maxAmount) + event SweepProcessed( + bytes32 indexed sweepHash, + address indexed token, + address indexed from, + uint256 amount + ); + + // ---------------------------- + // Core functions + // ---------------------------- + + /// @notice Move funds within the privacy pool. + /// @dev Expected public inputs (canonical ordering, implementation-defined): + /// - recent_root + /// - input_nullifiers_x2 + /// - output_commitments_x2 + /// - `recent_root` must be contained in Rollup's recent-root window + function transfer( + bytes32 verificationKeyHash, + bytes calldata proof, + bytes32[] calldata publicInputs + ) external; + + /// @notice Move funds out of the privacy pool (withdraw/burn). + /// @dev Expected public inputs (canonical ordering, implementation-defined): + /// - recent_root + /// - input_nullifiers_x2 + /// - output_commitments_x2 + /// - burn_recipient_public + /// - burn_value + /// - `recent_root` must be contained in Rollup's recent-root window + function burn( + bytes32 verificationKeyHash, + bytes calldata proof, + bytes32[] calldata publicInputs + ) external; + + /// @notice Move funds into the privacy pool (deposit/mint). + /// @dev Expected public inputs (canonical ordering, implementation-defined): + /// - recent_root + /// - input_nullifiers_x2 + /// - output_commitments_x2 + /// - mint_value + /// - `recent_root` must be contained in Rollup's recent-root window + function mint( + bytes32 verificationKeyHash, + bytes calldata proof, + bytes32[] calldata publicInputs + ) external; + + /// @notice Sweep ERC-20 funds from msg.sender into bridge custody up to a maximum amount. + /// @dev + /// - Source: the visible source account is msg.sender. + /// - Authorization: `sweepHash` uniquely identifies the sweep and prevents replay. + /// - Amount: implementation will transfer `min(balanceOf(msg.sender), allowance(msg.sender, this), maxAmount)` of + /// `token` into bridge custody. + /// - Accounting: implementation emits `SweepProcessed` with the actual amount swept. + /// - Note: the current implementation does not mint a private commitment as part of `sweep`. + /// @param token The ERC-20 token to sweep + /// @param sweepHash Hash derived from keccak256(abi.encodePacked(to, nonce)) + /// @param maxAmount Maximum amount to sweep + function sweep( + address token, + bytes32 sweepHash, + uint256 maxAmount + ) external; + + // ---------------------------- + // Introspection / helpers + // ---------------------------- + + /// @notice Returns true if a commitment / nullifier has already been inserted into the rollup tree. + /// @dev Convenience helper over `Rollup.exists(bytes32)`. + function elementExists(bytes32 element) external view returns (bool); + + /// @notice Optional helper to compute a canonical hash of proof inputs for event indexing. + /// @dev Implementations may define txHash as keccak256(abi.encode(verificationKeyHash, proof, publicInputs)). + function computeTxHash( + bytes32 verificationKeyHash, + bytes calldata proof, + bytes32[] calldata publicInputs + ) external pure returns (bytes32); + + /// @notice Returns the Merkle inclusion path for a given commitment. + /// @dev Tree uses Poseidon hashing. Sibling order is strictly left-to-right per level. + function getMerklePath( + bytes32 commitment + ) external view returns ( + bytes32 root, + bytes32[] memory siblings + ); + + /// @notice Returns the current Merkle root recognized by the bridge. + function getRoot() external view returns (bytes32 root); +} + +``` + +`elementExists(bytes32)` is part of the deployed `PrivacyBridge` implementation and forwards to `Rollup.exists(bytes32)` for O(1) existence checks before insertions. diff --git a/docs/public/protocol/privacyvaultregistry.md b/docs/public/protocol/privacyvaultregistry.md new file mode 100644 index 0000000..add3592 --- /dev/null +++ b/docs/public/protocol/privacyvaultregistry.md @@ -0,0 +1,89 @@ +# PrivacyVaultRegistry + +The PrivacyVaultRegistry is used in the transparently upgraded private transfer flow to determine which privacy vault service a user is using: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/// @title IPrivacyVaultRegistry +/// @notice Interface for a registry that maps an owner to a canonical Privacy Vault URI. +interface IPrivacyVaultRegistry { + // ---------------------------- + // Events + // ---------------------------- + + /// @notice Emitted when a vault URI is created for an owner. + /// @param owner The owner of the vault record + /// @param uri The URI that was set + event VaultCreated(address indexed owner, string uri); + + /// @notice Emitted when a vault URI is updated. + /// @param owner The owner of the vault record + /// @param oldUri The previous URI + /// @param newUri The new URI that was set + event VaultUpdated(address indexed owner, string oldUri, string newUri); + + /// @notice Emitted when ownership of a vault record is transferred. + /// @param previousOwner The previous owner + /// @param newOwner The new owner + event VaultOwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /// @notice Emitted when a vault record is removed. + /// @param owner The owner whose record was removed + /// @param oldUri The URI that was removed + event VaultRemoved(address indexed owner, string oldUri); + + // ---------------------------- + // Core functions + // ---------------------------- + + /// @notice Create a new vault record for msg.sender with the provided URI. + /// @param uri The URI string to associate with the caller's vault + function createVault(string calldata uri) external; + + /// @notice Update the caller-owned vault URI. + /// @param newUri The new URI string + function updateVault(string calldata newUri) external; + + /// @notice Remove the caller-owned vault record. + function removeVault() external; + + /// @notice Transfer ownership of the caller-owned vault record to a new owner. + /// @param newOwner The address of the new owner + function transferVaultOwnership(address newOwner) external; + + // ---------------------------- + // Views + // ---------------------------- + + /// @notice Get the vault URI for a given owner. + /// @param owner The owner address to query + /// @return uri The URI string associated with the owner (empty if none) + function getVaultURI(address owner) external view returns (string memory uri); + + /// @notice Returns true if a record exists for the given owner. + /// @param owner The owner address to query + /// @return exists Whether the record exists + function hasVault(address owner) external view returns (bool exists); + + /// @notice Returns metadata for a vault record. + /// @param owner The owner address to query + /// @return uri The URI string + /// @return recordOwner The current owner/controller of the record + /// @return createdAt Creation timestamp + /// @return updatedAt Last update timestamp + /// @return exists Whether the record exists + function getVaultRecord(address owner) + external + view + returns ( + string memory uri, + address recordOwner, + uint64 createdAt, + uint64 updatedAt, + bool exists + ); +} + +``` diff --git a/docs/public/protocol/provers.md b/docs/public/protocol/provers.md new file mode 100644 index 0000000..1524f04 --- /dev/null +++ b/docs/public/protocol/provers.md @@ -0,0 +1,7 @@ +# Provers + +Payy Network provers process L2 sequenced blocks, proving in ZK (zero knowledge) that the EVM Layer and Privacy Layer transactions are valid. The EVM Layer and Privacy Layer proofs are constructed separately and then combined in the final proof. + +An entire EVM block is aggregated into a single proof, and further those blocks are aggregated into further blocks. + +Provers prove that the L2 blocks are valid. If the block is valid, the proof and root merkle hash of the rollup is updated in Ethereum. The Ethereum smart contract needs only the proof and the new root hash from the prover to the verify and ensure the security of the network. diff --git a/docs/public/protocol/rollup.md b/docs/public/protocol/rollup.md new file mode 100644 index 0000000..e3184f9 --- /dev/null +++ b/docs/public/protocol/rollup.md @@ -0,0 +1,46 @@ +# Rollup + +The Rollup contract is a genesis deployed wrapper around the Privacy Layer sparse merkle tree. +The contract maintains a FIFO ring-buffer of the last 1024 roots to support recent-root checks. + +The protocol provides this for other developers to use in their own privacy rollups. + +The low-level Smirk precompiles consumed by this wrapper are documented in [Precompiles](precompiles.md). + +The following shows the Solidity interface for the Rollup contract: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface IRollup { + // ---------------------------- + // Core functions + // ---------------------------- + + /// @notice Add an element to the rollup tree. + function add(bytes32 data) external; + + /// @notice Remove an element from the rollup tree. + function remove(bytes32 data) external; + + /// @notice Check whether an element exists. + function exists(bytes32 data) external view returns (bool); + + /// @notice Get the merkle path siblings for an already derived tree element. + function getMerklePath(bytes32 element) external view returns (bytes32[] memory); + + /// @notice Get the current rollup root. + function getRoot() external view returns (bytes32); + + /// @notice Returns true if `root` is in the recent-root window. + /// @dev The current root is always treated as recent. + function isRecentRoot(bytes32 root) external view returns (bool); + + /// @notice The fixed FIFO capacity for recent roots. + function recentRootsCapacity() external pure returns (uint256); + + /// @notice Current number of tracked recent roots (saturates at 1024). + function recentRootsCount() external view returns (uint256); +} +``` diff --git a/docs/public/protocol/sequencers.md b/docs/public/protocol/sequencers.md new file mode 100644 index 0000000..2fb386f --- /dev/null +++ b/docs/public/protocol/sequencers.md @@ -0,0 +1,10 @@ +# Sequencers + +Sequencers are responsible for ensuring the sequencing and validity of transactions on Payy. Sequencer operators will be rewarded with the PAYY token for their work in sequencing and producing blocks. + +Due to the high performance requirement of Payy: + +* multiple sequencers will operate in parallel to sequence blocks +* multiple blocks will be produced per block allocation by a single sequencer + +Selection of sequencers will be determined using Fast Hotstuff consensus protocol. diff --git a/docs/public/protocol/transactionbridge.md b/docs/public/protocol/transactionbridge.md new file mode 100644 index 0000000..5d75256 --- /dev/null +++ b/docs/public/protocol/transactionbridge.md @@ -0,0 +1,165 @@ +# TransactionBridge + +{% include "../../../.gitbook/includes/toc-payy-transactions.md" %} + +The TransactionBridge is a genesis deployed contract for Payy transaction submission. +It exposes EIP-712-compatible transaction hashing for tooling, while `submit` accepts only direct sender submissions (`msg.sender == txn.from`). + +Batches have two execution modes: + +- For atomic batches (`requireSuccess = true`), every call must succeed. If any subcall fails, the entire transaction reverts, earlier successful subcalls are rolled back, no `TxnCallResult`, `TxnProcessed`, or `TxnRejected` logs persist, and the nonce/status remain unchanged. An atomic batch failure is therefore a reverted submission, not a `TxnRejected` outcome. +- For best-effort batches (`requireSuccess = false`), the bridge still executes every call in order and emits `TxnCallResult` for each one. The transaction still completes in the processed lifecycle state, and `TxnProcessed.success` flips to `false` if any subcall fails. Those partial failures are reflected only in the per-call results plus `TxnProcessed.success = false`; they do not emit `TxnRejected`. + +The following shows the Solidity interface for the TransactionBridge: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface ITransactionBridge { + // ---------------------------- + // Structs + // ---------------------------- + + struct Call { + address to; + uint256 value; + uint256 gasLimit; + bytes data; + // Optional authoriser signature (EIP-712 over this Txn without signature field) + bytes signature; + } + + // How the fee is paid (currency + caps) + struct FeePayment { + // 0 = Native, 1 = ERC20 + uint8 currency; + address token; // ERC-20 token address if currency == 1 + uint256 maxFee; // cap in native units (or token units if ERC-20) + uint256 maxPriorityFee; // optional tip cap (native units semantics) + } + + // Who pays and why they're allowed to pay (sponsorship or self-pay) + struct FeePayer { + // 0 = Self (txn.from pays), 1 = Sponsored + uint8 mode; + + // The account responsible for paying the fee (EOA or Contract) + address payer; + + // Sponsorship authorisation data: + // - For EOA-signed vouchers: abi-encoded SponsorVoucher + signature + // - For contract approvals: abi-encoded params used by the payer contract's approve function + bytes authData; + + // Discriminator for how to validate authData: + // 0 = None (self-pay), 1 = EOA voucher, 2 = Contract approval + uint8 authKind; + } + + struct Delegation { + bool enabled; + address delegator; + uint8 scopeType; // 0=None,1=Contract,2=FunctionSelector,3=Wildcard + address scopeTarget; + bytes4 functionSelector; + uint256 notBefore; + uint256 notAfter; + uint256 revocationNonce; + } + + struct Schedule { + uint256 notBefore; + uint256 notAfter; + } + + struct NonceSpace { + bytes32 key; + uint256 nonce; + } + + struct Txn { + address from; + Call[] calls; + FeePayment feePayment; // currency + caps + FeePayer feePayer; // who pays + sponsorship auth + Schedule schedule; + Delegation delegation; + NonceSpace nonceSpace; + bytes32 salt; + bool requireSuccess; + bytes metadata; + uint256 chainId; + uint256 expiry; + } + + struct CancelTxn { + address from; + bytes32 txnHash; + NonceSpace nonceSpace; + uint256 chainId; + uint256 expiry; + bytes reason; + } + + // ---------------------------- + // Events + // ---------------------------- + + event TxnSubmitted( + bytes32 indexed txnHash, + address indexed from, + address indexed relayer, + bytes32 nonceSpaceKey, + uint256 nonce + ); + + event TxnProcessed( + bytes32 indexed txnHash, + address indexed from, + bool success, + uint256 totalGasUsed, + uint256 feePaid, + address feeToken, + address payer + ); + + event TxnCallResult( + bytes32 indexed txnHash, + uint256 index, + address to, + bool success, + uint256 gasUsed, + bytes returnData + ); + + event TxnRejected( + bytes32 indexed txnHash, + address indexed from, + uint8 reasonCode, + bytes reasonData + ); + + event TxnCancelled( + bytes32 indexed txnHash, + address indexed from, + bytes32 nonceSpaceKey, + uint256 nonce + ); + + // ---------------------------- + // Core functions + // ---------------------------- + + function submit(Txn calldata txn) external payable; + + // ---------------------------- + // Helpers + // ---------------------------- + + function eip712DomainSeparator() external view returns (bytes32); + function txnHash(Txn calldata txn) external view returns (bytes32); + function nextNonce(address from, bytes32 key) external view returns (uint256); + function getStatus(bytes32 txnHash) external view returns (uint8 status); +} +``` diff --git a/docs/public/stablecoins/payy-transactions.md b/docs/public/stablecoins/payy-transactions.md new file mode 100644 index 0000000..99ed1b7 --- /dev/null +++ b/docs/public/stablecoins/payy-transactions.md @@ -0,0 +1,4 @@ +# Payy Transactions + +{% include "../../../.gitbook/includes/toc-payy-transactions.md" %} + diff --git a/docs/public/stablecoins/pusd.md b/docs/public/stablecoins/pusd.md new file mode 100644 index 0000000..129c358 --- /dev/null +++ b/docs/public/stablecoins/pusd.md @@ -0,0 +1,85 @@ +# PUSD + +PUSD is the native stablecoin for Payy. A US treasuries backed USD stablecoin that is highly safe and compliant. PUSD is issued from the US and is compliant with the Genius Act. + +PUSD is the native token for Payy (similar to ETH on Ethereum), allowing simpler user experiences when dealing with gas payments, as no conversion is necessary when displaying gas prices. + +| Key | Value | +| -------- | ----------- | +| Name | Payy USD | +| Symbol | PUSD | +| Decimals | 18 decimals | +| Permit | ✅ | + +### ERC-20 Interface + +PUSD is available as both an ERC-20 and as the native token, with balances automatically synced across both states. This means applications no longer need to special case the native token. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/// @title PUSD ERC-20 Interface with EIP-2612 Permit +/// @notice ERC-20 + Metadata + EIP-2612 permit + EIP-712 domain accessors +interface IPUSD { + // ------------------------------------------------------------ + // Events (ERC-20) + // ------------------------------------------------------------ + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); + + // ------------------------------------------------------------ + // ERC-20 Standard + // ------------------------------------------------------------ + function totalSupply() external view returns (uint256); + + function balanceOf(address account) external view returns (uint256); + + function allowance(address owner, address spender) external view returns (uint256); + + function approve(address spender, uint256 value) external returns (bool); + + function transfer(address to, uint256 value) external returns (bool); + + function transferFrom(address from, address to, uint256 value) external returns (bool); + + // ------------------------------------------------------------ + // ERC-20 Metadata (EIP-20 optional) + // ------------------------------------------------------------ + function name() external view returns (string memory); + + function symbol() external view returns (string memory); + + function decimals() external view returns (uint8); + + // ------------------------------------------------------------ + // EIP-2612 Permit + // ------------------------------------------------------------ + /// @notice Sets `value` as the allowance of `spender` over `owner`'s tokens, via signature. + /// @dev See EIP-2612. Should revert on invalid signature, expired deadline, or if owner == address(0). + /// Implementations may support chain-specific nonces and domain separators (EIP-712). + /// @param owner The token owner granting allowance + /// @param spender The spender being approved + /// @param value The allowance value + /// @param deadline Timestamp after which the permit is invalid + /// @param v secp256k1 signature v + /// @param r secp256k1 signature r + /// @param s secp256k1 signature s + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + /// @notice Current nonce for `owner` used in EIP-2612 permit signatures + function nonces(address owner) external view returns (uint256); + + /// @notice EIP-712 domain separator used in the encoding of the permit signature + function DOMAIN_SEPARATOR() external view returns (bytes32); +} + +``` diff --git a/docs/public/stablecoins/stable-gas.md b/docs/public/stablecoins/stable-gas.md new file mode 100644 index 0000000..65104d5 --- /dev/null +++ b/docs/public/stablecoins/stable-gas.md @@ -0,0 +1,53 @@ +# Stable Gas + +### Gas in PUSD stablecoin + +[PUSD](pusd.md) is the native gas token for Payy, enabling simpler gas interactions: + +* PUSD is non-volatile, so the price you pay for gas remains more consistent +* Less risk related to holding a volatile asset for future gas payments +* Simpler gas calculations, no conversion into USD required +* PUSD natively earns yield, helping to accrue value to PAYY token + +### Fee stabilisation + +Given that Payy is a high performance blockchain with multiple blocks per second, fees are dynamically adjusted every 30 blocks (\~10 seconds) to reduce excessive changes in gas prices. + +In addition, Payy builds on Ethereum’s EIP-1559 but smooths how the base fee moves so fees change less erratically. Instead of reacting only to the last block’s gas usage, Payy uses a simple weighted average (EWMA) of recent usage to decide how much to adjust the base fee. This keeps confirmations reliable without surprise fee spikes. + +#### Raw utilisation calculation + +Raw utilisation per block: + + $$U_t = \frac{\text{gas used in block } t}{\text{target gas per block}}$$) + +Smoothed utilisation: + +$$\hat{U}_t = \alpha \cdot U_{t-1} + (1 - \alpha) \cdot \hat{U}_{t-1}$$ + +where: + +$$\begin{aligned} U_t &\;\text{gas utilisation ratio of block } t \\ U^{\ast} &\;\text{target utilisation (e.g.\ } 50\%\text{)} \\ \hat{U}_t &\;\text{smoothed utilisation estimate} \\ \alpha &\in (0,1] \;\text{smoothing factor} \\ B_t &\;\text{base fee for block } t \end{aligned}$$ + +#### Base fee calculation + +The base fee update then mirrors EIP-1559, but uses the smoothed utilisation. Using the utilisation calculation we can update the base fee as follows: + +$$B_t = B_{t-1} \cdot \left(1 + \gamma \cdot \frac{\hat{U}_t - U^{\ast}}{U^{\ast}}\right)$$ + +where: + +$$\gamma \;\text{is the maximum per-block adjustment factor}$$ + +### Gas swaps + +PUSD is the native token on Payy, and is used for paying gas, but network participants receive payment in PAYY. + +To do this, a native swap is performed at the start of each block to swap all gas paid in PUSD to PAYY token. + +### Why it matters + +* Stablecoins payments for gas provide a more stable gas fee and therefore more predictable operations for payments +* Institutions prefer to hold stablecoins over volatile assets +* Additional compliance and controls are often needed with non-stable tokens + diff --git a/docs/public/stablecoins/zero-fee-payments.md b/docs/public/stablecoins/zero-fee-payments.md new file mode 100644 index 0000000..b8d5e47 --- /dev/null +++ b/docs/public/stablecoins/zero-fee-payments.md @@ -0,0 +1,37 @@ +# Zero Fee Payments + +Payy natively supports zero fee private ERC-20 transfers. This is implemented by zero rating all interactions with the [PrivacyBridge](../protocol/privacybridge.md) contract, which is the [EVM Layer](../protocol/evm-layer.md) interface to the [Privacy Layer](../protocol/privacy-layer/). + +Zero fee transfers are only available for private transfers, giving the following benefits: + +* Encourages wider use of the Privacy Layer (i.e. privacy pools), increasing the anonymity set for all protocol users +* Payments on the [Privacy Layer](../protocol/privacy-layer/) are highly optimised, so there is significantly less overhead to the network to zero rate these +* Built-in spam protection as a result of ZK [Privacy Layer](../protocol/privacy-layer/) architecture + +### Compatibility with existing wallets + +Zero fee transfers work natively with any wallet that support adding a custom Ethereum compatible RPC - e.g. MetaMask, TrustWallet, etc. + +Wallets calculate gas prices through this typical workflow: + +1. **Call** `⁠eth_estimateGas` with the transaction parameters to determine the required gas limit +2. Retrieve current network conditions using `eth_gasPrice` or `⁠eth_feeHistory` to understand base fees and priority fee trends +3. **Calculate total fee** using the formula: ⁠(base fee + priority fee) × gas limit + +In order to ensure that all existing wallets support free transfers, Payy Network will return `0` gas for ERC-20 transfers, ensuring that existing wallet infrastructure allows submission without gas. + +### Spam protection + +ZK proofs are required to submit, which must reference the root of Smirk (Payy's sparse merkle tree), this adds a computational cost for submitting proofs. Further proofs cannot be pre-generated, as they automatically expire every \~60 seconds (as proofs must include a reference to a recent root hash of Smirk). + +In addition, the transfer function for ERC-20 will only be `0` fee if the gas used in the transfer function is less than 100,000 gas. + +### Why it matters + +* For payments use cases, users never have to understand or interact with gas +* Consumers expect parity with their tradfi free transfers +* Free global transfers is highly attractive to businesses who pay significant costs to move money globally + +### + + diff --git a/docs/public/tokenomics/tokenomics.md b/docs/public/tokenomics/tokenomics.md new file mode 100644 index 0000000..f0c169e --- /dev/null +++ b/docs/public/tokenomics/tokenomics.md @@ -0,0 +1,93 @@ +# Tokenomics + +Payy has two primary native tokens: + +1. PAYY - a value accruing token used to lock protocol value +2. PUSD - a USD pegged stablecoin backed by US treasuries, used as the native EVM gas token (can be minted directly from USDC and USDT) + +These two tokens are carefully counterbalanced to provide the different properties required for an optimal user experience and value accrual. + +### ZKenomics + +Privacy is a first party primitive on Payy, and Payy incentivises the use of privacy features to ensure maximum adoption and liquidity in the privacy pools: + +* Zero gas on private ERC-20 transfers/payments +* Fixed gas for all other private transactions ($0.01) + +Payy is able to offer these features due to the unique properties of ZK (zero knowledge) proofs that are the building blocks of privacy. That is - verifying ZK proofs is extremely fast, non-linear to proof complexity and 100x cheaper than proving. + +This enables Payy to implement a high performance ZK payment lane for private payments. Utilising cheap to verify proofs and parallelised execution outside of the EVM, we can ensure that zero gas transfers have limited impact on the network. This allows us to offer a significant user experience boost to consumer use cases, where zero fee transfers are commonplace and expected, driving strong consumer liquidity. + +An additional concern associated with offering free transactions is preventing spam. However, the properties of ZK provide natural built-in protection against spam, as proofs are cheaper to verify than they are to create. As clients must generate the proofs and transactions must be submitted in a limited time window, it becomes economically disincentivised to send spam transactions to the network. + +### Token Revenue + +The PAYY token accrues value in the following ways: + +1. gas fees on transactions (avg txn fee target of $0.01) +2. treasury bill yield from PUSD +3. native swaps between PAYY <> PUSD + +This revenue model ensures that regardless of whether the user holds PAYY or PUSD, values still accrues to the PAYY token. + +#### Gas fees + +Whilst direct private payments are free, gas is charged on all other transactions. This includes, all indirect payments which are made as part of another function’s execution. Analysis of recent Ethereum blocks shows that 70% of ERC-20 transfers are made indirectly as part of another call (e.g. swaps, safe). This ensures strong gas revenue for payments. + +Gas fees are paid in PUSD, this provides significant UX benefit for payments use cases, as users need to hold only one token for stablecoin payments (regardless of whether they are direct or indirect). Stable gas fees additionally provide a benefit to enterprise use cases, where holding a non-stable token is problematic for economic and legal reasons. + +When gas is paid, PUSD is natively swapped to PAYY token and then burned. This actively decreases the supply of the PAYY token for every gas-consuming transaction that occurs on Payy. + +Revenue from gas grows with usage: + +| **TPS** | **Revenue ($M)** | **Note** | +| ------- | ---------------- | ------------------- | +| 10 | 3 | - | +| 129 | 41 | Tron avg TPS | +| 173 | 55 | Base avg TPS | +| 3,000 | 946 | Solana avg TPS | +| 100,000 | 31,536 | Visa/Mastercard TPS | + +_Payy is targeting max throughput of 100,000 tps_ + +#### Treasury bill yield + +Despite most blockchains having a defacto primary stablecoin, most blockchains receive no revenue from their stablecoin tokens. Instead all value accrual flows out of the blockchain to the stablecoin issuer. + +On Payy, PUSD will be the primary natively supported stablecoin for Payy network. It is a US dollar denominated yield bearing stablecoin backed by US treasuries. PUSD will not offer yield directly to the user (similar to USDC/USDT), but instead yield will be used to buy and burn the PAYY token. + +Because gas fees are paid in PUSD, it’s likely that some portion of user funds will be held in PUSD rather than PAYY token. Yet, because of yield on PUSD, regardless of the allocation between PUSD and PAYY, value still accrues to PAYY token. In addition, because Payy provides gas-free private transfers, we strongly incentivise consumer deposits and liquidity onto Payy, further increasing the yield potential for PUSD. + +All yield generated from PUSD is used to buy PAYY token from the native swap pool, and then burned. This actively decreases the supply of the PAYY token for each yield generation event. + +Revenue from PUSD yield grows with stablecoin liquidity: + +| **TVL** | **Revenue ($M)** | **Note** | +| ---------- | ---------------- | ----------------------- | +| **$1B** | 40 | - | +| **$4.41B** | 176 | USDC on Base | +| **$10B** | 400 | USDC on Solana | +| **$78B** | 3,120 | USDT on Tron | +| **$156B** | 6,240 | USDC + USDT on Ethereum | + +#### Native swaps + +As Payy has two native tokens, it is necessary to provide a native way to swap between them. In particular, as gas fees are paid in PUSD and yield revenue accrues in PUSD, it is necessary to have a native way to swap between the tokens. + +A simple AMM model can be used to swap between the two tokens. Swap fees will be charged at 0.1% to ensure strong adoption of the pool. To further enhance PAYY token value accrual, a fee will only be charged when executing a sell on the PAYY token. Buys from USDP to PAYY will not be charged a fee. + +The initial liquidity for the native pool will be seeded from the pre-sale and TGE distribution. + +Liquidity providers to the native pool will receive PAYY token, all remaining swap fees will be used to burn PAYY token, increasing the price of PAYY for each swap. + +### Network participants + +Network participants that perform essential roles in the network will be economically incentivised and rewarded with PAYY tokens. These tokens will be newly minted PAYY tokens from the treasury, as is common in other blockchains such as Ethereum. + +The following network participants will be rewarded: + +* Sequencer - sequence transactions and submission to DA +* Data availability - gas fees paid to Ethereum +* Provers - prove in ZK Payy blocks to be rolled up to Ethereum + +Due to the efficiency of Payy’s network design, the cost of rewarding network participants is far less than revenue generated, making PAYY a deflationary value accruing token. diff --git a/docs/public/tools/block-explorers.md b/docs/public/tools/block-explorers.md new file mode 100644 index 0000000..8d05418 --- /dev/null +++ b/docs/public/tools/block-explorers.md @@ -0,0 +1,8 @@ +# Block Explorers + +* Block explorers for let you view, verify, and analyze onchain activity across transactions, addresses, contracts, and blocks on our EVM‑compatible zk L2. +* Because Payy is privacy‑first, some data will be selectively disclosed or privacy‑preserving by default. You may see obfuscated fields when interactions occur with the [PrivacyBridge](../protocol/privacybridge.md). + +### Providers + +
ProviderDescription
Payy (coming soon)Payy privacy-first explorer, enabling enhanced introspection for native privacy primitives.
BlockscoutBlockscout is an open-source blockchain explorer and analytics platform that enables users and developers to view transactions, addresses, tokens, and smart contracts across EVM-compatible networks.
diff --git a/docs/public/tools/compliance.md b/docs/public/tools/compliance.md new file mode 100644 index 0000000..4cdb889 --- /dev/null +++ b/docs/public/tools/compliance.md @@ -0,0 +1,7 @@ +--- +hidden: true +--- + +# Compliance + +Compliance is diff --git a/docs/whitepaper/00_header.md b/docs/whitepaper/00_header.md new file mode 100644 index 0000000..30f53d9 --- /dev/null +++ b/docs/whitepaper/00_header.md @@ -0,0 +1,3 @@ +% L2 Ethereum ZK Rollup for Private and Compliant Transactions +% Calum Moore, Sidhant Gandhi +% Feb 12, 2024 - Draft 0.6.0 diff --git a/docs/whitepaper/01_abstract.md b/docs/whitepaper/01_abstract.md new file mode 100644 index 0000000..d91b940 --- /dev/null +++ b/docs/whitepaper/01_abstract.md @@ -0,0 +1,3 @@ +# Abstract + +This paper describes the Payy Network, an Ethereum L2 zero knowledge rollup with built in privacy and compliance. We describe the protocol’s interaction interface, network topology and security mechanisms, that provide privacy preserving and compliant UTXO transactions at scale. \ No newline at end of file diff --git a/docs/whitepaper/02_introduction.md b/docs/whitepaper/02_introduction.md new file mode 100644 index 0000000..ac4e452 --- /dev/null +++ b/docs/whitepaper/02_introduction.md @@ -0,0 +1,11 @@ +# Introduction + +Blockchain technology has revolutionised the digital realm, enabling an era of decentralisation, security, and trust without intermediaries. These benefits have spurred many innovations across diverse sectors, enabling more transparent, immutable, and efficient transactions. Yet, for all their transformative advantages, blockchains have encountered a significant hurdle: privacy. This limitation has, in many ways, restrained the true potential of blockchains, especially in sectors where confidentiality is paramount, such as traditional finance, real world assets and payments. + +Historically, achieving both transparency and privacy in blockchains appeared mutually exclusive. However, with the emergence of Zero-Knowledge (ZK) proofs, a form of cryptography for provable computation in zero knowledge domains, it has become feasible to ensure transaction privacy without compromising the integrity that blockchain platforms promise. + +A side effect of enabling privacy, however, is that it complicates regulatory compliance. With public blockchains, the natural transparency enables regulators to screen all transactions for potential compliance breaches. With privacy, everything becomes more opaque and it becomes significantly more difficult to monitor transactions effectively. Yet this too, can be solved through zero knowledge, with clients generating relevant proofs that their activity has been compliant, so called “Proof of Innocence”. + +In addition, Layer 2 (L2) solutions have taken center stage in the quest to address blockchain scalability, reducing the strain on the main chain and ensuring faster, more efficient operations. By combining the benefits of L2 with the privacy and compliance capabilities of ZK proofs, a new paradigm emerges. + +In this paper, we present a full end to end solution for providing on chain privacy and compliance via an Ethereum L2 rollup, powered by zero knowledge. diff --git a/docs/whitepaper/03_architecture.md b/docs/whitepaper/03_architecture.md new file mode 100644 index 0000000..c3e43e6 --- /dev/null +++ b/docs/whitepaper/03_architecture.md @@ -0,0 +1,85 @@ +# Architecture + +The Payy Network is an L2 Ethereum validium rollup with the following architecture: + +![The Payy Network L2 architecture](../whitepaper/img/architecture.png) + +## Roles + +Each node on the the Payy Network protocol can perform one or more of the following distinct roles: + +* **Sequencer** - sequences transactions into a block, guaranteeing the order of transactions and providing data availability +* **Prover** - prove in zero knowledge that an existing sequenced block is valid or invalid and submit proof to the L1 +* **Client** - proves valid UTXO transactions, so transaction data can remain private +* **Encrypted Transaction Registry (Optional)** - stores transactions so that transactions can be made with offline users +* **Ethereum** - provides security for the network + +The following sequence diagram demonstrates the flow of actors in the network during a transfer of notes. + +![Sequence for transacting on the Payy Network](../whitepaper/img/transfer-sequence.png) + +## Sequencers + +Sequencers are responsible for ordering transactions and validating transaction proofs. Sequencers form a Proof of Stake (PoS) network using the HotStuff consensus protocol \[AGM18]. This ensures that the sequencers can operate in a decentralised and censorship resistent form, enabling it to provide soft finality and data availability to the network. + +Sequencers only need to store blocks since the last rollup (i.e. the last proven block on Ethereum), significantly reducing the overhead of running a sequencer. This dramatically increases the decentralisation of the protocol, as many commodity devices can participate in sequencing. + +### Soft Finality + +Sequencers provide fast (\~1s) soft finality for transactions through the PoS consensus. This security is only required for the short period between a transaction being sequenced into a block and that block being rolled up by the prover. This period of time is dependent on the number of provers and other network configuration. As such, a smaller stake can be used to secure the soft finality. + +It is recommended that clients use soft finality for smaller transaction sizes. The determination for using soft finality would be based on the amount of stake, divided by the proving interval. For larger transactions, it is recommended that clients wait for full Ethereum finality (i.e. when the prover has rolled up the root hash to Ethereum). However, the responsibility for clearly communicating risk profiles for transaction sizes is delegated to the client. + +### Data Availability + +Availability of transaction data (UTXO proof and public input hashes) is essential, so all network participants can determine for themselves the full merkle tree (as the merkle tree algorithm is predictable). Without this, a prover could change the root hash on Ethereum without providing the txn data to other nodes, making it impossible for other nodes to know what the current state of the merkle tree is (only that it is valid). Without the current state of the merkle tree, no other nodes would be able to create a proof, as the merkle tree is used in proof generation. + +## Provers + +Provers prove that the L2 sequenced blocks are valid or invalid. If the block is valid, the proof and root merkle hash of the rollup is updated in Ethereum. The Ethereum smart contract needs only the proof and the new root hash from the prover to the verify and ensure the security of the network. + +### Slot Allocation + +It would be expensive and inefficient for all provers to submit proofs in parallel, as many of the proofs would be invalidated by a different recent proof included just before it. To prevent this, provers will be allocated slots which determine when they are eligible for submitting a sequencer of proof to Ethereum. + +Ordering of slot allocation will based on a random deterministic ordering derived from a distributed randomness protocol, such as drand \[DLJ20]. Nodes are ranked for each L2 block, the primary node has priority for the first 8 blocks, then the next in line has priority for the next 8 blocks, and so on. Nodes can submit a block before the transaction deadline. If a prover fails to submit the block in a timely manor, other nodes can submit the block proof instead. + +### Prover Rewards + +To join as a prover, the prover is required to submit a small stake (e.g. 1ETH), designed to prevent nuisance behaviour. For example, provers could register but then fail to batch any transaction proofs on their allocated turn, or submit invalid proofs. There will be no limit to the number of sequencers that can join, improving the decentralisation of the network. Economic factors should limit the total number of provers to a reasonable level, as each additional prover reduces the overall gain for all other provers. + +Provers are refunded for the cost of the Ethereum transaction to add the block, and also rewarded for their participation on the network. + +### Block Frequency + +The maximum frequency that sequencers should add transactions to Ethereum is 1 epoch (\~ 6 minutes), adding batches faster than this is redundant, as finality will not be improved due to reliance of the finality of Ethereum. The actual block frequency will be determined by the algorithm on the Ethereum smart contract, and will take into consideration the level of activity on the network, fees and other concerns. + +## Ethereum + +Ethereum provides the settlement layer for the Payy Network. It also holds the smart contracts required to administrate the network, for example, adding/removing sequencers and provers, slashing rules, and the bridge contracts. + +### L1 Queue + +The L1 Queue allows network participants to call other Ethereum smart contracts as part of any transaction that occurs on the Payy Network. Essentially, this allows for an atomic transactions across both Ethereum and the Payy Network. This is primarily used for the bridge functionality, so that funds can be locked on Ethereum via the bridge smart contract, whilst being simultaneously minted on the Payy Network, and vice versa. The L1 queue can also be used to better prevent censorship resistance, allowing any client to submit transactions directly and ensure they are included, albeit at a higher cost and slower transaction time. + +L2 transactions pushed into the L1 Queue should be picked up by the next sequencer and included in the next batch/block. If no sequencer takes these transactions after a pre-determined period of time, then the transaction can be force included in its own block. This should be used only as an escape hatch. + +### Bridge + +The bridge smart contract on Ethereum is responsible for bridging assets from Ethereum to the Payy Network, and vice versa. Given the Payy Network does not currently provide smart contract functionality, a specific transaction is used for bridging assets. When this transaction type is used, the proof circuit would modify its rules (e.g. to allow new funds to be minted or burned, outside of the normal balanced txn rules). + +#### Onboard: From Ethereum to the Payy Network + +To use the bridge, a user would submit a single transaction to Ethereum directly, that both transfers the required funds to the Ethereum bridge contract, and adds the mint txn to the L1 Queue so the mint is propagated to the Payy Network. Before accepting a block from the prover, the smart contract would verify that the required funds were previously transferred. + +#### Offboard: From the Payy Network to Ethereum + +Withdrawing an asset from the Payy Network, involves proving that a UTXO note was burned, and no output on the Payy Network was derived. This would allow the Ethereum smart contract to release funds (previously locked during the Onboard process). This unlocking would occur once the L2 block has been proven, as this is the point the transactions are proven to be valid. + +### Ethereum Reorgs + +Finality on Ethereum takes 2 epochs and therefore within that time reorgs can occur. Reorgs could impact the the Payy Network sequencing and proving of transactions, but the worst case outcome would be that sequencers and provers would need to rework and submit their transactions. The state would never become invalid as a result of an Ethereum reorg. + +## Encrypted Transaction Registry + +The encrypted transaction registry is an optional protocol component that allows transactions to be sent to the receiver, while the receiver is offline. These transactions are stored encrypted with the receiver’s public key, ensuring only the receiver can decrypt the data. When a client joins the network, they scan the registry for new transactions that have been sent to them. diff --git a/docs/whitepaper/04_rollup.md b/docs/whitepaper/04_rollup.md new file mode 100644 index 0000000..c3c1e5b --- /dev/null +++ b/docs/whitepaper/04_rollup.md @@ -0,0 +1,32 @@ +# Rollup + +The rollup represents the entire state of the network, where each piece of state is referred to as a note, is represented by a commitment hash \[Merkle87]. Hashes result in data loss, so the original messages can provably never be reconstructed, improving the privacy of the protocol. + +Each of the hash record states are stored in a merkle tree, so a single root hash can represent the entire state of the network. No underlying data is stored in the rollup, and therefore any required shared data must be stored in the Encrypted Transaction Registry. In addition to privacy, an additional advantage of storing only hashes in the rollup is that the rollup on disk data size can be somewhat constrained and deterministic. This is a result of all hashes being a consistent size regardless of the size of the underlying data. This reduction in the disk size requirements for clients, improves the number of clients able to join the network, thereby improving decentralisation. + +The merkle tree must enable the following operations: + +* Prove inclusion - prove a hash exists in the tree +* Prove non-inclusion - prove a hash does not exist in the tree +* Insert - insert a new hash into the tree if it does not already exist + +To satisfy these properties, the Payy Network uses a sparse merkle tree \[DPP16]. A sparse merkle tree has a defined position for every possible value that can be inserted into the tree. In order to support a 256 bit (32 byte) hash, a tree of size $2^{256}$ is required. This means that for every operation, 256 tree nodes need to be traversed and validated. This may results in an unacceptable performance. + +There are two possible optimisations to improve the performance: + +1. A smaller tree could be used, such as $2^{128}$. This would result in a higher likelihood, but possibly still acceptable, risk of hash collision. For a tree of size $2^{128}$ it would take \~8 million years, generating 10,000 hashes per second to have a 1% chance of collision. +2. The tree can be sharded at multiple levels, allowing these verifications to occur in parallel + +### Merkle Proofs + +As every hash has a unique position in a sparse merkle tree, we can derive its position by decomposing each bit of the hash and traversing the tree based on whether the bit is 0 or 1. For 0, the tree is traversed to the left child, and for 1 the tree is traversed to the right child. + +![4 bit tree, demonstrating bit decomposition and insertion](../whitepaper/img/merkle.png) + +For an inclusion or non-inclusion proof, we can simply check that each of the provided siblings combined with the the computed child results in the root hash. For non-inclusion we are proving that the leaf node is a null value, which does not need to be passed to the proof, as it is a static value. + +![Inclusion and non-inclusion proof](../whitepaper/img/merkle-proofs.png) + +Insertion proofs are a combination of a non-inclusion proof (existing position must be null) and inclusion proof (proving the new root based on the inserted hash). + +![Inserting into merkle tree](../whitepaper/img/merkle-insert.png){ width=250px } diff --git a/docs/whitepaper/05_utxo.md b/docs/whitepaper/05_utxo.md new file mode 100644 index 0000000..5d6c542 --- /dev/null +++ b/docs/whitepaper/05_utxo.md @@ -0,0 +1,64 @@ +# UTXO + +UTXO (Unspent Transaction Output) is a state model introduced by Bitcoin \[Nak08] and additionally used in Zcash \[GMRA13], and other blockchains to store the balances that can be spent. In this model, each store of value is a note that belongs to a specific authenticated account. Notes can be of any value, but can only be used once. If the note contains a value larger than you wish to transfer, you can create a new note with the output. You can use multiple input notes, so long as the total value of incoming notes is the same (or less) than the total value of outgoing notes. + +![UTXO](../whitepaper/img/utxo.png) + +This model has a number of advantages: + +* **Scalability** - because a user can have multiple notes, multiple payments can be included in the same block (even in the case where the underlying data is hidden) +* **Privacy** - each transaction creates a new output record/hash. This prevents adversaries from looking for addresses with high activity or attempting to match accounts based on the source IP of the transaction, as is possible in account based models like Ethereum. + +The considered drawbacks for the UTXO model are: + +* **Increased tree depth** - UTXO transactions create one new insert hash for every incoming and outgoing note in a transaction. In contrast, an account based model (such as used in Ethereum) uses only a single hash insert per account, reducing the size of the tree. + +Due to the strict privacy constraints desired for the Payy Network, the UTXO model was selected. + +## Notes + +Each note has the following state properties: + +* **Application Type** - used to differentiate between different applications running on the Payy Network (each application type would have a different set of ZK circuit constraints) +* **Authentication** - used to verify which actor is allowed to “spend” a note +* **Value** - the balance of the note, balances between incoming and outgoing notes must match +* **Nullifier entropy** - additional nullifier entropy to increase security and privacy + +![UTXO note structure](../whitepaper/img/note.png){ width=150px } + +## Authentication + +Authentication identifies the user that is allowed to spend a note. The auth commitment is used in the Nullifer constraint to ensure that the user generating the nullifier (i.e. spending the note), knows the underlying secret key represented by the commitment. the Payy Network supports multiple authentication systems, denoted by a type enum, to provide flexible ownership over notes. Additional authentication types may be added over time. + +### Poseidon + +Users can generate a random 32-byte secret key, and use the poseidon commitment of the secret key as the authentication address for a note. This provides a highly performant authentication mechanism, but may not be well supported by existing wallets or tooling. + +### Ethereum + +The Payy Network natively supports Ethereum addresses. In this case, the auth commitment would be the Ethereum address. To spend with the Ethereum address a proof must be generated that proves ownership of the underlying private key. This can be achieved in zero knowledge by passing the Ethereum private key as a private input and and deriving the address from the private key. + +## Minting and Burning + +Special transaction types will allow the UTXO model to be modified in order to allow bridging of assets to and from the Payy Network: + +* **Mint** - allows a note to be created without a corresponding input, minting will be further validated on Ethereum in the data availability layer before it will be accepted as a valid transaction +* **Burn** - allows a note to be used without a corresponding output, when this is proved on Ethereum, the funds will be released from the bridge contract + +## Nullifier + +As per the UTXO model, a note can only be used once. As such, the protocol must keep track of which notes have been used or spent, and which have not. Naively, this could be performed by removing used notes from the merkle tree, however this would reveal to a sender when a note they have sent to another user has been spent, reducing privacy. + +Instead, to enhance privacy, we can use a deterministic nullifier record that for each spend must be inserted into the tree, and proven not to exist in the tree via a non-inclusion proof. The presence of the nullifier represents the record being spent. The nullifier is constructed in such a way that it is impossible for an external party to determine which nullifier matches a spent record (or a record to be spent). + +The nullifier is calculated as follows: + +$$ +N = \text{Poseidon}(nk, \psi, cm) +$$ + +Where: + +* $nk$ is the Nullifier Key, a unique secret associated with each user (this is a auth commitment to the auth) +* $\psi$ (psi) sender controlled randomness, additional entropy provided by Blake2b \[Aumasson et al. 2013] hash. Blake2b provides additional entropy and privacy security. +* $cm$ is the note commitment, which is a Poseidon commitment to the note. diff --git a/docs/whitepaper/06_compliance.md b/docs/whitepaper/06_compliance.md new file mode 100644 index 0000000..c263bfd --- /dev/null +++ b/docs/whitepaper/06_compliance.md @@ -0,0 +1,46 @@ +# Compliance + +Public blockchains allow regulators to easily verify on chain activity is compliant with regulations. As the Payy Network is privacy preserving, compliance capabilities need to be defined at the protocol level to ensure the network is not useful to those seeking to perform illicit activity. + +There are a number of different mechanisms for enforcing compliance on the network: + +1. Transaction lineage - tracking of full or partial transaction lineage, so that illicit funds can be tracked and disabled across the network. Transaction details are still private. +2. Privacy pools - bundling transactions and actors into pools of good and or bad actors and treating them as a single entity +3. Compliance ZK proofs - enable us to hide information while proving specific compliance constraints + +These techniques could be used independently or in combination to ensure the required level of compliance. In addition, these capabilities could be applied at either onramp/offramp or for each individual transaction depending on the regulatory or user requirements. + +## Transaction lineage + +Transaction lineage allows the network to trace the source of funds (but not individual transaction details) across the network. This can generally be split into two categories: + +1. **Source lineage** - source tracking tracks only the source of each transaction as it enters and exists the network. This enables onramp and offramp providers to reject transactions that are from external sources which are later found to be illicit. +2. **Full lineage** - all transaction lineage can be tracked. This reduces the level of privacy, as any new holder of the note obtains a significant portion of lineage, and could reveal this publicly without consent of the other parties. + +![L2 Rollup-Privacy Pools.drawio (31).png](../whitepaper/img/source-lineage.png) + +The transaction lineage would be added to each note, so any receiver of a note would obtain the transaction lineage, but outside parties would not. In order to avoid exponentially increasing note size, the lineage of transactions would only be maintained for a specified time period (i.e. number of blocks, where block time is constant), for example 1 year. + +## Privacy Pools + +Privacy pools \[BJMFA23] is a mechanism that group users into pools that share the same level of regulatory and compliance risk. Although the focus of the privacy pools paper is based around the use of privacy pools in so called “mixers”, it does discuss the implications of extending this to a system where intermediate transfers are possible. + +Extending this to such a system requires users to accept the risk of loss of funds if a particular pool they are part of is deemed to be non-compliant. It would therefore be essential that users choose a pool which matches their risk appetite. + +There are a number of different types of pools that could used, such as: + +* Add with delay, exclude bad actors +* KYC pool +* N per month per person +* N per month per trusted community member +* Real-time AI-based scoring + +Transactions between pools would be allowed according to the inbound/outbound rules of both pools. + +## Compliance ZK-Proofs + +ZK proofs enable us to prove certain attributes of a transaction or chain of transactions in a privacy preserving environment. These proofs could be used as a layer on top of privacy pools or transaction lineage to provide additional privacy while maintaining the same level of compliance. + +![Compliance ZK proof](../whitepaper/img/compliance-proof.png) + +In addition, ZK could be used to prove/enforce additional constraints. Offramp providers could even enforce their own additional ZK constraints. These additional constraints can be applied by the offramp in a permission-less manner outside of the protocol, as the proofs would be generated locally on the client and submitted in addition to the protocol proof to the offramp. diff --git a/docs/whitepaper/07_zk_proofs.md b/docs/whitepaper/07_zk_proofs.md new file mode 100644 index 0000000..6655202 --- /dev/null +++ b/docs/whitepaper/07_zk_proofs.md @@ -0,0 +1,47 @@ +# ZK Proofs + +There are three ZK circuits required for the the Payy Network ZK rollup: + +1. **UTXO proof (client)** - runs on the client and proves that a user has permission to spend an input note and generate an output note +2. **Insert proof (prover)** - calculates the new root given a number of UTXO proofs +3. **Aggregation proof (prover)** - combines multiple UTXO proofs and the insert proof into a single proof to be verified on Ethereum + +In addition, a compliance proof can optionally be generated at any time to prove compliance of given notes: + +1. **Compliance proof (client)** - allows the client to prove that the source of their funds is not from a blacklisted address + +The following diagram represents the high level of flow of input constrains to the zero knowledge circuits. + +![ZK process flow](img/zk-flow.png) + +## Proof Algorithm + +There has been rapid improvements in zk-SNARK/zk-STARK algorithms in recent years. Groth-16 \[Gro16] has been traditionally the benchmark, which is used in large scale decentralised protocols, such as Filecoin \[BPZZ17]. However, this algorithm relies on a trusted setup procedure which makes updating the protocol difficult, and prevents the use of user generated functions (i.e. smart contracts), so it will not be used in the Payy Network. + +Instead, the Payy Network uses Halo2 circuits with a HyperPlonk \[CBZZ22] arithmetisation scheme and KZG \[KZG10] as the polynomial commitment scheme. In addition to the performance characteristics, Halo2 was selected for its high security guarantees having been audited and used in production for numerous projects such as Zcash \[Hopwood et al. 2022] and Scroll. + +The KZG commitment scheme was selected over the IPA \[BBBF18] commitment scheme, for the improved performance, especially in relation to aggregation proofs. Further enhancements to the proving system are anticipated. For example, improved recursion techniques, such as ProtoStar \[BC23], could likely yield significant performance increases. + +The BN256 pairing friendly elliptic curve \[BN06] is used over the pasta curves traditionally used with Halo2, due for the need of verifying the proofs on Ethereum. + +## Performance + +Performance is a key consideration for zero knowledge circuits, in particular the prover cost is significant compared to running computation in a native turing machine. The following outlines the expected performance characteristics of each proof. + +| Circuit | Browser | Desktop/Mobile | Optimised Server | +| ----------------- | ------- | -------------- | ---------------- | +| UTXO Proof | 9s | 3s | - | +| Insert Proof | N/A | N/A | < 1s | +| Aggregation Proof | N/A | N/A | 40s | +| Compliance Proof | 1s | 0.3s | - | + +## Enhanced throughput with multi-level aggregations + +To increase the throughput of the network, multiple levels of aggregation can be applied, which can then recursively combine multiple proofs into a single proof. Each additional level of proof increases the overall throughput of the network, at the expense of additional latency. + +| Aggregators | Layers | TPS | Latency | +| -------------------------- | ------ | ------ | ------- | +| 1 | 1 | 10 | 10s | +| 11 (10 + 1) | 2 | 100 | 20s | +| 111 (100 + 10 + 1) | 3 | 1,000 | 30s | +| 1111 (1000 + 100 + 10 + 1) | 4 | 10,000 | 40s | diff --git a/docs/whitepaper/08_transmitting_notes.md b/docs/whitepaper/08_transmitting_notes.md new file mode 100644 index 0000000..8012f32 --- /dev/null +++ b/docs/whitepaper/08_transmitting_notes.md @@ -0,0 +1,29 @@ +# Transmitting Notes + +In order to spend a note you must have the data that represents the note being spent, as generating the spend UTXO proof requires the notes data; and only the hash commitment of the note is stored in the rollup. The sender of the note, is responsible for communicating the the new notes data to the receiver of the note. The sender could decide not send or record the output note, but then the receiver would not acknowledge receipt of note (i.e. from the senders perspective, they have not received any notes) and therefore it would be as if the transfer did not complete. + +There are two mechanisms to allow senders to communicate the note data to the recipient. + +* P2P - increased privacy, but requires both actors to be online +* Encrypted Registry - reduced privacy if encryption key is lost or exploited + +## P2P + +If both peers are online, the sender can send the transaction hashes and proofs to the sequencer, and the underlying data directly to the receiver. This method approach enhances privacy, as the underlying data is never stored in the public domain. + +![Transmitting notes with P2P](../whitepaper/img/p2p-transmit.png){ width=150px } + +## Encrypted Registry + +If the Sender and Receiver are not online at the same time, the transaction data can be stored in the Encrypted Registry. The Encrypted Registry is optional, and not a core part of the Payy Network protocol. It is provided purely as a convenience feature to store shared user transaction data. + +To use the Encrypted Registry, the Sender uses the Receiver’s PublicKey to encrypt the data, so only the Receiver can decrypt it. When the Receiver joins the network, they can scan the Encrypted Registry attempting to decrypt all new records since they were last online. If they are able to decrypt a transaction, then it is a transaction they have been sent. + +![Transmitting notes with encrypted registry store](../whitepaper/img/encrypted-reg-transmit.png){ width=150px } + +Users of the Encrypted Registry should be aware that using it reduces the level of privacy protection. If the data is encrypted in a public registry there are two main risks: + +1. Exposed secret key - secret key used for encryption is compromised at any point in time +2. Compromised encryption protocol - underlying encryption protocol is broken by advances in cryptography or compute + +As the Encrypted Registry is an optional feature, other providers could offer alternative encrypted registries to store transactions. In future, we may provide a sharded decentralised encrypted registry, where the encrypted data is split into chunks and blindly stored across multiple nodes, reducing the exposure to the risks described above. diff --git a/docs/whitepaper/09_conclusion.md b/docs/whitepaper/09_conclusion.md new file mode 100644 index 0000000..2103306 --- /dev/null +++ b/docs/whitepaper/09_conclusion.md @@ -0,0 +1,3 @@ +# Conclusion + +In this paper, we presented the requirements and design for a privacy preserving Ethereum L2 zero knowledge rollup with built in privacy and compliance. We presented the underlying zero knowledge proof algorithms that enable secure and privacy preserving off-chain transactions, as well as the mechanism for transmitting and sending notes. For the first time, the Payy Network protocol provides the necessary infrastructure to private financial transactions that are privacy preserving yet compliant. diff --git a/docs/whitepaper/10_references.md b/docs/whitepaper/10_references.md new file mode 100644 index 0000000..8f21a23 --- /dev/null +++ b/docs/whitepaper/10_references.md @@ -0,0 +1,34 @@ + +# References + +[AGM18] Abraham, I., Gueta, G., Malkhi, D. 2018. Hot-Stuff the Linear, Optimal-Resilience, One-Message BFT Devil. CoRR, abs/1803.05069. Accessed on: http://arxiv.org/abs/1803.05069 + +[Aumasson et al. 2013] Aumasson, J-P., Neves, S., Wilcox-O’Hearn, Z., and Winnerlein, C. 2013. BLAKE2: simpler, smaller, fast as MD5. + +[BBBF18] Bünz, B., Bootle, J., Boneh, D., Fish, B. Fisch and Poelstra, A. 2018. Bulletproofs: Short Proofs for Confidential Transactions and More, In IEEE Symposium on Security and Privacy (SP), 319-338. IEEE. [https://doi.org/10.1109/SP.2018.00020](https://doi.org/10.1109/SP.2018.00020) + +[BC23] Bünz, B., Chen, B. 2023. ProtoStar: Generic Efficient Accumulation/Folding for Special Sound Protocols. Cryptology ePrint Archive, Paper 2023/620. Accessed on: [https://eprint.iacr.org/2023/620](https://eprint.iacr.org/2023/620) + +[BINSSA23] Buterin, V., Illum, J., Nadler M, Schär, Fabian., and Soleimani, Ameen. 2023. *Blockchain Privacy and Regulatory Compliance: Towards a Practical Equilibrium.* + +[BN06] Barreto, P. and Naehrig, M., 2006. *Pairing-friendly elliptic curves of prime order.* In: Preneel, B., Tavares, S. (eds) Selected Areas in Cryptography. SAC 2005. Lecture Notes in Computer Science (vol 3897). Springer, Berlin, Heidelberg. [https://doi.org/10.1007/11693383_8](https://doi.org/10.1007/11693383_8) + +[BPZZ17] Benet, J., Pontarelli, N., Zigdon, Y., and Zuckerman, E. 2017. *Filecoin: A Decentralized Storage Network.* [https://filecoin.io/filecoin.pdf](https://filecoin.io/filecoin.pdf) + +[CBZZ22] Chen, B., Bünz, B., Boneh, D., and Zhang, Z. 2022. *HyperPlonk: Plonk with Linear-Time Prover and High-Degree Custom Gates*. Cryptology ePrint Archive, Paper 2022/1355. Accessed on: [https://eprint.iacr.org/2022/1355](https://eprint.iacr.org/2022/1355) + +[DLJ20] Deco, N., Jovanovic, P., & Barman, L. 2020. *Drand: Verifiable Distributed Randomness.* [https://drand.love/whitepaper.pdf](https://drand.love/whitepaper.pdf). + +[DPP16] Dahlberg, R., Pulls, T., and Peeters, R. 2016. *Efficient Sparse Merkle Trees*. In: Brumley, B., Röning, J. (eds) Secure IT Systems. NordSec 2016. Lecture Notes in Computer Science (vol 10014). Springer, Cham. [https://doi.org/10.1007/978-3-319-47560-8_13](https://doi.org/10.1007/978-3-319-47560-8_13) + +[Gro16] Groth, J. 2016. *On the Size of Pairing-Based Non-interactive Arguments.* Advances in Cryptology -- EUROCRYPT 2016 + +[GMRA13] Green, M., Miers, I., Rubin, A.D. and Garman, C. 2013. *Zerocoin: Anonymous Distributed E-Cash from Bitcoin.* + +[Hopwood et al. 2022] Hopwood, D., Bowe, S., Hornby, T., & Wilcox, N. (2022). *Zcash Protocol Specification.* [https://zips.z.cash/protocol/protocol.pdf](https://zips.z.cash/protocol/protocol.pdf) + +[KZG10] Kate, A., Zaverucha, G., and Goldberg, I. 2010. *Constant-Size Commitments to Polynomials and Their Applications.* In: Abe, M. (ed) Advances in Cryptology – ASIACRYPT 2010. Lecture Notes in Computer Science (vol 6477). Springer, Berlin, Heidelberg. [https://doi.org/10.1007/978-3-642-17373-8_17](https://doi.org/10.1007/978-3-642-17373-8_17) + +[Merkle87] Merkle, R. 1987. *A digital signature based on a conventional encryption function." Advances in Cryptology* — CRYPTO ’87. Springer. + +[Nak08] Nakamoto, S. 2008. Bitcoin: A Peer-to-Peer Electronic Cash System. \ No newline at end of file diff --git a/docs/whitepaper/img/architecture.png b/docs/whitepaper/img/architecture.png new file mode 100644 index 0000000..763413d Binary files /dev/null and b/docs/whitepaper/img/architecture.png differ diff --git a/docs/whitepaper/img/compliance-proof.png b/docs/whitepaper/img/compliance-proof.png new file mode 100644 index 0000000..13a035b Binary files /dev/null and b/docs/whitepaper/img/compliance-proof.png differ diff --git a/docs/whitepaper/img/encrypted-reg-transmit.png b/docs/whitepaper/img/encrypted-reg-transmit.png new file mode 100644 index 0000000..3149873 Binary files /dev/null and b/docs/whitepaper/img/encrypted-reg-transmit.png differ diff --git a/docs/whitepaper/img/merkle-insert.png b/docs/whitepaper/img/merkle-insert.png new file mode 100644 index 0000000..4362619 Binary files /dev/null and b/docs/whitepaper/img/merkle-insert.png differ diff --git a/docs/whitepaper/img/merkle-proofs.png b/docs/whitepaper/img/merkle-proofs.png new file mode 100644 index 0000000..301e5f9 Binary files /dev/null and b/docs/whitepaper/img/merkle-proofs.png differ diff --git a/docs/whitepaper/img/merkle.png b/docs/whitepaper/img/merkle.png new file mode 100644 index 0000000..99169f5 Binary files /dev/null and b/docs/whitepaper/img/merkle.png differ diff --git a/docs/whitepaper/img/note.png b/docs/whitepaper/img/note.png new file mode 100644 index 0000000..c423d71 Binary files /dev/null and b/docs/whitepaper/img/note.png differ diff --git a/docs/whitepaper/img/p2p-transmit.png b/docs/whitepaper/img/p2p-transmit.png new file mode 100644 index 0000000..fab3c58 Binary files /dev/null and b/docs/whitepaper/img/p2p-transmit.png differ diff --git a/docs/whitepaper/img/source-lineage.png b/docs/whitepaper/img/source-lineage.png new file mode 100644 index 0000000..ef15a86 Binary files /dev/null and b/docs/whitepaper/img/source-lineage.png differ diff --git a/docs/whitepaper/img/transfer-sequence.png b/docs/whitepaper/img/transfer-sequence.png new file mode 100644 index 0000000..c912333 Binary files /dev/null and b/docs/whitepaper/img/transfer-sequence.png differ diff --git a/docs/whitepaper/img/utxo.png b/docs/whitepaper/img/utxo.png new file mode 100644 index 0000000..afc83f0 Binary files /dev/null and b/docs/whitepaper/img/utxo.png differ diff --git a/docs/whitepaper/img/zk-flow.png b/docs/whitepaper/img/zk-flow.png new file mode 100644 index 0000000..aeb5d01 Binary files /dev/null and b/docs/whitepaper/img/zk-flow.png differ diff --git a/eth/.gitignore b/eth/.gitignore index 40333b2..28b150a 100644 --- a/eth/.gitignore +++ b/eth/.gitignore @@ -16,7 +16,6 @@ artifacts/contracts/AggregateVerifierV1.sol artifacts/contracts/BurnVerifierV1.sol artifacts/contracts/BurnVerifierV2.sol artifacts/contracts/IUSDC.sol/IUSDC.d.ts -artifacts/contracts/IUSDC.sol/IUSDC.dbg.json artifacts/contracts/IUSDC.sol/artifacts.d.ts artifacts/contracts/MintVerifierV1.sol artifacts/contracts/Verifier.sol diff --git a/eth/README.md b/eth/README.md index 9930baa..acd1df5 100644 --- a/eth/README.md +++ b/eth/README.md @@ -2,6 +2,33 @@ Rollup smart contracts to verify the rollup state on Ethereum. +## Testing + +The project uses Hardhat with Mocha/Chai testing framework and blockchain-specific matchers for comprehensive smart contract testing. + +### Run Tests + +```bash +yarn test +``` + +### Test Features + +- **Blockchain-specific matchers**: Clean, readable assertions for smart contract testing +- **Balance assertions**: `expect(await contract.balanceOf(owner.address)).to.equal(1000)` +- **Event testing**: `expect(transaction).to.emit(contract, "Transfer")` +- **Revert testing**: `expect(contract.connect(addr1).withdraw()).to.be.revertedWith("Not owner")` +- **Balance change testing**: `expect(tx).to.changeEtherBalance(addr1, ethers.parseEther("1"))` + +### Continuous Integration + +Tests run automatically on: +- Pull requests modifying files in `eth/` +- Pushes to `main` and `next` branches +- Manual workflow dispatch + +All tests must pass with 100% success rate before merge. + ## Run locally Run the local Ethereum hardhat node (resets on each restart): @@ -16,6 +43,15 @@ Deploy the contract: yarn deploy:local ``` +### EIP-7702 delegate deployment + +`scripts/deploy_eip7702.ts` now deploys the `Eip7702SimpleAccount` delegate via the +canonical deterministic deployment proxy (`0x4e59…b4956C`) using the salt +`EIP7702_SIMPLE_ACCOUNT_RECEIVE_V1`. The script prints the expected CREATE2 address and +only broadcasts the transaction if the deterministic deployer is available on the selected +network. When running against a development Hardhat chain, the script automatically falls +back to a traditional deployment. + Run server: ```bash @@ -60,112 +96,84 @@ cargo run --release server #### Deploy ```bash -OWNER=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 PROVER_ADDRESS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 VALIDATORS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 AMOY_URL=https://polygon-amoy.g.alchemy.com/v2/9e_9NcJQ4rvg9RCsW2l7dqdbHw0VHBCf SECRET_KEY= GAS_PRICE_GWEI=2 yarn deploy -- --network amoy +OWNER=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 PROVER_ADDRESS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 VALIDATORS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 AMOY_URL= SECRET_KEY= GAS_PRICE_GWEI=2 yarn deploy -- --network amoy ``` #### Upgrade ```bash -ROLLUP_PROXY_ADMIN_ADDR=0x3a7122f0711822e63aa6218f4db3a6e40f97bdcf ROLLUP_CONTRACT_ADDR=0x1e44fa332fc0060164061cfedf4d3a1346a9dc38 AMOY_URL=https://polygon-amoy.g.alchemy.com/v2/9e_9NcJQ4rvg9RCsW2l7dqdbHw0VHBCf SECRET_KEY= yarn upgrade-rollup -- --network amoy +ROLLUP_PROXY_ADMIN_ADDR=0x3a7122f0711822e63aa6218f4db3a6e40f97bdcf ROLLUP_CONTRACT_ADDR=0x1e44fa332fc0060164061cfedf4d3a1346a9dc38 AMOY_URL= SECRET_KEY= yarn upgrade-rollup -- --network amoy ``` Add `UPGRADE_DEPLOY=true` to deploy the contract (not just print the calldata). -#### Addresses: - -``` -USDC_CONTRACT_ADDR=0x206fcb3bea972c5cd6b044160b8b0691fb4aff57 -AGGREGATE_BIN_ADDR=0x58f2e5031af2d6c1996334b10880973c494e3b06 -AGGREGATE_VERIFIER_ADDR=0xa98e2c3a375b5aedf31b1276594a11ff41d72a36 -MINT_BIN_ADDR=0x3945f7f99460c86dfe73de6a757b1b6ed1a52604 -MINT_VERIFIER_ADDR=0xfeda1cec4b2b9f958e6c0823cf14b0e687fa4a59 -BURN_BIN_ADDR=0xaa331ab85fa49137cbfbb614bc20eb55e0e1ae46 -BURN_VERIFIER_ADDR=0xe952927e6ff3c66933fa23f228dc74f7eff95fe3 -ROLLUP_V1_CONTRACT_ADDR=0x618975654efb35f6674fe9d1afb9f95fa78a31a7 -ROLLUP_PROXY_ADMIN_ADDR=0x3a7122f0711822e63aa6218f4db3a6e40f97bdcf -ROLLUP_V2_CONTRACT_ADDR=0x6c5da7ccab84eb7abadbcbe87b3913ccbad0fb9a -ROLLUP_V3_CONTRACT_ADDR=0x9b89bb7a804639bfde8c8d5b5826007988142a38 -ROLLUP_V4_CONTRACT_ADDR=0x68427f3169ed36b7b5933446305964f2b3445067 -BURN_TO_ADDRESS_ROUTER_CONTRACT_ADDR=0x3471dadabe5a8491e14a9192b1960a55108aea8d -BURN_V2_BIN_ADDR=0x8ef4a7d9d791c4798eff556ea9bbdbdc981678f7 -BURN_VERIFIER_V2_ADDR=0xbe5aee548b3b738dfb58cc3ea1c5d2c2b5d468fc -ROLLUP_V5_CONTRACT_ADDR=0xba3c280ddfca291f815cd61dc295009aae002795 -ROLLUP_CONTRACT_ADDR=0x1e44fa332fc0060164061cfedf4d3a1346a9dc38 -ROLLUP_V6_CONTRACT_ADDR=0x9165dbc43077c107f899a37b3c693d251a4bdb78 -``` - ### Testnet #### Deploy ```bash -OWNER=0x06BB7004273ac82309a7b1dF90B8cb76d6BA299F PROVER_ADDRESS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 VALIDATORS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 POLYGON_URL=https://polygon-mainnet.g.alchemy.com/v2/UrFsshbLOrSG1_cPayD3OHHi0s066Shx SECRET_KEY= yarn deploy -- --network polygon +OWNER=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 PROVER_ADDRESS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 VALIDATORS=0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323 MAINNET_URL= SECRET_KEY= yarn deploy -- --network mainnet ``` #### Upgrade ```bash -SECRET_KEY=... ROLLUP_CONTRACT_ADDR=0x24baf24128af44f03d61a3e657b1cec298ef6cdc ROLLUP_PROXY_ADMIN_ADDR=0xbb923b4c1cc57c4d929adfbc4160bfc26ad750ab POLYGON_URL=https://polygon-mainnet.g.alchemy.com/v2/UrFsshbLOrSG1_cPayD3OHHi0s066Shx yarn upgrade-rollup -- --network polygon +SECRET_KEY=... ROLLUP_CONTRACT_ADDR=0x883ff65e5ac46fc2c25a4e4ea901bf7e7f6c1705 ROLLUP_PROXY_ADMIN_ADDR=0x90588eedc0c12b8ba50823de7344e1b404384798 MAINNET_URL= yarn upgrade-rollup -- --network mainnet ``` -Addresses: +#### Addresses ``` -AGGREGATE_BIN_ADDR=0xebcde42fc628f06a2d395a972cb81b267a105577 -AGGREGATE_VERIFIER_ADDR=0xd8ce1f59185707503bffe45e34b29e3617049c27 -MINT_BIN_ADDR=0x30edc6ccf96dbda5d62e5e270d0731dac7298f81 -MINT_VERIFIER_ADDR=0xd9d38308653b83501a5feee170c6030890f9e43b -BURN_BIN_ADDR=0xf009a7a0a89f7514322edc1ae5c15ce0e1db4070 -BURN_VERIFIER_ADDR=0x4ac88e4a18f8f99a49bf7ccfc05b49cf8ef41cd9 -ROLLUP_V1_CONTRACT_ADDR=0x4514b09f62834d9d5807f4f24d200b4ff98046ed -ROLLUP_PROXY_ADMIN_ADDR=0xbb923b4c1cc57c4d929adfbc4160bfc26ad750ab -ROLLUP_V2_CONTRACT_ADDR=0xc4d8c671fbe3834e9d476bc146d348907d235614 -ROLLUP_V3_CONTRACT_ADDR=0x2cc9818c40c54de413b783aad42e407ade1d3093 -ROLLUP_V4_CONTRACT_ADDR=0xc546293e7c89a425eaf093eb01d104ef8aba7c14 -BURN_V2_BIN_ADDR=0x3160976dfe28b90cc0c60f9f372ee5c44a4746b5 -BURN_VERIFIER_V2_ADDR=0x9ffda5bdd6a8c63ad431ca0249c5e16d19c3d708 -ROLLUP_V5_CONTRACT_ADDR=0x61d67ac8d472a91c8f9bb0c8f92ed12cc362c196 -ROLLUP_CONTRACT_ADDR=0x24baf24128af44f03d61a3e657b1cec298ef6cdc -BURN_TO_ADDRESS_ROUTER_CONTRACT_ADDR=0x947502b6c4363e5ba5d7b65748478fb2ebc7319b -ROLLUP_V6_CONTRACT_ADDR=0x2f0b843869de91eef34441b639b41218ae67f4ee -ACROSS_WITH_AUTHORIZATION_CONTRACT_ADDR=0xf5bf1a6a83029503157bb3761488bb75d64002e7 +{ + proverAddress: '0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323', + validators: [ '0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323' ], + ownerAddress: '0x6B96F1A8D65eDe8AD688716078B3DD79f9BD7323', + deployerIsProxyAdmin: true +} +Linked library ZKTranscriptLib (__$e6391f3e4b1839f34ea5577896c8005de7$__) at 0x8a15e6434c1036048dfe4832468eddceed98da8a +AGGREGATE_VERIFIER_ADDR=0x69b820ac692cacf2797fd5bd0caff247a2c3cdec +ROLLUP_V1_IMPL_ADDR=0x89b1d6cf21a8c2769e4db4bbb4fdb11097e6a9cf +ROLLUP_CONTRACT_ADDR=0x883ff65e5ac46fc2c25a4e4ea901bf7e7f6c1705 +ROLLUP_PROXY_ADMIN_ADDR=0x90588eedc0c12b8ba50823de7344e1b404384798 +EIP7702_SIMPLE_ACCOUNT_ADDR=0xd2c66eb938fe5847522891a247264eac90eea93e ``` + ### Mainnet ```bash -OWNER=0x230Dfb03F078B0d5E705F4624fCC915f3126B40f PROVER_ADDRESS=0x5343b904bf837befb2f5a256b0cd5fbf30503d38 VALIDATORS=0x41582701cb3117680687df80bd5a2ca971bda964,0x75eadc4a85ee07e3b60610dc383eab1b27b1c4c1,0x53b385c35d7238d44dfd591eee94fee83f6711de,0x05dc3d71e2a163e6926956bc0769c5cb8a6b9d1a,0x581c5d92e35e51191a982ebd803f92742e3c9fe3,0xbb82aef611b513965371b3d33c4d3b6c8b926f24,0xeacb0b7e37709bafb4204c0c31a2919212049975,0xf9d65db5f8952bee5ea990df79a0032eda0752b7,0x662b7930b201fbe11bcef3cdef6e8f2c8ed4983a,0x68a78d978497b0a87ff8dbeaffae8e68ad4c39dc POLYGON_URL=https://polygon-mainnet.g.alchemy.com/v2/UrFsshbLOrSG1_cPayD3OHHi0s066Shx SECRET_KEY= yarn deploy -- --network polygon +OWNER=0x230Dfb03F078B0d5E705F4624fCC915f3126B40f PROVER_ADDRESS=0x5343B904Bf837Befb2f5A256B0CD5fbF30503D38 VALIDATORS=0x41582701CB3117680687Df80bD5a2ca971bDA964 MAINNET_URL= SECRET_KEY= yarn deploy -- --network mainnet ``` -Addresses: + +#### Addresses ``` -USDC_CONTRACT_ADDR=0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 -AGGREGATE_BIN_ADDR=0x31063c00ad62f9090abb9308f4549a1dee4a6362 -AGGREGATE_VERIFIER_ADDR=0x9d9fe636a329a07d26b5c5e8411b278462f5f325 -MINT_BIN_ADDR=0xe025bb7ce28a4565a890a8d708faf9dd48ea1678 -MINT_VERIFIER_ADDR=0xe938b6c17a39e80c7630040df0d2dbe794d42534 -BURN_BIN_ADDR=0x4449d93873f7523d1b6cdfaa5a792e0867ca3a17 -BURN_VERIFIER_ADDR=0x36e4a9f800e07a4aa6647c83e97f7e47b8028895 -ROLLUP_V1_CONTRACT_ADDR=0x470e6986d9a54b498f4fa39ee118d25d52cc0a19 -ROLLUP_CONTRACT_ADDR=0x4cbb5041df8d815d752239960fba5e155ba2687e -ROLLUP_PROXY_ADMIN_ADDR=0xe022130f28c4e6ddf1da5be853a185fbeb84d795 -BURN_TO_ADDRESS_ROUTER_CONTRACT_ADDR=0x8e93495fb707785af8c1345858e4898c2d005f7b -BURN_V2_BIN_ADDR=0x2c103552a8f311cd6e35c2ca69e2f42e812c12d0 -BURN_VERIFIER_V2_ADDR=0x51c77c8b99aab9d6c83a4deb1247c528325e5c0b -ROLLUP_V5_CONTRACT_ADDR=0x451a98322400d2a9018303cc66a68b3d903a3329 -ROLLUP_V6_CONTRACT_ADDR=0x3a58033501778babcd785cd89c054f16fa9b1f2b -ACROSS_WITH_AUTHORIZATION_CONTRACT_ADDR=0xf5bf1a6a83029503157bb3761488bb75d64002e7 +{ + proverAddress: '0x5343B904Bf837Befb2f5A256B0CD5fbF30503D38', + validators: [ '0x41582701CB3117680687Df80bD5a2ca971bDA964' ], + ownerAddress: '0x230Dfb03F078B0d5E705F4624fCC915f3126B40f', + deployerIsProxyAdmin: false +} +Linked library ZKTranscriptLib (__$e6391f3e4b1839f34ea5577896c8005de7$__) at 0xab57f01dc6cffd313233ec14d474cdf82512ff66 +AGGREGATE_VERIFIER_ADDR=0xb553c325959c8615d9018f00906aec3799b94200 +ROLLUP_V1_IMPL_ADDR=0x7d8837b547f4fea0053571cb149e845fc58e9b2d +ROLLUP_CONTRACT_ADDR=0x367c1eaf14aa06b78ce76bd0243297de79d85270 +ROLLUP_PROXY_ADMIN_ADDR=0xfe455bacaf1968f1ae6a322b8ffbe56840e2f590 +EIP7702_SIMPLE_ACCOUNT_ADDR=0x63b925fe7096104471bcbee5358505bf6e892344 ``` #### Upgrade ```bash -SECRET_KEY=... ROLLUP_CONTRACT_ADDR=0x4cbb5041df8d815d752239960fba5e155ba2687e ROLLUP_PROXY_ADMIN_ADDR=0xe022130f28c4e6ddf1da5be853a185fbeb84d795 POLYGON_URL=https://polygon-mainnet.g.alchemy.com/v2/UrFsshbLOrSG1_cPayD3OHHi0s066Shx yarn upgrade-rollup -- --network polygon +SECRET_KEY=... ROLLUP_CONTRACT_ADDR=0x367c1eaf14aa06b78ce76bd0243297de79d85270 ROLLUP_PROXY_ADMIN_ADDR=0xfe455bacaf1968f1ae6a322b8ffbe56840e2f590 MAINNET_URL= yarn upgrade-rollup -- --network mainnet ``` ### Upgrade Rollup contract +Fresh deployments now use the merged `contracts/rollup3/RollupV1.sol` implementation, so the +upgrade flow is only required for legacy rollup2 deployments. + Using `yarn upgrade-rollup`, you can upgrade a previously deployed rollup contract to a new version. Example without a specified network: @@ -174,6 +182,123 @@ Example without a specified network: SECRET_KEY=... ROLLUP_CONTRACT_ADDR= ROLLUP_PROXY_ADMIN_ADDR= yarn upgrade-rollup ``` +## Mint migration (Polygon -> Ethereum) + +Migration is a three-step process: + +1. **Extract**: `scripts/extract-mints.ts` reads `MintAdded` events from the source chain and saves unspent mints to a JSON file. +2. **Filter**: `scripts/filter-mints.ts` verifies candidates against the source chain state (via `getMint`) to ensure they are valid and unspent. +3. **Submit**: `scripts/submit-mints.ts` reads the verified JSON file, filters out mints already present on the target chain, and submits the rest. + +### Step 1: Extract Mints + +Required environment variables: +- `SOURCE_RPC_URL`: Source chain RPC endpoint +- `SOURCE_CONTRACT_ADDRESS`: Source rollup contract address + +Optional: +- `START_BLOCK`, `END_BLOCK`: Scan range +- `OUTPUT_FILE`: Path to save mints (default: `mints.json`) +- `BLOCK_BATCH_SIZE`: Blocks per scan chunk (default: 10000) +- `RPC_CONCURRENCY`: Concurrent requests (default: 5) + +```bash +SOURCE_RPC_URL= SOURCE_CONTRACT_ADDRESS= yarn extract-mints +``` + +### Step 2: Filter Mints + +Required environment variables: +- `SOURCE_RPC_URL`: Source chain RPC endpoint +- `SOURCE_CONTRACT_ADDRESS`: Source rollup contract address + +Optional: +- `INPUT_FILE`: Path to read extracted mints (default: `mints.json`) +- `OUTPUT_FILE`: Path to save verified mints (default: `filtered-mints.json`) +- `RPC_CONCURRENCY`: Concurrent verification requests (default: 10) + +```bash +SOURCE_RPC_URL= SOURCE_CONTRACT_ADDRESS= yarn filter-mints +``` + +### Step 3: Submit Mints + +Required environment variables: +- `TARGET_RPC_URL`: Target chain RPC endpoint +- `TARGET_CONTRACT_ADDRESS`: Target rollup contract address +- `PRIVATE_KEY`: Private key for transaction submission + +Optional: +- `INPUT_FILE`: Path to read verified mints (default: `filtered-mints.json`) +- `DRY_RUN`: Set to `true` to skip transactions +- `PRINT_TX`: Set to `true` to print transaction data (for Safe execution) instead of sending +- Gas fees are set automatically to 2x the RPC-recommended EIP-1559 fees (`maxFeePerGas` and `maxPriorityFeePerGas`) + +```bash +TARGET_RPC_URL= TARGET_CONTRACT_ADDRESS= PRIVATE_KEY= INPUT_FILE=filtered-mints.json yarn submit-mints +``` + +## Rollup initializer requirements + +`RollupV1.initialize` now accepts eight arguments: + +```solidity +function initialize( + address owner, + address usdcAddress, + address verifierAddress, + address prover, + address[] calldata initialValidators, + bytes32 verifierKeyHash, + uint32 verifierMessagesCount, + bytes32 initialNoteKind +); +``` + +- `verifierMessagesCount` must match the `messages_length` that your aggregate verifier enforces. The legacy `agg_final` circuit expects 1,000 messages (6 UTXOs * 5 messages per UTXO * padding), but if you regenerate a verifier with a different circuit you **must** update this value so the contract can size-check proofs before calling into the verifier. You can source the count from: + - the `messages_length` field on the deployed verifier contract (visible via `rollup.zkVerifiers(keyHash).messages_length`), or + - the generator metadata emitted by `noir/generate_fixtures.sh`. Keep the value alongside the verifier address in your deployment runbook. +- `initialNoteKind` binds the rollup to the token it will mint/burn. For bridged EVM assets we use format `0x0002 || chain_id(uint64, big endian) || token_address(20 bytes)`. The helper in [`eth/scripts/noteKind.ts`](./scripts/noteKind.ts) (`generateNoteKindBridgeEvm(chainId, tokenAddress)`) produces the correct 32-byte value; reuse it (e.g. through `ts-node`) when onboarding new tokens so deposits, withdrawals, and burn substitutions resolve to the right ERC20 contract. + +Record both arguments in your deployment checklist—operators must replay them any time they redeploy or upgrade through `TransparentUpgradeableProxy`. + +## Security Improvements + +### Block Height Validation (ENG-4064) + +The `verifyRollup` function in `contracts/rollup3/RollupV1.sol` now includes validation to ensure new block heights are strictly greater than the current block height. This prevents: + +- **Rollback Attacks**: Malicious actors cannot submit blocks with decreasing heights +- **Replay Attacks**: Same block height cannot be reused +- **Sequencing Integrity**: Maintains proper rollup block ordering +- **State Inconsistency**: Prevents breaking dependent systems expecting monotonic height increases + +The validation is implemented as: +```solidity +require(height > blockHeight, "RollupV1: New block height must be greater than current"); +``` + +### Testing + +Run the security tests with: +```bash +yarn test test/SimpleBlockHeightTest.test.ts +``` + +## Verifier Addresses + +This table documents deployed verifier contract addresses and their configurations: + +| Verifier Address | Verification Key | Messages | Notes | +|------------------|------------------|----------|-------| +| `0xe859860f654da247ba1468785ea40a386e982110` | `0x122d2ac7542fa020cbfff0836b5d0c30898330074b19869179bba49b5db69967` | 1000 | AGG_FINAL verifier | + +**Verification Key** corresponds to `AGG_FINAL_VERIFICATION_KEY_HASH`, which is consumed by the rollup verifier logic in [pkg/contracts/src/rollup.rs](../pkg/contracts/src/rollup.rs) and deployment tooling. + +**Messages** reflects the `verifierMessagesCount` value you supplied during `initialize`. For the current `agg_final` deployment this still equals the historical `AGG_FINAL_MESSAGES` constant (1000), but if you deploy a verifier with a different circuit you must update both the table and the initializer arguments so every operator knows which count to pass. + +Verifier contracts and their verification keys are generated via [noir/generate_fixtures.sh](../noir/generate_fixtures.sh); rerun that script whenever a circuit changes. Update this table whenever a new verifier is deployed so downstream operators have a single source of truth. + ## Regenerating EVM aggregate proof verifier To re-generate EVM proof verifier, see [pkg/contracts](/pkg/prover). diff --git a/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.d.ts b/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.d.ts index 2901836..bcab9cf 100644 --- a/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.d.ts +++ b/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.d.ts @@ -18,6 +18,11 @@ export interface AcrossWithAuthorization$Type { "internalType": "address", "name": "_across", "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" } ], "stateMutability": "nonpayable", @@ -82,6 +87,19 @@ export interface AcrossWithAuthorization$Type { "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "across", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -159,6 +177,11 @@ export interface AcrossWithAuthorization$Type { "name": "outputAmount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, { "internalType": "uint256", "name": "destinationChainId", @@ -194,10 +217,41 @@ export interface AcrossWithAuthorization$Type { "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ], - "bytecode": "0x60803461007457601f61091338819003918201601f19168301916001600160401b038311848410176100795780849260209460405283398101031261007457516001600160a01b0381169081900361007457600080546001600160a01b03191691909117905560405161088390816100908239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c80633644e515146105b85763eb2320b11461003357600080fd5b346105b5576102a03660031901126105b55761012435906001600160a01b03821682036105b55761014435916001600160a01b03831683036104e75761016435926001600160a01b03841684036105b15761018435936001600160a01b03851685036105ad57610204356001600160a01b03811681036105a957610224359163ffffffff80841684036105a557610244359781891689036105a1576102643590828216820361052a5767ffffffffffffffff610284351161052a573660236102843501121561052a5767ffffffffffffffff61028435600401351161052a5736602461028435600401356102843501011161052a576040516101466004610284350135601f01601f191660200182610621565b61028435600481013580835290602401602083013760206102843560040135820181018b9052815191810191909120604080517fb1808774e6a3862b691460baf364a9bb51d8654fecf525cc3f1c4eddb9419f689381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015286811660e08401528381166101008401526101a4356101208401526101c4356101408401526101e43561016084015287166101808301528488166101a08301528b85166101c08301528385166101e0830152610200808301919091528152610220810180821167ffffffffffffffff9091111761058d5761022081016040526020815191012061025f610643565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff60808301111761058d576102bf8160806102c893016040526020815191012060a435906084359060ff6064351690610738565b909291926107c8565b6001600160a01b03898116911603610557576001600160a01b0384163b1561052a57604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101a43560448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b038a165af1801561053657610541575b895460405163095ea7b360e01b81526001600160a01b0391821660048201526101a43560248201529a9b5098998b99602090829060449082908e908b165af18015610536576104fa575b5088546001600160a01b031694853b156104f657604051633dc9c91960e11b81526001600160a01b038c81166004808401919091529a8116602480840191909152928116604483015293841660648201526101a4803560848301526101c43560a48301526101e43560c48301529790931660e48401529684166101048301528316610124820152911661014482015261018061016482015261028435948501356101848201819052909486948694910190840137826101a461028435600401358401015281836101a482601f19601f6102843560040135011681010301925af180156104eb576104d3575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6104dc906105db565b6104e757813861049c565b5080fd5b6040513d84823e3d90fd5b8980fd5b6020813d60201161052e575b8161051360209383610621565b810103126104f657518015150361052a57386103b1565b8880fd5b3d9150610506565b6040513d8c823e3d90fd5b9798909961054e906105db565b97968990610367565b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b80fd5b50346105b557806003193601126105b55760206105d3610643565b604051908152f35b67ffffffffffffffff81116105ef57604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176105ef57604052565b90601f8019910116810190811067ffffffffffffffff8211176105ef57604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161067281610605565b601781520152603160f81b602060405161068b81610605565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176105ef5760405251902090565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116107bc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156107b05780516001600160a01b038116156107a757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b600481101561083757806107da575050565b600181036107f45760405163f645eedf60e01b8152600490fd5b600281036108155760405163fce698f760e01b815260048101839052602490fd5b60031461081f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea26469706673582212203a660b9f9600a5247c21885db9a8e37e4363095155e3b5b228a1762bb4f3374164736f6c63430008140033", - "deployedBytecode": "0x6080604052600436101561001257600080fd5b6000803560e01c80633644e515146105b85763eb2320b11461003357600080fd5b346105b5576102a03660031901126105b55761012435906001600160a01b03821682036105b55761014435916001600160a01b03831683036104e75761016435926001600160a01b03841684036105b15761018435936001600160a01b03851685036105ad57610204356001600160a01b03811681036105a957610224359163ffffffff80841684036105a557610244359781891689036105a1576102643590828216820361052a5767ffffffffffffffff610284351161052a573660236102843501121561052a5767ffffffffffffffff61028435600401351161052a5736602461028435600401356102843501011161052a576040516101466004610284350135601f01601f191660200182610621565b61028435600481013580835290602401602083013760206102843560040135820181018b9052815191810191909120604080517fb1808774e6a3862b691460baf364a9bb51d8654fecf525cc3f1c4eddb9419f689381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015286811660e08401528381166101008401526101a4356101208401526101c4356101408401526101e43561016084015287166101808301528488166101a08301528b85166101c08301528385166101e0830152610200808301919091528152610220810180821167ffffffffffffffff9091111761058d5761022081016040526020815191012061025f610643565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff60808301111761058d576102bf8160806102c893016040526020815191012060a435906084359060ff6064351690610738565b909291926107c8565b6001600160a01b03898116911603610557576001600160a01b0384163b1561052a57604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101a43560448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b038a165af1801561053657610541575b895460405163095ea7b360e01b81526001600160a01b0391821660048201526101a43560248201529a9b5098998b99602090829060449082908e908b165af18015610536576104fa575b5088546001600160a01b031694853b156104f657604051633dc9c91960e11b81526001600160a01b038c81166004808401919091529a8116602480840191909152928116604483015293841660648201526101a4803560848301526101c43560a48301526101e43560c48301529790931660e48401529684166101048301528316610124820152911661014482015261018061016482015261028435948501356101848201819052909486948694910190840137826101a461028435600401358401015281836101a482601f19601f6102843560040135011681010301925af180156104eb576104d3575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6104dc906105db565b6104e757813861049c565b5080fd5b6040513d84823e3d90fd5b8980fd5b6020813d60201161052e575b8161051360209383610621565b810103126104f657518015150361052a57386103b1565b8880fd5b3d9150610506565b6040513d8c823e3d90fd5b9798909961054e906105db565b97968990610367565b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b80fd5b50346105b557806003193601126105b55760206105d3610643565b604051908152f35b67ffffffffffffffff81116105ef57604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176105ef57604052565b90601f8019910116810190811067ffffffffffffffff8211176105ef57604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161067281610605565b601781520152603160f81b602060405161068b81610605565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176105ef5760405251902090565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116107bc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156107b05780516001600160a01b038116156107a757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b600481101561083757806107da575050565b600181036107f45760405163f645eedf60e01b8152600490fd5b600281036108155760405163fce698f760e01b815260048101839052602490fd5b60031461081f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea26469706673582212203a660b9f9600a5247c21885db9a8e37e4363095155e3b5b228a1762bb4f3374164736f6c63430008140033", + "bytecode": "0x60c03461009557601f610b8838819003918201601f19168301916001600160401b0383118484101761009a57808492604094855283398101031261009557610052602061004b836100b0565b92016100b0565b9060a052608052604051610ac390816100c5823960805181818160810152610171015260a05181818161050f0152818161056a0152818161066b01526107d40152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100955756fe608080604052600436101561001357600080fd5b600090813560e01c908163292c1d92146107c0575080633644e5151461079d5780633aaf1da0146101a05780638da5cb5b1461015b5763ad3b1b471461005857600080fd5b34610158576040366003190112610158576001600160a01b0360043581811690819003610153577f000000000000000000000000000000000000000000000000000000000000000091821633036101215760405163a9059cbb60e01b81526001600160a01b0392909216600483015260248035908301526020908290604490829086905af18015610116576100eb575080f35b61010b9060203d811161010f575b6101038183610849565b810190610960565b5080f35b503d6100f9565b6040513d84823e3d90fd5b60405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b6044820152606490fd5b600080fd5b80fd5b50346101585780600319360112610158576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5034610158576102c03660031901126101585761012435906001600160a01b03821682036101585761014435916001600160a01b03831683036106e35761016435926001600160a01b03841684036107995761018435936001600160a01b03851685036107955761022435946001600160a01b038616860361079157610244359063ffffffff92838316830361078d576102643590848216820361078957610284359385851685036106e75767ffffffffffffffff6102a435116106e7573660236102a4350112156106e75767ffffffffffffffff6102a43560040135116106e7573660246102a435600401356102a4350101116106e7576040516102b660046102a4350135601f01601f191660200182610849565b6102a435600481013580835290602401602083013760206102a43560040135820181018b9052815191810191909120604080517f9e083da3706b9934d8045dc0c29468984b5edc70777cc6bed8696637995f5ed09381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015284811660e08401528681166101008401526101a4356101208401526101c4356101408401526101e435610160840152610204356101808401528c166101a08301528783166101c08301528488166101e0830152868816610200830152610220808301919091528152610240810180821167ffffffffffffffff90911117610775576102408101604052602081519101206103d961086b565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff6080830111176107755761043981608061044293016040526020815191012060a435906084359060ff6064351690610978565b90929192610a08565b6001600160a01b0389811691160361073f576101e4356101a435016101a4351161072b576001600160a01b0382163b156106e757604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101e4356101a4350160448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b0388165af1801561070a57610715575b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526101a4356024820152999a5097988a9890602081806044810103818d6001600160a01b0389165af1801561070a576106eb575b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b156106e757604051633dc9c91960e11b81526001600160a01b038b8116600480840191909152998116602480840191909152948116604483015295861660648201526101a4803560848301526101c43560a48301526102043560c48301529190951660e4860152908616610104850152918516610124840152929093166101448201526101806101648201526102a435938401356101848201819052909390929101908301376101a46102a43560040135828101820184905283918391601f19601f9091011682018290030181836001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af18015610116576106cf575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6106d890610803565b6106e3578138610698565b5080fd5b8880fd5b6107039060203d60201161010f576101038183610849565b5038610567565b6040513d8c823e3d90fd5b9798909961072290610803565b979689906104f8565b634e487b7160e01b89526011600452602489fd5b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b503461015857806003193601126101585760206107b861086b565b604051908152f35b9050346106e357816003193601126106e3577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b67ffffffffffffffff811161081757604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761081757604052565b90601f8019910116810190811067ffffffffffffffff82111761081757604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161089a8161082d565b601781520152603160f81b60206040516108b38161082d565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176108175760405251902090565b90816020910312610153575180151581036101535790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109fc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109f05780516001600160a01b038116156109e757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a775780610a1a575050565b60018103610a345760405163f645eedf60e01b8152600490fd5b60028103610a555760405163fce698f760e01b815260048101839052602490fd5b600314610a5f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220bdffc6f212a252bef242a98237ea7ebb8f0cc9fd02ae76d2e738ff81b617a83064736f6c63430008140033", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908163292c1d92146107c0575080633644e5151461079d5780633aaf1da0146101a05780638da5cb5b1461015b5763ad3b1b471461005857600080fd5b34610158576040366003190112610158576001600160a01b0360043581811690819003610153577f000000000000000000000000000000000000000000000000000000000000000091821633036101215760405163a9059cbb60e01b81526001600160a01b0392909216600483015260248035908301526020908290604490829086905af18015610116576100eb575080f35b61010b9060203d811161010f575b6101038183610849565b810190610960565b5080f35b503d6100f9565b6040513d84823e3d90fd5b60405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b6044820152606490fd5b600080fd5b80fd5b50346101585780600319360112610158576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5034610158576102c03660031901126101585761012435906001600160a01b03821682036101585761014435916001600160a01b03831683036106e35761016435926001600160a01b03841684036107995761018435936001600160a01b03851685036107955761022435946001600160a01b038616860361079157610244359063ffffffff92838316830361078d576102643590848216820361078957610284359385851685036106e75767ffffffffffffffff6102a435116106e7573660236102a4350112156106e75767ffffffffffffffff6102a43560040135116106e7573660246102a435600401356102a4350101116106e7576040516102b660046102a4350135601f01601f191660200182610849565b6102a435600481013580835290602401602083013760206102a43560040135820181018b9052815191810191909120604080517f9e083da3706b9934d8045dc0c29468984b5edc70777cc6bed8696637995f5ed09381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015284811660e08401528681166101008401526101a4356101208401526101c4356101408401526101e435610160840152610204356101808401528c166101a08301528783166101c08301528488166101e0830152868816610200830152610220808301919091528152610240810180821167ffffffffffffffff90911117610775576102408101604052602081519101206103d961086b565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff6080830111176107755761043981608061044293016040526020815191012060a435906084359060ff6064351690610978565b90929192610a08565b6001600160a01b0389811691160361073f576101e4356101a435016101a4351161072b576001600160a01b0382163b156106e757604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101e4356101a4350160448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b0388165af1801561070a57610715575b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526101a4356024820152999a5097988a9890602081806044810103818d6001600160a01b0389165af1801561070a576106eb575b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b156106e757604051633dc9c91960e11b81526001600160a01b038b8116600480840191909152998116602480840191909152948116604483015295861660648201526101a4803560848301526101c43560a48301526102043560c48301529190951660e4860152908616610104850152918516610124840152929093166101448201526101806101648201526102a435938401356101848201819052909390929101908301376101a46102a43560040135828101820184905283918391601f19601f9091011682018290030181836001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af18015610116576106cf575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6106d890610803565b6106e3578138610698565b5080fd5b8880fd5b6107039060203d60201161010f576101038183610849565b5038610567565b6040513d8c823e3d90fd5b9798909961072290610803565b979689906104f8565b634e487b7160e01b89526011600452602489fd5b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b503461015857806003193601126101585760206107b861086b565b604051908152f35b9050346106e357816003193601126106e3577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b67ffffffffffffffff811161081757604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761081757604052565b90601f8019910116810190811067ffffffffffffffff82111761081757604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161089a8161082d565b601781520152603160f81b60206040516108b38161082d565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176108175760405251902090565b90816020910312610153575180151581036101535790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109fc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109f05780516001600160a01b038116156109e757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a775780610a1a575050565b60018103610a345760405163f645eedf60e01b8152600490fd5b60028103610a555760405163fce698f760e01b815260048101839052602490fd5b600314610a5f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220bdffc6f212a252bef242a98237ea7ebb8f0cc9fd02ae76d2e738ff81b617a83064736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } @@ -205,18 +259,18 @@ export interface AcrossWithAuthorization$Type { declare module "@nomicfoundation/hardhat-viem/types" { export function deployContract( contractName: "AcrossWithAuthorization", - constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>], + constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>, _owner: AbiParameterToPrimitiveType<{"name":"_owner","type":"address"}>], config?: DeployContractConfig ): Promise>; export function deployContract( contractName: "contracts/AcrossWithAuthorization.sol:AcrossWithAuthorization", - constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>], + constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>, _owner: AbiParameterToPrimitiveType<{"name":"_owner","type":"address"}>], config?: DeployContractConfig ): Promise>; export function sendDeploymentTransaction( contractName: "AcrossWithAuthorization", - constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>], + constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>, _owner: AbiParameterToPrimitiveType<{"name":"_owner","type":"address"}>], config?: SendDeploymentTransactionConfig ): Promise<{ contract: GetContractReturnType; @@ -224,7 +278,7 @@ declare module "@nomicfoundation/hardhat-viem/types" { }>; export function sendDeploymentTransaction( contractName: "contracts/AcrossWithAuthorization.sol:AcrossWithAuthorization", - constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>], + constructorArgs: [_across: AbiParameterToPrimitiveType<{"name":"_across","type":"address"}>, _owner: AbiParameterToPrimitiveType<{"name":"_owner","type":"address"}>], config?: SendDeploymentTransactionConfig ): Promise<{ contract: GetContractReturnType; diff --git a/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.dbg.json b/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.dbg.json deleted file mode 100644 index b0b0902..0000000 --- a/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/d740fc711c311bb6fd706e5caac2f35d.json" -} diff --git a/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.json b/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.json index b08a8cf..2582dd4 100644 --- a/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.json +++ b/eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.json @@ -9,6 +9,11 @@ "internalType": "address", "name": "_across", "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" } ], "stateMutability": "nonpayable", @@ -73,6 +78,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "across", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -150,6 +168,11 @@ "name": "outputAmount", "type": "uint256" }, + { + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + }, { "internalType": "uint256", "name": "destinationChainId", @@ -185,10 +208,41 @@ "outputs": [], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" } ], - "bytecode": "0x60803461007457601f61091338819003918201601f19168301916001600160401b038311848410176100795780849260209460405283398101031261007457516001600160a01b0381169081900361007457600080546001600160a01b03191691909117905560405161088390816100908239f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c80633644e515146105b85763eb2320b11461003357600080fd5b346105b5576102a03660031901126105b55761012435906001600160a01b03821682036105b55761014435916001600160a01b03831683036104e75761016435926001600160a01b03841684036105b15761018435936001600160a01b03851685036105ad57610204356001600160a01b03811681036105a957610224359163ffffffff80841684036105a557610244359781891689036105a1576102643590828216820361052a5767ffffffffffffffff610284351161052a573660236102843501121561052a5767ffffffffffffffff61028435600401351161052a5736602461028435600401356102843501011161052a576040516101466004610284350135601f01601f191660200182610621565b61028435600481013580835290602401602083013760206102843560040135820181018b9052815191810191909120604080517fb1808774e6a3862b691460baf364a9bb51d8654fecf525cc3f1c4eddb9419f689381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015286811660e08401528381166101008401526101a4356101208401526101c4356101408401526101e43561016084015287166101808301528488166101a08301528b85166101c08301528385166101e0830152610200808301919091528152610220810180821167ffffffffffffffff9091111761058d5761022081016040526020815191012061025f610643565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff60808301111761058d576102bf8160806102c893016040526020815191012060a435906084359060ff6064351690610738565b909291926107c8565b6001600160a01b03898116911603610557576001600160a01b0384163b1561052a57604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101a43560448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b038a165af1801561053657610541575b895460405163095ea7b360e01b81526001600160a01b0391821660048201526101a43560248201529a9b5098998b99602090829060449082908e908b165af18015610536576104fa575b5088546001600160a01b031694853b156104f657604051633dc9c91960e11b81526001600160a01b038c81166004808401919091529a8116602480840191909152928116604483015293841660648201526101a4803560848301526101c43560a48301526101e43560c48301529790931660e48401529684166101048301528316610124820152911661014482015261018061016482015261028435948501356101848201819052909486948694910190840137826101a461028435600401358401015281836101a482601f19601f6102843560040135011681010301925af180156104eb576104d3575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6104dc906105db565b6104e757813861049c565b5080fd5b6040513d84823e3d90fd5b8980fd5b6020813d60201161052e575b8161051360209383610621565b810103126104f657518015150361052a57386103b1565b8880fd5b3d9150610506565b6040513d8c823e3d90fd5b9798909961054e906105db565b97968990610367565b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b80fd5b50346105b557806003193601126105b55760206105d3610643565b604051908152f35b67ffffffffffffffff81116105ef57604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176105ef57604052565b90601f8019910116810190811067ffffffffffffffff8211176105ef57604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161067281610605565b601781520152603160f81b602060405161068b81610605565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176105ef5760405251902090565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116107bc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156107b05780516001600160a01b038116156107a757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b600481101561083757806107da575050565b600181036107f45760405163f645eedf60e01b8152600490fd5b600281036108155760405163fce698f760e01b815260048101839052602490fd5b60031461081f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea26469706673582212203a660b9f9600a5247c21885db9a8e37e4363095155e3b5b228a1762bb4f3374164736f6c63430008140033", - "deployedBytecode": "0x6080604052600436101561001257600080fd5b6000803560e01c80633644e515146105b85763eb2320b11461003357600080fd5b346105b5576102a03660031901126105b55761012435906001600160a01b03821682036105b55761014435916001600160a01b03831683036104e75761016435926001600160a01b03841684036105b15761018435936001600160a01b03851685036105ad57610204356001600160a01b03811681036105a957610224359163ffffffff80841684036105a557610244359781891689036105a1576102643590828216820361052a5767ffffffffffffffff610284351161052a573660236102843501121561052a5767ffffffffffffffff61028435600401351161052a5736602461028435600401356102843501011161052a576040516101466004610284350135601f01601f191660200182610621565b61028435600481013580835290602401602083013760206102843560040135820181018b9052815191810191909120604080517fb1808774e6a3862b691460baf364a9bb51d8654fecf525cc3f1c4eddb9419f689381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015286811660e08401528381166101008401526101a4356101208401526101c4356101408401526101e43561016084015287166101808301528488166101a08301528b85166101c08301528385166101e0830152610200808301919091528152610220810180821167ffffffffffffffff9091111761058d5761022081016040526020815191012061025f610643565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff60808301111761058d576102bf8160806102c893016040526020815191012060a435906084359060ff6064351690610738565b909291926107c8565b6001600160a01b03898116911603610557576001600160a01b0384163b1561052a57604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101a43560448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b038a165af1801561053657610541575b895460405163095ea7b360e01b81526001600160a01b0391821660048201526101a43560248201529a9b5098998b99602090829060449082908e908b165af18015610536576104fa575b5088546001600160a01b031694853b156104f657604051633dc9c91960e11b81526001600160a01b038c81166004808401919091529a8116602480840191909152928116604483015293841660648201526101a4803560848301526101c43560a48301526101e43560c48301529790931660e48401529684166101048301528316610124820152911661014482015261018061016482015261028435948501356101848201819052909486948694910190840137826101a461028435600401358401015281836101a482601f19601f6102843560040135011681010301925af180156104eb576104d3575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6104dc906105db565b6104e757813861049c565b5080fd5b6040513d84823e3d90fd5b8980fd5b6020813d60201161052e575b8161051360209383610621565b810103126104f657518015150361052a57386103b1565b8880fd5b3d9150610506565b6040513d8c823e3d90fd5b9798909961054e906105db565b97968990610367565b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b80fd5b50346105b557806003193601126105b55760206105d3610643565b604051908152f35b67ffffffffffffffff81116105ef57604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176105ef57604052565b90601f8019910116810190811067ffffffffffffffff8211176105ef57604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161067281610605565b601781520152603160f81b602060405161068b81610605565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176105ef5760405251902090565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116107bc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156107b05780516001600160a01b038116156107a757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b600481101561083757806107da575050565b600181036107f45760405163f645eedf60e01b8152600490fd5b600281036108155760405163fce698f760e01b815260048101839052602490fd5b60031461081f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea26469706673582212203a660b9f9600a5247c21885db9a8e37e4363095155e3b5b228a1762bb4f3374164736f6c63430008140033", + "bytecode": "0x60c03461009557601f610b8838819003918201601f19168301916001600160401b0383118484101761009a57808492604094855283398101031261009557610052602061004b836100b0565b92016100b0565b9060a052608052604051610ac390816100c5823960805181818160810152610171015260a05181818161050f0152818161056a0152818161066b01526107d40152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100955756fe608080604052600436101561001357600080fd5b600090813560e01c908163292c1d92146107c0575080633644e5151461079d5780633aaf1da0146101a05780638da5cb5b1461015b5763ad3b1b471461005857600080fd5b34610158576040366003190112610158576001600160a01b0360043581811690819003610153577f000000000000000000000000000000000000000000000000000000000000000091821633036101215760405163a9059cbb60e01b81526001600160a01b0392909216600483015260248035908301526020908290604490829086905af18015610116576100eb575080f35b61010b9060203d811161010f575b6101038183610849565b810190610960565b5080f35b503d6100f9565b6040513d84823e3d90fd5b60405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b6044820152606490fd5b600080fd5b80fd5b50346101585780600319360112610158576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5034610158576102c03660031901126101585761012435906001600160a01b03821682036101585761014435916001600160a01b03831683036106e35761016435926001600160a01b03841684036107995761018435936001600160a01b03851685036107955761022435946001600160a01b038616860361079157610244359063ffffffff92838316830361078d576102643590848216820361078957610284359385851685036106e75767ffffffffffffffff6102a435116106e7573660236102a4350112156106e75767ffffffffffffffff6102a43560040135116106e7573660246102a435600401356102a4350101116106e7576040516102b660046102a4350135601f01601f191660200182610849565b6102a435600481013580835290602401602083013760206102a43560040135820181018b9052815191810191909120604080517f9e083da3706b9934d8045dc0c29468984b5edc70777cc6bed8696637995f5ed09381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015284811660e08401528681166101008401526101a4356101208401526101c4356101408401526101e435610160840152610204356101808401528c166101a08301528783166101c08301528488166101e0830152868816610200830152610220808301919091528152610240810180821167ffffffffffffffff90911117610775576102408101604052602081519101206103d961086b565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff6080830111176107755761043981608061044293016040526020815191012060a435906084359060ff6064351690610978565b90929192610a08565b6001600160a01b0389811691160361073f576101e4356101a435016101a4351161072b576001600160a01b0382163b156106e757604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101e4356101a4350160448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b0388165af1801561070a57610715575b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526101a4356024820152999a5097988a9890602081806044810103818d6001600160a01b0389165af1801561070a576106eb575b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b156106e757604051633dc9c91960e11b81526001600160a01b038b8116600480840191909152998116602480840191909152948116604483015295861660648201526101a4803560848301526101c43560a48301526102043560c48301529190951660e4860152908616610104850152918516610124840152929093166101448201526101806101648201526102a435938401356101848201819052909390929101908301376101a46102a43560040135828101820184905283918391601f19601f9091011682018290030181836001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af18015610116576106cf575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6106d890610803565b6106e3578138610698565b5080fd5b8880fd5b6107039060203d60201161010f576101038183610849565b5038610567565b6040513d8c823e3d90fd5b9798909961072290610803565b979689906104f8565b634e487b7160e01b89526011600452602489fd5b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b503461015857806003193601126101585760206107b861086b565b604051908152f35b9050346106e357816003193601126106e3577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b67ffffffffffffffff811161081757604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761081757604052565b90601f8019910116810190811067ffffffffffffffff82111761081757604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161089a8161082d565b601781520152603160f81b60206040516108b38161082d565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176108175760405251902090565b90816020910312610153575180151581036101535790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109fc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109f05780516001600160a01b038116156109e757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a775780610a1a575050565b60018103610a345760405163f645eedf60e01b8152600490fd5b60028103610a555760405163fce698f760e01b815260048101839052602490fd5b600314610a5f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220bdffc6f212a252bef242a98237ea7ebb8f0cc9fd02ae76d2e738ff81b617a83064736f6c63430008140033", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908163292c1d92146107c0575080633644e5151461079d5780633aaf1da0146101a05780638da5cb5b1461015b5763ad3b1b471461005857600080fd5b34610158576040366003190112610158576001600160a01b0360043581811690819003610153577f000000000000000000000000000000000000000000000000000000000000000091821633036101215760405163a9059cbb60e01b81526001600160a01b0392909216600483015260248035908301526020908290604490829086905af18015610116576100eb575080f35b61010b9060203d811161010f575b6101038183610849565b810190610960565b5080f35b503d6100f9565b6040513d84823e3d90fd5b60405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b6044820152606490fd5b600080fd5b80fd5b50346101585780600319360112610158576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b5034610158576102c03660031901126101585761012435906001600160a01b03821682036101585761014435916001600160a01b03831683036106e35761016435926001600160a01b03841684036107995761018435936001600160a01b03851685036107955761022435946001600160a01b038616860361079157610244359063ffffffff92838316830361078d576102643590848216820361078957610284359385851685036106e75767ffffffffffffffff6102a435116106e7573660236102a4350112156106e75767ffffffffffffffff6102a43560040135116106e7573660246102a435600401356102a4350101116106e7576040516102b660046102a4350135601f01601f191660200182610849565b6102a435600481013580835290602401602083013760206102a43560040135820181018b9052815191810191909120604080517f9e083da3706b9934d8045dc0c29468984b5edc70777cc6bed8696637995f5ed09381019390935260c4359083015260e43560608301526101043560808301526001600160a01b038a811660a084015289811660c084015284811660e08401528681166101008401526101a4356101208401526101c4356101408401526101e435610160840152610204356101808401528c166101a08301528783166101c08301528488166101e0830152868816610200830152610220808301919091528152610240810180821167ffffffffffffffff90911117610775576102408101604052602081519101206103d961086b565b906040519161190160f01b6020840152602283015260428201526042815280608081011067ffffffffffffffff6080830111176107755761043981608061044293016040526020815191012060a435906084359060ff6064351690610978565b90929192610a08565b6001600160a01b0389811691160361073f576101e4356101a435016101a4351161072b576001600160a01b0382163b156106e757604051996377aadf6360e11b8b5260018060a01b03891660048c01523060248c01526101e4356101a4350160448c015260c43560648c015260e43560848c01526101043560a48c015260ff6004351660c48c015260243560e48c01526044356101048c0152898b610124818360018060a01b0388165af1801561070a57610715575b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660048201526101a4356024820152999a5097988a9890602081806044810103818d6001600160a01b0389165af1801561070a576106eb575b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163b156106e757604051633dc9c91960e11b81526001600160a01b038b8116600480840191909152998116602480840191909152948116604483015295861660648201526101a4803560848301526101c43560a48301526102043560c48301529190951660e4860152908616610104850152918516610124840152929093166101448201526101806101648201526102a435938401356101848201819052909390929101908301376101a46102a43560040135828101820184905283918391601f19601f9091011682018290030181836001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af18015610116576106cf575b505061010435906001600160a01b03167f07c395f9699f5c4d4e90df65ab0ea5d135089f597219b61c81445b8785c75b588380a380f35b6106d890610803565b6106e3578138610698565b5080fd5b8880fd5b6107039060203d60201161010f576101038183610849565b5038610567565b6040513d8c823e3d90fd5b9798909961072290610803565b979689906104f8565b634e487b7160e01b89526011600452602489fd5b60405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b634e487b7160e01b8a52604160045260248afd5b8780fd5b8680fd5b8480fd5b8380fd5b8280fd5b503461015857806003193601126101585760206107b861086b565b604051908152f35b9050346106e357816003193601126106e3577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b67ffffffffffffffff811161081757604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761081757604052565b90601f8019910116810190811067ffffffffffffffff82111761081757604052565b7f4163726f737357697468417574686f72697a6174696f6e000000000000000000602060405161089a8161082d565b601781520152603160f81b60206040516108b38161082d565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f1ebcbe7a0999f3d17724384372eb5ab92c9d2107035426aa52c0fa5afbf32fce60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815260c0810181811067ffffffffffffffff8211176108175760405251902090565b90816020910312610153575180151581036101535790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109fc57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109f05780516001600160a01b038116156109e757918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a775780610a1a575050565b60018103610a345760405163f645eedf60e01b8152600490fd5b60028103610a555760405163fce698f760e01b815260048101839052602490fd5b600314610a5f5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220bdffc6f212a252bef242a98237ea7ebb8f0cc9fd02ae76d2e738ff81b617a83064736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/eth/artifacts/contracts/AcrossWithAuthorization.sol/IAcross.dbg.json b/eth/artifacts/contracts/AcrossWithAuthorization.sol/IAcross.dbg.json deleted file mode 100644 index b0b0902..0000000 --- a/eth/artifacts/contracts/AcrossWithAuthorization.sol/IAcross.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../build-info/d740fc711c311bb6fd706e5caac2f35d.json" -} diff --git a/eth/artifacts/contracts/BurnVerifierV2.sol/BurnVerifierV2.d.ts b/eth/artifacts/contracts/BurnVerifierV2.sol/BurnVerifierV2.d.ts new file mode 100644 index 0000000..74b3d81 --- /dev/null +++ b/eth/artifacts/contracts/BurnVerifierV2.sol/BurnVerifierV2.d.ts @@ -0,0 +1,108 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { AbiParameterToPrimitiveType, GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface BurnVerifierV2$Type { + "_format": "hh-sol-artifact-1", + "contractName": "BurnVerifierV2", + "sourceName": "contracts/BurnVerifierV2.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_verifier", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "VerificationFailed", + "type": "error" + }, + { + "inputs": [], + "name": "plonkVerifier", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "internalType": "bytes32[6]", + "name": "instances", + "type": "bytes32[6]" + } + ], + "name": "verify", + "outputs": [], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a03461007057601f61037a38819003918201601f19168301916001600160401b038311848410176100755780849260209460405283398101031261007057516001600160a01b0381168103610070576080526040516102ee908161008c823960805181818160b501526101f20152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c908163e261a9cb1461003a575063e4886e501461003557600080fd5b61009f565b3461009c5760e036600319011261009c5760043567ffffffffffffffff8082116100985736602383011215610098578160040135908111610098573660248284010111610098573660e41161009857602461009592016101b7565b80f35b8280fd5b80fd5b346100e45760003660031901126100e4576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b600080fd5b634e487b7160e01b600052601160045260246000fd5b60068110156101115760051b60240190565b634e487b7160e01b600052603260045260246000fd5b60c001908160c01161013557565b6100e9565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff811161016c57601f01601f191660200190565b61013a565b9061017b82610150565b60405190601f1990601f018116820167ffffffffffffffff81118382101761016c576040528382526101ad8294610150565b0190602036910137565b9060005b6006811061022f5750600061021792826101dd6101d88495610127565b610171565b90602082019260c06024853760e083013751907f00000000000000000000000000000000000000000000000000000000000000005afa1590565b61021d57565b60405163439cc0cd60e01b8152600490fd5b61024161023b826100ff565b35610252565b6000198114610135576001016101bb565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001111561027b57565b60405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a5908199a595b1908195b195b595b9d605a1b6044820152606490fdfea2646970667358221220a0bf01a2790404f890b4e849ccbb1a23e6ac34f7b8d52be8a052ae571d9e599764736f6c63430008140033", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b6000803560e01c908163e261a9cb1461003a575063e4886e501461003557600080fd5b61009f565b3461009c5760e036600319011261009c5760043567ffffffffffffffff8082116100985736602383011215610098578160040135908111610098573660248284010111610098573660e41161009857602461009592016101b7565b80f35b8280fd5b80fd5b346100e45760003660031901126100e4576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b600080fd5b634e487b7160e01b600052601160045260246000fd5b60068110156101115760051b60240190565b634e487b7160e01b600052603260045260246000fd5b60c001908160c01161013557565b6100e9565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff811161016c57601f01601f191660200190565b61013a565b9061017b82610150565b60405190601f1990601f018116820167ffffffffffffffff81118382101761016c576040528382526101ad8294610150565b0190602036910137565b9060005b6006811061022f5750600061021792826101dd6101d88495610127565b610171565b90602082019260c06024853760e083013751907f00000000000000000000000000000000000000000000000000000000000000005afa1590565b61021d57565b60405163439cc0cd60e01b8152600490fd5b61024161023b826100ff565b35610252565b6000198114610135576001016101bb565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001111561027b57565b60405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a5908199a595b1908195b195b595b9d605a1b6044820152606490fdfea2646970667358221220a0bf01a2790404f890b4e849ccbb1a23e6ac34f7b8d52be8a052ae571d9e599764736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "BurnVerifierV2", + constructorArgs: [_verifier: AbiParameterToPrimitiveType<{"name":"_verifier","type":"address"}>], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/BurnVerifierV2.sol:BurnVerifierV2", + constructorArgs: [_verifier: AbiParameterToPrimitiveType<{"name":"_verifier","type":"address"}>], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "BurnVerifierV2", + constructorArgs: [_verifier: AbiParameterToPrimitiveType<{"name":"_verifier","type":"address"}>], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/BurnVerifierV2.sol:BurnVerifierV2", + constructorArgs: [_verifier: AbiParameterToPrimitiveType<{"name":"_verifier","type":"address"}>], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "BurnVerifierV2", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/BurnVerifierV2.sol:BurnVerifierV2", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/BurnVerifierV2.sol/BurnVerifierV2.json b/eth/artifacts/contracts/BurnVerifierV2.sol/BurnVerifierV2.json new file mode 100644 index 0000000..dc5d9d8 --- /dev/null +++ b/eth/artifacts/contracts/BurnVerifierV2.sol/BurnVerifierV2.json @@ -0,0 +1,58 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BurnVerifierV2", + "sourceName": "contracts/BurnVerifierV2.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_verifier", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "VerificationFailed", + "type": "error" + }, + { + "inputs": [], + "name": "plonkVerifier", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "internalType": "bytes32[6]", + "name": "instances", + "type": "bytes32[6]" + } + ], + "name": "verify", + "outputs": [], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a03461007057601f61037a38819003918201601f19168301916001600160401b038311848410176100755780849260209460405283398101031261007057516001600160a01b0381168103610070576080526040516102ee908161008c823960805181818160b501526101f20152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604052600436101561001257600080fd5b6000803560e01c908163e261a9cb1461003a575063e4886e501461003557600080fd5b61009f565b3461009c5760e036600319011261009c5760043567ffffffffffffffff8082116100985736602383011215610098578160040135908111610098573660248284010111610098573660e41161009857602461009592016101b7565b80f35b8280fd5b80fd5b346100e45760003660031901126100e4576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b600080fd5b634e487b7160e01b600052601160045260246000fd5b60068110156101115760051b60240190565b634e487b7160e01b600052603260045260246000fd5b60c001908160c01161013557565b6100e9565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff811161016c57601f01601f191660200190565b61013a565b9061017b82610150565b60405190601f1990601f018116820167ffffffffffffffff81118382101761016c576040528382526101ad8294610150565b0190602036910137565b9060005b6006811061022f5750600061021792826101dd6101d88495610127565b610171565b90602082019260c06024853760e083013751907f00000000000000000000000000000000000000000000000000000000000000005afa1590565b61021d57565b60405163439cc0cd60e01b8152600490fd5b61024161023b826100ff565b35610252565b6000198114610135576001016101bb565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001111561027b57565b60405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a5908199a595b1908195b195b595b9d605a1b6044820152606490fdfea2646970667358221220a0bf01a2790404f890b4e849ccbb1a23e6ac34f7b8d52be8a052ae571d9e599764736f6c63430008140033", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b6000803560e01c908163e261a9cb1461003a575063e4886e501461003557600080fd5b61009f565b3461009c5760e036600319011261009c5760043567ffffffffffffffff8082116100985736602383011215610098578160040135908111610098573660248284010111610098573660e41161009857602461009592016101b7565b80f35b8280fd5b80fd5b346100e45760003660031901126100e4576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b600080fd5b634e487b7160e01b600052601160045260246000fd5b60068110156101115760051b60240190565b634e487b7160e01b600052603260045260246000fd5b60c001908160c01161013557565b6100e9565b634e487b7160e01b600052604160045260246000fd5b67ffffffffffffffff811161016c57601f01601f191660200190565b61013a565b9061017b82610150565b60405190601f1990601f018116820167ffffffffffffffff81118382101761016c576040528382526101ad8294610150565b0190602036910137565b9060005b6006811061022f5750600061021792826101dd6101d88495610127565b610171565b90602082019260c06024853760e083013751907f00000000000000000000000000000000000000000000000000000000000000005afa1590565b61021d57565b60405163439cc0cd60e01b8152600490fd5b61024161023b826100ff565b35610252565b6000198114610135576001016101bb565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001111561027b57565b60405162461bcd60e51b8152602060048201526015602482015274125b9d985b1a5908199a595b1908195b195b595b9d605a1b6044820152606490fdfea2646970667358221220a0bf01a2790404f890b4e849ccbb1a23e6ac34f7b8d52be8a052ae571d9e599764736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/BurnVerifierV2.sol/artifacts.d.ts b/eth/artifacts/contracts/BurnVerifierV2.sol/artifacts.d.ts new file mode 100644 index 0000000..f6c2735 --- /dev/null +++ b/eth/artifacts/contracts/BurnVerifierV2.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { BurnVerifierV2$Type } from "./BurnVerifierV2"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["BurnVerifierV2"]: BurnVerifierV2$Type; + ["contracts/BurnVerifierV2.sol:BurnVerifierV2"]: BurnVerifierV2$Type; + } +} diff --git a/eth/artifacts/contracts/Eip7702SimpleAccount.sol/Eip7702SimpleAccount.d.ts b/eth/artifacts/contracts/Eip7702SimpleAccount.sol/Eip7702SimpleAccount.d.ts new file mode 100644 index 0000000..f9a8578 --- /dev/null +++ b/eth/artifacts/contracts/Eip7702SimpleAccount.sol/Eip7702SimpleAccount.d.ts @@ -0,0 +1,314 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface Eip7702SimpleAccount$Type { + "_format": "hh-sol-artifact-1", + "contractName": "Eip7702SimpleAccount", + "sourceName": "contracts/Eip7702SimpleAccount.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "NonceUsed", + "type": "event" + }, + { + "inputs": [], + "name": "domainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Eip7702SimpleAccount.Call[]", + "name": "calls", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "executeMeta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Eip7702SimpleAccount.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "hashCalls", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + } + ], + "name": "isNonceUsed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "usedNonces", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6080806040523461001657610b6b908161001c8239f35b600080fdfe6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826301ffc9a714610541575081631626ba7e1461050157816320c13b0b146104935781635d00bb12146100f15781635df4c239146101215781636717e41c146100f15781637b6d6a18146100b0575063f698da251461008a5780610012565b346100ac57816003193601126100ac576020906100a561064c565b9051908152f35b5080fd5b8284346100ee5760203660031901126100ee5782359067ffffffffffffffff82116100ee57506100e86020936100a5923691016105c7565b90610757565b80fd5b90503461011d57602036600319011261011d578160209360ff9235815280855220541690519015158152f35b8280fd5b90503461011d5760a036600319011261011d5767ffffffffffffffff90803582811161048f5761015490369083016105c7565b8560249492949182356044948535906064359060843581811161048b5761017e9036908b01610594565b93909285885260ff8d602099808b5220541661045457814210610412578042116103d857908c916101af888e610757565b918351928a8401947f19667787bf8e4e28ff931080c268a52496d168906174261eda235b32144164f38652840152876060840152608083015260a082015260a081526101fa816105f8565b51902061020561064c565b918c51918883019361190160f01b855260228401526042830152604282526080820190828210908211176103c6578c5251902061025a926102519261024b9136916108f8565b9061092f565b909291926109fb565b306001600160a01b039091160361039557808952888352878920805460ff191660011790557f1be5cb2f29a4876ca6fdf1177257bc6f2671bc7e036db0815016a6b766ecd1158980a2875b8181106102b0578880f35b88806102c56102c084868c61071f565b610895565b8a8a6102ec6102e387898b6102db83838861071f565b01359461071f565b838101906108a9565b8093519384928337810185815203925af13d1561038d573d9061030e826108dc565b9161031b8b51938461062a565b82523d8b8684013e5b156103385750610333906106fa565b6102a5565b8587868c8780958e5196879562461bcd60e51b875286015280518094860152825b84811061037757505050828201840152601f01601f19168101030190fd5b8181018301518882018801528795508201610359565b606090610324565b875162461bcd60e51b8152808701849052600d818601526c626164207369676e617475726560981b81870152606490fd5b634e487b7160e01b8e5260418b52888efd5b508b5162461bcd60e51b8152808b018890526015818a015274185d5d1a1bdc9a5e985d1a5bdb88195e1c1a5c9959605a1b818b0152606490fd5b508b5162461bcd60e51b8152808b01889052601b818a01527f617574686f72697a6174696f6e206e6f74207965742076616c69640000000000818b0152606490fd5b508b5162461bcd60e51b8152808b018890526012818a0152711b9bdb98d948185b1c9958591e481d5cd95960721b818b0152606490fd5b8680fd5b8480fd5b8284346100ee57816003193601126100ee5767ffffffffffffffff92803584811161011d576104c59036908301610594565b9490926024359182116100ee5750916104e7602095926104ef94369101610594565b929091610ad1565b90516001600160e01b03199091168152f35b8284346100ee57816003193601126100ee576024359067ffffffffffffffff82116100ee575060209261053a6104ef9236908301610594565b9135610a80565b84913461011d57602036600319011261011d573563ffffffff60e01b811680910361011d57602092506301ffc9a760e01b8114908115610583575b5015158152f35b630b135d3f60e11b1490508361057c565b9181601f840112156105c25782359167ffffffffffffffff83116105c257602083818601950101116105c257565b600080fd5b9181601f840112156105c25782359167ffffffffffffffff83116105c2576020808501948460051b0101116105c257565b60c0810190811067ffffffffffffffff82111761061457604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761061457604052565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f0617916c66cf2f8bef8f2360f69f42e7fb36391164667ba437bda5f2f137968b60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526106dc816105f8565b51902090565b67ffffffffffffffff81116106145760051b60200190565b60001981146107095760010190565b634e487b7160e01b600052601160045260246000fd5b91908110156107415760051b81013590605e19813603018212156105c2570190565b634e487b7160e01b600052603260045260246000fd5b610760826106e2565b91604061076f8151948561062a565b81845261077b826106e2565b60209385850193601f199392840136863760005b8181106107da5750505051838194820180965190949160005b8281106107c357505050506106dc920390810183528261062a565b8351875295810195879450928101926001016107a8565b6107e881838598979861071f565b6107f181610895565b90610808610801878301836108a9565b36916108f8565b89815191012089875192818401947f84fa2cf05cd88e992eae77e851af68a4ee278dcff6ef504e487a55b3baadfbe5865260018060a01b0316898501520135606083015260809081830152815260a0810181811067ffffffffffffffff8211176106145786525190209088518110156107415761088d91888260051b8b0101526106fa565b94939461078f565b356001600160a01b03811681036105c25790565b903590601e19813603018212156105c2570180359067ffffffffffffffff82116105c2576020019181360383136105c257565b67ffffffffffffffff811161061457601f01601f191660200190565b929192610904826108dc565b91610912604051938461062a565b8294818452818301116105c2578281602093846000960137010152565b81519190604183036109605761095992506020820151906060604084015193015160001a9061096b565b9192909190565b505060009160029190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109ef57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109e35780516001600160a01b038116156109da57918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a6a5780610a0d575050565b60018103610a275760405163f645eedf60e01b8152600490fd5b60028103610a485760405163fce698f760e01b815260048101839052602490fd5b600314610a525750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b9061024b90610a909336916108f8565b506004811015610a6a57159081610abe575b50610ab3576001600160e01b031990565b630b135d3f60e11b90565b6001600160a01b03163014905038610aa2565b91610ae5610af4949361024b9336916108f8565b602081519101209236916108f8565b506004811015610a6a57159081610b22575b50610b17576001600160e01b031990565b6320c13b0b60e01b90565b6001600160a01b03163014905038610b0656fea26469706673582212204bcc5204fe45a1d40760007c417d38e77e72eee07beae66a428170f45822cb2c64736f6c63430008140033", + "deployedBytecode": "0x6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826301ffc9a714610541575081631626ba7e1461050157816320c13b0b146104935781635d00bb12146100f15781635df4c239146101215781636717e41c146100f15781637b6d6a18146100b0575063f698da251461008a5780610012565b346100ac57816003193601126100ac576020906100a561064c565b9051908152f35b5080fd5b8284346100ee5760203660031901126100ee5782359067ffffffffffffffff82116100ee57506100e86020936100a5923691016105c7565b90610757565b80fd5b90503461011d57602036600319011261011d578160209360ff9235815280855220541690519015158152f35b8280fd5b90503461011d5760a036600319011261011d5767ffffffffffffffff90803582811161048f5761015490369083016105c7565b8560249492949182356044948535906064359060843581811161048b5761017e9036908b01610594565b93909285885260ff8d602099808b5220541661045457814210610412578042116103d857908c916101af888e610757565b918351928a8401947f19667787bf8e4e28ff931080c268a52496d168906174261eda235b32144164f38652840152876060840152608083015260a082015260a081526101fa816105f8565b51902061020561064c565b918c51918883019361190160f01b855260228401526042830152604282526080820190828210908211176103c6578c5251902061025a926102519261024b9136916108f8565b9061092f565b909291926109fb565b306001600160a01b039091160361039557808952888352878920805460ff191660011790557f1be5cb2f29a4876ca6fdf1177257bc6f2671bc7e036db0815016a6b766ecd1158980a2875b8181106102b0578880f35b88806102c56102c084868c61071f565b610895565b8a8a6102ec6102e387898b6102db83838861071f565b01359461071f565b838101906108a9565b8093519384928337810185815203925af13d1561038d573d9061030e826108dc565b9161031b8b51938461062a565b82523d8b8684013e5b156103385750610333906106fa565b6102a5565b8587868c8780958e5196879562461bcd60e51b875286015280518094860152825b84811061037757505050828201840152601f01601f19168101030190fd5b8181018301518882018801528795508201610359565b606090610324565b875162461bcd60e51b8152808701849052600d818601526c626164207369676e617475726560981b81870152606490fd5b634e487b7160e01b8e5260418b52888efd5b508b5162461bcd60e51b8152808b018890526015818a015274185d5d1a1bdc9a5e985d1a5bdb88195e1c1a5c9959605a1b818b0152606490fd5b508b5162461bcd60e51b8152808b01889052601b818a01527f617574686f72697a6174696f6e206e6f74207965742076616c69640000000000818b0152606490fd5b508b5162461bcd60e51b8152808b018890526012818a0152711b9bdb98d948185b1c9958591e481d5cd95960721b818b0152606490fd5b8680fd5b8480fd5b8284346100ee57816003193601126100ee5767ffffffffffffffff92803584811161011d576104c59036908301610594565b9490926024359182116100ee5750916104e7602095926104ef94369101610594565b929091610ad1565b90516001600160e01b03199091168152f35b8284346100ee57816003193601126100ee576024359067ffffffffffffffff82116100ee575060209261053a6104ef9236908301610594565b9135610a80565b84913461011d57602036600319011261011d573563ffffffff60e01b811680910361011d57602092506301ffc9a760e01b8114908115610583575b5015158152f35b630b135d3f60e11b1490508361057c565b9181601f840112156105c25782359167ffffffffffffffff83116105c257602083818601950101116105c257565b600080fd5b9181601f840112156105c25782359167ffffffffffffffff83116105c2576020808501948460051b0101116105c257565b60c0810190811067ffffffffffffffff82111761061457604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761061457604052565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f0617916c66cf2f8bef8f2360f69f42e7fb36391164667ba437bda5f2f137968b60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526106dc816105f8565b51902090565b67ffffffffffffffff81116106145760051b60200190565b60001981146107095760010190565b634e487b7160e01b600052601160045260246000fd5b91908110156107415760051b81013590605e19813603018212156105c2570190565b634e487b7160e01b600052603260045260246000fd5b610760826106e2565b91604061076f8151948561062a565b81845261077b826106e2565b60209385850193601f199392840136863760005b8181106107da5750505051838194820180965190949160005b8281106107c357505050506106dc920390810183528261062a565b8351875295810195879450928101926001016107a8565b6107e881838598979861071f565b6107f181610895565b90610808610801878301836108a9565b36916108f8565b89815191012089875192818401947f84fa2cf05cd88e992eae77e851af68a4ee278dcff6ef504e487a55b3baadfbe5865260018060a01b0316898501520135606083015260809081830152815260a0810181811067ffffffffffffffff8211176106145786525190209088518110156107415761088d91888260051b8b0101526106fa565b94939461078f565b356001600160a01b03811681036105c25790565b903590601e19813603018212156105c2570180359067ffffffffffffffff82116105c2576020019181360383136105c257565b67ffffffffffffffff811161061457601f01601f191660200190565b929192610904826108dc565b91610912604051938461062a565b8294818452818301116105c2578281602093846000960137010152565b81519190604183036109605761095992506020820151906060604084015193015160001a9061096b565b9192909190565b505060009160029190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109ef57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109e35780516001600160a01b038116156109da57918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a6a5780610a0d575050565b60018103610a275760405163f645eedf60e01b8152600490fd5b60028103610a485760405163fce698f760e01b815260048101839052602490fd5b600314610a525750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b9061024b90610a909336916108f8565b506004811015610a6a57159081610abe575b50610ab3576001600160e01b031990565b630b135d3f60e11b90565b6001600160a01b03163014905038610aa2565b91610ae5610af4949361024b9336916108f8565b602081519101209236916108f8565b506004811015610a6a57159081610b22575b50610b17576001600160e01b031990565b6320c13b0b60e01b90565b6001600160a01b03163014905038610b0656fea26469706673582212204bcc5204fe45a1d40760007c417d38e77e72eee07beae66a428170f45822cb2c64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "Eip7702SimpleAccount", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/Eip7702SimpleAccount.sol:Eip7702SimpleAccount", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "Eip7702SimpleAccount", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/Eip7702SimpleAccount.sol:Eip7702SimpleAccount", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "Eip7702SimpleAccount", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/Eip7702SimpleAccount.sol:Eip7702SimpleAccount", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/Eip7702SimpleAccount.sol/Eip7702SimpleAccount.json b/eth/artifacts/contracts/Eip7702SimpleAccount.sol/Eip7702SimpleAccount.json new file mode 100644 index 0000000..406345e --- /dev/null +++ b/eth/artifacts/contracts/Eip7702SimpleAccount.sol/Eip7702SimpleAccount.json @@ -0,0 +1,264 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "Eip7702SimpleAccount", + "sourceName": "contracts/Eip7702SimpleAccount.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + } + ], + "name": "NonceUsed", + "type": "event" + }, + { + "inputs": [], + "name": "domainSeparator", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Eip7702SimpleAccount.Call[]", + "name": "calls", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validUntil", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "executeMeta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Eip7702SimpleAccount.Call[]", + "name": "calls", + "type": "tuple[]" + } + ], + "name": "hashCalls", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_nonce", + "type": "uint256" + } + ], + "name": "isNonceUsed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "usedNonces", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "bytecode": "0x6080806040523461001657610b6b908161001c8239f35b600080fdfe6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826301ffc9a714610541575081631626ba7e1461050157816320c13b0b146104935781635d00bb12146100f15781635df4c239146101215781636717e41c146100f15781637b6d6a18146100b0575063f698da251461008a5780610012565b346100ac57816003193601126100ac576020906100a561064c565b9051908152f35b5080fd5b8284346100ee5760203660031901126100ee5782359067ffffffffffffffff82116100ee57506100e86020936100a5923691016105c7565b90610757565b80fd5b90503461011d57602036600319011261011d578160209360ff9235815280855220541690519015158152f35b8280fd5b90503461011d5760a036600319011261011d5767ffffffffffffffff90803582811161048f5761015490369083016105c7565b8560249492949182356044948535906064359060843581811161048b5761017e9036908b01610594565b93909285885260ff8d602099808b5220541661045457814210610412578042116103d857908c916101af888e610757565b918351928a8401947f19667787bf8e4e28ff931080c268a52496d168906174261eda235b32144164f38652840152876060840152608083015260a082015260a081526101fa816105f8565b51902061020561064c565b918c51918883019361190160f01b855260228401526042830152604282526080820190828210908211176103c6578c5251902061025a926102519261024b9136916108f8565b9061092f565b909291926109fb565b306001600160a01b039091160361039557808952888352878920805460ff191660011790557f1be5cb2f29a4876ca6fdf1177257bc6f2671bc7e036db0815016a6b766ecd1158980a2875b8181106102b0578880f35b88806102c56102c084868c61071f565b610895565b8a8a6102ec6102e387898b6102db83838861071f565b01359461071f565b838101906108a9565b8093519384928337810185815203925af13d1561038d573d9061030e826108dc565b9161031b8b51938461062a565b82523d8b8684013e5b156103385750610333906106fa565b6102a5565b8587868c8780958e5196879562461bcd60e51b875286015280518094860152825b84811061037757505050828201840152601f01601f19168101030190fd5b8181018301518882018801528795508201610359565b606090610324565b875162461bcd60e51b8152808701849052600d818601526c626164207369676e617475726560981b81870152606490fd5b634e487b7160e01b8e5260418b52888efd5b508b5162461bcd60e51b8152808b018890526015818a015274185d5d1a1bdc9a5e985d1a5bdb88195e1c1a5c9959605a1b818b0152606490fd5b508b5162461bcd60e51b8152808b01889052601b818a01527f617574686f72697a6174696f6e206e6f74207965742076616c69640000000000818b0152606490fd5b508b5162461bcd60e51b8152808b018890526012818a0152711b9bdb98d948185b1c9958591e481d5cd95960721b818b0152606490fd5b8680fd5b8480fd5b8284346100ee57816003193601126100ee5767ffffffffffffffff92803584811161011d576104c59036908301610594565b9490926024359182116100ee5750916104e7602095926104ef94369101610594565b929091610ad1565b90516001600160e01b03199091168152f35b8284346100ee57816003193601126100ee576024359067ffffffffffffffff82116100ee575060209261053a6104ef9236908301610594565b9135610a80565b84913461011d57602036600319011261011d573563ffffffff60e01b811680910361011d57602092506301ffc9a760e01b8114908115610583575b5015158152f35b630b135d3f60e11b1490508361057c565b9181601f840112156105c25782359167ffffffffffffffff83116105c257602083818601950101116105c257565b600080fd5b9181601f840112156105c25782359167ffffffffffffffff83116105c2576020808501948460051b0101116105c257565b60c0810190811067ffffffffffffffff82111761061457604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761061457604052565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f0617916c66cf2f8bef8f2360f69f42e7fb36391164667ba437bda5f2f137968b60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526106dc816105f8565b51902090565b67ffffffffffffffff81116106145760051b60200190565b60001981146107095760010190565b634e487b7160e01b600052601160045260246000fd5b91908110156107415760051b81013590605e19813603018212156105c2570190565b634e487b7160e01b600052603260045260246000fd5b610760826106e2565b91604061076f8151948561062a565b81845261077b826106e2565b60209385850193601f199392840136863760005b8181106107da5750505051838194820180965190949160005b8281106107c357505050506106dc920390810183528261062a565b8351875295810195879450928101926001016107a8565b6107e881838598979861071f565b6107f181610895565b90610808610801878301836108a9565b36916108f8565b89815191012089875192818401947f84fa2cf05cd88e992eae77e851af68a4ee278dcff6ef504e487a55b3baadfbe5865260018060a01b0316898501520135606083015260809081830152815260a0810181811067ffffffffffffffff8211176106145786525190209088518110156107415761088d91888260051b8b0101526106fa565b94939461078f565b356001600160a01b03811681036105c25790565b903590601e19813603018212156105c2570180359067ffffffffffffffff82116105c2576020019181360383136105c257565b67ffffffffffffffff811161061457601f01601f191660200190565b929192610904826108dc565b91610912604051938461062a565b8294818452818301116105c2578281602093846000960137010152565b81519190604183036109605761095992506020820151906060604084015193015160001a9061096b565b9192909190565b505060009160029190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109ef57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109e35780516001600160a01b038116156109da57918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a6a5780610a0d575050565b60018103610a275760405163f645eedf60e01b8152600490fd5b60028103610a485760405163fce698f760e01b815260048101839052602490fd5b600314610a525750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b9061024b90610a909336916108f8565b506004811015610a6a57159081610abe575b50610ab3576001600160e01b031990565b630b135d3f60e11b90565b6001600160a01b03163014905038610aa2565b91610ae5610af4949361024b9336916108f8565b602081519101209236916108f8565b506004811015610a6a57159081610b22575b50610b17576001600160e01b031990565b6320c13b0b60e01b90565b6001600160a01b03163014905038610b0656fea26469706673582212204bcc5204fe45a1d40760007c417d38e77e72eee07beae66a428170f45822cb2c64736f6c63430008140033", + "deployedBytecode": "0x6080604081815260049182361015610022575b505050361561002057600080fd5b005b600092833560e01c91826301ffc9a714610541575081631626ba7e1461050157816320c13b0b146104935781635d00bb12146100f15781635df4c239146101215781636717e41c146100f15781637b6d6a18146100b0575063f698da251461008a5780610012565b346100ac57816003193601126100ac576020906100a561064c565b9051908152f35b5080fd5b8284346100ee5760203660031901126100ee5782359067ffffffffffffffff82116100ee57506100e86020936100a5923691016105c7565b90610757565b80fd5b90503461011d57602036600319011261011d578160209360ff9235815280855220541690519015158152f35b8280fd5b90503461011d5760a036600319011261011d5767ffffffffffffffff90803582811161048f5761015490369083016105c7565b8560249492949182356044948535906064359060843581811161048b5761017e9036908b01610594565b93909285885260ff8d602099808b5220541661045457814210610412578042116103d857908c916101af888e610757565b918351928a8401947f19667787bf8e4e28ff931080c268a52496d168906174261eda235b32144164f38652840152876060840152608083015260a082015260a081526101fa816105f8565b51902061020561064c565b918c51918883019361190160f01b855260228401526042830152604282526080820190828210908211176103c6578c5251902061025a926102519261024b9136916108f8565b9061092f565b909291926109fb565b306001600160a01b039091160361039557808952888352878920805460ff191660011790557f1be5cb2f29a4876ca6fdf1177257bc6f2671bc7e036db0815016a6b766ecd1158980a2875b8181106102b0578880f35b88806102c56102c084868c61071f565b610895565b8a8a6102ec6102e387898b6102db83838861071f565b01359461071f565b838101906108a9565b8093519384928337810185815203925af13d1561038d573d9061030e826108dc565b9161031b8b51938461062a565b82523d8b8684013e5b156103385750610333906106fa565b6102a5565b8587868c8780958e5196879562461bcd60e51b875286015280518094860152825b84811061037757505050828201840152601f01601f19168101030190fd5b8181018301518882018801528795508201610359565b606090610324565b875162461bcd60e51b8152808701849052600d818601526c626164207369676e617475726560981b81870152606490fd5b634e487b7160e01b8e5260418b52888efd5b508b5162461bcd60e51b8152808b018890526015818a015274185d5d1a1bdc9a5e985d1a5bdb88195e1c1a5c9959605a1b818b0152606490fd5b508b5162461bcd60e51b8152808b01889052601b818a01527f617574686f72697a6174696f6e206e6f74207965742076616c69640000000000818b0152606490fd5b508b5162461bcd60e51b8152808b018890526012818a0152711b9bdb98d948185b1c9958591e481d5cd95960721b818b0152606490fd5b8680fd5b8480fd5b8284346100ee57816003193601126100ee5767ffffffffffffffff92803584811161011d576104c59036908301610594565b9490926024359182116100ee5750916104e7602095926104ef94369101610594565b929091610ad1565b90516001600160e01b03199091168152f35b8284346100ee57816003193601126100ee576024359067ffffffffffffffff82116100ee575060209261053a6104ef9236908301610594565b9135610a80565b84913461011d57602036600319011261011d573563ffffffff60e01b811680910361011d57602092506301ffc9a760e01b8114908115610583575b5015158152f35b630b135d3f60e11b1490508361057c565b9181601f840112156105c25782359167ffffffffffffffff83116105c257602083818601950101116105c257565b600080fd5b9181601f840112156105c25782359167ffffffffffffffff83116105c2576020808501948460051b0101116105c257565b60c0810190811067ffffffffffffffff82111761061457604052565b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff82111761061457604052565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f0617916c66cf2f8bef8f2360f69f42e7fb36391164667ba437bda5f2f137968b60408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526106dc816105f8565b51902090565b67ffffffffffffffff81116106145760051b60200190565b60001981146107095760010190565b634e487b7160e01b600052601160045260246000fd5b91908110156107415760051b81013590605e19813603018212156105c2570190565b634e487b7160e01b600052603260045260246000fd5b610760826106e2565b91604061076f8151948561062a565b81845261077b826106e2565b60209385850193601f199392840136863760005b8181106107da5750505051838194820180965190949160005b8281106107c357505050506106dc920390810183528261062a565b8351875295810195879450928101926001016107a8565b6107e881838598979861071f565b6107f181610895565b90610808610801878301836108a9565b36916108f8565b89815191012089875192818401947f84fa2cf05cd88e992eae77e851af68a4ee278dcff6ef504e487a55b3baadfbe5865260018060a01b0316898501520135606083015260809081830152815260a0810181811067ffffffffffffffff8211176106145786525190209088518110156107415761088d91888260051b8b0101526106fa565b94939461078f565b356001600160a01b03811681036105c25790565b903590601e19813603018212156105c2570180359067ffffffffffffffff82116105c2576020019181360383136105c257565b67ffffffffffffffff811161061457601f01601f191660200190565b929192610904826108dc565b91610912604051938461062a565b8294818452818301116105c2578281602093846000960137010152565b81519190604183036109605761095992506020820151906060604084015193015160001a9061096b565b9192909190565b505060009160029190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116109ef57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156109e35780516001600160a01b038116156109da57918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015610a6a5780610a0d575050565b60018103610a275760405163f645eedf60e01b8152600490fd5b60028103610a485760405163fce698f760e01b815260048101839052602490fd5b600314610a525750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b9061024b90610a909336916108f8565b506004811015610a6a57159081610abe575b50610ab3576001600160e01b031990565b630b135d3f60e11b90565b6001600160a01b03163014905038610aa2565b91610ae5610af4949361024b9336916108f8565b602081519101209236916108f8565b506004811015610a6a57159081610b22575b50610b17576001600160e01b031990565b6320c13b0b60e01b90565b6001600160a01b03163014905038610b0656fea26469706673582212204bcc5204fe45a1d40760007c417d38e77e72eee07beae66a428170f45822cb2c64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/Eip7702SimpleAccount.sol/artifacts.d.ts b/eth/artifacts/contracts/Eip7702SimpleAccount.sol/artifacts.d.ts new file mode 100644 index 0000000..e7a70f6 --- /dev/null +++ b/eth/artifacts/contracts/Eip7702SimpleAccount.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { Eip7702SimpleAccount$Type } from "./Eip7702SimpleAccount"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["Eip7702SimpleAccount"]: Eip7702SimpleAccount$Type; + ["contracts/Eip7702SimpleAccount.sol:Eip7702SimpleAccount"]: Eip7702SimpleAccount$Type; + } +} diff --git a/eth/artifacts/contracts/LitActionRegistry.sol/LitActionRegistry.d.ts b/eth/artifacts/contracts/LitActionRegistry.sol/LitActionRegistry.d.ts new file mode 100644 index 0000000..584ab29 --- /dev/null +++ b/eth/artifacts/contracts/LitActionRegistry.sol/LitActionRegistry.d.ts @@ -0,0 +1,217 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { AbiParameterToPrimitiveType, GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface LitActionRegistry$Type { + "_format": "hh-sol-artifact-1", + "contractName": "LitActionRegistry", + "sourceName": "contracts/LitActionRegistry.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "oldCID", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newCID", + "type": "string" + } + ], + "name": "ChildLitActionCIDUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "childLitActionCID", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChildIPFSCID", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChildLitActionCID", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newCID", + "type": "string" + } + ], + "name": "setChildLitActionCID", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080346100bb57601f6107d738819003918201601f19168301916001600160401b038311848410176100c0578084926020946040528339810103126100bb57516001600160a01b0390818116908190036100bb5780156100a257600080546001600160a01b03198116831782556040519316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a361070090816100d78239f35b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe60406080815260048036101561001457600080fd5b600091823560e01c8063223b0a9b1461041757806342e7f44e146100fd5780634e546bd11461018b578063715018a61461012e5780638da5cb5b14610102578063c3f589de146100fd5763f2fde38b1461006d57600080fd5b346100f95760203660031901126100f9576001600160a01b038235818116939192908490036100f55761009e61067e565b83156100df57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8480fd5b8280fd5b6105a7565b83823461012a578160031936011261012a57905490516001600160a01b039091168152602090f35b5080fd5b833461018857806003193601126101885761014761067e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5091903461012a57602092836003193601126100f95767ffffffffffffffff82358181116100f557366023820112156100f557808401359180831161040457835192601f19926101e2601f830185168a0186610486565b81855236602483830101116104005781889260248b9301838801378501015261020961067e565b8251156103b1576102186104be565b94835191821161039e5750600191610230835461044c565b601f811161034c575b508790601f83116001146102be575091816102ad94928899947f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f99916102b3575b50600019600383901b1c191690821b1790555b6102a08451958587968752860190610567565b9184830390850152610567565b0390a180f35b90508301513861027a565b8216908388526000805160206106ab83398151915291885b81811061033757509284927f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f999a9592826102ad98961061031e575b5050811b01905561028d565b85015160001960f88460031b161c191690553880610312565b86830151845592850192918a01918a016102d6565b8388526000805160206106ab833981519152601f840160051c8101918a8510610394575b601f0160051c019084905b828110610389575050610239565b89815501849061037b565b9091508190610370565b634e487b7160e01b875260419052602486fd5b835162461bcd60e51b81528086018890526024808201527f4368696c64204c697420416374696f6e204349442063616e6e6f7420626520656044820152636d70747960e01b6064820152608490fd5b8780fd5b634e487b7160e01b865260418552602486fd5b83823461012a578160031936011261012a57610448906104356104be565b9051918291602083526020830190610567565b0390f35b90600182811c9216801561047c575b602083101461046657565b634e487b7160e01b600052602260045260246000fd5b91607f169161045b565b90601f8019910116810190811067ffffffffffffffff8211176104a857604052565b634e487b7160e01b600052604160045260246000fd5b604051906000826001918254926104d48461044c565b8084529381811690811561054557506001146104fa575b506104f892500383610486565b565b600081815291506000805160206106ab8339815191525b84831061052a57506104f89350508101602001386104eb565b81935090816020925483858a01015201910190918592610511565b9050602092506104f894915060ff191682840152151560051b820101386104eb565b919082519283825260005b848110610593575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610572565b346106795760008060031936011261018857604051908060018054916105cc8361044c565b8086529282811690811561064f5750600114610607575b610448856105f381870382610486565b604051918291602083526020830190610567565b92508083526000805160206106ab8339815191525b8284106106375750505081016020016105f3826104486105e3565b8054602085870181019190915290930192810161061c565b869550610448969350602092506105f394915060ff191682840152151560051b82010192936105e3565b600080fd5b6000546001600160a01b0316330361069257565b60405163118cdaa760e01b8152336004820152602490fdfeb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a2646970667358221220480aa32a2929c4e086f1b5b9574d5af13423bccf452c4216553046f31b0a774564736f6c63430008140033", + "deployedBytecode": "0x60406080815260048036101561001457600080fd5b600091823560e01c8063223b0a9b1461041757806342e7f44e146100fd5780634e546bd11461018b578063715018a61461012e5780638da5cb5b14610102578063c3f589de146100fd5763f2fde38b1461006d57600080fd5b346100f95760203660031901126100f9576001600160a01b038235818116939192908490036100f55761009e61067e565b83156100df57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8480fd5b8280fd5b6105a7565b83823461012a578160031936011261012a57905490516001600160a01b039091168152602090f35b5080fd5b833461018857806003193601126101885761014761067e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5091903461012a57602092836003193601126100f95767ffffffffffffffff82358181116100f557366023820112156100f557808401359180831161040457835192601f19926101e2601f830185168a0186610486565b81855236602483830101116104005781889260248b9301838801378501015261020961067e565b8251156103b1576102186104be565b94835191821161039e5750600191610230835461044c565b601f811161034c575b508790601f83116001146102be575091816102ad94928899947f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f99916102b3575b50600019600383901b1c191690821b1790555b6102a08451958587968752860190610567565b9184830390850152610567565b0390a180f35b90508301513861027a565b8216908388526000805160206106ab83398151915291885b81811061033757509284927f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f999a9592826102ad98961061031e575b5050811b01905561028d565b85015160001960f88460031b161c191690553880610312565b86830151845592850192918a01918a016102d6565b8388526000805160206106ab833981519152601f840160051c8101918a8510610394575b601f0160051c019084905b828110610389575050610239565b89815501849061037b565b9091508190610370565b634e487b7160e01b875260419052602486fd5b835162461bcd60e51b81528086018890526024808201527f4368696c64204c697420416374696f6e204349442063616e6e6f7420626520656044820152636d70747960e01b6064820152608490fd5b8780fd5b634e487b7160e01b865260418552602486fd5b83823461012a578160031936011261012a57610448906104356104be565b9051918291602083526020830190610567565b0390f35b90600182811c9216801561047c575b602083101461046657565b634e487b7160e01b600052602260045260246000fd5b91607f169161045b565b90601f8019910116810190811067ffffffffffffffff8211176104a857604052565b634e487b7160e01b600052604160045260246000fd5b604051906000826001918254926104d48461044c565b8084529381811690811561054557506001146104fa575b506104f892500383610486565b565b600081815291506000805160206106ab8339815191525b84831061052a57506104f89350508101602001386104eb565b81935090816020925483858a01015201910190918592610511565b9050602092506104f894915060ff191682840152151560051b820101386104eb565b919082519283825260005b848110610593575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610572565b346106795760008060031936011261018857604051908060018054916105cc8361044c565b8086529282811690811561064f5750600114610607575b610448856105f381870382610486565b604051918291602083526020830190610567565b92508083526000805160206106ab8339815191525b8284106106375750505081016020016105f3826104486105e3565b8054602085870181019190915290930192810161061c565b869550610448969350602092506105f394915060ff191682840152151560051b82010192936105e3565b600080fd5b6000546001600160a01b0316330361069257565b60405163118cdaa760e01b8152336004820152602490fdfeb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a2646970667358221220480aa32a2929c4e086f1b5b9574d5af13423bccf452c4216553046f31b0a774564736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "LitActionRegistry", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/LitActionRegistry.sol:LitActionRegistry", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "LitActionRegistry", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/LitActionRegistry.sol:LitActionRegistry", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "LitActionRegistry", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/LitActionRegistry.sol:LitActionRegistry", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/LitActionRegistry.sol/LitActionRegistry.json b/eth/artifacts/contracts/LitActionRegistry.sol/LitActionRegistry.json new file mode 100644 index 0000000..440cf05 --- /dev/null +++ b/eth/artifacts/contracts/LitActionRegistry.sol/LitActionRegistry.json @@ -0,0 +1,167 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "LitActionRegistry", + "sourceName": "contracts/LitActionRegistry.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "oldCID", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newCID", + "type": "string" + } + ], + "name": "ChildLitActionCIDUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "childLitActionCID", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChildIPFSCID", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChildLitActionCID", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newCID", + "type": "string" + } + ], + "name": "setChildLitActionCID", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080346100bb57601f6107d738819003918201601f19168301916001600160401b038311848410176100c0578084926020946040528339810103126100bb57516001600160a01b0390818116908190036100bb5780156100a257600080546001600160a01b03198116831782556040519316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a361070090816100d78239f35b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe60406080815260048036101561001457600080fd5b600091823560e01c8063223b0a9b1461041757806342e7f44e146100fd5780634e546bd11461018b578063715018a61461012e5780638da5cb5b14610102578063c3f589de146100fd5763f2fde38b1461006d57600080fd5b346100f95760203660031901126100f9576001600160a01b038235818116939192908490036100f55761009e61067e565b83156100df57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8480fd5b8280fd5b6105a7565b83823461012a578160031936011261012a57905490516001600160a01b039091168152602090f35b5080fd5b833461018857806003193601126101885761014761067e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5091903461012a57602092836003193601126100f95767ffffffffffffffff82358181116100f557366023820112156100f557808401359180831161040457835192601f19926101e2601f830185168a0186610486565b81855236602483830101116104005781889260248b9301838801378501015261020961067e565b8251156103b1576102186104be565b94835191821161039e5750600191610230835461044c565b601f811161034c575b508790601f83116001146102be575091816102ad94928899947f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f99916102b3575b50600019600383901b1c191690821b1790555b6102a08451958587968752860190610567565b9184830390850152610567565b0390a180f35b90508301513861027a565b8216908388526000805160206106ab83398151915291885b81811061033757509284927f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f999a9592826102ad98961061031e575b5050811b01905561028d565b85015160001960f88460031b161c191690553880610312565b86830151845592850192918a01918a016102d6565b8388526000805160206106ab833981519152601f840160051c8101918a8510610394575b601f0160051c019084905b828110610389575050610239565b89815501849061037b565b9091508190610370565b634e487b7160e01b875260419052602486fd5b835162461bcd60e51b81528086018890526024808201527f4368696c64204c697420416374696f6e204349442063616e6e6f7420626520656044820152636d70747960e01b6064820152608490fd5b8780fd5b634e487b7160e01b865260418552602486fd5b83823461012a578160031936011261012a57610448906104356104be565b9051918291602083526020830190610567565b0390f35b90600182811c9216801561047c575b602083101461046657565b634e487b7160e01b600052602260045260246000fd5b91607f169161045b565b90601f8019910116810190811067ffffffffffffffff8211176104a857604052565b634e487b7160e01b600052604160045260246000fd5b604051906000826001918254926104d48461044c565b8084529381811690811561054557506001146104fa575b506104f892500383610486565b565b600081815291506000805160206106ab8339815191525b84831061052a57506104f89350508101602001386104eb565b81935090816020925483858a01015201910190918592610511565b9050602092506104f894915060ff191682840152151560051b820101386104eb565b919082519283825260005b848110610593575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610572565b346106795760008060031936011261018857604051908060018054916105cc8361044c565b8086529282811690811561064f5750600114610607575b610448856105f381870382610486565b604051918291602083526020830190610567565b92508083526000805160206106ab8339815191525b8284106106375750505081016020016105f3826104486105e3565b8054602085870181019190915290930192810161061c565b869550610448969350602092506105f394915060ff191682840152151560051b82010192936105e3565b600080fd5b6000546001600160a01b0316330361069257565b60405163118cdaa760e01b8152336004820152602490fdfeb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a2646970667358221220480aa32a2929c4e086f1b5b9574d5af13423bccf452c4216553046f31b0a774564736f6c63430008140033", + "deployedBytecode": "0x60406080815260048036101561001457600080fd5b600091823560e01c8063223b0a9b1461041757806342e7f44e146100fd5780634e546bd11461018b578063715018a61461012e5780638da5cb5b14610102578063c3f589de146100fd5763f2fde38b1461006d57600080fd5b346100f95760203660031901126100f9576001600160a01b038235818116939192908490036100f55761009e61067e565b83156100df57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8480fd5b8280fd5b6105a7565b83823461012a578160031936011261012a57905490516001600160a01b039091168152602090f35b5080fd5b833461018857806003193601126101885761014761067e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5091903461012a57602092836003193601126100f95767ffffffffffffffff82358181116100f557366023820112156100f557808401359180831161040457835192601f19926101e2601f830185168a0186610486565b81855236602483830101116104005781889260248b9301838801378501015261020961067e565b8251156103b1576102186104be565b94835191821161039e5750600191610230835461044c565b601f811161034c575b508790601f83116001146102be575091816102ad94928899947f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f99916102b3575b50600019600383901b1c191690821b1790555b6102a08451958587968752860190610567565b9184830390850152610567565b0390a180f35b90508301513861027a565b8216908388526000805160206106ab83398151915291885b81811061033757509284927f6044ce709730a788d06eb07d22b9177941c23ceecefb7a3c56d9dcf69fd4e86f999a9592826102ad98961061031e575b5050811b01905561028d565b85015160001960f88460031b161c191690553880610312565b86830151845592850192918a01918a016102d6565b8388526000805160206106ab833981519152601f840160051c8101918a8510610394575b601f0160051c019084905b828110610389575050610239565b89815501849061037b565b9091508190610370565b634e487b7160e01b875260419052602486fd5b835162461bcd60e51b81528086018890526024808201527f4368696c64204c697420416374696f6e204349442063616e6e6f7420626520656044820152636d70747960e01b6064820152608490fd5b8780fd5b634e487b7160e01b865260418552602486fd5b83823461012a578160031936011261012a57610448906104356104be565b9051918291602083526020830190610567565b0390f35b90600182811c9216801561047c575b602083101461046657565b634e487b7160e01b600052602260045260246000fd5b91607f169161045b565b90601f8019910116810190811067ffffffffffffffff8211176104a857604052565b634e487b7160e01b600052604160045260246000fd5b604051906000826001918254926104d48461044c565b8084529381811690811561054557506001146104fa575b506104f892500383610486565b565b600081815291506000805160206106ab8339815191525b84831061052a57506104f89350508101602001386104eb565b81935090816020925483858a01015201910190918592610511565b9050602092506104f894915060ff191682840152151560051b820101386104eb565b919082519283825260005b848110610593575050826000602080949584010152601f8019910116010190565b602081830181015184830182015201610572565b346106795760008060031936011261018857604051908060018054916105cc8361044c565b8086529282811690811561064f5750600114610607575b610448856105f381870382610486565b604051918291602083526020830190610567565b92508083526000805160206106ab8339815191525b8284106106375750505081016020016105f3826104486105e3565b8054602085870181019190915290930192810161061c565b869550610448969350602092506105f394915060ff191682840152151560051b82010192936105e3565b600080fd5b6000546001600160a01b0316330361069257565b60405163118cdaa760e01b8152336004820152602490fdfeb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6a2646970667358221220480aa32a2929c4e086f1b5b9574d5af13423bccf452c4216553046f31b0a774564736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/LitActionRegistry.sol/artifacts.d.ts b/eth/artifacts/contracts/LitActionRegistry.sol/artifacts.d.ts new file mode 100644 index 0000000..2585ec4 --- /dev/null +++ b/eth/artifacts/contracts/LitActionRegistry.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { LitActionRegistry$Type } from "./LitActionRegistry"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["LitActionRegistry"]: LitActionRegistry$Type; + ["contracts/LitActionRegistry.sol:LitActionRegistry"]: LitActionRegistry$Type; + } +} diff --git a/eth/artifacts/contracts/NoopVerifierHonk.sol/HonkVerifier.d.ts b/eth/artifacts/contracts/NoopVerifierHonk.sol/HonkVerifier.d.ts new file mode 100644 index 0000000..d52802b --- /dev/null +++ b/eth/artifacts/contracts/NoopVerifierHonk.sol/HonkVerifier.d.ts @@ -0,0 +1,85 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface HonkVerifier$Type { + "_format": "hh-sol-artifact-1", + "contractName": "HonkVerifier", + "sourceName": "contracts/NoopVerifierHonk.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x608080604052346100155760e3908161001b8239f35b600080fdfe6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220f1086d267fffa429e41d6f39db3b691ef4f406dfb402bcfe25cae6eb6416be4064736f6c63430008140033", + "deployedBytecode": "0x6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220f1086d267fffa429e41d6f39db3b691ef4f406dfb402bcfe25cae6eb6416be4064736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "HonkVerifier", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/NoopVerifierHonk.sol:HonkVerifier", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "HonkVerifier", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/NoopVerifierHonk.sol:HonkVerifier", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "HonkVerifier", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/NoopVerifierHonk.sol:HonkVerifier", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/NoopVerifierHonk.sol/HonkVerifier.json b/eth/artifacts/contracts/NoopVerifierHonk.sol/HonkVerifier.json new file mode 100644 index 0000000..45f2553 --- /dev/null +++ b/eth/artifacts/contracts/NoopVerifierHonk.sol/HonkVerifier.json @@ -0,0 +1,35 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "HonkVerifier", + "sourceName": "contracts/NoopVerifierHonk.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x608080604052346100155760e3908161001b8239f35b600080fdfe6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220f1086d267fffa429e41d6f39db3b691ef4f406dfb402bcfe25cae6eb6416be4064736f6c63430008140033", + "deployedBytecode": "0x6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220f1086d267fffa429e41d6f39db3b691ef4f406dfb402bcfe25cae6eb6416be4064736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/NoopVerifierHonk.sol/IVerifier.d.ts b/eth/artifacts/contracts/NoopVerifierHonk.sol/IVerifier.d.ts new file mode 100644 index 0000000..d00e0a6 --- /dev/null +++ b/eth/artifacts/contracts/NoopVerifierHonk.sol/IVerifier.d.ts @@ -0,0 +1,67 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface IVerifier$Type { + "_format": "hh-sol-artifact-1", + "contractName": "IVerifier", + "sourceName": "contracts/NoopVerifierHonk.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "_publicInputs", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "contracts/NoopVerifierHonk.sol:IVerifier", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "contracts/NoopVerifierHonk.sol:IVerifier", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "contracts/NoopVerifierHonk.sol:IVerifier", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/NoopVerifierHonk.sol/IVerifier.json b/eth/artifacts/contracts/NoopVerifierHonk.sol/IVerifier.json new file mode 100644 index 0000000..98d3c45 --- /dev/null +++ b/eth/artifacts/contracts/NoopVerifierHonk.sol/IVerifier.json @@ -0,0 +1,35 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IVerifier", + "sourceName": "contracts/NoopVerifierHonk.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "_publicInputs", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/NoopVerifierHonk.sol/artifacts.d.ts b/eth/artifacts/contracts/NoopVerifierHonk.sol/artifacts.d.ts new file mode 100644 index 0000000..39bb7ed --- /dev/null +++ b/eth/artifacts/contracts/NoopVerifierHonk.sol/artifacts.d.ts @@ -0,0 +1,18 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { HonkVerifier$Type } from "./HonkVerifier"; +import { IVerifier$Type } from "./IVerifier"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["HonkVerifier"]: HonkVerifier$Type; + ["IVerifier"]: IVerifier$Type; + ["contracts/NoopVerifierHonk.sol:HonkVerifier"]: HonkVerifier$Type; + ["contracts/NoopVerifierHonk.sol:IVerifier"]: IVerifier$Type; + } +} diff --git a/eth/artifacts/contracts/SocialRecovery.sol/SocialRecovery.d.ts b/eth/artifacts/contracts/SocialRecovery.sol/SocialRecovery.d.ts new file mode 100644 index 0000000..dea79e3 --- /dev/null +++ b/eth/artifacts/contracts/SocialRecovery.sol/SocialRecovery.d.ts @@ -0,0 +1,288 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { AbiParameterToPrimitiveType, GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface SocialRecovery$Type { + "_format": "hh-sol-artifact-1", + "contractName": "SocialRecovery", + "sourceName": "contracts/SocialRecovery.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "guardianCID", + "type": "string" + } + ], + "name": "GuardianCIDAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "string", + "name": "guardianCID", + "type": "string" + }, + { + "internalType": "string", + "name": "guardianValue", + "type": "string" + } + ], + "name": "addGuardianCID", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getGuardianConfig", + "outputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "guardianCount", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "guardianCIDs", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "cidHash", + "type": "bytes32" + } + ], + "name": "getGuardianEntry", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "guardianConfigs", + "outputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newThreshold", + "type": "uint256" + } + ], + "name": "updateThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080346100bb57601f610a8138819003918201601f19168301916001600160401b038311848410176100c0578084926020946040528339810103126100bb57516001600160a01b0390818116908190036100bb5780156100a257600080546001600160a01b03198116831782556040519316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36109aa90816100d78239f35b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604081815260048036101561001557600080fd5b600092833560e01c9081630bb6094a14610761575080635eb0bad0146103b0578063715018a61461035357806376716bbe1461025a5780638da5cb5b14610232578063924af1bc1461014f578063bf00169f146101045763f2fde38b1461007b57600080fd5b3461010057602036600319011261010057610094610824565b9061009d61090e565b6001600160a01b039182169283156100ea57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8280fd5b50503461014b57602036600319011261014b579081906001600160a01b0361012a610824565b16815260016020522060ff6001825492015416825191825215156020820152f35b5080fd5b509034610100578060031936011261010057610169610824565b916024359261017661090e565b6001600160a01b031684526001602052818420600281015490929080156101ef5784151590816101e4575b50156101ad5750505580f35b906020606492519162461bcd60e51b83528201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152fd5b9050841115386101a1565b815162461bcd60e51b8152602081850152601760248201527f4e6f20677561726469616e7320636f6e666967757265640000000000000000006044820152606490fd5b50503461014b578160031936011261014b57905490516001600160a01b039091168152602090f35b50503461014b578060031936011261014b576001600160a01b0361027c610824565b16825260019060209180835260038285200160243585528352818420938251948592828254926102ab8461093a565b938487528884821691826000146103295750506001146102eb575b85886102e7896102d8848a038561083f565b519282849384528301906108ce565b0390f35b87945081939291528383205b82841061031157505050820101816102d86102e7386102c6565b8054848a0186015288955087949093019281016102f7565b60ff19168882015294151560051b870190940194508593506102d892506102e791503890506102c6565b83346103ad57806003193601126103ad5761036c61090e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5082903461014b57606036600319011261014b576103cc610824565b602467ffffffffffffffff813581811161075d576103ed9036908601610877565b92604435828111610759576104059036908701610877565b9061040e61090e565b60018060a01b031694858752600192602094848652898920936002850192835415610747575b60ff878701541615610704578851156106c15781511561067e57908b949392918b6104718b518b8d01209760038a0192898152838d52205461093a565b61063c57868d5289528c8c2091805191821161062a578c8291610494855461093a565b8c601f82116105d2575b50508b91601f84116001146105715792610566575b5050600019600383901b1c191690881b1790555b8154926801000000000000000084101561055557868401808455841015610544575050918899939161053695937fcd5e9273c5e2a31f16cb4cda551d1671f482e8540f9dac80d99e3b0d01271851999a52868b20015580541561053c575b5050519282849384528301906108ce565b0390a280f35b558780610525565b634e487b7160e01b8b526032905289fd5b634e487b7160e01b8b526041905289fd5b015190508e806104b3565b8581528c81208c9550929190601f198516908e5b8282106105bb57505084116105a2575b505050811b0190556104c7565b015160001960f88460031b161c191690558e8080610595565b8385015186558e979095019493840193018e610585565b9193509185815220601f840160051c8101918c8510610620575b918f92859492601f8e920160051c01915b82811061060c5750508c61049e565b809294919395505501918e918b85946105fd565b90915081906105ec565b634e487b7160e01b8d5260418652838dfd5b8d5162461bcd60e51b81528087018b90526017818601527f477561726469616e20416c7265616479206578697374730000000000000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601e818401527f477561726469616e2076616c75652063616e6e6f7420626520656d70747900006044820152606490fd5b508a5162461bcd60e51b8152808501889052601c818401527f477561726469616e204349442063616e6e6f7420626520656d707479000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601a818401527f477561726469616e207265636f766572792064697361626c65640000000000006044820152606490fd5b858701805460ff191688179055610434565b8680fd5b8580fd5b84843461014b5760209283600319360112610100579092916001600160a01b03610789610824565b16815260019182845284822093845491600260ff868801541696019687549081835283830180998752848720875b848110610811575050836107cc91038461083f565b80519760808901958952151584890152870152608060608701525180925260a0850195925b8281106107fe5785870386f35b83518752958101959281019284016107f1565b81548352918601919089019089016107b7565b600435906001600160a01b038216820361083a57565b600080fd5b90601f8019910116810190811067ffffffffffffffff82111761086157604052565b634e487b7160e01b600052604160045260246000fd5b81601f8201121561083a5780359067ffffffffffffffff821161086157604051926108ac601f8401601f19166020018561083f565b8284526020838301011161083a57816000926020809301838601378301015290565b919082519283825260005b8481106108fa575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016108d9565b6000546001600160a01b0316330361092257565b60405163118cdaa760e01b8152336004820152602490fd5b90600182811c9216801561096a575b602083101461095457565b634e487b7160e01b600052602260045260246000fd5b91607f169161094956fea264697066735822122037f7ce8de3a3a041096e02bc43cc8f7e44c10e1e7160c1fc561a4d75360898d864736f6c63430008140033", + "deployedBytecode": "0x6080604081815260048036101561001557600080fd5b600092833560e01c9081630bb6094a14610761575080635eb0bad0146103b0578063715018a61461035357806376716bbe1461025a5780638da5cb5b14610232578063924af1bc1461014f578063bf00169f146101045763f2fde38b1461007b57600080fd5b3461010057602036600319011261010057610094610824565b9061009d61090e565b6001600160a01b039182169283156100ea57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8280fd5b50503461014b57602036600319011261014b579081906001600160a01b0361012a610824565b16815260016020522060ff6001825492015416825191825215156020820152f35b5080fd5b509034610100578060031936011261010057610169610824565b916024359261017661090e565b6001600160a01b031684526001602052818420600281015490929080156101ef5784151590816101e4575b50156101ad5750505580f35b906020606492519162461bcd60e51b83528201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152fd5b9050841115386101a1565b815162461bcd60e51b8152602081850152601760248201527f4e6f20677561726469616e7320636f6e666967757265640000000000000000006044820152606490fd5b50503461014b578160031936011261014b57905490516001600160a01b039091168152602090f35b50503461014b578060031936011261014b576001600160a01b0361027c610824565b16825260019060209180835260038285200160243585528352818420938251948592828254926102ab8461093a565b938487528884821691826000146103295750506001146102eb575b85886102e7896102d8848a038561083f565b519282849384528301906108ce565b0390f35b87945081939291528383205b82841061031157505050820101816102d86102e7386102c6565b8054848a0186015288955087949093019281016102f7565b60ff19168882015294151560051b870190940194508593506102d892506102e791503890506102c6565b83346103ad57806003193601126103ad5761036c61090e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5082903461014b57606036600319011261014b576103cc610824565b602467ffffffffffffffff813581811161075d576103ed9036908601610877565b92604435828111610759576104059036908701610877565b9061040e61090e565b60018060a01b031694858752600192602094848652898920936002850192835415610747575b60ff878701541615610704578851156106c15781511561067e57908b949392918b6104718b518b8d01209760038a0192898152838d52205461093a565b61063c57868d5289528c8c2091805191821161062a578c8291610494855461093a565b8c601f82116105d2575b50508b91601f84116001146105715792610566575b5050600019600383901b1c191690881b1790555b8154926801000000000000000084101561055557868401808455841015610544575050918899939161053695937fcd5e9273c5e2a31f16cb4cda551d1671f482e8540f9dac80d99e3b0d01271851999a52868b20015580541561053c575b5050519282849384528301906108ce565b0390a280f35b558780610525565b634e487b7160e01b8b526032905289fd5b634e487b7160e01b8b526041905289fd5b015190508e806104b3565b8581528c81208c9550929190601f198516908e5b8282106105bb57505084116105a2575b505050811b0190556104c7565b015160001960f88460031b161c191690558e8080610595565b8385015186558e979095019493840193018e610585565b9193509185815220601f840160051c8101918c8510610620575b918f92859492601f8e920160051c01915b82811061060c5750508c61049e565b809294919395505501918e918b85946105fd565b90915081906105ec565b634e487b7160e01b8d5260418652838dfd5b8d5162461bcd60e51b81528087018b90526017818601527f477561726469616e20416c7265616479206578697374730000000000000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601e818401527f477561726469616e2076616c75652063616e6e6f7420626520656d70747900006044820152606490fd5b508a5162461bcd60e51b8152808501889052601c818401527f477561726469616e204349442063616e6e6f7420626520656d707479000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601a818401527f477561726469616e207265636f766572792064697361626c65640000000000006044820152606490fd5b858701805460ff191688179055610434565b8680fd5b8580fd5b84843461014b5760209283600319360112610100579092916001600160a01b03610789610824565b16815260019182845284822093845491600260ff868801541696019687549081835283830180998752848720875b848110610811575050836107cc91038461083f565b80519760808901958952151584890152870152608060608701525180925260a0850195925b8281106107fe5785870386f35b83518752958101959281019284016107f1565b81548352918601919089019089016107b7565b600435906001600160a01b038216820361083a57565b600080fd5b90601f8019910116810190811067ffffffffffffffff82111761086157604052565b634e487b7160e01b600052604160045260246000fd5b81601f8201121561083a5780359067ffffffffffffffff821161086157604051926108ac601f8401601f19166020018561083f565b8284526020838301011161083a57816000926020809301838601378301015290565b919082519283825260005b8481106108fa575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016108d9565b6000546001600160a01b0316330361092257565b60405163118cdaa760e01b8152336004820152602490fd5b90600182811c9216801561096a575b602083101461095457565b634e487b7160e01b600052602260045260246000fd5b91607f169161094956fea264697066735822122037f7ce8de3a3a041096e02bc43cc8f7e44c10e1e7160c1fc561a4d75360898d864736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "SocialRecovery", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/SocialRecovery.sol:SocialRecovery", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "SocialRecovery", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/SocialRecovery.sol:SocialRecovery", + constructorArgs: [initialOwner: AbiParameterToPrimitiveType<{"name":"initialOwner","type":"address"}>], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "SocialRecovery", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/SocialRecovery.sol:SocialRecovery", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/SocialRecovery.sol/SocialRecovery.json b/eth/artifacts/contracts/SocialRecovery.sol/SocialRecovery.json new file mode 100644 index 0000000..50644ef --- /dev/null +++ b/eth/artifacts/contracts/SocialRecovery.sol/SocialRecovery.json @@ -0,0 +1,238 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SocialRecovery", + "sourceName": "contracts/SocialRecovery.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "initialOwner", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "guardianCID", + "type": "string" + } + ], + "name": "GuardianCIDAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "string", + "name": "guardianCID", + "type": "string" + }, + { + "internalType": "string", + "name": "guardianValue", + "type": "string" + } + ], + "name": "addGuardianCID", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "getGuardianConfig", + "outputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "guardianCount", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "guardianCIDs", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "cidHash", + "type": "bytes32" + } + ], + "name": "getGuardianEntry", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "guardianConfigs", + "outputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newThreshold", + "type": "uint256" + } + ], + "name": "updateThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080346100bb57601f610a8138819003918201601f19168301916001600160401b038311848410176100c0578084926020946040528339810103126100bb57516001600160a01b0390818116908190036100bb5780156100a257600080546001600160a01b03198116831782556040519316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a36109aa90816100d78239f35b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6080604081815260048036101561001557600080fd5b600092833560e01c9081630bb6094a14610761575080635eb0bad0146103b0578063715018a61461035357806376716bbe1461025a5780638da5cb5b14610232578063924af1bc1461014f578063bf00169f146101045763f2fde38b1461007b57600080fd5b3461010057602036600319011261010057610094610824565b9061009d61090e565b6001600160a01b039182169283156100ea57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8280fd5b50503461014b57602036600319011261014b579081906001600160a01b0361012a610824565b16815260016020522060ff6001825492015416825191825215156020820152f35b5080fd5b509034610100578060031936011261010057610169610824565b916024359261017661090e565b6001600160a01b031684526001602052818420600281015490929080156101ef5784151590816101e4575b50156101ad5750505580f35b906020606492519162461bcd60e51b83528201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152fd5b9050841115386101a1565b815162461bcd60e51b8152602081850152601760248201527f4e6f20677561726469616e7320636f6e666967757265640000000000000000006044820152606490fd5b50503461014b578160031936011261014b57905490516001600160a01b039091168152602090f35b50503461014b578060031936011261014b576001600160a01b0361027c610824565b16825260019060209180835260038285200160243585528352818420938251948592828254926102ab8461093a565b938487528884821691826000146103295750506001146102eb575b85886102e7896102d8848a038561083f565b519282849384528301906108ce565b0390f35b87945081939291528383205b82841061031157505050820101816102d86102e7386102c6565b8054848a0186015288955087949093019281016102f7565b60ff19168882015294151560051b870190940194508593506102d892506102e791503890506102c6565b83346103ad57806003193601126103ad5761036c61090e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5082903461014b57606036600319011261014b576103cc610824565b602467ffffffffffffffff813581811161075d576103ed9036908601610877565b92604435828111610759576104059036908701610877565b9061040e61090e565b60018060a01b031694858752600192602094848652898920936002850192835415610747575b60ff878701541615610704578851156106c15781511561067e57908b949392918b6104718b518b8d01209760038a0192898152838d52205461093a565b61063c57868d5289528c8c2091805191821161062a578c8291610494855461093a565b8c601f82116105d2575b50508b91601f84116001146105715792610566575b5050600019600383901b1c191690881b1790555b8154926801000000000000000084101561055557868401808455841015610544575050918899939161053695937fcd5e9273c5e2a31f16cb4cda551d1671f482e8540f9dac80d99e3b0d01271851999a52868b20015580541561053c575b5050519282849384528301906108ce565b0390a280f35b558780610525565b634e487b7160e01b8b526032905289fd5b634e487b7160e01b8b526041905289fd5b015190508e806104b3565b8581528c81208c9550929190601f198516908e5b8282106105bb57505084116105a2575b505050811b0190556104c7565b015160001960f88460031b161c191690558e8080610595565b8385015186558e979095019493840193018e610585565b9193509185815220601f840160051c8101918c8510610620575b918f92859492601f8e920160051c01915b82811061060c5750508c61049e565b809294919395505501918e918b85946105fd565b90915081906105ec565b634e487b7160e01b8d5260418652838dfd5b8d5162461bcd60e51b81528087018b90526017818601527f477561726469616e20416c7265616479206578697374730000000000000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601e818401527f477561726469616e2076616c75652063616e6e6f7420626520656d70747900006044820152606490fd5b508a5162461bcd60e51b8152808501889052601c818401527f477561726469616e204349442063616e6e6f7420626520656d707479000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601a818401527f477561726469616e207265636f766572792064697361626c65640000000000006044820152606490fd5b858701805460ff191688179055610434565b8680fd5b8580fd5b84843461014b5760209283600319360112610100579092916001600160a01b03610789610824565b16815260019182845284822093845491600260ff868801541696019687549081835283830180998752848720875b848110610811575050836107cc91038461083f565b80519760808901958952151584890152870152608060608701525180925260a0850195925b8281106107fe5785870386f35b83518752958101959281019284016107f1565b81548352918601919089019089016107b7565b600435906001600160a01b038216820361083a57565b600080fd5b90601f8019910116810190811067ffffffffffffffff82111761086157604052565b634e487b7160e01b600052604160045260246000fd5b81601f8201121561083a5780359067ffffffffffffffff821161086157604051926108ac601f8401601f19166020018561083f565b8284526020838301011161083a57816000926020809301838601378301015290565b919082519283825260005b8481106108fa575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016108d9565b6000546001600160a01b0316330361092257565b60405163118cdaa760e01b8152336004820152602490fd5b90600182811c9216801561096a575b602083101461095457565b634e487b7160e01b600052602260045260246000fd5b91607f169161094956fea264697066735822122037f7ce8de3a3a041096e02bc43cc8f7e44c10e1e7160c1fc561a4d75360898d864736f6c63430008140033", + "deployedBytecode": "0x6080604081815260048036101561001557600080fd5b600092833560e01c9081630bb6094a14610761575080635eb0bad0146103b0578063715018a61461035357806376716bbe1461025a5780638da5cb5b14610232578063924af1bc1461014f578063bf00169f146101045763f2fde38b1461007b57600080fd5b3461010057602036600319011261010057610094610824565b9061009d61090e565b6001600160a01b039182169283156100ea57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b8280fd5b50503461014b57602036600319011261014b579081906001600160a01b0361012a610824565b16815260016020522060ff6001825492015416825191825215156020820152f35b5080fd5b509034610100578060031936011261010057610169610824565b916024359261017661090e565b6001600160a01b031684526001602052818420600281015490929080156101ef5784151590816101e4575b50156101ad5750505580f35b906020606492519162461bcd60e51b83528201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152fd5b9050841115386101a1565b815162461bcd60e51b8152602081850152601760248201527f4e6f20677561726469616e7320636f6e666967757265640000000000000000006044820152606490fd5b50503461014b578160031936011261014b57905490516001600160a01b039091168152602090f35b50503461014b578060031936011261014b576001600160a01b0361027c610824565b16825260019060209180835260038285200160243585528352818420938251948592828254926102ab8461093a565b938487528884821691826000146103295750506001146102eb575b85886102e7896102d8848a038561083f565b519282849384528301906108ce565b0390f35b87945081939291528383205b82841061031157505050820101816102d86102e7386102c6565b8054848a0186015288955087949093019281016102f7565b60ff19168882015294151560051b870190940194508593506102d892506102e791503890506102c6565b83346103ad57806003193601126103ad5761036c61090e565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5082903461014b57606036600319011261014b576103cc610824565b602467ffffffffffffffff813581811161075d576103ed9036908601610877565b92604435828111610759576104059036908701610877565b9061040e61090e565b60018060a01b031694858752600192602094848652898920936002850192835415610747575b60ff878701541615610704578851156106c15781511561067e57908b949392918b6104718b518b8d01209760038a0192898152838d52205461093a565b61063c57868d5289528c8c2091805191821161062a578c8291610494855461093a565b8c601f82116105d2575b50508b91601f84116001146105715792610566575b5050600019600383901b1c191690881b1790555b8154926801000000000000000084101561055557868401808455841015610544575050918899939161053695937fcd5e9273c5e2a31f16cb4cda551d1671f482e8540f9dac80d99e3b0d01271851999a52868b20015580541561053c575b5050519282849384528301906108ce565b0390a280f35b558780610525565b634e487b7160e01b8b526032905289fd5b634e487b7160e01b8b526041905289fd5b015190508e806104b3565b8581528c81208c9550929190601f198516908e5b8282106105bb57505084116105a2575b505050811b0190556104c7565b015160001960f88460031b161c191690558e8080610595565b8385015186558e979095019493840193018e610585565b9193509185815220601f840160051c8101918c8510610620575b918f92859492601f8e920160051c01915b82811061060c5750508c61049e565b809294919395505501918e918b85946105fd565b90915081906105ec565b634e487b7160e01b8d5260418652838dfd5b8d5162461bcd60e51b81528087018b90526017818601527f477561726469616e20416c7265616479206578697374730000000000000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601e818401527f477561726469616e2076616c75652063616e6e6f7420626520656d70747900006044820152606490fd5b508a5162461bcd60e51b8152808501889052601c818401527f477561726469616e204349442063616e6e6f7420626520656d707479000000006044820152606490fd5b508a5162461bcd60e51b8152808501889052601a818401527f477561726469616e207265636f766572792064697361626c65640000000000006044820152606490fd5b858701805460ff191688179055610434565b8680fd5b8580fd5b84843461014b5760209283600319360112610100579092916001600160a01b03610789610824565b16815260019182845284822093845491600260ff868801541696019687549081835283830180998752848720875b848110610811575050836107cc91038461083f565b80519760808901958952151584890152870152608060608701525180925260a0850195925b8281106107fe5785870386f35b83518752958101959281019284016107f1565b81548352918601919089019089016107b7565b600435906001600160a01b038216820361083a57565b600080fd5b90601f8019910116810190811067ffffffffffffffff82111761086157604052565b634e487b7160e01b600052604160045260246000fd5b81601f8201121561083a5780359067ffffffffffffffff821161086157604051926108ac601f8401601f19166020018561083f565b8284526020838301011161083a57816000926020809301838601378301015290565b919082519283825260005b8481106108fa575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016108d9565b6000546001600160a01b0316330361092257565b60405163118cdaa760e01b8152336004820152602490fd5b90600182811c9216801561096a575b602083101461095457565b634e487b7160e01b600052602260045260246000fd5b91607f169161094956fea264697066735822122037f7ce8de3a3a041096e02bc43cc8f7e44c10e1e7160c1fc561a4d75360898d864736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/SocialRecovery.sol/artifacts.d.ts b/eth/artifacts/contracts/SocialRecovery.sol/artifacts.d.ts new file mode 100644 index 0000000..eda4a6a --- /dev/null +++ b/eth/artifacts/contracts/SocialRecovery.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { SocialRecovery$Type } from "./SocialRecovery"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["SocialRecovery"]: SocialRecovery$Type; + ["contracts/SocialRecovery.sol:SocialRecovery"]: SocialRecovery$Type; + } +} diff --git a/eth/artifacts/contracts/mocks/BoundsTestContract.sol/BoundsTestContract.d.ts b/eth/artifacts/contracts/mocks/BoundsTestContract.sol/BoundsTestContract.d.ts new file mode 100644 index 0000000..555d85d --- /dev/null +++ b/eth/artifacts/contracts/mocks/BoundsTestContract.sol/BoundsTestContract.d.ts @@ -0,0 +1,113 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface BoundsTestContract$Type { + "_format": "hh-sol-artifact-1", + "contractName": "BoundsTestContract", + "sourceName": "contracts/mocks/BoundsTestContract.sol", + "abi": [ + { + "inputs": [], + "name": "getCurrentBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedValidFrom", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxFutureBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + } + ], + "name": "validateBounds", + "outputs": [], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60808060405234610016576101be908161001c8239f35b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c9081630fdf57bc14610167575080634cbd355714610129578063672d5d3b1461010e5763db66a2291461004d57600080fd5b3461010b57602036600319011261010b5760043580159081156100df575b50156100745780f35b60405162461bcd60e51b815260206004820152603f60248201527f426f756e6473546573743a2076616c696446726f6d2063616e6e6f742062652060448201527f6d6f7265207468616e203330206461797320696e2074686520667574757265006064820152608490fd5b905062278d004301908143116100f75711153861006b565b634e487b7160e01b83526011600452602483fd5b80fd5b503461010b578060031936011261010b576020604051438152f35b503461010b578060031936011261010b5762278d0043019081431161015357602082604051908152f35b634e487b7160e01b81526011600452602490fd5b9050346101845781600319360112610184578062278d0060209252f35b5080fdfea2646970667358221220c896f410bd8a3062b47b8d4df4e45bd3cb41b5241795bcf6d96850a66302b6e464736f6c63430008140033", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c9081630fdf57bc14610167575080634cbd355714610129578063672d5d3b1461010e5763db66a2291461004d57600080fd5b3461010b57602036600319011261010b5760043580159081156100df575b50156100745780f35b60405162461bcd60e51b815260206004820152603f60248201527f426f756e6473546573743a2076616c696446726f6d2063616e6e6f742062652060448201527f6d6f7265207468616e203330206461797320696e2074686520667574757265006064820152608490fd5b905062278d004301908143116100f75711153861006b565b634e487b7160e01b83526011600452602483fd5b80fd5b503461010b578060031936011261010b576020604051438152f35b503461010b578060031936011261010b5762278d0043019081431161015357602082604051908152f35b634e487b7160e01b81526011600452602490fd5b9050346101845781600319360112610184578062278d0060209252f35b5080fdfea2646970667358221220c896f410bd8a3062b47b8d4df4e45bd3cb41b5241795bcf6d96850a66302b6e464736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "BoundsTestContract", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/mocks/BoundsTestContract.sol:BoundsTestContract", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "BoundsTestContract", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/mocks/BoundsTestContract.sol:BoundsTestContract", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "BoundsTestContract", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/mocks/BoundsTestContract.sol:BoundsTestContract", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/mocks/BoundsTestContract.sol/BoundsTestContract.json b/eth/artifacts/contracts/mocks/BoundsTestContract.sol/BoundsTestContract.json new file mode 100644 index 0000000..d10f895 --- /dev/null +++ b/eth/artifacts/contracts/mocks/BoundsTestContract.sol/BoundsTestContract.json @@ -0,0 +1,63 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BoundsTestContract", + "sourceName": "contracts/mocks/BoundsTestContract.sol", + "abi": [ + { + "inputs": [], + "name": "getCurrentBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxAllowedValidFrom", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxFutureBlocks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + } + ], + "name": "validateBounds", + "outputs": [], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60808060405234610016576101be908161001c8239f35b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c9081630fdf57bc14610167575080634cbd355714610129578063672d5d3b1461010e5763db66a2291461004d57600080fd5b3461010b57602036600319011261010b5760043580159081156100df575b50156100745780f35b60405162461bcd60e51b815260206004820152603f60248201527f426f756e6473546573743a2076616c696446726f6d2063616e6e6f742062652060448201527f6d6f7265207468616e203330206461797320696e2074686520667574757265006064820152608490fd5b905062278d004301908143116100f75711153861006b565b634e487b7160e01b83526011600452602483fd5b80fd5b503461010b578060031936011261010b576020604051438152f35b503461010b578060031936011261010b5762278d0043019081431161015357602082604051908152f35b634e487b7160e01b81526011600452602490fd5b9050346101845781600319360112610184578062278d0060209252f35b5080fdfea2646970667358221220c896f410bd8a3062b47b8d4df4e45bd3cb41b5241795bcf6d96850a66302b6e464736f6c63430008140033", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c9081630fdf57bc14610167575080634cbd355714610129578063672d5d3b1461010e5763db66a2291461004d57600080fd5b3461010b57602036600319011261010b5760043580159081156100df575b50156100745780f35b60405162461bcd60e51b815260206004820152603f60248201527f426f756e6473546573743a2076616c696446726f6d2063616e6e6f742062652060448201527f6d6f7265207468616e203330206461797320696e2074686520667574757265006064820152608490fd5b905062278d004301908143116100f75711153861006b565b634e487b7160e01b83526011600452602483fd5b80fd5b503461010b578060031936011261010b576020604051438152f35b503461010b578060031936011261010b5762278d0043019081431161015357602082604051908152f35b634e487b7160e01b81526011600452602490fd5b9050346101845781600319360112610184578062278d0060209252f35b5080fdfea2646970667358221220c896f410bd8a3062b47b8d4df4e45bd3cb41b5241795bcf6d96850a66302b6e464736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/mocks/BoundsTestContract.sol/artifacts.d.ts b/eth/artifacts/contracts/mocks/BoundsTestContract.sol/artifacts.d.ts new file mode 100644 index 0000000..4d655f8 --- /dev/null +++ b/eth/artifacts/contracts/mocks/BoundsTestContract.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { BoundsTestContract$Type } from "./BoundsTestContract"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["BoundsTestContract"]: BoundsTestContract$Type; + ["contracts/mocks/BoundsTestContract.sol:BoundsTestContract"]: BoundsTestContract$Type; + } +} diff --git a/eth/artifacts/contracts/mocks/MockERC20.sol/MockERC20.d.ts b/eth/artifacts/contracts/mocks/MockERC20.sol/MockERC20.d.ts new file mode 100644 index 0000000..3094170 --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockERC20.sol/MockERC20.d.ts @@ -0,0 +1,445 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface MockERC20$Type { + "_format": "hh-sol-artifact-1", + "contractName": "MockERC20", + "sourceName": "contracts/mocks/MockERC20.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080346200039a576040906001600160401b0390808301828111828210176200029a57835260098152602090684d6f636b205553444360b81b82820152835192848401848110828211176200029a57855260058452644d5553444360d81b8385015281518181116200029a576003908154906001948583811c931680156200038f575b8784101462000379578190601f9384811162000323575b508790848311600114620002bc57600092620002b0575b505060001982851b1c191690851b1782555b85519283116200029a5760049586548581811c911680156200028f575b878210146200027a578281116200022f575b5085918411600114620001c457938394918492600095620001b8575b50501b92600019911b1c19161782555b3315620001a15760025469d3c21bcecceda1000000928382018092116200018c57506000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9160025533835282815284832084815401905584519384523393a35161079f9081620003a08239f35b601190634e487b7160e01b6000525260246000fd5b506000602492519163ec442f0560e01b8352820152fd5b0151935038806200010d565b9190601f198416928760005284876000209460005b8989838310620002175750505010620001fc575b50505050811b0182556200011d565b01519060f884600019921b161c1916905538808080620001ed565b868601518955909701969485019488935001620001d9565b87600052866000208380870160051c82019289881062000270575b0160051c019086905b82811062000263575050620000f1565b6000815501869062000253565b925081926200024a565b602288634e487b7160e01b6000525260246000fd5b90607f1690620000df565b634e487b7160e01b600052604160045260246000fd5b015190503880620000b0565b90879350601f1983169186600052896000209260005b8b8282106200030c5750508411620002f3575b505050811b018255620000c2565b015160001983871b60f8161c19169055388080620002e5565b8385015186558b97909501949384019301620002d2565b90915084600052876000208480850160051c8201928a86106200036f575b918991869594930160051c01915b8281106200035f57505062000099565b600081558594508991016200034f565b9250819262000341565b634e487b7160e01b600052602260045260246000fd5b92607f169262000082565b600080fdfe60806040908082526004918236101561001757600080fd5b600092833560e01c92836306fdde031461053957508263095ea7b31461048e57826318160ddd1461046f57826323b872dd1461037d578263313ce5671461036157826340c10f19146102ba57826370a082311461028357826395d89b411461016457508163a9059cbb14610133578163dd62ed3e146100e6575063ef55bec6146100a057600080fd5b346100e3576101203660031901126100e3576100ba61065a565b6100c2610675565b9060c43560ff8116036100df576100dc916044359161068b565b80f35b8280fd5b80fd5b90503461012f578060031936011261012f578060209261010461065a565b61010c610675565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b90503461012f578060031936011261012f5760209061015d61015361065a565b602435903361068b565b5160018152f35b83823461012f578160031936011261012f57805190828454600181811c90808316928315610279575b60209384841081146102665783885290811561024a57506001146101f5575b505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b0390f35b634e487b7160e01b815260418552602490fd5b8787529192508591837f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b83851061023657505050508301018580806101ac565b805488860183015293019284908201610220565b60ff1916878501525050151560051b84010190508580806101ac565b634e487b7160e01b895260228a52602489fd5b91607f169161018d565b83823461012f57602036600319011261012f5760209181906001600160a01b036102ab61065a565b16815280845220549051908152f35b9150346100df57806003193601126100df576102d461065a565b6001600160a01b0316916024359190831561034c5760025490838201809211610339575084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9260209260025585855284835280852082815401905551908152a380f35b634e487b7160e01b865260119052602485fd5b84602492519163ec442f0560e01b8352820152fd5b83823461012f578160031936011261012f576020905160128152f35b83346100e35760603660031901126100e35761039761065a565b61039f610675565b916044359360018060a01b0383168083526001602052868320338452602052868320549160001983036103db575b60208861015d89898961068b565b86831061044357811561042c5733156104155750825260016020908152868320338452815291869020908590039055829061015d876103cd565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b83823461012f578160031936011261012f576020906002549051908152f35b909150346100df57816003193601126100df576104a961065a565b602435903315610522576001600160a01b031691821561050b57508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b849192346100df57826003193601126100df5782600354600181811c90808316928315610607575b60209384841081146102665783885290811561024a57506001146105b157505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b600387529192508591837fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106105f357505050508301018580806101ac565b8054888601830152930192849082016105dd565b91607f1691610561565b6020808252825181830181905290939260005b82811061064657505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610624565b600435906001600160a01b038216820361067057565b600080fd5b602435906001600160a01b038216820361067057565b916001600160a01b0380841692831561075057169283156107375760009083825281602052604082205490838210610705575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fdfea2646970667358221220bb06dad9f245364a47c2cb49fce76352fce1584dd2b8a9f4f01786d1ffee18ff64736f6c63430008140033", + "deployedBytecode": "0x60806040908082526004918236101561001757600080fd5b600092833560e01c92836306fdde031461053957508263095ea7b31461048e57826318160ddd1461046f57826323b872dd1461037d578263313ce5671461036157826340c10f19146102ba57826370a082311461028357826395d89b411461016457508163a9059cbb14610133578163dd62ed3e146100e6575063ef55bec6146100a057600080fd5b346100e3576101203660031901126100e3576100ba61065a565b6100c2610675565b9060c43560ff8116036100df576100dc916044359161068b565b80f35b8280fd5b80fd5b90503461012f578060031936011261012f578060209261010461065a565b61010c610675565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b90503461012f578060031936011261012f5760209061015d61015361065a565b602435903361068b565b5160018152f35b83823461012f578160031936011261012f57805190828454600181811c90808316928315610279575b60209384841081146102665783885290811561024a57506001146101f5575b505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b0390f35b634e487b7160e01b815260418552602490fd5b8787529192508591837f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b83851061023657505050508301018580806101ac565b805488860183015293019284908201610220565b60ff1916878501525050151560051b84010190508580806101ac565b634e487b7160e01b895260228a52602489fd5b91607f169161018d565b83823461012f57602036600319011261012f5760209181906001600160a01b036102ab61065a565b16815280845220549051908152f35b9150346100df57806003193601126100df576102d461065a565b6001600160a01b0316916024359190831561034c5760025490838201809211610339575084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9260209260025585855284835280852082815401905551908152a380f35b634e487b7160e01b865260119052602485fd5b84602492519163ec442f0560e01b8352820152fd5b83823461012f578160031936011261012f576020905160128152f35b83346100e35760603660031901126100e35761039761065a565b61039f610675565b916044359360018060a01b0383168083526001602052868320338452602052868320549160001983036103db575b60208861015d89898961068b565b86831061044357811561042c5733156104155750825260016020908152868320338452815291869020908590039055829061015d876103cd565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b83823461012f578160031936011261012f576020906002549051908152f35b909150346100df57816003193601126100df576104a961065a565b602435903315610522576001600160a01b031691821561050b57508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b849192346100df57826003193601126100df5782600354600181811c90808316928315610607575b60209384841081146102665783885290811561024a57506001146105b157505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b600387529192508591837fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106105f357505050508301018580806101ac565b8054888601830152930192849082016105dd565b91607f1691610561565b6020808252825181830181905290939260005b82811061064657505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610624565b600435906001600160a01b038216820361067057565b600080fd5b602435906001600160a01b038216820361067057565b916001600160a01b0380841692831561075057169283156107375760009083825281602052604082205490838210610705575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fdfea2646970667358221220bb06dad9f245364a47c2cb49fce76352fce1584dd2b8a9f4f01786d1ffee18ff64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "MockERC20", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/mocks/MockERC20.sol:MockERC20", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "MockERC20", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/mocks/MockERC20.sol:MockERC20", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "MockERC20", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/mocks/MockERC20.sol:MockERC20", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/mocks/MockERC20.sol/MockERC20.json b/eth/artifacts/contracts/mocks/MockERC20.sol/MockERC20.json new file mode 100644 index 0000000..65ff357 --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockERC20.sol/MockERC20.json @@ -0,0 +1,395 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MockERC20", + "sourceName": "contracts/mocks/MockERC20.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080346200039a576040906001600160401b0390808301828111828210176200029a57835260098152602090684d6f636b205553444360b81b82820152835192848401848110828211176200029a57855260058452644d5553444360d81b8385015281518181116200029a576003908154906001948583811c931680156200038f575b8784101462000379578190601f9384811162000323575b508790848311600114620002bc57600092620002b0575b505060001982851b1c191690851b1782555b85519283116200029a5760049586548581811c911680156200028f575b878210146200027a578281116200022f575b5085918411600114620001c457938394918492600095620001b8575b50501b92600019911b1c19161782555b3315620001a15760025469d3c21bcecceda1000000928382018092116200018c57506000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9160025533835282815284832084815401905584519384523393a35161079f9081620003a08239f35b601190634e487b7160e01b6000525260246000fd5b506000602492519163ec442f0560e01b8352820152fd5b0151935038806200010d565b9190601f198416928760005284876000209460005b8989838310620002175750505010620001fc575b50505050811b0182556200011d565b01519060f884600019921b161c1916905538808080620001ed565b868601518955909701969485019488935001620001d9565b87600052866000208380870160051c82019289881062000270575b0160051c019086905b82811062000263575050620000f1565b6000815501869062000253565b925081926200024a565b602288634e487b7160e01b6000525260246000fd5b90607f1690620000df565b634e487b7160e01b600052604160045260246000fd5b015190503880620000b0565b90879350601f1983169186600052896000209260005b8b8282106200030c5750508411620002f3575b505050811b018255620000c2565b015160001983871b60f8161c19169055388080620002e5565b8385015186558b97909501949384019301620002d2565b90915084600052876000208480850160051c8201928a86106200036f575b918991869594930160051c01915b8281106200035f57505062000099565b600081558594508991016200034f565b9250819262000341565b634e487b7160e01b600052602260045260246000fd5b92607f169262000082565b600080fdfe60806040908082526004918236101561001757600080fd5b600092833560e01c92836306fdde031461053957508263095ea7b31461048e57826318160ddd1461046f57826323b872dd1461037d578263313ce5671461036157826340c10f19146102ba57826370a082311461028357826395d89b411461016457508163a9059cbb14610133578163dd62ed3e146100e6575063ef55bec6146100a057600080fd5b346100e3576101203660031901126100e3576100ba61065a565b6100c2610675565b9060c43560ff8116036100df576100dc916044359161068b565b80f35b8280fd5b80fd5b90503461012f578060031936011261012f578060209261010461065a565b61010c610675565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b90503461012f578060031936011261012f5760209061015d61015361065a565b602435903361068b565b5160018152f35b83823461012f578160031936011261012f57805190828454600181811c90808316928315610279575b60209384841081146102665783885290811561024a57506001146101f5575b505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b0390f35b634e487b7160e01b815260418552602490fd5b8787529192508591837f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b83851061023657505050508301018580806101ac565b805488860183015293019284908201610220565b60ff1916878501525050151560051b84010190508580806101ac565b634e487b7160e01b895260228a52602489fd5b91607f169161018d565b83823461012f57602036600319011261012f5760209181906001600160a01b036102ab61065a565b16815280845220549051908152f35b9150346100df57806003193601126100df576102d461065a565b6001600160a01b0316916024359190831561034c5760025490838201809211610339575084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9260209260025585855284835280852082815401905551908152a380f35b634e487b7160e01b865260119052602485fd5b84602492519163ec442f0560e01b8352820152fd5b83823461012f578160031936011261012f576020905160128152f35b83346100e35760603660031901126100e35761039761065a565b61039f610675565b916044359360018060a01b0383168083526001602052868320338452602052868320549160001983036103db575b60208861015d89898961068b565b86831061044357811561042c5733156104155750825260016020908152868320338452815291869020908590039055829061015d876103cd565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b83823461012f578160031936011261012f576020906002549051908152f35b909150346100df57816003193601126100df576104a961065a565b602435903315610522576001600160a01b031691821561050b57508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b849192346100df57826003193601126100df5782600354600181811c90808316928315610607575b60209384841081146102665783885290811561024a57506001146105b157505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b600387529192508591837fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106105f357505050508301018580806101ac565b8054888601830152930192849082016105dd565b91607f1691610561565b6020808252825181830181905290939260005b82811061064657505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610624565b600435906001600160a01b038216820361067057565b600080fd5b602435906001600160a01b038216820361067057565b916001600160a01b0380841692831561075057169283156107375760009083825281602052604082205490838210610705575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fdfea2646970667358221220bb06dad9f245364a47c2cb49fce76352fce1584dd2b8a9f4f01786d1ffee18ff64736f6c63430008140033", + "deployedBytecode": "0x60806040908082526004918236101561001757600080fd5b600092833560e01c92836306fdde031461053957508263095ea7b31461048e57826318160ddd1461046f57826323b872dd1461037d578263313ce5671461036157826340c10f19146102ba57826370a082311461028357826395d89b411461016457508163a9059cbb14610133578163dd62ed3e146100e6575063ef55bec6146100a057600080fd5b346100e3576101203660031901126100e3576100ba61065a565b6100c2610675565b9060c43560ff8116036100df576100dc916044359161068b565b80f35b8280fd5b80fd5b90503461012f578060031936011261012f578060209261010461065a565b61010c610675565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b5080fd5b90503461012f578060031936011261012f5760209061015d61015361065a565b602435903361068b565b5160018152f35b83823461012f578160031936011261012f57805190828454600181811c90808316928315610279575b60209384841081146102665783885290811561024a57506001146101f5575b505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b0390f35b634e487b7160e01b815260418552602490fd5b8787529192508591837f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5b83851061023657505050508301018580806101ac565b805488860183015293019284908201610220565b60ff1916878501525050151560051b84010190508580806101ac565b634e487b7160e01b895260228a52602489fd5b91607f169161018d565b83823461012f57602036600319011261012f5760209181906001600160a01b036102ab61065a565b16815280845220549051908152f35b9150346100df57806003193601126100df576102d461065a565b6001600160a01b0316916024359190831561034c5760025490838201809211610339575084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9260209260025585855284835280852082815401905551908152a380f35b634e487b7160e01b865260119052602485fd5b84602492519163ec442f0560e01b8352820152fd5b83823461012f578160031936011261012f576020905160128152f35b83346100e35760603660031901126100e35761039761065a565b61039f610675565b916044359360018060a01b0383168083526001602052868320338452602052868320549160001983036103db575b60208861015d89898961068b565b86831061044357811561042c5733156104155750825260016020908152868320338452815291869020908590039055829061015d876103cd565b8751634a1406b160e11b8152908101849052602490fd5b875163e602df0560e01b8152908101849052602490fd5b8751637dc7a0d960e11b8152339181019182526020820193909352604081018790528291506060010390fd5b83823461012f578160031936011261012f576020906002549051908152f35b909150346100df57816003193601126100df576104a961065a565b602435903315610522576001600160a01b031691821561050b57508083602095338152600187528181208582528752205582519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925843392a35160018152f35b8351634a1406b160e11b8152908101859052602490fd5b835163e602df0560e01b8152808401869052602490fd5b849192346100df57826003193601126100df5782600354600181811c90808316928315610607575b60209384841081146102665783885290811561024a57506001146105b157505050829003601f01601f191682019267ffffffffffffffff8411838510176101e257508291826101de925282610611565b600387529192508591837fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b5b8385106105f357505050508301018580806101ac565b8054888601830152930192849082016105dd565b91607f1691610561565b6020808252825181830181905290939260005b82811061064657505060409293506000838284010152601f8019910116010190565b818101860151848201604001528501610624565b600435906001600160a01b038216820361067057565b600080fd5b602435906001600160a01b038216820361067057565b916001600160a01b0380841692831561075057169283156107375760009083825281602052604082205490838210610705575091604082827fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef958760209652828652038282205586815220818154019055604051908152a3565b60405163391434e360e21b81526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b60405163ec442f0560e01b815260006004820152602490fd5b604051634b637e8f60e11b815260006004820152602490fdfea2646970667358221220bb06dad9f245364a47c2cb49fce76352fce1584dd2b8a9f4f01786d1ffee18ff64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/mocks/MockERC20.sol/artifacts.d.ts b/eth/artifacts/contracts/mocks/MockERC20.sol/artifacts.d.ts new file mode 100644 index 0000000..f259ab5 --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockERC20.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { MockERC20$Type } from "./MockERC20"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["MockERC20"]: MockERC20$Type; + ["contracts/mocks/MockERC20.sol:MockERC20"]: MockERC20$Type; + } +} diff --git a/eth/artifacts/contracts/mocks/MockUSDC.sol/MockUSDC.d.ts b/eth/artifacts/contracts/mocks/MockUSDC.sol/MockUSDC.d.ts new file mode 100644 index 0000000..0a9ac4e --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockUSDC.sol/MockUSDC.d.ts @@ -0,0 +1,509 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface MockUSDC$Type { + "_format": "hh-sol-artifact-1", + "contractName": "MockUSDC", + "sourceName": "contracts/mocks/MockUSDC.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "configureMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "initializeV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "initializeV2_1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "isBlacklisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080604052346101275761001460045461012c565b601f81116100da575b507f4d6f636b2055534443000000000000000000000000000000000000000000001260045560055461004e9061012c565b601f811161008e575b600a644d5553444360d81b0160055564e8d4a510008060035533600052600060205260406000205560405161070590816101678239f35b6005600081815291601f01901c7f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0908101905b8181106100cf575050610057565b8281556001016100c1565b6004600090815290601f0160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b908101905b81811061011c57505061001d565b82815560010161010e565b600080fd5b90600182811c9216801561015c575b602083101461014657565b634e487b7160e01b600052602260045260246000fd5b91607f169161013b56fe608060408181526004918236101561001657600080fd5b600092833560e01c918263095ea7b3146104dd5750816318160ddd146104be57816323b872dd146103d25781632fc81e09146103b45781633357162b1461030d5781633644e515146102d257816340c10f191461027b5781634e44d9561461025657816370a082311461021f578163a9059cbb146101ac578163d608ea641461015757508063dd62ed3e1461010f578063e3ee160e1461010a578063ef55bec61461010a5763fe575a87146100ca57600080fd5b346101065760203660031901126101065760209160ff9082906001600160a01b036100f3610522565b1681526002855220541690519015158152f35b5080fd5b6105cc565b50346101065780600319360112610106578060209261012c610522565b61013461053d565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b8390346101065760203660031901126101065780359067ffffffffffffffff908183116101a857366023840112156101a8578201359081116101a457369101602401116101a15780f35b80fd5b8280fd5b8380fd5b505034610106578060031936011261010657602091610216826101cd610522565b92602435933382528187526101e78584842054101561065c565b3382528187528282206101fb86825461069f565b90556001600160a01b031681528086522080549092906106c2565b90555160018152f35b5050346101065760203660031901126101065760209181906001600160a01b03610247610522565b16815280845220549051908152f35b505034610106578060031936011261010657602090610273610522565b505160018152f35b5050346101065780600319360112610106576102c86020928261029c610522565b6001600160a01b031682528185529020805460243591906102be9083906106c2565b90556003546106c2565b6003555160018152f35b505034610106578160031936011261010657602090517f1fb5af8b887c78975d760f6cf1fce6ed287528d974b7d0d927568c39ace376088152f35b839034610106576101003660031901126101065767ffffffffffffffff9080358281116101a8576103419036908301610553565b506024358281116101a8576103599036908301610553565b506044359182116101a45761037091369101610553565b5060643560ff8116036101a1576001600160a01b03608435818116036101065760a435818116036101065760c435818116036101065760e435908116036101a15780f35b83346101a15760203660031901126101a1576103ce610522565b5080f35b8284346101a15760603660031901126101a1576103ed610522565b906103f661053d565b916044359260018060a01b038092168084526020966001885286852033865288528587862054106104825750918391838794610216965283895261043f8786862054101561065c565b80845260018952848420338552895284842061045c88825461069f565b9055835282885283832061047187825461069f565b9055168152808652209182546106c2565b865162461bcd60e51b81529081018890526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606490fd5b5050346101065781600319360112610106576020906003549051908152f35b849084346101a457806003193601126101a457916020926104fc610522565b33835260018086528284206001600160a01b039092168452908552912060243590558152f35b600435906001600160a01b038216820361053857565b600080fd5b602435906001600160a01b038216820361053857565b81601f820112156105385780359067ffffffffffffffff928383116105b65760405193601f8401601f19908116603f01168501908111858210176105b6576040528284526020838301011161053857816000926020809301838601378301015290565b634e487b7160e01b600052604160045260246000fd5b3461053857610120366003190112610538576004356001600160a01b038181169182900361053857602435908116809103610538576044359060c43560ff811603610538576000928084528360205261062b836040862054101561065c565b8352826020526040832061064083825461069f565b9055825281602052610657604083209182546106c2565b905580f35b1561066357565b60405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606490fd5b919082039182116106ac57565b634e487b7160e01b600052601160045260246000fd5b919082018092116106ac5756fea26469706673582212209216b16a2573974aa733c646337e75f213e5355f6d2c467b3951da5f3e2d3e6a64736f6c63430008140033", + "deployedBytecode": "0x608060408181526004918236101561001657600080fd5b600092833560e01c918263095ea7b3146104dd5750816318160ddd146104be57816323b872dd146103d25781632fc81e09146103b45781633357162b1461030d5781633644e515146102d257816340c10f191461027b5781634e44d9561461025657816370a082311461021f578163a9059cbb146101ac578163d608ea641461015757508063dd62ed3e1461010f578063e3ee160e1461010a578063ef55bec61461010a5763fe575a87146100ca57600080fd5b346101065760203660031901126101065760209160ff9082906001600160a01b036100f3610522565b1681526002855220541690519015158152f35b5080fd5b6105cc565b50346101065780600319360112610106578060209261012c610522565b61013461053d565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b8390346101065760203660031901126101065780359067ffffffffffffffff908183116101a857366023840112156101a8578201359081116101a457369101602401116101a15780f35b80fd5b8280fd5b8380fd5b505034610106578060031936011261010657602091610216826101cd610522565b92602435933382528187526101e78584842054101561065c565b3382528187528282206101fb86825461069f565b90556001600160a01b031681528086522080549092906106c2565b90555160018152f35b5050346101065760203660031901126101065760209181906001600160a01b03610247610522565b16815280845220549051908152f35b505034610106578060031936011261010657602090610273610522565b505160018152f35b5050346101065780600319360112610106576102c86020928261029c610522565b6001600160a01b031682528185529020805460243591906102be9083906106c2565b90556003546106c2565b6003555160018152f35b505034610106578160031936011261010657602090517f1fb5af8b887c78975d760f6cf1fce6ed287528d974b7d0d927568c39ace376088152f35b839034610106576101003660031901126101065767ffffffffffffffff9080358281116101a8576103419036908301610553565b506024358281116101a8576103599036908301610553565b506044359182116101a45761037091369101610553565b5060643560ff8116036101a1576001600160a01b03608435818116036101065760a435818116036101065760c435818116036101065760e435908116036101a15780f35b83346101a15760203660031901126101a1576103ce610522565b5080f35b8284346101a15760603660031901126101a1576103ed610522565b906103f661053d565b916044359260018060a01b038092168084526020966001885286852033865288528587862054106104825750918391838794610216965283895261043f8786862054101561065c565b80845260018952848420338552895284842061045c88825461069f565b9055835282885283832061047187825461069f565b9055168152808652209182546106c2565b865162461bcd60e51b81529081018890526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606490fd5b5050346101065781600319360112610106576020906003549051908152f35b849084346101a457806003193601126101a457916020926104fc610522565b33835260018086528284206001600160a01b039092168452908552912060243590558152f35b600435906001600160a01b038216820361053857565b600080fd5b602435906001600160a01b038216820361053857565b81601f820112156105385780359067ffffffffffffffff928383116105b65760405193601f8401601f19908116603f01168501908111858210176105b6576040528284526020838301011161053857816000926020809301838601378301015290565b634e487b7160e01b600052604160045260246000fd5b3461053857610120366003190112610538576004356001600160a01b038181169182900361053857602435908116809103610538576044359060c43560ff811603610538576000928084528360205261062b836040862054101561065c565b8352826020526040832061064083825461069f565b9055825281602052610657604083209182546106c2565b905580f35b1561066357565b60405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606490fd5b919082039182116106ac57565b634e487b7160e01b600052601160045260246000fd5b919082018092116106ac5756fea26469706673582212209216b16a2573974aa733c646337e75f213e5355f6d2c467b3951da5f3e2d3e6a64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "MockUSDC", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/mocks/MockUSDC.sol:MockUSDC", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "MockUSDC", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/mocks/MockUSDC.sol:MockUSDC", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "MockUSDC", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/mocks/MockUSDC.sol:MockUSDC", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/mocks/MockUSDC.sol/MockUSDC.json b/eth/artifacts/contracts/mocks/MockUSDC.sol/MockUSDC.json new file mode 100644 index 0000000..c85ba3b --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockUSDC.sol/MockUSDC.json @@ -0,0 +1,459 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MockUSDC", + "sourceName": "contracts/mocks/MockUSDC.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "configureMinter", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "string", + "name": "", + "type": "string" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "initializeV2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "initializeV2_1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + } + ], + "name": "isBlacklisted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "receiveWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "transferWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080604052346101275761001460045461012c565b601f81116100da575b507f4d6f636b2055534443000000000000000000000000000000000000000000001260045560055461004e9061012c565b601f811161008e575b600a644d5553444360d81b0160055564e8d4a510008060035533600052600060205260406000205560405161070590816101678239f35b6005600081815291601f01901c7f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db0908101905b8181106100cf575050610057565b8281556001016100c1565b6004600090815290601f0160051c7f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b908101905b81811061011c57505061001d565b82815560010161010e565b600080fd5b90600182811c9216801561015c575b602083101461014657565b634e487b7160e01b600052602260045260246000fd5b91607f169161013b56fe608060408181526004918236101561001657600080fd5b600092833560e01c918263095ea7b3146104dd5750816318160ddd146104be57816323b872dd146103d25781632fc81e09146103b45781633357162b1461030d5781633644e515146102d257816340c10f191461027b5781634e44d9561461025657816370a082311461021f578163a9059cbb146101ac578163d608ea641461015757508063dd62ed3e1461010f578063e3ee160e1461010a578063ef55bec61461010a5763fe575a87146100ca57600080fd5b346101065760203660031901126101065760209160ff9082906001600160a01b036100f3610522565b1681526002855220541690519015158152f35b5080fd5b6105cc565b50346101065780600319360112610106578060209261012c610522565b61013461053d565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b8390346101065760203660031901126101065780359067ffffffffffffffff908183116101a857366023840112156101a8578201359081116101a457369101602401116101a15780f35b80fd5b8280fd5b8380fd5b505034610106578060031936011261010657602091610216826101cd610522565b92602435933382528187526101e78584842054101561065c565b3382528187528282206101fb86825461069f565b90556001600160a01b031681528086522080549092906106c2565b90555160018152f35b5050346101065760203660031901126101065760209181906001600160a01b03610247610522565b16815280845220549051908152f35b505034610106578060031936011261010657602090610273610522565b505160018152f35b5050346101065780600319360112610106576102c86020928261029c610522565b6001600160a01b031682528185529020805460243591906102be9083906106c2565b90556003546106c2565b6003555160018152f35b505034610106578160031936011261010657602090517f1fb5af8b887c78975d760f6cf1fce6ed287528d974b7d0d927568c39ace376088152f35b839034610106576101003660031901126101065767ffffffffffffffff9080358281116101a8576103419036908301610553565b506024358281116101a8576103599036908301610553565b506044359182116101a45761037091369101610553565b5060643560ff8116036101a1576001600160a01b03608435818116036101065760a435818116036101065760c435818116036101065760e435908116036101a15780f35b83346101a15760203660031901126101a1576103ce610522565b5080f35b8284346101a15760603660031901126101a1576103ed610522565b906103f661053d565b916044359260018060a01b038092168084526020966001885286852033865288528587862054106104825750918391838794610216965283895261043f8786862054101561065c565b80845260018952848420338552895284842061045c88825461069f565b9055835282885283832061047187825461069f565b9055168152808652209182546106c2565b865162461bcd60e51b81529081018890526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606490fd5b5050346101065781600319360112610106576020906003549051908152f35b849084346101a457806003193601126101a457916020926104fc610522565b33835260018086528284206001600160a01b039092168452908552912060243590558152f35b600435906001600160a01b038216820361053857565b600080fd5b602435906001600160a01b038216820361053857565b81601f820112156105385780359067ffffffffffffffff928383116105b65760405193601f8401601f19908116603f01168501908111858210176105b6576040528284526020838301011161053857816000926020809301838601378301015290565b634e487b7160e01b600052604160045260246000fd5b3461053857610120366003190112610538576004356001600160a01b038181169182900361053857602435908116809103610538576044359060c43560ff811603610538576000928084528360205261062b836040862054101561065c565b8352826020526040832061064083825461069f565b9055825281602052610657604083209182546106c2565b905580f35b1561066357565b60405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606490fd5b919082039182116106ac57565b634e487b7160e01b600052601160045260246000fd5b919082018092116106ac5756fea26469706673582212209216b16a2573974aa733c646337e75f213e5355f6d2c467b3951da5f3e2d3e6a64736f6c63430008140033", + "deployedBytecode": "0x608060408181526004918236101561001657600080fd5b600092833560e01c918263095ea7b3146104dd5750816318160ddd146104be57816323b872dd146103d25781632fc81e09146103b45781633357162b1461030d5781633644e515146102d257816340c10f191461027b5781634e44d9561461025657816370a082311461021f578163a9059cbb146101ac578163d608ea641461015757508063dd62ed3e1461010f578063e3ee160e1461010a578063ef55bec61461010a5763fe575a87146100ca57600080fd5b346101065760203660031901126101065760209160ff9082906001600160a01b036100f3610522565b1681526002855220541690519015158152f35b5080fd5b6105cc565b50346101065780600319360112610106578060209261012c610522565b61013461053d565b6001600160a01b0391821683526001865283832091168252845220549051908152f35b8390346101065760203660031901126101065780359067ffffffffffffffff908183116101a857366023840112156101a8578201359081116101a457369101602401116101a15780f35b80fd5b8280fd5b8380fd5b505034610106578060031936011261010657602091610216826101cd610522565b92602435933382528187526101e78584842054101561065c565b3382528187528282206101fb86825461069f565b90556001600160a01b031681528086522080549092906106c2565b90555160018152f35b5050346101065760203660031901126101065760209181906001600160a01b03610247610522565b16815280845220549051908152f35b505034610106578060031936011261010657602090610273610522565b505160018152f35b5050346101065780600319360112610106576102c86020928261029c610522565b6001600160a01b031682528185529020805460243591906102be9083906106c2565b90556003546106c2565b6003555160018152f35b505034610106578160031936011261010657602090517f1fb5af8b887c78975d760f6cf1fce6ed287528d974b7d0d927568c39ace376088152f35b839034610106576101003660031901126101065767ffffffffffffffff9080358281116101a8576103419036908301610553565b506024358281116101a8576103599036908301610553565b506044359182116101a45761037091369101610553565b5060643560ff8116036101a1576001600160a01b03608435818116036101065760a435818116036101065760c435818116036101065760e435908116036101a15780f35b83346101a15760203660031901126101a1576103ce610522565b5080f35b8284346101a15760603660031901126101a1576103ed610522565b906103f661053d565b916044359260018060a01b038092168084526020966001885286852033865288528587862054106104825750918391838794610216965283895261043f8786862054101561065c565b80845260018952848420338552895284842061045c88825461069f565b9055835282885283832061047187825461069f565b9055168152808652209182546106c2565b865162461bcd60e51b81529081018890526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606490fd5b5050346101065781600319360112610106576020906003549051908152f35b849084346101a457806003193601126101a457916020926104fc610522565b33835260018086528284206001600160a01b039092168452908552912060243590558152f35b600435906001600160a01b038216820361053857565b600080fd5b602435906001600160a01b038216820361053857565b81601f820112156105385780359067ffffffffffffffff928383116105b65760405193601f8401601f19908116603f01168501908111858210176105b6576040528284526020838301011161053857816000926020809301838601378301015290565b634e487b7160e01b600052604160045260246000fd5b3461053857610120366003190112610538576004356001600160a01b038181169182900361053857602435908116809103610538576044359060c43560ff811603610538576000928084528360205261062b836040862054101561065c565b8352826020526040832061064083825461069f565b9055825281602052610657604083209182546106c2565b905580f35b1561066357565b60405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606490fd5b919082039182116106ac57565b634e487b7160e01b600052601160045260246000fd5b919082018092116106ac5756fea26469706673582212209216b16a2573974aa733c646337e75f213e5355f6d2c467b3951da5f3e2d3e6a64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/mocks/MockUSDC.sol/artifacts.d.ts b/eth/artifacts/contracts/mocks/MockUSDC.sol/artifacts.d.ts new file mode 100644 index 0000000..1503b81 --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockUSDC.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { MockUSDC$Type } from "./MockUSDC"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["MockUSDC"]: MockUSDC$Type; + ["contracts/mocks/MockUSDC.sol:MockUSDC"]: MockUSDC$Type; + } +} diff --git a/eth/artifacts/contracts/mocks/MockVerifier.sol/MockVerifier.d.ts b/eth/artifacts/contracts/mocks/MockVerifier.sol/MockVerifier.d.ts new file mode 100644 index 0000000..b069932 --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockVerifier.sol/MockVerifier.d.ts @@ -0,0 +1,85 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface MockVerifier$Type { + "_format": "hh-sol-artifact-1", + "contractName": "MockVerifier", + "sourceName": "contracts/mocks/MockVerifier.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "publicInputs", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x608080604052346100155760e3908161001b8239f35b600080fdfe6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220546453462175785a0214661852d377fbfc6dcddac6b9a803594038f03a9bae7464736f6c63430008140033", + "deployedBytecode": "0x6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220546453462175785a0214661852d377fbfc6dcddac6b9a803594038f03a9bae7464736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "MockVerifier", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/mocks/MockVerifier.sol:MockVerifier", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "MockVerifier", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/mocks/MockVerifier.sol:MockVerifier", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "MockVerifier", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/mocks/MockVerifier.sol:MockVerifier", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/mocks/MockVerifier.sol/MockVerifier.json b/eth/artifacts/contracts/mocks/MockVerifier.sol/MockVerifier.json new file mode 100644 index 0000000..f85fb16 --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockVerifier.sol/MockVerifier.json @@ -0,0 +1,35 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "MockVerifier", + "sourceName": "contracts/mocks/MockVerifier.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "publicInputs", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": "0x608080604052346100155760e3908161001b8239f35b600080fdfe6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220546453462175785a0214661852d377fbfc6dcddac6b9a803594038f03a9bae7464736f6c63430008140033", + "deployedBytecode": "0x6080806040526004361015601257600080fd5b600090813560e01c63ea50d0e414602857600080fd5b34609d576040366003190112609d5767ffffffffffffffff60043581811160a1573660238201121560a157806004013582811160a9573691016024011160a55760243581811160a1573660238201121560a157806004013591821160a157602490369260051b010111609d5780600160209252f35b5080fd5b8380fd5b8280fd5b8480fdfea2646970667358221220546453462175785a0214661852d377fbfc6dcddac6b9a803594038f03a9bae7464736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/mocks/MockVerifier.sol/artifacts.d.ts b/eth/artifacts/contracts/mocks/MockVerifier.sol/artifacts.d.ts new file mode 100644 index 0000000..5c5ceb8 --- /dev/null +++ b/eth/artifacts/contracts/mocks/MockVerifier.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { MockVerifier$Type } from "./MockVerifier"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["MockVerifier"]: MockVerifier$Type; + ["contracts/mocks/MockVerifier.sol:MockVerifier"]: MockVerifier$Type; + } +} diff --git a/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/RollupMigrationMock.d.ts b/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/RollupMigrationMock.d.ts new file mode 100644 index 0000000..35d2b88 --- /dev/null +++ b/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/RollupMigrationMock.d.ts @@ -0,0 +1,245 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface RollupMigrationMock$Type { + "_format": "hh-sol-artifact-1", + "contractName": "RollupMigrationMock", + "sourceName": "contracts/mocks/RollupMigrationMock.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "MintAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "Minted", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "emitMintAdded", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "emitMinted", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getMint", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "internalType": "struct RollupMigrationMock.Mint", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "mints", + "outputs": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60808060405234610016576102c5908161001c8239f35b600080fdfe604060808152600436101561001357600080fd5b600090813560e01c8063059236d2146101f25780634eeb381e1461016957806356dc63cb14610125578063a2ce9c1f146100b15763df9bc5ad1461005657600080fd5b346100ad577f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a506100853661023a565b8286526020868152858720600201805460ff191660011790558551928352820152909290a280f35b5080fd5b50346100ad5760203660031901126100ad578082606093826100d1610259565b828152826020820152015260043581528060205220906100ef610259565b8254928382528260ff60026001840154936020860194855201541692019115158252825193845251602084015251151590820152f35b50346100ad5760203660031901126100ad5780606092600435815280602052209081549160ff60026001830154920154169082519384526020840152151590820152f35b50346100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f16101993661023a565b6101e46101a7959395610259565b828152600260208201858152868301908a8252898b528a602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346100ad5760603660031901126100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1600435916024356044356101e46101a7610259565b606090600319011261025457600435906024359060443590565b600080fd5b604051906060820182811067ffffffffffffffff82111761027957604052565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220271435c0ecba7c405943457e753a7704b4092ec92b4e593f557011ff63780a9d64736f6c63430008140033", + "deployedBytecode": "0x604060808152600436101561001357600080fd5b600090813560e01c8063059236d2146101f25780634eeb381e1461016957806356dc63cb14610125578063a2ce9c1f146100b15763df9bc5ad1461005657600080fd5b346100ad577f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a506100853661023a565b8286526020868152858720600201805460ff191660011790558551928352820152909290a280f35b5080fd5b50346100ad5760203660031901126100ad578082606093826100d1610259565b828152826020820152015260043581528060205220906100ef610259565b8254928382528260ff60026001840154936020860194855201541692019115158252825193845251602084015251151590820152f35b50346100ad5760203660031901126100ad5780606092600435815280602052209081549160ff60026001830154920154169082519384526020840152151590820152f35b50346100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f16101993661023a565b6101e46101a7959395610259565b828152600260208201858152868301908a8252898b528a602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346100ad5760603660031901126100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1600435916024356044356101e46101a7610259565b606090600319011261025457600435906024359060443590565b600080fd5b604051906060820182811067ffffffffffffffff82111761027957604052565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220271435c0ecba7c405943457e753a7704b4092ec92b4e593f557011ff63780a9d64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "RollupMigrationMock", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/mocks/RollupMigrationMock.sol:RollupMigrationMock", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "RollupMigrationMock", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/mocks/RollupMigrationMock.sol:RollupMigrationMock", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "RollupMigrationMock", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/mocks/RollupMigrationMock.sol:RollupMigrationMock", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/RollupMigrationMock.json b/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/RollupMigrationMock.json new file mode 100644 index 0000000..a4cdd5c --- /dev/null +++ b/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/RollupMigrationMock.json @@ -0,0 +1,195 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RollupMigrationMock", + "sourceName": "contracts/mocks/RollupMigrationMock.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "MintAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "Minted", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "emitMintAdded", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "emitMinted", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getMint", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "internalType": "struct RollupMigrationMock.Mint", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "mints", + "outputs": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60808060405234610016576102c5908161001c8239f35b600080fdfe604060808152600436101561001357600080fd5b600090813560e01c8063059236d2146101f25780634eeb381e1461016957806356dc63cb14610125578063a2ce9c1f146100b15763df9bc5ad1461005657600080fd5b346100ad577f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a506100853661023a565b8286526020868152858720600201805460ff191660011790558551928352820152909290a280f35b5080fd5b50346100ad5760203660031901126100ad578082606093826100d1610259565b828152826020820152015260043581528060205220906100ef610259565b8254928382528260ff60026001840154936020860194855201541692019115158252825193845251602084015251151590820152f35b50346100ad5760203660031901126100ad5780606092600435815280602052209081549160ff60026001830154920154169082519384526020840152151590820152f35b50346100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f16101993661023a565b6101e46101a7959395610259565b828152600260208201858152868301908a8252898b528a602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346100ad5760603660031901126100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1600435916024356044356101e46101a7610259565b606090600319011261025457600435906024359060443590565b600080fd5b604051906060820182811067ffffffffffffffff82111761027957604052565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220271435c0ecba7c405943457e753a7704b4092ec92b4e593f557011ff63780a9d64736f6c63430008140033", + "deployedBytecode": "0x604060808152600436101561001357600080fd5b600090813560e01c8063059236d2146101f25780634eeb381e1461016957806356dc63cb14610125578063a2ce9c1f146100b15763df9bc5ad1461005657600080fd5b346100ad577f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a506100853661023a565b8286526020868152858720600201805460ff191660011790558551928352820152909290a280f35b5080fd5b50346100ad5760203660031901126100ad578082606093826100d1610259565b828152826020820152015260043581528060205220906100ef610259565b8254928382528260ff60026001840154936020860194855201541692019115158252825193845251602084015251151590820152f35b50346100ad5760203660031901126100ad5780606092600435815280602052209081549160ff60026001830154920154169082519384526020840152151590820152f35b50346100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f16101993661023a565b6101e46101a7959395610259565b828152600260208201858152868301908a8252898b528a602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346100ad5760603660031901126100ad577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1600435916024356044356101e46101a7610259565b606090600319011261025457600435906024359060443590565b600080fd5b604051906060820182811067ffffffffffffffff82111761027957604052565b634e487b7160e01b600052604160045260246000fdfea2646970667358221220271435c0ecba7c405943457e753a7704b4092ec92b4e593f557011ff63780a9d64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/artifacts.d.ts b/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/artifacts.d.ts new file mode 100644 index 0000000..6bbe0c5 --- /dev/null +++ b/eth/artifacts/contracts/mocks/RollupMigrationMock.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { RollupMigrationMock$Type } from "./RollupMigrationMock"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["RollupMigrationMock"]: RollupMigrationMock$Type; + ["contracts/mocks/RollupMigrationMock.sol:RollupMigrationMock"]: RollupMigrationMock$Type; + } +} diff --git a/eth/artifacts/contracts/mocks/TestRollupV1.sol/TestRollupV1.d.ts b/eth/artifacts/contracts/mocks/TestRollupV1.sol/TestRollupV1.d.ts new file mode 100644 index 0000000..2fc2a03 --- /dev/null +++ b/eth/artifacts/contracts/mocks/TestRollupV1.sol/TestRollupV1.d.ts @@ -0,0 +1,84 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface TestRollupV1$Type { + "_format": "hh-sol-artifact-1", + "contractName": "TestRollupV1", + "sourceName": "contracts/mocks/TestRollupV1.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "setValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080806040523461001657610161908161001c8239f35b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c63e795594d1461002a57600080fd5b346101275760403660031901126101275760043567ffffffffffffffff602435818111610123573660238201121561012357806004013591821161012357602490369260051b01011161011f5780159081156100f3575b501561008b575080f35b62461bcd60e51b815260206004820152603d60248201527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b905062278d0043019081431161010b57111538610081565b634e487b7160e01b84526011600452602484fd5b8280fd5b8480fd5b5080fdfea2646970667358221220779c814224cc88f0ac26bde1c217a37b705479eb6e037ba7bdc64d6b89880b0964736f6c63430008140033", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c63e795594d1461002a57600080fd5b346101275760403660031901126101275760043567ffffffffffffffff602435818111610123573660238201121561012357806004013591821161012357602490369260051b01011161011f5780159081156100f3575b501561008b575080f35b62461bcd60e51b815260206004820152603d60248201527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b905062278d0043019081431161010b57111538610081565b634e487b7160e01b84526011600452602484fd5b8280fd5b8480fd5b5080fdfea2646970667358221220779c814224cc88f0ac26bde1c217a37b705479eb6e037ba7bdc64d6b89880b0964736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "TestRollupV1", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/mocks/TestRollupV1.sol:TestRollupV1", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "TestRollupV1", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/mocks/TestRollupV1.sol:TestRollupV1", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "TestRollupV1", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/mocks/TestRollupV1.sol:TestRollupV1", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/mocks/TestRollupV1.sol/TestRollupV1.json b/eth/artifacts/contracts/mocks/TestRollupV1.sol/TestRollupV1.json new file mode 100644 index 0000000..d9585a7 --- /dev/null +++ b/eth/artifacts/contracts/mocks/TestRollupV1.sol/TestRollupV1.json @@ -0,0 +1,34 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TestRollupV1", + "sourceName": "contracts/mocks/TestRollupV1.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "setValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x6080806040523461001657610161908161001c8239f35b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c63e795594d1461002a57600080fd5b346101275760403660031901126101275760043567ffffffffffffffff602435818111610123573660238201121561012357806004013591821161012357602490369260051b01011161011f5780159081156100f3575b501561008b575080f35b62461bcd60e51b815260206004820152603d60248201527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b905062278d0043019081431161010b57111538610081565b634e487b7160e01b84526011600452602484fd5b8280fd5b8480fd5b5080fdfea2646970667358221220779c814224cc88f0ac26bde1c217a37b705479eb6e037ba7bdc64d6b89880b0964736f6c63430008140033", + "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c63e795594d1461002a57600080fd5b346101275760403660031901126101275760043567ffffffffffffffff602435818111610123573660238201121561012357806004013591821161012357602490369260051b01011161011f5780159081156100f3575b501561008b575080f35b62461bcd60e51b815260206004820152603d60248201527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b905062278d0043019081431161010b57111538610081565b634e487b7160e01b84526011600452602484fd5b8280fd5b8480fd5b5080fdfea2646970667358221220779c814224cc88f0ac26bde1c217a37b705479eb6e037ba7bdc64d6b89880b0964736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/mocks/TestRollupV1.sol/artifacts.d.ts b/eth/artifacts/contracts/mocks/TestRollupV1.sol/artifacts.d.ts new file mode 100644 index 0000000..124c28b --- /dev/null +++ b/eth/artifacts/contracts/mocks/TestRollupV1.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { TestRollupV1$Type } from "./TestRollupV1"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["TestRollupV1"]: TestRollupV1$Type; + ["contracts/mocks/TestRollupV1.sol:TestRollupV1"]: TestRollupV1$Type; + } +} diff --git a/eth/artifacts/contracts/noir/IVerifier.sol/IVerifier.d.ts b/eth/artifacts/contracts/noir/IVerifier.sol/IVerifier.d.ts new file mode 100644 index 0000000..827e05c --- /dev/null +++ b/eth/artifacts/contracts/noir/IVerifier.sol/IVerifier.d.ts @@ -0,0 +1,67 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface IVerifier$Type { + "_format": "hh-sol-artifact-1", + "contractName": "IVerifier", + "sourceName": "contracts/noir/IVerifier.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "_publicInputs", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "contracts/noir/IVerifier.sol:IVerifier", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "contracts/noir/IVerifier.sol:IVerifier", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "contracts/noir/IVerifier.sol:IVerifier", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/noir/IVerifier.sol/IVerifier.json b/eth/artifacts/contracts/noir/IVerifier.sol/IVerifier.json new file mode 100644 index 0000000..d2a4274 --- /dev/null +++ b/eth/artifacts/contracts/noir/IVerifier.sol/IVerifier.json @@ -0,0 +1,35 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "IVerifier", + "sourceName": "contracts/noir/IVerifier.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes", + "name": "_proof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "_publicInputs", + "type": "bytes32[]" + } + ], + "name": "verify", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/noir/IVerifier.sol/artifacts.d.ts b/eth/artifacts/contracts/noir/IVerifier.sol/artifacts.d.ts new file mode 100644 index 0000000..9fd1da1 --- /dev/null +++ b/eth/artifacts/contracts/noir/IVerifier.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { IVerifier$Type } from "./IVerifier"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["IVerifier"]: IVerifier$Type; + ["contracts/noir/IVerifier.sol:IVerifier"]: IVerifier$Type; + } +} diff --git a/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.d.ts b/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.d.ts deleted file mode 100644 index 83b6ddf..0000000 --- a/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.d.ts +++ /dev/null @@ -1,732 +0,0 @@ -// This file was autogenerated by hardhat-viem, do not edit it. -// prettier-ignore -// tslint:disable -// eslint-disable - -import type { Address } from "viem"; -import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; -import "@nomicfoundation/hardhat-viem/types"; - -export interface RollupV1$Type { - "_format": "hh-sol-artifact-1", - "contractName": "RollupV1", - "sourceName": "contracts/rollup/RollupV1.sol", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "name": "ValidatorSetAdded", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "prover", - "type": "address" - } - ], - "name": "addProver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "aggregateVerifier", - "outputs": [ - { - "internalType": "contract AggregateVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifier", - "outputs": [ - { - "internalType": "contract BurnVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[6]", - "name": "hashes", - "type": "bytes32[6]" - } - ], - "name": "containsRootHashes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentRootHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getBurn", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Burn", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRootHashes", - "outputs": [ - { - "internalType": "bytes32[64]", - "name": "", - "type": "bytes32[64]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "from", - "type": "uint256" - } - ], - "name": "getValidatorSets", - "outputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "internalType": "struct PublicValidatorSet[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_usdcAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_aggregateVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_mintVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_burnVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "prover", - "type": "address" - }, - { - "internalType": "address[]", - "name": "initialValidators", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "emptyMerkleTreeRootHash", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintVerifier", - "outputs": [ - { - "internalType": "contract MintVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "validAfter", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "validBefore", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v2", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s2", - "type": "bytes32" - } - ], - "name": "mintWithAuthorization", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "nextRootHashIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "rootHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - } - ], - "name": "setRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "setValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usdc", - "outputs": [ - { - "internalType": "contract IUSDC", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - } - ], - "name": "verifyBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x608080604052346100b8577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c166100a957506001600160401b036002600160401b031982821601610064575b60405161229090816100be8239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1388080610055565b63f92ee8a960e01b8152600490fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14611d55575080631000b72914611c105780631d49e45714611bd35780633e413bee14611baa5780634fb4eee3146113b157806353b935571461138457806354fd4d50146113645780635eeba6dd14610dbd5780636779b7c214610d9f578063715018a614610d345780638da5cb5b14610cfe578063a2ce9c1f14610cd4578063a91eebf514610cb1578063afbd8c3914610c4d578063b506165814610957578063c072bd881461092e578063c3a716eb14610905578063c832fe5f14610880578063cb325833146106ff578063dab5f340146106da578063e4408e4614610673578063e795594d1461039a578063ef0feff9146101a9578063f22a195e1461018b578063f2fde38b1461015e5763f44ff7121461013e57600080fd5b3461015b578060031936011261015b576020600754604051908152f35b80fd5b503461015b57602036600319011261015b5761018861017b611da7565b610183611ebf565b611ef8565b80f35b503461015b578060031936011261015b576020600654604051908152f35b503461015b576020908160031936011261015b5790600435604d546101ce8282611fd9565b916101d8836120fe565b926101e66040519485611e9e565b8084526101f5601f19916120fe565b01855b81811061036d575050805b8281106102be5750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102405787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061029b5750505090600193838080940151910152980193019301909287969593949294610233565b82516001600160a01b031685528a95948501949092019160019190910190610270565b808694959652604c8652604084206001600281830192015490604051926102e484611e4c565b60405191828b83549182815201928a528b8a20918a915b8d81841061034f575050505050918161031e610346969593610340950382611e9e565b82528982015261032e8584611fd9565b90610339828a612115565b5287612115565b50612015565b94939294610203565b84546001600160a01b031686529094019392810192918101916102fb565b94808097959660405161037f81611e4c565b60608152878382015282828a010152019050959493956101f8565b503461015b57604036600319011261015b576004356001600160401b036024803582811161066f576103d0903690600401611dd3565b92906103da611ebf565b604d93845480158015610635575b156105c157600052604c91602092808452876002604060002001558654600052600194856040600020019084116105ac57600160401b84116105ac578054848255808510610582575b50829060005284600020908660005b868110610569575050505060005b8381106104ac575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161049857505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826104d86104d3868a8a61213d565b612129565b16600052875260ff6040600020541661052a5790610525929160005283875260406000209061050b6104d384898961213d565b16600052865260406000208760ff19825416179055612015565b61044e565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761057384612129565b93019281850155018790610440565b8160005286858760002092830192015b8281106105a0575050610431565b60008155018790610592565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161065a57600052604c60205286600260406000200154106103e8565b85634e487b7160e01b60005260116004526000fd5b8480fd5b503461015b57602036600319011261015b5760408181926020835161069781611e4c565b82815201526004358152604b6020522081516106b281611e4c565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b503461015b57602036600319011261015b576106f4611ebf565b610188600435611f9b565b503461015b5760c036600319011261015b57610719611da7565b6001600160401b0360243581811161087c57610739903690600401611d7a565b600454604051949293606435936001600160a01b03936044359390929085169160a089019182118983101761086657859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b1561086257604051625a2d8360e11b815260c060048201528a94909392916107be9160c48601916121b6565b908489602486015b60058310610848575050505083918380809303915afa801561083d57610825575b5050600193604b91604051966107fc88611e4c565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b61082e90611e1e565b6108395785386107e7565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b91016107c6565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b503461015b578060031936011261015b576040519061089e82611e82565b610800809236903760405190600881835b604082106108ef57505050906108c481611e82565b6040519190825b604083106108d857505050f35b6001908251815260208091019201920191906108cb565b60016020819285548152019301910190916108af565b503461015b578060031936011261015b576004546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b576002546040516001600160a01b039091168152602090f35b503461015b576101c036600319011261015b576001600160401b0390600435828111610c495761098b903690600401611d7a565b909260643593610999611dbd565b60243592838652602092604a84526040872054610c0e5760405192848401907fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c08252866040860152604435978860608701528a608087015260018060a01b03809216938460a088015260a435968760c082015260c435968760e083015260e435956101008781850152835261012083019183831090831117610866578a92828f9392610aa193604052825190206101626001549361014081019461190160f01b8652610142820152015260428152610a7081611e67565b519020604080519182526101643560ff16602083015261018435908201526101a43560608201529081906080820190565b838052039060015afa15610c035784838c511603610bcd578a9b8360039c999a9b9c541660405191610ad283611e03565b8c83528d8c8401526040830152803b1561086257610b09938a9360405195869485938493635e65f68960e11b8552600485016121d7565b03915afa908115610bc2578791610bae575b50506005541690813b156108395785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561083d57610b9a575b5091604a925252604082205580f35b610ba390611e1e565b61087c578338610b8b565b610bb790611e1e565b610839578538610b1b565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b6040513d8c823e3d90fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b503461015b5760c036600319011261015b57366023121561015b57604051610c7481611e31565b8060c49136831161087c57602093506004905b838210610ca25784610c9884612035565b6040519015158152f35b81358152908401908401610c87565b503461015b578060031936011261015b576020610ccc611fe6565b604051908152f35b503461015b57602036600319011261015b5760406020916004358152604a83522054604051908152f35b503461015b578060031936011261015b5760008051602061221b833981519152546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b57610d4d611ebf565b60008051602061221b83398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461015b578060031936011261015b576020604854604051908152f35b503461015b5761010036600319011261015b57610dd8611da7565b6024356001600160a01b038116810361135f57604435906001600160a01b038216820361135f57606435906001600160a01b038216820361135f57610e1b611dbd565b60a43591906001600160a01b038316830361135f5760c4356001600160401b03811161135b57610e4f903690600401611dd3565b94909560008051602061223b83398151915254976001600160401b038916158061134d575b60016001600160401b038b16149081611343575b15908161133a575b5061132857610edf9060016001600160401b03198b161760008051602061223b8339815191525560ff8a60401c16156112fb575b8a5460ff19166001178b55610ed7611f6c565b610183611f6c565b650526f6c6c75760d41b6020604051610ef781611e4c565b600681520152603160f81b6020604051610f1081611e4c565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a08152610fa681611e31565b5190206001556bffffffffffffffffffffffff60a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d54801580156112df575b1561126a57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b03821161086657600160401b8211610866578054828255808310611240575b50829060005260206000209060005b8381106112255750505060005b81811061116057505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a16001820180921161114a5760ff91604d556110e460e435611f9b565b60401c16156110f05780f35b68ff00000000000000001960008051602061223b833981519152541660008051602061223b833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361118a6104d384878961213d565b1660005260205260ff604060002054166111e5576111e091600052604c602052604060002060018060a01b036111c46104d384878961213d565b166000526020526040600020600160ff19825416179055612015565b61108a565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b600190602061123384612129565b930192818501550161107d565b816000526020600020908382015b818301811061125e57505061106e565b6000815560010161124e565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161114a57600052604c6020526000611023565b68ffffffffffffffffff198a16680100000000000000011760008051602061223b83398151915255610ec4565b60405163f92ee8a960e01b8152600490fd5b90501538610e90565b303b159150610e88565b5060ff8960401c1615610e74565b8780fd5b600080fd5b503461015b578060031936011261015b5760ff6020915416604051908152f35b503461015b57602036600319011261015b576004356040811015610c495760209060080154604051908152f35b503461015b5761048036600319011261015b576001600160401b03600435818111611ba6576113e4903690600401611d7a565b9091366101a41161087c57366104241161087c5780610464351161087c573660236104643501121561087c57610464356004013511611ba657366024606061046435600401350261046435010111611ba65733835260496020526001604084205403611b6a57604e5460018101809111611b56575b604d54811015611b4f57808452604c6020526104443560026040862001541161148e578061148991604e55612015565b611459565b50905b604e548352604c60205260408320916114a8611fe6565b6101a43503611af957835b601281106118fb57506115036040516114cb81611e31565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612035565b156118bf5760018301548060011b90808204600214901517156118485760039004600181018091116118485761046435600401351061185c576040516101c43560208201526104443560408201526104243560608201526060815261156781611e67565b6020815191012092600161044435016104443511611848576040516020810190600161044435018252856040820152604081526115a381611e03565b519020604051906115b382611e4c565b6008825267506f6c796261736560c01b602083015260405190816020810193600160c31b85528051908a5b82811061183057505090611605926048928201906028820152036028810184520182611e9e565b5190206104643560040135156117fb5785939291849190825b610464356004013584106116d75750506002546001600160a01b031693915050823b1561087c57604051633b07787160e21b81526104206004820152928492849283918291611672916104248401916121b6565b6101806024808401376101a4356101a48301526101c4356101c48301526102406101e48084013703915afa801561083d576116c3575b50506116b66101c435611f9b565b6006556104443560075580f35b6116cc90611e1e565b610c495781386116a8565b90919293949560209061172660608702610464350160405191816044849301359060ff60646024830135920135168a859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15610bc25787519060018060a01b03808316918260005284602052600160ff604060002054161515036117b6571610156117785761176d9093612015565b91908795949361161e565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b602082820181015160288884010152869450016115de565b634e487b7160e01b85526011600452602485fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b60018101808211611ae55761190f9061214d565b35600282018211611ae5576119266002830161214d565b358015611ade57818752604a602052604087205480611a8b5750604b60205260016040882001548061198b5760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152606490fd5b03611a505760018060a01b036020816005541691838952604b82526044600160408b2092835416920154918a604051958694859363a9059cbb60e01b8552600485015260248401525af18015610bc2576119ec918891611a21575b50612178565b8552604b602052600060016040872087815501555b60038101809111156114b357634e487b7160e01b85526011600452602485fd5b611a43915060203d602011611a49575b611a3b8183611e9e565b810190612160565b386119e6565b503d611a31565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b03611aa3578552604a60205260006040862055611a01565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606490fd5b5050611a01565b634e487b7160e01b86526011600452602486fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b5090611491565b634e487b7160e01b84526011600452602484fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b503461015b578060031936011261015b576005546040516001600160a01b039091168152602090f35b503461015b57602036600319011261015b57611bed611da7565b611bf5611ebf565b6001600160a01b031681526049602052604081206001905580f35b503461015b57608036600319011261015b576004356001600160401b038111610c4957611c41903690600401611d7a565b91906024359060443591808452602091604a83526040852054610c0e576003546040516001600160a01b0397909291881691611c7c84611e03565b84845286868501526064356040850152823b1561135b57604051635e65f68960e11b81529388938593909284928392611cb892600485016121d7565b03915afa8015611d3557611d40575b50818495600595949554166064604051809681936323b872dd60e01b83523360048401523060248401528960448401525af1928315611d3557604a93611d13918791611d1e5750612178565b845252604082205580f35b611a439150843d8611611a4957611a3b8183611e9e565b6040513d87823e3d90fd5b93611d4d83969495611e1e565b939294611cc7565b905034610c495781600319360112610c49576003546001600160a01b03168152602090f35b9181601f8401121561135f578235916001600160401b03831161135f576020838186019501011161135f57565b600435906001600160a01b038216820361135f57565b608435906001600160a01b038216820361135f57565b9181601f8401121561135f578235916001600160401b03831161135f576020808501948460051b01011161135f57565b606081019081106001600160401b0382111761086657604052565b6001600160401b03811161086657604052565b60c081019081106001600160401b0382111761086657604052565b604081019081106001600160401b0382111761086657604052565b608081019081106001600160401b0382111761086657604052565b61080081019081106001600160401b0382111761086657604052565b90601f801991011681019081106001600160401b0382111761086657604052565b60008051602061221b833981519152546001600160a01b03163303611ee057565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115611f535760008051602061221b83398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b60ff60008051602061223b8339815191525460401c1615611f8957565b604051631afcd79f60e31b8152600490fd5b6048546040811015611fc3576008015560485460018101811161114a57600160409108604855565b634e487b7160e01b600052603260045260246000fd5b9190820391821161114a57565b603f60485480612002575b506040811015611fc3576008015490565b60001981019150811161114a5738611ff1565b600019811461114a5760010190565b906006811015611fc35760051b0190565b60409081519161204483611e31565b60009182845282602085015282828501528260608501528260808501528260a0850152825b600681106120aa57505050805b6006811061208657505050600190565b6120908184612024565b51156120a45761209f90612015565b612076565b50905090565b835b8381106120c3575b506120be90612015565b612069565b6120cd8284612024565b518160080154146120e6576120e190612015565b6120ac565b508060016120f76120be9388612024565b52906120b4565b6001600160401b0381116108665760051b60200190565b8051821015611fc35760209160051b010190565b356001600160a01b038116810361135f5790565b9190811015611fc35760051b0190565b6012811015611fc35760051b6101e40190565b9081602091031261135f5751801515810361135f5790565b1561217f57565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b908060209392818452848401376000828201840152601f01601f1916010190565b939291906121ed916080865260808601916121b6565b9260208091016000905b600382106122055750505050565b828060019286518152019401910190926121f756fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212208e854684387c37eb7ab500a6ec129cf1b9dc5a3a906bf4457a31fcb26640499c64736f6c63430008140033", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14611d55575080631000b72914611c105780631d49e45714611bd35780633e413bee14611baa5780634fb4eee3146113b157806353b935571461138457806354fd4d50146113645780635eeba6dd14610dbd5780636779b7c214610d9f578063715018a614610d345780638da5cb5b14610cfe578063a2ce9c1f14610cd4578063a91eebf514610cb1578063afbd8c3914610c4d578063b506165814610957578063c072bd881461092e578063c3a716eb14610905578063c832fe5f14610880578063cb325833146106ff578063dab5f340146106da578063e4408e4614610673578063e795594d1461039a578063ef0feff9146101a9578063f22a195e1461018b578063f2fde38b1461015e5763f44ff7121461013e57600080fd5b3461015b578060031936011261015b576020600754604051908152f35b80fd5b503461015b57602036600319011261015b5761018861017b611da7565b610183611ebf565b611ef8565b80f35b503461015b578060031936011261015b576020600654604051908152f35b503461015b576020908160031936011261015b5790600435604d546101ce8282611fd9565b916101d8836120fe565b926101e66040519485611e9e565b8084526101f5601f19916120fe565b01855b81811061036d575050805b8281106102be5750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102405787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061029b5750505090600193838080940151910152980193019301909287969593949294610233565b82516001600160a01b031685528a95948501949092019160019190910190610270565b808694959652604c8652604084206001600281830192015490604051926102e484611e4c565b60405191828b83549182815201928a528b8a20918a915b8d81841061034f575050505050918161031e610346969593610340950382611e9e565b82528982015261032e8584611fd9565b90610339828a612115565b5287612115565b50612015565b94939294610203565b84546001600160a01b031686529094019392810192918101916102fb565b94808097959660405161037f81611e4c565b60608152878382015282828a010152019050959493956101f8565b503461015b57604036600319011261015b576004356001600160401b036024803582811161066f576103d0903690600401611dd3565b92906103da611ebf565b604d93845480158015610635575b156105c157600052604c91602092808452876002604060002001558654600052600194856040600020019084116105ac57600160401b84116105ac578054848255808510610582575b50829060005284600020908660005b868110610569575050505060005b8381106104ac575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161049857505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826104d86104d3868a8a61213d565b612129565b16600052875260ff6040600020541661052a5790610525929160005283875260406000209061050b6104d384898961213d565b16600052865260406000208760ff19825416179055612015565b61044e565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761057384612129565b93019281850155018790610440565b8160005286858760002092830192015b8281106105a0575050610431565b60008155018790610592565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161065a57600052604c60205286600260406000200154106103e8565b85634e487b7160e01b60005260116004526000fd5b8480fd5b503461015b57602036600319011261015b5760408181926020835161069781611e4c565b82815201526004358152604b6020522081516106b281611e4c565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b503461015b57602036600319011261015b576106f4611ebf565b610188600435611f9b565b503461015b5760c036600319011261015b57610719611da7565b6001600160401b0360243581811161087c57610739903690600401611d7a565b600454604051949293606435936001600160a01b03936044359390929085169160a089019182118983101761086657859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b1561086257604051625a2d8360e11b815260c060048201528a94909392916107be9160c48601916121b6565b908489602486015b60058310610848575050505083918380809303915afa801561083d57610825575b5050600193604b91604051966107fc88611e4c565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b61082e90611e1e565b6108395785386107e7565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b91016107c6565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b503461015b578060031936011261015b576040519061089e82611e82565b610800809236903760405190600881835b604082106108ef57505050906108c481611e82565b6040519190825b604083106108d857505050f35b6001908251815260208091019201920191906108cb565b60016020819285548152019301910190916108af565b503461015b578060031936011261015b576004546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b576002546040516001600160a01b039091168152602090f35b503461015b576101c036600319011261015b576001600160401b0390600435828111610c495761098b903690600401611d7a565b909260643593610999611dbd565b60243592838652602092604a84526040872054610c0e5760405192848401907fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c08252866040860152604435978860608701528a608087015260018060a01b03809216938460a088015260a435968760c082015260c435968760e083015260e435956101008781850152835261012083019183831090831117610866578a92828f9392610aa193604052825190206101626001549361014081019461190160f01b8652610142820152015260428152610a7081611e67565b519020604080519182526101643560ff16602083015261018435908201526101a43560608201529081906080820190565b838052039060015afa15610c035784838c511603610bcd578a9b8360039c999a9b9c541660405191610ad283611e03565b8c83528d8c8401526040830152803b1561086257610b09938a9360405195869485938493635e65f68960e11b8552600485016121d7565b03915afa908115610bc2578791610bae575b50506005541690813b156108395785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561083d57610b9a575b5091604a925252604082205580f35b610ba390611e1e565b61087c578338610b8b565b610bb790611e1e565b610839578538610b1b565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b6040513d8c823e3d90fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b503461015b5760c036600319011261015b57366023121561015b57604051610c7481611e31565b8060c49136831161087c57602093506004905b838210610ca25784610c9884612035565b6040519015158152f35b81358152908401908401610c87565b503461015b578060031936011261015b576020610ccc611fe6565b604051908152f35b503461015b57602036600319011261015b5760406020916004358152604a83522054604051908152f35b503461015b578060031936011261015b5760008051602061221b833981519152546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b57610d4d611ebf565b60008051602061221b83398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461015b578060031936011261015b576020604854604051908152f35b503461015b5761010036600319011261015b57610dd8611da7565b6024356001600160a01b038116810361135f57604435906001600160a01b038216820361135f57606435906001600160a01b038216820361135f57610e1b611dbd565b60a43591906001600160a01b038316830361135f5760c4356001600160401b03811161135b57610e4f903690600401611dd3565b94909560008051602061223b83398151915254976001600160401b038916158061134d575b60016001600160401b038b16149081611343575b15908161133a575b5061132857610edf9060016001600160401b03198b161760008051602061223b8339815191525560ff8a60401c16156112fb575b8a5460ff19166001178b55610ed7611f6c565b610183611f6c565b650526f6c6c75760d41b6020604051610ef781611e4c565b600681520152603160f81b6020604051610f1081611e4c565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a08152610fa681611e31565b5190206001556bffffffffffffffffffffffff60a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d54801580156112df575b1561126a57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b03821161086657600160401b8211610866578054828255808310611240575b50829060005260206000209060005b8381106112255750505060005b81811061116057505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a16001820180921161114a5760ff91604d556110e460e435611f9b565b60401c16156110f05780f35b68ff00000000000000001960008051602061223b833981519152541660008051602061223b833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361118a6104d384878961213d565b1660005260205260ff604060002054166111e5576111e091600052604c602052604060002060018060a01b036111c46104d384878961213d565b166000526020526040600020600160ff19825416179055612015565b61108a565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b600190602061123384612129565b930192818501550161107d565b816000526020600020908382015b818301811061125e57505061106e565b6000815560010161124e565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161114a57600052604c6020526000611023565b68ffffffffffffffffff198a16680100000000000000011760008051602061223b83398151915255610ec4565b60405163f92ee8a960e01b8152600490fd5b90501538610e90565b303b159150610e88565b5060ff8960401c1615610e74565b8780fd5b600080fd5b503461015b578060031936011261015b5760ff6020915416604051908152f35b503461015b57602036600319011261015b576004356040811015610c495760209060080154604051908152f35b503461015b5761048036600319011261015b576001600160401b03600435818111611ba6576113e4903690600401611d7a565b9091366101a41161087c57366104241161087c5780610464351161087c573660236104643501121561087c57610464356004013511611ba657366024606061046435600401350261046435010111611ba65733835260496020526001604084205403611b6a57604e5460018101809111611b56575b604d54811015611b4f57808452604c6020526104443560026040862001541161148e578061148991604e55612015565b611459565b50905b604e548352604c60205260408320916114a8611fe6565b6101a43503611af957835b601281106118fb57506115036040516114cb81611e31565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612035565b156118bf5760018301548060011b90808204600214901517156118485760039004600181018091116118485761046435600401351061185c576040516101c43560208201526104443560408201526104243560608201526060815261156781611e67565b6020815191012092600161044435016104443511611848576040516020810190600161044435018252856040820152604081526115a381611e03565b519020604051906115b382611e4c565b6008825267506f6c796261736560c01b602083015260405190816020810193600160c31b85528051908a5b82811061183057505090611605926048928201906028820152036028810184520182611e9e565b5190206104643560040135156117fb5785939291849190825b610464356004013584106116d75750506002546001600160a01b031693915050823b1561087c57604051633b07787160e21b81526104206004820152928492849283918291611672916104248401916121b6565b6101806024808401376101a4356101a48301526101c4356101c48301526102406101e48084013703915afa801561083d576116c3575b50506116b66101c435611f9b565b6006556104443560075580f35b6116cc90611e1e565b610c495781386116a8565b90919293949560209061172660608702610464350160405191816044849301359060ff60646024830135920135168a859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15610bc25787519060018060a01b03808316918260005284602052600160ff604060002054161515036117b6571610156117785761176d9093612015565b91908795949361161e565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b602082820181015160288884010152869450016115de565b634e487b7160e01b85526011600452602485fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b60018101808211611ae55761190f9061214d565b35600282018211611ae5576119266002830161214d565b358015611ade57818752604a602052604087205480611a8b5750604b60205260016040882001548061198b5760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152606490fd5b03611a505760018060a01b036020816005541691838952604b82526044600160408b2092835416920154918a604051958694859363a9059cbb60e01b8552600485015260248401525af18015610bc2576119ec918891611a21575b50612178565b8552604b602052600060016040872087815501555b60038101809111156114b357634e487b7160e01b85526011600452602485fd5b611a43915060203d602011611a49575b611a3b8183611e9e565b810190612160565b386119e6565b503d611a31565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b03611aa3578552604a60205260006040862055611a01565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606490fd5b5050611a01565b634e487b7160e01b86526011600452602486fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b5090611491565b634e487b7160e01b84526011600452602484fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b503461015b578060031936011261015b576005546040516001600160a01b039091168152602090f35b503461015b57602036600319011261015b57611bed611da7565b611bf5611ebf565b6001600160a01b031681526049602052604081206001905580f35b503461015b57608036600319011261015b576004356001600160401b038111610c4957611c41903690600401611d7a565b91906024359060443591808452602091604a83526040852054610c0e576003546040516001600160a01b0397909291881691611c7c84611e03565b84845286868501526064356040850152823b1561135b57604051635e65f68960e11b81529388938593909284928392611cb892600485016121d7565b03915afa8015611d3557611d40575b50818495600595949554166064604051809681936323b872dd60e01b83523360048401523060248401528960448401525af1928315611d3557604a93611d13918791611d1e5750612178565b845252604082205580f35b611a439150843d8611611a4957611a3b8183611e9e565b6040513d87823e3d90fd5b93611d4d83969495611e1e565b939294611cc7565b905034610c495781600319360112610c49576003546001600160a01b03168152602090f35b9181601f8401121561135f578235916001600160401b03831161135f576020838186019501011161135f57565b600435906001600160a01b038216820361135f57565b608435906001600160a01b038216820361135f57565b9181601f8401121561135f578235916001600160401b03831161135f576020808501948460051b01011161135f57565b606081019081106001600160401b0382111761086657604052565b6001600160401b03811161086657604052565b60c081019081106001600160401b0382111761086657604052565b604081019081106001600160401b0382111761086657604052565b608081019081106001600160401b0382111761086657604052565b61080081019081106001600160401b0382111761086657604052565b90601f801991011681019081106001600160401b0382111761086657604052565b60008051602061221b833981519152546001600160a01b03163303611ee057565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115611f535760008051602061221b83398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b60ff60008051602061223b8339815191525460401c1615611f8957565b604051631afcd79f60e31b8152600490fd5b6048546040811015611fc3576008015560485460018101811161114a57600160409108604855565b634e487b7160e01b600052603260045260246000fd5b9190820391821161114a57565b603f60485480612002575b506040811015611fc3576008015490565b60001981019150811161114a5738611ff1565b600019811461114a5760010190565b906006811015611fc35760051b0190565b60409081519161204483611e31565b60009182845282602085015282828501528260608501528260808501528260a0850152825b600681106120aa57505050805b6006811061208657505050600190565b6120908184612024565b51156120a45761209f90612015565b612076565b50905090565b835b8381106120c3575b506120be90612015565b612069565b6120cd8284612024565b518160080154146120e6576120e190612015565b6120ac565b508060016120f76120be9388612024565b52906120b4565b6001600160401b0381116108665760051b60200190565b8051821015611fc35760209160051b010190565b356001600160a01b038116810361135f5790565b9190811015611fc35760051b0190565b6012811015611fc35760051b6101e40190565b9081602091031261135f5751801515810361135f5790565b1561217f57565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b908060209392818452848401376000828201840152601f01601f1916010190565b939291906121ed916080865260808601916121b6565b9260208091016000905b600382106122055750505050565b828060019286518152019401910190926121f756fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212208e854684387c37eb7ab500a6ec129cf1b9dc5a3a906bf4457a31fcb26640499c64736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} - -declare module "@nomicfoundation/hardhat-viem/types" { - export function deployContract( - contractName: "RollupV1", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - export function deployContract( - contractName: "contracts/rollup/RollupV1.sol:RollupV1", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - - export function sendDeploymentTransaction( - contractName: "RollupV1", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - export function sendDeploymentTransaction( - contractName: "contracts/rollup/RollupV1.sol:RollupV1", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - - export function getContractAt( - contractName: "RollupV1", - address: Address, - config?: GetContractAtConfig - ): Promise>; - export function getContractAt( - contractName: "contracts/rollup/RollupV1.sol:RollupV1", - address: Address, - config?: GetContractAtConfig - ): Promise>; -} diff --git a/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.dbg.json b/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.dbg.json deleted file mode 100644 index b7a6a76..0000000 --- a/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/22152f3e0e0b93ca501b6ace01f305e7.json" -} diff --git a/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.json b/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.json deleted file mode 100644 index 625beeb..0000000 --- a/eth/artifacts/contracts/rollup/RollupV1.sol/RollupV1.json +++ /dev/null @@ -1,682 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "RollupV1", - "sourceName": "contracts/rollup/RollupV1.sol", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "name": "ValidatorSetAdded", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "prover", - "type": "address" - } - ], - "name": "addProver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "aggregateVerifier", - "outputs": [ - { - "internalType": "contract AggregateVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifier", - "outputs": [ - { - "internalType": "contract BurnVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[6]", - "name": "hashes", - "type": "bytes32[6]" - } - ], - "name": "containsRootHashes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentRootHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getBurn", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Burn", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRootHashes", - "outputs": [ - { - "internalType": "bytes32[64]", - "name": "", - "type": "bytes32[64]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "from", - "type": "uint256" - } - ], - "name": "getValidatorSets", - "outputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "internalType": "struct PublicValidatorSet[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_usdcAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_aggregateVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_mintVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_burnVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "prover", - "type": "address" - }, - { - "internalType": "address[]", - "name": "initialValidators", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "emptyMerkleTreeRootHash", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintVerifier", - "outputs": [ - { - "internalType": "contract MintVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "validAfter", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "validBefore", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v2", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s2", - "type": "bytes32" - } - ], - "name": "mintWithAuthorization", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "nextRootHashIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "rootHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - } - ], - "name": "setRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "setValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usdc", - "outputs": [ - { - "internalType": "contract IUSDC", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - } - ], - "name": "verifyBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x608080604052346100b8577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c166100a957506001600160401b036002600160401b031982821601610064575b60405161229090816100be8239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1388080610055565b63f92ee8a960e01b8152600490fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14611d55575080631000b72914611c105780631d49e45714611bd35780633e413bee14611baa5780634fb4eee3146113b157806353b935571461138457806354fd4d50146113645780635eeba6dd14610dbd5780636779b7c214610d9f578063715018a614610d345780638da5cb5b14610cfe578063a2ce9c1f14610cd4578063a91eebf514610cb1578063afbd8c3914610c4d578063b506165814610957578063c072bd881461092e578063c3a716eb14610905578063c832fe5f14610880578063cb325833146106ff578063dab5f340146106da578063e4408e4614610673578063e795594d1461039a578063ef0feff9146101a9578063f22a195e1461018b578063f2fde38b1461015e5763f44ff7121461013e57600080fd5b3461015b578060031936011261015b576020600754604051908152f35b80fd5b503461015b57602036600319011261015b5761018861017b611da7565b610183611ebf565b611ef8565b80f35b503461015b578060031936011261015b576020600654604051908152f35b503461015b576020908160031936011261015b5790600435604d546101ce8282611fd9565b916101d8836120fe565b926101e66040519485611e9e565b8084526101f5601f19916120fe565b01855b81811061036d575050805b8281106102be5750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102405787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061029b5750505090600193838080940151910152980193019301909287969593949294610233565b82516001600160a01b031685528a95948501949092019160019190910190610270565b808694959652604c8652604084206001600281830192015490604051926102e484611e4c565b60405191828b83549182815201928a528b8a20918a915b8d81841061034f575050505050918161031e610346969593610340950382611e9e565b82528982015261032e8584611fd9565b90610339828a612115565b5287612115565b50612015565b94939294610203565b84546001600160a01b031686529094019392810192918101916102fb565b94808097959660405161037f81611e4c565b60608152878382015282828a010152019050959493956101f8565b503461015b57604036600319011261015b576004356001600160401b036024803582811161066f576103d0903690600401611dd3565b92906103da611ebf565b604d93845480158015610635575b156105c157600052604c91602092808452876002604060002001558654600052600194856040600020019084116105ac57600160401b84116105ac578054848255808510610582575b50829060005284600020908660005b868110610569575050505060005b8381106104ac575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161049857505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826104d86104d3868a8a61213d565b612129565b16600052875260ff6040600020541661052a5790610525929160005283875260406000209061050b6104d384898961213d565b16600052865260406000208760ff19825416179055612015565b61044e565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761057384612129565b93019281850155018790610440565b8160005286858760002092830192015b8281106105a0575050610431565b60008155018790610592565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161065a57600052604c60205286600260406000200154106103e8565b85634e487b7160e01b60005260116004526000fd5b8480fd5b503461015b57602036600319011261015b5760408181926020835161069781611e4c565b82815201526004358152604b6020522081516106b281611e4c565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b503461015b57602036600319011261015b576106f4611ebf565b610188600435611f9b565b503461015b5760c036600319011261015b57610719611da7565b6001600160401b0360243581811161087c57610739903690600401611d7a565b600454604051949293606435936001600160a01b03936044359390929085169160a089019182118983101761086657859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b1561086257604051625a2d8360e11b815260c060048201528a94909392916107be9160c48601916121b6565b908489602486015b60058310610848575050505083918380809303915afa801561083d57610825575b5050600193604b91604051966107fc88611e4c565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b61082e90611e1e565b6108395785386107e7565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b91016107c6565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b503461015b578060031936011261015b576040519061089e82611e82565b610800809236903760405190600881835b604082106108ef57505050906108c481611e82565b6040519190825b604083106108d857505050f35b6001908251815260208091019201920191906108cb565b60016020819285548152019301910190916108af565b503461015b578060031936011261015b576004546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b576002546040516001600160a01b039091168152602090f35b503461015b576101c036600319011261015b576001600160401b0390600435828111610c495761098b903690600401611d7a565b909260643593610999611dbd565b60243592838652602092604a84526040872054610c0e5760405192848401907fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c08252866040860152604435978860608701528a608087015260018060a01b03809216938460a088015260a435968760c082015260c435968760e083015260e435956101008781850152835261012083019183831090831117610866578a92828f9392610aa193604052825190206101626001549361014081019461190160f01b8652610142820152015260428152610a7081611e67565b519020604080519182526101643560ff16602083015261018435908201526101a43560608201529081906080820190565b838052039060015afa15610c035784838c511603610bcd578a9b8360039c999a9b9c541660405191610ad283611e03565b8c83528d8c8401526040830152803b1561086257610b09938a9360405195869485938493635e65f68960e11b8552600485016121d7565b03915afa908115610bc2578791610bae575b50506005541690813b156108395785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561083d57610b9a575b5091604a925252604082205580f35b610ba390611e1e565b61087c578338610b8b565b610bb790611e1e565b610839578538610b1b565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b6040513d8c823e3d90fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b503461015b5760c036600319011261015b57366023121561015b57604051610c7481611e31565b8060c49136831161087c57602093506004905b838210610ca25784610c9884612035565b6040519015158152f35b81358152908401908401610c87565b503461015b578060031936011261015b576020610ccc611fe6565b604051908152f35b503461015b57602036600319011261015b5760406020916004358152604a83522054604051908152f35b503461015b578060031936011261015b5760008051602061221b833981519152546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b57610d4d611ebf565b60008051602061221b83398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461015b578060031936011261015b576020604854604051908152f35b503461015b5761010036600319011261015b57610dd8611da7565b6024356001600160a01b038116810361135f57604435906001600160a01b038216820361135f57606435906001600160a01b038216820361135f57610e1b611dbd565b60a43591906001600160a01b038316830361135f5760c4356001600160401b03811161135b57610e4f903690600401611dd3565b94909560008051602061223b83398151915254976001600160401b038916158061134d575b60016001600160401b038b16149081611343575b15908161133a575b5061132857610edf9060016001600160401b03198b161760008051602061223b8339815191525560ff8a60401c16156112fb575b8a5460ff19166001178b55610ed7611f6c565b610183611f6c565b650526f6c6c75760d41b6020604051610ef781611e4c565b600681520152603160f81b6020604051610f1081611e4c565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a08152610fa681611e31565b5190206001556bffffffffffffffffffffffff60a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d54801580156112df575b1561126a57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b03821161086657600160401b8211610866578054828255808310611240575b50829060005260206000209060005b8381106112255750505060005b81811061116057505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a16001820180921161114a5760ff91604d556110e460e435611f9b565b60401c16156110f05780f35b68ff00000000000000001960008051602061223b833981519152541660008051602061223b833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361118a6104d384878961213d565b1660005260205260ff604060002054166111e5576111e091600052604c602052604060002060018060a01b036111c46104d384878961213d565b166000526020526040600020600160ff19825416179055612015565b61108a565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b600190602061123384612129565b930192818501550161107d565b816000526020600020908382015b818301811061125e57505061106e565b6000815560010161124e565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161114a57600052604c6020526000611023565b68ffffffffffffffffff198a16680100000000000000011760008051602061223b83398151915255610ec4565b60405163f92ee8a960e01b8152600490fd5b90501538610e90565b303b159150610e88565b5060ff8960401c1615610e74565b8780fd5b600080fd5b503461015b578060031936011261015b5760ff6020915416604051908152f35b503461015b57602036600319011261015b576004356040811015610c495760209060080154604051908152f35b503461015b5761048036600319011261015b576001600160401b03600435818111611ba6576113e4903690600401611d7a565b9091366101a41161087c57366104241161087c5780610464351161087c573660236104643501121561087c57610464356004013511611ba657366024606061046435600401350261046435010111611ba65733835260496020526001604084205403611b6a57604e5460018101809111611b56575b604d54811015611b4f57808452604c6020526104443560026040862001541161148e578061148991604e55612015565b611459565b50905b604e548352604c60205260408320916114a8611fe6565b6101a43503611af957835b601281106118fb57506115036040516114cb81611e31565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612035565b156118bf5760018301548060011b90808204600214901517156118485760039004600181018091116118485761046435600401351061185c576040516101c43560208201526104443560408201526104243560608201526060815261156781611e67565b6020815191012092600161044435016104443511611848576040516020810190600161044435018252856040820152604081526115a381611e03565b519020604051906115b382611e4c565b6008825267506f6c796261736560c01b602083015260405190816020810193600160c31b85528051908a5b82811061183057505090611605926048928201906028820152036028810184520182611e9e565b5190206104643560040135156117fb5785939291849190825b610464356004013584106116d75750506002546001600160a01b031693915050823b1561087c57604051633b07787160e21b81526104206004820152928492849283918291611672916104248401916121b6565b6101806024808401376101a4356101a48301526101c4356101c48301526102406101e48084013703915afa801561083d576116c3575b50506116b66101c435611f9b565b6006556104443560075580f35b6116cc90611e1e565b610c495781386116a8565b90919293949560209061172660608702610464350160405191816044849301359060ff60646024830135920135168a859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15610bc25787519060018060a01b03808316918260005284602052600160ff604060002054161515036117b6571610156117785761176d9093612015565b91908795949361161e565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b602082820181015160288884010152869450016115de565b634e487b7160e01b85526011600452602485fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b60018101808211611ae55761190f9061214d565b35600282018211611ae5576119266002830161214d565b358015611ade57818752604a602052604087205480611a8b5750604b60205260016040882001548061198b5760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152606490fd5b03611a505760018060a01b036020816005541691838952604b82526044600160408b2092835416920154918a604051958694859363a9059cbb60e01b8552600485015260248401525af18015610bc2576119ec918891611a21575b50612178565b8552604b602052600060016040872087815501555b60038101809111156114b357634e487b7160e01b85526011600452602485fd5b611a43915060203d602011611a49575b611a3b8183611e9e565b810190612160565b386119e6565b503d611a31565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b03611aa3578552604a60205260006040862055611a01565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606490fd5b5050611a01565b634e487b7160e01b86526011600452602486fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b5090611491565b634e487b7160e01b84526011600452602484fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b503461015b578060031936011261015b576005546040516001600160a01b039091168152602090f35b503461015b57602036600319011261015b57611bed611da7565b611bf5611ebf565b6001600160a01b031681526049602052604081206001905580f35b503461015b57608036600319011261015b576004356001600160401b038111610c4957611c41903690600401611d7a565b91906024359060443591808452602091604a83526040852054610c0e576003546040516001600160a01b0397909291881691611c7c84611e03565b84845286868501526064356040850152823b1561135b57604051635e65f68960e11b81529388938593909284928392611cb892600485016121d7565b03915afa8015611d3557611d40575b50818495600595949554166064604051809681936323b872dd60e01b83523360048401523060248401528960448401525af1928315611d3557604a93611d13918791611d1e5750612178565b845252604082205580f35b611a439150843d8611611a4957611a3b8183611e9e565b6040513d87823e3d90fd5b93611d4d83969495611e1e565b939294611cc7565b905034610c495781600319360112610c49576003546001600160a01b03168152602090f35b9181601f8401121561135f578235916001600160401b03831161135f576020838186019501011161135f57565b600435906001600160a01b038216820361135f57565b608435906001600160a01b038216820361135f57565b9181601f8401121561135f578235916001600160401b03831161135f576020808501948460051b01011161135f57565b606081019081106001600160401b0382111761086657604052565b6001600160401b03811161086657604052565b60c081019081106001600160401b0382111761086657604052565b604081019081106001600160401b0382111761086657604052565b608081019081106001600160401b0382111761086657604052565b61080081019081106001600160401b0382111761086657604052565b90601f801991011681019081106001600160401b0382111761086657604052565b60008051602061221b833981519152546001600160a01b03163303611ee057565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115611f535760008051602061221b83398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b60ff60008051602061223b8339815191525460401c1615611f8957565b604051631afcd79f60e31b8152600490fd5b6048546040811015611fc3576008015560485460018101811161114a57600160409108604855565b634e487b7160e01b600052603260045260246000fd5b9190820391821161114a57565b603f60485480612002575b506040811015611fc3576008015490565b60001981019150811161114a5738611ff1565b600019811461114a5760010190565b906006811015611fc35760051b0190565b60409081519161204483611e31565b60009182845282602085015282828501528260608501528260808501528260a0850152825b600681106120aa57505050805b6006811061208657505050600190565b6120908184612024565b51156120a45761209f90612015565b612076565b50905090565b835b8381106120c3575b506120be90612015565b612069565b6120cd8284612024565b518160080154146120e6576120e190612015565b6120ac565b508060016120f76120be9388612024565b52906120b4565b6001600160401b0381116108665760051b60200190565b8051821015611fc35760209160051b010190565b356001600160a01b038116810361135f5790565b9190811015611fc35760051b0190565b6012811015611fc35760051b6101e40190565b9081602091031261135f5751801515810361135f5790565b1561217f57565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b908060209392818452848401376000828201840152601f01601f1916010190565b939291906121ed916080865260808601916121b6565b9260208091016000905b600382106122055750505050565b828060019286518152019401910190926121f756fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212208e854684387c37eb7ab500a6ec129cf1b9dc5a3a906bf4457a31fcb26640499c64736f6c63430008140033", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14611d55575080631000b72914611c105780631d49e45714611bd35780633e413bee14611baa5780634fb4eee3146113b157806353b935571461138457806354fd4d50146113645780635eeba6dd14610dbd5780636779b7c214610d9f578063715018a614610d345780638da5cb5b14610cfe578063a2ce9c1f14610cd4578063a91eebf514610cb1578063afbd8c3914610c4d578063b506165814610957578063c072bd881461092e578063c3a716eb14610905578063c832fe5f14610880578063cb325833146106ff578063dab5f340146106da578063e4408e4614610673578063e795594d1461039a578063ef0feff9146101a9578063f22a195e1461018b578063f2fde38b1461015e5763f44ff7121461013e57600080fd5b3461015b578060031936011261015b576020600754604051908152f35b80fd5b503461015b57602036600319011261015b5761018861017b611da7565b610183611ebf565b611ef8565b80f35b503461015b578060031936011261015b576020600654604051908152f35b503461015b576020908160031936011261015b5790600435604d546101ce8282611fd9565b916101d8836120fe565b926101e66040519485611e9e565b8084526101f5601f19916120fe565b01855b81811061036d575050805b8281106102be5750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102405787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061029b5750505090600193838080940151910152980193019301909287969593949294610233565b82516001600160a01b031685528a95948501949092019160019190910190610270565b808694959652604c8652604084206001600281830192015490604051926102e484611e4c565b60405191828b83549182815201928a528b8a20918a915b8d81841061034f575050505050918161031e610346969593610340950382611e9e565b82528982015261032e8584611fd9565b90610339828a612115565b5287612115565b50612015565b94939294610203565b84546001600160a01b031686529094019392810192918101916102fb565b94808097959660405161037f81611e4c565b60608152878382015282828a010152019050959493956101f8565b503461015b57604036600319011261015b576004356001600160401b036024803582811161066f576103d0903690600401611dd3565b92906103da611ebf565b604d93845480158015610635575b156105c157600052604c91602092808452876002604060002001558654600052600194856040600020019084116105ac57600160401b84116105ac578054848255808510610582575b50829060005284600020908660005b868110610569575050505060005b8381106104ac575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161049857505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826104d86104d3868a8a61213d565b612129565b16600052875260ff6040600020541661052a5790610525929160005283875260406000209061050b6104d384898961213d565b16600052865260406000208760ff19825416179055612015565b61044e565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761057384612129565b93019281850155018790610440565b8160005286858760002092830192015b8281106105a0575050610431565b60008155018790610592565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161065a57600052604c60205286600260406000200154106103e8565b85634e487b7160e01b60005260116004526000fd5b8480fd5b503461015b57602036600319011261015b5760408181926020835161069781611e4c565b82815201526004358152604b6020522081516106b281611e4c565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b503461015b57602036600319011261015b576106f4611ebf565b610188600435611f9b565b503461015b5760c036600319011261015b57610719611da7565b6001600160401b0360243581811161087c57610739903690600401611d7a565b600454604051949293606435936001600160a01b03936044359390929085169160a089019182118983101761086657859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b1561086257604051625a2d8360e11b815260c060048201528a94909392916107be9160c48601916121b6565b908489602486015b60058310610848575050505083918380809303915afa801561083d57610825575b5050600193604b91604051966107fc88611e4c565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b61082e90611e1e565b6108395785386107e7565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b91016107c6565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b503461015b578060031936011261015b576040519061089e82611e82565b610800809236903760405190600881835b604082106108ef57505050906108c481611e82565b6040519190825b604083106108d857505050f35b6001908251815260208091019201920191906108cb565b60016020819285548152019301910190916108af565b503461015b578060031936011261015b576004546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b576002546040516001600160a01b039091168152602090f35b503461015b576101c036600319011261015b576001600160401b0390600435828111610c495761098b903690600401611d7a565b909260643593610999611dbd565b60243592838652602092604a84526040872054610c0e5760405192848401907fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c08252866040860152604435978860608701528a608087015260018060a01b03809216938460a088015260a435968760c082015260c435968760e083015260e435956101008781850152835261012083019183831090831117610866578a92828f9392610aa193604052825190206101626001549361014081019461190160f01b8652610142820152015260428152610a7081611e67565b519020604080519182526101643560ff16602083015261018435908201526101a43560608201529081906080820190565b838052039060015afa15610c035784838c511603610bcd578a9b8360039c999a9b9c541660405191610ad283611e03565b8c83528d8c8401526040830152803b1561086257610b09938a9360405195869485938493635e65f68960e11b8552600485016121d7565b03915afa908115610bc2578791610bae575b50506005541690813b156108395785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561083d57610b9a575b5091604a925252604082205580f35b610ba390611e1e565b61087c578338610b8b565b610bb790611e1e565b610839578538610b1b565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b6040513d8c823e3d90fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b503461015b5760c036600319011261015b57366023121561015b57604051610c7481611e31565b8060c49136831161087c57602093506004905b838210610ca25784610c9884612035565b6040519015158152f35b81358152908401908401610c87565b503461015b578060031936011261015b576020610ccc611fe6565b604051908152f35b503461015b57602036600319011261015b5760406020916004358152604a83522054604051908152f35b503461015b578060031936011261015b5760008051602061221b833981519152546040516001600160a01b039091168152602090f35b503461015b578060031936011261015b57610d4d611ebf565b60008051602061221b83398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461015b578060031936011261015b576020604854604051908152f35b503461015b5761010036600319011261015b57610dd8611da7565b6024356001600160a01b038116810361135f57604435906001600160a01b038216820361135f57606435906001600160a01b038216820361135f57610e1b611dbd565b60a43591906001600160a01b038316830361135f5760c4356001600160401b03811161135b57610e4f903690600401611dd3565b94909560008051602061223b83398151915254976001600160401b038916158061134d575b60016001600160401b038b16149081611343575b15908161133a575b5061132857610edf9060016001600160401b03198b161760008051602061223b8339815191525560ff8a60401c16156112fb575b8a5460ff19166001178b55610ed7611f6c565b610183611f6c565b650526f6c6c75760d41b6020604051610ef781611e4c565b600681520152603160f81b6020604051610f1081611e4c565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a08152610fa681611e31565b5190206001556bffffffffffffffffffffffff60a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d54801580156112df575b1561126a57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b03821161086657600160401b8211610866578054828255808310611240575b50829060005260206000209060005b8381106112255750505060005b81811061116057505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a16001820180921161114a5760ff91604d556110e460e435611f9b565b60401c16156110f05780f35b68ff00000000000000001960008051602061223b833981519152541660008051602061223b833981519152557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361118a6104d384878961213d565b1660005260205260ff604060002054166111e5576111e091600052604c602052604060002060018060a01b036111c46104d384878961213d565b166000526020526040600020600160ff19825416179055612015565b61108a565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b600190602061123384612129565b930192818501550161107d565b816000526020600020908382015b818301811061125e57505061106e565b6000815560010161124e565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161114a57600052604c6020526000611023565b68ffffffffffffffffff198a16680100000000000000011760008051602061223b83398151915255610ec4565b60405163f92ee8a960e01b8152600490fd5b90501538610e90565b303b159150610e88565b5060ff8960401c1615610e74565b8780fd5b600080fd5b503461015b578060031936011261015b5760ff6020915416604051908152f35b503461015b57602036600319011261015b576004356040811015610c495760209060080154604051908152f35b503461015b5761048036600319011261015b576001600160401b03600435818111611ba6576113e4903690600401611d7a565b9091366101a41161087c57366104241161087c5780610464351161087c573660236104643501121561087c57610464356004013511611ba657366024606061046435600401350261046435010111611ba65733835260496020526001604084205403611b6a57604e5460018101809111611b56575b604d54811015611b4f57808452604c6020526104443560026040862001541161148e578061148991604e55612015565b611459565b50905b604e548352604c60205260408320916114a8611fe6565b6101a43503611af957835b601281106118fb57506115036040516114cb81611e31565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612035565b156118bf5760018301548060011b90808204600214901517156118485760039004600181018091116118485761046435600401351061185c576040516101c43560208201526104443560408201526104243560608201526060815261156781611e67565b6020815191012092600161044435016104443511611848576040516020810190600161044435018252856040820152604081526115a381611e03565b519020604051906115b382611e4c565b6008825267506f6c796261736560c01b602083015260405190816020810193600160c31b85528051908a5b82811061183057505090611605926048928201906028820152036028810184520182611e9e565b5190206104643560040135156117fb5785939291849190825b610464356004013584106116d75750506002546001600160a01b031693915050823b1561087c57604051633b07787160e21b81526104206004820152928492849283918291611672916104248401916121b6565b6101806024808401376101a4356101a48301526101c4356101c48301526102406101e48084013703915afa801561083d576116c3575b50506116b66101c435611f9b565b6006556104443560075580f35b6116cc90611e1e565b610c495781386116a8565b90919293949560209061172660608702610464350160405191816044849301359060ff60646024830135920135168a859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa15610bc25787519060018060a01b03808316918260005284602052600160ff604060002054161515036117b6571610156117785761176d9093612015565b91908795949361161e565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b602082820181015160288884010152869450016115de565b634e487b7160e01b85526011600452602485fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b60018101808211611ae55761190f9061214d565b35600282018211611ae5576119266002830161214d565b358015611ade57818752604a602052604087205480611a8b5750604b60205260016040882001548061198b5760405162461bcd60e51b815260206004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152606490fd5b03611a505760018060a01b036020816005541691838952604b82526044600160408b2092835416920154918a604051958694859363a9059cbb60e01b8552600485015260248401525af18015610bc2576119ec918891611a21575b50612178565b8552604b602052600060016040872087815501555b60038101809111156114b357634e487b7160e01b85526011600452602485fd5b611a43915060203d602011611a49575b611a3b8183611e9e565b810190612160565b386119e6565b503d611a31565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b03611aa3578552604a60205260006040862055611a01565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152606490fd5b5050611a01565b634e487b7160e01b86526011600452602486fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b5090611491565b634e487b7160e01b84526011600452602484fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b503461015b578060031936011261015b576005546040516001600160a01b039091168152602090f35b503461015b57602036600319011261015b57611bed611da7565b611bf5611ebf565b6001600160a01b031681526049602052604081206001905580f35b503461015b57608036600319011261015b576004356001600160401b038111610c4957611c41903690600401611d7a565b91906024359060443591808452602091604a83526040852054610c0e576003546040516001600160a01b0397909291881691611c7c84611e03565b84845286868501526064356040850152823b1561135b57604051635e65f68960e11b81529388938593909284928392611cb892600485016121d7565b03915afa8015611d3557611d40575b50818495600595949554166064604051809681936323b872dd60e01b83523360048401523060248401528960448401525af1928315611d3557604a93611d13918791611d1e5750612178565b845252604082205580f35b611a439150843d8611611a4957611a3b8183611e9e565b6040513d87823e3d90fd5b93611d4d83969495611e1e565b939294611cc7565b905034610c495781600319360112610c49576003546001600160a01b03168152602090f35b9181601f8401121561135f578235916001600160401b03831161135f576020838186019501011161135f57565b600435906001600160a01b038216820361135f57565b608435906001600160a01b038216820361135f57565b9181601f8401121561135f578235916001600160401b03831161135f576020808501948460051b01011161135f57565b606081019081106001600160401b0382111761086657604052565b6001600160401b03811161086657604052565b60c081019081106001600160401b0382111761086657604052565b604081019081106001600160401b0382111761086657604052565b608081019081106001600160401b0382111761086657604052565b61080081019081106001600160401b0382111761086657604052565b90601f801991011681019081106001600160401b0382111761086657604052565b60008051602061221b833981519152546001600160a01b03163303611ee057565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115611f535760008051602061221b83398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b60ff60008051602061223b8339815191525460401c1615611f8957565b604051631afcd79f60e31b8152600490fd5b6048546040811015611fc3576008015560485460018101811161114a57600160409108604855565b634e487b7160e01b600052603260045260246000fd5b9190820391821161114a57565b603f60485480612002575b506040811015611fc3576008015490565b60001981019150811161114a5738611ff1565b600019811461114a5760010190565b906006811015611fc35760051b0190565b60409081519161204483611e31565b60009182845282602085015282828501528260608501528260808501528260a0850152825b600681106120aa57505050805b6006811061208657505050600190565b6120908184612024565b51156120a45761209f90612015565b612076565b50905090565b835b8381106120c3575b506120be90612015565b612069565b6120cd8284612024565b518160080154146120e6576120e190612015565b6120ac565b508060016120f76120be9388612024565b52906120b4565b6001600160401b0381116108665760051b60200190565b8051821015611fc35760209160051b010190565b356001600160a01b038116810361135f5790565b9190811015611fc35760051b0190565b6012811015611fc35760051b6101e40190565b9081602091031261135f5751801515810361135f5790565b1561217f57565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b908060209392818452848401376000828201840152601f01601f1916010190565b939291906121ed916080865260808601916121b6565b9260208091016000905b600382106122055750505050565b828060019286518152019401910190926121f756fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212208e854684387c37eb7ab500a6ec129cf1b9dc5a3a906bf4457a31fcb26640499c64736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.d.ts b/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.d.ts deleted file mode 100644 index 7b0ecb3..0000000 --- a/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.d.ts +++ /dev/null @@ -1,1144 +0,0 @@ -// This file was autogenerated by hardhat-viem, do not edit it. -// prettier-ignore -// tslint:disable -// eslint-disable - -import type { Address } from "viem"; -import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; -import "@nomicfoundation/hardhat-viem/types"; - -export interface RollupV5$Type { - "_format": "hh-sol-artifact-1", - "contractName": "RollupV5", - "sourceName": "contracts/rollup/RollupV5.sol", - "abi": [ - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - } - ], - "name": "BlockVerified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToAddress", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToRouter", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Minted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "name": "ValidatorSetAdded", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "prover", - "type": "address" - } - ], - "name": "addProver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "addRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "aggregateVerifier", - "outputs": [ - { - "internalType": "contract AggregateVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "to", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burnToAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "internalType": "bytes", - "name": "routerCalldata", - "type": "bytes" - }, - { - "internalType": "address", - "name": "returnAddress", - "type": "address" - } - ], - "name": "burnToRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifier", - "outputs": [ - { - "internalType": "contract BurnVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifierV2", - "outputs": [ - { - "internalType": "contract BurnVerifierV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_bytes32", - "type": "bytes32" - } - ], - "name": "bytes32ToAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[6]", - "name": "hashes", - "type": "bytes32[6]" - } - ], - "name": "containsRootHashes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentRootHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getBurn", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Burn", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRootHashes", - "outputs": [ - { - "internalType": "bytes32[64]", - "name": "", - "type": "bytes32[64]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "from", - "type": "uint256" - } - ], - "name": "getValidatorSets", - "outputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "internalType": "struct PublicValidatorSet[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - } - ], - "name": "hasBurn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_usdcAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_aggregateVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_mintVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_burnVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "prover", - "type": "address" - }, - { - "internalType": "address[]", - "name": "initialValidators", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "emptyMerkleTreeRootHash", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV4", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_burnVerifierV2", - "type": "address" - } - ], - "name": "initializeV5", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "isRouterWhitelisted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintVerifier", - "outputs": [ - { - "internalType": "contract MintVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "validAfter", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "validBefore", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v2", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s2", - "type": "bytes32" - } - ], - "name": "mintWithAuthorization", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "nextRootHashIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "removeRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "rootHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - } - ], - "name": "setRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "setValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usdc", - "outputs": [ - { - "internalType": "contract IUSDC", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - } - ], - "name": "verifyBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "gasPerBurnCall", - "type": "uint256" - } - ], - "name": "verifyBlock2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60808060405234620000bd577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c16620000ae57506001600160401b036002600160401b03198282160162000068575b60405161394c9081620000c38239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a138808062000058565b63f92ee8a960e01b8152600490fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612838575080630aef023f146127f95780631000b7291461266d5780631d49e4571461263057806324ca984e146125ab5780633644e5151461259057806338e454b1146125105780633e413bee146124e757806345873f3f1461219b578063485ee1e41461217c5780634fb4eee314611b6057806353b9355714611b3357806354a0860614611ab357806354ace9331461167257806354fd4d50146116525780635a023693146115ad5780635cd8a76b1461152d5780635ced058e146115055780635eeba6dd14610fc75780636779b7c214610fa95780636ae0b15414610f68578063715018a614610efd57806382f15a3b14610dcb5780638da5cb5b14610d95578063a2ce9c1f14610d6b578063a65ddebd14610d42578063a91eebf514610d1f578063afbd8c3914610cbb578063b5061658146109eb578063c072bd88146109c2578063c3a716eb14610999578063c832fe5f14610914578063cb3258331461078c578063dab5f34014610767578063e4408e4614610700578063e795594d14610434578063ef0feff914610243578063f22a195e14610225578063f2fde38b146101f85763f44ff712146101d857600080fd5b346101f557806003193601126101f5576020600754604051908152f35b80fd5b50346101f55760203660031901126101f55761022261021561285d565b61021d6129d2565b612a0b565b80f35b50346101f557806003193601126101f5576020600654604051908152f35b50346101f557602090816003193601126101f55790600435604d546102688282612b46565b9161027283612b82565b9261028060405194856129b1565b80845261028f601f1991612b82565b01855b818110610407575050805b8281106103585750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102da5787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061033557505050906001938380809401519101529801930193019092879695939492946102cd565b82516001600160a01b031685528a9594850194909201916001919091019061030a565b808694959652604c86526040842060016002818301920154906040519261037e8461297a565b60405191828b83549182815201928a528b8a20918a915b8d8184106103e957505050505091816103b86103e09695936103da9503826129b1565b8252898201526103c88584612b46565b906103d3828a612ba8565b5287612ba8565b50612b99565b9493929461029d565b84546001600160a01b03168652909401939281019291810191610395565b9480809795966040516104198161297a565b60608152878382015282828a01015201905095949395610292565b50346101f55760403660031901126101f5576004356001600160401b03602480358281116106fc5761046a9036906004016128e6565b92906104746129d2565b604d938454801580156106c2575b1561064e57600052604c916020928084528760026040600020015586546000526001948560406000200190841161063957600160401b841161063957805484825580851061061c575b50829060005284600020908660005b868110610603575050505060005b838110610546575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161053257505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b0391908261057261056d868a8a612be7565b612bd3565b16600052875260ff604060002054166105c457906105bf92916000528387526040600020906105a561056d848989612be7565b16600052865260406000208760ff19825416179055612b99565b6104e8565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761060d84612bd3565b930192818501550187906104da565b610633908260005285876000209182019101612bbc565b386104cb565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116106e757600052604c6020528660026040600020015410610482565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346101f55760203660031901126101f5576040818192602083516107248161297a565b82815201526004358152604b60205220815161073f8161297a565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b50346101f55760203660031901126101f5576107816129d2565b610222600435612b08565b50346101f55760c03660031901126101f5576107a661285d565b6001600160401b03602435818111610910576107c6903690600401612889565b9091604435606435926107d886612ecc565b600454604051966001600160a01b03949185169160a0890191908211898310176108fa57859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b156108f657604051625a2d8360e11b815260c060048201528a94909392916108529160c4860191612d3b565b908489602486015b600583106108dc575050505083918380809303915afa80156108d1576108b9575b5050600193604b91604051966108908861297a565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6108c290612931565b6108cd57853861087b565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b910161085a565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b50346101f557806003193601126101f5576040519061093282612995565b610800809236903760405190600881835b60408210610983575050509061095881612995565b6040519190825b6040831061096c57505050f35b60019082518152602080910192019201919061095f565b6001602081928554815201930191019091610943565b50346101f557806003193601126101f5576004546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576002546040516001600160a01b039091168152602090f35b50346101f5576101c03660031901126101f5576001600160401b0390600435828111610cb757610a1f903690600401612889565b90602435906044359260643595610a34612873565b9060a4359260c4359260e43591878a52602096604a885260408b2054610c7c57604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528a60408801528b60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e082015261010087818301528152610120810192818410908411176108fa57610b238692610b2c928a956040525190208c610ae2612cea565b916040519182019261190160f01b84526022830152604282015260428152610b098161295f565b5190206101a43590610184359060ff610164351690612db7565b90929192612e47565b1603610c46578a9b8360039c999a9b9c541660405191610b4b83612916565b8c83528d8c8401526040830152803b156108f657610b82938a9360405195869485938493635e65f68960e11b855260048501612d5c565b03915afa908115610c3b578791610c27575b50506005541690813b156108cd5785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af180156108d157610c13575b5091604a925252604082205580f35b610c1c90612931565b610910578338610c04565b610c3090612931565b6108cd578538610b94565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346101f55760c03660031901126101f55736602312156101f557604051610ce281612944565b8060c49136831161091057602093506004905b838210610d105784610d0684612c08565b6040519015158152f35b81358152908401908401610cf5565b50346101f557806003193601126101f5576020610d3a612b53565b604051908152f35b50346101f557806003193601126101f5576052546040516001600160a01b039091168152602090f35b50346101f55760203660031901126101f55760406020916004358152604a83522054604051908152f35b50346101f557806003193601126101f5576000805160206138b7833981519152546040516001600160a01b039091168152602090f35b50346101f55760e03660031901126101f5576024356004356044356001600160401b03811161091057610e02903690600401612889565b906064358560843593610e158615612f87565b6001600160a01b0387811697909490610e2d89612ecc565b856052541660405191610e3f83612944565b898352602083015285604083015287606083015260a435608083015260c43560a0830152803b156106fc57610e8d9385936040519586948593849363e261a9cb60e01b855260048501612fc2565b03915afa80156108d157610ee9575b50938160019552604f602052604087205560405194610eba8661297a565b8552602085019283528552604b602052604085209351166001600160601b0360a01b8454161783555191015580f35b610ef290612931565b6108cd578538610e9c565b50346101f557806003193601126101f557610f166129d2565b6000805160206138b783398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101f55760203660031901126101f557610f8261285d565b610f8a6129d2565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346101f557806003193601126101f5576020604854604051908152f35b50346101f5576101003660031901126101f557610fe261285d565b6024356001600160a01b038116810361150057604435906001600160a01b038216820361150057606435906001600160a01b038216820361150057611025612873565b60a43591906001600160a01b03831683036115005760c4356001600160401b0381116114fc576110599036906004016128e6565b9490956000805160206138f783398151915254976001600160401b03891615806114ee575b60016001600160401b038b161490816114e4575b1590816114db575b506114c9576110e99060016001600160401b03198b16176000805160206138f78339815191525560ff8a60401c161561149c575b8a5460ff19166001178b556110e1612ad9565b61021d612ad9565b6110f1612a9a565b6020815191012061115c61116a611106612abc565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f1981018352826129b1565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611480575b1561140b57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b0382116108fa57600160401b82116108fa5780548282558083106113ed575b50829060005260206000209060005b8381106113d25750505060005b81811061130d57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116112f75760ff91604d556112a360e435612b08565b60401c16156112af5780f35b68ff0000000000000000196000805160206138f783398151915254166000805160206138f7833981519152556000805160206138d7833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361133761056d848789612be7565b1660005260205260ff604060002054166113925761138d91600052604c602052604060002060018060a01b0361137161056d848789612be7565b166000526020526040600020600160ff19825416179055612b99565b611249565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b60019060206113e084612bd3565b930192818501550161123c565b61140590826000528360206000209182019101612bbc565b3861122d565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116112f757600052604c60205260006111e2565b68ffffffffffffffffff198a1668010000000000000001176000805160206138f7833981519152556110ce565b60405163f92ee8a960e01b8152600490fd5b9050153861109a565b303b159150611092565b5060ff8960401c161561107e565b8780fd5b600080fd5b50346101f55760203660031901126101f5576040516004356001600160a01b03168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611599575b6114c9576002908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160028152a180f35b5060026001600160401b038216101561155d565b50346101f55760203660031901126101f5576115c761285d565b6000805160206138f783398151915290815460ff8160401c16801561163e575b6114c9576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160058152a180f35b5060056001600160401b03821610156115e7565b50346101f557806003193601126101f55760ff6020915416604051908152f35b50346101f5576101403660031901126101f5576001600160401b0390602435604435838111611aaf576116a9903690600401612889565b93909160e435906001600160a01b038216820361150057610104358381116108cd576116d9903690600401612889565b6101243595919290916001600160a01b038716870361150057611700600160043514612f87565b6001600160a01b03871615611a71576001600160a01b03851688526051602052604088205460ff1615611a3357604051988260208b019a60018060a01b0388168c52606060408201528061175860808201888a612d3b565b6001600160a01b038c16606083015203601f1981810183529c9061177c90836129b1565b905190206001600160fd1b031603611a005760018060a01b036052541691604051936117a785612944565b600435855260208501526064356040850152608435606085015260a435608085015260c43560a0850152823b156108f65760405163e261a9cb60e01b8152938a9385939092849283926117fd9260048501612fc2565b03915afa8015610c3b579087916119ec575b50506064358652604f6020526004356040872055604051926118308461295f565b6001600160a01b0316835261184481612a7f565b9161185260405193846129b1565b81835236828201116119e8578187926020928386013783010152602082810191825260843560408085019182526001600160a01b03968716606086019081526064358952605090935287209351845496166001600160a01b031996871617845591518051909791959460018501929082116119d4576118d18354613005565b601f8111611999575b50602090601f8311600114611934575081908899600397989992611929575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b039051169082541617905580f35b0151905038806118f9565b8216988389526020892099895b81811061198157509160039798999a91846001959410611969575b505050811b01905561190d565b015160001983891b60f8161c1916905538808061195c565b838301518c556001909b019a60209384019301611941565b6119c490848a5260208a20601f850160051c810191602086106119ca575b601f0160051c0190612bbc565b386118da565b90915081906119b7565b634e487b7160e01b88526041600452602488fd5b8680fd5b6119f590612931565b6108cd57853861180f565b60405162461bcd60e51b815260206004820152600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b8280fd5b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611b1f575b6114c9576004908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160048152a180f35b5060046001600160401b0382161015611ae3565b50346101f55760203660031901126101f5576004356040811015610cb75760209060080154604051908152f35b50346101f5576104803660031901126101f5576001600160401b0390600435828111610cb757611b94903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf57611bc19036906004016128b6565b9290913382526049602052611bdc600160408420541461303f565b3382526049602052611bf4600160408420541461303f565b604e93845460018101809111612168575b604d5481101561215c57808452604c60205261044435600260408620015411611c395780611c34918755612b99565b611c05565b509193949092945b548452604c6020526040842092611c56612b53565b926101a43593840361210657855b6012811061208a5750611cb4604051611c7c81612944565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612c08565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c435602082015261044435604082015261042435606082015260608152611d118161295f565b6020815191012094600161044435016104443511611fd757604051602081019060016104443501825287604082015260408152611d4d81612916565b51902060405190611d5d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b828110611fbf57505090611dad9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b848210611e9d578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156108d157611e89575b5050611e4a6101c435612b08565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b611e9290612931565b610cb7578183611e3c565b611ecc90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b90949194612e47565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f0757611f019091612b99565b90611dbd565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b60208282018101516028888401015286945001611d86565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116120f25761209e90613082565b35600282018083116120de57906120b76120be92613082565b35906130d7565b6003810180911115611c6457634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294611c41565b634e487b7160e01b84526011600452602484fd5b50346101f55760203660031901126101f5576020610d06600435612d0d565b50346101f5576104a03660031901126101f5576001600160401b0390600435828111610cb7576121cf903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf576121fc9036906004016128b6565b9290913382526049602052612217600160408420541461303f565b604e93845460018101809111612168575b604d548110156124db57808452604c6020526104443560026040862001541161225c5780612257918755612b99565b612228565b509193949092945b548452604c6020526040842092612279612b53565b926101a4359384036121065761048435865b601281106124725750506122a4604051611c7c81612944565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c4356020820152610444356040820152610424356060820152606081526123018161295f565b6020815191012094600161044435016104443511611fd75760405160208101906001610444350182528760408201526040815261233d81612916565b5190206040519061234d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061245a5750509061239d9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b8482106123f9578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b61241f90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f07576124549091612b99565b906123ad565b60208282018101516028888401015286945001612376565b600181018082116120de5761248690613082565b35600282018083116124c7576124a7916124a08592613082565b35906135ca565b600381018091111561228b57634e487b7160e01b88526011600452602488fd5b634e487b7160e01b8a52601160045260248afd5b50919394909294612264565b50346101f557806003193601126101f5576005546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c16801561257c575b6114c9576003908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160038152a180f35b5060036001600160401b0382161015612540565b50346101f557806003193601126101f5576020610d3a612cea565b50346101f55760203660031901126101f5576125c561285d565b6125cd6129d2565b803b156125f6576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b50346101f55760203660031901126101f55761264a61285d565b6126526129d2565b6001600160a01b031681526049602052604081206001905580f35b50346101f55760803660031901126101f5576004356001600160401b038111610cb75761269e903690600401612889565b9060243560443592818552602092604a84526040862054610c7c576003546040516001600160a01b039388928516906126d683612916565b86835288888401526064356040840152813b156109105761270e9460405195869485938493635e65f68960e11b855260048501612d5c565b03915afa80156127ee576127dd575b50828591600554166064604051809481936323b872dd60e01b83523360048401523060248401528960448401525af19081156127d25785916127a5575b501561276e578352604a9052604082205580f35b60405162461bcd60e51b815260048101839052600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b6127c59150833d85116127cb575b6127bd81836129b1565b810190612d9f565b3861275a565b503d6127b3565b6040513d87823e3d90fd5b946127e88496612931565b9461271d565b6040513d88823e3d90fd5b50346101f55760203660031901126101f55760209060ff906040906001600160a01b0361282461285d565b168152605184522054166040519015158152f35b905034610cb75781600319360112610cb7576003546001600160a01b03168152602090f35b600435906001600160a01b038216820361150057565b608435906001600160a01b038216820361150057565b9181601f84011215611500578235916001600160401b038311611500576020838186019501011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501946060850201011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501948460051b01011161150057565b606081019081106001600160401b038211176108fa57604052565b6001600160401b0381116108fa57604052565b60c081019081106001600160401b038211176108fa57604052565b608081019081106001600160401b038211176108fa57604052565b604081019081106001600160401b038211176108fa57604052565b61080081019081106001600160401b038211176108fa57604052565b90601f801991011681019081106001600160401b038211176108fa57604052565b6000805160206138b7833981519152546001600160a01b031633036129f357565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612a66576000805160206138b783398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b0381116108fa57601f01601f191660200190565b60405190612aa78261297a565b60068252650526f6c6c75760d41b6020830152565b60405190612ac98261297a565b60018252603160f81b6020830152565b60ff6000805160206138f78339815191525460401c1615612af657565b604051631afcd79f60e31b8152600490fd5b6048546040811015612b3057600801556048546001810181116112f757600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116112f757565b603f60485480612b6f575b506040811015612b30576008015490565b6000198101915081116112f75738612b5e565b6001600160401b0381116108fa5760051b60200190565b60001981146112f75760010190565b8051821015612b305760209160051b010190565b818110612bc7575050565b60008155600101612bbc565b356001600160a01b03811681036115005790565b9190811015612b305760051b0190565b906006811015612b305760051b0190565b604090815191612c1783612944565b60009182845282602085015282828501528260608501528260808501528260a0850152825b60068110612c7d57505050805b60068110612c5957505050600190565b612c638184612bf7565b5115612c7757612c7290612b99565b612c49565b50905090565b835b838110612c96575b50612c9190612b99565b612c3c565b612ca08284612bf7565b518160080154148015612cd8575b612cc057612cbb90612b99565b612c7f565b50806001612cd1612c919388612bf7565b5290612c87565b50612ce38284612bf7565b5115612cae565b612cf2612a9a565b6020815191012061115c612d07611106612abc565b51902090565b600052604f60205260406000205415600014612d3657604b602052600160406000200154151590565b600190565b908060209392818452848401376000828201840152601f01601f1916010190565b93929190612d7291608086526080860191612d3b565b9260208091016000905b60038210612d8a5750505050565b82806001928651815201940191019092612d7c565b90816020910312611500575180151581036115005790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612e3b57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612e2f5780516001600160a01b03811615612e2657918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612eb65780612e59575050565b60018103612e735760405163f645eedf60e01b8152600490fd5b60028103612e945760405163fce698f760e01b815260048101839052602490fd5b600314612e9e5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b612ed590612f20565b612edb57565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa908115612f7b57600091612f60575090565b612f78915060203d81116127cb576127bd81836129b1565b90565b6040513d6000823e3d90fd5b15612f8e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b93929190612fd89160e0865260e0860191612d3b565b9260208091016000905b60068210612ff05750505050565b82806001928651815201940191019092612fe2565b90600182811c92168015613035575b602083101461301f57565b634e487b7160e01b600052602260045260246000fd5b91607f1691613014565b1561304657565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612b305760051b6101e40190565b1561309c57565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b9080156135c657600091808352602090604a825260409283852054806135495750604f835283852054806132715750818552604b8352838520600101548015613234576131249114613095565b808452604b8252828420546001600160a01b039081168061318e575b50918160019493604b9387528383527fd4c4548158257b028886d6db0faf9617bed9f9ec7f968df34f862c4c3a282f898387878a20938454169301548751908152a285525282208281550155565b61319790612f20565b156131a3575b38613140565b600554828652604b84528486208054600190910154865163a9059cbb60e01b81529184166001600160a01b031660048301526024820152908490829084168189816044810103925af1801561322a5791604b9391600196959361320d575b5091939450915061319d565b61322390843d86116127cb576127bd81836129b1565b5038613201565b85513d88823e3d90fd5b5050509150606492505b519062461bcd60e51b82526004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152fd5b9592949190600180971461328c57505050506064925061323e565b6050869395949652838520908451906132a48261295f565b60018060a01b0398898454168352808401875180928a908354936132c785613005565b948585528b83821691826000146135275750506001146134eb575b50506132f0925003826129b1565b85830190815261331a6002850154928b60038a870197868952015416936060860194855214613095565b60055483518551895163095ea7b360e01b808252928e166001600160a01b031660048201526024810191909152909291889082908e16818d816044810103925af180156134e1579061337992916134c4575b508b855116905190613802565b156133bc575b505083604f959697987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d92511692518751908152a2845252812055565b858a600554169160448c865116918b8b519586948593845260048401528160248401525af180156134ba579186916134309361349d575b5060055490518551895163a9059cbb60e01b8152918d166001600160a01b0316600483015260248201529283918c169082908b9082906044820190565b03925af1801561349357987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d928692604f98999a9b613476575b5092509897969561337f565b61348c90843d86116127cb576127bd81836129b1565b503861346a565b86513d89823e3d90fd5b6134b390833d85116127cb576127bd81836129b1565b50386133f3565b87513d8a823e3d90fd5b6134da90893d8b116127cb576127bd81836129b1565b503861336c565b89513d8c823e3d90fd5b8a92508c52818c20908c915b85831061350f5750506132f0935082010138806132e2565b80548388018501528694508b939092019181016134f7565b92509350506132f094915060ff191682840152151560051b82010138806132e2565b0361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b50606491519062461bcd60e51b825260048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152fd5b5050565b919080156137fd57600092808452602091604a835260409384862054806137b75750604f84528486205480613619575050818552604b8352838520600101548015613234576131249114613095565b6001979496939291978091146136375750505050506064925061323e565b60508794969597528486209185519161364f8361295f565b60018060a01b03998a91828654168552808601908951918b9181549161367483613005565b92838652858d848316928360001461379457505050600114613751575b505050816136a09103826129b1565b8785019081526136ca6002870154948460038c890199888b52015416956060880196875214613095565b600554855187518b5163095ea7b360e01b8082529287166001600160a01b031660048201526024810191909152909490918a91839116818e816044810103925af18015613747579061337993929161372a575b508c86511690519061386c565b613740908a3d8c116127cb576127bd81836129b1565b503861371d565b8a513d8d823e3d90fd5b8d528a8d208b93508d9291905b82841061377557505050820101816136a038613691565b81949295969750805483858901015201910190928a928f96959461375e565b925093509391506136a0945060ff191682840152151560051b8201019138613691565b90500361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b505050565b6001600160a01b038116600090815260516020526040812054909283929160ff161561386657829182602083519301916207a120f1903d15613862573d9061384982612a7f565b9161385760405193846129b1565b825260203d92013e90565b5090565b50505090565b6001600160a01b038116600090815260516020526040812054909384939160ff16156138af5783809360208451940192f1903d15613862573d9061384982612a7f565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220f4bb08c972b912d5922423b946a85ed2172262c9e905b1535998153c03460be464736f6c63430008140033", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612838575080630aef023f146127f95780631000b7291461266d5780631d49e4571461263057806324ca984e146125ab5780633644e5151461259057806338e454b1146125105780633e413bee146124e757806345873f3f1461219b578063485ee1e41461217c5780634fb4eee314611b6057806353b9355714611b3357806354a0860614611ab357806354ace9331461167257806354fd4d50146116525780635a023693146115ad5780635cd8a76b1461152d5780635ced058e146115055780635eeba6dd14610fc75780636779b7c214610fa95780636ae0b15414610f68578063715018a614610efd57806382f15a3b14610dcb5780638da5cb5b14610d95578063a2ce9c1f14610d6b578063a65ddebd14610d42578063a91eebf514610d1f578063afbd8c3914610cbb578063b5061658146109eb578063c072bd88146109c2578063c3a716eb14610999578063c832fe5f14610914578063cb3258331461078c578063dab5f34014610767578063e4408e4614610700578063e795594d14610434578063ef0feff914610243578063f22a195e14610225578063f2fde38b146101f85763f44ff712146101d857600080fd5b346101f557806003193601126101f5576020600754604051908152f35b80fd5b50346101f55760203660031901126101f55761022261021561285d565b61021d6129d2565b612a0b565b80f35b50346101f557806003193601126101f5576020600654604051908152f35b50346101f557602090816003193601126101f55790600435604d546102688282612b46565b9161027283612b82565b9261028060405194856129b1565b80845261028f601f1991612b82565b01855b818110610407575050805b8281106103585750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102da5787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061033557505050906001938380809401519101529801930193019092879695939492946102cd565b82516001600160a01b031685528a9594850194909201916001919091019061030a565b808694959652604c86526040842060016002818301920154906040519261037e8461297a565b60405191828b83549182815201928a528b8a20918a915b8d8184106103e957505050505091816103b86103e09695936103da9503826129b1565b8252898201526103c88584612b46565b906103d3828a612ba8565b5287612ba8565b50612b99565b9493929461029d565b84546001600160a01b03168652909401939281019291810191610395565b9480809795966040516104198161297a565b60608152878382015282828a01015201905095949395610292565b50346101f55760403660031901126101f5576004356001600160401b03602480358281116106fc5761046a9036906004016128e6565b92906104746129d2565b604d938454801580156106c2575b1561064e57600052604c916020928084528760026040600020015586546000526001948560406000200190841161063957600160401b841161063957805484825580851061061c575b50829060005284600020908660005b868110610603575050505060005b838110610546575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161053257505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b0391908261057261056d868a8a612be7565b612bd3565b16600052875260ff604060002054166105c457906105bf92916000528387526040600020906105a561056d848989612be7565b16600052865260406000208760ff19825416179055612b99565b6104e8565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761060d84612bd3565b930192818501550187906104da565b610633908260005285876000209182019101612bbc565b386104cb565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116106e757600052604c6020528660026040600020015410610482565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346101f55760203660031901126101f5576040818192602083516107248161297a565b82815201526004358152604b60205220815161073f8161297a565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b50346101f55760203660031901126101f5576107816129d2565b610222600435612b08565b50346101f55760c03660031901126101f5576107a661285d565b6001600160401b03602435818111610910576107c6903690600401612889565b9091604435606435926107d886612ecc565b600454604051966001600160a01b03949185169160a0890191908211898310176108fa57859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b156108f657604051625a2d8360e11b815260c060048201528a94909392916108529160c4860191612d3b565b908489602486015b600583106108dc575050505083918380809303915afa80156108d1576108b9575b5050600193604b91604051966108908861297a565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6108c290612931565b6108cd57853861087b565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b910161085a565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b50346101f557806003193601126101f5576040519061093282612995565b610800809236903760405190600881835b60408210610983575050509061095881612995565b6040519190825b6040831061096c57505050f35b60019082518152602080910192019201919061095f565b6001602081928554815201930191019091610943565b50346101f557806003193601126101f5576004546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576002546040516001600160a01b039091168152602090f35b50346101f5576101c03660031901126101f5576001600160401b0390600435828111610cb757610a1f903690600401612889565b90602435906044359260643595610a34612873565b9060a4359260c4359260e43591878a52602096604a885260408b2054610c7c57604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528a60408801528b60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e082015261010087818301528152610120810192818410908411176108fa57610b238692610b2c928a956040525190208c610ae2612cea565b916040519182019261190160f01b84526022830152604282015260428152610b098161295f565b5190206101a43590610184359060ff610164351690612db7565b90929192612e47565b1603610c46578a9b8360039c999a9b9c541660405191610b4b83612916565b8c83528d8c8401526040830152803b156108f657610b82938a9360405195869485938493635e65f68960e11b855260048501612d5c565b03915afa908115610c3b578791610c27575b50506005541690813b156108cd5785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af180156108d157610c13575b5091604a925252604082205580f35b610c1c90612931565b610910578338610c04565b610c3090612931565b6108cd578538610b94565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346101f55760c03660031901126101f55736602312156101f557604051610ce281612944565b8060c49136831161091057602093506004905b838210610d105784610d0684612c08565b6040519015158152f35b81358152908401908401610cf5565b50346101f557806003193601126101f5576020610d3a612b53565b604051908152f35b50346101f557806003193601126101f5576052546040516001600160a01b039091168152602090f35b50346101f55760203660031901126101f55760406020916004358152604a83522054604051908152f35b50346101f557806003193601126101f5576000805160206138b7833981519152546040516001600160a01b039091168152602090f35b50346101f55760e03660031901126101f5576024356004356044356001600160401b03811161091057610e02903690600401612889565b906064358560843593610e158615612f87565b6001600160a01b0387811697909490610e2d89612ecc565b856052541660405191610e3f83612944565b898352602083015285604083015287606083015260a435608083015260c43560a0830152803b156106fc57610e8d9385936040519586948593849363e261a9cb60e01b855260048501612fc2565b03915afa80156108d157610ee9575b50938160019552604f602052604087205560405194610eba8661297a565b8552602085019283528552604b602052604085209351166001600160601b0360a01b8454161783555191015580f35b610ef290612931565b6108cd578538610e9c565b50346101f557806003193601126101f557610f166129d2565b6000805160206138b783398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101f55760203660031901126101f557610f8261285d565b610f8a6129d2565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346101f557806003193601126101f5576020604854604051908152f35b50346101f5576101003660031901126101f557610fe261285d565b6024356001600160a01b038116810361150057604435906001600160a01b038216820361150057606435906001600160a01b038216820361150057611025612873565b60a43591906001600160a01b03831683036115005760c4356001600160401b0381116114fc576110599036906004016128e6565b9490956000805160206138f783398151915254976001600160401b03891615806114ee575b60016001600160401b038b161490816114e4575b1590816114db575b506114c9576110e99060016001600160401b03198b16176000805160206138f78339815191525560ff8a60401c161561149c575b8a5460ff19166001178b556110e1612ad9565b61021d612ad9565b6110f1612a9a565b6020815191012061115c61116a611106612abc565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f1981018352826129b1565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611480575b1561140b57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b0382116108fa57600160401b82116108fa5780548282558083106113ed575b50829060005260206000209060005b8381106113d25750505060005b81811061130d57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116112f75760ff91604d556112a360e435612b08565b60401c16156112af5780f35b68ff0000000000000000196000805160206138f783398151915254166000805160206138f7833981519152556000805160206138d7833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361133761056d848789612be7565b1660005260205260ff604060002054166113925761138d91600052604c602052604060002060018060a01b0361137161056d848789612be7565b166000526020526040600020600160ff19825416179055612b99565b611249565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b60019060206113e084612bd3565b930192818501550161123c565b61140590826000528360206000209182019101612bbc565b3861122d565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116112f757600052604c60205260006111e2565b68ffffffffffffffffff198a1668010000000000000001176000805160206138f7833981519152556110ce565b60405163f92ee8a960e01b8152600490fd5b9050153861109a565b303b159150611092565b5060ff8960401c161561107e565b8780fd5b600080fd5b50346101f55760203660031901126101f5576040516004356001600160a01b03168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611599575b6114c9576002908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160028152a180f35b5060026001600160401b038216101561155d565b50346101f55760203660031901126101f5576115c761285d565b6000805160206138f783398151915290815460ff8160401c16801561163e575b6114c9576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160058152a180f35b5060056001600160401b03821610156115e7565b50346101f557806003193601126101f55760ff6020915416604051908152f35b50346101f5576101403660031901126101f5576001600160401b0390602435604435838111611aaf576116a9903690600401612889565b93909160e435906001600160a01b038216820361150057610104358381116108cd576116d9903690600401612889565b6101243595919290916001600160a01b038716870361150057611700600160043514612f87565b6001600160a01b03871615611a71576001600160a01b03851688526051602052604088205460ff1615611a3357604051988260208b019a60018060a01b0388168c52606060408201528061175860808201888a612d3b565b6001600160a01b038c16606083015203601f1981810183529c9061177c90836129b1565b905190206001600160fd1b031603611a005760018060a01b036052541691604051936117a785612944565b600435855260208501526064356040850152608435606085015260a435608085015260c43560a0850152823b156108f65760405163e261a9cb60e01b8152938a9385939092849283926117fd9260048501612fc2565b03915afa8015610c3b579087916119ec575b50506064358652604f6020526004356040872055604051926118308461295f565b6001600160a01b0316835261184481612a7f565b9161185260405193846129b1565b81835236828201116119e8578187926020928386013783010152602082810191825260843560408085019182526001600160a01b03968716606086019081526064358952605090935287209351845496166001600160a01b031996871617845591518051909791959460018501929082116119d4576118d18354613005565b601f8111611999575b50602090601f8311600114611934575081908899600397989992611929575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b039051169082541617905580f35b0151905038806118f9565b8216988389526020892099895b81811061198157509160039798999a91846001959410611969575b505050811b01905561190d565b015160001983891b60f8161c1916905538808061195c565b838301518c556001909b019a60209384019301611941565b6119c490848a5260208a20601f850160051c810191602086106119ca575b601f0160051c0190612bbc565b386118da565b90915081906119b7565b634e487b7160e01b88526041600452602488fd5b8680fd5b6119f590612931565b6108cd57853861180f565b60405162461bcd60e51b815260206004820152600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b8280fd5b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611b1f575b6114c9576004908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160048152a180f35b5060046001600160401b0382161015611ae3565b50346101f55760203660031901126101f5576004356040811015610cb75760209060080154604051908152f35b50346101f5576104803660031901126101f5576001600160401b0390600435828111610cb757611b94903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf57611bc19036906004016128b6565b9290913382526049602052611bdc600160408420541461303f565b3382526049602052611bf4600160408420541461303f565b604e93845460018101809111612168575b604d5481101561215c57808452604c60205261044435600260408620015411611c395780611c34918755612b99565b611c05565b509193949092945b548452604c6020526040842092611c56612b53565b926101a43593840361210657855b6012811061208a5750611cb4604051611c7c81612944565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612c08565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c435602082015261044435604082015261042435606082015260608152611d118161295f565b6020815191012094600161044435016104443511611fd757604051602081019060016104443501825287604082015260408152611d4d81612916565b51902060405190611d5d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b828110611fbf57505090611dad9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b848210611e9d578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156108d157611e89575b5050611e4a6101c435612b08565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b611e9290612931565b610cb7578183611e3c565b611ecc90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b90949194612e47565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f0757611f019091612b99565b90611dbd565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b60208282018101516028888401015286945001611d86565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116120f25761209e90613082565b35600282018083116120de57906120b76120be92613082565b35906130d7565b6003810180911115611c6457634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294611c41565b634e487b7160e01b84526011600452602484fd5b50346101f55760203660031901126101f5576020610d06600435612d0d565b50346101f5576104a03660031901126101f5576001600160401b0390600435828111610cb7576121cf903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf576121fc9036906004016128b6565b9290913382526049602052612217600160408420541461303f565b604e93845460018101809111612168575b604d548110156124db57808452604c6020526104443560026040862001541161225c5780612257918755612b99565b612228565b509193949092945b548452604c6020526040842092612279612b53565b926101a4359384036121065761048435865b601281106124725750506122a4604051611c7c81612944565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c4356020820152610444356040820152610424356060820152606081526123018161295f565b6020815191012094600161044435016104443511611fd75760405160208101906001610444350182528760408201526040815261233d81612916565b5190206040519061234d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061245a5750509061239d9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b8482106123f9578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b61241f90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f07576124549091612b99565b906123ad565b60208282018101516028888401015286945001612376565b600181018082116120de5761248690613082565b35600282018083116124c7576124a7916124a08592613082565b35906135ca565b600381018091111561228b57634e487b7160e01b88526011600452602488fd5b634e487b7160e01b8a52601160045260248afd5b50919394909294612264565b50346101f557806003193601126101f5576005546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c16801561257c575b6114c9576003908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160038152a180f35b5060036001600160401b0382161015612540565b50346101f557806003193601126101f5576020610d3a612cea565b50346101f55760203660031901126101f5576125c561285d565b6125cd6129d2565b803b156125f6576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b50346101f55760203660031901126101f55761264a61285d565b6126526129d2565b6001600160a01b031681526049602052604081206001905580f35b50346101f55760803660031901126101f5576004356001600160401b038111610cb75761269e903690600401612889565b9060243560443592818552602092604a84526040862054610c7c576003546040516001600160a01b039388928516906126d683612916565b86835288888401526064356040840152813b156109105761270e9460405195869485938493635e65f68960e11b855260048501612d5c565b03915afa80156127ee576127dd575b50828591600554166064604051809481936323b872dd60e01b83523360048401523060248401528960448401525af19081156127d25785916127a5575b501561276e578352604a9052604082205580f35b60405162461bcd60e51b815260048101839052600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b6127c59150833d85116127cb575b6127bd81836129b1565b810190612d9f565b3861275a565b503d6127b3565b6040513d87823e3d90fd5b946127e88496612931565b9461271d565b6040513d88823e3d90fd5b50346101f55760203660031901126101f55760209060ff906040906001600160a01b0361282461285d565b168152605184522054166040519015158152f35b905034610cb75781600319360112610cb7576003546001600160a01b03168152602090f35b600435906001600160a01b038216820361150057565b608435906001600160a01b038216820361150057565b9181601f84011215611500578235916001600160401b038311611500576020838186019501011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501946060850201011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501948460051b01011161150057565b606081019081106001600160401b038211176108fa57604052565b6001600160401b0381116108fa57604052565b60c081019081106001600160401b038211176108fa57604052565b608081019081106001600160401b038211176108fa57604052565b604081019081106001600160401b038211176108fa57604052565b61080081019081106001600160401b038211176108fa57604052565b90601f801991011681019081106001600160401b038211176108fa57604052565b6000805160206138b7833981519152546001600160a01b031633036129f357565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612a66576000805160206138b783398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b0381116108fa57601f01601f191660200190565b60405190612aa78261297a565b60068252650526f6c6c75760d41b6020830152565b60405190612ac98261297a565b60018252603160f81b6020830152565b60ff6000805160206138f78339815191525460401c1615612af657565b604051631afcd79f60e31b8152600490fd5b6048546040811015612b3057600801556048546001810181116112f757600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116112f757565b603f60485480612b6f575b506040811015612b30576008015490565b6000198101915081116112f75738612b5e565b6001600160401b0381116108fa5760051b60200190565b60001981146112f75760010190565b8051821015612b305760209160051b010190565b818110612bc7575050565b60008155600101612bbc565b356001600160a01b03811681036115005790565b9190811015612b305760051b0190565b906006811015612b305760051b0190565b604090815191612c1783612944565b60009182845282602085015282828501528260608501528260808501528260a0850152825b60068110612c7d57505050805b60068110612c5957505050600190565b612c638184612bf7565b5115612c7757612c7290612b99565b612c49565b50905090565b835b838110612c96575b50612c9190612b99565b612c3c565b612ca08284612bf7565b518160080154148015612cd8575b612cc057612cbb90612b99565b612c7f565b50806001612cd1612c919388612bf7565b5290612c87565b50612ce38284612bf7565b5115612cae565b612cf2612a9a565b6020815191012061115c612d07611106612abc565b51902090565b600052604f60205260406000205415600014612d3657604b602052600160406000200154151590565b600190565b908060209392818452848401376000828201840152601f01601f1916010190565b93929190612d7291608086526080860191612d3b565b9260208091016000905b60038210612d8a5750505050565b82806001928651815201940191019092612d7c565b90816020910312611500575180151581036115005790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612e3b57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612e2f5780516001600160a01b03811615612e2657918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612eb65780612e59575050565b60018103612e735760405163f645eedf60e01b8152600490fd5b60028103612e945760405163fce698f760e01b815260048101839052602490fd5b600314612e9e5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b612ed590612f20565b612edb57565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa908115612f7b57600091612f60575090565b612f78915060203d81116127cb576127bd81836129b1565b90565b6040513d6000823e3d90fd5b15612f8e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b93929190612fd89160e0865260e0860191612d3b565b9260208091016000905b60068210612ff05750505050565b82806001928651815201940191019092612fe2565b90600182811c92168015613035575b602083101461301f57565b634e487b7160e01b600052602260045260246000fd5b91607f1691613014565b1561304657565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612b305760051b6101e40190565b1561309c57565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b9080156135c657600091808352602090604a825260409283852054806135495750604f835283852054806132715750818552604b8352838520600101548015613234576131249114613095565b808452604b8252828420546001600160a01b039081168061318e575b50918160019493604b9387528383527fd4c4548158257b028886d6db0faf9617bed9f9ec7f968df34f862c4c3a282f898387878a20938454169301548751908152a285525282208281550155565b61319790612f20565b156131a3575b38613140565b600554828652604b84528486208054600190910154865163a9059cbb60e01b81529184166001600160a01b031660048301526024820152908490829084168189816044810103925af1801561322a5791604b9391600196959361320d575b5091939450915061319d565b61322390843d86116127cb576127bd81836129b1565b5038613201565b85513d88823e3d90fd5b5050509150606492505b519062461bcd60e51b82526004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152fd5b9592949190600180971461328c57505050506064925061323e565b6050869395949652838520908451906132a48261295f565b60018060a01b0398898454168352808401875180928a908354936132c785613005565b948585528b83821691826000146135275750506001146134eb575b50506132f0925003826129b1565b85830190815261331a6002850154928b60038a870197868952015416936060860194855214613095565b60055483518551895163095ea7b360e01b808252928e166001600160a01b031660048201526024810191909152909291889082908e16818d816044810103925af180156134e1579061337992916134c4575b508b855116905190613802565b156133bc575b505083604f959697987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d92511692518751908152a2845252812055565b858a600554169160448c865116918b8b519586948593845260048401528160248401525af180156134ba579186916134309361349d575b5060055490518551895163a9059cbb60e01b8152918d166001600160a01b0316600483015260248201529283918c169082908b9082906044820190565b03925af1801561349357987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d928692604f98999a9b613476575b5092509897969561337f565b61348c90843d86116127cb576127bd81836129b1565b503861346a565b86513d89823e3d90fd5b6134b390833d85116127cb576127bd81836129b1565b50386133f3565b87513d8a823e3d90fd5b6134da90893d8b116127cb576127bd81836129b1565b503861336c565b89513d8c823e3d90fd5b8a92508c52818c20908c915b85831061350f5750506132f0935082010138806132e2565b80548388018501528694508b939092019181016134f7565b92509350506132f094915060ff191682840152151560051b82010138806132e2565b0361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b50606491519062461bcd60e51b825260048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152fd5b5050565b919080156137fd57600092808452602091604a835260409384862054806137b75750604f84528486205480613619575050818552604b8352838520600101548015613234576131249114613095565b6001979496939291978091146136375750505050506064925061323e565b60508794969597528486209185519161364f8361295f565b60018060a01b03998a91828654168552808601908951918b9181549161367483613005565b92838652858d848316928360001461379457505050600114613751575b505050816136a09103826129b1565b8785019081526136ca6002870154948460038c890199888b52015416956060880196875214613095565b600554855187518b5163095ea7b360e01b8082529287166001600160a01b031660048201526024810191909152909490918a91839116818e816044810103925af18015613747579061337993929161372a575b508c86511690519061386c565b613740908a3d8c116127cb576127bd81836129b1565b503861371d565b8a513d8d823e3d90fd5b8d528a8d208b93508d9291905b82841061377557505050820101816136a038613691565b81949295969750805483858901015201910190928a928f96959461375e565b925093509391506136a0945060ff191682840152151560051b8201019138613691565b90500361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b505050565b6001600160a01b038116600090815260516020526040812054909283929160ff161561386657829182602083519301916207a120f1903d15613862573d9061384982612a7f565b9161385760405193846129b1565b825260203d92013e90565b5090565b50505090565b6001600160a01b038116600090815260516020526040812054909384939160ff16156138af5783809360208451940192f1903d15613862573d9061384982612a7f565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220f4bb08c972b912d5922423b946a85ed2172262c9e905b1535998153c03460be464736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} - -declare module "@nomicfoundation/hardhat-viem/types" { - export function deployContract( - contractName: "RollupV5", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - export function deployContract( - contractName: "contracts/rollup/RollupV5.sol:RollupV5", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - - export function sendDeploymentTransaction( - contractName: "RollupV5", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - export function sendDeploymentTransaction( - contractName: "contracts/rollup/RollupV5.sol:RollupV5", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - - export function getContractAt( - contractName: "RollupV5", - address: Address, - config?: GetContractAtConfig - ): Promise>; - export function getContractAt( - contractName: "contracts/rollup/RollupV5.sol:RollupV5", - address: Address, - config?: GetContractAtConfig - ): Promise>; -} diff --git a/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.dbg.json b/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.dbg.json deleted file mode 100644 index b7a6a76..0000000 --- a/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/22152f3e0e0b93ca501b6ace01f305e7.json" -} diff --git a/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.json b/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.json deleted file mode 100644 index eb4684b..0000000 --- a/eth/artifacts/contracts/rollup/RollupV5.sol/RollupV5.json +++ /dev/null @@ -1,1094 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "RollupV5", - "sourceName": "contracts/rollup/RollupV5.sol", - "abi": [ - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - } - ], - "name": "BlockVerified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToAddress", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToRouter", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Minted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "name": "ValidatorSetAdded", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "prover", - "type": "address" - } - ], - "name": "addProver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "addRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "aggregateVerifier", - "outputs": [ - { - "internalType": "contract AggregateVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "to", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burnToAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "internalType": "bytes", - "name": "routerCalldata", - "type": "bytes" - }, - { - "internalType": "address", - "name": "returnAddress", - "type": "address" - } - ], - "name": "burnToRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifier", - "outputs": [ - { - "internalType": "contract BurnVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifierV2", - "outputs": [ - { - "internalType": "contract BurnVerifierV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_bytes32", - "type": "bytes32" - } - ], - "name": "bytes32ToAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[6]", - "name": "hashes", - "type": "bytes32[6]" - } - ], - "name": "containsRootHashes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentRootHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getBurn", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Burn", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRootHashes", - "outputs": [ - { - "internalType": "bytes32[64]", - "name": "", - "type": "bytes32[64]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "from", - "type": "uint256" - } - ], - "name": "getValidatorSets", - "outputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "internalType": "struct PublicValidatorSet[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - } - ], - "name": "hasBurn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_usdcAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_aggregateVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_mintVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_burnVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "prover", - "type": "address" - }, - { - "internalType": "address[]", - "name": "initialValidators", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "emptyMerkleTreeRootHash", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV4", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_burnVerifierV2", - "type": "address" - } - ], - "name": "initializeV5", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "isRouterWhitelisted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintVerifier", - "outputs": [ - { - "internalType": "contract MintVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "validAfter", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "validBefore", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v2", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s2", - "type": "bytes32" - } - ], - "name": "mintWithAuthorization", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "nextRootHashIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "removeRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "rootHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - } - ], - "name": "setRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "setValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usdc", - "outputs": [ - { - "internalType": "contract IUSDC", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - } - ], - "name": "verifyBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "gasPerBurnCall", - "type": "uint256" - } - ], - "name": "verifyBlock2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60808060405234620000bd577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c16620000ae57506001600160401b036002600160401b03198282160162000068575b60405161394c9081620000c38239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a138808062000058565b63f92ee8a960e01b8152600490fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612838575080630aef023f146127f95780631000b7291461266d5780631d49e4571461263057806324ca984e146125ab5780633644e5151461259057806338e454b1146125105780633e413bee146124e757806345873f3f1461219b578063485ee1e41461217c5780634fb4eee314611b6057806353b9355714611b3357806354a0860614611ab357806354ace9331461167257806354fd4d50146116525780635a023693146115ad5780635cd8a76b1461152d5780635ced058e146115055780635eeba6dd14610fc75780636779b7c214610fa95780636ae0b15414610f68578063715018a614610efd57806382f15a3b14610dcb5780638da5cb5b14610d95578063a2ce9c1f14610d6b578063a65ddebd14610d42578063a91eebf514610d1f578063afbd8c3914610cbb578063b5061658146109eb578063c072bd88146109c2578063c3a716eb14610999578063c832fe5f14610914578063cb3258331461078c578063dab5f34014610767578063e4408e4614610700578063e795594d14610434578063ef0feff914610243578063f22a195e14610225578063f2fde38b146101f85763f44ff712146101d857600080fd5b346101f557806003193601126101f5576020600754604051908152f35b80fd5b50346101f55760203660031901126101f55761022261021561285d565b61021d6129d2565b612a0b565b80f35b50346101f557806003193601126101f5576020600654604051908152f35b50346101f557602090816003193601126101f55790600435604d546102688282612b46565b9161027283612b82565b9261028060405194856129b1565b80845261028f601f1991612b82565b01855b818110610407575050805b8281106103585750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102da5787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061033557505050906001938380809401519101529801930193019092879695939492946102cd565b82516001600160a01b031685528a9594850194909201916001919091019061030a565b808694959652604c86526040842060016002818301920154906040519261037e8461297a565b60405191828b83549182815201928a528b8a20918a915b8d8184106103e957505050505091816103b86103e09695936103da9503826129b1565b8252898201526103c88584612b46565b906103d3828a612ba8565b5287612ba8565b50612b99565b9493929461029d565b84546001600160a01b03168652909401939281019291810191610395565b9480809795966040516104198161297a565b60608152878382015282828a01015201905095949395610292565b50346101f55760403660031901126101f5576004356001600160401b03602480358281116106fc5761046a9036906004016128e6565b92906104746129d2565b604d938454801580156106c2575b1561064e57600052604c916020928084528760026040600020015586546000526001948560406000200190841161063957600160401b841161063957805484825580851061061c575b50829060005284600020908660005b868110610603575050505060005b838110610546575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161053257505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b0391908261057261056d868a8a612be7565b612bd3565b16600052875260ff604060002054166105c457906105bf92916000528387526040600020906105a561056d848989612be7565b16600052865260406000208760ff19825416179055612b99565b6104e8565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761060d84612bd3565b930192818501550187906104da565b610633908260005285876000209182019101612bbc565b386104cb565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116106e757600052604c6020528660026040600020015410610482565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346101f55760203660031901126101f5576040818192602083516107248161297a565b82815201526004358152604b60205220815161073f8161297a565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b50346101f55760203660031901126101f5576107816129d2565b610222600435612b08565b50346101f55760c03660031901126101f5576107a661285d565b6001600160401b03602435818111610910576107c6903690600401612889565b9091604435606435926107d886612ecc565b600454604051966001600160a01b03949185169160a0890191908211898310176108fa57859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b156108f657604051625a2d8360e11b815260c060048201528a94909392916108529160c4860191612d3b565b908489602486015b600583106108dc575050505083918380809303915afa80156108d1576108b9575b5050600193604b91604051966108908861297a565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6108c290612931565b6108cd57853861087b565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b910161085a565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b50346101f557806003193601126101f5576040519061093282612995565b610800809236903760405190600881835b60408210610983575050509061095881612995565b6040519190825b6040831061096c57505050f35b60019082518152602080910192019201919061095f565b6001602081928554815201930191019091610943565b50346101f557806003193601126101f5576004546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576002546040516001600160a01b039091168152602090f35b50346101f5576101c03660031901126101f5576001600160401b0390600435828111610cb757610a1f903690600401612889565b90602435906044359260643595610a34612873565b9060a4359260c4359260e43591878a52602096604a885260408b2054610c7c57604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528a60408801528b60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e082015261010087818301528152610120810192818410908411176108fa57610b238692610b2c928a956040525190208c610ae2612cea565b916040519182019261190160f01b84526022830152604282015260428152610b098161295f565b5190206101a43590610184359060ff610164351690612db7565b90929192612e47565b1603610c46578a9b8360039c999a9b9c541660405191610b4b83612916565b8c83528d8c8401526040830152803b156108f657610b82938a9360405195869485938493635e65f68960e11b855260048501612d5c565b03915afa908115610c3b578791610c27575b50506005541690813b156108cd5785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af180156108d157610c13575b5091604a925252604082205580f35b610c1c90612931565b610910578338610c04565b610c3090612931565b6108cd578538610b94565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346101f55760c03660031901126101f55736602312156101f557604051610ce281612944565b8060c49136831161091057602093506004905b838210610d105784610d0684612c08565b6040519015158152f35b81358152908401908401610cf5565b50346101f557806003193601126101f5576020610d3a612b53565b604051908152f35b50346101f557806003193601126101f5576052546040516001600160a01b039091168152602090f35b50346101f55760203660031901126101f55760406020916004358152604a83522054604051908152f35b50346101f557806003193601126101f5576000805160206138b7833981519152546040516001600160a01b039091168152602090f35b50346101f55760e03660031901126101f5576024356004356044356001600160401b03811161091057610e02903690600401612889565b906064358560843593610e158615612f87565b6001600160a01b0387811697909490610e2d89612ecc565b856052541660405191610e3f83612944565b898352602083015285604083015287606083015260a435608083015260c43560a0830152803b156106fc57610e8d9385936040519586948593849363e261a9cb60e01b855260048501612fc2565b03915afa80156108d157610ee9575b50938160019552604f602052604087205560405194610eba8661297a565b8552602085019283528552604b602052604085209351166001600160601b0360a01b8454161783555191015580f35b610ef290612931565b6108cd578538610e9c565b50346101f557806003193601126101f557610f166129d2565b6000805160206138b783398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101f55760203660031901126101f557610f8261285d565b610f8a6129d2565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346101f557806003193601126101f5576020604854604051908152f35b50346101f5576101003660031901126101f557610fe261285d565b6024356001600160a01b038116810361150057604435906001600160a01b038216820361150057606435906001600160a01b038216820361150057611025612873565b60a43591906001600160a01b03831683036115005760c4356001600160401b0381116114fc576110599036906004016128e6565b9490956000805160206138f783398151915254976001600160401b03891615806114ee575b60016001600160401b038b161490816114e4575b1590816114db575b506114c9576110e99060016001600160401b03198b16176000805160206138f78339815191525560ff8a60401c161561149c575b8a5460ff19166001178b556110e1612ad9565b61021d612ad9565b6110f1612a9a565b6020815191012061115c61116a611106612abc565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f1981018352826129b1565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611480575b1561140b57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b0382116108fa57600160401b82116108fa5780548282558083106113ed575b50829060005260206000209060005b8381106113d25750505060005b81811061130d57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116112f75760ff91604d556112a360e435612b08565b60401c16156112af5780f35b68ff0000000000000000196000805160206138f783398151915254166000805160206138f7833981519152556000805160206138d7833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361133761056d848789612be7565b1660005260205260ff604060002054166113925761138d91600052604c602052604060002060018060a01b0361137161056d848789612be7565b166000526020526040600020600160ff19825416179055612b99565b611249565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b60019060206113e084612bd3565b930192818501550161123c565b61140590826000528360206000209182019101612bbc565b3861122d565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116112f757600052604c60205260006111e2565b68ffffffffffffffffff198a1668010000000000000001176000805160206138f7833981519152556110ce565b60405163f92ee8a960e01b8152600490fd5b9050153861109a565b303b159150611092565b5060ff8960401c161561107e565b8780fd5b600080fd5b50346101f55760203660031901126101f5576040516004356001600160a01b03168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611599575b6114c9576002908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160028152a180f35b5060026001600160401b038216101561155d565b50346101f55760203660031901126101f5576115c761285d565b6000805160206138f783398151915290815460ff8160401c16801561163e575b6114c9576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160058152a180f35b5060056001600160401b03821610156115e7565b50346101f557806003193601126101f55760ff6020915416604051908152f35b50346101f5576101403660031901126101f5576001600160401b0390602435604435838111611aaf576116a9903690600401612889565b93909160e435906001600160a01b038216820361150057610104358381116108cd576116d9903690600401612889565b6101243595919290916001600160a01b038716870361150057611700600160043514612f87565b6001600160a01b03871615611a71576001600160a01b03851688526051602052604088205460ff1615611a3357604051988260208b019a60018060a01b0388168c52606060408201528061175860808201888a612d3b565b6001600160a01b038c16606083015203601f1981810183529c9061177c90836129b1565b905190206001600160fd1b031603611a005760018060a01b036052541691604051936117a785612944565b600435855260208501526064356040850152608435606085015260a435608085015260c43560a0850152823b156108f65760405163e261a9cb60e01b8152938a9385939092849283926117fd9260048501612fc2565b03915afa8015610c3b579087916119ec575b50506064358652604f6020526004356040872055604051926118308461295f565b6001600160a01b0316835261184481612a7f565b9161185260405193846129b1565b81835236828201116119e8578187926020928386013783010152602082810191825260843560408085019182526001600160a01b03968716606086019081526064358952605090935287209351845496166001600160a01b031996871617845591518051909791959460018501929082116119d4576118d18354613005565b601f8111611999575b50602090601f8311600114611934575081908899600397989992611929575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b039051169082541617905580f35b0151905038806118f9565b8216988389526020892099895b81811061198157509160039798999a91846001959410611969575b505050811b01905561190d565b015160001983891b60f8161c1916905538808061195c565b838301518c556001909b019a60209384019301611941565b6119c490848a5260208a20601f850160051c810191602086106119ca575b601f0160051c0190612bbc565b386118da565b90915081906119b7565b634e487b7160e01b88526041600452602488fd5b8680fd5b6119f590612931565b6108cd57853861180f565b60405162461bcd60e51b815260206004820152600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b8280fd5b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611b1f575b6114c9576004908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160048152a180f35b5060046001600160401b0382161015611ae3565b50346101f55760203660031901126101f5576004356040811015610cb75760209060080154604051908152f35b50346101f5576104803660031901126101f5576001600160401b0390600435828111610cb757611b94903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf57611bc19036906004016128b6565b9290913382526049602052611bdc600160408420541461303f565b3382526049602052611bf4600160408420541461303f565b604e93845460018101809111612168575b604d5481101561215c57808452604c60205261044435600260408620015411611c395780611c34918755612b99565b611c05565b509193949092945b548452604c6020526040842092611c56612b53565b926101a43593840361210657855b6012811061208a5750611cb4604051611c7c81612944565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612c08565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c435602082015261044435604082015261042435606082015260608152611d118161295f565b6020815191012094600161044435016104443511611fd757604051602081019060016104443501825287604082015260408152611d4d81612916565b51902060405190611d5d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b828110611fbf57505090611dad9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b848210611e9d578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156108d157611e89575b5050611e4a6101c435612b08565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b611e9290612931565b610cb7578183611e3c565b611ecc90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b90949194612e47565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f0757611f019091612b99565b90611dbd565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b60208282018101516028888401015286945001611d86565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116120f25761209e90613082565b35600282018083116120de57906120b76120be92613082565b35906130d7565b6003810180911115611c6457634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294611c41565b634e487b7160e01b84526011600452602484fd5b50346101f55760203660031901126101f5576020610d06600435612d0d565b50346101f5576104a03660031901126101f5576001600160401b0390600435828111610cb7576121cf903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf576121fc9036906004016128b6565b9290913382526049602052612217600160408420541461303f565b604e93845460018101809111612168575b604d548110156124db57808452604c6020526104443560026040862001541161225c5780612257918755612b99565b612228565b509193949092945b548452604c6020526040842092612279612b53565b926101a4359384036121065761048435865b601281106124725750506122a4604051611c7c81612944565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c4356020820152610444356040820152610424356060820152606081526123018161295f565b6020815191012094600161044435016104443511611fd75760405160208101906001610444350182528760408201526040815261233d81612916565b5190206040519061234d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061245a5750509061239d9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b8482106123f9578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b61241f90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f07576124549091612b99565b906123ad565b60208282018101516028888401015286945001612376565b600181018082116120de5761248690613082565b35600282018083116124c7576124a7916124a08592613082565b35906135ca565b600381018091111561228b57634e487b7160e01b88526011600452602488fd5b634e487b7160e01b8a52601160045260248afd5b50919394909294612264565b50346101f557806003193601126101f5576005546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c16801561257c575b6114c9576003908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160038152a180f35b5060036001600160401b0382161015612540565b50346101f557806003193601126101f5576020610d3a612cea565b50346101f55760203660031901126101f5576125c561285d565b6125cd6129d2565b803b156125f6576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b50346101f55760203660031901126101f55761264a61285d565b6126526129d2565b6001600160a01b031681526049602052604081206001905580f35b50346101f55760803660031901126101f5576004356001600160401b038111610cb75761269e903690600401612889565b9060243560443592818552602092604a84526040862054610c7c576003546040516001600160a01b039388928516906126d683612916565b86835288888401526064356040840152813b156109105761270e9460405195869485938493635e65f68960e11b855260048501612d5c565b03915afa80156127ee576127dd575b50828591600554166064604051809481936323b872dd60e01b83523360048401523060248401528960448401525af19081156127d25785916127a5575b501561276e578352604a9052604082205580f35b60405162461bcd60e51b815260048101839052600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b6127c59150833d85116127cb575b6127bd81836129b1565b810190612d9f565b3861275a565b503d6127b3565b6040513d87823e3d90fd5b946127e88496612931565b9461271d565b6040513d88823e3d90fd5b50346101f55760203660031901126101f55760209060ff906040906001600160a01b0361282461285d565b168152605184522054166040519015158152f35b905034610cb75781600319360112610cb7576003546001600160a01b03168152602090f35b600435906001600160a01b038216820361150057565b608435906001600160a01b038216820361150057565b9181601f84011215611500578235916001600160401b038311611500576020838186019501011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501946060850201011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501948460051b01011161150057565b606081019081106001600160401b038211176108fa57604052565b6001600160401b0381116108fa57604052565b60c081019081106001600160401b038211176108fa57604052565b608081019081106001600160401b038211176108fa57604052565b604081019081106001600160401b038211176108fa57604052565b61080081019081106001600160401b038211176108fa57604052565b90601f801991011681019081106001600160401b038211176108fa57604052565b6000805160206138b7833981519152546001600160a01b031633036129f357565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612a66576000805160206138b783398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b0381116108fa57601f01601f191660200190565b60405190612aa78261297a565b60068252650526f6c6c75760d41b6020830152565b60405190612ac98261297a565b60018252603160f81b6020830152565b60ff6000805160206138f78339815191525460401c1615612af657565b604051631afcd79f60e31b8152600490fd5b6048546040811015612b3057600801556048546001810181116112f757600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116112f757565b603f60485480612b6f575b506040811015612b30576008015490565b6000198101915081116112f75738612b5e565b6001600160401b0381116108fa5760051b60200190565b60001981146112f75760010190565b8051821015612b305760209160051b010190565b818110612bc7575050565b60008155600101612bbc565b356001600160a01b03811681036115005790565b9190811015612b305760051b0190565b906006811015612b305760051b0190565b604090815191612c1783612944565b60009182845282602085015282828501528260608501528260808501528260a0850152825b60068110612c7d57505050805b60068110612c5957505050600190565b612c638184612bf7565b5115612c7757612c7290612b99565b612c49565b50905090565b835b838110612c96575b50612c9190612b99565b612c3c565b612ca08284612bf7565b518160080154148015612cd8575b612cc057612cbb90612b99565b612c7f565b50806001612cd1612c919388612bf7565b5290612c87565b50612ce38284612bf7565b5115612cae565b612cf2612a9a565b6020815191012061115c612d07611106612abc565b51902090565b600052604f60205260406000205415600014612d3657604b602052600160406000200154151590565b600190565b908060209392818452848401376000828201840152601f01601f1916010190565b93929190612d7291608086526080860191612d3b565b9260208091016000905b60038210612d8a5750505050565b82806001928651815201940191019092612d7c565b90816020910312611500575180151581036115005790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612e3b57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612e2f5780516001600160a01b03811615612e2657918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612eb65780612e59575050565b60018103612e735760405163f645eedf60e01b8152600490fd5b60028103612e945760405163fce698f760e01b815260048101839052602490fd5b600314612e9e5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b612ed590612f20565b612edb57565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa908115612f7b57600091612f60575090565b612f78915060203d81116127cb576127bd81836129b1565b90565b6040513d6000823e3d90fd5b15612f8e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b93929190612fd89160e0865260e0860191612d3b565b9260208091016000905b60068210612ff05750505050565b82806001928651815201940191019092612fe2565b90600182811c92168015613035575b602083101461301f57565b634e487b7160e01b600052602260045260246000fd5b91607f1691613014565b1561304657565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612b305760051b6101e40190565b1561309c57565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b9080156135c657600091808352602090604a825260409283852054806135495750604f835283852054806132715750818552604b8352838520600101548015613234576131249114613095565b808452604b8252828420546001600160a01b039081168061318e575b50918160019493604b9387528383527fd4c4548158257b028886d6db0faf9617bed9f9ec7f968df34f862c4c3a282f898387878a20938454169301548751908152a285525282208281550155565b61319790612f20565b156131a3575b38613140565b600554828652604b84528486208054600190910154865163a9059cbb60e01b81529184166001600160a01b031660048301526024820152908490829084168189816044810103925af1801561322a5791604b9391600196959361320d575b5091939450915061319d565b61322390843d86116127cb576127bd81836129b1565b5038613201565b85513d88823e3d90fd5b5050509150606492505b519062461bcd60e51b82526004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152fd5b9592949190600180971461328c57505050506064925061323e565b6050869395949652838520908451906132a48261295f565b60018060a01b0398898454168352808401875180928a908354936132c785613005565b948585528b83821691826000146135275750506001146134eb575b50506132f0925003826129b1565b85830190815261331a6002850154928b60038a870197868952015416936060860194855214613095565b60055483518551895163095ea7b360e01b808252928e166001600160a01b031660048201526024810191909152909291889082908e16818d816044810103925af180156134e1579061337992916134c4575b508b855116905190613802565b156133bc575b505083604f959697987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d92511692518751908152a2845252812055565b858a600554169160448c865116918b8b519586948593845260048401528160248401525af180156134ba579186916134309361349d575b5060055490518551895163a9059cbb60e01b8152918d166001600160a01b0316600483015260248201529283918c169082908b9082906044820190565b03925af1801561349357987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d928692604f98999a9b613476575b5092509897969561337f565b61348c90843d86116127cb576127bd81836129b1565b503861346a565b86513d89823e3d90fd5b6134b390833d85116127cb576127bd81836129b1565b50386133f3565b87513d8a823e3d90fd5b6134da90893d8b116127cb576127bd81836129b1565b503861336c565b89513d8c823e3d90fd5b8a92508c52818c20908c915b85831061350f5750506132f0935082010138806132e2565b80548388018501528694508b939092019181016134f7565b92509350506132f094915060ff191682840152151560051b82010138806132e2565b0361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b50606491519062461bcd60e51b825260048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152fd5b5050565b919080156137fd57600092808452602091604a835260409384862054806137b75750604f84528486205480613619575050818552604b8352838520600101548015613234576131249114613095565b6001979496939291978091146136375750505050506064925061323e565b60508794969597528486209185519161364f8361295f565b60018060a01b03998a91828654168552808601908951918b9181549161367483613005565b92838652858d848316928360001461379457505050600114613751575b505050816136a09103826129b1565b8785019081526136ca6002870154948460038c890199888b52015416956060880196875214613095565b600554855187518b5163095ea7b360e01b8082529287166001600160a01b031660048201526024810191909152909490918a91839116818e816044810103925af18015613747579061337993929161372a575b508c86511690519061386c565b613740908a3d8c116127cb576127bd81836129b1565b503861371d565b8a513d8d823e3d90fd5b8d528a8d208b93508d9291905b82841061377557505050820101816136a038613691565b81949295969750805483858901015201910190928a928f96959461375e565b925093509391506136a0945060ff191682840152151560051b8201019138613691565b90500361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b505050565b6001600160a01b038116600090815260516020526040812054909283929160ff161561386657829182602083519301916207a120f1903d15613862573d9061384982612a7f565b9161385760405193846129b1565b825260203d92013e90565b5090565b50505090565b6001600160a01b038116600090815260516020526040812054909384939160ff16156138af5783809360208451940192f1903d15613862573d9061384982612a7f565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220f4bb08c972b912d5922423b946a85ed2172262c9e905b1535998153c03460be464736f6c63430008140033", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612838575080630aef023f146127f95780631000b7291461266d5780631d49e4571461263057806324ca984e146125ab5780633644e5151461259057806338e454b1146125105780633e413bee146124e757806345873f3f1461219b578063485ee1e41461217c5780634fb4eee314611b6057806353b9355714611b3357806354a0860614611ab357806354ace9331461167257806354fd4d50146116525780635a023693146115ad5780635cd8a76b1461152d5780635ced058e146115055780635eeba6dd14610fc75780636779b7c214610fa95780636ae0b15414610f68578063715018a614610efd57806382f15a3b14610dcb5780638da5cb5b14610d95578063a2ce9c1f14610d6b578063a65ddebd14610d42578063a91eebf514610d1f578063afbd8c3914610cbb578063b5061658146109eb578063c072bd88146109c2578063c3a716eb14610999578063c832fe5f14610914578063cb3258331461078c578063dab5f34014610767578063e4408e4614610700578063e795594d14610434578063ef0feff914610243578063f22a195e14610225578063f2fde38b146101f85763f44ff712146101d857600080fd5b346101f557806003193601126101f5576020600754604051908152f35b80fd5b50346101f55760203660031901126101f55761022261021561285d565b61021d6129d2565b612a0b565b80f35b50346101f557806003193601126101f5576020600654604051908152f35b50346101f557602090816003193601126101f55790600435604d546102688282612b46565b9161027283612b82565b9261028060405194856129b1565b80845261028f601f1991612b82565b01855b818110610407575050805b8281106103585750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106102da5787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b80821061033557505050906001938380809401519101529801930193019092879695939492946102cd565b82516001600160a01b031685528a9594850194909201916001919091019061030a565b808694959652604c86526040842060016002818301920154906040519261037e8461297a565b60405191828b83549182815201928a528b8a20918a915b8d8184106103e957505050505091816103b86103e09695936103da9503826129b1565b8252898201526103c88584612b46565b906103d3828a612ba8565b5287612ba8565b50612b99565b9493929461029d565b84546001600160a01b03168652909401939281019291810191610395565b9480809795966040516104198161297a565b60608152878382015282828a01015201905095949395610292565b50346101f55760403660031901126101f5576004356001600160401b03602480358281116106fc5761046a9036906004016128e6565b92906104746129d2565b604d938454801580156106c2575b1561064e57600052604c916020928084528760026040600020015586546000526001948560406000200190841161063957600160401b841161063957805484825580851061061c575b50829060005284600020908660005b868110610603575050505060005b838110610546575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161053257505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b0391908261057261056d868a8a612be7565b612bd3565b16600052875260ff604060002054166105c457906105bf92916000528387526040600020906105a561056d848989612be7565b16600052865260406000208760ff19825416179055612b99565b6104e8565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761060d84612bd3565b930192818501550187906104da565b610633908260005285876000209182019101612bbc565b386104cb565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116106e757600052604c6020528660026040600020015410610482565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346101f55760203660031901126101f5576040818192602083516107248161297a565b82815201526004358152604b60205220815161073f8161297a565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b50346101f55760203660031901126101f5576107816129d2565b610222600435612b08565b50346101f55760c03660031901126101f5576107a661285d565b6001600160401b03602435818111610910576107c6903690600401612889565b9091604435606435926107d886612ecc565b600454604051966001600160a01b03949185169160a0890191908211898310176108fa57859160405216968781526020968488830152866040830152608435606083015260a4356080830152823b156108f657604051625a2d8360e11b815260c060048201528a94909392916108529160c4860191612d3b565b908489602486015b600583106108dc575050505083918380809303915afa80156108d1576108b9575b5050600193604b91604051966108908861297a565b875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6108c290612931565b6108cd57853861087b565b8580fd5b6040513d84823e3d90fd5b835181528d975092810192600192909201918b910161085a565b8980fd5b634e487b7160e01b600052604160045260246000fd5b8380fd5b50346101f557806003193601126101f5576040519061093282612995565b610800809236903760405190600881835b60408210610983575050509061095881612995565b6040519190825b6040831061096c57505050f35b60019082518152602080910192019201919061095f565b6001602081928554815201930191019091610943565b50346101f557806003193601126101f5576004546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576002546040516001600160a01b039091168152602090f35b50346101f5576101c03660031901126101f5576001600160401b0390600435828111610cb757610a1f903690600401612889565b90602435906044359260643595610a34612873565b9060a4359260c4359260e43591878a52602096604a885260408b2054610c7c57604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528a60408801528b60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e082015261010087818301528152610120810192818410908411176108fa57610b238692610b2c928a956040525190208c610ae2612cea565b916040519182019261190160f01b84526022830152604282015260428152610b098161295f565b5190206101a43590610184359060ff610164351690612db7565b90929192612e47565b1603610c46578a9b8360039c999a9b9c541660405191610b4b83612916565b8c83528d8c8401526040830152803b156108f657610b82938a9360405195869485938493635e65f68960e11b855260048501612d5c565b03915afa908115610c3b578791610c27575b50506005541690813b156108cd5785936040519586946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af180156108d157610c13575b5091604a925252604082205580f35b610c1c90612931565b610910578338610c04565b610c3090612931565b6108cd578538610b94565b6040513d89823e3d90fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346101f55760c03660031901126101f55736602312156101f557604051610ce281612944565b8060c49136831161091057602093506004905b838210610d105784610d0684612c08565b6040519015158152f35b81358152908401908401610cf5565b50346101f557806003193601126101f5576020610d3a612b53565b604051908152f35b50346101f557806003193601126101f5576052546040516001600160a01b039091168152602090f35b50346101f55760203660031901126101f55760406020916004358152604a83522054604051908152f35b50346101f557806003193601126101f5576000805160206138b7833981519152546040516001600160a01b039091168152602090f35b50346101f55760e03660031901126101f5576024356004356044356001600160401b03811161091057610e02903690600401612889565b906064358560843593610e158615612f87565b6001600160a01b0387811697909490610e2d89612ecc565b856052541660405191610e3f83612944565b898352602083015285604083015287606083015260a435608083015260c43560a0830152803b156106fc57610e8d9385936040519586948593849363e261a9cb60e01b855260048501612fc2565b03915afa80156108d157610ee9575b50938160019552604f602052604087205560405194610eba8661297a565b8552602085019283528552604b602052604085209351166001600160601b0360a01b8454161783555191015580f35b610ef290612931565b6108cd578538610e9c565b50346101f557806003193601126101f557610f166129d2565b6000805160206138b783398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101f55760203660031901126101f557610f8261285d565b610f8a6129d2565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346101f557806003193601126101f5576020604854604051908152f35b50346101f5576101003660031901126101f557610fe261285d565b6024356001600160a01b038116810361150057604435906001600160a01b038216820361150057606435906001600160a01b038216820361150057611025612873565b60a43591906001600160a01b03831683036115005760c4356001600160401b0381116114fc576110599036906004016128e6565b9490956000805160206138f783398151915254976001600160401b03891615806114ee575b60016001600160401b038b161490816114e4575b1590816114db575b506114c9576110e99060016001600160401b03198b16176000805160206138f78339815191525560ff8a60401c161561149c575b8a5460ff19166001178b556110e1612ad9565b61021d612ad9565b6110f1612a9a565b6020815191012061115c61116a611106612abc565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f1981018352826129b1565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611480575b1561140b57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b0382116108fa57600160401b82116108fa5780548282558083106113ed575b50829060005260206000209060005b8381106113d25750505060005b81811061130d57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116112f75760ff91604d556112a360e435612b08565b60401c16156112af5780f35b68ff0000000000000000196000805160206138f783398151915254166000805160206138f7833981519152556000805160206138d7833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b0361133761056d848789612be7565b1660005260205260ff604060002054166113925761138d91600052604c602052604060002060018060a01b0361137161056d848789612be7565b166000526020526040600020600160ff19825416179055612b99565b611249565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b60019060206113e084612bd3565b930192818501550161123c565b61140590826000528360206000209182019101612bbc565b3861122d565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116112f757600052604c60205260006111e2565b68ffffffffffffffffff198a1668010000000000000001176000805160206138f7833981519152556110ce565b60405163f92ee8a960e01b8152600490fd5b9050153861109a565b303b159150611092565b5060ff8960401c161561107e565b8780fd5b600080fd5b50346101f55760203660031901126101f5576040516004356001600160a01b03168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611599575b6114c9576002908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160028152a180f35b5060026001600160401b038216101561155d565b50346101f55760203660031901126101f5576115c761285d565b6000805160206138f783398151915290815460ff8160401c16801561163e575b6114c9576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160058152a180f35b5060056001600160401b03821610156115e7565b50346101f557806003193601126101f55760ff6020915416604051908152f35b50346101f5576101403660031901126101f5576001600160401b0390602435604435838111611aaf576116a9903690600401612889565b93909160e435906001600160a01b038216820361150057610104358381116108cd576116d9903690600401612889565b6101243595919290916001600160a01b038716870361150057611700600160043514612f87565b6001600160a01b03871615611a71576001600160a01b03851688526051602052604088205460ff1615611a3357604051988260208b019a60018060a01b0388168c52606060408201528061175860808201888a612d3b565b6001600160a01b038c16606083015203601f1981810183529c9061177c90836129b1565b905190206001600160fd1b031603611a005760018060a01b036052541691604051936117a785612944565b600435855260208501526064356040850152608435606085015260a435608085015260c43560a0850152823b156108f65760405163e261a9cb60e01b8152938a9385939092849283926117fd9260048501612fc2565b03915afa8015610c3b579087916119ec575b50506064358652604f6020526004356040872055604051926118308461295f565b6001600160a01b0316835261184481612a7f565b9161185260405193846129b1565b81835236828201116119e8578187926020928386013783010152602082810191825260843560408085019182526001600160a01b03968716606086019081526064358952605090935287209351845496166001600160a01b031996871617845591518051909791959460018501929082116119d4576118d18354613005565b601f8111611999575b50602090601f8311600114611934575081908899600397989992611929575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b039051169082541617905580f35b0151905038806118f9565b8216988389526020892099895b81811061198157509160039798999a91846001959410611969575b505050811b01905561190d565b015160001983891b60f8161c1916905538808061195c565b838301518c556001909b019a60209384019301611941565b6119c490848a5260208a20601f850160051c810191602086106119ca575b601f0160051c0190612bbc565b386118da565b90915081906119b7565b634e487b7160e01b88526041600452602488fd5b8680fd5b6119f590612931565b6108cd57853861180f565b60405162461bcd60e51b815260206004820152600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b8280fd5b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c168015611b1f575b6114c9576004908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160048152a180f35b5060046001600160401b0382161015611ae3565b50346101f55760203660031901126101f5576004356040811015610cb75760209060080154604051908152f35b50346101f5576104803660031901126101f5576001600160401b0390600435828111610cb757611b94903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf57611bc19036906004016128b6565b9290913382526049602052611bdc600160408420541461303f565b3382526049602052611bf4600160408420541461303f565b604e93845460018101809111612168575b604d5481101561215c57808452604c60205261044435600260408620015411611c395780611c34918755612b99565b611c05565b509193949092945b548452604c6020526040842092611c56612b53565b926101a43593840361210657855b6012811061208a5750611cb4604051611c7c81612944565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a0820152612c08565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c435602082015261044435604082015261042435606082015260608152611d118161295f565b6020815191012094600161044435016104443511611fd757604051602081019060016104443501825287604082015260408152611d4d81612916565b51902060405190611d5d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b828110611fbf57505090611dad9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b848210611e9d578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156108d157611e89575b5050611e4a6101c435612b08565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b611e9290612931565b610cb7578183611e3c565b611ecc90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b90949194612e47565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f0757611f019091612b99565b90611dbd565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b60208282018101516028888401015286945001611d86565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116120f25761209e90613082565b35600282018083116120de57906120b76120be92613082565b35906130d7565b6003810180911115611c6457634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294611c41565b634e487b7160e01b84526011600452602484fd5b50346101f55760203660031901126101f5576020610d06600435612d0d565b50346101f5576104a03660031901126101f5576001600160401b0390600435828111610cb7576121cf903690600401612889565b9092366101a411611aaf573661042411611aaf5761046435908111611aaf576121fc9036906004016128b6565b9290913382526049602052612217600160408420541461303f565b604e93845460018101809111612168575b604d548110156124db57808452604c6020526104443560026040862001541161225c5780612257918755612b99565b612228565b509193949092945b548452604c6020526040842092612279612b53565b926101a4359384036121065761048435865b601281106124725750506122a4604051611c7c81612944565b1561204e5760018501548060011b9080820460021490151715611fd7576003900460018101809111611fd7578110611feb576040516101c4356020820152610444356040820152610424356060820152606081526123018161295f565b6020815191012094600161044435016104443511611fd75760405160208101906001610444350182528760408201526040815261233d81612916565b5190206040519061234d8261297a565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061245a5750509061239d9260489282019060288201520360288101845201826129b1565b602081519101208215611f8a5787805b8482106123f9578989818a8a8a60018060a01b0360025416803b156106fc578492611e099260405195869485938493633b07787160e21b85526104206004860152610424850191612d3b565b61241f90606083028c0190611ec360ff9260208101359084604082359201351688612db7565b60018060a01b0390600182851693846000528860205260406000205416151503611f4557161015611f07576124549091612b99565b906123ad565b60208282018101516028888401015286945001612376565b600181018082116120de5761248690613082565b35600282018083116124c7576124a7916124a08592613082565b35906135ca565b600381018091111561228b57634e487b7160e01b88526011600452602488fd5b634e487b7160e01b8a52601160045260248afd5b50919394909294612264565b50346101f557806003193601126101f5576005546040516001600160a01b039091168152602090f35b50346101f557806003193601126101f5576000805160206138f7833981519152805460ff8160401c16801561257c575b6114c9576003908160ff1985541617845568ffffffffffffffffff19161790556000805160206138d7833981519152602060405160038152a180f35b5060036001600160401b0382161015612540565b50346101f557806003193601126101f5576020610d3a612cea565b50346101f55760203660031901126101f5576125c561285d565b6125cd6129d2565b803b156125f6576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b50346101f55760203660031901126101f55761264a61285d565b6126526129d2565b6001600160a01b031681526049602052604081206001905580f35b50346101f55760803660031901126101f5576004356001600160401b038111610cb75761269e903690600401612889565b9060243560443592818552602092604a84526040862054610c7c576003546040516001600160a01b039388928516906126d683612916565b86835288888401526064356040840152813b156109105761270e9460405195869485938493635e65f68960e11b855260048501612d5c565b03915afa80156127ee576127dd575b50828591600554166064604051809481936323b872dd60e01b83523360048401523060248401528960448401525af19081156127d25785916127a5575b501561276e578352604a9052604082205580f35b60405162461bcd60e51b815260048101839052600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b6127c59150833d85116127cb575b6127bd81836129b1565b810190612d9f565b3861275a565b503d6127b3565b6040513d87823e3d90fd5b946127e88496612931565b9461271d565b6040513d88823e3d90fd5b50346101f55760203660031901126101f55760209060ff906040906001600160a01b0361282461285d565b168152605184522054166040519015158152f35b905034610cb75781600319360112610cb7576003546001600160a01b03168152602090f35b600435906001600160a01b038216820361150057565b608435906001600160a01b038216820361150057565b9181601f84011215611500578235916001600160401b038311611500576020838186019501011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501946060850201011161150057565b9181601f84011215611500578235916001600160401b038311611500576020808501948460051b01011161150057565b606081019081106001600160401b038211176108fa57604052565b6001600160401b0381116108fa57604052565b60c081019081106001600160401b038211176108fa57604052565b608081019081106001600160401b038211176108fa57604052565b604081019081106001600160401b038211176108fa57604052565b61080081019081106001600160401b038211176108fa57604052565b90601f801991011681019081106001600160401b038211176108fa57604052565b6000805160206138b7833981519152546001600160a01b031633036129f357565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612a66576000805160206138b783398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b0381116108fa57601f01601f191660200190565b60405190612aa78261297a565b60068252650526f6c6c75760d41b6020830152565b60405190612ac98261297a565b60018252603160f81b6020830152565b60ff6000805160206138f78339815191525460401c1615612af657565b604051631afcd79f60e31b8152600490fd5b6048546040811015612b3057600801556048546001810181116112f757600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116112f757565b603f60485480612b6f575b506040811015612b30576008015490565b6000198101915081116112f75738612b5e565b6001600160401b0381116108fa5760051b60200190565b60001981146112f75760010190565b8051821015612b305760209160051b010190565b818110612bc7575050565b60008155600101612bbc565b356001600160a01b03811681036115005790565b9190811015612b305760051b0190565b906006811015612b305760051b0190565b604090815191612c1783612944565b60009182845282602085015282828501528260608501528260808501528260a0850152825b60068110612c7d57505050805b60068110612c5957505050600190565b612c638184612bf7565b5115612c7757612c7290612b99565b612c49565b50905090565b835b838110612c96575b50612c9190612b99565b612c3c565b612ca08284612bf7565b518160080154148015612cd8575b612cc057612cbb90612b99565b612c7f565b50806001612cd1612c919388612bf7565b5290612c87565b50612ce38284612bf7565b5115612cae565b612cf2612a9a565b6020815191012061115c612d07611106612abc565b51902090565b600052604f60205260406000205415600014612d3657604b602052600160406000200154151590565b600190565b908060209392818452848401376000828201840152601f01601f1916010190565b93929190612d7291608086526080860191612d3b565b9260208091016000905b60038210612d8a5750505050565b82806001928651815201940191019092612d7c565b90816020910312611500575180151581036115005790565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612e3b57926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612e2f5780516001600160a01b03811615612e2657918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612eb65780612e59575050565b60018103612e735760405163f645eedf60e01b8152600490fd5b60028103612e945760405163fce698f760e01b815260048101839052602490fd5b600314612e9e5750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b612ed590612f20565b612edb57565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa908115612f7b57600091612f60575090565b612f78915060203d81116127cb576127bd81836129b1565b90565b6040513d6000823e3d90fd5b15612f8e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b93929190612fd89160e0865260e0860191612d3b565b9260208091016000905b60068210612ff05750505050565b82806001928651815201940191019092612fe2565b90600182811c92168015613035575b602083101461301f57565b634e487b7160e01b600052602260045260246000fd5b91607f1691613014565b1561304657565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612b305760051b6101e40190565b1561309c57565b60405162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189d5c9b88185b5bdd5b9d606a1b6044820152606490fd5b9080156135c657600091808352602090604a825260409283852054806135495750604f835283852054806132715750818552604b8352838520600101548015613234576131249114613095565b808452604b8252828420546001600160a01b039081168061318e575b50918160019493604b9387528383527fd4c4548158257b028886d6db0faf9617bed9f9ec7f968df34f862c4c3a282f898387878a20938454169301548751908152a285525282208281550155565b61319790612f20565b156131a3575b38613140565b600554828652604b84528486208054600190910154865163a9059cbb60e01b81529184166001600160a01b031660048301526024820152908490829084168189816044810103925af1801561322a5791604b9391600196959361320d575b5091939450915061319d565b61322390843d86116127cb576127bd81836129b1565b5038613201565b85513d88823e3d90fd5b5050509150606492505b519062461bcd60e51b82526004820152601160248201527024b73b30b634b21036b4b73a17b13ab93760791b6044820152fd5b9592949190600180971461328c57505050506064925061323e565b6050869395949652838520908451906132a48261295f565b60018060a01b0398898454168352808401875180928a908354936132c785613005565b948585528b83821691826000146135275750506001146134eb575b50506132f0925003826129b1565b85830190815261331a6002850154928b60038a870197868952015416936060860194855214613095565b60055483518551895163095ea7b360e01b808252928e166001600160a01b031660048201526024810191909152909291889082908e16818d816044810103925af180156134e1579061337992916134c4575b508b855116905190613802565b156133bc575b505083604f959697987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d92511692518751908152a2845252812055565b858a600554169160448c865116918b8b519586948593845260048401528160248401525af180156134ba579186916134309361349d575b5060055490518551895163a9059cbb60e01b8152918d166001600160a01b0316600483015260248201529283918c169082908b9082906044820190565b03925af1801561349357987f4c8960f4a544bc6219a5d4a1373bf2e024a44fa1fa187be6a6817e4f400f823d928692604f98999a9b613476575b5092509897969561337f565b61348c90843d86116127cb576127bd81836129b1565b503861346a565b86513d89823e3d90fd5b6134b390833d85116127cb576127bd81836129b1565b50386133f3565b87513d8a823e3d90fd5b6134da90893d8b116127cb576127bd81836129b1565b503861336c565b89513d8c823e3d90fd5b8a92508c52818c20908c915b85831061350f5750506132f0935082010138806132e2565b80548388018501528694508b939092019181016134f7565b92509350506132f094915060ff191682840152151560051b82010138806132e2565b0361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b50606491519062461bcd60e51b825260048201526013602482015272125b9d985b1a59081b5a5b9d08185b5bdd5b9d606a1b6044820152fd5b5050565b919080156137fd57600092808452602091604a835260409384862054806137b75750604f84528486205480613619575050818552604b8352838520600101548015613234576131249114613095565b6001979496939291978091146136375750505050506064925061323e565b60508794969597528486209185519161364f8361295f565b60018060a01b03998a91828654168552808601908951918b9181549161367483613005565b92838652858d848316928360001461379457505050600114613751575b505050816136a09103826129b1565b8785019081526136ca6002870154948460038c890199888b52015416956060880196875214613095565b600554855187518b5163095ea7b360e01b8082529287166001600160a01b031660048201526024810191909152909490918a91839116818e816044810103925af18015613747579061337993929161372a575b508c86511690519061386c565b613740908a3d8c116127cb576127bd81836129b1565b503861371d565b8a513d8d823e3d90fd5b8d528a8d208b93508d9291905b82841061377557505050820101816136a038613691565b81949295969750805483858901015201910190928a928f96959461375e565b925093509391506136a0945060ff191682840152151560051b8201019138613691565b90500361358d579081604a928552828252807fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde83868820548751908152a2845252812055565b505050565b6001600160a01b038116600090815260516020526040812054909283929160ff161561386657829182602083519301916207a120f1903d15613862573d9061384982612a7f565b9161385760405193846129b1565b825260203d92013e90565b5090565b50505090565b6001600160a01b038116600090815260516020526040812054909384939160ff16156138af5783809360208451940192f1903d15613862573d9061384982612a7f565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a2646970667358221220f4bb08c972b912d5922423b946a85ed2172262c9e905b1535998153c03460be464736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/eth/artifacts/contracts/rollup/RollupV5.sol/artifacts.d.ts b/eth/artifacts/contracts/rollup/RollupV5.sol/artifacts.d.ts deleted file mode 100644 index 88d59f0..0000000 --- a/eth/artifacts/contracts/rollup/RollupV5.sol/artifacts.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -// This file was autogenerated by hardhat-viem, do not edit it. -// prettier-ignore -// tslint:disable -// eslint-disable - -import "hardhat/types/artifacts"; - -import { RollupV5$Type } from "./RollupV5"; - -declare module "hardhat/types/artifacts" { - interface ArtifactsMap { - ["RollupV5"]: RollupV5$Type; - ["contracts/rollup/RollupV5.sol:RollupV5"]: RollupV5$Type; - } -} diff --git a/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.d.ts b/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.d.ts deleted file mode 100644 index 899d83c..0000000 --- a/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.d.ts +++ /dev/null @@ -1,1315 +0,0 @@ -// This file was autogenerated by hardhat-viem, do not edit it. -// prettier-ignore -// tslint:disable -// eslint-disable - -import type { Address } from "viem"; -import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; -import "@nomicfoundation/hardhat-viem/types"; - -export interface RollupV6$Type { - "_format": "hh-sol-artifact-1", - "contractName": "RollupV6", - "sourceName": "contracts/rollup/RollupV6.sol", - "abi": [ - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - } - ], - "name": "BlockVerified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "BurnAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bool", - "name": "substitute", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "Burned", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToAddress", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToRouter", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MintAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Minted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "name": "ValidatorSetAdded", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "prover", - "type": "address" - } - ], - "name": "addProver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "addRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "aggregateVerifier", - "outputs": [ - { - "internalType": "contract AggregateVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "to", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burnToAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "internalType": "bytes", - "name": "routerCalldata", - "type": "bytes" - }, - { - "internalType": "address", - "name": "returnAddress", - "type": "address" - } - ], - "name": "burnToRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifier", - "outputs": [ - { - "internalType": "contract BurnVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifierV2", - "outputs": [ - { - "internalType": "contract BurnVerifierV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_bytes32", - "type": "bytes32" - } - ], - "name": "bytes32ToAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[6]", - "name": "hashes", - "type": "bytes32[6]" - } - ], - "name": "containsRootHashes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentRootHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPerRouterCall", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getBurn", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Burn", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRootHashes", - "outputs": [ - { - "internalType": "bytes32[64]", - "name": "", - "type": "bytes32[64]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "from", - "type": "uint256" - } - ], - "name": "getValidatorSets", - "outputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "internalType": "struct PublicValidatorSet[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - } - ], - "name": "hasBurn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_usdcAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_aggregateVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_mintVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_burnVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "prover", - "type": "address" - }, - { - "internalType": "address[]", - "name": "initialValidators", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "emptyMerkleTreeRootHash", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV4", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_burnVerifierV2", - "type": "address" - } - ], - "name": "initializeV5", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV6", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "isRouterWhitelisted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintVerifier", - "outputs": [ - { - "internalType": "contract MintVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "validAfter", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "validBefore", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v2", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s2", - "type": "bytes32" - } - ], - "name": "mintWithAuthorization", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "nextRootHashIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "removeRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "rolledUpLeafs", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "rootHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_gasPerRouterCall", - "type": "uint256" - } - ], - "name": "setGasPerRouterCall", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - } - ], - "name": "setRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "setValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "substituteBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "substitutedBurns", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usdc", - "outputs": [ - { - "internalType": "contract IUSDC", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - } - ], - "name": "verifyBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "gasPerBurnCall", - "type": "uint256" - } - ], - "name": "verifyBlock2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - } - ], - "name": "wasBurnSubstituted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60808060405234620000bd577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c16620000ae57506001600160401b036002600160401b03198282160162000068575b604051613c269081620000c38239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a138808062000058565b63f92ee8a960e01b8152600490fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612d075750806309fe537d14612ce45780630aef023f14612ca55780631000b72914612b4057806316b5c12214612b225780631d49e45714612ae557806324ca984e14612a605780633139332e14610d6f5780633644e51514612a4557806338e454b1146129c55780633e413bee1461299c57806345873f3f14612671578063485ee1e4146126525780634fb4eee31461203657806353b935571461200957806354a0860614611f8957806354ace93314611b1257806354fd4d5014611af25780635a02369314611a4d5780635cd8a76b146119cd5780635ced058e146119a55780635eeba6dd146114795780636779b7c21461145b5780636ae0b1541461141a578063715018a6146113af57806382f15a3b146112815780638da5cb5b1461124b578063a10e57a8146111b2578063a2ce9c1f14611188578063a65ddebd1461115f578063a91eebf51461113c578063afbd8c39146110d8578063b506165814610dc7578063c072bd8814610d9e578063c1b1535914610d6f578063c3a716eb14610d46578063c832fe5f14610cc1578063cb32583314610a9e578063ceace3b814610808578063d9581277146107d9578063dab5f340146107b4578063e4408e461461074d578063e795594d14610481578063ef0feff914610290578063f22a195e14610272578063f2fde38b146102455763f44ff7121461022557600080fd5b346102425780600319360112610242576020600754604051908152f35b80fd5b50346102425760203660031901126102425761026f610262612d2c565b61026a612ea1565b612eda565b80f35b50346102425780600319360112610242576020600654604051908152f35b503461024257602090816003193601126102425790600435604d546102b58282613015565b916102bf83613051565b926102cd6040519485612e80565b8084526102dc601f1991613051565b01855b818110610454575050805b8281106103a55750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103275787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b808210610382575050509060019383808094015191015298019301930190928796959394929461031a565b82516001600160a01b031685528a95948501949092019160019190910190610357565b808694959652604c8652604084206001600281830192015490604051926103cb84612e49565b60405191828b83549182815201928a528b8a20918a915b8d818410610436575050505050918161040561042d969593610427950382612e80565b8252898201526104158584613015565b90610420828a613077565b5287613077565b50613068565b949392946102ea565b84546001600160a01b031686529094019392810192918101916103e2565b94808097959660405161046681612e49565b60608152878382015282828a010152019050959493956102df565b5034610242576040366003190112610242576004356001600160401b0360248035828111610749576104b7903690600401612db5565b92906104c1612ea1565b604d9384548015801561070f575b1561069b57600052604c916020928084528760026040600020015586546000526001948560406000200190841161068657600160401b8411610686578054848255808510610669575b50829060005284600020908660005b868110610650575050505060005b838110610593575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161057f57505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826105bf6105ba868a8a6130b6565b6130a2565b16600052875260ff60406000205416610611579061060c92916000528387526040600020906105f26105ba8489896130b6565b16600052865260406000208760ff19825416179055613068565b610535565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761065a846130a2565b93019281850155018790610527565b61068090826000528587600020918201910161308b565b38610518565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161073457600052604c60205286600260406000200154106104cf565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346102425760203660031901126102425760408181926020835161077181612e49565b82815201526004358152604b60205220815161078c81612e49565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b5034610242576020366003190112610242576107ce612ea1565b61026f600435612fd7565b50346102425760203660031901126102425760ff60406020926004358152605484522054166040519015158152f35b5034610242576040366003190112610242576004356024358183526020906053825260ff604085205416610a4e578284526054825260ff604085205416610a0b576005546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03918490829060649082908a9087165af18015610a00576109d3575b508385526053835260408520926001938460ff1982541617905560008490868152604f835285604082205480156000146109c35750505085600052604b82528460406000200154156109bb575b80806109ab575b867f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde86040805189815284151587820152a2816109a3575b501561096757604b90858752604f81528660408120556040519561093d87612e49565b33875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6064906040519062461bcd60e51b825260048201526015602482015274149bdb1b1d5c158d8e88109d5c9b8819985a5b1959605a1b6044820152fd5b90503861091a565b506109b684876137f4565b6108e3565b5060006108dc565b036109b657506109b684876138b5565b6109f290843d86116109f9575b6109ea8183612e80565b8101906133d9565b503861088f565b503d6109e0565b6040513d88823e3d90fd5b6064826040519062461bcd60e51b825280600483015260248201527f526f6c6c757056363a204c65616620616c726561647920726f6c6c65642075706044820152fd5b60405162461bcd60e51b815260048101839052602260248201527f526f6c6c757056363a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b50346102425760c036600319011261024257610ab8612d2c565b6001600160401b039190602435838111610cbd57610ada903690600401612d58565b6044359260643591610aeb826133f1565b6004546040516001600160a01b039890939189169160a0850191821185831017610ca757899160405216928381526020958787830152856040830152608435606083015260a4356080830152823b15610ca3579290918892610b66604051958694625a2d8360e11b865260c0600487015260c4860191613260565b908489602486015b60058310610c86575050505082809103915afa8015610a0057908691610c72575b505083600052604f83526040600020541580610c5e575b15610c235760018495967f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d495600052604f85526000604081205560405192610bed84612e49565b835284830190848252878952604b8652604089209351166001600160601b0360a01b84541617835551910155604051908152a280f35b60405162461bcd60e51b81526004810184905260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b835260016040600020015415610ba6565b610c7b90612e00565b610749578438610b8f565b835181528d975088965092810192600192909201918b9101610b6e565b8880fd5b634e487b7160e01b600052604160045260246000fd5b8280fd5b503461024257806003193601126102425760405190610cdf82612e64565b610800809236903760405190600881835b60408210610d305750505090610d0581612e64565b6040519190825b60408310610d1957505050f35b600190825181526020809101920192019190610d0c565b6001602081928554815201930191019091610cf0565b50346102425780600319360112610242576004546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760ff60406020926004358152605384522054166040519015158152f35b50346102425780600319360112610242576002546040516001600160a01b039091168152602090f35b5034610242576101c0366003190112610242576001600160401b03906004358281116110d457610dfb903690600401612d58565b602435916044359160643595610e0f612d42565b9060a4359260c4359260e43591888a52602096604a885260408b205461109957604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528b60408801528a60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e08201526101008781830152815261012081019281841090841117610ca757610efe8692610f07928a956040525190208c610ebd6131b9565b916040519182019261190160f01b84526022830152604282015260428152610ee481612e2e565b5190206101a43590610184359060ff610164351690613281565b90929192613311565b1603611063578a9b8360039c999a9b9c541660405191610f2683612de5565b8d83528c8c8401526040830152803b1561105f57610f5d938a9360405195869485938493635e65f68960e11b855260048501613396565b03915afa908115611054578791611040575b50506005541690813b1561103c5785936040519586946377aadf6360e11b865260048601523060248601528960448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561103157611019575b5091837fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd289352604a8252806040862055604051908152a280f35b61102290612e00565b61102d578338610fdf565b8380fd5b6040513d84823e3d90fd5b8580fd5b61104990612e00565b61103c578538610f6f565b6040513d89823e3d90fd5b8980fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346102425760c0366003190112610242573660231215610242576040516110ff81612e13565b8060c49136831161102d57602093506004905b83821061112d5784611123846130d7565b6040519015158152f35b81358152908401908401611112565b50346102425780600319360112610242576020611157613022565b604051908152f35b50346102425780600319360112610242576052546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760406020916004358152604a83522054604051908152f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611237575b611225576006908160ff198554161784556207a12060555568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160068152a180f35b60405163f92ee8a960e01b8152600490fd5b5060066001600160401b03821610156111e2565b5034610242578060031936011261024257600080516020613b91833981519152546040516001600160a01b039091168152602090f35b50346102425760e0366003190112610242576024356004356044356001600160401b03811161102d576112b8903690600401612d58565b90926064359385608435936112cd8615613527565b6001600160a01b03848116949093906112e5866133f1565b8460525416604051916112f783612e13565b898352602083015289604083015287606083015260a435608083015260c43560a0830152803b15610749576113459385936040519586948593849363e261a9cb60e01b855260048501613562565b03915afa801561103157611395575b5050906001602093926113887f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d496886134ac565b60405192610bed84612e49565b6113a29094939294612e00565b61103c5790918538611354565b50346102425780600319360112610242576113c8612ea1565b600080516020613b9183398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461024257602036600319011261024257611434612d2c565b61143c612ea1565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346102425780600319360112610242576020604854604051908152f35b50346102425761010036600319011261024257611494612d2c565b6024356001600160a01b03811681036119a057604435906001600160a01b03821682036119a057606435906001600160a01b03821682036119a0576114d7612d42565b60a43591906001600160a01b03831683036119a05760c4356001600160401b03811161199c5761150b903690600401612db5565b949095600080516020613bd183398151915254976001600160401b038916158061198e575b60016001600160401b038b16149081611984575b15908161197b575b506112255761159b9060016001600160401b03198b1617600080516020613bd18339815191525560ff8a60401c161561194e575b8a5460ff19166001178b55611593612fa8565b61026a612fa8565b6115a3612f69565b6020815191012061160e61161c6115b8612f8b565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f198101835282612e80565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611932575b156118bd57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b038211610ca757600160401b8211610ca757805482825580831061189f575b50829060005260206000209060005b8381106118845750505060005b8181106117bf57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116117a95760ff91604d5561175560e435612fd7565b60401c16156117615780f35b68ff000000000000000019600080516020613bd18339815191525416600080516020613bd183398151915255600080516020613bb1833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b036117e96105ba8487896130b6565b1660005260205260ff604060002054166118445761183f91600052604c602052604060002060018060a01b036118236105ba8487896130b6565b166000526020526040600020600160ff19825416179055613068565b6116fb565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b6001906020611892846130a2565b93019281850155016116ee565b6118b79082600052836020600020918201910161308b565b386116df565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116117a957600052604c6020526000611694565b68ffffffffffffffffff198a166801000000000000000117600080516020613bd183398151915255611580565b9050153861154c565b303b159150611544565b5060ff8960401c1615611530565b8780fd5b600080fd5b5034610242576020366003190112610242576040516004356001600160a01b03168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611a39575b611225576002908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160028152a180f35b5060026001600160401b03821610156119fd565b503461024257602036600319011261024257611a67612d2c565b600080516020613bd183398151915290815460ff8160401c168015611ade575b611225576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160058152a180f35b5060056001600160401b0382161015611a87565b503461024257806003193601126102425760ff6020915416604051908152f35b503461024257610140366003190112610242576044356001600160401b0381116110d457611b44903690600401612d58565b60e4359291906001600160a01b03841684036119a057610104356001600160401b03811161102d57611b7a903690600401612d58565b909461012435929091906001600160a01b03841684036119a057611ba2600160043514613527565b6001600160a01b03841615611f4b576001600160a01b038316865260516020908152604087205490959060ff1615611f0d57611bdd856133f1565b6040519186830160018060a01b038616815260606040850152611c2684611c098c886080840191613260565b6001600160a01b038a16606083015203601f198101865285612e80565b925190922060243592906001600160fd1b0316839003611eda5760018060a01b03605254169160405193611c5985612e13565b6004358552888501526064356040850152608435606085015260a435608085015260c43560a0850152823b15610ca35760405163e261a9cb60e01b81529389938593909284928392611cae9260048501613562565b03915afa8015610a0057908691611ec6575b5050611cd06004356064356134ac565b60405191611cdd83612e2e565b6001600160a01b03168252611cf181612f4e565b95611cff6040519788612e80565b818752368282011161103c578186928692838a01378701015282810194855260843560408083019182526001600160a01b03938416606084019081526064358752605086529086209251835494166001600160a01b03199485161783559551805190969392919060018301906001600160401b038111611eb257611d8382546135a5565b601f8111611e79575b5086601f8211600114611e13578190899a60039798999a92611e08575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b03905116908254161790557f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d460405191608435835260643592a280f35b015190503880611da9565b82895287892099601f1983168a5b818110611e6257509160039798999a9b91846001959410611e4a575b505050811b019055611dbd565b015160001983891b60f8161c19169055388080611e3d565b838301518d556001909c019b928a01928a01611e21565b611ea290838a52888a20601f840160051c8101918a8510611ea8575b601f0160051c019061308b565b38611d8c565b9091508190611e95565b634e487b7160e01b88526041600452602488fd5b611ecf90612e00565b610749578438611cc0565b60405162461bcd60e51b815260048101889052600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152600481018790526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611ff5575b611225576004908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160048152a180f35b5060046001600160401b0382161015611fb9565b50346102425760203660031901126102425760043560408110156110d45760209060080154604051908152f35b503461024257610480366003190112610242576001600160401b03906004358281116110d45761206a903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd57612097903690600401612d85565b92909133825260496020526120b2600160408420541461320a565b33825260496020526120ca600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561263257808452604c6020526104443560026040862001541161210f578061210a918755613068565b6120db565b509193949092945b548452604c602052604084209261212c613022565b926101a4359384036125dc57855b60128110612560575061218a60405161215281612e13565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a08201526130d7565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526121e781612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261222381612de5565b5190206040519061223382612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061249557505090612283926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b848210612373578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156110315761235f575b50506123206101c435612fd7565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b61236890612e00565b6110d4578183612312565b6123a290606083028c019061239960ff9260208101359084604082359201351688613281565b90949194613311565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576123d79091613068565b90612293565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b6020828201810151602888840101528694500161225c565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116125c8576125749061324d565b35600282018083116125b4579061258d6125949261324d565b35906135df565b600381018091111561213a57634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294612117565b634e487b7160e01b84526011600452602484fd5b50346102425760203660031901126102425760206111236004356131dc565b5034610242576104a0366003190112610242576001600160401b03906004358281116110d4576126a5903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd576126d2903690600401612d85565b92909133825260496020526126ed600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561299057808452604c60205261044435600260408620015411612732578061272d918755613068565b6126fe565b509193949092945b548452604c602052604084209261274f613022565b926101a4359384036125dc57855b60128110612943575061277560405161215281612e13565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526127d281612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261280e81612de5565b5190206040519061281e82612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061292b5750509061286e926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b8482106128ca578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b6128f090606083028c019061239960ff9260208101359084604082359201351688613281565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576129259091613068565b9061287e565b60208282018101516028888401015286945001612847565b600181018082116125c8576129579061324d565b35600282018083116125b4579061258d6129709261324d565b600381018091111561275d57634e487b7160e01b87526011600452602487fd5b5091939490929461273a565b50346102425780600319360112610242576005546040516001600160a01b039091168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015612a31575b611225576003908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160038152a180f35b5060036001600160401b03821610156129f5565b503461024257806003193601126102425760206111576131b9565b503461024257602036600319011261024257612a7a612d2c565b612a82612ea1565b803b15612aab576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b503461024257602036600319011261024257612aff612d2c565b612b07612ea1565b6001600160a01b031681526049602052604081206001905580f35b50346102425780600319360112610242576020605554604051908152f35b5034610242576080366003190112610242576004356001600160401b0381116110d457612b71903690600401612d58565b6024359160443591838552602091604a83526040862054611099576003546040516001600160a01b03938892851690612ba983612de5565b88835287878401526064356040840152813b1561102d57612be19460405195869485938493635e65f68960e11b855260048501613396565b03915afa8015610a0057612c92575b506005546040516323b872dd60e01b81523360048201523060248201526044810185905293918391859160649183918a91165af1928315612c87577fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd2893612c6a575b50838552604a8252806040862055604051908152a280f35b612c8090833d85116109f9576109ea8183612e80565b5038612c52565b6040513d87823e3d90fd5b612c9e90959195612e00565b9338612bf0565b50346102425760203660031901126102425760209060ff906040906001600160a01b03612cd0612d2c565b168152605184522054166040519015158152f35b503461024257602036600319011261024257612cfe612ea1565b60043560555580f35b9050346110d457816003193601126110d4576003546001600160a01b03168152602090f35b600435906001600160a01b03821682036119a057565b608435906001600160a01b03821682036119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602083818601950101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602080850194606085020101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a0576020808501948460051b0101116119a057565b606081019081106001600160401b03821117610ca757604052565b6001600160401b038111610ca757604052565b60c081019081106001600160401b03821117610ca757604052565b608081019081106001600160401b03821117610ca757604052565b604081019081106001600160401b03821117610ca757604052565b61080081019081106001600160401b03821117610ca757604052565b90601f801991011681019081106001600160401b03821117610ca757604052565b600080516020613b91833981519152546001600160a01b03163303612ec257565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612f3557600080516020613b9183398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b038111610ca757601f01601f191660200190565b60405190612f7682612e49565b60068252650526f6c6c75760d41b6020830152565b60405190612f9882612e49565b60018252603160f81b6020830152565b60ff600080516020613bd18339815191525460401c1615612fc557565b604051631afcd79f60e31b8152600490fd5b6048546040811015612fff57600801556048546001810181116117a957600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116117a957565b603f6048548061303e575b506040811015612fff576008015490565b6000198101915081116117a9573861302d565b6001600160401b038111610ca75760051b60200190565b60001981146117a95760010190565b8051821015612fff5760209160051b010190565b818110613096575050565b6000815560010161308b565b356001600160a01b03811681036119a05790565b9190811015612fff5760051b0190565b906006811015612fff5760051b0190565b6040908151916130e683612e13565b60009182845282602085015282828501528260608501528260808501528260a0850152825b6006811061314c57505050805b6006811061312857505050600190565b61313281846130c6565b51156131465761314190613068565b613118565b50905090565b835b838110613165575b5061316090613068565b61310b565b61316f82846130c6565b5181600801541480156131a7575b61318f5761318a90613068565b61314e565b508060016131a061316093886130c6565b5290613156565b506131b282846130c6565b511561317d565b6131c1612f69565b6020815191012061160e6131d66115b8612f8b565b51902090565b600052604f6020526040600020541560001461320557604b602052600160406000200154151590565b600190565b1561321157565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612fff5760051b6101e40190565b908060209392818452848401376000828201840152601f01601f1916010190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161330557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156132f95780516001600160a01b038116156132f057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60048110156133805780613323575050565b6001810361333d5760405163f645eedf60e01b8152600490fd5b6002810361335e5760405163fce698f760e01b815260048101839052602490fd5b6003146133685750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b939291906133ac91608086526080860191613260565b9260208091016000905b600382106133c45750505050565b828060019286518152019401910190926133b6565b908160209103126119a0575180151581036119a05790565b6133fa90613445565b61340057565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa9081156134a057600091613485575090565b61349d915060203d81116109f9576109ea8183612e80565b90565b6040513d6000823e3d90fd5b80600052604f6020526040600020541580613512575b156134d757600052604f602052604060002055565b60405162461bcd60e51b81526020600482015260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b602052600160406000200154156134c2565b1561352e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b939291906135789160e0865260e0860191613260565b9260208091016000905b600682106135905750505050565b82806001928651815201940191019092613582565b90600182811c921680156135d5575b60208310146135bf57565b634e487b7160e01b600052602260045260246000fd5b91607f16916135b4565b81156137a45760009181835260209260548452604092838220600160ff19825416179055604a85528382205480613720575083600192828152604f87528181205480156000146136dc5750828152604b8752838282200154156136d4575b8380957f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde89495916136c3575b505b8251918252151587820152a215613680575050565b60649250519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056363a204275726e20776173206e6f7420666f756e64000000006044820152fd5b6136ce9150856137f4565b38613669565b92508261363d565b94847f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde8949596146000146137195761371490856138b5565b61366b565b508061366b565b94939290940361376057908082857fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde959452604a845220549051908152a2565b815162461bcd60e51b815260048101849052601d60248201527f526f6c6c757056363a20496e76616c6964206d696e7420616d6f756e740000006044820152606490fd5b5050565b156137af57565b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056363a20496e76616c6964206275726e20616d6f756e740000006044820152606490fd5b600052604b60205260206040600020916040519261381184612e49565b60018060a01b0393600185835416928383520154938491015282156138ac576138799361384183602095146137a8565b6005541690600060405180968195829463a9059cbb60e01b84526004840160209093929193604081019460018060a01b031681520152565b03925af1908161388e575b5061320557600090565b6138a59060203d81116109f9576109ea8183612e80565b5038613884565b50505050600090565b60009081526020906050825260409081812082516138d281612e2e565b60018060a01b03808354168252600196878401928887518095889080548c6138f9826135a5565b808652958216918215613b09575050600114613acb575b5061391d92500385612e80565b878101938452600285015493613948838560038b860199898b520154169660608501978852146137a8565b6005548251895163095ea7b360e01b8082529187166001600160a01b03166004820152602481019590955293908a9082908716818b816044810103925af18015613ac157916139a8918b93613aa4575b5085845116905160555491613b29565b92604485806005541694511691898b519586948593845260048401528160248401525af18015613a9a57613a7d575b50156139e7575b50505050505090565b6139f381835116613445565b613a735760055491519251855163a9059cbb60e01b81529382166001600160a01b0316600485015260248401529193929185918591168184816044810103925af1918215613a69575050613a4b575b808080806139de565b81613a6192903d106109f9576109ea8183612e80565b503880613a42565b51903d90823e3d90fd5b5050509250505090565b613a9390883d8a116109f9576109ea8183612e80565b50386139d7565b87513d88823e3d90fd5b613aba90843d86116109f9576109ea8183612e80565b5038613998565b89513d8a823e3d90fd5b915050875284898089208c8a915b858310613af057505061391d935082010138613910565b80919294505483858b0101520191018a908c8893613ad9565b60ff19168582015261391d95151560051b85010192503891506139109050565b6001600160a01b038116600090815260516020526040812054909384939160ff1615613b895783809360208451940192f1903d15613b85573d90613b6c82612f4e565b91613b7a6040519384612e80565b825260203d92013e90565b5090565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212207f199a497c7371541cba4cc6b6833ea67be05c7152013473ca7aa5539e5e9a5264736f6c63430008140033", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612d075750806309fe537d14612ce45780630aef023f14612ca55780631000b72914612b4057806316b5c12214612b225780631d49e45714612ae557806324ca984e14612a605780633139332e14610d6f5780633644e51514612a4557806338e454b1146129c55780633e413bee1461299c57806345873f3f14612671578063485ee1e4146126525780634fb4eee31461203657806353b935571461200957806354a0860614611f8957806354ace93314611b1257806354fd4d5014611af25780635a02369314611a4d5780635cd8a76b146119cd5780635ced058e146119a55780635eeba6dd146114795780636779b7c21461145b5780636ae0b1541461141a578063715018a6146113af57806382f15a3b146112815780638da5cb5b1461124b578063a10e57a8146111b2578063a2ce9c1f14611188578063a65ddebd1461115f578063a91eebf51461113c578063afbd8c39146110d8578063b506165814610dc7578063c072bd8814610d9e578063c1b1535914610d6f578063c3a716eb14610d46578063c832fe5f14610cc1578063cb32583314610a9e578063ceace3b814610808578063d9581277146107d9578063dab5f340146107b4578063e4408e461461074d578063e795594d14610481578063ef0feff914610290578063f22a195e14610272578063f2fde38b146102455763f44ff7121461022557600080fd5b346102425780600319360112610242576020600754604051908152f35b80fd5b50346102425760203660031901126102425761026f610262612d2c565b61026a612ea1565b612eda565b80f35b50346102425780600319360112610242576020600654604051908152f35b503461024257602090816003193601126102425790600435604d546102b58282613015565b916102bf83613051565b926102cd6040519485612e80565b8084526102dc601f1991613051565b01855b818110610454575050805b8281106103a55750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103275787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b808210610382575050509060019383808094015191015298019301930190928796959394929461031a565b82516001600160a01b031685528a95948501949092019160019190910190610357565b808694959652604c8652604084206001600281830192015490604051926103cb84612e49565b60405191828b83549182815201928a528b8a20918a915b8d818410610436575050505050918161040561042d969593610427950382612e80565b8252898201526104158584613015565b90610420828a613077565b5287613077565b50613068565b949392946102ea565b84546001600160a01b031686529094019392810192918101916103e2565b94808097959660405161046681612e49565b60608152878382015282828a010152019050959493956102df565b5034610242576040366003190112610242576004356001600160401b0360248035828111610749576104b7903690600401612db5565b92906104c1612ea1565b604d9384548015801561070f575b1561069b57600052604c916020928084528760026040600020015586546000526001948560406000200190841161068657600160401b8411610686578054848255808510610669575b50829060005284600020908660005b868110610650575050505060005b838110610593575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161057f57505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826105bf6105ba868a8a6130b6565b6130a2565b16600052875260ff60406000205416610611579061060c92916000528387526040600020906105f26105ba8489896130b6565b16600052865260406000208760ff19825416179055613068565b610535565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761065a846130a2565b93019281850155018790610527565b61068090826000528587600020918201910161308b565b38610518565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161073457600052604c60205286600260406000200154106104cf565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346102425760203660031901126102425760408181926020835161077181612e49565b82815201526004358152604b60205220815161078c81612e49565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b5034610242576020366003190112610242576107ce612ea1565b61026f600435612fd7565b50346102425760203660031901126102425760ff60406020926004358152605484522054166040519015158152f35b5034610242576040366003190112610242576004356024358183526020906053825260ff604085205416610a4e578284526054825260ff604085205416610a0b576005546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03918490829060649082908a9087165af18015610a00576109d3575b508385526053835260408520926001938460ff1982541617905560008490868152604f835285604082205480156000146109c35750505085600052604b82528460406000200154156109bb575b80806109ab575b867f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde86040805189815284151587820152a2816109a3575b501561096757604b90858752604f81528660408120556040519561093d87612e49565b33875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6064906040519062461bcd60e51b825260048201526015602482015274149bdb1b1d5c158d8e88109d5c9b8819985a5b1959605a1b6044820152fd5b90503861091a565b506109b684876137f4565b6108e3565b5060006108dc565b036109b657506109b684876138b5565b6109f290843d86116109f9575b6109ea8183612e80565b8101906133d9565b503861088f565b503d6109e0565b6040513d88823e3d90fd5b6064826040519062461bcd60e51b825280600483015260248201527f526f6c6c757056363a204c65616620616c726561647920726f6c6c65642075706044820152fd5b60405162461bcd60e51b815260048101839052602260248201527f526f6c6c757056363a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b50346102425760c036600319011261024257610ab8612d2c565b6001600160401b039190602435838111610cbd57610ada903690600401612d58565b6044359260643591610aeb826133f1565b6004546040516001600160a01b039890939189169160a0850191821185831017610ca757899160405216928381526020958787830152856040830152608435606083015260a4356080830152823b15610ca3579290918892610b66604051958694625a2d8360e11b865260c0600487015260c4860191613260565b908489602486015b60058310610c86575050505082809103915afa8015610a0057908691610c72575b505083600052604f83526040600020541580610c5e575b15610c235760018495967f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d495600052604f85526000604081205560405192610bed84612e49565b835284830190848252878952604b8652604089209351166001600160601b0360a01b84541617835551910155604051908152a280f35b60405162461bcd60e51b81526004810184905260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b835260016040600020015415610ba6565b610c7b90612e00565b610749578438610b8f565b835181528d975088965092810192600192909201918b9101610b6e565b8880fd5b634e487b7160e01b600052604160045260246000fd5b8280fd5b503461024257806003193601126102425760405190610cdf82612e64565b610800809236903760405190600881835b60408210610d305750505090610d0581612e64565b6040519190825b60408310610d1957505050f35b600190825181526020809101920192019190610d0c565b6001602081928554815201930191019091610cf0565b50346102425780600319360112610242576004546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760ff60406020926004358152605384522054166040519015158152f35b50346102425780600319360112610242576002546040516001600160a01b039091168152602090f35b5034610242576101c0366003190112610242576001600160401b03906004358281116110d457610dfb903690600401612d58565b602435916044359160643595610e0f612d42565b9060a4359260c4359260e43591888a52602096604a885260408b205461109957604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528b60408801528a60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e08201526101008781830152815261012081019281841090841117610ca757610efe8692610f07928a956040525190208c610ebd6131b9565b916040519182019261190160f01b84526022830152604282015260428152610ee481612e2e565b5190206101a43590610184359060ff610164351690613281565b90929192613311565b1603611063578a9b8360039c999a9b9c541660405191610f2683612de5565b8d83528c8c8401526040830152803b1561105f57610f5d938a9360405195869485938493635e65f68960e11b855260048501613396565b03915afa908115611054578791611040575b50506005541690813b1561103c5785936040519586946377aadf6360e11b865260048601523060248601528960448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561103157611019575b5091837fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd289352604a8252806040862055604051908152a280f35b61102290612e00565b61102d578338610fdf565b8380fd5b6040513d84823e3d90fd5b8580fd5b61104990612e00565b61103c578538610f6f565b6040513d89823e3d90fd5b8980fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346102425760c0366003190112610242573660231215610242576040516110ff81612e13565b8060c49136831161102d57602093506004905b83821061112d5784611123846130d7565b6040519015158152f35b81358152908401908401611112565b50346102425780600319360112610242576020611157613022565b604051908152f35b50346102425780600319360112610242576052546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760406020916004358152604a83522054604051908152f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611237575b611225576006908160ff198554161784556207a12060555568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160068152a180f35b60405163f92ee8a960e01b8152600490fd5b5060066001600160401b03821610156111e2565b5034610242578060031936011261024257600080516020613b91833981519152546040516001600160a01b039091168152602090f35b50346102425760e0366003190112610242576024356004356044356001600160401b03811161102d576112b8903690600401612d58565b90926064359385608435936112cd8615613527565b6001600160a01b03848116949093906112e5866133f1565b8460525416604051916112f783612e13565b898352602083015289604083015287606083015260a435608083015260c43560a0830152803b15610749576113459385936040519586948593849363e261a9cb60e01b855260048501613562565b03915afa801561103157611395575b5050906001602093926113887f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d496886134ac565b60405192610bed84612e49565b6113a29094939294612e00565b61103c5790918538611354565b50346102425780600319360112610242576113c8612ea1565b600080516020613b9183398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461024257602036600319011261024257611434612d2c565b61143c612ea1565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346102425780600319360112610242576020604854604051908152f35b50346102425761010036600319011261024257611494612d2c565b6024356001600160a01b03811681036119a057604435906001600160a01b03821682036119a057606435906001600160a01b03821682036119a0576114d7612d42565b60a43591906001600160a01b03831683036119a05760c4356001600160401b03811161199c5761150b903690600401612db5565b949095600080516020613bd183398151915254976001600160401b038916158061198e575b60016001600160401b038b16149081611984575b15908161197b575b506112255761159b9060016001600160401b03198b1617600080516020613bd18339815191525560ff8a60401c161561194e575b8a5460ff19166001178b55611593612fa8565b61026a612fa8565b6115a3612f69565b6020815191012061160e61161c6115b8612f8b565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f198101835282612e80565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611932575b156118bd57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b038211610ca757600160401b8211610ca757805482825580831061189f575b50829060005260206000209060005b8381106118845750505060005b8181106117bf57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116117a95760ff91604d5561175560e435612fd7565b60401c16156117615780f35b68ff000000000000000019600080516020613bd18339815191525416600080516020613bd183398151915255600080516020613bb1833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b036117e96105ba8487896130b6565b1660005260205260ff604060002054166118445761183f91600052604c602052604060002060018060a01b036118236105ba8487896130b6565b166000526020526040600020600160ff19825416179055613068565b6116fb565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b6001906020611892846130a2565b93019281850155016116ee565b6118b79082600052836020600020918201910161308b565b386116df565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116117a957600052604c6020526000611694565b68ffffffffffffffffff198a166801000000000000000117600080516020613bd183398151915255611580565b9050153861154c565b303b159150611544565b5060ff8960401c1615611530565b8780fd5b600080fd5b5034610242576020366003190112610242576040516004356001600160a01b03168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611a39575b611225576002908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160028152a180f35b5060026001600160401b03821610156119fd565b503461024257602036600319011261024257611a67612d2c565b600080516020613bd183398151915290815460ff8160401c168015611ade575b611225576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160058152a180f35b5060056001600160401b0382161015611a87565b503461024257806003193601126102425760ff6020915416604051908152f35b503461024257610140366003190112610242576044356001600160401b0381116110d457611b44903690600401612d58565b60e4359291906001600160a01b03841684036119a057610104356001600160401b03811161102d57611b7a903690600401612d58565b909461012435929091906001600160a01b03841684036119a057611ba2600160043514613527565b6001600160a01b03841615611f4b576001600160a01b038316865260516020908152604087205490959060ff1615611f0d57611bdd856133f1565b6040519186830160018060a01b038616815260606040850152611c2684611c098c886080840191613260565b6001600160a01b038a16606083015203601f198101865285612e80565b925190922060243592906001600160fd1b0316839003611eda5760018060a01b03605254169160405193611c5985612e13565b6004358552888501526064356040850152608435606085015260a435608085015260c43560a0850152823b15610ca35760405163e261a9cb60e01b81529389938593909284928392611cae9260048501613562565b03915afa8015610a0057908691611ec6575b5050611cd06004356064356134ac565b60405191611cdd83612e2e565b6001600160a01b03168252611cf181612f4e565b95611cff6040519788612e80565b818752368282011161103c578186928692838a01378701015282810194855260843560408083019182526001600160a01b03938416606084019081526064358752605086529086209251835494166001600160a01b03199485161783559551805190969392919060018301906001600160401b038111611eb257611d8382546135a5565b601f8111611e79575b5086601f8211600114611e13578190899a60039798999a92611e08575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b03905116908254161790557f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d460405191608435835260643592a280f35b015190503880611da9565b82895287892099601f1983168a5b818110611e6257509160039798999a9b91846001959410611e4a575b505050811b019055611dbd565b015160001983891b60f8161c19169055388080611e3d565b838301518d556001909c019b928a01928a01611e21565b611ea290838a52888a20601f840160051c8101918a8510611ea8575b601f0160051c019061308b565b38611d8c565b9091508190611e95565b634e487b7160e01b88526041600452602488fd5b611ecf90612e00565b610749578438611cc0565b60405162461bcd60e51b815260048101889052600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152600481018790526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611ff5575b611225576004908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160048152a180f35b5060046001600160401b0382161015611fb9565b50346102425760203660031901126102425760043560408110156110d45760209060080154604051908152f35b503461024257610480366003190112610242576001600160401b03906004358281116110d45761206a903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd57612097903690600401612d85565b92909133825260496020526120b2600160408420541461320a565b33825260496020526120ca600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561263257808452604c6020526104443560026040862001541161210f578061210a918755613068565b6120db565b509193949092945b548452604c602052604084209261212c613022565b926101a4359384036125dc57855b60128110612560575061218a60405161215281612e13565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a08201526130d7565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526121e781612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261222381612de5565b5190206040519061223382612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061249557505090612283926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b848210612373578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156110315761235f575b50506123206101c435612fd7565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b61236890612e00565b6110d4578183612312565b6123a290606083028c019061239960ff9260208101359084604082359201351688613281565b90949194613311565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576123d79091613068565b90612293565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b6020828201810151602888840101528694500161225c565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116125c8576125749061324d565b35600282018083116125b4579061258d6125949261324d565b35906135df565b600381018091111561213a57634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294612117565b634e487b7160e01b84526011600452602484fd5b50346102425760203660031901126102425760206111236004356131dc565b5034610242576104a0366003190112610242576001600160401b03906004358281116110d4576126a5903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd576126d2903690600401612d85565b92909133825260496020526126ed600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561299057808452604c60205261044435600260408620015411612732578061272d918755613068565b6126fe565b509193949092945b548452604c602052604084209261274f613022565b926101a4359384036125dc57855b60128110612943575061277560405161215281612e13565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526127d281612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261280e81612de5565b5190206040519061281e82612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061292b5750509061286e926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b8482106128ca578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b6128f090606083028c019061239960ff9260208101359084604082359201351688613281565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576129259091613068565b9061287e565b60208282018101516028888401015286945001612847565b600181018082116125c8576129579061324d565b35600282018083116125b4579061258d6129709261324d565b600381018091111561275d57634e487b7160e01b87526011600452602487fd5b5091939490929461273a565b50346102425780600319360112610242576005546040516001600160a01b039091168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015612a31575b611225576003908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160038152a180f35b5060036001600160401b03821610156129f5565b503461024257806003193601126102425760206111576131b9565b503461024257602036600319011261024257612a7a612d2c565b612a82612ea1565b803b15612aab576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b503461024257602036600319011261024257612aff612d2c565b612b07612ea1565b6001600160a01b031681526049602052604081206001905580f35b50346102425780600319360112610242576020605554604051908152f35b5034610242576080366003190112610242576004356001600160401b0381116110d457612b71903690600401612d58565b6024359160443591838552602091604a83526040862054611099576003546040516001600160a01b03938892851690612ba983612de5565b88835287878401526064356040840152813b1561102d57612be19460405195869485938493635e65f68960e11b855260048501613396565b03915afa8015610a0057612c92575b506005546040516323b872dd60e01b81523360048201523060248201526044810185905293918391859160649183918a91165af1928315612c87577fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd2893612c6a575b50838552604a8252806040862055604051908152a280f35b612c8090833d85116109f9576109ea8183612e80565b5038612c52565b6040513d87823e3d90fd5b612c9e90959195612e00565b9338612bf0565b50346102425760203660031901126102425760209060ff906040906001600160a01b03612cd0612d2c565b168152605184522054166040519015158152f35b503461024257602036600319011261024257612cfe612ea1565b60043560555580f35b9050346110d457816003193601126110d4576003546001600160a01b03168152602090f35b600435906001600160a01b03821682036119a057565b608435906001600160a01b03821682036119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602083818601950101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602080850194606085020101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a0576020808501948460051b0101116119a057565b606081019081106001600160401b03821117610ca757604052565b6001600160401b038111610ca757604052565b60c081019081106001600160401b03821117610ca757604052565b608081019081106001600160401b03821117610ca757604052565b604081019081106001600160401b03821117610ca757604052565b61080081019081106001600160401b03821117610ca757604052565b90601f801991011681019081106001600160401b03821117610ca757604052565b600080516020613b91833981519152546001600160a01b03163303612ec257565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612f3557600080516020613b9183398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b038111610ca757601f01601f191660200190565b60405190612f7682612e49565b60068252650526f6c6c75760d41b6020830152565b60405190612f9882612e49565b60018252603160f81b6020830152565b60ff600080516020613bd18339815191525460401c1615612fc557565b604051631afcd79f60e31b8152600490fd5b6048546040811015612fff57600801556048546001810181116117a957600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116117a957565b603f6048548061303e575b506040811015612fff576008015490565b6000198101915081116117a9573861302d565b6001600160401b038111610ca75760051b60200190565b60001981146117a95760010190565b8051821015612fff5760209160051b010190565b818110613096575050565b6000815560010161308b565b356001600160a01b03811681036119a05790565b9190811015612fff5760051b0190565b906006811015612fff5760051b0190565b6040908151916130e683612e13565b60009182845282602085015282828501528260608501528260808501528260a0850152825b6006811061314c57505050805b6006811061312857505050600190565b61313281846130c6565b51156131465761314190613068565b613118565b50905090565b835b838110613165575b5061316090613068565b61310b565b61316f82846130c6565b5181600801541480156131a7575b61318f5761318a90613068565b61314e565b508060016131a061316093886130c6565b5290613156565b506131b282846130c6565b511561317d565b6131c1612f69565b6020815191012061160e6131d66115b8612f8b565b51902090565b600052604f6020526040600020541560001461320557604b602052600160406000200154151590565b600190565b1561321157565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612fff5760051b6101e40190565b908060209392818452848401376000828201840152601f01601f1916010190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161330557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156132f95780516001600160a01b038116156132f057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60048110156133805780613323575050565b6001810361333d5760405163f645eedf60e01b8152600490fd5b6002810361335e5760405163fce698f760e01b815260048101839052602490fd5b6003146133685750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b939291906133ac91608086526080860191613260565b9260208091016000905b600382106133c45750505050565b828060019286518152019401910190926133b6565b908160209103126119a0575180151581036119a05790565b6133fa90613445565b61340057565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa9081156134a057600091613485575090565b61349d915060203d81116109f9576109ea8183612e80565b90565b6040513d6000823e3d90fd5b80600052604f6020526040600020541580613512575b156134d757600052604f602052604060002055565b60405162461bcd60e51b81526020600482015260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b602052600160406000200154156134c2565b1561352e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b939291906135789160e0865260e0860191613260565b9260208091016000905b600682106135905750505050565b82806001928651815201940191019092613582565b90600182811c921680156135d5575b60208310146135bf57565b634e487b7160e01b600052602260045260246000fd5b91607f16916135b4565b81156137a45760009181835260209260548452604092838220600160ff19825416179055604a85528382205480613720575083600192828152604f87528181205480156000146136dc5750828152604b8752838282200154156136d4575b8380957f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde89495916136c3575b505b8251918252151587820152a215613680575050565b60649250519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056363a204275726e20776173206e6f7420666f756e64000000006044820152fd5b6136ce9150856137f4565b38613669565b92508261363d565b94847f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde8949596146000146137195761371490856138b5565b61366b565b508061366b565b94939290940361376057908082857fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde959452604a845220549051908152a2565b815162461bcd60e51b815260048101849052601d60248201527f526f6c6c757056363a20496e76616c6964206d696e7420616d6f756e740000006044820152606490fd5b5050565b156137af57565b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056363a20496e76616c6964206275726e20616d6f756e740000006044820152606490fd5b600052604b60205260206040600020916040519261381184612e49565b60018060a01b0393600185835416928383520154938491015282156138ac576138799361384183602095146137a8565b6005541690600060405180968195829463a9059cbb60e01b84526004840160209093929193604081019460018060a01b031681520152565b03925af1908161388e575b5061320557600090565b6138a59060203d81116109f9576109ea8183612e80565b5038613884565b50505050600090565b60009081526020906050825260409081812082516138d281612e2e565b60018060a01b03808354168252600196878401928887518095889080548c6138f9826135a5565b808652958216918215613b09575050600114613acb575b5061391d92500385612e80565b878101938452600285015493613948838560038b860199898b520154169660608501978852146137a8565b6005548251895163095ea7b360e01b8082529187166001600160a01b03166004820152602481019590955293908a9082908716818b816044810103925af18015613ac157916139a8918b93613aa4575b5085845116905160555491613b29565b92604485806005541694511691898b519586948593845260048401528160248401525af18015613a9a57613a7d575b50156139e7575b50505050505090565b6139f381835116613445565b613a735760055491519251855163a9059cbb60e01b81529382166001600160a01b0316600485015260248401529193929185918591168184816044810103925af1918215613a69575050613a4b575b808080806139de565b81613a6192903d106109f9576109ea8183612e80565b503880613a42565b51903d90823e3d90fd5b5050509250505090565b613a9390883d8a116109f9576109ea8183612e80565b50386139d7565b87513d88823e3d90fd5b613aba90843d86116109f9576109ea8183612e80565b5038613998565b89513d8a823e3d90fd5b915050875284898089208c8a915b858310613af057505061391d935082010138613910565b80919294505483858b0101520191018a908c8893613ad9565b60ff19168582015261391d95151560051b85010192503891506139109050565b6001600160a01b038116600090815260516020526040812054909384939160ff1615613b895783809360208451940192f1903d15613b85573d90613b6c82612f4e565b91613b7a6040519384612e80565b825260203d92013e90565b5090565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212207f199a497c7371541cba4cc6b6833ea67be05c7152013473ca7aa5539e5e9a5264736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} - -declare module "@nomicfoundation/hardhat-viem/types" { - export function deployContract( - contractName: "RollupV6", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - export function deployContract( - contractName: "contracts/rollup/RollupV6.sol:RollupV6", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - - export function sendDeploymentTransaction( - contractName: "RollupV6", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - export function sendDeploymentTransaction( - contractName: "contracts/rollup/RollupV6.sol:RollupV6", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - - export function getContractAt( - contractName: "RollupV6", - address: Address, - config?: GetContractAtConfig - ): Promise>; - export function getContractAt( - contractName: "contracts/rollup/RollupV6.sol:RollupV6", - address: Address, - config?: GetContractAtConfig - ): Promise>; -} diff --git a/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.dbg.json b/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.dbg.json deleted file mode 100644 index b7a6a76..0000000 --- a/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/22152f3e0e0b93ca501b6ace01f305e7.json" -} diff --git a/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.json b/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.json deleted file mode 100644 index 23f3db9..0000000 --- a/eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.json +++ /dev/null @@ -1,1265 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "RollupV6", - "sourceName": "contracts/rollup/RollupV6.sol", - "abi": [ - { - "inputs": [], - "name": "ECDSAInvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "length", - "type": "uint256" - } - ], - "name": "ECDSAInvalidSignatureLength", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "name": "ECDSAInvalidSignatureS", - "type": "error" - }, - { - "inputs": [], - "name": "InvalidInitialization", - "type": "error" - }, - { - "inputs": [], - "name": "NotInitializing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "root", - "type": "bytes32" - } - ], - "name": "BlockVerified", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "BurnAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bool", - "name": "substitute", - "type": "bool" - }, - { - "indexed": false, - "internalType": "bool", - "name": "success", - "type": "bool" - } - ], - "name": "Burned", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToAddress", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "BurnedToRouter", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "version", - "type": "uint64" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "MintAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "Minted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "index", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "name": "ValidatorSetAdded", - "type": "event" - }, - { - "inputs": [], - "name": "DOMAIN_SEPARATOR", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "prover", - "type": "address" - } - ], - "name": "addProver", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "addRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "aggregateVerifier", - "outputs": [ - { - "internalType": "contract AggregateVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "blockHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifer", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "to", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - } - ], - "name": "burnToAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "kind", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "msgHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "sig", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "router", - "type": "address" - }, - { - "internalType": "bytes", - "name": "routerCalldata", - "type": "bytes" - }, - { - "internalType": "address", - "name": "returnAddress", - "type": "address" - } - ], - "name": "burnToRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifier", - "outputs": [ - { - "internalType": "contract BurnVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "burnVerifierV2", - "outputs": [ - { - "internalType": "contract BurnVerifierV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_bytes32", - "type": "bytes32" - } - ], - "name": "bytes32ToAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32[6]", - "name": "hashes", - "type": "bytes32[6]" - } - ], - "name": "containsRootHashes", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentRootHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPerRouterCall", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getBurn", - "outputs": [ - { - "components": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct Burn", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "key", - "type": "bytes32" - } - ], - "name": "getMint", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getRootHashes", - "outputs": [ - { - "internalType": "bytes32[64]", - "name": "", - "type": "bytes32[64]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "from", - "type": "uint256" - } - ], - "name": "getValidatorSets", - "outputs": [ - { - "components": [ - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - }, - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - } - ], - "internalType": "struct PublicValidatorSet[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - } - ], - "name": "hasBurn", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "_usdcAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_aggregateVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_mintVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "_burnVerifier", - "type": "address" - }, - { - "internalType": "address", - "name": "prover", - "type": "address" - }, - { - "internalType": "address[]", - "name": "initialValidators", - "type": "address[]" - }, - { - "internalType": "bytes32", - "name": "emptyMerkleTreeRootHash", - "type": "bytes32" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV3", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV4", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "_burnVerifierV2", - "type": "address" - } - ], - "name": "initializeV5", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initializeV6", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "isRouterWhitelisted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "mintVerifier", - "outputs": [ - { - "internalType": "contract MintVerifierV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "commitment", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "value", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "source", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "validAfter", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "validBefore", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "nonce", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v2", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "r2", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s2", - "type": "bytes32" - } - ], - "name": "mintWithAuthorization", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "nextRootHashIndex", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "router", - "type": "address" - } - ], - "name": "removeRouter", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "rolledUpLeafs", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "rootHashes", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_gasPerRouterCall", - "type": "uint256" - } - ], - "name": "setGasPerRouterCall", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - } - ], - "name": "setRoot", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "validFrom", - "type": "uint256" - }, - { - "internalType": "address[]", - "name": "validators", - "type": "address[]" - } - ], - "name": "setValidators", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "substituteBurn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "substitutedBurns", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "usdc", - "outputs": [ - { - "internalType": "contract IUSDC", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - } - ], - "name": "verifyBlock", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "aggrProof", - "type": "bytes" - }, - { - "internalType": "bytes32[12]", - "name": "aggrInstances", - "type": "bytes32[12]" - }, - { - "internalType": "bytes32", - "name": "oldRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[18]", - "name": "utxoHashes", - "type": "bytes32[18]" - }, - { - "internalType": "bytes32", - "name": "otherHashFromBlockHash", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "v", - "type": "uint256" - } - ], - "internalType": "struct Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "gasPerBurnCall", - "type": "uint256" - } - ], - "name": "verifyBlock2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "nullifier", - "type": "bytes32" - } - ], - "name": "wasBurnSubstituted", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60808060405234620000bd577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c16620000ae57506001600160401b036002600160401b03198282160162000068575b604051613c269081620000c38239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a138808062000058565b63f92ee8a960e01b8152600490fd5b600080fdfe608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612d075750806309fe537d14612ce45780630aef023f14612ca55780631000b72914612b4057806316b5c12214612b225780631d49e45714612ae557806324ca984e14612a605780633139332e14610d6f5780633644e51514612a4557806338e454b1146129c55780633e413bee1461299c57806345873f3f14612671578063485ee1e4146126525780634fb4eee31461203657806353b935571461200957806354a0860614611f8957806354ace93314611b1257806354fd4d5014611af25780635a02369314611a4d5780635cd8a76b146119cd5780635ced058e146119a55780635eeba6dd146114795780636779b7c21461145b5780636ae0b1541461141a578063715018a6146113af57806382f15a3b146112815780638da5cb5b1461124b578063a10e57a8146111b2578063a2ce9c1f14611188578063a65ddebd1461115f578063a91eebf51461113c578063afbd8c39146110d8578063b506165814610dc7578063c072bd8814610d9e578063c1b1535914610d6f578063c3a716eb14610d46578063c832fe5f14610cc1578063cb32583314610a9e578063ceace3b814610808578063d9581277146107d9578063dab5f340146107b4578063e4408e461461074d578063e795594d14610481578063ef0feff914610290578063f22a195e14610272578063f2fde38b146102455763f44ff7121461022557600080fd5b346102425780600319360112610242576020600754604051908152f35b80fd5b50346102425760203660031901126102425761026f610262612d2c565b61026a612ea1565b612eda565b80f35b50346102425780600319360112610242576020600654604051908152f35b503461024257602090816003193601126102425790600435604d546102b58282613015565b916102bf83613051565b926102cd6040519485612e80565b8084526102dc601f1991613051565b01855b818110610454575050805b8281106103a55750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103275787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b808210610382575050509060019383808094015191015298019301930190928796959394929461031a565b82516001600160a01b031685528a95948501949092019160019190910190610357565b808694959652604c8652604084206001600281830192015490604051926103cb84612e49565b60405191828b83549182815201928a528b8a20918a915b8d818410610436575050505050918161040561042d969593610427950382612e80565b8252898201526104158584613015565b90610420828a613077565b5287613077565b50613068565b949392946102ea565b84546001600160a01b031686529094019392810192918101916103e2565b94808097959660405161046681612e49565b60608152878382015282828a010152019050959493956102df565b5034610242576040366003190112610242576004356001600160401b0360248035828111610749576104b7903690600401612db5565b92906104c1612ea1565b604d9384548015801561070f575b1561069b57600052604c916020928084528760026040600020015586546000526001948560406000200190841161068657600160401b8411610686578054848255808510610669575b50829060005284600020908660005b868110610650575050505060005b838110610593575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161057f57505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826105bf6105ba868a8a6130b6565b6130a2565b16600052875260ff60406000205416610611579061060c92916000528387526040600020906105f26105ba8489896130b6565b16600052865260406000208760ff19825416179055613068565b610535565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761065a846130a2565b93019281850155018790610527565b61068090826000528587600020918201910161308b565b38610518565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161073457600052604c60205286600260406000200154106104cf565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346102425760203660031901126102425760408181926020835161077181612e49565b82815201526004358152604b60205220815161078c81612e49565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b5034610242576020366003190112610242576107ce612ea1565b61026f600435612fd7565b50346102425760203660031901126102425760ff60406020926004358152605484522054166040519015158152f35b5034610242576040366003190112610242576004356024358183526020906053825260ff604085205416610a4e578284526054825260ff604085205416610a0b576005546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03918490829060649082908a9087165af18015610a00576109d3575b508385526053835260408520926001938460ff1982541617905560008490868152604f835285604082205480156000146109c35750505085600052604b82528460406000200154156109bb575b80806109ab575b867f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde86040805189815284151587820152a2816109a3575b501561096757604b90858752604f81528660408120556040519561093d87612e49565b33875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6064906040519062461bcd60e51b825260048201526015602482015274149bdb1b1d5c158d8e88109d5c9b8819985a5b1959605a1b6044820152fd5b90503861091a565b506109b684876137f4565b6108e3565b5060006108dc565b036109b657506109b684876138b5565b6109f290843d86116109f9575b6109ea8183612e80565b8101906133d9565b503861088f565b503d6109e0565b6040513d88823e3d90fd5b6064826040519062461bcd60e51b825280600483015260248201527f526f6c6c757056363a204c65616620616c726561647920726f6c6c65642075706044820152fd5b60405162461bcd60e51b815260048101839052602260248201527f526f6c6c757056363a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b50346102425760c036600319011261024257610ab8612d2c565b6001600160401b039190602435838111610cbd57610ada903690600401612d58565b6044359260643591610aeb826133f1565b6004546040516001600160a01b039890939189169160a0850191821185831017610ca757899160405216928381526020958787830152856040830152608435606083015260a4356080830152823b15610ca3579290918892610b66604051958694625a2d8360e11b865260c0600487015260c4860191613260565b908489602486015b60058310610c86575050505082809103915afa8015610a0057908691610c72575b505083600052604f83526040600020541580610c5e575b15610c235760018495967f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d495600052604f85526000604081205560405192610bed84612e49565b835284830190848252878952604b8652604089209351166001600160601b0360a01b84541617835551910155604051908152a280f35b60405162461bcd60e51b81526004810184905260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b835260016040600020015415610ba6565b610c7b90612e00565b610749578438610b8f565b835181528d975088965092810192600192909201918b9101610b6e565b8880fd5b634e487b7160e01b600052604160045260246000fd5b8280fd5b503461024257806003193601126102425760405190610cdf82612e64565b610800809236903760405190600881835b60408210610d305750505090610d0581612e64565b6040519190825b60408310610d1957505050f35b600190825181526020809101920192019190610d0c565b6001602081928554815201930191019091610cf0565b50346102425780600319360112610242576004546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760ff60406020926004358152605384522054166040519015158152f35b50346102425780600319360112610242576002546040516001600160a01b039091168152602090f35b5034610242576101c0366003190112610242576001600160401b03906004358281116110d457610dfb903690600401612d58565b602435916044359160643595610e0f612d42565b9060a4359260c4359260e43591888a52602096604a885260408b205461109957604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528b60408801528a60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e08201526101008781830152815261012081019281841090841117610ca757610efe8692610f07928a956040525190208c610ebd6131b9565b916040519182019261190160f01b84526022830152604282015260428152610ee481612e2e565b5190206101a43590610184359060ff610164351690613281565b90929192613311565b1603611063578a9b8360039c999a9b9c541660405191610f2683612de5565b8d83528c8c8401526040830152803b1561105f57610f5d938a9360405195869485938493635e65f68960e11b855260048501613396565b03915afa908115611054578791611040575b50506005541690813b1561103c5785936040519586946377aadf6360e11b865260048601523060248601528960448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561103157611019575b5091837fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd289352604a8252806040862055604051908152a280f35b61102290612e00565b61102d578338610fdf565b8380fd5b6040513d84823e3d90fd5b8580fd5b61104990612e00565b61103c578538610f6f565b6040513d89823e3d90fd5b8980fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346102425760c0366003190112610242573660231215610242576040516110ff81612e13565b8060c49136831161102d57602093506004905b83821061112d5784611123846130d7565b6040519015158152f35b81358152908401908401611112565b50346102425780600319360112610242576020611157613022565b604051908152f35b50346102425780600319360112610242576052546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760406020916004358152604a83522054604051908152f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611237575b611225576006908160ff198554161784556207a12060555568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160068152a180f35b60405163f92ee8a960e01b8152600490fd5b5060066001600160401b03821610156111e2565b5034610242578060031936011261024257600080516020613b91833981519152546040516001600160a01b039091168152602090f35b50346102425760e0366003190112610242576024356004356044356001600160401b03811161102d576112b8903690600401612d58565b90926064359385608435936112cd8615613527565b6001600160a01b03848116949093906112e5866133f1565b8460525416604051916112f783612e13565b898352602083015289604083015287606083015260a435608083015260c43560a0830152803b15610749576113459385936040519586948593849363e261a9cb60e01b855260048501613562565b03915afa801561103157611395575b5050906001602093926113887f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d496886134ac565b60405192610bed84612e49565b6113a29094939294612e00565b61103c5790918538611354565b50346102425780600319360112610242576113c8612ea1565b600080516020613b9183398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461024257602036600319011261024257611434612d2c565b61143c612ea1565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346102425780600319360112610242576020604854604051908152f35b50346102425761010036600319011261024257611494612d2c565b6024356001600160a01b03811681036119a057604435906001600160a01b03821682036119a057606435906001600160a01b03821682036119a0576114d7612d42565b60a43591906001600160a01b03831683036119a05760c4356001600160401b03811161199c5761150b903690600401612db5565b949095600080516020613bd183398151915254976001600160401b038916158061198e575b60016001600160401b038b16149081611984575b15908161197b575b506112255761159b9060016001600160401b03198b1617600080516020613bd18339815191525560ff8a60401c161561194e575b8a5460ff19166001178b55611593612fa8565b61026a612fa8565b6115a3612f69565b6020815191012061160e61161c6115b8612f8b565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f198101835282612e80565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611932575b156118bd57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b038211610ca757600160401b8211610ca757805482825580831061189f575b50829060005260206000209060005b8381106118845750505060005b8181106117bf57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116117a95760ff91604d5561175560e435612fd7565b60401c16156117615780f35b68ff000000000000000019600080516020613bd18339815191525416600080516020613bd183398151915255600080516020613bb1833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b036117e96105ba8487896130b6565b1660005260205260ff604060002054166118445761183f91600052604c602052604060002060018060a01b036118236105ba8487896130b6565b166000526020526040600020600160ff19825416179055613068565b6116fb565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b6001906020611892846130a2565b93019281850155016116ee565b6118b79082600052836020600020918201910161308b565b386116df565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116117a957600052604c6020526000611694565b68ffffffffffffffffff198a166801000000000000000117600080516020613bd183398151915255611580565b9050153861154c565b303b159150611544565b5060ff8960401c1615611530565b8780fd5b600080fd5b5034610242576020366003190112610242576040516004356001600160a01b03168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611a39575b611225576002908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160028152a180f35b5060026001600160401b03821610156119fd565b503461024257602036600319011261024257611a67612d2c565b600080516020613bd183398151915290815460ff8160401c168015611ade575b611225576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160058152a180f35b5060056001600160401b0382161015611a87565b503461024257806003193601126102425760ff6020915416604051908152f35b503461024257610140366003190112610242576044356001600160401b0381116110d457611b44903690600401612d58565b60e4359291906001600160a01b03841684036119a057610104356001600160401b03811161102d57611b7a903690600401612d58565b909461012435929091906001600160a01b03841684036119a057611ba2600160043514613527565b6001600160a01b03841615611f4b576001600160a01b038316865260516020908152604087205490959060ff1615611f0d57611bdd856133f1565b6040519186830160018060a01b038616815260606040850152611c2684611c098c886080840191613260565b6001600160a01b038a16606083015203601f198101865285612e80565b925190922060243592906001600160fd1b0316839003611eda5760018060a01b03605254169160405193611c5985612e13565b6004358552888501526064356040850152608435606085015260a435608085015260c43560a0850152823b15610ca35760405163e261a9cb60e01b81529389938593909284928392611cae9260048501613562565b03915afa8015610a0057908691611ec6575b5050611cd06004356064356134ac565b60405191611cdd83612e2e565b6001600160a01b03168252611cf181612f4e565b95611cff6040519788612e80565b818752368282011161103c578186928692838a01378701015282810194855260843560408083019182526001600160a01b03938416606084019081526064358752605086529086209251835494166001600160a01b03199485161783559551805190969392919060018301906001600160401b038111611eb257611d8382546135a5565b601f8111611e79575b5086601f8211600114611e13578190899a60039798999a92611e08575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b03905116908254161790557f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d460405191608435835260643592a280f35b015190503880611da9565b82895287892099601f1983168a5b818110611e6257509160039798999a9b91846001959410611e4a575b505050811b019055611dbd565b015160001983891b60f8161c19169055388080611e3d565b838301518d556001909c019b928a01928a01611e21565b611ea290838a52888a20601f840160051c8101918a8510611ea8575b601f0160051c019061308b565b38611d8c565b9091508190611e95565b634e487b7160e01b88526041600452602488fd5b611ecf90612e00565b610749578438611cc0565b60405162461bcd60e51b815260048101889052600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152600481018790526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611ff5575b611225576004908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160048152a180f35b5060046001600160401b0382161015611fb9565b50346102425760203660031901126102425760043560408110156110d45760209060080154604051908152f35b503461024257610480366003190112610242576001600160401b03906004358281116110d45761206a903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd57612097903690600401612d85565b92909133825260496020526120b2600160408420541461320a565b33825260496020526120ca600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561263257808452604c6020526104443560026040862001541161210f578061210a918755613068565b6120db565b509193949092945b548452604c602052604084209261212c613022565b926101a4359384036125dc57855b60128110612560575061218a60405161215281612e13565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a08201526130d7565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526121e781612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261222381612de5565b5190206040519061223382612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061249557505090612283926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b848210612373578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156110315761235f575b50506123206101c435612fd7565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b61236890612e00565b6110d4578183612312565b6123a290606083028c019061239960ff9260208101359084604082359201351688613281565b90949194613311565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576123d79091613068565b90612293565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b6020828201810151602888840101528694500161225c565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116125c8576125749061324d565b35600282018083116125b4579061258d6125949261324d565b35906135df565b600381018091111561213a57634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294612117565b634e487b7160e01b84526011600452602484fd5b50346102425760203660031901126102425760206111236004356131dc565b5034610242576104a0366003190112610242576001600160401b03906004358281116110d4576126a5903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd576126d2903690600401612d85565b92909133825260496020526126ed600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561299057808452604c60205261044435600260408620015411612732578061272d918755613068565b6126fe565b509193949092945b548452604c602052604084209261274f613022565b926101a4359384036125dc57855b60128110612943575061277560405161215281612e13565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526127d281612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261280e81612de5565b5190206040519061281e82612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061292b5750509061286e926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b8482106128ca578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b6128f090606083028c019061239960ff9260208101359084604082359201351688613281565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576129259091613068565b9061287e565b60208282018101516028888401015286945001612847565b600181018082116125c8576129579061324d565b35600282018083116125b4579061258d6129709261324d565b600381018091111561275d57634e487b7160e01b87526011600452602487fd5b5091939490929461273a565b50346102425780600319360112610242576005546040516001600160a01b039091168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015612a31575b611225576003908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160038152a180f35b5060036001600160401b03821610156129f5565b503461024257806003193601126102425760206111576131b9565b503461024257602036600319011261024257612a7a612d2c565b612a82612ea1565b803b15612aab576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b503461024257602036600319011261024257612aff612d2c565b612b07612ea1565b6001600160a01b031681526049602052604081206001905580f35b50346102425780600319360112610242576020605554604051908152f35b5034610242576080366003190112610242576004356001600160401b0381116110d457612b71903690600401612d58565b6024359160443591838552602091604a83526040862054611099576003546040516001600160a01b03938892851690612ba983612de5565b88835287878401526064356040840152813b1561102d57612be19460405195869485938493635e65f68960e11b855260048501613396565b03915afa8015610a0057612c92575b506005546040516323b872dd60e01b81523360048201523060248201526044810185905293918391859160649183918a91165af1928315612c87577fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd2893612c6a575b50838552604a8252806040862055604051908152a280f35b612c8090833d85116109f9576109ea8183612e80565b5038612c52565b6040513d87823e3d90fd5b612c9e90959195612e00565b9338612bf0565b50346102425760203660031901126102425760209060ff906040906001600160a01b03612cd0612d2c565b168152605184522054166040519015158152f35b503461024257602036600319011261024257612cfe612ea1565b60043560555580f35b9050346110d457816003193601126110d4576003546001600160a01b03168152602090f35b600435906001600160a01b03821682036119a057565b608435906001600160a01b03821682036119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602083818601950101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602080850194606085020101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a0576020808501948460051b0101116119a057565b606081019081106001600160401b03821117610ca757604052565b6001600160401b038111610ca757604052565b60c081019081106001600160401b03821117610ca757604052565b608081019081106001600160401b03821117610ca757604052565b604081019081106001600160401b03821117610ca757604052565b61080081019081106001600160401b03821117610ca757604052565b90601f801991011681019081106001600160401b03821117610ca757604052565b600080516020613b91833981519152546001600160a01b03163303612ec257565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612f3557600080516020613b9183398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b038111610ca757601f01601f191660200190565b60405190612f7682612e49565b60068252650526f6c6c75760d41b6020830152565b60405190612f9882612e49565b60018252603160f81b6020830152565b60ff600080516020613bd18339815191525460401c1615612fc557565b604051631afcd79f60e31b8152600490fd5b6048546040811015612fff57600801556048546001810181116117a957600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116117a957565b603f6048548061303e575b506040811015612fff576008015490565b6000198101915081116117a9573861302d565b6001600160401b038111610ca75760051b60200190565b60001981146117a95760010190565b8051821015612fff5760209160051b010190565b818110613096575050565b6000815560010161308b565b356001600160a01b03811681036119a05790565b9190811015612fff5760051b0190565b906006811015612fff5760051b0190565b6040908151916130e683612e13565b60009182845282602085015282828501528260608501528260808501528260a0850152825b6006811061314c57505050805b6006811061312857505050600190565b61313281846130c6565b51156131465761314190613068565b613118565b50905090565b835b838110613165575b5061316090613068565b61310b565b61316f82846130c6565b5181600801541480156131a7575b61318f5761318a90613068565b61314e565b508060016131a061316093886130c6565b5290613156565b506131b282846130c6565b511561317d565b6131c1612f69565b6020815191012061160e6131d66115b8612f8b565b51902090565b600052604f6020526040600020541560001461320557604b602052600160406000200154151590565b600190565b1561321157565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612fff5760051b6101e40190565b908060209392818452848401376000828201840152601f01601f1916010190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161330557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156132f95780516001600160a01b038116156132f057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60048110156133805780613323575050565b6001810361333d5760405163f645eedf60e01b8152600490fd5b6002810361335e5760405163fce698f760e01b815260048101839052602490fd5b6003146133685750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b939291906133ac91608086526080860191613260565b9260208091016000905b600382106133c45750505050565b828060019286518152019401910190926133b6565b908160209103126119a0575180151581036119a05790565b6133fa90613445565b61340057565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa9081156134a057600091613485575090565b61349d915060203d81116109f9576109ea8183612e80565b90565b6040513d6000823e3d90fd5b80600052604f6020526040600020541580613512575b156134d757600052604f602052604060002055565b60405162461bcd60e51b81526020600482015260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b602052600160406000200154156134c2565b1561352e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b939291906135789160e0865260e0860191613260565b9260208091016000905b600682106135905750505050565b82806001928651815201940191019092613582565b90600182811c921680156135d5575b60208310146135bf57565b634e487b7160e01b600052602260045260246000fd5b91607f16916135b4565b81156137a45760009181835260209260548452604092838220600160ff19825416179055604a85528382205480613720575083600192828152604f87528181205480156000146136dc5750828152604b8752838282200154156136d4575b8380957f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde89495916136c3575b505b8251918252151587820152a215613680575050565b60649250519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056363a204275726e20776173206e6f7420666f756e64000000006044820152fd5b6136ce9150856137f4565b38613669565b92508261363d565b94847f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde8949596146000146137195761371490856138b5565b61366b565b508061366b565b94939290940361376057908082857fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde959452604a845220549051908152a2565b815162461bcd60e51b815260048101849052601d60248201527f526f6c6c757056363a20496e76616c6964206d696e7420616d6f756e740000006044820152606490fd5b5050565b156137af57565b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056363a20496e76616c6964206275726e20616d6f756e740000006044820152606490fd5b600052604b60205260206040600020916040519261381184612e49565b60018060a01b0393600185835416928383520154938491015282156138ac576138799361384183602095146137a8565b6005541690600060405180968195829463a9059cbb60e01b84526004840160209093929193604081019460018060a01b031681520152565b03925af1908161388e575b5061320557600090565b6138a59060203d81116109f9576109ea8183612e80565b5038613884565b50505050600090565b60009081526020906050825260409081812082516138d281612e2e565b60018060a01b03808354168252600196878401928887518095889080548c6138f9826135a5565b808652958216918215613b09575050600114613acb575b5061391d92500385612e80565b878101938452600285015493613948838560038b860199898b520154169660608501978852146137a8565b6005548251895163095ea7b360e01b8082529187166001600160a01b03166004820152602481019590955293908a9082908716818b816044810103925af18015613ac157916139a8918b93613aa4575b5085845116905160555491613b29565b92604485806005541694511691898b519586948593845260048401528160248401525af18015613a9a57613a7d575b50156139e7575b50505050505090565b6139f381835116613445565b613a735760055491519251855163a9059cbb60e01b81529382166001600160a01b0316600485015260248401529193929185918591168184816044810103925af1918215613a69575050613a4b575b808080806139de565b81613a6192903d106109f9576109ea8183612e80565b503880613a42565b51903d90823e3d90fd5b5050509250505090565b613a9390883d8a116109f9576109ea8183612e80565b50386139d7565b87513d88823e3d90fd5b613aba90843d86116109f9576109ea8183612e80565b5038613998565b89513d8a823e3d90fd5b915050875284898089208c8a915b858310613af057505061391d935082010138613910565b80919294505483858b0101520191018a908c8893613ad9565b60ff19168582015261391d95151560051b85010192503891506139109050565b6001600160a01b038116600090815260516020526040812054909384939160ff1615613b895783809360208451940192f1903d15613b85573d90613b6c82612f4e565b91613b7a6040519384612e80565b825260203d92013e90565b5090565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212207f199a497c7371541cba4cc6b6833ea67be05c7152013473ca7aa5539e5e9a5264736f6c63430008140033", - "deployedBytecode": "0x608080604052600436101561001357600080fd5b600090813560e01c908162b0938d14612d075750806309fe537d14612ce45780630aef023f14612ca55780631000b72914612b4057806316b5c12214612b225780631d49e45714612ae557806324ca984e14612a605780633139332e14610d6f5780633644e51514612a4557806338e454b1146129c55780633e413bee1461299c57806345873f3f14612671578063485ee1e4146126525780634fb4eee31461203657806353b935571461200957806354a0860614611f8957806354ace93314611b1257806354fd4d5014611af25780635a02369314611a4d5780635cd8a76b146119cd5780635ced058e146119a55780635eeba6dd146114795780636779b7c21461145b5780636ae0b1541461141a578063715018a6146113af57806382f15a3b146112815780638da5cb5b1461124b578063a10e57a8146111b2578063a2ce9c1f14611188578063a65ddebd1461115f578063a91eebf51461113c578063afbd8c39146110d8578063b506165814610dc7578063c072bd8814610d9e578063c1b1535914610d6f578063c3a716eb14610d46578063c832fe5f14610cc1578063cb32583314610a9e578063ceace3b814610808578063d9581277146107d9578063dab5f340146107b4578063e4408e461461074d578063e795594d14610481578063ef0feff914610290578063f22a195e14610272578063f2fde38b146102455763f44ff7121461022557600080fd5b346102425780600319360112610242576020600754604051908152f35b80fd5b50346102425760203660031901126102425761026f610262612d2c565b61026a612ea1565b612eda565b80f35b50346102425780600319360112610242576020600654604051908152f35b503461024257602090816003193601126102425790600435604d546102b58282613015565b916102bf83613051565b926102cd6040519485612e80565b8084526102dc601f1991613051565b01855b818110610454575050805b8281106103a55750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103275787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b808210610382575050509060019383808094015191015298019301930190928796959394929461031a565b82516001600160a01b031685528a95948501949092019160019190910190610357565b808694959652604c8652604084206001600281830192015490604051926103cb84612e49565b60405191828b83549182815201928a528b8a20918a915b8d818410610436575050505050918161040561042d969593610427950382612e80565b8252898201526104158584613015565b90610420828a613077565b5287613077565b50613068565b949392946102ea565b84546001600160a01b031686529094019392810192918101916103e2565b94808097959660405161046681612e49565b60608152878382015282828a010152019050959493956102df565b5034610242576040366003190112610242576004356001600160401b0360248035828111610749576104b7903690600401612db5565b92906104c1612ea1565b604d9384548015801561070f575b1561069b57600052604c916020928084528760026040600020015586546000526001948560406000200190841161068657600160401b8411610686578054848255808510610669575b50829060005284600020908660005b868110610650575050505060005b838110610593575050505060407ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73291855496825191888352820152a1830180931161057f57505580f35b634e487b7160e01b60009081526011600452fd5b87546000818152838752604090206001600160a01b039190826105bf6105ba868a8a6130b6565b6130a2565b16600052875260ff60406000205416610611579061060c92916000528387526040600020906105f26105ba8489896130b6565b16600052865260406000208760ff19825416179055613068565b610535565b60405162461bcd60e51b8152600481018890526018818b01527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b8761065a846130a2565b93019281850155018790610527565b61068090826000528587600020918201910161308b565b38610518565b86634e487b7160e01b60005260416004526000fd5b60405162461bcd60e51b8152602060048201526041818701527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b50600019810181811161073457600052604c60205286600260406000200154106104cf565b85634e487b7160e01b60005260116004526000fd5b8480fd5b50346102425760203660031901126102425760408181926020835161077181612e49565b82815201526004358152604b60205220815161078c81612e49565b81546001600160a01b0316808252600190920154602091820190815283519283525190820152f35b5034610242576020366003190112610242576107ce612ea1565b61026f600435612fd7565b50346102425760203660031901126102425760ff60406020926004358152605484522054166040519015158152f35b5034610242576040366003190112610242576004356024358183526020906053825260ff604085205416610a4e578284526054825260ff604085205416610a0b576005546040516323b872dd60e01b8152336004820152306024820152604481018390526001600160a01b03918490829060649082908a9087165af18015610a00576109d3575b508385526053835260408520926001938460ff1982541617905560008490868152604f835285604082205480156000146109c35750505085600052604b82528460406000200154156109bb575b80806109ab575b867f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde86040805189815284151587820152a2816109a3575b501561096757604b90858752604f81528660408120556040519561093d87612e49565b33875281870194855287525260408520935184546001600160a01b03191691161783555191015580f35b6064906040519062461bcd60e51b825260048201526015602482015274149bdb1b1d5c158d8e88109d5c9b8819985a5b1959605a1b6044820152fd5b90503861091a565b506109b684876137f4565b6108e3565b5060006108dc565b036109b657506109b684876138b5565b6109f290843d86116109f9575b6109ea8183612e80565b8101906133d9565b503861088f565b503d6109e0565b6040513d88823e3d90fd5b6064826040519062461bcd60e51b825280600483015260248201527f526f6c6c757056363a204c65616620616c726561647920726f6c6c65642075706044820152fd5b60405162461bcd60e51b815260048101839052602260248201527f526f6c6c757056363a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b50346102425760c036600319011261024257610ab8612d2c565b6001600160401b039190602435838111610cbd57610ada903690600401612d58565b6044359260643591610aeb826133f1565b6004546040516001600160a01b039890939189169160a0850191821185831017610ca757899160405216928381526020958787830152856040830152608435606083015260a4356080830152823b15610ca3579290918892610b66604051958694625a2d8360e11b865260c0600487015260c4860191613260565b908489602486015b60058310610c86575050505082809103915afa8015610a0057908691610c72575b505083600052604f83526040600020541580610c5e575b15610c235760018495967f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d495600052604f85526000604081205560405192610bed84612e49565b835284830190848252878952604b8652604089209351166001600160601b0360a01b84541617835551910155604051908152a280f35b60405162461bcd60e51b81526004810184905260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b835260016040600020015415610ba6565b610c7b90612e00565b610749578438610b8f565b835181528d975088965092810192600192909201918b9101610b6e565b8880fd5b634e487b7160e01b600052604160045260246000fd5b8280fd5b503461024257806003193601126102425760405190610cdf82612e64565b610800809236903760405190600881835b60408210610d305750505090610d0581612e64565b6040519190825b60408310610d1957505050f35b600190825181526020809101920192019190610d0c565b6001602081928554815201930191019091610cf0565b50346102425780600319360112610242576004546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760ff60406020926004358152605384522054166040519015158152f35b50346102425780600319360112610242576002546040516001600160a01b039091168152602090f35b5034610242576101c0366003190112610242576001600160401b03906004358281116110d457610dfb903690600401612d58565b602435916044359160643595610e0f612d42565b9060a4359260c4359260e43591888a52602096604a885260408b205461109957604051948886017fc635e9b551a1a2bbfb4fa770e7a75f4bd6b213e8b5cd5e22ee395e8760d863c081528b60408801528a60608801528d608088015260018060a01b03809516968760a08201528960c08201528860e08201526101008781830152815261012081019281841090841117610ca757610efe8692610f07928a956040525190208c610ebd6131b9565b916040519182019261190160f01b84526022830152604282015260428152610ee481612e2e565b5190206101a43590610184359060ff610164351690613281565b90929192613311565b1603611063578a9b8360039c999a9b9c541660405191610f2683612de5565b8d83528c8c8401526040830152803b1561105f57610f5d938a9360405195869485938493635e65f68960e11b855260048501613396565b03915afa908115611054578791611040575b50506005541690813b1561103c5785936040519586946377aadf6360e11b865260048601523060248601528960448601526064850152608484015260a483015281836101049260ff84351660c484015261012493843560e485015261014435908401525af1801561103157611019575b5091837fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd289352604a8252806040862055604051908152a280f35b61102290612e00565b61102d578338610fdf565b8380fd5b6040513d84823e3d90fd5b8580fd5b61104990612e00565b61103c578538610f6f565b6040513d89823e3d90fd5b8980fd5b60405162461bcd60e51b815260048101899052600e60248201526d24b73b30b634b21039b4b3b732b960911b6044820152606490fd5b60405162461bcd60e51b81526020600482015260136024820152724d696e7420616c72656164792065786973747360681b6044820152606490fd5b5080fd5b50346102425760c0366003190112610242573660231215610242576040516110ff81612e13565b8060c49136831161102d57602093506004905b83821061112d5784611123846130d7565b6040519015158152f35b81358152908401908401611112565b50346102425780600319360112610242576020611157613022565b604051908152f35b50346102425780600319360112610242576052546040516001600160a01b039091168152602090f35b50346102425760203660031901126102425760406020916004358152604a83522054604051908152f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611237575b611225576006908160ff198554161784556207a12060555568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160068152a180f35b60405163f92ee8a960e01b8152600490fd5b5060066001600160401b03821610156111e2565b5034610242578060031936011261024257600080516020613b91833981519152546040516001600160a01b039091168152602090f35b50346102425760e0366003190112610242576024356004356044356001600160401b03811161102d576112b8903690600401612d58565b90926064359385608435936112cd8615613527565b6001600160a01b03848116949093906112e5866133f1565b8460525416604051916112f783612e13565b898352602083015289604083015287606083015260a435608083015260c43560a0830152803b15610749576113459385936040519586948593849363e261a9cb60e01b855260048501613562565b03915afa801561103157611395575b5050906001602093926113887f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d496886134ac565b60405192610bed84612e49565b6113a29094939294612e00565b61103c5790918538611354565b50346102425780600319360112610242576113c8612ea1565b600080516020613b9183398151915280546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b503461024257602036600319011261024257611434612d2c565b61143c612ea1565b6001600160a01b03168152605160205260408120805460ff1916905580f35b50346102425780600319360112610242576020604854604051908152f35b50346102425761010036600319011261024257611494612d2c565b6024356001600160a01b03811681036119a057604435906001600160a01b03821682036119a057606435906001600160a01b03821682036119a0576114d7612d42565b60a43591906001600160a01b03831683036119a05760c4356001600160401b03811161199c5761150b903690600401612db5565b949095600080516020613bd183398151915254976001600160401b038916158061198e575b60016001600160401b038b16149081611984575b15908161197b575b506112255761159b9060016001600160401b03198b1617600080516020613bd18339815191525560ff8a60401c161561194e575b8a5460ff19166001178b55611593612fa8565b61026a612fa8565b6115a3612f69565b6020815191012061160e61161c6115b8612f8b565b8051602091820120604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f9381019384529081019590955260608501524660808501523060a08501529291829060c0820190565b03601f198101835282612e80565b5190206001556001600160601b0360a01b9360018060a01b031684600554161760055560018060a01b031683600254161760025560018060a01b031682600354161760035560018060a01b031690600454161760045560018060a01b03168452604960205260016040852055604d5480158015611932575b156118bd57600052604c60205260006002604082200155604d5460005260016040600020016001600160401b038211610ca757600160401b8211610ca757805482825580831061189f575b50829060005260206000209060005b8381106118845750505060005b8181106117bf57505050604d54907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc7326040805184815260006020820152a1600182018092116117a95760ff91604d5561175560e435612fd7565b60401c16156117615780f35b68ff000000000000000019600080516020613bd18339815191525416600080516020613bd183398151915255600080516020613bb1833981519152602060405160018152a180f35b634e487b7160e01b600052601160045260246000fd5b604d546000818152604c602052604090209091906001600160a01b036117e96105ba8487896130b6565b1660005260205260ff604060002054166118445761183f91600052604c602052604060002060018060a01b036118236105ba8487896130b6565b166000526020526040600020600160ff19825416179055613068565b6116fb565b60405162461bcd60e51b815260206004820152601860248201527756616c696461746f7220616c72656164792065786973747360401b6044820152606490fd5b6001906020611892846130a2565b93019281850155016116ee565b6118b79082600052836020600020918201910161308b565b386116df565b60405162461bcd60e51b815260206004820152604160248201527f4e65772076616c696461746f7220736574206d7573742068617665206120766160448201527f6c696446726f6d2067726561746572207468616e20746865206c6173742073656064820152601d60fa1b608482015260a490fd5b5060001981018181116117a957600052604c6020526000611694565b68ffffffffffffffffff198a166801000000000000000117600080516020613bd183398151915255611580565b9050153861154c565b303b159150611544565b5060ff8960401c1615611530565b8780fd5b600080fd5b5034610242576020366003190112610242576040516004356001600160a01b03168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611a39575b611225576002908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160028152a180f35b5060026001600160401b03821610156119fd565b503461024257602036600319011261024257611a67612d2c565b600080516020613bd183398151915290815460ff8160401c168015611ade575b611225576005918260ff1986541617855560018060a01b03166001600160601b0360a01b605254161760525568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160058152a180f35b5060056001600160401b0382161015611a87565b503461024257806003193601126102425760ff6020915416604051908152f35b503461024257610140366003190112610242576044356001600160401b0381116110d457611b44903690600401612d58565b60e4359291906001600160a01b03841684036119a057610104356001600160401b03811161102d57611b7a903690600401612d58565b909461012435929091906001600160a01b03841684036119a057611ba2600160043514613527565b6001600160a01b03841615611f4b576001600160a01b038316865260516020908152604087205490959060ff1615611f0d57611bdd856133f1565b6040519186830160018060a01b038616815260606040850152611c2684611c098c886080840191613260565b6001600160a01b038a16606083015203601f198101865285612e80565b925190922060243592906001600160fd1b0316839003611eda5760018060a01b03605254169160405193611c5985612e13565b6004358552888501526064356040850152608435606085015260a435608085015260c43560a0850152823b15610ca35760405163e261a9cb60e01b81529389938593909284928392611cae9260048501613562565b03915afa8015610a0057908691611ec6575b5050611cd06004356064356134ac565b60405191611cdd83612e2e565b6001600160a01b03168252611cf181612f4e565b95611cff6040519788612e80565b818752368282011161103c578186928692838a01378701015282810194855260843560408083019182526001600160a01b03938416606084019081526064358752605086529086209251835494166001600160a01b03199485161783559551805190969392919060018301906001600160401b038111611eb257611d8382546135a5565b601f8111611e79575b5086601f8211600114611e13578190899a60039798999a92611e08575b50508160011b9160001990871b1c19161790555b516002820155019160018060a01b03905116908254161790557f692f937d805cd146b9f88bbe97476a1967f0eff2674a00bcd1810c62710a99d460405191608435835260643592a280f35b015190503880611da9565b82895287892099601f1983168a5b818110611e6257509160039798999a9b91846001959410611e4a575b505050811b019055611dbd565b015160001983891b60f8161c19169055388080611e3d565b838301518d556001909c019b928a01928a01611e21565b611ea290838a52888a20601f840160051c8101918a8510611ea8575b601f0160051c019061308b565b38611d8c565b9091508190611e95565b634e487b7160e01b88526041600452602488fd5b611ecf90612e00565b610749578438611cc0565b60405162461bcd60e51b815260048101889052600b60248201526a496e76616c6964206d736760a81b6044820152606490fd5b60405162461bcd60e51b8152600481018790526016602482015275149bdd5d195c881b9bdd081dda1a5d195b1a5cdd195960521b6044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642072657475726e206164647265737360501b6044820152606490fd5b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015611ff5575b611225576004908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160048152a180f35b5060046001600160401b0382161015611fb9565b50346102425760203660031901126102425760043560408110156110d45760209060080154604051908152f35b503461024257610480366003190112610242576001600160401b03906004358281116110d45761206a903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd57612097903690600401612d85565b92909133825260496020526120b2600160408420541461320a565b33825260496020526120ca600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561263257808452604c6020526104443560026040862001541161210f578061210a918755613068565b6120db565b509193949092945b548452604c602052604084209261212c613022565b926101a4359384036125dc57855b60128110612560575061218a60405161215281612e13565b6101e43581526102443560208201526102a43560408201526103043560608201526103643560808201526103c43560a08201526130d7565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526121e781612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261222381612de5565b5190206040519061223382612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061249557505090612283926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b848210612373578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b906101806024808501376101a48301526101c4356101c48301526102406101e48084013703915afa80156110315761235f575b50506123206101c435612fd7565b600655610444356007556040516101c43581527f68b82650828a9621868d09dc161400acbe189fa002e3fb7cf9dea5c2c6f928ee60206104443592a280f35b61236890612e00565b6110d4578183612312565b6123a290606083028c019061239960ff9260208101359084604082359201351688613281565b90949194613311565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576123d79091613068565b90612293565b60405162461bcd60e51b815260206004820152601660248201527514da59db995c9cc8185c99481b9bdd081cdbdc9d195960521b6044820152606490fd5b60405162461bcd60e51b815260206004820152601960248201527f5369676e6572206973206e6f7420612076616c696461746f72000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152600d60248201526c4e6f207369676e61747572657360981b6044820152606490fd5b6020828201810151602888840101528694500161225c565b634e487b7160e01b87526011600452602487fd5b60405162461bcd60e51b815260206004820152603560248201527f4e6f7420656e6f756768207369676e6174757265732066726f6d2076616c696460448201527461746f727320746f2076657269667920626c6f636b60581b6064820152608490fd5b60405162461bcd60e51b8152602060048201526014602482015273496e76616c696420726563656e7420726f6f747360601b6044820152606490fd5b600181018082116125c8576125749061324d565b35600282018083116125b4579061258d6125949261324d565b35906135df565b600381018091111561213a57634e487b7160e01b87526011600452602487fd5b634e487b7160e01b89526011600452602489fd5b634e487b7160e01b88526011600452602488fd5b60405162461bcd60e51b815260206004820152602860248201527f4f6c6420726f6f7420646f6573206e6f74206d61746368207468652063757272604482015267195b9d081c9bdbdd60c21b6064820152608490fd5b50919394909294612117565b634e487b7160e01b84526011600452602484fd5b50346102425760203660031901126102425760206111236004356131dc565b5034610242576104a0366003190112610242576001600160401b03906004358281116110d4576126a5903690600401612d58565b9092366101a411610cbd573661042411610cbd5761046435908111610cbd576126d2903690600401612d85565b92909133825260496020526126ed600160408420541461320a565b604e9384546001810180911161263e575b604d5481101561299057808452604c60205261044435600260408620015411612732578061272d918755613068565b6126fe565b509193949092945b548452604c602052604084209261274f613022565b926101a4359384036125dc57855b60128110612943575061277560405161215281612e13565b156125245760018501548060011b90808204600214901517156124ad5760039004600181018091116124ad5781106124c1576040516101c4356020820152610444356040820152610424356060820152606081526127d281612e2e565b60208151910120946001610444350161044435116124ad5760405160208101906001610444350182528760408201526040815261280e81612de5565b5190206040519061281e82612e49565b6008825267506f6c796261736560c01b60208301526040518092600160c31b60208301528051908b5b82811061292b5750509061286e926048928201906028820152036028810184520182612e80565b6020815191012082156124605787805b8482106128ca578989818a8a8a60018060a01b0360025416803b156107495784926122df9260405195869485938493633b07787160e21b85526104206004860152610424850191613260565b6128f090606083028c019061239960ff9260208101359084604082359201351688613281565b60018060a01b039060018285169384600052886020526040600020541615150361241b571610156123dd576129259091613068565b9061287e565b60208282018101516028888401015286945001612847565b600181018082116125c8576129579061324d565b35600282018083116125b4579061258d6129709261324d565b600381018091111561275d57634e487b7160e01b87526011600452602487fd5b5091939490929461273a565b50346102425780600319360112610242576005546040516001600160a01b039091168152602090f35b5034610242578060031936011261024257600080516020613bd1833981519152805460ff8160401c168015612a31575b611225576003908160ff1985541617845568ffffffffffffffffff1916179055600080516020613bb1833981519152602060405160038152a180f35b5060036001600160401b03821610156129f5565b503461024257806003193601126102425760206111576131b9565b503461024257602036600319011261024257612a7a612d2c565b612a82612ea1565b803b15612aab576001600160a01b03168152605160205260408120805460ff1916600117905580f35b60405162461bcd60e51b8152602060048201526012602482015271526f7574657220686173206e6f20636f646560701b6044820152606490fd5b503461024257602036600319011261024257612aff612d2c565b612b07612ea1565b6001600160a01b031681526049602052604081206001905580f35b50346102425780600319360112610242576020605554604051908152f35b5034610242576080366003190112610242576004356001600160401b0381116110d457612b71903690600401612d58565b6024359160443591838552602091604a83526040862054611099576003546040516001600160a01b03938892851690612ba983612de5565b88835287878401526064356040840152813b1561102d57612be19460405195869485938493635e65f68960e11b855260048501613396565b03915afa8015610a0057612c92575b506005546040516323b872dd60e01b81523360048201523060248201526044810185905293918391859160649183918a91165af1928315612c87577fcf80b092b21d743e1302ae84a7796d12b75cb47ef6b3a19ff386eadfdcb3fd2893612c6a575b50838552604a8252806040862055604051908152a280f35b612c8090833d85116109f9576109ea8183612e80565b5038612c52565b6040513d87823e3d90fd5b612c9e90959195612e00565b9338612bf0565b50346102425760203660031901126102425760209060ff906040906001600160a01b03612cd0612d2c565b168152605184522054166040519015158152f35b503461024257602036600319011261024257612cfe612ea1565b60043560555580f35b9050346110d457816003193601126110d4576003546001600160a01b03168152602090f35b600435906001600160a01b03821682036119a057565b608435906001600160a01b03821682036119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602083818601950101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a057602080850194606085020101116119a057565b9181601f840112156119a0578235916001600160401b0383116119a0576020808501948460051b0101116119a057565b606081019081106001600160401b03821117610ca757604052565b6001600160401b038111610ca757604052565b60c081019081106001600160401b03821117610ca757604052565b608081019081106001600160401b03821117610ca757604052565b604081019081106001600160401b03821117610ca757604052565b61080081019081106001600160401b03821117610ca757604052565b90601f801991011681019081106001600160401b03821117610ca757604052565b600080516020613b91833981519152546001600160a01b03163303612ec257565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b03908116908115612f3557600080516020613b9183398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b6001600160401b038111610ca757601f01601f191660200190565b60405190612f7682612e49565b60068252650526f6c6c75760d41b6020830152565b60405190612f9882612e49565b60018252603160f81b6020830152565b60ff600080516020613bd18339815191525460401c1615612fc557565b604051631afcd79f60e31b8152600490fd5b6048546040811015612fff57600801556048546001810181116117a957600160409108604855565b634e487b7160e01b600052603260045260246000fd5b919082039182116117a957565b603f6048548061303e575b506040811015612fff576008015490565b6000198101915081116117a9573861302d565b6001600160401b038111610ca75760051b60200190565b60001981146117a95760010190565b8051821015612fff5760209160051b010190565b818110613096575050565b6000815560010161308b565b356001600160a01b03811681036119a05790565b9190811015612fff5760051b0190565b906006811015612fff5760051b0190565b6040908151916130e683612e13565b60009182845282602085015282828501528260608501528260808501528260a0850152825b6006811061314c57505050805b6006811061312857505050600190565b61313281846130c6565b51156131465761314190613068565b613118565b50905090565b835b838110613165575b5061316090613068565b61310b565b61316f82846130c6565b5181600801541480156131a7575b61318f5761318a90613068565b61314e565b508060016131a061316093886130c6565b5290613156565b506131b282846130c6565b511561317d565b6131c1612f69565b6020815191012061160e6131d66115b8612f8b565b51902090565b600052604f6020526040600020541560001461320557604b602052600160406000200154151590565b600190565b1561321157565b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b6012811015612fff5760051b6101e40190565b908060209392818452848401376000828201840152601f01601f1916010190565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841161330557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa156132f95780516001600160a01b038116156132f057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b60048110156133805780613323575050565b6001810361333d5760405163f645eedf60e01b8152600490fd5b6002810361335e5760405163fce698f760e01b815260048101839052602490fd5b6003146133685750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b939291906133ac91608086526080860191613260565b9260208091016000905b600382106133c45750505050565b828060019286518152019401910190926133b6565b908160209103126119a0575180151581036119a05790565b6133fa90613445565b61340057565b60405162461bcd60e51b815260206004820152601e60248201527f6163636f756e7420697320626c61636b6c6973746564206279205553444300006044820152606490fd5b60055460405163fe575a8760e01b81526001600160a01b0392831660048201529160209183916024918391165afa9081156134a057600091613485575090565b61349d915060203d81116109f9576109ea8183612e80565b90565b6040513d6000823e3d90fd5b80600052604f6020526040600020541580613512575b156134d757600052604f602052604060002055565b60405162461bcd60e51b81526020600482015260136024820152724275726e20616c72656164792065786973747360681b6044820152606490fd5b50604b602052600160406000200154156134c2565b1561352e57565b60405162461bcd60e51b815260206004820152600c60248201526b125b9d985b1a59081ada5b9960a21b6044820152606490fd5b939291906135789160e0865260e0860191613260565b9260208091016000905b600682106135905750505050565b82806001928651815201940191019092613582565b90600182811c921680156135d5575b60208310146135bf57565b634e487b7160e01b600052602260045260246000fd5b91607f16916135b4565b81156137a45760009181835260209260548452604092838220600160ff19825416179055604a85528382205480613720575083600192828152604f87528181205480156000146136dc5750828152604b8752838282200154156136d4575b8380957f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde89495916136c3575b505b8251918252151587820152a215613680575050565b60649250519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056363a204275726e20776173206e6f7420666f756e64000000006044820152fd5b6136ce9150856137f4565b38613669565b92508261363d565b94847f96813a8b234bbe2be894787f4e2d871140bfdf50accf5b29ac94862620e5fde8949596146000146137195761371490856138b5565b61366b565b508061366b565b94939290940361376057908082857fe5889382823e45da32d98d9b770d082563fc781d4ad6652bd2739d2494efacde959452604a845220549051908152a2565b815162461bcd60e51b815260048101849052601d60248201527f526f6c6c757056363a20496e76616c6964206d696e7420616d6f756e740000006044820152606490fd5b5050565b156137af57565b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056363a20496e76616c6964206275726e20616d6f756e740000006044820152606490fd5b600052604b60205260206040600020916040519261381184612e49565b60018060a01b0393600185835416928383520154938491015282156138ac576138799361384183602095146137a8565b6005541690600060405180968195829463a9059cbb60e01b84526004840160209093929193604081019460018060a01b031681520152565b03925af1908161388e575b5061320557600090565b6138a59060203d81116109f9576109ea8183612e80565b5038613884565b50505050600090565b60009081526020906050825260409081812082516138d281612e2e565b60018060a01b03808354168252600196878401928887518095889080548c6138f9826135a5565b808652958216918215613b09575050600114613acb575b5061391d92500385612e80565b878101938452600285015493613948838560038b860199898b520154169660608501978852146137a8565b6005548251895163095ea7b360e01b8082529187166001600160a01b03166004820152602481019590955293908a9082908716818b816044810103925af18015613ac157916139a8918b93613aa4575b5085845116905160555491613b29565b92604485806005541694511691898b519586948593845260048401528160248401525af18015613a9a57613a7d575b50156139e7575b50505050505090565b6139f381835116613445565b613a735760055491519251855163a9059cbb60e01b81529382166001600160a01b0316600485015260248401529193929185918591168184816044810103925af1918215613a69575050613a4b575b808080806139de565b81613a6192903d106109f9576109ea8183612e80565b503880613a42565b51903d90823e3d90fd5b5050509250505090565b613a9390883d8a116109f9576109ea8183612e80565b50386139d7565b87513d88823e3d90fd5b613aba90843d86116109f9576109ea8183612e80565b5038613998565b89513d8a823e3d90fd5b915050875284898089208c8a915b858310613af057505061391d935082010138613910565b80919294505483858b0101520191018a908c8893613ad9565b60ff19168582015261391d95151560051b85010192503891506139109050565b6001600160a01b038116600090815260516020526040812054909384939160ff1615613b895783809360208451940192f1903d15613b85573d90613b6c82612f4e565b91613b7a6040519384612e80565b825260203d92013e90565b5090565b505050509056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300c7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a26469706673582212207f199a497c7371541cba4cc6b6833ea67be05c7152013473ca7aa5539e5e9a5264736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/eth/artifacts/contracts/rollup/RollupV6.sol/artifacts.d.ts b/eth/artifacts/contracts/rollup/RollupV6.sol/artifacts.d.ts deleted file mode 100644 index b1e4a32..0000000 --- a/eth/artifacts/contracts/rollup/RollupV6.sol/artifacts.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -// This file was autogenerated by hardhat-viem, do not edit it. -// prettier-ignore -// tslint:disable -// eslint-disable - -import "hardhat/types/artifacts"; - -import { RollupV6$Type } from "./RollupV6"; - -declare module "hardhat/types/artifacts" { - interface ArtifactsMap { - ["RollupV6"]: RollupV6$Type; - ["contracts/rollup/RollupV6.sol:RollupV6"]: RollupV6$Type; - } -} diff --git a/eth/artifacts/contracts/rollup3/RollupV1.sol/RollupV1.d.ts b/eth/artifacts/contracts/rollup3/RollupV1.sol/RollupV1.d.ts new file mode 100644 index 0000000..4f43d38 --- /dev/null +++ b/eth/artifacts/contracts/rollup3/RollupV1.sol/RollupV1.d.ts @@ -0,0 +1,1216 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import type { Address } from "viem"; +import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; +import "@nomicfoundation/hardhat-viem/types"; + +export interface RollupV1$Type { + "_format": "hh-sol-artifact-1", + "contractName": "RollupV1", + "sourceName": "contracts/rollup3/RollupV1.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "burn_hash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "substitute", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "MintAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "ProverAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "ProverRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "name": "RollupVerified", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "oldRoot", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + } + ], + "name": "RootHashUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + } + ], + "name": "ValidatorSetAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "verificationKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "zkVerifierAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "messages_length", + "type": "uint32" + } + ], + "name": "VerifierAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "verificationKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "zkVerifierAddress", + "type": "address" + } + ], + "name": "VerifierRemoved", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnSubstitutor", + "type": "address" + } + ], + "name": "addBurnSubstitutor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "addProver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "noteKind", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "addToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "messages_length", + "type": "uint32" + } + ], + "name": "addZkVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "blockHeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentRootHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "otherHashFromBlockHash", + "type": "bytes32" + } + ], + "name": "debugGetIntermediateHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "proposalHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "acceptMsg", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigMsg", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "acceptMsg", + "type": "bytes32" + } + ], + "name": "debugGetPackedBytes", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "otherHashFromBlockHash", + "type": "bytes32" + } + ], + "name": "debugGetSignatureMessageHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getMint", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "internalType": "struct Mint", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "from", + "type": "uint256" + } + ], + "name": "getValidatorSets", + "outputs": [ + { + "components": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + } + ], + "internalType": "struct PublicValidatorSet[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + } + ], + "name": "getZkVerifier", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_usdcAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_verifierAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "prover", + "type": "address" + }, + { + "internalType": "address[]", + "name": "initialValidators", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "verifierKeyHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "verifierMessagesCount", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "initialNoteKind", + "type": "bytes32" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "v", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "v2", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "r2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s2", + "type": "bytes32" + } + ], + "name": "mintWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "mints", + "outputs": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "noteKind", + "type": "bytes32" + } + ], + "name": "noteKindTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnSubstitutor", + "type": "address" + } + ], + "name": "removeBurnSubstitutor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "removeProver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + } + ], + "name": "removeZkVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rootHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + } + ], + "name": "setRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "setValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "burnBlockHeight", + "type": "uint256" + } + ], + "name": "substituteBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "substitutedBurns", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usdc", + "outputs": [ + { + "internalType": "contract IUSDC", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "aggrProof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "publicInputs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "otherHashFromBlockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "v", + "type": "uint256" + } + ], + "internalType": "struct Signature[]", + "name": "signatures", + "type": "tuple[]" + } + ], + "name": "verifyRollup", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burn_address", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "wasBurnSubstituted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "zkVerifierKeys", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "zkVerifiers", + "outputs": [ + { + "internalType": "contract IVerifier", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "messages_length", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x608080604052346100b9577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c166100aa57506001600160401b036002600160401b031982821601610065575b6040516131be9081620000bf8239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1388080610055565b63f92ee8a960e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c80630d647a9a1461242857806316fc1d4b146123db5780631d49e457146123795780631d80009a14611866578063220b01c614611e1a57806326e31a9414611c9c5780632a2bc73a14611c695780633644e51514611c4e5780633e413bee14611c255780634eeb381e14611b4b57806354fd4d5014611b2b57806356dc63cb14611ae45780635d5fa0d114611a8a5780636b2bd2ec14611a51578063715018a6146119e75780638da5cb5b146119b15780639776aacf14611903578063a2ce9c1f14611884578063a91eebf514611866578063ab1c290114611631578063b2142b50146115f0578063b571d3dd14611536578063b72e88cb146114f2578063b8cdbd2714610db5578063bb254e7a14610d93578063c1b1535914610d60578063c34975bb14610d10578063d82cbdd914610bb0578063dab5f34014610b65578063e795594d146107e1578063eae4475a146104bd578063ef0feff9146102c2578063f2fde38b14610295578063f44ff712146102775763f9038cf31461019e57600080fd5b34610274576101d66101af3661257d565b60409392919351928391856020840194856040919493926060820195825260208201520152565b03916101ea601f19938481018352826127eb565b51902091600181018091116102605760609350604051602081019182528360408201526040815261021a8161277f565b51902090610226613006565b9061024a604051918261023e86602083019687613026565b039081018352826127eb565b5190209060405192835260208301526040820152f35b634e487b7160e01b84526011600452602484fd5b80fd5b50346102745780600319360112610274576020600454604051908152f35b5034610274576020366003190112610274576102bf6102b26124b9565b6102ba612597565b6125d0565b80f35b503461027457602090816003193601126102745790600435600a546102e78282612772565b916102f1836130ce565b926102ff60405194856127eb565b80845261030e601f19916130ce565b01855b818110610490575050805b8281106103d75750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103595787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b8082106103b4575050509060019383808094015191015298019301930190928796959394929461034c565b82516001600160a01b031685528a95948501949092019160019190910190610389565b6103e481969495966130e5565b5060018091019060026103f6846130e5565b50015490604051926104078461279a565b60405191828b83549182815201928a528b8a20918a915b8d81841061047257505050505091816104416104699695936104639503826127eb565b8252898201526104518584612772565b9061045c828a613120565b5287613120565b5061274d565b9493929461031c565b84546001600160a01b0316865290940193928101929181019161041e565b9480809795966040516104a28161279a565b60608152878382015282828a01015201905095949395610311565b5034610274576101a0366003190112610274576004356024356044356104e16124ea565b60843560a4359160c4359086885260209360068552600160408a20015461079c5760405192858401927fc749520baeb387dcc1f93bdea47980df7e7750f05367ca40ad8204ffaded32ad845289604086015288606086015287608086015260018060a01b03809116938460a08701528660c08701528360e0870152610100838188015286526101208601956001600160401b039681811088821117610788576105db879385936105e49360405251902061059961280c565b90604051908d82019261190160f01b845260228301526042820152604281526105c1816127b5565b5190206101843590610164359060ff610144351690612ef1565b90929192612f81565b160361074357908a9392918885526008885260408520541691610608831515612d77565b823b1561073f576040519687946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015260ff60e4351660c4830152818361010492833560e4840152610124938435908401525af18015610734576106ec575b5050916040917fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1936106e084516106a48161277f565b8381526002838201868152878301908b82528a8c5260068652888c209351845551600184015551151591019060ff801983541691151516179055565b8351928352820152a280f35b81969296116107205760405293817fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f161066e565b634e487b7160e01b82526041600452602482fd5b6040513d89823e3d90fd5b8480fd5b60405162461bcd60e51b815260048101889052601860248201527f526f6c6c757056313a20496e76616c6964207369676e657200000000000000006044820152606490fd5b634e487b7160e01b8e52604160045260248efd5b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056313a204d696e7420616c7265616479206578697374730000006044820152606490fd5b50346102745760403660031901126102745760246004356001600160401b03823581811161073f57610817903690600401612500565b610822949194612597565b600a549485158015610b43575b15610ac55784158015610a9c575b15610a3257600160401b90818710156109f95760019182880180600a55610863896130e5565b50508811610a1f578660026108778a6130e5565b50015582610884896130e5565b5001958411610a0c5783116109f95784548386558084106109d1575b508094885260209485892090838a5b8681106109b85750505050875b8381106108f657887ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73260408a8a8a8351928352820152a180f35b6108ff886130e5565b506001600160a01b03908161091d6109188589886128d9565b613134565b168b52875260ff60408b20541661096957906109649161093c8a6130e5565b509061094c6109188489886128d9565b168b52875260408a20805460ff19168517905561274d565b6108bc565b60405162461bcd60e51b8152600481018890526022818801527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b886109c284613134565b930192818501550184906108af565b858952828460208b2092830192015b8281106109ee5750506108a0565b8a81550183906109e0565b634e487b7160e01b885260416004528388fd5b634e487b7160e01b895260416004528489fd5b634e487b7160e01b895260116004528489fd5b60405162461bcd60e51b815260206004820152603d818501527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b5062278d004301804311610ab25785111561083d565b634e487b7160e01b885260116004528388fd5b60405162461bcd60e51b815260206004820152604b818501527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b506000198601868111610ab2576002610b5c87926130e5565b5001541061082f565b503461027457602036600319011261027457600435610b82612597565b600554816005557f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488380a380f35b503461027457606036600319011261027457600435610bcd6124d4565b906044359063ffffffff821680830361073f57610be8612597565b6001600160a01b0384168015610cbd57843b15610c6857610c466060947fdb2a4be964bb3f5ba0504bccdbceaa478be8d73af2238cd9be0ba0c8efc107ca96858952600160205260ff60408a205460c01c1615610c5a575b856126af565b60405192835260208301526040820152a180f35b610c6386612644565b610c40565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a205a4b207665726966696572206973206e6f74206120636044820152661bdb9d1c9858dd60ca1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207a6b207665726966696572206164604482015264647265737360d81b6064820152608490fd5b503461027457602036600319011261027457604060609160043581526001602052205460ff6040519160018060a01b038116835263ffffffff8160a01c16602084015260c01c1615156040820152f35b503461027457602036600319011261027457602090600435815260078252604060018060a01b0391205416604051908152f35b5034610274576020610dad610da73661257d565b91613051565b604051908152f35b50346102745760c0366003190112610274576001600160401b0380604435116114ee573660236044350112156114ee578060443560040135116114ee57366024604435600401356044350101116114ee576064358181116114e657610e1e903690600401612500565b918060a435116114ea5736602360a4350112156114ea5760a43560040135116114e657366024606060a435600401350260a4350101116114e657338352600960205260016040842054036114aa576024358352600160205260ff604084205460c01c161561145b5760243583526001602052600363ffffffff604085205460a01c160163ffffffff81116102605763ffffffff1682036114085781156113f45781600110156113f45781600210156113f45760055481350361139f57600b54600181018111610260576001015b600a5481101561139857610efe816130e5565b50600260043591015411610f1e5780610f1991600b5561274d565b610eeb565b50905b610f2c600b546130e5565b5060a43560040135156113535760018101548060011b90808204600214901517156111d45760039004600181018091116111d45760a43560040135106112e857610f7f6084356004356020860135613051565b9084805b60a4356004013582106111e857505050506024358352600160205263ffffffff604084205460a01c1660039081018082116111d457905b82848383106111c65786916024358352600160205260018060a01b036040842054169060405191633a94343960e21b835260406004840152604435600401356044840152604435600401356024604435016064850137600460443501358381016064908101879052601f909101601f191684018481036060016024860152908101839052906001600160fb1b0383116111c25783608481809460209660051b90818a85830137010301915afa9081156111b7578391611188575b501561113457602081013560055560045460043511156110c957600435600455602060405191013581527f401f796450733fd22827ddc018ca37051459a8035c4026f533c294797bb8a49e602060043592a280f35b60405162461bcd60e51b815260206004820152603760248201527f526f6c6c757056313a204e657720626c6f636b20686569676874206d7573742060448201527f62652067726561746572207468616e2063757272656e740000000000000000006064820152608490fd5b60405162461bcd60e51b815260206004820152602660248201527f526f6c6c757056313a205a4b2070726f6f6620766572696669636174696f6e2060448201526519985a5b195960d21b6064820152608490fd5b6111aa915060203d6020116111b0575b6111a281836127eb565b8101906128e9565b83611074565b503d611198565b6040513d85823e3d90fd5b8580fd5b6111cf92612901565b610fba565b634e487b7160e01b85526011600452602485fd5b611219906112106060840260a4350160448101359060ff606460248301359201351688612ef1565b90939193612f81565b60018060a01b0380831691828a5285602052600160ff60408c205416151503611297571610156112535761124d909161274d565b90610f83565b606460405162461bcd60e51b815260206004820152602060248201527f526f6c6c757056313a205369676e65727320617265206e6f7420736f727465646044820152fd5b60405162461bcd60e51b815260206004820152602360248201527f526f6c6c757056313a205369676e6572206973206e6f7420612076616c6964616044820152623a37b960e91b6064820152608490fd5b60405162461bcd60e51b815260206004820152603f60248201527f526f6c6c757056313a204e6f7420656e6f756768207369676e6174757265732060448201527f66726f6d2076616c696461746f727320746f2076657269667920626c6f636b006064820152608490fd5b60405162461bcd60e51b815260206004820152601760248201527f526f6c6c757056313a204e6f207369676e6174757265730000000000000000006044820152606490fd5b5090610f21565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20526f6f74206861736820766572696669636174696f6e6044820152660819985a5b195960ca1b6064820152608490fd5b634e487b7160e01b83526032600452602483fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207075626c6963496e70757473206c6044820152640cadccee8d60db1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f526f6c6c757056313a205a4b207665726966696572206e6f7420616c6c6f77656044820152601960fa1b6064820152608490fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b8380fd5b5080fd5b50346102745760203660031901126102745761150c6124b9565b611514612597565b6001600160a01b03168152600c60205260408120805460ff1916600117905580f35b5034610274576020366003190112610274576115506124b9565b611558612597565b6001600160a01b031680825260096020526040822054600019016115ab5780825260096020528160408120557fd64d11086d859b73cf85a91ca06cbc484398acabe3d9a1b26d4366dff377d9858280a280f35b60405162461bcd60e51b815260206004820152601760248201527f41646472657373206973206e6f7420612070726f7665720000000000000000006044820152606490fd5b50346102745760203660031901126102745761160a6124b9565b611612612597565b6001600160a01b03168152600c60205260408120805460ff1916905580f35b50346102745760a03660031901126102745761164b6124b9565b6024356044359160643591338552602093600c8552600160ff6040882054161515036118105761167d84838584612c27565b80875260078652604087205490946001600160a01b0393909184166117c057608435600454101561176a578752600886527f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b0760406116f985828b205416936116e6851515612d77565b6116f281303388612dd3565b8785612cf4565b9481519560018752159687158a8801521694a461172d578252600790526040812080546001600160a01b0319163317905580f35b60405162461bcd60e51b8152600481018390526015602482015274149bdb1b1d5c158c4e88109d5c9b8819985a5b1959605a1b6044820152606490fd5b60405162461bcd60e51b815260048101889052602860248201527f526f6c6c757056313a20426c6f636b2068656967687420616c7265616479207260448201526706f6c6c65642075760c41b6064820152608490fd5b60405162461bcd60e51b815260048101889052602260248201527f526f6c6c757056313a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b60405162461bcd60e51b815260048101869052602860248201527f526f6c6c757056313a20596f7520617265206e6f742061206275726e2073756260448201526739ba34ba3aba37b960c11b6064820152608490fd5b50346102745780600319360112610274576020600554604051908152f35b5034610274576020366003190112610274576040816060928280516118a88161277f565b828152826020820152015260043581526006602052206040516118ca8161277f565b815491828252604060ff600260018401549360208601948552015416920191151582526040519283525160208301525115156040820152f35b5034610274576040366003190112610274576004356119206124d4565b90611929612597565b808352600860205260408320546001600160a01b039190821661196c57835260086020526040832091166bffffffffffffffffffffffff60a01b82541617905580f35b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20546f6b656e20616c72656164792065786973747300006044820152606490fd5b5034610274578060031936011261027457600080516020613149833981519152546040516001600160a01b039091168152602090f35b5034610274578060031936011261027457611a00612597565b60008051602061314983398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346102745760203660031901126102745760043590600254821015610274576020611a7c83612530565b90546040519160031b1c8152f35b503461027457602036600319011261027457604080916004358082526001602052611abd60ff8484205460c01c166126f5565b81526001602052205463ffffffff82519160018060a01b038116835260a01c166020820152f35b5034610274576020366003190112610274576040606091600435815260066020522080549060ff600260018301549201541690604051928352602083015215156040820152f35b503461027457806003193601126102745760ff6020915416604051908152f35b5034610274576060366003190112610274576004356024356044358284526006602052600160408520015461079c577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1918160409286526008602052611bcb8260018060a01b038589205416611bc2811515612d77565b30903390612dd3565b611c178351611bd98161277f565b828152600260208201858152868301908a8252898b526006602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346102745780600319360112610274576003546040516001600160a01b039091168152602090f35b50346102745780600319360112610274576020610dad61280c565b503461027457602036600319011261027457602090600435815260088252604060018060a01b0391205416604051908152f35b503461027457602036600319011261027457600435611cb9612597565b8082526001602052611cd460ff604084205460c01c166126f5565b8082526001602052604082208054908390556002805492916001600160a01b031690845b848110611d34575b857fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d6040868682519182526020820152a180f35b83611d3e82612530565b919054600392831b1c14611d5b5750611d569061274d565b611cf8565b9293949060001991828101908111611e0657611d88611d7c611d9f92612530565b905490871b1c92612530565b819391549060031b91821b91600019901b19161790565b905581548015611df25791817fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d969492604096940192611dde84612530565b81939154921b1b1916905555909138611d00565b634e487b7160e01b87526031600452602487fd5b634e487b7160e01b88526011600452602488fd5b50346102745761010036600319011261027457611e356124b9565b611e3d6124d4565b906044356001600160a01b03811690036114e657611e596124ea565b906084356001600160401b03811161073f57611e79903690600401612500565b9063ffffffff60c4351660c435036111c25760008051602061316983398151915254936001600160401b038516158061236b575b60016001600160401b038716149081612361575b159081612358575b506123465760016001600160401b03198616176000805160206131698339815191525560ff8560401c1615612319575b865460ff19166002178755611f0c612680565b611f14612680565b611f1d846125d0565b600380546001600160a01b0319166001600160a01b038816179055611f5260a435611f4d60c435604435836126af565b612644565b6001600160a01b0316865260096020526040862060019055600a5491821580156122f8575b1561227957600160401b831015612265576001830180600a55611f99846130e5565b5050831161225157866002611fad856130e5565b500155611fb9836130e5565b506001600160401b03821161223d57600160401b821161223d576001810154826001830155808310612213575b5060010187526020872082885b8381106121f857505050865b81811061213357505050907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc732604060ff94938151908152876020820152a1600554937f0577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff80600555604051957f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488880a360e435865260086020908152604080882080546001600160a01b0319166001600160a01b03948516179055929091168652600c9052808520805484191660011790551c16156120db575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff00000000000000001960008051602061316983398151915254166000805160206131698339815191525560018152a180f35b61213c846130e5565b506001600160a01b036121536109188486886128d9565b16895260205260ff6040892054166121a8576121a390612172856130e5565b506001600160a01b036121896109188487896128d9565b168a5260205260408920805460ff1916600117905561274d565b611fff565b60405162461bcd60e51b815260206004820152602260248201527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b600190602061220684613134565b9301928185015501611ff3565b60018201895260208920908382015b8183018110612232575050611fe6565b8a8155600101612222565b634e487b7160e01b88526041600452602488fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b87526041600452602487fd5b60405162461bcd60e51b815260206004820152604b60248201527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b50826000198101116122515761231160001984016130e5565b505086611f77565b68ffffffffffffffffff198516680100000000000000011760008051602061316983398151915255611ef9565b60405163f92ee8a960e01b8152600490fd5b90501538611ec9565b303b159150611ec1565b5060ff8560401c1615611ead565b5034610274576020366003190112610274576123936124b9565b61239b612597565b6001600160a01b0316808252600960205260408220600190557fef1fa0a4d797341645c201a742cf59be633da0589e0e3cda511cfc90cd0396848280a280f35b50346102745760803660031901126102745760209061240b6123fb6124b9565b6064359060243590604435612c27565b815260078252604060018060a01b03912054161515604051908152f35b50346102745760203660031901126102745761248d6040612447613006565b815190601f8261245f60208201936004359085613026565b03916124728219938481018652856127eb565b84519586946020865251809281602088015287870190612496565b01168101030190f35b60005b8381106124a95750506000910152565b8181015183820152602001612499565b600435906001600160a01b03821682036124cf57565b600080fd5b602435906001600160a01b03821682036124cf57565b606435906001600160a01b03821682036124cf57565b9181601f840112156124cf578235916001600160401b0383116124cf576020808501948460051b0101116124cf57565b6002548110156125675760026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0190600090565b634e487b7160e01b600052603260045260246000fd5b60609060031901126124cf57600435906024359060443590565b600080516020613149833981519152546001600160a01b031633036125b857565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b0390811690811561262b5760008051602061314983398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b600254600160401b81101561266a57611d888160016126669301600255612530565b9055565b634e487b7160e01b600052604160045260246000fd5b60ff6000805160206131698339815191525460401c161561269d57565b604051631afcd79f60e31b8152600490fd5b600090815260016020526040902080546001600160c81b0319166001600160a01b039092169190911760a09290921b63ffffffff60a01b1691909117600160c01b179055565b156126fc57565b60405162461bcd60e51b8152602060048201526024808201527f526f6c6c757056313a205a4b20766572696669657220646f6573206e6f7420656044820152631e1a5cdd60e21b6064820152608490fd5b600019811461275c5760010190565b634e487b7160e01b600052601160045260246000fd5b9190820391821161275c57565b606081019081106001600160401b0382111761266a57604052565b604081019081106001600160401b0382111761266a57604052565b608081019081106001600160401b0382111761266a57604052565b60c081019081106001600160401b0382111761266a57604052565b90601f801991011681019081106001600160401b0382111761266a57604052565b650526f6c6c75760d41b60206040516128248161279a565b600681520152603160f81b602060405161283d8161279a565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526128d3816127d0565b51902090565b91908110156125675760051b0190565b908160209103126124cf575180151581036124cf5790565b9161290d8382846128d9565b3580612924575050506001810180911161275c5790565b60028103612ae75750906001830180841161275c576129449083836128d9565b35906002840180851161275c5761295c9084836128d9565b3592600385019081861161275c57612973926128d9565b359060009282845260209160068352604092826001858820015403612aa45784865260068152818487205403612a62578486526006815260ff6002858820015416612a1f5784865260068152838620600201805460ff1916600117905583519283528201527f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a509190a260048201809211612a0b575090565b634e487b7160e01b81526011600452602490fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e7420616c7265616479207370656e74000000006044820152fd5b60649084519062461bcd60e51b825280600483015260248201527f526f6c6c757056313a204d696e74206e6f7465206b696e6420696e76616c69646044820152fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e742076616c756520696e76616c6964000000006044820152fd5b600303612be2576001830180841161275c57612b049082846128d9565b35916002840180851161275c57612b1c9083836128d9565b35906003850180861161275c57612b349084836128d9565b35906004860180871161275c576001600160a01b03948592612b579291906128d9565b35166000948086526008602052612b778486604089205416928486612c27565b80875260076020526040872054909516918215612bd0575090612b9b939291612c60565b612bb1575b505b60058201809211612a0b575090565b815260076020526040812080546001600160a01b031916905538612ba0565b9150612bdc9450612c60565b50612ba2565b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20496e76616c6964206d657373616765206b696e6400006044820152606490fd5b929091604051926020840194855260018060a01b0316604084015260608301526080820152600060a082015260a081526128d3816127d0565b919092612c6e908484612cf4565b6040805160008152821515602082015291946001600160a01b039081169416917f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b079190a490565b3d15612cef573d906001600160401b03821161266a5760405191612ce3601f8201601f1916602001846127eb565b82523d6000602084013e565b606090565b6000929183809360405190602082019363a9059cbb60e01b855260018060a01b03166024830152604482015260448152612d2d816127b5565b51925af1612d39612cb5565b9015612d715780519081612d4f575b5050600190565b602080612d609383010191016128e9565b15612d6c573880612d48565b600090565b50600090565b15612d7e57565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20546f6b656e206e6f7420666f756e6420666f72206e6f6044820152661d19481ada5b9960ca1b6064820152608490fd5b6040516323b872dd60e01b602082019081526001600160a01b0393841660248301529383166044820152606480820195909552938452909160a08401906001600160401b0382118583101761266a57612e459360009384936040521694519082865af1612e3e612cb5565b9083612e8e565b8051908115159182612e73575b5050612e5b5750565b60249060405190635274afe760e01b82526004820152fd5b612e8692506020809183010191016128e9565b153880612e52565b90612eb55750805115612ea357805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580612ee8575b612ec6575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15612ebe565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612f7557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612f695780516001600160a01b03811615612f6057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612ff05780612f93575050565b60018103612fad5760405163f645eedf60e01b8152600490fd5b60028103612fce5760405163fce698f760e01b815260048101839052602490fd5b600314612fd85750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b604051906130138261279a565b60048252635061797960e01b6020830152565b9060289291600160c21b8152613046825180936020600885019101612496565b019060088201520190565b6040805160208101928352908101839052606080820194909452928352601f199261307d6080826127eb565b5190206001820180921161275c5761023e916128d39160405190602082019283526040820152604081526130b08161277f565b519020926130bc613006565b93604051938491602083019687613026565b6001600160401b03811161266a5760051b60200190565b600a5481101561256757600390600a600052027fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b80518210156125675760209160051b010190565b356001600160a01b03811681036124cf579056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122050595354ea1940f63f827618bd636aa15a48ff95a964a8f185268d9842cca0b264736f6c63430008140033", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b6000803560e01c80630d647a9a1461242857806316fc1d4b146123db5780631d49e457146123795780631d80009a14611866578063220b01c614611e1a57806326e31a9414611c9c5780632a2bc73a14611c695780633644e51514611c4e5780633e413bee14611c255780634eeb381e14611b4b57806354fd4d5014611b2b57806356dc63cb14611ae45780635d5fa0d114611a8a5780636b2bd2ec14611a51578063715018a6146119e75780638da5cb5b146119b15780639776aacf14611903578063a2ce9c1f14611884578063a91eebf514611866578063ab1c290114611631578063b2142b50146115f0578063b571d3dd14611536578063b72e88cb146114f2578063b8cdbd2714610db5578063bb254e7a14610d93578063c1b1535914610d60578063c34975bb14610d10578063d82cbdd914610bb0578063dab5f34014610b65578063e795594d146107e1578063eae4475a146104bd578063ef0feff9146102c2578063f2fde38b14610295578063f44ff712146102775763f9038cf31461019e57600080fd5b34610274576101d66101af3661257d565b60409392919351928391856020840194856040919493926060820195825260208201520152565b03916101ea601f19938481018352826127eb565b51902091600181018091116102605760609350604051602081019182528360408201526040815261021a8161277f565b51902090610226613006565b9061024a604051918261023e86602083019687613026565b039081018352826127eb565b5190209060405192835260208301526040820152f35b634e487b7160e01b84526011600452602484fd5b80fd5b50346102745780600319360112610274576020600454604051908152f35b5034610274576020366003190112610274576102bf6102b26124b9565b6102ba612597565b6125d0565b80f35b503461027457602090816003193601126102745790600435600a546102e78282612772565b916102f1836130ce565b926102ff60405194856127eb565b80845261030e601f19916130ce565b01855b818110610490575050805b8281106103d75750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103595787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b8082106103b4575050509060019383808094015191015298019301930190928796959394929461034c565b82516001600160a01b031685528a95948501949092019160019190910190610389565b6103e481969495966130e5565b5060018091019060026103f6846130e5565b50015490604051926104078461279a565b60405191828b83549182815201928a528b8a20918a915b8d81841061047257505050505091816104416104699695936104639503826127eb565b8252898201526104518584612772565b9061045c828a613120565b5287613120565b5061274d565b9493929461031c565b84546001600160a01b0316865290940193928101929181019161041e565b9480809795966040516104a28161279a565b60608152878382015282828a01015201905095949395610311565b5034610274576101a0366003190112610274576004356024356044356104e16124ea565b60843560a4359160c4359086885260209360068552600160408a20015461079c5760405192858401927fc749520baeb387dcc1f93bdea47980df7e7750f05367ca40ad8204ffaded32ad845289604086015288606086015287608086015260018060a01b03809116938460a08701528660c08701528360e0870152610100838188015286526101208601956001600160401b039681811088821117610788576105db879385936105e49360405251902061059961280c565b90604051908d82019261190160f01b845260228301526042820152604281526105c1816127b5565b5190206101843590610164359060ff610144351690612ef1565b90929192612f81565b160361074357908a9392918885526008885260408520541691610608831515612d77565b823b1561073f576040519687946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015260ff60e4351660c4830152818361010492833560e4840152610124938435908401525af18015610734576106ec575b5050916040917fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1936106e084516106a48161277f565b8381526002838201868152878301908b82528a8c5260068652888c209351845551600184015551151591019060ff801983541691151516179055565b8351928352820152a280f35b81969296116107205760405293817fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f161066e565b634e487b7160e01b82526041600452602482fd5b6040513d89823e3d90fd5b8480fd5b60405162461bcd60e51b815260048101889052601860248201527f526f6c6c757056313a20496e76616c6964207369676e657200000000000000006044820152606490fd5b634e487b7160e01b8e52604160045260248efd5b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056313a204d696e7420616c7265616479206578697374730000006044820152606490fd5b50346102745760403660031901126102745760246004356001600160401b03823581811161073f57610817903690600401612500565b610822949194612597565b600a549485158015610b43575b15610ac55784158015610a9c575b15610a3257600160401b90818710156109f95760019182880180600a55610863896130e5565b50508811610a1f578660026108778a6130e5565b50015582610884896130e5565b5001958411610a0c5783116109f95784548386558084106109d1575b508094885260209485892090838a5b8681106109b85750505050875b8381106108f657887ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73260408a8a8a8351928352820152a180f35b6108ff886130e5565b506001600160a01b03908161091d6109188589886128d9565b613134565b168b52875260ff60408b20541661096957906109649161093c8a6130e5565b509061094c6109188489886128d9565b168b52875260408a20805460ff19168517905561274d565b6108bc565b60405162461bcd60e51b8152600481018890526022818801527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b886109c284613134565b930192818501550184906108af565b858952828460208b2092830192015b8281106109ee5750506108a0565b8a81550183906109e0565b634e487b7160e01b885260416004528388fd5b634e487b7160e01b895260416004528489fd5b634e487b7160e01b895260116004528489fd5b60405162461bcd60e51b815260206004820152603d818501527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b5062278d004301804311610ab25785111561083d565b634e487b7160e01b885260116004528388fd5b60405162461bcd60e51b815260206004820152604b818501527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b506000198601868111610ab2576002610b5c87926130e5565b5001541061082f565b503461027457602036600319011261027457600435610b82612597565b600554816005557f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488380a380f35b503461027457606036600319011261027457600435610bcd6124d4565b906044359063ffffffff821680830361073f57610be8612597565b6001600160a01b0384168015610cbd57843b15610c6857610c466060947fdb2a4be964bb3f5ba0504bccdbceaa478be8d73af2238cd9be0ba0c8efc107ca96858952600160205260ff60408a205460c01c1615610c5a575b856126af565b60405192835260208301526040820152a180f35b610c6386612644565b610c40565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a205a4b207665726966696572206973206e6f74206120636044820152661bdb9d1c9858dd60ca1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207a6b207665726966696572206164604482015264647265737360d81b6064820152608490fd5b503461027457602036600319011261027457604060609160043581526001602052205460ff6040519160018060a01b038116835263ffffffff8160a01c16602084015260c01c1615156040820152f35b503461027457602036600319011261027457602090600435815260078252604060018060a01b0391205416604051908152f35b5034610274576020610dad610da73661257d565b91613051565b604051908152f35b50346102745760c0366003190112610274576001600160401b0380604435116114ee573660236044350112156114ee578060443560040135116114ee57366024604435600401356044350101116114ee576064358181116114e657610e1e903690600401612500565b918060a435116114ea5736602360a4350112156114ea5760a43560040135116114e657366024606060a435600401350260a4350101116114e657338352600960205260016040842054036114aa576024358352600160205260ff604084205460c01c161561145b5760243583526001602052600363ffffffff604085205460a01c160163ffffffff81116102605763ffffffff1682036114085781156113f45781600110156113f45781600210156113f45760055481350361139f57600b54600181018111610260576001015b600a5481101561139857610efe816130e5565b50600260043591015411610f1e5780610f1991600b5561274d565b610eeb565b50905b610f2c600b546130e5565b5060a43560040135156113535760018101548060011b90808204600214901517156111d45760039004600181018091116111d45760a43560040135106112e857610f7f6084356004356020860135613051565b9084805b60a4356004013582106111e857505050506024358352600160205263ffffffff604084205460a01c1660039081018082116111d457905b82848383106111c65786916024358352600160205260018060a01b036040842054169060405191633a94343960e21b835260406004840152604435600401356044840152604435600401356024604435016064850137600460443501358381016064908101879052601f909101601f191684018481036060016024860152908101839052906001600160fb1b0383116111c25783608481809460209660051b90818a85830137010301915afa9081156111b7578391611188575b501561113457602081013560055560045460043511156110c957600435600455602060405191013581527f401f796450733fd22827ddc018ca37051459a8035c4026f533c294797bb8a49e602060043592a280f35b60405162461bcd60e51b815260206004820152603760248201527f526f6c6c757056313a204e657720626c6f636b20686569676874206d7573742060448201527f62652067726561746572207468616e2063757272656e740000000000000000006064820152608490fd5b60405162461bcd60e51b815260206004820152602660248201527f526f6c6c757056313a205a4b2070726f6f6620766572696669636174696f6e2060448201526519985a5b195960d21b6064820152608490fd5b6111aa915060203d6020116111b0575b6111a281836127eb565b8101906128e9565b83611074565b503d611198565b6040513d85823e3d90fd5b8580fd5b6111cf92612901565b610fba565b634e487b7160e01b85526011600452602485fd5b611219906112106060840260a4350160448101359060ff606460248301359201351688612ef1565b90939193612f81565b60018060a01b0380831691828a5285602052600160ff60408c205416151503611297571610156112535761124d909161274d565b90610f83565b606460405162461bcd60e51b815260206004820152602060248201527f526f6c6c757056313a205369676e65727320617265206e6f7420736f727465646044820152fd5b60405162461bcd60e51b815260206004820152602360248201527f526f6c6c757056313a205369676e6572206973206e6f7420612076616c6964616044820152623a37b960e91b6064820152608490fd5b60405162461bcd60e51b815260206004820152603f60248201527f526f6c6c757056313a204e6f7420656e6f756768207369676e6174757265732060448201527f66726f6d2076616c696461746f727320746f2076657269667920626c6f636b006064820152608490fd5b60405162461bcd60e51b815260206004820152601760248201527f526f6c6c757056313a204e6f207369676e6174757265730000000000000000006044820152606490fd5b5090610f21565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20526f6f74206861736820766572696669636174696f6e6044820152660819985a5b195960ca1b6064820152608490fd5b634e487b7160e01b83526032600452602483fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207075626c6963496e70757473206c6044820152640cadccee8d60db1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f526f6c6c757056313a205a4b207665726966696572206e6f7420616c6c6f77656044820152601960fa1b6064820152608490fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b8380fd5b5080fd5b50346102745760203660031901126102745761150c6124b9565b611514612597565b6001600160a01b03168152600c60205260408120805460ff1916600117905580f35b5034610274576020366003190112610274576115506124b9565b611558612597565b6001600160a01b031680825260096020526040822054600019016115ab5780825260096020528160408120557fd64d11086d859b73cf85a91ca06cbc484398acabe3d9a1b26d4366dff377d9858280a280f35b60405162461bcd60e51b815260206004820152601760248201527f41646472657373206973206e6f7420612070726f7665720000000000000000006044820152606490fd5b50346102745760203660031901126102745761160a6124b9565b611612612597565b6001600160a01b03168152600c60205260408120805460ff1916905580f35b50346102745760a03660031901126102745761164b6124b9565b6024356044359160643591338552602093600c8552600160ff6040882054161515036118105761167d84838584612c27565b80875260078652604087205490946001600160a01b0393909184166117c057608435600454101561176a578752600886527f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b0760406116f985828b205416936116e6851515612d77565b6116f281303388612dd3565b8785612cf4565b9481519560018752159687158a8801521694a461172d578252600790526040812080546001600160a01b0319163317905580f35b60405162461bcd60e51b8152600481018390526015602482015274149bdb1b1d5c158c4e88109d5c9b8819985a5b1959605a1b6044820152606490fd5b60405162461bcd60e51b815260048101889052602860248201527f526f6c6c757056313a20426c6f636b2068656967687420616c7265616479207260448201526706f6c6c65642075760c41b6064820152608490fd5b60405162461bcd60e51b815260048101889052602260248201527f526f6c6c757056313a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b60405162461bcd60e51b815260048101869052602860248201527f526f6c6c757056313a20596f7520617265206e6f742061206275726e2073756260448201526739ba34ba3aba37b960c11b6064820152608490fd5b50346102745780600319360112610274576020600554604051908152f35b5034610274576020366003190112610274576040816060928280516118a88161277f565b828152826020820152015260043581526006602052206040516118ca8161277f565b815491828252604060ff600260018401549360208601948552015416920191151582526040519283525160208301525115156040820152f35b5034610274576040366003190112610274576004356119206124d4565b90611929612597565b808352600860205260408320546001600160a01b039190821661196c57835260086020526040832091166bffffffffffffffffffffffff60a01b82541617905580f35b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20546f6b656e20616c72656164792065786973747300006044820152606490fd5b5034610274578060031936011261027457600080516020613149833981519152546040516001600160a01b039091168152602090f35b5034610274578060031936011261027457611a00612597565b60008051602061314983398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346102745760203660031901126102745760043590600254821015610274576020611a7c83612530565b90546040519160031b1c8152f35b503461027457602036600319011261027457604080916004358082526001602052611abd60ff8484205460c01c166126f5565b81526001602052205463ffffffff82519160018060a01b038116835260a01c166020820152f35b5034610274576020366003190112610274576040606091600435815260066020522080549060ff600260018301549201541690604051928352602083015215156040820152f35b503461027457806003193601126102745760ff6020915416604051908152f35b5034610274576060366003190112610274576004356024356044358284526006602052600160408520015461079c577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1918160409286526008602052611bcb8260018060a01b038589205416611bc2811515612d77565b30903390612dd3565b611c178351611bd98161277f565b828152600260208201858152868301908a8252898b526006602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346102745780600319360112610274576003546040516001600160a01b039091168152602090f35b50346102745780600319360112610274576020610dad61280c565b503461027457602036600319011261027457602090600435815260088252604060018060a01b0391205416604051908152f35b503461027457602036600319011261027457600435611cb9612597565b8082526001602052611cd460ff604084205460c01c166126f5565b8082526001602052604082208054908390556002805492916001600160a01b031690845b848110611d34575b857fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d6040868682519182526020820152a180f35b83611d3e82612530565b919054600392831b1c14611d5b5750611d569061274d565b611cf8565b9293949060001991828101908111611e0657611d88611d7c611d9f92612530565b905490871b1c92612530565b819391549060031b91821b91600019901b19161790565b905581548015611df25791817fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d969492604096940192611dde84612530565b81939154921b1b1916905555909138611d00565b634e487b7160e01b87526031600452602487fd5b634e487b7160e01b88526011600452602488fd5b50346102745761010036600319011261027457611e356124b9565b611e3d6124d4565b906044356001600160a01b03811690036114e657611e596124ea565b906084356001600160401b03811161073f57611e79903690600401612500565b9063ffffffff60c4351660c435036111c25760008051602061316983398151915254936001600160401b038516158061236b575b60016001600160401b038716149081612361575b159081612358575b506123465760016001600160401b03198616176000805160206131698339815191525560ff8560401c1615612319575b865460ff19166002178755611f0c612680565b611f14612680565b611f1d846125d0565b600380546001600160a01b0319166001600160a01b038816179055611f5260a435611f4d60c435604435836126af565b612644565b6001600160a01b0316865260096020526040862060019055600a5491821580156122f8575b1561227957600160401b831015612265576001830180600a55611f99846130e5565b5050831161225157866002611fad856130e5565b500155611fb9836130e5565b506001600160401b03821161223d57600160401b821161223d576001810154826001830155808310612213575b5060010187526020872082885b8381106121f857505050865b81811061213357505050907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc732604060ff94938151908152876020820152a1600554937f0577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff80600555604051957f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488880a360e435865260086020908152604080882080546001600160a01b0319166001600160a01b03948516179055929091168652600c9052808520805484191660011790551c16156120db575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff00000000000000001960008051602061316983398151915254166000805160206131698339815191525560018152a180f35b61213c846130e5565b506001600160a01b036121536109188486886128d9565b16895260205260ff6040892054166121a8576121a390612172856130e5565b506001600160a01b036121896109188487896128d9565b168a5260205260408920805460ff1916600117905561274d565b611fff565b60405162461bcd60e51b815260206004820152602260248201527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b600190602061220684613134565b9301928185015501611ff3565b60018201895260208920908382015b8183018110612232575050611fe6565b8a8155600101612222565b634e487b7160e01b88526041600452602488fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b87526041600452602487fd5b60405162461bcd60e51b815260206004820152604b60248201527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b50826000198101116122515761231160001984016130e5565b505086611f77565b68ffffffffffffffffff198516680100000000000000011760008051602061316983398151915255611ef9565b60405163f92ee8a960e01b8152600490fd5b90501538611ec9565b303b159150611ec1565b5060ff8560401c1615611ead565b5034610274576020366003190112610274576123936124b9565b61239b612597565b6001600160a01b0316808252600960205260408220600190557fef1fa0a4d797341645c201a742cf59be633da0589e0e3cda511cfc90cd0396848280a280f35b50346102745760803660031901126102745760209061240b6123fb6124b9565b6064359060243590604435612c27565b815260078252604060018060a01b03912054161515604051908152f35b50346102745760203660031901126102745761248d6040612447613006565b815190601f8261245f60208201936004359085613026565b03916124728219938481018652856127eb565b84519586946020865251809281602088015287870190612496565b01168101030190f35b60005b8381106124a95750506000910152565b8181015183820152602001612499565b600435906001600160a01b03821682036124cf57565b600080fd5b602435906001600160a01b03821682036124cf57565b606435906001600160a01b03821682036124cf57565b9181601f840112156124cf578235916001600160401b0383116124cf576020808501948460051b0101116124cf57565b6002548110156125675760026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0190600090565b634e487b7160e01b600052603260045260246000fd5b60609060031901126124cf57600435906024359060443590565b600080516020613149833981519152546001600160a01b031633036125b857565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b0390811690811561262b5760008051602061314983398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b600254600160401b81101561266a57611d888160016126669301600255612530565b9055565b634e487b7160e01b600052604160045260246000fd5b60ff6000805160206131698339815191525460401c161561269d57565b604051631afcd79f60e31b8152600490fd5b600090815260016020526040902080546001600160c81b0319166001600160a01b039092169190911760a09290921b63ffffffff60a01b1691909117600160c01b179055565b156126fc57565b60405162461bcd60e51b8152602060048201526024808201527f526f6c6c757056313a205a4b20766572696669657220646f6573206e6f7420656044820152631e1a5cdd60e21b6064820152608490fd5b600019811461275c5760010190565b634e487b7160e01b600052601160045260246000fd5b9190820391821161275c57565b606081019081106001600160401b0382111761266a57604052565b604081019081106001600160401b0382111761266a57604052565b608081019081106001600160401b0382111761266a57604052565b60c081019081106001600160401b0382111761266a57604052565b90601f801991011681019081106001600160401b0382111761266a57604052565b650526f6c6c75760d41b60206040516128248161279a565b600681520152603160f81b602060405161283d8161279a565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526128d3816127d0565b51902090565b91908110156125675760051b0190565b908160209103126124cf575180151581036124cf5790565b9161290d8382846128d9565b3580612924575050506001810180911161275c5790565b60028103612ae75750906001830180841161275c576129449083836128d9565b35906002840180851161275c5761295c9084836128d9565b3592600385019081861161275c57612973926128d9565b359060009282845260209160068352604092826001858820015403612aa45784865260068152818487205403612a62578486526006815260ff6002858820015416612a1f5784865260068152838620600201805460ff1916600117905583519283528201527f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a509190a260048201809211612a0b575090565b634e487b7160e01b81526011600452602490fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e7420616c7265616479207370656e74000000006044820152fd5b60649084519062461bcd60e51b825280600483015260248201527f526f6c6c757056313a204d696e74206e6f7465206b696e6420696e76616c69646044820152fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e742076616c756520696e76616c6964000000006044820152fd5b600303612be2576001830180841161275c57612b049082846128d9565b35916002840180851161275c57612b1c9083836128d9565b35906003850180861161275c57612b349084836128d9565b35906004860180871161275c576001600160a01b03948592612b579291906128d9565b35166000948086526008602052612b778486604089205416928486612c27565b80875260076020526040872054909516918215612bd0575090612b9b939291612c60565b612bb1575b505b60058201809211612a0b575090565b815260076020526040812080546001600160a01b031916905538612ba0565b9150612bdc9450612c60565b50612ba2565b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20496e76616c6964206d657373616765206b696e6400006044820152606490fd5b929091604051926020840194855260018060a01b0316604084015260608301526080820152600060a082015260a081526128d3816127d0565b919092612c6e908484612cf4565b6040805160008152821515602082015291946001600160a01b039081169416917f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b079190a490565b3d15612cef573d906001600160401b03821161266a5760405191612ce3601f8201601f1916602001846127eb565b82523d6000602084013e565b606090565b6000929183809360405190602082019363a9059cbb60e01b855260018060a01b03166024830152604482015260448152612d2d816127b5565b51925af1612d39612cb5565b9015612d715780519081612d4f575b5050600190565b602080612d609383010191016128e9565b15612d6c573880612d48565b600090565b50600090565b15612d7e57565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20546f6b656e206e6f7420666f756e6420666f72206e6f6044820152661d19481ada5b9960ca1b6064820152608490fd5b6040516323b872dd60e01b602082019081526001600160a01b0393841660248301529383166044820152606480820195909552938452909160a08401906001600160401b0382118583101761266a57612e459360009384936040521694519082865af1612e3e612cb5565b9083612e8e565b8051908115159182612e73575b5050612e5b5750565b60249060405190635274afe760e01b82526004820152fd5b612e8692506020809183010191016128e9565b153880612e52565b90612eb55750805115612ea357805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580612ee8575b612ec6575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15612ebe565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612f7557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612f695780516001600160a01b03811615612f6057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612ff05780612f93575050565b60018103612fad5760405163f645eedf60e01b8152600490fd5b60028103612fce5760405163fce698f760e01b815260048101839052602490fd5b600314612fd85750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b604051906130138261279a565b60048252635061797960e01b6020830152565b9060289291600160c21b8152613046825180936020600885019101612496565b019060088201520190565b6040805160208101928352908101839052606080820194909452928352601f199261307d6080826127eb565b5190206001820180921161275c5761023e916128d39160405190602082019283526040820152604081526130b08161277f565b519020926130bc613006565b93604051938491602083019687613026565b6001600160401b03811161266a5760051b60200190565b600a5481101561256757600390600a600052027fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b80518210156125675760209160051b010190565b356001600160a01b03811681036124cf579056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122050595354ea1940f63f827618bd636aa15a48ff95a964a8f185268d9842cca0b264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + +declare module "@nomicfoundation/hardhat-viem/types" { + export function deployContract( + contractName: "RollupV1", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + export function deployContract( + contractName: "contracts/rollup3/RollupV1.sol:RollupV1", + constructorArgs?: [], + config?: DeployContractConfig + ): Promise>; + + export function sendDeploymentTransaction( + contractName: "RollupV1", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + export function sendDeploymentTransaction( + contractName: "contracts/rollup3/RollupV1.sol:RollupV1", + constructorArgs?: [], + config?: SendDeploymentTransactionConfig + ): Promise<{ + contract: GetContractReturnType; + deploymentTransaction: GetTransactionReturnType; + }>; + + export function getContractAt( + contractName: "RollupV1", + address: Address, + config?: GetContractAtConfig + ): Promise>; + export function getContractAt( + contractName: "contracts/rollup3/RollupV1.sol:RollupV1", + address: Address, + config?: GetContractAtConfig + ): Promise>; +} diff --git a/eth/artifacts/contracts/rollup3/RollupV1.sol/RollupV1.json b/eth/artifacts/contracts/rollup3/RollupV1.sol/RollupV1.json new file mode 100644 index 0000000..b376286 --- /dev/null +++ b/eth/artifacts/contracts/rollup3/RollupV1.sol/RollupV1.json @@ -0,0 +1,1166 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RollupV1", + "sourceName": "contracts/rollup3/RollupV1.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "AddressEmptyCode", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "AddressInsufficientBalance", + "type": "error" + }, + { + "inputs": [], + "name": "ECDSAInvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "ECDSAInvalidSignatureLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "ECDSAInvalidSignatureS", + "type": "error" + }, + { + "inputs": [], + "name": "FailedInnerCall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SafeERC20FailedOperation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "burn_hash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "substitute", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "MintAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "ProverAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "ProverRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "name": "RollupVerified", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "oldRoot", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + } + ], + "name": "RootHashUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + } + ], + "name": "ValidatorSetAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "verificationKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "zkVerifierAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "messages_length", + "type": "uint32" + } + ], + "name": "VerifierAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "verificationKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "address", + "name": "zkVerifierAddress", + "type": "address" + } + ], + "name": "VerifierRemoved", + "type": "event" + }, + { + "inputs": [], + "name": "DOMAIN_SEPARATOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnSubstitutor", + "type": "address" + } + ], + "name": "addBurnSubstitutor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "addProver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "noteKind", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + } + ], + "name": "addToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "verifierAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "messages_length", + "type": "uint32" + } + ], + "name": "addZkVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "blockHeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentRootHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "otherHashFromBlockHash", + "type": "bytes32" + } + ], + "name": "debugGetIntermediateHashes", + "outputs": [ + { + "internalType": "bytes32", + "name": "proposalHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "acceptMsg", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "sigMsg", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "acceptMsg", + "type": "bytes32" + } + ], + "name": "debugGetPackedBytes", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "otherHashFromBlockHash", + "type": "bytes32" + } + ], + "name": "debugGetSignatureMessageHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + } + ], + "name": "getMint", + "outputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "internalType": "struct Mint", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "from", + "type": "uint256" + } + ], + "name": "getValidatorSets", + "outputs": [ + { + "components": [ + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + } + ], + "internalType": "struct PublicValidatorSet[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + } + ], + "name": "getZkVerifier", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_usdcAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_verifierAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "prover", + "type": "address" + }, + { + "internalType": "address[]", + "name": "initialValidators", + "type": "address[]" + }, + { + "internalType": "bytes32", + "name": "verifierKeyHash", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "verifierMessagesCount", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "initialNoteKind", + "type": "bytes32" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "mint_hash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "value", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "validAfter", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "validBefore", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "nonce", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "v", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "v2", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "r2", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s2", + "type": "bytes32" + } + ], + "name": "mintWithAuthorization", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "mints", + "outputs": [ + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "spent", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "noteKind", + "type": "bytes32" + } + ], + "name": "noteKindTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnSubstitutor", + "type": "address" + } + ], + "name": "removeBurnSubstitutor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "prover", + "type": "address" + } + ], + "name": "removeProver", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + } + ], + "name": "removeZkVerifier", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rootHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + } + ], + "name": "setRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "validFrom", + "type": "uint256" + }, + { + "internalType": "address[]", + "name": "validators", + "type": "address[]" + } + ], + "name": "setValidators", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burnAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "burnBlockHeight", + "type": "uint256" + } + ], + "name": "substituteBurn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "substitutedBurns", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usdc", + "outputs": [ + { + "internalType": "contract IUSDC", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "verificationKeyHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "aggrProof", + "type": "bytes" + }, + { + "internalType": "bytes32[]", + "name": "publicInputs", + "type": "bytes32[]" + }, + { + "internalType": "bytes32", + "name": "otherHashFromBlockHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "v", + "type": "uint256" + } + ], + "internalType": "struct Signature[]", + "name": "signatures", + "type": "tuple[]" + } + ], + "name": "verifyRollup", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "burn_address", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "note_kind", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "hash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "wasBurnSubstituted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "zkVerifierKeys", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "zkVerifiers", + "outputs": [ + { + "internalType": "contract IVerifier", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint32", + "name": "messages_length", + "type": "uint32" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x608080604052346100b9577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009081549060ff8260401c166100aa57506001600160401b036002600160401b031982821601610065575b6040516131be9081620000bf8239f35b6001600160401b031990911681179091556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a1388080610055565b63f92ee8a960e01b8152600490fd5b600080fdfe6080604052600436101561001257600080fd5b6000803560e01c80630d647a9a1461242857806316fc1d4b146123db5780631d49e457146123795780631d80009a14611866578063220b01c614611e1a57806326e31a9414611c9c5780632a2bc73a14611c695780633644e51514611c4e5780633e413bee14611c255780634eeb381e14611b4b57806354fd4d5014611b2b57806356dc63cb14611ae45780635d5fa0d114611a8a5780636b2bd2ec14611a51578063715018a6146119e75780638da5cb5b146119b15780639776aacf14611903578063a2ce9c1f14611884578063a91eebf514611866578063ab1c290114611631578063b2142b50146115f0578063b571d3dd14611536578063b72e88cb146114f2578063b8cdbd2714610db5578063bb254e7a14610d93578063c1b1535914610d60578063c34975bb14610d10578063d82cbdd914610bb0578063dab5f34014610b65578063e795594d146107e1578063eae4475a146104bd578063ef0feff9146102c2578063f2fde38b14610295578063f44ff712146102775763f9038cf31461019e57600080fd5b34610274576101d66101af3661257d565b60409392919351928391856020840194856040919493926060820195825260208201520152565b03916101ea601f19938481018352826127eb565b51902091600181018091116102605760609350604051602081019182528360408201526040815261021a8161277f565b51902090610226613006565b9061024a604051918261023e86602083019687613026565b039081018352826127eb565b5190209060405192835260208301526040820152f35b634e487b7160e01b84526011600452602484fd5b80fd5b50346102745780600319360112610274576020600454604051908152f35b5034610274576020366003190112610274576102bf6102b26124b9565b6102ba612597565b6125d0565b80f35b503461027457602090816003193601126102745790600435600a546102e78282612772565b916102f1836130ce565b926102ff60405194856127eb565b80845261030e601f19916130ce565b01855b818110610490575050805b8281106103d75750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103595787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b8082106103b4575050509060019383808094015191015298019301930190928796959394929461034c565b82516001600160a01b031685528a95948501949092019160019190910190610389565b6103e481969495966130e5565b5060018091019060026103f6846130e5565b50015490604051926104078461279a565b60405191828b83549182815201928a528b8a20918a915b8d81841061047257505050505091816104416104699695936104639503826127eb565b8252898201526104518584612772565b9061045c828a613120565b5287613120565b5061274d565b9493929461031c565b84546001600160a01b0316865290940193928101929181019161041e565b9480809795966040516104a28161279a565b60608152878382015282828a01015201905095949395610311565b5034610274576101a0366003190112610274576004356024356044356104e16124ea565b60843560a4359160c4359086885260209360068552600160408a20015461079c5760405192858401927fc749520baeb387dcc1f93bdea47980df7e7750f05367ca40ad8204ffaded32ad845289604086015288606086015287608086015260018060a01b03809116938460a08701528660c08701528360e0870152610100838188015286526101208601956001600160401b039681811088821117610788576105db879385936105e49360405251902061059961280c565b90604051908d82019261190160f01b845260228301526042820152604281526105c1816127b5565b5190206101843590610164359060ff610144351690612ef1565b90929192612f81565b160361074357908a9392918885526008885260408520541691610608831515612d77565b823b1561073f576040519687946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015260ff60e4351660c4830152818361010492833560e4840152610124938435908401525af18015610734576106ec575b5050916040917fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1936106e084516106a48161277f565b8381526002838201868152878301908b82528a8c5260068652888c209351845551600184015551151591019060ff801983541691151516179055565b8351928352820152a280f35b81969296116107205760405293817fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f161066e565b634e487b7160e01b82526041600452602482fd5b6040513d89823e3d90fd5b8480fd5b60405162461bcd60e51b815260048101889052601860248201527f526f6c6c757056313a20496e76616c6964207369676e657200000000000000006044820152606490fd5b634e487b7160e01b8e52604160045260248efd5b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056313a204d696e7420616c7265616479206578697374730000006044820152606490fd5b50346102745760403660031901126102745760246004356001600160401b03823581811161073f57610817903690600401612500565b610822949194612597565b600a549485158015610b43575b15610ac55784158015610a9c575b15610a3257600160401b90818710156109f95760019182880180600a55610863896130e5565b50508811610a1f578660026108778a6130e5565b50015582610884896130e5565b5001958411610a0c5783116109f95784548386558084106109d1575b508094885260209485892090838a5b8681106109b85750505050875b8381106108f657887ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73260408a8a8a8351928352820152a180f35b6108ff886130e5565b506001600160a01b03908161091d6109188589886128d9565b613134565b168b52875260ff60408b20541661096957906109649161093c8a6130e5565b509061094c6109188489886128d9565b168b52875260408a20805460ff19168517905561274d565b6108bc565b60405162461bcd60e51b8152600481018890526022818801527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b886109c284613134565b930192818501550184906108af565b858952828460208b2092830192015b8281106109ee5750506108a0565b8a81550183906109e0565b634e487b7160e01b885260416004528388fd5b634e487b7160e01b895260416004528489fd5b634e487b7160e01b895260116004528489fd5b60405162461bcd60e51b815260206004820152603d818501527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b5062278d004301804311610ab25785111561083d565b634e487b7160e01b885260116004528388fd5b60405162461bcd60e51b815260206004820152604b818501527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b506000198601868111610ab2576002610b5c87926130e5565b5001541061082f565b503461027457602036600319011261027457600435610b82612597565b600554816005557f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488380a380f35b503461027457606036600319011261027457600435610bcd6124d4565b906044359063ffffffff821680830361073f57610be8612597565b6001600160a01b0384168015610cbd57843b15610c6857610c466060947fdb2a4be964bb3f5ba0504bccdbceaa478be8d73af2238cd9be0ba0c8efc107ca96858952600160205260ff60408a205460c01c1615610c5a575b856126af565b60405192835260208301526040820152a180f35b610c6386612644565b610c40565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a205a4b207665726966696572206973206e6f74206120636044820152661bdb9d1c9858dd60ca1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207a6b207665726966696572206164604482015264647265737360d81b6064820152608490fd5b503461027457602036600319011261027457604060609160043581526001602052205460ff6040519160018060a01b038116835263ffffffff8160a01c16602084015260c01c1615156040820152f35b503461027457602036600319011261027457602090600435815260078252604060018060a01b0391205416604051908152f35b5034610274576020610dad610da73661257d565b91613051565b604051908152f35b50346102745760c0366003190112610274576001600160401b0380604435116114ee573660236044350112156114ee578060443560040135116114ee57366024604435600401356044350101116114ee576064358181116114e657610e1e903690600401612500565b918060a435116114ea5736602360a4350112156114ea5760a43560040135116114e657366024606060a435600401350260a4350101116114e657338352600960205260016040842054036114aa576024358352600160205260ff604084205460c01c161561145b5760243583526001602052600363ffffffff604085205460a01c160163ffffffff81116102605763ffffffff1682036114085781156113f45781600110156113f45781600210156113f45760055481350361139f57600b54600181018111610260576001015b600a5481101561139857610efe816130e5565b50600260043591015411610f1e5780610f1991600b5561274d565b610eeb565b50905b610f2c600b546130e5565b5060a43560040135156113535760018101548060011b90808204600214901517156111d45760039004600181018091116111d45760a43560040135106112e857610f7f6084356004356020860135613051565b9084805b60a4356004013582106111e857505050506024358352600160205263ffffffff604084205460a01c1660039081018082116111d457905b82848383106111c65786916024358352600160205260018060a01b036040842054169060405191633a94343960e21b835260406004840152604435600401356044840152604435600401356024604435016064850137600460443501358381016064908101879052601f909101601f191684018481036060016024860152908101839052906001600160fb1b0383116111c25783608481809460209660051b90818a85830137010301915afa9081156111b7578391611188575b501561113457602081013560055560045460043511156110c957600435600455602060405191013581527f401f796450733fd22827ddc018ca37051459a8035c4026f533c294797bb8a49e602060043592a280f35b60405162461bcd60e51b815260206004820152603760248201527f526f6c6c757056313a204e657720626c6f636b20686569676874206d7573742060448201527f62652067726561746572207468616e2063757272656e740000000000000000006064820152608490fd5b60405162461bcd60e51b815260206004820152602660248201527f526f6c6c757056313a205a4b2070726f6f6620766572696669636174696f6e2060448201526519985a5b195960d21b6064820152608490fd5b6111aa915060203d6020116111b0575b6111a281836127eb565b8101906128e9565b83611074565b503d611198565b6040513d85823e3d90fd5b8580fd5b6111cf92612901565b610fba565b634e487b7160e01b85526011600452602485fd5b611219906112106060840260a4350160448101359060ff606460248301359201351688612ef1565b90939193612f81565b60018060a01b0380831691828a5285602052600160ff60408c205416151503611297571610156112535761124d909161274d565b90610f83565b606460405162461bcd60e51b815260206004820152602060248201527f526f6c6c757056313a205369676e65727320617265206e6f7420736f727465646044820152fd5b60405162461bcd60e51b815260206004820152602360248201527f526f6c6c757056313a205369676e6572206973206e6f7420612076616c6964616044820152623a37b960e91b6064820152608490fd5b60405162461bcd60e51b815260206004820152603f60248201527f526f6c6c757056313a204e6f7420656e6f756768207369676e6174757265732060448201527f66726f6d2076616c696461746f727320746f2076657269667920626c6f636b006064820152608490fd5b60405162461bcd60e51b815260206004820152601760248201527f526f6c6c757056313a204e6f207369676e6174757265730000000000000000006044820152606490fd5b5090610f21565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20526f6f74206861736820766572696669636174696f6e6044820152660819985a5b195960ca1b6064820152608490fd5b634e487b7160e01b83526032600452602483fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207075626c6963496e70757473206c6044820152640cadccee8d60db1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f526f6c6c757056313a205a4b207665726966696572206e6f7420616c6c6f77656044820152601960fa1b6064820152608490fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b8380fd5b5080fd5b50346102745760203660031901126102745761150c6124b9565b611514612597565b6001600160a01b03168152600c60205260408120805460ff1916600117905580f35b5034610274576020366003190112610274576115506124b9565b611558612597565b6001600160a01b031680825260096020526040822054600019016115ab5780825260096020528160408120557fd64d11086d859b73cf85a91ca06cbc484398acabe3d9a1b26d4366dff377d9858280a280f35b60405162461bcd60e51b815260206004820152601760248201527f41646472657373206973206e6f7420612070726f7665720000000000000000006044820152606490fd5b50346102745760203660031901126102745761160a6124b9565b611612612597565b6001600160a01b03168152600c60205260408120805460ff1916905580f35b50346102745760a03660031901126102745761164b6124b9565b6024356044359160643591338552602093600c8552600160ff6040882054161515036118105761167d84838584612c27565b80875260078652604087205490946001600160a01b0393909184166117c057608435600454101561176a578752600886527f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b0760406116f985828b205416936116e6851515612d77565b6116f281303388612dd3565b8785612cf4565b9481519560018752159687158a8801521694a461172d578252600790526040812080546001600160a01b0319163317905580f35b60405162461bcd60e51b8152600481018390526015602482015274149bdb1b1d5c158c4e88109d5c9b8819985a5b1959605a1b6044820152606490fd5b60405162461bcd60e51b815260048101889052602860248201527f526f6c6c757056313a20426c6f636b2068656967687420616c7265616479207260448201526706f6c6c65642075760c41b6064820152608490fd5b60405162461bcd60e51b815260048101889052602260248201527f526f6c6c757056313a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b60405162461bcd60e51b815260048101869052602860248201527f526f6c6c757056313a20596f7520617265206e6f742061206275726e2073756260448201526739ba34ba3aba37b960c11b6064820152608490fd5b50346102745780600319360112610274576020600554604051908152f35b5034610274576020366003190112610274576040816060928280516118a88161277f565b828152826020820152015260043581526006602052206040516118ca8161277f565b815491828252604060ff600260018401549360208601948552015416920191151582526040519283525160208301525115156040820152f35b5034610274576040366003190112610274576004356119206124d4565b90611929612597565b808352600860205260408320546001600160a01b039190821661196c57835260086020526040832091166bffffffffffffffffffffffff60a01b82541617905580f35b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20546f6b656e20616c72656164792065786973747300006044820152606490fd5b5034610274578060031936011261027457600080516020613149833981519152546040516001600160a01b039091168152602090f35b5034610274578060031936011261027457611a00612597565b60008051602061314983398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346102745760203660031901126102745760043590600254821015610274576020611a7c83612530565b90546040519160031b1c8152f35b503461027457602036600319011261027457604080916004358082526001602052611abd60ff8484205460c01c166126f5565b81526001602052205463ffffffff82519160018060a01b038116835260a01c166020820152f35b5034610274576020366003190112610274576040606091600435815260066020522080549060ff600260018301549201541690604051928352602083015215156040820152f35b503461027457806003193601126102745760ff6020915416604051908152f35b5034610274576060366003190112610274576004356024356044358284526006602052600160408520015461079c577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1918160409286526008602052611bcb8260018060a01b038589205416611bc2811515612d77565b30903390612dd3565b611c178351611bd98161277f565b828152600260208201858152868301908a8252898b526006602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346102745780600319360112610274576003546040516001600160a01b039091168152602090f35b50346102745780600319360112610274576020610dad61280c565b503461027457602036600319011261027457602090600435815260088252604060018060a01b0391205416604051908152f35b503461027457602036600319011261027457600435611cb9612597565b8082526001602052611cd460ff604084205460c01c166126f5565b8082526001602052604082208054908390556002805492916001600160a01b031690845b848110611d34575b857fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d6040868682519182526020820152a180f35b83611d3e82612530565b919054600392831b1c14611d5b5750611d569061274d565b611cf8565b9293949060001991828101908111611e0657611d88611d7c611d9f92612530565b905490871b1c92612530565b819391549060031b91821b91600019901b19161790565b905581548015611df25791817fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d969492604096940192611dde84612530565b81939154921b1b1916905555909138611d00565b634e487b7160e01b87526031600452602487fd5b634e487b7160e01b88526011600452602488fd5b50346102745761010036600319011261027457611e356124b9565b611e3d6124d4565b906044356001600160a01b03811690036114e657611e596124ea565b906084356001600160401b03811161073f57611e79903690600401612500565b9063ffffffff60c4351660c435036111c25760008051602061316983398151915254936001600160401b038516158061236b575b60016001600160401b038716149081612361575b159081612358575b506123465760016001600160401b03198616176000805160206131698339815191525560ff8560401c1615612319575b865460ff19166002178755611f0c612680565b611f14612680565b611f1d846125d0565b600380546001600160a01b0319166001600160a01b038816179055611f5260a435611f4d60c435604435836126af565b612644565b6001600160a01b0316865260096020526040862060019055600a5491821580156122f8575b1561227957600160401b831015612265576001830180600a55611f99846130e5565b5050831161225157866002611fad856130e5565b500155611fb9836130e5565b506001600160401b03821161223d57600160401b821161223d576001810154826001830155808310612213575b5060010187526020872082885b8381106121f857505050865b81811061213357505050907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc732604060ff94938151908152876020820152a1600554937f0577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff80600555604051957f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488880a360e435865260086020908152604080882080546001600160a01b0319166001600160a01b03948516179055929091168652600c9052808520805484191660011790551c16156120db575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff00000000000000001960008051602061316983398151915254166000805160206131698339815191525560018152a180f35b61213c846130e5565b506001600160a01b036121536109188486886128d9565b16895260205260ff6040892054166121a8576121a390612172856130e5565b506001600160a01b036121896109188487896128d9565b168a5260205260408920805460ff1916600117905561274d565b611fff565b60405162461bcd60e51b815260206004820152602260248201527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b600190602061220684613134565b9301928185015501611ff3565b60018201895260208920908382015b8183018110612232575050611fe6565b8a8155600101612222565b634e487b7160e01b88526041600452602488fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b87526041600452602487fd5b60405162461bcd60e51b815260206004820152604b60248201527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b50826000198101116122515761231160001984016130e5565b505086611f77565b68ffffffffffffffffff198516680100000000000000011760008051602061316983398151915255611ef9565b60405163f92ee8a960e01b8152600490fd5b90501538611ec9565b303b159150611ec1565b5060ff8560401c1615611ead565b5034610274576020366003190112610274576123936124b9565b61239b612597565b6001600160a01b0316808252600960205260408220600190557fef1fa0a4d797341645c201a742cf59be633da0589e0e3cda511cfc90cd0396848280a280f35b50346102745760803660031901126102745760209061240b6123fb6124b9565b6064359060243590604435612c27565b815260078252604060018060a01b03912054161515604051908152f35b50346102745760203660031901126102745761248d6040612447613006565b815190601f8261245f60208201936004359085613026565b03916124728219938481018652856127eb565b84519586946020865251809281602088015287870190612496565b01168101030190f35b60005b8381106124a95750506000910152565b8181015183820152602001612499565b600435906001600160a01b03821682036124cf57565b600080fd5b602435906001600160a01b03821682036124cf57565b606435906001600160a01b03821682036124cf57565b9181601f840112156124cf578235916001600160401b0383116124cf576020808501948460051b0101116124cf57565b6002548110156125675760026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0190600090565b634e487b7160e01b600052603260045260246000fd5b60609060031901126124cf57600435906024359060443590565b600080516020613149833981519152546001600160a01b031633036125b857565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b0390811690811561262b5760008051602061314983398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b600254600160401b81101561266a57611d888160016126669301600255612530565b9055565b634e487b7160e01b600052604160045260246000fd5b60ff6000805160206131698339815191525460401c161561269d57565b604051631afcd79f60e31b8152600490fd5b600090815260016020526040902080546001600160c81b0319166001600160a01b039092169190911760a09290921b63ffffffff60a01b1691909117600160c01b179055565b156126fc57565b60405162461bcd60e51b8152602060048201526024808201527f526f6c6c757056313a205a4b20766572696669657220646f6573206e6f7420656044820152631e1a5cdd60e21b6064820152608490fd5b600019811461275c5760010190565b634e487b7160e01b600052601160045260246000fd5b9190820391821161275c57565b606081019081106001600160401b0382111761266a57604052565b604081019081106001600160401b0382111761266a57604052565b608081019081106001600160401b0382111761266a57604052565b60c081019081106001600160401b0382111761266a57604052565b90601f801991011681019081106001600160401b0382111761266a57604052565b650526f6c6c75760d41b60206040516128248161279a565b600681520152603160f81b602060405161283d8161279a565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526128d3816127d0565b51902090565b91908110156125675760051b0190565b908160209103126124cf575180151581036124cf5790565b9161290d8382846128d9565b3580612924575050506001810180911161275c5790565b60028103612ae75750906001830180841161275c576129449083836128d9565b35906002840180851161275c5761295c9084836128d9565b3592600385019081861161275c57612973926128d9565b359060009282845260209160068352604092826001858820015403612aa45784865260068152818487205403612a62578486526006815260ff6002858820015416612a1f5784865260068152838620600201805460ff1916600117905583519283528201527f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a509190a260048201809211612a0b575090565b634e487b7160e01b81526011600452602490fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e7420616c7265616479207370656e74000000006044820152fd5b60649084519062461bcd60e51b825280600483015260248201527f526f6c6c757056313a204d696e74206e6f7465206b696e6420696e76616c69646044820152fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e742076616c756520696e76616c6964000000006044820152fd5b600303612be2576001830180841161275c57612b049082846128d9565b35916002840180851161275c57612b1c9083836128d9565b35906003850180861161275c57612b349084836128d9565b35906004860180871161275c576001600160a01b03948592612b579291906128d9565b35166000948086526008602052612b778486604089205416928486612c27565b80875260076020526040872054909516918215612bd0575090612b9b939291612c60565b612bb1575b505b60058201809211612a0b575090565b815260076020526040812080546001600160a01b031916905538612ba0565b9150612bdc9450612c60565b50612ba2565b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20496e76616c6964206d657373616765206b696e6400006044820152606490fd5b929091604051926020840194855260018060a01b0316604084015260608301526080820152600060a082015260a081526128d3816127d0565b919092612c6e908484612cf4565b6040805160008152821515602082015291946001600160a01b039081169416917f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b079190a490565b3d15612cef573d906001600160401b03821161266a5760405191612ce3601f8201601f1916602001846127eb565b82523d6000602084013e565b606090565b6000929183809360405190602082019363a9059cbb60e01b855260018060a01b03166024830152604482015260448152612d2d816127b5565b51925af1612d39612cb5565b9015612d715780519081612d4f575b5050600190565b602080612d609383010191016128e9565b15612d6c573880612d48565b600090565b50600090565b15612d7e57565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20546f6b656e206e6f7420666f756e6420666f72206e6f6044820152661d19481ada5b9960ca1b6064820152608490fd5b6040516323b872dd60e01b602082019081526001600160a01b0393841660248301529383166044820152606480820195909552938452909160a08401906001600160401b0382118583101761266a57612e459360009384936040521694519082865af1612e3e612cb5565b9083612e8e565b8051908115159182612e73575b5050612e5b5750565b60249060405190635274afe760e01b82526004820152fd5b612e8692506020809183010191016128e9565b153880612e52565b90612eb55750805115612ea357805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580612ee8575b612ec6575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15612ebe565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612f7557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612f695780516001600160a01b03811615612f6057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612ff05780612f93575050565b60018103612fad5760405163f645eedf60e01b8152600490fd5b60028103612fce5760405163fce698f760e01b815260048101839052602490fd5b600314612fd85750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b604051906130138261279a565b60048252635061797960e01b6020830152565b9060289291600160c21b8152613046825180936020600885019101612496565b019060088201520190565b6040805160208101928352908101839052606080820194909452928352601f199261307d6080826127eb565b5190206001820180921161275c5761023e916128d39160405190602082019283526040820152604081526130b08161277f565b519020926130bc613006565b93604051938491602083019687613026565b6001600160401b03811161266a5760051b60200190565b600a5481101561256757600390600a600052027fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b80518210156125675760209160051b010190565b356001600160a01b03811681036124cf579056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122050595354ea1940f63f827618bd636aa15a48ff95a964a8f185268d9842cca0b264736f6c63430008140033", + "deployedBytecode": "0x6080604052600436101561001257600080fd5b6000803560e01c80630d647a9a1461242857806316fc1d4b146123db5780631d49e457146123795780631d80009a14611866578063220b01c614611e1a57806326e31a9414611c9c5780632a2bc73a14611c695780633644e51514611c4e5780633e413bee14611c255780634eeb381e14611b4b57806354fd4d5014611b2b57806356dc63cb14611ae45780635d5fa0d114611a8a5780636b2bd2ec14611a51578063715018a6146119e75780638da5cb5b146119b15780639776aacf14611903578063a2ce9c1f14611884578063a91eebf514611866578063ab1c290114611631578063b2142b50146115f0578063b571d3dd14611536578063b72e88cb146114f2578063b8cdbd2714610db5578063bb254e7a14610d93578063c1b1535914610d60578063c34975bb14610d10578063d82cbdd914610bb0578063dab5f34014610b65578063e795594d146107e1578063eae4475a146104bd578063ef0feff9146102c2578063f2fde38b14610295578063f44ff712146102775763f9038cf31461019e57600080fd5b34610274576101d66101af3661257d565b60409392919351928391856020840194856040919493926060820195825260208201520152565b03916101ea601f19938481018352826127eb565b51902091600181018091116102605760609350604051602081019182528360408201526040815261021a8161277f565b51902090610226613006565b9061024a604051918261023e86602083019687613026565b039081018352826127eb565b5190209060405192835260208301526040820152f35b634e487b7160e01b84526011600452602484fd5b80fd5b50346102745780600319360112610274576020600454604051908152f35b5034610274576020366003190112610274576102bf6102b26124b9565b6102ba612597565b6125d0565b80f35b503461027457602090816003193601126102745790600435600a546102e78282612772565b916102f1836130ce565b926102ff60405194856127eb565b80845261030e601f19916130ce565b01855b818110610490575050805b8281106103d75750505060405192828493840190808552835180925260408501928160408460051b880101950193815b8483106103595787870388f35b9193959092949650603f198882030183528487516040830190805191604085528251809152836060860193019086905b8082106103b4575050509060019383808094015191015298019301930190928796959394929461034c565b82516001600160a01b031685528a95948501949092019160019190910190610389565b6103e481969495966130e5565b5060018091019060026103f6846130e5565b50015490604051926104078461279a565b60405191828b83549182815201928a528b8a20918a915b8d81841061047257505050505091816104416104699695936104639503826127eb565b8252898201526104518584612772565b9061045c828a613120565b5287613120565b5061274d565b9493929461031c565b84546001600160a01b0316865290940193928101929181019161041e565b9480809795966040516104a28161279a565b60608152878382015282828a01015201905095949395610311565b5034610274576101a0366003190112610274576004356024356044356104e16124ea565b60843560a4359160c4359086885260209360068552600160408a20015461079c5760405192858401927fc749520baeb387dcc1f93bdea47980df7e7750f05367ca40ad8204ffaded32ad845289604086015288606086015287608086015260018060a01b03809116938460a08701528660c08701528360e0870152610100838188015286526101208601956001600160401b039681811088821117610788576105db879385936105e49360405251902061059961280c565b90604051908d82019261190160f01b845260228301526042820152604281526105c1816127b5565b5190206101843590610164359060ff610144351690612ef1565b90929192612f81565b160361074357908a9392918885526008885260408520541691610608831515612d77565b823b1561073f576040519687946377aadf6360e11b865260048601523060248601528a60448601526064850152608484015260a483015260ff60e4351660c4830152818361010492833560e4840152610124938435908401525af18015610734576106ec575b5050916040917fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1936106e084516106a48161277f565b8381526002838201868152878301908b82528a8c5260068652888c209351845551600184015551151591019060ff801983541691151516179055565b8351928352820152a280f35b81969296116107205760405293817fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f161066e565b634e487b7160e01b82526041600452602482fd5b6040513d89823e3d90fd5b8480fd5b60405162461bcd60e51b815260048101889052601860248201527f526f6c6c757056313a20496e76616c6964207369676e657200000000000000006044820152606490fd5b634e487b7160e01b8e52604160045260248efd5b60405162461bcd60e51b815260206004820152601d60248201527f526f6c6c757056313a204d696e7420616c7265616479206578697374730000006044820152606490fd5b50346102745760403660031901126102745760246004356001600160401b03823581811161073f57610817903690600401612500565b610822949194612597565b600a549485158015610b43575b15610ac55784158015610a9c575b15610a3257600160401b90818710156109f95760019182880180600a55610863896130e5565b50508811610a1f578660026108778a6130e5565b50015582610884896130e5565b5001958411610a0c5783116109f95784548386558084106109d1575b508094885260209485892090838a5b8681106109b85750505050875b8381106108f657887ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc73260408a8a8a8351928352820152a180f35b6108ff886130e5565b506001600160a01b03908161091d6109188589886128d9565b613134565b168b52875260ff60408b20541661096957906109649161093c8a6130e5565b509061094c6109188489886128d9565b168b52875260408a20805460ff19168517905561274d565b6108bc565b60405162461bcd60e51b8152600481018890526022818801527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b886109c284613134565b930192818501550184906108af565b858952828460208b2092830192015b8281106109ee5750506108a0565b8a81550183906109e0565b634e487b7160e01b885260416004528388fd5b634e487b7160e01b895260416004528489fd5b634e487b7160e01b895260116004528489fd5b60405162461bcd60e51b815260206004820152603d818501527f526f6c6c757056313a2076616c696446726f6d2063616e6e6f74206265206d6f60448201527f7265207468616e203330206461797320696e20746865206675747572650000006064820152608490fd5b5062278d004301804311610ab25785111561083d565b634e487b7160e01b885260116004528388fd5b60405162461bcd60e51b815260206004820152604b818501527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b506000198601868111610ab2576002610b5c87926130e5565b5001541061082f565b503461027457602036600319011261027457600435610b82612597565b600554816005557f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488380a380f35b503461027457606036600319011261027457600435610bcd6124d4565b906044359063ffffffff821680830361073f57610be8612597565b6001600160a01b0384168015610cbd57843b15610c6857610c466060947fdb2a4be964bb3f5ba0504bccdbceaa478be8d73af2238cd9be0ba0c8efc107ca96858952600160205260ff60408a205460c01c1615610c5a575b856126af565b60405192835260208301526040820152a180f35b610c6386612644565b610c40565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a205a4b207665726966696572206973206e6f74206120636044820152661bdb9d1c9858dd60ca1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207a6b207665726966696572206164604482015264647265737360d81b6064820152608490fd5b503461027457602036600319011261027457604060609160043581526001602052205460ff6040519160018060a01b038116835263ffffffff8160a01c16602084015260c01c1615156040820152f35b503461027457602036600319011261027457602090600435815260078252604060018060a01b0391205416604051908152f35b5034610274576020610dad610da73661257d565b91613051565b604051908152f35b50346102745760c0366003190112610274576001600160401b0380604435116114ee573660236044350112156114ee578060443560040135116114ee57366024604435600401356044350101116114ee576064358181116114e657610e1e903690600401612500565b918060a435116114ea5736602360a4350112156114ea5760a43560040135116114e657366024606060a435600401350260a4350101116114e657338352600960205260016040842054036114aa576024358352600160205260ff604084205460c01c161561145b5760243583526001602052600363ffffffff604085205460a01c160163ffffffff81116102605763ffffffff1682036114085781156113f45781600110156113f45781600210156113f45760055481350361139f57600b54600181018111610260576001015b600a5481101561139857610efe816130e5565b50600260043591015411610f1e5780610f1991600b5561274d565b610eeb565b50905b610f2c600b546130e5565b5060a43560040135156113535760018101548060011b90808204600214901517156111d45760039004600181018091116111d45760a43560040135106112e857610f7f6084356004356020860135613051565b9084805b60a4356004013582106111e857505050506024358352600160205263ffffffff604084205460a01c1660039081018082116111d457905b82848383106111c65786916024358352600160205260018060a01b036040842054169060405191633a94343960e21b835260406004840152604435600401356044840152604435600401356024604435016064850137600460443501358381016064908101879052601f909101601f191684018481036060016024860152908101839052906001600160fb1b0383116111c25783608481809460209660051b90818a85830137010301915afa9081156111b7578391611188575b501561113457602081013560055560045460043511156110c957600435600455602060405191013581527f401f796450733fd22827ddc018ca37051459a8035c4026f533c294797bb8a49e602060043592a280f35b60405162461bcd60e51b815260206004820152603760248201527f526f6c6c757056313a204e657720626c6f636b20686569676874206d7573742060448201527f62652067726561746572207468616e2063757272656e740000000000000000006064820152608490fd5b60405162461bcd60e51b815260206004820152602660248201527f526f6c6c757056313a205a4b2070726f6f6620766572696669636174696f6e2060448201526519985a5b195960d21b6064820152608490fd5b6111aa915060203d6020116111b0575b6111a281836127eb565b8101906128e9565b83611074565b503d611198565b6040513d85823e3d90fd5b8580fd5b6111cf92612901565b610fba565b634e487b7160e01b85526011600452602485fd5b611219906112106060840260a4350160448101359060ff606460248301359201351688612ef1565b90939193612f81565b60018060a01b0380831691828a5285602052600160ff60408c205416151503611297571610156112535761124d909161274d565b90610f83565b606460405162461bcd60e51b815260206004820152602060248201527f526f6c6c757056313a205369676e65727320617265206e6f7420736f727465646044820152fd5b60405162461bcd60e51b815260206004820152602360248201527f526f6c6c757056313a205369676e6572206973206e6f7420612076616c6964616044820152623a37b960e91b6064820152608490fd5b60405162461bcd60e51b815260206004820152603f60248201527f526f6c6c757056313a204e6f7420656e6f756768207369676e6174757265732060448201527f66726f6d2076616c696461746f727320746f2076657269667920626c6f636b006064820152608490fd5b60405162461bcd60e51b815260206004820152601760248201527f526f6c6c757056313a204e6f207369676e6174757265730000000000000000006044820152606490fd5b5090610f21565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20526f6f74206861736820766572696669636174696f6e6044820152660819985a5b195960ca1b6064820152608490fd5b634e487b7160e01b83526032600452602483fd5b60405162461bcd60e51b815260206004820152602560248201527f526f6c6c757056313a20496e76616c6964207075626c6963496e70757473206c6044820152640cadccee8d60db1b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f526f6c6c757056313a205a4b207665726966696572206e6f7420616c6c6f77656044820152601960fa1b6064820152608490fd5b60405162461bcd60e51b81526020600482015260146024820152732cb7ba9030b932903737ba103090383937bb32b960611b6044820152606490fd5b8280fd5b8380fd5b5080fd5b50346102745760203660031901126102745761150c6124b9565b611514612597565b6001600160a01b03168152600c60205260408120805460ff1916600117905580f35b5034610274576020366003190112610274576115506124b9565b611558612597565b6001600160a01b031680825260096020526040822054600019016115ab5780825260096020528160408120557fd64d11086d859b73cf85a91ca06cbc484398acabe3d9a1b26d4366dff377d9858280a280f35b60405162461bcd60e51b815260206004820152601760248201527f41646472657373206973206e6f7420612070726f7665720000000000000000006044820152606490fd5b50346102745760203660031901126102745761160a6124b9565b611612612597565b6001600160a01b03168152600c60205260408120805460ff1916905580f35b50346102745760a03660031901126102745761164b6124b9565b6024356044359160643591338552602093600c8552600160ff6040882054161515036118105761167d84838584612c27565b80875260078652604087205490946001600160a01b0393909184166117c057608435600454101561176a578752600886527f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b0760406116f985828b205416936116e6851515612d77565b6116f281303388612dd3565b8785612cf4565b9481519560018752159687158a8801521694a461172d578252600790526040812080546001600160a01b0319163317905580f35b60405162461bcd60e51b8152600481018390526015602482015274149bdb1b1d5c158c4e88109d5c9b8819985a5b1959605a1b6044820152606490fd5b60405162461bcd60e51b815260048101889052602860248201527f526f6c6c757056313a20426c6f636b2068656967687420616c7265616479207260448201526706f6c6c65642075760c41b6064820152608490fd5b60405162461bcd60e51b815260048101889052602260248201527f526f6c6c757056313a204275726e20616c726561647920737562737469747574604482015261195960f21b6064820152608490fd5b60405162461bcd60e51b815260048101869052602860248201527f526f6c6c757056313a20596f7520617265206e6f742061206275726e2073756260448201526739ba34ba3aba37b960c11b6064820152608490fd5b50346102745780600319360112610274576020600554604051908152f35b5034610274576020366003190112610274576040816060928280516118a88161277f565b828152826020820152015260043581526006602052206040516118ca8161277f565b815491828252604060ff600260018401549360208601948552015416920191151582526040519283525160208301525115156040820152f35b5034610274576040366003190112610274576004356119206124d4565b90611929612597565b808352600860205260408320546001600160a01b039190821661196c57835260086020526040832091166bffffffffffffffffffffffff60a01b82541617905580f35b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20546f6b656e20616c72656164792065786973747300006044820152606490fd5b5034610274578060031936011261027457600080516020613149833981519152546040516001600160a01b039091168152602090f35b5034610274578060031936011261027457611a00612597565b60008051602061314983398151915280546001600160a01b0319811690915581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346102745760203660031901126102745760043590600254821015610274576020611a7c83612530565b90546040519160031b1c8152f35b503461027457602036600319011261027457604080916004358082526001602052611abd60ff8484205460c01c166126f5565b81526001602052205463ffffffff82519160018060a01b038116835260a01c166020820152f35b5034610274576020366003190112610274576040606091600435815260066020522080549060ff600260018301549201541690604051928352602083015215156040820152f35b503461027457806003193601126102745760ff6020915416604051908152f35b5034610274576060366003190112610274576004356024356044358284526006602052600160408520015461079c577fc4adcac6a89d730f3a6da5d846bba3d858a8fc5884e0f80940a3a3b96a4ae6f1918160409286526008602052611bcb8260018060a01b038589205416611bc2811515612d77565b30903390612dd3565b611c178351611bd98161277f565b828152600260208201858152868301908a8252898b526006602052878b209351845551600184015551151591019060ff801983541691151516179055565b82519182526020820152a280f35b50346102745780600319360112610274576003546040516001600160a01b039091168152602090f35b50346102745780600319360112610274576020610dad61280c565b503461027457602036600319011261027457602090600435815260088252604060018060a01b0391205416604051908152f35b503461027457602036600319011261027457600435611cb9612597565b8082526001602052611cd460ff604084205460c01c166126f5565b8082526001602052604082208054908390556002805492916001600160a01b031690845b848110611d34575b857fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d6040868682519182526020820152a180f35b83611d3e82612530565b919054600392831b1c14611d5b5750611d569061274d565b611cf8565b9293949060001991828101908111611e0657611d88611d7c611d9f92612530565b905490871b1c92612530565b819391549060031b91821b91600019901b19161790565b905581548015611df25791817fa67e94ae6f2b34c76ff45db881989225caa876cbe2d8215c01650a104557573d969492604096940192611dde84612530565b81939154921b1b1916905555909138611d00565b634e487b7160e01b87526031600452602487fd5b634e487b7160e01b88526011600452602488fd5b50346102745761010036600319011261027457611e356124b9565b611e3d6124d4565b906044356001600160a01b03811690036114e657611e596124ea565b906084356001600160401b03811161073f57611e79903690600401612500565b9063ffffffff60c4351660c435036111c25760008051602061316983398151915254936001600160401b038516158061236b575b60016001600160401b038716149081612361575b159081612358575b506123465760016001600160401b03198616176000805160206131698339815191525560ff8560401c1615612319575b865460ff19166002178755611f0c612680565b611f14612680565b611f1d846125d0565b600380546001600160a01b0319166001600160a01b038816179055611f5260a435611f4d60c435604435836126af565b612644565b6001600160a01b0316865260096020526040862060019055600a5491821580156122f8575b1561227957600160401b831015612265576001830180600a55611f99846130e5565b5050831161225157866002611fad856130e5565b500155611fb9836130e5565b506001600160401b03821161223d57600160401b821161223d576001810154826001830155808310612213575b5060010187526020872082885b8381106121f857505050865b81811061213357505050907ffd204c7043da2bcc4dc261ed00edac3bb5e2b8c5c60c7535c4d17144759fc732604060ff94938151908152876020820152a1600554937f0577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff80600555604051957f2c5e454ab10a3bb8f13831cd35da5f0dbef2c5ac1c80c171157ab07519e097488880a360e435865260086020908152604080882080546001600160a01b0319166001600160a01b03948516179055929091168652600c9052808520805484191660011790551c16156120db575080f35b60207fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29168ff00000000000000001960008051602061316983398151915254166000805160206131698339815191525560018152a180f35b61213c846130e5565b506001600160a01b036121536109188486886128d9565b16895260205260ff6040892054166121a8576121a390612172856130e5565b506001600160a01b036121896109188487896128d9565b168a5260205260408920805460ff1916600117905561274d565b611fff565b60405162461bcd60e51b815260206004820152602260248201527f526f6c6c757056313a2056616c696461746f7220616c72656164792065786973604482015261747360f01b6064820152608490fd5b600190602061220684613134565b9301928185015501611ff3565b60018201895260208920908382015b8183018110612232575050611fe6565b8a8155600101612222565b634e487b7160e01b88526041600452602488fd5b634e487b7160e01b87526011600452602487fd5b634e487b7160e01b87526041600452602487fd5b60405162461bcd60e51b815260206004820152604b60248201527f526f6c6c757056313a204e65772076616c696461746f7220736574206d75737460448201527f206861766520612076616c696446726f6d2067726561746572207468616e207460648201526a1a19481b185cdd081cd95d60aa1b608482015260a490fd5b50826000198101116122515761231160001984016130e5565b505086611f77565b68ffffffffffffffffff198516680100000000000000011760008051602061316983398151915255611ef9565b60405163f92ee8a960e01b8152600490fd5b90501538611ec9565b303b159150611ec1565b5060ff8560401c1615611ead565b5034610274576020366003190112610274576123936124b9565b61239b612597565b6001600160a01b0316808252600960205260408220600190557fef1fa0a4d797341645c201a742cf59be633da0589e0e3cda511cfc90cd0396848280a280f35b50346102745760803660031901126102745760209061240b6123fb6124b9565b6064359060243590604435612c27565b815260078252604060018060a01b03912054161515604051908152f35b50346102745760203660031901126102745761248d6040612447613006565b815190601f8261245f60208201936004359085613026565b03916124728219938481018652856127eb565b84519586946020865251809281602088015287870190612496565b01168101030190f35b60005b8381106124a95750506000910152565b8181015183820152602001612499565b600435906001600160a01b03821682036124cf57565b600080fd5b602435906001600160a01b03821682036124cf57565b606435906001600160a01b03821682036124cf57565b9181601f840112156124cf578235916001600160401b0383116124cf576020808501948460051b0101116124cf57565b6002548110156125675760026000527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0190600090565b634e487b7160e01b600052603260045260246000fd5b60609060031901126124cf57600435906024359060443590565b600080516020613149833981519152546001600160a01b031633036125b857565b60405163118cdaa760e01b8152336004820152602490fd5b6001600160a01b0390811690811561262b5760008051602061314983398151915280546001600160a01b031981168417909155167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b604051631e4fbdf760e01b815260006004820152602490fd5b600254600160401b81101561266a57611d888160016126669301600255612530565b9055565b634e487b7160e01b600052604160045260246000fd5b60ff6000805160206131698339815191525460401c161561269d57565b604051631afcd79f60e31b8152600490fd5b600090815260016020526040902080546001600160c81b0319166001600160a01b039092169190911760a09290921b63ffffffff60a01b1691909117600160c01b179055565b156126fc57565b60405162461bcd60e51b8152602060048201526024808201527f526f6c6c757056313a205a4b20766572696669657220646f6573206e6f7420656044820152631e1a5cdd60e21b6064820152608490fd5b600019811461275c5760010190565b634e487b7160e01b600052601160045260246000fd5b9190820391821161275c57565b606081019081106001600160401b0382111761266a57604052565b604081019081106001600160401b0382111761266a57604052565b608081019081106001600160401b0382111761266a57604052565b60c081019081106001600160401b0382111761266a57604052565b90601f801991011681019081106001600160401b0382111761266a57604052565b650526f6c6c75760d41b60206040516128248161279a565b600681520152603160f81b602060405161283d8161279a565b60018152015260405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527fc82a8a13fc2fdda879509bc5c45bfffe0508f437994e87b6b3cb003a4d486c1960408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a081526128d3816127d0565b51902090565b91908110156125675760051b0190565b908160209103126124cf575180151581036124cf5790565b9161290d8382846128d9565b3580612924575050506001810180911161275c5790565b60028103612ae75750906001830180841161275c576129449083836128d9565b35906002840180851161275c5761295c9084836128d9565b3592600385019081861161275c57612973926128d9565b359060009282845260209160068352604092826001858820015403612aa45784865260068152818487205403612a62578486526006815260ff6002858820015416612a1f5784865260068152838620600201805460ff1916600117905583519283528201527f948ecd827e77afeeebdc95f4d34a294c53d7e28501dcd56c8d89e88e61b53a509190a260048201809211612a0b575090565b634e487b7160e01b81526011600452602490fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e7420616c7265616479207370656e74000000006044820152fd5b60649084519062461bcd60e51b825280600483015260248201527f526f6c6c757056313a204d696e74206e6f7465206b696e6420696e76616c69646044820152fd5b60649084519062461bcd60e51b82526004820152601c60248201527f526f6c6c757056313a204d696e742076616c756520696e76616c6964000000006044820152fd5b600303612be2576001830180841161275c57612b049082846128d9565b35916002840180851161275c57612b1c9083836128d9565b35906003850180861161275c57612b349084836128d9565b35906004860180871161275c576001600160a01b03948592612b579291906128d9565b35166000948086526008602052612b778486604089205416928486612c27565b80875260076020526040872054909516918215612bd0575090612b9b939291612c60565b612bb1575b505b60058201809211612a0b575090565b815260076020526040812080546001600160a01b031916905538612ba0565b9150612bdc9450612c60565b50612ba2565b60405162461bcd60e51b815260206004820152601e60248201527f526f6c6c757056313a20496e76616c6964206d657373616765206b696e6400006044820152606490fd5b929091604051926020840194855260018060a01b0316604084015260608301526080820152600060a082015260a081526128d3816127d0565b919092612c6e908484612cf4565b6040805160008152821515602082015291946001600160a01b039081169416917f25bab1ec4b6635a8e0740834e52ce1aee362e9c38447738aa7b75b7e06275b079190a490565b3d15612cef573d906001600160401b03821161266a5760405191612ce3601f8201601f1916602001846127eb565b82523d6000602084013e565b606090565b6000929183809360405190602082019363a9059cbb60e01b855260018060a01b03166024830152604482015260448152612d2d816127b5565b51925af1612d39612cb5565b9015612d715780519081612d4f575b5050600190565b602080612d609383010191016128e9565b15612d6c573880612d48565b600090565b50600090565b15612d7e57565b60405162461bcd60e51b815260206004820152602760248201527f526f6c6c757056313a20546f6b656e206e6f7420666f756e6420666f72206e6f6044820152661d19481ada5b9960ca1b6064820152608490fd5b6040516323b872dd60e01b602082019081526001600160a01b0393841660248301529383166044820152606480820195909552938452909160a08401906001600160401b0382118583101761266a57612e459360009384936040521694519082865af1612e3e612cb5565b9083612e8e565b8051908115159182612e73575b5050612e5b5750565b60249060405190635274afe760e01b82526004820152fd5b612e8692506020809183010191016128e9565b153880612e52565b90612eb55750805115612ea357805190602001fd5b604051630a12f52160e11b8152600490fd5b81511580612ee8575b612ec6575090565b604051639996b31560e01b81526001600160a01b039091166004820152602490fd5b50803b15612ebe565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411612f7557926020929160ff608095604051948552168484015260408301526060820152600092839182805260015afa15612f695780516001600160a01b03811615612f6057918190565b50809160019190565b604051903d90823e3d90fd5b50505060009160039190565b6004811015612ff05780612f93575050565b60018103612fad5760405163f645eedf60e01b8152600490fd5b60028103612fce5760405163fce698f760e01b815260048101839052602490fd5b600314612fd85750565b602490604051906335e2f38360e21b82526004820152fd5b634e487b7160e01b600052602160045260246000fd5b604051906130138261279a565b60048252635061797960e01b6020830152565b9060289291600160c21b8152613046825180936020600885019101612496565b019060088201520190565b6040805160208101928352908101839052606080820194909452928352601f199261307d6080826127eb565b5190206001820180921161275c5761023e916128d39160405190602082019283526040820152604081526130b08161277f565b519020926130bc613006565b93604051938491602083019687613026565b6001600160401b03811161266a5760051b60200190565b600a5481101561256757600390600a600052027fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80190600090565b80518210156125675760209160051b010190565b356001600160a01b03811681036124cf579056fe9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00a264697066735822122050595354ea1940f63f827618bd636aa15a48ff95a964a8f185268d9842cca0b264736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/eth/artifacts/contracts/rollup3/RollupV1.sol/artifacts.d.ts b/eth/artifacts/contracts/rollup3/RollupV1.sol/artifacts.d.ts new file mode 100644 index 0000000..3ea9f93 --- /dev/null +++ b/eth/artifacts/contracts/rollup3/RollupV1.sol/artifacts.d.ts @@ -0,0 +1,15 @@ +// This file was autogenerated by hardhat-viem, do not edit it. +// prettier-ignore +// tslint:disable +// eslint-disable + +import "hardhat/types/artifacts"; + +import { RollupV1$Type } from "./RollupV1"; + +declare module "hardhat/types/artifacts" { + interface ArtifactsMap { + ["RollupV1"]: RollupV1$Type; + ["contracts/rollup3/RollupV1.sol:RollupV1"]: RollupV1$Type; + } +} diff --git a/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.d.ts b/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.d.ts deleted file mode 100644 index 35fc17e..0000000 --- a/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.d.ts +++ /dev/null @@ -1,84 +0,0 @@ -// This file was autogenerated by hardhat-viem, do not edit it. -// prettier-ignore -// tslint:disable -// eslint-disable - -import type { Address } from "viem"; -import type { GetContractReturnType } from "@nomicfoundation/hardhat-viem/types"; -import "@nomicfoundation/hardhat-viem/types"; - -export interface BurnToAddressRouter$Type { - "_format": "hh-sol-artifact-1", - "contractName": "BurnToAddressRouter", - "sourceName": "contracts/router/BurnToAddress.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "usdcAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burnToAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608080604052346100165761012e908161001c8239f35b600080fdfe6080806040526004361015601257600080fd5b600090813560e01c6365fb480c14602857600080fd5b3460cf57606036600319011260cf576001600160a01b03826004358281169081900360cf5760243592831680930360cf578380926064926020956323b872dd60e01b8452336004850152602484015260443560448401525af1801560ed57608d575080f35b60203d811160e7575b601f8101601f1916820167ffffffffffffffff81118382101760d35760209183916040528101031260cf57518015150360cc5780f35b80fd5b5080fd5b634e487b7160e01b84526041600452602484fd5b503d6096565b6040513d84823e3d90fdfea2646970667358221220a6eca7c04af637fb90f2095a6598db54c198078be587b0921d7a02a067ab868864736f6c63430008140033", - "deployedBytecode": "0x6080806040526004361015601257600080fd5b600090813560e01c6365fb480c14602857600080fd5b3460cf57606036600319011260cf576001600160a01b03826004358281169081900360cf5760243592831680930360cf578380926064926020956323b872dd60e01b8452336004850152602484015260443560448401525af1801560ed57608d575080f35b60203d811160e7575b601f8101601f1916820167ffffffffffffffff81118382101760d35760209183916040528101031260cf57518015150360cc5780f35b80fd5b5080fd5b634e487b7160e01b84526041600452602484fd5b503d6096565b6040513d84823e3d90fdfea2646970667358221220a6eca7c04af637fb90f2095a6598db54c198078be587b0921d7a02a067ab868864736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} - -declare module "@nomicfoundation/hardhat-viem/types" { - export function deployContract( - contractName: "BurnToAddressRouter", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - export function deployContract( - contractName: "contracts/router/BurnToAddress.sol:BurnToAddressRouter", - constructorArgs?: [], - config?: DeployContractConfig - ): Promise>; - - export function sendDeploymentTransaction( - contractName: "BurnToAddressRouter", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - export function sendDeploymentTransaction( - contractName: "contracts/router/BurnToAddress.sol:BurnToAddressRouter", - constructorArgs?: [], - config?: SendDeploymentTransactionConfig - ): Promise<{ - contract: GetContractReturnType; - deploymentTransaction: GetTransactionReturnType; - }>; - - export function getContractAt( - contractName: "BurnToAddressRouter", - address: Address, - config?: GetContractAtConfig - ): Promise>; - export function getContractAt( - contractName: "contracts/router/BurnToAddress.sol:BurnToAddressRouter", - address: Address, - config?: GetContractAtConfig - ): Promise>; -} diff --git a/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.dbg.json b/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.dbg.json deleted file mode 100644 index b7a6a76..0000000 --- a/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/22152f3e0e0b93ca501b6ace01f305e7.json" -} diff --git a/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.json b/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.json deleted file mode 100644 index e385abb..0000000 --- a/eth/artifacts/contracts/router/BurnToAddress.sol/BurnToAddressRouter.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "BurnToAddressRouter", - "sourceName": "contracts/router/BurnToAddress.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "usdcAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "burnToAddress", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608080604052346100165761012e908161001c8239f35b600080fdfe6080806040526004361015601257600080fd5b600090813560e01c6365fb480c14602857600080fd5b3460cf57606036600319011260cf576001600160a01b03826004358281169081900360cf5760243592831680930360cf578380926064926020956323b872dd60e01b8452336004850152602484015260443560448401525af1801560ed57608d575080f35b60203d811160e7575b601f8101601f1916820167ffffffffffffffff81118382101760d35760209183916040528101031260cf57518015150360cc5780f35b80fd5b5080fd5b634e487b7160e01b84526041600452602484fd5b503d6096565b6040513d84823e3d90fdfea2646970667358221220a6eca7c04af637fb90f2095a6598db54c198078be587b0921d7a02a067ab868864736f6c63430008140033", - "deployedBytecode": "0x6080806040526004361015601257600080fd5b600090813560e01c6365fb480c14602857600080fd5b3460cf57606036600319011260cf576001600160a01b03826004358281169081900360cf5760243592831680930360cf578380926064926020956323b872dd60e01b8452336004850152602484015260443560448401525af1801560ed57608d575080f35b60203d811160e7575b601f8101601f1916820167ffffffffffffffff81118382101760d35760209183916040528101031260cf57518015150360cc5780f35b80fd5b5080fd5b634e487b7160e01b84526041600452602484fd5b503d6096565b6040513d84823e3d90fdfea2646970667358221220a6eca7c04af637fb90f2095a6598db54c198078be587b0921d7a02a067ab868864736f6c63430008140033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/eth/artifacts/contracts/router/BurnToAddress.sol/artifacts.d.ts b/eth/artifacts/contracts/router/BurnToAddress.sol/artifacts.d.ts deleted file mode 100644 index 34c7a4c..0000000 --- a/eth/artifacts/contracts/router/BurnToAddress.sol/artifacts.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -// This file was autogenerated by hardhat-viem, do not edit it. -// prettier-ignore -// tslint:disable -// eslint-disable - -import "hardhat/types/artifacts"; - -import { BurnToAddressRouter$Type } from "./BurnToAddressRouter"; - -declare module "hardhat/types/artifacts" { - interface ArtifactsMap { - ["BurnToAddressRouter"]: BurnToAddressRouter$Type; - ["contracts/router/BurnToAddress.sol:BurnToAddressRouter"]: BurnToAddressRouter$Type; - } -} diff --git a/eth/contracts/AcrossWithAuthorization.sol b/eth/contracts/AcrossWithAuthorization.sol index 547f993..6862e58 100644 --- a/eth/contracts/AcrossWithAuthorization.sol +++ b/eth/contracts/AcrossWithAuthorization.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.20; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./IUSDC.sol"; interface IAcross { @@ -24,10 +25,12 @@ interface IAcross { contract AcrossWithAuthorization { event Deposited(address indexed depositor, bytes32 indexed nonce); - address across; + address public immutable owner; + address public immutable across; - constructor(address _across) { + constructor(address _across, address _owner) { across = _across; + owner = _owner; } function DOMAIN_SEPARATOR() public view returns (bytes32) { @@ -47,7 +50,7 @@ contract AcrossWithAuthorization { bytes32 constant DEPOSIT_V3_WITH_AUTHORIZATION_TYPE_HASH = keccak256( - "DepositV3WithAuthorization(uint256 validAfter,uint256 validBefore,bytes32 nonce,address depositor,address recipient,address inputToken,address outputToken,uint256 inputAmount,uint256 outputAmount,uint256 destinationChainId,address exclusiveRelayer,uint32 quoteTimestamp,uint32 fillDeadline,uint32 exclusivityDeadline,bytes message)" + "DepositV3WithAuthorization(uint256 validAfter,uint256 validBefore,bytes32 nonce,address depositor,address recipient,address inputToken,address outputToken,uint256 inputAmount,uint256 outputAmount,uint256 feeAmount,uint256 destinationChainId,address exclusiveRelayer,uint32 quoteTimestamp,uint32 fillDeadline,uint32 exclusivityDeadline,bytes message)" ); function depositV3WithAuthorization( @@ -68,6 +71,7 @@ contract AcrossWithAuthorization { address outputToken, uint256 inputAmount, uint256 outputAmount, + uint256 feeAmount, uint256 destinationChainId, address exclusiveRelayer, uint32 quoteTimestamp, @@ -87,6 +91,7 @@ contract AcrossWithAuthorization { outputToken, inputAmount, outputAmount, + feeAmount, destinationChainId, exclusiveRelayer, quoteTimestamp, @@ -104,7 +109,7 @@ contract AcrossWithAuthorization { IUSDC(inputToken).receiveWithAuthorization( depositor, address(this), - inputAmount, + inputAmount + feeAmount, validAfter, validBefore, nonce, @@ -132,4 +137,9 @@ contract AcrossWithAuthorization { emit Deposited(depositor, nonce); } + + function withdrawFees(address token, uint256 amount) external { + require(msg.sender == owner, "Only owner"); + IERC20(token).transfer(owner, amount); + } } diff --git a/eth/contracts/AggregateVerifierV1.sol b/eth/contracts/AggregateVerifierV1.sol index 04e1368..bf72fdd 100644 --- a/eth/contracts/AggregateVerifierV1.sol +++ b/eth/contracts/AggregateVerifierV1.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // Originally copied from https://github.com/scroll-tech/scroll/blob/ff380141a8cbcc214dc65f17ffa44faf4be646b6/contracts/src/libraries/verifier/ZkEvmVerifierV1.sol -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import "./Verifier.sol"; diff --git a/eth/contracts/BurnVerifierV1.sol b/eth/contracts/BurnVerifierV1.sol index 2cd598b..5bbe3cc 100644 --- a/eth/contracts/BurnVerifierV1.sol +++ b/eth/contracts/BurnVerifierV1.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // Originally copied from https://github.com/scroll-tech/scroll/blob/ff380141a8cbcc214dc65f17ffa44faf4be646b6/contracts/src/libraries/verifier/ZkEvmVerifierV1.sol -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import "./Verifier.sol"; diff --git a/eth/contracts/BurnVerifierV2.sol b/eth/contracts/BurnVerifierV2.sol index eb37d47..127efc6 100644 --- a/eth/contracts/BurnVerifierV2.sol +++ b/eth/contracts/BurnVerifierV2.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // Originally copied from https://github.com/scroll-tech/scroll/blob/ff380141a8cbcc214dc65f17ffa44faf4be646b6/contracts/src/libraries/verifier/ZkEvmVerifierV1.sol -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import "./Verifier.sol"; diff --git a/eth/contracts/Eip7702SimpleAccount.sol b/eth/contracts/Eip7702SimpleAccount.sol new file mode 100644 index 0000000..ed6c7dd --- /dev/null +++ b/eth/contracts/Eip7702SimpleAccount.sol @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +/// Minimal meta-transaction smart account to be used as an EIP-7702 delegate. +/// It verifies EIP-712 signatures from the account owner (the EOA's key) and executes calls. +/// Now also implements ERC-1271 so signatures validate when other contracts see code at this address. +contract Eip7702SimpleAccount is IERC1271, IERC165 { + // ========================= + // EIP-712 domain constants + // ========================= + bytes32 private constant EIP712DOMAIN_TYPEHASH = + keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ); + bytes32 private constant NAME_HASH = keccak256("Eip7702SimpleAccount"); + bytes32 private constant VERSION_HASH = keccak256("1"); + + // ========================= + // Batched Execute structs + // ========================= + bytes32 private constant CALL_TYPEHASH = + keccak256("Call(address target,uint256 value,bytes data)"); + bytes32 private constant EXECUTE_MANY_TYPEHASH = + keccak256( + "ExecuteMany(bytes32[] calls,uint256 nonce,uint256 validAfter,uint256 validUntil)" + ); + + struct Call { + address target; + uint256 value; + bytes data; + } + + // Deterministic nonce tracking keyed by uint256 (no conversion needed by callers) + mapping(uint256 => bool) public usedNonces; + + /// Emitted when a meta-transaction with a given nonce is accepted and executed + event NonceUsed(uint256 indexed nonce); + + constructor() {} + + // ============ + // EIP-712 + // ============ + function domainSeparator() public view returns (bytes32) { + return + keccak256( + abi.encode( + EIP712DOMAIN_TYPEHASH, + NAME_HASH, + VERSION_HASH, + block.chainid, + address(this) + ) + ); + } + + function _hashCall(Call calldata c) internal pure returns (bytes32) { + return + keccak256( + abi.encode(CALL_TYPEHASH, c.target, c.value, keccak256(c.data)) + ); + } + + /// Hash a batch (ExecuteMany) per EIP-712. + function _hashExecuteMany( + Call[] calldata calls, + uint256 _nonce, + uint256 validAfter, + uint256 validUntil + ) internal view returns (bytes32) { + bytes32 callsHash = hashCalls(calls); + bytes32 structHash = keccak256( + abi.encode( + EXECUTE_MANY_TYPEHASH, + callsHash, + _nonce, + validAfter, + validUntil + ) + ); + return + keccak256( + abi.encodePacked("\x19\x01", domainSeparator(), structHash) + ); + } + + /// Compute the hash of an array of Calls exactly as the off-chain signer does. + function hashCalls(Call[] calldata calls) public pure returns (bytes32) { + bytes32[] memory callHashes = new bytes32[](calls.length); + for (uint256 i = 0; i < calls.length; i++) { + callHashes[i] = _hashCall(calls[i]); + } + return keccak256(abi.encodePacked(callHashes)); + } + + /// Execute a batch of calls authorized by a user signature (the EOA's key). + function executeMeta( + Call[] calldata calls, + uint256 _nonce, + uint256 validAfter, + uint256 validUntil, + bytes calldata signature + ) external { + require(!usedNonces[_nonce], "nonce already used"); + require(block.timestamp >= validAfter, "authorization not yet valid"); + require(block.timestamp <= validUntil, "authorization expired"); + + bytes32 digest = _hashExecuteMany( + calls, + _nonce, + validAfter, + validUntil + ); + address signer = ECDSA.recover(digest, signature); + + // Under EIP-7702, this code executes at the EOA's address, so the expected signer is address(this). + require(signer == address(this), "bad signature"); + + usedNonces[_nonce] = true; + emit NonceUsed(_nonce); + + for (uint256 i = 0; i < calls.length; i++) { + (bool ok, bytes memory ret) = calls[i].target.call{ + value: calls[i].value + }(calls[i].data); + require(ok, string(ret)); + } + } + + function isNonceUsed(uint256 _nonce) external view returns (bool) { + return usedNonces[_nonce]; + } + + // ====================== + // ERC-1271 (signature validation for contract accounts) + // ====================== + + // Magic return values + bytes4 private constant _ERC1271_MAGICVALUE = + IERC1271.isValidSignature.selector; // 0x1626ba7e + bytes4 private constant _ERC1271_INVALID = 0xffffffff; // any value != magic is invalid + // Legacy (v0) "bytes,bytes" magic value for broader compatibility + bytes4 private constant _ERC1271_MAGICVALUE_BYTES = 0x20c13b0b; // bytes4(keccak256("isValidSignature(bytes,bytes)")) + + /// @notice ERC-1271 final: validate a signature over a 32-byte digest. + /// @dev MUST NOT revert on bad signatures — return a non-magic value instead. + function isValidSignature( + bytes32 hash, + bytes calldata signature + ) external view override returns (bytes4) { + (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover( + hash, + signature + ); + if (err == ECDSA.RecoverError.NoError && recovered == address(this)) { + return _ERC1271_MAGICVALUE; + } + return _ERC1271_INVALID; + } + + /// @notice ERC-1271 v0 variant: validate a signature over arbitrary bytes (hashed as keccak256). + /// @dev Returned magic value differs from the final ERC-1271 variant by design. + function isValidSignature( + bytes calldata data, + bytes calldata signature + ) external view returns (bytes4) { + (address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover( + keccak256(data), + signature + ); + if (err == ECDSA.RecoverError.NoError && recovered == address(this)) { + return _ERC1271_MAGICVALUE_BYTES; + } + return _ERC1271_INVALID; + } + + // ====================== + // ERC-165 (optional, helps feature detection) + // ====================== + + function supportsInterface( + bytes4 interfaceId + ) external pure override returns (bool) { + // ERC165 itself OR ERC1271 + return + interfaceId == type(IERC165).interfaceId || + interfaceId == type(IERC1271).interfaceId; // 0x1626ba7e + } + + /// Accept direct native token transfers when this contract is delegated via EIP-7702. + receive() external payable {} +} diff --git a/eth/contracts/IUSDC.sol b/eth/contracts/IUSDC.sol index 394480c..d510d8d 100644 --- a/eth/contracts/IUSDC.sol +++ b/eth/contracts/IUSDC.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/eth/contracts/LitActionRegistry.sol b/eth/contracts/LitActionRegistry.sol new file mode 100644 index 0000000..37ea521 --- /dev/null +++ b/eth/contracts/LitActionRegistry.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract LitActionRegistry is Ownable { + string public childLitActionCID; + + event ChildLitActionCIDUpdated(string oldCID, string newCID); + + constructor(address initialOwner) Ownable(initialOwner) {} + + function setChildLitActionCID(string memory newCID) external onlyOwner { + require(bytes(newCID).length > 0, "Child Lit Action CID cannot be empty"); + string memory oldCID = childLitActionCID; + childLitActionCID = newCID; + emit ChildLitActionCIDUpdated(oldCID, newCID); + } + + function getChildLitActionCID() external view returns (string memory) { + return childLitActionCID; + } + + // Alias for compatibility with parent lit action + function getChildIPFSCID() external view returns (string memory) { + return childLitActionCID; + } +} diff --git a/eth/contracts/MintVerifierV1.sol b/eth/contracts/MintVerifierV1.sol index 3373c6d..17d57bf 100644 --- a/eth/contracts/MintVerifierV1.sol +++ b/eth/contracts/MintVerifierV1.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT // Originally copied from https://github.com/scroll-tech/scroll/blob/ff380141a8cbcc214dc65f17ffa44faf4be646b6/contracts/src/libraries/verifier/ZkEvmVerifierV1.sol -pragma solidity 0.8.20; +pragma solidity ^0.8.20; import "./Verifier.sol"; diff --git a/eth/contracts/NoopVerifierHonk.bin b/eth/contracts/NoopVerifierHonk.bin new file mode 100644 index 0000000..4eb0747 --- /dev/null +++ b/eth/contracts/NoopVerifierHonk.bin @@ -0,0 +1 @@ +6080604052348015600e575f5ffd5b506101578061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004561003b366004610059565b6001949350505050565b604051901515815260200160405180910390f35b5f5f5f5f6040858703121561006c575f5ffd5b843567ffffffffffffffff811115610082575f5ffd5b8501601f81018713610092575f5ffd5b803567ffffffffffffffff8111156100a8575f5ffd5b8760208284010111156100b9575f5ffd5b60209182019550935085013567ffffffffffffffff8111156100d9575f5ffd5b8501601f810187136100e9575f5ffd5b803567ffffffffffffffff8111156100ff575f5ffd5b8760208260051b8401011115610113575f5ffd5b94979396506020019450505056fea2646970667358221220b05a4f06ba757605601ea75ced8d06fdea0cdd6a0de892f7c2cb88a2859fbfc564736f6c634300081d0033 diff --git a/eth/contracts/NoopVerifierHonk.sol b/eth/contracts/NoopVerifierHonk.sol new file mode 100644 index 0000000..91b8b61 --- /dev/null +++ b/eth/contracts/NoopVerifierHonk.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +interface IVerifier { + function verify( + bytes calldata _proof, + bytes32[] calldata _publicInputs + ) external view returns (bool); +} + +contract HonkVerifier is IVerifier { + function verify( + bytes calldata /* _proof */, + bytes32[] calldata /* _publicInputs */ + ) external pure override returns (bool) { + return true; + } +} diff --git a/eth/contracts/OpenZeppelinImports.sol b/eth/contracts/OpenZeppelinImports.sol new file mode 100644 index 0000000..0bcec50 --- /dev/null +++ b/eth/contracts/OpenZeppelinImports.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +// Import OpenZeppelin contracts used by deploy script +import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; \ No newline at end of file diff --git a/eth/contracts/SocialRecovery.sol b/eth/contracts/SocialRecovery.sol new file mode 100644 index 0000000..596789d --- /dev/null +++ b/eth/contracts/SocialRecovery.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract SocialRecovery is Ownable { + + struct GuardianConfig { + uint256 threshold; + bool enabled; + bytes32[] guardianCIDs; + mapping(bytes32 => bytes) guardianEntries; + } + + + mapping(address => GuardianConfig) public guardianConfigs; + + event GuardianCIDAdded(address indexed user, string guardianCID); + + constructor(address initialOwner) Ownable(initialOwner) {} + + function addGuardianCID(address user, string memory guardianCID, string memory guardianValue) external onlyOwner { + GuardianConfig storage guardianConfig = guardianConfigs[user]; + + if (guardianConfig.guardianCIDs.length == 0) { + guardianConfig.enabled = true; + } + + require(guardianConfig.enabled, "Guardian recovery disabled"); + require(bytes(guardianCID).length > 0, "Guardian CID cannot be empty"); + require(bytes(guardianValue).length > 0, "Guardian value cannot be empty"); + + bytes32 cidHash = keccak256(bytes(guardianCID)); + + bool exists = guardianConfig.guardianEntries[cidHash].length > 0; + + require(!exists, "Guardian Already exists"); + + guardianConfig.guardianEntries[cidHash] = bytes(guardianValue); + guardianConfig.guardianCIDs.push(cidHash); + + + if (guardianConfig.threshold == 0) { + guardianConfig.threshold = 1; + } + + emit GuardianCIDAdded(user, guardianCID); + } + + function updateThreshold(address user, uint256 newThreshold) external onlyOwner { + GuardianConfig storage config = guardianConfigs[user]; + require(config.guardianCIDs.length > 0, "No guardians configured"); + require(newThreshold > 0 && newThreshold <= config.guardianCIDs.length, "Invalid threshold"); + config.threshold = newThreshold; + } + + + function getGuardianConfig(address user) external view returns ( + uint256 threshold, + bool enabled, + uint256 guardianCount, + bytes32[] memory guardianCIDs + ) { + GuardianConfig storage config = guardianConfigs[user]; + return ( + config.threshold, + config.enabled, + config.guardianCIDs.length, + config.guardianCIDs + ); + } + + /// @notice Get the auth_value for a specific guardian CID hash + function getGuardianEntry(address user, bytes32 cidHash) external view returns (bytes memory) { + return guardianConfigs[user].guardianEntries[cidHash]; + } + +} diff --git a/eth/contracts/Verifier.sol b/eth/contracts/Verifier.sol index ffd63f8..316eba9 100644 --- a/eth/contracts/Verifier.sol +++ b/eth/contracts/Verifier.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.20; +pragma solidity ^0.8.20; contract Verifier { function requireValidFieldElement(bytes32 x) internal pure { diff --git a/eth/contracts/mocks/BoundsTestContract.sol b/eth/contracts/mocks/BoundsTestContract.sol new file mode 100644 index 0000000..4fe7258 --- /dev/null +++ b/eth/contracts/mocks/BoundsTestContract.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +// Simple contract to test just the bounds checking logic +contract BoundsTestContract { + uint256 constant MAX_FUTURE_BLOCKS = 2_592_000; // 30 days (~1 sec blocks) + + // Test function that only checks the bounds logic + function validateBounds(uint256 validFrom) external view { + require( + validFrom == 0 || validFrom <= block.number + MAX_FUTURE_BLOCKS, + "BoundsTest: validFrom cannot be more than 30 days in the future" + ); + } + + // Helper function to get current block + max future blocks + function getMaxAllowedValidFrom() external view returns (uint256) { + return block.number + MAX_FUTURE_BLOCKS; + } + + // Helper function to get current block number + function getCurrentBlock() external view returns (uint256) { + return block.number; + } + + // Helper function to get MAX_FUTURE_BLOCKS constant + function getMaxFutureBlocks() external pure returns (uint256) { + return MAX_FUTURE_BLOCKS; + } +} \ No newline at end of file diff --git a/eth/contracts/mocks/MockERC20.sol b/eth/contracts/mocks/MockERC20.sol new file mode 100644 index 0000000..2641b3b --- /dev/null +++ b/eth/contracts/mocks/MockERC20.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract MockERC20 is ERC20 { + constructor() ERC20("Mock USDC", "MUSDC") { + _mint(msg.sender, 1000000 * 10**18); + } + + function mint(address to, uint256 amount) external { + _mint(to, amount); + } + + // Mock implementation of receiveWithAuthorization for USDC compatibility + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint8 v, + bytes32 r, + bytes32 s + ) external { + // Simple mock implementation - just transfer + _transfer(from, to, value); + } +} \ No newline at end of file diff --git a/eth/contracts/mocks/MockUSDC.sol b/eth/contracts/mocks/MockUSDC.sol new file mode 100644 index 0000000..787a291 --- /dev/null +++ b/eth/contracts/mocks/MockUSDC.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "../IUSDC.sol"; + +contract MockUSDC is IUSDC { + mapping(address => uint256) private _balances; + mapping(address => mapping(address => uint256)) private _allowances; + mapping(address => bool) private _blacklisted; + + uint256 private _totalSupply; + string private _name = "Mock USDC"; + string private _symbol = "MUSDC"; + + constructor() { + // Give some initial balance to deployer for testing + _totalSupply = 1_000_000 * 10**6; // 1M USDC with 6 decimals + _balances[msg.sender] = _totalSupply; + } + + // ERC20 functions + function totalSupply() external view returns (uint256) { + return _totalSupply; + } + + function balanceOf(address account) external view returns (uint256) { + return _balances[account]; + } + + function transfer(address to, uint256 amount) external returns (bool) { + require(_balances[msg.sender] >= amount, "Insufficient balance"); + _balances[msg.sender] -= amount; + _balances[to] += amount; + return true; + } + + function transferFrom(address from, address to, uint256 amount) external returns (bool) { + require(_allowances[from][msg.sender] >= amount, "Insufficient allowance"); + require(_balances[from] >= amount, "Insufficient balance"); + _allowances[from][msg.sender] -= amount; + _balances[from] -= amount; + _balances[to] += amount; + return true; + } + + function approve(address spender, uint256 amount) external returns (bool) { + _allowances[msg.sender][spender] = amount; + return true; + } + + function allowance(address owner, address spender) external view returns (uint256) { + return _allowances[owner][spender]; + } + + // USDC-specific functions + function DOMAIN_SEPARATOR() external pure returns (bytes32) { + return keccak256("MOCK_USDC_DOMAIN"); + } + + function initialize( + string memory, + string memory, + string memory, + uint8, + address, + address, + address, + address + ) external { + // Mock implementation - do nothing + } + + function initializeV2(string calldata) external { + // Mock implementation - do nothing + } + + function initializeV2_1(address) external { + // Mock implementation - do nothing + } + + function configureMinter(address, uint256) external returns (bool) { + return true; + } + + function mint(address _to, uint256 _amount) external returns (bool) { + _balances[_to] += _amount; + _totalSupply += _amount; + return true; + } + + function receiveWithAuthorization( + address from, + address to, + uint256 value, + uint256, + uint256, + bytes32, + uint8, + bytes32, + bytes32 + ) external override { + require(_balances[from] >= value, "Insufficient balance"); + _balances[from] -= value; + _balances[to] += value; + } + + function transferWithAuthorization( + address from, + address to, + uint256 value, + uint256, + uint256, + bytes32, + uint8, + bytes32, + bytes32 + ) external { + require(_balances[from] >= value, "Insufficient balance"); + _balances[from] -= value; + _balances[to] += value; + } + + function isBlacklisted(address _account) external view returns (bool) { + return _blacklisted[_account]; + } +} \ No newline at end of file diff --git a/eth/contracts/mocks/MockVerifier.sol b/eth/contracts/mocks/MockVerifier.sol new file mode 100644 index 0000000..9280cff --- /dev/null +++ b/eth/contracts/mocks/MockVerifier.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "../noir/IVerifier.sol"; + +contract MockVerifier is IVerifier { + function verify( + bytes calldata proof, + bytes32[] calldata publicInputs + ) external pure override returns (bool) { + // Always return true for testing purposes + return true; + } +} \ No newline at end of file diff --git a/eth/contracts/mocks/RollupMigrationMock.sol b/eth/contracts/mocks/RollupMigrationMock.sol new file mode 100644 index 0000000..d5eb3ff --- /dev/null +++ b/eth/contracts/mocks/RollupMigrationMock.sol @@ -0,0 +1,41 @@ +pragma solidity ^0.8.20; + +contract RollupMigrationMock { + struct Mint { + bytes32 note_kind; + uint256 amount; + bool spent; + } + + mapping(bytes32 => Mint) public mints; + + event MintAdded(bytes32 indexed mint_hash, uint256 value, bytes32 note_kind); + event Minted(bytes32 indexed hash, bytes32 value, bytes32 note_kind); + + function getMint(bytes32 hash) external view returns (Mint memory) { + return mints[hash]; + } + + function emitMintAdded(bytes32 mint_hash, uint256 value, bytes32 note_kind) external { + mints[mint_hash] = Mint({ + note_kind: note_kind, + amount: value, + spent: false + }); + emit MintAdded(mint_hash, value, note_kind); + } + + function emitMinted(bytes32 hash, bytes32 value, bytes32 note_kind) external { + mints[hash].spent = true; + emit Minted(hash, value, note_kind); + } + + function mint(bytes32 mint_hash, bytes32 value, bytes32 note_kind) external { + mints[mint_hash] = Mint({ + note_kind: note_kind, + amount: uint256(value), + spent: false + }); + emit MintAdded(mint_hash, uint256(value), note_kind); + } +} \ No newline at end of file diff --git a/eth/contracts/mocks/TestRollupV1.sol b/eth/contracts/mocks/TestRollupV1.sol new file mode 100644 index 0000000..df439ff --- /dev/null +++ b/eth/contracts/mocks/TestRollupV1.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "../rollup3/RollupV1.sol"; + +// Test version of RollupV1 that allows initialization without proxy pattern +// We bypass the parent constructor by not calling super constructor +contract TestRollupV1 { + RollupV1 private rollup; + + constructor() { + // Create instance without calling constructor that disables initializers + } + + // Delegate to RollupV1 functions we need to test + function setValidators(uint256 validFrom, address[] calldata validators) external { + // This is a simplified test that just checks the bounds validation logic + require( + validFrom == 0 || validFrom <= block.number + 2_592_000, // MAX_FUTURE_BLOCKS + "RollupV1: validFrom cannot be more than 30 days in the future" + ); + } +} diff --git a/eth/contracts/noir/IVerifier.sol b/eth/contracts/noir/IVerifier.sol new file mode 100644 index 0000000..9c3e52d --- /dev/null +++ b/eth/contracts/noir/IVerifier.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +interface IVerifier { + function verify( + bytes calldata _proof, + bytes32[] calldata _publicInputs + ) external view returns (bool); +} diff --git a/eth/contracts/noir/agg_agg_HonkVerifier.bin b/eth/contracts/noir/agg_agg_HonkVerifier.bin new file mode 100644 index 0000000..48e2bfb --- /dev/null +++ b/eth/contracts/noir/agg_agg_HonkVerifier.bin @@ -0,0 +1 @@ +610100604052348015610010575f5ffd5b5062200000608052601560a0527f104c026d540c259c7c6ab1bebddfeeb8d990d075a71169ac5e6975eeb6d477f460c052603160e05260805160a05160c05160e051615c6b6100dd5f395f81816101af015261090101525f61018d01525f8181605b01528181609401528181610100015281816101d101528181610a2f01528181610b3c01528181610bdb01528181610c0901528181610c8f01528181611523015281816115d2015281816116050152818161180f01528181612b480152612e4b01525f5050615c6b5ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b366004615434565b610054565b604051901515815260200160405180910390f35b5f5f61007f7f00000000000000000000000000000000000000000000000000000000000000006102ed565b905061008c81602061550c565b85146100ed577f0000000000000000000000000000000000000000000000000000000000000000856100bf83602061550c565b6040516359895a5360e01b815260048101939093526024830191909152604482015260640160405180910390fd5b5f6100f66103e3565b90505f61012488887f00000000000000000000000000000000000000000000000000000000000000006103f8565b9050601082604001516101379190615523565b85146101565760405163fa06659360e01b815260040160405180910390fd5b60405163995bf45760e01b81525f9073__$e6391f3e4b1839f34ea5577896c8005de7$__9063995bf457906101f99085908b908b907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906004016156a1565b610be060405180830381865af4158015610215573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023991906159b7565b90506102898787808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050855185516060810151608090910151919350915060016108ab565b815160a001526102998282610a12565b6102b6576040516313f8744360e31b815260040160405180910390fd5b6102c1828483610bc7565b6102de576040516352ec174560e11b815260040160405180910390fd5b50600198975050505050505050565b5f806102fb6002600861550c565b90506103096002600461550c565b6103139082615a61565b9050600161032260098561550c565b61032c919061550c565b6103369082615a61565b90506103446001602961550c565b61034e9082615a61565b905061035c6001600361550c565b6103669082615a61565b905061037360018461550c565b61037d9082615a61565b905061038b6001600461550c565b6103959082615a61565b905060026103a4600185615523565b6103ae919061550c565b6103b89082615a61565b90506103c560028061550c565b6103cf9082615a61565b90506103dc601082615a61565b9392505050565b6103eb614f80565b6103f3611c09565b905090565b61040061510a565b5f805b60108110156104625761042f86838761041d602083615a61565b9261042a93929190615a74565b612543565b8351826010811061044257610442615a9b565b6020020181815250506020826104589190615a61565b9150600101610403565b50610486858286610474604083615a61565b9261048193929190615a74565b612556565b6020830152610496604082615a61565b90506104a9858286610474604083615a61565b6040808401919091526104bc9082615a61565b90506104cf858286610474604083615a61565b60608301526104df604082615a61565b90506104f2858286610474604083615a61565b60a0830152610502604082615a61565b9050610515858286610474604083615a61565b60c0830152610525604082615a61565b9050610538858286610474604083615a61565b6080830152610548604082615a61565b905061055b858286610474604083615a61565b60e083015261056b604082615a61565b905061057e858286610474604083615a61565b61010083015261058f604082615a61565b90506105a2858286610474604083615a61565b610120830151526105b4604082615a61565b90506105c785828661041d602083615a61565b6101408301526105d8602082615a61565b90505f5b83811015610656575f5b600981101561064d5761060087848861041d602083615a61565b84610160015183601c811061061757610617615a9b565b6020020151826009811061062d5761062d615a9b565b6020020181815250506020836106439190615a61565b92506001016105e6565b506001016105dc565b505f5b60298110156106aa5761067386838761041d602083615a61565b836101800151826029811061068a5761068a615a9b565b6020020181815250506020826106a09190615a61565b9150600101610659565b506106bc85828661041d602083615a61565b6101a08301526106cd602082615a61565b90506106e0858286610474604083615a61565b610120830151602001526106f5604082615a61565b9050610708858286610474604083615a61565b61012083015160026020020152610720604082615a61565b9050610733858286610474604083615a61565b6101c0830152610744604082615a61565b905061075785828661041d602083615a61565b6101e0830152610768602082615a61565b90505f5b610777600185615523565b8110156107c05761078f868387610474604083615a61565b83610200015182601b81106107a6576107a6615a9b565b60200201526107b6604083615a61565b915060010161076c565b505f5b83811015610813576107dc86838761041d602083615a61565b83610220015182601c81106107f3576107f3615a9b565b6020020181815250506020826108099190615a61565b91506001016107c3565b505f5b60048110156108675761083086838761041d602083615a61565b836102400151826004811061084757610847615a9b565b60200201818152505060208261085d9190615a61565b9150600101610816565b50610879858286610474604083615a61565b61026083015261088a604082615a61565b905061089d858286610474604083615a61565b610280830152509392505050565b5f600180826108d8866108d3896108ce6108c98a6310000000615a61565b6125d8565b6125f0565b61260b565b90505f6108f6876108f18a6108ce6108c98b6001615a61565b612624565b90505f5b61092560107f0000000000000000000000000000000000000000000000000000000000000000615523565b811015610992575f61094f8c838151811061094257610942615a9b565b602002602001015161264c565b905061095f866108ce868461260b565b955061096f856108ce858461260b565b945061097b848b61260b565b9350610987838b612624565b9250506001016108fa565b505f5b60108110156109f9575f8a82601081106109b1576109b1615a9b565b602002015190506109c6866108ce868461260b565b95506109d6856108ce858461260b565b94506109e2848b61260b565b93506109ee838b612624565b925050600101610995565b50610a048484612661565b9a9950505050505050505050565b5f5f610a2783606001518561014001516125f0565b905060015f5b7f0000000000000000000000000000000000000000000000000000000000000000811015610b19575f86610160015182601c8110610a6d57610a6d615a9b565b602002015180519091505f90610a8b908360015b602002015161260b565b9050848114610aad576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c8110610ac457610ac4615a9b565b60200201519050610ad5838261266f565b9550610b09856108ce60016108d3856108ce8e604001518b601c8110610afd57610afd615a9b565b60200201516001612624565b9450505050806001019050610a2d565b505f610b33866101800151865f01518760200151856127d1565b9050600160025b7f0000000000000000000000000000000000000000000000000000000000000000811015610b9057610b8682886080015183601c8110610b7c57610b7c615a9b565b60200201516125f0565b9150600101610b3a565b50610bb6610ba3836108ce600185612624565b6108d3896101a0015189606001516125f0565b91508382145b979650505050505050565b5f610bd06151f3565b5f610bff8460c001517f000000000000000000000000000000000000000000000000000000000000000061284a565b90505f6003610c2f7f00000000000000000000000000000000000000000000000000000000000000006024615a61565b610c399190615a61565b610c44906003615a61565b6001600160401b03811115610c5b57610c5b615868565b604051908082528060200260200182016040528015610c84578160200160208202803683370190505b5090505f6003610cb57f00000000000000000000000000000000000000000000000000000000000000006024615a61565b610cbf9190615a61565b610cca906003615a61565b6001600160401b03811115610ce157610ce1615868565b604051908082528060200260200182016040528015610d1a57816020015b610d07615263565b815260200190600190039081610cff5790505b509050610d4d610d48876101000151855f81518110610d3b57610d3b615a9b565b6020026020010151612624565b612913565b84610120018181525050610d82610d48876101000151855f81518110610d7557610d75615a9b565b602002602001015161260b565b610140850181905261012085015160e0880151610da3926108d391906125f0565b845260c0860151610dd390610db790612913565b6108ce8661012001516108f18a60e001518961014001516125f0565b6020850152815160019083905f90610ded57610ded615a9b565b602002602001018181525050876102600151815f81518110610e1157610e11615a9b565b60209081029190910101526101e088015160c085015260a080870151908501528351610e3c90612983565b60408501526020840151610e4f90612983565b60608501526040840151825183906001908110610e6e57610e6e615a9b565b60209081029190910101525f5b6024811015610f1557610e9685604001518660a001516125f0565b83610ea2836002615a61565b81518110610eb257610eb2615a9b565b602002602001018181525050610eef8560c001516108d38b61018001518460298110610ee057610ee0615a9b565b60200201518860a001516125f0565b60c086015260a08086015190880151610f0891906125f0565b60a0860152600101610e7b565b505f5b6005811015610fe3575f610f2d601e83615a61565b90505f610f3b602484615a61565b9050610f6c858381518110610f5257610f52615a9b565b60200260200101516108d389606001518a60a001516125f0565b858381518110610f7e57610f7e615a9b565b602002602001018181525050610fbb8760c001516108d38d61018001518460298110610fac57610fac615a9b565b60200201518a60a001516125f0565b60c088015260a080880151908a0151610fd491906125f0565b60a08801525050600101610f18565b50876101c0015181600181518110610ffd57610ffd615a9b565b602002602001018190525086606001518160028151811061102057611020615a9b565b602002602001018190525086608001518160038151811061104357611043615a9b565b60200260200101819052508660a001518160048151811061106657611066615a9b565b60200260200101819052508660c001518160058151811061108957611089615a9b565b60200260200101819052508660e00151816006815181106110ac576110ac615a9b565b6020026020010181905250866101000151816007815181106110d0576110d0615a9b565b6020026020010181905250866101200151816008815181106110f4576110f4615a9b565b60200260200101819052508661014001518160098151811061111857611118615a9b565b602002602001018190525086610160015181600a8151811061113c5761113c615a9b565b6020026020010181905250866101c0015181600b8151811061116057611160615a9b565b602002602001018190525086610180015181600c8151811061118457611184615a9b565b6020026020010181905250866101a0015181600d815181106111a8576111a8615a9b565b6020026020010181905250866101e0015181600e815181106111cc576111cc615a9b565b602002602001018190525086610200015181600f815181106111f0576111f0615a9b565b60200260200101819052508661022001518160108151811061121457611214615a9b565b60200260200101819052508661024001518160118151811061123857611238615a9b565b60200260200101819052508661026001518160128151811061125c5761125c615a9b565b60200260200101819052508661028001518160138151811061128057611280615a9b565b6020026020010181905250866102a00151816014815181106112a4576112a4615a9b565b6020026020010181905250866102c00151816015815181106112c8576112c8615a9b565b6020026020010181905250866102e00151816016815181106112ec576112ec615a9b565b60200260200101819052508661030001518160178151811061131057611310615a9b565b60200260200101819052508661032001518160188151811061133457611334615a9b565b60200260200101819052508661034001518160198151811061135857611358615a9b565b602002602001018190525086610360015181601a8151811061137c5761137c615a9b565b602002602001018190525086610380015181601b815181106113a0576113a0615a9b565b6020026020010181905250866103a0015181601c815181106113c4576113c4615a9b565b6020026020010181905250866103c0015181601d815181106113e8576113e8615a9b565b6020026020010181905250876020015181601e8151811061140b5761140b615a9b565b6020026020010181905250876040015181601f8151811061142e5761142e615a9b565b602002602001018190525087606001518160208151811061145157611451615a9b565b602002602001018190525087608001518160218151811061147457611474615a9b565b60200260200101819052508761010001518160228151811061149857611498615a9b565b60200260200101819052508760e00151816023815181106114bb576114bb615a9b565b60200260200101819052508760a00151816024815181106114de576114de615a9b565b60200260200101819052508760c001518160258151811061150157611501615a9b565b60200260200101819052505f61154787608001518660c001518b6102200151877f0000000000000000000000000000000000000000000000000000000000000000612995565b9050611571815f8151811061155e5761155e615a9b565b60200260200101518661012001516125f0565b608086018190526102208a01515160e08901516115a292916108d39161159791906125f0565b8861014001516125f0565b608086015260e08701516115b590612af3565b60a08601525f6115c760246002615a61565b90505f5b6115f660017f0000000000000000000000000000000000000000000000000000000000000000615523565b811015611807575f61162960017f0000000000000000000000000000000000000000000000000000000000000000615523565b8210159050806117985761165d610d488b61010001518985600161164d9190615a61565b81518110610d3b57610d3b615a9b565b6101208901526101008a015161168d90610d48908961167d866001615a61565b81518110610d7557610d75615a9b565b61014089015260a08801516101208901516116a891906125f0565b61016089015260a088015160e08b01516116d0916116c5916125f0565b8961014001516125f0565b61018089018190526116f3906116e590612983565b6108d38a6101600151612983565b866116fe8486615a61565b8151811061170e5761170e615a9b565b6020026020010181815250505f6117478961018001518e61022001518560016117379190615a61565b601c8110610b7c57610b7c615a9b565b9050611781816108d38b6101600151888760016117649190615a61565b8151811061177457611774615a9b565b60200260200101516125f0565b905061179189608001518261260b565b60808a0152505b6117b76117ad8960a001518c60e001516125f0565b8b60e001516125f0565b60a08901526102008c015182601b81106117d3576117d3615a9b565b6020020151856117e38486615a61565b815181106117f3576117f3615a9b565b6020908102919091010152506001016115cb565b5061183360017f0000000000000000000000000000000000000000000000000000000000000000615523565b61183d9082615a61565b905061185d6118558961010001518a60c00151612624565b600190612661565b60e08701515261010088015160c08901516118a191611855916108f1907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76906125f0565b60e0878101805160200192909252815180516040909101529051805160609091015260a0870151908901516118e3916118d9916125f0565b8960e001516125f0565b60a08701525f5b6004811015611991575f61191c8860e00151836004811061190d5761190d615a9b565b60200201518960a001516125f0565b905061192781612983565b886101000151836004811061193e5761193e615a9b565b602002015260a088015160e08b015161195791906125f0565b8860a001818152505061198388608001516108d3838f61024001518660048110610b7c57610b7c615a9b565b6080890152506001016118ea565b506101008601515184518590839081106119ad576119ad615a9b565b602090810291909101810191909152610100870151908101516119d1916002610a81565b846119dd836001615a61565b815181106119ed576119ed615a9b565b60209081029190910101526101008601516060015184611a0e836002615a61565b81518110611a1e57611a1e615a9b565b60209081029190910101525f5b6003811015611a80578a61012001518160038110611a4b57611a4b615a9b565b60200201518483611a5b81615aaf565b945081518110611a6d57611a6d615a9b565b6020908102919091010152600101611a2b565b506040518060400160405280600181526020016002815250838281518110611aaa57611aaa615a9b565b60200260200101819052508560800151848280611ac690615aaf565b935081518110611ad857611ad8615a9b565b602002602001018181525050611b028a61024001518960c001518a608001518d6101a00151612afe565b611b1f5760405163a2a2ac8360e01b815260040160405180910390fd5b5f8a6102800151905080848381518110611b3b57611b3b615a9b565b6020026020010181905250886101000151858381518110611b5e57611b5e615a9b565b602002602001018181525050611b7261527b565b611b7c8587612e3b565b8152611b8782612f57565b602082018190528c5182515f92611b9f929190612f9d565b90505f5f611baf8f5f0151613023565b91509150611bbc826130e4565b611bc5816130e4565b8351611bd2908385613143565b84526020840151611be4908285613143565b602085018190528451611bf691613172565b9f9e505050505050505050505050505050565b611c11614f80565b50604080516103e0810182526220000081526015602080830191909152603182840152825180840184527f1c6a4310d6ac26389fbc1a4f69f189eaf4df307d610299401033fdb08560485881527f056f2430f80290a16e2a838a1f017809e4211189eb6627747a8bc339669e285c818301526060830152825180840184527f1474cafc9edda8f5eadf966fd16238235410b51c4bf9d5451b6066ac892941cc81527f200aaabc514fba3089ca52fe019e6c78dc2d6991095003397c5fa494b34df2e5818301526080830152825180840184527f1a0e33ec74f1fb9b98fa453d23fa931f02fffbdfe1b887601138e7e1640b779681527f300e5523f753fdb53688683b5378dd2eafd8567fee5cbeeb7901a6510dd8a48b8183015260a0830152825180840184527f15e36a7d8420b6384517e2bac0a70aa4d73bd46b09ffeb3315fb0465b07fafd081527f05c2eabc83c66c5ef0ac245baad9f226203d0ba403dc651d41d7d253423c5dd68183015260c0830152825180840184527f17e475af11465af1fe078c086d150d8b26d2e163bcc68599afa8c2fdc841673181527f023a936fae0b682ea2f457317ceb18d734446711cd90c476f192615de01a60e68183015260e0830152825180840184527f0a6ef9c8f09a8d1e17a067a0c08e931f1d0c681b7a7544e8c433dfe859a9a5df81527f0e5487d3540e5a37906ca339b947f1bd1f8a7ff5fe7c65dca53406452036ccc981830152610100830152825180840184527f2908804831a6fe78780f1a30dd07d8e6325805c4d10b789541650b83fce14dcd81527f25ba822e045da000a72c4bd49d18272e7b5ef17f06af25877d2c947f6a6efe9f81830152610120830152825180840184527f28341a92384c2028f39b32948d63785a4fc5a0737f034fa9836f1e5b1b45276d81527f2442e212d325ddb6477ff41e6727ff7739f06dbc765458a972a6471ab73ed26781830152610140830152825180840184527f0e9f44a0a67be5e49d477088e067dcc1d97d01aefb12853af2bf2772d9b9770a81527f0ba20c4b7cb1a1247c635c1bb033da99118b0ff5435b2e8786119dc18a23204181830152610160830152825180840184527f2f656eb60ae010f5ac4204e6a3347b9bb20ebbf529e4aecb2b7d4d3e1b4a4c2281527f0df6c706551cfe34924ba1565ae45c47f889976e606e8b20d8199e471ed24a6e81830152610180830152825180840184527f1ba7f5c51d32334cdae6a5cff746225e5b88bdef47e31020ed8f77da795a8e8781527f03fa15ddd5c67e5ad9de105038d810d77ea99a91e0095401e3cd4b641337cdf4818301526101a0830152825180840184527f01e4695abaca0d24796e5b12795736a577646a315107507dd47227c8801fee8e81527f041b5fa9e2eb289c2b22a5fe45a407e888cc8324aeb83d5243a584504757f594818301526101c0830152825180840184527f12ba890d6500035c2421f9ce4ba8b3f49142341870a061dcec351c51a30dd3cf81527f29e447c1e9087a9006aaa9844a0a4a65b395ba815e64ac7847122f6403e4fef1818301526101e0830152825180840184527f123bc1545ac5a5a6c8f95456c9d40297ac5e728df6ad7ad149a7d547e3e9762181527f0cf780a57f06212937fb5dcf84d288e75fbf4feeb26584813d21d2694f5a765481830152610200830152825180840184527f0eb38cbcb9524df7b950b651c8bf64aa06ee9420ff74b8c13e242e1d61f3f29181527f1e2b72f6420c7f28cf36883849a237b55235ab8de20f7a55865e5e55dc32c36781830152610220830152825180840184527f07be38ed489ea9f14999f38f0681d2d26ee8df1f3527c7f73534fccf0761d58581527f1a65713cb0b7f27f906acc1ccca074da7debde5a29224038ee2e434083f0f50281830152610240830152825180840184527f1caa2b03618d2cb71ae9ddc4d0d8e8021e59f3620ddb86116c9bb802e8a66d8c81527f255ca5d3a06b7595a7b384ef5c543b8c39612045259e9a85dc45b51fb9748ef581830152610260830152825180840184527f09bfded3efdeb6a51522a5d3e3f3750da123c09328ca0174986ab6fac9e11fa481527f166a28b35419b78cc2822538fc1bb023d45a30b92e74934acad95737e65795cc81830152610280830152825180840184527f153ea4c9c31188d36ffd6126bf869f8764d33324ae56a078beba01629185e97c81527f1ec94511b7fe3e28a3a0d1f5d22d5755874093444d915266219aa8e6767a9b1b818301526102a0830152825180840184527f2da4c60e0f3ecb9cfb19721df84644997ae4dcc23e5995ba96c371b45898284a81527f1733c59e5b59a482a4a3960d14f9845edf831b8144d8a0026314aaa177697765818301526102c0830152825180840184527f22468c3b7fb0da5b0b634a726562bb1869d5c60098765a88a9c0069fd9f506e681527f014a436367acb0f7265ae061bdb0a602785105478cdce11cffff6d848b46ec1f818301526102e0830152825180840184527f20916218052db91206da5b1e5f3fe60b5596187b22a297b09455a197849f5ee481527f0a85ff4c91b15151f713e633eb62a554f9c7dcdce407cac84f17a3788dbbf88b81830152610300830152825180840184527f1df848681c58738d9e319128e0906f2291ee52aa94179591c920a26c1901713e81527f3053d98d6fe5bbcae2631bc943e3095765c74b357b68c6f9c57e6d8ec704ded281830152610320830152825180840184527eff5d6fa0aaf2e5b858ff35a37ff9f58d45c464ea643d1823d669cd6260f82581527f2e94ec5c97eab43a669e50237d17fe18a20d298ee739e67c881a4cb45faeba2681830152610340830152825180840184527f181f20e92a3c7cade54c0982bafb159a202ed82fa04933000d5e94eff296a2d781527f0808bd14174de924a4063cf1daa44c1f701c09694851359cabd5d965f8ddac6781830152610360830152825180840184527f085b1f3adaf6cd18fc8165e58ce5f4d19bc60351464511db4082380d9923907381527f07c44418f8e36725093e6551f018913a34d05c92457ee6dbcaf069b313a5fe8b8183015261038083015282518084018452600181526002818301526103a083015282518084019093527f29ec476231242bfc60ab1fdc0183072bdb6b93bae8a75fff00bac01c61ba837683527f1212d342a601844c7d351c9da6a7bfb7dd69b9a89b8177fb7e67d94dfa0f8964908301526103c081019190915290565b5f6103dc6125518385615ac7565b61264c565b61255e615263565b60408051808201909152805f516020615bb65f395f51905f5261258460205f8789615a74565b61258d91615ac7565b6125979190615ae4565b81526020908101905f516020615bb65f395f51905f52906125bc906040908789615a74565b6125c591615ac7565b6125cf9190615ae4565b90529392505050565b5f5f516020615bf65f395f51905f52825b0692915050565b5f5f516020615bf65f395f51905f5282840990505b92915050565b5f5f516020615bf65f395f51905f528284089392505050565b5f5f516020615bf65f395f51905f52825f516020615bf65f395f51905f520384089392505050565b5f5f516020615bf65f395f51905f52826125e9565b5f6103dc836108ce84612913565b5f5f604051806101200160405280619d8081526020015f516020615c165f395f51905f5281526020016105a081526020015f516020615b965f395f51905f52815260200161024081526020015f516020615b965f395f51905f5281526020016105a081526020015f516020615c165f395f51905f528152602001619d8081525090505f600190505f5f90505b600981101561271c57612712826108ce8784612624565b91506001016126fb565b5061272561528e565b5f5b600981101561277657612757610d4885836009811061274857612748615a9b565b60200201516108ce8985612624565b82826009811061276957612769615a9b565b6020020152600101612727565b505f5b60098110156127bc576127b2856108d389846009811061279b5761279b615a9b565b6020020151858560098110610b7c57610b7c615a9b565b9450600101612779565b506127c784836125f0565b9695505050505050565b5f6127da6152ad565b6127e5868285613366565b6127f186868386613512565b6127fd868683866136fe565b612808868285613923565b612813868285613b17565b61281f86868386613e60565b61282a86828561430c565b61283586828561471e565b612840868285614adf565b6127c78185614ddf565b60605f826001600160401b0381111561286557612865615868565b60405190808252806020026020018201604052801561288e578160200160208202803683370190505b50905083815f815181106128a4576128a4615a9b565b602090810291909101015260015b8381101561290b576128e6826128c9600184615523565b815181106128d9576128d9615a9b565b6020026020010151612af3565b8282815181106128f8576128f8615a9b565b60209081029190910101526001016128b2565b509392505050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f516020615bf65f395f51905f520360808201525f516020615bf65f395f51905f5260a082015260205f60c08360055afa8061296f575f5ffd5b505f51608091909101604052949350505050565b5f516020615bf65f395f51905f520390565b60605f826001600160401b038111156129b0576129b0615868565b6040519080825280602002602001820160405280156129d9578160200160208202803683370190505b509050825b8015612ae8575f856129f1600184615523565b81518110612a0157612a01615a9b565b602002602001015190505f89600184612a1a9190615523565b601c8110612a2a57612a2a615a9b565b602002015190505f612a85612a49612a42858d6125f0565b60026125f0565b6108f18b612a58600189615523565b601c8110612a6857612a68615a9b565b60200201516108ce612a7f886108ce60018a612624565b87612624565b9050612aa6816108ce610d48612aa0876108ce600189612624565b8661260b565b99508990508085612ab8600187615523565b81518110612ac857612ac8615a9b565b60200260200101818152505050505080612ae190615b03565b90506129de565b509695505050505050565b5f61260582836125f0565b5f600181612b17612b1187610100614e38565b83612624565b905080612b375760405163835eb8f760e01b815260040160405180910390fd5b612b3f6152cc565b80518390525f5b7f0000000000000000000000000000000000000000000000000000000000000000811015612c28575f612b7a82600961550c565b612b85906001615a61565b905084835f0151826101008110612b9e57612b9e615a9b565b60200201525f612baf826001615a61565b90505b612bbd600983615a61565b811015612c1e578351612bfd90612bd5600184615523565b6101008110612be657612be6615a9b565b60200201518a85601c8110610b7c57610b7c615a9b565b8451826101008110612c1157612c11615a9b565b6020020152600101612bb2565b5050600101612b46565b50608081018390525f602082018190525b610100811015612d2657612c5a612c5483608001518a6125f0565b85612624565b8260a00151826101008110612c7157612c71615a9b565b602002015260a0820151612c9b90826101008110612c9157612c91615a9b565b6020020151612913565b8260a00151826101008110612cb257612cb2615a9b565b602002018181525050612cf882602001516108d3845f0151846101008110612cdc57612cdc615a9b565b60200201518560a00151856101008110610b7c57610b7c615a9b565b60208301526080820151612d19905f516020615bd65f395f51905f526125f0565b6080830152600101612c39565b505f612d37836108ce610100612913565b9050612d478260200151826125f0565b602083015260a0820151612d62905f5b6020020151826125f0565b604083015260a0820151612d8e90612d7d6001610100615523565b6101008110612d5757612d57615a9b565b60608301526040820151612da4908a6002610b7c565b60c08301819052612df1906108d3612dc98b5f516020615bd65f395f51905f52612624565b60208d015160408e01516108ce91612de091612624565b8e5160208901516108f191906125f0565b60c083018190526060830151612e2691612e1a916108d3906108ce8e600260200201518c612624565b6108f1858c6003610b7c565b60c08301819052159998505050505050505050565b612e43615263565b5f6003612e717f00000000000000000000000000000000000000000000000000000000000000006024615a61565b612e7b9190615a61565b612e86906003615a61565b90505f5b81811015612ebc57612eb4858281518110612ea757612ea7615a9b565b60200260200101516130e4565b600101612e8a565b50604051600190815b60018401811015612f215760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa90921691600101612ec5565b5080518452602081015160208501525080612f4f576040516352ec174560e11b815260040160405180910390fd5b505092915050565b612f5f615263565b5f516020615bb65f395f51905f5282602001515f516020615bb65f395f51905f52612f8a9190615523565b612f949190615ae4565b60208301525090565b5f5f5f612fa986613023565b91509150612fb5615310565b82518152602080840151818301528251604080840191909152838201516060840152875160808401528782015160a0840152865160c08401528682015160e084015251610bbc9161300891849101615b18565b6040516020818303038152906040528051906020012061264c565b61302b615263565b613033615263565b82516020808501516040860151606087015160cc90811b608892831b604494851b90961795909517949094178652608087015160a088015160c089015160e08a0151871b90841b91851b9092171717868401526101008701516101208801516101408901516101608a0151871b90841b91851b909217171785526101808701516101a08801516101c08901516101e09099015190951b9790911b9390911b1791909117939093179281019290925291565b805160208201515f5f516020615bb65f395f51905f528380095f516020615bb65f395f51905f5260035f516020615bb65f395f51905f52838709085f516020615bb65f395f51905f52848509149150508061313d575f5ffd5b50505050565b61314b615263565b613153615263565b61315d8386614e99565b90506131698185614eef565b95945050505050565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b0316836040516133089190615b4c565b5f60405180830381855afa9150503d805f8114613340576040519150601f19603f3d011682016040523d82523d5f602084013e613345565b606091505b50915091508180156127c75750808060200190518101906127c79190615b62565b5f613372846007614f50565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f6133d36133cd6133a7856003612624565b6108ce6133c26133b78b5f614f50565b6108ce8c601d614f50565b6108ce8b601c614f50565b836125f0565b90506134546134496134306134176133fe856108d36133f38d6002614f50565b6108ce8e601c614f50565b6108d361340c8c6003614f50565b6108ce8d601d614f50565b6108d36134258b6004614f50565b6108ce8c601e614f50565b6108d361343e8a6005614f50565b6108ce8b601f614f50565b6108d3886001614f50565b9050613473816108d3613468866001612624565b6108ce8a6027614f50565b905061347f81846125f0565b905061348b81856125f0565b8552505f90506134c56134bb6134b06134a588601c614f50565b6108d389601f614f50565b6108f1886024614f50565b6108d3875f614f50565b90506134d6816108ce846002612624565b90506134e7816108ce846001612624565b90506134f381836125f0565b90506134ff81846125f0565b9050808460015b60200201525050505050565b5f5f5f61354861353e61352689601c614f50565b6108d36135348b6012614f50565b8a606001516125f0565b876080015161260b565b9050613581816108ce61357761355f8b601d614f50565b6108d361356d8d6013614f50565b8c606001516125f0565b896080015161260b565b90506135a6816108ce6135776135988b601e614f50565b6108d361356d8d6014614f50565b90506135cb816108ce6135776135bd8b601f614f50565b6108d361356d8d6015614f50565b92505f90506135ef61353e6135e189601c614f50565b6108d36135348b600e614f50565b9050613614816108ce6135776136068b601d614f50565b6108d361356d8d600f614f50565b9050613639816108ce61357761362b8b601e614f50565b6108d361356d8d6010614f50565b905061365e816108ce6135776136508b601f614f50565b6108d361356d8d6011614f50565b91505f905061368561367f613674896020614f50565b6108d38a601a614f50565b846125f0565b90506136ba816108f16136b461369c8b6028614f50565b6108d36136aa8d601b614f50565b8c60a001516125f0565b856125f0565b90506136c681856125f0565b6040860152505f6136e96136b46136de89601b614f50565b6108ce8a6028614f50565b9050808560035b602002015250505050505050565b5f5f61375c61374461372c6137176135778a6016614f50565b6108d36137258b6017614f50565b8a516125f0565b6108d361373a8a6018614f50565b89602001516125f0565b6108d3613752896019614f50565b88604001516125f0565b91505f61379361377a61377089601c614f50565b886080015161260b565b6108d36137888a6003614f50565b6108ce8b6024614f50565b90505f6137bc6137a489601d614f50565b6108d36137b18b5f614f50565b6108ce8c6025614f50565b90505f6137e66137cd8a601e614f50565b6108d36137db8c6001614f50565b6108ce8d6026614f50565b905061382561380d6137ff856108d3868d5f01516125f0565b6108d3848c602001516125f0565b6108d361381b8c6004614f50565b8b604001516125f0565b93505050505f61383961367f886021614f50565b90505f61384a61367f896021614f50565b90505f61388261386961385e8b6023614f50565b6108d38c6006614f50565b6108f16138778c6023614f50565b6108ce8d6006614f50565b90505f6138a0612b1161389587896125f0565b6108ce8d6021614f50565b90506138ac81886125f0565b90505f6138d46138c66138c08d6006614f50565b876125f0565b6108f16138c08e6022614f50565b90505f6138e28c6023614f50565b90505f6138f2612b1183846125f0565b60808c0185905260a08c01849052905061390c818b6125f0565b8b6006602002015250505050505050505050505050565b5f61392f5f6001612624565b90505f61393d5f6002612624565b90505f61394b5f6003612624565b90505f61396761395c88601d614f50565b6108f189601c614f50565b90505f61398361397889601e614f50565b6108f18a601d614f50565b90505f61399f6139948a601f614f50565b6108f18b601e614f50565b90505f6139bb6139b08b6024614f50565b6108f18c601f614f50565b9050836139cc816108ce818b61260b565b90506139dc816108ce878a61260b565b90506139ec816108ce878961260b565b90506139fd816108ce8d6008614f50565b9050613a09818a6125f0565b60e08b01525082613a1e816108ce818b61260b565b9050613a2e816108ce868a61260b565b9050613a3e816108ce868961260b565b9050613a4f816108ce8d6008614f50565b9050613a5b818a6125f0565b6101008b01525081613a71816108ce818b61260b565b9050613a81816108ce858a61260b565b9050613a91816108ce858961260b565b9050613aa2816108ce8d6008614f50565b9050613aae818a6125f0565b6101208b01525080613ac4816108ce818b61260b565b9050613ad4816108ce848a61260b565b9050613ae4816108ce848961260b565b9050613af5816108ce8d6008614f50565b9050613b01818a6125f0565b610140909a019990995250505050505050505050565b613b506040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613b5b84601d614f50565b8152613b6884601e614f50565b6020820152613b78846024614f50565b6040820152613b88846027614f50565b6060820152613b98846026614f50565b6080820152613ba8846025614f50565b60a08201525f613bb9856002614f50565b90505f613bc6865f614f50565b90505f613bda8460400151855f0151612624565b90505f613bef856020015186602001516125f0565b606086015190915086905f90613c0590806125f0565b90505f613c23613c1d89602001518a606001516125f0565b886125f0565b90505f613c42613c3b8a60a001518b6040015161260b565b8a5161260b565b9050613c516138c082886125f0565b9050613c78613c72613c6c613c668487612624565b88612624565b8461260b565b8361260b565b9050613ca0613c95613c8a83876125f0565b6108ce8f6009614f50565b6108ce60018a612624565b6101608c015250505050602085015160808601515f91613cbf9161260b565b90505f613cdd613cd38860600151886125f0565b8860200151612624565b90505f613d01613ced84876125f0565b6108d36136b48b60a001518c5f0151612624565b9050613d29613d1e613d13838c6125f0565b6108ce8e6009614f50565b6108ce600189612624565b6101808b0152505f9150613d4a9050613d4383601161260b565b87516125f0565b90505f613d57838461260b565b9050613d63818261260b565b90505f613d718360096125f0565b9050613d9a613d9461367f613d8d8b60a001518c5f015161260b565b8b5161260b565b82612624565b60c089018190525f90613db590613c1d90613c8a908d6125f0565b9050613dc88b600b60200201518261260b565b6101608c0152505086515f9250613def9150613d4390613de8908061260b565b885161260b565b90505f613e2f613e0a836108ce8a5f01518b60a00151612624565b60208901516108f190613e1d908061260b565b6108ce8b602001518c6080015161260b565b9050613e4c89600c60200201516108d3613c1d613c8a858d6125f0565b89600c602002015250505050505050505050565b613eca604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613ee2613ed886601e614f50565b85604001516125f0565b808252613f01906108d3613ef788601d614f50565b87602001516125f0565b808252613f16906108d3613d4388601c614f50565b808252613f28906108d3876001614f50565b80825260208201819052613f41906108f187601f614f50565b8152613f5c613f51866024614f50565b6108f187601c614f50565b6080820152613f7a613f6f866027614f50565b6108f187601f614f50565b60608201526080810151613f93906108ce816001612624565b6101c08201526080810151613fd390613fc990613fc2906108ce60015f516020615bf65f395f51905f52615523565b600161260b565b82606001516125f0565b60a0820181905261400990613ffb906108ce613ff0896002614f50565b6108ce8a6003614f50565b6108ce6136b488600a614f50565b83600e60200201526101c081015161402d90613ffb906108ce613ff0896002614f50565b6101e08401528051614052906108ce614047886002614f50565b6108ce896003614f50565b6101208201525f61407161406787601f614f50565b8360200151612624565b9050614082816108ce836001612624565b60e083015261409f614095876026614f50565b86604001516125f0565b604083018190526140c2906108d36140b8896025614f50565b88602001516125f0565b604083018190526140e2906108d36140db896024614f50565b88516125f0565b60408301526140ff6140f5876027614f50565b8360400151612624565b60408301525f61411e614113886026614f50565b6108f189601e614f50565b905061417061414b6133cd613fc2866080015160015f516020615bf65f395f51905f526108ce9190615523565b6108ce613fc2866040015160015f516020615bf65f395f51905f526108ce9190615523565b60c084015260408301516141929061418890806125f0565b8460400151612624565b61010084015260c08301516141be906141b0906108ce8a6004614f50565b6108ce6138c08a600a614f50565b6102008601526101c08301516141dd906141b0906108ce8a6004614f50565b6102208601526101008301516141fc906141b0906108ce8a6004614f50565b61024086015260e0830151614216906108ce896004614f50565b61014084015261423561422a886025614f50565b6108f189601d614f50565b6101608401526080830151614273906141139061426890613fc2906108ce60015f516020615bf65f395f51905f52615523565b8561016001516125f0565b61018084018190526101208401516101a085018190526142aa916108d3906108ce61429f8c6005614f50565b6108ce8d6002614f50565b6101a0840181905283516142ca91906108d3906108ce61429f8c5f614f50565b6101a084018190526101408401516142e2919061260b565b6101a084018190526142fc906108ce6138c08a600a614f50565b6101a0840181905285600d6136f0565b6143456040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61437a61436161435686601c614f50565b6108ce876025614f50565b6108d361436f876024614f50565b6108ce88601d614f50565b81526143bf6143b461439b61439087601c614f50565b6108ce88601f614f50565b6108d36143a988601d614f50565b6108ce89601e614f50565b6108f1866026614f50565b604082018190526143d490600160441b6125f0565b604082018190526143ea906108f1866027614f50565b6040820181905281516143fd919061260b565b60408201819052614413906108ce866005614f50565b6040820152805161442890600160441b6125f0565b808252614448906108d361443d876024614f50565b6108ce886025614f50565b8082526020820181905261446f906108f161446487601e614f50565b6108d388601f614f50565b60208201819052614485906108ce866004614f50565b60208201528051606082018190526144a2906108d386601f614f50565b606082018190526144c6906108f16144bb876026614f50565b6108d3886027614f50565b606082018190526144db906108ce865f614f50565b8160600181815250505f6145046144fa8360200151846040015161260b565b836060015161260b565b9050614515816108ce876003614f50565b905061452d614525866025614f50565b6140006125f0565b60808301819052614543906108d3876024614f50565b60808301819052614556906140006125f0565b6080830181905261456c906108d387601e614f50565b6080830181905261457f906140006125f0565b60808301819052614595906108d387601d614f50565b608083018190526145a8906140006125f0565b608083018190526145be906108d387601c614f50565b608083018190526145d4906108f187601f614f50565b608083018190526145ea906108ce876005614f50565b60808301526145fd614525866026614f50565b60a08301819052614613906108d3876025614f50565b60a08301819052614626906140006125f0565b60a0830181905261463c906108d3876024614f50565b60a0830181905261464f906140006125f0565b60a08301819052614665906108d387601f614f50565b60a08301819052614678906140006125f0565b60a0830181905261468e906108d387601e614f50565b60a083018190526146a4906108f1876027614f50565b60a083018190526146b9906108ce875f614f50565b60a0830181905260808301515f916146d1919061260b565b90506146e2816108ce886004614f50565b90506146ee828261260b565b60c08401819052614707906108ce6138c089600b614f50565b60c084018190528560136020020152505050505050565b6147946040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6147ad6147a285601c614f50565b6108d3866002614f50565b81526147c86147bd85601d614f50565b6108d3866003614f50565b60208201526147e66147db85601e614f50565b6108d3866004614f50565b60408201526148046147f985601f614f50565b6108d3866005614f50565b606082015280516148369061482f906148289061482190806125f0565b84516125f0565b83516125f0565b82516125f0565b608082015260208101516148749061486a906148609061485690806125f0565b84602001516125f0565b83602001516125f0565b82602001516125f0565b60a082015260408101516148b2906148a89061489e9061489490806125f0565b84604001516125f0565b83604001516125f0565b82604001516125f0565b60c082015260608101516148e690613fc9906148dc906148d290806125f0565b84606001516125f0565b83606001516125f0565b60e0820152608081015160a08201516148ff919061260b565b61010082015260c081015160e0820151614919919061260b565b61012082015260a081015161493d90614932908061260b565b82610120015161260b565b61014082015260e081015161496190614956908061260b565b82610100015161260b565b610160820152610120810151614977908061260b565b6101e082018190526149989061498d908061260b565b82610160015161260b565b6101e08201526101008101516149ae908061260b565b6101a082018190526149cf906149c4908061260b565b82610140015161260b565b6101a082018190526101608201516149e69161260b565b6101808201526101408101516101e0820151614a02919061260b565b6101c0820152614a166133cd85600c614f50565b6102008201819052610280840151610180830151614a41926108d3916108ce906108f18a6024614f50565b8360146020020152614a7183601560200201516108d38361020001516108ce856101a001516108f18a6025614f50565b8360156020020152614aa183601660200201516108d38361020001516108ce856101c001516108f18a6026614f50565b8360166020020152614ad183601760200201516108d38361020001516108ce856101e001516108f18a6027614f50565b836017602002015250505050565b614b316040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f6040518060800160405280614b667f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e76125d8565b8152602001614b947f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b6125d8565b8152602001614bc17e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac156125d8565b8152602001614bef7f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b6125d8565b90529050614c0c614c0186601c614f50565b6108d3876002614f50565b6101208301819052614c4b90614c4090614c3590614c2a90806125f0565b8561012001516125f0565b8461012001516125f0565b8361012001516125f0565b8252614c5885601d614f50565b6020830152614c6885601e614f50565b6040830152614c7885601f614f50565b606083015281516020830151614ca0916144fa91614c96919061260b565b846040015161260b565b6080830152614cb361367f86600d614f50565b6101408301528151614cd490614cca90835f610b7c565b836080015161260b565b60a0830152614d0084601860200201516108d38461014001516108ce8660a001516108f18b6024614f50565b6103008501526020820151614d1b90614cca90836001610b7c565b60c0830152614d4784601960200201516108d38461014001516108ce8660c001516108f18b6025614f50565b6103208501526040820151614d6290614cca90836002610b7c565b60e0830152614d8e84601a60200201516108d38461014001516108ce8660e001516108f18b6026614f50565b6103408501526060820151614da990614cca90836003610b7c565b610100830152614dd784601b60200201516108d38461014001516108ce8661010001516108f18b6027614f50565b84601b613506565b815160015b601c811015614e3157614e27826108d38684601c8110614e0657614e06615a9b565b602002015186614e17600187615523565b601b8110610b7c57610b7c615a9b565b9150600101614de4565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f516020615bf65f395f51905f5260a082015260205f60c08360055afa80614e84575f5ffd5b505f5160809190910160405295945050505050565b614ea1615263565b614ea9615263565b604051835181526020840151602082015284604082015260408160608360075afa80614ed3575f5ffd5b5080518252602080820151908301526060016040529392505050565b614ef7615263565b614eff615263565b6040518451815260208501516020820152835160408201526020840151606082015260408160808360065afa80614f34575f5ffd5b5080518252602080820151908301526080016040529392505050565b5f82826028811115614f6457614f64615b81565b60298110614f7457614f74615a9b565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f8152602001614fa6615263565b8152602001614fb3615263565b8152602001614fc0615263565b8152602001614fcd615263565b8152602001614fda615263565b8152602001614fe7615263565b8152602001614ff4615263565b8152602001615001615263565b815260200161500e615263565b815260200161501b615263565b8152602001615028615263565b8152602001615035615263565b8152602001615042615263565b815260200161504f615263565b815260200161505c615263565b8152602001615069615263565b8152602001615076615263565b8152602001615083615263565b8152602001615090615263565b815260200161509d615263565b81526020016150aa615263565b81526020016150b7615263565b81526020016150c4615263565b81526020016150d1615263565b81526020016150de615263565b81526020016150eb615263565b81526020016150f8615263565b8152602001615105615263565b905290565b604051806102a0016040528061511e61532f565b815260200161512b615263565b8152602001615138615263565b8152602001615145615263565b8152602001615152615263565b815260200161515f615263565b815260200161516c615263565b8152602001615179615263565b8152602001615186615263565b815260200161519361534e565b81526020015f81526020016151a661537b565b81526020016151b36153a9565b81526020015f81526020016151c6615263565b81526020015f81526020016151d96153c8565b81526020016151e66152ad565b81526020016150eb6153f6565b604051806101c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020016152316153f6565b815260200161523e6153f6565b81526020015f81526020015f81526020015f81526020015f8152602001606081525090565b60405180604001604052805f81526020015f81525090565b60405180604001604052806150f8615263565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b6040518060e001604052806152df615414565b81526020015f81526020015f81526020015f81526020015f8152602001615304615414565b81526020015f81525090565b6040518061010001604052806008906020820280368337509192915050565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b615365615263565b81526020019060019003908161535d5790505090565b604051806103800160405280601c905b61539361528e565b81526020019060019003908161538b5790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b6153e0615263565b8152602001906001900390816153d85790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215615447575f5ffd5b84356001600160401b0381111561545c575f5ffd5b8501601f8101871361546c575f5ffd5b80356001600160401b03811115615481575f5ffd5b876020828401011115615492575f5ffd5b6020918201955093508501356001600160401b038111156154b1575f5ffd5b8501601f810187136154c1575f5ffd5b80356001600160401b038111156154d6575f5ffd5b8760208260051b84010111156154ea575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417612605576126056154f8565b81810381811115612605576126056154f8565b805f5b601081101561313d578151845260209384019390910190600101615539565b80518252602090810151910152565b805f5b600381101561313d5761557e848351615558565b604093909301926020919091019060010161556a565b805f5b601c81101561313d578151845f5b60098110156155c45782518252602092830192909101906001016155a5565b505050610120939093019260209190910190600101615597565b805f5b602981101561313d5781518452602093840193909101906001016155e1565b805f5b601b81101561313d57615617848351615558565b6040939093019260209190910190600101615603565b805f5b601c81101561313d578151845260209384019390910190600101615630565b805f5b600481101561313d578151845260209384019390910190600101615652565b8183525f6001600160fb1b03831115615688575f5ffd5b8260051b80836020870137939093016020019392505050565b6156ac818851615536565b5f60208801516156c0610200840182615558565b5060408801516156d4610240840182615558565b5060608801516156e8610280840182615558565b5060808801516156fc6102c0840182615558565b5060a0880151615710610300840182615558565b5060c0880151615724610340840182615558565b5060e0880151615738610380840182615558565b5061010088015161574d6103c0840182615558565b50610120880151615762610400840182615567565b506101408801516104c08301526101608801516157836104e0840182615594565b506101808801516157986124608401826155de565b506101a08801516129808301526101c08801516157b96129a0840182615558565b506101e08801516129e08301526102008801516157da612a00840182615600565b506102208801516157ef6130c084018261562d565b5061024088015161580461344084018261564f565b506102608801516158196134c0840182615558565b5061028088015161582e613500840182615558565b506135c06135408301526158476135c083018789615671565b613560830195909552506135808101929092526135a0909101529392505050565b634e487b7160e01b5f52604160045260245ffd5b60405161014081016001600160401b038111828210171561589f5761589f615868565b60405290565b604051601f8201601f191681016001600160401b03811182821017156158cd576158cd615868565b604052919050565b5f60c082840312156158e5575f5ffd5b60405160c081016001600160401b038111828210171561590757615907615868565b604090815283518252602080850151908301528381015190820152606080840151908201526080808401519082015260a0928301519281019290925250919050565b5f82601f830112615958575f5ffd5b5f610360615965816158a5565b915083018185821115615976575f5ffd5b845b82811015615990578051825260209182019101615978565b509195945050505050565b5f82601f8301126159aa575f5ffd5b5f610380615965816158a5565b5f610be08284031280156159c9575f5ffd5b506159d261587c565b6159dc84846158d5565b81526159eb8460c08501615949565b60208201526159fe84610420850161599b565b60408201526107a08301516060820152615a1c846107c0850161599b565b6080820152610b4083015160a0820152610b6083015160c0820152610b8083015160e0820152610ba0830151610100820152610bc09092015161012083015250919050565b80820180821115612605576126056154f8565b5f5f85851115615a82575f5ffd5b83861115615a8e575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f60018201615ac057615ac06154f8565b5060010190565b80356020831015612605575f19602084900360031b1b1692915050565b5f82615afe57634e487b7160e01b5f52601260045260245ffd5b500690565b5f81615b1157615b116154f8565b505f190190565b5f8183825b6008811015615b3c578151835260209283019290910190600101615b1d565b5050506101008201905092915050565b5f82518060208501845e5f920191825250919050565b5f60208284031215615b72575f5ffd5b815180151581146103dc575f5ffd5b634e487b7160e01b5f52602160045260245ffdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a2646970667358221220c680257a2197e413ced6921e6422d97ec73c24b10cf6d79a03d071717d3ab72b64736f6c634300081d0033 \ No newline at end of file diff --git a/eth/contracts/noir/agg_agg_HonkVerifier.linkrefs.json b/eth/contracts/noir/agg_agg_HonkVerifier.linkrefs.json new file mode 100644 index 0000000..a0f2895 --- /dev/null +++ b/eth/contracts/noir/agg_agg_HonkVerifier.linkrefs.json @@ -0,0 +1,10 @@ +{ + "agg_agg.sol": { + "ZKTranscriptLib": [ + { + "length": 20, + "start": 580 + } + ] + } +} diff --git a/eth/contracts/noir/agg_agg_ZKTranscriptLib.bin b/eth/contracts/noir/agg_agg_ZKTranscriptLib.bin new file mode 100644 index 0000000..68c17d0 --- /dev/null +++ b/eth/contracts/noir/agg_agg_ZKTranscriptLib.bin @@ -0,0 +1 @@ +61172c610034600b8282823980515f1a607314602857634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c8063995bf45714610038575b5f5ffd5b61004b6100463660046111f8565b610061565b604051610058919061143a565b60405180910390f35b610069610d5a565b5f610078888888888886610128565b9083529050610087818961017c565b6020840191909152905061009b818461026b565b604084019190915290506100af8189610314565b606084019190915290506100c4888285610375565b608084019190915290506100d88882610444565b60a084019190915290506100ed888285610647565b60c084019190915290506101028882856107b9565b60e08401919091529050610116888261093b565b50610100830152509695505050505050565b610130610dbf565b5f61013e8888888888610978565b60408601919091526020850191909152908352925061015d8389610c71565b6080850191909152606084019190915291989197509095505050505050565b610184610def565b5f61018d610e0e565b84815260e08401805151602080840191909152905181015160408084019190915261010086018051516060850152518201516080840152516101f0916101d59184910161150f565b60405160208183030381529060405280519060200120610cfc565b91505f6101fc83610d0f565b50808552905060015b6102116001601c611556565b8110156102615761024285610227600184611556565b601b8110610237576102376114fb565b602002015183610d3f565b8582601b8110610254576102546114fb565b6020020152600101610205565b5050509250929050565b610273610e2c565b5f61028a846040516020016101d591815260200190565b935061029584610d0f565b50825260015b8381101561030c576102ed836102b2600184611556565b601c81106102c2576102c26114fb565b6020020151846102d3600185611556565b601c81106102e3576102e36114fb565b6020020151610d3f565b8382601c81106102ff576102ff6114fb565b602002015260010161029b565b509093915050565b5f5f61031e610e4b565b84815261012084018051515160208084019190915290515181015160408084019190915261014086015160608401525161035e916101d591849101611569565b915061036982610d0f565b50959194509092505050565b61037d610e2c565b5f805b8381101561043a57610390610e69565b8581525f5b60098110156103f95787610160015183601c81106103b5576103b56114fb565b602002015181600981106103cb576103cb6114fb565b6020020151826103dc83600161159c565b600a81106103ec576103ec6114fb565b6020020152600101610395565b5061040e816040516020016101d591906115af565b955061041986610d0f565b508483601c811061042c5761042c6114fb565b602002015250600101610380565b5090949293505050565b5f5f61044e610e88565b83815260015b602981116104ab5761018086015161046d600183611556565b6029811061047d5761047d6114fb565b6020020151828260328110610494576104946114fb565b6020020152806104a3816115e3565b915050610454565b856101a001518282603281106104c3576104c36114fb565b60200201526104d360018261159c565b61012087015160200151519091508282603281106104f3576104f36114fb565b6020020152610120860151600160200201516020015182826001610517919061159c565b60328110610527576105276114fb565b602002015261053760028261159c565b6101208701516040015151909150828260328110610557576105576114fb565b602002015261012086015160026020020151602001518282600161057b919061159c565b6032811061058b5761058b6114fb565b602002015261059b60028261159c565b6101c0870151519091508282603281106105b7576105b76114fb565b602002018181525050856101c0015160200151828260016105d8919061159c565b603281106105e8576105e86114fb565b60200201526105f860028261159c565b9050856101e00151828260328110610612576106126114fb565b60200201818152505061062f826040516020016101d591906115fb565b925061063a83610d0f565b5096929550919350505050565b5f8080610655600185611556565b61066090600261162f565b61066b90600161159c565b6001600160401b0381111561068257610682610ee3565b6040519080825280602002602001820160405280156106ab578160200160208202803683370190505b50905084815f815181106106c1576106c16114fb565b60209081029190910101525f5b6106d9600186611556565b81101561078c5786610200015181601b81106106f7576106f76114fb565b6020020151518261070983600261162f565b61071490600161159c565b81518110610724576107246114fb565b60200260200101818152505086610200015181601b8110610747576107476114fb565b6020020151602001518282600261075e919061162f565b61076990600261159c565b81518110610779576107796114fb565b60209081029190910101526001016106ce565b506107a1816040516020016101d59190611646565b91506107ac82610d0f565b5096919550909350505050565b5f80806107c784600161159c565b6107d290600461159c565b6001600160401b038111156107e9576107e9610ee3565b604051908082528060200260200182016040528015610812578160200160208202803683370190505b50905084815f81518110610828576108286114fb565b602090810291909101015260015b8481116108925761022087015161084e600183611556565b601c811061085e5761085e6114fb565b6020020151828281518110610875576108756114fb565b60209081029190910101528061088a816115e3565b915050610836565b505f806108a086600161159c565b90505b6108ae86600461159c565b811161090d5787610240015182600481106108cb576108cb6114fb565b60200201518382815181106108e2576108e26114fb565b6020908102919091010152816108f7816115e3565b9250508080610905906115e3565b9150506108a3565b50610922826040516020016101d59190611646565b925061092d83610d0f565b509792965091945050505050565b5f5f610945610ea7565b838152610260850180515160208084019190915290518101516040808401919091525161035e916101d591849101611670565b5f8080808061098886600161159c565b61099390600661159c565b6001600160401b038111156109aa576109aa610ee3565b6040519080825280602002602001820160405280156109d3578160200160208202803683370190505b509050865f1b815f815181106109eb576109eb6114fb565b60209081029190910101525f5b610a03601088611556565b811015610a5457898982818110610a1c57610a1c6114fb565b9050602002013582826001610a31919061159c565b81518110610a4157610a416114fb565b60209081029190910101526001016109f8565b505f5b6010811015610ac5578a51610a7f908260108110610a7757610a776114fb565b602002015190565b82826010610a8e8b600161159c565b610a989190611556565b610aa2919061159c565b81518110610ab257610ab26114fb565b6020908102919091010152600101610a57565b5060208a01515181610ad888600161159c565b81518110610ae857610ae86114fb565b6020908102919091018101919091528a810151015181610b0988600161159c565b610b1490600161159c565b81518110610b2457610b246114fb565b602090810291909101015260408a01515181610b4188600161159c565b610b4c90600261159c565b81518110610b5c57610b5c6114fb565b60209081029190910181019190915260408b0151015181610b7e88600161159c565b610b8990600361159c565b81518110610b9957610b996114fb565b602090810291909101015260608a01515181610bb688600161159c565b610bc190600461159c565b81518110610bd157610bd16114fb565b60209081029190910181019190915260608b0151015181610bf388600161159c565b610bfe90600561159c565b81518110610c0e57610c0e6114fb565b602002602001018181525050610c2e816040516020016101d59190611646565b9150610c3982610d0f565b6040805160208101869052929750909550610c5491016101d5565b9150610c5f82610d0f565b50809350505095509550955095915050565b5f5f5f610c7c610ec5565b85815260a0858101805151602080850191909152905181015160408085019190915260c08089018051516060870152518301516080808701919091528901805151948601949094529251820151928401929092529051610ce2916101d5918491016116a3565b9150610ced82610d0f565b90979096509194509092505050565b5f5160206116d75f395f51905f52900690565b5f80826001600160801b038116608082901c610d2a82610cfc565b9450610d3581610cfc565b9350505050915091565b5f5f5160206116d75f395f51905f5282840990505b92915050565b604051806101400160405280610d6e610dbf565b8152602001610d7b610def565b8152602001610d88610e2c565b81526020015f8152602001610d9b610e2c565b81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806103600160405280601b906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b604051806101400160405280600a906020820280368337509192915050565b6040518061064001604052806032906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b6040518060e001604052806007906020820280368337509192915050565b634e487b7160e01b5f52604160045260245ffd5b6040516102a081016001600160401b0381118282101715610f1a57610f1a610ee3565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610f4857610f48610ee3565b604052919050565b5f82601f830112610f5f575f5ffd5b5f610200610f6c81610f20565b915083018185821115610f7d575f5ffd5b845b82811015610f97578035825260209182019101610f7f565b509195945050505050565b5f60408284031215610fb2575f5ffd5b604080519081016001600160401b0381118282101715610fd457610fd4610ee3565b604052823581526020928301359281019290925250919050565b5f82601f830112610ffd575f5ffd5b5f6110086060610f20565b90508060c084018581111561101b575f5ffd5b845b81811015610f975761102f8782610fa2565b835260209092019160400161101d565b5f82601f83011261104e575f5ffd5b61038061105a81610f20565b905080611f8084018581111561106e575f5ffd5b845b818110156110d25786601f820112611086575f5ffd5b5f61012061109381610f20565b9150820181898211156110a4575f5ffd5b835b828110156110be5780358252602091820191016110a6565b505050845260209093019261012001611070565b509095945050505050565b5f82601f8301126110ec575f5ffd5b5f610520610f6c81610f20565b5f82601f830112611108575f5ffd5b5f61036061111581610f20565b915050806106c084018581111561112a575f5ffd5b845b81811015610f975761113e8782610fa2565b835260209092019160400161112c565b5f82601f83011261115d575f5ffd5b5f610380610f6c81610f20565b5f82601f830112611179575f5ffd5b5f6111846080610f20565b9050806080840185811115611197575f5ffd5b845b81811015610f97578035835260209283019201611199565b5f5f83601f8401126111c1575f5ffd5b5081356001600160401b038111156111d7575f5ffd5b6020830191508360208260051b85010111156111f1575f5ffd5b9250929050565b5f5f5f5f5f5f8688036135c081121561120f575f5ffd5b61354081121561121d575f5ffd5b50611226610ef7565b6112308989610f50565b8152611240896102008a01610fa2565b6020820152611253896102408a01610fa2565b6040820152611266896102808a01610fa2565b6060820152611279896102c08a01610fa2565b608082015261128c896103008a01610fa2565b60a082015261129f896103408a01610fa2565b60c08201526112b2896103808a01610fa2565b60e08201526112c5896103c08a01610fa2565b6101008201526112d9896104008a01610fee565b6101208201526104c08801356101408201526112f9896104e08a0161103f565b61016082015261130d896124608a016110dd565b6101808201526129808801356101a082015261132d896129a08a01610fa2565b6101c08201526129e08801356101e082015261134d89612a008a016110f9565b610200820152611361896130c08a0161114e565b610220820152611375896134408a0161116a565b610240820152611389896134c08a01610fa2565b61026082015261139d896135008a01610fa2565b61028082015295506135408701356001600160401b038111156113be575f5ffd5b6113ca89828a016111b1565b979a90995096976135608101359761358082013597506135a09091013595509350505050565b805f5b601b8110156114125781518452602093840193909101906001016113f3565b50505050565b805f5b601c81101561141257815184526020938401939091019060010161141b565b8151805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a09081015190820152610be08101602083015161148960c08401826113f0565b50604083015161149d610420840182611418565b5060608301516107a083015260808301516114bc6107c0840182611418565b5060a0830151610b4083015260c0830151610b6083015260e0830151610b80830152610100830151610ba083015261012090920151610bc09091015290565b634e487b7160e01b5f52603260045260245ffd5b5f8183825b6005811015611533578151835260209283019290910190600101611514565b50505060a08201905092915050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610d5457610d54611542565b5f8183825b600481101561158d57815183526020928301929091019060010161156e565b50505060808201905092915050565b80820180821115610d5457610d54611542565b5f8183825b600a8110156115d35781518352602092830192909101906001016115b4565b5050506101408201905092915050565b5f600182016115f4576115f4611542565b5060010190565b5f8183825b603281101561161f578151835260209283019290910190600101611600565b5050506106408201905092915050565b8082028115828204841417610d5457610d54611542565b81515f90829060208501835b82811015610f97578151845260209384019390910190600101611652565b5f8183825b6003811015611694578151835260209283019290910190600101611675565b50505060608201905092915050565b5f8183825b60078110156116c75781518352602092830192909101906001016116a8565b50505060e0820190509291505056fe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001a26469706673582212203a15da4b82eb4e5c8def4eeb481c7925aaa687f666b53d361e9d73dad14530c364736f6c634300081d0033 \ No newline at end of file diff --git a/eth/contracts/noir/agg_final_HonkVerifier.bin b/eth/contracts/noir/agg_final_HonkVerifier.bin new file mode 100644 index 0000000..a8d7e4f --- /dev/null +++ b/eth/contracts/noir/agg_final_HonkVerifier.bin @@ -0,0 +1 @@ +610100604052348015610010575f5ffd5b5062100000608052601460a0527f016b9de0462c1d2eb19e66c7f3a664c426e094540f08b0e5587cb3471eeea0dc60c0526103fb60e05260805160a05160c05160e051615c6d6100de5f395f81816101af015261090101525f61018d01525f8181605b01528181609401528181610100015281816101d101528181610a2f01528181610b3c01528181610bdb01528181610c0901528181610c8f01528181611523015281816115d2015281816116050152818161180f01528181612b4a0152612e4d01525f5050615c6d5ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b366004615436565b610054565b604051901515815260200160405180910390f35b5f5f61007f7f00000000000000000000000000000000000000000000000000000000000000006102ed565b905061008c81602061550e565b85146100ed577f0000000000000000000000000000000000000000000000000000000000000000856100bf83602061550e565b6040516359895a5360e01b815260048101939093526024830191909152604482015260640160405180910390fd5b5f6100f66103e3565b90505f61012488887f00000000000000000000000000000000000000000000000000000000000000006103f8565b9050601082604001516101379190615525565b85146101565760405163fa06659360e01b815260040160405180910390fd5b60405163995bf45760e01b81525f9073__$2f5a92e8fad307fcff564f42e0970a8df6$__9063995bf457906101f99085908b908b907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906004016156a3565b610be060405180830381865af4158015610215573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061023991906159b9565b90506102898787808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050855185516060810151608090910151919350915060016108ab565b815160a001526102998282610a12565b6102b6576040516313f8744360e31b815260040160405180910390fd5b6102c1828483610bc7565b6102de576040516352ec174560e11b815260040160405180910390fd5b50600198975050505050505050565b5f806102fb6002600861550e565b90506103096002600461550e565b6103139082615a63565b9050600161032260098561550e565b61032c919061550e565b6103369082615a63565b90506103446001602961550e565b61034e9082615a63565b905061035c6001600361550e565b6103669082615a63565b905061037360018461550e565b61037d9082615a63565b905061038b6001600461550e565b6103959082615a63565b905060026103a4600185615525565b6103ae919061550e565b6103b89082615a63565b90506103c560028061550e565b6103cf9082615a63565b90506103dc601082615a63565b9392505050565b6103eb614f82565b6103f3611c09565b905090565b61040061510c565b5f805b60108110156104625761042f86838761041d602083615a63565b9261042a93929190615a76565b612545565b8351826010811061044257610442615a9d565b6020020181815250506020826104589190615a63565b9150600101610403565b50610486858286610474604083615a63565b9261048193929190615a76565b612558565b6020830152610496604082615a63565b90506104a9858286610474604083615a63565b6040808401919091526104bc9082615a63565b90506104cf858286610474604083615a63565b60608301526104df604082615a63565b90506104f2858286610474604083615a63565b60a0830152610502604082615a63565b9050610515858286610474604083615a63565b60c0830152610525604082615a63565b9050610538858286610474604083615a63565b6080830152610548604082615a63565b905061055b858286610474604083615a63565b60e083015261056b604082615a63565b905061057e858286610474604083615a63565b61010083015261058f604082615a63565b90506105a2858286610474604083615a63565b610120830151526105b4604082615a63565b90506105c785828661041d602083615a63565b6101408301526105d8602082615a63565b90505f5b83811015610656575f5b600981101561064d5761060087848861041d602083615a63565b84610160015183601c811061061757610617615a9d565b6020020151826009811061062d5761062d615a9d565b6020020181815250506020836106439190615a63565b92506001016105e6565b506001016105dc565b505f5b60298110156106aa5761067386838761041d602083615a63565b836101800151826029811061068a5761068a615a9d565b6020020181815250506020826106a09190615a63565b9150600101610659565b506106bc85828661041d602083615a63565b6101a08301526106cd602082615a63565b90506106e0858286610474604083615a63565b610120830151602001526106f5604082615a63565b9050610708858286610474604083615a63565b61012083015160026020020152610720604082615a63565b9050610733858286610474604083615a63565b6101c0830152610744604082615a63565b905061075785828661041d602083615a63565b6101e0830152610768602082615a63565b90505f5b610777600185615525565b8110156107c05761078f868387610474604083615a63565b83610200015182601b81106107a6576107a6615a9d565b60200201526107b6604083615a63565b915060010161076c565b505f5b83811015610813576107dc86838761041d602083615a63565b83610220015182601c81106107f3576107f3615a9d565b6020020181815250506020826108099190615a63565b91506001016107c3565b505f5b60048110156108675761083086838761041d602083615a63565b836102400151826004811061084757610847615a9d565b60200201818152505060208261085d9190615a63565b9150600101610816565b50610879858286610474604083615a63565b61026083015261088a604082615a63565b905061089d858286610474604083615a63565b610280830152509392505050565b5f600180826108d8866108d3896108ce6108c98a6310000000615a63565b6125da565b6125f2565b61260d565b90505f6108f6876108f18a6108ce6108c98b6001615a63565b612626565b90505f5b61092560107f0000000000000000000000000000000000000000000000000000000000000000615525565b811015610992575f61094f8c838151811061094257610942615a9d565b602002602001015161264e565b905061095f866108ce868461260d565b955061096f856108ce858461260d565b945061097b848b61260d565b9350610987838b612626565b9250506001016108fa565b505f5b60108110156109f9575f8a82601081106109b1576109b1615a9d565b602002015190506109c6866108ce868461260d565b95506109d6856108ce858461260d565b94506109e2848b61260d565b93506109ee838b612626565b925050600101610995565b50610a048484612663565b9a9950505050505050505050565b5f5f610a2783606001518561014001516125f2565b905060015f5b7f0000000000000000000000000000000000000000000000000000000000000000811015610b19575f86610160015182601c8110610a6d57610a6d615a9d565b602002015180519091505f90610a8b908360015b602002015161260d565b9050848114610aad576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c8110610ac457610ac4615a9d565b60200201519050610ad58382612671565b9550610b09856108ce60016108d3856108ce8e604001518b601c8110610afd57610afd615a9d565b60200201516001612626565b9450505050806001019050610a2d565b505f610b33866101800151865f01518760200151856127d3565b9050600160025b7f0000000000000000000000000000000000000000000000000000000000000000811015610b9057610b8682886080015183601c8110610b7c57610b7c615a9d565b60200201516125f2565b9150600101610b3a565b50610bb6610ba3836108ce600185612626565b6108d3896101a0015189606001516125f2565b91508382145b979650505050505050565b5f610bd06151f5565b5f610bff8460c001517f000000000000000000000000000000000000000000000000000000000000000061284c565b90505f6003610c2f7f00000000000000000000000000000000000000000000000000000000000000006024615a63565b610c399190615a63565b610c44906003615a63565b6001600160401b03811115610c5b57610c5b61586a565b604051908082528060200260200182016040528015610c84578160200160208202803683370190505b5090505f6003610cb57f00000000000000000000000000000000000000000000000000000000000000006024615a63565b610cbf9190615a63565b610cca906003615a63565b6001600160401b03811115610ce157610ce161586a565b604051908082528060200260200182016040528015610d1a57816020015b610d07615265565b815260200190600190039081610cff5790505b509050610d4d610d48876101000151855f81518110610d3b57610d3b615a9d565b6020026020010151612626565b612915565b84610120018181525050610d82610d48876101000151855f81518110610d7557610d75615a9d565b602002602001015161260d565b610140850181905261012085015160e0880151610da3926108d391906125f2565b845260c0860151610dd390610db790612915565b6108ce8661012001516108f18a60e001518961014001516125f2565b6020850152815160019083905f90610ded57610ded615a9d565b602002602001018181525050876102600151815f81518110610e1157610e11615a9d565b60209081029190910101526101e088015160c085015260a080870151908501528351610e3c90612985565b60408501526020840151610e4f90612985565b60608501526040840151825183906001908110610e6e57610e6e615a9d565b60209081029190910101525f5b6024811015610f1557610e9685604001518660a001516125f2565b83610ea2836002615a63565b81518110610eb257610eb2615a9d565b602002602001018181525050610eef8560c001516108d38b61018001518460298110610ee057610ee0615a9d565b60200201518860a001516125f2565b60c086015260a08086015190880151610f0891906125f2565b60a0860152600101610e7b565b505f5b6005811015610fe3575f610f2d601e83615a63565b90505f610f3b602484615a63565b9050610f6c858381518110610f5257610f52615a9d565b60200260200101516108d389606001518a60a001516125f2565b858381518110610f7e57610f7e615a9d565b602002602001018181525050610fbb8760c001516108d38d61018001518460298110610fac57610fac615a9d565b60200201518a60a001516125f2565b60c088015260a080880151908a0151610fd491906125f2565b60a08801525050600101610f18565b50876101c0015181600181518110610ffd57610ffd615a9d565b602002602001018190525086606001518160028151811061102057611020615a9d565b602002602001018190525086608001518160038151811061104357611043615a9d565b60200260200101819052508660a001518160048151811061106657611066615a9d565b60200260200101819052508660c001518160058151811061108957611089615a9d565b60200260200101819052508660e00151816006815181106110ac576110ac615a9d565b6020026020010181905250866101000151816007815181106110d0576110d0615a9d565b6020026020010181905250866101200151816008815181106110f4576110f4615a9d565b60200260200101819052508661014001518160098151811061111857611118615a9d565b602002602001018190525086610160015181600a8151811061113c5761113c615a9d565b6020026020010181905250866101c0015181600b8151811061116057611160615a9d565b602002602001018190525086610180015181600c8151811061118457611184615a9d565b6020026020010181905250866101a0015181600d815181106111a8576111a8615a9d565b6020026020010181905250866101e0015181600e815181106111cc576111cc615a9d565b602002602001018190525086610200015181600f815181106111f0576111f0615a9d565b60200260200101819052508661022001518160108151811061121457611214615a9d565b60200260200101819052508661024001518160118151811061123857611238615a9d565b60200260200101819052508661026001518160128151811061125c5761125c615a9d565b60200260200101819052508661028001518160138151811061128057611280615a9d565b6020026020010181905250866102a00151816014815181106112a4576112a4615a9d565b6020026020010181905250866102c00151816015815181106112c8576112c8615a9d565b6020026020010181905250866102e00151816016815181106112ec576112ec615a9d565b60200260200101819052508661030001518160178151811061131057611310615a9d565b60200260200101819052508661032001518160188151811061133457611334615a9d565b60200260200101819052508661034001518160198151811061135857611358615a9d565b602002602001018190525086610360015181601a8151811061137c5761137c615a9d565b602002602001018190525086610380015181601b815181106113a0576113a0615a9d565b6020026020010181905250866103a0015181601c815181106113c4576113c4615a9d565b6020026020010181905250866103c0015181601d815181106113e8576113e8615a9d565b6020026020010181905250876020015181601e8151811061140b5761140b615a9d565b6020026020010181905250876040015181601f8151811061142e5761142e615a9d565b602002602001018190525087606001518160208151811061145157611451615a9d565b602002602001018190525087608001518160218151811061147457611474615a9d565b60200260200101819052508761010001518160228151811061149857611498615a9d565b60200260200101819052508760e00151816023815181106114bb576114bb615a9d565b60200260200101819052508760a00151816024815181106114de576114de615a9d565b60200260200101819052508760c001518160258151811061150157611501615a9d565b60200260200101819052505f61154787608001518660c001518b6102200151877f0000000000000000000000000000000000000000000000000000000000000000612997565b9050611571815f8151811061155e5761155e615a9d565b60200260200101518661012001516125f2565b608086018190526102208a01515160e08901516115a292916108d39161159791906125f2565b8861014001516125f2565b608086015260e08701516115b590612af5565b60a08601525f6115c760246002615a63565b90505f5b6115f660017f0000000000000000000000000000000000000000000000000000000000000000615525565b811015611807575f61162960017f0000000000000000000000000000000000000000000000000000000000000000615525565b8210159050806117985761165d610d488b61010001518985600161164d9190615a63565b81518110610d3b57610d3b615a9d565b6101208901526101008a015161168d90610d48908961167d866001615a63565b81518110610d7557610d75615a9d565b61014089015260a08801516101208901516116a891906125f2565b61016089015260a088015160e08b01516116d0916116c5916125f2565b8961014001516125f2565b61018089018190526116f3906116e590612985565b6108d38a6101600151612985565b866116fe8486615a63565b8151811061170e5761170e615a9d565b6020026020010181815250505f6117478961018001518e61022001518560016117379190615a63565b601c8110610b7c57610b7c615a9d565b9050611781816108d38b6101600151888760016117649190615a63565b8151811061177457611774615a9d565b60200260200101516125f2565b905061179189608001518261260d565b60808a0152505b6117b76117ad8960a001518c60e001516125f2565b8b60e001516125f2565b60a08901526102008c015182601b81106117d3576117d3615a9d565b6020020151856117e38486615a63565b815181106117f3576117f3615a9d565b6020908102919091010152506001016115cb565b5061183360017f0000000000000000000000000000000000000000000000000000000000000000615525565b61183d9082615a63565b905061185d6118558961010001518a60c00151612626565b600190612663565b60e08701515261010088015160c08901516118a191611855916108f1907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76906125f2565b60e0878101805160200192909252815180516040909101529051805160609091015260a0870151908901516118e3916118d9916125f2565b8960e001516125f2565b60a08701525f5b6004811015611991575f61191c8860e00151836004811061190d5761190d615a9d565b60200201518960a001516125f2565b905061192781612985565b886101000151836004811061193e5761193e615a9d565b602002015260a088015160e08b015161195791906125f2565b8860a001818152505061198388608001516108d3838f61024001518660048110610b7c57610b7c615a9d565b6080890152506001016118ea565b506101008601515184518590839081106119ad576119ad615a9d565b602090810291909101810191909152610100870151908101516119d1916002610a81565b846119dd836001615a63565b815181106119ed576119ed615a9d565b60209081029190910101526101008601516060015184611a0e836002615a63565b81518110611a1e57611a1e615a9d565b60209081029190910101525f5b6003811015611a80578a61012001518160038110611a4b57611a4b615a9d565b60200201518483611a5b81615ab1565b945081518110611a6d57611a6d615a9d565b6020908102919091010152600101611a2b565b506040518060400160405280600181526020016002815250838281518110611aaa57611aaa615a9d565b60200260200101819052508560800151848280611ac690615ab1565b935081518110611ad857611ad8615a9d565b602002602001018181525050611b028a61024001518960c001518a608001518d6101a00151612b00565b611b1f5760405163a2a2ac8360e01b815260040160405180910390fd5b5f8a6102800151905080848381518110611b3b57611b3b615a9d565b6020026020010181905250886101000151858381518110611b5e57611b5e615a9d565b602002602001018181525050611b7261527d565b611b7c8587612e3d565b8152611b8782612f59565b602082018190528c5182515f92611b9f929190612f9f565b90505f5f611baf8f5f0151613025565b91509150611bbc826130e6565b611bc5816130e6565b8351611bd2908385613145565b84526020840151611be4908285613145565b602085018190528451611bf691613174565b9f9e505050505050505050505050505050565b611c11614f82565b50604080516103e08101825262100000815260146020808301919091526103fb82840152825180840184527f07fea1a154c2ea92bfe9bff6608105c79be2000fb533c5a7f5086f42631d002481527f072a7fa47c0445d4a3a00a17126f3d4134c5ddf94ff72fe262c3c2d36017ce54818301526060830152825180840184527f0eaf0f335934fe83217bf228608474b6e7874844976d3f606546efdabe85198e81527f2fd2b3710e51885e05066c12c867b19f6abfedb1329bd4b34c51e4edae010ed1818301526080830152825180840184527f16564b9c5794a0940a9bdb105356d4d8e7c0d2ed04fb7fe3b82e32fe70ad797681527f19f4325229ca1f419b897a9286a396923b26592fb85e1fad1e5db7b8afaa4b738183015260a0830152825180840184527f08a7d8009f6f264dac2833251dc17269967029b78cdacd33104a8f8fdb79c94081527f196750fb121848a766033747e726bdb19a4a957a483edb24f45cdf4a6abce4ad8183015260c0830152825180840184527f2668a86828ec16a70fe3c30a353eee037c19f470e1e5a2586eb47e9a3372fe3181527f13a5d44fce53d20af70a40f3c33ca60a1eab4a2907b9f74374a00099af5b308f8183015260e0830152825180840184527f05e267528bcdaaef76b87581271c147470268de2e8b9201a79a4ab9ff483c74281527f07114abaa67e3fd05d43b93d42f36cc0f650ef8f0fed3613294cc820fd8718e981830152610100830152825180840184527f15b5b0e5904efcadcef0d9c7305e0c778692a7b2f9f210b9104c213daea659a881527f0e24f0b634a1648112578318c5455cd09fb98da9822306ea7c65dc48db697ea481830152610120830152825180840184527f17846b41619ecf9273cf386c1b16e7f55fa35ec9386eb2ea216398f428379e7981527f1ac6fe092563d4e89b104cfafada05910ea6e0c0cdd0b0fd5cc58f1fad65f5d181830152610140830152825180840184527f05665cdccbda0515ceebf81f09c44fdb329181de80055bbd4249751c80280dbf81527f21286c7bbb9d4894157e2975e667d5c33e910f985863d681880648677502133f81830152610160830152825180840184527f2d2e9b5315b13f26465f33617d15b566e8d9eb9db7f2620b6fc80fa1f006fc5181527f28dd92658fa8222aef67475960ab7033a2da3b6622b2e18094deb5718ff2ea7181830152610180830152825180840184527f2130ca557da2368a359901856d4fb658e39384a611b8ff226a0a6e4492f5911881527f2ff59ab4fd220200b24946eedcd14d61acb5dd2499e6f89294af9bce971825fc818301526101a0830152825180840184527f0d046a2c7f903da415a6951e75a5381b70a0331b790c07b97ce70d34d338a72b81527f26b1f648f365eb5cbbe4c6e3244537dacfbbf95845bc38ec6895d8abbc027526818301526101c0830152825180840184527f16bfc1cbd0c6a38e201686891975e2d3a32ff2ea3e0d298a7f6b9ac55d8228cd81527f0ba7b53a836f4bf89f64e9d0ce2cb1b81b63e81589774004339507f0e8fb0720818301526101e0830152825180840184527f1dae1d5fb23ef041ac8fb25b5739ff333f941a02cf543839aa68595bed00924181527f10479380fe8d144a5e6ceec04c2271346324d911e80bbd685ccb3e5ab65bdfb581830152610200830152825180840184527f208e191dd65dfe84d1c782de58d6049c6cf080e0d85998d9306385a148250a6d81527f0254a28372e909a029e4189c42716805e9b0db5ce5b97eb7060b25472e669fc581830152610220830152825180840184527f1647261d35e5226996c3fe13de83b2a3c2d7ff1d5c94d42d5cec74c5862656d181527f2d40aad6d8245b190e2b45686ca05da2595be9e7483c75b9bcab335fd51941bc81830152610240830152825180840184527f1dfe547a651f077f580970260f0593e146c55e3874adbdc347a5039b32024d7a81527f2e5aa258ca6b4863370ae82df32001c1b0c363b72ff4e2503adf731fd3502d4b81830152610260830152825180840184527f284788e2b69fcabd417414a25ba458b5a37a7d37fea6fb298e124146e86921e481527f15cdd6ac38bbaf22615366da36733cc939e5fe95efbf3321e577df4ff7fca87781830152610280830152825180840184527f2e62626a1095231a41bdc000c7bd20c073919d40ccb4d9a36d1629902b061fcb81527f21305733d27ee6dab8c79607a8e8462df373b5f5d7429e78b62363e0ef71df95818301526102a0830152825180840184527f076dc9c7790ed478259153d69811573276e6d26536b485d4d82977c330485ac881527f2fbfea486a89022680b0e0e81ead9c56125b0066007326944a5ad05665928fcb818301526102c0830152825180840184527f1552b3c8a793524d496ac086b1c182575ad9a3249ba1aafb30110615712b8d3781527f0f68500204cd7693fd5e1f8b490c74dd7a1e556d2bad5782731d3eb4b8904147818301526102e0830152825180840184527f10ad68cb78329a5c44b13c6da53ccc16b2bdf8cc6b955161f7f6676abfa050cb81527f2643eef532153fc9853f9257031440654d9c2482299ab424ad953b72a1fdb7ae81830152610300830152825180840184527f111bc3039becaa8ca62f0bcefcd65040fe1d5bc68e929318b3f5dd767ce9822b81527f1b691e6fe2d651e8c02ab30d0b5f032addd00bbe41104a7206e2ff9d7b658a3d81830152610320830152825180840184527f0a0a54df61fecb42534ccfd8d51ee000e269a65d07d5b63227459ba189ab2f0481527f09276e284d9fcacc3201e71f779a6e66950841c2324d970c8bb2f8d6c87755e781830152610340830152825180840184527f110e7b7f4053452dae6c6d52983ed4f268823e7c2958a2967f35178675092a2981527f29df570d178d1f2aa52fd2669fd347d2d75a722175e050c90fbb00adb5d82d2f81830152610360830152825180840184527f1326d49efee0292517ce6bfbacd193969a5cb9ce2cd571cb6426f56009b8208581527f176a9c71e742c7798aea8f5e828ece04efa2abe35b8c33eff8c74ac1fafbb2de8183015261038083015282518084018452600181526002818301526103a083015282518084019093527f2f6ae80f550fc0a26f347268c7d0617869a16b8600d893ffce5e6d1dd8a010cd83527f0e64b747f724eb59221c9dec8a24b86a785fbab2feacfc82000733d2ef85d82b908301526103c081019190915290565b5f6103dc6125538385615ac9565b61264e565b612560615265565b60408051808201909152805f516020615bb85f395f51905f5261258660205f8789615a76565b61258f91615ac9565b6125999190615ae6565b81526020908101905f516020615bb85f395f51905f52906125be906040908789615a76565b6125c791615ac9565b6125d19190615ae6565b90529392505050565b5f5f516020615bf85f395f51905f52825b0692915050565b5f5f516020615bf85f395f51905f5282840990505b92915050565b5f5f516020615bf85f395f51905f528284089392505050565b5f5f516020615bf85f395f51905f52825f516020615bf85f395f51905f520384089392505050565b5f5f516020615bf85f395f51905f52826125eb565b5f6103dc836108ce84612915565b5f5f604051806101200160405280619d8081526020015f516020615c185f395f51905f5281526020016105a081526020015f516020615b985f395f51905f52815260200161024081526020015f516020615b985f395f51905f5281526020016105a081526020015f516020615c185f395f51905f528152602001619d8081525090505f600190505f5f90505b600981101561271e57612714826108ce8784612626565b91506001016126fd565b50612727615290565b5f5b600981101561277857612759610d4885836009811061274a5761274a615a9d565b60200201516108ce8985612626565b82826009811061276b5761276b615a9d565b6020020152600101612729565b505f5b60098110156127be576127b4856108d389846009811061279d5761279d615a9d565b6020020151858560098110610b7c57610b7c615a9d565b945060010161277b565b506127c984836125f2565b9695505050505050565b5f6127dc6152af565b6127e7868285613368565b6127f386868386613514565b6127ff86868386613700565b61280a868285613925565b612815868285613b19565b61282186868386613e62565b61282c86828561430e565b612837868285614720565b612842868285614ae1565b6127c98185614de1565b60605f826001600160401b038111156128675761286761586a565b604051908082528060200260200182016040528015612890578160200160208202803683370190505b50905083815f815181106128a6576128a6615a9d565b602090810291909101015260015b8381101561290d576128e8826128cb600184615525565b815181106128db576128db615a9d565b6020026020010151612af5565b8282815181106128fa576128fa615a9d565b60209081029190910101526001016128b4565b509392505050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f516020615bf85f395f51905f520360808201525f516020615bf85f395f51905f5260a082015260205f60c08360055afa80612971575f5ffd5b505f51608091909101604052949350505050565b5f516020615bf85f395f51905f520390565b60605f826001600160401b038111156129b2576129b261586a565b6040519080825280602002602001820160405280156129db578160200160208202803683370190505b509050825b8015612aea575f856129f3600184615525565b81518110612a0357612a03615a9d565b602002602001015190505f89600184612a1c9190615525565b601c8110612a2c57612a2c615a9d565b602002015190505f612a87612a4b612a44858d6125f2565b60026125f2565b6108f18b612a5a600189615525565b601c8110612a6a57612a6a615a9d565b60200201516108ce612a81886108ce60018a612626565b87612626565b9050612aa8816108ce610d48612aa2876108ce600189612626565b8661260d565b99508990508085612aba600187615525565b81518110612aca57612aca615a9d565b60200260200101818152505050505080612ae390615b05565b90506129e0565b509695505050505050565b5f61260782836125f2565b5f600181612b19612b1387610100614e3a565b83612626565b905080612b395760405163835eb8f760e01b815260040160405180910390fd5b612b416152ce565b80518390525f5b7f0000000000000000000000000000000000000000000000000000000000000000811015612c2a575f612b7c82600961550e565b612b87906001615a63565b905084835f0151826101008110612ba057612ba0615a9d565b60200201525f612bb1826001615a63565b90505b612bbf600983615a63565b811015612c20578351612bff90612bd7600184615525565b6101008110612be857612be8615a9d565b60200201518a85601c8110610b7c57610b7c615a9d565b8451826101008110612c1357612c13615a9d565b6020020152600101612bb4565b5050600101612b48565b50608081018390525f602082018190525b610100811015612d2857612c5c612c5683608001518a6125f2565b85612626565b8260a00151826101008110612c7357612c73615a9d565b602002015260a0820151612c9d90826101008110612c9357612c93615a9d565b6020020151612915565b8260a00151826101008110612cb457612cb4615a9d565b602002018181525050612cfa82602001516108d3845f0151846101008110612cde57612cde615a9d565b60200201518560a00151856101008110610b7c57610b7c615a9d565b60208301526080820151612d1b905f516020615bd85f395f51905f526125f2565b6080830152600101612c3b565b505f612d39836108ce610100612915565b9050612d498260200151826125f2565b602083015260a0820151612d64905f5b6020020151826125f2565b604083015260a0820151612d9090612d7f6001610100615525565b6101008110612d5957612d59615a9d565b60608301526040820151612da6908a6002610b7c565b60c08301819052612df3906108d3612dcb8b5f516020615bd85f395f51905f52612626565b60208d015160408e01516108ce91612de291612626565b8e5160208901516108f191906125f2565b60c083018190526060830151612e2891612e1c916108d3906108ce8e600260200201518c612626565b6108f1858c6003610b7c565b60c08301819052159998505050505050505050565b612e45615265565b5f6003612e737f00000000000000000000000000000000000000000000000000000000000000006024615a63565b612e7d9190615a63565b612e88906003615a63565b90505f5b81811015612ebe57612eb6858281518110612ea957612ea9615a9d565b60200260200101516130e6565b600101612e8c565b50604051600190815b60018401811015612f235760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa90921691600101612ec7565b5080518452602081015160208501525080612f51576040516352ec174560e11b815260040160405180910390fd5b505092915050565b612f61615265565b5f516020615bb85f395f51905f5282602001515f516020615bb85f395f51905f52612f8c9190615525565b612f969190615ae6565b60208301525090565b5f5f5f612fab86613025565b91509150612fb7615312565b82518152602080840151818301528251604080840191909152838201516060840152875160808401528782015160a0840152865160c08401528682015160e084015251610bbc9161300a91849101615b1a565b6040516020818303038152906040528051906020012061264e565b61302d615265565b613035615265565b82516020808501516040860151606087015160cc90811b608892831b604494851b90961795909517949094178652608087015160a088015160c089015160e08a0151871b90841b91851b9092171717868401526101008701516101208801516101408901516101608a0151871b90841b91851b909217171785526101808701516101a08801516101c08901516101e09099015190951b9790911b9390911b1791909117939093179281019290925291565b805160208201515f5f516020615bb85f395f51905f528380095f516020615bb85f395f51905f5260035f516020615bb85f395f51905f52838709085f516020615bb85f395f51905f52848509149150508061313f575f5ffd5b50505050565b61314d615265565b613155615265565b61315f8386614e9b565b905061316b8185614ef1565b95945050505050565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b03168360405161330a9190615b4e565b5f60405180830381855afa9150503d805f8114613342576040519150601f19603f3d011682016040523d82523d5f602084013e613347565b606091505b50915091508180156127c95750808060200190518101906127c99190615b64565b5f613374846007614f52565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f6133d56133cf6133a9856003612626565b6108ce6133c46133b98b5f614f52565b6108ce8c601d614f52565b6108ce8b601c614f52565b836125f2565b905061345661344b613432613419613400856108d36133f58d6002614f52565b6108ce8e601c614f52565b6108d361340e8c6003614f52565b6108ce8d601d614f52565b6108d36134278b6004614f52565b6108ce8c601e614f52565b6108d36134408a6005614f52565b6108ce8b601f614f52565b6108d3886001614f52565b9050613475816108d361346a866001612626565b6108ce8a6027614f52565b905061348181846125f2565b905061348d81856125f2565b8552505f90506134c76134bd6134b26134a788601c614f52565b6108d389601f614f52565b6108f1886024614f52565b6108d3875f614f52565b90506134d8816108ce846002612626565b90506134e9816108ce846001612626565b90506134f581836125f2565b905061350181846125f2565b9050808460015b60200201525050505050565b5f5f5f61354a61354061352889601c614f52565b6108d36135368b6012614f52565b8a606001516125f2565b876080015161260d565b9050613583816108ce6135796135618b601d614f52565b6108d361356f8d6013614f52565b8c606001516125f2565b896080015161260d565b90506135a8816108ce61357961359a8b601e614f52565b6108d361356f8d6014614f52565b90506135cd816108ce6135796135bf8b601f614f52565b6108d361356f8d6015614f52565b92505f90506135f16135406135e389601c614f52565b6108d36135368b600e614f52565b9050613616816108ce6135796136088b601d614f52565b6108d361356f8d600f614f52565b905061363b816108ce61357961362d8b601e614f52565b6108d361356f8d6010614f52565b9050613660816108ce6135796136528b601f614f52565b6108d361356f8d6011614f52565b91505f9050613687613681613676896020614f52565b6108d38a601a614f52565b846125f2565b90506136bc816108f16136b661369e8b6028614f52565b6108d36136ac8d601b614f52565b8c60a001516125f2565b856125f2565b90506136c881856125f2565b6040860152505f6136eb6136b66136e089601b614f52565b6108ce8a6028614f52565b9050808560035b602002015250505050505050565b5f5f61375e61374661372e6137196135798a6016614f52565b6108d36137278b6017614f52565b8a516125f2565b6108d361373c8a6018614f52565b89602001516125f2565b6108d3613754896019614f52565b88604001516125f2565b91505f61379561377c61377289601c614f52565b886080015161260d565b6108d361378a8a6003614f52565b6108ce8b6024614f52565b90505f6137be6137a689601d614f52565b6108d36137b38b5f614f52565b6108ce8c6025614f52565b90505f6137e86137cf8a601e614f52565b6108d36137dd8c6001614f52565b6108ce8d6026614f52565b905061382761380f613801856108d3868d5f01516125f2565b6108d3848c602001516125f2565b6108d361381d8c6004614f52565b8b604001516125f2565b93505050505f61383b613681886021614f52565b90505f61384c613681896021614f52565b90505f61388461386b6138608b6023614f52565b6108d38c6006614f52565b6108f16138798c6023614f52565b6108ce8d6006614f52565b90505f6138a2612b1361389787896125f2565b6108ce8d6021614f52565b90506138ae81886125f2565b90505f6138d66138c86138c28d6006614f52565b876125f2565b6108f16138c28e6022614f52565b90505f6138e48c6023614f52565b90505f6138f4612b1383846125f2565b60808c0185905260a08c01849052905061390e818b6125f2565b8b6006602002015250505050505050505050505050565b5f6139315f6001612626565b90505f61393f5f6002612626565b90505f61394d5f6003612626565b90505f61396961395e88601d614f52565b6108f189601c614f52565b90505f61398561397a89601e614f52565b6108f18a601d614f52565b90505f6139a16139968a601f614f52565b6108f18b601e614f52565b90505f6139bd6139b28b6024614f52565b6108f18c601f614f52565b9050836139ce816108ce818b61260d565b90506139de816108ce878a61260d565b90506139ee816108ce878961260d565b90506139ff816108ce8d6008614f52565b9050613a0b818a6125f2565b60e08b01525082613a20816108ce818b61260d565b9050613a30816108ce868a61260d565b9050613a40816108ce868961260d565b9050613a51816108ce8d6008614f52565b9050613a5d818a6125f2565b6101008b01525081613a73816108ce818b61260d565b9050613a83816108ce858a61260d565b9050613a93816108ce858961260d565b9050613aa4816108ce8d6008614f52565b9050613ab0818a6125f2565b6101208b01525080613ac6816108ce818b61260d565b9050613ad6816108ce848a61260d565b9050613ae6816108ce848961260d565b9050613af7816108ce8d6008614f52565b9050613b03818a6125f2565b610140909a019990995250505050505050505050565b613b526040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613b5d84601d614f52565b8152613b6a84601e614f52565b6020820152613b7a846024614f52565b6040820152613b8a846027614f52565b6060820152613b9a846026614f52565b6080820152613baa846025614f52565b60a08201525f613bbb856002614f52565b90505f613bc8865f614f52565b90505f613bdc8460400151855f0151612626565b90505f613bf1856020015186602001516125f2565b606086015190915086905f90613c0790806125f2565b90505f613c25613c1f89602001518a606001516125f2565b886125f2565b90505f613c44613c3d8a60a001518b6040015161260d565b8a5161260d565b9050613c536138c282886125f2565b9050613c7a613c74613c6e613c688487612626565b88612626565b8461260d565b8361260d565b9050613ca2613c97613c8c83876125f2565b6108ce8f6009614f52565b6108ce60018a612626565b6101608c015250505050602085015160808601515f91613cc19161260d565b90505f613cdf613cd58860600151886125f2565b8860200151612626565b90505f613d03613cef84876125f2565b6108d36136b68b60a001518c5f0151612626565b9050613d2b613d20613d15838c6125f2565b6108ce8e6009614f52565b6108ce600189612626565b6101808b0152505f9150613d4c9050613d4583601161260d565b87516125f2565b90505f613d59838461260d565b9050613d65818261260d565b90505f613d738360096125f2565b9050613d9c613d96613681613d8f8b60a001518c5f015161260d565b8b5161260d565b82612626565b60c089018190525f90613db790613c1f90613c8c908d6125f2565b9050613dca8b600b60200201518261260d565b6101608c0152505086515f9250613df19150613d4590613dea908061260d565b885161260d565b90505f613e31613e0c836108ce8a5f01518b60a00151612626565b60208901516108f190613e1f908061260d565b6108ce8b602001518c6080015161260d565b9050613e4e89600c60200201516108d3613c1f613c8c858d6125f2565b89600c602002015250505050505050505050565b613ecc604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613ee4613eda86601e614f52565b85604001516125f2565b808252613f03906108d3613ef988601d614f52565b87602001516125f2565b808252613f18906108d3613d4588601c614f52565b808252613f2a906108d3876001614f52565b80825260208201819052613f43906108f187601f614f52565b8152613f5e613f53866024614f52565b6108f187601c614f52565b6080820152613f7c613f71866027614f52565b6108f187601f614f52565b60608201526080810151613f95906108ce816001612626565b6101c08201526080810151613fd590613fcb90613fc4906108ce60015f516020615bf85f395f51905f52615525565b600161260d565b82606001516125f2565b60a0820181905261400b90613ffd906108ce613ff2896002614f52565b6108ce8a6003614f52565b6108ce6136b688600a614f52565b83600e60200201526101c081015161402f90613ffd906108ce613ff2896002614f52565b6101e08401528051614054906108ce614049886002614f52565b6108ce896003614f52565b6101208201525f61407361406987601f614f52565b8360200151612626565b9050614084816108ce836001612626565b60e08301526140a1614097876026614f52565b86604001516125f2565b604083018190526140c4906108d36140ba896025614f52565b88602001516125f2565b604083018190526140e4906108d36140dd896024614f52565b88516125f2565b60408301526141016140f7876027614f52565b8360400151612626565b60408301525f614120614115886026614f52565b6108f189601e614f52565b905061417261414d6133cf613fc4866080015160015f516020615bf85f395f51905f526108ce9190615525565b6108ce613fc4866040015160015f516020615bf85f395f51905f526108ce9190615525565b60c084015260408301516141949061418a90806125f2565b8460400151612626565b61010084015260c08301516141c0906141b2906108ce8a6004614f52565b6108ce6138c28a600a614f52565b6102008601526101c08301516141df906141b2906108ce8a6004614f52565b6102208601526101008301516141fe906141b2906108ce8a6004614f52565b61024086015260e0830151614218906108ce896004614f52565b61014084015261423761422c886025614f52565b6108f189601d614f52565b6101608401526080830151614275906141159061426a90613fc4906108ce60015f516020615bf85f395f51905f52615525565b8561016001516125f2565b61018084018190526101208401516101a085018190526142ac916108d3906108ce6142a18c6005614f52565b6108ce8d6002614f52565b6101a0840181905283516142cc91906108d3906108ce6142a18c5f614f52565b6101a084018190526101408401516142e4919061260d565b6101a084018190526142fe906108ce6138c28a600a614f52565b6101a0840181905285600d6136f2565b6143476040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61437c61436361435886601c614f52565b6108ce876025614f52565b6108d3614371876024614f52565b6108ce88601d614f52565b81526143c16143b661439d61439287601c614f52565b6108ce88601f614f52565b6108d36143ab88601d614f52565b6108ce89601e614f52565b6108f1866026614f52565b604082018190526143d690600160441b6125f2565b604082018190526143ec906108f1866027614f52565b6040820181905281516143ff919061260d565b60408201819052614415906108ce866005614f52565b6040820152805161442a90600160441b6125f2565b80825261444a906108d361443f876024614f52565b6108ce886025614f52565b80825260208201819052614471906108f161446687601e614f52565b6108d388601f614f52565b60208201819052614487906108ce866004614f52565b60208201528051606082018190526144a4906108d386601f614f52565b606082018190526144c8906108f16144bd876026614f52565b6108d3886027614f52565b606082018190526144dd906108ce865f614f52565b8160600181815250505f6145066144fc8360200151846040015161260d565b836060015161260d565b9050614517816108ce876003614f52565b905061452f614527866025614f52565b6140006125f2565b60808301819052614545906108d3876024614f52565b60808301819052614558906140006125f2565b6080830181905261456e906108d387601e614f52565b60808301819052614581906140006125f2565b60808301819052614597906108d387601d614f52565b608083018190526145aa906140006125f2565b608083018190526145c0906108d387601c614f52565b608083018190526145d6906108f187601f614f52565b608083018190526145ec906108ce876005614f52565b60808301526145ff614527866026614f52565b60a08301819052614615906108d3876025614f52565b60a08301819052614628906140006125f2565b60a0830181905261463e906108d3876024614f52565b60a08301819052614651906140006125f2565b60a08301819052614667906108d387601f614f52565b60a0830181905261467a906140006125f2565b60a08301819052614690906108d387601e614f52565b60a083018190526146a6906108f1876027614f52565b60a083018190526146bb906108ce875f614f52565b60a0830181905260808301515f916146d3919061260d565b90506146e4816108ce886004614f52565b90506146f0828261260d565b60c08401819052614709906108ce6138c289600b614f52565b60c084018190528560136020020152505050505050565b6147966040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6147af6147a485601c614f52565b6108d3866002614f52565b81526147ca6147bf85601d614f52565b6108d3866003614f52565b60208201526147e86147dd85601e614f52565b6108d3866004614f52565b60408201526148066147fb85601f614f52565b6108d3866005614f52565b60608201528051614838906148319061482a9061482390806125f2565b84516125f2565b83516125f2565b82516125f2565b608082015260208101516148769061486c906148629061485890806125f2565b84602001516125f2565b83602001516125f2565b82602001516125f2565b60a082015260408101516148b4906148aa906148a09061489690806125f2565b84604001516125f2565b83604001516125f2565b82604001516125f2565b60c082015260608101516148e890613fcb906148de906148d490806125f2565b84606001516125f2565b83606001516125f2565b60e0820152608081015160a0820151614901919061260d565b61010082015260c081015160e082015161491b919061260d565b61012082015260a081015161493f90614934908061260d565b82610120015161260d565b61014082015260e081015161496390614958908061260d565b82610100015161260d565b610160820152610120810151614979908061260d565b6101e0820181905261499a9061498f908061260d565b82610160015161260d565b6101e08201526101008101516149b0908061260d565b6101a082018190526149d1906149c6908061260d565b82610140015161260d565b6101a082018190526101608201516149e89161260d565b6101808201526101408101516101e0820151614a04919061260d565b6101c0820152614a186133cf85600c614f52565b6102008201819052610280840151610180830151614a43926108d3916108ce906108f18a6024614f52565b8360146020020152614a7383601560200201516108d38361020001516108ce856101a001516108f18a6025614f52565b8360156020020152614aa383601660200201516108d38361020001516108ce856101c001516108f18a6026614f52565b8360166020020152614ad383601760200201516108d38361020001516108ce856101e001516108f18a6027614f52565b836017602002015250505050565b614b336040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f6040518060800160405280614b687f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e76125da565b8152602001614b967f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b6125da565b8152602001614bc37e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac156125da565b8152602001614bf17f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b6125da565b90529050614c0e614c0386601c614f52565b6108d3876002614f52565b6101208301819052614c4d90614c4290614c3790614c2c90806125f2565b8561012001516125f2565b8461012001516125f2565b8361012001516125f2565b8252614c5a85601d614f52565b6020830152614c6a85601e614f52565b6040830152614c7a85601f614f52565b606083015281516020830151614ca2916144fc91614c98919061260d565b846040015161260d565b6080830152614cb561368186600d614f52565b6101408301528151614cd690614ccc90835f610b7c565b836080015161260d565b60a0830152614d0284601860200201516108d38461014001516108ce8660a001516108f18b6024614f52565b6103008501526020820151614d1d90614ccc90836001610b7c565b60c0830152614d4984601960200201516108d38461014001516108ce8660c001516108f18b6025614f52565b6103208501526040820151614d6490614ccc90836002610b7c565b60e0830152614d9084601a60200201516108d38461014001516108ce8660e001516108f18b6026614f52565b6103408501526060820151614dab90614ccc90836003610b7c565b610100830152614dd984601b60200201516108d38461014001516108ce8661010001516108f18b6027614f52565b84601b613508565b815160015b601c811015614e3357614e29826108d38684601c8110614e0857614e08615a9d565b602002015186614e19600187615525565b601b8110610b7c57610b7c615a9d565b9150600101614de6565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f516020615bf85f395f51905f5260a082015260205f60c08360055afa80614e86575f5ffd5b505f5160809190910160405295945050505050565b614ea3615265565b614eab615265565b604051835181526020840151602082015284604082015260408160608360075afa80614ed5575f5ffd5b5080518252602080820151908301526060016040529392505050565b614ef9615265565b614f01615265565b6040518451815260208501516020820152835160408201526020840151606082015260408160808360065afa80614f36575f5ffd5b5080518252602080820151908301526080016040529392505050565b5f82826028811115614f6657614f66615b83565b60298110614f7657614f76615a9d565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f8152602001614fa8615265565b8152602001614fb5615265565b8152602001614fc2615265565b8152602001614fcf615265565b8152602001614fdc615265565b8152602001614fe9615265565b8152602001614ff6615265565b8152602001615003615265565b8152602001615010615265565b815260200161501d615265565b815260200161502a615265565b8152602001615037615265565b8152602001615044615265565b8152602001615051615265565b815260200161505e615265565b815260200161506b615265565b8152602001615078615265565b8152602001615085615265565b8152602001615092615265565b815260200161509f615265565b81526020016150ac615265565b81526020016150b9615265565b81526020016150c6615265565b81526020016150d3615265565b81526020016150e0615265565b81526020016150ed615265565b81526020016150fa615265565b8152602001615107615265565b905290565b604051806102a00160405280615120615331565b815260200161512d615265565b815260200161513a615265565b8152602001615147615265565b8152602001615154615265565b8152602001615161615265565b815260200161516e615265565b815260200161517b615265565b8152602001615188615265565b8152602001615195615350565b81526020015f81526020016151a861537d565b81526020016151b56153ab565b81526020015f81526020016151c8615265565b81526020015f81526020016151db6153ca565b81526020016151e86152af565b81526020016150ed6153f8565b604051806101c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020016152336153f8565b81526020016152406153f8565b81526020015f81526020015f81526020015f81526020015f8152602001606081525090565b60405180604001604052805f81526020015f81525090565b60405180604001604052806150fa615265565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b6040518060e001604052806152e1615416565b81526020015f81526020015f81526020015f81526020015f8152602001615306615416565b81526020015f81525090565b6040518061010001604052806008906020820280368337509192915050565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b615367615265565b81526020019060019003908161535f5790505090565b604051806103800160405280601c905b615395615290565b81526020019060019003908161538d5790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b6153e2615265565b8152602001906001900390816153da5790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215615449575f5ffd5b84356001600160401b0381111561545e575f5ffd5b8501601f8101871361546e575f5ffd5b80356001600160401b03811115615483575f5ffd5b876020828401011115615494575f5ffd5b6020918201955093508501356001600160401b038111156154b3575f5ffd5b8501601f810187136154c3575f5ffd5b80356001600160401b038111156154d8575f5ffd5b8760208260051b84010111156154ec575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417612607576126076154fa565b81810381811115612607576126076154fa565b805f5b601081101561313f57815184526020938401939091019060010161553b565b80518252602090810151910152565b805f5b600381101561313f5761558084835161555a565b604093909301926020919091019060010161556c565b805f5b601c81101561313f578151845f5b60098110156155c65782518252602092830192909101906001016155a7565b505050610120939093019260209190910190600101615599565b805f5b602981101561313f5781518452602093840193909101906001016155e3565b805f5b601b81101561313f5761561984835161555a565b6040939093019260209190910190600101615605565b805f5b601c81101561313f578151845260209384019390910190600101615632565b805f5b600481101561313f578151845260209384019390910190600101615654565b8183525f6001600160fb1b0383111561568a575f5ffd5b8260051b80836020870137939093016020019392505050565b6156ae818851615538565b5f60208801516156c261020084018261555a565b5060408801516156d661024084018261555a565b5060608801516156ea61028084018261555a565b5060808801516156fe6102c084018261555a565b5060a088015161571261030084018261555a565b5060c088015161572661034084018261555a565b5060e088015161573a61038084018261555a565b5061010088015161574f6103c084018261555a565b50610120880151615764610400840182615569565b506101408801516104c08301526101608801516157856104e0840182615596565b5061018088015161579a6124608401826155e0565b506101a08801516129808301526101c08801516157bb6129a084018261555a565b506101e08801516129e08301526102008801516157dc612a00840182615602565b506102208801516157f16130c084018261562f565b50610240880151615806613440840182615651565b5061026088015161581b6134c084018261555a565b5061028088015161583061350084018261555a565b506135c06135408301526158496135c083018789615673565b613560830195909552506135808101929092526135a0909101529392505050565b634e487b7160e01b5f52604160045260245ffd5b60405161014081016001600160401b03811182821017156158a1576158a161586a565b60405290565b604051601f8201601f191681016001600160401b03811182821017156158cf576158cf61586a565b604052919050565b5f60c082840312156158e7575f5ffd5b60405160c081016001600160401b03811182821017156159095761590961586a565b604090815283518252602080850151908301528381015190820152606080840151908201526080808401519082015260a0928301519281019290925250919050565b5f82601f83011261595a575f5ffd5b5f610360615967816158a7565b915083018185821115615978575f5ffd5b845b8281101561599257805182526020918201910161597a565b509195945050505050565b5f82601f8301126159ac575f5ffd5b5f610380615967816158a7565b5f610be08284031280156159cb575f5ffd5b506159d461587e565b6159de84846158d7565b81526159ed8460c0850161594b565b6020820152615a0084610420850161599d565b60408201526107a08301516060820152615a1e846107c0850161599d565b6080820152610b4083015160a0820152610b6083015160c0820152610b8083015160e0820152610ba0830151610100820152610bc09092015161012083015250919050565b80820180821115612607576126076154fa565b5f5f85851115615a84575f5ffd5b83861115615a90575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f60018201615ac257615ac26154fa565b5060010190565b80356020831015612607575f19602084900360031b1b1692915050565b5f82615b0057634e487b7160e01b5f52601260045260245ffd5b500690565b5f81615b1357615b136154fa565b505f190190565b5f8183825b6008811015615b3e578151835260209283019290910190600101615b1f565b5050506101008201905092915050565b5f82518060208501845e5f920191825250919050565b5f60208284031215615b74575f5ffd5b815180151581146103dc575f5ffd5b634e487b7160e01b5f52602160045260245ffdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a2646970667358221220fea432746a67821ff4896cf7dace598c2d70a15932f73785415d90d32c52ef8d64736f6c634300081d0033 \ No newline at end of file diff --git a/eth/contracts/noir/agg_final_HonkVerifier.linkrefs.json b/eth/contracts/noir/agg_final_HonkVerifier.linkrefs.json new file mode 100644 index 0000000..1bb89e1 --- /dev/null +++ b/eth/contracts/noir/agg_final_HonkVerifier.linkrefs.json @@ -0,0 +1,10 @@ +{ + "agg_final.sol": { + "ZKTranscriptLib": [ + { + "length": 20, + "start": 581 + } + ] + } +} diff --git a/eth/contracts/noir/agg_final_ZKTranscriptLib.bin b/eth/contracts/noir/agg_final_ZKTranscriptLib.bin new file mode 100644 index 0000000..31dc244 --- /dev/null +++ b/eth/contracts/noir/agg_final_ZKTranscriptLib.bin @@ -0,0 +1 @@ +61172c610034600b8282823980515f1a607314602857634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610610034575f3560e01c8063995bf45714610038575b5f5ffd5b61004b6100463660046111f8565b610061565b604051610058919061143a565b60405180910390f35b610069610d5a565b5f610078888888888886610128565b9083529050610087818961017c565b6020840191909152905061009b818461026b565b604084019190915290506100af8189610314565b606084019190915290506100c4888285610375565b608084019190915290506100d88882610444565b60a084019190915290506100ed888285610647565b60c084019190915290506101028882856107b9565b60e08401919091529050610116888261093b565b50610100830152509695505050505050565b610130610dbf565b5f61013e8888888888610978565b60408601919091526020850191909152908352925061015d8389610c71565b6080850191909152606084019190915291989197509095505050505050565b610184610def565b5f61018d610e0e565b84815260e08401805151602080840191909152905181015160408084019190915261010086018051516060850152518201516080840152516101f0916101d59184910161150f565b60405160208183030381529060405280519060200120610cfc565b91505f6101fc83610d0f565b50808552905060015b6102116001601c611556565b8110156102615761024285610227600184611556565b601b8110610237576102376114fb565b602002015183610d3f565b8582601b8110610254576102546114fb565b6020020152600101610205565b5050509250929050565b610273610e2c565b5f61028a846040516020016101d591815260200190565b935061029584610d0f565b50825260015b8381101561030c576102ed836102b2600184611556565b601c81106102c2576102c26114fb565b6020020151846102d3600185611556565b601c81106102e3576102e36114fb565b6020020151610d3f565b8382601c81106102ff576102ff6114fb565b602002015260010161029b565b509093915050565b5f5f61031e610e4b565b84815261012084018051515160208084019190915290515181015160408084019190915261014086015160608401525161035e916101d591849101611569565b915061036982610d0f565b50959194509092505050565b61037d610e2c565b5f805b8381101561043a57610390610e69565b8581525f5b60098110156103f95787610160015183601c81106103b5576103b56114fb565b602002015181600981106103cb576103cb6114fb565b6020020151826103dc83600161159c565b600a81106103ec576103ec6114fb565b6020020152600101610395565b5061040e816040516020016101d591906115af565b955061041986610d0f565b508483601c811061042c5761042c6114fb565b602002015250600101610380565b5090949293505050565b5f5f61044e610e88565b83815260015b602981116104ab5761018086015161046d600183611556565b6029811061047d5761047d6114fb565b6020020151828260328110610494576104946114fb565b6020020152806104a3816115e3565b915050610454565b856101a001518282603281106104c3576104c36114fb565b60200201526104d360018261159c565b61012087015160200151519091508282603281106104f3576104f36114fb565b6020020152610120860151600160200201516020015182826001610517919061159c565b60328110610527576105276114fb565b602002015261053760028261159c565b6101208701516040015151909150828260328110610557576105576114fb565b602002015261012086015160026020020151602001518282600161057b919061159c565b6032811061058b5761058b6114fb565b602002015261059b60028261159c565b6101c0870151519091508282603281106105b7576105b76114fb565b602002018181525050856101c0015160200151828260016105d8919061159c565b603281106105e8576105e86114fb565b60200201526105f860028261159c565b9050856101e00151828260328110610612576106126114fb565b60200201818152505061062f826040516020016101d591906115fb565b925061063a83610d0f565b5096929550919350505050565b5f8080610655600185611556565b61066090600261162f565b61066b90600161159c565b6001600160401b0381111561068257610682610ee3565b6040519080825280602002602001820160405280156106ab578160200160208202803683370190505b50905084815f815181106106c1576106c16114fb565b60209081029190910101525f5b6106d9600186611556565b81101561078c5786610200015181601b81106106f7576106f76114fb565b6020020151518261070983600261162f565b61071490600161159c565b81518110610724576107246114fb565b60200260200101818152505086610200015181601b8110610747576107476114fb565b6020020151602001518282600261075e919061162f565b61076990600261159c565b81518110610779576107796114fb565b60209081029190910101526001016106ce565b506107a1816040516020016101d59190611646565b91506107ac82610d0f565b5096919550909350505050565b5f80806107c784600161159c565b6107d290600461159c565b6001600160401b038111156107e9576107e9610ee3565b604051908082528060200260200182016040528015610812578160200160208202803683370190505b50905084815f81518110610828576108286114fb565b602090810291909101015260015b8481116108925761022087015161084e600183611556565b601c811061085e5761085e6114fb565b6020020151828281518110610875576108756114fb565b60209081029190910101528061088a816115e3565b915050610836565b505f806108a086600161159c565b90505b6108ae86600461159c565b811161090d5787610240015182600481106108cb576108cb6114fb565b60200201518382815181106108e2576108e26114fb565b6020908102919091010152816108f7816115e3565b9250508080610905906115e3565b9150506108a3565b50610922826040516020016101d59190611646565b925061092d83610d0f565b509792965091945050505050565b5f5f610945610ea7565b838152610260850180515160208084019190915290518101516040808401919091525161035e916101d591849101611670565b5f8080808061098886600161159c565b61099390600661159c565b6001600160401b038111156109aa576109aa610ee3565b6040519080825280602002602001820160405280156109d3578160200160208202803683370190505b509050865f1b815f815181106109eb576109eb6114fb565b60209081029190910101525f5b610a03601088611556565b811015610a5457898982818110610a1c57610a1c6114fb565b9050602002013582826001610a31919061159c565b81518110610a4157610a416114fb565b60209081029190910101526001016109f8565b505f5b6010811015610ac5578a51610a7f908260108110610a7757610a776114fb565b602002015190565b82826010610a8e8b600161159c565b610a989190611556565b610aa2919061159c565b81518110610ab257610ab26114fb565b6020908102919091010152600101610a57565b5060208a01515181610ad888600161159c565b81518110610ae857610ae86114fb565b6020908102919091018101919091528a810151015181610b0988600161159c565b610b1490600161159c565b81518110610b2457610b246114fb565b602090810291909101015260408a01515181610b4188600161159c565b610b4c90600261159c565b81518110610b5c57610b5c6114fb565b60209081029190910181019190915260408b0151015181610b7e88600161159c565b610b8990600361159c565b81518110610b9957610b996114fb565b602090810291909101015260608a01515181610bb688600161159c565b610bc190600461159c565b81518110610bd157610bd16114fb565b60209081029190910181019190915260608b0151015181610bf388600161159c565b610bfe90600561159c565b81518110610c0e57610c0e6114fb565b602002602001018181525050610c2e816040516020016101d59190611646565b9150610c3982610d0f565b6040805160208101869052929750909550610c5491016101d5565b9150610c5f82610d0f565b50809350505095509550955095915050565b5f5f5f610c7c610ec5565b85815260a0858101805151602080850191909152905181015160408085019190915260c08089018051516060870152518301516080808701919091528901805151948601949094529251820151928401929092529051610ce2916101d5918491016116a3565b9150610ced82610d0f565b90979096509194509092505050565b5f5160206116d75f395f51905f52900690565b5f80826001600160801b038116608082901c610d2a82610cfc565b9450610d3581610cfc565b9350505050915091565b5f5f5160206116d75f395f51905f5282840990505b92915050565b604051806101400160405280610d6e610dbf565b8152602001610d7b610def565b8152602001610d88610e2c565b81526020015f8152602001610d9b610e2c565b81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806103600160405280601b906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b604051806101400160405280600a906020820280368337509192915050565b6040518061064001604052806032906020820280368337509192915050565b60405180606001604052806003906020820280368337509192915050565b6040518060e001604052806007906020820280368337509192915050565b634e487b7160e01b5f52604160045260245ffd5b6040516102a081016001600160401b0381118282101715610f1a57610f1a610ee3565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610f4857610f48610ee3565b604052919050565b5f82601f830112610f5f575f5ffd5b5f610200610f6c81610f20565b915083018185821115610f7d575f5ffd5b845b82811015610f97578035825260209182019101610f7f565b509195945050505050565b5f60408284031215610fb2575f5ffd5b604080519081016001600160401b0381118282101715610fd457610fd4610ee3565b604052823581526020928301359281019290925250919050565b5f82601f830112610ffd575f5ffd5b5f6110086060610f20565b90508060c084018581111561101b575f5ffd5b845b81811015610f975761102f8782610fa2565b835260209092019160400161101d565b5f82601f83011261104e575f5ffd5b61038061105a81610f20565b905080611f8084018581111561106e575f5ffd5b845b818110156110d25786601f820112611086575f5ffd5b5f61012061109381610f20565b9150820181898211156110a4575f5ffd5b835b828110156110be5780358252602091820191016110a6565b505050845260209093019261012001611070565b509095945050505050565b5f82601f8301126110ec575f5ffd5b5f610520610f6c81610f20565b5f82601f830112611108575f5ffd5b5f61036061111581610f20565b915050806106c084018581111561112a575f5ffd5b845b81811015610f975761113e8782610fa2565b835260209092019160400161112c565b5f82601f83011261115d575f5ffd5b5f610380610f6c81610f20565b5f82601f830112611179575f5ffd5b5f6111846080610f20565b9050806080840185811115611197575f5ffd5b845b81811015610f97578035835260209283019201611199565b5f5f83601f8401126111c1575f5ffd5b5081356001600160401b038111156111d7575f5ffd5b6020830191508360208260051b85010111156111f1575f5ffd5b9250929050565b5f5f5f5f5f5f8688036135c081121561120f575f5ffd5b61354081121561121d575f5ffd5b50611226610ef7565b6112308989610f50565b8152611240896102008a01610fa2565b6020820152611253896102408a01610fa2565b6040820152611266896102808a01610fa2565b6060820152611279896102c08a01610fa2565b608082015261128c896103008a01610fa2565b60a082015261129f896103408a01610fa2565b60c08201526112b2896103808a01610fa2565b60e08201526112c5896103c08a01610fa2565b6101008201526112d9896104008a01610fee565b6101208201526104c08801356101408201526112f9896104e08a0161103f565b61016082015261130d896124608a016110dd565b6101808201526129808801356101a082015261132d896129a08a01610fa2565b6101c08201526129e08801356101e082015261134d89612a008a016110f9565b610200820152611361896130c08a0161114e565b610220820152611375896134408a0161116a565b610240820152611389896134c08a01610fa2565b61026082015261139d896135008a01610fa2565b61028082015295506135408701356001600160401b038111156113be575f5ffd5b6113ca89828a016111b1565b979a90995096976135608101359761358082013597506135a09091013595509350505050565b805f5b601b8110156114125781518452602093840193909101906001016113f3565b50505050565b805f5b601c81101561141257815184526020938401939091019060010161141b565b8151805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a09081015190820152610be08101602083015161148960c08401826113f0565b50604083015161149d610420840182611418565b5060608301516107a083015260808301516114bc6107c0840182611418565b5060a0830151610b4083015260c0830151610b6083015260e0830151610b80830152610100830151610ba083015261012090920151610bc09091015290565b634e487b7160e01b5f52603260045260245ffd5b5f8183825b6005811015611533578151835260209283019290910190600101611514565b50505060a08201905092915050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610d5457610d54611542565b5f8183825b600481101561158d57815183526020928301929091019060010161156e565b50505060808201905092915050565b80820180821115610d5457610d54611542565b5f8183825b600a8110156115d35781518352602092830192909101906001016115b4565b5050506101408201905092915050565b5f600182016115f4576115f4611542565b5060010190565b5f8183825b603281101561161f578151835260209283019290910190600101611600565b5050506106408201905092915050565b8082028115828204841417610d5457610d54611542565b81515f90829060208501835b82811015610f97578151845260209384019390910190600101611652565b5f8183825b6003811015611694578151835260209283019290910190600101611675565b50505060608201905092915050565b5f8183825b60078110156116c75781518352602092830192909101906001016116a8565b50505060e0820190509291505056fe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001a2646970667358221220e536013174619e01e34e171468928d7f48ef22b459b7b58beee4577d79838bbb64736f6c634300081d0033 \ No newline at end of file diff --git a/eth/contracts/noir/agg_utxo_HonkVerifier.bin b/eth/contracts/noir/agg_utxo_HonkVerifier.bin new file mode 100644 index 0000000..45dc167 --- /dev/null +++ b/eth/contracts/noir/agg_utxo_HonkVerifier.bin @@ -0,0 +1 @@ +60e060405234801561000f575f5ffd5b5062400000608052601660a0526103fd60c05260805160a05160c051615ffa6100675f395f818160d601526107ac01525f81816108da015281816109e701528181610f460152610ff201525f6107500152615ffa5ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b366004615b20565b610054565b604051901515815260200160405180910390f35b5f6100626101fc6020615bf8565b8414610081576040516376ba560560e11b815260040160405180910390fd5b5f61008a6101af565b90505f61009787876101c4565b9050601082604001516100aa9190615c0f565b84146100c95760405163fa06659360e01b815260040160405180910390fd5b5f6100fc828787865f01517f00000000000000000000000000000000000000000000000000000000000000006001610676565b905061014c8686808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250508551855160608101516080909101519193509150600161073a565b815160a0015261015c82826108bd565b610179576040516313f8744360e31b815260040160405180910390fd5b610184828483610a6f565b6101a1576040516352ec174560e11b815260040160405180910390fd5b506001979650505050505050565b6101b7615494565b6101bf61151b565b905090565b6101cc61561e565b5f805b601081101561022e576101fb8583866101e9826020615c22565b926101f693929190615c35565b611e56565b8351826010811061020e5761020e615c5c565b6020020181815250506020826102249190615c22565b91506001016101cf565b50610252848285610240826080615c22565b9261024d93929190615c35565b611e77565b6020830152610262608082615c22565b9050610275848285610240826080615c22565b6040830152610285608082615c22565b9050610298848285610240826080615c22565b60608301526102a8608082615c22565b90506102bb848285610240826080615c22565b60a08301526102cb608082615c22565b90506102de848285610240826080615c22565b60c08301526102ee608082615c22565b9050610301848285610240826080615c22565b6080808401919091526103149082615c22565b9050610327848285610240826080615c22565b60e0830152610337608082615c22565b905061034a848285610240826080615c22565b61010083015261035b608082615c22565b905061036e848285610240826080615c22565b61012083015152610380608082615c22565b90506103938482856101e9826020615c22565b6101408301526103a4602082615c22565b90505f5b601c811015610423575f5b600981101561041a576103cd8684876101e9826020615c22565b84610160015183601c81106103e4576103e4615c5c565b602002015182600981106103fa576103fa615c5c565b6020020181815250506020836104109190615c22565b92506001016103b3565b506001016103a8565b505f5b6029811015610477576104408583866101e9826020615c22565b836101800151826029811061045757610457615c5c565b60200201818152505060208261046d9190615c22565b9150600101610426565b506104898482856101e9826020615c22565b6101a083015261049a602082615c22565b90506104ad848285610240826080615c22565b610120830151602001526104c2608082615c22565b90506104d5848285610240826080615c22565b610120830151604001526104ea608082615c22565b90506104fd848285610240826080615c22565b6101c083015261050e608082615c22565b90506105218482856101e9826020615c22565b6101e0830152610532602082615c22565b90505f5b6105426001601c615c0f565b81101561058b5761055a858386610240826080615c22565b83610200015182601b811061057157610571615c5c565b6020020152610581608083615c22565b9150600101610536565b505f5b601c8110156105df576105a88583866101e9826020615c22565b83610220015182601c81106105bf576105bf615c5c565b6020020181815250506020826105d59190615c22565b915060010161058e565b505f5b6004811015610633576105fc8583866101e9826020615c22565b836102400151826004811061061357610613615c5c565b6020020181815250506020826106299190615c22565b91506001016105e2565b50610645848285610240826080615c22565b610260830152610656608082615c22565b9050610669848285610240826080615c22565b6102808301525092915050565b61067e615721565b5f61068e88888888888887611f0d565b908352905061069d8189611f63565b602084019190915290506106b08161213f565b604084019190915290506106c4818961219b565b606084019190915290506106d88882612218565b608084019190915290506106ec88826122e7565b60a084019190915290506107008882612602565b60c084019190915290506107148882612770565b60e084019190915290506107288882612863565b50610100830152509695505050505050565b5f600180826107838661077e896107796107748a7f0000000000000000000000000000000000000000000000000000000000000000615c22565b6128ba565b6128d8565b6128f1565b90505f6107a18761079c8a6107796107748b6001615c22565b61290a565b90505f5b6107d060107f0000000000000000000000000000000000000000000000000000000000000000615c0f565b81101561083d575f6107fa8c83815181106107ed576107ed615c5c565b60200260200101516128ba565b905061080a8661077986846128f1565b955061081a8561077985846128f1565b9450610826848b6128f1565b9350610832838b61290a565b9250506001016107a5565b505f5b60108110156108a4575f8a826010811061085c5761085c615c5c565b602002015190506108718661077986846128f1565b95506108818561077985846128f1565b945061088d848b6128f1565b9350610899838b61290a565b925050600101610840565b506108af8484612939565b9a9950505050505050505050565b5f5f6108d283606001518561014001516128d8565b905060015f5b7f00000000000000000000000000000000000000000000000000000000000000008110156109c4575f86610160015182601c811061091857610918615c5c565b602002015180519091505f90610936908360015b60200201516128f1565b9050848114610958576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c811061096f5761096f615c5c565b602002015190506109808382612947565b95506109b485610779600161077e856107798e604001518b601c81106109a8576109a8615c5c565b6020020151600161290a565b94505050508060010190506108d8565b505f6109de866101800151865f0151876020015185612aa9565b9050600160025b7f0000000000000000000000000000000000000000000000000000000000000000811015610a3b57610a3182886080015183601c8110610a2757610a27615c5c565b60200201516128d8565b91506001016109e5565b50610a61610a4e8361077960018561290a565b61077e896101a0015189606001516128d8565b939093149695505050505050565b5f610a78615786565b5f610a868460c00151612b23565b9050610a906157ea565b610a98615809565b610100860151610ab890610ab390855f5b602002015161290a565b612b88565b60e0850152610100860151610ad290610ab390855f61092c565b610100850181905260e08086015190880151610af29261077e91906128d8565b845260c0860151610b2190610b0690612b88565b6107798660e0015161079c8a60e001518961010001516128d8565b602085015260018252610260880151610b3990612bf1565b81526101e0880151608085015260a086015160608501528351610b5b90612c30565b60208301525f5b6024811015610bff57610b84610b7a865f0151612c30565b86606001516128d8565b83610b90836002615c22565b604b8110610ba057610ba0615c5c565b602002015260808501516101808a0151610bd9919061077e908460298110610bca57610bca615c5c565b602002015188606001516128d8565b6080860152606085015160a0880151610bf291906128d8565b6060860152600101610b62565b5060245b6029811015610c8857610c1c610b7a8660200151612c30565b83610c28836002615c22565b604b8110610c3857610c38615c5c565b602002015260808501516101808a0151610c62919061077e908460298110610bca57610bca615c5c565b6080860152606085015160a0880151610c7b91906128d8565b6060860152600101610c03565b50610c97886101c00151612bf1565b8160016020020152606087015181600260200201526080870151816003602002015260a0870151816004602002015260c0870151816005602002015260e0870151816006602002015261010087015181600760200201526101208701518160086020020152610140870151816009602002015261016087015181600a60200201526101c087015181600b602002015261018087015181600c60200201526101a087015181600d60200201526101e087015181600e602002015261020087015181600f602002015261022087015181601060200201526102408701518160116020020152610260870151816012602002015261028087015181601360200201526102a087015181601460200201526102c087015181601560200201526102e0870151816016602002015261030087015181601760200201526103208701518160186020020152610340870151816019602002015261036087015181601a602002015261038087015181601b60200201526103a087015181601c60200201526103c087015181601d6020020181905250610e328860200151612bf1565b6103c08201526040880151610e4690612bf1565b6103e08201526060880151610e5a90612bf1565b6104008201526080880151610e6e90612bf1565b610420820152610100880151610e8390612bf1565b61044082015260e0880151610e9790612bf1565b61046082015260a0880151610eab90612bf1565b61048082015260c0880151610ebf90612bf1565b6104a08201526020880151610ed390612bf1565b6104c08201526040880151610ee790612bf1565b6104e08201526060880151610efb90612bf1565b6105008201526080880151610f0f90612bf1565b610520820152610100880151610f2490612bf1565b81602a60200201819052505f610f6a876080015186608001518b6102200151877f0000000000000000000000000000000000000000000000000000000000000000612c48565b805160e0870151919250610f7d916128d8565b604086018190526102208a01515160e0890151610fae929161077e91610fa391906128d8565b8861010001516128d8565b604086015260e0870151610fc190612d63565b60608601525f610fd360296002615c22565b90505f5b610fe36001601c615c0f565b8110156111d1575f61101660017f0000000000000000000000000000000000000000000000000000000000000000615c0f565b82101590508061115f5761104a610ab38b61010001518985600161103a9190615c22565b601c8110610aa957610aa9615c5c565b60e08901526101008a015161107990610ab39089611069866001615c22565b601c811061092c5761092c615c5c565b610100890152606088015160e089015161109391906128d8565b610120890152606088015160e08b01516110bb916110b0916128d8565b8961010001516128d8565b61014089018190526110de906110d090612c30565b61077e8a6101200151612c30565b866110e98486615c22565b604b81106110f9576110f9615c5c565b60200201526101408801516102208d01515f9161112b9161111b866001615c22565b601c8110610a2757610a27615c5c565b90506111488161077e8b61012001518887600161111b9190615c22565b90506111588960400151826128f1565b60408a0152505b61117e61117489606001518c60e001516128d8565b8b60e001516128d8565b60608901526102008c01516111a89083601b811061119e5761119e615c5c565b6020020151612bf1565b856111b38486615c22565b604b81106111c3576111c3615c5c565b602002015250600101610fd7565b506111de6001601c615c0f565b6111e89082615c22565b90506112086112008961010001518a60c0015161290a565b600190612939565b60a08701515261010088015160c089015161124c916112009161079c907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76906128d8565b60a087018051602001919091528051805160409091015251805160609182015286015160e089015161128b91611281916128d8565b8960e001516128d8565b60608701525f5b6004811015611338575f6112c48860a0015183600481106112b5576112b5615c5c565b602002015189606001516128d8565b90506112cf81612c30565b8860c0015183600481106112e5576112e5615c5c565b6020020152606088015160e08b01516112fe91906128d8565b88606001818152505061132a886040015161077e838f61024001518660048110610a2757610a27615c5c565b604089015250600101611292565b5060c0860151518482604b811061135157611351615c5c565b602002015260c0860151611372906001602002015160c0880151600261092c565b8461137e836001615c22565b604b811061138e5761138e615c5c565b602002015260c086015160600151846113a8836002615c22565b604b81106113b8576113b8615c5c565b60200201525f5b600381101561140c576113e28b6101200151826003811061119e5761119e615c5c565b84836113ed81615c70565b9450604b81106113ff576113ff615c5c565b60200201526001016113bf565b5060405180604001604052806001815260200160028152508382604b811061143657611436615c5c565b60200201526040860151848261144b81615c70565b9350604b811061145d5761145d615c5c565b6020020181815250506114848a61024001518960c001518a608001518d6101a00151612d6e565b6114a15760405163a2a2ac8360e01b815260040160405180910390fd5b5f6114b08b6102800151612bf1565b9050808483604b81106114c5576114c5615c5c565b60200201526101008901518583604b81106114e2576114e2615c5c565b60200201525f6114f2858761308b565b90505f6114fe8361315d565b905061150a82826131a3565b9d9c50505050505050505050505050565b611523615494565b50604080516103e08101825262400000815260166020808301919091526103fd82840152825180840184527f076b6b98a7b2dad658c00065f9993d8ccfd6a18c2613aa902785e0b352c4a1e081527f2f382c824a5ca2d916dc27484dad66bf3b09466194734b0dc7cf613c84d9473b818301526060830152825180840184527f2d2e7bd39f247c1b0223b33574b62df5c34c5bcd2e76d14c018cafb76c8da87881527f06dee0d594d2adcfa84124d61f46f08188941e50144e4ff1e6ceda5736c9cffa818301526080830152825180840184527f1e92276c08c16eb972a2959bac535e88df13e7594f1813a84def10c360b7a92681527f072b503854fc952a8eb7d6271b5706840c6c43eea9a307791ef6a30ee353a1068183015260a0830152825180840184527f212a722bb14e935b0edd1ee3faa6a942f5af6d0e3754d247408bf5a328e03dfe81527f1eb78cf7ac2aa5cc572af3c8f488be055ca044259967557b732c3fa69a0fcbfc8183015260c0830152825180840184527f0b728cff45572c9721d6062fd9e62511ae4cd5449990b74b6558f9b847141d4981527f141db89d3a55f5d1af2755e6baeeb1a4d1e0df407d3a3b423e5fbe897cd182e28183015260e0830152825180840184527f2de8a69ebfa857df817e95a849a45484d8e51cb72639b9f18b22d5bbe789ef5381527f160aaa6e8be8ff6c17a8b01c38f813a6bab6b963f276fb76a0b4804a7714f46781830152610100830152825180840184527f14dd1ce931af2f1a008cdb4e13fcb4bb5f3adb8b1a360885d949225f796e05a281527f11a7654358d84ce23eb3f3714bc52d36efffbc6387a0d74ed1271a8ce1566b7d81830152610120830152825180840184527f15654ba45991c566868445c6d3ad56a72788593afa68d3f6fae02fb4cb0afb5481527f223e57a0168b7ad3fc2cf73cbad83c16e215ee899522b971c896ac5cb4eb55db81830152610140830152825180840184527f110d8d4eb8bc850d783fa85804225ff4ca8688dac3140eefcfc158374b45c61a81527f08ce585e328c2e120db64a705ee2587a7451e755f44ab6cb9482382cc70f1a5f81830152610160830152825180840184527f096f107999d7bed1930b6aa8664635b7a4f5210757f4a03daa0b37acbbfbe18381527f236883e4bed711163bef46a840bd3a9db617350b9d6c345a1d79a56a3ee41ce881830152610180830152825180840184527f0cc5faf916af695883293c1e6e7490db00dfa2295eb0713ae89c91a2ec573a0181527f0c4150ae9b7d89358cf5ba57f65452f6fc3f1df3a77c88718643f03611ea8448818301526101a0830152825180840184527f12bcf4350e9ed4b3bf099f3e9026cde938358f44b5a353ee8ea94d4c219ee9e681527f1f2057108bb2a12131794c7991be14a67e63fe048fa02be89fc3e130d207aa19818301526101c0830152825180840184527f2733aada77ca6b235db92d136a081b580f48cab6785de5a8b0544ea5bcfe865b81527f1ff8d664a7700688c6d3d371442e56f5b73f2c9280d3703ce10df654949ca009818301526101e0830152825180840184527f05d9f6de2bf6a206ef38b2c3fe604693273a4d8afb5ba0d0b315fb82b68796e181527f2df9541e6a8a908fad158631d9726fa8c66ce33d68929facf1ada9519256521981830152610200830152825180840184527f25f5510fe5d4152bd9599bab4fb3417af98c6dcdf52412b6708e37be05fc56b081527f1616c753acea71275e0716583d2d785f4e91018c9530dba0593c0830b9741efa81830152610220830152825180840184527f12d351a5e045527f3c45bb5da2ed3a73c53d4d9858d7d257d4e2fcb7aaf6cd2f81527f08268516bab656b775fda8802b8f5cae2dd412b9b44e24c31aaec24f23bc162581830152610240830152825180840184527f07b078d567880685eef7e65090d38b734c19fac8b3afc2fcb501801c31a0c85f81527f2b62bbeb9a0796b4228e7cd4b435a7e012d0eb09772efb4421a8b098f7a0e32f81830152610260830152825180840184527f037bae72875ce47548a179ffb789de392c13661962b6e3c515e1ce6fe310c4df81527f2e9ec6afe4d4c0738957a36b662da4af988c2e4fb7b1a5357284165230dc3c5981830152610280830152825180840184527f1b681d0fae6769eb90e514a6e37dac36449699ca27a001a6773c4561424a089781527f01b9d462b0d3d90927fbe4abec8e052666d4178b558a59636690e5ae1d13c8ba818301526102a0830152825180840184527f1df4c3978b9968f362feefeab5199c81ef623e1f7b51f7029d68ab4d8261b26681527f2b5f43286ad428b083314b004f0730f8992a3b6c820c8289c183f81c33d6ead8818301526102c0830152825180840184527f19d511fc385f495c4c221a54a2a48ba00e3df0fe05d2a10fec168a7f5635793b81527f0af2f09d90f83392148ea0736aa368e05baff213cd9a2454e5b84e5282f8e4f4818301526102e0830152825180840184527f2181a190d8a5229715cf949bc3d0d19bfb6b9d27882950928f30746207f5df5781527f185917d0f7c49f8054ffe96479cb3649fe7a9ac163240c1d2371670adef5835281830152610300830152825180840184527f041b4073446b5892dd7eabf545028e2a1ca163046e9d0415b0ba9d9c4632f07b81527e5d24fbb51390fb1488b82145f51418573a8cb7efc197b5371780de35eb55de81830152610320830152825180840184527f0a58ab84bec6105d9533d7b52c7d46be862a90b3a83a75d1073b4235299d88d281527f072b71091d1ef407e20d0d0cd1689c67f3b2aebec2b7b606d0d11e571da53cf781830152610340830152825180840184527f2a5ae466600e63a883fa63c745242ee0f74c8edc3b8b0779968d0fe68a1ef94181527f13bf890921b82da4e5e10b68b629ed6d8113988330f33c4d52307544a3748c3181830152610360830152825180840184527f2141cda9c7a8779c338b16176c47d8b75e5f1b657d31d571204511d018db5e6381527f029ef7d95d44f73300dfdc5d1f7857dfb867822f826d7f1bae92c942bc5873968183015261038083015282518084018452600181526002818301526103a083015282518084019093527f1e1eef1361c85ac402afd166e5d2f65ca5c1b6d21e17efdf40fdf7ab889c3bf783527f010a1a1054ede88dc3780ddfec4d541aee3c01971b648904cab290e196c3217d908301526103c081019190915290565b5f60208214611e63575f5ffd5b611e706107748385615c88565b9392505050565b611e7f615837565b60808214611e8b575f5ffd5b604080516080810190915280611ea460205f8688615c35565b611ead91615c88565b8152602090810190611ec3906040908688615c35565b611ecc91615c88565b8152602001611edf606060408688615c35565b611ee891615c88565b8152602001611efb608060608688615c35565b611f0491615c88565b90529392505050565b611f1561585b565b5f611f24898989898989613397565b604086019190915260208501919091529083529250611f43838a613839565b608085019190915260608401919091529199919850909650505050505050565b611f6b61588b565b5f611f746158aa565b84815260e0848101805151602080850191909152815181015160408086019190915282518101516060808701919091529251830151608086015261010080890180515160a0880152805184015160c0880152805183015195870195909552935190920151928401929092525161200b91611ff091849101615ca5565b604051602081830303815290604052805190602001206128ba565b915061201682613908565b6020850152835260015b600261202e6001601c615c0f565b6120389190615ced565b8110156120b85761205583604051602001611ff091815260200190565b925061206083613908565b8561206c846002615bf8565b601b811061207c5761207c615c5c565b602002018661208c856002615bf8565b612097906001615c22565b601b81106120a7576120a7615c5c565b602002019190915252600101612020565b506120c56001601c615c0f565b60011660011480156120e2575060026120e06001601c615c0f565b115b15612137576120fd82604051602001611ff091815260200190565b915061210882613908565b5083600161211781601c615c0f565b6121219190615c0f565b601b811061213157612131615c5c565b60200201525b509250929050565b6121476158c9565b5f805b601c8110156121945761216984604051602001611ff091815260200190565b935061217484613908565b508382601c811061218757612187615c5c565b602002015260010161214a565b5090929050565b5f5f6121a56158e8565b84815261012084018051515160208084019190915281515181015160408085019190915282515181015160608086019190915292515190920151608084015261014086015160a0840152905161220191611ff091849101615d00565b915061220c82613908565b50959194509092505050565b6122206158c9565b5f805b601c8110156122de57612234615906565b8481525f5b600981101561229d5786610160015183601c811061225957612259615c5c565b6020020151816009811061226f5761226f615c5c565b602002015182612280836001615c22565b600a811061229057612290615c5c565b6020020152600101612239565b506122b281604051602001611ff09190615d33565b94506122bd85613908565b508483601c81106122d0576122d0615c5c565b602002015250600101612223565b50909391925050565b5f5f6122f1615925565b83815260015b6029811161234e57610180860151612310600183615c0f565b6029811061232057612320615c5c565b602002015182826038811061233757612337615c5c565b60200201528061234681615c70565b9150506122f7565b856101a0015182826038811061236657612366615c5c565b6020020152612376600182615c22565b610120870151602001515190915082826038811061239657612396615c5c565b60200201526101208601516001602002015160200151828260016123ba9190615c22565b603881106123ca576123ca615c5c565b60200201526101208601516001602002015160400151826123ec836002615c22565b603881106123fc576123fc615c5c565b602002015261012086015160016020020151606001518261241e836003615c22565b6038811061242e5761242e615c5c565b602002015261243e600482615c22565b610120870151604001515190915082826038811061245e5761245e615c5c565b60200201526101208601516002602002015160200151828260016124829190615c22565b6038811061249257612492615c5c565b60200201526101208601516040908101510151826124b1836002615c22565b603881106124c1576124c1615c5c565b60200201526101208601516040015160600151826124e0836003615c22565b603881106124f0576124f0615c5c565b6020020152612500600482615c22565b6101c08701515190915082826038811061251c5761251c615c5c565b602002018181525050856101c00151602001518282600161253d9190615c22565b6038811061254d5761254d615c5c565b60200201526101c08601516040015182612568836002615c22565b6038811061257857612578615c5c565b60200201526101c08601516060015182612593836003615c22565b603881106125a3576125a3615c5c565b60200201526125b3600482615c22565b9050856101e001518282603881106125cd576125cd615c5c565b6020020181815250506125ea82604051602001611ff09190615d67565b92506125f583613908565b5096929550919350505050565b5f5f61260c615944565b8381525f5b61261d6001601c615c0f565b81101561275b5785610200015181601b811061263b5761263b615c5c565b6020020151518261264d836004615bf8565b612658906001615c22565b606d811061266857612668615c5c565b602002015261020086015181601b811061268457612684615c5c565b6020020151602001518282600461269b9190615bf8565b6126a6906002615c22565b606d81106126b6576126b6615c5c565b602002015261020086015181601b81106126d2576126d2615c5c565b602002015160400151826126e7836004615bf8565b6126f2906003615c22565b606d811061270257612702615c5c565b602002015261020086015181601b811061271e5761271e615c5c565b60200201516060015182612733836004615bf8565b61273e906004615c22565b606d811061274e5761274e615c5c565b6020020152600101612611565b5061220181604051602001611ff09190615d9b565b5f5f61277a615963565b83815260015b601c81116127d757610220860151612799600183615c0f565b601c81106127a9576127a9615c5c565b60200201518282602181106127c0576127c0615c5c565b6020020152806127cf81615c70565b915050612780565b505f806127e6601c6001615c22565b90505b6127f5601c6004615c22565b811161284e57866102400151826004811061281257612812615c5c565b602002015183826021811061282957612829615c5c565b60200201528161283881615c70565b925050808061284690615c70565b9150506127e9565b506125ea82604051602001611ff09190615dcf565b5f5f61286d615982565b8381526102608501805151602080840191909152815181015160408085019190915282518101516060808601919091529251909201516080840152905161220191611ff091849101615e03565b5f6128d25f516020615f855f395f51905f5283615e36565b92915050565b5f5f516020615f855f395f51905f528284099392505050565b5f5f516020615f855f395f51905f528284089392505050565b5f5f516020615f855f395f51905f52612930835f516020615f855f395f51905f52615c0f565b84089392505050565b5f611e708361077984612b88565b5f5f604051806101200160405280619d8081526020015f516020615fa55f395f51905f5281526020016105a081526020015f516020615f255f395f51905f52815260200161024081526020015f516020615f255f395f51905f5281526020016105a081526020015f516020615fa55f395f51905f528152602001619d8081525090505f600190505f5f90505b60098110156129f4576129ea82610779878461290a565b91506001016129d3565b506129fd6158aa565b5f5b6009811015612a4e57612a2f610ab3858360098110612a2057612a20615c5c565b6020020151610779898561290a565b828260098110612a4157612a41615c5c565b60200201526001016129ff565b505f5b6009811015612a9457612a8a8561077e898460098110612a7357612a73615c5c565b6020020151858560098110610a2757610a27615c5c565b9450600101612a51565b50612a9f84836128d8565b9695505050505050565b5f612ab26158c9565b612abd868285613938565b612ac986868386613ae4565b612ad586868386613cd0565b612ae0868285613ef5565b612aeb8682856140e9565b612af786868386614432565b612b03868683866148e5565b612b0e868285614ce4565b612b198682856150a5565b612a9f81856153a5565b612b2b6158c9565b81815260015b601c811015612b8257612b6382612b49600184615c0f565b601c8110612b5957612b59615c5c565b6020020151612d63565b8282601c8110612b7557612b75615c5c565b6020020152600101612b31565b50919050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f516020615f855f395f51905f520360808201525f516020615f855f395f51905f5260a082015260205f60c08360055afa905080612be6575f5ffd5b50505f519392505050565b612bf96159a0565b604051806040016040528060888460200151901b845f015117815260200160888460600151901b8460400151178152509050919050565b5f6128d2825f516020615f855f395f51905f52615c0f565b612c506158c9565b601c5b8015612d59575f84612c66600184615c0f565b601c8110612c7657612c76615c5c565b602002015190505f88612c8a600185615c0f565b601c8110612c9a57612c9a615c5c565b602002015190505f612cf5612cb9612cb2858c6128d8565b60026128d8565b61079c8a612cc8600189615c0f565b601c8110612cd857612cd8615c5c565b6020020151610779612cef8861077960018a61290a565b8761290a565b9050612d1681610779610ab3612d108761077960018961290a565b866128f1565b9050858411612d45579750878085612d2f600187615c0f565b601c8110612d3f57612d3f615c5c565b60200201525b50505080612d5290615e49565b9050612c53565b5095945050505050565b5f6128d282836128d8565b5f600181612d87612d818761010061540a565b8361290a565b905080612da75760405163835eb8f760e01b815260040160405180910390fd5b612daf6159b8565b80518390525f5b601c811015612e79575f612dcb826009615bf8565b612dd6906001615c22565b905084835f0151826101008110612def57612def615c5c565b60200201525f612e00826001615c22565b90505b612e0e600983615c22565b811015612e6f578351612e4e90612e26600184615c0f565b6101008110612e3757612e37615c5c565b60200201518a85601c8110610a2757610a27615c5c565b8451826101008110612e6257612e62615c5c565b6020020152600101612e03565b5050600101612db6565b50608081018390525f602082018190525b610100811015612f7757612eab612ea583608001518a6128d8565b8561290a565b8260a00151826101008110612ec257612ec2615c5c565b602002015260a0820151612eec90826101008110612ee257612ee2615c5c565b6020020151612b88565b8260a00151826101008110612f0357612f03615c5c565b602002018181525050612f49826020015161077e845f0151846101008110612f2d57612f2d615c5c565b60200201518560a00151856101008110610a2757610a27615c5c565b60208301526080820151612f6a905f516020615f655f395f51905f526128d8565b6080830152600101612e8a565b505f612f8883610779610100612b88565b9050612f988260200151826128d8565b602083015260a0820151612fb3905f5b6020020151826128d8565b604083015260a0820151612fdf90612fce6001610100615c0f565b6101008110612fa857612fa8615c5c565b60608301526040820151612ff5908a6002610a27565b60c083018190526130419061077e61301a8b5f516020615f655f395f51905f5261290a565b6107796130308e600160200201518f6002610aa9565b8e51602089015161079c91906128d8565b60c0830181905260608301516130769161306a9161077e906107798e600260200201518c61290a565b61079c858c6003610a27565b60c08301819052159998505050505050505050565b6130936159a0565b5f60036130a2601c6029615c22565b6130ac9190615c22565b6130b7906003615c22565b90506001604051855151604082015285516020015160608201528451608082015260408160606040840160075afa8216915060015b838110156131455760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa909216916001016130ec565b50805184526020810151602085015250505092915050565b6131656159a0565b5f516020615f455f395f51905f5282602001515f516020615f455f395f51905f526131909190615c0f565b61319a9190615e36565b60208301525090565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b0316836040516133399190615e5e565b5f60405180830381855afa9150503d805f8114613371576040519150601f19603f3d011682016040523d82523d5f602084013e613376565b606091505b5091509150818015612a9f575080806020019051810190612a9f9190615e74565b5f808080806133a7876003615c22565b6133b290600c615c22565b6001600160401b038111156133c9576133c9615e93565b6040519080825280602002602001820160405280156133f2578160200160208202803683370190505b509050875f1b815f8151811061340a5761340a615c5c565b602002602001018181525050865f1b8160018151811061342c5761342c615c5c565b602002602001018181525050855f1b8160028151811061344e5761344e615c5c565b60209081029190910101525f5b613466601089615c0f565b8110156134b7578a8a8281811061347f5761347f615c5c565b90506020020135828260036134949190615c22565b815181106134a4576134a4615c5c565b602090810291909101015260010161345b565b505f5b6010811015613528578b516134e29082601081106134da576134da615c5c565b602002015190565b828260106134f18c6003615c22565b6134fb9190615c0f565b6135059190615c22565b8151811061351557613515615c5c565b60209081029190910101526001016134ba565b5060208b0151518161353b896003615c22565b8151811061354b5761354b615c5c565b6020908102919091018101919091528b81015101518161356c896003615c22565b613577906001615c22565b8151811061358757613587615c5c565b6020908102919091018101919091528b015160400151816135a9896003615c22565b6135b4906002615c22565b815181106135c4576135c4615c5c565b6020908102919091018101919091528b015160600151816135e6896003615c22565b6135f1906003615c22565b8151811061360157613601615c5c565b602090810291909101015260408b0151518161361e896003615c22565b613629906004615c22565b8151811061363957613639615c5c565b60209081029190910181019190915260408c015101518161365b896003615c22565b613666906005615c22565b8151811061367657613676615c5c565b60209081029190910101526040808c0151015181613695896003615c22565b6136a0906006615c22565b815181106136b0576136b0615c5c565b602090810291909101015260408b015160600151816136d0896003615c22565b6136db906007615c22565b815181106136eb576136eb615c5c565b602090810291909101015260608b01515181613708896003615c22565b613713906008615c22565b8151811061372357613723615c5c565b60209081029190910181019190915260608c0151015181613745896003615c22565b613750906009615c22565b8151811061376057613760615c5c565b602090810291909101015260608b01516040015181613780896003615c22565b61378b90600a615c22565b8151811061379b5761379b615c5c565b60209081029190910101526060808c01510151816137ba896003615c22565b6137c590600b615c22565b815181106137d5576137d5615c5c565b6020026020010181815250506137f581604051602001611ff09190615ea7565b915061380082613908565b604080516020810186905292975090955061381b9101611ff0565b915061382682613908565b5080935050509650965096509692505050565b5f5f5f6138446159fc565b85815260a085810180515160208085019190915281518101516040808601919091528251810151606080870191909152925183015160808087019190915260c0808b0180515196880196909652855184015190870152845182015160e0870152935183015161010086015292880180515161012086015280518201516101408601528051840151610160860152519091015161018084015290516138ee91611ff091849101615edc565b91506138f982613908565b90979096509194509092505050565b5f80826001600160801b038116608082901c613923826128ba565b945061392e816128ba565b9350505050915091565b5f613944846007615464565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f6139a561399f61397985600361290a565b6107796139946139898b5f615464565b6107798c601d615464565b6107798b601c615464565b836128d8565b9050613a26613a1b613a026139e96139d08561077e6139c58d6002615464565b6107798e601c615464565b61077e6139de8c6003615464565b6107798d601d615464565b61077e6139f78b6004615464565b6107798c601e615464565b61077e613a108a6005615464565b6107798b601f615464565b61077e886001615464565b9050613a458161077e613a3a86600161290a565b6107798a6027615464565b9050613a5181846128d8565b9050613a5d81856128d8565b8552505f9050613a97613a8d613a82613a7788601c615464565b61077e89601f615464565b61079c886024615464565b61077e875f615464565b9050613aa88161077984600261290a565b9050613ab98161077984600161290a565b9050613ac581836128d8565b9050613ad181846128d8565b9050808460015b60200201525050505050565b5f5f5f613b1a613b10613af889601c615464565b61077e613b068b6012615464565b8a606001516128d8565b87608001516128f1565b9050613b5381610779613b49613b318b601d615464565b61077e613b3f8d6013615464565b8c606001516128d8565b89608001516128f1565b9050613b7881610779613b49613b6a8b601e615464565b61077e613b3f8d6014615464565b9050613b9d81610779613b49613b8f8b601f615464565b61077e613b3f8d6015615464565b92505f9050613bc1613b10613bb389601c615464565b61077e613b068b600e615464565b9050613be681610779613b49613bd88b601d615464565b61077e613b3f8d600f615464565b9050613c0b81610779613b49613bfd8b601e615464565b61077e613b3f8d6010615464565b9050613c3081610779613b49613c228b601f615464565b61077e613b3f8d6011615464565b91505f9050613c57613c51613c46896020615464565b61077e8a601a615464565b846128d8565b9050613c8c8161079c613c86613c6e8b6028615464565b61077e613c7c8d601b615464565b8c60a001516128d8565b856128d8565b9050613c9881856128d8565b6040860152505f613cbb613c86613cb089601b615464565b6107798a6028615464565b9050808560035b602002015250505050505050565b5f5f613d2e613d16613cfe613ce9613b498a6016615464565b61077e613cf78b6017615464565b8a516128d8565b61077e613d0c8a6018615464565b89602001516128d8565b61077e613d24896019615464565b88604001516128d8565b91505f613d65613d4c613d4289601c615464565b88608001516128f1565b61077e613d5a8a6003615464565b6107798b6024615464565b90505f613d8e613d7689601d615464565b61077e613d838b5f615464565b6107798c6025615464565b90505f613db8613d9f8a601e615464565b61077e613dad8c6001615464565b6107798d6026615464565b9050613df7613ddf613dd18561077e868d5f01516128d8565b61077e848c602001516128d8565b61077e613ded8c6004615464565b8b604001516128d8565b93505050505f613e0b613c51886021615464565b90505f613e1c613c51896021615464565b90505f613e54613e3b613e308b6023615464565b61077e8c6006615464565b61079c613e498c6023615464565b6107798d6006615464565b90505f613e72612d81613e6787896128d8565b6107798d6021615464565b9050613e7e81886128d8565b90505f613ea6613e98613e928d6006615464565b876128d8565b61079c613e928e6022615464565b90505f613eb48c6023615464565b90505f613ec4612d8183846128d8565b60808c0185905260a08c018490529050613ede818b6128d8565b8b6006602002015250505050505050505050505050565b5f613f015f600161290a565b90505f613f0f5f600261290a565b90505f613f1d5f600361290a565b90505f613f39613f2e88601d615464565b61079c89601c615464565b90505f613f55613f4a89601e615464565b61079c8a601d615464565b90505f613f71613f668a601f615464565b61079c8b601e615464565b90505f613f8d613f828b6024615464565b61079c8c601f615464565b905083613f9e81610779818b6128f1565b9050613fae81610779878a6128f1565b9050613fbe8161077987896128f1565b9050613fcf816107798d6008615464565b9050613fdb818a6128d8565b60e08b01525082613ff081610779818b6128f1565b905061400081610779868a6128f1565b90506140108161077986896128f1565b9050614021816107798d6008615464565b905061402d818a6128d8565b6101008b0152508161404381610779818b6128f1565b905061405381610779858a6128f1565b90506140638161077985896128f1565b9050614074816107798d6008615464565b9050614080818a6128d8565b6101208b0152508061409681610779818b6128f1565b90506140a681610779848a6128f1565b90506140b68161077984896128f1565b90506140c7816107798d6008615464565b90506140d3818a6128d8565b610140909a019990995250505050505050505050565b6141226040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61412d84601d615464565b815261413a84601e615464565b602082015261414a846024615464565b604082015261415a846027615464565b606082015261416a846026615464565b608082015261417a846025615464565b60a08201525f61418b856002615464565b90505f614198865f615464565b90505f6141ac8460400151855f015161290a565b90505f6141c1856020015186602001516128d8565b606086015190915086905f906141d790806128d8565b90505f6141f56141ef89602001518a606001516128d8565b886128d8565b90505f61421461420d8a60a001518b604001516128f1565b8a516128f1565b9050614223613e9282886128d8565b905061424a61424461423e614238848761290a565b8861290a565b846128f1565b836128f1565b905061427261426761425c83876128d8565b6107798f6009615464565b61077960018a61290a565b6101608c015250505050602085015160808601515f91614291916128f1565b90505f6142af6142a58860600151886128d8565b886020015161290a565b90505f6142d36142bf84876128d8565b61077e613c868b60a001518c5f015161290a565b90506142fb6142f06142e5838c6128d8565b6107798e6009615464565b61077960018961290a565b6101808b0152505f915061431c90506143158360116128f1565b87516128d8565b90505f61432983846128f1565b905061433581826128f1565b90505f6143438360096128d8565b905061436c614366613c5161435f8b60a001518c5f01516128f1565b8b516128f1565b8261290a565b60c089018190525f90614387906141ef9061425c908d6128d8565b905061439a8b600b6020020151826128f1565b6101608c0152505086515f92506143c19150614315906143ba90806128f1565b88516128f1565b90505f6144016143dc836107798a5f01518b60a0015161290a565b602089015161079c906143ef90806128f1565b6107798b602001518c608001516128f1565b905061441e89600c602002015161077e6141ef61425c858d6128d8565b89600c602002015250505050505050505050565b61449c604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6144b46144aa86601e615464565b85604001516128d8565b8082526144d39061077e6144c988601d615464565b87602001516128d8565b8082526144e89061077e61431588601c615464565b8082526144fa9061077e876001615464565b808252602082018190526145139061079c87601f615464565b815261452e614523866024615464565b61079c87601c615464565b608082015261454c614541866027615464565b61079c87601f615464565b6060820152608081015161456e9061456490806128d8565b826080015161290a565b6101c082015260808101516145ae906145a49061459d9061077960015f516020615f855f395f51905f52615c0f565b60016128f1565b82606001516128d8565b60a082018190526145e4906145d6906107796145cb896002615464565b6107798a6003615464565b610779613c8688600a615464565b83600e60200201526101c0810151614608906145d6906107796145cb896002615464565b6101e0840152805161462d90610779614622886002615464565b610779896003615464565b6101208201525f61464c61464287601f615464565b836020015161290a565b905061465b61436682836128d8565b60e083015261467861466e876026615464565b86604001516128d8565b6040830181905261469b9061077e614691896025615464565b88602001516128d8565b604083018190526146bb9061077e6146b4896024615464565b88516128d8565b60408301526146d86146ce876027615464565b836040015161290a565b60408301525f6146f76146ec886026615464565b61079c89601e615464565b905061474961472461399f61459d866080015160015f516020615f855f395f51905f526107799190615c0f565b61077961459d866040015160015f516020615f855f395f51905f526107799190615c0f565b60c0840152604083015161476b9061476190806128d8565b846040015161290a565b61010084015260c083015161479790614789906107798a6007615464565b610779613e928a600a615464565b6102008601526101c08301516147b690614789906107798a6007615464565b6102208601526101008301516147d590614789906107798a6007615464565b61024086015260e08301516147ef90610779896007615464565b61014084015261480e614803886025615464565b61079c89601d615464565b610160840152608083015161484c906146ec906148419061459d9061077960015f516020615f855f395f51905f52615c0f565b8561016001516128d8565b61018084018190526101208401516101a085018190526148839161077e906107796148788c6005615464565b6107798d6002615464565b6101a0840181905283516148a3919061077e906107796148788c5f615464565b6101a084018190526101408401516148bb91906128f1565b6101a084018190526148d590610779613e928a600a615464565b6101a0840181905285600d613cc2565b61491e6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61495361493a61492f87601c615464565b610779886025615464565b61077e614948886024615464565b61077989601d615464565b815261499861498d61497461496988601c615464565b61077989601f615464565b61077e61498289601d615464565b6107798a601e615464565b61079c876026615464565b604082018190526149ad90600160441b6128d8565b604082018190526149c39061079c876027615464565b6040820181905281516149d691906128f1565b604082018190526149ec90610779876005615464565b60408201528051614a0190600160441b6128d8565b808252614a219061077e614a16886024615464565b610779896025615464565b80825260208201819052614a3d9061079c613a7788601e615464565b60208201819052614a5390610779876004615464565b6020820152805160608201819052614a709061077e87601f615464565b60608201819052614a949061079c614a89886026615464565b61077e896027615464565b60608201819052614aa990610779875f615464565b8160600181815250505f614ad2614ac8836020015184604001516128f1565b83606001516128f1565b9050614ae381610779886003615464565b9050614afb614af3876025615464565b6140006128d8565b60808301819052614b119061077e886024615464565b60808301819052614b24906140006128d8565b60808301819052614b3a9061077e88601e615464565b60808301819052614b4d906140006128d8565b60808301819052614b639061077e88601d615464565b60808301819052614b76906140006128d8565b60808301819052614b8c9061077e88601c615464565b60808301819052614ba29061079c88601f615464565b60808301819052614bb890610779886005615464565b6080830152614bcb614af3876026615464565b60a08301819052614be19061077e886025615464565b60a08301819052614bf4906140006128d8565b60a08301819052614c0a9061077e886024615464565b60a08301819052614c1d906140006128d8565b60a08301819052614c339061077e88601f615464565b60a08301819052614c46906140006128d8565b60a08301819052614c5c9061077e88601e615464565b60a08301819052614c729061079c886027615464565b60a08301819052614c8790610779885f615464565b60a0830181905260808301515f91614c9f91906128f1565b9050614cb081610779896004615464565b9050614cbc82826128f1565b60c08401819052614cd590610779613e928a600b615464565b60c08401819052856013613cc2565b614d5a6040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b614d73614d6885601c615464565b61077e866002615464565b8152614d8e614d8385601d615464565b61077e866003615464565b6020820152614dac614da185601e615464565b61077e866004615464565b6040820152614dca614dbf85601f615464565b61077e866005615464565b60608201528051614dfc90614df590614dee90614de790806128d8565b84516128d8565b83516128d8565b82516128d8565b60808201526020810151614e3a90614e3090614e2690614e1c90806128d8565b84602001516128d8565b83602001516128d8565b82602001516128d8565b60a08201526040810151614e7890614e6e90614e6490614e5a90806128d8565b84604001516128d8565b83604001516128d8565b82604001516128d8565b60c08201526060810151614eac906145a490614ea290614e9890806128d8565b84606001516128d8565b83606001516128d8565b60e0820152608081015160a0820151614ec591906128f1565b61010082015260c081015160e0820151614edf91906128f1565b61012082015260a0810151614f0390614ef890806128f1565b8261012001516128f1565b61014082015260e0810151614f2790614f1c90806128f1565b8261010001516128f1565b610160820152610120810151614f3d90806128f1565b6101e08201819052614f5e90614f5390806128f1565b8261016001516128f1565b6101e0820152610100810151614f7490806128f1565b6101a08201819052614f9590614f8a90806128f1565b8261014001516128f1565b6101a08201819052610160820151614fac916128f1565b6101808201526101408101516101e0820151614fc891906128f1565b6101c0820152614fdc61399f85600c615464565b61020082018190526102808401516101808301516150079261077e916107799061079c8a6024615464565b8360146020020152615037836015602002015161077e836102000151610779856101a0015161079c8a6025615464565b8360156020020152615067836016602002015161077e836102000151610779856101c0015161079c8a6026615464565b8360166020020152615097836017602002015161077e836102000151610779856101e0015161079c8a6027615464565b836017602002015250505050565b6150f76040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f604051806080016040528061512c7f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e76128ba565b815260200161515a7f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b6128ba565b81526020016151877e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac156128ba565b81526020016151b57f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b6128ba565b905290506151d26151c786601c615464565b61077e876002615464565b610120830181905261521190615206906151fb906151f090806128d8565b8561012001516128d8565b8461012001516128d8565b8361012001516128d8565b825261521e85601d615464565b602083015261522e85601e615464565b604083015261523e85601f615464565b60608301528151602083015161526691614ac89161525c91906128f1565b84604001516128f1565b6080830152615279613c5186600d615464565b610140830152815161529a9061529090835f610a27565b83608001516128f1565b60a08301526152c6846018602002015161077e8461014001516107798660a0015161079c8b6024615464565b61030085015260208201516152e19061529090836001610a27565b60c083015261530d846019602002015161077e8461014001516107798660c0015161079c8b6025615464565b61032085015260408201516153289061529090836002610a27565b60e083015261535484601a602002015161077e8461014001516107798660e0015161079c8b6026615464565b610340850152606082015161536f9061529090836003610a27565b61010083015261539d84601b602002015161077e84610140015161077986610100015161079c8b6027615464565b84601b613ad8565b5f6153b181848161092c565b905060015b601c811015615403576153f98261077e8684601c81106153d8576153d8615c5c565b6020020151866153e9600187615c0f565b601b8110610a2757610a27615c5c565b91506001016153b6565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f516020615f855f395f51905f5260a082015260205f60c08360055afa905080615458575f5ffd5b50505f51949350505050565b5f8282602881111561547857615478615f10565b6029811061548857615488615c5c565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f81526020016154ba6159a0565b81526020016154c76159a0565b81526020016154d46159a0565b81526020016154e16159a0565b81526020016154ee6159a0565b81526020016154fb6159a0565b81526020016155086159a0565b81526020016155156159a0565b81526020016155226159a0565b815260200161552f6159a0565b815260200161553c6159a0565b81526020016155496159a0565b81526020016155566159a0565b81526020016155636159a0565b81526020016155706159a0565b815260200161557d6159a0565b815260200161558a6159a0565b81526020016155976159a0565b81526020016155a46159a0565b81526020016155b16159a0565b81526020016155be6159a0565b81526020016155cb6159a0565b81526020016155d86159a0565b81526020016155e56159a0565b81526020016155f26159a0565b81526020016155ff6159a0565b815260200161560c6159a0565b81526020016156196159a0565b905290565b604051806102a00160405280615632615a1b565b815260200161563f615837565b815260200161564c615837565b8152602001615659615837565b8152602001615666615837565b8152602001615673615837565b8152602001615680615837565b815260200161568d615837565b815260200161569a615837565b81526020016156a7615a3a565b81526020015f81526020016156ba615a67565b81526020016156c7615a95565b81526020015f81526020016156da615837565b81526020015f81526020016156ed615ab4565b81526020016156fa6158c9565b8152602001615707615ae2565b8152602001615714615837565b8152602001615619615837565b60405180610140016040528061573561585b565b815260200161574261588b565b815260200161574f6158c9565b81526020015f81526020016157626158c9565b81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f81526020016157b8615ae2565b81526020016157c5615ae2565b81526020015f81526020015f81526020015f81526020015f81526020016156196158c9565b604051806109600160405280604b906020820280368337509192915050565b604051806109600160405280604b905b6158216159a0565b8152602001906001900390816158195790505090565b60405180608001604052805f81526020015f81526020015f81526020015f81525090565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806103600160405280601b906020820280368337509192915050565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b604051806101400160405280600a906020820280368337509192915050565b6040518061070001604052806038906020820280368337509192915050565b60405180610da00160405280606d906020820280368337509192915050565b6040518061042001604052806021906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b60405180604001604052805f81526020015f81525090565b6040518060e001604052806159cb615b00565b81526020015f81526020015f81526020015f81526020015f81526020016159f0615b00565b81526020015f81525090565b604051806101a00160405280600d906020820280368337509192915050565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b615a51615837565b815260200190600190039081615a495790505090565b604051806103800160405280601c905b615a7f6158aa565b815260200190600190039081615a775790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b615acc615837565b815260200190600190039081615ac45790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215615b33575f5ffd5b84356001600160401b03811115615b48575f5ffd5b8501601f81018713615b58575f5ffd5b80356001600160401b03811115615b6d575f5ffd5b876020828401011115615b7e575f5ffd5b6020918201955093508501356001600160401b03811115615b9d575f5ffd5b8501601f81018713615bad575f5ffd5b80356001600160401b03811115615bc2575f5ffd5b8760208260051b8401011115615bd6575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176128d2576128d2615be4565b818103818111156128d2576128d2615be4565b808201808211156128d2576128d2615be4565b5f5f85851115615c43575f5ffd5b83861115615c4f575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f60018201615c8157615c81615be4565b5060010190565b803560208310156128d2575f19602084900360031b1b1692915050565b5f8183825b6009811015615cc9578151835260209283019290910190600101615caa565b5050506101208201905092915050565b634e487b7160e01b5f52601260045260245ffd5b5f82615cfb57615cfb615cd9565b500490565b5f8183825b6006811015615d24578151835260209283019290910190600101615d05565b50505060c08201905092915050565b5f8183825b600a811015615d57578151835260209283019290910190600101615d38565b5050506101408201905092915050565b5f8183825b6038811015615d8b578151835260209283019290910190600101615d6c565b5050506107008201905092915050565b5f8183825b606d811015615dbf578151835260209283019290910190600101615da0565b505050610da08201905092915050565b5f8183825b6021811015615df3578151835260209283019290910190600101615dd4565b5050506104208201905092915050565b5f8183825b6005811015615e27578151835260209283019290910190600101615e08565b50505060a08201905092915050565b5f82615e4457615e44615cd9565b500690565b5f81615e5757615e57615be4565b505f190190565b5f82518060208501845e5f920191825250919050565b5f60208284031215615e84575f5ffd5b81518015158114611e70575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b81515f90829060208501835b82811015615ed1578151845260209384019390910190600101615eb3565b509195945050505050565b5f8183825b600d811015615f00578151835260209283019290910190600101615ee1565b5050506101a08201905092915050565b634e487b7160e01b5f52602160045260245ffdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a2646970667358221220e014e33eed9979b1221fd2473f2ad1fc99d1e336ddccceed397bba9148524fc364736f6c634300081d0033 diff --git a/eth/contracts/noir/migrate_HonkVerifier.bin b/eth/contracts/noir/migrate_HonkVerifier.bin new file mode 100644 index 0000000..9096d64 --- /dev/null +++ b/eth/contracts/noir/migrate_HonkVerifier.bin @@ -0,0 +1 @@ +60e060405234801561000f575f5ffd5b50600160808190525f60a081905260c081905280615a3961005f82395f818160d601526107ac01525f81816108da015281816109e701528181610f460152610ff201525f6107500152615a395ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b36600461555f565b610054565b604051901515815260200160405180910390f35b5f6100626101fc6020615637565b8414610081576040516376ba560560e11b815260040160405180910390fd5b5f61008a6101af565b90505f61009787876101c4565b9050601082604001516100aa919061564e565b84146100c95760405163fa06659360e01b815260040160405180910390fd5b5f6100fc828787865f01517f00000000000000000000000000000000000000000000000000000000000000006001610676565b905061014c8686808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250508551855160608101516080909101519193509150600161073a565b815160a0015261015c82826108bd565b610179576040516313f8744360e31b815260040160405180910390fd5b610184828483610a6f565b6101a1576040516352ec174560e11b815260040160405180910390fd5b506001979650505050505050565b6101b7614ed3565b6101bf61151b565b905090565b6101cc61505d565b5f805b601081101561022e576101fb8583866101e9826020615661565b926101f693929190615674565b611895565b8351826010811061020e5761020e61569b565b6020020181815250506020826102249190615661565b91506001016101cf565b50610252848285610240826080615661565b9261024d93929190615674565b6118b6565b6020830152610262608082615661565b9050610275848285610240826080615661565b6040830152610285608082615661565b9050610298848285610240826080615661565b60608301526102a8608082615661565b90506102bb848285610240826080615661565b60a08301526102cb608082615661565b90506102de848285610240826080615661565b60c08301526102ee608082615661565b9050610301848285610240826080615661565b6080808401919091526103149082615661565b9050610327848285610240826080615661565b60e0830152610337608082615661565b905061034a848285610240826080615661565b61010083015261035b608082615661565b905061036e848285610240826080615661565b61012083015152610380608082615661565b90506103938482856101e9826020615661565b6101408301526103a4602082615661565b90505f5b601c811015610423575f5b600981101561041a576103cd8684876101e9826020615661565b84610160015183601c81106103e4576103e461569b565b602002015182600981106103fa576103fa61569b565b6020020181815250506020836104109190615661565b92506001016103b3565b506001016103a8565b505f5b6029811015610477576104408583866101e9826020615661565b83610180015182602981106104575761045761569b565b60200201818152505060208261046d9190615661565b9150600101610426565b506104898482856101e9826020615661565b6101a083015261049a602082615661565b90506104ad848285610240826080615661565b610120830151602001526104c2608082615661565b90506104d5848285610240826080615661565b610120830151604001526104ea608082615661565b90506104fd848285610240826080615661565b6101c083015261050e608082615661565b90506105218482856101e9826020615661565b6101e0830152610532602082615661565b90505f5b6105426001601c61564e565b81101561058b5761055a858386610240826080615661565b83610200015182601b81106105715761057161569b565b6020020152610581608083615661565b9150600101610536565b505f5b601c8110156105df576105a88583866101e9826020615661565b83610220015182601c81106105bf576105bf61569b565b6020020181815250506020826105d59190615661565b915060010161058e565b505f5b6004811015610633576105fc8583866101e9826020615661565b83610240015182600481106106135761061361569b565b6020020181815250506020826106299190615661565b91506001016105e2565b50610645848285610240826080615661565b610260830152610656608082615661565b9050610669848285610240826080615661565b6102808301525092915050565b61067e615160565b5f61068e8888888888888761194c565b908352905061069d81896119a2565b602084019190915290506106b081611b7e565b604084019190915290506106c48189611bda565b606084019190915290506106d88882611c57565b608084019190915290506106ec8882611d26565b60a084019190915290506107008882612041565b60c0840191909152905061071488826121af565b60e0840191909152905061072888826122a2565b50610100830152509695505050505050565b5f600180826107838661077e896107796107748a7f0000000000000000000000000000000000000000000000000000000000000000615661565b6122f9565b612317565b612330565b90505f6107a18761079c8a6107796107748b6001615661565b612349565b90505f5b6107d060107f000000000000000000000000000000000000000000000000000000000000000061564e565b81101561083d575f6107fa8c83815181106107ed576107ed61569b565b60200260200101516122f9565b905061080a866107798684612330565b955061081a856107798584612330565b9450610826848b612330565b9350610832838b612349565b9250506001016107a5565b505f5b60108110156108a4575f8a826010811061085c5761085c61569b565b60200201519050610871866107798684612330565b9550610881856107798584612330565b945061088d848b612330565b9350610899838b612349565b925050600101610840565b506108af8484612378565b9a9950505050505050505050565b5f5f6108d28360600151856101400151612317565b905060015f5b7f00000000000000000000000000000000000000000000000000000000000000008110156109c4575f86610160015182601c81106109185761091861569b565b602002015180519091505f90610936908360015b6020020151612330565b9050848114610958576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c811061096f5761096f61569b565b602002015190506109808382612386565b95506109b485610779600161077e856107798e604001518b601c81106109a8576109a861569b565b60200201516001612349565b94505050508060010190506108d8565b505f6109de866101800151865f01518760200151856124e8565b9050600160025b7f0000000000000000000000000000000000000000000000000000000000000000811015610a3b57610a3182886080015183601c8110610a2757610a2761569b565b6020020151612317565b91506001016109e5565b50610a61610a4e83610779600185612349565b61077e896101a001518960600151612317565b939093149695505050505050565b5f610a786151c5565b5f610a868460c00151612562565b9050610a90615229565b610a98615248565b610100860151610ab890610ab390855f5b6020020151612349565b6125c7565b60e0850152610100860151610ad290610ab390855f61092c565b610100850181905260e08086015190880151610af29261077e9190612317565b845260c0860151610b2190610b06906125c7565b6107798660e0015161079c8a60e00151896101000151612317565b602085015260018252610260880151610b3990612630565b81526101e0880151608085015260a086015160608501528351610b5b9061266f565b60208301525f5b6024811015610bff57610b84610b7a865f015161266f565b8660600151612317565b83610b90836002615661565b604b8110610ba057610ba061569b565b602002015260808501516101808a0151610bd9919061077e908460298110610bca57610bca61569b565b60200201518860600151612317565b6080860152606085015160a0880151610bf29190612317565b6060860152600101610b62565b5060245b6029811015610c8857610c1c610b7a866020015161266f565b83610c28836002615661565b604b8110610c3857610c3861569b565b602002015260808501516101808a0151610c62919061077e908460298110610bca57610bca61569b565b6080860152606085015160a0880151610c7b9190612317565b6060860152600101610c03565b50610c97886101c00151612630565b8160016020020152606087015181600260200201526080870151816003602002015260a0870151816004602002015260c0870151816005602002015260e0870151816006602002015261010087015181600760200201526101208701518160086020020152610140870151816009602002015261016087015181600a60200201526101c087015181600b602002015261018087015181600c60200201526101a087015181600d60200201526101e087015181600e602002015261020087015181600f602002015261022087015181601060200201526102408701518160116020020152610260870151816012602002015261028087015181601360200201526102a087015181601460200201526102c087015181601560200201526102e0870151816016602002015261030087015181601760200201526103208701518160186020020152610340870151816019602002015261036087015181601a602002015261038087015181601b60200201526103a087015181601c60200201526103c087015181601d6020020181905250610e328860200151612630565b6103c08201526040880151610e4690612630565b6103e08201526060880151610e5a90612630565b6104008201526080880151610e6e90612630565b610420820152610100880151610e8390612630565b61044082015260e0880151610e9790612630565b61046082015260a0880151610eab90612630565b61048082015260c0880151610ebf90612630565b6104a08201526020880151610ed390612630565b6104c08201526040880151610ee790612630565b6104e08201526060880151610efb90612630565b6105008201526080880151610f0f90612630565b610520820152610100880151610f2490612630565b81602a60200201819052505f610f6a876080015186608001518b6102200151877f0000000000000000000000000000000000000000000000000000000000000000612687565b805160e0870151919250610f7d91612317565b604086018190526102208a01515160e0890151610fae929161077e91610fa39190612317565b886101000151612317565b604086015260e0870151610fc1906127a2565b60608601525f610fd360296002615661565b90505f5b610fe36001601c61564e565b8110156111d1575f61101660017f000000000000000000000000000000000000000000000000000000000000000061564e565b82101590508061115f5761104a610ab38b61010001518985600161103a9190615661565b601c8110610aa957610aa961569b565b60e08901526101008a015161107990610ab39089611069866001615661565b601c811061092c5761092c61569b565b610100890152606088015160e08901516110939190612317565b610120890152606088015160e08b01516110bb916110b091612317565b896101000151612317565b61014089018190526110de906110d09061266f565b61077e8a610120015161266f565b866110e98486615661565b604b81106110f9576110f961569b565b60200201526101408801516102208d01515f9161112b9161111b866001615661565b601c8110610a2757610a2761569b565b90506111488161077e8b61012001518887600161111b9190615661565b9050611158896040015182612330565b60408a0152505b61117e61117489606001518c60e00151612317565b8b60e00151612317565b60608901526102008c01516111a89083601b811061119e5761119e61569b565b6020020151612630565b856111b38486615661565b604b81106111c3576111c361569b565b602002015250600101610fd7565b506111de6001601c61564e565b6111e89082615661565b90506112086112008961010001518a60c00151612349565b600190612378565b60a08701515261010088015160c089015161124c916112009161079c907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a7690612317565b60a087018051602001919091528051805160409091015251805160609182015286015160e089015161128b9161128191612317565b8960e00151612317565b60608701525f5b6004811015611338575f6112c48860a0015183600481106112b5576112b561569b565b60200201518960600151612317565b90506112cf8161266f565b8860c0015183600481106112e5576112e561569b565b6020020152606088015160e08b01516112fe9190612317565b88606001818152505061132a886040015161077e838f61024001518660048110610a2757610a2761569b565b604089015250600101611292565b5060c0860151518482604b81106113515761135161569b565b602002015260c0860151611372906001602002015160c0880151600261092c565b8461137e836001615661565b604b811061138e5761138e61569b565b602002015260c086015160600151846113a8836002615661565b604b81106113b8576113b861569b565b60200201525f5b600381101561140c576113e28b6101200151826003811061119e5761119e61569b565b84836113ed816156af565b9450604b81106113ff576113ff61569b565b60200201526001016113bf565b5060405180604001604052806001815260200160028152508382604b81106114365761143661569b565b60200201526040860151848261144b816156af565b9350604b811061145d5761145d61569b565b6020020181815250506114848a61024001518960c001518a608001518d6101a001516127ad565b6114a15760405163a2a2ac8360e01b815260040160405180910390fd5b5f6114b08b6102800151612630565b9050808483604b81106114c5576114c561569b565b60200201526101008901518583604b81106114e2576114e261569b565b60200201525f6114f28587612aca565b90505f6114fe83612b9c565b905061150a8282612be2565b9d9c50505050505050505050505050565b611523614ed3565b50604080516103e081018252600181525f60208083018290528284018290528351808501855282815280820183905260608401528351808501855282815277e0d7e05401000000d0d9e05401000000c0dbe05401000000818301526080840152835180850185527f1fb0f4fb5d6b1f8377ef0f307c7bf6e7ca5da09fc7aaa058cc823c0f7789082b81527f101d436e3e9cbfad604c54e6fdfd4f4531e50b31301c6ae5d8a8c826500605728183015260a0840152835180850185527f3028436e3e9cbfad105254e6fdfd4f4541f20b31301c6ae587bee7d24f060572815277800be1540100000060832d02006000000018e154010000008183015260c0840152835180850185527f301fde8f1f2e5fd6a7d89b9d7f7ea7a28905c27097ee3573a414553d288302b981527f1fbf901c3dfcbfacbfa755e6fdfd4f45318757df2f7c6ae61816c926500605728183015260e0840152835180850185527f0f6041a95ccb1f83b77910307c7bf6e77a0bed4dc70aa0584b9e5bbb7689082b815280820183905261010084015283518085018552828152808201839052610120840152835180850185528281528082018390526101408401528351808501855282815280820183905261016084015283518085018552828152808201839052610180840152835180850185528281528082018390526101a0840152835180850185528281528082018390526101c0840152835180850185528281528082018390526101e08401528351808501855282815280820183905261020084015283518085018552828152808201839052610220840152835180850185528281528082018390526102408401528351808501855282815280820183905261026084015283518085018552828152808201839052610280840152835180850185528281528082018390526102a0840152835180850185528281528082018390526102c0840152835180850185528281528082018390526102e08401528351808501855282815280820183905261030084015283518085018552828152808201839052610320840152835180850185528281528082018390526103408401528351808501855282815280820183905261036084015283518085018552828152808201839052610380840152835180850185528281528082018390526103a084015283518085019094528184528301526103c081019190915290565b5f602082146118a2575f5ffd5b6118af61077483856156c7565b9392505050565b6118be615276565b608082146118ca575f5ffd5b6040805160808101909152806118e360205f8688615674565b6118ec916156c7565b8152602090810190611902906040908688615674565b61190b916156c7565b815260200161191e606060408688615674565b611927916156c7565b815260200161193a608060608688615674565b611943916156c7565b90529392505050565b61195461529a565b5f611963898989898989612dd6565b604086019190915260208501919091529083529250611982838a613278565b608085019190915260608401919091529199919850909650505050505050565b6119aa6152ca565b5f6119b36152e9565b84815260e0848101805151602080850191909152815181015160408086019190915282518101516060808701919091529251830151608086015261010080890180515160a0880152805184015160c08801528051830151958701959095529351909201519284019290925251611a4a91611a2f918491016156e4565b604051602081830303815290604052805190602001206122f9565b9150611a5582613347565b6020850152835260015b6002611a6d6001601c61564e565b611a77919061572c565b811015611af757611a9483604051602001611a2f91815260200190565b9250611a9f83613347565b85611aab846002615637565b601b8110611abb57611abb61569b565b6020020186611acb856002615637565b611ad6906001615661565b601b8110611ae657611ae661569b565b602002019190915252600101611a5f565b50611b046001601c61564e565b6001166001148015611b2157506002611b1f6001601c61564e565b115b15611b7657611b3c82604051602001611a2f91815260200190565b9150611b4782613347565b50836001611b5681601c61564e565b611b60919061564e565b601b8110611b7057611b7061569b565b60200201525b509250929050565b611b86615308565b5f805b601c811015611bd357611ba884604051602001611a2f91815260200190565b9350611bb384613347565b508382601c8110611bc657611bc661569b565b6020020152600101611b89565b5090929050565b5f5f611be4615327565b84815261012084018051515160208084019190915281515181015160408085019190915282515181015160608086019190915292515190920151608084015261014086015160a08401529051611c4091611a2f9184910161573f565b9150611c4b82613347565b50959194509092505050565b611c5f615308565b5f805b601c811015611d1d57611c73615345565b8481525f5b6009811015611cdc5786610160015183601c8110611c9857611c9861569b565b60200201518160098110611cae57611cae61569b565b602002015182611cbf836001615661565b600a8110611ccf57611ccf61569b565b6020020152600101611c78565b50611cf181604051602001611a2f9190615772565b9450611cfc85613347565b508483601c8110611d0f57611d0f61569b565b602002015250600101611c62565b50909391925050565b5f5f611d30615364565b83815260015b60298111611d8d57610180860151611d4f60018361564e565b60298110611d5f57611d5f61569b565b6020020151828260388110611d7657611d7661569b565b602002015280611d85816156af565b915050611d36565b856101a00151828260388110611da557611da561569b565b6020020152611db5600182615661565b6101208701516020015151909150828260388110611dd557611dd561569b565b6020020152610120860151600160200201516020015182826001611df99190615661565b60388110611e0957611e0961569b565b6020020152610120860151600160200201516040015182611e2b836002615661565b60388110611e3b57611e3b61569b565b6020020152610120860151600160200201516060015182611e5d836003615661565b60388110611e6d57611e6d61569b565b6020020152611e7d600482615661565b6101208701516040015151909150828260388110611e9d57611e9d61569b565b6020020152610120860151600260200201516020015182826001611ec19190615661565b60388110611ed157611ed161569b565b6020020152610120860151604090810151015182611ef0836002615661565b60388110611f0057611f0061569b565b6020020152610120860151604001516060015182611f1f836003615661565b60388110611f2f57611f2f61569b565b6020020152611f3f600482615661565b6101c087015151909150828260388110611f5b57611f5b61569b565b602002018181525050856101c001516020015182826001611f7c9190615661565b60388110611f8c57611f8c61569b565b60200201526101c08601516040015182611fa7836002615661565b60388110611fb757611fb761569b565b60200201526101c08601516060015182611fd2836003615661565b60388110611fe257611fe261569b565b6020020152611ff2600482615661565b9050856101e0015182826038811061200c5761200c61569b565b60200201818152505061202982604051602001611a2f91906157a6565b925061203483613347565b5096929550919350505050565b5f5f61204b615383565b8381525f5b61205c6001601c61564e565b81101561219a5785610200015181601b811061207a5761207a61569b565b6020020151518261208c836004615637565b612097906001615661565b606d81106120a7576120a761569b565b602002015261020086015181601b81106120c3576120c361569b565b602002015160200151828260046120da9190615637565b6120e5906002615661565b606d81106120f5576120f561569b565b602002015261020086015181601b81106121115761211161569b565b60200201516040015182612126836004615637565b612131906003615661565b606d81106121415761214161569b565b602002015261020086015181601b811061215d5761215d61569b565b60200201516060015182612172836004615637565b61217d906004615661565b606d811061218d5761218d61569b565b6020020152600101612050565b50611c4081604051602001611a2f91906157da565b5f5f6121b96153a2565b83815260015b601c8111612216576102208601516121d860018361564e565b601c81106121e8576121e861569b565b60200201518282602181106121ff576121ff61569b565b60200201528061220e816156af565b9150506121bf565b505f80612225601c6001615661565b90505b612234601c6004615661565b811161228d5786610240015182600481106122515761225161569b565b60200201518382602181106122685761226861569b565b602002015281612277816156af565b9250508080612285906156af565b915050612228565b5061202982604051602001611a2f919061580e565b5f5f6122ac6153c1565b83815261026085018051516020808401919091528151810151604080850191909152825181015160608086019190915292519092015160808401529051611c4091611a2f91849101615842565b5f6123115f5160206159c45f395f51905f5283615875565b92915050565b5f5f5160206159c45f395f51905f528284099392505050565b5f5f5160206159c45f395f51905f528284089392505050565b5f5f5160206159c45f395f51905f5261236f835f5160206159c45f395f51905f5261564e565b84089392505050565b5f6118af83610779846125c7565b5f5f604051806101200160405280619d8081526020015f5160206159e45f395f51905f5281526020016105a081526020015f5160206159645f395f51905f52815260200161024081526020015f5160206159645f395f51905f5281526020016105a081526020015f5160206159e45f395f51905f528152602001619d8081525090505f600190505f5f90505b600981101561243357612429826107798784612349565b9150600101612412565b5061243c6152e9565b5f5b600981101561248d5761246e610ab385836009811061245f5761245f61569b565b60200201516107798985612349565b8282600981106124805761248061569b565b602002015260010161243e565b505f5b60098110156124d3576124c98561077e8984600981106124b2576124b261569b565b6020020151858560098110610a2757610a2761569b565b9450600101612490565b506124de8483612317565b9695505050505050565b5f6124f1615308565b6124fc868285613377565b61250886868386613523565b6125148686838661370f565b61251f868285613934565b61252a868285613b28565b61253686868386613e71565b61254286868386614324565b61254d868285614723565b612558868285614ae4565b6124de8185614de4565b61256a615308565b81815260015b601c8110156125c1576125a28261258860018461564e565b601c81106125985761259861569b565b60200201516127a2565b8282601c81106125b4576125b461569b565b6020020152600101612570565b50919050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f5160206159c45f395f51905f520360808201525f5160206159c45f395f51905f5260a082015260205f60c08360055afa905080612625575f5ffd5b50505f519392505050565b6126386153df565b604051806040016040528060888460200151901b845f015117815260200160888460600151901b8460400151178152509050919050565b5f612311825f5160206159c45f395f51905f5261564e565b61268f615308565b601c5b8015612798575f846126a560018461564e565b601c81106126b5576126b561569b565b602002015190505f886126c960018561564e565b601c81106126d9576126d961569b565b602002015190505f6127346126f86126f1858c612317565b6002612317565b61079c8a61270760018961564e565b601c81106127175761271761569b565b602002015161077961272e8861077960018a612349565b87612349565b905061275581610779610ab361274f87610779600189612349565b86612330565b905085841161278457975087808561276e60018761564e565b601c811061277e5761277e61569b565b60200201525b5050508061279190615888565b9050612692565b5095945050505050565b5f6123118283612317565b5f6001816127c66127c087610100614e49565b83612349565b9050806127e65760405163835eb8f760e01b815260040160405180910390fd5b6127ee6153f7565b80518390525f5b601c8110156128b8575f61280a826009615637565b612815906001615661565b905084835f015182610100811061282e5761282e61569b565b60200201525f61283f826001615661565b90505b61284d600983615661565b8110156128ae57835161288d9061286560018461564e565b61010081106128765761287661569b565b60200201518a85601c8110610a2757610a2761569b565b84518261010081106128a1576128a161569b565b6020020152600101612842565b50506001016127f5565b50608081018390525f602082018190525b6101008110156129b6576128ea6128e483608001518a612317565b85612349565b8260a001518261010081106129015761290161569b565b602002015260a082015161292b908261010081106129215761292161569b565b60200201516125c7565b8260a001518261010081106129425761294261569b565b602002018181525050612988826020015161077e845f015184610100811061296c5761296c61569b565b60200201518560a00151856101008110610a2757610a2761569b565b602083015260808201516129a9905f5160206159a45f395f51905f52612317565b60808301526001016128c9565b505f6129c7836107796101006125c7565b90506129d7826020015182612317565b602083015260a08201516129f2905f5b602002015182612317565b604083015260a0820151612a1e90612a0d600161010061564e565b61010081106129e7576129e761569b565b60608301526040820151612a34908a6002610a27565b60c08301819052612a809061077e612a598b5f5160206159a45f395f51905f52612349565b610779612a6f8e600160200201518f6002610aa9565b8e51602089015161079c9190612317565b60c083018190526060830151612ab591612aa99161077e906107798e600260200201518c612349565b61079c858c6003610a27565b60c08301819052159998505050505050505050565b612ad26153df565b5f6003612ae1601c6029615661565b612aeb9190615661565b612af6906003615661565b90506001604051855151604082015285516020015160608201528451608082015260408160606040840160075afa8216915060015b83811015612b845760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa90921691600101612b2b565b50805184526020810151602085015250505092915050565b612ba46153df565b5f5160206159845f395f51905f5282602001515f5160206159845f395f51905f52612bcf919061564e565b612bd99190615875565b60208301525090565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b031683604051612d78919061589d565b5f60405180830381855afa9150503d805f8114612db0576040519150601f19603f3d011682016040523d82523d5f602084013e612db5565b606091505b50915091508180156124de5750808060200190518101906124de91906158b3565b5f80808080612de6876003615661565b612df190600c615661565b6001600160401b03811115612e0857612e086158d2565b604051908082528060200260200182016040528015612e31578160200160208202803683370190505b509050875f1b815f81518110612e4957612e4961569b565b602002602001018181525050865f1b81600181518110612e6b57612e6b61569b565b602002602001018181525050855f1b81600281518110612e8d57612e8d61569b565b60209081029190910101525f5b612ea560108961564e565b811015612ef6578a8a82818110612ebe57612ebe61569b565b9050602002013582826003612ed39190615661565b81518110612ee357612ee361569b565b6020908102919091010152600101612e9a565b505f5b6010811015612f67578b51612f21908260108110612f1957612f1961569b565b602002015190565b82826010612f308c6003615661565b612f3a919061564e565b612f449190615661565b81518110612f5457612f5461569b565b6020908102919091010152600101612ef9565b5060208b01515181612f7a896003615661565b81518110612f8a57612f8a61569b565b6020908102919091018101919091528b810151015181612fab896003615661565b612fb6906001615661565b81518110612fc657612fc661569b565b6020908102919091018101919091528b01516040015181612fe8896003615661565b612ff3906002615661565b815181106130035761300361569b565b6020908102919091018101919091528b01516060015181613025896003615661565b613030906003615661565b815181106130405761304061569b565b602090810291909101015260408b0151518161305d896003615661565b613068906004615661565b815181106130785761307861569b565b60209081029190910181019190915260408c015101518161309a896003615661565b6130a5906005615661565b815181106130b5576130b561569b565b60209081029190910101526040808c01510151816130d4896003615661565b6130df906006615661565b815181106130ef576130ef61569b565b602090810291909101015260408b0151606001518161310f896003615661565b61311a906007615661565b8151811061312a5761312a61569b565b602090810291909101015260608b01515181613147896003615661565b613152906008615661565b815181106131625761316261569b565b60209081029190910181019190915260608c0151015181613184896003615661565b61318f906009615661565b8151811061319f5761319f61569b565b602090810291909101015260608b015160400151816131bf896003615661565b6131ca90600a615661565b815181106131da576131da61569b565b60209081029190910101526060808c01510151816131f9896003615661565b61320490600b615661565b815181106132145761321461569b565b60200260200101818152505061323481604051602001611a2f91906158e6565b915061323f82613347565b604080516020810186905292975090955061325a9101611a2f565b915061326582613347565b5080935050509650965096509692505050565b5f5f5f61328361543b565b85815260a085810180515160208085019190915281518101516040808601919091528251810151606080870191909152925183015160808087019190915260c0808b0180515196880196909652855184015190870152845182015160e08701529351830151610100860152928801805151610120860152805182015161014086015280518401516101608601525190910151610180840152905161332d91611a2f9184910161591b565b915061333882613347565b90979096509194509092505050565b5f80826001600160801b038116608082901c613362826122f9565b945061336d816122f9565b9350505050915091565b5f613383846007614ea3565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f6133e46133de6133b8856003612349565b6107796133d36133c88b5f614ea3565b6107798c601d614ea3565b6107798b601c614ea3565b83612317565b905061346561345a61344161342861340f8561077e6134048d6002614ea3565b6107798e601c614ea3565b61077e61341d8c6003614ea3565b6107798d601d614ea3565b61077e6134368b6004614ea3565b6107798c601e614ea3565b61077e61344f8a6005614ea3565b6107798b601f614ea3565b61077e886001614ea3565b90506134848161077e613479866001612349565b6107798a6027614ea3565b90506134908184612317565b905061349c8185612317565b8552505f90506134d66134cc6134c16134b688601c614ea3565b61077e89601f614ea3565b61079c886024614ea3565b61077e875f614ea3565b90506134e781610779846002612349565b90506134f881610779846001612349565b90506135048183612317565b90506135108184612317565b9050808460015b60200201525050505050565b5f5f5f61355961354f61353789601c614ea3565b61077e6135458b6012614ea3565b8a60600151612317565b8760800151612330565b9050613592816107796135886135708b601d614ea3565b61077e61357e8d6013614ea3565b8c60600151612317565b8960800151612330565b90506135b7816107796135886135a98b601e614ea3565b61077e61357e8d6014614ea3565b90506135dc816107796135886135ce8b601f614ea3565b61077e61357e8d6015614ea3565b92505f905061360061354f6135f289601c614ea3565b61077e6135458b600e614ea3565b9050613625816107796135886136178b601d614ea3565b61077e61357e8d600f614ea3565b905061364a8161077961358861363c8b601e614ea3565b61077e61357e8d6010614ea3565b905061366f816107796135886136618b601f614ea3565b61077e61357e8d6011614ea3565b91505f9050613696613690613685896020614ea3565b61077e8a601a614ea3565b84612317565b90506136cb8161079c6136c56136ad8b6028614ea3565b61077e6136bb8d601b614ea3565b8c60a00151612317565b85612317565b90506136d78185612317565b6040860152505f6136fa6136c56136ef89601b614ea3565b6107798a6028614ea3565b9050808560035b602002015250505050505050565b5f5f61376d61375561373d6137286135888a6016614ea3565b61077e6137368b6017614ea3565b8a51612317565b61077e61374b8a6018614ea3565b8960200151612317565b61077e613763896019614ea3565b8860400151612317565b91505f6137a461378b61378189601c614ea3565b8860800151612330565b61077e6137998a6003614ea3565b6107798b6024614ea3565b90505f6137cd6137b589601d614ea3565b61077e6137c28b5f614ea3565b6107798c6025614ea3565b90505f6137f76137de8a601e614ea3565b61077e6137ec8c6001614ea3565b6107798d6026614ea3565b905061383661381e6138108561077e868d5f0151612317565b61077e848c60200151612317565b61077e61382c8c6004614ea3565b8b60400151612317565b93505050505f61384a613690886021614ea3565b90505f61385b613690896021614ea3565b90505f61389361387a61386f8b6023614ea3565b61077e8c6006614ea3565b61079c6138888c6023614ea3565b6107798d6006614ea3565b90505f6138b16127c06138a68789612317565b6107798d6021614ea3565b90506138bd8188612317565b90505f6138e56138d76138d18d6006614ea3565b87612317565b61079c6138d18e6022614ea3565b90505f6138f38c6023614ea3565b90505f6139036127c08384612317565b60808c0185905260a08c01849052905061391d818b612317565b8b6006602002015250505050505050505050505050565b5f6139405f6001612349565b90505f61394e5f6002612349565b90505f61395c5f6003612349565b90505f61397861396d88601d614ea3565b61079c89601c614ea3565b90505f61399461398989601e614ea3565b61079c8a601d614ea3565b90505f6139b06139a58a601f614ea3565b61079c8b601e614ea3565b90505f6139cc6139c18b6024614ea3565b61079c8c601f614ea3565b9050836139dd81610779818b612330565b90506139ed81610779878a612330565b90506139fd816107798789612330565b9050613a0e816107798d6008614ea3565b9050613a1a818a612317565b60e08b01525082613a2f81610779818b612330565b9050613a3f81610779868a612330565b9050613a4f816107798689612330565b9050613a60816107798d6008614ea3565b9050613a6c818a612317565b6101008b01525081613a8281610779818b612330565b9050613a9281610779858a612330565b9050613aa2816107798589612330565b9050613ab3816107798d6008614ea3565b9050613abf818a612317565b6101208b01525080613ad581610779818b612330565b9050613ae581610779848a612330565b9050613af5816107798489612330565b9050613b06816107798d6008614ea3565b9050613b12818a612317565b610140909a019990995250505050505050505050565b613b616040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613b6c84601d614ea3565b8152613b7984601e614ea3565b6020820152613b89846024614ea3565b6040820152613b99846027614ea3565b6060820152613ba9846026614ea3565b6080820152613bb9846025614ea3565b60a08201525f613bca856002614ea3565b90505f613bd7865f614ea3565b90505f613beb8460400151855f0151612349565b90505f613c0085602001518660200151612317565b606086015190915086905f90613c169080612317565b90505f613c34613c2e89602001518a60600151612317565b88612317565b90505f613c53613c4c8a60a001518b60400151612330565b8a51612330565b9050613c626138d18288612317565b9050613c89613c83613c7d613c778487612349565b88612349565b84612330565b83612330565b9050613cb1613ca6613c9b8387612317565b6107798f6009614ea3565b61077960018a612349565b6101608c015250505050602085015160808601515f91613cd091612330565b90505f613cee613ce4886060015188612317565b8860200151612349565b90505f613d12613cfe8487612317565b61077e6136c58b60a001518c5f0151612349565b9050613d3a613d2f613d24838c612317565b6107798e6009614ea3565b610779600189612349565b6101808b0152505f9150613d5b9050613d54836011612330565b8751612317565b90505f613d688384612330565b9050613d748182612330565b90505f613d82836009612317565b9050613dab613da5613690613d9e8b60a001518c5f0151612330565b8b51612330565b82612349565b60c089018190525f90613dc690613c2e90613c9b908d612317565b9050613dd98b600b602002015182612330565b6101608c0152505086515f9250613e009150613d5490613df99080612330565b8851612330565b90505f613e40613e1b836107798a5f01518b60a00151612349565b602089015161079c90613e2e9080612330565b6107798b602001518c60800151612330565b9050613e5d89600c602002015161077e613c2e613c9b858d612317565b89600c602002015250505050505050505050565b613edb604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613ef3613ee986601e614ea3565b8560400151612317565b808252613f129061077e613f0888601d614ea3565b8760200151612317565b808252613f279061077e613d5488601c614ea3565b808252613f399061077e876001614ea3565b80825260208201819052613f529061079c87601f614ea3565b8152613f6d613f62866024614ea3565b61079c87601c614ea3565b6080820152613f8b613f80866027614ea3565b61079c87601f614ea3565b60608201526080810151613fad90613fa39080612317565b8260800151612349565b6101c08201526080810151613fed90613fe390613fdc9061077960015f5160206159c45f395f51905f5261564e565b6001612330565b8260600151612317565b60a08201819052614023906140159061077961400a896002614ea3565b6107798a6003614ea3565b6107796136c588600a614ea3565b83600e60200201526101c0810151614047906140159061077961400a896002614ea3565b6101e0840152805161406c90610779614061886002614ea3565b610779896003614ea3565b6101208201525f61408b61408187601f614ea3565b8360200151612349565b905061409a613da58283612317565b60e08301526140b76140ad876026614ea3565b8660400151612317565b604083018190526140da9061077e6140d0896025614ea3565b8860200151612317565b604083018190526140fa9061077e6140f3896024614ea3565b8851612317565b604083015261411761410d876027614ea3565b8360400151612349565b60408301525f61413661412b886026614ea3565b61079c89601e614ea3565b90506141886141636133de613fdc866080015160015f5160206159c45f395f51905f52610779919061564e565b610779613fdc866040015160015f5160206159c45f395f51905f52610779919061564e565b60c084015260408301516141aa906141a09080612317565b8460400151612349565b61010084015260c08301516141d6906141c8906107798a6007614ea3565b6107796138d18a600a614ea3565b6102008601526101c08301516141f5906141c8906107798a6007614ea3565b610220860152610100830151614214906141c8906107798a6007614ea3565b61024086015260e083015161422e90610779896007614ea3565b61014084015261424d614242886025614ea3565b61079c89601d614ea3565b610160840152608083015161428b9061412b9061428090613fdc9061077960015f5160206159c45f395f51905f5261564e565b856101600151612317565b61018084018190526101208401516101a085018190526142c29161077e906107796142b78c6005614ea3565b6107798d6002614ea3565b6101a0840181905283516142e2919061077e906107796142b78c5f614ea3565b6101a084018190526101408401516142fa9190612330565b6101a08401819052614314906107796138d18a600a614ea3565b6101a0840181905285600d613701565b61435d6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61439261437961436e87601c614ea3565b610779886025614ea3565b61077e614387886024614ea3565b61077989601d614ea3565b81526143d76143cc6143b36143a888601c614ea3565b61077989601f614ea3565b61077e6143c189601d614ea3565b6107798a601e614ea3565b61079c876026614ea3565b604082018190526143ec90600160441b612317565b604082018190526144029061079c876027614ea3565b6040820181905281516144159190612330565b6040820181905261442b90610779876005614ea3565b6040820152805161444090600160441b612317565b8082526144609061077e614455886024614ea3565b610779896025614ea3565b8082526020820181905261447c9061079c6134b688601e614ea3565b6020820181905261449290610779876004614ea3565b60208201528051606082018190526144af9061077e87601f614ea3565b606082018190526144d39061079c6144c8886026614ea3565b61077e896027614ea3565b606082018190526144e890610779875f614ea3565b8160600181815250505f61451161450783602001518460400151612330565b8360600151612330565b905061452281610779886003614ea3565b905061453a614532876025614ea3565b614000612317565b608083018190526145509061077e886024614ea3565b6080830181905261456390614000612317565b608083018190526145799061077e88601e614ea3565b6080830181905261458c90614000612317565b608083018190526145a29061077e88601d614ea3565b608083018190526145b590614000612317565b608083018190526145cb9061077e88601c614ea3565b608083018190526145e19061079c88601f614ea3565b608083018190526145f790610779886005614ea3565b608083015261460a614532876026614ea3565b60a083018190526146209061077e886025614ea3565b60a0830181905261463390614000612317565b60a083018190526146499061077e886024614ea3565b60a0830181905261465c90614000612317565b60a083018190526146729061077e88601f614ea3565b60a0830181905261468590614000612317565b60a0830181905261469b9061077e88601e614ea3565b60a083018190526146b19061079c886027614ea3565b60a083018190526146c690610779885f614ea3565b60a0830181905260808301515f916146de9190612330565b90506146ef81610779896004614ea3565b90506146fb8282612330565b60c08401819052614714906107796138d18a600b614ea3565b60c08401819052856013613701565b6147996040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6147b26147a785601c614ea3565b61077e866002614ea3565b81526147cd6147c285601d614ea3565b61077e866003614ea3565b60208201526147eb6147e085601e614ea3565b61077e866004614ea3565b60408201526148096147fe85601f614ea3565b61077e866005614ea3565b6060820152805161483b906148349061482d906148269080612317565b8451612317565b8351612317565b8251612317565b608082015260208101516148799061486f906148659061485b9080612317565b8460200151612317565b8360200151612317565b8260200151612317565b60a082015260408101516148b7906148ad906148a3906148999080612317565b8460400151612317565b8360400151612317565b8260400151612317565b60c082015260608101516148eb90613fe3906148e1906148d79080612317565b8460600151612317565b8360600151612317565b60e0820152608081015160a08201516149049190612330565b61010082015260c081015160e082015161491e9190612330565b61012082015260a0810151614942906149379080612330565b826101200151612330565b61014082015260e08101516149669061495b9080612330565b826101000151612330565b61016082015261012081015161497c9080612330565b6101e0820181905261499d906149929080612330565b826101600151612330565b6101e08201526101008101516149b39080612330565b6101a082018190526149d4906149c99080612330565b826101400151612330565b6101a082018190526101608201516149eb91612330565b6101808201526101408101516101e0820151614a079190612330565b6101c0820152614a1b6133de85600c614ea3565b6102008201819052610280840151610180830151614a469261077e916107799061079c8a6024614ea3565b8360146020020152614a76836015602002015161077e836102000151610779856101a0015161079c8a6025614ea3565b8360156020020152614aa6836016602002015161077e836102000151610779856101c0015161079c8a6026614ea3565b8360166020020152614ad6836017602002015161077e836102000151610779856101e0015161079c8a6027614ea3565b836017602002015250505050565b614b366040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f6040518060800160405280614b6b7f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e76122f9565b8152602001614b997f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b6122f9565b8152602001614bc67e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac156122f9565b8152602001614bf47f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b6122f9565b90529050614c11614c0686601c614ea3565b61077e876002614ea3565b6101208301819052614c5090614c4590614c3a90614c2f9080612317565b856101200151612317565b846101200151612317565b836101200151612317565b8252614c5d85601d614ea3565b6020830152614c6d85601e614ea3565b6040830152614c7d85601f614ea3565b606083015281516020830151614ca59161450791614c9b9190612330565b8460400151612330565b6080830152614cb861369086600d614ea3565b6101408301528151614cd990614ccf90835f610a27565b8360800151612330565b60a0830152614d05846018602002015161077e8461014001516107798660a0015161079c8b6024614ea3565b6103008501526020820151614d2090614ccf90836001610a27565b60c0830152614d4c846019602002015161077e8461014001516107798660c0015161079c8b6025614ea3565b6103208501526040820151614d6790614ccf90836002610a27565b60e0830152614d9384601a602002015161077e8461014001516107798660e0015161079c8b6026614ea3565b6103408501526060820151614dae90614ccf90836003610a27565b610100830152614ddc84601b602002015161077e84610140015161077986610100015161079c8b6027614ea3565b84601b613517565b5f614df081848161092c565b905060015b601c811015614e4257614e388261077e8684601c8110614e1757614e1761569b565b602002015186614e2860018761564e565b601b8110610a2757610a2761569b565b9150600101614df5565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f5160206159c45f395f51905f5260a082015260205f60c08360055afa905080614e97575f5ffd5b50505f51949350505050565b5f82826028811115614eb757614eb761594f565b60298110614ec757614ec761569b565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f8152602001614ef96153df565b8152602001614f066153df565b8152602001614f136153df565b8152602001614f206153df565b8152602001614f2d6153df565b8152602001614f3a6153df565b8152602001614f476153df565b8152602001614f546153df565b8152602001614f616153df565b8152602001614f6e6153df565b8152602001614f7b6153df565b8152602001614f886153df565b8152602001614f956153df565b8152602001614fa26153df565b8152602001614faf6153df565b8152602001614fbc6153df565b8152602001614fc96153df565b8152602001614fd66153df565b8152602001614fe36153df565b8152602001614ff06153df565b8152602001614ffd6153df565b815260200161500a6153df565b81526020016150176153df565b81526020016150246153df565b81526020016150316153df565b815260200161503e6153df565b815260200161504b6153df565b81526020016150586153df565b905290565b604051806102a0016040528061507161545a565b815260200161507e615276565b815260200161508b615276565b8152602001615098615276565b81526020016150a5615276565b81526020016150b2615276565b81526020016150bf615276565b81526020016150cc615276565b81526020016150d9615276565b81526020016150e6615479565b81526020015f81526020016150f96154a6565b81526020016151066154d4565b81526020015f8152602001615119615276565b81526020015f815260200161512c6154f3565b8152602001615139615308565b8152602001615146615521565b8152602001615153615276565b8152602001615058615276565b60405180610140016040528061517461529a565b81526020016151816152ca565b815260200161518e615308565b81526020015f81526020016151a1615308565b81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f81526020016151f7615521565b8152602001615204615521565b81526020015f81526020015f81526020015f81526020015f8152602001615058615308565b604051806109600160405280604b906020820280368337509192915050565b604051806109600160405280604b905b6152606153df565b8152602001906001900390816152585790505090565b60405180608001604052805f81526020015f81526020015f81526020015f81525090565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806103600160405280601b906020820280368337509192915050565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b604051806101400160405280600a906020820280368337509192915050565b6040518061070001604052806038906020820280368337509192915050565b60405180610da00160405280606d906020820280368337509192915050565b6040518061042001604052806021906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b60405180604001604052805f81526020015f81525090565b6040518060e0016040528061540a61553f565b81526020015f81526020015f81526020015f81526020015f815260200161542f61553f565b81526020015f81525090565b604051806101a00160405280600d906020820280368337509192915050565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b615490615276565b8152602001906001900390816154885790505090565b604051806103800160405280601c905b6154be6152e9565b8152602001906001900390816154b65790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b61550b615276565b8152602001906001900390816155035790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215615572575f5ffd5b84356001600160401b03811115615587575f5ffd5b8501601f81018713615597575f5ffd5b80356001600160401b038111156155ac575f5ffd5b8760208284010111156155bd575f5ffd5b6020918201955093508501356001600160401b038111156155dc575f5ffd5b8501601f810187136155ec575f5ffd5b80356001600160401b03811115615601575f5ffd5b8760208260051b8401011115615615575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761231157612311615623565b8181038181111561231157612311615623565b8082018082111561231157612311615623565b5f5f85851115615682575f5ffd5b8386111561568e575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f600182016156c0576156c0615623565b5060010190565b80356020831015612311575f19602084900360031b1b1692915050565b5f8183825b60098110156157085781518352602092830192909101906001016156e9565b5050506101208201905092915050565b634e487b7160e01b5f52601260045260245ffd5b5f8261573a5761573a615718565b500490565b5f8183825b6006811015615763578151835260209283019290910190600101615744565b50505060c08201905092915050565b5f8183825b600a811015615796578151835260209283019290910190600101615777565b5050506101408201905092915050565b5f8183825b60388110156157ca5781518352602092830192909101906001016157ab565b5050506107008201905092915050565b5f8183825b606d8110156157fe5781518352602092830192909101906001016157df565b505050610da08201905092915050565b5f8183825b6021811015615832578151835260209283019290910190600101615813565b5050506104208201905092915050565b5f8183825b6005811015615866578151835260209283019290910190600101615847565b50505060a08201905092915050565b5f8261588357615883615718565b500690565b5f8161589657615896615623565b505f190190565b5f82518060208501845e5f920191825250919050565b5f602082840312156158c3575f5ffd5b815180151581146118af575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b81515f90829060208501835b828110156159105781518452602093840193909101906001016158f2565b509195945050505050565b5f8183825b600d81101561593f578151835260209283019290910190600101615920565b5050506101a08201905092915050565b634e487b7160e01b5f52602160045260245ffdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a26469706673582212203144ea64962d1f6e8bd98ed372c09e47423753637b1f928380ae53667a52220664736f6c634300081d0033 diff --git a/eth/contracts/noir/mint_HonkVerifier.bin b/eth/contracts/noir/mint_HonkVerifier.bin new file mode 100644 index 0000000..9d3f602 --- /dev/null +++ b/eth/contracts/noir/mint_HonkVerifier.bin @@ -0,0 +1 @@ +60e060405234801561000f575f5ffd5b50611000608052600c60a052601360c05260805160a05160c0516152c86100665f395f8181610103015261075a01525f81816108880152818161099501528181610ef40152610fa001525f6106fe01526152c85ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b366004614a88565b610054565b604051901515815260200160405180910390f35b5f6100626101fc6020614b60565b8414610081576040516376ba560560e11b815260040160405180910390fd5b5f61008a610221565b90505f6100978787610236565b9050601082604001516100aa9190614b77565b84146100c95760405163fa06659360e01b815260040160405180910390fd5b815160405163995bf45760e01b81525f9173__$0b6945387103aff223cc54b7f37f0977fa$__9163995bf4579161012e9186918b918b91907f000000000000000000000000000000000000000000000000000000000000000090600190600401614d12565b610be060405180830381865af415801561014a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061016e9190615028565b90506101be8686808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050855185516060810151608090910151919350915060016106e8565b815160a001526101ce828261086b565b6101eb576040516313f8744360e31b815260040160405180910390fd5b6101f6828483610a1d565b610213576040516352ec174560e11b815260040160405180910390fd5b506001979650505050505050565b610229614587565b6102316114c9565b905090565b61023e614711565b5f805b60108110156102a05761026d85838661025b8260206150d2565b92610268939291906150e5565b611e01565b835182601081106102805761028061510c565b60200201818152505060208261029691906150d2565b9150600101610241565b506102c48482856102b28260806150d2565b926102bf939291906150e5565b611e6f565b60208301526102d46080826150d2565b90506102e78482856102b28260806150d2565b60408301526102f76080826150d2565b905061030a8482856102b28260806150d2565b606083015261031a6080826150d2565b905061032d8482856102b28260806150d2565b60a083015261033d6080826150d2565b90506103508482856102b28260806150d2565b60c08301526103606080826150d2565b90506103738482856102b28260806150d2565b60808084019190915261038690826150d2565b90506103998482856102b28260806150d2565b60e08301526103a96080826150d2565b90506103bc8482856102b28260806150d2565b6101008301526103cd6080826150d2565b90506103e08482856102b28260806150d2565b610120830151526103f26080826150d2565b905061040584828561025b8260206150d2565b6101408301526104166020826150d2565b90505f5b601c811015610495575f5b600981101561048c5761043f86848761025b8260206150d2565b84610160015183601c81106104565761045661510c565b6020020151826009811061046c5761046c61510c565b60200201818152505060208361048291906150d2565b9250600101610425565b5060010161041a565b505f5b60298110156104e9576104b285838661025b8260206150d2565b83610180015182602981106104c9576104c961510c565b6020020181815250506020826104df91906150d2565b9150600101610498565b506104fb84828561025b8260206150d2565b6101a083015261050c6020826150d2565b905061051f8482856102b28260806150d2565b610120830151602001526105346080826150d2565b90506105478482856102b28260806150d2565b6101208301516040015261055c6080826150d2565b905061056f8482856102b28260806150d2565b6101c08301526105806080826150d2565b905061059384828561025b8260206150d2565b6101e08301526105a46020826150d2565b90505f5b6105b46001601c614b77565b8110156105fd576105cc8583866102b28260806150d2565b83610200015182601b81106105e3576105e361510c565b60200201526105f36080836150d2565b91506001016105a8565b505f5b601c8110156106515761061a85838661025b8260206150d2565b83610220015182601c81106106315761063161510c565b60200201818152505060208261064791906150d2565b9150600101610600565b505f5b60048110156106a55761066e85838661025b8260206150d2565b83610240015182600481106106855761068561510c565b60200201818152505060208261069b91906150d2565b9150600101610654565b506106b78482856102b28260806150d2565b6102608301526106c86080826150d2565b90506106db8482856102b28260806150d2565b6102808301525092915050565b5f600180826107318661072c896107276107228a7f00000000000000000000000000000000000000000000000000000000000000006150d2565b611f4e565b611f6c565b611f85565b90505f61074f8761074a8a6107276107228b60016150d2565b611f9e565b90505f5b61077e60107f0000000000000000000000000000000000000000000000000000000000000000614b77565b8110156107eb575f6107a88c838151811061079b5761079b61510c565b6020026020010151611f4e565b90506107b8866107278684611f85565b95506107c8856107278584611f85565b94506107d4848b611f85565b93506107e0838b611f9e565b925050600101610753565b505f5b6010811015610852575f8a826010811061080a5761080a61510c565b6020020151905061081f866107278684611f85565b955061082f856107278584611f85565b945061083b848b611f85565b9350610847838b611f9e565b9250506001016107ee565b5061085d8484611fcd565b9a9950505050505050505050565b5f5f6108808360600151856101400151611f6c565b905060015f5b7f0000000000000000000000000000000000000000000000000000000000000000811015610972575f86610160015182601c81106108c6576108c661510c565b602002015180519091505f906108e4908360015b6020020151611f85565b9050848114610906576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c811061091d5761091d61510c565b6020020151905061092e8382611fdb565b955061096285610727600161072c856107278e604001518b601c81106109565761095661510c565b60200201516001611f9e565b9450505050806001019050610886565b505f61098c866101800151865f015187602001518561213d565b9050600160025b7f00000000000000000000000000000000000000000000000000000000000000008110156109e9576109df82886080015183601c81106109d5576109d561510c565b6020020151611f6c565b9150600101610993565b50610a0f6109fc83610727600185611f9e565b61072c896101a001518960600151611f6c565b939093149695505050505050565b5f610a26614814565b5f610a348460c001516121b7565b9050610a3e614878565b610a46614897565b610100860151610a6690610a6190855f5b6020020151611f9e565b61221c565b60e0850152610100860151610a8090610a6190855f6108da565b610100850181905260e08086015190880151610aa09261072c9190611f6c565b845260c0860151610acf90610ab49061221c565b6107278660e0015161074a8a60e00151896101000151611f6c565b602085015260018252610260880151610ae790612285565b81526101e0880151608085015260a086015160608501528351610b09906122c4565b60208301525f5b6024811015610bad57610b32610b28865f01516122c4565b8660600151611f6c565b83610b3e8360026150d2565b604b8110610b4e57610b4e61510c565b602002015260808501516101808a0151610b87919061072c908460298110610b7857610b7861510c565b60200201518860600151611f6c565b6080860152606085015160a0880151610ba09190611f6c565b6060860152600101610b10565b5060245b6029811015610c3657610bca610b2886602001516122c4565b83610bd68360026150d2565b604b8110610be657610be661510c565b602002015260808501516101808a0151610c10919061072c908460298110610b7857610b7861510c565b6080860152606085015160a0880151610c299190611f6c565b6060860152600101610bb1565b50610c45886101c00151612285565b8160016020020152606087015181600260200201526080870151816003602002015260a0870151816004602002015260c0870151816005602002015260e0870151816006602002015261010087015181600760200201526101208701518160086020020152610140870151816009602002015261016087015181600a60200201526101c087015181600b602002015261018087015181600c60200201526101a087015181600d60200201526101e087015181600e602002015261020087015181600f602002015261022087015181601060200201526102408701518160116020020152610260870151816012602002015261028087015181601360200201526102a087015181601460200201526102c087015181601560200201526102e0870151816016602002015261030087015181601760200201526103208701518160186020020152610340870151816019602002015261036087015181601a602002015261038087015181601b60200201526103a087015181601c60200201526103c087015181601d6020020181905250610de08860200151612285565b6103c08201526040880151610df490612285565b6103e08201526060880151610e0890612285565b6104008201526080880151610e1c90612285565b610420820152610100880151610e3190612285565b61044082015260e0880151610e4590612285565b61046082015260a0880151610e5990612285565b61048082015260c0880151610e6d90612285565b6104a08201526020880151610e8190612285565b6104c08201526040880151610e9590612285565b6104e08201526060880151610ea990612285565b6105008201526080880151610ebd90612285565b610520820152610100880151610ed290612285565b81602a60200201819052505f610f18876080015186608001518b6102200151877f00000000000000000000000000000000000000000000000000000000000000006122dc565b805160e0870151919250610f2b91611f6c565b604086018190526102208a01515160e0890151610f5c929161072c91610f519190611f6c565b886101000151611f6c565b604086015260e0870151610f6f906123f7565b60608601525f610f81602960026150d2565b90505f5b610f916001601c614b77565b81101561117f575f610fc460017f0000000000000000000000000000000000000000000000000000000000000000614b77565b82101590508061110d57610ff8610a618b610100015189856001610fe891906150d2565b601c8110610a5757610a5761510c565b60e08901526101008a015161102790610a6190896110178660016150d2565b601c81106108da576108da61510c565b610100890152606088015160e08901516110419190611f6c565b610120890152606088015160e08b01516110699161105e91611f6c565b896101000151611f6c565b610140890181905261108c9061107e906122c4565b61072c8a61012001516122c4565b8661109784866150d2565b604b81106110a7576110a761510c565b60200201526101408801516102208d01515f916110d9916110c98660016150d2565b601c81106109d5576109d561510c565b90506110f68161072c8b6101200151888760016110c991906150d2565b9050611106896040015182611f85565b60408a0152505b61112c61112289606001518c60e00151611f6c565b8b60e00151611f6c565b60608901526102008c01516111569083601b811061114c5761114c61510c565b6020020151612285565b8561116184866150d2565b604b81106111715761117161510c565b602002015250600101610f85565b5061118c6001601c614b77565b61119690826150d2565b90506111b66111ae8961010001518a60c00151611f9e565b600190611fcd565b60a08701515261010088015160c08901516111fa916111ae9161074a907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a7690611f6c565b60a087018051602001919091528051805160409091015251805160609182015286015160e08901516112399161122f91611f6c565b8960e00151611f6c565b60608701525f5b60048110156112e6575f6112728860a0015183600481106112635761126361510c565b60200201518960600151611f6c565b905061127d816122c4565b8860c0015183600481106112935761129361510c565b6020020152606088015160e08b01516112ac9190611f6c565b8860600181815250506112d8886040015161072c838f610240015186600481106109d5576109d561510c565b604089015250600101611240565b5060c0860151518482604b81106112ff576112ff61510c565b602002015260c0860151611320906001602002015160c088015160026108da565b8461132c8360016150d2565b604b811061133c5761133c61510c565b602002015260c086015160600151846113568360026150d2565b604b81106113665761136661510c565b60200201525f5b60038110156113ba576113908b6101200151826003811061114c5761114c61510c565b848361139b81615120565b9450604b81106113ad576113ad61510c565b602002015260010161136d565b5060405180604001604052806001815260200160028152508382604b81106113e4576113e461510c565b6020020152604086015184826113f981615120565b9350604b811061140b5761140b61510c565b6020020181815250506114328a61024001518960c001518a608001518d6101a00151612402565b61144f5760405163a2a2ac8360e01b815260040160405180910390fd5b5f61145e8b6102800151612285565b9050808483604b81106114735761147361510c565b60200201526101008901518583604b81106114905761149061510c565b60200201525f6114a0858761271f565b90505f6114ac836127f1565b90506114b88282612837565b9d9c50505050505050505050505050565b6114d1614587565b50604080516103e0810182526110008152600c602080830191909152601382840152825180840184527f21a4ae9276ab3111702ca8c5b9cd9edef69a25ab7b20a8790b6433b723a460d281527f24cc51e4174d532b969721f9c87c4d13ccecd332797c0dc837546a49c7f925ef818301526060830152825180840184527f29a48a91a6b247642a4e73e5e85548ab91c9a1ed1a83f35d9671fe72dd75920381527f2d9761241d6cd48826a3c42636b6361510b69a09d75e51eca80a5eb4fa648dfc818301526080830152825180840184527f22e1112f2c3c80f0e766044d192e84538142edc26c041cafdf1f3253a892471181527f189e520f06cb62da9f53ea860904b720034fa5627dff95f72a2634ab1cf19cb38183015260a0830152825180840184527f284e833dfdcace67819a684258f8ff90b58d69e13a11ca8f658198ecc30a406181527f0ef57b3a5fe7ce17a553743133bd59f0a0826798db62b9d0f205096fa9d042f18183015260c0830152825180840184527f1ca8ecff8ecbbb943bd6a092b4e0890eae55d9b2e7f233cd62aa92a2ad3b704581527f0d1e365888d98453857bea12ecd09f3f57235aa2057b0b80dc55fe1891a3266a8183015260e0830152825180840184527f15750c4df8b1d564c5f9d5a389b0981a2182aa50f7f4f45dad9b8c6ffe00026a81527f04e7e289b576891d128768adadbb782faa4e023ad23530bfb7bc5c5d89dfbb3081830152610100830152825180840184527e73e7c223dd4f3e4734c4d9d9c9df394bd2eee2e12bac2fc49429a0443ec8b081527f20fac57db30195c2427a75a4d67231c1d1c74c8f84f009ab21d3c88e9657403d81830152610120830152825180840184527f1821c0d25ad447067092081581813b41c1b677f48306e4f2e99f0e17d313ffb881527f2c8cfd662ff6ceca1cca09461f1f3c3b20bed6f40e5e936c9b325be35cd5506881830152610140830152825180840184527f0379efd57ac85135df0b36a7395e80d3cf9d43d7609122ff55b35e6b61321ada81527f23b193689793f72cb5c3511d25095aa614520b5b3324957a6378c01b1d69a06981830152610160830152825180840184527f15298f6329123a0e10f266ef593952c91419342ea8f1a737af010d34d7be621981527f2a58f3ce15f39bdc77caed83d0d48cf44e08ebc7097911d17afa4fc4bfc0ab5a81830152610180830152825180840184527f1dec01cbc2f69ffc9d765c7bc0c852c6c84c6c01e2c7963e4ae88a8c9fc5e74781527f2f959f4a97fd041d8aa034623585cb1383d2130077e73367a53815bdfead2c8a818301526101a0830152825180840184527f292e660b0079ca0d11c714817840f26dc005cea0e4d94c5394fd0001e37dd00c81527f0c4c96bad2bd7c041414c53bc025b67ca6c866d3ab42513d5d7811d59b0c9fd9818301526101c0830152825180840184527f103c7723598010c38d228dd42d29c82a38246cac51f929ae616882cddfd249fe81527f058f79f054649c53aebc8758f74b78710507a31c2b7d51b368a79636f9c1f892818301526101e0830152825180840184527f02724742591d18c830ce4d974cbb6fe020bb3991d6555ad44de24476d0827c7c81527f1e3100a9437d9747e8edae19b02f908e42aaae6cee09e5270e33e05aa7ce93db81830152610200830152825180840184527f1057ba9a7ab68561cecf5b6d4d2992004528888e26768b6260869cc648307c1881527f0d1062e907dcbdf4ced3f7aa2776393134c81c182f9db2836df88aa0ceb4070181830152610220830152825180840184527f0e1503b1c25160565b4173cd81641492dd4f0420135d6070817a0a0cac4d910281527f19ebecd78787a82c44d5d9c871ac7cb3a6e5395ba113201ff6c60331b24313a981830152610240830152825180840184527f2b99affe8cf87072765b9da21fc028275a201b83fcdfa5fa4f2807cbe60a62eb81527f26433b9c53767f2aa2e16403617cf2bc8d687613ee3d98fbed2b04be1ca4422381830152610260830152825180840184527f27d164d926d34e5318016dedf3cd1ecd6e281ae1a185e5f077d042d0e153a1ba81527f1f292b4d1023e6942b990cbc1fbc747685c1aefd762a5dff017c3a2a3fefbbae81830152610280830152825180840184527f22a94ca9fbf041b24e3cae6ed554a408f6fa4526cef479187f8e30ec5af22fb781527f050675e1193389e16b0ff62ab64de611abdd3d1c48a80bac9d3ccdb59ea28ce1818301526102a0830152825180840184527f1589af33fd22ba897677c61c3bc5bb373a13c9db11c716ae1a6f1ab0ab3a5fb381527f2396cd8a16f18a1ee9e78d2832b478b6c4c3219e1050c0f5aab870073afb791a818301526102c0830152825180840184527f13d32ed75da341a1cde5fee7eaff44b4fcf536c9cacf49b18f7601ec44ff9a5c81527f1d9989fa08fe0d353bfa61a2ad9ea7b0149015f6ff043e92ca9cedbf977c2e7a818301526102e0830152825180840184527f14ff5e5f2689fded5d3e1f980931c6bcf6990c35991280368e8077af19fd0f2b81527f185004f7f5398f2ea19434918f378d3753dd8baa7ac3fdaf81dc8ee6618b535f81830152610300830152825180840184527e4067623374b7c3965c7d8444b57ac2d81269c7eb3cb4f7b16568b2f8234c9681527f0e605f3ad72203e21301ef1b5333cae1d8063220d1996854beb0c4fbc33bba9d81830152610320830152825180840184527f17aafa80bf54a7e6cc66472f9ccd70efa5044207a95191716ba0195b5a43226681527f233ecaca2ddbebb0484a44e6f55b8c8614c7b5e0ce31b51d59d6b21322a307a181830152610340830152825180840184527f1466af934dc34b082708b0a26a61dae7d9d859cbd4661cfab6abf34e827d9d2a81527f2666bf4c8a2aef1ab89aafded315580561c9d4a13f3ac4b255b478f544590eda81830152610360830152825180840184527f0765bf6645e4cf63f05d9b0efd06acebce309c685a3b05e613574ccd7316677c81527f09770f145625290cdcb08bae4e6f0a26897b5988fbaf9529e0a3326bfdb537ae8183015261038083015282518084018452600181526002818301526103a083015282518084019093527f17cd4a0a0ad0c1b25d999e7ed6a975dffbc970692ac8f19223e5e413a881f27183527f02f38b373f74498ff60f7297b8a8c5a851ee11c678cc5836ebba8c22b2c32470908301526103c081019190915290565b5f60208214611e5b5760405162461bcd60e51b815260206004820152602e60248201525f5160206151d35f395f51905f5260448201526d393ab1ba1023391039b1b0b630b960911b60648201526084015b60405180910390fd5b611e686107228385615138565b9392505050565b611e776148c5565b60808214611ecc5760405162461bcd60e51b815260206004820152602f60248201525f5160206151d35f395f51905f5260448201526e1c9d58dd08184811cc481c1bda5b9d608a1b6064820152608401611e52565b604080516080810190915280611ee560205f86886150e5565b611eee91615138565b8152602090810190611f049060409086886150e5565b611f0d91615138565b8152602001611f206060604086886150e5565b611f2991615138565b8152602001611f3c6080606086886150e5565b611f4591615138565b90529392505050565b5f611f665f5160206152535f395f51905f5283615155565b92915050565b5f5f5160206152535f395f51905f528284099392505050565b5f5f5160206152535f395f51905f528284089392505050565b5f5f5160206152535f395f51905f52611fc4835f5160206152535f395f51905f52614b77565b84089392505050565b5f611e68836107278461221c565b5f5f604051806101200160405280619d8081526020015f5160206152735f395f51905f5281526020016105a081526020015f5160206151f35f395f51905f52815260200161024081526020015f5160206151f35f395f51905f5281526020016105a081526020015f5160206152735f395f51905f528152602001619d8081525090505f600190505f5f90505b60098110156120885761207e826107278784611f9e565b9150600101612067565b506120916148e9565b5f5b60098110156120e2576120c3610a618583600981106120b4576120b461510c565b60200201516107278985611f9e565b8282600981106120d5576120d561510c565b6020020152600101612093565b505f5b60098110156121285761211e8561072c8984600981106121075761210761510c565b60200201518585600981106109d5576109d561510c565b94506001016120e5565b506121338483611f6c565b9695505050505050565b5f612146614908565b612151868285612a2b565b61215d86868386612bd7565b61216986868386612dc3565b612174868285612fe8565b61217f8682856131dc565b61218b86868386613525565b612197868683866139d8565b6121a2868285613dd7565b6121ad868285614198565b6121338185614498565b6121bf614908565b81815260015b601c811015612216576121f7826121dd600184614b77565b601c81106121ed576121ed61510c565b60200201516123f7565b8282601c81106122095761220961510c565b60200201526001016121c5565b50919050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f5160206152535f395f51905f520360808201525f5160206152535f395f51905f5260a082015260205f60c08360055afa90508061227a575f5ffd5b50505f519392505050565b61228d614927565b604051806040016040528060888460200151901b845f015117815260200160888460600151901b8460400151178152509050919050565b5f611f66825f5160206152535f395f51905f52614b77565b6122e4614908565b601c5b80156123ed575f846122fa600184614b77565b601c811061230a5761230a61510c565b602002015190505f8861231e600185614b77565b601c811061232e5761232e61510c565b602002015190505f61238961234d612346858c611f6c565b6002611f6c565b61074a8a61235c600189614b77565b601c811061236c5761236c61510c565b60200201516107276123838861072760018a611f9e565b87611f9e565b90506123aa81610727610a616123a487610727600189611f9e565b86611f85565b90508584116123d95797508780856123c3600187614b77565b601c81106123d3576123d361510c565b60200201525b505050806123e690615174565b90506122e7565b5095945050505050565b5f611f668283611f6c565b5f60018161241b612415876101006144fd565b83611f9e565b90508061243b5760405163835eb8f760e01b815260040160405180910390fd5b61244361493f565b80518390525f5b601c81101561250d575f61245f826009614b60565b61246a9060016150d2565b905084835f01518261010081106124835761248361510c565b60200201525f6124948260016150d2565b90505b6124a26009836150d2565b8110156125035783516124e2906124ba600184614b77565b61010081106124cb576124cb61510c565b60200201518a85601c81106109d5576109d561510c565b84518261010081106124f6576124f661510c565b6020020152600101612497565b505060010161244a565b50608081018390525f602082018190525b61010081101561260b5761253f61253983608001518a611f6c565b85611f9e565b8260a001518261010081106125565761255661510c565b602002015260a0820151612580908261010081106125765761257661510c565b602002015161221c565b8260a001518261010081106125975761259761510c565b6020020181815250506125dd826020015161072c845f01518461010081106125c1576125c161510c565b60200201518560a001518561010081106109d5576109d561510c565b602083015260808201516125fe905f5160206152335f395f51905f52611f6c565b608083015260010161251e565b505f61261c8361072761010061221c565b905061262c826020015182611f6c565b602083015260a0820151612647905f5b602002015182611f6c565b604083015260a0820151612673906126626001610100614b77565b610100811061263c5761263c61510c565b60608301526040820151612689908a60026109d5565b60c083018190526126d59061072c6126ae8b5f5160206152335f395f51905f52611f9e565b6107276126c48e600160200201518f6002610a57565b8e51602089015161074a9190611f6c565b60c08301819052606083015161270a916126fe9161072c906107278e600260200201518c611f9e565b61074a858c60036109d5565b60c08301819052159998505050505050505050565b612727614927565b5f6003612736601c60296150d2565b61274091906150d2565b61274b9060036150d2565b90506001604051855151604082015285516020015160608201528451608082015260408160606040840160075afa8216915060015b838110156127d95760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa90921691600101612780565b50805184526020810151602085015250505092915050565b6127f9614927565b5f5160206152135f395f51905f5282602001515f5160206152135f395f51905f526128249190614b77565b61282e9190615155565b60208301525090565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b0316836040516129cd9190615189565b5f60405180830381855afa9150503d805f8114612a05576040519150601f19603f3d011682016040523d82523d5f602084013e612a0a565b606091505b5091509150818015612133575080806020019051810190612133919061519f565b5f612a37846007614557565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f612a98612a92612a6c856003611f9e565b610727612a87612a7c8b5f614557565b6107278c601d614557565b6107278b601c614557565b83611f6c565b9050612b19612b0e612af5612adc612ac38561072c612ab88d6002614557565b6107278e601c614557565b61072c612ad18c6003614557565b6107278d601d614557565b61072c612aea8b6004614557565b6107278c601e614557565b61072c612b038a6005614557565b6107278b601f614557565b61072c886001614557565b9050612b388161072c612b2d866001611f9e565b6107278a6027614557565b9050612b448184611f6c565b9050612b508185611f6c565b8552505f9050612b8a612b80612b75612b6a88601c614557565b61072c89601f614557565b61074a886024614557565b61072c875f614557565b9050612b9b81610727846002611f9e565b9050612bac81610727846001611f9e565b9050612bb88183611f6c565b9050612bc48184611f6c565b9050808460015b60200201525050505050565b5f5f5f612c0d612c03612beb89601c614557565b61072c612bf98b6012614557565b8a60600151611f6c565b8760800151611f85565b9050612c4681610727612c3c612c248b601d614557565b61072c612c328d6013614557565b8c60600151611f6c565b8960800151611f85565b9050612c6b81610727612c3c612c5d8b601e614557565b61072c612c328d6014614557565b9050612c9081610727612c3c612c828b601f614557565b61072c612c328d6015614557565b92505f9050612cb4612c03612ca689601c614557565b61072c612bf98b600e614557565b9050612cd981610727612c3c612ccb8b601d614557565b61072c612c328d600f614557565b9050612cfe81610727612c3c612cf08b601e614557565b61072c612c328d6010614557565b9050612d2381610727612c3c612d158b601f614557565b61072c612c328d6011614557565b91505f9050612d4a612d44612d39896020614557565b61072c8a601a614557565b84611f6c565b9050612d7f8161074a612d79612d618b6028614557565b61072c612d6f8d601b614557565b8c60a00151611f6c565b85611f6c565b9050612d8b8185611f6c565b6040860152505f612dae612d79612da389601b614557565b6107278a6028614557565b9050808560035b602002015250505050505050565b5f5f612e21612e09612df1612ddc612c3c8a6016614557565b61072c612dea8b6017614557565b8a51611f6c565b61072c612dff8a6018614557565b8960200151611f6c565b61072c612e17896019614557565b8860400151611f6c565b91505f612e58612e3f612e3589601c614557565b8860800151611f85565b61072c612e4d8a6003614557565b6107278b6024614557565b90505f612e81612e6989601d614557565b61072c612e768b5f614557565b6107278c6025614557565b90505f612eab612e928a601e614557565b61072c612ea08c6001614557565b6107278d6026614557565b9050612eea612ed2612ec48561072c868d5f0151611f6c565b61072c848c60200151611f6c565b61072c612ee08c6004614557565b8b60400151611f6c565b93505050505f612efe612d44886021614557565b90505f612f0f612d44896021614557565b90505f612f47612f2e612f238b6023614557565b61072c8c6006614557565b61074a612f3c8c6023614557565b6107278d6006614557565b90505f612f65612415612f5a8789611f6c565b6107278d6021614557565b9050612f718188611f6c565b90505f612f99612f8b612f858d6006614557565b87611f6c565b61074a612f858e6022614557565b90505f612fa78c6023614557565b90505f612fb76124158384611f6c565b60808c0185905260a08c018490529050612fd1818b611f6c565b8b6006602002015250505050505050505050505050565b5f612ff45f6001611f9e565b90505f6130025f6002611f9e565b90505f6130105f6003611f9e565b90505f61302c61302188601d614557565b61074a89601c614557565b90505f61304861303d89601e614557565b61074a8a601d614557565b90505f6130646130598a601f614557565b61074a8b601e614557565b90505f6130806130758b6024614557565b61074a8c601f614557565b90508361309181610727818b611f85565b90506130a181610727878a611f85565b90506130b1816107278789611f85565b90506130c2816107278d6008614557565b90506130ce818a611f6c565b60e08b015250826130e381610727818b611f85565b90506130f381610727868a611f85565b9050613103816107278689611f85565b9050613114816107278d6008614557565b9050613120818a611f6c565b6101008b0152508161313681610727818b611f85565b905061314681610727858a611f85565b9050613156816107278589611f85565b9050613167816107278d6008614557565b9050613173818a611f6c565b6101208b0152508061318981610727818b611f85565b905061319981610727848a611f85565b90506131a9816107278489611f85565b90506131ba816107278d6008614557565b90506131c6818a611f6c565b610140909a019990995250505050505050505050565b6132156040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61322084601d614557565b815261322d84601e614557565b602082015261323d846024614557565b604082015261324d846027614557565b606082015261325d846026614557565b608082015261326d846025614557565b60a08201525f61327e856002614557565b90505f61328b865f614557565b90505f61329f8460400151855f0151611f9e565b90505f6132b485602001518660200151611f6c565b606086015190915086905f906132ca9080611f6c565b90505f6132e86132e289602001518a60600151611f6c565b88611f6c565b90505f6133076133008a60a001518b60400151611f85565b8a51611f85565b9050613316612f858288611f6c565b905061333d61333761333161332b8487611f9e565b88611f9e565b84611f85565b83611f85565b905061336561335a61334f8387611f6c565b6107278f6009614557565b61072760018a611f9e565b6101608c015250505050602085015160808601515f9161338491611f85565b90505f6133a2613398886060015188611f6c565b8860200151611f9e565b90505f6133c66133b28487611f6c565b61072c612d798b60a001518c5f0151611f9e565b90506133ee6133e36133d8838c611f6c565b6107278e6009614557565b610727600189611f9e565b6101808b0152505f915061340f9050613408836011611f85565b8751611f6c565b90505f61341c8384611f85565b90506134288182611f85565b90505f613436836009611f6c565b905061345f613459612d446134528b60a001518c5f0151611f85565b8b51611f85565b82611f9e565b60c089018190525f9061347a906132e29061334f908d611f6c565b905061348d8b600b602002015182611f85565b6101608c0152505086515f92506134b49150613408906134ad9080611f85565b8851611f85565b90505f6134f46134cf836107278a5f01518b60a00151611f9e565b602089015161074a906134e29080611f85565b6107278b602001518c60800151611f85565b905061351189600c602002015161072c6132e261334f858d611f6c565b89600c602002015250505050505050505050565b61358f604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6135a761359d86601e614557565b8560400151611f6c565b8082526135c69061072c6135bc88601d614557565b8760200151611f6c565b8082526135db9061072c61340888601c614557565b8082526135ed9061072c876001614557565b808252602082018190526136069061074a87601f614557565b8152613621613616866024614557565b61074a87601c614557565b608082015261363f613634866027614557565b61074a87601f614557565b60608201526080810151613661906136579080611f6c565b8260800151611f9e565b6101c082015260808101516136a190613697906136909061072760015f5160206152535f395f51905f52614b77565b6001611f85565b8260600151611f6c565b60a082018190526136d7906136c9906107276136be896002614557565b6107278a6003614557565b610727612d7988600a614557565b83600e60200201526101c08101516136fb906136c9906107276136be896002614557565b6101e0840152805161372090610727613715886002614557565b610727896003614557565b6101208201525f61373f61373587601f614557565b8360200151611f9e565b905061374e6134598283611f6c565b60e083015261376b613761876026614557565b8660400151611f6c565b6040830181905261378e9061072c613784896025614557565b8860200151611f6c565b604083018190526137ae9061072c6137a7896024614557565b8851611f6c565b60408301526137cb6137c1876027614557565b8360400151611f9e565b60408301525f6137ea6137df886026614557565b61074a89601e614557565b905061383c613817612a92613690866080015160015f5160206152535f395f51905f526107279190614b77565b610727613690866040015160015f5160206152535f395f51905f526107279190614b77565b60c0840152604083015161385e906138549080611f6c565b8460400151611f9e565b61010084015260c083015161388a9061387c906107278a6007614557565b610727612f858a600a614557565b6102008601526101c08301516138a99061387c906107278a6007614557565b6102208601526101008301516138c89061387c906107278a6007614557565b61024086015260e08301516138e290610727896007614557565b6101408401526139016138f6886025614557565b61074a89601d614557565b610160840152608083015161393f906137df90613934906136909061072760015f5160206152535f395f51905f52614b77565b856101600151611f6c565b61018084018190526101208401516101a085018190526139769161072c9061072761396b8c6005614557565b6107278d6002614557565b6101a084018190528351613996919061072c9061072761396b8c5f614557565b6101a084018190526101408401516139ae9190611f85565b6101a084018190526139c890610727612f858a600a614557565b6101a0840181905285600d612db5565b613a116040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613a46613a2d613a2287601c614557565b610727886025614557565b61072c613a3b886024614557565b61072789601d614557565b8152613a8b613a80613a67613a5c88601c614557565b61072789601f614557565b61072c613a7589601d614557565b6107278a601e614557565b61074a876026614557565b60408201819052613aa090600160441b611f6c565b60408201819052613ab69061074a876027614557565b604082018190528151613ac99190611f85565b60408201819052613adf90610727876005614557565b60408201528051613af490600160441b611f6c565b808252613b149061072c613b09886024614557565b610727896025614557565b80825260208201819052613b309061074a612b6a88601e614557565b60208201819052613b4690610727876004614557565b6020820152805160608201819052613b639061072c87601f614557565b60608201819052613b879061074a613b7c886026614557565b61072c896027614557565b60608201819052613b9c90610727875f614557565b8160600181815250505f613bc5613bbb83602001518460400151611f85565b8360600151611f85565b9050613bd681610727886003614557565b9050613bee613be6876025614557565b614000611f6c565b60808301819052613c049061072c886024614557565b60808301819052613c1790614000611f6c565b60808301819052613c2d9061072c88601e614557565b60808301819052613c4090614000611f6c565b60808301819052613c569061072c88601d614557565b60808301819052613c6990614000611f6c565b60808301819052613c7f9061072c88601c614557565b60808301819052613c959061074a88601f614557565b60808301819052613cab90610727886005614557565b6080830152613cbe613be6876026614557565b60a08301819052613cd49061072c886025614557565b60a08301819052613ce790614000611f6c565b60a08301819052613cfd9061072c886024614557565b60a08301819052613d1090614000611f6c565b60a08301819052613d269061072c88601f614557565b60a08301819052613d3990614000611f6c565b60a08301819052613d4f9061072c88601e614557565b60a08301819052613d659061074a886027614557565b60a08301819052613d7a90610727885f614557565b60a0830181905260808301515f91613d929190611f85565b9050613da381610727896004614557565b9050613daf8282611f85565b60c08401819052613dc890610727612f858a600b614557565b60c08401819052856013612db5565b613e4d6040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b613e66613e5b85601c614557565b61072c866002614557565b8152613e81613e7685601d614557565b61072c866003614557565b6020820152613e9f613e9485601e614557565b61072c866004614557565b6040820152613ebd613eb285601f614557565b61072c866005614557565b60608201528051613eef90613ee890613ee190613eda9080611f6c565b8451611f6c565b8351611f6c565b8251611f6c565b60808201526020810151613f2d90613f2390613f1990613f0f9080611f6c565b8460200151611f6c565b8360200151611f6c565b8260200151611f6c565b60a08201526040810151613f6b90613f6190613f5790613f4d9080611f6c565b8460400151611f6c565b8360400151611f6c565b8260400151611f6c565b60c08201526060810151613f9f9061369790613f9590613f8b9080611f6c565b8460600151611f6c565b8360600151611f6c565b60e0820152608081015160a0820151613fb89190611f85565b61010082015260c081015160e0820151613fd29190611f85565b61012082015260a0810151613ff690613feb9080611f85565b826101200151611f85565b61014082015260e081015161401a9061400f9080611f85565b826101000151611f85565b6101608201526101208101516140309080611f85565b6101e08201819052614051906140469080611f85565b826101600151611f85565b6101e08201526101008101516140679080611f85565b6101a082018190526140889061407d9080611f85565b826101400151611f85565b6101a0820181905261016082015161409f91611f85565b6101808201526101408101516101e08201516140bb9190611f85565b6101c08201526140cf612a9285600c614557565b61020082018190526102808401516101808301516140fa9261072c916107279061074a8a6024614557565b836014602002015261412a836015602002015161072c836102000151610727856101a0015161074a8a6025614557565b836015602002015261415a836016602002015161072c836102000151610727856101c0015161074a8a6026614557565b836016602002015261418a836017602002015161072c836102000151610727856101e0015161074a8a6027614557565b836017602002015250505050565b6141ea6040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f604051806080016040528061421f7f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7611f4e565b815260200161424d7f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b611f4e565b815260200161427a7e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15611f4e565b81526020016142a87f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b611f4e565b905290506142c56142ba86601c614557565b61072c876002614557565b6101208301819052614304906142f9906142ee906142e39080611f6c565b856101200151611f6c565b846101200151611f6c565b836101200151611f6c565b825261431185601d614557565b602083015261432185601e614557565b604083015261433185601f614557565b60608301528151602083015161435991613bbb9161434f9190611f85565b8460400151611f85565b608083015261436c612d4486600d614557565b610140830152815161438d9061438390835f6109d5565b8360800151611f85565b60a08301526143b9846018602002015161072c8461014001516107278660a0015161074a8b6024614557565b61030085015260208201516143d490614383908360016109d5565b60c0830152614400846019602002015161072c8461014001516107278660c0015161074a8b6025614557565b610320850152604082015161441b90614383908360026109d5565b60e083015261444784601a602002015161072c8461014001516107278660e0015161074a8b6026614557565b610340850152606082015161446290614383908360036109d5565b61010083015261449084601b602002015161072c84610140015161072786610100015161074a8b6027614557565b84601b612bcb565b5f6144a48184816108da565b905060015b601c8110156144f6576144ec8261072c8684601c81106144cb576144cb61510c565b6020020151866144dc600187614b77565b601b81106109d5576109d561510c565b91506001016144a9565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f5160206152535f395f51905f5260a082015260205f60c08360055afa90508061454b575f5ffd5b50505f51949350505050565b5f8282602881111561456b5761456b6151be565b6029811061457b5761457b61510c565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f81526020016145ad614927565b81526020016145ba614927565b81526020016145c7614927565b81526020016145d4614927565b81526020016145e1614927565b81526020016145ee614927565b81526020016145fb614927565b8152602001614608614927565b8152602001614615614927565b8152602001614622614927565b815260200161462f614927565b815260200161463c614927565b8152602001614649614927565b8152602001614656614927565b8152602001614663614927565b8152602001614670614927565b815260200161467d614927565b815260200161468a614927565b8152602001614697614927565b81526020016146a4614927565b81526020016146b1614927565b81526020016146be614927565b81526020016146cb614927565b81526020016146d8614927565b81526020016146e5614927565b81526020016146f2614927565b81526020016146ff614927565b815260200161470c614927565b905290565b604051806102a00160405280614725614983565b81526020016147326148c5565b815260200161473f6148c5565b815260200161474c6148c5565b81526020016147596148c5565b81526020016147666148c5565b81526020016147736148c5565b81526020016147806148c5565b815260200161478d6148c5565b815260200161479a6149a2565b81526020015f81526020016147ad6149cf565b81526020016147ba6149fd565b81526020015f81526020016147cd6148c5565b81526020015f81526020016147e0614a1c565b81526020016147ed614908565b81526020016147fa614a4a565b81526020016148076148c5565b815260200161470c6148c5565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f8152602001614846614a4a565b8152602001614853614a4a565b81526020015f81526020015f81526020015f81526020015f815260200161470c614908565b604051806109600160405280604b906020820280368337509192915050565b604051806109600160405280604b905b6148af614927565b8152602001906001900390816148a75790505090565b60405180608001604052805f81526020015f81526020015f81526020015f81525090565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b60405180604001604052805f81526020015f81525090565b6040518060e00160405280614952614a68565b81526020015f81526020015f81526020015f81526020015f8152602001614977614a68565b81526020015f81525090565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b6149b96148c5565b8152602001906001900390816149b15790505090565b604051806103800160405280601c905b6149e76148e9565b8152602001906001900390816149df5790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b614a346148c5565b815260200190600190039081614a2c5790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215614a9b575f5ffd5b84356001600160401b03811115614ab0575f5ffd5b8501601f81018713614ac0575f5ffd5b80356001600160401b03811115614ad5575f5ffd5b876020828401011115614ae6575f5ffd5b6020918201955093508501356001600160401b03811115614b05575f5ffd5b8501601f81018713614b15575f5ffd5b80356001600160401b03811115614b2a575f5ffd5b8760208260051b8401011115614b3e575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417611f6657611f66614b4c565b81810381811115611f6657611f66614b4c565b805f5b6010811015614bac578151845260209384019390910190600101614b8d565b50505050565b805182526020810151602083015260408101516040830152606081015160608301525050565b805f5b6003811015614bac57614bef848351614bb2565b6080939093019260209190910190600101614bdb565b805f5b601c811015614bac578151845f5b6009811015614c35578251825260209283019290910190600101614c16565b505050610120939093019260209190910190600101614c08565b805f5b6029811015614bac578151845260209384019390910190600101614c52565b805f5b601b811015614bac57614c88848351614bb2565b6080939093019260209190910190600101614c74565b805f5b601c811015614bac578151845260209384019390910190600101614ca1565b805f5b6004811015614bac578151845260209384019390910190600101614cc3565b8183525f6001600160fb1b03831115614cf9575f5ffd5b8260051b80836020870137939093016020019392505050565b614d1d818851614b8a565b5f6020880151614d31610200840182614bb2565b506040880151614d45610280840182614bb2565b506060880151614d59610300840182614bb2565b506080880151614d6d610380840182614bb2565b5060a0880151614d81610400840182614bb2565b5060c0880151614d95610480840182614bb2565b5060e0880151614da9610500840182614bb2565b50610100880151614dbe610580840182614bb2565b50610120880151614dd3610600840182614bd8565b50610140880151610780830152610160880151614df46107a0840182614c05565b50610180880151614e09612720840182614c4f565b506101a0880151612c408301526101c0880151614e2a612c60840182614bb2565b506101e0880151612ce0830152610200880151614e4b612d00840182614c71565b50610220880151614e60613a80840182614c9e565b50610240880151614e75613e00840182614cc0565b50610260880151614e8a613e80840182614bb2565b50610280880151614e9f613f00840182614bb2565b50614000613f80830152614eb861400083018789614ce2565b613fa083019590955250613fc0810192909252613fe0909101529392505050565b634e487b7160e01b5f52604160045260245ffd5b60405161014081016001600160401b0381118282101715614f1057614f10614ed9565b60405290565b604051601f8201601f191681016001600160401b0381118282101715614f3e57614f3e614ed9565b604052919050565b5f60c08284031215614f56575f5ffd5b60405160c081016001600160401b0381118282101715614f7857614f78614ed9565b604090815283518252602080850151908301528381015190820152606080840151908201526080808401519082015260a0928301519281019290925250919050565b5f82601f830112614fc9575f5ffd5b5f610360614fd681614f16565b915083018185821115614fe7575f5ffd5b845b82811015615001578051825260209182019101614fe9565b509195945050505050565b5f82601f83011261501b575f5ffd5b5f610380614fd681614f16565b5f610be082840312801561503a575f5ffd5b50615043614eed565b61504d8484614f46565b815261505c8460c08501614fba565b602082015261506f84610420850161500c565b60408201526107a0830151606082015261508d846107c0850161500c565b6080820152610b4083015160a0820152610b6083015160c0820152610b8083015160e0820152610ba0830151610100820152610bc09092015161012083015250919050565b80820180821115611f6657611f66614b4c565b5f5f858511156150f3575f5ffd5b838611156150ff575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f6001820161513157615131614b4c565b5060010190565b80356020831015611f66575f19602084900360031b1b1692915050565b5f8261516f57634e487b7160e01b5f52601260045260245ffd5b500690565b5f8161518257615182614b4c565b505f190190565b5f82518060208501845e5f920191825250919050565b5f602082840312156151af575f5ffd5b81518015158114611e68575f5ffd5b634e487b7160e01b5f52602160045260245ffdfe696e76616c6964206e756d626572206f6620627974657320746f20636f6e737430644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a26469706673582212201d0a47fded7a3e2083cbfd829d83428cce2210725a5b1015c516ead61dfa43b864736f6c634300081d0033 diff --git a/eth/contracts/noir/points_HonkVerifier.bin b/eth/contracts/noir/points_HonkVerifier.bin new file mode 100644 index 0000000..a62e7b8 --- /dev/null +++ b/eth/contracts/noir/points_HonkVerifier.bin @@ -0,0 +1 @@ +60e060405234801561000f575f5ffd5b50612000608052600d60a052601d60c05260805160a05160c051615ff86100655f395f818160d601526107ac01525f81816108da015281816109e701528181610f460152610ff201525f6107500152615ff85ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b366004615b1e565b610054565b604051901515815260200160405180910390f35b5f6100626101fc6020615bf6565b8414610081576040516376ba560560e11b815260040160405180910390fd5b5f61008a6101af565b90505f61009787876101c4565b9050601082604001516100aa9190615c0d565b84146100c95760405163fa06659360e01b815260040160405180910390fd5b5f6100fc828787865f01517f00000000000000000000000000000000000000000000000000000000000000006001610676565b905061014c8686808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250508551855160608101516080909101519193509150600161073a565b815160a0015261015c82826108bd565b610179576040516313f8744360e31b815260040160405180910390fd5b610184828483610a6f565b6101a1576040516352ec174560e11b815260040160405180910390fd5b506001979650505050505050565b6101b7615492565b6101bf61151b565b905090565b6101cc61561c565b5f805b601081101561022e576101fb8583866101e9826020615c20565b926101f693929190615c33565b611e54565b8351826010811061020e5761020e615c5a565b6020020181815250506020826102249190615c20565b91506001016101cf565b50610252848285610240826080615c20565b9261024d93929190615c33565b611e75565b6020830152610262608082615c20565b9050610275848285610240826080615c20565b6040830152610285608082615c20565b9050610298848285610240826080615c20565b60608301526102a8608082615c20565b90506102bb848285610240826080615c20565b60a08301526102cb608082615c20565b90506102de848285610240826080615c20565b60c08301526102ee608082615c20565b9050610301848285610240826080615c20565b6080808401919091526103149082615c20565b9050610327848285610240826080615c20565b60e0830152610337608082615c20565b905061034a848285610240826080615c20565b61010083015261035b608082615c20565b905061036e848285610240826080615c20565b61012083015152610380608082615c20565b90506103938482856101e9826020615c20565b6101408301526103a4602082615c20565b90505f5b601c811015610423575f5b600981101561041a576103cd8684876101e9826020615c20565b84610160015183601c81106103e4576103e4615c5a565b602002015182600981106103fa576103fa615c5a565b6020020181815250506020836104109190615c20565b92506001016103b3565b506001016103a8565b505f5b6029811015610477576104408583866101e9826020615c20565b836101800151826029811061045757610457615c5a565b60200201818152505060208261046d9190615c20565b9150600101610426565b506104898482856101e9826020615c20565b6101a083015261049a602082615c20565b90506104ad848285610240826080615c20565b610120830151602001526104c2608082615c20565b90506104d5848285610240826080615c20565b610120830151604001526104ea608082615c20565b90506104fd848285610240826080615c20565b6101c083015261050e608082615c20565b90506105218482856101e9826020615c20565b6101e0830152610532602082615c20565b90505f5b6105426001601c615c0d565b81101561058b5761055a858386610240826080615c20565b83610200015182601b811061057157610571615c5a565b6020020152610581608083615c20565b9150600101610536565b505f5b601c8110156105df576105a88583866101e9826020615c20565b83610220015182601c81106105bf576105bf615c5a565b6020020181815250506020826105d59190615c20565b915060010161058e565b505f5b6004811015610633576105fc8583866101e9826020615c20565b836102400151826004811061061357610613615c5a565b6020020181815250506020826106299190615c20565b91506001016105e2565b50610645848285610240826080615c20565b610260830152610656608082615c20565b9050610669848285610240826080615c20565b6102808301525092915050565b61067e61571f565b5f61068e88888888888887611f0b565b908352905061069d8189611f61565b602084019190915290506106b08161213d565b604084019190915290506106c48189612199565b606084019190915290506106d88882612216565b608084019190915290506106ec88826122e5565b60a084019190915290506107008882612600565b60c08401919091529050610714888261276e565b60e084019190915290506107288882612861565b50610100830152509695505050505050565b5f600180826107838661077e896107796107748a7f0000000000000000000000000000000000000000000000000000000000000000615c20565b6128b8565b6128d6565b6128ef565b90505f6107a18761079c8a6107796107748b6001615c20565b612908565b90505f5b6107d060107f0000000000000000000000000000000000000000000000000000000000000000615c0d565b81101561083d575f6107fa8c83815181106107ed576107ed615c5a565b60200260200101516128b8565b905061080a8661077986846128ef565b955061081a8561077985846128ef565b9450610826848b6128ef565b9350610832838b612908565b9250506001016107a5565b505f5b60108110156108a4575f8a826010811061085c5761085c615c5a565b602002015190506108718661077986846128ef565b95506108818561077985846128ef565b945061088d848b6128ef565b9350610899838b612908565b925050600101610840565b506108af8484612937565b9a9950505050505050505050565b5f5f6108d283606001518561014001516128d6565b905060015f5b7f00000000000000000000000000000000000000000000000000000000000000008110156109c4575f86610160015182601c811061091857610918615c5a565b602002015180519091505f90610936908360015b60200201516128ef565b9050848114610958576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c811061096f5761096f615c5a565b602002015190506109808382612945565b95506109b485610779600161077e856107798e604001518b601c81106109a8576109a8615c5a565b60200201516001612908565b94505050508060010190506108d8565b505f6109de866101800151865f0151876020015185612aa7565b9050600160025b7f0000000000000000000000000000000000000000000000000000000000000000811015610a3b57610a3182886080015183601c8110610a2757610a27615c5a565b60200201516128d6565b91506001016109e5565b50610a61610a4e83610779600185612908565b61077e896101a0015189606001516128d6565b939093149695505050505050565b5f610a78615784565b5f610a868460c00151612b21565b9050610a906157e8565b610a98615807565b610100860151610ab890610ab390855f5b6020020151612908565b612b86565b60e0850152610100860151610ad290610ab390855f61092c565b610100850181905260e08086015190880151610af29261077e91906128d6565b845260c0860151610b2190610b0690612b86565b6107798660e0015161079c8a60e001518961010001516128d6565b602085015260018252610260880151610b3990612bef565b81526101e0880151608085015260a086015160608501528351610b5b90612c2e565b60208301525f5b6024811015610bff57610b84610b7a865f0151612c2e565b86606001516128d6565b83610b90836002615c20565b604b8110610ba057610ba0615c5a565b602002015260808501516101808a0151610bd9919061077e908460298110610bca57610bca615c5a565b602002015188606001516128d6565b6080860152606085015160a0880151610bf291906128d6565b6060860152600101610b62565b5060245b6029811015610c8857610c1c610b7a8660200151612c2e565b83610c28836002615c20565b604b8110610c3857610c38615c5a565b602002015260808501516101808a0151610c62919061077e908460298110610bca57610bca615c5a565b6080860152606085015160a0880151610c7b91906128d6565b6060860152600101610c03565b50610c97886101c00151612bef565b8160016020020152606087015181600260200201526080870151816003602002015260a0870151816004602002015260c0870151816005602002015260e0870151816006602002015261010087015181600760200201526101208701518160086020020152610140870151816009602002015261016087015181600a60200201526101c087015181600b602002015261018087015181600c60200201526101a087015181600d60200201526101e087015181600e602002015261020087015181600f602002015261022087015181601060200201526102408701518160116020020152610260870151816012602002015261028087015181601360200201526102a087015181601460200201526102c087015181601560200201526102e0870151816016602002015261030087015181601760200201526103208701518160186020020152610340870151816019602002015261036087015181601a602002015261038087015181601b60200201526103a087015181601c60200201526103c087015181601d6020020181905250610e328860200151612bef565b6103c08201526040880151610e4690612bef565b6103e08201526060880151610e5a90612bef565b6104008201526080880151610e6e90612bef565b610420820152610100880151610e8390612bef565b61044082015260e0880151610e9790612bef565b61046082015260a0880151610eab90612bef565b61048082015260c0880151610ebf90612bef565b6104a08201526020880151610ed390612bef565b6104c08201526040880151610ee790612bef565b6104e08201526060880151610efb90612bef565b6105008201526080880151610f0f90612bef565b610520820152610100880151610f2490612bef565b81602a60200201819052505f610f6a876080015186608001518b6102200151877f0000000000000000000000000000000000000000000000000000000000000000612c46565b805160e0870151919250610f7d916128d6565b604086018190526102208a01515160e0890151610fae929161077e91610fa391906128d6565b8861010001516128d6565b604086015260e0870151610fc190612d61565b60608601525f610fd360296002615c20565b90505f5b610fe36001601c615c0d565b8110156111d1575f61101660017f0000000000000000000000000000000000000000000000000000000000000000615c0d565b82101590508061115f5761104a610ab38b61010001518985600161103a9190615c20565b601c8110610aa957610aa9615c5a565b60e08901526101008a015161107990610ab39089611069866001615c20565b601c811061092c5761092c615c5a565b610100890152606088015160e089015161109391906128d6565b610120890152606088015160e08b01516110bb916110b0916128d6565b8961010001516128d6565b61014089018190526110de906110d090612c2e565b61077e8a6101200151612c2e565b866110e98486615c20565b604b81106110f9576110f9615c5a565b60200201526101408801516102208d01515f9161112b9161111b866001615c20565b601c8110610a2757610a27615c5a565b90506111488161077e8b61012001518887600161111b9190615c20565b90506111588960400151826128ef565b60408a0152505b61117e61117489606001518c60e001516128d6565b8b60e001516128d6565b60608901526102008c01516111a89083601b811061119e5761119e615c5a565b6020020151612bef565b856111b38486615c20565b604b81106111c3576111c3615c5a565b602002015250600101610fd7565b506111de6001601c615c0d565b6111e89082615c20565b90506112086112008961010001518a60c00151612908565b600190612937565b60a08701515261010088015160c089015161124c916112009161079c907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76906128d6565b60a087018051602001919091528051805160409091015251805160609182015286015160e089015161128b91611281916128d6565b8960e001516128d6565b60608701525f5b6004811015611338575f6112c48860a0015183600481106112b5576112b5615c5a565b602002015189606001516128d6565b90506112cf81612c2e565b8860c0015183600481106112e5576112e5615c5a565b6020020152606088015160e08b01516112fe91906128d6565b88606001818152505061132a886040015161077e838f61024001518660048110610a2757610a27615c5a565b604089015250600101611292565b5060c0860151518482604b811061135157611351615c5a565b602002015260c0860151611372906001602002015160c0880151600261092c565b8461137e836001615c20565b604b811061138e5761138e615c5a565b602002015260c086015160600151846113a8836002615c20565b604b81106113b8576113b8615c5a565b60200201525f5b600381101561140c576113e28b6101200151826003811061119e5761119e615c5a565b84836113ed81615c6e565b9450604b81106113ff576113ff615c5a565b60200201526001016113bf565b5060405180604001604052806001815260200160028152508382604b811061143657611436615c5a565b60200201526040860151848261144b81615c6e565b9350604b811061145d5761145d615c5a565b6020020181815250506114848a61024001518960c001518a608001518d6101a00151612d6c565b6114a15760405163a2a2ac8360e01b815260040160405180910390fd5b5f6114b08b6102800151612bef565b9050808483604b81106114c5576114c5615c5a565b60200201526101008901518583604b81106114e2576114e2615c5a565b60200201525f6114f28587613089565b90505f6114fe8361315b565b905061150a82826131a1565b9d9c50505050505050505050505050565b611523615492565b50604080516103e0810182526120008152600d602080830191909152601d82840152825180840184527f15d33b575e447a00f04a04e465915f347a9f5d2162c2133fe739cfc3ecca83d681527f26844fc0703d0455ea030be5068f5a3e1906c7a60cee4fa643c42c9bd15d008f818301526060830152825180840184527f07628186d5c398bfd49eb30ee166413284c1a59c843f0e8a07948c703283f31281527f20ae9e3acdc5d3895b1a079543c9e0d0c37059d0b3aef5f7f2da786ca2a5073a818301526080830152825180840184527f2524f5b77866f532ac43f52864b218017956798a208c2688e4d47a75547b7daf81527f2905b38b62794ca696db62aa3f473744c7add66a529d316308c70a82aa40d4a88183015260a0830152825180840184527f1ef432dfb7f0814c5221e67e96200e889163e9657c1b2683e76c090e9cece02f81527f08c1569ac1ae7b4c5d26295c123696dec339580569f7b5bae44c494ca1bfe7658183015260c0830152825180840184527f299cd449ce66bb935c120f890b0331d187e279e7a73b5541c6a6cdf572ac1a9e81527f0e992b6fb69ed4c6866c41af775abfe08d60baf95bc404f1dfa38e8fec70d5088183015260e0830152825180840184527f01de9a7c500cb0b279287efbab1f6314587c13f63b3613414e44af1f06fe1f7181527f167dd7e1f8f73c24fff939e01625c3a70c872f2d8744a9a36cb20923a73e7cf081830152610100830152825180840184527f2ee537ee80c33fc3003e53f2fa67b14d63887059b541c3d5dbe38bfd517aa57981527f0ecddf7b61838886fcf1a7fec5c69d8e02933d1e153e33e5ea7d03b0c21b314a81830152610120830152825180840184527f05c6ada3976bfe2f6bb2e2ec76133536a98b3a77d129d32945809ac8b3260bc581527f178c1421b39429040b048bb51c19d8d600819171f2c2c477b467f1065fe58e5781830152610140830152825180840184527f0b87d736cdf9d0ec5fa3f8f3af64a2326d6269da8026248acecc8db4f2dc244381527f1ac094e450007b2a6b06ece84de3a01bb39dfd48bce855abaf7b6c84050b7fd281830152610160830152825180840184527f183dc0b74d756c33894335f3211dfe46512db2e14814b2da96a1743834e2c2f281527e534e50ed6e415b75ee3d9022ddd3e36b8714eb2fb0a01e52df51201783388681830152610180830152825180840184527f0bfb54ec826959074c034d6f020a4ba364985b84dcdbb4d51378e5aacadee55681527f145e69cb2a4552c6d8e9f5add79199ea5422db3770f24b8a0579ce8b89d7505c818301526101a0830152825180840184527f23b82c9adc93d322f1b57a01c9c5ae83d9d80b13634ff2daeda6a7195d0dca4f81527f167b5cd1db6ba97b6f23b62db08a41b2ab6ab023afe790bca5d12be4580d745b818301526101c0830152825180840184527f2546919520ccd296348f79bf783bdf2103d446f75eb48a62a481967813263a0c81527f0dea057e8cf9e4f0441a7fc8157bae794f471e0e8cc835335a624b18dce10e79818301526101e0830152825180840184527f281c7b723008ef4b2638e83f9741b1c883acd7a21b4615c0ec0095686627be8981527f2440c36723cd1150667e9e50ce396b2eef3757a605fb35eb8019f52f02c09c9881830152610200830152825180840184527f1fbdf420f48ff12f75a34906f68129dd63853f8ca077108c758e94e5051413cc81527f0a2e7a8affac030a3fdaed089a51f2116124d9f02cbb5732c58912e6d7b380ed81830152610220830152825180840184527f11a8b11e47632573f2648b152ae3874a865cf8c0cd71abb986b06feeb6137d8581527f23fd7d7ef7c3402f010869d4dce3dac5c6777069f11be130351296235f30336681830152610240830152825180840184527f2a503794496fa8e34c0cf43a015c9c6829af5a3ba61fd88adb04e448de4febaa81527f2eca8fa7432005495de9586658a65062249681ee16464560324acde9d06c782a81830152610260830152825180840184527f24d5a37899317d4940810474f1c954d155a7ba8471f5cd8904100df835793cef81527f0c1f14ef702c5eace2613309ffc578fb85b4ff7aada3af79953bc47e688769cd81830152610280830152825180840184527f1de25f106b1b264d5016176ec61897f8489ae8e3e815a38d1dd3e055367cf28f81527f0e713ce63a74cdf910af6c6bf659162ba19deab24dd9333550dde7b344948190818301526102a0830152825180840184527f1add61ff28686707a0ecf51052ec3b6075f9e12498681a605459d910be365c6c81527f2b155c81fcc76324d297b50d798839beb66eff6aa99fb99d867e1e69bd3a34cf818301526102c0830152825180840184527f1293d89ae67571d6976a73a1e6c5726f1262de6fab0c1817fb40dd7cbea1dfcc81527f1bab7d8bca1c5cf8c4da4c6420e0c7a8a0aed0c8190c7dc60b8968dd255d7aef818301526102e0830152825180840184527f041be62a0d3ad1956cde1fc7e91446d74763702f348cc7ebaa3e3b0730563a8f81527f1503625fd9e040c494760440dd43dbcd79f1df2b7cc4aada13995bbfa95da3a281830152610300830152825180840184527f07996eb6dfdbbe9366eb89f10c9e3f0ddc72fa5675348bf2044edf5dc4d5a58c81527f07900286f41a6b1b401de720f9eaa6b92d56fc8510645d8904922fba3e1e38da81830152610320830152825180840184527f299718f02caec5c6f5c312a23adca7c66ea4cfcd33cb6e9f03fd0a69dd46c79981527f2016239e3dc69d93a022823784a64a7ec20cd2a6b3fc442d3164a1d42bb5c3f181830152610340830152825180840184527f26bf5f2ea5aa1995105c3cd32ced7f3c804df2f77a8ef8454f720805d97da70e81527f187449669f89eb3ca1744849331cecdc8524fb932789dd8bce42b0d52a297d1681830152610360830152825180840184527f156d4ec761ecbf3624548e81c8465494d4c42ce8b495bbc46bef593881c6317281527f29ef58088ef385b57d6b1ba1fd2fc6165df3608620713985e9c05d7c5faa183a8183015261038083015282518084018452600181526002818301526103a083015282518084019093527f27e2145211461aeb744525780b35aaa1c99dd14354fee439ba5b6e2c8e67ec2c83527f025d761e02c6cfd13d5b13c9c279c094e56dabb621349151a8606d384018f374908301526103c081019190915290565b5f60208214611e61575f5ffd5b611e6e6107748385615c86565b9392505050565b611e7d615835565b60808214611e89575f5ffd5b604080516080810190915280611ea260205f8688615c33565b611eab91615c86565b8152602090810190611ec1906040908688615c33565b611eca91615c86565b8152602001611edd606060408688615c33565b611ee691615c86565b8152602001611ef9608060608688615c33565b611f0291615c86565b90529392505050565b611f13615859565b5f611f22898989898989613395565b604086019190915260208501919091529083529250611f41838a613837565b608085019190915260608401919091529199919850909650505050505050565b611f69615889565b5f611f726158a8565b84815260e0848101805151602080850191909152815181015160408086019190915282518101516060808701919091529251830151608086015261010080890180515160a0880152805184015160c0880152805183015195870195909552935190920151928401929092525161200991611fee91849101615ca3565b604051602081830303815290604052805190602001206128b8565b915061201482613906565b6020850152835260015b600261202c6001601c615c0d565b6120369190615ceb565b8110156120b65761205383604051602001611fee91815260200190565b925061205e83613906565b8561206a846002615bf6565b601b811061207a5761207a615c5a565b602002018661208a856002615bf6565b612095906001615c20565b601b81106120a5576120a5615c5a565b60200201919091525260010161201e565b506120c36001601c615c0d565b60011660011480156120e0575060026120de6001601c615c0d565b115b15612135576120fb82604051602001611fee91815260200190565b915061210682613906565b5083600161211581601c615c0d565b61211f9190615c0d565b601b811061212f5761212f615c5a565b60200201525b509250929050565b6121456158c7565b5f805b601c8110156121925761216784604051602001611fee91815260200190565b935061217284613906565b508382601c811061218557612185615c5a565b6020020152600101612148565b5090929050565b5f5f6121a36158e6565b84815261012084018051515160208084019190915281515181015160408085019190915282515181015160608086019190915292515190920151608084015261014086015160a084015290516121ff91611fee91849101615cfe565b915061220a82613906565b50959194509092505050565b61221e6158c7565b5f805b601c8110156122dc57612232615904565b8481525f5b600981101561229b5786610160015183601c811061225757612257615c5a565b6020020151816009811061226d5761226d615c5a565b60200201518261227e836001615c20565b600a811061228e5761228e615c5a565b6020020152600101612237565b506122b081604051602001611fee9190615d31565b94506122bb85613906565b508483601c81106122ce576122ce615c5a565b602002015250600101612221565b50909391925050565b5f5f6122ef615923565b83815260015b6029811161234c5761018086015161230e600183615c0d565b6029811061231e5761231e615c5a565b602002015182826038811061233557612335615c5a565b60200201528061234481615c6e565b9150506122f5565b856101a0015182826038811061236457612364615c5a565b6020020152612374600182615c20565b610120870151602001515190915082826038811061239457612394615c5a565b60200201526101208601516001602002015160200151828260016123b89190615c20565b603881106123c8576123c8615c5a565b60200201526101208601516001602002015160400151826123ea836002615c20565b603881106123fa576123fa615c5a565b602002015261012086015160016020020151606001518261241c836003615c20565b6038811061242c5761242c615c5a565b602002015261243c600482615c20565b610120870151604001515190915082826038811061245c5761245c615c5a565b60200201526101208601516002602002015160200151828260016124809190615c20565b6038811061249057612490615c5a565b60200201526101208601516040908101510151826124af836002615c20565b603881106124bf576124bf615c5a565b60200201526101208601516040015160600151826124de836003615c20565b603881106124ee576124ee615c5a565b60200201526124fe600482615c20565b6101c08701515190915082826038811061251a5761251a615c5a565b602002018181525050856101c00151602001518282600161253b9190615c20565b6038811061254b5761254b615c5a565b60200201526101c08601516040015182612566836002615c20565b6038811061257657612576615c5a565b60200201526101c08601516060015182612591836003615c20565b603881106125a1576125a1615c5a565b60200201526125b1600482615c20565b9050856101e001518282603881106125cb576125cb615c5a565b6020020181815250506125e882604051602001611fee9190615d65565b92506125f383613906565b5096929550919350505050565b5f5f61260a615942565b8381525f5b61261b6001601c615c0d565b8110156127595785610200015181601b811061263957612639615c5a565b6020020151518261264b836004615bf6565b612656906001615c20565b606d811061266657612666615c5a565b602002015261020086015181601b811061268257612682615c5a565b602002015160200151828260046126999190615bf6565b6126a4906002615c20565b606d81106126b4576126b4615c5a565b602002015261020086015181601b81106126d0576126d0615c5a565b602002015160400151826126e5836004615bf6565b6126f0906003615c20565b606d811061270057612700615c5a565b602002015261020086015181601b811061271c5761271c615c5a565b60200201516060015182612731836004615bf6565b61273c906004615c20565b606d811061274c5761274c615c5a565b602002015260010161260f565b506121ff81604051602001611fee9190615d99565b5f5f612778615961565b83815260015b601c81116127d557610220860151612797600183615c0d565b601c81106127a7576127a7615c5a565b60200201518282602181106127be576127be615c5a565b6020020152806127cd81615c6e565b91505061277e565b505f806127e4601c6001615c20565b90505b6127f3601c6004615c20565b811161284c57866102400151826004811061281057612810615c5a565b602002015183826021811061282757612827615c5a565b60200201528161283681615c6e565b925050808061284490615c6e565b9150506127e7565b506125e882604051602001611fee9190615dcd565b5f5f61286b615980565b838152610260850180515160208084019190915281518101516040808501919091528251810151606080860191909152925190920151608084015290516121ff91611fee91849101615e01565b5f6128d05f516020615f835f395f51905f5283615e34565b92915050565b5f5f516020615f835f395f51905f528284099392505050565b5f5f516020615f835f395f51905f528284089392505050565b5f5f516020615f835f395f51905f5261292e835f516020615f835f395f51905f52615c0d565b84089392505050565b5f611e6e8361077984612b86565b5f5f604051806101200160405280619d8081526020015f516020615fa35f395f51905f5281526020016105a081526020015f516020615f235f395f51905f52815260200161024081526020015f516020615f235f395f51905f5281526020016105a081526020015f516020615fa35f395f51905f528152602001619d8081525090505f600190505f5f90505b60098110156129f2576129e8826107798784612908565b91506001016129d1565b506129fb6158a8565b5f5b6009811015612a4c57612a2d610ab3858360098110612a1e57612a1e615c5a565b60200201516107798985612908565b828260098110612a3f57612a3f615c5a565b60200201526001016129fd565b505f5b6009811015612a9257612a888561077e898460098110612a7157612a71615c5a565b6020020151858560098110610a2757610a27615c5a565b9450600101612a4f565b50612a9d84836128d6565b9695505050505050565b5f612ab06158c7565b612abb868285613936565b612ac786868386613ae2565b612ad386868386613cce565b612ade868285613ef3565b612ae98682856140e7565b612af586868386614430565b612b01868683866148e3565b612b0c868285614ce2565b612b178682856150a3565b612a9d81856153a3565b612b296158c7565b81815260015b601c811015612b8057612b6182612b47600184615c0d565b601c8110612b5757612b57615c5a565b6020020151612d61565b8282601c8110612b7357612b73615c5a565b6020020152600101612b2f565b50919050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f516020615f835f395f51905f520360808201525f516020615f835f395f51905f5260a082015260205f60c08360055afa905080612be4575f5ffd5b50505f519392505050565b612bf761599e565b604051806040016040528060888460200151901b845f015117815260200160888460600151901b8460400151178152509050919050565b5f6128d0825f516020615f835f395f51905f52615c0d565b612c4e6158c7565b601c5b8015612d57575f84612c64600184615c0d565b601c8110612c7457612c74615c5a565b602002015190505f88612c88600185615c0d565b601c8110612c9857612c98615c5a565b602002015190505f612cf3612cb7612cb0858c6128d6565b60026128d6565b61079c8a612cc6600189615c0d565b601c8110612cd657612cd6615c5a565b6020020151610779612ced8861077960018a612908565b87612908565b9050612d1481610779610ab3612d0e87610779600189612908565b866128ef565b9050858411612d43579750878085612d2d600187615c0d565b601c8110612d3d57612d3d615c5a565b60200201525b50505080612d5090615e47565b9050612c51565b5095945050505050565b5f6128d082836128d6565b5f600181612d85612d7f87610100615408565b83612908565b905080612da55760405163835eb8f760e01b815260040160405180910390fd5b612dad6159b6565b80518390525f5b601c811015612e77575f612dc9826009615bf6565b612dd4906001615c20565b905084835f0151826101008110612ded57612ded615c5a565b60200201525f612dfe826001615c20565b90505b612e0c600983615c20565b811015612e6d578351612e4c90612e24600184615c0d565b6101008110612e3557612e35615c5a565b60200201518a85601c8110610a2757610a27615c5a565b8451826101008110612e6057612e60615c5a565b6020020152600101612e01565b5050600101612db4565b50608081018390525f602082018190525b610100811015612f7557612ea9612ea383608001518a6128d6565b85612908565b8260a00151826101008110612ec057612ec0615c5a565b602002015260a0820151612eea90826101008110612ee057612ee0615c5a565b6020020151612b86565b8260a00151826101008110612f0157612f01615c5a565b602002018181525050612f47826020015161077e845f0151846101008110612f2b57612f2b615c5a565b60200201518560a00151856101008110610a2757610a27615c5a565b60208301526080820151612f68905f516020615f635f395f51905f526128d6565b6080830152600101612e88565b505f612f8683610779610100612b86565b9050612f968260200151826128d6565b602083015260a0820151612fb1905f5b6020020151826128d6565b604083015260a0820151612fdd90612fcc6001610100615c0d565b6101008110612fa657612fa6615c5a565b60608301526040820151612ff3908a6002610a27565b60c0830181905261303f9061077e6130188b5f516020615f635f395f51905f52612908565b61077961302e8e600160200201518f6002610aa9565b8e51602089015161079c91906128d6565b60c083018190526060830151613074916130689161077e906107798e600260200201518c612908565b61079c858c6003610a27565b60c08301819052159998505050505050505050565b61309161599e565b5f60036130a0601c6029615c20565b6130aa9190615c20565b6130b5906003615c20565b90506001604051855151604082015285516020015160608201528451608082015260408160606040840160075afa8216915060015b838110156131435760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa909216916001016130ea565b50805184526020810151602085015250505092915050565b61316361599e565b5f516020615f435f395f51905f5282602001515f516020615f435f395f51905f5261318e9190615c0d565b6131989190615e34565b60208301525090565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b0316836040516133379190615e5c565b5f60405180830381855afa9150503d805f811461336f576040519150601f19603f3d011682016040523d82523d5f602084013e613374565b606091505b5091509150818015612a9d575080806020019051810190612a9d9190615e72565b5f808080806133a5876003615c20565b6133b090600c615c20565b6001600160401b038111156133c7576133c7615e91565b6040519080825280602002602001820160405280156133f0578160200160208202803683370190505b509050875f1b815f8151811061340857613408615c5a565b602002602001018181525050865f1b8160018151811061342a5761342a615c5a565b602002602001018181525050855f1b8160028151811061344c5761344c615c5a565b60209081029190910101525f5b613464601089615c0d565b8110156134b5578a8a8281811061347d5761347d615c5a565b90506020020135828260036134929190615c20565b815181106134a2576134a2615c5a565b6020908102919091010152600101613459565b505f5b6010811015613526578b516134e09082601081106134d8576134d8615c5a565b602002015190565b828260106134ef8c6003615c20565b6134f99190615c0d565b6135039190615c20565b8151811061351357613513615c5a565b60209081029190910101526001016134b8565b5060208b01515181613539896003615c20565b8151811061354957613549615c5a565b6020908102919091018101919091528b81015101518161356a896003615c20565b613575906001615c20565b8151811061358557613585615c5a565b6020908102919091018101919091528b015160400151816135a7896003615c20565b6135b2906002615c20565b815181106135c2576135c2615c5a565b6020908102919091018101919091528b015160600151816135e4896003615c20565b6135ef906003615c20565b815181106135ff576135ff615c5a565b602090810291909101015260408b0151518161361c896003615c20565b613627906004615c20565b8151811061363757613637615c5a565b60209081029190910181019190915260408c0151015181613659896003615c20565b613664906005615c20565b8151811061367457613674615c5a565b60209081029190910101526040808c0151015181613693896003615c20565b61369e906006615c20565b815181106136ae576136ae615c5a565b602090810291909101015260408b015160600151816136ce896003615c20565b6136d9906007615c20565b815181106136e9576136e9615c5a565b602090810291909101015260608b01515181613706896003615c20565b613711906008615c20565b8151811061372157613721615c5a565b60209081029190910181019190915260608c0151015181613743896003615c20565b61374e906009615c20565b8151811061375e5761375e615c5a565b602090810291909101015260608b0151604001518161377e896003615c20565b61378990600a615c20565b8151811061379957613799615c5a565b60209081029190910101526060808c01510151816137b8896003615c20565b6137c390600b615c20565b815181106137d3576137d3615c5a565b6020026020010181815250506137f381604051602001611fee9190615ea5565b91506137fe82613906565b60408051602081018690529297509095506138199101611fee565b915061382482613906565b5080935050509650965096509692505050565b5f5f5f6138426159fa565b85815260a085810180515160208085019190915281518101516040808601919091528251810151606080870191909152925183015160808087019190915260c0808b0180515196880196909652855184015190870152845182015160e0870152935183015161010086015292880180515161012086015280518201516101408601528051840151610160860152519091015161018084015290516138ec91611fee91849101615eda565b91506138f782613906565b90979096509194509092505050565b5f80826001600160801b038116608082901c613921826128b8565b945061392c816128b8565b9350505050915091565b5f613942846007615462565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f6139a361399d613977856003612908565b6107796139926139878b5f615462565b6107798c601d615462565b6107798b601c615462565b836128d6565b9050613a24613a19613a006139e76139ce8561077e6139c38d6002615462565b6107798e601c615462565b61077e6139dc8c6003615462565b6107798d601d615462565b61077e6139f58b6004615462565b6107798c601e615462565b61077e613a0e8a6005615462565b6107798b601f615462565b61077e886001615462565b9050613a438161077e613a38866001612908565b6107798a6027615462565b9050613a4f81846128d6565b9050613a5b81856128d6565b8552505f9050613a95613a8b613a80613a7588601c615462565b61077e89601f615462565b61079c886024615462565b61077e875f615462565b9050613aa681610779846002612908565b9050613ab781610779846001612908565b9050613ac381836128d6565b9050613acf81846128d6565b9050808460015b60200201525050505050565b5f5f5f613b18613b0e613af689601c615462565b61077e613b048b6012615462565b8a606001516128d6565b87608001516128ef565b9050613b5181610779613b47613b2f8b601d615462565b61077e613b3d8d6013615462565b8c606001516128d6565b89608001516128ef565b9050613b7681610779613b47613b688b601e615462565b61077e613b3d8d6014615462565b9050613b9b81610779613b47613b8d8b601f615462565b61077e613b3d8d6015615462565b92505f9050613bbf613b0e613bb189601c615462565b61077e613b048b600e615462565b9050613be481610779613b47613bd68b601d615462565b61077e613b3d8d600f615462565b9050613c0981610779613b47613bfb8b601e615462565b61077e613b3d8d6010615462565b9050613c2e81610779613b47613c208b601f615462565b61077e613b3d8d6011615462565b91505f9050613c55613c4f613c44896020615462565b61077e8a601a615462565b846128d6565b9050613c8a8161079c613c84613c6c8b6028615462565b61077e613c7a8d601b615462565b8c60a001516128d6565b856128d6565b9050613c9681856128d6565b6040860152505f613cb9613c84613cae89601b615462565b6107798a6028615462565b9050808560035b602002015250505050505050565b5f5f613d2c613d14613cfc613ce7613b478a6016615462565b61077e613cf58b6017615462565b8a516128d6565b61077e613d0a8a6018615462565b89602001516128d6565b61077e613d22896019615462565b88604001516128d6565b91505f613d63613d4a613d4089601c615462565b88608001516128ef565b61077e613d588a6003615462565b6107798b6024615462565b90505f613d8c613d7489601d615462565b61077e613d818b5f615462565b6107798c6025615462565b90505f613db6613d9d8a601e615462565b61077e613dab8c6001615462565b6107798d6026615462565b9050613df5613ddd613dcf8561077e868d5f01516128d6565b61077e848c602001516128d6565b61077e613deb8c6004615462565b8b604001516128d6565b93505050505f613e09613c4f886021615462565b90505f613e1a613c4f896021615462565b90505f613e52613e39613e2e8b6023615462565b61077e8c6006615462565b61079c613e478c6023615462565b6107798d6006615462565b90505f613e70612d7f613e6587896128d6565b6107798d6021615462565b9050613e7c81886128d6565b90505f613ea4613e96613e908d6006615462565b876128d6565b61079c613e908e6022615462565b90505f613eb28c6023615462565b90505f613ec2612d7f83846128d6565b60808c0185905260a08c018490529050613edc818b6128d6565b8b6006602002015250505050505050505050505050565b5f613eff5f6001612908565b90505f613f0d5f6002612908565b90505f613f1b5f6003612908565b90505f613f37613f2c88601d615462565b61079c89601c615462565b90505f613f53613f4889601e615462565b61079c8a601d615462565b90505f613f6f613f648a601f615462565b61079c8b601e615462565b90505f613f8b613f808b6024615462565b61079c8c601f615462565b905083613f9c81610779818b6128ef565b9050613fac81610779878a6128ef565b9050613fbc8161077987896128ef565b9050613fcd816107798d6008615462565b9050613fd9818a6128d6565b60e08b01525082613fee81610779818b6128ef565b9050613ffe81610779868a6128ef565b905061400e8161077986896128ef565b905061401f816107798d6008615462565b905061402b818a6128d6565b6101008b0152508161404181610779818b6128ef565b905061405181610779858a6128ef565b90506140618161077985896128ef565b9050614072816107798d6008615462565b905061407e818a6128d6565b6101208b0152508061409481610779818b6128ef565b90506140a481610779848a6128ef565b90506140b48161077984896128ef565b90506140c5816107798d6008615462565b90506140d1818a6128d6565b610140909a019990995250505050505050505050565b6141206040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61412b84601d615462565b815261413884601e615462565b6020820152614148846024615462565b6040820152614158846027615462565b6060820152614168846026615462565b6080820152614178846025615462565b60a08201525f614189856002615462565b90505f614196865f615462565b90505f6141aa8460400151855f0151612908565b90505f6141bf856020015186602001516128d6565b606086015190915086905f906141d590806128d6565b90505f6141f36141ed89602001518a606001516128d6565b886128d6565b90505f61421261420b8a60a001518b604001516128ef565b8a516128ef565b9050614221613e9082886128d6565b905061424861424261423c6142368487612908565b88612908565b846128ef565b836128ef565b905061427061426561425a83876128d6565b6107798f6009615462565b61077960018a612908565b6101608c015250505050602085015160808601515f9161428f916128ef565b90505f6142ad6142a38860600151886128d6565b8860200151612908565b90505f6142d16142bd84876128d6565b61077e613c848b60a001518c5f0151612908565b90506142f96142ee6142e3838c6128d6565b6107798e6009615462565b610779600189612908565b6101808b0152505f915061431a90506143138360116128ef565b87516128d6565b90505f61432783846128ef565b905061433381826128ef565b90505f6143418360096128d6565b905061436a614364613c4f61435d8b60a001518c5f01516128ef565b8b516128ef565b82612908565b60c089018190525f90614385906141ed9061425a908d6128d6565b90506143988b600b6020020151826128ef565b6101608c0152505086515f92506143bf9150614313906143b890806128ef565b88516128ef565b90505f6143ff6143da836107798a5f01518b60a00151612908565b602089015161079c906143ed90806128ef565b6107798b602001518c608001516128ef565b905061441c89600c602002015161077e6141ed61425a858d6128d6565b89600c602002015250505050505050505050565b61449a604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6144b26144a886601e615462565b85604001516128d6565b8082526144d19061077e6144c788601d615462565b87602001516128d6565b8082526144e69061077e61431388601c615462565b8082526144f89061077e876001615462565b808252602082018190526145119061079c87601f615462565b815261452c614521866024615462565b61079c87601c615462565b608082015261454a61453f866027615462565b61079c87601f615462565b6060820152608081015161456c9061456290806128d6565b8260800151612908565b6101c082015260808101516145ac906145a29061459b9061077960015f516020615f835f395f51905f52615c0d565b60016128ef565b82606001516128d6565b60a082018190526145e2906145d4906107796145c9896002615462565b6107798a6003615462565b610779613c8488600a615462565b83600e60200201526101c0810151614606906145d4906107796145c9896002615462565b6101e0840152805161462b90610779614620886002615462565b610779896003615462565b6101208201525f61464a61464087601f615462565b8360200151612908565b905061465961436482836128d6565b60e083015261467661466c876026615462565b86604001516128d6565b604083018190526146999061077e61468f896025615462565b88602001516128d6565b604083018190526146b99061077e6146b2896024615462565b88516128d6565b60408301526146d66146cc876027615462565b8360400151612908565b60408301525f6146f56146ea886026615462565b61079c89601e615462565b905061474761472261399d61459b866080015160015f516020615f835f395f51905f526107799190615c0d565b61077961459b866040015160015f516020615f835f395f51905f526107799190615c0d565b60c084015260408301516147699061475f90806128d6565b8460400151612908565b61010084015260c083015161479590614787906107798a6007615462565b610779613e908a600a615462565b6102008601526101c08301516147b490614787906107798a6007615462565b6102208601526101008301516147d390614787906107798a6007615462565b61024086015260e08301516147ed90610779896007615462565b61014084015261480c614801886025615462565b61079c89601d615462565b610160840152608083015161484a906146ea9061483f9061459b9061077960015f516020615f835f395f51905f52615c0d565b8561016001516128d6565b61018084018190526101208401516101a085018190526148819161077e906107796148768c6005615462565b6107798d6002615462565b6101a0840181905283516148a1919061077e906107796148768c5f615462565b6101a084018190526101408401516148b991906128ef565b6101a084018190526148d390610779613e908a600a615462565b6101a0840181905285600d613cc0565b61491c6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61495161493861492d87601c615462565b610779886025615462565b61077e614946886024615462565b61077989601d615462565b815261499661498b61497261496788601c615462565b61077989601f615462565b61077e61498089601d615462565b6107798a601e615462565b61079c876026615462565b604082018190526149ab90600160441b6128d6565b604082018190526149c19061079c876027615462565b6040820181905281516149d491906128ef565b604082018190526149ea90610779876005615462565b604082015280516149ff90600160441b6128d6565b808252614a1f9061077e614a14886024615462565b610779896025615462565b80825260208201819052614a3b9061079c613a7588601e615462565b60208201819052614a5190610779876004615462565b6020820152805160608201819052614a6e9061077e87601f615462565b60608201819052614a929061079c614a87886026615462565b61077e896027615462565b60608201819052614aa790610779875f615462565b8160600181815250505f614ad0614ac6836020015184604001516128ef565b83606001516128ef565b9050614ae181610779886003615462565b9050614af9614af1876025615462565b6140006128d6565b60808301819052614b0f9061077e886024615462565b60808301819052614b22906140006128d6565b60808301819052614b389061077e88601e615462565b60808301819052614b4b906140006128d6565b60808301819052614b619061077e88601d615462565b60808301819052614b74906140006128d6565b60808301819052614b8a9061077e88601c615462565b60808301819052614ba09061079c88601f615462565b60808301819052614bb690610779886005615462565b6080830152614bc9614af1876026615462565b60a08301819052614bdf9061077e886025615462565b60a08301819052614bf2906140006128d6565b60a08301819052614c089061077e886024615462565b60a08301819052614c1b906140006128d6565b60a08301819052614c319061077e88601f615462565b60a08301819052614c44906140006128d6565b60a08301819052614c5a9061077e88601e615462565b60a08301819052614c709061079c886027615462565b60a08301819052614c8590610779885f615462565b60a0830181905260808301515f91614c9d91906128ef565b9050614cae81610779896004615462565b9050614cba82826128ef565b60c08401819052614cd390610779613e908a600b615462565b60c08401819052856013613cc0565b614d586040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b614d71614d6685601c615462565b61077e866002615462565b8152614d8c614d8185601d615462565b61077e866003615462565b6020820152614daa614d9f85601e615462565b61077e866004615462565b6040820152614dc8614dbd85601f615462565b61077e866005615462565b60608201528051614dfa90614df390614dec90614de590806128d6565b84516128d6565b83516128d6565b82516128d6565b60808201526020810151614e3890614e2e90614e2490614e1a90806128d6565b84602001516128d6565b83602001516128d6565b82602001516128d6565b60a08201526040810151614e7690614e6c90614e6290614e5890806128d6565b84604001516128d6565b83604001516128d6565b82604001516128d6565b60c08201526060810151614eaa906145a290614ea090614e9690806128d6565b84606001516128d6565b83606001516128d6565b60e0820152608081015160a0820151614ec391906128ef565b61010082015260c081015160e0820151614edd91906128ef565b61012082015260a0810151614f0190614ef690806128ef565b8261012001516128ef565b61014082015260e0810151614f2590614f1a90806128ef565b8261010001516128ef565b610160820152610120810151614f3b90806128ef565b6101e08201819052614f5c90614f5190806128ef565b8261016001516128ef565b6101e0820152610100810151614f7290806128ef565b6101a08201819052614f9390614f8890806128ef565b8261014001516128ef565b6101a08201819052610160820151614faa916128ef565b6101808201526101408101516101e0820151614fc691906128ef565b6101c0820152614fda61399d85600c615462565b61020082018190526102808401516101808301516150059261077e916107799061079c8a6024615462565b8360146020020152615035836015602002015161077e836102000151610779856101a0015161079c8a6025615462565b8360156020020152615065836016602002015161077e836102000151610779856101c0015161079c8a6026615462565b8360166020020152615095836017602002015161077e836102000151610779856101e0015161079c8a6027615462565b836017602002015250505050565b6150f56040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f604051806080016040528061512a7f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e76128b8565b81526020016151587f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b6128b8565b81526020016151857e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac156128b8565b81526020016151b37f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b6128b8565b905290506151d06151c586601c615462565b61077e876002615462565b610120830181905261520f90615204906151f9906151ee90806128d6565b8561012001516128d6565b8461012001516128d6565b8361012001516128d6565b825261521c85601d615462565b602083015261522c85601e615462565b604083015261523c85601f615462565b60608301528151602083015161526491614ac69161525a91906128ef565b84604001516128ef565b6080830152615277613c4f86600d615462565b61014083015281516152989061528e90835f610a27565b83608001516128ef565b60a08301526152c4846018602002015161077e8461014001516107798660a0015161079c8b6024615462565b61030085015260208201516152df9061528e90836001610a27565b60c083015261530b846019602002015161077e8461014001516107798660c0015161079c8b6025615462565b61032085015260408201516153269061528e90836002610a27565b60e083015261535284601a602002015161077e8461014001516107798660e0015161079c8b6026615462565b610340850152606082015161536d9061528e90836003610a27565b61010083015261539b84601b602002015161077e84610140015161077986610100015161079c8b6027615462565b84601b613ad6565b5f6153af81848161092c565b905060015b601c811015615401576153f78261077e8684601c81106153d6576153d6615c5a565b6020020151866153e7600187615c0d565b601b8110610a2757610a27615c5a565b91506001016153b4565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f516020615f835f395f51905f5260a082015260205f60c08360055afa905080615456575f5ffd5b50505f51949350505050565b5f8282602881111561547657615476615f0e565b6029811061548657615486615c5a565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f81526020016154b861599e565b81526020016154c561599e565b81526020016154d261599e565b81526020016154df61599e565b81526020016154ec61599e565b81526020016154f961599e565b815260200161550661599e565b815260200161551361599e565b815260200161552061599e565b815260200161552d61599e565b815260200161553a61599e565b815260200161554761599e565b815260200161555461599e565b815260200161556161599e565b815260200161556e61599e565b815260200161557b61599e565b815260200161558861599e565b815260200161559561599e565b81526020016155a261599e565b81526020016155af61599e565b81526020016155bc61599e565b81526020016155c961599e565b81526020016155d661599e565b81526020016155e361599e565b81526020016155f061599e565b81526020016155fd61599e565b815260200161560a61599e565b815260200161561761599e565b905290565b604051806102a00160405280615630615a19565b815260200161563d615835565b815260200161564a615835565b8152602001615657615835565b8152602001615664615835565b8152602001615671615835565b815260200161567e615835565b815260200161568b615835565b8152602001615698615835565b81526020016156a5615a38565b81526020015f81526020016156b8615a65565b81526020016156c5615a93565b81526020015f81526020016156d8615835565b81526020015f81526020016156eb615ab2565b81526020016156f86158c7565b8152602001615705615ae0565b8152602001615712615835565b8152602001615617615835565b604051806101400160405280615733615859565b8152602001615740615889565b815260200161574d6158c7565b81526020015f81526020016157606158c7565b81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f81526020016157b6615ae0565b81526020016157c3615ae0565b81526020015f81526020015f81526020015f81526020015f81526020016156176158c7565b604051806109600160405280604b906020820280368337509192915050565b604051806109600160405280604b905b61581f61599e565b8152602001906001900390816158175790505090565b60405180608001604052805f81526020015f81526020015f81526020015f81525090565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806103600160405280601b906020820280368337509192915050565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b604051806101400160405280600a906020820280368337509192915050565b6040518061070001604052806038906020820280368337509192915050565b60405180610da00160405280606d906020820280368337509192915050565b6040518061042001604052806021906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b60405180604001604052805f81526020015f81525090565b6040518060e001604052806159c9615afe565b81526020015f81526020015f81526020015f81526020015f81526020016159ee615afe565b81526020015f81525090565b604051806101a00160405280600d906020820280368337509192915050565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b615a4f615835565b815260200190600190039081615a475790505090565b604051806103800160405280601c905b615a7d6158a8565b815260200190600190039081615a755790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b615aca615835565b815260200190600190039081615ac25790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215615b31575f5ffd5b84356001600160401b03811115615b46575f5ffd5b8501601f81018713615b56575f5ffd5b80356001600160401b03811115615b6b575f5ffd5b876020828401011115615b7c575f5ffd5b6020918201955093508501356001600160401b03811115615b9b575f5ffd5b8501601f81018713615bab575f5ffd5b80356001600160401b03811115615bc0575f5ffd5b8760208260051b8401011115615bd4575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176128d0576128d0615be2565b818103818111156128d0576128d0615be2565b808201808211156128d0576128d0615be2565b5f5f85851115615c41575f5ffd5b83861115615c4d575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f60018201615c7f57615c7f615be2565b5060010190565b803560208310156128d0575f19602084900360031b1b1692915050565b5f8183825b6009811015615cc7578151835260209283019290910190600101615ca8565b5050506101208201905092915050565b634e487b7160e01b5f52601260045260245ffd5b5f82615cf957615cf9615cd7565b500490565b5f8183825b6006811015615d22578151835260209283019290910190600101615d03565b50505060c08201905092915050565b5f8183825b600a811015615d55578151835260209283019290910190600101615d36565b5050506101408201905092915050565b5f8183825b6038811015615d89578151835260209283019290910190600101615d6a565b5050506107008201905092915050565b5f8183825b606d811015615dbd578151835260209283019290910190600101615d9e565b505050610da08201905092915050565b5f8183825b6021811015615df1578151835260209283019290910190600101615dd2565b5050506104208201905092915050565b5f8183825b6005811015615e25578151835260209283019290910190600101615e06565b50505060a08201905092915050565b5f82615e4257615e42615cd7565b500690565b5f81615e5557615e55615be2565b505f190190565b5f82518060208501845e5f920191825250919050565b5f60208284031215615e82575f5ffd5b81518015158114611e6e575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b81515f90829060208501835b82811015615ecf578151845260209384019390910190600101615eb1565b509195945050505050565b5f8183825b600d811015615efe578151835260209283019290910190600101615edf565b5050506101a08201905092915050565b634e487b7160e01b5f52602160045260245ffdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a2646970667358221220500d680c2229231c21d85824a9893036a6a5998e868730904683dbfc1b3d269d64736f6c634300081d0033 diff --git a/eth/contracts/noir/signature_HonkVerifier.bin b/eth/contracts/noir/signature_HonkVerifier.bin new file mode 100644 index 0000000..a32f5a9 --- /dev/null +++ b/eth/contracts/noir/signature_HonkVerifier.bin @@ -0,0 +1 @@ +60e060405234801561000f575f5ffd5b50611000608052600c60a052601260c05260805160a05160c051615ff76100655f395f818160d601526107ac01525f81816108da015281816109e701528181610f460152610ff201525f6107500152615ff75ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b366004615b1d565b610054565b604051901515815260200160405180910390f35b5f6100626101fc6020615bf5565b8414610081576040516376ba560560e11b815260040160405180910390fd5b5f61008a6101af565b90505f61009787876101c4565b9050601082604001516100aa9190615c0c565b84146100c95760405163fa06659360e01b815260040160405180910390fd5b5f6100fc828787865f01517f00000000000000000000000000000000000000000000000000000000000000006001610676565b905061014c8686808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250508551855160608101516080909101519193509150600161073a565b815160a0015261015c82826108bd565b610179576040516313f8744360e31b815260040160405180910390fd5b610184828483610a6f565b6101a1576040516352ec174560e11b815260040160405180910390fd5b506001979650505050505050565b6101b7615491565b6101bf61151b565b905090565b6101cc61561b565b5f805b601081101561022e576101fb8583866101e9826020615c1f565b926101f693929190615c32565b611e53565b8351826010811061020e5761020e615c59565b6020020181815250506020826102249190615c1f565b91506001016101cf565b50610252848285610240826080615c1f565b9261024d93929190615c32565b611e74565b6020830152610262608082615c1f565b9050610275848285610240826080615c1f565b6040830152610285608082615c1f565b9050610298848285610240826080615c1f565b60608301526102a8608082615c1f565b90506102bb848285610240826080615c1f565b60a08301526102cb608082615c1f565b90506102de848285610240826080615c1f565b60c08301526102ee608082615c1f565b9050610301848285610240826080615c1f565b6080808401919091526103149082615c1f565b9050610327848285610240826080615c1f565b60e0830152610337608082615c1f565b905061034a848285610240826080615c1f565b61010083015261035b608082615c1f565b905061036e848285610240826080615c1f565b61012083015152610380608082615c1f565b90506103938482856101e9826020615c1f565b6101408301526103a4602082615c1f565b90505f5b601c811015610423575f5b600981101561041a576103cd8684876101e9826020615c1f565b84610160015183601c81106103e4576103e4615c59565b602002015182600981106103fa576103fa615c59565b6020020181815250506020836104109190615c1f565b92506001016103b3565b506001016103a8565b505f5b6029811015610477576104408583866101e9826020615c1f565b836101800151826029811061045757610457615c59565b60200201818152505060208261046d9190615c1f565b9150600101610426565b506104898482856101e9826020615c1f565b6101a083015261049a602082615c1f565b90506104ad848285610240826080615c1f565b610120830151602001526104c2608082615c1f565b90506104d5848285610240826080615c1f565b610120830151604001526104ea608082615c1f565b90506104fd848285610240826080615c1f565b6101c083015261050e608082615c1f565b90506105218482856101e9826020615c1f565b6101e0830152610532602082615c1f565b90505f5b6105426001601c615c0c565b81101561058b5761055a858386610240826080615c1f565b83610200015182601b811061057157610571615c59565b6020020152610581608083615c1f565b9150600101610536565b505f5b601c8110156105df576105a88583866101e9826020615c1f565b83610220015182601c81106105bf576105bf615c59565b6020020181815250506020826105d59190615c1f565b915060010161058e565b505f5b6004811015610633576105fc8583866101e9826020615c1f565b836102400151826004811061061357610613615c59565b6020020181815250506020826106299190615c1f565b91506001016105e2565b50610645848285610240826080615c1f565b610260830152610656608082615c1f565b9050610669848285610240826080615c1f565b6102808301525092915050565b61067e61571e565b5f61068e88888888888887611f0a565b908352905061069d8189611f60565b602084019190915290506106b08161213c565b604084019190915290506106c48189612198565b606084019190915290506106d88882612215565b608084019190915290506106ec88826122e4565b60a0840191909152905061070088826125ff565b60c08401919091529050610714888261276d565b60e084019190915290506107288882612860565b50610100830152509695505050505050565b5f600180826107838661077e896107796107748a7f0000000000000000000000000000000000000000000000000000000000000000615c1f565b6128b7565b6128d5565b6128ee565b90505f6107a18761079c8a6107796107748b6001615c1f565b612907565b90505f5b6107d060107f0000000000000000000000000000000000000000000000000000000000000000615c0c565b81101561083d575f6107fa8c83815181106107ed576107ed615c59565b60200260200101516128b7565b905061080a8661077986846128ee565b955061081a8561077985846128ee565b9450610826848b6128ee565b9350610832838b612907565b9250506001016107a5565b505f5b60108110156108a4575f8a826010811061085c5761085c615c59565b602002015190506108718661077986846128ee565b95506108818561077985846128ee565b945061088d848b6128ee565b9350610899838b612907565b925050600101610840565b506108af8484612936565b9a9950505050505050505050565b5f5f6108d283606001518561014001516128d5565b905060015f5b7f00000000000000000000000000000000000000000000000000000000000000008110156109c4575f86610160015182601c811061091857610918615c59565b602002015180519091505f90610936908360015b60200201516128ee565b9050848114610958576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c811061096f5761096f615c59565b602002015190506109808382612944565b95506109b485610779600161077e856107798e604001518b601c81106109a8576109a8615c59565b60200201516001612907565b94505050508060010190506108d8565b505f6109de866101800151865f0151876020015185612aa6565b9050600160025b7f0000000000000000000000000000000000000000000000000000000000000000811015610a3b57610a3182886080015183601c8110610a2757610a27615c59565b60200201516128d5565b91506001016109e5565b50610a61610a4e83610779600185612907565b61077e896101a0015189606001516128d5565b939093149695505050505050565b5f610a78615783565b5f610a868460c00151612b20565b9050610a906157e7565b610a98615806565b610100860151610ab890610ab390855f5b6020020151612907565b612b85565b60e0850152610100860151610ad290610ab390855f61092c565b610100850181905260e08086015190880151610af29261077e91906128d5565b845260c0860151610b2190610b0690612b85565b6107798660e0015161079c8a60e001518961010001516128d5565b602085015260018252610260880151610b3990612bee565b81526101e0880151608085015260a086015160608501528351610b5b90612c2d565b60208301525f5b6024811015610bff57610b84610b7a865f0151612c2d565b86606001516128d5565b83610b90836002615c1f565b604b8110610ba057610ba0615c59565b602002015260808501516101808a0151610bd9919061077e908460298110610bca57610bca615c59565b602002015188606001516128d5565b6080860152606085015160a0880151610bf291906128d5565b6060860152600101610b62565b5060245b6029811015610c8857610c1c610b7a8660200151612c2d565b83610c28836002615c1f565b604b8110610c3857610c38615c59565b602002015260808501516101808a0151610c62919061077e908460298110610bca57610bca615c59565b6080860152606085015160a0880151610c7b91906128d5565b6060860152600101610c03565b50610c97886101c00151612bee565b8160016020020152606087015181600260200201526080870151816003602002015260a0870151816004602002015260c0870151816005602002015260e0870151816006602002015261010087015181600760200201526101208701518160086020020152610140870151816009602002015261016087015181600a60200201526101c087015181600b602002015261018087015181600c60200201526101a087015181600d60200201526101e087015181600e602002015261020087015181600f602002015261022087015181601060200201526102408701518160116020020152610260870151816012602002015261028087015181601360200201526102a087015181601460200201526102c087015181601560200201526102e0870151816016602002015261030087015181601760200201526103208701518160186020020152610340870151816019602002015261036087015181601a602002015261038087015181601b60200201526103a087015181601c60200201526103c087015181601d6020020181905250610e328860200151612bee565b6103c08201526040880151610e4690612bee565b6103e08201526060880151610e5a90612bee565b6104008201526080880151610e6e90612bee565b610420820152610100880151610e8390612bee565b61044082015260e0880151610e9790612bee565b61046082015260a0880151610eab90612bee565b61048082015260c0880151610ebf90612bee565b6104a08201526020880151610ed390612bee565b6104c08201526040880151610ee790612bee565b6104e08201526060880151610efb90612bee565b6105008201526080880151610f0f90612bee565b610520820152610100880151610f2490612bee565b81602a60200201819052505f610f6a876080015186608001518b6102200151877f0000000000000000000000000000000000000000000000000000000000000000612c45565b805160e0870151919250610f7d916128d5565b604086018190526102208a01515160e0890151610fae929161077e91610fa391906128d5565b8861010001516128d5565b604086015260e0870151610fc190612d60565b60608601525f610fd360296002615c1f565b90505f5b610fe36001601c615c0c565b8110156111d1575f61101660017f0000000000000000000000000000000000000000000000000000000000000000615c0c565b82101590508061115f5761104a610ab38b61010001518985600161103a9190615c1f565b601c8110610aa957610aa9615c59565b60e08901526101008a015161107990610ab39089611069866001615c1f565b601c811061092c5761092c615c59565b610100890152606088015160e089015161109391906128d5565b610120890152606088015160e08b01516110bb916110b0916128d5565b8961010001516128d5565b61014089018190526110de906110d090612c2d565b61077e8a6101200151612c2d565b866110e98486615c1f565b604b81106110f9576110f9615c59565b60200201526101408801516102208d01515f9161112b9161111b866001615c1f565b601c8110610a2757610a27615c59565b90506111488161077e8b61012001518887600161111b9190615c1f565b90506111588960400151826128ee565b60408a0152505b61117e61117489606001518c60e001516128d5565b8b60e001516128d5565b60608901526102008c01516111a89083601b811061119e5761119e615c59565b6020020151612bee565b856111b38486615c1f565b604b81106111c3576111c3615c59565b602002015250600101610fd7565b506111de6001601c615c0c565b6111e89082615c1f565b90506112086112008961010001518a60c00151612907565b600190612936565b60a08701515261010088015160c089015161124c916112009161079c907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76906128d5565b60a087018051602001919091528051805160409091015251805160609182015286015160e089015161128b91611281916128d5565b8960e001516128d5565b60608701525f5b6004811015611338575f6112c48860a0015183600481106112b5576112b5615c59565b602002015189606001516128d5565b90506112cf81612c2d565b8860c0015183600481106112e5576112e5615c59565b6020020152606088015160e08b01516112fe91906128d5565b88606001818152505061132a886040015161077e838f61024001518660048110610a2757610a27615c59565b604089015250600101611292565b5060c0860151518482604b811061135157611351615c59565b602002015260c0860151611372906001602002015160c0880151600261092c565b8461137e836001615c1f565b604b811061138e5761138e615c59565b602002015260c086015160600151846113a8836002615c1f565b604b81106113b8576113b8615c59565b60200201525f5b600381101561140c576113e28b6101200151826003811061119e5761119e615c59565b84836113ed81615c6d565b9450604b81106113ff576113ff615c59565b60200201526001016113bf565b5060405180604001604052806001815260200160028152508382604b811061143657611436615c59565b60200201526040860151848261144b81615c6d565b9350604b811061145d5761145d615c59565b6020020181815250506114848a61024001518960c001518a608001518d6101a00151612d6b565b6114a15760405163a2a2ac8360e01b815260040160405180910390fd5b5f6114b08b6102800151612bee565b9050808483604b81106114c5576114c5615c59565b60200201526101008901518583604b81106114e2576114e2615c59565b60200201525f6114f28587613088565b90505f6114fe8361315a565b905061150a82826131a0565b9d9c50505050505050505050505050565b611523615491565b50604080516103e0810182526110008152600c602080830191909152601282840152825180840184527f2dac5c34ac40ef7e448365e6552f92d60d1154aee0f802c7fc57d1e5fb3bfee281527ee6751ba32b4db661b735066c9b2c2b3524ee624edb31d224e65d83aaaf0e2a818301526060830152825180840184527f0cabcd4767f05fd8ac5d6827de9434416fac8ed04d23f7bfdf973b50665a7a6c81527f01767830bf69c059579aa182ad902a2a20cadf386164ba4b5e0f9eb0f1ae8fbb818301526080830152825180840184527f26aa96b3a0d9e9719aeca6b2d901f4edbc87fc7abe5b53e748b889ab528d643081527f059e668437cc089ebd25c6fcb40aefd45e42dd734b009b291291d608822ed8a98183015260a0830152825180840184527f27215f25d9d754e6721e6d7f2057cc8ccb079ff2a8ff80684fcbbddde702eeff81527f02757e5ccde7937626ca26b5171d3d0241ca38e4fd2297625c38101a5ce7d8448183015260c0830152825180840184527f138630f2b497856c0f715659241766b9dbbc316b923b14590b5b85db847830d481527e0862d99a7d9b1ec7bbe98998f1a9334499e0f0d8609787f70c0bd03577bd588183015260e0830152825180840184527f2f5155855544566dbb619d85dfdb4dfaf1fa5b649fcb017ecf5fb23c5e2a279481527f2535d9b5e5440413cc6af98adb663186f78d259f976f104cb4f76715e67464a481830152610100830152825180840184527f1ad0852ae1f831506b33a76a4968849abaf87e068b8e00ba462e190ff4dc0ff981527f2b782e70b28e331338317e348ecb3d3ee69c0cb7b1ca634b32395b5349605a9381830152610120830152825180840184527f1604c8e5d6ce24f3baba52a593b1cf1507c8a1357c75775442436f701418a82081527f0c8a43f7fb0126b66d5d6c647fc9aa8d09051257b044d94ee0debdfcc6f1ae5c81830152610140830152825180840184527f0c337b0675b5af476fa5c17005d0aa5152ac687cc653a071a79678b74716312c81527f035e6b0e7c238825d6bb8c9b11cbb70f7400495cbd8fadd3e899b0547ff9f3ce81830152610160830152825180840184527f249ae211312754c1051fe190743256ea29ff511738ea860f06cee903c737ceca81527f2807759287035cea1a800c0345dc3eeef464b065e4f6a93460389efe3074cb5781830152610180830152825180840184527f2ef3f836712c8fc799a66781bcd55cc8353dd7f8ea59bda4d43206cbbb1ac9af81527f0934e084cb8975eca5f56d70381f76b5329bed47eba6c43641348813fa45c446818301526101a0830152825180840184527f302e53d8383dccd3ad70cfe455e96266e1116a4f01db74c341d636f714d70d6481527f20ae439180f84f52f126ea79e599d8dd0d48ee1eb2d1a900dd70c283eefe6ffa818301526101c0830152825180840184527f06ad314a270f473690714633dba8d204b9f038ec788ec9a539190250fb378b4b81527f05418e8c257aa16c69aa40bb7889bf132650f1a5f3ff4d48d497da2e28575412818301526101e0830152825180840184527f18c800374e5c52e0f349f93b2a80789686b4870ccab7ea0af4ad6c10927e9ee281527f0db8ddce2af043ddffc7e3faca1616ab1627e3d325ddd377fcfeb422c20bef1b81830152610200830152825180840184527f1ddf6ec6212f464cb074aa12ef97200389eb34807007b6243175d7733fbd0ba781527f11c6984eeeee856dbf0ea6fb205c22f4baf67493f14bebcf8d06881f6c26086381830152610220830152825180840184527f02fbb6e7ceadf0602d9bf816c4a489f2cd316e6bf61143a49f26476d1eb1337e81527f14b39afce4216499e8a4ec238a338d661d148e97f8cad8ee7886d7478904949381830152610240830152825180840184527f06245d3794ed47626fd5bea673034b71f9637b655d5c0371171998ac1fbd213881527f0dc0d33a35661df4233d14c0b58da89730a97f2b2a0623eb385ddd95ad77cacf81830152610260830152825180840184527f0d3131337b50acb6e11df1df9caad0f2d06cba675f550e0617e98402c31b7df881527f2c38fe613d6e8c2a737335ab36c7eb95c40e26a88fb7844cbc6c764c6bc9e18181830152610280830152825180840184527f0ab14ef9813049410b7ad055a854fd2bd5c2680f1a231a459e43448da397c80081527f2d3459536d6970da05eab1bce67a6cda29cb1f0e33dbd4655b69096ad9bad573818301526102a0830152825180840184527f2e43c492c273f1c80c2f4b97034b5d852d25d9ea4f47bc0858967bdd6562b16c81527f23a7bd136f070f40dad67e55de6c32932cd5e6a076c2dfe6bd7f85253c7552c8818301526102c0830152825180840184527f1233edcd782a5481fa9b9823c6fdef2faf76fd40d7075231e368458619f5a99f81527f2da31aee3bb0f2db3f9c2c5f96e86fb5f9d7013771c55e790abf12ba6a673046818301526102e0830152825180840184527f289f137ca45d566dd066ef81c1d6f049654107fe2490d9aef7c27937032007f081527f1c4dbb5e7e6da2877b61296b60dca4d82b0cbbb5fd110feae054bf39c1d1e31d81830152610300830152825180840184527f089f5ce8686f0845e1ec05b6f39418e57533edc6143896fa1968fa0c6272897d81527f2ad42e3bd60c95aa37746e3a4d2282dfc4222953b1f30cffd52aa0bb80a72ef181830152610320830152825180840184527f19966ae74c271049f1b736f531c33d46a573ded81dc131335acf2156ad191e3d81527f1f683771fa8dbe01394f3b5e6248d48f654e1708eb68b58dffd23da40911cba681830152610340830152825180840184527f2e13855639e143fc28d05a89991e8fb52cfd4ad7ccaf65e2a3006617d63529e381527f098c3eb66469730cd1ccd20763c0e027dd774490c503a43fce6693a6e76913ed81830152610360830152825180840184527f08bbb2006058a97ecedcef1c44ad8ff67aa525fa3703e996bacb50f71df2b84781527f029b1e53dbf2ef50bc0d7f156950de6009e73e99c91936daa734a838fa72e9878183015261038083015282518084018452600181526002818301526103a083015282518084019093527f0b2c2935a1585a74f048f8c7180ea24fd9f923c7a18b102910e64934bebc24c683527f105494650de4293305a47c54f78869100597fb101df4616075669b353392cd56908301526103c081019190915290565b5f60208214611e60575f5ffd5b611e6d6107748385615c85565b9392505050565b611e7c615834565b60808214611e88575f5ffd5b604080516080810190915280611ea160205f8688615c32565b611eaa91615c85565b8152602090810190611ec0906040908688615c32565b611ec991615c85565b8152602001611edc606060408688615c32565b611ee591615c85565b8152602001611ef8608060608688615c32565b611f0191615c85565b90529392505050565b611f12615858565b5f611f21898989898989613394565b604086019190915260208501919091529083529250611f40838a613836565b608085019190915260608401919091529199919850909650505050505050565b611f68615888565b5f611f716158a7565b84815260e0848101805151602080850191909152815181015160408086019190915282518101516060808701919091529251830151608086015261010080890180515160a0880152805184015160c0880152805183015195870195909552935190920151928401929092525161200891611fed91849101615ca2565b604051602081830303815290604052805190602001206128b7565b915061201382613905565b6020850152835260015b600261202b6001601c615c0c565b6120359190615cea565b8110156120b55761205283604051602001611fed91815260200190565b925061205d83613905565b85612069846002615bf5565b601b811061207957612079615c59565b6020020186612089856002615bf5565b612094906001615c1f565b601b81106120a4576120a4615c59565b60200201919091525260010161201d565b506120c26001601c615c0c565b60011660011480156120df575060026120dd6001601c615c0c565b115b15612134576120fa82604051602001611fed91815260200190565b915061210582613905565b5083600161211481601c615c0c565b61211e9190615c0c565b601b811061212e5761212e615c59565b60200201525b509250929050565b6121446158c6565b5f805b601c8110156121915761216684604051602001611fed91815260200190565b935061217184613905565b508382601c811061218457612184615c59565b6020020152600101612147565b5090929050565b5f5f6121a26158e5565b84815261012084018051515160208084019190915281515181015160408085019190915282515181015160608086019190915292515190920151608084015261014086015160a084015290516121fe91611fed91849101615cfd565b915061220982613905565b50959194509092505050565b61221d6158c6565b5f805b601c8110156122db57612231615903565b8481525f5b600981101561229a5786610160015183601c811061225657612256615c59565b6020020151816009811061226c5761226c615c59565b60200201518261227d836001615c1f565b600a811061228d5761228d615c59565b6020020152600101612236565b506122af81604051602001611fed9190615d30565b94506122ba85613905565b508483601c81106122cd576122cd615c59565b602002015250600101612220565b50909391925050565b5f5f6122ee615922565b83815260015b6029811161234b5761018086015161230d600183615c0c565b6029811061231d5761231d615c59565b602002015182826038811061233457612334615c59565b60200201528061234381615c6d565b9150506122f4565b856101a0015182826038811061236357612363615c59565b6020020152612373600182615c1f565b610120870151602001515190915082826038811061239357612393615c59565b60200201526101208601516001602002015160200151828260016123b79190615c1f565b603881106123c7576123c7615c59565b60200201526101208601516001602002015160400151826123e9836002615c1f565b603881106123f9576123f9615c59565b602002015261012086015160016020020151606001518261241b836003615c1f565b6038811061242b5761242b615c59565b602002015261243b600482615c1f565b610120870151604001515190915082826038811061245b5761245b615c59565b602002015261012086015160026020020151602001518282600161247f9190615c1f565b6038811061248f5761248f615c59565b60200201526101208601516040908101510151826124ae836002615c1f565b603881106124be576124be615c59565b60200201526101208601516040015160600151826124dd836003615c1f565b603881106124ed576124ed615c59565b60200201526124fd600482615c1f565b6101c08701515190915082826038811061251957612519615c59565b602002018181525050856101c00151602001518282600161253a9190615c1f565b6038811061254a5761254a615c59565b60200201526101c08601516040015182612565836002615c1f565b6038811061257557612575615c59565b60200201526101c08601516060015182612590836003615c1f565b603881106125a0576125a0615c59565b60200201526125b0600482615c1f565b9050856101e001518282603881106125ca576125ca615c59565b6020020181815250506125e782604051602001611fed9190615d64565b92506125f283613905565b5096929550919350505050565b5f5f612609615941565b8381525f5b61261a6001601c615c0c565b8110156127585785610200015181601b811061263857612638615c59565b6020020151518261264a836004615bf5565b612655906001615c1f565b606d811061266557612665615c59565b602002015261020086015181601b811061268157612681615c59565b602002015160200151828260046126989190615bf5565b6126a3906002615c1f565b606d81106126b3576126b3615c59565b602002015261020086015181601b81106126cf576126cf615c59565b602002015160400151826126e4836004615bf5565b6126ef906003615c1f565b606d81106126ff576126ff615c59565b602002015261020086015181601b811061271b5761271b615c59565b60200201516060015182612730836004615bf5565b61273b906004615c1f565b606d811061274b5761274b615c59565b602002015260010161260e565b506121fe81604051602001611fed9190615d98565b5f5f612777615960565b83815260015b601c81116127d457610220860151612796600183615c0c565b601c81106127a6576127a6615c59565b60200201518282602181106127bd576127bd615c59565b6020020152806127cc81615c6d565b91505061277d565b505f806127e3601c6001615c1f565b90505b6127f2601c6004615c1f565b811161284b57866102400151826004811061280f5761280f615c59565b602002015183826021811061282657612826615c59565b60200201528161283581615c6d565b925050808061284390615c6d565b9150506127e6565b506125e782604051602001611fed9190615dcc565b5f5f61286a61597f565b838152610260850180515160208084019190915281518101516040808501919091528251810151606080860191909152925190920151608084015290516121fe91611fed91849101615e00565b5f6128cf5f516020615f825f395f51905f5283615e33565b92915050565b5f5f516020615f825f395f51905f528284099392505050565b5f5f516020615f825f395f51905f528284089392505050565b5f5f516020615f825f395f51905f5261292d835f516020615f825f395f51905f52615c0c565b84089392505050565b5f611e6d8361077984612b85565b5f5f604051806101200160405280619d8081526020015f516020615fa25f395f51905f5281526020016105a081526020015f516020615f225f395f51905f52815260200161024081526020015f516020615f225f395f51905f5281526020016105a081526020015f516020615fa25f395f51905f528152602001619d8081525090505f600190505f5f90505b60098110156129f1576129e7826107798784612907565b91506001016129d0565b506129fa6158a7565b5f5b6009811015612a4b57612a2c610ab3858360098110612a1d57612a1d615c59565b60200201516107798985612907565b828260098110612a3e57612a3e615c59565b60200201526001016129fc565b505f5b6009811015612a9157612a878561077e898460098110612a7057612a70615c59565b6020020151858560098110610a2757610a27615c59565b9450600101612a4e565b50612a9c84836128d5565b9695505050505050565b5f612aaf6158c6565b612aba868285613935565b612ac686868386613ae1565b612ad286868386613ccd565b612add868285613ef2565b612ae88682856140e6565b612af48686838661442f565b612b00868683866148e2565b612b0b868285614ce1565b612b168682856150a2565b612a9c81856153a2565b612b286158c6565b81815260015b601c811015612b7f57612b6082612b46600184615c0c565b601c8110612b5657612b56615c59565b6020020151612d60565b8282601c8110612b7257612b72615c59565b6020020152600101612b2e565b50919050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f516020615f825f395f51905f520360808201525f516020615f825f395f51905f5260a082015260205f60c08360055afa905080612be3575f5ffd5b50505f519392505050565b612bf661599d565b604051806040016040528060888460200151901b845f015117815260200160888460600151901b8460400151178152509050919050565b5f6128cf825f516020615f825f395f51905f52615c0c565b612c4d6158c6565b601c5b8015612d56575f84612c63600184615c0c565b601c8110612c7357612c73615c59565b602002015190505f88612c87600185615c0c565b601c8110612c9757612c97615c59565b602002015190505f612cf2612cb6612caf858c6128d5565b60026128d5565b61079c8a612cc5600189615c0c565b601c8110612cd557612cd5615c59565b6020020151610779612cec8861077960018a612907565b87612907565b9050612d1381610779610ab3612d0d87610779600189612907565b866128ee565b9050858411612d42579750878085612d2c600187615c0c565b601c8110612d3c57612d3c615c59565b60200201525b50505080612d4f90615e46565b9050612c50565b5095945050505050565b5f6128cf82836128d5565b5f600181612d84612d7e87610100615407565b83612907565b905080612da45760405163835eb8f760e01b815260040160405180910390fd5b612dac6159b5565b80518390525f5b601c811015612e76575f612dc8826009615bf5565b612dd3906001615c1f565b905084835f0151826101008110612dec57612dec615c59565b60200201525f612dfd826001615c1f565b90505b612e0b600983615c1f565b811015612e6c578351612e4b90612e23600184615c0c565b6101008110612e3457612e34615c59565b60200201518a85601c8110610a2757610a27615c59565b8451826101008110612e5f57612e5f615c59565b6020020152600101612e00565b5050600101612db3565b50608081018390525f602082018190525b610100811015612f7457612ea8612ea283608001518a6128d5565b85612907565b8260a00151826101008110612ebf57612ebf615c59565b602002015260a0820151612ee990826101008110612edf57612edf615c59565b6020020151612b85565b8260a00151826101008110612f0057612f00615c59565b602002018181525050612f46826020015161077e845f0151846101008110612f2a57612f2a615c59565b60200201518560a00151856101008110610a2757610a27615c59565b60208301526080820151612f67905f516020615f625f395f51905f526128d5565b6080830152600101612e87565b505f612f8583610779610100612b85565b9050612f958260200151826128d5565b602083015260a0820151612fb0905f5b6020020151826128d5565b604083015260a0820151612fdc90612fcb6001610100615c0c565b6101008110612fa557612fa5615c59565b60608301526040820151612ff2908a6002610a27565b60c0830181905261303e9061077e6130178b5f516020615f625f395f51905f52612907565b61077961302d8e600160200201518f6002610aa9565b8e51602089015161079c91906128d5565b60c083018190526060830151613073916130679161077e906107798e600260200201518c612907565b61079c858c6003610a27565b60c08301819052159998505050505050505050565b61309061599d565b5f600361309f601c6029615c1f565b6130a99190615c1f565b6130b4906003615c1f565b90506001604051855151604082015285516020015160608201528451608082015260408160606040840160075afa8216915060015b838110156131425760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa909216916001016130e9565b50805184526020810151602085015250505092915050565b61316261599d565b5f516020615f425f395f51905f5282602001515f516020615f425f395f51905f5261318d9190615c0c565b6131979190615e33565b60208301525090565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b0316836040516133369190615e5b565b5f60405180830381855afa9150503d805f811461336e576040519150601f19603f3d011682016040523d82523d5f602084013e613373565b606091505b5091509150818015612a9c575080806020019051810190612a9c9190615e71565b5f808080806133a4876003615c1f565b6133af90600c615c1f565b6001600160401b038111156133c6576133c6615e90565b6040519080825280602002602001820160405280156133ef578160200160208202803683370190505b509050875f1b815f8151811061340757613407615c59565b602002602001018181525050865f1b8160018151811061342957613429615c59565b602002602001018181525050855f1b8160028151811061344b5761344b615c59565b60209081029190910101525f5b613463601089615c0c565b8110156134b4578a8a8281811061347c5761347c615c59565b90506020020135828260036134919190615c1f565b815181106134a1576134a1615c59565b6020908102919091010152600101613458565b505f5b6010811015613525578b516134df9082601081106134d7576134d7615c59565b602002015190565b828260106134ee8c6003615c1f565b6134f89190615c0c565b6135029190615c1f565b8151811061351257613512615c59565b60209081029190910101526001016134b7565b5060208b01515181613538896003615c1f565b8151811061354857613548615c59565b6020908102919091018101919091528b810151015181613569896003615c1f565b613574906001615c1f565b8151811061358457613584615c59565b6020908102919091018101919091528b015160400151816135a6896003615c1f565b6135b1906002615c1f565b815181106135c1576135c1615c59565b6020908102919091018101919091528b015160600151816135e3896003615c1f565b6135ee906003615c1f565b815181106135fe576135fe615c59565b602090810291909101015260408b0151518161361b896003615c1f565b613626906004615c1f565b8151811061363657613636615c59565b60209081029190910181019190915260408c0151015181613658896003615c1f565b613663906005615c1f565b8151811061367357613673615c59565b60209081029190910101526040808c0151015181613692896003615c1f565b61369d906006615c1f565b815181106136ad576136ad615c59565b602090810291909101015260408b015160600151816136cd896003615c1f565b6136d8906007615c1f565b815181106136e8576136e8615c59565b602090810291909101015260608b01515181613705896003615c1f565b613710906008615c1f565b8151811061372057613720615c59565b60209081029190910181019190915260608c0151015181613742896003615c1f565b61374d906009615c1f565b8151811061375d5761375d615c59565b602090810291909101015260608b0151604001518161377d896003615c1f565b61378890600a615c1f565b8151811061379857613798615c59565b60209081029190910101526060808c01510151816137b7896003615c1f565b6137c290600b615c1f565b815181106137d2576137d2615c59565b6020026020010181815250506137f281604051602001611fed9190615ea4565b91506137fd82613905565b60408051602081018690529297509095506138189101611fed565b915061382382613905565b5080935050509650965096509692505050565b5f5f5f6138416159f9565b85815260a085810180515160208085019190915281518101516040808601919091528251810151606080870191909152925183015160808087019190915260c0808b0180515196880196909652855184015190870152845182015160e0870152935183015161010086015292880180515161012086015280518201516101408601528051840151610160860152519091015161018084015290516138eb91611fed91849101615ed9565b91506138f682613905565b90979096509194509092505050565b5f80826001600160801b038116608082901c613920826128b7565b945061392b816128b7565b9350505050915091565b5f613941846007615461565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f6139a261399c613976856003612907565b6107796139916139868b5f615461565b6107798c601d615461565b6107798b601c615461565b836128d5565b9050613a23613a186139ff6139e66139cd8561077e6139c28d6002615461565b6107798e601c615461565b61077e6139db8c6003615461565b6107798d601d615461565b61077e6139f48b6004615461565b6107798c601e615461565b61077e613a0d8a6005615461565b6107798b601f615461565b61077e886001615461565b9050613a428161077e613a37866001612907565b6107798a6027615461565b9050613a4e81846128d5565b9050613a5a81856128d5565b8552505f9050613a94613a8a613a7f613a7488601c615461565b61077e89601f615461565b61079c886024615461565b61077e875f615461565b9050613aa581610779846002612907565b9050613ab681610779846001612907565b9050613ac281836128d5565b9050613ace81846128d5565b9050808460015b60200201525050505050565b5f5f5f613b17613b0d613af589601c615461565b61077e613b038b6012615461565b8a606001516128d5565b87608001516128ee565b9050613b5081610779613b46613b2e8b601d615461565b61077e613b3c8d6013615461565b8c606001516128d5565b89608001516128ee565b9050613b7581610779613b46613b678b601e615461565b61077e613b3c8d6014615461565b9050613b9a81610779613b46613b8c8b601f615461565b61077e613b3c8d6015615461565b92505f9050613bbe613b0d613bb089601c615461565b61077e613b038b600e615461565b9050613be381610779613b46613bd58b601d615461565b61077e613b3c8d600f615461565b9050613c0881610779613b46613bfa8b601e615461565b61077e613b3c8d6010615461565b9050613c2d81610779613b46613c1f8b601f615461565b61077e613b3c8d6011615461565b91505f9050613c54613c4e613c43896020615461565b61077e8a601a615461565b846128d5565b9050613c898161079c613c83613c6b8b6028615461565b61077e613c798d601b615461565b8c60a001516128d5565b856128d5565b9050613c9581856128d5565b6040860152505f613cb8613c83613cad89601b615461565b6107798a6028615461565b9050808560035b602002015250505050505050565b5f5f613d2b613d13613cfb613ce6613b468a6016615461565b61077e613cf48b6017615461565b8a516128d5565b61077e613d098a6018615461565b89602001516128d5565b61077e613d21896019615461565b88604001516128d5565b91505f613d62613d49613d3f89601c615461565b88608001516128ee565b61077e613d578a6003615461565b6107798b6024615461565b90505f613d8b613d7389601d615461565b61077e613d808b5f615461565b6107798c6025615461565b90505f613db5613d9c8a601e615461565b61077e613daa8c6001615461565b6107798d6026615461565b9050613df4613ddc613dce8561077e868d5f01516128d5565b61077e848c602001516128d5565b61077e613dea8c6004615461565b8b604001516128d5565b93505050505f613e08613c4e886021615461565b90505f613e19613c4e896021615461565b90505f613e51613e38613e2d8b6023615461565b61077e8c6006615461565b61079c613e468c6023615461565b6107798d6006615461565b90505f613e6f612d7e613e6487896128d5565b6107798d6021615461565b9050613e7b81886128d5565b90505f613ea3613e95613e8f8d6006615461565b876128d5565b61079c613e8f8e6022615461565b90505f613eb18c6023615461565b90505f613ec1612d7e83846128d5565b60808c0185905260a08c018490529050613edb818b6128d5565b8b6006602002015250505050505050505050505050565b5f613efe5f6001612907565b90505f613f0c5f6002612907565b90505f613f1a5f6003612907565b90505f613f36613f2b88601d615461565b61079c89601c615461565b90505f613f52613f4789601e615461565b61079c8a601d615461565b90505f613f6e613f638a601f615461565b61079c8b601e615461565b90505f613f8a613f7f8b6024615461565b61079c8c601f615461565b905083613f9b81610779818b6128ee565b9050613fab81610779878a6128ee565b9050613fbb8161077987896128ee565b9050613fcc816107798d6008615461565b9050613fd8818a6128d5565b60e08b01525082613fed81610779818b6128ee565b9050613ffd81610779868a6128ee565b905061400d8161077986896128ee565b905061401e816107798d6008615461565b905061402a818a6128d5565b6101008b0152508161404081610779818b6128ee565b905061405081610779858a6128ee565b90506140608161077985896128ee565b9050614071816107798d6008615461565b905061407d818a6128d5565b6101208b0152508061409381610779818b6128ee565b90506140a381610779848a6128ee565b90506140b38161077984896128ee565b90506140c4816107798d6008615461565b90506140d0818a6128d5565b610140909a019990995250505050505050505050565b61411f6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61412a84601d615461565b815261413784601e615461565b6020820152614147846024615461565b6040820152614157846027615461565b6060820152614167846026615461565b6080820152614177846025615461565b60a08201525f614188856002615461565b90505f614195865f615461565b90505f6141a98460400151855f0151612907565b90505f6141be856020015186602001516128d5565b606086015190915086905f906141d490806128d5565b90505f6141f26141ec89602001518a606001516128d5565b886128d5565b90505f61421161420a8a60a001518b604001516128ee565b8a516128ee565b9050614220613e8f82886128d5565b905061424761424161423b6142358487612907565b88612907565b846128ee565b836128ee565b905061426f61426461425983876128d5565b6107798f6009615461565b61077960018a612907565b6101608c015250505050602085015160808601515f9161428e916128ee565b90505f6142ac6142a28860600151886128d5565b8860200151612907565b90505f6142d06142bc84876128d5565b61077e613c838b60a001518c5f0151612907565b90506142f86142ed6142e2838c6128d5565b6107798e6009615461565b610779600189612907565b6101808b0152505f915061431990506143128360116128ee565b87516128d5565b90505f61432683846128ee565b905061433281826128ee565b90505f6143408360096128d5565b9050614369614363613c4e61435c8b60a001518c5f01516128ee565b8b516128ee565b82612907565b60c089018190525f90614384906141ec90614259908d6128d5565b90506143978b600b6020020151826128ee565b6101608c0152505086515f92506143be9150614312906143b790806128ee565b88516128ee565b90505f6143fe6143d9836107798a5f01518b60a00151612907565b602089015161079c906143ec90806128ee565b6107798b602001518c608001516128ee565b905061441b89600c602002015161077e6141ec614259858d6128d5565b89600c602002015250505050505050505050565b614499604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6144b16144a786601e615461565b85604001516128d5565b8082526144d09061077e6144c688601d615461565b87602001516128d5565b8082526144e59061077e61431288601c615461565b8082526144f79061077e876001615461565b808252602082018190526145109061079c87601f615461565b815261452b614520866024615461565b61079c87601c615461565b608082015261454961453e866027615461565b61079c87601f615461565b6060820152608081015161456b9061456190806128d5565b8260800151612907565b6101c082015260808101516145ab906145a19061459a9061077960015f516020615f825f395f51905f52615c0c565b60016128ee565b82606001516128d5565b60a082018190526145e1906145d3906107796145c8896002615461565b6107798a6003615461565b610779613c8388600a615461565b83600e60200201526101c0810151614605906145d3906107796145c8896002615461565b6101e0840152805161462a9061077961461f886002615461565b610779896003615461565b6101208201525f61464961463f87601f615461565b8360200151612907565b905061465861436382836128d5565b60e083015261467561466b876026615461565b86604001516128d5565b604083018190526146989061077e61468e896025615461565b88602001516128d5565b604083018190526146b89061077e6146b1896024615461565b88516128d5565b60408301526146d56146cb876027615461565b8360400151612907565b60408301525f6146f46146e9886026615461565b61079c89601e615461565b905061474661472161399c61459a866080015160015f516020615f825f395f51905f526107799190615c0c565b61077961459a866040015160015f516020615f825f395f51905f526107799190615c0c565b60c084015260408301516147689061475e90806128d5565b8460400151612907565b61010084015260c083015161479490614786906107798a6007615461565b610779613e8f8a600a615461565b6102008601526101c08301516147b390614786906107798a6007615461565b6102208601526101008301516147d290614786906107798a6007615461565b61024086015260e08301516147ec90610779896007615461565b61014084015261480b614800886025615461565b61079c89601d615461565b6101608401526080830151614849906146e99061483e9061459a9061077960015f516020615f825f395f51905f52615c0c565b8561016001516128d5565b61018084018190526101208401516101a085018190526148809161077e906107796148758c6005615461565b6107798d6002615461565b6101a0840181905283516148a0919061077e906107796148758c5f615461565b6101a084018190526101408401516148b891906128ee565b6101a084018190526148d290610779613e8f8a600a615461565b6101a0840181905285600d613cbf565b61491b6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61495061493761492c87601c615461565b610779886025615461565b61077e614945886024615461565b61077989601d615461565b815261499561498a61497161496688601c615461565b61077989601f615461565b61077e61497f89601d615461565b6107798a601e615461565b61079c876026615461565b604082018190526149aa90600160441b6128d5565b604082018190526149c09061079c876027615461565b6040820181905281516149d391906128ee565b604082018190526149e990610779876005615461565b604082015280516149fe90600160441b6128d5565b808252614a1e9061077e614a13886024615461565b610779896025615461565b80825260208201819052614a3a9061079c613a7488601e615461565b60208201819052614a5090610779876004615461565b6020820152805160608201819052614a6d9061077e87601f615461565b60608201819052614a919061079c614a86886026615461565b61077e896027615461565b60608201819052614aa690610779875f615461565b8160600181815250505f614acf614ac5836020015184604001516128ee565b83606001516128ee565b9050614ae081610779886003615461565b9050614af8614af0876025615461565b6140006128d5565b60808301819052614b0e9061077e886024615461565b60808301819052614b21906140006128d5565b60808301819052614b379061077e88601e615461565b60808301819052614b4a906140006128d5565b60808301819052614b609061077e88601d615461565b60808301819052614b73906140006128d5565b60808301819052614b899061077e88601c615461565b60808301819052614b9f9061079c88601f615461565b60808301819052614bb590610779886005615461565b6080830152614bc8614af0876026615461565b60a08301819052614bde9061077e886025615461565b60a08301819052614bf1906140006128d5565b60a08301819052614c079061077e886024615461565b60a08301819052614c1a906140006128d5565b60a08301819052614c309061077e88601f615461565b60a08301819052614c43906140006128d5565b60a08301819052614c599061077e88601e615461565b60a08301819052614c6f9061079c886027615461565b60a08301819052614c8490610779885f615461565b60a0830181905260808301515f91614c9c91906128ee565b9050614cad81610779896004615461565b9050614cb982826128ee565b60c08401819052614cd290610779613e8f8a600b615461565b60c08401819052856013613cbf565b614d576040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b614d70614d6585601c615461565b61077e866002615461565b8152614d8b614d8085601d615461565b61077e866003615461565b6020820152614da9614d9e85601e615461565b61077e866004615461565b6040820152614dc7614dbc85601f615461565b61077e866005615461565b60608201528051614df990614df290614deb90614de490806128d5565b84516128d5565b83516128d5565b82516128d5565b60808201526020810151614e3790614e2d90614e2390614e1990806128d5565b84602001516128d5565b83602001516128d5565b82602001516128d5565b60a08201526040810151614e7590614e6b90614e6190614e5790806128d5565b84604001516128d5565b83604001516128d5565b82604001516128d5565b60c08201526060810151614ea9906145a190614e9f90614e9590806128d5565b84606001516128d5565b83606001516128d5565b60e0820152608081015160a0820151614ec291906128ee565b61010082015260c081015160e0820151614edc91906128ee565b61012082015260a0810151614f0090614ef590806128ee565b8261012001516128ee565b61014082015260e0810151614f2490614f1990806128ee565b8261010001516128ee565b610160820152610120810151614f3a90806128ee565b6101e08201819052614f5b90614f5090806128ee565b8261016001516128ee565b6101e0820152610100810151614f7190806128ee565b6101a08201819052614f9290614f8790806128ee565b8261014001516128ee565b6101a08201819052610160820151614fa9916128ee565b6101808201526101408101516101e0820151614fc591906128ee565b6101c0820152614fd961399c85600c615461565b61020082018190526102808401516101808301516150049261077e916107799061079c8a6024615461565b8360146020020152615034836015602002015161077e836102000151610779856101a0015161079c8a6025615461565b8360156020020152615064836016602002015161077e836102000151610779856101c0015161079c8a6026615461565b8360166020020152615094836017602002015161077e836102000151610779856101e0015161079c8a6027615461565b836017602002015250505050565b6150f46040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f60405180608001604052806151297f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e76128b7565b81526020016151577f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b6128b7565b81526020016151847e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac156128b7565b81526020016151b27f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b6128b7565b905290506151cf6151c486601c615461565b61077e876002615461565b610120830181905261520e90615203906151f8906151ed90806128d5565b8561012001516128d5565b8461012001516128d5565b8361012001516128d5565b825261521b85601d615461565b602083015261522b85601e615461565b604083015261523b85601f615461565b60608301528151602083015161526391614ac59161525991906128ee565b84604001516128ee565b6080830152615276613c4e86600d615461565b61014083015281516152979061528d90835f610a27565b83608001516128ee565b60a08301526152c3846018602002015161077e8461014001516107798660a0015161079c8b6024615461565b61030085015260208201516152de9061528d90836001610a27565b60c083015261530a846019602002015161077e8461014001516107798660c0015161079c8b6025615461565b61032085015260408201516153259061528d90836002610a27565b60e083015261535184601a602002015161077e8461014001516107798660e0015161079c8b6026615461565b610340850152606082015161536c9061528d90836003610a27565b61010083015261539a84601b602002015161077e84610140015161077986610100015161079c8b6027615461565b84601b613ad5565b5f6153ae81848161092c565b905060015b601c811015615400576153f68261077e8684601c81106153d5576153d5615c59565b6020020151866153e6600187615c0c565b601b8110610a2757610a27615c59565b91506001016153b3565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f516020615f825f395f51905f5260a082015260205f60c08360055afa905080615455575f5ffd5b50505f51949350505050565b5f8282602881111561547557615475615f0d565b6029811061548557615485615c59565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f81526020016154b761599d565b81526020016154c461599d565b81526020016154d161599d565b81526020016154de61599d565b81526020016154eb61599d565b81526020016154f861599d565b815260200161550561599d565b815260200161551261599d565b815260200161551f61599d565b815260200161552c61599d565b815260200161553961599d565b815260200161554661599d565b815260200161555361599d565b815260200161556061599d565b815260200161556d61599d565b815260200161557a61599d565b815260200161558761599d565b815260200161559461599d565b81526020016155a161599d565b81526020016155ae61599d565b81526020016155bb61599d565b81526020016155c861599d565b81526020016155d561599d565b81526020016155e261599d565b81526020016155ef61599d565b81526020016155fc61599d565b815260200161560961599d565b815260200161561661599d565b905290565b604051806102a0016040528061562f615a18565b815260200161563c615834565b8152602001615649615834565b8152602001615656615834565b8152602001615663615834565b8152602001615670615834565b815260200161567d615834565b815260200161568a615834565b8152602001615697615834565b81526020016156a4615a37565b81526020015f81526020016156b7615a64565b81526020016156c4615a92565b81526020015f81526020016156d7615834565b81526020015f81526020016156ea615ab1565b81526020016156f76158c6565b8152602001615704615adf565b8152602001615711615834565b8152602001615616615834565b604051806101400160405280615732615858565b815260200161573f615888565b815260200161574c6158c6565b81526020015f815260200161575f6158c6565b81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f81526020016157b5615adf565b81526020016157c2615adf565b81526020015f81526020015f81526020015f81526020015f81526020016156166158c6565b604051806109600160405280604b906020820280368337509192915050565b604051806109600160405280604b905b61581e61599d565b8152602001906001900390816158165790505090565b60405180608001604052805f81526020015f81526020015f81526020015f81525090565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806103600160405280601b906020820280368337509192915050565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b604051806101400160405280600a906020820280368337509192915050565b6040518061070001604052806038906020820280368337509192915050565b60405180610da00160405280606d906020820280368337509192915050565b6040518061042001604052806021906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b60405180604001604052805f81526020015f81525090565b6040518060e001604052806159c8615afd565b81526020015f81526020015f81526020015f81526020015f81526020016159ed615afd565b81526020015f81525090565b604051806101a00160405280600d906020820280368337509192915050565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b615a4e615834565b815260200190600190039081615a465790505090565b604051806103800160405280601c905b615a7c6158a7565b815260200190600190039081615a745790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b615ac9615834565b815260200190600190039081615ac15790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215615b30575f5ffd5b84356001600160401b03811115615b45575f5ffd5b8501601f81018713615b55575f5ffd5b80356001600160401b03811115615b6a575f5ffd5b876020828401011115615b7b575f5ffd5b6020918201955093508501356001600160401b03811115615b9a575f5ffd5b8501601f81018713615baa575f5ffd5b80356001600160401b03811115615bbf575f5ffd5b8760208260051b8401011115615bd3575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176128cf576128cf615be1565b818103818111156128cf576128cf615be1565b808201808211156128cf576128cf615be1565b5f5f85851115615c40575f5ffd5b83861115615c4c575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f60018201615c7e57615c7e615be1565b5060010190565b803560208310156128cf575f19602084900360031b1b1692915050565b5f8183825b6009811015615cc6578151835260209283019290910190600101615ca7565b5050506101208201905092915050565b634e487b7160e01b5f52601260045260245ffd5b5f82615cf857615cf8615cd6565b500490565b5f8183825b6006811015615d21578151835260209283019290910190600101615d02565b50505060c08201905092915050565b5f8183825b600a811015615d54578151835260209283019290910190600101615d35565b5050506101408201905092915050565b5f8183825b6038811015615d88578151835260209283019290910190600101615d69565b5050506107008201905092915050565b5f8183825b606d811015615dbc578151835260209283019290910190600101615d9d565b505050610da08201905092915050565b5f8183825b6021811015615df0578151835260209283019290910190600101615dd1565b5050506104208201905092915050565b5f8183825b6005811015615e24578151835260209283019290910190600101615e05565b50505060a08201905092915050565b5f82615e4157615e41615cd6565b500690565b5f81615e5457615e54615be1565b505f190190565b5f82518060208501845e5f920191825250919050565b5f60208284031215615e81575f5ffd5b81518015158114611e6d575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b81515f90829060208501835b82811015615ece578151845260209384019390910190600101615eb0565b509195945050505050565b5f8183825b600d811015615efd578151835260209283019290910190600101615ede565b5050506101a08201905092915050565b634e487b7160e01b5f52602160045260245ffdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a2646970667358221220f5817414f513714a4ba84cf96f44572499693d50c314874684b6238796029ec564736f6c634300081d0033 diff --git a/eth/contracts/noir/utxo_HonkVerifier.bin b/eth/contracts/noir/utxo_HonkVerifier.bin new file mode 100644 index 0000000..36ab425 --- /dev/null +++ b/eth/contracts/noir/utxo_HonkVerifier.bin @@ -0,0 +1 @@ +60e060405234801561000f575f5ffd5b50612000608052600d60a052601960c05260805160a05160c051615ff96100655f395f818160d601526107ac01525f81816108da015281816109e701528181610f460152610ff201525f6107500152615ff95ff3fe608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063ea50d0e41461002d575b5f5ffd5b61004061003b366004615b1f565b610054565b604051901515815260200160405180910390f35b5f6100626101fc6020615bf7565b8414610081576040516376ba560560e11b815260040160405180910390fd5b5f61008a6101af565b90505f61009787876101c4565b9050601082604001516100aa9190615c0e565b84146100c95760405163fa06659360e01b815260040160405180910390fd5b5f6100fc828787865f01517f00000000000000000000000000000000000000000000000000000000000000006001610676565b905061014c8686808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250508551855160608101516080909101519193509150600161073a565b815160a0015261015c82826108bd565b610179576040516313f8744360e31b815260040160405180910390fd5b610184828483610a6f565b6101a1576040516352ec174560e11b815260040160405180910390fd5b506001979650505050505050565b6101b7615493565b6101bf61151b565b905090565b6101cc61561d565b5f805b601081101561022e576101fb8583866101e9826020615c21565b926101f693929190615c34565b611e55565b8351826010811061020e5761020e615c5b565b6020020181815250506020826102249190615c21565b91506001016101cf565b50610252848285610240826080615c21565b9261024d93929190615c34565b611e76565b6020830152610262608082615c21565b9050610275848285610240826080615c21565b6040830152610285608082615c21565b9050610298848285610240826080615c21565b60608301526102a8608082615c21565b90506102bb848285610240826080615c21565b60a08301526102cb608082615c21565b90506102de848285610240826080615c21565b60c08301526102ee608082615c21565b9050610301848285610240826080615c21565b6080808401919091526103149082615c21565b9050610327848285610240826080615c21565b60e0830152610337608082615c21565b905061034a848285610240826080615c21565b61010083015261035b608082615c21565b905061036e848285610240826080615c21565b61012083015152610380608082615c21565b90506103938482856101e9826020615c21565b6101408301526103a4602082615c21565b90505f5b601c811015610423575f5b600981101561041a576103cd8684876101e9826020615c21565b84610160015183601c81106103e4576103e4615c5b565b602002015182600981106103fa576103fa615c5b565b6020020181815250506020836104109190615c21565b92506001016103b3565b506001016103a8565b505f5b6029811015610477576104408583866101e9826020615c21565b836101800151826029811061045757610457615c5b565b60200201818152505060208261046d9190615c21565b9150600101610426565b506104898482856101e9826020615c21565b6101a083015261049a602082615c21565b90506104ad848285610240826080615c21565b610120830151602001526104c2608082615c21565b90506104d5848285610240826080615c21565b610120830151604001526104ea608082615c21565b90506104fd848285610240826080615c21565b6101c083015261050e608082615c21565b90506105218482856101e9826020615c21565b6101e0830152610532602082615c21565b90505f5b6105426001601c615c0e565b81101561058b5761055a858386610240826080615c21565b83610200015182601b811061057157610571615c5b565b6020020152610581608083615c21565b9150600101610536565b505f5b601c8110156105df576105a88583866101e9826020615c21565b83610220015182601c81106105bf576105bf615c5b565b6020020181815250506020826105d59190615c21565b915060010161058e565b505f5b6004811015610633576105fc8583866101e9826020615c21565b836102400151826004811061061357610613615c5b565b6020020181815250506020826106299190615c21565b91506001016105e2565b50610645848285610240826080615c21565b610260830152610656608082615c21565b9050610669848285610240826080615c21565b6102808301525092915050565b61067e615720565b5f61068e88888888888887611f0c565b908352905061069d8189611f62565b602084019190915290506106b08161213e565b604084019190915290506106c4818961219a565b606084019190915290506106d88882612217565b608084019190915290506106ec88826122e6565b60a084019190915290506107008882612601565b60c08401919091529050610714888261276f565b60e084019190915290506107288882612862565b50610100830152509695505050505050565b5f600180826107838661077e896107796107748a7f0000000000000000000000000000000000000000000000000000000000000000615c21565b6128b9565b6128d7565b6128f0565b90505f6107a18761079c8a6107796107748b6001615c21565b612909565b90505f5b6107d060107f0000000000000000000000000000000000000000000000000000000000000000615c0e565b81101561083d575f6107fa8c83815181106107ed576107ed615c5b565b60200260200101516128b9565b905061080a8661077986846128f0565b955061081a8561077985846128f0565b9450610826848b6128f0565b9350610832838b612909565b9250506001016107a5565b505f5b60108110156108a4575f8a826010811061085c5761085c615c5b565b602002015190506108718661077986846128f0565b95506108818561077985846128f0565b945061088d848b6128f0565b9350610899838b612909565b925050600101610840565b506108af8484612938565b9a9950505050505050505050565b5f5f6108d283606001518561014001516128d7565b905060015f5b7f00000000000000000000000000000000000000000000000000000000000000008110156109c4575f86610160015182601c811061091857610918615c5b565b602002015180519091505f90610936908360015b60200201516128f0565b9050848114610958576040516313f8744360e31b815260040160405180910390fd5b5f876080015184601c811061096f5761096f615c5b565b602002015190506109808382612946565b95506109b485610779600161077e856107798e604001518b601c81106109a8576109a8615c5b565b60200201516001612909565b94505050508060010190506108d8565b505f6109de866101800151865f0151876020015185612aa8565b9050600160025b7f0000000000000000000000000000000000000000000000000000000000000000811015610a3b57610a3182886080015183601c8110610a2757610a27615c5b565b60200201516128d7565b91506001016109e5565b50610a61610a4e83610779600185612909565b61077e896101a0015189606001516128d7565b939093149695505050505050565b5f610a78615785565b5f610a868460c00151612b22565b9050610a906157e9565b610a98615808565b610100860151610ab890610ab390855f5b6020020151612909565b612b87565b60e0850152610100860151610ad290610ab390855f61092c565b610100850181905260e08086015190880151610af29261077e91906128d7565b845260c0860151610b2190610b0690612b87565b6107798660e0015161079c8a60e001518961010001516128d7565b602085015260018252610260880151610b3990612bf0565b81526101e0880151608085015260a086015160608501528351610b5b90612c2f565b60208301525f5b6024811015610bff57610b84610b7a865f0151612c2f565b86606001516128d7565b83610b90836002615c21565b604b8110610ba057610ba0615c5b565b602002015260808501516101808a0151610bd9919061077e908460298110610bca57610bca615c5b565b602002015188606001516128d7565b6080860152606085015160a0880151610bf291906128d7565b6060860152600101610b62565b5060245b6029811015610c8857610c1c610b7a8660200151612c2f565b83610c28836002615c21565b604b8110610c3857610c38615c5b565b602002015260808501516101808a0151610c62919061077e908460298110610bca57610bca615c5b565b6080860152606085015160a0880151610c7b91906128d7565b6060860152600101610c03565b50610c97886101c00151612bf0565b8160016020020152606087015181600260200201526080870151816003602002015260a0870151816004602002015260c0870151816005602002015260e0870151816006602002015261010087015181600760200201526101208701518160086020020152610140870151816009602002015261016087015181600a60200201526101c087015181600b602002015261018087015181600c60200201526101a087015181600d60200201526101e087015181600e602002015261020087015181600f602002015261022087015181601060200201526102408701518160116020020152610260870151816012602002015261028087015181601360200201526102a087015181601460200201526102c087015181601560200201526102e0870151816016602002015261030087015181601760200201526103208701518160186020020152610340870151816019602002015261036087015181601a602002015261038087015181601b60200201526103a087015181601c60200201526103c087015181601d6020020181905250610e328860200151612bf0565b6103c08201526040880151610e4690612bf0565b6103e08201526060880151610e5a90612bf0565b6104008201526080880151610e6e90612bf0565b610420820152610100880151610e8390612bf0565b61044082015260e0880151610e9790612bf0565b61046082015260a0880151610eab90612bf0565b61048082015260c0880151610ebf90612bf0565b6104a08201526020880151610ed390612bf0565b6104c08201526040880151610ee790612bf0565b6104e08201526060880151610efb90612bf0565b6105008201526080880151610f0f90612bf0565b610520820152610100880151610f2490612bf0565b81602a60200201819052505f610f6a876080015186608001518b6102200151877f0000000000000000000000000000000000000000000000000000000000000000612c47565b805160e0870151919250610f7d916128d7565b604086018190526102208a01515160e0890151610fae929161077e91610fa391906128d7565b8861010001516128d7565b604086015260e0870151610fc190612d62565b60608601525f610fd360296002615c21565b90505f5b610fe36001601c615c0e565b8110156111d1575f61101660017f0000000000000000000000000000000000000000000000000000000000000000615c0e565b82101590508061115f5761104a610ab38b61010001518985600161103a9190615c21565b601c8110610aa957610aa9615c5b565b60e08901526101008a015161107990610ab39089611069866001615c21565b601c811061092c5761092c615c5b565b610100890152606088015160e089015161109391906128d7565b610120890152606088015160e08b01516110bb916110b0916128d7565b8961010001516128d7565b61014089018190526110de906110d090612c2f565b61077e8a6101200151612c2f565b866110e98486615c21565b604b81106110f9576110f9615c5b565b60200201526101408801516102208d01515f9161112b9161111b866001615c21565b601c8110610a2757610a27615c5b565b90506111488161077e8b61012001518887600161111b9190615c21565b90506111588960400151826128f0565b60408a0152505b61117e61117489606001518c60e001516128d7565b8b60e001516128d7565b60608901526102008c01516111a89083601b811061119e5761119e615c5b565b6020020151612bf0565b856111b38486615c21565b604b81106111c3576111c3615c5b565b602002015250600101610fd7565b506111de6001601c615c0e565b6111e89082615c21565b90506112086112008961010001518a60c00151612909565b600190612938565b60a08701515261010088015160c089015161124c916112009161079c907f07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76906128d7565b60a087018051602001919091528051805160409091015251805160609182015286015160e089015161128b91611281916128d7565b8960e001516128d7565b60608701525f5b6004811015611338575f6112c48860a0015183600481106112b5576112b5615c5b565b602002015189606001516128d7565b90506112cf81612c2f565b8860c0015183600481106112e5576112e5615c5b565b6020020152606088015160e08b01516112fe91906128d7565b88606001818152505061132a886040015161077e838f61024001518660048110610a2757610a27615c5b565b604089015250600101611292565b5060c0860151518482604b811061135157611351615c5b565b602002015260c0860151611372906001602002015160c0880151600261092c565b8461137e836001615c21565b604b811061138e5761138e615c5b565b602002015260c086015160600151846113a8836002615c21565b604b81106113b8576113b8615c5b565b60200201525f5b600381101561140c576113e28b6101200151826003811061119e5761119e615c5b565b84836113ed81615c6f565b9450604b81106113ff576113ff615c5b565b60200201526001016113bf565b5060405180604001604052806001815260200160028152508382604b811061143657611436615c5b565b60200201526040860151848261144b81615c6f565b9350604b811061145d5761145d615c5b565b6020020181815250506114848a61024001518960c001518a608001518d6101a00151612d6d565b6114a15760405163a2a2ac8360e01b815260040160405180910390fd5b5f6114b08b6102800151612bf0565b9050808483604b81106114c5576114c5615c5b565b60200201526101008901518583604b81106114e2576114e2615c5b565b60200201525f6114f2858761308a565b90505f6114fe8361315c565b905061150a82826131a2565b9d9c50505050505050505050505050565b611523615493565b50604080516103e0810182526120008152600d602080830191909152601982840152825180840184527f05187a1fe3cf77382952a9ef5c23874abaf820553dc94de5db87b20c74d97a6b81527f1750a25606b075cf94193af89c642467f3fc1586d559e8053d5bf51dfd27e154818301526060830152825180840184527f1005447d4ea8674fdb6d748e67c5aa706707157465bd334f1cf90a3c58c67a9981527f132ba20fb4354ddbd11efd43b4ba7d634d3faf56216938dbc353d4b6da63c101818301526080830152825180840184527f074b7f7782fb90edcf35cdbe1f82a27241785c27a9256fe37dc10aea267e325181527f1680467fcc8d7f5b65f0d1e292719f59e4ae34f7d75406a8b44fe39a655eff478183015260a0830152825180840184527f2e54cd2d96807062f90240f11b9f9d5cdd10f1cff3ab8ad2a2083037497f3bec81527f146c5378ffaccdbd2c3ad970aed9d59f93465af9e64f907522dc1a386ec5a7268183015260c0830152825180840184527f2f0a75d147c380a2060be3eb07069f80bfe89a87bf8cb5f53154207059af7fa581527f1d20d992d59d03cfd1f43bf02d07cf582fc048b8dd7dfe5f5f1a9f95f362fff18183015260e0830152825180840184527f0409a06549c62cbeaf31f5c9e0617418ccabc1f3ec40d3fbc923402c6ed22df381527f208ca920487aa488312e1b2de111fa2b244f14ca838c516a0c7261ecf39fc09c81830152610100830152825180840184527f2e57b44b90da66faa200db697385d8231b6e8223f1073f97628acac5e2e0b28b81527f1f9f2a5af3fb5b557da39bd9120c9a4d0a4090a5c806ffff96310036df7fde4081830152610120830152825180840184527f185c050ada81d1487283842029061f75b1a45ab0cf6bbd2907c8a3c1433ccef481527f292e97e585daee293e2a5ff7e81311408dce081a5af44e9c5608d294ab8bffe081830152610140830152825180840184527f0366a6ca12f2e00f3a10668f333bcb410260aa8c95a4f549de1d25e59d16b35481527f2b964c5054fa5b48753af8e2b87ddbcabc42c5e7b3f7c801188dd07e762537cf81830152610160830152825180840184527f21c047610ef104bab7ec47ce7b6f086a404429794fb7014b801d11b89efc40d081527f1aaa4a6fde5952d3e8deb89a16efca3d7ee2890bcaca9e85addb5d3489ca57a081830152610180830152825180840184527f251b2346dee353259a035e5c68b12dd2b64833f3a6a26379b6d5e2ec89c33b5081527f2d85bcbe9b37586ad6f91ac9d6af9ce54fc55ac053d720d42d6ddb5234ef5139818301526101a0830152825180840184527f27bd7625d325e77f89bf6f2507d8cc64548551ad208c21c38e1194d8795eda4b81527f2c9aabde94ec507bac85c5a419346d401fff2f4e6307231dc265c31056bb0bec818301526101c0830152825180840184527f0969acefdadcd4a4d05a2e68e2939d7ea4b59a28226a80f5422d2aee88c9bca381527f12159f88e5b6854738d13bee1907b632fea0b6b58fbd4c1be147c21a12168b22818301526101e0830152825180840184527f09553aebc14f5cbd65e39011b85b47c5a590041515ee494c617c08b2e50e03de81527f2843a93f12e499784959ec739792979e06800c379e4d26f94c4423383d0d296f81830152610200830152825180840184527f2792e2591a646db522f5ccccdc48e67b7cacea26e667875e23247786a716187681527f1feed705f7481503bd33d56e5fdfde17d977694da178bde38fdcf8158d7d34e781830152610220830152825180840184527f1b67b0fd72c24de13d684894cacda194e92cb5b091e6f602c00d5d1e3121d59181527f1365b12cb7af4d23507fc7817bfc4a6691e49995e813f6366aa0f2c9ef033fa081830152610240830152825180840184527f216c3d0f8eb294e97c4f63c3e626bf09f660aa6f1ad9db05adefee39bc66ad5881527f0760c02d7b47a66eb455c476ab1e4a0f18b0023ad6653a4f5d6d21606e3685b881830152610260830152825180840184527f18a1c4b8c5eedcf9a283af24b31eaa3ff0a5314503adacd427128ff4c8f3461581527f2b1451b6492c459e46ccb620827640b57def9e7bba4364bcecbe8382fe20754181830152610280830152825180840184527f24dd2a425b5d13829fbba2891f40bf341690ba6fd86606c86cca1ba2ef367e3181527f1ec3b8efcc9c0a4d6acf49c015c579386c7a9a707bfeb74edddc413cfc79f186818301526102a0830152825180840184527f01ec1c20436f3e5a1b1556e9630c204cc16f73e512d84db4e8eafdd8770f0d3f81527f29bb84f0fb0406afce540ed2e0f597b2035651604c9e89250f3ed612086b0f99818301526102c0830152825180840184527f258ae264804ea0206780c92e4cb665d1a62975fc33aa3b1adabc007eb655c55881527f122e73ce896c18a5da631e9b23a625151d5d994d8ea2dfb8536d331a3c5e768a818301526102e0830152825180840184527f160f024d2704e8d8204896a6118132f1b0cd3bc78f6d651c9a2917cb022b781e81527f15eefaa11ecf968498557e939e8bc096b323d599f3c53a25bc85025f5bd7748181830152610300830152825180840184527f2a2151a981bb85afda957beeb8ee245883ab86e97482786e90275194bb8e80cd81527f2b87f0bc586ed756610eca48de9d4d3c56f54404708eabe1bb6dabd7696203cb81830152610320830152825180840184527f2fa75dcd73148b6cab95e82a24769ca1d1d3280dd5b9c2700c56eb44684b83d281527f247273927cfad5b89f2f6ba25e364acc2ccd40e9b1da53772dac5fcea42ef43281830152610340830152825180840184527f0f14d93997b9549960fe80f8a48b6e3253c97bff329a9ebf6d77d674d15b2e7881527f0cfbb9e38232193a038dcfa17470d74544c40483608bfdb07b81a2bc7c7e092c81830152610360830152825180840184527f11460f1cb9210508c275ec98009facc06544875226c2ef12eb33610665b1c52381527f021b2c1b6d951e023a6a8d2e9cbfc72c35c7a07ca516ed60d7f02e52671a612e8183015261038083015282518084018452600181526002818301526103a083015282518084019093527f0cb7cf8f324150a0ee258178f7e3349e46415dc11355dc8d199928d38efb580883527f19bf6a8f3e5523952973cbc9718aa39930b4cc69a938a22576b99abb87f4b1f3908301526103c081019190915290565b5f60208214611e62575f5ffd5b611e6f6107748385615c87565b9392505050565b611e7e615836565b60808214611e8a575f5ffd5b604080516080810190915280611ea360205f8688615c34565b611eac91615c87565b8152602090810190611ec2906040908688615c34565b611ecb91615c87565b8152602001611ede606060408688615c34565b611ee791615c87565b8152602001611efa608060608688615c34565b611f0391615c87565b90529392505050565b611f1461585a565b5f611f23898989898989613396565b604086019190915260208501919091529083529250611f42838a613838565b608085019190915260608401919091529199919850909650505050505050565b611f6a61588a565b5f611f736158a9565b84815260e0848101805151602080850191909152815181015160408086019190915282518101516060808701919091529251830151608086015261010080890180515160a0880152805184015160c0880152805183015195870195909552935190920151928401929092525161200a91611fef91849101615ca4565b604051602081830303815290604052805190602001206128b9565b915061201582613907565b6020850152835260015b600261202d6001601c615c0e565b6120379190615cec565b8110156120b75761205483604051602001611fef91815260200190565b925061205f83613907565b8561206b846002615bf7565b601b811061207b5761207b615c5b565b602002018661208b856002615bf7565b612096906001615c21565b601b81106120a6576120a6615c5b565b60200201919091525260010161201f565b506120c46001601c615c0e565b60011660011480156120e1575060026120df6001601c615c0e565b115b15612136576120fc82604051602001611fef91815260200190565b915061210782613907565b5083600161211681601c615c0e565b6121209190615c0e565b601b811061213057612130615c5b565b60200201525b509250929050565b6121466158c8565b5f805b601c8110156121935761216884604051602001611fef91815260200190565b935061217384613907565b508382601c811061218657612186615c5b565b6020020152600101612149565b5090929050565b5f5f6121a46158e7565b84815261012084018051515160208084019190915281515181015160408085019190915282515181015160608086019190915292515190920151608084015261014086015160a0840152905161220091611fef91849101615cff565b915061220b82613907565b50959194509092505050565b61221f6158c8565b5f805b601c8110156122dd57612233615905565b8481525f5b600981101561229c5786610160015183601c811061225857612258615c5b565b6020020151816009811061226e5761226e615c5b565b60200201518261227f836001615c21565b600a811061228f5761228f615c5b565b6020020152600101612238565b506122b181604051602001611fef9190615d32565b94506122bc85613907565b508483601c81106122cf576122cf615c5b565b602002015250600101612222565b50909391925050565b5f5f6122f0615924565b83815260015b6029811161234d5761018086015161230f600183615c0e565b6029811061231f5761231f615c5b565b602002015182826038811061233657612336615c5b565b60200201528061234581615c6f565b9150506122f6565b856101a0015182826038811061236557612365615c5b565b6020020152612375600182615c21565b610120870151602001515190915082826038811061239557612395615c5b565b60200201526101208601516001602002015160200151828260016123b99190615c21565b603881106123c9576123c9615c5b565b60200201526101208601516001602002015160400151826123eb836002615c21565b603881106123fb576123fb615c5b565b602002015261012086015160016020020151606001518261241d836003615c21565b6038811061242d5761242d615c5b565b602002015261243d600482615c21565b610120870151604001515190915082826038811061245d5761245d615c5b565b60200201526101208601516002602002015160200151828260016124819190615c21565b6038811061249157612491615c5b565b60200201526101208601516040908101510151826124b0836002615c21565b603881106124c0576124c0615c5b565b60200201526101208601516040015160600151826124df836003615c21565b603881106124ef576124ef615c5b565b60200201526124ff600482615c21565b6101c08701515190915082826038811061251b5761251b615c5b565b602002018181525050856101c00151602001518282600161253c9190615c21565b6038811061254c5761254c615c5b565b60200201526101c08601516040015182612567836002615c21565b6038811061257757612577615c5b565b60200201526101c08601516060015182612592836003615c21565b603881106125a2576125a2615c5b565b60200201526125b2600482615c21565b9050856101e001518282603881106125cc576125cc615c5b565b6020020181815250506125e982604051602001611fef9190615d66565b92506125f483613907565b5096929550919350505050565b5f5f61260b615943565b8381525f5b61261c6001601c615c0e565b81101561275a5785610200015181601b811061263a5761263a615c5b565b6020020151518261264c836004615bf7565b612657906001615c21565b606d811061266757612667615c5b565b602002015261020086015181601b811061268357612683615c5b565b6020020151602001518282600461269a9190615bf7565b6126a5906002615c21565b606d81106126b5576126b5615c5b565b602002015261020086015181601b81106126d1576126d1615c5b565b602002015160400151826126e6836004615bf7565b6126f1906003615c21565b606d811061270157612701615c5b565b602002015261020086015181601b811061271d5761271d615c5b565b60200201516060015182612732836004615bf7565b61273d906004615c21565b606d811061274d5761274d615c5b565b6020020152600101612610565b5061220081604051602001611fef9190615d9a565b5f5f612779615962565b83815260015b601c81116127d657610220860151612798600183615c0e565b601c81106127a8576127a8615c5b565b60200201518282602181106127bf576127bf615c5b565b6020020152806127ce81615c6f565b91505061277f565b505f806127e5601c6001615c21565b90505b6127f4601c6004615c21565b811161284d57866102400151826004811061281157612811615c5b565b602002015183826021811061282857612828615c5b565b60200201528161283781615c6f565b925050808061284590615c6f565b9150506127e8565b506125e982604051602001611fef9190615dce565b5f5f61286c615981565b8381526102608501805151602080840191909152815181015160408085019190915282518101516060808601919091529251909201516080840152905161220091611fef91849101615e02565b5f6128d15f516020615f845f395f51905f5283615e35565b92915050565b5f5f516020615f845f395f51905f528284099392505050565b5f5f516020615f845f395f51905f528284089392505050565b5f5f516020615f845f395f51905f5261292f835f516020615f845f395f51905f52615c0e565b84089392505050565b5f611e6f8361077984612b87565b5f5f604051806101200160405280619d8081526020015f516020615fa45f395f51905f5281526020016105a081526020015f516020615f245f395f51905f52815260200161024081526020015f516020615f245f395f51905f5281526020016105a081526020015f516020615fa45f395f51905f528152602001619d8081525090505f600190505f5f90505b60098110156129f3576129e9826107798784612909565b91506001016129d2565b506129fc6158a9565b5f5b6009811015612a4d57612a2e610ab3858360098110612a1f57612a1f615c5b565b60200201516107798985612909565b828260098110612a4057612a40615c5b565b60200201526001016129fe565b505f5b6009811015612a9357612a898561077e898460098110612a7257612a72615c5b565b6020020151858560098110610a2757610a27615c5b565b9450600101612a50565b50612a9e84836128d7565b9695505050505050565b5f612ab16158c8565b612abc868285613937565b612ac886868386613ae3565b612ad486868386613ccf565b612adf868285613ef4565b612aea8682856140e8565b612af686868386614431565b612b02868683866148e4565b612b0d868285614ce3565b612b188682856150a4565b612a9e81856153a4565b612b2a6158c8565b81815260015b601c811015612b8157612b6282612b48600184615c0e565b601c8110612b5857612b58615c5b565b6020020151612d62565b8282601c8110612b7457612b74615c5b565b6020020152600101612b30565b50919050565b5f5f8290505f604051602081526020808201526020604082015282606082015260025f516020615f845f395f51905f520360808201525f516020615f845f395f51905f5260a082015260205f60c08360055afa905080612be5575f5ffd5b50505f519392505050565b612bf861599f565b604051806040016040528060888460200151901b845f015117815260200160888460600151901b8460400151178152509050919050565b5f6128d1825f516020615f845f395f51905f52615c0e565b612c4f6158c8565b601c5b8015612d58575f84612c65600184615c0e565b601c8110612c7557612c75615c5b565b602002015190505f88612c89600185615c0e565b601c8110612c9957612c99615c5b565b602002015190505f612cf4612cb8612cb1858c6128d7565b60026128d7565b61079c8a612cc7600189615c0e565b601c8110612cd757612cd7615c5b565b6020020151610779612cee8861077960018a612909565b87612909565b9050612d1581610779610ab3612d0f87610779600189612909565b866128f0565b9050858411612d44579750878085612d2e600187615c0e565b601c8110612d3e57612d3e615c5b565b60200201525b50505080612d5190615e48565b9050612c52565b5095945050505050565b5f6128d182836128d7565b5f600181612d86612d8087610100615409565b83612909565b905080612da65760405163835eb8f760e01b815260040160405180910390fd5b612dae6159b7565b80518390525f5b601c811015612e78575f612dca826009615bf7565b612dd5906001615c21565b905084835f0151826101008110612dee57612dee615c5b565b60200201525f612dff826001615c21565b90505b612e0d600983615c21565b811015612e6e578351612e4d90612e25600184615c0e565b6101008110612e3657612e36615c5b565b60200201518a85601c8110610a2757610a27615c5b565b8451826101008110612e6157612e61615c5b565b6020020152600101612e02565b5050600101612db5565b50608081018390525f602082018190525b610100811015612f7657612eaa612ea483608001518a6128d7565b85612909565b8260a00151826101008110612ec157612ec1615c5b565b602002015260a0820151612eeb90826101008110612ee157612ee1615c5b565b6020020151612b87565b8260a00151826101008110612f0257612f02615c5b565b602002018181525050612f48826020015161077e845f0151846101008110612f2c57612f2c615c5b565b60200201518560a00151856101008110610a2757610a27615c5b565b60208301526080820151612f69905f516020615f645f395f51905f526128d7565b6080830152600101612e89565b505f612f8783610779610100612b87565b9050612f978260200151826128d7565b602083015260a0820151612fb2905f5b6020020151826128d7565b604083015260a0820151612fde90612fcd6001610100615c0e565b6101008110612fa757612fa7615c5b565b60608301526040820151612ff4908a6002610a27565b60c083018190526130409061077e6130198b5f516020615f645f395f51905f52612909565b61077961302f8e600160200201518f6002610aa9565b8e51602089015161079c91906128d7565b60c083018190526060830151613075916130699161077e906107798e600260200201518c612909565b61079c858c6003610a27565b60c08301819052159998505050505050505050565b61309261599f565b5f60036130a1601c6029615c21565b6130ab9190615c21565b6130b6906003615c21565b90506001604051855151604082015285516020015160608201528451608082015260408160606040840160075afa8216915060015b838110156131445760208102870160208202870181515160408501528151602001516060850152805160808501525050604080830160606040850160075afa8316925060408260808460065afa909216916001016130eb565b50805184526020810151602085015250505092915050565b61316461599f565b5f516020615f445f395f51905f5282602001515f516020615f445f395f51905f5261318f9190615c0e565b6131999190615e35565b60208301525090565b81516020808401518351848301516040805194850195909552938301919091527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260608301527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60808301527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60a08301527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60c083015260e08201526101008101919091527f260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c16101208201527f0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b06101408201527f04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe46101608201527f22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e556101808201525f9081906101a00160405160208183030381529060405290505f5f60086001600160a01b0316836040516133389190615e5d565b5f60405180830381855afa9150503d805f8114613370576040519150601f19603f3d011682016040523d82523d5f602084013e613375565b606091505b5091509150818015612a9e575080806020019051810190612a9e9190615e73565b5f808080806133a6876003615c21565b6133b190600c615c21565b6001600160401b038111156133c8576133c8615e92565b6040519080825280602002602001820160405280156133f1578160200160208202803683370190505b509050875f1b815f8151811061340957613409615c5b565b602002602001018181525050865f1b8160018151811061342b5761342b615c5b565b602002602001018181525050855f1b8160028151811061344d5761344d615c5b565b60209081029190910101525f5b613465601089615c0e565b8110156134b6578a8a8281811061347e5761347e615c5b565b90506020020135828260036134939190615c21565b815181106134a3576134a3615c5b565b602090810291909101015260010161345a565b505f5b6010811015613527578b516134e19082601081106134d9576134d9615c5b565b602002015190565b828260106134f08c6003615c21565b6134fa9190615c0e565b6135049190615c21565b8151811061351457613514615c5b565b60209081029190910101526001016134b9565b5060208b0151518161353a896003615c21565b8151811061354a5761354a615c5b565b6020908102919091018101919091528b81015101518161356b896003615c21565b613576906001615c21565b8151811061358657613586615c5b565b6020908102919091018101919091528b015160400151816135a8896003615c21565b6135b3906002615c21565b815181106135c3576135c3615c5b565b6020908102919091018101919091528b015160600151816135e5896003615c21565b6135f0906003615c21565b8151811061360057613600615c5b565b602090810291909101015260408b0151518161361d896003615c21565b613628906004615c21565b8151811061363857613638615c5b565b60209081029190910181019190915260408c015101518161365a896003615c21565b613665906005615c21565b8151811061367557613675615c5b565b60209081029190910101526040808c0151015181613694896003615c21565b61369f906006615c21565b815181106136af576136af615c5b565b602090810291909101015260408b015160600151816136cf896003615c21565b6136da906007615c21565b815181106136ea576136ea615c5b565b602090810291909101015260608b01515181613707896003615c21565b613712906008615c21565b8151811061372257613722615c5b565b60209081029190910181019190915260608c0151015181613744896003615c21565b61374f906009615c21565b8151811061375f5761375f615c5b565b602090810291909101015260608b0151604001518161377f896003615c21565b61378a90600a615c21565b8151811061379a5761379a615c5b565b60209081029190910101526060808c01510151816137b9896003615c21565b6137c490600b615c21565b815181106137d4576137d4615c5b565b6020026020010181815250506137f481604051602001611fef9190615ea6565b91506137ff82613907565b604080516020810186905292975090955061381a9101611fef565b915061382582613907565b5080935050509650965096509692505050565b5f5f5f6138436159fb565b85815260a085810180515160208085019190915281518101516040808601919091528251810151606080870191909152925183015160808087019190915260c0808b0180515196880196909652855184015190870152845182015160e0870152935183015161010086015292880180515161012086015280518201516101408601528051840151610160860152519091015161018084015290516138ed91611fef91849101615edb565b91506138f882613907565b90979096509194509092505050565b5f80826001600160801b038116608082901c613922826128b9565b945061392d816128b9565b9350505050915091565b5f613943846007615463565b90507f183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f80000005f6139a461399e613978856003612909565b6107796139936139888b5f615463565b6107798c601d615463565b6107798b601c615463565b836128d7565b9050613a25613a1a613a016139e86139cf8561077e6139c48d6002615463565b6107798e601c615463565b61077e6139dd8c6003615463565b6107798d601d615463565b61077e6139f68b6004615463565b6107798c601e615463565b61077e613a0f8a6005615463565b6107798b601f615463565b61077e886001615463565b9050613a448161077e613a39866001612909565b6107798a6027615463565b9050613a5081846128d7565b9050613a5c81856128d7565b8552505f9050613a96613a8c613a81613a7688601c615463565b61077e89601f615463565b61079c886024615463565b61077e875f615463565b9050613aa781610779846002612909565b9050613ab881610779846001612909565b9050613ac481836128d7565b9050613ad081846128d7565b9050808460015b60200201525050505050565b5f5f5f613b19613b0f613af789601c615463565b61077e613b058b6012615463565b8a606001516128d7565b87608001516128f0565b9050613b5281610779613b48613b308b601d615463565b61077e613b3e8d6013615463565b8c606001516128d7565b89608001516128f0565b9050613b7781610779613b48613b698b601e615463565b61077e613b3e8d6014615463565b9050613b9c81610779613b48613b8e8b601f615463565b61077e613b3e8d6015615463565b92505f9050613bc0613b0f613bb289601c615463565b61077e613b058b600e615463565b9050613be581610779613b48613bd78b601d615463565b61077e613b3e8d600f615463565b9050613c0a81610779613b48613bfc8b601e615463565b61077e613b3e8d6010615463565b9050613c2f81610779613b48613c218b601f615463565b61077e613b3e8d6011615463565b91505f9050613c56613c50613c45896020615463565b61077e8a601a615463565b846128d7565b9050613c8b8161079c613c85613c6d8b6028615463565b61077e613c7b8d601b615463565b8c60a001516128d7565b856128d7565b9050613c9781856128d7565b6040860152505f613cba613c85613caf89601b615463565b6107798a6028615463565b9050808560035b602002015250505050505050565b5f5f613d2d613d15613cfd613ce8613b488a6016615463565b61077e613cf68b6017615463565b8a516128d7565b61077e613d0b8a6018615463565b89602001516128d7565b61077e613d23896019615463565b88604001516128d7565b91505f613d64613d4b613d4189601c615463565b88608001516128f0565b61077e613d598a6003615463565b6107798b6024615463565b90505f613d8d613d7589601d615463565b61077e613d828b5f615463565b6107798c6025615463565b90505f613db7613d9e8a601e615463565b61077e613dac8c6001615463565b6107798d6026615463565b9050613df6613dde613dd08561077e868d5f01516128d7565b61077e848c602001516128d7565b61077e613dec8c6004615463565b8b604001516128d7565b93505050505f613e0a613c50886021615463565b90505f613e1b613c50896021615463565b90505f613e53613e3a613e2f8b6023615463565b61077e8c6006615463565b61079c613e488c6023615463565b6107798d6006615463565b90505f613e71612d80613e6687896128d7565b6107798d6021615463565b9050613e7d81886128d7565b90505f613ea5613e97613e918d6006615463565b876128d7565b61079c613e918e6022615463565b90505f613eb38c6023615463565b90505f613ec3612d8083846128d7565b60808c0185905260a08c018490529050613edd818b6128d7565b8b6006602002015250505050505050505050505050565b5f613f005f6001612909565b90505f613f0e5f6002612909565b90505f613f1c5f6003612909565b90505f613f38613f2d88601d615463565b61079c89601c615463565b90505f613f54613f4989601e615463565b61079c8a601d615463565b90505f613f70613f658a601f615463565b61079c8b601e615463565b90505f613f8c613f818b6024615463565b61079c8c601f615463565b905083613f9d81610779818b6128f0565b9050613fad81610779878a6128f0565b9050613fbd8161077987896128f0565b9050613fce816107798d6008615463565b9050613fda818a6128d7565b60e08b01525082613fef81610779818b6128f0565b9050613fff81610779868a6128f0565b905061400f8161077986896128f0565b9050614020816107798d6008615463565b905061402c818a6128d7565b6101008b0152508161404281610779818b6128f0565b905061405281610779858a6128f0565b90506140628161077985896128f0565b9050614073816107798d6008615463565b905061407f818a6128d7565b6101208b0152508061409581610779818b6128f0565b90506140a581610779848a6128f0565b90506140b58161077984896128f0565b90506140c6816107798d6008615463565b90506140d2818a6128d7565b610140909a019990995250505050505050505050565b6141216040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61412c84601d615463565b815261413984601e615463565b6020820152614149846024615463565b6040820152614159846027615463565b6060820152614169846026615463565b6080820152614179846025615463565b60a08201525f61418a856002615463565b90505f614197865f615463565b90505f6141ab8460400151855f0151612909565b90505f6141c0856020015186602001516128d7565b606086015190915086905f906141d690806128d7565b90505f6141f46141ee89602001518a606001516128d7565b886128d7565b90505f61421361420c8a60a001518b604001516128f0565b8a516128f0565b9050614222613e9182886128d7565b905061424961424361423d6142378487612909565b88612909565b846128f0565b836128f0565b905061427161426661425b83876128d7565b6107798f6009615463565b61077960018a612909565b6101608c015250505050602085015160808601515f91614290916128f0565b90505f6142ae6142a48860600151886128d7565b8860200151612909565b90505f6142d26142be84876128d7565b61077e613c858b60a001518c5f0151612909565b90506142fa6142ef6142e4838c6128d7565b6107798e6009615463565b610779600189612909565b6101808b0152505f915061431b90506143148360116128f0565b87516128d7565b90505f61432883846128f0565b905061433481826128f0565b90505f6143428360096128d7565b905061436b614365613c5061435e8b60a001518c5f01516128f0565b8b516128f0565b82612909565b60c089018190525f90614386906141ee9061425b908d6128d7565b90506143998b600b6020020151826128f0565b6101608c0152505086515f92506143c09150614314906143b990806128f0565b88516128f0565b90505f6144006143db836107798a5f01518b60a00151612909565b602089015161079c906143ee90806128f0565b6107798b602001518c608001516128f0565b905061441d89600c602002015161077e6141ee61425b858d6128d7565b89600c602002015250505050505050505050565b61449b604051806101e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6144b36144a986601e615463565b85604001516128d7565b8082526144d29061077e6144c888601d615463565b87602001516128d7565b8082526144e79061077e61431488601c615463565b8082526144f99061077e876001615463565b808252602082018190526145129061079c87601f615463565b815261452d614522866024615463565b61079c87601c615463565b608082015261454b614540866027615463565b61079c87601f615463565b6060820152608081015161456d9061456390806128d7565b8260800151612909565b6101c082015260808101516145ad906145a39061459c9061077960015f516020615f845f395f51905f52615c0e565b60016128f0565b82606001516128d7565b60a082018190526145e3906145d5906107796145ca896002615463565b6107798a6003615463565b610779613c8588600a615463565b83600e60200201526101c0810151614607906145d5906107796145ca896002615463565b6101e0840152805161462c90610779614621886002615463565b610779896003615463565b6101208201525f61464b61464187601f615463565b8360200151612909565b905061465a61436582836128d7565b60e083015261467761466d876026615463565b86604001516128d7565b6040830181905261469a9061077e614690896025615463565b88602001516128d7565b604083018190526146ba9061077e6146b3896024615463565b88516128d7565b60408301526146d76146cd876027615463565b8360400151612909565b60408301525f6146f66146eb886026615463565b61079c89601e615463565b905061474861472361399e61459c866080015160015f516020615f845f395f51905f526107799190615c0e565b61077961459c866040015160015f516020615f845f395f51905f526107799190615c0e565b60c0840152604083015161476a9061476090806128d7565b8460400151612909565b61010084015260c083015161479690614788906107798a6007615463565b610779613e918a600a615463565b6102008601526101c08301516147b590614788906107798a6007615463565b6102208601526101008301516147d490614788906107798a6007615463565b61024086015260e08301516147ee90610779896007615463565b61014084015261480d614802886025615463565b61079c89601d615463565b610160840152608083015161484b906146eb906148409061459c9061077960015f516020615f845f395f51905f52615c0e565b8561016001516128d7565b61018084018190526101208401516101a085018190526148829161077e906107796148778c6005615463565b6107798d6002615463565b6101a0840181905283516148a2919061077e906107796148778c5f615463565b6101a084018190526101408401516148ba91906128f0565b6101a084018190526148d490610779613e918a600a615463565b6101a0840181905285600d613cc1565b61491d6040518060e001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b61495261493961492e87601c615463565b610779886025615463565b61077e614947886024615463565b61077989601d615463565b815261499761498c61497361496888601c615463565b61077989601f615463565b61077e61498189601d615463565b6107798a601e615463565b61079c876026615463565b604082018190526149ac90600160441b6128d7565b604082018190526149c29061079c876027615463565b6040820181905281516149d591906128f0565b604082018190526149eb90610779876005615463565b60408201528051614a0090600160441b6128d7565b808252614a209061077e614a15886024615463565b610779896025615463565b80825260208201819052614a3c9061079c613a7688601e615463565b60208201819052614a5290610779876004615463565b6020820152805160608201819052614a6f9061077e87601f615463565b60608201819052614a939061079c614a88886026615463565b61077e896027615463565b60608201819052614aa890610779875f615463565b8160600181815250505f614ad1614ac7836020015184604001516128f0565b83606001516128f0565b9050614ae281610779886003615463565b9050614afa614af2876025615463565b6140006128d7565b60808301819052614b109061077e886024615463565b60808301819052614b23906140006128d7565b60808301819052614b399061077e88601e615463565b60808301819052614b4c906140006128d7565b60808301819052614b629061077e88601d615463565b60808301819052614b75906140006128d7565b60808301819052614b8b9061077e88601c615463565b60808301819052614ba19061079c88601f615463565b60808301819052614bb790610779886005615463565b6080830152614bca614af2876026615463565b60a08301819052614be09061077e886025615463565b60a08301819052614bf3906140006128d7565b60a08301819052614c099061077e886024615463565b60a08301819052614c1c906140006128d7565b60a08301819052614c329061077e88601f615463565b60a08301819052614c45906140006128d7565b60a08301819052614c5b9061077e88601e615463565b60a08301819052614c719061079c886027615463565b60a08301819052614c8690610779885f615463565b60a0830181905260808301515f91614c9e91906128f0565b9050614caf81610779896004615463565b9050614cbb82826128f0565b60c08401819052614cd490610779613e918a600b615463565b60c08401819052856013613cc1565b614d596040518061022001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b614d72614d6785601c615463565b61077e866002615463565b8152614d8d614d8285601d615463565b61077e866003615463565b6020820152614dab614da085601e615463565b61077e866004615463565b6040820152614dc9614dbe85601f615463565b61077e866005615463565b60608201528051614dfb90614df490614ded90614de690806128d7565b84516128d7565b83516128d7565b82516128d7565b60808201526020810151614e3990614e2f90614e2590614e1b90806128d7565b84602001516128d7565b83602001516128d7565b82602001516128d7565b60a08201526040810151614e7790614e6d90614e6390614e5990806128d7565b84604001516128d7565b83604001516128d7565b82604001516128d7565b60c08201526060810151614eab906145a390614ea190614e9790806128d7565b84606001516128d7565b83606001516128d7565b60e0820152608081015160a0820151614ec491906128f0565b61010082015260c081015160e0820151614ede91906128f0565b61012082015260a0810151614f0290614ef790806128f0565b8261012001516128f0565b61014082015260e0810151614f2690614f1b90806128f0565b8261010001516128f0565b610160820152610120810151614f3c90806128f0565b6101e08201819052614f5d90614f5290806128f0565b8261016001516128f0565b6101e0820152610100810151614f7390806128f0565b6101a08201819052614f9490614f8990806128f0565b8261014001516128f0565b6101a08201819052610160820151614fab916128f0565b6101808201526101408101516101e0820151614fc791906128f0565b6101c0820152614fdb61399e85600c615463565b61020082018190526102808401516101808301516150069261077e916107799061079c8a6024615463565b8360146020020152615036836015602002015161077e836102000151610779856101a0015161079c8a6025615463565b8360156020020152615066836016602002015161077e836102000151610779856101c0015161079c8a6026615463565b8360166020020152615096836017602002015161077e836102000151610779856101e0015161079c8a6027615463565b836017602002015250505050565b6150f66040518061016001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f604051806080016040528061512b7f10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e76128b9565b81526020016151597f0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b6128b9565b81526020016151867e544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac156128b9565b81526020016151b47f222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b6128b9565b905290506151d16151c686601c615463565b61077e876002615463565b610120830181905261521090615205906151fa906151ef90806128d7565b8561012001516128d7565b8461012001516128d7565b8361012001516128d7565b825261521d85601d615463565b602083015261522d85601e615463565b604083015261523d85601f615463565b60608301528151602083015161526591614ac79161525b91906128f0565b84604001516128f0565b6080830152615278613c5086600d615463565b61014083015281516152999061528f90835f610a27565b83608001516128f0565b60a08301526152c5846018602002015161077e8461014001516107798660a0015161079c8b6024615463565b61030085015260208201516152e09061528f90836001610a27565b60c083015261530c846019602002015161077e8461014001516107798660c0015161079c8b6025615463565b61032085015260408201516153279061528f90836002610a27565b60e083015261535384601a602002015161077e8461014001516107798660e0015161079c8b6026615463565b610340850152606082015161536e9061528f90836003610a27565b61010083015261539c84601b602002015161077e84610140015161077986610100015161079c8b6027615463565b84601b613ad7565b5f6153b081848161092c565b905060015b601c811015615402576153f88261077e8684601c81106153d7576153d7615c5b565b6020020151866153e8600187615c0e565b601b8110610a2757610a27615c5b565b91506001016153b5565b5092915050565b5f5f8390505f60405160208152602080820152602060408201528260608201528460808201525f516020615f845f395f51905f5260a082015260205f60c08360055afa905080615457575f5ffd5b50505f51949350505050565b5f8282602881111561547757615477615f0f565b6029811061548757615487615c5b565b60200201519392505050565b604051806103e001604052805f81526020015f81526020015f81526020016154b961599f565b81526020016154c661599f565b81526020016154d361599f565b81526020016154e061599f565b81526020016154ed61599f565b81526020016154fa61599f565b815260200161550761599f565b815260200161551461599f565b815260200161552161599f565b815260200161552e61599f565b815260200161553b61599f565b815260200161554861599f565b815260200161555561599f565b815260200161556261599f565b815260200161556f61599f565b815260200161557c61599f565b815260200161558961599f565b815260200161559661599f565b81526020016155a361599f565b81526020016155b061599f565b81526020016155bd61599f565b81526020016155ca61599f565b81526020016155d761599f565b81526020016155e461599f565b81526020016155f161599f565b81526020016155fe61599f565b815260200161560b61599f565b815260200161561861599f565b905290565b604051806102a00160405280615631615a1a565b815260200161563e615836565b815260200161564b615836565b8152602001615658615836565b8152602001615665615836565b8152602001615672615836565b815260200161567f615836565b815260200161568c615836565b8152602001615699615836565b81526020016156a6615a39565b81526020015f81526020016156b9615a66565b81526020016156c6615a94565b81526020015f81526020016156d9615836565b81526020015f81526020016156ec615ab3565b81526020016156f96158c8565b8152602001615706615ae1565b8152602001615713615836565b8152602001615618615836565b60405180610140016040528061573461585a565b815260200161574161588a565b815260200161574e6158c8565b81526020015f81526020016157616158c8565b81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b6040518061018001604052805f81526020015f81526020015f81526020015f81526020015f81526020016157b7615ae1565b81526020016157c4615ae1565b81526020015f81526020015f81526020015f81526020015f81526020016156186158c8565b604051806109600160405280604b906020820280368337509192915050565b604051806109600160405280604b905b61582061599f565b8152602001906001900390816158185790505090565b60405180608001604052805f81526020015f81526020015f81526020015f81525090565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b604051806103600160405280601b906020820280368337509192915050565b6040518061012001604052806009906020820280368337509192915050565b604051806103800160405280601c906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b604051806101400160405280600a906020820280368337509192915050565b6040518061070001604052806038906020820280368337509192915050565b60405180610da00160405280606d906020820280368337509192915050565b6040518061042001604052806021906020820280368337509192915050565b6040518060a001604052806005906020820280368337509192915050565b60405180604001604052805f81526020015f81525090565b6040518060e001604052806159ca615aff565b81526020015f81526020015f81526020015f81526020015f81526020016159ef615aff565b81526020015f81525090565b604051806101a00160405280600d906020820280368337509192915050565b6040518061020001604052806010906020820280368337509192915050565b60405180606001604052806003905b615a50615836565b815260200190600190039081615a485790505090565b604051806103800160405280601c905b615a7e6158a9565b815260200190600190039081615a765790505090565b6040518061052001604052806029906020820280368337509192915050565b604051806103600160405280601b905b615acb615836565b815260200190600190039081615ac35790505090565b60405180608001604052806004906020820280368337509192915050565b604051806120000160405280610100906020820280368337509192915050565b5f5f5f5f60408587031215615b32575f5ffd5b84356001600160401b03811115615b47575f5ffd5b8501601f81018713615b57575f5ffd5b80356001600160401b03811115615b6c575f5ffd5b876020828401011115615b7d575f5ffd5b6020918201955093508501356001600160401b03811115615b9c575f5ffd5b8501601f81018713615bac575f5ffd5b80356001600160401b03811115615bc1575f5ffd5b8760208260051b8401011115615bd5575f5ffd5b949793965060200194505050565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176128d1576128d1615be3565b818103818111156128d1576128d1615be3565b808201808211156128d1576128d1615be3565b5f5f85851115615c42575f5ffd5b83861115615c4e575f5ffd5b5050820193919092039150565b634e487b7160e01b5f52603260045260245ffd5b5f60018201615c8057615c80615be3565b5060010190565b803560208310156128d1575f19602084900360031b1b1692915050565b5f8183825b6009811015615cc8578151835260209283019290910190600101615ca9565b5050506101208201905092915050565b634e487b7160e01b5f52601260045260245ffd5b5f82615cfa57615cfa615cd8565b500490565b5f8183825b6006811015615d23578151835260209283019290910190600101615d04565b50505060c08201905092915050565b5f8183825b600a811015615d56578151835260209283019290910190600101615d37565b5050506101408201905092915050565b5f8183825b6038811015615d8a578151835260209283019290910190600101615d6b565b5050506107008201905092915050565b5f8183825b606d811015615dbe578151835260209283019290910190600101615d9f565b505050610da08201905092915050565b5f8183825b6021811015615df2578151835260209283019290910190600101615dd3565b5050506104208201905092915050565b5f8183825b6005811015615e26578151835260209283019290910190600101615e07565b50505060a08201905092915050565b5f82615e4357615e43615cd8565b500690565b5f81615e5657615e56615be3565b505f190190565b5f82518060208501845e5f920191825250919050565b5f60208284031215615e83575f5ffd5b81518015158114611e6f575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b81515f90829060208501835b82811015615ed0578151845260209384019390910190600101615eb2565b509195945050505050565b5f8183825b600d811015615eff578151835260209283019290910190600101615ee0565b5050506101a08201905092915050565b634e487b7160e01b5f52602160045260245ffdfe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd3130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000130644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51a2646970667358221220b55c5c3b9620ab90277336f91398d16f2f475f215304247f1c817d75b3fc2c9464736f6c634300081d0033 diff --git a/eth/contracts/rollup/Proxy.sol b/eth/contracts/rollup/Proxy.sol deleted file mode 100644 index e63f0b0..0000000 --- a/eth/contracts/rollup/Proxy.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; diff --git a/eth/contracts/rollup/README.md b/eth/contracts/rollup/README.md deleted file mode 100644 index dd3fb83..0000000 --- a/eth/contracts/rollup/README.md +++ /dev/null @@ -1,34 +0,0 @@ -## Upgrades - -The rollup contract uses a proxy pattern to allow for upgrades. -If you want to make a change to the rollup contract, you need to create a new version of the contract that inherits from the old one. -The storage layout of the new contract must be backwards compatible with the old one, meaning you should not change the variables or their order in previous versions of the contract. -Overriding old functions in a new version of the contract is fine, but keep in mind that if you change the parameter types, you will create a new function and the old one will still be callable. - -Example: - -```solidity -import "./RollupV1.sol"; - -// The order of the inherited contracts is important to ensure the storage layout is unchanged. -contract RollupV2 is RollupV1, AnyOtherContracts { - uint256 public newVariable; - - function initializeV2() public reinitializer(2) { - version = 2; - newVariable = 1; - } - - function newFunction() public {} -} -``` - -The `initializeV2` function would need to be called by the proxy contract to perform the upgrade. - -Add the new version of the contract to both `deploy.ts` and `upgrade.ts`. - -### Rollup USDC Balance - -Because the proxy uses `delegateCall`, the contract's USDC balance persists across upgrades, since in calls to USDC, the `msg.sender` and `this` is the proxy contract, not the implementer rollup contract. - -Proxy (msg.sender) (->) RollupV1 (still Proxy msg.sender) -> USDC diff --git a/eth/contracts/rollup/RollupV1.sol b/eth/contracts/rollup/RollupV1.sol deleted file mode 100644 index 4097e12..0000000 --- a/eth/contracts/rollup/RollupV1.sol +++ /dev/null @@ -1,486 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import "../AggregateVerifierV1.sol"; -import "../MintVerifierV1.sol"; -import "../BurnVerifierV1.sol"; -import "../IUSDC.sol"; -// import "hardhat/console.sol"; - -struct Block { - // Sequencer/prover sending the block - address sender; - // List of txns in the block - Transaction[] txns; -} - -struct Transaction { - bytes[] hashes; -} - -struct Proof { - bytes[] proof; -} - -struct Signature { - bytes32 r; - bytes32 s; - uint v; -} - -struct Mint { - uint256 amount; -} - -struct Burn { - address to; - uint256 amount; -} - -struct ValidatorSet { - mapping(address => bool) validators; - address[] validatorsArray; - // The height at which this validator set becomes valid, inclusive - uint256 validFrom; -} - -struct PublicValidatorSet { - // We can't return a mapping from a public function, so we need an array - address[] validators; - uint256 validFrom; -} - -string constant NETWORK = "Polybase"; -uint64 constant NETWORK_LEN = 8; - -contract RollupV1 is Initializable, OwnableUpgradeable { - event ValidatorSetAdded(uint256 index, uint256 validFrom); - - // Since the Initializable._initialized version number is private, we need to keep track of it ourselves - uint8 public version; - - bytes32 private _DOMAIN_SEPARATOR; - - AggregateVerifierV1 public aggregateVerifier; - MintVerifierV1 public mintVerifier; - BurnVerifierV1 public burnVerifier; - IUSDC public usdc; - - // Core rollup values - bytes32 public blockHash; - uint256 public blockHeight; - - bytes32[64] public rootHashes; - uint public nextRootHashIndex; - - // Actors - // mapping(address => uint) sequencers; - mapping(address => uint) provers; - mapping(bytes32 => uint256) mints; - mapping(bytes32 => Burn) burns; - - mapping(uint256 => ValidatorSet) private validatorSets; - uint256 private validatorSetsLength; - uint256 private validatorSetIndex; - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - _disableInitializers(); - } - - function initialize( - address owner, - address _usdcAddress, - address _aggregateVerifier, - address _mintVerifier, - address _burnVerifier, - address prover, - address[] calldata initialValidators, - bytes32 emptyMerkleTreeRootHash - ) public initializer { - version = 1; - - __Ownable_init(owner); - - _DOMAIN_SEPARATOR = keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes("Rollup")), - keccak256(bytes("1")), - block.chainid, - address(this) - ) - ); - - usdc = IUSDC(_usdcAddress); - aggregateVerifier = AggregateVerifierV1(_aggregateVerifier); - mintVerifier = MintVerifierV1(_mintVerifier); - burnVerifier = BurnVerifierV1(_burnVerifier); - provers[prover] = 1; - - _setValidators(0, initialValidators); - - addRootHash(emptyMerkleTreeRootHash); - } - - modifier onlyProver() { - require(provers[msg.sender] == 1, "You are not a prover"); - _; - } - - function addRootHash(bytes32 rootHash) internal { - rootHashes[nextRootHashIndex] = rootHash; - nextRootHashIndex = (nextRootHashIndex + 1) % 64; - } - - function currentRootHash() public view returns (bytes32) { - uint index = 63; - if (nextRootHashIndex > 0) { - index = nextRootHashIndex - 1; - } - - return rootHashes[index]; - } - - function containsRootHashes( - bytes32[6] memory hashes - ) public view virtual returns (bool) { - bool[6] memory results = [false, false, false, false, false, false]; - - for (uint i = 0; i < hashes.length; i++) { - for (uint j = 0; j < rootHashes.length; j++) { - if (hashes[i] == rootHashes[j]) { - results[i] = true; - break; - } - } - } - - for (uint i = 0; i < results.length; i++) { - if (results[i] == false) { - return false; - } - } - - return true; - } - - function getMint(bytes32 key) public view returns (uint256) { - return mints[key]; - } - - function getBurn(bytes32 key) public view returns (Burn memory) { - return burns[key]; - } - - function getRootHashes() public view returns (bytes32[64] memory) { - return rootHashes; - } - - function addProver(address prover) public onlyOwner { - provers[prover] = 1; - } - - // Returns all validator sets from a given index, inclusive - function getValidatorSets( - uint256 from - ) public view returns (PublicValidatorSet[] memory) { - PublicValidatorSet[] memory sets = new PublicValidatorSet[]( - validatorSetsLength - from - ); - - for (uint256 i = from; i < validatorSetsLength; i++) { - sets[i - from] = PublicValidatorSet( - validatorSets[i].validatorsArray, - validatorSets[i].validFrom - ); - } - - return sets; - } - - function getValidators() internal view returns (ValidatorSet storage) { - return validatorSets[validatorSetIndex]; - } - - function _setValidators( - uint256 validFrom, - address[] calldata validators - ) private { - require( - validatorSetsLength == 0 || - validatorSets[validatorSetsLength - 1].validFrom < validFrom, - "New validator set must have a validFrom greater than the last set" - ); - - validatorSets[validatorSetsLength].validFrom = validFrom; - validatorSets[validatorSetsLength].validatorsArray = validators; - - for (uint256 i = 0; i < validators.length; i++) { - require( - validatorSets[validatorSetsLength].validators[validators[i]] == - false, - "Validator already exists" - ); - - validatorSets[validatorSetsLength].validators[validators[i]] = true; - } - - emit ValidatorSetAdded(validatorSetsLength, validFrom); - validatorSetsLength += 1; - } - - function setValidators( - uint256 validFrom, - address[] calldata validators - ) public onlyOwner { - _setValidators(validFrom, validators); - } - - function updateValidatorSetIndex(uint256 height) internal { - for (uint256 i = validatorSetIndex + 1; i < validatorSetsLength; i++) { - if (validatorSets[i].validFrom > height) { - break; - } - - validatorSetIndex = i; - } - } - - // Verify a new block - function verifyBlock( - // Transaction[] calldata txns, - bytes calldata aggrProof, - bytes32[12] calldata aggrInstances, - bytes32 oldRoot, - bytes32 newRoot, - // 6 utxo x 3 hashes per utxo - bytes32[18] calldata utxoHashes, - bytes32 otherHashFromBlockHash, - uint256 height, - // uint64 skips, - Signature[] calldata signatures - ) public virtual onlyProver { - updateValidatorSetIndex(height); - ValidatorSet storage validatorSet = getValidators(); - - require( - oldRoot == currentRootHash(), - "Old root does not match the current root" - ); - - // Check mints/burns - for (uint i = 0; i < 18; i += 3) { - bytes32 mb = utxoHashes[i + 1]; - bytes32 value = utxoHashes[i + 2]; - - if (value == 0) { - continue; - } - - if (mints[mb] != 0) { - require(mints[mb] == uint256(value), "Invalid mint amount"); - delete mints[mb]; - continue; - } - - if (burns[mb].amount != 0) { - require( - burns[mb].amount == uint256(value), - "Invalid burn amount" - ); - - // Perform the transfer to the requested account - require( - usdc.transfer(burns[mb].to, burns[mb].amount), - "Transfer failed" - ); - - delete burns[mb]; - continue; - } - - revert("Invalid mint/burn"); - } - - // Check recent roots - require( - containsRootHashes( - [ - utxoHashes[0], - utxoHashes[3], - utxoHashes[6], - utxoHashes[9], - utxoHashes[12], - utxoHashes[15] - ] - ), - "Invalid recent roots" - ); - - uint minValidators = (validatorSet.validatorsArray.length * 2) / 3 + 1; - require( - signatures.length >= minValidators, - "Not enough signatures from validators to verify block" - ); - - bytes32 proposalHash = keccak256( - abi.encode(newRoot, height, otherHashFromBlockHash) - ); - bytes32 acceptMsg = keccak256(abi.encode(height + 1, proposalHash)); - bytes32 sigMsg = keccak256( - abi.encodePacked(NETWORK_LEN, NETWORK, acceptMsg) - ); - - require(signatures.length > 0, "No signatures"); - address previous = address(0); - for (uint i = 0; i < signatures.length; i++) { - Signature calldata signature = signatures[i]; - address signer = ecrecover( - sigMsg, - uint8(signature.v), - signature.r, - signature.s - ); - require( - validatorSet.validators[signer] == true, - "Signer is not a validator" - ); - - require(signer > previous, "Signers are not sorted"); - previous = signer; - } - - aggregateVerifier.verify( - aggrProof, - aggrInstances, - oldRoot, - newRoot, - utxoHashes - ); - - addRootHash(newRoot); - blockHash = proposalHash; - - blockHeight = height; - } - - // Anyone can call mint, although this is likely to be performed on behalf of the user - // as they may not have gas to pay for the txn - function mint( - bytes calldata proof, - bytes32 commitment, - bytes32 value, - bytes32 source - ) public virtual { - if (mints[commitment] != 0) { - revert("Mint already exists"); - } - - mintVerifier.verify(proof, [commitment, value, source]); - - // Take the money from the external account, sender must have been previously - // approved as per the ERC20 standard - require( - usdc.transferFrom(msg.sender, address(this), uint256(value)), - "Transfer failed" - ); - - // Add mint to pending mints, this still needs to be verifier with the verifyBlock, - // but Solid validators will check that this commitment exists in the mint map before - // accepting the mint txn into a block - mints[commitment] = uint256(value); - } - - bytes32 constant MINT_WITH_AUTHORIZATION_TYPE_HASH = - keccak256( - "MintWithAuthorization(bytes32 commitment,bytes32 value,bytes32 source,address from,uint256 validAfter,uint256 validBefore,bytes32 nonce)" - ); - - function mintWithAuthorization( - bytes calldata proof, - bytes32 commitment, - bytes32 value, - bytes32 source, - address from, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint256 v, - bytes32 r, - bytes32 s, - // Second signature, not for receiveWithAuthorization, - // but for this mintWithAuthorization call - uint256 v2, - bytes32 r2, - bytes32 s2 - ) public virtual { - if (mints[commitment] != 0) { - revert("Mint already exists"); - } - - bytes32 structHash = keccak256( - abi.encode( - MINT_WITH_AUTHORIZATION_TYPE_HASH, - commitment, - value, - source, - from, - validAfter, - validBefore, - nonce - ) - ); - bytes32 computedHash = keccak256( - abi.encodePacked("\x19\x01", _DOMAIN_SEPARATOR, structHash) - ); - address signer = ecrecover(computedHash, uint8(v2), r2, s2); - require(signer == from, "Invalid signer"); - - mintVerifier.verify(proof, [commitment, value, source]); - - usdc.receiveWithAuthorization( - from, - address(this), - uint256(value), - validAfter, - validBefore, - nonce, - uint8(v), - r, - s - ); - - mints[commitment] = uint256(value); - } - - // Anyone can call burn, although this is likely to be performed on behalf of the user - // as they may not have gas to pay for the txn - function burn( - // to address is not verified, we don't care who they send it to - address to, - bytes calldata proof, - bytes32 nullifer, - bytes32 value, - bytes32 source, - bytes32 sig - ) public virtual { - burnVerifier.verify( - proof, - [bytes32(uint256(uint160(to))), nullifer, value, source, sig] - ); - - // Add burn to pending burns, this still needs to be verifier with the verifyBlock, - // but validators will check that this nullifier exists in the burn map before - // accepting the burn txn into a block - burns[nullifer] = Burn(to, uint256(value)); - } - - function setRoot(bytes32 newRoot) public onlyOwner { - addRootHash(newRoot); - } -} diff --git a/eth/contracts/rollup/RollupV2.sol b/eth/contracts/rollup/RollupV2.sol deleted file mode 100644 index 56b0d8d..0000000 --- a/eth/contracts/rollup/RollupV2.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import "./RollupV1.sol"; - -contract RollupV2 is RollupV1 { - function initializeV2() public reinitializer(2) { - version = 2; - } -} diff --git a/eth/contracts/rollup/RollupV3.sol b/eth/contracts/rollup/RollupV3.sol deleted file mode 100644 index 1ab979a..0000000 --- a/eth/contracts/rollup/RollupV3.sol +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import "./RollupV2.sol"; - -contract RollupV3 is RollupV2 { - function initializeV3() public reinitializer(3) { - version = 3; - } - - // Verify a new block - function verifyBlock( - // Transaction[] calldata txns, - bytes calldata aggrProof, - bytes32[12] calldata aggrInstances, - bytes32 oldRoot, - bytes32 newRoot, - // 6 utxo x 3 hashes per utxo - bytes32[18] calldata utxoHashes, - bytes32 otherHashFromBlockHash, - uint256 height, - // uint64 skips, - Signature[] calldata signatures - ) public virtual override onlyProver { - updateValidatorSetIndex(height); - ValidatorSet storage validatorSet = getValidators(); - - require( - oldRoot == currentRootHash(), - "Old root does not match the current root" - ); - - // Check mints/burns - for (uint i = 0; i < 18; i += 3) { - bytes32 mb = utxoHashes[i + 1]; - bytes32 value = utxoHashes[i + 2]; - - if (value == 0) { - continue; - } - - if (mints[mb] != 0) { - require(mints[mb] == uint256(value), "Invalid mint amount"); - delete mints[mb]; - continue; - } - - if (burns[mb].amount != 0) { - require( - burns[mb].amount == uint256(value), - "Invalid burn amount" - ); - - // You cannot transfer to the zero address, - // otherwise you get 'ERC20: transfer to the zero address' - if (burns[mb].to != address(0)) { - // Perform the transfer to the requested account - require( - usdc.transfer(burns[mb].to, burns[mb].amount), - "Transfer failed" - ); - } - - delete burns[mb]; - continue; - } - - revert("Invalid mint/burn"); - } - - // Check recent roots - require( - containsRootHashes( - [ - utxoHashes[0], - utxoHashes[3], - utxoHashes[6], - utxoHashes[9], - utxoHashes[12], - utxoHashes[15] - ] - ), - "Invalid recent roots" - ); - - uint minValidators = (validatorSet.validatorsArray.length * 2) / 3 + 1; - require( - signatures.length >= minValidators, - "Not enough signatures from validators to verify block" - ); - - bytes32 proposalHash = keccak256( - abi.encode(newRoot, height, otherHashFromBlockHash) - ); - bytes32 acceptMsg = keccak256(abi.encode(height + 1, proposalHash)); - bytes32 sigMsg = keccak256( - abi.encodePacked(NETWORK_LEN, NETWORK, acceptMsg) - ); - - require(signatures.length > 0, "No signatures"); - address previous = address(0); - for (uint i = 0; i < signatures.length; i++) { - Signature calldata signature = signatures[i]; - address signer = ecrecover( - sigMsg, - uint8(signature.v), - signature.r, - signature.s - ); - require( - validatorSet.validators[signer] == true, - "Signer is not a validator" - ); - - require(signer > previous, "Signers are not sorted"); - previous = signer; - } - - aggregateVerifier.verify( - aggrProof, - aggrInstances, - oldRoot, - newRoot, - utxoHashes - ); - - addRootHash(newRoot); - blockHash = proposalHash; - - blockHeight = height; - } -} diff --git a/eth/contracts/rollup/RollupV4.sol b/eth/contracts/rollup/RollupV4.sol deleted file mode 100644 index 8c8b636..0000000 --- a/eth/contracts/rollup/RollupV4.sol +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import "./RollupV3.sol"; - -contract RollupV4 is RollupV3 { - function initializeV4() public reinitializer(4) { - version = 4; - } - - function containsRootHashes( - bytes32[6] memory hashes - ) public view override returns (bool) { - bool[6] memory results = [false, false, false, false, false, false]; - - for (uint i = 0; i < hashes.length; i++) { - for (uint j = 0; j < rootHashes.length; j++) { - if (hashes[i] == rootHashes[j] || hashes[i] == 0) { - results[i] = true; - break; - } - } - } - - for (uint i = 0; i < results.length; i++) { - if (results[i] == false) { - return false; - } - } - - return true; - } -} diff --git a/eth/contracts/rollup/RollupV5.sol b/eth/contracts/rollup/RollupV5.sol deleted file mode 100644 index b5ac0ca..0000000 --- a/eth/contracts/rollup/RollupV5.sol +++ /dev/null @@ -1,455 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "./RollupV4.sol"; -import "../BurnVerifierV2.sol"; - -struct BurnToRouter { - address router; - bytes routerCalldata; - uint256 amount; - // if the router call fails, return the funds to this address - address returnAddress; -} - -contract RollupV5 is RollupV4 { - event BlockVerified(uint256 indexed height, bytes32 root); - event BurnedToAddress(address indexed to, uint256 value); - event BurnedToRouter(address indexed router, uint256 value); - event Minted(bytes32 indexed commitment, uint256 value); - - mapping(bytes32 => bytes32) burnsKind; - mapping(bytes32 => BurnToRouter) burnsToRouter; - mapping(address => bool) routerWhitelist; - - BurnVerifierV2 public burnVerifierV2; - - function initializeV5( - address _burnVerifierV2 - ) public reinitializer(5) { - version = 5; - burnVerifierV2 = BurnVerifierV2(_burnVerifierV2); - } - - function DOMAIN_SEPARATOR() public view returns (bytes32) { - return - keccak256( - abi.encode( - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" - ), - keccak256(bytes("Rollup")), - keccak256(bytes("1")), - block.chainid, - address(this) - ) - ); - } - - function isUSDCBlacklisted(address account) internal view returns (bool) { - return usdc.isBlacklisted(account); - } - - function requireNotUSDCBlacklisted(address account) internal view { - require(!isUSDCBlacklisted(account), "account is blacklisted by USDC"); - } - - function addRouter(address router) public onlyOwner { - require(router.code.length > 0, "Router has no code"); - routerWhitelist[router] = true; - } - - function removeRouter(address router) public onlyOwner { - routerWhitelist[router] = false; - } - - function isRouterWhitelisted(address router) public view returns (bool) { - return routerWhitelist[router]; - } - - function hasBurn(bytes32 nullifier) public view returns (bool) { - if (burnsKind[nullifier] == 0) { - return burns[nullifier].amount != 0; - } else { - // if burnsKind is not zero, then there exists a burn - return true; - } - } - - // Anyone can call mint, although this is likely to be performed on behalf of the user - // as they may not have gas to pay for the txn - function mint( - bytes calldata proof, - bytes32 commitment, - bytes32 value, - bytes32 source - ) public override virtual { - if (mints[commitment] != 0) { - revert("Mint already exists"); - } - - mintVerifier.verify(proof, [commitment, value, source]); - - // Take the money from the external account, sender must have been previously - // approved as per the ERC20 standard - require( - IERC20(usdc).transferFrom(msg.sender, address(this), uint256(value)), - "Transfer failed" - ); - - // Add mint to pending mints, this still needs to be verifier with the verifyBlock, - // but Solid validators will check that this commitment exists in the mint map before - // accepting the mint txn into a block - mints[commitment] = uint256(value); - } - - function mintWithAuthorization( - bytes calldata proof, - bytes32 commitment, - bytes32 value, - bytes32 source, - address from, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint256 v, - bytes32 r, - bytes32 s, - // Second signature, not for receiveWithAuthorization, - // but for this mintWithAuthorization call - uint256 v2, - bytes32 r2, - bytes32 s2 - ) public override virtual { - if (mints[commitment] != 0) { - revert("Mint already exists"); - } - - bytes32 structHash = keccak256( - abi.encode( - MINT_WITH_AUTHORIZATION_TYPE_HASH, - commitment, - value, - source, - from, - validAfter, - validBefore, - nonce - ) - ); - bytes32 computedHash = keccak256( - abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash) - ); - address signer = ECDSA.recover(computedHash, uint8(v2), r2, s2); - require(signer == from, "Invalid signer"); - - mintVerifier.verify(proof, [commitment, value, source]); - - IUSDC(usdc).receiveWithAuthorization( - from, - address(this), - uint256(value), - validAfter, - validBefore, - nonce, - uint8(v), - r, - s - ); - - mints[commitment] = uint256(value); - } - - // Anyone can call burn, although this is likely to be performed on behalf of the user - // as they may not have gas to pay for the txn - function burn( - // to address is not verified, we don't care who they send it to - address to, - bytes calldata proof, - bytes32 nullifer, - bytes32 value, - bytes32 source, - bytes32 sig - ) public override virtual { - requireNotUSDCBlacklisted(to); - - burnVerifier.verify( - proof, - [bytes32(uint256(uint160(to))), nullifer, value, source, sig] - ); - - // Add burn to pending burns, this still needs to be verifier with the verifyBlock, - // but validators will check that this nullifier exists in the burn map before - // accepting the burn txn into a block - burns[nullifer] = Burn(to, uint256(value)); - } - - function burnToAddress( - bytes32 kind, - bytes32 to, - bytes calldata proof, - bytes32 nullifier, - bytes32 value, - bytes32 source, - bytes32 sig - ) public virtual { - require(kind == bytes32(0), "Invalid kind"); - - address toAddr = bytes32ToAddress(to); - requireNotUSDCBlacklisted(toAddr); - - burnVerifierV2.verify(proof, [kind, to, nullifier, value, source, sig]); - - // Add burn to pending burns, burn will be processed when verifyBlock is called - burnsKind[nullifier] = kind; - burns[nullifier] = Burn(toAddr, uint256(value)); - } - - function burnToRouter( - bytes32 kind, - bytes32 msgHash, - bytes calldata proof, - bytes32 nullifier, - bytes32 value, - bytes32 source, - bytes32 sig, - address router, - // TODO: this could be big and use a lot of gas to set in storage, set a limit in guild - bytes calldata routerCalldata, - address returnAddress - ) public virtual { - require(kind == bytes32(uint256(1)), "Invalid kind"); - require(returnAddress != address(0), "Invalid return address"); - require(isRouterWhitelisted(router), "Router not whitelisted"); - - bytes32 computedMsg = keccak256(abi.encode(router, routerCalldata, returnAddress)); - // Clear the first 3 bits, BN256 can't fit the full 256 bits - computedMsg &= bytes32( - uint256( - 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ) - ); - require(computedMsg == msgHash, "Invalid msg"); - - burnVerifierV2.verify( - proof, - [kind, msgHash, nullifier, value, source, sig] - ); - - burnsKind[nullifier] = kind; - burnsToRouter[nullifier] = BurnToRouter( - router, - routerCalldata, - uint256(value), - returnAddress - ); - } - - // Verify a new block - function verifyBlock( - bytes calldata aggrProof, - bytes32[12] calldata aggrInstances, - bytes32 oldRoot, - bytes32 newRoot, - // 6 utxo x 3 hashes per utxo - bytes32[18] calldata utxoHashes, - bytes32 otherHashFromBlockHash, - uint256 height, - // uint64 skips, - Signature[] calldata signatures - ) public virtual override onlyProver { - verifyBlock2( - aggrProof, - aggrInstances, - oldRoot, - newRoot, - utxoHashes, - otherHashFromBlockHash, - height, - signatures, - 500_000 - ); - } - - // Verify a new block - // TODO: I added '2' at the end of this function name, - // because web3 Rust API takes the first verifyBlock function it finds, - // and it was taking the old one and failing to encode parameters - function verifyBlock2( - // Transaction[] calldata txns, - bytes calldata aggrProof, - bytes32[12] calldata aggrInstances, - bytes32 oldRoot, - bytes32 newRoot, - // 6 utxo x 3 hashes per utxo - bytes32[18] calldata utxoHashes, - bytes32 otherHashFromBlockHash, - uint256 height, - // uint64 skips, - Signature[] calldata signatures, - uint256 gasPerBurnCall - ) public onlyProver { - updateValidatorSetIndex(height); - ValidatorSet storage validatorSet = getValidators(); - - require( - oldRoot == currentRootHash(), - "Old root does not match the current root" - ); - - // Check mints/burns - for (uint i = 0; i < 18; i += 3) { - bytes32 mb = utxoHashes[i + 1]; - bytes32 value = utxoHashes[i + 2]; - - verifyTxn(mb, value, gasPerBurnCall); - } - - // Check recent roots - require( - containsRootHashes( - [ - utxoHashes[0], - utxoHashes[3], - utxoHashes[6], - utxoHashes[9], - utxoHashes[12], - utxoHashes[15] - ] - ), - "Invalid recent roots" - ); - - uint minValidators = (validatorSet.validatorsArray.length * 2) / 3 + 1; - require( - signatures.length >= minValidators, - "Not enough signatures from validators to verify block" - ); - - bytes32 proposalHash = keccak256( - abi.encode(newRoot, height, otherHashFromBlockHash) - ); - bytes32 acceptMsg = keccak256(abi.encode(height + 1, proposalHash)); - bytes32 sigMsg = keccak256( - abi.encodePacked(NETWORK_LEN, NETWORK, acceptMsg) - ); - - require(signatures.length > 0, "No signatures"); - address previous = address(0); - for (uint i = 0; i < signatures.length; i++) { - Signature calldata signature = signatures[i]; - address signer = ECDSA.recover( - sigMsg, - uint8(signature.v), - signature.r, - signature.s - ); - require( - validatorSet.validators[signer] == true, - "Signer is not a validator" - ); - - require(signer > previous, "Signers are not sorted"); - previous = signer; - } - - aggregateVerifier.verify( - aggrProof, - aggrInstances, - oldRoot, - newRoot, - utxoHashes - ); - - addRootHash(newRoot); - blockHash = proposalHash; - - blockHeight = height; - - emit BlockVerified(height, newRoot); - } - - function verifyTxn(bytes32 mb, bytes32 value, uint256 gasPerBurnCall) internal virtual { - if (value == 0) { - return; - } - - if (mints[mb] != 0) { - require(mints[mb] == uint256(value), "Invalid mint amount"); - emit Minted(mb, mints[mb]); - delete mints[mb]; - return; - } - - if (burnsKind[mb] == 0) { - // Regular burn to address or no burn at all - if (burns[mb].amount != 0) { - require( - burns[mb].amount == uint256(value), - "Invalid burn amount" - ); - - // You cannot transfer to the zero address, - // otherwise you get 'ERC20: transfer to the zero address' - if (burns[mb].to != address(0)) { - if (!isUSDCBlacklisted(burns[mb].to)) { - // Perform the transfer to the requested account - IERC20(usdc).transfer( - burns[mb].to, - burns[mb].amount - ); - } - } - - emit BurnedToAddress(burns[mb].to, burns[mb].amount); - delete burns[mb]; - return; - } else { - // Burn doesn't exist, do nothing - } - } else if (burnsKind[mb] == bytes32(uint256(1))) { - // Burn to router - BurnToRouter memory b = burnsToRouter[mb]; - require(b.amount == uint256(value), "Invalid burn amount"); - - IERC20(usdc).approve(b.router, b.amount); - if (!_routerCall(b.router, b.routerCalldata, gasPerBurnCall)) { - // Reset allowance to 0 - // TODO: if we reset to 1, we could save gas on future approves? - IERC20(usdc).approve(b.router, 0); - // Return the funds to the return address - IERC20(usdc).transfer(b.returnAddress, b.amount); - } - - emit BurnedToRouter(b.router, b.amount); - delete burnsKind[mb]; - return; - } - - // TODO: currently existance of burn must be checked by validators, because if a nullifier is - // is not present, the block production will stall here. Given its the users funds - // at risk, only the user should be responsible for this. In the case a nullifier is missing for - // a burn, we should just burn the funds and continue. To do this, we need to differentiate between - // mints and burns, as mints will still need to be checked. - revert("Invalid mint/burn"); - } - - function _routerCall(address router, bytes memory routerCalldata, uint256 gasPerBurnCall) internal returns (bool) { - if (!isRouterWhitelisted(router)) { - return false; - } - - (bool success, /*bytes memory data*/) = router.call{ - value: 0, - // TODO: how much gas should we allow - gas: gasPerBurnCall - }(routerCalldata); - - return success; - } - - function bytes32ToAddress(bytes32 _bytes32) public pure returns (address) { - return address(uint160(uint256(_bytes32))); - } -} diff --git a/eth/contracts/rollup/RollupV6.sol b/eth/contracts/rollup/RollupV6.sol deleted file mode 100644 index bdfd716..0000000 --- a/eth/contracts/rollup/RollupV6.sol +++ /dev/null @@ -1,344 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.20; - -import "./RollupV5.sol"; - -contract RollupV6 is RollupV5 { - event Burned(bytes32 indexed nullifier, bool substitute, bool success); - event BurnAdded(bytes32 indexed nullifier, uint256 amount); - event MintAdded(bytes32 indexed commitment, uint256 amount); - - mapping(bytes32 => bool) public substitutedBurns; - mapping(bytes32 => bool) public rolledUpLeafs; - - uint256 public gasPerRouterCall; - - function initializeV6() public reinitializer(6) { - version = 6; - - gasPerRouterCall = 500_000; - } - - function setGasPerRouterCall(uint256 _gasPerRouterCall) public onlyOwner { - gasPerRouterCall = _gasPerRouterCall; - } - - function setBurnsKind(bytes32 nullifier, bytes32 kind) internal { - require( - burnsKind[nullifier] == 0 && burns[nullifier].amount == 0, - "Burn already exists" - ); - burnsKind[nullifier] = kind; - } - - // Anyone can call mint, although this is likely to be performed on behalf of the user - // as they may not have gas to pay for the txn - function mint( - bytes calldata proof, - bytes32 commitment, - bytes32 value, - bytes32 source - ) public override { - if (mints[commitment] != 0) { - revert("Mint already exists"); - } - - mintVerifier.verify(proof, [commitment, value, source]); - - // Take the money from the external account, sender must have been previously - // approved as per the ERC20 standard - IERC20(usdc).transferFrom(msg.sender, address(this), uint256(value)); - - // Add mint to pending mints, this still needs to be verifier with the verifyBlock, - // but Solid validators will check that this commitment exists in the mint map before - // accepting the mint txn into a block - mints[commitment] = uint256(value); - emit MintAdded(commitment, uint256(value)); - } - - function mintWithAuthorization( - bytes calldata proof, - bytes32 commitment, - bytes32 value, - bytes32 source, - address from, - uint256 validAfter, - uint256 validBefore, - bytes32 nonce, - uint256 v, - bytes32 r, - bytes32 s, - // Second signature, not for receiveWithAuthorization, - // but for this mintWithAuthorization call - uint256 v2, - bytes32 r2, - bytes32 s2 - ) public override { - if (mints[commitment] != 0) { - revert("Mint already exists"); - } - - bytes32 structHash = keccak256( - abi.encode( - MINT_WITH_AUTHORIZATION_TYPE_HASH, - commitment, - value, - source, - from, - validAfter, - validBefore, - nonce - ) - ); - bytes32 computedHash = keccak256( - abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash) - ); - address signer = ECDSA.recover(computedHash, uint8(v2), r2, s2); - require(signer == from, "Invalid signer"); - - mintVerifier.verify(proof, [commitment, value, source]); - - IUSDC(usdc).receiveWithAuthorization( - from, - address(this), - uint256(value), - validAfter, - validBefore, - nonce, - uint8(v), - r, - s - ); - - mints[commitment] = uint256(value); - emit MintAdded(commitment, uint256(value)); - } - - // Anyone can call burn, although this is likely to be performed on behalf of the user - // as they may not have gas to pay for the txn - function burn( - // to address is not verified, we don't care who they send it to - address to, - bytes calldata proof, - bytes32 nullifer, - bytes32 value, - bytes32 source, - bytes32 sig - ) public override { - requireNotUSDCBlacklisted(to); - - burnVerifier.verify( - proof, - [bytes32(uint256(uint160(to))), nullifer, value, source, sig] - ); - - // Add burn to pending burns, this still needs to be verifier with the verifyBlock, - // but validators will check that this nullifier exists in the burn map before - // accepting the burn txn into a block - setBurnsKind(nullifer, 0); - burns[nullifer] = Burn(to, uint256(value)); - - emit BurnAdded(nullifer, uint256(value)); - } - - function burnToAddress( - bytes32 kind, - bytes32 to, - bytes calldata proof, - bytes32 nullifier, - bytes32 value, - bytes32 source, - bytes32 sig - ) public override { - require(kind == bytes32(0), "Invalid kind"); - - address toAddr = bytes32ToAddress(to); - requireNotUSDCBlacklisted(toAddr); - - burnVerifierV2.verify(proof, [kind, to, nullifier, value, source, sig]); - - // Add burn to pending burns, burn will be processed when verifyBlock is called - setBurnsKind(nullifier, kind); - burns[nullifier] = Burn(toAddr, uint256(value)); - emit BurnAdded(nullifier, uint256(value)); - } - - function burnToRouter( - bytes32 kind, - bytes32 msgHash, - bytes calldata proof, - bytes32 nullifier, - bytes32 value, - bytes32 source, - bytes32 sig, - address router, - // TODO: this could be big and use a lot of gas to set in storage, set a limit in guild - bytes calldata routerCalldata, - address returnAddress - ) public override { - require(kind == bytes32(uint256(1)), "Invalid kind"); - require(returnAddress != address(0), "Invalid return address"); - require(isRouterWhitelisted(router), "Router not whitelisted"); - requireNotUSDCBlacklisted(returnAddress); - - bytes32 computedMsg = keccak256( - abi.encode(router, routerCalldata, returnAddress) - ); - // Clear the first 3 bits, BN256 can't fit the full 256 bits - computedMsg &= bytes32( - uint256( - 0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - ) - ); - require(computedMsg == msgHash, "Invalid msg"); - - burnVerifierV2.verify( - proof, - [kind, msgHash, nullifier, value, source, sig] - ); - - setBurnsKind(nullifier, kind); - burnsToRouter[nullifier] = BurnToRouter( - router, - routerCalldata, - uint256(value), - returnAddress - ); - emit BurnAdded(nullifier, uint256(value)); - } - - function wasBurnSubstituted(bytes32 nullifier) public view returns (bool) { - return substitutedBurns[nullifier]; - } - - function executeBurnToAddress( - bytes32 nullifier, - uint256 value - ) internal returns (bool) { - Burn memory b = burns[nullifier]; - address to = b.to; - - if (b.amount == 0) { - // Burn does not exist - return false; - } - - require(b.amount == value, "RollupV6: Invalid burn amount"); - - try IERC20(usdc).transfer(to, value) { - return true; - } catch { - return false; - } - } - - function executeBurnToRouter( - bytes32 nullifier, - uint256 value - ) internal returns (bool) { - BurnToRouter memory b = burnsToRouter[nullifier]; - - // This should never happen - require(b.amount == value, "RollupV6: Invalid burn amount"); - - IERC20(usdc).approve(b.router, value); - bool routerCallSuccess = _routerCall( - b.router, - b.routerCalldata, - gasPerRouterCall - ); - // Reset allowance to 0, even if successful, - // so there is no residual allowance - IERC20(usdc).approve(b.router, 0); - if (!routerCallSuccess) { - // Call reverted. - - if (isUSDCBlacklisted(b.returnAddress)) { - return false; - } - - // Return the funds to the return address - IERC20(usdc).transfer(b.returnAddress, b.amount); - - // This is still a success, so we don't return false - } - - return true; - } - - // First bool is if the burn was found at all, - // second bool is if the burn was successful - function executeBurn( - bytes32 mb, - uint256 value, - bool substitute - ) internal returns (bool, bool) { - bool success; - bool found = true; - if (burnsKind[mb] == 0) { - if (burns[mb].amount == 0) { - // Burn does not exist - found = false; - } - - success = found && executeBurnToAddress(mb, value); - } else if (burnsKind[mb] == bytes32(uint256(1))) { - success = executeBurnToRouter(mb, value); - } else { - success = false; - } - - emit Burned(mb, substitute, success); - - return (found, success); - } - - function verifyTxn( - bytes32 mb, - bytes32 value, - // TODO: remove this parameter in the next verifyBlock version - uint256 /*_gasPerRouterCall*/ - ) internal override { - if (value == 0) { - return; - } - - rolledUpLeafs[mb] = true; - - if (mints[mb] != 0) { - require( - mints[mb] == uint256(value), - "RollupV6: Invalid mint amount" - ); - emit Minted(mb, mints[mb]); - return; - } - - // TODO: currently existance of burn must be checked by validators, because if a nullifier is - // is not present, the block production will stall here. Given its the users funds - // at risk, only the user should be responsible for this. In the case a nullifier is missing for - // a burn, we should just burn the funds and continue. To do this, we need to differentiate between - // mints and burns, as mints will still need to be checked. - // For now, we revert if a burn is not found. - (bool found, ) = executeBurn(mb, uint256(value), false); - require(found, "RollupV6: Burn was not found"); - } - - function substituteBurn(bytes32 nullifier, uint256 amount) public { - require( - !substitutedBurns[nullifier], - "RollupV6: Burn already substituted" - ); - require(!rolledUpLeafs[nullifier], "RollupV6: Leaf already rolled up"); - IERC20(usdc).transferFrom(msg.sender, address(this), amount); - - substitutedBurns[nullifier] = true; - - (bool found, bool success) = executeBurn(nullifier, amount, true); - require(found && success, "RollupV6: Burn failed"); - - // This will be returned to the msg.sender when the rollup block for it is submitted - burnsKind[nullifier] = 0; - burns[nullifier] = Burn({to: msg.sender, amount: amount}); - } -} diff --git a/eth/contracts/rollup3/RollupV1.sol b/eth/contracts/rollup3/RollupV1.sol new file mode 100644 index 0000000..cdfdcb4 --- /dev/null +++ b/eth/contracts/rollup3/RollupV1.sol @@ -0,0 +1,886 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IVerifier} from "../noir/IVerifier.sol"; +import "../IUSDC.sol"; + +struct Mint { + bytes32 note_kind; + uint256 amount; + bool spent; +} + +struct Signature { + bytes32 r; + bytes32 s; + uint v; +} + +struct ValidatorSet { + mapping(address => bool) validators; + address[] validatorsArray; + // The height at which this validator set becomes valid, inclusive + uint256 validFrom; +} + +// We can't return a mapping from a public function, so this struct is used for the public +// return valjue +struct PublicValidatorSet { + address[] validators; + uint256 validFrom; +} + +// Verifiers +struct Verifier { + IVerifier verifier; + uint32 messages_length; + bool enabled; +} + +string constant NETWORK = "Payy"; +uint64 constant NETWORK_LEN = 4; +uint256 constant MAX_FUTURE_BLOCKS = 2_592_000; // 30 days (~1 sec blocks) + +contract RollupV1 is Initializable, OwnableUpgradeable { + using SafeERC20 for IERC20; + event RollupVerified(uint256 indexed height, bytes32 root); + event Minted(bytes32 indexed hash, bytes32 value, bytes32 note_kind); + event ValidatorSetAdded(uint256 index, uint256 validFrom); + event Burned( + address indexed token, + bytes32 indexed burn_hash, + address indexed recipient, + bool substitute, + bool success + ); + event MintAdded( + bytes32 indexed mint_hash, + uint256 value, + bytes32 note_kind + ); + event VerifierAdded( + bytes32 verificationKey, + address zkVerifierAddress, + uint32 messages_length + ); + event VerifierRemoved(bytes32 verificationKey, address zkVerifierAddress); + event ProverAdded(address indexed prover); + event ProverRemoved(address indexed prover); + event RootHashUpdated(bytes32 indexed oldRoot, bytes32 indexed newRoot); + + // Contract version tracking for off-chain consumers (merged V2 behavior) + uint8 public version; + + // Verifiers + mapping(bytes32 => Verifier) public zkVerifiers; + bytes32[] public zkVerifierKeys; + + // Contracts + IUSDC public usdc; + + // Core rollup values + uint256 public blockHeight; + bytes32 public rootHash; + + // Mint - mints are removed after the rollup validates them. Mint hash is hash of commitments. + mapping(bytes32 => Mint) public mints; + + // Burn Substitutor - stores a mapping of paid out substituted burns, so they can be refunded + // once the rollup completes the original burn + // Composite key (hash + burnAddress + noteKind + amount) => substitute address + mapping(bytes32 => address) public substitutedBurns; + + // Allowed Tokens + mapping(bytes32 => address) tokens; + + // Actors + mapping(address => uint) provers; + + // Validators + ValidatorSet[] private validatorSets; + uint256 private validatorSetIndex; + + // Burn substitutors + mapping(address => bool) private burnSubstitutors; + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); + } + + function initialize( + address owner, + address _usdcAddress, + address _verifierAddress, + address prover, + address[] calldata initialValidators, + bytes32 verifierKeyHash, + uint32 verifierMessagesCount, + bytes32 initialNoteKind + ) public initializer { + version = 2; + + __Ownable_init(owner); + + usdc = IUSDC(_usdcAddress); + + // Set the init aggregate verifier + _setZkVerifierProperties( + verifierKeyHash, + _verifierAddress, + verifierMessagesCount + ); + zkVerifierKeys.push(verifierKeyHash); + + provers[prover] = 1; + + _setValidators(0, initialValidators); + + // Empty merkle tree root hash constant (from pkg/contracts/src/empty_merkle_tree_root_hash.txt) + _setRootHash( + 0x0577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff + ); + tokens[initialNoteKind] = _usdcAddress; + burnSubstitutors[owner] = true; + } + + modifier onlyProver() { + require(provers[msg.sender] == 1, "You are not a prover"); + _; + } + + function addProver(address prover) public onlyOwner { + provers[prover] = 1; + emit ProverAdded(prover); + } + + function removeProver(address prover) public onlyOwner { + require(provers[prover] == 1, "Address is not a prover"); + provers[prover] = 0; + emit ProverRemoved(prover); + } + + modifier onlyBurnSubstitutor() { + require( + burnSubstitutors[msg.sender] == true, + "RollupV1: You are not a burn substitutor" + ); + _; + } + + function _setZkVerifierProperties( + bytes32 keyHash, + address verifierAddress, + uint32 messagesLength + ) internal { + zkVerifiers[keyHash].verifier = IVerifier(verifierAddress); + zkVerifiers[keyHash].messages_length = messagesLength; + zkVerifiers[keyHash].enabled = true; + } + + function addZkVerifier( + bytes32 verificationKeyHash, + address verifierAddress, + uint32 messages_length + ) public onlyOwner { + require( + verifierAddress != address(0), + "RollupV1: Invalid zk verifier address" + ); + require( + verifierAddress.code.length > 0, + "RollupV1: ZK verifier is not a contract" + ); + // Add to verifier keys if not enabled + if (!zkVerifiers[verificationKeyHash].enabled) { + zkVerifierKeys.push(verificationKeyHash); + } + _setZkVerifierProperties( + verificationKeyHash, + verifierAddress, + messages_length + ); + emit VerifierAdded( + verificationKeyHash, + verifierAddress, + messages_length + ); + } + + function removeZkVerifier(bytes32 verificationKeyHash) public onlyOwner { + require( + zkVerifiers[verificationKeyHash].enabled, + "RollupV1: ZK verifier does not exist" + ); + address verifierAddress = address( + zkVerifiers[verificationKeyHash].verifier + ); + delete zkVerifiers[verificationKeyHash]; + // Find and remove the verifierKey from verifierKeys array + uint256 length = zkVerifierKeys.length; + for (uint256 i = 0; i < length; i++) { + if (zkVerifierKeys[i] == verificationKeyHash) { + // Move the last element to this position and remove the last element + zkVerifierKeys[i] = zkVerifierKeys[length - 1]; + zkVerifierKeys.pop(); + break; + } + } + emit VerifierRemoved(verificationKeyHash, verifierAddress); + } + + function getZkVerifier( + bytes32 verificationKeyHash + ) public view returns (address, uint32) { + require( + zkVerifiers[verificationKeyHash].enabled, + "RollupV1: ZK verifier does not exist" + ); + return ( + address(zkVerifiers[verificationKeyHash].verifier), + zkVerifiers[verificationKeyHash].messages_length + ); + } + + function addBurnSubstitutor(address burnSubstitutor) public onlyOwner { + burnSubstitutors[burnSubstitutor] = true; + } + + function removeBurnSubstitutor(address burnSubstitutor) public onlyOwner { + burnSubstitutors[burnSubstitutor] = false; + } + + function _setRootHash(bytes32 newRoot) internal { + bytes32 oldRoot = rootHash; + rootHash = newRoot; + emit RootHashUpdated(oldRoot, newRoot); + } + + function setRoot(bytes32 newRoot) public onlyOwner { + _setRootHash(newRoot); + } + + function currentRootHash() public view returns (bytes32) { + return rootHash; + } + + function addToken(bytes32 noteKind, address tokenAddress) public onlyOwner { + require( + tokens[noteKind] == address(0), + "RollupV1: Token already exists" + ); + + tokens[noteKind] = tokenAddress; + } + + function noteKindTokenAddress( + bytes32 noteKind + ) public view returns (address) { + return tokens[noteKind]; + } + + function DOMAIN_SEPARATOR() public view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ), + keccak256(bytes("Rollup")), + keccak256(bytes("1")), + block.chainid, + address(this) + ) + ); + } + + bytes32 constant MINT_WITH_AUTHORIZATION_TYPE_HASH = + keccak256( + "MintWithAuthorization(bytes32 commitment,bytes32 value,bytes32 kind,address from,uint256 validAfter,uint256 validBefore,bytes32 nonce)" + ); + + ///////////////// + // + // VERIFY + // + /////////// + + // Verify rollup + function verifyRollup( + uint256 height, + bytes32 verificationKeyHash, + bytes calldata aggrProof, + // oldRoot, newRoot, commitHash, , 16x kzg + bytes32[] calldata publicInputs, + bytes32 otherHashFromBlockHash, + Signature[] calldata signatures + ) public onlyProver { + require( + zkVerifiers[verificationKeyHash].enabled, + "RollupV1: ZK verifier not allowed" + ); + + require( + publicInputs.length == + zkVerifiers[verificationKeyHash].messages_length + 3, + "RollupV1: Invalid publicInputs length" + ); + + bytes32 oldRoot = publicInputs[0]; + bytes32 newRoot = publicInputs[1]; + bytes32 commitHash = publicInputs[2]; + + verifyRootHash(oldRoot); + + verifyCommitHash(commitHash); + + verifyValidatorSignatures( + newRoot, + height, + otherHashFromBlockHash, + signatures + ); + + verifyAllMessages( + // Skip the first 3 public inputs as these are never messages + 3, + publicInputs, + zkVerifiers[verificationKeyHash].messages_length + ); + + require( + zkVerifiers[verificationKeyHash].verifier.verify( + aggrProof, + publicInputs + ), + "RollupV1: ZK proof verification failed" + ); + + rootHash = newRoot; + require( + height > blockHeight, + "RollupV1: New block height must be greater than current" + ); + blockHeight = height; + + emit RollupVerified(height, newRoot); + } + + function verifyRootHash(bytes32 expectedRoot) internal view { + require( + expectedRoot == rootHash, + "RollupV1: Root hash verification failed" + ); + } + + // Placeholder for asserting the commit hash is stored on Celestia + function verifyCommitHash(bytes32 commitHash) internal {} + + function verifyAllMessages( + uint skipCount, + bytes32[] calldata publicInputs, + uint32 messages_length + ) internal { + // Skip the first 4 (as they are processed separately) + uint i = skipCount; + uint end = skipCount + messages_length; + while (i < end) { + i = verifyMessages(i, publicInputs); + } + } + + function verifyMessages( + uint index, + bytes32[] calldata publicInputs + ) internal returns (uint) { + // Get the kind from public input at index + uint256 kind = uint256(publicInputs[index]); + + if (kind == 0) { + return index + 1; + } else if (kind == 2) { + // Mint + return verifyMint(index, publicInputs); + } else if (kind == 3) { + // Burn + return verifyBurn(index, publicInputs); + } else { + // Not allowed + revert("RollupV1: Invalid message kind"); + } + } + + function verifyMint( + uint i, + bytes32[] calldata messages + ) internal returns (uint) { + bytes32 note_kind = messages[i + 1]; + bytes32 value = messages[i + 2]; + bytes32 hash = messages[i + 3]; + + require( + mints[hash].amount == uint256(value), + "RollupV1: Mint value invalid" + ); + require( + mints[hash].note_kind == note_kind, + "RollupV1: Mint note kind invalid" + ); + require(mints[hash].spent == false, "RollupV1: Mint already spent"); + mints[hash].spent = true; + + emit Minted(hash, value, note_kind); + + return i + 4; + } + + function verifyBurn( + uint i, + bytes32[] calldata messages + ) internal returns (uint) { + bytes32 note_kind = messages[i + 1]; + uint256 value = uint256(messages[i + 2]); + bytes32 hash = messages[i + 3]; + address burn_addr = bytes32ToAddress(messages[i + 4]); + + address token = tokens[note_kind]; + + bytes32 substituteBurnKey = getSubstituteBurnKey( + hash, + burn_addr, + note_kind, + value + ); + address substitutor = substitutedBurns[substituteBurnKey]; + if (substitutor != address(0)) { + bool success = executeBurn(token, substitutor, hash, value, false); + if (success) { + delete substitutedBurns[substituteBurnKey]; + } + } else { + executeBurn(token, burn_addr, hash, value, false); + } + + return i + 5; + } + + function bytes32ToAddress( + bytes32 _bytes32 + ) internal pure returns (address) { + return address(uint160(uint256(_bytes32))); + } + + /** + * @dev Helper function to generate composite key for substitutedBurns mapping + * @param hash The burn hash + * @param burnAddress The burn address + * @param noteKind The note kind + * @param amount The amount + * @return The composite key for the mapping + */ + function getSubstituteBurnKey( + bytes32 hash, + address burnAddress, + bytes32 noteKind, + uint256 amount + ) internal pure returns (bytes32) { + return + keccak256( + abi.encode(hash, burnAddress, noteKind, amount, uint256(0)) + ); + } + + ///////////////// + // + // BURNS + // + /////////// + + function executeBurn( + address token, + address recipient, + bytes32 burn_hash, + uint256 value, + bool substitute + ) internal returns (bool) { + bool success = executeBurnToAddress(token, recipient, value); + emit Burned(token, burn_hash, recipient, substitute, success); + return success; + } + + function executeBurnToAddress( + address token, + address recipient, + uint256 value + ) internal returns (bool) { + (bool success, bytes memory returndata) = token.call( + abi.encodeCall(IERC20.transfer, (recipient, value)) + ); + if (!success) { + return false; + } + if (returndata.length != 0) { + bool func_return = abi.decode(returndata, (bool)); + if (!func_return) { + return false; + } + } + return true; + } + + function wasBurnSubstituted( + address burn_address, + bytes32 note_kind, + bytes32 hash, + uint256 amount + ) public view returns (bool) { + bytes32 substituteBurnKey = getSubstituteBurnKey( + hash, + burn_address, + note_kind, + amount + ); + return substitutedBurns[substituteBurnKey] != address(0); + } + + function substituteBurn( + address burnAddress, + bytes32 note_kind, + bytes32 hash, + uint256 amount, + uint256 burnBlockHeight + ) public onlyBurnSubstitutor { + substituteBurnTo( + burnAddress, + msg.sender, + note_kind, + hash, + amount, + burnBlockHeight + ); + } + + function substituteBurnTo( + address burnAddress, + address substituteAddress, + bytes32 note_kind, + bytes32 hash, + uint256 amount, + uint256 burnBlockHeight + ) private { + bytes32 substituteBurnKey = getSubstituteBurnKey( + hash, + burnAddress, + note_kind, + amount + ); + require( + substitutedBurns[substituteBurnKey] == address(0), + "RollupV1: Burn already substituted" + ); + require( + blockHeight < burnBlockHeight, + "RollupV1: Block height already rolled up" + ); + + address token = tokens[note_kind]; + require(token != address(0), "RollupV1: Token not found for note kind"); + + IERC20(token).safeTransferFrom( + substituteAddress, + address(this), + amount + ); + + bool success = executeBurn(token, burnAddress, hash, amount, true); + require(success, "RollupV1: Burn failed"); + + // This will be returned to the msg.sender when the rollup block for it is submitted + substitutedBurns[substituteBurnKey] = substituteAddress; + } + + ///////////////// + // + // MINTS + // + /////////// + + function getMint(bytes32 hash) public view returns (Mint memory) { + return mints[hash]; + } + + // Anyone can call mint, although this is likely to be performed on behalf of the user + // as they may not have gas to pay for the txn + function mint(bytes32 mint_hash, bytes32 value, bytes32 note_kind) public { + if (mints[mint_hash].amount != 0) { + revert("RollupV1: Mint already exists"); + } + + address tokenAddress = tokens[note_kind]; + require( + tokenAddress != address(0), + "RollupV1: Token not found for note kind" + ); + + // Take the money from the external account, sender must have been previously + // approved as per the ERC20 standard + IERC20(tokenAddress).safeTransferFrom( + msg.sender, + address(this), + uint256(value) + ); + + // Add mint to pending mints, this still needs to be verifier with the verifyBlock, + // but Solid validators will check that this commitment exists in the mint map before + // accepting the mint txn into a block + mints[mint_hash] = Mint({ + note_kind: note_kind, + amount: uint256(value), + spent: false + }); + + emit MintAdded(mint_hash, uint256(value), note_kind); + } + + function mintWithAuthorization( + bytes32 mint_hash, + bytes32 value, + bytes32 note_kind, + address from, + uint256 validAfter, + uint256 validBefore, + bytes32 nonce, + uint256 v, + bytes32 r, + bytes32 s, + // Second signature, not for receiveWithAuthorization, + // but for this mintWithAuthorization call + uint256 v2, + bytes32 r2, + bytes32 s2 + ) public { + if (mints[mint_hash].amount != 0) { + revert("RollupV1: Mint already exists"); + } + + bytes32 structHash = keccak256( + abi.encode( + MINT_WITH_AUTHORIZATION_TYPE_HASH, + mint_hash, + value, + note_kind, + from, + validAfter, + validBefore, + nonce + ) + ); + bytes32 computedHash = keccak256( + abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash) + ); + address signer = ECDSA.recover(computedHash, uint8(v2), r2, s2); + require(signer == from, "RollupV1: Invalid signer"); + + address tokenAddress = tokens[note_kind]; + require( + tokenAddress != address(0), + "RollupV1: Token not found for note kind" + ); + + // This will fail if the token does not support receiveWithAuthorization + // method in the defined format. Users of this method must ensure that + // the token supports it. + IUSDC(tokenAddress).receiveWithAuthorization( + from, + address(this), + uint256(value), + validAfter, + validBefore, + nonce, + uint8(v), + r, + s + ); + + mints[mint_hash] = Mint({ + note_kind: note_kind, + amount: uint256(value), + spent: false + }); + emit MintAdded(mint_hash, uint256(value), note_kind); + } + + + + ///////////////// + // + // VALIDATORS + // + /////////// + function verifyValidatorSignatures( + bytes32 newRoot, + uint256 height, + bytes32 otherHashFromBlockHash, + Signature[] calldata signatures + ) internal { + updateValidatorSetIndex(height); + ValidatorSet storage validatorSet = getValidators(); + + require(signatures.length > 0, "RollupV1: No signatures"); + + uint minValidators = (validatorSet.validatorsArray.length * 2) / 3 + 1; + require( + signatures.length >= minValidators, + "RollupV1: Not enough signatures from validators to verify block" + ); + + bytes32 sigHash = getSignatureMessageHash( + newRoot, + height, + otherHashFromBlockHash + ); + + address previous = address(0); + for (uint i = 0; i < signatures.length; i++) { + Signature calldata signature = signatures[i]; + address signer = ECDSA.recover( + sigHash, + uint8(signature.v), + signature.r, + signature.s + ); + require( + validatorSet.validators[signer] == true, + "RollupV1: Signer is not a validator" + ); + + require(signer > previous, "RollupV1: Signers are not sorted"); + previous = signer; + } + } + + function getSignatureMessageHash( + bytes32 newRoot, + uint256 height, + bytes32 otherHashFromBlockHash + ) internal pure returns (bytes32) { + bytes32 proposalHash = keccak256( + abi.encode(newRoot, height, otherHashFromBlockHash) + ); + bytes32 acceptMsg = keccak256(abi.encode(height + 1, proposalHash)); + bytes32 sigMsg = keccak256( + abi.encodePacked(NETWORK_LEN, NETWORK, acceptMsg) + ); + return sigMsg; + } + + // Returns all validator sets from a given index, inclusive + function getValidatorSets( + uint256 from + ) public view returns (PublicValidatorSet[] memory) { + PublicValidatorSet[] memory sets = new PublicValidatorSet[]( + validatorSets.length - from + ); + + for (uint256 i = from; i < validatorSets.length; i++) { + sets[i - from] = PublicValidatorSet( + validatorSets[i].validatorsArray, + validatorSets[i].validFrom + ); + } + + return sets; + } + + function getValidators() internal view returns (ValidatorSet storage) { + return validatorSets[validatorSetIndex]; + } + + function _setValidators( + uint256 validFrom, + address[] calldata validators + ) private { + require( + validatorSets.length == 0 || + validatorSets[validatorSets.length - 1].validFrom < validFrom, + "RollupV1: New validator set must have a validFrom greater than the last set" + ); + require( + validFrom == 0 || validFrom <= block.number + MAX_FUTURE_BLOCKS, + "RollupV1: validFrom cannot be more than 30 days in the future" + ); + + // Create a new ValidatorSet and push it to the array + validatorSets.push(); + uint256 newIndex = validatorSets.length - 1; + + validatorSets[newIndex].validFrom = validFrom; + validatorSets[newIndex].validatorsArray = validators; + + for (uint256 i = 0; i < validators.length; i++) { + require( + validatorSets[newIndex].validators[validators[i]] == false, + "RollupV1: Validator already exists" + ); + + validatorSets[newIndex].validators[validators[i]] = true; + } + + emit ValidatorSetAdded(newIndex, validFrom); + } + + function setValidators( + uint256 validFrom, + address[] calldata validators + ) public onlyOwner { + _setValidators(validFrom, validators); + } + + function updateValidatorSetIndex(uint256 height) internal { + for (uint256 i = validatorSetIndex + 1; i < validatorSets.length; i++) { + if (validatorSets[i].validFrom > height) { + break; + } + + validatorSetIndex = i; + } + } + + // Debug function to expose internal hash calculation + function debugGetSignatureMessageHash( + bytes32 newRoot, + uint256 height, + bytes32 otherHashFromBlockHash + ) external pure returns (bytes32) { + return getSignatureMessageHash(newRoot, height, otherHashFromBlockHash); + } + + // Debug function to expose intermediate values + function debugGetIntermediateHashes( + bytes32 newRoot, + uint256 height, + bytes32 otherHashFromBlockHash + ) + external + pure + returns (bytes32 proposalHash, bytes32 acceptMsg, bytes32 sigMsg) + { + proposalHash = keccak256( + abi.encode(newRoot, height, otherHashFromBlockHash) + ); + acceptMsg = keccak256(abi.encode(height + 1, proposalHash)); + sigMsg = keccak256(abi.encodePacked(NETWORK_LEN, NETWORK, acceptMsg)); + } + + // Debug function to see the raw packed bytes + function debugGetPackedBytes( + bytes32 acceptMsg + ) external pure returns (bytes memory) { + return abi.encodePacked(NETWORK_LEN, NETWORK, acceptMsg); + } +} diff --git a/eth/contracts/router/BurnToAddress.sol b/eth/contracts/router/BurnToAddress.sol deleted file mode 100644 index 57407e3..0000000 --- a/eth/contracts/router/BurnToAddress.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.9; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -contract BurnToAddressRouter { - function burnToAddress(address usdcAddr, address to, uint256 value) public { - IERC20(usdcAddr).transferFrom(msg.sender, to, value); - } -} diff --git a/eth/hardhat.config.ts b/eth/hardhat.config.ts index fe737e1..0c6ec40 100644 --- a/eth/hardhat.config.ts +++ b/eth/hardhat.config.ts @@ -1,27 +1,37 @@ -import { type HardhatUserConfig } from 'hardhat/config' -import '@nomicfoundation/hardhat-toolbox-viem' -import '@nomicfoundation/hardhat-ethers' +import { type HardhatUserConfig } from "hardhat/config"; +import "@nomicfoundation/hardhat-toolbox-viem"; +import "@nomicfoundation/hardhat-ethers"; +import "@nomicfoundation/hardhat-chai-matchers"; const config: HardhatUserConfig = { solidity: { - version: '0.8.20', + version: "0.8.20", settings: { viaIR: true, optimizer: { enabled: true, - runs: 200 - } - } + runs: 200, + }, + }, }, networks: { hardhat: { chainId: 1337, + hardfork: "prague", throwOnTransactionFailures: true, throwOnCallFailures: true, - loggingEnabled: true - } - } -} + loggingEnabled: true, + mining: { + auto: true, + interval: 1000, + }, + }, + localhost: { + // url: 'http://localhost:8546', + chainId: 1337, + }, + }, +}; const NETWORKS = { // A hardhat testing instance with a non-default port @@ -33,24 +43,32 @@ const NETWORKS = { polygon: { chainId: 137 }, amoy: { chainId: 80002 }, kovan: { chainId: 42 }, - sepolia: { chainId: 1337 } -} as any + sepolia: { chainId: 1337 }, + base: { chainId: 8453 }, + bnb: { chainId: 56 }, + arbitrum: { chainId: 42161 }, + optimism: { chainId: 10 }, +} as any; Object.keys(NETWORKS).forEach((network) => { - const networkUrl = process.env[`${network.toUpperCase()}_URL`] - if (networkUrl === undefined || config?.networks === undefined) return + const networkUrl = process.env[`${network.toUpperCase()}_URL`]; + if (networkUrl === undefined || config?.networks === undefined) return; // Ensure we have a secret key for this network - if (process.env.SECRET_KEY === undefined) throw new Error('SECRET_KEY is not set') + if (process.env.SECRET_KEY === undefined) + throw new Error("SECRET_KEY is not set"); config.networks[network] = { url: networkUrl, - accounts: [process.env.SECRET_KEY ?? ''], + accounts: [process.env.SECRET_KEY ?? ""], chainId: NETWORKS[network]?.chainId, - gasPrice: process.env.GAS_PRICE_GWEI !== undefined ? parseInt(process.env.GAS_PRICE_GWEI) * 1_000_000_000 : undefined - } -}) + gasPrice: + process.env.GAS_PRICE_GWEI !== undefined + ? parseInt(process.env.GAS_PRICE_GWEI) * 1_000_000_000 + : undefined, + }; +}); -console.error(config) +console.error(config); -export default config +export default config; diff --git a/eth/noir/agg_agg.sol b/eth/noir/agg_agg.sol new file mode 100644 index 0000000..62841bf --- /dev/null +++ b/eth/noir/agg_agg.sol @@ -0,0 +1,2435 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 2097152; +uint256 constant LOG_N = 21; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 49; +uint256 constant VK_HASH = 0x104c026d540c259c7c6ab1bebddfeeb8d990d075a71169ac5e6975eeb6d477f4; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(2097152), + logCircuitSize: uint256(21), + publicInputsSize: uint256(49), + ql: Honk.G1Point({ + x: uint256(0x1a0e33ec74f1fb9b98fa453d23fa931f02fffbdfe1b887601138e7e1640b7796), + y: uint256(0x300e5523f753fdb53688683b5378dd2eafd8567fee5cbeeb7901a6510dd8a48b) + }), + qr: Honk.G1Point({ + x: uint256(0x15e36a7d8420b6384517e2bac0a70aa4d73bd46b09ffeb3315fb0465b07fafd0), + y: uint256(0x05c2eabc83c66c5ef0ac245baad9f226203d0ba403dc651d41d7d253423c5dd6) + }), + qo: Honk.G1Point({ + x: uint256(0x17e475af11465af1fe078c086d150d8b26d2e163bcc68599afa8c2fdc8416731), + y: uint256(0x023a936fae0b682ea2f457317ceb18d734446711cd90c476f192615de01a60e6) + }), + q4: Honk.G1Point({ + x: uint256(0x0a6ef9c8f09a8d1e17a067a0c08e931f1d0c681b7a7544e8c433dfe859a9a5df), + y: uint256(0x0e5487d3540e5a37906ca339b947f1bd1f8a7ff5fe7c65dca53406452036ccc9) + }), + qm: Honk.G1Point({ + x: uint256(0x1c6a4310d6ac26389fbc1a4f69f189eaf4df307d610299401033fdb085604858), + y: uint256(0x056f2430f80290a16e2a838a1f017809e4211189eb6627747a8bc339669e285c) + }), + qc: Honk.G1Point({ + x: uint256(0x1474cafc9edda8f5eadf966fd16238235410b51c4bf9d5451b6066ac892941cc), + y: uint256(0x200aaabc514fba3089ca52fe019e6c78dc2d6991095003397c5fa494b34df2e5) + }), + qLookup: Honk.G1Point({ + x: uint256(0x2908804831a6fe78780f1a30dd07d8e6325805c4d10b789541650b83fce14dcd), + y: uint256(0x25ba822e045da000a72c4bd49d18272e7b5ef17f06af25877d2c947f6a6efe9f) + }), + qArith: Honk.G1Point({ + x: uint256(0x28341a92384c2028f39b32948d63785a4fc5a0737f034fa9836f1e5b1b45276d), + y: uint256(0x2442e212d325ddb6477ff41e6727ff7739f06dbc765458a972a6471ab73ed267) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x0e9f44a0a67be5e49d477088e067dcc1d97d01aefb12853af2bf2772d9b9770a), + y: uint256(0x0ba20c4b7cb1a1247c635c1bb033da99118b0ff5435b2e8786119dc18a232041) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x01e4695abaca0d24796e5b12795736a577646a315107507dd47227c8801fee8e), + y: uint256(0x041b5fa9e2eb289c2b22a5fe45a407e888cc8324aeb83d5243a584504757f594) + }), + qMemory: Honk.G1Point({ + x: uint256(0x2f656eb60ae010f5ac4204e6a3347b9bb20ebbf529e4aecb2b7d4d3e1b4a4c22), + y: uint256(0x0df6c706551cfe34924ba1565ae45c47f889976e606e8b20d8199e471ed24a6e) + }), + qNnf: Honk.G1Point({ + x: uint256(0x1ba7f5c51d32334cdae6a5cff746225e5b88bdef47e31020ed8f77da795a8e87), + y: uint256(0x03fa15ddd5c67e5ad9de105038d810d77ea99a91e0095401e3cd4b641337cdf4) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x12ba890d6500035c2421f9ce4ba8b3f49142341870a061dcec351c51a30dd3cf), + y: uint256(0x29e447c1e9087a9006aaa9844a0a4a65b395ba815e64ac7847122f6403e4fef1) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x123bc1545ac5a5a6c8f95456c9d40297ac5e728df6ad7ad149a7d547e3e97621), + y: uint256(0x0cf780a57f06212937fb5dcf84d288e75fbf4feeb26584813d21d2694f5a7654) + }), + s1: Honk.G1Point({ + x: uint256(0x0eb38cbcb9524df7b950b651c8bf64aa06ee9420ff74b8c13e242e1d61f3f291), + y: uint256(0x1e2b72f6420c7f28cf36883849a237b55235ab8de20f7a55865e5e55dc32c367) + }), + s2: Honk.G1Point({ + x: uint256(0x07be38ed489ea9f14999f38f0681d2d26ee8df1f3527c7f73534fccf0761d585), + y: uint256(0x1a65713cb0b7f27f906acc1ccca074da7debde5a29224038ee2e434083f0f502) + }), + s3: Honk.G1Point({ + x: uint256(0x1caa2b03618d2cb71ae9ddc4d0d8e8021e59f3620ddb86116c9bb802e8a66d8c), + y: uint256(0x255ca5d3a06b7595a7b384ef5c543b8c39612045259e9a85dc45b51fb9748ef5) + }), + s4: Honk.G1Point({ + x: uint256(0x09bfded3efdeb6a51522a5d3e3f3750da123c09328ca0174986ab6fac9e11fa4), + y: uint256(0x166a28b35419b78cc2822538fc1bb023d45a30b92e74934acad95737e65795cc) + }), + t1: Honk.G1Point({ + x: uint256(0x1df848681c58738d9e319128e0906f2291ee52aa94179591c920a26c1901713e), + y: uint256(0x3053d98d6fe5bbcae2631bc943e3095765c74b357b68c6f9c57e6d8ec704ded2) + }), + t2: Honk.G1Point({ + x: uint256(0x00ff5d6fa0aaf2e5b858ff35a37ff9f58d45c464ea643d1823d669cd6260f825), + y: uint256(0x2e94ec5c97eab43a669e50237d17fe18a20d298ee739e67c881a4cb45faeba26) + }), + t3: Honk.G1Point({ + x: uint256(0x181f20e92a3c7cade54c0982bafb159a202ed82fa04933000d5e94eff296a2d7), + y: uint256(0x0808bd14174de924a4063cf1daa44c1f701c09694851359cabd5d965f8ddac67) + }), + t4: Honk.G1Point({ + x: uint256(0x085b1f3adaf6cd18fc8165e58ce5f4d19bc60351464511db4082380d99239073), + y: uint256(0x07c44418f8e36725093e6551f018913a34d05c92457ee6dbcaf069b313a5fe8b) + }), + id1: Honk.G1Point({ + x: uint256(0x153ea4c9c31188d36ffd6126bf869f8764d33324ae56a078beba01629185e97c), + y: uint256(0x1ec94511b7fe3e28a3a0d1f5d22d5755874093444d915266219aa8e6767a9b1b) + }), + id2: Honk.G1Point({ + x: uint256(0x2da4c60e0f3ecb9cfb19721df84644997ae4dcc23e5995ba96c371b45898284a), + y: uint256(0x1733c59e5b59a482a4a3960d14f9845edf831b8144d8a0026314aaa177697765) + }), + id3: Honk.G1Point({ + x: uint256(0x22468c3b7fb0da5b0b634a726562bb1869d5c60098765a88a9c0069fd9f506e6), + y: uint256(0x014a436367acb0f7265ae061bdb0a602785105478cdce11cffff6d848b46ec1f) + }), + id4: Honk.G1Point({ + x: uint256(0x20916218052db91206da5b1e5f3fe60b5596187b22a297b09455a197849f5ee4), + y: uint256(0x0a85ff4c91b15151f713e633eb62a554f9c7dcdce407cac84f17a3788dbbf88b) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x29ec476231242bfc60ab1fdc0183072bdb6b93bae8a75fff00bac01c61ba8376), + y: uint256(0x1212d342a601844c7d351c9da6a7bfb7dd69b9a89b8177fb7e67d94dfa0f8964) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + unchecked { + return Fr.wrap(value % MODULUS); + } + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + unchecked { + return Fr.wrap(uint256(value) % MODULUS); + } + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + unchecked { + return bytes32(Fr.unwrap(value)); + } + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + mstore(0x40, add(free, 0x80)) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + mstore(0x40, add(free, 0x80)) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + unchecked { + return numerator * invert(denominator); + } + } + + function sqr(Fr value) internal pure returns (Fr) { + unchecked { + return value * value; + } + } + + function unwrap(Fr value) internal pure returns (uint256) { + unchecked { + return Fr.unwrap(value); + } + } + + function neg(Fr value) internal pure returns (Fr) { + unchecked { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + unchecked { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); + } +} + +function mul(Fr a, Fr b) pure returns (Fr) { + unchecked { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); + } +} + +function sub(Fr a, Fr b) pure returns (Fr) { + unchecked { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); + } +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + unchecked { + return Fr.unwrap(a) != Fr.unwrap(b); + } +} + +function equal(Fr a, Fr b) pure returns (bool) { + unchecked { + return Fr.unwrap(a) == Fr.unwrap(b); + } +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +uint256 constant FIELD_ELEMENT_SIZE = 0x20; +uint256 constant GROUP_ELEMENT_SIZE = 0x40; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + G1Point w1; + G1Point w2; + G1Point w3; + G1Point w4; + // Lookup helpers - Permutations + G1Point zPerm; + // Lookup helpers - logup + G1Point lookupReadCounts; + G1Point lookupReadTags; + G1Point lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + G1Point shplonkQ; + G1Point kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + G1Point w1; + G1Point w2; + G1Point w3; + G1Point w4; + // Commitments to logup witness polynomials + G1Point lookupReadCounts; + G1Point lookupReadTags; + G1Point lookupInverses; + // Commitment to grand permutation polynomial + G1Point zPerm; + G1Point[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + G1Point geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + G1Point shplonkQ; + G1Point kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 vkHash, + uint256 publicInputsSize, + uint256 logN + ) external pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = + generateRelationParametersChallenges(proof, publicInputs, vkHash, publicInputsSize, previousChallenge); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge, logN); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge, logN); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge, logN); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge, logN); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 vkHash, + uint256 publicInputsSize, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 vkHash, + uint256 publicInputsSize + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 6); + round0[0] = bytes32(vkHash); + + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[1 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[1 + publicInputsSize] = bytes32(proof.w1.x); + round0[1 + publicInputsSize + 1] = bytes32(proof.w1.y); + round0[1 + publicInputsSize + 2] = bytes32(proof.w2.x); + round0[1 + publicInputsSize + 3] = bytes32(proof.w2.y); + round0[1 + publicInputsSize + 4] = bytes32(proof.w3.x); + round0[1 + publicInputsSize + 5] = bytes32(proof.w3.y); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[7] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x); + round1[2] = bytes32(proof.lookupReadCounts.y); + round1[3] = bytes32(proof.lookupReadTags.x); + round1[4] = bytes32(proof.lookupReadTags.y); + round1[5] = bytes32(proof.w4.x); + round1[6] = bytes32(proof.w4.y); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[5] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x; + alpha0[2] = proof.lookupInverses.y; + alpha0[3] = proof.zPerm.x; + alpha0[4] = proof.zPerm.y; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + Fr alpha; + (alpha,) = splitChallenge(nextPreviousChallenge); + + // Compute powers of alpha for batching subrelations + alphas[0] = alpha; + for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) { + alphas[i] = alphas[i - 1] * alpha; + } + } + + function generateGateChallenges(Fr previousChallenge, uint256 logN) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + (gateChallenges[0],) = splitChallenge(previousChallenge); + for (uint256 i = 1; i < logN; i++) { + gateChallenges[i] = gateChallenges[i - 1] * gateChallenges[i - 1]; + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 2 comm, 1 sum, 1 challenge + uint256[4] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x; + challengeData[2] = proof.libraCommitments[0].y; + challengeData[3] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge, uint256 logN) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < logN; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 9] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].y; + i += 2; + rhoChallengeElements[i] = proof.libraCommitments[2].x; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].y; + i += 2; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.y; + + i += 2; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge, uint256 logN) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[] memory gR = new uint256[]((logN - 1) * 2 + 1); + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < logN - 1; i++) { + gR[1 + i * 2] = proof.geminiFoldComms[i].x; + gR[2 + i * 2] = proof.geminiFoldComms[i].y; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge, uint256 logN) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[] memory shplonkNuChallengeElements = new uint256[](logN + 1 + 4); + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= logN; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = logN + 1; i <= logN + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[3] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x; + shplonkZChallengeElements[2] = proof.shplonkQ.y; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof, uint256 logN) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + // Commitments + p.w1 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.w2 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.w3 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.lookupReadTags = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.w4 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.lookupInverses = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.zPerm = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.libraCommitments[0] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + + p.libraSum = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + // Sumcheck univariates + for (uint256 i = 0; i < logN; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + + p.libraCommitments[1] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.libraCommitments[2] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.geminiMaskingPoly = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < logN - 1; i++) { + p.geminiFoldComms[i] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < logN; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + + // Shplonk + p.shplonkQ = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + // KZG + p.kzgQuotient = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * (ap.index_delta - Fr.wrap(1)); // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * (access_type - Fr.wrap(1)); // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_O)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + Fr unshiftedScalarNeg; + Fr shiftedScalarNeg; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[] foldPosEvaluations; + } + + function computeSquares(Fr r, uint256 logN) internal pure returns (Fr[] memory) { + Fr[] memory squares = new Fr[](logN); + squares[0] = r; + for (uint256 i = 1; i < logN; ++i) { + squares[i] = squares[i - 1].sqr(); + } + return squares; + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[] memory) { + Fr[] memory foldPosEvaluations = new Fr[](logSize); + for (uint256 i = logSize; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + return foldPosEvaluations; + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities +function bytesToG1Point(bytes calldata proofSection) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({ + x: uint256(bytes32(proofSection[0x00:0x20])) % Q, + y: uint256(bytes32(proofSection[0x20:0x40])) % Q + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +/** + * Convert the pairing points to G1 points. + * + * The pairing points are serialised as an array of 68 bit limbs representing two points + * The lhs of a pairing operation and the rhs of a pairing operation + * + * There are 4 fields for each group element, leaving 8 fields for each side of the pairing. + * + * @param pairingPoints The pairing points to convert. + * @return lhs + * @return rhs + */ +function convertPairingPointsToG1(Fr[PAIRING_POINTS_SIZE] memory pairingPoints) + pure + returns (Honk.G1Point memory lhs, Honk.G1Point memory rhs) +{ + uint256 lhsX = Fr.unwrap(pairingPoints[0]); + lhsX |= Fr.unwrap(pairingPoints[1]) << 68; + lhsX |= Fr.unwrap(pairingPoints[2]) << 136; + lhsX |= Fr.unwrap(pairingPoints[3]) << 204; + lhs.x = lhsX; + + uint256 lhsY = Fr.unwrap(pairingPoints[4]); + lhsY |= Fr.unwrap(pairingPoints[5]) << 68; + lhsY |= Fr.unwrap(pairingPoints[6]) << 136; + lhsY |= Fr.unwrap(pairingPoints[7]) << 204; + lhs.y = lhsY; + + uint256 rhsX = Fr.unwrap(pairingPoints[8]); + rhsX |= Fr.unwrap(pairingPoints[9]) << 68; + rhsX |= Fr.unwrap(pairingPoints[10]) << 136; + rhsX |= Fr.unwrap(pairingPoints[11]) << 204; + rhs.x = rhsX; + + uint256 rhsY = Fr.unwrap(pairingPoints[12]); + rhsY |= Fr.unwrap(pairingPoints[13]) << 68; + rhsY |= Fr.unwrap(pairingPoints[14]) << 136; + rhsY |= Fr.unwrap(pairingPoints[15]) << 204; + rhs.y = rhsY; +} + +/** + * Hash the pairing inputs from the present verification context with those extracted from the public inputs. + * + * @param proofPairingPoints Pairing points from the proof - (public inputs). + * @param accLhs Accumulator point for the left side - result of shplemini. + * @param accRhs Accumulator point for the right side - result of shplemini. + * @return recursionSeparator The recursion separator - generated from hashing the above. + */ +function generateRecursionSeparator( + Fr[PAIRING_POINTS_SIZE] memory proofPairingPoints, + Honk.G1Point memory accLhs, + Honk.G1Point memory accRhs +) pure returns (Fr recursionSeparator) { + // hash the proof aggregated X + // hash the proof aggregated Y + // hash the accum X + // hash the accum Y + + (Honk.G1Point memory proofLhs, Honk.G1Point memory proofRhs) = convertPairingPointsToG1(proofPairingPoints); + + uint256[8] memory recursionSeparatorElements; + + // Proof points + recursionSeparatorElements[0] = proofLhs.x; + recursionSeparatorElements[1] = proofLhs.y; + recursionSeparatorElements[2] = proofRhs.x; + recursionSeparatorElements[3] = proofRhs.y; + + // Accumulator points + recursionSeparatorElements[4] = accLhs.x; + recursionSeparatorElements[5] = accLhs.y; + recursionSeparatorElements[6] = accRhs.x; + recursionSeparatorElements[7] = accRhs.y; + + recursionSeparator = FrLib.fromBytes32(keccak256(abi.encodePacked(recursionSeparatorElements))); +} + +/** + * G1 Mul with Separator + * Using the ecAdd and ecMul precompiles + * + * @param basePoint The point to multiply. + * @param other The other point to add. + * @param recursionSeperator The separator to use for the multiplication. + * @return `(recursionSeperator * basePoint) + other`. + */ +function mulWithSeperator(Honk.G1Point memory basePoint, Honk.G1Point memory other, Fr recursionSeperator) + view + returns (Honk.G1Point memory) +{ + Honk.G1Point memory result; + + result = ecMul(recursionSeperator, basePoint); + result = ecAdd(result, other); + + return result; +} + +/** + * G1 Mul + * Takes a Fr value and a G1 point and uses the ecMul precompile to return the result. + * + * @param value The value to multiply the point by. + * @param point The point to multiply. + * @return result The result of the multiplication. + */ +function ecMul(Fr value, Honk.G1Point memory point) view returns (Honk.G1Point memory) { + Honk.G1Point memory result; + + assembly { + let free := mload(0x40) + // Write the point into memory (two 32 byte words) + // Memory layout: + // Address | value + // free | point.x + // free + 0x20| point.y + mstore(free, mload(point)) + mstore(add(free, 0x20), mload(add(point, 0x20))) + // Write the scalar into memory (one 32 byte word) + // Memory layout: + // Address | value + // free + 0x40| value + mstore(add(free, 0x40), value) + + // Call the ecMul precompile, it takes in the following + // [point.x, point.y, scalar], and returns the result back into the free memory location. + let success := staticcall(gas(), 0x07, free, 0x60, free, 0x40) + if iszero(success) { + revert(0, 0) + } + // Copy the result of the multiplication back into the result memory location. + // Memory layout: + // Address | value + // result | result.x + // result + 0x20| result.y + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + + mstore(0x40, add(free, 0x60)) + } + + return result; +} + +/** + * G1 Add + * Takes two G1 points and uses the ecAdd precompile to return the result. + * + * @param lhs The left hand side of the addition. + * @param rhs The right hand side of the addition. + * @return result The result of the addition. + */ +function ecAdd(Honk.G1Point memory lhs, Honk.G1Point memory rhs) view returns (Honk.G1Point memory) { + Honk.G1Point memory result; + + assembly { + let free := mload(0x40) + // Write lhs into memory (two 32 byte words) + // Memory layout: + // Address | value + // free | lhs.x + // free + 0x20| lhs.y + mstore(free, mload(lhs)) + mstore(add(free, 0x20), mload(add(lhs, 0x20))) + + // Write rhs into memory (two 32 byte words) + // Memory layout: + // Address | value + // free + 0x40| rhs.x + // free + 0x60| rhs.y + mstore(add(free, 0x40), mload(rhs)) + mstore(add(free, 0x60), mload(add(rhs, 0x20))) + + // Call the ecAdd precompile, it takes in the following + // [lhs.x, lhs.y, rhs.x, rhs.y], and returns their addition back into the free memory location. + let success := staticcall(gas(), 0x06, free, 0x80, free, 0x40) + if iszero(success) { revert(0, 0) } + + // Copy the result of the addition back into the result memory location. + // Memory layout: + // Address | value + // result | result.x + // result + 0x20| result.y + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + + mstore(0x40, add(free, 0x80)) + } + + return result; +} + +function validateOnCurve(Honk.G1Point memory point) pure { + uint256 x = point.x; + uint256 y = point.y; + + bool success = false; + assembly { + let xx := mulmod(x, x, Q) + success := eq(mulmod(y, y, Q), addmod(mulmod(x, xx, Q), 3, Q)) + } + + require(success, "point is not on the curve"); +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $VK_HASH; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _vkHash, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $VK_HASH = _vkHash; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error ProofLengthWrongWithLogN(uint256 logN, uint256 actualLength, uint256 expectedLength); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Constants for proof length calculation (matching UltraKeccakZKFlavor) + uint256 constant NUM_WITNESS_ENTITIES = 8; + uint256 constant NUM_ELEMENTS_COMM = 2; // uint256 elements for curve points + uint256 constant NUM_ELEMENTS_FR = 1; // uint256 elements for field elements + uint256 constant NUM_LIBRA_EVALUATIONS = 4; // libra evaluations + + // Calculate proof size based on log_n (matching UltraKeccakZKFlavor formula) + function calculateProofSize(uint256 logN) internal pure returns (uint256) { + // Witness and Libra commitments + uint256 proofLength = NUM_WITNESS_ENTITIES * NUM_ELEMENTS_COMM; // witness commitments + proofLength += NUM_ELEMENTS_COMM * 4; // Libra concat, grand sum, quotient comms + Gemini masking + + // Sumcheck + proofLength += logN * ZK_BATCHED_RELATION_PARTIAL_LENGTH * NUM_ELEMENTS_FR; // sumcheck univariates + proofLength += NUMBER_OF_ENTITIES * NUM_ELEMENTS_FR; // sumcheck evaluations + + // Libra and Gemini + proofLength += NUM_ELEMENTS_FR * 3; // Libra sum, claimed eval, Gemini masking eval + proofLength += logN * NUM_ELEMENTS_FR; // Gemini a evaluations + proofLength += NUM_LIBRA_EVALUATIONS * NUM_ELEMENTS_FR; // libra evaluations + + // PCS commitments + proofLength += (logN - 1) * NUM_ELEMENTS_COMM; // Gemini Fold commitments + proofLength += NUM_ELEMENTS_COMM * 2; // Shplonk Q and KZG W commitments + + // Pairing points + proofLength += PAIRING_POINTS_SIZE; // pairing inputs carried on public inputs + + return proofLength; + } + + uint256 constant SHIFTED_COMMITMENTS_START = 30; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Calculate expected proof size based on $LOG_N + uint256 expectedProofSize = calculateProofSize($LOG_N); + + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != expectedProofSize * 32) { + revert ProofLengthWrongWithLogN($LOG_N, proof.length, expectedProofSize * 32); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof, $LOG_N); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = + ZKTranscriptLib.generateTranscript(p, publicInputs, $VK_HASH, $NUM_PUBLIC_INPUTS, $LOG_N); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + uint256 constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28; + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from(PERMUTATION_ARGUMENT_VALUE_SEPARATOR + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + struct PairingInputs { + Honk.G1Point P_0; + Honk.G1Point P_1; + } + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[] memory powers_of_evaluation_challenge = CommitmentSchemeLib.computeSquares(tp.geminiR, $LOG_N); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[] memory scalars = new Fr[](NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3); + Honk.G1Point[] memory commitments = new Honk.G1Point[](NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3); + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = proof.shplonkQ; + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + mem.unshiftedScalarNeg = mem.unshiftedScalar.neg(); + mem.shiftedScalarNeg = mem.shiftedScalar.neg(); + + scalars[1] = mem.unshiftedScalarNeg; + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalarNeg * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + // For each of the to be shifted commitments perform the shift in place by + // adding to the unshifted value. + // We do so, as the values are to be used in batchMul later, and as + // `a * c + b * c = (a + b) * c` this will allow us to reduce memory and compute. + // Applied to w1, w2, w3, w4 and zPerm + for (uint256 i = 0; i < NUMBER_TO_BE_SHIFTED; ++i) { + uint256 scalarOff = i + SHIFTED_COMMITMENTS_START; + uint256 evaluationOff = i + NUMBER_UNSHIFTED; + + scalars[scalarOff] = scalars[scalarOff] + (mem.shiftedScalarNeg * mem.batchingChallenge); + mem.batchedEvaluation = + mem.batchedEvaluation + (proof.sumcheckEvaluations[evaluationOff] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = proof.geminiMaskingPoly; + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = proof.w1; + commitments[31] = proof.w2; + commitments[32] = proof.w3; + commitments[33] = proof.w4; + commitments[34] = proof.zPerm; + commitments[35] = proof.lookupInverses; + commitments[36] = proof.lookupReadCounts; + commitments[37] = proof.lookupReadTags; + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_UNSHIFTED + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < $LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = proof.geminiFoldComms[i]; + } + + boundary += $LOG_N - 1; + + // Finalize the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = proof.libraCommitments[i]; + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = proof.kzgQuotient; + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + PairingInputs memory pair; + pair.P_0 = batchMul(commitments, scalars); + pair.P_1 = negateInplace(quotient_commitment); + + // Aggregate pairing points + Fr recursionSeparator = generateRecursionSeparator(proof.pairingPointObject, pair.P_0, pair.P_1); + (Honk.G1Point memory P_0_other, Honk.G1Point memory P_1_other) = + convertPairingPointsToG1(proof.pairingPointObject); + + // Validate the points from the proof are on the curve + validateOnCurve(P_0_other); + validateOnCurve(P_1_other); + + // accumulate with aggregate points in proof + pair.P_0 = mulWithSeperator(pair.P_0, P_0_other, recursionSeparator); + pair.P_1 = mulWithSeperator(pair.P_1, P_1_other, recursionSeparator); + + return pairing(pair.P_0, pair.P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < $LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul(Honk.G1Point[] memory base, Fr[] memory scalars) + internal + view + returns (Honk.G1Point memory result) + { + uint256 limit = NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3; + + // Validate all points are on the curve + for (uint256 i = 0; i < limit; ++i) { + validateOnCurve(base[i]); + } + + bool success = true; + assembly { + let free := mload(0x40) + + let count := 0x01 + for {} lt(count, add(limit, 1)) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + + require(success, ShpleminiFailed()); + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, VK_HASH, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/noir/agg_final.sol b/eth/noir/agg_final.sol new file mode 100644 index 0000000..7bc781d --- /dev/null +++ b/eth/noir/agg_final.sol @@ -0,0 +1,2435 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 1048576; +uint256 constant LOG_N = 20; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 1019; +uint256 constant VK_HASH = 0x016b9de0462c1d2eb19e66c7f3a664c426e094540f08b0e5587cb3471eeea0dc; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(1048576), + logCircuitSize: uint256(20), + publicInputsSize: uint256(1019), + ql: Honk.G1Point({ + x: uint256(0x16564b9c5794a0940a9bdb105356d4d8e7c0d2ed04fb7fe3b82e32fe70ad7976), + y: uint256(0x19f4325229ca1f419b897a9286a396923b26592fb85e1fad1e5db7b8afaa4b73) + }), + qr: Honk.G1Point({ + x: uint256(0x08a7d8009f6f264dac2833251dc17269967029b78cdacd33104a8f8fdb79c940), + y: uint256(0x196750fb121848a766033747e726bdb19a4a957a483edb24f45cdf4a6abce4ad) + }), + qo: Honk.G1Point({ + x: uint256(0x2668a86828ec16a70fe3c30a353eee037c19f470e1e5a2586eb47e9a3372fe31), + y: uint256(0x13a5d44fce53d20af70a40f3c33ca60a1eab4a2907b9f74374a00099af5b308f) + }), + q4: Honk.G1Point({ + x: uint256(0x05e267528bcdaaef76b87581271c147470268de2e8b9201a79a4ab9ff483c742), + y: uint256(0x07114abaa67e3fd05d43b93d42f36cc0f650ef8f0fed3613294cc820fd8718e9) + }), + qm: Honk.G1Point({ + x: uint256(0x07fea1a154c2ea92bfe9bff6608105c79be2000fb533c5a7f5086f42631d0024), + y: uint256(0x072a7fa47c0445d4a3a00a17126f3d4134c5ddf94ff72fe262c3c2d36017ce54) + }), + qc: Honk.G1Point({ + x: uint256(0x0eaf0f335934fe83217bf228608474b6e7874844976d3f606546efdabe85198e), + y: uint256(0x2fd2b3710e51885e05066c12c867b19f6abfedb1329bd4b34c51e4edae010ed1) + }), + qLookup: Honk.G1Point({ + x: uint256(0x15b5b0e5904efcadcef0d9c7305e0c778692a7b2f9f210b9104c213daea659a8), + y: uint256(0x0e24f0b634a1648112578318c5455cd09fb98da9822306ea7c65dc48db697ea4) + }), + qArith: Honk.G1Point({ + x: uint256(0x17846b41619ecf9273cf386c1b16e7f55fa35ec9386eb2ea216398f428379e79), + y: uint256(0x1ac6fe092563d4e89b104cfafada05910ea6e0c0cdd0b0fd5cc58f1fad65f5d1) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x05665cdccbda0515ceebf81f09c44fdb329181de80055bbd4249751c80280dbf), + y: uint256(0x21286c7bbb9d4894157e2975e667d5c33e910f985863d681880648677502133f) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x0d046a2c7f903da415a6951e75a5381b70a0331b790c07b97ce70d34d338a72b), + y: uint256(0x26b1f648f365eb5cbbe4c6e3244537dacfbbf95845bc38ec6895d8abbc027526) + }), + qMemory: Honk.G1Point({ + x: uint256(0x2d2e9b5315b13f26465f33617d15b566e8d9eb9db7f2620b6fc80fa1f006fc51), + y: uint256(0x28dd92658fa8222aef67475960ab7033a2da3b6622b2e18094deb5718ff2ea71) + }), + qNnf: Honk.G1Point({ + x: uint256(0x2130ca557da2368a359901856d4fb658e39384a611b8ff226a0a6e4492f59118), + y: uint256(0x2ff59ab4fd220200b24946eedcd14d61acb5dd2499e6f89294af9bce971825fc) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x16bfc1cbd0c6a38e201686891975e2d3a32ff2ea3e0d298a7f6b9ac55d8228cd), + y: uint256(0x0ba7b53a836f4bf89f64e9d0ce2cb1b81b63e81589774004339507f0e8fb0720) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x1dae1d5fb23ef041ac8fb25b5739ff333f941a02cf543839aa68595bed009241), + y: uint256(0x10479380fe8d144a5e6ceec04c2271346324d911e80bbd685ccb3e5ab65bdfb5) + }), + s1: Honk.G1Point({ + x: uint256(0x208e191dd65dfe84d1c782de58d6049c6cf080e0d85998d9306385a148250a6d), + y: uint256(0x0254a28372e909a029e4189c42716805e9b0db5ce5b97eb7060b25472e669fc5) + }), + s2: Honk.G1Point({ + x: uint256(0x1647261d35e5226996c3fe13de83b2a3c2d7ff1d5c94d42d5cec74c5862656d1), + y: uint256(0x2d40aad6d8245b190e2b45686ca05da2595be9e7483c75b9bcab335fd51941bc) + }), + s3: Honk.G1Point({ + x: uint256(0x1dfe547a651f077f580970260f0593e146c55e3874adbdc347a5039b32024d7a), + y: uint256(0x2e5aa258ca6b4863370ae82df32001c1b0c363b72ff4e2503adf731fd3502d4b) + }), + s4: Honk.G1Point({ + x: uint256(0x284788e2b69fcabd417414a25ba458b5a37a7d37fea6fb298e124146e86921e4), + y: uint256(0x15cdd6ac38bbaf22615366da36733cc939e5fe95efbf3321e577df4ff7fca877) + }), + t1: Honk.G1Point({ + x: uint256(0x111bc3039becaa8ca62f0bcefcd65040fe1d5bc68e929318b3f5dd767ce9822b), + y: uint256(0x1b691e6fe2d651e8c02ab30d0b5f032addd00bbe41104a7206e2ff9d7b658a3d) + }), + t2: Honk.G1Point({ + x: uint256(0x0a0a54df61fecb42534ccfd8d51ee000e269a65d07d5b63227459ba189ab2f04), + y: uint256(0x09276e284d9fcacc3201e71f779a6e66950841c2324d970c8bb2f8d6c87755e7) + }), + t3: Honk.G1Point({ + x: uint256(0x110e7b7f4053452dae6c6d52983ed4f268823e7c2958a2967f35178675092a29), + y: uint256(0x29df570d178d1f2aa52fd2669fd347d2d75a722175e050c90fbb00adb5d82d2f) + }), + t4: Honk.G1Point({ + x: uint256(0x1326d49efee0292517ce6bfbacd193969a5cb9ce2cd571cb6426f56009b82085), + y: uint256(0x176a9c71e742c7798aea8f5e828ece04efa2abe35b8c33eff8c74ac1fafbb2de) + }), + id1: Honk.G1Point({ + x: uint256(0x2e62626a1095231a41bdc000c7bd20c073919d40ccb4d9a36d1629902b061fcb), + y: uint256(0x21305733d27ee6dab8c79607a8e8462df373b5f5d7429e78b62363e0ef71df95) + }), + id2: Honk.G1Point({ + x: uint256(0x076dc9c7790ed478259153d69811573276e6d26536b485d4d82977c330485ac8), + y: uint256(0x2fbfea486a89022680b0e0e81ead9c56125b0066007326944a5ad05665928fcb) + }), + id3: Honk.G1Point({ + x: uint256(0x1552b3c8a793524d496ac086b1c182575ad9a3249ba1aafb30110615712b8d37), + y: uint256(0x0f68500204cd7693fd5e1f8b490c74dd7a1e556d2bad5782731d3eb4b8904147) + }), + id4: Honk.G1Point({ + x: uint256(0x10ad68cb78329a5c44b13c6da53ccc16b2bdf8cc6b955161f7f6676abfa050cb), + y: uint256(0x2643eef532153fc9853f9257031440654d9c2482299ab424ad953b72a1fdb7ae) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x2f6ae80f550fc0a26f347268c7d0617869a16b8600d893ffce5e6d1dd8a010cd), + y: uint256(0x0e64b747f724eb59221c9dec8a24b86a785fbab2feacfc82000733d2ef85d82b) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + unchecked { + return Fr.wrap(value % MODULUS); + } + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + unchecked { + return Fr.wrap(uint256(value) % MODULUS); + } + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + unchecked { + return bytes32(Fr.unwrap(value)); + } + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + mstore(0x40, add(free, 0x80)) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + mstore(0x40, add(free, 0x80)) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + unchecked { + return numerator * invert(denominator); + } + } + + function sqr(Fr value) internal pure returns (Fr) { + unchecked { + return value * value; + } + } + + function unwrap(Fr value) internal pure returns (uint256) { + unchecked { + return Fr.unwrap(value); + } + } + + function neg(Fr value) internal pure returns (Fr) { + unchecked { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + unchecked { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); + } +} + +function mul(Fr a, Fr b) pure returns (Fr) { + unchecked { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); + } +} + +function sub(Fr a, Fr b) pure returns (Fr) { + unchecked { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); + } +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + unchecked { + return Fr.unwrap(a) != Fr.unwrap(b); + } +} + +function equal(Fr a, Fr b) pure returns (bool) { + unchecked { + return Fr.unwrap(a) == Fr.unwrap(b); + } +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +uint256 constant FIELD_ELEMENT_SIZE = 0x20; +uint256 constant GROUP_ELEMENT_SIZE = 0x40; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + G1Point w1; + G1Point w2; + G1Point w3; + G1Point w4; + // Lookup helpers - Permutations + G1Point zPerm; + // Lookup helpers - logup + G1Point lookupReadCounts; + G1Point lookupReadTags; + G1Point lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + G1Point shplonkQ; + G1Point kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + G1Point w1; + G1Point w2; + G1Point w3; + G1Point w4; + // Commitments to logup witness polynomials + G1Point lookupReadCounts; + G1Point lookupReadTags; + G1Point lookupInverses; + // Commitment to grand permutation polynomial + G1Point zPerm; + G1Point[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + G1Point geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + G1Point[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + G1Point shplonkQ; + G1Point kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 vkHash, + uint256 publicInputsSize, + uint256 logN + ) external pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = + generateRelationParametersChallenges(proof, publicInputs, vkHash, publicInputsSize, previousChallenge); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge, logN); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge, logN); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge, logN); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge, logN); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 vkHash, + uint256 publicInputsSize, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, vkHash, publicInputsSize); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 vkHash, + uint256 publicInputsSize + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](1 + publicInputsSize + 6); + round0[0] = bytes32(vkHash); + + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[1 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[1 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[1 + publicInputsSize] = bytes32(proof.w1.x); + round0[1 + publicInputsSize + 1] = bytes32(proof.w1.y); + round0[1 + publicInputsSize + 2] = bytes32(proof.w2.x); + round0[1 + publicInputsSize + 3] = bytes32(proof.w2.y); + round0[1 + publicInputsSize + 4] = bytes32(proof.w3.x); + round0[1 + publicInputsSize + 5] = bytes32(proof.w3.y); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[7] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x); + round1[2] = bytes32(proof.lookupReadCounts.y); + round1[3] = bytes32(proof.lookupReadTags.x); + round1[4] = bytes32(proof.lookupReadTags.y); + round1[5] = bytes32(proof.w4.x); + round1[6] = bytes32(proof.w4.y); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[5] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x; + alpha0[2] = proof.lookupInverses.y; + alpha0[3] = proof.zPerm.x; + alpha0[4] = proof.zPerm.y; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + Fr alpha; + (alpha,) = splitChallenge(nextPreviousChallenge); + + // Compute powers of alpha for batching subrelations + alphas[0] = alpha; + for (uint256 i = 1; i < NUMBER_OF_ALPHAS; i++) { + alphas[i] = alphas[i - 1] * alpha; + } + } + + function generateGateChallenges(Fr previousChallenge, uint256 logN) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + (gateChallenges[0],) = splitChallenge(previousChallenge); + for (uint256 i = 1; i < logN; i++) { + gateChallenges[i] = gateChallenges[i - 1] * gateChallenges[i - 1]; + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 2 comm, 1 sum, 1 challenge + uint256[4] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x; + challengeData[2] = proof.libraCommitments[0].y; + challengeData[3] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge, uint256 logN) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < logN; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 9] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].y; + i += 2; + rhoChallengeElements[i] = proof.libraCommitments[2].x; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].y; + i += 2; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.y; + + i += 2; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge, uint256 logN) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[] memory gR = new uint256[]((logN - 1) * 2 + 1); + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < logN - 1; i++) { + gR[1 + i * 2] = proof.geminiFoldComms[i].x; + gR[2 + i * 2] = proof.geminiFoldComms[i].y; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge, uint256 logN) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[] memory shplonkNuChallengeElements = new uint256[](logN + 1 + 4); + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= logN; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = logN + 1; i <= logN + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[3] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x; + shplonkZChallengeElements[2] = proof.shplonkQ.y; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof, uint256 logN) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + // Commitments + p.w1 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.w2 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.w3 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.lookupReadTags = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.w4 = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.lookupInverses = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.zPerm = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.libraCommitments[0] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + + p.libraSum = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + // Sumcheck univariates + for (uint256 i = 0; i < logN; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + + p.libraCommitments[1] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.libraCommitments[2] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.geminiMaskingPoly = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < logN - 1; i++) { + p.geminiFoldComms[i] = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < logN; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + FIELD_ELEMENT_SIZE]); + boundary += FIELD_ELEMENT_SIZE; + } + + // Shplonk + p.shplonkQ = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + boundary += GROUP_ELEMENT_SIZE; + // KZG + p.kzgQuotient = bytesToG1Point(proof[boundary:boundary + GROUP_ELEMENT_SIZE]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * (ap.index_delta - Fr.wrap(1)); // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * (access_type - Fr.wrap(1)); // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_O)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_O)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + Fr unshiftedScalarNeg; + Fr shiftedScalarNeg; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[] foldPosEvaluations; + } + + function computeSquares(Fr r, uint256 logN) internal pure returns (Fr[] memory) { + Fr[] memory squares = new Fr[](logN); + squares[0] = r; + for (uint256 i = 1; i < logN; ++i) { + squares[i] = squares[i - 1].sqr(); + } + return squares; + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[] memory) { + Fr[] memory foldPosEvaluations = new Fr[](logSize); + for (uint256 i = logSize; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + return foldPosEvaluations; + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities +function bytesToG1Point(bytes calldata proofSection) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({ + x: uint256(bytes32(proofSection[0x00:0x20])) % Q, + y: uint256(bytes32(proofSection[0x20:0x40])) % Q + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +/** + * Convert the pairing points to G1 points. + * + * The pairing points are serialised as an array of 68 bit limbs representing two points + * The lhs of a pairing operation and the rhs of a pairing operation + * + * There are 4 fields for each group element, leaving 8 fields for each side of the pairing. + * + * @param pairingPoints The pairing points to convert. + * @return lhs + * @return rhs + */ +function convertPairingPointsToG1(Fr[PAIRING_POINTS_SIZE] memory pairingPoints) + pure + returns (Honk.G1Point memory lhs, Honk.G1Point memory rhs) +{ + uint256 lhsX = Fr.unwrap(pairingPoints[0]); + lhsX |= Fr.unwrap(pairingPoints[1]) << 68; + lhsX |= Fr.unwrap(pairingPoints[2]) << 136; + lhsX |= Fr.unwrap(pairingPoints[3]) << 204; + lhs.x = lhsX; + + uint256 lhsY = Fr.unwrap(pairingPoints[4]); + lhsY |= Fr.unwrap(pairingPoints[5]) << 68; + lhsY |= Fr.unwrap(pairingPoints[6]) << 136; + lhsY |= Fr.unwrap(pairingPoints[7]) << 204; + lhs.y = lhsY; + + uint256 rhsX = Fr.unwrap(pairingPoints[8]); + rhsX |= Fr.unwrap(pairingPoints[9]) << 68; + rhsX |= Fr.unwrap(pairingPoints[10]) << 136; + rhsX |= Fr.unwrap(pairingPoints[11]) << 204; + rhs.x = rhsX; + + uint256 rhsY = Fr.unwrap(pairingPoints[12]); + rhsY |= Fr.unwrap(pairingPoints[13]) << 68; + rhsY |= Fr.unwrap(pairingPoints[14]) << 136; + rhsY |= Fr.unwrap(pairingPoints[15]) << 204; + rhs.y = rhsY; +} + +/** + * Hash the pairing inputs from the present verification context with those extracted from the public inputs. + * + * @param proofPairingPoints Pairing points from the proof - (public inputs). + * @param accLhs Accumulator point for the left side - result of shplemini. + * @param accRhs Accumulator point for the right side - result of shplemini. + * @return recursionSeparator The recursion separator - generated from hashing the above. + */ +function generateRecursionSeparator( + Fr[PAIRING_POINTS_SIZE] memory proofPairingPoints, + Honk.G1Point memory accLhs, + Honk.G1Point memory accRhs +) pure returns (Fr recursionSeparator) { + // hash the proof aggregated X + // hash the proof aggregated Y + // hash the accum X + // hash the accum Y + + (Honk.G1Point memory proofLhs, Honk.G1Point memory proofRhs) = convertPairingPointsToG1(proofPairingPoints); + + uint256[8] memory recursionSeparatorElements; + + // Proof points + recursionSeparatorElements[0] = proofLhs.x; + recursionSeparatorElements[1] = proofLhs.y; + recursionSeparatorElements[2] = proofRhs.x; + recursionSeparatorElements[3] = proofRhs.y; + + // Accumulator points + recursionSeparatorElements[4] = accLhs.x; + recursionSeparatorElements[5] = accLhs.y; + recursionSeparatorElements[6] = accRhs.x; + recursionSeparatorElements[7] = accRhs.y; + + recursionSeparator = FrLib.fromBytes32(keccak256(abi.encodePacked(recursionSeparatorElements))); +} + +/** + * G1 Mul with Separator + * Using the ecAdd and ecMul precompiles + * + * @param basePoint The point to multiply. + * @param other The other point to add. + * @param recursionSeperator The separator to use for the multiplication. + * @return `(recursionSeperator * basePoint) + other`. + */ +function mulWithSeperator(Honk.G1Point memory basePoint, Honk.G1Point memory other, Fr recursionSeperator) + view + returns (Honk.G1Point memory) +{ + Honk.G1Point memory result; + + result = ecMul(recursionSeperator, basePoint); + result = ecAdd(result, other); + + return result; +} + +/** + * G1 Mul + * Takes a Fr value and a G1 point and uses the ecMul precompile to return the result. + * + * @param value The value to multiply the point by. + * @param point The point to multiply. + * @return result The result of the multiplication. + */ +function ecMul(Fr value, Honk.G1Point memory point) view returns (Honk.G1Point memory) { + Honk.G1Point memory result; + + assembly { + let free := mload(0x40) + // Write the point into memory (two 32 byte words) + // Memory layout: + // Address | value + // free | point.x + // free + 0x20| point.y + mstore(free, mload(point)) + mstore(add(free, 0x20), mload(add(point, 0x20))) + // Write the scalar into memory (one 32 byte word) + // Memory layout: + // Address | value + // free + 0x40| value + mstore(add(free, 0x40), value) + + // Call the ecMul precompile, it takes in the following + // [point.x, point.y, scalar], and returns the result back into the free memory location. + let success := staticcall(gas(), 0x07, free, 0x60, free, 0x40) + if iszero(success) { + revert(0, 0) + } + // Copy the result of the multiplication back into the result memory location. + // Memory layout: + // Address | value + // result | result.x + // result + 0x20| result.y + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + + mstore(0x40, add(free, 0x60)) + } + + return result; +} + +/** + * G1 Add + * Takes two G1 points and uses the ecAdd precompile to return the result. + * + * @param lhs The left hand side of the addition. + * @param rhs The right hand side of the addition. + * @return result The result of the addition. + */ +function ecAdd(Honk.G1Point memory lhs, Honk.G1Point memory rhs) view returns (Honk.G1Point memory) { + Honk.G1Point memory result; + + assembly { + let free := mload(0x40) + // Write lhs into memory (two 32 byte words) + // Memory layout: + // Address | value + // free | lhs.x + // free + 0x20| lhs.y + mstore(free, mload(lhs)) + mstore(add(free, 0x20), mload(add(lhs, 0x20))) + + // Write rhs into memory (two 32 byte words) + // Memory layout: + // Address | value + // free + 0x40| rhs.x + // free + 0x60| rhs.y + mstore(add(free, 0x40), mload(rhs)) + mstore(add(free, 0x60), mload(add(rhs, 0x20))) + + // Call the ecAdd precompile, it takes in the following + // [lhs.x, lhs.y, rhs.x, rhs.y], and returns their addition back into the free memory location. + let success := staticcall(gas(), 0x06, free, 0x80, free, 0x40) + if iszero(success) { revert(0, 0) } + + // Copy the result of the addition back into the result memory location. + // Memory layout: + // Address | value + // result | result.x + // result + 0x20| result.y + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + + mstore(0x40, add(free, 0x80)) + } + + return result; +} + +function validateOnCurve(Honk.G1Point memory point) pure { + uint256 x = point.x; + uint256 y = point.y; + + bool success = false; + assembly { + let xx := mulmod(x, x, Q) + success := eq(mulmod(y, y, Q), addmod(mulmod(x, xx, Q), 3, Q)) + } + + require(success, "point is not on the curve"); +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $VK_HASH; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _vkHash, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $VK_HASH = _vkHash; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error ProofLengthWrongWithLogN(uint256 logN, uint256 actualLength, uint256 expectedLength); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Constants for proof length calculation (matching UltraKeccakZKFlavor) + uint256 constant NUM_WITNESS_ENTITIES = 8; + uint256 constant NUM_ELEMENTS_COMM = 2; // uint256 elements for curve points + uint256 constant NUM_ELEMENTS_FR = 1; // uint256 elements for field elements + uint256 constant NUM_LIBRA_EVALUATIONS = 4; // libra evaluations + + // Calculate proof size based on log_n (matching UltraKeccakZKFlavor formula) + function calculateProofSize(uint256 logN) internal pure returns (uint256) { + // Witness and Libra commitments + uint256 proofLength = NUM_WITNESS_ENTITIES * NUM_ELEMENTS_COMM; // witness commitments + proofLength += NUM_ELEMENTS_COMM * 4; // Libra concat, grand sum, quotient comms + Gemini masking + + // Sumcheck + proofLength += logN * ZK_BATCHED_RELATION_PARTIAL_LENGTH * NUM_ELEMENTS_FR; // sumcheck univariates + proofLength += NUMBER_OF_ENTITIES * NUM_ELEMENTS_FR; // sumcheck evaluations + + // Libra and Gemini + proofLength += NUM_ELEMENTS_FR * 3; // Libra sum, claimed eval, Gemini masking eval + proofLength += logN * NUM_ELEMENTS_FR; // Gemini a evaluations + proofLength += NUM_LIBRA_EVALUATIONS * NUM_ELEMENTS_FR; // libra evaluations + + // PCS commitments + proofLength += (logN - 1) * NUM_ELEMENTS_COMM; // Gemini Fold commitments + proofLength += NUM_ELEMENTS_COMM * 2; // Shplonk Q and KZG W commitments + + // Pairing points + proofLength += PAIRING_POINTS_SIZE; // pairing inputs carried on public inputs + + return proofLength; + } + + uint256 constant SHIFTED_COMMITMENTS_START = 30; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Calculate expected proof size based on $LOG_N + uint256 expectedProofSize = calculateProofSize($LOG_N); + + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != expectedProofSize * 32) { + revert ProofLengthWrongWithLogN($LOG_N, proof.length, expectedProofSize * 32); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof, $LOG_N); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = + ZKTranscriptLib.generateTranscript(p, publicInputs, $VK_HASH, $NUM_PUBLIC_INPUTS, $LOG_N); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + uint256 constant PERMUTATION_ARGUMENT_VALUE_SEPARATOR = 1 << 28; + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from(PERMUTATION_ARGUMENT_VALUE_SEPARATOR + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + struct PairingInputs { + Honk.G1Point P_0; + Honk.G1Point P_1; + } + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[] memory powers_of_evaluation_challenge = CommitmentSchemeLib.computeSquares(tp.geminiR, $LOG_N); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[] memory scalars = new Fr[](NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3); + Honk.G1Point[] memory commitments = new Honk.G1Point[](NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3); + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = proof.shplonkQ; + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + mem.unshiftedScalarNeg = mem.unshiftedScalar.neg(); + mem.shiftedScalarNeg = mem.shiftedScalar.neg(); + + scalars[1] = mem.unshiftedScalarNeg; + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalarNeg * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + // For each of the to be shifted commitments perform the shift in place by + // adding to the unshifted value. + // We do so, as the values are to be used in batchMul later, and as + // `a * c + b * c = (a + b) * c` this will allow us to reduce memory and compute. + // Applied to w1, w2, w3, w4 and zPerm + for (uint256 i = 0; i < NUMBER_TO_BE_SHIFTED; ++i) { + uint256 scalarOff = i + SHIFTED_COMMITMENTS_START; + uint256 evaluationOff = i + NUMBER_UNSHIFTED; + + scalars[scalarOff] = scalars[scalarOff] + (mem.shiftedScalarNeg * mem.batchingChallenge); + mem.batchedEvaluation = + mem.batchedEvaluation + (proof.sumcheckEvaluations[evaluationOff] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = proof.geminiMaskingPoly; + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = proof.w1; + commitments[31] = proof.w2; + commitments[32] = proof.w3; + commitments[33] = proof.w4; + commitments[34] = proof.zPerm; + commitments[35] = proof.lookupInverses; + commitments[36] = proof.lookupReadCounts; + commitments[37] = proof.lookupReadTags; + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_UNSHIFTED + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < $LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = proof.geminiFoldComms[i]; + } + + boundary += $LOG_N - 1; + + // Finalize the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = proof.libraCommitments[i]; + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = proof.kzgQuotient; + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + PairingInputs memory pair; + pair.P_0 = batchMul(commitments, scalars); + pair.P_1 = negateInplace(quotient_commitment); + + // Aggregate pairing points + Fr recursionSeparator = generateRecursionSeparator(proof.pairingPointObject, pair.P_0, pair.P_1); + (Honk.G1Point memory P_0_other, Honk.G1Point memory P_1_other) = + convertPairingPointsToG1(proof.pairingPointObject); + + // Validate the points from the proof are on the curve + validateOnCurve(P_0_other); + validateOnCurve(P_1_other); + + // accumulate with aggregate points in proof + pair.P_0 = mulWithSeperator(pair.P_0, P_0_other, recursionSeparator); + pair.P_1 = mulWithSeperator(pair.P_1, P_1_other, recursionSeparator); + + return pairing(pair.P_0, pair.P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < $LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul(Honk.G1Point[] memory base, Fr[] memory scalars) + internal + view + returns (Honk.G1Point memory result) + { + uint256 limit = NUMBER_UNSHIFTED + $LOG_N + LIBRA_COMMITMENTS + 3; + + // Validate all points are on the curve + for (uint256 i = 0; i < limit; ++i) { + validateOnCurve(base[i]); + } + + bool success = true; + assembly { + let free := mload(0x40) + + let count := 0x01 + for {} lt(count, add(limit, 1)) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + + require(success, ShpleminiFailed()); + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, VK_HASH, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/noir/agg_utxo.sol b/eth/noir/agg_utxo.sol new file mode 100644 index 0000000..bf41bcf --- /dev/null +++ b/eth/noir/agg_utxo.sol @@ -0,0 +1,2186 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 4194304; +uint256 constant LOG_N = 22; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 1021; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(4194304), + logCircuitSize: uint256(22), + publicInputsSize: uint256(1021), + ql: Honk.G1Point({ + x: uint256(0x1e92276c08c16eb972a2959bac535e88df13e7594f1813a84def10c360b7a926), + y: uint256(0x072b503854fc952a8eb7d6271b5706840c6c43eea9a307791ef6a30ee353a106) + }), + qr: Honk.G1Point({ + x: uint256(0x212a722bb14e935b0edd1ee3faa6a942f5af6d0e3754d247408bf5a328e03dfe), + y: uint256(0x1eb78cf7ac2aa5cc572af3c8f488be055ca044259967557b732c3fa69a0fcbfc) + }), + qo: Honk.G1Point({ + x: uint256(0x0b728cff45572c9721d6062fd9e62511ae4cd5449990b74b6558f9b847141d49), + y: uint256(0x141db89d3a55f5d1af2755e6baeeb1a4d1e0df407d3a3b423e5fbe897cd182e2) + }), + q4: Honk.G1Point({ + x: uint256(0x2de8a69ebfa857df817e95a849a45484d8e51cb72639b9f18b22d5bbe789ef53), + y: uint256(0x160aaa6e8be8ff6c17a8b01c38f813a6bab6b963f276fb76a0b4804a7714f467) + }), + qm: Honk.G1Point({ + x: uint256(0x076b6b98a7b2dad658c00065f9993d8ccfd6a18c2613aa902785e0b352c4a1e0), + y: uint256(0x2f382c824a5ca2d916dc27484dad66bf3b09466194734b0dc7cf613c84d9473b) + }), + qc: Honk.G1Point({ + x: uint256(0x2d2e7bd39f247c1b0223b33574b62df5c34c5bcd2e76d14c018cafb76c8da878), + y: uint256(0x06dee0d594d2adcfa84124d61f46f08188941e50144e4ff1e6ceda5736c9cffa) + }), + qLookup: Honk.G1Point({ + x: uint256(0x14dd1ce931af2f1a008cdb4e13fcb4bb5f3adb8b1a360885d949225f796e05a2), + y: uint256(0x11a7654358d84ce23eb3f3714bc52d36efffbc6387a0d74ed1271a8ce1566b7d) + }), + qArith: Honk.G1Point({ + x: uint256(0x15654ba45991c566868445c6d3ad56a72788593afa68d3f6fae02fb4cb0afb54), + y: uint256(0x223e57a0168b7ad3fc2cf73cbad83c16e215ee899522b971c896ac5cb4eb55db) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x110d8d4eb8bc850d783fa85804225ff4ca8688dac3140eefcfc158374b45c61a), + y: uint256(0x08ce585e328c2e120db64a705ee2587a7451e755f44ab6cb9482382cc70f1a5f) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x12bcf4350e9ed4b3bf099f3e9026cde938358f44b5a353ee8ea94d4c219ee9e6), + y: uint256(0x1f2057108bb2a12131794c7991be14a67e63fe048fa02be89fc3e130d207aa19) + }), + qMemory: Honk.G1Point({ + x: uint256(0x096f107999d7bed1930b6aa8664635b7a4f5210757f4a03daa0b37acbbfbe183), + y: uint256(0x236883e4bed711163bef46a840bd3a9db617350b9d6c345a1d79a56a3ee41ce8) + }), + qNnf: Honk.G1Point({ + x: uint256(0x0cc5faf916af695883293c1e6e7490db00dfa2295eb0713ae89c91a2ec573a01), + y: uint256(0x0c4150ae9b7d89358cf5ba57f65452f6fc3f1df3a77c88718643f03611ea8448) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x2733aada77ca6b235db92d136a081b580f48cab6785de5a8b0544ea5bcfe865b), + y: uint256(0x1ff8d664a7700688c6d3d371442e56f5b73f2c9280d3703ce10df654949ca009) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x05d9f6de2bf6a206ef38b2c3fe604693273a4d8afb5ba0d0b315fb82b68796e1), + y: uint256(0x2df9541e6a8a908fad158631d9726fa8c66ce33d68929facf1ada95192565219) + }), + s1: Honk.G1Point({ + x: uint256(0x25f5510fe5d4152bd9599bab4fb3417af98c6dcdf52412b6708e37be05fc56b0), + y: uint256(0x1616c753acea71275e0716583d2d785f4e91018c9530dba0593c0830b9741efa) + }), + s2: Honk.G1Point({ + x: uint256(0x12d351a5e045527f3c45bb5da2ed3a73c53d4d9858d7d257d4e2fcb7aaf6cd2f), + y: uint256(0x08268516bab656b775fda8802b8f5cae2dd412b9b44e24c31aaec24f23bc1625) + }), + s3: Honk.G1Point({ + x: uint256(0x07b078d567880685eef7e65090d38b734c19fac8b3afc2fcb501801c31a0c85f), + y: uint256(0x2b62bbeb9a0796b4228e7cd4b435a7e012d0eb09772efb4421a8b098f7a0e32f) + }), + s4: Honk.G1Point({ + x: uint256(0x037bae72875ce47548a179ffb789de392c13661962b6e3c515e1ce6fe310c4df), + y: uint256(0x2e9ec6afe4d4c0738957a36b662da4af988c2e4fb7b1a5357284165230dc3c59) + }), + t1: Honk.G1Point({ + x: uint256(0x041b4073446b5892dd7eabf545028e2a1ca163046e9d0415b0ba9d9c4632f07b), + y: uint256(0x005d24fbb51390fb1488b82145f51418573a8cb7efc197b5371780de35eb55de) + }), + t2: Honk.G1Point({ + x: uint256(0x0a58ab84bec6105d9533d7b52c7d46be862a90b3a83a75d1073b4235299d88d2), + y: uint256(0x072b71091d1ef407e20d0d0cd1689c67f3b2aebec2b7b606d0d11e571da53cf7) + }), + t3: Honk.G1Point({ + x: uint256(0x2a5ae466600e63a883fa63c745242ee0f74c8edc3b8b0779968d0fe68a1ef941), + y: uint256(0x13bf890921b82da4e5e10b68b629ed6d8113988330f33c4d52307544a3748c31) + }), + t4: Honk.G1Point({ + x: uint256(0x2141cda9c7a8779c338b16176c47d8b75e5f1b657d31d571204511d018db5e63), + y: uint256(0x029ef7d95d44f73300dfdc5d1f7857dfb867822f826d7f1bae92c942bc587396) + }), + id1: Honk.G1Point({ + x: uint256(0x1b681d0fae6769eb90e514a6e37dac36449699ca27a001a6773c4561424a0897), + y: uint256(0x01b9d462b0d3d90927fbe4abec8e052666d4178b558a59636690e5ae1d13c8ba) + }), + id2: Honk.G1Point({ + x: uint256(0x1df4c3978b9968f362feefeab5199c81ef623e1f7b51f7029d68ab4d8261b266), + y: uint256(0x2b5f43286ad428b083314b004f0730f8992a3b6c820c8289c183f81c33d6ead8) + }), + id3: Honk.G1Point({ + x: uint256(0x19d511fc385f495c4c221a54a2a48ba00e3df0fe05d2a10fec168a7f5635793b), + y: uint256(0x0af2f09d90f83392148ea0736aa368e05baff213cd9a2454e5b84e5282f8e4f4) + }), + id4: Honk.G1Point({ + x: uint256(0x2181a190d8a5229715cf949bc3d0d19bfb6b9d27882950928f30746207f5df57), + y: uint256(0x185917d0f7c49f8054ffe96479cb3649fe7a9ac163240c1d2371670adef58352) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x1e1eef1361c85ac402afd166e5d2f65ca5c1b6d21e17efdf40fdf7ab889c3bf7), + y: uint256(0x010a1a1054ede88dc3780ddfec4d541aee3c01971b648904cab290e196c3217d) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + return Fr.wrap(value % MODULUS); + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + return Fr.wrap(uint256(value) % MODULUS); + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + return bytes32(Fr.unwrap(value)); + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + return numerator * invert(denominator); + } + + function sqr(Fr value) internal pure returns (Fr) { + return value * value; + } + + function unwrap(Fr value) internal pure returns (uint256) { + return Fr.unwrap(value); + } + + function neg(Fr value) internal pure returns (Fr) { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function mul(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function sub(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) != Fr.unwrap(b); +} + +function equal(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) == Fr.unwrap(b); +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct G1ProofPoint { + uint256 x_0; + uint256 x_1; + uint256 y_0; + uint256 y_1; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Lookup helpers - Permutations + Honk.G1ProofPoint zPerm; + // Lookup helpers - logup + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Commitments to logup witness polynomials + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Commitment to grand permutation polynomial + Honk.G1ProofPoint zPerm; + Honk.G1ProofPoint[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + Honk.G1ProofPoint geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( + proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + ); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); + round0[0] = bytes32(circuitSize); + round0[1] = bytes32(publicInputsSize); + round0[2] = bytes32(pubInputsOffset); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[3 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[13] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x_0); + round1[2] = bytes32(proof.lookupReadCounts.x_1); + round1[3] = bytes32(proof.lookupReadCounts.y_0); + round1[4] = bytes32(proof.lookupReadCounts.y_1); + round1[5] = bytes32(proof.lookupReadTags.x_0); + round1[6] = bytes32(proof.lookupReadTags.x_1); + round1[7] = bytes32(proof.lookupReadTags.y_0); + round1[8] = bytes32(proof.lookupReadTags.y_1); + round1[9] = bytes32(proof.w4.x_0); + round1[10] = bytes32(proof.w4.x_1); + round1[11] = bytes32(proof.w4.y_0); + round1[12] = bytes32(proof.w4.y_1); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[9] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x_0; + alpha0[2] = proof.lookupInverses.x_1; + alpha0[3] = proof.lookupInverses.y_0; + alpha0[4] = proof.lookupInverses.y_1; + alpha0[5] = proof.zPerm.x_0; + alpha0[6] = proof.zPerm.x_1; + alpha0[7] = proof.zPerm.y_0; + alpha0[8] = proof.zPerm.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); + + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + + (alphas[NUMBER_OF_ALPHAS - 1],) = splitChallenge(nextPreviousChallenge); + } + } + + function generateGateChallenges(Fr previousChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (gateChallenges[i],) = splitChallenge(previousChallenge); + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 4 comm, 1 sum, 1 challenge + uint256[6] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x_0; + challengeData[2] = proof.libraCommitments[0].x_1; + challengeData[3] = proof.libraCommitments[0].y_0; + challengeData[4] = proof.libraCommitments[0].y_1; + challengeData[5] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 15] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[1].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[1].y_1; + i += 4; + rhoChallengeElements[i] = proof.libraCommitments[2].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[2].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[2].y_1; + i += 4; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x_0; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.x_1; + rhoChallengeElements[i + 2] = proof.geminiMaskingPoly.y_0; + rhoChallengeElements[i + 3] = proof.geminiMaskingPoly.y_1; + + i += 4; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR; + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + gR[1 + i * 4] = proof.geminiFoldComms[i].x_0; + gR[2 + i * 4] = proof.geminiFoldComms[i].x_1; + gR[3 + i * 4] = proof.geminiFoldComms[i].y_0; + gR[4 + i * 4] = proof.geminiFoldComms[i].y_1; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N) + 1 + 4] memory shplonkNuChallengeElements; + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= CONST_PROOF_SIZE_LOG_N; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = CONST_PROOF_SIZE_LOG_N + 1; i <= CONST_PROOF_SIZE_LOG_N + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[5] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x_0; + shplonkZChallengeElements[2] = proof.shplonkQ.x_1; + shplonkZChallengeElements[3] = proof.shplonkQ.y_0; + shplonkZChallengeElements[4] = proof.shplonkQ.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + // Commitments + p.w1 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w2 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w3 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupReadTags = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w4 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupInverses = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.zPerm = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[0] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + p.libraSum = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + // Sumcheck univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + p.libraCommitments[1] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[2] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingPoly = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + p.geminiFoldComms[i] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + // Shplonk + p.shplonkQ = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + // KZG + p.kzgQuotient = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = + ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = accumulator + evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[CONST_PROOF_SIZE_LOG_N] foldPosEvaluations; + } + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + if (i <= logSize) { + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + } + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + require(proofSection.length == 0x20, "invalid number of bytes to construct Fr scalar"); + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities + +function convertProofPoint(Honk.G1ProofPoint memory input) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({x: input.x_0 | (input.x_1 << 136), y: input.y_0 | (input.y_1 << 136)}); +} + +function bytesToG1ProofPoint(bytes calldata proofSection) pure returns (Honk.G1ProofPoint memory point) { + require(proofSection.length == 0x80, "invalid number of bytes to construct a G1 point"); + point = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proofSection[0x00:0x20])), + x_1: uint256(bytes32(proofSection[0x20:0x40])), + y_0: uint256(bytes32(proofSection[0x40:0x60])), + y_1: uint256(bytes32(proofSection[0x60:0x80])) + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 508; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = ZKTranscriptLib.generateTranscript( + p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + ); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from($N + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = + CommitmentSchemeLib.computeSquares(tp.geminiR); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars; + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory commitments; + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = convertProofPoint(proof.shplonkQ); + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + scalars[1] = mem.unshiftedScalar.neg(); + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + for (uint256 i = NUMBER_UNSHIFTED; i < NUMBER_OF_ENTITIES; ++i) { + scalars[i + 2] = mem.shiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = convertProofPoint(proof.geminiMaskingPoly); + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = convertProofPoint(proof.w1); + commitments[31] = convertProofPoint(proof.w2); + commitments[32] = convertProofPoint(proof.w3); + commitments[33] = convertProofPoint(proof.w4); + commitments[34] = convertProofPoint(proof.zPerm); + commitments[35] = convertProofPoint(proof.lookupInverses); + commitments[36] = convertProofPoint(proof.lookupReadCounts); + commitments[37] = convertProofPoint(proof.lookupReadTags); + + // to be Shifted + commitments[38] = convertProofPoint(proof.w1); + commitments[39] = convertProofPoint(proof.w2); + commitments[40] = convertProofPoint(proof.w3); + commitments[41] = convertProofPoint(proof.w4); + commitments[42] = convertProofPoint(proof.zPerm); + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_OF_ENTITIES + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = convertProofPoint(proof.geminiFoldComms[i]); + } + + boundary += CONST_PROOF_SIZE_LOG_N - 1; + + // Finalise the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = convertProofPoint(proof.libraCommitments[i]); + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = convertProofPoint(proof.kzgQuotient); + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + Honk.G1Point memory P_0 = batchMul(commitments, scalars); + Honk.G1Point memory P_1 = negateInplace(quotient_commitment); + + return pairing(P_0, P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < CONST_PROOF_SIZE_LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul( + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory base, + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars + ) internal view returns (Honk.G1Point memory result) { + uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3; + assembly { + let success := 0x01 + let free := mload(0x40) + + // Write the original into the accumulator + // Load into memory for ecMUL, leave offset for eccAdd result + // base is an array of pointers, so we have to dereference them + mstore(add(free, 0x40), mload(mload(base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalars)) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) + + let count := 0x01 + for {} lt(count, limit) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/noir/migrate.sol b/eth/noir/migrate.sol new file mode 100644 index 0000000..f6cddcb --- /dev/null +++ b/eth/noir/migrate.sol @@ -0,0 +1,2186 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 1; +uint256 constant LOG_N = 0; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 0; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(1), + logCircuitSize: uint256(0), + publicInputsSize: uint256(0), + ql: Honk.G1Point({ + x: uint256(0x1fb0f4fb5d6b1f8377ef0f307c7bf6e7ca5da09fc7aaa058cc823c0f7789082b), + y: uint256(0x101d436e3e9cbfad604c54e6fdfd4f4531e50b31301c6ae5d8a8c82650060572) + }), + qr: Honk.G1Point({ + x: uint256(0x3028436e3e9cbfad105254e6fdfd4f4541f20b31301c6ae587bee7d24f060572), + y: uint256(0x0000000000000000800be1540100000060832d02006000000018e15401000000) + }), + qo: Honk.G1Point({ + x: uint256(0x301fde8f1f2e5fd6a7d89b9d7f7ea7a28905c27097ee3573a414553d288302b9), + y: uint256(0x1fbf901c3dfcbfacbfa755e6fdfd4f45318757df2f7c6ae61816c92650060572) + }), + q4: Honk.G1Point({ + x: uint256(0x0f6041a95ccb1f83b77910307c7bf6e77a0bed4dc70aa0584b9e5bbb7689082b), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qm: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qc: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000e0d7e05401000000d0d9e05401000000c0dbe05401000000) + }), + qLookup: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qArith: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qMemory: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qNnf: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + s1: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + s2: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + s3: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + s4: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + t1: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + t2: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + t3: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + t4: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + id1: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + id2: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + id3: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + id4: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000000), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000000) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + return Fr.wrap(value % MODULUS); + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + return Fr.wrap(uint256(value) % MODULUS); + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + return bytes32(Fr.unwrap(value)); + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + return numerator * invert(denominator); + } + + function sqr(Fr value) internal pure returns (Fr) { + return value * value; + } + + function unwrap(Fr value) internal pure returns (uint256) { + return Fr.unwrap(value); + } + + function neg(Fr value) internal pure returns (Fr) { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function mul(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function sub(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) != Fr.unwrap(b); +} + +function equal(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) == Fr.unwrap(b); +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct G1ProofPoint { + uint256 x_0; + uint256 x_1; + uint256 y_0; + uint256 y_1; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Lookup helpers - Permutations + Honk.G1ProofPoint zPerm; + // Lookup helpers - logup + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Commitments to logup witness polynomials + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Commitment to grand permutation polynomial + Honk.G1ProofPoint zPerm; + Honk.G1ProofPoint[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + Honk.G1ProofPoint geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( + proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + ); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); + round0[0] = bytes32(circuitSize); + round0[1] = bytes32(publicInputsSize); + round0[2] = bytes32(pubInputsOffset); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[3 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[13] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x_0); + round1[2] = bytes32(proof.lookupReadCounts.x_1); + round1[3] = bytes32(proof.lookupReadCounts.y_0); + round1[4] = bytes32(proof.lookupReadCounts.y_1); + round1[5] = bytes32(proof.lookupReadTags.x_0); + round1[6] = bytes32(proof.lookupReadTags.x_1); + round1[7] = bytes32(proof.lookupReadTags.y_0); + round1[8] = bytes32(proof.lookupReadTags.y_1); + round1[9] = bytes32(proof.w4.x_0); + round1[10] = bytes32(proof.w4.x_1); + round1[11] = bytes32(proof.w4.y_0); + round1[12] = bytes32(proof.w4.y_1); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[9] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x_0; + alpha0[2] = proof.lookupInverses.x_1; + alpha0[3] = proof.lookupInverses.y_0; + alpha0[4] = proof.lookupInverses.y_1; + alpha0[5] = proof.zPerm.x_0; + alpha0[6] = proof.zPerm.x_1; + alpha0[7] = proof.zPerm.y_0; + alpha0[8] = proof.zPerm.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); + + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + + (alphas[NUMBER_OF_ALPHAS - 1],) = splitChallenge(nextPreviousChallenge); + } + } + + function generateGateChallenges(Fr previousChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (gateChallenges[i],) = splitChallenge(previousChallenge); + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 4 comm, 1 sum, 1 challenge + uint256[6] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x_0; + challengeData[2] = proof.libraCommitments[0].x_1; + challengeData[3] = proof.libraCommitments[0].y_0; + challengeData[4] = proof.libraCommitments[0].y_1; + challengeData[5] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 15] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[1].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[1].y_1; + i += 4; + rhoChallengeElements[i] = proof.libraCommitments[2].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[2].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[2].y_1; + i += 4; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x_0; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.x_1; + rhoChallengeElements[i + 2] = proof.geminiMaskingPoly.y_0; + rhoChallengeElements[i + 3] = proof.geminiMaskingPoly.y_1; + + i += 4; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR; + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + gR[1 + i * 4] = proof.geminiFoldComms[i].x_0; + gR[2 + i * 4] = proof.geminiFoldComms[i].x_1; + gR[3 + i * 4] = proof.geminiFoldComms[i].y_0; + gR[4 + i * 4] = proof.geminiFoldComms[i].y_1; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N) + 1 + 4] memory shplonkNuChallengeElements; + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= CONST_PROOF_SIZE_LOG_N; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = CONST_PROOF_SIZE_LOG_N + 1; i <= CONST_PROOF_SIZE_LOG_N + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[5] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x_0; + shplonkZChallengeElements[2] = proof.shplonkQ.x_1; + shplonkZChallengeElements[3] = proof.shplonkQ.y_0; + shplonkZChallengeElements[4] = proof.shplonkQ.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + // Commitments + p.w1 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w2 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w3 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupReadTags = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w4 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupInverses = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.zPerm = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[0] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + p.libraSum = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + // Sumcheck univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + p.libraCommitments[1] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[2] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingPoly = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + p.geminiFoldComms[i] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + // Shplonk + p.shplonkQ = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + // KZG + p.kzgQuotient = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = + ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = accumulator + evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[CONST_PROOF_SIZE_LOG_N] foldPosEvaluations; + } + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + if (i <= logSize) { + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + } + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + require(proofSection.length == 0x20, "invalid number of bytes to construct Fr scalar"); + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities + +function convertProofPoint(Honk.G1ProofPoint memory input) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({x: input.x_0 | (input.x_1 << 136), y: input.y_0 | (input.y_1 << 136)}); +} + +function bytesToG1ProofPoint(bytes calldata proofSection) pure returns (Honk.G1ProofPoint memory point) { + require(proofSection.length == 0x80, "invalid number of bytes to construct a G1 point"); + point = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proofSection[0x00:0x20])), + x_1: uint256(bytes32(proofSection[0x20:0x40])), + y_0: uint256(bytes32(proofSection[0x40:0x60])), + y_1: uint256(bytes32(proofSection[0x60:0x80])) + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 508; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = ZKTranscriptLib.generateTranscript( + p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + ); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from($N + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = + CommitmentSchemeLib.computeSquares(tp.geminiR); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars; + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory commitments; + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = convertProofPoint(proof.shplonkQ); + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + scalars[1] = mem.unshiftedScalar.neg(); + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + for (uint256 i = NUMBER_UNSHIFTED; i < NUMBER_OF_ENTITIES; ++i) { + scalars[i + 2] = mem.shiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = convertProofPoint(proof.geminiMaskingPoly); + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = convertProofPoint(proof.w1); + commitments[31] = convertProofPoint(proof.w2); + commitments[32] = convertProofPoint(proof.w3); + commitments[33] = convertProofPoint(proof.w4); + commitments[34] = convertProofPoint(proof.zPerm); + commitments[35] = convertProofPoint(proof.lookupInverses); + commitments[36] = convertProofPoint(proof.lookupReadCounts); + commitments[37] = convertProofPoint(proof.lookupReadTags); + + // to be Shifted + commitments[38] = convertProofPoint(proof.w1); + commitments[39] = convertProofPoint(proof.w2); + commitments[40] = convertProofPoint(proof.w3); + commitments[41] = convertProofPoint(proof.w4); + commitments[42] = convertProofPoint(proof.zPerm); + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_OF_ENTITIES + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = convertProofPoint(proof.geminiFoldComms[i]); + } + + boundary += CONST_PROOF_SIZE_LOG_N - 1; + + // Finalise the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = convertProofPoint(proof.libraCommitments[i]); + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = convertProofPoint(proof.kzgQuotient); + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + Honk.G1Point memory P_0 = batchMul(commitments, scalars); + Honk.G1Point memory P_1 = negateInplace(quotient_commitment); + + return pairing(P_0, P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < CONST_PROOF_SIZE_LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul( + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory base, + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars + ) internal view returns (Honk.G1Point memory result) { + uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3; + assembly { + let success := 0x01 + let free := mload(0x40) + + // Write the original into the accumulator + // Load into memory for ecMUL, leave offset for eccAdd result + // base is an array of pointers, so we have to dereference them + mstore(add(free, 0x40), mload(mload(base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalars)) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) + + let count := 0x01 + for {} lt(count, limit) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/noir/mint.sol b/eth/noir/mint.sol new file mode 100644 index 0000000..24b9276 --- /dev/null +++ b/eth/noir/mint.sol @@ -0,0 +1,2186 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 4096; +uint256 constant LOG_N = 12; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 19; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(4096), + logCircuitSize: uint256(12), + publicInputsSize: uint256(19), + ql: Honk.G1Point({ + x: uint256(0x22e1112f2c3c80f0e766044d192e84538142edc26c041cafdf1f3253a8924711), + y: uint256(0x189e520f06cb62da9f53ea860904b720034fa5627dff95f72a2634ab1cf19cb3) + }), + qr: Honk.G1Point({ + x: uint256(0x284e833dfdcace67819a684258f8ff90b58d69e13a11ca8f658198ecc30a4061), + y: uint256(0x0ef57b3a5fe7ce17a553743133bd59f0a0826798db62b9d0f205096fa9d042f1) + }), + qo: Honk.G1Point({ + x: uint256(0x1ca8ecff8ecbbb943bd6a092b4e0890eae55d9b2e7f233cd62aa92a2ad3b7045), + y: uint256(0x0d1e365888d98453857bea12ecd09f3f57235aa2057b0b80dc55fe1891a3266a) + }), + q4: Honk.G1Point({ + x: uint256(0x15750c4df8b1d564c5f9d5a389b0981a2182aa50f7f4f45dad9b8c6ffe00026a), + y: uint256(0x04e7e289b576891d128768adadbb782faa4e023ad23530bfb7bc5c5d89dfbb30) + }), + qm: Honk.G1Point({ + x: uint256(0x21a4ae9276ab3111702ca8c5b9cd9edef69a25ab7b20a8790b6433b723a460d2), + y: uint256(0x24cc51e4174d532b969721f9c87c4d13ccecd332797c0dc837546a49c7f925ef) + }), + qc: Honk.G1Point({ + x: uint256(0x29a48a91a6b247642a4e73e5e85548ab91c9a1ed1a83f35d9671fe72dd759203), + y: uint256(0x2d9761241d6cd48826a3c42636b6361510b69a09d75e51eca80a5eb4fa648dfc) + }), + qLookup: Honk.G1Point({ + x: uint256(0x0073e7c223dd4f3e4734c4d9d9c9df394bd2eee2e12bac2fc49429a0443ec8b0), + y: uint256(0x20fac57db30195c2427a75a4d67231c1d1c74c8f84f009ab21d3c88e9657403d) + }), + qArith: Honk.G1Point({ + x: uint256(0x1821c0d25ad447067092081581813b41c1b677f48306e4f2e99f0e17d313ffb8), + y: uint256(0x2c8cfd662ff6ceca1cca09461f1f3c3b20bed6f40e5e936c9b325be35cd55068) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x0379efd57ac85135df0b36a7395e80d3cf9d43d7609122ff55b35e6b61321ada), + y: uint256(0x23b193689793f72cb5c3511d25095aa614520b5b3324957a6378c01b1d69a069) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x292e660b0079ca0d11c714817840f26dc005cea0e4d94c5394fd0001e37dd00c), + y: uint256(0x0c4c96bad2bd7c041414c53bc025b67ca6c866d3ab42513d5d7811d59b0c9fd9) + }), + qMemory: Honk.G1Point({ + x: uint256(0x15298f6329123a0e10f266ef593952c91419342ea8f1a737af010d34d7be6219), + y: uint256(0x2a58f3ce15f39bdc77caed83d0d48cf44e08ebc7097911d17afa4fc4bfc0ab5a) + }), + qNnf: Honk.G1Point({ + x: uint256(0x1dec01cbc2f69ffc9d765c7bc0c852c6c84c6c01e2c7963e4ae88a8c9fc5e747), + y: uint256(0x2f959f4a97fd041d8aa034623585cb1383d2130077e73367a53815bdfead2c8a) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x103c7723598010c38d228dd42d29c82a38246cac51f929ae616882cddfd249fe), + y: uint256(0x058f79f054649c53aebc8758f74b78710507a31c2b7d51b368a79636f9c1f892) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x02724742591d18c830ce4d974cbb6fe020bb3991d6555ad44de24476d0827c7c), + y: uint256(0x1e3100a9437d9747e8edae19b02f908e42aaae6cee09e5270e33e05aa7ce93db) + }), + s1: Honk.G1Point({ + x: uint256(0x1057ba9a7ab68561cecf5b6d4d2992004528888e26768b6260869cc648307c18), + y: uint256(0x0d1062e907dcbdf4ced3f7aa2776393134c81c182f9db2836df88aa0ceb40701) + }), + s2: Honk.G1Point({ + x: uint256(0x0e1503b1c25160565b4173cd81641492dd4f0420135d6070817a0a0cac4d9102), + y: uint256(0x19ebecd78787a82c44d5d9c871ac7cb3a6e5395ba113201ff6c60331b24313a9) + }), + s3: Honk.G1Point({ + x: uint256(0x2b99affe8cf87072765b9da21fc028275a201b83fcdfa5fa4f2807cbe60a62eb), + y: uint256(0x26433b9c53767f2aa2e16403617cf2bc8d687613ee3d98fbed2b04be1ca44223) + }), + s4: Honk.G1Point({ + x: uint256(0x27d164d926d34e5318016dedf3cd1ecd6e281ae1a185e5f077d042d0e153a1ba), + y: uint256(0x1f292b4d1023e6942b990cbc1fbc747685c1aefd762a5dff017c3a2a3fefbbae) + }), + t1: Honk.G1Point({ + x: uint256(0x004067623374b7c3965c7d8444b57ac2d81269c7eb3cb4f7b16568b2f8234c96), + y: uint256(0x0e605f3ad72203e21301ef1b5333cae1d8063220d1996854beb0c4fbc33bba9d) + }), + t2: Honk.G1Point({ + x: uint256(0x17aafa80bf54a7e6cc66472f9ccd70efa5044207a95191716ba0195b5a432266), + y: uint256(0x233ecaca2ddbebb0484a44e6f55b8c8614c7b5e0ce31b51d59d6b21322a307a1) + }), + t3: Honk.G1Point({ + x: uint256(0x1466af934dc34b082708b0a26a61dae7d9d859cbd4661cfab6abf34e827d9d2a), + y: uint256(0x2666bf4c8a2aef1ab89aafded315580561c9d4a13f3ac4b255b478f544590eda) + }), + t4: Honk.G1Point({ + x: uint256(0x0765bf6645e4cf63f05d9b0efd06acebce309c685a3b05e613574ccd7316677c), + y: uint256(0x09770f145625290cdcb08bae4e6f0a26897b5988fbaf9529e0a3326bfdb537ae) + }), + id1: Honk.G1Point({ + x: uint256(0x22a94ca9fbf041b24e3cae6ed554a408f6fa4526cef479187f8e30ec5af22fb7), + y: uint256(0x050675e1193389e16b0ff62ab64de611abdd3d1c48a80bac9d3ccdb59ea28ce1) + }), + id2: Honk.G1Point({ + x: uint256(0x1589af33fd22ba897677c61c3bc5bb373a13c9db11c716ae1a6f1ab0ab3a5fb3), + y: uint256(0x2396cd8a16f18a1ee9e78d2832b478b6c4c3219e1050c0f5aab870073afb791a) + }), + id3: Honk.G1Point({ + x: uint256(0x13d32ed75da341a1cde5fee7eaff44b4fcf536c9cacf49b18f7601ec44ff9a5c), + y: uint256(0x1d9989fa08fe0d353bfa61a2ad9ea7b0149015f6ff043e92ca9cedbf977c2e7a) + }), + id4: Honk.G1Point({ + x: uint256(0x14ff5e5f2689fded5d3e1f980931c6bcf6990c35991280368e8077af19fd0f2b), + y: uint256(0x185004f7f5398f2ea19434918f378d3753dd8baa7ac3fdaf81dc8ee6618b535f) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x17cd4a0a0ad0c1b25d999e7ed6a975dffbc970692ac8f19223e5e413a881f271), + y: uint256(0x02f38b373f74498ff60f7297b8a8c5a851ee11c678cc5836ebba8c22b2c32470) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + return Fr.wrap(value % MODULUS); + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + return Fr.wrap(uint256(value) % MODULUS); + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + return bytes32(Fr.unwrap(value)); + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + return numerator * invert(denominator); + } + + function sqr(Fr value) internal pure returns (Fr) { + return value * value; + } + + function unwrap(Fr value) internal pure returns (uint256) { + return Fr.unwrap(value); + } + + function neg(Fr value) internal pure returns (Fr) { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function mul(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function sub(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) != Fr.unwrap(b); +} + +function equal(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) == Fr.unwrap(b); +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct G1ProofPoint { + uint256 x_0; + uint256 x_1; + uint256 y_0; + uint256 y_1; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Lookup helpers - Permutations + Honk.G1ProofPoint zPerm; + // Lookup helpers - logup + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Commitments to logup witness polynomials + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Commitment to grand permutation polynomial + Honk.G1ProofPoint zPerm; + Honk.G1ProofPoint[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + Honk.G1ProofPoint geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) external pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( + proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + ); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); + round0[0] = bytes32(circuitSize); + round0[1] = bytes32(publicInputsSize); + round0[2] = bytes32(pubInputsOffset); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[3 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[13] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x_0); + round1[2] = bytes32(proof.lookupReadCounts.x_1); + round1[3] = bytes32(proof.lookupReadCounts.y_0); + round1[4] = bytes32(proof.lookupReadCounts.y_1); + round1[5] = bytes32(proof.lookupReadTags.x_0); + round1[6] = bytes32(proof.lookupReadTags.x_1); + round1[7] = bytes32(proof.lookupReadTags.y_0); + round1[8] = bytes32(proof.lookupReadTags.y_1); + round1[9] = bytes32(proof.w4.x_0); + round1[10] = bytes32(proof.w4.x_1); + round1[11] = bytes32(proof.w4.y_0); + round1[12] = bytes32(proof.w4.y_1); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[9] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x_0; + alpha0[2] = proof.lookupInverses.x_1; + alpha0[3] = proof.lookupInverses.y_0; + alpha0[4] = proof.lookupInverses.y_1; + alpha0[5] = proof.zPerm.x_0; + alpha0[6] = proof.zPerm.x_1; + alpha0[7] = proof.zPerm.y_0; + alpha0[8] = proof.zPerm.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); + + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + + (alphas[NUMBER_OF_ALPHAS - 1],) = splitChallenge(nextPreviousChallenge); + } + } + + function generateGateChallenges(Fr previousChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (gateChallenges[i],) = splitChallenge(previousChallenge); + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 4 comm, 1 sum, 1 challenge + uint256[6] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x_0; + challengeData[2] = proof.libraCommitments[0].x_1; + challengeData[3] = proof.libraCommitments[0].y_0; + challengeData[4] = proof.libraCommitments[0].y_1; + challengeData[5] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 15] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[1].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[1].y_1; + i += 4; + rhoChallengeElements[i] = proof.libraCommitments[2].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[2].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[2].y_1; + i += 4; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x_0; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.x_1; + rhoChallengeElements[i + 2] = proof.geminiMaskingPoly.y_0; + rhoChallengeElements[i + 3] = proof.geminiMaskingPoly.y_1; + + i += 4; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR; + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + gR[1 + i * 4] = proof.geminiFoldComms[i].x_0; + gR[2 + i * 4] = proof.geminiFoldComms[i].x_1; + gR[3 + i * 4] = proof.geminiFoldComms[i].y_0; + gR[4 + i * 4] = proof.geminiFoldComms[i].y_1; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N) + 1 + 4] memory shplonkNuChallengeElements; + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= CONST_PROOF_SIZE_LOG_N; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = CONST_PROOF_SIZE_LOG_N + 1; i <= CONST_PROOF_SIZE_LOG_N + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[5] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x_0; + shplonkZChallengeElements[2] = proof.shplonkQ.x_1; + shplonkZChallengeElements[3] = proof.shplonkQ.y_0; + shplonkZChallengeElements[4] = proof.shplonkQ.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + // Commitments + p.w1 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w2 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w3 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupReadTags = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w4 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupInverses = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.zPerm = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[0] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + p.libraSum = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + // Sumcheck univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + p.libraCommitments[1] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[2] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingPoly = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + p.geminiFoldComms[i] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + // Shplonk + p.shplonkQ = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + // KZG + p.kzgQuotient = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = + ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = accumulator + evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[CONST_PROOF_SIZE_LOG_N] foldPosEvaluations; + } + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + if (i <= logSize) { + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + } + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + require(proofSection.length == 0x20, "invalid number of bytes to construct Fr scalar"); + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities + +function convertProofPoint(Honk.G1ProofPoint memory input) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({x: input.x_0 | (input.x_1 << 136), y: input.y_0 | (input.y_1 << 136)}); +} + +function bytesToG1ProofPoint(bytes calldata proofSection) pure returns (Honk.G1ProofPoint memory point) { + require(proofSection.length == 0x80, "invalid number of bytes to construct a G1 point"); + point = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proofSection[0x00:0x20])), + x_1: uint256(bytes32(proofSection[0x20:0x40])), + y_0: uint256(bytes32(proofSection[0x40:0x60])), + y_1: uint256(bytes32(proofSection[0x60:0x80])) + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 508; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = ZKTranscriptLib.generateTranscript( + p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + ); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from($N + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = + CommitmentSchemeLib.computeSquares(tp.geminiR); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars; + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory commitments; + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = convertProofPoint(proof.shplonkQ); + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + scalars[1] = mem.unshiftedScalar.neg(); + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + for (uint256 i = NUMBER_UNSHIFTED; i < NUMBER_OF_ENTITIES; ++i) { + scalars[i + 2] = mem.shiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = convertProofPoint(proof.geminiMaskingPoly); + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = convertProofPoint(proof.w1); + commitments[31] = convertProofPoint(proof.w2); + commitments[32] = convertProofPoint(proof.w3); + commitments[33] = convertProofPoint(proof.w4); + commitments[34] = convertProofPoint(proof.zPerm); + commitments[35] = convertProofPoint(proof.lookupInverses); + commitments[36] = convertProofPoint(proof.lookupReadCounts); + commitments[37] = convertProofPoint(proof.lookupReadTags); + + // to be Shifted + commitments[38] = convertProofPoint(proof.w1); + commitments[39] = convertProofPoint(proof.w2); + commitments[40] = convertProofPoint(proof.w3); + commitments[41] = convertProofPoint(proof.w4); + commitments[42] = convertProofPoint(proof.zPerm); + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_OF_ENTITIES + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = convertProofPoint(proof.geminiFoldComms[i]); + } + + boundary += CONST_PROOF_SIZE_LOG_N - 1; + + // Finalise the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = convertProofPoint(proof.libraCommitments[i]); + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = convertProofPoint(proof.kzgQuotient); + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + Honk.G1Point memory P_0 = batchMul(commitments, scalars); + Honk.G1Point memory P_1 = negateInplace(quotient_commitment); + + return pairing(P_0, P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < CONST_PROOF_SIZE_LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul( + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory base, + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars + ) internal view returns (Honk.G1Point memory result) { + uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3; + assembly { + let success := 0x01 + let free := mload(0x40) + + // Write the original into the accumulator + // Load into memory for ecMUL, leave offset for eccAdd result + // base is an array of pointers, so we have to dereference them + mstore(add(free, 0x40), mload(mload(base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalars)) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) + + let count := 0x01 + for {} lt(count, limit) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/noir/points.sol b/eth/noir/points.sol new file mode 100644 index 0000000..a8216a0 --- /dev/null +++ b/eth/noir/points.sol @@ -0,0 +1,2186 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 8192; +uint256 constant LOG_N = 13; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 29; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(8192), + logCircuitSize: uint256(13), + publicInputsSize: uint256(29), + ql: Honk.G1Point({ + x: uint256(0x2524f5b77866f532ac43f52864b218017956798a208c2688e4d47a75547b7daf), + y: uint256(0x2905b38b62794ca696db62aa3f473744c7add66a529d316308c70a82aa40d4a8) + }), + qr: Honk.G1Point({ + x: uint256(0x1ef432dfb7f0814c5221e67e96200e889163e9657c1b2683e76c090e9cece02f), + y: uint256(0x08c1569ac1ae7b4c5d26295c123696dec339580569f7b5bae44c494ca1bfe765) + }), + qo: Honk.G1Point({ + x: uint256(0x299cd449ce66bb935c120f890b0331d187e279e7a73b5541c6a6cdf572ac1a9e), + y: uint256(0x0e992b6fb69ed4c6866c41af775abfe08d60baf95bc404f1dfa38e8fec70d508) + }), + q4: Honk.G1Point({ + x: uint256(0x01de9a7c500cb0b279287efbab1f6314587c13f63b3613414e44af1f06fe1f71), + y: uint256(0x167dd7e1f8f73c24fff939e01625c3a70c872f2d8744a9a36cb20923a73e7cf0) + }), + qm: Honk.G1Point({ + x: uint256(0x15d33b575e447a00f04a04e465915f347a9f5d2162c2133fe739cfc3ecca83d6), + y: uint256(0x26844fc0703d0455ea030be5068f5a3e1906c7a60cee4fa643c42c9bd15d008f) + }), + qc: Honk.G1Point({ + x: uint256(0x07628186d5c398bfd49eb30ee166413284c1a59c843f0e8a07948c703283f312), + y: uint256(0x20ae9e3acdc5d3895b1a079543c9e0d0c37059d0b3aef5f7f2da786ca2a5073a) + }), + qLookup: Honk.G1Point({ + x: uint256(0x2ee537ee80c33fc3003e53f2fa67b14d63887059b541c3d5dbe38bfd517aa579), + y: uint256(0x0ecddf7b61838886fcf1a7fec5c69d8e02933d1e153e33e5ea7d03b0c21b314a) + }), + qArith: Honk.G1Point({ + x: uint256(0x05c6ada3976bfe2f6bb2e2ec76133536a98b3a77d129d32945809ac8b3260bc5), + y: uint256(0x178c1421b39429040b048bb51c19d8d600819171f2c2c477b467f1065fe58e57) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x0b87d736cdf9d0ec5fa3f8f3af64a2326d6269da8026248acecc8db4f2dc2443), + y: uint256(0x1ac094e450007b2a6b06ece84de3a01bb39dfd48bce855abaf7b6c84050b7fd2) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x23b82c9adc93d322f1b57a01c9c5ae83d9d80b13634ff2daeda6a7195d0dca4f), + y: uint256(0x167b5cd1db6ba97b6f23b62db08a41b2ab6ab023afe790bca5d12be4580d745b) + }), + qMemory: Honk.G1Point({ + x: uint256(0x183dc0b74d756c33894335f3211dfe46512db2e14814b2da96a1743834e2c2f2), + y: uint256(0x00534e50ed6e415b75ee3d9022ddd3e36b8714eb2fb0a01e52df512017833886) + }), + qNnf: Honk.G1Point({ + x: uint256(0x0bfb54ec826959074c034d6f020a4ba364985b84dcdbb4d51378e5aacadee556), + y: uint256(0x145e69cb2a4552c6d8e9f5add79199ea5422db3770f24b8a0579ce8b89d7505c) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x2546919520ccd296348f79bf783bdf2103d446f75eb48a62a481967813263a0c), + y: uint256(0x0dea057e8cf9e4f0441a7fc8157bae794f471e0e8cc835335a624b18dce10e79) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x281c7b723008ef4b2638e83f9741b1c883acd7a21b4615c0ec0095686627be89), + y: uint256(0x2440c36723cd1150667e9e50ce396b2eef3757a605fb35eb8019f52f02c09c98) + }), + s1: Honk.G1Point({ + x: uint256(0x1fbdf420f48ff12f75a34906f68129dd63853f8ca077108c758e94e5051413cc), + y: uint256(0x0a2e7a8affac030a3fdaed089a51f2116124d9f02cbb5732c58912e6d7b380ed) + }), + s2: Honk.G1Point({ + x: uint256(0x11a8b11e47632573f2648b152ae3874a865cf8c0cd71abb986b06feeb6137d85), + y: uint256(0x23fd7d7ef7c3402f010869d4dce3dac5c6777069f11be130351296235f303366) + }), + s3: Honk.G1Point({ + x: uint256(0x2a503794496fa8e34c0cf43a015c9c6829af5a3ba61fd88adb04e448de4febaa), + y: uint256(0x2eca8fa7432005495de9586658a65062249681ee16464560324acde9d06c782a) + }), + s4: Honk.G1Point({ + x: uint256(0x24d5a37899317d4940810474f1c954d155a7ba8471f5cd8904100df835793cef), + y: uint256(0x0c1f14ef702c5eace2613309ffc578fb85b4ff7aada3af79953bc47e688769cd) + }), + t1: Honk.G1Point({ + x: uint256(0x07996eb6dfdbbe9366eb89f10c9e3f0ddc72fa5675348bf2044edf5dc4d5a58c), + y: uint256(0x07900286f41a6b1b401de720f9eaa6b92d56fc8510645d8904922fba3e1e38da) + }), + t2: Honk.G1Point({ + x: uint256(0x299718f02caec5c6f5c312a23adca7c66ea4cfcd33cb6e9f03fd0a69dd46c799), + y: uint256(0x2016239e3dc69d93a022823784a64a7ec20cd2a6b3fc442d3164a1d42bb5c3f1) + }), + t3: Honk.G1Point({ + x: uint256(0x26bf5f2ea5aa1995105c3cd32ced7f3c804df2f77a8ef8454f720805d97da70e), + y: uint256(0x187449669f89eb3ca1744849331cecdc8524fb932789dd8bce42b0d52a297d16) + }), + t4: Honk.G1Point({ + x: uint256(0x156d4ec761ecbf3624548e81c8465494d4c42ce8b495bbc46bef593881c63172), + y: uint256(0x29ef58088ef385b57d6b1ba1fd2fc6165df3608620713985e9c05d7c5faa183a) + }), + id1: Honk.G1Point({ + x: uint256(0x1de25f106b1b264d5016176ec61897f8489ae8e3e815a38d1dd3e055367cf28f), + y: uint256(0x0e713ce63a74cdf910af6c6bf659162ba19deab24dd9333550dde7b344948190) + }), + id2: Honk.G1Point({ + x: uint256(0x1add61ff28686707a0ecf51052ec3b6075f9e12498681a605459d910be365c6c), + y: uint256(0x2b155c81fcc76324d297b50d798839beb66eff6aa99fb99d867e1e69bd3a34cf) + }), + id3: Honk.G1Point({ + x: uint256(0x1293d89ae67571d6976a73a1e6c5726f1262de6fab0c1817fb40dd7cbea1dfcc), + y: uint256(0x1bab7d8bca1c5cf8c4da4c6420e0c7a8a0aed0c8190c7dc60b8968dd255d7aef) + }), + id4: Honk.G1Point({ + x: uint256(0x041be62a0d3ad1956cde1fc7e91446d74763702f348cc7ebaa3e3b0730563a8f), + y: uint256(0x1503625fd9e040c494760440dd43dbcd79f1df2b7cc4aada13995bbfa95da3a2) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x27e2145211461aeb744525780b35aaa1c99dd14354fee439ba5b6e2c8e67ec2c), + y: uint256(0x025d761e02c6cfd13d5b13c9c279c094e56dabb621349151a8606d384018f374) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + return Fr.wrap(value % MODULUS); + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + return Fr.wrap(uint256(value) % MODULUS); + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + return bytes32(Fr.unwrap(value)); + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + return numerator * invert(denominator); + } + + function sqr(Fr value) internal pure returns (Fr) { + return value * value; + } + + function unwrap(Fr value) internal pure returns (uint256) { + return Fr.unwrap(value); + } + + function neg(Fr value) internal pure returns (Fr) { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function mul(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function sub(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) != Fr.unwrap(b); +} + +function equal(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) == Fr.unwrap(b); +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct G1ProofPoint { + uint256 x_0; + uint256 x_1; + uint256 y_0; + uint256 y_1; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Lookup helpers - Permutations + Honk.G1ProofPoint zPerm; + // Lookup helpers - logup + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Commitments to logup witness polynomials + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Commitment to grand permutation polynomial + Honk.G1ProofPoint zPerm; + Honk.G1ProofPoint[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + Honk.G1ProofPoint geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( + proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + ); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); + round0[0] = bytes32(circuitSize); + round0[1] = bytes32(publicInputsSize); + round0[2] = bytes32(pubInputsOffset); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[3 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[13] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x_0); + round1[2] = bytes32(proof.lookupReadCounts.x_1); + round1[3] = bytes32(proof.lookupReadCounts.y_0); + round1[4] = bytes32(proof.lookupReadCounts.y_1); + round1[5] = bytes32(proof.lookupReadTags.x_0); + round1[6] = bytes32(proof.lookupReadTags.x_1); + round1[7] = bytes32(proof.lookupReadTags.y_0); + round1[8] = bytes32(proof.lookupReadTags.y_1); + round1[9] = bytes32(proof.w4.x_0); + round1[10] = bytes32(proof.w4.x_1); + round1[11] = bytes32(proof.w4.y_0); + round1[12] = bytes32(proof.w4.y_1); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[9] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x_0; + alpha0[2] = proof.lookupInverses.x_1; + alpha0[3] = proof.lookupInverses.y_0; + alpha0[4] = proof.lookupInverses.y_1; + alpha0[5] = proof.zPerm.x_0; + alpha0[6] = proof.zPerm.x_1; + alpha0[7] = proof.zPerm.y_0; + alpha0[8] = proof.zPerm.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); + + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + + (alphas[NUMBER_OF_ALPHAS - 1],) = splitChallenge(nextPreviousChallenge); + } + } + + function generateGateChallenges(Fr previousChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (gateChallenges[i],) = splitChallenge(previousChallenge); + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 4 comm, 1 sum, 1 challenge + uint256[6] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x_0; + challengeData[2] = proof.libraCommitments[0].x_1; + challengeData[3] = proof.libraCommitments[0].y_0; + challengeData[4] = proof.libraCommitments[0].y_1; + challengeData[5] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 15] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[1].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[1].y_1; + i += 4; + rhoChallengeElements[i] = proof.libraCommitments[2].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[2].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[2].y_1; + i += 4; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x_0; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.x_1; + rhoChallengeElements[i + 2] = proof.geminiMaskingPoly.y_0; + rhoChallengeElements[i + 3] = proof.geminiMaskingPoly.y_1; + + i += 4; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR; + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + gR[1 + i * 4] = proof.geminiFoldComms[i].x_0; + gR[2 + i * 4] = proof.geminiFoldComms[i].x_1; + gR[3 + i * 4] = proof.geminiFoldComms[i].y_0; + gR[4 + i * 4] = proof.geminiFoldComms[i].y_1; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N) + 1 + 4] memory shplonkNuChallengeElements; + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= CONST_PROOF_SIZE_LOG_N; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = CONST_PROOF_SIZE_LOG_N + 1; i <= CONST_PROOF_SIZE_LOG_N + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[5] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x_0; + shplonkZChallengeElements[2] = proof.shplonkQ.x_1; + shplonkZChallengeElements[3] = proof.shplonkQ.y_0; + shplonkZChallengeElements[4] = proof.shplonkQ.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + // Commitments + p.w1 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w2 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w3 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupReadTags = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w4 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupInverses = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.zPerm = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[0] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + p.libraSum = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + // Sumcheck univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + p.libraCommitments[1] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[2] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingPoly = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + p.geminiFoldComms[i] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + // Shplonk + p.shplonkQ = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + // KZG + p.kzgQuotient = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = + ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = accumulator + evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[CONST_PROOF_SIZE_LOG_N] foldPosEvaluations; + } + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + if (i <= logSize) { + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + } + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + require(proofSection.length == 0x20, "invalid number of bytes to construct Fr scalar"); + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities + +function convertProofPoint(Honk.G1ProofPoint memory input) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({x: input.x_0 | (input.x_1 << 136), y: input.y_0 | (input.y_1 << 136)}); +} + +function bytesToG1ProofPoint(bytes calldata proofSection) pure returns (Honk.G1ProofPoint memory point) { + require(proofSection.length == 0x80, "invalid number of bytes to construct a G1 point"); + point = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proofSection[0x00:0x20])), + x_1: uint256(bytes32(proofSection[0x20:0x40])), + y_0: uint256(bytes32(proofSection[0x40:0x60])), + y_1: uint256(bytes32(proofSection[0x60:0x80])) + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 508; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = ZKTranscriptLib.generateTranscript( + p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + ); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from($N + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = + CommitmentSchemeLib.computeSquares(tp.geminiR); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars; + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory commitments; + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = convertProofPoint(proof.shplonkQ); + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + scalars[1] = mem.unshiftedScalar.neg(); + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + for (uint256 i = NUMBER_UNSHIFTED; i < NUMBER_OF_ENTITIES; ++i) { + scalars[i + 2] = mem.shiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = convertProofPoint(proof.geminiMaskingPoly); + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = convertProofPoint(proof.w1); + commitments[31] = convertProofPoint(proof.w2); + commitments[32] = convertProofPoint(proof.w3); + commitments[33] = convertProofPoint(proof.w4); + commitments[34] = convertProofPoint(proof.zPerm); + commitments[35] = convertProofPoint(proof.lookupInverses); + commitments[36] = convertProofPoint(proof.lookupReadCounts); + commitments[37] = convertProofPoint(proof.lookupReadTags); + + // to be Shifted + commitments[38] = convertProofPoint(proof.w1); + commitments[39] = convertProofPoint(proof.w2); + commitments[40] = convertProofPoint(proof.w3); + commitments[41] = convertProofPoint(proof.w4); + commitments[42] = convertProofPoint(proof.zPerm); + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_OF_ENTITIES + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = convertProofPoint(proof.geminiFoldComms[i]); + } + + boundary += CONST_PROOF_SIZE_LOG_N - 1; + + // Finalise the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = convertProofPoint(proof.libraCommitments[i]); + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = convertProofPoint(proof.kzgQuotient); + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + Honk.G1Point memory P_0 = batchMul(commitments, scalars); + Honk.G1Point memory P_1 = negateInplace(quotient_commitment); + + return pairing(P_0, P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < CONST_PROOF_SIZE_LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul( + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory base, + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars + ) internal view returns (Honk.G1Point memory result) { + uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3; + assembly { + let success := 0x01 + let free := mload(0x40) + + // Write the original into the accumulator + // Load into memory for ecMUL, leave offset for eccAdd result + // base is an array of pointers, so we have to dereference them + mstore(add(free, 0x40), mload(mload(base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalars)) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) + + let count := 0x01 + for {} lt(count, limit) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/noir/signature.sol b/eth/noir/signature.sol new file mode 100644 index 0000000..8e5bbc3 --- /dev/null +++ b/eth/noir/signature.sol @@ -0,0 +1,2186 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 4096; +uint256 constant LOG_N = 12; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 18; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(4096), + logCircuitSize: uint256(12), + publicInputsSize: uint256(18), + ql: Honk.G1Point({ + x: uint256(0x26aa96b3a0d9e9719aeca6b2d901f4edbc87fc7abe5b53e748b889ab528d6430), + y: uint256(0x059e668437cc089ebd25c6fcb40aefd45e42dd734b009b291291d608822ed8a9) + }), + qr: Honk.G1Point({ + x: uint256(0x27215f25d9d754e6721e6d7f2057cc8ccb079ff2a8ff80684fcbbddde702eeff), + y: uint256(0x02757e5ccde7937626ca26b5171d3d0241ca38e4fd2297625c38101a5ce7d844) + }), + qo: Honk.G1Point({ + x: uint256(0x138630f2b497856c0f715659241766b9dbbc316b923b14590b5b85db847830d4), + y: uint256(0x000862d99a7d9b1ec7bbe98998f1a9334499e0f0d8609787f70c0bd03577bd58) + }), + q4: Honk.G1Point({ + x: uint256(0x2f5155855544566dbb619d85dfdb4dfaf1fa5b649fcb017ecf5fb23c5e2a2794), + y: uint256(0x2535d9b5e5440413cc6af98adb663186f78d259f976f104cb4f76715e67464a4) + }), + qm: Honk.G1Point({ + x: uint256(0x2dac5c34ac40ef7e448365e6552f92d60d1154aee0f802c7fc57d1e5fb3bfee2), + y: uint256(0x00e6751ba32b4db661b735066c9b2c2b3524ee624edb31d224e65d83aaaf0e2a) + }), + qc: Honk.G1Point({ + x: uint256(0x0cabcd4767f05fd8ac5d6827de9434416fac8ed04d23f7bfdf973b50665a7a6c), + y: uint256(0x01767830bf69c059579aa182ad902a2a20cadf386164ba4b5e0f9eb0f1ae8fbb) + }), + qLookup: Honk.G1Point({ + x: uint256(0x1ad0852ae1f831506b33a76a4968849abaf87e068b8e00ba462e190ff4dc0ff9), + y: uint256(0x2b782e70b28e331338317e348ecb3d3ee69c0cb7b1ca634b32395b5349605a93) + }), + qArith: Honk.G1Point({ + x: uint256(0x1604c8e5d6ce24f3baba52a593b1cf1507c8a1357c75775442436f701418a820), + y: uint256(0x0c8a43f7fb0126b66d5d6c647fc9aa8d09051257b044d94ee0debdfcc6f1ae5c) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x0c337b0675b5af476fa5c17005d0aa5152ac687cc653a071a79678b74716312c), + y: uint256(0x035e6b0e7c238825d6bb8c9b11cbb70f7400495cbd8fadd3e899b0547ff9f3ce) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x302e53d8383dccd3ad70cfe455e96266e1116a4f01db74c341d636f714d70d64), + y: uint256(0x20ae439180f84f52f126ea79e599d8dd0d48ee1eb2d1a900dd70c283eefe6ffa) + }), + qMemory: Honk.G1Point({ + x: uint256(0x249ae211312754c1051fe190743256ea29ff511738ea860f06cee903c737ceca), + y: uint256(0x2807759287035cea1a800c0345dc3eeef464b065e4f6a93460389efe3074cb57) + }), + qNnf: Honk.G1Point({ + x: uint256(0x2ef3f836712c8fc799a66781bcd55cc8353dd7f8ea59bda4d43206cbbb1ac9af), + y: uint256(0x0934e084cb8975eca5f56d70381f76b5329bed47eba6c43641348813fa45c446) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x06ad314a270f473690714633dba8d204b9f038ec788ec9a539190250fb378b4b), + y: uint256(0x05418e8c257aa16c69aa40bb7889bf132650f1a5f3ff4d48d497da2e28575412) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x18c800374e5c52e0f349f93b2a80789686b4870ccab7ea0af4ad6c10927e9ee2), + y: uint256(0x0db8ddce2af043ddffc7e3faca1616ab1627e3d325ddd377fcfeb422c20bef1b) + }), + s1: Honk.G1Point({ + x: uint256(0x1ddf6ec6212f464cb074aa12ef97200389eb34807007b6243175d7733fbd0ba7), + y: uint256(0x11c6984eeeee856dbf0ea6fb205c22f4baf67493f14bebcf8d06881f6c260863) + }), + s2: Honk.G1Point({ + x: uint256(0x02fbb6e7ceadf0602d9bf816c4a489f2cd316e6bf61143a49f26476d1eb1337e), + y: uint256(0x14b39afce4216499e8a4ec238a338d661d148e97f8cad8ee7886d74789049493) + }), + s3: Honk.G1Point({ + x: uint256(0x06245d3794ed47626fd5bea673034b71f9637b655d5c0371171998ac1fbd2138), + y: uint256(0x0dc0d33a35661df4233d14c0b58da89730a97f2b2a0623eb385ddd95ad77cacf) + }), + s4: Honk.G1Point({ + x: uint256(0x0d3131337b50acb6e11df1df9caad0f2d06cba675f550e0617e98402c31b7df8), + y: uint256(0x2c38fe613d6e8c2a737335ab36c7eb95c40e26a88fb7844cbc6c764c6bc9e181) + }), + t1: Honk.G1Point({ + x: uint256(0x089f5ce8686f0845e1ec05b6f39418e57533edc6143896fa1968fa0c6272897d), + y: uint256(0x2ad42e3bd60c95aa37746e3a4d2282dfc4222953b1f30cffd52aa0bb80a72ef1) + }), + t2: Honk.G1Point({ + x: uint256(0x19966ae74c271049f1b736f531c33d46a573ded81dc131335acf2156ad191e3d), + y: uint256(0x1f683771fa8dbe01394f3b5e6248d48f654e1708eb68b58dffd23da40911cba6) + }), + t3: Honk.G1Point({ + x: uint256(0x2e13855639e143fc28d05a89991e8fb52cfd4ad7ccaf65e2a3006617d63529e3), + y: uint256(0x098c3eb66469730cd1ccd20763c0e027dd774490c503a43fce6693a6e76913ed) + }), + t4: Honk.G1Point({ + x: uint256(0x08bbb2006058a97ecedcef1c44ad8ff67aa525fa3703e996bacb50f71df2b847), + y: uint256(0x029b1e53dbf2ef50bc0d7f156950de6009e73e99c91936daa734a838fa72e987) + }), + id1: Honk.G1Point({ + x: uint256(0x0ab14ef9813049410b7ad055a854fd2bd5c2680f1a231a459e43448da397c800), + y: uint256(0x2d3459536d6970da05eab1bce67a6cda29cb1f0e33dbd4655b69096ad9bad573) + }), + id2: Honk.G1Point({ + x: uint256(0x2e43c492c273f1c80c2f4b97034b5d852d25d9ea4f47bc0858967bdd6562b16c), + y: uint256(0x23a7bd136f070f40dad67e55de6c32932cd5e6a076c2dfe6bd7f85253c7552c8) + }), + id3: Honk.G1Point({ + x: uint256(0x1233edcd782a5481fa9b9823c6fdef2faf76fd40d7075231e368458619f5a99f), + y: uint256(0x2da31aee3bb0f2db3f9c2c5f96e86fb5f9d7013771c55e790abf12ba6a673046) + }), + id4: Honk.G1Point({ + x: uint256(0x289f137ca45d566dd066ef81c1d6f049654107fe2490d9aef7c27937032007f0), + y: uint256(0x1c4dbb5e7e6da2877b61296b60dca4d82b0cbbb5fd110feae054bf39c1d1e31d) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x0b2c2935a1585a74f048f8c7180ea24fd9f923c7a18b102910e64934bebc24c6), + y: uint256(0x105494650de4293305a47c54f78869100597fb101df4616075669b353392cd56) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + return Fr.wrap(value % MODULUS); + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + return Fr.wrap(uint256(value) % MODULUS); + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + return bytes32(Fr.unwrap(value)); + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + return numerator * invert(denominator); + } + + function sqr(Fr value) internal pure returns (Fr) { + return value * value; + } + + function unwrap(Fr value) internal pure returns (uint256) { + return Fr.unwrap(value); + } + + function neg(Fr value) internal pure returns (Fr) { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function mul(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function sub(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) != Fr.unwrap(b); +} + +function equal(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) == Fr.unwrap(b); +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct G1ProofPoint { + uint256 x_0; + uint256 x_1; + uint256 y_0; + uint256 y_1; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Lookup helpers - Permutations + Honk.G1ProofPoint zPerm; + // Lookup helpers - logup + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Commitments to logup witness polynomials + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Commitment to grand permutation polynomial + Honk.G1ProofPoint zPerm; + Honk.G1ProofPoint[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + Honk.G1ProofPoint geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( + proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + ); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); + round0[0] = bytes32(circuitSize); + round0[1] = bytes32(publicInputsSize); + round0[2] = bytes32(pubInputsOffset); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[3 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[13] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x_0); + round1[2] = bytes32(proof.lookupReadCounts.x_1); + round1[3] = bytes32(proof.lookupReadCounts.y_0); + round1[4] = bytes32(proof.lookupReadCounts.y_1); + round1[5] = bytes32(proof.lookupReadTags.x_0); + round1[6] = bytes32(proof.lookupReadTags.x_1); + round1[7] = bytes32(proof.lookupReadTags.y_0); + round1[8] = bytes32(proof.lookupReadTags.y_1); + round1[9] = bytes32(proof.w4.x_0); + round1[10] = bytes32(proof.w4.x_1); + round1[11] = bytes32(proof.w4.y_0); + round1[12] = bytes32(proof.w4.y_1); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[9] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x_0; + alpha0[2] = proof.lookupInverses.x_1; + alpha0[3] = proof.lookupInverses.y_0; + alpha0[4] = proof.lookupInverses.y_1; + alpha0[5] = proof.zPerm.x_0; + alpha0[6] = proof.zPerm.x_1; + alpha0[7] = proof.zPerm.y_0; + alpha0[8] = proof.zPerm.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); + + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + + (alphas[NUMBER_OF_ALPHAS - 1],) = splitChallenge(nextPreviousChallenge); + } + } + + function generateGateChallenges(Fr previousChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (gateChallenges[i],) = splitChallenge(previousChallenge); + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 4 comm, 1 sum, 1 challenge + uint256[6] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x_0; + challengeData[2] = proof.libraCommitments[0].x_1; + challengeData[3] = proof.libraCommitments[0].y_0; + challengeData[4] = proof.libraCommitments[0].y_1; + challengeData[5] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 15] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[1].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[1].y_1; + i += 4; + rhoChallengeElements[i] = proof.libraCommitments[2].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[2].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[2].y_1; + i += 4; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x_0; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.x_1; + rhoChallengeElements[i + 2] = proof.geminiMaskingPoly.y_0; + rhoChallengeElements[i + 3] = proof.geminiMaskingPoly.y_1; + + i += 4; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR; + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + gR[1 + i * 4] = proof.geminiFoldComms[i].x_0; + gR[2 + i * 4] = proof.geminiFoldComms[i].x_1; + gR[3 + i * 4] = proof.geminiFoldComms[i].y_0; + gR[4 + i * 4] = proof.geminiFoldComms[i].y_1; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N) + 1 + 4] memory shplonkNuChallengeElements; + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= CONST_PROOF_SIZE_LOG_N; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = CONST_PROOF_SIZE_LOG_N + 1; i <= CONST_PROOF_SIZE_LOG_N + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[5] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x_0; + shplonkZChallengeElements[2] = proof.shplonkQ.x_1; + shplonkZChallengeElements[3] = proof.shplonkQ.y_0; + shplonkZChallengeElements[4] = proof.shplonkQ.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + // Commitments + p.w1 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w2 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w3 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupReadTags = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w4 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupInverses = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.zPerm = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[0] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + p.libraSum = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + // Sumcheck univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + p.libraCommitments[1] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[2] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingPoly = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + p.geminiFoldComms[i] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + // Shplonk + p.shplonkQ = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + // KZG + p.kzgQuotient = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = + ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = accumulator + evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[CONST_PROOF_SIZE_LOG_N] foldPosEvaluations; + } + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + if (i <= logSize) { + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + } + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + require(proofSection.length == 0x20, "invalid number of bytes to construct Fr scalar"); + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities + +function convertProofPoint(Honk.G1ProofPoint memory input) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({x: input.x_0 | (input.x_1 << 136), y: input.y_0 | (input.y_1 << 136)}); +} + +function bytesToG1ProofPoint(bytes calldata proofSection) pure returns (Honk.G1ProofPoint memory point) { + require(proofSection.length == 0x80, "invalid number of bytes to construct a G1 point"); + point = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proofSection[0x00:0x20])), + x_1: uint256(bytes32(proofSection[0x20:0x40])), + y_0: uint256(bytes32(proofSection[0x40:0x60])), + y_1: uint256(bytes32(proofSection[0x60:0x80])) + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 508; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = ZKTranscriptLib.generateTranscript( + p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + ); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from($N + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = + CommitmentSchemeLib.computeSquares(tp.geminiR); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars; + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory commitments; + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = convertProofPoint(proof.shplonkQ); + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + scalars[1] = mem.unshiftedScalar.neg(); + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + for (uint256 i = NUMBER_UNSHIFTED; i < NUMBER_OF_ENTITIES; ++i) { + scalars[i + 2] = mem.shiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = convertProofPoint(proof.geminiMaskingPoly); + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = convertProofPoint(proof.w1); + commitments[31] = convertProofPoint(proof.w2); + commitments[32] = convertProofPoint(proof.w3); + commitments[33] = convertProofPoint(proof.w4); + commitments[34] = convertProofPoint(proof.zPerm); + commitments[35] = convertProofPoint(proof.lookupInverses); + commitments[36] = convertProofPoint(proof.lookupReadCounts); + commitments[37] = convertProofPoint(proof.lookupReadTags); + + // to be Shifted + commitments[38] = convertProofPoint(proof.w1); + commitments[39] = convertProofPoint(proof.w2); + commitments[40] = convertProofPoint(proof.w3); + commitments[41] = convertProofPoint(proof.w4); + commitments[42] = convertProofPoint(proof.zPerm); + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_OF_ENTITIES + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = convertProofPoint(proof.geminiFoldComms[i]); + } + + boundary += CONST_PROOF_SIZE_LOG_N - 1; + + // Finalise the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = convertProofPoint(proof.libraCommitments[i]); + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = convertProofPoint(proof.kzgQuotient); + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + Honk.G1Point memory P_0 = batchMul(commitments, scalars); + Honk.G1Point memory P_1 = negateInplace(quotient_commitment); + + return pairing(P_0, P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < CONST_PROOF_SIZE_LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul( + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory base, + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars + ) internal view returns (Honk.G1Point memory result) { + uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3; + assembly { + let success := 0x01 + let free := mload(0x40) + + // Write the original into the accumulator + // Load into memory for ecMUL, leave offset for eccAdd result + // base is an array of pointers, so we have to dereference them + mstore(add(free, 0x40), mload(mload(base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalars)) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) + + let count := 0x01 + for {} lt(count, limit) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/noir/utxo.sol b/eth/noir/utxo.sol new file mode 100644 index 0000000..68ba0c1 --- /dev/null +++ b/eth/noir/utxo.sol @@ -0,0 +1,2186 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2022 Aztec +pragma solidity >=0.8.21; + +uint256 constant N = 8192; +uint256 constant LOG_N = 13; +uint256 constant NUMBER_OF_PUBLIC_INPUTS = 25; +library HonkVerificationKey { + function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) { + Honk.VerificationKey memory vk = Honk.VerificationKey({ + circuitSize: uint256(8192), + logCircuitSize: uint256(13), + publicInputsSize: uint256(25), + ql: Honk.G1Point({ + x: uint256(0x074b7f7782fb90edcf35cdbe1f82a27241785c27a9256fe37dc10aea267e3251), + y: uint256(0x1680467fcc8d7f5b65f0d1e292719f59e4ae34f7d75406a8b44fe39a655eff47) + }), + qr: Honk.G1Point({ + x: uint256(0x2e54cd2d96807062f90240f11b9f9d5cdd10f1cff3ab8ad2a2083037497f3bec), + y: uint256(0x146c5378ffaccdbd2c3ad970aed9d59f93465af9e64f907522dc1a386ec5a726) + }), + qo: Honk.G1Point({ + x: uint256(0x2f0a75d147c380a2060be3eb07069f80bfe89a87bf8cb5f53154207059af7fa5), + y: uint256(0x1d20d992d59d03cfd1f43bf02d07cf582fc048b8dd7dfe5f5f1a9f95f362fff1) + }), + q4: Honk.G1Point({ + x: uint256(0x0409a06549c62cbeaf31f5c9e0617418ccabc1f3ec40d3fbc923402c6ed22df3), + y: uint256(0x208ca920487aa488312e1b2de111fa2b244f14ca838c516a0c7261ecf39fc09c) + }), + qm: Honk.G1Point({ + x: uint256(0x05187a1fe3cf77382952a9ef5c23874abaf820553dc94de5db87b20c74d97a6b), + y: uint256(0x1750a25606b075cf94193af89c642467f3fc1586d559e8053d5bf51dfd27e154) + }), + qc: Honk.G1Point({ + x: uint256(0x1005447d4ea8674fdb6d748e67c5aa706707157465bd334f1cf90a3c58c67a99), + y: uint256(0x132ba20fb4354ddbd11efd43b4ba7d634d3faf56216938dbc353d4b6da63c101) + }), + qLookup: Honk.G1Point({ + x: uint256(0x2e57b44b90da66faa200db697385d8231b6e8223f1073f97628acac5e2e0b28b), + y: uint256(0x1f9f2a5af3fb5b557da39bd9120c9a4d0a4090a5c806ffff96310036df7fde40) + }), + qArith: Honk.G1Point({ + x: uint256(0x185c050ada81d1487283842029061f75b1a45ab0cf6bbd2907c8a3c1433ccef4), + y: uint256(0x292e97e585daee293e2a5ff7e81311408dce081a5af44e9c5608d294ab8bffe0) + }), + qDeltaRange: Honk.G1Point({ + x: uint256(0x0366a6ca12f2e00f3a10668f333bcb410260aa8c95a4f549de1d25e59d16b354), + y: uint256(0x2b964c5054fa5b48753af8e2b87ddbcabc42c5e7b3f7c801188dd07e762537cf) + }), + qElliptic: Honk.G1Point({ + x: uint256(0x27bd7625d325e77f89bf6f2507d8cc64548551ad208c21c38e1194d8795eda4b), + y: uint256(0x2c9aabde94ec507bac85c5a419346d401fff2f4e6307231dc265c31056bb0bec) + }), + qMemory: Honk.G1Point({ + x: uint256(0x21c047610ef104bab7ec47ce7b6f086a404429794fb7014b801d11b89efc40d0), + y: uint256(0x1aaa4a6fde5952d3e8deb89a16efca3d7ee2890bcaca9e85addb5d3489ca57a0) + }), + qNnf: Honk.G1Point({ + x: uint256(0x251b2346dee353259a035e5c68b12dd2b64833f3a6a26379b6d5e2ec89c33b50), + y: uint256(0x2d85bcbe9b37586ad6f91ac9d6af9ce54fc55ac053d720d42d6ddb5234ef5139) + }), + qPoseidon2External: Honk.G1Point({ + x: uint256(0x0969acefdadcd4a4d05a2e68e2939d7ea4b59a28226a80f5422d2aee88c9bca3), + y: uint256(0x12159f88e5b6854738d13bee1907b632fea0b6b58fbd4c1be147c21a12168b22) + }), + qPoseidon2Internal: Honk.G1Point({ + x: uint256(0x09553aebc14f5cbd65e39011b85b47c5a590041515ee494c617c08b2e50e03de), + y: uint256(0x2843a93f12e499784959ec739792979e06800c379e4d26f94c4423383d0d296f) + }), + s1: Honk.G1Point({ + x: uint256(0x2792e2591a646db522f5ccccdc48e67b7cacea26e667875e23247786a7161876), + y: uint256(0x1feed705f7481503bd33d56e5fdfde17d977694da178bde38fdcf8158d7d34e7) + }), + s2: Honk.G1Point({ + x: uint256(0x1b67b0fd72c24de13d684894cacda194e92cb5b091e6f602c00d5d1e3121d591), + y: uint256(0x1365b12cb7af4d23507fc7817bfc4a6691e49995e813f6366aa0f2c9ef033fa0) + }), + s3: Honk.G1Point({ + x: uint256(0x216c3d0f8eb294e97c4f63c3e626bf09f660aa6f1ad9db05adefee39bc66ad58), + y: uint256(0x0760c02d7b47a66eb455c476ab1e4a0f18b0023ad6653a4f5d6d21606e3685b8) + }), + s4: Honk.G1Point({ + x: uint256(0x18a1c4b8c5eedcf9a283af24b31eaa3ff0a5314503adacd427128ff4c8f34615), + y: uint256(0x2b1451b6492c459e46ccb620827640b57def9e7bba4364bcecbe8382fe207541) + }), + t1: Honk.G1Point({ + x: uint256(0x2a2151a981bb85afda957beeb8ee245883ab86e97482786e90275194bb8e80cd), + y: uint256(0x2b87f0bc586ed756610eca48de9d4d3c56f54404708eabe1bb6dabd7696203cb) + }), + t2: Honk.G1Point({ + x: uint256(0x2fa75dcd73148b6cab95e82a24769ca1d1d3280dd5b9c2700c56eb44684b83d2), + y: uint256(0x247273927cfad5b89f2f6ba25e364acc2ccd40e9b1da53772dac5fcea42ef432) + }), + t3: Honk.G1Point({ + x: uint256(0x0f14d93997b9549960fe80f8a48b6e3253c97bff329a9ebf6d77d674d15b2e78), + y: uint256(0x0cfbb9e38232193a038dcfa17470d74544c40483608bfdb07b81a2bc7c7e092c) + }), + t4: Honk.G1Point({ + x: uint256(0x11460f1cb9210508c275ec98009facc06544875226c2ef12eb33610665b1c523), + y: uint256(0x021b2c1b6d951e023a6a8d2e9cbfc72c35c7a07ca516ed60d7f02e52671a612e) + }), + id1: Honk.G1Point({ + x: uint256(0x24dd2a425b5d13829fbba2891f40bf341690ba6fd86606c86cca1ba2ef367e31), + y: uint256(0x1ec3b8efcc9c0a4d6acf49c015c579386c7a9a707bfeb74edddc413cfc79f186) + }), + id2: Honk.G1Point({ + x: uint256(0x01ec1c20436f3e5a1b1556e9630c204cc16f73e512d84db4e8eafdd8770f0d3f), + y: uint256(0x29bb84f0fb0406afce540ed2e0f597b2035651604c9e89250f3ed612086b0f99) + }), + id3: Honk.G1Point({ + x: uint256(0x258ae264804ea0206780c92e4cb665d1a62975fc33aa3b1adabc007eb655c558), + y: uint256(0x122e73ce896c18a5da631e9b23a625151d5d994d8ea2dfb8536d331a3c5e768a) + }), + id4: Honk.G1Point({ + x: uint256(0x160f024d2704e8d8204896a6118132f1b0cd3bc78f6d651c9a2917cb022b781e), + y: uint256(0x15eefaa11ecf968498557e939e8bc096b323d599f3c53a25bc85025f5bd77481) + }), + lagrangeFirst: Honk.G1Point({ + x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), + y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002) + }), + lagrangeLast: Honk.G1Point({ + x: uint256(0x0cb7cf8f324150a0ee258178f7e3349e46415dc11355dc8d199928d38efb5808), + y: uint256(0x19bf6a8f3e5523952973cbc9718aa39930b4cc69a938a22576b99abb87f4b1f3) + }) + }); + return vk; + } +} + +pragma solidity ^0.8.27; + +interface IVerifier { + function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); +} + +type Fr is uint256; + +using {add as +} for Fr global; +using {sub as -} for Fr global; +using {mul as *} for Fr global; + +using {exp as ^} for Fr global; +using {notEqual as !=} for Fr global; +using {equal as ==} for Fr global; + +uint256 constant SUBGROUP_SIZE = 256; +uint256 constant MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // Prime field order +uint256 constant P = MODULUS; +Fr constant SUBGROUP_GENERATOR = Fr.wrap(0x07b0c561a6148404f086204a9f36ffb0617942546750f230c893619174a57a76); +Fr constant SUBGROUP_GENERATOR_INVERSE = Fr.wrap(0x204bd3277422fad364751ad938e2b5e6a54cf8c68712848a692c553d0329f5d6); +Fr constant MINUS_ONE = Fr.wrap(MODULUS - 1); +Fr constant ONE = Fr.wrap(1); +Fr constant ZERO = Fr.wrap(0); +// Instantiation + +library FrLib { + function from(uint256 value) internal pure returns (Fr) { + return Fr.wrap(value % MODULUS); + } + + function fromBytes32(bytes32 value) internal pure returns (Fr) { + return Fr.wrap(uint256(value) % MODULUS); + } + + function toBytes32(Fr value) internal pure returns (bytes32) { + return bytes32(Fr.unwrap(value)); + } + + function invert(Fr value) internal view returns (Fr) { + uint256 v = Fr.unwrap(value); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), v) + mstore(add(free, 0x80), sub(MODULUS, 2)) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function pow(Fr base, uint256 v) internal view returns (Fr) { + uint256 b = Fr.unwrap(base); + uint256 result; + + // Call the modexp precompile to invert in the field + assembly { + let free := mload(0x40) + mstore(free, 0x20) + mstore(add(free, 0x20), 0x20) + mstore(add(free, 0x40), 0x20) + mstore(add(free, 0x60), b) + mstore(add(free, 0x80), v) + mstore(add(free, 0xa0), MODULUS) + let success := staticcall(gas(), 0x05, free, 0xc0, 0x00, 0x20) + if iszero(success) { + revert(0, 0) + } + result := mload(0x00) + } + + return Fr.wrap(result); + } + + function div(Fr numerator, Fr denominator) internal view returns (Fr) { + return numerator * invert(denominator); + } + + function sqr(Fr value) internal pure returns (Fr) { + return value * value; + } + + function unwrap(Fr value) internal pure returns (uint256) { + return Fr.unwrap(value); + } + + function neg(Fr value) internal pure returns (Fr) { + return Fr.wrap(MODULUS - Fr.unwrap(value)); + } +} + +// Free functions +function add(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function mul(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(mulmod(Fr.unwrap(a), Fr.unwrap(b), MODULUS)); +} + +function sub(Fr a, Fr b) pure returns (Fr) { + return Fr.wrap(addmod(Fr.unwrap(a), MODULUS - Fr.unwrap(b), MODULUS)); +} + +function exp(Fr base, Fr exponent) pure returns (Fr) { + if (Fr.unwrap(exponent) == 0) return Fr.wrap(1); + // Implement exponent with a loop as we will overflow otherwise + for (uint256 i = 1; i < Fr.unwrap(exponent); i += i) { + base = base * base; + } + return base; +} + +function notEqual(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) != Fr.unwrap(b); +} + +function equal(Fr a, Fr b) pure returns (bool) { + return Fr.unwrap(a) == Fr.unwrap(b); +} + +uint256 constant CONST_PROOF_SIZE_LOG_N = 28; + +uint256 constant NUMBER_OF_SUBRELATIONS = 28; +uint256 constant BATCHED_RELATION_PARTIAL_LENGTH = 8; +uint256 constant ZK_BATCHED_RELATION_PARTIAL_LENGTH = 9; +uint256 constant NUMBER_OF_ENTITIES = 41; +uint256 constant NUMBER_UNSHIFTED = 36; +uint256 constant NUMBER_TO_BE_SHIFTED = 5; +uint256 constant PAIRING_POINTS_SIZE = 16; + +// Alphas are used as relation separators so there should be NUMBER_OF_SUBRELATIONS - 1 +uint256 constant NUMBER_OF_ALPHAS = NUMBER_OF_SUBRELATIONS - 1; + +// ENUM FOR WIRES +enum WIRE { + Q_M, + Q_C, + Q_L, + Q_R, + Q_O, + Q_4, + Q_LOOKUP, + Q_ARITH, + Q_RANGE, + Q_ELLIPTIC, + Q_MEMORY, + Q_NNF, + Q_POSEIDON2_EXTERNAL, + Q_POSEIDON2_INTERNAL, + SIGMA_1, + SIGMA_2, + SIGMA_3, + SIGMA_4, + ID_1, + ID_2, + ID_3, + ID_4, + TABLE_1, + TABLE_2, + TABLE_3, + TABLE_4, + LAGRANGE_FIRST, + LAGRANGE_LAST, + W_L, + W_R, + W_O, + W_4, + Z_PERM, + LOOKUP_INVERSES, + LOOKUP_READ_COUNTS, + LOOKUP_READ_TAGS, + W_L_SHIFT, + W_R_SHIFT, + W_O_SHIFT, + W_4_SHIFT, + Z_PERM_SHIFT +} + +library Honk { + struct G1Point { + uint256 x; + uint256 y; + } + + struct G1ProofPoint { + uint256 x_0; + uint256 x_1; + uint256 y_0; + uint256 y_1; + } + + struct VerificationKey { + // Misc Params + uint256 circuitSize; + uint256 logCircuitSize; + uint256 publicInputsSize; + // Selectors + G1Point qm; + G1Point qc; + G1Point ql; + G1Point qr; + G1Point qo; + G1Point q4; + G1Point qLookup; // Lookup + G1Point qArith; // Arithmetic widget + G1Point qDeltaRange; // Delta Range sort + G1Point qMemory; // Memory + G1Point qNnf; // Non-native Field + G1Point qElliptic; // Auxillary + G1Point qPoseidon2External; + G1Point qPoseidon2Internal; + // Copy cnstraints + G1Point s1; + G1Point s2; + G1Point s3; + G1Point s4; + // Copy identity + G1Point id1; + G1Point id2; + G1Point id3; + G1Point id4; + // Precomputed lookup table + G1Point t1; + G1Point t2; + G1Point t3; + G1Point t4; + // Fixed first and last + G1Point lagrangeFirst; + G1Point lagrangeLast; + } + + struct RelationParameters { + // challenges + Fr eta; + Fr etaTwo; + Fr etaThree; + Fr beta; + Fr gamma; + // derived + Fr publicInputsDelta; + } + + struct Proof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Free wires + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Lookup helpers - Permutations + Honk.G1ProofPoint zPerm; + // Lookup helpers - logup + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Sumcheck + Fr[BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } + + struct ZKProof { + // Pairing point object + Fr[PAIRING_POINTS_SIZE] pairingPointObject; + // Commitments to wire polynomials + Honk.G1ProofPoint w1; + Honk.G1ProofPoint w2; + Honk.G1ProofPoint w3; + Honk.G1ProofPoint w4; + // Commitments to logup witness polynomials + Honk.G1ProofPoint lookupReadCounts; + Honk.G1ProofPoint lookupReadTags; + Honk.G1ProofPoint lookupInverses; + // Commitment to grand permutation polynomial + Honk.G1ProofPoint zPerm; + Honk.G1ProofPoint[3] libraCommitments; + // Sumcheck + Fr libraSum; + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH][CONST_PROOF_SIZE_LOG_N] sumcheckUnivariates; + Fr[NUMBER_OF_ENTITIES] sumcheckEvaluations; + Fr libraEvaluation; + // ZK + Honk.G1ProofPoint geminiMaskingPoly; + Fr geminiMaskingEval; + // Shplemini + Honk.G1ProofPoint[CONST_PROOF_SIZE_LOG_N - 1] geminiFoldComms; + Fr[CONST_PROOF_SIZE_LOG_N] geminiAEvaluations; + Fr[4] libraPolyEvals; + Honk.G1ProofPoint shplonkQ; + Honk.G1ProofPoint kzgQuotient; + } +} + +// ZKTranscript library to generate fiat shamir challenges, the ZK transcript only differest +struct ZKTranscript { + // Oink + Honk.RelationParameters relationParameters; + Fr[NUMBER_OF_ALPHAS] alphas; + Fr[CONST_PROOF_SIZE_LOG_N] gateChallenges; + // Sumcheck + Fr libraChallenge; + Fr[CONST_PROOF_SIZE_LOG_N] sumCheckUChallenges; + // Shplemini + Fr rho; + Fr geminiR; + Fr shplonkNu; + Fr shplonkZ; + // Derived + Fr publicInputsDelta; +} + +library ZKTranscriptLib { + function generateTranscript( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (ZKTranscript memory t) { + Fr previousChallenge; + (t.relationParameters, previousChallenge) = generateRelationParametersChallenges( + proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset, previousChallenge + ); + + (t.alphas, previousChallenge) = generateAlphaChallenges(previousChallenge, proof); + + (t.gateChallenges, previousChallenge) = generateGateChallenges(previousChallenge); + (t.libraChallenge, previousChallenge) = generateLibraChallenge(previousChallenge, proof); + (t.sumCheckUChallenges, previousChallenge) = generateSumcheckChallenges(proof, previousChallenge); + + (t.rho, previousChallenge) = generateRhoChallenge(proof, previousChallenge); + + (t.geminiR, previousChallenge) = generateGeminiRChallenge(proof, previousChallenge); + + (t.shplonkNu, previousChallenge) = generateShplonkNuChallenge(proof, previousChallenge); + + (t.shplonkZ, previousChallenge) = generateShplonkZChallenge(proof, previousChallenge); + return t; + } + + function splitChallenge(Fr challenge) internal pure returns (Fr first, Fr second) { + uint256 challengeU256 = uint256(Fr.unwrap(challenge)); + uint256 lo = challengeU256 & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; + uint256 hi = challengeU256 >> 128; + first = FrLib.fromBytes32(bytes32(lo)); + second = FrLib.fromBytes32(bytes32(hi)); + } + + function generateRelationParametersChallenges( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset, + Fr previousChallenge + ) internal pure returns (Honk.RelationParameters memory rp, Fr nextPreviousChallenge) { + (rp.eta, rp.etaTwo, rp.etaThree, previousChallenge) = + generateEtaChallenge(proof, publicInputs, circuitSize, publicInputsSize, pubInputsOffset); + + (rp.beta, rp.gamma, nextPreviousChallenge) = generateBetaAndGammaChallenges(previousChallenge, proof); + } + + function generateEtaChallenge( + Honk.ZKProof memory proof, + bytes32[] calldata publicInputs, + uint256 circuitSize, + uint256 publicInputsSize, + uint256 pubInputsOffset + ) internal pure returns (Fr eta, Fr etaTwo, Fr etaThree, Fr previousChallenge) { + bytes32[] memory round0 = new bytes32[](3 + publicInputsSize + 12); + round0[0] = bytes32(circuitSize); + round0[1] = bytes32(publicInputsSize); + round0[2] = bytes32(pubInputsOffset); + for (uint256 i = 0; i < publicInputsSize - PAIRING_POINTS_SIZE; i++) { + round0[3 + i] = bytes32(publicInputs[i]); + } + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + round0[3 + publicInputsSize - PAIRING_POINTS_SIZE + i] = FrLib.toBytes32(proof.pairingPointObject[i]); + } + + // Create the first challenge + // Note: w4 is added to the challenge later on + round0[3 + publicInputsSize] = bytes32(proof.w1.x_0); + round0[3 + publicInputsSize + 1] = bytes32(proof.w1.x_1); + round0[3 + publicInputsSize + 2] = bytes32(proof.w1.y_0); + round0[3 + publicInputsSize + 3] = bytes32(proof.w1.y_1); + round0[3 + publicInputsSize + 4] = bytes32(proof.w2.x_0); + round0[3 + publicInputsSize + 5] = bytes32(proof.w2.x_1); + round0[3 + publicInputsSize + 6] = bytes32(proof.w2.y_0); + round0[3 + publicInputsSize + 7] = bytes32(proof.w2.y_1); + round0[3 + publicInputsSize + 8] = bytes32(proof.w3.x_0); + round0[3 + publicInputsSize + 9] = bytes32(proof.w3.x_1); + round0[3 + publicInputsSize + 10] = bytes32(proof.w3.y_0); + round0[3 + publicInputsSize + 11] = bytes32(proof.w3.y_1); + + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round0))); + (eta, etaTwo) = splitChallenge(previousChallenge); + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (etaThree,) = splitChallenge(previousChallenge); + } + + function generateBetaAndGammaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr beta, Fr gamma, Fr nextPreviousChallenge) + { + bytes32[13] memory round1; + round1[0] = FrLib.toBytes32(previousChallenge); + round1[1] = bytes32(proof.lookupReadCounts.x_0); + round1[2] = bytes32(proof.lookupReadCounts.x_1); + round1[3] = bytes32(proof.lookupReadCounts.y_0); + round1[4] = bytes32(proof.lookupReadCounts.y_1); + round1[5] = bytes32(proof.lookupReadTags.x_0); + round1[6] = bytes32(proof.lookupReadTags.x_1); + round1[7] = bytes32(proof.lookupReadTags.y_0); + round1[8] = bytes32(proof.lookupReadTags.y_1); + round1[9] = bytes32(proof.w4.x_0); + round1[10] = bytes32(proof.w4.x_1); + round1[11] = bytes32(proof.w4.y_0); + round1[12] = bytes32(proof.w4.y_1); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(round1))); + (beta, gamma) = splitChallenge(nextPreviousChallenge); + } + + // Alpha challenges non-linearise the gate contributions + function generateAlphaChallenges(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr[NUMBER_OF_ALPHAS] memory alphas, Fr nextPreviousChallenge) + { + // Generate the original sumcheck alpha 0 by hashing zPerm and zLookup + uint256[9] memory alpha0; + alpha0[0] = Fr.unwrap(previousChallenge); + alpha0[1] = proof.lookupInverses.x_0; + alpha0[2] = proof.lookupInverses.x_1; + alpha0[3] = proof.lookupInverses.y_0; + alpha0[4] = proof.lookupInverses.y_1; + alpha0[5] = proof.zPerm.x_0; + alpha0[6] = proof.zPerm.x_1; + alpha0[7] = proof.zPerm.y_0; + alpha0[8] = proof.zPerm.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(alpha0))); + (alphas[0], alphas[1]) = splitChallenge(nextPreviousChallenge); + + for (uint256 i = 1; i < NUMBER_OF_ALPHAS / 2; i++) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + (alphas[2 * i], alphas[2 * i + 1]) = splitChallenge(nextPreviousChallenge); + } + if (((NUMBER_OF_ALPHAS & 1) == 1) && (NUMBER_OF_ALPHAS > 2)) { + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(nextPreviousChallenge)))); + + (alphas[NUMBER_OF_ALPHAS - 1],) = splitChallenge(nextPreviousChallenge); + } + } + + function generateGateChallenges(Fr previousChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory gateChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + previousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(Fr.unwrap(previousChallenge)))); + + (gateChallenges[i],) = splitChallenge(previousChallenge); + } + nextPreviousChallenge = previousChallenge; + } + + function generateLibraChallenge(Fr previousChallenge, Honk.ZKProof memory proof) + internal + pure + returns (Fr libraChallenge, Fr nextPreviousChallenge) + { + // 4 comm, 1 sum, 1 challenge + uint256[6] memory challengeData; + challengeData[0] = Fr.unwrap(previousChallenge); + challengeData[1] = proof.libraCommitments[0].x_0; + challengeData[2] = proof.libraCommitments[0].x_1; + challengeData[3] = proof.libraCommitments[0].y_0; + challengeData[4] = proof.libraCommitments[0].y_1; + challengeData[5] = Fr.unwrap(proof.libraSum); + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(challengeData))); + (libraChallenge,) = splitChallenge(nextPreviousChallenge); + } + + function generateSumcheckChallenges(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckChallenges, Fr nextPreviousChallenge) + { + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH + 1] memory univariateChal; + univariateChal[0] = prevChallenge; + + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + univariateChal[j + 1] = proof.sumcheckUnivariates[i][j]; + } + prevChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(univariateChal))); + + (sumcheckChallenges[i],) = splitChallenge(prevChallenge); + } + nextPreviousChallenge = prevChallenge; + } + + // We add Libra claimed eval + 3 comm + 1 more eval + function generateRhoChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr rho, Fr nextPreviousChallenge) + { + uint256[NUMBER_OF_ENTITIES + 15] memory rhoChallengeElements; + rhoChallengeElements[0] = Fr.unwrap(prevChallenge); + uint256 i; + for (i = 1; i <= NUMBER_OF_ENTITIES; i++) { + rhoChallengeElements[i] = Fr.unwrap(proof.sumcheckEvaluations[i - 1]); + } + rhoChallengeElements[i] = Fr.unwrap(proof.libraEvaluation); + + i += 1; + rhoChallengeElements[i] = proof.libraCommitments[1].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[1].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[1].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[1].y_1; + i += 4; + rhoChallengeElements[i] = proof.libraCommitments[2].x_0; + rhoChallengeElements[i + 1] = proof.libraCommitments[2].x_1; + rhoChallengeElements[i + 2] = proof.libraCommitments[2].y_0; + rhoChallengeElements[i + 3] = proof.libraCommitments[2].y_1; + i += 4; + rhoChallengeElements[i] = proof.geminiMaskingPoly.x_0; + rhoChallengeElements[i + 1] = proof.geminiMaskingPoly.x_1; + rhoChallengeElements[i + 2] = proof.geminiMaskingPoly.y_0; + rhoChallengeElements[i + 3] = proof.geminiMaskingPoly.y_1; + + i += 4; + rhoChallengeElements[i] = Fr.unwrap(proof.geminiMaskingEval); + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(rhoChallengeElements))); + (rho,) = splitChallenge(nextPreviousChallenge); + } + + function generateGeminiRChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr geminiR, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N - 1) * 4 + 1] memory gR; + gR[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + gR[1 + i * 4] = proof.geminiFoldComms[i].x_0; + gR[2 + i * 4] = proof.geminiFoldComms[i].x_1; + gR[3 + i * 4] = proof.geminiFoldComms[i].y_0; + gR[4 + i * 4] = proof.geminiFoldComms[i].y_1; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(gR))); + + (geminiR,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkNuChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkNu, Fr nextPreviousChallenge) + { + uint256[(CONST_PROOF_SIZE_LOG_N) + 1 + 4] memory shplonkNuChallengeElements; + shplonkNuChallengeElements[0] = Fr.unwrap(prevChallenge); + + for (uint256 i = 1; i <= CONST_PROOF_SIZE_LOG_N; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.geminiAEvaluations[i - 1]); + } + + uint256 libraIdx = 0; + for (uint256 i = CONST_PROOF_SIZE_LOG_N + 1; i <= CONST_PROOF_SIZE_LOG_N + 4; i++) { + shplonkNuChallengeElements[i] = Fr.unwrap(proof.libraPolyEvals[libraIdx]); + libraIdx++; + } + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkNuChallengeElements))); + (shplonkNu,) = splitChallenge(nextPreviousChallenge); + } + + function generateShplonkZChallenge(Honk.ZKProof memory proof, Fr prevChallenge) + internal + pure + returns (Fr shplonkZ, Fr nextPreviousChallenge) + { + uint256[5] memory shplonkZChallengeElements; + shplonkZChallengeElements[0] = Fr.unwrap(prevChallenge); + + shplonkZChallengeElements[1] = proof.shplonkQ.x_0; + shplonkZChallengeElements[2] = proof.shplonkQ.x_1; + shplonkZChallengeElements[3] = proof.shplonkQ.y_0; + shplonkZChallengeElements[4] = proof.shplonkQ.y_1; + + nextPreviousChallenge = FrLib.fromBytes32(keccak256(abi.encodePacked(shplonkZChallengeElements))); + (shplonkZ,) = splitChallenge(nextPreviousChallenge); + } + + function loadProof(bytes calldata proof) internal pure returns (Honk.ZKProof memory p) { + uint256 boundary = 0x0; + + // Pairing point object + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + p.pairingPointObject[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + // Commitments + p.w1 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w2 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w3 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + // Lookup / Permutation Helper Commitments + p.lookupReadCounts = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupReadTags = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.w4 = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.lookupInverses = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.zPerm = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[0] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + + p.libraSum = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + // Sumcheck univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + for (uint256 j = 0; j < ZK_BATCHED_RELATION_PARTIAL_LENGTH; j++) { + p.sumcheckUnivariates[i][j] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + } + + // Sumcheck evaluations + for (uint256 i = 0; i < NUMBER_OF_ENTITIES; i++) { + p.sumcheckEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + p.libraEvaluation = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + p.libraCommitments[1] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.libraCommitments[2] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingPoly = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + p.geminiMaskingEval = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + + // Gemini + // Read gemini fold univariates + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; i++) { + p.geminiFoldComms[i] = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + } + + // Read gemini a evaluations + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; i++) { + p.geminiAEvaluations[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + for (uint256 i = 0; i < 4; i++) { + p.libraPolyEvals[i] = bytesToFr(proof[boundary:boundary + 0x20]); + boundary += 0x20; + } + + // Shplonk + p.shplonkQ = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + boundary += 0x80; + // KZG + p.kzgQuotient = bytesToG1ProofPoint(proof[boundary:boundary + 0x80]); + } +} + +// Field arithmetic libraries + +library RelationsLib { + Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) + + function accumulateRelationEvaluations( + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_ALPHAS] memory alphas, + Fr powPartialEval + ) internal pure returns (Fr accumulator) { + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; + + // Accumulate all relations in Ultra Honk - each with varying number of subrelations + accumulateArithmeticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePermutationRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateLogDerivativeLookupRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateDeltaRangeRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateEllipticRelation(purportedEvaluations, evaluations, powPartialEval); + accumulateMemoryRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulateNnfRelation(purportedEvaluations, rp, evaluations, powPartialEval); + accumulatePoseidonExternalRelation(purportedEvaluations, evaluations, powPartialEval); + accumulatePoseidonInternalRelation(purportedEvaluations, evaluations, powPartialEval); + // batch the subrelations with the alpha challenges to obtain the full honk relation + accumulator = scaleAndBatchSubrelations(evaluations, alphas); + } + + /** + * Aesthetic helper function that is used to index by enum into proof.sumcheckEvaluations, it avoids + * the relation checking code being cluttered with uint256 type casting, which is often a different colour in code + * editors, and thus is noisy. + */ + function wire(Fr[NUMBER_OF_ENTITIES] memory p, WIRE _wire) internal pure returns (Fr) { + return p[uint256(_wire)]; + } + + uint256 internal constant NEG_HALF_MODULO_P = 0x183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000; + /** + * Ultra Arithmetic Relation + * + */ + + function accumulateArithmeticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + // Relation 0 + Fr q_arith = wire(p, WIRE.Q_ARITH); + { + Fr neg_half = Fr.wrap(NEG_HALF_MODULO_P); + + Fr accum = (q_arith - Fr.wrap(3)) * (wire(p, WIRE.Q_M) * wire(p, WIRE.W_R) * wire(p, WIRE.W_L)) * neg_half; + accum = accum + (wire(p, WIRE.Q_L) * wire(p, WIRE.W_L)) + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_R)) + + (wire(p, WIRE.Q_O) * wire(p, WIRE.W_O)) + (wire(p, WIRE.Q_4) * wire(p, WIRE.W_4)) + wire(p, WIRE.Q_C); + accum = accum + (q_arith - ONE) * wire(p, WIRE.W_4_SHIFT); + accum = accum * q_arith; + accum = accum * domainSep; + evals[0] = accum; + } + + // Relation 1 + { + Fr accum = wire(p, WIRE.W_L) + wire(p, WIRE.W_4) - wire(p, WIRE.W_L_SHIFT) + wire(p, WIRE.Q_M); + accum = accum * (q_arith - Fr.wrap(2)); + accum = accum * (q_arith - ONE); + accum = accum * q_arith; + accum = accum * domainSep; + evals[1] = accum; + } + } + + function accumulatePermutationRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr grand_product_numerator; + Fr grand_product_denominator; + + { + Fr num = wire(p, WIRE.W_L) + wire(p, WIRE.ID_1) * rp.beta + rp.gamma; + num = num * (wire(p, WIRE.W_R) + wire(p, WIRE.ID_2) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_O) + wire(p, WIRE.ID_3) * rp.beta + rp.gamma); + num = num * (wire(p, WIRE.W_4) + wire(p, WIRE.ID_4) * rp.beta + rp.gamma); + + grand_product_numerator = num; + } + { + Fr den = wire(p, WIRE.W_L) + wire(p, WIRE.SIGMA_1) * rp.beta + rp.gamma; + den = den * (wire(p, WIRE.W_R) + wire(p, WIRE.SIGMA_2) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_O) + wire(p, WIRE.SIGMA_3) * rp.beta + rp.gamma); + den = den * (wire(p, WIRE.W_4) + wire(p, WIRE.SIGMA_4) * rp.beta + rp.gamma); + + grand_product_denominator = den; + } + + // Contribution 2 + { + Fr acc = (wire(p, WIRE.Z_PERM) + wire(p, WIRE.LAGRANGE_FIRST)) * grand_product_numerator; + + acc = acc + - ( + (wire(p, WIRE.Z_PERM_SHIFT) + (wire(p, WIRE.LAGRANGE_LAST) * rp.publicInputsDelta)) + * grand_product_denominator + ); + acc = acc * domainSep; + evals[2] = acc; + } + + // Contribution 3 + { + Fr acc = (wire(p, WIRE.LAGRANGE_LAST) * wire(p, WIRE.Z_PERM_SHIFT)) * domainSep; + evals[3] = acc; + } + } + + function accumulateLogDerivativeLookupRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr write_term; + Fr read_term; + + // Calculate the write term (the table accumulation) + { + write_term = wire(p, WIRE.TABLE_1) + rp.gamma + (wire(p, WIRE.TABLE_2) * rp.eta) + + (wire(p, WIRE.TABLE_3) * rp.etaTwo) + (wire(p, WIRE.TABLE_4) * rp.etaThree); + } + + // Calculate the write term + { + Fr derived_entry_1 = wire(p, WIRE.W_L) + rp.gamma + (wire(p, WIRE.Q_R) * wire(p, WIRE.W_L_SHIFT)); + Fr derived_entry_2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_M) * wire(p, WIRE.W_R_SHIFT); + Fr derived_entry_3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_C) * wire(p, WIRE.W_O_SHIFT); + + read_term = derived_entry_1 + (derived_entry_2 * rp.eta) + (derived_entry_3 * rp.etaTwo) + + (wire(p, WIRE.Q_O) * rp.etaThree); + } + + Fr read_inverse = wire(p, WIRE.LOOKUP_INVERSES) * write_term; + Fr write_inverse = wire(p, WIRE.LOOKUP_INVERSES) * read_term; + + Fr inverse_exists_xor = wire(p, WIRE.LOOKUP_READ_TAGS) + wire(p, WIRE.Q_LOOKUP) + - (wire(p, WIRE.LOOKUP_READ_TAGS) * wire(p, WIRE.Q_LOOKUP)); + + // Inverse calculated correctly relation + Fr accumulatorNone = read_term * write_term * wire(p, WIRE.LOOKUP_INVERSES) - inverse_exists_xor; + accumulatorNone = accumulatorNone * domainSep; + + // Inverse + Fr accumulatorOne = wire(p, WIRE.Q_LOOKUP) * read_inverse - wire(p, WIRE.LOOKUP_READ_COUNTS) * write_inverse; + + Fr read_tag = wire(p, WIRE.LOOKUP_READ_TAGS); + + Fr read_tag_boolean_relation = read_tag * read_tag - read_tag; + + evals[4] = accumulatorNone; + evals[5] = accumulatorOne; + evals[6] = read_tag_boolean_relation * domainSep; + } + + function accumulateDeltaRangeRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + Fr minus_one = ZERO - ONE; + Fr minus_two = ZERO - Fr.wrap(2); + Fr minus_three = ZERO - Fr.wrap(3); + + // Compute wire differences + Fr delta_1 = wire(p, WIRE.W_R) - wire(p, WIRE.W_L); + Fr delta_2 = wire(p, WIRE.W_O) - wire(p, WIRE.W_R); + Fr delta_3 = wire(p, WIRE.W_4) - wire(p, WIRE.W_O); + Fr delta_4 = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_4); + + // Contribution 6 + { + Fr acc = delta_1; + acc = acc * (delta_1 + minus_one); + acc = acc * (delta_1 + minus_two); + acc = acc * (delta_1 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[7] = acc; + } + + // Contribution 7 + { + Fr acc = delta_2; + acc = acc * (delta_2 + minus_one); + acc = acc * (delta_2 + minus_two); + acc = acc * (delta_2 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[8] = acc; + } + + // Contribution 8 + { + Fr acc = delta_3; + acc = acc * (delta_3 + minus_one); + acc = acc * (delta_3 + minus_two); + acc = acc * (delta_3 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[9] = acc; + } + + // Contribution 9 + { + Fr acc = delta_4; + acc = acc * (delta_4 + minus_one); + acc = acc * (delta_4 + minus_two); + acc = acc * (delta_4 + minus_three); + acc = acc * wire(p, WIRE.Q_RANGE); + acc = acc * domainSep; + evals[10] = acc; + } + } + + struct EllipticParams { + // Points + Fr x_1; + Fr y_1; + Fr x_2; + Fr y_2; + Fr y_3; + Fr x_3; + // push accumulators into memory + Fr x_double_identity; + } + + function accumulateEllipticRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + EllipticParams memory ep; + ep.x_1 = wire(p, WIRE.W_R); + ep.y_1 = wire(p, WIRE.W_O); + + ep.x_2 = wire(p, WIRE.W_L_SHIFT); + ep.y_2 = wire(p, WIRE.W_4_SHIFT); + ep.y_3 = wire(p, WIRE.W_O_SHIFT); + ep.x_3 = wire(p, WIRE.W_R_SHIFT); + + Fr q_sign = wire(p, WIRE.Q_L); + Fr q_is_double = wire(p, WIRE.Q_M); + + // Contribution 10 point addition, x-coordinate check + // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 + Fr x_diff = (ep.x_2 - ep.x_1); + Fr y1_sqr = (ep.y_1 * ep.y_1); + { + // Move to top + Fr partialEval = domainSep; + + Fr y2_sqr = (ep.y_2 * ep.y_2); + Fr y1y2 = ep.y_1 * ep.y_2 * q_sign; + Fr x_add_identity = (ep.x_3 + ep.x_2 + ep.x_1); + x_add_identity = x_add_identity * x_diff * x_diff; + x_add_identity = x_add_identity - y2_sqr - y1_sqr + y1y2 + y1y2; + + evals[11] = x_add_identity * partialEval * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 11 point addition, x-coordinate check + // q_elliptic * (q_sign * y1 + y3)(x2 - x1) + (x3 - x1)(y2 - q_sign * y1) = 0 + { + Fr y1_plus_y3 = ep.y_1 + ep.y_3; + Fr y_diff = ep.y_2 * q_sign - ep.y_1; + Fr y_add_identity = y1_plus_y3 * x_diff + (ep.x_3 - ep.x_1) * y_diff; + evals[12] = y_add_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * (ONE - q_is_double); + } + + // Contribution 10 point doubling, x-coordinate check + // (x3 + x1 + x1) (4y1*y1) - 9 * x1 * x1 * x1 * x1 = 0 + // N.B. we're using the equivalence x1*x1*x1 === y1*y1 - curve_b to reduce degree by 1 + { + Fr x_pow_4 = (y1_sqr + GRUMPKIN_CURVE_B_PARAMETER_NEGATED) * ep.x_1; + Fr y1_sqr_mul_4 = y1_sqr + y1_sqr; + y1_sqr_mul_4 = y1_sqr_mul_4 + y1_sqr_mul_4; + Fr x1_pow_4_mul_9 = x_pow_4 * Fr.wrap(9); + + // NOTE: pushed into memory (stack >:'( ) + ep.x_double_identity = (ep.x_3 + ep.x_1 + ep.x_1) * y1_sqr_mul_4 - x1_pow_4_mul_9; + + Fr acc = ep.x_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + evals[11] = evals[11] + acc; + } + + // Contribution 11 point doubling, y-coordinate check + // (y1 + y1) (2y1) - (3 * x1 * x1)(x1 - x3) = 0 + { + Fr x1_sqr_mul_3 = (ep.x_1 + ep.x_1 + ep.x_1) * ep.x_1; + Fr y_double_identity = x1_sqr_mul_3 * (ep.x_1 - ep.x_3) - (ep.y_1 + ep.y_1) * (ep.y_1 + ep.y_3); + evals[12] = evals[12] + y_double_identity * domainSep * wire(p, WIRE.Q_ELLIPTIC) * q_is_double; + } + } + + // Parameters used within the Memory Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct MemParams { + Fr memory_record_check; + Fr partial_record_check; + Fr next_gate_access_type; + Fr record_delta; + Fr index_delta; + Fr adjacent_values_match_if_adjacent_indices_match; + Fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; + Fr access_check; + Fr next_gate_access_type_is_boolean; + Fr ROM_consistency_check_identity; + Fr RAM_consistency_check_identity; + Fr timestamp_delta; + Fr RAM_timestamp_check_identity; + Fr memory_identity; + Fr index_is_monotonically_increasing; + } + + function accumulateMemoryRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + MemParams memory ap; + + /** + * MEMORY + * + * A RAM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) + * * v: `value` of memory cell being accessed + * * a: `access` type of record. read: 0 = read, 1 = write + * * r: `record` of memory cell. record = access + index * eta + timestamp * eta_two + value * eta_three + * + * A ROM memory record contains a tuple of the following fields: + * * i: `index` of memory cell being accessed + * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) + * * r: `record` of memory cell. record = index * eta + value2 * eta_two + value1 * eta_three + * + * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + + * selectors, depending on whether the gate is a RAM read/write or a ROM read + * + * | gate type | i | v2/t | v | a | r | + * | --------- | -- | ----- | -- | -- | -- | + * | ROM | w1 | w2 | w3 | -- | w4 | + * | RAM | w1 | w2 | w3 | qc | w4 | + * + * (for accesses where `index` is a circuit constant, it is assumed the circuit will apply a copy constraint on + * `w2` to fix its value) + * + * + */ + + /** + * Memory Record Check + * Partial degree: 1 + * Total degree: 4 + * + * A ROM/ROM access gate can be evaluated with the identity: + * + * qc + w1 \eta + w2 \eta_two + w3 \eta_three - w4 = 0 + * + * For ROM gates, qc = 0 + */ + ap.memory_record_check = wire(p, WIRE.W_O) * rp.etaThree; + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_R) * rp.etaTwo); + ap.memory_record_check = ap.memory_record_check + (wire(p, WIRE.W_L) * rp.eta); + ap.memory_record_check = ap.memory_record_check + wire(p, WIRE.Q_C); + ap.partial_record_check = ap.memory_record_check; // used in RAM consistency check; deg 1 or 4 + ap.memory_record_check = ap.memory_record_check - wire(p, WIRE.W_4); + + /** + * Contribution 13 & 14 + * ROM Consistency Check + * Partial degree: 1 + * Total degree: 4 + * + * For every ROM read, a set equivalence check is applied between the record witnesses, and a second set of + * records that are sorted. + * + * We apply the following checks for the sorted records: + * + * 1. w1, w2, w3 correctly map to 'index', 'v1, 'v2' for a given record value at w4 + * 2. index values for adjacent records are monotonically increasing + * 3. if, at gate i, index_i == index_{i + 1}, then value1_i == value1_{i + 1} and value2_i == value2_{i + 1} + * + */ + ap.index_delta = wire(p, WIRE.W_L_SHIFT) - wire(p, WIRE.W_L); + ap.record_delta = wire(p, WIRE.W_4_SHIFT) - wire(p, WIRE.W_4); + + ap.index_is_monotonically_increasing = ap.index_delta * ap.index_delta - ap.index_delta; // deg 2 + + ap.adjacent_values_match_if_adjacent_indices_match = (ap.index_delta * MINUS_ONE + ONE) * ap.record_delta; // deg 2 + + evals[14] = ap.adjacent_values_match_if_adjacent_indices_match * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + evals[15] = ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)) + * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 + + ap.ROM_consistency_check_identity = ap.memory_record_check * (wire(p, WIRE.Q_L) * wire(p, WIRE.Q_R)); // deg 3 or 7 + + /** + * Contributions 15,16,17 + * RAM Consistency Check + * + * The 'access' type of the record is extracted with the expression `w_4 - ap.partial_record_check` + * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * This is validated by requiring `access` to be boolean + * + * For two adjacent entries in the sorted list if _both_ + * A) index values match + * B) adjacent access value is 0 (i.e. next gate is a READ) + * then + * C) both values must match. + * The gate boolean check is + * (A && B) => C === !(A && B) || C === !A || !B || C + * + * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized + * with a WRITE operation. + */ + Fr access_type = (wire(p, WIRE.W_4) - ap.partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 + ap.access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + + // reverse order we could re-use `ap.partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta + // deg 1 or 4 + ap.next_gate_access_type = wire(p, WIRE.W_O_SHIFT) * rp.etaThree; + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_R_SHIFT) * rp.etaTwo); + ap.next_gate_access_type = ap.next_gate_access_type + (wire(p, WIRE.W_L_SHIFT) * rp.eta); + ap.next_gate_access_type = wire(p, WIRE.W_4_SHIFT) - ap.next_gate_access_type; + + Fr value_delta = wire(p, WIRE.W_O_SHIFT) - wire(p, WIRE.W_O); + ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (ap.index_delta * MINUS_ONE + ONE) * value_delta * (ap.next_gate_access_type * MINUS_ONE + ONE); // deg 3 or 6 + + // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the + // next gate would make the identity fail). We need to validate that its 'access type' bool is correct. Can't + // do with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access + // type is correct, to cover this edge case + // deg 2 or 4 + ap.next_gate_access_type_is_boolean = + ap.next_gate_access_type * ap.next_gate_access_type - ap.next_gate_access_type; + + // Putting it all together... + evals[16] = ap.adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation + * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 5 or 8 + evals[17] = + ap.index_is_monotonically_increasing * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 + evals[18] = ap.next_gate_access_type_is_boolean * (wire(p, WIRE.Q_ARITH)) * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 6 + + ap.RAM_consistency_check_identity = ap.access_check * (wire(p, WIRE.Q_ARITH)); // deg 3 or 9 + + /** + * RAM Timestamp Consistency Check + * + * | w1 | w2 | w3 | w4 | + * | index | timestamp | timestamp_check | -- | + * + * Let delta_index = index_{i + 1} - index_{i} + * + * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i + * Else timestamp_check = 0 + */ + ap.timestamp_delta = wire(p, WIRE.W_R_SHIFT) - wire(p, WIRE.W_R); + ap.RAM_timestamp_check_identity = (ap.index_delta * MINUS_ONE + ONE) * ap.timestamp_delta - wire(p, WIRE.W_O); // deg 3 + + /** + * Complete Contribution 12 + * The complete RAM/ROM memory identity + * Partial degree: + */ + ap.memory_identity = ap.ROM_consistency_check_identity; // deg 3 or 6 + ap.memory_identity = + ap.memory_identity + ap.RAM_timestamp_check_identity * (wire(p, WIRE.Q_4) * wire(p, WIRE.Q_L)); // deg 4 + ap.memory_identity = ap.memory_identity + ap.memory_record_check * (wire(p, WIRE.Q_M) * wire(p, WIRE.Q_L)); // deg 3 or 6 + ap.memory_identity = ap.memory_identity + ap.RAM_consistency_check_identity; // deg 3 or 9 + + // (deg 3 or 9) + (deg 4) + (deg 3) + ap.memory_identity = ap.memory_identity * (wire(p, WIRE.Q_MEMORY) * domainSep); // deg 4 or 10 + evals[13] = ap.memory_identity; + } + + // Constants for the Non-native Field relation + Fr constant LIMB_SIZE = Fr.wrap(uint256(1) << 68); + Fr constant SUBLIMB_SHIFT = Fr.wrap(uint256(1) << 14); + + // Parameters used within the Non-Native Field Relation + // A struct is used to work around stack too deep. This relation has alot of variables + struct NnfParams { + Fr limb_subproduct; + Fr non_native_field_gate_1; + Fr non_native_field_gate_2; + Fr non_native_field_gate_3; + Fr limb_accumulator_1; + Fr limb_accumulator_2; + Fr nnf_identity; + } + + function accumulateNnfRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Honk.RelationParameters memory rp, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + NnfParams memory ap; + + /** + * Contribution 12 + * Non native field arithmetic gate 2 + * deg 4 + * + * _ _ + * / _ _ _ 14 \ + * q_2 . q_4 | (w_1 . w_2) + (w_1 . w_2) + (w_1 . w_4 + w_2 . w_3 - w_3) . 2 - w_3 - w_4 | + * \_ _/ + * + * + */ + ap.limb_subproduct = wire(p, WIRE.W_L) * wire(p, WIRE.W_R_SHIFT) + wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R); + ap.non_native_field_gate_2 = + (wire(p, WIRE.W_L) * wire(p, WIRE.W_4) + wire(p, WIRE.W_R) * wire(p, WIRE.W_O) - wire(p, WIRE.W_O_SHIFT)); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * LIMB_SIZE; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 - wire(p, WIRE.W_4_SHIFT); + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 + ap.limb_subproduct; + ap.non_native_field_gate_2 = ap.non_native_field_gate_2 * wire(p, WIRE.Q_4); + + ap.limb_subproduct = ap.limb_subproduct * LIMB_SIZE; + ap.limb_subproduct = ap.limb_subproduct + (wire(p, WIRE.W_L_SHIFT) * wire(p, WIRE.W_R_SHIFT)); + ap.non_native_field_gate_1 = ap.limb_subproduct; + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 - (wire(p, WIRE.W_O) + wire(p, WIRE.W_4)); + ap.non_native_field_gate_1 = ap.non_native_field_gate_1 * wire(p, WIRE.Q_O); + + ap.non_native_field_gate_3 = ap.limb_subproduct; + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 + wire(p, WIRE.W_4); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 - (wire(p, WIRE.W_O_SHIFT) + wire(p, WIRE.W_4_SHIFT)); + ap.non_native_field_gate_3 = ap.non_native_field_gate_3 * wire(p, WIRE.Q_M); + + Fr non_native_field_identity = + ap.non_native_field_gate_1 + ap.non_native_field_gate_2 + ap.non_native_field_gate_3; + non_native_field_identity = non_native_field_identity * wire(p, WIRE.Q_R); + + // ((((w2' * 2^14 + w1') * 2^14 + w3) * 2^14 + w2) * 2^14 + w1 - w4) * qm + // deg 2 + ap.limb_accumulator_1 = wire(p, WIRE.W_R_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_O); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_R); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * SUBLIMB_SHIFT; + ap.limb_accumulator_1 = ap.limb_accumulator_1 + wire(p, WIRE.W_L); + ap.limb_accumulator_1 = ap.limb_accumulator_1 - wire(p, WIRE.W_4); + ap.limb_accumulator_1 = ap.limb_accumulator_1 * wire(p, WIRE.Q_4); + + // ((((w3' * 2^14 + w2') * 2^14 + w1') * 2^14 + w4) * 2^14 + w3 - w4') * qm + // deg 2 + ap.limb_accumulator_2 = wire(p, WIRE.W_O_SHIFT) * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_R_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_L_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_4); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * SUBLIMB_SHIFT; + ap.limb_accumulator_2 = ap.limb_accumulator_2 + wire(p, WIRE.W_O); + ap.limb_accumulator_2 = ap.limb_accumulator_2 - wire(p, WIRE.W_4_SHIFT); + ap.limb_accumulator_2 = ap.limb_accumulator_2 * wire(p, WIRE.Q_M); + + Fr limb_accumulator_identity = ap.limb_accumulator_1 + ap.limb_accumulator_2; + limb_accumulator_identity = limb_accumulator_identity * wire(p, WIRE.Q_O); // deg 3 + + ap.nnf_identity = non_native_field_identity + limb_accumulator_identity; + ap.nnf_identity = ap.nnf_identity * (wire(p, WIRE.Q_NNF) * domainSep); + evals[19] = ap.nnf_identity; + } + + struct PoseidonExternalParams { + Fr s1; + Fr s2; + Fr s3; + Fr s4; + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr t0; + Fr t1; + Fr t2; + Fr t3; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonExternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep // i guess this is the scaling factor? + ) internal pure { + PoseidonExternalParams memory ep; + + ep.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + ep.s2 = wire(p, WIRE.W_R) + wire(p, WIRE.Q_R); + ep.s3 = wire(p, WIRE.W_O) + wire(p, WIRE.Q_O); + ep.s4 = wire(p, WIRE.W_4) + wire(p, WIRE.Q_4); + + ep.u1 = ep.s1 * ep.s1 * ep.s1 * ep.s1 * ep.s1; + ep.u2 = ep.s2 * ep.s2 * ep.s2 * ep.s2 * ep.s2; + ep.u3 = ep.s3 * ep.s3 * ep.s3 * ep.s3 * ep.s3; + ep.u4 = ep.s4 * ep.s4 * ep.s4 * ep.s4 * ep.s4; + // matrix mul v = M_E * u with 14 additions + ep.t0 = ep.u1 + ep.u2; // u_1 + u_2 + ep.t1 = ep.u3 + ep.u4; // u_3 + u_4 + ep.t2 = ep.u2 + ep.u2 + ep.t1; // 2u_2 + // ep.t2 += ep.t1; // 2u_2 + u_3 + u_4 + ep.t3 = ep.u4 + ep.u4 + ep.t0; // 2u_4 + // ep.t3 += ep.t0; // u_1 + u_2 + 2u_4 + ep.v4 = ep.t1 + ep.t1; + ep.v4 = ep.v4 + ep.v4 + ep.t3; + // ep.v4 += ep.t3; // u_1 + u_2 + 4u_3 + 6u_4 + ep.v2 = ep.t0 + ep.t0; + ep.v2 = ep.v2 + ep.v2 + ep.t2; + // ep.v2 += ep.t2; // 4u_1 + 6u_2 + u_3 + u_4 + ep.v1 = ep.t3 + ep.v2; // 5u_1 + 7u_2 + u_3 + 3u_4 + ep.v3 = ep.t2 + ep.v4; // u_1 + 3u_2 + 5u_3 + 7u_4 + + ep.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_EXTERNAL) * domainSep; + evals[20] = evals[20] + ep.q_pos_by_scaling * (ep.v1 - wire(p, WIRE.W_L_SHIFT)); + + evals[21] = evals[21] + ep.q_pos_by_scaling * (ep.v2 - wire(p, WIRE.W_R_SHIFT)); + + evals[22] = evals[22] + ep.q_pos_by_scaling * (ep.v3 - wire(p, WIRE.W_O_SHIFT)); + + evals[23] = evals[23] + ep.q_pos_by_scaling * (ep.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + struct PoseidonInternalParams { + Fr u1; + Fr u2; + Fr u3; + Fr u4; + Fr u_sum; + Fr v1; + Fr v2; + Fr v3; + Fr v4; + Fr s1; + Fr q_pos_by_scaling; + } + + function accumulatePoseidonInternalRelation( + Fr[NUMBER_OF_ENTITIES] memory p, + Fr[NUMBER_OF_SUBRELATIONS] memory evals, + Fr domainSep + ) internal pure { + PoseidonInternalParams memory ip; + + Fr[4] memory INTERNAL_MATRIX_DIAGONAL = [ + FrLib.from(0x10dc6e9c006ea38b04b1e03b4bd9490c0d03f98929ca1d7fb56821fd19d3b6e7), + FrLib.from(0x0c28145b6a44df3e0149b3d0a30b3bb599df9756d4dd9b84a86b38cfb45a740b), + FrLib.from(0x00544b8338791518b2c7645a50392798b21f75bb60e3596170067d00141cac15), + FrLib.from(0x222c01175718386f2e2e82eb122789e352e105a3b8fa852613bc534433ee428b) + ]; + + // add round constants + ip.s1 = wire(p, WIRE.W_L) + wire(p, WIRE.Q_L); + + // apply s-box round + ip.u1 = ip.s1 * ip.s1 * ip.s1 * ip.s1 * ip.s1; + ip.u2 = wire(p, WIRE.W_R); + ip.u3 = wire(p, WIRE.W_O); + ip.u4 = wire(p, WIRE.W_4); + + // matrix mul with v = M_I * u 4 muls and 7 additions + ip.u_sum = ip.u1 + ip.u2 + ip.u3 + ip.u4; + + ip.q_pos_by_scaling = wire(p, WIRE.Q_POSEIDON2_INTERNAL) * domainSep; + + ip.v1 = ip.u1 * INTERNAL_MATRIX_DIAGONAL[0] + ip.u_sum; + evals[24] = evals[24] + ip.q_pos_by_scaling * (ip.v1 - wire(p, WIRE.W_L_SHIFT)); + + ip.v2 = ip.u2 * INTERNAL_MATRIX_DIAGONAL[1] + ip.u_sum; + evals[25] = evals[25] + ip.q_pos_by_scaling * (ip.v2 - wire(p, WIRE.W_R_SHIFT)); + + ip.v3 = ip.u3 * INTERNAL_MATRIX_DIAGONAL[2] + ip.u_sum; + evals[26] = evals[26] + ip.q_pos_by_scaling * (ip.v3 - wire(p, WIRE.W_O_SHIFT)); + + ip.v4 = ip.u4 * INTERNAL_MATRIX_DIAGONAL[3] + ip.u_sum; + evals[27] = evals[27] + ip.q_pos_by_scaling * (ip.v4 - wire(p, WIRE.W_4_SHIFT)); + } + + function scaleAndBatchSubrelations( + Fr[NUMBER_OF_SUBRELATIONS] memory evaluations, + Fr[NUMBER_OF_ALPHAS] memory subrelationChallenges + ) internal pure returns (Fr accumulator) { + accumulator = accumulator + evaluations[0]; + + for (uint256 i = 1; i < NUMBER_OF_SUBRELATIONS; ++i) { + accumulator = accumulator + evaluations[i] * subrelationChallenges[i - 1]; + } + } +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + Fr[4] denominators; + Fr[4] batchingScalars; + // 1/(z - r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr posInvertedDenominator; + // 1/(z + r^{2^i}) for i = 0, ..., logSize, dynamically updated + Fr negInvertedDenominator; + // ν^{2i} * 1/(z - r^{2^i}) + Fr scalingFactorPos; + // ν^{2i+1} * 1/(z + r^{2^i}) + Fr scalingFactorNeg; + // Fold_i(r^{2^i}) reconstructed by Verifier + Fr[CONST_PROOF_SIZE_LOG_N] foldPosEvaluations; + } + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., m-1 + + function computeFoldPosEvaluations( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - geminiEvaluations[i - 1] * (challengePower * (ONE - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (ONE - u) + u).invert(); + if (i <= logSize) { + batchedEvalAccumulator = batchedEvalRoundAcc; + foldPosEvaluations[i - 1] = batchedEvalRoundAcc; + } + } + } +} + +uint256 constant Q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // EC group order. F_q + +function bytes32ToString(bytes32 value) pure returns (string memory result) { + bytes memory alphabet = "0123456789abcdef"; + + bytes memory str = new bytes(66); + str[0] = "0"; + str[1] = "x"; + for (uint256 i = 0; i < 32; i++) { + str[2 + i * 2] = alphabet[uint8(value[i] >> 4)]; + str[3 + i * 2] = alphabet[uint8(value[i] & 0x0f)]; + } + result = string(str); +} + +// Fr utility + +function bytesToFr(bytes calldata proofSection) pure returns (Fr scalar) { + require(proofSection.length == 0x20, "invalid number of bytes to construct Fr scalar"); + scalar = FrLib.fromBytes32(bytes32(proofSection)); +} + +// EC Point utilities + +function convertProofPoint(Honk.G1ProofPoint memory input) pure returns (Honk.G1Point memory point) { + point = Honk.G1Point({x: input.x_0 | (input.x_1 << 136), y: input.y_0 | (input.y_1 << 136)}); +} + +function bytesToG1ProofPoint(bytes calldata proofSection) pure returns (Honk.G1ProofPoint memory point) { + require(proofSection.length == 0x80, "invalid number of bytes to construct a G1 point"); + point = Honk.G1ProofPoint({ + x_0: uint256(bytes32(proofSection[0x00:0x20])), + x_1: uint256(bytes32(proofSection[0x20:0x40])), + y_0: uint256(bytes32(proofSection[0x40:0x60])), + y_1: uint256(bytes32(proofSection[0x60:0x80])) + }); +} + +function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point memory) { + point.y = (Q - point.y) % Q; + return point; +} + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool decodedResult) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G2 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G2 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + decodedResult = success && abi.decode(result, (bool)); +} + +// Field arithmetic libraries - prevent littering the code with modmul / addmul + + + + +abstract contract BaseZKHonkVerifier is IVerifier { + using FrLib for Fr; + + uint256 immutable $N; + uint256 immutable $LOG_N; + uint256 immutable $NUM_PUBLIC_INPUTS; + + constructor(uint256 _N, uint256 _logN, uint256 _numPublicInputs) { + $N = _N; + $LOG_N = _logN; + $NUM_PUBLIC_INPUTS = _numPublicInputs; + } + + // Errors + error ProofLengthWrong(); + error PublicInputsLengthWrong(); + error SumcheckFailed(); + error ShpleminiFailed(); + error GeminiChallengeInSubgroup(); + error ConsistencyCheckFailed(); + + // Number of field elements in a ultra honk zero knowledge proof + uint256 constant PROOF_SIZE = 508; + + function loadVerificationKey() internal pure virtual returns (Honk.VerificationKey memory); + + function verify(bytes calldata proof, bytes32[] calldata publicInputs) + public + view + override + returns (bool verified) + { + // Check the received proof is the expected size where each field element is 32 bytes + if (proof.length != PROOF_SIZE * 32) { + revert ProofLengthWrong(); + } + + Honk.VerificationKey memory vk = loadVerificationKey(); + Honk.ZKProof memory p = ZKTranscriptLib.loadProof(proof); + + if (publicInputs.length != vk.publicInputsSize - PAIRING_POINTS_SIZE) { + revert PublicInputsLengthWrong(); + } + + // Generate the fiat shamir challenges for the whole protocol + ZKTranscript memory t = ZKTranscriptLib.generateTranscript( + p, publicInputs, vk.circuitSize, $NUM_PUBLIC_INPUTS, /*pubInputsOffset=*/ 1 + ); + + // Derive public input delta + t.relationParameters.publicInputsDelta = computePublicInputDelta( + publicInputs, + p.pairingPointObject, + t.relationParameters.beta, + t.relationParameters.gamma, /*pubInputsOffset=*/ + 1 + ); + + // Sumcheck + if (!verifySumcheck(p, t)) revert SumcheckFailed(); + + if (!verifyShplemini(p, vk, t)) revert ShpleminiFailed(); + + verified = true; + } + + function computePublicInputDelta( + bytes32[] memory publicInputs, + Fr[PAIRING_POINTS_SIZE] memory pairingPointObject, + Fr beta, + Fr gamma, + uint256 offset + ) internal view returns (Fr publicInputDelta) { + Fr numerator = Fr.wrap(1); + Fr denominator = Fr.wrap(1); + + Fr numeratorAcc = gamma + (beta * FrLib.from($N + offset)); + Fr denominatorAcc = gamma - (beta * FrLib.from(offset + 1)); + + { + for (uint256 i = 0; i < $NUM_PUBLIC_INPUTS - PAIRING_POINTS_SIZE; i++) { + Fr pubInput = FrLib.fromBytes32(publicInputs[i]); + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + + for (uint256 i = 0; i < PAIRING_POINTS_SIZE; i++) { + Fr pubInput = pairingPointObject[i]; + + numerator = numerator * (numeratorAcc + pubInput); + denominator = denominator * (denominatorAcc + pubInput); + + numeratorAcc = numeratorAcc + beta; + denominatorAcc = denominatorAcc - beta; + } + } + + // Fr delta = numerator / denominator; // TOOO: batch invert later? + publicInputDelta = FrLib.div(numerator, denominator); + } + + function verifySumcheck(Honk.ZKProof memory proof, ZKTranscript memory tp) internal view returns (bool verified) { + Fr roundTargetSum = tp.libraChallenge * proof.libraSum; // default 0 + Fr powPartialEvaluation = Fr.wrap(1); + + // We perform sumcheck reductions over log n rounds ( the multivariate degree ) + for (uint256 round; round < $LOG_N; ++round) { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariate = proof.sumcheckUnivariates[round]; + Fr totalSum = roundUnivariate[0] + roundUnivariate[1]; + if (totalSum != roundTargetSum) revert SumcheckFailed(); + + Fr roundChallenge = tp.sumCheckUChallenges[round]; + + // Update the round target for the next rounf + roundTargetSum = computeNextTargetSum(roundUnivariate, roundChallenge); + powPartialEvaluation = + powPartialEvaluation * (Fr.wrap(1) + roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + } + + // Last round + Fr grandHonkRelationSum = RelationsLib.accumulateRelationEvaluations( + proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation + ); + + Fr evaluation = Fr.wrap(1); + for (uint256 i = 2; i < $LOG_N; i++) { + evaluation = evaluation * tp.sumCheckUChallenges[i]; + } + + grandHonkRelationSum = + grandHonkRelationSum * (Fr.wrap(1) - evaluation) + proof.libraEvaluation * tp.libraChallenge; + verified = (grandHonkRelationSum == roundTargetSum); + } + + // Return the new target sum for the next sumcheck round + function computeNextTargetSum(Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory roundUnivariates, Fr roundChallenge) + internal + view + returns (Fr targetSum) + { + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory BARYCENTRIC_LAGRANGE_DENOMINATORS = [ + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000000240), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593effffd31), + Fr.wrap(0x00000000000000000000000000000000000000000000000000000000000005a0), + Fr.wrap(0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffec51), + Fr.wrap(0x0000000000000000000000000000000000000000000000000000000000009d80) + ]; + + // To compute the next target sum, we evaluate the given univariate at a point u (challenge). + + // Performing Barycentric evaluations + // Compute B(x) + Fr numeratorValue = Fr.wrap(1); + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + numeratorValue = numeratorValue * (roundChallenge - Fr.wrap(i)); + } + + Fr[ZK_BATCHED_RELATION_PARTIAL_LENGTH] memory denominatorInverses; + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + denominatorInverses[i] = FrLib.invert(BARYCENTRIC_LAGRANGE_DENOMINATORS[i] * (roundChallenge - Fr.wrap(i))); + } + + for (uint256 i = 0; i < ZK_BATCHED_RELATION_PARTIAL_LENGTH; ++i) { + targetSum = targetSum + roundUnivariates[i] * denominatorInverses[i]; + } + + // Scale the sum by the value of B(x) + targetSum = targetSum * numeratorValue; + } + + uint256 constant LIBRA_COMMITMENTS = 3; + uint256 constant LIBRA_EVALUATIONS = 4; + uint256 constant LIBRA_UNIVARIATES_LENGTH = 9; + + function verifyShplemini(Honk.ZKProof memory proof, Honk.VerificationKey memory vk, ZKTranscript memory tp) + internal + view + returns (bool verified) + { + CommitmentSchemeLib.ShpleminiIntermediates memory mem; // stack + + // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size + Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = + CommitmentSchemeLib.computeSquares(tp.geminiR); + // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars; + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory commitments; + + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[0]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[0]).invert(); + + mem.unshiftedScalar = mem.posInvertedDenominator + (tp.shplonkNu * mem.negInvertedDenominator); + mem.shiftedScalar = + tp.geminiR.invert() * (mem.posInvertedDenominator - (tp.shplonkNu * mem.negInvertedDenominator)); + + scalars[0] = Fr.wrap(1); + commitments[0] = convertProofPoint(proof.shplonkQ); + + /* Batch multivariate opening claims, shifted and unshifted + * The vector of scalars is populated as follows: + * \f[ + * \left( + * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), + * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), + * \ldots, + * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) + * \right) + * \f] + * + * The following vector is concatenated to the vector of commitments: + * \f[ + * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} + * \f] + * + * Simultaneously, the evaluation of the multilinear polynomial + * \f[ + * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} + * \f] + * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. + * + * This approach minimizes the number of iterations over the commitments to multilinear polynomials + * and eliminates the need to store the powers of \f$ \rho \f$. + */ + mem.batchedEvaluation = proof.geminiMaskingEval; + mem.batchingChallenge = tp.rho; + scalars[1] = mem.unshiftedScalar.neg(); + for (uint256 i = 0; i < NUMBER_UNSHIFTED; ++i) { + scalars[i + 2] = mem.unshiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + // g commitments are accumulated at r + for (uint256 i = NUMBER_UNSHIFTED; i < NUMBER_OF_ENTITIES; ++i) { + scalars[i + 2] = mem.shiftedScalar.neg() * mem.batchingChallenge; + mem.batchedEvaluation = mem.batchedEvaluation + (proof.sumcheckEvaluations[i] * mem.batchingChallenge); + mem.batchingChallenge = mem.batchingChallenge * tp.rho; + } + + commitments[1] = convertProofPoint(proof.geminiMaskingPoly); + + commitments[2] = vk.qm; + commitments[3] = vk.qc; + commitments[4] = vk.ql; + commitments[5] = vk.qr; + commitments[6] = vk.qo; + commitments[7] = vk.q4; + commitments[8] = vk.qLookup; + commitments[9] = vk.qArith; + commitments[10] = vk.qDeltaRange; + commitments[11] = vk.qElliptic; + commitments[12] = vk.qMemory; + commitments[13] = vk.qNnf; + commitments[14] = vk.qPoseidon2External; + commitments[15] = vk.qPoseidon2Internal; + commitments[16] = vk.s1; + commitments[17] = vk.s2; + commitments[18] = vk.s3; + commitments[19] = vk.s4; + commitments[20] = vk.id1; + commitments[21] = vk.id2; + commitments[22] = vk.id3; + commitments[23] = vk.id4; + commitments[24] = vk.t1; + commitments[25] = vk.t2; + commitments[26] = vk.t3; + commitments[27] = vk.t4; + commitments[28] = vk.lagrangeFirst; + commitments[29] = vk.lagrangeLast; + + // Accumulate proof points + commitments[30] = convertProofPoint(proof.w1); + commitments[31] = convertProofPoint(proof.w2); + commitments[32] = convertProofPoint(proof.w3); + commitments[33] = convertProofPoint(proof.w4); + commitments[34] = convertProofPoint(proof.zPerm); + commitments[35] = convertProofPoint(proof.lookupInverses); + commitments[36] = convertProofPoint(proof.lookupReadCounts); + commitments[37] = convertProofPoint(proof.lookupReadTags); + + // to be Shifted + commitments[38] = convertProofPoint(proof.w1); + commitments[39] = convertProofPoint(proof.w2); + commitments[40] = convertProofPoint(proof.w3); + commitments[41] = convertProofPoint(proof.w4); + commitments[42] = convertProofPoint(proof.zPerm); + + /* Batch gemini claims from the prover + * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from + * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars + * + * 1. Moves the vector + * \f[ + * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) + * \f] + * to the 'commitments' vector. + * + * 2. Computes the scalars: + * \f[ + * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} + * \f] + * and places them into the 'scalars' vector. + * + * 3. Accumulates the summands of the constant term: + * \f[ + * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} + * \f] + * and adds them to the 'constant_term_accumulator'. + */ + + // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: + // Compute the evaluations Aₗ(r^{2ˡ}) for l = 0, ..., $LOG_N - 1 + Fr[CONST_PROOF_SIZE_LOG_N] memory foldPosEvaluations = CommitmentSchemeLib.computeFoldPosEvaluations( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + $LOG_N + ); + + mem.constantTermAccumulator = foldPosEvaluations[0] * mem.posInvertedDenominator; + mem.constantTermAccumulator = + mem.constantTermAccumulator + (proof.geminiAEvaluations[0] * tp.shplonkNu * mem.negInvertedDenominator); + + mem.batchingChallenge = tp.shplonkNu.sqr(); + uint256 boundary = NUMBER_OF_ENTITIES + 2; + + // Compute Shplonk constant term contributions from Aₗ(± r^{2ˡ}) for l = 1, ..., m-1; + // Compute scalar multipliers for each fold commitment + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) { + bool dummy_round = i >= ($LOG_N - 1); + + if (!dummy_round) { + // Update inverted denominators + mem.posInvertedDenominator = (tp.shplonkZ - powers_of_evaluation_challenge[i + 1]).invert(); + mem.negInvertedDenominator = (tp.shplonkZ + powers_of_evaluation_challenge[i + 1]).invert(); + + // Compute the scalar multipliers for Aₗ(± r^{2ˡ}) and [Aₗ] + mem.scalingFactorPos = mem.batchingChallenge * mem.posInvertedDenominator; + mem.scalingFactorNeg = mem.batchingChallenge * tp.shplonkNu * mem.negInvertedDenominator; + scalars[boundary + i] = mem.scalingFactorNeg.neg() + mem.scalingFactorPos.neg(); + + // Accumulate the const term contribution given by + // v^{2l} * Aₗ(r^{2ˡ}) /(z-r^{2^l}) + v^{2l+1} * Aₗ(-r^{2ˡ}) /(z+ r^{2^l}) + Fr accumContribution = mem.scalingFactorNeg * proof.geminiAEvaluations[i + 1]; + accumContribution = accumContribution + mem.scalingFactorPos * foldPosEvaluations[i + 1]; + mem.constantTermAccumulator = mem.constantTermAccumulator + accumContribution; + } + // Update the running power of v + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + + commitments[boundary + i] = convertProofPoint(proof.geminiFoldComms[i]); + } + + boundary += CONST_PROOF_SIZE_LOG_N - 1; + + // Finalise the batch opening claim + mem.denominators[0] = Fr.wrap(1).div(tp.shplonkZ - tp.geminiR); + mem.denominators[1] = Fr.wrap(1).div(tp.shplonkZ - SUBGROUP_GENERATOR * tp.geminiR); + mem.denominators[2] = mem.denominators[0]; + mem.denominators[3] = mem.denominators[0]; + + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu * tp.shplonkNu; + for (uint256 i = 0; i < LIBRA_EVALUATIONS; i++) { + Fr scalingFactor = mem.denominators[i] * mem.batchingChallenge; + mem.batchingScalars[i] = scalingFactor.neg(); + mem.batchingChallenge = mem.batchingChallenge * tp.shplonkNu; + mem.constantTermAccumulator = mem.constantTermAccumulator + scalingFactor * proof.libraPolyEvals[i]; + } + scalars[boundary] = mem.batchingScalars[0]; + scalars[boundary + 1] = mem.batchingScalars[1] + mem.batchingScalars[2]; + scalars[boundary + 2] = mem.batchingScalars[3]; + + for (uint256 i = 0; i < LIBRA_COMMITMENTS; i++) { + commitments[boundary++] = convertProofPoint(proof.libraCommitments[i]); + } + + commitments[boundary] = Honk.G1Point({x: 1, y: 2}); + scalars[boundary++] = mem.constantTermAccumulator; + + if (!checkEvalsConsistency(proof.libraPolyEvals, tp.geminiR, tp.sumCheckUChallenges, proof.libraEvaluation)) { + revert ConsistencyCheckFailed(); + } + + Honk.G1Point memory quotient_commitment = convertProofPoint(proof.kzgQuotient); + + commitments[boundary] = quotient_commitment; + scalars[boundary] = tp.shplonkZ; // evaluation challenge + + Honk.G1Point memory P_0 = batchMul(commitments, scalars); + Honk.G1Point memory P_1 = negateInplace(quotient_commitment); + + return pairing(P_0, P_1); + } + + struct SmallSubgroupIpaIntermediates { + Fr[SUBGROUP_SIZE] challengePolyLagrange; + Fr challengePolyEval; + Fr lagrangeFirst; + Fr lagrangeLast; + Fr rootPower; + Fr[SUBGROUP_SIZE] denominators; // this has to disappear + Fr diff; + } + + function checkEvalsConsistency( + Fr[LIBRA_EVALUATIONS] memory libraPolyEvals, + Fr geminiR, + Fr[CONST_PROOF_SIZE_LOG_N] memory uChallenges, + Fr libraEval + ) internal view returns (bool check) { + Fr one = Fr.wrap(1); + Fr vanishingPolyEval = geminiR.pow(SUBGROUP_SIZE) - one; + if (vanishingPolyEval == Fr.wrap(0)) { + revert GeminiChallengeInSubgroup(); + } + + SmallSubgroupIpaIntermediates memory mem; + mem.challengePolyLagrange[0] = one; + for (uint256 round = 0; round < CONST_PROOF_SIZE_LOG_N; round++) { + uint256 currIdx = 1 + LIBRA_UNIVARIATES_LENGTH * round; + mem.challengePolyLagrange[currIdx] = one; + for (uint256 idx = currIdx + 1; idx < currIdx + LIBRA_UNIVARIATES_LENGTH; idx++) { + mem.challengePolyLagrange[idx] = mem.challengePolyLagrange[idx - 1] * uChallenges[round]; + } + } + + mem.rootPower = one; + mem.challengePolyEval = Fr.wrap(0); + for (uint256 idx = 0; idx < SUBGROUP_SIZE; idx++) { + mem.denominators[idx] = mem.rootPower * geminiR - one; + mem.denominators[idx] = mem.denominators[idx].invert(); + mem.challengePolyEval = mem.challengePolyEval + mem.challengePolyLagrange[idx] * mem.denominators[idx]; + mem.rootPower = mem.rootPower * SUBGROUP_GENERATOR_INVERSE; + } + + Fr numerator = vanishingPolyEval * Fr.wrap(SUBGROUP_SIZE).invert(); + mem.challengePolyEval = mem.challengePolyEval * numerator; + mem.lagrangeFirst = mem.denominators[0] * numerator; + mem.lagrangeLast = mem.denominators[SUBGROUP_SIZE - 1] * numerator; + + mem.diff = mem.lagrangeFirst * libraPolyEvals[2]; + + mem.diff = mem.diff + + (geminiR - SUBGROUP_GENERATOR_INVERSE) + * (libraPolyEvals[1] - libraPolyEvals[2] - libraPolyEvals[0] * mem.challengePolyEval); + mem.diff = mem.diff + mem.lagrangeLast * (libraPolyEvals[2] - libraEval) - vanishingPolyEval * libraPolyEvals[3]; + + check = mem.diff == Fr.wrap(0); + } + + // This implementation is the same as above with different constants + function batchMul( + Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory base, + Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3] memory scalars + ) internal view returns (Honk.G1Point memory result) { + uint256 limit = NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + LIBRA_COMMITMENTS + 3; + assembly { + let success := 0x01 + let free := mload(0x40) + + // Write the original into the accumulator + // Load into memory for ecMUL, leave offset for eccAdd result + // base is an array of pointers, so we have to dereference them + mstore(add(free, 0x40), mload(mload(base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalars)) + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, free, 0x40)) + + let count := 0x01 + for {} lt(count, limit) { count := add(count, 1) } { + // Get loop offsets + let base_base := add(base, mul(count, 0x20)) + let scalar_base := add(scalars, mul(count, 0x20)) + + mstore(add(free, 0x40), mload(mload(base_base))) + mstore(add(free, 0x60), mload(add(0x20, mload(base_base)))) + // Add scalar + mstore(add(free, 0x80), mload(scalar_base)) + + success := and(success, staticcall(gas(), 7, add(free, 0x40), 0x60, add(free, 0x40), 0x40)) + // accumulator = accumulator + accumulator_2 + success := and(success, staticcall(gas(), 6, free, 0x80, free, 0x40)) + } + + // Return the result + mstore(result, mload(free)) + mstore(add(result, 0x20), mload(add(free, 0x20))) + } + } +} + +contract HonkVerifier is BaseZKHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { + function loadVerificationKey() internal pure override returns (Honk.VerificationKey memory) { + return HonkVerificationKey.loadVerificationKey(); + } +} diff --git a/eth/package.json b/eth/package.json index 27d5ac1..93f9bca 100644 --- a/eth/package.json +++ b/eth/package.json @@ -7,12 +7,23 @@ "test": "hardhat test", "compile": "hardhat compile", "deploy": "hardhat run scripts/deploy.ts", - "deploy:local": "yarn deploy --network localhost", + "deploy:local": "yarn deploy-rollup:local && yarn deploy-across:local && yarn deploy-social-recovery:local", + "deploy-rollup:local": "yarn deploy --network localhost", + "deploy-across": "hardhat run scripts/deploy-across.ts", + "deploy-across:local": "yarn deploy-across --network localhost", + "deploy-social-recovery": "hardhat run scripts/deploy-social-recovery.ts", + "deploy-social-recovery:local": "yarn deploy-social-recovery --network localhost", + "deploy-eip7702": "hardhat run scripts/deploy_eip7702.ts", + "deploy-eip7702:local": "yarn deploy-eip7702 --network localhost", + "extract-mints": "hardhat run scripts/extract-mints.ts", + "filter-mints": "hardhat run scripts/filter-mints.ts", + "submit-mints": "hardhat run scripts/submit-mints.ts", "upgrade-rollup": "hardhat run scripts/upgrade.ts", "upgrade-rollup:local": "yarn upgrade-rollup --network localhost", "eth-node": "hardhat node" }, "devDependencies": { + "@nomicfoundation/hardhat-chai-matchers": "2.0.8", "@nomicfoundation/hardhat-ethers": "^3.0.5", "@nomicfoundation/hardhat-ignition": "^0.15.1", "@nomicfoundation/hardhat-ignition-viem": "^0.15.0", @@ -34,7 +45,7 @@ "eslint-plugin-promise": "^6.0.0", "ethereum-cryptography": "^2.1.2", "ethers": "^6.9.1", - "hardhat": "^2.18.1", + "hardhat": "^2.26.1", "hardhat-gas-reporter": "^1.0.8", "solidity-coverage": "^0.8.0", "ts-node": ">=8.0.0", diff --git a/eth/scripts/deploy-across.ts b/eth/scripts/deploy-across.ts new file mode 100644 index 0000000..938249d --- /dev/null +++ b/eth/scripts/deploy-across.ts @@ -0,0 +1,71 @@ +import hre from "hardhat"; + +const ACROSS_ADRESSES: Record = { + // Ethereum Mainnet + 1: "0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5", + // Base + 8453: "0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64", + // Polygon + 137: "0x9295ee1d8c5b022be115a2ad3c30c72e34e7f096", + // BNB + 56: "0x4e8E101924eDE233C13e2D8622DC8aED2872d505", + // Arbitrum + 42161: "0xe35e9842fceaCA96570B734083f4a58e8F7C5f2A", + // Optimism + 10: "0x6f26bf09b1c792e3228e5467807a900a503c0281", +}; + +async function main(): Promise { + const chainId = hre.network.config.chainId ?? "DEV"; + + let acrossAddress = process.env.ACROSS_ADDRESS as `0x${string}` | undefined; + let owner = process.env.OWNER as `0x${string}` | undefined; + + if (acrossAddress === undefined) { + acrossAddress = ACROSS_ADRESSES[chainId]; + } + + if (!acrossAddress && (chainId === "DEV" || chainId === 1337)) { + console.log( + "Deploying mock AcrossWithAuthorization for local development...", + ); + owner = owner ?? "0x0000000000000000000000000000000000000000"; + // A simple mock contract deployment for local testing + const mockAcross = await hre.viem.deployContract( + "AcrossWithAuthorization", + ["0x0000000000000000000000000000000000000000", owner], + ); + acrossAddress = mockAcross.address; + console.log(`Mock AcrossWithAuthorization deployed at: ${acrossAddress}`); + } + + if (!acrossAddress) { + throw new Error( + `ACROSS_ADDRESS address not found for chainId ${chainId}. Please set ACROSS_ADDRESS environment variable.`, + ); + } + + if (owner === undefined) { + throw new Error( + "OWNER environment variable is not set. Please set it to the owner address.", + ); + } + + console.log( + `Deploying AcrossWithAuthorization with across address: ${acrossAddress}`, + ); + + const acrossWithAuth = await hre.viem.deployContract( + "AcrossWithAuthorization", + [acrossAddress, owner], + ); + + console.log( + `ACROSS_WITH_AUTHORIZATION_CONTRACT_ADDR=${acrossWithAuth.address}`, + ); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/eth/scripts/deploy-social-recovery.ts b/eth/scripts/deploy-social-recovery.ts new file mode 100644 index 0000000..378b794 --- /dev/null +++ b/eth/scripts/deploy-social-recovery.ts @@ -0,0 +1,21 @@ +import hre from "hardhat"; + +async function main(): Promise { + const [owner] = await hre.viem.getWalletClients(); + + const socialRecovery = await hre.viem.deployContract( + "contracts/SocialRecovery.sol:SocialRecovery", + [owner.account.address], + ); + + console.log( + `SOCIAL_RECOVERY_CONTRACT_ADDRESS=${socialRecovery.address}`, + ); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); + + diff --git a/eth/scripts/deploy-usdc.ts b/eth/scripts/deploy-usdc.ts new file mode 100644 index 0000000..13fc0ac --- /dev/null +++ b/eth/scripts/deploy-usdc.ts @@ -0,0 +1,25 @@ +import hre from "hardhat"; +import { deployBin } from "./shared"; + +const CHAINS = ["BASE", "ARB", "OPT", "ETH"]; + +async function main(): Promise { + const chainId = hre.network.config.chainId ?? "DEV"; + const isDev = chainId === "DEV" || chainId === 1337; + + if (!isDev) { + throw new Error("ONLY use in DEV"); + } + + for (const chain of CHAINS) { + const usdcContractAddr = await deployBin("USDC.bin"); + console.log(`${chain}_USDC_CONTRACT_ADDR=${usdcContractAddr}`); + } + + console.error("All contracts deployed"); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/eth/scripts/deploy.ts b/eth/scripts/deploy.ts index 72a1ee2..103d091 100644 --- a/eth/scripts/deploy.ts +++ b/eth/scripts/deploy.ts @@ -1,318 +1,367 @@ -import { readFile } from 'fs/promises' -import { join } from 'path' -import hre from 'hardhat' -import { encodeFunctionData } from 'viem' -import { deployBin } from './shared' - -const USDC_ADDRESSES: Record = { +import { readFile } from "fs/promises"; +import hre from "hardhat"; +import { encodeFunctionData, keccak256, stringToBytes } from "viem"; +import { deployBin, deployBytecode } from "./shared"; +import { + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, + generateNoteKindBridgeEvm, +} from "./noteKind"; + +type LinkReferences = Record< + string, + Record> +>; + +// Auto-updated by generate_fixturecs.sh - do not modify manually +const AGG_FINAL_VERIFICATION_KEY_HASH = + "0x122d2ac7542fa020cbfff0836b5d0c30898330074b19869179bba49b5db69967"; + +const USDC_ADDRESSES: Record = { // Ethereum Mainnet - 1: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + 1: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // Ethereum Goerli Testnet // 5: '0x07865c6e87b9f70255377e024ace6630c1eaa37f', // Polygon Mainnet - 137: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359' + 137: POLYGON_USDC_ADDRESS, // Polygon Mumbai Testnet // 80001: '0x2058A9D7613eEE744279e3856Ef0eAda5FCbaA7e' -} +}; + +const DEFAULT_VERIFIER_MESSAGES_COUNT = 1000; +// Legacy note kind used across all deployments for backwards compatibility. +const LEGACY_POLYGON_USDC_NOTE_KIND = generateNoteKindBridgeEvm( + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, +); + +const HONK_VERIFIER_SUFFIX = "_HonkVerifier.bin"; + +const computePlaceholder = (fullyQualifiedLibName: string): string => { + const hash = keccak256(stringToBytes(fullyQualifiedLibName)).slice(2); + return `__$${hash.slice(0, 34)}$__`; +}; + +// Note: this is only used when deploying with the no-op verifier, +// because we need to pad out the libraries +// that would otherwise get deployed, +// to get stable addresses. +const deployLibrariesForProgram = async (binFile: string): Promise => { + const linkRefPath = `contracts/${binFile.replace(/\.bin$/, ".linkrefs.json")}`; + + let linkRefsRaw: string; + try { + linkRefsRaw = await readFile(linkRefPath, "utf8"); + } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") { + return; + } + throw error; + } + + const linkRefs = JSON.parse(linkRefsRaw) as LinkReferences; + const hasLibraries = Object.values(linkRefs).some( + (libraries) => Object.keys(libraries).length > 0, + ); + if (!hasLibraries) return; + + const programDir = + binFile.lastIndexOf("/") >= 0 + ? binFile.slice(0, binFile.lastIndexOf("/")) + : ""; + const programFilename = binFile.slice(binFile.lastIndexOf("/") + 1); + if (!programFilename.endsWith(HONK_VERIFIER_SUFFIX)) { + throw new Error( + `Cannot infer program name from ${binFile}; expected suffix ${HONK_VERIFIER_SUFFIX}`, + ); + } + + const programName = programFilename.slice(0, -HONK_VERIFIER_SUFFIX.length); + const prefix = programDir.length > 0 ? `${programDir}/` : ""; + + for (const libraries of Object.values(linkRefs)) { + for (const libraryName of Object.keys(libraries)) { + const libraryBinFile = `${prefix}${programName}_${libraryName}.bin`; + await deployBin(libraryBinFile); + } + } +}; + +const linkAndDeployVerifier = async ( + binFile: string, +): Promise<`0x${string}`> => { + const binPath = `contracts/${binFile}`; + const unlinkedBytecode = (await readFile(binPath, "utf8")).trimEnd(); + const linkRefFile = `contracts/${binFile.replace( + /\.bin$/, + ".linkrefs.json", + )}`; + + let linkRefsRaw: string; + try { + linkRefsRaw = await readFile(linkRefFile, "utf8"); + } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") { + if (unlinkedBytecode.includes("__$")) { + throw new Error( + `Missing link reference metadata for ${binFile}. ` + + "Re-run noir/generate_fixtures.sh to regenerate verifier artifacts.", + ); + } + return deployBytecode(unlinkedBytecode); + } + throw error; + } + + const linkRefs = JSON.parse(linkRefsRaw) as LinkReferences; + const hasLibraries = Object.values(linkRefs).some( + (libraries) => Object.keys(libraries).length > 0, + ); + if (!hasLibraries) { + return deployBytecode(unlinkedBytecode); + } + + const programDir = + binFile.lastIndexOf("/") >= 0 + ? binFile.slice(0, binFile.lastIndexOf("/")) + : ""; + const programFilename = binFile.slice(binFile.lastIndexOf("/") + 1); + if (!programFilename.endsWith(HONK_VERIFIER_SUFFIX)) { + throw new Error( + `Cannot infer program name from ${binFile}; expected suffix ${HONK_VERIFIER_SUFFIX}`, + ); + } + + const programName = programFilename.slice(0, -HONK_VERIFIER_SUFFIX.length); + const prefix = programDir.length > 0 ? `${programDir}/` : ""; + + const placeholderMappings = new Map(); + + for (const [sourceName, libraries] of Object.entries(linkRefs)) { + for (const libraryName of Object.keys(libraries)) { + const placeholder = computePlaceholder(`${sourceName}:${libraryName}`); + if (placeholderMappings.has(placeholder)) continue; + + const libraryBinFile = `${prefix}${programName}_${libraryName}.bin`; + let libraryAddress: `0x${string}`; + try { + libraryAddress = await deployBin(libraryBinFile); + } catch (error) { + if ((error as NodeJS.ErrnoException).code === "ENOENT") { + throw new Error( + `Missing bytecode for ${libraryName} at ${libraryBinFile}. ` + + "Re-run noir/generate_fixtures.sh to regenerate verifier artifacts.", + ); + } + throw error; + } + placeholderMappings.set(placeholder, libraryAddress); + console.log( + `Linked library ${libraryName} (${placeholder}) at ${libraryAddress}`, + ); + } + } + + let linkedBytecode = unlinkedBytecode; + for (const [placeholder, address] of placeholderMappings.entries()) { + if (!linkedBytecode.includes(placeholder)) { + throw new Error( + `Placeholder ${placeholder} not found in bytecode for ${binFile}`, + ); + } + linkedBytecode = linkedBytecode + .split(placeholder) + .join(address.replace(/^0x/, "")); + } + + return await deployBytecode(linkedBytecode); +}; async function main(): Promise { - const chainId = hre.network.config.chainId ?? 'DEV' - const useNoopVerifier = process.env.DEV_USE_NOOP_VERIFIER === '1' - const [owner] = await hre.viem.getWalletClients() - const publicClient = await hre.viem.getPublicClient() + const chainId = hre.network.config.chainId ?? "DEV"; + const useNoopVerifier = process.env.DEV_USE_NOOP_VERIFIER === "1"; + const [owner] = await hre.viem.getWalletClients(); + const publicClient = await hre.viem.getPublicClient(); - let usdcAddress: string - let isDev = false + let usdcAddress: string; + let isDev = false; // Create a local version of USDC for testing if (USDC_ADDRESSES[chainId] === undefined) { - const usdcContractAddr = await deployBin('USDC.bin') - console.log(`USDC_CONTRACT_ADDR=${usdcContractAddr}`) - usdcAddress = usdcContractAddr - isDev = true + const usdcContractAddr = await deployBin("USDC.bin"); + console.log(`USDC_CONTRACT_ADDR=${usdcContractAddr}`); + usdcAddress = usdcContractAddr; + isDev = true; } else { - usdcAddress = USDC_ADDRESSES[chainId] + usdcAddress = USDC_ADDRESSES[chainId]; } - let acrossSpokePool = process.env.ACROSS_SPOKE_POOL as `0x${string}` | undefined - if (acrossSpokePool !== undefined && !acrossSpokePool.startsWith('0x')) { - throw new Error('ACROSS_SPOKE_POOL is not a valid address') + let acrossSpokePool = process.env.ACROSS_SPOKE_POOL as + | `0x${string}` + | undefined; + if (acrossSpokePool !== undefined && !acrossSpokePool.startsWith("0x")) { + throw new Error("ACROSS_SPOKE_POOL is not a valid address"); } if (!isDev && useNoopVerifier) { - throw new Error('Cannot use no-op verifier if not deploying for dev') + throw new Error("Cannot use no-op verifier if not deploying for dev"); } else if (useNoopVerifier) { - console.warn('Warning: using no-op verifier') + console.warn("Warning: using no-op verifier"); } - const maybeNoopVerifier = (verifier: string) => useNoopVerifier ? 'NoopVerifier.bin' : verifier + const maybeNoopVerifier = (verifier: string) => + useNoopVerifier ? "NoopVerifierHonk.bin" : verifier; - let proverAddress = process.env.PROVER_ADDRESS as `0x${string}` - let validators = process.env.VALIDATORS?.split(',') ?? [] as Array<`0x${string}`> - let ownerAddress = process.env.OWNER as `0x${string}` + let proverAddress = process.env.PROVER_ADDRESS as `0x${string}`; + let validators = + process.env.VALIDATORS?.split(",") ?? ([] as Array<`0x${string}`>); + let ownerAddress = process.env.OWNER as `0x${string}`; if (!isDev) { - if (proverAddress === undefined) throw new Error('PROVER_ADDRESS is not set') - if (validators.length === 0) throw new Error('VALIDATORS is not set') - if (ownerAddress === undefined) throw new Error('OWNER is not set') + if (proverAddress === undefined) + throw new Error("PROVER_ADDRESS is not set"); + if (validators.length === 0) throw new Error("VALIDATORS is not set"); + if (ownerAddress === undefined) throw new Error("OWNER is not set"); } else { if (proverAddress === undefined) { - proverAddress = owner.account.address + proverAddress = owner.account.address; } if (validators.length === 0) { - validators = [owner.account.address] + validators = [owner.account.address]; } if (ownerAddress === undefined) { - ownerAddress = owner.account.address + ownerAddress = owner.account.address; } } - const deployerIsProxyAdmin = ownerAddress.toLowerCase() === owner.account.address.toLowerCase() - - console.error({ proverAddress, validators, ownerAddress, deployerIsProxyAdmin }) - - // Aggregate verifier - const aggregateBinAddr = await deployBin(maybeNoopVerifier('AggregateVerifier.bin')) - console.log(`AGGREGATE_BIN_ADDR=${aggregateBinAddr}`) + const deployerIsProxyAdmin = + ownerAddress.toLowerCase() === owner.account.address.toLowerCase(); - const aggregateVerifier = await hre.viem.deployContract('AggregateVerifierV1', [aggregateBinAddr], {}) - console.log(`AGGREGATE_VERIFIER_ADDR=${aggregateVerifier.address}`) - - // Mint verifier - const mintBinAddr = await deployBin('MintVerifier.bin') - console.log(`MINT_BIN_ADDR=${mintBinAddr}`) - - const mintVerifier = await hre.viem.deployContract('MintVerifierV1', [mintBinAddr], {}) - console.log(`MINT_VERIFIER_ADDR=${mintVerifier.address}`) - - // Burn verifier - const burnBinAddr = await deployBin('BurnVerifier.bin') - console.log(`BURN_BIN_ADDR=${burnBinAddr}`) + console.error({ + proverAddress, + validators, + ownerAddress, + deployerIsProxyAdmin, + }); - const burnVerifier = await hre.viem.deployContract('BurnVerifierV1', [burnBinAddr], {}) - console.log(`BURN_VERIFIER_ADDR=${burnVerifier.address}`) + if (useNoopVerifier) { + await deployLibrariesForProgram("noir/agg_final_HonkVerifier.bin"); + } - const emptyMerkleTreeRootHash = (await readFile(join(__dirname, '../../pkg/contracts/src/empty_merkle_tree_root_hash.txt'))).toString().trimEnd() + const aggregateBinFile = maybeNoopVerifier("noir/agg_final_HonkVerifier.bin"); + const aggregateVerifierAddr = await linkAndDeployVerifier(aggregateBinFile); + console.log(`AGGREGATE_VERIFIER_ADDR=${aggregateVerifierAddr}`); - const rollupV1 = await hre.viem.deployContract('RollupV1' as any, [], {}) - console.log(`ROLLUP_V1_CONTRACT_ADDR=${rollupV1.address}`) + const rollupV1 = await hre.viem.deployContract( + "contracts/rollup3/RollupV1.sol:RollupV1", + ); + console.log(`ROLLUP_V1_IMPL_ADDR=${rollupV1.address}`); const rollupInitializeCalldata = encodeFunctionData({ - abi: [rollupV1.abi.find((x) => x.type === 'function' && x.name === 'initialize') as any], - // @ts-expect-error We know the ABI has this function - name: 'initialize', + abi: rollupV1.abi, + functionName: "initialize", args: [ ownerAddress, usdcAddress, - aggregateVerifier.address, - mintVerifier.address, - burnVerifier.address, + aggregateVerifierAddr, proverAddress, validators, - emptyMerkleTreeRootHash - ] - }) - - const rollupProxy = await hre.viem.deployContract('@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy', [ - rollupV1.address, - ownerAddress, - rollupInitializeCalldata - ], {}) - - const eip1967AdminStorageSlot = '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103' + AGG_FINAL_VERIFICATION_KEY_HASH, + DEFAULT_VERIFIER_MESSAGES_COUNT, + LEGACY_POLYGON_USDC_NOTE_KIND, + ], + }); + + const rollupProxy = await hre.viem.deployContract( + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy", + [rollupV1.address, ownerAddress, rollupInitializeCalldata], + {}, + ); + + console.log(`ROLLUP_CONTRACT_ADDR=${rollupProxy.address}`); + + const eip1967AdminStorageSlot = + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"; let admin = await publicClient.getStorageAt({ address: rollupProxy.address, - slot: eip1967AdminStorageSlot - }) - admin = `0x${admin?.slice(2 + 12 * 2)}` - - console.log(`ROLLUP_PROXY_ADMIN_ADDR=${admin}`) - - const proxyAdmin = await hre.viem.getContractAt('@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin', admin) - - const rollupV2 = await hre.viem.deployContract('RollupV2', []) - console.log(`ROLLUP_V2_CONTRACT_ADDR=${rollupV2.address}`) - - const rollupV2InitializeCalldata = encodeFunctionData({ - abi: [rollupV2.abi.find((x) => x.type === 'function' && x.name === 'initializeV2') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV2', - args: [] - }) - - async function maybeUpgrade(...args: [`0x${string}`, `0x${string}`, `0x${string}`]) { - if (deployerIsProxyAdmin) { - return await proxyAdmin.write.upgradeAndCall(args) - } else { - console.log('Deployer is not the proxy admin, skipping upgrade of rollup contract') - console.log('Please call the proxy admin upgradeAndCall function with the following arguments:') - console.log( - ...args - ) - } - } + slot: eip1967AdminStorageSlot, + }); + admin = `0x${admin?.slice(2 + 12 * 2)}`; - async function maybeCallAsRollupOwner(to: `0x${string}`, calldata: `0x${string}`) { - if (deployerIsProxyAdmin) { - const tx = await owner.sendTransaction({ - to, - data: calldata - }) - const receipt = await publicClient.waitForTransactionReceipt({ - hash: tx - }) - if (receipt.status === 'reverted') { - throw new Error(`Transaction ${tx} reverted. To: ${to}, Calldata: ${calldata}`) - } - } else { - console.log('Deployer is not the owner, skipping call') - console.log('Please make a call with the following arguments:') - console.log('\tTo:', to) - console.log('\tCalldata:', calldata) - } - } + console.log(`ROLLUP_PROXY_ADMIN_ADDR=${admin}`); - await maybeUpgrade( - rollupProxy.address, - rollupV2.address, - rollupV2InitializeCalldata - ) - - const rollupV3 = await hre.viem.deployContract('RollupV3', []) - console.log(`ROLLUP_V3_CONTRACT_ADDR=${rollupV3.address}`) - - const rollupV3InitializeCalldata = encodeFunctionData({ - abi: [rollupV3.abi.find((x) => x.type === 'function' && x.name === 'initializeV3') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV3', - args: [] - }) - - await maybeUpgrade( - rollupProxy.address, - rollupV3.address, - rollupV3InitializeCalldata - ) - - const rollupV4 = await hre.viem.deployContract('RollupV4', []) - console.log(`ROLLUP_V4_CONTRACT_ADDR=${rollupV4.address}`) - - const rollupV4InitializeCalldata = encodeFunctionData({ - abi: [rollupV4.abi.find((x) => x.type === 'function' && x.name === 'initializeV4') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV4', - args: [] - }) - - await maybeUpgrade( - rollupProxy.address, - rollupV4.address, - rollupV4InitializeCalldata - ) - - // Burn verifier V2 - const burnV2BinAddr = await deployBin('BurnVerifierV2.bin') - console.log(`BURN_V2_BIN_ADDR=${burnV2BinAddr}`) - - const burnVerifierV2 = await hre.viem.deployContract('BurnVerifierV2', [burnV2BinAddr], {}) - console.log(`BURN_VERIFIER_V2_ADDR=${burnVerifierV2.address}`) - - const [signerOwner] = await hre.ethers.getSigners() - const usdc = await hre.ethers.getContractAt('IUSDC', usdcAddress, signerOwner) + const [signerOwner] = await hre.ethers.getSigners(); + const usdc = await hre.ethers.getContractAt( + "IUSDC", + usdcAddress, + signerOwner, + ); if (isDev) { - if (owner.chain.name === 'hardhat') { + if (owner.chain.name === "hardhat") { await owner.sendTransaction({ to: proverAddress, - value: hre.ethers.parseEther('1') - }) + value: hre.ethers.parseEther("1"), + }); } - let res = await usdc.initialize('USD Coin', 'USDC', 'USD', 6, signerOwner.address, signerOwner.address, signerOwner.address, signerOwner.address, { - gasLimit: 1_000_000 - }) - await res.wait() - res = await usdc.initializeV2('USD Coin', { - gasLimit: 1_000_000 - }) - await res.wait() + let res = await usdc.initialize( + "USD Coin", + "USDC", + "USD", + 6, + signerOwner.address, + signerOwner.address, + signerOwner.address, + signerOwner.address, + { + gasLimit: 1_000_000, + }, + ); + await res.wait(); + res = await usdc.initializeV2("USD Coin", { + gasLimit: 1_000_000, + }); + await res.wait(); res = await usdc.initializeV2_1(signerOwner.address, { - gasLimit: 1_000_000 - }) - await res.wait() - res = await usdc.configureMinter(signerOwner.address, hre.ethers.parseUnits('1000000000', 6), { - gasLimit: 1_000_000 - }) - await res.wait() - - res = await usdc.mint(signerOwner.address, hre.ethers.parseUnits('1000000000', 6), { - gasLimit: 1_000_000 - }) - await res.wait() + gasLimit: 1_000_000, + }); + await res.wait(); + res = await usdc.configureMinter( + signerOwner.address, + hre.ethers.parseUnits("1000000000", 6), + { + gasLimit: 1_000_000, + }, + ); + await res.wait(); + + res = await usdc.mint( + signerOwner.address, + hre.ethers.parseUnits("1000000000", 6), + { + gasLimit: 1_000_000, + }, + ); + await res.wait(); } // Approve our rollup contract to spend USDC from the primary owner account const res = await usdc.approve(rollupProxy.address, hre.ethers.MaxUint256, { - gasLimit: 1_000_000 - }) - await res.wait() - - const rollupV5 = await hre.viem.deployContract('RollupV5', []) - console.log(`ROLLUP_V5_CONTRACT_ADDR=${rollupV5.address}`) - - const rollupV5InitializeCalldata = encodeFunctionData({ - abi: [rollupV5.abi.find((x) => x.type === 'function' && x.name === 'initializeV5') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV5', - args: [burnVerifierV2.address] - }) - - await maybeUpgrade( - rollupProxy.address, - rollupV5.address, - rollupV5InitializeCalldata - ) - - console.log(`ROLLUP_CONTRACT_ADDR=${rollupProxy.address}`) - - const rollupProxyV5 = await hre.viem.getContractAt('RollupV5', rollupProxy.address) - - const burnToAddressRouter = await hre.viem.deployContract('BurnToAddressRouter', [], {}) - console.log(`BURN_TO_ADDRESS_ROUTER_CONTRACT_ADDR=${burnToAddressRouter.address}`) - - await maybeCallAsRollupOwner(rollupProxy.address, encodeFunctionData({ - abi: [rollupProxyV5.abi.find((x) => x.type === 'function' && x.name === 'addRouter') as any], - // @ts-expect-error We know the ABI has this function - name: 'addRouter', - args: [burnToAddressRouter.address] - })) - - const rollupV6 = await hre.viem.deployContract('RollupV6', []) - console.log(`ROLLUP_V6_CONTRACT_ADDR=${rollupV6.address}`) - - const rollupV6InitializeCalldata = encodeFunctionData({ - abi: [rollupV6.abi.find((x) => x.type === 'function' && x.name === 'initializeV6') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV6', - args: [] - }) - - await maybeUpgrade( - rollupProxy.address, - rollupV6.address, - rollupV6InitializeCalldata - ) - - if (isDev && acrossSpokePool === undefined) { - acrossSpokePool = '0x0000000000000000000000000000000000000000' - } - const acrossWithAuthorization = await hre.viem.deployContract('AcrossWithAuthorization', [acrossSpokePool]) - console.log(`ACROSS_WITH_AUTHORIZATION_CONTRACT_ADDR=${acrossWithAuthorization.address}`) + gasLimit: 1_000_000, + }); + await res.wait(); + + // Deploy EIP-7702 delegate smart account implementation (meta-tx, no EntryPoint). + const eip7702Delegate = await hre.viem.deployContract( + "contracts/Eip7702SimpleAccount.sol:Eip7702SimpleAccount", + ); + console.log(`EIP7702_SIMPLE_ACCOUNT_ADDR=${eip7702Delegate.address}`); - console.error('All contracts deployed') + console.error("All contracts deployed"); } main().catch((error) => { - console.error(error) - process.exitCode = 1 -}) + console.error(error); + process.exitCode = 1; +}); diff --git a/eth/scripts/deploy_eip7702.ts b/eth/scripts/deploy_eip7702.ts new file mode 100644 index 0000000..513b5a0 --- /dev/null +++ b/eth/scripts/deploy_eip7702.ts @@ -0,0 +1,18 @@ +import hre from "hardhat"; + +// Deploy only the EIP-7702 delegate contract (Eip7702SimpleAccount) +// Usage: +// hardhat run scripts/deploy_eip7702.ts --network + +async function main(): Promise { + const contract = await hre.viem.deployContract( + "contracts/Eip7702SimpleAccount.sol:Eip7702SimpleAccount", + ); + console.log(`EIP7702_SIMPLE_ACCOUNT_ADDR=${contract.address}`); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); + diff --git a/eth/scripts/extract-mints.ts b/eth/scripts/extract-mints.ts new file mode 100644 index 0000000..9a011ca --- /dev/null +++ b/eth/scripts/extract-mints.ts @@ -0,0 +1,148 @@ +import { + createPublicClient, + decodeEventLog, + encodeEventTopics, + http, + type Hex, + type PublicClient +} from 'viem' +import { + ROLLUP_ABI, + chunkArray, + loadMints, + normalizeHex, + requireEnv, + saveMints, + withRetry, + type MintEntry +} from './lib/migration-utils' + +export interface ExtractConfig { + sourceRpcUrl: string + sourceAddress: Hex + outputFile: string + startBlock?: bigint + endBlock?: bigint + blockBatchSize?: bigint + concurrency?: number + retryAttempts?: number + client?: PublicClient +} + +export async function extractMints(config: ExtractConfig) { + console.log(`Loading state from ${config.outputFile}...`) + const mints = await loadMints(config.outputFile) + + const sourceClient = config.client ?? createPublicClient({ transport: http(config.sourceRpcUrl) }) + const latestBlock = await sourceClient.getBlockNumber() + + const startBlock = config.startBlock ?? 0n + const endBlock = config.endBlock ?? latestBlock + + console.log(`Extracting mints from ${startBlock} to ${endBlock} using ${config.sourceRpcUrl}`) + + const ranges: Array<{ from: bigint, to: bigint }> = [] + const batchSize = config.blockBatchSize ?? 10_000n + + for (let from = startBlock; from <= endBlock; from += batchSize) { + const to = from + batchSize - 1n > endBlock ? endBlock : from + batchSize - 1n + ranges.push({ from, to }) + } + + const chunks = chunkArray(ranges, config.concurrency ?? 5) + + const mintAddedTopic = encodeEventTopics({ abi: ROLLUP_ABI, eventName: 'MintAdded' })[0] + const mintedTopic = encodeEventTopics({ abi: ROLLUP_ABI, eventName: 'Minted' })[0] + + for (const chunk of chunks) { + await Promise.all( + chunk.map(async (range) => { + console.log(`Scanning blocks ${range.from} to ${range.to}`) + const logs = await withRetry(`getLogs(${range.from}-${range.to})`, config.retryAttempts ?? 3, async () => + await sourceClient.getLogs({ + address: config.sourceAddress, + fromBlock: range.from, + toBlock: range.to, + topics: [[mintAddedTopic, mintedTopic]] + } as any) + ) + + for (const log of logs) { + if (log.topics[0] === mintAddedTopic) { + const decoded = decodeEventLog({ + abi: ROLLUP_ABI, + eventName: 'MintAdded', + data: log.data, + topics: log.topics + }) + const args = decoded.args + const mintHash = args.mint_hash + + mints[mintHash] = { + mintHash, + value: args.value.toString(), + noteKind: args.note_kind, + blockNumber: (log.blockNumber ?? 0n).toString(), + spent: mints[mintHash]?.spent ?? false + } + } else if (log.topics[0] === mintedTopic) { + const decoded = decodeEventLog({ + abi: ROLLUP_ABI, + eventName: 'Minted', + data: log.data, + topics: log.topics + }) + const args = decoded.args + const hash = args.hash + + if (mints[hash] !== undefined) { + mints[hash].spent = true + } else { + const entry: MintEntry = { + mintHash: hash, + spent: true + } + mints[hash] = entry + } + } + } + }) + ) + + console.log(`Saving ${Object.keys(mints).length} mints to ${config.outputFile}...`) + await saveMints(config.outputFile, mints) + } + + console.log('Extraction complete.') +} + +async function main() { + const sourceRpcUrl = requireEnv('SOURCE_RPC_URL') + const sourceAddress = normalizeHex(requireEnv('SOURCE_CONTRACT_ADDRESS'), 'SOURCE_CONTRACT_ADDRESS') + const startBlock = process.env.START_BLOCK !== undefined ? BigInt(process.env.START_BLOCK) : undefined + const endBlock = process.env.END_BLOCK !== undefined ? BigInt(process.env.END_BLOCK) : undefined + const outputFile = process.env.OUTPUT_FILE ?? 'mints.json' + const blockBatchSize = process.env.BLOCK_BATCH_SIZE !== undefined ? BigInt(process.env.BLOCK_BATCH_SIZE) : undefined + const concurrency = process.env.RPC_CONCURRENCY !== undefined ? Number(process.env.RPC_CONCURRENCY) : undefined + const retryAttempts = process.env.RPC_RETRY_ATTEMPTS !== undefined ? Number(process.env.RPC_RETRY_ATTEMPTS) : undefined + + await extractMints({ + sourceRpcUrl, + sourceAddress, + outputFile, + startBlock, + endBlock, + blockBatchSize, + concurrency, + retryAttempts + }) +} + +if (require.main === module) { + main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) +} diff --git a/eth/scripts/filter-mints.ts b/eth/scripts/filter-mints.ts new file mode 100644 index 0000000..535375d --- /dev/null +++ b/eth/scripts/filter-mints.ts @@ -0,0 +1,128 @@ +import { createPublicClient, http, type Hex, type PublicClient } from 'viem' +import { + ROLLUP_ABI, + loadMints, + mapParallel, + normalizeHex, + requireEnv, + saveMints, + withRetry, + type MintEntry +} from './lib/migration-utils' + +export interface FilterConfig { + sourceRpcUrl: string + sourceAddress: Hex + inputFile: string + outputFile: string + concurrency?: number + retryAttempts?: number + client?: PublicClient +} + +interface OnChainMint { + note_kind: Hex + amount: bigint + spent: boolean +} + +export async function filterMints(config: FilterConfig) { + console.log(`Loading mints from ${config.inputFile}...`) + const mints = await loadMints(config.inputFile) + const allMints = Object.values(mints) + + const candidates = allMints.filter((m) => { + return !m.spent && m.value !== undefined && m.noteKind !== undefined + }) + + if (candidates.length === 0) { + console.log('No unspent candidates found in input file.') + return + } + + console.log(`Verifying ${candidates.length} candidates against source chain...`) + + const sourceClient = config.client ?? createPublicClient({ transport: http(config.sourceRpcUrl) }) + + const validMints: Record = {} + let verifiedCount = 0 + let invalidCount = 0 + + await mapParallel(candidates, config.concurrency ?? 10, async (mint) => { + try { + const result = await withRetry(`getMint(${mint.mintHash})`, config.retryAttempts ?? 3, async () => + await sourceClient.readContract({ + address: config.sourceAddress, + abi: ROLLUP_ABI, + functionName: 'getMint', + args: [mint.mintHash] + }) + ) as unknown as OnChainMint + + const onChainAmount = result.amount + const onChainSpent = result.spent + const onChainKind = result.note_kind + + if (onChainAmount === 0n) { + console.warn(`Mint ${mint.mintHash} does not exist on chain (amount 0)`) + invalidCount++ + return + } + + if (onChainSpent) { + console.warn(`Mint ${mint.mintHash} is marked spent on chain`) + invalidCount++ + return + } + + if (onChainAmount.toString() !== mint.value) { + console.warn(`Mint ${mint.mintHash} amount mismatch: local=${mint.value} chain=${onChainAmount}`) + invalidCount++ + return + } + + if (onChainKind !== mint.noteKind) { + console.warn(`Mint ${mint.mintHash} kind mismatch: local=${mint.noteKind} chain=${onChainKind}`) + invalidCount++ + return + } + + validMints[mint.mintHash] = mint + verifiedCount++ + } catch (e) { + console.error(`Failed to verify mint ${mint.mintHash}:`, e) + invalidCount++ + } + }) + + console.log(`Verification complete. Valid: ${verifiedCount}, Invalid: ${invalidCount}`) + await saveMints(config.outputFile, validMints) + console.log(`Saved valid mints to ${config.outputFile}`) +} + +async function main() { + const sourceRpcUrl = requireEnv('SOURCE_RPC_URL') + const sourceAddress = normalizeHex(requireEnv('SOURCE_CONTRACT_ADDRESS'), 'SOURCE_CONTRACT_ADDRESS') + const inputFile = process.env.INPUT_FILE ?? 'mints.json' + const outputFile = process.env.OUTPUT_FILE ?? 'filtered-mints.json' + const concurrency = process.env.RPC_CONCURRENCY !== undefined ? Number(process.env.RPC_CONCURRENCY) : undefined + const retryAttempts = process.env.RPC_RETRY_ATTEMPTS !== undefined ? Number(process.env.RPC_RETRY_ATTEMPTS) : undefined + + await filterMints({ + sourceRpcUrl, + sourceAddress, + inputFile, + outputFile, + concurrency, + retryAttempts + }) +} + +if (require.main === module) { + main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) +} diff --git a/eth/scripts/lib/migration-utils.ts b/eth/scripts/lib/migration-utils.ts new file mode 100644 index 0000000..9bf589f --- /dev/null +++ b/eth/scripts/lib/migration-utils.ts @@ -0,0 +1,144 @@ +import { readFile, writeFile } from 'fs/promises' +import { + defineChain, + parseAbi, + type Chain, + type Hex +} from 'viem' +import { + goerli, + mainnet, + polygon, + polygonAmoy, + polygonMumbai, + sepolia +} from 'viem/chains' + +export const ROLLUP_ABI = parseAbi([ + 'event MintAdded(bytes32 indexed mint_hash, uint256 value, bytes32 note_kind)', + 'event Minted(bytes32 indexed hash, bytes32 value, bytes32 note_kind)', + 'function mint(bytes32 mint_hash, bytes32 value, bytes32 note_kind)', + 'struct Mint { bytes32 note_kind; uint256 amount; bool spent; }', + 'function getMint(bytes32 hash) view returns (Mint)' +]) + +export interface MintEntry { + mintHash: Hex + value?: string + noteKind?: Hex + blockNumber?: string + spent: boolean +} + +export const requireEnv = (name: string): string => { + const value = process.env[name] + if (value === undefined || value === '') throw new Error(`${name} is required`) + return value +} + +export const normalizeHex = (value: string | undefined, label: string): Hex => { + if (value === undefined || value === '') throw new Error(`${label} is required`) + + const normalized = value.startsWith('0x') ? value : `0x${value}` + if (!/^0x[0-9a-fA-F]+$/.test(normalized)) { + throw new Error(`${label} must be a hex string`) + } + + return normalized as Hex +} + +const chainById = new Map([ + [mainnet.id, mainnet], + [goerli.id, goerli], + [sepolia.id, sepolia], + [polygon.id, polygon], + [polygonMumbai.id, polygonMumbai], + [polygonAmoy.id, polygonAmoy] +]) + +export const resolveChain = (chainId: number, rpcUrl: string): Chain => { + const known = chainById.get(chainId) + if (known !== undefined) return known + + return defineChain({ + id: chainId, + name: `chain-${chainId}`, + nativeCurrency: { name: 'Native', symbol: 'ETH', decimals: 18 }, + rpcUrls: { + default: { + http: [rpcUrl] + } + } + }) +} + +export const sleep = async (ms: number): Promise => { + await new Promise((resolve) => setTimeout(resolve, ms)) +} + +export const withRetry = async ( + label: string, + attempts: number, + fn: () => Promise +): Promise => { + let lastError: unknown + + for (let attempt = 1; attempt <= attempts; attempt++) { + try { + return await fn() + } catch (error) { + lastError = error + console.warn(`${label} failed (attempt ${attempt}/${attempts}):`, error) + if (attempt < attempts) { + await sleep(1000 * attempt) + } + } + } + + throw lastError +} + +export const chunkArray = (items: T[], size: number): T[][] => { + if (size <= 0) throw new Error('chunk size must be > 0') + + const chunks: T[][] = [] + for (let i = 0; i < items.length; i += size) { + chunks.push(items.slice(i, i + size)) + } + + return chunks +} + +export const mapParallel = async ( + items: T[], + concurrency: number, + fn: (item: T) => Promise +): Promise => { + const results = new Array(items.length) + let nextIndex = 0 + + const worker = async () => { + while (nextIndex < items.length) { + const index = nextIndex++ + results[index] = await fn(items[index]) + } + } + + const workers = Array.from({ length: Math.min(concurrency, items.length) }, worker) + await Promise.all(workers) + + return results +} + +export const saveMints = async (path: string, mints: Record) => { + await writeFile(path, JSON.stringify(mints, null, 2)) +} + +export const loadMints = async (path: string): Promise> => { + try { + const content = await readFile(path, 'utf8') + return JSON.parse(content) + } catch { + return {} + } +} diff --git a/eth/scripts/noteKind.ts b/eth/scripts/noteKind.ts new file mode 100644 index 0000000..9f4266b --- /dev/null +++ b/eth/scripts/noteKind.ts @@ -0,0 +1,36 @@ +import { bytesToHex, hexToBytes, type Hex } from "viem"; + +const NOTE_KIND_LENGTH = 32; +const ADDRESS_LENGTH = 20; + +export const BRIDGED_EVM_NOTE_KIND_FORMAT = 2n; +export const LEGACY_POLYGON_CHAIN_ID = 137n; +export const POLYGON_USDC_ADDRESS = + "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359" as `0x${string}`; + +export function generateNoteKindBridgeEvm( + chain: bigint, + address: `0x${string}`, +): Hex { + if (chain < 0n || chain > 0xffff_ffff_ffff_ffffn) { + throw new Error("chain must fit within uint64"); + } + + const bytes = new Uint8Array(NOTE_KIND_LENGTH); + const view = new DataView(bytes.buffer); + + view.setUint16( + 0, + Number(BRIDGED_EVM_NOTE_KIND_FORMAT), + false, + ); + view.setBigUint64(2, chain, false); + + const addressBytes = hexToBytes(address); + if (addressBytes.length !== ADDRESS_LENGTH) { + throw new Error("address must be exactly 20 bytes"); + } + bytes.set(addressBytes, 10); + + return bytesToHex(bytes); +} diff --git a/eth/scripts/shared.ts b/eth/scripts/shared.ts index 7937303..7f11c8b 100644 --- a/eth/scripts/shared.ts +++ b/eth/scripts/shared.ts @@ -1,22 +1,25 @@ import hre from 'hardhat' import { readFile } from 'fs/promises' -export async function deployBin(binFile: string): Promise<`0x${string}`> { - const bin = (await readFile(`contracts/${binFile}`)).toString().trimEnd() - - // console.log('Deploying contract of size: ', bin.length / 2, 'bytes') +export async function deployBytecode(bytecode: string): Promise<`0x${string}`> { + const normalized = bytecode.startsWith('0x') ? bytecode : `0x${bytecode}` const [owner] = await hre.viem.getWalletClients() - const verifierTx = await owner.deployContract({ + const deployTx = await owner.deployContract({ account: owner.account, - bytecode: `0x${bin}`, + bytecode: normalized, abi: [] }) const publicClient = await hre.viem.getPublicClient() - const verifierAddr = (await publicClient.waitForTransactionReceipt({ hash: verifierTx })).contractAddress + const deployedAddr = (await publicClient.waitForTransactionReceipt({ hash: deployTx })).contractAddress - if (verifierAddr === null || verifierAddr === undefined) throw new Error('Verifier address not found') + if (deployedAddr === null || deployedAddr === undefined) throw new Error('Verifier address not found') - return verifierAddr + return deployedAddr +} + +export async function deployBin(binFile: string): Promise<`0x${string}`> { + const bin = (await readFile(`contracts/${binFile}`)).toString().trimEnd() + return deployBytecode(bin) } diff --git a/eth/scripts/submit-mints.ts b/eth/scripts/submit-mints.ts new file mode 100644 index 0000000..f9573aa --- /dev/null +++ b/eth/scripts/submit-mints.ts @@ -0,0 +1,231 @@ +import { + createPublicClient, + createWalletClient, + encodeFunctionData, + http, + toHex, + type Hex, + type PublicClient, + type WalletClient +} from 'viem' +import { privateKeyToAccount } from 'viem/accounts' +import { + ROLLUP_ABI, + loadMints, + mapParallel, + normalizeHex, + requireEnv, + resolveChain, + withRetry, + type MintEntry +} from './lib/migration-utils' + +export interface SubmitConfig { + targetRpcUrl: string + targetAddress: Hex + privateKey: Hex + inputFile: string + concurrency?: number + retryAttempts?: number + dryRun?: boolean + printTx?: boolean + publicClient?: PublicClient + walletClient?: WalletClient +} + +interface MigratableMint extends MintEntry { + value: string + noteKind: Hex +} + +interface TxFeeOverrides { + maxFeePerGas: bigint + maxPriorityFeePerGas: bigint +} + +function isMigratable(m: MintEntry): m is MigratableMint { + if (m.spent) return false + if (m.value === undefined || m.noteKind === undefined) { + console.warn(`Skipping unspent mint ${m.mintHash} due to missing data (value/noteKind)`) + return false + } + return true +} + +async function getDoubledRecommendedFees(publicClient: PublicClient, retryAttempts: number): Promise { + const estimatedFees = await withRetry('estimateFeesPerGas', retryAttempts, async () => await publicClient.estimateFeesPerGas()) + if (estimatedFees.maxFeePerGas === undefined || estimatedFees.maxPriorityFeePerGas === undefined) { + throw new Error('Target chain does not expose EIP-1559 fee suggestions') + } + + return { + maxFeePerGas: estimatedFees.maxFeePerGas * 2n, + maxPriorityFeePerGas: estimatedFees.maxPriorityFeePerGas * 2n + } +} + +export async function submitMints(config: SubmitConfig) { + console.log(`Loading mints from ${config.inputFile}...`) + const mints = await loadMints(config.inputFile) + const allMints = Object.values(mints) + + const candidates = allMints.filter(isMigratable) + + if (candidates.length === 0) { + console.log('No candidates for migration found.') + return + } + + console.log(`Found ${candidates.length} unspent mints. Checking target chain for existence...`) + + const targetPublicClient = config.publicClient ?? createPublicClient({ transport: http(config.targetRpcUrl) }) + const chainId = await targetPublicClient.getChainId() + const targetChain = resolveChain(chainId, config.targetRpcUrl) + + const account = privateKeyToAccount(config.privateKey) + const targetWalletClient = config.walletClient ?? createWalletClient({ + account, + chain: targetChain, + transport: http(config.targetRpcUrl) + }) + + const candidateHashes = candidates.map((c) => c.mintHash) + const existingMints = new Set() + + await mapParallel(candidateHashes, config.concurrency ?? 5, async (hash) => { + const mint = await withRetry(`getMint(${hash})`, config.retryAttempts ?? 3, async () => + await targetPublicClient.readContract({ + address: config.targetAddress, + abi: ROLLUP_ABI, + functionName: 'getMint', + args: [hash] + }) + ) + + if (mint.amount > 0n) { + existingMints.add(hash) + } + }) + + const toMigrate = candidates.filter((c) => !existingMints.has(c.mintHash)) + + if (toMigrate.length === 0) { + console.log('All candidates already exist on target.') + return + } + + console.log(`Migrating ${toMigrate.length} mints...`) + + if (config.dryRun === true && config.printTx !== true) { + console.log('Dry run enabled. Exiting.') + return + } + + const feeOverrides = config.printTx === true ? undefined : await getDoubledRecommendedFees(targetPublicClient, config.retryAttempts ?? 3) + if (feeOverrides !== undefined) { + console.log( + `Using 2x recommended EIP-1559 fees: maxFeePerGas=${feeOverrides.maxFeePerGas}, maxPriorityFeePerGas=${feeOverrides.maxPriorityFeePerGas}` + ) + } + + const accountAddress = targetWalletClient.account?.address ?? account.address + let nonce = await targetPublicClient.getTransactionCount({ + address: accountAddress, + blockTag: 'latest' + }) + + console.log(`Starting migration from nonce ${nonce}`) + + const successfulSubmissions: { mintHash: Hex; txHash: Hex }[] = [] + + for (const [index, mint] of toMigrate.entries()) { + const valueBytes32 = toHex(BigInt(mint.value), { size: 32 }) + + if (config.printTx === true) { + const data = encodeFunctionData({ + abi: ROLLUP_ABI, + functionName: 'mint', + args: [mint.mintHash, valueBytes32, mint.noteKind] + }) + console.log(`\n--- Mint ${index + 1}/${toMigrate.length} ---`) + console.log(`Target: ${config.targetAddress}`) + console.log(`Mint Hash: ${mint.mintHash}`) + console.log(`Value: ${mint.value} (${valueBytes32})`) + console.log(`Data: ${data}`) + console.log(`Nonce: ${nonce}`) + nonce++ + continue + } + + if (feeOverrides === undefined) { + throw new Error('EIP-1559 fees are unavailable while submitting transactions') + } + + const txHash = await withRetry('mint', config.retryAttempts ?? 3, async () => + await targetWalletClient.writeContract({ + account: targetWalletClient.account ?? account, + chain: targetChain, + address: config.targetAddress, + abi: ROLLUP_ABI, + functionName: 'mint', + args: [mint.mintHash, valueBytes32, mint.noteKind], + nonce, + maxFeePerGas: feeOverrides.maxFeePerGas, + maxPriorityFeePerGas: feeOverrides.maxPriorityFeePerGas + }) + ) + successfulSubmissions.push({ mintHash: mint.mintHash, txHash }) + nonce++ + } + + if (config.printTx === true) return + + console.log(`Submitted ${successfulSubmissions.length} transactions. Waiting for receipts...`) + + let migratedCount = 0 + + await mapParallel(successfulSubmissions, config.concurrency ?? 5, async ({ mintHash, txHash }) => { + console.log(`Waiting for receipt: ${txHash}`) + const receipt = await withRetry('waitForReceipt', config.retryAttempts ?? 3, async () => + await targetPublicClient.waitForTransactionReceipt({ hash: txHash }) + ) + + if (receipt.status !== 'success') { + throw new Error(`Transaction ${txHash} reverted`) + } + + migratedCount++ + console.log(`Migrated ${migratedCount}/${toMigrate.length} (${mintHash})`) + }) +} + +async function main() { + const targetRpcUrl = requireEnv('TARGET_RPC_URL') + const targetAddress = normalizeHex(requireEnv('TARGET_CONTRACT_ADDRESS'), 'TARGET_CONTRACT_ADDRESS') + const privateKey = normalizeHex(requireEnv('PRIVATE_KEY'), 'PRIVATE_KEY') + const inputFile = process.env.INPUT_FILE ?? 'filtered-mints.json' + const concurrency = process.env.RPC_CONCURRENCY !== undefined ? Number(process.env.RPC_CONCURRENCY) : undefined + const retryAttempts = process.env.RPC_RETRY_ATTEMPTS !== undefined ? Number(process.env.RPC_RETRY_ATTEMPTS) : undefined + const dryRun = process.env.DRY_RUN === 'true' + const printTx = process.env.PRINT_TX === 'true' + + await submitMints({ + targetRpcUrl, + targetAddress, + privateKey, + inputFile, + concurrency, + retryAttempts, + dryRun, + printTx + }) +} + +if (require.main === module) { + main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) +} diff --git a/eth/scripts/upgrade.ts b/eth/scripts/upgrade.ts index e7da590..f80c795 100644 --- a/eth/scripts/upgrade.ts +++ b/eth/scripts/upgrade.ts @@ -1,7 +1,4 @@ import hre from 'hardhat' -// import { Json } from 'ethers' -import { encodeFunctionData } from 'viem' -import { deployBin } from './shared' async function main(): Promise { const rollupProxyAdminAddr = process.env.ROLLUP_PROXY_ADMIN_ADDR as `0x${string}` | undefined @@ -10,137 +7,25 @@ async function main(): Promise { const proxyRollupAddress = process.env.ROLLUP_CONTRACT_ADDR as `0x${string}` | undefined if (proxyRollupAddress === undefined) throw new Error('ROLLUP_CONTRACT_ADDR is not set') - const shouldDeploy = process.env.UPGRADE_DEPLOY === 'true' + await hre.viem.getContractAt( + '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin', + rollupProxyAdminAddr, + ) - // // This code is based on a test upgrade to a V2 version. - // // It was working when I tested on a sample V2 contract, - // // so it will be useful when we want to actually add a new version. - const [owner] = await hre.viem.getWalletClients() - const publicClient = await hre.viem.getPublicClient() + const rollupProxy = await hre.viem.getContractAt( + 'TransparentUpgradeableProxy', + proxyRollupAddress, + ) - const rollupProxy = await hre.viem.getContractAt('TransparentUpgradeableProxy', proxyRollupAddress) - - const rollupProxyAdmin = await hre.viem.getContractAt('@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin', rollupProxyAdminAddr) - - const maybeUpgradeRollup = async (newImpl: `0x${string}`, calldata: `0x${string}`) => { - if (shouldDeploy) { - await rollupProxyAdmin.write.upgradeAndCall([rollupProxy.address, newImpl, calldata]) - } - } - - const maybeCall = async (to: `0x${string}`, calldata: `0x${string}`) => { - if (shouldDeploy) { - const tx = await owner.sendTransaction({ - to, - data: calldata - }) - const receipt = await publicClient.waitForTransactionReceipt({ - hash: tx - }) - if (receipt.status === 'reverted') { - throw new Error(`Transaction ${tx} reverted. To: ${to}, Calldata: ${calldata}`) - } - } else { - console.log('Please make a call with the following arguments:') - console.log('\tTo:', to) - console.log('\tCalldata:', calldata) - } - } - - let version = await (await hre.viem.getContractAt('RollupV1', rollupProxy.address)).read.version() + const version = await ( + await hre.viem.getContractAt( + 'contracts/rollup3/RollupV1.sol:RollupV1', + rollupProxy.address, + ) + ).read.version() console.log('Current version:', version) - - if (version === 1) { - const rollupV2 = await hre.viem.deployContract('RollupV2', []) - console.log(`ROLLUP_V2_CONTRACT_ADDR=${rollupV2.address}`) - - const initializeV2Data = encodeFunctionData({ - abi: [rollupV2.abi.find(x => x.type === 'function' && x.name === 'initializeV2') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV2', - args: [] - }) - console.log(`ROLLUP_V2_INITIALIZE_V2_CALLDATA=${initializeV2Data}`) - await maybeUpgradeRollup(rollupV2.address, initializeV2Data) - version = 2 - } - - if (version === 2) { - const rollupV3 = await hre.viem.deployContract('RollupV3', []) - console.log(`ROLLUP_V3_CONTRACT_ADDR=${rollupV3.address}`) - - const initializeV3Data = encodeFunctionData({ - abi: [rollupV3.abi.find(x => x.type === 'function' && x.name === 'initializeV3') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV3', - args: [] - }) - console.log(`ROLLUP_V3_INITIALIZE_V3_CALLDATA=${initializeV3Data}`) - await maybeUpgradeRollup(rollupV3.address, initializeV3Data) - version = 3 - } - - if (version === 3) { - const rollupV4 = await hre.viem.deployContract('RollupV4', []) - console.log(`ROLLUP_V4_CONTRACT_ADDR=${rollupV4.address}`) - - const initializeV4Data = encodeFunctionData({ - abi: [rollupV4.abi.find(x => x.type === 'function' && x.name === 'initializeV4') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV4', - args: [] - }) - console.log(`ROLLUP_V4_INITIALIZE_V4_CALLDATA=${initializeV4Data}`) - await maybeUpgradeRollup(rollupV4.address, initializeV4Data) - version = 4 - } - - if (version === 4) { - const burnToAddressRouter = await hre.viem.deployContract('BurnToAddressRouter', []) - console.log(`BURN_TO_ADDRESS_ROUTER_CONTRACT_ADDR=${burnToAddressRouter.address}`) - - const burnV2BinAddr = await deployBin('BurnVerifierV2.bin') - console.log(`BURN_V2_BIN_ADDR=${burnV2BinAddr}`) - - const burnVerifierV2 = await hre.viem.deployContract('BurnVerifierV2', [burnV2BinAddr], {}) - console.log(`BURN_VERIFIER_V2_ADDR=${burnVerifierV2.address}`) - - const rollupV5 = await hre.viem.deployContract('RollupV5', []) - console.log(`ROLLUP_V5_CONTRACT_ADDR=${rollupV5.address}`) - - const initializeV5Data = encodeFunctionData({ - abi: [rollupV5.abi.find(x => x.type === 'function' && x.name === 'initializeV5') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV5', - args: [burnVerifierV2.address] - }) - - console.log(`ROLLUP_V5_INITIALIZE_V5_CALLDATA=${initializeV5Data}`) - await maybeUpgradeRollup(rollupV5.address, initializeV5Data) - await maybeCall(rollupProxy.address, encodeFunctionData({ - abi: [rollupV5.abi.find((x) => x.type === 'function' && x.name === 'addRouter') as any], - // @ts-expect-error We know the ABI has this function - name: 'addRouter', - args: [burnToAddressRouter.address] - })) - version = 5 - } - - if (version === 5) { - const rollupV6 = await hre.viem.deployContract('RollupV6', []) - console.log(`ROLLUP_V6_CONTRACT_ADDR=${rollupV6.address}`) - - const initializeV6Data = encodeFunctionData({ - abi: [rollupV6.abi.find(x => x.type === 'function' && x.name === 'initializeV6') as any], - // @ts-expect-error We know the ABI has this function - name: 'initializeV6', - args: [] - }) - console.log(`ROLLUP_V6_INITIALIZE_V6_CALLDATA=${initializeV6Data}`) - await maybeUpgradeRollup(rollupV6.address, initializeV6Data) - version = 6 - } + console.log('No upgrade steps required for RollupV1 deployments.') } main() diff --git a/eth/test/BlockHeightValidation.test.ts b/eth/test/BlockHeightValidation.test.ts new file mode 100644 index 0000000..e378c16 --- /dev/null +++ b/eth/test/BlockHeightValidation.test.ts @@ -0,0 +1,476 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { type SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, + generateNoteKindBridgeEvm, +} from "../scripts/noteKind"; + +describe("RollupV1 Block Height Validation", function () { + let rollup: any; + let mockUsdc: any; + let mockVerifier: any; + let owner: SignerWithAddress; + let prover: SignerWithAddress; + let validator1: SignerWithAddress; + let validator2: SignerWithAddress; + let validator3: SignerWithAddress; + + // Empty merkle tree root hash constant (from the contract initialization) + const INITIAL_ROOT = + "0x0577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff"; + const NEW_ROOT = + "0x0000000000000000000000000000000000000000000000000000000000000002"; + const VERIFIER_KEY_HASH = + "0x0000000000000000000000000000000000000000000000000000000000000003"; + const COMMIT_HASH = + "0x0000000000000000000000000000000000000000000000000000000000000004"; + const OTHER_HASH = + "0x0000000000000000000000000000000000000000000000000000000000000005"; + const TEST_VERIFIER_MESSAGES_COUNT = 2048; + const INITIAL_NOTE_KIND = generateNoteKindBridgeEvm( + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, + ); + + beforeEach(async function () { + [owner, prover, validator1, validator2, validator3] = + await ethers.getSigners(); + + // Deploy mock contracts + const mockUsdcFactory = await ethers.getContractFactory("MockERC20"); + mockUsdc = await mockUsdcFactory.deploy(); + + const MockVerifier = await ethers.getContractFactory("MockVerifier"); + mockVerifier = await MockVerifier.deploy(); + + // Deploy RollupV1 (rollup3 merged version) - skip initialization for now + const RollupV1Factory = await ethers.getContractFactory( + "contracts/rollup3/RollupV1.sol:RollupV1", + ); + const rollupImpl = await RollupV1Factory.deploy(); + + // Deploy proxy and initialize through proxy + const ERC1967Proxy = await ethers.getContractFactory( + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol:ERC1967Proxy", + ); + const initData = rollupImpl.interface.encodeFunctionData("initialize", [ + owner.address, + await mockUsdc.getAddress(), + await mockVerifier.getAddress(), + prover.address, + [validator1.address, validator2.address, validator3.address], + VERIFIER_KEY_HASH, + TEST_VERIFIER_MESSAGES_COUNT, + INITIAL_NOTE_KIND, + ]); + + const proxy = await ERC1967Proxy.deploy( + await rollupImpl.getAddress(), + initData, + ); + rollup = RollupV1Factory.attach(await proxy.getAddress()); + }); + + describe("Block Height Validation", function () { + it("should start with block height 0", async function () { + expect(await rollup.blockHeight()).to.equal(0); + }); + + it("should set the provided note kind mapping during initialization", async function () { + const mappedToken = await rollup.noteKindTokenAddress(INITIAL_NOTE_KIND); + expect(mappedToken).to.equal(await mockUsdc.getAddress()); + }); + + it("should store the verifier message count provided at initialization", async function () { + const verifier = await rollup.zkVerifiers(VERIFIER_KEY_HASH); + expect(verifier.messages_length).to.equal(TEST_VERIFIER_MESSAGES_COUNT); + }); + + it("should have the validators registered correctly", async function () { + // Get the validator sets + const validatorSets = await rollup.getValidatorSets(0); + console.log("Validator sets from contract:", validatorSets); + expect(validatorSets).to.have.length(1); + expect(validatorSets[0].validators).to.have.length(3); + + // Check that our test validators are included + expect(validatorSets[0].validators).to.include(validator1.address); + expect(validatorSets[0].validators).to.include(validator2.address); + expect(validatorSets[0].validators).to.include(validator3.address); + + console.log("Expected validators:"); + console.log(` validator1: ${validator1.address}`); + console.log(` validator2: ${validator2.address}`); + console.log(` validator3: ${validator3.address}`); + console.log("Contract validators:"); + validatorSets[0].validators.forEach((v, i) => + console.log(` ${i}: ${v}`), + ); + }); + + it("should have matching hash calculations", async function () { + const height = 1; + const newRoot = NEW_ROOT; + const otherHash = OTHER_HASH; + + // Get acceptMsg from our calculation (we know this matches) + const acceptMsg = + "0x21dc7da13d8dfdb18b2b9d5dfab00e5ac63a1b60bff6de58b526a5ef5262177a"; + + // Get packed bytes from contract + const contractPackedBytes = await rollup.debugGetPackedBytes(acceptMsg); + + // Create our packed bytes + const NETWORK = "Payy"; + const NETWORK_LEN = 4; + + // Create the uint64 encoding manually - 8 bytes big-endian + const networkLenBytes = new Uint8Array(8); + new DataView(networkLenBytes.buffer).setBigUint64( + 0, + BigInt(NETWORK_LEN), + false, + ); // false = big-endian + + const testPackedBytes = ethers.concat([ + networkLenBytes, + ethers.toUtf8Bytes(NETWORK), + ethers.getBytes(acceptMsg), + ]); + + console.log(`Contract packed bytes: ${contractPackedBytes}`); + console.log(`Test packed bytes: ${ethers.hexlify(testPackedBytes)}`); + console.log(`Contract hash: ${ethers.keccak256(contractPackedBytes)}`); + console.log(`Test hash: ${ethers.keccak256(testPackedBytes)}`); + + // Let's also try different encodings of NETWORK_LEN + console.log("Different NETWORK_LEN encodings:"); + console.log( + ` toBeArray(4, 8): ${ethers.hexlify(ethers.toBeArray(NETWORK_LEN, 8))}`, + ); + console.log( + ` toBeArray(4, 4): ${ethers.hexlify(ethers.toBeArray(NETWORK_LEN, 4))}`, + ); + console.log( + ` toBeArray(4, 1): ${ethers.hexlify(ethers.toBeArray(NETWORK_LEN, 1))}`, + ); + }); + + it("should allow increasing block height from 0 to 1", async function () { + const height = 1; + + // Create signatures for validators + const signatures = await createValidSignatures(height, NEW_ROOT); + const publicInputs = createBasicPublicInputs( + INITIAL_ROOT, + NEW_ROOT, + COMMIT_HASH, + ); + + await expect( + rollup.connect(prover).verifyRollup( + height, + VERIFIER_KEY_HASH, + "0x00", // mock proof + publicInputs, + OTHER_HASH, + signatures, + ), + ).to.not.be.reverted; + + expect(await rollup.blockHeight()).to.equal(height); + }); + + it("should reject same block height (0 to 0)", async function () { + const height = 0; + + const signatures = await createValidSignatures(height, NEW_ROOT); + const publicInputs = createBasicPublicInputs( + INITIAL_ROOT, + NEW_ROOT, + COMMIT_HASH, + ); + + await expect( + rollup + .connect(prover) + .verifyRollup( + height, + VERIFIER_KEY_HASH, + "0x00", + publicInputs, + OTHER_HASH, + signatures, + ), + ).to.be.revertedWith( + "RollupV1: New block height must be greater than current", + ); + }); + + it("should allow sequential height increases", async function () { + // First: 0 to 1 + await verifyRollupAtHeight(1, INITIAL_ROOT, NEW_ROOT); + expect(await rollup.blockHeight()).to.equal(1); + + // Second: 1 to 2 + const newRoot2 = + "0x0000000000000000000000000000000000000000000000000000000000000006"; + await verifyRollupAtHeight(2, NEW_ROOT, newRoot2); + expect(await rollup.blockHeight()).to.equal(2); + + // Third: 2 to 3 + const newRoot3 = + "0x0000000000000000000000000000000000000000000000000000000000000007"; + await verifyRollupAtHeight(3, newRoot2, newRoot3); + expect(await rollup.blockHeight()).to.equal(3); + }); + + it("should reject decreasing block height after increase", async function () { + // First increase to height 5 + await verifyRollupAtHeight(1, INITIAL_ROOT, NEW_ROOT); + await verifyRollupAtHeight( + 2, + NEW_ROOT, + "0x0000000000000000000000000000000000000000000000000000000000000006", + ); + await verifyRollupAtHeight( + 3, + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007", + ); + await verifyRollupAtHeight( + 4, + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x0000000000000000000000000000000000000000000000000000000000000008", + ); + await verifyRollupAtHeight( + 5, + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000009", + ); + + expect(await rollup.blockHeight()).to.equal(5); + + // Try to decrease to height 4 + const height = 4; + const signatures = await createValidSignatures( + height, + "0x000000000000000000000000000000000000000000000000000000000000000a", + ); + const publicInputs = createBasicPublicInputs( + "0x0000000000000000000000000000000000000000000000000000000000000009", + "0x000000000000000000000000000000000000000000000000000000000000000a", + COMMIT_HASH, + ); + + await expect( + rollup + .connect(prover) + .verifyRollup( + height, + VERIFIER_KEY_HASH, + "0x00", + publicInputs, + OTHER_HASH, + signatures, + ), + ).to.be.revertedWith( + "RollupV1: New block height must be greater than current", + ); + }); + + it("should reject same block height after increase", async function () { + // First increase to height 3 + await verifyRollupAtHeight(1, INITIAL_ROOT, NEW_ROOT); + await verifyRollupAtHeight( + 2, + NEW_ROOT, + "0x0000000000000000000000000000000000000000000000000000000000000006", + ); + await verifyRollupAtHeight( + 3, + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000007", + ); + + expect(await rollup.blockHeight()).to.equal(3); + + // Try to submit same height 3 + const height = 3; + const signatures = await createValidSignatures( + height, + "0x000000000000000000000000000000000000000000000000000000000000000a", + ); + const publicInputs = createBasicPublicInputs( + "0x0000000000000000000000000000000000000000000000000000000000000007", + "0x000000000000000000000000000000000000000000000000000000000000000a", + COMMIT_HASH, + ); + + await expect( + rollup + .connect(prover) + .verifyRollup( + height, + VERIFIER_KEY_HASH, + "0x00", + publicInputs, + OTHER_HASH, + signatures, + ), + ).to.be.revertedWith( + "RollupV1: New block height must be greater than current", + ); + }); + }); + + // Helper functions + async function verifyRollupAtHeight( + height: number, + oldRoot: string, + newRoot: string, + ) { + const signatures = await createValidSignatures(height, newRoot); + const publicInputs = createBasicPublicInputs(oldRoot, newRoot, COMMIT_HASH); + + await rollup + .connect(prover) + .verifyRollup( + height, + VERIFIER_KEY_HASH, + "0x00", + publicInputs, + OTHER_HASH, + signatures, + ); + } + + async function createValidSignatures(height: number, newRoot: string) { + const messageHash = await getSignatureMessageHash( + newRoot, + height, + OTHER_HASH, + ); + console.log(`Message hash: ${messageHash}`); + console.log(` newRoot: ${newRoot}`); + console.log(` height: ${height}`); + console.log(` otherHash: ${OTHER_HASH}`); + + const signatures = []; + const validators = [validator1, validator2, validator3]; + + // We need to sign the raw messageHash without the Ethereum prefix + // Since the contract expects raw hash signatures, we need to use the private keys directly + // Hardhat signers don't expose private keys directly, so we need to use known test private keys + const testPrivateKeys = [ + "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a", // validator1 + "0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6", // validator2 + "0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a", // validator3 + ]; + + for (let i = 0; i < validators.length; i++) { + const validator = validators[i]; + // Create signing key from known private key + const signingKey = new ethers.SigningKey(testPrivateKeys[i]); + + // Verify the signing key matches the validator address + const address = ethers.computeAddress(signingKey.publicKey); + console.log( + `Validator ${i}: Expected ${validator.address}, Computed ${address}`, + ); + + if (address.toLowerCase() !== validator.address.toLowerCase()) { + throw new Error( + `Private key mismatch for validator ${i}: expected ${validator.address}, got ${address}`, + ); + } + + // Sign the raw messageHash + const signature = signingKey.sign(messageHash); + console.log( + `Validator: ${validator.address}, Signature: r=${signature.r}, s=${signature.s}, v=${signature.v}`, + ); + + signatures.push({ r: signature.r, s: signature.s, v: signature.v }); + } + + // Sort signatures by validator address (contract requirement) + const sortedValidators = validators + .map((v, i) => ({ validator: v, signature: signatures[i] })) + .sort((a, b) => + a.validator.address + .toLowerCase() + .localeCompare(b.validator.address.toLowerCase()), + ); + + console.log("Original validator order:"); + validators.forEach((v, i) => console.log(` ${i}: ${v.address}`)); + console.log("Sorted validator order:"); + sortedValidators.forEach((v, i) => + console.log(` ${i}: ${v.validator.address}`), + ); + + return sortedValidators.map((v) => v.signature); + } + + async function getSignatureMessageHash( + newRoot: string, + height: number, + otherHash: string, + ) { + const NETWORK = "Payy"; + const NETWORK_LEN = 4; + + const proposalHash = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["bytes32", "uint256", "bytes32"], + [newRoot, height, otherHash], + ), + ); + console.log(` proposalHash: ${proposalHash}`); + + const acceptMsg = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["uint256", "bytes32"], + [height + 1, proposalHash], + ), + ); + console.log(` acceptMsg: ${acceptMsg}`); + + // Create the uint64 encoding manually - 8 bytes big-endian + const networkLenBytes = new Uint8Array(8); + new DataView(networkLenBytes.buffer).setBigUint64( + 0, + BigInt(NETWORK_LEN), + false, + ); // false = big-endian + + const sigMsg = ethers.keccak256( + ethers.concat([ + networkLenBytes, + ethers.toUtf8Bytes(NETWORK), + ethers.getBytes(acceptMsg), + ]), + ); + console.log(` sigMsg: ${sigMsg}`); + + return sigMsg; + } + + function createBasicPublicInputs( + oldRoot: string, + newRoot: string, + commitHash: string, + ) { + const inputs = [oldRoot, newRoot, commitHash]; + // Match the verifier messages length passed during initialization. + for (let i = 0; i < TEST_VERIFIER_MESSAGES_COUNT; i++) { + inputs.push( + "0x0000000000000000000000000000000000000000000000000000000000000000", + ); + } + return inputs; + } +}); diff --git a/eth/test/BoundsCheck.test.ts b/eth/test/BoundsCheck.test.ts new file mode 100644 index 0000000..de8da35 --- /dev/null +++ b/eth/test/BoundsCheck.test.ts @@ -0,0 +1,60 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; + +describe("Bounds Check Logic Tests", function () { + let boundsTest: any; + + const MAX_FUTURE_BLOCKS = 2_592_000; // 30 days worth of blocks + + beforeEach(async function () { + const BoundsTestFactory = await ethers.getContractFactory("BoundsTestContract"); + boundsTest = await BoundsTestFactory.deploy(); + }); + + describe("validateBounds function", function () { + it("should allow validFrom = 0 (special case for initialization)", async function () { + await expect(boundsTest.validateBounds(0)).to.not.be.rejected; + }); + + it("should allow validFrom within 30 days of current block", async function () { + const currentBlock = await boundsTest.getCurrentBlock(); + const validFrom = currentBlock + 1000n; // 1000 blocks in the future + + await expect(boundsTest.validateBounds(validFrom)).to.not.be.rejected; + }); + + it("should allow validFrom exactly at the boundary (30 days)", async function () { + const maxAllowed = await boundsTest.getMaxAllowedValidFrom(); + + await expect(boundsTest.validateBounds(maxAllowed)).to.not.be.rejected; + }); + + it("should reject validFrom more than 30 days in the future", async function () { + const maxAllowed = await boundsTest.getMaxAllowedValidFrom(); + const validFrom = maxAllowed + 1n; // One block beyond the limit + + await expect(boundsTest.validateBounds(validFrom)) + .to.be.revertedWith("BoundsTest: validFrom cannot be more than 30 days in the future"); + }); + + it("should reject extremely large validFrom values", async function () { + const validFrom = ethers.MaxUint256; // type(uint256).max + + await expect(boundsTest.validateBounds(validFrom)) + .to.be.revertedWith("BoundsTest: validFrom cannot be more than 30 days in the future"); + }); + + it("should have correct MAX_FUTURE_BLOCKS constant", async function () { + const maxFutureBlocks = await boundsTest.getMaxFutureBlocks(); + expect(Number(maxFutureBlocks)).to.equal(MAX_FUTURE_BLOCKS); + }); + + it("should calculate correct max allowed validFrom", async function () { + const currentBlock = await boundsTest.getCurrentBlock(); + const maxAllowed = await boundsTest.getMaxAllowedValidFrom(); + const expectedMax = currentBlock + BigInt(MAX_FUTURE_BLOCKS); + + expect(maxAllowed).to.equal(expectedMax); + }); + }); +}); \ No newline at end of file diff --git a/eth/test/Eip7702SimpleAccount.eip712.test.ts b/eth/test/Eip7702SimpleAccount.eip712.test.ts new file mode 100644 index 0000000..b694922 --- /dev/null +++ b/eth/test/Eip7702SimpleAccount.eip712.test.ts @@ -0,0 +1,30 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import fs from 'node:fs' +import path from 'node:path' + +describe('Eip712 array encoding stays in sync', () => { + it('hashCalls(Call[]) matches the Rust implementation', async () => { + const contract = await hre.viem.deployContract('Eip7702SimpleAccount') + + const calls = [ + { + target: '0x1111111111111111111111111111111111111111', + value: 1n, + data: '0x' + }, + { + target: '0x2222222222222222222222222222222222222222', + value: 2n, + data: '0xdeadbeef' + } + ] as const + + const onchain = await contract.read.hashCalls([calls]) + const expected = fs + .readFileSync(path.join(__dirname, '..', '..', 'fixtures', 'eip7702', 'hashcalls_vector1.hex'), 'utf8') + .trim() + + expect(onchain.toLowerCase()).to.eq(expected) + }) +}) diff --git a/eth/test/Eip7702SimpleAccount.erc1271.test.ts b/eth/test/Eip7702SimpleAccount.erc1271.test.ts new file mode 100644 index 0000000..f795da0 --- /dev/null +++ b/eth/test/Eip7702SimpleAccount.erc1271.test.ts @@ -0,0 +1,124 @@ +import { expect } from 'chai' +import hre from 'hardhat' +import { secp256k1 } from '@noble/curves/secp256k1' +import { keccak256, hexToBytes, type Hex } from 'viem' +import { privateKeyToAccount } from 'viem/accounts' + +const OWNER_PRIVATE_KEY = '0x59c6995e998f97a5a0044974fee25b4152cf92f5b1eb2d6feab718a6b7f7d9c7' +const OTHER_PRIVATE_KEY = '0x8b3a350cf5c34c9194ca10060b7a0fba8f5a2f05d5d3f5c5cbd3e55e3f66b2b1' + +const ownerAccount = privateKeyToAccount(OWNER_PRIVATE_KEY) + +const digestMagic = '0x1626ba7e' +const bytesMagic = '0x20c13b0b' +const invalidMagic = '0xffffffff' + +const digestSignatureAbi = [ + { + inputs: [ + { internalType: 'bytes32', name: 'hash', type: 'bytes32' }, + { internalType: 'bytes', name: 'signature', type: 'bytes' } + ], + name: 'isValidSignature', + outputs: [{ internalType: 'bytes4', name: '', type: 'bytes4' }], + stateMutability: 'view', + type: 'function' + } +] as const + +const bytesSignatureAbi = [ + { + inputs: [ + { internalType: 'bytes', name: 'data', type: 'bytes' }, + { internalType: 'bytes', name: 'signature', type: 'bytes' } + ], + name: 'isValidSignature', + outputs: [{ internalType: 'bytes4', name: '', type: 'bytes4' }], + stateMutability: 'view', + type: 'function' + } +] as const + +function signDigest(hash: Hex, privateKey: Hex): `0x${string}` { + const signature = secp256k1.sign(hexToBytes(hash), hexToBytes(privateKey)) + const r = signature.r.toString(16).padStart(64, '0') + const s = signature.s.toString(16).padStart(64, '0') + const v = (signature.recovery + 27).toString(16).padStart(2, '0') + return `0x${r}${s}${v}` +} + +describe('Eip7702SimpleAccount ERC1271', () => { + let bytecode: Hex + + before(async () => { + const artifact = await hre.artifacts.readArtifact('Eip7702SimpleAccount') + bytecode = artifact.deployedBytecode as Hex + }) + + beforeEach(async () => { + const testClient = await hre.viem.getTestClient() + await testClient.setCode({ address: ownerAccount.address, bytecode }) + }) + + it('returns the ERC-1271 magic value for digest signatures signed by the contract owner', async () => { + const digest = keccak256('0xdeadbeef') + const signature = signDigest(digest, OWNER_PRIVATE_KEY) + const publicClient = await hre.viem.getPublicClient() + + const result = await publicClient.readContract({ + address: ownerAccount.address, + abi: digestSignatureAbi, + functionName: 'isValidSignature', + args: [digest, signature] + }) + + expect(result).to.equal(digestMagic) + }) + + it('rejects digest signatures that were not produced by the contract owner', async () => { + const digest = keccak256('0x1337') + const signature = signDigest(digest, OTHER_PRIVATE_KEY) + const publicClient = await hre.viem.getPublicClient() + + const result = await publicClient.readContract({ + address: ownerAccount.address, + abi: digestSignatureAbi, + functionName: 'isValidSignature', + args: [digest, signature] + }) + + expect(result).to.equal(invalidMagic) + }) + + it('returns the legacy bytes magic value when signing raw calldata with the owner key', async () => { + const data = '0xc0ffee' + const digest = keccak256(data) + const signature = signDigest(digest, OWNER_PRIVATE_KEY) + const publicClient = await hre.viem.getPublicClient() + + const result = await publicClient.readContract({ + address: ownerAccount.address, + abi: bytesSignatureAbi, + functionName: 'isValidSignature', + args: [data, signature] + }) + + expect(result).to.equal(bytesMagic) + }) + + it('rejects bytes signatures signed by any other key', async () => { + const data = '0x1234' + const digest = keccak256(data) + const signature = signDigest(digest, OTHER_PRIVATE_KEY) + const publicClient = await hre.viem.getPublicClient() + + const result = await publicClient.readContract({ + address: ownerAccount.address, + abi: bytesSignatureAbi, + functionName: 'isValidSignature', + args: [data, signature] + }) + + expect(result).to.equal(invalidMagic) + }) +}) diff --git a/eth/test/Eip7702SimpleAccount.receive.test.ts b/eth/test/Eip7702SimpleAccount.receive.test.ts new file mode 100644 index 0000000..06d536e --- /dev/null +++ b/eth/test/Eip7702SimpleAccount.receive.test.ts @@ -0,0 +1,53 @@ +import { expect } from 'chai' +import hre from 'hardhat' + +describe('Eip7702SimpleAccount native deposits', () => { + it('accepts multiple native deposits after delegation is installed', async () => { + const [sendWallet, recipientWallet] = await hre.viem.getWalletClients() + const sender = sendWallet + const recipient = recipientWallet.account.address + + const contract = await hre.viem.deployContract('Eip7702SimpleAccount') + const publicClient = await hre.viem.getPublicClient() + const testClient = await hre.viem.getTestClient() + + // Baseline: first deposit succeeds while the account still has empty code + const initialBalance = await publicClient.getBalance({ address: recipient }) + const firstTx = await sender.sendTransaction({ + account: sender.account, + to: recipient, + value: 1n + }) + const firstReceipt = await publicClient.waitForTransactionReceipt({ hash: firstTx }) + expect(firstReceipt.status).to.equal('success') + const firstBalance = await publicClient.getBalance({ address: recipient }) + expect(firstBalance - initialBalance).to.equal(1n) + + // After delegation (0xef0100 || delegate), subsequent deposits should still succeed. + const delegationCode = (`0xef0100${contract.address.slice(2)}`) as `0x${string}` + await testClient.setCode({ + address: recipient, + bytecode: delegationCode + }) + + const secondTx = await sender.sendTransaction({ + account: sender.account, + to: recipient, + value: 2n + }) + const secondReceipt = await publicClient.waitForTransactionReceipt({ hash: secondTx }) + expect(secondReceipt.status).to.equal('success') + const secondBalance = await publicClient.getBalance({ address: recipient }) + expect(secondBalance - firstBalance).to.equal(2n) + + const thirdTx = await sender.sendTransaction({ + account: sender.account, + to: recipient, + value: 5n + }) + const thirdReceipt = await publicClient.waitForTransactionReceipt({ hash: thirdTx }) + expect(thirdReceipt.status).to.equal('success') + const finalBalance = await publicClient.getBalance({ address: recipient }) + expect(finalBalance - secondBalance).to.equal(5n) + }) +}) diff --git a/eth/test/LitActionRegistry.test.ts b/eth/test/LitActionRegistry.test.ts new file mode 100644 index 0000000..045165c --- /dev/null +++ b/eth/test/LitActionRegistry.test.ts @@ -0,0 +1,58 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; + +describe("LitActionRegistry", function () { + let owner: HardhatEthersSigner; + let nonOwner: HardhatEthersSigner; + let registry: any; + + beforeEach(async function () { + [owner, nonOwner] = await ethers.getSigners(); + + const LitActionRegistry = await ethers.getContractFactory("LitActionRegistry"); + registry = await LitActionRegistry.deploy(owner.address); + await registry.waitForDeployment(); + }); + + it("sets child lit action CID", async function () { + const cid = "QmChildCID"; + + await expect(registry.setChildLitActionCID(cid)) + .to.emit(registry, "ChildLitActionCIDUpdated") + .withArgs("", cid); + + expect(await registry.getChildLitActionCID()).to.equal(cid); + }); + + it("returns CID via alias", async function () { + const cid = "QmAliasCID"; + await registry.setChildLitActionCID(cid); + + expect(await registry.getChildIPFSCID()).to.equal(cid); + }); + + it("enforces owner-only setter", async function () { + await expect( + registry.connect(nonOwner).setChildLitActionCID("cid"), + ) + .to.be.revertedWithCustomError(registry, "OwnableUnauthorizedAccount") + .withArgs(nonOwner.address); + }); + + it("rejects empty CID", async function () { + await expect(registry.setChildLitActionCID("")) + .to.be.revertedWith("Child Lit Action CID cannot be empty"); + }); + + it("emits update with previous CID", async function () { + const first = "QmFirst"; + const second = "QmSecond"; + + await registry.setChildLitActionCID(first); + + await expect(registry.setChildLitActionCID(second)) + .to.emit(registry, "ChildLitActionCIDUpdated") + .withArgs(first, second); + }); +}); diff --git a/eth/test/NoteKind.test.ts b/eth/test/NoteKind.test.ts new file mode 100644 index 0000000..9875d36 --- /dev/null +++ b/eth/test/NoteKind.test.ts @@ -0,0 +1,19 @@ +import { expect } from "chai"; +import { + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, + generateNoteKindBridgeEvm, +} from "../scripts/noteKind"; + +describe("note kind helpers", function () { + it("derives the Polygon USDC note kind", function () { + const noteKind = generateNoteKindBridgeEvm( + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, + ); + + expect(noteKind).to.equal( + "0x000200000000000000893c499c542cef5e3811e1192ce70d8cc03d5c33590000", + ); + }); +}); diff --git a/eth/test/RollupV1.test.ts b/eth/test/RollupV1.test.ts new file mode 100644 index 0000000..3ce8c4c --- /dev/null +++ b/eth/test/RollupV1.test.ts @@ -0,0 +1,91 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; + +describe("RollupV1 Validator Set Tests", function () { + let rollup: any; + let usdc: any; + let mockVerifier: any; + let owner: HardhatEthersSigner; + let prover: HardhatEthersSigner; + let validators: HardhatEthersSigner[]; + let nonOwner: HardhatEthersSigner; + + const MAX_FUTURE_BLOCKS = 2_592_000; // 30 days worth of blocks + const EMPTY_MERKLE_ROOT = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; + const VERIFIER_KEY_HASH = "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"; + + beforeEach(async function () { + [owner, prover, nonOwner, ...validators] = await ethers.getSigners(); + + // Deploy TestRollupV1 (simplified test version for bounds checking) + const RollupV1Factory = await ethers.getContractFactory("TestRollupV1"); + rollup = await RollupV1Factory.deploy(); + }); + + describe("setValidators bounds checking", function () { + it("should allow setting validFrom within 30 days of current block", async function () { + const currentBlock = await ethers.provider.getBlockNumber(); + const validFrom = currentBlock + 1000; // 1000 blocks in the future + const newValidators = validators.slice(3, 6).map(v => v.address); + + await expect(rollup.setValidators(validFrom, newValidators)) + .to.not.be.reverted; + }); + + it("should allow setting validFrom exactly at the boundary (30 days)", async function () { + const currentBlock = await ethers.provider.getBlockNumber(); + const validFrom = currentBlock + MAX_FUTURE_BLOCKS; + const newValidators = validators.slice(3, 6).map(v => v.address); + + await expect(rollup.setValidators(validFrom, newValidators)) + .to.not.be.reverted; + }); + + it("should reject validFrom more than 30 days in the future", async function () { + const currentBlock = await ethers.provider.getBlockNumber(); + const validFrom = currentBlock + MAX_FUTURE_BLOCKS + 100; // Use a clearly invalid value + const newValidators = validators.slice(3, 6).map(v => v.address); + + await expect(rollup.setValidators(validFrom, newValidators)) + .to.be.revertedWith("RollupV1: validFrom cannot be more than 30 days in the future"); + }); + + it("should reject extremely large validFrom values", async function () { + const validFrom = ethers.MaxUint256; // type(uint256).max + const newValidators = validators.slice(3, 6).map(v => v.address); + + await expect(rollup.setValidators(validFrom, newValidators)) + .to.be.revertedWith("RollupV1: validFrom cannot be more than 30 days in the future"); + }); + + it("should focus on bounds checking only", async function () { + // This simplified test only checks bounds validation + // More complex validator sequence validation is tested elsewhere + expect(true).to.be.true; + }); + + it("should allow multiple validator sets with increasing validFrom within bounds", async function () { + const currentBlock = await ethers.provider.getBlockNumber(); + + // Test first validator set within bounds + const firstValidFrom = currentBlock + 1000; + const firstValidators = validators.slice(3, 6).map(v => v.address); + await expect(rollup.setValidators(firstValidFrom, firstValidators)) + .to.not.be.reverted; + + // Test second validator set within bounds + const secondValidFrom = currentBlock + MAX_FUTURE_BLOCKS - 1000; + const secondValidators = validators.slice(6, 9).map(v => v.address); + + await expect(rollup.setValidators(secondValidFrom, secondValidators)) + .to.not.be.reverted; + }); + + it("should test bounds validation only in simplified contract", async function () { + // Our simplified TestRollupV1 only tests bounds validation + // Access control and other features are tested in other test files + expect(true).to.be.true; + }); + }); +}); \ No newline at end of file diff --git a/eth/test/RollupV1Debug.test.ts b/eth/test/RollupV1Debug.test.ts new file mode 100644 index 0000000..5ac5eb2 --- /dev/null +++ b/eth/test/RollupV1Debug.test.ts @@ -0,0 +1,69 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, + generateNoteKindBridgeEvm, +} from "../scripts/noteKind"; + +describe("RollupV1 Debug Tests", function () { + let rollup: any; + let usdc: any; + let mockVerifier: any; + let owner: HardhatEthersSigner; + let prover: HardhatEthersSigner; + let validators: HardhatEthersSigner[]; + + const EMPTY_MERKLE_ROOT = + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; + const VERIFIER_KEY_HASH = + "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"; + const INITIAL_NOTE_KIND = generateNoteKindBridgeEvm( + LEGACY_POLYGON_CHAIN_ID, + POLYGON_USDC_ADDRESS, + ); + const DEFAULT_VERIFIER_MESSAGES_COUNT = 1000; + + beforeEach(async function () { + [owner, prover, ...validators] = await ethers.getSigners(); + + // Deploy a mock USDC contract + const MockUSDC = await ethers.getContractFactory("MockUSDC"); + usdc = await MockUSDC.deploy(); + + // Deploy a mock verifier + const MockVerifier = await ethers.getContractFactory("MockVerifier"); + mockVerifier = await MockVerifier.deploy(); + + // Deploy RollupV1 (rollup3 merged version) + const RollupV1Factory = await ethers.getContractFactory( + "contracts/rollup3/RollupV1.sol:RollupV1", + ); + rollup = await RollupV1Factory.deploy(); + }); + + it("should deploy contracts successfully", async function () { + expect(await usdc.getAddress()).to.be.a("string"); + expect(await mockVerifier.getAddress()).to.be.a("string"); + expect(await rollup.getAddress()).to.be.a("string"); + }); + + it("should fail initialization due to disabled initializers", async function () { + const initialValidators = validators.slice(0, 3).map((v) => v.address); + + // This should fail because the constructor calls _disableInitializers() + await expect( + rollup.initialize( + owner.address, + await usdc.getAddress(), + await mockVerifier.getAddress(), + prover.address, + initialValidators, + VERIFIER_KEY_HASH, + DEFAULT_VERIFIER_MESSAGES_COUNT, + INITIAL_NOTE_KIND, + ), + ).to.be.revertedWithCustomError(rollup, "InvalidInitialization"); + }); +}); diff --git a/eth/test/RollupV1Simple.test.ts b/eth/test/RollupV1Simple.test.ts new file mode 100644 index 0000000..2a0945f --- /dev/null +++ b/eth/test/RollupV1Simple.test.ts @@ -0,0 +1,54 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; + +describe("RollupV1 Validator Bounds Tests", function () { + let rollup: any; + let owner: HardhatEthersSigner; + let validators: HardhatEthersSigner[]; + let nonOwner: HardhatEthersSigner; + + const MAX_FUTURE_BLOCKS = 2_592_000; // 30 days worth of blocks + + beforeEach(async function () { + [owner, nonOwner, ...validators] = await ethers.getSigners(); + + // Deploy TestRollupV1 (test version that allows initialization) + const RollupV1Factory = await ethers.getContractFactory("TestRollupV1"); + rollup = await RollupV1Factory.deploy(); + }); + + describe("setValidators bounds checking (manual testing)", function () { + it("should allow call to setValidators with valid validFrom", async function () { + const currentBlock = await ethers.provider.getBlockNumber(); + const validFrom = currentBlock + 1000; // 1000 blocks in the future + const newValidators = validators.slice(0, 3).map(v => v.address); + + await expect(rollup.setValidators(validFrom, newValidators)) + .to.not.be.reverted; + }); + + it("should reject validFrom more than 30 days in the future", async function () { + const currentBlock = await ethers.provider.getBlockNumber(); + const validFrom = currentBlock + MAX_FUTURE_BLOCKS + 100; // Use a clearly invalid value + const newValidators = validators.slice(0, 3).map(v => v.address); + + await expect(rollup.setValidators(validFrom, newValidators)) + .to.be.revertedWith("RollupV1: validFrom cannot be more than 30 days in the future"); + }); + + it("should reject extremely large validFrom values", async function () { + const validFrom = ethers.MaxUint256; // type(uint256).max + const newValidators = validators.slice(0, 3).map(v => v.address); + + await expect(rollup.setValidators(validFrom, newValidators)) + .to.be.revertedWith("RollupV1: validFrom cannot be more than 30 days in the future"); + }); + + it("should test bounds validation in simplified contract", async function () { + // Our simplified TestRollupV1 focuses on bounds validation only + // Access control tests are handled in other test files + expect(true).to.be.true; + }); + }); +}); \ No newline at end of file diff --git a/eth/test/SocialRecovery.test.ts b/eth/test/SocialRecovery.test.ts new file mode 100644 index 0000000..b82bc83 --- /dev/null +++ b/eth/test/SocialRecovery.test.ts @@ -0,0 +1,67 @@ +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { expect } from "chai"; +import { ethers } from "hardhat"; + +describe("SocialRecovery", function () { + let owner: HardhatEthersSigner; + let user: HardhatEthersSigner; + let nonOwner: HardhatEthersSigner; + let socialRecovery: any; + + beforeEach(async function () { + [owner, user, nonOwner] = await ethers.getSigners(); + + const SocialRecovery = await ethers.getContractFactory("SocialRecovery"); + socialRecovery = await SocialRecovery.deploy(owner.address); + await socialRecovery.waitForDeployment(); + }); + + describe("Guardian CID functionality", function () { + it("Should add guardian successfully", async function () { + await socialRecovery.addGuardianCID( + user.address, + "Password", + "guardian-data", + ); + + const config = await socialRecovery.getGuardianConfig(user.address); + expect(config.enabled).to.equal(true); + expect(config.guardianCount).to.equal(1); + expect(config.threshold).to.equal(1); + }); + + it("Should not allow duplicate guardians", async function () { + await socialRecovery.addGuardianCID(user.address, "Password", "password-1"); + + await expect( + socialRecovery.addGuardianCID(user.address, "Password", "password-1"), + ).to.be.revertedWith("Guardian Already exists"); + }); + + it("Should return guardian entry for CID hash", async function () { + const cid = "Password"; + const guardianValue = "guardian-data"; + + await socialRecovery.addGuardianCID(user.address, cid, guardianValue); + + const cidHash = ethers.keccak256(ethers.toUtf8Bytes(cid)); + const storedGuardian = await socialRecovery.getGuardianEntry( + user.address, + cidHash, + ); + + expect(storedGuardian).to.equal( + ethers.hexlify(ethers.toUtf8Bytes(guardianValue)), + ); + + const config = await socialRecovery.getGuardianConfig(user.address); + expect(config.guardianCIDs[0]).to.equal(cidHash); + }); + + it("Should reject empty guardian value", async function () { + await expect( + socialRecovery.addGuardianCID(user.address, "Password", ""), + ).to.be.revertedWith("Guardian value cannot be empty"); + }); + }); +}); diff --git a/eth/test/scripts/migration.test.ts b/eth/test/scripts/migration.test.ts new file mode 100644 index 0000000..0350092 --- /dev/null +++ b/eth/test/scripts/migration.test.ts @@ -0,0 +1,165 @@ +/* eslint-disable @typescript-eslint/no-unused-expressions */ +import { loadFixture } from '@nomicfoundation/hardhat-toolbox-viem/network-helpers' +import { expect } from 'chai' +import fs from 'fs' +import hre from 'hardhat' +import path from 'path' +import { keccak256, toHex, zeroHash } from 'viem' +import { extractMints } from '../../scripts/extract-mints' +import { filterMints } from '../../scripts/filter-mints' +import { loadMints } from '../../scripts/lib/migration-utils' +import { submitMints } from '../../scripts/submit-mints' + +describe('Migration Scripts', function () { + const OUTPUT_FILE = path.join(__dirname, 'temp-mints.json') + const FILTERED_FILE = path.join(__dirname, 'filtered-mints.json') + + afterEach(() => { + if (fs.existsSync(OUTPUT_FILE)) { + fs.unlinkSync(OUTPUT_FILE) + } + if (fs.existsSync(FILTERED_FILE)) { + fs.unlinkSync(FILTERED_FILE) + } + }) + + async function deployFixture() { + const [owner] = await hre.viem.getWalletClients() + const publicClient = await hre.viem.getPublicClient() + const source = await hre.viem.deployContract('RollupMigrationMock') + const target = await hre.viem.deployContract('RollupMigrationMock') + return { source, target, owner, publicClient } + } + + it('should extract, filter, and submit mints correctly', async function () { + const { source, target, owner, publicClient } = await loadFixture(deployFixture) + + const mint1 = { hash: keccak256(toHex('mint1')), value: 100n, kind: toHex('kind1', { size: 32 }) } + const mint2 = { hash: keccak256(toHex('mint2')), value: 200n, kind: toHex('kind2', { size: 32 }) } + const mint3 = { hash: keccak256(toHex('mint3')), value: 300n, kind: toHex('kind3', { size: 32 }) } + const mint4 = { hash: keccak256(toHex('mint4')), value: 400n, kind: toHex('kind4', { size: 32 }) } + + // 1. Setup Source State (Extraction Phase) + // Mint 1: Valid + const h1 = await source.write.emitMintAdded([mint1.hash, mint1.value, mint1.kind]) + await publicClient.waitForTransactionReceipt({ hash: h1 }) + + // Mint 2: Spent + const h2 = await source.write.emitMintAdded([mint2.hash, mint2.value, mint2.kind]) + await publicClient.waitForTransactionReceipt({ hash: h2 }) + const h3 = await source.write.emitMinted([mint2.hash, zeroHash, zeroHash]) + await publicClient.waitForTransactionReceipt({ hash: h3 }) + + // Mint 3: Valid + const h4 = await source.write.emitMintAdded([mint3.hash, mint3.value, mint3.kind]) + await publicClient.waitForTransactionReceipt({ hash: h4 }) + + // Mint 4: Valid (at extraction time) + const h5 = await source.write.emitMintAdded([mint4.hash, mint4.value, mint4.kind]) + await publicClient.waitForTransactionReceipt({ hash: h5 }) + + // 2. Extract + await extractMints({ + sourceRpcUrl: 'http://localhost:8545', + sourceAddress: source.address, + outputFile: OUTPUT_FILE, + startBlock: 0n, + concurrency: 1, + blockBatchSize: 100n, + client: publicClient + }) + + const extracted = await loadMints(OUTPUT_FILE) + expect(extracted[mint1.hash].spent).to.equal(false) + expect(extracted[mint2.hash].spent).to.equal(true) + expect(extracted[mint3.hash].spent).to.equal(false) + expect(extracted[mint4.hash].spent).to.equal(false) + + // 3. Change State (Between Extract and Filter) + // Spend Mint 4 on chain + const h6 = await source.write.emitMinted([mint4.hash, zeroHash, zeroHash]) + await publicClient.waitForTransactionReceipt({ hash: h6 }) + + // 4. Filter + await filterMints({ + sourceRpcUrl: 'http://localhost:8545', + sourceAddress: source.address, + inputFile: OUTPUT_FILE, + outputFile: FILTERED_FILE, + client: publicClient + }) + + const filtered = await loadMints(FILTERED_FILE) + // Mint 1: kept + expect(filtered[mint1.hash]).to.not.be.undefined + // Mint 2: removed (spent in extract) + expect(filtered[mint2.hash]).to.be.undefined + // Mint 3: kept + expect(filtered[mint3.hash]).to.not.be.undefined + // Mint 4: removed (spent on chain after extract) + expect(filtered[mint4.hash]).to.be.undefined + + // 5. Submit + await submitMints({ + targetRpcUrl: 'http://localhost:8545', + targetAddress: target.address, + privateKey: '0x0000000000000000000000000000000000000000000000000000000000000001', + inputFile: FILTERED_FILE, + publicClient, + walletClient: owner + }) + + // 6. Verify Target + const logs = await publicClient.getLogs({ + address: target.address, + event: { + type: 'event', + name: 'MintAdded', + inputs: [ + { type: 'bytes32', name: 'mint_hash', indexed: true }, + { type: 'uint256', name: 'value' }, + { type: 'bytes32', name: 'note_kind' } + ] + }, + fromBlock: 'earliest' + }) + + expect(logs.length).to.equal(2) + const hashes = logs.map(l => l.args.mint_hash) + expect(hashes).to.include(mint1.hash) + expect(hashes).to.include(mint3.hash) + expect(hashes).to.not.include(mint2.hash) + expect(hashes).to.not.include(mint4.hash) + + // 7. Test Print Mode + const consoleLogs: string[] = [] + const originalLog = console.log + console.log = (...args) => consoleLogs.push(args.join(' ')) + + // We need new candidates to test printTx effectively. + // Add Mint 5 to file manually. + const mint5 = { hash: keccak256(toHex('mint5')), value: '500', noteKind: toHex('kind5', { size: 32 }), spent: false, mintHash: keccak256(toHex('mint5')) } + const inputMints = await loadMints(FILTERED_FILE) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + inputMints[mint5.hash] = mint5 as any + await fs.promises.writeFile(FILTERED_FILE, JSON.stringify(inputMints)) + + try { + await submitMints({ + targetRpcUrl: 'http://localhost:8545', + targetAddress: target.address, + privateKey: '0x0000000000000000000000000000000000000000000000000000000000000001', + inputFile: FILTERED_FILE, + publicClient, + walletClient: owner, + printTx: true + }) + } finally { + console.log = originalLog + } + + const dataLogs = consoleLogs.filter(l => l.includes('Data: 0x')) + expect(dataLogs.length).to.be.greaterThan(0) + expect(dataLogs[0]).to.include('Data: 0x') // Ensure it printed hex data + }) +}) diff --git a/eth/yarn.lock b/eth/yarn.lock index a5a74b4..33ef1a8 100644 --- a/eth/yarn.lock +++ b/eth/yarn.lock @@ -17,42 +17,6 @@ resolved "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz" integrity sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw== -"@chainsafe/as-sha256@^0.3.1": - version "0.3.1" - resolved "https://registry.npmjs.org/@chainsafe/as-sha256/-/as-sha256-0.3.1.tgz" - integrity sha512-hldFFYuf49ed7DAakWVXSJODuq3pzJEguD8tQ7h+sGkM18vja+OFoJI9krnGmgzyuZC2ETX0NOIcCTy31v2Mtg== - -"@chainsafe/persistent-merkle-tree@^0.4.2": - version "0.4.2" - resolved "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.4.2.tgz" - integrity sha512-lLO3ihKPngXLTus/L7WHKaw9PnNJWizlOF1H9NNzHP6Xvh82vzg9F2bzkXhYIFshMZ2gTCEz8tq6STe7r5NDfQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/persistent-merkle-tree@^0.5.0": - version "0.5.0" - resolved "https://registry.npmjs.org/@chainsafe/persistent-merkle-tree/-/persistent-merkle-tree-0.5.0.tgz" - integrity sha512-l0V1b5clxA3iwQLXP40zYjyZYospQLZXzBVIhhr9kDg/1qHZfzzHw0jj4VPBijfYCArZDlPkRi1wZaV2POKeuw== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - -"@chainsafe/ssz@^0.10.0": - version "0.10.2" - resolved "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.10.2.tgz" - integrity sha512-/NL3Lh8K+0q7A3LsiFq09YXS9fPE+ead2rr7vM2QK8PLzrNsw3uqrif9bpRX5UxgeRjM+vYi+boCM3+GM4ovXg== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.5.0" - -"@chainsafe/ssz@^0.9.2": - version "0.9.4" - resolved "https://registry.npmjs.org/@chainsafe/ssz/-/ssz-0.9.4.tgz" - integrity sha512-77Qtg2N1ayqs4Bg/wvnWfg5Bta7iy7IRh8XqXh7oNMeP2HBbBwx8m6yTpA8p0EHItWPEBkgZd5S5/LSlp3GXuQ== - dependencies: - "@chainsafe/as-sha256" "^0.3.1" - "@chainsafe/persistent-merkle-tree" "^0.4.2" - case "^1.6.3" - "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz" @@ -102,6 +66,11 @@ resolved "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz" integrity sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw== +"@ethereumjs/rlp@^5.0.2": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-5.0.2.tgz#c89bd82f2f3bec248ab2d517ae25f5bbc4aac842" + integrity sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA== + "@ethereumjs/util@^8.1.0": version "8.1.0" resolved "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz" @@ -111,6 +80,14 @@ ethereum-cryptography "^2.0.0" micro-ftch "^0.3.1" +"@ethereumjs/util@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/util/-/util-9.1.0.tgz#75e3898a3116d21c135fa9e29886565609129bce" + integrity sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog== + dependencies: + "@ethereumjs/rlp" "^5.0.2" + ethereum-cryptography "^2.2.1" + "@ethersproject/abi@5.7.0", "@ethersproject/abi@^5.0.9", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.7.0": version "5.7.0" resolved "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz" @@ -313,7 +290,7 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.2", "@ethersproject/providers@^5.7.1", "@ethersproject/providers@^5.7.2": +"@ethersproject/providers@5.7.2": version "5.7.2" resolved "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz" integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== @@ -523,17 +500,6 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@metamask/eth-sig-util@^4.0.0": - version "4.0.1" - resolved "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz" - integrity sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ== - dependencies: - ethereumjs-abi "^0.6.8" - ethereumjs-util "^6.2.1" - ethjs-util "^0.1.6" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.1" - "@noble/curves@1.1.0", "@noble/curves@~1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz" @@ -548,6 +514,20 @@ dependencies: "@noble/hashes" "1.3.2" +"@noble/curves@1.4.2", "@noble/curves@~1.4.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.4.2.tgz#40309198c76ed71bc6dbf7ba24e81ceb4d0d1fe9" + integrity sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw== + dependencies: + "@noble/hashes" "1.4.0" + +"@noble/curves@~1.8.1": + version "1.8.2" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.8.2.tgz#8f24c037795e22b90ae29e222a856294c1d9ffc7" + integrity sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g== + dependencies: + "@noble/hashes" "1.7.2" + "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz" @@ -563,6 +543,16 @@ resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz" integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== +"@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" + integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== + +"@noble/hashes@1.7.2", "@noble/hashes@~1.7.1": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.7.2.tgz#d53c65a21658fb02f3303e7ee3ba89d6754c64b4" + integrity sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ== + "@noble/secp256k1@1.7.1", "@noble/secp256k1@~1.7.0": version "1.7.1" resolved "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz" @@ -589,139 +579,63 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@nomicfoundation/ethereumjs-block@5.0.2": - version "5.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.2.tgz" - integrity sha512-hSe6CuHI4SsSiWWjHDIzWhSiAVpzMUcDRpWYzN0T9l8/Rz7xNn3elwVOJ/tAyS0LqL6vitUD78Uk7lQDXZun7Q== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-trie" "6.0.2" - "@nomicfoundation/ethereumjs-tx" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - -"@nomicfoundation/ethereumjs-blockchain@7.0.2": - version "7.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.2.tgz" - integrity sha512-8UUsSXJs+MFfIIAKdh3cG16iNmWzWC/91P40sazNvrqhhdR/RtGDlFk2iFTGbBAZPs2+klZVzhRX8m2wvuvz3w== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.2" - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-ethash" "3.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-trie" "6.0.2" - "@nomicfoundation/ethereumjs-tx" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - abstract-level "^1.0.3" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - level "^8.0.0" - lru-cache "^5.1.1" - memory-level "^1.0.0" - -"@nomicfoundation/ethereumjs-common@4.0.2": - version "4.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.2.tgz" - integrity sha512-I2WGP3HMGsOoycSdOTSqIaES0ughQTueOsddJ36aYVpI3SN8YSusgRFLwzDJwRFVIYDKx/iJz0sQ5kBHVgdDwg== - dependencies: - "@nomicfoundation/ethereumjs-util" "9.0.2" - crc-32 "^1.2.0" - -"@nomicfoundation/ethereumjs-ethash@3.0.2": - version "3.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.2.tgz" - integrity sha512-8PfoOQCcIcO9Pylq0Buijuq/O73tmMVURK0OqdjhwqcGHYC2PwhbajDh7GZ55ekB0Px197ajK3PQhpKoiI/UPg== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - abstract-level "^1.0.3" - bigint-crypto-utils "^3.0.23" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-evm@2.0.2": - version "2.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.2.tgz" - integrity sha512-rBLcUaUfANJxyOx9HIdMX6uXGin6lANCulIm/pjMgRqfiCRMZie3WKYxTSd8ZE/d+qT+zTedBF4+VHTdTSePmQ== - dependencies: - "@ethersproject/providers" "^5.7.1" - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-tx" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" - -"@nomicfoundation/ethereumjs-rlp@5.0.2": - version "5.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.2.tgz" - integrity sha512-QwmemBc+MMsHJ1P1QvPl8R8p2aPvvVcKBbvHnQOKBpBztEo0omN0eaob6FeZS/e3y9NSe+mfu3nNFBHszqkjTA== - -"@nomicfoundation/ethereumjs-statemanager@2.0.2": - version "2.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.2.tgz" - integrity sha512-dlKy5dIXLuDubx8Z74sipciZnJTRSV/uHG48RSijhgm1V7eXYFC567xgKtsKiVZB1ViTP9iFL4B6Je0xD6X2OA== - dependencies: - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - ethers "^5.7.1" - js-sdsl "^4.1.4" - -"@nomicfoundation/ethereumjs-trie@6.0.2": - version "6.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.2.tgz" - integrity sha512-yw8vg9hBeLYk4YNg5MrSJ5H55TLOv2FSWUTROtDtTMMmDGROsAu+0tBjiNGTnKRi400M6cEzoFfa89Fc5k8NTQ== - dependencies: - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - "@types/readable-stream" "^2.3.13" - ethereum-cryptography "0.1.3" - readable-stream "^3.6.0" - -"@nomicfoundation/ethereumjs-tx@5.0.2": - version "5.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.2.tgz" - integrity sha512-T+l4/MmTp7VhJeNloMkM+lPU3YMUaXdcXgTGCf8+ZFvV9NYZTRLFekRwlG6/JMmVfIfbrW+dRRJ9A6H5Q/Z64g== - dependencies: - "@chainsafe/ssz" "^0.9.2" - "@ethersproject/providers" "^5.7.2" - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-util@9.0.2": - version "9.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.2.tgz" - integrity sha512-4Wu9D3LykbSBWZo8nJCnzVIYGvGCuyiYLIJa9XXNVt1q1jUzHdB+sJvx95VGCpPkCT+IbLecW6yfzy3E1bQrwQ== - dependencies: - "@chainsafe/ssz" "^0.10.0" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - ethereum-cryptography "0.1.3" - -"@nomicfoundation/ethereumjs-vm@7.0.2": - version "7.0.2" - resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.2.tgz" - integrity sha512-Bj3KZT64j54Tcwr7Qm/0jkeZXJMfdcAtRBedou+Hx0dPOSIgqaIr0vvLwP65TpHbak2DmAq+KJbW2KNtIoFwvA== - dependencies: - "@nomicfoundation/ethereumjs-block" "5.0.2" - "@nomicfoundation/ethereumjs-blockchain" "7.0.2" - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-evm" "2.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-statemanager" "2.0.2" - "@nomicfoundation/ethereumjs-trie" "6.0.2" - "@nomicfoundation/ethereumjs-tx" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - debug "^4.3.3" - ethereum-cryptography "0.1.3" - mcl-wasm "^0.7.1" - rustbn.js "~0.2.0" +"@nomicfoundation/edr-darwin-arm64@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.11.3.tgz#d8e2609fc24cf20e75c3782e39cd5a95f7488075" + integrity sha512-w0tksbdtSxz9nuzHKsfx4c2mwaD0+l5qKL2R290QdnN9gi9AV62p9DHkOgfBdyg6/a6ZlnQqnISi7C9avk/6VA== + +"@nomicfoundation/edr-darwin-x64@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.11.3.tgz#7a9e94cee330269a33c7f1dce267560c7e12dbd3" + integrity sha512-QR4jAFrPbOcrO7O2z2ESg+eUeIZPe2bPIlQYgiJ04ltbSGW27FblOzdd5+S3RoOD/dsZGKAvvy6dadBEl0NgoA== + +"@nomicfoundation/edr-linux-arm64-gnu@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.11.3.tgz#cd5ec90c7263045c3dfd0b109c73206e488edc27" + integrity sha512-Ktjv89RZZiUmOFPspuSBVJ61mBZQ2+HuLmV67InNlh9TSUec/iDjGIwAn59dx0bF/LOSrM7qg5od3KKac4LJDQ== + +"@nomicfoundation/edr-linux-arm64-musl@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.11.3.tgz#ed23df2d9844470f5661716da27d99a72a69e99e" + integrity sha512-B3sLJx1rL2E9pfdD4mApiwOZSrX0a/KQSBWdlq1uAhFKqkl00yZaY4LejgZndsJAa4iKGQJlGnw4HCGeVt0+jA== + +"@nomicfoundation/edr-linux-x64-gnu@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.11.3.tgz#87a62496c2c4b808bc4a9ae96cca1642a21c2b51" + integrity sha512-D/4cFKDXH6UYyKPu6J3Y8TzW11UzeQI0+wS9QcJzjlrrfKj0ENW7g9VihD1O2FvXkdkTjcCZYb6ai8MMTCsaVw== + +"@nomicfoundation/edr-linux-x64-musl@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.11.3.tgz#8cfe408c73bcb9ed5e263910c313866d442f4b48" + integrity sha512-ergXuIb4nIvmf+TqyiDX5tsE49311DrBky6+jNLgsGDTBaN1GS3OFwFS8I6Ri/GGn6xOaT8sKu3q7/m+WdlFzg== + +"@nomicfoundation/edr-win32-x64-msvc@0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.11.3.tgz#fb208b94553c7eb22246d73a1ac4de5bfdb97d01" + integrity sha512-snvEf+WB3OV0wj2A7kQ+ZQqBquMcrozSLXcdnMdEl7Tmn+KDCbmFKBt3Tk0X3qOU4RKQpLPnTxdM07TJNVtung== + +"@nomicfoundation/edr@^0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.11.3.tgz#e8b30b868788e45d7a2ee2359a021ef7dcb96952" + integrity sha512-kqILRkAd455Sd6v8mfP3C1/0tCOynJWY+Ir+k/9Boocu2kObCrsFgG+ZWB7fSBVdd9cPVSNrnhWS+V+PEo637g== + dependencies: + "@nomicfoundation/edr-darwin-arm64" "0.11.3" + "@nomicfoundation/edr-darwin-x64" "0.11.3" + "@nomicfoundation/edr-linux-arm64-gnu" "0.11.3" + "@nomicfoundation/edr-linux-arm64-musl" "0.11.3" + "@nomicfoundation/edr-linux-x64-gnu" "0.11.3" + "@nomicfoundation/edr-linux-x64-musl" "0.11.3" + "@nomicfoundation/edr-win32-x64-msvc" "0.11.3" + +"@nomicfoundation/hardhat-chai-matchers@2.0.8": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.8.tgz#9c7cfc4ad0f0a5e9cf16aba8ab668c02f6e273aa" + integrity sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg== + dependencies: + "@types/chai-as-promised" "^7.1.3" + chai-as-promised "^7.1.1" + deep-eql "^4.0.1" + ordinal "^1.0.3" "@nomicfoundation/hardhat-ethers@^3.0.5": version "3.0.5" @@ -1100,6 +1014,16 @@ resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz" integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== +"@scure/base@~1.1.6": + version "1.1.9" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.9.tgz#e5e142fbbfe251091f9c5f1dd4c834ac04c3dbd1" + integrity sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg== + +"@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + "@scure/bip32@1.1.5": version "1.1.5" resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz" @@ -1127,6 +1051,15 @@ "@noble/hashes" "~1.3.2" "@scure/base" "~1.1.2" +"@scure/bip32@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.4.0.tgz#4e1f1e196abedcef395b33b9674a042524e20d67" + integrity sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg== + dependencies: + "@noble/curves" "~1.4.0" + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + "@scure/bip39@1.1.1": version "1.1.1" resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz" @@ -1143,6 +1076,14 @@ "@noble/hashes" "~1.3.0" "@scure/base" "~1.1.0" +"@scure/bip39@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.3.0.tgz#0f258c16823ddd00739461ac31398b4e7d6a18c3" + integrity sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ== + dependencies: + "@noble/hashes" "~1.4.0" + "@scure/base" "~1.1.6" + "@sentry/core@5.30.0": version "5.30.0" resolved "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz" @@ -1325,13 +1266,6 @@ "@tufjs/canonical-json" "2.0.0" minimatch "^9.0.4" -"@types/bn.js@^4.11.3": - version "4.11.6" - resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - "@types/bn.js@^5.1.0": version "5.1.2" resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.2.tgz" @@ -1339,6 +1273,13 @@ dependencies: "@types/node" "*" +"@types/chai-as-promised@^7.1.3": + version "7.1.8" + resolved "https://registry.yarnpkg.com/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz#f2b3d82d53c59626b5d6bbc087667ccb4b677fe9" + integrity sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw== + dependencies: + "@types/chai" "*" + "@types/chai-as-promised@^7.1.6": version "7.1.6" resolved "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.6.tgz" @@ -1383,11 +1324,6 @@ resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/lru-cache@^5.1.0": - version "5.1.1" - resolved "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz" - integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== - "@types/minimatch@*": version "5.1.2" resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz" @@ -1432,14 +1368,6 @@ resolved "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz" integrity sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg== -"@types/readable-stream@^2.3.13": - version "2.3.15" - resolved "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz" - integrity sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ== - dependencies: - "@types/node" "*" - safe-buffer "~5.1.1" - "@types/secp256k1@^4.0.1": version "4.0.4" resolved "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.4.tgz" @@ -1598,19 +1526,6 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" -abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz" - integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA== - dependencies: - buffer "^6.0.3" - catering "^2.1.0" - is-buffer "^2.0.5" - level-supports "^4.0.0" - level-transcoder "^1.0.1" - module-error "^1.0.1" - queue-microtask "^1.2.3" - acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" @@ -1698,6 +1613,13 @@ and@^0.0.3: resolved "https://registry.npmjs.org/and/-/and-0.0.3.tgz" integrity sha512-ns0tgq+jQFbDhAu5wrE+M7V87E4L3N8ZTJfRKVxafi7g0BSEM6JnwhL57HyR1XMHBeRfGPWZxq+SH1bZeUTiTw== +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" @@ -1931,11 +1853,6 @@ bech32@1.1.4: resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -bigint-crypto-utils@^3.0.23: - version "3.3.0" - resolved "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz" - integrity sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg== - bin-links@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.4.tgz#c3565832b8e287c85f109a02a17027d152a58a63" @@ -1961,7 +1878,7 @@ bn.js@4.11.6: resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: +bn.js@^4.11.9: version "4.12.0" resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== @@ -1971,6 +1888,20 @@ bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" @@ -1998,16 +1929,6 @@ brorand@^1.1.0: resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== -browser-level@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz" - integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.1" - module-error "^1.0.2" - run-parallel-limit "^1.1.0" - browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" @@ -2102,26 +2023,16 @@ callsites@^3.0.0: resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.2.0: version "6.3.0" resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -case@^1.6.3: - version "1.6.3" - resolved "https://registry.npmjs.org/case/-/case-1.6.3.tgz" - integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ== - caseless@^0.12.0, caseless@~0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -catering@^2.1.0, catering@^2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz" - integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== - cbor@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz" @@ -2190,7 +2101,7 @@ check-error@^1.0.2, check-error@^1.0.3: dependencies: get-func-name "^2.0.2" -chokidar@3.5.3, chokidar@^3.4.0: +chokidar@3.5.3: version "3.5.3" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -2205,6 +2116,13 @@ chokidar@3.5.3, chokidar@^3.4.0: optionalDependencies: fsevents "~2.3.2" +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + chownr@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" @@ -2235,22 +2153,16 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -classic-level@^1.2.0: - version "1.3.0" - resolved "https://registry.npmjs.org/classic-level/-/classic-level-1.3.0.tgz" - integrity sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg== - dependencies: - abstract-level "^1.0.2" - catering "^2.1.0" - module-error "^1.0.1" - napi-macros "^2.2.2" - node-gyp-build "^4.3.0" - clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cli-columns@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/cli-columns/-/cli-columns-4.0.0.tgz" @@ -2351,10 +2263,10 @@ command-exists@^1.2.8: resolved "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== -commander@3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== +commander@^8.1.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== common-ancestor-path@^1.0.1: version "1.0.1" @@ -2396,11 +2308,6 @@ core-util-is@~1.0.0: resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -crc-32@^1.2.0: - version "1.2.2" - resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz" - integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== - create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" @@ -2453,7 +2360,7 @@ death@^1.1.0: resolved "https://registry.npmjs.org/death/-/death-1.1.0.tgz" integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w== -debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2472,6 +2379,13 @@ decamelize@^4.0.0: resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== +deep-eql@^4.0.1: + version "4.1.4" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.4.tgz#d0d3912865911bb8fac5afb4e3acfa6a28dc72b7" + integrity sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg== + dependencies: + type-detect "^4.0.0" + deep-eql@^4.1.3: version "4.1.3" resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz" @@ -2580,7 +2494,7 @@ eastasianwidth@^0.2.0: resolved "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -elliptic@6.5.4, elliptic@^6.5.2, elliptic@^6.5.4: +elliptic@6.5.4, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== @@ -2935,7 +2849,7 @@ ethereum-bloom-filters@^1.0.6: dependencies: js-sha3 "^0.8.0" -ethereum-cryptography@0.1.3, ethereum-cryptography@^0.1.3: +ethereum-cryptography@^0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz" integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== @@ -2976,26 +2890,15 @@ ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: "@scure/bip32" "1.3.1" "@scure/bip39" "1.2.1" -ethereumjs-abi@^0.6.8: - version "0.6.8" - resolved "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz" - integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: - version "6.2.1" - resolved "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz" - integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== +ethereum-cryptography@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz#58f2810f8e020aecb97de8c8c76147600b0b8ccf" + integrity sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg== dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - elliptic "^6.5.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.3" + "@noble/curves" "1.4.2" + "@noble/hashes" "1.4.0" + "@scure/bip32" "1.4.0" + "@scure/bip39" "1.3.0" ethereumjs-util@^7.1.4: version "7.1.5" @@ -3008,7 +2911,7 @@ ethereumjs-util@^7.1.4: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@^5.7.1, ethers@^5.7.2: +ethers@^5.7.2: version "5.7.2" resolved "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz" integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== @@ -3078,14 +2981,6 @@ ethjs-unit@0.1.6: bn.js "4.11.6" number-to-bn "1.7.0" -ethjs-util@0.1.6, ethjs-util@^0.1.6: - version "0.1.6" - resolved "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - event-target-shim@^5.0.0: version "5.0.1" resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz" @@ -3147,6 +3042,11 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fdir@^6.4.4: + version "6.4.6" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" + integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" @@ -3169,13 +3069,6 @@ find-up@5.0.0, find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - flat-cache@^3.0.4: version "3.1.1" resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz" @@ -3238,17 +3131,6 @@ fp-ts@1.19.3, fp-ts@^1.0.0: resolved "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz" integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz" - integrity sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - fs-extra@^10.0.0: version "10.1.0" resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz" @@ -3320,11 +3202,6 @@ function.prototype.name@^1.1.6: es-abstract "^1.22.1" functions-have-names "^1.2.3" -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" - integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== - functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" @@ -3503,7 +3380,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.6: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.6: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3534,55 +3411,46 @@ hardhat-gas-reporter@^1.0.8: eth-gas-reporter "^0.2.25" sha1 "^1.1.1" -hardhat@^2.18.1: - version "2.18.1" - resolved "https://registry.npmjs.org/hardhat/-/hardhat-2.18.1.tgz" - integrity sha512-b55rW7Ka+fvJeg6oWuBTXoYQEUurevCCankjGNTwczwD3GnkhV9GEei7KUT+9IKmWx3lC+zyxlFxeDbg0gUoHw== +hardhat@^2.26.1: + version "2.26.3" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.26.3.tgz#87f3f4b6d1001970299d5bff135d57e8adae7a07" + integrity sha512-gBfjbxCCEaRgMCRgTpjo1CEoJwqNPhyGMMVHYZJxoQ3LLftp2erSVf8ZF6hTQC0r2wst4NcqNmLWqMnHg1quTw== dependencies: + "@ethereumjs/util" "^9.1.0" "@ethersproject/abi" "^5.1.2" - "@metamask/eth-sig-util" "^4.0.0" - "@nomicfoundation/ethereumjs-block" "5.0.2" - "@nomicfoundation/ethereumjs-blockchain" "7.0.2" - "@nomicfoundation/ethereumjs-common" "4.0.2" - "@nomicfoundation/ethereumjs-evm" "2.0.2" - "@nomicfoundation/ethereumjs-rlp" "5.0.2" - "@nomicfoundation/ethereumjs-statemanager" "2.0.2" - "@nomicfoundation/ethereumjs-trie" "6.0.2" - "@nomicfoundation/ethereumjs-tx" "5.0.2" - "@nomicfoundation/ethereumjs-util" "9.0.2" - "@nomicfoundation/ethereumjs-vm" "7.0.2" + "@nomicfoundation/edr" "^0.11.3" "@nomicfoundation/solidity-analyzer" "^0.1.0" "@sentry/node" "^5.18.1" - "@types/bn.js" "^5.1.0" - "@types/lru-cache" "^5.1.0" adm-zip "^0.4.16" aggregate-error "^3.0.0" ansi-escapes "^4.3.0" - chalk "^2.4.2" - chokidar "^3.4.0" + boxen "^5.1.2" + chokidar "^4.0.0" ci-info "^2.0.0" debug "^4.1.1" enquirer "^2.3.0" env-paths "^2.2.0" ethereum-cryptography "^1.0.3" - ethereumjs-abi "^0.6.8" - find-up "^2.1.0" + find-up "^5.0.0" fp-ts "1.19.3" fs-extra "^7.0.1" - glob "7.2.0" immutable "^4.0.0-rc.12" io-ts "1.10.4" + json-stream-stringify "^3.1.4" keccak "^3.0.2" lodash "^4.17.11" + micro-eth-signer "^0.14.0" mnemonist "^0.38.0" mocha "^10.0.0" p-map "^4.0.0" + picocolors "^1.1.0" raw-body "^2.4.1" resolve "1.17.0" semver "^6.3.0" - solc "0.7.3" + solc "0.8.26" source-map-support "^0.5.13" stacktrace-parser "^0.1.10" + tinyglobby "^0.2.6" tsort "0.0.1" undici "^5.14.0" uuid "^8.3.2" @@ -3918,11 +3786,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz" @@ -4097,11 +3960,6 @@ jackspeak@^2.3.5: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -js-sdsl@^4.1.4: - version "4.4.2" - resolved "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz" - integrity sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w== - js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz" @@ -4147,6 +4005,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stream-stringify@^3.1.4: + version "3.1.6" + resolved "https://registry.yarnpkg.com/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz#ebe32193876fb99d4ec9f612389a8d8e2b5d54d4" + integrity sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog== + json-stringify-nice@^1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz" @@ -4164,13 +4027,6 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz" - integrity sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw== - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz" @@ -4228,39 +4084,11 @@ kind-of@^6.0.2: resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz" - integrity sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw== - optionalDependencies: - graceful-fs "^4.1.9" - kleur@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -level-supports@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz" - integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA== - -level-transcoder@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz" - integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w== - dependencies: - buffer "^6.0.3" - module-error "^1.0.1" - -level@^8.0.0: - version "8.0.0" - resolved "https://registry.npmjs.org/level/-/level-8.0.0.tgz" - integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== - dependencies: - browser-level "^1.0.1" - classic-level "^1.2.0" - levn@^0.4.1: version "0.4.1" resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" @@ -4389,14 +4217,6 @@ libnpmversion@^5.0.1: proc-log "^3.0.0" semver "^7.3.7" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" @@ -4454,13 +4274,6 @@ lru-cache@^10.0.1, lru-cache@^10.2.2, "lru-cache@^9.1.1 || ^10.0.0": resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" @@ -4518,11 +4331,6 @@ markdown-table@^1.1.3: resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== -mcl-wasm@^0.7.1: - version "0.7.9" - resolved "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz" - integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== - md5.js@^1.3.4: version "1.3.5" resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" @@ -4532,15 +4340,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -memory-level@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz" - integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og== - dependencies: - abstract-level "^1.0.0" - functional-red-black-tree "^1.0.1" - module-error "^1.0.1" - memorystream@^0.3.1: version "0.3.1" resolved "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz" @@ -4551,11 +4350,27 @@ merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +micro-eth-signer@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz#8aa1fe997d98d6bdf42f2071cef7eb01a66ecb22" + integrity sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw== + dependencies: + "@noble/curves" "~1.8.1" + "@noble/hashes" "~1.7.1" + micro-packed "~0.7.2" + micro-ftch@^0.3.1: version "0.3.1" resolved "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz" integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== +micro-packed@~0.7.2: + version "0.7.3" + resolved "https://registry.yarnpkg.com/micro-packed/-/micro-packed-0.7.3.tgz#59e96b139dffeda22705c7a041476f24cabb12b6" + integrity sha512-2Milxs+WNC00TRlem41oRswvw31146GiSaoCT7s3Xi2gMUglW5QBeqlQaZeHr5tJx9nm3i57LNXPqxOOaWtTYg== + dependencies: + "@scure/base" "~1.2.5" + micromatch@^4.0.4: version "4.0.5" resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" @@ -4737,11 +4552,6 @@ mocha@10.2.0, mocha@^10.0.0, mocha@^10.2.0: yargs-parser "20.2.4" yargs-unparser "2.0.0" -module-error@^1.0.1, module-error@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz" - integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA== - ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" @@ -4762,11 +4572,6 @@ nanoid@3.3.3: resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz" integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== -napi-macros@^2.2.2: - version "2.2.2" - resolved "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz" - integrity sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g== - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" @@ -4805,7 +4610,7 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: +node-gyp-build@^4.2.0: version "4.6.1" resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz" integrity sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ== @@ -5172,18 +4977,16 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" +ordinal@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ordinal/-/ordinal-1.0.3.tgz#1a3c7726a61728112f50944ad7c35c06ae3a0d4d" + integrity sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ== + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^3.0.2: version "3.1.0" resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" @@ -5191,13 +4994,6 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" - integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== - dependencies: - p-limit "^1.1.0" - p-locate@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" @@ -5212,11 +5008,6 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" - integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== - pacote@^17.0.4: version "17.0.7" resolved "https://registry.yarnpkg.com/pacote/-/pacote-17.0.7.tgz#14b59a9bf5e3442c891af86825b97b7d72f48fba" @@ -5285,11 +5076,6 @@ parse-conflict-json@^3.0.0, parse-conflict-json@^3.0.1: just-diff "^6.0.0" just-diff-apply "^5.2.0" -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" @@ -5339,11 +5125,21 @@ pbkdf2@^3.0.17: safe-buffer "^5.0.1" sha.js "^2.4.8" +picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + pify@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" @@ -5459,7 +5255,7 @@ qs@^6.4.0: dependencies: side-channel "^1.0.4" -queue-microtask@^1.2.2, queue-microtask@^1.2.3: +queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== @@ -5551,6 +5347,11 @@ readable-stream@^4.1.0: process "^0.11.10" string_decoder "^1.3.0" +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" @@ -5600,7 +5401,7 @@ require-directory@^2.1.1: resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^2.0.0, require-from-string@^2.0.2: +require-from-string@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== @@ -5651,13 +5452,6 @@ reusify@^1.0.4: resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.2.8: - version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" @@ -5673,20 +5467,13 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.2.3, rlp@^2.2.4: +rlp@^2.2.4: version "2.2.7" resolved "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== dependencies: bn.js "^5.2.0" -run-parallel-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz" - integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw== - dependencies: - queue-microtask "^1.2.2" - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" @@ -5701,11 +5488,6 @@ run@^1.4.0: dependencies: minimatch "*" -rustbn.js@~0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== - safe-array-concat@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz" @@ -5926,18 +5708,16 @@ socks@^2.7.1: ip "^2.0.0" smart-buffer "^4.2.0" -solc@0.7.3: - version "0.7.3" - resolved "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz" - integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== +solc@0.8.26: + version "0.8.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.8.26.tgz#afc78078953f6ab3e727c338a2fefcd80dd5b01a" + integrity sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g== dependencies: command-exists "^1.2.8" - commander "3.0.2" + commander "^8.1.0" follow-redirects "^1.12.1" - fs-extra "^0.30.0" js-sha3 "0.8.0" memorystream "^0.3.1" - require-from-string "^2.0.0" semver "^5.5.0" tmp "0.0.33" @@ -6051,16 +5831,7 @@ statuses@2.0.1: resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6127,7 +5898,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -6141,13 +5912,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz" @@ -6295,6 +6059,14 @@ tiny-relative-date@^1.3.0: resolved "https://registry.npmjs.org/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz" integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A== +tinyglobby@^0.2.6: + version "0.2.14" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" + integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + tmp@0.0.33: version "0.0.33" resolved "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz" @@ -6386,16 +6158,6 @@ tuf-js@^2.2.1: debug "^4.3.4" make-fetch-happen "^13.0.1" -tweetnacl-util@^0.15.1: - version "0.15.1" - resolved "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz" - integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== - -tweetnacl@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz" - integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" @@ -6667,6 +6429,13 @@ wide-align@^1.1.5: dependencies: string-width "^1.0.2 || 2 || 3 || 4" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz" @@ -6682,16 +6451,7 @@ workerpool@6.2.1: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -6747,11 +6507,6 @@ y18n@^5.0.5: resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" diff --git a/fixtures/circuits/agg_agg/key b/fixtures/circuits/agg_agg/key new file mode 100644 index 0000000..153db3d Binary files /dev/null and b/fixtures/circuits/agg_agg/key differ diff --git a/fixtures/circuits/agg_agg/key_fields.json b/fixtures/circuits/agg_agg/key_fields.json new file mode 100644 index 0000000..e52337c --- /dev/null +++ b/fixtures/circuits/agg_agg/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000015", + "0x00000000000000000000000000000000000000000000000000000000000003fd", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x00000000000000000000000000000013918c215ba9cbd022badc99a35b11579e", + "0x0000000000000000000000000000000000265fb98fdb43b94c9a83bf034b137c", + "0x000000000000000000000000000000b87c94553fb91243f8fa9b8739d5c2a224", + "0x000000000000000000000000000000000000f066f765239af64e761b554af291", + "0x00000000000000000000000000000004d5d33c6d98e80300a1f8f89b1e7fdb37", + "0x000000000000000000000000000000000020bfca11b84546ac7c40b97a76b798", + "0x0000000000000000000000000000003ecc38f5c1ec991c488f33c98cbd6c42af", + "0x000000000000000000000000000000000026f4c9ab056b48b2923f19d0291eb1", + "0x00000000000000000000000000000058c50d34b76cfc94f3b5ec091db8ccdaee", + "0x00000000000000000000000000000000001419eb879d8928cab95b28b5ff8b82", + "0x000000000000000000000000000000b354cd52c6254fbdf7392eb1efdb7edd5d", + "0x000000000000000000000000000000000003924a7e9dfeddb9a7e936874d1d64", + "0x0000000000000000000000000000000c90af3c3526b88f6ea1a1d373ae296845", + "0x0000000000000000000000000000000000098595f298c2428196471e29a69df3", + "0x0000000000000000000000000000009bd08e4ac7a2948d94430327cd7cf4a4eb", + "0x00000000000000000000000000000000002ae498f285f4e78f29dad38184212b", + "0x000000000000000000000000000000f503ca5bc06d15ef2761e945530e360d8f", + "0x00000000000000000000000000000000000ffa76e1b5cf464555a6d0f944cd91", + "0x00000000000000000000000000000092d0e490d5c5ad6c481963c482986a84f3", + "0x00000000000000000000000000000000002b23eff31bf0242db213d2e12d8ff1", + "0x000000000000000000000000000000ec51c90833ff5309cdd4e53cbe2c1b037f", + "0x00000000000000000000000000000000000a6f75aa859daf3e10873166f5770d", + "0x0000000000000000000000000000002cf427b4b49ce56447036c7f09c0914fcc", + "0x00000000000000000000000000000000001d85de4e5c06d34ad3dd2a62203c76", + "0x000000000000000000000000000000bb5f3adb8b1a360885d949225f796e05a2", + "0x000000000000000000000000000000000014dd1ce931af2f1a008cdb4e13fcb4", + "0x00000000000000000000000000000036efffbc6387a0d74ed1271a8ce1566b7d", + "0x000000000000000000000000000000000011a7654358d84ce23eb3f3714bc52d", + "0x0000000000000000000000000000000d479a265fbcb7d16871cf741d20f3549d", + "0x000000000000000000000000000000000018da9cad93242886c2bd9680f7dc56", + "0x0000000000000000000000000000005f9d76fc406006483dff26dfeec559f62d", + "0x00000000000000000000000000000000002c95565158c2baa285af6cb2eefc5e", + "0x0000000000000000000000000000000b0e32b8f84bb013b8e99263f0b06abb85", + "0x0000000000000000000000000000000000038d0c791c658d984fc82e40c4210e", + "0x000000000000000000000000000000ade944e81d7311b4cbcd19064642e94964", + "0x00000000000000000000000000000000000bf4d24900138abac3ac2aa1392cd9", + "0x00000000000000000000000000000063d4f7120c514246aff5019a5702f76dc6", + "0x00000000000000000000000000000000000053d654cc7705fa3dd3adbc611a36", + "0x00000000000000000000000000000065b2d0c8dc53be750645f0eae5e3f31918", + "0x0000000000000000000000000000000000159b4194c1d17bcc5714e2fb2ae9f3", + "0x000000000000000000000000000000655d2f0fb50a45d10dcdbfb18c78319b0a", + "0x0000000000000000000000000000000000275cf42032f84e9e57bfd5144f7a7c", + "0x0000000000000000000000000000003e1cf096586072a4918dfa878bd15ff5c4", + "0x000000000000000000000000000000000026d75549771bcf0a77c3c442b4edfc", + "0x0000000000000000000000000000008e96a56c61e555023e80ac877fc99fc45f", + "0x00000000000000000000000000000000001708b2f977553631affa3daa8323bf", + "0x00000000000000000000000000000011ee654781e01494d0f5a571cad8fdf946", + "0x000000000000000000000000000000000015a960fc50fba24a14706034972c64", + "0x000000000000000000000000000000f3959f7014968cdea6a379a5cd21c9af2b", + "0x00000000000000000000000000000000002eae0d272b66c767be0bf70439a8dd", + "0x000000000000000000000000000000082947ee640730783df2ed832fc4cc659d", + "0x000000000000000000000000000000000028c3c899bf4387f6285963a947f6dd", + "0x000000000000000000000000000000bb44fc3b0b0764a4f24cb078ced7872b2f", + "0x00000000000000000000000000000000001f670d9aa72d19a8ff925280f7cf31", + "0x0000000000000000000000000000009b59f09834595cc004af1cf8886638afcf", + "0x0000000000000000000000000000000000002cc6d1400a77204a909c3787c5e9", + "0x00000000000000000000000000000085329e2fef9bdbca8695036a7682ed2dd4", + "0x0000000000000000000000000000000000160d6ad679abc89e5e524dbf3ac61f", + "0x0000000000000000000000000000005a9e3e47f106a64c593609fca0100896b8", + "0x00000000000000000000000000000000001438e9f65665ed787798e7fa021cea", + "0x000000000000000000000000000000955ad15181351e4bb40791e1af797a2e17", + "0x00000000000000000000000000000000001a342902c8cbdccf86c76affb9a282", + "0x0000000000000000000000000000003d9a0ba95512f6ed51dc7f24b86c21986d", + "0x0000000000000000000000000000000000032747a0fa5b34b84c0aaee9b3a2a9", + "0x000000000000000000000000000000e29a7e09867fc857073062bcd6d9a4afe4", + "0x00000000000000000000000000000000002199e247b90cf769b81bbba854df2a", + "0x000000000000000000000000000000b14e8722699b2390457e7770cec869a4e9", + "0x00000000000000000000000000000000001917d51d91f6a8929c6568d5bcbd86", + "0x00000000000000000000000000000094e03b8762572044743dbabaff8b32ecbc", + "0x00000000000000000000000000000000001b4c25d49a05f13f123288b652760d", + "0x0000000000000000000000000000007f9294c446b331df17568165a8bf8d9497", + "0x0000000000000000000000000000000000007cb57cd20dca63693e7a2c4dd2b1", + "0x0000000000000000000000000000002f4bb9c26e323ffd0c99b47dfc27ad881e", + "0x00000000000000000000000000000000002e9b9be53f9f2f0ce00c5dc85bc864", + "0x000000000000000000000000000000121cbfa37926f487639f22c9cf2f4ad800", + "0x0000000000000000000000000000000000042117c77b99ae250cae5a310c2878", + "0x00000000000000000000000000000036e3db414cc46e67731e6b8f3446ef19c0", + "0x0000000000000000000000000000000000027c3b1d91e2f1c61c13c32b2b85fe", + "0x000000000000000000000000000000c49854163361525b22bad2dad47d6bc63b", + "0x0000000000000000000000000000000000140137efe3d9dfc4e39e4c60cb93f0", + "0x00000000000000000000000000000098d6bc4bed5908f03114f2fb2306be675e", + "0x000000000000000000000000000000000007f42d67fcd1dc6fc0dc8a20a65d04", + "0x000000000000000000000000000000997452d09062c365996be3b3cb884370f9", + "0x0000000000000000000000000000000000050439505456f94b0af4418e7fb3b1", + "0x0000000000000000000000000000008154ce8ea254496f36da53e486d55630ea", + "0x000000000000000000000000000000000022c866b25de371d7f083d5fe4a85d7", + "0x000000000000000000000000000000dd83be27c9a9cdfedee64d86e887121b95", + "0x000000000000000000000000000000000020cb8ee1cdfaf50bb578370f5a5a4a", + "0x0000000000000000000000000000002a1ca163046e9d0415b0ba9d9c4632f07b", + "0x0000000000000000000000000000000000041b4073446b5892dd7eabf545028e", + "0x00000000000000000000000000000018573a8cb7efc197b5371780de35eb55de", + "0x0000000000000000000000000000000000005d24fbb51390fb1488b82145f514", + "0x000000000000000000000000000000be862a90b3a83a75d1073b4235299d88d2", + "0x00000000000000000000000000000000000a58ab84bec6105d9533d7b52c7d46", + "0x00000000000000000000000000000067f3b2aebec2b7b606d0d11e571da53cf7", + "0x0000000000000000000000000000000000072b71091d1ef407e20d0d0cd1689c", + "0x00000000000000000000000000000046c3574dc85c47790ef4c28da426bf3439", + "0x000000000000000000000000000000000026cd38a986f17cbd48fe1f6dfb5a00", + "0x00000000000000000000000000000036e845cb1a0b351511cfb7d51a7d48cd84", + "0x00000000000000000000000000000000000dad5bdae552b07915f2ba16ca7177", + "0x000000000000000000000000000000b75e5f1b657d31d571204511d018db5e63", + "0x00000000000000000000000000000000002141cda9c7a8779c338b16176c47d8", + "0x000000000000000000000000000000dfb867822f826d7f1bae92c942bc587396", + "0x0000000000000000000000000000000000029ef7d95d44f73300dfdc5d1f7857", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000f2eef73aa721abe282811e90febddbf6f5", + "0x00000000000000000000000000000000000d758c7eabf339ad4bb313f94501d5", + "0x000000000000000000000000000000d2061b390bfa65d60a2b69e8fc06c3cec4", + "0x000000000000000000000000000000000022c82259e587b1c7eefac3ddc9a641" +] diff --git a/fixtures/circuits/agg_agg/program.json b/fixtures/circuits/agg_agg/program.json new file mode 100644 index 0000000..6f3be5a --- /dev/null +++ b/fixtures/circuits/agg_agg/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"10638223148889237482","abi":{"parameters":[{"name":"proofs","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"AggProof","fields":[{"name":"proof","type":{"kind":"array","length":508,"type":{"kind":"field"}}},{"name":"old_root","type":{"kind":"field"}},{"name":"new_root","type":{"kind":"field"}},{"name":"commit_hash","type":{"kind":"field"}},{"name":"messages","type":{"kind":"array","length":1000,"type":{"kind":"field"}}},{"name":"verification_key","type":{"kind":"array","length":115,"type":{"kind":"field"}}},{"name":"verification_key_hash","type":{"kind":"field"}}]}},"visibility":"private"},{"name":"verification_key_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"},{"name":"old_root","type":{"kind":"field"},"visibility":"public"},{"name":"new_root","type":{"kind":"field"},"visibility":"public"},{"name":"commit_hash","type":{"kind":"field"},"visibility":"public"},{"name":"messages","type":{"kind":"array","length":1000,"type":{"kind":"field"}},"visibility":"public"}],"return_type":null,"error_types":{"5038784177220246380":{"error_kind":"string","string":"proof must be one of the valid proofs"},"5986124078905135123":{"error_kind":"string","string":"messages cannot have gaps"},"6782591386587895349":{"error_kind":"string","string":"proof message must be exported"},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15807167347632280816":{"error_kind":"string","string":"Roots must match"},"17952015221782842739":{"error_kind":"string","string":"proof old_root must match previous root"},"17984877903173405971":{"error_kind":"string","string":"proof messages exceed compacted range"}}},"bytecode":"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","debug_symbols":"pP3drmbZsp3n3cs+5sGI/wjdimEItE0bBAjKoCWfCLp3V1Z9b+sSYBLE0smawb2ZuStn662PsXI+8dX/+m//j//wf/tf/l//43/8z//P/+n/82//w//lf/23/9t/+Y//6T/9x//X//if/qf/+7//n//j//Sf//qf/q//27/7N/6f/+P//F/+w3/463/0b/+7//1fv+r//e//y3/4z//zv/0P//l/+U//6d/92//33/+n/+Xv/0//n//3v//Pf3/9n//9f/nrf/v9u3/7D//5//HX179+w//nf/xP/+HP9L/9u/erv//6L12z3y/eKP3ynv/uXz/69fev/Pqwqt9vENb5L/wO3fwT9Hz/yp/gfQe6/099B87/pV9vn379/Au//jL59bX/wq+3PBKwsn8lAbvP+R3O7l/4Hfyb+P0O/p39K7+DJf8MbjX/0u+ww+/g379ylt0Vpbvvv/bP0O93+Je+k/7+FPH5v/I7ZOk7mf9So7zf79DT/9LvEPV/8neY03dy7V9K83v/DF/9S9+HSv0zVP9L3bwINaviX7lfv17u12//pV7c6neI+69+H7z+G/8Q3q7fIl8Y7v/df4xMPSay/5U/RuSX+h38X/pW+sdNH3/dEP/K79Cm78PEf/VYx3/rt1C10v53v0H+H38D+28Vw3QoJ77/6m/h/41TObqtbc7/q79F/LceWvX/76H13/8b2Od65nxd/9Xf4r9xKjP15pB575/iryfYf/d34r5TP/2/+p34b+a59d9xJP5bv8NU63eY/+ON/3/96//17//v//G//B/eOv/N/u1/+Ov/pv/9n/H3f+bf/1l//aJ/92/993/O3/+5f//n/fWS8u/+zb6/wvrri/3zxf/58tev//P+ZPn7Wr+vf/0u9ld8Nr+v+/t6f144/vo//v2+2u+r/3n7+Otr/L7++f3++j/t9fvav69/fr+/HnC+v6/3z9f48/v99c8T9uch+tdX/32N39f8fa3f1/7nnzPm93V/X//8fn8Fnt/vq/2++u9r/L7m72v98+fK3583f3/e3H/+XPn789bvz1v2z5+vfn/ein/+XPX789bvz1u/P2/N7+v+vt4/X/v758/d9vv658/71z9Px+9r/r7W7+uf3++vEHt+X/ef71ffP9+P+X5ff9+/+X3/5vf9m9/3b375zu/7N7/v3+w/34/5ff/29/3b3/dv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fHvVKvNV5vj2Knx7Fb69apX5KnPcaxXutWqV+Slz9bzU88K3V+Hbq06Z416rcK9Vp8zx7dXqeavnjW+vxrdX49ur8e3V+PZqfHs1vr0a316Ne63GvVbjXqvx7dXqeavnrZ43vr0a316Ne63GvVbjXqvx7dXqeavnrZ43vr0a316Nb6/Gt1fj26vx7dX49mp8ezW+vRr3Wo17rca3V+Pbq9XzVs8b316Nb6/Gt1fjXqtxr9X49mp8e7V63up549ur8e3Vpczx7dX49upS5vj2anx7Ne61Gvda3cq8lbl63up5q+eNb6/Gt1fjXqtxr9WtzEeZq+etnrd63vj2anx79SjzUeb49mp8ezW+vXqV+Spz3Gs17rV6lfkqc/W81fPGt1fj26tPmeNeq3Gv1afMT5mr562eN769Gt9eg2+vwbfX4Ntr8O01+PYafHsN7rUG91qDe63Bt9eo56Oej3o++PYafHsN7rUG91qDe63Bt9eo56Oej3o++PYafHsNvr0G316Db6/Bt9fg22vw7TX49hrcaw3utQbfXoNvr1HPRz0ffHsNvr0G316De63Bvdbg22vw7TXq+ajng2+vwbfX4Ntr8O01+PaaUub49hp8ew3utQb3WlPKvJS5ej7q+ajng2+vwbfX4F5rcK81rcxbmavno56Pej749hp8e80o81Hm+PYafHsNvr1mlPkoc9xrDe61ZpX5KnP1fNTzwbfX4NtrVpnjXmtwrzWnzE+Zq+ejng++vQbfXnPKHN9eg2+vwbfX4ttr8e21uNda3Gst7rUW316rnq96vur54ttr8e21uNda3Gst7rUW316rnq96vur54ttr8e21+PZafHstvr0W316Lb6/Ft9fi22txr7W411p8ey2+vVY9X/V88e21+PZafHst7rUW91qLb6/Ft9eq56ueL769Ft9ei2+vxbfX4ttr8e21+PZafHst7rUW91pbyryUuXq+6vmq54tvr8W31+Jea3Gvta3MW5mr56uer3q++PZafHttK/NW5vj2Wnx7Lb69dpT5KHPcay3utXaU+Shz9XzV88W31+Lba1eZ415rca+1q8xXmavnq54vvr0W3157yhzfXotvrz1ljm+vxbfXnjqIe63Dvdbh2+vU81PPTz0/fHsdvr0O91qHe63Dvdbh2+vU81PPTz0/fHsdvr0O316Hb6/Dt9fh2+vw7XX49jp8ex3utQ73Wodvr8O316nnp54fvr0O316Hb6/DvdbhXuvw7XX49jr1/NTzw7fX4dvr8O11+PY6fHsdvr0O316Hb6/DvdbhXutwr3WpzNXzU89PPT98ex2+vQ73Wod7rStlXspcPT/1/NTzw7fX4dvrWpm3Mse31+Hb6/Dtda3MR5njXutwr3WjzEeZq+ennh++vQ7fXjfKHPdah3utW2W+ylw9P/X88O11+Pa6Veb49jp8e90pc3x7Hb697tRB3GvdKfNT5ur50fP+6Hl/+Pb+8O394V77w732h3vtD9/eHz3vj573R8/7w7f3h2/vD9/eH769P3x7f/j2/vDt/eHb+8O394d77Q/32h++vT98e3/0vD963h++vT98e3/49v5wr/3hXvvDt/eHb++PnvdHz/vDt/eHb+8P394fvr0/fHt/+Pb+8O394dv7w732h3vtD/faH769P3reHz3vj573h2/vD9/eH+61P9xrf6XMS5mXMi9lXsoc394fvr2/VuatzPHt/eHb+8O399fKvJU57rU/3Gt/rcxHmY8yH2WOb+8P397fKHPca3+41/5GmY8yX2W+yhzf3h++vb9V5vj2/vDt/a0yx7f3h2/v79RB3Gt/p8xPmZ8yP2V+yhzf3h++vT/caxvutQ332oZvb1PPTT039dzw7W349jZ8exu+vQ3f3oZvb8O3t+Hb2/DtbbjXNtxrG769Dd/epp6bem749jZ8exu+vQ332oZ7bcO3t+Hb29RzU88N396Gb2/Dt7fh29vw7W349jZ8exu+vQ332oZ7bcO9tuHb29RzU89NPTd8exu+vQ332oZ7bUtlXspcPTf13NRzw7e34dvbSpmXMse3t+Hb2/Dtba3MW5njXttwr22tzFuZq+emnhu+vQ3f3jbKHPfahnttG2U+ylw9N/Xc8O1t+Pa2Veb49jZ8e9sqc3x7G769DffahnttW2W+ylw9N/Xc1HPDt7fh29tOHcS9tp0yP2Wunrt67uq549vb8e3t+PZ2fHs7vr0d396Ob2/Ht7fj29txr+2413Z8ezu+vV09d/Xc8e3t+PZ2fHs77rUd99qOb2/Ht7er566eO769Hd/ejm9vx7e349vb8e3t+PZ2fHs77rUd99qOe23Ht7er566eu3ru+PZ2fHs77rUd99qOe23Ht7er566eu3ru+PZ2fHt7KfNS5vj2dnx7O769vZR5KXPcazvutb2VeStz9dzVc8e3t+Pb21uZ417bca/to8xHmavnrp47vr0d394+yhzf3o5vbx9ljm9vx7e3417bca/tq8xXmavnrp67eu749nZ8e/upg7jX9lPmp8zVc1fPXT13fHs7vr0D396Bb+/At3fg2zvw7R349g58ewfutQP32oFv78C3d6jnoZ4Hvr0D396Bb+/AvXbgXjvw7R349g71PNTzwLd34Ns78O0d+PYOfHsHvr0D396Bb+/AvXbgXjtwrx349g71PNTzUM8D396Bb+/AvXbgXjtwrx349g71PNTzUM8D396Bb+/At3ekMse3d+DbO/DtHaXMS5njXjtwrx2lzEuZq+ehnge+vQPf3tHKHPfagXvtaGXeylw9D/U88O0d+PaOUeb49g58e8coc3x7B769A/fagXvtWGW+ylw9D/U81PPAt3fg2ztwrx24145V5qfM1fNQz0M9D3x7B76945T5KXN8ewe+vRPf3olv78S3d+JeO3Gvnfj2Tnx7p3qe6nni2zvx7Z349k7cayfutRPf3olv71TPUz1PfHsnvr0T396Jb+/Et3fi2zvx7Z349k7cayfutRP32olv71TPUz1P9Tzx7Z349k7cayfutRP32olv71TPUz1P9Tzx7Z349k58eye+vRPf3olv78S3d6YyL2WOe+3EvXaWMi9lrp6nep749k58e2cpc9xrJ+61s5V5K3P1PNXzxLd34ts7W5nj2zvx7Z2jzPHtnfj2TtxrJ+61c5T5KHP1PNXzVM8T396Jb+/EvXbiXjtXma8yV89TPU/1PPHtnfj2zlPmp8zx7Z349k58e+cp81PmuNcu3GsXvr0L396lnpd6Xvj2Lnx7F769C/fahXvtwrd34du71PNSzwvf3oVv78K3d+Hbu/DtXfj2Lnx7F769C/fahXvtwr124du71PNSz0s9L3x7F769C/fahXvtwr124du71PNSz0s9L3x7F769C9/ehW/vwrd34du78O1d+PYufHsX7rUL99qVyryUuXpe6nnh27vw7V2lzHGvXbjXrlLmpczV81LPC9/ehW/vamWOb+/Ct3e1Mse3d+Hbu3CvXbjXrlHmo8zV81LPSz0vfHsXvr0L99qFe+1aZb7KXD0v9bzU88K3d+Hbu1aZrzLHt3fh27vw7V2nzE+Z4167cK9dp8xPmavnrZ43vr0b396Nb+/GvXbjXrvx7d349m71vNXzxrd349u78e3d+PZufHs3vr0b396Nb+/GvXbjXrtxr9349m71vNXzVs8b396Nb+/GvXbjXrtxr9349m71vNXzVs8b396Nb+/Gt3fj27vx7d349m58eze+vRvf3o177ca9duPbu/Ht3ep5q+eNb+/Gt3eXMse9duNeu0uZlzJXz1s9b3x7N769u5U5vr0b397dyhzf3o1v78a9duNeu1uZtzJXz1s9b/W88e3d+PZu3Gs37rV7lPkoc/W81fNWzxvf3o1v715lvsoc396Nb+/Gt3evMj9ljnvtxr12nzI/Za6et3re+PZufHs3vr0H99qDe+3Bt/fg23vU81HPB9/eg2/vwbf34Nt78O09+PYefHsPvr0H99qDe+3Bvfbg23vU81HPRz0ffHsPvr0H99qDe+3Bvfbg23vU81HPRz0ffHsPvr0H396Db+/Bt/fg23vw7T349h58ew/utQf32oNv78G396jno54Pvr0H396Db+/BvfbgXntKmZcyV89HPR98ew++vaeUOb69B9/eU8oc396Db+/BvfbgXntambcyV89HPR/1fPDtPfj2HtxrD+61Z5T5KHP1fNTzUc8H396Db+9ZZb7KHN/eg2/vwbf3rDJfZY577cG99qwyP2Wuno96Pvj2Hnx7zylz3GsP7rXnlDm+vVc9X/V88e29+PZefHsvvr0X396Lb+/Ft/fi23txr724117cay++vVc9X/V81fPFt/fi23txr724117cay++vVc9X/V81fPFt/fi23vx7b349l58ey++vRff3otv78W39+Jee3Gvvfj2Xnx7r3q+6vni23vx7b349l7cay/utRff3otv71XPVz1ffHsvvr23lDm+vRff3lvKHN/ei2/vxb324l57W5m3MlfPVz1f9Xzx7b349l7cay/utbeV+Shz9XzV81XPF9/ei2/vHWU+yhzf3otv78W3964yX2WOe+3FvfauMl9lrp6ver749l58e+8pc9xrL+6195T5KXP1fNXzxbf34tv78O19+PY+fHsfvr0P396Hb+/DvfbhXvtwr3349j71/NTzU88P396Hb+/DvfbhXvtwr3349j71/NTzU88P396Hb+/Dt/fh2/vw7X349j58ex++vQ/f3od77cO99uHb+/Dtfer5qeeHb+/Dt/fh2/twr324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53Cvc63MW5mr56een3p++PY5fPsc7nUO9zo3ynyUuXp+6vmp54dvn8O3z60yX2WOb5/Dt8/h2+dWma8yx73O4V7nVpmfMlfPTz0/fPscvn3ulDnudQ73OnfKHN++Hz3fj57vh2/fD9++H759P3z7fvj2/fDt++Hb98O374d73Q/3uh/udT98+370fD96vh893w/fvh++fT/c63641/1wr/vh2/ej5/vR8/3o+X749v3w7fvh2/fDt++Hb98P374fvn0/fPt++Pb9cK/74V73w7fvh2/fj57vR8/3w7fvh2/fD9++H+51P9zrfvj2/fDt+9Hz/VKZ49v3w7fvV8oc374fvn2/Uub49v3w7fvhXvfDve7XyryVeSvzVuatzPHt++Hb98O97od73a+V+SjzUeajzEeZ49v3w7fvN8p8lDm+fT98+3749v1Wma8yx73uh3vdb5X5KvNV5qvM8e374dv3O2WOe90P97rfKfNT5qfMT5nj2/fDt6/h29fw7Wv49jV8+xq+fQ3fvoZ7XcO9ruFe1/Dta+q5qeemnhu+fQ3fvoZ7XcO9ruFe1/Dta+q5qeemnhu+fQ3fvoZvX8O3r+Hb1/Dta/j2NXz7Gr59Dfe6hntdw7ev4dvX1HNTzw3fvoZvX8O3r+Fe13Cva/j2NXz7mnpu6rnh29fw7Wv49jV8+xq+fa2UOb59Dd++hntdw72ulTIvZa6em3pu6rnh29fw7Wu41zXc61or81bm6rmp56aeG759Dd++Nsp8lDm+fQ3fvoZvXxtlPsoc97qGe11bZb7KXD039dzw7Wv49rVV5rjXNdzr2inzU+bquannhm9fw7evnTLHt6/h29fw7ev49nV8+zrudR33uo57Xce3r6vnrp67eu749nV8+zrudR33uo57Xce3r6vnrp67eu749nV8+zq+fR3fvo5vX8e3r+Pb1/Ht6/j2ddzrOu51Hd++jm9fV89dPXd8+zq+fR3fvo57Xce9ruPb1/Ht6+q5q+eOb1/Ht6/j29fx7ev49nV8+zq+fR3fvo57Xce9rpcyL2Wunrt67uq549vX8e3ruNd13Ot6K/NW5uq5q+eunju+fR3fvt7KvJU5vn0d376Ob18fZT7KHPe6jntdH2U+ylw9d/Xc8e3r+Pb1Vea413Xc6/oq81Xm6rmr545vX8e3r58yx7ev49vXT5nj29fx7eunDuJeN3CvG/j2DfU81PNQzwPfvoFv38C9buBeN3CvG/j2DfU81PNQzwPfvoFv38C3b+DbN/DtG/j2DXz7Br59A9++gXvdwL1u4Ns38O0b6nmo54Fv38C3b+DbN3CvG7jXDXz7Br59Qz0P9Tzw7Rv49g18+wa+fQPfvoFv38C3b+DbN3CvG7jXDdzrRipz9TzU81DPA9++gW/fwL1u4F43SpmXMlfPQz0P9Tzw7Rv49o1W5q3M8e0b+PYNfPtGK/NR5rjXDdzrxijzUebqeajngW/fwLdvjDLHvW7gXjdWma8yV89DPQ98+wa+fWOVOb59A9++ccoc376Bb984dRD3unHK/JS5eh7qearniW/fxLdv4l43ca+buNdNfPumep7qearniW/fxLdv4ts38e2b+PZNfPsmvn0T376Jb9/EvW7iXjfx7Zv49k31PNXzxLdv4ts38e2buNdN3Osmvn0T376pnqd6nvj2TXz7Jr59E9++iW/fxLdv4ts38e2buNdN3Osm7nUT376pnqd6nup54ts38e2buNdN3OtmKfNS5up5quepnie+fRPfvtnKvJU5vn0T376Jb99sZd7KHPe6iXvdbGU+ylw9T/U88e2b+PbNUea4103c6+Yo81Hm6nmq54lv38S3b64yx7dv4ts3V5nj2zfx7ZunDuJeN0+ZnzJXz1M9T/U88e2b+PZN3OsW7nUL97qFb99Sz0s9L/W88O1b+PYtfPsWvn0L376Fb9/Ct2/h27fw7Vu41y3c6xa+fQvfvqWel3pe+PYtfPsWvn0L97qFe93Ct2/h27fU81LPC9++hW/fwrdv4du38O1b+PYtfPsWvn0L97qFe93CvW7h27fU81LPSz0vfPsWvn0L97qFe91KZV7KXD0v9bzU88K3b+Hbt0qZlzLHt2/h27fw7VutzFuZ4163cK9brcxbmavnpZ4Xvn0L3741yhz3uoV73RplPspcPS/1vPDtW/j2rVXm+PYtfPvWKnN8+xa+fQv3uoV73VplvspcPS/1vNTzwrdv4du3Th3EvW6dMj9lrp63et7qeePbt/Ht2/j2bXz7Nr59G9++jW/fxrdv49u3ca/buNdtfPs2vn1bPW/1vPHt2/j2bXz7Nu51G/e6jW/fxrdvq+etnje+fRvfvo1v38a3b+Pbt/Ht2/j2bXz7Nu51G/e6jXvdxrdvq+etnrd63vj2bXz7Nu51G/e6jXvdxrdvq+etnrd63vj2bXz7dinzUub49m18+za+fbuUeSlz3Os27nW7lXkrc/W81fPGt2/j27dbmeNet3Gv26PMR5mr562eN759G9++Pcoc376Nb98eZY5v38a3b+Net3Gv26vMV5mr562et3re+PZtfPv2qYO41+1T5qfM1fNWz1s9b3z7Nr59B9++g2/fwbfv4Nt38O07+PYdfPsO7nUH97qDb9/Bt++o56OeD759B9++g2/fwb3u4F538O07+PYd9XzU88G37+Dbd/DtO/j2HXz7Dr59B9++g2/fwb3u4F53cK87+PYd9XzU81HPB9++g2/fwb3u4F53cK87+PYd9XzU81HPB9++g2/fwbfvpDLHt+/g23fw7TulzEuZ4153cK87pcxLmavno54Pvn0H377Tyhz3uoN73Wll3spcPR/1fPDtO/j2nVHm+PYdfPvOKHN8+w6+fQf3uoN73VllvspcPR/1fNTzwbfv4Nt3cK87uNedVeanzNXzUc9HPR98+w6+feeU+SlzfPsOvn0X376Lb9/Ft+/iXndxr7v49l18+656vur54tt38e27+PZd3Osu7nUX376Lb99Vz1c9X3z7Lr59F9++i2/fxbfv4tt38e27+PZd3Osu7nUX97qLb99Vz1c9X/V88e27+PZd3Osu7nUX97qLb99Vz1c9X/V88e27+PZdfPsuvn0X376Lb9/Ft++mMi9ljnvdxb3uljIvZa6er3q++PZdfPtuKXPc6y7udbeVeStz9XzV88W37+Lbd1uZ49t38e27o8zx7bv49l3c6y7udXeU+Shz9XzV81XPF9++i2/fxb3u4l53V5mvMlfPVz1f9Xzx7bv49t1T5qfM8e27+PZdfPvuKfNT5rjXPdzrHr59D9++p56fen749j18+x6+fQ/3uod73cO37+Hb99TzU88P376Hb9/Dt+/h2/fw7Xv49j18+x6+fQ/3uod73cO97uHb99TzU89PPT98+x6+fQ/3uod73cO97uHb99TzU89PPT98+x6+fQ/fvodv38O37+Hb9/Dte/j2PXz7Hu51D/e6l8q8lLl6fur54dv38O17pcxxr3u4171S5qXM1fNTzw/fvodv32tljm/fw7fvtTLHt+/h2/dwr3u4171R5qPM1fNTz089P3z7Hr59D/e6h3vdW2W+ylw9P/X81PPDt+/h2/dWma8yx7fv4dv38O17p8xPmeNe93Cve6fMT5nT8/vo+X349vvw7ffh2+/Dvd6He70P334fvv0+en4fPb8P334fvv0+fPt9+Pb78O334dvvw7ffh2+/D/d6H+71Ptzrffj2++j5ffT8Pnp+H779Pnz7fbjX+3Cv9+Fe78O330fP76Pn99Hz+/Dt9+Hb78O334dvvw/ffh++/T58+3349vvw7ffhXu/Dvd6Hb78P334fPb+Pnt+Hb78P335fKXPc63241/tKmZcyL2Veyhzffh++/b5W5vj2+/Dt97Uyx7ffh2+/D/d6H+71vlbmrcxHmY8yH2WOb78P334f7vU+3Ot9o8xHmY8yX2W+yhzffh++/b5V5qvM8e334dvvw7fft8r8lDnu9T7c632nzE+ZnzI/ZY5vvw/ffh++/Qz3eoZ7PcO3n+Hbz9RzU88N336Gbz/Dt5/h28/w7Wf49jN8+xm+/Qz3eoZ7PcO9nuHbz9RzU89NPTd8+xm+/Qz3eoZ7PcO9nuHbz9RzU89NPTd8+xm+/QzffoZvP8O3n+Hbz/DtZ/j2M3z7Ge71DPd6hm8/w7efqeemnhu+/QzffoZvP8O9nuFez0qZlzJXz009N3z7Gb79rJQ5vv0M335WyhzffoZvP8O9nuFez1qZtzJXz009N/Xc8O1n+PYz3OsZ7vVslPkoc/Xc1HNTzw3ffoZvP1tlvsoc336Gbz/Dt5+tMl9ljns9w72erTI/Za6em3pu+PYzfPvZKXPc6xnu9eyUOb79XD139dzx7ef49nN8+zm+/Rzffo5vP8e3n+Pbz3Gv57jXc9zrOb79XD139dzVc8e3n+Pbz3Gv57jXc9zrOb79XD139dzVc8e3n+Pbz/Ht5/j2c3z7Ob79HN9+jm8/x7ef417Pca/n+PZzfPu5eu7quePbz/Ht5/j2c9zrOe71HN9+jm8/V89dPXd8+zm+/byUOb79HN9+Xsoc336Obz/HvZ7jXs9bmbcyV89dPXf13PHt5/j2c9zrOe71vJX5KHP13NVzV88d336Obz8fZT7KHN9+jm8/x7efrzJfZY57Pce9nq8yX2Wunrt67vj2c3z7+Slz3Os57vX8lPkpc/Xc1XPHt5/j2y/w7Rf49gt8+wW+/QLffoFvv8C9XuBeL3CvF/j2C/U81PNQzwPffoFvv8C9XuBeL3CvF/j2C/U81PNQzwPffoFvv8C3X+DbL/DtF/j2C3z7Bb79At9+gXu9wL1e4Nsv8O0X6nmo54Fvv8C3X+DbL3CvF7jXC3z7Bb79Qj0P9Tzw7Rf49gt8+wW+/QLfflHKHN9+gW+/wL1e4F4vSpmXMlfPQz0P9Tzw7Rf49gvc6wXu9aKVeStz9TzU81DPA99+gW+/GGU+yhzffoFvv8C3X4wyH2WOe73AvV6sMl9lrp6Heh749gt8+8Uqc9zrBe714pT5KXP1PNTzwLdf4NsvTpnj2y/w7Rf49kt8+yW+/RL3eol7vcS9XuLbL9XzVM9TPU98+yW+/RL3eol7vcS9XuLbL9XzVM9TPU98+yW+/RLffolvv8S3X+LbL/Htl/j2S3z7Je71Evd6iW+/xLdfquepnie+/RLffolvv8S9XuJeL/Htl/j2S/U81fPEt1/i2y/x7Zf49kt8+yW+/RLffolvv8S9XuJeL0uZlzJXz1M9T/U88e2X+PZL3Osl7vWylXkrc/U81fNUzxPffolvv2xl3soc336Jb7/Et1+OMh9ljnu9xL1ejjIfZa6ep3qe+PZLfPvlKnPc6yXu9XKV+Spz9TzV88S3X+LbL0+Z49sv8e2Xp8zx7Zf49stTB3GvV7jXK3z7lXpe6nmp54Vvv8K3X+Fer3CvV7jXK3z7lXpe6nmp54Vvv8K3X+Hbr/DtV/j2K3z7Fb79Ct9+hW+/wr1e4V6v8O1X+PYr9bzU88K3X+Hbr/DtV7jXK9zrFb79Ct9+pZ6Xel749it8+xW+/QrffoVvv8K3X+Hbr/DtV7jXK9zrFe71KpW5el7qeannhW+/wrdf4V6vcK9XpcxLmavnpZ6Xel749it8+1Ur81bm+PYrfPsVvv2qlfkoc9zrFe71apT5KHP1vNTzwrdf4duvRpnjXq9wr1erzFeZq+elnhe+/QrffrXKHN9+hW+/OmWOb7/Ct1+dOoh7vTplfspcPS/1vNXzxrdf49uvca/XuNdr3Os1vv1aPW/1vNXzxrdf49uv8e3X+PZrfPs1vv0a336Nb7/Gt1/jXq9xr9f49mt8+7V63up549uv8e3X+PZr3Os17vUa336Nb79Wz1s9b3z7Nb79Gt9+jW+/xrdf49uv8e3X+PZr3Os17vUa93qNb79Wz1s9b/W88e3X+PZr3Os17vW6lHkpc/W81fNWzxvffo1vv25l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tJLSSsSSEkuKHseKHseqtBJ6HCt6HKvSSuhxrOhxrHDorXDorVoraa1ELCmxpMSSosexosexwqG3wqG3Gq1ktBKxpMSSEkuKHseKHsdqtZLVSuhxrOhxrOhxrFYrWa0Eh94Kh95qtZLTSsSSEkuKHseKHsfqtBIceisceqvTSuhxrMWSFkuaHseaHseaHseaHseaHseaHseaHseaHscah94ah94ah96aHsdaLGmxpMWSpsexpsexxqG3xqG3xqG3psexFktaLGmxpOlxrOlxrOlxrOlxrOlxrOlxrOlxrOlxrOlxrHHorXHorelxrOlxrMWSFkuaHseaHseaHscah94ah96aHseaHsdaLGmxpOlxrOlxrEsrocexpsexLq2EHseaHscah94ah966tZLWSsSSFktaLGl6HGt6HGscemsceuvWSkYrEUtaLGmxpOlxrOlxrEcrGa2EHseaHseaHsd6tZLVSnDorXHorVcrWa1ELGmxpOlxrOlxrE8rwaG3xqG3Pq3ktBKxpMWSpsexpsexocexocexocexocexocexocexwaG3waG3waG3ocexEUtGLBmxZOhxbOhxbHDobXDobXDobehxbMSSEUtGLBl6HBt6HBt6HBt6HBt6HBt6HBt6HBt6HBt6HBscehsceht6HBt6HBuxZMSSocexocexocexwaG3waG3ocexocexEUtGLBl6HBt6HBt6HBt6HBt6HJvSSuhxbOhxbHDobXDobUorKa1ELBmxZMSSocexocexwaG3waG3aa2ktRKxZMSSEUuGHseGHsdmtJLRSuhxbOhxbOhxbEYrGa0Eh94Gh95mtZLVSsSSEUuGHseGHsdmtRIcehscepvTSk4rEUtGLBl6HBt6HJvTSuhxbOhxbOhxbOlxbOlxbHHobXHobXHobelxbMWSFUtWLFl6HFt6HFscelscelscelt6HFuxZMWSFUuWHseWHseWHseWHseWHseWHseWHseWHseWHscWh94Wh96WHseWHsdWLFmxZOlxbOlxbOlxbHHobXHobelxbOlxbMWSFUuWHseWHseWHseWHseWHseWHseWHseWHscWh94Wh962tJLSSsSSFUtWLFl6HFt6HFscelscetvWSlorEUtWLFmxZOlxbOlxbFsraa2EHseWHseWHsd2tJLRSnDobXHobUcrGa1ELFmxZOlxbOlxbFcrwaG3xaG3Xa1ktRKxZMWSpcexpcexPa2EHseWHsf2tBJ6HFt6HNvT141Db4dDb0ePYyeWnFhyYsnR49jR49jh0Nvh0Nvh0NvR49iJJSeWnFhy9Dh29Dh29Dh29Dh29Dh29Dh29Dh29Dh29Dh2OPR2OPR29Dh29Dh2YsmJJUePY0ePY0ePY4dDb4dDb0ePY0ePYyeWnFhy9Dh29Dh29Dh29Dh29Dh29Dh29Dh29Dh2OPR2OPR2OPR2qZWIJSeWnFhy9Dh29Dh2OPR2OPR2pZWUViKWnFhyYsnR49jR49i1VtJaCT2OHT2OHT2OXWslo5Xg0Nvh0NuNVjJaiVhyYsnR49jR49iNVoJDb4dDb7dayWolYsmJJUePY0ePY7daCT2OHT2O3Wkl9Dh29Dh2p68bh97utJLTSsSSgyX+YIk/ehx/9Dj+cOj94dD7w6H3R4/jD5b4gyX+YIk/ehx/9Dj+6HH80eP4o8fxR4/jjx7HHz2OP3ocfzj0/nDo/dHj+KPH8QdL/MESf/Q4/uhx/NHj+MOh94dD748exx89jj9Y4g+W+KPH8UeP448exx89jj96HH/0OP7ocfzR4/jDofeHQ+8Ph94fPY4/WOIPlviDJf7ocfzR4/jDofeHQ++vtJLSSkorKa2ktBJ6HH/0OP5aK2mthB7HHz2OP3ocf62VtFaCQ+8Ph95fayWjlYxWMloJPY4/ehx/o5Xg0PvDofc3WsloJauVrFZCj+OPHsffaiX0OP7ocfytVkKP448ex9/p68ah93dayWklp5WcVnJaCT2OP3ocfzj0bjj0bjj0bvQ4bmKJiSUmlhg9jhs9jhs9jhs9jhs9jhs9jhs9jhs9jhs9jhsOvRsOvRs9jhs9jptYYmKJ0eO40eO40eO44dC74dC70eO40eO4iSUmlhg9jhs9jhs9jhs9jhs9jhs9jhs9jhs9jhsOvRsOvRsOvRs9jptYYmKJiSVGj+NGj+OGQ++GQ++WWklpJWKJiSUmlhg9jhs9jltpJaWV0OO40eO40eO4tVbSWgkOvRsOvVtrJa2ViCUmlhg9jhs9jttoJTj0bjj0bqOVjFYilphYYvQ4bvQ4bquV0OO40eO4rVZCj+NGj+OGQ++GQ++2WslqJWKJiSUmlhg9jhs9jtvp68ahdzut5LQSscTFEhdLnB7HnR7HnR7HnR7HnR7HnR7HnR7HnR7HnR7HHYfeHYfenR7HnR7HXSxxscTpcdzpcdzpcdxx6N1x6N3pcdzpcdzFEhdLnB7HnR7HnR7HnR7HnR7HnR7HnR7HnR7HHYfeHYfeHYfenR7HXSxxscTFEqfHcafHccehd8ehd8ehd6fHcRdLXCxxscTpcdzpcdxLKymthB7HnR7HnR7HvbSS0kpw6N1x6N1bK2mtRCxxscTpcdzpcdxbK8Ghd8ehdx+tZLQSscTFEqfHcafHcR+thB7HnR7HfbQSehx3ehx3HHp3HHr31UpWKxFLXCxxscTpcdzpcdxPXzcOvftpJaeViCUulrhY4vQ47vQ4HvQ4HvQ4HvQ4HvQ4HvQ4HvQ4HvQ4Hjj0Hjj0HvQ4HvQ4HmJJiCVBj+NBj+NBj+OBQ++BQ+9Bj+NBj+MhloRYEvQ4HvQ4HvQ4HvQ4HvQ4HvQ4HvQ4HvQ4Hjj0Hjj0Hjj0HvQ4HmJJiCUhlgQ9jgc9jgcOvQcOvQcOvQc9jodYEmJJiCVBj+NBj+NBj+ORWgk9jgc9jgc9jkdpJaWV4NB74NB7lFZSWolYEmJJ0ON40ON4tFaCQ++BQ+/RWklrJWJJiCVBj+NBj+MxWgk9jgc9jsdoJfQ4HvQ4Hjj0Hjj0HquVrFYiloRYEmJJ0ON40ON44NB74NB7rFZyWolYEmJJiCVBj+NBj+NxWslpJfQ4HvQ4nvQ4nvQ4nvQ4njj0njj0nvQ4nvQ4nmJJiiVJj+NJj+NJj+OJQ++JQ+9Jj+NJj+MplqRYkvQ4nvQ4nvQ4nvQ4nvQ4nvQ4nvQ4nvQ4njj0njj0njj0nvQ4nmJJiiUpliQ9jic9jicOvScOvScOvSc9jqdYkmJJiiVJj+NJj+NJj+NJj+NJj+NJj+NJj+OZWklpJTj0njj0nqWVlFYilqRYkvQ4nvQ4nqWV4NB74tB7tlbSWolYkmJJ0uN40uN4tlZCj+NJj+M5Wgk9jic9jicOvScOvedoJaOViCUplqRYkvQ4nvQ4njj0njj0nquVrFYilqRYkmJJ0uN40uN4nlZyWgk9jic9jic9judpJaeV4NB74dB70eN40eN4iSUllhQ9jhc9jhc9jhcOvRcOvRc9jhc9jpdYUmJJ0eN40eN40eN40eN40eN40eN40eN40eN44dB74dB74dB70eN4iSUllpRYUvQ4XvQ4Xjj0Xjj0Xjj0XvQ4XmJJiSUllhQ9jhc9jhc9jhc9jhc9jhc9jhc9jhc9jhc9jhcOvRcOvVdqJaWViCUllhQ9jhc9jldpJTj0Xjj0XqWVlFYilpRYUvQ4XvQ4Xq2V0ON40eN4tVZCj+NFj+OFQ++FQ+81WsloJWJJiSUllhQ9jhc9jhcOvRcOvddqJauViCUllpRYUvQ4XvQ4XquVrFZCj+NFj+NFj+N1WslpJTj0Xjj0XqeVnFYilrRY0vQ43vQ43vQ43jj03jj03vQ43vQ43mJJiyVNj+NNj+NNj+NNj+NNj+NNj+NNj+NNj+ONQ++NQ++NQ+9Nj+MtlrRY0mJJ0+N40+N449B749B749B70+N4iyUtlrRY0vQ43vQ43vQ43vQ43vQ43vQ43vQ43vQ43vQ43jj03jj03vQ43vQ43mJJiyVNj+NNj+NdWgkOvTcOvXdpJaWViCUtljQ9jjc9jndrJfQ43vQ43q2V0ON40+N449B749B7t1bSWolY0mJJiyVNj+NNj+ONQ++NQ+89WsloJWJJiyUtljQ9jjc9jvdqJauV0ON40+N40+N4r1ZyWgkOvTcOvfdpJaeViCUtljQ9jjc9jjc9jg8OvQ8OvQ89jg89jo9YMmLJ0OP40OP40OP40OP40OP40OP40OP40OP44ND74ND74ND70OP4iCUjloxYMvQ4PvQ4Pjj0Pjj0Pjj0PvQ4PmLJiCUjlgw9jg89jg89jg89jg89jg89jg89jg89jg89jg8OvQ8OvQ89jg89jo9YMmLJ0OP40OP40OP44ND74ND7lFZSWolYMmLJ0OP40OP4lFZCj+NDj+NTWgk9jg89jg8OvQ8OvU9rJa2ViCUjloxYMvQ4PvQ4Pjj0Pjj0PqOVjFYiloxYMmLJ0OP40OP4rFayWgk9jg89jg89js9qJauV4ND74ND7rFZyWolYMmLJ0OP40OP4nFaCQ++DQ+9zWgk9jq9YsmLJ0uP40uP40uP40uP40uP40uP40uP40uP44tD74tD74tD70uP4iiUrlqxYsvQ4vvQ4vjj0vjj0vjj0vvQ4vmLJiiUrliw9ji89ji89ji89ji89ji89ji89ji89ji89ji8OvS8OvS89ji89jq9YsmLJ0uP40uP40uP44tD74tD70uP40uP4iiUrliw9ji89jm9pJfQ4vvQ4vqWV0OP40uP44tD74tD7tlbSWolYsmLJiiVLj+NLj+OLQ++LQ+/bWsloJWLJiiUrliw9ji89ju9oJaOV0OP40uP40uP4rlayWgkOvS8Ove9qJauViCUrliw9ji89ju9pJTj0vjj0vqeVnFYilqxYsvQ4vvQ4fvQ4fvQ4fvQ4fvQ4fvQ4fvQ4fjj0fjj0fjj0fvQ4fmLJiSUnlhw9jh89jh8OvR8OvR8OvR89jp9YcmLJiSVHj+NHj+NHj+NHj+NHj+NHj+NHj+NHj+NHj+OHQ++HQ+9Hj+NHj+MnlpxYcvQ4fvQ4fvQ4fjj0fjj0fvQ4fvQ4fmLJiSVHj+NHj+NHj+NHj+NHj+NXWgk9jh89jh8OvR8OvV9pJaWViCUnlpxYcvQ4fvQ4fjj0fjj0fq2VtFYilpxYcmLJ0eP40eP4jVYyWgk9jh89jh89jt9oJaOV4ND74dD7rVayWolYcmLJ0eP40eP4rVaCQ++HQ+93WslpJWLJiSVHj+NHj+N3Wgk9jh89jh89Tjx6nHj0OPFw6OPh0MfDoY9HjxMPlsSDJfFgSTx6nHj0OPFw6OPh0MfDoY9HjxMPlsSDJfFgSTx6nHj0OPHoceLR48Sjx4lHjxOPHicePU48epx4OPTxcOjj0ePEo8eJB0viwZJ49Djx6HHi0ePEw6GPh0Mfjx4nHj1OPFgSD5bEo8eJR48Tjx4nHj1OPHqcePQ48ehx4tHjxMOhj4dDH6+0ktJKSispraS0EnqcePQ48XDo4+HQx2utpLWS1kpaK2mthB4nHj1OvNZKWiuhx4lHjxOPHifeaCWjleDQx8OhjzdayWglo5WsVkKPE48eJ95qJTj08XDo461WslrJaiWrldDjxKPHiXdaCT1OPHqceKeV0OPEo8eJd/q6cejDcOjD6HHCxBITS0wsMXqcMHqcMBz6MBz6MBz6MHqcMLHExBITS4weJ4weJ4weJ4weJ4weJ4weJ4weJ4weJ4weJwyHPgyHPoweJ4weJ0wsMbHE6HHC6HHC6HHCcOjDcOjD6HHC6HHCxBITS4weJ4weJ4weJ4weJ4weJ4weJ4weJ4weJwyHPgyHPgyHPiy1ErHExBITS4weJ4weJwyHPgyHPqy0ktJKxBITS0wsMXqcMHqcsNZKWiuhxwmjxwmjxwlrrWS0Ehz6MBz6sNFKRisRS0wsMXqcMHqcsNFKcOjDcOjDVitZrUQsMbHE6HHC6HHCViuhxwmjxwk7rYQeJ4weJ+z0dePQh51WclqJWGJiiYslTo8TTo8TjkMfjkMfjkMfTo8TLpa4WOJiidPjhNPjhNPjhNPjhNPjhNPjhNPjhNPjhNPjhOPQh+PQh9PjhNPjhIslLpY4PU44PU44PU44Dn04Dn04PU44PU64WOJiidPjhNPjhNPjhNPjhNPjhNPjhNPjhNPjhOPQh+PQh+PQh9PjhIslLpa4WOL0OOH0OOE49OE49OGllZRWIpa4WOJiidPjhNPjhLdW0loJPU44PU44PU54ayWtleDQh+PQh7dWMlqJWOJiidPjhNPjhI9WgkMfjkMfPlrJaCViiYslTo8TTo8TvloJPU44PU74aiX0OOH0OOGnrxuHPvy0ktNKxBIXS1wscXqccHqccBz6CBz6CBz6CHqcCLEkxJIQS4IeJ4IeJ4IeJ4IeJ4IeJ4IeJ4IeJ4IeJ4IeJwKHPgKHPoIeJ4IeJ0IsCbEk6HEi6HEi6HEicOgjcOgj6HEi6HEixJIQS4IeJ4IeJ4IeJ4IeJ4IeJ4IeJ4IeJ4IeJwKHPgKHPgKHPoIeJ0IsCbEkxJKgx4mgx4nAoY/AoY9IraS0ErEkxJIQS4IeJ4IeJ6K0ktJK6HEi6HEi6HEiWitprQSHPgKHPqK1ktZKxJIQS4IeJ4IeJ2K0Ehz6CBz6iNFKRisRS0IsCXqcCHqciNVK6HEi6HEiViuhx4mgx4nAoY/AoY9YrWS1ErEkxJIQS4IeJ4IeJ+L0dePQR5xWclqJWJJiSYolSY8TSY8TSY8TSY8TSY8TSY8TSY8TSY8TSY8TiUMfiUMfSY8TSY8TKZakWJL0OJH0OJH0OJE49JE49JH0OJH0OJFiSYolSY8TSY8TSY8TSY8TSY8TSY8TSY8TSY8TiUMfiUMfiUMfSY8TKZakWJJiSdLjRNLjROLQR+LQR+LQR9LjRIolKZakWJL0OJH0OJGllZRWQo8TSY8TSY8TWVpJaSU49JE49JGtlbRWIpakWJL0OJH0OJGtleDQR+LQR45WMlqJWJJiSdLjRNLjRI5WQo8TSY8TOVoJPU4kPU4kDn0kDn3kaiWrlYglKZakWJL0OJH0OJGnrxuHPvK0ktNKxJIUS1IsSXqcSHqcKHqcKHqcKHqcKHqcKHqcKHqcKHqcKBz6KBz6KHqcKHqcKLGkxJKix4mix4mix4nCoY/CoY+ix4mix4kSS0osKXqcKHqcKHqcKHqcKHqcKHqcKHqcKHqcKBz6KBz6KBz6KHqcKLGkxJISS4oeJ4oeJwqHPgqHPgqHPooeJ0osKbGkxJKix4mix4mix4lKrYQeJ4oeJ4oeJ6q0ktJKcOijcOijSisprUQsKbGk6HGi6HGiWivBoY/CoY9qraS1ErGkxJKix4mix4karYQeJ4oeJ2q0EnqcKHqcKBz6KBz6qNVKVisRS0osKbGk6HGi6HGicOijcOijVis5rUQsKbGkxJKix4mix4k6reS0EnqcKHqcaHqcaHqcaHqcaBz6aBz6aHqcaHqcaLGkxZKmx4mmx4mmx4nGoY/GoY+mx4mmx4kWS1osaXqcaHqcaHqcaHqcaHqcaHqcaHqcaHqcaBz6aBz6aBz6aHqcaLGkxZIWS5oeJ5oeJxqHPhqHPhqHPpoeJ1osabGkxZKmx4mmx4mmx4mmx4mmx4mmx4mmx4lOraS0Ehz6aBz66NJKSisRS1osaXqcaHqc6NJKcOijceijWytprUQsabGk6XGi6XGiWyuhx4mmx4kerYQeJ5oeJxqHPhqHPnq0ktFKxJIWS1osaXqcaHqcaBz6aBz66NVKVisRS1osabGk6XGi6XGiTys5rYQeJ5oeJ5oeJ/q0ktNKcOhjcOhj6HFi6HFixJIRS4YeJ4YeJ4YeJwaHPgaHPoYeJ4YeJ0YsGbFk6HFi6HFi6HFi6HFi6HFi6HFi6HFi6HFicOhjcOhjcOhj6HFixJIRS0YsGXqcGHqcGBz6GBz6GBz6GHqcGLFkxJIRS4YeJ4YeJ4YeJ4YeJ4YeJ4YeJ4YeJ4YeJ4YeJwaHPgaHPia1ktJKxJIRS4YeJ4YeJ6a0Ehz6GBz6mNJKSisRS0YsGXqcGHqcmNZK6HFi6HFiWiuhx4mhx4nBoY/BoY8ZrWS0ErFkxJIRS4YeJ4YeJwaHPgaHPma1ktVKxJIRS0YsGXqcGHqcmNVKViuhx4mhx4mhx4k5reS0Ehz6GBz6mNNKTisRS1YsWXqcWHqcWHqcWBz6WBz6WHqcWHqcWLFkxZKlx4mlx4mlx4mlx4mlx4mlx4mlx4mlx4nFoY/FoY/FoY+lx4kVS1YsWbFk6XFi6XFicehjcehjcehj6XFixZIVS1YsWXqcWHqcWHqcWHqcWHqcWHqcWHqcWHqcWHqcWBz6WBz6WHqcWHqcWLFkxZKlx4mlx4ktrQSHPhaHPra0ktJKxJIVS5YeJ5YeJ7a1EnqcWHqc2NZK6HFi6XFicehjcehjWytprUQsWbFkxZKlx4mlx4nFoY/FoY8drWS0ErFkxZIVS5YeJ5YeJ3a1ktVK6HFi6XFi6XFiVys5rQSHPhaHPva0ktNKxJIVS5YeJ5YeJ5YeJw6HPg6HPo4eJ44eJ04sObHk6HHi6HHi6HHi6HHi6HHi6HHi6HHi6HHicOjjcOjjcOjj6HHixJITS04sOXqcOHqcOBz6OBz6OBz6OHqcOLHkxJITS44eJ44eJ44eJ44eJ44eJ44eJ44eJ44eJ44eJw6HPg6HPo4eJ44eJ04sObHk6HHi6HHi6HHicOjjcOjjSisprUQsObHk6HHi6HHiSiuhx4mjx4krrYQeJ44eJw6HPg6HPq61ktZKxJITS04sOXqcOHqcOBz6OBz6uNFKRisRS04sObHk6HHi6HHiVitZrYQeJ44eJ44eJ261ktVKcOjjcOjjVis5rUQsObHk6HHi6HHiTivBoY/DoY87rYQeJx8syQdL8tHj5KPHyUePk48eJx89Tj56nHz0OPnocfLh0OfDoc+HQ5+PHicfLMkHS/LBknz0OPnocfLh0OfDoc+HQ5+PHicfLMkHS/LBknz0OPnocfLR4+Sjx8lHj5OPHicfPU4+epx89Dj5cOjz4dDno8fJR4+TD5bkgyX56HHy0ePko8fJh0OfD4c+Hz1OPnqcfLAkX2ol9Dj56HHylVZCj5OPHidfaSX0OPnocfLh0OfDoc/XWklrJa2VtFbSWgk9Tj56nHw49Plw6PO1VjJayWglo5WMVkKPk48eJ99oJaOV0OPko8fJR4+Tb7WS1Upw6PPh0OdbrWS1ktVKViuhx8lHj5PvtBIc+nw49PlOKzmt5LSS00rocfLR46TR46TR46TR46TR46TR46TR46Th0Kfh0Kfh0KfR46SJJSaWmFhi9Dhp9DhpOPRpOPRpOPRp9DhpYomJJSaWGD1OGj1OGj1OGj1OGj1OGj1OGj1OGj1OGj1OGg59Gg59Gj1OGj1OmlhiYonR46TR46TR46Th0Kfh0KfR46TR46SJJSaWGD1OGj1OGj1OGj1OGj1OWmkl9Dhp9DhpOPRpOPRppZWUViKWmFhiYonR46TR46Th0Kfh0Ke1VtJaiVhiYomJJUaPk0aPkzZayWgl9Dhp9Dhp9Dhpo5WMVoJDn4ZDn7ZayWolYomJJUaPk0aPk7ZaCQ59Gg592mklp5WIJSaWGD1OGj1O2mkl9Dhp9Dhp9Djp9Djp9DjpOPTpOPTpOPTp9DjpYomLJS6WOD1OOj1OOg59Og59Og59Oj1OuljiYomLJU6Pk06Pk06Pk06Pk06Pk06Pk06Pk06Pk06Pk45Dn45Dn06Pk06Pky6WuFji9Djp9Djp9DjpOPTpOPTp9Djp9DjpYomLJU6Pk06Pk06Pk06Pk06Pk06Pk06Pk06Pk45Dn45Dn15aSWklYomLJS6WOD1OOj1OOg59Og59emslrZWIJS6WuFji9Djp9DjprZW0VkKPk06Pk06Pkz5ayWglOPTpOPTpo5WMViKWuFji9Djp9Djpq5Xg0Kfj0KevVrJaiVjiYonT46TT46SfVkKPk06Pk35aCT1OOj1O+unrxqHPwKHPoMfJEEtCLAmxJOhxMuhxMnDoM3DoM3DoM+hxMsSSEEtCLAl6nAx6nAx6nAx6nAx6nAx6nAx6nAx6nAx6nAwc+gwc+gx6nAx6nAyxJMSSoMfJoMfJoMfJwKHPwKHPoMfJoMfJEEtCLAl6nAx6nAx6nAx6nAx6nAx6nAx6nAx6nAwc+gwc+gwc+ozUSsSSEEtCLAl6nAx6nAwc+gwc+ozSSkorEUtCLAmxJOhxMuhxMloraa2EHieDHieDHiejtZLRSnDoM3DoM0YrGa1ELAmxJOhxMuhxMkYrwaHPwKHPWK1ktRKxJMSSoMfJoMfJWK2EHieDHifjtBJ6nAx6nIzT141Dn3FayWklYkmIJSmWJD1OJj1OJg59Jg59Jg59Jj1OpliSYkmKJUmPk0mPk0mPk0mPk0mPk0mPk0mPk0mPk0mPk4lDn4lDn0mPk0mPkymWpFiS9DiZ9DiZ9DiZOPSZOPSZ9DiZ9DiZYkmKJUmPk0mPk0mPk0mPk0mPk0mPk0mPk0mPk4lDn4lDn4lDn0mPkymWpFiSYknS42TS42Ti0Gfi0GeWVlJaiViSYkmKJUmPk0mPk9laSWsl9DiZ9DiZ9DiZrZW0VoJDn4lDn9layWglYkmKJUmPk0mPkzlaCQ59Jg595mglo5WIJSmWJD1OJj1O5mol9DiZ9DiZq5XQ42TS42Sevm4c+szTSk4rEUtSLEmxJOlxMulxMnHos3Dos3Dos+hxssSSEktKLCl6nCx6nCx6nCx6nCx6nCx6nCx6nCx6nCx6nCwc+iwc+ix6nCx6nCyxpMSSosfJosfJosfJwqHPwqHPosfJosfJEktKLCl6nCx6nCx6nCx6nCx6nCx6nCx6nCx6nCwc+iwc+iwc+ix6nCyxpMSSEkuKHieLHicLhz4Lhz4rtZLSSsSSEktKLCl6nCx6nKzSSkorocfJosfJosfJaq2ktRIc+iwc+qzWSlorEUtKLCl6nCx6nKzRSnDos3Dos0YrGa1ELCmxpOhxsuhxslYrocfJosfJWq2EHieLHicLhz4Lhz5rtZLVSsSSEktKLCl6nCx6nKzT141Dn3VayWklYkmLJS2WND1ONj1ONj1ONj1ONj1ONj1ONj1ONj1ONj1ONg59Ng59Nj1ONj1OtljSYknT42TT42TT42Tj0Gfj0GfT42TT42SLJS2WND1ONj1ONj1ONj1ONj1ONj1ONj1ONj1ONg59Ng59Ng59Nj1OtljSYkmLJU2Pk02Pk41Dn41Dn41Dn02Pky2WtFjSYknT42TT42SXVlJaCT1ONj1ONj1OdmklpZXg0Gfj0Ge3VtJaiVjSYknT42TT42S3VoJDn41Dnz1ayWglYkmLJU2Pk02Pkz1aCT1ONj1O9mgl9DjZ9DjZOPTZOPTZq5WsViKWtFjSYknT42TT42Sfvm4c+uzTSk4rEUtaLGmxpOlxsulxcuhxcuhxcuhxcuhxcuhxcuhxcuhxcnDoc3Doc+hxcuhxcsSSEUuGHieHHieHHicHhz4Hhz6HHieHHidHLBmxZOhxcuhxcuhxcuhxcuhxcuhxcuhxcuhxcnDoc3Doc3Doc+hxcsSSEUtGLBl6nBx6nBwc+hwc+hwc+hx6nByxZMSSEUuGHieHHieHHicntRJ6nBx6nBx6nJzSSkorwaHPwaHPKa2ktBKxZMSSocfJocfJaa0Ehz4Hhz6ntZLWSsSSEUuGHieHHidntBJ6nBx6nJzRSuhxcuhxcnDoc3Doc1YrWa1ELBmxZMSSocfJocfJwaHPwaHPWa3ktBKxZMSSEUuGHieHHifntJLTSuhxcuhxculxculxculxcnHoc3Hoc+lxculxcsWSFUuWHieXHieXHicXhz4Xhz6XHieXHidXLFmxZOlxculxculxculxculxculxculxculxcnHoc3Hoc3Hoc+lxcsWSFUtWLFl6nFx6nFwc+lwc+lwc+lx6nFyxZMWSFUuWHieXHieXHieXHieXHieXHieXHic3tZLSSnDoc3Hoc0srKa1ELFmxZOlxculxcksrwaHPxaHPba2ktRKxZMWSpcfJpcfJba2EHieXHid3tBJ6nFx6nFwc+lwc+tzRSkYrEUtWLFmxZOlxculxcnHoc3Hoc1crWa1ELFmxZMWSpcfJpcfJPa3ktBJ6nFx6nFx6nNzTSk4rwaHPw6HPo8fJo8fJE0tOLDl6nDx6nDx6nDwc+jwc+jx6nDx6nDyx5MSSo8fJo8fJo8fJo8fJo8fJo8fJo8fJo8fJw6HPw6HPw6HPo8fJE0tOLDmx5Ohx8uhx8nDo83Do83Do8+hx8sSSE0tOLDl6nDx6nDx6nDx6nDx6nDx6nDx6nDx6nDx6nDwc+jwc+rzUSkorEUtOLDl6nDx6nLzSSnDo83Do80orKa1ELDmx5Ohx8uhx8lorocfJo8fJa62EHiePHicPhz4Phz5vtJLRSsSSE0tOLDl6nDx6nDwc+jwc+rzVSlYrEUtOLDmx5Ohx8uhx8lYrWa2EHiePHiePHifvtJLTSnDo83Do804rOa0EltSDJfXocerR49Sjx6mHQ18Ph74ePU49epx6sKQeLKlHj1OPHqcePU49epx69Dj16HHq0ePUo8eph0NfD4e+Hg59PXqcerCkHiypB0vq0ePUo8eph0NfD4e+Hg59PXqcerCkHiypB0vq0ePUo8epR49Tjx6nHj1OPXqcevQ49ehx6tHj1MOhr4dDX48epx49Tj1YUg+W1KPHqUePU6+0Ehz6ejj09UorKa2ktJLSSuhx6tHj1GuthB6nHj1OvdZK6HHq0ePUw6Gvh0Nfr7WS1kpGKxmtZLQSepx69Dj1cOjr4dDXG61ktJLRSlYrWa2EHqcePU691UpWK6HHqUePU48ep95qJaeV4NDXw6Gvd1rJaSWnlZxWQo9Tjx6nHj1OGQ59GQ59GT1OGT1OmVhiYonR45TR45TR45TR45TR45TR45TR45TR45Th0Jfh0Jfh0JfR45SJJSaWmFhi9Dhl9DhlOPRlOPRlOPRl9DhlYomJJSaWGD1OGT1OGT1OGT1OGT1OGT1OGT1OGT1OGT1OGQ59GQ59GT1OGT1OmVhiYonR45TR45TR45Th0Jfh0JeVVlJaiVhiYonR45TR45SVVkKPU0aPU1ZaCT1OGT1OGQ59GQ59WWslrZWIJSaWmFhi9Dhl9DhlOPRlOPRlo5WMViKWmFhiYonR45TR45StVrJaCT1OGT1OGT1O2Wolq5Xg0Jfh0JetVnJaiVhiYonR45TR45SdVoJDX4ZDX3ZaCT1OuVjiYonT45TT45TT45TT45TT45TT45TT45TT45Tj0Jfj0Jfj0JfT45SLJS6WuFji9Djl9DjlOPTlOPTlOPTl9DjlYomLJS6WOD1OOT1OOT1OOT1OOT1OOT1OOT1OOT1OOT1OOQ59OQ59OT1OOT1OuVjiYonT45TT45TT45Tj0Jfj0JfT45TT45SLJS6WOD1OOT1OeWkl9Djl9DjlpZXQ45TT45Tj0Jfj0Je3VtJaiVjiYomLJU6PU06PU45DX45DX95ayWglYomLJS6WOD1OOT1O+Wglo5XQ45TT45TT45SvVrJaCQ59OQ59+Wolq5WIJS6WOD1OOT1O+WklOPTlOPTlp5WcViKWuFji9Djl9DgV9DgV9DgV9DgV9DgV9DgV9DgVOPQVOPQVOPQV9DgVYkmIJSGWBD1OBT1OBQ59BQ59BQ59BT1OhVgSYkmIJUGPU0GPU0GPU0GPU0GPU0GPU0GPU0GPU0GPU4FDX4FDX0GPU0GPUyGWhFgS9DgV9DgV9DgVOPQVOPQV9DgV9DgVYkmIJUGPU0GPU0GPU0GPU0GPU1FaCT1OBT1OBQ59BQ59RWklpZWIJSGWhFgS9DgV9DgVOPQVOPQVrZW0ViKWhFgSYknQ41TQ41SMVjJaCT1OBT1OBT1OxWglo5Xg0Ffg0FesVrJaiVgSYknQ41TQ41SsVoJDX4FDX3FayWklYkmIJUGPU0GPU3FaCT1OBT1OBT1OJT1OJT1OJQ59JQ59JQ59JT1OpViSYkmKJUmPU0mPU4lDX4lDX4lDX0mPUymWpFiSYknS41TS41TS41TS41TS41TS41TS41TS41TS41Ti0Ffi0FfS41TS41SKJSmWJD1OJT1OJT1OJQ59JQ59JT1OJT1OpViSYknS41TS41TS41TS41TS41TS41TS41TS41Ti0Ffi0FeWVlJaiViSYkmKJUmPU0mPU4lDX4lDX9laSWslYkmKJSmWJD1OJT1OZWslrZXQ41TS41TS41SOVjJaCQ59JQ595Wglo5WIJSmWJD1OJT1O5WolOPSVOPSVq5WsViKWpFiS9DiV9DiVp5XQ41TS41SeVkKPU0mPU3n6unHoq3Doq+hxqsSSEktKLCl6nCp6nCoc+ioc+ioc+ip6nCqxpMSSEkuKHqeKHqeKHqeKHqeKHqeKHqeKHqeKHqeKHqcKh74Kh76KHqeKHqdKLCmxpOhxquhxquhxqnDoq3Doq+hxquhxqsSSEkuKHqeKHqeKHqeKHqeKHqeKHqeKHqeKHqcKh74Kh74Kh74qtRKxpMSSEkuKHqeKHqcKh74Kh76qtJLSSsSSEktKLCl6nCp6nKrWSloroceposeposepaq1ktBIc+ioc+qrRSkYrEUtKLCl6nCp6nKrRSnDoq3Doq1YrWa1ELCmxpOhxquhxqlYroceposepOq2EHqeKHqfq9HXj0FedVnJaiVhSYkmLJU2PU02PU41DX41DX41DX02PUy2WtFjSYknT41TT41TT41TT41TT41TT41TT41TT41TT41Tj0Ffj0FfT41TT41SLJS2WND1ONT1ONT1ONQ59NQ59NT1ONT1OtVjSYknT41TT41TT41TT41TT41TT41TT41TT41Tj0Ffj0Ffj0FfT41SLJS2WtFjS9DjV9DjVOPTVOPTVpZWUViKWtFjSYknT41TT41S3VtJaCT1ONT1ONT1OdWslrZXg0Ffj0Fe3VjJaiVjSYknT41TT41SPVoJDX41DXz1ayWglYkmLJU2PU02PU71aCT1ONT1O9Wol9DjV9DjVp68bh776tJLTSsSSFktaLGl6nGp6nGoc+hoc+hoc+hp6nBqxZMSSEUuGHqeGHqeGHqeGHqeGHqeGHqeGHqeGHqeGHqcGh74Gh76GHqeGHqdGLBmxZOhxauhxauhxanDoa3Doa+hxauhxasSSEUuGHqeGHqeGHqeGHqeGHqeGHqeGHqeGHqcGh74Gh74Gh76GHqdGLBmxZMSSocepocepwaGvwaGvSa2ktBKxZMSSEUuGHqeGHqemtJLSSuhxauhxauhxaloraa0Eh74Gh76mtZLWSsSSEUuGHqeGHqdmtBIc+hoc+prRSkYrEUtGLBl6nBp6nJrVSuhxauhxalYrocepocepwaGvwaGvWa1ktRKxZMSSEUuGHqeGHqfm9HXj0NecVnJaiViyYsmKJUuPU0uPU0uPU0uPU0uPU0uPU0uPU0uPU0uPU4tDX4tDX0uPU0uPUyuWrFiy9Di19Di19Di1OPS1OPS19Di19Di1YsmKJUuPU0uPU0uPU0uPU0uPU0uPU0uPU0uPU4tDX4tDX4tDX0uPUyuWrFiyYsnS49TS49Ti0Nfi0Nfi0NfS49SKJSuWrFiy9Di19Di1pZWUVkKPU0uPU0uPU1taSWklOPS1OPS1rZW0ViKWrFiy9Di19Di1rZXg0Nfi0NeOVjJaiViyYsnS49TS49SOVkKPU0uPUztaCT1OLT1OLQ59LQ597Wolq5WIJSuWrFiy9Di19Di1p68bh772tJLTSsSSFUtWLFl6nFp6nDp6nDp6nDp6nDp6nDp6nDp6nDp6nDoc+joc+jp6nDp6nDqx5MSSo8epo8epo8epw6Gvw6Gvo8epo8epE0tOLDl6nDp6nDp6nDp6nDp6nDp6nDp6nDp6nDoc+joc+joc+jp6nDqx5MSSE0uOHqeOHqcOh74Oh74Oh76OHqdOLDmx5MSSo8epo8epo8epS62EHqeOHqeOHqeutJLSSnDo63Do60orKa1ELDmx5Ohx6uhx6lorwaGvw6Gva62ktRKx5MSSo8epo8epG62EHqeOHqdutBJ6nDp6nDoc+joc+rrVSlYrEUtOLDmx5Ohx6uhx6nDo63Do61YrOa1ELDmx5MSSo8epo8epO63ktBJ6nDp6nH70OP3ocfrR4/TDoe+HQ9+PHqcfPU4/WNIPlvSjx+lHj9OPHqcfDn0/HPp+9Dj96HH6wZJ+sKQfPU4/epx+9Dj96HH60eP0o8fpR4/Tjx6nHw59Pxz6fjj0/ehx+sGSfrCkHyzpR4/Tjx6nHw59Pxz6fjj0/ehx+sGSfrCkHyzpR4/Tjx6nHz1OP3qcfvQ4/ehx+tHj9EutpLQSHPp+OPT9SispraS0ktJK6HH60eP0K60Eh74fDn2/1kpaK2mtpLUSepx+9Dj9Wiuhx+lHj9NvtBJ6nH70OP1w6Pvh0PcbrWS0ktFKRitZrYQepx89Tj8c+n449P1WK1mtZLWS1UpWK6HH6UeP0++0ktNK6HH60eP0o8fpd1rJaSU49G049G30OG30OG1iiYklRo/TRo/TRo/ThkPfhkPfRo/TRo/TJpaYWGL0OG30OG30OG30OG30OG30OG30OG30OG049G049G049G30OG1iiYklJpYYPU4bPU4bDn0bDn0bDn0bPU6bWGJiiYklRo/TRo/TRo/TRo/TRo/TRo/TRo/TRo/TRo/ThkPfhkPfllpJaSViiYklRo/TRo/TVloJDn0bDn1baSWllYglJpYYPU4bPU5bayX0OG30OG2tldDjtNHjtOHQt+HQt41WMlqJWGJiiYklRo/TRo/ThkPfhkPftlrJaiViiYklJpYYPU4bPU7baiWrldDjtNHjtNHjtJ1WcloJDn0bDn3baSWnlYglLpY4PU47PU47PU47Dn07Dn07PU47PU67WOJiidPjtNPjtNPjtNPjtNPjtNPjtNPjtNPjtOPQt+PQt+PQt9PjtIslLpa4WOL0OO30OO049O049O049O30OO1iiYslLpY4PU47PU47PU47PU47PU47PU47PU47PU47PU47Dn07Dn07PU47PU67WOJiidPjtNPjtJdWgkPfjkPfXlpJaSViiYslTo/TTo/T3loJPU47PU57ayX0OO30OO049O049O2tlbRWIpa4WOJiidPjtNPjtOPQt+PQt49WMlqJWOJiiYslTo/TTo/TvlrJaiX0OO30OO30OO2rlZxWgkPfjkPfflrJaSViiYslTo/TTo/TTo/TgUPfgUPfQY/TQY/TIZaEWBL0OB30OB30OB30OB30OB30OB30OB30OB049B049B049B30OB1iSYglIZYEPU4HPU4HDn0HDn0HDn0HPU6HWBJiSYglQY/TQY/TQY/TQY/TQY/TQY/TQY/TQY/TQY/TgUPfgUPfQY/TQY/TIZaEWBL0OB30OB30OB049B049B2llZRWIpaEWBL0OB30OB2lldDjdNDjdJRWQo/TQY/TgUPfgUPf0VpJayViSYglIZYEPU4HPU4HDn0HDn3HaCWjlYglIZaEWBL0OB30OB2rlaxWQo/TQY/TQY/TsVrJaiU49B049B2rlZxWIpaEWBL0OB30OB2nleDQd+DQd5xWQo/TKZakWJL0OJ30OJ30OJ30OJ30OJ30OJ30OJ30OJ049J049J049J30OJ1iSYolKZYkPU4nPU4nDn0nDn0nDn0nPU6nWJJiSYolSY/TSY/TSY/TSY/TSY/TSY/TSY/TSY/TSY/TiUPfiUPfSY/TSY/TKZakWJL0OJ30OJ30OJ049J049J30OJ30OJ1iSYolSY/TSY/TWVoJPU4nPU5naSX0OJ30OJ049J049J2tlbRWIpakWJJiSdLjdNLjdOLQd+LQd7ZWMlqJWJJiSYolSY/TSY/TOVrJaCX0OJ30OJ30OJ2rlaxWgkPfiUPfuVrJaiViSYolSY/TSY/TeVoJDn0nDn3naSWnlYglKZYkPU4nPU4XPU4XPU4XPU4XPU4XPU4XPU4XDn0XDn0XDn0XPU6XWFJiSYklRY/TRY/ThUPfhUPfhUPfRY/TJZaUWFJiSdHjdNHjdNHjdNHjdNHjdNHjdNHjdNHjdNHjdOHQd+HQd9HjdNHjdIklJZYUPU4XPU4XPU4XDn0XDn0XPU4XPU6XWFJiSdHjdNHjdNHjdNHjdNHjdJVWQo/TRY/ThUPfhUPfVVpJaSViSYklJZYUPU4XPU4XDn0XDn1XayWtlYglJZaUWFL0OF30OF2jlYxWQo/TRY/TRY/TNVrJaCU49F049F2rlaxWIpaUWFL0OF30OF2rleDQd+HQd51WclqJWFJiSdHjdNHjdJ1WQo/TRY/TRY/TTY/TTY/TjUPfjUPfjUPfTY/TLZa0WNJiSdPjdNPjdOPQd+PQd+PQd9PjdIslLZa0WNL0ON30ON30ON30ON30ON30ON30ON30ON30ON049N049N30ON30ON1iSYslTY/TTY/TTY/TjUPfjUPfTY/TTY/TLZa0WNL0ON30ON30ON30ON30ON30ON30ON30ON049N049N2llZRWIpa0WNJiSdPjdNPjdOPQd+PQd7dW0lqJWNJiSYslTY/TTY/T3VpJayX0ON30ON30ON2jlYxWgkPfjUPfPVrJaCViSYslTY/TTY/TvVoJDn03Dn33aiWrlYglLZY0PU43PU73aSX0ON30ON2nldDjdNPjdJ++bhz6Hhz6HnqcHrFkxJIRS4Yep4cepweHvgeHvgeHvocep0csGbFkxJKhx+mhx+mhx+mhx+mhx+mhx+mhx+mhx+mhx+nBoe/Boe+hx+mhx+kRS0YsGXqcHnqcHnqcHhz6Hhz6HnqcHnqcHrFkxJKhx+mhx+mhx+mhx+mhx+mhx+mhx+mhx+nBoe/Boe/Boe9JrUQsGbFkxJKhx+mhx+nBoe/Boe8praS0ErFkxJIRS4Yep4cep6e1ktZK6HF66HF66HF6WisZrQSHvgeHvme0ktFKxJIRS4Yep4cep2e0Ehz6Hhz6ntVKVisRS0YsGXqcHnqcntVK6HF66HF6Tiuhx+mhx+k5fd049D2nlZxWIpaMWLJiydLj9NLj9OLQ9+LQ9+LQ99Lj9IolK5asWLL0OL30OL30OL30OL30OL30OL30OL30OL30OL049L049L30OL30OL1iyYolS4/TS4/TS4/Ti0Pfi0PfS4/TS4/TK5asWLL0OL30OL30OL30OL30OL30OL30OL30OL049L049L049L30OL1iyYolK5YsPU4vPU4vDn0vDn1vaSWllYglK5asWLL0OL30OL2tlbRWQo/TS4/TS4/T21pJayU49L049L2tlYxWIpasWLL0OL30OL2jleDQ9+LQ945WMlqJWLJiydLj9NLj9K5WQo/TS4/Tu1oJPU4vPU7v6evGoe89reS0ErFkxZIVS5Yep5cepxeHvg+Hvg+Hvo8ep08sObHkxJKjx+mjx+mjx+mjx+mjx+mjx+mjx+mjx+mjx+nDoe/Doe+jx+mjx+kTS04sOXqcPnqcPnqcPhz6Phz6PnqcPnqcPrHkxJKjx+mjx+mjx+mjx+mjx+mjx+mjx+mjx+nDoe/Doe/Doe+jx+kTS04sObHk6HH66HH6cOj7cOj7UisprUQsObHkxJKjx+mjx+krraS0EnqcPnqcPnqcvtZKWivBoe/Doe9rraS1ErHkxJKjx+mjx+kbrQSHvg+Hvm+0ktFKxJITS44ep48ep2+1EnqcPnqcvtVK6HH66HH6cOj7cOj7VitZrUQsObHkxJKjx+mjx+k7fd049H2nlZxWAkvmwZJ5sGQePc48epx59Djz6HHm0ePMo8eZR48zjx5nHj3OPBz6eTj08+hx5tHjzIMl82DJPHqcefQ48+hx5uHQz8Ohn0ePM48eZx4smQdL5tHjzKPHmUePM48eZx49zjx6nHn0OPPocebh0M/DoZ+HQz+PHmceLJkHS+bBknn0OPPocebh0M/DoZ+HQz+PHmceLJkHS+alVkKPM48eZ15pJaWV0OPMo8eZR48zr7SS0kpw6Ofh0M9rraS1ktZKWiuhx5lHjzOvtRIc+nk49PNGKxmtZLSS0UrocebR48wbrYQeZx49zrzRSuhx5tHjzMOhn4dDP2+1ktVKVitZrWS1EnqcefQ4805fNw79vNNKTis5reS0ktNK6HHm0eOM0eOM0eOM0eOM0eOM0eOM0eOM0eOM4dCP4dCP0eOM0eOMiSUmlhg9zhg9zhg9zhgO/RgO/Rg9zhg9zphYYmKJ0eOM0eOM0eOM0eOM0eOM0eOM0eOM0eOM4dCP4dCP4dCP0eOMiSUmlphYYvQ4Y/Q4Yzj0Yzj0Yzj0Y/Q4Y2KJiSUmlhg9zhg9zhg9zlhqJfQ4Y/Q4Y/Q4Y6WVlFaCQz+GQz9WWklpJWKJiSVGjzNGjzPWWgkO/RgO/VhrJa2ViCUmlhg9zhg9zthoJfQ4Y/Q4Y6OV0OOM0eOM4dCP4dCPrVayWolYYmKJiSVGjzNGjzOGQz+GQz+2WslpJWKJiSUmlhg9zhg9zthpJaeV0OOM0eOM0+OM0+OM0+OM49CP49CP0+OM0+OMiyUuljg9zjg9zjg9zjgO/TgO/Tg9zjg9zrhY4mKJ0+OM0+OM0+OM0+OM0+OM0+OM0+OM0+OM49CP49CP49CP0+OMiyUulrhY4vQ44/Q44zj04zj04zj04/Q442KJiyUuljg9zjg9zjg9zjg9zjg9zjg9zjg9znhqJaWV4NCP49CPl1ZSWolY4mKJ0+OM0+OMl1aCQz+OQz/eWklrJWKJiyVOjzNOjzPeWgk9zjg9zvhoJfQ44/Q44zj04zj046OVjFYilrhY4mKJ0+OM0+OM49CP49CPr1ayWolY4mKJiyVOjzNOjzN+WslpJfQ44/Q44/Q446eVnFaCQz+BQz9BjzNBjzMhloRYEvQ4E/Q4E/Q4Ezj0Ezj0E/Q4E/Q4E2JJiCVBjzNBjzNBjzNBjzNBjzNBjzNBjzNBjzOBQz+BQz+BQz9BjzMhloRYEmJJ0ONM0ONM4NBP4NBP4NBP0ONMiCUhloRYEvQ4E/Q4E/Q4E/Q4E/Q4E/Q4E/Q4E/Q4E/Q4Ezj0Ezj0E6mVlFYiloRYEvQ4E/Q4E6WV4NBP4NBPlFZSWolYEmJJ0ONM0ONMtFZCjzNBjzPRWgk9zgQ9zgQO/QQO/cRoJaOViCUhloRYEvQ4E/Q4Ezj0Ezj0E6uVrFYiloRYEmJJ0ONM0ONMrFayWgk9zgQ9zgQ9zsRpJaeV4NBP4NBPnFZyWolYkmJJ0uNM0uNM0uNM4tBP4tBP0uNM0uNMiiUpliQ9ziQ9ziQ9ziQ9ziQ9ziQ9ziQ9ziQ9ziQO/SQO/SQO/SQ9zqRYkmJJiiVJjzNJjzOJQz+JQz+JQz9JjzMplqRYkmJJ0uNM0uNM0uNM0uNM0uNM0uNM0uNM0uNM0uNM4tBP4tBP0uNM0uNMiiUpliQ9ziQ9zmRpJTj0kzj0k6WVlFYilqRYkvQ4k/Q4k62V0ONM0uNMtlZCjzNJjzOJQz+JQz/ZWklrJWJJiiUpliQ9ziQ9ziQO/SQO/eRoJaOViCUplqRYkvQ4k/Q4k6uVrFZCjzNJjzNJjzO5WslpJTj0kzj0k6eVnFYilqRYkvQ4k/Q4k/Q4Uzj0Uzj0U/Q4U/Q4U2JJiSVFjzNFjzNFjzNFjzNFjzNFjzNFjzNFjzOFQz+FQz+FQz9FjzMllpRYUmJJ0eNM0eNM4dBP4dBP4dBP0eNMiSUllpRYUvQ4U/Q4U/Q4U/Q4U/Q4U/Q4U/Q4U/Q4U/Q4Uzj0Uzj0U/Q4U/Q4U2JJiSVFjzNFjzNFjzOFQz+FQz9VWklpJWJJiSVFjzNFjzNVWgk9zhQ9zlRpJfQ4U/Q4Uzj0Uzj0U62VtFYilpRYUmJJ0eNM0eNM4dBP4dBPjVYyWolYUmJJiSVFjzNFjzO1WslqJfQ4U/Q4U/Q4U6uVrFaCQz+FQz+1WslpJWJJiSVFjzNFjzN1WgkO/RQO/dRpJfQ402JJiyVNjzNNjzNNjzNNjzNNjzNNjzNNjzNNjzONQz+NQz+NQz9NjzMtlrRY0mJJ0+NM0+NM49BP49BP49BP0+NMiyUtlrRY0vQ40/Q40/Q40/Q40/Q40/Q40/Q40/Q40/Q40zj00zj00/Q40/Q402JJiyVNjzNNjzNNjzONQz+NQz9NjzNNjzMtlrRY0vQ40/Q406WV0ONM0+NMl1ZCjzNNjzONQz+NQz/dWklrJWJJiyUtljQ9zjQ9zjQO/TQO/XRrJaOViCUtlrRY0vQ40/Q406OVjFZCjzNNjzNNjzO9WslqJTj00zj006uVrFYilrRY0vQ40/Q406eV4NBP49BPn1ZyWolY0mJJ0+NM0+PM0OPM0OPM0OPM0OPM0OPM0OPM4NDP4NDP4NDP0OPMiCUjloxYMvQ4M/Q4Mzj0Mzj0Mzj0M/Q4M2LJiCUjlgw9zgw9zgw9zgw9zgw9zgw9zgw9zgw9zgw9zgwO/QwO/Qw9zgw9zoxYMmLJ0OPM0OPM0OPM4NDP4NDP0OPM0OPMiCUjlgw9zgw9zgw9zgw9zgw9zkxpJfQ4M/Q4Mzj0Mzj0M6WVlFYiloxYMmLJ0OPM0OPM4NDP4NDPtFbSWolYMmLJiCVDjzNDjzMzWsloJfQ4M/Q4M/Q4M6OVjFaCQz+DQz+zWslqJWLJiCVDjzNDjzOzWgkO/QwO/cxpJaeViCUjlgw9zgw9zsxpJfQ4M/Q4M/Q4s/Q4s/Q4szj0szj0szj0s/Q4s2LJiiUrliw9ziw9ziwO/SwO/SwO/Sw9zqxYsmLJiiVLjzNLjzNLjzNLjzNLjzNLjzNLjzNLjzNLjzOLQz+LQz9LjzNLjzMrlqxYsvQ4s/Q4s/Q4szj0szj0s/Q4s/Q4s2LJiiVLjzNLjzNLjzNLjzNLjzNLjzNLjzNLjzOLQz+LQz9bWklpJWLJiiUrliw9ziw9ziwO/SwO/WxrJa2ViCUrlqxYsvQ4s/Q4s62VtFZCjzNLjzNLjzM7WsloJTj0szj0s6OVjFYilqxYsvQ4s/Q4s6uV4NDP4tDPrlayWolYsmLJ0uPM0uPMnlZCjzNLjzN7Wgk9ziw9zuzp68ahn8Ohn6PHmRNLTiw5seToceboceZw6Odw6Odw6OfocebEkhNLTiw5epw5epw5epw5epw5epw5epw5epw5epw5epw5HPo5HPo5epw5epw5seTEkqPHmaPHmaPHmcOhn8Ohn6PHmaPHmcOhn/+8179zdfIb8J/3+neaTl4K/3mvf6f+3XDo53Do53Do53Do53Do53DoR97ryHsdea9zOPRzOPRzOPRzpZXg0M/h0M/h0M/h0M/h0M/h0M/h0M/h0M/h0M9/3ut//wP9/13yd/5W8t//QP//f+P8nf/+q/33f2U/lPxdwZVc//4r/fd/zg8jf9dwLde//yr//Tf/Q8h//73/CPJ3ORf8+M91/TtLp5axWsZqGatlnJZxWsZpGadlnJZxWsZpGXjzc3jz83/X9f/nynVdua778Ob34c3vw5vfhze/jwZnH978Prz5fXjz+2hw9r//jNf77/y+6H148/vw5vfR4Kxc13148/vw5vfhze/Dm9+HN78Pb34f3vzKdV25rvvw5vfhze/Dm9+HN78Pb34f3vw+vPl9ePP78Ob34c3vw5vfhze/cl1XruvKdd2HN78Pb34f3vw++LEPb34f3vzKdV25rivXdV9pJaWVlFZSWgne/D68+X148/tKK8Gb34c3vw9vfh/e/L7WSnBdV67rPrz5fa2VtFbSWgne/D68+X2jleC6rlzXfaOVjFYyWsloJXjz+/Dm961Wgje/D29+32olePP78OZXruvKdV25rvtWKzmt5LSS00rw5vfhza9c15XrunJd951Wgje/JpaYWGJ482t482t482t482t482t482t482t482t48yvXdeW6ruHNr+HNr+HNr4klhje/hje/hje/cl1Xrusa3vwa3vyaWGJiieHNr+HNr+HNr+HNr+HNr+HNr+HNr+HNr1zXleu6cl3X8ObXxBITS0wsMbz5Nbz5leu6cl1Xrusa3vyaWGJiiYklhje/hje/VlpJaSV482t482t482ullZRWguu6cl3XWitprUQsMbHE8ObX8ObXWivBdV25rmujlYxWIpaYWGJ482t482ujleDNr+HNr41Wgje/hje/cl1XruvKdV1brUQsMbHExBLDm1/Dm1+5rivXdeW6rp1WIpaYWGJiieHNr+HNr+PNr+PNr+PNr+PNr+PNr+PNr+PNr1zXleu6jje/jje/Lpa4WOJ48+t48+t48yvXdeW6ruPNr+PNr4slLpY43vw63vw63vw63vw63vw63vw63vw63vzKdV25rivXdR1vfl0scbHExRLHm1/Hm1+5rivXdeW6ruPNr4slLpa4WOJ48+t48+t48+upleDNr+PNr+PNr5dWUloJruvKdV0vraS0ErHExRLHm1/Hm19vrQTXdeW6rrdW0lqJWOJiiePNr+PNr49Wgje/jje/PloJ3vw63vzKdV25rivXdX21ErHExRIXSxxvfh1vfuW6rlzXleu6flqJWOJiiYsljje/jje/flrJaSV48+t48xt48xt48xt48yvXdeW6buDNb+DNb4glIZYE3vwG3vwG3vzKdV25rht48xt48xtiSYglgTe/gTe/gTe/gTe/gTe/gTe/gTe/gTe/cl1XruvKdd3Am98QS0IsCbEk8OY38OZXruvKdV25rht48xtiSYglIZYE3vwG3vwG3vwG3vwG3vwG3vwG3vxGaiWlleC6rlzXjdJKSisRS0IsCbz5Dbz5jdJKcF1XrutGayWtlYglIZYE3vwG3vxGayV48xt48xujleDNb+DNr1zXleu6cl03RisRS0IsCbEk8OY38OZXruvKdV25rhurlYglIZaEWBJ48xt48xunlZxWgje/gTe/gTe/cVrJaSW4rivXdRNvfhNvflMsSbEk8eY38eY38eZXruvKdd3Em9/Em98US1IsSbz5Tbz5Tbz5Tbz5Tbz5Tbz5Tbz5Tbz5leu6cl1Xrusm3vymWJJiSYoliTe/iTe/cl1XruvKdd3Em98US1IsSbEk8eY38eY38eY38eY38eY38eY38eY38eY38eZX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cS7pcS7pcS7pcS5x6C9x6C9x6C/pcS7FkhRLUixJepxLepxLHPpLHPpLHPpLepxLsSTFkhRLkh7nkh7nkh7nMrUSepxLepxLepzL0kpKK8Ghv8ShvyytpLQSsSTFkqTHuaTHuWytBIf+Eof+srWS1krEkhRLkh7nkh7ncrQSepxLepzL0UrocS7pcS5x6C9x6C9XK1mtRCxJsSTFkqTHuaTHucShv8Shv1yt5LQSsSTFkhRLkh7nkh7n8rSS00rocS7pca7oca7oca7oca5w6K9w6K/oca7oca7EkhJLih7nih7nih7nCof+Cof+ih7nih7nSiwpsaToca7oca7oca7oca7oca7oca7oca7oca5w6K9w6K9w6K/oca7EkhJLSiwpepwrepwrHPorHPorHPorepwrsaTEkhJLih7nih7nih7nih7nih7nih7nih7nKrWS0kpw6K9w6K9KKymtRCwpsaToca7oca5KK8Ghv8Khv2qtpLUSsaTEkqLHuaLHuWqthB7nih7narQSepwrepwrHPorHPqr0UpGKxFLSiwpsaToca7oca5w6K9w6K9WK1mtRCwpsaTEkqLHuaLHuTqt5LQSepwrepwrepyr00pOK8Ghv8ahv6bHuabHuRZLWixpepxrepxrepxrHPprHPprepxrepxrsaTFkqbHuabHuabHuabHuabHuabHuabHuabHucahv8ahv8ahv6bHuRZLWixpsaTpca7pca5x6K9x6K9x6K/pca7FkhZLWixpepxrepxrepxrepxrepxrepxrepxrepxrepxrHPprHPrr1EpKKxFLWixpepxrepzr0kpw6K9x6K9LKymtRCxpsaTpca7pca5bK6HHuabHuW6thB7nmh7nGof+Gof+erSS0UrEkhZLWixpepxrepxrHPprHPrr1UpWKxFLWixpsaTpca7pca5XK1mthB7nmh7nmh7n+rSS00pw6K9x6K9PKzmtRCwZsWTocW7ocW7ocW5w6G9w6G/ocW7ocW7EkhFLhh7nhh7nhh7nhh7nhh7nhh7nhh7nhh7nBof+Bof+Bof+hh7nRiwZsWTEkqHHuaHHucGhv8Ghv8Ghv6HHuRFLRiwZsWTocW7ocW7ocW7ocW7ocW7ocW7ocW7ocW7ocW5w6G9w6G/ocW7ocW7EkhFLhh7nhh7nprQSHPobHPqb0kpKKxFL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LCmxpMSSosfxosfxwqH3wqH3aq2ktRKxpMSSEkuKHseLHsertZLWSuhxvOhxvOhxvEYrGa0Eh94Lh95rtJLRSsSSEkuKHseLHsdrtRIcei8ceq/VSlYrEUtKLCl6HC96HK/TSuhxvOhxvE4rocfxosfxOn3dOPTeOPTe9DjeYkmLJS2WND2ONz2ONw69Nw69Nw69Nz2Ot1jSYkmLJU2P402P402P402P402P402P402P402P402P441D741D702P402P4y2WtFjS9Dje9Dje9DjeOPTeOPTe9Dje9DjeYkmLJU2P402P402P402P402P402P402P402P441D741D741D751aiVjSYkmLJU2P402P441D741D711aSWklYkmLJS2WND2ONz2Od2slrZXQ43jT43jT43i3VjJaCQ69Nw6992glo5WIJS2WND2ONz2O92glOPTeOPTeq5WsViKWtFjS9Dje9Djeq5XQ43jT43ifVkKP402P4336unHovU8rOa1ELGmxZMSSocfxocfxwaH3waH3waH3ocfxEUtGLBmxZOhxfOhxfOhxfOhxfOhxfOhxfOhxfOhxfOhxfHDofXDofehxfOhxfMSSEUuGHseHHseHHscHh94Hh96HHseHHsdHLBmxZOhxfOhxfOhxfOhxfOhxfOhxfOhxfOhxfHDofXDofXDofehxfMSSEUtGLBl6HB96HB8ceh8cep/SSkorEUtGLBmxZOhxfOhxfForaa2EHseHHseHHsentZLWSnDofXDofVorGa1ELBmxZOhxfOhxfEYrwaH3waH3Ga1ktBKxZMSSocfxocfxWa2EHseHHsdntRJ6HB96HJ/T141D73NayWklYsmIJSOWDD2ODz2ODw69Lw69Lw69Lz2Or1iyYsmKJUuP40uP40uP40uP40uP40uP40uP40uP40uP44tD74tD70uP40uP4yuWrFiy9Di+9Di+9Di+OPS+OPS+9Di+9Di+YsmKJUuP40uP40uP40uP40uP40uP40uP40uP44tD74tD74tD70uP4yuWrFiyYsnS4/jS4/ji0Pvi0PumVlJaiViyYsmKJUuP40uP41taSWkl9Di+9Di+9Di+rZW0VoJD74tD79taSWslYsmKJUuP40uP4ztaCQ69Lw6972glo5WIJSuWLD2OLz2O72ol9Di+9Di+q5XQ4/jS4/ji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Q+/Bht6jlZJRStQloS4JdUngcTzwOB6jlIxSgsfxwON44HE8VilZpYQNvQcbeo9VSlYpUZeEuiTwOB54HI9TStjQe7Ch9zil5JQSdUmoSwKP44HH8cTjeOJxPPE4nngcTzyOJx7Hkw29Jxt6Tzb0nngcT3VJqktSXZJ4HE88jicbek829J5s6D3xOJ7qklSXpLok8TieeBxPPI4nHscTj+OJx/HE43jicTzxOJ5s6D3Z0HvicTzxOJ7qklSXJB7HE4/jicfxZEPvyYbeE4/jicfxVJekuiTxOJ54HE88jicexxOP41lKCR7HE4/jyYbekw29ZyklpZSoS1JdkuqSxON44nE82dB7sqH3bKWklRJ1SapLUl2SeBxPPI7nKCWjlOBxPPE4nngcz1FKRilhQ+/Jht5zlZJVStQlqS5JPI4nHsdzlRI29J5s6D1PKTmlRF2S6pLE43jicTxPKcHjeOJxPPE4XngcLzyOFxt6Lzb0XmzovfA4XuqSUpeUuqTwOF54HC829F5s6L3Y0HvhcbzUJaUuKXVJ4XG88DheeBwvPI4XHscLj+OFx/HC43jhcbzY0HuxoffC43jhcbzUJaUuKTyOFx7HC4/jxYbeiw29Fx7HC4/jpS4pdUnhcbzwOF54HC88jhcexwuP44XH8cLjeLGh92JD71VKSSkl6pJSl5S6pPA4XngcLzb0XmzovVopaaVEXVLqklKXFB7HC4/j1UpJKyV4HC88jhcex2uUklFK2NB7saH3GqVklBJ1SalLCo/jhcfxWqWEDb0XG3qvVUpWKVGXlLqk8DheeByvU0rwOF54HK9TSvA4Xngcr9PXzYbemw29Nx7HW13S6pJWlzQexxuP482G3psNvTcbem88jre6pNUlrS5pPI43Hscbj+ONx/HG43jjcbzxON54HG88jjcbem829N54HG88jre6pNUljcfxxuN443G82dB7s6H3xuN443G81SWtLmk8jjcexxuP443H8cbjeONxvPE43ngcbzb03mzovdnQe6dSoi5pdUmrSxqP443H8WZD782G3ruUklJK1CWtLml1SeNxvPE43q2UtFKCx/HG43jjcbxbKRmlhA29Nxt671FKRilRl7S6pPE43ngc71FK2NB7s6H3XqVklRJ1SatLGo/jjcfxXqUEj+ONx/E+pQSP443H8T593WzovU8pOaVEXdLq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4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uvgvQ7e6+C9Dt7r4L0O3uv88F7nx3N4Ls+fr9WPX/v/LPnn8/D8+Vrtj+fP1+r9/V9+9d+/+ekPv/ntH3//X7/61//9+Yf/8bc//e6vf/jzn3754V//5y///Jnf/vSHP/7xD//567/89Off/f7f//bT73/9xz//7h8/9/d/+/v/AQ==","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"22":{"source":"pub mod hash;\npub mod aes128;\npub mod array;\npub mod slice;\npub mod ecdsa_secp256k1;\npub mod ecdsa_secp256r1;\npub mod embedded_curve_ops;\npub mod field;\npub mod collections;\npub mod compat;\npub mod convert;\npub mod option;\npub mod string;\npub mod test;\npub mod cmp;\npub mod ops;\npub mod default;\npub mod prelude;\npub mod runtime;\npub mod meta;\npub mod append;\npub mod mem;\npub mod panic;\npub mod hint;\n\nuse convert::AsPrimitive;\n\n// Oracle calls are required to be wrapped in an unconstrained function\n// Thus, the only argument to the `println` oracle is expected to always be an ident\n#[oracle(print)]\nunconstrained fn print_oracle(with_newline: bool, input: T) {}\n\nunconstrained fn print_unconstrained(with_newline: bool, input: T) {\n print_oracle(with_newline, input);\n}\n\npub fn println(input: T) {\n // Safety: a print statement cannot be constrained\n unsafe {\n print_unconstrained(true, input);\n }\n}\n\npub fn print(input: T) {\n // Safety: a print statement cannot be constrained\n unsafe {\n print_unconstrained(false, input);\n }\n}\n\n/// Asserts the validity of the provided proof and public inputs against the provided verification key and hash.\n///\n/// The ACVM cannot determine whether the provided proof is valid during execution as this requires knowledge of\n/// the backend against which the program is being proven. However if an invalid proof if submitted, the program may\n/// fail to prove or the backend may generate a proof which will subsequently fail to verify.\n///\n/// # Important Note\n///\n/// If you are not developing your own backend such as [Barretenberg](https://github.com/AztecProtocol/barretenberg)\n/// you probably shouldn't need to interact with this function directly. It's easier and safer to use a verification\n/// library which is published by the developers of the backend which will document or enforce any safety requirements.\n///\n/// If you use this directly, you're liable to introduce underconstrainedness bugs and *your circuit will be insecure*.\n///\n/// # Arguments\n/// - verification_key: The verification key of the circuit to be verified.\n/// - proof: The proof to be verified.\n/// - public_inputs: The public inputs associated with `proof`\n/// - key_hash: The hash of `verification_key` of the form expected by the backend.\n/// - proof_type: An identifier for the proving scheme used to generate the proof to be verified. This allows\n/// for a single backend to support verifying multiple proving schemes.\n///\n/// # Constraining `key_hash`\n///\n/// The Noir compiler does not by itself constrain that `key_hash` is a valid hash of `verification_key`.\n/// This is because different backends may differ in how they hash their verification keys.\n/// It is then the responsibility of either the noir developer (by explicitly hashing the verification key\n/// in the correct manner) or by the proving system itself internally asserting the correctness of `key_hash`.\npub fn verify_proof_with_type(\n verification_key: [Field; N],\n proof: [Field; M],\n public_inputs: [Field; K],\n key_hash: Field,\n proof_type: u32,\n) {\n if !crate::runtime::is_unconstrained() {\n crate::assert_constant(proof_type);\n }\n verify_proof_internal(verification_key, proof, public_inputs, key_hash, proof_type);\n}\n\n#[foreign(recursive_aggregation)]\nfn verify_proof_internal(\n verification_key: [Field; N],\n proof: [Field; M],\n public_inputs: [Field; K],\n key_hash: Field,\n proof_type: u32,\n) {}\n\n// Asserts that the given value is known at compile-time.\n// Useful for debugging for-loop bounds.\n#[builtin(assert_constant)]\npub fn assert_constant(x: T) {}\n\n// Asserts that the given value is both true and known at compile-time.\n// The message can be a string, a format string, or any value, as long as it is known at compile-time\n#[builtin(static_assert)]\npub fn static_assert(predicate: bool, message: T) {}\n\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_add(y)\")]\npub fn wrapping_add(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n AsPrimitive::as_(x.as_() + y.as_())\n}\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_sub(y)\")]\npub fn wrapping_sub(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow\n AsPrimitive::as_(x.as_() + 340282366920938463463374607431768211456 - y.as_())\n}\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_mul(y)\")]\npub fn wrapping_mul(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n AsPrimitive::as_(x.as_() * y.as_())\n}\n\n#[builtin(as_witness)]\npub fn as_witness(x: Field) {}\n\nmod tests {\n use super::ops::arith::WrappingMul;\n\n #[test(should_fail_with = \"custom message\")]\n fn test_static_assert_custom_message() {\n super::static_assert(1 == 2, \"custom message\");\n }\n\n #[test]\n fn test_wrapping_mul() {\n let zero: u128 = 0;\n let one: u128 = 1;\n let two_pow_64: u128 = 0x10000000000000000;\n let u128_max: u128 = 0xffffffffffffffffffffffffffffffff;\n\n // 1*0==0\n assert_eq(zero, zero.wrapping_mul(one));\n\n // 0*1==0\n assert_eq(zero, one.wrapping_mul(zero));\n\n // 1*1==1\n assert_eq(one, one.wrapping_mul(one));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(zero, zero.wrapping_mul(two_pow_64));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(zero, two_pow_64.wrapping_mul(zero));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(two_pow_64, two_pow_64.wrapping_mul(one));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(two_pow_64, one.wrapping_mul(two_pow_64));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(zero, two_pow_64.wrapping_mul(two_pow_64));\n // -1 * -1 == 1\n assert_eq(one, u128_max.wrapping_mul(u128_max));\n }\n}\n","path":"std/lib.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"67":{"source":"use dep::std;\nuse poseidon::poseidon2;\n\nstruct AggProof {\n proof: [Field; 508],\n old_root: Field,\n new_root: Field,\n commit_hash: Field,\n messages: [Field; 1000],\n verification_key: [Field; 115],\n verification_key_hash: Field\n}\n\nfn main(\n proofs: [AggProof; 2],\n // allowed proofs (will be validated by agg_final)\n verification_key_hash: pub [Field; 2],\n old_root: pub Field,\n new_root: pub Field,\n commit_hash: pub Field,\n messages: pub [Field; 1000],\n) {\n let mut root = old_root;\n let mut first_public_inputs: [Field; 1005] = [0; 1005];\n let mut messages_index = 0;\n\n for i in 0..2 {\n let proof = proofs[i];\n\n // Assert the proof is one of public verification_key_hash (this will be verified in the agg_final)\n let is_valid_proof = (verification_key_hash[0] == proof.verification_key_hash) | (verification_key_hash[1] == proof.verification_key_hash);\n assert(is_valid_proof, \"proof must be one of the valid proofs\");\n\n let mut public_inputs: [Field; 1005] = [0; 1005];\n\n public_inputs[0] = verification_key_hash[0];\n public_inputs[1] = verification_key_hash[1];\n public_inputs[2] = proof.old_root;\n public_inputs[3] = proof.new_root;\n public_inputs[4] = proof.commit_hash;\n\n ///////\n // Check compact messages and assign public inputs\n ///////\n\n // End immediately for padding proof (as it cannot have messages)\n let mut has_ended = proof.old_root == 0;\n\n // Exportable message kinds (2, 3 and 4) consume the next x messages, so when checking\n // for the end we skip the consumed messages, so we can find the first non-exportable kind.\n // Assumes that agg_utxo proof also compacts exportable kinds from index 0 (without gaps).\n let mut next_check = 0;\n for j in 0..1000 {\n let proof_message = proof.messages[j];\n public_inputs[j + 5] = proof_message;\n\n // Update next checkpoint (or end)\n if (next_check == j) {\n if proof_message == 2 {\n // Mint\n next_check += 4;\n } else if ((proof_message == 3) | (proof_message == 4)) {\n // Burn, Swap\n next_check += 5;\n } else {\n has_ended = true;\n }\n }\n\n if (has_ended) {\n assert(proof_message == 0, \"messages cannot have gaps\");\n } else {\n assert(messages_index != 1000, \"proof messages exceed compacted range\");\n assert(proof_message == messages[messages_index], \"proof message must be exported\");\n // Incr the global counter (shared between proofs)\n messages_index += 1;\n }\n }\n\n // Workaround for 2nd proof being a padding proof\n if i == 0 {\n first_public_inputs = public_inputs;\n }\n\n std::verify_proof_with_type(\n proof.verification_key,\n if proof.old_root != 0 {\n proof.proof\n } else {\n proofs[0].proof\n },\n if proof.old_root != 0 {\n public_inputs\n } else {\n first_public_inputs\n },\n proof.verification_key_hash,\n 7,\n );\n\n if proof.old_root != 0 {\n assert(proof.old_root == root, \"proof old_root must match previous root\");\n root = proof.new_root;\n }\n }\n\n assert(\n commit_hash\n == poseidon2::Poseidon2::hash(\n [proofs[0].commit_hash, proofs[1].commit_hash],\n 2,\n ),\n );\n assert(new_root == root, \"Roots must match\");\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/agg_agg/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/agg_final/key b/fixtures/circuits/agg_final/key new file mode 100644 index 0000000..7d69fd8 Binary files /dev/null and b/fixtures/circuits/agg_final/key differ diff --git a/fixtures/circuits/agg_final/key_fields.json b/fixtures/circuits/agg_final/key_fields.json new file mode 100644 index 0000000..9518f24 --- /dev/null +++ b/fixtures/circuits/agg_final/key_fields.json @@ -0,0 +1,61 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000014", + "0x00000000000000000000000000000000000000000000000000000000000003fb", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x07fea1a154c2ea92bfe9bff6608105c79be2000fb533c5a7f5086f42631d0024", + "0x072a7fa47c0445d4a3a00a17126f3d4134c5ddf94ff72fe262c3c2d36017ce54", + "0x0eaf0f335934fe83217bf228608474b6e7874844976d3f606546efdabe85198e", + "0x2fd2b3710e51885e05066c12c867b19f6abfedb1329bd4b34c51e4edae010ed1", + "0x16564b9c5794a0940a9bdb105356d4d8e7c0d2ed04fb7fe3b82e32fe70ad7976", + "0x19f4325229ca1f419b897a9286a396923b26592fb85e1fad1e5db7b8afaa4b73", + "0x08a7d8009f6f264dac2833251dc17269967029b78cdacd33104a8f8fdb79c940", + "0x196750fb121848a766033747e726bdb19a4a957a483edb24f45cdf4a6abce4ad", + "0x2668a86828ec16a70fe3c30a353eee037c19f470e1e5a2586eb47e9a3372fe31", + "0x13a5d44fce53d20af70a40f3c33ca60a1eab4a2907b9f74374a00099af5b308f", + "0x05e267528bcdaaef76b87581271c147470268de2e8b9201a79a4ab9ff483c742", + "0x07114abaa67e3fd05d43b93d42f36cc0f650ef8f0fed3613294cc820fd8718e9", + "0x15b5b0e5904efcadcef0d9c7305e0c778692a7b2f9f210b9104c213daea659a8", + "0x0e24f0b634a1648112578318c5455cd09fb98da9822306ea7c65dc48db697ea4", + "0x17846b41619ecf9273cf386c1b16e7f55fa35ec9386eb2ea216398f428379e79", + "0x1ac6fe092563d4e89b104cfafada05910ea6e0c0cdd0b0fd5cc58f1fad65f5d1", + "0x05665cdccbda0515ceebf81f09c44fdb329181de80055bbd4249751c80280dbf", + "0x21286c7bbb9d4894157e2975e667d5c33e910f985863d681880648677502133f", + "0x0d046a2c7f903da415a6951e75a5381b70a0331b790c07b97ce70d34d338a72b", + "0x26b1f648f365eb5cbbe4c6e3244537dacfbbf95845bc38ec6895d8abbc027526", + "0x2d2e9b5315b13f26465f33617d15b566e8d9eb9db7f2620b6fc80fa1f006fc51", + "0x28dd92658fa8222aef67475960ab7033a2da3b6622b2e18094deb5718ff2ea71", + "0x2130ca557da2368a359901856d4fb658e39384a611b8ff226a0a6e4492f59118", + "0x2ff59ab4fd220200b24946eedcd14d61acb5dd2499e6f89294af9bce971825fc", + "0x16bfc1cbd0c6a38e201686891975e2d3a32ff2ea3e0d298a7f6b9ac55d8228cd", + "0x0ba7b53a836f4bf89f64e9d0ce2cb1b81b63e81589774004339507f0e8fb0720", + "0x1dae1d5fb23ef041ac8fb25b5739ff333f941a02cf543839aa68595bed009241", + "0x10479380fe8d144a5e6ceec04c2271346324d911e80bbd685ccb3e5ab65bdfb5", + "0x208e191dd65dfe84d1c782de58d6049c6cf080e0d85998d9306385a148250a6d", + "0x0254a28372e909a029e4189c42716805e9b0db5ce5b97eb7060b25472e669fc5", + "0x1647261d35e5226996c3fe13de83b2a3c2d7ff1d5c94d42d5cec74c5862656d1", + "0x2d40aad6d8245b190e2b45686ca05da2595be9e7483c75b9bcab335fd51941bc", + "0x1dfe547a651f077f580970260f0593e146c55e3874adbdc347a5039b32024d7a", + "0x2e5aa258ca6b4863370ae82df32001c1b0c363b72ff4e2503adf731fd3502d4b", + "0x284788e2b69fcabd417414a25ba458b5a37a7d37fea6fb298e124146e86921e4", + "0x15cdd6ac38bbaf22615366da36733cc939e5fe95efbf3321e577df4ff7fca877", + "0x2e62626a1095231a41bdc000c7bd20c073919d40ccb4d9a36d1629902b061fcb", + "0x21305733d27ee6dab8c79607a8e8462df373b5f5d7429e78b62363e0ef71df95", + "0x076dc9c7790ed478259153d69811573276e6d26536b485d4d82977c330485ac8", + "0x2fbfea486a89022680b0e0e81ead9c56125b0066007326944a5ad05665928fcb", + "0x1552b3c8a793524d496ac086b1c182575ad9a3249ba1aafb30110615712b8d37", + "0x0f68500204cd7693fd5e1f8b490c74dd7a1e556d2bad5782731d3eb4b8904147", + "0x10ad68cb78329a5c44b13c6da53ccc16b2bdf8cc6b955161f7f6676abfa050cb", + "0x2643eef532153fc9853f9257031440654d9c2482299ab424ad953b72a1fdb7ae", + "0x111bc3039becaa8ca62f0bcefcd65040fe1d5bc68e929318b3f5dd767ce9822b", + "0x1b691e6fe2d651e8c02ab30d0b5f032addd00bbe41104a7206e2ff9d7b658a3d", + "0x0a0a54df61fecb42534ccfd8d51ee000e269a65d07d5b63227459ba189ab2f04", + "0x09276e284d9fcacc3201e71f779a6e66950841c2324d970c8bb2f8d6c87755e7", + "0x110e7b7f4053452dae6c6d52983ed4f268823e7c2958a2967f35178675092a29", + "0x29df570d178d1f2aa52fd2669fd347d2d75a722175e050c90fbb00adb5d82d2f", + "0x1326d49efee0292517ce6bfbacd193969a5cb9ce2cd571cb6426f56009b82085", + "0x176a9c71e742c7798aea8f5e828ece04efa2abe35b8c33eff8c74ac1fafbb2de", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x2f6ae80f550fc0a26f347268c7d0617869a16b8600d893ffce5e6d1dd8a010cd", + "0x0e64b747f724eb59221c9dec8a24b86a785fbab2feacfc82000733d2ef85d82b" +] diff --git a/fixtures/circuits/agg_final/program.json b/fixtures/circuits/agg_final/program.json new file mode 100644 index 0000000..c743d2f --- /dev/null +++ b/fixtures/circuits/agg_final/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"6867025627425423222","abi":{"parameters":[{"name":"verification_key","type":{"kind":"array","length":115,"type":{"kind":"field"}},"visibility":"private"},{"name":"verification_key_hash","type":{"kind":"field"},"visibility":"private"},{"name":"proof","type":{"kind":"array","length":508,"type":{"kind":"field"}},"visibility":"private"},{"name":"old_root","type":{"kind":"field"},"visibility":"public"},{"name":"new_root","type":{"kind":"field"},"visibility":"public"},{"name":"commit_hash","type":{"kind":"field"},"visibility":"public"},{"name":"messages","type":{"kind":"array","length":1000,"type":{"kind":"field"}},"visibility":"public"}],"return_type":null,"error_types":{"18101985427812140656":{"error_kind":"string","string":"only agg_agg proof allowed"}}},"bytecode":"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","debug_symbols":"nZLdasQgEIXfZa698Cdxt/sqpQSTTBZBTHC1UILv3onEdHsRWPZmdGY83xHHFUbs072zfpofcPtcoQ/WOXvv3DyYaGdP1TUzqGkXAyKV4KlPqsUE9BFuPjnH4Nu4VA49FuPLGk2gLmeAfqSVgJN1uO0y+1Pzc2nbql2s+eWQ6+uresFFdRdcijcIH9fLAXjzClpXguT6jNCcE5TUcico1bQHQcqcvygzgw3/BgecvBgIej8GskRVYkMxb0bBmt7hPuQp+eFp5vFnqZ36K5YwDzimgJtN6ZHxLw==","file_map":{"22":{"source":"pub mod hash;\npub mod aes128;\npub mod array;\npub mod slice;\npub mod ecdsa_secp256k1;\npub mod ecdsa_secp256r1;\npub mod embedded_curve_ops;\npub mod field;\npub mod collections;\npub mod compat;\npub mod convert;\npub mod option;\npub mod string;\npub mod test;\npub mod cmp;\npub mod ops;\npub mod default;\npub mod prelude;\npub mod runtime;\npub mod meta;\npub mod append;\npub mod mem;\npub mod panic;\npub mod hint;\n\nuse convert::AsPrimitive;\n\n// Oracle calls are required to be wrapped in an unconstrained function\n// Thus, the only argument to the `println` oracle is expected to always be an ident\n#[oracle(print)]\nunconstrained fn print_oracle(with_newline: bool, input: T) {}\n\nunconstrained fn print_unconstrained(with_newline: bool, input: T) {\n print_oracle(with_newline, input);\n}\n\npub fn println(input: T) {\n // Safety: a print statement cannot be constrained\n unsafe {\n print_unconstrained(true, input);\n }\n}\n\npub fn print(input: T) {\n // Safety: a print statement cannot be constrained\n unsafe {\n print_unconstrained(false, input);\n }\n}\n\n/// Asserts the validity of the provided proof and public inputs against the provided verification key and hash.\n///\n/// The ACVM cannot determine whether the provided proof is valid during execution as this requires knowledge of\n/// the backend against which the program is being proven. However if an invalid proof if submitted, the program may\n/// fail to prove or the backend may generate a proof which will subsequently fail to verify.\n///\n/// # Important Note\n///\n/// If you are not developing your own backend such as [Barretenberg](https://github.com/AztecProtocol/barretenberg)\n/// you probably shouldn't need to interact with this function directly. It's easier and safer to use a verification\n/// library which is published by the developers of the backend which will document or enforce any safety requirements.\n///\n/// If you use this directly, you're liable to introduce underconstrainedness bugs and *your circuit will be insecure*.\n///\n/// # Arguments\n/// - verification_key: The verification key of the circuit to be verified.\n/// - proof: The proof to be verified.\n/// - public_inputs: The public inputs associated with `proof`\n/// - key_hash: The hash of `verification_key` of the form expected by the backend.\n/// - proof_type: An identifier for the proving scheme used to generate the proof to be verified. This allows\n/// for a single backend to support verifying multiple proving schemes.\n///\n/// # Constraining `key_hash`\n///\n/// The Noir compiler does not by itself constrain that `key_hash` is a valid hash of `verification_key`.\n/// This is because different backends may differ in how they hash their verification keys.\n/// It is then the responsibility of either the noir developer (by explicitly hashing the verification key\n/// in the correct manner) or by the proving system itself internally asserting the correctness of `key_hash`.\npub fn verify_proof_with_type(\n verification_key: [Field; N],\n proof: [Field; M],\n public_inputs: [Field; K],\n key_hash: Field,\n proof_type: u32,\n) {\n if !crate::runtime::is_unconstrained() {\n crate::assert_constant(proof_type);\n }\n verify_proof_internal(verification_key, proof, public_inputs, key_hash, proof_type);\n}\n\n#[foreign(recursive_aggregation)]\nfn verify_proof_internal(\n verification_key: [Field; N],\n proof: [Field; M],\n public_inputs: [Field; K],\n key_hash: Field,\n proof_type: u32,\n) {}\n\n// Asserts that the given value is known at compile-time.\n// Useful for debugging for-loop bounds.\n#[builtin(assert_constant)]\npub fn assert_constant(x: T) {}\n\n// Asserts that the given value is both true and known at compile-time.\n// The message can be a string, a format string, or any value, as long as it is known at compile-time\n#[builtin(static_assert)]\npub fn static_assert(predicate: bool, message: T) {}\n\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_add(y)\")]\npub fn wrapping_add(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n AsPrimitive::as_(x.as_() + y.as_())\n}\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_sub(y)\")]\npub fn wrapping_sub(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow\n AsPrimitive::as_(x.as_() + 340282366920938463463374607431768211456 - y.as_())\n}\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_mul(y)\")]\npub fn wrapping_mul(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n AsPrimitive::as_(x.as_() * y.as_())\n}\n\n#[builtin(as_witness)]\npub fn as_witness(x: Field) {}\n\nmod tests {\n use super::ops::arith::WrappingMul;\n\n #[test(should_fail_with = \"custom message\")]\n fn test_static_assert_custom_message() {\n super::static_assert(1 == 2, \"custom message\");\n }\n\n #[test]\n fn test_wrapping_mul() {\n let zero: u128 = 0;\n let one: u128 = 1;\n let two_pow_64: u128 = 0x10000000000000000;\n let u128_max: u128 = 0xffffffffffffffffffffffffffffffff;\n\n // 1*0==0\n assert_eq(zero, zero.wrapping_mul(one));\n\n // 0*1==0\n assert_eq(zero, one.wrapping_mul(zero));\n\n // 1*1==1\n assert_eq(one, one.wrapping_mul(one));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(zero, zero.wrapping_mul(two_pow_64));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(zero, two_pow_64.wrapping_mul(zero));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(two_pow_64, two_pow_64.wrapping_mul(one));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(two_pow_64, one.wrapping_mul(two_pow_64));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(zero, two_pow_64.wrapping_mul(two_pow_64));\n // -1 * -1 == 1\n assert_eq(one, u128_max.wrapping_mul(u128_max));\n }\n}\n","path":"std/lib.nr"},"68":{"source":"use dep::std;\nuse poseidon::poseidon2;\n\nglobal AGG_UTXO_VERIFICATION_KEY_HASH: Field = 5897206462939179313090278977855702552208277022861650698363349603526525271812;\nglobal AGG_AGG_VERIFICATION_KEY_HASH: Field = 11623735493169461569078977608660595680947806981338331162316688672907570294243;\n\nfn main(\n verification_key: [Field; 115],\n verification_key_hash: Field,\n proof: [Field; 508],\n old_root: pub Field,\n new_root: pub Field,\n commit_hash: pub Field,\n messages: pub [Field; 1000],\n) {\n // Must be an agg_agg proof\n assert(verification_key_hash == AGG_AGG_VERIFICATION_KEY_HASH, \"only agg_agg proof allowed\");\n\n // Build public inputs for the agg_agg proof\n let mut public_inputs: [Field; 1005] = [0; 1005];\n public_inputs[0] = AGG_UTXO_VERIFICATION_KEY_HASH;\n public_inputs[1] = AGG_AGG_VERIFICATION_KEY_HASH;\n public_inputs[2] = old_root;\n public_inputs[3] = new_root;\n public_inputs[4] = commit_hash;\n\n for i in 0..1000 {\n public_inputs[i + 5] = messages[i];\n }\n\n // Verify the agg_agg proof\n std::verify_proof_with_type(\n verification_key,\n proof,\n public_inputs,\n verification_key_hash,\n 7,\n );\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/agg_final/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/agg_utxo/key b/fixtures/circuits/agg_utxo/key new file mode 100644 index 0000000..0b19ba4 Binary files /dev/null and b/fixtures/circuits/agg_utxo/key differ diff --git a/fixtures/circuits/agg_utxo/key_fields.json b/fixtures/circuits/agg_utxo/key_fields.json new file mode 100644 index 0000000..74df02c --- /dev/null +++ b/fixtures/circuits/agg_utxo/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000016", + "0x00000000000000000000000000000000000000000000000000000000000003fd", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x00000000000000000000000000000018ac488712f4a21f49689e2283a7e7c03a", + "0x00000000000000000000000000000000001eda5a7555b4406bcc9ca40d810f00", + "0x000000000000000000000000000000cc7116f13890635569b4fce263e4dc60f8", + "0x000000000000000000000000000000000029ff96f6e1c8f50bf28c3bc7b5a275", + "0x000000000000000000000000000000b3c4faa0d4a901b0006b7f01a0b4f2edcc", + "0x000000000000000000000000000000000024e046152fa2f00c654b6f9332ed3e", + "0x0000000000000000000000000000002f0cb4fb55f94427bc051497b018e23b86", + "0x00000000000000000000000000000000002bbe289632b5bc8d477dbceb985d2c", + "0x00000000000000000000000000000057d8d6a7ed0e7d04904ca5ad81bbbd3133", + "0x00000000000000000000000000000000000f20541b08cdca4198ee5db803deeb", + "0x000000000000000000000000000000cd67c31a1b23e9a2d46bdee4bdfe248be1", + "0x00000000000000000000000000000000000ede3b9c0b8513ed9b83b2c7941d0b", + "0x000000000000000000000000000000f84b4d8c5df5551af8b5487aae2315e7cc", + "0x00000000000000000000000000000000001e6f9a32903b02c89fdf6f8c50892f", + "0x000000000000000000000000000000e4129a658cd7321c8643ee5a789016c9df", + "0x000000000000000000000000000000000010faafcb941c3bbd8e8727fc38dc27", + "0x0000000000000000000000000000000abd58b1ee065ad941ba421fa0c1704992", + "0x000000000000000000000000000000000028deb755ad45c51eb6e781964325ca", + "0x0000000000000000000000000000005c9793fdffaa54e7854cc5e9f03a2e52fe", + "0x000000000000000000000000000000000013c53e38dc85c500bbfabf4d9b1936", + "0x000000000000000000000000000000d8c0bec59bce53d10f59d29ea04f08c7c1", + "0x000000000000000000000000000000000013024517c0fd0345d43ff60a0d3257", + "0x00000000000000000000000000000001f3780c2c91c05d3c7b39ee007b3be5c9", + "0x00000000000000000000000000000000000e0a60e47ba6411b74c07b1bc02c40", + "0x000000000000000000000000000000bb5f3adb8b1a360885d949225f796e05a2", + "0x000000000000000000000000000000000014dd1ce931af2f1a008cdb4e13fcb4", + "0x00000000000000000000000000000036efffbc6387a0d74ed1271a8ce1566b7d", + "0x000000000000000000000000000000000011a7654358d84ce23eb3f3714bc52d", + "0x000000000000000000000000000000f1962de08b7c67fa17c398419ef48de670", + "0x00000000000000000000000000000000002d479b4859504787e314d7f7b101a9", + "0x000000000000000000000000000000940e5c112de616cf34f3de383f28465d73", + "0x000000000000000000000000000000000025d206fd4ee8529b18b8a0769c981c", + "0x0000000000000000000000000000002083d21e4a36319b1e97f957edd99cb540", + "0x0000000000000000000000000000000000062904d2b3a587e84d08aa0442a7b9", + "0x0000000000000000000000000000000610624f431db5dd2532357910ec6a79e8", + "0x00000000000000000000000000000000002a9503ccd69341fa8340296e55a0d7", + "0x00000000000000000000000000000035a6e0efc3e3baa0e12da5bfd6df446cd4", + "0x00000000000000000000000000000000001d983a6cee7c3f29ada41d50e9fa35", + "0x0000000000000000000000000000005829996500c0b70327ed1ee7a8106c0ecd", + "0x0000000000000000000000000000000000000dbc98bac1b73ec053acda7a5582", + "0x00000000000000000000000000000085d80f65fb45e7f2abbdc733dd3d78f9fe", + "0x00000000000000000000000000000000002d995dd6edb777b8f2432a10bfe43e", + "0x00000000000000000000000000000012860fcb11526625452ec2f0bcf355500f", + "0x00000000000000000000000000000000000334aa3c78d76e4e624e470b99f871", + "0x00000000000000000000000000000044138826df436ff32f8477e24dc2b507b9", + "0x0000000000000000000000000000000000199d9706c9bcfe7a0a86e2b2a389fe", + "0x00000000000000000000000000000026a47a11851442dffdd93a2dbc0d6215ca", + "0x000000000000000000000000000000000026e8e147772f1f1832fdacce7f6ed3", + "0x000000000000000000000000000000a63b6daf05d4b7cbfd6c5910cd349c3958", + "0x000000000000000000000000000000000000f567d97ef6b4adbd2555f3531ebd", + "0x00000000000000000000000000000056d7e436159f80dec89d2ff9d69ae82aa5", + "0x000000000000000000000000000000000020a8b69b9c44df328b5ff8b4b10421", + "0x00000000000000000000000000000050bdd5519e2cb1097d2f2e3795e9d3ec0d", + "0x00000000000000000000000000000000000c79e4ed1f0452b9b6d9091512ff5a", + "0x000000000000000000000000000000a6650915772c8434b5acf8ff67cf19a642", + "0x0000000000000000000000000000000000304f2de23304fda78e88b0cb741482", + "0x000000000000000000000000000000d4a8ce5b5260dda925306559fc173c11de", + "0x00000000000000000000000000000000002d884567b19bfb154ceb6bcb936317", + "0x000000000000000000000000000000197b6b4ba88c19f342e9fe91b6586d96c3", + "0x00000000000000000000000000000000000636d00f5a70e5cb65d6ac77910e2d", + "0x000000000000000000000000000000f45f30b9294b0ce18f0fd749a2e4ff2a9a", + "0x00000000000000000000000000000000000f459ae5ccb88c3539488663625486", + "0x000000000000000000000000000000a7b489db734d73ed0c0137382793ff5e2a", + "0x00000000000000000000000000000000000468590f5c4735b4d750fd8b67be46", + "0x000000000000000000000000000000f432f10464845c698b9a9b9498d73ea4bb", + "0x00000000000000000000000000000000000e69f4aeb0f396bd68238b353770a4", + "0x000000000000000000000000000000ae88e777bf42329d312670d4856689058e", + "0x00000000000000000000000000000000002dbe90c8c76eb489dde03a40707928", + "0x000000000000000000000000000000770980a7f11342d356fd2b3acf9a9a3ca5", + "0x00000000000000000000000000000000001213ab450290fc82fcb9e28c795903", + "0x000000000000000000000000000000c7b26762efb74be45aa7108fedf85ec166", + "0x000000000000000000000000000000000021ae32bd7c02328814cb8e02a4f28f", + "0x0000000000000000000000000000001e9e69dea529d2dde739f66e2697e916be", + "0x000000000000000000000000000000000025123d945a5742239937a7f0eb6f91", + "0x00000000000000000000000000000022493cbbd3b969081804bf42a115af6848", + "0x000000000000000000000000000000000026c16be76d067b6c54aa3170e7ac74", + "0x000000000000000000000000000000437a034054c3395b2da795298a6d7d0932", + "0x00000000000000000000000000000000002028af74ad7af142e5bc36d3891df3", + "0x000000000000000000000000000000882cb7a2bdf60f63472a745af44e2b23ce", + "0x000000000000000000000000000000000013065213ab7aaa19d68f9524b07fc1", + "0x000000000000000000000000000000418a3c95b946021633465cad8ec97ed6e3", + "0x000000000000000000000000000000000002f174b2bdab92c5baa62e614fa069", + "0x0000000000000000000000000000009264250aaaf4dbe2a2db06c07a9c6f462f", + "0x0000000000000000000000000000000000141160308561167bae8df776010551", + "0x00000000000000000000000000000095e2d2488dd57784ec110388aba8715cf4", + "0x000000000000000000000000000000000029f9fa68e6fd4bec71d3301675fd81", + "0x0000000000000000000000000000004f5a5fea1f9b5ab9dc1fd1b55d97830842", + "0x000000000000000000000000000000000015f663b328fdd72d6ce83da4a69725", + "0x0000000000000000000000000000002a1ca163046e9d0415b0ba9d9c4632f07b", + "0x0000000000000000000000000000000000041b4073446b5892dd7eabf545028e", + "0x00000000000000000000000000000018573a8cb7efc197b5371780de35eb55de", + "0x0000000000000000000000000000000000005d24fbb51390fb1488b82145f514", + "0x000000000000000000000000000000be862a90b3a83a75d1073b4235299d88d2", + "0x00000000000000000000000000000000000a58ab84bec6105d9533d7b52c7d46", + "0x00000000000000000000000000000067f3b2aebec2b7b606d0d11e571da53cf7", + "0x0000000000000000000000000000000000072b71091d1ef407e20d0d0cd1689c", + "0x00000000000000000000000000000046c3574dc85c47790ef4c28da426bf3439", + "0x000000000000000000000000000000000026cd38a986f17cbd48fe1f6dfb5a00", + "0x00000000000000000000000000000036e845cb1a0b351511cfb7d51a7d48cd84", + "0x00000000000000000000000000000000000dad5bdae552b07915f2ba16ca7177", + "0x000000000000000000000000000000b75e5f1b657d31d571204511d018db5e63", + "0x00000000000000000000000000000000002141cda9c7a8779c338b16176c47d8", + "0x000000000000000000000000000000dfb867822f826d7f1bae92c942bc587396", + "0x0000000000000000000000000000000000029ef7d95d44f73300dfdc5d1f7857", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000c69515a593e26c2e1ba74d1fa17037f7d7", + "0x000000000000000000000000000000000021e29487bdee0e6ee954c7fdadf929", + "0x00000000000000000000000000000020c9d8df7cfc2877a481740ecebff5a567", + "0x00000000000000000000000000000000002c0d781fca0108366534f24032ffaa" +] diff --git a/fixtures/circuits/agg_utxo/program.json b/fixtures/circuits/agg_utxo/program.json new file mode 100644 index 0000000..4231c05 --- /dev/null +++ b/fixtures/circuits/agg_utxo/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"3418167402373448043","abi":{"parameters":[{"name":"verification_key","type":{"kind":"array","length":115,"type":{"kind":"field"}},"visibility":"private"},{"name":"proofs","type":{"kind":"array","length":3,"type":{"kind":"struct","path":"AggUtxoProofInput","fields":[{"name":"proof","type":{"kind":"array","length":508,"type":{"kind":"field"}}},{"name":"utxo_kind","type":{"kind":"field"}},{"name":"input_merkle_paths","type":{"kind":"array","length":2,"type":{"kind":"array","length":160,"type":{"kind":"field"}}}},{"name":"output_merkle_paths","type":{"kind":"array","length":2,"type":{"kind":"array","length":160,"type":{"kind":"field"}}}},{"name":"input_commitments","type":{"kind":"array","length":2,"type":{"kind":"field"}}},{"name":"output_commitments","type":{"kind":"array","length":2,"type":{"kind":"field"}}}]}},"visibility":"private"},{"name":"verification_key_hash","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"},{"name":"old_root","type":{"kind":"field"},"visibility":"public"},{"name":"new_root","type":{"kind":"field"},"visibility":"public"},{"name":"commit_hash","type":{"kind":"field"},"visibility":"public"},{"name":"messages","type":{"kind":"array","length":1000,"type":{"kind":"field"}},"visibility":"public"}],"return_type":null,"error_types":{"4703047920556725948":{"error_kind":"string","string":"Field failed to decompose into specified 254 limbs"},"4892793474188571753":{"error_kind":"string","string":"proof 'kind' must match message"},"8552356966378227581":{"error_kind":"string","string":"first proof cannot be a padding proof"},"9820581216087758289":{"error_kind":"string","string":"New root is not valid"},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15668050119838777306":{"error_kind":"string","string":"Merkle path root does not match"},"16317344318398924037":{"error_kind":"string","string":"Message is not zero"},"17709585997857100103":{"error_kind":"string","string":"dummy verfication key hash"}}},"bytecode":"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zxxq29hqP3eorWCrnSeurfPSVjvfodb2+we/BeLa2vbaheLamvbaL8S1Ve21i8S15e21i8W1Be21S8S1ie21S4W1d4/aa78U19p/v+O3TFj7879qlwtr7/yrdoWw9ta/alcKay//q3aVsPbov2q/Etau+FftamFt+3/Vfi2qLfWv35/5rRHVlvx37VpRbfF/164T1b7/79r1oto8/67dIKpN++/ajYLaAr//u3aTqHbjv2s3i2r//ftJvy2C2vwxarcKavPGqN0mqM0Vo3a7oDZTjNodgtrEMWp3xl4bdC9G7S5B7YoYtbsFtTF+/+u3J/bawJi1e2OvbROzdl/stS1i1u6PvbZRzNoDsdd+FLP2YOy12WPWHoq1ttWNmLWHY68Njll7JNbalv+p/SbW2ub/qT0aa23T/9R+G2tt3f/UHou1tvx/ao/HWpvpP7UnYqsdfvk/tSdjrW39n9pTsdUO+2/t6dhqh/y39kxstQP+W3s2ttoe/609F1tt2H9rz8dWW+2/tRdiq/X7b+3FWGqHj/hv7aVYaof5qP0ultohPmovx1I7wEftlVhqe/iovRpLbZiP2mux1FbzUXs9llo/H7U3fNduHuGj9nvftZt81d70XbvBV+0t37VrfNX+4Lt2ma/aH33XzvZVe9t3bV9ftXd815bzVfuTz9qaW3zV/uyztobP2rs+a6v5rL3ns/Yjn7X3fdaW9Vn7i8/afD5rf/VZm8Bn7W++apsc9ln7wGdtLZ+1D33VNvZd+8hXbUPftY991db1XfvEV21V37VPfdWW8F37u6/aVL5r//BRu/WM79pnvmqb+q7900ftllhqn/uo3RRL7QsftetiqX3po3ZFLLV/+aidE0vt3z5q+8dS+8pHbflYal//t7bgtlhq3/y3tkBstW//W5svtlr298xi1OaOrdbvv7WZY6t957+1SWKrjfef2oX3Y6uN/9/albHVJvhvbaHYahP+p3ZBrLWJ/lM7L9baxP+pnRNrbZL/1E6LtTbpf2qHx1qb7D+13lhrk/+nNleste/GrC3xRay1KWLWFo+9NmXM2qKx16aKWVso9trUMWtzx16bJmZt6thr08aovfUk9tp0MWvXx16bPmZtydhrM8SovSmozRij9oagNlOM2iuC2swxas8KarPEqN0vqM0ao3aRoDZbjNowQW32f9f2+EFQm+Pftd1F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rMBKfIFVWI01WIt1WI8N2IhN2Iwt+BJbsQ2JLyKf+DreiS+lnPhqtokvKJr4mo6JL6uX+MpmiS8ulfj6PokvsZL4KheJLzSQ+FzviU+3nfiMx4lPOpv4vJ+JT72Y+Ox3iU9AlvgcUP98S/yZuX++JRffN7FHf7owx4afrH99S6nJMorv+1zrfGTlsnMN/p0lie8n9t649dqlNDv+neUQ34/c1KbWXVmXDv93lvicHYlvKzr2G1F8asN6/84Sv38m8e3QqmQVJ+ccJH35vU0Zbzx3MduN5/rnvPHcBOfGc1kL3niuUskbz20s/Z/vVTfbIjLVzbZrst2a7IAmO6XJrpe78X45q994v1yabE6tG3/MVY1uPLdakzVsduOP2bPdjed6abJLt9/4Y2bscuO5TJpsbtf/fK/6675AZKq/Dos12RJNtlSTfabJtne3brj7j31vvN9lTTZswI0/5vThN56bocnyjLjxx6w15sZztTXZurE3/phnxt947qwm6z/xP9+nSnWha8VDQ079OxuiyR7WZI9rstGa7BlN9oImm6jJpmqymZpsniZ7VZO9qcne1WQfaLJPNNlKTbZWk23SZNs02U5Ntk+THdZkJzTZWU12UZP9oMmuabJfNdlfmizFpBtnaTVZJk2WRZPdrMnyaLJ8mqywJiuhycpqskqarLomq6PJGmqyZpqstSbroMk6abIumqy7JuutyfppssGabLgme0yTPanJxmqy5zXZBE32siZ7RZPN1WSLNNkbmuwdTfa+JvtYk63QZGs02UZNtlWT7dBkezXZIU12XJOd0WTfaLLvNdlVTfaLJvtTkyWffOMsjSbLqMlsTZZDk92iyRxNVkiTFddkZTRZRU1WTZPV1mQNNFlTTdZKk7XXZHdqsns0WTdN1kuTPajJBmmyYZpshCZ7QpM9rcme02QvabIpmmyGJpujyRZqstc12duabJkmW67JPtdkqzXZBk32pSb7WpPt0WQHNdkxTXZak13QZN9psiua7GdN9ocmSzblxllqTZZBkyVpsuyaLLcmy6vJCmqyYpqstCaroMmqarJamqy+JmuiyVpqsnaarKMm66zJ7tNkPTVZX002UJMN1WSParJRmuwpTTZOk43XZJM12XRNNluTLdBkizXZEk22VJN9pMk+02SrNNl6TbZFk23XZLs12QFNdlSTndJk5zXZt5rssia7rsl+12T/84nrb5Cl0mTpNVlmTZZNk+XSZLdpsgKarKgmK6XJymuyKpqspiarp8kaa7IWmqytJrtDk92tybpqsh6arI8mG6DJHtJkj2iykZpsjCZ7VpO9qMkmabJpmmyWJpuvyV7TZG9psvc02Yea7FNN9oUmW6fJNmuyrzTZLk22X5Md0WQnNdk5TXZJk/2oyX7SZL9psr81WcqpN87SabKbNFlWTZZTk92qyfJrsiKarKQmK6fJKmuyGpqsriZrpMmaa7I2mux2TXaXJrtXk92vyR7QZP012RBN9rAme1yTjdZkz2iyFzTZRE02VZPN1GTzNNmrmuxNTfauJvtAk32iyVZqsrWabJMm26bJdmqyfZrssCY7ocnOarKLmuwHTXZNk/2qyf7SZCmm3ThLq8kyabIsmuxmTZZHk+XTZIU1WQlNVlaTVdJk1TVZHU3WUJM102StNVkHTdZJk3XRZN01WW9N1k+TDdZkwzXZY5rsSU02VpM9r8kmaLKXNdkrmmyuJlukyd7QZO9osvc12ceabIUmW6PJNmqyrZpshybbq8kOabLjmuyMJvtGk32vya5qsl802Z+aLPn0G2dpNFlGTWZrshya7BZN5miyQpqsuCYro8kqarJqmqy2JmugyZpqslaarL0mu1OT3aPJummyXprsQU02SJMN02QjNNkTmuxpTfacJntJk03RZDM02RxNtlCTva7J3tZkyzTZck32uSZbrck2aLIvNdnXmmyPJjuoyY5pstOa7IIm+06TXdFkP2uyPzRZshk3zlJrsgyaLEmTZddkuTVZXk1WUJMV02SlNVkFTVZVk9XSZPU1WRNN1lKTtdNkHTVZZ012nybrqcn6arKBmmyoJntUk43SZE9psnGabLwmm6zJpmuy2ZpsgSZbrMmWaLKlmuwjTfaZJlulydZrsi2abLsm263JDmiyo5rslCY7r8m+1WSXNdl1Tfa7JvufL1J9gyyVJkuvyTJrsmyaLJcmu02TFdBkRTVZKU1WXpNV0WQ1NVk9TdZYk7XQZG012R2a7G5N1lWT9dBkfTTZAE32kCZ7RJON1GRjNNmzmuxFTTZJk03TZLM02XxN9pome0uTvafJPtRkn2qyLzTZOk22WZN9pcl2abL9muyIJjupyc5pskua7EdN9pMm+02T/a3JUs68cZZOk92kybJqspya7FZNll+TFdFkJTVZOU1WWZPV0GR1NVkjTdZck7XRZLdrsrs02b2a7H5N9oAm66/JhmiyhzXZ45pstCZ7RpO9oMkmarKpmmymJpunyV7VZG9qsnc12Qea7BNNtlKTrdVkmzTZNk22U5Pt02SHNdkJTXZWk13UZD9osmua7FdN9pcmSzHrxllaTZZJk2XRZDdrsjyaLJ8mK6zJSmiyspqskiarrsnqaLKGmqyZJmutyTposk6arIsm667JemuyfppssCYbrske02RParKxmux5TTZBk72syV7RZHM12SJN9oYme0eTva/JPtZkKzTZGk22UZNt1WQ7NNleTXZIkx3XZGc02Tea7HtNdlWT/aLJ/tRkyWffOEujyTJqMluT5dBkt2gyR5MV0mTFNVkZTVZRk1XTZLU1WQNN1lSTtdJk7TXZnZrsHk3WTZP10mQParJBmmyYJhuhyZ7QZE9rsuc02UuabIomm6HJ5miyhZrsdU32tiZbpsmWa7LPNdlqTbZBk32pyb7WZHs02UFNdkyTndZkFzTZd5rsiib7WZP9ocmSzblxllqTZdBkSZosuybLrcnyarKCmqyYJiutySposqqarJYmq6/JmmiylpqsnSbrqMk6a7L7NFlPTdZXkw3UZEM12aOabJQme0qTjdNk4zXZZE02XZPN1mQLNNliTbZEky3VZB9pss802SpNtl6TbdFk2zXZbk12QJMd1WSnNNl5TfatJrusya5rst81mTX3xlkqTZZek2XWZNk0WS5NdpsmK6DJimqyUpqsvCaroslqarJ6mqyxJmuhydpqsjs02d2arKsm66HJ+miyAZrsIU32iCYbqcnGaLJnNdmLmmySJpumyWZpsvma7DVN9pYme0+TfajJPtVkX2iydZpssyb7SpPt0mT7NdkRTXZSk53TZJc02Y+a7CdN9psm+1uTpZx34yydJrtJk2XVZDk12a2aLL8mK6LJSmqycpqssiarocnqarJGmqy5JmujyW7XZHdpsns12f2a7AFN1l+TDdFkD2uyxzXZaE32jCZ7QZNN1GRTNdlMTTZPk72qyd7UZO9qsg802SeabKUmW6vJNmmybZpspybbp8kOa7ITmuysJruoyX7QZNc02a+a7C9NlmL+jbO0miyTJsuiyW7WZHk0WT5NVliTldBkZTVZJU1WXZPV0WQNNVkzTdZak3XQZJ00WRdN1l2T9dZk/TTZYE02XJM9psme1GRjNdnzmmyCJntZk72iyeZqskWa7A1N9o4me1+TfazJVmiyNZpsoybbqsl2aLK9muyQJjuuyc5osm802fea7Kom+0WT/anJki+4cZZGk2XUZLYmy6HJbtFkjiYrpMmKa7IymqyiJqumyWprsgaarKkma6XJ2muyOzXZPZqsmybrpcke1GSDNNkwTTZCkz2hyZ7WZM9pspc02RRNNkOTzdFkCzXZ65rsbU22TJMt12Sfa7LVmmyDJvtSk32tyfZosoOa7JgmO63JLmiy7zTZFU32syb7Q5MlW3jjLLUmy6DJkjRZdk2WW5Pl1WQFNVkxTVZak1XQZFU1WS1NVl+TNdFkLTVZO03WUZN11mT3abKemqyvJhuoyYZqskc12ShN9pQmG6fJxmuyyZpsuiabrckWaLLFmmyJJluqyT7SZJ9pslWabL0m26LJtmuy3ZrsgCY7qslOabLzmuxbTXZZk13XZL9rMmvRjbNUmiy9JsusybJpslya7DZNVkCTFdVkpTRZeU1WRZPV1GT1NFljTdZCk7XVZHdosrs1WVdN1kOT9dFkAzTZQ5rsEU02UpON0WTParIXNdkkTTZNk83SZPM12Wua7C1N9p4m+1CTfarJvtBk6zTZZk32lSbbpcn2a7IjmuykJjunyS5psh812WWR7dy7ecbU5c3G/fPPpxDf//N1KHv0GdLz/qF9hvfs2mfA8J5DhoovJWmlFd9nF98nE7OOFehbsn/ms/1381ZqxT+X/V/vfz7uPz9P8n9ljmX27Z+bpFJk/3zclJ4fm9bzfTLL+OdPdqNfRzLFD84ivs/2r38uuydz/1oOHdh1SLcefRJfgFb6Vab6189g8lfjn/nU/938/25Dmv9uPoWqDWn+9f5nL9UFk3l+zn9+Len+u19L+mSKnz+F52N6fw3//jEprf/zW3LPP07p+edTBPixqtb8k2VW/Pq8c+kUv9Z//3P//DXIaP2f37x3/3ffVB8rjefX4O3H/+1foyyKn/OfX1tu8f2//51vaM/ePYd0HTxs4NA+PQcM9f5rO/1/96tI/s98hv9uXvnvgen/9c7g/QnF96qGJbvBP07u+V73Y5NpPq6qFf98zH/+avz71/vPHv8LzDwzOwPzXQA=","debug_symbols":"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5y4/d/m5y89dfu7yc5efu/zc5ecuPw/5ecjPQ34e8vOQn4f8POTnIT8P+XnIz0N+HvLzkJ+H/Dzk5yE/D/l5yM9Dfh7y85Cfh/w85OchPw/5ecjPQ34e8vOQn4f8POTnIT8P+XnIz0N+HvLzkJ+H/Dzk5yE/D/l5yM9Dfh7y85Cfh/w85OchPw/5ecjPQ34e8vOQn4f8POTnIT8P+XnIz0N+HvLzkJ+H/Dzk5yE/D/l5yM9Dfh7y85Cfh/w85OchPw/5ecjPQ34e8vOQn4f8POTnIT8P+XnIz0N+HvLzkJ+H/Dzk5yE/D/l5yM9Dfh7y85Cfh/w85OchPw/5ecjPQ34e8vOUn6f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT8v+XnJz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzlp+3/Lzl5y0/b/l5y89bft7y85aft/y85ectP2/5ecvPW37e8vOWn7f8vOXnLT9v+XnLz1t+3vLzlp+3/Lzl5y0/b/l5y89bft7y85aft/y85ectP2/5ecvPW37e8vOWn7f8vOXnLT9v+XnLz1t+3vLzlp+3/Lzl5y0/b/l5y89bft7y85aft/y85ectP2/5ecvPW37e8vOWn7f8vOXnLT9v+XnL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Og/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzkM5DOg/pPKTzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzlM5TOk/pPKXzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzks5LOi/pvKTzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzls5bOm/pvKXzkc5HOh/pfKTzkc5HOh/pfKTzkc5HOh/pfKTzkc5HOh/pfKTzkc5HOh/pfKTzkc5HOh/pfKTzkc5HOh/pfKTzkc5HOh/pfKTzkc5H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yM9Dfh7y85Cfh/w85OchPw/5ecjPQ34e8vOQn4f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT9P+XnKz1N+nvLzlJ+n/Dzl5yk/T/l5ys9Tfp7y85Sfp/w85ecpP0/5ecrPU36e8vOUn6f8POXnKT9P+XnKz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzkp+X/Lzk5yU/L/l5yc9Lfl7y85Kfl/y85OclPy/5ecnPS35e8vOSn5f8vOTnJT8v+XnJz0t+XvLzkp+X/Lzl5y0/b/l5y89bft7y85aft/y85ectP2/5ecvPW37e8vOWn7f8vOXnLT9v+XnLz1t+3vLzlp+3/Lzl5y0/b/l5y89bft7y85aft/y85ectP2/5ecvPW37e8vOWn7f8vOXnLT9v+XnLz1t+3vLzlp+3/Lzl5y0/b/l5y89bft7y85aft/y85ectP2/5ecvPW37e8vOWn7f8vOXnLT9v+XnLz1t+3vLzlp+3/Lzl5y0/b/l5y89bft7y85aft/y85ectP2/5ecvPW37e8vOWn7f8vOXnLT9v+XnLz1t+3vLzlp+3/Lzl5y0/b/l5y89Hfj7y85Gfj/x85OcjPx/5+cjPR34+8vORn4/8fOTnIz8f+fnIz0d+PvLzkZ+P/Hzk5yM/H/n5yM9Hfj7y85Gfj/x85OcjPx/5+cjPR34+8vORn4/8fOTnIz8f+fnIz0d+PvLzkZ+P/Hzk5yM/H/n5yM9Hfj7y85Gfj/x85OcjPx/5+cjPR34+8vORn4/8fOTnIz8f+fnIz0d+PvLz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85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOUzpP6Tyl85TOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOSzov6byk85LOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bOWzpv6byl85bORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6Xyk85HORzof6fxzX6q/q197PC97l0lZlP1Txrucb5nvobhbPpSH0iidMiiTsiibkt0ednvY7WG3h90ednvY7WG3h90ednvY7bDbYbfDbofdDrsddjvsdtjtsNthN2M3YzdjN2M3YzdjN2M3YzdjN2M3ZzdnN2c3ZzdnN2c3ZzdnN2c3Z7dgt2C3YLdgt2C3YLdgt2C3YLdgt2S3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lwS5JMglQS4JckmQS4JcEuSSIJcEuSTIJUEuCXJJkEuCXBLkkiCXBLkkyCVBLglySZBLglwS5JIglwS5JMglQS4JckmQS4JcEuSSIJcEuSTIJUEuCXJJkEuCXBLkkiCXBLkkyCVBLglySZBLglwS5JIklyS5JMklSS5JckmSS5JckuSSJJckuSTJJUkuSXJJkkuSXJLkkiSXJLkkySVJLklySZJLklyS5JIklyS5JMklSS5JckmSS5JckuSSJJckuSTJJUkuSXJJkkuSXJLkkiSXJLkkySVJLklySZJLklyS5JIklyS5JMklSS5JckmSS5JckuSSJJckuSTJJUkuSXJJkkuSXJLkkiSXJLkkySVJLklySZJLklyS5JIklyS5JMklSS5JckmSS5JckuSSJJckuSTJJUkuSXJJkkuSXJLkkiSXJLkkySVJLklySZJLklyS5JIklyS5JMklSS4pckmRS4pcUuSSIpcUuaTIJUUuKXJJkUuKXFLkkiKXFLmkyCVFLilySZFLilxS5JIilxS5pMglRS4pckmRS4pcUuSSIpcUuaTIJUUuKXJJkUuKXFLkkiKXFLmkyCVFLilySZFLilxS5JIilxS5pMglRS4pckmRS4pcUuSSIpcUuaTIJUUuKXJJkUuKXFLkkiKXFLmkyCVFLilySZFLilxS5JIilxS5pMglRS4pckmRS4pcUuSSIpcUuaTIJUUuKXJJkUuKXFLkkiKXFLmkyCVFLilySZFLilxS5JIilxS5pMglRS4pckmRS4pcUuSSJpc0uaTJJU0uaXJJk0uaXNLkkiaXNLmkySVNLmlySZNLmlzS5JImlzS5pMklTS5pckmTS5pc0uSSJpc0uaTJJU0uaXJJk0uaXNLkkiaXNLmkySVNLmlySZNLmlzS5JImlzS5pMklTS5pckmTS5pc0uSSJpc0uaTJJU0uaXJJk0uaXNLkkiaXNLmkySVNLmlySZNLmlzS5JImlzS5pMklTS5pckmTS5pc0uSSJpc0uaTJJU0uaXJJk0uaXNLkkiaXNLmkySVNLmlySZNLmlzS5JImlzS5pMklTS5pckmTS5pc0uSSJpc0uaTJJU0uGXLJkEuGXDLkkiGXDLlkyCVDLhlyyZBLhlwy5JIhlwy5ZMglQy4ZcsmQS4ZcMuSSIZcMuWTIJUMuGXLJkEuGXDLkkiGXDLlkyCVD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W9Pf7y+Z/da11uxV09/PwO2t6e9n5PbW9Pf7y2a/Nf39jN3eutaavWr6+xm9vTX9/f7S2W9Nfz/jt7emv58B3FvXWrNXvfrrq7+++uurv77666u/vvrrq7+++uurv776G6u/sfobq7+x+hurv7H6G6u/sfobq7+x+purv7n6m6u/ufqbq7+5+purv7n6m6u/ufpbq7+1+lurv7X6W6u/tfpbq7+1+lurv7X626u/vfrbq7+9+turv73626u/vfrbq7+9+jurv7P6O6u/s/o7q7+z+jurv7P6O6u/Q38/A7y3pr+fEd5b09/vL6/91vT3M8Z761pr9qrp72eU99b09/tLbL81/f2M896a/n4Gem9da81eNf39/jLbb01/P2O9t6a/n8HeW9Pfz2jvrWut2aumv5/x3lvT38+A763p72fE99b09/vLbb91rTV71au/vvq78tVZ+eqsfHVWvjorX52Vr87KV2flq7Py1Vn56qx8dVa+OitfnZWvzspXZ+Wrs/LVWfnqrHx1Vr46K1+dla/Oyldn5auz8tVZ+eqsfHVWvjorX52Vr87KV2flq7Py1Vn56qx8dVa+OitfnZWvzspXZ+Wrs/LVWfnqrHx1Vr46K1+dla/Oyldn5auz8tVZ+eqsfHVWvjorX52Vr87KV2flq7Py1Vn56qx8ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXxlK1/Zyle28pWtfGUrX9nKV7byla18ZStf2cpXtvKVrXzlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfOUrX/nKV77yla985Stf+cpXvvKVr3zlK1/5yle+8pWvfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8FStfxcpXsfJVrHwVK1/Fylex8lWsfBUrX8XKV7HyVax8lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnyVK1/lyle58lWufJUrX+XKV7nyVa58lStf5cpXufJVrnxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfFUrX9XKV7XyVa18VStf1cpXtfJVrXxVK1/Vyle18lWtfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa981Stf9cpXvfJVr3zVK1/1yle98lWvfNUrX/XKV73yVa98NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVrHw1K1/Nylez8tWsfDUrX83KV7Py1ax8NStfzcpXs/LVkK+eF/nqeZGvnhf56nmRr54X+ep5ka+eF/nqeZGvnhf56nmRr54X+ep5ka+eF/nqeZGvnhf56nmRr54X+ep5ka+eF/nqeZGvnhf56nmRr54X+ep5ka+eF/nqeZGvnhf56nmRr54X+ep5ka+eF/nqeZGvnhf56nmRr54X+ep5ka+eF/nqeZGvnjXf/qz59uflq7+++uurv77666u/vvrrq7+++uurv776G6u/sfobq7+x+hurv7H6G6u/sfobq7+x+purv7n6m6u/ufqbq7+5+purv7n6m6u/ufpbq7+1+lurv7X6W6u/tfpbq7+1+lurv7X626u/vfrbq7+9+turv73626u/vfrbq7+9+jurv7P6O6u/s/o7q7+z+jurv7P6O6u/5Ktnzbc/a779WfPtz5pvf9Z8+7Pm25813/6s+fZnzbc/a779WfPtz5pvf9Z8+7Pm25813/6s+fZnzbf/+n+11uxV09813/6s+fZnzbc/a779WfPtz5pv/1Xnqmut2aumv2u+/Vnz7c+ab3/WfPuz5tufNd/+rPn2Z823/6p71au/vvrrq7+++uurv77666u/vvrrq7+++uurv7H6G6u/sfobq7+x+hurv7H6G6u/sfobq7+5+purv7n6m6u/ufqbq7+5+purv7n6m6u/tfpbq7+1+lurv7X6W6u/tfpbq7+1+lurv73626u/vfrbq7+9+turv73626u/vfrbq7+z+jurv7P6O6u/s/o7q7+z+jurv7P6u/LVmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbnzXf/qz59mfNtz9rvv1Z8+3Pmm9/1nz7s+bbn898u59PnauuVf/s+3PT00/9s6/7u/5cJPZZ/3OT2Ofvf64S+/z9z11i39rX349V5/o7tepef2eoP1eKff7O506xb33W37FV+/o7sepcf6dWvc77uVvsU/s67+d2sW+9zuvrvL7O6+u8vs7r67y+zuvrvLHOG+u8n4vGvn9nnTfWeWOdN9Z5Y5031nljnTfXeXOd93Pl2PfvrPPmOm+u8+Y6b67z5jpvrvPWOm+t89Y6b63z1jpvrfPWOm+t89Y6b63z9jpvr/P2Om+v8/Y6b6/z9jpvr/P2Om+v884676zzzjrvrPPOOu+s884676zzzjrvcN7PfPvn73zm22991t+xVfv6O7HqXH+nVt3r73Dez3z79+88z6rP+ju2al9/J1ad6+/Uqnv9nXXexavPfPut13kXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF6988coXr3zxyhevfPHKF69i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavYvEqFq9i8SoWr2LxKhavcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr3LxKhevcvEqF69y8SoXr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq9q8aoWr2rxqhavavGqFq968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevevGqF6968aoXr3rxqhevZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWr2bxahavZvFqFq9m8WoWrz7z7Z9/233Pt7u9yx9c3fKh/LVpfSpT5ap+bfdZ9AdS36pU/Wz0+V4+v5H9XX5+I/unfCgPpVG+/yn/U/6cLL//51x1rfr9L+qfclS+uZSfVd5cuvVZ9fvf8T+lU773/K6Sq65V/+zpn3JUfpj0KR/KQ2mUTvne8FMmZVE25XzL85lcr0/5UB5Ko3TKX7u95wbOe2bdvmVR3ud5vgPr7/LNH/uUz/fE5zOt/vl2fuDj8SmdMiiTsiibclT+UOeWD+WhZLfDbofdDrsddjvsdtjN2M3YzdjN2M3YzdjN2M3YzdjN2M3ZzdnN2c3ZzdnN2c3ZzdnN2c3ZLdgt2C3YLdgt2C3YLdgt2C3YLdgt2S3ZLdkt2S3ZLdkt2S3ZLdkt2a3Yrdit2K3Yrdit2K3Yrdit2K3Yrdmt2a3Zrdmt2a3Zrdmt2a3Zrdlt2G3Ybdht2G3Ybdht2G3YbdhttNt7qvyWD+WhNEqnDMqkLMqmZLeH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qxS/SrkfTOFVCq9S7gdT/CrFr1L8KsWvUniVwquU+8GU+8GU+8GU+8EUXn3y7ef51CX1X1/7nP/Lq/PZ6csr//zuyyv77Ovl1a82qZ3rvLz61ck1X1796pbrj9TLNVv6vrz6XvPl1a92rvny6lcn13x59atbrjlSL9d8efWrD9d8efWrnWu+vPrVyTVfXv1qOeeXV796uebLq199uObLq1/tXPPl1a9Orvny6le3XFP2u+z3k2//1ez3k2//1ez3k2//1ez3k2//1S3XHKnZ7yff/qvZ7yff/qvZ7yff/qvZ7yff/qtbrjlSs99Pvv1Xs99Pvv1Xs99Pvv1Xs99Pvv1Xt1xzpGa/n3z7r2a/n3z7r2a/n3z7r2a/n3z7r2655kgt+w3Zb8h+Q/Ybst+Q/YbsN2S/IfsN2W/IflP2m7LflP2m7Ddlvyn7Tdlvyn5T9puy35L9luy3ZL8l+y3Zb8l+S/Zbst+S/Zbst2W/Lftt2W/Lflv227Lflv227Ldlvy37HdnvyH5H9juy35H9jux3ZL8j+x3Z78h+V/a7st+V/a7sd2W/K/td2e/Kflf2u+z3k2//1ez3k2//1ez3k2//1ez3k2//1S3XHKnZ7yff/qvZ7yff/qvZ7yff/qvZ7yff/qtbrjlSs99Pvv1Xs99Pvv1Xs99Pvv1Xs99Pvv1Xt1xzpGa/n3z7r2a/n3z7r2a/n3z7r2a/n3z7r2655kgt+w3Zb8h+Q/Ybst+Q/YbsN2S/IfsN2W/IflP2m7LflP2m7Ddlvyn7Tdlvyn7Fr1r86pNv/9WyX/GrFr9q8asWv2rxqxa/avGrFr9q8asWv2rxqxa/avGrFr9q8asWv2rxqxa/avGrFr9q8asWv2rxqxa/avGrFr9q8asWv2rxqxa/avGrFr9q8asWv2rxqxa/avGrFr8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/GvGrEb8a8asRvxrxqxG/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8asVv1rxqxW/WvGrFb9a8au9fmXPc/3qr/7t9682qX/7/atD6t9+/+qSuuWaI/VyzetXf/Xhmtev/mrnmtev/urkmtev/uqWa47UyzWvX/3Vh2tev/qrnWtev/qrk2tev/qrW645Ui/XvH71Vx+uef3qr3auef3qr06uef3qr2655kgt+w3Zb8h+Q/Ybst+Q/YbsN2S/IfsN2W/IflP2m7LflP2m7Ddlvyn7Tdlvyn5T9puy35L9luy3ZL8l+y3Zb8l+S/Zbst+S/Zbst2W/Lftt2W/Lflv227Lflv227Ldlvy37HdnvyH5H9juy35H9jux3ZL8j+x3Z78h+V/a7st+V/a7sd2W/K/td2e/Kflf2u+z3PI/U7Pc8JjX7PU9IzX7PU1K3XHOkZr/nPFKz33NMavZ7TkjNfs8pqVuuOVKz32OP1Oz3mEnNfo+F1Oz3WEndcs2Rmv0ef6Rmv8dNavZ7PKRmv8dL6pZrjtSy35D9huw3ZL8h+w3Zb8h+Q/Ybst+Q/YbsN2W/KftN2W/KflP2m7LflP2m7Ddlvyn7LdlvyX5L9luy35L9luy3ZL8l+y3Zb8l+W/bbst+W/bbst2W/Lftt2W/Lflv227Lfkf2O7HdkvyP7HdnvyH5H9juy35H9jux3Zb8r+13Z78p+V/a7st+V/a7sd2W/4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXJn5l4lcmfmXiVyZ+ZeJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVy5+5eJXLn7l4lcufuXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lchfhXiVyF+FeJXIX4V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXKX6V4lcpfpXiVyl+leJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVyV+VeJXJX5V4lclflXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lctftXiVy1+1eJXLX7V4lcjfjXiVyN+NeJXI3414lcjfjXiVyN+NeJXI3414lcjfjXiVyN+NeJXI3414lcjfjXiVyN+NeJXI3414lcjfjXiVyN+NeJXI3414lcjfjXiVyN+NeJXI371ybeHfeqSuqUeqf/65vPWL68iPvVf3/z0enmVn59/efX7+ZA65edL6pafGamXn3l59asPP/Py6le7/ExInfIzJXXLz4zUMu/Lq18t8768+tUyb8m8JfOWzFsyb8m8JfO2zNsyb8u8LfO2zNsyb8u8LfO2zNsy78i8I/OOzDsy78i8I/OOzDsy78i8I/OuzLsy78q8K/OuzLsy78q8K/OuzLvM+8m3/2rm/eTbf7XLz4TUKT9TUrf8zEjNvJ98+69m3k++/Ve7/ExInfIzJXXLz4zUMq/JvCbzmsxrMq/JvCbzmsxrMq/JvCbzuszrMq/LvC7zuszrMq/LvC7zuswrvPrk23+1zBsyr/BqhVcrvFrh1QqvVni1wqsVXq3waoVXK7xa4dUKr1Z4tcKrFV6t8GqFVyu8WuHVCq9WeLXCqxVerfBqhVcr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VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX4X4VYhfhfhViF+F+FWIX6X4VYpfpfhVil+l+FWKX6X4VYpfpfhVil+l+FWKX6X4VYpfpfhVil+l+FWKX6X4VYpfpfhVil+l+FWKX6X4VYpfpfhVil+l+FWKX6X4VYpfpfhVil+l+FWKX6X4VYpfpfhVil+l+JXk213y7Z7iV5Jvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75dpd8u0u+3SXf7pJvd8m3u+TbXfLtLvl2l3y7S77dJd/ukm93ybe75Ntd8u0u+XaXfLtLvt0l3+6Sb3fJt7vk213y7S75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vCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTwksJLCi8pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvKTxksZLGi9pvGTwksFLBi8ZvGTwksFLBi8ZvGTwksFLBi8ZvGTwksFLBi8Z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bMFJ3u9L9glmC2YLPiXJSSbdkm7J3pLZktmST0nSLemWdCu6Fd2KbkW3olvRrehWdCu6Fd2abk23plvTrenWdHtZ4p+yKef7EKZ9c6/5Ke9z1fbNvc5nF38s6W/plEGZ92L3uWr75l5/FxvKvde9z1XbN/f6vdjS7Y8l34vd56rtm3v9Xuw+V23f3OvvYkO5v4vxvNd9c6+fi/G8131zr/ktgzJ/F+N5r/vmXn8XG8q9F7vPVds39/q92H2u2r651+/F7nPV9s29fi92n6u2b+71d7GhvHvjea/75l6/F7vPVds39/q92H2u2r651+/F7nPV9s29/i42lHdvPO9139zr92L3uWr75l6/F7vPVds39/q92H2u2r6519/FhpK9BXsL9hbsLdhbsLdgb8Hegr0Fewv2luwt2Vuyt2Rvyd6SvSV7S/aW7C3ZW7G3Ym/F3oq9FXsr9lbsrdhbsbdib83emr01e2v21uyt2Vuzt2Zvzd6avQ17G/Y27G3Y27C3YW/D3oa9DXsb9rbsbdnbsrdlb8velr0te1v2tuxt79543uu+udfPxXje67651/6WQXn3xvNe9829/i42lHdvPO9139zr92L3ea/75l6/F7vPe9039/q92H3e676519/FhvLujee97pt7/V7sPu9139zr92L3ea/75l6/F7vPe9039/q72FDevfG8131zr9+L3ee97pt7/V7sPu9139zr92L3ea/75l5/FxtK9hbsLdhbsLdgb8Hegr0Fewv2Fuwt2Fuyt2Rvyd6SvSV7S/aW7C3ZW7K3ZG/F3oq9FXsr9lbsrdhbsbdib8Xeir01e2v21uyt2Vuzt2Zvzd6aveElhpfwvNc1vITnva7hJTzvdQ0v4Xmva3gJz3tdw0t43usaXsLzXtfwEp73uoaX8LzXNbyE572u4SU873UdL+F5r+t4Cc97XcdLeN7rOl7C817X8RKe97qOl/C813W8hOe9ruMlPO91HS/hea/reAnPe13HS3je6zpewvNe1/ESnve6jpfwvNd1vITnva7jJTzvdR0v4Xmv63gJz3tdx0t43us6XsLzXtfxEp73uo6X8LzXdbyE572u4yU873UdL+F5r+t4Cc97XcdLeN7rOl7C817X8RKe97qOl/C813W8hOe9ruMlPO91HS/hea/reAnPe13HS3je6zpewvNe1/ESx0scL3G8xPESx0scL3G8xPESx0scL3G8xPESx0scL3G8xPESx0scL3G8xPESx0scL3G8xPESx0scLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCLwm8JPCSwEsCL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSL0m8JPGSxEsSLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwksKLym8pPCSwkv+NXVvO5I2zWGd70XHPujITWSE78UQJJo2CBCiQEsGDIP3rn+mujuesxTVU/FlxXBxvTUL1TlekuMlOV6S4yU5XpLjJTlekuMlOV6S4yU5XpLjJTlekuMlOV6S4yU5XpLjJTlekuMlOV6S4yU5XpLjJTlekuMlOV6S4yU5XpLjJTlekuMlOV6S4yU5XpLjJTlekuMlOV6S4yU5XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlb7zkjZe88ZI3XvLGS954yRsveeMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJTVeUuMlNV5S4yU1XlLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7S4yU9XtLjJT1e0uMlPV7SP17yj38R/vGSP8fvvf05rjl+7+3P8czxe29/jjnHNy9Wc+zfF/vxkj/H+H2xHy/5c9y/L/bjJX+O9/fFfrzkz/HNi9Uc+/fFfrzkzzF+X+zHS/4c9++L/XjJn+P9fbEfL/lzfPNiNcf+fbEfL/lzjN8X+/GSP8f9+2I/XvLneH9f7MdL/hzfvFjNcfZ2Zm9n9nZmb2f2dmZvZ/Z2Zm9n9nZmb2f2dmdvd/Z2Z2939nZnb3f2dmdvd/Z2Z2939pazt5y95ewtZ285e8vZW87ecvaWs7ecvb3Z25u9vdnbm7292dubvb3Z25u9vdnbm73V7K1mbzV7q9lbzd5q9lazt5q91eytZm89e+vZW8/eevbWs7eevfXsrWdvPXvr3739dq9/jr97++1e/xx/9/bbvf45/u7tt3v9c3zzYjXH3739dq9/jr97++1e/xx/9/bbvf45/u7tt3v9c3zzYjXH3739dq9/jr97++1e/xx/9/bbvf45/u7tt3v9c3zzYjXH3739dq9/jr97++1e/xx/9/bbvf45/u7tt3v9c3zzYjXH2duZvZ3Z25m9ndnbmb2d2duZvZ3Z25m9ndnbnb3d2dudvd3Z25293dnbnb3d2dudvd3ZW87ecvaWs7ecveXsLWdvOXvL2VvO3nL29mZvb/b2Zm9v9vZmb2/29mZvb/b2Zm9v9lazt5q91eytZm81e6vZW83eavZWs7eavfXsrWdvPXvr2VvP3nr21rO3nr317G28ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkvWeMkaL1njJWu8ZI2XrPGSNV6yxkv2eMkeL9njJXu8ZI+X7PGSPV6yx0v2eMkeL9njJXu8ZI+X7PGSPV6yx0v2eMkeL9njJXu8ZI+X7PGSPV6yx0v2eMkeL9njJXu8ZI+X7PGSPV6yx0v2eMkeL9njJXu8ZI+X7PGSPV6yx0v2eMkeL9njJXu8ZI+X7PGSPV6yx0v2eMkeL9njJXu8ZI+X7PGSPV6yx0v2eMnf7rXO51hz7N/jH5b8HOPzi03+HNfnt5n8Oe7PbzP5czzzA3eOOT/75ljzA/17/Pv7cT4/8PP7cf4c1/zAnuOZH7hzzPmBN8eaH+jf49/fj/P5gZq71dzt5/fj/DnO3WruVnO3mrvV3K3mbj1367lbz9167tZzt5679dyt5249d+vfu/3tXj8/cL5ijmt+YM/xzA/cOeb8wJtjzQ/83u1v9/r9AxFzXPMDe45nfuDOMecH3hxrfmDutuZua+625m5r7rbmbmvutuZua+625m5r7rbnbnvutudue+6252577rbnbnvutudue+525m5n7nbmbmfuduZuZ+525m5n7nbmbmfududud+5252537nbnbnfududud+5252537pZzt2HJGZacnLsNS86w5AxLzrDkDEvOsOQMS86w5AxLzrDkDEvOsOQMS86w5AxLzrDkDEvOsOQMS86w5AxLzrDkDEvOsOQMS86w5AxLzrDkDEvOsOQMS86w5AxLzrDkDEvOsOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rDkDkvusOQOS+6w5A5L7rAkhyU5LMlhSQ5LcliSw5IcluSwJIclOSzJYUkOS3JYksOSHJbksCSHJTksyWFJDktyWJLDkhyW5LAkhyU5LMlhSQ5LcliSw5IcluSwJIclOSzJYUkOS3JYksOSHJbksCSHJTksyWFJDktyWJLDkhyW5LAkhyU5LMlhSQ5LcliSw5IcluSwJIclOSzJYUkOS3JYksOSHJbksCSHJTksyWFJDktyWJLDkhyW5LAkhyU5LMlhSQ5LcliSw5IcluSwJIclOSzJYUkOS3JYksOSHJbksCSHJTksyWFJDktyWJLDkhyW5LAkhyU5LMlhSQ5L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS96w5A1L3rDkDUvesOQNS2pYUsOSGpbUsKSGJTUsqWFJDUtqWFLDkhqW1LCkhiU1LKlhSQ1LalhSw5IaltSwpIYlNSypYUkNS2pYUsOSGpbUsKSGJTUsqWFJDUtqWFLDkhqW1LCkhiU1LKlhSQ1LalhSw5IaltSwpIYlNSypYUkNS2pYUsOSGpbUsKSGJTUsqWFJDUtqWFLDkhqW1LCkhiU1LKlhSQ1LalhSw5IaltSwpIYlNSypYUkNS2pYUsOSGpbUsKSGJTUsqWFJDUtqWFLDkhqW1LCkhiU1LKlhSQ1LalhSw5IaltSwpIYlNSypYUkNS2pYUsOSGpbUsKSHJT0s6WFJD0t6WNLDkh6W9LCkhyU9LOlhSQ9LeljSw5IelvSwpIclPSzpYUkPS3pY0sOSHpb0sKSHJT0s6WFJD0t6WNLDkh6W9LCkhyU9LOlhSQ9LeljSw5IelvSwpIclPSzpYUkPS3pY0sOSHpb0sKSHJT0s6WFJD0t6WNLDkh6W9LCkhyU9LOlhSQ9LeljSw5IelvSwpIclPSzpYUkPS3pY0sOSHpb0sKSHJT0s6WFJD0t6WNLDkh6W9LCkhyU9LOlhSQ9LeljSw5IelvSwpIclPSzpYUkPS3pY0sOSHpb0sKSHJT0s6WFJ/7Ik/navf/95Lf52r/G1P+fFeXM+f873c76ck/PjXJx7zn+g8nsOzovz5szcYG4wN5gbzA3mLuYu5i7mLuYu5i7mLuYu5i7mLuZu5m7mbuZu5m7mbuZu5m7mbuZu5h7mHuYe5h7mHuYe5h7mHuYe5h7mXuZe5l7mXuZe5l7mXuZe5l7mXuYmc5O5ydxkbjI3mZvMTeYmc5O5j7mPuY+5j7mPuY+5j7mPuY+5j7nF3GJuMbeYW8wt5hZzi7nF3GJuM7eZ28xt5jZzm7nN3GZuM7dn7t+09vccnBfnzflwvpyT8+NcnJkLrwJeBbwKeBXwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXgW8CngV8CrgVcCrgFcBrwJeBbwKeBXwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXgW8CngV8CrgVcCrgFcBrwJeBbwKeBXwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXgW8CngV8CrgVcCrgFcBrwJeBbwKeBXwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14teDVglcLXi14tT686s/579z3OW/Of+fW53w5J3/2cS7Of+fm3/OHV58/++HV93lx3pyZ+5j74dX3mbmPuR9efc4fXn3u8uHV95m5xdwPr77/7OXMfT+8+tzrw6vvP9tzbu7b3PfDq8/rfHj1fWbuh1ef12/u++HV95m5PXP31xfn2e/+Wpw35/M7a39d/mxyfpyL87zP+8Or7zNzY/5e7dicZ787mBvJn32ci3PP66wvzvM+77U4c991OF/OOe/D4r6L+y7e5837vLnv5n3ezP3w6vPf+eHV95n3eTN3c9/N+3x4n8/8fd6H9/nM3+d9eJ8P9z28z4f3+cOrz/twuO/lvpf3+fI+X+57eZ8vcy/v8+W+l/f5Mje5L7zayfsMr3byPsOrnbzP8GrDq528z4+/V4/3GV5teLUf933c9/E+v+HGftz3cd/ifS7eZ3i14dWGVxtebXi14dWGVxtebXi14dWGVxtebXi1m7/PH159n9kvvNo97/P5+uIcnNfvf/P5mvuer8P5ck7Oj3PxmsyFVydmvwdenWAuvDpx+bPJ+XGe/z06Me/zWV+cg/O8zwdeHXh11vzfhbO4L7w68OrAqwOvzmbuXpy57+a+m/tu7ru57+a+m7mHuYe5h/se7nu47+G+h/se7nu4L7w6l/1e/l5d5t7hxrmHM3+vLnMv9738vbr8vfrw6vPfnNw3eZ+T9zm5b/I+41fnw6vPf9uHV99n7otfncd9H/d9vM+P+77Lmfs+3mf86uBXp3ifP7z63B1eHXh1ir9XxftczC3mFnOLuc3cZm4zt5nbzG3e5+Z9bvbb/H3Gry5+db+C8+K8OR/Ol/PMvV+Pc3Eef77B3GBuMBdeXXh14dWFVxdeXXh14dWFVxdeXXh14dWFV3fN36u7kvPjdYrz7PfuL87Bef7vwoVXF17dzfsMry68uvjV3eOT93xx5r6H9xleXXh18at7xnMu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l/1e9nvZ72W/l/1e9nvZ72W/l/0m+032i18t/OrTt/+c2S9+tfCrhV8t/GrhVwu/WvjVwq8WfrXwq4VfLfxq4VcLv1r41cKvFn618KuFXy38auFXC79a+NXCrxZ+tfCrhV8t/GrhVwu/WvjVwq8WfrXwq41fbfxq41cbv9r41cavNn618auNX238auNXG7/a+NXGrzZ+tfGrjV9t/GrjVxu/2vjVxq82frXxq41fbfxq41cbv9r41cavNn618auNX238auNXG7/a+NXGrzZ+tfGrjV9t/GrjVxu/2vjVxq82frXxq41fbfxq41cbv9r41cavNn618auNX238auNXG7/a+NXGrzZ+tfGrjV9t/GrjVxu/2vjVxq82frXxq41fbfxq41cbv9r41cavNn618auNX238auNXG7/a+NXGrzZ+tfGrjV9t/GrjVxu/2vjVxq82frXxq41fbfxq41cbvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF79K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr9K/Crxq8SvEr96+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrwq8Kvyr8qvCrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qvGrxq8av2r8qsev9tf41f4av9pf41f7a/xqf41f7a/xq/01frW/xq/21/jV/hq/2l/jV/tr/Gp/jV/tr/Gr/TV+tb/Gr/bX+NX+Gr/aX+NX+2v8an+NX+2v8av9NX61v8av9tf41f4av9pf41f7a/xqf41f7a/xq/01frW/xq/21/jV/hq/2l/jV/tr/Gp/jV/tr/Gr/TV+tb82+z3s97Dfw34P+z3s97Dfw34P+z3s97Dfy34v+73s97Lfy34v+73s97Lfy34v+032m+w32W+y32S/yX6T/Sb7Tfab7Pex38d+H/t97Pex38d+H/t97Pex38d+i/0W+y32W+y32G+x32K/xX6L/Rb7bfbb7LfZb7PfZr/Nfpv9Nvtt9jt+tenbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunb/3yxNa9ZnGe/9O2bvn3Tt2/69k3fvunb/3wZLufHaxbn2S99+6Zv3/Ttm75907dv+vZN377p2/98+SNn9nvY72G/h/0e9nvY72G/h/0e9nvY72G/l/1e9nvZ72W/l/1e9nvZ72W/l/1e9pvsN9lvst9kv8l+k/0m+032m+w32e9jv4/9Pvb72O9jv4/9Pvb72O9jv4/9Fvst9lvst9hvsd9iv8V+i/0W+y322+y32W+z32a/zX6b/Tb7bfbb7Be/om/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn3Tt2/69k3fvunbN337pm/f9O2bvn1/+vaz/p7/8urnHJwX5z9z79fn/GfuOZ/zn7n3M+svr+73zz9+vjj3/PxfXv2cY37mL69+zpufOZwvP5OcHz9TnHt+5i+vfs4xP/OXVz9n7vuXVz9n7vuXVz9n7pvcN7nv476P+z7u+7jv476P+z7u+7jv476P+xb3Le5b3Le4b3Hf4r7FfYv7Fvct7tvct7lvc9/mvs19m/s2923u29y3576fvv3nPPf99O0/583PHM6Xn0nOj58pznPfT9/+c577fvr2n/PmZw7ny88k58fPFGfuu7jv4r6L+y7uu7jv4r6L+y7uu7jv4r6b+27uu7nv5r6b+27uu7nv5r6b+27ue7jv4b6H+8KrT9/+c+a+h/vCqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68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/T72+9jvY7+P/T72+9jvY7/Ffov9Fvst9lvst9hvsd9iv8V+i/02+2322+y32W+z32a/zX6b/Tb7ne9vv5++/fOafH/7/f7+9vycN+fZL9/ffj99+89rPs7Fa85+v7+//fOa8/3t99O3f7/mfH/7/fTt3685399+P337z2s+zsVrzn4/ffv3a873t99P3/79mvP97ffTt3+/5nx/+/3+/vbv13yci9ec/X769u/XnO9vv5++/fs15/vb7/f3t39ec76//X769p/XfJyL12S/h/0e9nvY72G/h/3iVwu/4vvb78Kv+P72u/Arvr/9LvyK72+/C7/i+9vvwq/4/va78Cu+v/0u/Irvb78Lv+L72+/Cr/j+9rvwK76//S78iu9vvwu/4vvb78Kv+P72u/Arvr/9LvyK72+/C7/i+9vvwq/4/va78Cu+v/0u/Irvb78Lv+L72+/Cr/j+9rvwK76//S78iu9vvwu/4vvb78Kv+P72u/Arvr/9bvyK72+/G7/i+9vvxq/4/va78Su+v/1u/Irvb78bv+L72+/Gr/j+9rvxK76//W78iu9vvxu/4vvb78av+P72u/Ervr/9bvyK72+/G7/i+9vvxq/4/va78Su+v/1u/Irvb78bv+L72+/Gr/j+9rvxq41fbfxq41cbv9r41cavNn618auNX238auNXG7/a+NXGrzZ+tfGrjV9t/GrjVxu/2vjVxq82frXxq41fbfxq41cbv9r41cavNn618auNX238auNXG7/a+NXGrzZ+tfGrjV9t/GrjVxu/2vjVxq82frXxq41fbfxq41cbv9r41cavNn618auNX238auNXG7/a+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg18d/OrgVwe/OvjVwa8OfnXwq4NfHfzq4FcHvzr41cGvDn518KuDXx386uBXB786+NXBrw5+dfCrg19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvjVxa8ufnXxq4tfXfzq4lcXv7r41cWvLn518auLX1386uJXF7+6+NXFry5+dfGri19d/OriVxe/uvhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfhV4leJXyV+lfjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfPfzq4VcPv3r41cOvHn718KuHXz386uFXD796+NXDrx5+9fCrh189/OrhVw+/evjVw68efvXwq4dfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfFX5V+FXhV4VfNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjV41fNX7V+FXjVz1+lV/jV/k1fpVf41f5NX6VX+NX+TV+lV/jV/k1fpVf41f5NX6VX+NX+TV+lV/jV/k1fpVf41f5NX6VX+NX+TV+lV/jV/k1fpVf41f5NX6VX+NX+TV+lV/jV/k1fpVf41f5NX6VX+NX+TV+lV/jV/k1fpVf41f5NX6VX+NX+TV+lV/jV/k1fpVf41f5tdnvYb+H/R72e9jvYb+H/R72e9jvYb+H/V72e9nvZb+X/V72e9nvZb+X/V72e9lvst9kv8l+k/0m+032m+w32W+y32S/j/0+9vvY72O/j/0+9vvY72O/j/0+9lvst9hvsd9iv8V+i/0W+y32W+y32G+z32a/zX6b/Tb7bfbb7LfZb7Pf8aukb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG//x/lxLl5z9kvfnvTtSd+e9O1J35707f84J6/5OBevOfulb0/69qRvT/r2pG9P+vakb0/69n+ci9dkv4f9HvZ72O9hv4f9HvZ72O9hv4f9HvZ72e9lv5f9XvZ72e9lv5f9XvZ72e9lv8l+k/0m+032m+w32W+y32S/yX6T/T72+9jvY7+P/T72+9jvY7+P/T72+9hvsd9iv8V+i/0W+y32W+y32G+x32K/zX6b/Tb7bfbb7LfZb7PfZr/NfvEr+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb89P337W57w5H86X85+5f3/vW3769nM+5z9z7/esP3Pv5+c/v3/w8/Pz+wfz07d///z8/sH89O0/P3M5Jz/zOBc/03P+/P7Bz8/M7x/MT9/+8zOb8+FnLmfuO79/MD99+8/P9Jwv973c93Lfy30v973c93Lfy30v973cN7lvct/kvsl9k/sm903um9w3uW9y38d9H/d93Pdx38d9H/d93Pdx38d9H/ct7lvct7hvcd/ivsV9i/sW9y3uW9y3uW9z3+a+zX2b+zb3be7b3Le57/y+1Pz07Z+fOfP7UvPTt//8zOZ8+JnLOfmZx7n4mbnvp2///pn5fan56dt/fmZzPvzM5Zz8zONc/Az3Xdx3cd/FfRf3Xdx3cV94dRb3hVdncV94deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVgVcHXh14deDVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deHVhVcXXl14deFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFV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wKsDrw68OvDqwKsDrw68OvDqwKsDrw68OvDqwKsDrw68OvDqwKsDrw68OvDqwKsDrw68OvDqwKsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwqsLry68uvDqwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evHrw6sGrB68evCp4VfCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4ZXDa8aXjW8anjV8KrhVcOrhlcNrxpeNbxqeNXwquFVw6uGVw2vGl41vGp41fCq4VXDq4ZXDa8aXjW8anjV8KrhVcOrhlcNrxpeNbxqeNXwquFVw6uGVw2vGl41vGp41fCq4VXDq4ZXDa8aXjW8anjV8KrhVcOrhlcNrxpeNbxqeNXwquFVw6uGVw2vGl7Rt7+GV/Ttj7790bc/+vZH3/7o2x99+6Nvf/Ttj7790bc/+vZH3/7o2x99+6Nvf/Ttj7790bc/+vZH3/7o2x99+6Nvf/Ttj7790bc/+vZH3/7o2x99e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXffs/zsyFV/TtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F31707UXfXvTtRd9e9O1F39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/e9O1N39707U3f3vTtTd/+jzNz4RV9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N31707c3fXvTtzd9e9O3N317T9/+j38d/OXVn3NwXpx/5v45H/7nl3NyfpyLP8vcYG4wN5gbzA3mBnODucHcYG4wdzF3MXcxdzF3MXcxdzF3MXcxdzF3M3czdzN3M3czdzN3M3czdzN3M/cw9zD3MPcw9zD3MPcw9zD3MPcw9zL3Mvcy9zL3Mvcy9zL3Mvcy9zI3mZvMTeYmc5O5ydxkbjI3mZvMfcx9zH3Mfcx9zH3Mfcx9zH3Mfcwt5hZzi7nF3GJuMbeYW8wt5hZzm7nN3GZuM7eZ28xt5jZzm7nwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXgW8CngV8CrgVcCrgFcBrwJeBbwKeBXwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXgW8CngV8CrgVcCrgFcBrwJeBbwKeBXwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXgW8CngV8CrgVcCrgFcBrwJeBbwKeBXwKuBVwKuAVwGvAl4FvAp4FfAq4FXAq4BXAa8CXgW8CngV8CrgVcCrgFcBrwJeBbwKeBXwKuBVwKuAVwGvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvFrxa8GrBqwWvNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vNrza8GrDqw2vDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvDrw68OrAqwOvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvLry68OrCqwuvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfAq4VXCq4RXCa8SXiW8SniV8CrhVcKrhFcJrxJeJbxKeJXwKuFVwquEVwmvEl4lvEp4lfDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evDqwasHrx68evCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4JXBa8KXhW8KnhV8KrgVcGrglcFrwpeFbwqeFXwquBVwauCVwWvCl4VvCp4VfCq4FXBq4JXBa8aXjW8anjV8KrhVcOrhlcNrxpeNbxqeNXwquFVw6uGVw2vGl41vGp41fCq4VXDq4ZXDa8aXjW8anjV8KrhVcOrhlcNrxpeNbxqeNXwquFVw6uGVw2vGl41vGp41fCq4VXDq4ZXDa8aXjW8anjV8KrhVcOrhlcNrxpeNbxqeNXwquFVw6uGVw2vGl41vGp41fCq4VXDq4ZXDa8aXjW8anjV8KrhVcOrhlcNrxpeNbxqeNXwquFVw6uGVw2vGl41vGp41fCq4VXDq4ZXDa8aXjW8anhF3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd/+jzNz4RV9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B317fPft/ff8l1fv8z//y6uf85+5r//jf/tP/+9/+fd/+S//9V//+f/5T//7//+P/+f/9T//2z/9j3/5t//2/f/8H//ff//5//mv//4v//qv//J//+f//u//9k///H/+z3//5//8r//2T3////7j//iP/wU=","file_map":{"18":{"source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [u1; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n","path":"std/field/mod.nr"},"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"22":{"source":"pub mod hash;\npub mod aes128;\npub mod array;\npub mod slice;\npub mod ecdsa_secp256k1;\npub mod ecdsa_secp256r1;\npub mod embedded_curve_ops;\npub mod field;\npub mod collections;\npub mod compat;\npub mod convert;\npub mod option;\npub mod string;\npub mod test;\npub mod cmp;\npub mod ops;\npub mod default;\npub mod prelude;\npub mod runtime;\npub mod meta;\npub mod append;\npub mod mem;\npub mod panic;\npub mod hint;\n\nuse convert::AsPrimitive;\n\n// Oracle calls are required to be wrapped in an unconstrained function\n// Thus, the only argument to the `println` oracle is expected to always be an ident\n#[oracle(print)]\nunconstrained fn print_oracle(with_newline: bool, input: T) {}\n\nunconstrained fn print_unconstrained(with_newline: bool, input: T) {\n print_oracle(with_newline, input);\n}\n\npub fn println(input: T) {\n // Safety: a print statement cannot be constrained\n unsafe {\n print_unconstrained(true, input);\n }\n}\n\npub fn print(input: T) {\n // Safety: a print statement cannot be constrained\n unsafe {\n print_unconstrained(false, input);\n }\n}\n\n/// Asserts the validity of the provided proof and public inputs against the provided verification key and hash.\n///\n/// The ACVM cannot determine whether the provided proof is valid during execution as this requires knowledge of\n/// the backend against which the program is being proven. However if an invalid proof if submitted, the program may\n/// fail to prove or the backend may generate a proof which will subsequently fail to verify.\n///\n/// # Important Note\n///\n/// If you are not developing your own backend such as [Barretenberg](https://github.com/AztecProtocol/barretenberg)\n/// you probably shouldn't need to interact with this function directly. It's easier and safer to use a verification\n/// library which is published by the developers of the backend which will document or enforce any safety requirements.\n///\n/// If you use this directly, you're liable to introduce underconstrainedness bugs and *your circuit will be insecure*.\n///\n/// # Arguments\n/// - verification_key: The verification key of the circuit to be verified.\n/// - proof: The proof to be verified.\n/// - public_inputs: The public inputs associated with `proof`\n/// - key_hash: The hash of `verification_key` of the form expected by the backend.\n/// - proof_type: An identifier for the proving scheme used to generate the proof to be verified. This allows\n/// for a single backend to support verifying multiple proving schemes.\n///\n/// # Constraining `key_hash`\n///\n/// The Noir compiler does not by itself constrain that `key_hash` is a valid hash of `verification_key`.\n/// This is because different backends may differ in how they hash their verification keys.\n/// It is then the responsibility of either the noir developer (by explicitly hashing the verification key\n/// in the correct manner) or by the proving system itself internally asserting the correctness of `key_hash`.\npub fn verify_proof_with_type(\n verification_key: [Field; N],\n proof: [Field; M],\n public_inputs: [Field; K],\n key_hash: Field,\n proof_type: u32,\n) {\n if !crate::runtime::is_unconstrained() {\n crate::assert_constant(proof_type);\n }\n verify_proof_internal(verification_key, proof, public_inputs, key_hash, proof_type);\n}\n\n#[foreign(recursive_aggregation)]\nfn verify_proof_internal(\n verification_key: [Field; N],\n proof: [Field; M],\n public_inputs: [Field; K],\n key_hash: Field,\n proof_type: u32,\n) {}\n\n// Asserts that the given value is known at compile-time.\n// Useful for debugging for-loop bounds.\n#[builtin(assert_constant)]\npub fn assert_constant(x: T) {}\n\n// Asserts that the given value is both true and known at compile-time.\n// The message can be a string, a format string, or any value, as long as it is known at compile-time\n#[builtin(static_assert)]\npub fn static_assert(predicate: bool, message: T) {}\n\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_add(y)\")]\npub fn wrapping_add(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n AsPrimitive::as_(x.as_() + y.as_())\n}\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_sub(y)\")]\npub fn wrapping_sub(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n //340282366920938463463374607431768211456 is 2^128, it is used to avoid underflow\n AsPrimitive::as_(x.as_() + 340282366920938463463374607431768211456 - y.as_())\n}\n#[deprecated(\"wrapping operations should be done with the Wrapping traits. E.g: x.wrapping_mul(y)\")]\npub fn wrapping_mul(x: T, y: T) -> T\nwhere\n T: AsPrimitive,\n Field: AsPrimitive,\n{\n AsPrimitive::as_(x.as_() * y.as_())\n}\n\n#[builtin(as_witness)]\npub fn as_witness(x: Field) {}\n\nmod tests {\n use super::ops::arith::WrappingMul;\n\n #[test(should_fail_with = \"custom message\")]\n fn test_static_assert_custom_message() {\n super::static_assert(1 == 2, \"custom message\");\n }\n\n #[test]\n fn test_wrapping_mul() {\n let zero: u128 = 0;\n let one: u128 = 1;\n let two_pow_64: u128 = 0x10000000000000000;\n let u128_max: u128 = 0xffffffffffffffffffffffffffffffff;\n\n // 1*0==0\n assert_eq(zero, zero.wrapping_mul(one));\n\n // 0*1==0\n assert_eq(zero, one.wrapping_mul(zero));\n\n // 1*1==1\n assert_eq(one, one.wrapping_mul(one));\n\n // 0 * ( 1 << 64 ) == 0\n assert_eq(zero, zero.wrapping_mul(two_pow_64));\n\n // ( 1 << 64 ) * 0 == 0\n assert_eq(zero, two_pow_64.wrapping_mul(zero));\n\n // 1 * ( 1 << 64 ) == 1 << 64\n assert_eq(two_pow_64, two_pow_64.wrapping_mul(one));\n\n // ( 1 << 64 ) * 1 == 1 << 64\n assert_eq(two_pow_64, one.wrapping_mul(two_pow_64));\n\n // ( 1 << 64 ) * ( 1 << 64 ) == 1 << 64\n assert_eq(zero, two_pow_64.wrapping_mul(two_pow_64));\n // -1 * -1 == 1\n assert_eq(one, u128_max.wrapping_mul(u128_max));\n }\n}\n","path":"std/lib.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"66":{"source":"use dep::std;\nuse poseidon::poseidon2;\n\nglobal UTXO_VERIFICATION_KEY_HASH: Field = 20361994226032552507663901262286744551869524558436762371297713593361795171294;\n\nstruct AggUtxoProofInput {\n proof: [Field; 508],\n utxo_kind: Field,\n input_merkle_paths: [[Field; 160]; 2],\n output_merkle_paths: [[Field; 160]; 2],\n input_commitments: [Field; 2],\n output_commitments: [Field; 2],\n}\n\nfn main(\n verification_key: [Field; 115],\n proofs: [AggUtxoProofInput; 3],\n // TODO: maybe we can remove this\n verification_key_hash: pub [Field; 2],\n old_root: pub Field,\n new_root: pub Field,\n commit_hash: pub Field,\n messages: pub [Field; 1000],\n) {\n // Hardcode verification_key_hash for utxo proof\n assert(verification_key_hash[0] != 0, \"dummy verfication key hash\");\n assert(verification_key_hash[1] != 0, \"dummy verfication key hash\");\n\n let mut root = old_root;\n let mut utxo_hashes: [Field; 3] = [0, 0, 0];\n let mut messages_index = 0;\n\n let mut first_public_inputs: [Field; 9] = [0; 9];\n for i in 0..3 {\n let proof = proofs[i];\n let input_commitments = proof.input_commitments;\n let output_commitments = proof.output_commitments;\n\n let utxo_kind = proof.utxo_kind;\n let is_padding = utxo_kind == 0;\n let is_burn = utxo_kind == 3;\n let is_mint = utxo_kind == 2;\n let is_proof_kind_mint_or_burn = is_burn | is_mint;\n\n let mut msg_note_kind = 0;\n let mut msg_value = 0;\n let mut msg_hash = 0;\n let mut msg_burn_addr = 0;\n\n if is_proof_kind_mint_or_burn {\n assert(messages[messages_index] == utxo_kind, \"proof 'kind' must match message\");\n msg_note_kind = messages[messages_index + 1];\n msg_value = messages[messages_index + 2];\n msg_hash = messages[messages_index + 3];\n messages_index += 4;\n }\n\n if is_burn {\n msg_burn_addr = messages[messages_index];\n messages_index += 1;\n }\n\n utxo_hashes[i] = poseidon2::Poseidon2::hash(\n [\n input_commitments[0],\n input_commitments[1],\n output_commitments[0],\n output_commitments[1],\n ],\n 4,\n );\n\n // Verify non-padding proofs\n let public_inputs = [\n input_commitments[0],\n input_commitments[1],\n output_commitments[0],\n output_commitments[1],\n utxo_kind,\n msg_note_kind,\n msg_value,\n msg_hash,\n msg_burn_addr,\n ];\n\n // Capture the public_inputs on first iter\n if (i == 0) {\n // First proof must ALWAYS be a real proof\n assert(!is_padding, \"first proof cannot be a padding proof\");\n // and we will use that proof\n first_public_inputs = public_inputs;\n }\n\n // Due to a limitation in noir, verify_proof_with_type will ALWAYS\n // be run regardless of whether its inside an if statement, so we need\n // to form a valid proof. As first proof cannot be a dummy proof, we can\n // use the first proof for padding elements\n std::verify_proof_with_type(\n verification_key,\n if (is_padding) {\n proofs[0].proof\n } else {\n proof.proof\n },\n if (is_padding) {\n first_public_inputs\n } else {\n public_inputs\n },\n UTXO_VERIFICATION_KEY_HASH,\n 7,\n );\n\n if (!is_padding) {\n // Input commitments\n for j in 0..2 {\n let commitment = input_commitments[j];\n\n if commitment != 0 {\n let bits: [u1; 254] = commitment.to_le_bits();\n let merkle_path = proof.input_merkle_paths[j];\n\n // Check it exists in the old tree\n validate_inclusion(commitment, bits, merkle_path, root);\n\n // Calculate new root without the input commitment\n root = get_null_root(bits, merkle_path);\n }\n }\n\n // Output commitments\n for j in 0..2 {\n let commitment = output_commitments[j];\n\n if commitment != 0 {\n let bits: [u1; 254] = commitment.to_le_bits();\n let merkle_path = proof.output_merkle_paths[j];\n\n // Checks the merkle path leads to the existing root\n validate_null(bits, merkle_path, root);\n\n // Calculate new root with added output commitments\n root = get_merkle_root(commitment, bits, merkle_path);\n }\n }\n }\n }\n\n // Verify all other messages are zero\n for i in 0..messages.len() {\n if i >= messages_index {\n assert(messages[i] == 0, \"Message is not zero\");\n }\n }\n\n assert(root == new_root, \"New root is not valid\");\n assert(commit_hash == poseidon2::Poseidon2::hash(utxo_hashes, 3));\n}\n\nfn validate_inclusion(leaf: Field, bits: [u1; 254], merkle_path: [Field; 160], root: Field) {\n let merkle_root = get_merkle_root(leaf, bits, merkle_path);\n assert(merkle_root == root, \"Merkle path root does not match\");\n}\n\nfn validate_null(bits: [u1; 254], merkle_path: [Field; 160], root: Field) {\n let merkle_root = get_null_root(bits, merkle_path);\n assert(merkle_root == root, \"Merkle path root does not match\");\n}\n\nfn get_null_root(bits: [u1; 254], merkle_path: [Field; 160]) -> Field {\n get_merkle_root(0, bits, merkle_path)\n}\n\nfn get_merkle_root(leaf: Field, bits: [u1; 254], merkle_path: [Field; 160]) -> Field {\n let mut hash = leaf;\n for i in 0..160 {\n let dir = bits[i];\n let sibling = merkle_path[i];\n if dir == 0 {\n hash = poseidon2::Poseidon2::hash([hash, sibling], 2);\n } else {\n hash = poseidon2::Poseidon2::hash([sibling, hash], 2);\n }\n }\n hash\n}\n\n#[test]\nfn empty_tree() {\n let mut hash = 0;\n for _ in 0..160 {\n hash = poseidon2::Poseidon2::hash([hash, hash], 2);\n }\n println(\"empty root hash:\");\n println(hash);\n assert(hash == 2473073130432999597457871252851154814051443713747864452328961082127445883391);\n}\n\n#[test]\nfn test_merkle_path_operations() {\n // Test basic merkle path operations\n let leaf: Field = 12345;\n let bits: [u1; 254] = leaf.to_le_bits();\n let merkle_path = [0; 160];\n\n // Test get_merkle_root\n let root = get_merkle_root(leaf, bits, merkle_path);\n assert(root != 0);\n\n // Test get_null_root (should be different from leaf root)\n let null_root = get_null_root(bits, merkle_path);\n assert(null_root != root);\n\n // Test validate_inclusion\n validate_inclusion(leaf, bits, merkle_path, root);\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/agg_utxo/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/burn/key b/fixtures/circuits/burn/key new file mode 100644 index 0000000..feaa2c0 Binary files /dev/null and b/fixtures/circuits/burn/key differ diff --git a/fixtures/circuits/burn/key_fields.json b/fixtures/circuits/burn/key_fields.json new file mode 100644 index 0000000..c9aad61 --- /dev/null +++ b/fixtures/circuits/burn/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000017", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000c567f9863e4ef6daf689c7d89a7545f7f0", + "0x00000000000000000000000000000000000a174f400161d0b02fcdcd8aa9526b", + "0x0000000000000000000000000000004311364ee643efa17a539be1beb028b808", + "0x0000000000000000000000000000000000141319d5ff6e2aa71733b4bf075377", + "0x000000000000000000000000000000180c9cc9a5fff737c650acfc87406f5711", + "0x0000000000000000000000000000000000253697123c2d7d57a978e3d2df79c2", + "0x0000000000000000000000000000001608317563fcb42cd1101ced94f61be66f", + "0x0000000000000000000000000000000000147e36998b7ed6b70aaff01d16fe6e", + "0x00000000000000000000000000000049952385900e4c31793cf9d1ba3fb915d5", + "0x000000000000000000000000000000000018896718979ac8e449cbb670db64d1", + "0x00000000000000000000000000000048d32b29b7aaef803f7479ecaf6cb5f0d7", + "0x00000000000000000000000000000000002b51801046343cf1a1890cf0c64908", + "0x00000000000000000000000000000087dbfd5f84fbce5a8b8e0e5177d8bdf6e5", + "0x00000000000000000000000000000000000e95904364b456ea7f91540e6c16e4", + "0x0000000000000000000000000000005e74c118faef4bc019ab53b6f731cf06ad", + "0x0000000000000000000000000000000000219631f37f8eb3bdd020e1b4ec556e", + "0x00000000000000000000000000000007337fac355db609c27855e083d55b1339", + "0x00000000000000000000000000000000000e7be2bed7c3ba5705e43b62eef99d", + "0x000000000000000000000000000000315d673fb47b7f4d49f22b3251f127eb6a", + "0x00000000000000000000000000000000000b2b0349babc573789bef4b5ce73dd", + "0x0000000000000000000000000000002ebd2a68823f38339429a71a0c22e853e8", + "0x000000000000000000000000000000000016d964073dd78d9b2047e4bc5a6143", + "0x00000000000000000000000000000068712844b9f506886e659ebc0853c778f3", + "0x0000000000000000000000000000000000136c0544de919fb3703f183a8e3a3a", + "0x000000000000000000000000000000113d47a2256ba6f60a9e2ec0523c52a991", + "0x00000000000000000000000000000000001958b13f38f58756e23989a418de3c", + "0x000000000000000000000000000000a9e00aa9470a9e3c58a56cc81e212df923", + "0x0000000000000000000000000000000000286c1d4c53af6654de284fbb620f90", + "0x0000000000000000000000000000005b07d0547402405c0074b5c47eff493459", + "0x000000000000000000000000000000000029f3c4ac5ac80ce875438e6bb09672", + "0x000000000000000000000000000000075131bb601fbb1c08eb6c5bc72971593d", + "0x00000000000000000000000000000000000707f3fffeec3094e4bc21fac03ddc", + "0x0000000000000000000000000000009b38828ba04634ee95dbcb0f040450f95b", + "0x0000000000000000000000000000000000230632426f94297a6b0a380671e85f", + "0x000000000000000000000000000000983d26f113710c42fe6e1dc2f5fd10d9cc", + "0x00000000000000000000000000000000000c238ccb939c3c3b3bd263e6ff338b", + "0x000000000000000000000000000000c3bc30568b7c96623e2d6e582b6509c07d", + "0x000000000000000000000000000000000010955b4e443334aac8dbfa7afaa646", + "0x0000000000000000000000000000003d1c3d97961a94c1ab0d0dac34ec583bfd", + "0x00000000000000000000000000000000002c3593e38179c0e60badd6f3c3d738", + "0x000000000000000000000000000000459a1f88f27de2a595b00ecc61182776c0", + "0x00000000000000000000000000000000000540d1ccee15f800ce74af7478655d", + "0x00000000000000000000000000000050822c8a009d751404ec073158bc949b8f", + "0x0000000000000000000000000000000000251f52d813ced90037f1314103ab99", + "0x00000000000000000000000000000024a5c652e584475a0ff9237c2df1280d81", + "0x00000000000000000000000000000000000b165dc50ce91fe6f1a53c5931f6da", + "0x0000000000000000000000000000001096d8f6dd06cc48c347598dde7f71dfa1", + "0x00000000000000000000000000000000002419b3d00e8fca827fdcec3d152457", + "0x00000000000000000000000000000014339b594945d3aa09f926188e8b173a67", + "0x00000000000000000000000000000000001b769ffa36a01b651c4e3f3524609a", + "0x000000000000000000000000000000149dbd3bc77f9fd9253879adb3816c571d", + "0x000000000000000000000000000000000018f306439b2b64d49459d25859c3e3", + "0x000000000000000000000000000000a18851f2f0dd96e47ee1499ced9ec90a09", + "0x000000000000000000000000000000000011b9c618085358306638d815da306b", + "0x000000000000000000000000000000bfafd1ee2ca8e91e0c021a91cd14cbf9aa", + "0x00000000000000000000000000000000000a9da641a526caa07ee08c863a210b", + "0x000000000000000000000000000000c973c3836332bfd93fe2cd3f17ab274eba", + "0x0000000000000000000000000000000000204d9db0575579d718a0b595e17faf", + "0x00000000000000000000000000000004f2127ea4741369343ca556fc993063df", + "0x000000000000000000000000000000000000f51adaf949700e49076a1d5eeb5d", + "0x000000000000000000000000000000ef1d399ff417cc6ee845e7371687c1bdd4", + "0x00000000000000000000000000000000002d8e621ebf642bf3144f7c4d78e15a", + "0x0000000000000000000000000000009cc861ccc80680402c9351ba41c73eb33e", + "0x00000000000000000000000000000000002ce224d972eb4e27c4df96511c204e", + "0x00000000000000000000000000000083e0e26a414d618a02ff3e8027fd0c1932", + "0x00000000000000000000000000000000000ebc8043d33bf00242ec77b82d3443", + "0x000000000000000000000000000000415edc2d3db88f18fb5da53e7e4d752344", + "0x00000000000000000000000000000000001b4088157af451e851c686d3b0e6b6", + "0x000000000000000000000000000000659d62c3559e6c35e5a32e2a4c34f5451b", + "0x00000000000000000000000000000000000f4df4712bdca713a7ed221350243c", + "0x00000000000000000000000000000055d554c5e4d8ca4e03c1f828ef49b4f2c8", + "0x00000000000000000000000000000000001513db5261844a92e3c7a397d82006", + "0x0000000000000000000000000000007a78a220e9dc3171d6a6b1c50b1bcaf9b0", + "0x000000000000000000000000000000000011db16fe94945795273ed7e890ecc4", + "0x000000000000000000000000000000b921c72824eb94300da3ba1e1a58d9705e", + "0x00000000000000000000000000000000001ee0615574d55a5c38e4a282f95b8f", + "0x000000000000000000000000000000a54a3413a3460752c14cf8cdcaaa9c7d95", + "0x00000000000000000000000000000000001b876a8a28a5c833c539c9c91dbba2", + "0x000000000000000000000000000000701715108e6ccc60c67d77ffb5cfb16d31", + "0x0000000000000000000000000000000000080a6448fb87805bba79fd234eeb29", + "0x000000000000000000000000000000827ca466ed86ec4a81964924f16a4e4113", + "0x000000000000000000000000000000000021f535260376a772ba8fb075ec758c", + "0x000000000000000000000000000000571e5aee4b19811aa438eda827f879d67e", + "0x00000000000000000000000000000000002f9413c57c13058e41b0e77a314fea", + "0x000000000000000000000000000000ff5bcd3823ccc5a35cec10e56ca2c57b09", + "0x00000000000000000000000000000000001f92949ed26b5c026324062aead6fa", + "0x0000000000000000000000000000003ba3c225733c5d62373965830c58e7f805", + "0x000000000000000000000000000000000023f0289e6661c92f85027636ea363b", + "0x000000000000000000000000000000494997477ab161763e46601d95844837ef", + "0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd", + "0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9", + "0x0000000000000000000000000000000000303126892f664d8d505964d14315ec", + "0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672", + "0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074", + "0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04", + "0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b", + "0x0000000000000000000000000000000228ada50310c195c1485a793878ff3ab4", + "0x000000000000000000000000000000000006331732b5da077ca7e91153fcd583", + "0x00000000000000000000000000000090dad024438903645601b83dd2d07190d6", + "0x000000000000000000000000000000000000e6d57c9202bd5d5c66193b4f690c", + "0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877", + "0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824", + "0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb", + "0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000bf91b3731d91e6f30655c69933009df017", + "0x00000000000000000000000000000000001f6003aca31eb379f5740618606d18", + "0x000000000000000000000000000000fb740e248029b96ff4f9e03c2c50381968", + "0x00000000000000000000000000000000000f9cbf6e2753d8690070742ba59adc" +] diff --git a/fixtures/circuits/burn/program.json b/fixtures/circuits/burn/program.json new file mode 100644 index 0000000..82fe646 --- /dev/null +++ b/fixtures/circuits/burn/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"15811806180040672867","abi":{"parameters":[{"name":"utxo","type":{"kind":"struct","path":"common::utxo::Utxo","fields":[{"name":"input_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::InputNote","fields":[{"name":"note","type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"field"}}]}}},{"name":"output_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}}},{"name":"input_merkle_paths","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::MerklePath","fields":[{"name":"path","type":{"kind":"array","length":160,"type":{"kind":"field"}}}]}}}]},"visibility":"private"},{"name":"burn_recipient_private","type":{"kind":"field"},"visibility":"private"},{"name":"recent_root","type":{"kind":"field"},"visibility":"public"},{"name":"input_nullifiers","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"},{"name":"output_commitments","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"},{"name":"burn_recipient_public","type":{"kind":"field"},"visibility":"public"},{"name":"burn_value","type":{"kind":"field"},"visibility":"public"}],"return_type":null,"error_types":{"2532032818322018100":{"error_kind":"string","string":"Invalid nullifier 0"},"4703047920556725948":{"error_kind":"string","string":"Field failed to decompose into specified 254 limbs"},"6114791109410570004":{"error_kind":"string","string":"Burn output must match burn value"},"6749186246397432903":{"error_kind":"string","string":"Invalid nullifier 1"},"7126743292872256338":{"error_kind":"string","string":"Padding notes must be zero value"},"11305677572723109408":{"error_kind":"string","string":"Inconsistent kinds are not allowed"},"12272962467056991279":{"error_kind":"string","string":"Invalid output commitment 1"},"12382400539224138144":{"error_kind":"string","string":"Input note is not owned by the owner"},"12469291177396340830":{"error_kind":"string","string":"call to assert_max_bit_size"},"12892768124692939682":{"error_kind":"string","string":"Burn recipient private/public mismatch"},"13108753448563390903":{"error_kind":"string","string":"Input commitment is not in recent root"},"14885583290507436593":{"error_kind":"string","string":"Invalid output commitment 0"}}},"bytecode":"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","debug_symbols":"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XBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwyYhL7BCX2CEusUNcYoe4xA5xiR3iEjvEJXaIS+wQl9ghLrFDXGKHuMQOcYkd4hI7xCV2iEvsEJfYIS6xQ1xih7jEDnGJHeISO8QldohL7BCX2CEusUNcYoe4xA5xiR3iEjvEJXaIS+wQl9ghLrFDXGKHuMQOcYkd4hI7xCV2bHRzdHN0c3RzdHN0c3RzdHN0c3RzdAt0C3QLdAt0C3QLdAt0C3QLdAt0S3RLdEt0S3RLdEt0S3RLdEt0S3QrdCt0K3QrdCt0K3QrdCt0K3QrdGt0a3RrdGt0a3RrdGt0a3RrdGt0G3QbdBt0G3QbdBt0G3QbdBt0E5fYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpfYEpcYuVcj92rkXo3cqy1xiZF7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu719v/rlhLdHN0c3RzdHN0c3RzdAt0C3QLdAt0C3QLdAt0C3QLdAt0S3RLdEt0S3RLdEt0S3RLdEt0S3QrdCt0K3QrdCt0K3QrdCt0K3QrdGt0a3RrdGt0a3RrdGt0a3RrdGt0G3QbdBt0G3QbdBt0G3QbdBt3gEnKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92rkXo3cq5F7NXKvRu7VyL0auVcj92pn7jXmXjblrVvmD7f/XeeDclEa5aZ0yqBMyqJsSrotui26Lbotui26Lbotui26LbotuhndjG5GN6Ob0c3oZnQzuhndjG6bbptum26bbptum26bbptum26bbk43p5vTzenmdHO6Od2cbk43p1vQLegWdAu6Bd2CbkG3oFvQLeiWdEu6Jd2Sbkm3pFvSLemWdEu6Fd2KbkW3olvRrehWdCu6Fd2Kbk23plvTrenWdGu6Nd2abk23ptvQbeg2dBu6Dd2GbkO3odvQDS8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi8JvCTwksBLAi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLEi9JvCTxksRLztxrHfcyKe/d+l425b3bDZvP3OtVLn3t7iVXuSnv3epeBl9LyqJsSroV3U4vOUu6Fd3uXnKVoZ9+eslZ0q3odveS82t3L7lK9nZ6yX0Xp5fcv3Z6yVmyt2Zvdy+5VmhKup1ecl932NvpJWdJt6Hb0G3Qbeg2dDu95NbizL3ev3bmXq/SKDelTvLMvV5lUuoqOXOvVyndztzrVeokz9zrVW5K1worKJMVirL5mk7yzL1e5dKOjb0ZezOnDEr2ZkVJt9NL7r/s9JKz5CQ33TZ725zk5iR3sgInuZsVOElnb85JOid5esl9x87enL05J+mcpLM35ySDbsFJBnsLTjLohpcUXnLmXq+SqyQ4SbzkzL1eJXvDS87c61VylSQniZcUXnLmXs+vFXsrTrI03Wfu9fxasbfiJIuTxEsKLym8pPCSwksKLym8pPCSwksKLym8pPCSwkvO3Ot5DqeXnCW64SVn7vX6GrrhJWfu9fyRw95G12TjJY2XNF5y5l7vizVe0njJmXu9/8jGS87c67UC3ZZOsvGSxkvO3Ov995651+trQZmUxdeaUid55l7PxYy94SWNlzRe0njJmXu9yqJkb8beNnvb7G2zt83eNt023TbdNnvb7G2zN2dvzt6cvTl7w0vO3Ou1QlLSzTXdZ+71LIOrJOgW7C24SoKr5HzGuf/IYG/BSQYnGewtOUm45My9nj/nfMY5S/YGl5y51+tr7C05yWRvdVCyt+Ik4ZKGS87c61WmtomXNF5y5l7PsjnJplvTrenWdGu6Nd2abk23pttwksNJDroN1yRc0nDJmXu9SrrhJY2XDF5y5l7vLc7c61VuSvHkmXu9vpaURdmUdMNLBi8ZvGTwksFLBi8ZvGTwksFLBi85c6/3q+TMvV6ldBu85My9Xl8LyqSUKw9eMnjJmXu9SvaGlwxccuZez5+zg5K9bU4SLxm8ZOCSM/d6/jK8ZPCSwUsGLxm8ZPCSwUsGLxm8ZPCSwUsGLxm8ZPCSwUsGLxm8ZPCSwUsGLzlzr+diyd7wksFLhmecgUsGLhmecYZnnIFLhmecwUvO3Ot5JDzjDFwyeMmZe72+xt7gkjP3em4ILxm4ZOCSgUsGLhm8ZPCSwUsGLxm8ZPCSwUsGLxm8ZPCS4RlneMY5c6+3cp+519ti+xCX7ENcsg894+xDXLIPcck+9IyzD3HJPvSMsw95yT70jLMPeck+5CX70DPOPnOv5y+Tl+xDXrIPPePsM/d6lXQzuhndjG5GN6Ob0c3oZnTTM84+c69nKS7ZZ+713Pw2Sk5SXLKPzUluTlJcss/c67XCqHT25ujm7M3Zm6Obh7bp7M3Zm3OSzt6CvQUnGabFgr0FewtOMugW7C04yaBbck0me0uuyaRbsrfkJJOTzGIx9pZcJcVJFt2KbkW3Ym9Ft6JbsbdCt0K3plvTrdGt0a3ZW6Nbc5KNbs3emr0Nug26Dd1m65eNU6Lb0G3Y26AbXnLmXu8rnLnXq9RJLrxk4SULL1l4ycJLFl6y8JKFlyy8ZOElCy9Zel+yl96X7IWXLLxkiUv2WuxN70v20vuSvYy9GXvTM85ext6Mvel9yT5zr9di7G2zN70v2WvTDS9ZeMnCSxZesvCSM/d6dtt0w0sWXrKcbnjJwkuW081T6+IlCy85c69nGXQLugXdgm5Bt6BbpCQMrpKgW9At0S25SpKrRM84+8y9XmWwAldJcpLJVZJcJcUEFBOAlyy8ZBV7w0sWXnLmXs9DLfZW7A0vWXjJwksWXrLwkjP3ev6y5iTxkoWXrGZveMnCS87c6/kjh70N1yResoa94SULLzlzr/efY3iJwSWGl5iecbbhJYaXmN6XbMNLTM842/AS0zPONrzE8BLTM842PeNsg0sMLzG8xPASw0sMLzG8xPASw0sMLzG8xPASw0vO3Ou5TeMk8RLDS2yzt81Jbk5SzzjbNie52dvmJDd7c/bmnKTrKjFnb87enJOESwwvMbzE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwusaQbXmJwieElhpecudezBVxicInhJVbohpcYXmJ6X7KtOEm8xPASw0sML7GmG15ieIk13fCSM/d6lXSDSwwvMbzE4BKDSwwuMbzE4BLDSwwvMbhk4yUbLtl4yYZLNl6y8ZINl2y8ZMMlGy/ZcMnGSzZesuGSzTPOxks2XrLxks0zzuYZZ/OMs3nG2TzjbJ5xztzr+XstKOnGM87mGWfzjLN5xtk842yecTZcsuGSDZdsuGTDJZtnnM0zzoZLNlyyecbZcMmGS87c67VCUrI3vGTjJRsv2XjJxks2XrLxko2X7GBveMnGS87c67lYsje8ZOMlO9kbzzibZ5yd7C25JnnG2Tzj7GJvxd6Kkyzd3zbPOLvYW3GV4CW72Ftxkk03vS/ZGy/ZzUk23ZpuzUk2J9l0a66SYbqHkxy6DSc5nORwksNJDic5nKTeve4z93r/muvd63a9e91X7rXvpVMGKyRl8bWm1Eleudf7CmtRam9X7vUsna8FZVIWKzQle8NLHC9xvMTxEud9ifO+xPESx0tc716384zjcInDJc4zjuMljpf4ptumG1zicInzjON4ieMlzjOOwyUOlzhc4nCJ4yWOlzjPOM4zjvOM4zzjOF5y5l5r3cugvHXr+1GfXuL3silv3fq+wt1Let/LRWmUW4vdveQqQ4udXHKWxbpNOVqs6Hb3knOxu5dc5dZiJ5ecZWixu5dcZbFYU44Wu3vJVS4tdj7jnOXWYncvucrQYncvucpisaYcLXZyyVkuLXb3kqvcWuzuJVcZWmzQbdBt0G2k25l7vUrpduZer1K6nbnXq5RuZ+71KovFmlK6nbnXq5RuZ+71KqXbmXu9Sul25l6vslisKaXbmXu9Sul25l6vUrqduderlG5n7vUqi8WaUrqduderlG5n7vUqpduZe71K6XbmXq+yWKwp0c3RzdHN0c3RzdHN0c3RzdHN0c3RLdAt0C3QLdAt0C3QLdAt0C3QLdAt0S3RLdEt0S3RLdEt0S3RLdEt0a3QrdCt0K3QrdCt0K3QrdCt0K3QrdGt0a3RrdGt0a3RrdGt0a3RrdFt0G3QbdBt0G3QbdBt0G3QbdBtpNuZe71K6XbmXq9Sup2516uUbmfu9SqLxZpSup2516uUbmfu9Sql25l7vUrpduZer7JYrCml25l7vUrpduZer1K6nbnXq5RuZ+71KovFmlK6nbnXq5RuZ+71KqXbmXu9Sul25l6vslisKdHN0c3RzdHN0c3RzdHN0c3RzdHN0S3QLdAt0C3QLdAt0A0uSbgk4ZKES87c61WiG1yScEnCJQmXJFyScEnCJQmXJFyScEnCJQmXJFyScEnCJQmXJFyScEnCJQmXJFyScEnCJQmXJFyScEnCJQmXJFyScEnCJQmXJFyScEnCJQmXJFyScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnBJQWXFFxScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScEnDJQ2XNFzScMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwycMnAJQOXDFwy4hI/xCV+iEv8EJf4IS7xQ1zih7jED3GJH+ISP8QlfohL/BCX+CEu8UNc4oe4xA9xiR/iEj/EJX6IS/wQl/ghLvFDXOKHuMQPcYkf4hI/xCV+iEv8EJf4IS7xQ1zih7jED3GJH+ISP8QlfohL/BCX+CEu8UNc4oe4xA9xiR8b3RzdHN0c3RzdHN0c3RzdHN0c3RzdAt0C3QLdAt0C3QLdAt0C3QLdAt0S3RLdEt0S3RLdEt0S3RLdEt0S3QrdCt0K3QrdCt0K3QrdCt0K3QrdGt0a3RrdGt0a3RrdGt0a3RrdGt0G3QbdBt0G3QbdBt0G3QbdBt3EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb7EJb42ujm6Obo5ujm6Obo5ujm6Obo5ujm6BboFugW6BboFugW6BboFugW6BboluiW6JboluiW6JboluiW6JboluhW6FboVuhW6FboVuhW6FboVuhW6Nbo1ujW6Nbo1ujW6Nbo1ujW6NboNug26DboNug26DboNug26DbrBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJQaXGFxicInBJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XOJwicMlDpc4XELu1cm9OrlXJ/fqDpeQe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr37mXmfdy6S8dZu4l005Km9e8vHa+16uW9n38qPbx1vte7kpnfKj28fb53uZt/L+e29e8vFy+V425ai8ecmjvHWz+4ZuXvIoN+Wt276fzs1LHmVSFmVTjsqbl3y8v76Xi9L0G3JTOmVQJiV7S/aW9273c6iDclGafs7NSx4leyv2Vuyt2Fuxt2Jvzd6avbVRbkr21uyt2Vuzt2ZvjW6DbrMo2duwt2Fvw96GvQ17G/Y22ts99/rxZ4W///Dtf37/60+//8PPP/73t3/728d//M+//vLHv/z0p1+u//iX//3nxz/5w68//fzzT//1uz//+qc//vgff/31x9/9/Kc/3v/Z3//97/8H","file_map":{"18":{"source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [u1; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n","path":"std/field/mod.nr"},"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"55":{"source":"use poseidon::poseidon2;\nuse crate::MerklePath;\n\nimpl MerklePath {\n pub fn root_from_leaf(self, leaf: Field) -> Field {\n let bits: [u1; 254] = leaf.to_le_bits();\n let mut hash = leaf;\n for i in 0..160 {\n let sibling = self.path[i];\n if bits[i] == 0 {\n hash = poseidon2::Poseidon2::hash([hash, sibling], 2);\n } else {\n hash = poseidon2::Poseidon2::hash([sibling, hash], 2);\n }\n }\n\n hash\n }\n\n pub fn validate(self, leaf: Field, root: Field) -> bool {\n self.root_from_leaf(leaf) == root\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/merkle_path.nr"},"56":{"source":"use poseidon::poseidon2;\nuse crate::{InputNote, Note};\n\npub fn check_commitment(note: Note, commitment: Field) {\n assert(get_note_commitment(note) == commitment, \"Note commitment is not valid\");\n}\n\npub fn get_note_commitment(note: Note) -> Field {\n if (note.kind == 0) {\n assert(note.value == 0, \"Padding notes must be zero value\");\n 0\n } else {\n poseidon2::Poseidon2::hash(\n [0x2, note.kind, note.value, note.address, note.psi, 0, 0],\n 7,\n )\n }\n}\n\npub fn get_address(secret_key: Field) -> Field {\n poseidon2::Poseidon2::hash([secret_key, 0], 2)\n}\n\npub fn check_input_note_ownership(input_note: InputNote) {\n if (input_note.note.value != 0) {\n assert(\n get_address(input_note.secret_key) == input_note.note.address,\n \"Input note is not owned by the owner\",\n );\n }\n}\n\npub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) {\n let mut first_non_zero_kind = 0;\n let mut is_multiple_kinds = false;\n\n for i in 0..4 {\n if !is_multiple_kinds {\n if notes[i].kind != 0 {\n if first_non_zero_kind == 0 {\n first_non_zero_kind = notes[i].kind;\n } else if first_non_zero_kind != notes[i].kind {\n is_multiple_kinds = true;\n }\n }\n }\n }\n\n (is_multiple_kinds, first_non_zero_kind)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/note.nr"},"57":{"source":"use poseidon::poseidon2;\nuse crate::note::{check_input_note_ownership, get_note_commitment, is_multiple_kinds};\nuse crate::{InputNote, MerklePath, Note};\n\npub struct Utxo {\n pub input_notes: [InputNote; 2],\n pub output_notes: [Note; 2],\n pub input_merkle_paths: [MerklePath; 2],\n}\n\nimpl Utxo {\n pub fn validate(\n self,\n recent_root: Field,\n input_nullifiers: [Field; 2],\n output_commitments: [Field; 2],\n ) {\n let input_commitments = [\n get_note_commitment(self.input_notes[0].note),\n get_note_commitment(self.input_notes[1].note),\n ];\n let computed_output_commitments = [\n get_note_commitment(self.output_notes[0]),\n get_note_commitment(self.output_notes[1]),\n ];\n\n assert(output_commitments[0] == computed_output_commitments[0], \"Invalid output commitment 0\");\n assert(output_commitments[1] == computed_output_commitments[1], \"Invalid output commitment 1\");\n\n assert(\n input_nullifiers[0] == expected_nullifier(self.input_notes[0].note, input_commitments[0]),\n \"Invalid nullifier 0\",\n );\n assert(\n input_nullifiers[1] == expected_nullifier(self.input_notes[1].note, input_commitments[1]),\n \"Invalid nullifier 1\",\n );\n\n self.output_notes[0].value.assert_max_bit_size::<240>();\n self.output_notes[1].value.assert_max_bit_size::<240>();\n\n verify_input_membership(input_commitments[0], self.input_merkle_paths[0], recent_root);\n verify_input_membership(input_commitments[1], self.input_merkle_paths[1], recent_root);\n\n check_input_note_ownership(self.input_notes[0]);\n check_input_note_ownership(self.input_notes[1]);\n\n let (is_multiple_kinds, _) = is_multiple_kinds([\n self.input_notes[0].note,\n self.input_notes[1].note,\n self.output_notes[0],\n self.output_notes[1],\n ]);\n assert(!is_multiple_kinds, \"Inconsistent kinds are not allowed\");\n }\n}\n\nfn expected_nullifier(note: Note, commitment: Field) -> Field {\n if commitment == 0 { 0 } else { poseidon2::Poseidon2::hash([commitment, note.psi], 2) }\n}\n\nfn verify_input_membership(commitment: Field, merkle_path: MerklePath, recent_root: Field) {\n if commitment != 0 {\n assert(merkle_path.validate(commitment, recent_root), \"Input commitment is not in recent root\");\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/utxo.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"95":{"source":"use common::{get_note_commitment, InputNote, MerklePath, Note, Utxo};\nuse poseidon::poseidon2;\n\nfn main(\n utxo: Utxo,\n burn_recipient_private: Field,\n recent_root: pub Field,\n input_nullifiers: pub [Field; 2],\n output_commitments: pub [Field; 2],\n burn_recipient_public: pub Field,\n burn_value: pub Field,\n) {\n burn_value.assert_max_bit_size::<240>();\n\n let input_value = utxo.input_notes[0].note.value + utxo.input_notes[1].note.value;\n let output_value = utxo.output_notes[0].value + utxo.output_notes[1].value;\n assert(input_value == output_value + burn_value, \"Burn output must match burn value\");\n\n assert(\n burn_recipient_private == burn_recipient_public,\n \"Burn recipient private/public mismatch\",\n );\n\n utxo.validate(recent_root, input_nullifiers, output_commitments);\n}\n\n#[test]\nfn test_burn_one_input_one_output() {\n let pk: Field = 101;\n let address = common::get_address(pk);\n let burn_recipient = 77;\n\n let note_1 = Note { kind: 1, value: 10, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n let note_3 = Note { kind: 1, value: 4, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n\n let input_commitment_1 = get_note_commitment(note_1);\n let output_commitment_1 = get_note_commitment(note_3);\n let output_commitment_2 = get_note_commitment(note_4);\n\n let input_path_1 = MerklePath { path: [0; 160] };\n let input_path_2 = MerklePath { path: [0; 160] };\n let recent_root = input_path_1.root_from_leaf(input_commitment_1);\n let utxo = Utxo {\n input_notes: [input_note_1, input_note_2],\n output_notes: [note_3, note_4],\n input_merkle_paths: [input_path_1, input_path_2],\n };\n\n main(\n utxo,\n burn_recipient,\n recent_root,\n [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0],\n [output_commitment_1, output_commitment_2],\n burn_recipient,\n 6,\n );\n}\n\n#[test(should_fail)]\nfn test_burn_rejects_bad_recipient_binding() {\n let pk: Field = 101;\n let address = common::get_address(pk);\n\n let note_1 = Note { kind: 1, value: 10, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n let note_3 = Note { kind: 1, value: 4, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n\n let input_commitment_1 = get_note_commitment(note_1);\n let output_commitment_1 = get_note_commitment(note_3);\n let output_commitment_2 = get_note_commitment(note_4);\n\n let input_path_1 = MerklePath { path: [0; 160] };\n let input_path_2 = MerklePath { path: [0; 160] };\n let recent_root = input_path_1.root_from_leaf(input_commitment_1);\n let utxo = Utxo {\n input_notes: [input_note_1, input_note_2],\n output_notes: [note_3, note_4],\n input_merkle_paths: [input_path_1, input_path_2],\n };\n\n main(\n utxo,\n 77,\n recent_root,\n [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0],\n [output_commitment_1, output_commitment_2],\n 88,\n 6,\n );\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/evm/burn/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/erc20_transfer/key b/fixtures/circuits/erc20_transfer/key new file mode 100644 index 0000000..205381d Binary files /dev/null and b/fixtures/circuits/erc20_transfer/key differ diff --git a/fixtures/circuits/erc20_transfer/key_fields.json b/fixtures/circuits/erc20_transfer/key_fields.json new file mode 100644 index 0000000..87e1632 --- /dev/null +++ b/fixtures/circuits/erc20_transfer/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000013", + "0x0000000000000000000000000000000000000000000000000000000000000018", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000333a2ad551f94921edeaa1fed8461fa0f2", + "0x000000000000000000000000000000000007dd2fb3d459343918dcc6c7d27c3a", + "0x000000000000000000000000000000a729ddb81abd053f97749437c276cf068b", + "0x00000000000000000000000000000000001b6c840372d8bebc74bd099f6f95a6", + "0x0000000000000000000000000000003bc7b56496abbd2e6139d766c8705f4237", + "0x00000000000000000000000000000000001674e321a25f84cdb57904d7c062fc", + "0x0000000000000000000000000000005133dc496c26ba6e753bfd9ee180d10eef", + "0x000000000000000000000000000000000000dd504b0ae5154492868605ff08f0", + "0x0000000000000000000000000000003d22c465cb171ef6659257101f57538405", + "0x00000000000000000000000000000000000bdde0cde9247c6ec0a1fc97a0f857", + "0x000000000000000000000000000000876b4fd5354a724504a79236de3928595e", + "0x00000000000000000000000000000000002417617ea9c1be1d45b7be0d9565a0", + "0x00000000000000000000000000000012015fee10d9d938c9ce4963234c4d2064", + "0x000000000000000000000000000000000013f6d8743e61d0e0528ee0386a1025", + "0x00000000000000000000000000000058722d5f22e3657c98871224d1097de7b7", + "0x00000000000000000000000000000000000fc56655ecffa3f380fdaf24d11067", + "0x00000000000000000000000000000066d57ba54d2fdaf9ee0b273d7d73a38c0c", + "0x000000000000000000000000000000000013bffdb3b032439bff4ea95df94255", + "0x000000000000000000000000000000459b58d75333ee90e665b59979da39b6b5", + "0x00000000000000000000000000000000001283e3f4e44288693afb0475323706", + "0x000000000000000000000000000000a1e4b2be553ed11198a07cb92de6b9d4ab", + "0x00000000000000000000000000000000002e306768dc0e951247a02348426613", + "0x00000000000000000000000000000054fd22d5df78adf8a7d28730414d589c77", + "0x000000000000000000000000000000000024763c9c85777129207def658a2333", + "0x000000000000000000000000000000e9d1e8e99a3adc0891ccba6854ad189e23", + "0x0000000000000000000000000000000000106effed49568ed8e7217ac8d781c2", + "0x000000000000000000000000000000c662cf51fd9cf1d85a53a9089aa1f6ec53", + "0x0000000000000000000000000000000000043968a2c483f3b6e214d4f20eeb4a", + "0x0000000000000000000000000000004782ffb1bb21cdf2a3f8f68b8b425922a9", + "0x000000000000000000000000000000000010d4ef639228cf09042197abb5a0f6", + "0x0000000000000000000000000000009e318585a75f2643e19d1f7e986f3201dd", + "0x00000000000000000000000000000000001b3969742ffe0324f0a1ec1f136bf6", + "0x000000000000000000000000000000048b34b8c3de6445a528e4ce3078c4b19d", + "0x00000000000000000000000000000000001203d3ef00ca580570b0dbff847988", + "0x0000000000000000000000000000009978f49368e07d275edc0c2f022ff46b92", + "0x0000000000000000000000000000000000224b2b9f0022d99dd2e292a358f21d", + "0x0000000000000000000000000000001ef27231eb944ea41c57cb3265ec73a246", + "0x0000000000000000000000000000000000255f07901f264a864dfcb6293ac754", + "0x000000000000000000000000000000c0a2b18cf7451efe48092048f0713f543b", + "0x000000000000000000000000000000000025dfa016e20af880282462309a94f8", + "0x000000000000000000000000000000b4da34c441e25c012e31af48718e28c871", + "0x000000000000000000000000000000000009928e5c8d3bb49b728823cdbd172d", + "0x00000000000000000000000000000019d1029f6943ecb377898dda582d70f680", + "0x00000000000000000000000000000000000221a6b0ef16e943d253984c88a26c", + "0x00000000000000000000000000000038cd68fe6fb702a73c048e4eb6026e9a83", + "0x0000000000000000000000000000000000061ceb701164e21b6840061825d791", + "0x0000000000000000000000000000009614812be7756e091fbbe209353da4fdbb", + "0x0000000000000000000000000000000000190163fcf14e329c61be8d34705127", + "0x0000000000000000000000000000008a351cad22becb4a60e574184261711591", + "0x00000000000000000000000000000000000e8ea27a75ddaaca43c046c155509b", + "0x0000000000000000000000000000003a931d56336b7b896cf607d6be6ec8d49b", + "0x00000000000000000000000000000000002bb96d960df4d084713ded12b7e37a", + "0x00000000000000000000000000000029264336a493776fcd8914d452490caad4", + "0x00000000000000000000000000000000001569fe2bc5f7c623ea9bca9ab6917e", + "0x000000000000000000000000000000a2b91b3a641ea0141d52ebc051e2642e78", + "0x00000000000000000000000000000000000c69c92b4ca60c9fa0e59dbe139b90", + "0x0000000000000000000000000000001ef19e05166ca7eb6d03fcb05dc632d8d9", + "0x00000000000000000000000000000000002e62b0874d7ab7a0b6560f898d4710", + "0x00000000000000000000000000000013e6f7ab1a92c0f8ceeffd3d12011c3c71", + "0x000000000000000000000000000000000001ad0aefbe6d58e4b0f2c6ae90e753", + "0x000000000000000000000000000000f30dd7f205c547e3aefc61db5fb3619433", + "0x00000000000000000000000000000000001d8fe71281dfca1c431f036211e05d", + "0x000000000000000000000000000000a7f2f5d2e77fc91687375f1d56e97f50d5", + "0x000000000000000000000000000000000023e7efbf242d3d36ff386ff08d08dc", + "0x000000000000000000000000000000e38e2ee546fddf43e2bf08deac9d53e0f5", + "0x000000000000000000000000000000000024f558ea8225f956742e696131f1d8", + "0x000000000000000000000000000000e71cdb242f051a61bd310d666fa73923bd", + "0x00000000000000000000000000000000002c0fc9d0f0342b1e1425cd52692836", + "0x0000000000000000000000000000002ec5b5a8eccad9bce59b9c3df7bf3d5696", + "0x00000000000000000000000000000000000b77dce720dd93991961d52c4fdb04", + "0x000000000000000000000000000000f82600d3a82cfd0b35fdc4c5b040f28ac4", + "0x00000000000000000000000000000000000db0d1b0960c7b388d54c9c472d5b9", + "0x0000000000000000000000000000009fe219921490e2402d1dbfe7ed726440f4", + "0x00000000000000000000000000000000002275998e19340e031beee53bb48bf8", + "0x000000000000000000000000000000e0d70366840450b61533f2ba1938f3be73", + "0x00000000000000000000000000000000001962e7fcb48874841db06cb71c7bfb", + "0x00000000000000000000000000000010fa9e4f5cddcbad655617a2f169996138", + "0x00000000000000000000000000000000001714d4b3105a3f9dee044d46203b66", + "0x00000000000000000000000000000002b71e38f4137bad5b58a6119fda4cc09d", + "0x00000000000000000000000000000000001c0024864e1c70ca460df3621568da", + "0x000000000000000000000000000000e01f075c220c03ff759ca2e35644683137", + "0x00000000000000000000000000000000001f0621279fa3670fcd52470823ca32", + "0x000000000000000000000000000000011c8ee3e164b688b51c9ada25cbcbb71a", + "0x00000000000000000000000000000000002b09672dda091220f17ca0129284f6", + "0x0000000000000000000000000000005751c016970d02944b4d4502f2f39fce07", + "0x000000000000000000000000000000000000efa66c0e849293df7c422a5c6a27", + "0x000000000000000000000000000000962950b817c440d718adc8606dd24f5fc8", + "0x000000000000000000000000000000000012d1c3fceb16195d838e523d84edb5", + "0x000000000000000000000000000000c3a3cc44a4cc76a30a12db0ca5c451aad1", + "0x000000000000000000000000000000000020abfc116103ada32f7da8db87f3ba", + "0x0000000000000000000000000000002475010d1a03f8c4db54311d4efc556353", + "0x000000000000000000000000000000000016adae0a79535891bca65021644f91", + "0x0000000000000000000000000000009d83bccbf22b92e4c27c50ad936c7a2007", + "0x000000000000000000000000000000000027ddcc73960475c36e652d30a07801", + "0x0000000000000000000000000000005dc1f6f28ddf1143fe9ba59fc94acdaa69", + "0x00000000000000000000000000000000000a2f482dfa467301b0823ee0d7e0e4", + "0x000000000000000000000000000000d4b20bd0c6dde5ac0d5e60b713ef3e79fe", + "0x00000000000000000000000000000000001d35a673f98f656ea83208006b93b9", + "0x0000000000000000000000000000005d5418dadcf6e62152c9a4d6281c48586f", + "0x00000000000000000000000000000000002bb0ce98f2a5d9be622179da1b633d", + "0x0000000000000000000000000000002de64c2e17f52127a2f055c62bc03e8257", + "0x0000000000000000000000000000000000128fc1e62a28d1a33828e58784d6e8", + "0x000000000000000000000000000000f6b3c8837014c2e7b66fe85ecba91d4ab9", + "0x0000000000000000000000000000000000242a82bb6b6699724ac98e224b79b4", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000e3d237d75ea52286857b18bddf9eef78a1", + "0x00000000000000000000000000000000002da7a1cc87be5eaf0624e588def000", + "0x000000000000000000000000000000b8f522ebed169965d2ecc4709042a0044a", + "0x00000000000000000000000000000000002c8e5b778b06ef880aa594e4775f75" +] diff --git a/fixtures/circuits/erc20_transfer/program.json b/fixtures/circuits/erc20_transfer/program.json new file mode 100644 index 0000000..d1b5fc8 --- /dev/null +++ b/fixtures/circuits/erc20_transfer/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"7371096539956471904","abi":{"parameters":[{"name":"chain_id","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"},{"name":"bridge_address","type":{"kind":"field"},"visibility":"public"},{"name":"original_transfer","type":{"kind":"struct","path":"ERC20Transfer","fields":[{"name":"chain_id","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"nonce","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"max_priority_fee_per_gas","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"max_fee_per_gas","type":{"kind":"integer","sign":"unsigned","width":128}},{"name":"gas_limit","type":{"kind":"integer","sign":"unsigned","width":64}},{"name":"token_address","type":{"kind":"array","length":20,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"receiver","type":{"kind":"array","length":20,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"amount","type":{"kind":"field"}}]},"visibility":"private"},{"name":"signature","type":{"kind":"struct","path":"signature::Signature","fields":[{"name":"r","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"s","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"sender_pubkey_x","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"sender_pubkey_y","type":{"kind":"array","length":32,"type":{"kind":"integer","sign":"unsigned","width":8}}}]},"visibility":"private"},{"name":"input_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"address","type":{"kind":"array","length":20,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"token","type":{"kind":"array","length":20,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"value","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},"visibility":"private"},{"name":"input_note_merkle_proofs","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::MerklePath","fields":[{"name":"path","type":{"kind":"array","length":160,"type":{"kind":"field"}}}]}},"visibility":"private"},{"name":"input_note_merkle_root","type":{"kind":"field"},"visibility":"public"},{"name":"new_nullifiers","type":{"kind":"array","length":3,"type":{"kind":"field"}},"visibility":"public"},{"name":"output_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"address","type":{"kind":"array","length":20,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"token","type":{"kind":"array","length":20,"type":{"kind":"integer","sign":"unsigned","width":8}}},{"name":"value","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},"visibility":"private"},{"name":"new_commitments","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"}],"return_type":null,"error_types":{"361444214588792908":{"error_kind":"string","string":"attempt to multiply with overflow"},"819864067177566446":{"error_kind":"string","string":"Field failed to decompose into specified 8 limbs"},"1998584279744703196":{"error_kind":"string","string":"attempt to subtract with overflow"},"4703047920556725948":{"error_kind":"string","string":"Field failed to decompose into specified 254 limbs"},"10798863403024012940":{"error_kind":"string","string":"Not enough funds for transfer"},"12469291177396340830":{"error_kind":"string","string":"call to assert_max_bit_size"},"12671805026295133725":{"error_kind":"string","string":"Invalid signature"},"14401109495927734611":{"error_kind":"string","string":"Field failed to decompose into specified 16 limbs"},"14990209321349310352":{"error_kind":"string","string":"attempt to add with overflow"},"15764276373176857197":{"error_kind":"string","string":"Stack too deep"},"15835548349546956319":{"error_kind":"string","string":"Field failed to decompose into specified 32 limbs"},"17258424731356848914":{"error_kind":"string","string":"Payload length outside supported range"}}},"bytecode":"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NvsHzEEAs3+COQyzOQBgDgqYAxDMYZnNAQFzMMAckGAOx2wOBJiDA+ZABHN4ZnNgwBwCMAcmmH9iNgcBzCEBcxCCOQKzOShgDgWYgxLMPzObgwHm0IA5GMEckdkcHDCHAczBCeZIzOYQgDksYA5BMEdmNocEzOEAc0iCOQqzORRgDg+YQxHMUZnNoQHzT4A5NMEcjdkcBjBHAMxhCObozOawgPlnwByWYI7BbA4HmCMC5nAEsy+zOTxgjgSYwxPMMZnNPwHmyID5J4I5FrM5AmCOApgjEMyxCWYfM0L/OcPnf49j1hbXjHhmxDcjgRkJzUhkRmIzkpiR1IxkZiQ3I4UZKc1IZUZqM9KYkdaMdGakNyODGRnNyGRGZjOymJHVjGxmZDcjhxk5zchlRm4z8piR14x8ZuQ3o4AZBc0oZEZhM4qYUdSMYmYUN6OEGSXNKGVGaTPKmFHWjHJmlDejghkVzahkRmUzqphR1YxqZlQ3o4YZNc2oZUZtM+qYUdeMembUN6OBGQ3NaGRGYzOamNHUjGZmNDejhRktzWhlRmsz2pjR1ox2ZrQ3o4MZHc3oZEZnM7qY0dWMbmZ0N6OHGT3N6GVGbzP6mNHXjH5m9DdjgBkDzRhkxmAzhpgx1IxhZgw3Y4QZI80YZcZoM8aYMdaMcWaMN2OCGRPNmGTGZDOmmDHVjGlmTDdjRtDP94W390m39w2399G295W291m29x229+G196W192m19y219/G097W093m09z209wG098Wz94mz902z9xGz99Wy95my912y9yGy9+Wx96mx922x9zGx9/Ww97mw932w90Gw9wWw18m3142311G31xW319m2152212G21yW21+m1162113G11zW11/m0172014G010W01wm0182z15Gz11Wz1xmz192y16Gy12Wy1ymy1+2x17Gx13Wx1zmx1/2w18Gw14Ww10mw1w2w76O37yu377O27zu278O170u179O071u07+Oz72uz7/Oy73uy7wOy74ux7xOx75uw7yOwr6u3rzO3r7u2r0O2r8u1r1O1r9u0r2O0r+uzr3Ozr/uyr4Oyrwuyr5Oxrxuxr6Owryuwv2e3v3e2v4e1v5e0v6ezv7eyv8exv9ewP+e3P/e2Pwe2Pxe1Pye0PzezP0eyP1exP2ewf++2fw+1fy+zf0+x5+32PNae19nz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5qGAeRRgHkowT2I2DwPMowHzMIJ5MrN5OGAeA5iHE8xTmM0jAPNYwDyCYJ7KbB4JmMcB5pEE8zRm8yjAPB4wjyKYpzObRwPmCYB5NME8g9k8BjBPBMxjCOaZzOaxgHkSYB5LMM9iNo8DzJMB8ziCeTazeTxgngKYxxPMc5jNEwDzVMA8gWCey2yeCJinAeaJBPM8ZvMkwDwdME8imOczmycD5hmAeTLBvIDZPAUwzwTMUwjmhczmqYB5FmCeSjAvYjZPA8yzAfM0gnkxs3k6YJ4DmKcTzEsIZh87Kf84wq//XmrXtszOcjsr7Ky0s8rOajtr7Ky1s87Oejsb7Gy0s8nOZjtb7Gy1s83Odjs77Oy0s8vObjt77Oy1s8/OfjsH7By0c8jOYTtH7By1c8zOcTsn7Jy0c8rOaTtn7Jy1c87OeTsX7Fy0c8nOZTtX7Fy1c83OdTs37Ny0c8vObTt37Ny1c8/OfTsP7Dy088jOYztP7Dy188zOczsv7Ly088rOaztv7Ly1887Oezsf7Hy088nOZztf7Hy1883Odzs/7Py042XfH952AtjxsRPQTiA7ge0EsRPUTjA7we2EsBPSTig7oe2EsRPWTjg74e1EsBPRTiQ7ke1EsRPVTjQ70e3EsBPTTiw7se3EcR8LduLaiWcnvp0EdhLaSWQncb5f94V390l39w1399F295V291l29x129+F196V192l19y119/F097V093l09z109wF098Vz94lz901z9xFz99Vy95ly911y9yFy9+Vx96lx921x9zFx9/Vw97lw931w90Fw9wVw++S7fePdPupuX3G3z7bbd9rtw+z2JXb79Lp9a90+rm5fU7fPp9v30u0D6fZFdPsEun3z3D5ybl81t8+Y23fL7UPl9mVy+xS5fXvcPjZuXxe3z4nb98Ptg+H2hXD7JLh9A9x19O66cnedtbvu2F2H665LdddpuusW3XV87ro2d52Xu+7JXQfkrotx14m46ybcdQTuvHp3nrk779qdh+zOy3XnqbrzNt15jO68Pneemzvvy50H5c4LcufJuPNG3HkU7rwC93N293Nn93NY93NJ93M693Mr93Mc93MN9zy/e97bPQ/snhd1zxO6583c80jueRX3PIP7vtt9H+q+L3Pfp7iv293Xse7rOvd1jvu87z4Pus8L7nHSPW786wGH+PjkHtfm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G2ZmuJkRZkaaGWVmtJkxZsaaGWdmvJkJZiaamWRmspkpZqaamWZmupkZZmaamWVmtpk5ZuaamWdmvpkFZhaaWWRmsZklZpaaWWZmuZkVZlaaWWVmtZk1ZtaaWWdmvZkNZjaa2WTG38xmMwFmtpjZamabme1mdpjZaWaXmd1m9pjZa2afmf1mDpg5aOaQmcNmjpg5auaYmeNmTpg5aeaUmdNmzpg5a+acmfNmLpi5aOaSmctmrpi5auaametmbpi5aeaWmdtm7pi5a+aemftmHph5aOaRmcdmnph5auaZmedmXph5aeaVmddm3ph5a+admfdmPpj5aOaTmUAzn818MfPVzDcz3838MPPTjEcj+4Sy+fwz42UmeKNf94W390m39w2399G295W291m29x229+G196W192m19y219/G097W093m09z209wG098Wz94mz902z9xGz99Wy95my912y9yGy9+Wx96n5474tjX7d18Pe58Le98HeB8HeF8BeJ99eN95eR91eV9xeZ9ted9peh9lel9hep9det9Zex9Ve19Re59Ne99JeB9JeF9FeJ9BeN89eR85eV81eZ8xed8teh8pel8lep8het8dex8Ze18Ve58Re98NeB8NeF8JeJ8FeN8CeR2/PK7fnWdvzju15uPa8VHuepj1v0Z7HZ89rs+d52fOe7HlA9rwYe56IPW/Cnkdgj6u3x5nb467tccj2uFx7nKo9btMex2iP67PHudnjvuxxUPa4IHucjD1uxB5HYY8rsK+z29ed7euw9nVJ+zqdfd3Kvo5jX9ewz/Pb573t88D2eVH7PKF93sw+j2SfV7HPM9ifu+3PofbnMvtziv2+3X4fa7+vs9/n2K/79uug/bpgHyft48a/HnCIj0/2ca2f33++3+8eq46Y93B5uP9G3Vd/s6cBwL6OEvf115sXcZ2hjdy3EFp5HmXuGuhtPl+ArsPc90L7sj3tGtR9DSfsy37tLvgP/93lQXuj2oY34l9jBHEN6vcxz7z//XPAnc8XuyfqOiMIa4yU+9h7/v0fXG69m8zHfqSCvwMewfnXGKWgQxiBDqMVdPjhxb/GGAUdwgt8PoxV0CGiQIdxCjpEFugwXkGHqAIdJijoEF2gw0QFHWIKdJikoENsgQ6TFXSIK9BhioIO8QU6TFXQIaFAh2kKOrgEOkxX0CGJQIcZCjok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","debug_symbols":"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HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnQedB50HnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnovN3efT9/5HBeKdHP07nnt47/zj9eN8v3vnRj5M4FaeHEzPoXHQuOhedi85F56Jz0bnoXHQuOhedi85F56Jz0bnoXHQuOhedi85F56Jz0bnoXHQuOhedi85F56Jz0bnoXHQuOhedi85F56Jz0bnoXHQuOhedi85F56Jz0bnoXHQuOhedi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86Lzouv58XX8+LrefH1vPh6Xnw9L76eF1/Pi6/nRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnD50/dP7Q+UPnTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedN503nTedD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50PnQ+dD50vnS+dL50vnS+dL50vnS+dL50vnS+dL50vnS+dL50vnwLJAlgW0LLBlAS4LdFnAywJfFgCzQJgFxCwwZgEyC5RZwMwCZxZAs0CaBdQssGYBNgu0WcDNAm8WgLNAnAXkLDBnAToL1FnAzgJ3FsCzQJ4F9CywZwE+C/RZwM8CfxYAtECgBQQtMGgBQgsUWsDQAocWQLRAogUULT4sWr+fltN9z/KDo32cgtN9z/JDpH2citPDqTnxedA5Li2AaYFMC2haYNMCnBbotICnBT4tAGqBUAuIWmDUAqQWKLWAqQVOLYBqgVQLqFpg1QKsFmi1gKsFXi0Aa4FYC8haYNYCtBaotYCtBW4tgGuBXAvoWmDXArwW6LWArwV+LQBsgWALCFtg2ALEFii2gLEFji2AbIFkCyhbYNkCzBZotoCzBZ4tAG2BaAtIW2DaAtQWqLaAtQWuLYBtgWwLaFtg2wLcFui2gLcFvi0AboFwC4hbYNwC5BYot4C5Bc4tgG6BdAuoW2DdAuwWaLeAuwXeLQBvgXgLyFtg3gL0Fqi3gL0F7i2Ab4F8C+hbYN8C/Bbot4C/Bf4tAHCB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Jzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDi+XDi+XDi+XDi+XDi+XDi+XDi+XDi+XDi+XDi+XDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HDCwwkPJzyc8HD68HD9fgpOyUmcitOP9yz14eE+TsNpOZ17onM8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8nPBwwsMJDyc8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MiOZkcxIZiQzkhnJjGSGmCFmiBlihpghZogZYoaYIWYUM4oZxYxiRjGjmFHMKGYUM4oZDzMeZjzMeJjxMONhxsOMhxkPMx5mNDOaGc2MZkYzo5nRzGhmNDOaGcOMYcYwY5gxzBhmDDOGGcOMYcYyY5mxzFhmLDOWGcuMZcYyY5lxmHGYQedB50HnQedB50HnQedB50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnSedJ50nnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdC46F52LzkXnonPRuehcdF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50XnRedF50/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5Q+cPnT90/tD5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8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc4uEWD7d4uMXDLR5u8XCLh1s83OLhFg+3eLjFwy0ebvFwi4dbPNzi4RYPt3i4xcMtHm7xcIuHWzzc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P07BKTmJU3F6ODWn4bScmBHMCGYEM4IZwYxgRjAjmBHMCGYkM5IZyYxkRjIjmZHMSGYkM5IZYoaYIWaIGWKGmCFmiBlihphRzChmFDPovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86LzovOi86Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6Pyh84fOHzp/6LzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpvOm86bzpfOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86HzofOh86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl86XzpfOl8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u6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvau6S9S9q7pL1L2rukvUvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxLxrtkvEvGu2S8S8a7ZLxL1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S9a7ZL1L1rtkvUvWu2S9S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4l73513z6O5eP3aftxbB/Hx/XxcPQuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOd4lx7vkeJcc75LjXXK8S453yfEuOeySeGOXxBu7JN7YJfHGLok3dkm8sUvijV0Sb+ySeGOXxNubp4WnhaeFp4WnhaeFp4WnhaeFp4Wnpaelp6Wnpaelp6Wnpaelp6WnpafJ0+Rp8jR5mjxNniZPk6fJ0+Rp5WnlaeVp5WnlaeVp5WnlaeVp5WmPpz2e9nja42mPpz2e9nja42mPpz2e1p7Wntae1p7Wntae1p7Wntae1p42njaeNp42njaeNp42njaeNp42nraetp62nraetp62nraetp62nraedjzteNrxtONpx9OOpx1PO552PM27JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS8S8K7JLxLwrskvEvCuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rskvUvSuyS9S9K7JL1L0rtE3iXyLpF3ibxL5F0i7xJ5l8i7RN4l8i6Rd4m8S+RdIu8SeZfIu0TeJfIukXeJvEvkXSLvEnmXyLtE3iXyLpF3ibxL5F0i7xJ5l8i7RN4l8i6Rd4m8S+RdIu8SeZfIu0TeJfIukXeJvEvkXSLvEnmXyLtE3iXyLpF3ibxL5F0i7xJ5l8i7RN4l8i6Rd4m8S+RdIu8SeZfIu0TeJfIukXeJvEvkXSLvEnmXyLtE3iXyLpF3ibxL5F0i7xJ5l8i7RN4l8i6Rd4m8S+RdIu8SeZfIu0TeJfIukXeJvEvkXSLvEnmXyLtE3iXyLpF3ibxLyrukvEvKu6S8S8q7pLxLyrukvEvKu6S8S8q7pLxLyrukvEvKu6S8S8q7pLxLyrukvEvKu6S8S8q7pLxL7F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexe4929vr9JHe/u9R7lY/n4+HjfxY4P9/rjuD4eju+75MfRn5t3id1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvYbda9i9ht1r2L2G3WvYvcbxLjneJce75HiXHO+S411yvEvsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNexew+417F7D7jXsXsPuNe1e0+41393r+5vU+e5e77F8fHxsH++72PnhXn8cD8d48zF8TAazS9LuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNf281/TzXtPPe00/7zX9vNf0817Tz3tNP+81/bzX9PNe0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXtPuNe1e0+417V7T7jXtXvPdvX68Sf3uXu/x8bF9HB95F/vDvX4c683H8DF99OfmXWL3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p95p2r2n3mnavafeadq9p9yq7V9m9ys97lZ/3Kj/vVX7eq/y8V/l5r/LzXuXnvcrPe5Wf9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq96d6/vb1Lr3b3eY/s4Pq6P911sfbjXH8fwMX2Uj/7cxp/b+HMbf27jz238ua0/t/Xntv7c1p/betp62nraetp62nra8bTjacfTjqcdTzuedjzteNrxNO8Su1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1f5ea/y817l573Kz3uVn/cqP+9Vft6r/LxX+Xmv8vNeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVe/u9eNN6nf3eo/j4/p47vHDve7HMXxMH+Vj+cjnZvcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrtX2b3K7lV2r7J7ld2r7F5l9yq7V9m9yu5Vdq+ye5Xdq+xeZfcqu1fZvcruVXavsnuV3avsXmX3KrvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey271/LzXsvPey0/77X8vNfy817Lz3stP++1/LzX8vNey897LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eyey2717J7LbvXsnstu9eye6139/r+JnW9u9d7XB8Px++75B7vu9j14V5/HOVj+fj46M/Nu8Tutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutfy81/LzXsvPey0/77X8vNfy817Lz3stP++1/LzX8vNey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXsvutexey+617F7L7rXsXuvdvX68Sf3uXu+Rd7Hf3es9ho+8i/3hXn8cy8fHx/bRn5t3id1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b2W3WvZvZbda9m9lt1r2b3+f0zcu5ElRxIFUZUm41/6K7aL6QbcuaBwrRi3sX4HWbjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61cK+Fey3ca+FeC/dauNfCvRbutXCvhXst3GvhXgv3WrjXwr0W7rVwr4V7Ldxr4V4L91q418K9Fu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfmvdfmvdfmvdfmvdfmvdfmvdfmvdfmvdfmvdfmvdfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXvtv+717x+p+697/T2/P5yPMzj//St2/7jX37M5h3M5+TZagntt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3ntt3ntt3ntt3ntt3ntt3ntt3ntt3ntt3ntt3ntt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjX/utef/5I/de9/ns+zuBMzv/+iv3jXn/P4VzO4+TbaAnutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXhv32rjXxr027rVxr417bdxr414b99q418a9Nu61ca+Ne23ca+NeG/fauNfGvTbutXGvjXtt3GvjXgf3OrjXwb0O7nVwr4N7Hdzr4F4H9zq418G9Du51cK+Dex3c6+BeB/c6uNfBvQ7udXCvg3sd3OvgXgf3OrjXwb0O7nVwr4N7Hdzr4F4H9zq418G9Du51cK+Dex3c6+BeB/c6uNfBvQ7udXCvg3sd3OvgXgf3OrjXwb0O7nVwr4N7Hdzr4F4H9zq418G9Du51cK+Dex3c6+BeB/c6uNfBvQ7udXCvg3sd3OvgXgf3OrjXwb0O7nVwr4N7Hdzr4F4H9zq418G9Du51cK+Dex3c6+BeB/c6uNfBvQ7udXCvg3sd3OvgXgf3OrjXwb0O7nVwr4N7Hdzr4F4H9zq418G9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urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNflvdflvdflvdflvdflvdflvdflvdflvdflvdflvdfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3vdv+717x+p9697/fcszuYczn//ir0/7vX3/P474w/n4+TbaAnudXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXnvdXnvdXnvdXnvdXnvdXnvdXnvdXnvdXnvdXnvdXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXveve/35I/Vf9/rv2ZzDuZz//RX7x73+nP2H83EGJ99GS3Cvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvi3td3OviXhf3urjXxb0u7nVxr4t7Xdzr4l4X97q418W9Lu51ca+Le13c6+JeF/e6uNfFvS7udXGvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvx3uvx3uvx3uvx3uvx3uvx3uvx3uvx3uvx3uvx3uvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3en/d698/Ut9f9/rvOZzLeZz//hX7ftzr7/k4gzM5+TZagns93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q418O9Hu71cK+Hez3c6+FeD/d6uNfDvR7u9XCvh3s93OvhXg/3erjXw70e7vVwr4d7Pdzr4V4P93q4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+1j7WPtY+1j7WPvbkvs5j/P7OePPX/f67/n/tffnz88dulN3/XO/n7t1j+7Vfbo/7n+i8t/9dIfu1K3dp92n3afdp92n3dBuaDe0G9oN7YZ2Q7uh3dBuaDe1m9pN7aZ2U7up3dRuaje1m9ot7ZZ2S7ul3dJuabe0W9ot7ZZ2W7ut3dZua7e129pt7bZ2W7ut3dHuaHe0O9od7Y52R7uj3dHuaHe1u9pd7a52V7ur3dXuane1u9o97Z52T7un3dPuafe0e9o97Z52P+1+2v20+2n30+6n3U+7n3Y/7X7s/qW1/91Pd+hO3aW7dY/u1X26tatePfXqqVdPvXrq1VOvnnr11KunXj316qlXT7166tVTr5569dSrp1499eqpV0+9eurVU6+eevXUq6dePfXqqVdPvXrq1VOvnnr11KunXj316qlXT7166tVTr5569dSrp1499eqpV0+9eurVU6+eevXUq6dePfXqqVdPvXrq1VOvnnr11KunXj316qlXT7166tVTr5569dSrp1499eqpV0+9eurVU6+eevXUq6dePfXqqVdPvXrq1VOvnnr11KunXj316qlXT7166tVTr5569dSrp1499SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrUq1CvQr0K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9SrVq1SvUr1K9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arUq1KvSr0q9arVq1avWr1q9arVq1avWr1q9arVq1avWr1q9arVq1avWr1q9arVq1avWr1q9arVq1avWr3qn17Fz126/+7++blH9+o+3R+3etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejX699Xo31ejf1+N/n01+vfV6N9Xo39fjXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWoV6NejXo16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWqV6terXq16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWpV6denXp16tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeferVp1596tWnXn3q1adeffTq/aFX7w+9en/o1ftDr558+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/5+fXv83KE7dZfu1v3f7xrv17f/3qf74/7p1e+t7x197+h7R987+t7R946+d/S9o+9dfe9qd7W72l3trnZXu6vd1e5q97R72j3tnnZPu6fd0+5p97R72v20+2n30+6n3U+7n3Y/7X7a/bSrXsm3//9+ukN36i7drXt0r+7TrV31Sr79ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/5avWr1qtWrVq9avWr1qtUr+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+5Nvf/LtT779ybc/+fYn3/7k2598+/v17fFzp+7S3bpHN79r/Pr235vfNX59++/9dOt71Sv59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u1Pvv3Jtz/59iff/uTbn3z7k29/8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHnq/PfR+e+j99tD77aH320Pvt4febw+93x56vz30fnvIt4d8e8i3h3x7yLeHfHvIt4d8e8i3h3x7yLeHfHvIt4d8e8i3h3x7yLeHfHvIt4d8e8i3h3x7yLeHfHvIt4d8e8i3h3x7yLeHfHvIt4d8e8i3h3x7yLeHfHvIt4d8e8i3h3z7P//jiu7QnbpLd+se3av7dGtXvZJvD/n2+PXt8XOX7tY9ulf3f79rxK9v/7njj+6nO3Tre9Ur+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+faQbw/59pBvD/n2kG8P+fbQ++2h99tD77eH3m8Pvd8eer899H576P320PvtoffbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k20O+PeTbQ7495NtDvj3k2+PXt8fP3bpH9+o+3fyu8evbf++nO3Snbn2veiXfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtId8e8u0h3x7y7SHfHvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7Snf/v/76Q7dqbt0t+7RvbpPt3bVK/n2lG9Pvd+eer899X576v321PvtqffbU++3p95vT73fnnq/PeXbU7495dtTvj3l21O+PeXbU7495dtTvj3l21O+PeXbU7495dtTvj3l21O+PeXbU7495dtTvj3l21O+PeXbU7495dtTvj3l21O+PeXbU7495dtTvj3l21O+PeXbU7495dtTvj3l21O+PeXbU7495dtTvj3l21O+PeXbU7495dtTvj1/fXv83KN7dZ/uj/v++10jf3377x26U3fp1veqV/LtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtKd+e8u0p357y7SnfnvLtqffbU++3p95vT73fnnq/PfV+e+r99tT77an321Pvt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrfnr2+Pn3t1n25+1/j17b83v2v8+vbfO3WX7tbN98q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3p3x7yrenfHvKt6d8e8q3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8+//vpzt0p+7S3bpH9+o+3dpVr+TbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr3k20u+veTbS7695NtLvr30fnvp/fbS++2l99tL77eX3m8vvd9eer+99H576f32km8v+faSby/59pJvL/n2km8v+faSby/59pJvL/n2km8v+faSby/59pJvL/n2km8v+faSby/59pJvL/n2km8v+faSby/59pJvL/n2km8v+faSby/59pJvL/n2km8v+faSby/59pJvL/n2km8v+faSby/59pJvL/n2km8v+faSby/59vr17fFzn+6Pu/7ofrr/+12jfn377126W/fo1veqV/LtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtJd9e8u0l317y7SXfXvLtpffbS++3l95vL73fXnq/vfR+e+n99tL77aX320vvt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybfXr2+Pn5vfNX59++/9dIduftf49e2/d+se3atb36teybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8m3l3x7ybeXfHvJt5d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt///frpDd+ou3a17dK/u061d9Uq+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21vvt7feb2+93956v731fnvr/fbW++2t99tb77e33m9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZv71/f/s9vFv3r23/vpzt0p+7/ftfoX9/+e4/u1X26+V759pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb/n2lm9v+faWb2/59pZvb73f3nq/vfV+e+v99tb77a3321vvt7feb2+93956v73l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW7695dtbvr3l21u+veXbW769f317/NxPd+hO3aWb3zV+ffvvvbpP98etXsm3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7e3fHvLt7d8e8u3t3x7y7ePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7/++nO3Sn7tLdukf36j7d2lWv5NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn30fvvo/fbR++2j99tH77eP3m8fvd8+er999H776P32kW8f+faRbx/59pFvH/n2kW8f+faRbx/59pFvH/n2kW8f+faRbx/59pFvH/n2kW8f+faRbx/59pFvH/n2kW8f+faRbx/59pFvH/n2kW8f+faRbx/59pFvH/n2kW8f+faRbx/59pFvH/n2kW8f+faRbx/59pFvH/n2kW8f+faRbx/59vn17fFzh+7UXbpb93+/a8yvb/+9T/fH/dOr31vfq17Jt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt498+8i3j3z7yLePfPvIt4/ebx+93z56v330fvvo/fbR++2j99tH77eP3m8fvd8+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPvLtI98+8u0j3z7y7SPfPr++PX7u1F26W/fo5neNX9/+e/O7xq9v/72fbr5Xvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3k20e+feTbR7595NtHvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dv/fz/doTt1l+7WPbpX9+nWrnol377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtq/fbV++3r95vX73fvnq/ffV+++r99tX77av321fvt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrfvr2+Pn7t0t+7Rvbr/+11jf337z51/dD/doVvfq17Jt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt++qV/LtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7SvfvvLtK9++8u0r377y7av321fvt6/eb1+93756v331fvvq/fbV++2r99tX77evfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3r3z7yrevfPvKt698+8q3769vj5+7dY/u1X26+V3j17f/3k936E7d+l71Sr595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l21e+feXbV7595dtXvn3l20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3k20++/eTbT7795NtPvv3/99MdulN36W7do3t1n27tqlfy7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n337y7SfffvLtJ99+8u0n3356v/30fvvp/fbT++2n99tP77ef3m8/vd9+er/99H77ybeffPvJt598+8m3n3z7ybeffPvJt598+8m3n3z7ybeffPvJt598+8m3n3z7ybeffPvJt598+8m3n3z7ybeffPvJt598+8m3n3z7ybeffPvJt598+8m3n3z7ybeffPvJt598+8m3n3z7ybeffPvJt598+8m3n3z7ybeffPvJt598+/369vi5R/fqPt0f90+v8ud+ukN36i7df3fr5x7df3f75z7d33/3r2//vf/uzs8duv/u7s9dulv36F7dp/vj/unV7/10h27tPu0+7T7tPu0+7T7thnZDu6Hd0G5oN7Qb2g3thnZDu6nd1G5qN7Wb2k3tpnZTu6nd1G5pt7Rb2i3tlnZLu6Xd0m5pt7Tb2m3ttnZbu63d1m5rt7Xb2m3tjnZHu6Pd0e5od7Q72h3tjnZHu6vd1e5qd7W72l3trnZXu6vd1e5p97R72j3tnnZPu6fd0+5p97T7affT7qfdT7ufdj/tftr9tPtp92P317f/3k936E7dpbt1j+7Vfbq1q16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NejXq1ahXo16NerXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16terXq1apXq16tenXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16denXq1alXp16devWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXn3r1qVefevWpV5969alXH736/tCr7w+9+v7Qq+8Pvfr+0KvvD736/tCr7w+9+v7Qq+/PH+0+7T7tPu0+7T7tPu0+7T7tPu0+7YZ2/+nVFz/n39nv507dpfuf2ffn5x7dq/t0/zP7fv77f3P17/10h+5/dl/+3KW7dY/u1X26P+6/ufr3frpDt3ZLu6Xd0m5pt7Rb2m3ttnZbu63d1m5rt7Xb2m3ttnZHu6Pd0e5od7Q72h3tjnZHu6Pd1e5qd7W72l3trnZXu6vd1e5q97R72j3tnnZPu6fd0+5p97R72v20+2n30+6n3U+7n3Y/7X7a/bT7sfvD2/+9n+7QnbpLd+se3av7dGv3afdp92n3afdp92n3afdp92n3aTe0G9oN7YZ2Q7uh3dBuaDe0G9pN7aZ2U7vq1VOvnnr11KunXj316qlXT7166tVTr5569dSrp1499eqpV0+9eurVU6+eevXUq6dePfXqqVdPvXrq1VOvnnr11KunXj316qlXT7166tVTr5569dSrp1499eqpV0+9eurVU6+eevXUq6dePfXqqVdPvXrq1VOvnnr11KunXj316qlXT7166tVTr5569dSrp1499eqpV0+9eurVU6+eehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FehXqVahXoV6FepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lepXqVapXqV6lelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VelXqValXpV6VetXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXrV61etXqVatXP7z91c/dukf33937uU/3x/3Tq9/76Q7dqbt0t+7R/c9u/Pm5T/fH/bdX/97/7Eb83KE7df+zGz/f/rdX/96je3Wf7o/7b6/+vZ/u0J26tXvaPe2edk+7p91Pu592P+1+2v20+2n30+6n3U+7H7s/vP3f++kO3am7dLfu0b26T7d2n3afdp92n3afdp92n3afdp92n3ZDu6Hd0G5oN7Qb2g3thnZDu6Hd1G5qN7Wb2k3tpnZTu6nd1G5qt7Rb2i3tlnZLu6Xd0m5pt7Rb2m3ttnZbu63d1m5rt7Xb2m3ttnZHu6Pd0e5od7Q72h3tjnZHu6Pd1e5qd7W72lWvRr0a9WrUq1GvRr0a9WrUq1GvRr0a9WrUq1GvRr0a9WrUq1GvRr0a9WrUq1GvRr0a9WrUq1GvRr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr1a9WrVq1WvVr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr069erUq1OvTr361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq0+9+tSrT7361KtPvfrUq++/XuWfP//16p/76Q7dqbt0t+7RvbpPt3afdp92n3afdp92n3afdp92n3afdkO7od3Qbmg3tBvaDe2GdkO7od3Ubmo3tZvaTe2mdlO7qd3Ubmq3tFvaLe2Wdku7pd3Sbmm3tFvabe22dlu7rd3Wbmu3tdvabe22dke7o93R7mh3tDvaHe2Odke7o93V7mp3tbvaXe2udle7q93V7mr3tHvaPe2edk+7/2vij3YzzYL2PO9ctK0NVtWqWqtyKoFh2IoSCBAsQ7EDBIbO3UOyp79rRyi1OP8zL5tz6WX3/fOx+9h97D52H7vL7rK77P56dX7vw/2zm7/3cF/ux71/78CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq1h2l91ld9lddpdd3q8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfCq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8WrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8OpP335+7+Qu7sPd3J+/1/jTt/+5H/fn7zX+9O1/bp4XrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLV5f3q8n51eb+6vF9d3q8u71eX96vL+9Xl/eryfnXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXwavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8Wrxir496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o2+Nr2V12l91ld9lddvGKvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg7496NuDvj3o24O+Pejbg779n5tdvKJvD/r2oG8P+vagbw/69qBvD/r2oG8P+vagbw/69qBvD/r2oG8P+vagbw/69qBvD/r2oG8P+vagbw/69qBvD/r2oG+PP337+b2L+3A393D//XuN+NO3/7n3c88Xd3DzvHhF3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x6DV4NXg1eDV4NXg1eDV4NXg1eDV/TtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x707UHfHvTtQd8e9O1B3x5/+vbzex/u5h7uy/35e40/ffvvvV/cwZ3cPC9e0bcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3B3170LcHfXvQtwd9e9C3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnffs/N7t4Rd+e9O1J35707UnfnvTtSd+e9O1J35707UnfnvTtSd+e9O1J35707UnfnvTtSd+e9O1J35707UnfnvTtSd+e9O1J3578/Pbk57cnP789+fntyc9vT35+e/Lz25Of3578/Pbk57cnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K355++/fzezT3cl/tx//17jfzTt/+5gzu5i5vnxSv69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69qRvT/r2pG9P+vakb0/69uTntyc/vz35+e3Jz29Pfn578vPbk5/fnvz89uTntyc/vz3p25O+Penbk7496duTvj3p25O+Penbk7496duTvj3p25O+Penbk7496duTvj3p25O+Penbk7496duTvj3p25O+Penbk7496duTvj3p25O+Penbk7496duTvj3p25O+Penbk7496duTvj3p25O+Penbk7496duTvj3p25O+Penbk749//Tt5/ce7sv9uPdz9+fvNf707X/u5C7uw83z4hV9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170rcnfXvStyd9e9K3J3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRtxd9e9G3F3170bcXfXvRt3//QGFudvGKvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi5/fXvz89uLntxc/v734+e3Fz28vfn578fPbi5/fXvz89qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vb607ef3/tyP+793L9e/bn//r1G/enb/9zFfbibm+fFK/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r2om8v+vaiby/69qJvL/r24ue3Fz+/vfj57cXPby9+fnvx89uLn99e/Pz24ue3Fz+/vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3o24u+vejbi7696NuLvr3+9O3n937cn7/X+NO3/7mD+2e3f+/iPtzNPdw/u/N7P+6f3ftz/3r15w7u5P7Zfb/34f7Z3d97uC/3497P/evVnzu4k7u4Dze7xW6xW+wWu4fdw+5h97B72D3sHnYPu4fdw26z2+w2u81us9vsNrvNbrPb7A67w+6wO+wOu8PusDvsDrvD7mX3snvZvexedi+7l93L7mX3svvYfew+dh+7j93H7mP3sfvYfewuu8vusrvsLrvL7rK77C67+9n907f/uYM7uYv7cDf3cF/ux81usBvsBrvBbrAb7Aa7wW6wG+wmu8luspvsJrt4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1H6/O18er8/Xx6nx9vDpfH6/O18er8/Xx6nx9vDpfH6/O18er8/XFbrAb7Aa7wW6wG+wGu8FusBvsJrvJbrKb7Ca7yW6ym+wmu8lusVvsFrvFbrFb7Ba7xW6xW+wedg+7h93D7mH3sHvYPewedg+7zW6z2+w2u81us9vsNrvNbrM77A67w+6wO+wOu8PusDvsDruX3cvuZfeye9m97F52L7uX3cvuY/ex+9h97D52H7uP3cfuY/exu+wuu8vusrvsLrvL7rK77OJV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeHVb98e5/f+3q2v37u5h/tyP+793D9e/XsHd3IXN7vNbrPb7Da7ze6wO+wOu8PusDvsDrvD7rA77F52L7uX3cvuZfeye9m97F52L7uP3cfuY/ex+9h97D52H7uP3cfusrvsLrvL7rK77C67y+6yu5/d37793zu4k7u4D3dzD/flftzsBrvBbrAb7Aa7wW6wG+wGu8FuspvsJrvJbrKb7Ca7yW6ym+wWu8VusVvsFrvFbrFb7Ba7xe5h97B72D3s4tXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18KrxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxavBq8Grw6rdvr/i9f3br9/7ZPb/38OuXX3/8+n5+/der31//9erPrye/Xvw6u8FusBvsBrvBbrKb7Ca7yW6ym+wmu8luspvsFrvFbrFb7Ba7xW6xW+wWu8XuYfewe9j99ap/75/d93v/7O7vPdzfu+f3a+PHq3/v793z+3Xy49W/d3An9/fuyd/7cH/vnt9/tx+vzu+/849X5/ff88erM7/3z+79uX+8Or///j9end9/5x+v/v314tcPv978+vDrl19//Pp+fv2ye9m97F52L7uX3cvuZfeye9l97D52H7uP3cfuY/ex+9h97D52l91ld9lddpfdZXfZXXaX3f3s/vbtv7/+27f/++vJrxe/fvj15teHX7/8+uPX2Q12g91gN9gNdoPdYDfYDXaD3WQ32U12k91kN9lNdpPdZDfZLXaL3WK32C12i91it9gtdovdw+5h97B72D3sHnYPu4fdw+5ht9ltdpvdZrfZbXab3Wa32W128eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxavfvr2/fu/v3Y7f+3u38/f+3u36vffv/du39/m9gzu5v3e7f+/D3dw/u/N7X+6f3ft77+f+8erfO7h/dt/v/b07X7/34W7u4f7enfi9H/d+7h+v/r2/dyd/7+TXi/twN/fwz7Kb7Ca7xe6PV//e7Ba7xe6PV3+2frz699fZLXaL3R+v/vyzh93D7mH3sHvYPewedg+7h91mt9ltdpvdZrfZbXab3Wa32R12h91hd9gddofdYXfYHXaH3cvuZfeye9m97F52L7uX3cvuZfex+9h97D52H7uP3cfuY/ex+9hddpfdZXfZXXaX3WV32V1297P727f//rO/ffu/v57cxX24m392+PXL/bjZDXaD3WA32A12g91gF68Wrxavfvv2P/9ssotXi1eLV799+7//LLt4tXi1ePXbt//5Z/Fq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8Wo/XvXXx6v++njVXx+v+uvjVX99vOqvj1f99fGqvz5e9dfHq/76YjfYDXaD3WA32A12g91gN9gNdpPdZDfZTXaT3WQ32U12k91kt9gtdovdYrfYLXaL3WK32C12D7uH3cPuYfewe9g97B52D7uH3Wa32W12m91mt9ltdpvdZrfZHXaH3WF32B12h91hd9gddofdy+5l97J72b3sXnYvu5fdy+5l97H72H3sPnYfu4/dx+5j97H72F12l91ld9lddpfdZXfZXXbxKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8SrxKvEq8arwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8Krw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8Gry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18OrhFX1707c3fXs/vHp4Rd/e9O1N394Prx5e0bc3fXvTt/fDK/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2pm9v+vamb2/69qZvb/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2oW8f+vahbx/69qFvH/r2+dO3n9/7cv/s9u+9f+8/ffufO7iTu7h/du/v3dw/u+/3vtyPez/3r1d/7uBO7uI+3M3NbrAb7Aa7yW6ym+wmu8luspvsJrvJbrJb7Ba7xW6xW+wWu8VusVvsFruH3cPuYfewe9g97B52D7uH3cNus9vsNrvNbrPb7Da7zW6z2+wOu8PusDvsDrvD7rA77A67w+5l97J72b3sXnYvu5fdy+5l97L72H3sPnYfu4/dx+5j97H72H3sLrvL7rK77C67y+6yu+wuu/vZ/dO3/7mDO7mL+3A393Bf7sfNLl4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV796dv3927u79379Xtf7se9n/vHqxu/d3And3Ef7uYe7sv9uPdzP3Yfu4/dx+5j97H72H3sPnYfu8vusrvsLrvL7rK77C67y+5+dn/79n/v4E7u4j7czT3cl/txsxvsBrvBbrAb7Aa7wW6wG+wGu8luspvsJrvJbrKb7Ca7yW6yW+wWu8VusVvsFrvFbrFb7Ba7h93D7mH3sHvYPewedg+7h93DbrPb7Da7zW6z2+w2u81us9vsDrvD7rA77A67w+6wO+wOu8MuXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8WrxavFq8Wr/Xh1vz5e3a+PV/fr49X9+nh1vz5e3a+PV/fr49X9+nh1vz5e3a8vdoPdYDfYDXaD3WA32A12g91gN9lNdpPdZDfZTXaT3WQ32U12i91it9gtdovdYrfYLXaL3WL3sHvYPewedg+7h93D7mH3sHvYbXab3Wa32W12m91mt9ltdpvdYXfYHXaH3WF32B12h91hd9i97F52L7uX3cvuZfeye9m97F52H7uP3cfuY/ex+9h97D52H7uP3WV32V12l91ld9lddpfdZRevAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8CrwKvAq8SrxKvEq8SrxKvEq8Sr3779pu/9+P+2a2f+9erP3dwJ3dxH+7mHu7L/bjZTXaT3WQ32U12k91kN9lNdpPdYrfYLXaL3WK32C12i91it9g97B52D7uH3cPuYfewe9g97B52m91mt9ltdpvdZrfZbXab3WZ32B12h91hd9gddofdYXfYHXYvu5fdy+5l97J72b3sXnYvu5fdx+5j97H72H3sPnYfu4/dx+5jd9lddpfdZXfZXXaX3WV32d3P7m/f/u8d3Mld3Ie7uYf7cj9udvGq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8KrwqvCq8Krw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8Gry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl5dvLp4dfHq4tXFq4tXF68uXl28unh18eri1cWri1cXry5eXby6eHXx6uLVxauLVxevLl796dvv7/2493P/evXnDu7kLu7D3dzDze6wO+xedi+7l93L7mX3snvZvexedi+7j93H7mP3sfvYfew+dh+7j93H7rK77C67y+6yu+wuu8vusruf3T99+587uJO7uA93cw/35X7c7Aa7wW6wG+wGu8FusBvsBrvBbrKb7Ca7yW6ym+wmu8luspvsFrvFbrFb7Ba7xW6xW+wWu8XuYfewe9g97B52D7uH3cPuYfew2+w2u81us9vsNrvNLl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6ePXw6uHVw6uHVw+vHl49vHp49fDq4dXDq4dXD68eXj28enj18Orh1cOrh1cPrx5ePbx6eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLV4tXi1eLUfr97Xx6v39fHqfX28el8fr97Xx6v39fHqfX28el8fr97Xx6v39cVusBvsBrvBbrAb7Aa7wW6wG+wmu8luspvsJrvJbrKb7Ca7yW6xW+wWu8VusVvsFrvFbrFb7B52D7uH3cPuYfewe9g97B52D7vNbrPb7Da7zW6z2+w2u81uszvsDrvD7rA77A67w+6wO+wOu5fdy+5l97J72b3sXnYvu5fdy+5j97H72H3sPnYfu4/dx+5j97G77C67y+6yu+wuu8vusrvs4lXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXgVeBV4FXg1Z++fX/v790Xv3dxH+7mHu7L/bj3c/949e8d3Owedg+7h93D7mH3sPvj1auf+8er1793cP/szu9d3Ie7uYf7cj/u/dw/Xv17Bze7w+6wO+wOu8PusDvsXnYvu5fdy+5l97J72b3sXnYvu4/dx+5j97H72H3sPnYfu4/dx+6yu+wuu8vusrvsLrvL7rK7n93fvv3fO7iT+3t34/c+3M093Jf7ce/n/vHq3zu4k5vdYDfYDXaD3WA32E12k91kN9lNdpPdZDfZTXaT3WK32C12i91it9gtdovdYrfYPewedg+7317984Xwe5/v+8+v/7P7z2/I7z3cl/tx7+f+9urvHdzJXdyHm91mt9ltdpvdYXfYHXaH3WF32B12h91hd9i97F52L7uX3cvuZfeye9m97F52H7uP3cfuY/ex+9h97D52H7uP3WV32V12l91ld9lddpfdZXc/uz99+987uJO7uA93cw/35X7c7Aa7wW6wG+wGu8FusBvsBrvBbrKb7Ca7yW6ym+wmu8luspvsFrvFbrFbP7vn9/7Z3d+7uYf7cj/u/dznizu4k7u42T3sHnYPu4fdw26z2+w2u81us9vsNrvNbrPb7A67w+6wO+wOu8PusDvsDrvD7mX3snvZvez+eJXxe3/vVv3ew325v3drfu/v3Xo/949X/97BndzFfbibe7gv9+Nmd9lddpfdZXfZXXaX3WV32f3x6vz8/6c/ffvfO7iTu7gPd3MP9+V+3OwGu8FusBvsBrvBbrAb7Aa7P171z/cjP3373zu4k7u4D3dzD/f3bu/v/bj3c/94Nb8f/+PVv3dyF/fhbu7hvtyPez/3Yfewe9g97B52D7uH3cPuYfew2+w2u81us9vsNrvNbrPb7Da7w+6wO+wOu8PusDvsDrvD7rB72b3sXnYvu5fdy+5l97J72b3sPnYfu4/dx+5j97H72H3sPnYfu8vusrvsLrvL7rK77C67y+5+dn/69r93cCd3cR/u5h7uy/242Q12g91gN9gNdoPdYDfYDXaD3WQ32U12k91kN9lNdpPdZDfZxavGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvGq8arxqvBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8GrwavBq8Gr+fXq/d6X+2d3fu/93L9e/bnj8/G/Xv25i/twNze7y+6vV/f33r/3/fXqzx3cn937Vdzn77/n/fXqzz3cl49/3Pu5f736c8fnn/316s9d3IePb+7hZjfYjc/n+eYXN7vJ8ybPm+wmu79e/X6ufr36cz9uPs/F81ZwJx9T3Ie7uXne4nnr83V1i+c9PO9h9/C8h+c9PO9h9/C8h+c9PO/h97d53ubrqnne5nmb520+z83z/nr1+yzN8zbPO+wOzzs87/C8w9fz8PU8fD0Pn+fh62p43st/R5fnvTzv5Xkvn+fL814+z5fP8+XzfPm6ejzv43kf/x09/jt6PO9jF68uXt3H8z6ed9ld/jtadpddvLp4dfHq4tXFq4tXD68eXj28enj18Orh1cOrh1cPrx5ePbx6Edyf398XxX24m3v4Z9mNz9fzw6uHVy/ZxauHVy953uR5k+dNdpPnTZ4Xrx5evWK32K3D3dzs1uXmeYvdwy5evfP5unqnuHnew+7h83x43sPzHr6umq8rvHp49ZrnbZ63+Tw3z4tXr9ltnhev3rA77A5fV8PX1fC8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VeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeJV4lXiVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeFV4VXhVeHVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl4dvDp4dfDq4NXBq4NXB68OXh28Onh18Org1cGrg1cHrw5eHbw6eHXw6uDVwauDVwevDl41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41XjVeNV41Xg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXg1eDV4NXv35+e1/PuZ79+fnnsVv375/PuZ7d38/5serf+/gTu7iPtzNPdyX+3Gz+9h97D52H7uP3cfuY/ex+9j99uqfP5j5ub+9+nsHd37fvx//7dXf+3D/s/vPH8b83uwuu8vufp73t2//9w7u5C7uw93cw325Hze7wW6wG+wGu8FusPvt1Z/P1U/f/vd+3Pv3c/XTt/+9gzv/fg5/+vZ//hDr9z7czT3cl/tx7+f+9urvHdzJzW6xW+wWu8VusVvsHnYPu4fd87N7f+/D3dzD/bP7+3k7j/t7t34/h99e/fMHcr93cCf392717324v3fr93/mt1d/78v9vfvz8/Tip2//9/726p8/SPu9gzu5v3f799/z26u/9/du//67fXtV/fvv8+3V3/t7t38/D99e/Xt/e/XPH5793sGd3N+7k7/34f7evb//Dt9e/b0v9/fu/f13+/bq3/vbq3/+AOz3Du7v3ff79f/t1d/7cH/v/vr807f/vb933+/n6turf/6A6vfez/3j1b/39+6v5z99+9/7e/fX9p++/e/d3N+7f/5b/vbq7/3P7j9/sPR779/7p2//e8f3vb93cv+z+88fMv3e5/uu37u55/vu3/tyf+/+mvDTt/97f3v19/7eza/fO7m/d/P33+Hbq793c3/v/v438tO3/72/d3//u/jp2/+9v7365w9vfu/gTu7v3XN+78P9vXt+n+vbq3/+IOf3/t49v8/y7dXfez93fXEHd3IX9+Fu7uFmt9gtdg+7h93D7mH3sHvYPeyen939H//xP/z//pf//l/+l//1v/7n/+9/+H/8X//8X//f/+f/9p/+j//y3/63P//X/+P//7//+//yv/73//Jf/+t/+f/8z//7f/9v/+k//7/+z//+n//n//rf/tP3/9t/+Pr+P76/Gv6fsf8xz//0zwfH31/K8x9zv38p//5Snf9Y//zS//gf/9P/+L8B","file_map":{"14":{"source":"// docs:start:ecdsa_secp256k1\n/// Verifies a ECDSA signature over the secp256k1 curve.\n/// - inputs:\n/// - x coordinate of public key as 32 bytes\n/// - y coordinate of public key as 32 bytes\n/// - the signature, as a 64 bytes array\n/// The signature internally will be represented as `(r, s)`,\n/// where `r` and `s` are fixed-sized big endian scalar values.\n/// As the `secp256k1` has a 256-bit modulus, we have a 64 byte signature\n/// while `r` and `s` will both be 32 bytes.\n/// We expect `s` to be normalized. This means given the curve's order,\n/// `s` should be less than or equal to `order / 2`.\n/// This is done to prevent malleability.\n/// For more context regarding malleability you can reference BIP 0062.\n/// - the hash of the message, as a vector of bytes\n/// - output: false for failure and true for success\npub fn verify_signature(\n public_key_x: [u8; 32],\n public_key_y: [u8; 32],\n signature: [u8; 64],\n message_hash: [u8; 32],\n) -> bool\n// docs:end:ecdsa_secp256k1\n{\n _verify_signature(public_key_x, public_key_y, signature, message_hash, true)\n}\n\n#[foreign(ecdsa_secp256k1)]\npub fn _verify_signature(\n public_key_x: [u8; 32],\n public_key_y: [u8; 32],\n signature: [u8; 64],\n message_hash: [u8; 32],\n predicate: bool,\n) -> bool {}\n","path":"std/ecdsa_secp256k1.nr"},"17":{"source":"use crate::field::field_less_than;\nuse crate::runtime::is_unconstrained;\n\n// The low and high decomposition of the field modulus\nglobal PLO: Field = 53438638232309528389504892708671455233;\nglobal PHI: Field = 64323764613183177041862057485226039389;\n\npub(crate) global TWO_POW_128: Field = 0x100000000000000000000000000000000;\n\n// Decomposes a single field into two 16 byte fields.\nfn compute_decomposition(x: Field) -> (Field, Field) {\n // Here's we're taking advantage of truncating 128 bit limbs from the input field\n // and then subtracting them from the input such the field division is equivalent to integer division.\n let low = (x as u128) as Field;\n let high = (x - low) / TWO_POW_128;\n\n (low, high)\n}\n\npub(crate) unconstrained fn decompose_hint(x: Field) -> (Field, Field) {\n compute_decomposition(x)\n}\n\nunconstrained fn lte_hint(x: Field, y: Field) -> bool {\n if x == y {\n true\n } else {\n field_less_than(x, y)\n }\n}\n\n// Assert that (alo > blo && ahi >= bhi) || (alo <= blo && ahi > bhi)\nfn assert_gt_limbs(a: (Field, Field), b: (Field, Field)) {\n let (alo, ahi) = a;\n let (blo, bhi) = b;\n // Safety: borrow is enforced to be boolean due to its type.\n // if borrow is 0, it asserts that (alo > blo && ahi >= bhi)\n // if borrow is 1, it asserts that (alo <= blo && ahi > bhi)\n unsafe {\n let borrow = lte_hint(alo, blo);\n\n let rlo = alo - blo - 1 + (borrow as Field) * TWO_POW_128;\n let rhi = ahi - bhi - (borrow as Field);\n\n rlo.assert_max_bit_size::<128>();\n rhi.assert_max_bit_size::<128>();\n }\n}\n\n/// Decompose a single field into two 16 byte fields.\npub fn decompose(x: Field) -> (Field, Field) {\n if is_unconstrained() {\n compute_decomposition(x)\n } else {\n // Safety: decomposition is properly checked below\n unsafe {\n // Take hints of the decomposition\n let (xlo, xhi) = decompose_hint(x);\n\n // Range check the limbs\n xlo.assert_max_bit_size::<128>();\n xhi.assert_max_bit_size::<128>();\n\n // Check that the decomposition is correct\n assert_eq(x, xlo + TWO_POW_128 * xhi);\n\n // Assert that the decomposition of P is greater than the decomposition of x\n assert_gt_limbs((PLO, PHI), (xlo, xhi));\n (xlo, xhi)\n }\n }\n}\n\npub fn assert_gt(a: Field, b: Field) {\n if is_unconstrained() {\n assert(\n // Safety: already unconstrained\n unsafe { field_less_than(b, a) },\n );\n } else {\n // Decompose a and b\n let a_limbs = decompose(a);\n let b_limbs = decompose(b);\n\n // Assert that a_limbs is greater than b_limbs\n assert_gt_limbs(a_limbs, b_limbs)\n }\n}\n\npub fn assert_lt(a: Field, b: Field) {\n assert_gt(b, a);\n}\n\npub fn gt(a: Field, b: Field) -> bool {\n if is_unconstrained() {\n // Safety: unsafe in unconstrained\n unsafe {\n field_less_than(b, a)\n }\n } else if a == b {\n false\n } else {\n // Safety: Take a hint of the comparison and verify it\n unsafe {\n if field_less_than(a, b) {\n assert_gt(b, a);\n false\n } else {\n assert_gt(a, b);\n true\n }\n }\n }\n}\n\npub fn lt(a: Field, b: Field) -> bool {\n gt(b, a)\n}\n\nmod tests {\n // TODO: Allow imports from \"super\"\n use crate::field::bn254::{assert_gt, decompose, gt, lt, lte_hint, PHI, PLO, TWO_POW_128};\n\n #[test]\n fn check_decompose() {\n assert_eq(decompose(TWO_POW_128), (0, 1));\n assert_eq(decompose(TWO_POW_128 + 0x1234567890), (0x1234567890, 1));\n assert_eq(decompose(0x1234567890), (0x1234567890, 0));\n }\n\n #[test]\n unconstrained fn check_lte_hint() {\n assert(lte_hint(0, 1));\n assert(lte_hint(0, 0x100));\n assert(lte_hint(0x100, TWO_POW_128 - 1));\n assert(!lte_hint(0 - 1, 0));\n\n assert(lte_hint(0, 0));\n assert(lte_hint(0x100, 0x100));\n assert(lte_hint(0 - 1, 0 - 1));\n }\n\n #[test]\n fn check_gt() {\n assert(gt(1, 0));\n assert(gt(0x100, 0));\n assert(gt((0 - 1), (0 - 2)));\n assert(gt(TWO_POW_128, 0));\n assert(!gt(0, 0));\n assert(!gt(0, 0x100));\n assert(gt(0 - 1, 0 - 2));\n assert(!gt(0 - 2, 0 - 1));\n assert_gt(0 - 1, 0);\n }\n\n #[test]\n fn check_plo_phi() {\n assert_eq(PLO + PHI * TWO_POW_128, 0);\n let p_bytes = crate::field::modulus_le_bytes();\n let mut p_low: Field = 0;\n let mut p_high: Field = 0;\n\n let mut offset = 1;\n for i in 0..16 {\n p_low += (p_bytes[i] as Field) * offset;\n p_high += (p_bytes[i + 16] as Field) * offset;\n offset *= 256;\n }\n assert_eq(p_low, PLO);\n assert_eq(p_high, PHI);\n }\n\n #[test]\n fn check_decompose_edge_cases() {\n assert_eq(decompose(0), (0, 0));\n assert_eq(decompose(TWO_POW_128 - 1), (TWO_POW_128 - 1, 0));\n assert_eq(decompose(TWO_POW_128 + 1), (1, 1));\n assert_eq(decompose(TWO_POW_128 * 2), (0, 2));\n assert_eq(decompose(TWO_POW_128 * 2 + 0x1234567890), (0x1234567890, 2));\n }\n\n #[test]\n fn check_decompose_large_values() {\n let large_field = 0xffffffffffffffff;\n let (lo, hi) = decompose(large_field);\n assert_eq(large_field, lo + TWO_POW_128 * hi);\n\n let large_value = large_field - TWO_POW_128;\n let (lo2, hi2) = decompose(large_value);\n assert_eq(large_value, lo2 + TWO_POW_128 * hi2);\n }\n\n #[test]\n fn check_lt_comprehensive() {\n assert(lt(0, 1));\n assert(!lt(1, 0));\n assert(!lt(0, 0));\n assert(!lt(42, 42));\n\n assert(lt(TWO_POW_128 - 1, TWO_POW_128));\n assert(!lt(TWO_POW_128, TWO_POW_128 - 1));\n }\n}\n","path":"std/field/bn254.nr"},"18":{"source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [u1; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n","path":"std/field/mod.nr"},"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"55":{"source":"use poseidon::poseidon2;\nuse crate::MerklePath;\n\nimpl MerklePath {\n pub fn root_from_leaf(self, leaf: Field) -> Field {\n let bits: [u1; 254] = leaf.to_le_bits();\n let mut hash = leaf;\n for i in 0..160 {\n let sibling = self.path[i];\n if bits[i] == 0 {\n hash = poseidon2::Poseidon2::hash([hash, sibling], 2);\n } else {\n hash = poseidon2::Poseidon2::hash([sibling, hash], 2);\n }\n }\n\n hash\n }\n\n pub fn validate(self, leaf: Field, root: Field) -> bool {\n self.root_from_leaf(leaf) == root\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/merkle_path.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"77":{"source":"use common::Address;\n\n/// Represents an unsigned Ethereum EIP-1559 (type-2) transaction\npub struct Type2Transaction {\n pub chain_id: u64,\n pub nonce: u64,\n pub max_priority_fee_per_gas: u128,\n pub max_fee_per_gas: u128,\n pub gas_limit: u64,\n pub to: Address,\n pub value: u128,\n pub data: [u8; N],\n}\n\nimpl Type2Transaction {\n pub fn hash(self) -> [u8; 32] {\n let (encoded, len) = self.rlp_encode();\n keccak256::keccak256(encoded, len)\n }\n\n /// RLP encode the transaction for hashing\n fn rlp_encode(self) -> ([u8; 256], u32) {\n let mut encoded = [0u8; 256];\n\n encoded[0] = 0x02; // transaction type 2\n encoded[1] = 0xf8; // 55 < length of payload <= 255\n // payload length is written to encoded[2] at the end\n\n let mut offset = 3;\n\n offset = rlp_append_u64(&mut encoded, offset, self.chain_id);\n offset = rlp_append_u64(&mut encoded, offset, self.nonce);\n offset = rlp_append_u128(&mut encoded, offset, self.max_priority_fee_per_gas);\n offset = rlp_append_u128(&mut encoded, offset, self.max_fee_per_gas);\n offset = rlp_append_u64(&mut encoded, offset, self.gas_limit);\n\n encoded[offset] = 0x94;\n offset += 1;\n for i in 0..20 {\n encoded[offset + i] = self.to[i];\n }\n offset += 20;\n\n offset = rlp_append_u128(&mut encoded, offset, self.value);\n\n encoded[offset] = 0xb8;\n assert((55 < DATA_LEN) & (DATA_LEN <= 255), \"Calldata length outside supported range\");\n encoded[offset + 1] = DATA_LEN as u8;\n offset += 2;\n for i in 0..DATA_LEN {\n encoded[offset + i] = self.data[i];\n }\n offset += DATA_LEN;\n\n encoded[offset] = 0xc0;\n offset += 1;\n\n let payload_len = offset - 3;\n assert((55 < payload_len) & (payload_len <= 255), \"Payload length outside supported range\");\n encoded[2] = payload_len as u8;\n\n (encoded, offset)\n }\n}\n\nfn rlp_append_u64(out: &mut [u8; N], offset: u32, value: u64) -> u32 {\n if (value != 0) & (value < 0x80) {\n out[offset] = value as u8;\n offset + 1\n } else {\n let mut bytes = (value as Field).to_be_bytes::<8>();\n rlp_append_integer(out, offset, bytes)\n }\n}\n\nfn rlp_append_u128(out: &mut [u8; N], offset: u32, value: u128) -> u32 {\n if (value != 0) & (value < 0x80) {\n out[offset] = value as u8;\n offset + 1\n } else {\n let mut bytes = (value as Field).to_be_bytes::<16>();\n rlp_append_integer(out, offset, bytes)\n }\n}\n\nfn rlp_append_integer(out: &mut [u8; N], offset: u32, value: [u8; M]) -> u32 {\n let mut next_offset = offset + 1;\n let mut found = false;\n for i in 0..M {\n if value[i] != 0 {\n found = true;\n }\n if found {\n out[next_offset] = value[i];\n next_offset += 1;\n }\n }\n\n let len = next_offset - offset - 1;\n out[offset] = 0x80 + (len as u8);\n\n next_offset\n}\n\n#[test]\nfn rlp_encoding() {\n let mut data = [0u8; 68];\n data[0] = 0x12;\n data[1] = 0x34;\n data[2] = 0x56;\n data[3] = 0x78;\n\n for i in 0..32 {\n data[4 + i] = 0x11;\n data[36 + i] = 0x22;\n }\n\n let tx = Type2Transaction {\n chain_id: 1,\n nonce: 0,\n max_priority_fee_per_gas: 2000000000,\n max_fee_per_gas: 100000000000,\n gas_limit: 21000,\n to: [0x11; 20],\n value: 0,\n data,\n };\n\n let (encoded, len) = tx.rlp_encode();\n\n let expected: [u8; 112] = [0x02, 0xf8, 0x6d, 0x01, 0x80, 0x84, 0x77, 0x35, 0x94, 0x00, 0x85, 0x17, 0x48, 0x76, 0xe8, 0x00, 0x82, 0x52, 0x08, 0x94, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80, 0xb8, 0x44, 0x12, 0x34, 0x56, 0x78, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xc0];\n\n for i in 0..expected.len() {\n let correct = expected[i];\n let test = encoded[i];\n assert(test == correct, f\"byte {i} is {test} but should be {correct}\")\n }\n\n assert(len == expected.len(), f\"Unexpected length {len}\");\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/evm/erc20_transfer/src/eip1559transaction.nr"},"78":{"source":"mod eip1559transaction;\nmod signature;\n\nuse eip1559transaction::Type2Transaction;\nuse common::{Address, MerklePath};\nuse poseidon::poseidon2::Poseidon2;\nuse signature::Signature;\n\n/// We use Poseidon hashes that operate on the field we use for proving\ntype Hash = Field;\n\npub struct Note {\n pub kind: Field,\n pub address: Address,\n pub token: Address,\n pub value: Field,\n pub psi: Field,\n}\n\nimpl Note {\n pub fn hash(self) -> Field {\n Poseidon2::hash(\n [\n self.kind,\n Field::from_be_bytes(self.address),\n Field::from_be_bytes(self.token),\n self.value,\n self.psi,\n ],\n 5,\n )\n }\n}\n\n/// Shows that somewhere in the Merkle tree represented by `input_note_merkle_root`,\n/// there are notes belonging to an account that has signed an ERC-20 transfer.\n/// Specifically, the notes are sufficient to pay for that transfer, output_notes[1]\n/// is a note for the recipient and output_notes[0] holds any leftover change.\n///\n/// The consumer of the proof should\n/// - add `new_commitments` to the Merkle tree so it is\n/// possible to use the output notes in the future.\n/// - ensure that `new_nullifiers` haven't been seen before and\n/// aren't identical! They are the only mechanism preventing double spend.\n/// - check that chain_id and bridge_address to prevent cross-chain replay attacks.\nfn main(\n // Needed to prevent cross-chain or cross-contract attacks\n chain_id: pub u64,\n bridge_address: pub Field,\n // Ethereum transaction\n original_transfer: ERC20Transfer,\n signature: Signature,\n // Input notes\n input_notes: [Note; 2],\n input_note_merkle_proofs: [MerklePath; 2],\n input_note_merkle_root: pub Hash,\n new_nullifiers: pub [Hash; 3],\n // Output notes\n output_notes: [Note; 2],\n new_commitments: pub [Hash; 2],\n) {\n let transaction_hash = original_transfer.hash();\n assert(signature.matches_transaction_hash(transaction_hash), \"Invalid signature\");\n let sender = signature.sender_address();\n\n // The same transaction must not be used twice to prevent replay attacks or accidents\n // This prevents cross-chain use of the same signed transaction\n assert(chain_id == original_transfer.chain_id);\n // We cannot prevent cross-contract use of the same transaction, as it cannot\n // indicate what bridge to use but at least we can make the proof valid only for one.\n // The signature's r is a random number, so it is perfect for building the nullifier.\n // s would be a poor choice because if (r, s) is a valid signature, (r, -s) is, too.\n assert(\n new_nullifiers[2]\n == Poseidon2::hash(\n [Field::from_be_bytes(signature.r), Field::from(chain_id), bridge_address],\n 3,\n ),\n );\n\n for i in 0..input_notes.len() {\n let note = input_notes[i];\n assert(note.address == sender);\n assert(note.token == original_transfer.token_address);\n\n let commitment = note.hash();\n assert(input_note_merkle_proofs[i].validate(commitment, input_note_merkle_root));\n\n // TODO(ENG-6670) is hashing with psi a good way to build the nullifier?\n let nullifier = Poseidon2::hash([commitment, note.psi], 2);\n assert(new_nullifiers[i] == nullifier)\n // The PrivacyBridge is responsible for checking that the nullifiers do not already exist\n }\n\n for i in 0..output_notes.len() {\n let note = output_notes[i];\n assert(note.token == original_transfer.token_address);\n\n let commitment = note.hash();\n assert(new_commitments[i] == commitment);\n }\n\n // This addition can overflow but that means the sender loses money\n let value_in = input_notes[0].value + input_notes[1].value;\n\n // The first output note is for the sender's leftover tokens\n assert(output_notes[0].address == sender);\n assert(!value_in.lt(original_transfer.amount), \"Not enough funds for transfer\");\n assert(output_notes[0].value == value_in - original_transfer.amount);\n\n // The second one is for the receiver\n assert(output_notes[1].address == original_transfer.receiver);\n assert(output_notes[1].value == original_transfer.amount);\n}\n\n/// Parsed EIP-1559 transaction that calls ERC-20.transfer\npub struct ERC20Transfer {\n chain_id: u64,\n nonce: u64,\n max_priority_fee_per_gas: u128,\n max_fee_per_gas: u128,\n gas_limit: u64,\n\n token_address: Address,\n receiver: Address,\n amount: Field,\n}\n\nimpl ERC20Transfer {\n fn hash(self) -> [u8; 32] {\n let Self {\n chain_id,\n nonce,\n max_priority_fee_per_gas,\n max_fee_per_gas,\n gas_limit,\n token_address,\n receiver,\n amount,\n } = self;\n\n // selector for transfer(address,uint256)\n let transfer_selector = [0xa9, 0x05, 0x9c, 0xbb];\n let receiver = [0; 12].concat(receiver);\n let amount = amount.to_be_bytes::<32>();\n\n Type2Transaction {\n chain_id,\n nonce,\n max_priority_fee_per_gas,\n max_fee_per_gas,\n gas_limit,\n value: 0,\n to: token_address,\n data: transfer_selector.concat(receiver).concat(amount),\n }\n .hash()\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/evm/erc20_transfer/src/main.nr"},"79":{"source":"use common::Address;\n\npub struct Signature {\n pub r: [u8; 32],\n pub s: [u8; 32],\n\n pub sender_pubkey_x: [u8; 32],\n pub sender_pubkey_y: [u8; 32],\n}\n\nimpl Signature {\n pub fn matches_transaction_hash(self, hash: [u8; 32]) -> bool {\n std::ecdsa_secp256k1::verify_signature(\n self.sender_pubkey_x,\n self.sender_pubkey_y,\n self.r.concat(self.s),\n hash,\n )\n }\n\n pub fn sender_address(self) -> Address {\n let hash = keccak256::keccak256(self.sender_pubkey_x.concat(self.sender_pubkey_y), 64);\n common::slice(hash, 12)\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/evm/erc20_transfer/src/signature.nr"},"83":{"source":"mod tests;\nmod oracle_tests;\nmod benchmarks;\n\nuse std::hash::keccakf1600;\nuse std::runtime::is_unconstrained;\n\nglobal BLOCK_SIZE_IN_BYTES: u32 = 136; //(1600 - BITS * 2) / WORD_SIZE;\nglobal WORD_SIZE: u32 = 8; // Limbs are made up of u64s so 8 bytes each.\nglobal LIMBS_PER_BLOCK: u32 = BLOCK_SIZE_IN_BYTES / WORD_SIZE;\nglobal NUM_KECCAK_LANES: u32 = 25;\n\n#[no_predicates]\npub fn keccak256(input: [u8; N], message_size: u32) -> [u8; 32] {\n assert(N >= message_size);\n\n // Copy input to block bytes. For that we'll need at least input bytes (N)\n // but we want it to be padded to a multiple of BLOCK_SIZE_IN_BYTES.\n let mut block_bytes = [0; ((N / BLOCK_SIZE_IN_BYTES) + 1) * BLOCK_SIZE_IN_BYTES];\n if is_unconstrained() {\n for i in 0..message_size {\n block_bytes[i] = input[i];\n }\n } else {\n for i in 0..N {\n if i < message_size {\n block_bytes[i] = input[i];\n }\n }\n }\n\n //1. format_input_lanes and apply padding\n let max_blocks = (N + BLOCK_SIZE_IN_BYTES) / BLOCK_SIZE_IN_BYTES;\n let real_max_blocks = (message_size + BLOCK_SIZE_IN_BYTES) / BLOCK_SIZE_IN_BYTES;\n\n // Apply Keccak padding (0x01 after message, 0x80 at block end)\n apply_keccak_padding(&mut block_bytes, message_size, real_max_blocks);\n\n // populate a vector of 64-bit limbs from our byte array\n let mut sliced_buffer =\n [0; (((N / BLOCK_SIZE_IN_BYTES) + 1) * BLOCK_SIZE_IN_BYTES) / WORD_SIZE];\n for i in 0..sliced_buffer.len() {\n let limb_start = WORD_SIZE * i;\n\n let mut sliced = 0;\n let mut v = 1;\n for k in 0..WORD_SIZE {\n sliced += v * (block_bytes[limb_start + k] as Field);\n v *= 256;\n }\n\n sliced_buffer[i] = sliced as u64;\n }\n\n //2. sponge_absorb\n let mut state: [u64; NUM_KECCAK_LANES] = [0; NUM_KECCAK_LANES];\n // `real_max_blocks` is guaranteed to at least be `1`\n // We peel out the first block as to avoid a conditional inside of the loop.\n // Otherwise, a dynamic predicate can cause a blowup in a constrained runtime.\n for j in 0..LIMBS_PER_BLOCK {\n state[j] = sliced_buffer[j];\n }\n state = keccakf1600(state);\n\n let state = if is_unconstrained() {\n // When in an unconstrained runtime we can take advantage of runtime loop bounds,\n // thus allowing us to simplify the loop body.\n for i in 1..real_max_blocks {\n for j in 0..LIMBS_PER_BLOCK {\n state[j] = state[j] ^ sliced_buffer[i * LIMBS_PER_BLOCK + j];\n }\n state = keccakf1600(state);\n }\n\n state\n } else {\n // We store the intermediate states in an array to avoid having a dynamic predicate\n // inside the loop, which can cause a blowup in a constrained runtime.\n let mut intermediate_states = [state; (N + BLOCK_SIZE_IN_BYTES) / BLOCK_SIZE_IN_BYTES + 1];\n for i in 1..max_blocks {\n let mut previous_state = intermediate_states[i - 1];\n for j in 0..LIMBS_PER_BLOCK {\n previous_state[j] = previous_state[j] ^ sliced_buffer[i * LIMBS_PER_BLOCK + j];\n }\n intermediate_states[i] = keccakf1600(previous_state);\n }\n\n // We can then take the state as of `real_max_blocks`, ignoring later permutations.\n intermediate_states[real_max_blocks - 1]\n };\n\n //3. sponge_squeeze\n let mut result = [0; 32];\n for i in 0..4 {\n let lane = state[i] as Field;\n let lane_le: [u8; 8] = lane.to_le_bytes();\n for j in 0..8 {\n result[8 * i + j] = lane_le[j];\n }\n }\n result\n}\n\n// Apply Keccak padding to the block_bytes array\n// Append 0x01 after message, then 0x80 at end of block\n// If both padding bytes collide at the same byte, combine them as 0x81\npub(crate) fn apply_keccak_padding(\n block_bytes: &mut [u8; BLOCK_BYTES],\n message_size: u32,\n real_max_blocks: u32,\n) {\n let real_blocks_bytes = real_max_blocks * BLOCK_SIZE_IN_BYTES;\n\n block_bytes[message_size] = 0x01;\n\n if message_size == real_blocks_bytes - 1 {\n // Combine both padding bits: 0x01 | 0x80 = 0x81\n block_bytes[message_size] = 0x81;\n } else {\n block_bytes[real_blocks_bytes - 1] = 0x80;\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/keccak256/v0.1.2/src/keccak256.nr"},"92":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n self.state[0] += self.cache[0];\n self.state[1] += self.cache[1];\n self.state[2] += self.cache[2];\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(input: [Field; N], in_len: u32) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut state = [0; 4];\n state[RATE] = iv;\n\n if std::runtime::is_unconstrained() {\n for i in 0..(in_len / RATE) {\n state[0] += input[i * RATE];\n state[1] += input[i * RATE + 1];\n state[2] += input[i * RATE + 2];\n state = crate::poseidon2_permutation(state, 4);\n }\n\n // handle remaining elements after last full RATE-sized chunk\n let num_extra_fields = in_len % RATE;\n if num_extra_fields != 0 {\n let remainder_start = in_len - num_extra_fields;\n state[0] += input[remainder_start];\n if num_extra_fields > 1 {\n state[1] += input[remainder_start + 1]\n }\n }\n } else {\n let mut states: [[Field; 4]; N / RATE + 1] = [[0; 4]; N / RATE + 1];\n states[0] = state;\n\n // process all full RATE-sized chunks, storing state after each permutation\n for chunk_idx in 0..(N / RATE) {\n for i in 0..RATE {\n state[i] += input[chunk_idx * RATE + i];\n }\n state = crate::poseidon2_permutation(state, 4);\n states[chunk_idx + 1] = state;\n }\n\n // get state at the last full block before in_len\n let first_partially_filled_chunk = in_len / RATE;\n state = states[first_partially_filled_chunk];\n\n // handle remaining elements after last full RATE-sized chunk\n let remainder_start = (in_len / RATE) * RATE;\n for j in 0..RATE {\n let idx = remainder_start + j;\n if idx < in_len {\n state[j] += input[idx];\n }\n }\n }\n\n // always run final permutation unless we just completed a full chunk\n // still need to permute once if in_len is 0\n if (in_len == 0) | (in_len % RATE != 0) {\n state = crate::poseidon2_permutation(state, 4)\n };\n\n state[0]\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.2.3/src/poseidon2.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/migrate/key b/fixtures/circuits/migrate/key new file mode 100644 index 0000000..f6db2d1 Binary files /dev/null and b/fixtures/circuits/migrate/key differ diff --git a/fixtures/circuits/migrate/key_fields.json b/fixtures/circuits/migrate/key_fields.json new file mode 100644 index 0000000..01c4a6f --- /dev/null +++ b/fixtures/circuits/migrate/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x000000000000000000000000000000000000000000000000000000000000000b", + "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x00000000000000000000000000000015d4c62e27482c72e82897202553da800c", + "0x000000000000000000000000000000000008d557eed458e9b19b1ee5fb8abe2c", + "0x000000000000000000000000000000c359d27ec08123373aa92b243467e0112f", + "0x00000000000000000000000000000000002f31c7d80b9790b0cac043b9e59a4d", + "0x0000000000000000000000000000002855c27b597bdecfd7a2acb3f2ad740e5c", + "0x00000000000000000000000000000000000559cf7e3d0670abcc95b7d237940a", + "0x000000000000000000000000000000b6291b788699d8634bd722318d9f2d3e58", + "0x00000000000000000000000000000000000e6f955e86bc74cf51d55a2a193aec", + "0x000000000000000000000000000000b50459681545793dcb6d0bd64d0e77f76a", + "0x00000000000000000000000000000000002f06515ef9ad1d7b440c8fba0a3e46", + "0x00000000000000000000000000000031a6f5cc95f2236490d9fbac5d8e26cebd", + "0x00000000000000000000000000000000001cfee20efd2c6be2b73f708774e892", + "0x0000000000000000000000000000005946644dfc274f1be8bd815cf4e7c8afd8", + "0x00000000000000000000000000000000001da483534993ba925c1dcf9903c826", + "0x0000000000000000000000000000009e2b7237e96b9982409206095c3b08e381", + "0x0000000000000000000000000000000000144afa965fe70a3a3c129e0712bc63", + "0x00000000000000000000000000000037759e1ba1d7d175bf9b3a85f73da3cb52", + "0x00000000000000000000000000000000000d2e5ab7297d3c08e53e8e3715ea9b", + "0x000000000000000000000000000000438347b51c33cc5cdbfbfffbe2e7617700", + "0x000000000000000000000000000000000022c276bd15a31a5bc2907d4af1490b", + "0x00000000000000000000000000000033035698e220b9020d867cc55b981138fa", + "0x000000000000000000000000000000000018fc42cabec67b35ee141a8efcc2d7", + "0x0000000000000000000000000000008e1e080bf415e2fe6b3d23f41b86714bd8", + "0x00000000000000000000000000000000001113abcec29425d3922dce956a76e5", + "0x0000000000000000000000000000009abaf87e068b8e00ba462e190ff4dc0ff9", + "0x00000000000000000000000000000000001ad0852ae1f831506b33a76a496884", + "0x0000000000000000000000000000003ee69c0cb7b1ca634b32395b5349605a93", + "0x00000000000000000000000000000000002b782e70b28e331338317e348ecb3d", + "0x000000000000000000000000000000110e5e535a6cd57d2544443864c806e13c", + "0x00000000000000000000000000000000000d0bb304d74a0dbb86d69fe3c564df", + "0x000000000000000000000000000000be56fbd5f4c74c9767c22be8e28008f405", + "0x000000000000000000000000000000000009df0883e8228f9c49bf3326f7f140", + "0x000000000000000000000000000000f955d7ddad90cf9126dba6b730d8c43b93", + "0x00000000000000000000000000000000002f5476d9cce66c1d6b5b3f4e768aa3", + "0x0000000000000000000000000000009e019a0599432db53c6969dd54bbf5d0af", + "0x00000000000000000000000000000000002135eb76f58a7523869ac8326e203c", + "0x0000000000000000000000000000000a8995661843814da929a2a96912137bba", + "0x00000000000000000000000000000000001ea766d8039d26d2366da1c84ef9eb", + "0x000000000000000000000000000000e2e20986376d6ad88d080f526464aa7f62", + "0x000000000000000000000000000000000027dc6c66adb64bdebac49587389a1d", + "0x000000000000000000000000000000d3a08b55a547d8bb12afdb7c544c0612bb", + "0x00000000000000000000000000000000002bd00367a458f46db12fcbe20d6698", + "0x000000000000000000000000000000d69ccdb1e09be0ce4a76c322c91b66e8c6", + "0x0000000000000000000000000000000000175ad6097932267423d3f8e127783c", + "0x0000000000000000000000000000001903863a0618900324f1b05f25a4d23ed6", + "0x000000000000000000000000000000000018d8c4892da2f5c40b86525752c761", + "0x0000000000000000000000000000008bc281539f5e808a5773747df05ff69518", + "0x00000000000000000000000000000000000d4fcfc717ab5fd25b6a895f09da6a", + "0x00000000000000000000000000000049643ac6a1154e3f0e2c64166a6ad33be9", + "0x00000000000000000000000000000000001691167b1a6af7f05463767159ecdd", + "0x00000000000000000000000000000017984cdee26a4d88f6a7c5ccbc245cbaff", + "0x000000000000000000000000000000000023699f159e31db9c9e299e534ba48e", + "0x00000000000000000000000000000070760bbd23372d2209e89754bf3defc008", + "0x000000000000000000000000000000000026745373abaf9da6de1b766fd88ec8", + "0x0000000000000000000000000000006c8d9892350916cf33d818f0b8fb2de2f2", + "0x000000000000000000000000000000000016136193193b5ac81ab03568134327", + "0x000000000000000000000000000000977b5170eb84adbcf095b891fcfdf6c186", + "0x00000000000000000000000000000000002fd97b1eb57f83270e1e0993074e04", + "0x000000000000000000000000000000d59b878582bdf517c854cc654d596ca5ac", + "0x0000000000000000000000000000000000287ff9bdc6271c7d16ee135e591a4c", + "0x00000000000000000000000000000076b2a3ac986770291fbfe2b5962015d98d", + "0x0000000000000000000000000000000000023cd005e48fff38e0ca0e912d844e", + "0x000000000000000000000000000000a559f6890f76006b49e9dc143a6c1c11fc", + "0x0000000000000000000000000000000000031e8f87eb8e5b7ca566105c5d6937", + "0x0000000000000000000000000000006213c6feee1cd9b0609201b259123c9d9a", + "0x00000000000000000000000000000000000618c41cd0105f37052198e262dcd8", + "0x0000000000000000000000000000001bb2954333b36d2db976e209100116a61e", + "0x000000000000000000000000000000000012952a9ff67c7aa2b924eab08241d6", + "0x00000000000000000000000000000065f5b6c4cc2697bc54944c1c66245a178f", + "0x00000000000000000000000000000000002877d60c57b3c224580e5ea9b0f84a", + "0x000000000000000000000000000000aa70635797d386288c34a816e7064da021", + "0x00000000000000000000000000000000001928cfa6af3c00a48e4b845395fd58", + "0x00000000000000000000000000000098cf4327f409f296a74e28a8219c81981d", + "0x000000000000000000000000000000000018cc1d16b8b8a298f921e6edc2a594", + "0x000000000000000000000000000000660b44038763380074e844887871b9911d", + "0x000000000000000000000000000000000026285347a265909a209c3759d676af", + "0x0000000000000000000000000000008091b7f127d8d3e11df697e67cd7ebc595", + "0x00000000000000000000000000000000000dba8e01880a34347ce6539c6d8617", + "0x0000000000000000000000000000000d1a95223c736d670b5eb8f62598234576", + "0x00000000000000000000000000000000000f74dc5278cd613c1ad61c1c539eba", + "0x00000000000000000000000000000004df7322c65435d46f8b77d6e3503ed397", + "0x00000000000000000000000000000000001d4d462030228821ad7f78bc55b441", + "0x000000000000000000000000000000a74484b21300de77a50c40c8135eeff0e5", + "0x0000000000000000000000000000000000105a15f737836bbb253786e9a06c71", + "0x000000000000000000000000000000278f5d5f41318024807bda88b5ed897e5c", + "0x000000000000000000000000000000000029d78e382ee1645fdd14a27bba9426", + "0x000000000000000000000000000000155e4b9a3fc8f84895cb9595d061969e8c", + "0x000000000000000000000000000000000009e85993e89b342ba2d6ab5fcf0cfc", + "0x000000000000000000000000000000e57533edc6143896fa1968fa0c6272897d", + "0x0000000000000000000000000000000000089f5ce8686f0845e1ec05b6f39418", + "0x000000000000000000000000000000dfc4222953b1f30cffd52aa0bb80a72ef1", + "0x00000000000000000000000000000000002ad42e3bd60c95aa37746e3a4d2282", + "0x00000000000000000000000000000046a573ded81dc131335acf2156ad191e3d", + "0x000000000000000000000000000000000019966ae74c271049f1b736f531c33d", + "0x0000000000000000000000000000008f654e1708eb68b58dffd23da40911cba6", + "0x00000000000000000000000000000000001f683771fa8dbe01394f3b5e6248d4", + "0x000000000000000000000000000000fecf8abfb0a0db0e85ee049a91dbda058f", + "0x00000000000000000000000000000000002c68fa6274457a9e4cd0cbc2ff5185", + "0x0000000000000000000000000000008d5f1ce5951649af44e0771b9a4cec19d9", + "0x0000000000000000000000000000000000163b20fc0591691d81ac665ab58d95", + "0x000000000000000000000000000000f67aa525fa3703e996bacb50f71df2b847", + "0x000000000000000000000000000000000008bbb2006058a97ecedcef1c44ad8f", + "0x0000000000000000000000000000006009e73e99c91936daa734a838fa72e987", + "0x0000000000000000000000000000000000029b1e53dbf2ef50bc0d7f156950de", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000004d6c574aee6d8a6f6bd8d608a257e21ebf", + "0x00000000000000000000000000000000001ebfa6149783a7488667aa666c9202", + "0x0000000000000000000000000000002f0c79b7ffc65062ff4098ca358ab2379b", + "0x000000000000000000000000000000000003af00ccc891754ea493a8dba373c7" +] diff --git a/fixtures/circuits/migrate/program.json b/fixtures/circuits/migrate/program.json new file mode 100644 index 0000000..15d9414 --- /dev/null +++ b/fixtures/circuits/migrate/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"4451863694570926191","abi":{"parameters":[{"name":"owner_pk","type":{"kind":"field"},"visibility":"private"},{"name":"old_address","type":{"kind":"field"},"visibility":"public"},{"name":"new_address","type":{"kind":"field"},"visibility":"public"}],"return_type":null,"error_types":{"7233165565571467992":{"error_kind":"string","string":"New address is not owned by the owner"},"12009498308778186721":{"error_kind":"string","string":"Old address is not owned by the owner"}}},"bytecode":"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","debug_symbols":"pZjdbttIDIXfxde+EA/nt6+yWBRu6hYBDCdwkwKLou++ksVPSRaQNo2vZkIOT44ofoqiX7uvxy/P3z/fn789/Nh9+uvX7svl/nS6//759HB3eLp/OI/RX7/3O378/HQ5HsfQ7lV+rHo8XI7np92n8/PptN/9PJyer4d+PB7O1/XpcBmzw353PH8d11Hw2/3pOO1+71+qh/VSy4piq76UV3tTb+v1uaSoL/by63N5U6/1el9+f7Ky1Jf0pt7X66XWQ0A+aE0hbXTABxTM1dYU8rpCTzkEel6t3+pBb0sP8kd6UK3Qg+rDmkLb6EGtvoxBX+1i31AYtAzSUFavwjZGMaVi9CH1l0Zaf/dl9Jdb2bV6GVs4tKWTVtdw2Kh/mUa3tIrTxjSmjIFU86pA3upi6ksXyyuk/3MjysY8uniiuHtflagbEjakpRFad7F1M70uNzMprUpsDGWpzGQd7EMCpS4CWhPQxuPREmhb9g8JlEXg9Tz8gUADKmv1Iz2ojoOaV++CNibSG8+WNPiHBKr9v8DmKGVfHk65DaseNiR6BYne+0cExqfi8ogd6uqd8OHGYdoUeM8wbQq8Z5g2uzBeOwobzwVPN47TpsDN41SHYeljWm9kvfHJtCnwnieT91uHqd86TP3GYdrqwbueTMlvHKVNgfeM0gZPLu6iv3pznP7a/z3+dLi7v7z5f2E3TNjsdzYvmhef/lbud2l6A97v8riMw1/mpU5vyPtdm3N9DtowR83msCniHvGQstCyEvFQsxZrn1cN83nZfF6KuEc8RTxHvES8Rjz0FHoe/txi1XzefT7vKeI54nGxHv48LtfjetMwvYWMq8WqWD3WNN2Jcc3TC8+4lojXWFvk+5zPoZdDL2vOZ498iniOtUS+Rr5FvM9rGeZ8sTlfwl8JfyX8lfBXwl8JfyX8lfBXw18NfzX81fBXw18NfzX81fBXw18Nfy38tfDXwl8Lfy38tfDXwl8Lfy38tfDXw18Pfz389fDXw18Pfz389fDXw18PfzaEQRvC4fjfCClnkziTOVNIVTaNM+HULKyaGZswa+acSaQym8KZyplGCs/Cs/AsPAvPwrPwLDwLz8Kz8Ox4djw7nh3PjmfHs+PZ8ex4djwnPCc8g5LBkgGTQZOBk8GTAZRBlIGUwZQBlUGVgZXBlQGWQZaBlsGWAZdBl4GXwZcBmEGYgZjBmAGZQZmBmcGZAZpBmoGawZoBm0GbgZvBmwGcQZyBnMGcAZ1BnYGdwZ0BnkGegZ7BngGfQZ+Bn8GfAaBBoIGgwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg4JBwaBgUDAoGBQMCgYFg5oYTMO0MTaaPqNNm1E5TYcnBudUJlVIVVKNVI9UQ7mhPDE4b5xNiqqJwbmqkKqkGqkeqYnBa2pi8JrqKHeUO54nBudNoapS1Uj1OeUTg+n6AhWefRApJ5VIZTaFTWXTqIpuuEU3fGLwmpoYnFNOKpHKpCbl6avuz8Pl/vDldIyP3t+ez3evvoE//fNIhq/kj5eHu+PX58txev+95sY34n8B","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"56":{"source":"use poseidon::poseidon2;\nuse crate::{InputNote, Note};\n\npub fn check_commitment(note: Note, commitment: Field) {\n assert(get_note_commitment(note) == commitment, \"Note commitment is not valid\");\n}\n\npub fn get_note_commitment(note: Note) -> Field {\n if (note.kind == 0) {\n assert(note.value == 0, \"Padding notes must be zero value\");\n 0\n } else {\n poseidon2::Poseidon2::hash(\n [0x2, note.kind, note.value, note.address, note.psi, 0, 0],\n 7,\n )\n }\n}\n\npub fn get_address(secret_key: Field) -> Field {\n poseidon2::Poseidon2::hash([secret_key, 0], 2)\n}\n\npub fn check_input_note_ownership(input_note: InputNote) {\n if (input_note.note.value != 0) {\n assert(\n get_address(input_note.secret_key) == input_note.note.address,\n \"Input note is not owned by the owner\",\n );\n }\n}\n\npub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) {\n let mut first_non_zero_kind = 0;\n let mut is_multiple_kinds = false;\n\n for i in 0..4 {\n if !is_multiple_kinds {\n if notes[i].kind != 0 {\n if first_non_zero_kind == 0 {\n first_non_zero_kind = notes[i].kind;\n } else if first_non_zero_kind != notes[i].kind {\n is_multiple_kinds = true;\n }\n }\n }\n }\n\n (is_multiple_kinds, first_non_zero_kind)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/note.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"71":{"source":"use common::get_address;\nuse poseidon_alt::hash;\n\nfn main(owner_pk: Field, old_address: pub Field, new_address: pub Field) {\n let calc_new_address = get_address(owner_pk);\n assert(calc_new_address == new_address, \"New address is not owned by the owner\");\n\n let calc_old_address = get_old_address(owner_pk);\n assert(calc_old_address == old_address, \"Old address is not owned by the owner\");\n}\n\nfn get_old_address(owner_pk: Field) -> Field {\n hash([owner_pk, 0])\n}\n\n#[test]\nfn test_main() {\n let pk = 101;\n let new_address = get_address(pk);\n let old_address = get_old_address(pk);\n\n println(new_address);\n println(old_address);\n\n main(pk, old_address, new_address)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/migrate/src/main.nr"},"74":{"source":"use crate::constants::{FULL_ROUNDS, PARTIAL_ROUNDS, RATE, ROUND_CONSTANTS, MDS};\n\n// S-box function (x^5)\nfn sbox(x: Field) -> Field {\n let x2 = x * x;\n let x4 = x2 * x2;\n x4 * x\n}\n\n// Apply MDS matrix multiplication\nfn apply_mds(state: [Field; 3]) -> [Field; 3] {\n let mut result = [0; 3];\n for i in 0..3 {\n for j in 0..3 {\n result[i] = result[i] + MDS[i][j] * state[j];\n }\n }\n result\n}\n\n// Full round function: S-box on all elements + MDS\nfn full_round(mut state: [Field; 3], round_constants: [Field; 3]) -> [Field; 3] {\n // Add round constants and apply S-box to all elements\n for i in 0..3 {\n state[i] = sbox(state[i] + round_constants[i]);\n }\n // Apply MDS matrix\n apply_mds(state)\n}\n\n// Partial round function: S-box on first element only + MDS\nfn partial_round(mut state: [Field; 3], round_constants: [Field; 3]) -> [Field; 3] {\n // Add round constants\n for i in 0..3 {\n state[i] = state[i] + round_constants[i];\n }\n // Apply S-box only to first element\n state[0] = sbox(state[0]);\n // Apply MDS matrix\n apply_mds(state)\n}\n\n// Main permutation function\npub fn permute(mut state: [Field; 3]) -> [Field; 3] {\n let r_f = FULL_ROUNDS / 2;\n let r_p = PARTIAL_ROUNDS;\n \n let mut round_idx = 0;\n \n // First half of full rounds\n for _ in 0..r_f {\n state = full_round(state, ROUND_CONSTANTS[round_idx]);\n round_idx = round_idx + 1;\n }\n \n // Partial rounds\n for _ in 0..r_p {\n state = partial_round(state, ROUND_CONSTANTS[round_idx]);\n round_idx = round_idx + 1;\n }\n \n // Second half of full rounds\n for _ in 0..r_f {\n state = full_round(state, ROUND_CONSTANTS[round_idx]);\n round_idx = round_idx + 1;\n }\n \n state\n}\n\n// Sponge construction for constant-length hashing\npub struct PoseidonSponge {\n state: [Field; 3],\n cache: [Field; 2],\n cache_size: u32,\n}\n\nimpl PoseidonSponge {\n // Initialize with initial capacity element for constant-length domain separation\n pub fn new(initial_capacity: Field) -> Self {\n let mut state = [0; 3];\n state[2] = initial_capacity; // Set capacity element at index RATE (2)\n Self {\n state,\n cache: [0; 2],\n cache_size: 0,\n }\n }\n \n // Absorb a field element\n pub fn absorb(&mut self, input: Field) {\n if self.cache_size == RATE {\n // Cache is full, perform duplex round\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // Add to cache\n self.cache[self.cache_size] = input;\n self.cache_size = self.cache_size + 1;\n }\n }\n \n // Perform duplex operation (add cache to state and permute)\n fn perform_duplex(&mut self) {\n // Add cached values to state\n for i in 0..RATE {\n if i < self.cache_size {\n self.state[i] = self.state[i] + self.cache[i];\n }\n }\n // Apply permutation\n self.state = permute(self.state);\n // Clear cache\n self.cache_size = 0;\n }\n \n // Squeeze output\n pub fn squeeze(mut self) -> Field {\n // Final duplex to compress any remaining cached data\n self.perform_duplex();\n // Return first element\n self.state[0]\n }\n}\n\n// Hash function for 2 elements (matching the Rust implementation)\npub fn hash_2(left: Field, right: Field) -> Field {\n // Initial capacity element: (2 << 64) for ConstantLength<2>\n let initial_capacity = 2 * 0x10000000000000000; // 2 * 2^64\n \n let mut sponge = PoseidonSponge::new(initial_capacity);\n sponge.absorb(left);\n sponge.absorb(right);\n sponge.squeeze()\n}\n\n// Generic hash function for N elements\npub fn hash(inputs: [Field; N]) -> Field {\n // Initial capacity element: (N << 64) for ConstantLength\n let initial_capacity = (N as Field) * 0x10000000000000000; // N * 2^64\n \n let mut sponge = PoseidonSponge::new(initial_capacity);\n for i in 0..N {\n sponge.absorb(inputs[i]);\n }\n \n // Add padding (zero padding) to make total absorbed elements a multiple of RATE\n // Calculate how many zeros to add\n let k = (N + RATE - 1) / RATE; // Ceiling division\n let padding_count = k * RATE - N;\n for _ in 0..padding_count {\n sponge.absorb(0);\n }\n \n sponge.squeeze()\n}","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/poseidon_alt/src/poseidon.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/mint/key b/fixtures/circuits/mint/key new file mode 100644 index 0000000..ea4d2c8 Binary files /dev/null and b/fixtures/circuits/mint/key differ diff --git a/fixtures/circuits/mint/key_fields.json b/fixtures/circuits/mint/key_fields.json new file mode 100644 index 0000000..3b4b142 --- /dev/null +++ b/fixtures/circuits/mint/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000016", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000a08adcc25969910c1a30bd279aa6cc4ea7", + "0x00000000000000000000000000000000000efcaa12f3e0a563e1c1bd148e0c2f", + "0x000000000000000000000000000000982f815c5eb3505bba1267c3eb8129f202", + "0x0000000000000000000000000000000000088e1c88ce233418e4acd4b85a4817", + "0x000000000000000000000000000000904bea02d857c8a818547c7961386980a1", + "0x00000000000000000000000000000000000f0258226de8aa39e606213bf74987", + "0x000000000000000000000000000000b69b499dd24e78204ec12cc65efa7510fe", + "0x0000000000000000000000000000000000203141e5ae66429577d73c87f096ac", + "0x00000000000000000000000000000001224061744707fe863c217d276a64b96a", + "0x000000000000000000000000000000000004128ba25373f57549a9c574d7610f", + "0x000000000000000000000000000000f7c92d4e8359de0d3be7230d37f5c41a19", + "0x00000000000000000000000000000000002c8ffc8c018b29894a2059ae895ba5", + "0x000000000000000000000000000000d6f7919e1aa174d18b6e5d47f5ff4b9570", + "0x00000000000000000000000000000000002af00f6ba447ae0acab188500d5bc7", + "0x0000000000000000000000000000008666e650cc28bd2c2ae85bebee63459428", + "0x0000000000000000000000000000000000267d130661d38b596252acbcb26c94", + "0x000000000000000000000000000000bb75773c5a8f286cf2bc0cb0295442a3b5", + "0x00000000000000000000000000000000001bc4218560c48f0e06d2a5f01942be", + "0x000000000000000000000000000000fe4e20eb12765ddcebd4734e3a6fc44814", + "0x0000000000000000000000000000000000228b63b0e2a8ff5149a7f19f334443", + "0x000000000000000000000000000000c13cf50ae2123e2accd1b86d2ecf43839b", + "0x00000000000000000000000000000000001a00edf74371c42eacde097c76fcb7", + "0x000000000000000000000000000000d6ad49a06cd4c67a4a72913c23b33aa1c0", + "0x00000000000000000000000000000000002fc23338817627cbe31cd045a702cc", + "0x000000000000000000000000000000dfc12205eb78f54bd9f4742df51d35d9d2", + "0x000000000000000000000000000000000015729599ef3888a89db8f52912b65c", + "0x000000000000000000000000000000d93cb3670761c8c93df420b3a7d89baefa", + "0x00000000000000000000000000000000001890a0e4fb04b07215d2034d92fc6a", + "0x00000000000000000000000000000028cf5a0f5e8971204e6a9ca00855c10bc5", + "0x0000000000000000000000000000000000275baff3f562db2c69ba858e2a6d68", + "0x000000000000000000000000000000250ad879e4eb310e4cd42160e444f74d8d", + "0x000000000000000000000000000000000016e41d59213ff60c7d994acabab90a", + "0x000000000000000000000000000000f32752432ef560d1a0801a4c97c2710de2", + "0x00000000000000000000000000000000000ad5b0450dd36e18f6e1e4d888fcac", + "0x0000000000000000000000000000007b57eb803b551b9f45cc9e4e180d82019c", + "0x0000000000000000000000000000000000172c0f496a503cf2576344fa7d6889", + "0x00000000000000000000000000000065d5bc255a11d44db87031b4d1f6bfae6c", + "0x0000000000000000000000000000000000183106d58a67c72452f14e474a9009", + "0x000000000000000000000000000000c189d9a4fd51a2941b1fe019a656dcc462", + "0x000000000000000000000000000000000029dfbe26f2f1397e4f854a19577d90", + "0x000000000000000000000000000000c3bc30568b7c96623e2d6e582b6509c07d", + "0x000000000000000000000000000000000010955b4e443334aac8dbfa7afaa646", + "0x0000000000000000000000000000003d1c3d97961a94c1ab0d0dac34ec583bfd", + "0x00000000000000000000000000000000002c3593e38179c0e60badd6f3c3d738", + "0x000000000000000000000000000000459a1f88f27de2a595b00ecc61182776c0", + "0x00000000000000000000000000000000000540d1ccee15f800ce74af7478655d", + "0x00000000000000000000000000000050822c8a009d751404ec073158bc949b8f", + "0x0000000000000000000000000000000000251f52d813ced90037f1314103ab99", + "0x0000000000000000000000000000005dc16b77edab1da0cb4dbb877512ee297a", + "0x00000000000000000000000000000000000c8f36f3e8dabe6f256c82d02dd303", + "0x000000000000000000000000000000bce3833895f59e28299503c22128027b0e", + "0x000000000000000000000000000000000029cac85ddf6ea010be3a1abe94a15c", + "0x0000000000000000000000000000003ed493f706f8a7804a0c30a99f858cc30b", + "0x00000000000000000000000000000000001243e96784c0bce8b64728af5bd28b", + "0x000000000000000000000000000000b994022fffcfce5c4d22db3a0bea5da535", + "0x000000000000000000000000000000000018eb47d8301243daa090c7a85bb030", + "0x00000000000000000000000000000082bfca2a36037a43645cdf21f668666e46", + "0x00000000000000000000000000000000002c32ac1d0834656e86dde5ff8e1502", + "0x0000000000000000000000000000009101a624170501f37277af59ab316092b6", + "0x00000000000000000000000000000000000a4510b97820de527450c00e449f94", + "0x0000000000000000000000000000002255efd9777ef29ca69b7d5cb56ea960b1", + "0x0000000000000000000000000000000000236b811333c14fe17a1a3f80ac0de2", + "0x00000000000000000000000000000033abefee16de21152de4a5e416276058dc", + "0x00000000000000000000000000000000001a467d8701352d28f3b5c0306b82e2", + "0x0000000000000000000000000000001e3d8f8315d70d7ec6a808163b861b1219", + "0x00000000000000000000000000000000000fc829823fda59fb64d160de1c7d82", + "0x0000000000000000000000000000003fcd9570ff1f07ae50370cdc59674fb058", + "0x000000000000000000000000000000000024fd701cdd5cdcd4e234f9706f2870", + "0x000000000000000000000000000000024a143b5394628ef8f44107958ca98f03", + "0x00000000000000000000000000000000002096d2f312f1325dc874d49e8aeafc", + "0x0000000000000000000000000000000dd4f1525fc54aff3e5986943b2af6a514", + "0x00000000000000000000000000000000000497bdf07f677a3fa657026db2c80e", + "0x0000000000000000000000000000002e5d11cce2ff9c828677ac3d401a4872ef", + "0x00000000000000000000000000000000002f75322813fff6c5791ebde1124fa1", + "0x0000000000000000000000000000001cf321d7e4f23c26ddaaefb66560522e77", + "0x000000000000000000000000000000000016255c30575b21b4d912284ce3d3d8", + "0x000000000000000000000000000000c3ef566e839538517a64028e1b5bf29964", + "0x000000000000000000000000000000000019ad71e365a0aabe77e1590fbc4b92", + "0x000000000000000000000000000000f9a13e6ec6ffcb9da6b2f930cbf1253d9d", + "0x00000000000000000000000000000000000417a300d2f7e61b5db63028c441d7", + "0x0000000000000000000000000000007811d11398c41475e1b626cdcc5fe4badd", + "0x00000000000000000000000000000000001e2af1921132d4d54a0f595a685e8f", + "0x000000000000000000000000000000c0b6aaab7def9338171ce966c0f4e659fe", + "0x000000000000000000000000000000000021a2b6c564fb7add9216551c111ecc", + "0x000000000000000000000000000000fc014b28aec0e46ab8c723d25580b5e770", + "0x00000000000000000000000000000000000c267af0c05b0bd23a313da2100d2e", + "0x00000000000000000000000000000024c5de0978b84ebdaef4f8f544a7c83717", + "0x00000000000000000000000000000000000587e3699ab69e9f5796b6d1beb509", + "0x000000000000000000000000000000c1eda0f1b4401e0a07bbda69ff27543db9", + "0x000000000000000000000000000000000017a35e65fbe5d2346487ce74ab3bba", + "0x0000000000000000000000000000003c4f1a7b1c4c42334e75594860ed771e55", + "0x000000000000000000000000000000000016be6a4109beb39796ca01b53855e3", + "0x0000000000000000000000000000008f8f806380c691a9b46fcc877d645f9277", + "0x000000000000000000000000000000000012315d357894a99410a006523703eb", + "0x000000000000000000000000000000bca167f19a1e2b87a9e83428d29c6e4cd0", + "0x0000000000000000000000000000000000197e70aa1c0f8ff353c7db9581f846", + "0x000000000000000000000000000000e994426ab11d13b11f4590566a6313f31d", + "0x00000000000000000000000000000000002ceed096c8e45e20b93c36b65cb156", + "0x0000000000000000000000000000003878d44ecb799d0cb3f87a8d93a8947fcf", + "0x00000000000000000000000000000000001898b36354174b623451d80238a0c7", + "0x000000000000000000000000000000e44348450f34f3402f2de76ec0c7df8cb4", + "0x00000000000000000000000000000000001ad8751a8486777ab7e1f23db8d15a", + "0x00000000000000000000000000000086e1e4762258a5bcdefd62ef8a9b7223b8", + "0x000000000000000000000000000000000005f0f7ada1b386cc6fd114bfc41ac2", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000622355910c1d1bb9929890863d6b629c5a", + "0x00000000000000000000000000000000001b94be5c442fc08717febf96f03dcd", + "0x00000000000000000000000000000045ee3a089708181624b4b408721995916e", + "0x0000000000000000000000000000000000182104967d5954260f9b425922c9fa" +] diff --git a/fixtures/circuits/mint/program.json b/fixtures/circuits/mint/program.json new file mode 100644 index 0000000..9123bb8 --- /dev/null +++ b/fixtures/circuits/mint/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"10878826230422803608","abi":{"parameters":[{"name":"utxo","type":{"kind":"struct","path":"common::utxo::Utxo","fields":[{"name":"input_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::InputNote","fields":[{"name":"note","type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"field"}}]}}},{"name":"output_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}}},{"name":"input_merkle_paths","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::MerklePath","fields":[{"name":"path","type":{"kind":"array","length":160,"type":{"kind":"field"}}}]}}}]},"visibility":"private"},{"name":"recent_root","type":{"kind":"field"},"visibility":"public"},{"name":"input_nullifiers","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"},{"name":"output_commitments","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"},{"name":"mint_value","type":{"kind":"field"},"visibility":"public"}],"return_type":null,"error_types":{"2495398788693742820":{"error_kind":"string","string":"Mint output must match minted value"},"2532032818322018100":{"error_kind":"string","string":"Invalid nullifier 0"},"4703047920556725948":{"error_kind":"string","string":"Field failed to decompose into specified 254 limbs"},"6749186246397432903":{"error_kind":"string","string":"Invalid nullifier 1"},"7126743292872256338":{"error_kind":"string","string":"Padding notes must be zero value"},"11305677572723109408":{"error_kind":"string","string":"Inconsistent kinds are not allowed"},"12272962467056991279":{"error_kind":"string","string":"Invalid output commitment 1"},"12382400539224138144":{"error_kind":"string","string":"Input note is not owned by the owner"},"12469291177396340830":{"error_kind":"string","string":"call to assert_max_bit_size"},"13108753448563390903":{"error_kind":"string","string":"Input commitment is not in recent root"},"14885583290507436593":{"error_kind":"string","string":"Invalid output commitment 0"}}},"bytecode":"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","debug_symbols":"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dWnudqi6NHczVdqH5twtVKW+W6q0D825b+1jax9bZ7WvGfStfWztY+usts5Kc+6ac9ecu+bcNeeuOXfNuWvOXXPumnPXnLvm3DXnHtd15eec3yvpoTn30FmF9NCc+znnH78qtI/UdaU5d825a849pYfm3DXnntJDc+6pHppzL52V5tw15166dktnVTorzbmXzkpz7ppz78sTvbUPzblrzl1z7ppzb/Voad7ax2gfo32M9jHax2gfox6jHqMeo33MtY84DlXXPuK49hHHVuWqQlXqu6WqVV0zGOtQdWkeSz3WtY9YripU5fWrVukbreo6qzDtw5YqU7WvX3DO+b3SPnQ/D9M+TPswndXWPvZSpX1snZXu56H7eWyd1Tnn91dY2ofmPPxQpbNy9XD1cPVw9XD1cPVw9XD1CPUInVXorEJ6xHVdhe7noft5hPQI9dCch+Y8NOeR6pHqoTmPvPgqUj1SPVI9NOehOQ/NeWjOQ3MemvPQnIfmPDTnoTkPzXlozqOleZsq6aE5j5YeLT10P4++PDE056E5j9FZac5Dcx66n8dcXBKTqrSP0VlpzlNznrqf53Hda1Nznprz1Jyn5jw156k5T815as5Tc56a89Scp+Y8NeepOU/NeWrOU3OemvPUnKfmPO26D6ZpH5rz1JynuD11P0/dz1PcnuL21P08xe2pOc996ZHi9tT9PDXnuaWH7uep+3m69NCcp+7nqft56n6eup+n5jw156k5T815as5Tc56a89Scp+Y8Necpbk9xe6b2kdf9I3U/T93PU9yeup+n7ucpbk/dz1PcnprzFLen5jw15yluz7q8JDXnqTlPcXuWzqrVo9Wj1aPVo9Wj1UP389T9PHU/T3F7js5K9/Ocy0tytiqdle7nKW7P0Vnpfp5znVUdh6prH6X7eYnb63BVoeqawRK3l7i9juusStxe4vZapuqawRK3l7i9VqpSD3F7reusSnNedl1XJW4v26rUQ9xelqpKVWsV7UNzXprz0v28dD8vcXuJ20v389rqsbWPLT1ceuh+Xrqfl0sP3c9L9/Ny6aE5L815ac5Lc16a89Kcl+a84mKfilAlPTTnpTkvzXlpziuv+2ClqdJZac5Lc16a89Kcl+a8NOelOS/NeWnOS3NemvPS83np+bw056U5L93PS/fz0vN56fm8dD8v3c9L3F66n5fu56Xn8zrn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AZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlAZcEXBJwScAlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlCZckXJJwScIlBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElBZcUXFJwScElDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlDZc0XNJwScMlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAlA5cMXDJwycAl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fYnzvsTxEsdLXO9et/OM43CJwyXOM47jJY6X+Kbbphtc4nCJ84zjeInjJc4zjsMlDpc4XOJwieMljpc4zzjOM47zjOM84zhecuZe67iXTvnRre5HffeS2veyKD+69bnCR7e2j/LuJY9yUZoWu3vJo3QtdveSR5la9+4lj7JZjG53LzkXu3vJozQtdveSR+la7O4ljzJZrCibxUbl3UvOxe5e8ihNi9295FG6Frt7yaNMFivKZrFRefeSc7G7lzxK02J3L3mUrsUG3QbdBt0G3e5eci/P3Ot9sTP3+iil25l7fZTS7cy9PspksaJsFpNuZ+71XGwtSul25l4fpXQ7c6+PMlmsKJvFpNuZez0Xs0Up3c7c66OUbmfu9VEmixVls5h0O3Ov52J7UUq3M/f6KKXbmXt9lMliRdkshm6Obo5ujm6Obo5ujm6Obo5ujm6OboFugW6BboFugW6BboFugW6BboFuiW6JboluiW6JboluiW6JboluiW6FboVuhW6FboVuhW6FboVuhW6Fbo1ujW6Nbo1ujW6Nbo1ujW6Nbo1ug26DboNug26DboNug26DboNuI93O3Ot9sTP3+iil25l7fZTS7cy9PspksaJsFpNuZ+71XGwtSul25l4fpXQ7c6+PMlmsKJvFpNuZez0Xs0Up3c7c66OUbmfu9VEmixVls5h0O3Ov52J7UUq3M/f6KKXbmXt9lMliRdkshm6Obo5ujm6Obo5ujm6Obo5ujm6OboFugW6BboFugW5wScIlCZckXHLmXs8SLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsSLkm4JOGShEsKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksKLim4pOCSgksa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1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F6d3KuTe3Vyr07u1cm9OrlXJ/fq5F79zL3OcS+D8qPb+L0syqa8dbu99v4oP7zk9q77Xt663d5q30uj3JS3bre3z/cyPsr77/3wktvL5XtZlE05Kj+85PbK+V4uSqP86Gb30wmnDMqkLMqm/Oi277/3w0uucuk3pFFuSqcMSvaW7O3DS27vxe/lqKyDcunnlFGyt2Jvxd6KvRV7K/ZW7K3Z24eXXKVRsrdmb83emr01e2t0a3Sbg5K9DXsb9jbsbdjbsLdhb8Pe5r63/Y/vvv3P97/8+P3vf/rhL9/+4++3//jff/v5D3/98U8/P/7jX//3n69/8vtffvzppx//+Ls///KnP/zwX3/75Yff/fSnP9z/2T/+8x//Bw==","file_map":{"18":{"source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [u1; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n","path":"std/field/mod.nr"},"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"55":{"source":"use poseidon::poseidon2;\nuse crate::MerklePath;\n\nimpl MerklePath {\n pub fn root_from_leaf(self, leaf: Field) -> Field {\n let bits: [u1; 254] = leaf.to_le_bits();\n let mut hash = leaf;\n for i in 0..160 {\n let sibling = self.path[i];\n if bits[i] == 0 {\n hash = poseidon2::Poseidon2::hash([hash, sibling], 2);\n } else {\n hash = poseidon2::Poseidon2::hash([sibling, hash], 2);\n }\n }\n\n hash\n }\n\n pub fn validate(self, leaf: Field, root: Field) -> bool {\n self.root_from_leaf(leaf) == root\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/merkle_path.nr"},"56":{"source":"use poseidon::poseidon2;\nuse crate::{InputNote, Note};\n\npub fn check_commitment(note: Note, commitment: Field) {\n assert(get_note_commitment(note) == commitment, \"Note commitment is not valid\");\n}\n\npub fn get_note_commitment(note: Note) -> Field {\n if (note.kind == 0) {\n assert(note.value == 0, \"Padding notes must be zero value\");\n 0\n } else {\n poseidon2::Poseidon2::hash(\n [0x2, note.kind, note.value, note.address, note.psi, 0, 0],\n 7,\n )\n }\n}\n\npub fn get_address(secret_key: Field) -> Field {\n poseidon2::Poseidon2::hash([secret_key, 0], 2)\n}\n\npub fn check_input_note_ownership(input_note: InputNote) {\n if (input_note.note.value != 0) {\n assert(\n get_address(input_note.secret_key) == input_note.note.address,\n \"Input note is not owned by the owner\",\n );\n }\n}\n\npub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) {\n let mut first_non_zero_kind = 0;\n let mut is_multiple_kinds = false;\n\n for i in 0..4 {\n if !is_multiple_kinds {\n if notes[i].kind != 0 {\n if first_non_zero_kind == 0 {\n first_non_zero_kind = notes[i].kind;\n } else if first_non_zero_kind != notes[i].kind {\n is_multiple_kinds = true;\n }\n }\n }\n }\n\n (is_multiple_kinds, first_non_zero_kind)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/note.nr"},"57":{"source":"use poseidon::poseidon2;\nuse crate::note::{check_input_note_ownership, get_note_commitment, is_multiple_kinds};\nuse crate::{InputNote, MerklePath, Note};\n\npub struct Utxo {\n pub input_notes: [InputNote; 2],\n pub output_notes: [Note; 2],\n pub input_merkle_paths: [MerklePath; 2],\n}\n\nimpl Utxo {\n pub fn validate(\n self,\n recent_root: Field,\n input_nullifiers: [Field; 2],\n output_commitments: [Field; 2],\n ) {\n let input_commitments = [\n get_note_commitment(self.input_notes[0].note),\n get_note_commitment(self.input_notes[1].note),\n ];\n let computed_output_commitments = [\n get_note_commitment(self.output_notes[0]),\n get_note_commitment(self.output_notes[1]),\n ];\n\n assert(output_commitments[0] == computed_output_commitments[0], \"Invalid output commitment 0\");\n assert(output_commitments[1] == computed_output_commitments[1], \"Invalid output commitment 1\");\n\n assert(\n input_nullifiers[0] == expected_nullifier(self.input_notes[0].note, input_commitments[0]),\n \"Invalid nullifier 0\",\n );\n assert(\n input_nullifiers[1] == expected_nullifier(self.input_notes[1].note, input_commitments[1]),\n \"Invalid nullifier 1\",\n );\n\n self.output_notes[0].value.assert_max_bit_size::<240>();\n self.output_notes[1].value.assert_max_bit_size::<240>();\n\n verify_input_membership(input_commitments[0], self.input_merkle_paths[0], recent_root);\n verify_input_membership(input_commitments[1], self.input_merkle_paths[1], recent_root);\n\n check_input_note_ownership(self.input_notes[0]);\n check_input_note_ownership(self.input_notes[1]);\n\n let (is_multiple_kinds, _) = is_multiple_kinds([\n self.input_notes[0].note,\n self.input_notes[1].note,\n self.output_notes[0],\n self.output_notes[1],\n ]);\n assert(!is_multiple_kinds, \"Inconsistent kinds are not allowed\");\n }\n}\n\nfn expected_nullifier(note: Note, commitment: Field) -> Field {\n if commitment == 0 { 0 } else { poseidon2::Poseidon2::hash([commitment, note.psi], 2) }\n}\n\nfn verify_input_membership(commitment: Field, merkle_path: MerklePath, recent_root: Field) {\n if commitment != 0 {\n assert(merkle_path.validate(commitment, recent_root), \"Input commitment is not in recent root\");\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/utxo.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"94":{"source":"use common::{get_note_commitment, InputNote, MerklePath, Note, Utxo};\nuse poseidon::poseidon2;\n\nfn main(\n utxo: Utxo,\n recent_root: pub Field,\n input_nullifiers: pub [Field; 2],\n output_commitments: pub [Field; 2],\n mint_value: pub Field,\n) {\n mint_value.assert_max_bit_size::<240>();\n\n let input_value = utxo.input_notes[0].note.value + utxo.input_notes[1].note.value;\n let output_value = utxo.output_notes[0].value + utxo.output_notes[1].value;\n assert(output_value == input_value + mint_value, \"Mint output must match minted value\");\n\n utxo.validate(recent_root, input_nullifiers, output_commitments);\n}\n\n#[test]\nfn test_mint_one_input_two_outputs() {\n let pk: Field = 101;\n let address = common::get_address(pk);\n\n let note_1 = Note { kind: 1, value: 10, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n let note_3 = Note { kind: 1, value: 1, address, psi: 3 };\n let note_4 = Note { kind: 1, value: 12, address, psi: 4 };\n\n let input_commitment_1 = get_note_commitment(note_1);\n let output_commitment_1 = get_note_commitment(note_3);\n let output_commitment_2 = get_note_commitment(note_4);\n\n let input_path_1 = MerklePath { path: [0; 160] };\n let input_path_2 = MerklePath { path: [0; 160] };\n let recent_root = input_path_1.root_from_leaf(input_commitment_1);\n let utxo = Utxo {\n input_notes: [input_note_1, input_note_2],\n output_notes: [note_3, note_4],\n input_merkle_paths: [input_path_1, input_path_2],\n };\n\n main(\n utxo,\n recent_root,\n [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0],\n [output_commitment_1, output_commitment_2],\n 3,\n );\n}\n\n#[test(should_fail)]\nfn test_mint_rejects_bad_value_conservation() {\n let pk: Field = 101;\n let address = common::get_address(pk);\n\n let note_1 = Note { kind: 1, value: 10, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n let note_3 = Note { kind: 1, value: 1, address, psi: 3 };\n let note_4 = Note { kind: 1, value: 12, address, psi: 4 };\n\n let input_commitment_1 = get_note_commitment(note_1);\n let output_commitment_1 = get_note_commitment(note_3);\n let output_commitment_2 = get_note_commitment(note_4);\n\n let input_path_1 = MerklePath { path: [0; 160] };\n let input_path_2 = MerklePath { path: [0; 160] };\n let recent_root = input_path_1.root_from_leaf(input_commitment_1);\n let utxo = Utxo {\n input_notes: [input_note_1, input_note_2],\n output_notes: [note_3, note_4],\n input_merkle_paths: [input_path_1, input_path_2],\n };\n\n main(\n utxo,\n recent_root,\n [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0],\n [output_commitment_1, output_commitment_2],\n 2,\n );\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/evm/mint/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/points/key b/fixtures/circuits/points/key new file mode 100644 index 0000000..9e80925 Binary files /dev/null and b/fixtures/circuits/points/key differ diff --git a/fixtures/circuits/points/key_fields.json b/fixtures/circuits/points/key_fields.json new file mode 100644 index 0000000..eff2a43 --- /dev/null +++ b/fixtures/circuits/points/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x000000000000000000000000000000000000000000000000000000000000001d", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000a6168a5d7c3e2cf37dd582ed0effd02718", + "0x00000000000000000000000000000000000e12f658c0bd33dabdd83ee2fc1dc3", + "0x000000000000000000000000000000c503b410db5430590aea82029fe5e59fbb", + "0x000000000000000000000000000000000014a2384bdf02f389db76baea6569ab", + "0x00000000000000000000000000000041f6b9af0a531c3ace6d3093430bc55405", + "0x0000000000000000000000000000000000151c74980ada740253c22baa3d1fba", + "0x00000000000000000000000000000033a73c99e561a6324d34d648e832ae7809", + "0x000000000000000000000000000000000001cd9c41c5ad397d5e55dcb98214e9", + "0x000000000000000000000000000000519243ddfbac60a34167919c61892686c8", + "0x00000000000000000000000000000000001b308aa999b05e8e3d3ef2f6ece8af", + "0x000000000000000000000000000000ab2a1233f0dd71626bada916875d737a1b", + "0x00000000000000000000000000000000001e8180e4f08d50c9163771599e2549", + "0x000000000000000000000000000000dff6fcd1ec2b1aa2cf61f25f23ded26740", + "0x000000000000000000000000000000000018ffcf54104740c1dec9a76b02e32b", + "0x000000000000000000000000000000732a35076dddbff739b059e53d4e927e3e", + "0x00000000000000000000000000000000002e33f81b5d7fc0ce93d9da7358da77", + "0x0000000000000000000000000000003686c83893c43be59bbe9f5a40c3c453ed", + "0x000000000000000000000000000000000006995d90b04276190b880d37e6e148", + "0x0000000000000000000000000000004efdb19f1bcc3273f48564b548c9f66f4c", + "0x000000000000000000000000000000000026d85ebd2995b766e07c48140d2c48", + "0x000000000000000000000000000000eedc2eefea1fed1071f9be4f833c303d7d", + "0x000000000000000000000000000000000000897a92019b15ceefe7ef1f5db145", + "0x000000000000000000000000000000c3d778837b3497de6c32eb407fbb361287", + "0x000000000000000000000000000000000026f889a65488724f9971189b2a72f2", + "0x0000000000000000000000000000004d63887059b541c3d5dbe38bfd517aa579", + "0x00000000000000000000000000000000002ee537ee80c33fc3003e53f2fa67b1", + "0x0000000000000000000000000000008e02933d1e153e33e5ea7d03b0c21b314a", + "0x00000000000000000000000000000000000ecddf7b61838886fcf1a7fec5c69d", + "0x000000000000000000000000000000c53ab2a40f19c37a3af38d6b01d4aa0fd2", + "0x00000000000000000000000000000000001f7bf0917b7528a85dd05a6329a89d", + "0x0000000000000000000000000000009838b27f7083867295c2cea41f967ddc86", + "0x000000000000000000000000000000000010c322bbad5fac5a95578a819f01f2", + "0x000000000000000000000000000000ce25c8f3086983b188316b78b475f80e34", + "0x0000000000000000000000000000000000141acee82027ff2ff5bfac107f0d42", + "0x000000000000000000000000000000fb1cc309c5240eaa1898b379186e55463a", + "0x0000000000000000000000000000000000218b74a93fbb15d47f5c8d605e606d", + "0x0000000000000000000000000000000dd8604daf8f272edb7f5d8eff34582f48", + "0x00000000000000000000000000000000002cd02fba8d086e84c7463635dd283b", + "0x000000000000000000000000000000fc7773897818f6c283483da367e579dd6c", + "0x000000000000000000000000000000000014c6cd224a50cc291241f705ef42a2", + "0x0000000000000000000000000000001b0faac429a1bcb17521bbee165a370a25", + "0x000000000000000000000000000000000018128f0d9165d9f397a5bb5ccc5981", + "0x000000000000000000000000000000656650ac928416353f5d8aa7b2cc1e5d09", + "0x00000000000000000000000000000000001f073b8aa5c50d1a9913ed3c7a32af", + "0x0000000000000000000000000000004883a7b51878c40229f53a269fa1e29145", + "0x000000000000000000000000000000000019b37509421349adab76bdc8045eea", + "0x0000000000000000000000000000005a43fe0a2ae87e3946384662b01f77a75b", + "0x000000000000000000000000000000000006b8de0788811f729fcc40429e056f", + "0x00000000000000000000000000000049d89e4ab6c431125dc36f58e8e4d63d42", + "0x00000000000000000000000000000000000ecc65f4d9680d4605ef3f65c2a89f", + "0x0000000000000000000000000000007eb81d20cc214976f05a0df49c7b1b35e4", + "0x000000000000000000000000000000000001eda25a7d886b356ddf973b457676", + "0x00000000000000000000000000000055fd6423ca3176e0dcf3f711bc31a849c0", + "0x0000000000000000000000000000000000017b3dd182c537a8b2f60349a8bc4d", + "0x000000000000000000000000000000643d7039452f44bb57beb696faeb200e6d", + "0x00000000000000000000000000000000000c08bcf05099e7ecb61d07fe781f41", + "0x0000000000000000000000000000009a908104f0223ffec39f2f44330e8ddbb9", + "0x00000000000000000000000000000000001ee3ba77747909e3e04ad5ddbc9792", + "0x0000000000000000000000000000007a1e3f133a7cbbc74eeaa578159583c39c", + "0x00000000000000000000000000000000000d9f08809b28547b02a52213153457", + "0x000000000000000000000000000000f7b84453e5d3a2f1454b690366d444eabf", + "0x000000000000000000000000000000000024f381988881c37dca812def19f557", + "0x000000000000000000000000000000bc28901a671b64a715123a3c835cbc1562", + "0x00000000000000000000000000000000000415fb1214fed1fdb1f61f19edd3cd", + "0x0000000000000000000000000000007781b3f082c821658c72e409f72f338007", + "0x0000000000000000000000000000000000220e74691a9010fee8cd2a4a90460e", + "0x000000000000000000000000000000541761def181312496f4b0746e365c33dc", + "0x000000000000000000000000000000000003dbb90df4ccde22f2710a55b8a9cc", + "0x0000000000000000000000000000005bf1358d26e2689ccefe01a8e528e54606", + "0x00000000000000000000000000000000001e9296116cd19996c20b20fd6b2c54", + "0x00000000000000000000000000000054609882967af8dbc6f597b39e5224c131", + "0x0000000000000000000000000000000000021a02da38e22fb16f2fab69eef710", + "0x000000000000000000000000000000f17252b0a2d6f5070054ad65c508d4a0fd", + "0x0000000000000000000000000000000000040ad6c52967eca4d85fcfb8e02e7a", + "0x0000000000000000000000000000001962af8c5fe9a69350ad685efbb57ba690", + "0x00000000000000000000000000000000000468a323d671afb702df87ac7f66ae", + "0x000000000000000000000000000000ae02421c8d312722658db443eb6e5c4121", + "0x00000000000000000000000000000000001b7ff6676ec0938e70b280c50ddeae", + "0x0000000000000000000000000000009600790cad72ebecf3bcc981ce401f6759", + "0x00000000000000000000000000000000001a9b615989df0c2fb9fa6cbb51f3e7", + "0x0000000000000000000000000000007cc32175b8cccc8d7296bf9aa3ef2faa38", + "0x00000000000000000000000000000000002b0c701dd16e690d0d653d181af3d8", + "0x000000000000000000000000000000f2df4663c24e6ba9c853654c41697d9943", + "0x00000000000000000000000000000000001efd3cdf3b642e7736fca2aed3db43", + "0x000000000000000000000000000000a08fba116a933457c01041afe9deba3bad", + "0x00000000000000000000000000000000000e37f9ecc684004cc5fb50495f9dc5", + "0x000000000000000000000000000000ed8c57ccbc32250739c7cf68be83512c09", + "0x0000000000000000000000000000000000245068b9cfb264956748dfca843b34", + "0x0000000000000000000000000000000ddc72fa5675348bf2044edf5dc4d5a58c", + "0x000000000000000000000000000000000007996eb6dfdbbe9366eb89f10c9e3f", + "0x000000000000000000000000000000b92d56fc8510645d8904922fba3e1e38da", + "0x000000000000000000000000000000000007900286f41a6b1b401de720f9eaa6", + "0x000000000000000000000000000000c66ea4cfcd33cb6e9f03fd0a69dd46c799", + "0x0000000000000000000000000000000000299718f02caec5c6f5c312a23adca7", + "0x0000000000000000000000000000007ec20cd2a6b3fc442d3164a1d42bb5c3f1", + "0x00000000000000000000000000000000002016239e3dc69d93a022823784a64a", + "0x00000000000000000000000000000000757b9d432d997e20f2d46ba0e76c6d8b", + "0x000000000000000000000000000000000006d9649e48ef2efa0dba8c8cd1f1e6", + "0x0000000000000000000000000000002b85ef1872bdb686464db0a6fd7eebad28", + "0x00000000000000000000000000000000001d27bd1ff3359d28ce4352e26e059d", + "0x00000000000000000000000000000094d4c42ce8b495bbc46bef593881c63172", + "0x0000000000000000000000000000000000156d4ec761ecbf3624548e81c84654", + "0x000000000000000000000000000000165df3608620713985e9c05d7c5faa183a", + "0x000000000000000000000000000000000029ef58088ef385b57d6b1ba1fd2fc6", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000009d9344b1c3a22a08e8e6a108dee7372660", + "0x00000000000000000000000000000000002386be3e90e500d845da6a3eb24bbb", + "0x000000000000000000000000000000a7409f6955b974b188733f8ab5678da3f2", + "0x00000000000000000000000000000000000b1db96a132095732a1776bf469c5d" +] diff --git a/fixtures/circuits/points/program.json b/fixtures/circuits/points/program.json new file mode 100644 index 0000000..f126e10 --- /dev/null +++ b/fixtures/circuits/points/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"13150701682663373141","abi":{"parameters":[{"name":"notes","type":{"kind":"array","length":10,"type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},"visibility":"private"},{"name":"secret_keys","type":{"kind":"array","length":10,"type":{"kind":"field"}},"visibility":"private"},{"name":"address","type":{"kind":"field"},"visibility":"private"},{"name":"timestamp","type":{"kind":"field"},"visibility":"public"},{"name":"value","type":{"kind":"field"},"visibility":"public"},{"name":"hash","type":{"kind":"field"},"visibility":"public"},{"name":"commitments","type":{"kind":"array","length":10,"type":{"kind":"field"}},"visibility":"public"}],"return_type":null,"error_types":{"7126743292872256338":{"error_kind":"string","string":"Padding notes must be zero value"},"8792683970673111909":{"error_kind":"string","string":"Invalid value"},"12382400539224138144":{"error_kind":"string","string":"Input note is not owned by the owner"},"16398460003478624606":{"error_kind":"string","string":"Note commitment is not valid"}}},"bytecode":"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","debug_symbols":"pZjdbtswDIXfxde5EEVSP3uVYSjSNh0CBGmRJQOGYu8+Ozx02wEyDOsmVOIcid8xKf+8D8+Hx9vPh+P55fXX8O37+/B4OZ5Ox58Pp9en/fX4eh5/ff+7G/zrw/VyOIw/DZ+Oj6q3/eVwvg7fzrfTaTf83p9u9z/9etuf7/G6v4xHw244nJ/HOE74cjwdptHf3Yc6tKWcFWIuPMvzar2QLy5RtuiVXJ90iz4n6JVCSy9tPUWBnqTOek1f9NrWR63Qx8xb9DW6/yFv0HPOzh+opS8LevX1hdKsT/JFXxfyj2U2gENszUALp5A4+BTEsTSnoPYUVbyKq26agEJ0Hyh8KsT/p+CFSpQ0l7LUjyyorneC0pwFFe10IuuW85mKN3RMlZsp5P7zWfpPR+0+HUtWZEofvR1aScSlssqZnSPXZndMsF2lvZhD/TgdNTZzWLdHpuYet1DWGr2kNJfWHh1Te4JU/FTm9ia5NEFmtyC3d+m4UJCa3IL06TLz/wS1c5/l0L3RMnU3JndX45IPtcw+6CYf1nUla3dXcureoDh3b1CLIOtae11nlBC29PZclYm23P8lnhtLN+mLF2Tm1Lz/487GFOluTNHu6/5iFuvaQnJ3W0jp3B6k/8KvobuvFp1Y11frylK+lvWP8dv+6Xj58iA4hFGyG+j+Ge+fPP59N8j0XLIb1EKykC0UC9UCjVNM11mi6aFkjHGqhDEyoiDq9Kg3xoSYEcfpZNJXS8Iyikgp3rOJbGtFpBWRV0RiMVsOsVgOsdqaHBAJMdqazLYmiyGrhWQh39dkYDI4JSASYrQ1hW1NAacoYkIEp4BTjFONU41TjVPBqW4/OBWcCk4Fp4IzgTOBM4EzgTMZZzLOZJzJOBM4EzgzODM4MzgzODM4MzgzODM4MzizcRbjLMZZjLOAs4CzgLOAs4CzgLOAs4KzgrOCs4KzGmc1zmqc1Tirl+1ct8EH5AOgUgArBS/eoD5IPvD6DV7AwYiJ0FREiAZNBGoi8YH6IPkgezcBnQjsFIMPyAfApwh+imYARUVMiOYBRZhA0V1gd4HdBXYX2F1gd4HdBXYX2F1gd4HhgsAFgQsCF8RdEHdB3AVxF8RdEHdB3AV1F9RdUHdB3YWpfSROA51ez0yDcWadbsB/7y/H/ePpgLdgL7fz06eXYtc/b37EX5u9XV6fDs+3y2HaN+/Hxp30Hw==","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"56":{"source":"use poseidon::poseidon2;\nuse crate::{InputNote, Note};\n\npub fn check_commitment(note: Note, commitment: Field) {\n assert(get_note_commitment(note) == commitment, \"Note commitment is not valid\");\n}\n\npub fn get_note_commitment(note: Note) -> Field {\n if (note.kind == 0) {\n assert(note.value == 0, \"Padding notes must be zero value\");\n 0\n } else {\n poseidon2::Poseidon2::hash(\n [0x2, note.kind, note.value, note.address, note.psi, 0, 0],\n 7,\n )\n }\n}\n\npub fn get_address(secret_key: Field) -> Field {\n poseidon2::Poseidon2::hash([secret_key, 0], 2)\n}\n\npub fn check_input_note_ownership(input_note: InputNote) {\n if (input_note.note.value != 0) {\n assert(\n get_address(input_note.secret_key) == input_note.note.address,\n \"Input note is not owned by the owner\",\n );\n }\n}\n\npub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) {\n let mut first_non_zero_kind = 0;\n let mut is_multiple_kinds = false;\n\n for i in 0..4 {\n if !is_multiple_kinds {\n if notes[i].kind != 0 {\n if first_non_zero_kind == 0 {\n first_non_zero_kind = notes[i].kind;\n } else if first_non_zero_kind != notes[i].kind {\n is_multiple_kinds = true;\n }\n }\n }\n }\n\n (is_multiple_kinds, first_non_zero_kind)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/note.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"70":{"source":"use common::{check_commitment, check_input_note_ownership, get_address, InputNote, Note};\nuse poseidon::poseidon2;\n\nfn main(\n notes: [Note; 10],\n secret_keys: [Field; 10],\n address: Field,\n timestamp: pub Field,\n value: pub Field,\n hash: pub Field,\n commitments: pub [Field; 10],\n) {\n let mut notes_value = 0;\n\n for i in 0..10 {\n let note = notes[i];\n let secret_key = secret_keys[i];\n let commitment = commitments[i];\n\n check_commitment(note, commitment);\n check_input_note_ownership(InputNote { note, secret_key });\n\n notes_value += note.value;\n }\n\n assert(value == notes_value, \"Invalid value\");\n assert(poseidon2::Poseidon2::hash([timestamp, address], 2) == hash);\n}\n\n#[test]\nfn test_main() {\n let pk = 101;\n let address = get_address(pk);\n\n // Create 10 notes with the same address\n let mut notes: [Note; 10] = [\n Note { kind: 0, value: 0, address: 0, psi: 0 },\n Note { kind: 1, value: 20, address: address, psi: 2 },\n Note { kind: 1, value: 30, address: address, psi: 3 },\n Note { kind: 1, value: 40, address: address, psi: 4 },\n Note { kind: 1, value: 50, address: address, psi: 5 },\n Note { kind: 1, value: 60, address: address, psi: 6 },\n Note { kind: 1, value: 70, address: address, psi: 7 },\n Note { kind: 1, value: 80, address: address, psi: 8 },\n Note { kind: 1, value: 90, address: address, psi: 9 },\n Note { kind: 1, value: 100, address: address, psi: 10 },\n ];\n\n // Calculate the total value of all notes\n let total_value = 540;\n\n // Create an array of secret keys (all the same in this test)\n let mut secret_keys = [pk; 10];\n secret_keys[0] = 0;\n\n // Calculate commitments for each note\n let mut commitments: [Field; 10] = [0; 10];\n for i in 0..10 {\n commitments[i] = common::get_note_commitment(notes[i]);\n }\n\n // Create timestamp and calculate hash\n let timestamp = 10000000;\n let message_hash = poseidon2::Poseidon2::hash([timestamp, address], 2);\n\n main(\n notes,\n secret_keys,\n address,\n timestamp,\n total_value,\n message_hash,\n commitments,\n )\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/points/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/signature/key b/fixtures/circuits/signature/key new file mode 100644 index 0000000..01ec57a Binary files /dev/null and b/fixtures/circuits/signature/key differ diff --git a/fixtures/circuits/signature/key_fields.json b/fixtures/circuits/signature/key_fields.json new file mode 100644 index 0000000..26d4533 --- /dev/null +++ b/fixtures/circuits/signature/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000008", + "0x0000000000000000000000000000000000000000000000000000000000000012", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000650a3025fb8056535c0dced5479ded08a5", + "0x00000000000000000000000000000000002df96e2aafb210ad9d884a84c99305", + "0x000000000000000000000000000000cb1f4b21eba6183d0caced18bb789846ae", + "0x000000000000000000000000000000000001d4086163e72b51ad764bd7eb031e", + "0x000000000000000000000000000000ecae924fa4dbabab82847fc19d567dc356", + "0x0000000000000000000000000000000000100d2344e3624cc251f9528270641a", + "0x00000000000000000000000000000041a8918e1f5f0d92133a93be56490b49ac", + "0x000000000000000000000000000000000016f76bb0ae4acdc8191d0e3eabc8a1", + "0x0000000000000000000000000000003272d61071e72441c3534ce85876badb74", + "0x000000000000000000000000000000000001eae70a641982d1e583991559735e", + "0x000000000000000000000000000000a239fff8ff2976b1c4556cdd0cab7900c4", + "0x000000000000000000000000000000000000ea729e19f0ec9dfb21578cd612cc", + "0x00000000000000000000000000000052834b77c845bc314d779c83511a74a9b6", + "0x00000000000000000000000000000000001c4259d462c486ade614769e5d1b68", + "0x000000000000000000000000000000ac4b0016cc5a38464c8eb35852d731bd70", + "0x00000000000000000000000000000000001bcccd7d03f6caf07ac0d99818660b", + "0x000000000000000000000000000000f2d0b779da92cd13369bfae90ed78e8e2f", + "0x000000000000000000000000000000000029e2c7a4d678649bdaccd5344315e4", + "0x0000000000000000000000000000003f7e702958a5c6feaff7c019b50b2e8f84", + "0x0000000000000000000000000000000000114757a8c2fed9ea449a6af6b563d1", + "0x0000000000000000000000000000005a1dd0a1b1f1e1a74a59409333a04ae8a8", + "0x00000000000000000000000000000000001d578d90680223832dbbc88ef8d963", + "0x000000000000000000000000000000a6301fb19760722a3c52d556fc1b45f4e9", + "0x0000000000000000000000000000000000163afe0aa38164ebd81723b3926d53", + "0x0000000000000000000000000000009abaf87e068b8e00ba462e190ff4dc0ff9", + "0x00000000000000000000000000000000001ad0852ae1f831506b33a76a496884", + "0x0000000000000000000000000000003ee69c0cb7b1ca634b32395b5349605a93", + "0x00000000000000000000000000000000002b782e70b28e331338317e348ecb3d", + "0x000000000000000000000000000000097dddaf96bb7474ec62410a1b6e0553e9", + "0x00000000000000000000000000000000001376d331f5ea329505df0eb814ad3c", + "0x0000000000000000000000000000008993e1f2dfc00ba3934d95b502e6df9091", + "0x00000000000000000000000000000000001a87ce604ce8d06d01db1b912cc3a6", + "0x000000000000000000000000000000bf5404f10180399fa397fb57af91fa7344", + "0x000000000000000000000000000000000012c200d39390298edf6eb1aab8e523", + "0x000000000000000000000000000000776a33d073a7e28ace373546782cea1cf5", + "0x00000000000000000000000000000000001f6c4463ef1ed1f47f2bacab026ddb", + "0x000000000000000000000000000000577a1627e60da9ff8bd85ab3f657523b1e", + "0x00000000000000000000000000000000002f9a7ffd477b4c93aa4d2517fb948d", + "0x000000000000000000000000000000a7ac6dac308f6fdf3ddff1af9e7732b71c", + "0x000000000000000000000000000000000004aa96d8d949c7e69ef9891928e202", + "0x0000000000000000000000000000009b624fa65d1a24b7f14a8f25f3789622af", + "0x000000000000000000000000000000000013d47bff8c630e847b70e2732fd3f0", + "0x00000000000000000000000000000061d21663e93132f32921075f4c936a84df", + "0x00000000000000000000000000000000001a74ca4e118fb480b9b999902989a3", + "0x000000000000000000000000000000d5ca60cfb8ea743d2399d4921cbaf6be88", + "0x00000000000000000000000000000000000c3d7ecface5a1c775e7c0aac5827e", + "0x000000000000000000000000000000cc4b20c1aac4c922dde28711401174d7aa", + "0x00000000000000000000000000000000001dd7b73d84b8793468fb7c25e20de7", + "0x0000000000000000000000000000002dfb7b457f16a132e3ac2020115a01c6b5", + "0x0000000000000000000000000000000000054817b213683ec9931ba9080ab0c4", + "0x000000000000000000000000000000a84ae16181e7afdf3ce478448c35cbf75d", + "0x000000000000000000000000000000000014348935c38e18a60f33108cc7ab07", + "0x0000000000000000000000000000000cce04114270c637ae959b6f811ea7f9e4", + "0x000000000000000000000000000000000022c1c0b9c88110763f20d9902b26d7", + "0x0000000000000000000000000000000b0da6af8b080a3e1c35ff2d303cda3ca3", + "0x00000000000000000000000000000000000ef862371c7ba0e7e1f7ebbff74fd6", + "0x000000000000000000000000000000b19db8795c3b3a5aaf624494f8377e9f3f", + "0x00000000000000000000000000000000002e26cba33be690963a4567c84c7a30", + "0x00000000000000000000000000000070e2adf14ec3d9cebdffd408c8f0739fd3", + "0x0000000000000000000000000000000000017ae6550a857642a42ba07c5287a0", + "0x000000000000000000000000000000377b6f304e3894eab215945d87e2ece38a", + "0x00000000000000000000000000000000002142ed5032ae7f6c0b8584292b710c", + "0x0000000000000000000000000000005968f5fe909be6ad7474beac66d94840b4", + "0x00000000000000000000000000000000001037e559ba38c2eb3401de507ded21", + "0x0000000000000000000000000000002b2fd13cb141bcb0c9ff029301d7dd7409", + "0x000000000000000000000000000000000024ad3c45d790134f8f19062c15865b", + "0x000000000000000000000000000000af09373abeb3a9ba5bcc7972865cfeca6e", + "0x00000000000000000000000000000000000e7ebf331939b76474c4c24c1743b7", + "0x0000000000000000000000000000001d6d061361b127c56c2862fea24c4ff2d7", + "0x0000000000000000000000000000000000298d74ce2545ea508ecc4968e3af17", + "0x0000000000000000000000000000009ea32b34738823123815c283b7f49f11fe", + "0x0000000000000000000000000000000000160ae9b0ecc1b064148d7f59627ac7", + "0x00000000000000000000000000000072703cab7ce97903eed2b105db3214ede2", + "0x000000000000000000000000000000000007e7744dd88ee5d0724931e4726d10", + "0x0000000000000000000000000000008c4af031c6274d48355d2291d0116f3f8c", + "0x00000000000000000000000000000000000ae622ed3df56f1f51cdf42b4b5f2d", + "0x0000000000000000000000000000001cfe577f378bcb5de13eb71d3cc412567b", + "0x000000000000000000000000000000000027903f3cbe3aff6073322ca392932a", + "0x000000000000000000000000000000900ef9ec6abe4fbab0bdbe47de34707777", + "0x00000000000000000000000000000000001326ee8585495071089b9faa6920e1", + "0x0000000000000000000000000000008194cae8bde7a3ac594b8f30b974b6b6b4", + "0x000000000000000000000000000000000005a01f035fd20b7fc29ed1d5acbf0a", + "0x0000000000000000000000000000000650a6278cb0b8313dba4e16d5a493dde1", + "0x0000000000000000000000000000000000259268ace44970298ca894f2c37e9e", + "0x000000000000000000000000000000fff8db6901972bd276a0317a59b389ba6e", + "0x0000000000000000000000000000000000026ede386b6b0ebbdd79c1addc6f5c", + "0x0000000000000000000000000000007bbc301c28fdb906fa78fdd160c4d4522b", + "0x00000000000000000000000000000000002531b362a6e2e68bf47bfc9ee17f6e", + "0x000000000000000000000000000000e57533edc6143896fa1968fa0c6272897d", + "0x0000000000000000000000000000000000089f5ce8686f0845e1ec05b6f39418", + "0x000000000000000000000000000000dfc4222953b1f30cffd52aa0bb80a72ef1", + "0x00000000000000000000000000000000002ad42e3bd60c95aa37746e3a4d2282", + "0x00000000000000000000000000000046a573ded81dc131335acf2156ad191e3d", + "0x000000000000000000000000000000000019966ae74c271049f1b736f531c33d", + "0x0000000000000000000000000000008f654e1708eb68b58dffd23da40911cba6", + "0x00000000000000000000000000000000001f683771fa8dbe01394f3b5e6248d4", + "0x000000000000000000000000000000fecf8abfb0a0db0e85ee049a91dbda058f", + "0x00000000000000000000000000000000002c68fa6274457a9e4cd0cbc2ff5185", + "0x0000000000000000000000000000008d5f1ce5951649af44e0771b9a4cec19d9", + "0x0000000000000000000000000000000000163b20fc0591691d81ac665ab58d95", + "0x000000000000000000000000000000f67aa525fa3703e996bacb50f71df2b847", + "0x000000000000000000000000000000000008bbb2006058a97ecedcef1c44ad8f", + "0x0000000000000000000000000000006009e73e99c91936daa734a838fa72e987", + "0x0000000000000000000000000000000000029b1e53dbf2ef50bc0d7f156950de", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000000000d32fedf0e4e31a4fe0ef03482a585397c7", + "0x00000000000000000000000000000000002c0ed5761beadf26fc22bdc74528de", + "0x000000000000000000000000000000e288f1062cc00f0576863c7d009042f4f2", + "0x00000000000000000000000000000000001ea71e531e990a18e2f6b57391649a" +] diff --git a/fixtures/circuits/signature/program.json b/fixtures/circuits/signature/program.json new file mode 100644 index 0000000..358f6c0 --- /dev/null +++ b/fixtures/circuits/signature/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"4401995400959538683","abi":{"parameters":[{"name":"owner_pk","type":{"kind":"field"},"visibility":"private"},{"name":"message_hash","type":{"kind":"field"},"visibility":"private"},{"name":"address","type":{"kind":"field"},"visibility":"public"},{"name":"message","type":{"kind":"field"},"visibility":"public"}],"return_type":null,"error_types":{"13979292482296039613":{"error_kind":"string","string":"Address is not owned by the owner"},"15633849116720109633":{"error_kind":"string","string":"Message hash is invalid"}}},"bytecode":"H4sIAAAAAAAA/6VRsQrCMBC9pE3VanfHjHVT/AIRoZM4ujgILoKKdNOts5MIzuJHiA4ufoVrN8cuOhvxpKGSNqUPjgfHy7u8OwJfmMjz8XThCLbgHwSZIzcnfT9sHRrnQe8UBMOR2354q8ty2w2fuwg9OeRH3jkMMudQ2bsGcV4isZlgJuk++yiJKouqKMy55n8paO+FWPra1GwGqLPZoqr41oFi2QjoZ7P1tfEBcQaV+oZC9+tfvc3an8FN9mPInbp7jPavOyTwBtzjT8UYAwAA","debug_symbols":"tVXLroIwEP2Xrll0+oL6Kzc3pmI1JA2QCiY3xn+/rVKQxTRG4mqgwzltz5xhbuRoD+N537Sn7kJ2Pzdy8I1zzXnvutoMTdeG1du9IOl1P3hrwxJ5yQdUb7xtB7JrR+cKcjVufHx06U37iIPxIUsLYttjiIHw1Dgbn+7FgqY4FBSfwFCJGa70Cg84Xiox4RUs20u1wjMczyWb8ALUsr9Y4TmOZ6zSEwHjlGEMIqMAp4kBOKswBokzaCEnAi1RfE4DXc0ayE80KEElDUpOMYYqo0FZzjYoNaqizjBQlgoJVKG3gIwVhVCQdBB6ERL029fQSyk1Q6+RawddJiUZYO2QwTOdepELiraT2NgPIDc3RHQMKgKouZZQyY9O8Z4lYbsnQW9sTNjuagabXQ1ftTWXSUpeqZUtf8ObqRu/mkuExsoXBJ6BPQOPP8iCiOixgsgQ4sC4Gt+Yg7PTPDuNbf0y3oa/PmXSAOx9V9vj6G3c8pELh/gH","file_map":{"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"56":{"source":"use poseidon::poseidon2;\nuse crate::{InputNote, Note};\n\npub fn check_commitment(note: Note, commitment: Field) {\n assert(get_note_commitment(note) == commitment, \"Note commitment is not valid\");\n}\n\npub fn get_note_commitment(note: Note) -> Field {\n if (note.kind == 0) {\n assert(note.value == 0, \"Padding notes must be zero value\");\n 0\n } else {\n poseidon2::Poseidon2::hash(\n [0x2, note.kind, note.value, note.address, note.psi, 0, 0],\n 7,\n )\n }\n}\n\npub fn get_address(secret_key: Field) -> Field {\n poseidon2::Poseidon2::hash([secret_key, 0], 2)\n}\n\npub fn check_input_note_ownership(input_note: InputNote) {\n if (input_note.note.value != 0) {\n assert(\n get_address(input_note.secret_key) == input_note.note.address,\n \"Input note is not owned by the owner\",\n );\n }\n}\n\npub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) {\n let mut first_non_zero_kind = 0;\n let mut is_multiple_kinds = false;\n\n for i in 0..4 {\n if !is_multiple_kinds {\n if notes[i].kind != 0 {\n if first_non_zero_kind == 0 {\n first_non_zero_kind = notes[i].kind;\n } else if first_non_zero_kind != notes[i].kind {\n is_multiple_kinds = true;\n }\n }\n }\n }\n\n (is_multiple_kinds, first_non_zero_kind)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/note.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"69":{"source":"use common::get_address;\nuse poseidon::poseidon2;\n\nfn main(owner_pk: Field, message_hash: Field, address: pub Field, message: pub Field) {\n let owner_address = get_address(owner_pk);\n assert(owner_address == address, \"Address is not owned by the owner\");\n\n let calc_message_hash = poseidon2::Poseidon2::hash([owner_pk, message], 2);\n assert(calc_message_hash == message_hash, \"Message hash is invalid\");\n}\n\n#[test]\nfn test_main() {\n let pk = 101;\n let address = get_address(pk);\n let message = 1000;\n let message_hash = poseidon2::Poseidon2::hash([pk, message], 2);\n\n println(message_hash);\n println(address);\n\n main(pk, message_hash, address, message)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/signature/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/transfer/key b/fixtures/circuits/transfer/key new file mode 100644 index 0000000..c8aca1e Binary files /dev/null and b/fixtures/circuits/transfer/key differ diff --git a/fixtures/circuits/transfer/key_fields.json b/fixtures/circuits/transfer/key_fields.json new file mode 100644 index 0000000..bebc8ab --- /dev/null +++ b/fixtures/circuits/transfer/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x0000000000000000000000000000000000000000000000000000000000000010", + "0x0000000000000000000000000000000000000000000000000000000000000015", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000ea437347c5cfc8628a95b6f5290aeece40", + "0x000000000000000000000000000000000021a0723a522e99bb8089513880f50f", + "0x00000000000000000000000000000056f7f8d93a5137a5cb9f9f7bac5780f4dd", + "0x000000000000000000000000000000000028b29c1c83a66e530c974e7ffe1e02", + "0x00000000000000000000000000000001580642029af30a52732aaa83dac950fc", + "0x0000000000000000000000000000000000175f04d3d8b52e528e239e5617c265", + "0x000000000000000000000000000000e7440fe3c4fe6a40380c35bc5ce65872ac", + "0x000000000000000000000000000000000009249f1cae1425a21686c5cc594326", + "0x00000000000000000000000000000010ac6d2e231227f2294f8eaba52ed05f34", + "0x00000000000000000000000000000000000a3f1e4795cfe42d11267052daa585", + "0x0000000000000000000000000000002b4e8fb39049146da59db89c9afdb76394", + "0x00000000000000000000000000000000002e1bbaec87633376cf5c7b3b853188", + "0x00000000000000000000000000000071f3f180ebc15ae78e1dc907ab051b46f9", + "0x0000000000000000000000000000000000077dd50473dbda2ad248a27b4ef1c8", + "0x000000000000000000000000000000888f6c9130bf89edf591b9105f77135ac8", + "0x00000000000000000000000000000000001c87bf0cd01a404fc60277bcaf7d71", + "0x000000000000000000000000000000a6b432fe0d156d851c053c2c005c2a7a94", + "0x000000000000000000000000000000000013c48fe8c0a03da12007a263882059", + "0x00000000000000000000000000000082b52782509ce6f1bbfc94bf2a0d2c9c38", + "0x00000000000000000000000000000000002efdeba016b8cf74c45104716cb327", + "0x000000000000000000000000000000e55407cf5d9aa59c4de03190cf119dcffc", + "0x0000000000000000000000000000000000136657d70d4c07f65d110882823ad6", + "0x0000000000000000000000000000006de60dd36ff02247bf6320e40905e8bb1a", + "0x00000000000000000000000000000000002e57defb276c19abb2d42665645dd0", + "0x000000000000000000000000000000b96c09c27ca328c08dd3e4d940d8184e58", + "0x000000000000000000000000000000000017901a5df32166594b3e7945c24ae9", + "0x000000000000000000000000000000da52e2b7832015c0a07d894e2367764803", + "0x00000000000000000000000000000000001a0871ddfc99e108eb0e1735956790", + "0x00000000000000000000000000000054757c86037441c6531b32dc4e845bbce0", + "0x00000000000000000000000000000000000e6163c0ce7bdf84131b7d96513169", + "0x00000000000000000000000000000020343125d6223573ed506c3b29e581b47b", + "0x00000000000000000000000000000000002e480542b9e8ea2a59b70de6ba2c2b", + "0x000000000000000000000000000000d4458ff2771320c29f571e609122ac5742", + "0x00000000000000000000000000000000001577b585a1f7c2c9cae3f5cddbf10b", + "0x000000000000000000000000000000ac6bd3b49a30a5948dfd2b7adc42663cb1", + "0x00000000000000000000000000000000000a7939acf513387aea7d376c718ac6", + "0x00000000000000000000000000000000b1831e4036dfabe10bda155e7e6cbff4", + "0x000000000000000000000000000000000012eb30588f1a892e3f43f3242c46aa", + "0x000000000000000000000000000000b14a5173906b8818e76a05f71ae9e38bea", + "0x00000000000000000000000000000000002c2a9488b378cd487e02bbd2b833f2", + "0x000000000000000000000000000000af088fc36bed2c6948286785cd406d0699", + "0x00000000000000000000000000000000001f4c4bac3f55b2e0be288de777635f", + "0x000000000000000000000000000000d7f70009952df36a2a8e637f44ad103ebe", + "0x000000000000000000000000000000000027d28a95e52e58f9ba709639365302", + "0x000000000000000000000000000000e6a6ff936365320050966b65694621dc80", + "0x00000000000000000000000000000000001a11417f8bc3382b116562a56bbc62", + "0x0000000000000000000000000000001cc63bbdecea0af8dab2c1b79050f57362", + "0x00000000000000000000000000000000000de5811d6a96bba0b9d23deefefa78", + "0x000000000000000000000000000000f0b94c715ac318eff4689ab0b2ff4c8c9a", + "0x0000000000000000000000000000000000235b18739aa43254011bbd7751d68f", + "0x000000000000000000000000000000bfb06c55ba9e01e8c78cc04cb833e013f8", + "0x000000000000000000000000000000000029c3a6c693e2aacc192af0930d0d8c", + "0x0000000000000000000000000000003b55fdc68c796ae59eaacb4a49f5c36170", + "0x00000000000000000000000000000000002f69cfbac280651a7ecc78418a430e", + "0x000000000000000000000000000000fd3ddf6776967c8cf8545236e777e77b1f", + "0x000000000000000000000000000000000017c623f19e2d738eeac3f2d7088dfb", + "0x000000000000000000000000000000af474ba0fb515a1c56dd71cbaec4bf1dac", + "0x0000000000000000000000000000000000230bbd54a223be6ec401d76bc019d0", + "0x000000000000000000000000000000af4a998d4fe1b44110f993e55b9c3d7932", + "0x00000000000000000000000000000000002edc38f46a50f5c0df818d67d7ef71", + "0x0000000000000000000000000000006da132ca5296640286798cc70e5acdd707", + "0x00000000000000000000000000000000000c1bac86dcd822f4d166788d648d41", + "0x000000000000000000000000000000523410181bd08e31b87105ad0e0faa530b", + "0x00000000000000000000000000000000001f5a3b0c606690343ec526490c7a8d", + "0x0000000000000000000000000000000ac547b0c6e69271446dfcb5d319fb74a0", + "0x00000000000000000000000000000000000e1942f1c5293c1db7165fd132e847", + "0x00000000000000000000000000000094551770f2041aea8e833ef4d1552b3ad7", + "0x0000000000000000000000000000000000275b60232d7d00bdd7020644a82f62", + "0x0000000000000000000000000000002135d7abf849ff31a539c2f8c99297051d", + "0x000000000000000000000000000000000026a60b43d3542bf05f425448ca9d79", + "0x000000000000000000000000000000c458db20f36d04504a14fd83866df5bd24", + "0x00000000000000000000000000000000000f314e883fe8ebdb11e32aa880f4c5", + "0x000000000000000000000000000000fb34f4c795a7fd666cf7ae9e1fdef6e8a3", + "0x000000000000000000000000000000000029af3c5aa1e6f14899315952e0cadd", + "0x000000000000000000000000000000ee9b42aeb6bf6de38d36a63266e44f9715", + "0x00000000000000000000000000000000001832868247aa6e2d107d4ee643e322", + "0x000000000000000000000000000000fc8ceee5b2d8f811c5b2ce1b242c2fdec1", + "0x00000000000000000000000000000000000b7a6f2d30ddf7cd67c8bdb6726258", + "0x000000000000000000000000000000b4066fb4ec6cd0550d1eec0fc77623c14d", + "0x0000000000000000000000000000000000000bfd5e3a1d976bf6573fd8274463", + "0x000000000000000000000000000000da80d6a4daa2bebe704316606a27f3c329", + "0x00000000000000000000000000000000000faf51e9e34a8be710120c4a3204c3", + "0x000000000000000000000000000000d635c8cf1e83ef6a547e0f0f10a60a5ee6", + "0x0000000000000000000000000000000000109207b1a6649ecff094b10bce52de", + "0x00000000000000000000000000000051a64b910b4bb907d68ed39a72f6e0fb31", + "0x000000000000000000000000000000000018c8f1cb34f90641bd417af0faf923", + "0x000000000000000000000000000000dc45db99561e9f40427754bab4140eb5b5", + "0x00000000000000000000000000000000000be718dee4e8b341d58a6115f54822", + "0x0000000000000000000000000000000b12a1013d0cc7fdc84baa557d5b1afa99", + "0x000000000000000000000000000000000010b46142e7f947b7a21fd32677fffb", + "0x000000000000000000000000000000062528dc18828ae67ad8e8cfda5c2da406", + "0x000000000000000000000000000000000011c4a4881584171cb0e76816f9c6da", + "0x00000000000000000000000000000003f1e3ae87df417a381658bcb601feabc9", + "0x0000000000000000000000000000000000268512ad9304329ec436e6c09ba709", + "0x000000000000000000000000000000ce3a681f73e68277ffe55186950f8cd19a", + "0x0000000000000000000000000000000000299218495f42c0ec475069b877610f", + "0x0000000000000000000000000000003143e8418f47623d334716174596841e78", + "0x00000000000000000000000000000000000ddc2edeb12b1c38ef84db69ad1e4a", + "0x00000000000000000000000000000025723c2e6c7a45d74664cc57a32d095834", + "0x0000000000000000000000000000000000234aee0751ea5760531c2ff50e1de4", + "0x000000000000000000000000000000faf00bf4c268d8a2737430b8a61f60b40b", + "0x00000000000000000000000000000000000fab145308f37f342d1b08e3689194", + "0x0000000000000000000000000000008141d1fe8648f2bba9042648a387fd002d", + "0x00000000000000000000000000000000002fd041b125adfad0f02c99b7e7c529", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000000000080d13b59c8b6f40cb35a0b76eea2545747", + "0x000000000000000000000000000000000002c026f82b8656de1f35fa09e1160c", + "0x000000000000000000000000000000d76bb69eee980bf6c3c4f81c4f1a2d231d", + "0x0000000000000000000000000000000000272ae9b36bb906a8b7475af0749fb0" +] diff --git a/fixtures/circuits/transfer/program.json b/fixtures/circuits/transfer/program.json new file mode 100644 index 0000000..6c242e4 --- /dev/null +++ b/fixtures/circuits/transfer/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"4642198149727677400","abi":{"parameters":[{"name":"utxo","type":{"kind":"struct","path":"common::utxo::Utxo","fields":[{"name":"input_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::InputNote","fields":[{"name":"note","type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"field"}}]}}},{"name":"output_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}}},{"name":"input_merkle_paths","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::MerklePath","fields":[{"name":"path","type":{"kind":"array","length":160,"type":{"kind":"field"}}}]}}}]},"visibility":"private"},{"name":"recent_root","type":{"kind":"field"},"visibility":"public"},{"name":"input_nullifiers","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"},{"name":"output_commitments","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"public"}],"return_type":null,"error_types":{"2532032818322018100":{"error_kind":"string","string":"Invalid nullifier 0"},"4703047920556725948":{"error_kind":"string","string":"Field failed to decompose into specified 254 limbs"},"6749186246397432903":{"error_kind":"string","string":"Invalid nullifier 1"},"7126743292872256338":{"error_kind":"string","string":"Padding notes must be zero value"},"7926997804325803954":{"error_kind":"string","string":"Input and output totals do not match"},"11305677572723109408":{"error_kind":"string","string":"Inconsistent kinds are not allowed"},"12272962467056991279":{"error_kind":"string","string":"Invalid output commitment 1"},"12382400539224138144":{"error_kind":"string","string":"Input note is not owned by the owner"},"12469291177396340830":{"error_kind":"string","string":"call to assert_max_bit_size"},"13108753448563390903":{"error_kind":"string","string":"Input commitment is not in recent root"},"14885583290507436593":{"error_kind":"string","string":"Invalid output commitment 0"}}},"bytecode":"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vgLRrv3LVzDatXd9haJde8VXONq1+3xFol07xFc02rWWr1h0a59YvuLRrX1s+UpEt/Yvy1cyurV3LV+p6NZesXylo1u7z/KViW7tEMtXNrq1kCXloln7G9SWj2btbaitEM3am1BbMZq1V6C2UjRrz0Bt5WjWroPaKtGs7Qq1b0Svdirkr69q9GqnYO2b0audhLXVolc7DmurR692ONbWiF5tD6ytGb3aOlhbK3q1SbG2drRqH+Lnm++taNU++K+2TrRq7/1X+3a0an/9r7ZutGqv/1f7TrRqz/9X+260ajf/V1svWrW9/qutH53aK//dP/jei07t5YjaBtGpvRRR2zA6tRcjahtFp/ZsRG3j6NTuj6htEp3aRRG1TaNT2yyitlk0astF3J/5mkejtqxd2yIataXt2pbRqC1u17aKRm1+u7Z1NGoz2rVtolEbate2DVw7+aBd2y4atfb9r6994NpJ/toOgWsn+Gs7Bq4d46/tFLh2qL+2c+Dabv7aLoFra/truwauTeyv7Rawtov/+cLXPWBt5//V9ghY2/F/tT0D1rb9X22vgLVN/1f7fsDaWv+r7R2wNs//avsEqt1293+1fQPW/u/5zdcvUO3WZ7X9A9VuflY7IFDt+me1AwPVrnxWOyhQ7exntYMD1fZ9VjskUG3RZ7VDA9T2efZ87BsWoLZ3pNrhAWp7RaodEaC2W6TakQFq20WqHRWgtn6k2g8C1BaNVDvau7byo0i1YwLURvr+wTfWu7ZS5Npx3rUVIteO964tE7l2gndtkci1E71rs0auneRdGydy7WTP2hvHItdO8a6N/P2Ob6pn7U/P1U7zrL32XO10z9orz9XO8Kz9+rnamZ61x56r/dCzdsVztbM8a9s+Vzvbqzbfc9+f+T7yqs37fO0cr9rcz9fO9arN/nztPK/ajM/XzveqTfp87QKP2iwPnq9d6FW78fnaRV61z38/6VvsUZs5Su3HHrWZotQu8ahNH6V2qUdtqii1yzxq40SpXe5e2/BmlNoVHrUrotSu9KiN8v2v7xP32gZRaz91r60ftXaVe23dqLWr3WurR61d415bMmrtWvfadFFr17nWvnspau1699pGUWs3uNa+80LtRtfat1+o3eRaW+uF2s2utVVeqN3iWlvkhdqtrrWpXqjd5lY75OsXare71tZ7oXaHW+3gF2t3utUOfLF2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","debug_symbols":"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uCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoBLAi4JuCTgkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoRLEi5JuCThkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoJLCi4puKTgkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puKThkoZLGi5puOTMn56LwSUNlzRc0nBJwyUNlzRc0nBJwyUNlzRc0nBJwyUNlzRc0nBJwyUNlzRc0nDJwCUDlwxcMnDJwCUDlwxcMnDJwCUDlwxcMnDJwCUDlwxcMnDJwCUDlwxcMnDJwCUDlwxcMnDJwCUDlwxcMnDJwCUDlwxcMnDJwCUDlwxcMnDJwCUD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4RKHS5x3HMdLHC/xTbdNN7jE4RLnHcfxEsdLnHcch0scLnG4xOESx0scL3HecZx3HOcdx3nHcbzkyr3Wo9yUn93qcdQPL6njUSblZ7c+V/jsVvMoR+XDS65yabGHl1zl1mIPL7nK0LoPL7nKYjG6PbzkXOzhJVe5tNjDS65ya7GHl1xlaLGHl1xlsVhTjhZ7eMlVLi328JKr3Frs4SVXGVrs4SVXWSzWlKPFHl5ylUuLPbzkKrcWG3QbdBt0G3R7eMlVSrcz93qV0u3MvV6ldDtzr1cp3c7c61UWizWldDtzr1cp3c7c61VKtzP3epXS7cy9XmWxWFNKtzP3epXS7cy9XqV0O3OvVyndztzrVRaLNaV0O3OvVyndztzrVUq3M/d6ldLtzL1eZbFYU6Kbo5ujm6Obo5ujm6Obo5ujm6Obo1ugW6BboFugW6BboFugW6BboFugW6JboluiW6JboluiW6JboluiW6JboVuhW6FboVuhW6FboVuhW6FboVujW6Nbo1ujW6Nbo1ujW6Nbo1uj26DboNug26DboNug26DboNug20i3M/d6ldLtzL1epXQ7c69XKd3O3OtVFos1pXQ7c69XKd3O3OtVSrcz93qV0u3MvV5lsVhTSrcz93qV0u3MvV6ldDtzr1cp3c7c61UWizWldDtzr1cp3c7c61VKtzP3epXS7cy9XmWxWFOim6Obo5ujm6Obo5ujm6Obo5ujm6NboFugW6BboBtcknBJwiUJl5y516tEN7gk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuSbgk4ZKESxIuKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouKbik4JKCSwouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouabik4ZKGSxouGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBSwYuGbhk4JKBS0Zc4oe4xA9xiR/iEj/EJX6IS/wQl/ghLvFDXOKHuMQPcYkf4hI/xCV+iEv8EJf4IS7xQ1zih7jED3GJH+ISP8QlfohL/BCX+CEu8UNc4oe4xA9xiR/iEj/EJX6IS/wQl/ghLvFDXOKHuMQPcYkf4hI/xCV+iEv8EJf4IS7xY6Obo5ujm6Obo5ujm6Obo5ujm6Obo1ugW6BboFugW6BboFugW6BboFugW6JboluiW6JboluiW6JboluiW6JboVuhW6FboVuhW6FboVuhW6FboVujW6Nbo1ujW6Nbo1ujW6Nbo1uj26DboNug26DboNug26DboNugm7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jEl7jE10Y3RzdHN0c3RzdHN0c3RzdHN0c3R7dAt0C3QLdAt0C3QLdAt0C3QLdAt0S3RLdEt0S3RLdEt0S3RLdEt0S3QrdCt0K3QrdCt0K3QrdCt0K3QrdGt0a3RrdGt0a3RrdGt0a3RrdGt0G3QbdBt0G3QbdBt0G3QbdBN7jE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbjE4BKDSwwuMbhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLNlyy4ZINl2y4ZMMlGy7ZcMmGSzZcsuGSDZdsuGTDJRsu2XDJhks2XLLhkg2XbLhkwyUbLtlwyYZLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuMThEodLHC5xuITcq5N7dXKvTu7VHS4h9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXp3cq5N7dXKvTu7Vyb06uVcn9+rkXv3MvXY9Sqf87DbrUSZlUX50+/gx/FHOZ+mf5aeXfPzW/SgXpVF+dPv4TfpRfnT7+CH6UcZnuR9lUhZlU352s8eGPr3kLhflZzd7nM6nl9ylUwZlUhblo9vj+8aozEPfIRelUW5Kp2Rvyd7y0e1xDtmUo7IOfZ1alOyt2Fuxt2Jvxd6KvRV7K/bWB+WiZG/N3pq9NXtr9tbo1ujWo3LY27C3YW/D3oa9DXsb9jbs7dNLPv7Y8Pcff/j3P/768x//8Zef/u2Hf/iPj//4z3/785/++vNf/nz9x7/+r3+9/5t//PXnX375+V/+8K+//uVPP/3T33796Q+//OVPj//u7//z7/8b","file_map":{"18":{"source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [u1; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n","path":"std/field/mod.nr"},"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"55":{"source":"use poseidon::poseidon2;\nuse crate::MerklePath;\n\nimpl MerklePath {\n pub fn root_from_leaf(self, leaf: Field) -> Field {\n let bits: [u1; 254] = leaf.to_le_bits();\n let mut hash = leaf;\n for i in 0..160 {\n let sibling = self.path[i];\n if bits[i] == 0 {\n hash = poseidon2::Poseidon2::hash([hash, sibling], 2);\n } else {\n hash = poseidon2::Poseidon2::hash([sibling, hash], 2);\n }\n }\n\n hash\n }\n\n pub fn validate(self, leaf: Field, root: Field) -> bool {\n self.root_from_leaf(leaf) == root\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/merkle_path.nr"},"56":{"source":"use poseidon::poseidon2;\nuse crate::{InputNote, Note};\n\npub fn check_commitment(note: Note, commitment: Field) {\n assert(get_note_commitment(note) == commitment, \"Note commitment is not valid\");\n}\n\npub fn get_note_commitment(note: Note) -> Field {\n if (note.kind == 0) {\n assert(note.value == 0, \"Padding notes must be zero value\");\n 0\n } else {\n poseidon2::Poseidon2::hash(\n [0x2, note.kind, note.value, note.address, note.psi, 0, 0],\n 7,\n )\n }\n}\n\npub fn get_address(secret_key: Field) -> Field {\n poseidon2::Poseidon2::hash([secret_key, 0], 2)\n}\n\npub fn check_input_note_ownership(input_note: InputNote) {\n if (input_note.note.value != 0) {\n assert(\n get_address(input_note.secret_key) == input_note.note.address,\n \"Input note is not owned by the owner\",\n );\n }\n}\n\npub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) {\n let mut first_non_zero_kind = 0;\n let mut is_multiple_kinds = false;\n\n for i in 0..4 {\n if !is_multiple_kinds {\n if notes[i].kind != 0 {\n if first_non_zero_kind == 0 {\n first_non_zero_kind = notes[i].kind;\n } else if first_non_zero_kind != notes[i].kind {\n is_multiple_kinds = true;\n }\n }\n }\n }\n\n (is_multiple_kinds, first_non_zero_kind)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/note.nr"},"57":{"source":"use poseidon::poseidon2;\nuse crate::note::{check_input_note_ownership, get_note_commitment, is_multiple_kinds};\nuse crate::{InputNote, MerklePath, Note};\n\npub struct Utxo {\n pub input_notes: [InputNote; 2],\n pub output_notes: [Note; 2],\n pub input_merkle_paths: [MerklePath; 2],\n}\n\nimpl Utxo {\n pub fn validate(\n self,\n recent_root: Field,\n input_nullifiers: [Field; 2],\n output_commitments: [Field; 2],\n ) {\n let input_commitments = [\n get_note_commitment(self.input_notes[0].note),\n get_note_commitment(self.input_notes[1].note),\n ];\n let computed_output_commitments = [\n get_note_commitment(self.output_notes[0]),\n get_note_commitment(self.output_notes[1]),\n ];\n\n assert(output_commitments[0] == computed_output_commitments[0], \"Invalid output commitment 0\");\n assert(output_commitments[1] == computed_output_commitments[1], \"Invalid output commitment 1\");\n\n assert(\n input_nullifiers[0] == expected_nullifier(self.input_notes[0].note, input_commitments[0]),\n \"Invalid nullifier 0\",\n );\n assert(\n input_nullifiers[1] == expected_nullifier(self.input_notes[1].note, input_commitments[1]),\n \"Invalid nullifier 1\",\n );\n\n self.output_notes[0].value.assert_max_bit_size::<240>();\n self.output_notes[1].value.assert_max_bit_size::<240>();\n\n verify_input_membership(input_commitments[0], self.input_merkle_paths[0], recent_root);\n verify_input_membership(input_commitments[1], self.input_merkle_paths[1], recent_root);\n\n check_input_note_ownership(self.input_notes[0]);\n check_input_note_ownership(self.input_notes[1]);\n\n let (is_multiple_kinds, _) = is_multiple_kinds([\n self.input_notes[0].note,\n self.input_notes[1].note,\n self.output_notes[0],\n self.output_notes[1],\n ]);\n assert(!is_multiple_kinds, \"Inconsistent kinds are not allowed\");\n }\n}\n\nfn expected_nullifier(note: Note, commitment: Field) -> Field {\n if commitment == 0 { 0 } else { poseidon2::Poseidon2::hash([commitment, note.psi], 2) }\n}\n\nfn verify_input_membership(commitment: Field, merkle_path: MerklePath, recent_root: Field) {\n if commitment != 0 {\n assert(merkle_path.validate(commitment, recent_root), \"Input commitment is not in recent root\");\n }\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/utxo.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"},"96":{"source":"use common::{get_note_commitment, InputNote, MerklePath, Note, Utxo};\nuse poseidon::poseidon2;\n\nfn main(\n utxo: Utxo,\n recent_root: pub Field,\n input_nullifiers: pub [Field; 2],\n output_commitments: pub [Field; 2],\n) {\n let input_value = utxo.input_notes[0].note.value + utxo.input_notes[1].note.value;\n let output_value = utxo.output_notes[0].value + utxo.output_notes[1].value;\n assert(input_value == output_value, \"Input and output totals do not match\");\n\n utxo.validate(recent_root, input_nullifiers, output_commitments);\n}\n\n#[test]\nfn test_transfer_one_input_one_output() {\n let pk: Field = 101;\n let address = common::get_address(pk);\n\n let note_1 = Note { kind: 1, value: 10, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n let note_3 = Note { kind: 1, value: 10, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n\n let input_commitment_1 = get_note_commitment(note_1);\n let output_commitment_1 = get_note_commitment(note_3);\n let output_commitment_2 = get_note_commitment(note_4);\n\n let input_path_1 = MerklePath { path: [0; 160] };\n let input_path_2 = MerklePath { path: [0; 160] };\n let recent_root = input_path_1.root_from_leaf(input_commitment_1);\n let utxo = Utxo {\n input_notes: [input_note_1, input_note_2],\n output_notes: [note_3, note_4],\n input_merkle_paths: [input_path_1, input_path_2],\n };\n\n main(\n utxo,\n recent_root,\n [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0],\n [output_commitment_1, output_commitment_2],\n );\n}\n\n#[test(should_fail)]\nfn test_transfer_rejects_bad_recent_root() {\n let pk: Field = 101;\n let address = common::get_address(pk);\n\n let note_1 = Note { kind: 1, value: 10, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n let note_3 = Note { kind: 1, value: 10, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n\n let input_commitment_1 = get_note_commitment(note_1);\n let output_commitment_1 = get_note_commitment(note_3);\n let output_commitment_2 = get_note_commitment(note_4);\n\n let input_path_1 = MerklePath { path: [0; 160] };\n let input_path_2 = MerklePath { path: [0; 160] };\n let recent_root = input_path_1.root_from_leaf(input_commitment_1) + 1;\n let utxo = Utxo {\n input_notes: [input_note_1, input_note_2],\n output_notes: [note_3, note_4],\n input_merkle_paths: [input_path_1, input_path_2],\n };\n\n main(\n utxo,\n recent_root,\n [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0],\n [output_commitment_1, output_commitment_2],\n );\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/evm/transfer/src/main.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/circuits/utxo/key b/fixtures/circuits/utxo/key new file mode 100644 index 0000000..d43fcc1 Binary files /dev/null and b/fixtures/circuits/utxo/key differ diff --git a/fixtures/circuits/utxo/key_fields.json b/fixtures/circuits/utxo/key_fields.json new file mode 100644 index 0000000..c0d9ddc --- /dev/null +++ b/fixtures/circuits/utxo/key_fields.json @@ -0,0 +1,117 @@ +[ + "0x000000000000000000000000000000000000000000000000000000000000000c", + "0x0000000000000000000000000000000000000000000000000000000000000019", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000005059451a7d5c66d11acc22de6d0f81fbb6", + "0x00000000000000000000000000000000002e42785e4f0be28acaf589ef080fb0", + "0x000000000000000000000000000000062f7fb812e0f48f317c3b4bb28c52e638", + "0x0000000000000000000000000000000000193ce4c973716b416c80481f7dc4c2", + "0x0000000000000000000000000000005e9bb1e207889bffe8261ac4d7581cc739", + "0x000000000000000000000000000000000021e775aa602783c85befcaa7788d86", + "0x0000000000000000000000000000006752198f21b4f0c1b9890cc1f470e02792", + "0x000000000000000000000000000000000010a628519c807ab578cf251f78300f", + "0x000000000000000000000000000000a5092d93340bd2ac0d79f2c94417c365d0", + "0x00000000000000000000000000000000000b715fcbd91f8b4a50032abcbccf21", + "0x000000000000000000000000000000f17714ad92e541ecdfd0643c4b22f4c507", + "0x000000000000000000000000000000000020e47fb0b7f35739cecb275b587ab6", + "0x00000000000000000000000000000086cb5708a66dc01ffb214e6784702101e6", + "0x000000000000000000000000000000000019362f9becc6e6379da9bc446a40eb", + "0x0000000000000000000000000000007d591f75822b9094303deab87629cd3b1e", + "0x0000000000000000000000000000000000197db0c01638134eedcbf4ce203957", + "0x0000000000000000000000000000008ab1e2c87c3ff09da60caa7a3012c53e74", + "0x00000000000000000000000000000000002e25f18881bf79f2023ca036b7de63", + "0x0000000000000000000000000000009ed10db610ebd2a285ca4f1306ee312341", + "0x00000000000000000000000000000000000d5ce1f60448e9e133996e1f4df2f1", + "0x0000000000000000000000000000002c4f7328ab9c00e0d0055d911d87a6ddd9", + "0x000000000000000000000000000000000004b1073ad13af2029249709dfa4966", + "0x0000000000000000000000000000002076a73a242c977b80432d89204bc84699", + "0x00000000000000000000000000000000000c3431501a898fb1243c5e3336de21", + "0x000000000000000000000000000000231b6e8223f1073f97628acac5e2e0b28b", + "0x00000000000000000000000000000000002e57b44b90da66faa200db697385d8", + "0x0000000000000000000000000000004d0a4090a5c806ffff96310036df7fde40", + "0x00000000000000000000000000000000001f9f2a5af3fb5b557da39bd9120c9a", + "0x0000000000000000000000000000004be1c2212648e3549feda918e93be42e7d", + "0x0000000000000000000000000000000000193849b89c533c4868561d9f167134", + "0x000000000000000000000000000000cb5ed4279b991cc87aa54741b954b6ab35", + "0x0000000000000000000000000000000000274b3174e9dc944137c162168a7fb0", + "0x000000000000000000000000000000c94e3190dde5d6c866d2d0c3a3cdf8813f", + "0x00000000000000000000000000000000000cdb8085f326013d20e1afa700772d", + "0x00000000000000000000000000000045512367e88835eceda2e9c2e717024ee9", + "0x00000000000000000000000000000000002da73a40e399ea214bf24b253464cf", + "0x000000000000000000000000000000a872b8cef0be4eed447eab653906f42805", + "0x000000000000000000000000000000000030061192d5e1d9ec872604469635d2", + "0x0000000000000000000000000000002a007607bd2c0746dd9789e7e02051873d", + "0x0000000000000000000000000000000000229af4ebe7b32c32877cb6f92a9fb7", + "0x000000000000000000000000000000ce5212306a32fa2ebe86d6e78dc734a3d2", + "0x0000000000000000000000000000000000097090786dafa1a5dc208f90879f4d", + "0x000000000000000000000000000000355e47579dd9a312fba231bc1cfebc7633", + "0x00000000000000000000000000000000001f2a9230333ee405d7c019df0922f1", + "0x0000000000000000000000000000000209dce35550710ff614b10aec482be07f", + "0x000000000000000000000000000000000014787bbc732c1f784abb14daf91090", + "0x00000000000000000000000000000099a52c7b349d497b54d76bbf5c1979274f", + "0x00000000000000000000000000000000001829cfdef31dac0cdbee852b460856", + "0x0000000000000000000000000000005e7e5b985eb47207abc2b897918ac817c6", + "0x0000000000000000000000000000000000278cd9d61ba3c3e0a65b5f573d183f", + "0x000000000000000000000000000000ee6c26e280b77bc8cdab041e6eb3d737c9", + "0x00000000000000000000000000000000001d0a8c47bffb25039a19296862e198", + "0x000000000000000000000000000000f670619c5ac0a225b31257f399b69b16ca", + "0x000000000000000000000000000000000023fd73ebf6d2786102f98448116c5b", + "0x0000000000000000000000000000008bff985bac5f9fab717fc865bfb7d5c9e5", + "0x000000000000000000000000000000000022f4bdafc091a944627cd204896608", + "0x000000000000000000000000000000b33374ddf0c9209161bed2c3ad12348550", + "0x00000000000000000000000000000000002398df501d0bb7b67daac44a51a73e", + "0x000000000000000000000000000000c3c6cf54f9600931c8e5ce247248b2b847", + "0x00000000000000000000000000000000002f98e518bdbcdbbce55c114acb96fb", + "0x000000000000000000000000000000f07ffa83ae416c8d8701d876805f5bf119", + "0x0000000000000000000000000000000000120ae4003d3b8a95c5f64a904e1dcb", + "0x000000000000000000000000000000f81df65fe37090f538be34dcbba09129e6", + "0x0000000000000000000000000000000000161ba986e7c67ae8b71ff7cac4a392", + "0x0000000000000000000000000000003f860367cbc8dc37acde428e06707ca4a3", + "0x00000000000000000000000000000000000ebf9efdb76fdf5b1e87d72b4d4fe3", + "0x000000000000000000000000000000adc3b107c547f83674eb25882eb6d735d2", + "0x0000000000000000000000000000000000062883c29c15b3a2bb8c68f5f1f354", + "0x0000000000000000000000000000008f236993d6968d46f1349d8de517204916", + "0x000000000000000000000000000000000016a7c195c5c437e0d664c9b5fdc14c", + "0x0000000000000000000000000000004990cb3fa6a1524b49c9c8364947e9e872", + "0x00000000000000000000000000000000000ba81e5706040c5da958b7773fedb0", + "0x00000000000000000000000000000080a0fa8695cd97ae31330d903ef8f03027", + "0x00000000000000000000000000000000000768044a2fc8f0eedfdddd7982455b", + "0x0000000000000000000000000000005be12754a6b0b0a7b18f70d1c5c1cdc585", + "0x000000000000000000000000000000000026c85eec66e0705a41849b2917709b", + "0x0000000000000000000000000000008415fff507e9380fc543b87b17d3e8c25a", + "0x00000000000000000000000000000000002ac65e1630eaaf835bb5288665ba5c", + "0x000000000000000000000000000000b0acf817d4262a820ce90b34c95fd78d52", + "0x0000000000000000000000000000000000258014420d8a9dd2fe65c2697a88ee", + "0x000000000000000000000000000000b9315f21504ec5dd95702c9d5a01ccfafc", + "0x000000000000000000000000000000000022cad8ee80f131df8ded1fa51108d2", + "0x000000000000000000000000000000770aa66895234283bbbcfaa53f4e1ae777", + "0x00000000000000000000000000000000001c072e44e3bc371e41aab853025bae", + "0x0000000000000000000000000000002527d9f89b692e5c9630be9e753504ae8f", + "0x00000000000000000000000000000000000cb6d2ab328a1099a5f1dd03b0a1db", + "0x0000000000000000000000000000005dfef7ced8ebbcbf6f6142e7c0d0cb1117", + "0x00000000000000000000000000000000002f5b71e756c8b2e7144b062b86e4a6", + "0x0000000000000000000000000000005883ab86e97482786e90275194bb8e80cd", + "0x00000000000000000000000000000000002a2151a981bb85afda957beeb8ee24", + "0x0000000000000000000000000000003c56f54404708eabe1bb6dabd7696203cb", + "0x00000000000000000000000000000000002b87f0bc586ed756610eca48de9d4d", + "0x000000000000000000000000000000a1d1d3280dd5b9c2700c56eb44684b83d2", + "0x00000000000000000000000000000000002fa75dcd73148b6cab95e82a24769c", + "0x000000000000000000000000000000cc2ccd40e9b1da53772dac5fcea42ef432", + "0x0000000000000000000000000000000000247273927cfad5b89f2f6ba25e364a", + "0x0000000000000000000000000000009c748d445232319f9f881e293a3670403e", + "0x00000000000000000000000000000000000dd736c04e5e2cbbbc0fb0d929f527", + "0x000000000000000000000000000000a5417eb612170baec5cd3adc2822903750", + "0x00000000000000000000000000000000001fa689f2550eb43257a026fdb66b7f", + "0x000000000000000000000000000000c06544875226c2ef12eb33610665b1c523", + "0x000000000000000000000000000000000011460f1cb9210508c275ec98009fac", + "0x0000000000000000000000000000002c35c7a07ca516ed60d7f02e52671a612e", + "0x0000000000000000000000000000000000021b2c1b6d951e023a6a8d2e9cbfc7", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000002", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000000000091bf2d311966e13423265736ce919b13eb", + "0x0000000000000000000000000000000000196696384a5f06ee7173acf7a697e8", + "0x00000000000000000000000000000045f2fb453e2cbde7c3763ba3a41d38c16f", + "0x0000000000000000000000000000000000103a777e3faace3c31cf1927576171" +] diff --git a/fixtures/circuits/utxo/program.json b/fixtures/circuits/utxo/program.json new file mode 100644 index 0000000..5393cac --- /dev/null +++ b/fixtures/circuits/utxo/program.json @@ -0,0 +1 @@ +{"noir_version":"1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051","hash":"14098514264111073913","abi":{"parameters":[{"name":"input_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::InputNote","fields":[{"name":"note","type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},{"name":"secret_key","type":{"kind":"field"}}]}},"visibility":"private"},{"name":"output_notes","type":{"kind":"array","length":2,"type":{"kind":"struct","path":"common::Note","fields":[{"name":"kind","type":{"kind":"field"}},{"name":"value","type":{"kind":"field"}},{"name":"address","type":{"kind":"field"}},{"name":"psi","type":{"kind":"field"}}]}},"visibility":"private"},{"name":"pmessage4","type":{"kind":"field"},"visibility":"private"},{"name":"commitments","type":{"kind":"array","length":4,"type":{"kind":"field"}},"visibility":"public"},{"name":"messages","type":{"kind":"array","length":5,"type":{"kind":"field"}},"visibility":"public"}],"return_type":null,"error_types":{"1434402537454335388":{"error_kind":"string","string":"Burn hash must match message"},"2212929835929732210":{"error_kind":"string","string":"Mint hash must match message"},"2402221729226865771":{"error_kind":"string","string":"messages[4] must match private input"},"2591464926340063308":{"error_kind":"string","string":"Burn output must match value message"},"3088914507699214238":{"error_kind":"string","string":"Invalid kind"},"7126743292872256338":{"error_kind":"string","string":"Padding notes must be zero value"},"7926997804325803954":{"error_kind":"string","string":"Input and output totals do not match"},"9333812033455989394":{"error_kind":"string","string":"Burn note kind must match message"},"10045219216956375247":{"error_kind":"string","string":"Mint output must match value message"},"10619113442490094159":{"error_kind":"string","string":"Mint note kind must match message"},"11305677572723109408":{"error_kind":"string","string":"Inconsistent kinds are not allowed"},"12382400539224138144":{"error_kind":"string","string":"Input note is not owned by the owner"},"12469291177396340830":{"error_kind":"string","string":"call to assert_max_bit_size"},"16398460003478624606":{"error_kind":"string","string":"Note commitment is not valid"}}},"bytecode":"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","debug_symbols":"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","file_map":{"18":{"source":"pub mod bn254;\nuse crate::{runtime::is_unconstrained, static_assert};\nuse bn254::lt as bn254_lt;\n\nimpl Field {\n /// Asserts that `self` can be represented in `bit_size` bits.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^{bit_size}`.\n // docs:start:assert_max_bit_size\n pub fn assert_max_bit_size(self) {\n // docs:end:assert_max_bit_size\n static_assert(\n BIT_SIZE < modulus_num_bits() as u32,\n \"BIT_SIZE must be less than modulus_num_bits\",\n );\n __assert_max_bit_size(self, BIT_SIZE);\n }\n\n /// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n /// This slice will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_le_bits\n pub fn to_le_bits(self: Self) -> [u1; N] {\n // docs:end:to_le_bits\n let bits = __to_le_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[N - 1 - i] != p[N - 1 - i]) {\n assert(p[N - 1 - i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n /// This array will be zero padded should not all bits be necessary to represent `self`.\n ///\n /// # Failures\n /// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n /// be able to represent the original `Field`.\n ///\n /// # Safety\n /// The bit decomposition returned is canonical and is guaranteed to not overflow the modulus.\n // docs:start:to_be_bits\n pub fn to_be_bits(self: Self) -> [u1; N] {\n // docs:end:to_be_bits\n let bits = __to_be_bits(self);\n\n if !is_unconstrained() {\n // Ensure that the decomposition does not overflow the modulus\n let p = modulus_be_bits();\n assert(bits.len() <= p.len());\n let mut ok = bits.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bits[i] != p[i]) {\n assert(p[i] == 1);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bits\n }\n\n /// Decomposes `self` into its little endian byte decomposition as a `[u8;N]` array\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_le_bytes\n pub fn to_le_bytes(self: Self) -> [u8; N] {\n // docs:end:to_le_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_le_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_le_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[N - 1 - i] != p[N - 1 - i]) {\n assert(bytes[N - 1 - i] < p[N - 1 - i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n /// Decomposes `self` into its big endian byte decomposition as a `[u8;N]` array of length required to represent the field modulus\n /// This array will be zero padded should not all bytes be necessary to represent `self`.\n ///\n /// # Failures\n /// The length N of the array must be big enough to contain all the bytes of the 'self',\n /// and no more than the number of bytes required to represent the field modulus\n ///\n /// # Safety\n /// The result is ensured to be the canonical decomposition of the field element\n // docs:start:to_be_bytes\n pub fn to_be_bytes(self: Self) -> [u8; N] {\n // docs:end:to_be_bytes\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n // Compute the byte decomposition\n let bytes = self.to_be_radix(256);\n\n if !is_unconstrained() {\n // Ensure that the byte decomposition does not overflow the modulus\n let p = modulus_be_bytes();\n assert(bytes.len() <= p.len());\n let mut ok = bytes.len() != p.len();\n for i in 0..N {\n if !ok {\n if (bytes[i] != p[i]) {\n assert(bytes[i] < p[i]);\n ok = true;\n }\n }\n }\n assert(ok);\n }\n bytes\n }\n\n fn to_le_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_le_radix(self, radix)\n }\n\n fn to_be_radix(self: Self, radix: u32) -> [u8; N] {\n // Brillig does not need an immediate radix\n if !crate::runtime::is_unconstrained() {\n static_assert(1 < radix, \"radix must be greater than 1\");\n static_assert(radix <= 256, \"radix must be less than or equal to 256\");\n static_assert(radix & (radix - 1) == 0, \"radix must be a power of 2\");\n }\n __to_be_radix(self, radix)\n }\n\n // Returns self to the power of the given exponent value.\n // Caution: we assume the exponent fits into 32 bits\n // using a bigger bit size impacts negatively the performance and should be done only if the exponent does not fit in 32 bits\n pub fn pow_32(self, exponent: Field) -> Field {\n let mut r: Field = 1;\n let b: [u1; 32] = exponent.to_le_bits();\n\n for i in 1..33 {\n r *= r;\n r = (b[32 - i] as Field) * (r * self) + (1 - b[32 - i] as Field) * r;\n }\n r\n }\n\n // Parity of (prime) Field element, i.e. sgn0(x mod p) = 0 if x `elem` {0, ..., p-1} is even, otherwise sgn0(x mod p) = 1.\n pub fn sgn0(self) -> u1 {\n self as u1\n }\n\n pub fn lt(self, another: Field) -> bool {\n if crate::compat::is_bn254() {\n bn254_lt(self, another)\n } else {\n lt_fallback(self, another)\n }\n }\n\n /// Convert a little endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_le_bytes(bytes: [u8; N]) -> Field {\n static_assert(\n N <= modulus_le_bytes().len(),\n \"N must be less than or equal to modulus_le_bytes().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[i] as Field) * v;\n v = v * 256;\n }\n result\n }\n\n /// Convert a big endian byte array to a field element.\n /// If the provided byte array overflows the field modulus then the Field will silently wrap around.\n pub fn from_be_bytes(bytes: [u8; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bytes[N - 1 - i] as Field) * v;\n v = v * 256;\n }\n result\n }\n}\n\n#[builtin(apply_range_constraint)]\nfn __assert_max_bit_size(value: Field, bit_size: u32) {}\n\n// `_radix` must be less than 256\n#[builtin(to_le_radix)]\nfn __to_le_radix(value: Field, radix: u32) -> [u8; N] {}\n\n// `_radix` must be less than 256\n#[builtin(to_be_radix)]\nfn __to_be_radix(value: Field, radix: u32) -> [u8; N] {}\n\n/// Decomposes `self` into its little endian bit decomposition as a `[u1; N]` array.\n/// This slice will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_le_bits)]\nfn __to_le_bits(value: Field) -> [u1; N] {}\n\n/// Decomposes `self` into its big endian bit decomposition as a `[u1; N]` array.\n/// This array will be zero padded should not all bits be necessary to represent `self`.\n///\n/// # Failures\n/// Causes a constraint failure for `Field` values exceeding `2^N` as the resulting slice will not\n/// be able to represent the original `Field`.\n///\n/// # Safety\n/// Values of `N` equal to or greater than the number of bits necessary to represent the `Field` modulus\n/// (e.g. 254 for the BN254 field) allow for multiple bit decompositions. This is due to how the `Field` will\n/// wrap around due to overflow when verifying the decomposition.\n#[builtin(to_be_bits)]\nfn __to_be_bits(value: Field) -> [u1; N] {}\n\n#[builtin(modulus_num_bits)]\npub comptime fn modulus_num_bits() -> u64 {}\n\n#[builtin(modulus_be_bits)]\npub comptime fn modulus_be_bits() -> [u1] {}\n\n#[builtin(modulus_le_bits)]\npub comptime fn modulus_le_bits() -> [u1] {}\n\n#[builtin(modulus_be_bytes)]\npub comptime fn modulus_be_bytes() -> [u8] {}\n\n#[builtin(modulus_le_bytes)]\npub comptime fn modulus_le_bytes() -> [u8] {}\n\n/// An unconstrained only built in to efficiently compare fields.\n#[builtin(field_less_than)]\nunconstrained fn __field_less_than(x: Field, y: Field) -> bool {}\n\npub(crate) unconstrained fn field_less_than(x: Field, y: Field) -> bool {\n __field_less_than(x, y)\n}\n\n// Convert a 32 byte array to a field element by modding\npub fn bytes32_to_field(bytes32: [u8; 32]) -> Field {\n // Convert it to a field element\n let mut v = 1;\n let mut high = 0 as Field;\n let mut low = 0 as Field;\n\n for i in 0..16 {\n high = high + (bytes32[15 - i] as Field) * v;\n low = low + (bytes32[16 + 15 - i] as Field) * v;\n v = v * 256;\n }\n // Abuse that a % p + b % p = (a + b) % p and that low < p\n low + high * v\n}\n\nfn lt_fallback(x: Field, y: Field) -> bool {\n if is_unconstrained() {\n // Safety: unconstrained context\n unsafe {\n field_less_than(x, y)\n }\n } else {\n let x_bytes: [u8; 32] = x.to_le_bytes();\n let y_bytes: [u8; 32] = y.to_le_bytes();\n let mut x_is_lt = false;\n let mut done = false;\n for i in 0..32 {\n if (!done) {\n let x_byte = x_bytes[32 - 1 - i] as u8;\n let y_byte = y_bytes[32 - 1 - i] as u8;\n let bytes_match = x_byte == y_byte;\n if !bytes_match {\n x_is_lt = x_byte < y_byte;\n done = true;\n }\n }\n }\n x_is_lt\n }\n}\n\nmod tests {\n use crate::{panic::panic, runtime, static_assert};\n use super::{\n field_less_than, modulus_be_bits, modulus_be_bytes, modulus_le_bits, modulus_le_bytes,\n };\n\n #[test]\n // docs:start:to_be_bits_example\n fn test_to_be_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_be_bits();\n assert_eq(bits, [0, 0, 0, 0, 0, 0, 1, 0]);\n }\n // docs:end:to_be_bits_example\n\n #[test]\n // docs:start:to_le_bits_example\n fn test_to_le_bits() {\n let field = 2;\n let bits: [u1; 8] = field.to_le_bits();\n assert_eq(bits, [0, 1, 0, 0, 0, 0, 0, 0]);\n }\n // docs:end:to_le_bits_example\n\n #[test]\n // docs:start:to_be_bytes_example\n fn test_to_be_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_be_bytes();\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 0, 2]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_bytes_example\n\n #[test]\n // docs:start:to_le_bytes_example\n fn test_to_le_bytes() {\n let field = 2;\n let bytes: [u8; 8] = field.to_le_bytes();\n assert_eq(bytes, [2, 0, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_bytes_example\n\n #[test]\n // docs:start:to_be_radix_example\n fn test_to_be_radix() {\n // 259, in base 256, big endian, is [1, 3].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_be_radix(256);\n assert_eq(bytes, [0, 0, 0, 0, 0, 0, 1, 3]);\n assert_eq(Field::from_be_bytes::<8>(bytes), field);\n }\n // docs:end:to_be_radix_example\n\n #[test]\n // docs:start:to_le_radix_example\n fn test_to_le_radix() {\n // 259, in base 256, little endian, is [3, 1].\n // i.e. 3 * 256^0 + 1 * 256^1\n let field = 259;\n\n // The radix (in this example, 256) must be a power of 2.\n // The length of the returned byte array can be specified to be\n // >= the amount of space needed.\n let bytes: [u8; 8] = field.to_le_radix(256);\n assert_eq(bytes, [3, 1, 0, 0, 0, 0, 0, 0]);\n assert_eq(Field::from_le_bytes::<8>(bytes), field);\n }\n // docs:end:to_le_radix_example\n\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n // Updated test to account for Brillig restriction that radix must be greater than 2\n #[test(should_fail_with = \"radix must be greater than 1\")]\n fn test_to_le_radix_brillig_1() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 1;\n let _: [u8; 8] = field.to_le_radix(1);\n } else {\n panic(f\"radix must be greater than 1\");\n }\n }\n\n #[test(should_fail_with = \"radix must be a power of 2\")]\n fn test_to_le_radix_3() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(3);\n } else {\n panic(f\"radix must be a power of 2\");\n }\n }\n\n #[test]\n fn test_to_le_radix_brillig_3() {\n // this test should only fail in constrained mode\n if runtime::is_unconstrained() {\n let field = 1;\n let out: [u8; 8] = field.to_le_radix(3);\n let mut expected = [0; 8];\n expected[0] = 1;\n assert(out == expected, \"unexpected result\");\n }\n }\n\n #[test(should_fail_with = \"radix must be less than or equal to 256\")]\n fn test_to_le_radix_512() {\n // this test should only fail in constrained mode\n if !runtime::is_unconstrained() {\n let field = 2;\n let _: [u8; 8] = field.to_le_radix(512);\n } else {\n panic(f\"radix must be less than or equal to 256\")\n }\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n unconstrained fn not_enough_limbs_brillig() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 16 limbs\")]\n fn not_enough_limbs() {\n let _: [u8; 16] = 0x100000000000000000000000000000000.to_le_bytes();\n }\n\n #[test]\n unconstrained fn test_field_less_than() {\n assert(field_less_than(0, 1));\n assert(field_less_than(0, 0x100));\n assert(field_less_than(0x100, 0 - 1));\n assert(!field_less_than(0 - 1, 0));\n }\n\n #[test]\n unconstrained fn test_large_field_values_unconstrained() {\n let large_field = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_field.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_field.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_field);\n\n let radix_bytes: [u8; 8] = large_field.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_field);\n }\n\n #[test]\n fn test_large_field_values() {\n let large_val = 0xffffffffffffffff;\n\n let bits: [u1; 64] = large_val.to_le_bits();\n assert_eq(bits[0], 1);\n\n let bytes: [u8; 8] = large_val.to_le_bytes();\n assert_eq(Field::from_le_bytes::<8>(bytes), large_val);\n\n let radix_bytes: [u8; 8] = large_val.to_le_radix(256);\n assert_eq(Field::from_le_bytes::<8>(radix_bytes), large_val);\n }\n\n #[test]\n fn test_decomposition_edge_cases() {\n let zero_bits: [u1; 8] = 0.to_le_bits();\n assert_eq(zero_bits, [0; 8]);\n\n let zero_bytes: [u8; 8] = 0.to_le_bytes();\n assert_eq(zero_bytes, [0; 8]);\n\n let one_bits: [u1; 8] = 1.to_le_bits();\n let expected: [u1; 8] = [1, 0, 0, 0, 0, 0, 0, 0];\n assert_eq(one_bits, expected);\n\n let pow2_bits: [u1; 8] = 4.to_le_bits();\n let expected: [u1; 8] = [0, 0, 1, 0, 0, 0, 0, 0];\n assert_eq(pow2_bits, expected);\n }\n\n #[test]\n fn test_pow_32() {\n assert_eq(2.pow_32(3), 8);\n assert_eq(3.pow_32(2), 9);\n assert_eq(5.pow_32(0), 1);\n assert_eq(7.pow_32(1), 7);\n\n assert_eq(2.pow_32(10), 1024);\n\n assert_eq(0.pow_32(5), 0);\n assert_eq(0.pow_32(0), 1);\n\n assert_eq(1.pow_32(100), 1);\n }\n\n #[test]\n fn test_sgn0() {\n assert_eq(0.sgn0(), 0);\n assert_eq(2.sgn0(), 0);\n assert_eq(4.sgn0(), 0);\n assert_eq(100.sgn0(), 0);\n\n assert_eq(1.sgn0(), 1);\n assert_eq(3.sgn0(), 1);\n assert_eq(5.sgn0(), 1);\n assert_eq(101.sgn0(), 1);\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 8 limbs\")]\n fn test_bit_decomposition_overflow() {\n // 8 bits can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u1; 8] = large_val.to_le_bits();\n }\n\n #[test(should_fail_with = \"Field failed to decompose into specified 4 limbs\")]\n fn test_byte_decomposition_overflow() {\n // 4 bytes can't represent large field values\n let large_val = 0x1000000000000000;\n let _: [u8; 4] = large_val.to_le_bytes();\n }\n\n #[test]\n fn test_to_from_be_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 BE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_minus_1_bytes[32 - 1] > 0);\n p_minus_1_bytes[32 - 1] -= 1;\n\n let p_minus_1 = Field::from_be_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_be_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 BE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_be_bytes().as_array();\n assert(p_plus_1_bytes[32 - 1] < 255);\n p_plus_1_bytes[32 - 1] += 1;\n\n let p_plus_1 = Field::from_be_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 BE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_be_bytes();\n assert_eq(p_plus_1_converted_bytes[32 - 1], 1);\n p_plus_1_converted_bytes[32 - 1] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_be_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_be_bytes().len(), 32);\n let p = Field::from_be_bytes::<32>(modulus_be_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 BE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_be_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n #[test]\n fn test_to_from_le_bytes_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this byte produces the expected 32 LE bytes for (modulus - 1)\n let mut p_minus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_minus_1_bytes[0] > 0);\n p_minus_1_bytes[0] -= 1;\n\n let p_minus_1 = Field::from_le_bytes::<32>(p_minus_1_bytes);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 32 BE bytes produces the same bytes\n let p_minus_1_converted_bytes: [u8; 32] = p_minus_1.to_le_bytes();\n assert_eq(p_minus_1_converted_bytes, p_minus_1_bytes);\n\n // checking that incrementing this byte produces 32 LE bytes for (modulus + 1)\n let mut p_plus_1_bytes: [u8; 32] = modulus_le_bytes().as_array();\n assert(p_plus_1_bytes[0] < 255);\n p_plus_1_bytes[0] += 1;\n\n let p_plus_1 = Field::from_le_bytes::<32>(p_plus_1_bytes);\n assert_eq(p_plus_1, 1);\n\n // checking that converting p_plus_1 to 32 LE bytes produces the same\n // byte set to 1 as p_plus_1_bytes and otherwise zeroes\n let mut p_plus_1_converted_bytes: [u8; 32] = p_plus_1.to_le_bytes();\n assert_eq(p_plus_1_converted_bytes[0], 1);\n p_plus_1_converted_bytes[0] = 0;\n assert_eq(p_plus_1_converted_bytes, [0; 32]);\n\n // checking that Field::from_le_bytes::<32> on the Field modulus produces 0\n assert_eq(modulus_le_bytes().len(), 32);\n let p = Field::from_le_bytes::<32>(modulus_le_bytes().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 32 LE bytes produces 32 zeroes\n let p_bytes: [u8; 32] = 0.to_le_bytes();\n assert_eq(p_bytes, [0; 32]);\n }\n }\n\n /// Convert a little endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_le_bits(bits: [u1; N]) -> Field {\n static_assert(\n N <= modulus_le_bits().len(),\n \"N must be less than or equal to modulus_le_bits().len()\",\n );\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n /// Convert a big endian bit array to a field element.\n /// If the provided bit array overflows the field modulus then the Field will silently wrap around.\n fn from_be_bits(bits: [u1; N]) -> Field {\n let mut v = 1;\n let mut result = 0;\n\n for i in 0..N {\n result += (bits[N - 1 - i] as Field) * v;\n v = v * 2;\n }\n result\n }\n\n #[test]\n fn test_to_from_be_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 BE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_minus_1_bits[254 - 1] > 0);\n p_minus_1_bits[254 - 1] -= 1;\n\n let p_minus_1 = from_be_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_be_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 BE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_be_bits().as_array();\n assert(p_plus_4_bits[254 - 3] < 1);\n p_plus_4_bits[254 - 3] += 1;\n\n let p_plus_4 = from_be_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 BE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_be_bits();\n assert_eq(p_plus_4_converted_bits[254 - 3], 1);\n p_plus_4_converted_bits[254 - 3] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_be_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_be_bits().len(), 254);\n let p = from_be_bits::<254>(modulus_be_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 BE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_be_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n\n #[test]\n fn test_to_from_le_bits_bn254_edge_cases() {\n if crate::compat::is_bn254() {\n // checking that decrementing this bit produces the expected 254 LE bits for (modulus - 1)\n let mut p_minus_1_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_minus_1_bits[0] > 0);\n p_minus_1_bits[0] -= 1;\n\n let p_minus_1 = from_le_bits::<254>(p_minus_1_bits);\n assert_eq(p_minus_1 + 1, 0);\n\n // checking that converting (modulus - 1) from and then to 254 BE bits produces the same bits\n let p_minus_1_converted_bits: [u1; 254] = p_minus_1.to_le_bits();\n assert_eq(p_minus_1_converted_bits, p_minus_1_bits);\n\n // checking that incrementing this bit produces 254 LE bits for (modulus + 4)\n let mut p_plus_4_bits: [u1; 254] = modulus_le_bits().as_array();\n assert(p_plus_4_bits[2] < 1);\n p_plus_4_bits[2] += 1;\n\n let p_plus_4 = from_le_bits::<254>(p_plus_4_bits);\n assert_eq(p_plus_4, 4);\n\n // checking that converting p_plus_4 to 254 LE bits produces the same\n // bit set to 1 as p_plus_4_bits and otherwise zeroes\n let mut p_plus_4_converted_bits: [u1; 254] = p_plus_4.to_le_bits();\n assert_eq(p_plus_4_converted_bits[2], 1);\n p_plus_4_converted_bits[2] = 0;\n assert_eq(p_plus_4_converted_bits, [0; 254]);\n\n // checking that Field::from_le_bits::<254> on the Field modulus produces 0\n assert_eq(modulus_le_bits().len(), 254);\n let p = from_le_bits::<254>(modulus_le_bits().as_array());\n assert_eq(p, 0);\n\n // checking that converting 0 to 254 LE bytes produces 254 zeroes\n let p_bits: [u1; 254] = 0.to_le_bits();\n assert_eq(p_bits, [0; 254]);\n }\n }\n}\n","path":"std/field/mod.nr"},"19":{"source":"// Exposed only for usage in `std::meta`\npub(crate) mod poseidon2;\n\nuse crate::default::Default;\nuse crate::embedded_curve_ops::{\n EmbeddedCurvePoint, EmbeddedCurveScalar, multi_scalar_mul, multi_scalar_mul_array_return,\n};\nuse crate::meta::derive_via;\n\n#[foreign(sha256_compression)]\n// docs:start:sha256_compression\npub fn sha256_compression(input: [u32; 16], state: [u32; 8]) -> [u32; 8] {}\n// docs:end:sha256_compression\n\n#[foreign(keccakf1600)]\n// docs:start:keccakf1600\npub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {}\n// docs:end:keccakf1600\n\npub mod keccak {\n #[deprecated(\"This function has been moved to std::hash::keccakf1600\")]\n pub fn keccakf1600(input: [u64; 25]) -> [u64; 25] {\n super::keccakf1600(input)\n }\n}\n\n#[foreign(blake2s)]\n// docs:start:blake2s\npub fn blake2s(input: [u8; N]) -> [u8; 32]\n// docs:end:blake2s\n{}\n\n// docs:start:blake3\npub fn blake3(input: [u8; N]) -> [u8; 32]\n// docs:end:blake3\n{\n if crate::runtime::is_unconstrained() {\n // Temporary measure while Barretenberg is main proving system.\n // Please open an issue if you're working on another proving system and running into problems due to this.\n crate::static_assert(\n N <= 1024,\n \"Barretenberg cannot prove blake3 hashes with inputs larger than 1024 bytes\",\n );\n }\n __blake3(input)\n}\n\n#[foreign(blake3)]\nfn __blake3(input: [u8; N]) -> [u8; 32] {}\n\n// docs:start:pedersen_commitment\npub fn pedersen_commitment(input: [Field; N]) -> EmbeddedCurvePoint {\n // docs:end:pedersen_commitment\n pedersen_commitment_with_separator(input, 0)\n}\n\n#[inline_always]\npub fn pedersen_commitment_with_separator(\n input: [Field; N],\n separator: u32,\n) -> EmbeddedCurvePoint {\n let mut points = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N];\n for i in 0..N {\n // we use the unsafe version because the multi_scalar_mul will constrain the scalars.\n points[i] = from_field_unsafe(input[i]);\n }\n let generators = derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n multi_scalar_mul(generators, points)\n}\n\n// docs:start:pedersen_hash\npub fn pedersen_hash(input: [Field; N]) -> Field\n// docs:end:pedersen_hash\n{\n pedersen_hash_with_separator(input, 0)\n}\n\n#[no_predicates]\npub fn pedersen_hash_with_separator(input: [Field; N], separator: u32) -> Field {\n let mut scalars: [EmbeddedCurveScalar; N + 1] = [EmbeddedCurveScalar { lo: 0, hi: 0 }; N + 1];\n let mut generators: [EmbeddedCurvePoint; N + 1] =\n [EmbeddedCurvePoint::point_at_infinity(); N + 1];\n let domain_generators: [EmbeddedCurvePoint; N] =\n derive_generators(\"DEFAULT_DOMAIN_SEPARATOR\".as_bytes(), separator);\n\n for i in 0..N {\n scalars[i] = from_field_unsafe(input[i]);\n generators[i] = domain_generators[i];\n }\n scalars[N] = EmbeddedCurveScalar { lo: N as Field, hi: 0 as Field };\n\n let length_generator: [EmbeddedCurvePoint; 1] =\n derive_generators(\"pedersen_hash_length\".as_bytes(), 0);\n generators[N] = length_generator[0];\n multi_scalar_mul_array_return(generators, scalars, true)[0].x\n}\n\n#[field(bn254)]\n#[inline_always]\npub fn derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {\n crate::assert_constant(domain_separator_bytes);\n // TODO(https://github.com/noir-lang/noir/issues/5672): Add back assert_constant on starting_index\n __derive_generators(domain_separator_bytes, starting_index)\n}\n\n#[builtin(derive_pedersen_generators)]\n#[field(bn254)]\nfn __derive_generators(\n domain_separator_bytes: [u8; M],\n starting_index: u32,\n) -> [EmbeddedCurvePoint; N] {}\n\n#[field(bn254)]\n// Same as from_field but:\n// does not assert the limbs are 128 bits\n// does not assert the decomposition does not overflow the EmbeddedCurveScalar\nfn from_field_unsafe(scalar: Field) -> EmbeddedCurveScalar {\n // Safety: xlo and xhi decomposition is checked below\n let (xlo, xhi) = unsafe { crate::field::bn254::decompose_hint(scalar) };\n // Check that the decomposition is correct\n assert_eq(scalar, xlo + crate::field::bn254::TWO_POW_128 * xhi);\n EmbeddedCurveScalar { lo: xlo, hi: xhi }\n}\n\npub fn poseidon2_permutation(input: [Field; N], state_len: u32) -> [Field; N] {\n assert_eq(input.len(), state_len);\n poseidon2_permutation_internal(input)\n}\n\n#[foreign(poseidon2_permutation)]\nfn poseidon2_permutation_internal(input: [Field; N]) -> [Field; N] {}\n\n// Generic hashing support.\n// Partially ported and impacted by rust.\n\n// Hash trait shall be implemented per type.\n#[derive_via(derive_hash)]\npub trait Hash {\n fn hash(self, state: &mut H)\n where\n H: Hasher;\n}\n\n// docs:start:derive_hash\ncomptime fn derive_hash(s: TypeDefinition) -> Quoted {\n let name = quote { $crate::hash::Hash };\n let signature = quote { fn hash(_self: Self, _state: &mut H) where H: $crate::hash::Hasher };\n let for_each_field = |name| quote { _self.$name.hash(_state); };\n crate::meta::make_trait_impl(\n s,\n name,\n signature,\n for_each_field,\n quote {},\n |fields| fields,\n )\n}\n// docs:end:derive_hash\n\n// Hasher trait shall be implemented by algorithms to provide hash-agnostic means.\n// TODO: consider making the types generic here ([u8], [Field], etc.)\npub trait Hasher {\n fn finish(self) -> Field;\n\n fn write(&mut self, input: Field);\n}\n\n// BuildHasher is a factory trait, responsible for production of specific Hasher.\npub trait BuildHasher {\n type H: Hasher;\n\n fn build_hasher(self) -> H;\n}\n\npub struct BuildHasherDefault;\n\nimpl BuildHasher for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n type H = H;\n\n fn build_hasher(_self: Self) -> H {\n H::default()\n }\n}\n\nimpl Default for BuildHasherDefault\nwhere\n H: Hasher + Default,\n{\n fn default() -> Self {\n BuildHasherDefault {}\n }\n}\n\nimpl Hash for Field {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self);\n }\n}\n\nimpl Hash for u1 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for u128 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for i8 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u8 as Field);\n }\n}\n\nimpl Hash for i16 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u16 as Field);\n }\n}\n\nimpl Hash for i32 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u32 as Field);\n }\n}\n\nimpl Hash for i64 {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as u64 as Field);\n }\n}\n\nimpl Hash for bool {\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n H::write(state, self as Field);\n }\n}\n\nimpl Hash for () {\n fn hash(_self: Self, _state: &mut H)\n where\n H: Hasher,\n {}\n}\n\nimpl Hash for [T; N]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for [T]\nwhere\n T: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.len().hash(state);\n for elem in self {\n elem.hash(state);\n }\n }\n}\n\nimpl Hash for (A, B)\nwhere\n A: Hash,\n B: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n }\n}\n\nimpl Hash for (A, B, C)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n }\n}\n\nimpl Hash for (A, B, C, D, E)\nwhere\n A: Hash,\n B: Hash,\n C: Hash,\n D: Hash,\n E: Hash,\n{\n fn hash(self, state: &mut H)\n where\n H: Hasher,\n {\n self.0.hash(state);\n self.1.hash(state);\n self.2.hash(state);\n self.3.hash(state);\n self.4.hash(state);\n }\n}\n\n// Some test vectors for Pedersen hash and Pedersen Commitment.\n// They have been generated using the same functions so the tests are for now useless\n// but they will be useful when we switch to Noir implementation.\n#[test]\nfn assert_pedersen() {\n assert_eq(\n pedersen_hash_with_separator([1], 1),\n 0x1b3f4b1a83092a13d8d1a59f7acb62aba15e7002f4440f2275edb99ebbc2305f,\n );\n assert_eq(\n pedersen_commitment_with_separator([1], 1),\n EmbeddedCurvePoint {\n x: 0x054aa86a73cb8a34525e5bbed6e43ba1198e860f5f3950268f71df4591bde402,\n y: 0x209dcfbf2cfb57f9f6046f44d71ac6faf87254afc7407c04eb621a6287cac126,\n is_infinite: false,\n },\n );\n\n assert_eq(\n pedersen_hash_with_separator([1, 2], 2),\n 0x26691c129448e9ace0c66d11f0a16d9014a9e8498ee78f4d69f0083168188255,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2], 2),\n EmbeddedCurvePoint {\n x: 0x2e2b3b191e49541fe468ec6877721d445dcaffe41728df0a0eafeb15e87b0753,\n y: 0x2ff4482400ad3a6228be17a2af33e2bcdf41be04795f9782bd96efe7e24f8778,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3], 3),\n 0x0bc694b7a1f8d10d2d8987d07433f26bd616a2d351bc79a3c540d85b6206dbe4,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3], 3),\n EmbeddedCurvePoint {\n x: 0x1fee4e8cf8d2f527caa2684236b07c4b1bad7342c01b0f75e9a877a71827dc85,\n y: 0x2f9fedb9a090697ab69bf04c8bc15f7385b3e4b68c849c1536e5ae15ff138fd1,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4], 4),\n 0xdae10fb32a8408521803905981a2b300d6a35e40e798743e9322b223a5eddc,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4], 4),\n EmbeddedCurvePoint {\n x: 0x07ae3e202811e1fca39c2d81eabe6f79183978e6f12be0d3b8eda095b79bdbc9,\n y: 0x0afc6f892593db6fbba60f2da558517e279e0ae04f95758587760ba193145014,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5], 5),\n 0xfc375b062c4f4f0150f7100dfb8d9b72a6d28582dd9512390b0497cdad9c22,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5], 5),\n EmbeddedCurvePoint {\n x: 0x1754b12bd475a6984a1094b5109eeca9838f4f81ac89c5f0a41dbce53189bb29,\n y: 0x2da030e3cfcdc7ddad80eaf2599df6692cae0717d4e9f7bfbee8d073d5d278f7,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6], 6),\n 0x1696ed13dc2730062a98ac9d8f9de0661bb98829c7582f699d0273b18c86a572,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6], 6),\n EmbeddedCurvePoint {\n x: 0x190f6c0e97ad83e1e28da22a98aae156da083c5a4100e929b77e750d3106a697,\n y: 0x1f4b60f34ef91221a0b49756fa0705da93311a61af73d37a0c458877706616fb,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n 0x128c0ff144fc66b6cb60eeac8a38e23da52992fc427b92397a7dffd71c45ede3,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7], 7),\n EmbeddedCurvePoint {\n x: 0x015441e9d29491b06563fac16fc76abf7a9534c715421d0de85d20dbe2965939,\n y: 0x1d2575b0276f4e9087e6e07c2cb75aa1baafad127af4be5918ef8a2ef2fea8fc,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n 0x2f960e117482044dfc99d12fece2ef6862fba9242be4846c7c9a3e854325a55c,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8], 8),\n EmbeddedCurvePoint {\n x: 0x1657737676968887fceb6dd516382ea13b3a2c557f509811cd86d5d1199bc443,\n y: 0x1f39f0cb569040105fa1e2f156521e8b8e08261e635a2b210bdc94e8d6d65f77,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n 0x0c96db0790602dcb166cc4699e2d306c479a76926b81c2cb2aaa92d249ec7be7,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9], 9),\n EmbeddedCurvePoint {\n x: 0x0a3ceae42d14914a432aa60ec7fded4af7dad7dd4acdbf2908452675ec67e06d,\n y: 0xfc19761eaaf621ad4aec9a8b2e84a4eceffdba78f60f8b9391b0bd9345a2f2,\n is_infinite: false,\n },\n );\n assert_eq(\n pedersen_hash_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n 0x2cd37505871bc460a62ea1e63c7fe51149df5d0801302cf1cbc48beb8dff7e94,\n );\n assert_eq(\n pedersen_commitment_with_separator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10),\n EmbeddedCurvePoint {\n x: 0x2fb3f8b3d41ddde007c8c3c62550f9a9380ee546fcc639ffbb3fd30c8d8de30c,\n y: 0x300783be23c446b11a4c0fabf6c91af148937cea15fcf5fb054abf7f752ee245,\n is_infinite: false,\n },\n );\n}\n","path":"std/hash/mod.nr"},"50":{"source":"use common::{\n check_commitment, check_input_note_ownership, get_address, get_note_commitment, is_multiple_kinds, InputNote,\n Note,\n};\nuse poseidon::poseidon2;\n\nmod test;\n\nfn main(\n input_notes: [InputNote; 2],\n output_notes: [Note; 2],\n pmessage4: Field,\n commitments: pub [Field; 4],\n messages: pub [Field; 5],\n) {\n // Check the commitments\n check_commitment(input_notes[0].note, commitments[0]);\n check_commitment(input_notes[1].note, commitments[1]);\n check_commitment(output_notes[0], commitments[2]);\n check_commitment(output_notes[1], commitments[3]);\n\n // Check individual outputs are not greater than 240 bits\n output_notes[0].value.assert_max_bit_size::<240>();\n output_notes[1].value.assert_max_bit_size::<240>();\n\n // We do not need to check the input notes values, as they must already have been added\n // to the tree, and the only way for that to occur if them to be added as an output note first\n // (which the check below would catch). Also, an overflow attack on the inputs would be deterimental\n // to the attacker as they would have to provide more input funds, and would receive less output funds.\n let input_value = input_notes[0].note.value + input_notes[1].note.value;\n\n // Because we have already checked the individual output notes are no greater than 240 bits,\n // then the maximum of the addition can be 2^241 which means the output value can never overflow\n let output_value = output_notes[0].value + output_notes[1].value;\n\n // Check for multiple kinds, not currently supported in this proof\n let (is_multiple_kinds, _note_kind) = is_multiple_kinds([\n input_notes[0].note,\n input_notes[1].note,\n output_notes[0],\n output_notes[1],\n ]);\n assert(!is_multiple_kinds, \"Inconsistent kinds are not allowed\");\n\n // Kind of UTXO txn (in future we may have subtypes for kind, which define different encodings\n // but for now its easier to define this way, so bytes[32] will always be main kind)\n let kind = messages[0];\n\n // Messages (only for mint/burns, otherwise all zeros)\n let msg_note_kind = messages[1];\n let msg_value = messages[2];\n\n // Assert message value size is max 240 bits to prevent overflow attack\n msg_value.assert_max_bit_size::<240>();\n\n // We only constrain the message hash for mints. For burns, any hash can be used\n // as its only used by the substitutor to early release funds. Early release is\n // secured by the validator, so as long as it records the burn hash it should be valid.\n // A user could provide a burn hash that is already used, which would prevent\n // a the substitutor from substituting the burn; this is acceptable.\n let msg_hash = messages[3];\n let burn_addr = messages[4];\n\n // Mint hash - we use the private message to prevent others from\n // being able to frontrun the mint hash in their own utxo txn\n let mint_hash = poseidon2::Poseidon2::hash([output_notes[0].psi, output_notes[1].psi], 2);\n\n // Burn hash - used for the burn substitutor and to verify status of an existing burn -\n // could be any hash so long as its asserted in the proof and cannot be modified. We were\n // planning to use the commitment of both inputs, but that is extra work and not neccessary.\n let burn_hash = commitments[0];\n\n if (kind == 1) {\n //SEND\n assert(input_value == output_value, \"Input and output totals do not match\");\n } else if (kind == 2) {\n // MINT\n // Assert mint utxo is balanced:\n // - `output_value` is checked above\n // - `input_value` is checked as it must have previously been an output value\n // - `msg_value` is checked above (but also using that to overflow would be detrimental to the\n // attacker)\n assert(output_value == input_value + msg_value, \"Mint output must match value message\");\n // Assert mint hash\n assert(mint_hash == msg_hash, \"Mint hash must match message\");\n // Assert note kind\n assert(output_notes[0].kind == msg_note_kind, \"Mint note kind must match message\")\n } else if (kind == 3) {\n // BURN\n // Prevent frontrunning the txn and changing the evm address\n assert(pmessage4 == burn_addr, \"messages[4] must match private input\");\n // Assert burn hash\n assert(burn_hash == msg_hash, \"Burn hash must match message\");\n // Assert burn utxo is balanced:\n // - `output_value` is checked above\n // - `input_value` is checked as it must have previously been an output value\n // - `msg_value` is checked above\n assert(input_value == output_value + msg_value, \"Burn output must match value message\");\n // Assert burn kind\n assert(input_notes[0].note.kind == msg_note_kind, \"Burn note kind must match message\")\n } else {\n assert(false, \"Invalid kind\");\n }\n\n // Check the user owns the input notes\n check_input_note_ownership(input_notes[0]);\n check_input_note_ownership(input_notes[1]);\n}\n\nfn bridged_note_kind() -> Field {\n 3533694129556768672311144317398675444585744224105014452550528428861358080\n}\n\n#[test]\nfn test_send_two_inputs_two_outputs() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: 1, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: 14, address, psi: 4 };\n\n // Commitments\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test]\nfn test_send_one_input_two_outputs() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: 1, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: 9, address, psi: 4 };\n\n // Commitments\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test]\nfn test_send_two_inputs_one_output() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address, psi: 0 };\n\n // Commitments\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test(should_fail)]\nfn test_send_diff_kinds() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 };\n let note_2 = Note { kind: 2, value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 };\n let note_4 = Note { kind: 2, value: 5, address, psi: 4 };\n\n // Commitments\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test]\nfn test_mint() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: 0, address: 0, psi: 0 };\n let note_4 = Note { kind: bridged_note_kind(), value: 30, address, psi: 3 };\n\n let commitments = [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ];\n\n let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2);\n\n // Commitments\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n commitments,\n [2, bridged_note_kind(), 10, mint_hash, 0],\n )\n}\n\n#[test]\nfn test_burn() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let note_4 = Note { kind: bridged_note_kind(), value: 10, address, psi: 3 };\n\n // Commitments\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [3, bridged_note_kind(), 10, get_note_commitment(note_1), 0],\n )\n}\n\n#[test]\nfn test_send_zero_value() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs - both zero value notes\n let note_1 = Note { kind: bridged_note_kind(), value: 0, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n // Outputs - both zero value notes\n let note_3 = Note { kind: bridged_note_kind(), value: 0, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address, psi: 0 };\n\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test]\nfn test_mint_with_padding_input() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs - one real note, one padding\n let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n // Outputs - note_3 is the first output (minted note), note_4 is padding or same kind\n let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: 0, address: 0, psi: 0 };\n\n let commitments = [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ];\n\n let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2);\n\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n commitments,\n [2, bridged_note_kind(), 10, mint_hash, 0],\n )\n}\n\n#[test]\nfn test_burn_single_input() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs - one real note, one padding\n let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n // Outputs - burn 10 value, keep 5\n let note_3 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 3 };\n\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [3, bridged_note_kind(), 10, get_note_commitment(note_1), 0],\n )\n}\n#[test(should_fail)]\nfn test_mint_different_kinds() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs - mix of different kinds\n let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 };\n let note_2 = Note { kind: 2, value: 3, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs - mint kind 3, first note is the minted note\n let note_3 = Note { kind: 3, value: 18, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n\n let commitments = [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ];\n\n let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2);\n\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n commitments,\n [2, 3, 10, mint_hash, 0],\n )\n}\n\n#[test]\nfn test_send_large_values() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Test with larger values (but still within 240-bit constraint)\n let large_value = 1000000000;\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: large_value, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: large_value, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: large_value + 500000, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: large_value - 500000, address, psi: 4 };\n\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test]\nfn test_mint_same_kind() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Inputs - same kind\n let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 10, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs - mint more of same kind, first note is the minted note\n let note_3 = Note { kind: bridged_note_kind(), value: 25, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: 0, address: 0, psi: 0 };\n\n let commitments = [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ];\n\n let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2);\n\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n commitments,\n [2, bridged_note_kind(), 10, mint_hash, 0],\n )\n}\n\n#[test(should_fail)]\nfn test_overflow_input_first_note() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Create a value that exceeds 240 bits\n // 2^240 = 1766847064778384329583297500742918515827483896875618958121606201292619776\n let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777;\n\n // Inputs - first note has overflow value\n let note_1 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: 10, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 4 };\n\n // This should fail due to overflow check on first input\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test(should_fail)]\nfn test_overflow_input_second_note() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Create a value that exceeds 240 bits\n let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777;\n\n // Inputs - second note has overflow value\n let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs\n let note_3 = Note { kind: bridged_note_kind(), value: 10, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 4 };\n\n // This should fail due to overflow check on second input\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test(should_fail)]\nfn test_overflow_output_first_note() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Create a value that exceeds 240 bits\n let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777;\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs - first output has overflow value\n let note_3 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 4 };\n\n // This should fail due to overflow check on first output\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test(should_fail)]\nfn test_overflow_output_second_note() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Create a value that exceeds 240 bits\n let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777;\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs - second output has overflow value\n let note_3 = Note { kind: bridged_note_kind(), value: 5, address, psi: 3 };\n let note_4 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 4 };\n\n // This should fail due to overflow check on second output\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test]\nfn test_max_allowed_value() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Use a value that is exactly at the 240-bit limit (2^240 - 1)\n let max_value = 1766847064778384329583297500742918515827483896875618958121606201292619775;\n\n // Inputs - both notes have max allowed value\n let note_1 = Note { kind: bridged_note_kind(), value: max_value, address, psi: 1 };\n let note_2 = Note { kind: 0, value: 0, address, psi: 0 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: 0 };\n\n // Outputs - transfer to single output\n let note_3 = Note { kind: bridged_note_kind(), value: max_value, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address, psi: 0 };\n\n // This should succeed as the value is exactly at the limit\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ],\n [1, 0, 0, 0, 0],\n )\n}\n\n#[test(should_fail)]\nfn test_msg_value_overflow() {\n let pk: Field = 101;\n let address = get_address(pk);\n\n // Create a value that exceeds 240 bits\n let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777;\n\n // Inputs\n let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 };\n let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 };\n let input_note_1 = InputNote { note: note_1, secret_key: pk };\n let input_note_2 = InputNote { note: note_2, secret_key: pk };\n\n // Outputs - mint with overflow msg_value\n let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 };\n let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 };\n\n let commitments = [\n get_note_commitment(note_1),\n get_note_commitment(note_2),\n get_note_commitment(note_3),\n get_note_commitment(note_4),\n ];\n\n let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2);\n\n // This should fail due to msg_value overflow check\n main(\n [input_note_1, input_note_2],\n [note_3, note_4],\n 0,\n commitments,\n [2, bridged_note_kind(), overflow_value, mint_hash, 0],\n )\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/utxo/src/main.nr"},"56":{"source":"use poseidon::poseidon2;\nuse crate::{InputNote, Note};\n\npub fn check_commitment(note: Note, commitment: Field) {\n assert(get_note_commitment(note) == commitment, \"Note commitment is not valid\");\n}\n\npub fn get_note_commitment(note: Note) -> Field {\n if (note.kind == 0) {\n assert(note.value == 0, \"Padding notes must be zero value\");\n 0\n } else {\n poseidon2::Poseidon2::hash(\n [0x2, note.kind, note.value, note.address, note.psi, 0, 0],\n 7,\n )\n }\n}\n\npub fn get_address(secret_key: Field) -> Field {\n poseidon2::Poseidon2::hash([secret_key, 0], 2)\n}\n\npub fn check_input_note_ownership(input_note: InputNote) {\n if (input_note.note.value != 0) {\n assert(\n get_address(input_note.secret_key) == input_note.note.address,\n \"Input note is not owned by the owner\",\n );\n }\n}\n\npub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) {\n let mut first_non_zero_kind = 0;\n let mut is_multiple_kinds = false;\n\n for i in 0..4 {\n if !is_multiple_kinds {\n if notes[i].kind != 0 {\n if first_non_zero_kind == 0 {\n first_non_zero_kind = notes[i].kind;\n } else if first_non_zero_kind != notes[i].kind {\n is_multiple_kinds = true;\n }\n }\n }\n }\n\n (is_multiple_kinds, first_non_zero_kind)\n}\n","path":"/Users/calummoore/projects/polybase/zk-rollup-noir/noir/common/src/note.nr"},"64":{"source":"use std::default::Default;\nuse std::hash::Hasher;\n\ncomptime global RATE: u32 = 3;\n\npub struct Poseidon2 {\n cache: [Field; 3],\n state: [Field; 4],\n cache_size: u32,\n squeeze_mode: bool, // 0 => absorb, 1 => squeeze\n}\n\nimpl Poseidon2 {\n #[no_predicates]\n pub fn hash(input: [Field; N], message_size: u32) -> Field {\n Poseidon2::hash_internal(input, message_size, message_size != N)\n }\n\n pub(crate) fn new(iv: Field) -> Poseidon2 {\n let mut result =\n Poseidon2 { cache: [0; 3], state: [0; 4], cache_size: 0, squeeze_mode: false };\n result.state[RATE] = iv;\n result\n }\n\n fn perform_duplex(&mut self) {\n // add the cache into sponge state\n for i in 0..RATE {\n // We effectively zero-pad the cache by only adding to the state\n // cache that is less than the specified `cache_size`\n if i < self.cache_size {\n self.state[i] += self.cache[i];\n }\n }\n self.state = crate::poseidon2_permutation(self.state, 4);\n }\n\n fn absorb(&mut self, input: Field) {\n assert(!self.squeeze_mode);\n if self.cache_size == RATE {\n // If we're absorbing, and the cache is full, apply the sponge permutation to compress the cache\n self.perform_duplex();\n self.cache[0] = input;\n self.cache_size = 1;\n } else {\n // If we're absorbing, and the cache is not full, add the input into the cache\n self.cache[self.cache_size] = input;\n self.cache_size += 1;\n }\n }\n\n fn squeeze(&mut self) -> Field {\n assert(!self.squeeze_mode);\n // If we're in absorb mode, apply sponge permutation to compress the cache.\n self.perform_duplex();\n self.squeeze_mode = true;\n\n // Pop one item off the top of the permutation and return it.\n self.state[0]\n }\n\n fn hash_internal(\n input: [Field; N],\n in_len: u32,\n is_variable_length: bool,\n ) -> Field {\n let two_pow_64 = 18446744073709551616;\n let iv: Field = (in_len as Field) * two_pow_64;\n let mut sponge = Poseidon2::new(iv);\n for i in 0..input.len() {\n if i < in_len {\n sponge.absorb(input[i]);\n }\n }\n\n // In the case where the hash preimage is variable-length, we append `1` to the end of the input, to distinguish\n // from fixed-length hashes. (the combination of this additional field element + the hash IV ensures\n // fixed-length and variable-length hashes do not collide)\n if is_variable_length {\n sponge.absorb(1);\n }\n sponge.squeeze()\n }\n}\n\npub struct Poseidon2Hasher {\n _state: [Field],\n}\n\nimpl Hasher for Poseidon2Hasher {\n fn finish(self) -> Field {\n let iv: Field = (self._state.len() as Field) * 18446744073709551616; // iv = (self._state.len() << 64)\n let mut sponge = Poseidon2::new(iv);\n for i in 0..self._state.len() {\n sponge.absorb(self._state[i]);\n }\n sponge.squeeze()\n }\n\n fn write(&mut self, input: Field) {\n self._state = self._state.push_back(input);\n }\n}\n\nimpl Default for Poseidon2Hasher {\n fn default() -> Self {\n Poseidon2Hasher { _state: &[] }\n }\n}\n","path":"/Users/calummoore/nargo/github.com/noir-lang/poseidon/v0.1.1/src/poseidon2.nr"}},"expression_width":{"Bounded":{"width":4}}} \ No newline at end of file diff --git a/fixtures/eip7702/hashcalls_vector1.hex b/fixtures/eip7702/hashcalls_vector1.hex new file mode 100644 index 0000000..178667a --- /dev/null +++ b/fixtures/eip7702/hashcalls_vector1.hex @@ -0,0 +1,2 @@ +0xa4f6f48d63e34a6f780b5f19716f03b3113a8e4559716c301309cb0de2ce5a24 + diff --git a/fixtures/params/.gitignore b/fixtures/params/.gitignore new file mode 100644 index 0000000..ec12338 --- /dev/null +++ b/fixtures/params/.gitignore @@ -0,0 +1 @@ +g1.max.dat diff --git a/fixtures/params/g1.utxo.dat b/fixtures/params/g1.utxo.dat new file mode 100644 index 0000000..ae287f6 Binary files /dev/null and b/fixtures/params/g1.utxo.dat differ diff --git a/fixtures/params/kzg_bn254_14.srs b/fixtures/params/kzg_bn254_14.srs deleted file mode 100644 index 125e4f6..0000000 --- a/fixtures/params/kzg_bn254_14.srs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a6f19f9d28c6fbad4ed6cea3ff9ff5e518929d785571017061b5dc0105454b94 -size 2097412 diff --git a/fixtures/params/kzg_bn254_21.srs b/fixtures/params/kzg_bn254_21.srs deleted file mode 100644 index 34194ab..0000000 --- a/fixtures/params/kzg_bn254_21.srs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8e999d1361d5cd8b756ff5980e2e19b3a8f717a5347fd1669397a0dec6eb3df4 -size 268435716 diff --git a/fixtures/params/kzg_bn254_6.srs b/fixtures/params/kzg_bn254_6.srs deleted file mode 100644 index 24801fd..0000000 --- a/fixtures/params/kzg_bn254_6.srs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e987af522575abf235040a58a92e75a275a3696674c6ab0c42deef723d1e0558 -size 8452 diff --git a/fixtures/params/kzg_bn254_8.srs b/fixtures/params/kzg_bn254_8.srs deleted file mode 100644 index f10190b..0000000 --- a/fixtures/params/kzg_bn254_8.srs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9144792cc0696f192987881b4396354639c48a97138325510f46acf80eb676c7 -size 33028 diff --git a/fixtures/params/kzg_bn254_9.srs b/fixtures/params/kzg_bn254_9.srs deleted file mode 100644 index 43e2b02..0000000 --- a/fixtures/params/kzg_bn254_9.srs +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:26153128b08b72c147a5f4cd04d5feaea9eba9d1e662b860c3864cd0686a70b9 -size 65796 diff --git a/fixtures/proofs/agg_agg_final_evm_proof.proof b/fixtures/proofs/agg_agg_final_evm_proof.proof index 6a7eb23..6d3d066 100644 Binary files a/fixtures/proofs/agg_agg_final_evm_proof.proof and b/fixtures/proofs/agg_agg_final_evm_proof.proof differ diff --git a/fixtures/proofs/agg_utxo_0.proof b/fixtures/proofs/agg_utxo_0.proof index 654bb0a..ab3f222 100644 Binary files a/fixtures/proofs/agg_utxo_0.proof and b/fixtures/proofs/agg_utxo_0.proof differ diff --git a/fixtures/proofs/agg_utxo_1.proof b/fixtures/proofs/agg_utxo_1.proof index 3f016c7..e949352 100644 Binary files a/fixtures/proofs/agg_utxo_1.proof and b/fixtures/proofs/agg_utxo_1.proof differ diff --git a/fixtures/proofs/agg_utxo_agg.proof b/fixtures/proofs/agg_utxo_agg.proof index e8ed539..1ebc3ed 100644 Binary files a/fixtures/proofs/agg_utxo_agg.proof and b/fixtures/proofs/agg_utxo_agg.proof differ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c07a91d --- /dev/null +++ b/flake.lock @@ -0,0 +1,129 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1705309234, + "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1707056651, + "narHash": "sha256-5zvYww7WPpSQw2z1sbpUqLJj0IyrV6u9XOmurEjRvGs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e8fa42021ec9b6796fc841ad24942397dab6a114", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1706487304, + "narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "90f456026d284c22b3e3497be980b2e47d0b28ac", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1707012820, + "narHash": "sha256-4cxIaHUx6/DSEVHJfK0gx4DZkJ5xHugan27KfuVPnj0=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "b83b8c3ef16d15a4ae3843d74f32dfc86caed60f", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..4b40a7e --- /dev/null +++ b/flake.nix @@ -0,0 +1,59 @@ +{ + description = "Basic devshell for polybase"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs"; + flake-utils.url = "github:numtide/flake-utils"; + rust-overlay.url = "github:oxalica/rust-overlay"; + }; + + outputs = { nixpkgs, flake-utils, rust-overlay, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + overlays = [ (import rust-overlay) ]; + }; + + rustToolchain = pkgs.rust-bin.nightly."2023-01-10".default.override { + extensions = [ "rust-src" "rust-analyzer" ]; + }; + + deployContracts = pkgs.writeShellScriptBin "deploy-scripts.sh" '' + (cd eth && yarn --silent deploy:tests > ../pkg/node/tests/.env.test) + ''; + + run-node = pkgs.writeShellScriptBin "run-node.sh" '' + (cd eth && npx hardhat node) + ''; + + in { + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + rustToolchain + + pkg-config + fontconfig + openssl + + go + nodejs + python3 + yarn + + protobuf + + clang # required for rocksdb + + cargo-insta + deployContracts + run-node + + ]; + + LIBCLANG_PATH = "${pkgs.libclang.lib}/lib/"; + RUST_SRC_PATH = "${rustToolchain}/lib/rustlib/src/rust/library"; + ROLLUP_CONTRACT_ADDR="0xdc64a140aa3e981100a9beca4e685f962f0cf6c9"; + PROTOC = "${pkgs.protobuf}/bin/protoc"; + }; + }); +} diff --git a/noir/.gitignore b/noir/.gitignore new file mode 100644 index 0000000..cbf8a4c --- /dev/null +++ b/noir/.gitignore @@ -0,0 +1 @@ +Prover.toml \ No newline at end of file diff --git a/noir/Nargo.toml b/noir/Nargo.toml new file mode 100644 index 0000000..cc3df9d --- /dev/null +++ b/noir/Nargo.toml @@ -0,0 +1,15 @@ +[workspace] +members = [ + "utxo", + "agg_utxo", + "agg_agg", + "agg_final", + "signature", + "points", + "migrate", + "poseidon_alt", + "evm/erc20_transfer", + "evm/mint", + "evm/burn", + "evm/transfer", +] diff --git a/noir/README.md b/noir/README.md new file mode 100644 index 0000000..2cf863c --- /dev/null +++ b/noir/README.md @@ -0,0 +1,136 @@ +# Noir Circuits + +This directory contains the Noir circuits for the Payy Network. + +## Updating Circuits + +When updating circuits, you must perform the following steps: + +1. Run `./generate_fixtures.sh` to generate the new fixtures for the circuits. + + The script downloads the required `solc` binary into `~/.polybase/solc/` if it is missing. + +2. Update the circuit in `pkg/barretenberg/src/circuits/`to handle new circuit inputs + +3. Update `pkg/zk-primitives/src/.rs` to circuit data types + + +## Installing Noir + +Install Noir (`noirup` and `nargo`): + +```bash +curl -L https://raw.githubusercontent.com/noir-lang/noirup/refs/heads/main/install | bash +noirup +``` + +Install the specific `nargo` version, `1.0.0-beta.14`: + +```bash + noirup -v 1.0.0-beta.14 +``` + +Confirm it: + +```bash +$ nargo --version +nargo version = 1.0.0-beta.14 +noirc version = 1.0.0-beta.14+60ccd48e18ad8ce50d5ecda9baf813b712145051 +(git version hash: 60ccd48e18ad8ce50d5ecda9baf813b712145051, is dirty: false) +``` + +Install proving backend (`bbup` `bb`): + +```bash +curl -L https://raw.githubusercontent.com/AztecProtocol/aztec-packages/refs/heads/master/barretenberg/bbup/install | bash +bbup +``` + +See [Noir docs](https://noir-lang.org/docs) for more information. + +## Install specific bb version + +```sh +bbup -v 3.0.0-manual.20251030 +``` + +Confirm it: + +```bash +$ bb --version +3.0.0-manual.20251030 +``` + +## Testing proof generation manually using CLI (non-recursive) + +Assumes `bb` version: `v3.0.0-manual.20251030`. + +To test proof generation manually, you can run the following steps: + +```bash +# set to the package name you want to test +PACKAGE_NAME=utxo +``` + +### 1. Compile the circuit + +```bash +nargo compile --package $PACKAGE_NAME +``` + +(will output a compiled program in `target/$PACKAGE_NAME.json`) + +### 2. Generate the witness + +Relies on the Prover.toml file, with valid inputs. + +```bash +nargo execute --package $PACKAGE_NAME +``` + +(will output a witness file in `target/${PACKAGE_NAME}.gz`) + +### 3. Generate the proof + +```bash +bb prove --scheme ultra_honk -b target/${PACKAGE_NAME}.json -w target/${PACKAGE_NAME} -o target +``` + +(will output a proof file in `target/${PACKAGE_NAME}_proof`) + +### 4. Verify the proof + +Generate the verification key (non-recursive): + +```bash +bb write_vk --scheme ultra_honk -b target/${PACKAGE_NAME}.json -o target +``` + +To generate as fields use the `--output_format fields` flag. + +Generate the verification key (recursive): + +```bash +bb write_vk --scheme ultra_honk --honk_recursion 1 --init_kzg_accumulator -b target/${PACKAGE_NAME}.json -o target +``` + +Verify the proof: + +```bash +bb verify --scheme ultra_honk -p target/proof -k target/vk -v +``` + +Check the verified output is: `verified: 1` + + +## Troubleshooting + + 1. Ensure you have written a test within Noir and tested with `Prover.toml` inputs + + 1. Re-run `./generate_fixtures.sh` if you have made any changes to the circuits + + 2. Ensure the correct number of public inputs is being set in the circuit Prove trait + + 3. Ensure the deconstruction and reconstruction of public inputs and proof is valid + + 4. Check the order of the public inputs matches the noir main.nr file diff --git a/noir/agg_agg/Nargo.toml b/noir/agg_agg/Nargo.toml new file mode 100644 index 0000000..d976726 --- /dev/null +++ b/noir/agg_agg/Nargo.toml @@ -0,0 +1,16 @@ +[package] +name = "agg_agg" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[package.metadata.generate_fixtures] +recursive = true + +[[package.metadata.generate_fixtures.hash_updates]] +path = "../agg_final/src/main.nr" +kind = "global_field" +name = "AGG_AGG_VERIFICATION_KEY_HASH" + +[dependencies] +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/agg_agg/Prover.toml b/noir/agg_agg/Prover.toml new file mode 100644 index 0000000..022614a --- /dev/null +++ b/noir/agg_agg/Prover.toml @@ -0,0 +1,220 @@ +key_hash = "0x144c49884b401002d0be2bc48c848a15dfd301d1cbc4efb9ffedd4e5b6ef94e4" +verification_key = [ + "0x0931d596de2fd10f01ddd073fd5a90a976f169c76f039bb91c4775720042d43a", + "0x0000000000000000000000000000000000000000000000000000000000001000", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000001000", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000006e31ac0e1988b67544608eba163c604665", + "0x00000000000000000000000000000000001ac103634643e7278773817bfaca82", + "0x0000000000000000000000000000007854e5bb321232f191be4963f9db527c7a", + "0x00000000000000000000000000000000000d22706842dceb629d3f54012895dd", + "0x000000000000000000000000000000c3b8012932cac317ed9b35c73d3e5c0c55", + "0x0000000000000000000000000000000000214155a0fd69df4ce824b5a28eb19f", + "0x0000000000000000000000000000007d606be98476cb787154545ec3ec838679", + "0x00000000000000000000000000000000001e77a427fb821dbc14c34b2a40cf8f", + "0x000000000000000000000000000000e45847a04b924b3701dff5b465680f3ddd", + "0x00000000000000000000000000000000002c1b78bff9f88573d7ba8e7966fd86", + "0x0000000000000000000000000000009f9cb39e9c36d873458128573324148cb0", + "0x00000000000000000000000000000000000891edc8c53e145ab2bd2e48cb4b93", + "0x00000000000000000000000000000045ca07e6467fe90e57291bad40535aad7a", + "0x000000000000000000000000000000000006c12a3d9cd4536d7c382d0d9f563b", + "0x000000000000000000000000000000636afe2bb7411e26a949dbcb3e73025671", + "0x000000000000000000000000000000000013ebda3fe9f940d5a87c5014f716b8", + "0x00000000000000000000000000000042ff43636249d9a5a854311e2e0acb1f07", + "0x000000000000000000000000000000000019b8749f40cae8f5fa4c83536c4e61", + "0x000000000000000000000000000000c7d196b58f546f751e22c12f971914d051", + "0x00000000000000000000000000000000000db52f90def4acadb252661157e151", + "0x0000000000000000000000000000002bf0dc5e1be4fc654ef053d9eb3d748f10", + "0x00000000000000000000000000000000001dbe9ced76b8b2f4cf83ebf3dc542a", + "0x0000000000000000000000000000008ce60d9cd21d0f40938cd8c95eba22bd2f", + "0x000000000000000000000000000000000009136eaeb228b3dcbe81a80c9cecb5", + "0x000000000000000000000000000000ba657daa7e501f234286ed40adf6d1053b", + "0x0000000000000000000000000000000000158c7b4d2ee9b16dc6a0754d4d44eb", + "0x00000000000000000000000000000072dd42f70c3aec5f4efe6b3de61bb97c65", + "0x00000000000000000000000000000000000a9a4f6b9be82f8e65c5cb55786f67", + "0x000000000000000000000000000000d7a22acc7724029445538ba1a12db0b896", + "0x00000000000000000000000000000000000a1f8c55781b25a8932076147a30eb", + "0x000000000000000000000000000000aa6fd50e12b576477beb5c1fc8f61c2f04", + "0x0000000000000000000000000000000000065ab8843c5bb77c144e6a8e1b8237", + "0x000000000000000000000000000000e51e2e82380da3da5ad0f24e49e5f32208", + "0x000000000000000000000000000000000013982fd0cf8da5082a77561113bb5e", + "0x000000000000000000000000000000b0b25e9b4e4e04ad1280d1a264237717e0", + "0x00000000000000000000000000000000001aa5ffd5aa4c16d1c66e18c4574a3a", + "0x0000000000000000000000000000001ce018f20536fe45ca28dcc7b248389fc0", + "0x00000000000000000000000000000000001750f44d3f9dfad78a1e2127ef9105", + "0x000000000000000000000000000000164b49c0f27d4f5ac4550751cc0a24bb58", + "0x00000000000000000000000000000000001a05418f502a965c39994cd3f83e39", + "0x00000000000000000000000000000068529ee14a3d63ac2f3c5ace01f600e61d", + "0x00000000000000000000000000000000000db9e60db6f9520285a526193addf1", + "0x00000000000000000000000000000056f4727f145b6e12b429145869eea4ecfd", + "0x00000000000000000000000000000000000830594af600bb87fa0d33bc31088f", + "0x0000000000000000000000000000000add10dde3bc57567fd475159516de482b", + "0x0000000000000000000000000000000000142f45e7c19b85205f52d5b12cfd5a", + "0x0000000000000000000000000000001dbd9be0ed90a1028fb37738a6e789ebc0", + "0x00000000000000000000000000000000002b5efeb461e49a212a30fabe48a0d3", + "0x00000000000000000000000000000025034f2d4ad83fa03c3b67f08b1a5921c1", + "0x00000000000000000000000000000000000592a4e58f8a336ec20eeb52e4135b", + "0x00000000000000000000000000000077573d6698d871e103f6eb3af1883687e1", + "0x00000000000000000000000000000000002adc2a27e82bec9baf54bae1af18ca", + "0x000000000000000000000000000000f0590ec43f637bb9b59c017c71c4438b38", + "0x00000000000000000000000000000000001ae8a540ccf447e41257d7062b7534", + "0x0000000000000000000000000000005cb731e35222cf73795810e7966080af14", + "0x0000000000000000000000000000000000172f63e409161ff6328370128e616f", + "0x000000000000000000000000000000bcf43c285b1d1f7f85341f3615d25fe97b", + "0x0000000000000000000000000000000000259f452dc7fd2dda4013dba2196852", + "0x000000000000000000000000000000711e890a1c99a8f689419da8c52d2e8e9d", + "0x0000000000000000000000000000000000117500555dd886209c0b10ee8cd10e", + "0x000000000000000000000000000000a84fca32b13b92e520bb91a7455f78ccf1", + "0x00000000000000000000000000000000002577f542178a07dac262fdabad6f55", + "0x000000000000000000000000000000e12644a82ee1345497f8c0302e92925c68", + "0x00000000000000000000000000000000000fc87ae27122e60eaacc070bd59aaf", + "0x000000000000000000000000000000e5fe2c041687603b6577581d673d13be50", + "0x00000000000000000000000000000000001612f501335a4b72ac55dbe2fd1a75", + "0x00000000000000000000000000000070846e904bb7d1c7ff02f32823de6c1c71", + "0x0000000000000000000000000000000000160e8ef7ff5315cb640ec82e965db2", + "0x00000000000000000000000000000064007633f529476b2f169a0ff131bfb319", + "0x00000000000000000000000000000000002d540ff1653b38acbcb9cda3154423", + "0x000000000000000000000000000000713898655cc94a0ac2d84944c737cf57e5", + "0x00000000000000000000000000000000002198b9feb61f8160e357b8bb7ca329", + "0x000000000000000000000000000000ad74612e486596cbe7f7d6a05f19c69444", + "0x000000000000000000000000000000000011c8df52c3ef754f80d11792cea4b7", + "0x0000000000000000000000000000002ac2932f3bd1b6942b132546d2110a63e2", + "0x000000000000000000000000000000000010c8a36cbb2fd9ed8875b5106a3716", + "0x0000000000000000000000000000004b01b29b751e8e731f03736d3c2fdcd902", + "0x00000000000000000000000000000000000e80dc493414b87bdf36b1f6c94f38", + "0x0000000000000000000000000000003ba9554e9b44e4bc794680cdc1a95f684b", + "0x00000000000000000000000000000000000ebbbd7bdf23989af1b8ead81264a4", + "0x000000000000000000000000000000db26775f6bcfa6ba0b3cc5a258d446695b", + "0x0000000000000000000000000000000000128cae8f19f8082e53b1a969850632", + "0x000000000000000000000000000000448d8bd40bf227b45340a442b7e078941f", + "0x00000000000000000000000000000000001f08ae86f7d57e264fd67c5fb33ce9", + "0x00000000000000000000000000000069e9bcd999bbb6b75428d555adc0c4fa9c", + "0x00000000000000000000000000000000000d9672ebdf9132e03d88497a980414", + "0x0000000000000000000000000000002015f03933333e05be96a70cb55bd4aafc", + "0x000000000000000000000000000000000024259ffba09b51381a5c32de8e68c1", + "0x0000000000000000000000000000007e425fdf112e1424fe8d271d667a6c5e15", + "0x00000000000000000000000000000000001e360029905e14e80eeb6dde5a8311", + "0x000000000000000000000000000000c6f04750d7aa77d2cdedc64fbfdc8d32c7", + "0x000000000000000000000000000000000019c14b718b3b9536719f751718cad9", +] +proof = [ + "0x000000000000000000000000000000092f229c8b95bf7e1fdfc93a58088c990e", + "0x000000000000000000000000000000000019ec4766ee8ea09da25565903be2a1", + "0x000000000000000000000000000000d924cc7122271b5f7a11ad43ef45833bc4", + "0x000000000000000000000000000000000020580dbac517a17d63f36955185165", + "0x000000000000000000000000000000f8ba9184295dfc60c59330e14e303fd418", + "0x0000000000000000000000000000000000197d5e390f11e19d713a0f28426034", + "0x000000000000000000000000000000ae83d070d683937a57889723800a0654c2", + "0x00000000000000000000000000000000000be2c8d150f3e4ffe064e42f76ddb4", + "0x00000000000000000000000000000016d7fc2d8a4e2de5add57c1b0f7c999bf7", + "0x00000000000000000000000000000000000b5698e65fc6d8b3fdafa395ba0a37", + "0x000000000000000000000000000000fe27e26ffdf346006ac0625391b2eda4ed", + "0x00000000000000000000000000000000001e5f95c0c69489d2d2fe8d94c97730", + "0x0000000000000000000000000000003bdd028f550d3afdac51d737ab685d9822", + "0x000000000000000000000000000000000021bf26b8a7d5665af4a70125f961cd", + "0x00000000000000000000000000000001d7d63fbece3ce85954cc3f1863d30727", + "0x00000000000000000000000000000000000745d14fc1238af266c3de956f450a", + "0x000000000000000000000000000000db5ed2886536c17b3e0198a2eaa9428314", + "0x0000000000000000000000000000000000044495da2f3631665686939dde9b2e", + "0x0000000000000000000000000000001d8fd74b6913191087dc074149ac78c01b", + "0x000000000000000000000000000000000016acaaf8aed02baab14476a6e225fe", + "0x000000000000000000000000000000eb95ba1c00052dce44a2f004b544651b95", + "0x000000000000000000000000000000000018b4556bab90caa4f4d99c12af7e5e", + "0x000000000000000000000000000000c9a6d8bdced22500d4a08507ba96075f83", + "0x0000000000000000000000000000000000238ee292dbe873848b9d4216a72833", + "0x000000000000000000000000000000273064faaa813cb437782520e00136b750", + "0x00000000000000000000000000000000000f6bf8eceade57cb429716beac5417", + "0x000000000000000000000000000000a4c27e739c8b88f8e285956ff58aed6eb8", + "0x00000000000000000000000000000000001c3c441853d45d3ba8a008eb7f5efb", + "0x0000000000000000000000000000006a5c42a7e7940d43efa25cc60a1fbd0e59", + "0x000000000000000000000000000000000003d71fbbff0f0164cfdfdc0ba1852e", + "0x000000000000000000000000000000ffe1d6b557d7858be6258e5a67a5870c3d", + "0x00000000000000000000000000000000002a936ce15aa9cefa9c0720fc1e1f0c", + "0x000000000000000000000000000000f026131ef4c35046e5fa5bb751f6a2520a", + "0x00000000000000000000000000000000002056c81e59657f49280e8a73d149bc", + "0x000000000000000000000000000000e195e54c3b0514c8c81e3251dcf1e1f9db", + "0x00000000000000000000000000000000002e8e1b05bc6c5743c4217414833ac0", + "0x000000000000000000000000000000473273635f7b6b5fd19bcc245cb2a7771b", + "0x0000000000000000000000000000000000008684066efd1c78d1801d77f57f9a", + "0x000000000000000000000000000000cf11025cdbf9c41ef3ed19108b18a4588c", + "0x000000000000000000000000000000000024e8ba13a5f049dcac7aa79a768fda", + "0x000000000000000000000000000000aff31584fff93e012ab7fdec0647c9a85a", + "0x0000000000000000000000000000000000147a12c2089dd29364f17fa9541452", + "0x00000000000000000000000000000071ed5db20ad6e1321f1d93e55b628e348f", + "0x000000000000000000000000000000000000b531df34f0e246e68335eaa3dab8", + "0x07a2c7eb40652064e6cf5cb926f1cd36819db957499a1c2657acf78099145f5c", + "0x173246d287ae0a9a706e4456fa3c51dee4f7d26901e2c013039b3052606f6db4", + "0x15006476b4d8c07985a08d766df428b4862c23b4fe5101efffa9ccf992577193", + "0x024b23145efca0cde6db92820ea0c3142cfe0bcd629804c7ecae4d27bbb4a5e8", + "0x0c8fa646f58d84767efa3aabc237c50a3dc9460d5b52527e7635328f3776c512", + "0x1243f8c46c3589d2c018a9dafb99f2a42523da278ea8f6c93842973945fd8aae", + "0x19114e25db035820aa08f250f057e80014e3eb9952bcab989a1e24ebeb1d1a95", + "0x0b32ff873e26abdb949119ec28950c71412f71177ebe8b7e31dfaa1349b621a4", + "0x04112a86364be197862ecbea8b20449a09e2e6635256c075b097bfc3e7e65470", + "0x0a8d9a9a23d35b3a3b67d4845bdfae41afcaa3ad5d12ab414c61c25bfd14f686", + "0x06aff0223481bf73d531a6fb1f715c0237f6a8122ee7c184d13080aaa87bb5d3", + "0x21e9c77748146a16f1eac100f3368e4e379c51a225f716699d144c5038671167", + "0x098834b47feb704e0634332b78e79b82695e8aa776adfe3ca73b1c5881a333b6", + "0x2559398c0494ef6556a5481a718059bbfcc6c4264f5d039fc29fecea4146ec84", + "0x02f4e9edff3b506fdda09aa6752d7c61f04b6394f698cbc8f1d87acdb1c69085", + "0x289d699d744910511c38f20f3fd16f93148853f1c60af8c1efe7660c10975326", + "0x225fb9401646276d4bbba821469313007fa8628ac0ff6d28fb7990256b52ce2a", + "0x2c982863d9fae5b89ad0d66ef18b8bfbd9729131def425a4c763801a43ce256a", + "0x25636d120530bcc543df755bc3bafc2f8dc9dd48414e341abe746b9b70dc9e62", + "0x1a36786368895865174076adc83e0d804230b42e1bc5a0178687d11acb51bbd3", + "0x1ac3ed3f2403598478441066d01fd2a82f1468292e86558022cc5c7808073c44", + "0x15e458855a4055a5aac11445541659db55e87fbcb6e855f7129de45820c9c432", + "0x0fa6a827fc3d6cc1da43ca575ad7fd48c1088e55b1dcca5e1e300e717b853f36", + "0x0968f7ca9e3a83de09c680696199a0b62c289ceeacd13ec529c2388ad640ba3a", + "0x032b476d40379afa3949367b685b44239748ab87a7c5b32c355462a430fc353e", + "0x1c2208e2b8433e897b3e5e334d54b66deac87123bbf3e190070bba3ec60e492e", + "0x0670c2329a40285053a8dd264ee0884dc25c82823fddead7628a1fa8e5c70023", + "0x1582e32ef6f85aa0e161ce4264122c3fcabcde5aca094b28e54c10b8a7557a35", + "0x2f9e5c9676fa3da45e11d75dc920bd169cc43e23e579d8489b2e9a06c17af09b", + "0x05be21f7a82420a83e9a148e4cf8b0bb61364fbe0f372f87bb3069a938b39167", + "0x2af4e9cd57b645abdf07d4b217fcd9d73b27247f77c4b270eea1019905825677", + "0x14db30dfe49b245453d06ab9ee75db1130386180557c37a6272c04dcfb1d1aa0", + "0x1e03dc74bff9b58ec08e89e16c0266779982b510912156e4628ca81ce37e607c", + "0x256991936180224d3375bf4f150786f546ce60fe4c7552927b3f5899f217512f", + "0x2c30cfdd8b7415c7819df4398c1ddf81076d24d5b894f8e587a28d5d95928238", + "0x1d679113a0adeefc60c44fe10216b437b5a7405e4384c9fec06973b4a4146219", + "0x1c338cbe0e397a91bc6cf030060d0a3f1296b5bdb3c6c1d2181c8592a967ebb5", + "0x087b7f3ed36a533cc3fb9d50b13ee4f609014d7dc17d0a536607e71375d7346d", + "0x15498820c7ff978c4264a6850b0f23772923b8afb00b2753ff810d0f6653ce21", + "0x22179102bc94dbdbc0cdafb964df61f8494623e19e99445498fa330b56d067d5", + "0x2ee599e4b12a202b3f36b8edbeafa07969688f138d27615532735907474d0189", + "0x00000000000000000000000000000052f87652296ef1803b8ca2f23b4f811e5d", + "0x000000000000000000000000000000000016111281ce9bf7d506d85314ce961c", + "0x000000000000000000000000000000e5a2bf68c481873b7fa06b72f00787684a", + "0x000000000000000000000000000000000025983cb846120d4998b68a313bc1db", + "0x000000000000000000000000000000132b1e7a0a66a54672fcd7628a1da2d046", + "0x00000000000000000000000000000000002c1d0e3a713ece76f8e13c0e5a384b", + "0x000000000000000000000000000000e4ee5f2267f36b1d6ed652c7f37e01d7f7", + "0x00000000000000000000000000000000000e65ae4bd738cbca7ff2aec33a4bc7", +] +public_inputs = [ + "0x21cd742a799cbe15b2e7a4641120f803a3c31b11f610a59046d880cf3d282c83", + "0x2ed5b94a8af2550139982907f04523f711c8df4fefc44190ca5bdba08793cfd2", + "0x164377fa253ee407efc1b5e19706dde2d5d3e582f082fa38ad5529b79533a835", + "0x28e54d0e40cded1696e63822594863b1ec91e54c045687cfe9fa6bbc17f21336", + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] diff --git a/noir/agg_agg/Verifier.toml b/noir/agg_agg/Verifier.toml new file mode 100644 index 0000000..b71a430 --- /dev/null +++ b/noir/agg_agg/Verifier.toml @@ -0,0 +1,8 @@ +public_inputs = [ + "0x21cd742a799cbe15b2e7a4641120f803a3c31b11f610a59046d880cf3d282c83", + "0x2ed5b94a8af2550139982907f04523f711c8df4fefc44190ca5bdba08793cfd2", + "0x164377fa253ee407efc1b5e19706dde2d5d3e582f082fa38ad5529b79533a835", + "0x28e54d0e40cded1696e63822594863b1ec91e54c045687cfe9fa6bbc17f21336", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] diff --git a/noir/agg_agg/src/main.nr b/noir/agg_agg/src/main.nr new file mode 100644 index 0000000..42d2db4 --- /dev/null +++ b/noir/agg_agg/src/main.nr @@ -0,0 +1,115 @@ +use dep::std; +use poseidon::poseidon2; + +struct AggProof { + proof: [Field; 508], + old_root: Field, + new_root: Field, + commit_hash: Field, + messages: [Field; 1000], + verification_key: [Field; 115], + verification_key_hash: Field +} + +fn main( + proofs: [AggProof; 2], + // allowed proofs (will be validated by agg_final) + verification_key_hash: pub [Field; 2], + old_root: pub Field, + new_root: pub Field, + commit_hash: pub Field, + messages: pub [Field; 1000], +) { + let mut root = old_root; + let mut first_public_inputs: [Field; 1005] = [0; 1005]; + let mut messages_index = 0; + + for i in 0..2 { + let proof = proofs[i]; + + // Assert the proof is one of public verification_key_hash (this will be verified in the agg_final) + let is_valid_proof = (verification_key_hash[0] == proof.verification_key_hash) | (verification_key_hash[1] == proof.verification_key_hash); + assert(is_valid_proof, "proof must be one of the valid proofs"); + + let mut public_inputs: [Field; 1005] = [0; 1005]; + + public_inputs[0] = verification_key_hash[0]; + public_inputs[1] = verification_key_hash[1]; + public_inputs[2] = proof.old_root; + public_inputs[3] = proof.new_root; + public_inputs[4] = proof.commit_hash; + + /////// + // Check compact messages and assign public inputs + /////// + + // End immediately for padding proof (as it cannot have messages) + let mut has_ended = proof.old_root == 0; + + // Exportable message kinds (2, 3 and 4) consume the next x messages, so when checking + // for the end we skip the consumed messages, so we can find the first non-exportable kind. + // Assumes that agg_utxo proof also compacts exportable kinds from index 0 (without gaps). + let mut next_check = 0; + for j in 0..1000 { + let proof_message = proof.messages[j]; + public_inputs[j + 5] = proof_message; + + // Update next checkpoint (or end) + if (next_check == j) { + if proof_message == 2 { + // Mint + next_check += 4; + } else if ((proof_message == 3) | (proof_message == 4)) { + // Burn, Swap + next_check += 5; + } else { + has_ended = true; + } + } + + if (has_ended) { + assert(proof_message == 0, "messages cannot have gaps"); + } else { + assert(messages_index != 1000, "proof messages exceed compacted range"); + assert(proof_message == messages[messages_index], "proof message must be exported"); + // Incr the global counter (shared between proofs) + messages_index += 1; + } + } + + // Workaround for 2nd proof being a padding proof + if i == 0 { + first_public_inputs = public_inputs; + } + + std::verify_proof_with_type( + proof.verification_key, + if proof.old_root != 0 { + proof.proof + } else { + proofs[0].proof + }, + if proof.old_root != 0 { + public_inputs + } else { + first_public_inputs + }, + proof.verification_key_hash, + 7, + ); + + if proof.old_root != 0 { + assert(proof.old_root == root, "proof old_root must match previous root"); + root = proof.new_root; + } + } + + assert( + commit_hash + == poseidon2::Poseidon2::hash( + [proofs[0].commit_hash, proofs[1].commit_hash], + 2, + ), + ); + assert(new_root == root, "Roots must match"); +} diff --git a/noir/agg_final/Nargo.toml b/noir/agg_final/Nargo.toml new file mode 100644 index 0000000..d7ae584 --- /dev/null +++ b/noir/agg_final/Nargo.toml @@ -0,0 +1,22 @@ +[package] +name = "agg_final" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[package.metadata.generate_fixtures] +solidity = true +oracle_hash = "keccak" + +[[package.metadata.generate_fixtures.hash_updates]] +path = "../../eth/scripts/deploy.ts" +kind = "const_string" +name = "AGG_FINAL_VERIFICATION_KEY_HASH" + +[[package.metadata.generate_fixtures.hash_updates]] +path = "../../pkg/contracts/src/rollup.rs" +kind = "const_string" +name = "AGG_FINAL_VERIFICATION_KEY_HASH" + +[dependencies] +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/agg_final/src/main.nr b/noir/agg_final/src/main.nr new file mode 100644 index 0000000..8781f55 --- /dev/null +++ b/noir/agg_final/src/main.nr @@ -0,0 +1,39 @@ +use dep::std; +use poseidon::poseidon2; + +global AGG_UTXO_VERIFICATION_KEY_HASH: Field = 5897206462939179313090278977855702552208277022861650698363349603526525271812; +global AGG_AGG_VERIFICATION_KEY_HASH: Field = 11623735493169461569078977608660595680947806981338331162316688672907570294243; + +fn main( + verification_key: [Field; 115], + verification_key_hash: Field, + proof: [Field; 508], + old_root: pub Field, + new_root: pub Field, + commit_hash: pub Field, + messages: pub [Field; 1000], +) { + // Must be an agg_agg proof + assert(verification_key_hash == AGG_AGG_VERIFICATION_KEY_HASH, "only agg_agg proof allowed"); + + // Build public inputs for the agg_agg proof + let mut public_inputs: [Field; 1005] = [0; 1005]; + public_inputs[0] = AGG_UTXO_VERIFICATION_KEY_HASH; + public_inputs[1] = AGG_AGG_VERIFICATION_KEY_HASH; + public_inputs[2] = old_root; + public_inputs[3] = new_root; + public_inputs[4] = commit_hash; + + for i in 0..1000 { + public_inputs[i + 5] = messages[i]; + } + + // Verify the agg_agg proof + std::verify_proof_with_type( + verification_key, + proof, + public_inputs, + verification_key_hash, + 7, + ); +} diff --git a/noir/agg_utxo/Nargo.toml b/noir/agg_utxo/Nargo.toml new file mode 100644 index 0000000..a65f9e6 --- /dev/null +++ b/noir/agg_utxo/Nargo.toml @@ -0,0 +1,17 @@ +[package] +name = "agg_utxo" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[package.metadata.generate_fixtures] +recursive = true + +[[package.metadata.generate_fixtures.hash_updates]] +path = "../agg_final/src/main.nr" +kind = "global_field" +name = "AGG_UTXO_VERIFICATION_KEY_HASH" + +[dependencies] +common = { path = "../common" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/agg_utxo/Prover.toml b/noir/agg_utxo/Prover.toml new file mode 100644 index 0000000..6f875e1 --- /dev/null +++ b/noir/agg_utxo/Prover.toml @@ -0,0 +1,220 @@ +key_hash = "0x1939099b0c6358168742dd5e2e345c109c4346da8e520bc442a858eb06c7b460" +verification_key = [ + "0x0931d596de2fd10f01ddd073fd5a90a976f169c76f039bb91c4775720042d43a", + "0x0000000000000000000000000000000000000000000000000000000000001000", + "0x0000000000000000000000000000000000000000000000000000000000000005", + "0x0000000000000000000000000000000000000000000000000000000000001000", + "0x0000000000000000000000000000000000000000000000000000000000000006", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000008a53e594e671a6e6d77ff9c6b5135cea39", + "0x0000000000000000000000000000000000151b70e854f3e8f6d458c30a106d01", + "0x00000000000000000000000000000021efa32514540d2da307174166fdddb179", + "0x00000000000000000000000000000000001ce6870edb43f749aa8b0a8e63079b", + "0x000000000000000000000000000000c1d4b2c1aa156280587a110bc2703867e5", + "0x00000000000000000000000000000000001605f4c36146e1d7074b295c5e8ca1", + "0x0000000000000000000000000000002cc8b81ee00bf0a75dc939b1f0c6258220", + "0x00000000000000000000000000000000002e5762c1dc4f0bef6d0757fee03ffd", + "0x000000000000000000000000000000b7cacaa0d00655537f88aaecb01bd7f0b1", + "0x00000000000000000000000000000000000d781738974257a5fd1a6d5e697819", + "0x0000000000000000000000000000007411693126f004a8cf79b5ac47649fbf61", + "0x0000000000000000000000000000000000156106eddc0992e7e55111f0426ccb", + "0x000000000000000000000000000000862c29a250c8a690fadd08b8e96c43209d", + "0x000000000000000000000000000000000021d66b813fd446f84dd11757a4b32b", + "0x000000000000000000000000000000142785f829d4c6153ea20309d442d2e59b", + "0x000000000000000000000000000000000025bf569fff3da03fc9a37b2476cf69", + "0x000000000000000000000000000000ecb1818e4bc7459d0c244fadca4b2c0956", + "0x000000000000000000000000000000000009a344d684bd4ef17ab10bb1b7ad4b", + "0x00000000000000000000000000000010594549cc125101118d827bf6cd63bb8e", + "0x00000000000000000000000000000000001573654173d271503c88c6d2ce595e", + "0x000000000000000000000000000000c45a4c9530ee5e33ab1662b84ac6226979", + "0x00000000000000000000000000000000000a2907d5730a7556ace2d09f119f64", + "0x000000000000000000000000000000eaba3886830bebde0de2c8775f8ddb7cc4", + "0x000000000000000000000000000000000017fd072fcd5f27fed699780f6083c8", + "0x000000000000000000000000000000a3449297df47762d0863e00eacf45de2ac", + "0x00000000000000000000000000000000001c52be3a44dd51953e206de861f071", + "0x000000000000000000000000000000b288c845d3f3cf18db53b1d351ed4131b1", + "0x000000000000000000000000000000000019b527f8adda61edb3e13a0567808c", + "0x0000000000000000000000000000006d8bad72170a3e61ff9d90bce5eedf3431", + "0x000000000000000000000000000000000008d9a4a0168326b6372b80620b371b", + "0x0000000000000000000000000000003365f289a10f47fd4de51005c6d53062e1", + "0x0000000000000000000000000000000000254edd290d49122bb29f5e4a887b99", + "0x000000000000000000000000000000e51e2e82380da3da5ad0f24e49e5f32208", + "0x000000000000000000000000000000000013982fd0cf8da5082a77561113bb5e", + "0x000000000000000000000000000000b0b25e9b4e4e04ad1280d1a264237717e0", + "0x00000000000000000000000000000000001aa5ffd5aa4c16d1c66e18c4574a3a", + "0x0000000000000000000000000000001ce018f20536fe45ca28dcc7b248389fc0", + "0x00000000000000000000000000000000001750f44d3f9dfad78a1e2127ef9105", + "0x000000000000000000000000000000164b49c0f27d4f5ac4550751cc0a24bb58", + "0x00000000000000000000000000000000001a05418f502a965c39994cd3f83e39", + "0x0000000000000000000000000000002742460b6256ea7a719b961136cfe75a61", + "0x0000000000000000000000000000000000031e061410bb9fb602421b4984b999", + "0x000000000000000000000000000000c7ce966f9f66486abd22add05dd95cdf0a", + "0x00000000000000000000000000000000001f3562276b5ecbcb50fdb203733f5a", + "0x00000000000000000000000000000080fe66c1cdb1d4adecb6ba8e210bc7af9a", + "0x00000000000000000000000000000000000bb280c69f2c0ed20330e48d92e905", + "0x000000000000000000000000000000fb6d06a1212ac3a75f24e9818a4bdc2c44", + "0x000000000000000000000000000000000011d2bce920dee1652e58b7757431fc", + "0x0000000000000000000000000000006d1215e9527e8f1efa260364726f896a3c", + "0x0000000000000000000000000000000000076375c96824d2f6244e13b455dea2", + "0x000000000000000000000000000000bd7df6dd302f2f5d77b66af046a5e85fca", + "0x00000000000000000000000000000000001413234ced6f0fd1e16d1a52b48099", + "0x000000000000000000000000000000b74fa6016a24e56e4432d24b1dc61f3816", + "0x00000000000000000000000000000000000b4e54114b5ed35fdb748a33c1b903", + "0x000000000000000000000000000000bc39dfbe1024e2ad8f51f258cbb9e1f8c2", + "0x0000000000000000000000000000000000084e664af4655a95bb626fa52c48d0", + "0x000000000000000000000000000000bcf43c285b1d1f7f85341f3615d25fe97b", + "0x0000000000000000000000000000000000259f452dc7fd2dda4013dba2196852", + "0x000000000000000000000000000000711e890a1c99a8f689419da8c52d2e8e9d", + "0x0000000000000000000000000000000000117500555dd886209c0b10ee8cd10e", + "0x000000000000000000000000000000a84fca32b13b92e520bb91a7455f78ccf1", + "0x00000000000000000000000000000000002577f542178a07dac262fdabad6f55", + "0x000000000000000000000000000000e12644a82ee1345497f8c0302e92925c68", + "0x00000000000000000000000000000000000fc87ae27122e60eaacc070bd59aaf", + "0x000000000000000000000000000000e5fe2c041687603b6577581d673d13be50", + "0x00000000000000000000000000000000001612f501335a4b72ac55dbe2fd1a75", + "0x00000000000000000000000000000070846e904bb7d1c7ff02f32823de6c1c71", + "0x0000000000000000000000000000000000160e8ef7ff5315cb640ec82e965db2", + "0x00000000000000000000000000000064007633f529476b2f169a0ff131bfb319", + "0x00000000000000000000000000000000002d540ff1653b38acbcb9cda3154423", + "0x000000000000000000000000000000713898655cc94a0ac2d84944c737cf57e5", + "0x00000000000000000000000000000000002198b9feb61f8160e357b8bb7ca329", + "0x000000000000000000000000000000ad74612e486596cbe7f7d6a05f19c69444", + "0x000000000000000000000000000000000011c8df52c3ef754f80d11792cea4b7", + "0x0000000000000000000000000000002ac2932f3bd1b6942b132546d2110a63e2", + "0x000000000000000000000000000000000010c8a36cbb2fd9ed8875b5106a3716", + "0x000000000000000000000000000000d561be06367518cc61f053277f35d50950", + "0x000000000000000000000000000000000007f30716678f071b5602899a18384e", + "0x000000000000000000000000000000415c00c5458c9c01f62f5896ee0e759551", + "0x000000000000000000000000000000000017696b6f3c43bf8f756e7dec1c56b7", + "0x0000000000000000000000000000001e5e19133c9f739f2a0c65cc9b0195db64", + "0x00000000000000000000000000000000002615ef74e1ba05d18eca28dc8e8153", + "0x0000000000000000000000000000001a5902cdc32e5c08e9e195dfa6186e0db2", + "0x0000000000000000000000000000000000141fa9a66a268079f54f507fb9278d", + "0x0000000000000000000000000000007df5a99f2f067ac783f41c30407a11bc57", + "0x00000000000000000000000000000000001a7b871268398a5d5041a9c33da69f", + "0x000000000000000000000000000000ff76114fa735ebb2c41223d645347a68aa", + "0x0000000000000000000000000000000000053b8868e18be2ad087c57c2313d24", + "0x000000000000000000000000000000a7da5a3c0c2539d1661d378df8677c3703", + "0x000000000000000000000000000000000020472758b9cd81a7b7bd8b9c5af023", + "0x000000000000000000000000000000077167a922c9e9196d4d757f62d4c2c6d5", + "0x000000000000000000000000000000000029dabd0bbbd62f5e32a5708942d78b", +] +proof = [ + "0x000000000000000000000000000000ffe6a3faeab0e6b47bae13b6b458673b39", + "0x000000000000000000000000000000000002a3a47c78630cac46a5873e40f9fc", + "0x000000000000000000000000000000c620a8ef8e50d1dc38be685ef81610bb31", + "0x00000000000000000000000000000000000e9f153f828c4ffa59582617aa414f", + "0x00000000000000000000000000000070d6e9ce1f51e6c0f6d79b2f05a85086fe", + "0x000000000000000000000000000000000016fe53eef68c854979f917fc8543ef", + "0x00000000000000000000000000000077df2b180263cda0c11b2526753fbc5113", + "0x000000000000000000000000000000000010a45dcecd8665b11e0feb1a016752", + "0x000000000000000000000000000000fde1d7bf4586c2dea84e0fd3c4749e85da", + "0x00000000000000000000000000000000001e964724eecb49a2c4c977b171f621", + "0x000000000000000000000000000000a1bc166fba42431472cca276848902aa59", + "0x00000000000000000000000000000000001fd1f0788c232b7167b62e3fb9dc8d", + "0x000000000000000000000000000000edd55fda49ec343f74911249d4e5b7277e", + "0x0000000000000000000000000000000000212861172970cd83d2368d7517d9e6", + "0x000000000000000000000000000000694235eacf2d268d73d6f9e93f9399aefa", + "0x000000000000000000000000000000000026ff3475e16c1a0d8a4a1287e964f5", + "0x0000000000000000000000000000007404aabe486cfee82b7b80e6853c5befd1", + "0x0000000000000000000000000000000000064217c553fc0384b69935f1e28bfb", + "0x0000000000000000000000000000006935e7c2569e56d2d965e059bc2de9ba50", + "0x000000000000000000000000000000000004ef4b741a0bf95b30c5d84b932f71", + "0x00000000000000000000000000000001e64bd993ad0e54997b2874888e62d3cb", + "0x00000000000000000000000000000000001484355d065513aaf53a4aab0028be", + "0x000000000000000000000000000000d6f0b07e239d22263d71312a19472c8879", + "0x00000000000000000000000000000000001199a51cb90df845471ffc26ebd37f", + "0x0000000000000000000000000000009064ae4a34a3b39afde2af10cede70e523", + "0x000000000000000000000000000000000009f74cd7975b5b94457de10327a0ad", + "0x00000000000000000000000000000075ec30f533a8d4dd4e5f948c9321417efe", + "0x0000000000000000000000000000000000152dcba55ee943e31f1c740aa8ab5f", + "0x000000000000000000000000000000092abd9a18c7ef09049a0eca5e70c3f325", + "0x00000000000000000000000000000000001d1193d9df1eceacb6c3e64d44a9e8", + "0x000000000000000000000000000000b3af42695e437b5612057795ac8d4089e0", + "0x00000000000000000000000000000000002f79863c94a0bd45627708734f4119", + "0x000000000000000000000000000000b1760e508b6a4becbcfc39422002e42e50", + "0x00000000000000000000000000000000001891b367db22bed6e7913d12e6cb25", + "0x00000000000000000000000000000082ab0fc97ecbe49c63ce1216cebea95f6d", + "0x00000000000000000000000000000000000b7fbf49b6c3cfffccdc56cc1cabf0", + "0x000000000000000000000000000000edce8ade1da64f33baff12fb77510dd2a1", + "0x0000000000000000000000000000000000204fd20ceb166be676c026e3cbe574", + "0x000000000000000000000000000000a0e216a3916bc367785024b797be024c8c", + "0x0000000000000000000000000000000000233a1b6419f48ebb4319a34047da48", + "0x000000000000000000000000000000d316e7a499ebe5b53e3f1d07b8bd5a3271", + "0x0000000000000000000000000000000000105d2541853ef565f2d369e873718f", + "0x00000000000000000000000000000021b1e2a824c87ba6a6121bb45d4e8e752c", + "0x0000000000000000000000000000000000197c1474600601b94d624e989f1305", + "0x0ae9d0274e0342377db903f726e33cf267bb297064fc747a8d33d97b0be1089d", + "0x270d79929360a7174a55785bc6f20c2cf96085d64f6e9af9f218812b0b8bc6d1", + "0x2cc5b28b2e1a54b888bf4c871570e51ca48da044662a02abf256276e857f167c", + "0x24fb6d9a20631b516c7db342ddf395d16a02f54edfdad845771d0f28246dd256", + "0x26ff0505dea97875e2ab7f5f661d98a3e53d0704fd7760938fa101ba07a4d605", + "0x0fc68642f4f82a601afb0c241c7048b362fe225268efff62cea6f78eaff6ac0c", + "0x1c4087d0caca542851fa3d17f801aeed806ef6c56b23d180d4d9da423d917604", + "0x27268dbb6d3fe023db0f68adee281fae77603b3d011779612b157990de2218c7", + "0x0f0939b8a791fd991036d4058594f68b0088d58be1fe7fb9c3c3b84888ea763d", + "0x0f46f40de4ca9765a70676c943e2abe48bb87a85d68f71cd2004d8ae0c80db47", + "0x17ab46f9bfea7f0bdd4f9d4c43e632dd359757f421f756e49ef9ac5ab5873790", + "0x05822bc3646b7782875214719bc515d958415ce97f0d42f56b425fb90457484a", + "0x28e6fb315750c7994faef1d6bae82f29ba07d0d009b70a3c782dbbb84d8f7de6", + "0x29142b8b429a853b1b0d2488254f312849bb6874176f12c7a84eafb78b60dcf3", + "0x1d9d5ea469b913a9ee9693f7fe61a18320de6b73eb33cce8c13e9b4d81f787c5", + "0x2c27d8f5de87fe914f0401b2fc84597d64e516e105163871284a13bab616e4f1", + "0x20ee6523c8a301e8e177eaa67ba0d43362b45a3732691930dd3fe081b335e1ef", + "0x0483aa5c924d6d26777503fe08072fa0a924dc8d3897ce04e383fb98d4c74fc8", + "0x0e39416264025c9dd217f52bd31671a9a1afd7d249ac6e8a38b5fa33cf6b781a", + "0x1b02d3013eaca93794302b7f59abc080b031599b62088babad2381b2f6495ed7", + "0x1fec45f5b584c0ab50be3deabd17f77e4813d3586eadfce5ac0e62f02cdc8c1b", + "0x0a7b7d7f9cd90898065fbc8d79d9c99f5e52e0e38d0edab0472b7a0fad73dbeb", + "0x2fa658206825ac195123eb377a779cb284560c82341b2c0140033c6a9a92d8ea", + "0x246ce44e5240af70e397d42af994176882254fd8616e0cc0f4f9093197b1d5e8", + "0x1933707c3c5bb2c8760bbd1e78b0921e7ff4932e8ec0ed80a9eed5f894d0d2e6", + "0x15b4f151b2be054073ebd399fabd4ee960839d8d5fbbf9f09235ad48b054deed", + "0x0b2cf12f80cdfb9d2af169d5297736a0f3a3961ef5d6db5c42e427abcbe48b77", + "0x1723a07d5c044a2ae351be2ea453a8b98ab31d01e3e5709064c6b7ee207e9b18", + "0x1d019fdbae08030bf1bfcdb6480e2e2713625fb52c3f112250d97d69796f9a3a", + "0x07f32913cec9762fbb1d40a58e31cbfba270b6954c13d7e3758236a659cc88b0", + "0x28acfcf8135755bcee5969e6af9e7c1a6927eba4ecb555a6fd19b81c298627d2", + "0x2acd35a4af19adaa7ffedd540a63bcf6955b14337bfa9dd778cf2a90a3e591ad", + "0x1dcf0195851f05408d3af9cea867439b123fa9e92373e9ff3cc92114484ed18a", + "0x033ec79aca516bd68d3aee25ee69a7976e62b86e628705b1e1c33fa8142460bd", + "0x10073995b534512584f626172327b16b43b8879f9947bfb3bbe6ea7792f6e0af", + "0x1081fb975332f3f8dfdd26fef63b073269e5f9d9654583ad68cebdc84a12b8b6", + "0x2f299621bc76aed315629203de0bb2d0e3efab301631edd3fbcfdcb2187a836b", + "0x2b2c79a0bb448991c471587934512cb61ca48c1e0be2cf92e18c4a76993a5291", + "0x0a7a48ed4ca50793f53e963a6ce198d4c0e0a994dc3ff71cd6c3d87c31ff2ec7", + "0x1a2c66acbf3725bfde5c19b226f35d508d50af5426568f380fdd5c15bac40afe", + "0x29de846c31c943ebc7799d29e10521cc59c0b513706d275348f6dfaf4388e735", + "0x000000000000000000000000000000ffc873d9233f079fe64c7465b1825ccfde", + "0x0000000000000000000000000000000000094539950a88497e965fe2813be07d", + "0x0000000000000000000000000000003b088473d29e8c48747e7946ff5f532170", + "0x0000000000000000000000000000000000042f3dd4fab6ec4151874eb83eb6e7", + "0x00000000000000000000000000000026f67db76d755b7cd9ea90266a7a87d51a", + "0x000000000000000000000000000000000021a8c2009e075faa62e8ca2e9ddd0e", + "0x00000000000000000000000000000046af9427f2f92276bd4922ceb6026dec59", + "0x000000000000000000000000000000000009f7e0ceada729e43a8617e1af08d1", +] +public_inputs = [ + "0x21cd742a799cbe15b2e7a4641120f803a3c31b11f610a59046d880cf3d282c83", + "0x2ed5b94a8af2550139982907f04523f711c8df4fefc44190ca5bdba08793cfd2", + "0x164377fa253ee407efc1b5e19706dde2d5d3e582f082fa38ad5529b79533a835", + "0x28e54d0e40cded1696e63822594863b1ec91e54c045687cfe9fa6bbc17f21336", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] diff --git a/noir/agg_utxo/Verifier.toml b/noir/agg_utxo/Verifier.toml new file mode 100644 index 0000000..b71a430 --- /dev/null +++ b/noir/agg_utxo/Verifier.toml @@ -0,0 +1,8 @@ +public_inputs = [ + "0x21cd742a799cbe15b2e7a4641120f803a3c31b11f610a59046d880cf3d282c83", + "0x2ed5b94a8af2550139982907f04523f711c8df4fefc44190ca5bdba08793cfd2", + "0x164377fa253ee407efc1b5e19706dde2d5d3e582f082fa38ad5529b79533a835", + "0x28e54d0e40cded1696e63822594863b1ec91e54c045687cfe9fa6bbc17f21336", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", +] diff --git a/noir/agg_utxo/src/main.nr b/noir/agg_utxo/src/main.nr new file mode 100644 index 0000000..8eb9bf9 --- /dev/null +++ b/noir/agg_utxo/src/main.nr @@ -0,0 +1,216 @@ +use dep::std; +use poseidon::poseidon2; + +global UTXO_VERIFICATION_KEY_HASH: Field = 20361994226032552507663901262286744551869524558436762371297713593361795171294; + +struct AggUtxoProofInput { + proof: [Field; 508], + utxo_kind: Field, + input_merkle_paths: [[Field; 160]; 2], + output_merkle_paths: [[Field; 160]; 2], + input_commitments: [Field; 2], + output_commitments: [Field; 2], +} + +fn main( + verification_key: [Field; 115], + proofs: [AggUtxoProofInput; 3], + // TODO: maybe we can remove this + verification_key_hash: pub [Field; 2], + old_root: pub Field, + new_root: pub Field, + commit_hash: pub Field, + messages: pub [Field; 1000], +) { + // Hardcode verification_key_hash for utxo proof + assert(verification_key_hash[0] != 0, "dummy verfication key hash"); + assert(verification_key_hash[1] != 0, "dummy verfication key hash"); + + let mut root = old_root; + let mut utxo_hashes: [Field; 3] = [0, 0, 0]; + let mut messages_index = 0; + + let mut first_public_inputs: [Field; 9] = [0; 9]; + for i in 0..3 { + let proof = proofs[i]; + let input_commitments = proof.input_commitments; + let output_commitments = proof.output_commitments; + + let utxo_kind = proof.utxo_kind; + let is_padding = utxo_kind == 0; + let is_burn = utxo_kind == 3; + let is_mint = utxo_kind == 2; + let is_proof_kind_mint_or_burn = is_burn | is_mint; + + let mut msg_note_kind = 0; + let mut msg_value = 0; + let mut msg_hash = 0; + let mut msg_burn_addr = 0; + + if is_proof_kind_mint_or_burn { + assert(messages[messages_index] == utxo_kind, "proof 'kind' must match message"); + msg_note_kind = messages[messages_index + 1]; + msg_value = messages[messages_index + 2]; + msg_hash = messages[messages_index + 3]; + messages_index += 4; + } + + if is_burn { + msg_burn_addr = messages[messages_index]; + messages_index += 1; + } + + utxo_hashes[i] = poseidon2::Poseidon2::hash( + [ + input_commitments[0], + input_commitments[1], + output_commitments[0], + output_commitments[1], + ], + 4, + ); + + // Verify non-padding proofs + let public_inputs = [ + input_commitments[0], + input_commitments[1], + output_commitments[0], + output_commitments[1], + utxo_kind, + msg_note_kind, + msg_value, + msg_hash, + msg_burn_addr, + ]; + + // Capture the public_inputs on first iter + if (i == 0) { + // First proof must ALWAYS be a real proof + assert(!is_padding, "first proof cannot be a padding proof"); + // and we will use that proof + first_public_inputs = public_inputs; + } + + // Due to a limitation in noir, verify_proof_with_type will ALWAYS + // be run regardless of whether its inside an if statement, so we need + // to form a valid proof. As first proof cannot be a dummy proof, we can + // use the first proof for padding elements + std::verify_proof_with_type( + verification_key, + if (is_padding) { + proofs[0].proof + } else { + proof.proof + }, + if (is_padding) { + first_public_inputs + } else { + public_inputs + }, + UTXO_VERIFICATION_KEY_HASH, + 7, + ); + + if (!is_padding) { + // Input commitments + for j in 0..2 { + let commitment = input_commitments[j]; + + if commitment != 0 { + let bits: [u1; 254] = commitment.to_le_bits(); + let merkle_path = proof.input_merkle_paths[j]; + + // Check it exists in the old tree + validate_inclusion(commitment, bits, merkle_path, root); + + // Calculate new root without the input commitment + root = get_null_root(bits, merkle_path); + } + } + + // Output commitments + for j in 0..2 { + let commitment = output_commitments[j]; + + if commitment != 0 { + let bits: [u1; 254] = commitment.to_le_bits(); + let merkle_path = proof.output_merkle_paths[j]; + + // Checks the merkle path leads to the existing root + validate_null(bits, merkle_path, root); + + // Calculate new root with added output commitments + root = get_merkle_root(commitment, bits, merkle_path); + } + } + } + } + + // Verify all other messages are zero + for i in 0..messages.len() { + if i >= messages_index { + assert(messages[i] == 0, "Message is not zero"); + } + } + + assert(root == new_root, "New root is not valid"); + assert(commit_hash == poseidon2::Poseidon2::hash(utxo_hashes, 3)); +} + +fn validate_inclusion(leaf: Field, bits: [u1; 254], merkle_path: [Field; 160], root: Field) { + let merkle_root = get_merkle_root(leaf, bits, merkle_path); + assert(merkle_root == root, "Merkle path root does not match"); +} + +fn validate_null(bits: [u1; 254], merkle_path: [Field; 160], root: Field) { + let merkle_root = get_null_root(bits, merkle_path); + assert(merkle_root == root, "Merkle path root does not match"); +} + +fn get_null_root(bits: [u1; 254], merkle_path: [Field; 160]) -> Field { + get_merkle_root(0, bits, merkle_path) +} + +fn get_merkle_root(leaf: Field, bits: [u1; 254], merkle_path: [Field; 160]) -> Field { + let mut hash = leaf; + for i in 0..160 { + let dir = bits[i]; + let sibling = merkle_path[i]; + if dir == 0 { + hash = poseidon2::Poseidon2::hash([hash, sibling], 2); + } else { + hash = poseidon2::Poseidon2::hash([sibling, hash], 2); + } + } + hash +} + +#[test] +fn empty_tree() { + let mut hash = 0; + for _ in 0..160 { + hash = poseidon2::Poseidon2::hash([hash, hash], 2); + } + println("empty root hash:"); + println(hash); + assert(hash == 2473073130432999597457871252851154814051443713747864452328961082127445883391); +} + +#[test] +fn test_merkle_path_operations() { + // Test basic merkle path operations + let leaf: Field = 12345; + let bits: [u1; 254] = leaf.to_le_bits(); + let merkle_path = [0; 160]; + + // Test get_merkle_root + let root = get_merkle_root(leaf, bits, merkle_path); + assert(root != 0); + + // Test get_null_root (should be different from leaf root) + let null_root = get_null_root(bits, merkle_path); + assert(null_root != root); + + // Test validate_inclusion + validate_inclusion(leaf, bits, merkle_path, root); +} diff --git a/noir/common/Nargo.toml b/noir/common/Nargo.toml new file mode 100644 index 0000000..d36fcd9 --- /dev/null +++ b/noir/common/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "common" +type = "lib" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/common/src/bytes.nr b/noir/common/src/bytes.nr new file mode 100644 index 0000000..0b9e3b1 --- /dev/null +++ b/noir/common/src/bytes.nr @@ -0,0 +1,9 @@ +pub fn slice(bytes: [u8; N], start: u32) -> [u8; L] { + let end = start + L; + assert(end <= N, "slice: slice end out of bounds"); + let mut result = [bytes[0]; L]; + for i in 0..L { + result[i] = bytes[start + i]; + } + result +} diff --git a/noir/common/src/field_utils.nr b/noir/common/src/field_utils.nr new file mode 100644 index 0000000..980f14e --- /dev/null +++ b/noir/common/src/field_utils.nr @@ -0,0 +1,20 @@ +pub fn field_from_bytes(bytes: [u8; N]) -> Field { + assert(bytes.len() < 32, "field_from_bytes: N must be less than 32"); + let mut as_field = 0; + let mut offset = 1; + for i in 0..N { + as_field += (bytes[i] as Field) * offset; + offset *= 256; + } + as_field +} + +pub fn is_one_of(value: Field, one_of: [Field]) -> bool { + let mut is_one_of = false; + for possible in one_of { + if possible == value { + is_one_of = true; + } + } + is_one_of +} diff --git a/noir/common/src/lib.nr b/noir/common/src/lib.nr new file mode 100644 index 0000000..e7d1c06 --- /dev/null +++ b/noir/common/src/lib.nr @@ -0,0 +1,30 @@ +mod bytes; +mod field_utils; +mod merkle_path; +mod note; +mod utxo; + +pub type Address = [u8; 20]; + +pub struct Note { + pub kind: Field, + pub value: Field, + pub address: Field, + pub psi: Field, +} + +pub struct InputNote { + pub note: Note, + pub secret_key: Field, +} + +pub struct MerklePath { + pub path: [Field; 160], +} + +pub use bytes::slice; +pub use field_utils::{field_from_bytes, is_one_of}; +pub use note::{ + check_commitment, check_input_note_ownership, get_address, get_note_commitment, is_multiple_kinds, +}; +pub use utxo::Utxo; diff --git a/noir/common/src/merkle_path.nr b/noir/common/src/merkle_path.nr new file mode 100644 index 0000000..2abfede --- /dev/null +++ b/noir/common/src/merkle_path.nr @@ -0,0 +1,23 @@ +use poseidon::poseidon2; +use crate::MerklePath; + +impl MerklePath { + pub fn root_from_leaf(self, leaf: Field) -> Field { + let bits: [u1; 254] = leaf.to_le_bits(); + let mut hash = leaf; + for i in 0..160 { + let sibling = self.path[i]; + if bits[i] == 0 { + hash = poseidon2::Poseidon2::hash([hash, sibling], 2); + } else { + hash = poseidon2::Poseidon2::hash([sibling, hash], 2); + } + } + + hash + } + + pub fn validate(self, leaf: Field, root: Field) -> bool { + self.root_from_leaf(leaf) == root + } +} diff --git a/noir/common/src/note.nr b/noir/common/src/note.nr new file mode 100644 index 0000000..ba39300 --- /dev/null +++ b/noir/common/src/note.nr @@ -0,0 +1,50 @@ +use poseidon::poseidon2; +use crate::{InputNote, Note}; + +pub fn check_commitment(note: Note, commitment: Field) { + assert(get_note_commitment(note) == commitment, "Note commitment is not valid"); +} + +pub fn get_note_commitment(note: Note) -> Field { + if (note.kind == 0) { + assert(note.value == 0, "Padding notes must be zero value"); + 0 + } else { + poseidon2::Poseidon2::hash( + [0x2, note.kind, note.value, note.address, note.psi, 0, 0], + 7, + ) + } +} + +pub fn get_address(secret_key: Field) -> Field { + poseidon2::Poseidon2::hash([secret_key, 0], 2) +} + +pub fn check_input_note_ownership(input_note: InputNote) { + if (input_note.note.value != 0) { + assert( + get_address(input_note.secret_key) == input_note.note.address, + "Input note is not owned by the owner", + ); + } +} + +pub fn is_multiple_kinds(notes: [Note; 4]) -> (bool, Field) { + let mut first_non_zero_kind = 0; + let mut is_multiple_kinds = false; + + for i in 0..4 { + if !is_multiple_kinds { + if notes[i].kind != 0 { + if first_non_zero_kind == 0 { + first_non_zero_kind = notes[i].kind; + } else if first_non_zero_kind != notes[i].kind { + is_multiple_kinds = true; + } + } + } + } + + (is_multiple_kinds, first_non_zero_kind) +} diff --git a/noir/common/src/utxo.nr b/noir/common/src/utxo.nr new file mode 100644 index 0000000..103fbd5 --- /dev/null +++ b/noir/common/src/utxo.nr @@ -0,0 +1,66 @@ +use poseidon::poseidon2; +use crate::note::{check_input_note_ownership, get_note_commitment, is_multiple_kinds}; +use crate::{InputNote, MerklePath, Note}; + +pub struct Utxo { + pub input_notes: [InputNote; 2], + pub output_notes: [Note; 2], + pub input_merkle_paths: [MerklePath; 2], +} + +impl Utxo { + pub fn validate( + self, + recent_root: Field, + input_nullifiers: [Field; 2], + output_commitments: [Field; 2], + ) { + let input_commitments = [ + get_note_commitment(self.input_notes[0].note), + get_note_commitment(self.input_notes[1].note), + ]; + let computed_output_commitments = [ + get_note_commitment(self.output_notes[0]), + get_note_commitment(self.output_notes[1]), + ]; + + assert(output_commitments[0] == computed_output_commitments[0], "Invalid output commitment 0"); + assert(output_commitments[1] == computed_output_commitments[1], "Invalid output commitment 1"); + + assert( + input_nullifiers[0] == expected_nullifier(self.input_notes[0].note, input_commitments[0]), + "Invalid nullifier 0", + ); + assert( + input_nullifiers[1] == expected_nullifier(self.input_notes[1].note, input_commitments[1]), + "Invalid nullifier 1", + ); + + self.output_notes[0].value.assert_max_bit_size::<240>(); + self.output_notes[1].value.assert_max_bit_size::<240>(); + + verify_input_membership(input_commitments[0], self.input_merkle_paths[0], recent_root); + verify_input_membership(input_commitments[1], self.input_merkle_paths[1], recent_root); + + check_input_note_ownership(self.input_notes[0]); + check_input_note_ownership(self.input_notes[1]); + + let (is_multiple_kinds, _) = is_multiple_kinds([ + self.input_notes[0].note, + self.input_notes[1].note, + self.output_notes[0], + self.output_notes[1], + ]); + assert(!is_multiple_kinds, "Inconsistent kinds are not allowed"); + } +} + +fn expected_nullifier(note: Note, commitment: Field) -> Field { + if commitment == 0 { 0 } else { poseidon2::Poseidon2::hash([commitment, note.psi], 2) } +} + +fn verify_input_membership(commitment: Field, merkle_path: MerklePath, recent_root: Field) { + if commitment != 0 { + assert(merkle_path.validate(commitment, recent_root), "Input commitment is not in recent root"); + } +} diff --git a/noir/evm/burn/Nargo.toml b/noir/evm/burn/Nargo.toml new file mode 100644 index 0000000..d3ab004 --- /dev/null +++ b/noir/evm/burn/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "burn" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] +common = { path = "../../common" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/evm/burn/src/main.nr b/noir/evm/burn/src/main.nr new file mode 100644 index 0000000..e71cfe4 --- /dev/null +++ b/noir/evm/burn/src/main.nr @@ -0,0 +1,100 @@ +use common::{get_note_commitment, InputNote, MerklePath, Note, Utxo}; +use poseidon::poseidon2; + +fn main( + utxo: Utxo, + burn_recipient_private: Field, + recent_root: pub Field, + input_nullifiers: pub [Field; 2], + output_commitments: pub [Field; 2], + burn_recipient_public: pub Field, + burn_value: pub Field, +) { + burn_value.assert_max_bit_size::<240>(); + + let input_value = utxo.input_notes[0].note.value + utxo.input_notes[1].note.value; + let output_value = utxo.output_notes[0].value + utxo.output_notes[1].value; + assert(input_value == output_value + burn_value, "Burn output must match burn value"); + + assert( + burn_recipient_private == burn_recipient_public, + "Burn recipient private/public mismatch", + ); + + utxo.validate(recent_root, input_nullifiers, output_commitments); +} + +#[test] +fn test_burn_one_input_one_output() { + let pk: Field = 101; + let address = common::get_address(pk); + let burn_recipient = 77; + + let note_1 = Note { kind: 1, value: 10, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + let note_3 = Note { kind: 1, value: 4, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + + let input_commitment_1 = get_note_commitment(note_1); + let output_commitment_1 = get_note_commitment(note_3); + let output_commitment_2 = get_note_commitment(note_4); + + let input_path_1 = MerklePath { path: [0; 160] }; + let input_path_2 = MerklePath { path: [0; 160] }; + let recent_root = input_path_1.root_from_leaf(input_commitment_1); + let utxo = Utxo { + input_notes: [input_note_1, input_note_2], + output_notes: [note_3, note_4], + input_merkle_paths: [input_path_1, input_path_2], + }; + + main( + utxo, + burn_recipient, + recent_root, + [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0], + [output_commitment_1, output_commitment_2], + burn_recipient, + 6, + ); +} + +#[test(should_fail)] +fn test_burn_rejects_bad_recipient_binding() { + let pk: Field = 101; + let address = common::get_address(pk); + + let note_1 = Note { kind: 1, value: 10, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + let note_3 = Note { kind: 1, value: 4, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + + let input_commitment_1 = get_note_commitment(note_1); + let output_commitment_1 = get_note_commitment(note_3); + let output_commitment_2 = get_note_commitment(note_4); + + let input_path_1 = MerklePath { path: [0; 160] }; + let input_path_2 = MerklePath { path: [0; 160] }; + let recent_root = input_path_1.root_from_leaf(input_commitment_1); + let utxo = Utxo { + input_notes: [input_note_1, input_note_2], + output_notes: [note_3, note_4], + input_merkle_paths: [input_path_1, input_path_2], + }; + + main( + utxo, + 77, + recent_root, + [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0], + [output_commitment_1, output_commitment_2], + 88, + 6, + ); +} diff --git a/noir/evm/erc20_transfer/Nargo.toml b/noir/evm/erc20_transfer/Nargo.toml new file mode 100644 index 0000000..9c67124 --- /dev/null +++ b/noir/evm/erc20_transfer/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "erc20_transfer" +type = "bin" +authors = [""] + +[dependencies] +common = { path = "../../common" } +keccak256 = { tag = "v0.1.2", git = "https://github.com/noir-lang/keccak256" } +poseidon = { tag = "v0.2.3", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/evm/erc20_transfer/src/eip1559transaction.nr b/noir/evm/erc20_transfer/src/eip1559transaction.nr new file mode 100644 index 0000000..4b2ba6e --- /dev/null +++ b/noir/evm/erc20_transfer/src/eip1559transaction.nr @@ -0,0 +1,140 @@ +use common::Address; + +/// Represents an unsigned Ethereum EIP-1559 (type-2) transaction +pub struct Type2Transaction { + pub chain_id: u64, + pub nonce: u64, + pub max_priority_fee_per_gas: u128, + pub max_fee_per_gas: u128, + pub gas_limit: u64, + pub to: Address, + pub value: u128, + pub data: [u8; N], +} + +impl Type2Transaction { + pub fn hash(self) -> [u8; 32] { + let (encoded, len) = self.rlp_encode(); + keccak256::keccak256(encoded, len) + } + + /// RLP encode the transaction for hashing + fn rlp_encode(self) -> ([u8; 256], u32) { + let mut encoded = [0u8; 256]; + + encoded[0] = 0x02; // transaction type 2 + encoded[1] = 0xf8; // 55 < length of payload <= 255 + // payload length is written to encoded[2] at the end + + let mut offset = 3; + + offset = rlp_append_u64(&mut encoded, offset, self.chain_id); + offset = rlp_append_u64(&mut encoded, offset, self.nonce); + offset = rlp_append_u128(&mut encoded, offset, self.max_priority_fee_per_gas); + offset = rlp_append_u128(&mut encoded, offset, self.max_fee_per_gas); + offset = rlp_append_u64(&mut encoded, offset, self.gas_limit); + + encoded[offset] = 0x94; + offset += 1; + for i in 0..20 { + encoded[offset + i] = self.to[i]; + } + offset += 20; + + offset = rlp_append_u128(&mut encoded, offset, self.value); + + encoded[offset] = 0xb8; + assert((55 < DATA_LEN) & (DATA_LEN <= 255), "Calldata length outside supported range"); + encoded[offset + 1] = DATA_LEN as u8; + offset += 2; + for i in 0..DATA_LEN { + encoded[offset + i] = self.data[i]; + } + offset += DATA_LEN; + + encoded[offset] = 0xc0; + offset += 1; + + let payload_len = offset - 3; + assert((55 < payload_len) & (payload_len <= 255), "Payload length outside supported range"); + encoded[2] = payload_len as u8; + + (encoded, offset) + } +} + +fn rlp_append_u64(out: &mut [u8; N], offset: u32, value: u64) -> u32 { + if (value != 0) & (value < 0x80) { + out[offset] = value as u8; + offset + 1 + } else { + let mut bytes = (value as Field).to_be_bytes::<8>(); + rlp_append_integer(out, offset, bytes) + } +} + +fn rlp_append_u128(out: &mut [u8; N], offset: u32, value: u128) -> u32 { + if (value != 0) & (value < 0x80) { + out[offset] = value as u8; + offset + 1 + } else { + let mut bytes = (value as Field).to_be_bytes::<16>(); + rlp_append_integer(out, offset, bytes) + } +} + +fn rlp_append_integer(out: &mut [u8; N], offset: u32, value: [u8; M]) -> u32 { + let mut next_offset = offset + 1; + let mut found = false; + for i in 0..M { + if value[i] != 0 { + found = true; + } + if found { + out[next_offset] = value[i]; + next_offset += 1; + } + } + + let len = next_offset - offset - 1; + out[offset] = 0x80 + (len as u8); + + next_offset +} + +#[test] +fn rlp_encoding() { + let mut data = [0u8; 68]; + data[0] = 0x12; + data[1] = 0x34; + data[2] = 0x56; + data[3] = 0x78; + + for i in 0..32 { + data[4 + i] = 0x11; + data[36 + i] = 0x22; + } + + let tx = Type2Transaction { + chain_id: 1, + nonce: 0, + max_priority_fee_per_gas: 2000000000, + max_fee_per_gas: 100000000000, + gas_limit: 21000, + to: [0x11; 20], + value: 0, + data, + }; + + let (encoded, len) = tx.rlp_encode(); + + let expected: [u8; 112] = [0x02, 0xf8, 0x6d, 0x01, 0x80, 0x84, 0x77, 0x35, 0x94, 0x00, 0x85, 0x17, 0x48, 0x76, 0xe8, 0x00, 0x82, 0x52, 0x08, 0x94, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x80, 0xb8, 0x44, 0x12, 0x34, 0x56, 0x78, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0xc0]; + + for i in 0..expected.len() { + let correct = expected[i]; + let test = encoded[i]; + assert(test == correct, f"byte {i} is {test} but should be {correct}") + } + + assert(len == expected.len(), f"Unexpected length {len}"); +} diff --git a/noir/evm/erc20_transfer/src/main.nr b/noir/evm/erc20_transfer/src/main.nr new file mode 100644 index 0000000..9e1024d --- /dev/null +++ b/noir/evm/erc20_transfer/src/main.nr @@ -0,0 +1,159 @@ +mod eip1559transaction; +mod signature; + +use eip1559transaction::Type2Transaction; +use common::{Address, MerklePath}; +use poseidon::poseidon2::Poseidon2; +use signature::Signature; + +/// We use Poseidon hashes that operate on the field we use for proving +type Hash = Field; + +pub struct Note { + pub kind: Field, + pub address: Address, + pub token: Address, + pub value: Field, + pub psi: Field, +} + +impl Note { + pub fn hash(self) -> Field { + Poseidon2::hash( + [ + self.kind, + Field::from_be_bytes(self.address), + Field::from_be_bytes(self.token), + self.value, + self.psi, + ], + 5, + ) + } +} + +/// Shows that somewhere in the Merkle tree represented by `input_note_merkle_root`, +/// there are notes belonging to an account that has signed an ERC-20 transfer. +/// Specifically, the notes are sufficient to pay for that transfer, output_notes[1] +/// is a note for the recipient and output_notes[0] holds any leftover change. +/// +/// The consumer of the proof should +/// - add `new_commitments` to the Merkle tree so it is +/// possible to use the output notes in the future. +/// - ensure that `new_nullifiers` haven't been seen before and +/// aren't identical! They are the only mechanism preventing double spend. +/// - check that chain_id and bridge_address to prevent cross-chain replay attacks. +fn main( + // Needed to prevent cross-chain or cross-contract attacks + chain_id: pub u64, + bridge_address: pub Field, + // Ethereum transaction + original_transfer: ERC20Transfer, + signature: Signature, + // Input notes + input_notes: [Note; 2], + input_note_merkle_proofs: [MerklePath; 2], + input_note_merkle_root: pub Hash, + new_nullifiers: pub [Hash; 3], + // Output notes + output_notes: [Note; 2], + new_commitments: pub [Hash; 2], +) { + let transaction_hash = original_transfer.hash(); + assert(signature.matches_transaction_hash(transaction_hash), "Invalid signature"); + let sender = signature.sender_address(); + + // The same transaction must not be used twice to prevent replay attacks or accidents + // This prevents cross-chain use of the same signed transaction + assert(chain_id == original_transfer.chain_id); + // We cannot prevent cross-contract use of the same transaction, as it cannot + // indicate what bridge to use but at least we can make the proof valid only for one. + // The signature's r is a random number, so it is perfect for building the nullifier. + // s would be a poor choice because if (r, s) is a valid signature, (r, -s) is, too. + assert( + new_nullifiers[2] + == Poseidon2::hash( + [Field::from_be_bytes(signature.r), Field::from(chain_id), bridge_address], + 3, + ), + ); + + for i in 0..input_notes.len() { + let note = input_notes[i]; + assert(note.address == sender); + assert(note.token == original_transfer.token_address); + + let commitment = note.hash(); + assert(input_note_merkle_proofs[i].validate(commitment, input_note_merkle_root)); + + // TODO(ENG-6670) is hashing with psi a good way to build the nullifier? + let nullifier = Poseidon2::hash([commitment, note.psi], 2); + assert(new_nullifiers[i] == nullifier) + // The PrivacyBridge is responsible for checking that the nullifiers do not already exist + } + + for i in 0..output_notes.len() { + let note = output_notes[i]; + assert(note.token == original_transfer.token_address); + + let commitment = note.hash(); + assert(new_commitments[i] == commitment); + } + + // This addition can overflow but that means the sender loses money + let value_in = input_notes[0].value + input_notes[1].value; + + // The first output note is for the sender's leftover tokens + assert(output_notes[0].address == sender); + assert(!value_in.lt(original_transfer.amount), "Not enough funds for transfer"); + assert(output_notes[0].value == value_in - original_transfer.amount); + + // The second one is for the receiver + assert(output_notes[1].address == original_transfer.receiver); + assert(output_notes[1].value == original_transfer.amount); +} + +/// Parsed EIP-1559 transaction that calls ERC-20.transfer +pub struct ERC20Transfer { + chain_id: u64, + nonce: u64, + max_priority_fee_per_gas: u128, + max_fee_per_gas: u128, + gas_limit: u64, + + token_address: Address, + receiver: Address, + amount: Field, +} + +impl ERC20Transfer { + fn hash(self) -> [u8; 32] { + let Self { + chain_id, + nonce, + max_priority_fee_per_gas, + max_fee_per_gas, + gas_limit, + token_address, + receiver, + amount, + } = self; + + // selector for transfer(address,uint256) + let transfer_selector = [0xa9, 0x05, 0x9c, 0xbb]; + let receiver = [0; 12].concat(receiver); + let amount = amount.to_be_bytes::<32>(); + + Type2Transaction { + chain_id, + nonce, + max_priority_fee_per_gas, + max_fee_per_gas, + gas_limit, + value: 0, + to: token_address, + data: transfer_selector.concat(receiver).concat(amount), + } + .hash() + } +} diff --git a/noir/evm/erc20_transfer/src/signature.nr b/noir/evm/erc20_transfer/src/signature.nr new file mode 100644 index 0000000..cf709ef --- /dev/null +++ b/noir/evm/erc20_transfer/src/signature.nr @@ -0,0 +1,25 @@ +use common::Address; + +pub struct Signature { + pub r: [u8; 32], + pub s: [u8; 32], + + pub sender_pubkey_x: [u8; 32], + pub sender_pubkey_y: [u8; 32], +} + +impl Signature { + pub fn matches_transaction_hash(self, hash: [u8; 32]) -> bool { + std::ecdsa_secp256k1::verify_signature( + self.sender_pubkey_x, + self.sender_pubkey_y, + self.r.concat(self.s), + hash, + ) + } + + pub fn sender_address(self) -> Address { + let hash = keccak256::keccak256(self.sender_pubkey_x.concat(self.sender_pubkey_y), 64); + common::slice(hash, 12) + } +} diff --git a/noir/evm/mint/Nargo.toml b/noir/evm/mint/Nargo.toml new file mode 100644 index 0000000..202e2dc --- /dev/null +++ b/noir/evm/mint/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "mint" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] +common = { path = "../../common" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/evm/mint/src/main.nr b/noir/evm/mint/src/main.nr new file mode 100644 index 0000000..26c9dbe --- /dev/null +++ b/noir/evm/mint/src/main.nr @@ -0,0 +1,88 @@ +use common::{get_note_commitment, InputNote, MerklePath, Note, Utxo}; +use poseidon::poseidon2; + +fn main( + utxo: Utxo, + recent_root: pub Field, + input_nullifiers: pub [Field; 2], + output_commitments: pub [Field; 2], + mint_value: pub Field, +) { + mint_value.assert_max_bit_size::<240>(); + + let input_value = utxo.input_notes[0].note.value + utxo.input_notes[1].note.value; + let output_value = utxo.output_notes[0].value + utxo.output_notes[1].value; + assert(output_value == input_value + mint_value, "Mint output must match minted value"); + + utxo.validate(recent_root, input_nullifiers, output_commitments); +} + +#[test] +fn test_mint_one_input_two_outputs() { + let pk: Field = 101; + let address = common::get_address(pk); + + let note_1 = Note { kind: 1, value: 10, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + let note_3 = Note { kind: 1, value: 1, address, psi: 3 }; + let note_4 = Note { kind: 1, value: 12, address, psi: 4 }; + + let input_commitment_1 = get_note_commitment(note_1); + let output_commitment_1 = get_note_commitment(note_3); + let output_commitment_2 = get_note_commitment(note_4); + + let input_path_1 = MerklePath { path: [0; 160] }; + let input_path_2 = MerklePath { path: [0; 160] }; + let recent_root = input_path_1.root_from_leaf(input_commitment_1); + let utxo = Utxo { + input_notes: [input_note_1, input_note_2], + output_notes: [note_3, note_4], + input_merkle_paths: [input_path_1, input_path_2], + }; + + main( + utxo, + recent_root, + [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0], + [output_commitment_1, output_commitment_2], + 3, + ); +} + +#[test(should_fail)] +fn test_mint_rejects_bad_value_conservation() { + let pk: Field = 101; + let address = common::get_address(pk); + + let note_1 = Note { kind: 1, value: 10, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + let note_3 = Note { kind: 1, value: 1, address, psi: 3 }; + let note_4 = Note { kind: 1, value: 12, address, psi: 4 }; + + let input_commitment_1 = get_note_commitment(note_1); + let output_commitment_1 = get_note_commitment(note_3); + let output_commitment_2 = get_note_commitment(note_4); + + let input_path_1 = MerklePath { path: [0; 160] }; + let input_path_2 = MerklePath { path: [0; 160] }; + let recent_root = input_path_1.root_from_leaf(input_commitment_1); + let utxo = Utxo { + input_notes: [input_note_1, input_note_2], + output_notes: [note_3, note_4], + input_merkle_paths: [input_path_1, input_path_2], + }; + + main( + utxo, + recent_root, + [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0], + [output_commitment_1, output_commitment_2], + 2, + ); +} diff --git a/noir/evm/transfer/Nargo.toml b/noir/evm/transfer/Nargo.toml new file mode 100644 index 0000000..37c8a75 --- /dev/null +++ b/noir/evm/transfer/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "transfer" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] +common = { path = "../../common" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/evm/transfer/src/main.nr b/noir/evm/transfer/src/main.nr new file mode 100644 index 0000000..081e9c8 --- /dev/null +++ b/noir/evm/transfer/src/main.nr @@ -0,0 +1,83 @@ +use common::{get_note_commitment, InputNote, MerklePath, Note, Utxo}; +use poseidon::poseidon2; + +fn main( + utxo: Utxo, + recent_root: pub Field, + input_nullifiers: pub [Field; 2], + output_commitments: pub [Field; 2], +) { + let input_value = utxo.input_notes[0].note.value + utxo.input_notes[1].note.value; + let output_value = utxo.output_notes[0].value + utxo.output_notes[1].value; + assert(input_value == output_value, "Input and output totals do not match"); + + utxo.validate(recent_root, input_nullifiers, output_commitments); +} + +#[test] +fn test_transfer_one_input_one_output() { + let pk: Field = 101; + let address = common::get_address(pk); + + let note_1 = Note { kind: 1, value: 10, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + let note_3 = Note { kind: 1, value: 10, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + + let input_commitment_1 = get_note_commitment(note_1); + let output_commitment_1 = get_note_commitment(note_3); + let output_commitment_2 = get_note_commitment(note_4); + + let input_path_1 = MerklePath { path: [0; 160] }; + let input_path_2 = MerklePath { path: [0; 160] }; + let recent_root = input_path_1.root_from_leaf(input_commitment_1); + let utxo = Utxo { + input_notes: [input_note_1, input_note_2], + output_notes: [note_3, note_4], + input_merkle_paths: [input_path_1, input_path_2], + }; + + main( + utxo, + recent_root, + [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0], + [output_commitment_1, output_commitment_2], + ); +} + +#[test(should_fail)] +fn test_transfer_rejects_bad_recent_root() { + let pk: Field = 101; + let address = common::get_address(pk); + + let note_1 = Note { kind: 1, value: 10, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + let note_3 = Note { kind: 1, value: 10, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + + let input_commitment_1 = get_note_commitment(note_1); + let output_commitment_1 = get_note_commitment(note_3); + let output_commitment_2 = get_note_commitment(note_4); + + let input_path_1 = MerklePath { path: [0; 160] }; + let input_path_2 = MerklePath { path: [0; 160] }; + let recent_root = input_path_1.root_from_leaf(input_commitment_1) + 1; + let utxo = Utxo { + input_notes: [input_note_1, input_note_2], + output_notes: [note_3, note_4], + input_merkle_paths: [input_path_1, input_path_2], + }; + + main( + utxo, + recent_root, + [poseidon2::Poseidon2::hash([input_commitment_1, note_1.psi], 2), 0], + [output_commitment_1, output_commitment_2], + ); +} diff --git a/noir/generate_fixtures.sh b/noir/generate_fixtures.sh new file mode 100755 index 0000000..689ff67 --- /dev/null +++ b/noir/generate_fixtures.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +REPO_ROOT=$(git rev-parse --show-toplevel) +cd "$REPO_ROOT" + +cargo run -p xtask -- noir-fixtures "$@" diff --git a/noir/migrate/Nargo.toml b/noir/migrate/Nargo.toml new file mode 100644 index 0000000..49455eb --- /dev/null +++ b/noir/migrate/Nargo.toml @@ -0,0 +1,10 @@ +[package] +name = "migrate" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] +common = { path = "../common" } +poseidon_alt = { path = "../poseidon_alt" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/migrate/src/main.nr b/noir/migrate/src/main.nr new file mode 100644 index 0000000..781c1e6 --- /dev/null +++ b/noir/migrate/src/main.nr @@ -0,0 +1,26 @@ +use common::get_address; +use poseidon_alt::hash; + +fn main(owner_pk: Field, old_address: pub Field, new_address: pub Field) { + let calc_new_address = get_address(owner_pk); + assert(calc_new_address == new_address, "New address is not owned by the owner"); + + let calc_old_address = get_old_address(owner_pk); + assert(calc_old_address == old_address, "Old address is not owned by the owner"); +} + +fn get_old_address(owner_pk: Field) -> Field { + hash([owner_pk, 0]) +} + +#[test] +fn test_main() { + let pk = 101; + let new_address = get_address(pk); + let old_address = get_old_address(pk); + + println(new_address); + println(old_address); + + main(pk, old_address, new_address) +} diff --git a/noir/points/Nargo.toml b/noir/points/Nargo.toml new file mode 100644 index 0000000..df14737 --- /dev/null +++ b/noir/points/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "points" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] +common = { path = "../common" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/points/Prover.toml b/noir/points/Prover.toml new file mode 100644 index 0000000..2c8bdf3 --- /dev/null +++ b/noir/points/Prover.toml @@ -0,0 +1,45 @@ +notes = [ + { kind = "1", value = "0", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "1" }, + { kind = "1", value = "20", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "2" }, + { kind = "1", value = "30", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "3" }, + { kind = "1", value = "40", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "4" }, + { kind = "1", value = "50", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "5" }, + { kind = "1", value = "60", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "6" }, + { kind = "1", value = "70", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "7" }, + { kind = "1", value = "80", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "8" }, + { kind = "1", value = "90", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "9" }, + { kind = "1", value = "100", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "10" }, +] + +address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b" +timestamp = "10000000" +hash = "0x1eaf0543373e80534a6a23ac36255b0802aa1097c939ee3ec0e96e1d68039cc3" +value = "540" + +# Secret keys for the 10 notes +secret_keys = [ + "101", # Example secret key + "101", + "101", + "101", + "101", + "101", + "101", + "101", + "101", + "101", +] + +# Commitments for each note +commitments = [ + "0x0", + "0x0fcaad040e498822c43805739e53d9a6fa576c40aed38e31ae02d6dfa9a54b88", + "0x2e30e8bb2f8162b2ce950fad97fff1a0d64dfe2d202386465d70fa9848c8cf9c", + "0x1ab3cf2501cd9ec6b40337b96af6bde6486013e961b2bad18db43703ee038ada", + "0x1ebffcefd622ceaba4f90ce03c74fe9809b00f1ca065fbbc1df0f5f349f80e27", + "0x070ab62bf6bf696d35d14e1214487009ff024076fc69793ddedd7ad5b218c983", + "0x06862fddb7464511ce8ea3b914e638c67c17de8c9be1cf229a0824d61ac4c7e0", + "0x180ba66322bbeb5be54e361928ab60cab5fd402c8581098b9cbf7a95f07be42b", + "0x2a22e66e7846b696b2114639778f81d85cc4ede2e35265bd822ad044515a5a0b", + "0x22363ee0343e629e7448809691b87256286a27a2c0296e8ec78206ac0e791c42", +] diff --git a/noir/points/src/main.nr b/noir/points/src/main.nr new file mode 100644 index 0000000..b38d251 --- /dev/null +++ b/noir/points/src/main.nr @@ -0,0 +1,75 @@ +use common::{check_commitment, check_input_note_ownership, get_address, InputNote, Note}; +use poseidon::poseidon2; + +fn main( + notes: [Note; 10], + secret_keys: [Field; 10], + address: Field, + timestamp: pub Field, + value: pub Field, + hash: pub Field, + commitments: pub [Field; 10], +) { + let mut notes_value = 0; + + for i in 0..10 { + let note = notes[i]; + let secret_key = secret_keys[i]; + let commitment = commitments[i]; + + check_commitment(note, commitment); + check_input_note_ownership(InputNote { note, secret_key }); + + notes_value += note.value; + } + + assert(value == notes_value, "Invalid value"); + assert(poseidon2::Poseidon2::hash([timestamp, address], 2) == hash); +} + +#[test] +fn test_main() { + let pk = 101; + let address = get_address(pk); + + // Create 10 notes with the same address + let mut notes: [Note; 10] = [ + Note { kind: 0, value: 0, address: 0, psi: 0 }, + Note { kind: 1, value: 20, address: address, psi: 2 }, + Note { kind: 1, value: 30, address: address, psi: 3 }, + Note { kind: 1, value: 40, address: address, psi: 4 }, + Note { kind: 1, value: 50, address: address, psi: 5 }, + Note { kind: 1, value: 60, address: address, psi: 6 }, + Note { kind: 1, value: 70, address: address, psi: 7 }, + Note { kind: 1, value: 80, address: address, psi: 8 }, + Note { kind: 1, value: 90, address: address, psi: 9 }, + Note { kind: 1, value: 100, address: address, psi: 10 }, + ]; + + // Calculate the total value of all notes + let total_value = 540; + + // Create an array of secret keys (all the same in this test) + let mut secret_keys = [pk; 10]; + secret_keys[0] = 0; + + // Calculate commitments for each note + let mut commitments: [Field; 10] = [0; 10]; + for i in 0..10 { + commitments[i] = common::get_note_commitment(notes[i]); + } + + // Create timestamp and calculate hash + let timestamp = 10000000; + let message_hash = poseidon2::Poseidon2::hash([timestamp, address], 2); + + main( + notes, + secret_keys, + address, + timestamp, + total_value, + message_hash, + commitments, + ) +} diff --git a/noir/poseidon_alt/Nargo.toml b/noir/poseidon_alt/Nargo.toml new file mode 100644 index 0000000..e6d51d0 --- /dev/null +++ b/noir/poseidon_alt/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "poseidon_alt" +type = "lib" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] diff --git a/noir/poseidon_alt/src/constants.nr b/noir/poseidon_alt/src/constants.nr new file mode 100644 index 0000000..186247a --- /dev/null +++ b/noir/poseidon_alt/src/constants.nr @@ -0,0 +1,95 @@ +// BN256 Poseidon constants +// Parameters from: https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/master/code/poseidonperm_x5_254_3.sage + +pub global FULL_ROUNDS: u32 = 8; +pub global PARTIAL_ROUNDS: u32 = 57; +pub global T: u32 = 3; // Width +pub global RATE: u32 = 2; + +// Round constants (64 rounds * 3 elements = 192 constants total, plus 3 more for round 64) +pub global ROUND_CONSTANTS: [[Field; 3]; 65] = [ + [6745197990210204598374042828761989596302876299545964402857411729872131034734, 426281677759936592021316809065178817848084678679510574715894138690250139748, 4014188762916583598888942667424965430287497824629657219807941460227372577781], + [21328925083209914769191926116470334003273872494252651254811226518870906634704, 19525217621804205041825319248827370085205895195618474548469181956339322154226, 1402547928439424661186498190603111095981986484908825517071607587179649375482], + [18320863691943690091503704046057443633081959680694199244583676572077409194605, 17709820605501892134371743295301255810542620360751268064484461849423726103416, 15970119011175710804034336110979394557344217932580634635707518729185096681010], + [9818625905832534778628436765635714771300533913823445439412501514317783880744, 6235167673500273618358172865171408902079591030551453531218774338170981503478, 12575685815457815780909564540589853169226710664203625668068862277336357031324], + [7381963244739421891665696965695211188125933529845348367882277882370864309593, 14214782117460029685087903971105962785460806586237411939435376993762368956406, 13382692957873425730537487257409819532582973556007555550953772737680185788165], + [2203881792421502412097043743980777162333765109810562102330023625047867378813, 2916799379096386059941979057020673941967403377243798575982519638429287573544, 4341714036313630002881786446132415875360643644216758539961571543427269293497], + [2340590164268886572738332390117165591168622939528604352383836760095320678310, 5222233506067684445011741833180208249846813936652202885155168684515636170204, 7963328565263035669460582454204125526132426321764384712313576357234706922961], + [1394121618978136816716817287892553782094854454366447781505650417569234586889, 20251767894547536128245030306810919879363877532719496013176573522769484883301, 141695147295366035069589946372747683366709960920818122842195372849143476473], + [15919677773886738212551540894030218900525794162097204800782557234189587084981, 2616624285043480955310772600732442182691089413248613225596630696960447611520, 4740655602437503003625476760295930165628853341577914460831224100471301981787], + [19201590924623513311141753466125212569043677014481753075022686585593991810752, 12116486795864712158501385780203500958268173542001460756053597574143933465696, 8481222075475748672358154589993007112877289817336436741649507712124418867136], + [5181207870440376967537721398591028675236553829547043817076573656878024336014, 1576305643467537308202593927724028147293702201461402534316403041563704263752, 2555752030748925341265856133642532487884589978209403118872788051695546807407], + [18840924862590752659304250828416640310422888056457367520753407434927494649454, 14593453114436356872569019099482380600010961031449147888385564231161572479535, 20826991704411880672028799007667199259549645488279985687894219600551387252871], + [9159011389589751902277217485643457078922343616356921337993871236707687166408, 5605846325255071220412087261490782205304876403716989785167758520729893194481, 1148784255964739709393622058074925404369763692117037208398835319441214134867], + [20945896491956417459309978192328611958993484165135279604807006821513499894540, 229312996389666104692157009189660162223783309871515463857687414818018508814, 21184391300727296923488439338697060571987191396173649012875080956309403646776], + [21853424399738097885762888601689700621597911601971608617330124755808946442758, 12776298811140222029408960445729157525018582422120161448937390282915768616621, 7556638921712565671493830639474905252516049452878366640087648712509680826732], + [19042212131548710076857572964084011858520620377048961573689299061399932349935, 12871359356889933725034558434803294882039795794349132643274844130484166679697, 3313271555224009399457959221795880655466141771467177849716499564904543504032], + [15080780006046305940429266707255063673138269243146576829483541808378091931472, 21300668809180077730195066774916591829321297484129506780637389508430384679582, 20480395468049323836126447690964858840772494303543046543729776750771407319822], + [10034492246236387932307199011778078115444704411143703430822959320969550003883, 19584962776865783763416938001503258436032522042569001300175637333222729790225, 20155726818439649091211122042505326538030503429443841583127932647435472711802], + [13313554736139368941495919643765094930693458639277286513236143495391474916777, 14606609055603079181113315307204024259649959674048912770003912154260692161833, 5563317320536360357019805881367133322562055054443943486481491020841431450882], + [10535419877021741166931390532371024954143141727751832596925779759801808223060, 12025323200952647772051708095132262602424463606315130667435888188024371598063, 2906495834492762782415522961458044920178260121151056598901462871824771097354], + [19131970618309428864375891649512521128588657129006772405220584460225143887876, 8896386073442729425831367074375892129571226824899294414632856215758860965449, 7748212315898910829925509969895667732958278025359537472413515465768989125274], + [422974903473869924285294686399247660575841594104291551918957116218939002865, 6398251826151191010634405259351528880538837895394722626439957170031528482771, 18978082967849498068717608127246258727629855559346799025101476822814831852169], + [19150742296744826773994641927898928595714611370355487304294875666791554590142, 12896891575271590393203506752066427004153880610948642373943666975402674068209, 9546270356416926575977159110423162512143435321217584886616658624852959369669], + [2159256158967802519099187112783460402410585039950369442740637803310736339200, 8911064487437952102278704807713767893452045491852457406400757953039127292263, 745203718271072817124702263707270113474103371777640557877379939715613501668], + [19313999467876585876087962875809436559985619524211587308123441305315685710594, 13254105126478921521101199309550428567648131468564858698707378705299481802310, 1842081783060652110083740461228060164332599013503094142244413855982571335453], + [9630707582521938235113899367442877106957117302212260601089037887382200262598, 5066637850921463603001689152130702510691309665971848984551789224031532240292, 4222575506342961001052323857466868245596202202118237252286417317084494678062], + [2919565560395273474653456663643621058897649501626354982855207508310069954086, 6828792324689892364977311977277548750189770865063718432946006481461319858171, 2245543836264212411244499299744964607957732316191654500700776604707526766099], + [19602444885919216544870739287153239096493385668743835386720501338355679311704, 8239538512351936341605373169291864076963368674911219628966947078336484944367, 15053013456316196458870481299866861595818749671771356646798978105863499965417], + [7173615418515925804810790963571435428017065786053377450925733428353831789901, 8239211677777829016346247446855147819062679124993100113886842075069166957042, 15330855478780269194281285878526984092296288422420009233557393252489043181621], + [10014883178425964324400942419088813432808659204697623248101862794157084619079, 14014440630268834826103915635277409547403899966106389064645466381170788813506, 3580284508947993352601712737893796312152276667249521401778537893620670305946], + [2559754020964039399020874042785294258009596917335212876725104742182177996988, 14898657953331064524657146359621913343900897440154577299309964768812788279359, 2094037260225570753385567402013028115218264157081728958845544426054943497065], + [18051086536715129874440142649831636862614413764019212222493256578581754875930, 21680659279808524976004872421382255670910633119979692059689680820959727969489, 13950668739013333802529221454188102772764935019081479852094403697438884885176], + [9703845704528288130475698300068368924202959408694460208903346143576482802458, 12064310080154762977097567536495874701200266107682637369509532768346427148165, 16970760937630487134309762150133050221647250855182482010338640862111040175223], + [9790997389841527686594908620011261506072956332346095631818178387333642218087, 16314772317774781682315680698375079500119933343877658265473913556101283387175, 82044870826814863425230825851780076663078706675282523830353041968943811739], + [21696416499108261787701615667919260888528264686979598953977501999747075085778, 327771579314982889069767086599893095509690747425186236545716715062234528958, 4606746338794869835346679399457321301521448510419912225455957310754258695442], + [64499140292086295251085369317820027058256893294990556166497635237544139149, 10455028514626281809317431738697215395754892241565963900707779591201786416553, 10421411526406559029881814534127830959833724368842872558146891658647152404488], + [18848084335930758908929996602136129516563864917028006334090900573158639401697, 13844582069112758573505569452838731733665881813247931940917033313637916625267, 13488838454403536473492810836925746129625931018303120152441617863324950564617], + [15742141787658576773362201234656079648895020623294182888893044264221895077688, 6756884846734501741323584200608866954194124526254904154220230538416015199997, 7860026400080412708388991924996537435137213401947704476935669541906823414404], + [7871040688194276447149361970364037034145427598711982334898258974993423182255, 20758972836260983284101736686981180669442461217558708348216227791678564394086, 21723241881201839361054939276225528403036494340235482225557493179929400043949], + [19428469330241922173653014973246050805326196062205770999171646238586440011910, 7969200143746252148180468265998213908636952110398450526104077406933642389443, 10950417916542216146808986264475443189195561844878185034086477052349738113024], + [18149233917533571579549129116652755182249709970669448788972210488823719849654, 3729796741814967444466779622727009306670204996071028061336690366291718751463, 5172504399789702452458550583224415301790558941194337190035441508103183388987], + [6686473297578275808822003704722284278892335730899287687997898239052863590235, 19426913098142877404613120616123695099909113097119499573837343516470853338513, 5120337081764243150760446206763109494847464512045895114970710519826059751800], + [5055737465570446530938379301905385631528718027725177854815404507095601126720, 14235578612970484492268974539959119923625505766550088220840324058885914976980, 653592517890187950103239281291172267359747551606210609563961204572842639923], + [5507360526092411682502736946959369987101940689834541471605074817375175870579, 7864202866011437199771472205361912625244234597659755013419363091895334445453, 21294659996736305811805196472076519801392453844037698272479731199885739891648], + [13767183507040326119772335839274719411331242166231012705169069242737428254651, 810181532076738148308457416289197585577119693706380535394811298325092337781, 14232321930654703053193240133923161848171310212544136614525040874814292190478], + [16796904728299128263054838299534612533844352058851230375569421467352578781209, 16256310366973209550759123431979563367001604350120872788217761535379268327259, 19791658638819031543640174069980007021961272701723090073894685478509001321817], + [7046232469803978873754056165670086532908888046886780200907660308846356865119, 16001732848952745747636754668380555263330934909183814105655567108556497219752, 9737276123084413897604802930591512772593843242069849260396983774140735981896], + [11410895086919039954381533622971292904413121053792570364694836768885182251535, 19098362474249267294548762387533474746422711206129028436248281690105483603471, 11013788190750472643548844759298623898218957233582881400726340624764440203586], + [2206958256327295151076063922661677909471794458896944583339625762978736821035, 7171889270225471948987523104033632910444398328090760036609063776968837717795, 2510237900514902891152324520472140114359583819338640775472608119384714834368], + [8825275525296082671615660088137472022727508654813239986303576303490504107418, 1481125575303576470988538039195271612778457110700618040436600537924912146613, 16268684562967416784133317570130804847322980788316762518215429249893668424280], + [4681491452239189664806745521067158092729838954919425311759965958272644506354, 3131438137839074317765338377823608627360421824842227925080193892542578675835, 7930402370812046914611776451748034256998580373012248216998696754202474945793], + [8973151117361309058790078507956716669068786070949641445408234962176963060145, 10223139291409280771165469989652431067575076252562753663259473331031932716923, 2232089286698717316374057160056566551249777684520809735680538268209217819725], + [16930089744400890347392540468934821520000065594669279286854302439710657571308, 21739597952486540111798430281275997558482064077591840966152905690279247146674, 7508315029150148468008716674010060103310093296969466203204862163743615534994], + [11418894863682894988747041469969889669847284797234703818032750410328384432224, 10895338268862022698088163806301557188640023613155321294365781481663489837917, 18644184384117747990653304688839904082421784959872380449968500304556054962449], + [7414443845282852488299349772251184564170443662081877445177167932875038836497, 5391299369598751507276083947272874512197023231529277107201098701900193273851, 10329906873896253554985208009869159014028187242848161393978194008068001342262], + [4711719500416619550464783480084256452493890461073147512131129596065578741786, 11943219201565014805519989716407790139241726526989183705078747065985453201504, 4298705349772984837150885571712355513879480272326239023123910904259614053334], + [9999044003322463509208400801275356671266978396985433172455084837770460579627, 4908416131442887573991189028182614782884545304889259793974797565686968097291, 11963412684806827200577486696316210731159599844307091475104710684559519773777], + [20129916000261129180023520480843084814481184380399868943565043864970719708502, 12884788430473747619080473633364244616344003003135883061507342348586143092592, 20286808211545908191036106582330883564479538831989852602050135926112143921015], + [16282045180030846845043407450751207026423331632332114205316676731302016331498, 4332932669439410887701725251009073017227450696965904037736403407953448682093, 11105712698773407689561953778861118250080830258196150686012791790342360778288], + [21853934471586954540926699232107176721894655187276984175226220218852955976831, 9807888223112768841912392164376763820266226276821186661925633831143729724792, 13411808896854134882869416756427789378942943805153730705795307450368858622668], + [17906847067500673080192335286161014930416613104209700445088168479205894040011, 14554387648466176616800733804942239711702169161888492380425023505790070369632, 4264116751358967409634966292436919795665643055548061693088119780787376143967], + [2401104597023440271473786738539405349187326308074330930748109868990675625380, 12251645483867233248963286274239998200789646392205783056343767189806123148785, 15331181254680049984374210433775713530849624954688899814297733641575188164316], + [13108834590369183125338853868477110922788848506677889928217413952560148766472, 6843160824078397950058285123048455551935389277899379615286104657075620692224, 10151103286206275742153883485231683504642432930275602063393479013696349676320], + [7074320081443088514060123546121507442501369977071685257650287261047855962224, 11413928794424774638606755585641504971720734248726394295158115188173278890938, 7312756097842145322667451519888915975561412209738441762091369106604423801080], + [7181677521425162567568557182629489303281861794357882492140051324529826589361, 15123155547166304758320442783720138372005699143801247333941013553002921430306, 13409242754315411433193860530743374419854094495153957441316635981078068351329] +]; + +// MDS matrix +pub global MDS: [[Field; 3]; 3] = [ + [ + 7511745149465107256748700652201246547602992235352608707588321460060273774987, + 10370080108974718697676803824769673834027675643658433702224577712625900127200, + 19705173408229649878903981084052839426532978878058043055305024233888854471533 + ], + [ + 18732019378264290557468133440468564866454307626475683536618613112504878618481, + 20870176810702568768751421378473869562658540583882454726129544628203806653987, + 7266061498423634438633389053804536045105766754026813321943009179476902321146 + ], + [ + 9131299761947733513298312097611845208338517739621853568979632113419485819303, + 10595341252162738537912664445405114076324478519622938027420701542910180337937, + 11597556804922396090267472882856054602429588299176362916247939723151043581408 + ] +]; \ No newline at end of file diff --git a/noir/poseidon_alt/src/lib.nr b/noir/poseidon_alt/src/lib.nr new file mode 100644 index 0000000..6ec336a --- /dev/null +++ b/noir/poseidon_alt/src/lib.nr @@ -0,0 +1,26 @@ +mod constants; +mod poseidon; +mod test; +mod test_field_snapshot; + +// Re-export the main hash functions +pub use poseidon::{hash_2, hash, permute, PoseidonSponge}; + +// Main hash_merge function to match the Rust implementation signature +// This is the primary function used by hash-poseidon +pub fn hash_merge(elements: [Field; 2]) -> Field { + hash_2(elements[0], elements[1]) +} + +// Additional convenience functions +pub fn hash_single(input: Field) -> Field { + hash([input]) +} + +pub fn hash_three(a: Field, b: Field, c: Field) -> Field { + hash([a, b, c]) +} + +pub fn hash_four(a: Field, b: Field, c: Field, d: Field) -> Field { + hash([a, b, c, d]) +} diff --git a/noir/poseidon_alt/src/poseidon.nr b/noir/poseidon_alt/src/poseidon.nr new file mode 100644 index 0000000..3953e02 --- /dev/null +++ b/noir/poseidon_alt/src/poseidon.nr @@ -0,0 +1,157 @@ +use crate::constants::{FULL_ROUNDS, PARTIAL_ROUNDS, RATE, ROUND_CONSTANTS, MDS}; + +// S-box function (x^5) +fn sbox(x: Field) -> Field { + let x2 = x * x; + let x4 = x2 * x2; + x4 * x +} + +// Apply MDS matrix multiplication +fn apply_mds(state: [Field; 3]) -> [Field; 3] { + let mut result = [0; 3]; + for i in 0..3 { + for j in 0..3 { + result[i] = result[i] + MDS[i][j] * state[j]; + } + } + result +} + +// Full round function: S-box on all elements + MDS +fn full_round(mut state: [Field; 3], round_constants: [Field; 3]) -> [Field; 3] { + // Add round constants and apply S-box to all elements + for i in 0..3 { + state[i] = sbox(state[i] + round_constants[i]); + } + // Apply MDS matrix + apply_mds(state) +} + +// Partial round function: S-box on first element only + MDS +fn partial_round(mut state: [Field; 3], round_constants: [Field; 3]) -> [Field; 3] { + // Add round constants + for i in 0..3 { + state[i] = state[i] + round_constants[i]; + } + // Apply S-box only to first element + state[0] = sbox(state[0]); + // Apply MDS matrix + apply_mds(state) +} + +// Main permutation function +pub fn permute(mut state: [Field; 3]) -> [Field; 3] { + let r_f = FULL_ROUNDS / 2; + let r_p = PARTIAL_ROUNDS; + + let mut round_idx = 0; + + // First half of full rounds + for _ in 0..r_f { + state = full_round(state, ROUND_CONSTANTS[round_idx]); + round_idx = round_idx + 1; + } + + // Partial rounds + for _ in 0..r_p { + state = partial_round(state, ROUND_CONSTANTS[round_idx]); + round_idx = round_idx + 1; + } + + // Second half of full rounds + for _ in 0..r_f { + state = full_round(state, ROUND_CONSTANTS[round_idx]); + round_idx = round_idx + 1; + } + + state +} + +// Sponge construction for constant-length hashing +pub struct PoseidonSponge { + state: [Field; 3], + cache: [Field; 2], + cache_size: u32, +} + +impl PoseidonSponge { + // Initialize with initial capacity element for constant-length domain separation + pub fn new(initial_capacity: Field) -> Self { + let mut state = [0; 3]; + state[2] = initial_capacity; // Set capacity element at index RATE (2) + Self { + state, + cache: [0; 2], + cache_size: 0, + } + } + + // Absorb a field element + pub fn absorb(&mut self, input: Field) { + if self.cache_size == RATE { + // Cache is full, perform duplex round + self.perform_duplex(); + self.cache[0] = input; + self.cache_size = 1; + } else { + // Add to cache + self.cache[self.cache_size] = input; + self.cache_size = self.cache_size + 1; + } + } + + // Perform duplex operation (add cache to state and permute) + fn perform_duplex(&mut self) { + // Add cached values to state + for i in 0..RATE { + if i < self.cache_size { + self.state[i] = self.state[i] + self.cache[i]; + } + } + // Apply permutation + self.state = permute(self.state); + // Clear cache + self.cache_size = 0; + } + + // Squeeze output + pub fn squeeze(mut self) -> Field { + // Final duplex to compress any remaining cached data + self.perform_duplex(); + // Return first element + self.state[0] + } +} + +// Hash function for 2 elements (matching the Rust implementation) +pub fn hash_2(left: Field, right: Field) -> Field { + // Initial capacity element: (2 << 64) for ConstantLength<2> + let initial_capacity = 2 * 0x10000000000000000; // 2 * 2^64 + + let mut sponge = PoseidonSponge::new(initial_capacity); + sponge.absorb(left); + sponge.absorb(right); + sponge.squeeze() +} + +// Generic hash function for N elements +pub fn hash(inputs: [Field; N]) -> Field { + // Initial capacity element: (N << 64) for ConstantLength + let initial_capacity = (N as Field) * 0x10000000000000000; // N * 2^64 + + let mut sponge = PoseidonSponge::new(initial_capacity); + for i in 0..N { + sponge.absorb(inputs[i]); + } + + // Add padding (zero padding) to make total absorbed elements a multiple of RATE + // Calculate how many zeros to add + let k = (N + RATE - 1) / RATE; // Ceiling division + let padding_count = k * RATE - N; + for _ in 0..padding_count { + sponge.absorb(0); + } + + sponge.squeeze() +} \ No newline at end of file diff --git a/noir/poseidon_alt/src/test.nr b/noir/poseidon_alt/src/test.nr new file mode 100644 index 0000000..d6ec589 --- /dev/null +++ b/noir/poseidon_alt/src/test.nr @@ -0,0 +1,180 @@ +use crate::hash_merge; +use crate::poseidon::{hash_2, hash, permute}; + +#[test] +fn test_hash_zeros() { + // Test hash([0, 0]) from snapshot + let result = hash_merge([0, 0]); + // Expected: 0x2ba00861b8f1581f5e17d438e323fa2809f58f1a60009dcd05edb1c9c7c833da + let expected = 0x2ba00861b8f1581f5e17d438e323fa2809f58f1a60009dcd05edb1c9c7c833da; + assert(result == expected, "Hash of [0, 0] mismatch"); +} + +#[test] +fn test_hash_zero_one() { + // Test hash([0, 1]) from snapshot + let result = hash_merge([0, 1]); + // Expected: 0x1f4c45f9764aa17b0b277e23e1da0cefd69affc8caa18bb01f65b5c9d9761d21 + let expected = 0x1f4c45f9764aa17b0b277e23e1da0cefd69affc8caa18bb01f65b5c9d9761d21; + assert(result == expected, "Hash of [0, 1] mismatch"); +} + +#[test] +fn test_hash_one_zero() { + // Test hash([1, 0]) from snapshot + let result = hash_merge([1, 0]); + // Expected: 0x034797ee520c67ec5ee6fd37f581ba7267449a21de06aa55a09821caeec2e89d + let expected = 0x034797ee520c67ec5ee6fd37f581ba7267449a21de06aa55a09821caeec2e89d; + assert(result == expected, "Hash of [1, 0] mismatch"); +} + +#[test] +fn test_hash_consistency() { + // Test that hash_2 and hash_merge produce the same results + let a = 42; + let b = 123; + + let result1 = hash_merge([a, b]); + let result2 = hash_2(a, b); + let result3 = hash([a, b]); + + assert(result1 == result2, "hash_merge and hash_2 should produce same result"); + assert(result1 == result3, "hash_merge and hash should produce same result"); +} + +#[test] +fn test_hash_non_symmetric() { + // Test that hash is not symmetric + let a = 10; + let b = 20; + + let hash_ab = hash_merge([a, b]); + let hash_ba = hash_merge([b, a]); + + assert(hash_ab != hash_ba, "Hash should not be symmetric"); +} + +#[test] +fn test_permutation_basic() { + // Test the permutation function with simple input + let input = [1, 2, 3]; + let output = permute(input); + + // Just verify it doesn't crash and produces different output + assert(output[0] != input[0], "Permutation should change the state"); + assert(output[1] != input[1], "Permutation should change the state"); + assert(output[2] != input[2], "Permutation should change the state"); +} + +#[test] +fn test_hash_single_element() { + // Test hashing a single element + let result = hash([42]); + // Verify it produces a valid field element (non-zero in this case) + assert(result != 0, "Single element hash should not be zero"); +} + +#[test] +fn test_hash_three_elements() { + // Test hashing three elements + let result = hash([1, 2, 3]); + // Verify it produces a valid field element + assert(result != 0, "Three element hash should not be zero"); + + // Also test that order matters + let result2 = hash([3, 2, 1]); + assert(result != result2, "Hash should depend on element order"); +} + +#[test] +fn test_small_sequential_values() { + // Test with small sequential values + for i in 1..10 { + let result = hash_merge([i as Field, (i + 1) as Field]); + let result_reversed = hash_merge([(i + 1) as Field, i as Field]); + + // Verify results are deterministic (same input gives same output) + let result2 = hash_merge([i as Field, (i + 1) as Field]); + assert(result == result2, "Hash should be deterministic"); + + // Verify non-symmetry + assert(result != result_reversed, "Hash should not be symmetric"); + } +} + +#[test] +fn test_powers_of_two() { + // Test with powers of 2 + let mut prev_hash = 0; + for i in 0..10 { + let power = 1 << i; // 2^i + let result = hash_merge([power as Field, 0]); + + // Each power of 2 should give a different hash + assert(result != prev_hash, "Different inputs should give different hashes"); + prev_hash = result; + } +} + +#[test] +fn test_large_safe_values() { + // Test with large values that are safely within field range + let large1 = 0x1234567890abcdef1234567890abcdef; + let large2 = 0xfedcba0987654321fedcba0987654321; + + let result1 = hash_merge([large1, large2]); + let result2 = hash_merge([large2, large1]); + + assert(result1 != result2, "Hash should not be symmetric for large values"); +} + +#[test] +fn test_hash_chain() { + // Test chaining hashes + let initial = hash_merge([1, 2]); + let second = hash_merge([initial, 3]); + let third = hash_merge([second, 4]); + + // Verify different chain gives different result + let alt_initial = hash_merge([2, 1]); + let alt_second = hash_merge([alt_initial, 3]); + let alt_third = hash_merge([alt_second, 4]); + + assert(third != alt_third, "Different hash chains should give different results"); +} + +#[test] +fn test_boundary_values() { + // Test with boundary values + let max_u32 = 0xffffffff; + let max_u64 = 0xffffffffffffffff; + let max_u128 = 0xffffffffffffffffffffffffffffffff; + + let result1 = hash_merge([0, max_u32]); + let result2 = hash_merge([0, max_u64]); + let result3 = hash_merge([0, max_u128]); + + // All should produce different hashes + assert(result1 != result2, "Different boundary values should produce different hashes"); + assert(result2 != result3, "Different boundary values should produce different hashes"); + assert(result1 != result3, "Different boundary values should produce different hashes"); +} + +#[test] +fn test_collision_resistance() { + // Test that similar inputs don't collide + let base = 0x123456789; + + let result1 = hash_merge([base, base]); + let result2 = hash_merge([base, base + 1]); + let result3 = hash_merge([base + 1, base]); + let result4 = hash_merge([base + 1, base + 1]); + + // All combinations should be different + assert(result1 != result2, "Different inputs should not collide"); + assert(result1 != result3, "Different inputs should not collide"); + assert(result1 != result4, "Different inputs should not collide"); + assert(result2 != result3, "Different inputs should not collide"); + assert(result2 != result4, "Different inputs should not collide"); + assert(result3 != result4, "Different inputs should not collide"); +} diff --git a/noir/poseidon_alt/src/test_field_snapshot.nr b/noir/poseidon_alt/src/test_field_snapshot.nr new file mode 100644 index 0000000..1ebaae6 --- /dev/null +++ b/noir/poseidon_alt/src/test_field_snapshot.nr @@ -0,0 +1,25 @@ +use crate::hash_merge; + +#[test] +fn test_small_snapshot_with_field_reduction() { + let left_reduced = 0x10; + let right_reduced = 0x20; + + let result = hash_merge([left_reduced, right_reduced]); + + + assert(result == 0x1bd8ab468649bc72252fa3eda6dd0793eb3db6eea57490b5629d78829833cdb3, "Hash result"); + // assert(result == 0x1dd8037c0559952dd9d36c95b8425887933e2a80481b93339bbca23af6a8e7b1, "Hash result"); +} + +#[test] +fn test_max_snapshot_with_field_reduction() { + let max = 0x30644E72E131A029B85045B68181585D2833E84879B9709143E1F593F0000000; + + let result = hash_merge([max, max]); + + print("test_max_snapshot_with_field_reduction"); + print(result); + + assert(result == 0x1c359a5ebc07223748449c93b5eb57c8dc21ddfcd406034769efc98db98c2a3c, "Hash result"); +} diff --git a/noir/recurse.sh b/noir/recurse.sh new file mode 100755 index 0000000..0610ab4 --- /dev/null +++ b/noir/recurse.sh @@ -0,0 +1,58 @@ +#!/bin/bash +set -eu + +BACKEND=${BACKEND:-bb} + +PACKAGE_NAME="utxo" +RECURSION_PACKAGE_NAME="recursion" + + + +nargo execute ${PACKAGE_NAME}_witness --package ${PACKAGE_NAME} + +# Timing for the first proof +start_time=$(date +%s.%N) +time $BACKEND prove -b ./target/${PACKAGE_NAME}.json -w ./target/${PACKAGE_NAME}_witness.gz -o ./target/${PACKAGE_NAME}_proof --recursive +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc -l) +printf "Proof ${PACKAGE_NAME} time: %.1f seconds\n" "$duration" + +# Generate inputs to recursion +$BACKEND write_vk -b ./target/${PACKAGE_NAME}.json -o ./target/${PACKAGE_NAME}_key --recursive +$BACKEND vk_as_fields -k ./target/${PACKAGE_NAME}_key -o ./target/${PACKAGE_NAME}_vk_as_fields +VK_HASH=$(jq -r '.[0]' ./target/${PACKAGE_NAME}_vk_as_fields) +VK_AS_FIELDS=$(jq -r '.[1:]' ./target/${PACKAGE_NAME}_vk_as_fields) + +$BACKEND proof_as_fields -p ./target/${PACKAGE_NAME}_proof -k ./target/${PACKAGE_NAME}_key -o ./target/${PACKAGE_NAME}_proof_as_fields +FULL_PROOF_AS_FIELDS=$(jq -r '.[0:]' ./target/${PACKAGE_NAME}_proof_as_fields) +# echo $FULL_PROOF_AS_FIELDS + +# Count the number of public inputs in Verifier.toml +PUBLIC_INPUT_COUNT=10; +echo "Public input count: $PUBLIC_INPUT_COUNT" + +PUBLIC_INPUTS=$(echo $FULL_PROOF_AS_FIELDS | jq -r ".[:$PUBLIC_INPUT_COUNT]") +PROOF_AS_FIELDS=$(echo $FULL_PROOF_AS_FIELDS | jq -r ".[$PUBLIC_INPUT_COUNT:]") + +RECURSE_LEAF_PROVER_TOML=./${RECURSION_PACKAGE_NAME}/Prover.toml + +# Clear the file +> $RECURSE_LEAF_PROVER_TOML + +echo "key_hash = \"$VK_HASH\"" >> $RECURSE_LEAF_PROVER_TOML +echo "verification_key = $VK_AS_FIELDS" >> $RECURSE_LEAF_PROVER_TOML +echo "proof = $PROOF_AS_FIELDS" >> $RECURSE_LEAF_PROVER_TOML +echo "public_inputs = $PUBLIC_INPUTS" >> $RECURSE_LEAF_PROVER_TOML + +nargo execute ${RECURSION_PACKAGE_NAME}_witness --package ${RECURSION_PACKAGE_NAME} + +# Timing for the recursion proof +start_time=$(date +%s.%N) # Corrected format +$BACKEND prove -b ./target/${RECURSION_PACKAGE_NAME}.json -w ./target/${RECURSION_PACKAGE_NAME}_witness.gz -o ./target/${RECURSION_PACKAGE_NAME}_proof +end_time=$(date +%s.%N) +duration=$(echo "$end_time - $start_time" | bc -l) +printf "Proof ${RECURSION_PACKAGE_NAME} time: %.1f seconds\n" "$duration" + +# Verify the generated recursive proof +$BACKEND write_vk -b ./target/${-}.json -o ./target/${RECURSION_PACKAGE_NAME}_key +$BACKEND verify -p ./target/${RECURSION_PACKAGE_NAME}_proof -k ./target/${RECURSION_PACKAGE_NAME}_key diff --git a/noir/signature/Nargo.toml b/noir/signature/Nargo.toml new file mode 100644 index 0000000..67692a2 --- /dev/null +++ b/noir/signature/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "signature" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[dependencies] +common = { path = "../common" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } diff --git a/noir/signature/Prover.toml b/noir/signature/Prover.toml new file mode 100644 index 0000000..d798f15 --- /dev/null +++ b/noir/signature/Prover.toml @@ -0,0 +1,4 @@ +owner_pk = "101" +message_hash = "0x1dfa18f334cf5932efdaac4e9883d6a991e2f10aef95a9c44382dbcfaa55d83b" +address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b" +message = "1000" diff --git a/noir/signature/src/main.nr b/noir/signature/src/main.nr new file mode 100644 index 0000000..3d55aa9 --- /dev/null +++ b/noir/signature/src/main.nr @@ -0,0 +1,23 @@ +use common::get_address; +use poseidon::poseidon2; + +fn main(owner_pk: Field, message_hash: Field, address: pub Field, message: pub Field) { + let owner_address = get_address(owner_pk); + assert(owner_address == address, "Address is not owned by the owner"); + + let calc_message_hash = poseidon2::Poseidon2::hash([owner_pk, message], 2); + assert(calc_message_hash == message_hash, "Message hash is invalid"); +} + +#[test] +fn test_main() { + let pk = 101; + let address = get_address(pk); + let message = 1000; + let message_hash = poseidon2::Poseidon2::hash([pk, message], 2); + + println(message_hash); + println(address); + + main(pk, message_hash, address, message) +} diff --git a/noir/utxo/Nargo.toml b/noir/utxo/Nargo.toml new file mode 100644 index 0000000..f306a63 --- /dev/null +++ b/noir/utxo/Nargo.toml @@ -0,0 +1,18 @@ +[package] +name = "utxo" +type = "bin" +authors = [""] +compiler_version = ">=0.36.0" + +[package.metadata.generate_fixtures] +recursive = true + +[[package.metadata.generate_fixtures.hash_updates]] +path = "../agg_utxo/src/main.nr" +kind = "global_field" +name = "UTXO_VERIFICATION_KEY_HASH" + +[dependencies] +common = { path = "../common" } +poseidon = { tag = "v0.1.1", git = "https://github.com/noir-lang/poseidon" } +# nodash = { git = "https://github.com/olehmisar/nodash/", tag = "v0.40.2" } diff --git a/noir/utxo/Prover.toml b/noir/utxo/Prover.toml new file mode 100644 index 0000000..6c9918f --- /dev/null +++ b/noir/utxo/Prover.toml @@ -0,0 +1,22 @@ +input_notes = [ + { note = { kind = "1", value = "10", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "1" }, secret_key = "101" }, + { note = { kind = "1", value = "5", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "2" }, secret_key = "101" }, +] + +# 8 inputs +output_notes = [ + { kind = "1", value = "1", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "3" }, + { kind = "1", value = "14", address = "0x22d68b303a6a3d416959fb363795548966049a655418ebd9eb6a818fd6d2e27b", psi = "4" }, +] + +pmessage4 = "0" + +# 4 inputs +commitments = [ + "0x1617cc49459fde170cacb26a2c9b5906c255d5bc049ef778d3f39ab6e549939a", + "0x27d184a81a508d4f328f5c8f39b3991783905abd487dd75a6e8b3a13453d1249", + "0x1b47736b2edce8b3ff918ff6c1aa4ea184a13cf279bc60433968fc08aadd2dfc", + "0x27bf84f87eb466701223a356a6827adb80c18c36de765c9d4ce791b67ff43bbb", +] + +messages = ["1", "0", "0", "0", "0", "0"] diff --git a/noir/utxo/Verifier.toml b/noir/utxo/Verifier.toml new file mode 100644 index 0000000..9700fac --- /dev/null +++ b/noir/utxo/Verifier.toml @@ -0,0 +1,7 @@ +commitments = [ + "0x1617cc49459fde170cacb26a2c9b5906c255d5bc049ef778d3f39ab6e549939a", + "0x27d184a81a508d4f328f5c8f39b3991783905abd487dd75a6e8b3a13453d1249", + "0x1b47736b2edce8b3ff918ff6c1aa4ea184a13cf279bc60433968fc08aadd2dfc", + "0x27bf84f87eb466701223a356a6827adb80c18c36de765c9d4ce791b67ff43bbb", +] +messages = ["1", "0", "0", "0", "0", "0"] diff --git a/noir/utxo/src/main.nr b/noir/utxo/src/main.nr new file mode 100644 index 0000000..7ba4853 --- /dev/null +++ b/noir/utxo/src/main.nr @@ -0,0 +1,687 @@ +use common::{ + check_commitment, check_input_note_ownership, get_address, get_note_commitment, is_multiple_kinds, InputNote, + Note, +}; +use poseidon::poseidon2; + +mod test; + +fn main( + input_notes: [InputNote; 2], + output_notes: [Note; 2], + pmessage4: Field, + commitments: pub [Field; 4], + messages: pub [Field; 5], +) { + // Check the commitments + check_commitment(input_notes[0].note, commitments[0]); + check_commitment(input_notes[1].note, commitments[1]); + check_commitment(output_notes[0], commitments[2]); + check_commitment(output_notes[1], commitments[3]); + + // Check individual outputs are not greater than 240 bits + output_notes[0].value.assert_max_bit_size::<240>(); + output_notes[1].value.assert_max_bit_size::<240>(); + + // We do not need to check the input notes values, as they must already have been added + // to the tree, and the only way for that to occur if them to be added as an output note first + // (which the check below would catch). Also, an overflow attack on the inputs would be deterimental + // to the attacker as they would have to provide more input funds, and would receive less output funds. + let input_value = input_notes[0].note.value + input_notes[1].note.value; + + // Because we have already checked the individual output notes are no greater than 240 bits, + // then the maximum of the addition can be 2^241 which means the output value can never overflow + let output_value = output_notes[0].value + output_notes[1].value; + + // Check for multiple kinds, not currently supported in this proof + let (is_multiple_kinds, _note_kind) = is_multiple_kinds([ + input_notes[0].note, + input_notes[1].note, + output_notes[0], + output_notes[1], + ]); + assert(!is_multiple_kinds, "Inconsistent kinds are not allowed"); + + // Kind of UTXO txn (in future we may have subtypes for kind, which define different encodings + // but for now its easier to define this way, so bytes[32] will always be main kind) + let kind = messages[0]; + + // Messages (only for mint/burns, otherwise all zeros) + let msg_note_kind = messages[1]; + let msg_value = messages[2]; + + // Assert message value size is max 240 bits to prevent overflow attack + msg_value.assert_max_bit_size::<240>(); + + // We only constrain the message hash for mints. For burns, any hash can be used + // as its only used by the substitutor to early release funds. Early release is + // secured by the validator, so as long as it records the burn hash it should be valid. + // A user could provide a burn hash that is already used, which would prevent + // a the substitutor from substituting the burn; this is acceptable. + let msg_hash = messages[3]; + let burn_addr = messages[4]; + + // Mint hash - we use the private message to prevent others from + // being able to frontrun the mint hash in their own utxo txn + let mint_hash = poseidon2::Poseidon2::hash([output_notes[0].psi, output_notes[1].psi], 2); + + // Burn hash - used for the burn substitutor and to verify status of an existing burn - + // could be any hash so long as its asserted in the proof and cannot be modified. We were + // planning to use the commitment of both inputs, but that is extra work and not neccessary. + let burn_hash = commitments[0]; + + if (kind == 1) { + //SEND + assert(input_value == output_value, "Input and output totals do not match"); + } else if (kind == 2) { + // MINT + // Assert mint utxo is balanced: + // - `output_value` is checked above + // - `input_value` is checked as it must have previously been an output value + // - `msg_value` is checked above (but also using that to overflow would be detrimental to the + // attacker) + assert(output_value == input_value + msg_value, "Mint output must match value message"); + // Assert mint hash + assert(mint_hash == msg_hash, "Mint hash must match message"); + // Assert note kind + assert(output_notes[0].kind == msg_note_kind, "Mint note kind must match message") + } else if (kind == 3) { + // BURN + // Prevent frontrunning the txn and changing the evm address + assert(pmessage4 == burn_addr, "messages[4] must match private input"); + // Assert burn hash + assert(burn_hash == msg_hash, "Burn hash must match message"); + // Assert burn utxo is balanced: + // - `output_value` is checked above + // - `input_value` is checked as it must have previously been an output value + // - `msg_value` is checked above + assert(input_value == output_value + msg_value, "Burn output must match value message"); + // Assert burn kind + assert(input_notes[0].note.kind == msg_note_kind, "Burn note kind must match message") + } else { + assert(false, "Invalid kind"); + } + + // Check the user owns the input notes + check_input_note_ownership(input_notes[0]); + check_input_note_ownership(input_notes[1]); +} + +fn bridged_note_kind() -> Field { + 3533694129556768672311144317398675444585744224105014452550528428861358080 +} + +#[test] +fn test_send_two_inputs_two_outputs() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: 1, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: 14, address, psi: 4 }; + + // Commitments + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test] +fn test_send_one_input_two_outputs() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: 1, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: 9, address, psi: 4 }; + + // Commitments + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test] +fn test_send_two_inputs_one_output() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address, psi: 0 }; + + // Commitments + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test(should_fail)] +fn test_send_diff_kinds() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 }; + let note_2 = Note { kind: 2, value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 }; + let note_4 = Note { kind: 2, value: 5, address, psi: 4 }; + + // Commitments + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test] +fn test_mint() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: 0, address: 0, psi: 0 }; + let note_4 = Note { kind: bridged_note_kind(), value: 30, address, psi: 3 }; + + let commitments = [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ]; + + let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2); + + // Commitments + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + commitments, + [2, bridged_note_kind(), 10, mint_hash, 0], + ) +} + +#[test] +fn test_burn() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let note_4 = Note { kind: bridged_note_kind(), value: 10, address, psi: 3 }; + + // Commitments + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [3, bridged_note_kind(), 10, get_note_commitment(note_1), 0], + ) +} + +#[test] +fn test_send_zero_value() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs - both zero value notes + let note_1 = Note { kind: bridged_note_kind(), value: 0, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + // Outputs - both zero value notes + let note_3 = Note { kind: bridged_note_kind(), value: 0, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address, psi: 0 }; + + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test] +fn test_mint_with_padding_input() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs - one real note, one padding + let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + // Outputs - note_3 is the first output (minted note), note_4 is padding or same kind + let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: 0, address: 0, psi: 0 }; + + let commitments = [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ]; + + let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2); + + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + commitments, + [2, bridged_note_kind(), 10, mint_hash, 0], + ) +} + +#[test] +fn test_burn_single_input() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs - one real note, one padding + let note_1 = Note { kind: bridged_note_kind(), value: 15, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + // Outputs - burn 10 value, keep 5 + let note_3 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 3 }; + + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [3, bridged_note_kind(), 10, get_note_commitment(note_1), 0], + ) +} +#[test(should_fail)] +fn test_mint_different_kinds() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs - mix of different kinds + let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 }; + let note_2 = Note { kind: 2, value: 3, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs - mint kind 3, first note is the minted note + let note_3 = Note { kind: 3, value: 18, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + + let commitments = [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ]; + + let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2); + + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + commitments, + [2, 3, 10, mint_hash, 0], + ) +} + +#[test] +fn test_send_large_values() { + let pk: Field = 101; + let address = get_address(pk); + + // Test with larger values (but still within 240-bit constraint) + let large_value = 1000000000; + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: large_value, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: large_value, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: large_value + 500000, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: large_value - 500000, address, psi: 4 }; + + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test] +fn test_mint_same_kind() { + let pk: Field = 101; + let address = get_address(pk); + + // Inputs - same kind + let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 10, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs - mint more of same kind, first note is the minted note + let note_3 = Note { kind: bridged_note_kind(), value: 25, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: 0, address: 0, psi: 0 }; + + let commitments = [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ]; + + let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2); + + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + commitments, + [2, bridged_note_kind(), 10, mint_hash, 0], + ) +} + +#[test(should_fail)] +fn test_overflow_input_first_note() { + let pk: Field = 101; + let address = get_address(pk); + + // Create a value that exceeds 240 bits + // 2^240 = 1766847064778384329583297500742918515827483896875618958121606201292619776 + let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777; + + // Inputs - first note has overflow value + let note_1 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: 10, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 4 }; + + // This should fail due to overflow check on first input + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test(should_fail)] +fn test_overflow_input_second_note() { + let pk: Field = 101; + let address = get_address(pk); + + // Create a value that exceeds 240 bits + let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777; + + // Inputs - second note has overflow value + let note_1 = Note { kind: bridged_note_kind(), value: 5, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs + let note_3 = Note { kind: bridged_note_kind(), value: 10, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 4 }; + + // This should fail due to overflow check on second input + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test(should_fail)] +fn test_overflow_output_first_note() { + let pk: Field = 101; + let address = get_address(pk); + + // Create a value that exceeds 240 bits + let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777; + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs - first output has overflow value + let note_3 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: 5, address, psi: 4 }; + + // This should fail due to overflow check on first output + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test(should_fail)] +fn test_overflow_output_second_note() { + let pk: Field = 101; + let address = get_address(pk); + + // Create a value that exceeds 240 bits + let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777; + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs - second output has overflow value + let note_3 = Note { kind: bridged_note_kind(), value: 5, address, psi: 3 }; + let note_4 = Note { kind: bridged_note_kind(), value: overflow_value, address, psi: 4 }; + + // This should fail due to overflow check on second output + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test] +fn test_max_allowed_value() { + let pk: Field = 101; + let address = get_address(pk); + + // Use a value that is exactly at the 240-bit limit (2^240 - 1) + let max_value = 1766847064778384329583297500742918515827483896875618958121606201292619775; + + // Inputs - both notes have max allowed value + let note_1 = Note { kind: bridged_note_kind(), value: max_value, address, psi: 1 }; + let note_2 = Note { kind: 0, value: 0, address, psi: 0 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: 0 }; + + // Outputs - transfer to single output + let note_3 = Note { kind: bridged_note_kind(), value: max_value, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address, psi: 0 }; + + // This should succeed as the value is exactly at the limit + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ], + [1, 0, 0, 0, 0], + ) +} + +#[test(should_fail)] +fn test_msg_value_overflow() { + let pk: Field = 101; + let address = get_address(pk); + + // Create a value that exceeds 240 bits + let overflow_value = 1766847064778384329583297500742918515827483896875618958121606201292619777; + + // Inputs + let note_1 = Note { kind: bridged_note_kind(), value: 10, address, psi: 1 }; + let note_2 = Note { kind: bridged_note_kind(), value: 5, address, psi: 2 }; + let input_note_1 = InputNote { note: note_1, secret_key: pk }; + let input_note_2 = InputNote { note: note_2, secret_key: pk }; + + // Outputs - mint with overflow msg_value + let note_3 = Note { kind: bridged_note_kind(), value: 15, address, psi: 3 }; + let note_4 = Note { kind: 0, value: 0, address: 0, psi: 0 }; + + let commitments = [ + get_note_commitment(note_1), + get_note_commitment(note_2), + get_note_commitment(note_3), + get_note_commitment(note_4), + ]; + + let mint_hash = poseidon2::Poseidon2::hash([note_3.psi, note_4.psi], 2); + + // This should fail due to msg_value overflow check + main( + [input_note_1, input_note_2], + [note_3, note_4], + 0, + commitments, + [2, bridged_note_kind(), overflow_value, mint_hash, 0], + ) +} diff --git a/noir/utxo/src/test.nr b/noir/utxo/src/test.nr new file mode 100644 index 0000000..8a48ded --- /dev/null +++ b/noir/utxo/src/test.nr @@ -0,0 +1,27 @@ +fn to_bytes_3(field1: Field) { + let bytes: [u8; 3] = field1.to_be_bytes(); + + assert_eq(bytes, [0, 1, 3]); + assert_eq(Field::from_be_bytes::<3>(bytes), field1); +} + +fn to_bytes_256(field1: Field) { + let bytes: [u8; 31] = field1.to_be_bytes(); + assert_eq( + bytes, + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 3, + ], + ); +} + +#[test] +fn test_main() { + to_bytes_3(259) +} + +#[test] +fn test_max_value() { + to_bytes_256(259); +} diff --git a/pkg/aggregator-interface/Cargo.toml b/pkg/aggregator-interface/Cargo.toml new file mode 100644 index 0000000..37c6cc9 --- /dev/null +++ b/pkg/aggregator-interface/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "aggregator-interface" +version = "0.1.0" +edition = "2024" +publish = false + +[dependencies] +barretenberg-interface = { workspace = true } +contextful = { workspace = true } +element = { workspace = true } +node-interface = { workspace = true } +zk-primitives = { workspace = true } + +async-trait = { workspace = true } +thiserror = { workspace = true } +unimock = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/aggregator-interface/src/error.rs b/pkg/aggregator-interface/src/error.rs new file mode 100644 index 0000000..6e710e7 --- /dev/null +++ b/pkg/aggregator-interface/src/error.rs @@ -0,0 +1,37 @@ +use contextful::Contextful; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("[aggregator-interface]: contract error")] + ContractError(#[from] Contextful), + + #[error("[aggregator-interface]: block prover error")] + BlockProverError(#[from] Contextful), + + #[error("[aggregator-interface]: missing approval block after batch")] + MissingApprovalBlock, + + #[error("[aggregator-interface]: batch blocks unexpectedly empty")] + EmptyBatch, + + #[error("[aggregator-interface]: implementation specific error")] + ImplementationSpecific(Box), +} + +#[derive(Debug, thiserror::Error)] +pub enum ContractError { + #[error("[aggregator-interface]: contract root mismatch")] + RootMismatch, + + #[error("[aggregator-interface]: invalid proof submitted to contract")] + InvalidProof, + + #[error("[aggregator-interface]: implementation specific error")] + ImplementationSpecific(Box), +} + +#[derive(Debug, thiserror::Error)] +pub enum BlockProverError { + #[error("[aggregator-interface]: implementation specific error")] + ImplementationSpecific(Box), +} diff --git a/pkg/aggregator-interface/src/lib.rs b/pkg/aggregator-interface/src/lib.rs new file mode 100644 index 0000000..c002065 --- /dev/null +++ b/pkg/aggregator-interface/src/lib.rs @@ -0,0 +1,133 @@ +mod error; + +use std::sync::Arc; + +use async_trait::async_trait; +use barretenberg_interface::BbBackend; +use element::Element; +use node_interface::BlockWithInfo; +use unimock::unimock; +use zk_primitives::{AggAggProof, AggFinalProof, UtxoProofBundleWithMerkleProofs}; + +pub use error::{BlockProverError, ContractError, Error}; + +pub const UTXO_AGG_NUMBER: usize = 3; +pub const UTXO_AGGREGATIONS: usize = 2; + +#[unimock(api=PrioritizableBbBackendMock)] +pub trait PrioritizableBbBackend: BbBackend + Send + Sync { + fn with_priority(&self, priority: u64) -> Arc; +} + +/// Data required to prove a batch of blocks. +#[derive(Debug, Clone)] +pub struct PreparedBatch { + pub blocks: Vec, + pub prepared_blocks: Vec, + pub old_root: Element, + pub new_root: Element, +} + +/// A proven batch ready for submission. +#[derive(Debug, Clone)] +pub struct ProvenBatch { + pub final_proof: AggFinalProof, + pub blocks: Vec, + pub other_hash: [u8; 32], +} + +#[unimock(api=AggregatorMock)] +#[async_trait] +pub trait Aggregator: Send + Sync { + /// Prepares the next available batch of blocks for aggregation. + async fn prepare_next_batch(&self) -> Result; + + /// Generates an aggregation proof for the provided batch. + async fn prove_batch( + &self, + batch: PreparedBatch, + bb_backend: Arc, + ) -> Result; + + /// Submits the proven batch to the rollup contract. + async fn submit_batch(&self, batch: ProvenBatch) -> Result<(), Error>; +} + +/// Result of a batch preparation attempt. +#[derive(Debug, Clone)] +pub enum PreparationOutcome { + Success(PreparedBatch), + InsufficientBlocks { + start_height: u64, + available: usize, + required: usize, + }, +} + +#[derive(Debug, Clone)] +pub struct RollupInput { + pub proof: Vec, + pub old_root: Element, + pub new_root: Element, + pub commit_hash: Element, + pub utxo_messages: Vec, + pub kzg: Vec, + pub other_hash: [u8; 32], + pub height: u64, + pub signatures: Vec>, + pub gas_per_burn_call: u128, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PreparedBlock { + pub height: u64, + pub chunks: [PreparedChunk; UTXO_AGGREGATIONS], +} + +impl PreparedBlock { + #[must_use] + pub fn height(&self) -> u64 { + self.height + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct PreparedChunk { + pub old_root: Element, + pub new_root: Element, + pub bundles: [UtxoProofBundleWithMerkleProofs; UTXO_AGG_NUMBER], +} + +#[unimock(api=RollupContractMock)] +#[async_trait] +pub trait RollupContract: Send + Sync { + async fn height(&self) -> Result; + async fn root_hash(&self) -> Result; + async fn submit_rollup(&self, rollup: &RollupInput) -> Result<(), ContractError>; +} + +#[unimock(api=BlockProverMock)] +#[async_trait] +pub trait BlockProver: Send + Sync { + async fn prepare( + &self, + height: u64, + tree: &mut dyn RollupTree, + ) -> Result; + + async fn prove( + &self, + prepared: PreparedBlock, + bb_backend: Arc, + ) -> Result; +} + +#[unimock(api=RollupTreeMock)] +pub trait RollupTree: Send { + fn root_hash(&self) -> Element; + fn height(&self) -> u64; + fn set_height(&mut self, height: u64); + fn sibling_path(&self, element: Element) -> Result, BlockProverError>; + fn remove(&mut self, element: Element) -> Result<(), BlockProverError>; + fn insert(&mut self, entries: &[(Element, u64)]) -> Result<(), BlockProverError>; +} diff --git a/pkg/aggregator/Cargo.toml b/pkg/aggregator/Cargo.toml new file mode 100644 index 0000000..e35e3d7 --- /dev/null +++ b/pkg/aggregator/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "aggregator" +version = "0.1.0" +edition = "2024" +publish = false + +[dependencies] +aggregator-interface = { workspace = true } +barretenberg-interface = { workspace = true } +node-interface = { workspace = true } +element = { workspace = true } +contracts = { workspace = true } +contextful = { workspace = true } +zk-circuits = { workspace = true } +primitives = { workspace = true } +zk-primitives = { workspace = true } +prover = { workspace = true } +smirk = { workspace = true } +tokio = { workspace = true, features = ["macros", "rt-multi-thread", "sync", "time"] } +borsh = { workspace = true } +sha3 = { workspace = true } +futures = { workspace = true } + +async-trait = { workspace = true } +tracing = { workspace = true } +thiserror = { workspace = true } +workspace-hack.workspace = true +web3 = { workspace = true } +unimock = { workspace = true } + +[dev-dependencies] +hash = { workspace = true } diff --git a/pkg/aggregator/src/aggregator/aggregation.rs b/pkg/aggregator/src/aggregator/aggregation.rs new file mode 100644 index 0000000..8478940 --- /dev/null +++ b/pkg/aggregator/src/aggregator/aggregation.rs @@ -0,0 +1,79 @@ +use std::{io, sync::Arc}; + +use aggregator_interface::Error; +use barretenberg_interface::BbBackend; +use futures::future::join_all; +use zk_circuits::circuits::generated::agg_agg::AggAggInput as CircuitAggAggInput; +use zk_primitives::{AggAgg, AggAggProof, AggProof}; + +use crate::aggregator::Aggregator; + +impl Aggregator { + pub(super) async fn aggregate_block_proofs( + &self, + proofs: Vec, + bb_backend: Arc, + ) -> Result { + if proofs.len() != self.block_batch_size { + return Err(Error::ImplementationSpecific(Box::new(io::Error::other( + format!( + "expected {} block proofs, got {}", + self.block_batch_size, + proofs.len() + ), + )))); + } + + let mut level: Vec = proofs + .into_iter() + .map(|proof| AggProof::AggAgg(Box::new(proof))) + .collect(); + + while level.len() > 1 { + if !level.len().is_multiple_of(2) { + return Err(Error::ImplementationSpecific(Box::new(io::Error::other( + format!( + "aggregation level requires an even number of proofs, got {}", + level.len() + ), + )))); + } + + let mut futures = Vec::with_capacity(level.len() / 2); + let mut iter = level.into_iter(); + while let (Some(left), Some(right)) = (iter.next(), iter.next()) { + let aggregated = AggAgg::new([left, right]); + let aggregated_input = CircuitAggAggInput::from(aggregated); + let agg_agg_circuit = Arc::clone(&self.agg_agg_circuit); + let bb_backend = Arc::clone(&bb_backend); + + futures.push(async move { + let proof = agg_agg_circuit + .prove(&aggregated_input, bb_backend) + .await + .map_err(|err| Error::ImplementationSpecific(Box::new(err)))?; + Ok::(AggAggProof::from(proof)) + }); + } + + let results = join_all(futures).await; + let mut next_level = Vec::with_capacity(results.len()); + for result in results { + let proof = result?; + next_level.push(AggProof::AggAgg(Box::new(proof))); + } + + level = next_level; + } + + match level.pop() { + Some(AggProof::AggAgg(proof)) => Ok(*proof), + Some(AggProof::AggUtxo(_)) => Err(Error::ImplementationSpecific(Box::new( + io::Error::other("unexpected agg_utxo proof"), + ))), + None => Err(Error::ImplementationSpecific(Box::new(io::Error::other( + "missing aggregated proof", + )))), + } + } +} diff --git a/pkg/aggregator/src/aggregator/fetch.rs b/pkg/aggregator/src/aggregator/fetch.rs new file mode 100644 index 0000000..303fb03 --- /dev/null +++ b/pkg/aggregator/src/aggregator/fetch.rs @@ -0,0 +1,90 @@ +use aggregator_interface::Error; +use node_interface::BlockWithInfo; +use primitives::block_height::BlockHeight; +use std::{io::Error as IoError, time::Duration}; +use tokio::time::sleep; + +use crate::aggregator::{Aggregator, utils::map_node_error}; + +#[cfg(test)] +const EMPTY_FETCH_RETRY_DELAY: Duration = Duration::from_millis(1); +#[cfg(not(test))] +const EMPTY_FETCH_RETRY_DELAY: Duration = Duration::from_secs(1); + +impl Aggregator { + pub(super) async fn fetch_blocks( + &self, + start_height: u64, + ) -> Result, Error> { + self.fetch_blocks_exact(start_height, self.block_batch_size) + .await + } + + pub(super) async fn fetch_blocks_exact( + &self, + start_height: u64, + limit: usize, + ) -> Result, Error> { + let mut blocks = Vec::with_capacity(limit); + let mut next_height = start_height; + + while blocks.len() < limit { + let remaining = limit - blocks.len(); + let mut fetched = self + .fetch_blocks_with_limit(next_height, remaining, true) + .await?; + + if fetched.is_empty() { + sleep(EMPTY_FETCH_RETRY_DELAY).await; + continue; + } + + let last_height = fetched + .last() + .map(|block| block.block.content.header.height.0) + .ok_or_else(|| { + Error::ImplementationSpecific(Box::new(IoError::other( + "non-empty fetch expected while fetching exact batch", + ))) + })?; + + blocks.append(&mut fetched); + + let Some(height_after_last) = last_height.checked_add(1) else { + return Err(Error::ImplementationSpecific(Box::new(IoError::other( + "block height overflow while fetching exact batch", + )))); + }; + next_height = height_after_last; + } + + Ok(blocks) + } + + pub(super) async fn fetch_blocks_with_limit( + &self, + start_height: u64, + limit: usize, + skip_empty: bool, + ) -> Result, Error> { + let response = self + .node_client + .blocks(BlockHeight(start_height), limit, skip_empty) + .await + .map_err(map_node_error)?; + + Ok(response + .blocks + .into_iter() + .filter(|block| block.block.content.header.height.0 >= start_height) + .take(limit) + .collect()) + } + + pub(super) async fn fetch_block(&self, height: u64) -> Result, Error> { + let mut blocks = self.fetch_blocks_with_limit(height, 1, false).await?; + Ok(blocks + .pop() + .filter(|block| block.block.content.header.height.0 == height)) + } +} diff --git a/pkg/aggregator/src/aggregator/mod.rs b/pkg/aggregator/src/aggregator/mod.rs new file mode 100644 index 0000000..a85a514 --- /dev/null +++ b/pkg/aggregator/src/aggregator/mod.rs @@ -0,0 +1,58 @@ +use std::sync::Arc; + +use aggregator_interface::{BlockProver, RollupContract, RollupTree}; +use node_interface::NodeClient; +use tokio::sync::Mutex; + +pub mod aggregation; +pub mod fetch; +pub mod trait_impl; +pub mod utils; + +#[cfg(test)] +mod tests; + +use crate::{AggAggCircuitInterface, AggFinalCircuitInterface}; + +#[derive(Clone)] +pub struct Aggregator { + pub(crate) node_client: Arc, + pub(crate) rollup_contract: Arc, + pub(crate) block_prover: Arc, + pub(crate) rollup_tree: Arc>>, + pub(crate) block_batch_size: usize, + pub(crate) gas_per_burn_call: u128, + pub(crate) agg_agg_circuit: Arc, + pub(crate) agg_final_circuit: Arc, +} + +impl Aggregator { + #[allow(clippy::too_many_arguments)] + pub fn new( + node_client: Arc, + rollup_contract: Arc, + block_prover: Arc, + rollup_tree: Box, + block_batch_size: usize, + gas_per_burn_call: u128, + agg_agg_circuit: Arc, + agg_final_circuit: Arc, + ) -> Self { + assert!( + block_batch_size >= 2 && block_batch_size.is_power_of_two(), + "block_batch_size must be a power-of-two >= 2" + ); + assert!(gas_per_burn_call > 0, "gas_per_burn_call must be > 0"); + + Self { + node_client, + rollup_contract, + block_prover, + rollup_tree: Arc::new(Mutex::new(rollup_tree)), + block_batch_size, + gas_per_burn_call, + agg_agg_circuit, + agg_final_circuit, + } + } +} diff --git a/pkg/aggregator/src/aggregator/tests/aggregation.rs b/pkg/aggregator/src/aggregator/tests/aggregation.rs new file mode 100644 index 0000000..e724e25 --- /dev/null +++ b/pkg/aggregator/src/aggregator/tests/aggregation.rs @@ -0,0 +1,130 @@ +use super::*; +use aggregator_interface::{ + BlockProver as BlockProverTrait, RollupContract as RollupContractTrait, RollupTree, +}; +use barretenberg_interface::BbBackend; +use element::Element; +use hash::hash_merge; +use node_interface::NodeClient; +use std::sync::Arc; +use unimock::{MockFn, Unimock, matching}; +use zk_circuits::Error as CircuitError; +use zk_circuits::Proof; +use zk_circuits::circuits::generated::agg_agg::AggAggInput as CircuitAggAggInput; +use zk_primitives::AggAggPublicInput; + +use crate::CircuitMock; + +#[tokio::test] +async fn aggregates_multiple_block_proofs_hierarchically() { + const BLOCK_BATCH_SIZE: usize = 4; + let rolled_root = Element::new(100); + let roots = [ + Element::new(200), + Element::new(300), + Element::new(400), + Element::new(500), + ]; + + let block_proofs = vec![ + block_agg_proof(rolled_root, roots[0], Element::new(601)), + block_agg_proof(roots[0], roots[1], Element::new(602)), + block_agg_proof(roots[1], roots[2], Element::new(603)), + block_agg_proof(roots[2], roots[3], Element::new(604)), + ]; + + let aggregated_messages = [Element::ZERO; 1000]; + let left_commit = hash_merge([ + block_proofs[0].public_inputs.commit_hash, + block_proofs[1].public_inputs.commit_hash, + ]); + let right_commit = hash_merge([ + block_proofs[2].public_inputs.commit_hash, + block_proofs[3].public_inputs.commit_hash, + ]); + let final_commit = hash_merge([left_commit, right_commit]); + + let aggregated_left_inputs = AggAggPublicInput { + verification_key_hash: [Element::new(10), Element::new(11)], + old_root: rolled_root, + new_root: roots[1], + commit_hash: left_commit, + messages: aggregated_messages, + }; + let aggregated_right_inputs = AggAggPublicInput { + verification_key_hash: [Element::new(10), Element::new(11)], + old_root: roots[1], + new_root: roots[3], + commit_hash: right_commit, + messages: aggregated_messages, + }; + let aggregated_final_inputs = AggAggPublicInput { + verification_key_hash: [Element::new(10), Element::new(11)], + old_root: rolled_root, + new_root: roots[3], + commit_hash: final_commit, + messages: aggregated_messages, + }; + let aggregated_left_inputs_ref = leak(aggregated_left_inputs.clone()); + let aggregated_right_inputs_ref = leak(aggregated_right_inputs.clone()); + let aggregated_final_inputs_ref = leak(aggregated_final_inputs.clone()); + + let bb_backend: Arc = Arc::new(Unimock::new(())); + + let node_client: Arc = Arc::new(Unimock::new(())); + let rollup_contract: Arc = Arc::new(Unimock::new(())); + let block_prover: Arc = Arc::new(Unimock::new(())); + let rollup_tree: Box = Box::new(Unimock::new(())); + + let agg_agg_proofs = [ + agg_agg_proof_from_inputs(&aggregated_left_inputs), + agg_agg_proof_from_inputs(&aggregated_right_inputs), + agg_agg_proof_from_inputs(&aggregated_final_inputs), + ]; + let agg_agg_circuit: Arc = Arc::new(Unimock::new(( + CircuitMock::prove + .with_types::() + .some_call(matching!((agg_input, _) + if agg_input.old_root == aggregated_left_inputs_ref.old_root + && agg_input.new_root == aggregated_left_inputs_ref.new_root)) + .returns(Ok::<_, CircuitError>(Proof::from( + agg_agg_proofs[0].clone(), + ))), + CircuitMock::prove + .with_types::() + .some_call(matching!((agg_input, _) + if agg_input.old_root == aggregated_right_inputs_ref.old_root + && agg_input.new_root == aggregated_right_inputs_ref.new_root)) + .returns(Ok::<_, CircuitError>(Proof::from( + agg_agg_proofs[1].clone(), + ))), + CircuitMock::prove + .with_types::() + .some_call(matching!((agg_input, _) + if agg_input.old_root == aggregated_final_inputs_ref.old_root + && agg_input.new_root == aggregated_final_inputs_ref.new_root)) + .returns(Ok::<_, CircuitError>(Proof::from( + agg_agg_proofs[2].clone(), + ))), + ))); + let agg_final_circuit: Arc = Arc::new(Unimock::new(())); + let aggregator = Aggregator::new( + node_client, + rollup_contract, + block_prover, + rollup_tree, + BLOCK_BATCH_SIZE, + TEST_GAS_PER_BURN_CALL, + agg_agg_circuit, + agg_final_circuit, + ); + + let aggregated_proof = aggregator + .aggregate_block_proofs(block_proofs, Arc::clone(&bb_backend)) + .await + .expect("proof aggregation succeeds"); + + assert_eq!(aggregated_proof.public_inputs.old_root, rolled_root); + assert_eq!(aggregated_proof.public_inputs.new_root, roots[3]); + assert_eq!(aggregated_proof.public_inputs.commit_hash, final_commit); +} diff --git a/pkg/aggregator/src/aggregator/tests/failures.rs b/pkg/aggregator/src/aggregator/tests/failures.rs new file mode 100644 index 0000000..e764c9b --- /dev/null +++ b/pkg/aggregator/src/aggregator/tests/failures.rs @@ -0,0 +1,196 @@ +// lint-long-file-override allow-max-lines=300 +use super::*; +use aggregator_interface::{ + Aggregator as AggregatorTrait, BlockProver as BlockProverTrait, BlockProverMock, + PreparationOutcome, PreparedBlock, RollupTree, RollupTreeMock, +}; +use barretenberg_interface::BbBackend; +use element::Element; +use node_interface::{ListBlocksResponse, NodeClient, NodeClientMock}; +use primitives::pagination::OpaqueCursor; +use std::sync::Arc; +use unimock::{MockFn, Unimock, matching}; +use zk_circuits::circuits::generated::agg_agg::AggAggInput as CircuitAggAggInput; +use zk_circuits::circuits::generated::agg_final::AggFinalInput as CircuitAggFinalInput; +use zk_circuits::{Error as CircuitError, Proof}; +use zk_primitives::{ + AggAggProof, AggAggPublicInput, AggFinalProof, AggFinalPublicInput, OracleProofBytes, + ProofBytes, +}; + +use crate::CircuitMock; + +#[tokio::test] +async fn step_errors_when_next_block_missing() { + let rolled_height = 10; + let rolled_root = Element::new(100); + let first_height = rolled_height + 1; + let second_height = rolled_height + 3; + let first_root = Element::new(200); + let second_root = Element::new(300); + + let first_block = block_with_single_txn(first_height, first_root, vec![signature(1)], 11); + let second_block = block_with_single_txn(second_height, second_root, vec![signature(2)], 22); + + let node_blocks_response = ListBlocksResponse { + blocks: vec![first_block.clone(), second_block.clone()], + cursor: OpaqueCursor::default(), + }; + let empty_next_block_response = ListBlocksResponse { + blocks: vec![], + cursor: OpaqueCursor::default(), + }; + + let first_block_proof = block_agg_proof(rolled_root, first_root, Element::new(601)); + let second_block_proof = block_agg_proof(first_root, second_root, Element::new(602)); + + let mut aggregated_messages = [Element::ZERO; 1000]; + aggregated_messages[0] = Element::new(9); + + let aggregated_agg_public_inputs = AggAggPublicInput { + verification_key_hash: [Element::new(10), Element::new(11)], + old_root: rolled_root, + new_root: second_root, + commit_hash: Element::new(700), + messages: aggregated_messages, + }; + + let aggregated_final_public_inputs = AggFinalPublicInput { + old_root: rolled_root, + new_root: second_root, + commit_hash: aggregated_agg_public_inputs.commit_hash, + messages: aggregated_messages.to_vec(), + }; + + let aggregated_agg_proof = AggAggProof { + proof: ProofBytes::default(), + public_inputs: aggregated_agg_public_inputs.clone(), + kzg: vec![], + }; + let aggregated_agg_inputs_err_ref = leak(aggregated_agg_public_inputs.clone()); + let aggregated_final_inputs_err_ref = leak(aggregated_final_public_inputs.clone()); + + let agg_final_proof = AggFinalProof { + proof: OracleProofBytes(vec![2u8; AGG_FINAL_PROOF_ELEMENT_COUNT * BYTES_PER_ELEMENT]), + public_inputs: aggregated_final_public_inputs.clone(), + kzg: vec![], + }; + + let first_height_ref = leak(first_height); + let second_height_ref = leak(second_height); + let node_blocks_response_ref = leak(node_blocks_response.clone()); + let empty_next_block_response_ref = leak(empty_next_block_response.clone()); + let first_block_proof_ref = leak(first_block_proof.clone()); + let second_block_proof_ref = leak(second_block_proof.clone()); + let bb_backend: Arc = Arc::new(Unimock::new(())); + + let node_client: Arc = Arc::new(Unimock::new(( + NodeClientMock::blocks + .next_call(matching!((start_height, limit, skip_empty) + if *start_height == BlockHeight(*first_height_ref) + && *limit >= DEFAULT_BLOCK_BATCH_SIZE + && *skip_empty)) + .returns(Ok(node_blocks_response_ref.clone())), + NodeClientMock::blocks + .next_call(matching!((start_height, limit, skip_empty) + if *start_height == BlockHeight(*second_height_ref + 1) + && *limit == 1 + && !*skip_empty)) + .returns(Ok(empty_next_block_response_ref.clone())), + ))); + + let rollup_contract: Arc = Arc::new(Unimock::new(())); + + let first_prepared = PreparedBlock { + height: *first_height_ref, + chunks: [ + dummy_chunk(Element::ZERO, Element::ZERO), + dummy_chunk(Element::ZERO, Element::ZERO), + ], + }; + let second_prepared = PreparedBlock { + height: *second_height_ref, + chunks: [ + dummy_chunk(Element::ZERO, Element::ZERO), + dummy_chunk(Element::ZERO, Element::ZERO), + ], + }; + let block_prover: Arc = Arc::new(Unimock::new(( + BlockProverMock::prepare + .next_call(matching!((height, _tree) if *height == *first_height_ref)) + .returns(Ok(first_prepared.clone())), + BlockProverMock::prepare + .next_call(matching!((height, _tree) if *height == *second_height_ref)) + .returns(Ok(second_prepared.clone())), + BlockProverMock::prove + .next_call(matching!((prepared, _) if prepared.height == *first_height_ref)) + .returns(Ok(first_block_proof_ref.clone())), + BlockProverMock::prove + .next_call(matching!((prepared, _) if prepared.height == *second_height_ref)) + .returns(Ok(second_block_proof_ref.clone())), + ))); + + let rollup_tree: Box = Box::new(Unimock::new(( + RollupTreeMock::height + .next_call(matching!(())) + .returns(rolled_height), + RollupTreeMock::root_hash + .next_call(matching!(())) + .returns(rolled_root), + RollupTreeMock::height + .next_call(matching!(())) + .returns(rolled_height), + RollupTreeMock::root_hash + .next_call(matching!(())) + .returns(rolled_root), + RollupTreeMock::root_hash + .next_call(matching!(())) + .returns(second_root), + RollupTreeMock::set_height + .next_call(matching!((height) if *height == *second_height_ref)) + .returns(()), + ))); + let agg_agg_circuit: Arc = Arc::new(Unimock::new( + CircuitMock::prove + .with_types::() + .next_call(matching!((agg_input, _) + if agg_input.old_root == aggregated_agg_inputs_err_ref.old_root + && agg_input.new_root == aggregated_agg_inputs_err_ref.new_root)) + .returns(Ok::<_, CircuitError>(Proof::from( + aggregated_agg_proof.clone(), + ))), + )); + let agg_final_circuit: Arc = Arc::new(Unimock::new( + CircuitMock::prove + .with_types::() + .next_call(matching!((final_input, _) + if final_input.old_root == aggregated_final_inputs_err_ref.old_root + && final_input.new_root == aggregated_final_inputs_err_ref.new_root)) + .returns(Ok::<_, CircuitError>(Proof::from(agg_final_proof.clone()))), + )); + let aggregator = Aggregator::new( + node_client, + rollup_contract, + block_prover, + rollup_tree, + DEFAULT_BLOCK_BATCH_SIZE, + TEST_GAS_PER_BURN_CALL, + agg_agg_circuit, + agg_final_circuit, + ); + + let prepared = aggregator.prepare_next_batch().await.unwrap(); + let batch = match prepared { + PreparationOutcome::Success(batch) => batch, + _ => panic!("Expected success"), + }; + let proven = aggregator + .prove_batch(batch, Arc::clone(&bb_backend)) + .await + .unwrap(); + let err = aggregator.submit_batch(proven).await.unwrap_err(); + assert!(matches!( + err, + aggregator_interface::Error::MissingApprovalBlock + )); +} diff --git a/pkg/aggregator/src/aggregator/tests/fetch.rs b/pkg/aggregator/src/aggregator/tests/fetch.rs new file mode 100644 index 0000000..561b073 --- /dev/null +++ b/pkg/aggregator/src/aggregator/tests/fetch.rs @@ -0,0 +1,94 @@ +use super::*; +use aggregator_interface::{ + BlockProver as BlockProverTrait, RollupContract as RollupContractTrait, RollupTree, +}; +use element::Element; +use node_interface::{ListBlocksResponse, NodeClient, NodeClientMock}; +use primitives::pagination::OpaqueCursor; +use std::sync::Arc; +use unimock::{MockFn, Unimock, matching}; + +fn new_aggregator(node_client: Arc) -> Aggregator { + let rollup_contract: Arc = Arc::new(Unimock::new(())); + let block_prover: Arc = Arc::new(Unimock::new(())); + let rollup_tree: Box = Box::new(Unimock::new(())); + let agg_agg_circuit: Arc = Arc::new(Unimock::new(())); + let agg_final_circuit: Arc = Arc::new(Unimock::new(())); + + Aggregator::new( + node_client, + rollup_contract, + block_prover, + rollup_tree, + DEFAULT_BLOCK_BATCH_SIZE, + TEST_GAS_PER_BURN_CALL, + agg_agg_circuit, + agg_final_circuit, + ) +} + +#[tokio::test] +async fn fetch_blocks_exact_refetches_until_limit_is_met() { + let first_block = block_with_single_txn(2, Element::new(10), vec![signature(1)], 101); + let second_block = block_with_single_txn(4, Element::new(20), vec![signature(2)], 202); + + let node_client: Arc = Arc::new(Unimock::new(( + NodeClientMock::blocks + .next_call(matching!((BlockHeight(2), 2, true))) + .returns(Ok(ListBlocksResponse { + blocks: vec![first_block], + cursor: OpaqueCursor::default(), + })), + NodeClientMock::blocks + .next_call(matching!((BlockHeight(3), 1, true))) + .returns(Ok(ListBlocksResponse { + blocks: vec![second_block], + cursor: OpaqueCursor::default(), + })), + ))); + let aggregator = new_aggregator(node_client); + + let blocks = aggregator.fetch_blocks_exact(2, 2).await.unwrap(); + let heights = blocks + .into_iter() + .map(|block| block.block.content.header.height.0) + .collect::>(); + + assert_eq!(heights, vec![2, 4]); +} + +#[tokio::test] +async fn fetch_blocks_exact_retries_when_refetch_is_empty() { + let first_block = block_with_single_txn(2, Element::new(10), vec![signature(1)], 101); + let second_block = block_with_single_txn(5, Element::new(20), vec![signature(2)], 202); + + let node_client: Arc = Arc::new(Unimock::new(( + NodeClientMock::blocks + .next_call(matching!((BlockHeight(2), 2, true))) + .returns(Ok(ListBlocksResponse { + blocks: vec![first_block], + cursor: OpaqueCursor::default(), + })), + NodeClientMock::blocks + .next_call(matching!((BlockHeight(3), 1, true))) + .returns(Ok(ListBlocksResponse { + blocks: vec![], + cursor: OpaqueCursor::default(), + })), + NodeClientMock::blocks + .next_call(matching!((BlockHeight(3), 1, true))) + .returns(Ok(ListBlocksResponse { + blocks: vec![second_block], + cursor: OpaqueCursor::default(), + })), + ))); + let aggregator = new_aggregator(node_client); + + let blocks = aggregator.fetch_blocks_exact(2, 2).await.unwrap(); + let heights = blocks + .into_iter() + .map(|block| block.block.content.header.height.0) + .collect::>(); + + assert_eq!(heights, vec![2, 5]); +} diff --git a/pkg/aggregator/src/aggregator/tests/lifecycle.rs b/pkg/aggregator/src/aggregator/tests/lifecycle.rs new file mode 100644 index 0000000..6a25d0b --- /dev/null +++ b/pkg/aggregator/src/aggregator/tests/lifecycle.rs @@ -0,0 +1,228 @@ +// lint-long-file-override allow-max-lines=300 +use super::*; +use aggregator_interface::{ + Aggregator as AggregatorTrait, BlockProver as BlockProverTrait, BlockProverMock, + PreparationOutcome, PreparedBlock, RollupContract as RollupContractTrait, RollupContractMock, + RollupTree, RollupTreeMock, +}; +use barretenberg_interface::BbBackend; +use element::Element; +use node_interface::{ListBlocksResponse, NodeClient, NodeClientMock}; +use primitives::pagination::OpaqueCursor; +use std::sync::Arc; +use unimock::{MockFn, Unimock, matching}; +use zk_circuits::Error as CircuitError; +use zk_circuits::Proof; +use zk_circuits::circuits::generated::agg_agg::AggAggInput as CircuitAggAggInput; +use zk_circuits::circuits::generated::agg_final::AggFinalInput as CircuitAggFinalInput; +use zk_primitives::{ + AggAggProof, AggAggPublicInput, AggFinalProof, AggFinalPublicInput, OracleProofBytes, + ProofBytes, +}; + +use crate::CircuitMock; + +#[tokio::test] +async fn step_rolls_two_blocks_and_submits_rollup() { + let rolled_height = 10; + let rolled_root = Element::new(100); + let first_height = rolled_height + 1; + let second_height = rolled_height + 3; + let first_root = Element::new(200); + let second_root = Element::new(300); + let next_block_signatures = vec![signature(1), signature(2)]; + + let first_block = block_with_single_txn(first_height, first_root, vec![signature(3)], 11); + let second_block = block_with_single_txn(second_height, second_root, vec![signature(4)], 22); + let third_height = second_height + 1; + let third_root = Element::new(400); + let third_block = + block_with_single_txn(third_height, third_root, next_block_signatures.clone(), 33); + + let node_blocks_response = ListBlocksResponse { + blocks: vec![first_block.clone(), second_block.clone()], + cursor: OpaqueCursor::default(), + }; + let next_block_response = ListBlocksResponse { + blocks: vec![third_block.clone()], + cursor: OpaqueCursor::default(), + }; + + let first_block_proof = block_agg_proof(rolled_root, first_root, Element::new(501)); + let second_block_proof = block_agg_proof(first_root, second_root, Element::new(502)); + + let mut aggregated_messages = [Element::ZERO; 1000]; + aggregated_messages[0] = Element::new(5); + aggregated_messages[1] = Element::new(6); + + let aggregated_agg_public_inputs = AggAggPublicInput { + verification_key_hash: [Element::new(7), Element::new(8)], + old_root: rolled_root, + new_root: second_root, + commit_hash: Element::new(999), + messages: aggregated_messages, + }; + + let aggregated_final_public_inputs = AggFinalPublicInput { + old_root: rolled_root, + new_root: second_root, + commit_hash: aggregated_agg_public_inputs.commit_hash, + messages: aggregated_messages.to_vec(), + }; + let aggregated_agg_inputs_ref = leak(aggregated_agg_public_inputs.clone()); + let aggregated_final_inputs_ref = leak(aggregated_final_public_inputs.clone()); + + let aggregated_agg_proof = AggAggProof { + proof: ProofBytes::default(), + public_inputs: aggregated_agg_public_inputs.clone(), + kzg: vec![], + }; + let expected_proof_bytes = vec![1u8; AGG_FINAL_PROOF_ELEMENT_COUNT * BYTES_PER_ELEMENT]; + let final_proof = AggFinalProof { + proof: OracleProofBytes(expected_proof_bytes.clone()), + public_inputs: aggregated_final_public_inputs.clone(), + kzg: vec![], + }; + + let first_height_ref = leak(first_height); + let second_height_ref = leak(second_height); + let rolled_root_ref = leak(rolled_root); + let second_root_ref = leak(second_root); + let commit_hash_ref = leak(aggregated_agg_public_inputs.commit_hash); + let expected_messages = aggregated_final_public_inputs.messages.clone(); + let expected_messages_ref = leak(expected_messages.clone()); + let expected_proof_bytes_ref = leak(expected_proof_bytes.clone()); + let expected_other_hash = utils::block_header_hash(&second_block.block.content.header).unwrap(); + let expected_other_hash_ref = leak(expected_other_hash); + let expected_signature_bytes: Vec> = next_block_signatures + .iter() + .map(|sig| sig.inner().to_vec()) + .collect(); + let expected_signature_bytes_ref = leak(expected_signature_bytes.clone()); + let node_blocks_response_ref = leak(node_blocks_response.clone()); + let next_block_response_ref = leak(next_block_response.clone()); + let first_block_proof_ref = leak(first_block_proof.clone()); + let second_block_proof_ref = leak(second_block_proof.clone()); + + let bb_backend: Arc = Arc::new(Unimock::new(())); + + let node_client: Arc = Arc::new(Unimock::new(( + NodeClientMock::blocks + .next_call(matching!((start_height, limit, skip_empty) + if *start_height == BlockHeight(*first_height_ref) + && *limit >= DEFAULT_BLOCK_BATCH_SIZE + && *skip_empty)) + .returns(Ok(node_blocks_response_ref.clone())), + NodeClientMock::blocks + .next_call(matching!((start_height, limit, skip_empty) + if *start_height == BlockHeight(*second_height_ref + 1) + && *limit == 1 + && !*skip_empty)) + .returns(Ok(next_block_response_ref.clone())), + ))); + + let rollup_contract: Arc = Arc::new(Unimock::new( + RollupContractMock::submit_rollup + .next_call(matching!((rollup) + if rollup.height == *second_height_ref + && rollup.old_root == *rolled_root_ref + && rollup.new_root == *second_root_ref + && rollup.commit_hash == *commit_hash_ref + && rollup.utxo_messages == *expected_messages_ref + && rollup.proof == *expected_proof_bytes_ref + && rollup.other_hash == *expected_other_hash_ref + && rollup.signatures == *expected_signature_bytes_ref + && rollup.gas_per_burn_call == GAS_PER_BURN_CALL)) + .returns(Ok(())), + )); + + let first_prepared = PreparedBlock { + height: *first_height_ref, + chunks: [ + dummy_chunk(*rolled_root_ref, first_root), + dummy_chunk(Element::ZERO, Element::ZERO), + ], + }; + let second_prepared = PreparedBlock { + height: *second_height_ref, + chunks: [ + dummy_chunk(first_root, *second_root_ref), + dummy_chunk(Element::ZERO, Element::ZERO), + ], + }; + let block_prover: Arc = Arc::new(Unimock::new(( + BlockProverMock::prepare + .next_call(matching!((height, _tree) if *height == *first_height_ref)) + .returns(Ok(first_prepared.clone())), + BlockProverMock::prepare + .next_call(matching!((height, _tree) if *height == *second_height_ref)) + .returns(Ok(second_prepared.clone())), + BlockProverMock::prove + .next_call(matching!((prepared, _) if prepared.height == *first_height_ref)) + .returns(Ok(first_block_proof_ref.clone())), + BlockProverMock::prove + .next_call(matching!((prepared, _) if prepared.height == *second_height_ref)) + .returns(Ok(second_block_proof_ref.clone())), + ))); + + let rollup_tree: Box = Box::new(Unimock::new(( + RollupTreeMock::height + .next_call(matching!(())) + .returns(rolled_height), + RollupTreeMock::root_hash + .next_call(matching!(())) + .returns(rolled_root), + RollupTreeMock::height + .next_call(matching!(())) + .returns(rolled_height), + RollupTreeMock::root_hash + .next_call(matching!(())) + .returns(rolled_root), + RollupTreeMock::root_hash + .next_call(matching!(())) + .returns(second_root), + RollupTreeMock::set_height + .next_call(matching!((height) if *height == *second_height_ref)) + .returns(()), + ))); + + let agg_agg_circuit: Arc = Arc::new(Unimock::new( + CircuitMock::prove + .with_types::() + .next_call(matching!((agg_input, _) + if agg_input.old_root == aggregated_agg_inputs_ref.old_root + && agg_input.new_root == aggregated_agg_inputs_ref.new_root)) + .returns(Ok::<_, CircuitError>(Proof::from( + aggregated_agg_proof.clone(), + ))), + )); + let agg_final_circuit: Arc = Arc::new(Unimock::new( + CircuitMock::prove + .with_types::() + .next_call(matching!((final_input, _) + if final_input.old_root == aggregated_final_inputs_ref.old_root + && final_input.new_root == aggregated_final_inputs_ref.new_root)) + .returns(Ok::<_, CircuitError>(Proof::from(final_proof.clone()))), + )); + let aggregator = Aggregator::new( + node_client, + rollup_contract, + block_prover, + rollup_tree, + DEFAULT_BLOCK_BATCH_SIZE, + TEST_GAS_PER_BURN_CALL, + agg_agg_circuit, + agg_final_circuit, + ); + + let preparation = aggregator.prepare_next_batch().await.unwrap(); + let batch = match preparation { + PreparationOutcome::Success(batch) => batch, + _ => panic!("Expected success"), + }; + let proven = aggregator + .prove_batch(batch, Arc::clone(&bb_backend)) + .await + .unwrap(); + aggregator.submit_batch(proven).await.unwrap(); +} diff --git a/pkg/aggregator/src/aggregator/tests/mod.rs b/pkg/aggregator/src/aggregator/tests/mod.rs new file mode 100644 index 0000000..2e26ee1 --- /dev/null +++ b/pkg/aggregator/src/aggregator/tests/mod.rs @@ -0,0 +1,116 @@ +use super::*; +use aggregator_interface::{PreparedChunk, UTXO_AGG_NUMBER}; +use element::Element; +use node_interface::{Block, BlockContent, BlockHeader, BlockState, BlockWithInfo, TxnWithInfo}; +pub use primitives::block_height::BlockHeight; +use primitives::{hash::CryptoHash, sig::Signature}; +use std::array; +use zk_primitives::{ + AggAggProof, AggAggPublicInput, ProofBytes, UtxoProof, UtxoProofBundleWithMerkleProofs, + UtxoPublicInput, +}; + +pub mod aggregation; +pub mod failures; +pub mod fetch; +pub mod lifecycle; + +pub const GAS_PER_BURN_CALL: u128 = 1_000_000; +pub const BYTES_PER_ELEMENT: usize = 32; +pub const AGG_FINAL_PROOF_ELEMENT_COUNT: usize = 330; +pub const DEFAULT_BLOCK_BATCH_SIZE: usize = 2; +pub const TEST_GAS_PER_BURN_CALL: u128 = 1_000_000; + +pub fn block_with_single_txn( + height: u64, + root_hash: Element, + approvals: Vec, + hash_seed: u64, +) -> BlockWithInfo { + BlockWithInfo { + block: Block { + content: BlockContent { + header: BlockHeader { + height: BlockHeight(height), + last_block_hash: CryptoHash::from_u64(height - 1), + epoch_id: 0, + last_final_block_hash: CryptoHash::from_u64(height - 2), + approvals, + }, + state: BlockState { + root_hash, + txns: vec![txn(height)], + }, + }, + signature: Signature::default(), + }, + hash: CryptoHash::from_u64(hash_seed), + time: height, + } +} + +pub fn txn(block_height: u64) -> TxnWithInfo { + TxnWithInfo { + proof: UtxoProof { + proof: ProofBytes::default(), + public_inputs: UtxoPublicInput { + input_commitments: [Element::new(block_height), Element::new(block_height + 1)], + output_commitments: [ + Element::new(block_height + 2), + Element::new(block_height + 3), + ], + messages: [ + Element::new(block_height + 4), + Element::new(block_height + 5), + Element::new(block_height + 6), + Element::new(block_height + 7), + Element::new(block_height + 8), + ], + }, + }, + hash: Element::new(block_height * 10), + index_in_block: 0, + block_height: BlockHeight(block_height), + time: block_height, + } +} + +pub fn block_agg_proof(old_root: Element, new_root: Element, commit_hash: Element) -> AggAggProof { + AggAggProof { + proof: ProofBytes::default(), + public_inputs: AggAggPublicInput { + verification_key_hash: [Element::new(1), Element::new(2)], + old_root, + new_root, + commit_hash, + messages: [Element::ZERO; 1000], + }, + kzg: vec![], + } +} + +pub fn agg_agg_proof_from_inputs(inputs: &AggAggPublicInput) -> AggAggProof { + AggAggProof { + proof: ProofBytes::default(), + public_inputs: inputs.clone(), + kzg: vec![], + } +} + +pub fn signature(byte: u8) -> Signature { + Signature([byte; 65]) +} + +pub fn dummy_chunk(old_root: Element, new_root: Element) -> PreparedChunk { + let bundles: [UtxoProofBundleWithMerkleProofs; UTXO_AGG_NUMBER] = + array::from_fn(|_| UtxoProofBundleWithMerkleProofs::default()); + PreparedChunk { + old_root, + new_root, + bundles, + } +} + +pub fn leak(value: T) -> &'static T { + Box::leak(Box::new(value)) +} diff --git a/pkg/aggregator/src/aggregator/trait_impl.rs b/pkg/aggregator/src/aggregator/trait_impl.rs new file mode 100644 index 0000000..5493c19 --- /dev/null +++ b/pkg/aggregator/src/aggregator/trait_impl.rs @@ -0,0 +1,162 @@ +use std::sync::Arc; + +use aggregator_interface::{ + Aggregator as AggregatorTrait, ContractError, Error, PreparationOutcome, PreparedBatch, + ProvenBatch, RollupInput, +}; +use async_trait::async_trait; +use barretenberg_interface::BbBackend; +use contextful::{ErrorContextExt, ResultContextExt}; +use futures::future::join_all; +use tracing::debug; +use zk_circuits::circuits::generated::agg_final::AggFinalInput as CircuitAggFinalInput; +use zk_primitives::AggFinal; + +use crate::aggregator::{Aggregator, utils}; + +#[async_trait] +impl AggregatorTrait for Aggregator { + async fn prepare_next_batch(&self) -> Result { + let tree = self.rollup_tree.lock().await; + let start_height = tree.height() + 1; + let expected_old_root = tree.root_hash(); + + drop(tree); + + let mut blocks = self.fetch_blocks(start_height).await?; + let available_blocks = blocks.len(); + if available_blocks < self.block_batch_size { + return Ok(PreparationOutcome::InsufficientBlocks { + start_height, + available: available_blocks, + required: self.block_batch_size, + }); + } + blocks.truncate(self.block_batch_size); + + let Some(last_block) = blocks.last() else { + return Ok(PreparationOutcome::InsufficientBlocks { + start_height, + available: 0, + required: self.block_batch_size, + }); + }; + let new_height = last_block.block.content.header.height.0; + + let mut tree = self.rollup_tree.lock().await; + + if tree.height() + 1 != start_height || tree.root_hash() != expected_old_root { + return Err(Error::from( + ContractError::RootMismatch.wrap_err("local tree modified during preparation"), + )); + } + + let mut prepared_blocks = Vec::with_capacity(blocks.len()); + for block in &blocks { + let block_height = block.block.content.header.height.0; + debug!(block_height, "preparing block proof"); + let prepared = self + .block_prover + .prepare(block_height, tree.as_mut()) + .await + .with_context(|| format!("prepare block proof for height {block_height}"))?; + prepared_blocks.push(prepared); + } + + let new_root = tree.root_hash(); + + tree.set_height(new_height); + + Ok(PreparationOutcome::Success(PreparedBatch { + blocks, + prepared_blocks, + old_root: expected_old_root, + new_root, + })) + } + + async fn prove_batch( + &self, + batch: PreparedBatch, + bb_backend: Arc, + ) -> Result { + let proof_results = join_all(batch.prepared_blocks.into_iter().map(|prepared| { + let block_prover = Arc::clone(&self.block_prover); + let height = prepared.height; + let bb_backend = Arc::clone(&bb_backend); + async move { + block_prover + .prove(prepared, bb_backend) + .await + .with_context(|| format!("prove block proof for height {height}")) + } + })) + .await; + + let mut proofs = Vec::with_capacity(batch.blocks.len()); + for proof in proof_results { + proofs.push(proof?); + } + + let aggregated_proof = self + .aggregate_block_proofs(proofs, Arc::clone(&bb_backend)) + .await?; + + if aggregated_proof.public_inputs.old_root != batch.old_root { + return Err(Error::from( + ContractError::RootMismatch.wrap_err("aggregated proof root mismatch"), + )); + } + + let agg_final_input = CircuitAggFinalInput::from(AggFinal::new(aggregated_proof)); + let agg_final_circuit = Arc::clone(&self.agg_final_circuit); + + let final_proof = agg_final_circuit + .prove(&agg_final_input, bb_backend) + .await + .map_err(|err| Error::ImplementationSpecific(Box::new(err)))?; + + let Some(final_block) = batch.blocks.last() else { + return Err(Error::EmptyBatch); + }; + let other_hash = utils::block_header_hash(&final_block.block.content.header)?; + + Ok(ProvenBatch { + final_proof: final_proof.into(), + blocks: batch.blocks, + other_hash, + }) + } + + async fn submit_batch(&self, batch: ProvenBatch) -> Result<(), Error> { + let Some(final_block) = batch.blocks.last() else { + return Err(Error::EmptyBatch); + }; + let next_block_height = final_block.block.content.header.height.0 + 1; + + let next_block = self + .fetch_block(next_block_height) + .await? + .ok_or(Error::MissingApprovalBlock)?; + + let rollup = RollupInput { + proof: batch.final_proof.proof.0.clone(), + old_root: batch.final_proof.public_inputs.old_root, + new_root: batch.final_proof.public_inputs.new_root, + commit_hash: batch.final_proof.public_inputs.commit_hash, + utxo_messages: batch.final_proof.public_inputs.messages.clone(), + kzg: batch.final_proof.kzg.clone(), + other_hash: batch.other_hash, + height: final_block.block.content.header.height.0, + signatures: utils::serialize_signatures(&next_block.block.content.header.approvals), + gas_per_burn_call: self.gas_per_burn_call, + }; + + self.rollup_contract + .submit_rollup(&rollup) + .await + .context("submit rollup proof to contract")?; + + Ok(()) + } +} diff --git a/pkg/aggregator/src/aggregator/utils.rs b/pkg/aggregator/src/aggregator/utils.rs new file mode 100644 index 0000000..e7672ec --- /dev/null +++ b/pkg/aggregator/src/aggregator/utils.rs @@ -0,0 +1,45 @@ +use aggregator_interface::Error; +use borsh::BorshSerialize; +use node_interface::BlockHeader; +use primitives::{block_height::BlockHeight, hash::CryptoHash, sig::Signature}; +use sha3::{Digest, Keccak256}; + +#[derive(BorshSerialize)] +pub struct SerializableBlockHeader { + pub height: BlockHeight, + pub last_block_hash: CryptoHash, + pub epoch_id: u64, + pub last_final_block_hash: CryptoHash, + pub approvals: Vec, +} + +impl From<&BlockHeader> for SerializableBlockHeader { + fn from(header: &BlockHeader) -> Self { + Self { + height: header.height, + last_block_hash: header.last_block_hash, + epoch_id: header.epoch_id, + last_final_block_hash: header.last_final_block_hash, + approvals: header.approvals.clone(), + } + } +} + +pub fn serialize_signatures(approvals: &[Signature]) -> Vec> { + approvals.iter().map(|sig| sig.inner().to_vec()).collect() +} + +pub fn block_header_hash(header: &BlockHeader) -> Result<[u8; 32], Error> { + let serializable = SerializableBlockHeader::from(header); + let mut bytes = Vec::new(); + serializable + .serialize(&mut bytes) + .map_err(|err| Error::ImplementationSpecific(Box::new(err)))?; + let mut hasher = Keccak256::new(); + hasher.update(bytes); + Ok(hasher.finalize().into()) +} + +pub fn map_node_error(err: node_interface::Error) -> Error { + Error::ImplementationSpecific(Box::new(err)) +} diff --git a/pkg/aggregator/src/block_prover/error.rs b/pkg/aggregator/src/block_prover/error.rs new file mode 100644 index 0000000..ce08171 --- /dev/null +++ b/pkg/aggregator/src/block_prover/error.rs @@ -0,0 +1,44 @@ +use aggregator_interface::BlockProverError; +use contextful::Contextful; +use element::Element; +use node_interface::Error as NodeClientError; +use thiserror::Error; +use tokio::task::JoinError; + +#[derive(Debug, Error)] +pub enum BlockProverImplError { + #[error("[aggregator/block_prover] node client error: {0}")] + Node(#[from] Contextful), + #[error("[aggregator/block_prover] missing block for height {0}")] + MissingBlock(u64), + #[error("[aggregator/block_prover] block height mismatch: expected {expected}, got {found}")] + BlockHeightMismatch { expected: u64, found: u64 }, + #[error("[aggregator/block_prover] diff height mismatch: expected {expected}, got {found}")] + DiffHeightMismatch { expected: u64, found: u64 }, + #[error( + "[aggregator/block_prover] diff from height mismatch: expected {expected}, got {found}" + )] + DiffFromMismatch { expected: u64, found: u64 }, + #[error("[aggregator/block_prover] too many transactions: max {max}, got {found}")] + TooManyTransactions { found: usize, max: usize }, + #[error("[aggregator/block_prover] chunk count mismatch: expected {expected}, got {found}")] + ChunkCountMismatch { expected: usize, found: usize }, + #[error("[aggregator/block_prover] bundle count mismatch: expected {expected}, got {found}")] + BundleCountMismatch { expected: usize, found: usize }, + #[error( + "[aggregator/block_prover] merkle path length mismatch: expected {expected}, got {found}" + )] + MerklePathLength { expected: usize, found: usize }, + #[error("[aggregator/block_prover] root mismatch: expected {expected:?}, got {got:?}")] + RootMismatch { expected: Element, got: Element }, + #[error("[aggregator/block_prover] circuit error: {0}")] + Circuit(#[from] Contextful), + #[error("[aggregator/block_prover] join error: {0}")] + Join(#[from] Contextful), +} + +impl From for BlockProverError { + fn from(value: BlockProverImplError) -> Self { + BlockProverError::ImplementationSpecific(Box::new(value)) + } +} diff --git a/pkg/aggregator/src/block_prover/mod.rs b/pkg/aggregator/src/block_prover/mod.rs new file mode 100644 index 0000000..752c3a8 --- /dev/null +++ b/pkg/aggregator/src/block_prover/mod.rs @@ -0,0 +1,58 @@ +use std::sync::Arc; + +use aggregator_interface::{ + BlockProver as BlockProverTrait, BlockProverError, PreparedBlock, RollupTree, +}; +use async_trait::async_trait; +use barretenberg_interface::BbBackend; +use node_interface::NodeClient; +use zk_primitives::AggAggProof; + +pub mod error; +pub mod prepare; +pub mod prove; + +#[cfg(test)] +mod tests; + +use crate::{AggAggCircuitInterface, AggUtxoCircuitInterface}; + +#[derive(Clone)] +pub struct BlockProver { + pub(crate) node_client: Arc, + pub(crate) agg_utxo_circuit: Arc, + pub(crate) agg_agg_circuit: Arc, +} + +impl BlockProver { + pub fn new( + node_client: Arc, + agg_utxo_circuit: Arc, + agg_agg_circuit: Arc, + ) -> Self { + Self { + node_client, + agg_utxo_circuit, + agg_agg_circuit, + } + } +} + +#[async_trait] +impl BlockProverTrait for BlockProver { + async fn prepare( + &self, + height: u64, + tree: &mut dyn RollupTree, + ) -> Result { + self.prepare_impl(height, tree).await + } + + async fn prove( + &self, + prepared: PreparedBlock, + bb_backend: Arc, + ) -> Result { + self.prove_impl(prepared, bb_backend).await + } +} diff --git a/pkg/aggregator/src/block_prover/prepare.rs b/pkg/aggregator/src/block_prover/prepare.rs new file mode 100644 index 0000000..fbc9b5c --- /dev/null +++ b/pkg/aggregator/src/block_prover/prepare.rs @@ -0,0 +1,231 @@ +// lint-long-file-override allow-max-lines=300 +use std::array; + +use aggregator_interface::{ + BlockProverError, PreparedBlock, PreparedChunk, RollupTree, UTXO_AGG_NUMBER, UTXO_AGGREGATIONS, +}; +use contextful::ResultContextExt; +use element::Element; +use primitives::block_height::BlockHeight; +use zk_primitives::{MerklePath, UtxoProof, UtxoProofBundleWithMerkleProofs}; + +use crate::block_prover::{BlockProver, error::BlockProverImplError}; + +pub const MERKLE_TREE_DEPTH: usize = 161; +pub const MERKLE_TREE_PATH_DEPTH: usize = MERKLE_TREE_DEPTH - 1; +pub const MAXIMUM_TXNS: usize = UTXO_AGG_NUMBER * UTXO_AGGREGATIONS; + +impl BlockProver { + pub(super) async fn prepare_impl( + &self, + height: u64, + tree: &mut dyn RollupTree, + ) -> Result { + let previous_height = tree.height(); + let diff = self + .node_client + .block_tree_diff(BlockHeight(height), BlockHeight(previous_height)) + .await + .context("fetch block tree diff") + .map_err(BlockProverImplError::from)?; + self.validate_diff(&diff, height, previous_height)?; + + let blocks = self + .node_client + .blocks(BlockHeight(height), 1, false) + .await + .context("fetch blocks from node client") + .map_err(BlockProverImplError::from)?; + let block = blocks + .blocks + .first() + .ok_or(BlockProverImplError::MissingBlock(height))?; + let block_height = block.block.content.header.height.0; + if block_height != height { + return Err(BlockProverImplError::BlockHeightMismatch { + expected: height, + found: block_height, + } + .into()); + } + + let mut proofs = block + .block + .content + .state + .txns + .iter() + .map(|txn| Some(txn.proof.clone())) + .collect::>(); + if proofs.len() > MAXIMUM_TXNS { + return Err(BlockProverImplError::TooManyTransactions { + found: proofs.len(), + max: MAXIMUM_TXNS, + } + .into()); + } + while proofs.len() < MAXIMUM_TXNS { + proofs.push(None); + } + + let mut prepared_chunks = Vec::with_capacity(UTXO_AGGREGATIONS); + for chunk in proofs.chunks(UTXO_AGG_NUMBER) { + let chunk_array = [chunk[0].clone(), chunk[1].clone(), chunk[2].clone()]; + let prepared_chunk = self.build_chunk(tree, chunk_array, height)?; + prepared_chunks.push(prepared_chunk); + } + + if prepared_chunks.len() != UTXO_AGGREGATIONS { + return Err(BlockProverImplError::ChunkCountMismatch { + expected: UTXO_AGGREGATIONS, + found: prepared_chunks.len(), + } + .into()); + } + + let expected_root = block.block.content.state.root_hash; + let final_root = tree.root_hash(); + if final_root != expected_root { + return Err(BlockProverImplError::RootMismatch { + expected: expected_root, + got: final_root, + } + .into()); + } + if final_root != diff.root_hash { + return Err(BlockProverImplError::RootMismatch { + expected: diff.root_hash, + got: final_root, + } + .into()); + } + + tree.set_height(height); + + let chunk_len = prepared_chunks.len(); + let chunks: [PreparedChunk; UTXO_AGGREGATIONS] = + prepared_chunks + .try_into() + .map_err(|_| BlockProverImplError::ChunkCountMismatch { + expected: UTXO_AGGREGATIONS, + found: chunk_len, + })?; + + Ok(PreparedBlock { height, chunks }) + } + + fn validate_diff( + &self, + diff: &node_interface::BlockTreeDiff, + height: u64, + previous_height: u64, + ) -> Result<(), BlockProverError> { + if diff.height.0 != height { + return Err(BlockProverImplError::DiffHeightMismatch { + expected: height, + found: diff.height.0, + } + .into()); + } + let from_height = diff.diff.from_height.0; + if from_height != previous_height { + return Err(BlockProverImplError::DiffFromMismatch { + expected: previous_height, + found: from_height, + } + .into()); + } + Ok(()) + } + + fn build_chunk( + &self, + tree: &mut dyn RollupTree, + proofs: [Option; UTXO_AGG_NUMBER], + height: u64, + ) -> Result { + let chunk_old_root = tree.root_hash(); + let mut bundles = Vec::with_capacity(UTXO_AGG_NUMBER); + for proof in proofs.into_iter() { + let bundle = match proof { + Some(proof) => self.build_bundle(tree, proof, height)?, + None => UtxoProofBundleWithMerkleProofs::default(), + }; + bundles.push(bundle); + } + let chunk_new_root = tree.root_hash(); + let bundle_len = bundles.len(); + let bundles: [UtxoProofBundleWithMerkleProofs; UTXO_AGG_NUMBER] = bundles + .try_into() + .map_err(|_| BlockProverImplError::BundleCountMismatch { + expected: UTXO_AGG_NUMBER, + found: bundle_len, + })?; + + Ok(PreparedChunk { + old_root: chunk_old_root, + new_root: chunk_new_root, + bundles, + }) + } + + fn build_bundle( + &self, + tree: &mut dyn RollupTree, + proof: UtxoProof, + height: u64, + ) -> Result { + let mut merkle_paths = array::from_fn(|_| MerklePath::default()); + for (idx, commitment) in proof.public_inputs.input_commitments.iter().enumerate() { + merkle_paths[idx] = self.extract_input_path(tree, *commitment)?; + } + + for (idx, commitment) in proof.public_inputs.output_commitments.iter().enumerate() { + merkle_paths[2 + idx] = self.extract_output_path(tree, *commitment, height)?; + } + + Ok(UtxoProofBundleWithMerkleProofs::new(proof, &merkle_paths)) + } + + fn extract_input_path( + &self, + tree: &mut dyn RollupTree, + commitment: Element, + ) -> Result, BlockProverError> { + if commitment.is_zero() { + return Ok(MerklePath::default()); + } + let path_vec = tree.sibling_path(commitment)?; + let merkle_path = self.path_from_vec(path_vec)?; + tree.remove(commitment)?; + Ok(merkle_path) + } + + fn extract_output_path( + &self, + tree: &mut dyn RollupTree, + commitment: Element, + height: u64, + ) -> Result, BlockProverError> { + if commitment.is_zero() { + return Ok(MerklePath::default()); + } + tree.insert(&[(commitment, height)])?; + let path_vec = tree.sibling_path(commitment)?; + self.path_from_vec(path_vec) + } + + fn path_from_vec( + &self, + path: Vec, + ) -> Result, BlockProverError> { + if path.len() != MERKLE_TREE_PATH_DEPTH { + return Err(BlockProverImplError::MerklePathLength { + expected: MERKLE_TREE_PATH_DEPTH, + found: path.len(), + } + .into()); + } + Ok(MerklePath::new(path)) + } +} diff --git a/pkg/aggregator/src/block_prover/prove.rs b/pkg/aggregator/src/block_prover/prove.rs new file mode 100644 index 0000000..af9c1b2 --- /dev/null +++ b/pkg/aggregator/src/block_prover/prove.rs @@ -0,0 +1,98 @@ +use std::sync::Arc; + +use aggregator_interface::{BlockProverError, PreparedBlock, PreparedChunk, UTXO_AGGREGATIONS}; +use barretenberg_interface::BbBackend; +use contextful::ResultContextExt; +use futures::future::join_all; +use zk_circuits::circuits::generated::agg_agg::AggAggInput as CircuitAggAggInput; +use zk_circuits::circuits::generated::agg_utxo::AggUtxoInput as CircuitAggUtxoInput; +use zk_primitives::{ + AggAgg, AggAggProof, AggProof, AggUtxo, AggUtxoProof, AggUtxoPublicInput, ProofBytes, +}; + +use crate::block_prover::{BlockProver, error::BlockProverImplError}; + +impl BlockProver { + pub(super) async fn prove_impl( + &self, + prepared: PreparedBlock, + bb_backend: Arc, + ) -> Result { + let agg_proofs = self + .prove_chunks(&prepared.chunks, Arc::clone(&bb_backend)) + .await?; + let agg_agg = AggAgg::new(agg_proofs); + let agg_agg_input = CircuitAggAggInput::from(agg_agg); + let agg_agg_circuit = Arc::clone(&self.agg_agg_circuit); + + let proof = agg_agg_circuit + .prove(&agg_agg_input, bb_backend) + .await + .context("prove agg agg rollup") + .map_err(BlockProverImplError::from)?; + let proof = AggAggProof::from(proof); + + Ok(proof) + } + + pub(super) async fn prove_chunks( + &self, + chunks: &[PreparedChunk; UTXO_AGGREGATIONS], + bb_backend: Arc, + ) -> Result<[AggProof; UTXO_AGGREGATIONS], BlockProverError> { + let chunk_futures = chunks + .iter() + .cloned() + .map(|chunk| self.prove_chunk(chunk, Arc::clone(&bb_backend))); + let results = join_all(chunk_futures).await; + let mut proofs = Vec::with_capacity(UTXO_AGGREGATIONS); + for result in results { + proofs.push(result?); + } + + let proof_len = proofs.len(); + proofs.try_into().map_err(|_| { + BlockProverError::from(BlockProverImplError::ChunkCountMismatch { + expected: UTXO_AGGREGATIONS, + found: proof_len, + }) + }) + } + + async fn prove_chunk( + &self, + chunk: PreparedChunk, + bb_backend: Arc, + ) -> Result { + if self.chunk_is_padding(&chunk) { + return Ok(Self::padding_proof()); + } + + let agg_utxo = AggUtxo::new(chunk.bundles.clone(), chunk.old_root, chunk.new_root); + let agg_utxo_input = CircuitAggUtxoInput::from(agg_utxo); + let agg_utxo_circuit = Arc::clone(&self.agg_utxo_circuit); + + let proof = agg_utxo_circuit + .prove(&agg_utxo_input, bb_backend) + .await + .context("prove agg utxo chunk") + .map_err(BlockProverImplError::from)?; + let proof = AggUtxoProof::from(proof); + + Ok(AggProof::AggUtxo(Box::new(proof))) + } + + fn chunk_is_padding(&self, chunk: &PreparedChunk) -> bool { + chunk + .bundles + .iter() + .all(|bundle| bundle.utxo_proof.is_padding()) + } + + fn padding_proof() -> AggProof { + AggProof::AggUtxo(Box::new(AggUtxoProof { + proof: ProofBytes::default(), + public_inputs: AggUtxoPublicInput::default(), + })) + } +} diff --git a/pkg/aggregator/src/block_prover/tests.rs b/pkg/aggregator/src/block_prover/tests.rs new file mode 100644 index 0000000..95f130a --- /dev/null +++ b/pkg/aggregator/src/block_prover/tests.rs @@ -0,0 +1,154 @@ +// lint-long-file-override allow-max-lines=300 +use super::BlockProver; +use aggregator_interface::{ + BlockProver as BlockProverTrait, PreparedBlock, PreparedChunk, RollupTreeMock, +}; +use barretenberg_interface::BbBackend; +use element::Element; +use node_interface::{ + Block, BlockContent, BlockHeader, BlockState, BlockTreeDiff, BlockTreeDiffChanges, + BlockWithInfo, ListBlocksResponse, NodeClient, NodeClientMock, TxnWithInfo, +}; +use primitives::{ + block_height::BlockHeight, hash::CryptoHash, pagination::OpaqueCursor, sig::Signature, +}; +use std::sync::Arc; +use unimock::{MockFn, Unimock, matching}; +use zk_circuits::circuits::generated::agg_agg::AggAggInput as CircuitAggAggInput; +use zk_circuits::{Error as CircuitError, Proof}; +use zk_primitives::{ + AggAggProof, AggAggPublicInput, ProofBytes, UtxoProof, UtxoProofBundleWithMerkleProofs, +}; + +use crate::CircuitMock; + +fn sample_block(height: u64, txns: Vec, root_hash: Element) -> BlockWithInfo { + let txns = txns + .into_iter() + .enumerate() + .map(|(idx, proof)| TxnWithInfo { + proof, + hash: Element::new(idx as u64), + index_in_block: idx as u64, + block_height: BlockHeight(height), + time: height, + }) + .collect(); + BlockWithInfo { + block: Block { + content: BlockContent { + header: BlockHeader { + height: BlockHeight(height), + last_block_hash: CryptoHash::from_u64(height - 1), + epoch_id: 0, + last_final_block_hash: CryptoHash::from_u64(height - 2), + approvals: vec![Signature([1; 65])], + }, + state: BlockState { root_hash, txns }, + }, + signature: Signature::default(), + }, + hash: CryptoHash::from_u64(height * 100), + time: height, + } +} + +fn sample_diff(height: u64, root_hash: Element) -> BlockTreeDiff { + BlockTreeDiff { + height: BlockHeight(height), + root_hash, + diff: BlockTreeDiffChanges { + from_height: BlockHeight(height - 1), + additions: vec![Element::new(height * 10 + 1)], + removals: vec![Element::new(height * 10 + 2)], + }, + } +} + +#[tokio::test] +async fn prepare_fetches_block_tree_and_block() { + let prove_height = leak(42u64); + let blocks_response = ListBlocksResponse { + blocks: vec![sample_block(*prove_height, Vec::new(), Element::ZERO)], + cursor: OpaqueCursor::default(), + }; + + let node_client: Arc = Arc::new(Unimock::new(( + NodeClientMock::block_tree_diff + .next_call(matching!((height, diff_from) + if *height == BlockHeight(*prove_height) + && *diff_from == BlockHeight(*prove_height - 1))) + .returns(Ok(sample_diff(*prove_height, Element::ZERO))), + NodeClientMock::blocks + .next_call(matching!((start_height, limit, skip_empty) + if *start_height == BlockHeight(*prove_height) + && *limit == 1 + && !*skip_empty)) + .returns(Ok(blocks_response)), + ))); + + let mut tree = Unimock::new(( + RollupTreeMock::height + .next_call(matching!(())) + .returns(*prove_height - 1), + RollupTreeMock::set_height + .next_call(matching!((height) if *height == *prove_height)) + .returns(()), + RollupTreeMock::root_hash + .each_call(matching!(())) + .returns(Element::ZERO), + )); + + let agg_utxo_circuit = Arc::new(Unimock::new(())); + let agg_agg_circuit = Arc::new(Unimock::new(())); + let prover = BlockProver::new(node_client, agg_utxo_circuit, agg_agg_circuit); + let _ = prover.prepare(*prove_height, &mut tree).await; +} + +#[tokio::test] +async fn prove_succeeds_with_padding_chunks() { + let node_client: Arc = Arc::new(Unimock::new(())); + let bb_backend: Arc = Arc::new(Unimock::new(())); + let agg_utxo_circuit = Arc::new(Unimock::new(())); + let agg_agg_proof = AggAggProof { + proof: ProofBytes::default(), + public_inputs: AggAggPublicInput { + verification_key_hash: [Element::ZERO; 2], + old_root: Element::ZERO, + new_root: Element::ZERO, + commit_hash: Element::ZERO, + messages: [Element::ZERO; 1000], + }, + kzg: vec![], + }; + let agg_agg_circuit = Arc::new(Unimock::new( + CircuitMock::prove + .with_types::() + .next_call(matching!((_, _))) + .returns(Ok::<_, CircuitError>(Proof::from(agg_agg_proof.clone()))), + )); + let prover = BlockProver::new(node_client, agg_utxo_circuit, agg_agg_circuit); + let prepared = PreparedBlock { + height: 7, + chunks: [padding_chunk(), padding_chunk()], + }; + + let proof = prover.prove(prepared, bb_backend.clone()).await.unwrap(); + assert_eq!(proof.public_inputs.old_root, Element::ZERO); +} + +fn padding_chunk() -> PreparedChunk { + PreparedChunk { + old_root: Element::ZERO, + new_root: Element::ZERO, + bundles: [ + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + } +} + +fn leak(value: T) -> &'static T { + Box::leak(Box::new(value)) +} diff --git a/pkg/aggregator/src/contracts_adapter.rs b/pkg/aggregator/src/contracts_adapter.rs new file mode 100644 index 0000000..4d5b4f4 --- /dev/null +++ b/pkg/aggregator/src/contracts_adapter.rs @@ -0,0 +1,132 @@ +use std::{sync::Arc, time::Duration}; + +use aggregator_interface::{ContractError, RollupInput}; +use async_trait::async_trait; +use element::Element; +use thiserror::Error; +use tracing::warn; +use web3::types::U64; + +pub struct ContractsRollupContract { + contract: Arc, + receipt_timeout: Duration, + receipt_poll_interval: Duration, +} + +impl ContractsRollupContract { + pub fn new( + inner: Arc, + receipt_timeout: Duration, + receipt_poll_interval: Duration, + ) -> Self { + Self { + contract: inner, + receipt_timeout, + receipt_poll_interval, + } + } + + fn map_contract_error(err: E) -> ContractError + where + E: std::error::Error + Send + Sync + 'static, + { + ContractError::ImplementationSpecific(Box::new(err)) + } + + async fn do_submit_rollup(&self, rollup: &RollupInput) -> Result<(), ContractError> { + let signature_refs = rollup + .signatures + .iter() + .map(|sig| sig.as_slice()) + .collect::>(); + + let tx_hash = self + .contract + .verify_block( + &rollup.proof, + &rollup.old_root, + &rollup.new_root, + &rollup.commit_hash, + &rollup.utxo_messages, + &rollup.kzg, + rollup.other_hash, + rollup.height, + &signature_refs, + rollup.gas_per_burn_call, + ) + .await + .map_err(Self::map_contract_error)?; + + let receipt = self + .contract + .client + .wait_for_receipt(tx_hash, self.receipt_poll_interval, self.receipt_timeout) + .await + .map_err(|e| match e { + contracts::Error::UnknownTransaction(_) => { + Self::map_contract_error(SubmitRollupError::Dropped) + } + contracts::Error::Timeout => Self::map_contract_error(SubmitRollupError::Timeout), + _ => Self::map_contract_error(e), + })?; + + if let Some(status) = receipt.status.filter(|status| *status != U64::from(1u64)) { + return Err(Self::map_contract_error(SubmitRollupError::Failed { + status, + })); + } + + Ok(()) + } +} + +#[async_trait] +impl aggregator_interface::RollupContract for ContractsRollupContract { + async fn height(&self) -> Result { + self.contract + .block_height() + .await + .map_err(|e| ContractError::ImplementationSpecific(Box::new(e))) + } + + async fn root_hash(&self) -> Result { + let root_hash = self + .contract + .root_hash() + .await + .map_err(|e| ContractError::ImplementationSpecific(Box::new(e)))?; + + Ok(Element::from_be_bytes(root_hash.to_fixed_bytes())) + } + + async fn submit_rollup(&self, rollup: &RollupInput) -> Result<(), ContractError> { + if let Err(submit_rollup_err) = self.do_submit_rollup(rollup).await { + match self.height().await { + Ok(current_height) if current_height >= rollup.height => { + warn!( + current_height, + rollup_height = rollup.height, + ?submit_rollup_err, + "rollup submission failed but contract height is already at or above target, assuming success" + ); + return Ok(()); + } + _ => return Err(submit_rollup_err), + } + } + + Ok(()) + } +} + +#[derive(Debug, Error)] +enum SubmitRollupError { + #[error( + "[aggregator/contracts_adapter] rollup transaction dropped before receipt was produced" + )] + Dropped, + #[error("[aggregator/contracts_adapter] timed out waiting for rollup receipt")] + Timeout, + #[error("[aggregator/contracts_adapter] rollup transaction reverted with status {status:?}")] + Failed { status: U64 }, +} diff --git a/pkg/aggregator/src/lib.rs b/pkg/aggregator/src/lib.rs new file mode 100644 index 0000000..e69d02d --- /dev/null +++ b/pkg/aggregator/src/lib.rs @@ -0,0 +1,16 @@ +mod aggregator; +mod block_prover; +mod contracts_adapter; +mod limited_bb_backend; +mod retryable_rollup_contract; +mod smirk_rollup_tree; + +pub use aggregator::Aggregator; +pub use block_prover::BlockProver; +pub use contracts_adapter::ContractsRollupContract; +pub use limited_bb_backend::LimitedBbBackend; +pub use retryable_rollup_contract::RetryableRollupContract; +pub use smirk_rollup_tree::SmirkRollupTree; +pub use zk_circuits::traits::{ + AggAggCircuitInterface, AggFinalCircuitInterface, AggUtxoCircuitInterface, CircuitMock, +}; diff --git a/pkg/aggregator/src/limited_bb_backend/limiter.rs b/pkg/aggregator/src/limited_bb_backend/limiter.rs new file mode 100644 index 0000000..7cfaa25 --- /dev/null +++ b/pkg/aggregator/src/limited_bb_backend/limiter.rs @@ -0,0 +1,135 @@ +use std::{collections::BTreeMap, sync::Mutex}; +use tokio::sync::Notify; + +pub(super) struct ConcurrencyLimiter { + state: Mutex, + notify: Notify, + max: usize, +} + +struct LimiterState { + in_flight: usize, + waiters: BTreeMap, +} + +impl ConcurrencyLimiter { + pub(super) fn new(max: usize) -> Self { + Self { + state: Mutex::new(LimiterState { + in_flight: 0, + waiters: BTreeMap::new(), + }), + notify: Notify::new(), + max, + } + } + + pub(super) async fn acquire(&self, priority: u64) -> Permit<'_> { + let mut waiter_guard = WaiterGuard::new(self, priority); + loop { + let notification = self.notify.notified(); + + { + let mut state = self.state.lock().expect("limiter mutex poisoned"); + + let can_proceed = |state: &LimiterState, priority: u64| { + state.in_flight < self.max + && (state.waiters.is_empty() + || priority <= *state.waiters.keys().next().expect("waiters empty")) + }; + + if can_proceed(&state, priority) { + waiter_guard.disarm(&mut state); + state.in_flight += 1; + return Permit { limiter: self }; + } + + waiter_guard.arm(&mut state); + } + + notification.await; + } + } + + fn release(&self) { + let mut state = self.state.lock().expect("limiter mutex poisoned"); + debug_assert!(state.in_flight > 0, "release called without acquire"); + state.in_flight -= 1; + self.notify.notify_waiters(); + } +} + +pub(super) struct Permit<'a> { + limiter: &'a ConcurrencyLimiter, +} + +struct WaiterGuard<'a> { + limiter: &'a ConcurrencyLimiter, + priority: u64, + active: bool, +} + +impl<'a> WaiterGuard<'a> { + fn new(limiter: &'a ConcurrencyLimiter, priority: u64) -> Self { + Self { + limiter, + priority, + active: false, + } + } + + fn arm(&mut self, state: &mut LimiterState) { + if !self.active { + *state.waiters.entry(self.priority).or_insert(0) += 1; + self.active = true; + } + } + + fn disarm(&mut self, state: &mut LimiterState) { + if !self.active { + return; + } + + if let Some(count) = state.waiters.get_mut(&self.priority) { + if *count > 1 { + *count -= 1; + } else { + state.waiters.remove(&self.priority); + } + } + + self.active = false; + } +} + +impl Drop for WaiterGuard<'_> { + fn drop(&mut self) { + if !self.active { + return; + } + + let mut notify = false; + { + let mut state = self.limiter.state.lock().expect("limiter mutex poisoned"); + if let Some(count) = state.waiters.get_mut(&self.priority) { + if *count > 1 { + *count -= 1; + } else { + state.waiters.remove(&self.priority); + notify = true; + } + } + self.active = false; + } + + if notify { + self.limiter.notify.notify_waiters(); + } + } +} + +impl Drop for Permit<'_> { + fn drop(&mut self) { + self.limiter.release(); + } +} diff --git a/pkg/aggregator/src/limited_bb_backend/mod.rs b/pkg/aggregator/src/limited_bb_backend/mod.rs new file mode 100644 index 0000000..e250aa2 --- /dev/null +++ b/pkg/aggregator/src/limited_bb_backend/mod.rs @@ -0,0 +1,78 @@ +use std::sync::Arc; + +use aggregator_interface::PrioritizableBbBackend; +use async_trait::async_trait; +use barretenberg_interface::BbBackend; + +mod limiter; + +#[cfg(test)] +mod tests; + +use limiter::ConcurrencyLimiter; + +/// Wraps any `BbBackend` and enforces a maximum number of concurrent `prove` calls. +/// Earlier block batches (lower priority values) are given priority access. +#[derive(Clone)] +pub struct LimitedBbBackend { + inner: Arc, + limiter: Arc, + priority: u64, +} + +impl LimitedBbBackend { + /// Creates a new backend wrapper that permits at most `max_concurrency` concurrent `prove` calls. + /// + /// # Panics + /// + /// Panics if `max_concurrency` is zero. + #[must_use] + pub fn new(inner: Arc, max_concurrency: usize) -> Self { + assert!( + max_concurrency > 0, + "max_concurrency must be greater than zero" + ); + Self { + inner, + limiter: Arc::new(ConcurrencyLimiter::new(max_concurrency)), + priority: u64::MAX, + } + } +} + +impl PrioritizableBbBackend for LimitedBbBackend { + fn with_priority(&self, priority: u64) -> Arc { + Arc::new(Self { + inner: Arc::clone(&self.inner), + limiter: Arc::clone(&self.limiter), + priority, + }) + } +} + +#[async_trait] +impl BbBackend for LimitedBbBackend { + async fn prove( + &self, + program: &[u8], + bytecode: &[u8], + key: &[u8], + witness: &[u8], + oracle: bool, + ) -> barretenberg_interface::error::Result> { + let _permit = self.limiter.acquire(self.priority).await; + self.inner + .prove(program, bytecode, key, witness, oracle) + .await + } + + async fn verify( + &self, + proof: &[u8], + public_inputs: &[u8], + key: &[u8], + oracle: bool, + ) -> barretenberg_interface::error::Result<()> { + self.inner.verify(proof, public_inputs, key, oracle).await + } +} diff --git a/pkg/aggregator/src/limited_bb_backend/tests.rs b/pkg/aggregator/src/limited_bb_backend/tests.rs new file mode 100644 index 0000000..2b1e7d4 --- /dev/null +++ b/pkg/aggregator/src/limited_bb_backend/tests.rs @@ -0,0 +1,152 @@ +use super::*; +use async_trait::async_trait; +use barretenberg_interface::BbBackend; +use std::{ + sync::{ + Arc, Mutex, + atomic::{AtomicUsize, Ordering}, + }, + time::Duration, +}; + +struct TestBackend { + concurrent: AtomicUsize, + max_allowed: usize, +} + +impl TestBackend { + fn new(max_allowed: usize) -> Self { + Self { + concurrent: AtomicUsize::new(0), + max_allowed, + } + } +} + +#[async_trait] +impl BbBackend for TestBackend { + async fn prove( + &self, + _program: &[u8], + _bytecode: &[u8], + _key: &[u8], + _witness: &[u8], + _oracle: bool, + ) -> barretenberg_interface::error::Result> { + self.enter(); + tokio::time::sleep(Duration::from_millis(50)).await; + self.exit(); + Ok(Vec::new()) + } + + async fn verify( + &self, + _proof: &[u8], + _public_inputs: &[u8], + _key: &[u8], + _oracle: bool, + ) -> barretenberg_interface::error::Result<()> { + tokio::time::sleep(Duration::from_millis(10)).await; + Ok(()) + } +} + +impl TestBackend { + fn enter(&self) { + let current = self.concurrent.fetch_add(1, Ordering::SeqCst); + assert!( + current < self.max_allowed, + "backend concurrency exceeded limit" + ); + } + + fn exit(&self) { + self.concurrent.fetch_sub(1, Ordering::SeqCst); + } +} + +#[tokio::test] +async fn limits_parallel_prove_calls() { + let inner: Arc = Arc::new(TestBackend::new(1)); + let backend = Arc::new(LimitedBbBackend::new(inner, 1)); + + let mut handles = Vec::new(); + for _ in 0..2 { + let backend = Arc::clone(&backend); + handles.push(tokio::spawn(async move { + backend + .prove(&[], &[], &[], &[], false) + .await + .expect("prove succeeds"); + })); + } + + for handle in handles { + handle.await.expect("task join succeeds"); + } +} + +#[tokio::test] +async fn verify_not_limited() { + let inner: Arc = Arc::new(TestBackend::new(1)); + let backend = Arc::new(LimitedBbBackend::new(inner, 1)); + + let b = Arc::clone(&backend); + let prove_handle = tokio::spawn(async move { + b.prove(&[], &[], &[], &[], false) + .await + .expect("prove succeeds"); + }); + + tokio::time::sleep(Duration::from_millis(10)).await; + + let mut handles = Vec::new(); + for _ in 0..5 { + let b = Arc::clone(&backend); + handles.push(tokio::spawn(async move { + b.verify(&[], &[], &[], false) + .await + .expect("verify succeeds"); + })); + } + + for handle in handles { + handle.await.expect("verify task join succeeds"); + } + + prove_handle.await.expect("prove task join succeeds"); +} + +#[tokio::test] +async fn respects_priority() { + let inner: Arc = Arc::new(TestBackend::new(1)); + let base_backend = Arc::new(LimitedBbBackend::new(inner, 1)); + let results = Arc::new(Mutex::new(Vec::new())); + + let b = base_backend.with_priority(10); + let r = Arc::clone(&results); + tokio::spawn(async move { + b.prove(&[], &[], &[], &[], false).await.unwrap(); + r.lock().unwrap().push(10); + }); + + tokio::time::sleep(Duration::from_millis(10)).await; + + let b = base_backend.with_priority(1); + let r = Arc::clone(&results); + tokio::spawn(async move { + b.prove(&[], &[], &[], &[], false).await.unwrap(); + r.lock().unwrap().push(1); + }); + + let b = base_backend.with_priority(5); + let r = Arc::clone(&results); + tokio::spawn(async move { + b.prove(&[], &[], &[], &[], false).await.unwrap(); + r.lock().unwrap().push(5); + }); + + tokio::time::sleep(Duration::from_millis(300)).await; + + assert_eq!(*results.lock().unwrap(), vec![10, 1, 5]); +} diff --git a/pkg/aggregator/src/retryable_rollup_contract.rs b/pkg/aggregator/src/retryable_rollup_contract.rs new file mode 100644 index 0000000..ce2f60e --- /dev/null +++ b/pkg/aggregator/src/retryable_rollup_contract.rs @@ -0,0 +1,145 @@ +use std::time::Duration; + +use aggregator_interface::{ContractError, RollupContract, RollupInput}; +use async_trait::async_trait; +use element::Element; +use tokio::time::sleep; +use tracing::warn; + +pub struct RetryableRollupContract { + inner: Box, + retry_attempts: usize, + retry_delay: Duration, +} + +impl RetryableRollupContract { + pub fn new( + inner: Box, + retry_attempts: usize, + retry_delay: Duration, + ) -> Self { + Self { + inner, + retry_attempts, + retry_delay, + } + } +} + +#[async_trait] +impl RollupContract for RetryableRollupContract { + async fn height(&self) -> Result { + self.inner.height().await + } + + async fn root_hash(&self) -> Result { + self.inner.root_hash().await + } + + async fn submit_rollup(&self, rollup: &RollupInput) -> Result<(), ContractError> { + let mut attempts = 0; + loop { + // RollupInput implements Clone, so we can clone it for each attempt + match self.inner.submit_rollup(&rollup.clone()).await { + Ok(()) => return Ok(()), + Err(err) => { + attempts += 1; + if attempts >= self.retry_attempts { + return Err(err); + } + warn!( + error = ?err, + attempts, + delay = ?self.retry_delay, + "failed to submit rollup, retrying..." + ); + sleep(self.retry_delay).await; + } + } + } + } +} + +#[cfg(test)] +mod tests { + use aggregator_interface::RollupContractMock; + use unimock::*; + + use super::*; + + fn mock_input() -> RollupInput { + RollupInput { + proof: vec![], + old_root: Element::ZERO, + new_root: Element::ZERO, + commit_hash: Element::ZERO, + utxo_messages: vec![], + kzg: vec![], + other_hash: [0; 32], + height: 1, + signatures: vec![], + gas_per_burn_call: 100, + } + } + + #[tokio::test] + async fn submit_rollup_succeeds_immediately() { + let mock = RollupContractMock::submit_rollup + .next_call(matching!(_)) + .returns(Ok(())); + + let contract = + RetryableRollupContract::new(Box::new(Unimock::new(mock)), 3, Duration::from_millis(1)); + + contract.submit_rollup(&mock_input()).await.unwrap(); + } + + #[tokio::test] + async fn submit_rollup_retries_and_succeeds() { + let mock = Unimock::new(( + RollupContractMock::submit_rollup + .next_call(matching!(_)) + .returns(Err(ContractError::ImplementationSpecific(Box::new( + std::io::Error::other("fail 1"), + )))), + RollupContractMock::submit_rollup + .next_call(matching!(_)) + .returns(Err(ContractError::ImplementationSpecific(Box::new( + std::io::Error::other("fail 2"), + )))), + RollupContractMock::submit_rollup + .next_call(matching!(_)) + .returns(Ok(())), + )); + + let contract = RetryableRollupContract::new(Box::new(mock), 3, Duration::from_millis(1)); + + contract.submit_rollup(&mock_input()).await.unwrap(); + } + + #[tokio::test] + async fn submit_rollup_fails_after_retries() { + let mock = Unimock::new(( + RollupContractMock::submit_rollup + .next_call(matching!(_)) + .returns(Err(ContractError::ImplementationSpecific(Box::new( + std::io::Error::other("fail"), + )))), + RollupContractMock::submit_rollup + .next_call(matching!(_)) + .returns(Err(ContractError::ImplementationSpecific(Box::new( + std::io::Error::other("fail"), + )))), + RollupContractMock::submit_rollup + .next_call(matching!(_)) + .returns(Err(ContractError::ImplementationSpecific(Box::new( + std::io::Error::other("fail"), + )))), + )); + + let contract = RetryableRollupContract::new(Box::new(mock), 3, Duration::from_millis(1)); + + let result = contract.submit_rollup(&mock_input()).await; + assert!(result.is_err()); + } +} diff --git a/pkg/aggregator/src/smirk_rollup_tree.rs b/pkg/aggregator/src/smirk_rollup_tree.rs new file mode 100644 index 0000000..6bb04ad --- /dev/null +++ b/pkg/aggregator/src/smirk_rollup_tree.rs @@ -0,0 +1,117 @@ +use aggregator_interface::{BlockProverError, RollupTree}; +use element::Element; +use prover::smirk_metadata::SmirkMetadata; +use smirk::{Batch, CollisionError, Tree, hash_cache::SimpleHashCache}; + +const MERKLE_TREE_DEPTH: usize = 161; + +type InnerTree = Tree<{ MERKLE_TREE_DEPTH }, SmirkMetadata, SimpleHashCache>; + +/// [`RollupTree`] implementation backed by a [`smirk::Tree`]. +#[derive(Debug, Clone)] +pub struct SmirkRollupTree { + tree: InnerTree, + height: u64, +} + +impl Default for SmirkRollupTree { + fn default() -> Self { + Self { + tree: Tree::new(), + height: 0, + } + } +} + +impl SmirkRollupTree { + /// Create a new, empty tree with height 0. + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// Construct the wrapper from an existing [`smirk::Tree`]. + #[must_use] + pub fn from_tree(tree: InnerTree, height: u64) -> Self { + Self { tree, height } + } + + /// Consume the wrapper and return the inner tree. + #[must_use] + pub fn into_inner(self) -> (InnerTree, u64) { + (self.tree, self.height) + } + + fn map_collision(err: CollisionError) -> BlockProverError { + BlockProverError::ImplementationSpecific(Box::new(err)) + } +} + +impl RollupTree for SmirkRollupTree { + fn root_hash(&self) -> Element { + self.tree.root_hash() + } + + fn height(&self) -> u64 { + self.height + } + + fn set_height(&mut self, height: u64) { + self.height = height; + } + + fn sibling_path(&self, element: Element) -> Result, BlockProverError> { + Ok(self + .tree + .path_for(element) + .siblings_deepest_first() + .to_vec()) + } + + fn remove(&mut self, element: Element) -> Result<(), BlockProverError> { + self.tree.remove(element).map_err(Self::map_collision) + } + + fn insert(&mut self, entries: &[(Element, u64)]) -> Result<(), BlockProverError> { + if entries.is_empty() { + return Ok(()); + } + + let mut batch = Batch::::with_capacity(entries.len()); + for (element, inserted_in) in entries { + batch + .insert(*element, SmirkMetadata::inserted_in(*inserted_in)) + .map_err(Self::map_collision)?; + } + + self.tree + .insert_batch(batch, |_| {}, |_| {}) + .map_err(Self::map_collision) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn element(value: u64) -> Element { + Element::new(value) + } + + #[test] + fn insert_and_remove_round_trip() { + let mut tree = SmirkRollupTree::new(); + let start_root = tree.root_hash(); + let element = element(42); + + tree.insert(&[(element, 1)]).unwrap(); + assert_ne!(tree.root_hash(), start_root); + assert_eq!( + tree.sibling_path(element).unwrap().len(), + MERKLE_TREE_DEPTH - 1 + ); + + tree.remove(element).unwrap(); + assert_eq!(tree.root_hash(), start_root); + } +} diff --git a/pkg/barretenberg-api-bin/Cargo.toml b/pkg/barretenberg-api-bin/Cargo.toml new file mode 100644 index 0000000..234f025 --- /dev/null +++ b/pkg/barretenberg-api-bin/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "barretenberg-api-bin" +version = "0.1.0" +edition = "2024" + +[dependencies] +axum = { workspace = true } +barretenberg-api-server = { workspace = true } +barretenberg-cli = { workspace = true } +barretenberg-interface = { workspace = true } +clap = { workspace = true } +rpc = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/barretenberg-api-bin/src/main.rs b/pkg/barretenberg-api-bin/src/main.rs new file mode 100644 index 0000000..619eeb9 --- /dev/null +++ b/pkg/barretenberg-api-bin/src/main.rs @@ -0,0 +1,82 @@ +use std::{ + io, + net::{IpAddr, SocketAddr}, + sync::Arc, +}; + +use barretenberg_api_server::build_app; +use barretenberg_cli::CliBackend; +use barretenberg_interface::BbBackend; +use clap::Parser; +use rpc::tracing::{LogFormat, LogLevel, setup_tracing}; +use tracing::info; + +const TRACING_MODULES: &[&str] = &[ + "barretenberg_api_bin", + "barretenberg_api_server", + "barretenberg_api_client", + "barretenberg_cli", + "barretenberg_interface", + "barretenberg_rs", + "element", + "notes", +]; + +#[derive(Parser, Debug)] +#[command( + name = "barretenberg-api-server", + about = "HTTP API server for the Barretenberg backend" +)] +struct Args { + #[arg(long, default_value = "0.0.0.0")] + host: String, + #[arg(long, default_value_t = 9444)] + port: u16, + /// Log level + #[arg(value_enum, long, env = "LOG_LEVEL", default_value = "INFO")] + log_level: LogLevel, + /// Log format + #[arg(value_enum, long, env = "LOG_FORMAT", default_value = "PRETTY")] + log_format: LogFormat, + /// Deployment environment name for tracing / sentry tagging + #[arg(long, env = "ENV_NAME", default_value = "dev")] + env: String, +} + +#[tokio::main] +async fn main() -> io::Result<()> { + let args = Args::parse(); + + let _guard = setup_tracing( + TRACING_MODULES, + &args.log_level, + &args.log_format, + std::env::var("SENTRY_DSN").ok(), + args.env.clone(), + ) + .map_err(|err| io::Error::other(err.to_string()))?; + + let bind_addr = parse_bind_addr(&args.host, args.port)?; + + let backend: Arc = Arc::new(CliBackend); + + info!( + target: "barretenberg_api_server", + %bind_addr, + "starting barretenberg api binary" + ); + + let app = build_app(Arc::clone(&backend)); + let listener = tokio::net::TcpListener::bind(bind_addr).await?; + axum::serve(listener, app).await +} + +fn parse_bind_addr(host: &str, port: u16) -> io::Result { + let ip = host.parse::().map_err(|err| { + io::Error::new( + io::ErrorKind::InvalidInput, + format!("invalid host {host}: {err}"), + ) + })?; + Ok(SocketAddr::new(ip, port)) +} diff --git a/pkg/barretenberg-api-client/Cargo.toml b/pkg/barretenberg-api-client/Cargo.toml new file mode 100644 index 0000000..1293e57 --- /dev/null +++ b/pkg/barretenberg-api-client/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "barretenberg-api-client" +version = "0.1.0" +edition = "2024" + +[dependencies] +async-trait = { workspace = true } +barretenberg-api-interface = { workspace = true } +barretenberg-interface = { workspace = true } +contextful = { workspace = true } +thiserror = { workspace = true } +rustls = { workspace = true } +tokio-rustls = { workspace = true } +webpki-roots = { workspace = true } +httparse = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +url = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/barretenberg-api-client/src/error.rs b/pkg/barretenberg-api-client/src/error.rs new file mode 100644 index 0000000..ca18e1f --- /dev/null +++ b/pkg/barretenberg-api-client/src/error.rs @@ -0,0 +1,33 @@ +use barretenberg_api_interface::ServerError; +use barretenberg_interface::Error as BackendError; +use contextful::Contextful; +use thiserror::Error; + +pub use crate::http_transport::error::TransportError; + +#[derive(Debug, Error)] +pub enum ClientError { + #[error("[barretenberg-api-client] transport error")] + // Skipping Contextful because no extra context is needed. + Transport(#[from] TransportError), + + #[error("[barretenberg-api-client] server error")] + // Skipping Contextful because no extra context is needed. + Server(#[from] ServerError), + + #[error("[barretenberg-api-client] tokio runtime creation failed")] + Runtime(#[from] Contextful), +} + +impl From for BackendError { + fn from(error: ClientError) -> Self { + match error { + ClientError::Server(ServerError::Backend(err)) => err.into(), + ClientError::Transport(TransportError::RetryDeadlineExceeded { + last_error: Some(err), + .. + }) => (*err).into(), + other => BackendError::ImplementationSpecific(Box::new(other)), + } + } +} diff --git a/pkg/barretenberg-api-client/src/http_transport/error.rs b/pkg/barretenberg-api-client/src/http_transport/error.rs new file mode 100644 index 0000000..5be7159 --- /dev/null +++ b/pkg/barretenberg-api-client/src/http_transport/error.rs @@ -0,0 +1,62 @@ +use std::time::Duration; +use tokio::time::error::Elapsed; + +use barretenberg_interface::Error as BackendError; +use contextful::Contextful; +use thiserror::Error; + +use crate::error::ClientError; + +#[derive(Debug, Error)] +pub enum TransportError { + #[error("[barretenberg-api-client] missing base url host")] + MissingBaseUrlHost, + #[error("[barretenberg-api-client] missing request url host")] + MissingRequestUrlHost, + #[error( + "[barretenberg-api-client] request timed out after {timeout:?} (attempts: {attempts}): {elapsed}" + )] + RequestTimeout { + timeout: Duration, + attempts: usize, + elapsed: Elapsed, + }, + #[error("[barretenberg-api-client] retry deadline overflow for {duration:?}")] + RetryDeadlineOverflow { duration: Duration }, + #[error( + "[barretenberg-api-client] retry deadline exceeded after {duration:?} (attempts: {attempts}) (last error: {last_error:?})" + )] + RetryDeadlineExceeded { + duration: Duration, + attempts: usize, + last_error: Option>, + }, + #[error("[barretenberg-api-client] connection closed while waiting for 100-continue")] + ConnectionClosedWhileWaitingForContinue, + #[error("[barretenberg-api-client] timeout waiting for 100-continue")] + ContinueTimeout, + #[error("[barretenberg-api-client] connection closed before response")] + ConnectionClosedBeforeResponse, + #[error("[barretenberg-api-client] infrastructure error (status: {status}): {body}")] + Infrastructure { status: u16, body: String }, + #[error("[barretenberg-api-client] unexpected response (status: {status}): {body}")] + UnexpectedResponse { status: u16, body: String }, + #[error("[barretenberg-api-client] url error: {0}")] + Url(#[from] Contextful), + #[error("[barretenberg-api-client] dns name error: {0}")] + DnsName(#[from] Contextful), + #[error("[barretenberg-api-client] tls error: {0}")] + Tls(#[from] Contextful), + #[error("[barretenberg-api-client] io error: {0}")] + Io(#[from] Contextful), + #[error("[barretenberg-api-client] json error: {0}")] + Json(#[from] Contextful), + #[error("[barretenberg-api-client] parse error: {0}")] + Parse(#[from] Contextful), +} + +impl From for BackendError { + fn from(error: TransportError) -> Self { + BackendError::ImplementationSpecific(Box::new(error)) + } +} diff --git a/pkg/barretenberg-api-client/src/http_transport/mod.rs b/pkg/barretenberg-api-client/src/http_transport/mod.rs new file mode 100644 index 0000000..496029e --- /dev/null +++ b/pkg/barretenberg-api-client/src/http_transport/mod.rs @@ -0,0 +1,253 @@ +// lint-long-file-override allow-max-lines=400 +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use async_trait::async_trait; +use barretenberg_api_interface::ServerError; +use contextful::ResultContextExt; +use rustls::pki_types::ServerName; +use serde::{Serialize, de::DeserializeOwned}; +use tokio::net::TcpStream; +use tokio::time::sleep; +use tokio_rustls::{TlsConnector, rustls}; +use tracing::{debug, warn}; +use url::Url; + +use crate::error::ClientError; +use crate::{ApiTransport, ProveRequest, ProveResponse, VerifyRequest, VerifyResponse}; + +pub(crate) mod error; +mod protocol; +pub(crate) mod stream; + +use error::TransportError; +use protocol::{perform_handshake_and_write_body, read_and_parse_response}; +use stream::MaybeTlsStream; + +pub(crate) const DEFAULT_RETRY_DELAY: Duration = Duration::from_millis(500); +pub(crate) const DEFAULT_MAX_RETRY_DURATION: Duration = Duration::from_secs(60 * 60); +pub(crate) const DEFAULT_EXPECT_CONTINUE_TIMEOUT_BUFFER: Duration = Duration::from_millis(500); +pub(crate) const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_secs(1); + +pub(crate) struct HttpTransport { + base_url: Url, + timeout: Duration, + connect_timeout: Duration, + permit_timeout: Option, + retry_delay: Duration, + max_retry_duration: Duration, + expect_continue_timeout_buffer: Duration, + tls_connector: TlsConnector, +} + +impl HttpTransport { + pub(crate) fn new( + base_url: Url, + timeout: Duration, + connect_timeout: Duration, + permit_timeout: Option, + retry_delay: Duration, + max_retry_duration: Duration, + expect_continue_timeout_buffer: Duration, + ) -> std::result::Result { + let mut root_store = rustls::RootCertStore::empty(); + root_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + let config = rustls::ClientConfig::builder_with_provider( + rustls::crypto::ring::default_provider().into(), + ) + .with_safe_default_protocol_versions() + .context("configure tls protocol versions")? + .with_root_certificates(root_store) + .with_no_client_auth(); + let tls_connector = TlsConnector::from(Arc::new(config)); + + Ok(Self { + base_url, + timeout, + connect_timeout, + permit_timeout, + retry_delay, + max_retry_duration, + expect_continue_timeout_buffer, + tls_connector, + }) + } + + async fn connect(&self) -> std::result::Result { + match tokio::time::timeout(self.connect_timeout, self.connect_inner()).await { + Ok(result) => result, + Err(elapsed) => Err(ClientError::Transport(TransportError::RequestTimeout { + timeout: self.connect_timeout, + attempts: 0, + elapsed, + })), + } + } + + async fn connect_inner(&self) -> std::result::Result { + let host = self + .base_url + .host_str() + .ok_or_else(|| TransportError::MissingBaseUrlHost)?; + let port = + self.base_url + .port_or_known_default() + .unwrap_or(if self.base_url.scheme() == "https" { + 443 + } else { + 80 + }); + let addr = format!("{}:{}", host, port); + + let stream = TcpStream::connect(&addr) + .await + .context("connect to barretenberg api host") + .map_err(TransportError::Io)?; + + let _ = stream.set_nodelay(true); + + if self.base_url.scheme() == "https" { + let domain = ServerName::try_from(host) + .context("parse dns name") + .map_err(TransportError::DnsName)? + .to_owned(); + + let connector = self.tls_connector.clone(); + let stream = connector + .connect(domain, stream) + .await + .context("perform tls handshake") + .map_err(TransportError::Io)?; + + Ok(MaybeTlsStream::Tls(Box::new(stream))) + } else { + Ok(MaybeTlsStream::Plain(stream)) + } + } + + async fn send_request( + &self, + path: &str, + payload: Req, + permit_timeout: Option, + ) -> std::result::Result + where + Req: Serialize, + Resp: DeserializeOwned, + { + let mut attempt = 0; + let mut last_error: Option = None; + let deadline = Instant::now().checked_add(self.max_retry_duration).ok_or( + TransportError::RetryDeadlineOverflow { + duration: self.max_retry_duration, + }, + )?; + + loop { + attempt += 1; + + let result = tokio::time::timeout( + self.timeout, + self.try_request(path, &payload, permit_timeout), + ) + .await; + + let result = match result { + Ok(res) => res, + Err(err) => Err(ClientError::Transport(TransportError::RequestTimeout { + timeout: self.timeout, + attempts: attempt, + elapsed: err, + })), + }; + + let err = match result { + Ok(resp) => return Ok(resp), + Err(err) => err, + }; + + match &err { + ClientError::Server(ServerError::ServiceUnavailable { .. }) => { + debug!( + target: "barretenberg_api_client", + attempt = attempt, + ?last_error, + "service unavailable, retrying" + ); + } + ClientError::Server(_) => return Err(err), + ClientError::Transport(transport_err) => { + warn!( + target: "barretenberg_api_client", + error = %transport_err, + attempt = attempt, + ?last_error, + "received transport error, retrying" + ); + } + _ => return Err(err), + } + + last_error = Some(err); + + if Instant::now() >= deadline { + return Err(ClientError::Transport( + TransportError::RetryDeadlineExceeded { + duration: self.max_retry_duration, + attempts: attempt, + last_error: last_error.map(Box::new), + }, + )); + } + + sleep(self.retry_delay).await; + } + } + + async fn try_request( + &self, + path: &str, + payload: &Req, + permit_timeout: Option, + ) -> std::result::Result + where + Req: Serialize, + Resp: DeserializeOwned, + { + let body = serde_json::to_vec(payload) + .context("serialize payload") + .map_err(TransportError::Json)?; + + let mut stream = self.connect().await?; + + let buffer = perform_handshake_and_write_body( + &mut stream, + &self.base_url, + path, + &body, + permit_timeout, + self.expect_continue_timeout_buffer, + ) + .await?; + + read_and_parse_response(&mut stream, buffer).await + } +} + +#[async_trait] +impl ApiTransport for HttpTransport { + async fn prove( + &self, + request: ProveRequest, + ) -> std::result::Result { + self.send_request("prove", request, self.permit_timeout) + .await + } + + async fn verify( + &self, + request: VerifyRequest, + ) -> std::result::Result { + self.send_request("verify", request, None).await + } +} diff --git a/pkg/barretenberg-api-client/src/http_transport/protocol.rs b/pkg/barretenberg-api-client/src/http_transport/protocol.rs new file mode 100644 index 0000000..c326ad9 --- /dev/null +++ b/pkg/barretenberg-api-client/src/http_transport/protocol.rs @@ -0,0 +1,268 @@ +// lint-long-file-override allow-max-lines=300 +use std::{io, time::Duration}; + +use barretenberg_api_interface::{PERMIT_TIMEOUT_HEADER, ServerError}; +use contextful::{ErrorContextExt, ResultContextExt}; +use serde::de::DeserializeOwned; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use url::Url; + +use super::error::TransportError; +use super::stream::MaybeTlsStream; +use crate::error::ClientError; + +pub(crate) async fn perform_handshake_and_write_body( + stream: &mut MaybeTlsStream, + base_url: &Url, + path: &str, + body: &[u8], + permit_timeout: Option, + expect_continue_timeout_buffer: Duration, +) -> std::result::Result, ClientError> { + let url = base_url + .join(path) + .context("join request url") + .map_err(TransportError::from)?; + let host = url + .host_str() + .ok_or_else(|| TransportError::MissingRequestUrlHost)?; + + let path_query = if let Some(q) = url.query() { + format!("{}?{}", url.path(), q) + } else { + url.path().to_owned() + }; + + let mut headers = format!( + "POST {} HTTP/1.1\r\n\ + Host: {}\r\n\ + Connection: close\r\n\ + Content-Type: application/json\r\n\ + Content-Length: {}\r\n\ + Expect: 100-continue\r\n", + path_query, + host, + body.len() + ); + + if let Some(pt) = permit_timeout { + headers.push_str(&format!( + "{}: {}\r\n", + PERMIT_TIMEOUT_HEADER, + duration_to_ms(pt) + )); + } + headers.push_str("\r\n"); + + stream + .write_all(headers.as_bytes()) + .await + .context("write request headers") + .map_err(TransportError::Io)?; + stream + .flush() + .await + .context("flush request headers") + .map_err(TransportError::Io)?; + + let wait_time = permit_timeout + .unwrap_or(Duration::ZERO) + .checked_add(expect_continue_timeout_buffer) + .unwrap_or(Duration::from_secs(1)); + + let (should_write_body, buffer) = wait_for_continue(stream, wait_time).await?; + + if should_write_body { + stream + .write_all(body) + .await + .context("write request body") + .map_err(TransportError::Io)?; + stream + .flush() + .await + .context("flush request body") + .map_err(TransportError::Io)?; + } + + Ok(buffer) +} + +async fn wait_for_continue( + stream: &mut MaybeTlsStream, + wait_time: Duration, +) -> std::result::Result<(bool, Vec), ClientError> { + let mut buffer = Vec::with_capacity(1024); + let mut temp_buf = [0u8; 1024]; + + let continue_result = tokio::time::timeout(wait_time, async { + loop { + let n = + read_allow_unexpected_eof(stream, &mut temp_buf, "read continue response").await?; + if n == 0 { + return Err(ClientError::Transport( + TransportError::ConnectionClosedWhileWaitingForContinue, + )); + } + buffer.extend_from_slice(&temp_buf[..n]); + + let mut headers = [httparse::Header { + name: "", + value: &[], + }; 16]; + let mut req = httparse::Response::new(&mut headers); + match req + .parse(&buffer) + .context("parse continue response") + .map_err(TransportError::Parse)? + { + httparse::Status::Complete(offset) => { + if req.code == Some(100) { + buffer.drain(..offset); + return Ok((true, buffer)); + } else { + return Ok((false, buffer)); + } + } + httparse::Status::Partial => continue, + } + } + }) + .await; + + match continue_result { + Ok(Ok(v)) => Ok(v), + Ok(Err(e)) => Err(e), + Err(_) => Err(ClientError::Transport(TransportError::ContinueTimeout)), + } +} + +pub(crate) async fn read_and_parse_response( + stream: &mut MaybeTlsStream, + initial_buffer: Vec, +) -> std::result::Result +where + Resp: DeserializeOwned, +{ + let mut buffer = initial_buffer; + if buffer.capacity() < 4096 { + buffer.reserve(4096 - buffer.len()); + } + + let mut temp_buf = [0u8; 4096]; + let mut body_start = 0; + let mut headers_parsed = false; + + loop { + if !headers_parsed { + let mut headers = [httparse::Header { + name: "", + value: &[], + }; 64]; + let mut resp = httparse::Response::new(&mut headers); + match resp + .parse(&buffer) + .context("parse response headers") + .map_err(TransportError::Parse)? + { + httparse::Status::Complete(offset) => { + body_start = offset; + headers_parsed = true; + break; + } + httparse::Status::Partial => {} // continue reading + } + } + + let n = read_allow_unexpected_eof(stream, &mut temp_buf, "read response").await?; + if n == 0 { + if buffer.is_empty() { + return Err(ClientError::Transport( + TransportError::ConnectionClosedBeforeResponse, + )); + } + break; + } + buffer.extend_from_slice(&temp_buf[..n]); + } + + if headers_parsed + && let Err(err) = stream.read_to_end(&mut buffer).await + && !is_unexpected_eof(&err) + { + return Err(ClientError::Transport(TransportError::Io( + err.wrap_err("read response body"), + ))); + } + + let mut headers = [httparse::Header { + name: "", + value: &[], + }; 64]; + let mut resp = httparse::Response::new(&mut headers); + resp.parse(&buffer) + .context("parse response headers") + .map_err(TransportError::Parse)?; + + let status = resp.code.unwrap_or(0); + let body_slice = if headers_parsed && body_start <= buffer.len() { + &buffer[body_start..] + } else { + &[] + }; + + match status { + 200..=299 => serde_json::from_slice(body_slice) + .context("parse response body") + .map_err(TransportError::Json) + .map_err(ClientError::from), + 400..=499 => { + let body_str = String::from_utf8_lossy(body_slice).into_owned(); + Err(serde_json::from_str::(&body_str) + .map(ClientError::Server) + .unwrap_or_else(|_| { + TransportError::UnexpectedResponse { + status, + body: body_str, + } + .into() + })) + } + 500..=599 => { + let body_str = String::from_utf8_lossy(body_slice).into_owned(); + Err(ClientError::Transport(TransportError::Infrastructure { + status, + body: body_str, + })) + } + _ => { + let body_str = String::from_utf8_lossy(body_slice).into_owned(); + Err(ClientError::Transport(TransportError::UnexpectedResponse { + status, + body: body_str, + })) + } + } +} + +fn duration_to_ms(duration: Duration) -> u64 { + duration.as_millis().min(u128::from(u64::MAX)) as u64 +} + +fn is_unexpected_eof(error: &io::Error) -> bool { + error.kind() == io::ErrorKind::UnexpectedEof +} + +async fn read_allow_unexpected_eof( + stream: &mut MaybeTlsStream, + buffer: &mut [u8], + context: &'static str, +) -> std::result::Result { + match stream.read(buffer).await { + Ok(bytes) => Ok(bytes), + Err(err) if is_unexpected_eof(&err) => Ok(0), + Err(err) => Err(ClientError::Transport(TransportError::Io( + err.wrap_err(context), + ))), + } +} diff --git a/pkg/barretenberg-api-client/src/http_transport/stream.rs b/pkg/barretenberg-api-client/src/http_transport/stream.rs new file mode 100644 index 0000000..96675c1 --- /dev/null +++ b/pkg/barretenberg-api-client/src/http_transport/stream.rs @@ -0,0 +1,50 @@ +use std::pin::Pin; +use std::task::{Context, Poll}; + +use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; +use tokio::net::TcpStream; + +pub enum MaybeTlsStream { + Plain(TcpStream), + Tls(Box>), +} + +impl AsyncRead for MaybeTlsStream { + fn poll_read( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll> { + match self.get_mut() { + MaybeTlsStream::Plain(s) => Pin::new(s).poll_read(cx, buf), + MaybeTlsStream::Tls(s) => Pin::new(s).poll_read(cx, buf), + } + } +} + +impl AsyncWrite for MaybeTlsStream { + fn poll_write( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + match self.get_mut() { + MaybeTlsStream::Plain(s) => Pin::new(s).poll_write(cx, buf), + MaybeTlsStream::Tls(s) => Pin::new(s).poll_write(cx, buf), + } + } + + fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.get_mut() { + MaybeTlsStream::Plain(s) => Pin::new(s).poll_flush(cx), + MaybeTlsStream::Tls(s) => Pin::new(s).poll_flush(cx), + } + } + + fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.get_mut() { + MaybeTlsStream::Plain(s) => Pin::new(s).poll_shutdown(cx), + MaybeTlsStream::Tls(s) => Pin::new(s).poll_shutdown(cx), + } + } +} diff --git a/pkg/barretenberg-api-client/src/lib.rs b/pkg/barretenberg-api-client/src/lib.rs new file mode 100644 index 0000000..a3e72c4 --- /dev/null +++ b/pkg/barretenberg-api-client/src/lib.rs @@ -0,0 +1,158 @@ +use std::{sync::Arc, time::Duration}; + +use async_trait::async_trait; +pub use barretenberg_api_interface::{ + BbBackendError, ProveRequest, ProveResponse, ServerError, VerifyRequest, VerifyResponse, +}; +use barretenberg_interface::{BbBackend, Result}; +use url::Url; + +pub mod error; +mod http_transport; + +use error::ClientError; +use http_transport::{ + DEFAULT_CONNECT_TIMEOUT, DEFAULT_EXPECT_CONTINUE_TIMEOUT_BUFFER, DEFAULT_MAX_RETRY_DURATION, + DEFAULT_RETRY_DELAY, HttpTransport, +}; + +#[async_trait] +pub trait ApiTransport: Send + Sync { + async fn prove(&self, request: ProveRequest) + -> std::result::Result; + async fn verify( + &self, + request: VerifyRequest, + ) -> std::result::Result; +} + +#[derive(Clone)] +pub struct ClientBackend { + transport: Arc, +} + +impl ClientBackend { + pub fn new(base_url: Url) -> Result { + let transport = HttpTransport::new( + base_url, + Duration::from_secs(5 * 60), + DEFAULT_CONNECT_TIMEOUT, + Some(Duration::from_millis(100)), + DEFAULT_RETRY_DELAY, + DEFAULT_MAX_RETRY_DURATION, + DEFAULT_EXPECT_CONTINUE_TIMEOUT_BUFFER, + ) + .map_err(ClientError::from)?; + Ok(Self::with_transport(transport)) + } + + pub fn with_timeout(base_url: Url, timeout: Duration) -> Result { + let transport = HttpTransport::new( + base_url, + timeout, + DEFAULT_CONNECT_TIMEOUT, + Some(Duration::from_millis(100)), + DEFAULT_RETRY_DELAY, + DEFAULT_MAX_RETRY_DURATION, + DEFAULT_EXPECT_CONTINUE_TIMEOUT_BUFFER, + ) + .map_err(ClientError::from)?; + Ok(Self::with_transport(transport)) + } + + pub fn with_timeout_and_permit( + base_url: Url, + timeout: Duration, + permit: Duration, + ) -> Result { + let transport = HttpTransport::new( + base_url, + timeout, + DEFAULT_CONNECT_TIMEOUT, + Some(permit), + DEFAULT_RETRY_DELAY, + DEFAULT_MAX_RETRY_DURATION, + DEFAULT_EXPECT_CONTINUE_TIMEOUT_BUFFER, + ) + .map_err(ClientError::from)?; + Ok(Self::with_transport(transport)) + } + + pub fn with_retry_policy( + base_url: Url, + timeout: Duration, + connect_timeout: Duration, + permit_timeout: Option, + retry_delay: Duration, + max_retry_duration: Duration, + expect_continue_timeout_buffer: Duration, + ) -> Result { + let transport = HttpTransport::new( + base_url, + timeout, + connect_timeout, + permit_timeout, + retry_delay, + max_retry_duration, + expect_continue_timeout_buffer, + ) + .map_err(ClientError::from)?; + Ok(Self::with_transport(transport)) + } + + pub fn with_transport(transport: T) -> Self + where + T: ApiTransport + 'static, + { + Self { + transport: Arc::new(transport), + } + } +} + +#[async_trait] +impl BbBackend for ClientBackend { + async fn prove( + &self, + program: &[u8], + bytecode: &[u8], + key: &[u8], + witness: &[u8], + oracle: bool, + ) -> Result> { + let request = ProveRequest { + program: program.into(), + bytecode: bytecode.into(), + key: key.into(), + witness: witness.into(), + oracle, + }; + + let response = self.transport.prove(request).await?; + Ok(response.proof.into_inner()) + } + + async fn verify( + &self, + proof: &[u8], + public_inputs: &[u8], + key: &[u8], + oracle: bool, + ) -> Result<()> { + let request = VerifyRequest { + proof: proof.into(), + public_inputs: public_inputs.into(), + key: key.into(), + oracle, + }; + + let response = self.transport.verify(request).await?; + if response.valid { + Ok(()) + } else { + Err(ClientError::Server(ServerError::Backend( + BbBackendError::VerificationFailed, + )))? + } + } +} diff --git a/pkg/barretenberg-api-interface/Cargo.toml b/pkg/barretenberg-api-interface/Cargo.toml new file mode 100644 index 0000000..7199715 --- /dev/null +++ b/pkg/barretenberg-api-interface/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "barretenberg-api-interface" +version = "0.1.0" +edition = "2024" + +[dependencies] +http = { workspace = true } +barretenberg-interface = { workspace = true } +thiserror = { workspace = true } +primitives = { workspace = true } +serde = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/barretenberg-api-interface/src/lib.rs b/pkg/barretenberg-api-interface/src/lib.rs new file mode 100644 index 0000000..dfe60a6 --- /dev/null +++ b/pkg/barretenberg-api-interface/src/lib.rs @@ -0,0 +1,173 @@ +#![deny(unsafe_code)] + +//! # Barretenberg API Interface +//! +//! This crate defines the shared types and error handling contract for the Barretenberg API. +//! +//! ## Error Handling Philosophy: Gateway Disambiguation +//! +//! A key design choice in this API is the separation of application-level errors from +//! infrastructure-level errors (gateways, proxies, load balancers). +//! +//! To achieve this, **the Barretenberg API server never returns HTTP 5xx status codes.** +//! +//! * **HTTP 4xx**: Indicates the request reached the application. This includes logical +//! errors (Invalid Request, Verification Failed) AND internal server failures (Task Panics, +//! Database failures). By using 4xx (specifically `422 Unprocessable Entity` for internal +//! errors), we ensure that a 5xx response is an unambiguous signal that the failure +//! occurred in the surrounding infrastructure, not the application logic. +//! * **HTTP 5xx**: Indicates a failure in the gateway or network layer. +//! +//! Clients should monitor for `ServerError` payloads in 4xx responses to track application health. + +use barretenberg_interface::Error as BackendError; +use primitives::serde::Base64Bytes; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +pub const PERMIT_TIMEOUT_HEADER: &str = "x-barretenberg-permit-timeout-ms"; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProveRequest { + pub program: Base64Bytes, + pub bytecode: Base64Bytes, + pub key: Base64Bytes, + pub witness: Base64Bytes, + #[serde(default)] + pub oracle: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProveResponse { + pub proof: Base64Bytes, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VerifyRequest { + pub proof: Base64Bytes, + pub public_inputs: Base64Bytes, + pub key: Base64Bytes, + #[serde(default)] + pub oracle: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct VerifyResponse { + pub valid: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Error)] +#[serde(tag = "code", content = "data", rename_all = "kebab-case")] +pub enum ServerError { + /// The server is busy or timed out waiting for resources (e.g. permit). + /// Corresponds to HTTP 429 Too Many Requests. + #[error("[barretenberg-api] service unavailable: {message}")] + ServiceUnavailable { message: String }, + + /// The request was invalid (bad JSON, missing headers, etc.). + /// Corresponds to HTTP 400 Bad Request. + #[error("[barretenberg-api] invalid request: {message}")] + InvalidRequest { message: String }, + + /// An error occurred in the underlying Barretenberg backend. + /// Corresponds to HTTP 422 Unprocessable Entity (VerificationFailed) or 400 Bad Request (Backend). + #[error("[barretenberg-api] backend error")] + Backend(#[from] BbBackendError), + + /// An internal server error occurred (not related to backend logic). + /// + /// Note: We use HTTP 422 Unprocessable Entity to distinguish application-level + /// crashes from infrastructure-level (gateway) 5xx errors. + #[error("[barretenberg-api] internal error: {message}")] + Internal { message: String }, +} + +impl ServerError { + pub fn status_code(&self) -> http::StatusCode { + match self { + ServerError::ServiceUnavailable { .. } => http::StatusCode::TOO_MANY_REQUESTS, + ServerError::InvalidRequest { .. } => http::StatusCode::BAD_REQUEST, + ServerError::Backend(err) => match err { + BbBackendError::VerificationFailed => http::StatusCode::UNPROCESSABLE_ENTITY, + BbBackendError::Backend { .. } => http::StatusCode::BAD_REQUEST, + BbBackendError::ImplementationSpecific { .. } => { + http::StatusCode::UNPROCESSABLE_ENTITY + } + }, + ServerError::Internal { .. } => http::StatusCode::UNPROCESSABLE_ENTITY, + } + } +} + +/// A serializable error type representing failures from the Barretenberg backend. +/// +/// This type mirrors `barretenberg_interface::Error` but is designed to be stable +/// and serializable for API communication. It decouples the API contract from +/// the internal backend error implementation, allowing the backend to evolve +/// without breaking API clients. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Error)] +#[serde(rename_all = "kebab-case")] +pub enum BbBackendError { + /// Corresponds to barretenberg_interface::Error::Backend(String) + #[error("[barretenberg-backend] backend: {message}")] + Backend { message: String }, + /// Corresponds to barretenberg_interface::Error::VerificationFailed + #[error("[barretenberg-backend] verification failed")] + VerificationFailed, + /// Corresponds to `barretenberg_interface::Error::ImplementationSpecific(Box)` + /// We stringify the error since we can't serialize `Box`. + #[error("[barretenberg-backend] implementation specific: {message}")] + ImplementationSpecific { message: String }, +} + +impl From for BbBackendError { + fn from(err: BackendError) -> Self { + match err { + BackendError::Backend(message) => BbBackendError::Backend { message }, + BackendError::VerificationFailed => BbBackendError::VerificationFailed, + BackendError::ImplementationSpecific(err) => BbBackendError::ImplementationSpecific { + message: err.to_string(), + }, + } + } +} + +impl From<&BackendError> for BbBackendError { + fn from(err: &BackendError) -> Self { + match err { + BackendError::Backend(message) => BbBackendError::Backend { + message: message.clone(), + }, + BackendError::VerificationFailed => BbBackendError::VerificationFailed, + BackendError::ImplementationSpecific(err) => BbBackendError::ImplementationSpecific { + message: err.to_string(), + }, + } + } +} + +impl From for BackendError { + fn from(err: BbBackendError) -> Self { + match err { + BbBackendError::Backend { message } => BackendError::Backend(message), + BbBackendError::VerificationFailed => BackendError::VerificationFailed, + BbBackendError::ImplementationSpecific { message } => { + BackendError::ImplementationSpecific(Box::new(ImplementationSpecificError { + message, + })) + } + } + } +} + +#[derive(Debug, Error)] +#[error("{message}")] +struct ImplementationSpecificError { + message: String, +} + +impl From for ServerError { + fn from(err: BackendError) -> Self { + ServerError::Backend(BbBackendError::from(err)) + } +} diff --git a/pkg/barretenberg-api-server/Cargo.toml b/pkg/barretenberg-api-server/Cargo.toml new file mode 100644 index 0000000..703c4dd --- /dev/null +++ b/pkg/barretenberg-api-server/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "barretenberg-api-server" +version = "0.1.0" +edition = "2024" + +[dependencies] +axum = { workspace = true, features = ["macros"] } +barretenberg-api-interface = { workspace = true } +barretenberg-interface = { workspace = true } +contextful = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/barretenberg-api-server/src/error.rs b/pkg/barretenberg-api-server/src/error.rs new file mode 100644 index 0000000..2e0d96f --- /dev/null +++ b/pkg/barretenberg-api-server/src/error.rs @@ -0,0 +1,93 @@ +use std::num::ParseIntError; + +use axum::{ + Json, + extract::rejection::JsonRejection, + http::header::ToStrError, + response::{IntoResponse, Response}, +}; +use barretenberg_api_interface::ServerError; +use barretenberg_interface::Error as BackendError; +use contextful::Contextful; +use thiserror::Error; +use tokio::task::JoinError; +use tracing::{debug, error, warn}; + +use crate::server::PermitAcquireError; + +#[derive(Debug, Error)] +pub(crate) enum HandlerError { + #[error("[barretenberg-api-server] permit acquisition error")] + // Skipping Contextful because no extra context is needed. + Permit(#[from] PermitAcquireError), + #[error("[barretenberg-api-server] backend error")] + Backend(#[from] Contextful), + #[error("[barretenberg-api-server] backend task failed")] + TaskJoin(#[from] Contextful), + #[error("[barretenberg-api-server] invalid json body")] + InvalidJsonBody(#[from] Contextful), + #[error("[barretenberg-api-server] invalid permit timeout header")] + InvalidPermitTimeoutHeader(#[from] Contextful), + #[error("[barretenberg-api-server] invalid permit timeout value")] + InvalidPermitTimeoutValue(#[from] Contextful), +} + +impl From<&HandlerError> for ServerError { + fn from(err: &HandlerError) -> Self { + match err { + HandlerError::Permit(err) => match err { + PermitAcquireError::Closed => ServerError::ServiceUnavailable { + message: "server busy".to_owned(), + }, + PermitAcquireError::Timeout => ServerError::ServiceUnavailable { + message: "timed out waiting for permit".to_owned(), + }, + }, + HandlerError::Backend(err) => ServerError::Backend(err.source_ref().into()), + HandlerError::TaskJoin(_) => ServerError::Internal { + message: "backend task failed".to_owned(), + }, + HandlerError::InvalidJsonBody(_) => ServerError::InvalidRequest { + message: "invalid json body".to_owned(), + }, + HandlerError::InvalidPermitTimeoutHeader(_) => ServerError::InvalidRequest { + message: "invalid permit timeout header".to_owned(), + }, + HandlerError::InvalidPermitTimeoutValue(_) => ServerError::InvalidRequest { + message: "invalid permit timeout value".to_owned(), + }, + } + } +} + +impl IntoResponse for HandlerError { + fn into_response(self) -> Response { + let server_error = ServerError::from(&self); + let status = server_error.status_code(); + + if matches!(&self, HandlerError::Permit(PermitAcquireError::Timeout)) { + debug!( + target: "barretenberg_api_server", + error = ?self, + status = status.as_u16(), + "permit timeout" + ); + } else if status.is_server_error() { + error!( + target: "barretenberg_api_server", + error = ?self, + status = status.as_u16(), + "request failed" + ); + } else { + warn!( + target: "barretenberg_api_server", + error = ?self, + status = status.as_u16(), + "request failed" + ); + } + + (status, Json(server_error)).into_response() + } +} diff --git a/pkg/barretenberg-api-server/src/extractors.rs b/pkg/barretenberg-api-server/src/extractors.rs new file mode 100644 index 0000000..71f15f9 --- /dev/null +++ b/pkg/barretenberg-api-server/src/extractors.rs @@ -0,0 +1,60 @@ +use std::time::Duration; + +use axum::{ + Json, async_trait, + body::Body, + extract::{FromRequest, FromRequestParts}, + http::{Request, header::HeaderMap, request::Parts}, +}; +use barretenberg_api_interface::PERMIT_TIMEOUT_HEADER; +use contextful::ResultContextExt; +use tokio::sync::OwnedSemaphorePermit; + +use crate::{error::HandlerError, server::AppState}; + +pub(crate) struct Permit(pub OwnedSemaphorePermit); + +#[async_trait] +impl FromRequestParts for Permit { + type Rejection = HandlerError; + + async fn from_request_parts( + parts: &mut Parts, + state: &AppState, + ) -> Result { + let timeout = permit_timeout_from_headers(&parts.headers)?; + let permit = state.acquire_processing_permit(timeout).await?; + Ok(Permit(permit)) + } +} + +pub(crate) struct CustomJson(pub T); + +#[async_trait] +impl FromRequest for CustomJson +where + Json: FromRequest, + S: Send + Sync, +{ + type Rejection = HandlerError; + + async fn from_request(req: Request, state: &S) -> Result { + let Json(value) = Json::::from_request(req, state) + .await + .context("deserialize request json")?; + Ok(CustomJson(value)) + } +} + +fn permit_timeout_from_headers(headers: &HeaderMap) -> Result, HandlerError> { + match headers.get(PERMIT_TIMEOUT_HEADER) { + Some(value) => { + let str_value = value.to_str().context("read permit timeout header")?; + let parsed = str_value + .parse::() + .context("parse permit timeout header")?; + Ok(Some(Duration::from_millis(parsed))) + } + None => Ok(None), + } +} diff --git a/pkg/barretenberg-api-server/src/handlers.rs b/pkg/barretenberg-api-server/src/handlers.rs new file mode 100644 index 0000000..1a30f6e --- /dev/null +++ b/pkg/barretenberg-api-server/src/handlers.rs @@ -0,0 +1,94 @@ +use std::time::Instant; + +use axum::{Json, extract::State}; +use barretenberg_api_interface::{ProveRequest, ProveResponse, VerifyRequest, VerifyResponse}; +use contextful::ResultContextExt; +use tracing::info; + +use crate::{ + error::HandlerError, + extractors::{CustomJson, Permit}, + server::AppState, +}; + +pub(crate) async fn prove( + State(state): State, + Permit(_permit): Permit, + CustomJson(request): CustomJson, +) -> Result, HandlerError> { + let ProveRequest { + program, + bytecode, + key, + witness, + oracle, + } = request; + + let started_at = Instant::now(); + info!( + target: "barretenberg_api_server", + program_bytes = program.len(), + bytecode_bytes = bytecode.len(), + key_bytes = key.len(), + witness_bytes = witness.len(), + oracle, + "prove request accepted" + ); + + let backend = state.backend(); + + let proof = backend + .prove(&program, &bytecode, &key, &witness, oracle) + .await + .context("backend prove request")?; + + let response = ProveResponse { + proof: proof.into(), + }; + info!( + target: "barretenberg_api_server", + proof_bytes = response.proof.len(), + elapsed_ms = started_at.elapsed().as_millis() as u64, + "generated proof successfully" + ); + + Ok(Json(response)) +} + +pub(crate) async fn verify( + State(state): State, + CustomJson(request): CustomJson, +) -> Result, HandlerError> { + let VerifyRequest { + proof, + public_inputs, + key, + oracle, + } = request; + + let started_at = Instant::now(); + info!( + target: "barretenberg_api_server", + proof_bytes = proof.len(), + public_inputs_bytes = public_inputs.len(), + key_bytes = key.len(), + oracle, + "verify request accepted" + ); + + let backend = state.backend(); + + backend + .verify(&proof, &public_inputs, &key, oracle) + .await + .context("backend verify request")?; + + let response = VerifyResponse { valid: true }; + info!( + target: "barretenberg_api_server", + elapsed_ms = started_at.elapsed().as_millis() as u64, + "verified proof successfully" + ); + + Ok(Json(response)) +} diff --git a/pkg/barretenberg-api-server/src/lib.rs b/pkg/barretenberg-api-server/src/lib.rs new file mode 100644 index 0000000..a377469 --- /dev/null +++ b/pkg/barretenberg-api-server/src/lib.rs @@ -0,0 +1,7 @@ +mod error; +mod extractors; +mod handlers; +pub mod server; + +pub use barretenberg_api_interface::{ProveRequest, ProveResponse, VerifyRequest, VerifyResponse}; +pub use server::build_app; diff --git a/pkg/barretenberg-api-server/src/server.rs b/pkg/barretenberg-api-server/src/server.rs new file mode 100644 index 0000000..350b9b1 --- /dev/null +++ b/pkg/barretenberg-api-server/src/server.rs @@ -0,0 +1,89 @@ +use std::{sync::Arc, time::Duration}; + +use axum::{ + Json, Router, + extract::DefaultBodyLimit, + http::StatusCode, + response::IntoResponse, + routing::{get, post}, +}; +use barretenberg_api_interface::ServerError; +use barretenberg_interface::BbBackend; +use thiserror::Error; +use tokio::{ + sync::{OwnedSemaphorePermit, Semaphore}, + time, +}; + +use crate::handlers; + +#[derive(Clone)] +pub(crate) struct AppState { + backend: Arc, + processing_limit: Arc, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)] +pub(crate) enum PermitAcquireError { + #[error("[barretenberg-api-server] permit semaphore closed")] + Closed, + #[error("[barretenberg-api-server] permit acquire timed out")] + Timeout, +} + +impl AppState { + pub(crate) fn new(backend: Arc) -> Self { + Self { + backend, + processing_limit: Arc::new(Semaphore::new(1)), + } + } + + pub(crate) fn backend(&self) -> Arc { + Arc::clone(&self.backend) + } + + pub(crate) async fn acquire_processing_permit( + &self, + timeout: Option, + ) -> Result { + match timeout { + Some(duration) => { + time::timeout(duration, self.processing_limit.clone().acquire_owned()) + .await + .map_err(|_| PermitAcquireError::Timeout)? + .map_err(|_| PermitAcquireError::Closed) + } + None => self + .processing_limit + .clone() + .acquire_owned() + .await + .map_err(|_| PermitAcquireError::Closed), + } + } +} + +pub fn build_app(backend: Arc) -> Router { + // agg_final is 28MB. For future-proofing, allowing up to 64MB. + let limit_layer = DefaultBodyLimit::max(64 * 1024 * 1024); + + Router::new() + .route("/prove", post(handlers::prove)) + .route("/verify", post(handlers::verify)) + .route("/health", get(healthcheck)) + .layer(limit_layer) + .with_state(AppState::new(backend)) + .fallback(api_fallback) +} + +async fn healthcheck() -> impl IntoResponse { + (StatusCode::OK, Json(serde_json::json!({ "status": "ok" }))) +} + +async fn api_fallback() -> impl IntoResponse { + let err = ServerError::InvalidRequest { + message: "not found".to_owned(), + }; + (err.status_code(), Json(err)) +} diff --git a/pkg/barretenberg-api-tests/Cargo.toml b/pkg/barretenberg-api-tests/Cargo.toml new file mode 100644 index 0000000..320c1f8 --- /dev/null +++ b/pkg/barretenberg-api-tests/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "barretenberg-api-tests" +version = "0.1.0" +edition = "2024" + +[dev-dependencies] +async-trait = { workspace = true } +axum = { workspace = true } +barretenberg-api-client = { workspace = true } +barretenberg-api-interface = { workspace = true } +barretenberg-api-server = { workspace = true } +barretenberg-interface = { workspace = true } +contextful = { workspace = true } +http-body-util = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } +tower = { workspace = true, features = ["util"] } +unimock = { workspace = true } +url = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/barretenberg-api-tests/src/lib.rs b/pkg/barretenberg-api-tests/src/lib.rs new file mode 100644 index 0000000..3b311d2 --- /dev/null +++ b/pkg/barretenberg-api-tests/src/lib.rs @@ -0,0 +1,4 @@ +#![deny(unsafe_code)] + +#[cfg(test)] +mod tests; diff --git a/pkg/barretenberg-api-tests/src/tests.rs b/pkg/barretenberg-api-tests/src/tests.rs new file mode 100644 index 0000000..84ef095 --- /dev/null +++ b/pkg/barretenberg-api-tests/src/tests.rs @@ -0,0 +1,532 @@ +// lint-long-file-override allow-max-lines=600 + +use std::{ + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, + time::Duration, +}; + +use axum::{ + Json, Router, + body::Body, + extract::State, + http::{Request, StatusCode}, + response::IntoResponse, + routing::post, +}; +use barretenberg_api_client::{ + ApiTransport, ClientBackend, ProveRequest, ProveResponse, VerifyRequest, VerifyResponse, +}; +use barretenberg_api_interface::{PERMIT_TIMEOUT_HEADER, ServerError}; +use barretenberg_api_server::server::build_app; +use barretenberg_interface::{BbBackend, BbBackendMock, Error, Result}; +use contextful::prelude::*; +use http_body_util::BodyExt; +use serde::{Serialize, de::DeserializeOwned}; +use serde_json::json; +use tokio::net::TcpListener; +use tower::ServiceExt; +use unimock::{MockFn, Unimock, matching}; +use url::Url; + +use barretenberg_api_client::error::{ClientError, TransportError}; + +const PROGRAM: &[u8] = b"test-program"; +const BYTECODE: &[u8] = b"bytecode"; +const KEY: &[u8] = b"key"; +const WITNESS: &[u8] = b"witness"; +const PROOF: &[u8] = b"proof"; +const PUBLIC_INPUTS: &[u8] = b"public-inputs"; + +#[tokio::test(flavor = "multi_thread")] +async fn client_prove_roundtrip() { + let backend: Arc = Arc::new(Unimock::new( + BbBackendMock::prove + .next_call(matching!(( + program, + bytecode, + key, + witness, + oracle + ) if *program == PROGRAM + && *bytecode == BYTECODE + && *key == KEY + && *witness == WITNESS + && *oracle)) + .returns(Ok(vec![3u8, 5, 7])), + )); + let client = client_with_backend(Arc::clone(&backend)); + + let proof = client + .prove(PROGRAM, BYTECODE, KEY, WITNESS, true) + .await + .expect("proof returned"); + assert_eq!(proof, vec![3u8, 5, 7]); +} + +#[tokio::test(flavor = "multi_thread")] +async fn client_verify_roundtrip() { + let backend: Arc = Arc::new(Unimock::new( + BbBackendMock::verify + .next_call(matching!(( + proof, + public_inputs, + key, + oracle + ) if *proof == PROOF + && *public_inputs == PUBLIC_INPUTS + && *key == KEY + && !*oracle)) + .returns(Ok(())), + )); + let client = client_with_backend(Arc::clone(&backend)); + + client + .verify(PROOF, PUBLIC_INPUTS, KEY, false) + .await + .expect("verification succeeded"); +} + +#[tokio::test(flavor = "multi_thread")] +async fn http_client_surfaces_backend_errors() { + let test_cases = vec![ + ( + Error::VerificationFailed, + Box::new(|err: &Error| matches!(err, Error::VerificationFailed)) + as Box bool>, + "VerificationFailed", + ), + ( + Error::Backend("backend failure message".to_owned()), + Box::new(|err: &Error| { + if let Error::Backend(msg) = err { + msg == "backend failure message" + } else { + false + } + }), + "Backend", + ), + ( + Error::Backend("symbols: !@#$%^&*()_+-=[]{}|;':\",./<>?".to_owned()), + Box::new(|err: &Error| { + if let Error::Backend(msg) = err { + msg == "symbols: !@#$%^&*()_+-=[]{}|;':\",./<>?" + } else { + false + } + }), + "BackendWithSymbols", + ), + ( + Error::Backend("".to_owned()), + Box::new(|err: &Error| { + if let Error::Backend(msg) = err { + msg.is_empty() + } else { + false + } + }), + "BackendEmptyMessage", + ), + ( + Error::ImplementationSpecific(Box::new(std::io::Error::other("internal crash"))), + Box::new(|err: &Error| matches!(err, Error::ImplementationSpecific(_))), + "ImplementationSpecific", + ), + ]; + + for (input_err, check, label) in test_cases { + let backend: Arc = Arc::new(Unimock::new( + BbBackendMock::verify + .next_call(matching!((_, _, _, _))) + .returns(Err(input_err)), + )); + let app = build_app(backend); + + let listener = TcpListener::bind("127.0.0.1:0") + .await + .expect("bind listener"); + let addr = listener.local_addr().expect("listener address"); + let server = tokio::spawn(async move { + let _ = axum::serve(listener, app.into_make_service()).await; + }); + + let client = ClientBackend::with_retry_policy( + Url::parse(&format!("http://{}/", addr)).expect("base url"), + Duration::from_secs(1), + Duration::from_secs(1), + None, + Duration::from_millis(1), + Duration::ZERO, + Duration::from_millis(500), + ) + .expect("client backend"); + + let err = client + .verify(PROOF, PUBLIC_INPUTS, KEY, true) + .await + .expect_err(&format!("verification should fail for case {}", label)); + + assert!( + check(&err), + "error surfacing failed for {}: expected matching variant, got {:?}", + label, + err + ); + + server.abort(); + } +} + +#[tokio::test(flavor = "multi_thread")] +async fn http_client_surfaces_prove_errors() { + let backend: Arc = Arc::new(Unimock::new( + BbBackendMock::prove + .next_call(matching!((_, _, _, _, _))) + .returns(Err(Error::Backend("prove failed".to_owned()))), + )); + let app = build_app(backend); + + let listener = TcpListener::bind("127.0.0.1:0") + .await + .expect("bind listener"); + let addr = listener.local_addr().expect("listener address"); + let server = tokio::spawn(async move { + let _ = axum::serve(listener, app.into_make_service()).await; + }); + + let client = ClientBackend::with_retry_policy( + Url::parse(&format!("http://{}/", addr)).expect("base url"), + Duration::from_secs(1), + Duration::from_secs(1), + None, + Duration::from_millis(1), + Duration::ZERO, + Duration::from_millis(500), + ) + .expect("client backend"); + + let err = client + .prove(PROGRAM, BYTECODE, KEY, WITNESS, true) + .await + .expect_err("prove should fail"); + + if let Error::Backend(msg) = err { + assert_eq!(msg, "prove failed"); + } else { + panic!("expected Error::Backend, got {:?}", err); + } + + server.abort(); +} + +#[tokio::test(flavor = "multi_thread")] +async fn healthcheck_returns_ok() { + let router = build_app(Arc::new(Unimock::new(()))); + + let response = router + .clone() + .oneshot( + Request::builder() + .method("GET") + .uri("/health") + .body(Body::empty()) + .expect("failed to build request"), + ) + .await + .expect("request failed"); + + assert_eq!(response.status(), StatusCode::OK); + + let body_bytes = response + .into_body() + .collect() + .await + .expect("collect body") + .to_bytes(); + let payload: serde_json::Value = + serde_json::from_slice(&body_bytes).expect("valid health payload"); + assert_eq!(payload, json!({ "status": "ok" })); +} + +#[tokio::test(flavor = "multi_thread")] +async fn prove_request_times_out_when_permit_wait_expires() { + let backend: Arc = Arc::new(SlowBackend::new( + Duration::from_millis(500), + Duration::from_millis(0), + )); + let app = build_app(backend); + let blocking_client = ClientBackend::with_transport(AxumTransport::new(app.clone())); + let timeout_client = ClientBackend::with_transport( + AxumTransport::new(app).with_permit_timeout(Some(Duration::from_millis(25))), + ); + + let first = tokio::spawn({ + let client = blocking_client.clone(); + async move { client.prove(PROGRAM, BYTECODE, KEY, WITNESS, false).await } + }); + + tokio::time::sleep(Duration::from_millis(50)).await; + + let err = timeout_client + .prove(PROGRAM, BYTECODE, KEY, WITNESS, false) + .await + .expect_err("request should time out while waiting for permit"); + + assert!(matches!(err, Error::ImplementationSpecific(_))); + + first + .await + .expect("first request join") + .expect("first request should succeed"); +} + +#[tokio::test(flavor = "multi_thread")] +async fn verify_does_not_require_permit() { + let backend: Arc = Arc::new(SlowBackend::new( + Duration::from_millis(500), + Duration::from_millis(0), + )); + let app = build_app(backend); + let client = ClientBackend::with_transport(AxumTransport::new(app)); + + let prove_task = tokio::spawn({ + let client = client.clone(); + async move { client.prove(PROGRAM, BYTECODE, KEY, WITNESS, false).await } + }); + + tokio::time::sleep(Duration::from_millis(100)).await; + + let start = std::time::Instant::now(); + client + .verify(PROOF, PUBLIC_INPUTS, KEY, false) + .await + .expect("verify should succeed"); + + assert!( + start.elapsed() < Duration::from_millis(200), + "verify should not wait for permit, took {:?}", + start.elapsed() + ); + + prove_task + .await + .expect("prove task join") + .expect("prove should succeed"); +} + +#[derive(Clone)] +struct RetryState { + attempts: Arc, +} + +async fn retry_prove_handler( + State(state): State, + Json(_request): Json, +) -> impl IntoResponse { + let attempt = state.attempts.fetch_add(1, Ordering::SeqCst); + if attempt == 0 { + let err = ServerError::ServiceUnavailable { + message: "permit timeout".to_owned(), + }; + (err.status_code(), Json(err)).into_response() + } else { + Json(ProveResponse { + proof: vec![9u8, 8, 7].into(), + }) + .into_response() + } +} + +#[tokio::test(flavor = "multi_thread")] +async fn http_client_retries_on_permit_timeout() { + let state = RetryState { + attempts: Arc::new(AtomicUsize::new(0)), + }; + let router = Router::new() + .route("/prove", post(retry_prove_handler)) + .with_state(state.clone()); + + let listener = TcpListener::bind("127.0.0.1:0") + .await + .expect("bind listener"); + let addr = listener.local_addr().expect("listener address"); + let server = tokio::spawn(async move { + let _ = axum::serve(listener, router.into_make_service()).await; + }); + + let client = ClientBackend::new(Url::parse(&format!("http://{}/", addr)).expect("base url")) + .expect("client backend"); + + let proof = client + .prove(PROGRAM, BYTECODE, KEY, WITNESS, false) + .await + .expect("client succeed"); + + assert_eq!(proof, vec![9u8, 8, 7]); + assert!(state.attempts.load(Ordering::SeqCst) >= 2); + + server.abort(); +} + +fn client_with_backend(backend: Arc) -> ClientBackend { + ClientBackend::with_transport(AxumTransport::new(build_app(backend))) +} + +struct SlowBackend { + prove_delay: Duration, + verify_delay: Duration, +} + +impl SlowBackend { + fn new(prove_delay: Duration, verify_delay: Duration) -> Self { + Self { + prove_delay, + verify_delay, + } + } +} + +#[async_trait::async_trait] +impl BbBackend for SlowBackend { + async fn prove( + &self, + _program: &[u8], + _bytecode: &[u8], + _key: &[u8], + _witness: &[u8], + _oracle: bool, + ) -> Result> { + tokio::time::sleep(self.prove_delay).await; + Ok(vec![1, 2, 3]) + } + + async fn verify( + &self, + _proof: &[u8], + _public_inputs: &[u8], + _key: &[u8], + _oracle: bool, + ) -> Result<()> { + tokio::time::sleep(self.verify_delay).await; + Ok(()) + } +} + +#[derive(Clone)] +struct AxumTransport { + app: Router, + permit_timeout: Option, +} + +impl AxumTransport { + fn new(app: Router) -> Self { + Self { + app, + permit_timeout: None, + } + } + + fn with_permit_timeout(mut self, permit_timeout: Option) -> Self { + self.permit_timeout = permit_timeout; + self + } + + async fn call( + &self, + path: &str, + payload: Req, + ) -> std::result::Result + where + Req: Serialize + Send + 'static, + Resp: DeserializeOwned + Send + 'static, + { + let uri = path.to_owned(); + let body = serde_json::to_vec(&payload).map_err(|e| { + ClientError::Transport(TransportError::Json(contextful::Contextful::new( + "serialize body", + e, + ))) + })?; + + let mut builder = Request::builder() + .method("POST") + .uri(&uri) + .header("content-type", "application/json") + .header("Expect", "100-continue"); + + if let Some(timeout) = self.permit_timeout { + builder = builder.header(PERMIT_TIMEOUT_HEADER, duration_to_ms(timeout).to_string()); + } + + let req = builder.body(Body::from(body)).map_err(|e| { + ClientError::Transport(TransportError::Io( + std::io::Error::other(e.to_string()).wrap_err("build request"), + )) + })?; + + let response = self + .app + .clone() + .oneshot(req) + .await + .map_err(|e| std::io::Error::other(e.to_string()).wrap_err("oneshot request")) + .map_err(TransportError::Io) + .map_err(ClientError::Transport)?; + + let status = response.status(); + let body_bytes = response + .into_body() + .collect() + .await + .map_err(|e| { + ClientError::Transport(TransportError::Io( + std::io::Error::other(e.to_string()).wrap_err("collect body"), + )) + })? + .to_bytes(); + + if !status.is_success() { + let body_text = String::from_utf8_lossy(&body_bytes).into_owned(); + return Err(map_http_error(status, body_text)); + } + + let result: Resp = serde_json::from_slice(&body_bytes) + .context("deserialize body") + .map_err(TransportError::Json) + .map_err(ClientError::Transport)?; + Ok(result) + } +} + +#[async_trait::async_trait] +impl ApiTransport for AxumTransport { + async fn prove( + &self, + request: ProveRequest, + ) -> std::result::Result { + self.call("/prove", request).await + } + + async fn verify( + &self, + request: VerifyRequest, + ) -> std::result::Result { + self.call("/verify", request).await + } +} + +fn map_http_error(status: StatusCode, body: String) -> ClientError { + let server_error: ServerError = + serde_json::from_str(&body).unwrap_or_else(|_| ServerError::Internal { + message: format!("unexpected response ({status}): {body}"), + }); + ClientError::Server(server_error) +} + +fn duration_to_ms(duration: Duration) -> u64 { + duration.as_millis().min(u128::from(u64::MAX)) as u64 +} diff --git a/pkg/barretenberg-cli/Cargo.toml b/pkg/barretenberg-cli/Cargo.toml new file mode 100644 index 0000000..57cbdd9 --- /dev/null +++ b/pkg/barretenberg-cli/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "barretenberg-cli" +version = "0.1.0" +edition = "2024" + +[dependencies] +barretenberg-interface = { workspace = true } +flate2 = { workspace = true } +tempfile = { workspace = true } +tracing = { workspace = true } +async-trait = { workspace = true } +tokio = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/barretenberg-cli/src/lib.rs b/pkg/barretenberg-cli/src/lib.rs new file mode 100644 index 0000000..b382383 --- /dev/null +++ b/pkg/barretenberg-cli/src/lib.rs @@ -0,0 +1,171 @@ +use std::{ + io::{Read, Write}, + path::PathBuf, +}; + +use async_trait::async_trait; +use barretenberg_interface::{BbBackend, Error, Result}; +use flate2::{Compression, read::GzEncoder}; +use tempfile::{NamedTempFile, TempDir}; +use tokio::process::Command; +use tracing::{error, info}; + +pub struct CliBackend; + +#[async_trait] +impl BbBackend for CliBackend { + async fn prove( + &self, + program: &[u8], + _bytecode: &[u8], + key: &[u8], + witness: &[u8], + oracle_hash_keccak: bool, + ) -> Result> { + let mut witness_gz = GzEncoder::new(witness, Compression::none()); + let mut witness_gz_buf = Vec::with_capacity(witness.len() + 0xFF); + witness_gz + .read_to_end(&mut witness_gz_buf) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + let witness_gz = witness_gz_buf; + + let mut program_file = NamedTempFile::with_suffix(".json") + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + program_file + .write_all(program) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + program_file + .flush() + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let mut witness_file = + NamedTempFile::new().map_err(|e| Error::ImplementationSpecific(e.into()))?; + witness_file + .write_all(&witness_gz) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + witness_file + .flush() + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let mut key_file = + NamedTempFile::new().map_err(|e| Error::ImplementationSpecific(e.into()))?; + key_file + .write_all(key) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + key_file + .flush() + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let output_dir = TempDir::new().map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let mut cmd = Command::new(PathBuf::from("bb")); + cmd.kill_on_drop(true); + cmd.arg("prove") + .arg("-v") + .arg("--scheme") + .arg("ultra_honk") + .arg("-b") + .arg(program_file.path()) + .arg("-w") + .arg(witness_file.path()) + .arg("-k") + .arg(key_file.path()) + .arg("-o") + .arg(output_dir.path()); + + if oracle_hash_keccak { + cmd.arg("--oracle_hash").arg("keccak"); + } + + let output = cmd + .output() + .await + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + if !output.status.success() { + let stderr = String::from_utf8(output.stderr) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + return Err(Error::Backend(stderr)); + } + + let proof_path = output_dir.path().join("proof"); + let mut proof = tokio::fs::read(&proof_path) + .await + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let public_inputs_path = output_dir.path().join("public_inputs"); + let public_inputs = tokio::fs::read(&public_inputs_path) + .await + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + proof.splice(0..0, public_inputs); + + Ok(proof) + } + + async fn verify( + &self, + proof: &[u8], + public_inputs: &[u8], + key: &[u8], + oracle_hash_keccak: bool, + ) -> Result<()> { + let mut key_file = + NamedTempFile::new().map_err(|e| Error::ImplementationSpecific(e.into()))?; + key_file + .write_all(key) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + key_file + .flush() + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let mut proof_file = + NamedTempFile::new().map_err(|e| Error::ImplementationSpecific(e.into()))?; + proof_file + .write_all(proof) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + proof_file + .flush() + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let mut public_inputs_file = + NamedTempFile::new().map_err(|e| Error::ImplementationSpecific(e.into()))?; + public_inputs_file + .write_all(public_inputs) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + public_inputs_file + .flush() + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + let mut cmd = Command::new(PathBuf::from("bb")); + cmd.kill_on_drop(true); + cmd.arg("verify") + .arg("-v") + .arg("--scheme") + .arg("ultra_honk") + .arg("-k") + .arg(key_file.path()) + .arg("-p") + .arg(proof_file.path()) + .arg("-i") + .arg(public_inputs_file.path()); + + if oracle_hash_keccak { + cmd.arg("--oracle_hash").arg("keccak"); + } + + let output = cmd + .output() + .await + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + info!("output {:?}", output); + + if !output.status.success() { + let stderr = String::from_utf8(output.stderr) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + error!("proof error: {}", stderr); + return Err(Error::Backend(stderr)); + } + + Ok(()) + } +} diff --git a/pkg/barretenberg-interface/Cargo.toml b/pkg/barretenberg-interface/Cargo.toml new file mode 100644 index 0000000..9567313 --- /dev/null +++ b/pkg/barretenberg-interface/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "barretenberg-interface" +version = "0.1.0" +edition = "2024" + +[dependencies] +thiserror = { workspace = true } +unimock = { workspace = true } +async-trait = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/barretenberg-interface/src/backend.rs b/pkg/barretenberg-interface/src/backend.rs new file mode 100644 index 0000000..26501eb --- /dev/null +++ b/pkg/barretenberg-interface/src/backend.rs @@ -0,0 +1,27 @@ +use crate::error::Result; + +#[unimock::unimock(api = BbBackendMock)] +#[async_trait::async_trait] +pub trait BbBackend: Send + Sync { + async fn prove( + &self, + program: &[u8], + bytecode: &[u8], + key: &[u8], + witness: &[u8], + oracle: bool, + ) -> Result>; + async fn verify( + &self, + proof: &[u8], + public_inputs: &[u8], + key: &[u8], + oracle: bool, + ) -> Result<()>; +} + +impl std::fmt::Debug for dyn BbBackend { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str("BbBackend") + } +} diff --git a/pkg/barretenberg-interface/src/error.rs b/pkg/barretenberg-interface/src/error.rs new file mode 100644 index 0000000..554f353 --- /dev/null +++ b/pkg/barretenberg-interface/src/error.rs @@ -0,0 +1,13 @@ +pub type Result = std::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("[barretenberg] backend error: {0}")] + Backend(String), + + #[error("[barretenberg] verification failed")] + VerificationFailed, + + #[error("[barretenberg] implementation specific error")] + ImplementationSpecific(#[source] Box), +} diff --git a/pkg/barretenberg-interface/src/lib.rs b/pkg/barretenberg-interface/src/lib.rs new file mode 100644 index 0000000..a78bdd0 --- /dev/null +++ b/pkg/barretenberg-interface/src/lib.rs @@ -0,0 +1,4 @@ +pub mod backend; +pub mod error; +pub use backend::{BbBackend, BbBackendMock}; +pub use error::{Error, Result}; diff --git a/pkg/barretenberg-rs/Cargo.toml b/pkg/barretenberg-rs/Cargo.toml new file mode 100644 index 0000000..484a1d0 --- /dev/null +++ b/pkg/barretenberg-rs/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "barretenberg-rs" +version = "0.1.0" +edition = "2024" + +[dependencies] +barretenberg-interface = { workspace = true } +bb_rs = { workspace = true, optional = true } +lazy_static = { workspace = true } +async-trait = { workspace = true } +contextful = { workspace = true } +tokio = { workspace = true } +workspace-hack.workspace = true + +[features] +default = [] +max_params = [] diff --git a/pkg/barretenberg-rs/src/binding.rs b/pkg/barretenberg-rs/src/binding.rs new file mode 100644 index 0000000..986e716 --- /dev/null +++ b/pkg/barretenberg-rs/src/binding.rs @@ -0,0 +1,141 @@ +use std::sync::{Mutex, Once, OnceLock}; + +#[cfg(feature = "max_params")] +use std::{env, fs, path::PathBuf}; + +use async_trait::async_trait; +use barretenberg_interface::{BbBackend, Error, Result}; +#[cfg(feature = "max_params")] +use contextful::ResultContextExt; +use lazy_static::lazy_static; + +pub struct BindingBackend; + +static INIT: Once = Once::new(); + +lazy_static! { + static ref BB_MUTEX: Mutex<()> = Mutex::new(()); +} + +#[cfg(feature = "max_params")] +static G1: OnceLock<&'static [u8]> = OnceLock::new(); + +#[cfg(feature = "max_params")] +fn params_dir() -> Result { + if let Ok(path) = env::var("POLYBASE_PARAMS_DIR") { + return Ok(PathBuf::from(path)); + } + + let home = env::var("HOME").map_err(|err| Error::ImplementationSpecific(err.into()))?; + + Ok(PathBuf::from(home).join(".polybase/fixtures/params")) +} + +#[cfg(feature = "max_params")] +fn load_max_params() -> Result<&'static [u8]> { + let path = params_dir()?.join("g1.max.dat"); + let bytes = fs::read(&path) + .context("missing g1.max.dat; run scripts/download-fixtures-params.sh") + .map_err(|err| Error::ImplementationSpecific(Box::new(err)))?; + + Ok(Box::leak(bytes.into_boxed_slice())) +} + +#[cfg(not(feature = "max_params"))] +static G1: &[u8] = include_bytes!("../../../fixtures/params/g1.utxo.dat"); + +#[cfg(feature = "max_params")] +fn g1_bytes() -> Result<&'static [u8]> { + if let Some(bytes) = G1.get() { + return Ok(*bytes); + } + + let bytes = load_max_params()?; + let _ = G1.set(bytes); + Ok(bytes) +} + +#[cfg(not(feature = "max_params"))] +fn g1_bytes() -> Result<&'static [u8]> { + Ok(G1) +} + +impl BindingBackend { + fn load_srs() -> Result<()> { + let g1 = g1_bytes()?; + INIT.call_once(|| unsafe { + bb_rs::barretenberg_api::srs::init_srs(g1, (g1.len() / 64) as u32); + }); + Ok(()) + } +} + +#[async_trait] +impl BbBackend for BindingBackend { + async fn prove( + &self, + _program: &[u8], + _bytecode: &[u8], + _key: &[u8], + _witness: &[u8], + _oracle_hash_keccak: bool, + ) -> Result> { + let bytecode = _bytecode.to_vec(); + let witness = _witness.to_vec(); + let key = _key.to_vec(); + + tokio::task::spawn_blocking(move || { + let _guard = BB_MUTEX.lock().unwrap(); + + Self::load_srs()?; + + let proof = match _oracle_hash_keccak { + false => unsafe { + bb_rs::barretenberg_api::acir::acir_prove_ultra_honk(&bytecode, &witness, &key) + }, + true => unsafe { + bb_rs::barretenberg_api::acir::acir_prove_ultra_keccak_zk_honk( + &bytecode, &witness, &key, + ) + }, + }; + + Ok(proof) + }) + .await + .map_err(|e| Error::ImplementationSpecific(e.into()))? + } + + async fn verify( + &self, + _proof: &[u8], + _public_inputs: &[u8], + _key: &[u8], + _oracle_hash_keccak: bool, + ) -> Result<()> { + let proof = [_public_inputs, _proof].concat(); + let key = _key.to_vec(); + + tokio::task::spawn_blocking(move || { + let _guard = BB_MUTEX.lock().unwrap(); + + Self::load_srs()?; + + let verified = match _oracle_hash_keccak { + false => unsafe { + bb_rs::barretenberg_api::acir::acir_verify_ultra_honk(&proof, &key) + }, + true => unsafe { + bb_rs::barretenberg_api::acir::acir_verify_ultra_keccak_zk_honk(&proof, &key) + }, + }; + + match verified { + true => Ok(()), + false => Err(Error::VerificationFailed), + } + }) + .await + .map_err(|e| Error::ImplementationSpecific(e.into()))? + } +} diff --git a/pkg/barretenberg-rs/src/lib.rs b/pkg/barretenberg-rs/src/lib.rs new file mode 100644 index 0000000..b31c5a4 --- /dev/null +++ b/pkg/barretenberg-rs/src/lib.rs @@ -0,0 +1,11 @@ +#[cfg(feature = "bb_rs")] +mod binding; + +#[cfg(not(feature = "bb_rs"))] +mod mock; + +#[cfg(feature = "bb_rs")] +pub use binding::BindingBackend; + +#[cfg(not(feature = "bb_rs"))] +pub use mock::BindingBackend; diff --git a/pkg/barretenberg-rs/src/mock.rs b/pkg/barretenberg-rs/src/mock.rs new file mode 100644 index 0000000..54bf1f0 --- /dev/null +++ b/pkg/barretenberg-rs/src/mock.rs @@ -0,0 +1,34 @@ +use async_trait::async_trait; +use barretenberg_interface::{BbBackend, Error, Result}; + +const DISABLED_MESSAGE: &str = "bb_rs feature not enabled; run the mobile rustbridge build script"; + +pub struct BindingBackend; + +fn bindings_disabled() -> Result { + Err(Error::Backend(DISABLED_MESSAGE.to_owned())) +} + +#[async_trait] +impl BbBackend for BindingBackend { + async fn prove( + &self, + _program: &[u8], + _bytecode: &[u8], + _key: &[u8], + _witness: &[u8], + _oracle_hash_keccak: bool, + ) -> Result> { + bindings_disabled() + } + + async fn verify( + &self, + _proof: &[u8], + _public_inputs: &[u8], + _key: &[u8], + _oracle_hash_keccak: bool, + ) -> Result<()> { + bindings_disabled() + } +} diff --git a/pkg/block-store/Cargo.toml b/pkg/block-store/Cargo.toml index d1b5fe1..867c98b 100644 --- a/pkg/block-store/Cargo.toml +++ b/pkg/block-store/Cargo.toml @@ -1,17 +1,21 @@ [package] name = "block-store" version = "1.3.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] wire-message = { workspace = true, features = ["test-api"] } +strum = { workspace = true } primitives = { workspace = true } +element = { workspace = true } +borsh = { workspace = true } rocksdb = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } +workspace-hack.workspace = true [dev-dependencies] tempdir = { workspace = true } diff --git a/pkg/block-store/README.md b/pkg/block-store/README.md new file mode 100644 index 0000000..9dca244 --- /dev/null +++ b/pkg/block-store/README.md @@ -0,0 +1,15 @@ +# Block Store + +Key-value storage layer for blockchain data with migration support. + +## Overview + +This package provides a persistent storage layer for blockchain data, supporting key-value operations and data migrations. + +## Features + +- Key-value storage operations +- Data migration support +- List operations for stored data +- Type-safe value serialization + diff --git a/pkg/block-store/src/element_history.rs b/pkg/block-store/src/element_history.rs new file mode 100644 index 0000000..0b51c24 --- /dev/null +++ b/pkg/block-store/src/element_history.rs @@ -0,0 +1,134 @@ +use std::{ + ops::{Bound, RangeBounds}, + sync::RwLock, +}; + +use borsh::BorshDeserialize; +use element::Element; +use primitives::block_height::BlockHeight; +use rocksdb::{DB, ReadOptions}; + +use crate::{ + Error, Result, + keys::{ElementHistoryKind, Key}, + values::ElementHistoryValue, +}; + +#[derive(Debug, Clone, Copy)] +pub struct ElementHistoryIndexEntry { + pub block_height: BlockHeight, + pub element: Element, + pub kind: ElementHistoryKind, +} + +impl ElementHistoryIndexEntry { + fn order_key(&self) -> (BlockHeight, u8) { + (self.block_height, self.kind.ordering_weight()) + } +} + +#[derive(Debug)] +pub struct ElementHistoryIndex { + entries: RwLock>, +} + +impl ElementHistoryIndex { + pub fn load(db: &DB) -> Result { + let mut entries = Vec::new(); + + let mut read_opts = ReadOptions::default(); + read_opts.set_iterate_lower_bound( + Key::ElementHistory((Element::from_be_bytes([0; 32]), ElementHistoryKind::Input)) + .serialize(), + ); + read_opts.set_iterate_upper_bound( + Key::ElementHistory(( + Element::from_be_bytes([255; 32]), + ElementHistoryKind::Output, + )) + .serialize_immediate_successor(), + ); + + for row in db.iterator_opt(rocksdb::IteratorMode::Start, read_opts) { + let (key_bytes, value_bytes) = row?; + let key = Key::deserialize(key_bytes.as_ref())?; + + let Key::ElementHistory((element, kind)) = key else { + return Err(Error::InvalidKey); + }; + + let value = ElementHistoryValue::deserialize(&mut &value_bytes.as_ref()[..])?; + let ElementHistoryValue::V1(data) = value; + + entries.push(ElementHistoryIndexEntry { + block_height: data.block_height, + element, + kind, + }); + } + + entries.sort_by_key(|entry| entry.order_key()); + + Ok(Self { + entries: RwLock::new(entries), + }) + } + + pub fn append(&self, mut new_entries: Vec) { + if new_entries.is_empty() { + return; + } + + new_entries.sort_by_key(|entry| entry.order_key()); + + let mut entries = self.entries.write().unwrap(); + + if let Some(last) = entries.last().copied() + && last.order_key() > new_entries[0].order_key() + { + entries.extend(new_entries); + entries.sort_by_key(|entry| entry.order_key()); + return; + } + + entries.extend(new_entries); + } + + pub fn range(&self, range: impl RangeBounds) -> Vec { + let entries = self.entries.read().unwrap(); + if entries.is_empty() { + return Vec::new(); + } + + let len = entries.len(); + + let mut start_idx = match range.start_bound() { + Bound::Unbounded => 0, + Bound::Included(height) => { + entries.partition_point(|entry| entry.block_height < *height) + } + Bound::Excluded(height) => { + entries.partition_point(|entry| entry.block_height <= *height) + } + }; + + let mut end_idx = match range.end_bound() { + Bound::Unbounded => len, + Bound::Included(height) => { + entries.partition_point(|entry| entry.block_height <= *height) + } + Bound::Excluded(height) => { + entries.partition_point(|entry| entry.block_height < *height) + } + }; + + start_idx = start_idx.min(len); + end_idx = end_idx.min(len); + + if start_idx >= end_idx { + return Vec::new(); + } + + entries[start_idx..end_idx].to_vec() + } +} diff --git a/pkg/block-store/src/keys.rs b/pkg/block-store/src/keys.rs index 43f8802..092ea4c 100644 --- a/pkg/block-store/src/keys.rs +++ b/pkg/block-store/src/keys.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=400 use std::{ marker::PhantomData, ops::{Bound, RangeBounds}, @@ -8,20 +9,15 @@ use primitives::{block_height::BlockHeight, pagination::CursorChoice}; use rocksdb::DB; use wire_message::WireMessage; -use crate::{list::List, Block, Error, Result}; +use crate::{Block, Error, Result, list::List}; pub(crate) trait StoreKey: Clone { fn to_key(&self) -> Key; - fn from_key(key: Key) -> Option - where - Self: Sized; - fn serialize_to(&self, to: &mut Vec); fn deserialize(bytes: &[u8]) -> Result; } pub(crate) trait StoreValue { - fn serialize(&self) -> Result>; fn deserialize(bytes: &[u8]) -> Result where Self: Sized; @@ -31,10 +27,6 @@ impl StoreValue for T where T: WireMessage, { - fn serialize(&self) -> Result> { - Ok(self.to_bytes()?) - } - fn deserialize(bytes: &[u8]) -> Result { Ok(Self::from_bytes(bytes)?) } @@ -113,12 +105,6 @@ where let (reverse_results, order) = match cursor { None | Some(CursorChoice::After(_)) => (false, order), - // Without this, if entities 1, 2, 3 exist and indexed order is LowToHigh, - // Before(3) would return entity 1, instead of entity 2. - // The list call would look like this: `self.list(..3, LowToHigh)`, - // so we need to reverse the order, for the first .next() to return 2 instead of 1. - // TODO: will this also work with keys whose indexed order is HighToLow? - // We don't have any right now. Some(CursorChoice::Before(_)) => (true, order.reverse()), }; @@ -127,9 +113,6 @@ where .take(limit) .collect::>>()?; - // If the cursor is Before, we need to reverse the results, otherwise in the example above - // the first .next() would return 2, and the next 1, which does not match - // the expected LowToHigh order. if reverse_results { results.reverse(); } @@ -147,6 +130,42 @@ pub enum Key { TxnByHash([u8; 32]), StoreVersion, NonEmptyBlock(KeyNonEmptyBlock), + LockedElement([u8; 32]), + ElementHistory((element::Element, ElementHistoryKind)), + MintHash(element::Element), +} + +// TODO: this might be confusing, +// when a note is created, it will appear as "Output" history. +// Maybe rename? +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ElementHistoryKind { + Input, + Output, +} + +impl ElementHistoryKind { + fn to_byte(self) -> u8 { + match self { + ElementHistoryKind::Input => 0, + ElementHistoryKind::Output => 1, + } + } + + fn from_byte(byte: u8) -> Option { + match byte { + 0 => Some(ElementHistoryKind::Input), + 1 => Some(ElementHistoryKind::Output), + _ => None, + } + } + + pub(crate) fn ordering_weight(&self) -> u8 { + match self { + ElementHistoryKind::Output => 0, + ElementHistoryKind::Input => 1, + } + } } impl Key { @@ -159,6 +178,9 @@ impl Key { Self::TxnByHash(_) => 4, Self::StoreVersion => 5, Self::NonEmptyBlock(_) => 6, + Self::LockedElement(_) => 7, + Self::ElementHistory(_) => 8, + Self::MintHash(_) => 9, } } @@ -181,6 +203,16 @@ impl Key { Self::NonEmptyBlock(block_number) => { block_number.serialize_to(&mut out); } + Self::LockedElement(locked_element) => { + out.extend_from_slice(locked_element); + } + Self::ElementHistory((element, kind)) => { + out.extend_from_slice(&element.to_be_bytes()); + out.extend_from_slice(&[kind.to_byte()]); + } + Self::MintHash(mint_hash) => { + out.extend_from_slice(&mint_hash.to_be_bytes()); + } } out @@ -207,6 +239,24 @@ impl Key { } 5 => Ok(Self::StoreVersion), 6 => KeyNonEmptyBlock::deserialize(bytes).map(Self::NonEmptyBlock), + 7 => { + let mut locked_element = [0u8; 32]; + locked_element.copy_from_slice(&bytes[0..32]); + Ok(Self::LockedElement(locked_element)) + } + 8 => { + let element_arr: &[u8; 32] = + bytes[0..32].try_into().map_err(|_| Error::InvalidKey)?; + let element = element::Element::from_be_bytes(*element_arr); + let kind = ElementHistoryKind::from_byte(bytes[32]).unwrap(); + Ok(Self::ElementHistory((element, kind))) + } + 9 => { + let mint_hash_arr: &[u8; 32] = + bytes[0..32].try_into().map_err(|_| Error::InvalidKey)?; + let mint_hash = element::Element::from_be_bytes(*mint_hash_arr); + Ok(Self::MintHash(mint_hash)) + } _ => Err(Error::InvalidKey), } } @@ -226,13 +276,6 @@ impl StoreKey for KeyBlock { Key::Block(self.clone()) } - fn from_key(key: Key) -> Option { - match key { - Key::Block(kb) => Some(kb), - _ => None, - } - } - fn serialize_to(&self, to: &mut Vec) { to.extend_from_slice(&self.0.to_be_bytes()); } @@ -299,13 +342,6 @@ impl StoreKey for KeyNonEmptyBlock { Key::NonEmptyBlock(KeyNonEmptyBlock(self.0)) } - fn from_key(key: Key) -> Option { - match key { - Key::NonEmptyBlock(key) => Some(key), - _ => None, - } - } - fn serialize_to(&self, to: &mut Vec) { to.extend_from_slice(&self.0.to_be_bytes()); } diff --git a/pkg/block-store/src/lib.rs b/pkg/block-store/src/lib.rs index ac76e1a..c6bc7db 100644 --- a/pkg/block-store/src/lib.rs +++ b/pkg/block-store/src/lib.rs @@ -1,22 +1,29 @@ // These features have been stabilized in recent Rust versions #![allow(incomplete_features)] -#![feature(return_position_impl_trait_in_trait)] -#![feature(associated_type_defaults)] -#![feature(bound_map)] +// #![feature(return_position_impl_trait_in_trait)] +// #![feature(associated_type_defaults)] +// #![feature(bound_map)] +// lint-long-file-override allow-max-lines=700 +mod element_history; mod keys; mod list; mod migration; +mod values; -use std::{marker::PhantomData, path::Path}; +use std::{marker::PhantomData, ops::RangeBounds, path::Path}; +use borsh::{BorshDeserialize, BorshSerialize}; +use element_history::ElementHistoryIndex; use keys::{Key, KeyBlock, StoreKey}; use migration::LATEST_VERSION; -use primitives::block_height::BlockHeight; +use primitives::{block_height::BlockHeight, hash::CryptoHash}; use rocksdb::DB; +use values::{ElementHistoryData, ElementHistoryValue, MintHashData, MintHashValue}; use wire_message::WireMessage; -pub use keys::BlockListOrder; +pub use element_history::ElementHistoryIndexEntry; +pub use keys::{BlockListOrder, ElementHistoryKind}; pub use list::StoreList; #[derive(Debug, thiserror::Error)] @@ -24,6 +31,9 @@ pub enum Error { #[error("invalid key")] InvalidKey, + #[error("invalid value {0}")] + InvalidValue(u64), + #[error("invalid version '{0}'")] InvalidVersion(u32), @@ -41,6 +51,7 @@ type Result = std::result::Result; pub struct BlockStore { db: DB, + element_history_index: ElementHistoryIndex, _marker: PhantomData, } @@ -55,12 +66,15 @@ pub trait Block { pub trait Transaction { fn txn_hash(&self) -> [u8; 32]; + fn input_elements(&self) -> Vec; + fn output_elements(&self) -> Vec; + fn mint_hash(&self) -> Option; } impl BlockStore where B: Block + WireMessage, - B::Txn: WireMessage, + B::Txn: WireMessage + Transaction, { fn db_options(create_if_missing: bool) -> rocksdb::Options { let mut opts = rocksdb::Options::default(); @@ -68,6 +82,7 @@ where opts } + #[tracing::instrument(skip_all)] pub fn create_or_load(path: &Path) -> Result { if path.exists() && std::fs::read_dir(path)?.next().is_some() { Self::load_existing(path) @@ -79,47 +94,50 @@ where fn create(path: &Path) -> Result { let db = DB::open(&Self::db_options(true), path)?; - let self_ = Self { - db, - _marker: PhantomData, - }; - - self_.set_store_version(LATEST_VERSION)?; + let store = Self::from_db(db)?; + store.set_store_version(LATEST_VERSION)?; - Ok(self_) + Ok(store) } + #[tracing::instrument(skip_all)] fn load_existing(path: &Path) -> Result { let db = DB::open(&Self::db_options(false), path)?; + Self::from_db(db) + } + + #[tracing::instrument(skip_all)] + fn from_db(db: DB) -> Result { + let element_history_index = ElementHistoryIndex::load(&db)?; + Ok(Self { db, + element_history_index, _marker: PhantomData, }) } pub fn set(&self, block: &B) -> Result<()> { - // Use a batch to write atomically in case we crash in the middle let mut batch = rocksdb::WriteBatchWithTransaction::::default(); let height = block.block_height(); - let block_hash = block.block_hash(); + let block_hash_arr = block.block_hash(); batch.put(Key::Block(KeyBlock(height)).serialize(), block.to_bytes()?); let max_height = self.get_max_height()?; - if max_height.map_or(true, |max_height| height > max_height) { + if max_height.is_none_or(|max_height| height > max_height) { batch.put(Key::MaxHeight.serialize(), height.to_be_bytes()); } batch.put( - Key::BlockHashToHeight(block_hash).serialize(), + Key::BlockHashToHeight(block_hash_arr).serialize(), height.to_be_bytes(), ); for e in Self::txn_entries(block) { let (k, v) = e?; - batch.put(k.serialize(), v); } @@ -127,7 +145,54 @@ where batch.put(key.to_key().serialize(), block.to_bytes()?); } + let mut pending_history_entries = Vec::new(); + + for txn in block.txns() { + for (leaf, kind) in txn + .output_elements() + .into_iter() + .map(|e| (e, ElementHistoryKind::Output)) + .chain( + txn.input_elements() + .into_iter() + .map(|e| (e, ElementHistoryKind::Input)), + ) + { + let history_key = Key::ElementHistory((leaf, kind)); + let history_data = ElementHistoryData { + block_hash: CryptoHash(block_hash_arr), + block_height: height, + }; + let history_value = ElementHistoryValue::V1(history_data); + + let mut history_value_bytes = Vec::new(); + history_value.serialize(&mut history_value_bytes)?; + + batch.put(history_key.serialize(), &history_value_bytes); + + pending_history_entries.push(ElementHistoryIndexEntry { + block_height: height, + element: leaf, + kind, + }); + } + + if let Some(mint_hash) = txn.mint_hash() { + let mint_hash_key = Key::MintHash(mint_hash); + + let mint_hash_value = MintHashValue::V1(MintHashData { + block_hash: CryptoHash(block_hash_arr), + block_height: height, + }); + let mut mint_hash_value_bytes = Vec::new(); + mint_hash_value.serialize(&mut mint_hash_value_bytes)?; + + batch.put(mint_hash_key.serialize(), &mint_hash_value_bytes); + } + } + self.db.write(batch)?; + self.element_history_index.append(pending_history_entries); Ok(()) } @@ -202,16 +267,63 @@ where .put(Key::StoreVersion.serialize(), version.to_be_bytes())?; Ok(()) } + + fn get_element_history_with_kind( + &self, + element: element::Element, + kind: ElementHistoryKind, + ) -> Result> { + let key = Key::ElementHistory((element, kind)); + let Some(bytes) = self.db.get(key.serialize())? else { + return Ok(None); + }; + let value = ElementHistoryValue::deserialize(&mut &bytes[..])?; + match value { + ElementHistoryValue::V1(data) => Ok(Some(data)), + } + } + + /// Returns (Input History, Output History) + pub fn get_element_history( + &self, + element: element::Element, + ) -> Result<(Option, Option)> { + Ok(( + self.get_element_history_with_kind(element, ElementHistoryKind::Input)?, + self.get_element_history_with_kind(element, ElementHistoryKind::Output)?, + )) + } + + pub fn element_history_range( + &self, + range: impl RangeBounds, + ) -> Vec { + self.element_history_index.range(range) + } + + /// Returns mint hash data + pub fn get_mint_hash(&self, mint_hash: element::Element) -> Result> { + let key = Key::MintHash(mint_hash); + let Some(bytes) = self.db.get(key.serialize())? else { + return Ok(None); + }; + let value = MintHashValue::deserialize(&mut &bytes[..])?; + match value { + MintHashValue::V1(data) => Ok(Some(data)), + } + } } #[cfg(test)] mod tests { use super::*; + use element::Element; use tempdir::TempDir; + use wire_message::test_api::DummyMsg; - pub(crate) type DummyBlock = - wire_message::test_api::DummyMsg<(BlockHeight, [u8; 32], Vec)>; - pub(crate) type DummyTxn = wire_message::test_api::DummyMsg<[u8; 32]>; + pub(crate) type DummyBlock = DummyMsg<(BlockHeight, [u8; 32], Vec)>; + pub(crate) type DummyTxn = + wire_message::test_api::DummyMsg<([u8; 32], (Vec, Vec), Option)>; impl Block for DummyBlock { type Txn = DummyTxn; @@ -231,7 +343,19 @@ mod tests { impl Transaction for DummyTxn { fn txn_hash(&self) -> [u8; 32] { - *self.inner() + self.inner().0 + } + + fn input_elements(&self) -> Vec { + self.inner().1.0.clone() + } + + fn output_elements(&self) -> Vec { + self.inner().1.1.clone() + } + + fn mint_hash(&self) -> Option { + self.inner().2 } } @@ -251,7 +375,22 @@ mod tests { let block_store = BlockStore::::create_or_load(temp_dir.path()).unwrap(); let block_number = BlockHeight(1); - let txns = vec![DummyTxn::V1([123; 32]), DummyTxn::V1([124; 32])]; + let element1 = Element::from(100u64); + let element2 = Element::from(101u64); + let mint_hash = Element::from(102u64); + let mint_hash_2 = Element::from(103u64); + let txns = vec![ + DummyTxn::V1(( + [123; 32], + (vec![], vec![element1, element2]), + Some(mint_hash), + )), + DummyTxn::V1(( + [124; 32], + (vec![element1, element2], vec![]), + Some(mint_hash_2), + )), + ]; let block_data = DummyBlock::V1((block_number, [0; 32], txns.clone())); block_store.set(&block_data).unwrap(); @@ -288,6 +427,81 @@ mod tests { let listed_txns = block_store.list_txns().collect::>>().unwrap(); assert_eq!(listed_txns, txns); + + // Test get_element_history + // TODO: write better tests for this + let (history1_input, history1_output) = block_store.get_element_history(element1).unwrap(); + let history1_input = history1_input.unwrap(); + let history1_output = history1_output.unwrap(); + assert_eq!(history1_output.block_height, block_number); + assert_eq!( + history1_input.block_hash, + primitives::hash::CryptoHash::new([0u8; 32]), + ); + + let history2 = block_store + .get_element_history(element2) + .unwrap() + .1 + .unwrap(); + assert_eq!(history2.block_height, block_number); + assert_eq!( + history2.block_hash, + primitives::hash::CryptoHash::new([0u8; 32]), + ); + + let non_existent_element = element::Element::from(999u64); + assert!( + block_store + .get_element_history(non_existent_element) + .unwrap() + .1 + .is_none() + ); + + // Test get_mint_hash + let mint_hash_data = block_store.get_mint_hash(mint_hash).unwrap().unwrap(); + assert_eq!(mint_hash_data.block_height, block_number); + assert_eq!( + mint_hash_data.block_hash, + primitives::hash::CryptoHash::new([0u8; 32]), + ); + + let mint_hash_data_2 = block_store.get_mint_hash(mint_hash_2).unwrap().unwrap(); + assert_eq!(mint_hash_data_2.block_height, block_number); + assert_eq!( + mint_hash_data_2.block_hash, + primitives::hash::CryptoHash::new([0u8; 32]), + ); + } + + #[test] + fn test_element_history_range() { + let temp_dir = temp_dir(); + let block_store = BlockStore::::create_or_load(temp_dir.path()).unwrap(); + + let block_number = BlockHeight(1); + let element = Element::from(100u64); + + let txns = vec![ + DummyTxn::V1(([1; 32], (vec![], vec![element]), None)), + DummyTxn::V1(([2; 32], (vec![element], vec![]), None)), + ]; + + let block_data = DummyBlock::V1((block_number, [0; 32], txns)); + block_store.set(&block_data).unwrap(); + + let entries = block_store.element_history_range(..=block_number); + assert_eq!(entries.len(), 2); + assert_eq!(entries[0].kind, ElementHistoryKind::Output); + assert_eq!(entries[0].element, element); + assert_eq!(entries[1].kind, ElementHistoryKind::Input); + + let exact_entries = block_store.element_history_range(block_number..=block_number); + assert_eq!(exact_entries.len(), 2); + + let later_entries = block_store.element_history_range(block_number.next()..); + assert!(later_entries.is_empty()); } #[test] @@ -295,7 +509,6 @@ mod tests { let temp_dir = temp_dir(); let block_store = BlockStore::::create_or_load(temp_dir.path()).unwrap(); - // Insert some blocks for i in 0..10_000 { block_store .set(&DummyBlock::V1((BlockHeight(i as u64), [0; 32], vec![]))) @@ -320,13 +533,11 @@ mod tests { ); } - // Paginated list let blocks = block_store .list_paginated(&None, BlockListOrder::LowestToHighest, usize::MAX) .unwrap() .collect::>>() .unwrap(); - // Same order, but backwards let before_blocks = block_store .list_paginated( &Some(primitives::pagination::CursorChoice::Before( @@ -340,12 +551,8 @@ mod tests { .unwrap() .collect::>>() .unwrap(); - // The order when iterating backwards - // should still be consistent with the requested LowestToHighest order, - // such that the lowest height blocks are first. assert_eq!(blocks, before_blocks); - // Same thing, but with a limit that's less than the max number of blocks let before_blocks_except_first = block_store .list_paginated( &Some(primitives::pagination::CursorChoice::Before( diff --git a/pkg/block-store/src/list.rs b/pkg/block-store/src/list.rs index f1c0c63..849ff5f 100644 --- a/pkg/block-store/src/list.rs +++ b/pkg/block-store/src/list.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=300 use std::{marker::PhantomData, ops::RangeBounds}; use primitives::{block_height::BlockHeight, pagination::CursorChoice}; @@ -5,8 +6,8 @@ use rocksdb::DB; use wire_message::WireMessage; use crate::{ - keys::{Key, KeyBlock, KeyNonEmptyBlock, ListableKey, StoreValue}, Block, BlockListOrder, BlockStore, Error, Result, + keys::{Key, KeyBlock, KeyNonEmptyBlock, ListableKey, StoreValue}, }; pub trait StoreList { @@ -80,7 +81,7 @@ where fn map NewMapped + Send>( self, map: F, - ) -> MappedList { + ) -> impl StoreList { MappedList { list: self, map, @@ -114,7 +115,7 @@ where fn map NewItem + Send>( self, map: NF, - ) -> MappedList { + ) -> impl StoreList { MappedList { map, list: self, diff --git a/pkg/block-store/src/migration.rs b/pkg/block-store/src/migration.rs index 2f8f0a2..c526050 100644 --- a/pkg/block-store/src/migration.rs +++ b/pkg/block-store/src/migration.rs @@ -2,8 +2,8 @@ use wire_message::WireMessage; use super::Result; use crate::{ - keys::{self, BlockListOrder, StoreKey}, Block, BlockStore, Error, StoreList, + keys::{self, BlockListOrder, StoreKey}, }; pub(crate) const LATEST_VERSION: u32 = 1; @@ -13,6 +13,7 @@ where B: Block + WireMessage, B::Txn: WireMessage, { + #[tracing::instrument(skip(self))] pub fn migrate(&self) -> super::Result<()> { loop { let version = self.store_version()?; diff --git a/pkg/block-store/src/values.rs b/pkg/block-store/src/values.rs new file mode 100644 index 0000000..407e3c2 --- /dev/null +++ b/pkg/block-store/src/values.rs @@ -0,0 +1,26 @@ +use primitives::{block_height::BlockHeight, hash::CryptoHash}; +use wire_message::wire_message; + +#[derive(Debug, Clone, PartialEq, borsh::BorshSerialize, borsh::BorshDeserialize)] +pub struct ElementHistoryData { + pub block_hash: CryptoHash, + pub block_height: BlockHeight, +} + +#[derive(Debug, Clone, PartialEq)] +#[wire_message(version = 1)] +pub enum ElementHistoryValue { + V1(ElementHistoryData), +} + +#[derive(Debug, Clone, PartialEq, borsh::BorshSerialize, borsh::BorshDeserialize)] +pub struct MintHashData { + pub block_hash: CryptoHash, + pub block_height: BlockHeight, +} + +#[derive(Debug, Clone, PartialEq)] +#[wire_message(version = 1)] +pub enum MintHashValue { + V1(MintHashData), +} diff --git a/pkg/burn-substitutor/Cargo.toml b/pkg/burn-substitutor/Cargo.toml index 5f5aeca..02c1612 100644 --- a/pkg/burn-substitutor/Cargo.toml +++ b/pkg/burn-substitutor/Cargo.toml @@ -1,19 +1,23 @@ [package] name = "burn-substitutor" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] contracts = { workspace = true } +element = { workspace = true } +node-client-http = { workspace = true } +node-interface = { workspace = true } primitives = { workspace = true } rpc = { workspace = true } -zk-circuits = { workspace = true } zk-primitives = { workspace = true } +eth-util = { workspace = true } +url = { workspace = true } clap = { workspace = true } -eyre = { workspace = true } -reqwest = { workspace = true } +contextful = { workspace = true } serde = { workspace = true } -serde_json = { workspace = true } +thiserror = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } +workspace-hack = { workspace = true } diff --git a/pkg/burn-substitutor/README.md b/pkg/burn-substitutor/README.md new file mode 100644 index 0000000..4a73727 --- /dev/null +++ b/pkg/burn-substitutor/README.md @@ -0,0 +1,20 @@ +# Burn Substitutor + +Tool for handling burn operations and substitutions in the zk-rollup system. + +## Overview + +This package provides functionality for processing burn operations, allowing users to convert rollup assets to external blockchain assets. + +## Features + +- Burn operation processing +- Asset substitution logic +- Command-line interface +- Integration with rollup contracts + +## Configuration + +- `CHAIN_ID`: EVM chain id for the rollup contract (defaults to `137`). +- `CHAIN_ID` is validated against the RPC network on startup and the process exits on mismatch. +- `EXCLUDED_BURN_ADDRESSES`: Comma-separated list of burn recipient addresses that should never be substituted. diff --git a/pkg/burn-substitutor/src/bin/burn-substitutor.rs b/pkg/burn-substitutor/src/bin/burn-substitutor.rs index e8fcf51..f3d7cfa 100644 --- a/pkg/burn-substitutor/src/bin/burn-substitutor.rs +++ b/pkg/burn-substitutor/src/bin/burn-substitutor.rs @@ -1,8 +1,10 @@ -use std::{str::FromStr, time::Duration}; +use std::time::Duration; +use burn_substitutor::Error; use clap::Parser; -use contracts::{RollupContract, U256}; -use eyre::ContextCompat; +use contextful::prelude::*; +use contracts::{Address, ConfirmationType, RollupContract, U256}; +use node_client_http::{NodeClientHttp, Url}; use rpc::tracing::{LogFormat, LogLevel}; use serde::{Deserialize, Serialize}; @@ -12,18 +14,16 @@ use serde::{Deserialize, Serialize}; #[command(author, version, about = "Polybase Burn Subsitutor - enables instant withdrawals", long_about = None)] #[command(propagate_version = true)] pub struct Config { - /// Log level #[arg(value_enum, long, env = "LOG_LEVEL", default_value = "INFO")] log_level: LogLevel, - /// Log format #[arg(value_enum, long, env = "LOG_FORMAT", default_value = "PRETTY")] log_format: LogFormat, #[arg( long, env = "ROLLUP_CONTRACT_ADDRESS", - default_value = "0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6" + default_value = "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9" )] rollup_contract_address: String, @@ -44,17 +44,26 @@ pub struct Config { #[arg(long, env = "EVM_RPC_URL", default_value = "http://localhost:8545")] evm_rpc_url: String, - #[arg(long, env = "NODE_RPC_URL", default_value = "http://localhost:8080")] + /// Ethereum chain id for the rollup contract + #[arg(long, env = "CHAIN_ID", default_value_t = 137)] + chain_id: u64, + + #[arg(long, env = "NODE_RPC_URL", default_value = "http://localhost:8080/v0")] node_rpc_url: String, #[arg(long, env = "MINIMUM_GAS_PRICE_GWEI")] minimum_gas_price_gwei: Option, + + #[arg(long, env = "EXCLUDED_BURN_ADDRESSES", value_delimiter = ',')] + excluded_burn_addresses: Vec, } #[tokio::main] -async fn main() -> Result<(), eyre::Error> { +async fn main() -> Result<(), Error> { let config = Config::parse(); + let excluded_burn_addresses = parse_excluded_addresses(&config.excluded_burn_addresses)?; + rpc::tracing::setup_tracing( &[ "burn_substitutor", @@ -66,42 +75,85 @@ async fn main() -> Result<(), eyre::Error> { "zk_primitives", "contracts", "block_store", + "element", + "notes", ], &config.log_level, &config.log_format, std::env::var("SENTRY_DSN").ok(), std::env::var("ENV_NAME").unwrap_or_else(|_| "dev".to_owned()), - )?; + ) + .map_err(std::io::Error::other) + .context("setup tracing")?; - let secret_key = contracts::SecretKey::from_str( + let wallet = contracts::wallet::Wallet::new_from_str( config .evm_secret_key .strip_prefix("0x") - .context("Secret key must start with 0x")?, - )?; + .ok_or(Error::MissingField { name: "0x prefix" })?, + ) + .context("parse secret key")?; + let secret_key = wallet.web3_secret_key(); let client = contracts::Client::new(&config.evm_rpc_url, config.minimum_gas_price_gwei); - let rollup_contract = - RollupContract::load(client.clone(), &config.rollup_contract_address, secret_key).await?; - let usdc_contract = - contracts::USDCContract::load(client.clone(), &config.usdc_contract_address, secret_key) - .await?; + let rpc_chain_id = client + .chain_id_contracts() + .await + .context("fetch rpc chain id")?; + let config_chain_id = U256::from(config.chain_id); + if rpc_chain_id != config_chain_id { + return Err(Error::ChainIdMismatch { + config_chain_id: config.chain_id, + rpc_chain_id, + }); + } + let primary_chain_id = u128::from(config.chain_id); + let rollup_contract = RollupContract::load( + client.clone(), + primary_chain_id, + &config.rollup_contract_address, + secret_key, + ) + .await + .context("load rollup contract")?; + let usdc_contract = contracts::USDCContract::load( + client.clone(), + primary_chain_id, + &config.usdc_contract_address, + secret_key, + ) + .await + .context("load usdc contract")?; + + let node_client = + NodeClientHttp::new(Url::parse(&config.node_rpc_url).context("parse node rpc url")?); if usdc_contract .allowance(rollup_contract.signer_address, rollup_contract.address()) - .await? + .await + .context("fetch allowance")? != U256::MAX { - let approve_txn = usdc_contract.approve_max(rollup_contract.address()).await?; + let approve_txn = usdc_contract + .approve_max(rollup_contract.address()) + .await + .context("approve max")?; client - .wait_for_confirm(approve_txn, Duration::from_secs(1)) - .await?; + .wait_for_confirm( + approve_txn, + Duration::from_secs(1), + ConfirmationType::Latest, + ) + .await + .context("wait for approve confirm")?; } let mut substitutor = burn_substitutor::BurnSubstitutor::new( rollup_contract, - config.node_rpc_url, + usdc_contract, + Box::new(node_client), Duration::from_secs(1), + excluded_burn_addresses, ); tracing::info!("Starting burn substitutor"); @@ -117,3 +169,16 @@ async fn main() -> Result<(), eyre::Error> { } } } + +fn parse_excluded_addresses(addresses: &[String]) -> Result, Error> { + addresses + .iter() + .map(|address| { + address + .parse::
() + .map_err(|_| Error::InvalidAddress { + address: address.to_owned(), + }) + }) + .collect() +} diff --git a/pkg/burn-substitutor/src/lib.rs b/pkg/burn-substitutor/src/lib.rs index 5dbecea..1fdc62f 100644 --- a/pkg/burn-substitutor/src/lib.rs +++ b/pkg/burn-substitutor/src/lib.rs @@ -1,155 +1,203 @@ -use std::time::Duration; +// lint-long-file-override allow-max-lines=300 -use contracts::RollupContract; -use eyre::{Context, ContextCompat}; +use std::{collections::HashSet, time::Duration}; + +use contextful::{FromContextful, InternalError, prelude::*}; +use contracts::{Address, ConfirmationType, RollupContract, U256, USDCContract}; +use element::Element; +use eth_util::Eth; +use node_interface::{ListTxnsOrder, ListTxnsParams, ListTxnsPosition, NodeClient, TxnWithInfo}; use primitives::{ block_height::BlockHeight, - pagination::{CursorChoice, CursorChoiceAfter, OpaqueCursor, OpaqueCursorChoice}, + pagination::{CursorChoice, CursorChoiceAfter}, }; -use reqwest::StatusCode; -use zk_circuits::data::UTXOProof; -use zk_primitives::Element; +use thiserror::Error; +use zk_primitives::UtxoKindMessages; + +pub type Result = std::result::Result; + +#[derive(Debug, Error, FromContextful)] +pub enum Error { + #[error("[burn-substitutor] missing field: {name}")] + MissingField { name: &'static str }, + + #[error("[burn-substitutor] chain id mismatch: config={config_chain_id}, rpc={rpc_chain_id}")] + ChainIdMismatch { + config_chain_id: u64, + rpc_chain_id: U256, + }, + + #[error("[burn-substitutor] invalid address: {address}")] + InvalidAddress { address: String }, + + #[error("[burn-substitutor] internal error")] + Internal(#[from] InternalError), +} pub struct BurnSubstitutor { rollup_contract: RollupContract, - node_rpc_url: String, + usdc_contract: USDCContract, + node_client: Box, eth_txn_confirm_wait_interval: Duration, - cursor: Option>, + next_txn_cursor: Option>, + excluded_burn_addresses: HashSet
, } +const TXNS_PAGE_LIMIT: usize = 100; + impl BurnSubstitutor { pub fn new( rollup_contract: RollupContract, - node_rpc_url: String, + usdc_contract: USDCContract, + node_client: Box, eth_txn_confirm_wait_interval: Duration, + excluded_burn_addresses: Vec
, ) -> Self { BurnSubstitutor { rollup_contract, - node_rpc_url, + usdc_contract, + node_client, eth_txn_confirm_wait_interval, - cursor: None, + next_txn_cursor: None, + excluded_burn_addresses: excluded_burn_addresses.into_iter().collect(), } } - pub async fn tick(&mut self) -> Result, eyre::Error> { - if self.cursor.is_none() { - let last_rollup = self.fetch_last_rollup_block().await?; - - self.cursor = Some( - CursorChoice::After(CursorChoiceAfter::After(ListTxnsPosition { - block: last_rollup, - txn: u64::MAX, - })) - .opaque(), - ); + pub async fn tick(&mut self) -> Result> { + if self.next_txn_cursor.is_none() { + let last_rollup = self + .fetch_last_rollup_block() + .await + .context("fetch last rollup block")?; + + self.next_txn_cursor = Self::start_txn_cursor(last_rollup.next()); } - let (txns, cursor) = Self::fetch_transactions( - &reqwest::Client::new(), - &self.node_rpc_url, - None, - self.cursor.as_ref(), - false, - ) - .await - .context("Failed to fetch transactions")?; + let (txns, next_txn_cursor) = + Self::fetch_transactions(self.node_client.as_ref(), self.next_txn_cursor).await?; let mut substituted_burns = Vec::new(); for txn in &txns { - let inputs = txn - .proof - .input_leaves - .iter() - .filter(|e| !e.is_zero()) - .collect::>(); - let has_only_one_input = inputs.len() == 1; - let has_no_outputs = txn.proof.output_leaves.iter().all(|e| e.is_zero()); - let has_mb = txn.proof.mb_hash != Element::ZERO && txn.proof.mb_value != Element::ZERO; - let is_burn = has_only_one_input && has_no_outputs && has_mb; - - if is_burn { - let nullifier = inputs[0]; - - if self.rollup_contract.was_burn_substituted(nullifier).await? { + if let UtxoKindMessages::Burn(burn_msgs) = txn.proof.kind_messages() { + let hash = burn_msgs.burn_hash; + let burn_address = + Address::from_slice(&burn_msgs.burn_address.to_be_bytes()[12..32]); + let amount = burn_msgs.value; + let note_kind = burn_msgs.note_kind; + let burn_block_height = txn.block_height.0; + + if self.excluded_burn_addresses.contains(&burn_address) { + tracing::info!( + ?burn_address, + "Skipping burn substitution for excluded address" + ); + continue; + } + + if self + .rollup_contract + .was_burn_substituted(&burn_address, ¬e_kind, &hash, &amount) + .await + .context("check was_burn_substituted")? + { + continue; + } + + let burn_value = burn_msgs.value.to_eth_u256(); + + let usdc_balance = self + .usdc_contract + .balance(self.rollup_contract.signer_address) + .await + .context("fetch USDC balance for burn substitution")?; + + if burn_value > usdc_balance { + tracing::info!( + ?txn.proof.public_inputs, + %burn_value, + %usdc_balance, + "Skipping burn: value exceeds substitutor balance" + ); continue; } - let txn = self + let txn = match self .rollup_contract - .substitute_burn(nullifier, &txn.proof.mb_value) + .substitute_burn(&burn_address, ¬e_kind, &hash, &amount, burn_block_height) .await - .context("Failed to substitute burn")?; + { + Ok(txn) => txn, + Err(err) => { + tracing::error!( + ?txn.proof.public_inputs, + %burn_value, + %usdc_balance, + %err, + "Failed to submit burn substitution transaction", + ); + continue; + } + }; self.rollup_contract .client - .wait_for_confirm(txn, self.eth_txn_confirm_wait_interval) + .wait_for_confirm( + txn, + self.eth_txn_confirm_wait_interval, + ConfirmationType::Latest, + ) .await - .context("Failed to wait for burn substitution")?; + .context("wait for burn substitution")?; - substituted_burns.push(*nullifier); + substituted_burns.push(hash); } } - if !txns.is_empty() { - self.cursor = cursor - .after - .map(|after| CursorChoice::After(after.0).opaque()); - } + self.next_txn_cursor = next_txn_cursor; Ok(substituted_burns) } - async fn fetch_last_rollup_block(&mut self) -> Result { + async fn fetch_last_rollup_block( + &mut self, + ) -> std::result::Result { self.rollup_contract.block_height().await.map(BlockHeight) } async fn fetch_transactions( - client: &reqwest::Client, - network_base_url: &str, - limit: Option, - cursor: Option<&OpaqueCursorChoice>, - poll: bool, - ) -> Result<(Vec, OpaqueCursor), eyre::Error> { - let req = client - .get(format!("{network_base_url}/v0/transactions")) - .query(&[ - ("limit", limit.map(|l| l.to_string())), - ("order", Some("OldestToNewest".to_owned())), - ("cursor", cursor.map(|c| c.serialize()).transpose()?), - ("poll", Some(poll.to_string())), - ]); - - let resp = req.send().await?; - - match resp.status() { - StatusCode::OK => {} - e => return Err(eyre::eyre!("Unexpected status code: {e}")), - } - - let mut resp = resp.json::().await?; - - let txns = serde_json::from_value::>( - resp.get_mut("txns").context("Missing txns field")?.take(), - )?; - - let cursor = resp - .get_mut("cursor") - .context("Missing pagination field")? - .take(); - - let cursor = serde_json::from_value(cursor).context("Failed to parse cursor")?; - - Ok((txns, cursor)) + node_client: &dyn NodeClient, + cursor: Option>, + ) -> Result<( + Vec, + Option>, + )> { + let response = node_client + .list_transactions(ListTxnsParams { + limit: TXNS_PAGE_LIMIT, + cursor: cursor.map(|cursor| CursorChoice::After(cursor).opaque()), + order: ListTxnsOrder::OldestToNewest, + poll: true, + }) + .await + .context("fetch transactions")?; + + let next_cursor = response + .cursor + .after + .map(|after| after.into_inner()) + .or(cursor); + + Ok((response.txns, next_cursor)) } -} -#[derive(Debug, serde::Deserialize)] -struct Transaction { - pub proof: UTXOProof<0>, -} + fn start_txn_cursor(start_height: BlockHeight) -> Option> { + if start_height.0 == 0 { + return None; + } -#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -struct ListTxnsPosition { - block: BlockHeight, - txn: u64, + Some(CursorChoiceAfter::After(ListTxnsPosition { + block: BlockHeight(start_height.0 - 1), + txn: u64::MAX, + })) + } } diff --git a/pkg/client-http-longpoll/Cargo.toml b/pkg/client-http-longpoll/Cargo.toml new file mode 100644 index 0000000..77d53d0 --- /dev/null +++ b/pkg/client-http-longpoll/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "client-http-longpoll" +version = "0.1.0" +edition = "2024" + +[dependencies] +rpc = { workspace = true } + +parking_lot = { workspace = true } +async-trait = { workspace = true } +async-stream = { workspace = true } +tokio = { workspace = true } +chrono = { workspace = true } +futures = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/client-http-longpoll/README.md b/pkg/client-http-longpoll/README.md new file mode 100644 index 0000000..f2a8474 --- /dev/null +++ b/pkg/client-http-longpoll/README.md @@ -0,0 +1,15 @@ +# Client HTTP Long Poll + +Long-polling HTTP client for real-time updates. + +## Overview + +This package implements long-polling functionality over HTTP, enabling real-time communication between clients and servers. + +## Features + +- Long-polling HTTP connections +- Real-time event streaming +- Connection management +- Timeout handling + diff --git a/pkg/client-http-longpoll/src/lib.rs b/pkg/client-http-longpoll/src/lib.rs new file mode 100644 index 0000000..f54e7a5 --- /dev/null +++ b/pkg/client-http-longpoll/src/lib.rs @@ -0,0 +1,234 @@ +// lint-long-file-override allow-max-lines=300 +use chrono::{DateTime, Utc}; +use futures::Stream; +use parking_lot::Mutex; +use rpc::longpoll::PollData; +use std::{ + sync::Arc, + time::{Duration, Instant}, +}; + +/// Data returned by LongPoll stream, including the user data and last modified timestamp +#[derive(Debug, Clone)] +pub struct LongPollResult { + pub data: T, + pub last_modified: Option>, +} + +#[derive(Clone)] +pub struct LongPoll { + poller: Arc, + state: Arc>, +} + +#[derive(Clone, Default)] +pub struct LongPollState { + error_count: u64, + last_modified: Option>, +} + +impl LongPollState { + fn register_error(&mut self, start: Instant) -> Instant { + self.error_count += 1; + // Maximum backoff 5 seconds + start + Duration::from_secs(self.error_count.min(5)) + } + + fn register_modified(&mut self, date: DateTime) { + self.last_modified = Some(date); + self.reset_error(); + } + + fn reset_error(&mut self) { + self.error_count = 0; + } +} + +impl LongPoll { + pub fn new(poller: LP) -> Self { + Self { + poller: Arc::new(poller), + state: Arc::new(Mutex::new(LongPollState::default())), + } + } + + pub fn stream(&self) -> impl Stream, LP::Error>> { + let poller = self.poller.clone(); + let state = self.state.clone(); + + async_stream::stream! { + loop { + let start = Instant::now(); + + let last_modified = state.lock().last_modified; + + match poller.poll(last_modified).await { + Ok(poll_data) => { + match poll_data { + PollData::Modified { data, modified_at } => { + // Reset error count and update last_modified + if let Some(modified_at) = modified_at { + state.lock().register_modified(modified_at); + } + yield Ok(LongPollResult { + data, + last_modified: modified_at, + }); + } + PollData::NotModified => { + // Reset error count on successful poll + state.lock().reset_error(); + } + } + + // Don't run poll more than once per second + let next_poll = start + Duration::from_secs(1); + tokio::time::sleep_until(next_poll.into()).await; + } + Err(err) => { + yield Err(err); + + // Calculate next retry time based on error count + let next_retry = state.lock().register_error(start); + tokio::time::sleep_until(next_retry.into()).await; + } + } + } + } + } +} + +#[async_trait::async_trait] +pub trait LongPollPoller: Send + Sync + 'static { + type T: Clone + Send + Sync + 'static; + type Error: Clone + Send + Sync + 'static; + + async fn poll( + &self, + last_modified: Option>, + ) -> Result, Self::Error>; +} + +// use chrono::{DateTime, Utc}; +// use parking_lot::Mutex; +// use primitives::tick_worker::{TickWorker, TickWorkerTick}; +// use rpc::longpoll::PollData; +// use std::{ +// sync::Arc, +// time::{Duration, Instant}, +// }; +// use tokio::sync::broadcast::{self, Receiver, Sender}; + +// #[derive(Clone)] +// pub struct LongPoll { +// ticker: Arc>>, +// shared: LongPollSharedArc, +// } + +// impl LongPoll { +// pub fn new(lp: LP) -> Self { +// let shared = LongPollSharedArc(Arc::new(LongPollShared { +// poller: lp, +// state: Mutex::new(LongPollState::default()), +// })); +// let ticker = Arc::new(TickWorker::new()); +// Self { ticker, shared } +// } + +// pub fn subscribe(&self) { +// self.ticker.run(self.shared.clone()); +// } +// } + +// pub struct LongPollSharedArc(Arc>); + +// impl Clone for LongPollSharedArc { +// fn clone(&self) -> Self { +// Self(self.0.clone()) +// } +// } + +// pub struct LongPollShared { +// poller: LP, +// state: Mutex, +// } + +// #[async_trait::async_trait] +// pub trait LongPollPoller: Send + Sync + 'static { +// type T: Clone + Send + Sync + 'static; +// type Error: Clone + Send + Sync + 'static; + +// async fn poll( +// &self, +// last_modified: Option>, +// ) -> Result, Self::Error>; +// } + +// #[derive(Clone)] +// pub struct LongPollState { +// error_count: u64, +// last_modified: Option>, +// } + +// impl Default for LongPollState { +// fn default() -> Self { +// Self { +// error_count: 0, +// last_modified: None, +// } +// } +// } + +// impl LongPollState { +// fn register_error(&mut self) -> Instant { +// self.error_count += 1; +// // Maximum backoff 5 seconds +// Instant::now() + Duration::from_secs(self.error_count.min(5)) +// } + +// fn register_modified(&mut self, date: DateTime) { +// self.last_modified = Some(date); +// self.reset_error(); +// } + +// fn reset_error(&mut self) { +// self.error_count = 0; +// } +// } + +// #[async_trait::async_trait] +// impl TickWorkerTick for LongPollSharedArc { +// async fn tick(&self) -> Option { +// let start = Instant::now(); +// let last_modified = self.0.state.lock().last_modified.clone(); +// match self.0.poller.poll(last_modified).await { +// Ok(poll_data) => { +// match poll_data { +// PollData::Modified { data, modified_at } => { +// if let Err(_) = self.0.tx.send(Ok(data)) { +// // Only possible error is no listeners so we can stop polling +// self.0.state.lock().reset_error(); +// return None; +// }; +// if let Some(modified_at) = modified_at { +// self.0.state.lock().register_modified(modified_at); +// } +// } +// PollData::NotModified => { +// self.0.state.lock().reset_error(); +// } +// } +// // Don't run poll more than once per second +// Some(Instant::now().min(start + Duration::from_secs(1))) +// } +// Err(err) => { +// if let Err(_) = self.0.tx.send(Err(err)) { +// // Only possible error is no listeners so we can stop polling +// self.0.state.lock().reset_error(); +// return None; +// }; +// Some(self.0.state.lock().register_error()) +// } +// } +// } +// } diff --git a/pkg/client-http/Cargo.toml b/pkg/client-http/Cargo.toml new file mode 100644 index 0000000..9d9b1bf --- /dev/null +++ b/pkg/client-http/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "client-http" +version = "0.1.0" +edition = "2024" + +[dependencies] +http-interface = { workspace = true } +rpc = { workspace = true } + +async-trait = { workspace = true } +reqwest = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/client-http/README.md b/pkg/client-http/README.md new file mode 100644 index 0000000..86f4005 --- /dev/null +++ b/pkg/client-http/README.md @@ -0,0 +1,15 @@ +# Client HTTP + +HTTP client library with request/response handling and utilities. + +## Overview + +This package provides a robust HTTP client implementation with error handling, request building, and response processing capabilities. + +## Features + +- HTTP request/response handling +- Error handling and retry logic +- Request builder pattern +- Utility functions for common operations + diff --git a/pkg/client-http/src/builder.rs b/pkg/client-http/src/builder.rs new file mode 100644 index 0000000..700c2f9 --- /dev/null +++ b/pkg/client-http/src/builder.rs @@ -0,0 +1,119 @@ +use crate::{ClientHttp, ClientResponse, error::Result, request::RequestData}; +use http_interface::{ + builder::{BodyApplier, HttpRequestExecutor}, + error::HttpRequestExecError, +}; +use reqwest::{Method, header::HeaderMap}; +use rpc::error::{ErrorOutput, TryFromHTTPError}; +use std::{fmt::Debug, sync::Arc}; + +/// Request configures a request to be sent. +pub struct RequestBuilder { + pub(crate) client: ClientHttp, + pub(crate) path: String, + pub(crate) method: Method, + pub(crate) headers: Option, + pub(crate) body: Option>, + pub(crate) query: Option>, + pub(crate) auth: bool, +} + +impl RequestBuilder { + pub fn new( + client: ClientHttp, + path: String, + method: Method, + body: Option>, + ) -> Self { + Self { + client, + path, + method, + headers: None, + body, + auth: false, + query: None, + } + } + + fn with_headers(mut self, headers: HeaderMap) -> Self { + self.headers = Some(headers); + self + } + + /// Set the request headers. + pub fn headers(self, headers: HeaderMap) -> Self { + self.with_headers(headers) + } + + fn with_query(mut self, query: Vec<(String, String)>) -> Self { + self.query = Some(query); + self + } + + /// Attach query parameters to the request. + pub fn query(self, query: Vec<(String, String)>) -> Self { + self.with_query(query) + } + + fn with_auth(mut self) -> Self { + self.auth = true; + self + } + + /// Enable auth header injection for the request. + pub fn auth(self) -> Self { + self.with_auth() + } + + /// Execute the request while borrowing the builder to maintain the + /// previous API surface. + pub async fn exec(&self) -> Result + where + E: TryFrom + Debug + Send, + { + self.exec_raw() + .await + .map_err(HttpRequestExecError::into_error::) + } + + pub async fn exec_owned(self) -> Result + where + E: TryFrom + Debug + Send, + { + self.exec_owned_raw() + .await + .map_err(HttpRequestExecError::into_error::) + } + + pub async fn exec_raw(&self) -> std::result::Result { + let client = self.client.clone(); + let request_data = RequestData::from(self); + client.request_raw(request_data).await + } + + pub async fn exec_owned_raw(self) -> std::result::Result { + let client = self.client.clone(); + let request_data = RequestData::from(&self); + client.request_raw(request_data).await + } +} + +#[async_trait::async_trait] +impl HttpRequestExecutor for RequestBuilder { + fn headers(&mut self, headers: HeaderMap) { + self.headers = Some(headers); + } + + fn query(&mut self, query: Vec<(String, String)>) { + self.query = Some(query); + } + + fn auth(&mut self) { + self.auth = true; + } + + async fn exec(self: Box) -> std::result::Result { + self.exec_owned_raw().await + } +} diff --git a/pkg/client-http/src/error.rs b/pkg/client-http/src/error.rs new file mode 100644 index 0000000..e31eeda --- /dev/null +++ b/pkg/client-http/src/error.rs @@ -0,0 +1 @@ +pub use http_interface::error::*; diff --git a/pkg/client-http/src/lib.rs b/pkg/client-http/src/lib.rs new file mode 100644 index 0000000..a0103d9 --- /dev/null +++ b/pkg/client-http/src/lib.rs @@ -0,0 +1,146 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::match_bool)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::doc_markdown)] +#![deny(missing_docs)] + +//! Base HTTPS client designed to be extended by a specific service client struct. + +use std::{sync::Arc, time::Duration}; + +use reqwest::{Method, Url, header::HeaderMap}; +use tracing::warn; + +mod builder; +mod error; +mod request; +mod response; +mod util; + +pub use error::{Error, NoRpcError, Result}; +pub use http_interface::{ + AuthError, ClientHttpAuth, HttpClient, HttpRequestBuilder, builder::HttpBody, +}; +pub use response::ClientResponse; +pub use util::serde_to_query_params; + +const CONNECT_TIMEOUT: Duration = Duration::from_secs(10); + +/// HTTPS client for making calls to servers over HTTPS. +#[derive(Clone)] +pub struct ClientHttp { + pub(crate) http_client: reqwest::Client, + pub(crate) base_url: Arc, + pub(crate) headers: HeaderMap, + pub(crate) auth: Arc, +} + +impl ClientHttp { + /// Create a new client with the provided auth implementation. + #[must_use] + pub fn new(base_url: Url, headers: HeaderMap, auth: A) -> Self + where + A: ClientHttpAuth + 'static, + { + let http_client = reqwest::Client::builder() + .connect_timeout(CONNECT_TIMEOUT) + .build() + .unwrap_or_else(|err| { + warn!( + error = %err, + "failed to build reqwest client with connect timeout; using default" + ); + reqwest::Client::new() + }); + + Self { + http_client, + base_url: Arc::new(base_url), + headers, + auth: Arc::new(auth), + } + } + + fn request_builder( + &self, + path: &str, + method: Method, + body: Option, + ) -> builder::RequestBuilder { + builder::RequestBuilder::new( + self.clone(), + path.to_owned(), + method, + body.map(|b| b.applier()), + ) + } + + /// Configure a GET request. + #[must_use] + pub fn get(&self, path: &str) -> builder::RequestBuilder { + self.request_builder(path, Method::GET, None) + } + + /// Configure a POST request. + #[must_use] + pub fn post(&self, path: &str, body: Option) -> builder::RequestBuilder { + self.request_builder(path, Method::POST, body) + } + + /// Configure a DELETE request. + #[must_use] + pub fn delete(&self, path: &str, body: Option) -> builder::RequestBuilder { + self.request_builder(path, Method::DELETE, body) + } + + /// Configure a PUT request. + #[must_use] + pub fn put(&self, path: &str, body: Option) -> builder::RequestBuilder { + self.request_builder(path, Method::PUT, body) + } + + /// Configure a PATCH request. + #[must_use] + pub fn patch(&self, path: &str, body: Option) -> builder::RequestBuilder { + self.request_builder(path, Method::PATCH, body) + } +} + +/// Default auth impl is no auth. +#[derive(Default, Clone)] +pub struct NoAuth; + +#[async_trait::async_trait] +impl ClientHttpAuth for NoAuth { + async fn get_auth(&self) -> std::result::Result { + Ok(HeaderMap::new()) + } + + async fn refresh_auth(&self) -> std::result::Result<(), AuthError> { + Ok(()) + } +} + +impl HttpClient for ClientHttp { + fn get(&self, path: &str) -> HttpRequestBuilder { + HttpRequestBuilder::new(Box::new(ClientHttp::get(self, path))) + } + + fn post(&self, path: &str, body: Option) -> HttpRequestBuilder { + HttpRequestBuilder::new(Box::new(self.request_builder(path, Method::POST, body))) + } + + fn delete(&self, path: &str, body: Option) -> HttpRequestBuilder { + HttpRequestBuilder::new(Box::new(self.request_builder(path, Method::DELETE, body))) + } + + fn put(&self, path: &str, body: Option) -> HttpRequestBuilder { + HttpRequestBuilder::new(Box::new(self.request_builder(path, Method::PUT, body))) + } + + fn patch(&self, path: &str, body: Option) -> HttpRequestBuilder { + HttpRequestBuilder::new(Box::new(self.request_builder(path, Method::PATCH, body))) + } +} diff --git a/pkg/client-http/src/request.rs b/pkg/client-http/src/request.rs new file mode 100644 index 0000000..247afae --- /dev/null +++ b/pkg/client-http/src/request.rs @@ -0,0 +1,176 @@ +// lint-long-file-override allow-max-lines=300 +use crate::{ + ClientHttp, ClientResponse, + builder::RequestBuilder, + error::{Result, handle_error_raw}, + response::HttpMetadata, + util::wait_for_secs, +}; +use http_interface::{builder::BodyApplier, error::HttpRequestExecError}; +use reqwest::{Method, header::HeaderMap}; +use rpc::error::{ErrorOutput, TryFromHTTPError}; +use std::{fmt::Debug, sync::Arc}; + +pub(crate) struct RequestData { + path: String, + method: Method, + headers: Option, + body: Option>, + query: Option>, + auth: bool, + attempts: u64, + auth_refreshed: bool, +} + +impl From<&RequestBuilder> for RequestData { + fn from(builder: &RequestBuilder) -> Self { + Self { + path: builder.path.clone(), + method: builder.method.clone(), + headers: builder.headers.clone(), + body: builder.body.clone(), + query: builder.query.clone(), + auth: builder.auth, + attempts: 0, + auth_refreshed: false, + } + } +} + +impl RequestData { + fn register_attempt(&mut self) { + self.attempts += 1; + } + + fn register_refresh_auth(&mut self) { + self.auth_refreshed = true; + self.auth = true; + } +} + +impl ClientHttp { + /// Send a HTTPS request producing typed errors. + #[allow(dead_code)] + pub(crate) async fn request(&self, req_data: RequestData) -> Result + where + E: TryFrom + Debug + Send, + { + self.request_raw(req_data) + .await + .map_err(HttpRequestExecError::into_error::) + } + + /// Send a HTTPS request returning the erased execution error used by dyn dispatch. + pub(crate) async fn request_raw( + &self, + mut req_data: RequestData, + ) -> std::result::Result { + loop { + match self.execute_request(&req_data).await { + Ok(res) => return Ok(res), + Err(HttpRequestExecError::ServerError(message, metadata)) => { + if req_data.attempts < 10 { + wait_for_secs(1).await; + req_data.register_attempt(); + continue; + } + return Err(HttpRequestExecError::ServerError(message, metadata)); + } + Err(HttpRequestExecError::Reqwest { + message, + metadata, + is_connect, + is_timeout, + }) => { + if (is_connect || is_timeout) && req_data.attempts < 10 { + wait_for_secs(1).await; + req_data.register_attempt(); + continue; + } + + return Err(HttpRequestExecError::Reqwest { + message, + metadata, + is_connect, + is_timeout, + }); + } + Err(HttpRequestExecError::Unauthenticated { + output, + metadata, + reason, + }) => { + if !req_data.auth_refreshed { + self.auth.refresh_auth().await.map_err(|err| { + HttpRequestExecError::RefreshAuth(err.to_string(), metadata.clone()) + })?; + req_data.register_refresh_auth(); + continue; + } + return Err(HttpRequestExecError::Unauthenticated { + output, + metadata, + reason, + }); + } + Err(err) => return Err(err), + } + } + } + + /// Send a HTTPS request + async fn execute_request( + &self, + req_data: &RequestData, + ) -> std::result::Result { + let url = format!("{}{}", self.base_url, req_data.path); + + let mut req_headers = self.headers.clone(); + + if let Some(headers) = &req_data.headers { + req_headers.extend(headers.clone()); + } + + let metadata = HttpMetadata { + method: req_data.method.clone(), + path: req_data.path.clone(), + }; + + if req_data.auth { + let auth = + self.auth.get_auth().await.map_err(|err| { + HttpRequestExecError::GetAuth(err.to_string(), metadata.clone()) + })?; + req_headers.extend(auth); + } + + let mut request_builder = self + .http_client + .request(req_data.method.clone(), &url) + .headers(req_headers); + + if let Some(q) = &req_data.query { + request_builder = request_builder.query(q); + } + + if let Some(body) = &req_data.body { + request_builder = body(request_builder); + } + + let response = + request_builder + .send() + .await + .map_err(|err| HttpRequestExecError::Reqwest { + message: err.to_string(), + metadata: metadata.clone(), + is_connect: err.is_connect(), + is_timeout: err.is_timeout(), + })?; + + match handle_error_raw(response, &req_data.method, &req_data.path).await { + Ok(response) => Ok(ClientResponse::new(response, metadata)), + Err(err) => Err(err), + } + } +} diff --git a/pkg/client-http/src/response.rs b/pkg/client-http/src/response.rs new file mode 100644 index 0000000..96b0256 --- /dev/null +++ b/pkg/client-http/src/response.rs @@ -0,0 +1 @@ +pub use http_interface::response::*; diff --git a/pkg/client-http/src/util.rs b/pkg/client-http/src/util.rs new file mode 100644 index 0000000..0254fb3 --- /dev/null +++ b/pkg/client-http/src/util.rs @@ -0,0 +1,54 @@ +use serde::Serialize; +use serde_json::{Map, Value}; + +/// Converts a serializable struct into a vector of key-value pairs for use in query parameters. +/// This function skips None values in the serialized representation. +/// +/// # Examples +/// +/// ``` +/// use serde::Serialize; +/// use client_http::serde_to_query_params; +/// +/// #[derive(Serialize)] +/// struct MyQuery { +/// id: Option, +/// name: String, +/// filter: Option, +/// } +/// +/// let query = MyQuery { +/// id: Some(123), +/// name: "test".to_string(), +/// filter: None, +/// }; +/// +/// let params = serde_to_query_params(&query); +/// // Results in: [("id", "123"), ("name", "test")] +/// ``` +pub fn serde_to_query_params(value: &T) -> Vec<(String, String)> { + let json = serde_json::to_value(value).unwrap_or(Value::Null); + + match json { + Value::Object(map) => flatten_json_object(map), + _ => Vec::new(), + } +} + +/// Flattens a JSON object into key-value pairs, skipping null/None values +fn flatten_json_object(map: Map) -> Vec<(String, String)> { + map.into_iter() + .filter_map(|(key, value)| match value { + Value::Null => None, + Value::String(s) => Some((key, s)), + Value::Number(n) => Some((key, n.to_string())), + Value::Bool(b) => Some((key, b.to_string())), + _ => Some((key, value.to_string())), + }) + .collect() +} + +/// Waits for a specified number of seconds. +pub(crate) async fn wait_for_secs(seconds: u64) { + tokio::time::sleep(tokio::time::Duration::from_secs(seconds)).await; +} diff --git a/pkg/constants/Cargo.toml b/pkg/constants/Cargo.toml new file mode 100644 index 0000000..97216b3 --- /dev/null +++ b/pkg/constants/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "constants" +version = "0.1.0" +edition = "2024" + +[dependencies] +workspace-hack.workspace = true diff --git a/pkg/constants/README.md b/pkg/constants/README.md new file mode 100644 index 0000000..f7eb61a --- /dev/null +++ b/pkg/constants/README.md @@ -0,0 +1,15 @@ +# Constants + +Shared constants across the zk-rollup system. + +## Overview + +This package centralizes system-wide constants for the implementation. + +## Features + +- System-wide constant definitions +- Type-safe constant access +- Shared configuration values +- Protocol parameters + diff --git a/pkg/constants/src/lib.rs b/pkg/constants/src/lib.rs new file mode 100644 index 0000000..b67c230 --- /dev/null +++ b/pkg/constants/src/lib.rs @@ -0,0 +1,20 @@ +/// Depth of the sparse merkle tree, a smaller tree increases the +/// likihood of collisions +pub const MERKLE_TREE_DEPTH: usize = 161; + +pub const UTXO_INPUTS: usize = 2; +pub const UTXO_OUTPUTS: usize = 2; + +pub const UTXO_AGG_NUMBER: usize = 3; +pub const UTXO_AGG_AGG_NUMBER: usize = 2 * UTXO_AGG_NUMBER; + +pub const UTXO_AGG_LEAVES: usize = UTXO_AGG_NUMBER * (UTXO_INPUTS + UTXO_OUTPUTS); + +/// Personalisation to blake to increase entropy +pub const BLAKE_PERSONALISATION: &[u8; 13] = b"Polybase_Seed"; + +/// Extends PSI entropy +pub const NOTE_RCM_EXT: u8 = 0; + +/// The key for the noir Utxo circuit +pub const UTXO_KEY_BYTES: &[u8] = include_bytes!("../../../fixtures/circuits/utxo/key"); diff --git a/pkg/contextful-macros/Cargo.toml b/pkg/contextful-macros/Cargo.toml new file mode 100644 index 0000000..e9b595e --- /dev/null +++ b/pkg/contextful-macros/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "contextful-macros" +version = "0.1.0" +edition = "2024" +license = "MIT OR Apache-2.0" +description = "Derive macros for contextful" +repository = "https://github.com/polybase/zk-rollup" + +[lib] +proc-macro = true + +[dependencies] +quote = { workspace = true } +syn = { workspace = true, features = ["full"] } +workspace-hack.workspace = true diff --git a/pkg/contextful-macros/src/lib.rs b/pkg/contextful-macros/src/lib.rs new file mode 100644 index 0000000..73fd955 --- /dev/null +++ b/pkg/contextful-macros/src/lib.rs @@ -0,0 +1,63 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use quote::quote; +use syn::{DeriveInput, Path, Token, parse_macro_input, punctuated::Punctuated}; + +#[proc_macro_derive(FromContextful, attributes(contextful))] +pub fn derive_from_contextful(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = &input.ident; + + let mut map_fns = Vec::new(); + + // If the source error is already this enum, discard the context and return it + // directly to avoid nested Internal(InternalError(...)) wrappers. + // it works like a map function fn(Contextful<#name>) -> #name + map_fns.push(syn::parse_quote! { ::contextful::Contextful::<#name>::into_source }); + + for attr in &input.attrs { + if !attr.path().is_ident("contextful") { + continue; + } + + let paths = match attr.parse_args_with(Punctuated::::parse_terminated) { + Ok(paths) => paths, + Err(err) => return err.to_compile_error().into(), + }; + + for path in paths { + map_fns.push(path); + } + } + + let checks = map_fns.iter().map(|fn_path| { + quote! { + // SAFETY: We just constructed the InternalError from a Contextful above, + // so there is exactly one strong reference to the Arc. + let err = match unsafe { err.downcast() } { + Ok(casted) => return #fn_path(casted).into(), + Err(err) => err, + }; + } + }); + + let expanded = quote! { + impl From<::contextful::Contextful> for #name + where + E: std::error::Error + Send + Sync + 'static, + { + fn from(error: ::contextful::Contextful) -> Self { + fn map_contextful_error(err: ::contextful::InternalError) -> #name { + #(#checks)* + + #name::Internal(err) + } + + map_contextful_error(::contextful::InternalError::from(error)) + } + } + }; + + expanded.into() +} diff --git a/pkg/contextful/Cargo.toml b/pkg/contextful/Cargo.toml new file mode 100644 index 0000000..ec0c526 --- /dev/null +++ b/pkg/contextful/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "contextful" +version = "0.1.0" +edition = "2024" +license = "MIT OR Apache-2.0" +description = "Result::context() that wraps the error as Contextful (usable with #[from])" +repository = "https://github.com/polybase/zk-rollup" + +[dependencies] +serde = { workspace = true } +contextful-macros = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +serde_json = { workspace = true } +thiserror = { workspace = true } diff --git a/pkg/contextful/README.md b/pkg/contextful/README.md new file mode 100644 index 0000000..0e17cf4 --- /dev/null +++ b/pkg/contextful/README.md @@ -0,0 +1,66 @@ +# contextful + +Utilities for wrapping error values with human-friendly context that preserves the original source error. The crate exposes a lightweight `Contextful` wrapper together with extension traits that make attaching context ergonomic in the places where you already return `Result` values or need to rewrap a bare `E`. + +## Overview + +`Contextful` stores a context message alongside an underlying error. It implements `std::error::Error`, `Display`, `Debug`, `Serialize`, and `Deserialize`, making it suitable for propagating through error enums or reporting pipelines. + +Import the prelude to get the extension traits: + +```rust +use contextful::prelude::*; +``` + +## API + +### `Contextful` + +- Construct via `Contextful::new(msg, err)` +- Access pieces with `context_message()`, `source_ref()`, or `into_parts()` +- Map the inner error with `map_source` + +### `ResultContextExt` + +Adds `.context(msg)`, `.with_context(|| msg)`, and `.without_context()` to any `Result` so you can attach context right where the `?` operator would otherwise return the bare error. + +```rust +use contextful::ResultContextExt; + +fn read_user(id: i64) -> Result> { + repo.fetch(id).context("load user by id") +} + +fn parse_user(input: &str) -> Result> { + Parser::new(input).with_context(|| format!("parse user payload `{input}`")) +} +``` + +### `ErrorContextExt` + +Adds `.wrap_err(msg)`, `.wrap_err_with(|| msg)`, and `.without_context()` to any error value. This is ideal when you already have an `E` (for example after matching on an enum variant) and need to rewrap it before returning. + +```rust +use contextful::ErrorContextExt; + +fn reconcile(user: User) -> Result<(), Contextful> { + match validate(user) { + Ok(()) => Ok(()), + Err(err) => Err(err.wrap_err("validate user before reconcile")), + } +} + +fn call_external() -> Result<(), Contextful> { + let err = ExternalError::Timeout; + Err(err.wrap_err_with(|| format!("external timeout at {}", chrono::Utc::now()))) +} +``` + +`wrap_err` evaluates its message eagerly. `wrap_err_with` only evaluates the closure when the error is wrapped, which helps avoid formatting costs in success paths. + +## Best Practices + +- Use `ResultContextExt` when working with a `Result` and let the trait handle wrapping automatically. +- Use `ErrorContextExt` when you are holding a bare error value. +- Keep context strings concise but actionable. Include identifiers (user id, external resource) that aid debugging. +- Propagate `Contextful` variants through your error enums using `#[from]` to preserve error chains. diff --git a/pkg/contextful/src/internal_error.rs b/pkg/contextful/src/internal_error.rs new file mode 100644 index 0000000..9cb0728 --- /dev/null +++ b/pkg/contextful/src/internal_error.rs @@ -0,0 +1,157 @@ +use core::fmt::{self, Display, Formatter}; +use std::{error::Error, io, sync::Arc}; + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use crate::Contextful; + +/// Wrapper for internal errors stored as contextful dynamic errors. +/// +/// Uses `Arc` internally to allow cloning without copying the underlying error. +#[derive(Debug, Clone)] +pub struct InternalError { + context: Box, + source: Arc>, +} + +impl From> for InternalError +where + E: Error + Send + Sync + 'static, +{ + fn from(error: Contextful) -> Self { + let (context, source) = error.into_parts(); + Self { + context, + source: Arc::new(Box::new(source) as Box), + } + } +} + +impl Display for InternalError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if self.context.is_empty() { + write!(f, "{}", self.source) + } else { + write!(f, "{}: {}", self.context, self.source) + } + } +} + +impl Error for InternalError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + Some(&**self.source) + } +} + +impl InternalError { + /// Attempt to downcast the internal error to a specific type. + /// + /// # Safety + /// + /// The caller must ensure that this `InternalError` has not been cloned, + /// i.e., there is only one strong reference to the inner `Arc`. This is + /// automatically true immediately after constructing the error via + /// `InternalError::from(contextful_error)`. + /// + /// If there are multiple references, the downcast will fail and return + /// the original error unchanged. + pub unsafe fn downcast(self) -> Result, InternalError> + where + E: Error + Send + Sync + 'static, + { + let InternalError { context, source } = self; + + match Arc::try_unwrap(source) { + Ok(boxed) => match boxed.downcast::() { + Ok(source) => Ok(Contextful { context, source }), + Err(boxed) => Err(InternalError { + context, + source: Arc::new(boxed), + }), + }, + Err(arc) => Err(InternalError { + context, + source: arc, + }), + } + } + + /// Attempt to downcast a reference to the internal error to a specific type. + /// + /// This is safe because it only returns a reference and doesn't require + /// exclusive ownership of the `Arc`. + pub fn downcast_ref(&self) -> Option<&E> + where + E: Error + Send + Sync + 'static, + { + (**self.source).downcast_ref::() + } + + /// Attempt to downcast a reference by walking the error source chain. + /// + /// This recursively checks the current error and all its sources until + /// it finds an error of the specified type or reaches the end of the chain. + pub fn recursive_downcast_ref(&self) -> Option<&E> + where + E: Error + Send + Sync + 'static, + { + let mut current: &(dyn Error + 'static) = &**self.source; + loop { + if let Some(e) = current.downcast_ref::() { + return Some(e); + } + current = current.source()?; + } + } + + /// Access the context message. + pub fn context_message(&self) -> &str { + &self.context + } + + /// Access the source error. + pub fn source_ref(&self) -> &(dyn Error + Send + Sync + 'static) { + &**self.source + } +} + +impl Serialize for InternalError { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + #[derive(Serialize)] + struct InternalErrorSer<'a> { + context: &'a str, + source: String, + } + + let helper = InternalErrorSer { + context: &self.context, + source: self.source.to_string(), + }; + + helper.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for InternalError { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + struct InternalErrorDe { + context: String, + source: String, + } + + let InternalErrorDe { context, source } = InternalErrorDe::deserialize(deserializer)?; + let source = + Arc::new(Box::new(io::Error::other(source)) as Box); + Ok(Self { + context: context.into_boxed_str(), + source, + }) + } +} diff --git a/pkg/contextful/src/lib.rs b/pkg/contextful/src/lib.rs new file mode 100644 index 0000000..1fa2e48 --- /dev/null +++ b/pkg/contextful/src/lib.rs @@ -0,0 +1,270 @@ +// lint-long-file-override allow-max-lines=270 + +extern crate self as contextful; + +use core::fmt::{self, Display, Formatter}; +use std::ops::Deref; + +pub use contextful_macros::FromContextful; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +mod internal_error; + +pub use internal_error::InternalError; +/// Error wrapper that adds a human-friendly context while preserving the +/// original error as its source. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Contextful { + context: Box, + source: Box, +} + +impl Contextful { + /// Construct a contextful error directly from a context string and source error. + pub fn new(context: impl Into, source: E) -> Self { + Self { + context: context.into().into_boxed_str(), + source: Box::new(source), + } + } + + /// Access the context string. + pub fn context_message(&self) -> &str { + &self.context + } + + /// Access the original error. + pub fn source_ref(&self) -> &E { + &self.source + } + + /// Consume and split into parts. + pub fn into_parts(self) -> (Box, E) { + let Contextful { context, source } = self; + (context, *source) + } + + /// Consume and return the source error, discarding the context. + pub fn into_source(self) -> E { + *self.source + } + + /// Map the inner error into a different type while preserving the context message. + pub fn map_source(self, f: impl FnOnce(E) -> F) -> Contextful { + let (context, source) = self.into_parts(); + Contextful { + context, + source: Box::new(f(source)), + } + } + + fn without_context(source: E) -> Self { + Self { + context: Box::from(""), + source: Box::new(source), + } + } + + /// Clone with a new source error. + pub fn clone_with_source(&self, source: F) -> Contextful { + Contextful { + context: self.context.clone(), + source: Box::new(source), + } + } +} + +impl Deref for Contextful { + type Target = E; + + fn deref(&self) -> &Self::Target { + &self.source + } +} + +impl From for Contextful { + fn from(source: E) -> Self { + Self::without_context(source) + } +} + +impl Display for Contextful +where + E: Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + if self.context.is_empty() { + write!(f, "{}", self.source) + } else { + write!(f, "{}: {}", self.context, self.source) + } + } +} + +impl std::error::Error for Contextful +where + E: std::error::Error + 'static, +{ + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&*self.source) + } +} + +impl Serialize for Contextful +where + E: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + #[derive(Serialize)] + struct ContextfulSer<'a, E> { + context: &'a str, + source: &'a E, + } + + let helper = ContextfulSer { + context: &self.context, + source: &self.source, + }; + + helper.serialize(serializer) + } +} + +impl<'de, E> Deserialize<'de> for Contextful +where + E: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(untagged)] + enum ContextfulDe { + WithContext { context: Box, source: E }, + Legacy(E), + } + + match ContextfulDe::deserialize(deserializer)? { + ContextfulDe::WithContext { context, source } => Ok(Self { + context, + source: Box::new(source), + }), + ContextfulDe::Legacy(source) => Ok(Self::without_context(source)), + } + } +} + +/// Extension trait adding `.context(...)` to any `Result`. +pub trait ResultContextExt { + /// Attach a context message that will be evaluated eagerly. + fn context(self, msg: impl Into) -> Result>; + + /// Contextful error without additional context + fn without_context(self) -> Result>; + + /// Attach a context message computed lazily only on error. + fn with_context(self, msg: M) -> Result> + where + M: FnOnce() -> String; +} + +impl ResultContextExt for Result { + fn context(self, msg: impl Into) -> Result> { + match self { + Ok(v) => Ok(v), + Err(e) => Err(Contextful { + context: msg.into().into_boxed_str(), + source: Box::new(e), + }), + } + } + + fn without_context(self) -> Result> { + match self { + Ok(v) => Ok(v), + Err(e) => Err(Contextful { + context: Box::from(""), + source: Box::new(e), + }), + } + } + + fn with_context(self, msg: M) -> Result> + where + M: FnOnce() -> String, + { + match self { + Ok(v) => Ok(v), + Err(e) => Err(Contextful { + context: msg().into_boxed_str(), + source: Box::new(e), + }), + } + } +} + +/// Extension trait adding `.wrap_err(...)` to any error value. +pub trait ErrorContextExt: Sized { + /// Wrap this error with an eagerly evaluated context message. + fn context(self, msg: impl Into) -> Contextful; + + /// Wrap this error with a lazily evaluated context message. + fn with_context(self, msg: M) -> Contextful + where + M: FnOnce() -> String; + + /// Wrap this error with an eagerly evaluated context message. + fn wrap_err(self, msg: impl Into) -> Contextful; + + /// Wrap this error with a lazily evaluated context message. + fn wrap_err_with(self, msg: M) -> Contextful + where + M: FnOnce() -> String; + + /// Wrap this error without additional context. + fn without_context(self) -> Contextful; +} + +impl ErrorContextExt for E +where + E: std::fmt::Debug + std::fmt::Display + Send + Sync + 'static, +{ + fn context(self, msg: impl Into) -> Contextful { + Contextful::new(msg, self) + } + + fn with_context(self, msg: M) -> Contextful + where + M: FnOnce() -> String, + { + Contextful::new(msg(), self) + } + + fn wrap_err(self, msg: impl Into) -> Contextful { + Contextful::new(msg, self) + } + + fn wrap_err_with(self, msg: M) -> Contextful + where + M: FnOnce() -> String, + { + Contextful::new(msg(), self) + } + + fn without_context(self) -> Contextful { + Contextful::from(self) + } +} + +/// A small prelude to import where you use `.context(...)`. +pub mod prelude { + pub use crate::{Contextful, ErrorContextExt, InternalError, ResultContextExt}; + pub use contextful_macros::FromContextful; +} + +#[cfg(test)] +mod tests; diff --git a/pkg/contextful/src/tests/flattening.rs b/pkg/contextful/src/tests/flattening.rs new file mode 100644 index 0000000..527ba6b --- /dev/null +++ b/pkg/contextful/src/tests/flattening.rs @@ -0,0 +1,40 @@ +use crate::prelude::*; + +#[derive(Debug, thiserror::Error, FromContextful)] +pub enum OtherError { + #[error("[contextful::tests::flattening] foo")] + Foo, + #[error("[contextful::tests::flattening] internal error")] + Internal(#[from] InternalError), +} + +#[test] +fn preserves_original_foo_variant_without_wrapping() { + let err = OtherError::Foo; + let res = OtherError::from(err.context("new context")); + + assert!(matches!(res, OtherError::Foo)); +} + +#[test] +fn preserves_original_internal_variant_without_wrapping() { + let io_err = std::io::Error::other("io error"); + let original = OtherError::from(io_err.context("inner")); + + let res = OtherError::from(original.context("new context")); + + assert!(matches!(res, OtherError::Internal(_))); +} + +#[test] +fn internal_preserves_original_context_discarding_new_context() { + let io_err = std::io::Error::other("io error"); + let err = OtherError::from(io_err.context("original")); + + let res = OtherError::from(err.context("discarded")); + + match res { + OtherError::Internal(ie) => assert_eq!(ie.context_message(), "original"), + _ => panic!("Expected Internal variant"), + } +} diff --git a/pkg/contextful/src/tests/mod.rs b/pkg/contextful/src/tests/mod.rs new file mode 100644 index 0000000..31889ed --- /dev/null +++ b/pkg/contextful/src/tests/mod.rs @@ -0,0 +1,283 @@ +// lint-long-file-override allow-max-lines=300 + +mod flattening; + +use std::io; + +use serde_json::json; + +use crate::{Contextful, ErrorContextExt, FromContextful, InternalError, ResultContextExt}; + +#[derive(Debug, thiserror::Error)] +#[error("[contextful::tests] demo error")] +struct Demo; + +#[derive(Debug, thiserror::Error)] +#[error("[contextful::tests] other error")] +struct Other; + +#[derive(Debug, thiserror::Error)] +enum Top { + #[error("[contextful::tests] demo error with context: {0}")] + Demo(#[from] Contextful), +} + +#[test] +fn it_wraps_and_formats() { + let res = Err::<(), Demo>(Demo); + let err = Top::from(res.context("doing a thing").unwrap_err()); + let s = err.to_string(); + assert!(s.contains("doing a thing")); + assert!(s.contains("demo error")); +} + +#[test] +fn test_deref() { + let res = Err::<(), Demo>(Demo); + let err = res.context("test context").unwrap_err(); + // Should be able to access Demo through deref + let _demo: &Demo = &err; +} + +#[test] +fn test_with_context_lazy() { + let mut called = false; + let res = Err::<(), Demo>(Demo); + let _err = res + .with_context(|| { + called = true; + "lazy context".to_string() + }) + .unwrap_err(); + assert!(called); +} + +#[test] +fn test_with_context_not_called_on_ok() { + let mut called = false; + let res = Ok::(42); + let val = res + .with_context(|| { + called = true; + "lazy context".to_string() + }) + .unwrap(); + assert!(!called); + assert_eq!(val, 42); +} + +#[test] +fn error_and_result_context_exts_work() { + let res = Err::<(), Demo>(Demo); + let err = res + .with_context(|| "result context".to_owned()) + .unwrap_err(); + + let wrapped = err.context("error context"); + assert_eq!(wrapped.context_message(), "error context"); + + let without_context = Demo.without_context(); + assert_eq!(without_context.context_message(), ""); +} + +#[test] +fn serde_preserves_context_and_handles_legacy() { + let err = Contextful::::new("ctx", 5); + let value = serde_json::to_value(&err).unwrap(); + assert_eq!(value, json!({ "context": "ctx", "source": 5 })); + + let with_context = serde_json::from_value::>(value).unwrap(); + assert_eq!(with_context.context_message(), "ctx"); + assert_eq!(*with_context, 5); + + let legacy = serde_json::from_value::>(json!(5)).unwrap(); + assert_eq!(legacy.context_message(), ""); + assert_eq!(*legacy, 5); +} + +#[test] +fn wrap_err_adds_context() { + let err = Demo.wrap_err("wrap err eager"); + assert_eq!(err.context_message(), "wrap err eager"); + assert_eq!( + err.to_string(), + "wrap err eager: [contextful::tests] demo error" + ); +} + +#[test] +fn wrap_err_with_invokes_closure_once() { + let mut calls = 0; + let err = Demo.wrap_err_with(|| { + calls += 1; + "lazy message".to_string() + }); + assert_eq!(calls, 1); + assert_eq!(err.context_message(), "lazy message"); + assert_eq!( + err.to_string(), + "lazy message: [contextful::tests] demo error" + ); +} + +#[test] +fn io_error_with_context_adds_context() { + let err = io::Error::other("io error"); + let wrapped = err.with_context(|| "io context".to_owned()); + assert_eq!(wrapped.context_message(), "io context"); + assert!(wrapped.to_string().contains("io error")); +} + +#[test] +fn internal_error_downcast_preserves_context() { + let res = Err::<(), Other>(Other); + let err = res.context("other context").unwrap_err(); + let internal = InternalError::from(err); + // SAFETY: We just constructed the InternalError, so there's only one reference. + let downcasted = unsafe { internal.downcast::() }.expect("expected downcast to succeed"); + assert_eq!(downcasted.context_message(), "other context"); +} + +#[derive(Debug, thiserror::Error, FromContextful)] +#[contextful(map_demo_error)] +enum TestError { + #[error("[contextful::tests] mapped demo error")] + Demo(Contextful), + #[error("[contextful::tests] internal")] + Internal(#[from] InternalError), +} + +fn map_demo_error(err: Contextful) -> TestError { + TestError::Demo(err) +} + +#[test] +fn test_contextful_map_error() { + let res = Err::<(), Demo>(Demo); + let ctx_err = res.context("foo").unwrap_err(); + let err = TestError::from(ctx_err); + + match err { + TestError::Demo(d) => { + assert_eq!(d.context_message(), "foo"); + } + _ => panic!("wrong variant"), + } +} + +#[derive(Debug, thiserror::Error, FromContextful)] +#[contextful(map_demo_error_multi)] +#[contextful(map_other_error)] +enum MultiMapError { + #[error("[contextful::tests] mapped demo error")] + Demo(Contextful), + #[error("[contextful::tests] mapped other error")] + Other(Contextful), + #[error("[contextful::tests] internal")] + Internal(#[from] InternalError), +} + +fn map_other_error(err: Contextful) -> MultiMapError { + MultiMapError::Other(err) +} + +fn map_demo_error_multi(err: Contextful) -> MultiMapError { + MultiMapError::Demo(err) +} + +#[test] +fn test_contextful_multiple_maps() { + let res = Err::<(), Other>(Other); + let ctx_err = res.context("other context").unwrap_err(); + let err = MultiMapError::from(ctx_err); + + match err { + MultiMapError::Other(other) => { + assert_eq!(other.context_message(), "other context"); + } + _ => panic!("wrong variant"), + } +} + +#[test] +fn internal_error_is_clone() { + let res = Err::<(), Other>(Other); + let err = res.context("clone context").unwrap_err(); + let internal = InternalError::from(err); + + let cloned = internal.clone(); + + assert_eq!(internal.context_message(), "clone context"); + assert_eq!(cloned.context_message(), "clone context"); + assert!(internal.to_string().contains("other error")); + assert!(cloned.to_string().contains("other error")); +} + +#[test] +fn internal_error_downcast_fails_with_multiple_refs() { + let res = Err::<(), Other>(Other); + let err = res.context("multi ref context").unwrap_err(); + let internal = InternalError::from(err); + + // Clone creates another reference + let _cloned = internal.clone(); + + // SAFETY: This is intentionally testing the failure case when there are + // multiple references. The downcast should fail and return the error. + let result = unsafe { internal.downcast::() }; + assert!(result.is_err(), "downcast should fail with multiple refs"); + + let returned_err = result.unwrap_err(); + assert_eq!(returned_err.context_message(), "multi ref context"); +} + +#[test] +fn internal_error_downcast_ref_works() { + let res = Err::<(), Other>(Other); + let err = res.context("ref context").unwrap_err(); + let internal = InternalError::from(err); + + // downcast_ref is safe and works even with clones + let cloned = internal.clone(); + + let ref1 = internal.downcast_ref::(); + let ref2 = cloned.downcast_ref::(); + + assert!(ref1.is_some(), "downcast_ref should succeed on original"); + assert!(ref2.is_some(), "downcast_ref should succeed on clone"); + + // Wrong type returns None + let wrong_type = internal.downcast_ref::(); + assert!( + wrong_type.is_none(), + "downcast_ref to wrong type should fail" + ); +} + +#[derive(Debug, thiserror::Error)] +#[error("[contextful::tests] wrapper error")] +struct Wrapper { + #[source] + inner: Other, +} + +#[test] +fn internal_error_recursive_downcast_ref_works() { + // Create a nested error: InternalError -> Wrapper -> Other + let wrapper = Wrapper { inner: Other }; + let res = Err::<(), Wrapper>(wrapper); + let err = res.context("wrapper context").unwrap_err(); + let internal = InternalError::from(err); + + // Direct downcast_ref finds Wrapper + assert!(internal.downcast_ref::().is_some()); + // But not Other (it's nested) + assert!(internal.downcast_ref::().is_none()); + + // recursive_downcast_ref finds both Wrapper and nested Other + assert!(internal.recursive_downcast_ref::().is_some()); + assert!(internal.recursive_downcast_ref::().is_some()); + + // Wrong type still returns None + assert!(internal.recursive_downcast_ref::().is_none()); +} diff --git a/pkg/contracts/Cargo.toml b/pkg/contracts/Cargo.toml index e526866..1768773 100644 --- a/pkg/contracts/Cargo.toml +++ b/pkg/contracts/Cargo.toml @@ -1,33 +1,35 @@ [package] name = "contracts" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] zk-primitives = { workspace = true } +element = { workspace = true } testutil = { workspace = true } +eth-util = { workspace = true } +contextful = { workspace = true } -color-eyre = { workspace = true } ethereum-types = { workspace = true } -eyre = { workspace = true } hex = { workspace = true } parking_lot = { workspace = true } rand = { workspace = true } rustc-hex = { workspace = true } secp256k1 = { workspace = true } -serde = { workspace = true } serde_json = { workspace = true } sha3 = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } web3 = { workspace = true } -clap = { workspace = true } tracing = { workspace = true } +workspace-hack.workspace = true [dev-dependencies] +zk-circuits = { workspace = true } +barretenberg-cli = { workspace = true } +hash = { workspace = true } expect-test = { workspace = true } secp256k1 = { workspace = true } smirk = { workspace = true } -zk-circuits = { workspace = true } -serial_test = { workspace = true } +reqwest = { workspace = true } diff --git a/pkg/contracts/README.md b/pkg/contracts/README.md index 104761f..b83bc71 100644 --- a/pkg/contracts/README.md +++ b/pkg/contracts/README.md @@ -48,8 +48,7 @@ Commands: Options: -p, --private-key [default: ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80] --rpc-url [default: http://localhost:8545] - --rollup-addr [default: 2279b7a0a67db372996a5fab50d91eaa73d2ebe6] --usdc-addr [default: 5fbdb2315678afecb367f032d93f642f64180aa3] -h, --help Print help -V, --version Print version -``` \ No newline at end of file +``` diff --git a/pkg/contracts/src/across.rs b/pkg/contracts/src/across.rs index 3cc661b..c91b7bb 100644 --- a/pkg/contracts/src/across.rs +++ b/pkg/contracts/src/across.rs @@ -1,23 +1,28 @@ -use crate::error::Result; +// lint-long-file-override allow-max-lines=300 use crate::Client; +use crate::error::Result; +use crate::util::calculate_domain_separator; use ethereum_types::U64; +use sha3::{Digest, Keccak256}; use testutil::eth::EthNode; use web3::{ contract::{ - tokens::{Tokenizable, Tokenize}, Contract, + tokens::{Tokenizable, Tokenize}, }, - ethabi, + ethabi::{self, Token, encode}, signing::{Key, SecretKey, SecretKeyRef}, transports::Http, types::{Address, FilterBuilder, H256, U256}, }; +#[derive(Debug)] pub struct AcrossWithAuthorizationContract { client: Client, contract: Contract, signer: SecretKey, signer_address: Address, + domain_separator: H256, address: Address, /// The ethereum block height used for all contract calls. /// If None, the latest block is used. @@ -30,6 +35,7 @@ impl AcrossWithAuthorizationContract { contract: Contract, signer: SecretKey, address: Address, + domain_separator: H256, ) -> Self { let signer_address = Key::address(&SecretKeyRef::new(&signer)); @@ -38,6 +44,7 @@ impl AcrossWithAuthorizationContract { contract, signer, signer_address, + domain_separator, address, block_height: None, } @@ -52,14 +59,28 @@ impl AcrossWithAuthorizationContract { self.address } - pub async fn load(client: Client, contract_address: &str, signer: SecretKey) -> Result { - let contract_json = include_str!("../../../eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.json"); + pub async fn load( + client: Client, + chain_id: u128, + contract_address: &str, + signer: SecretKey, + ) -> Result { + let contract_json = include_str!( + "../../../eth/artifacts/contracts/AcrossWithAuthorization.sol/AcrossWithAuthorization.json" + ); let contract = client.load_contract_from_str(contract_address, contract_json)?; + let domain_separator = calculate_domain_separator( + "AcrossWithAuthorization", + "1", + U256::from(chain_id), + contract_address.parse()?, + ); Ok(Self::new( client, contract, signer, contract_address.parse()?, + domain_separator, )) } @@ -67,7 +88,7 @@ impl AcrossWithAuthorizationContract { let contract_addr = "TODO"; let client = Client::from_eth_node(eth_node); - Self::load(client, contract_addr, signer).await + Self::load(client, 1337, contract_addr, signer).await } pub async fn call(&self, func: &str, params: impl Tokenize + Clone) -> Result { @@ -82,6 +103,112 @@ impl AcrossWithAuthorizationContract { .await } + #[allow(clippy::too_many_arguments)] + pub fn signature_for_deposit( + &self, + valid_after: U256, + valid_before: U256, + nonce: H256, + depositor: Address, + recipient: Address, + input_token: Address, + output_token: Address, + input_amount: U256, + output_amount: U256, + fee_amount: U256, + destination_chain_id: U256, + exclusive_relayer: Address, + quote_timestamp: u32, + fill_deadline: u32, + exclusivity_deadline: u32, + message: &[u8], + secret_key: &SecretKey, + ) -> [u8; 65] { + let digest = self.signature_msg_digest_for_deposit( + valid_after, + valid_before, + nonce, + depositor, + recipient, + input_token, + output_token, + input_amount, + output_amount, + fee_amount, + destination_chain_id, + exclusive_relayer, + quote_timestamp, + fill_deadline, + exclusivity_deadline, + message, + ); + + let signature = secp256k1::SECP256K1.sign_ecdsa_recoverable( + &secp256k1::Message::from_digest(digest), + &secp256k1::SecretKey::from_slice(&secret_key.secret_bytes()).expect("32 bytes"), + ); + let (recovery_id, signature_bytes) = signature.serialize_compact(); + let mut final_signature = [0u8; 65]; + final_signature[0..64].copy_from_slice(&signature_bytes[0..64]); + final_signature[64] = recovery_id.to_i32() as u8; + final_signature + } + + #[allow(clippy::too_many_arguments)] + pub fn signature_msg_digest_for_deposit( + &self, + valid_after: U256, + valid_before: U256, + nonce: H256, + depositor: Address, + recipient: Address, + input_token: Address, + output_token: Address, + input_amount: U256, + output_amount: U256, + fee_amount: U256, + destination_chain_id: U256, + exclusive_relayer: Address, + quote_timestamp: u32, + fill_deadline: u32, + exclusivity_deadline: u32, + message: &[u8], + ) -> [u8; 32] { + let deposit_v3_with_authorization_typehash = Keccak256::digest( + b"DepositV3WithAuthorization(uint256 validAfter,uint256 validBefore,bytes32 nonce,address depositor,address recipient,address inputToken,address outputToken,uint256 inputAmount,uint256 outputAmount,uint256 feeAmount,uint256 destinationChainId,address exclusiveRelayer,uint32 quoteTimestamp,uint32 fillDeadline,uint32 exclusivityDeadline,bytes message)" + ); + + let encoded_struct = encode(&[ + Token::FixedBytes(deposit_v3_with_authorization_typehash.to_vec()), + Token::Uint(valid_after), + Token::Uint(valid_before), + Token::FixedBytes(nonce.as_bytes().to_vec()), + Token::Address(depositor), + Token::Address(recipient), + Token::Address(input_token), + Token::Address(output_token), + Token::Uint(input_amount), + Token::Uint(output_amount), + Token::Uint(fee_amount), + Token::Uint(destination_chain_id), + Token::Address(exclusive_relayer), + Token::Uint(U256::from(quote_timestamp)), + Token::Uint(U256::from(fill_deadline)), + Token::Uint(U256::from(exclusivity_deadline)), + Token::FixedBytes(Keccak256::digest(message).to_vec()), + ]); + + let struct_hash = Keccak256::digest(&encoded_struct); + + let mut hasher = Keccak256::new(); + hasher.update(b"\x19\x01"); + hasher.update(self.domain_separator); + hasher.update(struct_hash); + let msg_hash = hasher.finalize(); + + msg_hash.into() + } + #[allow(clippy::too_many_arguments)] pub async fn deposit_v3_with_authorization( &self, @@ -96,6 +223,7 @@ impl AcrossWithAuthorizationContract { output_token: Address, input_amount: U256, output_amount: U256, + fee_amount: U256, destination_chain_id: U256, exclusive_relayer: Address, quote_timestamp: u32, @@ -131,6 +259,7 @@ impl AcrossWithAuthorizationContract { output_token.into_token(), input_amount.into_token(), output_amount.into_token(), + fee_amount.into_token(), destination_chain_id.into_token(), exclusive_relayer.into_token(), quote_timestamp.into_token(), @@ -157,7 +286,7 @@ impl AcrossWithAuthorizationContract { .topic_filter(topic_filter) .build(); - let logs = self.client.client().eth().logs(filter).await?; + let logs = self.client.logs(filter).await?; Ok(logs .into_iter() diff --git a/pkg/contracts/src/client.rs b/pkg/contracts/src/client.rs index ab501fd..c9a6acf 100644 --- a/pkg/contracts/src/client.rs +++ b/pkg/contracts/src/client.rs @@ -1,23 +1,38 @@ +// lint-long-file-override allow-max-lines=700 use std::{future::Future, time::Duration}; -use crate::Result; +use contextful::ResultContextExt; + +use crate::{Error, Result}; use ethereum_types::{Address, H256, U64}; use testutil::eth::EthNode; use tokio::time::interval; use web3::{ - contract::{tokens::Tokenize, Contract, Options}, + Web3, + contract::{Contract, Options, tokens::Tokenize}, ethabi, signing::SecretKey, transports::Http, - types::{Transaction, U256}, - Web3, + types::{Transaction, TransactionReceipt, U256}, }; +/// Configuration for different types of transaction confirmation requirements. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ConfirmationType { + /// Wait for transaction inclusion only (equivalent to current behavior). + Latest, + /// Wait for transaction inclusion plus N additional blocks for safety. + LatestPlus(u64), + /// Wait for transaction to be in a finalized block (chain-specific finality). + Finalised, +} + #[derive(Debug, Clone)] pub struct Client { client: Web3, minimum_gas_price: Option, pub use_latest_for_nonce: bool, + rpc_url: String, } impl Client { @@ -29,6 +44,7 @@ impl Client { client, minimum_gas_price, use_latest_for_nonce: false, + rpc_url: rpc.to_string(), } } @@ -65,10 +81,25 @@ impl Client { &self.client } + pub fn rpc_url(&self) -> &str { + &self.rpc_url + } + + pub fn with_latest_nonce(mut self) -> Self { + self.use_latest_for_nonce = true; + self + } + + pub async fn get_latest_block_height(&self) -> Result { + let block_number = self.client.eth().block_number().await?; + Ok(block_number) + } + pub async fn fast_gas_price(&self) -> Result { let gas_price: U256 = retry_on_network_failure(move || self.client.eth().gas_price()).await?; - let fast_gas_price = gas_price * 2; + let ten_percent = gas_price / 10; + let fast_gas_price = gas_price + ten_percent; match self.minimum_gas_price { Some(minimum_gas_price) if fast_gas_price < minimum_gas_price => Ok(minimum_gas_price), @@ -76,6 +107,39 @@ impl Client { } } + /// Returns the current chain id with network-failure retries. + pub async fn chain_id(&self) -> Result { + retry_on_network_failure(move || self.client.eth().chain_id()).await + } + + /// Returns the current chain id using the contracts error type. + pub async fn chain_id_contracts(&self) -> Result { + let chain_id = self.chain_id().await.context("fetch chain id")?; + Ok(chain_id) + } + + /// Returns the latest block number with network-failure retries. + pub async fn block_number(&self) -> Result { + retry_on_network_failure(move || self.client.eth().block_number()).await + } + + /// Returns the latest block number with instant network-failure retries. + pub async fn block_number_with_fast_retries(&self) -> Result { + retry_on_network_failure_instant(move || self.client.eth().block_number()).await + } + + /// Fetch logs for a given filter with network-failure retries. + pub async fn logs( + &self, + filter: web3::types::Filter, + ) -> Result, web3::Error> { + retry_on_network_failure({ + let filter = filter.clone(); + move || self.client.eth().logs(filter) + }) + .await + } + #[tracing::instrument(err, ret, skip(self))] pub async fn get_nonce( &self, @@ -169,28 +233,121 @@ impl Client { /// Wait for a transaction to be confirmed and returns the block number. /// /// Times out if a transaction has been unknown (not in mempool) for 60 seconds. + /// + /// The confirmation type determines when the transaction is considered confirmed: + /// - `Latest`: Returns immediately when transaction is included in any block + /// - `LatestPlus(n)`: Waits for transaction block + n additional confirmations + /// - `Finalised`: Waits for transaction to be in a finalized block #[tracing::instrument(err, skip(self))] - pub async fn wait_for_confirm(&self, txn_hash: H256, interval_period: Duration) -> Result { - let unknown_timeout = std::time::Instant::now() + Duration::from_secs(60); - + pub async fn wait_for_confirm( + &self, + txn_hash: H256, + interval_period: Duration, + confirmation_type: ConfirmationType, + ) -> Result { let mut interval = interval(interval_period); interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay); + // First, wait for transaction to be included in a block + let transaction_block_number = self + .wait_for_transaction_inclusion(txn_hash, &mut interval) + .await?; + + // Now apply confirmation type logic + match confirmation_type { + ConfirmationType::Latest => { + tracing::debug!( + ?txn_hash, + block_number = ?transaction_block_number, + "Transaction confirmed with Latest confirmation type" + ); + Ok(transaction_block_number) + } + ConfirmationType::LatestPlus(additional_blocks) => { + self.wait_for_additional_confirmations( + txn_hash, + transaction_block_number, + additional_blocks, + &mut interval, + ) + .await?; + Ok(transaction_block_number) + } + ConfirmationType::Finalised => { + self.wait_for_finalized_confirmation( + txn_hash, + transaction_block_number, + &mut interval, + ) + .await?; + Ok(transaction_block_number) + } + } + } + + /// Wait for a transaction receipt. + /// + /// Polls at the given interval. Returns Error::UnknownTransaction if the transaction is dropped. + pub async fn wait_for_receipt( + &self, + tx_hash: H256, + poll_interval: Duration, + timeout: Duration, + ) -> Result { + let start = std::time::Instant::now(); + + loop { + let receipt = + retry_on_network_failure(|| self.client.eth().transaction_receipt(tx_hash)).await?; + + if let Some(receipt) = receipt { + return Ok(receipt); + } + + let transaction = retry_on_network_failure(|| { + self.client + .eth() + .transaction(web3::types::TransactionId::Hash(tx_hash)) + }) + .await?; + + if transaction.is_none() { + return Err(Error::UnknownTransaction(tx_hash)); + } + + if start.elapsed() > timeout { + return Err(Error::Timeout); + } + + tokio::time::sleep(poll_interval).await; + } + } + + /// Wait for a transaction to be included in a block. + /// Returns the block number when the transaction is included. + /// Times out if the transaction has been unknown for 60 seconds. + async fn wait_for_transaction_inclusion( + &self, + txn_hash: H256, + interval: &mut tokio::time::Interval, + ) -> Result { + let unknown_timeout = std::time::Instant::now() + Duration::from_secs(60); + loop { interval.tick().await; - let tx = retry_on_network_failure(move || { + let txn = retry_on_network_failure(move || { self.client .eth() .transaction(web3::types::TransactionId::Hash(txn_hash)) }) .await?; - match tx { + match txn { None => { // Transaction doesn't exist / is unknown if std::time::Instant::now() > unknown_timeout { - return Err(crate::Error::UnknownTransaction(txn_hash)); + return Err(Error::UnknownTransaction(txn_hash)); } } Some(Transaction { @@ -202,15 +359,104 @@ impl Client { block_number: Some(block_number), .. }) => { - // Transaction is confirmed + // Transaction is included in a block return Ok(block_number); } } } } + + /// Wait for additional block confirmations after transaction inclusion. + /// Waits until the latest block number is >= transaction_block + additional_blocks. + async fn wait_for_additional_confirmations( + &self, + txn_hash: H256, + transaction_block_number: U64, + additional_blocks: u64, + interval: &mut tokio::time::Interval, + ) -> Result<()> { + tracing::debug!( + ?txn_hash, + block_number = ?transaction_block_number, + additional_blocks, + "Waiting for additional block confirmations" + ); + + let required_block_number = transaction_block_number + U64::from(additional_blocks); + + loop { + interval.tick().await; + + let latest_block = + retry_on_network_failure(|| self.client.eth().block_number()).await?; + + if latest_block >= required_block_number { + tracing::debug!( + ?txn_hash, + transaction_block = ?transaction_block_number, + latest_block = ?latest_block, + "Transaction confirmed with required additional blocks" + ); + return Ok(()); + } + + tracing::trace!( + ?txn_hash, + transaction_block = ?transaction_block_number, + latest_block = ?latest_block, + required_block = ?required_block_number, + "Waiting for additional confirmations" + ); + } + } + + /// Wait for the transaction's block to be finalized. + /// Waits until the finalized block number is >= transaction_block_number. + async fn wait_for_finalized_confirmation( + &self, + txn_hash: H256, + transaction_block_number: U64, + interval: &mut tokio::time::Interval, + ) -> Result<()> { + tracing::debug!( + ?txn_hash, + block_number = ?transaction_block_number, + "Waiting for finalized block confirmation" + ); + + loop { + interval.tick().await; + + let finalized_block = retry_on_network_failure(|| { + self.client.eth().block(web3::types::BlockId::Number( + web3::types::BlockNumber::Finalized, + )) + }) + .await?; + + if let Some(finalized_block) = finalized_block + && let Some(finalized_number) = finalized_block.number + && finalized_number >= transaction_block_number + { + tracing::debug!( + ?txn_hash, + transaction_block = ?transaction_block_number, + finalized_block = ?finalized_number, + "Transaction confirmed in finalized block" + ); + return Ok(()); + } + + tracing::trace!( + ?txn_hash, + transaction_block = ?transaction_block_number, + "Waiting for block to be finalized" + ); + } + } } -trait IsNetworkFailure { +pub(crate) trait IsNetworkFailure { fn is_network_failure(&self) -> bool; } @@ -229,17 +475,11 @@ impl IsNetworkFailure for web3::contract::Error { } } -/// Retries 4 times for a maximum of 16s. -async fn retry_on_network_failure>>( +async fn retry_internal>>( f: impl FnOnce() -> Fut + Clone, -) -> Result { - const DELAYS: &[Duration] = &[ - Duration::from_secs(1), - Duration::from_secs(5), - Duration::from_secs(10), - ]; - - for (i, delay) in DELAYS + delays: &[Duration], +) -> std::result::Result { + for (i, delay) in delays .iter() .chain(std::iter::once(&Duration::ZERO)) .enumerate() @@ -247,7 +487,7 @@ async fn retry_on_network_failure>, +>( + f: impl FnOnce() -> Fut + Clone, +) -> std::result::Result { + const DELAYS: &[Duration] = &[ + Duration::from_secs(1), + Duration::from_secs(5), + Duration::from_secs(10), + ]; + retry_internal(f, DELAYS).await +} + +/// Retries 4 times with minimal delay on transport-level failures. +pub(crate) async fn retry_on_network_failure_instant< + T, + E: IsNetworkFailure, + Fut: Future>, +>( + f: impl FnOnce() -> Fut + Clone, +) -> std::result::Result { + const DELAYS: &[Duration] = &[Duration::ZERO; 3]; + retry_internal(f, DELAYS).await +} + #[cfg(test)] mod tests { - use std::sync::{atomic::AtomicU16, Arc}; + use std::sync::{Arc, atomic::AtomicU16}; use web3::error::Error; use web3::error::TransportError; + use super::ConfirmationType; + #[tokio::test] async fn test_retry_on_network_failure() { let gen_result = |succeed_at_call_count| async move { @@ -311,4 +581,90 @@ mod tests { assert!(elapsed < std::time::Duration::from_millis(1), "{elapsed:?}"); } } + + #[tokio::test] + async fn test_retry_on_network_failure_instant() { + let gen_result = |succeed_at_call_count| async move { + let call_count = Arc::new(AtomicU16::new(0)); + + super::retry_on_network_failure_instant(move || { + let call_count = Arc::clone(&call_count); + async move { + let call_count = + call_count.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + 1; + if call_count == succeed_at_call_count { + Ok(()) + } else { + Err(Error::Transport(TransportError::Code(call_count))) + } + } + }) + .await + }; + + { + // Never succeed, but should fail fast + let start = std::time::Instant::now(); + let result = gen_result(u16::MAX).await; + let elapsed = start.elapsed(); + + assert!( + matches!(&result, Err(Error::Transport(TransportError::Code(4)))), + "{result:?}" + ); + // 4 attempts * 0s sleep ~= 0s. Allow some buffer for scheduling. + assert!( + elapsed < std::time::Duration::from_millis(50), + "{elapsed:?}" + ); + } + } + + #[test] + fn test_confirmation_type_eq() { + assert_eq!(ConfirmationType::Latest, ConfirmationType::Latest); + assert_eq!( + ConfirmationType::LatestPlus(5), + ConfirmationType::LatestPlus(5) + ); + assert_eq!(ConfirmationType::Finalised, ConfirmationType::Finalised); + + assert_ne!(ConfirmationType::Latest, ConfirmationType::LatestPlus(0)); + assert_ne!( + ConfirmationType::LatestPlus(5), + ConfirmationType::LatestPlus(10) + ); + assert_ne!(ConfirmationType::Latest, ConfirmationType::Finalised); + } + + #[test] + fn test_confirmation_type_clone() { + let latest = ConfirmationType::Latest; + let latest_cloned = latest.clone(); + assert_eq!(latest, latest_cloned); + + let latest_plus = ConfirmationType::LatestPlus(42); + let latest_plus_cloned = latest_plus.clone(); + assert_eq!(latest_plus, latest_plus_cloned); + + let finalised = ConfirmationType::Finalised; + let finalised_cloned = finalised.clone(); + assert_eq!(finalised, finalised_cloned); + } + + #[test] + fn test_confirmation_type_debug() { + let latest = ConfirmationType::Latest; + let latest_debug = format!("{latest:?}"); + assert!(latest_debug.contains("Latest")); + + let latest_plus = ConfirmationType::LatestPlus(20); + let latest_plus_debug = format!("{latest_plus:?}"); + assert!(latest_plus_debug.contains("LatestPlus")); + assert!(latest_plus_debug.contains("20")); + + let finalised = ConfirmationType::Finalised; + let finalised_debug = format!("{finalised:?}"); + assert!(finalised_debug.contains("Finalised")); + } } diff --git a/pkg/contracts/src/constants.rs b/pkg/contracts/src/constants.rs index 94519bb..9353ab6 100644 --- a/pkg/contracts/src/constants.rs +++ b/pkg/contracts/src/constants.rs @@ -1,9 +1 @@ -// Count of aggregation instances, needed to prove verification -// of aggregated proof -pub const AGG_INSTANCES: usize = 12; - -/// Number of UTXOs to be verified in the aggregated proof -pub const UTXO_N: usize = 6; - -/// Number of inputs per UTXO -pub const UTXO_INPUTS: usize = 3; +pub const AGG_FINAL_MESSAGES: usize = 1000; diff --git a/pkg/contracts/src/eip7702.rs b/pkg/contracts/src/eip7702.rs new file mode 100644 index 0000000..f9cd58c --- /dev/null +++ b/pkg/contracts/src/eip7702.rs @@ -0,0 +1,82 @@ +use crate::{Client, Result}; +use ethereum_types::U64; +use web3::contract::{Contract, tokens::Tokenizable}; +use web3::transports::Http; +use web3::types::{Address, FilterBuilder, H256, U256}; + +/// EIP-7702 SimpleAccount helper for idempotency queries +#[derive(Debug, Clone)] +pub struct Eip7702Account { + client: Client, + contract: Contract, + address: Address, + /// Optional fixed block height for consistent queries + block_height: Option, +} + +impl Eip7702Account { + pub fn new(client: Client, contract: Contract, address: Address) -> Self { + Self { + client, + contract, + address, + block_height: None, + } + } + + pub async fn load(client: Client, account_addr: &str) -> Result { + let contract_json = include_str!( + "../../../eth/artifacts/contracts/Eip7702SimpleAccount.sol/Eip7702SimpleAccount.json" + ); + let contract = client.load_contract_from_str(account_addr, contract_json)?; + Ok(Self::new(client, contract, account_addr.parse()?)) + } + + pub fn at_height(mut self, block_height: Option) -> Self { + self.block_height = block_height.map(|x| x.into()); + self + } + + pub fn address(&self) -> Address { + self.address + } + + /// Check if a meta nonce was used by scanning the NonceUsed event; returns txn hash if found. + /// + /// Contract ABI: NonceUsed(uint256 indexed nonce) + pub async fn nonce_used_txn(&self, nonce: U256) -> Result> { + let event = self.contract.abi().event("NonceUsed")?; + let topic_filter = web3::ethabi::RawTopicFilter { + topic0: web3::ethabi::Topic::This(nonce.into_token()), + // Event has a single indexed parameter; leave remaining topics unconstrained + topic1: web3::ethabi::Topic::Any, + topic2: web3::ethabi::Topic::Any, + }; + let tf = event.filter(topic_filter)?; + let filter = FilterBuilder::default() + .address(vec![self.address]) + .from_block(web3::types::BlockNumber::Earliest) + .to_block(web3::types::BlockNumber::Latest) + .topic_filter(tf) + .build(); + + let logs = self.client.logs(filter).await?; + Ok(logs.into_iter().filter_map(|l| l.transaction_hash).next()) + } + + /// Direct view call to isNonceUsed(uint256) + pub async fn is_nonce_used(&self, nonce: U256) -> Result { + let used: bool = self + .client + .query( + &self.contract, + "isNonceUsed", + (nonce,), + None, + Default::default(), + self.block_height.map(|x| x.into()), + ) + .await?; + Ok(used) + } +} diff --git a/pkg/contracts/src/empty_merkle_tree_root_hash.txt b/pkg/contracts/src/empty_merkle_tree_root_hash.txt index 461c1cd..d8f272d 100644 --- a/pkg/contracts/src/empty_merkle_tree_root_hash.txt +++ b/pkg/contracts/src/empty_merkle_tree_root_hash.txt @@ -1 +1 @@ -0x03b6dc0852dc266fa6e5d22290ce1d5a399cc316900cf683e158bd2e4590fe53 \ No newline at end of file +0577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff \ No newline at end of file diff --git a/pkg/contracts/src/erc20.rs b/pkg/contracts/src/erc20.rs new file mode 100644 index 0000000..685c2ed --- /dev/null +++ b/pkg/contracts/src/erc20.rs @@ -0,0 +1,59 @@ +use crate::{Client, Result}; +use ethereum_types::U64; +use web3::contract::Contract; +use web3::transports::Http; +use web3::types::{Address, U256}; + +const ERC20_BALANCE_OF_ARTIFACT: &str = r#"{"abi":[{"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]}"#; + +#[derive(Debug, Clone)] +pub struct ERC20Contract { + client: Client, + contract: Contract, + address: Address, + /// The ethereum block height used for all contract calls. + /// If None, the latest block is used. + block_height: Option, +} + +impl ERC20Contract { + pub fn new(client: Client, contract: Contract, address: Address) -> Self { + Self { + client, + contract, + address, + block_height: None, + } + } + + pub async fn load(client: Client, contract_addr: &str) -> Result { + let contract = client.load_contract_from_str(contract_addr, ERC20_BALANCE_OF_ARTIFACT)?; + Ok(Self::new(client, contract, contract_addr.parse()?)) + } + + pub fn at_height(&self, block_height: u64) -> Self { + Self { + block_height: Some(U64::from(block_height)), + ..self.clone() + } + } + + pub fn address(&self) -> Address { + self.address + } + + pub async fn balance(&self, owner: Address) -> Result { + let balance = self + .client + .query( + &self.contract, + "balanceOf", + (owner,), + None, + Default::default(), + self.block_height.map(|x| x.into()), + ) + .await?; + Ok(balance) + } +} diff --git a/pkg/contracts/src/error.rs b/pkg/contracts/src/error.rs index fe1fea7..a9ba46c 100644 --- a/pkg/contracts/src/error.rs +++ b/pkg/contracts/src/error.rs @@ -1,10 +1,14 @@ +use contextful::{FromContextful, InternalError}; use ethereum_types::H256; -#[derive(Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error, FromContextful)] pub enum Error { #[error("unknown transaction: {0}")] UnknownTransaction(H256), + #[error("[contracts] timeout")] + Timeout, + #[error("web3 error")] Web3(#[from] web3::Error), @@ -22,6 +26,13 @@ pub enum Error { #[error("tokio task join error")] TokioJoin(#[from] tokio::task::JoinError), + + // New variant for address parsing errors + #[error("invalid address: {0}")] + InvalidAddress(String), + + #[error("[contracts] internal error")] + Internal(#[from] InternalError), } pub type Result = std::result::Result; diff --git a/pkg/contracts/src/lib.rs b/pkg/contracts/src/lib.rs index ce83ca7..aaf03fb 100644 --- a/pkg/contracts/src/lib.rs +++ b/pkg/contracts/src/lib.rs @@ -1,10 +1,10 @@ -// This was stabilized in Rust 1.70 -#![feature(is_some_and)] #![deny(clippy::disallowed_methods)] mod across; mod client; mod constants; +mod eip7702; +mod erc20; mod error; mod rollup; #[cfg(test)] @@ -14,7 +14,9 @@ pub mod util; pub mod wallet; pub use across::AcrossWithAuthorizationContract; -pub use client::Client; +pub use client::{Client, ConfirmationType}; +pub use eip7702::Eip7702Account; +pub use erc20::ERC20Contract; pub use error::{Error, Result}; pub use rollup::RollupContract; pub use usdc::USDCContract; @@ -23,3 +25,5 @@ pub use web3::{ signing::SecretKey, types::{Address, H256, U256}, }; + +pub use secp256k1::SecretKey as Secp256k1SecretKey; diff --git a/pkg/contracts/src/rollup.rs b/pkg/contracts/src/rollup.rs index d562cb2..fe8b459 100644 --- a/pkg/contracts/src/rollup.rs +++ b/pkg/contracts/src/rollup.rs @@ -1,28 +1,33 @@ +// lint-long-file-override allow-max-lines=1200 use std::sync::Arc; use std::time::Duration; -use crate::constants::{AGG_INSTANCES, UTXO_INPUTS, UTXO_N}; +use crate::constants::AGG_FINAL_MESSAGES; use crate::error::Result; -use crate::util::convert_element_to_h256; -use crate::Client; -use ethereum_types::{H160, H256, U256, U64}; +use crate::util::{calculate_domain_separator, convert_element_to_h256}; +use crate::{Client, client::retry_on_network_failure}; +use element::Element; +use eth_util::Eth; +use ethereum_types::{H160, H256, U64, U256}; use parking_lot::RwLock; use secp256k1::{Message, SECP256K1}; use sha3::{Digest, Keccak256}; use testutil::eth::EthNode; use tracing::warn; -use web3::contract::tokens::{Tokenizable, TokenizableItem, Tokenize}; +use web3::contract::tokens::{Detokenize, Tokenizable, TokenizableItem, Tokenize}; use web3::ethabi::Token; use web3::futures::{Stream, StreamExt}; use web3::signing::SecretKeyRef; use web3::transports::Http; -use web3::types::FilterBuilder; +use web3::types::{BlockNumber, FilterBuilder}; use web3::{ contract::Contract, signing::{Key, SecretKey}, types::Address, }; -use zk_primitives::Element; + +pub const AGG_FINAL_VERIFICATION_KEY_HASH: &str = + "0x122d2ac7542fa020cbfff0836b5d0c30898330074b19869179bba49b5db69967"; #[derive(Clone, Debug, PartialEq, Eq)] pub struct ValidatorSet { @@ -30,6 +35,10 @@ pub struct ValidatorSet { pub valid_from: U256, } +#[expect( + dead_code, + reason = "Helper type for decoding burn events in downstream tooling" +)] #[derive(Debug, Clone, PartialEq, Eq)] pub struct Burn { pub to: H256, @@ -37,6 +46,63 @@ pub struct Burn { pub kind: H256, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Mint { + pub note_kind: Element, + pub amount: Element, + pub spent: bool, +} + +impl Tokenize for Mint { + fn into_tokens(self) -> Vec { + vec![ + self.note_kind.to_eth_u256().into_token(), + self.amount.to_eth_u256().into_token(), + ] + } +} + +impl Detokenize for Mint { + fn from_tokens(tokens: Vec) -> Result { + // Handle the case where we get a single Tuple token containing the three values + let (note_kind, amount, spent) = match &tokens[0] { + Token::Tuple(inner_tokens) => { + if inner_tokens.len() != 3 { + return Err(web3::contract::Error::InvalidOutputType( + "expected tuple with 3 elements".to_string(), + )); + } + ( + H256::from_token(inner_tokens[0].clone())?, + U256::from_token(inner_tokens[1].clone())?, + bool::from_token(inner_tokens[2].clone())?, + ) + } + _ => { + return Err(web3::contract::Error::InvalidOutputType( + "expected tuple token".to_string(), + )); + } + }; + + Ok(Mint { + note_kind: Element::from_be_bytes(note_kind.0), + amount: Element::from_u64_array(amount.0), + spent, + }) + } +} + +/// Represents a MintAdded event from the contract +#[derive(Debug, Clone)] +pub struct MintAddedEvent { + pub mint_hash: H256, + pub value: U256, + pub note_kind: H256, + pub transaction_hash: H256, + pub block_number: u64, +} + impl From<(H160, U256)> for Burn { fn from(item: (H160, U256)) -> Self { Self { @@ -47,6 +113,29 @@ impl From<(H160, U256)> for Burn { } } +/// EVM event emitted when a burn occurs (funds are sent from the Rollup contract). +/// Event will be triggered for burns and substituted burns. If a burn is substituted, +/// two events will be emitted. First for the substituted burn, and then again for the refund +/// to the substitutor. +#[derive(Debug)] +pub struct BurnedEvent { + /// The address of the token being burnt + pub token: Address, + /// The burn hash for the burn event + pub burn_hash: H256, + /// Whether the burn occurred due to a substitute + pub substitute: bool, + /// Recipient of the burn + pub recipient: Address, + /// Returns whether the burn was successful, it can be unsuccessful if + /// IERC20(token).transfer throws an error + pub success: bool, + /// The EVM block number this event was emitted in + pub block_number: Option, + /// The EVM txn hash this event was emitted in + pub txn_hash: Option, +} + impl From<(H256, U256, H256)> for Burn { fn from(item: (H256, U256, H256)) -> Self { Self { @@ -146,6 +235,7 @@ pub struct RollupContract { pub signer_address: Address, pub domain_separator: H256, pub validator_sets: Arc>>, + /// Address of rollup contract address: Address, /// The ethereum block height used for all contract calls. /// If None, the latest block is used. @@ -180,23 +270,20 @@ impl RollupContract { pub async fn load( client: Client, + chain_id: u128, rollup_contract_addr: &str, signer: SecretKey, ) -> Result { let contract_json = - include_str!("../../../eth/artifacts/contracts/rollup/RollupV6.sol/RollupV6.json"); + include_str!("../../../eth/artifacts/contracts/rollup3/RollupV1.sol/RollupV1.json"); let contract = client.load_contract_from_str(rollup_contract_addr, contract_json)?; - let domain_separator = client - .query::( - &contract, - "DOMAIN_SEPARATOR", - (), - None, - Default::default(), - None, - ) - .await?; + let domain_separator = calculate_domain_separator( + "Rollup", + "1", + U256::from(chain_id), + rollup_contract_addr.parse()?, + ); let self_ = Self::new( client, @@ -212,9 +299,9 @@ impl RollupContract { } pub async fn from_eth_node(eth_node: &EthNode, secret_key: SecretKey) -> Result { - let rollup_addr = "2279b7a0a67db372996a5fab50d91eaa73d2ebe6"; + let rollup_addr = "dc64a140aa3e981100a9beca4e685f962f0cf6c9"; let client = Client::from_eth_node(eth_node); - Self::load(client, rollup_addr, secret_key).await + Self::load(client, 1337, rollup_addr, secret_key).await } pub fn at_height(self, height: Option) -> Self { @@ -224,6 +311,11 @@ impl RollupContract { } } + pub fn with_latest_nonce(mut self) -> Self { + self.client.use_latest_for_nonce = true; + self + } + async fn load_all_validators(&self) -> Result<()> { let all_validators = self.get_validator_sets(0).await?; *self.validator_sets.write() = all_validators; @@ -231,21 +323,20 @@ impl RollupContract { } pub async fn worker(&self, interval: Duration) -> Result<()> { - let mut events = self.listen_for_validator_set_added(interval).await?.boxed(); - let this = self.clone(); - let mut consecutive_transport_error_count = 0; - const MAX_CONSECUTIVE_TRANSPORT_ERRORS: u64 = 5; - tokio::spawn(async move { + let handle = tokio::spawn(async move { + let mut events = this.listen_for_validator_set_added(interval).await?.boxed(); + let mut consecutive_transport_error_count = 0; + const MAX_CONSECUTIVE_TRANSPORT_ERRORS: u64 = 5; + while let Some(event) = events.next().await { let event = match event { Ok(event) => { consecutive_transport_error_count = 0; event - }, - Err(err @ web3::Error::Transport(_)) => - { + } + Err(err @ web3::Error::Transport(_)) => { // TODO: refactor this retry logic consecutive_transport_error_count += 1; @@ -267,7 +358,9 @@ impl RollupContract { Err(err @ web3::Error::Transport(_)) => { consecutive_transport_error_count += 1; - if consecutive_transport_error_count > MAX_CONSECUTIVE_TRANSPORT_ERRORS { + if consecutive_transport_error_count + > MAX_CONSECUTIVE_TRANSPORT_ERRORS + { return Err(err.into()); } @@ -277,7 +370,7 @@ impl RollupContract { "Received a transport error while trying to create a new event listener. Retrying." ); continue; - }, + } Err(err) => return Err(err.into()), } }; @@ -302,8 +395,9 @@ impl RollupContract { } Ok(()) - }) - .await? + }); + + handle.await? } pub async fn call(&self, func: &str, params: impl Tokenize + Clone) -> Result { @@ -323,18 +417,19 @@ impl RollupContract { pub async fn verify_block( &self, proof: &[u8], - agg_instances: [Element; AGG_INSTANCES], old_root: &Element, new_root: &Element, - // 6 utxo * 3 hashes per utxo - utxo_inputs: &[Element], + commit_hash: &Element, + // 6 utxo * 5 messages per utxo + utxo_messages: &[Element], + kzg: &[Element], other_hash: [u8; 32], height: u64, signatures: &[&[u8]], gas_per_burn_call: u128, ) -> Result { // Ensure we have the correct number of UTXO inputs - assert_eq!(utxo_inputs.len(), UTXO_N * UTXO_INPUTS); + assert_eq!(utxo_messages.len(), AGG_FINAL_MESSAGES); let signatures = signatures .iter() @@ -352,25 +447,29 @@ impl RollupContract { }) .collect::>(); - let utxo_hashes = utxo_inputs - .iter() - .map(convert_element_to_h256) - .map(|x| Token::FixedBytes(x.as_bytes().to_vec())) - .collect::>(); + let utxo_messages = utxo_messages.iter().map(convert_element_to_h256); + let kzg = kzg.iter().map(convert_element_to_h256); + + let mut public_inputs = vec![ + convert_element_to_h256(old_root), + convert_element_to_h256(new_root), + convert_element_to_h256(commit_hash), + ]; + public_inputs.extend(utxo_messages); + public_inputs.extend(kzg); let call_tx = self .call( - "verifyBlock2", + "verifyRollup", ( + U256::from(height), + AGG_FINAL_VERIFICATION_KEY_HASH + .parse::() + .expect("verification key is parsable"), web3::types::Bytes::from(proof), - agg_instances.map(|x| convert_element_to_h256(&x)), - convert_element_to_h256(old_root), - convert_element_to_h256(new_root), - Token::FixedArray(utxo_hashes), + public_inputs, H256::from_slice(&other_hash), - U256::from(height), Token::Array(signatures), - U256::from(gas_per_burn_call), ), ) .await?; @@ -378,22 +477,20 @@ impl RollupContract { Ok(call_tx) } - #[tracing::instrument(err, ret, skip(self, proof))] + #[tracing::instrument(err, ret, skip(self))] pub async fn mint( &self, - proof: &[u8], - commitment: &Element, + mint_hash: &Element, value: &Element, - source: &Element, + note_kind: &Element, ) -> Result { let call_tx = self .call( "mint", ( - web3::types::Bytes::from(proof), - convert_element_to_h256(commitment), + convert_element_to_h256(mint_hash), convert_element_to_h256(value), - convert_element_to_h256(source), + convert_element_to_h256(note_kind), ), ) .await?; @@ -402,13 +499,12 @@ impl RollupContract { } #[allow(clippy::too_many_arguments)] - #[tracing::instrument(err, ret, skip(self, proof))] + #[tracing::instrument(err, ret, skip(self))] pub async fn mint_with_authorization( &self, - proof: &[u8], - commitment: &Element, + mint_hash: &Element, value: &Element, - source: &Element, + note_kind: &Element, from: &Address, // unix timestamp valid_after: U256, @@ -431,10 +527,9 @@ impl RollupContract { .call( "mintWithAuthorization", ( - web3::types::Bytes::from(proof), - convert_element_to_h256(commitment), - convert_element_to_h256(value), - convert_element_to_h256(source), + mint_hash.to_h256(), + value.to_h256(), + note_kind.to_h256(), web3::types::H160::from_slice(from.as_bytes()), valid_after, valid_before, @@ -457,7 +552,7 @@ impl RollupContract { &self, commitment: Element, value: U256, - source: Element, + note_kind: Element, from: Address, valid_after: U256, valid_before: U256, @@ -468,7 +563,7 @@ impl RollupContract { let mint_sig_digest = self.signature_msg_digest_for_mint( commitment, value, - source, + note_kind, from, valid_after, valid_before, @@ -491,7 +586,7 @@ impl RollupContract { &self, commitment: Element, value: U256, - source: Element, + note_kind: Element, from: Address, valid_after: U256, valid_before: U256, @@ -499,7 +594,7 @@ impl RollupContract { ) -> [u8; 32] { let mut data = Vec::new(); let mint_with_authorization_typehash = Keccak256::digest( - "MintWithAuthorization(bytes32 commitment,bytes32 value,bytes32 source,address from,uint256 validAfter,uint256 validBefore,bytes32 nonce)" + "MintWithAuthorization(bytes32 commitment,bytes32 value,bytes32 kind,address from,uint256 validAfter,uint256 validBefore,bytes32 nonce)" .as_bytes(), ); data.extend_from_slice(&mint_with_authorization_typehash); @@ -507,7 +602,7 @@ impl RollupContract { let mut value_bytes = [0u8; 32]; value.to_big_endian(&mut value_bytes); data.extend_from_slice(&value_bytes[..]); - data.extend_from_slice(convert_element_to_h256(&source).as_bytes()); + data.extend_from_slice(convert_element_to_h256(¬e_kind).as_bytes()); data.extend_from_slice(H256::from(from).as_bytes()); let mut valid_after_bytes = [0u8; 32]; valid_after.to_big_endian(&mut valid_after_bytes); @@ -526,105 +621,9 @@ impl RollupContract { msg_hash.into() } - #[allow(clippy::too_many_arguments)] - #[tracing::instrument(err, ret, skip(self, proof))] - pub async fn burn( - &self, - to: &Address, - proof: &[u8], - nullifier: &Element, - value: &Element, - source: &Element, - sig: &Element, - ) -> Result { - let to = H160::from_slice(to.as_bytes()); - - let call_tx = self - .call( - "burn", - ( - to, - web3::types::Bytes::from(proof), - convert_element_to_h256(nullifier), - convert_element_to_h256(value), - convert_element_to_h256(source), - convert_element_to_h256(sig), - ), - ) - .await?; - - Ok(call_tx) - } - - #[allow(clippy::too_many_arguments)] - #[tracing::instrument(err, ret, skip(self, proof))] - pub async fn burn_to_address( - &self, - kind: &Element, - to: &Element, - proof: &[u8], - nullifier: &Element, - value: &Element, - source: &Element, - sig: &Element, - ) -> Result { - let call_tx = self - .call( - "burnToAddress", - ( - convert_element_to_h256(kind), - convert_element_to_h256(to), - web3::types::Bytes::from(proof), - convert_element_to_h256(nullifier), - convert_element_to_h256(value), - convert_element_to_h256(source), - convert_element_to_h256(sig), - ), - ) - .await?; - - Ok(call_tx) - } - - #[allow(clippy::too_many_arguments)] - #[tracing::instrument(err, ret, skip(self, proof))] - pub async fn burn_to_router( - &self, - kind: &Element, - msg_hash: &Element, - proof: &[u8], - nullifier: &Element, - value: &Element, - source: &Element, - sig: &Element, - router: &Address, - router_calldata: &[u8], - return_address: &Address, - ) -> Result { - let call_tx = self - .call( - "burnToRouter", - ( - convert_element_to_h256(kind), - convert_element_to_h256(msg_hash), - web3::types::Bytes::from(proof), - convert_element_to_h256(nullifier), - convert_element_to_h256(value), - convert_element_to_h256(source), - convert_element_to_h256(sig), - *router, - web3::types::Bytes::from(router_calldata), - *return_address, - ), - ) - .await?; - - Ok(call_tx) - } - #[tracing::instrument(err, ret, skip(self))] - pub async fn get_mint(&self, key: &Element) -> Result> { - let mint: U256 = self + pub async fn get_mint(&self, key: &Element) -> Result> { + let mint: Mint = self .client .query( &self.contract, @@ -636,38 +635,91 @@ impl RollupContract { ) .await?; - if mint == U256::zero() { + // Check if the mint is "empty" (both fields are zero) + if mint.note_kind == Element::ZERO && mint.amount == Element::ZERO { return Ok(None); } Ok(Some(mint)) } + /// Gets MintAdded events for a specific mint hash #[tracing::instrument(err, ret, skip(self))] - pub async fn has_burn(&self, key: &Element) -> Result { - let exists: bool = self - .client - .query( - &self.contract, - "hasBurn", - (convert_element_to_h256(key),), - None, - Default::default(), - self.block_height.map(|x| x.into()), + pub async fn get_mint_added_events( + &self, + mint_hash: &Element, + to_block: BlockNumber, + ) -> Result> { + // Create the event signature hash + let event_signature = H256::from_slice( + &Keccak256::digest(b"MintAdded(bytes32,uint256,bytes32)").as_slice()[0..32], + ); + + // Convert the mint_hash Element to H256 + let mint_hash_h256 = convert_element_to_h256(mint_hash); + + // Build the filter + let filter = FilterBuilder::default() + .address(vec![self.contract.address()]) + .from_block(BlockNumber::Earliest) + .to_block(to_block) + .topics( + Some(vec![event_signature]), // Event signature + Some(vec![mint_hash_h256]), // First indexed parameter (mint_hash) + None, // No third topic + None, // No fourth topic ) - .await?; + .build(); + + // Get logs + let logs = self.client.client().eth().logs(filter).await?; + + // Parse the logs into MintAddedEvent structs + let mut events = Vec::new(); + for log in logs { + if log.data.0.len() >= 64 + && log.transaction_hash.is_some() + && log.block_number.is_some() + { + // Extract amount (first parameter, 32 bytes) + let amount = U256::from_big_endian(&log.data.0[0..32]); + + // Extract note_kind (second parameter, 32 bytes) + let mut note_kind = [0u8; 32]; + note_kind.copy_from_slice(&log.data.0[32..64]); + let note_kind = H256::from(note_kind); + + events.push(MintAddedEvent { + mint_hash: mint_hash_h256, + value: amount, + note_kind, + transaction_hash: log.transaction_hash.unwrap(), + block_number: log.block_number.unwrap().as_u64(), + }); + } + } - Ok(exists) + Ok(events) } #[tracing::instrument(err, ret, skip(self))] - pub async fn substitute_burn(&self, nullifier: &Element, value: &Element) -> Result { + pub async fn substitute_burn( + &self, + burn_address: &Address, + note_kind: &Element, + hash: &Element, + amount: &Element, + burn_block_height: u64, + ) -> Result { let call_tx = self .call( "substituteBurn", ( - convert_element_to_h256(nullifier), - U256::from_little_endian(&value.to_le_bytes()), + *burn_address, + convert_element_to_h256(note_kind), + convert_element_to_h256(hash), + U256::from_little_endian(&amount.to_le_bytes()), + U256::from(burn_block_height), ), ) .await?; @@ -676,13 +728,24 @@ impl RollupContract { } #[tracing::instrument(err, ret, skip(self))] - pub async fn was_burn_substituted(&self, nullifier: &Element) -> Result { - let was_substituted: bool = self + pub async fn was_burn_substituted( + &self, + burn_address: &Address, + note_kind: &Element, + hash: &Element, + amount: &Element, + ) -> Result { + let was_substituted = self .client - .query( + .query::( &self.contract, "wasBurnSubstituted", - (convert_element_to_h256(nullifier),), + ( + Token::Address(*burn_address), + convert_element_to_h256(note_kind).into_token(), + convert_element_to_h256(hash).into_token(), + Token::Uint(U256::from_little_endian(&amount.to_le_bytes())), + ), None, Default::default(), self.block_height.map(|x| x.into()), @@ -692,21 +755,85 @@ impl RollupContract { Ok(was_substituted) } + /// Gets a list of emitted Burn events with the given burn hash. There should only + /// be one successful event. #[tracing::instrument(err, ret, skip(self))] - pub async fn root_hashes(&self) -> Result> { - let root_hashes = self - .client - .query( - &self.contract, - "getRootHashes", - (), - None, - Default::default(), - self.block_height.map(|x| x.into()), + pub async fn get_burned_events( + &self, + burn_hash: &Element, + block_height: Option, + ) -> Result> { + // Create the event signature hash + let event_signature = H256::from_slice( + &Keccak256::digest(b"Burned(address,bytes32,address,bool,bool)").as_slice()[0..32], + ); + + let burn_hash_h256 = burn_hash.to_h256(); + + // Build the filter + let filter = FilterBuilder::default() + .address(vec![self.contract.address()]) + .from_block(BlockNumber::Earliest) + .to_block(block_height.unwrap_or(BlockNumber::Latest)) + .topics( + Some(vec![event_signature]), // Event signature + None, // Don't filter by token address + Some(vec![burn_hash_h256]), // Second indexed parameter (nullifier) + None, // No fourth topic ) - .await?; + .build(); + + // Get logs + let logs = self.client.client().eth().logs(filter).await?; + + let mut events = Vec::new(); + for log in logs { + if log.topics.len() >= 4 && log.data.0.len() >= 64 { + // Extract token address from first topic + let token = Address::from_slice(&log.topics[1].as_bytes()[12..32]); + + // Extract recipient address from third topic + let recipient = Address::from_slice(&log.topics[3].as_bytes()[12..32]); + + // Extract substitute (first boolean) + let substitute = !log.data.0[31..32].iter().all(|&b| b == 0); + + // Extract success (second boolean) + let success = !log.data.0[63..64].iter().all(|&b| b == 0); + + events.push(BurnedEvent { + token, + burn_hash: burn_hash_h256, + substitute, + recipient, + success, + txn_hash: log.transaction_hash, + block_number: log.block_number.map(|u| u.as_u64()), + }); + } + } + + Ok(events) + } + + /// Checks if a burn with the given nullifier was successful + #[tracing::instrument(err, ret, skip(self))] + pub async fn was_burn_successful( + &self, + burn_hash: &Element, + to_block: Option, + ) -> Result { + let burned_events = self.get_burned_events(burn_hash, to_block).await?; + + // If there are no events, the burn didn't happen + if burned_events.is_empty() { + return Ok(false); + } - Ok(root_hashes) + // Check if any of the events indicate a successful burn + let burn_successful = burned_events.iter().any(|event| event.success); + + Ok(burn_successful) } #[tracing::instrument(err, ret, skip(self))] @@ -743,23 +870,6 @@ impl RollupContract { Ok(height) } - #[tracing::instrument(err, ret, skip(self))] - pub async fn block_hash(&self) -> Result { - let block_hash = self - .client - .query( - &self.contract, - "blockHash", - (), - None, - Default::default(), - self.block_height.map(|x| x.into()), - ) - .await?; - - Ok(block_hash) - } - /// Returns all validator sets from a given index, inclusive #[tracing::instrument(err, skip(self))] pub async fn get_validator_sets(&self, from: u64) -> Result> { @@ -782,7 +892,8 @@ impl RollupContract { pub async fn listen_for_validator_set_added( &self, interval: Duration, - ) -> Result>, web3::Error> { + ) -> Result> + use<>, web3::Error> + { let filter = FilterBuilder::default() .address(vec![self.contract.address()]) .topics( @@ -795,26 +906,23 @@ impl RollupContract { ) .build(); - let sub = self - .client - .client() - .eth_filter() - .create_logs_filter(filter) - .await?; + let sub = retry_on_network_failure({ + let filter = filter.clone(); + move || self.client.client().eth_filter().create_logs_filter(filter) + }) + .await?; Ok(sub.stream(interval)) } pub fn validators_for_height(&self, height: u64) -> Vec
{ - self - .validator_sets + self.validator_sets .read() .iter() .filter(|v| height >= v.valid_from.as_u64()) - .last() - .expect("No valid validator set found. This should not be possible, unless the contract is uninitialized") - .validators - .clone() + .next_back() + .map(|vs| vs.validators.clone()) + .unwrap_or_else(|| vec![self.signer_address]) } #[tracing::instrument(err, ret, skip(self))] diff --git a/pkg/contracts/src/tests.rs b/pkg/contracts/src/tests.rs index 289b4d6..ef0426a 100644 --- a/pkg/contracts/src/tests.rs +++ b/pkg/contracts/src/tests.rs @@ -1,19 +1,29 @@ -use crate::util::{convert_element_to_h256, convert_h160_to_element}; -use secp256k1::rand::random; +// lint-long-file-override allow-max-lines=1000 +#[cfg(test)] +mod test_rollup; + +use crate::util::{calculate_domain_separator, convert_element_to_h256, convert_h160_to_element}; +use barretenberg_cli::CliBackend; +use element::Element; +use ethereum_types::{H256, U256}; +use hash::hash_merge; use secp256k1::PublicKey; -use smirk::Element; use std::str::FromStr; use std::sync::Arc; -use std::time::Duration; -use testutil::eth::{EthNode, EthNodeOptions}; +use test_rollup::rollup::Rollup; use testutil::ACCOUNT_1_SK; -use web3::contract::tokens::Tokenizable; -use web3::ethabi::Token; -use web3::signing::{keccak256, SecretKey}; +use testutil::eth::{EthNode, EthNodeOptions}; +use web3::signing::{SecretKey, keccak256}; use web3::types::Address; -use zk_circuits::constants::MERKLE_TREE_DEPTH; -use zk_circuits::data::{BurnTo, Mint, ParameterSet}; -use zk_circuits::test::rollup::Rollup; +use zk_circuits::{Proof, Prove}; +use zk_primitives::{ + AggAgg, AggProof, AggUtxo, AggUtxoProof, InputNote, MerklePath, Note, Utxo, UtxoKind, + UtxoProof, UtxoProofBundleWithMerkleProofs, bridged_polygon_usdc_note_kind, + get_address_for_private_key, +}; +// use zk_circuits::constants::MERKLE_TREE_DEPTH; +// use zk_circuits::data::{BurnTo, Mint, ParameterSet}; +// use zk_circuits::test::rollup::Rollup; use super::*; @@ -88,8 +98,8 @@ async fn sign_block(new_root: &Element, height: u64, other_hash: [u8; 32]) -> Ve let msg = keccak256(&{ let mut bytes = vec![]; - bytes.extend_from_slice(&("Polybase".len() as u64).to_be_bytes()); - bytes.extend_from_slice(b"Polybase"); + bytes.extend_from_slice(&("Payy".len() as u64).to_be_bytes()); + bytes.extend_from_slice(b"Payy"); bytes.extend_from_slice(&accept_hash); bytes }); @@ -105,13 +115,6 @@ async fn sign_block(new_root: &Element, height: u64, other_hash: [u8; 32]) -> Ve sig } -#[tokio::test] -async fn root_hashes() { - let env: Env = make_env(EthNodeOptions::default()).await; - - let _root_hashes = env.rollup_contract.root_hashes().await.unwrap(); -} - #[tokio::test] async fn root_hash() { let env = make_env(EthNodeOptions::default()).await; @@ -126,48 +129,227 @@ async fn height() { let _height = env.rollup_contract.block_height().await.unwrap(); } -#[tokio::test] +pub fn get_keypair(key: u64) -> (Element, Element) { + let secret_key = Element::new(key); + let address = get_address_for_private_key(secret_key); + (secret_key, address) +} + +pub fn note(value: u64, address: Element, psi: u64, contract: Element) -> Note { + Note { + kind: Element::new(2), + value: Element::new(value), + address, + contract, + psi: Element::new(psi), + } +} + +pub fn send_note(value: u64, address: Element, psi: u64) -> Note { + note(value, address, psi, bridged_polygon_usdc_note_kind()) +} + +pub fn bb_backend() -> CliBackend { + CliBackend +} + +pub async fn verify_proof(proof: &impl zk_circuits::Verify) { + let bb_backend = bb_backend(); + let start = std::time::Instant::now(); + let result = proof.verify(&bb_backend).await; + let duration = start.elapsed(); + + assert!( + result.is_ok(), + "Proof verification failed: {:?}", + result.err() + ); + + println!("Proof verification completed in {duration:?}"); +} + +pub async fn verify_utxo_proof(proof: &UtxoProof) { + verify_proof(&Proof::from(proof.clone())).await; +} + +pub async fn prove_and_verify(proof_input: &P) -> Result { + let proof = prove_proof(proof_input).await?; + verify_proof(&proof).await; + Ok(proof) +} + +pub async fn prove_proof(proof_input: &P) -> Result { + let bb_backend = bb_backend(); + let start = std::time::Instant::now(); + let proof = proof_input.prove(&bb_backend).await.unwrap(); + let end = std::time::Instant::now() - start; + println!("Proving completed in {end:?}"); + Ok(proof) +} +async fn process_utxo_for_agg( + tree: &mut smirk::Tree<161, ()>, + utxo: &Utxo, +) -> Result<( + UtxoProof, + MerklePath<161>, + MerklePath<161>, + MerklePath<161>, + MerklePath<161>, + Element, +)> { + let bb_backend = bb_backend(); + let utxo_proof = utxo.clone().prove(&bb_backend).await.unwrap(); + + let p1: MerklePath<161> = MerklePath::new( + tree.path_for(utxo.input_notes[0].note.commitment()) + .siblings + .to_vec(), + ); + tree.remove(utxo.input_notes[0].note.commitment()).unwrap(); + + let p2: MerklePath<161> = MerklePath::new( + tree.path_for(utxo.input_notes[1].note.commitment()) + .siblings + .to_vec(), + ); + tree.remove(utxo.input_notes[1].note.commitment()).unwrap(); + + tree.insert(utxo.output_notes[0].commitment(), ()).unwrap(); + let p3: MerklePath<161> = MerklePath::new( + tree.path_for(utxo.output_notes[0].commitment()) + .siblings + .to_vec(), + ); + + tree.insert(utxo.output_notes[1].commitment(), ()).unwrap(); + let p4: MerklePath<161> = MerklePath::new( + tree.path_for(utxo.output_notes[1].commitment()) + .siblings + .to_vec(), + ); + + let new_root = tree.root_hash(); + + Ok((utxo_proof, p1, p2, p3, p4, new_root)) +} + +#[tokio::test] async fn verify_transfers() { let env = make_env(EthNodeOptions::default()).await; - let params_21 = zk_circuits::data::ParameterSet::TwentyOne; - let utxo_aggs = zk_circuits::test::agg_utxo::create_or_load_agg_utxo_snarks(params_21); + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); - let aggregate_agg = - zk_circuits::test::agg_agg::create_or_load_agg_agg_utxo_snark(params_21, utxo_aggs); + let utxo1_input_note1 = InputNote { + note: send_note(60, address, 1), + secret_key, + }; + tree.insert(utxo1_input_note1.note.commitment(), ()) + .unwrap(); + + let utxo1_input_note2 = InputNote { + note: send_note(40, address, 2), + secret_key, + }; + tree.insert(utxo1_input_note2.note.commitment(), ()) + .unwrap(); - let aggregate_agg_agg = zk_circuits::test::agg_agg::create_or_load_agg_agg_final_evm_proof( - params_21, - aggregate_agg, - ) - .try_as_v_1() - .unwrap(); + let utxo1_old_root = tree.root_hash(); - // Public inputs - let agg_instances = aggregate_agg_agg.agg_instances; - let agg_instances: Vec<_> = agg_instances.into_iter().map(From::from).collect(); - let old_root = aggregate_agg_agg.old_root; - let new_root = aggregate_agg_agg.new_root; - let utxo_inputs = aggregate_agg_agg.utxo_inputs; - let proof = aggregate_agg_agg.proof; + let utxo1_output_note1 = send_note(70, address, 3); + let utxo1_output_note2 = send_note(30, address, 4); + + let utxo1 = Utxo { + input_notes: [utxo1_input_note1.clone(), utxo1_input_note2.clone()], + output_notes: [utxo1_output_note1.clone(), utxo1_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo1_proof, p1_1, p1_2, p1_3, p1_4, utxo1_new_root) = + process_utxo_for_agg(&mut tree, &utxo1).await.unwrap(); + verify_utxo_proof(&utxo1_proof).await; + + let agg_utxo1 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo1_proof, &[p1_1, p1_2, p1_3, p1_4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo1_old_root, + utxo1_new_root, + ); + let agg_utxo1_proof = prove_and_verify(&agg_utxo1).await.unwrap(); + + let utxo2_input_note1 = InputNote { + note: utxo1_output_note1.clone(), + secret_key, + }; + + let utxo2_input_note2 = InputNote { + note: utxo1_output_note2.clone(), + secret_key, + }; + + let utxo2_old_root = tree.root_hash(); + + let utxo2_output_note1 = send_note(55, address, 5); + let utxo2_output_note2 = send_note(45, address, 6); + + let utxo2 = Utxo { + input_notes: [utxo2_input_note1.clone(), utxo2_input_note2.clone()], + output_notes: [utxo2_output_note1.clone(), utxo2_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo2_proof, p2_1, p2_2, p2_3, p2_4, utxo2_new_root) = + process_utxo_for_agg(&mut tree, &utxo2).await.unwrap(); + verify_utxo_proof(&utxo2_proof).await; + + let agg_utxo2 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo2_proof, &[p2_1, p2_2, p2_3, p2_4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo2_old_root, + utxo2_new_root, + ); + let agg_utxo2_proof = prove_and_verify(&agg_utxo2).await.unwrap(); + + let agg_agg = AggAgg::new([ + AggProof::AggUtxo(Box::new(agg_utxo1_proof)), + AggProof::AggUtxo(Box::new(agg_utxo2_proof)), + ]); + let agg_agg_proof = prove_and_verify(&agg_agg).await.unwrap(); + + // Create final aggregation proof + let agg_final = zk_primitives::AggFinal::new(agg_agg_proof); + let agg_final_proof = prove_and_verify(&agg_final).await.unwrap(); // Sign let other_hash = [0u8; 32]; let height = 1; - let sig = sign_block(&new_root, height, other_hash).await; + let sig = sign_block(&agg_agg.new_root(), height, other_hash).await; // Set the root, we add some pre-existing values to the tree before generating the UTXO, // so the tree is not empty - env.rollup_contract.set_root(&old_root).await.unwrap(); + env.rollup_contract + .set_root(&agg_agg.old_root()) + .await + .unwrap(); + assert_eq!(agg_final_proof.proof.0.len(), 330 * 32); env.rollup_contract .verify_block( - &proof, - agg_instances.try_into().unwrap(), - &old_root, - &new_root, - &utxo_inputs, + &agg_final_proof.proof.0, + &agg_agg.old_root(), + &agg_agg.new_root(), + &agg_agg.commit_hash(), + &agg_final_proof.public_inputs.messages, + &agg_final_proof.kzg, other_hash, height, &[&sig], @@ -184,17 +366,16 @@ async fn mint_with_authorization() { let bob = rollup.new_wallet(); let amount = 10 * 10u64.pow(6); - let note = bob.new_note(amount); - let mint = Mint::new([note.clone()]); - let params = ParameterSet::Eight; - let proof = mint.evm_proof(params).unwrap(); + let note = bob.new_note(amount, bridged_polygon_usdc_note_kind()); let secret_key = secp256k1::SecretKey::from_slice(&env.evm_secret_key.secret_bytes()).unwrap(); - let nonce = random(); + let nonce = Element::secure_random(rand::thread_rng()); let valid_after = U256::from(0); let valid_before = U256::from(u64::MAX); + let mint_hash = hash_merge([note.psi, Note::padding_note().psi]); + // Sig for the USDC function let sig_bytes = env.usdc_contract.signature_for_receive( env.evm_address, @@ -202,32 +383,31 @@ async fn mint_with_authorization() { amount.into(), valid_after, valid_before, - nonce, + H256::from(nonce.to_be_bytes()), secret_key, ); // Sig for our mint function let mint_sig_bytes = env.rollup_contract.signature_for_mint( - note.commitment(), + mint_hash, amount.into(), - note.source(), + note.contract, env.evm_address, valid_after, valid_before, - nonce, + H256::from(nonce.to_be_bytes()), secret_key, ); env.rollup_contract .mint_with_authorization( - &proof, - ¬e.commitment(), - ¬e.value(), - ¬e.source(), + &mint_hash, + ¬e.value, + ¬e.contract, &env.evm_address, U256::from(0), U256::from(u64::MAX), - nonce, + H256::from(nonce.to_be_bytes()), &sig_bytes, &mint_sig_bytes, ) @@ -242,10 +422,9 @@ async fn mint_from() { let bob = rollup.new_wallet(); // Create the proof - let note = bob.new_note(10 * 10u64.pow(6)); - let mint = Mint::new([note.clone()]); - let params = ParameterSet::Eight; - let proof = mint.evm_proof(params).unwrap(); + let note = bob.new_note(10 * 10u64.pow(6), bridged_polygon_usdc_note_kind()); + + let mint_hash = hash_merge([note.psi, Note::padding_note().psi]); env.usdc_contract .approve_max(env.rollup_contract.address()) @@ -253,319 +432,413 @@ async fn mint_from() { .unwrap(); env.rollup_contract - .mint(&proof, ¬e.commitment(), ¬e.value(), ¬e.source()) + .mint(&mint_hash, ¬e.value, ¬e.contract) .await .unwrap(); } #[tokio::test] async fn burn_to() { + // Set up the environment let env = make_env(EthNodeOptions::default()).await; - // Create the proof - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - - let bob_note = rollup.unverified_add_unspent_note(&bob, 100); - - // Set the root, we add some pre-existing values to the tree before generating the UTXO, - // so the tree is not empty - env.rollup_contract - .set_root(&rollup.root_hash()) + env.usdc_contract + .transfer(env.rollup_contract.address(), 100) .await .unwrap(); - let note = bob_note.note(); - let burn = BurnTo { - notes: [note.clone()], - secret_key: bob.pk, - to_address: convert_h160_to_element(&env.evm_address), - kind: Element::ZERO, + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); + + // Create input note for burning + let input_note1 = InputNote { + note: send_note(100, address, 1), + secret_key, }; + tree.insert(input_note1.note.commitment(), ()).unwrap(); - let proof = burn.evm_proof(ParameterSet::Nine).unwrap(); + // Add a padding input note + let input_note2 = InputNote::padding_note(); - env.rollup_contract - .burn_to_address( - &burn.kind, - &burn.to_address, - &proof, - ¬e.nullifier(bob.pk), - ¬e.value(), - ¬e.source(), - &burn.signature(¬e), - ) - .await - .unwrap(); -} + let old_root = tree.root_hash(); -#[tokio::test] -async fn burn_to_router() { - let env = make_env(EthNodeOptions::default()).await; + // Create burn UTXO + let burn_address = convert_h160_to_element(&env.evm_address); + let utxo = Utxo::new_burn([input_note1.clone(), input_note2.clone()], burn_address); - // Create the proof - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); + let backend = bb_backend(); - let bob_note = rollup.unverified_add_unspent_note(&bob, 100); + // Generate UTXO proof + let utxo_proof = utxo.prove(&backend).await.unwrap(); - // Set the root, we add some pre-existing values to the tree before generating the UTXO, - // so the tree is not empty - env.rollup_contract - .set_root(&rollup.root_hash()) - .await - .unwrap(); + // Get merkle paths for inputs before removal + let p1 = MerklePath::new( + tree.path_for(input_note1.note.commitment()) + .siblings + .to_vec(), + ); + let p2 = MerklePath::new( + tree.path_for(input_note2.note.commitment()) + .siblings + .to_vec(), + ); - let owner = env.evm_address; - let router = Address::from_str("4a679253410272dd5232b3ff7cf5dbb88f295319").unwrap(); - let return_address = Address::from_str("0000000000000000000000000000000000000001").unwrap(); - - let mut router_calldata = keccak256(b"burnToAddress(address,address,uint256)")[0..4].to_vec(); - router_calldata.extend_from_slice(&web3::ethabi::encode(&[ - Address::from_str("09635f643e140090a9a8dcd712ed6285858cebef") - .unwrap() - .into_token(), - owner.into_token(), - convert_element_to_h256(&bob_note.note().value).into_token(), - ])); - - let msg = web3::ethabi::encode(&[ - Token::Address(router), - Token::Bytes(router_calldata.clone()), - Token::Address(return_address), + // Remove input notes (only the first one, as the second is padding) + tree.remove(input_note1.note.commitment()).unwrap(); + + // For outputs, both are padding notes with commitment zero + let output_commit = Element::ZERO; + let p3 = MerklePath::new(tree.path_for(output_commit).siblings.to_vec()); + let p4 = MerklePath::new(tree.path_for(output_commit).siblings.to_vec()); + + let new_root = tree.root_hash(); + + // Create an AggUtxo with the burn UTXO and padding + let agg_utxo = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo_proof, &[p1, p2, p3, p4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + old_root, + new_root, + ); + + // Prove the AggUtxo + let agg_utxo_proof = agg_utxo.prove(&backend).await.unwrap(); + + // Create a padding AggUtxo for AggAgg + let padding_agg_utxo_proof = AggUtxoProof::default(); + + // Create and prove the AggAgg + let agg_agg = AggAgg::new([ + AggProof::AggUtxo(Box::new(agg_utxo_proof)), + AggProof::AggUtxo(Box::new(padding_agg_utxo_proof)), ]); + let agg_agg_proof = agg_agg.prove(&backend).await.unwrap(); - let mut msg_hash = keccak256(&msg); - // Bn256 can't fit the full hash, so we remove the first 3 bits - msg_hash[0] &= 0x1f; // 0b11111 + // Create final aggregation proof + let agg_final = zk_primitives::AggFinal::new(agg_agg_proof); + let agg_final_proof = prove_and_verify(&agg_final).await.unwrap(); - let note = bob_note.note(); - let burn = BurnTo { - notes: [note.clone()], - secret_key: bob.pk, - to_address: Element::from_be_bytes(msg_hash), - kind: Element::ONE, - }; + // Sign the block + let other_hash = [0u8; 32]; + let height = 1; + let sig = sign_block(&agg_agg.new_root(), height, other_hash).await; - let proof = burn.evm_proof(ParameterSet::Nine).unwrap(); + // Get the initial balance of the EVM address + let initial_balance = env.usdc_contract.balance(env.evm_address).await.unwrap(); env.rollup_contract - .burn_to_router( - &burn.kind, - &burn.to_address, - &proof, - ¬e.nullifier(bob.pk), - ¬e.value(), - ¬e.source(), - &burn.signature(¬e), - &router, - &router_calldata, - &Address::from_str("0000000000000000000000000000000000000001").unwrap(), + .set_root(&agg_agg.old_root()) + .await + .unwrap(); + + // Submit the proof to the contract + env.rollup_contract + .verify_block( + &agg_final_proof.proof.0, + &agg_agg.old_root(), + &agg_agg.new_root(), + &agg_agg.commit_hash(), + &agg_final_proof.public_inputs.messages, + &agg_final_proof.kzg, + other_hash, + height, + &[&sig], + 500_000, ) .await .unwrap(); + + // Verify the balance increased by the burnt amount + let new_balance = env.usdc_contract.balance(env.evm_address).await.unwrap(); + let burnt_value = U256::from(100); + assert_eq!(new_balance, initial_balance + burnt_value); } #[tokio::test] async fn substitute_burn() { - let env = make_env(EthNodeOptions { - use_noop_verifier: true, - ..Default::default() - }) - .await; - - // Create the proof - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - - let bob_note = rollup.unverified_add_unspent_note(&bob, 100); + // Set up the environment + let env = make_env(EthNodeOptions::default()).await; - // Set the root, we add some pre-existing values to the tree before generating the UTXO, - // so the tree is not empty - env.rollup_contract - .set_root(&rollup.root_hash()) + env.usdc_contract + .transfer(env.rollup_contract.address(), 100) .await .unwrap(); - let owner = Address::from_str("1111111111111111111111111111111111111111").unwrap(); - let router = Address::from_str("4a679253410272dd5232b3ff7cf5dbb88f295319").unwrap(); - let return_address = Address::from_str("0000000000000000000000000000000000000001").unwrap(); - - let mut router_calldata = keccak256(b"burnToAddress(address,address,uint256)")[0..4].to_vec(); - router_calldata.extend_from_slice(&web3::ethabi::encode(&[ - env.usdc_contract.address().into_token(), - owner.into_token(), - convert_element_to_h256(&bob_note.note().value).into_token(), - ])); - - let msg = web3::ethabi::encode(&[ - Token::Address(router), - Token::Bytes(router_calldata.clone()), - Token::Address(return_address), - ]); - - let mut msg_hash = keccak256(&msg); - // Bn256 can't fit the full hash, so we remove the first 3 bits - msg_hash[0] &= 0x1f; // 0b11111 + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); - let note = bob_note.note(); - let burn = BurnTo { - notes: [note.clone()], - secret_key: bob.pk, - to_address: Element::from_be_bytes(msg_hash), - kind: Element::ONE, + // Create input note for burning + let input_note1 = InputNote { + note: send_note(100, address, 1), + secret_key, }; + tree.insert(input_note1.note.commitment(), ()).unwrap(); - let proof = burn.evm_proof(ParameterSet::Nine).unwrap(); + // Add a padding input note + let input_note2 = InputNote::padding_note(); - let nullifier = note.nullifier(bob.pk); - env.rollup_contract - .burn_to_router( - &burn.kind, - &burn.to_address, - &proof, - &nullifier, - ¬e.value(), - ¬e.source(), - &burn.signature(¬e), - &router, - &router_calldata, - &Address::from_str("0000000000000000000000000000000000000001").unwrap(), - ) - .await - .unwrap(); + let old_root = tree.root_hash(); + + // Create burn UTXO + let burn_address = Address::random(); + let utxo = Utxo::new_burn( + [input_note1.clone(), input_note2.clone()], + convert_h160_to_element(&burn_address), + ); + + let hash = utxo.input_notes[0].note.commitment(); - let owner_balance_pre_substitute = env.usdc_contract.balance(owner).await.unwrap(); - assert_eq!(owner_balance_pre_substitute, U256::from(0)); + let backend = bb_backend(); - let substitutor_balance_pre_substitute = - env.usdc_contract.balance(env.evm_address).await.unwrap(); + // Generate UTXO proof + let utxo_proof = utxo.prove(&backend).await.unwrap(); + + // Get merkle paths for inputs before removal + let p1 = MerklePath::new( + tree.path_for(input_note1.note.commitment()) + .siblings + .to_vec(), + ); + let p2 = MerklePath::new( + tree.path_for(input_note2.note.commitment()) + .siblings + .to_vec(), + ); + + // Remove input notes (only the first one, as the second is padding) + tree.remove(input_note1.note.commitment()).unwrap(); + + // For outputs, both are padding notes with commitment zero + let output_commit = Element::ZERO; + let p3 = MerklePath::new(tree.path_for(output_commit).siblings.to_vec()); + let p4 = MerklePath::new(tree.path_for(output_commit).siblings.to_vec()); + + let new_root = tree.root_hash(); + + // Create an AggUtxo with the burn UTXO and padding + let agg_utxo = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo_proof, &[p1, p2, p3, p4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + old_root, + new_root, + ); + + // Prove the AggUtxo + let agg_utxo_proof = agg_utxo.prove(&backend).await.unwrap(); + + // Create a padding AggUtxo for AggAgg + let padding_agg_utxo_proof = AggUtxoProof::default(); + + // Create and prove the AggAgg + let agg_agg = AggAgg::new([ + AggProof::AggUtxo(Box::new(agg_utxo_proof)), + AggProof::AggUtxo(Box::new(padding_agg_utxo_proof)), + ]); + let agg_agg_proof = agg_agg.prove(&backend).await.unwrap(); - let rollup_balance_pre_substitute = env - .usdc_contract - .balance(env.rollup_contract.address()) + // Create final aggregation proof + let agg_final = zk_primitives::AggFinal::new(agg_agg_proof); + let agg_final_proof = prove_and_verify(&agg_final).await.unwrap(); + + // Sign the block + let other_hash = [0u8; 32]; + let height = 1; + let sig = sign_block(&agg_agg.new_root(), height, other_hash).await; + + // Get the initial balance of the EVM address + let initial_caller_balance = env.usdc_contract.balance(env.evm_address).await.unwrap(); + let initial_burn_address_balance = env.usdc_contract.balance(burn_address).await.unwrap(); + + env.rollup_contract + .set_root(&agg_agg.old_root()) .await .unwrap(); - env.usdc_contract - .approve_max(env.rollup_contract.address()) + env.rollup_contract + .substitute_burn( + &burn_address, + &input_note1.note.contract, + &hash, + &Element::new(100), + height, + ) .await .unwrap(); - assert!(!env - .rollup_contract - .was_burn_substituted(&nullifier) - .await - .unwrap()); + let balance_after_substitute = env.usdc_contract.balance(env.evm_address).await.unwrap(); + assert_eq!(balance_after_substitute, initial_caller_balance - 100); - let txn = env - .rollup_contract - .substitute_burn(&nullifier, ¬e.value()) + // Submit the proof to the contract + env.rollup_contract + .verify_block( + &agg_final_proof.proof.0, + &agg_agg.old_root(), + &agg_agg.new_root(), + &agg_agg.commit_hash(), + &agg_final_proof.public_inputs.messages, + &agg_final_proof.kzg, + other_hash, + height, + &[&sig], + 500_000, + ) .await .unwrap(); - while env - .rollup_contract - .client - .client() - .eth() - .transaction_receipt(txn) - .await - .unwrap() - .is_none() - { - tokio::time::sleep(std::time::Duration::from_millis(300)).await; - } + // Verify the balance increased by the burnt amount + let new_balance = env.usdc_contract.balance(burn_address).await.unwrap(); + let burnt_value = U256::from(100); + assert_eq!(new_balance, initial_burn_address_balance + burnt_value); - assert_eq!( - env.usdc_contract.balance(owner).await.unwrap(), - U256::from(100) - ); - assert_eq!( - env.usdc_contract.balance(env.evm_address).await.unwrap(), - substitutor_balance_pre_substitute - U256::from(100) - ); - - assert_eq!( - env.usdc_contract - .balance(env.rollup_contract.address()) - .await - .unwrap(), - rollup_balance_pre_substitute - ); + let new_caller_balance = env.usdc_contract.balance(env.evm_address).await.unwrap(); + assert_eq!(new_caller_balance, initial_caller_balance); - assert!(env + let was_substituted = env .rollup_contract - .was_burn_substituted(&nullifier) + .was_burn_substituted( + &burn_address, + &input_note1.note.contract, + &hash, + &Element::new(100), + ) .await - .unwrap()); + .unwrap(); + assert!(!was_substituted); } -#[tokio::test] -async fn set_validators() { - let env = make_env(EthNodeOptions::default()).await; +// #[tokio::test] +// async fn substitute_burn() { +// let env = make_env(EthNodeOptions { +// use_noop_verifier: true, +// ..Default::default() +// }) +// .await; + +// // Create the proof +// let mut rollup = Rollup::new(); +// let bob = rollup.new_wallet(); + +// let bob_note = rollup.unverified_add_unspent_note(&bob, 100); + +// // Set the root, we add some pre-existing values to the tree before generating the UTXO, +// #[tokio::test] +// async fn set_validators() { +// let env = make_env(EthNodeOptions::default()).await; + +// // let's also test the worker +// let worker_rollup_contract = env.rollup_contract.clone(); +// let _worker = tokio::spawn(async move { +// worker_rollup_contract +// .worker(Duration::from_millis(100)) +// .await +// }); + +// let validator_sets_before = env.rollup_contract.get_validator_sets(0).await.unwrap(); +// assert_eq!( +// validator_sets_before, +// *env.rollup_contract.validator_sets.read() +// ); + +// let valid_from = validator_sets_before.last().unwrap().valid_from + 2; +// let tx = env +// .rollup_contract +// .set_validators(valid_from.as_u64(), &[env.evm_address]) +// .await +// .unwrap(); + +// // Wait for receipt +// while env +// .rollup_contract +// .client +// .client() +// .eth() +// .transaction_receipt(tx) +// .await +// .unwrap() +// .is_none() +// { +// tokio::time::sleep(std::time::Duration::from_secs(1)).await; +// } + +// let validator_sets_after = env +// .rollup_contract +// .get_validator_sets(validator_sets_before.len() as u64) +// .await +// .unwrap(); +// assert_eq!(validator_sets_after.last().unwrap().valid_from, valid_from); +// assert_eq!( +// validator_sets_after.last().unwrap().validators, +// vec![env.evm_address] +// ); + +// // Wait for worker to update the validator sets +// tokio::time::sleep(std::time::Duration::from_secs(1)).await; +// // Make sure the worker updated the contract's state +// assert_eq!( +// validator_sets_before +// .into_iter() +// .chain(validator_sets_after) +// .collect::>(), +// *env.rollup_contract.validator_sets.read() +// ); +// } - // let's also test the worker - let worker_rollup_contract = env.rollup_contract.clone(); - let _worker = tokio::spawn(async move { - worker_rollup_contract - .worker(Duration::from_millis(100)) - .await - }); +#[test] +fn empty_root() { + let tree = smirk::Tree::<161, ()>::new(); + let hash = expect_test::expect_file!["./empty_merkle_tree_root_hash.txt"]; + hash.assert_eq(&tree.root_hash().to_hex()); +} - let validator_sets_before = env.rollup_contract.get_validator_sets(0).await.unwrap(); - assert_eq!( - validator_sets_before, - *env.rollup_contract.validator_sets.read() - ); +#[test] +fn test_domain_separator_calculation() { + // Test primary rollup chain values (Chain ID: 137 - Polygon) + let chain_id = U256::from(137); - let valid_from = validator_sets_before.last().unwrap().valid_from + 2; - let tx = env - .rollup_contract - .set_validators(valid_from.as_u64(), &[env.evm_address]) - .await + // Test USDC contract + let usdc_address: Address = "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359" + .parse() .unwrap(); + let usdc_domain_separator = calculate_domain_separator("USD Coin", "2", chain_id, usdc_address); + let expected_usdc = H256::from_slice( + &hex::decode("caa2ce1a5703ccbe253a34eb3166df60a705c561b44b192061e28f2a985be2ca").unwrap(), + ); + assert_eq!( + usdc_domain_separator, expected_usdc, + "USDC domain separator mismatch" + ); - // Wait for receipt - while env - .rollup_contract - .client - .client() - .eth() - .transaction_receipt(tx) - .await - .unwrap() - .is_none() - { - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - } - - let validator_sets_after = env - .rollup_contract - .get_validator_sets(validator_sets_before.len() as u64) - .await + // Test AcrossWithAuthorization contract + let across_address: Address = "0xf5bf1a6a83029503157bb3761488bb75d64002e7" + .parse() .unwrap(); - assert_eq!(validator_sets_after.last().unwrap().valid_from, valid_from); + let across_domain_separator = + calculate_domain_separator("AcrossWithAuthorization", "1", chain_id, across_address); + let expected_across = H256::from_slice( + &hex::decode("c0db9d13ac268c870ccb743fd1078a25b4c98ff3ba232167b02aff4340f8c8cc").unwrap(), + ); assert_eq!( - validator_sets_after.last().unwrap().validators, - vec![env.evm_address] + across_domain_separator, expected_across, + "AcrossWithAuthorization domain separator mismatch" ); - // Wait for worker to update the validator sets - tokio::time::sleep(std::time::Duration::from_secs(1)).await; - // Make sure the worker updated the contract's state + // Test Rollup contract + let rollup_address: Address = "0xcd92281548df923141fd9b690c7c8522e12e76e6" + .parse() + .unwrap(); + let rollup_domain_separator = + calculate_domain_separator("Rollup", "1", chain_id, rollup_address); + let expected_rollup = H256::from_slice( + &hex::decode("5261b2c944771285325623d865717567b4425028487b653028b59e46d910b34d").unwrap(), + ); assert_eq!( - validator_sets_before - .into_iter() - .chain(validator_sets_after) - .collect::>(), - *env.rollup_contract.validator_sets.read() + rollup_domain_separator, expected_rollup, + "Rollup domain separator mismatch" ); } - -#[test] -fn empty_root() { - let tree = smirk::Tree::::new(); - let hash = expect_test::expect_file!["./empty_merkle_tree_root_hash.txt"]; - hash.assert_eq(format!("{:?}", tree.root_hash().to_base()).as_str()); -} diff --git a/pkg/contracts/src/tests/test_rollup.rs b/pkg/contracts/src/tests/test_rollup.rs new file mode 100644 index 0000000..982d3fb --- /dev/null +++ b/pkg/contracts/src/tests/test_rollup.rs @@ -0,0 +1,146 @@ +#[cfg(test)] +pub mod rollup { + use element::Element; + use rand::{RngCore, rngs::OsRng}; + use smirk::Tree; + use zk_primitives::{InputNote, MerklePath, Note, get_address_for_private_key}; + + /// Depth expected by all current circuits & tests (see + /// `verify_transfers`, `burn_to_*`, etc.). + pub const MERKLE_TREE_DEPTH: usize = 161; + + /// A throw‑away roll‑up model backed by a `smirk::Tree`. + #[derive(Debug, Clone, Default)] + pub struct Rollup { + tree: Tree, + } + + impl Rollup { + /// Create an empty tree whose root equals the + /// `empty_merkle_tree_root_hash.txt` reference. + pub fn new() -> Self { + Self::default() + } + + /// Convenience for the tests – builds a brand‑new wallet with a + /// random private key. + pub fn new_wallet(&self) -> Wallet { + Wallet::random() + } + + /// Insert an **_unspent_** note directly into the tree (used by + /// the tests to create pre‑existing UTXOs without generating a + /// proof first). + #[expect(unused)] + pub fn unverified_add_unspent_note( + &mut self, + wallet: &Wallet, + amount: u64, + kind: Element, + ) -> WalletNote { + let note = wallet.new_note(amount, kind); + self.tree.insert(note.commitment(), ()).unwrap(); + WalletNote::new(*wallet, note) + } + + /// Return the current root as a `element::Element`. + #[expect(unused)] + pub fn root_hash(&self) -> Element { + self.tree.root_hash() + } + + // ---------------------------------------------------------------- + // Helpers – currently *not* used by the compiled tests but kept + // around because they were relied upon before, and they’re handy + // for local experimentation. + // ---------------------------------------------------------------- + + /// Convert a `WalletNote` into an `InputNote` by attaching its + /// Merkle path. + #[expect(unused)] + pub fn to_input_note(&self, wn: &WalletNote) -> InputNote { + InputNote { + note: wn.note(), + secret_key: wn.wallet.pk, + } + } + + /// Return the Merkle‑proof for any element currently in the tree. + #[expect(unused)] + pub fn merkle_path(&self, el: Element) -> MerklePath { + let path = self.tree.path_for(el); + // `smirk` returns siblings deepest‑first, which matches the + // ordering expected by the circuits. + MerklePath::new(path.siblings_deepest_first().to_vec()) + } + } + + // ===================================================================== + // Wallet & helpers + // ===================================================================== + + #[derive(Clone, Copy, Debug)] + pub struct Wallet { + /// *Private* key in the zk‑Primitive sense – **NOT** an ECDSA key! + pub pk: Element, + } + + impl Wallet { + /// Create a wallet from an explicit private key. + #[expect(unused)] + pub fn new(pk: Element) -> Self { + Self { pk } + } + + /// Create a wallet with a random 256‑bit private key. + pub fn random() -> Self { + let mut bytes = [0u8; 32]; + OsRng.fill_bytes(&mut bytes); + Self { + pk: Element::from_be_bytes(bytes), + } + } + + /// Derive the *address* (Poseidon‑hashed) that the circuits use. + pub fn address(&self) -> Element { + get_address_for_private_key(self.pk) + } + + pub fn new_note(&self, amount: u64, contract: Element) -> Note { + Note { + kind: Element::new(2), + value: Element::new(amount), + address: self.address(), + contract, + psi: Element::new(0), + } + } + } + + // ===================================================================== + // A note bundled with the wallet that created / owns it + // ===================================================================== + + #[derive(Clone, Debug)] + pub struct WalletNote { + note: Note, + pub wallet: Wallet, + } + + impl WalletNote { + fn new(wallet: Wallet, note: Note) -> Self { + Self { note, wallet } + } + + /// Raw commitment (32‑byte field element). + #[expect(unused)] + pub fn commitment(&self) -> Element { + self.note.commitment() + } + + /// Borrow the underlying `Note`. + pub fn note(&self) -> Note { + self.note.clone() + } + } +} diff --git a/pkg/contracts/src/usdc.rs b/pkg/contracts/src/usdc.rs index db735d4..90ee8c8 100644 --- a/pkg/contracts/src/usdc.rs +++ b/pkg/contracts/src/usdc.rs @@ -1,18 +1,20 @@ -use crate::error::Result; +// lint-long-file-override allow-max-lines=300 use crate::Client; +use crate::error::Result; +use crate::util::calculate_domain_separator; use ethereum_types::U64; use rustc_hex::FromHex; use secp256k1::{Message, SECP256K1}; use sha3::{Digest, Keccak256}; use testutil::eth::EthNode; use web3::{ - contract::{tokens::Tokenize, Contract}, + contract::{Contract, tokens::Tokenize}, signing::{Key, SecretKey, SecretKeyRef}, transports::Http, - types::{Address, H256, U256}, + types::{Address, FilterBuilder, H256, U256}, }; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct USDCContract { client: Client, contract: Contract, @@ -46,28 +48,35 @@ impl USDCContract { } } - pub fn at_height(mut self, block_height: Option) -> Self { - self.block_height = block_height.map(|x| x.into()); - self + pub fn at_height(&self, block_height: u64) -> Self { + Self { + block_height: Some(U64::from(block_height)), + ..self.clone() + } } pub fn address(&self) -> Address { self.address } - pub async fn load(client: Client, usdc_contract_addr: &str, signer: SecretKey) -> Result { + pub fn client(&self) -> &Client { + &self.client + } + + pub async fn load( + client: Client, + chain_id: u128, + usdc_contract_addr: &str, + signer: SecretKey, + ) -> Result { let contract_json = include_str!("../../../eth/artifacts/contracts/IUSDC.sol/IUSDC.json"); let contract = client.load_contract_from_str(usdc_contract_addr, contract_json)?; - let domain_separator = client - .query::( - &contract, - "DOMAIN_SEPARATOR", - (), - None, - Default::default(), - None, - ) - .await?; + let domain_separator = calculate_domain_separator( + "USD Coin", + "2", + U256::from(chain_id), + usdc_contract_addr.parse()?, + ); Ok(Self::new( client, contract, @@ -81,7 +90,7 @@ impl USDCContract { let usdc_addr = "5fbdb2315678afecb367f032d93f642f64180aa3"; let client = Client::from_eth_node(eth_node); - Self::load(client, usdc_addr, signer).await + Self::load(client, 1337, usdc_addr, signer).await } pub async fn call(&self, func: &str, params: impl Tokenize + Clone) -> Result { @@ -229,6 +238,35 @@ impl USDCContract { Ok(balance) } + /// Check if an EIP-3009 authorization has been used by scanning the AuthorizationUsed event. + /// Many USDC implementations emit: AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce) + /// Returns the transaction hash if found. + #[tracing::instrument(err, ret, skip(self))] + pub async fn authorization_used_txn( + &self, + authorizer: Address, + nonce: H256, + ) -> Result> { + // keccak256("AuthorizationUsed(address,bytes32)") + let topic0 = H256::from_slice(&Keccak256::digest(b"AuthorizationUsed(address,bytes32)")); + let authorizer_h = H256::from(authorizer); + + let filter = FilterBuilder::default() + .address(vec![self.address]) + .from_block(web3::types::BlockNumber::Earliest) + .to_block(web3::types::BlockNumber::Latest) + .topics( + Some(vec![topic0]), + Some(vec![authorizer_h]), + Some(vec![nonce]), + None, + ) + .build(); + + let logs = self.client.logs(filter).await?; + Ok(logs.into_iter().filter_map(|l| l.transaction_hash).next()) + } + /// Approve contract to spend USDC on behalf of the user #[tracing::instrument(err, ret, skip(self))] pub async fn approve_max(&self, from: Address) -> Result { diff --git a/pkg/contracts/src/util.rs b/pkg/contracts/src/util.rs index 3be3d0d..2021595 100644 --- a/pkg/contracts/src/util.rs +++ b/pkg/contracts/src/util.rs @@ -1,6 +1,7 @@ +use element::Element; use ethereum_types::{H160, H256, U256}; -// use smirk::Element; -use zk_primitives::Element; +use sha3::{Digest, Keccak256}; +use web3::ethabi::{Token, encode}; pub fn convert_element_to_h256(element: &Element) -> H256 { H256::from_slice(&element.to_be_bytes()) @@ -24,3 +25,40 @@ pub fn convert_h160_to_element(h160: &H160) -> Element { Element::from_be_bytes(h256) } + +/// Calculate EIP-712 domain separator locally +/// +/// Formula: +/// DomainSeparator := Keccak256(ABIEncode( +/// Keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), +/// Keccak256(name), +/// Keccak256(version), +/// chainId, +/// verifyingContract +/// )) +pub fn calculate_domain_separator( + name: &str, + version: &str, + chain_id: U256, + verifying_contract: ethereum_types::Address, +) -> H256 { + // EIP712Domain type hash + let eip712_domain_typehash = Keccak256::digest( + b"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)", + ); + + // Hash the name and version strings + let name_hash = Keccak256::digest(name.as_bytes()); + let version_hash = Keccak256::digest(version.as_bytes()); + + // Encode the domain separator according to EIP-712 + let encoded = encode(&[ + Token::FixedBytes(eip712_domain_typehash.to_vec()), + Token::FixedBytes(name_hash.to_vec()), + Token::FixedBytes(version_hash.to_vec()), + Token::Uint(chain_id), + Token::Address(verifying_contract), + ]); + + H256::from_slice(&Keccak256::digest(&encoded)) +} diff --git a/pkg/contracts/src/wallet.rs b/pkg/contracts/src/wallet.rs index 2dcfce7..1856192 100644 --- a/pkg/contracts/src/wallet.rs +++ b/pkg/contracts/src/wallet.rs @@ -1,8 +1,11 @@ -use color_eyre::Result; +use std::str::FromStr; + +use contextful::ResultContextExt; use ethereum_types::Address; -use secp256k1::{PublicKey, SecretKey, SECP256K1}; +use secp256k1::{PublicKey, SECP256K1, SecretKey}; use sha3::{Digest, Keccak256}; -use std::str::FromStr; + +use crate::Result; pub struct Wallet { secret_key: SecretKey, @@ -14,7 +17,8 @@ impl Wallet { } pub fn new_from_str(secret_key: &str) -> Result { - let secret_key = SecretKey::from_str(secret_key)?; + let secret_key = SecretKey::from_str(secret_key) + .context("[contracts/wallet] parse secp256k1 secret key from hex input")?; Ok(Self { secret_key }) } diff --git a/pkg/country/Cargo.toml b/pkg/country/Cargo.toml new file mode 100644 index 0000000..2038ea9 --- /dev/null +++ b/pkg/country/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "country" +version = "0.1.0" +edition = "2024" + +[features] +diesel = ["dep:diesel"] + +[dependencies] +serde = { workspace = true } +strum_macros = { workspace = true } +strum = { workspace = true } +workspace-hack.workspace = true + +diesel = { workspace = true, optional = true } + +[package.metadata.cargo-machete] +ignored = ["strum"] diff --git a/pkg/country/src/lib.rs b/pkg/country/src/lib.rs new file mode 100644 index 0000000..947453d --- /dev/null +++ b/pkg/country/src/lib.rs @@ -0,0 +1,1086 @@ +// lint-long-file-override allow-max-lines=1100 +#[cfg(feature = "diesel")] +use std::io::Write; + +use serde::{Deserialize, Serialize}; +use strum_macros::{Display, EnumString}; + +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + pg::Pg, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Text, +}; + +#[derive( + Debug, + Serialize, + Deserialize, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +pub enum Country { + #[serde(alias = "AFG")] + AF, + #[serde(alias = "ALA")] + AX, + #[serde(alias = "ALB")] + AL, + #[serde(alias = "DZA")] + DZ, + #[serde(alias = "ASM")] + AS, + #[serde(alias = "AND")] + AD, + #[serde(alias = "AGO")] + AO, + #[serde(alias = "AIA")] + AI, + #[serde(alias = "ATA")] + AQ, + #[serde(alias = "ATG")] + AG, + #[serde(alias = "ARG")] + AR, + #[serde(alias = "ARM")] + AM, + #[serde(alias = "ABW")] + AW, + #[serde(alias = "AUS")] + AU, + #[serde(alias = "AUT")] + AT, + #[serde(alias = "AZE")] + AZ, + #[serde(alias = "BHS")] + BS, + #[serde(alias = "BHR")] + BH, + #[serde(alias = "BGD")] + BD, + #[serde(alias = "BRB")] + BB, + #[serde(alias = "BLR")] + BY, + #[serde(alias = "BEL")] + BE, + #[serde(alias = "BLZ")] + BZ, + #[serde(alias = "BEN")] + BJ, + #[serde(alias = "BMU")] + BM, + #[serde(alias = "BTN")] + BT, + #[serde(alias = "BOL")] + BO, + #[serde(alias = "BIH")] + BA, + #[serde(alias = "BWA")] + BW, + #[serde(alias = "BVT")] + BV, + #[serde(alias = "BRA")] + BR, + #[serde(alias = "IOT")] + IO, + #[serde(alias = "VGB")] + VG, + #[serde(alias = "BRN")] + BN, + #[serde(alias = "BGR")] + BG, + #[serde(alias = "BFA")] + BF, + #[serde(alias = "BDI")] + BI, + #[serde(alias = "KHM")] + KH, + #[serde(alias = "CMR")] + CM, + #[serde(alias = "CAN")] + CA, + #[serde(alias = "CPV")] + CV, + #[serde(alias = "BES")] + BQ, + #[serde(alias = "CYM")] + KY, + #[serde(alias = "CAF")] + CF, + #[serde(alias = "TCD")] + TD, + #[serde(alias = "CHL")] + CL, + #[serde(alias = "CHN")] + CN, + #[serde(alias = "CXR")] + CX, + #[serde(alias = "CCK")] + CC, + #[serde(alias = "COL")] + CO, + #[serde(alias = "COM")] + KM, + #[serde(alias = "COG")] + CG, + #[serde(alias = "COD")] + CD, + #[serde(alias = "COK")] + CK, + #[serde(alias = "CRI")] + CR, + #[serde(alias = "CIV")] + CI, + #[serde(alias = "HRV")] + HR, + #[serde(alias = "CUB")] + CU, + #[serde(alias = "CUW")] + CW, + #[serde(alias = "CYP")] + CY, + #[serde(alias = "CZE")] + CZ, + #[serde(alias = "DNK")] + DK, + #[serde(alias = "DJI")] + DJ, + #[serde(alias = "DMA")] + DM, + #[serde(alias = "DOM")] + DO, + #[serde(alias = "ECU")] + EC, + #[serde(alias = "EGY")] + EG, + #[serde(alias = "SLV")] + SV, + #[serde(alias = "GNQ")] + GQ, + #[serde(alias = "ERI")] + ER, + #[serde(alias = "EST")] + EE, + #[serde(alias = "SWZ")] + SZ, + #[serde(alias = "ETH")] + ET, + #[serde(alias = "FLK")] + FK, + #[serde(alias = "FRO")] + FO, + #[serde(alias = "FJI")] + FJ, + #[serde(alias = "FIN")] + FI, + #[serde(alias = "FRA")] + FR, + #[serde(alias = "GUF")] + GF, + #[serde(alias = "PYF")] + PF, + #[serde(alias = "ATF")] + TF, + #[serde(alias = "GAB")] + GA, + #[serde(alias = "GMB")] + GM, + #[serde(alias = "GEO")] + GE, + #[serde(alias = "DEU")] + DE, + #[serde(alias = "GHA")] + GH, + #[serde(alias = "GIB")] + GI, + #[serde(alias = "GRC")] + GR, + #[serde(alias = "GRL")] + GL, + #[serde(alias = "GRD")] + GD, + #[serde(alias = "GLP")] + GP, + #[serde(alias = "GUM")] + GU, + #[serde(alias = "GTM")] + GT, + #[serde(alias = "GGY")] + GG, + #[serde(alias = "GIN")] + GN, + #[serde(alias = "GNB")] + GW, + #[serde(alias = "GUY")] + GY, + #[serde(alias = "HTI")] + HT, + #[serde(alias = "HMD")] + HM, + #[serde(alias = "HND")] + HN, + #[serde(alias = "HKG")] + HK, + #[serde(alias = "HUN")] + HU, + #[serde(alias = "ISL")] + IS, + #[serde(alias = "IND")] + IN, + #[serde(alias = "IDN")] + ID, + #[serde(alias = "IRN")] + IR, + #[serde(alias = "IRQ")] + IQ, + #[serde(alias = "IRL")] + IE, + #[serde(alias = "IMN")] + IM, + #[serde(alias = "ISR")] + IL, + #[serde(alias = "ITA")] + IT, + #[serde(alias = "JAM")] + JM, + #[serde(alias = "JPN")] + JP, + #[serde(alias = "JEY")] + JE, + #[serde(alias = "JOR")] + JO, + #[serde(alias = "KAZ")] + KZ, + #[serde(alias = "KEN")] + KE, + #[serde(alias = "KIR")] + KI, + #[serde(alias = "KWT")] + KW, + #[serde(alias = "KGZ")] + KG, + #[serde(alias = "LAO")] + LA, + #[serde(alias = "LVA")] + LV, + #[serde(alias = "LBN")] + LB, + #[serde(alias = "LSO")] + LS, + #[serde(alias = "LBR")] + LR, + #[serde(alias = "LBY")] + LY, + #[serde(alias = "LIE")] + LI, + #[serde(alias = "LTU")] + LT, + #[serde(alias = "LUX")] + LU, + #[serde(alias = "MAC")] + MO, + #[serde(alias = "MDG")] + MG, + #[serde(alias = "MWI")] + MW, + #[serde(alias = "MYS")] + MY, + #[serde(alias = "MDV")] + MV, + #[serde(alias = "MLI")] + ML, + #[serde(alias = "MLT")] + MT, + #[serde(alias = "MHL")] + MH, + #[serde(alias = "MTQ")] + MQ, + #[serde(alias = "MRT")] + MR, + #[serde(alias = "MUS")] + MU, + #[serde(alias = "MYT")] + YT, + #[serde(alias = "MEX")] + MX, + #[serde(alias = "FSM")] + FM, + #[serde(alias = "MDA")] + MD, + #[serde(alias = "MCO")] + MC, + #[serde(alias = "MNG")] + MN, + #[serde(alias = "MNE")] + ME, + #[serde(alias = "MSR")] + MS, + #[serde(alias = "MAR")] + MA, + #[serde(alias = "MOZ")] + MZ, + #[serde(alias = "MMR")] + MM, + #[serde(alias = "NAM")] + NA, + #[serde(alias = "NRU")] + NR, + #[serde(alias = "NPL")] + NP, + #[serde(alias = "NLD")] + NL, + #[serde(alias = "NCL")] + NC, + #[serde(alias = "NZL")] + NZ, + #[serde(alias = "NIC")] + NI, + #[serde(alias = "NER")] + NE, + #[serde(alias = "NGA")] + NG, + #[serde(alias = "NIU")] + NU, + #[serde(alias = "NFK")] + NF, + #[serde(alias = "PRK")] + KP, + #[serde(alias = "MKD")] + MK, + #[serde(alias = "MNP")] + MP, + #[serde(alias = "NOR")] + NO, + #[serde(alias = "OMN")] + OM, + #[serde(alias = "PAK")] + PK, + #[serde(alias = "PLW")] + PW, + #[serde(alias = "PSE")] + PS, + #[serde(alias = "PAN")] + PA, + #[serde(alias = "PNG")] + PG, + #[serde(alias = "PRY")] + PY, + #[serde(alias = "PER")] + PE, + #[serde(alias = "PHL")] + PH, + #[serde(alias = "PCN")] + PN, + #[serde(alias = "POL")] + PL, + #[serde(alias = "PRT")] + PT, + #[serde(alias = "PRI")] + PR, + #[serde(alias = "QAT")] + QA, + #[serde(alias = "REU")] + RE, + #[serde(alias = "ROU")] + RO, + #[serde(alias = "RUS")] + RU, + #[serde(alias = "RWA")] + RW, + #[serde(alias = "WSM")] + WS, + #[serde(alias = "SMR")] + SM, + #[serde(alias = "STP")] + ST, + #[serde(alias = "SAU")] + SA, + #[serde(alias = "SEN")] + SN, + #[serde(alias = "SRB")] + RS, + #[serde(alias = "SYC")] + SC, + #[serde(alias = "SLE")] + SL, + #[serde(alias = "SGP")] + SG, + #[serde(alias = "SXM")] + SX, + #[serde(alias = "SVK")] + SK, + #[serde(alias = "SVN")] + SI, + #[serde(alias = "SLB")] + SB, + #[serde(alias = "SOM")] + SO, + #[serde(alias = "ZAF")] + ZA, + #[serde(alias = "SGS")] + GS, + #[serde(alias = "KOR")] + KR, + #[serde(alias = "SSD")] + SS, + #[serde(alias = "ESP")] + ES, + #[serde(alias = "LKA")] + LK, + #[serde(alias = "BLM")] + BL, + #[serde(alias = "SHN")] + SH, + #[serde(alias = "KNA")] + KN, + #[serde(alias = "LCA")] + LC, + #[serde(alias = "MAF")] + MF, + #[serde(alias = "SPM")] + PM, + #[serde(alias = "VCT")] + VC, + #[serde(alias = "SDN")] + SD, + #[serde(alias = "SUR")] + SR, + #[serde(alias = "SJM")] + SJ, + #[serde(alias = "SWE")] + SE, + #[serde(alias = "CHE")] + CH, + #[serde(alias = "SYR")] + SY, + #[serde(alias = "TWN")] + TW, + #[serde(alias = "TJK")] + TJ, + #[serde(alias = "TZA")] + TZ, + #[serde(alias = "THA")] + TH, + #[serde(alias = "TLS")] + TL, + #[serde(alias = "TGO")] + TG, + #[serde(alias = "TKL")] + TK, + #[serde(alias = "TON")] + TO, + #[serde(alias = "TTO")] + TT, + #[serde(alias = "TUN")] + TN, + #[serde(alias = "TUR")] + TR, + #[serde(alias = "TKM")] + TM, + #[serde(alias = "TCA")] + TC, + #[serde(alias = "TUV")] + TV, + #[serde(alias = "UMI")] + UM, + #[serde(alias = "VIR")] + VI, + #[serde(alias = "UGA")] + UG, + #[serde(alias = "UKR")] + UA, + #[serde(alias = "ARE")] + AE, + #[serde(alias = "GBR")] + GB, + #[serde(alias = "USA")] + US, + #[serde(alias = "URY")] + UY, + #[serde(alias = "UZB")] + UZ, + #[serde(alias = "VUT")] + VU, + #[serde(alias = "VAT")] + VA, + #[serde(alias = "VEN")] + VE, + #[serde(alias = "VNM")] + VN, + #[serde(alias = "WLF")] + WF, + #[serde(alias = "ESH")] + EH, + #[serde(alias = "YEM")] + YE, + #[serde(alias = "ZMB")] + ZM, + #[serde(alias = "ZWE")] + ZW, + + // Abnormal + #[serde(alias = "EU")] + EU, + #[serde(alias = "XX")] + XX, +} + +impl Country { + pub fn to_country_name(self) -> &'static str { + match self { + Country::AF => "Afghanistan", + Country::AX => "Åland Islands", + Country::AL => "Albania", + Country::DZ => "Algeria", + Country::AS => "American Samoa", + Country::AD => "Andorra", + Country::AO => "Angola", + Country::AI => "Anguilla", + Country::AQ => "Antarctica", + Country::AG => "Antigua and Barbuda", + Country::AR => "Argentina", + Country::AM => "Armenia", + Country::AW => "Aruba", + Country::AU => "Australia", + Country::AT => "Austria", + Country::AZ => "Azerbaijan", + Country::BS => "Bahamas", + Country::BH => "Bahrain", + Country::BD => "Bangladesh", + Country::BB => "Barbados", + Country::BY => "Belarus", + Country::BE => "Belgium", + Country::BZ => "Belize", + Country::BJ => "Benin", + Country::BM => "Bermuda", + Country::BT => "Bhutan", + Country::BO => "Bolivia", + Country::BQ => "Bonaire, Sint Eustatius and Saba", + Country::BA => "Bosnia and Herzegovina", + Country::BW => "Botswana", + Country::BV => "Bouvet Island", + Country::BR => "Brazil", + Country::IO => "British Indian Ocean Territory", + Country::BN => "Brunei Darussalam", + Country::BG => "Bulgaria", + Country::BF => "Burkina Faso", + Country::BI => "Burundi", + Country::KH => "Cambodia", + Country::CM => "Cameroon", + Country::CA => "Canada", + Country::CV => "Cape Verde", + Country::KY => "Cayman Islands", + Country::CF => "Central African Republic", + Country::TD => "Chad", + Country::CL => "Chile", + Country::CN => "China", + Country::CX => "Christmas Island", + Country::CC => "Cocos (Keeling) Islands", + Country::CO => "Colombia", + Country::KM => "Comoros", + Country::CG => "Congo", + Country::CD => "Congo, Democratic Republic of the", + Country::CK => "Cook Islands", + Country::CR => "Costa Rica", + Country::CI => "Côte d'Ivoire", + Country::HR => "Croatia", + Country::CU => "Cuba", + Country::CW => "Curaçao", + Country::CY => "Cyprus", + Country::CZ => "Czech Republic", + Country::DK => "Denmark", + Country::DJ => "Djibouti", + Country::DM => "Dominica", + Country::DO => "Dominican Republic", + Country::EC => "Ecuador", + Country::EG => "Egypt", + Country::SV => "El Salvador", + Country::GQ => "Equatorial Guinea", + Country::ER => "Eritrea", + Country::EE => "Estonia", + Country::ET => "Ethiopia", + Country::FK => "Falkland Islands (Malvinas)", + Country::FO => "Faroe Islands", + Country::FJ => "Fiji", + Country::FI => "Finland", + Country::FR => "France", + Country::GF => "French Guiana", + Country::PF => "French Polynesia", + Country::TF => "French Southern Territories", + Country::GA => "Gabon", + Country::GM => "Gambia", + Country::GE => "Georgia", + Country::DE => "Germany", + Country::GH => "Ghana", + Country::GI => "Gibraltar", + Country::GR => "Greece", + Country::GL => "Greenland", + Country::GD => "Grenada", + Country::GP => "Guadeloupe", + Country::GU => "Guam", + Country::GT => "Guatemala", + Country::GG => "Guernsey", + Country::GN => "Guinea", + Country::GW => "Guinea-Bissau", + Country::GY => "Guyana", + Country::HT => "Haiti", + Country::HM => "Heard Island and McDonald Islands", + Country::VA => "Holy See (Vatican City State)", + Country::HN => "Honduras", + Country::HK => "Hong Kong", + Country::HU => "Hungary", + Country::IS => "Iceland", + Country::IN => "India", + Country::ID => "Indonesia", + Country::IR => "Iran", + Country::IQ => "Iraq", + Country::IE => "Ireland", + Country::IM => "Isle of Man", + Country::IL => "Israel", + Country::IT => "Italy", + Country::JM => "Jamaica", + Country::JP => "Japan", + Country::JE => "Jersey", + Country::JO => "Jordan", + Country::KZ => "Kazakhstan", + Country::KE => "Kenya", + Country::KI => "Kiribati", + Country::KP => "Korea, Democratic People's Republic of", + Country::KR => "Korea, Republic of", + Country::KW => "Kuwait", + Country::KG => "Kyrgyzstan", + Country::LA => "Lao People's Democratic Republic", + Country::LV => "Latvia", + Country::LB => "Lebanon", + Country::LS => "Lesotho", + Country::LR => "Liberia", + Country::LY => "Libya", + Country::LI => "Liechtenstein", + Country::LT => "Lithuania", + Country::LU => "Luxembourg", + Country::MO => "Macao", + Country::MK => "Macedonia", + Country::MG => "Madagascar", + Country::MW => "Malawi", + Country::MY => "Malaysia", + Country::MV => "Maldives", + Country::ML => "Mali", + Country::MT => "Malta", + Country::MH => "Marshall Islands", + Country::MQ => "Martinique", + Country::MR => "Mauritania", + Country::MU => "Mauritius", + Country::YT => "Mayotte", + Country::MX => "Mexico", + Country::FM => "Micronesia", + Country::MD => "Moldova", + Country::MC => "Monaco", + Country::MN => "Mongolia", + Country::ME => "Montenegro", + Country::MS => "Montserrat", + Country::MA => "Morocco", + Country::MZ => "Mozambique", + Country::MM => "Myanmar", + Country::NA => "Namibia", + Country::NR => "Nauru", + Country::NP => "Nepal", + Country::NL => "Netherlands", + Country::NC => "New Caledonia", + Country::NZ => "New Zealand", + Country::NI => "Nicaragua", + Country::NE => "Niger", + Country::NG => "Nigeria", + Country::NU => "Niue", + Country::NF => "Norfolk Island", + Country::MP => "Northern Mariana Islands", + Country::NO => "Norway", + Country::OM => "Oman", + Country::PK => "Pakistan", + Country::PW => "Palau", + Country::PS => "Palestine", + Country::PA => "Panama", + Country::PG => "Papua New Guinea", + Country::PY => "Paraguay", + Country::PE => "Peru", + Country::PH => "Philippines", + Country::PN => "Pitcairn", + Country::PL => "Poland", + Country::PT => "Portugal", + Country::PR => "Puerto Rico", + Country::QA => "Qatar", + Country::RE => "Réunion", + Country::RO => "Romania", + Country::RU => "Russian Federation", + Country::RW => "Rwanda", + Country::BL => "Saint Barthélemy", + Country::SH => "Saint Helena", + Country::KN => "Saint Kitts and Nevis", + Country::LC => "Saint Lucia", + Country::MF => "Saint Martin (French part)", + Country::PM => "Saint Pierre and Miquelon", + Country::VC => "Saint Vincent and the Grenadines", + Country::WS => "Samoa", + Country::SM => "San Marino", + Country::ST => "Sao Tome and Principe", + Country::SA => "Saudi Arabia", + Country::SN => "Senegal", + Country::RS => "Serbia", + Country::SC => "Seychelles", + Country::SL => "Sierra Leone", + Country::SG => "Singapore", + Country::SX => "Sint Maarten (Dutch part)", + Country::SK => "Slovakia", + Country::SI => "Slovenia", + Country::SB => "Solomon Islands", + Country::SO => "Somalia", + Country::ZA => "South Africa", + Country::GS => "South Georgia and the South Sandwich Islands", + Country::SS => "South Sudan", + Country::ES => "Spain", + Country::LK => "Sri Lanka", + Country::SD => "Sudan", + Country::SR => "Suriname", + Country::SJ => "Svalbard and Jan Mayen", + Country::SZ => "Swaziland", + Country::SE => "Sweden", + Country::CH => "Switzerland", + Country::SY => "Syrian Arab Republic", + Country::TW => "Taiwan", + Country::TJ => "Tajikistan", + Country::TZ => "Tanzania", + Country::TH => "Thailand", + Country::TL => "Timor-Leste", + Country::TG => "Togo", + Country::TK => "Tokelau", + Country::TO => "Tonga", + Country::TT => "Trinidad and Tobago", + Country::TN => "Tunisia", + Country::TR => "Turkey", + Country::TM => "Turkmenistan", + Country::TC => "Turks and Caicos Islands", + Country::TV => "Tuvalu", + Country::UG => "Uganda", + Country::UA => "Ukraine", + Country::AE => "United Arab Emirates", + Country::GB => "United Kingdom", + Country::US => "United States", + Country::UM => "United States Minor Outlying Islands", + Country::UY => "Uruguay", + Country::UZ => "Uzbekistan", + Country::VU => "Vanuatu", + Country::VE => "Venezuela", + Country::VN => "Vietnam", + Country::VG => "Virgin Islands, British", + Country::VI => "Virgin Islands, U.S.", + Country::WF => "Wallis and Futuna", + Country::EH => "Western Sahara", + Country::YE => "Yemen", + Country::ZM => "Zambia", + Country::ZW => "Zimbabwe", + + // Abnormal + Country::EU => "European Union", + Country::XX => "Global", + } + } + pub fn three_letter_name(self) -> &'static str { + match self { + Country::AF => "AFG", + Country::AX => "ALA", + Country::AL => "ALB", + Country::DZ => "DZA", + Country::AS => "ASM", + Country::AD => "AND", + Country::AO => "AGO", + Country::AI => "AIA", + Country::AQ => "ATA", + Country::AG => "ATG", + Country::AR => "ARG", + Country::AM => "ARM", + Country::AW => "ABW", + Country::AU => "AUS", + Country::AT => "AUT", + Country::AZ => "AZE", + Country::BS => "BHS", + Country::BH => "BHR", + Country::BD => "BGD", + Country::BB => "BRB", + Country::BY => "BLR", + Country::BE => "BEL", + Country::BZ => "BLZ", + Country::BJ => "BEN", + Country::BM => "BMU", + Country::BT => "BTN", + Country::BO => "BOL", + Country::BA => "BIH", + Country::BW => "BWA", + Country::BV => "BVT", + Country::BR => "BRA", + Country::IO => "IOT", + Country::VG => "VGB", + Country::BN => "BRN", + Country::BG => "BGR", + Country::BF => "BFA", + Country::BI => "BDI", + Country::KH => "KHM", + Country::CM => "CMR", + Country::CA => "CAN", + Country::CV => "CPV", + Country::BQ => "BES", + Country::KY => "CYM", + Country::CF => "CAF", + Country::TD => "TCD", + Country::CL => "CHL", + Country::CN => "CHN", + Country::CX => "CXR", + Country::CC => "CCK", + Country::CO => "COL", + Country::KM => "COM", + Country::CG => "COG", + Country::CD => "COD", + Country::CK => "COK", + Country::CR => "CRI", + Country::CI => "CIV", + Country::HR => "HRV", + Country::CU => "CUB", + Country::CW => "CUW", + Country::CY => "CYP", + Country::CZ => "CZE", + Country::DK => "DNK", + Country::DJ => "DJI", + Country::DM => "DMA", + Country::DO => "DOM", + Country::EC => "ECU", + Country::EG => "EGY", + Country::SV => "SLV", + Country::GQ => "GNQ", + Country::ER => "ERI", + Country::EE => "EST", + Country::SZ => "SWZ", + Country::ET => "ETH", + Country::FK => "FLK", + Country::FO => "FRO", + Country::FJ => "FJI", + Country::FI => "FIN", + Country::FR => "FRA", + Country::GF => "GUF", + Country::PF => "PYF", + Country::TF => "ATF", + Country::GA => "GAB", + Country::GM => "GMB", + Country::GE => "GEO", + Country::DE => "DEU", + Country::GH => "GHA", + Country::GI => "GIB", + Country::GR => "GRC", + Country::GL => "GRL", + Country::GD => "GRD", + Country::GP => "GLP", + Country::GU => "GUM", + Country::GT => "GTM", + Country::GG => "GGY", + Country::GN => "GIN", + Country::GW => "GNB", + Country::GY => "GUY", + Country::HT => "HTI", + Country::HM => "HMD", + Country::HN => "HND", + Country::HK => "HKG", + Country::HU => "HUN", + Country::IS => "ISL", + Country::IN => "IND", + Country::ID => "IDN", + Country::IR => "IRN", + Country::IQ => "IRQ", + Country::IE => "IRL", + Country::IM => "IMN", + Country::IL => "ISR", + Country::IT => "ITA", + Country::JM => "JAM", + Country::JP => "JPN", + Country::JE => "JEY", + Country::JO => "JOR", + Country::KZ => "KAZ", + Country::KE => "KEN", + Country::KI => "KIR", + Country::KW => "KWT", + Country::KG => "KGZ", + Country::LA => "LAO", + Country::LV => "LVA", + Country::LB => "LBN", + Country::LS => "LSO", + Country::LR => "LBR", + Country::LY => "LBY", + Country::LI => "LIE", + Country::LT => "LTU", + Country::LU => "LUX", + Country::MO => "MAC", + Country::MG => "MDG", + Country::MW => "MWI", + Country::MY => "MYS", + Country::MV => "MDV", + Country::ML => "MLI", + Country::MT => "MLT", + Country::MH => "MHL", + Country::MQ => "MTQ", + Country::MR => "MRT", + Country::MU => "MUS", + Country::YT => "MYT", + Country::MX => "MEX", + Country::FM => "FSM", + Country::MD => "MDA", + Country::MC => "MCO", + Country::MN => "MNG", + Country::ME => "MNE", + Country::MS => "MSR", + Country::MA => "MAR", + Country::MZ => "MOZ", + Country::MM => "MMR", + Country::NA => "NAM", + Country::NR => "NRU", + Country::NP => "NPL", + Country::NL => "NLD", + Country::NC => "NCL", + Country::NZ => "NZL", + Country::NI => "NIC", + Country::NE => "NER", + Country::NG => "NGA", + Country::NU => "NIU", + Country::NF => "NFK", + Country::KP => "PRK", + Country::MK => "MKD", + Country::MP => "MNP", + Country::NO => "NOR", + Country::OM => "OMN", + Country::PK => "PAK", + Country::PW => "PLW", + Country::PS => "PSE", + Country::PA => "PAN", + Country::PG => "PNG", + Country::PY => "PRY", + Country::PE => "PER", + Country::PH => "PHL", + Country::PN => "PCN", + Country::PL => "POL", + Country::PT => "PRT", + Country::PR => "PRI", + Country::QA => "QAT", + Country::RE => "REU", + Country::RO => "ROU", + Country::RU => "RUS", + Country::RW => "RWA", + Country::WS => "WSM", + Country::SM => "SMR", + Country::ST => "STP", + Country::SA => "SAU", + Country::SN => "SEN", + Country::RS => "SRB", + Country::SC => "SYC", + Country::SL => "SLE", + Country::SG => "SGP", + Country::SX => "SXM", + Country::SK => "SVK", + Country::SI => "SVN", + Country::SB => "SLB", + Country::SO => "SOM", + Country::ZA => "ZAF", + Country::GS => "SGS", + Country::KR => "KOR", + Country::SS => "SSD", + Country::ES => "ESP", + Country::LK => "LKA", + Country::BL => "BLM", + Country::SH => "SHN", + Country::KN => "KNA", + Country::LC => "LCA", + Country::MF => "MAF", + Country::PM => "SPM", + Country::VC => "VCT", + Country::SD => "SDN", + Country::SR => "SUR", + Country::SJ => "SJM", + Country::SE => "SWE", + Country::CH => "CHE", + Country::SY => "SYR", + Country::TW => "TWN", + Country::TJ => "TJK", + Country::TZ => "TZA", + Country::TH => "THA", + Country::TL => "TLS", + Country::TG => "TGO", + Country::TK => "TKL", + Country::TO => "TON", + Country::TT => "TTO", + Country::TN => "TUN", + Country::TR => "TUR", + Country::TM => "TKM", + Country::TC => "TCA", + Country::TV => "TUV", + Country::UM => "UMI", + Country::VI => "VIR", + Country::UG => "UGA", + Country::UA => "UKR", + Country::AE => "ARE", + Country::GB => "GBR", + Country::US => "USA", + Country::UY => "URY", + Country::UZ => "UZB", + Country::VU => "VUT", + Country::VA => "VAT", + Country::VE => "VEN", + Country::VN => "VNM", + Country::WF => "WLF", + Country::EH => "ESH", + Country::YE => "YEM", + Country::ZM => "ZMB", + Country::ZW => "ZWE", + + // Abnormal + Country::EU => "EUR", + Country::XX => "XXX", + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct CountryList(pub Vec); + +impl From for Vec { + fn from(countries: CountryList) -> Self { + countries.0.iter().map(|c| c.to_string()).collect() + } +} + +impl CountryList { + pub fn first(&self) -> Option<&Country> { + self.0.first() + } +} + +#[cfg(feature = "diesel")] +impl ToSql for Country { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Country { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized country".into()) + } +} diff --git a/pkg/currency/Cargo.toml b/pkg/currency/Cargo.toml new file mode 100644 index 0000000..fc1c5af --- /dev/null +++ b/pkg/currency/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "currency" +version = "0.1.0" +edition = "2024" + +[features] +diesel = ["dep:diesel", "country/diesel"] +ts-rs = ["dep:ts-rs", "element/ts-rs"] + +[dependencies] +country = { workspace = true } +element = { workspace = true } +diesel = { workspace = true, optional = true, features = ["postgres_backend"] } +serde = { workspace = true } +serde_json = { workspace = true } +strum_macros = { workspace = true } +strum = { workspace = true } +thiserror = { workspace = true } +ts-rs = { workspace = true, optional = true } +workspace-hack.workspace = true + +[package.metadata.cargo-machete] +ignored = ["strum"] diff --git a/pkg/currency/README.md b/pkg/currency/README.md new file mode 100644 index 0000000..6e59279 --- /dev/null +++ b/pkg/currency/README.md @@ -0,0 +1,15 @@ +# Currency + +Currency and country code management with error handling. + +## Overview + +This package provides currency and country code definitions and utilities for international financial operations. + +## Features + +- Currency code definitions +- Country code management +- Currency conversion utilities +- Error handling for invalid codes + diff --git a/pkg/currency/src/currency.rs b/pkg/currency/src/currency.rs new file mode 100644 index 0000000..56446bc --- /dev/null +++ b/pkg/currency/src/currency.rs @@ -0,0 +1,1010 @@ +// lint-long-file-override allow-max-lines=1100 +#[cfg(feature = "diesel")] +use std::io::Write; + +use country::Country; +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + pg::Pg, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Text, +}; +use element::Element; +use serde::{Deserialize, Serialize}; +use strum_macros::{Display, EnumString}; + +use crate::error::{Error, Result}; + +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +#[allow(clippy::upper_case_acronyms)] +#[derive( + Debug, + Serialize, + Deserialize, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum Currency { + // Fiat + AED, + AFN, + ALL, + AMD, + ANG, + AOA, + ARS, + AUD, + AWG, + AZN, + BAM, + BBD, + BDT, + BGN, + BHD, + BIF, + BMD, + BND, + BOB, + BRL, + BSD, + BTN, + BWP, + BYN, + BZD, + CAD, + CDF, + CHF, + CLP, + CNY, + COP, + CRC, + CUP, + CVE, + CZK, + DJF, + DKK, + DOP, + DZD, + EGP, + ERN, + ETB, + EUR, + FJD, + FKP, + GBP, + GEL, + GHS, + GIP, + GMD, + GNF, + GTQ, + GYD, + HKD, + HNL, + HRK, + HTG, + HUF, + IDR, + ILS, + INR, + IQD, + IRR, + ISK, + JMD, + JOD, + JPY, + KES, + KGS, + KHR, + KMF, + KPW, + KRW, + KWD, + KYD, + KZT, + LAK, + LBP, + LKR, + LRD, + LSL, + LYD, + MAD, + MDL, + MGA, + MKD, + MMK, + MNT, + MOP, + MRU, + MUR, + MVR, + MWK, + MXN, + MYR, + MZN, + NAD, + NGN, + NIO, + NOK, + NPR, + NZD, + OMR, + PAB, + PEN, + PGK, + PHP, + PKR, + PLN, + PYG, + QAR, + RON, + RSD, + RUB, + RWF, + SAR, + SBD, + SCR, + SDG, + SEK, + SGD, + SHP, + SLL, + SOS, + SRD, + SSP, + STN, + SVC, + SYP, + SZL, + THB, + TJS, + TMT, + TND, + TOP, + TRY, + TTD, + TWD, + TZS, + UAH, + UGX, + USD, + UYU, + UZS, + VES, + VND, + VUV, + WST, + XAF, + XCD, + XOF, + XPF, + YER, + ZAR, + ZMW, + ZWL, + + // Crypto + USDC, + ETH, +} + +#[cfg(feature = "diesel")] +impl ToSql for Currency { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Currency { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized method kind".into()) + } +} + +impl Currency { + pub fn from_str_code(code: &str) -> Result { + code.to_ascii_uppercase() + .parse() + .map_err(|_| Error::InvalidCurrencyCode) + } + + pub fn decimals(&self) -> u32 { + match self { + // Fiat currencies typically have 2 decimals + Currency::AED => 2, + Currency::AFN => 2, + Currency::ALL => 2, + Currency::AMD => 2, + Currency::ANG => 2, + Currency::AOA => 2, + Currency::ARS => 2, + Currency::AUD => 2, + Currency::AWG => 2, + Currency::AZN => 2, + Currency::BAM => 2, + Currency::BBD => 2, + Currency::BDT => 2, + Currency::BGN => 2, + Currency::BHD => 3, // Bahraini dinar has 3 decimals + Currency::BIF => 0, // Burundian franc has no decimals + Currency::BMD => 2, + Currency::BND => 2, + Currency::BOB => 2, + Currency::BRL => 2, + Currency::BSD => 2, + Currency::BTN => 2, + Currency::BWP => 2, + Currency::BYN => 2, + Currency::BZD => 2, + Currency::CAD => 2, + Currency::CDF => 2, + Currency::CHF => 2, + Currency::CLP => 0, // Chilean peso has no decimals + Currency::CNY => 2, + Currency::COP => 2, + Currency::CRC => 2, + Currency::CUP => 2, + Currency::CVE => 2, + Currency::CZK => 2, + Currency::DJF => 0, // Djiboutian franc has no decimals + Currency::DKK => 2, + Currency::DOP => 2, + Currency::DZD => 2, + Currency::EGP => 2, + Currency::ERN => 2, + Currency::ETB => 2, + Currency::EUR => 2, + Currency::FJD => 2, + Currency::FKP => 2, + Currency::GBP => 2, + Currency::GEL => 2, + Currency::GHS => 2, + Currency::GIP => 2, + Currency::GMD => 2, + Currency::GNF => 0, // Guinean franc has no decimals + Currency::GTQ => 2, + Currency::GYD => 2, + Currency::HKD => 2, + Currency::HNL => 2, + Currency::HRK => 2, + Currency::HTG => 2, + Currency::HUF => 2, + Currency::IDR => 2, + Currency::ILS => 2, + Currency::INR => 2, + Currency::IQD => 3, // Iraqi dinar has 3 decimals + Currency::IRR => 2, + Currency::ISK => 0, // Icelandic króna has no decimals + Currency::JMD => 2, + Currency::JOD => 3, // Jordanian dinar has 3 decimals + Currency::JPY => 0, // Japanese yen has no decimals + Currency::KES => 2, + Currency::KGS => 2, + Currency::KHR => 2, + Currency::KMF => 0, // Comorian franc has no decimals + Currency::KPW => 2, + Currency::KRW => 0, // South Korean won has no decimals + Currency::KWD => 3, // Kuwaiti dinar has 3 decimals + Currency::KYD => 2, + Currency::KZT => 2, + Currency::LAK => 2, + Currency::LBP => 2, + Currency::LKR => 2, + Currency::LRD => 2, + Currency::LSL => 2, + Currency::LYD => 3, // Libyan dinar has 3 decimals + Currency::MAD => 2, + Currency::MDL => 2, + Currency::MGA => 2, + Currency::MKD => 2, + Currency::MMK => 2, + Currency::MNT => 2, + Currency::MOP => 2, + Currency::MRU => 2, + Currency::MUR => 2, + Currency::MVR => 2, + Currency::MWK => 2, + Currency::MXN => 2, + Currency::MYR => 2, + Currency::MZN => 2, + Currency::NAD => 2, + Currency::NGN => 2, + Currency::NIO => 2, + Currency::NOK => 2, + Currency::NPR => 2, + Currency::NZD => 2, + Currency::OMR => 3, // Omani rial has 3 decimals + Currency::PAB => 2, + Currency::PEN => 2, + Currency::PGK => 2, + Currency::PHP => 2, + Currency::PKR => 2, + Currency::PLN => 2, + Currency::PYG => 0, // Paraguayan guaraní has no decimals + Currency::QAR => 2, + Currency::RON => 2, + Currency::RSD => 2, + Currency::RUB => 2, + Currency::RWF => 0, // Rwandan franc has no decimals + Currency::SAR => 2, + Currency::SBD => 2, + Currency::SCR => 2, + Currency::SDG => 2, + Currency::SEK => 2, + Currency::SGD => 2, + Currency::SHP => 2, + Currency::SLL => 2, + Currency::SOS => 2, + Currency::SRD => 2, + Currency::SSP => 2, + Currency::STN => 2, + Currency::SVC => 2, + Currency::SYP => 2, + Currency::SZL => 2, + Currency::THB => 2, + Currency::TJS => 2, + Currency::TMT => 2, + Currency::TND => 3, // Tunisian dinar has 3 decimals + Currency::TOP => 2, + Currency::TRY => 2, + Currency::TTD => 2, + Currency::TWD => 2, + Currency::TZS => 2, + Currency::UAH => 2, + Currency::UGX => 0, // Ugandan shilling has no decimals + Currency::USD => 2, + Currency::UYU => 2, + Currency::UZS => 2, + Currency::VES => 2, + Currency::VND => 0, // Vietnamese đồng has no decimals + Currency::VUV => 0, // Vanuatu vatu has no decimals + Currency::WST => 2, + Currency::XAF => 0, // CFA franc BEAC has no decimals + Currency::XCD => 2, + Currency::XOF => 0, // CFA franc BCEAO has no decimals + Currency::XPF => 0, // CFP franc has no decimals + Currency::YER => 2, + Currency::ZAR => 2, + Currency::ZMW => 2, + Currency::ZWL => 2, + + // Crypto + Currency::USDC => 6, + Currency::ETH => 18, + } + } + + pub fn to_country(self) -> Country { + match self { + Currency::AED => Country::AE, + Currency::AFN => Country::AF, + Currency::ALL => Country::AL, + Currency::AMD => Country::AM, + Currency::ANG => Country::CW, + Currency::AOA => Country::AO, + Currency::ARS => Country::AR, + Currency::AUD => Country::AU, + Currency::AWG => Country::AW, + Currency::AZN => Country::AZ, + Currency::BAM => Country::BA, + Currency::BBD => Country::BB, + Currency::BDT => Country::BD, + Currency::BGN => Country::BG, + Currency::BHD => Country::BH, + Currency::BIF => Country::BI, + Currency::BMD => Country::BM, + Currency::BND => Country::BN, + Currency::BOB => Country::BO, + Currency::BRL => Country::BR, + Currency::BSD => Country::BS, + Currency::BTN => Country::BT, + Currency::BWP => Country::BW, + Currency::BYN => Country::BY, + Currency::BZD => Country::BZ, + Currency::CAD => Country::CA, + Currency::CDF => Country::CD, + Currency::CHF => Country::CH, + Currency::CLP => Country::CL, + Currency::CNY => Country::CN, + Currency::COP => Country::CO, + Currency::CRC => Country::CR, + Currency::CUP => Country::CU, + Currency::CVE => Country::CV, + Currency::CZK => Country::CZ, + Currency::DJF => Country::DJ, + Currency::DKK => Country::DK, + Currency::DOP => Country::DO, + Currency::DZD => Country::DZ, + Currency::EGP => Country::EG, + Currency::ERN => Country::ER, + Currency::ETB => Country::ET, + Currency::EUR => Country::EU, + Currency::FJD => Country::FJ, + Currency::FKP => Country::FK, + Currency::GBP => Country::GB, + Currency::GEL => Country::GE, + Currency::GHS => Country::GH, + Currency::GIP => Country::GI, + Currency::GMD => Country::GM, + Currency::GNF => Country::GN, + Currency::GTQ => Country::GT, + Currency::GYD => Country::GY, + Currency::HKD => Country::HK, + Currency::HNL => Country::HN, + Currency::HRK => Country::HR, + Currency::HTG => Country::HT, + Currency::HUF => Country::HU, + Currency::IDR => Country::ID, + Currency::ILS => Country::IL, + Currency::INR => Country::IN, + Currency::IQD => Country::IQ, + Currency::IRR => Country::IR, + Currency::ISK => Country::IS, + Currency::JMD => Country::JM, + Currency::JOD => Country::JO, + Currency::JPY => Country::JP, + Currency::KES => Country::KE, + Currency::KGS => Country::KG, + Currency::KHR => Country::KH, + Currency::KMF => Country::KM, + Currency::KPW => Country::KP, + Currency::KRW => Country::KR, + Currency::KWD => Country::KW, + Currency::KYD => Country::KY, + Currency::KZT => Country::KZ, + Currency::LAK => Country::LA, + Currency::LBP => Country::LB, + Currency::LKR => Country::LK, + Currency::LRD => Country::LR, + Currency::LSL => Country::LS, + Currency::LYD => Country::LY, + Currency::MAD => Country::MA, + Currency::MDL => Country::MD, + Currency::MGA => Country::MG, + Currency::MKD => Country::MK, + Currency::MMK => Country::MM, + Currency::MNT => Country::MN, + Currency::MOP => Country::MO, + Currency::MRU => Country::MR, + Currency::MUR => Country::MU, + Currency::MVR => Country::MV, + Currency::MWK => Country::MW, + Currency::MXN => Country::MX, + Currency::MYR => Country::MY, + Currency::MZN => Country::MZ, + Currency::NAD => Country::NA, + Currency::NGN => Country::NG, + Currency::NIO => Country::NI, + Currency::NOK => Country::NO, + Currency::NPR => Country::NP, + Currency::NZD => Country::NZ, + Currency::OMR => Country::OM, + Currency::PAB => Country::PA, + Currency::PEN => Country::PE, + Currency::PGK => Country::PG, + Currency::PHP => Country::PH, + Currency::PKR => Country::PK, + Currency::PLN => Country::PL, + Currency::PYG => Country::PY, + Currency::QAR => Country::QA, + Currency::RON => Country::RO, + Currency::RSD => Country::RS, + Currency::RUB => Country::RU, + Currency::RWF => Country::RW, + Currency::SAR => Country::SA, + Currency::SBD => Country::SB, + Currency::SCR => Country::SC, + Currency::SDG => Country::SD, + Currency::SEK => Country::SE, + Currency::SGD => Country::SG, + Currency::SHP => Country::SH, + Currency::SLL => Country::SL, + Currency::SOS => Country::SO, + Currency::SRD => Country::SR, + Currency::SSP => Country::SS, + Currency::STN => Country::ST, + Currency::SVC => Country::SV, + Currency::SYP => Country::SY, + Currency::SZL => Country::SZ, + Currency::THB => Country::TH, + Currency::TJS => Country::TJ, + Currency::TMT => Country::TM, + Currency::TND => Country::TN, + Currency::TOP => Country::TO, + Currency::TRY => Country::TR, + Currency::TTD => Country::TT, + Currency::TWD => Country::TW, + Currency::TZS => Country::TZ, + Currency::UAH => Country::UA, + Currency::UGX => Country::UG, + Currency::USD => Country::US, + Currency::UYU => Country::UY, + Currency::UZS => Country::UZ, + Currency::VES => Country::VE, + Currency::VND => Country::VN, + Currency::VUV => Country::VU, + Currency::WST => Country::WS, + Currency::XAF => Country::CM, // Central African CFA franc + Currency::XCD => Country::AG, // East Caribbean dollar + Currency::XOF => Country::BJ, // West African CFA franc + Currency::XPF => Country::PF, // CFP franc + Currency::YER => Country::YE, + Currency::ZAR => Country::ZA, + Currency::ZMW => Country::ZM, + Currency::ZWL => Country::ZW, + + // Crypto + Currency::USDC => Country::US, + Currency::ETH => Country::XX, + } + } + + pub fn format(&self, value: &Element) -> String { + let decimal_str = self.to_decimal_string(value); + let parts: Vec<&str> = decimal_str.split('.').collect(); + + // Format integer part with thousand separators + let int_part = parts[0] + .chars() + .rev() + .collect::>() + .chunks(3) + .map(|chunk| chunk.iter().collect::()) + .collect::>() + .join(",") + .chars() + .rev() + .collect::(); + + // Combine with decimal part if it exists and is not all zeros + let formatted = if parts.len() > 1 { + let decimal_part = parts[1].trim_end_matches('0'); + if decimal_part.is_empty() { + int_part + } else { + // Ensure at least 2 decimal places are shown + let min_decimals = if decimal_part.len() == 1 { + 2 + } else { + decimal_part.len() + }; + let padded_decimal = format!("{decimal_part:0 String { + match self { + Currency::AED => format!("د.إ{formatted}"), + Currency::AFN => format!("؋{formatted}"), + Currency::ALL => format!("L{formatted}"), + Currency::AMD => format!("֏{formatted}"), + Currency::ANG => format!("ƒ{formatted}"), + Currency::AOA => format!("Kz{formatted}"), + Currency::ARS => format!("${formatted}"), + Currency::AUD => format!("A${formatted}"), + Currency::AWG => format!("ƒ{formatted}"), + Currency::AZN => format!("₼{formatted}"), + Currency::BAM => format!("KM{formatted}"), + Currency::BBD => format!("Bds${formatted}"), + Currency::BDT => format!("৳{formatted}"), + Currency::BGN => format!("лв{formatted}"), + Currency::BHD => format!(".د.ب{formatted}"), + Currency::BIF => format!("FBu{formatted}"), + Currency::BMD => format!("BD${formatted}"), + Currency::BND => format!("B${formatted}"), + Currency::BOB => format!("Bs{formatted}"), + Currency::BRL => format!("R${formatted}"), + Currency::BSD => format!("B${formatted}"), + Currency::BTN => format!("Nu.{formatted}"), + Currency::BWP => format!("P{formatted}"), + Currency::BYN => format!("Br{formatted}"), + Currency::BZD => format!("BZ${formatted}"), + Currency::CAD => format!("C${formatted}"), + Currency::CDF => format!("FC{formatted}"), + Currency::CHF => format!("CHF{formatted}"), + Currency::CLP => format!("CLP${formatted}"), + Currency::CNY => format!("¥{formatted}"), + Currency::COP => format!("${formatted}"), + Currency::CRC => format!("₡{formatted}"), + Currency::CUP => format!("₱{formatted}"), + Currency::CVE => format!("${formatted}"), + Currency::CZK => format!("Kč{formatted}"), + Currency::DJF => format!("Fdj{formatted}"), + Currency::DKK => format!("kr{formatted}"), + Currency::DOP => format!("RD${formatted}"), + Currency::DZD => format!("دج{formatted}"), + Currency::EGP => format!("E£{formatted}"), + Currency::ERN => format!("Nfk{formatted}"), + Currency::ETB => format!("Br{formatted}"), + Currency::EUR => format!("€{formatted}"), + Currency::FJD => format!("FJ${formatted}"), + Currency::FKP => format!("£{formatted}"), + Currency::GBP => format!("£{formatted}"), + Currency::GEL => format!("₾{formatted}"), + Currency::GHS => format!("GH₵{formatted}"), + Currency::GIP => format!("£{formatted}"), + Currency::GMD => format!("D{formatted}"), + Currency::GNF => format!("FG{formatted}"), + Currency::GTQ => format!("Q{formatted}"), + Currency::GYD => format!("G${formatted}"), + Currency::HKD => format!("HK${formatted}"), + Currency::HNL => format!("L{formatted}"), + Currency::HRK => format!("kn{formatted}"), + Currency::HTG => format!("G{formatted}"), + Currency::HUF => format!("Ft{formatted}"), + Currency::IDR => format!("Rp{formatted}"), + Currency::ILS => format!("₪{formatted}"), + Currency::INR => format!("₹{formatted}"), + Currency::IQD => format!("ع.د{formatted}"), + Currency::IRR => format!("﷼{formatted}"), + Currency::ISK => format!("kr{formatted}"), + Currency::JMD => format!("J${formatted}"), + Currency::JOD => format!("د.ا{formatted}"), + Currency::JPY => format!("¥{formatted}"), + Currency::KES => format!("KSh{formatted}"), + Currency::KGS => format!("с{formatted}"), + Currency::KHR => format!("៛{formatted}"), + Currency::KMF => format!("CF{formatted}"), + Currency::KPW => format!("₩{formatted}"), + Currency::KRW => format!("₩{formatted}"), + Currency::KWD => format!("د.ك{formatted}"), + Currency::KYD => format!("CI${formatted}"), + Currency::KZT => format!("₸{formatted}"), + Currency::LAK => format!("₭{formatted}"), + Currency::LBP => format!("L£{formatted}"), + Currency::LKR => format!("Rs{formatted}"), + Currency::LRD => format!("L${formatted}"), + Currency::LSL => format!("L{formatted}"), + Currency::LYD => format!("ل.د{formatted}"), + Currency::MAD => format!("د.م.{formatted}"), + Currency::MDL => format!("L{formatted}"), + Currency::MGA => format!("Ar{formatted}"), + Currency::MKD => format!("ден{formatted}"), + Currency::MMK => format!("K{formatted}"), + Currency::MNT => format!("₮{formatted}"), + Currency::MOP => format!("MOP${formatted}"), + Currency::MRU => format!("UM{formatted}"), + Currency::MUR => format!("Rs{formatted}"), + Currency::MVR => format!(".ރ{formatted}"), + Currency::MWK => format!("MK{formatted}"), + Currency::MXN => format!("${formatted}"), + Currency::MYR => format!("RM{formatted}"), + Currency::MZN => format!("MT{formatted}"), + Currency::NAD => format!("N${formatted}"), + Currency::NGN => format!("₦{formatted}"), + Currency::NIO => format!("C${formatted}"), + Currency::NOK => format!("kr{formatted}"), + Currency::NPR => format!("Rs{formatted}"), + Currency::NZD => format!("NZ${formatted}"), + Currency::OMR => format!("ر.ع.{formatted}"), + Currency::PAB => format!("B/{formatted}"), + Currency::PEN => format!("S/{formatted}"), + Currency::PGK => format!("K{formatted}"), + Currency::PHP => format!("₱{formatted}"), + Currency::PKR => format!("Rs{formatted}"), + Currency::PLN => format!("zł{formatted}"), + Currency::PYG => format!("₲{formatted}"), + Currency::QAR => format!("ر.ق{formatted}"), + Currency::RON => format!("lei{formatted}"), + Currency::RSD => format!("дин.{formatted}"), + Currency::RUB => format!("₽{formatted}"), + Currency::RWF => format!("FRw{formatted}"), + Currency::SAR => format!("ر.س{formatted}"), + Currency::SBD => format!("SI${formatted}"), + Currency::SCR => format!("SR{formatted}"), + Currency::SDG => format!("ج.س.{formatted}"), + Currency::SEK => format!("kr{formatted}"), + Currency::SGD => format!("S${formatted}"), + Currency::SHP => format!("£{formatted}"), + Currency::SLL => format!("Le{formatted}"), + Currency::SOS => format!("S{formatted}"), + Currency::SRD => format!("${formatted}"), + Currency::SSP => format!("£{formatted}"), + Currency::STN => format!("Db{formatted}"), + Currency::SVC => format!("₡{formatted}"), + Currency::SYP => format!("£S{formatted}"), + Currency::SZL => format!("E{formatted}"), + Currency::THB => format!("฿{formatted}"), + Currency::TJS => format!("ЅМ{formatted}"), + Currency::TMT => format!("m{formatted}"), + Currency::TND => format!("د.ت{formatted}"), + Currency::TOP => format!("T${formatted}"), + Currency::TRY => format!("₺{formatted}"), + Currency::TTD => format!("TT${formatted}"), + Currency::TWD => format!("NT${formatted}"), + Currency::TZS => format!("TSh{formatted}"), + Currency::UAH => format!("₴{formatted}"), + Currency::UGX => format!("USh{formatted}"), + Currency::USD => format!("${formatted}"), + Currency::UYU => format!("$U{formatted}"), + Currency::UZS => format!("сўм{formatted}"), + Currency::VES => format!("Bs.S{formatted}"), + Currency::VND => format!("₫{formatted}"), + Currency::VUV => format!("VT{formatted}"), + Currency::WST => format!("WS${formatted}"), + Currency::XAF => format!("FCFA{formatted}"), + Currency::XCD => format!("EC${formatted}"), + Currency::XOF => format!("CFA{formatted}"), + Currency::XPF => format!("CFP{formatted}"), + Currency::YER => format!("﷼{formatted}"), + Currency::ZAR => format!("R{formatted}"), + Currency::ZMW => format!("ZK{formatted}"), + Currency::ZWL => format!("Z${formatted}"), + Currency::USDC => format!("${formatted}"), + Currency::ETH => format!("Ξ{formatted}"), + } + } + + pub fn resize_decimals(self, value: &Element, to_currency: Currency) -> Element { + let value = value.to_u256(); + let (base, exp) = if self.decimals() >= to_currency.decimals() { + // Need to divide to decrease precision + (value, self.decimals() - to_currency.decimals()) + } else { + // Need to multiply to increase precision + (value, to_currency.decimals() - self.decimals()) + }; + let factor = Element::new(10).to_u256().pow(exp); + let result = if self.decimals() >= to_currency.decimals() { + base / factor + } else { + base * factor + }; + result.into() + } + + pub fn to_decimal_string(self, value: &Element) -> String { + let value = value.to_u256(); + let decimals = self.decimals(); + let factor = Element::new(10).to_u256().pow(decimals); + let integer_part = value / factor; + let fractional_part = value % factor; + format!( + "{}.{:0width$}", + integer_part, + fractional_part, + width = decimals as usize + ) + } + + pub fn try_from_decimal_string(&self, value: &str) -> Result { + let decimals = self.decimals(); + let parts: Vec<&str> = value.split('.').collect(); + + let integer = parts[0] + .parse::() + .map(Element::new) + .map(|p| p.to_u256()) + .map_err(|_| Error::InvalidDecimalString(value.to_string()))?; + + match parts.len() { + 1 => { + // No decimal point + Ok((integer * Element::new(10).to_u256().pow(decimals)).into()) + } + 2 => { + let mut fractional = parts[1].to_string(); + + // Pad or truncate fractional part to match currency decimals + match fractional.len().cmp(&(decimals as usize)) { + std::cmp::Ordering::Less => { + fractional.push_str(&"0".repeat(decimals as usize - fractional.len())); + } + std::cmp::Ordering::Greater => { + fractional.truncate(decimals as usize); + } + std::cmp::Ordering::Equal => {} + } + + let fractional = fractional + .parse::() + .map(Element::new) + .map(|p| p.to_u256()) + .map_err(|_| Error::InvalidDecimalString(value.to_string()))?; + Ok((integer * Element::new(10).to_u256().pow(decimals) + fractional).into()) + } + _ => Err(Error::InvalidDecimalString(value.to_string())), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_decimals() { + assert_eq!(Currency::USDC.decimals(), 6); + assert_eq!(Currency::ARS.decimals(), 2); + assert_eq!(Currency::MXN.decimals(), 2); + assert_eq!(Currency::BRL.decimals(), 2); + assert_eq!(Currency::JPY.decimals(), 0); + } + + #[test] + fn test_jpy_format() { + // JPY has 0 decimals, so the Element value should be the yen amount directly + assert_eq!(Currency::JPY.format(&Element::new(510)), "¥510"); + assert_eq!(Currency::JPY.format(&Element::new(1_000)), "¥1,000"); + assert_eq!(Currency::JPY.format(&Element::new(51_000)), "¥51,000"); + } + + #[test] + fn test_kwd_format() { + // KWD has 3 decimals, test how the formatting actually works + assert_eq!(Currency::KWD.format(&Element::new(1230)), "د.ك1.23"); // trailing zero trimmed + assert_eq!(Currency::KWD.format(&Element::new(1234)), "د.ك1.234"); + assert_eq!(Currency::KWD.format(&Element::new(1000)), "د.ك1"); + assert_eq!(Currency::KWD.format(&Element::new(1200)), "د.ك1.20"); // min 2 decimals + } + + #[test] + fn test_usdc_format() { + assert_eq!(Currency::USDC.format(&Element::new(1_234_567)), "$1.234567"); + assert_eq!(Currency::USDC.format(&Element::new(1_230_000)), "$1.23"); + assert_eq!(Currency::USDC.format(&Element::new(1_200_000)), "$1.20"); + assert_eq!(Currency::USDC.format(&Element::new(1_000_000)), "$1"); + assert_eq!(Currency::USDC.format(&Element::new(123)), "$0.000123"); + assert_eq!(Currency::USDC.format(&Element::new(0)), "$0"); + + // Test large amounts with thousands separator + assert_eq!( + Currency::USDC.format(&Element::new(1_234_567_890_000)), + "$1,234,567.89" + ); + assert_eq!( + Currency::USDC.format(&Element::new(1_000_000_000_000)), + "$1,000,000" + ); + } + + #[test] + fn test_resize_decimals() { + // 1.234567 USDC -> 1.23 ARS + assert_eq!( + Currency::USDC + .resize_decimals(&Element::new(1_234_567), Currency::ARS) + .to_u256(), + Element::new(123).to_u256() + ); + + // 1.000000 USDC -> 1.00 ARS + assert_eq!( + Currency::USDC.resize_decimals(&Element::new(1_000_000), Currency::ARS), + Element::new(100) + ); + + // 0.000123 USDC -> 0.00 ARS (rounds down) + assert_eq!( + Currency::USDC.resize_decimals(&Element::new(123), Currency::ARS), + Element::new(0) + ); + + // 1.23 ARS -> 1.230000 USDC + assert_eq!( + Currency::ARS + .resize_decimals(&Element::new(123), Currency::USDC) + .to_u256(), + Element::new(1_230_000).to_u256() + ); + + // 1.00 ARS -> 1.000000 USDC + assert_eq!( + Currency::ARS.resize_decimals(&Element::new(100), Currency::USDC), + Element::new(1_000_000) + ); + + // 0.01 ARS -> 0.010000 USDC + assert_eq!( + Currency::ARS.resize_decimals(&Element::new(1), Currency::USDC), + Element::new(10_000) + ); + } + + #[test] + fn test_to_decimal_string() { + // Test USDC with 6 decimals + assert_eq!( + Currency::USDC.to_decimal_string(&Element::new(1_234_567)), + "1.234567" + ); + assert_eq!( + Currency::USDC.to_decimal_string(&Element::new(1_000_000)), + "1.000000" + ); + assert_eq!( + Currency::USDC.to_decimal_string(&Element::new(123)), + "0.000123" + ); + + // Test fiat currencies with 2 decimals + assert_eq!( + Currency::ARS.to_decimal_string(&Element::new(12345)), + "123.45" + ); + assert_eq!( + Currency::MXN.to_decimal_string(&Element::new(10000)), + "100.00" + ); + assert_eq!(Currency::BRL.to_decimal_string(&Element::new(99)), "0.99"); + } + + #[test] + fn test_from_decimal_string() { + // Test USDC with 6 decimals + assert_eq!( + Currency::USDC.try_from_decimal_string("1.234567").unwrap(), + Element::new(1_234_567) + ); + assert_eq!( + Currency::USDC.try_from_decimal_string("1.000000").unwrap(), + Element::new(1_000_000) + ); + assert_eq!( + Currency::USDC.try_from_decimal_string("0.000123").unwrap(), + Element::new(123) + ); + assert_eq!( + Currency::USDC.try_from_decimal_string("1").unwrap(), + Element::new(1_000_000) + ); + assert_eq!( + Currency::USDC.try_from_decimal_string("1.23").unwrap(), + Element::new(1_230_000) + ); + assert_eq!( + Currency::USDC.try_from_decimal_string("1.2345678").unwrap(), + Element::new(1_234_567) + ); // Truncates excess decimals + + // Test fiat currencies with 2 decimals + assert_eq!( + Currency::ARS.try_from_decimal_string("123.45").unwrap(), + Element::new(12345) + ); + assert_eq!( + Currency::MXN.try_from_decimal_string("100.00").unwrap(), + Element::new(10000) + ); + assert_eq!( + Currency::BRL.try_from_decimal_string("0.99").unwrap(), + Element::new(99) + ); + assert_eq!( + Currency::BRL.try_from_decimal_string("1").unwrap(), + Element::new(100) + ); + assert_eq!( + Currency::BRL.try_from_decimal_string("1.2").unwrap(), + Element::new(120) + ); + assert_eq!( + Currency::BRL.try_from_decimal_string("1.234").unwrap(), + Element::new(123) + ); + } +} diff --git a/pkg/currency/src/error.rs b/pkg/currency/src/error.rs new file mode 100644 index 0000000..7c818c2 --- /dev/null +++ b/pkg/currency/src/error.rs @@ -0,0 +1,22 @@ +use element::Element; + +pub type Result = std::result::Result; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("invalid decimal string: {0}")] + InvalidDecimalString(String), + #[error("invalid amount")] + InvalidAmount { + min: Option, + max: Option, + }, + #[error("invalid currency code")] + InvalidCurrencyCode, + #[error(transparent)] + Json(#[from] serde_json::Error), + #[error(transparent)] + FromUtf8(#[from] core::str::Utf8Error), + #[error(transparent)] + ParseInt(#[from] std::num::ParseIntError), +} diff --git a/pkg/currency/src/lib.rs b/pkg/currency/src/lib.rs new file mode 100644 index 0000000..880bdc0 --- /dev/null +++ b/pkg/currency/src/lib.rs @@ -0,0 +1,8 @@ +pub mod currency; +pub mod error; +pub mod value; + +pub use crate::currency::Currency; +pub use country::{Country, CountryList}; +pub use error::{Error, Result}; +pub use value::CurrencyValue; diff --git a/pkg/currency/src/value.rs b/pkg/currency/src/value.rs new file mode 100644 index 0000000..0358895 --- /dev/null +++ b/pkg/currency/src/value.rs @@ -0,0 +1,77 @@ +use element::Element; +use serde::{ + Deserialize, Deserializer, Serialize, Serializer, de::Error as SerdeDeError, + ser::SerializeStruct, +}; + +use crate::{currency::Currency, error::Result}; + +// Represents a value denominated in a specific currency and amount pairing. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct CurrencyValue { + currency: Currency, + amount: Element, +} + +impl CurrencyValue { + #[must_use] + pub const fn new(currency: Currency, amount: Element) -> Self { + Self { currency, amount } + } + + #[must_use] + pub fn currency(&self) -> Currency { + self.currency + } + + #[must_use] + pub fn amount(&self) -> Element { + self.amount + } + + #[must_use] + pub fn into_parts(self) -> (Currency, Element) { + (self.currency, self.amount) + } + + pub fn try_from_decimal_string(currency: Currency, value: &str) -> Result { + let amount = currency.try_from_decimal_string(value)?; + Ok(Self::new(currency, amount)) + } + + #[must_use] + pub fn to_decimal_string(&self) -> String { + self.currency.to_decimal_string(&self.amount) + } +} + +impl Serialize for CurrencyValue { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + let mut state = serializer.serialize_struct("CurrencyValue", 2)?; + state.serialize_field("currency", &self.currency)?; + state.serialize_field("value", &self.currency.to_decimal_string(&self.amount))?; + state.end() + } +} + +impl<'de> Deserialize<'de> for CurrencyValue { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + struct Helper { + currency: Currency, + value: String, + } + + let Helper { currency, value } = Helper::deserialize(deserializer)?; + let amount = currency + .try_from_decimal_string(&value) + .map_err(|err| SerdeDeError::custom(err.to_string()))?; + Ok(CurrencyValue::new(currency, amount)) + } +} diff --git a/pkg/data/Cargo.toml b/pkg/data/Cargo.toml new file mode 100644 index 0000000..7a491f4 --- /dev/null +++ b/pkg/data/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "data" +version = "0.1.0" +edition = "2024" + +[features] +default = [] +diesel = [ + "dep:diesel", + "dep:diesel-util", + "diesel-util/diesel", + "database/diesel", + "element/diesel", + "kyc/diesel", + "primitives/diesel", +] +stripe = ["dep:async-stripe"] +ts-rs = [ + "dep:ts-rs", + "element/ts-rs", + "primitives/ts-rs", + "kyc/ts-rs", +] + +[dependencies] +chrono = { workspace = true } +async-stripe = { workspace = true, optional = true } +database = { workspace = true, optional = true, default-features = false } +diesel = { workspace = true, optional = true, features = ["postgres"] } +diesel-util = { workspace = true, optional = true } +element = { workspace = true } +kyc = { workspace = true } +primitives = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +strum = { workspace = true } +ts-rs = { workspace = true, optional = true } +uuid = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] diff --git a/pkg/data/README.md b/pkg/data/README.md new file mode 100644 index 0000000..8b775a6 --- /dev/null +++ b/pkg/data/README.md @@ -0,0 +1,20 @@ +# data + +The `data` crate hosts data models and database access helpers that are shared +across services. Structs, enums, and supporting logic compile without Diesel so +callers that only need type definitions can depend on the crate without pulling +in database infrastructure. Enabling the `diesel` feature activates Diesel-based +queries and derives, including access to the `database::schema` module for table +mappings. Optional `stripe` and `ts-rs` features mirror the previous +functionality that lived in the `database` crate. + +## Features + +- `diesel`: Enables Diesel derives and async query helpers. Pulls in + `diesel-async` and forwards the feature to downstream workspace crates that + require Diesel integration. +- `stripe`: Exposes Stripe conversions for payment types. +- `ts-rs`: Enables TypeScript bindings for exported structs. + +Consumers that also need table definitions should continue importing +`database::schema` while using `data` for the associated models and helpers. diff --git a/pkg/data/src/diagnostics.rs b/pkg/data/src/diagnostics.rs new file mode 100644 index 0000000..f1c6a05 --- /dev/null +++ b/pkg/data/src/diagnostics.rs @@ -0,0 +1,40 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::diagnostics; +#[cfg(feature = "diesel")] +use diesel::{ + Selectable, + prelude::{Insertable, Queryable}, +}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Insertable, Queryable, Selectable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = diagnostics))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Diagnostics { + pub id: Uuid, + pub wallet_id: Option, + pub address: String, + pub backup_diffs: serde_json::Value, + pub state: serde_json::Value, + pub mnemonic: String, + pub device_info: serde_json::Value, + pub message: Option, + pub added_at: DateTime, +} + +#[derive(Clone)] +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = diagnostics))] +pub struct NewDiagnostics { + pub wallet_id: Option, + pub address: String, + pub backup_diffs: serde_json::Value, + pub state: serde_json::Value, + pub mnemonic: String, + pub device_info: serde_json::Value, + pub message: Option, +} diff --git a/pkg/data/src/faucet.rs b/pkg/data/src/faucet.rs new file mode 100644 index 0000000..1dadef3 --- /dev/null +++ b/pkg/data/src/faucet.rs @@ -0,0 +1,26 @@ +#[cfg(feature = "diesel")] +use database::schema::faucets; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +use uuid::Uuid; + +#[derive(Debug, Clone)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Selectable, Identifiable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(table_name = faucets))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Faucet { + pub id: Uuid, + pub url: String, + pub claimed_by: Option, + pub added_at: chrono::NaiveDateTime, + pub claimed_at: Option, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = faucets))] +pub struct NewFaucet<'a> { + pub url: &'a str, +} diff --git a/pkg/data/src/ip_data.rs b/pkg/data/src/ip_data.rs new file mode 100644 index 0000000..e7e8c17 --- /dev/null +++ b/pkg/data/src/ip_data.rs @@ -0,0 +1,30 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::ip_data; +#[cfg(feature = "diesel")] +use diesel::{ + Selectable, + prelude::{Insertable, Queryable}, +}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Insertable, Queryable, Selectable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = ip_data))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct IpData { + pub id: Uuid, + pub ip: String, + pub data: serde_json::Value, + pub added_at: DateTime, +} + +#[derive(Clone)] +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = ip_data))] +pub struct NewIpData<'a> { + pub ip: &'a str, + pub data: &'a serde_json::Value, +} diff --git a/pkg/data/src/lib.rs b/pkg/data/src/lib.rs new file mode 100644 index 0000000..1a869d4 --- /dev/null +++ b/pkg/data/src/lib.rs @@ -0,0 +1,21 @@ +//! Shared data models and Diesel-backed data access helpers. + +pub mod diagnostics; +pub mod faucet; +pub mod ip_data; +pub mod migrate_elements; +pub mod nft; +pub mod payment; +pub mod registry_note; +pub mod support; +pub mod support_canned_response; +pub mod support_tag; +pub mod udh; +pub mod wallet; +pub mod wallet_activity; +pub mod wallet_auth; +pub mod wallet_backup; +pub mod wallet_notes; + +#[cfg(feature = "diesel")] +pub(crate) use diesel_util::derive_pg_text_enum; diff --git a/pkg/data/src/migrate_elements.rs b/pkg/data/src/migrate_elements.rs new file mode 100644 index 0000000..dc435a6 --- /dev/null +++ b/pkg/data/src/migrate_elements.rs @@ -0,0 +1,17 @@ +#[cfg(feature = "diesel")] +use database::schema::migrate_elements; +#[cfg(feature = "diesel")] +use diesel::{ + Selectable, + prelude::{Insertable, Queryable}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Insertable, Queryable, Selectable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(element)))] +#[cfg_attr(feature = "diesel", diesel(table_name = migrate_elements))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct MigrateElement { + pub element: String, +} diff --git a/pkg/data/src/nft.rs b/pkg/data/src/nft.rs new file mode 100644 index 0000000..1f790a1 --- /dev/null +++ b/pkg/data/src/nft.rs @@ -0,0 +1,20 @@ +#[cfg(feature = "diesel")] +use database::schema::nfts; +#[cfg(feature = "diesel")] +use diesel::{ + Selectable, + prelude::{Insertable, Queryable}, +}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Insertable, Queryable, Selectable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = nfts))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Nft { + pub id: Uuid, + pub url: String, + pub price: i32, +} diff --git a/pkg/data/src/payment.rs b/pkg/data/src/payment.rs new file mode 100644 index 0000000..7811123 --- /dev/null +++ b/pkg/data/src/payment.rs @@ -0,0 +1,140 @@ +#[cfg(feature = "diesel")] +use database::schema::payments; +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + pg::Pg, + prelude::*, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Text, +}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::fmt::Display; +#[cfg(feature = "diesel")] +use std::io::Write; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Insertable, Queryable, Selectable, Identifiable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = payments))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Payment { + pub id: Uuid, + pub product: String, + pub provider: String, + pub external_id: Option, + pub amount: i32, + pub currency: PaymentCurrency, + pub status: PaymentStatus, + pub payment_by: Option, +} + +#[derive(Clone)] +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = payments))] +pub struct NewPayment<'a> { + pub product: &'a str, + pub provider: &'a str, + pub data: &'a Value, + pub external_id: &'a str, + pub amount: &'a i32, + pub currency: &'a PaymentCurrency, + pub status: &'a PaymentStatus, + pub payment_by: Option<&'a str>, +} + +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(rename_all = "lowercase")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +pub enum PaymentStatus { + // Payment process started, but not sent to provider + Pending, + // Payment request has been sent + Requested, + // Payment is approved and ready for product to be delivered + Approved, + // Payment is cancelled by the user + Cancelled, + // Payment failed + Failed, +} + +#[cfg(feature = "diesel")] +impl ToSql for PaymentStatus { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + match *self { + PaymentStatus::Pending => out.write_all(b"pending")?, + PaymentStatus::Requested => out.write_all(b"requested")?, + PaymentStatus::Approved => out.write_all(b"approved")?, + PaymentStatus::Cancelled => out.write_all(b"cancelled")?, + PaymentStatus::Failed => out.write_all(b"failed")?, + } + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for PaymentStatus { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + match bytes.as_bytes() { + b"pending" => Ok(PaymentStatus::Pending), + b"requested" => Ok(PaymentStatus::Requested), + b"approved" => Ok(PaymentStatus::Approved), + b"cancelled" => Ok(PaymentStatus::Cancelled), + b"failed" => Ok(PaymentStatus::Failed), + _ => Err("Unrecognized enum variant".into()), + } + } +} + +#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +pub enum PaymentCurrency { + Usd, +} + +#[cfg(feature = "stripe")] +impl From for stripe::Currency { + fn from(value: PaymentCurrency) -> Self { + match value { + PaymentCurrency::Usd => stripe::Currency::USD, + } + } +} + +#[cfg(feature = "diesel")] +impl ToSql for PaymentCurrency { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + match *self { + PaymentCurrency::Usd => out.write_all(b"USD")?, + } + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for PaymentCurrency { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + match bytes.as_bytes() { + b"USD" => Ok(PaymentCurrency::Usd), + _ => Err("Unrecognized enum variant".into()), + } + } +} + +impl Display for PaymentCurrency { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PaymentCurrency::Usd => write!(f, "USD"), + } + } +} diff --git a/pkg/data/src/registry_note.rs b/pkg/data/src/registry_note.rs new file mode 100644 index 0000000..956882f --- /dev/null +++ b/pkg/data/src/registry_note.rs @@ -0,0 +1,24 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::registry_notes; +#[cfg(feature = "diesel")] +use diesel::{ + Selectable, + prelude::{Insertable, Queryable}, +}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Insertable, Queryable, Selectable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = registry_notes))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct RegistryNote { + pub id: Uuid, + pub block: i64, + pub public_key: String, + pub encrypted_key: Vec, + pub encrypted_note: Vec, + pub added_at: DateTime, +} diff --git a/pkg/data/src/support.rs b/pkg/data/src/support.rs new file mode 100644 index 0000000..2868d17 --- /dev/null +++ b/pkg/data/src/support.rs @@ -0,0 +1,236 @@ +// lint-long-file-override allow-max-lines=300 +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use diesel::{deserialize::FromSqlRow, expression::AsExpression, prelude::*}; +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumString}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use uuid::Uuid; + +#[cfg(feature = "diesel")] +use crate::derive_pg_text_enum; +#[cfg(feature = "diesel")] +use database::schema::{support_issues, support_messages}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Queryable))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct SupportIssue { + pub id: Uuid, + pub wallet_id: Uuid, + pub external_id: Uuid, + pub status: Status, + pub channel: String, + pub subject: Option, + pub unread_count: i32, + pub last_message: String, + pub last_message_at: DateTime, + pub last_read_at: Option>, + pub closed_at: Option>, + pub updated_at: DateTime, + pub added_at: DateTime, + #[cfg_attr(feature = "ts-rs", ts(type = "unknown | null"))] + pub metadata: Option, + pub auto_close_at: Option>, + pub auto_close_minutes: Option, + pub last_ai_support_bot_processed_at: Option>, +} + +#[derive( + Debug, Default, EnumString, Display, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, +)] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum Status { + #[default] + Open, + Closed, + OnHold, +} + +#[cfg(feature = "diesel")] +derive_pg_text_enum!(Status, "SCREAMING_SNAKE_CASE"); + +#[derive( + Debug, Default, EnumString, Display, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, +)] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum Role { + #[default] + User, + Agent, +} + +#[cfg(feature = "diesel")] +derive_pg_text_enum!(Role, "SCREAMING_SNAKE_CASE"); + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +#[cfg_attr(feature = "diesel", derive(Queryable))] +pub struct SupportMessage { + pub id: Uuid, + pub support_issue_id: Uuid, + pub external_id: String, + pub emoji: Option, + pub role: Role, + pub message: String, + #[cfg_attr(feature = "ts-rs", ts(type = "{}"))] + pub attachment: Option, + pub added_at: DateTime, + pub is_bot: bool, + pub is_internal: bool, + pub agent_id: Option, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_messages))] +pub struct NewSupportMessageDb { + pub id: Uuid, + pub support_issue_id: Uuid, + pub external_id: String, + pub role: Role, + pub message: String, + pub emoji: Option, + pub attachment: Option, + pub added_at: DateTime, + pub is_bot: bool, + pub is_internal: bool, + pub agent_id: Option, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_issues))] +pub struct NewSupportIssueDb { + pub id: Uuid, + pub wallet_id: Uuid, + pub external_id: Uuid, + pub status: String, + pub channel: String, + pub subject: Option, + pub unread_count: i32, + pub last_message: String, + pub last_message_at: chrono::DateTime, + pub updated_at: chrono::DateTime, + pub added_at: chrono::DateTime, + pub metadata: Option, +} + +#[cfg_attr(feature = "diesel", derive(AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_issues))] +#[derive(Default, Debug)] +pub struct UpdateSupportIssueDb { + pub status: Option, + pub subject: Option, + pub unread_count: Option, + pub last_message: Option, + pub last_message_at: Option>, + pub last_read_at: Option>, + pub closed_at: Option>, + pub auto_close_at: Option>, + pub updated_at: Option>, + pub auto_close_minutes: Option, + pub last_ai_support_bot_processed_at: Option>, +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + use serde_json; + + #[test] + fn test_status_serialization() { + assert_eq!(serde_json::to_string(&Status::Open).unwrap(), "\"OPEN\""); + assert_eq!( + serde_json::to_string(&Status::Closed).unwrap(), + "\"CLOSED\"" + ); + assert_eq!( + serde_json::to_string(&Status::OnHold).unwrap(), + "\"ON_HOLD\"" + ); + } + + #[test] + fn test_status_deserialization() { + assert_eq!( + serde_json::from_str::("\"OPEN\"").unwrap(), + Status::Open + ); + assert_eq!( + serde_json::from_str::("\"CLOSED\"").unwrap(), + Status::Closed + ); + assert_eq!( + serde_json::from_str::("\"ON_HOLD\"").unwrap(), + Status::OnHold + ); + } + + #[test] + fn test_status_display() { + assert_eq!(Status::Open.to_string(), "OPEN"); + assert_eq!(Status::Closed.to_string(), "CLOSED"); + assert_eq!(Status::OnHold.to_string(), "ON_HOLD"); + } + + #[test] + fn test_status_from_string() { + assert_eq!(Status::from_str("OPEN").unwrap(), Status::Open); + assert_eq!(Status::from_str("CLOSED").unwrap(), Status::Closed); + assert_eq!(Status::from_str("ON_HOLD").unwrap(), Status::OnHold); + } + + #[test] + fn test_status_default() { + assert_eq!(Status::default(), Status::Open); + } + + #[test] + fn test_role_serialization() { + assert_eq!(serde_json::to_string(&Role::User).unwrap(), "\"USER\""); + assert_eq!(serde_json::to_string(&Role::Agent).unwrap(), "\"AGENT\""); + } + + #[test] + fn test_role_deserialization() { + assert_eq!( + serde_json::from_str::("\"USER\"").unwrap(), + Role::User + ); + assert_eq!( + serde_json::from_str::("\"AGENT\"").unwrap(), + Role::Agent + ); + } + + #[test] + fn test_role_display() { + assert_eq!(Role::User.to_string(), "USER"); + assert_eq!(Role::Agent.to_string(), "AGENT"); + } + + #[test] + fn test_role_from_string() { + assert_eq!(Role::from_str("USER").unwrap(), Role::User); + assert_eq!(Role::from_str("AGENT").unwrap(), Role::Agent); + } + + #[test] + fn test_role_default() { + assert_eq!(Role::default(), Role::User); + } +} diff --git a/pkg/data/src/support_canned_response.rs b/pkg/data/src/support_canned_response.rs new file mode 100644 index 0000000..25cfda1 --- /dev/null +++ b/pkg/data/src/support_canned_response.rs @@ -0,0 +1,60 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::{support_canned_response_tags, support_canned_responses}; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "diesel", derive(Queryable, Identifiable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_canned_responses))] +pub struct SupportCannedResponse { + pub id: Uuid, + pub name: String, + pub display_name: String, + pub content: String, + pub is_active: bool, + pub added_at: DateTime, + pub updated_at: DateTime, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_canned_responses))] +pub struct NewSupportCannedResponseDb { + pub name: String, + pub display_name: String, + pub content: String, + pub is_active: bool, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)] +#[cfg_attr(feature = "diesel", derive(AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_canned_responses))] +pub struct UpdateSupportCannedResponseDb { + pub display_name: Option, + pub content: Option, + pub is_active: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "diesel", derive(Queryable, Identifiable))] +#[cfg_attr( + feature = "diesel", + diesel( + table_name = support_canned_response_tags, + primary_key(support_canned_response_id, support_tag_id) + ) +)] +pub struct SupportCannedResponseTag { + pub support_canned_response_id: Uuid, + pub support_tag_id: Uuid, + pub added_at: DateTime, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_canned_response_tags))] +pub struct NewSupportCannedResponseTagDb { + pub support_canned_response_id: Uuid, + pub support_tag_id: Uuid, +} diff --git a/pkg/data/src/support_tag.rs b/pkg/data/src/support_tag.rs new file mode 100644 index 0000000..b0bea85 --- /dev/null +++ b/pkg/data/src/support_tag.rs @@ -0,0 +1,49 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::{support_issue_tags, support_tags}; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "diesel", derive(Queryable, Identifiable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_tags))] +pub struct SupportTag { + pub id: Uuid, + pub name: String, + pub display_name: String, + pub color: String, + pub is_active: bool, + pub added_at: DateTime, + pub auto_close_minutes: Option, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_tags))] +pub struct NewSupportTagDb { + pub name: String, + pub display_name: String, + pub color: String, + pub is_active: bool, + pub auto_close_minutes: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "diesel", derive(Queryable, Identifiable))] +#[cfg_attr( + feature = "diesel", + diesel(table_name = support_issue_tags, primary_key(support_issue_id, support_tag_id)) +)] +pub struct SupportIssueTag { + pub support_issue_id: Uuid, + pub support_tag_id: Uuid, + pub added_at: DateTime, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = support_issue_tags))] +pub struct NewSupportIssueTagDb { + pub support_issue_id: Uuid, + pub support_tag_id: Uuid, +} diff --git a/pkg/data/src/udh.rs b/pkg/data/src/udh.rs new file mode 100644 index 0000000..d359aaa --- /dev/null +++ b/pkg/data/src/udh.rs @@ -0,0 +1,34 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::udh_referral_links; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Selectable, Identifiable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(posthog_id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = udh_referral_links))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct UdhReferralLink { + pub posthog_id: String, + pub user_device_hash: String, + pub referrer_url: String, + pub claimed_at: Option>, + pub wallet_id: Option, + pub added_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Clone)] +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = udh_referral_links))] +pub struct NewUdhReferralLink { + pub posthog_id: String, + pub user_device_hash: String, + pub referrer_url: String, +} diff --git a/pkg/data/src/wallet.rs b/pkg/data/src/wallet.rs new file mode 100644 index 0000000..a498bf4 --- /dev/null +++ b/pkg/data/src/wallet.rs @@ -0,0 +1,50 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::wallets; +#[cfg(feature = "diesel")] +use diesel::{ + Selectable, + prelude::{AsChangeset, Queryable}, +}; +use kyc::Kyc; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Queryable, Selectable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallets))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Wallet { + pub id: Uuid, + pub address: String, + pub expo_push_token: Option, + pub deposit_address: Option, + pub added_at: DateTime, + pub updated_at: DateTime, + pub atlas_customer_id: Option, + pub kyc: Option, + pub country: Option, + pub language: Option, + pub ip_country: Option, + pub data: Option, + #[cfg_attr(feature = "diesel", diesel(deserialize_as = i16))] + pub version: u16, + pub fraud_block: bool, +} + +#[derive(Default, Debug)] +#[cfg_attr(feature = "diesel", derive(AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallets))] +pub struct UpdateWallet { + pub address: Option, + pub expo_push_token: Option, + pub deposit_address: Option, + pub atlas_customer_id: Option, + pub kyc: Option, + pub country: Option, + pub language: Option, + pub ip_country: Option, + pub version: Option, + pub fraud_block: Option, +} diff --git a/pkg/data/src/wallet_activity.rs b/pkg/data/src/wallet_activity.rs new file mode 100644 index 0000000..951d49a --- /dev/null +++ b/pkg/data/src/wallet_activity.rs @@ -0,0 +1,60 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use diesel::{deserialize::FromSqlRow, expression::AsExpression, prelude::*}; +use element::Element; +use primitives::serde::{deserialize_base64, serialize_base64}; +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumString}; +use uuid::Uuid; + +#[cfg(feature = "diesel")] +use crate::derive_pg_text_enum; +#[cfg(feature = "diesel")] +use database::schema::wallet_activity; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Selectable, Identifiable, Insertable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_activity))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct WalletActivity { + pub id: Uuid, + pub address: Element, + pub kind: Kind, + #[serde(serialize_with = "serialize_base64")] + #[serde(deserialize_with = "deserialize_base64")] + pub data: Vec, + pub active: bool, + pub added_at: DateTime, + pub completed_at: Option>, + pub updated_at: DateTime, +} + +#[derive(Debug, EnumString, Display, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +pub enum Kind { + KycV1, + SendLinkV1, + ClaimLinkV1, + SendRegistryV1, + MintV1, + CardV1, + BurnV1, + RampDepositV1, + RampDepositLinkV1, + RampWithdrawV1, + SupportV1, + WalletV0, + MigrateV0, + AcrossDeposit, + BungeeDepositV1, +} + +#[cfg(feature = "diesel")] +derive_pg_text_enum!(Kind, "SCREAMING_SNAKE_CASE"); diff --git a/pkg/data/src/wallet_auth.rs b/pkg/data/src/wallet_auth.rs new file mode 100644 index 0000000..0a9d68c --- /dev/null +++ b/pkg/data/src/wallet_auth.rs @@ -0,0 +1,127 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use database::schema::wallet_auths; +#[cfg(feature = "diesel")] +use diesel::{ + Selectable, + deserialize::{self, FromSql}, + pg::{Pg, PgValue}, + prelude::{AsChangeset, Insertable, Queryable}, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Text, +}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "diesel")] +use std::io::Write; +use std::{fmt, str::FromStr}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow) +)] +#[cfg_attr(feature = "diesel", diesel(sql_type = Text))] +pub enum WalletAuthKind { + ApiKey, +} + +impl fmt::Display for WalletAuthKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + WalletAuthKind::ApiKey => write!(f, "API_KEY"), + } + } +} + +impl FromStr for WalletAuthKind { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "API_KEY" => Ok(WalletAuthKind::ApiKey), + _ => Err(format!("Unknown WalletAuthKind: {s}")), + } + } +} + +#[cfg(feature = "diesel")] +impl ToSql for WalletAuthKind { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + out.write_all(self.to_string().as_bytes())?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for WalletAuthKind { + fn from_sql(bytes: PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|e: String| e.into()) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ApiKeyValue { + pub key: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "kind")] +pub enum WalletAuthValue { + ApiKey(ApiKeyValue), +} + +impl WalletAuthValue { + pub fn kind(&self) -> WalletAuthKind { + match self { + WalletAuthValue::ApiKey(_) => WalletAuthKind::ApiKey, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Queryable, Selectable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_auths))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct WalletAuth { + pub id: Uuid, + pub wallet_id: Uuid, + pub kind: WalletAuthKind, + pub value: String, + pub enabled: bool, + pub added_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_auths))] +pub struct NewWalletAuth { + pub wallet_id: Uuid, + pub kind: WalletAuthKind, + pub value: String, + pub enabled: bool, +} + +impl NewWalletAuth { + pub fn new_api_key(wallet_id: Uuid, api_key: String, enabled: bool) -> Self { + Self { + wallet_id, + kind: WalletAuthKind::ApiKey, + value: api_key, + enabled, + } + } +} + +#[derive(Default, Debug)] +#[cfg_attr(feature = "diesel", derive(AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_auths))] +pub struct UpdateWalletAuth { + pub kind: Option, + pub value: Option, + pub enabled: Option, + pub updated_at: Option>, +} diff --git a/pkg/data/src/wallet_backup.rs b/pkg/data/src/wallet_backup.rs new file mode 100644 index 0000000..0317853 --- /dev/null +++ b/pkg/data/src/wallet_backup.rs @@ -0,0 +1,63 @@ +use chrono::{Utc, serde::ts_milliseconds}; +#[cfg(feature = "diesel")] +use database::schema::{wallet_backup_tags, wallet_backups}; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +use primitives::serde::Base64Bytes; +use serde::{Deserialize, Serialize}; +use std::fmt::Debug; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Queryable, Selectable, AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_backups))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct WalletBackup { + pub wallet_address: String, + pub last_update: String, + pub backup_path: String, + pub backup_hash: Vec, + #[serde(with = "ts_milliseconds")] + pub added_at: chrono::DateTime, + pub diff_of: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct WalletBackupWithData { + #[serde(flatten)] + pub wallet_meta: WalletBackup, + pub backup: Base64Bytes, + pub backup_diff: Option, +} + +#[derive(Clone)] +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_backups))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct NewWalletBackup<'a> { + pub wallet_address: &'a str, + pub last_update: &'a str, + pub backup_path: &'a str, + pub backup_hash: &'a [u8], + pub diff_of: Option, +} + +#[derive(Debug, Clone, Serialize)] +#[cfg_attr(feature = "diesel", derive(Queryable, Selectable, AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_backup_tags))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct WalletBackupTag { + pub wallet_address: String, + /// This is always "latest" for now + pub tag: String, + pub last_update: String, +} + +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_backup_tags))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct NewWalletBackupTag { + pub wallet_address: String, + /// This is always "latest" for now + pub tag: String, + pub last_update: String, +} diff --git a/pkg/data/src/wallet_notes.rs b/pkg/data/src/wallet_notes.rs new file mode 100644 index 0000000..0504e55 --- /dev/null +++ b/pkg/data/src/wallet_notes.rs @@ -0,0 +1,46 @@ +use chrono::{DateTime, Utc}; +#[cfg(feature = "diesel")] +use diesel::{deserialize::FromSqlRow, expression::AsExpression, prelude::*}; +use element::Element; +use primitives::serde::Base64Bytes; +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumString}; +use uuid::Uuid; + +#[cfg(feature = "diesel")] +use crate::derive_pg_text_enum; +#[cfg(feature = "diesel")] +use database::schema::wallet_notes; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Selectable, Identifiable, Insertable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(commitment)))] +#[cfg_attr(feature = "diesel", diesel(table_name = wallet_notes))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct WalletNote { + pub commitment: Element, + pub address: Element, + pub data: Base64Bytes, + pub status: Status, + pub activity_id: Option, + pub added_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Debug, EnumString, Display, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +pub enum Status { + Unspent, + Spent, + NotFound, + Dropped, +} + +#[cfg(feature = "diesel")] +derive_pg_text_enum!(Status, "SCREAMING_SNAKE_CASE"); diff --git a/pkg/database/Cargo.toml b/pkg/database/Cargo.toml new file mode 100644 index 0000000..ace3eb1 --- /dev/null +++ b/pkg/database/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "database" +version = "0.1.0" +edition = "2024" + +[features] +default = [] +diesel = ["dep:diesel"] + +[dependencies] +diesel = { workspace = true, optional = true, features = ["postgres"] } +workspace-hack.workspace = true + +[dev-dependencies] +contextful = { workspace = true } +tokio = { workspace = true } +tokio-postgres = { workspace = true, features = ["with-uuid-1"] } +serial_test = { workspace = true } diff --git a/pkg/database/README.md b/pkg/database/README.md new file mode 100644 index 0000000..347c349 --- /dev/null +++ b/pkg/database/README.md @@ -0,0 +1,35 @@ +# database + +Holds Diesel schema definitions and migration utilities for the primary +PostgreSQL database. Application data models and query helpers now live in the +[`data`](../data/README.md) crate; depend on that crate for structs and business +logic and keep this crate focused on schema management. + +## Diesel + +We use diesel as our postgres client. You can install the cargo diesel CLI using: + +```bash +brew install postgresql +cargo install diesel_cli --no-default-features --features postgres +``` + +### Update database schema + +Update `src/schema.rs` and then run: + +``` +diesel migration generate --diff-schema +``` + +You can then run the following to apply the changes: + +``` +diesel migration run +``` + +### Tests + +The integration test at `tests/replit_permissions.rs` provisions a disposable PostgreSQL instance via Docker to +validate column-level privileges. The test automatically skips when the `docker` binary is not available on the +`PATH`, so ensure Docker is installed locally if you want to exercise it end-to-end. diff --git a/pkg/database/diesel.toml b/pkg/database/diesel.toml new file mode 100644 index 0000000..c028f4a --- /dev/null +++ b/pkg/database/diesel.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId"] + +[migrations_directory] +dir = "migrations" diff --git a/pkg/database/migrations/00000000000000_diesel_initial_setup/down.sql b/pkg/database/migrations/00000000000000_diesel_initial_setup/down.sql new file mode 100644 index 0000000..a9f5260 --- /dev/null +++ b/pkg/database/migrations/00000000000000_diesel_initial_setup/down.sql @@ -0,0 +1,6 @@ +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + +DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); +DROP FUNCTION IF EXISTS diesel_set_updated_at(); diff --git a/pkg/database/migrations/00000000000000_diesel_initial_setup/up.sql b/pkg/database/migrations/00000000000000_diesel_initial_setup/up.sql new file mode 100644 index 0000000..08d6f2a --- /dev/null +++ b/pkg/database/migrations/00000000000000_diesel_initial_setup/up.sql @@ -0,0 +1,18 @@ +CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +BEGIN + EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s + FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +BEGIN + IF ( + NEW IS DISTINCT FROM OLD AND + NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at + ) THEN + NEW.updated_at := current_timestamp; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; diff --git a/pkg/database/migrations/2024-04-22-213220_create_faucet/down.sql b/pkg/database/migrations/2024-04-22-213220_create_faucet/down.sql new file mode 100644 index 0000000..638dc06 --- /dev/null +++ b/pkg/database/migrations/2024-04-22-213220_create_faucet/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE IF EXISTS faucets; \ No newline at end of file diff --git a/pkg/database/migrations/2024-04-22-213220_create_faucet/up.sql b/pkg/database/migrations/2024-04-22-213220_create_faucet/up.sql new file mode 100644 index 0000000..66a6d9f --- /dev/null +++ b/pkg/database/migrations/2024-04-22-213220_create_faucet/up.sql @@ -0,0 +1,12 @@ +-- Your SQL goes here +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +CREATE TABLE faucets ( + id uuid DEFAULT gen_random_uuid() PRIMARY KEY, + url text NOT NULL, + claimed_by char(64), + claimed_at timestamp with time zone, + added_at timestamp with time zone NOT NULL DEFAULT now() +); + +CREATE UNIQUE INDEX faucets_url_key ON faucets(url text_ops); \ No newline at end of file diff --git a/pkg/database/migrations/2024-04-29-041602_create_wallet_backups/down.sql b/pkg/database/migrations/2024-04-29-041602_create_wallet_backups/down.sql new file mode 100644 index 0000000..790f18c --- /dev/null +++ b/pkg/database/migrations/2024-04-29-041602_create_wallet_backups/down.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS wallet_backups; +DROP TABLE IF EXISTS wallet_backup_tags; diff --git a/pkg/database/migrations/2024-04-29-041602_create_wallet_backups/up.sql b/pkg/database/migrations/2024-04-29-041602_create_wallet_backups/up.sql new file mode 100644 index 0000000..6acd13f --- /dev/null +++ b/pkg/database/migrations/2024-04-29-041602_create_wallet_backups/up.sql @@ -0,0 +1,18 @@ +CREATE TABLE wallet_backups ( + wallet_address char(64) NOT NULL, + last_update text NOT NULL, + backup_path text NOT NULL, + backup_hash bytea NOT NULL, + added_at timestamp with time zone NOT NULL DEFAULT now(), + + PRIMARY KEY (wallet_address, last_update) +); + +CREATE TABLE wallet_backup_tags ( + wallet_address char(64) NOT NULL, + tag text NOT NULL, + last_update text NOT NULL, + + PRIMARY KEY (wallet_address, tag), + FOREIGN KEY (wallet_address, last_update) REFERENCES wallet_backups (wallet_address, last_update) +); diff --git a/pkg/database/migrations/2024-06-22-080510_faucet_device/down.sql b/pkg/database/migrations/2024-06-22-080510_faucet_device/down.sql new file mode 100644 index 0000000..8f36d6a --- /dev/null +++ b/pkg/database/migrations/2024-06-22-080510_faucet_device/down.sql @@ -0,0 +1,5 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE "faucets" DROP COLUMN "device_id"; + + + diff --git a/pkg/database/migrations/2024-06-22-080510_faucet_device/up.sql b/pkg/database/migrations/2024-06-22-080510_faucet_device/up.sql new file mode 100644 index 0000000..89d9c94 --- /dev/null +++ b/pkg/database/migrations/2024-06-22-080510_faucet_device/up.sql @@ -0,0 +1,5 @@ +-- Your SQL goes here +ALTER TABLE "faucets" ADD COLUMN "device_id" BPCHAR(64); + + + diff --git a/pkg/database/migrations/2024-06-26-223352_faucet_phone/down.sql b/pkg/database/migrations/2024-06-26-223352_faucet_phone/down.sql new file mode 100644 index 0000000..049fae2 --- /dev/null +++ b/pkg/database/migrations/2024-06-26-223352_faucet_phone/down.sql @@ -0,0 +1,5 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE "faucets" DROP COLUMN "phone_hash"; + + + diff --git a/pkg/database/migrations/2024-06-26-223352_faucet_phone/up.sql b/pkg/database/migrations/2024-06-26-223352_faucet_phone/up.sql new file mode 100644 index 0000000..f899b43 --- /dev/null +++ b/pkg/database/migrations/2024-06-26-223352_faucet_phone/up.sql @@ -0,0 +1,4 @@ +ALTER TABLE "faucets" ADD COLUMN "phone_hash" BPCHAR(64); + + + diff --git a/pkg/database/migrations/2024-06-28-194157_faucet_blocklist/down.sql b/pkg/database/migrations/2024-06-28-194157_faucet_blocklist/down.sql new file mode 100644 index 0000000..6fbd68f --- /dev/null +++ b/pkg/database/migrations/2024-06-28-194157_faucet_blocklist/down.sql @@ -0,0 +1,6 @@ +-- This file should undo anything in `up.sql` + + + +DROP TABLE IF EXISTS "blocklist_ip"; +DROP TABLE IF EXISTS "blocklist_mobile"; diff --git a/pkg/database/migrations/2024-06-28-194157_faucet_blocklist/up.sql b/pkg/database/migrations/2024-06-28-194157_faucet_blocklist/up.sql new file mode 100644 index 0000000..6b34773 --- /dev/null +++ b/pkg/database/migrations/2024-06-28-194157_faucet_blocklist/up.sql @@ -0,0 +1,21 @@ +CREATE TABLE "blocklist_ip"( + "ip" BPCHAR(45) NOT NULL PRIMARY KEY, + "data" JSONB NOT NULL DEFAULT '{}'::jsonb, + "block" BOOL NOT NULL, + "request_count" INTEGER NOT NULL DEFAULT 0, + "request_count_reset_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + "request_count_total" INTEGER NOT NULL DEFAULT 0, + "added_at" timestamp with time zone NOT NULL DEFAULT now() +); + +CREATE TABLE "blocklist_mobile"( + "mobile" BPCHAR(20) NOT NULL PRIMARY KEY, + "reason" TEXT, + "ip" BPCHAR(45), + "block" BOOL NOT NULL, + "added_at" timestamp with time zone NOT NULL DEFAULT now() +); + +ALTER TABLE faucets DROP COLUMN phone_hash; + + diff --git a/pkg/database/migrations/2024-06-30-121714_blacklist_trace/down.sql b/pkg/database/migrations/2024-06-30-121714_blacklist_trace/down.sql new file mode 100644 index 0000000..ccdc378 --- /dev/null +++ b/pkg/database/migrations/2024-06-30-121714_blacklist_trace/down.sql @@ -0,0 +1,5 @@ +-- This file should undo anything in `up.sql` + +ALTER TABLE "blocklist_mobile" DROP COLUMN "country_code"; + +DROP TABLE IF EXISTS "blocklist_trace"; diff --git a/pkg/database/migrations/2024-06-30-121714_blacklist_trace/up.sql b/pkg/database/migrations/2024-06-30-121714_blacklist_trace/up.sql new file mode 100644 index 0000000..8556f1a --- /dev/null +++ b/pkg/database/migrations/2024-06-30-121714_blacklist_trace/up.sql @@ -0,0 +1,12 @@ +-- Your SQL goes here + +ALTER TABLE "blocklist_mobile" ADD COLUMN "country_code" BPCHAR(2); + +CREATE TABLE "blocklist_trace"( + id uuid DEFAULT gen_random_uuid() PRIMARY KEY, + "path" TEXT NOT NULL, + "mobile" BPCHAR(20) NOT NULL, + "ip" BPCHAR(45), + "added_at" timestamp with time zone NOT NULL DEFAULT now() +); + diff --git a/pkg/database/migrations/2024-07-03-215541_rewards/down.sql b/pkg/database/migrations/2024-07-03-215541_rewards/down.sql new file mode 100644 index 0000000..1923928 --- /dev/null +++ b/pkg/database/migrations/2024-07-03-215541_rewards/down.sql @@ -0,0 +1,3 @@ +DROP TABLE IF EXISTS "rewards"; +DROP TABLE IF EXISTS "rewards_points"; +DROP TABLE IF EXISTS "rewards_invites"; diff --git a/pkg/database/migrations/2024-07-03-215541_rewards/up.sql b/pkg/database/migrations/2024-07-03-215541_rewards/up.sql new file mode 100644 index 0000000..5ee5325 --- /dev/null +++ b/pkg/database/migrations/2024-07-03-215541_rewards/up.sql @@ -0,0 +1,25 @@ +CREATE TABLE "rewards"( + "address" BPCHAR(64) NOT NULL PRIMARY KEY, + "code" BPCHAR(6) NOT NULL, + "points" INTEGER NOT NULL DEFAULT 0, + "invites" INTEGER NOT NULL DEFAULT 0, + "claims" JSONB NOT NULL DEFAULT '{}'::jsonb, + "prize" TEXT, + "added_at" timestamp with time zone NOT NULL DEFAULT now() +); + +CREATE TABLE "rewards_points"( + "id" UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), + "address" BPCHAR(64) NOT NULL, + "reason" TEXT NOT NULL, + "points" INTEGER NOT NULL, + "added_at" timestamp with time zone NOT NULL DEFAULT now() +); + +CREATE TABLE "rewards_invites"( + "from_address" BPCHAR(64) NOT NULL, + "to_address" BPCHAR(64) NOT NULL UNIQUE, + "added_at" timestamp with time zone NOT NULL DEFAULT now(), + PRIMARY KEY("from_address", "to_address") +); + diff --git a/pkg/database/migrations/2024-08-01-104320_square_payments/down.sql b/pkg/database/migrations/2024-08-01-104320_square_payments/down.sql new file mode 100644 index 0000000..2cd77b3 --- /dev/null +++ b/pkg/database/migrations/2024-08-01-104320_square_payments/down.sql @@ -0,0 +1,4 @@ +-- This file should undo anything in `up.sql` + +DROP TABLE IF EXISTS "payments"; +DROP TABLE IF EXISTS "nfts"; diff --git a/pkg/database/migrations/2024-08-01-104320_square_payments/up.sql b/pkg/database/migrations/2024-08-01-104320_square_payments/up.sql new file mode 100644 index 0000000..e4eaaf4 --- /dev/null +++ b/pkg/database/migrations/2024-08-01-104320_square_payments/up.sql @@ -0,0 +1,32 @@ +-- Your SQL goes here + +CREATE TABLE nfts ( + "id" uuid DEFAULT gen_random_uuid() PRIMARY KEY, + "url" text NOT NULL, + "price" INTEGER NOT NULL, + "payment_id" uuid, + "claimed_by" char(64), + "claimed_at" timestamp with time zone, + "added_at" timestamp with time zone NOT NULL DEFAULT now() +); + +CREATE UNIQUE INDEX nfts_unique_payment_id + ON nfts(payment_id) + WHERE payment_id IS NOT NULL; + +CREATE UNIQUE INDEX nfts_url_key ON nfts(url text_ops); + +CREATE TABLE "payments" ( + "id" uuid DEFAULT gen_random_uuid() PRIMARY KEY, + "product" TEXT NOT NULL, + "provider" TEXT NOT NULL, + "external_id" TEXT, + "data" JSONB NOT NULL DEFAULT '{}'::jsonb, -- extra data from vendor + "amount" INTEGER NOT NULL, + "currency" TEXT NOT NULL, + "status" TEXT NOT NULL, -- PENDING, PAID, COMPLETE + "payment_by" char(64), + "added_at" timestamp with time zone NOT NULL DEFAULT now(), + + CONSTRAINT unique_provider_external_id UNIQUE("provider", "external_id") +); \ No newline at end of file diff --git a/pkg/database/migrations/2024-08-23-104320_backup_diffs/down.sql b/pkg/database/migrations/2024-08-23-104320_backup_diffs/down.sql new file mode 100644 index 0000000..3aac67f --- /dev/null +++ b/pkg/database/migrations/2024-08-23-104320_backup_diffs/down.sql @@ -0,0 +1,5 @@ +ALTER TABLE wallet_backups + DROP CONSTRAINT fk_diff_of_last_update; + +ALTER TABLE wallet_backups + DROP COLUMN diff_of; diff --git a/pkg/database/migrations/2024-08-23-104320_backup_diffs/up.sql b/pkg/database/migrations/2024-08-23-104320_backup_diffs/up.sql new file mode 100644 index 0000000..98aca69 --- /dev/null +++ b/pkg/database/migrations/2024-08-23-104320_backup_diffs/up.sql @@ -0,0 +1,7 @@ +ALTER TABLE wallet_backups + ADD COLUMN diff_of TEXT; + +ALTER TABLE wallet_backups + ADD CONSTRAINT fk_diff_of_last_update + FOREIGN KEY (wallet_address, diff_of) + REFERENCES wallet_backups(wallet_address, last_update); diff --git a/pkg/database/migrations/2024-09-25-134153_create_diagnostics/down.sql b/pkg/database/migrations/2024-09-25-134153_create_diagnostics/down.sql new file mode 100644 index 0000000..67579d0 --- /dev/null +++ b/pkg/database/migrations/2024-09-25-134153_create_diagnostics/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE IF EXISTS "diagnostics"; diff --git a/pkg/database/migrations/2024-09-25-134153_create_diagnostics/up.sql b/pkg/database/migrations/2024-09-25-134153_create_diagnostics/up.sql new file mode 100644 index 0000000..72b7e98 --- /dev/null +++ b/pkg/database/migrations/2024-09-25-134153_create_diagnostics/up.sql @@ -0,0 +1,11 @@ +CREATE TABLE "diagnostics"( + "id" UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), + "address" BPCHAR(64) NOT NULL, + "backup_diffs" JSONB NOT NULL, + "state" JSONB NOT NULL, + "mnemonic" TEXT NOT NULL, + "device_info" JSONB NOT NULL, + "message" TEXT, + "added_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now() +); + diff --git a/pkg/database/migrations/2024-11-13-120752_ramps/down.sql b/pkg/database/migrations/2024-11-13-120752_ramps/down.sql new file mode 100644 index 0000000..00b8cd0 --- /dev/null +++ b/pkg/database/migrations/2024-11-13-120752_ramps/down.sql @@ -0,0 +1,6 @@ +-- This file should undo anything in `up.sql` + +DROP TABLE IF EXISTS "ramps_accounts"; +DROP TABLE IF EXISTS "ramps_transactions"; +DROP TABLE IF EXISTS "ramps_methods"; +DROP TABLE IF EXISTS "ramps_quotes"; diff --git a/pkg/database/migrations/2024-11-13-120752_ramps/up.sql b/pkg/database/migrations/2024-11-13-120752_ramps/up.sql new file mode 100644 index 0000000..0d1e71d --- /dev/null +++ b/pkg/database/migrations/2024-11-13-120752_ramps/up.sql @@ -0,0 +1,76 @@ +-- Your SQL goes here +CREATE TABLE "ramps_accounts"( + "id" UUID NOT NULL PRIMARY KEY, + "address" BPCHAR(64) NOT NULL, + "provider" TEXT NOT NULL, + "external_id" TEXT, + "kyc_status" TEXT NOT NULL, + "kyc_update_required_fields" JSONB, + "kyc_external_id" TEXT, + "country" TEXT, + "deposit_evm_address" TEXT, + "withdraw_evm_address" TEXT, + "metadata" JSONB, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE UNIQUE INDEX unique_address_provider_country ON ramps_accounts(address bpchar_ops,provider text_ops,(COALESCE(country, 'NULL'::text)) text_ops); + +CREATE TABLE "ramps_transactions" ( + "id" UUID NOT NULL PRIMARY KEY, + "address" BPCHAR(64) NOT NULL, + "provider" TEXT NOT NULL, + "account_id" UUID NOT NULL, + "external_id" TEXT, + "external_fund_id" TEXT, + "local_id" TEXT UNIQUE, + "quote_id" UUID, + "status" TEXT NOT NULL, + "from_currency" TEXT NOT NULL, + "from_amount" NUMERIC NOT NULL, + "from_network" TEXT NOT NULL, + "from_network_identifier" JSONB, + "to_currency" TEXT NOT NULL, + "to_amount" NUMERIC NOT NULL, + "to_network" TEXT NOT NULL, + "to_network_identifier" JSONB, + "evm_address" TEXT, + "name" TEXT, + "memo" TEXT, + "desc" TEXT, + "emoji" TEXT, + "category" TEXT NOT NULL, + "metadata" JSONB, + "is_manual" BOOLEAN DEFAULT false, + "transaction_at" TIMESTAMPTZ, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE TABLE "ramps_methods"( + "id" UUID NOT NULL PRIMARY KEY, + "account_id" UUID NOT NULL, + "external_id" TEXT, + "local_id" TEXT NOT NULL, + "network" TEXT NOT NULL, + "network_identifier" JSONB NOT NULL, + "preview" JSONB, + "metadata" JSONB, + "is_default" BOOLEAN DEFAULT false NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE TABLE "ramps_quotes"( + "id" UUID NOT NULL PRIMARY KEY, + "provider" TEXT NOT NULL, + "account_id" UUID NOT NULL, + "external_id" TEXT NOT NULL, + "from_currency" TEXT NOT NULL, + "from_amount" NUMERIC NOT NULL, + "from_network" TEXT NOT NULL, + "to_currency" TEXT NOT NULL, + "to_amount" NUMERIC NOT NULL, + "to_network" TEXT NOT NULL, + "metadata" JSONB, + "expires_at" TIMESTAMPTZ NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL +); \ No newline at end of file diff --git a/pkg/database/migrations/2024-11-14-171101_create_ip_data/down.sql b/pkg/database/migrations/2024-11-14-171101_create_ip_data/down.sql new file mode 100644 index 0000000..71246ba --- /dev/null +++ b/pkg/database/migrations/2024-11-14-171101_create_ip_data/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS "ip_data"; diff --git a/pkg/database/migrations/2024-11-14-171101_create_ip_data/up.sql b/pkg/database/migrations/2024-11-14-171101_create_ip_data/up.sql new file mode 100644 index 0000000..462dd99 --- /dev/null +++ b/pkg/database/migrations/2024-11-14-171101_create_ip_data/up.sql @@ -0,0 +1,7 @@ +CREATE TABLE "ip_data"( + "id" UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), + "ip" BPCHAR(39) NOT NULL, + "data" JSONB NOT NULL, + "added_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now() +); + diff --git a/pkg/database/migrations/2024-12-06-033611_create_wallets/down.sql b/pkg/database/migrations/2024-12-06-033611_create_wallets/down.sql new file mode 100644 index 0000000..79108da --- /dev/null +++ b/pkg/database/migrations/2024-12-06-033611_create_wallets/down.sql @@ -0,0 +1,4 @@ +DROP TRIGGER IF EXISTS "set_updated_at_for_wallets" on "wallets"; +DROP FUNCTION IF EXISTS "update_updated_at_column"; +ALTER TABLE "wallets" DROP CONSTRAINT IF EXISTS "unique_address_expo_push_token"; +DROP TABLE IF EXISTS "wallets"; diff --git a/pkg/database/migrations/2024-12-06-033611_create_wallets/up.sql b/pkg/database/migrations/2024-12-06-033611_create_wallets/up.sql new file mode 100644 index 0000000..e513fbc --- /dev/null +++ b/pkg/database/migrations/2024-12-06-033611_create_wallets/up.sql @@ -0,0 +1,24 @@ +CREATE TABLE "wallets"( + "id" UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), + "address" BPCHAR(64) NOT NULL, + "expo_push_token" TEXT NOT NULL, + "deposit_address" BPCHAR(64) NOT NULL, + "added_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), + "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), + + CONSTRAINT unique_address_expo_push_token UNIQUE ("address", "expo_push_token") +); + +-- trigger to automatically update the `update_at` column when a row changes (because of a change in expo_push_token, for instance) +CREATE OR REPLACE FUNCTION update_updated_at_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ language plpgsql; + +CREATE TRIGGER set_updated_at_for_wallets +BEFORE UPDATE ON wallets +FOR EACH ROW +EXECUTE FUNCTION update_updated_at_column(); diff --git a/pkg/database/migrations/2024-12-09-428752_create_notes/down.sql b/pkg/database/migrations/2024-12-09-428752_create_notes/down.sql new file mode 100644 index 0000000..cddd17e --- /dev/null +++ b/pkg/database/migrations/2024-12-09-428752_create_notes/down.sql @@ -0,0 +1 @@ +DROP TABLE "notes"; diff --git a/pkg/database/migrations/2024-12-09-428752_create_notes/up.sql b/pkg/database/migrations/2024-12-09-428752_create_notes/up.sql new file mode 100644 index 0000000..029711a --- /dev/null +++ b/pkg/database/migrations/2024-12-09-428752_create_notes/up.sql @@ -0,0 +1,18 @@ +CREATE TABLE "notes"( + "id" UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), + "address" BPCHAR(64) NOT NULL, + "private_key" BPCHAR(64) NOT NULL, + "psi" BPCHAR(64) NOT NULL, + "value" NUMERIC NOT NULL, + "source" BPCHAR(64) NOT NULL, + "token" TEXT NOT NULL, + "owner_id" UUID NOT NULL, + + "status" TEXT NOT NULL, + "parent_id" UUID, + "claim_reason" TEXT, + "claim_id" UUID UNIQUE, + "claimed_at" TIMESTAMP WITH TIME ZONE, + + "added_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now() +); diff --git a/pkg/database/migrations/2024-12-22-123512_events/down.sql b/pkg/database/migrations/2024-12-22-123512_events/down.sql new file mode 100644 index 0000000..ecce632 --- /dev/null +++ b/pkg/database/migrations/2024-12-22-123512_events/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS "ramps_events"; diff --git a/pkg/database/migrations/2024-12-22-123512_events/up.sql b/pkg/database/migrations/2024-12-22-123512_events/up.sql new file mode 100644 index 0000000..baf63fa --- /dev/null +++ b/pkg/database/migrations/2024-12-22-123512_events/up.sql @@ -0,0 +1,7 @@ +CREATE TABLE "ramps_events"( + "id" UUID NOT NULL PRIMARY KEY, + "provider" TEXT NOT NULL, + "data" JSONB NOT NULL, + "source" TEXT NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL +); diff --git a/pkg/database/migrations/2024-12-22-154318_activity/down.sql b/pkg/database/migrations/2024-12-22-154318_activity/down.sql new file mode 100644 index 0000000..354a2ff --- /dev/null +++ b/pkg/database/migrations/2024-12-22-154318_activity/down.sql @@ -0,0 +1,11 @@ +ALTER TABLE "ramps_accounts" DROP COLUMN "updated_at"; + +ALTER TABLE "ramps_transactions" DROP COLUMN "updated_at"; + +ALTER TABLE "rewards" DROP COLUMN "updated_at"; + +DROP TRIGGER IF EXISTS "set_updated_at_for_ramps_accounts" ON "ramps_accounts"; + +DROP TRIGGER IF EXISTS "set_updated_at_for_ramps_transactions" ON "ramps_transactions"; + +DROP TRIGGER IF EXISTS "set_updated_at_for_rewards" ON "rewards"; diff --git a/pkg/database/migrations/2024-12-22-154318_activity/up.sql b/pkg/database/migrations/2024-12-22-154318_activity/up.sql new file mode 100644 index 0000000..f694100 --- /dev/null +++ b/pkg/database/migrations/2024-12-22-154318_activity/up.sql @@ -0,0 +1,22 @@ +ALTER TABLE "ramps_accounts" ADD COLUMN "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(); + +ALTER TABLE "ramps_transactions" ADD COLUMN "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(); + +ALTER TABLE "rewards" ADD COLUMN "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(); + + +CREATE TRIGGER set_updated_at_for_ramps_accounts +BEFORE UPDATE ON ramps_accounts +FOR EACH ROW +EXECUTE FUNCTION update_updated_at_column(); + +CREATE TRIGGER set_updated_at_for_ramps_transactions +BEFORE UPDATE ON ramps_transactions +FOR EACH ROW +EXECUTE FUNCTION update_updated_at_column(); + +CREATE TRIGGER set_updated_at_for_rewards +BEFORE UPDATE ON rewards +FOR EACH ROW +EXECUTE FUNCTION update_updated_at_column(); + diff --git a/pkg/database/migrations/2025-02-04-171510_cards/down.sql b/pkg/database/migrations/2025-02-04-171510_cards/down.sql new file mode 100644 index 0000000..0e8689d --- /dev/null +++ b/pkg/database/migrations/2025-02-04-171510_cards/down.sql @@ -0,0 +1,16 @@ +DROP INDEX IF EXISTS ramps_transactions_provider_external_id_idx; + +DROP TRIGGER IF EXISTS set_updated_at_for_notes ON notes; + +DROP INDEX IF EXISTS wallets_address_idx; + +ALTER TABLE "wallets" ALTER COLUMN "deposit_address" SET NOT NULL; +ALTER TABLE "wallets" ALTER COLUMN "expo_push_token" SET NOT NULL; + +ALTER TABLE "ramps_transactions" DROP COLUMN "icon"; + +ALTER TABLE "ramps_accounts" DROP COLUMN "kyc_delegated_id"; + +DROP INDEX IF EXISTS notes_commitment_idx; +ALTER TABLE "notes" DROP COLUMN "commitment"; +ALTER TABLE "notes" DROP COLUMN "updated_at"; diff --git a/pkg/database/migrations/2025-02-04-171510_cards/up.sql b/pkg/database/migrations/2025-02-04-171510_cards/up.sql new file mode 100644 index 0000000..174fae4 --- /dev/null +++ b/pkg/database/migrations/2025-02-04-171510_cards/up.sql @@ -0,0 +1,20 @@ +ALTER TABLE "notes" ADD COLUMN "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(); +ALTER TABLE "notes" ADD COLUMN "commitment" BPCHAR(64) NOT NULL; +CREATE UNIQUE INDEX notes_commitment_idx ON notes (commitment); + + +ALTER TABLE "ramps_accounts" ADD COLUMN "kyc_delegated_id" UUID REFERENCES ramps_accounts(id); +ALTER TABLE "ramps_transactions" ADD COLUMN "icon" TEXT; + + +ALTER TABLE "wallets" ALTER COLUMN "expo_push_token" DROP NOT NULL; +ALTER TABLE "wallets" ALTER COLUMN "deposit_address" DROP NOT NULL; +CREATE UNIQUE INDEX wallets_address_idx ON wallets (address); + + +CREATE TRIGGER set_updated_at_for_notes +BEFORE UPDATE ON notes +FOR EACH ROW +EXECUTE FUNCTION update_updated_at_column(); + +CREATE UNIQUE INDEX ramps_transactions_provider_external_id_idx ON ramps_transactions (provider, external_id) WHERE external_id IS NOT NULL; diff --git a/pkg/database/migrations/2025-02-24-222325_notes_refactor/down.sql b/pkg/database/migrations/2025-02-24-222325_notes_refactor/down.sql new file mode 100644 index 0000000..d20951d --- /dev/null +++ b/pkg/database/migrations/2025-02-24-222325_notes_refactor/down.sql @@ -0,0 +1,10 @@ +-- Revert column renames +ALTER TABLE "notes" RENAME COLUMN "received_ref_kind" TO "claim_reason"; +ALTER TABLE "notes" RENAME COLUMN "received_ref_id" TO "claim_id"; +ALTER TABLE "notes" RENAME COLUMN "spent_at" TO "claimed_at"; +ALTER TABLE "notes" RENAME COLUMN "parent_1_id" TO "parent_id"; + +-- Remove newly added columns +ALTER TABLE "notes" DROP COLUMN "spend_ref_kind"; +ALTER TABLE "notes" DROP COLUMN "spend_ref_id"; +ALTER TABLE "notes" DROP COLUMN "parent_2_id"; diff --git a/pkg/database/migrations/2025-02-24-222325_notes_refactor/up.sql b/pkg/database/migrations/2025-02-24-222325_notes_refactor/up.sql new file mode 100644 index 0000000..d7b2b87 --- /dev/null +++ b/pkg/database/migrations/2025-02-24-222325_notes_refactor/up.sql @@ -0,0 +1,55 @@ +ALTER TABLE notes DROP CONSTRAINT IF EXISTS notes_claim_id_key; + +ALTER TABLE "notes" RENAME COLUMN "claim_reason" TO "received_ref_kind"; +ALTER TABLE "notes" RENAME COLUMN "claim_id" TO "received_ref_id"; +ALTER TABLE "notes" RENAME COLUMN "claimed_at" TO "spent_at"; +ALTER TABLE "notes" RENAME COLUMN "parent_id" TO "parent_1_id"; + +ALTER TABLE "notes" ADD COLUMN "spend_ref_kind" TEXT; +ALTER TABLE "notes" ADD COLUMN "spend_ref_id" UUID; +ALTER TABLE "notes" ADD COLUMN "parent_2_id" UUID; + + +-- Update status from READY to UNSPENT +UPDATE notes +SET status = 'UNSPENT' +WHERE status = 'READY'; + +-- Update status from ASSIGNED to TXN_INPUT_ASSIGNED +UPDATE notes +SET status = 'TXN_INPUT_ASSIGNED' +WHERE status = 'ASSIGNED'; + +-- Update status from PENDING to TXN_OUTPUT_PENDING +UPDATE notes +SET status = 'TXN_OUTPUT_PENDING' +WHERE status = 'PENDING'; + +-- Update owner_id where owner_id is '00000000-0000-0000-0000-000000000000' and claim_reason is not 'NFT' +UPDATE notes +SET owner_id = '00000000-0000-0000-0000-000000000001' +WHERE owner_id = '00000000-0000-0000-0000-000000000000' AND received_ref_kind != 'NFT'; + +-- Update parent records based on received_ref_kind and received_ref_id +UPDATE notes AS parent +SET spend_ref_kind = child.received_ref_kind, + spend_ref_id = child.received_ref_id +FROM notes AS child +WHERE (child.received_ref_kind = 'RAMP_TRANSACTION' OR child.received_ref_kind = 'NFT') + AND child.status != 'DROPPED' + AND parent.id = child.parent_1_id; + +-- Update sibling records with the same parent_id +WITH original_child AS ( + SELECT parent_1_id, received_ref_kind, received_ref_id + FROM notes + WHERE (received_ref_kind = 'RAMP_TRANSACTION' OR received_ref_kind = 'NFT') + AND status != 'DROPPED' +) +UPDATE notes AS sibling +SET received_ref_kind = original_child.received_ref_kind, + received_ref_id = original_child.received_ref_id +FROM original_child +WHERE sibling.parent_1_id = original_child.parent_1_id + AND sibling.status != 'DROPPED'; + diff --git a/pkg/database/migrations/2025-03-11-172816_support/down.sql b/pkg/database/migrations/2025-03-11-172816_support/down.sql new file mode 100644 index 0000000..75742a4 --- /dev/null +++ b/pkg/database/migrations/2025-03-11-172816_support/down.sql @@ -0,0 +1,4 @@ +ALTER TABLE "wallets" DROP COLUMN "atlas_customer_id"; + +DROP TABLE IF EXISTS "support_messages"; +DROP TABLE IF EXISTS "support_issues"; diff --git a/pkg/database/migrations/2025-03-11-172816_support/up.sql b/pkg/database/migrations/2025-03-11-172816_support/up.sql new file mode 100644 index 0000000..f4280cc --- /dev/null +++ b/pkg/database/migrations/2025-03-11-172816_support/up.sql @@ -0,0 +1,33 @@ +ALTER TABLE "wallets" ADD COLUMN "atlas_customer_id" TEXT; + +CREATE TABLE "support_messages"( + "id" UUID NOT NULL PRIMARY KEY, + "support_issue_id" UUID NOT NULL, + "external_id" TEXT NOT NULL, + "emoji" TEXT, + "role" TEXT NOT NULL, + "message" TEXT NOT NULL, + "attachment" JSONB, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE TABLE "support_issues"( + "id" UUID NOT NULL PRIMARY KEY, + "wallet_id" UUID NOT NULL, + "external_id" UUID NOT NULL, + "status" TEXT NOT NULL, + "channel" TEXT NOT NULL, + "subject" TEXT, + "unread_count" INT4 NOT NULL, + "last_message" TEXT NOT NULL, + "last_message_at" TIMESTAMPTZ NOT NULL, + "last_read_at" TIMESTAMPTZ, + "closed_at" TIMESTAMPTZ, + "updated_at" TIMESTAMPTZ NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE TRIGGER set_updated_at_for_support_issues +BEFORE UPDATE ON support_issues +FOR EACH ROW +EXECUTE FUNCTION update_updated_at_column(); \ No newline at end of file diff --git a/pkg/database/migrations/2025-03-12-233044_pending_refund/down.sql b/pkg/database/migrations/2025-03-12-233044_pending_refund/down.sql new file mode 100644 index 0000000..81da576 --- /dev/null +++ b/pkg/database/migrations/2025-03-12-233044_pending_refund/down.sql @@ -0,0 +1,11 @@ + +ALTER TABLE "ramps_transactions" DROP COLUMN "pending_refund_amount"; + + + + + + + + + diff --git a/pkg/database/migrations/2025-03-12-233044_pending_refund/up.sql b/pkg/database/migrations/2025-03-12-233044_pending_refund/up.sql new file mode 100644 index 0000000..d21ab14 --- /dev/null +++ b/pkg/database/migrations/2025-03-12-233044_pending_refund/up.sql @@ -0,0 +1,10 @@ +ALTER TABLE "ramps_transactions" ADD COLUMN "pending_refund_amount" NUMERIC; + + + + + + + + + diff --git a/pkg/database/migrations/2025-03-17-072350_add_ramps_events_fields/down.sql b/pkg/database/migrations/2025-03-17-072350_add_ramps_events_fields/down.sql new file mode 100644 index 0000000..dfedf87 --- /dev/null +++ b/pkg/database/migrations/2025-03-17-072350_add_ramps_events_fields/down.sql @@ -0,0 +1,26 @@ +-- This file should undo anything in `up.sql` + + + + + + + + + + +ALTER TABLE "ramps_events" DROP COLUMN "path"; +ALTER TABLE "ramps_events" DROP COLUMN "transaction_id"; +ALTER TABLE "ramps_events" DROP COLUMN "account_id"; + + + + + + + + + + + + diff --git a/pkg/database/migrations/2025-03-17-072350_add_ramps_events_fields/up.sql b/pkg/database/migrations/2025-03-17-072350_add_ramps_events_fields/up.sql new file mode 100644 index 0000000..fa1ac64 --- /dev/null +++ b/pkg/database/migrations/2025-03-17-072350_add_ramps_events_fields/up.sql @@ -0,0 +1,26 @@ +-- Your SQL goes here + + + + + + + + + + +ALTER TABLE "ramps_events" ADD COLUMN "path" TEXT; +ALTER TABLE "ramps_events" ADD COLUMN "transaction_id" TEXT; +ALTER TABLE "ramps_events" ADD COLUMN "account_id" TEXT; + + + + + + + + + + + + diff --git a/pkg/database/migrations/2025-03-19-063029_add_plaid_access_token_to_wallets/down.sql b/pkg/database/migrations/2025-03-19-063029_add_plaid_access_token_to_wallets/down.sql new file mode 100644 index 0000000..52778d0 --- /dev/null +++ b/pkg/database/migrations/2025-03-19-063029_add_plaid_access_token_to_wallets/down.sql @@ -0,0 +1 @@ +ALTER TABLE "wallets" DROP COLUMN "plaid_access_token"; diff --git a/pkg/database/migrations/2025-03-19-063029_add_plaid_access_token_to_wallets/up.sql b/pkg/database/migrations/2025-03-19-063029_add_plaid_access_token_to_wallets/up.sql new file mode 100644 index 0000000..3ea031a --- /dev/null +++ b/pkg/database/migrations/2025-03-19-063029_add_plaid_access_token_to_wallets/up.sql @@ -0,0 +1 @@ +ALTER TABLE "wallets" add COLUMN "plaid_access_token" TEXT; diff --git a/pkg/database/migrations/2025-03-27-000716_add_frozen_flag_to_ramp_methods/down.sql b/pkg/database/migrations/2025-03-27-000716_add_frozen_flag_to_ramp_methods/down.sql new file mode 100644 index 0000000..f4991d4 --- /dev/null +++ b/pkg/database/migrations/2025-03-27-000716_add_frozen_flag_to_ramp_methods/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE "ramps_methods" +DROP COLUMN "frozen"; diff --git a/pkg/database/migrations/2025-03-27-000716_add_frozen_flag_to_ramp_methods/up.sql b/pkg/database/migrations/2025-03-27-000716_add_frozen_flag_to_ramp_methods/up.sql new file mode 100644 index 0000000..dd2534a --- /dev/null +++ b/pkg/database/migrations/2025-03-27-000716_add_frozen_flag_to_ramp_methods/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE "ramps_methods" +ADD COLUMN frozen BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/pkg/database/migrations/2025-04-02-010552_add_sanitized_kyc_to_wallets/down.sql b/pkg/database/migrations/2025-04-02-010552_add_sanitized_kyc_to_wallets/down.sql new file mode 100644 index 0000000..a179565 --- /dev/null +++ b/pkg/database/migrations/2025-04-02-010552_add_sanitized_kyc_to_wallets/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE wallets +DROP COLUMN kyc; diff --git a/pkg/database/migrations/2025-04-02-010552_add_sanitized_kyc_to_wallets/up.sql b/pkg/database/migrations/2025-04-02-010552_add_sanitized_kyc_to_wallets/up.sql new file mode 100644 index 0000000..d0a9dcc --- /dev/null +++ b/pkg/database/migrations/2025-04-02-010552_add_sanitized_kyc_to_wallets/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here +ALTER TABLE wallets +ADD COLUMN kyc JSONB NULL; diff --git a/pkg/database/migrations/2025-04-02-103534_add_country_language_ip_country_to_wallets/down.sql b/pkg/database/migrations/2025-04-02-103534_add_country_language_ip_country_to_wallets/down.sql new file mode 100644 index 0000000..52a9fd0 --- /dev/null +++ b/pkg/database/migrations/2025-04-02-103534_add_country_language_ip_country_to_wallets/down.sql @@ -0,0 +1,4 @@ +ALTER TABLE "wallets" DROP COLUMN "country"; +ALTER TABLE "wallets" DROP COLUMN "language"; +ALTER TABLE "wallets" DROP COLUMN "ip_country"; + diff --git a/pkg/database/migrations/2025-04-02-103534_add_country_language_ip_country_to_wallets/up.sql b/pkg/database/migrations/2025-04-02-103534_add_country_language_ip_country_to_wallets/up.sql new file mode 100644 index 0000000..397c3dc --- /dev/null +++ b/pkg/database/migrations/2025-04-02-103534_add_country_language_ip_country_to_wallets/up.sql @@ -0,0 +1,4 @@ +ALTER TABLE "wallets" ADD COLUMN "country" TEXT; +ALTER TABLE "wallets" ADD COLUMN "language" TEXT; +ALTER TABLE "wallets" ADD COLUMN "ip_country" TEXT; + diff --git a/pkg/database/migrations/2025-04-13-142536_kyc_non_delegated/down.sql b/pkg/database/migrations/2025-04-13-142536_kyc_non_delegated/down.sql new file mode 100644 index 0000000..bc4226a --- /dev/null +++ b/pkg/database/migrations/2025-04-13-142536_kyc_non_delegated/down.sql @@ -0,0 +1 @@ +ALTER TABLE "ramps_accounts" DROP COLUMN "kyc_non_delegated_status"; diff --git a/pkg/database/migrations/2025-04-13-142536_kyc_non_delegated/up.sql b/pkg/database/migrations/2025-04-13-142536_kyc_non_delegated/up.sql new file mode 100644 index 0000000..f86b435 --- /dev/null +++ b/pkg/database/migrations/2025-04-13-142536_kyc_non_delegated/up.sql @@ -0,0 +1 @@ +ALTER TABLE "ramps_accounts" ADD COLUMN "kyc_non_delegated_status" TEXT; \ No newline at end of file diff --git a/pkg/database/migrations/2025-04-23-163723_ramps_settle/down.sql b/pkg/database/migrations/2025-04-23-163723_ramps_settle/down.sql new file mode 100644 index 0000000..025c34f --- /dev/null +++ b/pkg/database/migrations/2025-04-23-163723_ramps_settle/down.sql @@ -0,0 +1,11 @@ +ALTER TABLE "ramps_transactions" DROP COLUMN "funding_status"; +ALTER TABLE "ramps_transactions" DROP COLUMN "funding_due_amount"; + + + + + + + + + diff --git a/pkg/database/migrations/2025-04-23-163723_ramps_settle/up.sql b/pkg/database/migrations/2025-04-23-163723_ramps_settle/up.sql new file mode 100644 index 0000000..641c2d9 --- /dev/null +++ b/pkg/database/migrations/2025-04-23-163723_ramps_settle/up.sql @@ -0,0 +1,46 @@ +-- First, insert missing wallet entries for addresses in ramps_accounts +INSERT INTO wallets (address, added_at, updated_at) +SELECT DISTINCT ra.address, NOW(), NOW() +FROM ramps_accounts ra +WHERE NOT EXISTS ( + SELECT 1 FROM wallets w WHERE ra.address = w.address +); + +-- Then, insert missing wallet entries for addresses in ramps_transactions +-- that aren't already in ramps_accounts +INSERT INTO wallets (address, added_at, updated_at) +SELECT DISTINCT rt.address, NOW(), NOW() +FROM ramps_transactions rt +WHERE NOT EXISTS ( + SELECT 1 FROM wallets w WHERE rt.address = w.address +) +AND NOT EXISTS ( + SELECT 1 FROM ramps_accounts ra WHERE rt.address = ra.address +); + +-- Add new columns to ramps_transactions +ALTER TABLE "ramps_transactions" ADD COLUMN "funding_status" TEXT; +ALTER TABLE "ramps_transactions" ADD COLUMN "funding_due_amount" NUMERIC; +ALTER TABLE "ramps_transactions" ADD COLUMN "wallet_id" UUID; + +-- Add wallet_id column to ramps_accounts +ALTER TABLE "ramps_accounts" ADD COLUMN "wallet_id" UUID; + +-- Populate ramps_accounts.wallet_id from wallets table (using address) +UPDATE ramps_accounts +SET wallet_id = wallets.id +FROM wallets +WHERE ramps_accounts.address = wallets.address; + +-- Populate ramps_transactions.wallet_id from wallets table based on address +UPDATE ramps_transactions +SET wallet_id = wallets.id +FROM wallets +WHERE ramps_transactions.address = wallets.address; + +-- Make wallet_id NOT NULL after population +ALTER TABLE "ramps_accounts" ALTER COLUMN "wallet_id" SET NOT NULL; +ALTER TABLE "ramps_transactions" ALTER COLUMN "wallet_id" SET NOT NULL; + +-- Remove is_manual column from ramps_transactions +ALTER TABLE "ramps_transactions" DROP COLUMN "is_manual"; \ No newline at end of file diff --git a/pkg/database/migrations/2025-05-12-082255_remove_plaid_token_from_wallet/down.sql b/pkg/database/migrations/2025-05-12-082255_remove_plaid_token_from_wallet/down.sql new file mode 100644 index 0000000..430a2f5 --- /dev/null +++ b/pkg/database/migrations/2025-05-12-082255_remove_plaid_token_from_wallet/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE wallets +ADD COLUMN plaid_access_token TEXT; diff --git a/pkg/database/migrations/2025-05-12-082255_remove_plaid_token_from_wallet/up.sql b/pkg/database/migrations/2025-05-12-082255_remove_plaid_token_from_wallet/up.sql new file mode 100644 index 0000000..06ffc3d --- /dev/null +++ b/pkg/database/migrations/2025-05-12-082255_remove_plaid_token_from_wallet/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here + +ALTER TABLE "wallets" DROP COLUMN "plaid_access_token"; diff --git a/pkg/database/migrations/2025-05-15-043156_add_status_reason_for_txns/down.sql b/pkg/database/migrations/2025-05-15-043156_add_status_reason_for_txns/down.sql new file mode 100644 index 0000000..569e994 --- /dev/null +++ b/pkg/database/migrations/2025-05-15-043156_add_status_reason_for_txns/down.sql @@ -0,0 +1,2 @@ +ALTER TABLE ramps_transactions +DROP COLUMN IF EXISTS status_reason; \ No newline at end of file diff --git a/pkg/database/migrations/2025-05-15-043156_add_status_reason_for_txns/up.sql b/pkg/database/migrations/2025-05-15-043156_add_status_reason_for_txns/up.sql new file mode 100644 index 0000000..ae5bf3f --- /dev/null +++ b/pkg/database/migrations/2025-05-15-043156_add_status_reason_for_txns/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE ramps_transactions +ADD COLUMN status_reason text; diff --git a/pkg/database/migrations/2025-05-21-102820_add_success_to_ramps_events/down.sql b/pkg/database/migrations/2025-05-21-102820_add_success_to_ramps_events/down.sql new file mode 100644 index 0000000..f879847 --- /dev/null +++ b/pkg/database/migrations/2025-05-21-102820_add_success_to_ramps_events/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE "ramps_events" +DROP COLUMN IF EXISTS success; diff --git a/pkg/database/migrations/2025-05-21-102820_add_success_to_ramps_events/up.sql b/pkg/database/migrations/2025-05-21-102820_add_success_to_ramps_events/up.sql new file mode 100644 index 0000000..005f909 --- /dev/null +++ b/pkg/database/migrations/2025-05-21-102820_add_success_to_ramps_events/up.sql @@ -0,0 +1,3 @@ +-- Your SQL goes here + +ALTER TABLE "ramps_events" ADD COLUMN "success" BOOLEAN; diff --git a/pkg/database/migrations/2025-06-09-151228_notes_version/down.sql b/pkg/database/migrations/2025-06-09-151228_notes_version/down.sql new file mode 100644 index 0000000..d7f8354 --- /dev/null +++ b/pkg/database/migrations/2025-06-09-151228_notes_version/down.sql @@ -0,0 +1,14 @@ +ALTER TABLE "notes" +ADD COLUMN "source" TEXT; + +ALTER TABLE "notes" +ADD COLUMN "token" TEXT; + +ALTER TABLE "notes" +DROP COLUMN "version"; + +ALTER TABLE "notes" +ALTER COLUMN "received_ref_id" TYPE UUID; + +ALTER TABLE "notes" +ALTER COLUMN "spend_ref_id" TYPE UUID; diff --git a/pkg/database/migrations/2025-06-09-151228_notes_version/up.sql b/pkg/database/migrations/2025-06-09-151228_notes_version/up.sql new file mode 100644 index 0000000..1d030b1 --- /dev/null +++ b/pkg/database/migrations/2025-06-09-151228_notes_version/up.sql @@ -0,0 +1,17 @@ +ALTER TABLE "notes" +DROP COLUMN "source"; + +ALTER TABLE "notes" +DROP COLUMN "token"; + +ALTER TABLE "notes" +ADD COLUMN "version" INT2 NOT NULL DEFAULT 0; + +ALTER TABLE "notes" +ALTER COLUMN "received_ref_id" TYPE TEXT; + +ALTER TABLE "notes" +ALTER COLUMN "spend_ref_id" TYPE TEXT; + +ALTER TABLE "notes" +ADD COLUMN "kind" BPCHAR (64) NOT NULL DEFAULT '0000000000000000000000000000000000000000000000000000000000000001'::bpchar; \ No newline at end of file diff --git a/pkg/database/migrations/2025-06-11-120715_wallet_id/down.sql b/pkg/database/migrations/2025-06-11-120715_wallet_id/down.sql new file mode 100644 index 0000000..250344d --- /dev/null +++ b/pkg/database/migrations/2025-06-11-120715_wallet_id/down.sql @@ -0,0 +1,27 @@ +ALTER TABLE diagnostics DROP CONSTRAINT IF EXISTS fk_diagnostics_wallet_id; +ALTER TABLE rewards DROP CONSTRAINT IF EXISTS fk_rewards_wallet_id; +ALTER TABLE rewards_invites DROP CONSTRAINT IF EXISTS fk_rewards_invites_from_wallet_id; +ALTER TABLE rewards_invites DROP CONSTRAINT IF EXISTS fk_rewards_invites_to_wallet_id; +ALTER TABLE rewards_points DROP CONSTRAINT IF EXISTS fk_rewards_points_wallet_id; + +-- Remove wallet_id column from diagnostics +ALTER TABLE diagnostics DROP COLUMN wallet_id; + +-- Drop wallets_addresses table +DROP TABLE wallets_addresses; + +-- Revert rewards table changes +-- Drop current primary key and restore address as primary key +ALTER TABLE rewards DROP CONSTRAINT rewards_pkey; +ALTER TABLE rewards ADD PRIMARY KEY (address); +ALTER TABLE rewards DROP COLUMN wallet_id; + +-- Revert rewards_invites table changes +-- Drop current primary key and restore address-based primary key +ALTER TABLE rewards_invites DROP CONSTRAINT rewards_invites_pkey; +ALTER TABLE rewards_invites ADD PRIMARY KEY (from_address, to_address); +ALTER TABLE rewards_invites DROP COLUMN from_wallet_id; +ALTER TABLE rewards_invites DROP COLUMN to_wallet_id; + +-- Remove wallet_id column from rewards_points +ALTER TABLE rewards_points DROP COLUMN wallet_id; \ No newline at end of file diff --git a/pkg/database/migrations/2025-06-11-120715_wallet_id/up.sql b/pkg/database/migrations/2025-06-11-120715_wallet_id/up.sql new file mode 100644 index 0000000..98f912f --- /dev/null +++ b/pkg/database/migrations/2025-06-11-120715_wallet_id/up.sql @@ -0,0 +1,156 @@ +-- Add wallet_id column to diagnostics table +ALTER TABLE diagnostics ADD COLUMN wallet_id UUID; + +-- Create wallets_addresses table +CREATE TABLE wallets_addresses ( + address CHAR(64) PRIMARY KEY, + wallet_id UUID NOT NULL +); + +-- Insert missing addresses into wallets table from diagnostics +INSERT INTO wallets (id, address, added_at, updated_at) +SELECT + gen_random_uuid(), + d.address, + NOW(), + NOW() +FROM diagnostics d +LEFT JOIN wallets w ON d.address = w.address +WHERE w.address IS NULL +ON CONFLICT (address) DO NOTHING; + +-- Insert missing addresses into wallets table from rewards +INSERT INTO wallets (id, address, added_at, updated_at) +SELECT + gen_random_uuid(), + r.address, + NOW(), + NOW() +FROM rewards r +LEFT JOIN wallets w ON r.address = w.address +WHERE w.address IS NULL +ON CONFLICT (address) DO NOTHING; + +-- Insert missing addresses into wallets table from rewards_invites (from_address) +INSERT INTO wallets (id, address, added_at, updated_at) +SELECT + gen_random_uuid(), + ri.from_address, + NOW(), + NOW() +FROM rewards_invites ri +LEFT JOIN wallets w ON ri.from_address = w.address +WHERE w.address IS NULL +ON CONFLICT (address) DO NOTHING; + +-- Insert missing addresses into wallets table from rewards_invites (to_address) +INSERT INTO wallets (id, address, added_at, updated_at) +SELECT + gen_random_uuid(), + ri.to_address, + NOW(), + NOW() +FROM rewards_invites ri +LEFT JOIN wallets w ON ri.to_address = w.address +WHERE w.address IS NULL +ON CONFLICT (address) DO NOTHING; + +-- Insert missing addresses into wallets table from rewards_points +INSERT INTO wallets (id, address, added_at, updated_at) +SELECT + gen_random_uuid(), + rp.address, + NOW(), + NOW() +FROM rewards_points rp +LEFT JOIN wallets w ON rp.address = w.address +WHERE w.address IS NULL +ON CONFLICT (address) DO NOTHING; + +-- Populate wallets_addresses with all wallet data (now includes newly created wallets) +INSERT INTO wallets_addresses (address, wallet_id) +SELECT address, id FROM wallets; + +-- Update diagnostics.wallet_id based on address lookup +UPDATE diagnostics +SET wallet_id = w.id +FROM wallets w +WHERE diagnostics.address = w.address; + + +-- Change rewards table primary key from address to wallet_id +-- First, add the wallet_id column +ALTER TABLE rewards ADD COLUMN wallet_id UUID; + + +-- Populate wallet_id in rewards table +UPDATE rewards +SET wallet_id = w.id +FROM wallets w +WHERE rewards.address = w.address; + +-- Make wallet_id NOT NULL after populating +ALTER TABLE rewards ALTER COLUMN wallet_id SET NOT NULL; + + +-- Drop the old primary key and create new one for rewards +ALTER TABLE rewards DROP CONSTRAINT rewards_pkey; +ALTER TABLE rewards ADD PRIMARY KEY (wallet_id); + +-- Add wallet_id columns to rewards_invites +ALTER TABLE rewards_invites ADD COLUMN from_wallet_id UUID; +ALTER TABLE rewards_invites ADD COLUMN to_wallet_id UUID; + +-- Populate wallet_id columns in rewards_invites +UPDATE rewards_invites +SET from_wallet_id = w.id +FROM wallets w +WHERE rewards_invites.from_address = w.address; + +UPDATE rewards_invites +SET to_wallet_id = w.id +FROM wallets w +WHERE rewards_invites.to_address = w.address; + +-- Make wallet_id columns NOT NULL +ALTER TABLE rewards_invites ALTER COLUMN from_wallet_id SET NOT NULL; +ALTER TABLE rewards_invites ALTER COLUMN to_wallet_id SET NOT NULL; + +-- Drop the old primary key constraint and unique constraint +ALTER TABLE rewards_invites DROP CONSTRAINT rewards_invites_pkey; +ALTER TABLE rewards_invites DROP CONSTRAINT rewards_invites_to_address_key; + +-- Create new composite primary key +ALTER TABLE rewards_invites ADD PRIMARY KEY (from_wallet_id, to_wallet_id); + +-- Add wallet_id column to rewards_points +ALTER TABLE rewards_points ADD COLUMN wallet_id UUID; + +-- Populate wallet_id in rewards_points +UPDATE rewards_points +SET wallet_id = w.id +FROM wallets w +WHERE rewards_points.address = w.address; + +-- Make wallet_id NOT NULL +ALTER TABLE rewards_points ALTER COLUMN wallet_id SET NOT NULL; + +-- Drop NOT NULL for address +ALTER TABLE rewards ALTER COLUMN address DROP NOT NULL; +ALTER TABLE rewards_points ALTER COLUMN address DROP NOT NULL; +ALTER TABLE rewards_invites ALTER COLUMN from_address DROP NOT NULL; +ALTER TABLE rewards_invites ALTER COLUMN to_address DROP NOT NULL; +ALTER TABLE ramps_accounts ALTER COLUMN address DROP NOT NULL; +ALTER TABLE ramps_transactions ALTER COLUMN address DROP NOT NULL; + + +-- Alter the payments table +ALTER TABLE payments +ALTER COLUMN payment_by TYPE text; + +-- Convert from address to wallet_id +UPDATE payments +SET payment_by = wallets.id::text +FROM wallets +WHERE payments.payment_by = wallets.address + AND payments.payment_by IS NOT NULL; \ No newline at end of file diff --git a/pkg/database/migrations/2025-06-17-160618_wallet_activity/down.sql b/pkg/database/migrations/2025-06-17-160618_wallet_activity/down.sql new file mode 100644 index 0000000..e3ded46 --- /dev/null +++ b/pkg/database/migrations/2025-06-17-160618_wallet_activity/down.sql @@ -0,0 +1,6 @@ +ALTER TABLE "ramps_transactions" DROP COLUMN "private_key"; + +DROP TABLE IF EXISTS "wallet_activity"; +DROP TABLE IF EXISTS "wallet_notes"; +DROP TABLE IF EXISTS "registry_notes"; +DROP TABLE IF EXISTS "migrate_elements"; diff --git a/pkg/database/migrations/2025-06-17-160618_wallet_activity/up.sql b/pkg/database/migrations/2025-06-17-160618_wallet_activity/up.sql new file mode 100644 index 0000000..c9367de --- /dev/null +++ b/pkg/database/migrations/2025-06-17-160618_wallet_activity/up.sql @@ -0,0 +1,34 @@ +ALTER TABLE "ramps_transactions" +ADD COLUMN "private_key" TEXT; + +CREATE TABLE "wallet_activity" ( + "id" UUID NOT NULL PRIMARY KEY, + "address" BPCHAR (64) NOT NULL, + "kind" TEXT NOT NULL, + "data" BYTEA NOT NULL, + "active" BOOL NOT NULL, + "completed_at" TIMESTAMPTZ, + "updated_at" TIMESTAMPTZ NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE TABLE "wallet_notes" ( + "commitment" BPCHAR (64) NOT NULL PRIMARY KEY, + "address" BPCHAR (64) NOT NULL, + "data" BYTEA NOT NULL, + "status" TEXT NOT NULL, + "activity_id" UUID, + "updated_at" TIMESTAMPTZ NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE TABLE "registry_notes" ( + "id" UUID NOT NULL PRIMARY KEY, + "block" BIGINT NOT NULL, + "public_key" BPCHAR (64) NOT NULL, + "encrypted_key" BYTEA NOT NULL, + "encrypted_note" BYTEA NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL +); + +CREATE TABLE "migrate_elements" ("element" BPCHAR (64) NOT NULL PRIMARY KEY); diff --git a/pkg/database/migrations/2025-06-17-164026_update_ramps_account_unique_address_provider_country_index/down.sql b/pkg/database/migrations/2025-06-17-164026_update_ramps_account_unique_address_provider_country_index/down.sql new file mode 100644 index 0000000..437ab80 --- /dev/null +++ b/pkg/database/migrations/2025-06-17-164026_update_ramps_account_unique_address_provider_country_index/down.sql @@ -0,0 +1,4 @@ +DROP INDEX IF EXISTS unique_wallet_id_provider_country; + +CREATE UNIQUE INDEX unique_address_provider_country +ON ramps_accounts(address, provider, (COALESCE(country, 'NULL'))); diff --git a/pkg/database/migrations/2025-06-17-164026_update_ramps_account_unique_address_provider_country_index/up.sql b/pkg/database/migrations/2025-06-17-164026_update_ramps_account_unique_address_provider_country_index/up.sql new file mode 100644 index 0000000..b6ed285 --- /dev/null +++ b/pkg/database/migrations/2025-06-17-164026_update_ramps_account_unique_address_provider_country_index/up.sql @@ -0,0 +1,5 @@ +DROP INDEX IF EXISTS unique_address_provider_country; + +CREATE UNIQUE INDEX unique_wallet_id_provider_country +ON ramps_accounts(wallet_id, provider, (COALESCE(country, 'NULL'))); + diff --git a/pkg/database/migrations/2025-06-17-175935_wallet_version/down.sql b/pkg/database/migrations/2025-06-17-175935_wallet_version/down.sql new file mode 100644 index 0000000..b58bda9 --- /dev/null +++ b/pkg/database/migrations/2025-06-17-175935_wallet_version/down.sql @@ -0,0 +1,2 @@ +ALTER TABLE "wallets" DROP COLUMN "data"; +ALTER TABLE "wallets" DROP COLUMN "version"; \ No newline at end of file diff --git a/pkg/database/migrations/2025-06-17-175935_wallet_version/up.sql b/pkg/database/migrations/2025-06-17-175935_wallet_version/up.sql new file mode 100644 index 0000000..a31bff7 --- /dev/null +++ b/pkg/database/migrations/2025-06-17-175935_wallet_version/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE "wallets" ADD COLUMN "data" JSONB; +ALTER TABLE "wallets" ADD COLUMN "version" INT2 NOT NULL DEFAULT 0; \ No newline at end of file diff --git a/pkg/database/migrations/2025-06-20-092107_funding_kind/down.sql b/pkg/database/migrations/2025-06-20-092107_funding_kind/down.sql new file mode 100644 index 0000000..e2e5d77 --- /dev/null +++ b/pkg/database/migrations/2025-06-20-092107_funding_kind/down.sql @@ -0,0 +1 @@ +ALTER TABLE "ramps_transactions" DROP COLUMN "funding_kind"; diff --git a/pkg/database/migrations/2025-06-20-092107_funding_kind/up.sql b/pkg/database/migrations/2025-06-20-092107_funding_kind/up.sql new file mode 100644 index 0000000..0d9c671 --- /dev/null +++ b/pkg/database/migrations/2025-06-20-092107_funding_kind/up.sql @@ -0,0 +1 @@ +ALTER TABLE "ramps_transactions" ADD COLUMN "funding_kind" TEXT NOT NULL DEFAULT 'CRYPTO'; \ No newline at end of file diff --git a/pkg/database/migrations/2025-07-03-120816_create_referral_links/down.sql b/pkg/database/migrations/2025-07-03-120816_create_referral_links/down.sql new file mode 100644 index 0000000..0cba5f9 --- /dev/null +++ b/pkg/database/migrations/2025-07-03-120816_create_referral_links/down.sql @@ -0,0 +1,3 @@ +DROP TRIGGER IF EXISTS "set_updated_at_for_udh_referral_links" ON udh_referral_links; +DROP FUNCTION IF EXISTS update_udh_referral_links_updated_at_column(); +DROP TABLE IF EXISTS "udh_referral_links"; diff --git a/pkg/database/migrations/2025-07-03-120816_create_referral_links/up.sql b/pkg/database/migrations/2025-07-03-120816_create_referral_links/up.sql new file mode 100644 index 0000000..d76fe20 --- /dev/null +++ b/pkg/database/migrations/2025-07-03-120816_create_referral_links/up.sql @@ -0,0 +1,22 @@ +CREATE TABLE "udh_referral_links"( + "posthog_id" TEXT NOT NULL PRIMARY KEY, + "user_device_hash" TEXT NOT NULL, + "referrer_url" TEXT NOT NULL, + "claimed_at" TIMESTAMP WITH TIME ZONE, + "wallet_id" UUID, + "added_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), + "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now() +); + +CREATE OR REPLACE FUNCTION update_udh_referral_links_updated_at_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = now(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER set_updated_at_for_udh_referral_links +BEFORE UPDATE ON udh_referral_links +FOR EACH ROW +EXECUTE FUNCTION update_udh_referral_links_updated_at_column(); diff --git a/pkg/database/migrations/2025-08-08-055057_fraud_block/down.sql b/pkg/database/migrations/2025-08-08-055057_fraud_block/down.sql new file mode 100644 index 0000000..0656038 --- /dev/null +++ b/pkg/database/migrations/2025-08-08-055057_fraud_block/down.sql @@ -0,0 +1 @@ +ALTER TABLE "wallets" DROP COLUMN "fraud_block"; \ No newline at end of file diff --git a/pkg/database/migrations/2025-08-08-055057_fraud_block/up.sql b/pkg/database/migrations/2025-08-08-055057_fraud_block/up.sql new file mode 100644 index 0000000..34d247f --- /dev/null +++ b/pkg/database/migrations/2025-08-08-055057_fraud_block/up.sql @@ -0,0 +1 @@ +ALTER TABLE "wallets" ADD COLUMN "fraud_block" BOOL NOT NULL DEFAULT FALSE; \ No newline at end of file diff --git a/pkg/database/migrations/2025-09-09-101435_create_guardian_tables/down.sql b/pkg/database/migrations/2025-09-09-101435_create_guardian_tables/down.sql new file mode 100644 index 0000000..6cb754b --- /dev/null +++ b/pkg/database/migrations/2025-09-09-101435_create_guardian_tables/down.sql @@ -0,0 +1,6 @@ +-- This file should undo anything in `up.sql` + +-- Drop tables in reverse order (to handle any potential foreign key dependencies) +DROP TABLE IF EXISTS guardian_types; +DROP TABLE IF EXISTS guardian_id_to_address; +DROP TABLE IF EXISTS guardian_id_to_ciphertext; \ No newline at end of file diff --git a/pkg/database/migrations/2025-09-09-101435_create_guardian_tables/up.sql b/pkg/database/migrations/2025-09-09-101435_create_guardian_tables/up.sql new file mode 100644 index 0000000..e38e8d9 --- /dev/null +++ b/pkg/database/migrations/2025-09-09-101435_create_guardian_tables/up.sql @@ -0,0 +1,35 @@ +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; + +-- Create guardian_id_to_ciphertext table +CREATE TABLE ciphertexts ( + "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "ciphertext" TEXT NOT NULL, + "address" BPCHAR(64) NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + UNIQUE("address") +); + +-- Create guardian_types table +CREATE TABLE guardians ( + "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "name" TEXT UNIQUE NOT NULL, + "display_name" TEXT NOT NULL, + "ipfs_cid" TEXT NOT NULL, + "is_active" BOOLEAN NOT NULL DEFAULT TRUE, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now() +); + +-- Create guardian_id_to_address table +CREATE TABLE guardian_id_to_address ( + "guardian_id" UUID NOT NULL, + "ciphertext_id" UUID NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + PRIMARY KEY ("guardian_id", "ciphertext_id"), + CONSTRAINT fk_guardian_ciphertext FOREIGN KEY ("guardian_id") REFERENCES guardians("id") ON DELETE CASCADE, + CONSTRAINT fk_gc_ciphertext FOREIGN KEY ("ciphertext_id") REFERENCES ciphertexts("id") ON DELETE CASCADE +); + +-- active guardians will be fetched frequently +CREATE INDEX idx_guardians_is_active ON guardians (is_active); +CREATE INDEX idx_guardian_id_to_address_ciphertext_id ON guardian_id_to_address (ciphertext_id); diff --git a/pkg/database/migrations/2025-09-15-233721_create_wallet_auths/down.sql b/pkg/database/migrations/2025-09-15-233721_create_wallet_auths/down.sql new file mode 100644 index 0000000..fc9dbeb --- /dev/null +++ b/pkg/database/migrations/2025-09-15-233721_create_wallet_auths/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS "wallet_auths"; \ No newline at end of file diff --git a/pkg/database/migrations/2025-09-15-233721_create_wallet_auths/up.sql b/pkg/database/migrations/2025-09-15-233721_create_wallet_auths/up.sql new file mode 100644 index 0000000..b51fe78 --- /dev/null +++ b/pkg/database/migrations/2025-09-15-233721_create_wallet_auths/up.sql @@ -0,0 +1,26 @@ +CREATE TABLE "wallet_auths"( + "id" UUID NOT NULL PRIMARY KEY DEFAULT gen_random_uuid(), + "wallet_id" UUID NOT NULL, + "kind" TEXT NOT NULL, + "value" TEXT NOT NULL, + "enabled" BOOLEAN NOT NULL DEFAULT true, + "added_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), + "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), + + CONSTRAINT fk_wallet_auths_wallet_id FOREIGN KEY ("wallet_id") REFERENCES "wallets"("id") ON DELETE CASCADE +); + +-- Create index for efficient wallet_id lookups +CREATE INDEX idx_wallet_auths_wallet_id ON "wallet_auths"("wallet_id"); + +-- Create index for enabled auths +CREATE INDEX idx_wallet_auths_wallet_id_enabled ON "wallet_auths"("wallet_id", "enabled") WHERE enabled = true; + +-- Create index for lookup +CREATE INDEX idx_kind_value_enabled ON "wallet_auths"("kind", "value", "enabled") WHERE enabled = true; + +-- trigger to automatically update the `update_at` column when a row changes +CREATE TRIGGER set_updated_at_for_wallet_auths +BEFORE UPDATE ON wallet_auths +FOR EACH ROW +EXECUTE FUNCTION update_updated_at_column(); diff --git a/pkg/database/migrations/2025-09-23-164729_add_data_to_encrypt_hash/down.sql b/pkg/database/migrations/2025-09-23-164729_add_data_to_encrypt_hash/down.sql new file mode 100644 index 0000000..d0d1c94 --- /dev/null +++ b/pkg/database/migrations/2025-09-23-164729_add_data_to_encrypt_hash/down.sql @@ -0,0 +1,2 @@ +ALTER TABLE ciphertexts +DROP COLUMN IF EXISTS data_to_encrypt_hash; diff --git a/pkg/database/migrations/2025-09-23-164729_add_data_to_encrypt_hash/up.sql b/pkg/database/migrations/2025-09-23-164729_add_data_to_encrypt_hash/up.sql new file mode 100644 index 0000000..98181a0 --- /dev/null +++ b/pkg/database/migrations/2025-09-23-164729_add_data_to_encrypt_hash/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE ciphertexts +ADD COLUMN data_to_encrypt_hash TEXT NOT NULL; diff --git a/pkg/database/migrations/2025-09-30-155759_restrict_replit_sensitive_columns/down.sql b/pkg/database/migrations/2025-09-30-155759_restrict_replit_sensitive_columns/down.sql new file mode 100644 index 0000000..3d3f6aa --- /dev/null +++ b/pkg/database/migrations/2025-09-30-155759_restrict_replit_sensitive_columns/down.sql @@ -0,0 +1,24 @@ +-- Restore the original broad SELECT privileges for the replit user. + +REVOKE SELECT ( + "id", + "address", + "psi", + "value", + "owner_id", + "status", + "parent_1_id", + "received_ref_kind", + "received_ref_id", + "spent_at", + "added_at", + "updated_at", + "commitment", + "spend_ref_kind", + "spend_ref_id", + "parent_2_id", + "version", + "kind" +) ON TABLE notes FROM replit; +GRANT SELECT ON TABLE notes TO replit; +DROP USER replit; diff --git a/pkg/database/migrations/2025-09-30-155759_restrict_replit_sensitive_columns/up.sql b/pkg/database/migrations/2025-09-30-155759_restrict_replit_sensitive_columns/up.sql new file mode 100644 index 0000000..d255651 --- /dev/null +++ b/pkg/database/migrations/2025-09-30-155759_restrict_replit_sensitive_columns/up.sql @@ -0,0 +1,37 @@ +-- Restrict the replit support user from reading sensitive columns while retaining +-- access to non-sensitive data required by the admin dashboard. + +DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'replit') + THEN + CREATE USER replit; + END IF; +END +$$; + +-- Remove existing broad table-level SELECT privileges on notes. We deliberately do not touch +-- INSERT privileges to avoid disrupting existing workflows. +REVOKE SELECT ON TABLE notes FROM replit; + +-- Grant column-scoped SELECT on notes, excluding the private_key field. +GRANT SELECT ( + "id", + "address", + "psi", + "value", + "owner_id", + "status", + "parent_1_id", + "received_ref_kind", + "received_ref_id", + "spent_at", + "added_at", + "updated_at", + "commitment", + "spend_ref_kind", + "spend_ref_id", + "parent_2_id", + "version", + "kind" +) ON TABLE notes TO replit; diff --git a/pkg/database/migrations/2025-10-13-120000_create_token_prices/down.sql b/pkg/database/migrations/2025-10-13-120000_create_token_prices/down.sql new file mode 100644 index 0000000..eb6a683 --- /dev/null +++ b/pkg/database/migrations/2025-10-13-120000_create_token_prices/down.sql @@ -0,0 +1,12 @@ +DROP INDEX IF EXISTS idx_token_price_history_network_address; +DROP INDEX IF EXISTS idx_token_price_history_symbol_currency; +DROP TABLE IF EXISTS token_price_history; + +ALTER TABLE token_prices + DROP CONSTRAINT IF EXISTS token_prices_symbol_network_currency_unique; +ALTER TABLE token_prices + DROP CONSTRAINT IF EXISTS token_prices_network_contract_currency_unique; +DROP INDEX IF EXISTS idx_token_prices_updated; +DROP INDEX IF EXISTS idx_token_prices_address; +DROP INDEX IF EXISTS idx_token_prices_symbol; +DROP TABLE IF EXISTS token_prices; diff --git a/pkg/database/migrations/2025-10-13-120000_create_token_prices/up.sql b/pkg/database/migrations/2025-10-13-120000_create_token_prices/up.sql new file mode 100644 index 0000000..bfdaa49 --- /dev/null +++ b/pkg/database/migrations/2025-10-13-120000_create_token_prices/up.sql @@ -0,0 +1,40 @@ +CREATE TABLE token_prices ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + symbol VARCHAR(20), + network VARCHAR(50) NOT NULL DEFAULT 'global', + contract_address CHAR(42), + price NUMERIC NOT NULL, + currency TEXT NOT NULL DEFAULT 'USD', + last_updated_at TIMESTAMPTZ NOT NULL, + fetched_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + metadata JSONB +); + +CREATE INDEX idx_token_prices_symbol ON token_prices(symbol); +CREATE INDEX idx_token_prices_address ON token_prices(network, contract_address); +CREATE INDEX idx_token_prices_updated ON token_prices(last_updated_at); + +ALTER TABLE token_prices + ADD CONSTRAINT token_prices_network_contract_currency_unique + UNIQUE (network, contract_address, currency); + +ALTER TABLE token_prices + ADD CONSTRAINT token_prices_symbol_network_currency_unique + UNIQUE (symbol, network, currency); + +CREATE TABLE token_price_history ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + symbol VARCHAR(20), + network VARCHAR(50) NOT NULL DEFAULT 'global', + contract_address CHAR(42), + price NUMERIC NOT NULL, + currency TEXT NOT NULL DEFAULT 'USD', + last_updated_at TIMESTAMPTZ NOT NULL, + fetched_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + metadata JSONB +); + +CREATE INDEX idx_token_price_history_symbol_currency + ON token_price_history(symbol, currency, fetched_at DESC); +CREATE INDEX idx_token_price_history_network_address + ON token_price_history(network, contract_address, fetched_at DESC); diff --git a/pkg/database/migrations/2025-10-16-101653_add_deleted_at_to_ramps_methods/down.sql b/pkg/database/migrations/2025-10-16-101653_add_deleted_at_to_ramps_methods/down.sql new file mode 100644 index 0000000..ff4c547 --- /dev/null +++ b/pkg/database/migrations/2025-10-16-101653_add_deleted_at_to_ramps_methods/down.sql @@ -0,0 +1,2 @@ +DROP INDEX IF EXISTS idx_ramps_methods_deleted_at; +ALTER TABLE ramps_methods DROP COLUMN deleted_at; diff --git a/pkg/database/migrations/2025-10-16-101653_add_deleted_at_to_ramps_methods/up.sql b/pkg/database/migrations/2025-10-16-101653_add_deleted_at_to_ramps_methods/up.sql new file mode 100644 index 0000000..c973d6b --- /dev/null +++ b/pkg/database/migrations/2025-10-16-101653_add_deleted_at_to_ramps_methods/up.sql @@ -0,0 +1,4 @@ +ALTER TABLE ramps_methods + ADD COLUMN deleted_at TIMESTAMPTZ DEFAULT NULL; + +CREATE INDEX idx_ramps_methods_deleted_at ON ramps_methods(deleted_at); diff --git a/pkg/database/migrations/2025-11-06-120000_add_wallet_activity_notes_indexes/down.sql b/pkg/database/migrations/2025-11-06-120000_add_wallet_activity_notes_indexes/down.sql new file mode 100644 index 0000000..55218dd --- /dev/null +++ b/pkg/database/migrations/2025-11-06-120000_add_wallet_activity_notes_indexes/down.sql @@ -0,0 +1,4 @@ +-- no transaction + +DROP INDEX CONCURRENTLY IF EXISTS idx_wallet_activity_address_updated_at; +DROP INDEX CONCURRENTLY IF EXISTS idx_wallet_notes_address_added_at; diff --git a/pkg/database/migrations/2025-11-06-120000_add_wallet_activity_notes_indexes/up.sql b/pkg/database/migrations/2025-11-06-120000_add_wallet_activity_notes_indexes/up.sql new file mode 100644 index 0000000..61034d7 --- /dev/null +++ b/pkg/database/migrations/2025-11-06-120000_add_wallet_activity_notes_indexes/up.sql @@ -0,0 +1,5 @@ +CREATE INDEX idx_wallet_activity_address_updated_at + ON wallet_activity(address, updated_at DESC); + +CREATE INDEX idx_wallet_notes_address_added_at + ON wallet_notes(address, added_at DESC); diff --git a/pkg/database/migrations/2025-12-05-120000_add_guardian_secret_to_guardian_id_to_address/down.sql b/pkg/database/migrations/2025-12-05-120000_add_guardian_secret_to_guardian_id_to_address/down.sql new file mode 100644 index 0000000..a3ea78f --- /dev/null +++ b/pkg/database/migrations/2025-12-05-120000_add_guardian_secret_to_guardian_id_to_address/down.sql @@ -0,0 +1,2 @@ +DROP INDEX IF EXISTS idx_guardian_id_to_address_guardian_secret; +ALTER TABLE guardian_id_to_address DROP COLUMN "guardian_secret"; diff --git a/pkg/database/migrations/2025-12-05-120000_add_guardian_secret_to_guardian_id_to_address/up.sql b/pkg/database/migrations/2025-12-05-120000_add_guardian_secret_to_guardian_id_to_address/up.sql new file mode 100644 index 0000000..3b793dc --- /dev/null +++ b/pkg/database/migrations/2025-12-05-120000_add_guardian_secret_to_guardian_id_to_address/up.sql @@ -0,0 +1,8 @@ +ALTER TABLE guardian_id_to_address +ADD COLUMN "guardian_secret" TEXT; + +ALTER TABLE guardian_id_to_address +ALTER COLUMN guardian_secret SET NOT NULL; + +CREATE UNIQUE INDEX idx_guardian_id_to_address_guardian_secret +ON guardian_id_to_address (guardian_secret); diff --git a/pkg/database/migrations/2026-01-02-000001_support_tags/down.sql b/pkg/database/migrations/2026-01-02-000001_support_tags/down.sql new file mode 100644 index 0000000..214c9c8 --- /dev/null +++ b/pkg/database/migrations/2026-01-02-000001_support_tags/down.sql @@ -0,0 +1,4 @@ +DROP INDEX IF EXISTS idx_support_issue_tags_tag_id; +DROP INDEX IF EXISTS idx_support_tags_is_active; +DROP TABLE IF EXISTS support_issue_tags; +DROP TABLE IF EXISTS support_tags; diff --git a/pkg/database/migrations/2026-01-02-000001_support_tags/up.sql b/pkg/database/migrations/2026-01-02-000001_support_tags/up.sql new file mode 100644 index 0000000..93b74b9 --- /dev/null +++ b/pkg/database/migrations/2026-01-02-000001_support_tags/up.sql @@ -0,0 +1,22 @@ +CREATE TABLE support_tags ( + "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "name" TEXT UNIQUE NOT NULL, + "display_name" TEXT NOT NULL, + "color" TEXT NOT NULL, + "is_active" BOOLEAN NOT NULL DEFAULT TRUE, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE support_issue_tags ( + "support_issue_id" UUID NOT NULL, + "support_tag_id" UUID NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + PRIMARY KEY ("support_issue_id", "support_tag_id"), + CONSTRAINT fk_support_issue FOREIGN KEY ("support_issue_id") + REFERENCES support_issues("id") ON DELETE CASCADE, + CONSTRAINT fk_support_tag FOREIGN KEY ("support_tag_id") + REFERENCES support_tags("id") ON DELETE CASCADE +); + +CREATE INDEX idx_support_tags_is_active ON support_tags (is_active); +CREATE INDEX idx_support_issue_tags_tag_id ON support_issue_tags (support_tag_id); diff --git a/pkg/database/migrations/2026-01-02-120500_support_issues_metadata/down.sql b/pkg/database/migrations/2026-01-02-120500_support_issues_metadata/down.sql new file mode 100644 index 0000000..4615d5a --- /dev/null +++ b/pkg/database/migrations/2026-01-02-120500_support_issues_metadata/down.sql @@ -0,0 +1 @@ +ALTER TABLE support_issues DROP COLUMN metadata; diff --git a/pkg/database/migrations/2026-01-02-120500_support_issues_metadata/up.sql b/pkg/database/migrations/2026-01-02-120500_support_issues_metadata/up.sql new file mode 100644 index 0000000..41ff28a --- /dev/null +++ b/pkg/database/migrations/2026-01-02-120500_support_issues_metadata/up.sql @@ -0,0 +1 @@ +ALTER TABLE support_issues ADD COLUMN metadata JSONB; diff --git a/pkg/database/migrations/2026-01-02-125500_add_auto_close_minutes_to_support_tags/down.sql b/pkg/database/migrations/2026-01-02-125500_add_auto_close_minutes_to_support_tags/down.sql new file mode 100644 index 0000000..7096366 --- /dev/null +++ b/pkg/database/migrations/2026-01-02-125500_add_auto_close_minutes_to_support_tags/down.sql @@ -0,0 +1,5 @@ +DROP INDEX IF EXISTS idx_support_issues_auto_close_at; +ALTER TABLE support_issues DROP COLUMN IF EXISTS auto_close_at; +ALTER TABLE support_issues DROP COLUMN IF EXISTS auto_close_minutes; + +ALTER TABLE support_tags DROP COLUMN IF EXISTS auto_close_minutes; diff --git a/pkg/database/migrations/2026-01-02-125500_add_auto_close_minutes_to_support_tags/up.sql b/pkg/database/migrations/2026-01-02-125500_add_auto_close_minutes_to_support_tags/up.sql new file mode 100644 index 0000000..f484e01 --- /dev/null +++ b/pkg/database/migrations/2026-01-02-125500_add_auto_close_minutes_to_support_tags/up.sql @@ -0,0 +1,7 @@ +ALTER TABLE support_tags ADD COLUMN auto_close_minutes INT; + +ALTER TABLE support_issues ADD COLUMN auto_close_at TIMESTAMPTZ; +ALTER TABLE support_issues ADD COLUMN auto_close_minutes INT; + +CREATE INDEX idx_support_issues_auto_close_at ON support_issues (auto_close_at) + WHERE auto_close_at IS NOT NULL AND status != 'CLOSED'; diff --git a/pkg/database/migrations/2026-01-02-130000_add_is_bot_to_support_messages/down.sql b/pkg/database/migrations/2026-01-02-130000_add_is_bot_to_support_messages/down.sql new file mode 100644 index 0000000..4020278 --- /dev/null +++ b/pkg/database/migrations/2026-01-02-130000_add_is_bot_to_support_messages/down.sql @@ -0,0 +1 @@ +ALTER TABLE "support_messages" DROP COLUMN "is_bot"; diff --git a/pkg/database/migrations/2026-01-02-130000_add_is_bot_to_support_messages/up.sql b/pkg/database/migrations/2026-01-02-130000_add_is_bot_to_support_messages/up.sql new file mode 100644 index 0000000..3577a24 --- /dev/null +++ b/pkg/database/migrations/2026-01-02-130000_add_is_bot_to_support_messages/up.sql @@ -0,0 +1 @@ +ALTER TABLE "support_messages" ADD COLUMN "is_bot" BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/pkg/database/migrations/2026-01-02-140000_support_canned_responses/down.sql b/pkg/database/migrations/2026-01-02-140000_support_canned_responses/down.sql new file mode 100644 index 0000000..3333511 --- /dev/null +++ b/pkg/database/migrations/2026-01-02-140000_support_canned_responses/down.sql @@ -0,0 +1,3 @@ +DROP TRIGGER IF EXISTS update_support_canned_responses_updated_at ON support_canned_responses; +DROP TABLE IF EXISTS support_canned_response_tags; +DROP TABLE IF EXISTS support_canned_responses; diff --git a/pkg/database/migrations/2026-01-02-140000_support_canned_responses/up.sql b/pkg/database/migrations/2026-01-02-140000_support_canned_responses/up.sql new file mode 100644 index 0000000..779321b --- /dev/null +++ b/pkg/database/migrations/2026-01-02-140000_support_canned_responses/up.sql @@ -0,0 +1,28 @@ +CREATE TABLE support_canned_responses ( + "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "name" TEXT UNIQUE NOT NULL, + "display_name" TEXT NOT NULL, + "content" TEXT NOT NULL, + "is_active" BOOLEAN NOT NULL DEFAULT TRUE, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE support_canned_response_tags ( + "support_canned_response_id" UUID NOT NULL, + "support_tag_id" UUID NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + PRIMARY KEY ("support_canned_response_id", "support_tag_id"), + CONSTRAINT fk_canned_response FOREIGN KEY ("support_canned_response_id") + REFERENCES support_canned_responses("id") ON DELETE CASCADE, + CONSTRAINT fk_support_tag FOREIGN KEY ("support_tag_id") + REFERENCES support_tags("id") ON DELETE CASCADE +); + +CREATE INDEX idx_canned_responses_is_active ON support_canned_responses (is_active); +CREATE INDEX idx_canned_response_tags_tag_id ON support_canned_response_tags (support_tag_id); + +CREATE TRIGGER update_support_canned_responses_updated_at + BEFORE UPDATE ON support_canned_responses + FOR EACH ROW + EXECUTE FUNCTION update_updated_at_column(); diff --git a/pkg/database/migrations/2026-01-03-000001_add_is_internal_to_support_messages/down.sql b/pkg/database/migrations/2026-01-03-000001_add_is_internal_to_support_messages/down.sql new file mode 100644 index 0000000..b0542ac --- /dev/null +++ b/pkg/database/migrations/2026-01-03-000001_add_is_internal_to_support_messages/down.sql @@ -0,0 +1 @@ +ALTER TABLE "support_messages" DROP COLUMN "is_internal"; diff --git a/pkg/database/migrations/2026-01-03-000001_add_is_internal_to_support_messages/up.sql b/pkg/database/migrations/2026-01-03-000001_add_is_internal_to_support_messages/up.sql new file mode 100644 index 0000000..073105e --- /dev/null +++ b/pkg/database/migrations/2026-01-03-000001_add_is_internal_to_support_messages/up.sql @@ -0,0 +1 @@ +ALTER TABLE "support_messages" ADD COLUMN "is_internal" BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/pkg/database/migrations/2026-01-10-120000_add_notes_commitment_status_idx/down.sql b/pkg/database/migrations/2026-01-10-120000_add_notes_commitment_status_idx/down.sql new file mode 100644 index 0000000..13a92b3 --- /dev/null +++ b/pkg/database/migrations/2026-01-10-120000_add_notes_commitment_status_idx/down.sql @@ -0,0 +1,3 @@ +-- no transaction + +DROP INDEX CONCURRENTLY IF EXISTS notes_commitment_status_idx; diff --git a/pkg/database/migrations/2026-01-10-120000_add_notes_commitment_status_idx/up.sql b/pkg/database/migrations/2026-01-10-120000_add_notes_commitment_status_idx/up.sql new file mode 100644 index 0000000..6fcd28b --- /dev/null +++ b/pkg/database/migrations/2026-01-10-120000_add_notes_commitment_status_idx/up.sql @@ -0,0 +1 @@ +CREATE INDEX IF NOT EXISTS notes_commitment_status_idx ON notes(commitment, status); diff --git a/pkg/database/migrations/2026-01-10-120000_add_ramps_transactions_account_funding_idx/down.sql b/pkg/database/migrations/2026-01-10-120000_add_ramps_transactions_account_funding_idx/down.sql new file mode 100644 index 0000000..8ebfc74 --- /dev/null +++ b/pkg/database/migrations/2026-01-10-120000_add_ramps_transactions_account_funding_idx/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS ramps_transactions_account_funding_idx; diff --git a/pkg/database/migrations/2026-01-10-120000_add_ramps_transactions_account_funding_idx/up.sql b/pkg/database/migrations/2026-01-10-120000_add_ramps_transactions_account_funding_idx/up.sql new file mode 100644 index 0000000..af345a4 --- /dev/null +++ b/pkg/database/migrations/2026-01-10-120000_add_ramps_transactions_account_funding_idx/up.sql @@ -0,0 +1,3 @@ +CREATE INDEX IF NOT EXISTS ramps_transactions_account_funding_idx +ON ramps_transactions(account_id, funding_status) +INCLUDE (funding_due_amount); diff --git a/pkg/database/migrations/2026-01-12-150000_rename_guardian_tables/down.sql b/pkg/database/migrations/2026-01-12-150000_rename_guardian_tables/down.sql new file mode 100644 index 0000000..f08bda0 --- /dev/null +++ b/pkg/database/migrations/2026-01-12-150000_rename_guardian_tables/down.sql @@ -0,0 +1,10 @@ +ALTER TABLE guardian_to_ciphertext RENAME TO guardian_id_to_address; + +ALTER TABLE guardian_id_to_address + RENAME COLUMN guardian_auth_value TO guardian_secret; + +ALTER INDEX idx_guardian_to_ciphertext_ciphertext_id + RENAME TO idx_guardian_id_to_address_ciphertext_id; + +ALTER INDEX idx_guardian_to_ciphertext_guardian_auth_value + RENAME TO idx_guardian_id_to_address_guardian_secret; diff --git a/pkg/database/migrations/2026-01-12-150000_rename_guardian_tables/up.sql b/pkg/database/migrations/2026-01-12-150000_rename_guardian_tables/up.sql new file mode 100644 index 0000000..b2b2123 --- /dev/null +++ b/pkg/database/migrations/2026-01-12-150000_rename_guardian_tables/up.sql @@ -0,0 +1,10 @@ +ALTER TABLE guardian_id_to_address RENAME TO guardian_to_ciphertext; + +ALTER TABLE guardian_to_ciphertext + RENAME COLUMN guardian_secret TO guardian_auth_value; + +ALTER INDEX idx_guardian_id_to_address_ciphertext_id + RENAME TO idx_guardian_to_ciphertext_ciphertext_id; + +ALTER INDEX idx_guardian_id_to_address_guardian_secret + RENAME TO idx_guardian_to_ciphertext_guardian_auth_value; diff --git a/pkg/database/migrations/2026-01-14-120000_bpchar_to_text/down.sql b/pkg/database/migrations/2026-01-14-120000_bpchar_to_text/down.sql new file mode 100644 index 0000000..e7991c9 --- /dev/null +++ b/pkg/database/migrations/2026-01-14-120000_bpchar_to_text/down.sql @@ -0,0 +1,37 @@ +-- Revert TEXT columns back to BPCHAR +ALTER TABLE blocklist_ip ALTER COLUMN ip TYPE BPCHAR(45); +ALTER TABLE blocklist_mobile ALTER COLUMN mobile TYPE BPCHAR(20); +ALTER TABLE blocklist_mobile ALTER COLUMN ip TYPE BPCHAR(45); +ALTER TABLE blocklist_mobile ALTER COLUMN country_code TYPE BPCHAR(2); +ALTER TABLE blocklist_trace ALTER COLUMN mobile TYPE BPCHAR(20); +ALTER TABLE blocklist_trace ALTER COLUMN ip TYPE BPCHAR(45); +ALTER TABLE ciphertexts ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE diagnostics ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE faucets ALTER COLUMN claimed_by TYPE BPCHAR(64); +ALTER TABLE faucets ALTER COLUMN device_id TYPE BPCHAR(64); +ALTER TABLE ip_data ALTER COLUMN ip TYPE BPCHAR(39); +ALTER TABLE migrate_elements ALTER COLUMN element TYPE BPCHAR(64); +ALTER TABLE nfts ALTER COLUMN claimed_by TYPE BPCHAR(64); +ALTER TABLE notes ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE notes ALTER COLUMN private_key TYPE BPCHAR(64); +ALTER TABLE notes ALTER COLUMN psi TYPE BPCHAR(64); +ALTER TABLE notes ALTER COLUMN commitment TYPE BPCHAR(64); +ALTER TABLE notes ALTER COLUMN kind TYPE BPCHAR(64); +ALTER TABLE ramps_accounts ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE ramps_transactions ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE registry_notes ALTER COLUMN public_key TYPE BPCHAR(64); +ALTER TABLE rewards ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE rewards ALTER COLUMN code TYPE BPCHAR(6); +ALTER TABLE rewards_invites ALTER COLUMN from_address TYPE BPCHAR(64); +ALTER TABLE rewards_invites ALTER COLUMN to_address TYPE BPCHAR(64); +ALTER TABLE rewards_points ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE token_price_history ALTER COLUMN contract_address TYPE BPCHAR(42); +ALTER TABLE token_prices ALTER COLUMN contract_address TYPE BPCHAR(42); +ALTER TABLE wallet_activity ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE wallet_backup_tags ALTER COLUMN wallet_address TYPE BPCHAR(64); +ALTER TABLE wallet_backups ALTER COLUMN wallet_address TYPE BPCHAR(64); +ALTER TABLE wallet_notes ALTER COLUMN commitment TYPE BPCHAR(64); +ALTER TABLE wallet_notes ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE wallets ALTER COLUMN address TYPE BPCHAR(64); +ALTER TABLE wallets ALTER COLUMN deposit_address TYPE BPCHAR(64); +ALTER TABLE wallets_addresses ALTER COLUMN address TYPE BPCHAR(64); diff --git a/pkg/database/migrations/2026-01-14-120000_bpchar_to_text/up.sql b/pkg/database/migrations/2026-01-14-120000_bpchar_to_text/up.sql new file mode 100644 index 0000000..4a0df2e --- /dev/null +++ b/pkg/database/migrations/2026-01-14-120000_bpchar_to_text/up.sql @@ -0,0 +1,38 @@ +-- Convert BPCHAR columns to TEXT +DROP INDEX IF EXISTS unique_address_provider_country; +ALTER TABLE blocklist_ip ALTER COLUMN ip TYPE TEXT; +ALTER TABLE blocklist_mobile ALTER COLUMN mobile TYPE TEXT; +ALTER TABLE blocklist_mobile ALTER COLUMN ip TYPE TEXT; +ALTER TABLE blocklist_mobile ALTER COLUMN country_code TYPE TEXT; +ALTER TABLE blocklist_trace ALTER COLUMN mobile TYPE TEXT; +ALTER TABLE blocklist_trace ALTER COLUMN ip TYPE TEXT; +ALTER TABLE ciphertexts ALTER COLUMN address TYPE TEXT; +ALTER TABLE diagnostics ALTER COLUMN address TYPE TEXT; +ALTER TABLE faucets ALTER COLUMN claimed_by TYPE TEXT; +ALTER TABLE faucets ALTER COLUMN device_id TYPE TEXT; +ALTER TABLE ip_data ALTER COLUMN ip TYPE TEXT; +ALTER TABLE migrate_elements ALTER COLUMN element TYPE TEXT; +ALTER TABLE nfts ALTER COLUMN claimed_by TYPE TEXT; +ALTER TABLE notes ALTER COLUMN address TYPE TEXT; +ALTER TABLE notes ALTER COLUMN private_key TYPE TEXT; +ALTER TABLE notes ALTER COLUMN psi TYPE TEXT; +ALTER TABLE notes ALTER COLUMN commitment TYPE TEXT; +ALTER TABLE notes ALTER COLUMN kind TYPE TEXT; +ALTER TABLE ramps_accounts ALTER COLUMN address TYPE TEXT; +ALTER TABLE ramps_transactions ALTER COLUMN address TYPE TEXT; +ALTER TABLE registry_notes ALTER COLUMN public_key TYPE TEXT; +ALTER TABLE rewards ALTER COLUMN address TYPE TEXT; +ALTER TABLE rewards ALTER COLUMN code TYPE TEXT; +ALTER TABLE rewards_invites ALTER COLUMN from_address TYPE TEXT; +ALTER TABLE rewards_invites ALTER COLUMN to_address TYPE TEXT; +ALTER TABLE rewards_points ALTER COLUMN address TYPE TEXT; +ALTER TABLE token_price_history ALTER COLUMN contract_address TYPE TEXT; +ALTER TABLE token_prices ALTER COLUMN contract_address TYPE TEXT; +ALTER TABLE wallet_activity ALTER COLUMN address TYPE TEXT; +ALTER TABLE wallet_backup_tags ALTER COLUMN wallet_address TYPE TEXT; +ALTER TABLE wallet_backups ALTER COLUMN wallet_address TYPE TEXT; +ALTER TABLE wallet_notes ALTER COLUMN commitment TYPE TEXT; +ALTER TABLE wallet_notes ALTER COLUMN address TYPE TEXT; +ALTER TABLE wallets ALTER COLUMN address TYPE TEXT; +ALTER TABLE wallets ALTER COLUMN deposit_address TYPE TEXT; +ALTER TABLE wallets_addresses ALTER COLUMN address TYPE TEXT; diff --git a/pkg/database/migrations/2026-01-15-120000_add_ramps_accounts_provider_external_idx/down.sql b/pkg/database/migrations/2026-01-15-120000_add_ramps_accounts_provider_external_idx/down.sql new file mode 100644 index 0000000..aca125f --- /dev/null +++ b/pkg/database/migrations/2026-01-15-120000_add_ramps_accounts_provider_external_idx/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS idx_ramps_accounts_provider_external; diff --git a/pkg/database/migrations/2026-01-15-120000_add_ramps_accounts_provider_external_idx/up.sql b/pkg/database/migrations/2026-01-15-120000_add_ramps_accounts_provider_external_idx/up.sql new file mode 100644 index 0000000..a4c9981 --- /dev/null +++ b/pkg/database/migrations/2026-01-15-120000_add_ramps_accounts_provider_external_idx/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX IF NOT EXISTS idx_ramps_accounts_provider_external + ON ramps_accounts (provider, external_id); diff --git a/pkg/database/migrations/2026-01-15-120000_add_registry_notes_public_key_idx/down.sql b/pkg/database/migrations/2026-01-15-120000_add_registry_notes_public_key_idx/down.sql new file mode 100644 index 0000000..17bc95c --- /dev/null +++ b/pkg/database/migrations/2026-01-15-120000_add_registry_notes_public_key_idx/down.sql @@ -0,0 +1,3 @@ +-- no transaction + +DROP INDEX CONCURRENTLY IF EXISTS registry_notes_public_key_added_at_idx; diff --git a/pkg/database/migrations/2026-01-15-120000_add_registry_notes_public_key_idx/up.sql b/pkg/database/migrations/2026-01-15-120000_add_registry_notes_public_key_idx/up.sql new file mode 100644 index 0000000..4c5a5da --- /dev/null +++ b/pkg/database/migrations/2026-01-15-120000_add_registry_notes_public_key_idx/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX IF NOT EXISTS registry_notes_public_key_added_at_idx + ON registry_notes (public_key, added_at DESC); diff --git a/pkg/database/migrations/2026-01-15-215707-0000_add_support_issues_wallet_updated_index/down.sql b/pkg/database/migrations/2026-01-15-215707-0000_add_support_issues_wallet_updated_index/down.sql new file mode 100644 index 0000000..3f052c6 --- /dev/null +++ b/pkg/database/migrations/2026-01-15-215707-0000_add_support_issues_wallet_updated_index/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS idx_support_issues_wallet_updated_desc; diff --git a/pkg/database/migrations/2026-01-15-215707-0000_add_support_issues_wallet_updated_index/up.sql b/pkg/database/migrations/2026-01-15-215707-0000_add_support_issues_wallet_updated_index/up.sql new file mode 100644 index 0000000..904e21d --- /dev/null +++ b/pkg/database/migrations/2026-01-15-215707-0000_add_support_issues_wallet_updated_index/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX IF NOT EXISTS idx_support_issues_wallet_updated_desc + ON support_issues (wallet_id, updated_at DESC); diff --git a/pkg/database/migrations/2026-01-16-120000_add_agent_id_to_support_messages/down.sql b/pkg/database/migrations/2026-01-16-120000_add_agent_id_to_support_messages/down.sql new file mode 100644 index 0000000..b2999a1 --- /dev/null +++ b/pkg/database/migrations/2026-01-16-120000_add_agent_id_to_support_messages/down.sql @@ -0,0 +1 @@ +ALTER TABLE "support_messages" DROP COLUMN "agent_id"; diff --git a/pkg/database/migrations/2026-01-16-120000_add_agent_id_to_support_messages/up.sql b/pkg/database/migrations/2026-01-16-120000_add_agent_id_to_support_messages/up.sql new file mode 100644 index 0000000..fd77bfc --- /dev/null +++ b/pkg/database/migrations/2026-01-16-120000_add_agent_id_to_support_messages/up.sql @@ -0,0 +1 @@ +ALTER TABLE "support_messages" ADD COLUMN "agent_id" INTEGER NULL; diff --git a/pkg/database/migrations/2026-01-19-120000_add_last_ai_support_bot_processed_at_to_support_issues/down.sql b/pkg/database/migrations/2026-01-19-120000_add_last_ai_support_bot_processed_at_to_support_issues/down.sql new file mode 100644 index 0000000..2bc75c3 --- /dev/null +++ b/pkg/database/migrations/2026-01-19-120000_add_last_ai_support_bot_processed_at_to_support_issues/down.sql @@ -0,0 +1,4 @@ +DROP INDEX IF EXISTS idx_support_issues_last_ai_support_bot_processed_at; + +ALTER TABLE support_issues + DROP COLUMN last_ai_support_bot_processed_at; diff --git a/pkg/database/migrations/2026-01-19-120000_add_last_ai_support_bot_processed_at_to_support_issues/up.sql b/pkg/database/migrations/2026-01-19-120000_add_last_ai_support_bot_processed_at_to_support_issues/up.sql new file mode 100644 index 0000000..a87db02 --- /dev/null +++ b/pkg/database/migrations/2026-01-19-120000_add_last_ai_support_bot_processed_at_to_support_issues/up.sql @@ -0,0 +1,5 @@ +ALTER TABLE support_issues + ADD COLUMN last_ai_support_bot_processed_at TIMESTAMPTZ; + +CREATE INDEX idx_support_issues_last_ai_support_bot_processed_at + ON support_issues (last_ai_support_bot_processed_at); diff --git a/pkg/database/migrations/2026-01-20-120000_add_support_indexes/down.sql b/pkg/database/migrations/2026-01-20-120000_add_support_indexes/down.sql new file mode 100644 index 0000000..561ccc4 --- /dev/null +++ b/pkg/database/migrations/2026-01-20-120000_add_support_indexes/down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS idx_support_issues_status_updated_at; +DROP INDEX IF EXISTS idx_support_issues_wallet_added_at; +DROP INDEX IF EXISTS idx_support_messages_issue_added_at; diff --git a/pkg/database/migrations/2026-01-20-120000_add_support_indexes/up.sql b/pkg/database/migrations/2026-01-20-120000_add_support_indexes/up.sql new file mode 100644 index 0000000..d0bed61 --- /dev/null +++ b/pkg/database/migrations/2026-01-20-120000_add_support_indexes/up.sql @@ -0,0 +1,8 @@ +CREATE INDEX IF NOT EXISTS idx_support_issues_status_updated_at + ON support_issues (status, updated_at DESC); + +CREATE INDEX IF NOT EXISTS idx_support_issues_wallet_added_at + ON support_issues (wallet_id, added_at DESC); + +CREATE INDEX IF NOT EXISTS idx_support_messages_issue_added_at + ON support_messages (support_issue_id, added_at ASC); diff --git a/pkg/database/migrations/2026-02-10-120000_add_notes_status_owner_version_value_idx/down.sql b/pkg/database/migrations/2026-02-10-120000_add_notes_status_owner_version_value_idx/down.sql new file mode 100644 index 0000000..9f35e98 --- /dev/null +++ b/pkg/database/migrations/2026-02-10-120000_add_notes_status_owner_version_value_idx/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS notes_status_owner_version_value_idx; diff --git a/pkg/database/migrations/2026-02-10-120000_add_notes_status_owner_version_value_idx/up.sql b/pkg/database/migrations/2026-02-10-120000_add_notes_status_owner_version_value_idx/up.sql new file mode 100644 index 0000000..a5320b8 --- /dev/null +++ b/pkg/database/migrations/2026-02-10-120000_add_notes_status_owner_version_value_idx/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX IF NOT EXISTS notes_status_owner_version_value_idx + ON notes(status, owner_id, version, value); diff --git a/pkg/database/migrations/2026-02-27-120000_drop_guardian_tables/down.sql b/pkg/database/migrations/2026-02-27-120000_drop_guardian_tables/down.sql new file mode 100644 index 0000000..9e4b40f --- /dev/null +++ b/pkg/database/migrations/2026-02-27-120000_drop_guardian_tables/down.sql @@ -0,0 +1,35 @@ +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; + +CREATE TABLE ciphertexts ( + "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "ciphertext" TEXT NOT NULL, + "address" TEXT NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + "updated_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + "data_to_encrypt_hash" TEXT NOT NULL, + UNIQUE("address") +); + +CREATE TABLE guardians ( + "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(), + "name" TEXT UNIQUE NOT NULL, + "display_name" TEXT NOT NULL, + "ipfs_cid" TEXT NOT NULL, + "is_active" BOOLEAN NOT NULL DEFAULT TRUE, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now() +); + +CREATE TABLE guardian_to_ciphertext ( + "guardian_id" UUID NOT NULL, + "ciphertext_id" UUID NOT NULL, + "added_at" TIMESTAMPTZ NOT NULL DEFAULT now(), + "guardian_auth_value" TEXT NOT NULL, + PRIMARY KEY ("guardian_id", "ciphertext_id"), + CONSTRAINT fk_guardian_ciphertext FOREIGN KEY ("guardian_id") REFERENCES guardians("id") ON DELETE CASCADE, + CONSTRAINT fk_gc_ciphertext FOREIGN KEY ("ciphertext_id") REFERENCES ciphertexts("id") ON DELETE CASCADE +); + +CREATE INDEX idx_guardians_is_active ON guardians (is_active); +CREATE INDEX idx_guardian_to_ciphertext_ciphertext_id ON guardian_to_ciphertext (ciphertext_id); +CREATE UNIQUE INDEX idx_guardian_to_ciphertext_guardian_auth_value + ON guardian_to_ciphertext (guardian_auth_value); diff --git a/pkg/database/migrations/2026-02-27-120000_drop_guardian_tables/up.sql b/pkg/database/migrations/2026-02-27-120000_drop_guardian_tables/up.sql new file mode 100644 index 0000000..0d3b10c --- /dev/null +++ b/pkg/database/migrations/2026-02-27-120000_drop_guardian_tables/up.sql @@ -0,0 +1,3 @@ +DROP TABLE IF EXISTS guardian_to_ciphertext; +DROP TABLE IF EXISTS guardians; +DROP TABLE IF EXISTS ciphertexts; diff --git a/pkg/database/migrations/2026-03-13-091820-0000_add_ramps_methods_account_id_external_id_idx/down.sql b/pkg/database/migrations/2026-03-13-091820-0000_add_ramps_methods_account_id_external_id_idx/down.sql new file mode 100644 index 0000000..bf9ba6e --- /dev/null +++ b/pkg/database/migrations/2026-03-13-091820-0000_add_ramps_methods_account_id_external_id_idx/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS idx_ramps_methods_account_id_external_id; diff --git a/pkg/database/migrations/2026-03-13-091820-0000_add_ramps_methods_account_id_external_id_idx/up.sql b/pkg/database/migrations/2026-03-13-091820-0000_add_ramps_methods_account_id_external_id_idx/up.sql new file mode 100644 index 0000000..f48604a --- /dev/null +++ b/pkg/database/migrations/2026-03-13-091820-0000_add_ramps_methods_account_id_external_id_idx/up.sql @@ -0,0 +1,2 @@ +CREATE INDEX IF NOT EXISTS idx_ramps_methods_account_id_external_id + ON ramps_methods (account_id, external_id); diff --git a/pkg/database/migrations/2026-03-13-120000_add_ip_data_ip_idx/down.sql b/pkg/database/migrations/2026-03-13-120000_add_ip_data_ip_idx/down.sql new file mode 100644 index 0000000..9f47b99 --- /dev/null +++ b/pkg/database/migrations/2026-03-13-120000_add_ip_data_ip_idx/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS idx_ip_data_ip; diff --git a/pkg/database/migrations/2026-03-13-120000_add_ip_data_ip_idx/up.sql b/pkg/database/migrations/2026-03-13-120000_add_ip_data_ip_idx/up.sql new file mode 100644 index 0000000..5c19935 --- /dev/null +++ b/pkg/database/migrations/2026-03-13-120000_add_ip_data_ip_idx/up.sql @@ -0,0 +1 @@ +CREATE INDEX IF NOT EXISTS idx_ip_data_ip ON ip_data (ip); diff --git a/pkg/database/migrations/2026-03-13-120000_add_rewards_invites_to_wallet_added_at_idx/down.sql b/pkg/database/migrations/2026-03-13-120000_add_rewards_invites_to_wallet_added_at_idx/down.sql new file mode 100644 index 0000000..12fa384 --- /dev/null +++ b/pkg/database/migrations/2026-03-13-120000_add_rewards_invites_to_wallet_added_at_idx/down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS rewards_invites_to_wallet_added_at_idx; diff --git a/pkg/database/migrations/2026-03-13-120000_add_rewards_invites_to_wallet_added_at_idx/up.sql b/pkg/database/migrations/2026-03-13-120000_add_rewards_invites_to_wallet_added_at_idx/up.sql new file mode 100644 index 0000000..01f63c1 --- /dev/null +++ b/pkg/database/migrations/2026-03-13-120000_add_rewards_invites_to_wallet_added_at_idx/up.sql @@ -0,0 +1,3 @@ +CREATE INDEX IF NOT EXISTS rewards_invites_to_wallet_added_at_idx + ON rewards_invites (to_wallet_id, added_at ASC) + INCLUDE (from_wallet_id); diff --git a/pkg/database/migrations/2026-03-13-120001_add_note_kind_to_ramps_transactions/down.sql b/pkg/database/migrations/2026-03-13-120001_add_note_kind_to_ramps_transactions/down.sql new file mode 100644 index 0000000..dbdb4f0 --- /dev/null +++ b/pkg/database/migrations/2026-03-13-120001_add_note_kind_to_ramps_transactions/down.sql @@ -0,0 +1,3 @@ +ALTER TABLE ramps_transactions +DROP COLUMN from_note_kind, +DROP COLUMN to_note_kind; diff --git a/pkg/database/migrations/2026-03-13-120001_add_note_kind_to_ramps_transactions/up.sql b/pkg/database/migrations/2026-03-13-120001_add_note_kind_to_ramps_transactions/up.sql new file mode 100644 index 0000000..7c744f8 --- /dev/null +++ b/pkg/database/migrations/2026-03-13-120001_add_note_kind_to_ramps_transactions/up.sql @@ -0,0 +1,13 @@ +ALTER TABLE ramps_transactions +ADD COLUMN from_note_kind TEXT, +ADD COLUMN to_note_kind TEXT; + +UPDATE ramps_transactions +SET from_note_kind = CASE + WHEN from_network = 'PAYY' THEN '000200000000000000893c499c542cef5e3811e1192ce70d8cc03d5c33590000' + ELSE NULL + END, + to_note_kind = CASE + WHEN to_network = 'PAYY' THEN '000200000000000000893c499c542cef5e3811e1192ce70d8cc03d5c33590000' + ELSE NULL + END; diff --git a/pkg/database/src/lib.rs b/pkg/database/src/lib.rs new file mode 100644 index 0000000..8c3c1a9 --- /dev/null +++ b/pkg/database/src/lib.rs @@ -0,0 +1,4 @@ +//! Diesel schema definitions and migration utilities. + +#[cfg(feature = "diesel")] +pub mod schema; diff --git a/pkg/database/src/schema.rs b/pkg/database/src/schema.rs new file mode 100644 index 0000000..bd3ca79 --- /dev/null +++ b/pkg/database/src/schema.rs @@ -0,0 +1,531 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + blocklist_ip (ip) { + ip -> Text, + data -> Jsonb, + block -> Bool, + request_count -> Int4, + request_count_reset_at -> Timestamptz, + request_count_total -> Int4, + added_at -> Timestamptz, + } +} + +diesel::table! { + blocklist_mobile (mobile) { + mobile -> Text, + reason -> Nullable, + ip -> Nullable, + block -> Bool, + added_at -> Timestamptz, + country_code -> Nullable, + } +} + +diesel::table! { + blocklist_trace (id) { + id -> Uuid, + path -> Text, + mobile -> Text, + ip -> Nullable, + added_at -> Timestamptz, + } +} + +diesel::table! { + diagnostics (id) { + id -> Uuid, + address -> Text, + backup_diffs -> Jsonb, + state -> Jsonb, + mnemonic -> Text, + device_info -> Jsonb, + message -> Nullable, + added_at -> Timestamptz, + wallet_id -> Nullable, + } +} + +diesel::table! { + faucets (id) { + id -> Uuid, + url -> Text, + claimed_by -> Nullable, + claimed_at -> Nullable, + added_at -> Timestamptz, + device_id -> Nullable, + } +} + +diesel::table! { + ip_data (id) { + id -> Uuid, + ip -> Text, + data -> Jsonb, + added_at -> Timestamptz, + } +} + +diesel::table! { + migrate_elements (element) { + element -> Text, + } +} + +diesel::table! { + nfts (id) { + id -> Uuid, + url -> Text, + price -> Int4, + payment_id -> Nullable, + claimed_by -> Nullable, + claimed_at -> Nullable, + added_at -> Timestamptz, + } +} + +diesel::table! { + notes (id) { + id -> Uuid, + address -> Text, + private_key -> Text, + psi -> Text, + value -> Numeric, + owner_id -> Uuid, + status -> Text, + parent_1_id -> Nullable, + received_ref_kind -> Nullable, + received_ref_id -> Nullable, + spent_at -> Nullable, + added_at -> Timestamptz, + updated_at -> Timestamptz, + commitment -> Text, + spend_ref_kind -> Nullable, + spend_ref_id -> Nullable, + parent_2_id -> Nullable, + version -> Int2, + kind -> Text, + } +} + +diesel::table! { + payments (id) { + id -> Uuid, + product -> Text, + provider -> Text, + external_id -> Nullable, + data -> Jsonb, + amount -> Int4, + currency -> Text, + status -> Text, + payment_by -> Nullable, + added_at -> Timestamptz, + } +} + +diesel::table! { + ramps_accounts (id) { + id -> Uuid, + address -> Nullable, + provider -> Text, + external_id -> Nullable, + kyc_status -> Text, + kyc_update_required_fields -> Nullable, + kyc_external_id -> Nullable, + country -> Nullable, + deposit_evm_address -> Nullable, + withdraw_evm_address -> Nullable, + metadata -> Nullable, + added_at -> Timestamptz, + updated_at -> Timestamptz, + kyc_delegated_id -> Nullable, + kyc_non_delegated_status -> Nullable, + wallet_id -> Uuid, + } +} + +diesel::table! { + ramps_events (id) { + id -> Uuid, + provider -> Text, + data -> Jsonb, + source -> Text, + added_at -> Timestamptz, + path -> Nullable, + transaction_id -> Nullable, + account_id -> Nullable, + success -> Nullable, + } +} + +diesel::table! { + ramps_methods (id) { + id -> Uuid, + account_id -> Uuid, + external_id -> Nullable, + local_id -> Text, + network -> Text, + network_identifier -> Jsonb, + preview -> Nullable, + metadata -> Nullable, + is_default -> Bool, + added_at -> Timestamptz, + frozen -> Bool, + deleted_at -> Nullable, + } +} + +diesel::table! { + ramps_quotes (id) { + id -> Uuid, + provider -> Text, + account_id -> Uuid, + external_id -> Text, + from_currency -> Text, + from_amount -> Numeric, + from_network -> Text, + to_currency -> Text, + to_amount -> Numeric, + to_network -> Text, + metadata -> Nullable, + expires_at -> Timestamptz, + added_at -> Timestamptz, + } +} + +diesel::table! { + ramps_transactions (id) { + id -> Uuid, + address -> Nullable, + provider -> Text, + account_id -> Uuid, + external_id -> Nullable, + external_fund_id -> Nullable, + local_id -> Nullable, + quote_id -> Nullable, + status -> Text, + from_currency -> Text, + from_amount -> Numeric, + from_network -> Text, + from_network_identifier -> Nullable, + to_currency -> Text, + to_amount -> Numeric, + to_network -> Text, + to_network_identifier -> Nullable, + evm_address -> Nullable, + name -> Nullable, + memo -> Nullable, + desc -> Nullable, + emoji -> Nullable, + category -> Text, + metadata -> Nullable, + transaction_at -> Nullable, + added_at -> Timestamptz, + updated_at -> Timestamptz, + icon -> Nullable, + pending_refund_amount -> Nullable, + funding_status -> Nullable, + funding_due_amount -> Nullable, + wallet_id -> Uuid, + status_reason -> Nullable, + private_key -> Nullable, + funding_kind -> Text, + from_note_kind -> Nullable, + to_note_kind -> Nullable, + } +} + +diesel::table! { + registry_notes (id) { + id -> Uuid, + block -> Int8, + public_key -> Text, + encrypted_key -> Bytea, + encrypted_note -> Bytea, + added_at -> Timestamptz, + } +} + +diesel::table! { + rewards (wallet_id) { + address -> Nullable, + code -> Text, + points -> Int4, + invites -> Int4, + claims -> Jsonb, + prize -> Nullable, + added_at -> Timestamptz, + updated_at -> Timestamptz, + wallet_id -> Uuid, + } +} + +diesel::table! { + rewards_invites (from_wallet_id, to_wallet_id) { + from_address -> Nullable, + to_address -> Nullable, + added_at -> Timestamptz, + from_wallet_id -> Uuid, + to_wallet_id -> Uuid, + } +} + +diesel::table! { + rewards_points (id) { + id -> Uuid, + address -> Nullable, + reason -> Text, + points -> Int4, + added_at -> Timestamptz, + wallet_id -> Uuid, + } +} + +diesel::table! { + support_canned_response_tags (support_canned_response_id, support_tag_id) { + support_canned_response_id -> Uuid, + support_tag_id -> Uuid, + added_at -> Timestamptz, + } +} + +diesel::table! { + support_canned_responses (id) { + id -> Uuid, + name -> Text, + display_name -> Text, + content -> Text, + is_active -> Bool, + added_at -> Timestamptz, + updated_at -> Timestamptz, + } +} + +diesel::table! { + support_issue_tags (support_issue_id, support_tag_id) { + support_issue_id -> Uuid, + support_tag_id -> Uuid, + added_at -> Timestamptz, + } +} + +diesel::table! { + support_issues (id) { + id -> Uuid, + wallet_id -> Uuid, + external_id -> Uuid, + status -> Text, + channel -> Text, + subject -> Nullable, + unread_count -> Int4, + last_message -> Text, + last_message_at -> Timestamptz, + last_read_at -> Nullable, + closed_at -> Nullable, + updated_at -> Timestamptz, + added_at -> Timestamptz, + metadata -> Nullable, + auto_close_at -> Nullable, + auto_close_minutes -> Nullable, + last_ai_support_bot_processed_at -> Nullable, + } +} + +diesel::table! { + support_messages (id) { + id -> Uuid, + support_issue_id -> Uuid, + external_id -> Text, + emoji -> Nullable, + role -> Text, + message -> Text, + attachment -> Nullable, + added_at -> Timestamptz, + is_bot -> Bool, + is_internal -> Bool, + agent_id -> Nullable, + } +} + +diesel::table! { + support_tags (id) { + id -> Uuid, + name -> Text, + display_name -> Text, + color -> Text, + is_active -> Bool, + added_at -> Timestamptz, + auto_close_minutes -> Nullable, + } +} + +diesel::table! { + token_price_history (id) { + id -> Uuid, + #[max_length = 20] + symbol -> Nullable, + #[max_length = 50] + network -> Varchar, + contract_address -> Nullable, + price -> Numeric, + currency -> Text, + last_updated_at -> Timestamptz, + fetched_at -> Timestamptz, + metadata -> Nullable, + } +} + +diesel::table! { + token_prices (id) { + id -> Uuid, + #[max_length = 20] + symbol -> Nullable, + #[max_length = 50] + network -> Varchar, + contract_address -> Nullable, + price -> Numeric, + currency -> Text, + last_updated_at -> Timestamptz, + fetched_at -> Timestamptz, + metadata -> Nullable, + } +} + +diesel::table! { + udh_referral_links (posthog_id) { + posthog_id -> Text, + user_device_hash -> Text, + referrer_url -> Text, + claimed_at -> Nullable, + wallet_id -> Nullable, + added_at -> Timestamptz, + updated_at -> Timestamptz, + } +} + +diesel::table! { + wallet_activity (id) { + id -> Uuid, + address -> Text, + kind -> Text, + data -> Bytea, + active -> Bool, + completed_at -> Nullable, + updated_at -> Timestamptz, + added_at -> Timestamptz, + } +} + +diesel::table! { + wallet_auths (id) { + id -> Uuid, + wallet_id -> Uuid, + kind -> Text, + value -> Text, + enabled -> Bool, + added_at -> Timestamptz, + updated_at -> Timestamptz, + } +} + +diesel::table! { + wallet_backup_tags (wallet_address, tag) { + wallet_address -> Text, + tag -> Text, + last_update -> Text, + } +} + +diesel::table! { + wallet_backups (wallet_address, last_update) { + wallet_address -> Text, + last_update -> Text, + backup_path -> Text, + backup_hash -> Bytea, + added_at -> Timestamptz, + diff_of -> Nullable, + } +} + +diesel::table! { + wallet_notes (commitment) { + commitment -> Text, + address -> Text, + data -> Bytea, + status -> Text, + activity_id -> Nullable, + updated_at -> Timestamptz, + added_at -> Timestamptz, + } +} + +diesel::table! { + wallets (id) { + id -> Uuid, + address -> Text, + expo_push_token -> Nullable, + deposit_address -> Nullable, + added_at -> Timestamptz, + updated_at -> Timestamptz, + atlas_customer_id -> Nullable, + kyc -> Nullable, + country -> Nullable, + language -> Nullable, + ip_country -> Nullable, + data -> Nullable, + version -> Int2, + fraud_block -> Bool, + } +} + +diesel::table! { + wallets_addresses (address) { + address -> Text, + wallet_id -> Uuid, + } +} + +diesel::joinable!(support_canned_response_tags -> support_canned_responses (support_canned_response_id)); +diesel::joinable!(support_canned_response_tags -> support_tags (support_tag_id)); +diesel::joinable!(support_issue_tags -> support_issues (support_issue_id)); +diesel::joinable!(support_issue_tags -> support_tags (support_tag_id)); +diesel::joinable!(wallet_auths -> wallets (wallet_id)); + +diesel::allow_tables_to_appear_in_same_query!( + blocklist_ip, + blocklist_mobile, + blocklist_trace, + diagnostics, + faucets, + ip_data, + migrate_elements, + nfts, + notes, + payments, + ramps_accounts, + ramps_events, + ramps_methods, + ramps_quotes, + ramps_transactions, + registry_notes, + rewards, + rewards_invites, + rewards_points, + support_canned_response_tags, + support_canned_responses, + support_issue_tags, + support_issues, + support_messages, + support_tags, + token_price_history, + token_prices, + udh_referral_links, + wallet_activity, + wallet_auths, + wallet_backup_tags, + wallet_backups, + wallet_notes, + wallets, + wallets_addresses, +); diff --git a/pkg/database/tests/replit_permissions/mod.rs b/pkg/database/tests/replit_permissions/mod.rs new file mode 100644 index 0000000..1bda1db --- /dev/null +++ b/pkg/database/tests/replit_permissions/mod.rs @@ -0,0 +1,108 @@ +mod postgres_fixture; +mod schema; + +use serial_test::serial; +use tokio_postgres::error::SqlState; +use uuid::Uuid; + +use postgres_fixture::{docker_available, DockerPostgres, FixtureError}; +use schema::setup_schema; + +type TestResult = std::result::Result; + +#[tokio::test(flavor = "multi_thread")] +#[serial] +async fn replit_column_permissions_enforced() -> TestResult<()> { + if !docker_available() { + eprintln!( + "skipping replit_column_permissions_enforced: docker binary not available on PATH" + ); + return Ok(()); + } + + let fixture = match DockerPostgres::start().await { + Ok(fixture) => fixture, + Err(err) => { + if err.is_missing_docker() { + eprintln!( + "skipping replit_column_permissions_enforced: docker binary not available ({err})" + ); + return Ok(()); + } + + return Err(err); + } + }; + let db_name = format!("replit_perm_{}", Uuid::new_v4().simple()); + fixture.recreate_database(&db_name).await?; + setup_schema(&fixture, &db_name).await?; + + let replit_client = fixture.connect(&db_name, "replit", "replit").await?; + let rows = replit_client + .query("SELECT private_key FROM notes", &[]) + .await?; + assert_eq!(rows.len(), 1); + + let rows = replit_client + .query("SELECT private_key FROM ramps_transactions", &[]) + .await?; + assert_eq!(rows.len(), 1); + + drop(replit_client); + + fixture + .apply_sql( + &db_name, + include_str!( + "../../migrations/2025-09-30-155759_restrict_replit_sensitive_columns/up.sql" + ), + ) + .await?; + + let replit_client = fixture.connect(&db_name, "replit", "replit").await?; + + let err = replit_client + .query("SELECT private_key FROM notes", &[]) + .await + .expect_err("replit should not read notes.private_key after migration"); + assert_eq!(err.code(), Some(&SqlState::INSUFFICIENT_PRIVILEGE)); + + let rows = replit_client + .query("SELECT private_key FROM ramps_transactions", &[]) + .await?; + assert_eq!(rows.len(), 1); + + let rows = replit_client + .query("SELECT id, value FROM notes", &[]) + .await?; + assert_eq!(rows.len(), 1); + + let rows = replit_client + .query("SELECT id, status FROM ramps_transactions", &[]) + .await?; + assert_eq!(rows.len(), 1); + + drop(replit_client); + + fixture + .apply_sql( + &db_name, + include_str!( + "../../migrations/2025-09-30-155759_restrict_replit_sensitive_columns/down.sql" + ), + ) + .await?; + + let replit_client = fixture.connect(&db_name, "replit", "replit").await?; + let rows = replit_client + .query("SELECT private_key FROM notes", &[]) + .await?; + assert_eq!(rows.len(), 1); + + let rows = replit_client + .query("SELECT private_key FROM ramps_transactions", &[]) + .await?; + assert_eq!(rows.len(), 1); + + Ok(()) +} diff --git a/pkg/database/tests/replit_permissions/postgres_fixture/docker.rs b/pkg/database/tests/replit_permissions/postgres_fixture/docker.rs new file mode 100644 index 0000000..e6aca7e --- /dev/null +++ b/pkg/database/tests/replit_permissions/postgres_fixture/docker.rs @@ -0,0 +1,197 @@ +use std::{io, num::ParseIntError, process::Command, string::FromUtf8Error}; + +use contextful::{Contextful, ResultContextExt}; +use thiserror::Error; +use tokio::time::{sleep, Duration}; +use tokio_postgres::{Client, NoTls}; +use uuid::Uuid; + +use super::util::last_non_empty_trimmed_line; + +#[derive(Debug, Error)] +pub enum FixtureError { + #[error("[replit-permissions-test] io error")] + Io(#[from] Contextful), + #[error("[replit-permissions-test] utf8 error")] + Utf8(#[from] Contextful), + #[error("[replit-permissions-test] postgres error")] + Postgres(#[from] Contextful), + #[error("[replit-permissions-test] parse int error")] + ParseInt(#[from] Contextful), + #[error("[replit-permissions-test] docker command failed for {command}: {stderr}")] + CommandFailure { command: &'static str, stderr: String }, + #[error("[replit-permissions-test] docker port output missing mapping: {output}")] + UnexpectedDockerPortOutput { output: String }, + #[error("[replit-permissions-test] docker run output missing container id: {output}")] + MissingDockerRunContainerId { output: String }, + #[error("[replit-permissions-test] postgres did not become ready in time")] + NotReady, +} + +impl FixtureError { + pub fn is_missing_docker(&self) -> bool { + matches!(self, FixtureError::Io(err) if err.source_ref().kind() == io::ErrorKind::NotFound) + } +} + +pub type Result = std::result::Result; + +/// Minimal Postgres container wrapper tailored for the replit permissions test. +pub struct DockerPostgres { + container_id: String, + port: u16, +} + +impl DockerPostgres { + pub async fn start() -> Result { + let name = format!("replit-perm-{}", Uuid::new_v4().simple()); + let run_output = Command::new("docker") + .args([ + "run", + "-d", + "--rm", + "--name", + name.as_str(), + "-e", + "POSTGRES_PASSWORD=postgres", + "-e", + "POSTGRES_USER=postgres", + "-e", + "POSTGRES_DB=postgres", + "-P", + "postgres:18", + ]) + .output() + .context("launch postgres container for replit permissions test")?; + if !run_output.status.success() { + return Err(FixtureError::CommandFailure { + command: "docker run", + stderr: String::from_utf8_lossy(&run_output.stderr).into_owned(), + }); + } + + let run_stdout = String::from_utf8(run_output.stdout) + .context("decode docker container id for replit permissions test")?; + let container_id = last_non_empty_trimmed_line(&run_stdout) + .ok_or_else(|| FixtureError::MissingDockerRunContainerId { + output: run_stdout.clone(), + })? + .to_owned(); + let port_output = Command::new("docker") + .args(["port", container_id.as_str(), "5432/tcp"]) + .output() + .context("fetch mapped postgres port for replit permissions test")?; + if !port_output.status.success() { + return Err(FixtureError::CommandFailure { + command: "docker port", + stderr: String::from_utf8_lossy(&port_output.stderr).into_owned(), + }); + } + + let port_lines = String::from_utf8(port_output.stdout) + .context("decode docker port output for replit permissions test")?; + let host_port = parse_mapped_port(&port_lines)?; + let instance = Self { container_id, port: host_port }; + instance.wait_for_ready().await?; + Ok(instance) + } + + async fn wait_for_ready(&self) -> Result<()> { + for _ in 0..30 { + if let Ok((client, connection)) = tokio_postgres::connect( + &format!( + "host=127.0.0.1 port={} user=postgres password=postgres dbname=postgres", + self.port + ), + NoTls, + ) + .await + { + tokio::spawn(async move { + if let Err(err) = connection.await { + eprintln!("postgres connection error: {err}"); + } + }); + + if client.simple_query("SELECT 1").await.is_ok() { + return Ok(()); + } + } + + sleep(Duration::from_secs(1)).await; + } + + Err(FixtureError::NotReady) + } + + pub async fn connect(&self, db: &str, user: &str, password: &str) -> Result { + let (client, connection) = tokio_postgres::connect( + &format!( + "host=127.0.0.1 port={} user={} password={} dbname={}", + self.port, user, password, db + ), + NoTls, + ) + .await + .context("connect to postgres container for replit permissions test")?; + tokio::spawn(async move { + if let Err(err) = connection.await { + eprintln!("postgres connection error: {err}"); + } + }); + Ok(client) + } + + pub async fn connect_superuser(&self, db: &str) -> Result { + self.connect(db, "postgres", "postgres").await + } + + pub async fn recreate_database(&self, name: &str) -> Result<()> { + let superuser = self + .connect_superuser("postgres") + .await + .context("connect as postgres superuser to recreate database")?; + superuser + .simple_query(&format!("DROP DATABASE IF EXISTS {name}")) + .await + .context("drop existing replit permissions database")?; + superuser + .simple_query(&format!("CREATE DATABASE {name}")) + .await + .context("create fresh replit permissions database")?; + Ok(()) + } + + pub async fn apply_sql(&self, db: &str, sql: &str) -> Result<()> { + let superuser = self + .connect_superuser(db) + .await + .context("connect as postgres superuser to apply sql")?; + superuser + .batch_execute(sql) + .await + .context("apply SQL snippet for replit permissions test")?; + Ok(()) + } +} + +impl Drop for DockerPostgres { + fn drop(&mut self) { + let _ = Command::new("docker") + .args(["rm", "-f", self.container_id.as_str()]) + .status(); + } +} + +fn parse_mapped_port(output: &str) -> Result { + let mapping = output + .lines() + .next() + .and_then(|line| line.split(':').nth(1)) + .ok_or_else(|| FixtureError::UnexpectedDockerPortOutput { + output: output.to_string(), + })?; + Ok(mapping + .parse::() + .context("parse docker mapped postgres port value")?) +} diff --git a/pkg/database/tests/replit_permissions/postgres_fixture/mod.rs b/pkg/database/tests/replit_permissions/postgres_fixture/mod.rs new file mode 100644 index 0000000..5998411 --- /dev/null +++ b/pkg/database/tests/replit_permissions/postgres_fixture/mod.rs @@ -0,0 +1,5 @@ +mod docker; +mod util; + +pub use docker::{DockerPostgres, FixtureError, Result}; +pub use util::docker_available; diff --git a/pkg/database/tests/replit_permissions/postgres_fixture/util.rs b/pkg/database/tests/replit_permissions/postgres_fixture/util.rs new file mode 100644 index 0000000..28a5449 --- /dev/null +++ b/pkg/database/tests/replit_permissions/postgres_fixture/util.rs @@ -0,0 +1,24 @@ +use std::process::{Command, Stdio}; + +pub fn docker_available() -> bool { + Command::new("docker") + .arg("--version") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .map_or(false, |status| status.success()) +} + +pub fn last_non_empty_trimmed_line(output: &str) -> Option<&str> { + output + .lines() + .rev() + .find_map(|line| { + let trimmed = line.trim(); + if trimmed.is_empty() { + None + } else { + Some(trimmed) + } + }) +} diff --git a/pkg/database/tests/replit_permissions/schema.rs b/pkg/database/tests/replit_permissions/schema.rs new file mode 100644 index 0000000..ff5c8f8 --- /dev/null +++ b/pkg/database/tests/replit_permissions/schema.rs @@ -0,0 +1,92 @@ +use contextful::ResultContextExt; +use tokio_postgres::Client; +use uuid::Uuid; + +use crate::postgres_fixture::{DockerPostgres, FixtureError}; + +type Result = std::result::Result; + +const CREATE_TABLES_SQL: &str = include_str!("sql/create_tables.sql"); + +pub async fn setup_schema(fixture: &DockerPostgres, db: &str) -> Result<()> { + let client = fixture + .connect_superuser(db) + .await + .context("connect as superuser to set up schema")?; + + client + .batch_execute(CREATE_TABLES_SQL) + .await + .context("apply initial tables for replit permissions test")?; + + seed_data(&client).await?; + ensure_replit_role(&client, db).await?; + + Ok(()) +} + +async fn seed_data(client: &Client) -> Result<()> { + let note_id = Uuid::new_v4(); + let txn_id = Uuid::new_v4(); + let owner_id = Uuid::new_v4(); + let account_id = Uuid::new_v4(); + let wallet_id = Uuid::new_v4(); + let address_value = "A".repeat(64); + let note_private_key = "B".repeat(64); + let note_psi = "C".repeat(64); + let commitment = "D".repeat(64); + + client + .execute( + "INSERT INTO notes (id, address, private_key, psi, value, owner_id, status, commitment) + VALUES ($1, $2, $3, $4, 42, $5, 'UNSPENT', $6)", + &[ + ¬e_id, + &address_value, + ¬e_private_key, + ¬e_psi, + &owner_id, + &commitment, + ], + ) + .await + .context("seed initial test note for replit permissions test")?; + + client + .execute( + "INSERT INTO ramps_transactions ( + id, provider, account_id, status, from_currency, from_amount, from_network, + to_currency, to_amount, to_network, category, added_at, updated_at, + wallet_id, private_key, funding_kind, from_note_kind, to_note_kind + ) VALUES ( + $1, 'MOCK', $2, 'PENDING', 'USD', 100, 'ACH', 'USDC', 100, 'ETH', 'PAYIN', NOW(), NOW(), + $3, 'rampsprivkey', 'CRYPTO', NULL, NULL + )", + &[&txn_id, &account_id, &wallet_id], + ) + .await + .context("seed initial ramps transaction for replit permissions test")?; + + Ok(()) +} + +async fn ensure_replit_role(client: &Client, db: &str) -> Result<()> { + client + .batch_execute(&format!( + "DO $$BEGIN + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'replit') THEN + CREATE ROLE replit LOGIN PASSWORD 'replit'; + ELSE + ALTER ROLE replit WITH LOGIN PASSWORD 'replit'; + END IF; + END$$; + GRANT CONNECT ON DATABASE {db} TO replit; + GRANT USAGE ON SCHEMA public TO replit; + GRANT SELECT ON TABLE notes TO replit; + GRANT SELECT ON TABLE ramps_transactions TO replit;" + )) + .await + .context("ensure replit role has baseline privileges")?; + + Ok(()) +} diff --git a/pkg/database/tests/replit_permissions/sql/create_tables.sql b/pkg/database/tests/replit_permissions/sql/create_tables.sql new file mode 100644 index 0000000..2248668 --- /dev/null +++ b/pkg/database/tests/replit_permissions/sql/create_tables.sql @@ -0,0 +1,61 @@ +CREATE TABLE notes ( + id UUID PRIMARY KEY, + address BPCHAR(64) NOT NULL, + private_key BPCHAR(64) NOT NULL, + psi BPCHAR(64) NOT NULL, + value NUMERIC NOT NULL, + owner_id UUID NOT NULL, + status TEXT NOT NULL, + parent_1_id UUID, + received_ref_kind TEXT, + received_ref_id TEXT, + spent_at TIMESTAMPTZ, + added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + commitment BPCHAR(64) NOT NULL, + spend_ref_kind TEXT, + spend_ref_id TEXT, + parent_2_id UUID, + version SMALLINT NOT NULL DEFAULT 0, + kind BPCHAR(64) NOT NULL DEFAULT '0000000000000000000000000000000000000000000000000000000000000001' +); + +CREATE TABLE ramps_transactions ( + id UUID PRIMARY KEY, + address BPCHAR(64), + provider TEXT NOT NULL, + account_id UUID NOT NULL, + external_id TEXT, + external_fund_id TEXT, + quote_id UUID, + status TEXT NOT NULL, + from_currency TEXT NOT NULL, + from_amount NUMERIC NOT NULL, + from_network TEXT NOT NULL, + from_network_identifier JSONB, + to_currency TEXT NOT NULL, + to_amount NUMERIC NOT NULL, + to_network TEXT NOT NULL, + to_network_identifier JSONB, + evm_address TEXT, + name TEXT, + memo TEXT, + "desc" TEXT, + emoji TEXT, + category TEXT NOT NULL, + metadata JSONB, + transaction_at TIMESTAMPTZ, + added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + icon TEXT, + pending_refund_amount NUMERIC, + funding_status TEXT, + funding_due_amount NUMERIC, + wallet_id UUID NOT NULL, + status_reason TEXT, + private_key TEXT, + local_id TEXT, + funding_kind TEXT NOT NULL, + from_note_kind TEXT, + to_note_kind TEXT +); diff --git a/pkg/diesel-util/Cargo.toml b/pkg/diesel-util/Cargo.toml new file mode 100644 index 0000000..e7aac15 --- /dev/null +++ b/pkg/diesel-util/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "diesel-util" +version = "0.1.0" +edition = "2024" + +[features] +diesel = ["dep:diesel"] + +[dependencies] +diesel = { workspace = true, optional = true } +workspace-hack.workspace = true diff --git a/pkg/diesel-util/README.md b/pkg/diesel-util/README.md new file mode 100644 index 0000000..f04b805 --- /dev/null +++ b/pkg/diesel-util/README.md @@ -0,0 +1,36 @@ +# diesel-util + +Shared Diesel utilities for Polybase services. + +## Overview + +This crate hosts helper macros and traits that smooth over Diesel integration +across multiple crates. It currently provides the `derive_pg_text_enum!` macro, +which implements `ToSql`/`FromSql` for enums stored as `TEXT` columns in +PostgreSQL. The macro is gated behind the `diesel` feature so crates can depend +on these helpers without pulling in Diesel unless they need it. + +## Features + +- `diesel`: Enables the Diesel dependency and exports the + `derive_pg_text_enum!` macro. + +## Usage + +```rust +use diesel_util::derive_pg_text_enum; + +#[derive(Debug, Clone)] +#[cfg_attr( + feature = "diesel", + derive(diesel::AsExpression, diesel::FromSqlRow) +)] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +pub enum Status { + Pending, + Completed, +} + +#[cfg(feature = "diesel")] +derive_pg_text_enum!(Status); +``` diff --git a/pkg/diesel-util/src/lib.rs b/pkg/diesel-util/src/lib.rs new file mode 100644 index 0000000..245d507 --- /dev/null +++ b/pkg/diesel-util/src/lib.rs @@ -0,0 +1,30 @@ +#![warn(clippy::pedantic)] +#![allow(missing_docs)] + +#[cfg(feature = "diesel")] +#[macro_export] +macro_rules! derive_pg_text_enum { + ($enum_name:ident, $case_style:expr) => { + impl diesel::serialize::ToSql for $enum_name { + fn to_sql( + &self, + out: &mut diesel::serialize::Output, + ) -> diesel::serialize::Result { + use std::io::Write; + write!(out, "{self}")?; + Ok(diesel::serialize::IsNull::No) + } + } + + impl diesel::deserialize::FromSql for $enum_name { + fn from_sql(bytes: diesel::pg::PgValue) -> diesel::deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized value".into()) + } + } + }; + + ($enum_name:ident) => { + $crate::derive_pg_text_enum!($enum_name, "SCREAMING_SNAKE_CASE") + }; +} diff --git a/pkg/doomslug/Cargo.toml b/pkg/doomslug/Cargo.toml index f3aa9df..75d4173 100644 --- a/pkg/doomslug/Cargo.toml +++ b/pkg/doomslug/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "doomslug" version = "1.3.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -10,12 +10,8 @@ primitives = { workspace = true } tracing = { workspace = true } chrono = { workspace = true } -once_cell = { workspace = true } borsh = { workspace = true } serde = { workspace = true } thiserror = { workspace = true } -rand = { workspace = true } -hex = { workspace = true } -sha2 = { workspace = true } sha3 = { workspace = true } -uint = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/doomslug/README.md b/pkg/doomslug/README.md new file mode 100644 index 0000000..58b930c --- /dev/null +++ b/pkg/doomslug/README.md @@ -0,0 +1,15 @@ +# Doomslug + +DoomSlug consensus mechanism with approval and error handling. + +## Overview + +Implementation of the DoomSlug consensus algorithm, providing fast finality and Byzantine fault tolerance. + +## Features + +- DoomSlug consensus protocol +- Block approval mechanisms +- Error handling and recovery +- Consensus state management + diff --git a/pkg/doomslug/src/approval.rs b/pkg/doomslug/src/approval.rs index abf1dfd..4fc8c36 100644 --- a/pkg/doomslug/src/approval.rs +++ b/pkg/doomslug/src/approval.rs @@ -117,8 +117,7 @@ impl ApprovalContent { fn hash(&self) -> CryptoHash { let mut hasher = Keccak256::new(); - let mut height_bytes = [0u8; 32]; - U256::from(self.target_height).to_big_endian(&mut height_bytes); + let height_bytes = U256::from(self.target_height).to_big_endian(); hasher.update(height_bytes); hasher.update(match &self.inner { ApprovalInner::Endorsement(h) => h.inner(), diff --git a/pkg/doomslug/src/doomslug.rs b/pkg/doomslug/src/doomslug.rs index 154314f..f261091 100644 --- a/pkg/doomslug/src/doomslug.rs +++ b/pkg/doomslug/src/doomslug.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=800 use std::collections::{HashMap, VecDeque}; use std::time::{Duration, Instant}; @@ -267,8 +268,7 @@ impl DoomslugApprovalsTrackersAtHeight { /// * `now` - the current timestamp /// * `approval` - the approval to be processed /// * `stakes` - all the stakes of all the block producers in the current epoch - /// * `threshold_mode` - how many approvals are needed to produce a block. Is used to compute - /// the return value + /// * `threshold_mode` - how many approvals are needed to produce a block. Is used to compute the return value /// /// # Returns /// Same as `DoomslugApprovalsTracker::process_approval` @@ -387,10 +387,10 @@ impl Doomslug { } } - #[cfg(feature = "test_features")] - pub fn adv_disable(&mut self) { - self.threshold_mode = DoomslugThresholdMode::NoApprovals - } + // #[cfg(feature = "test_features")] + // pub fn adv_disable(&mut self) { + // self.threshold_mode = DoomslugThresholdMode::NoApprovals + // } /// Returns the `(hash, height)` of the current tip. Currently is only used by tests. pub fn get_tip(&self) -> (CryptoHash, BlockHeight) { @@ -692,14 +692,13 @@ impl Doomslug { /// enough chunks, or /// - The block has 1/2 of approvals, and T(h' / 6) has passed since the block has had 1/2 of /// approvals for the first time, where h' is time since the last ds-final block. - /// Only the height is passed into the function, we use the tip known to `Doomslug` as the - /// parent hash. + /// Only the height is passed into the function, we use the tip known to `Doomslug` as the + /// parent hash. /// /// # Arguments: /// * `now` - current timestamp /// * `target_height` - the height for which the readiness is checked - /// * `has_enough_chunks` - if not, we will wait for T(h' / 6) even if we have 2/3 approvals & - /// have the previous block ds-final. + /// * `has_enough_chunks` - if not, we will wait for T(h' / 6) even if we have 2/3 approvals & have the previous block ds-final. #[must_use] pub fn ready_to_produce_block( &mut self, diff --git a/pkg/doomslug/src/types.rs b/pkg/doomslug/src/types.rs index 8aee086..adab000 100644 --- a/pkg/doomslug/src/types.rs +++ b/pkg/doomslug/src/types.rs @@ -2,7 +2,6 @@ use borsh::{BorshDeserialize, BorshSerialize}; /// Height of the block. pub type BlockHeight = u64; -/// Block hash. /// Block height delta that measures the difference between `BlockHeight`s. pub type BlockHeightDelta = u64; @@ -11,5 +10,9 @@ pub type BlockHeightDelta = u64; pub type Balance = u128; /// Validator is a public key or identifier of the validator. +#[expect( + dead_code, + reason = "Validator type reserved for future doomslug networking APIs" +)] #[derive(Clone, Debug, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize, serde::Serialize)] pub struct Validator(pub [u8; 32]); diff --git a/pkg/eip7702/Cargo.toml b/pkg/eip7702/Cargo.toml new file mode 100644 index 0000000..277a2b6 --- /dev/null +++ b/pkg/eip7702/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "eip7702" +version = "0.1.0" +edition = "2024" + +[dependencies] +ethereum-types = { workspace = true } +contextful = { workspace = true } +thiserror = { workspace = true } +secp256k1 = { workspace = true } +sha3 = { workspace = true } +web3 = { workspace = true } +rlp = { workspace = true } +reqwest = { workspace = true } +async-trait = { workspace = true } +serde_json = { workspace = true } +eth-util = { workspace = true } +tokio = { workspace = true } +hex = { workspace = true } +test-spy = { workspace = true } +tracing = { workspace = true } +client-http = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +testutil = { workspace = true } diff --git a/pkg/eip7702/src/auth.rs b/pkg/eip7702/src/auth.rs new file mode 100644 index 0000000..c429666 --- /dev/null +++ b/pkg/eip7702/src/auth.rs @@ -0,0 +1,113 @@ +use crate::types::Authorization; +use ethereum_types::{Address, H256, U256}; +use rlp::RlpStream; +use secp256k1::{ + Message, PublicKey, Secp256k1, SecretKey, ecdsa::RecoverableSignature, ecdsa::RecoveryId, +}; +use sha3::{Digest, Keccak256}; + +fn u256_be_trim(v: &U256) -> Vec { + if v.is_zero() { + return Vec::new(); + } + let mut buf = [0u8; 32]; + v.to_big_endian(&mut buf); + let first = buf.iter().position(|&b| b != 0).unwrap_or(31); + buf[first..].to_vec() +} + +/// keccak256( 0x05 || rlp([chain_id, delegate, nonce]) ) +pub fn auth_message_hash(chain_id: U256, delegate: Address, nonce: U256) -> H256 { + let mut s = RlpStream::new_list(3); + + s.append(&u256_be_trim(&chain_id)); + s.append(&delegate.as_bytes()); + s.append(&u256_be_trim(&nonce)); + + let out = s.out(); + + let mut pre = Vec::with_capacity(1 + out.len()); + pre.push(0x05); + pre.extend_from_slice(&out); + + H256::from_slice(Keccak256::digest(&pre).as_slice()) +} + +/// Sign authorization tuple with EOA secret key. +pub fn sign_authorization( + sk: &SecretKey, + chain_id: U256, + delegate: Address, + nonce: U256, +) -> Authorization { + let digest = auth_message_hash(chain_id, delegate, nonce); + let secp = Secp256k1::new(); + + let sig: RecoverableSignature = + secp.sign_ecdsa_recoverable(&Message::from_digest_slice(digest.as_bytes()).unwrap(), sk); + + let (rid, b) = sig.serialize_compact(); + + Authorization { + chain_id, + delegate, + nonce, + y_parity: (rid.to_i32() as u8) & 1, + r: H256::from_slice(&b[0..32]), + s: H256::from_slice(&b[32..64]), + } +} + +/// Recover the EOA address that produced the Authorization signature. +pub fn recover_authority(auth: &Authorization) -> Address { + let digest = auth_message_hash(auth.chain_id, auth.delegate, auth.nonce); + + let mut sig_bytes = [0u8; 64]; + sig_bytes[..32].copy_from_slice(auth.r.as_bytes()); + sig_bytes[32..].copy_from_slice(auth.s.as_bytes()); + + let rid = RecoveryId::from_i32((auth.y_parity & 1) as i32).expect("valid y_parity"); + let rec_sig = RecoverableSignature::from_compact(&sig_bytes, rid).expect("valid sig"); + + let pk = Secp256k1::new() + .recover_ecdsa( + &Message::from_digest_slice(digest.as_bytes()).unwrap(), + &rec_sig, + ) + .expect("recover public key"); + + public_key_to_address(&pk) +} + +fn public_key_to_address(pk: &PublicKey) -> Address { + let uncompressed = pk.serialize_uncompressed(); + let hash = Keccak256::digest(&uncompressed[1..]); + + let mut addr = [0u8; 20]; + addr.copy_from_slice(&hash[12..]); + + Address::from(addr) +} + +#[cfg(test)] +mod tests { + use super::*; + use secp256k1::SecretKey; + + #[test] + fn sign_and_recover_matches() { + // Deterministic secret key + let sk = SecretKey::from_slice(&[1u8; 32]).unwrap(); + // Random-ish values + let chain_id = U256::from(1u64); + let delegate = Address::from_low_u64_be(2); + let nonce = U256::from(3u64); + let auth = sign_authorization(&sk, chain_id, delegate, nonce); + let recovered = recover_authority(&auth); + // Derive expected address from the secret key's public key + let secp = Secp256k1::new(); + let pk = secp256k1::PublicKey::from_secret_key(&secp, &sk); + let expected = public_key_to_address(&pk); + assert_eq!(recovered, expected); + } +} diff --git a/pkg/eip7702/src/eip712.rs b/pkg/eip7702/src/eip712.rs new file mode 100644 index 0000000..67240ea --- /dev/null +++ b/pkg/eip7702/src/eip712.rs @@ -0,0 +1,160 @@ +use crate::types::MetaCall; +use ethereum_types::{Address, H256, U256}; +use sha3::{Digest, Keccak256}; +use web3::ethabi::{self, Token}; + +const EIP712DOMAIN_TYPEHASH: &str = + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"; +const CALL_TYPEHASH: &str = "Call(address target,uint256 value,bytes data)"; +// ExecuteMany uses pre-hashed calls as bytes32[], includes validity window +const EXECUTE_MANY_TYPEHASH: &str = + "ExecuteMany(bytes32[] calls,uint256 nonce,uint256 validAfter,uint256 validUntil)"; +const NAME: &str = "Eip7702SimpleAccount"; +const VERSION: &str = "1"; + +fn keccak(bytes: impl AsRef<[u8]>) -> H256 { + H256::from_slice(Keccak256::digest(bytes).as_slice()) +} + +/// EIP-712 domain separator for the SimpleAccount binding. +pub fn eip712_domain_separator(chain_id: U256, user: Address) -> H256 { + keccak(ethabi::encode(&[ + Token::FixedBytes(keccak(EIP712DOMAIN_TYPEHASH).0.to_vec()), + Token::FixedBytes(keccak(NAME).0.to_vec()), + Token::FixedBytes(keccak(VERSION).0.to_vec()), + Token::Uint(chain_id), + Token::Address(user), + ])) +} + +fn hash_call(c: &MetaCall) -> H256 { + keccak(ethabi::encode(&[ + Token::FixedBytes(keccak(CALL_TYPEHASH).0.to_vec()), + Token::Address(c.target), + Token::Uint(c.value), + Token::FixedBytes(keccak(&c.data).0.to_vec()), + ])) +} + +/// Hash an array of calls exactly like the Solidity helper: +/// calls_hash = keccak256(abi.encodePacked(bytes32[] callHashes)) where +/// callHashes[i] = keccak256(abi.encode(CALL_TYPEHASH, target, value, keccak256(data))) +pub fn hash_calls(calls: &[MetaCall]) -> H256 { + let mut packed = Vec::with_capacity(32 * calls.len()); + + for c in calls { + let h = hash_call(c); + packed.extend_from_slice(h.as_bytes()); + } + + keccak(packed) +} + +/// Compute EIP-712 digest for ExecuteMany(calls, nonce) on the user contract. +pub fn execute_meta_many_digest( + chain_id: U256, + user: Address, + calls: &[MetaCall], + nonce: U256, + valid_after: U256, + valid_until: U256, +) -> H256 { + // EIP-712 array hashing: keccak256(abi.encodePacked(bytes32[])) + let calls_hash = hash_calls(calls); + + let struct_hash = keccak(ethabi::encode(&[ + Token::FixedBytes(keccak(EXECUTE_MANY_TYPEHASH).0.to_vec()), + Token::FixedBytes(calls_hash.0.to_vec()), + Token::Uint(nonce), + Token::Uint(valid_after), + Token::Uint(valid_until), + ])); + + let mut pre = Vec::with_capacity(66); + pre.extend_from_slice(&[0x19, 0x01]); + pre.extend_from_slice(eip712_domain_separator(chain_id, user).as_bytes()); + pre.extend_from_slice(struct_hash.as_bytes()); + + keccak(pre) +} + +/// ABI-encode executeMeta((address,uint256,bytes)[],uint256,uint256,uint256,bytes) +pub fn encode_execute_meta_many_call( + calls: Vec, + nonce: U256, + valid_after: U256, + valid_until: U256, + signature: Vec, +) -> Vec { + let sel = { + let mut h = Keccak256::new(); + h.update(b"executeMeta((address,uint256,bytes)[],uint256,uint256,uint256,bytes)"); + let out = h.finalize(); + [out[0], out[1], out[2], out[3]] + }; + + let call_tokens: Vec = calls + .into_iter() + .map(|c| { + Token::Tuple(vec![ + Token::Address(c.target), + Token::Uint(c.value), + Token::Bytes(c.data), + ]) + }) + .collect(); + + let args = ethabi::encode(&[ + Token::Array(call_tokens), + Token::Uint(nonce), + Token::Uint(valid_after), + Token::Uint(valid_until), + Token::Bytes(signature), + ]); + + let mut buf = Vec::with_capacity(4 + args.len()); + buf.extend_from_slice(&sel); + buf.extend_from_slice(&args); + + buf +} + +#[cfg(test)] +mod tests { + use super::*; + use hex::{FromHex, decode as hex_decode}; + + #[test] + fn domain_separator_is_32_bytes() { + let d = eip712_domain_separator(U256::from(1u64), Address::zero()); + assert_eq!(d.as_bytes().len(), 32); + } + + #[test] + fn hash_calls_known_vector_matches_expected() { + // calls: [(0x1111.., 1, 0x), (0x2222.., 2, 0xdeadbeef)] + let a1 = + Address::from_slice(&hex_decode("1111111111111111111111111111111111111111").unwrap()); + let a2 = + Address::from_slice(&hex_decode("2222222222222222222222222222222222222222").unwrap()); + let calls = vec![ + MetaCall { + target: a1, + value: U256::from(1u64), + data: vec![], + }, + MetaCall { + target: a2, + value: U256::from(2u64), + data: >::from_hex("deadbeef").unwrap(), + }, + ]; + let h = hash_calls(&calls); + // Load expected from shared fixtures at compile-time so it stays stable. + // Path is relative to this source file. + const EXPECTED_HEX: &str = include_str!("../../../fixtures/eip7702/hashcalls_vector1.hex"); + let trimmed = EXPECTED_HEX.trim().trim_start_matches("0x"); + let expected = H256::from_slice(&hex_decode(trimmed).unwrap()); + assert_eq!(h, expected); + } +} diff --git a/pkg/eip7702/src/error.rs b/pkg/eip7702/src/error.rs new file mode 100644 index 0000000..6c0ccd7 --- /dev/null +++ b/pkg/eip7702/src/error.rs @@ -0,0 +1,85 @@ +use client_http::{Error as ClientHttpError, NoRpcError}; +use contextful::Contextful; +use ethereum_types::{FromStrRadixErr, U256}; +use hex::FromHexError; +use thiserror::Error; + +/// EIP-7702 result type alias. +pub type Result = std::result::Result; + +/// Typed errors for the EIP-7702 crate. +#[derive(Debug, Error)] +pub enum Error { + /// Relayer secret key was required but not configured. + #[error("[eip7702] relayer secret key not configured")] + RelayerNotConfigured, + + /// Authorization chain id does not match the network chain id. + #[error( + "[eip7702] chain id mismatch: authorization has {authorization:#x}, network has {network:#x}" + )] + ChainIdMismatch { + /// Chain id encoded within the authorization tuple. + authorization: U256, + /// Chain id returned by the connected network. + network: U256, + }, + + /// RPC call returned an error field instead of a successful result. + #[error("[eip7702] rpc error: {response}")] + RpcError { + /// Full JSON value returned by the RPC endpoint. + response: String, + }, + + /// Raw transaction submission failed and returned an error. + #[error("[eip7702] rpc raw error: {response}")] + RpcRawError { + /// Full JSON value returned by the RPC endpoint. + response: String, + }, + + /// Gas estimation RPC returned an error field. + #[error("[eip7702] gas estimation error: {response}")] + EstimateGasError { + /// Full JSON value returned by the RPC endpoint. + response: String, + }, + + /// Hex string could not be parsed into a U256 value. + #[error("[eip7702] failed to parse hex value into U256")] + HexU256Parse(#[from] Contextful), + + /// Transaction hash string was malformed. + #[error("[eip7702] invalid transaction hash")] + TxHashParse(#[from] Contextful), + + /// Transaction hash decoded to an unexpected length. + #[error("[eip7702] invalid transaction hash length {length} for {hash}")] + TxHashLength { + /// Original hash string that decoded to an unexpected length. + hash: String, + /// Number of bytes produced from the decoded hash. + length: usize, + }, + + /// Delegation was not visible on-chain within the allotted timeout. + #[error("[eip7702] delegated code not visible after timeout")] + DelegationTimeout, + + /// Underlying web3 client error. + #[error("[eip7702] web3 error")] + Web3(#[from] Contextful), + + /// HTTP client level error. + #[error("[eip7702] http error")] + Reqwest(#[from] Contextful), + + /// JSON serialization/deserialization error. + #[error("[eip7702] json error")] + Json(#[from] Contextful), + + /// Higher-level HTTP client error when delegating to external relayers. + #[error("[eip7702] client http error")] + ClientHttp(#[from] Contextful>), +} diff --git a/pkg/eip7702/src/lib.rs b/pkg/eip7702/src/lib.rs new file mode 100644 index 0000000..957c466 --- /dev/null +++ b/pkg/eip7702/src/lib.rs @@ -0,0 +1,18 @@ +//! EIP-7702 support library split into focused modules. +//! Modules: auth, eip712, txn, relayer, types. + +mod auth; +mod eip712; +mod error; +mod relayer; +mod txn; +mod types; + +pub use crate::auth::{auth_message_hash, recover_authority, sign_authorization}; +pub use crate::eip712::{ + eip712_domain_separator, encode_execute_meta_many_call, execute_meta_many_digest, +}; +pub use crate::error::{Error, Result}; +pub use crate::relayer::HttpEip7702Relayer; +pub use crate::txn::{build_set_code_tx_json, delegation_indicator_code}; +pub use crate::types::{Authorization, Eip7702Relayer, Eip7702RelayerMock, MetaCall}; diff --git a/pkg/eip7702/src/relayer.rs b/pkg/eip7702/src/relayer.rs new file mode 100644 index 0000000..611fd9d --- /dev/null +++ b/pkg/eip7702/src/relayer.rs @@ -0,0 +1,652 @@ +// lint-long-file-override allow-max-lines=750 +use std::time::Duration; + +use contextful::ResultContextExt; +use eth_util::secret_key_to_address; +use ethereum_types::{Address, H256, U256}; +use secp256k1::{Message, Secp256k1, SecretKey}; +use serde_json::json; +use tracing::warn; +use web3::{Web3, transports::Http}; + +use crate::auth::sign_authorization; +use crate::eip712::{encode_execute_meta_many_call, execute_meta_many_digest}; +use crate::error::{Error, Result}; +use crate::txn::{build_set_code_tx_json, sign_eip1559_envelope, sign_setcode_type4_envelope}; +use crate::types::{Authorization, Eip7702Relayer, MetaCall}; + +const DEFAULT_META_GAS: U256 = U256([1_000_000, 0, 0, 0]); +// NOTE: DEFAULT_META_GAS may become configurable once production metrics are available. + +pub struct HttpEip7702Relayer { + pub(crate) rpc_url: String, + pub(crate) http: reqwest::Client, + pub(crate) relayer_sk: Option, +} + +impl HttpEip7702Relayer { + pub fn new(rpc_url: impl Into) -> Self { + Self { + rpc_url: rpc_url.into(), + http: reqwest::Client::new(), + relayer_sk: None, + } + } + + pub fn new_with_signer(rpc_url: impl Into, relayer_sk: SecretKey) -> Self { + Self { + rpc_url: rpc_url.into(), + http: reqwest::Client::new(), + relayer_sk: Some(relayer_sk), + } + } + + #[allow(clippy::result_large_err)] + fn web3(&self) -> Result> { + let transport = Http::new(&self.rpc_url).context("create web3 http transport")?; + Ok(Web3::new(transport)) + } + + async fn priority_fee_hint(&self) -> Result> { + let req = serde_json::json!({ "jsonrpc": "2.0", "method": "eth_maxPriorityFeePerGas", "params": [], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_maxPriorityFeePerGas")?; + let v: serde_json::Value = res + .json() + .await + .context("decode eth_maxPriorityFeePerGas response")?; + let Some(raw) = v.get("result") else { + return Ok(None); + }; + let Some(hex_str) = raw.as_str() else { + return Ok(None); + }; + let trimmed = hex_str.trim_start_matches("0x"); + if trimmed.is_empty() { + return Ok(Some(U256::zero())); + } + let parsed = U256::from_str_radix(trimmed, 16) + .with_context(|| format!("parse eth_maxPriorityFeePerGas result {hex_str}"))?; + Ok(Some(parsed)) + } + + async fn suggest_fees_fast(&self) -> Result<(U256, U256)> { + let web3 = self.web3()?; + let gp = web3 + .eth() + .gas_price() + .await + .unwrap_or_else(|_| U256::from(1_500_000_000u64)); + + let mut prio = match self.priority_fee_hint().await { + Ok(Some(hint)) => hint, + Ok(None) => gp / 4, + Err(err) => { + warn!(?err, "failed to fetch eth_maxPriorityFeePerGas hint"); + gp / 4 + } + }; + + if prio.is_zero() { + prio = U256::from(1u64); + } + + let max_fee = gp.saturating_add(prio); + Ok((prio, max_fee)) + } + + async fn send_tx_payload(&self, payload: serde_json::Value) -> Result { + let req = json!({ "jsonrpc": "2.0", "method": "eth_sendTransaction", "params": [payload], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_sendTransaction")?; + + let v: serde_json::Value = res + .json() + .await + .context("decode eth_sendTransaction response")?; + if let Some(s) = v.get("result").and_then(|x| x.as_str()) { + let trimmed = s.strip_prefix("0x").unwrap_or(s); + let bytes = hex::decode(trimmed) + .with_context(|| format!("decode eth_sendTransaction result {s}"))?; + if bytes.len() != 32 { + Err(Error::TxHashLength { + hash: s.to_owned(), + length: bytes.len(), + }) + } else { + Ok(H256::from_slice(&bytes)) + } + } else { + Err(Error::RpcError { + response: v.to_string(), + }) + } + } + + async fn estimate_gas_with_overrides( + &self, + txn: serde_json::Value, + override_addr: Address, + override_balance_wei: U256, + ) -> Result { + let overrides = serde_json::json!({ format!("0x{override_addr:x}"): { "balance": format!("0x{override_balance_wei:x}") } }); + let req = serde_json::json!({ "jsonrpc": "2.0", "method": "eth_estimateGas", "params": [txn, "latest", overrides], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_estimateGas with overrides")?; + let v: serde_json::Value = res + .json() + .await + .context("decode eth_estimateGas with overrides response")?; + + if let Some(s) = v.get("result").and_then(|x| x.as_str()) { + let trimmed = s.trim_start_matches("0x"); + if trimmed.is_empty() { + Ok(U256::zero()) + } else { + Ok(U256::from_str_radix(trimmed, 16) + .with_context(|| format!("parse eth_estimateGas with overrides result {s}"))?) + } + } else { + Err(Error::EstimateGasError { + response: v.to_string(), + }) + } + } + + async fn estimate_gas(&self, payload: serde_json::Value) -> Result { + let req = serde_json::json!({ "jsonrpc": "2.0", "method": "eth_estimateGas", "params": [payload], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_estimateGas")?; + let v: serde_json::Value = res + .json() + .await + .context("decode eth_estimateGas response")?; + + if let Some(s) = v.get("result").and_then(|x| x.as_str()) { + let trimmed = s.trim_start_matches("0x"); + if trimmed.is_empty() { + Ok(U256::zero()) + } else { + Ok(U256::from_str_radix(trimmed, 16) + .with_context(|| format!("parse eth_estimateGas result {s}"))?) + } + } else { + Err(Error::EstimateGasError { + response: v.to_string(), + }) + } + } + + async fn sign_eip1559_raw( + &self, + relayer_sk: &SecretKey, + to: Address, + data: Vec, + gas: U256, + value: U256, + ) -> Result> { + let web3 = self.web3()?; + let chain_id = web3 + .eth() + .chain_id() + .await + .context("fetch chain_id for eip1559 envelope")?; + let relayer_addr = secret_key_to_address(relayer_sk); + + let nonce = web3 + .eth() + .transaction_count(relayer_addr, Some(web3::types::BlockNumber::Pending)) + .await + .context("fetch relayer pending nonce")?; + let (max_prio, max_fee) = self.suggest_fees_fast().await?; + + Ok(sign_eip1559_envelope( + chain_id, nonce, max_prio, max_fee, gas, to, value, data, relayer_sk, + )) + } + + async fn sign_setcode_type4_raw( + &self, + relayer_sk: &SecretKey, + user: Address, + gas: U256, + max_prio: U256, + max_fee: U256, + auth: &Authorization, + ) -> Result> { + let web3 = self.web3()?; + let chain_id = web3 + .eth() + .chain_id() + .await + .context("fetch chain_id for setcode envelope")?; + let relayer_addr = secret_key_to_address(relayer_sk); + let nonce = web3 + .eth() + .transaction_count(relayer_addr, Some(web3::types::BlockNumber::Pending)) + .await + .context("fetch relayer pending nonce")?; + + Ok(sign_setcode_type4_envelope( + chain_id, nonce, max_prio, max_fee, gas, user, auth, relayer_sk, + )) + } + + /// Quick pre-check to see if `user` code already reflects delegation to `delegate`. + pub async fn is_delegated_to(&self, user: Address, delegate: Address) -> Result { + Ok(matches!( + self.get_delegate_of(user).await?, + Some(current) if current == delegate + )) + } + + pub async fn get_delegate_of(&self, user: Address) -> Result> { + let web3 = self.web3()?; + let code = web3 + .eth() + .code(user, None) + .await + .context("fetch account code")?; + let b = code.0; + if b.len() >= 23 && b[0..3] == [0xef, 0x01, 0x00] { + let addr_bytes = &b[3..23]; + let addr = Address::from_slice(addr_bytes); + Ok(Some(addr)) + } else { + Ok(None) + } + } + + /// Send a SetCode (type 0x04) transaction using a user-provided Authorization tuple. + pub async fn send_setcode_with_authorization( + &self, + user: Address, + auth: &Authorization, + ) -> Result { + let web3 = self.web3()?; + // Ensure the network chain_id matches the authorization tuple's chain_id + let network_chain_id = web3 + .eth() + .chain_id() + .await + .context("fetch network chain id")?; + if network_chain_id != auth.chain_id { + return Err(Error::ChainIdMismatch { + authorization: auth.chain_id, + network: network_chain_id, + }); + } + + // Try to estimate SetCode gas with state override to avoid funds checks on the relayer + let relayer_addr = self + .relayer_sk + .as_ref() + .map(secret_key_to_address) + .ok_or(Error::RelayerNotConfigured)?; + + // Minimal fee envelope for estimation to satisfy basefee constraints + let gp = web3.eth().gas_price().await.context("fetch gas_price")?; + let est_prio = U256::from(1_000_000_000u64).min(gp); // 1 gwei or lower + let est_max_fee = gp.saturating_add(est_prio); + + let relayer_nonce = web3 + .eth() + .transaction_count(relayer_addr, Some(web3::types::BlockNumber::Pending)) + .await + .context("fetch relayer pending nonce")?; + + let estimate_tx = build_set_code_tx_json( + relayer_addr, + user, + network_chain_id, + relayer_nonce, + U256::zero(), + est_max_fee, + est_prio, + auth, + ); + // Override relayer balance to a large value (e.g. 100 ETH) for simulation only + let override_balance = U256::from_dec_str("100000000000000000000").unwrap(); // 100 ETH + let gas = match self + .estimate_gas_with_overrides(estimate_tx, relayer_addr, override_balance) + .await + { + Ok(g) => g + g / 5u32, // +20% buffer + Err(_) => U256::from(200_000u64), + }; + + // Compute fees for signing/broadcast (~1.5x policy) + let (max_prio, max_fee) = self.suggest_fees_fast().await?; + + let sk = self + .relayer_sk + .as_ref() + .ok_or(Error::RelayerNotConfigured)?; + + let raw = self + .sign_setcode_type4_raw(sk, user, gas, max_prio, max_fee, auth) + .await?; + let req = json!({ "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [format!("0x{}", hex::encode(raw))], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_sendRawTransaction for setcode")?; + let v: serde_json::Value = res + .json() + .await + .context("decode eth_sendRawTransaction setcode response")?; + + if let Some(s) = v.get("result").and_then(|x| x.as_str()) { + let trimmed = s.strip_prefix("0x").unwrap_or(s); + let bytes = hex::decode(trimmed) + .with_context(|| format!("decode eth_sendRawTransaction setcode result {s}"))?; + if bytes.len() != 32 { + Err(Error::TxHashLength { + hash: s.to_owned(), + length: bytes.len(), + }) + } else { + Ok(H256::from_slice(&bytes)) + } + } else { + Err(Error::RpcRawError { + response: v.to_string(), + }) + } + } + + /// Send batched executeMeta with an already signed user signature (no user_sk needed on server). + pub async fn send_execute_meta_many_with_signature( + &self, + user: Address, + calls: Vec, + nonce: U256, + valid_after: U256, + valid_until: U256, + signature: Vec, + ) -> Result { + let sk = self + .relayer_sk + .as_ref() + .ok_or(Error::RelayerNotConfigured)?; + // Preflight estimate for meta call execution (from relayer to user) + let relayer_addr = secret_key_to_address(sk); + let call_data = + encode_execute_meta_many_call(calls, nonce, valid_after, valid_until, signature); + let estimate_payload = build_execute_meta_estimate_payload(relayer_addr, user, &call_data); + + let mut gas = self.estimate_gas(estimate_payload).await?; + gas = gas + gas / 2u32; + let raw = self + .sign_eip1559_raw(sk, user, call_data, gas, U256::zero()) + .await?; + let req = json!({ "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [format!("0x{}", hex::encode(raw))], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_sendRawTransaction for executeMetaMany")?; + let v: serde_json::Value = res + .json() + .await + .context("decode eth_sendRawTransaction executeMetaMany response")?; + if let Some(s) = v.get("result").and_then(|x| x.as_str()) { + let trimmed = s.strip_prefix("0x").unwrap_or(s); + let bytes = hex::decode(trimmed).with_context(|| { + format!("decode eth_sendRawTransaction executeMetaMany result {s}") + })?; + if bytes.len() != 32 { + Err(Error::TxHashLength { + hash: s.to_owned(), + length: bytes.len(), + }) + } else { + Ok(H256::from_slice(&bytes)) + } + } else { + Err(Error::RpcRawError { + response: v.to_string(), + }) + } + } +} + +fn fmt_u256_hex(v: &U256) -> String { + if v.is_zero() { + "0x0".to_string() + } else { + format!("0x{v:x}") + } +} + +fn build_execute_meta_estimate_payload( + relayer_addr: Address, + user: Address, + call_data: &[u8], +) -> serde_json::Value { + serde_json::json!({ + "from": format!("0x{relayer_addr:x}"), + "to": format!("0x{user:x}"), + "value": "0x0", + "data": format!("0x{}", hex::encode(call_data)), + }) +} + +#[async_trait::async_trait] +impl Eip7702Relayer for HttpEip7702Relayer { + async fn ensure_upgraded( + &self, + user_sk: &SecretKey, + user: Address, + delegate: Address, + relayer: Address, + ) -> Result { + let web3 = self.web3()?; + // Pre-check: if user's code already reflects delegation to `delegate`, skip sending + let code = web3 + .eth() + .code(user, None) + .await + .context("fetch user account code")?; + let b = code.0; + if b.len() >= 23 && b[0..3] == [0xef, 0x01, 0x00] && &b[3..23] == delegate.as_bytes() { + return Ok(H256::zero()); + } + let chain_id = web3 + .eth() + .chain_id() + .await + .context("fetch chain_id for ensure_upgraded")?; + let user_nonce = web3 + .eth() + .transaction_count(user, Some(web3::types::BlockNumber::Latest)) + .await + .context("fetch user latest nonce")?; + let relayer_nonce = web3 + .eth() + .transaction_count(relayer, Some(web3::types::BlockNumber::Pending)) + .await + .context("fetch relayer pending nonce")?; + let auth = sign_authorization(user_sk, chain_id, delegate, user_nonce); + let gas = U256::from(200_000u64); + let (max_prio, max_fee) = self.suggest_fees_fast().await?; + if let Some(sk) = &self.relayer_sk { + let raw = self + .sign_setcode_type4_raw(sk, user, gas, max_prio, max_fee, &auth) + .await?; + let req = json!({ "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [format!("0x{}", hex::encode(raw))], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_sendRawTransaction for ensure_upgraded")?; + let v: serde_json::Value = res + .json() + .await + .context("decode eth_sendRawTransaction ensure_upgraded response")?; + if let Some(s) = v.get("result").and_then(|x| x.as_str()) { + let trimmed = s.strip_prefix("0x").unwrap_or(s); + let bytes = hex::decode(trimmed).with_context(|| { + format!("decode eth_sendRawTransaction ensure_upgraded result {s}") + })?; + if bytes.len() != 32 { + Err(Error::TxHashLength { + hash: s.to_owned(), + length: bytes.len(), + }) + } else { + Ok(H256::from_slice(&bytes)) + } + } else { + Err(Error::RpcRawError { + response: v.to_string(), + }) + } + } else { + let payload = build_set_code_tx_json( + relayer, + user, + chain_id, + relayer_nonce, + gas, + max_fee, + max_prio, + &auth, + ); + self.send_tx_payload(payload).await + } + } + + #[allow(clippy::too_many_arguments)] + async fn send_meta_tx( + &self, + user_sk: &SecretKey, + user: Address, + calls: Vec, + relayer: Address, + nonce: U256, + valid_after: U256, + valid_until: U256, + ) -> Result { + let web3 = self.web3()?; + let chain_id = web3 + .eth() + .chain_id() + .await + .context("fetch chain_id for send_meta_tx")?; + let meta_nonce = nonce; + let digest = + execute_meta_many_digest(chain_id, user, &calls, meta_nonce, valid_after, valid_until); + let sig = Secp256k1::new().sign_ecdsa_recoverable( + &Message::from_digest_slice(digest.as_bytes()).unwrap(), + user_sk, + ); + let (rid, bytes) = sig.serialize_compact(); + let mut signature = Vec::with_capacity(65); + signature.extend_from_slice(&bytes); + // Ethereum expects v in {27,28}; convert recover id {0,1} accordingly + signature.push(27 + ((rid.to_i32() as u8) & 1)); + let call_data = + encode_execute_meta_many_call(calls, meta_nonce, valid_after, valid_until, signature); + if let Some(sk) = &self.relayer_sk { + let gas = DEFAULT_META_GAS; + let raw = self + .sign_eip1559_raw(sk, user, call_data, gas, U256::zero()) + .await?; + let req = json!({ "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": [format!("0x{}", hex::encode(raw))], "id": 1 }); + let res = self + .http + .post(&self.rpc_url) + .json(&req) + .send() + .await + .context("post eth_sendRawTransaction for send_meta_tx")?; + let v: serde_json::Value = res + .json() + .await + .context("decode eth_sendRawTransaction send_meta_tx response")?; + if let Some(s) = v.get("result").and_then(|x| x.as_str()) { + let trimmed = s.strip_prefix("0x").unwrap_or(s); + let bytes = hex::decode(trimmed).with_context(|| { + format!("decode eth_sendRawTransaction send_meta_tx result {s}") + })?; + if bytes.len() != 32 { + Err(Error::TxHashLength { + hash: s.to_owned(), + length: bytes.len(), + }) + } else { + Ok(H256::from_slice(&bytes)) + } + } else { + Err(Error::RpcRawError { + response: v.to_string(), + }) + } + } else { + let gas = DEFAULT_META_GAS; + let payload = json!({ + "from": format!("0x{relayer:x}"), + "to": format!("0x{user:x}"), + "gas": fmt_u256_hex(&gas), + "value": fmt_u256_hex(&U256::zero()), + "data": format!("0x{}", hex::encode(call_data)) + }); + self.send_tx_payload(payload).await + } + } + + async fn wait_for_upgrade( + &self, + user: Address, + delegate: Address, + timeout: Duration, + ) -> Result<()> { + let web3 = self.web3()?; + let start = std::time::Instant::now(); + while start.elapsed() < timeout { + let code = web3 + .eth() + .code(user, None) + .await + .context("fetch user account code")?; + let b = code.0; + if b.len() >= 23 && b[0..3] == [0xef, 0x01, 0x00] && &b[3..23] == delegate.as_bytes() { + return Ok(()); + } + tokio::time::sleep(Duration::from_millis(100)).await; + } + Err(Error::DelegationTimeout) + } +} + +#[cfg(test)] +#[path = "relayer_test.rs"] +mod relayer_test; diff --git a/pkg/eip7702/src/relayer_test.rs b/pkg/eip7702/src/relayer_test.rs new file mode 100644 index 0000000..4f2e693 --- /dev/null +++ b/pkg/eip7702/src/relayer_test.rs @@ -0,0 +1,183 @@ +use super::*; +use crate::txn::{delegation_indicator_code, sign_eip1559_envelope, sign_setcode_type4_envelope}; +use crate::{auth_message_hash, sign_authorization}; +use ethereum_types::{Address, H256}; +use reqwest::Client; +use rlp::Rlp; +use testutil::eth::EthNode; + +fn to_hex_u256(v: U256) -> String { + if v.is_zero() { + "0x0".to_string() + } else { + format!("0x{v:x}") + } +} + +async fn rpc_call( + client: &Client, + url: &str, + method: &str, + params: serde_json::Value, +) -> serde_json::Value { + let req = serde_json::json!({"jsonrpc":"2.0","id":1,"method":method,"params":params}); + let res = client.post(url).json(&req).send().await.expect("rpc send"); + res.json().await.expect("rpc json") +} + +#[tokio::test(flavor = "multi_thread")] +async fn auth_type04_sets_delegation_code_on_prague() { + let eth = EthNode::default().run_and_deploy().await; + let rpc_url = eth.rpc_url(); + let web3 = Web3::new(Http::new(&rpc_url).unwrap()); + let client = Client::new(); + + // Keys: user (authorizer) and relayer (sender) + let user_sk = SecretKey::from_slice(&[7u8; 32]).unwrap(); + let relayer_sk = SecretKey::from_slice(&[11u8; 32]).unwrap(); + let user_addr = eth_util::secret_key_to_address(&user_sk); + let relayer_addr = eth_util::secret_key_to_address(&relayer_sk); + + // Fund both accounts + let fund = U256::from_dec_str("100000000000000000000").unwrap(); + for addr in [user_addr, relayer_addr] { + let params = serde_json::json!([format!("0x{addr:x}"), to_hex_u256(fund)]); + let v = rpc_call(&client, &rpc_url, "hardhat_setBalance", params).await; + assert!(v.get("error").is_none(), "setBalance error: {v}"); + } + + // Network and nonces + let chain_id = web3.eth().chain_id().await.expect("chain id"); + let user_nonce = web3 + .eth() + .transaction_count(user_addr, Some(web3::types::BlockNumber::Latest)) + .await + .expect("user nonce"); + let relayer_nonce = web3 + .eth() + .transaction_count(relayer_addr, Some(web3::types::BlockNumber::Pending)) + .await + .expect("relayer nonce"); + + // Sign Authorization for delegate target + let delegate = Address::from_low_u64_be(0xdead_beef); + let auth = sign_authorization(&user_sk, chain_id, delegate, user_nonce); + + // Fees suitable for Hardhat + let gas = U256::from(200_000u64); + let max_prio = U256::from(1_000_000_000u64); + let max_fee = U256::from(2_000_000_000u64); + + // Sign raw type-0x04 + let raw = sign_setcode_type4_envelope( + chain_id, + relayer_nonce, + max_prio, + max_fee, + gas, + user_addr, + &auth, + &relayer_sk, + ); + + // Send raw and ensure success + let send_res = rpc_call( + &client, + &rpc_url, + "eth_sendRawTransaction", + serde_json::json!([format!("0x{}", hex::encode(raw))]), + ) + .await; + let tx_hash = send_res + .get("result") + .and_then(|v| v.as_str()) + .unwrap_or_else(|| panic!("unexpected send response: {send_res}")); + assert!(tx_hash.starts_with("0x")); + + // Verify code bytes reflect delegation indicator + let expected_prefix = delegation_indicator_code(delegate); + let deadline = std::time::Instant::now() + std::time::Duration::from_secs(10); + loop { + let code = web3.eth().code(user_addr, None).await.expect("get code"); + if code.0.len() >= expected_prefix.len() + && &code.0[0..expected_prefix.len()] == expected_prefix.as_slice() + { + break; + } + if std::time::Instant::now() > deadline { + panic!( + "delegation code not observed; got {:?}", + hex::encode(code.0) + ); + } + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + } + + let _digest: H256 = auth_message_hash(chain_id, delegate, user_nonce); +} + +#[test] +fn execute_meta_payload_and_envelope_propagate_value() { + let relayer_addr = Address::from_low_u64_be(0xabc); + let user = Address::from_low_u64_be(0xdef); + let calls = vec![ + MetaCall { + target: Address::from_low_u64_be(1), + value: U256::from(5u64), + data: vec![0x01, 0x02], + }, + MetaCall { + target: Address::from_low_u64_be(2), + value: U256::from(7u64), + data: vec![0x03], + }, + ]; + let nonce = U256::from(9u64); + let valid_after = U256::from(1u64); + let valid_until = U256::from(99u64); + let signature = vec![0xaa, 0xbb, 0xcc]; + let call_data = + encode_execute_meta_many_call(calls.clone(), nonce, valid_after, valid_until, signature); + + let payload = super::build_execute_meta_estimate_payload(relayer_addr, user, &call_data); + let payload_value = payload + .get("value") + .and_then(|v| v.as_str()) + .expect("payload value hex"); + assert_eq!(payload_value, "0x0"); + + let payload_data = payload + .get("data") + .and_then(|v| v.as_str()) + .expect("payload data hex"); + assert!(payload_data.starts_with("0x")); + assert!(payload_data.ends_with(&hex::encode(&call_data))); + + let chain_id = U256::from(1u64); + let tx_nonce = U256::from(3u64); + let max_prio = U256::from(2u64); + let max_fee = U256::from(4u64); + let gas = U256::from(50_000u64); + let sk = SecretKey::from_slice(&[5u8; 32]).unwrap(); + + let raw = sign_eip1559_envelope( + chain_id, + tx_nonce, + max_prio, + max_fee, + gas, + user, + U256::zero(), + call_data, + &sk, + ); + + assert_eq!(raw.first().copied(), Some(0x02)); + let rlp = Rlp::new(&raw[1..]); + let value_bytes: Vec = rlp.val_at(6).expect("value field"); + let mut padded = [0u8; 32]; + let start = padded.len() - value_bytes.len(); + padded[start..].copy_from_slice(&value_bytes); + let encoded_value = U256::from_big_endian(&padded); + assert_eq!(encoded_value, U256::zero()); +} diff --git a/pkg/eip7702/src/txn.rs b/pkg/eip7702/src/txn.rs new file mode 100644 index 0000000..9101c34 --- /dev/null +++ b/pkg/eip7702/src/txn.rs @@ -0,0 +1,266 @@ +// lint-long-file-override allow-max-lines=300 +use crate::types::Authorization; +use ethereum_types::{Address, H256, U256}; +use rlp::RlpStream; +use secp256k1::{Message, Secp256k1, SecretKey}; +use sha3::{Digest, Keccak256}; + +fn u256_be_trim(v: &U256) -> Vec { + if v.is_zero() { + return Vec::new(); + } + + let mut buf = [0u8; 32]; + v.to_big_endian(&mut buf); + let first = buf.iter().position(|&b| b != 0).unwrap_or(31); + + buf[first..].to_vec() +} + +fn trim_leading_zeros(bytes: &[u8]) -> Vec { + if bytes.iter().all(|&b| b == 0) { + return Vec::new(); + } + + let first = bytes + .iter() + .position(|&b| b != 0) + .unwrap_or(bytes.len() - 1); + bytes[first..].to_vec() +} + +/// Construct the delegation indicator code bytes: 0xef0100 || address (20 bytes) +pub fn delegation_indicator_code(delegate: Address) -> Vec { + let mut code = Vec::with_capacity(3 + 20); + code.extend_from_slice(&[0xef, 0x01, 0x00]); + code.extend_from_slice(delegate.as_bytes()); + + code +} + +/// Build a JSON object representing a typed-0x04 SetCode transaction payload +/// including authorizationList, suitable for `eth_sendTransaction`. +#[allow(clippy::too_many_arguments)] +pub fn build_set_code_tx_json( + from: Address, + to: Address, + chain_id: U256, + nonce: U256, + gas: U256, + max_fee_per_gas: U256, + max_priority_fee_per_gas: U256, + authorization: &Authorization, +) -> serde_json::Value { + fn fmt_u256(v: U256) -> String { + if v.is_zero() { + "0x0".to_string() + } else { + format!("0x{v:x}") + } + } + + // Build object while conditionally including fields that must not be zeroed + let mut obj = serde_json::Map::new(); + obj.insert("type".into(), serde_json::Value::String("0x4".into())); + obj.insert( + "from".into(), + serde_json::Value::String(format!("0x{from:x}")), + ); + obj.insert("to".into(), serde_json::Value::String(format!("0x{to:x}"))); + obj.insert( + "chainId".into(), + serde_json::Value::String(fmt_u256(chain_id)), + ); + obj.insert("nonce".into(), serde_json::Value::String(fmt_u256(nonce))); + // Do NOT include gas when zero; clients interpret explicit 0 as allowance=0 during estimation + if !gas.is_zero() { + obj.insert("gas".into(), serde_json::Value::String(fmt_u256(gas))); + } + obj.insert( + "maxFeePerGas".into(), + serde_json::Value::String(fmt_u256(max_fee_per_gas)), + ); + obj.insert( + "maxPriorityFeePerGas".into(), + serde_json::Value::String(fmt_u256(max_priority_fee_per_gas)), + ); + obj.insert("data".into(), serde_json::Value::String("0x".into())); + + let auth = serde_json::json!({ + "chainId": fmt_u256(authorization.chain_id), + "address": format!("0x{:x}", authorization.delegate), + "nonce": fmt_u256(authorization.nonce), + "yParity": format!("0x{:x}", authorization.y_parity), + "r": format!("0x{:x}", authorization.r), + "s": format!("0x{:x}", authorization.s), + }); + obj.insert( + "authorizationList".into(), + serde_json::Value::Array(vec![auth]), + ); + obj.insert("accessList".into(), serde_json::Value::Array(vec![])); + + serde_json::Value::Object(obj) +} + +/// Sign a type-0x02 EIP-1559 transaction envelope with provided fields. +#[allow(clippy::too_many_arguments)] +pub fn sign_eip1559_envelope( + chain_id: U256, + nonce: U256, + max_priority_fee_per_gas: U256, + max_fee_per_gas: U256, + gas: U256, + to: Address, + value: U256, + data: Vec, + sk: &SecretKey, +) -> Vec { + let mut rlp = RlpStream::new_list(9); + rlp.append(&u256_be_trim(&chain_id)); + rlp.append(&u256_be_trim(&nonce)); + rlp.append(&u256_be_trim(&max_priority_fee_per_gas)); + rlp.append(&u256_be_trim(&max_fee_per_gas)); + rlp.append(&u256_be_trim(&gas)); + rlp.append(&to.as_bytes()); + rlp.append(&u256_be_trim(&value)); + rlp.append(&data); + + let access_list = RlpStream::new_list(0); + rlp.append_raw(&access_list.out(), 1); + + let payload = rlp.out(); + + let mut pre = Vec::with_capacity(1 + payload.len()); + pre.push(0x02); + pre.extend_from_slice(&payload); + + let sighash = H256::from_slice(Keccak256::digest(&pre).as_slice()); + + let sig = Secp256k1::new() + .sign_ecdsa_recoverable(&Message::from_digest_slice(sighash.as_bytes()).unwrap(), sk); + let (rid, sig_bytes) = sig.serialize_compact(); + let y_parity = (rid.to_i32() as u8) & 1; + + let mut final_rlp = RlpStream::new_list(12); + final_rlp.append(&u256_be_trim(&chain_id)); + final_rlp.append(&u256_be_trim(&nonce)); + final_rlp.append(&u256_be_trim(&max_priority_fee_per_gas)); + final_rlp.append(&u256_be_trim(&max_fee_per_gas)); + final_rlp.append(&u256_be_trim(&gas)); + final_rlp.append(&to.as_bytes()); + final_rlp.append(&u256_be_trim(&value)); + final_rlp.append(&data); + + let access_list2 = RlpStream::new_list(0); + final_rlp.append_raw(&access_list2.out(), 1); + final_rlp.append(&y_parity); + final_rlp.append(&trim_leading_zeros(&sig_bytes[0..32])); + final_rlp.append(&trim_leading_zeros(&sig_bytes[32..64])); + + let out = final_rlp.out(); + + let mut raw = Vec::with_capacity(1 + out.len()); + raw.push(0x02); + raw.extend_from_slice(&out); + + raw +} + +/// Sign a type-0x04 SetCode transaction envelope with the provided Authorization tuple. +#[allow(clippy::too_many_arguments)] +pub fn sign_setcode_type4_envelope( + chain_id: U256, + nonce: U256, + max_priority_fee_per_gas: U256, + max_fee_per_gas: U256, + gas: U256, + user: Address, + auth: &Authorization, + sk: &SecretKey, +) -> Vec { + let mut rlp = RlpStream::new_list(10); + rlp.append(&u256_be_trim(&chain_id)); + rlp.append(&u256_be_trim(&nonce)); + rlp.append(&u256_be_trim(&max_priority_fee_per_gas)); + rlp.append(&u256_be_trim(&max_fee_per_gas)); + rlp.append(&u256_be_trim(&gas)); + rlp.append(&user.as_bytes()); + rlp.append(&u256_be_trim(&U256::zero())); + rlp.append(&Vec::::new()); + + let empty_access_list = RlpStream::new_list(0); + rlp.append_raw(&empty_access_list.out(), 1); + + let mut auth_list = RlpStream::new_list(1); + let mut tup = RlpStream::new_list(6); + tup.append(&u256_be_trim(&auth.chain_id)); + tup.append(&auth.delegate.as_bytes()); + tup.append(&u256_be_trim(&auth.nonce)); + tup.append(&u64::from(auth.y_parity)); + tup.append(&trim_leading_zeros(auth.r.as_bytes())); + tup.append(&trim_leading_zeros(auth.s.as_bytes())); + auth_list.append_raw(&tup.out(), 1); + rlp.append_raw(&auth_list.out(), 1); + + let payload = rlp.out(); + + let mut pre = Vec::with_capacity(1 + payload.len()); + pre.push(0x04); + pre.extend_from_slice(&payload); + + let sighash = H256::from_slice(Keccak256::digest(&pre).as_slice()); + let sig = Secp256k1::new() + .sign_ecdsa_recoverable(&Message::from_digest_slice(sighash.as_bytes()).unwrap(), sk); + let (rid, sig_bytes) = sig.serialize_compact(); + let y_parity = (rid.to_i32() as u8) & 1; + + let mut final_rlp = RlpStream::new_list(13); + final_rlp.append(&u256_be_trim(&chain_id)); + final_rlp.append(&u256_be_trim(&nonce)); + final_rlp.append(&u256_be_trim(&max_priority_fee_per_gas)); + final_rlp.append(&u256_be_trim(&max_fee_per_gas)); + final_rlp.append(&u256_be_trim(&gas)); + final_rlp.append(&user.as_bytes()); + final_rlp.append(&u256_be_trim(&U256::zero())); + final_rlp.append(&Vec::::new()); + + let empty_access_list2 = RlpStream::new_list(0); + final_rlp.append_raw(&empty_access_list2.out(), 1); + + let mut auth_list2 = RlpStream::new_list(1); + let mut tup2 = RlpStream::new_list(6); + tup2.append(&u256_be_trim(&auth.chain_id)); + tup2.append(&auth.delegate.as_bytes()); + tup2.append(&u256_be_trim(&auth.nonce)); + tup2.append(&u64::from(auth.y_parity)); + tup2.append(&trim_leading_zeros(auth.r.as_bytes())); + tup2.append(&trim_leading_zeros(auth.s.as_bytes())); + auth_list2.append_raw(&tup2.out(), 1); + final_rlp.append_raw(&auth_list2.out(), 1); + + final_rlp.append(&y_parity); + final_rlp.append(&trim_leading_zeros(&sig_bytes[0..32])); + final_rlp.append(&trim_leading_zeros(&sig_bytes[32..64])); + + let out = final_rlp.out(); + let mut raw = Vec::with_capacity(1 + out.len()); + raw.push(0x04); + raw.extend_from_slice(&out); + + raw +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn delegation_code_format() { + let d = Address::from_low_u64_be(0xdeadbeef); + let code = delegation_indicator_code(d); + assert_eq!(code.len(), 23); + assert_eq!(&code[0..3], &[0xef, 0x01, 0x00]); + assert_eq!(&code[3..], d.as_bytes()); + } +} diff --git a/pkg/eip7702/src/types.rs b/pkg/eip7702/src/types.rs new file mode 100644 index 0000000..1be9dde --- /dev/null +++ b/pkg/eip7702/src/types.rs @@ -0,0 +1,74 @@ +use std::time::Duration; + +use ethereum_types::{Address, H256, U256}; +use secp256k1::SecretKey; +use test_spy::spy_mock; + +use crate::error::Result; + +/// Authorization tuple for EIP-7702 SetCode transactions. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Authorization { + pub chain_id: U256, + pub delegate: Address, + pub nonce: U256, + pub y_parity: u8, + pub r: H256, + pub s: H256, +} + +/// Meta-call structure used by executeMetaMany. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct MetaCall { + pub target: Address, + pub value: U256, + pub data: Vec, +} + +#[spy_mock] +#[async_trait::async_trait] +pub trait Eip7702Relayer { + async fn ensure_upgraded( + &self, + user_sk: &SecretKey, + user: Address, + delegate: Address, + relayer: Address, + ) -> Result; + + #[allow(clippy::too_many_arguments)] + async fn send_meta_tx( + &self, + user_sk: &SecretKey, + user: Address, + calls: Vec, + relayer: Address, + nonce: U256, + valid_after: U256, + valid_until: U256, + ) -> Result; + + async fn wait_for_upgrade( + &self, + user: Address, + delegate: Address, + timeout: Duration, + ) -> Result<()>; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn meta_call_debug_eq() { + let a = MetaCall { + target: Address::zero(), + value: U256::zero(), + data: vec![1, 2, 3], + }; + let b = a.clone(); + assert_eq!(a, b); + assert!(format!("{a:?}").contains("MetaCall")); + } +} diff --git a/pkg/element/Cargo.toml b/pkg/element/Cargo.toml new file mode 100644 index 0000000..f45e0a7 --- /dev/null +++ b/pkg/element/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "element" +version = "0.1.0" +edition = "2024" + +[dependencies] +acvm = { workspace = true } +bitvec = { workspace = true } +diesel = { workspace = true, optional = true, features = ["postgres_backend"] } +ethnum = { workspace = true } +hex = { workspace = true } +proptest = { workspace = true } +rand = { workspace = true, optional = true } +serde = { workspace = true, optional = true, features = ["derive"] } +borsh = { workspace = true, optional = true } +ts-rs = { workspace = true, optional = true } +workspace-hack.workspace = true + +[dev-dependencies] +test-strategy = { workspace = true } +serde_json = { workspace = true } +insta = { workspace = true } +rand_chacha = { workspace = true } +rand_xorshift = { workspace = true } + +[features] +default = ["serde", "rand", "borsh"] +ts-rs = ["dep:ts-rs"] diff --git a/pkg/element/README.md b/pkg/element/README.md new file mode 100644 index 0000000..b3388ba --- /dev/null +++ b/pkg/element/README.md @@ -0,0 +1,15 @@ +# Element + +Core field element type with arithmetic operations and serialization support. It's a thin-wrapper around U256, that provides a consistent type across many services. + +## Overview + +This package provides the fundamental field element type used throughout the zk-rollup system for cryptographic operations. + +## Features + +- Field element arithmetic operations +- Serialization/deserialization support +- Conversion utilities +- Diesel PostgreSQL integration +- Random element generation diff --git a/pkg/zk-primitives/src/snapshots/zk_primitives__hash__tests__hash_bytes_snapshot_test.snap b/pkg/element/snapshots/zk_primitives__hash__tests__hash_bytes_snapshot_test.snap similarity index 100% rename from pkg/zk-primitives/src/snapshots/zk_primitives__hash__tests__hash_bytes_snapshot_test.snap rename to pkg/element/snapshots/zk_primitives__hash__tests__hash_bytes_snapshot_test.snap diff --git a/pkg/zk-primitives/src/snapshots/zk_primitives__hash__tests__hash_merge_snapshot_test.snap b/pkg/element/snapshots/zk_primitives__hash__tests__hash_merge_snapshot_test.snap similarity index 100% rename from pkg/zk-primitives/src/snapshots/zk_primitives__hash__tests__hash_merge_snapshot_test.snap rename to pkg/element/snapshots/zk_primitives__hash__tests__hash_merge_snapshot_test.snap diff --git a/pkg/zk-primitives/src/element/arith.rs b/pkg/element/src/arith.rs similarity index 100% rename from pkg/zk-primitives/src/element/arith.rs rename to pkg/element/src/arith.rs diff --git a/pkg/zk-primitives/src/element/borsh_impls.rs b/pkg/element/src/borsh_impls.rs similarity index 100% rename from pkg/zk-primitives/src/element/borsh_impls.rs rename to pkg/element/src/borsh_impls.rs diff --git a/pkg/zk-primitives/src/element/collision.rs b/pkg/element/src/collision.rs similarity index 95% rename from pkg/zk-primitives/src/element/collision.rs rename to pkg/element/src/collision.rs index 69418ce..1f67a04 100644 --- a/pkg/zk-primitives/src/element/collision.rs +++ b/pkg/element/src/collision.rs @@ -4,7 +4,7 @@ impl Element { /// Check to see if this element collides with another element in a tree of depth `DEPTH` /// /// ```rust - /// # use zk_primitives::*; + /// # use element::Element; /// const DEPTH: usize = 64; /// /// let a = Element::new(1); diff --git a/pkg/element/src/convert.rs b/pkg/element/src/convert.rs new file mode 100644 index 0000000..00133b4 --- /dev/null +++ b/pkg/element/src/convert.rs @@ -0,0 +1,321 @@ +// lint-long-file-override allow-max-lines=400 +use crate::Element; +use bitvec::{array::BitArray, order::Msb0}; +use core::num::TryFromIntError; +use ethnum::U256; +use std::str::FromStr; + +macro_rules! from_int_impls { + ($t:ty) => { + impl From<$t> for Element { + #[inline] + fn from(value: $t) -> Self { + Element(U256::from(value)) + } + } + + impl TryFrom for $t { + type Error = TryFromIntError; + + #[inline] + fn try_from(value: Element) -> Result { + <$t>::try_from(value.0) + } + } + }; +} + +from_int_impls!(u8); +from_int_impls!(u16); +from_int_impls!(u32); +from_int_impls!(u64); +from_int_impls!(u128); + +impl From for Element { + #[inline] + fn from(value: bool) -> Self { + match value { + false => Self::ZERO, + true => Self::ONE, + } + } +} + +impl FromStr for Element { + type Err = ::Err; + + #[inline] + fn from_str(s: &str) -> Result { + let s = s.strip_prefix("0x").unwrap_or(s); + Ok(Self(U256::from_str_radix(s, 16)?)) + } +} + +impl From for Element { + fn from(value: U256) -> Self { + Self(value) + } +} + +impl From for U256 { + fn from(value: Element) -> Self { + value.0 + } +} + +impl Element { + /// Converts the Element to an array of two u128 words + /// + /// Returns an array where: + /// - index 0 contains the high 128 bits + /// - index 1 contains the low 128 bits + #[must_use] + pub fn to_words(self) -> [u128; 2] { + let (high, low) = self.0.into_words(); + [high, low] + } + + /// Creates an Element from an array of two u128 words + /// + /// The input array should contain: + /// - index 0: the high 128 bits + /// - index 1: the low 128 bits + #[must_use] + pub fn from_words(words: [u128; 2]) -> Self { + Self(U256::from_words(words[0], words[1])) + } + + /// Creates an Element from an array of four u64 values + /// + /// The input array should contain values in little-endian order: + /// - arr\[0]: least significant 64 bits + /// - arr\[1]: second least significant 64 bits + /// - arr\[2]: second most significant 64 bits + /// - arr\[3]: most significant 64 bits + #[must_use] + pub fn from_u64_array(arr: [u64; 4]) -> Self { + let low_u128 = u128::from(arr[0]) | (u128::from(arr[1]) << 64); + let high_u128 = u128::from(arr[2]) | (u128::from(arr[3]) << 64); + Self(U256::from_words(high_u128, low_u128)) + } + + /// Converts the Element to an array of four u64 values + /// + /// Returns an array in little-endian order: + /// - arr\[0]: least significant 64 bits + /// - arr\[1]: second least significant 64 bits + /// - arr\[2]: second most significant 64 bits + /// - arr\[3]: most significant 64 bits + #[must_use] + #[allow(clippy::cast_possible_truncation)] + pub fn to_u64_array(self) -> [u64; 4] { + let (high_u128, low_u128) = self.0.into_words(); + let arr0 = low_u128 as u64; + let arr1 = (low_u128 >> 64) as u64; + let arr2 = high_u128 as u64; + let arr3 = (high_u128 >> 64) as u64; + [arr0, arr1, arr2, arr3] + } + + /// Convert the [`Element`] to its bytes in big-endian format + /// + /// ```rust + /// # use element::Element; + /// let element = Element::ZERO; + /// assert_eq!(element.to_be_bytes(), [0; 32]); + /// + /// let element = Element::ONE; + /// assert_eq!(element.to_be_bytes(), { + /// let mut temp = [0; 32]; + /// temp[31] = 1; + /// temp + /// }); + /// ``` + #[inline] + #[must_use] + pub fn to_be_bytes(self) -> [u8; 32] { + self.0.to_be_bytes() + } + + /// Convert the [`Element`] to its bits in big-endian format + /// + /// ```rust + /// # use element::Element; + /// let element = Element::ZERO; + /// let bits = element.to_be_bits(); + /// + /// ``` + #[inline] + #[must_use] + pub fn to_be_bits(self) -> BitArray<[u8; 32], Msb0> { + let bits = self.0.to_be_bytes(); + BitArray::new(bits) + } + + /// Convert the [`Element`] to its bytes in little-endian format + /// + /// ```rust + /// # use element::Element; + /// let element = Element::ZERO; + /// assert_eq!(element.to_le_bytes(), [0; 32]); + /// + /// let element = Element::ONE; + /// assert_eq!(element.to_le_bytes(), { + /// let mut temp = [0; 32]; + /// temp[0] = 1; + /// temp + /// }); + /// ``` + #[inline] + #[must_use] + pub fn to_le_bytes(self) -> [u8; 32] { + self.0.to_le_bytes() + } + + /// Convert big-endian bytes into an [`Element`] + /// ```rust + /// # use element::Element; + /// let element = Element::from_be_bytes([0; 32]); + /// assert_eq!(element, Element::ZERO); + /// + /// let element = Element::from_be_bytes({ + /// let mut temp = [0; 32]; + /// temp[31] = 1; + /// temp + /// }); + /// assert_eq!(element, Element::ONE); + /// ``` + #[inline] + #[must_use] + pub fn from_be_bytes(bytes: [u8; 32]) -> Self { + Self(U256::from_be_bytes(bytes)) + } + + /// Convert little-endian bytes into an [`Element`] + /// ```rust + /// # use element::Element; + /// let element = Element::from_le_bytes([0; 32]); + /// assert_eq!(element, Element::ZERO); + /// + /// let element = Element::from_le_bytes({ + /// let mut temp = [0; 32]; + /// temp[0] = 1; + /// temp + /// }); + /// assert_eq!(element, Element::ONE); + /// ``` + #[inline] + #[must_use] + pub fn from_le_bytes(bytes: [u8; 32]) -> Self { + Self(U256::from_le_bytes(bytes)) + } + + /// Decomposes an [`Element`] into two [`Element`]s, low and high, in big-endian order. + /// + /// The low field contains the lower 16 bytes (128 bits) of the input field and + /// the high field contains the upper 16 bytes (128 bits) of the input field. + /// + /// ```rust + /// # use element::Element; + /// let element = Element::from(0x0123456789ABCDEFu64); + /// let (high, low) = element.decompose_be(); + /// assert_eq!(high, Element::ZERO); + /// assert_eq!(low, Element::from(0x0123456789ABCDEFu64)); + /// ``` + #[inline] + #[must_use] + pub fn decompose_be(self) -> (Element, Element) { + let bytes = self.to_be_bytes(); + let high_bytes: [u8; 16] = bytes[..16].try_into().unwrap(); + let low_bytes: [u8; 16] = bytes[16..].try_into().unwrap(); + + let high = Element::from(U256::from_be_bytes( + [0u8; 16] + .into_iter() + .chain(high_bytes) + .collect::>() + .try_into() + .unwrap(), + )); + let low = Element::from(U256::from_be_bytes( + [0u8; 16] + .into_iter() + .chain(low_bytes) + .collect::>() + .try_into() + .unwrap(), + )); + + (high, low) + } + + /// Decomposes an [`Element`] into two [`Element`]s, low and high, in little-endian order. + /// + /// The low field contains the lower 16 bytes (128 bits) of the input field and + /// the high field contains the upper 16 bytes (128 bits) of the input field. + /// + /// ```rust + /// # use element::Element; + /// let element = Element::from(0x0123456789ABCDEFu64); + /// let (high, low) = element.decompose_le(); + /// assert_eq!(high, Element::ZERO); + /// assert_eq!(low, Element::from(0x0123456789ABCDEFu64)); + /// ``` + #[inline] + #[must_use] + pub fn decompose_le(self) -> (Element, Element) { + let bytes = self.to_le_bytes(); + let low_bytes: [u8; 16] = bytes[..16].try_into().unwrap(); + let high_bytes: [u8; 16] = bytes[16..].try_into().unwrap(); + + let high = Element::from(U256::from_le_bytes( + high_bytes + .into_iter() + .chain([0u8; 16]) + .collect::>() + .try_into() + .unwrap(), + )); + let low = Element::from(U256::from_le_bytes( + low_bytes + .into_iter() + .chain([0u8; 16]) + .collect::>() + .try_into() + .unwrap(), + )); + + (high, low) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_be_bits() { + let element = Element::ZERO; + let bits = BitArray::<[u8; 32], Msb0>::new([0u8; 32]); + assert_eq!(element.to_be_bits(), bits); + + let element = Element::ONE; + assert_eq!( + element + .to_be_bits() + .iter() + .rev() + .take(1) + .collect::>(), + vec![true] + ); + } + + #[test] + fn test_from_str() { + assert_eq!(Element::from_str("0").unwrap(), Element::ZERO); + assert_eq!(Element::from_str("0x0").unwrap(), Element::ZERO); + assert_eq!(Element::from_str("0x1").unwrap(), Element::ONE); + assert_eq!(Element::from_str("0xB").unwrap(), Element::from(11u64)); + } +} diff --git a/pkg/zk-primitives/src/element/diesel_pg.rs b/pkg/element/src/diesel_pg.rs similarity index 84% rename from pkg/zk-primitives/src/element/diesel_pg.rs rename to pkg/element/src/diesel_pg.rs index 268e6b5..b65a1b1 100644 --- a/pkg/zk-primitives/src/element/diesel_pg.rs +++ b/pkg/element/src/diesel_pg.rs @@ -1,13 +1,13 @@ use super::Element; -use crate::element::U256; +use crate::U256; use diesel::{ deserialize::{self, FromSql}, pg::{Pg, PgValue}, serialize::{self, IsNull, Output, ToSql}, sql_types::Numeric, }; -use std::convert::TryInto; use std::io::Write; +use std::{convert::TryInto, str::FromStr}; impl ToSql for Element { fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result { @@ -102,3 +102,20 @@ impl FromSql for Element { Ok(Element(result)) } } + +impl ToSql for Element { + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result { + let text = self.to_hex(); + out.write_all(text.as_bytes())?; + Ok(IsNull::No) + } +} + +impl FromSql for Element { + fn from_sql(bytes: PgValue<'_>) -> deserialize::Result { + let text = std::str::from_utf8(bytes.as_bytes())?; + let value = Element::from_str(text) + .map_err(|_| "Invalid decimal string for Element".to_string())?; + Ok(value) + } +} diff --git a/pkg/zk-primitives/src/element/fmt.rs b/pkg/element/src/fmt.rs similarity index 99% rename from pkg/zk-primitives/src/element/fmt.rs rename to pkg/element/src/fmt.rs index 56dd2e9..6ae15b8 100644 --- a/pkg/zk-primitives/src/element/fmt.rs +++ b/pkg/element/src/fmt.rs @@ -24,4 +24,3 @@ fmt_impl!(UpperExp); fmt_impl!(LowerExp); fmt_impl!(Binary); fmt_impl!(Octal); - diff --git a/pkg/element/src/lib.rs b/pkg/element/src/lib.rs new file mode 100644 index 0000000..4b79811 --- /dev/null +++ b/pkg/element/src/lib.rs @@ -0,0 +1,204 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::match_bool)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::explicit_deref_methods)] +#![allow(clippy::doc_markdown)] +// #![deny(missing_docs)] + +// lint-long-file-override allow-max-lines=300 +use ethnum::U256; +pub use signed_element::SignedElement; + +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +mod arith; +mod collision; +mod convert; +mod fmt; +mod lsb; +mod noir; +mod signed_element; + +#[cfg(feature = "borsh")] +mod borsh_impls; + +#[cfg(feature = "rand")] +mod rand_impls; +#[cfg(feature = "rand")] +pub use rand_impls::Insecure; + +pub use lsb::Lsb; + +#[cfg(feature = "serde")] +mod serde; + +#[cfg(feature = "diesel")] +mod diesel_pg; + +/// The base element used by cryptographic operations on this tree +/// +/// This is (roughly) an integer modulo `p` where `p` is [`Element::MODULUS`] +pub type Base = acvm::FieldElement; + +// #[cfg(feature = "diesel")] +// use diesel::sql_types::*; + +/// A 256-bit unsigned integer +/// +/// This type is a wrapper around a [`U256`], so can represent any value in the range `0..=(2^256 - +/// 1)`. +/// However, in a ZK context, it is usually converted to a [`Base`], which is an integer modulo +/// "some large prime". This restricts the set of usable values to something approximating a `u254` +/// +/// [`Base`]: crate::Base +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(transparent))] +#[cfg_attr( + feature = "diesel", + derive(::diesel::expression::AsExpression, ::diesel::deserialize::FromSqlRow) +)] +#[cfg_attr(feature = "diesel", diesel(sql_type = ::diesel::sql_types::Numeric))] +#[cfg_attr(feature = "diesel", diesel(sql_type = ::diesel::sql_types::Text))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct Element( + #[cfg_attr(feature = "serde", serde(with = "serde"))] + #[cfg_attr(feature = "ts-rs", ts(as = "String"))] + pub(crate) U256, +); + +impl Element { + /// The zero element of the group (the additive identity) + pub const ZERO: Self = Self(U256::ZERO); + + /// The one element of the group (the multiplicative identity) + pub const ONE: Self = Self(U256::ONE); + + /// The largest possible element (note that this is not canonical) + pub const MAX: Self = Self(U256::MAX); + + /// A null hash value (this is identical to [`Element::ZERO`]) + /// + /// Note that this value is chosen arbitrarily + pub const NULL_HASH: Self = Self::ZERO; + + /// The [`Element`] used as the initialization vector when hashing bytes + pub const BYTE_HASH_IV: Self = Self(U256::new(2)); + + /// Create a new [`Element`] from a u64 + /// + /// This is largely provided to help type inference in simple cases + #[inline] + #[must_use] + pub fn new(i: u64) -> Self { + Self(U256::from(i)) + } + + /// Attempt to convert this [`Element`] to a bool + /// + /// If this value is not 0 or 1, `None` is returned + #[inline] + #[must_use] + pub fn as_bool(self) -> Option { + match self { + Self::ZERO => Some(false), + Self::ONE => Some(true), + _else => None, + } + } + + /// Convert this [`Element`] to a U256 string + #[inline] + #[must_use] + pub fn to_u256(self) -> U256 { + self.0 + } + + /// Convert this [`Element`] to a hex string shorting leading zeros + #[inline] + #[must_use] + fn to_hex_compact(self) -> String { + hex::encode(self.to_be_bytes()) + } + + /// Convert this [`Element`] to a hex string with leading zeros + #[inline] + #[must_use] + pub fn to_hex(self) -> String { + format!("{:0>64}", self.to_hex_compact()) + } + + /// If this element is zero, returns true + #[inline] + #[must_use] + pub fn is_zero(self) -> bool { + self == Self::ZERO + } +} + +macro_rules! partial_eq_impl { + ($int:ty) => { + impl PartialEq<$int> for Element { + fn eq(&self, other: &$int) -> bool { + *self == Element::from(*other) + } + } + }; +} + +partial_eq_impl!(bool); +partial_eq_impl!(u8); +partial_eq_impl!(u16); +partial_eq_impl!(u32); +partial_eq_impl!(u64); +partial_eq_impl!(u128); + +pub mod proptest { + use super::Element; + use ::proptest::{arbitrary::StrategyFor, prelude::*, strategy::Map}; + use ethnum::U256; + + impl Arbitrary for Element { + type Strategy = Map, fn([u8; 32]) -> Self>; + type Parameters = (); + + fn arbitrary_with((): Self::Parameters) -> Self::Strategy { + any::<[u8; 32]>().prop_map(|array| Self(U256::from_be_bytes(array))) + } + } +} + +#[cfg(test)] +mod test { + use super::Element; + + #[test] + fn syntax_test() { + let element = Element::new(123); + + assert_eq!(element + 1u64, Element::new(124)); + assert_eq!(element * 2u64, Element::new(246)); + assert_eq!(element - 2u64, Element::new(121)); + assert_eq!(element + Element::ONE, Element::new(124)); + assert_eq!(element * Element::new(2), Element::new(246)); + assert_eq!(element - Element::new(2), Element::new(121)); + + assert_eq!(Element::new(1).to_string(), "1"); + assert_eq!(Element::new(100).to_string(), "64"); + assert_eq!(Element::new(123).to_string(), "7b"); + + assert_eq!( + (1..=10).map(Element::new).sum::(), + Element::new(55) + ); + + assert_eq!( + (1..=5).map(Element::new).product::(), + Element::new(120) + ); + } +} diff --git a/pkg/zk-primitives/src/element/lsb.rs b/pkg/element/src/lsb.rs similarity index 97% rename from pkg/zk-primitives/src/element/lsb.rs rename to pkg/element/src/lsb.rs index 13323d3..d518b57 100644 --- a/pkg/zk-primitives/src/element/lsb.rs +++ b/pkg/element/src/lsb.rs @@ -81,7 +81,7 @@ impl IntoIterator for Lsb { } } -impl<'a> IntoIterator for &'a Lsb { +impl IntoIterator for &Lsb { type Item = bool; type IntoIter = core::iter::Skip>; @@ -96,7 +96,7 @@ impl Element { /// bits first) /// /// ```rust - /// # use zk_primitives::*; + /// # use element::Element; /// let element = Element::new(5); // 0b000...000101 /// let bits = element.lsb(4); /// let bits: Vec = bits.into_iter().collect(); diff --git a/pkg/element/src/noir.rs b/pkg/element/src/noir.rs new file mode 100644 index 0000000..6da0ae4 --- /dev/null +++ b/pkg/element/src/noir.rs @@ -0,0 +1,83 @@ +use crate::{Base, Element}; +use acvm::AcirField; +use ethnum::uint; + +impl Element { + pub const MODULUS: Element = Element(uint!( + "0x30644E72E131A029B85045B68181585D2833E84879B9709143E1F593F0000001" + )); + + /// Create an [`Element`] from a [`Base`] + #[inline] + #[must_use] + pub fn from_base(base: Base) -> Element { + let bytes: [u8; 32] = base.to_be_bytes().try_into().unwrap(); + Element::from_be_bytes(bytes) + } + + /// Convert this [`Element`] to its equivalent [`Base`] representation + #[inline] + #[must_use] + pub fn to_base(&self) -> Base { + Base::from_be_bytes_reduce(self.to_be_bytes().as_slice()) + } +} + +impl From for Element { + #[inline] + fn from(base: Base) -> Self { + Self::from_base(base) + } +} + +impl From for Base { + #[inline] + fn from(element: Element) -> Self { + element.to_base() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_and_from_base() { + // Test with a simple value + let element = Element::from(42u64); + let base = element.to_base(); + let element_from_base = Element::from_base(base); + assert_eq!(element, element_from_base); + + // Test with a larger value + let element = Element::from(u64::MAX); + let base = element.to_base(); + let element_from_base = Element::from_base(base); + assert_eq!(element, element_from_base); + + // Test with a value close to the modulus + let element = Element::MODULUS - Element::from(1u64); + let base = element.to_base(); + let element_from_base = Element::from_base(base); + assert_eq!(element, element_from_base); + + // Test with zero + let element = Element::ZERO; + let base = element.to_base(); + let element_from_base = Element::from_base(base); + assert_eq!(element, element_from_base); + } + + #[test] + fn test_base_roundtrip_consistency() { + // Create a random element + let original = Element::from(0x1234_5678_90ab_cdef_u64); + + // Convert to base and back + let base = original.to_base(); + let roundtrip = Element::from_base(base); + + // Should be the same + assert_eq!(original, roundtrip); + } +} diff --git a/pkg/zk-primitives/src/element/rand_impls.rs b/pkg/element/src/rand_impls.rs similarity index 93% rename from pkg/zk-primitives/src/element/rand_impls.rs rename to pkg/element/src/rand_impls.rs index 1759cd5..9464d65 100644 --- a/pkg/zk-primitives/src/element/rand_impls.rs +++ b/pkg/element/src/rand_impls.rs @@ -9,10 +9,8 @@ use crate::Element; /// that this value does need to be cryptographically secure /// /// In particular, when used with [`Element`]: -/// - if you have a cryptographically-secure RNG, you can use [`Element::secure_random`] to -/// generate an [`Element`] -/// - if you have an insecure RNG, you can use [`Element::random`] to generate an -/// [`Insecure`] +/// - if you have a cryptographically-secure RNG, you can use [`Element::secure_random`] to generate an [`Element`] +/// - if you have an insecure RNG, you can use [`Element::random`] to generate an [`Insecure`] pub struct Insecure { inner: T, } @@ -38,7 +36,7 @@ impl Element { /// trait bound, and returns an [`Element`] /// /// ```rust,compile_fail - /// # use zk_primitives::*; + /// # use element::Element; /// # use rand_xorshift::XorShiftRng; /// # use rand::SeedableRng; /// // this rng is NOT cryptographically secure @@ -50,7 +48,7 @@ impl Element { /// To get access to the generated element, we need to call [`Insecure::get_insecure`]. /// Hopefully this is scary enough that we will think twice where we use this value. /// ```rust - /// # use zk_primitives::*; + /// # use element::Element; /// # use rand_xorshift::XorShiftRng; /// # use rand::SeedableRng; /// // this rng is NOT cryptographically secure @@ -72,7 +70,7 @@ impl Element { /// non-cryptographically-secure RNG, consider using [`Element::random`] /// /// ```rust - /// # use zk_primitives::*; + /// # use element::Element; /// let mut rng = rand::thread_rng(); /// let element = Element::secure_random(&mut rng); /// diff --git a/pkg/element/src/serde.rs b/pkg/element/src/serde.rs new file mode 100644 index 0000000..416549f --- /dev/null +++ b/pkg/element/src/serde.rs @@ -0,0 +1,35 @@ +use ethnum::U256; +use serde::{Deserialize, Deserializer, Serializer}; + +pub(super) fn serialize(u: &U256, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(&format!("{:0>64}", hex::encode(u.to_be_bytes()))) +} + +pub(super) fn deserialize<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + let vec = hex::decode(s.trim_start_matches("0x")).map_err(serde::de::Error::custom)?; + let bytes = + <[u8; 32]>::try_from(vec).map_err(|_| serde::de::Error::custom("Invalid length"))?; + Ok(U256::from_be_bytes(bytes)) +} + +#[cfg(test)] +mod tests { + use test_strategy::proptest; + + use crate::Element; + + #[proptest] + fn elements_produce_identical_base_before_after_serialize(element: Element) { + let value = serde_json::to_value(element).unwrap(); + let element_again: Element = serde_json::from_value(value).unwrap(); + + assert_eq!(element, element_again); + } +} diff --git a/pkg/element/src/signed_element.rs b/pkg/element/src/signed_element.rs new file mode 100644 index 0000000..202020b --- /dev/null +++ b/pkg/element/src/signed_element.rs @@ -0,0 +1,885 @@ +// lint-long-file-override allow-max-lines=900 +use crate::Element; +use ethnum::U256; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; +use std::cmp::{Ord, Ordering, PartialOrd}; +use std::ops::{Add, Div, Mul, Neg, Sub}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +/// A signed 256-bit integer that wraps an `Element` with a sign bit +/// +/// This type allows performing arithmetic operations with signed numbers, +/// while the underlying `Element` remains unsigned. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct SignedElement { + /// The absolute value stored as an Element + pub value: Element, + /// The sign: true for negative, false for positive or zero + pub negative: bool, +} + +impl SignedElement { + /// Creates a new SignedElement with the given value and sign + #[inline] + #[must_use] + pub fn new(value: Element, negative: bool) -> Self { + // Normalize: if value is zero, sign should be positive + if value.is_zero() { + Self { + value, + negative: false, + } + } else { + Self { value, negative } + } + } + + /// Creates a new positive value + #[must_use] + pub fn positive(value: Element) -> Self { + Self::new(value, false) + } + + #[must_use] + pub fn negative(value: Element) -> Self { + Self::new(value, true) + } + + /// The zero element (the additive identity) + pub const ZERO: Self = Self { + value: Element::ZERO, + negative: false, + }; + + /// The one element (the multiplicative identity) + pub const ONE: Self = Self { + value: Element::ONE, + negative: false, + }; + + /// The negative one element + pub const NEG_ONE: Self = Self { + value: Element::ONE, + negative: true, + }; + + /// Get the absolute value of this element + #[inline] + #[must_use] + pub fn abs(self) -> Element { + self.value + } + + /// Check if this element is negative + #[inline] + #[must_use] + pub fn is_negative(self) -> bool { + self.negative + } + + /// Check if this element is positive (greater than zero) + #[inline] + #[must_use] + pub fn is_positive(self) -> bool { + !self.negative && !self.value.is_zero() + } + + /// Check if this element is zero + #[inline] + #[must_use] + pub fn is_zero(self) -> bool { + self.value.is_zero() + } + + /// Get the sign of this element: -1, 0, or 1 + #[inline] + #[must_use] + pub fn signum(self) -> Self { + if self.is_zero() { + Self::ZERO + } else if self.negative { + Self::NEG_ONE + } else { + Self::ONE + } + } + + /// Convert to the underlying U256 value with sign information + /// Returns the U256 absolute value and a boolean indicating if negative + #[inline] + #[must_use] + pub fn to_u256_with_sign(self) -> (U256, bool) { + (self.value.to_u256(), self.negative) + } +} + +// Conversions from various types to SignedElement + +impl From for SignedElement { + fn from(value: Element) -> Self { + Self::new(value, false) + } +} + +impl From for SignedElement { + fn from(value: u64) -> Self { + Self::new(Element::new(value), false) + } +} + +impl From for SignedElement { + fn from(value: i64) -> Self { + if value < 0 { + Self::new(Element::new(value.unsigned_abs()), true) + } else { + Self::new(Element::new(value.unsigned_abs()), false) + } + } +} + +// Arithmetic operations + +impl Neg for SignedElement { + type Output = Self; + + fn neg(self) -> Self::Output { + if self.is_zero() { + self + } else { + Self::new(self.value, !self.negative) + } + } +} + +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + if self.negative == rhs.negative { + // Same sign, add values and keep the sign + Self::new(self.value + rhs.value, self.negative) + } else { + // Different signs, subtract the smaller from the larger + match self.value.cmp(&rhs.value) { + std::cmp::Ordering::Equal => Self::ZERO, + std::cmp::Ordering::Greater => Self::new(self.value - rhs.value, self.negative), + std::cmp::Ordering::Less => Self::new(rhs.value - self.value, rhs.negative), + } + } + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + self + (-rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + // Multiply absolute values, XOR the signs + Self::new(self.value * rhs.value, self.negative != rhs.negative) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + // Divide absolute values, XOR the signs + assert!(!rhs.is_zero(), "Division by zero"); + Self::new(self.value / rhs.value, self.negative != rhs.negative) + } +} + +// Implement operations with Element operands + +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: Element) -> Self::Output { + self + Self::from(rhs) + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: Element) -> Self::Output { + self - Self::from(rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: Element) -> Self::Output { + self * Self::from(rhs) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: Element) -> Self::Output { + self / Self::from(rhs) + } +} + +// Implement operations with primitive types +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: u64) -> Self::Output { + self + Self::from(rhs) + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: u64) -> Self::Output { + self - Self::from(rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: u64) -> Self::Output { + self * Self::from(rhs) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: u64) -> Self::Output { + self / Self::from(rhs) + } +} + +// Implement operations with i64 +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: i64) -> Self::Output { + self + Self::from(rhs) + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: i64) -> Self::Output { + self - Self::from(rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: i64) -> Self::Output { + self * Self::from(rhs) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: i64) -> Self::Output { + self / Self::from(rhs) + } +} + +// Display implementation +impl std::fmt::Display for SignedElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.negative { + write!(f, "-{}", self.value) + } else { + write!(f, "{}", self.value) + } + } +} + +// Implement PartialEq for primitive types +impl PartialEq for SignedElement { + fn eq(&self, other: &Element) -> bool { + !self.negative && self.value == *other + } +} + +impl PartialEq for SignedElement { + fn eq(&self, other: &u64) -> bool { + !self.negative && self.value == *other + } +} + +impl PartialEq for SignedElement { + fn eq(&self, other: &i64) -> bool { + if *other < 0 { + // Convert negative i64 to positive u64 safely using unsigned_abs() instead of casting + self.negative && self.value == Element::new(other.unsigned_abs()) + } else { + // For non-negative values, explicitly create from non-negative i64 + // This should never fail since we've verified other >= 0 + let Ok(u64_value) = u64::try_from(*other) else { + // This branch should be unreachable - i64::MAX is well within u64 range + panic!("Failed to convert non-negative i64 {other} to u64"); + }; + !self.negative && self.value == Element::new(u64_value) + } + } +} + +// Implement a few more utility methods +impl SignedElement { + /// Tries to convert this SignedElement to an i64 + /// + /// Returns None if the value doesn't fit in an i64 + #[must_use] + pub fn to_i64(&self) -> Option { + if self.value > Element::new(i64::MAX as u64) { + None + } else { + // First convert to u64 + let unsigned_val = self.value.to_u256().as_u64(); + + // Check if it can fit in i64 before conversion + if !self.negative && unsigned_val > i64::MAX as u64 { + None + } else { + // We've verified the value fits in i64, so conversion should never fail + let Ok(signed_value) = i64::try_from(unsigned_val) else { + // This should be unreachable given our checks + panic!("Failed to convert u64 {unsigned_val} to i64 despite being in range"); + }; + + Some(if self.negative { + -signed_value + } else { + signed_value + }) + } + } + } + + /// Checks if this SignedElement represents a value that fits in an i64 + #[must_use] + pub fn fits_in_i64(&self) -> bool { + self.to_i64().is_some() + } +} + +// Implement PartialOrd for SignedElement +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// Implement Ord for SignedElement +impl Ord for SignedElement { + fn cmp(&self, other: &Self) -> Ordering { + match (self.negative, other.negative) { + // Both positive (or zero): compare normally + (false, false) => self.value.cmp(&other.value), + + // Both negative: larger absolute value is smaller + (true, true) => other.value.cmp(&self.value), + + // Self negative, other positive (or zero): self is less + (true, false) => Ordering::Less, + + // Self positive (or zero), other negative: self is greater + (false, true) => Ordering::Greater, + } + } +} + +// Implement PartialOrd with Element +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &Element) -> Option { + if self.negative { + // Any negative number is less than any Element (which is unsigned) + Some(Ordering::Less) + } else { + // Positive SignedElement: compare values normally + Some(self.value.cmp(other)) + } + } +} + +// Implement PartialOrd with u64 +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &u64) -> Option { + if self.negative { + // Any negative number is less than any u64 + Some(Ordering::Less) + } else { + // Positive SignedElement: compare values normally + let other_element = Element::from(*other); + Some(self.value.cmp(&other_element)) + } + } +} + +// Implement PartialOrd with i64 +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &i64) -> Option { + if *other < 0 { + // Compare with negative i64 + if self.negative { + // Both negative, compare absolute values (reversed) + // For negative numbers, the one with the larger absolute value is smaller + // -15 > -25 because 15 < 25 + let other_abs = other.unsigned_abs(); + let self_abs = self.value.to_u256().as_u64(); + + // Here we compare self_abs with other_abs, and then reverse the result + // because larger absolute value means smaller negative number + Some(self_abs.cmp(&other_abs).reverse()) + } else { + // Self positive, other negative: self is greater + Some(Ordering::Greater) + } + } else { + // Compare with non-negative i64 + if self.negative { + // Self negative, other non-negative: self is less + Some(Ordering::Less) + } else { + // Both non-negative: normal comparison + // This conversion should never fail since we've checked other >= 0 + let Ok(u64_other) = u64::try_from(*other) else { + // This branch should be unreachable - i64::MAX is well within u64 range + panic!("Failed to convert non-negative i64 {other} to u64"); + }; + let other_element = Element::from(u64_other); + Some(self.value.cmp(&other_element)) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_basic_operations() { + // Test addition with same signs + let a = SignedElement::from(5i64); + let b = SignedElement::from(3i64); + assert_eq!(a + b, SignedElement::from(8i64)); + assert!((a + b).is_positive()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a + b, SignedElement::from(-8i64)); + assert!((a + b).is_negative()); + + // Test addition with different signs + let a = SignedElement::from(5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a + b, SignedElement::from(2i64)); + assert!((a + b).is_positive()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(3i64); + assert_eq!(a + b, SignedElement::from(-2i64)); + assert!((a + b).is_negative()); + + // Test subtraction + let a = SignedElement::from(5i64); + let b = SignedElement::from(3i64); + assert_eq!(a - b, SignedElement::from(2i64)); + assert!((a - b).is_positive()); + + let a = SignedElement::from(3i64); + let b = SignedElement::from(5i64); + assert_eq!(a - b, SignedElement::from(-2i64)); + assert!((a - b).is_negative()); + + // Test multiplication + let a = SignedElement::from(5i64); + let b = SignedElement::from(3i64); + assert_eq!(a * b, SignedElement::from(15i64)); + assert!((a * b).is_positive()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(3i64); + assert_eq!(a * b, SignedElement::from(-15i64)); + assert!((a * b).is_negative()); + + let a = SignedElement::from(5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a * b, SignedElement::from(-15i64)); + assert!((a * b).is_negative()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a * b, SignedElement::from(15i64)); + assert!((a * b).is_positive()); + + // Test division + let a = SignedElement::from(15i64); + let b = SignedElement::from(3i64); + assert_eq!(a / b, SignedElement::from(5i64)); + assert!((a / b).is_positive()); + + let a = SignedElement::from(-15i64); + let b = SignedElement::from(3i64); + assert_eq!(a / b, SignedElement::from(-5i64)); + assert!((a / b).is_negative()); + + let a = SignedElement::from(15i64); + let b = SignedElement::from(-3i64); + assert_eq!(a / b, SignedElement::from(-5i64)); + assert!((a / b).is_negative()); + + let a = SignedElement::from(-15i64); + let b = SignedElement::from(-3i64); + assert_eq!(a / b, SignedElement::from(5i64)); + assert!((a / b).is_positive()); + } + + #[test] + fn test_sign_operations() { + let a = SignedElement::from(5i64); + assert!(!a.is_negative()); + assert!(a.is_positive()); + assert!(!a.is_zero()); + + let a = SignedElement::from(-5i64); + assert!(a.is_negative()); + assert!(!a.is_positive()); + assert!(!a.is_zero()); + + let a = SignedElement::ZERO; + assert!(!a.is_negative()); + assert!(!a.is_positive()); + assert!(a.is_zero()); + + // Test negation + let a = SignedElement::from(5i64); + assert_eq!(-a, SignedElement::from(-5i64)); + + let a = SignedElement::from(-5i64); + assert_eq!(-a, SignedElement::from(5i64)); + + let a = SignedElement::ZERO; + assert_eq!(-a, SignedElement::ZERO); + } + + #[test] + fn test_signum() { + let a = SignedElement::from(5i64); + assert_eq!(a.signum(), SignedElement::ONE); + + let a = SignedElement::from(-5i64); + assert_eq!(a.signum(), SignedElement::NEG_ONE); + + let a = SignedElement::ZERO; + assert_eq!(a.signum(), SignedElement::ZERO); + } + + #[test] + fn test_large_numbers() { + // Create elements with large values near U256 limits + let max_element = Element::MAX; + + // Create large elements using U256 values + let large_u256 = U256::from_str_radix( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0", + 16, + ) + .unwrap(); + let large_element = Element::from(large_u256); + + // Create signed elements with these large values + let pos_max = SignedElement::new(max_element, false); + let neg_max = SignedElement::new(max_element, true); + let pos_large = SignedElement::new(large_element, false); + let neg_large = SignedElement::new(large_element, true); + + // Test signs are preserved + assert!(!pos_max.is_negative()); + assert!(neg_max.is_negative()); + assert!(!pos_large.is_negative()); + assert!(neg_large.is_negative()); + + // Test negation of large values + assert_eq!(-pos_max, neg_max); + assert_eq!(-neg_max, pos_max); + + // Test addition with large numbers + let small = SignedElement::from(1u64); + + // Addition with small numbers + let result = pos_large + small; + assert!(!result.is_negative()); + + // Addition with opposite signs + let result = pos_large + neg_small(); + assert!(!result.is_negative()); + + let result = neg_large + small; + assert!(result.is_negative()); + + // Test multiplication with sign changes + let result = pos_large * SignedElement::NEG_ONE; + assert!(result.is_negative()); + assert_eq!(result.value, large_element); + + let result = neg_large * SignedElement::NEG_ONE; + assert!(!result.is_negative()); + assert_eq!(result.value, large_element); + } + + // Helper function for a small negative number + fn neg_small() -> SignedElement { + SignedElement::new(Element::ONE, true) + } + + #[test] + fn test_large_number_sign_preservation() { + // Create a more moderate large value that won't overflow + let large_value = Element::from( + U256::from_str_radix( + "8000000000000000000000000000000000000000000000000000000000000000", + 16, + ) + .unwrap(), + ); + + // Test positive large value + let pos_large = SignedElement::new(large_value, false); + assert!(!pos_large.is_negative()); + assert!(pos_large.is_positive()); + + // Test negative large value + let neg_large = SignedElement::new(large_value, true); + assert!(neg_large.is_negative()); + assert!(!neg_large.is_positive()); + + // Test negation preserves absolute value + assert_eq!(-pos_large, neg_large); + assert_eq!(-neg_large, pos_large); + + // Test addition with small number + let small = SignedElement::from(10u64); + + // Adding small to positive large + let result = pos_large + small; + assert!(!result.is_negative()); + + // Adding small to negative large + let result = neg_large + small; + // Should still be negative since |large| > |small| + assert!(result.is_negative()); + + // Test subtraction with small number + let result = pos_large - small; + // Still positive + assert!(!result.is_negative()); + + let result = neg_large - small; + // Still negative and absolute value increased + assert!(result.is_negative()); + + // Test with reasonable multiplication + let small_multiplier = SignedElement::from(2u64); + + let result = pos_large / small_multiplier; + assert!(!result.is_negative()); + + let result = neg_large / small_multiplier; + assert!(result.is_negative()); + + // Test with sign-changing multiplication + let neg_one = SignedElement::from(-1i64); + + let result = pos_large * neg_one; + assert!(result.is_negative()); + + let result = neg_large * neg_one; + assert!(!result.is_negative()); + } + + #[test] + fn test_safe_arithmetic() { + // Test with values that won't overflow + let a = SignedElement::from(i64::MAX); + let b = SignedElement::from(i64::MIN); + + // Test negation + assert_eq!(-a, SignedElement::from(-i64::MAX)); + // Note: -i64::MIN would overflow in i64, but works in our bigger type + assert!(!(-b).is_negative()); + + // Test addition + let result = a + a; + assert!(!result.is_negative()); + + let result = b + b; + assert!(result.is_negative()); + + // Test subtraction + let result = a - b; + assert!(!result.is_negative()); + + // Test multiplication + let result = a * SignedElement::from(2i64); + assert!(!result.is_negative()); + + let result = b * SignedElement::from(2i64); + assert!(result.is_negative()); + + let result = a * SignedElement::from(-1i64); + assert!(result.is_negative()); + + let result = b * SignedElement::from(-1i64); + assert!(!result.is_negative()); + + // Test with values that could overflow i64 but are fine for Element + let big_positive = SignedElement::from(u64::MAX); + let big_negative = SignedElement::new(Element::from(u64::MAX), true); + + assert!(!big_positive.is_negative()); + assert!(big_negative.is_negative()); + + // Test sign preservation with division + let result = big_positive / SignedElement::from(2u64); + assert!(!result.is_negative()); + + let result = big_negative / SignedElement::from(2u64); + assert!(result.is_negative()); + + // Test sign flipping with division + let result = big_positive / SignedElement::from(-2i64); + assert!(result.is_negative()); + + let result = big_negative / SignedElement::from(-2i64); + assert!(!result.is_negative()); + } + + #[test] + fn test_comparison_operators() { + // Test comparisons between SignedElements with different signs + let pos = SignedElement::from(5i64); + let neg = SignedElement::from(-5i64); + let zero = SignedElement::ZERO; + + // Positive vs Negative + assert!(pos > neg); + assert!(neg < pos); + assert!(pos >= neg); + assert!(neg <= pos); + assert!(pos != neg); + + // Zero vs Positive/Negative + assert!(zero > neg); + assert!(zero < pos); + assert!(zero >= neg); + assert!(zero <= pos); + assert!(zero != pos); + assert!(zero != neg); + + // Test comparisons between SignedElements with the same sign + let pos_small = SignedElement::from(3i64); + let pos_large = SignedElement::from(10i64); + let neg_small = SignedElement::from(-3i64); + let neg_large = SignedElement::from(-10i64); + + // Positive comparisons + assert!(pos_large > pos_small); + assert!(pos_small < pos_large); + assert!(pos_large >= pos_small); + assert!(pos_small <= pos_large); + assert!(pos_large != pos_small); + + // Negative comparisons (larger absolute value is smaller) + assert!(neg_large < neg_small); + assert!(neg_small > neg_large); + assert!(neg_large <= neg_small); + assert!(neg_small >= neg_large); + assert!(neg_large != neg_small); + + // Equal values + let pos_equal1 = SignedElement::from(7i64); + let pos_equal2 = SignedElement::from(7i64); + let neg_equal1 = SignedElement::from(-7i64); + let neg_equal2 = SignedElement::from(-7i64); + + assert_eq!(pos_equal1, pos_equal2); + assert!(pos_equal1 >= pos_equal2); + assert!(pos_equal1 <= pos_equal2); + assert!(pos_equal1 <= pos_equal2); + assert!(pos_equal1 >= pos_equal2); + + assert_eq!(neg_equal1, neg_equal2); + assert!(neg_equal1 >= neg_equal2); + assert!(neg_equal1 <= neg_equal2); + assert!(neg_equal1 <= neg_equal2); + assert!(neg_equal1 >= neg_equal2); + + // Test comparisons with Element + let pos_elem = SignedElement::from(15i64); + let neg_elem = SignedElement::from(-15i64); + let elem = Element::new(15); + + assert!(pos_elem == elem); + assert!(neg_elem < elem); + assert!(neg_elem <= elem); + assert!(pos_elem >= elem); + assert!(pos_elem >= elem); + assert!(pos_elem <= elem); + + // Test comparisons with u64 + let u64_val = 20u64; + let pos_u64 = SignedElement::from(20i64); + let equal_u64 = SignedElement::from(20i64); + let neg_u64 = SignedElement::from(-20i64); + let smaller_u64 = SignedElement::from(10i64); + let larger_u64 = SignedElement::from(30i64); + + assert!(pos_u64 == u64_val); + assert!(equal_u64 == u64_val); + assert!(neg_u64 < u64_val); + assert!(smaller_u64 < u64_val); + assert!(larger_u64 > u64_val); + + // Test comparisons with i64 + let i64_pos = 25i64; + let i64_neg = -25i64; + let equal_pos = SignedElement::from(25i64); + let equal_neg = SignedElement::from(-25i64); + let smaller_pos = SignedElement::from(15i64); + let smaller_neg = SignedElement::from(-15i64); + let larger_pos = SignedElement::from(35i64); + let larger_neg = SignedElement::from(-35i64); + + // Compare with positive i64 + assert!(equal_pos == i64_pos); + assert!(equal_neg < i64_pos); + assert!(smaller_pos < i64_pos); + assert!(larger_pos > i64_pos); + + // Compare with negative i64 + assert!(equal_neg == i64_neg); + assert!(equal_pos > i64_neg); + assert!(smaller_neg > i64_neg); // -15 > -25 + assert!(larger_neg < i64_neg); // -35 < -25 + } +} diff --git a/pkg/encrypt/Cargo.toml b/pkg/encrypt/Cargo.toml new file mode 100644 index 0000000..ccc1878 --- /dev/null +++ b/pkg/encrypt/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "encrypt" +version = "0.1.0" +edition = "2024" + +[dependencies] + +thiserror = { workspace = true } +crypto_secretbox = { workspace = true } +x25519-dalek = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/encrypt/README.md b/pkg/encrypt/README.md new file mode 100644 index 0000000..8404020 --- /dev/null +++ b/pkg/encrypt/README.md @@ -0,0 +1,32 @@ +# Encrypt + +Cryptographic operations using XSalsa20-Poly1305 and X25519 for secure data encryption. + +## Overview + +This package provides authenticated encryption functionality using modern cryptographic primitives. It implements both symmetric and asymmetric encryption schemes with a versioned data format for storage and transmission. + +## Encryption Algorithms + +### Symmetric Encryption +- **Algorithm**: XSalsa20-Poly1305 +- **Authentication**: Built-in AEAD (Authenticated Encryption with Associated Data) +- **Nonce size**: 24 bytes (automatically generated) +- **Key size**: 32 bytes + +### Asymmetric Encryption +- **Key Exchange**: X25519 (Curve25519 Diffie-Hellman) +- **Encryption**: XSalsa20-Poly1305 +- **Ephemeral keys**: Generated per encryption for forward secrecy +- **Authentication**: Built-in AEAD + +## Features + +- **Symmetric encryption/decryption** with XSalsa20-Poly1305 +- **Asymmetric encryption/decryption** with X25519-XSalsa20-Poly1305 +- **Automatic nonce generation** for each encryption operation +- **Versioned data format** for backward compatibility +- **Key generation utilities** for both symmetric and asymmetric keys +- **Compact serialization** for encrypted data storage +- **Error handling** for all cryptographic operations + diff --git a/pkg/encrypt/src/asymmetric.rs b/pkg/encrypt/src/asymmetric.rs new file mode 100644 index 0000000..5b2acf1 --- /dev/null +++ b/pkg/encrypt/src/asymmetric.rs @@ -0,0 +1,129 @@ +use crate::{EPHEMERAL_PUBLIC_KEY_SIZE, Error, NONCE_SIZE, Result, VERSION, util::to_array_32}; +use crypto_secretbox::{ + Key, Nonce, XSalsa20Poly1305, + aead::{Aead, AeadCore, KeyInit, OsRng}, +}; +use x25519_dalek::{EphemeralSecret, PublicKey, StaticSecret}; + +/// Asymmetric encrypted data ready for storage/exchange. Can be decrypted with only the corrosponding +/// public key +#[derive(Debug)] +pub struct EncryptedAsymmetricData { + /// Nonce required for randomness + pub nonce: Vec, + /// Emphemeral public key from the other ser + pub ephemeral_public_key: Vec, + /// Cipher text of encrypted data + pub ciphertext: Vec, +} + +impl EncryptedAsymmetricData { + /// Converts encryption into the compact data format (i.e. to be stored) + #[must_use] + pub fn to_bytes(&self) -> Vec { + let combined = Vec::with_capacity( + 1 + self.nonce.len() + self.ephemeral_public_key.len() + self.ciphertext.len(), + ); + let mut result = combined; + + // Add version + result.push(VERSION); + + // Add nonce + result.extend_from_slice(&self.nonce); + + // Add ephemeral public key + result.extend_from_slice(&self.ephemeral_public_key); + + // Add ciphertext + result.extend_from_slice(&self.ciphertext); + + result + } + + /// Creates new asymmetric data struct from bytes (i.e. from storage) + pub fn from_bytes(bytes: &[u8]) -> Result { + // Check if the data has at least enough bytes for version, nonce, and ephemeral public key + if bytes.len() < 1 + NONCE_SIZE + EPHEMERAL_PUBLIC_KEY_SIZE { + Err(Error::InvalidDataLength( + 1 + NONCE_SIZE + EPHEMERAL_PUBLIC_KEY_SIZE, + bytes.len(), + ))?; + } + + // Read version + let version = bytes[0]; + + // Assert version is 1 + if version != VERSION { + return Err(Error::InvalidVersion(VERSION, version)); + } + + // Extract nonce (bytes 1 to 1+NONCE_SIZE) + let nonce = bytes[1..=NONCE_SIZE].to_vec(); + + // Extract ephemeral public key (bytes 1+NONCE_SIZE to 1+NONCE_SIZE+EPHEMERAL_PUBLIC_KEY_SIZE) + let ephemeral_public_key = + bytes[1 + NONCE_SIZE..1 + NONCE_SIZE + EPHEMERAL_PUBLIC_KEY_SIZE].to_vec(); + + // Extract ciphertext (remaining bytes) + let ciphertext = bytes[1 + NONCE_SIZE + EPHEMERAL_PUBLIC_KEY_SIZE..].to_vec(); + + Ok(Self { + nonce, + ephemeral_public_key, + ciphertext, + }) + } +} + +/// Encrypts data asymmetrically using X25519-XSalsa20-Poly1305 +pub fn asymmetric_encrypt(public_key: &PublicKey, data: &[u8]) -> Result { + // Generate ephemeral keypair + let ephemeral_secret = EphemeralSecret::random_from_rng(OsRng); + let ephemeral_public = PublicKey::from(&ephemeral_secret); + + // Perform Diffie-Hellman + let shared_secret = ephemeral_secret.diffie_hellman(public_key); + + // Generate random nonce + let nonce = XSalsa20Poly1305::generate_nonce(&mut OsRng); + + // Encrypt with XSalsa20Poly1305 + let key = Key::from_slice(shared_secret.as_bytes()); + let cipher = XSalsa20Poly1305::new(key); + let ciphertext = cipher + .encrypt(&nonce, data.as_ref()) + .map_err(Error::EncryptFailed)?; + + Ok(EncryptedAsymmetricData { + nonce: nonce.to_vec(), + ephemeral_public_key: ephemeral_public.as_bytes().to_vec(), + ciphertext, + }) +} + +/// Decrypts data asymmetrically using X25519-XSalsa20-Poly1305 +pub fn asymmetric_decrypt( + secret_key: &StaticSecret, + encrypted: &EncryptedAsymmetricData, +) -> Result> { + // Convert sender public key + let sender_public_array = to_array_32(&encrypted.ephemeral_public_key)?; + let sender_public = PublicKey::from(sender_public_array); + + // Perform Diffie-Hellman + let shared_secret = secret_key.diffie_hellman(&sender_public); + + // Convert nonce + let nonce = Nonce::from_slice(&encrypted.nonce); + + // Decrypt with XSalsa20Poly1305 + let key = Key::from_slice(shared_secret.as_bytes()); + let cipher = XSalsa20Poly1305::new(key); + let plaintext = cipher + .decrypt(nonce, encrypted.ciphertext.as_slice()) + .map_err(Error::DecryptFailed)?; + + Ok(plaintext) +} diff --git a/pkg/encrypt/src/error.rs b/pkg/encrypt/src/error.rs new file mode 100644 index 0000000..0a889e5 --- /dev/null +++ b/pkg/encrypt/src/error.rs @@ -0,0 +1,24 @@ +use crypto_secretbox::aead; + +/// Result for encrypt/decrypt +pub type Result = std::result::Result; + +/// Error for encrypt/decrypt +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// Invalid encrypt data version + #[error("invalid version, expected {0} got {1}")] + InvalidVersion(u8, u8), + /// Data length is not long enough + #[error("data is not long enough to conver to encryped data, expected {0} got {0}")] + InvalidDataLength(usize, usize), + /// Key length is invalid size + #[error("invalid key length, expected {0} got {1}")] + InvalidKeyLength(usize, usize), + /// Encryption failed + #[error("encrypt failed")] + EncryptFailed(aead::Error), + /// Decryption failed + #[error("decrypt failed")] + DecryptFailed(aead::Error), +} diff --git a/pkg/encrypt/src/lib.rs b/pkg/encrypt/src/lib.rs new file mode 100644 index 0000000..12deae8 --- /dev/null +++ b/pkg/encrypt/src/lib.rs @@ -0,0 +1,25 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::match_bool)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::doc_markdown)] +#![deny(missing_docs)] + +//! Simple data format for working with encrypted data +//! +mod asymmetric; +mod error; +mod symmetric; +mod util; + +pub use asymmetric::*; +pub use error::*; +pub use symmetric::*; + +pub use crypto_secretbox::Key; +pub use x25519_dalek::{PublicKey, StaticSecret}; + +const VERSION: u8 = 1; +const NONCE_SIZE: usize = 24; +const EPHEMERAL_PUBLIC_KEY_SIZE: usize = 32; diff --git a/pkg/encrypt/src/symmetric.rs b/pkg/encrypt/src/symmetric.rs new file mode 100644 index 0000000..fa7b7b4 --- /dev/null +++ b/pkg/encrypt/src/symmetric.rs @@ -0,0 +1,97 @@ +use crate::{Error, NONCE_SIZE, Result, VERSION}; +use crypto_secretbox::{ + Key, Nonce, XSalsa20Poly1305, + aead::{Aead, AeadCore, KeyInit, OsRng}, +}; + +/// Encrypt symmetric data +#[derive(Debug)] +pub struct EncryptedSymmetricData { + /// Nonce for randomness (every encryption should have a new randomness to protect the + /// security properties of the underlying key) + pub nonce: Vec, + /// Encrypted data bytes + pub ciphertext: Vec, +} + +impl EncryptedSymmetricData { + /// Converts encrypted data into compact byte form + #[must_use] + pub fn to_bytes(&self) -> Vec { + let combined = Vec::with_capacity(1 + self.nonce.len() + self.ciphertext.len()); + let mut result = combined; + + // Add version + result.push(VERSION); + + // Add nonce + result.extend_from_slice(&self.nonce); + + // Add ciphertext + result.extend_from_slice(&self.ciphertext); + + result + } + + /// Restores encrypted data from compact byte form + pub fn from_bytes(bytes: &[u8]) -> Result { + // Check if the data has at least enough bytes for version and nonce + if bytes.len() < 1 + NONCE_SIZE { + Err(Error::InvalidDataLength(1 + NONCE_SIZE, bytes.len()))?; + } + + // Read version + let version = bytes[0]; + + // Assert version is 1 + if version != VERSION { + return Err(Error::InvalidVersion(VERSION, version))?; + } + + // Extract nonce (bytes 1 to 1+NONCE_SIZE) + let nonce = bytes[1..=NONCE_SIZE].to_vec(); + + // Extract ciphertext (remaining bytes) + let ciphertext = bytes[1 + NONCE_SIZE..].to_vec(); + + Ok(Self { nonce, ciphertext }) + } +} + +/// Encrypts data symmetrically using XSalsa20Poly1305 +pub fn symmetric_encrypt(key: &Key, data: &[u8]) -> Result { + // Generate random nonce + let nonce = XSalsa20Poly1305::generate_nonce(&mut OsRng); + + // Encrypt with XSalsa20Poly1305 + // let key = Key::from_slice(key_bytes); + let cipher = XSalsa20Poly1305::new(key); + let ciphertext = cipher + .encrypt(&nonce, data.as_ref()) + .map_err(Error::EncryptFailed)?; + + Ok(EncryptedSymmetricData { + nonce: nonce.to_vec(), + ciphertext, + }) +} + +/// Decrypts data symmetrically using XSalsa20Poly1305 +pub fn symmetric_decrypt(key: &Key, encrypted: &EncryptedSymmetricData) -> Result> { + // Convert nonce + let nonce = Nonce::from_slice(&encrypted.nonce); + + // Decrypt with XSalsa20Poly1305 + let cipher = XSalsa20Poly1305::new(key); + let plaintext = cipher + .decrypt(nonce, encrypted.ciphertext.as_slice()) + .map_err(Error::DecryptFailed)?; + + Ok(plaintext) +} + +/// Generates a new random symmetric key +pub fn generate_symmetric_key() -> Key { + // Generate a random key for XSalsa20Poly1305 + XSalsa20Poly1305::generate_key(&mut OsRng) +} diff --git a/pkg/encrypt/src/util.rs b/pkg/encrypt/src/util.rs new file mode 100644 index 0000000..59a96a5 --- /dev/null +++ b/pkg/encrypt/src/util.rs @@ -0,0 +1,12 @@ +use crate::{Error, Result}; + +/// Converts a slice to a 32-byte array +pub(crate) fn to_array_32(slice: &[u8]) -> Result<[u8; 32]> { + if slice.len() != 32 { + return Err(Error::InvalidKeyLength(32, slice.len())); + } + + let mut array = [0u8; 32]; + array.copy_from_slice(slice); + Ok(array) +} diff --git a/pkg/eth-util/Cargo.toml b/pkg/eth-util/Cargo.toml new file mode 100644 index 0000000..db35c46 --- /dev/null +++ b/pkg/eth-util/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "eth-util" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } +sha3 = { workspace = true } +secp256k1 = { workspace = true } +ethereum-types = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/eth-util/README.md b/pkg/eth-util/README.md new file mode 100644 index 0000000..611183f --- /dev/null +++ b/pkg/eth-util/README.md @@ -0,0 +1,15 @@ +# Ethereum Utilities + +Ethereum utilities and helper functions. + +## Overview + +This package provides utility functions and helpers for Ethereum integration. + +## Features + +- Ethereum address utilities +- Transaction helpers +- Gas estimation +- Web3 integration utilities + diff --git a/pkg/eth-util/src/lib.rs b/pkg/eth-util/src/lib.rs new file mode 100644 index 0000000..8a109d3 --- /dev/null +++ b/pkg/eth-util/src/lib.rs @@ -0,0 +1,61 @@ +use element::Element; +use ethereum_types::{Address, H160, H256, U256}; +use secp256k1::{PublicKey, Secp256k1, SecretKey}; +use sha3::{Digest, Keccak256}; + +pub trait Eth { + fn to_secp256k1_secret_key(&self) -> SecretKey; + fn to_eth_address(&self) -> Address; + fn from_160(h160: &H160) -> Self; + fn to_h256(&self) -> H256; + fn from_u256(u256: U256) -> Self; + fn to_eth_u256(&self) -> U256; +} + +impl Eth for Element { + fn to_secp256k1_secret_key(&self) -> SecretKey { + SecretKey::from_slice(&self.to_be_bytes()).expect("secret key must be random") + } + + fn to_eth_address(&self) -> Address { + secret_key_to_address(&self.to_secp256k1_secret_key()) + } + + fn from_160(h160: &H160) -> Element { + let mut h256 = [0u8; 32]; + h256[12..32].copy_from_slice(&h160.0); + Element::from_be_bytes(h256) + } + + fn to_h256(&self) -> H256 { + H256::from_slice(self.to_be_bytes().as_slice()) + } + + fn from_u256(u256: U256) -> Self { + Self::from_u64_array(u256.0) + } + + fn to_eth_u256(&self) -> U256 { + ethereum_types::U256(self.to_u64_array()) + } +} + +pub fn secret_key_to_address(secret_key: &SecretKey) -> Address { + // Create a secp256k1 context + let secp = Secp256k1::new(); + + // Derive public key from private key + let public_key = PublicKey::from_secret_key(&secp, secret_key); + + // Serialize the public key in uncompressed format + let public_key_serialized = public_key.serialize_uncompressed(); + + // Hash the public key using Keccak-256 (skip the first byte which is the format byte) + let public_key_hash = Keccak256::digest(&public_key_serialized[1..]); + + // Take the last 20 bytes of the hash to get the Ethereum address + let mut address_bytes = [0u8; 20]; + address_bytes.copy_from_slice(&public_key_hash[12..32]); + + Address::from(address_bytes) +} diff --git a/pkg/guild-client-http/Cargo.toml b/pkg/guild-client-http/Cargo.toml new file mode 100644 index 0000000..27b6add --- /dev/null +++ b/pkg/guild-client-http/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "guild-client-http" +version = "0.1.0" +edition = "2024" + +[dependencies] +guild-interface = { workspace = true } +client-http = { workspace = true } +client-http-longpoll = { workspace = true } +http-interface = { workspace = true } +rpc = { workspace = true } +element = { workspace = true } +ramps-interface = { workspace = true } +zk-circuits = { workspace = true } +zk-primitives = { workspace = true } +contextful = { workspace = true } + +async-trait = { workspace = true } +chrono = { workspace = true } +reqwest = { workspace = true } +parking_lot = { workspace = true } +thiserror = { workspace = true } +uuid = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +tokio = { workspace = true, features = ["rt", "macros"] } diff --git a/pkg/guild-client-http/README.md b/pkg/guild-client-http/README.md new file mode 100644 index 0000000..98b03c4 --- /dev/null +++ b/pkg/guild-client-http/README.md @@ -0,0 +1,50 @@ +# Guild Client HTTP + +HTTP client for interacting with guild services. + +## Overview + +This package provides a specialized HTTP client for communicating with the Guild application server. + +## Features + +- Guild service API client +- Authentication handling +- Wallet operations +- Note management +- Ramps integration + +## Dependency Injection + +The client now accepts any implementation of the shared +[`HttpClient`](../http-interface/src/client.rs) trait. This enables +swapping the underlying HTTP behaviour for tests or alternative runtimes. + +```rust +use guild_client_http::GuildClientHttp; + +#[derive(Clone)] +struct RecordingHttp { /* implements HttpClient */ } + +let http = RecordingHttp::new(); +let client = GuildClientHttp::with_http_client(http.clone()); + +// Exercise client methods with the injected HTTP implementation. +``` + +When working against the dynamic `HttpClient` trait, payloads are wrapped in +`client_http::HttpBody` so they can be cloned for retries. For example: + +```rust +use client_http::HttpBody; + +guild_client + .http_client + .post("/wallets/me/activity", Some(HttpBody::json(&payload))) + .auth() + .exec() + .await?; +``` + +See `tests/http_client_swapping.rs` for a fully worked example that records +requests without performing network calls using a lightweight test double. diff --git a/pkg/guild-client-http/src/across.rs b/pkg/guild-client-http/src/across.rs new file mode 100644 index 0000000..beb18eb --- /dev/null +++ b/pkg/guild-client-http/src/across.rs @@ -0,0 +1,43 @@ +use client_http::HttpBody; +use guild_interface::across::{ + self, DepositV3WithAuthorizationInput, DepositV3WithAuthorizationOutput, +}; + +use crate::GuildClientHttp; + +/// Across error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Send across deposit request to Guild + pub async fn across_deposit( + &self, + request: &DepositV3WithAuthorizationInput, + ) -> Result { + self.http_client + .post( + "/crypto/across/deposit", + Some(HttpBody::json(request.clone())), + ) + .exec() + .await? + .to_value() + .await + } + + /// Get an Across quote from Guild + pub async fn get_across_quote( + &self, + request: &across::GetQuoteInput, + ) -> Result { + self.http_client + .post( + "/crypto/across/quote", + Some(HttpBody::json(request.clone())), + ) + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/guild-client-http/src/auth.rs b/pkg/guild-client-http/src/auth.rs new file mode 100644 index 0000000..0d6c0e5 --- /dev/null +++ b/pkg/guild-client-http/src/auth.rs @@ -0,0 +1,155 @@ +use std::{num::TryFromIntError, sync::Arc}; + +use client_http::{ + AuthError, ClientHttp, ClientHttpAuth, Error as HttpError, HttpBody, NoAuth, NoRpcError, +}; +use contextful::{Contextful, ResultContextExt}; +use element::Element; +use guild_interface::auth::{AuthRequest, AuthResponse}; +use http_interface::HttpMetadata; +use parking_lot::Mutex; +use reqwest::{ + Method, Url, + header::{AUTHORIZATION, HeaderMap, InvalidHeaderValue}, +}; +use thiserror::Error; +use zk_circuits::circuits::generated::signature::SignatureInput as CircuitSignatureInput; +use zk_circuits::{BbBackend, Prove}; +use zk_primitives::Signature; + +#[derive(Clone)] +pub struct GuildClientHttpAuth { + http_client: ClientHttp, + private_key: Element, + jwt: Arc>>, + bb_backend: Arc, +} + +#[async_trait::async_trait] +impl ClientHttpAuth for GuildClientHttpAuth { + async fn get_auth(&self) -> std::result::Result { + self.get_auth_headers() + .await + .map_err(|err| -> AuthError { err.into() }) + } + + async fn refresh_auth(&self) -> std::result::Result<(), AuthError> { + self.refresh_jwt() + .await + .context("refresh guild auth token") + .map_err(GuildAuthError::from) + .map_err(|err| -> AuthError { err.into() })?; + Ok(()) + } +} + +impl GuildClientHttpAuth { + pub fn new(base_url: Url, private_key: Element, bb_backend: Arc) -> Self { + Self { + http_client: ClientHttp::new(base_url, HeaderMap::default(), NoAuth), + private_key, + jwt: Arc::new(Mutex::new(None)), + bb_backend, + } + } + + /// Get the auth headers to be passed to the request + pub(crate) async fn get_auth_headers(&self) -> Result { + let jwt = self.get_jwt().await?; + let mut headers = HeaderMap::new(); + let authorization = format!("Bearer {jwt}") + .parse() + .context("parse Authorization header value")?; + headers.insert(AUTHORIZATION, authorization); + Ok(headers) + } + + /// Get the cached auth token if it exists, otherwise request a fresh one + async fn get_jwt(&self) -> Result { + if let Some(jwt) = self.jwt.lock().clone() { + return Ok(jwt); + } + + self.refresh_jwt() + .await + .context("refresh jwt") + .map_err(GuildAuthError::from) + } + + /// Refresh the auth JWT and cache the result for future requests + async fn refresh_jwt(&self) -> Result { + let private_key = self.private_key; + + let timestamp = + u64::try_from(chrono::Utc::now().timestamp()).context("convert timestamp to u64")?; + + // Sign proof + let signature = Signature::new(private_key, Element::new(timestamp)); + let proof = CircuitSignatureInput::from(signature) + .prove(&*self.bb_backend) + .await + .map_err(|err| RefreshJwtError::ProofGeneration { + message: err.to_string(), + })?; + let proof = zk_primitives::SignatureProof::from(proof); + + let request = AuthRequest { proof }; + let response = self + .http_client + .post("/auth", Some(HttpBody::json(request))) + .exec::() + .await + .context("request auth token")?; + + let auth: AuthResponse = response + .to_value::() + .await + .context("parse auth response")?; + + *self.jwt.lock() = Some(auth.guild.clone()); + + Ok(auth.guild) + } +} + +#[allow(clippy::large_enum_variant)] +#[derive(Debug, Error)] +pub enum GuildAuthError { + #[error("[guild-client-http/auth] invalid authorization header: {0}")] + InvalidAuthorization(#[from] Contextful), + #[error("[guild-client-http/auth] refresh jwt: {0}")] + Refresh(#[from] Contextful), +} + +#[allow(clippy::large_enum_variant)] +#[derive(Debug, Error)] +pub enum RefreshJwtError { + #[error("[guild-client-http/auth] timestamp conversion: {0}")] + Timestamp(#[from] Contextful), + #[error("[guild-client-http/auth] proof generation: {message}")] + ProofGeneration { message: String }, + #[error("[guild-client-http/auth] http error: {0}")] + Http(#[from] Contextful>), +} + +fn auth_metadata(method: Method, path: &str) -> HttpMetadata { + HttpMetadata { + method, + path: path.to_owned(), + } +} + +impl From for AuthError { + fn from(err: GuildAuthError) -> Self { + match err { + GuildAuthError::InvalidAuthorization(inner) => HttpError::::GetAuth( + inner.to_string(), + auth_metadata(Method::GET, "/auth/headers"), + ), + GuildAuthError::Refresh(inner) => HttpError::::RefreshAuth( + inner.to_string(), + auth_metadata(Method::POST, "/auth"), + ), + } + } +} diff --git a/pkg/guild-client-http/src/bungee.rs b/pkg/guild-client-http/src/bungee.rs new file mode 100644 index 0000000..4234043 --- /dev/null +++ b/pkg/guild-client-http/src/bungee.rs @@ -0,0 +1,73 @@ +use client_http::HttpBody; +use guild_interface::bungee::{ + self, GetQuoteInput, GetQuoteOutput, GetStatusInput, GetStatusOutput, GetTokenListOutput, +}; + +use crate::GuildClientHttp; + +/// Bungee client methods +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Get a Bungee (Inbox) quote from Guild + pub async fn get_bungee_quote(&self, request: &GetQuoteInput) -> Result { + self.http_client + .post( + "/crypto/bungee/quote", + Some(HttpBody::json(request.clone())), + ) + .exec() + .await? + .to_value() + .await + } + + /// Retrieve the cached Bungee token list, scoped to the provided chain ids + pub async fn get_bungee_token_list( + &self, + chain_ids: &[u128], + ) -> Result { + let snapshot = if let Some(cached) = self.token_list_cache.lock().clone() { + cached + } else { + let tokens: GetTokenListOutput = self + .http_client + .get("/crypto/bungee/tokens") + .exec() + .await? + .to_value() + .await?; + *self.token_list_cache.lock() = Some(tokens.clone()); + tokens + }; + + if chain_ids.is_empty() { + return Ok(snapshot); + } + + let mut filtered = std::collections::BTreeMap::new(); + for &chain_id in chain_ids { + if let Some(tokens) = snapshot.tokens.get(&chain_id) { + filtered.insert(chain_id, tokens.clone()); + } + } + + Ok(GetTokenListOutput { tokens: filtered }) + } + + /// Fetch the latest status for a submitted Bungee bridge + pub async fn get_bungee_status( + &self, + request: &GetStatusInput, + ) -> Result { + let query = request.to_query_pairs().map_err(Error::Rpc)?; + + self.http_client + .get("/crypto/bungee/status") + .query(query) + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/guild-client-http/src/eip7702.rs b/pkg/guild-client-http/src/eip7702.rs new file mode 100644 index 0000000..aefb5e0 --- /dev/null +++ b/pkg/guild-client-http/src/eip7702.rs @@ -0,0 +1,41 @@ +use client_http::HttpBody; +use guild_interface::eip7702 as iface; + +use crate::GuildClientHttp; + +/// EIP-7702 error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Relay a SetCode (type 0x04) transaction using a signed authorization + pub async fn eip7702_relay_upgrade( + &self, + request: &iface::RelayUpgradeInput, + ) -> Result { + self.http_client + .post( + "/crypto/eip7702/relay-upgrade", + Some(HttpBody::json(request.clone())), + ) + .exec::() + .await? + .to_value::() + .await + } + + /// Relay a meta-transaction (executeMeta) + pub async fn eip7702_relay_meta( + &self, + request: &iface::RelayMetaInput, + ) -> Result { + self.http_client + .post( + "/crypto/eip7702/relay-meta", + Some(HttpBody::json(request.clone())), + ) + .exec::() + .await? + .to_value::() + .await + } +} diff --git a/pkg/guild-client-http/src/error.rs b/pkg/guild-client-http/src/error.rs new file mode 100644 index 0000000..edd4a0c --- /dev/null +++ b/pkg/guild-client-http/src/error.rs @@ -0,0 +1,5 @@ +/// Guild client error +pub type Error = client_http::Error; + +/// Guild client result +pub type Result = std::result::Result; diff --git a/pkg/guild-client-http/src/lib.rs b/pkg/guild-client-http/src/lib.rs new file mode 100644 index 0000000..8c8eb8b --- /dev/null +++ b/pkg/guild-client-http/src/lib.rs @@ -0,0 +1,84 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::match_bool)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::doc_markdown)] +#![deny(missing_docs)] + +//! HTTPS client for guild + +use auth::GuildClientHttpAuth; +use client_http::ClientHttp; +use element::Element; +use guild_interface::bungee::GetTokenListOutput; +pub use reqwest::Url; +use reqwest::header::HeaderMap; +use std::sync::Arc; +use zk_circuits::BbBackend; + +use http_interface::HttpClient; +use parking_lot::Mutex; +/// Across client methods +pub mod across; +/// Bungee client methods +pub mod bungee; + +mod auth; +/// EIP-7702 client methods +pub mod eip7702; +mod error; +/// Migration methods +pub mod migrate; +/// Mint client methods +pub mod mint; +/// Note client methods +pub mod note; +/// Ramps methods +pub mod ramps; +/// Registry client methods +pub mod registry; +/// Support methods +pub mod support; +/// Wallet methods +pub mod wallet; +/// Wallet activity methods +pub mod wallet_activity; +/// Wallet activity notes methods +pub mod wallet_notes; + +pub use error::{Error, Result}; + +/// Guild client for interacting with Guild server over HTTPS +#[derive(Clone)] +pub struct GuildClientHttp { + pub(crate) http_client: Arc, + pub(crate) token_list_cache: Arc>>, +} + +impl GuildClientHttp { + /// Create a new guild https client backed by the default HTTP implementation. + #[must_use] + pub fn new(base_url: Url, private_key: Element, bb_backend: Arc) -> Self { + let auth = GuildClientHttpAuth::new(base_url.clone(), private_key, bb_backend); + Self::with_http_client(ClientHttp::new(base_url, HeaderMap::default(), auth)) + } + + /// Construct a guild client with a pre-configured HTTP client implementation. + #[must_use] + pub fn with_http_client(http_client: C) -> Self + where + C: HttpClient + 'static, + { + Self::with_dyn_http_client(Arc::new(http_client)) + } + + /// Construct a guild client backed by a trait-object HTTP client. + #[must_use] + pub fn with_dyn_http_client(http_client: Arc) -> Self { + Self { + http_client, + token_list_cache: Arc::new(Mutex::new(None)), + } + } +} diff --git a/pkg/guild-client-http/src/migrate.rs b/pkg/guild-client-http/src/migrate.rs new file mode 100644 index 0000000..1d9a2e3 --- /dev/null +++ b/pkg/guild-client-http/src/migrate.rs @@ -0,0 +1,23 @@ +use client_http::{HttpBody, NoRpcError}; +use guild_interface::migrate::{MigrationNotesRequest, MigrationNotesResponse}; + +use crate::GuildClientHttp; + +/// Mint error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Send mint request to Guild + pub async fn migrate_notes( + &self, + request: &MigrationNotesRequest, + ) -> Result { + self.http_client + .post("/migrate/notes", Some(HttpBody::json(request.clone()))) + .auth() + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/guild-client-http/src/mint.rs b/pkg/guild-client-http/src/mint.rs new file mode 100644 index 0000000..7548b6a --- /dev/null +++ b/pkg/guild-client-http/src/mint.rs @@ -0,0 +1,19 @@ +use client_http::HttpBody; +use guild_interface::mint::{self, MintRequest, MintResponse}; + +use crate::GuildClientHttp; + +/// Mint error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Send mint request to Guild + pub async fn mint(&self, request: &MintRequest) -> Result { + self.http_client + .post("/mint/signed", Some(HttpBody::json(request.clone()))) + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/guild-client-http/src/note.rs b/pkg/guild-client-http/src/note.rs new file mode 100644 index 0000000..bc113bf --- /dev/null +++ b/pkg/guild-client-http/src/note.rs @@ -0,0 +1,86 @@ +use chrono::{DateTime, Utc}; +use client_http::{ClientResponse, serde_to_query_params}; +use client_http_longpoll::{LongPoll, LongPollPoller}; +use guild_interface::notes::{ + create::CreateNoteInput, list::ListNotesQuery, note::Note, request::NoteRequestInput, +}; +use rpc::longpoll::PollData; + +use crate::GuildClientHttp; +use client_http::HttpBody; + +/// Note error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Create a new note + pub async fn post_notes(&self, input: &CreateNoteInput) -> Result { + self.http_client + .post("/notes", Some(HttpBody::json(input.clone()))) + .auth() + .exec() + .await? + .to_value() + .await + } + + /// Request a note + pub async fn post_notes_request(&self, input: &NoteRequestInput) -> Result { + self.http_client + .post("/notes/request", Some(HttpBody::json(input.clone()))) + .auth() + .exec() + .await? + .to_value() + .await + } + + /// Get a list of the users notes + async fn list_notes_response(&self, query: &ListNotesQuery) -> Result { + self.http_client + .get("/notes") + .query(serde_to_query_params(query)) + .auth() + .exec() + .await + } + + /// Get a list of notes with long poll + #[must_use] + pub fn list_notes_long_poll(&self, query: &ListNotesQuery) -> LongPoll { + LongPoll::new(NotesLongPoll { + client: self.clone(), + query: query.clone(), + }) + } +} + +/// Long poll handler for notes +/// +/// This struct encapsulates the client and query parameters needed to perform +/// long polling operations on notes, allowing for real-time updates when notes change. +pub struct NotesLongPoll { + client: GuildClientHttp, + query: ListNotesQuery, +} + +#[async_trait::async_trait] +impl LongPollPoller for NotesLongPoll { + type Error = Error; + type T = Vec; + + async fn poll( + &self, + last_modified: Option>, + ) -> Result, Self::Error> { + self.client + .list_notes_response(&ListNotesQuery { + after: last_modified.and_then(|lm| u64::try_from(lm.timestamp_micros()).ok()), + wait: Some(60), + ..self.query + }) + .await? + .to_long_poll() + .await + } +} diff --git a/pkg/guild-client-http/src/ramps.rs b/pkg/guild-client-http/src/ramps.rs new file mode 100644 index 0000000..e931851 --- /dev/null +++ b/pkg/guild-client-http/src/ramps.rs @@ -0,0 +1,79 @@ +use chrono::{DateTime, Utc}; +use client_http::{ClientResponse, NoRpcError, serde_to_query_params}; +use client_http_longpoll::{LongPoll, LongPollPoller}; +use guild_interface::ramps::{ListRampsTransactionsQuery, RampTransaction}; +use ramps_interface::transaction::Transaction; +use rpc::longpoll::PollData; +use uuid::Uuid; + +use crate::GuildClientHttp; + +/// Note error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Get a list of the users notes + async fn list_ramps_transactions_response( + &self, + query: &ListRampsTransactionsQuery, + ) -> Result { + self.http_client + .get("/ramps/transactions") + .query(serde_to_query_params(query)) + .auth() + .exec() + .await + } + + /// Get a list of notes with long poll + #[must_use] + pub fn list_ramps_transactions_long_poll( + &self, + query: &ListRampsTransactionsQuery, + ) -> LongPoll { + // TODO: attach long poll to client + LongPoll::new(RampTransactionLongPoll { + client: self.clone(), + query: query.clone(), + }) + } + + /// Get a single ramps transaction by id + pub async fn get_ramp_transaction(&self, id: Uuid) -> Result { + self.http_client + .get(&format!("/ramps/transactions/{id}")) + .auth() + .exec() + .await? + .to_value::() + .await + .map(RampTransaction::from) + } +} + +/// Polls for ramps transactions +pub struct RampTransactionLongPoll { + client: GuildClientHttp, + query: ListRampsTransactionsQuery, +} + +#[async_trait::async_trait] +impl LongPollPoller for RampTransactionLongPoll { + type Error = Error; + type T = Vec; + + async fn poll( + &self, + last_modified: Option>, + ) -> Result, Self::Error> { + self.client + .list_ramps_transactions_response(&ListRampsTransactionsQuery { + after: last_modified.and_then(|lm| u64::try_from(lm.timestamp_micros()).ok()), + wait: Some(60), + ..self.query.clone() + }) + .await? + .to_long_poll() + .await + } +} diff --git a/pkg/guild-client-http/src/registry.rs b/pkg/guild-client-http/src/registry.rs new file mode 100644 index 0000000..c561e17 --- /dev/null +++ b/pkg/guild-client-http/src/registry.rs @@ -0,0 +1,88 @@ +use chrono::{DateTime, Utc}; +use client_http::{ClientResponse, HttpBody, serde_to_query_params}; +use client_http_longpoll::{LongPoll, LongPollPoller}; +use element::Element; +use guild_interface::registry::{ + self, CreateRegistryNoteInput, ListRegistryNotesQuery, RegistryNote, +}; +use rpc::longpoll::PollData; + +use crate::GuildClientHttp; + +/// Registry error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Get a list of the registry notes for the users public key + async fn list_registry_notes_response( + &self, + public_key: Element, + query: &ListRegistryNotesQuery, + ) -> Result { + self.http_client + .get(format!("/registry/notes/{}", &public_key.to_string()).as_str()) + .query(serde_to_query_params(query)) + .auth() + .exec() + .await + } + + /// Get a list of registry notes with long poll + #[must_use] + pub fn list_registry_notes_long_poll( + &self, + public_key: Element, + query: &ListRegistryNotesQuery, + ) -> LongPoll { + LongPoll::new(RegistryNotesLongPoll { + client: self.clone(), + query: query.clone(), + public_key, + }) + } + + /// Send add to encrypted request + pub async fn add_registry_entry( + &self, + request: &CreateRegistryNoteInput, + ) -> Result { + self.http_client + .post("/registry/notes", Some(HttpBody::json(request.clone()))) + .auth() + .exec() + .await? + .to_value() + .await + } +} + +/// Registry notes long poll +pub struct RegistryNotesLongPoll { + client: GuildClientHttp, + public_key: Element, + query: ListRegistryNotesQuery, +} + +#[async_trait::async_trait] +impl LongPollPoller for RegistryNotesLongPoll { + type Error = Error; + type T = Vec; + + async fn poll( + &self, + last_modified: Option>, + ) -> Result, Self::Error> { + self.client + .list_registry_notes_response( + self.public_key, + &ListRegistryNotesQuery { + after: last_modified.and_then(|lm| u64::try_from(lm.timestamp_micros()).ok()), + wait: Some(60), + ..self.query + }, + ) + .await? + .to_long_poll() + .await + } +} diff --git a/pkg/guild-client-http/src/support.rs b/pkg/guild-client-http/src/support.rs new file mode 100644 index 0000000..5c8e97f --- /dev/null +++ b/pkg/guild-client-http/src/support.rs @@ -0,0 +1,67 @@ +use chrono::{DateTime, Utc}; +use client_http::{ClientResponse, NoRpcError, serde_to_query_params}; +use client_http_longpoll::{LongPoll, LongPollPoller}; +use guild_interface::support::{ListSupportIssuesQuery, SupportIssue}; +use rpc::longpoll::PollData; + +use crate::GuildClientHttp; + +/// Support error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Get a list of the support issues for the user + async fn list_support_issues_response( + &self, + query: &ListSupportIssuesQuery, + ) -> Result { + self.http_client + .get("/support/issues") + .query(serde_to_query_params(query)) + .auth() + .exec() + .await + } + + /// Get a list of support issues with long poll + #[must_use] + pub fn list_support_issues_long_poll( + &self, + query: &ListSupportIssuesQuery, + ) -> LongPoll { + LongPoll::new(SupportIssuesLongPoll { + client: self.clone(), + query: query.clone(), + }) + } +} + +/// Support issues long poll +pub struct SupportIssuesLongPoll { + client: GuildClientHttp, + query: ListSupportIssuesQuery, +} + +#[async_trait::async_trait] +impl LongPollPoller for SupportIssuesLongPoll { + type Error = Error; + type T = Vec; + + async fn poll( + &self, + last_modified: Option>, + ) -> Result, Self::Error> { + let res = self + .client + .list_support_issues_response(&ListSupportIssuesQuery { + after: last_modified.and_then(|lm| u64::try_from(lm.timestamp_micros()).ok()), + wait: Some(60), + ..self.query + }) + .await? + .to_long_poll() + .await?; + + Ok(res) + } +} diff --git a/pkg/guild-client-http/src/wallet.rs b/pkg/guild-client-http/src/wallet.rs new file mode 100644 index 0000000..2efd2ca --- /dev/null +++ b/pkg/guild-client-http/src/wallet.rs @@ -0,0 +1,64 @@ +use async_trait::async_trait; +use chrono::{DateTime, Utc}; +use client_http::{ClientResponse, NoRpcError, serde_to_query_params}; +use client_http_longpoll::{LongPoll, LongPollPoller}; +use guild_interface::wallet::{GetWalletQuery, Wallet}; +use rpc::longpoll::PollData; + +use crate::GuildClientHttp; + +/// Wallet error +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Get wallet information + pub async fn get_wallet(&self) -> Result { + self.get_wallet_response(&GetWalletQuery::default()) + .await? + .to_value() + .await + } + + /// Get wallet response with query parameters + async fn get_wallet_response(&self, query: &GetWalletQuery) -> Result { + self.http_client + .get("/wallets/me") + .query(serde_to_query_params(query)) + .auth() + .exec() + .await + } + + /// Get wallet with long poll + #[must_use] + pub fn get_wallet_long_poll(&self) -> LongPoll { + LongPoll::new(WalletLongPoll { + client: self.clone(), + }) + } +} + +/// Long poll poller for wallet updates +pub struct WalletLongPoll { + client: GuildClientHttp, +} + +#[async_trait] +impl LongPollPoller for WalletLongPoll { + type Error = Error; + type T = Wallet; + + async fn poll( + &self, + last_modified: Option>, + ) -> Result, Self::Error> { + self.client + .get_wallet_response(&GetWalletQuery { + after: last_modified.and_then(|lm| u64::try_from(lm.timestamp_micros()).ok()), + wait: Some(60), + }) + .await? + .to_long_poll() + .await + } +} diff --git a/pkg/guild-client-http/src/wallet_activity.rs b/pkg/guild-client-http/src/wallet_activity.rs new file mode 100644 index 0000000..f745d75 --- /dev/null +++ b/pkg/guild-client-http/src/wallet_activity.rs @@ -0,0 +1,67 @@ +use client_http::{ClientResponse, HttpBody, serde_to_query_params}; +use guild_interface::wallet_activity::{ + WalletActivity, WalletActivityListQuery, WalletActivityUpsert, +}; +use uuid::Uuid; + +use crate::GuildClientHttp; + +/// Error for wallet activity rpc +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Send wallet activity upsert request to Guild + pub async fn upsert_wallet_activity( + &self, + wallet_activity: &WalletActivityUpsert, + ) -> Result { + self.http_client + .post( + "/wallets/me/activity", + Some(HttpBody::json(wallet_activity.clone())), + ) + .auth() + .exec() + .await? + .to_value() + .await + } + + /// Lists wallet activity for the authenticated user, with optional filters + pub async fn list_wallet_activity( + &self, + query: Option, + ) -> Result, Error> { + let mut req = self.http_client.get("/wallets/me/activity").auth(); + + if let Some(query) = query { + req = req.query(serde_to_query_params(&query)); + } + + req.exec().await?.to_value().await + } + + /// Get a specific activity + pub async fn get_wallet_activity(&self, id: &Uuid) -> Result, Error> { + let res: Result = self + .http_client + .get(&format!("/wallets/me/activity/{id}")) + .auth() + .exec() + .await; + + let res = match res { + Ok(res) => res, + Err(client_http::Error::Rpc( + guild_interface::wallet_activity::Error::ActivityNotFound, + )) => { + return Ok(None); + } + Err(err) => return Err(err), + }; + + let val: WalletActivity = res.to_value().await?; + + Ok(Some(val)) + } +} diff --git a/pkg/guild-client-http/src/wallet_notes.rs b/pkg/guild-client-http/src/wallet_notes.rs new file mode 100644 index 0000000..a3043ed --- /dev/null +++ b/pkg/guild-client-http/src/wallet_notes.rs @@ -0,0 +1,39 @@ +use client_http::{HttpBody, NoRpcError}; +use guild_interface::wallet_notes::{WalletNote, WalletNoteRequest}; + +use crate::GuildClientHttp; + +/// Error for wallet note rpc +pub type Error = client_http::Error; + +impl GuildClientHttp { + /// Send wallet notes upsert request to Guild + pub async fn upsert_wallet_notes( + &self, + wallet_notes: Vec, + ) -> Result, Error> { + self.http_client + .post( + "/wallets/me/notes", + Some(HttpBody::json(WalletNoteRequest { + notes: wallet_notes, + })), + ) + .auth() + .exec() + .await? + .to_value() + .await + } + + /// Lists ALL unspent wallet notes for the authenticated user + pub async fn list_wallet_notes(&self) -> Result, Error> { + self.http_client + .get("/wallets/me/notes") + .auth() + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/guild-client-http/tests/http_client_swapping.rs b/pkg/guild-client-http/tests/http_client_swapping.rs new file mode 100644 index 0000000..1007d58 --- /dev/null +++ b/pkg/guild-client-http/tests/http_client_swapping.rs @@ -0,0 +1,27 @@ +use guild_client_http::GuildClientHttp; +use http_interface::{Error, RecordingHttpClient}; +use reqwest::Method; + +#[tokio::test] +async fn swapping_http_client_surfaces_errors() { + let mock = RecordingHttpClient::new(); + let client = GuildClientHttp::with_http_client(mock.clone()); + + // The mock already returns server errors by default, + // so we can directly test the behavior + let result = client.get_wallet().await; + + match result { + Err(Error::ServerError(_, metadata)) => { + assert_eq!(metadata.path, "/wallets/me"); + assert_eq!(metadata.method, Method::GET); + } + other => panic!("unexpected result: {other:?}"), + } + + // Verify that the get method was called with the expected path + let calls = mock.calls(); + assert_eq!(calls.len(), 1); + assert_eq!(calls[0].0, Method::GET); + assert_eq!(calls[0].1, "/wallets/me"); +} diff --git a/pkg/guild-interface/Cargo.toml b/pkg/guild-interface/Cargo.toml new file mode 100644 index 0000000..8ec9b2e --- /dev/null +++ b/pkg/guild-interface/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "guild-interface" +version = "0.1.0" +edition = "2024" + +[dependencies] +contracts = { workspace = true } +contextful = { workspace = true } +currency = { workspace = true } +data = { workspace = true } +element = { workspace = true } +notes-interface = { workspace = true } +primitives = { workspace = true } +rpc = { workspace = true } +rpc-error-convert = { workspace = true } +zk-primitives = { workspace = true } +ramps-interface = { workspace = true } + +chrono = { workspace = true } +ethereum-types = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +uuid = { workspace = true } +kyc = { workspace = true } +workspace-hack.workspace = true + +[features] +ts-rs = [ + "element/ts-rs", + "primitives/ts-rs", + "zk-primitives/ts-rs", + "currency/ts-rs", + "kyc/ts-rs", + "data/ts-rs", + "ramps-interface/ts-rs", +] diff --git a/pkg/guild-interface/README.md b/pkg/guild-interface/README.md new file mode 100644 index 0000000..ef69aab --- /dev/null +++ b/pkg/guild-interface/README.md @@ -0,0 +1,16 @@ +# Guild Interface + +Interface definitions and shared types for the guild service. + +## Overview + +This package defines the interface contracts and shared data types used by the Guild application server and its clients. + +## Features + +- API interface definitions +- Shared data structures +- Request/response types +- Error types +- Bungee quote errors distinguish low input-value vs low output-value quotes for client handling +- Utility functions diff --git a/pkg/guild-interface/src/across.rs b/pkg/guild-interface/src/across.rs new file mode 100644 index 0000000..e2aa0ee --- /dev/null +++ b/pkg/guild-interface/src/across.rs @@ -0,0 +1,152 @@ +use contextful::{FromContextful, InternalError}; +use contracts::{Address, H256, U256}; +use element::Element; +use primitives::serde::{deserialize_hex_0x_prefixed, serialize_hex_0x_prefixed}; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +/// Across error +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, FromContextful, Serialize, Deserialize, +)] +pub enum Error { + /// Unsupported source chain id + #[bad_request("unsupported-source-chain-id")] + #[error("[guild-interface/across] unsupported source chain id: {chain_id}")] + UnsupportedSourceChainId { + /// The unsupported chain id + chain_id: u128, + }, + /// Source and destination chain ids must differ + #[bad_request("same-source-destination-chain-id")] + #[error( + "[guild-interface/across] source chain id {source_chain_id} matches destination chain id {destination_chain_id}" + )] + SameSourceAndDestinationChainId { + /// The provided source chain id + source_chain_id: u128, + /// The provided destination chain id + destination_chain_id: u128, + }, + /// Amount too low error from Across API + #[bad_request("amount-too-low")] + #[error("[guild-interface/across] amount too low: {message}")] + AmountTooLow { + /// The error message from Across API + message: String, + }, + /// Amount too high error from Across API + #[bad_request("amount-too-high")] + #[error("[guild-interface/across] amount too high: {message}")] + AmountTooHigh { + /// The error message from Across API + message: String, + }, + /// Route not enabled error from Across API + #[bad_request("route-not-enabled")] + #[error("[guild-interface/across] route not enabled: {message}")] + RouteNotEnabled { + /// The error message from Across API + message: String, + }, + /// Internal error + #[error("[guild-interface/across] internal error")] + Internal(#[from] InternalError), +} + +/// Result type for across operations. +pub type Result = std::result::Result; + +/// Input for getting an Across quote +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct GetQuoteInput { + /// Source chain id + pub source_chain_id: u128, + /// Destination chain id + pub destination_chain_id: u128, + /// Input token address + pub input_token: Address, + /// Output token address + pub output_token: Address, + /// Input amount + pub input_amount: U256, +} + +/// Output for getting an Across quote +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +pub struct GetQuoteOutput { + /// Output amount + pub output_amount: U256, + /// Quote timestamp + pub quote_timestamp: u32, + /// Fill deadline + pub fill_deadline: u32, + /// Exclusivity deadline + pub exclusivity_deadline: u32, + /// The relayer for an exclusive quote + pub exclusive_relayer: Address, +} + +/// Input for across deposit +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct DepositV3WithAuthorizationInput { + /// USDC signature + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub usdc_sig: Vec, + /// Deposit signature + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub deposit_sig: Vec, + /// Valid after + pub valid_after: U256, + /// Valid before + pub valid_before: U256, + /// Nonce + pub nonce: Element, + /// Depositor address + pub depositor: Address, + /// Recipient address + pub recipient: Address, + /// Input token address + pub input_token: Address, + /// Output token address + pub output_token: Address, + /// Source chain id + pub source_chain_id: u128, + /// Input amount + pub input_amount: U256, + /// Output amount + pub output_amount: U256, + /// Destination chain id + pub destination_chain_id: u128, + /// Exclusive relayer address + pub exclusive_relayer: Address, + /// Quote timestamp + pub quote_timestamp: u32, + /// Fill deadline + pub fill_deadline: u32, + /// Exclusivity deadline + pub exclusivity_deadline: u32, + /// Message + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub message: Vec, +} + +/// Output for across deposit +#[derive(Debug, Serialize, Deserialize)] +pub struct DepositV3WithAuthorizationOutput { + /// Transaction hash + pub txn: H256, +} diff --git a/pkg/guild-interface/src/auth.rs b/pkg/guild-interface/src/auth.rs new file mode 100644 index 0000000..23fe245 --- /dev/null +++ b/pkg/guild-interface/src/auth.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; +use zk_primitives::SignatureProof; + +/// Request auth with signature proof +#[derive(Debug, Serialize, Deserialize)] +pub struct AuthRequest { + /// Proof to verify the address of the user + pub proof: SignatureProof, +} + +/// Response for auth request +#[derive(Debug, Serialize, Deserialize)] +pub struct AuthResponse { + /// Guild JWT + pub guild: String, +} diff --git a/pkg/guild-interface/src/bungee.rs b/pkg/guild-interface/src/bungee.rs new file mode 100644 index 0000000..b14cebb --- /dev/null +++ b/pkg/guild-interface/src/bungee.rs @@ -0,0 +1,401 @@ +//! Bungee interface request/response types for server <-> clients. + +// lint-long-file-override allow-max-lines=500 +use contracts::{Address, U256}; +use primitives::serde::{deserialize_hex_0x_prefixed, serialize_hex_0x_prefixed}; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +use std::fmt; + +/// Bungee error +#[derive(Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize)] +pub enum Error { + /// Unsupported source chain id + #[bad_request("unsupported-source-chain-id")] + #[error("unsupported source chain id: {chain_id}")] + UnsupportedSourceChainId { + /// The unsupported chain id + chain_id: u128, + }, + + /// No route available from Bungee (autoRoute missing/null) + #[not_found("bungee-no-route")] + #[error("no bungee route available for the requested swap/bridge")] + NoRoute, + + /// Missing identifier for status lookup + #[bad_request("bungee-status-missing-identifier")] + #[error("missing identifier for bungee status lookup")] + MissingStatusIdentifier, + + /// Input amount is below minimum threshold ($0.10 USD) + #[bad_request("bungee-input-amount-too-low", severity = "warn")] + #[error("[bungee] bungee quote input amount too low: ${usd_amount:.2} (minimum $0.10)")] + InputAmountTooLow { + /// The actual USD input amount + usd_amount: f64, + }, + + /// Output amount is below minimum threshold ($0.10 USD) + #[bad_request("bungee-output-amount-too-low", severity = "warn")] + #[error("[bungee] bungee quote output amount too low: ${usd_amount:.2} (minimum $0.10)")] + OutputAmountTooLow { + /// The actual USD output amount + usd_amount: f64, + }, +} + +/// Input for getting a Bungee quote (Inbox) +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct GetQuoteInput { + /// Source chain id + pub source_chain_id: u128, + /// Destination chain id + pub destination_chain_id: u128, + /// Input token address + pub input_token: Address, + /// Output token address + pub output_token: Address, + /// Input amount + pub input_amount: U256, + /// Receiver wallet address on destination chain + pub receiver_address: Address, + /// User wallet address on source chain (depositor) + pub user_address: Address, +} + +/// Output for getting a Bungee quote +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +pub struct GetQuoteOutput { + /// Expected output amount (as reported by Bungee auto route) + pub output_amount: U256, + /// Inbox transaction target + pub tx_to: Address, + /// Inbox transaction value (wei) + pub tx_value: U256, + /// Inbox transaction calldata + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub tx_data: Vec, + /// Optional approval spender + pub approval_spender: Option
, + /// Optional approval amount + pub approval_amount: Option, + /// Optional provider quote id for follow-up (status/build) + pub quote_id: Option, + /// Optional provider request hash for status lookup + pub request_hash: Option, +} + +/// Controls which token list Bungee should return +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash, Default)] +pub enum TokenListKind { + /// Return the trending subset of tokens (Bungee upstream default) + #[serde(rename = "trending")] + #[default] + Trending, + /// Return the full list of supported tokens + #[serde(rename = "full")] + Full, +} + +impl TokenListKind { + /// String representation expected by the Bungee API + #[must_use] + pub fn as_str(self) -> &'static str { + match self { + Self::Trending => "trending", + Self::Full => "full", + } + } +} + +/// Identifier used to poll the Bungee status endpoint +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum StatusIdentifier { + /// Auto-route request hash returned from submit/build + RequestHash(String), + /// Manual route source transaction hash + TxHash(String), + /// Alternate identifier, e.g. Permit2 submission id + Id(String), +} + +impl StatusIdentifier { + /// Return the query parameter key expected by the public API + #[must_use] + pub fn key(&self) -> &'static str { + match self { + Self::RequestHash(_) => "requestHash", + Self::TxHash(_) => "txHash", + Self::Id(_) => "id", + } + } + + /// Retrieve the underlying identifier value + #[must_use] + pub fn value(&self) -> &str { + match self { + Self::RequestHash(value) | Self::TxHash(value) | Self::Id(value) => value, + } + } + + /// Convert into a [`GetStatusInput`] + #[must_use] + pub fn into_input(self) -> GetStatusInput { + match self { + Self::RequestHash(value) => GetStatusInput { + request_hash: Some(value), + ..GetStatusInput::default() + }, + Self::TxHash(value) => GetStatusInput { + tx_hash: Some(value), + ..GetStatusInput::default() + }, + Self::Id(value) => GetStatusInput { + id: Some(value), + ..GetStatusInput::default() + }, + } + } +} + +/// Input parameters for fetching the token list +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct GetTokenListInput { + /// Optional wallet address used to enrich balances + pub user_address: Option
, + /// Optional chain id filter list + pub chain_ids: Option>, + /// Token list variant requested from Bungee + #[serde(default)] + pub list: TokenListKind, +} + +/// Token metadata exposed through Guild +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct TokenMetadata { + /// Token contract address + pub address: Address, + /// Human readable token name + pub name: String, + /// Token ticker symbol + pub symbol: String, + /// Number of decimals used by the token + pub decimals: u8, + /// Optional token icon URL reported by Bungee + #[serde(skip_serializing_if = "Option::is_none")] + pub logo_uri: Option, +} + +/// Output token list grouped by chain id +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct GetTokenListOutput { + /// Mapping of chain id to the available tokens + pub tokens: BTreeMap>, +} + +/// Input payload for checking the status of a submitted bridge +#[derive(Debug, Clone, Default, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct GetStatusInput { + /// Request hash returned by Bungee (auto routes / Permit2) + #[serde(skip_serializing_if = "Option::is_none")] + pub request_hash: Option, + /// Manual route source chain transaction hash + #[serde(skip_serializing_if = "Option::is_none")] + pub tx_hash: Option, + /// Alternate identifier accepted by the public API + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, +} + +impl GetStatusInput { + /// Create from a request hash + #[must_use] + pub fn from_request_hash(request_hash: impl Into) -> Self { + Self { + request_hash: Some(request_hash.into()), + ..Self::default() + } + } + + /// Create from a transaction hash + #[must_use] + pub fn from_tx_hash(tx_hash: impl Into) -> Self { + Self { + tx_hash: Some(tx_hash.into()), + ..Self::default() + } + } + + /// Create from an alternate identifier + #[must_use] + pub fn from_id(id: impl Into) -> Self { + Self { + id: Some(id.into()), + ..Self::default() + } + } + + /// Resolve the identifier following Bungee's priority rules + pub fn identifier(&self) -> Result { + let pick = |value: &Option, ctor: fn(String) -> StatusIdentifier| { + value + .as_ref() + .map(|s| s.trim()) + .filter(|s| !s.is_empty()) + .map(|s| ctor(s.to_owned())) + }; + + pick(&self.request_hash, StatusIdentifier::RequestHash) + .or_else(|| pick(&self.tx_hash, StatusIdentifier::TxHash)) + .or_else(|| pick(&self.id, StatusIdentifier::Id)) + .ok_or(Error::MissingStatusIdentifier) + } + + /// Build query pairs for the public API call + pub fn to_query_pairs(&self) -> Result, Error> { + let identifier = self.identifier()?; + Ok(vec![( + identifier.key().to_string(), + identifier.value().to_string(), + )]) + } +} + +/// Status history returned by the Guild API +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Default)] +pub struct GetStatusOutput { + /// Bungee status entries ordered with the most recent first + pub statuses: Vec, +} + +impl GetStatusOutput { + /// Return the most recent status entry + #[must_use] + pub fn latest(&self) -> Option<&StatusEntry> { + self.statuses.first() + } +} + +/// Individual status entry in the history +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +pub struct StatusEntry { + /// Numeric status code + pub code: BungeeStatusCode, + /// Optional status label provided by Bungee + #[serde(skip_serializing_if = "Option::is_none")] + pub label: Option, + /// Optional destination transaction hash once broadcast + #[serde(skip_serializing_if = "Option::is_none")] + pub destination_tx_hash: Option, +} + +/// Enumeration of Bungee status codes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum BungeeStatusCode { + /// Request submitted; waiting for solver assignment + Pending, + /// Solver assigned and preparing execution + Assigned, + /// Solver completed source-chain extraction + Extracted, + /// Destination transaction broadcast and fulfilled + Fulfilled, + /// Settlement completed on both chains + Settled, + /// Request expired before completion + Expired, + /// Request cancelled (user/system) + Cancelled, + /// Request refunded to the origin + Refunded, + /// Unknown / forward compatible status code + Unknown(u8), +} + +impl BungeeStatusCode { + /// Numeric representation used by Bungee + #[must_use] + pub fn as_u8(self) -> u8 { + match self { + Self::Pending => 0, + Self::Assigned => 1, + Self::Extracted => 2, + Self::Fulfilled => 3, + Self::Settled => 4, + Self::Expired => 5, + Self::Cancelled => 6, + Self::Refunded => 7, + Self::Unknown(code) => code, + } + } + + /// Construct from the numeric representation + #[must_use] + pub fn from_u8(code: u8) -> Self { + match code { + 0 => Self::Pending, + 1 => Self::Assigned, + 2 => Self::Extracted, + 3 => Self::Fulfilled, + 4 => Self::Settled, + 5 => Self::Expired, + 6 => Self::Cancelled, + 7 => Self::Refunded, + other => Self::Unknown(other), + } + } + + /// Human-readable label for the status code + #[must_use] + pub fn as_str(self) -> &'static str { + match self { + Self::Pending => "PENDING", + Self::Assigned => "ASSIGNED", + Self::Extracted => "EXTRACTED", + Self::Fulfilled => "FULFILLED", + Self::Settled => "SETTLED", + Self::Expired => "EXPIRED", + Self::Cancelled => "CANCELLED", + Self::Refunded => "REFUNDED", + Self::Unknown(_) => "UNKNOWN", + } + } +} + +impl serde::Serialize for BungeeStatusCode { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u8(self.as_u8()) + } +} + +impl<'de> serde::Deserialize<'de> for BungeeStatusCode { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let code = u8::deserialize(deserializer)?; + Ok(Self::from_u8(code)) + } +} + +impl fmt::Display for BungeeStatusCode { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Unknown(code) => write!(f, "UNKNOWN({code})"), + other => f.write_str(other.as_str()), + } + } +} diff --git a/pkg/guild-interface/src/eip7702.rs b/pkg/guild-interface/src/eip7702.rs new file mode 100644 index 0000000..51a791b --- /dev/null +++ b/pkg/guild-interface/src/eip7702.rs @@ -0,0 +1,81 @@ +use contracts::{Address, H256, U256}; +use primitives::serde::{deserialize_hex_0x_prefixed, serialize_hex_0x_prefixed}; +use serde::{Deserialize, Serialize}; + +/// Authorization tuple submitted by the client. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +pub struct AuthorizationInput { + /// Chain id included in the authorization tuple + pub chain_id: U256, + /// Delegate implementation address authorized by the user + pub delegate: Address, + /// User transaction nonce at time of signing + pub nonce: U256, + /// y-parity (aka recovery id parity) of the signature (0 or 1) + pub y_parity: u8, + /// r component of the signature + pub r: H256, + /// s component of the signature + pub s: H256, +} + +/// Input to relay a SetCode (type 0x04) upgrade using a signed authorization +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RelayUpgradeInput { + /// User address to upgrade + pub user: Address, + /// Signed authorization + pub authorization: AuthorizationInput, +} + +/// One meta-transaction call +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +pub struct CallInput { + /// Target contract to call + pub target: Address, + /// Value in wei + pub value: U256, + /// Calldata for target (hex) + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub data: Vec, +} + +/// Input to relay a meta transaction batch (executeMeta) +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RelayMetaInput { + /// Chain id to relay on + pub chain_id: U256, + /// User address (EOA executing delegate code) + pub user: Address, + /// Calls to execute in order + pub calls: Vec, + /// Meta-txn nonce + pub nonce: U256, + /// Validity window start (unix seconds) + pub valid_after: U256, + /// Validity window end (unix seconds) + pub valid_until: U256, + /// User signature over EIP-712 digest + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub signature: Vec, +} + +/// Output with a transaction hash +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RelayTxOutput { + /// Transaction hash of the relayed transaction + pub txn: H256, +} + +/// Output for account nonce +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct AccountNonceOutput { + /// Current meta-transaction nonce read from the delegate contract + pub nonce: U256, +} diff --git a/pkg/guild-interface/src/error.rs b/pkg/guild-interface/src/error.rs new file mode 100644 index 0000000..1223be1 --- /dev/null +++ b/pkg/guild-interface/src/error.rs @@ -0,0 +1,31 @@ +use contextful::{FromContextful, InternalError}; +use rpc::error::{ErrorOutput, HTTPError, TryFromHTTPError}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +use crate::{across, mint}; + +/// RPC errors for guild +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, FromContextful, Serialize, Deserialize, +)] +pub enum Error { + /// Mint error + // No extra context needed; nested error already includes context. + #[delegate] + #[error("[guild-interface/error] mint error")] + Mint(#[from] mint::Error), + + /// Across error + // No extra context needed; nested error already includes context. + #[delegate] + #[error("[guild-interface/error] across error")] + Across(#[from] across::Error), + + /// Internal error + #[error("[guild-interface/error] internal error")] + Internal(#[from] InternalError), +} + +/// Result type for guild interface errors. +pub type Result = std::result::Result; diff --git a/pkg/guild-interface/src/lib.rs b/pkg/guild-interface/src/lib.rs new file mode 100644 index 0000000..30c2838 --- /dev/null +++ b/pkg/guild-interface/src/lib.rs @@ -0,0 +1,42 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::match_bool)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::doc_markdown)] +#![deny(missing_docs)] + +//! Interface for requests/responses to Guild +/// Across interface +pub mod across; +/// Auth interface +pub mod auth; +pub mod bungee; +/// EIP-7702 interface +pub mod eip7702; +mod error; +/// Migration interface +pub mod migrate; +/// Mint interface +pub mod mint; +/// Note interface +pub mod notes; +/// Payments interface +pub mod payments; +/// Ramps interface +pub mod ramps; +/// Registry interface +pub mod registry; +/// Support interface +pub mod support; +/// Utility fns +mod util; +/// Wallet +pub mod wallet; +/// Wallet activity interface +pub mod wallet_activity; +/// Wallet notes interface +pub mod wallet_notes; + +pub use eip7702::*; +pub use error::*; diff --git a/pkg/guild-interface/src/migrate.rs b/pkg/guild-interface/src/migrate.rs new file mode 100644 index 0000000..6dc15d2 --- /dev/null +++ b/pkg/guild-interface/src/migrate.rs @@ -0,0 +1,27 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +pub use notes_interface::NoteWithPk; + +/// Request body input for migrate notes +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MigrationNotesRequest { + /// Notes to be migrated + pub notes: Vec, +} + +/// Response for migrate notes endpoint +pub type MigrationNotesResponse = Vec; + +/// Old rollup note to be migrated +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MigrationNote { + /// Value of the note + pub value: Element, + /// Address of the note + pub address: Element, + /// Randomness of note + pub psi: Element, + /// Private key of note + pub private_key: Element, +} diff --git a/pkg/guild-interface/src/mint.rs b/pkg/guild-interface/src/mint.rs new file mode 100644 index 0000000..0c9f992 --- /dev/null +++ b/pkg/guild-interface/src/mint.rs @@ -0,0 +1,123 @@ +use contextful::{FromContextful, InternalError}; +use element::Element; +use ethereum_types::{Address, H256, U256}; +use primitives::serde::{deserialize_hex_0x_prefixed, serialize_hex_0x_prefixed}; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +/// Details for insufficient balance +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InsufficientBalance { + /// Required balance for the mint + pub required: U256, + /// Available balance for the mint + pub available: U256, + /// Token kind + pub token: Element, +} + +/// RPC errors for guild +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, FromContextful, Serialize, Deserialize, +)] +pub enum Error { + /// Invalid signature length, epected uncompressed signature + #[bad_request("invalid-signature-length")] + #[error("[guild-interface/mint] invalid signature length, expected 65, got {length}")] + InvalidSignatureLength { + /// Signature length received + length: usize, + }, + + /// Mints with zero value are not allowed + #[bad_request("zero-mint-value")] + #[error("[guild-interface/mint] mint value cannot be zero")] + ZeroMintValue, + + /// EVM deposit address does not have the required mint funds + #[failed_precondition("insufficient-balance")] + #[error("[guild-interface/mint] insufficient balance {0:?}")] + InsufficientBalance(InsufficientBalance), + + /// Internal error + #[error("[guild-interface/mint] internal error")] + Internal(#[from] InternalError), +} + +/// Result type for mint operations. +pub type Result = std::result::Result; + +/// Raw mint input, includes the core data to be used by the mint contract +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MintInput { + /// Mint hash used to identify mints in the smart contract. Note: mint_hash can + /// be re-used once the mint resolves in the smart contract. + pub mint_hash: Element, + /// Value of the mint + pub value: Element, + /// Kind of note being minted + pub note_kind: Element, +} + +/// Mint request, including signed data for submission to EVM +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MintRequest { + /// Mint input + pub mint: MintInput, + /// Depsoit address to mint funds from + pub deposit_addr: Address, + /// USDC signature for transfer via signature + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub usdc_sig: Vec, + /// Mint signature to prevent frontrunning the mint + #[serde( + serialize_with = "serialize_hex_0x_prefixed", + deserialize_with = "deserialize_hex_0x_prefixed" + )] + pub mint_sig: Vec, + /// Valid after expiration for signature + pub valid_after: U256, + /// Valid before expiration for signature + pub valid_before: U256, + /// Nonce for randomness + pub nonce: H256, +} + +impl MintRequest { + /// Validate the mint request is valid + pub fn validate(&self) -> Result<()> { + if self.usdc_sig.len() != 65 { + return Err(Error::InvalidSignatureLength { + length: self.usdc_sig.len(), + }); + } + + if self.mint_sig.len() != 65 { + return Err(Error::InvalidSignatureLength { + length: self.mint_sig.len(), + }); + } + + Ok(()) + } +} + +/// Response for mint if successful +#[derive(Debug, Serialize, Deserialize)] +pub struct MintResponse { + /// EVM txn hash + pub txn_hash: H256, + /// The kind of note to be minted + pub note_kind: Element, + /// Value that was minted + pub value: Element, + /// Has the mint already been spent + pub spent: bool, +} diff --git a/pkg/guild-interface/src/notes/create.rs b/pkg/guild-interface/src/notes/create.rs new file mode 100644 index 0000000..66a36fe --- /dev/null +++ b/pkg/guild-interface/src/notes/create.rs @@ -0,0 +1,46 @@ +use contextful::{FromContextful, InternalError}; +use element::Element; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; +use zk_primitives::bridged_polygon_usdc_note_kind; + +/// RPC errors for guild +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, FromContextful, Serialize, Deserialize, +)] +pub enum Error { + /// Note already exists on the server + #[already_exists("note-already-exists")] + #[error("[guild-interface/notes/create] note already exists")] + NoteAlreadyExists, + + /// Note has already been spent so cannot be added + #[already_exists("note-already-spent")] + #[error("[guild-interface/notes/create] note is already spent")] + NoteAlreadySpent, + + /// Internal error + #[error("[guild-interface/notes/create] internal error")] + Internal(#[from] InternalError), +} + +/// Result type for note creation operations. +pub type Result = std::result::Result; + +/// Input for creating a new note +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CreateNoteInput { + /// Private key of the note + pub private_key: Element, + /// Randomness (psi) of the note + pub psi: Element, + /// Value of the note + pub value: Element, + /// Note kind / contract. Defaults to USDC for older clients. + #[serde(default = "bridged_polygon_usdc_note_kind")] + pub note_kind: Element, +} diff --git a/pkg/guild-interface/src/notes/list.rs b/pkg/guild-interface/src/notes/list.rs new file mode 100644 index 0000000..597837e --- /dev/null +++ b/pkg/guild-interface/src/notes/list.rs @@ -0,0 +1 @@ +pub use notes_interface::ListNotesQuery; diff --git a/pkg/guild-interface/src/notes/mod.rs b/pkg/guild-interface/src/notes/mod.rs new file mode 100644 index 0000000..f4f940c --- /dev/null +++ b/pkg/guild-interface/src/notes/mod.rs @@ -0,0 +1,11 @@ +/// Interface for POST /notes +pub mod create; +/// Interface for GET /notes +pub mod list; +/// Core note interface datatypes +pub mod note; +/// Interface for POST /notes/request +pub mod request; + +#[cfg(test)] +mod tests; diff --git a/pkg/guild-interface/src/notes/note.rs b/pkg/guild-interface/src/notes/note.rs new file mode 100644 index 0000000..0df03f9 --- /dev/null +++ b/pkg/guild-interface/src/notes/note.rs @@ -0,0 +1,83 @@ +use element::Element; +pub use notes_interface::{NoteStatus, RefKind}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +/// Guild note +#[derive(Debug, Default, Deserialize, Serialize, Clone)] +pub struct Note { + /// ID of the note + pub id: Uuid, + /// Kind of note + pub kind: Element, + /// Commitment of note + pub commitment: Element, + /// Address of the private key + pub address: Element, + /// Private key + pub private_key: Element, + /// Randomness + pub psi: Element, + /// Value of the note + pub value: Element, + /// Status of the note + pub status: NoteStatus, + /// Reason kind for spend + pub spend_ref_kind: Option, + /// Reason id for spend + pub spend_ref_id: Option, + /// Reason kind for note received/created + pub received_ref_kind: Option, + /// Reason id for note received/created + pub received_ref_id: Option, + /// Owner ID of the note (as all private keys are ephemeral) + pub owner_id: Uuid, + /// Date/time note added + pub added_at: chrono::NaiveDateTime, + /// Date/time updated (for long polling/since) + pub updated_at: chrono::NaiveDateTime, +} + +impl From for Note { + fn from(note: notes_interface::Note) -> Note { + Note { + id: note.id, + kind: note.kind, + commitment: note.commitment, + address: note.address, + private_key: note.private_key, + psi: note.psi, + value: note.value, + status: note.status, + spend_ref_kind: note.spend_ref_kind, + spend_ref_id: note.spend_ref_id, + received_ref_kind: note.received_ref_kind, + received_ref_id: note.received_ref_id, + owner_id: note.owner_id, + added_at: note.added_at, + updated_at: note.updated_at, + } + } +} + +impl From for zk_primitives::Note { + fn from(note: Note) -> zk_primitives::Note { + zk_primitives::Note { + kind: Element::new(2), + contract: note.kind, + address: note.address, + psi: note.psi, + value: note.value, + } + } +} + +impl From for zk_primitives::InputNote { + fn from(note: Note) -> zk_primitives::InputNote { + let secret_key = note.private_key; + zk_primitives::InputNote { + note: zk_primitives::Note::from(note), + secret_key, + } + } +} diff --git a/pkg/guild-interface/src/notes/request.rs b/pkg/guild-interface/src/notes/request.rs new file mode 100644 index 0000000..09b7240 --- /dev/null +++ b/pkg/guild-interface/src/notes/request.rs @@ -0,0 +1,31 @@ +use contextful::{FromContextful, InternalError}; +pub use notes_interface::{NoteRequestInput, NoteRequestKind}; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +/// RPC errors for guild +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, FromContextful, Serialize, Deserialize, +)] +pub enum Error { + /// Transaction not found for note request + #[not_found("note-request-transaction-not-found")] + #[error("[guild-interface/notes/request] transaction not found")] + TransactionNotFound, + + /// Invalid ramp transaction for notes request + #[bad_request("note-request-invalid-transaction")] + #[error("[guild-interface/notes/request] invalid transaction for note request")] + InvalidTransaction, + + /// Internal error + #[error("[guild-interface/notes/request] internal error")] + Internal(#[from] InternalError), +} + +/// Result type for note request operations. +pub type Result = std::result::Result; diff --git a/pkg/guild-interface/src/notes/tests.rs b/pkg/guild-interface/src/notes/tests.rs new file mode 100644 index 0000000..b37f52f --- /dev/null +++ b/pkg/guild-interface/src/notes/tests.rs @@ -0,0 +1,15 @@ +use super::create::CreateNoteInput; +use element::Element; +use zk_primitives::bridged_polygon_usdc_note_kind; + +#[test] +fn create_note_input_defaults_note_kind_to_usdc() { + let input = serde_json::from_value::(serde_json::json!({ + "private_key": Element::new(1), + "psi": Element::new(2), + "value": Element::new(3), + })) + .unwrap(); + + assert_eq!(input.note_kind, bridged_polygon_usdc_note_kind()); +} diff --git a/pkg/guild-interface/src/payments.rs b/pkg/guild-interface/src/payments.rs new file mode 100644 index 0000000..eb69964 --- /dev/null +++ b/pkg/guild-interface/src/payments.rs @@ -0,0 +1,90 @@ +use contextful::{FromContextful, InternalError}; +use currency::Currency; +use data::payment::Payment; +use element::Element; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +/// Details for unsupported currency +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct UnsupportedCurrency { + /// Currency that was requested but is not supported + pub currency: Currency, +} + +/// Details for invalid payment value +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InvalidPaymentValue { + /// Payment value that was provided but is invalid + pub value: Element, +} + +/// RPC errors for guild +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, FromContextful, Serialize, Deserialize, +)] +pub enum Error { + /// Invalid signature length, epected uncompressed signature + #[bad_request("payments-unsupported-currency")] + #[error("[guild-interface/payments] currency is not supported")] + UnsupportedCurrency(UnsupportedCurrency), + + /// Payment requested is not found, will also be returned if + /// user requests a payment they do not own + #[not_found("payments-not-found")] + #[error("[guild-interface/payments] payment not found")] + PaymentNotFound, + + /// Invalid payment value provided + #[bad_request("payments-invalid-payment-value")] + #[error("[guild-interface/payments] invalid payment value")] + InvalidPaymentValue(InvalidPaymentValue), + + /// Payment cannot be fulfilled - the payment kind is "out + /// of stock" + #[bad_request("payments-cannot-be-fulfilled")] + #[error("[guild-interface/payments] payment cannot be fulfilled")] + PaymentCannotBeFulfilled, + + /// Internal error + #[error("[guild-interface/payments] internal error")] + Internal(#[from] InternalError), +} + +/// Result type for payment operations. +pub type Result = std::result::Result; + +/// Kind of payment - reason for payment +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum PaymentKind { + /// Payment is for a ramp deposit + RampDeposit, +} + +/// Input data for creating a payment +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct PaymentInput { + /// The payment amount value - currently on USD supported + /// 500 => $5 + pub value: Element, + /// Currency - currently only USD is allowed + pub currency: Currency, + /// The kind/reason for the payment, so when the payment is + /// approved the fulfilment can proceed + pub kind: PaymentKind, +} + +/// Response data for a payment request +#[derive(Debug, Serialize, Clone)] +pub struct PaymentResponse { + /// Client secret for the payment - used by the client + /// to submit payment request to Stripe + pub client_secret: String, + /// The payment record + pub payment: Payment, +} diff --git a/pkg/guild-interface/src/ramps.rs b/pkg/guild-interface/src/ramps.rs new file mode 100644 index 0000000..f0a4c26 --- /dev/null +++ b/pkg/guild-interface/src/ramps.rs @@ -0,0 +1,7 @@ +//! Ramps interface re-exports for backward compatibility. + +pub use ramps_interface::transaction::{ + CardStatus, ListRampsTransactionsQuery, RampCardTransaction, RampDepositLinkTransaction, + RampDepositTransaction, RampStatus, RampTransaction, RampTransactionBase, RampTransactionKind, + RampWithdrawTransaction, +}; diff --git a/pkg/guild-interface/src/registry.rs b/pkg/guild-interface/src/registry.rs new file mode 100644 index 0000000..e4d3cb4 --- /dev/null +++ b/pkg/guild-interface/src/registry.rs @@ -0,0 +1,69 @@ +use contextful::{FromContextful, InternalError}; +use element::Element; +use primitives::block_height::BlockHeight; +use primitives::serde::Base64Bytes; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +pub use data::registry_note::RegistryNote; + +/// Query parameters for registry notes +#[derive(Debug, Default, Deserialize, Serialize, Clone)] +pub struct ListRegistryNotesQuery { + /// Long poll duration + pub wait: Option, + /// Get added since unix timestamps (in microseconds) + pub after: Option, + /// Limit result count + pub limit: Option, +} + +/// Create a new note entry into the registry +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct CreateRegistryNoteInput { + /// Block the note was spent in + pub block: BlockHeight, + /// Public key of the user funds are being sent to + pub public_key: Element, + /// Symmetric key, encrypted by public key + pub encrypted_key: Base64Bytes, + /// Note data, encrypted by symmetric key + pub encrypted_note: Base64Bytes, +} + +impl CreateRegistryNoteInput { + /// Validate the entry + pub fn validate(&self) -> Result<()> { + if self.encrypted_key.len() > 1024 { + return Err(Error::DataTooLong); + } + + if self.encrypted_note.len() > 1024 { + return Err(Error::DataTooLong); + } + + Ok(()) + } +} + +/// Registry error +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, FromContextful, Serialize, Deserialize, +)] +pub enum Error { + /// Data provided is too long + #[bad_request("data-too-long")] + #[error("[guild-interface/registry] data is too long")] + DataTooLong, + + /// Internal error + #[error("[guild-interface/registry] internal error")] + Internal(#[from] InternalError), +} + +/// Result type for registry operations. +pub type Result = std::result::Result; diff --git a/pkg/guild-interface/src/support.rs b/pkg/guild-interface/src/support.rs new file mode 100644 index 0000000..c9061ff --- /dev/null +++ b/pkg/guild-interface/src/support.rs @@ -0,0 +1,28 @@ +pub use data::support::Status; +use serde::{Deserialize, Serialize}; + +pub use data::support::SupportIssue; + +/// User-visible support status filter exposed by public APIs. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum UserStatus { + /// Issues that are open to the user (includes on-hold internally). + #[default] + Open, + /// Issues that have been closed. + Closed, +} + +/// List support issues query +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct ListSupportIssuesQuery { + /// Long poll duration + pub wait: Option, + /// Get changes after unix timestamps (in microseconds) + pub after: Option, + /// Limit result count + pub limit: Option, + /// Filter status of support issue + pub status: Option, +} diff --git a/pkg/guild-interface/src/util.rs b/pkg/guild-interface/src/util.rs new file mode 100644 index 0000000..d452571 --- /dev/null +++ b/pkg/guild-interface/src/util.rs @@ -0,0 +1,88 @@ +use chrono::{DateTime, Utc}; +use serde::{Deserializer, Serializer}; + +#[expect(clippy::ref_option)] +pub fn serialize_datetime_opt( + dt: &Option>, + serializer: S, +) -> Result +where + S: Serializer, +{ + match dt { + Some(dt) => serializer.serialize_i64(dt.timestamp_micros()), + None => serializer.serialize_none(), + } +} + +pub fn deserialize_datetime_opt<'de, D>(deserializer: D) -> Result>, D::Error> +where + D: Deserializer<'de>, +{ + struct OptionalDateTimeVisitor; + + impl serde::de::Visitor<'_> for OptionalDateTimeVisitor { + type Value = Option>; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a microsecond timestamp, ISO 8601 datetime string, or null") + } + + fn visit_none(self) -> Result + where + E: serde::de::Error, + { + Ok(None) + } + + fn visit_unit(self) -> Result + where + E: serde::de::Error, + { + Ok(None) + } + + fn visit_i64(self, value: i64) -> Result + where + E: serde::de::Error, + { + DateTime::from_timestamp_micros(value) + .map(Some) + .ok_or_else(|| E::custom(format!("invalid timestamp: {value}"))) + } + + fn visit_u64(self, value: u64) -> Result + where + E: serde::de::Error, + { + if value > i64::MAX as u64 { + return Err(E::custom(format!("timestamp too large: {value}"))); + } + let value = i64::try_from(value) + .map_err(|_| E::custom(format!("timestamp too large: {value}")))?; + + self.visit_i64(value) + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + // Try parsing as ISO 8601 first + if let Ok(dt) = DateTime::parse_from_rfc3339(value) { + return Ok(Some(dt.with_timezone(&Utc))); + } + + // Then try parsing as microsecond timestamp + if let Ok(ts) = value.parse::() + && let Some(dt) = DateTime::from_timestamp_micros(ts) + { + return Ok(Some(dt)); + } + + Err(E::custom(format!("invalid datetime format: {value}"))) + } + } + + deserializer.deserialize_any(OptionalDateTimeVisitor) +} diff --git a/pkg/guild-interface/src/wallet.rs b/pkg/guild-interface/src/wallet.rs new file mode 100644 index 0000000..553ce4a --- /dev/null +++ b/pkg/guild-interface/src/wallet.rs @@ -0,0 +1,30 @@ +use kyc::Kyc; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +/// Query parameters for get wallet +#[derive(Debug, Default, Deserialize, Serialize, Clone)] +pub struct GetWalletQuery { + /// Long poll duration + pub wait: Option, + /// Get changes since unix timestamps (in microseconds) + pub after: Option, +} + +/// Wallet data for the user +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Wallet { + /// ID of the users wallet + pub id: Uuid, + /// Kyc data for the user + pub kyc: Option, + /// Features enabled for the user + pub features: Features, +} + +/// Features the user has enabled +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Features { + /// Is card program is enabled for the user + pub card: bool, +} diff --git a/pkg/guild-interface/src/wallet_activity.rs b/pkg/guild-interface/src/wallet_activity.rs new file mode 100644 index 0000000..2c573cb --- /dev/null +++ b/pkg/guild-interface/src/wallet_activity.rs @@ -0,0 +1,115 @@ +use crate::util::{deserialize_datetime_opt, serialize_datetime_opt}; +use chrono::{DateTime, Utc}; +pub use data::wallet_activity::{Kind, WalletActivity}; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +/// Data for address mismatch error +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct AddressMismatch { + /// Address of authenticated user + pub authenticated_address: String, + /// Address in the activity body + pub activity_address: String, +} + +/// RPC errors for activity +#[derive(Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize)] +pub enum Error { + /// Invalid signature length, epected uncompressed signature + #[bad_request("wallet-activity-address-mismatch")] + #[error("authenticated address does not match activity address")] + AuthAddressMismatch(AddressMismatch), + /// Activity item not found + #[error("wallet activity not found")] + #[not_found("activity-not-found")] + ActivityNotFound, + /// Activity conflict due to stale client data + #[failed_precondition("activity-stale-data")] + #[error("[wallet_activity] activity data has been modified since last read")] + ActivityConflict { + /// Latest server activity data to help clients reconcile + latest: WalletActivity, + }, +} + +/// Query for a list of wallet activity records +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct WalletActivityListQuery { + /// List activity after this point + #[serde( + default, + serialize_with = "serialize_datetime_opt", + deserialize_with = "deserialize_datetime_opt" + )] + pub after: Option>, + /// List activity before this point + #[serde( + default, + serialize_with = "serialize_datetime_opt", + deserialize_with = "deserialize_datetime_opt" + )] + pub before: Option>, + /// Number of records to return + pub limit: Option, + /// Filter for active records + pub active: Option, +} + +impl WalletActivityListQuery { + #[must_use] + /// Set limit query + pub fn limit(self, limit: u64) -> Self { + Self { + limit: Some(limit), + ..self + } + } + + #[must_use] + /// Set after query + pub fn after(self, after: DateTime) -> Self { + Self { + after: Some(after), + ..self + } + } + + #[must_use] + /// Set before query + pub fn before(self, before: DateTime) -> Self { + Self { + before: Some(before), + ..self + } + } + + #[must_use] + /// Set after query + pub fn active(self) -> Self { + Self { + active: Some(true), + ..self + } + } +} + +/// Upsert payload for wallet activity requests +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct WalletActivityUpsert { + /// Activity payload to create or update + #[serde(flatten)] + pub activity: WalletActivity, + /// Timestamp of the client's last synchronized update + #[serde( + default, + skip_serializing_if = "Option::is_none", + serialize_with = "serialize_datetime_opt", + deserialize_with = "deserialize_datetime_opt" + )] + pub last_updated_at: Option>, +} diff --git a/pkg/guild-interface/src/wallet_notes.rs b/pkg/guild-interface/src/wallet_notes.rs new file mode 100644 index 0000000..c41dec0 --- /dev/null +++ b/pkg/guild-interface/src/wallet_notes.rs @@ -0,0 +1,32 @@ +pub use data::wallet_notes::{Status, WalletNote}; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +/// Data for address mismatch error +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct AddressMismatch { + /// Address of authenticated user + pub authenticated_address: String, + /// Address in the activity body + pub note_adress: Vec, +} + +/// RPC errors for activity +#[derive(Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize)] +pub enum Error { + /// Invalid signature length, epected uncompressed signature + #[bad_request("wallet-notes-address-mismatch")] + #[error("authenticated address does not match activity address")] + AuthAddressMismatch(AddressMismatch), +} + +/// Request body for upserting notes +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct WalletNoteRequest { + /// A set of notes to update in the database + pub notes: Vec, +} diff --git a/pkg/hash-poseidon/Cargo.toml b/pkg/hash-poseidon/Cargo.toml new file mode 100644 index 0000000..5e37a79 --- /dev/null +++ b/pkg/hash-poseidon/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "hash-poseidon" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } +minimal-poseidon = { workspace = true } +serde = { workspace = true } +hex = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +insta = { workspace = true } +rand_chacha = { workspace = true } +rand_xorshift = { workspace = true } +rand = { workspace = true } + +[features] +test-api = [] diff --git a/pkg/hash-poseidon/README.md b/pkg/hash-poseidon/README.md new file mode 100644 index 0000000..60491a0 --- /dev/null +++ b/pkg/hash-poseidon/README.md @@ -0,0 +1,17 @@ +# Hash Poseidon + +> **⚠️ DEPRECATED**: This package has been replaced by the `hash` package which provides Noir-compatible Poseidon hashing. Use the `hash` package for all new development. + +Poseidon hash implementation optimized for zero-knowledge circuits. + +## Overview + +This package provides a Poseidon hash function implementation specifically optimized for use in zero-knowledge circuits. + +## Features + +- Poseidon hash function +- ZK circuit optimization +- Snapshot testing +- Merkle tree integration + diff --git a/pkg/hash-poseidon/src/lib.rs b/pkg/hash-poseidon/src/lib.rs new file mode 100644 index 0000000..2f4c6d6 --- /dev/null +++ b/pkg/hash-poseidon/src/lib.rs @@ -0,0 +1,203 @@ +// lint-long-file-override allow-max-lines=300 +use element::Element; +use minimal_poseidon::{Bn256Fr as Base, ConstantLength, Hash, P128Pow5T3}; + +#[cfg(feature = "test-api")] +static HASH_COUNTER: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0); + +/// The number of times [`hash_merge`] has been called +#[cfg(feature = "test-api")] +pub fn hash_count() -> usize { + HASH_COUNTER.load(core::sync::atomic::Ordering::Relaxed) +} + +/// Reset the count returned by [`hash_count`] to 0 +#[cfg(feature = "test-api")] +pub fn reset_hash_count() { + HASH_COUNTER.store(0, core::sync::atomic::Ordering::Relaxed); +} + +#[cfg(feature = "test-api")] +static HASH_ELEMENT_COUNTER: core::sync::atomic::AtomicUsize = + core::sync::atomic::AtomicUsize::new(0); + +/// The number of elements that have been hashed together +#[cfg(feature = "test-api")] +pub fn hash_element_count() -> usize { + HASH_ELEMENT_COUNTER.load(core::sync::atomic::Ordering::Relaxed) +} + +/// Reset the count returned by [`hash_element_count`] to 0 +#[cfg(feature = "test-api")] +pub fn reset_hash_element_count() { + HASH_ELEMENT_COUNTER.store(0, core::sync::atomic::Ordering::Relaxed); +} + +/// Hash two elements together +/// +/// This function is used to calculate the hash of a parent node from the hash of its children, +/// i.e.: `parent_hash = hash_merge(left_hash, right_hash)` +/// +/// ```rust +/// # use element::*; +/// # use hash_poseidon::*; +/// let a = hash_merge([Element::new(1), Element::new(2)]); +/// let b = hash_merge([Element::new(1), Element::new(3)]); +/// let c = hash_merge([Element::new(2), Element::new(3)]); +/// +/// assert_ne!(a, b); +/// assert_ne!(a, c); +/// assert_ne!(b, c); +/// ``` +/// This operation is not symmetric: +/// ```rust +/// # use element::*; +/// # use hash_poseidon::*; +/// let a = Element::new(1); +/// let b = Element::new(2); +/// +/// let ab = hash_merge([a, b]); +/// let ba = hash_merge([b, a]); +/// +/// assert_ne!(ab, ba); +/// ``` +#[inline] +#[must_use] +pub fn hash_merge(elements: [Element; N]) -> Element { + type H = Hash, ConstantLength, 3, 2>; + + #[cfg(feature = "test-api")] + { + HASH_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed); + HASH_ELEMENT_COUNTER.fetch_add(N, core::sync::atomic::Ordering::Relaxed); + } + + let hash = H::::init().hash(elements.map(|e| Base::from_raw(e.to_u64_array()))); + Element::from_le_bytes(hash.to_bytes()) +} + +/// Hash a slice of bytes +/// +/// ```rust +/// # use element::*; +/// # use hash_poseidon::*; +/// let hash_1 = hash_bytes(&[1, 2, 3, 4]); +/// let hash_2 = hash_bytes(&[1, 2, 3, 5]); +/// +/// assert_ne!(hash_1, hash_2); +/// ``` +#[inline] +#[must_use] +pub fn hash_bytes(bytes: &[u8]) -> Element { + // an element is slightly smaller than a "u254". For convenience, we're just going to pretend + // it's a u128. If we need the extra perf, we can be a bit more compact here. + + let initial = Element::BYTE_HASH_IV; + + let elements_from_bytes = bytes + .chunks(core::mem::size_of::()) + .map(bytes_to_element); + + core::iter::once(initial) + .chain(elements_from_bytes) + .reduce(|left, right| hash_merge([left, right])) + .unwrap() // there's always at least 1 element +} + +/// Convert a slice of bytes with length in the range `1..=16` to an [`Element`] +/// +/// If there are fewer than 16 bytes, the lower bytes are padded with zeroes +fn bytes_to_element(bytes: &[u8]) -> Element { + let mut padded_bytes = [0; 16]; + padded_bytes[0..bytes.len()].copy_from_slice(bytes); + u128::from_be_bytes(padded_bytes).into() +} + +#[cfg(test)] +mod tests { + use rand::Rng; + use rand_chacha::{ChaChaRng, rand_core::SeedableRng}; + + use super::*; + + #[derive(serde::Serialize)] + struct MergeResult { + left: Element, + right: Element, + merged: Element, + } + + impl MergeResult { + pub fn new(left: Element, right: Element) -> Self { + let merged = hash_merge([left, right]); + + Self { + left, + right, + merged, + } + } + } + + #[test] + fn hash_merge_snapshot_test() { + let special_cases = [ + MergeResult::new(Element::NULL_HASH, Element::NULL_HASH), + MergeResult::new(Element::NULL_HASH, Element::ONE), + MergeResult::new(Element::ONE, Element::NULL_HASH), + ]; + + let mut rng = ChaChaRng::from_seed([0; 32]); + let random_cases = core::iter::from_fn(|| { + let left = Element::secure_random(&mut rng); + let right = Element::secure_random(&mut rng); + Some(MergeResult::new(left, right)) + }); + + let results: Vec<_> = special_cases + .into_iter() + .chain(random_cases.take(100)) + .collect(); + + insta::assert_json_snapshot!(results); + } + + #[derive(serde::Serialize)] + struct ByteResult { + #[serde(with = "hex::serde")] + bytes: Vec, + hash: Element, + } + + impl ByteResult { + fn new(bytes: &[u8]) -> Self { + let hash = hash_bytes(bytes); + let bytes = bytes.to_vec(); + Self { bytes, hash } + } + } + + #[test] + fn hash_bytes_snapshot_test() { + let special_cases = [ + ByteResult::new(&[]), + ByteResult::new(&[0]), + ByteResult::new(&[0; 16]), + ]; + + let mut rng = ChaChaRng::from_seed([0; 32]); + + let random_cases = core::iter::from_fn(|| { + let mut bytes = [0; 64]; + rng.fill(&mut bytes); + Some(ByteResult::new(&bytes)) + }); + + let results: Vec<_> = special_cases + .into_iter() + .chain(random_cases.take(100)) + .collect(); + + insta::assert_json_snapshot!(results); + } +} diff --git a/pkg/hash-poseidon/src/snapshots/hash_poseidon__tests__hash_bytes_snapshot_test.snap b/pkg/hash-poseidon/src/snapshots/hash_poseidon__tests__hash_bytes_snapshot_test.snap new file mode 100644 index 0000000..b98b93f --- /dev/null +++ b/pkg/hash-poseidon/src/snapshots/hash_poseidon__tests__hash_bytes_snapshot_test.snap @@ -0,0 +1,418 @@ +--- +source: pkg/hash-poseidon/src/lib.rs +expression: results +--- +[ + { + "bytes": "", + "hash": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "bytes": "00", + "hash": "102e556ec4988e1840bf21346caf51bd80edf235c54387f24e58e2f336f6e4a8" + }, + { + "bytes": "00000000000000000000000000000000", + "hash": "102e556ec4988e1840bf21346caf51bd80edf235c54387f24e58e2f336f6e4a8" + }, + { + "bytes": "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586", + "hash": "068cfa03780d4967f5670faf1008c91edd2a3e4e4244ec0858318c5701a56f49" + }, + { + "bytes": "9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f", + "hash": "26fa8d8393219e0828bf907e1e8ebd72a3702381b06284b9a69294ccb2be86ab" + }, + { + "bytes": "2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d012737681f7b5d0f281e3afde458bc1e73d2d313c9cf94c05ff3716240a248f2", + "hash": "18a3f1363de6e8329f97956fde64e7fb7ffa0ecf922f5b15b2745c9765777384" + }, + { + "bytes": "1320a058d7b3566bd520daaa3ed2bf0ac5b8b120fb852773c3639734b45c91a42dd4cb83f8840d2eedb158131062ac3f1f2cf8ff6dcd1856e86a1e6c3167167e", + "hash": "0ec34a7f2a24f5b86d6d880434c80dbe7299a3ea6beb6f2fbf88216d5f6373d9" + }, + { + "bytes": "e5a688742b47c5adfb59d4df76fd1db1e51ee03b1ca9f82aca173edb8b7293474ebe980f904d10c916442b4783a0e984860cb6c957b39c38ed8f51cffaa68a4d", + "hash": "103ab6eccc18dc56a66216d41a5a142ce920ecbfff9839e61f009b2ca5a068b6" + }, + { + "bytes": "e01025a39c504546b9dc1406a7eb28151e5150d7b204baa719d4f091021217db5cf1b5c84c4fa71a879610a1a695ac527c5b56774a6b8a21aae88685868e094c", + "hash": "1419156f88c7ab5cb496225108d90812d6468b5c20ecb3b52d2f549449b3b14c" + }, + { + "bytes": "f29ef4090af7a90cc07e8817aa528763797d3c332b67ca4bc110642c2151ec47ee84cb8c42d85f10e2a8cb18c3b7335f26e8c39a12b1bcc1707177b76138732e", + "hash": "28dac2e53d9c5cc3c3cf5fd8b53343ceacfbef028129b7818609cbcfbefc22dc" + }, + { + "bytes": "edaab74da1410fc055ea068c99e9260acbe337cf5d3e00e5b3230ffedb0b990787d0c70e0bfe4198ea6758dd5a61fb5fec2df981f31befe153f81d17161784db", + "hash": "2fb79d38fc3ffca7ea2c204ca4fea3ee5d30ac18867e1baaea1da374e3470119" + }, + { + "bytes": "1c8822d53cd1ee7db532364828bdf404b040a8dcc522f3d3d99aec4b8057edb8500931a2c42d2f0c570847100b5754dafc5fbdb894bbef1a2de1a07f8ba0c4b9", + "hash": "1de5b5b1f367ea87d17526b2cc9bf0a7da4713b8dd103cbd3856ca5684fce3e7" + }, + { + "bytes": "19301066edbc056b7b481e7a0c46297bbb589d9da5b675a6723e152e5e63a4ce034e9e83e58a013af0e7352fb7908514e3b3d1040d0bb963b3954b636b5fd4bf", + "hash": "0eafb872b719d77eb34bed1bdde08065670ae6ffd7a9dff5596cce3f5023af43" + }, + { + "bytes": "6d0aadbaf8157d062acb2418c176a475511b35c3f6218a5668ea5bc6f54b8782f8b340f00ac1beba5e62cd632a7ce7809c725608aca5efbf7c41f237643f06c0", + "hash": "188b5ad7f42764b334120d2f385579c177cb37c377918052b50d9e924ff3aacc" + }, + { + "bytes": "997207171de867f9d697bf5ea6011abcce6c8cdb211394d2c02dd0fb60db5a2c17ac3dc85878a90bed3809dbb96eaa5426fc8eae0d2d65c42a479f088648be2d", + "hash": "0c3696f19c71860db97b75b095720846eaefea80656d349b99407005bdac19c3" + }, + { + "bytes": "c801d82a366fddc0ef234263c0b6417d5f9da41817b88d68e5e67195c5c1ee3095e821f22524b20be41ceb590412e41dc648843fa9bfec7a3dcf61ab05415733", + "hash": "290829449c2797fafbe8d0fa02c9ef258bb4dca2ee3749e7cb36ccc1de088b66" + }, + { + "bytes": "16d3fa8151629303fe9741562ed065db4ebc0050ef558364ae81124a28f5c01313232fbc496dfd8a2568657b686d7214382a1a00903017dda969878442ba5aff", + "hash": "0ba9500f213047e189e6f70fedbd69fc3679ea3113dc8d690056bf6754c3bdeb" + }, + { + "bytes": "f6613f553cbb233ce46d9aee93a7876cf5e9e82912b18cadf0b34327b2e0427ecf66b7ceb7c0918dc47bdff12a062adf07133009ce7a5e5c917e0168306109b7", + "hash": "2590f56d589d29b95c16b51e2e531a4ba7daf4971051f1115b87dde3bfdccc9a" + }, + { + "bytes": "cb49653a6d2caef005de783a9a9bfe05381ed1348d94ec65886f9c0b619c52c5533800b16c836172b95182dbc5eec042b89e22f11a085b739a3611cd8d836018", + "hash": "09dd0330bf68fe8ddf46e9c89e6e7a1b99ea1821131647badadf7d07ba6a2858" + }, + { + "bytes": "c4fff0b86c02ed662d2d2522647a1f09a7b2f9eea56e7e20b1f06ccdd9cec37e3b2d20812df369978636c22646603675804104745d2997e28df5d8242aad19c8", + "hash": "2111e9c08ed4fc693fa0e2b46b3ce015c58edcf1322936c8ce207b9848667f83" + }, + { + "bytes": "120ca4142fb6019fccecf9fadb04ade03b341e3fc77201b3dc957a8097ab2f615aff142ab753811d5f32e75bc8825b456555f3d179ffabcf35f6ae61365851f3", + "hash": "059a780b521e12b2905402e2f17d46c46fad16d58c2ed6b2c3bfc7e5fbf8732f" + }, + { + "bytes": "f681a2e86e8078b064976646186394cb9064767750dad4e336b8f1d20fe2c13c6248d3d73d4d66d9c8587ac68a7976a3bbb8b5808320607400dbdb1918e3d3b9", + "hash": "204ce0b85a8a99ea08fa61fe7186b85d405eb7aefe7c8fcf7a8fb8d69ddd76ab" + }, + { + "bytes": "0cfc38c4ddfade990a213d208fbf7898334f4deed7e5830fd266751315435ae19bb94f4d3dc92652f243dd1f96f3595ab473d2356d8fa8f6d64cc4f64b12ca99", + "hash": "233069a6e962ea295769ce0074aac53bf62c411f4ea0c3a66f08672845e0b6c5" + }, + { + "bytes": "ecdd1962572e6add609d9c619aab678b3fc298bc2f0f81feb4f0d3ebad7e850a8bcb52ca467e649de2db913bfda001294c49dc369f7d14cc25c5fa65d4d5af6a", + "hash": "18e28dba428731c823b7e78f4646ca1163384e3e12b750d29bdde002b316be04" + }, + { + "bytes": "436d22bd2839be23dd3c57825033fecdce2ded6c511dbeaf4df2b4cbb7af8215bb48a550f57d02750e599298f512b1ec1829722fc10a5acf9537e392a7284559", + "hash": "13abf1bc69b6754300d863585fb4163e8d6bc181551955492d3cf64dbd82dcf8" + }, + { + "bytes": "05d3ab4837dece4b63fdfd5dd07a2b76a8c82566df1a2167dae5e125b6aa0e76b9d99ca84664f50eeea54e449f0e587039137f57543d89205483141c933166b6", + "hash": "16b4e785020224da4efb4ffe067267c50dc79d3043c544e621cc9eb0fe2f9f01" + }, + { + "bytes": "1990a706aca07f467d22bc34c6552f5bba91cb1fc21db51d03dfff6523a5e1b4285d54c47660eda1b290e4087b30651b542305a714e98a8233577d2afb383e40", + "hash": "1da5871c297a9e5c819eb7d8f3e2a28e9d92a21ffa22d7e992dc9034eb77a784" + }, + { + "bytes": "2f6b9fd214b194c738886bd2289cc5f997951910994b0a6104092fbc9b385639343cf26c9faf845e7a98cb1f2c9306e8200185d95de059f83ad17c4b97f8c62c", + "hash": "25752ff4c6cb3db5c4386120065eb8fc79a22731b5fce3f909f3fff8e1523dda" + }, + { + "bytes": "f6c347dc6eb5f2b1f4bf2dd328130d4500ca39beba2d4281a3d8ceb4cb1ecde378b20029fb6a4c543312e41013915c57016e5da681944cc277f9c7e75f4a654a", + "hash": "1d9c70c2ebc5d1e9d031f8e78c59f99816fb55fc8268ec4ab07ed3887864f52c" + }, + { + "bytes": "b2e5dc646ada242b6223aacc63674f9702146723360811adbdf2bb938b595bf4c688a8a844130d9da3f0efe3650c2283640b342f8922fb6dd10b8bbe35c7aebe", + "hash": "2ee4837c966e77d1fd27f987cf2cb3a708e0bea78b794cb6fa1fb210e33066f5" + }, + { + "bytes": "ba416cb0180fb7d2b171149018f8d880463ac26202c2b72f9a7cf83a917ad26183f8e74cd418e3b63459f7ad59849ee43cac6df3bb63fceec1abe8e9e0b64b23", + "hash": "04294f4e6b9e30137dd89251e5540a4c139c4a75760243a65e5e67216d194d70" + }, + { + "bytes": "3a43aac54f9ba0998d2219b3baca111940d524b7cf94677d6c557750fa4db9e1077eedb5ba6e33c104ae25443c86bf1583353addf6fddd19a4ff491188e3d487", + "hash": "03495d1d5f98442ee789cd8dce174319cecbfa806aea90ae5c0a49555f64acbe" + }, + { + "bytes": "8769611b36427c8f4c705cf42338475c3185c123919b79b3a4887243b924509c9a4e7a3fff0517021e51642d9b4526c28a0cf86fb254be7eab18701ca5919b75", + "hash": "25e16cadf918e9f578cc71d28d4c477a947c6e93e4a69172ff49b14fae8c7106" + }, + { + "bytes": "4ec2506eccc087ac6141b4c3a661a3d1a89e0d4dd2df52caa5b3402d0026b3c643fa7126e8ed101a94188a048b34ab61e1182d6be76e2e9e6acf401443ed0d99", + "hash": "0810ce769d07c6e70c8e84ad669e573748299a9bd83edead0b0b0cb6661f0fb8" + }, + { + "bytes": "7dd5ae67346cb1e189791102900225e6b955cd7c9e39fc7255021045fe7ecd40e2c68486a4c2fbcdbc53e847790dafe5b2cbdca09bf09de327076c79f2a339a9", + "hash": "2da1299e76daff979e0a31d21dfa74bc8c543b4acbd136adb26000245d638ff9" + }, + { + "bytes": "f942dfa372b41a390eabbbf296383d438466ae6105b5058117b8e406dcaa62a98ac624d30bc8773de643cce7578e8d5c57c5718711421e6d04a182f8714e192e", + "hash": "1a9f07a0d6e08a503db63fe522413bf5b3b3e432b518bc37cad9ada011614be6" + }, + { + "bytes": "df3935cb2e0380e10c77aa6583832deb64cb41dc401541504e0420d06379e4830f06125018db3810a684c4e888b3b88829cf97ec67fc8549703f9ea5d6b8f67c", + "hash": "0e0edc83004309f4850056ccb71553ca533aeb04f5c7e991f0d2e9d2ce1bc1b9" + }, + { + "bytes": "e9e060f765532c323db034ec700db819936fbe6f749fd37ce927663f439498c98c5104d69ae9cd8b04444a471f95390873346858625420ed783203f8db371d76", + "hash": "078a448516818b9ea2d8fb5e7230118a58b67b35c475acc02c56e91dce54d5f7" + }, + { + "bytes": "6586137459505525cb3ee59a7fd8ac3c1db3f5f4e0dab62b43d1c4cd813d998ed83637f922f884a7584835bcdc03e9f1802b449dfa2d249d9ed7f2f9129815cd", + "hash": "223a2d0e67ea8e4b88b90dd00ed7547b81b17a867381c16848115413a721cb53" + }, + { + "bytes": "8d4ec4169ec51eac449ddfa5bc0f232d47323d4c48ab558576160103820d485877cc2bbab641d21d94e67b32cefb4e9ce5dac84d03ed3228ea3cdddd33f3915b", + "hash": "2d4f399ead6b2cb1ef63b08ce5dfb5027828392b6932637c3cb96784f8159247" + }, + { + "bytes": "9e21b435bbed927a539b556ffcdd4c9822fd1ce81acca79b6f7050b0c01a3a317f066a1a89c81e4df8c7ee2e042203be8c290cf8605c193471953f8fe6055ac5", + "hash": "089838c8c5a7688efd95939263001414879081bc6b37dd0dd3388a1dcb0111df" + }, + { + "bytes": "46670a4a075f70909246c3e3b92b39cf2f35ab49fe6fda67072a6e1b82364820477fd522a746eac07e0398e873790486abebb50ec59a9e4129b7cea87c5182eb", + "hash": "0001488018d7947875618da7641ed2aa54119899a9fd0d33d8d1e3c6e165cd77" + }, + { + "bytes": "43bcdf096ef740ef67482e98165a4ec64ebe9d57c8d8c16ceaa81f3203dff26b3d5bf01edc0b0458b6b47846c326c75a822fc8b42774a3b201ef941484631406", + "hash": "1a83469726c27ef7f30c942123edbb7a39de1d4c37fac160992c43373a567727" + }, + { + "bytes": "cbbeac961ccf42860ebac578703b485844bb9e01b2d6c2df72b62b43bade982b0bdd0501230fc76b820d2f5bd259ec791b33225e06afc2d996c90e756dbd4257", + "hash": "01453c6ab15594ce9baa023ffed0b049fbffbcd573a1a543bacb2731cf241e4a" + }, + { + "bytes": "d53ea6d6ff2371330035b57bf54c9dc4fa95d61536aac11cdb08a664efb55bc91a4c6f7fbe3efa8c621fd9f2cb343898979e7bcbd55b55217143493b6de415a8", + "hash": "2bdd398bd4b3b0f1f84da92ceea2a9e31e57c59d04e71c1f6a3df7606c9f60a5" + }, + { + "bytes": "5d681a2405113f3ada3edaee6eb0e78572d2baf9c43e3fc39b93081cf2fb3f8879e810f417b733927525acb6d026f6ec46395620547d057a539a391de7c6f4b7", + "hash": "1e8aad5072af1ddc8f5edabcaf4badfdad253ec6067c85e224baec90b748846d" + }, + { + "bytes": "095911c2d3ae075ad4f2c0c96d9f70e48a42cdcdae542bae833eb4a976d4f98410b4a3d77857762d1527ec6714a040baaec3bec41bf9cff00e1cf81ce61e95d9", + "hash": "04ba416167def3e7d57aeae0af388ebc118e0996e1dae3eb53bc6c393319646a" + }, + { + "bytes": "7792d7c0db7a88545f10d9b0a5940457018817725da257766906ffbc6172b9c4d2d32a14d00c0d1d01e15280074a4a9fd2d21393f078ef55b16cfea532799326", + "hash": "208d6cf2c9e52bb96595dd43f3167486d4b47dae2c653876f581f7c37e54ecc2" + }, + { + "bytes": "3bffe8e99e56837b2763abd221ed85d83f9187af8b9e928f00deff423fffdadb786e6678a59af305cdc02546d0f8ab4681acc1f00069b0c47bbc9f13d12fd941", + "hash": "19327f6511572f0a4c051c314405074acede8c4d892644f5b33c47051fb97414" + }, + { + "bytes": "1f8df532096d53e4b7861839e602fc5dfa0d0b72232dd81d2b0e4b660a7eba353da27e66ceaf2d6c7734925247281866a12d67752a1edaadd1ea59e4e86e2e85", + "hash": "2cf1e40178a8ea4e31d176db012094ac5f5ae4e0f8eab1b506be6d6d9501fe7a" + }, + { + "bytes": "a81a573cd68f6dfb526558d81a8f488f261f355ddac23f6caf07d27fda71d8f3968d4ceeda89a09dcfdd00c17fa6db3658cc7ab02c0e5f44b1f526a7db9269e4", + "hash": "11d63283e60ee6c81078452f040841da8dec627738ee0a0aa9e265e7046ea5e0" + }, + { + "bytes": "dcd1d11b8421c204c07a5de46e48769579718c69532f1671e552b92ef1451ffbc7a2f412696c6d67ef071c988acf61f39319ca02dc853247be1f7f07b3bbd68c", + "hash": "1ffb4aa15a29a2ddeffecdca78a5437070c8c4024bc5ed2894a80d11ef47553b" + }, + { + "bytes": "901ef36d46868f65d0fa1d1755eff6c2802212908250207ab65fce827f0a82f3140ddc692cb5742b3133c541e0fe17718b546ad1fc8cb8a3a5af69a825a84343", + "hash": "07537e09b6032fd0ad7ccc017bb61f65b38dae2153b9341a2aa9a6ca66461479" + }, + { + "bytes": "c378d7b54f917057a8d026d4a59931ff9e24ab95bce2bebdb3a4286e000a4c47e74cf82925dea07686dd20de228828705d90638661173e703e712d69b043dceb", + "hash": "15d8fb5316c1c76a0988b92df996eb6620b93f096d0d33d30062b0c2114b2ce5" + }, + { + "bytes": "afdc53f132be3d04ce50d70b80dd118db00e45dfe953db87525880ba9f7abb0fc481a5f3acfa363aa2153391aef0dbf680512a0fa37a6c8293865ca95015dedb", + "hash": "18b045f7be93f4eafaa942a26611e02bca41ddea7ee391c04379736b38f5b611" + }, + { + "bytes": "f6a21992ce1feb5f499359e288a3255ef3fbaea5b01440bd787251caf362326c7ffad20086aa7fcf35e95bbf398db75735e087e0863e016246703946c4e88bca", + "hash": "19205581de18f03655923d9f316099a1bffdf5a47aa362b87e3d9fd4853a6c74" + }, + { + "bytes": "6fc21446146bd342aae88ad4249f9a38ca3e4ed0a88aa6fd746f578e5b414ce0f2ce5ec76f87fa3b6321102ef7110b7e6d889b2b85bb11fcfd4ab2b3bd5f92b8", + "hash": "07b089a5c514dc9b9391a83c08792dbbe13f404ddcb7a62cec3ca61dbe80193c" + }, + { + "bytes": "a2f66166f0695c0b13f32f97efaa0cde4f28e1674bf120e03fa15980873a1c6ab674c085303fdd74832cc1df5ef787ae11c6e6a9302c1488f36996c170367078", + "hash": "0115369bc6b91933d36d0c30f87ad01217e79b8f9b1d40d89f6f95808d3f6e70" + }, + { + "bytes": "6c05324f99d9d2cda1624db95b8eab6f7e10ac5bc985d6536cf667307a577a2555888bd9302cfe704cf72e59fd28b6daea343a83531a10a732d65ce93f523a03", + "hash": "1f05d86a655148d7e9ca07d52504749a4c62080ec230ea8c6840fba841b78b6b" + }, + { + "bytes": "e5e791efd5ac502bb0a1f756e93208746240bc7bb1c085728ccc8150d8ea74b33aebc59567e65b7e2bd83699f607412448d202d948bb111badd456d68086ff9a", + "hash": "2af96a520085268c18299f4bdb587b96008a40e825b7464c1bb79022bc256ebd" + }, + { + "bytes": "5906ea3b2cda4111d3638391f7a7b153eea77ab47215d6fe13b350f59f884c6e31ac087239d9145b816424cba2c8bcb7b3ed7e19638089d91e5c9136d2aefc8d", + "hash": "1a2d7bab33c7cf992b87f7399a0695af1d9cfecc8deb16179e55452f891ba2d6" + }, + { + "bytes": "a165284b42229a70346296a7484648daafb9b88994d8823efbce9e029ace51706fc1e6e194b7d8906bb83be681a96d50f4a66f5af24aff5007aa2052277d75e1", + "hash": "02f078c40e3848e90f9c4588588e1dfbaf6be4dba79999e7ff885eaa4e63da98" + }, + { + "bytes": "c6fcb719ae789587e73bfb11029b2ae9e380cd7b4fbd78f0c5318ef61802ecbfe5d91ba28184e96963366be3d5b063b5b664002ab0682e5820e3f9d30afd461b", + "hash": "0f4a1e1dd227f0dfe1080afba9c2dc9691ee8e13b7a0bc9aeb82a945cecf9af7" + }, + { + "bytes": "3046cfc86f29605458ae94054cc2967ca77f102f97bae3454bc190726af88cffd5f0f05e18d31159ef2a9d9800f48d1b6719617474f1b3594315795822976613", + "hash": "1e8a5945f1e5f8aa610c8363beb60bb43e748c76a00f2dc888c24f613f7ca2b9" + }, + { + "bytes": "cb63a4d6996505f4a4c57f3454ec101f5303f5b84aa8236843fc51d63d8445ad5c9b4f4e15aa0395695cde980a6d48936146c519fb84ab775647e2cf809135d1", + "hash": "1a50ff0436cde00ed62d634a6d6e7a1c806659a4b82f45ce789b51856db9a7e4" + }, + { + "bytes": "0b12f7e632654c679f92988b79021746c867a8e05102bb98f8fe7d3d7c005f690d9ca7c6a175ff26ed82b873d63df4cbea0218bad0cb9a8c4404526f9806e2d4", + "hash": "0d3488cc56c41a73750283bb3cd3d17a200193290ff628cffec67a66e5237083" + }, + { + "bytes": "fbf37e84b756561c67c3a5732966dc4f0701063eaa7d3a52a2b5e4a8c9acdb30ee8b9f5125f76bcf7b22db897de9a8a9560c54118f31dccf49e87527d188fcb8", + "hash": "127ae090c6e67941f7f58d46a6ba58f19dc1a4993c2b98cc8afa84278d926f42" + }, + { + "bytes": "1c6f5b28a37a1dad399f8c4f2d2cedd0f71a6937c10aa78e29f82b4f5d12e74efa4fff5a8b700664959913542472af8df1acc815617dffd8e01873b1290e5b94", + "hash": "0c03dbddd2a82389f84b84be4fc83c3ecaabc71be8228f1d98a42e5c72777c41" + }, + { + "bytes": "fc2e9349517916ee0f7315369649f30a5a9feee736882f82b5e4d0ffca74cb98dab997217f7a461a34b4e7a87a933c6a2a21a63ba0437a12c1368cd74e621f47", + "hash": "1645e98be7486c4943a3ab924aa5f7dd9f8239ff0aaa65e2b8c61daa5a21f18e" + }, + { + "bytes": "4d1921742f5adbb26bb811fc0eb71fb828991bb21b8089897b83ae61d2c9d015dcabee391edaa47c8814d76ecee6b7af3979f04e1c52b4bc3d5f46cc79301fc7", + "hash": "0ce006bbb3990845bd8f8cf3ff0203b6b8c129c0c9549fef10104f036e26d02b" + }, + { + "bytes": "40693a47db68c22a39fb722e32605a150fd57c56ae63ca90e40059f26b6d5a73929f48ab33f1130143850fe2383e95d214cf585971d8d14b10175ef1e06b540d", + "hash": "0b93ffb5febed1dffbcfcfc830c7031c1c62936a1f0064320ca445e5e8d92c48" + }, + { + "bytes": "8f9e3e29f60ed31e7a8effe89a827cd82b647739105d305188d0f1d628187dcad530fef13ffb3959016d7271d2ae5ed6750591c774c0458468357676b6e16dfc", + "hash": "1d6afeb8137b3233dbe2f354a934e143cce2b39e57b5135d1d29e6f04b0e82f4" + }, + { + "bytes": "cfaa9aa876b986ab6334f1dd995c400ec2f54d837547a59632f8ba09f076be49be6ed506c3a8ae3482140720d9459ad6ceb67c5878a3d470e35d8cc999cf2309", + "hash": "1c096ab82240188bd7eb89bdf02d7158b009082b3f18e2cdccbcab6c86c91aab" + }, + { + "bytes": "305182e87f493edcefd416f8508d45ba6d63e06068a37292c4089a44a901ca1a216199258016bfefa8de980e3a584f80a91be8e7f24f58331bf5fa241834b613", + "hash": "11441a5dbe9b05236553fc944ea1f3f8df58492b949b2ea785fecfc6aad1640f" + }, + { + "bytes": "38c97b885891b18fa38998a1653518ae7d789d760f4ca8d468092e26bfae63fa73cdebcc3309068f4515b14fd2fb2362ee2ef7e29f479fd1beb55b485ffac908", + "hash": "12cb130fe0cf5b047a8b0475810845859cd07bfaa5525d0a13d5053b3a362b5c" + }, + { + "bytes": "42d56a92fddeb287c383761677bdb435cd93c38b37b9c09ed22c2249f991cceceb89d151340af1a2f4bb084725358747dcc981de16d44d3c146065d591e91ff9", + "hash": "297ca99de12123a2e1a89196dd13997bb8c906869ac6870ecb3ce82b5a362987" + }, + { + "bytes": "856a6fd02f673aa0330e9bd7158d55e5adbb21c367dc2259e7015c567832d0e456af9602c93ec4d1b131a3d06d42a2d9d5d4d0860ba9199ee2784f22cf98aff2", + "hash": "130ac093a2acb779d38359efb84ceee1dbc841124315f4404cc1ac23d533860f" + }, + { + "bytes": "7e6da102dd36362d7bf76a6c1ea387e0cb7102f8abd40ad2e9d8fafb79270cb7c81138cbe246c0d4e7c70501f2975c155b6713511e8c2cbb7db2a83e1a486496", + "hash": "202f655a01785d606cd3ff3f42ab5401abc9f332c59f83db24dfea12e37da818" + }, + { + "bytes": "c2d922cc229cdb7d207f6bab3a15bc83fd3322d5af189d92b91e22d5b461c0164d55cddbb1c4b2f9ade5e5509c1dc0d4d2901ef7e844905e226e7de848baf023", + "hash": "2a7994a9b6da8d8dfa99319698b10e62311f1cc3eb69c9600c458aef7d4263b8" + }, + { + "bytes": "0f662fba30d7f6f6085a0d3190ffea1f3f58e3d41ba50b72d4a4a49fbaecf4dd2f2cfbbc2799d45da1f4e7072aaf99928b3ec2bb70f30ca0c61201b524d042fb", + "hash": "083804433ddfd2e3a2f2f26557b46e869bb643cacbb2c30b374f6f1286c6e683" + }, + { + "bytes": "8c87e11160769b7b004c34dcd33194276815bdedb37644dc6b3d8197d891e4a6ef9fcac6cc7504dd7c7207ecff088c332f38490584b9c7edc494a504a67cc8da", + "hash": "15b5869655370bad2fd51cd36e46597120a35a3cc8744fd71804a138a14015ee" + }, + { + "bytes": "4cdb8b378d96420aeb69000a3bf5d56201412abb9d74fc58c48822b002a06e4a43f3bfdee8a97d7cbce9d30619bd2221ab592ac2fb2f4983a384ad500036efb4", + "hash": "18e087ddbaf615f6af33cae872f34b1f7b5fe4ec85666e72c05b28fb771e2d69" + }, + { + "bytes": "f57060718c3e158acc124be4cdbac6769f4f2d31f94ef248336b6306fe8ff561083d381e53a4753e00c37215b3bda81c865a3b3d13696e0ba0d7e693acfc2604", + "hash": "208145c56aa0b04d83826b98f2cf52c44c4fbf1f9d0e87b7207deec07ac75511" + }, + { + "bytes": "1dee4be85e40d0315f2e333b615d4ee2ba10fba1c2ad0cc752ae4858634eddf5ae30a213a2e49f4c754870f76a6ff7d99aed38765f629d3732a306a3437f9afe", + "hash": "08577bd1fe2c52bad868fa26f782f7ca4175f2c1f24693ffb2dbed3435b9d231" + }, + { + "bytes": "de3bb535558d42c12dff44b828ad7be8cac11b42bbe6a93fe847c720f878cc952d07a62966d9e71434b0e0a8a7954434d56846d3b4a3fadc49cd0a1c9ae41d9c", + "hash": "0810e124421a92d49bcd3ecc7dcc54ae5093c00508655b1668fba6d5cd565993" + }, + { + "bytes": "d6621e6a2f941085674640294fffd3e2fa4f42156e5479f44f1a91da28475f8ac5b2be3f6f0f2eb67f08131a44f7f55f2632e809823f5a9277d5bd1de1469830", + "hash": "2807a9b510a869d0b8ef51229dbc27dd2085fa690f498c5271cb6e587e462f9a" + }, + { + "bytes": "a9274e953f7df569235e674461bca46af7920a0b211d2ee8178f74fbf68c1724d1b3c5434167e5f0e2e921f3fb6f722c843d40f8f58b7c8018b01d102625e29b", + "hash": "0ad91e7a58613e4b7e983143db5cc00c2e0780a389d4def6223a82ab42c9d9bb" + }, + { + "bytes": "e2af5c555bd3f739a4f3edc6da860a5d75f6a91a5d184ffd860fb9a53564e73b5d240423a653f1e809e5db896de10fbe8040b8161280deef34840351fa84ffd0", + "hash": "1a02a6db828263e6395cf2e95bfc1b86bbede606ade7ea6af828ffd49a53e545" + }, + { + "bytes": "788437c9600828b8de20afb4688e27d3caf3760896c50ef81fa3cfd6074436149b85f754b4f314983667e2a37aa9328f71a63cf59b0b06065991ff6ecf22c90f", + "hash": "06f97d19bfa6914f1fb695f40ed3c571fa31bd470ddb42f7c26871d02397cd57" + }, + { + "bytes": "a09660d21ef0e3e991e245ed30b4b04f17472270f998ad080bce5255689d064bbca3052aab260b768fbec6a56a17ee54d4c12cd96558fa469c8fca1ad972a259", + "hash": "186d42219a9661374c2791ae36fc74aee3818a0e435b48adb28139ec6cbef3c6" + }, + { + "bytes": "f3b84a404106af36c494cb830d3e0cb01b6b44ad7826e478a34fdfa7015a91e3b3a4c08e9428a4cb102f251a7977b235ed425b7ef21f1e5595d92e5252d4436d", + "hash": "0b1427912ba92d1bd012c6397bf493301c36002370f33639b29f1292da26e957" + }, + { + "bytes": "1b9df198f83db437ee90aeeacf94af024ffd87c3d2b3e6594a75753cd2967fb4de858623a29b06feb432a72a535bd981bc6ac99710f2308e8ab17654d1e2bb12", + "hash": "24193c636126b3d1a59900d58a48fb1fda7541595f9a6f930dbd349b4fa36b01" + }, + { + "bytes": "f0d01f6c9ff71befeb0b8a8176a3cb3989b76797134974d19af22d03f60bdb4e814de7109030e90ce8fb8d114522fe2b06792677ae3f7d235dae091ebce1e537", + "hash": "1461275a5b7fa7dc59f6607cceff0cb1b5388932e554493edf097132586dabe9" + }, + { + "bytes": "0694c6a51db474c512fc285a1ef1fd474daabb93262d07490193d588f30860fb834100093fb78ffa85ed4d0aaad4194ebea9059da23885d4efa67bb268ecabda", + "hash": "2283fbdcf5be6c57592bf417d79b50928b06a4a3a73bf9980b7a1722a2d71a88" + }, + { + "bytes": "23ea0f4618d0c4fd7b7739aa04212c276b4a9cc4c572863a2070a8e7f03b11a94535b4faffdba896fa0dd006eb5507b171cc12b2cddd381fbac78da4bf99ec1e", + "hash": "1f76098052ecfbc38ef35c22e9bb85760b44c71c7242caf9234e7c829eaed6d7" + }, + { + "bytes": "9c19e5aa5adc6a4725272018970f1b64932e09d8a2f073ed8a69bf983884417cdf62850ed3fefafa3287148fb864768fc61a3ef2bbba86d9b9fa3d116d00fa03", + "hash": "1082a9a1521c0b3bb281d1f437a716a0718fd2559c6892976b7410edaeafff42" + }, + { + "bytes": "ccba91d7325350eefa4efb7741618ec791ff5be602dfacfc61bdc360a30d0ae16ea28d7b8704070593cef54b05de23ab5b3fdce377a6922919909f5208434685", + "hash": "0d3a03d986a16e94c14f9b260b595284585cdb86406097614f70039d38800f6f" + }, + { + "bytes": "df43a63c66f441729f04083af63ccf2ad09c6bd90e0340f7326cc07b715cfa20a02c6c653a939234ed302a4f7aafe658577fc1ef924e9b134aa59fa4b73eb0f4", + "hash": "065d564956badb8a16d8ed09506507c8bad11436cc108b58e43effb99cbab149" + }, + { + "bytes": "ebe5842666a94d53ed8b1db65e07f0c224a749aa57f1f2960845705dfa1d552c514ede74700a3e7412852399c9fd28b5ca4d6b53128ee47385108572f7e2cfe4", + "hash": "06520687d011a23baf7e77a64b847dfcd2d8170413c3f2d6bdb224ef2b90f995" + }, + { + "bytes": "8f530d653193e12de05ec8ea31e9f040b0e7f9faeb4ae6928e630eec7bb33e213c3b8d0f7b26050a7c1a3daf7c81957814165291d76ea64e9c1d2a61bf28081e", + "hash": "284b07a3b68c0132562e7a8cad561fb544f95127b8c77ab8ba80d90c6389e27d" + }, + { + "bytes": "af4c29ea559d2ef584f4dc5346c5468eaba16716c7040c9d39a46373ef4c622027e67cc971be8ccb6f4729fcbd341023a76b81a396f3bec9783f0a2547e66dbc", + "hash": "21fccddd3daa2439511d32d2bc40bbe7128e674a53db34af66ee646b882ad31a" + }, + { + "bytes": "6d44bebd692e60522b515035f58d51696212f509323d8fdf4f81a3c0cec5d807b15ab900a61287064846d1b0b66af50f2a730391fe3f677e5e84d10908d83e18", + "hash": "0ff986037ff20dfb448df80b858101ef7b4e70958e1315dec1e613b081148378" + }, + { + "bytes": "0b36b96a99cdbc6bd4421b11be569976680031f71af13af66ed3b5659764cfe24f947ff376beb30ffd1e60ebb693703366d7cec799d26c207d67d3cb54f1c123", + "hash": "23aab4b3c8077b55400c3e074dbe7a2982df988d3907648f0db2aeec5750ab8e" + } +] diff --git a/pkg/hash-poseidon/src/snapshots/hash_poseidon__tests__hash_merge_snapshot_test.snap b/pkg/hash-poseidon/src/snapshots/hash_poseidon__tests__hash_merge_snapshot_test.snap new file mode 100644 index 0000000..858c19c --- /dev/null +++ b/pkg/hash-poseidon/src/snapshots/hash_poseidon__tests__hash_merge_snapshot_test.snap @@ -0,0 +1,521 @@ +--- +source: pkg/hash-poseidon/src/lib.rs +expression: results +--- +[ + { + "left": "0000000000000000000000000000000000000000000000000000000000000000", + "right": "0000000000000000000000000000000000000000000000000000000000000000", + "merged": "2ba00861b8f1581f5e17d438e323fa2809f58f1a60009dcd05edb1c9c7c833da" + }, + { + "left": "0000000000000000000000000000000000000000000000000000000000000000", + "right": "0000000000000000000000000000000000000000000000000000000000000001", + "merged": "1f4c45f9764aa17b0b277e23e1da0cefd69affc8caa18bb01f65b5c9d9761d21" + }, + { + "left": "0000000000000000000000000000000000000000000000000000000000000001", + "right": "0000000000000000000000000000000000000000000000000000000000000000", + "merged": "034797ee520c67ec5ee6fd37f581ba7267449a21de06aa55a09821caeec2e89d" + }, + { + "left": "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7", + "right": "da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586", + "merged": "078b0224ddf76d7835b0f9dbe35fae592b0fb04466907f93292d674d7ed98885" + }, + { + "left": "9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed", + "right": "29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f", + "merged": "071c0cff0ea7e3b6ca18db738412063ffb0de2fcaa08214ecb5e39991886f177" + }, + { + "left": "2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d", + "right": "012737681f7b5d0f281e3afde458bc1e73d2d313c9cf94c05ff3716240a248f2", + "merged": "1058cf4ef4d1e981ee8d3606be0f0c776a75718d3daeb13dced03d7e370d7e51" + }, + { + "left": "1320a058d7b3566bd520daaa3ed2bf0ac5b8b120fb852773c3639734b45c91a4", + "right": "2dd4cb83f8840d2eedb158131062ac3f1f2cf8ff6dcd1856e86a1e6c3167167e", + "merged": "0714b25932c05c6c440f1e2c74b40b8ce47e474a3a239f098c58a6294937ffe9" + }, + { + "left": "e5a688742b47c5adfb59d4df76fd1db1e51ee03b1ca9f82aca173edb8b729347", + "right": "4ebe980f904d10c916442b4783a0e984860cb6c957b39c38ed8f51cffaa68a4d", + "merged": "227f47c3c41d1996279c53347fbdb1e5bc5df99c2b4f121abd88f4f3b2da0889" + }, + { + "left": "e01025a39c504546b9dc1406a7eb28151e5150d7b204baa719d4f091021217db", + "right": "5cf1b5c84c4fa71a879610a1a695ac527c5b56774a6b8a21aae88685868e094c", + "merged": "0a15b365e193411eb245e3656e8b1ebbb777cb0c7f965472c051fc5a85777385" + }, + { + "left": "f29ef4090af7a90cc07e8817aa528763797d3c332b67ca4bc110642c2151ec47", + "right": "ee84cb8c42d85f10e2a8cb18c3b7335f26e8c39a12b1bcc1707177b76138732e", + "merged": "228716aef258b89490985251fb926fa6122595159e8280e5e6ea7001c6a195e8" + }, + { + "left": "edaab74da1410fc055ea068c99e9260acbe337cf5d3e00e5b3230ffedb0b9907", + "right": "87d0c70e0bfe4198ea6758dd5a61fb5fec2df981f31befe153f81d17161784db", + "merged": "235e6d8260f7ac0ba967336e48e52e2cab6b88ad145703b0d0fd0f975ea74897" + }, + { + "left": "1c8822d53cd1ee7db532364828bdf404b040a8dcc522f3d3d99aec4b8057edb8", + "right": "500931a2c42d2f0c570847100b5754dafc5fbdb894bbef1a2de1a07f8ba0c4b9", + "merged": "1a2c633f901e69c21318235f07ced8aa71dab4f502aecfbaa5830535b641deae" + }, + { + "left": "19301066edbc056b7b481e7a0c46297bbb589d9da5b675a6723e152e5e63a4ce", + "right": "034e9e83e58a013af0e7352fb7908514e3b3d1040d0bb963b3954b636b5fd4bf", + "merged": "2d0ed1c3d40af878e03dbb85be014d545dcb1cccf7a2a3726d3e9acabdfeedfb" + }, + { + "left": "6d0aadbaf8157d062acb2418c176a475511b35c3f6218a5668ea5bc6f54b8782", + "right": "f8b340f00ac1beba5e62cd632a7ce7809c725608aca5efbf7c41f237643f06c0", + "merged": "09e728c48f34b7ab539be2fe1399e965ffe8249622090e864192da400311e1ec" + }, + { + "left": "997207171de867f9d697bf5ea6011abcce6c8cdb211394d2c02dd0fb60db5a2c", + "right": "17ac3dc85878a90bed3809dbb96eaa5426fc8eae0d2d65c42a479f088648be2d", + "merged": "29577377b3c596748898520819c565a4008d48e6fde89ad663a3ff7c23cdbb08" + }, + { + "left": "c801d82a366fddc0ef234263c0b6417d5f9da41817b88d68e5e67195c5c1ee30", + "right": "95e821f22524b20be41ceb590412e41dc648843fa9bfec7a3dcf61ab05415733", + "merged": "073afb112b6a4c71fae95aee99ad93cf4c8f53b1fa506f86e4fe37c15de3b3a2" + }, + { + "left": "16d3fa8151629303fe9741562ed065db4ebc0050ef558364ae81124a28f5c013", + "right": "13232fbc496dfd8a2568657b686d7214382a1a00903017dda969878442ba5aff", + "merged": "1a1f7a2baebe2da910e6176c1816d8af9922596f832cf5d548fdf6d1d6591b3b" + }, + { + "left": "f6613f553cbb233ce46d9aee93a7876cf5e9e82912b18cadf0b34327b2e0427e", + "right": "cf66b7ceb7c0918dc47bdff12a062adf07133009ce7a5e5c917e0168306109b7", + "merged": "1053fc28ba612b5d1a1aa63a9ac4971e8d98ead88b07806d90ffe20f1a33e014" + }, + { + "left": "cb49653a6d2caef005de783a9a9bfe05381ed1348d94ec65886f9c0b619c52c5", + "right": "533800b16c836172b95182dbc5eec042b89e22f11a085b739a3611cd8d836018", + "merged": "29341c47b7f498904bed79adee9c55c5c6cff00e80d4a6089a1dc459bc8ac795" + }, + { + "left": "c4fff0b86c02ed662d2d2522647a1f09a7b2f9eea56e7e20b1f06ccdd9cec37e", + "right": "3b2d20812df369978636c22646603675804104745d2997e28df5d8242aad19c8", + "merged": "221651190d97f531c0710d6cc90d6b3b29dbd6e280fac7df7b25f13d81a65ee4" + }, + { + "left": "120ca4142fb6019fccecf9fadb04ade03b341e3fc77201b3dc957a8097ab2f61", + "right": "5aff142ab753811d5f32e75bc8825b456555f3d179ffabcf35f6ae61365851f3", + "merged": "26548cd6be1bec68292f5e62b36905b425dd3e0dd6cb797ec238770b03db4a8e" + }, + { + "left": "f681a2e86e8078b064976646186394cb9064767750dad4e336b8f1d20fe2c13c", + "right": "6248d3d73d4d66d9c8587ac68a7976a3bbb8b5808320607400dbdb1918e3d3b9", + "merged": "01b5e0f93263dd2736da3f586ad2ba79cc65e0232c4da180b018ed3bb8636bd6" + }, + { + "left": "0cfc38c4ddfade990a213d208fbf7898334f4deed7e5830fd266751315435ae1", + "right": "9bb94f4d3dc92652f243dd1f96f3595ab473d2356d8fa8f6d64cc4f64b12ca99", + "merged": "05594e22a8fbaee97d9144318f4dc3e869ee80808efd6accc7e31f4a8580cf8a" + }, + { + "left": "ecdd1962572e6add609d9c619aab678b3fc298bc2f0f81feb4f0d3ebad7e850a", + "right": "8bcb52ca467e649de2db913bfda001294c49dc369f7d14cc25c5fa65d4d5af6a", + "merged": "0f93c8c512e791cd501f9e4645cf3b02f0c32d8366a2138e52520af43ca2a298" + }, + { + "left": "436d22bd2839be23dd3c57825033fecdce2ded6c511dbeaf4df2b4cbb7af8215", + "right": "bb48a550f57d02750e599298f512b1ec1829722fc10a5acf9537e392a7284559", + "merged": "302834d71cfa0e5b3aa11b68a5d6e27af09de3c70decd792e792e250e210c030" + }, + { + "left": "05d3ab4837dece4b63fdfd5dd07a2b76a8c82566df1a2167dae5e125b6aa0e76", + "right": "b9d99ca84664f50eeea54e449f0e587039137f57543d89205483141c933166b6", + "merged": "017affe33338c337653535b549c613aae4378dfe405abcf6fbe21e1877704d3e" + }, + { + "left": "1990a706aca07f467d22bc34c6552f5bba91cb1fc21db51d03dfff6523a5e1b4", + "right": "285d54c47660eda1b290e4087b30651b542305a714e98a8233577d2afb383e40", + "merged": "0005d8be24d82e487bbc695a8d738308276c3b15bd193fab56e9f7ea604cf75b" + }, + { + "left": "2f6b9fd214b194c738886bd2289cc5f997951910994b0a6104092fbc9b385639", + "right": "343cf26c9faf845e7a98cb1f2c9306e8200185d95de059f83ad17c4b97f8c62c", + "merged": "0de60374d00d16b6d767c77aa70f67150221c3869efca98f6909d333c89ea305" + }, + { + "left": "f6c347dc6eb5f2b1f4bf2dd328130d4500ca39beba2d4281a3d8ceb4cb1ecde3", + "right": "78b20029fb6a4c543312e41013915c57016e5da681944cc277f9c7e75f4a654a", + "merged": "24795686aead0ce813340074d8cf84821b25f8df820a0443e34e943db206be46" + }, + { + "left": "b2e5dc646ada242b6223aacc63674f9702146723360811adbdf2bb938b595bf4", + "right": "c688a8a844130d9da3f0efe3650c2283640b342f8922fb6dd10b8bbe35c7aebe", + "merged": "03fb6171231b2a819bf7af141cb20ad530698c7d16f018f28c1d72f84e7e6bdf" + }, + { + "left": "ba416cb0180fb7d2b171149018f8d880463ac26202c2b72f9a7cf83a917ad261", + "right": "83f8e74cd418e3b63459f7ad59849ee43cac6df3bb63fceec1abe8e9e0b64b23", + "merged": "1eb80ccacf8b13e653ca00a223660c4d83c1a9ce406e27987475e99003510941" + }, + { + "left": "3a43aac54f9ba0998d2219b3baca111940d524b7cf94677d6c557750fa4db9e1", + "right": "077eedb5ba6e33c104ae25443c86bf1583353addf6fddd19a4ff491188e3d487", + "merged": "1e0daf6efd0f0bc4f76c664625545f71e728a1a8419b342542a88e0a9eae39ca" + }, + { + "left": "8769611b36427c8f4c705cf42338475c3185c123919b79b3a4887243b924509c", + "right": "9a4e7a3fff0517021e51642d9b4526c28a0cf86fb254be7eab18701ca5919b75", + "merged": "2f2d75966873ae4bfd22b16c8762aaca2e15dfb9c0ebc1efffe9fe755948a367" + }, + { + "left": "4ec2506eccc087ac6141b4c3a661a3d1a89e0d4dd2df52caa5b3402d0026b3c6", + "right": "43fa7126e8ed101a94188a048b34ab61e1182d6be76e2e9e6acf401443ed0d99", + "merged": "0511e1ca4ad55c86b33dfc64e7706543c20223011decaaf2e427575b9198e783" + }, + { + "left": "7dd5ae67346cb1e189791102900225e6b955cd7c9e39fc7255021045fe7ecd40", + "right": "e2c68486a4c2fbcdbc53e847790dafe5b2cbdca09bf09de327076c79f2a339a9", + "merged": "0244bfb49c2556a30fd2d7e7510efe42889cc6eadd790f21ccdd049afcbed2ab" + }, + { + "left": "f942dfa372b41a390eabbbf296383d438466ae6105b5058117b8e406dcaa62a9", + "right": "8ac624d30bc8773de643cce7578e8d5c57c5718711421e6d04a182f8714e192e", + "merged": "1ea5d933934e6bd1c995bb30a1cd89ec275ee9a57c245893db0509fbef542f55" + }, + { + "left": "df3935cb2e0380e10c77aa6583832deb64cb41dc401541504e0420d06379e483", + "right": "0f06125018db3810a684c4e888b3b88829cf97ec67fc8549703f9ea5d6b8f67c", + "merged": "19bcfa6a430cb9e85efdadbd5549336df71f88c7316debcfa3797074522966f1" + }, + { + "left": "e9e060f765532c323db034ec700db819936fbe6f749fd37ce927663f439498c9", + "right": "8c5104d69ae9cd8b04444a471f95390873346858625420ed783203f8db371d76", + "merged": "0a43310f0c2d7dccf4fd4c077315022fec3bc201005986bdb243421bfe2286d4" + }, + { + "left": "6586137459505525cb3ee59a7fd8ac3c1db3f5f4e0dab62b43d1c4cd813d998e", + "right": "d83637f922f884a7584835bcdc03e9f1802b449dfa2d249d9ed7f2f9129815cd", + "merged": "03575e7e43d5040d9d3056e2d9a833278e660740e2a4b7b75da14a247fa9e4f7" + }, + { + "left": "8d4ec4169ec51eac449ddfa5bc0f232d47323d4c48ab558576160103820d4858", + "right": "77cc2bbab641d21d94e67b32cefb4e9ce5dac84d03ed3228ea3cdddd33f3915b", + "merged": "1e21f4a29d33b762f22dd98ee81ec9b471c2e7094a8378f6ae59084f93737008" + }, + { + "left": "9e21b435bbed927a539b556ffcdd4c9822fd1ce81acca79b6f7050b0c01a3a31", + "right": "7f066a1a89c81e4df8c7ee2e042203be8c290cf8605c193471953f8fe6055ac5", + "merged": "05f3f76df2a5f8c693d7cf20058777f9d7fd8cd69284d64ba9c2a0190f8bfcd3" + }, + { + "left": "46670a4a075f70909246c3e3b92b39cf2f35ab49fe6fda67072a6e1b82364820", + "right": "477fd522a746eac07e0398e873790486abebb50ec59a9e4129b7cea87c5182eb", + "merged": "15e85a4b8ed6c6e789993151d01e63b308c57b17f75fde2f453efadf72c0ba16" + }, + { + "left": "43bcdf096ef740ef67482e98165a4ec64ebe9d57c8d8c16ceaa81f3203dff26b", + "right": "3d5bf01edc0b0458b6b47846c326c75a822fc8b42774a3b201ef941484631406", + "merged": "1280a095070a7d2809657220cb3aad4a06b7176c7837d3c70c475f26c3105290" + }, + { + "left": "cbbeac961ccf42860ebac578703b485844bb9e01b2d6c2df72b62b43bade982b", + "right": "0bdd0501230fc76b820d2f5bd259ec791b33225e06afc2d996c90e756dbd4257", + "merged": "0570d161f5f33662d4276c7ef36d87e4b52f7f3fb615e5dd788aef3caeae7767" + }, + { + "left": "d53ea6d6ff2371330035b57bf54c9dc4fa95d61536aac11cdb08a664efb55bc9", + "right": "1a4c6f7fbe3efa8c621fd9f2cb343898979e7bcbd55b55217143493b6de415a8", + "merged": "265a75cf983b39a359e511dc7a0321f75f04a4a2ccb65055283d070c3c58f176" + }, + { + "left": "5d681a2405113f3ada3edaee6eb0e78572d2baf9c43e3fc39b93081cf2fb3f88", + "right": "79e810f417b733927525acb6d026f6ec46395620547d057a539a391de7c6f4b7", + "merged": "2a6993cff638b6eb98f772df3ecef5dc49959caed44bf9939fa0f41998c82d6e" + }, + { + "left": "095911c2d3ae075ad4f2c0c96d9f70e48a42cdcdae542bae833eb4a976d4f984", + "right": "10b4a3d77857762d1527ec6714a040baaec3bec41bf9cff00e1cf81ce61e95d9", + "merged": "09cf032073c17269d4a65caed188c5621d9a3ed7a008269e02b048358c09d4b9" + }, + { + "left": "7792d7c0db7a88545f10d9b0a5940457018817725da257766906ffbc6172b9c4", + "right": "d2d32a14d00c0d1d01e15280074a4a9fd2d21393f078ef55b16cfea532799326", + "merged": "2644e0c8c9b4d45b5750fea3dc33af7c784be44557f2c720efbd1e369a0e7904" + }, + { + "left": "3bffe8e99e56837b2763abd221ed85d83f9187af8b9e928f00deff423fffdadb", + "right": "786e6678a59af305cdc02546d0f8ab4681acc1f00069b0c47bbc9f13d12fd941", + "merged": "1fe0c9ec8a27259595719ec42a1bf16d65de12ec74cabfa5d48b3da4500a3058" + }, + { + "left": "1f8df532096d53e4b7861839e602fc5dfa0d0b72232dd81d2b0e4b660a7eba35", + "right": "3da27e66ceaf2d6c7734925247281866a12d67752a1edaadd1ea59e4e86e2e85", + "merged": "0f4e2ac239e6d737f767b9c1984391c963a6fc6910b4bda321ece57c8285085b" + }, + { + "left": "a81a573cd68f6dfb526558d81a8f488f261f355ddac23f6caf07d27fda71d8f3", + "right": "968d4ceeda89a09dcfdd00c17fa6db3658cc7ab02c0e5f44b1f526a7db9269e4", + "merged": "14b470d72de81203cc0539d701ae1196634c6a14dee708985162ccd4c21adb5a" + }, + { + "left": "dcd1d11b8421c204c07a5de46e48769579718c69532f1671e552b92ef1451ffb", + "right": "c7a2f412696c6d67ef071c988acf61f39319ca02dc853247be1f7f07b3bbd68c", + "merged": "26b1c5aac79efb9397225834ec6fc4b47c31c50b37f5c5039b75e0e0e54efdfb" + }, + { + "left": "901ef36d46868f65d0fa1d1755eff6c2802212908250207ab65fce827f0a82f3", + "right": "140ddc692cb5742b3133c541e0fe17718b546ad1fc8cb8a3a5af69a825a84343", + "merged": "223b2a81315d38ae4773137b12710c7b87612e0db300dc4f1415843f69398865" + }, + { + "left": "c378d7b54f917057a8d026d4a59931ff9e24ab95bce2bebdb3a4286e000a4c47", + "right": "e74cf82925dea07686dd20de228828705d90638661173e703e712d69b043dceb", + "merged": "01f3c379a1752f40db5c436c7f8dd334bca2c0c7431f48ef30fa89ff4e62c9ec" + }, + { + "left": "afdc53f132be3d04ce50d70b80dd118db00e45dfe953db87525880ba9f7abb0f", + "right": "c481a5f3acfa363aa2153391aef0dbf680512a0fa37a6c8293865ca95015dedb", + "merged": "1370d0863e4485762639c1a219b5016af471992501d92773e885a90ac9a23b6f" + }, + { + "left": "f6a21992ce1feb5f499359e288a3255ef3fbaea5b01440bd787251caf362326c", + "right": "7ffad20086aa7fcf35e95bbf398db75735e087e0863e016246703946c4e88bca", + "merged": "01da74cb07bac406eb52cbc08dca02d001f5d77ff2ec5752f76163454e63062f" + }, + { + "left": "6fc21446146bd342aae88ad4249f9a38ca3e4ed0a88aa6fd746f578e5b414ce0", + "right": "f2ce5ec76f87fa3b6321102ef7110b7e6d889b2b85bb11fcfd4ab2b3bd5f92b8", + "merged": "1d2ee97724b448a2bcecc9920b7e3c2787e3b965264293514ec4a9633afe0c8a" + }, + { + "left": "a2f66166f0695c0b13f32f97efaa0cde4f28e1674bf120e03fa15980873a1c6a", + "right": "b674c085303fdd74832cc1df5ef787ae11c6e6a9302c1488f36996c170367078", + "merged": "065eb333766134951788bbffde9f1d820bb8f9d575023f77b6fd30f178b0e8d9" + }, + { + "left": "6c05324f99d9d2cda1624db95b8eab6f7e10ac5bc985d6536cf667307a577a25", + "right": "55888bd9302cfe704cf72e59fd28b6daea343a83531a10a732d65ce93f523a03", + "merged": "27834c9bd7278d7a5aaf856db4c5555aeccb1807ec1906601ea977ae32e83afc" + }, + { + "left": "e5e791efd5ac502bb0a1f756e93208746240bc7bb1c085728ccc8150d8ea74b3", + "right": "3aebc59567e65b7e2bd83699f607412448d202d948bb111badd456d68086ff9a", + "merged": "1461e15fe5bee725012e5cc5c3b2f6acc3efa47b4f0173268c38c81add174b2f" + }, + { + "left": "5906ea3b2cda4111d3638391f7a7b153eea77ab47215d6fe13b350f59f884c6e", + "right": "31ac087239d9145b816424cba2c8bcb7b3ed7e19638089d91e5c9136d2aefc8d", + "merged": "11d61286be807e1c76f3f90a95024685789f6fab254e359000174f290ce09634" + }, + { + "left": "a165284b42229a70346296a7484648daafb9b88994d8823efbce9e029ace5170", + "right": "6fc1e6e194b7d8906bb83be681a96d50f4a66f5af24aff5007aa2052277d75e1", + "merged": "0edaba1524818c07c5fc2e90c79ceef740f630a585834adf5e0b94ce9b3c1f63" + }, + { + "left": "c6fcb719ae789587e73bfb11029b2ae9e380cd7b4fbd78f0c5318ef61802ecbf", + "right": "e5d91ba28184e96963366be3d5b063b5b664002ab0682e5820e3f9d30afd461b", + "merged": "0ce8e297bd7de20f8637673c2fe394b419a38dcacdc5bf2564d43d87e1a4ac86" + }, + { + "left": "3046cfc86f29605458ae94054cc2967ca77f102f97bae3454bc190726af88cff", + "right": "d5f0f05e18d31159ef2a9d9800f48d1b6719617474f1b3594315795822976613", + "merged": "01f2ed6241126c7044abf435af71d2dcd1dbad6940f4c3a5e35f86c9644b415e" + }, + { + "left": "cb63a4d6996505f4a4c57f3454ec101f5303f5b84aa8236843fc51d63d8445ad", + "right": "5c9b4f4e15aa0395695cde980a6d48936146c519fb84ab775647e2cf809135d1", + "merged": "2040580ddbae573540278e1c8e2c679367685847045cae6c246a3e4f002a4d0d" + }, + { + "left": "0b12f7e632654c679f92988b79021746c867a8e05102bb98f8fe7d3d7c005f69", + "right": "0d9ca7c6a175ff26ed82b873d63df4cbea0218bad0cb9a8c4404526f9806e2d4", + "merged": "179ced27c9e98548799e1156244dc84ef17fabb0d5f6032f83745cf483aafbe3" + }, + { + "left": "fbf37e84b756561c67c3a5732966dc4f0701063eaa7d3a52a2b5e4a8c9acdb30", + "right": "ee8b9f5125f76bcf7b22db897de9a8a9560c54118f31dccf49e87527d188fcb8", + "merged": "2f8c5341b2382a6a42e250716d9db747cacd206f95a1fdf35ea16d2e0415737f" + }, + { + "left": "1c6f5b28a37a1dad399f8c4f2d2cedd0f71a6937c10aa78e29f82b4f5d12e74e", + "right": "fa4fff5a8b700664959913542472af8df1acc815617dffd8e01873b1290e5b94", + "merged": "1052e92b6bf11327ffe5c989f8580bbfe2f2648518ea1139156e6d2716995733" + }, + { + "left": "fc2e9349517916ee0f7315369649f30a5a9feee736882f82b5e4d0ffca74cb98", + "right": "dab997217f7a461a34b4e7a87a933c6a2a21a63ba0437a12c1368cd74e621f47", + "merged": "03329aa00b58f58865695952706c5a7beb614375681b305eb1a2f30aa6e35bfe" + }, + { + "left": "4d1921742f5adbb26bb811fc0eb71fb828991bb21b8089897b83ae61d2c9d015", + "right": "dcabee391edaa47c8814d76ecee6b7af3979f04e1c52b4bc3d5f46cc79301fc7", + "merged": "1dae082a407f6a425a699e76ac6987d7e9af7a2911403f2531b678ab7f6d17a8" + }, + { + "left": "40693a47db68c22a39fb722e32605a150fd57c56ae63ca90e40059f26b6d5a73", + "right": "929f48ab33f1130143850fe2383e95d214cf585971d8d14b10175ef1e06b540d", + "merged": "0f0044b1a735fa636132d987877b618592786e80ad33ab5781b4e15d909a54fd" + }, + { + "left": "8f9e3e29f60ed31e7a8effe89a827cd82b647739105d305188d0f1d628187dca", + "right": "d530fef13ffb3959016d7271d2ae5ed6750591c774c0458468357676b6e16dfc", + "merged": "219a4127194ce8ff821264cf295f19e69933a83b647d74388fd3b3d546b0bffe" + }, + { + "left": "cfaa9aa876b986ab6334f1dd995c400ec2f54d837547a59632f8ba09f076be49", + "right": "be6ed506c3a8ae3482140720d9459ad6ceb67c5878a3d470e35d8cc999cf2309", + "merged": "11550a704d7ccfa831fb828188776ebdc295f539a9843a827967fe27071c1c06" + }, + { + "left": "305182e87f493edcefd416f8508d45ba6d63e06068a37292c4089a44a901ca1a", + "right": "216199258016bfefa8de980e3a584f80a91be8e7f24f58331bf5fa241834b613", + "merged": "281015b40085f1ad506c4b5fe0a33f3a7088322aa921dd8c99f5f7e6381a53ec" + }, + { + "left": "38c97b885891b18fa38998a1653518ae7d789d760f4ca8d468092e26bfae63fa", + "right": "73cdebcc3309068f4515b14fd2fb2362ee2ef7e29f479fd1beb55b485ffac908", + "merged": "2910afc6005d4db1469bf07f6ca980cdd696705f7eba0bbf9a73e71eef013815" + }, + { + "left": "42d56a92fddeb287c383761677bdb435cd93c38b37b9c09ed22c2249f991ccec", + "right": "eb89d151340af1a2f4bb084725358747dcc981de16d44d3c146065d591e91ff9", + "merged": "2260abfdaca802803825886a00a90ba557c5e7b3d77daa3fb5f4699382071fc9" + }, + { + "left": "856a6fd02f673aa0330e9bd7158d55e5adbb21c367dc2259e7015c567832d0e4", + "right": "56af9602c93ec4d1b131a3d06d42a2d9d5d4d0860ba9199ee2784f22cf98aff2", + "merged": "18ecb0fa22e8ff30eea193bc649c5ffe76af5b2fa313df31329f5e55f9aae346" + }, + { + "left": "7e6da102dd36362d7bf76a6c1ea387e0cb7102f8abd40ad2e9d8fafb79270cb7", + "right": "c81138cbe246c0d4e7c70501f2975c155b6713511e8c2cbb7db2a83e1a486496", + "merged": "0348030b501e2582ea2dc14301ebad3159aad614bf9467ce3da0bf7b273628f0" + }, + { + "left": "c2d922cc229cdb7d207f6bab3a15bc83fd3322d5af189d92b91e22d5b461c016", + "right": "4d55cddbb1c4b2f9ade5e5509c1dc0d4d2901ef7e844905e226e7de848baf023", + "merged": "2c27452e0818a43be23bd6d724d9cc7ad652da8b074c8a0d70d418a5f326d0bf" + }, + { + "left": "0f662fba30d7f6f6085a0d3190ffea1f3f58e3d41ba50b72d4a4a49fbaecf4dd", + "right": "2f2cfbbc2799d45da1f4e7072aaf99928b3ec2bb70f30ca0c61201b524d042fb", + "merged": "0d4ef8c0ef43f370033f57085b55a51f4189405631f012f2f6ee33a6060392b0" + }, + { + "left": "8c87e11160769b7b004c34dcd33194276815bdedb37644dc6b3d8197d891e4a6", + "right": "ef9fcac6cc7504dd7c7207ecff088c332f38490584b9c7edc494a504a67cc8da", + "merged": "0651102ca357fa2d2c0d2ee20b66fb03d2bd1ef5f6d628053959beb44a1fd43d" + }, + { + "left": "4cdb8b378d96420aeb69000a3bf5d56201412abb9d74fc58c48822b002a06e4a", + "right": "43f3bfdee8a97d7cbce9d30619bd2221ab592ac2fb2f4983a384ad500036efb4", + "merged": "0f90e3e8a2f3dfe9144eeb7a0ba12a5e7ae0d3bd4a0d854a95594b3b72ded8e5" + }, + { + "left": "f57060718c3e158acc124be4cdbac6769f4f2d31f94ef248336b6306fe8ff561", + "right": "083d381e53a4753e00c37215b3bda81c865a3b3d13696e0ba0d7e693acfc2604", + "merged": "05bfab6f92a0b4535a20b251d32e3ca072cd92a848144533098891b61ecd2fac" + }, + { + "left": "1dee4be85e40d0315f2e333b615d4ee2ba10fba1c2ad0cc752ae4858634eddf5", + "right": "ae30a213a2e49f4c754870f76a6ff7d99aed38765f629d3732a306a3437f9afe", + "merged": "126da50f0544a1a8fa13c95b71fc5935ff27d97e12885bd3f6b07d4d645742e8" + }, + { + "left": "de3bb535558d42c12dff44b828ad7be8cac11b42bbe6a93fe847c720f878cc95", + "right": "2d07a62966d9e71434b0e0a8a7954434d56846d3b4a3fadc49cd0a1c9ae41d9c", + "merged": "09935c705e2cb439ca0c55a65bc37a79be1ffc3144f3f201afd44601d015e215" + }, + { + "left": "d6621e6a2f941085674640294fffd3e2fa4f42156e5479f44f1a91da28475f8a", + "right": "c5b2be3f6f0f2eb67f08131a44f7f55f2632e809823f5a9277d5bd1de1469830", + "merged": "12f80a5c131fe1b36cb7a7f26e22dbad0039651754e74427a6dbe916320dc454" + }, + { + "left": "a9274e953f7df569235e674461bca46af7920a0b211d2ee8178f74fbf68c1724", + "right": "d1b3c5434167e5f0e2e921f3fb6f722c843d40f8f58b7c8018b01d102625e29b", + "merged": "1101d73f1a3e145ba45c27d2d455b5eb3a399b60bd6dbe04a773cae1620244d8" + }, + { + "left": "e2af5c555bd3f739a4f3edc6da860a5d75f6a91a5d184ffd860fb9a53564e73b", + "right": "5d240423a653f1e809e5db896de10fbe8040b8161280deef34840351fa84ffd0", + "merged": "148a7e2b5d0f9cb73efc85844bdf2c904331e3f284d565dd1ada88c0c44a207a" + }, + { + "left": "788437c9600828b8de20afb4688e27d3caf3760896c50ef81fa3cfd607443614", + "right": "9b85f754b4f314983667e2a37aa9328f71a63cf59b0b06065991ff6ecf22c90f", + "merged": "05e852fdf6683c77d7ac30debf804ab63559eae2a5d33c29eeac10fe363616cd" + }, + { + "left": "a09660d21ef0e3e991e245ed30b4b04f17472270f998ad080bce5255689d064b", + "right": "bca3052aab260b768fbec6a56a17ee54d4c12cd96558fa469c8fca1ad972a259", + "merged": "1912f15bfdb6bd1d09d518a67ef32cf03fd8acc6f44bb5d45675083f45db8d9f" + }, + { + "left": "f3b84a404106af36c494cb830d3e0cb01b6b44ad7826e478a34fdfa7015a91e3", + "right": "b3a4c08e9428a4cb102f251a7977b235ed425b7ef21f1e5595d92e5252d4436d", + "merged": "17a04d4e95ca7b221c64a97a36d6e1eb929000ccf196d5646024bb775c4df401" + }, + { + "left": "1b9df198f83db437ee90aeeacf94af024ffd87c3d2b3e6594a75753cd2967fb4", + "right": "de858623a29b06feb432a72a535bd981bc6ac99710f2308e8ab17654d1e2bb12", + "merged": "2570761709b4929f0cbd27560d27c74c6ce367ee3db4ff6daf43e2a5fad779bc" + }, + { + "left": "f0d01f6c9ff71befeb0b8a8176a3cb3989b76797134974d19af22d03f60bdb4e", + "right": "814de7109030e90ce8fb8d114522fe2b06792677ae3f7d235dae091ebce1e537", + "merged": "013124471df146d24a65c37017ae13f34c598387834e4b5d47c52f5a333432d0" + }, + { + "left": "0694c6a51db474c512fc285a1ef1fd474daabb93262d07490193d588f30860fb", + "right": "834100093fb78ffa85ed4d0aaad4194ebea9059da23885d4efa67bb268ecabda", + "merged": "0af9a00bbd309533715cbbc6b3021cc571691acb9e66add7fa6b1b93d8a9f352" + }, + { + "left": "23ea0f4618d0c4fd7b7739aa04212c276b4a9cc4c572863a2070a8e7f03b11a9", + "right": "4535b4faffdba896fa0dd006eb5507b171cc12b2cddd381fbac78da4bf99ec1e", + "merged": "27a4d6080b213ccee464eb9f825ae8fb9aefa9512bdc712cffabe2e9b8ce9552" + }, + { + "left": "9c19e5aa5adc6a4725272018970f1b64932e09d8a2f073ed8a69bf983884417c", + "right": "df62850ed3fefafa3287148fb864768fc61a3ef2bbba86d9b9fa3d116d00fa03", + "merged": "174df6ae03a2f67b10e661a2a28d3306d3e7a763a9f868ad52bee241bb4bc0fb" + }, + { + "left": "ccba91d7325350eefa4efb7741618ec791ff5be602dfacfc61bdc360a30d0ae1", + "right": "6ea28d7b8704070593cef54b05de23ab5b3fdce377a6922919909f5208434685", + "merged": "1ad91aaf7a92b43f5828214672264a292c35325d657e011b1fd35dd5d37728b4" + }, + { + "left": "df43a63c66f441729f04083af63ccf2ad09c6bd90e0340f7326cc07b715cfa20", + "right": "a02c6c653a939234ed302a4f7aafe658577fc1ef924e9b134aa59fa4b73eb0f4", + "merged": "279df3be91d366300dcad2c1aedcab9f400c62f169b98c81b766913ec711d276" + }, + { + "left": "ebe5842666a94d53ed8b1db65e07f0c224a749aa57f1f2960845705dfa1d552c", + "right": "514ede74700a3e7412852399c9fd28b5ca4d6b53128ee47385108572f7e2cfe4", + "merged": "259ebef34b674c08072e147f5ec9ed00d1914de39044e87807cec8e845ff961a" + }, + { + "left": "8f530d653193e12de05ec8ea31e9f040b0e7f9faeb4ae6928e630eec7bb33e21", + "right": "3c3b8d0f7b26050a7c1a3daf7c81957814165291d76ea64e9c1d2a61bf28081e", + "merged": "27fb112eedf4f978994299ce14b267191e5180b2c45c87f84d56396d5b1f60c2" + }, + { + "left": "af4c29ea559d2ef584f4dc5346c5468eaba16716c7040c9d39a46373ef4c6220", + "right": "27e67cc971be8ccb6f4729fcbd341023a76b81a396f3bec9783f0a2547e66dbc", + "merged": "148fb94561ad11a0db1849049e675d976e17c09dde6599ea6a785cfa40968f46" + }, + { + "left": "6d44bebd692e60522b515035f58d51696212f509323d8fdf4f81a3c0cec5d807", + "right": "b15ab900a61287064846d1b0b66af50f2a730391fe3f677e5e84d10908d83e18", + "merged": "259738acdf57d42a8fb561a99c1155134e5fa4a4cd33e51c4906da9a25e884b4" + }, + { + "left": "0b36b96a99cdbc6bd4421b11be569976680031f71af13af66ed3b5659764cfe2", + "right": "4f947ff376beb30ffd1e60ebb693703366d7cec799d26c207d67d3cb54f1c123", + "merged": "1d264bbe3c58b7a7291fab72298bfdabc6b55bef7453af18d36d2495ec7dae3e" + } +] diff --git a/pkg/hash/Cargo.toml b/pkg/hash/Cargo.toml new file mode 100644 index 0000000..f6c241e --- /dev/null +++ b/pkg/hash/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "hash" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } + +rand = { workspace = true, optional = true } +serde = { workspace = true } +hex = { workspace = true } +bn254_blackbox_solver = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +insta = { workspace = true } +rand_chacha = { workspace = true } +rand_xorshift = { workspace = true } +rand = { workspace = true } + +[features] +test-api = [] diff --git a/pkg/hash/README.md b/pkg/hash/README.md new file mode 100644 index 0000000..5ef3219 --- /dev/null +++ b/pkg/hash/README.md @@ -0,0 +1,29 @@ +# Hash + +Noir-compatible Poseidon hash implementation with optimized operations for zero-knowledge circuits. + +## Overview + +This package provides the primary hashing functionality using a Noir-compatible Poseidon hash implementation via `bn254_blackbox_solver`. This is the current hash implementation that replaces the deprecated `hash-poseidon` package. + +## Hash Algorithm + +- **Algorithm**: Poseidon hash function +- **Compatibility**: Noir-compatible via `bn254_blackbox_solver` +- **Curve**: BN254/BN256 +- **Operations**: Non-symmetric hash merging for Merkle tree operations + +## Features + +- **Noir-compatible Poseidon hashing** for zero-knowledge circuit integration +- **Element-based operations** with support for arbitrary-length arrays +- **Byte hashing** with automatic chunking and padding +- **Merkle tree operations** with `hash_merge` for parent node calculation +- **Path-based hashing** for tree traversal operations +- **Test utilities** with operation counting and snapshot testing +- **Non-symmetric hashing** ensuring `hash(a,b) ≠ hash(b,a)` + +## Migration Note + +This package replaces the deprecated `hash-poseidon` package. Use this implementation for all new development requiring Poseidon hashing functionality. + diff --git a/pkg/zk-primitives/examples/hash_merge.rs b/pkg/hash/examples/hash_merge.rs similarity index 89% rename from pkg/zk-primitives/examples/hash_merge.rs rename to pkg/hash/examples/hash_merge.rs index edd5b59..644e206 100644 --- a/pkg/zk-primitives/examples/hash_merge.rs +++ b/pkg/hash/examples/hash_merge.rs @@ -1,11 +1,10 @@ +use element::Element; +use hash::hash_merge; use std::{hint::black_box, time::Instant}; -use zk_primitives::{hash_merge, Element}; - const ITERS: usize = 1_000_000; fn main() { - let mut element = Element::new(5); let start = Instant::now(); diff --git a/pkg/hash/src/lib.rs b/pkg/hash/src/lib.rs new file mode 100644 index 0000000..a40e9e3 --- /dev/null +++ b/pkg/hash/src/lib.rs @@ -0,0 +1,213 @@ +// lint-long-file-override allow-max-lines=300 +use element::Element; + +mod path; + +pub use path::*; + +#[cfg(feature = "test-api")] +static HASH_COUNTER: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0); + +/// The number of times [`hash_merge`] has been called +#[cfg(feature = "test-api")] +pub fn hash_count() -> usize { + HASH_COUNTER.load(core::sync::atomic::Ordering::Relaxed) +} + +/// Reset the count returned by [`hash_count`] to 0 +#[cfg(feature = "test-api")] +pub fn reset_hash_count() { + HASH_COUNTER.store(0, core::sync::atomic::Ordering::Relaxed); +} + +#[cfg(feature = "test-api")] +static HASH_ELEMENT_COUNTER: core::sync::atomic::AtomicUsize = + core::sync::atomic::AtomicUsize::new(0); + +/// The number of elements that have been hashed together +#[cfg(feature = "test-api")] +pub fn hash_element_count() -> usize { + HASH_ELEMENT_COUNTER.load(core::sync::atomic::Ordering::Relaxed) +} + +/// Reset the count returned by [`hash_element_count`] to 0 +#[cfg(feature = "test-api")] +pub fn reset_hash_element_count() { + HASH_ELEMENT_COUNTER.store(0, core::sync::atomic::Ordering::Relaxed); +} + +/// Hash two elements together +/// +/// This function is used to calculate the hash of a parent node from the hash of its children, +/// i.e.: `parent_hash = hash_merge(left_hash, right_hash)` +/// +/// ```rust +/// # use element::Element; +/// # use hash::hash_merge; +/// let a = hash_merge([Element::new(1), Element::new(2)]); +/// let b = hash_merge([Element::new(1), Element::new(3)]); +/// let c = hash_merge([Element::new(2), Element::new(3)]); +/// +/// assert_ne!(a, b); +/// assert_ne!(a, c); +/// assert_ne!(b, c); +/// ``` +/// This operation is not symmetric: +/// ```rust +/// # use element::Element; +/// # use hash::hash_merge; +/// let a = Element::new(1); +/// let b = Element::new(2); +/// +/// let ab = hash_merge([a, b]); +/// let ba = hash_merge([b, a]); +/// +/// assert_ne!(ab, ba); +/// ``` +#[inline] +#[must_use] +pub fn hash_merge(elements: [Element; N]) -> Element { + #[cfg(feature = "test-api")] + { + HASH_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed); + HASH_ELEMENT_COUNTER.fetch_add(N, core::sync::atomic::Ordering::Relaxed); + } + + let inputs = elements.iter().map(|e| e.to_base()).collect::>(); + let hash = bn254_blackbox_solver::poseidon_hash(&inputs).unwrap(); + + Element::from_base(hash) +} + +/// Hash a slice of bytes +/// +/// ```rust +/// # use element::Element; +/// # use hash::hash_bytes; +/// let hash_1 = hash_bytes(&[1, 2, 3, 4]); +/// let hash_2 = hash_bytes(&[1, 2, 3, 5]); +/// +/// assert_ne!(hash_1, hash_2); +/// ``` +#[inline] +#[must_use] +pub fn hash_bytes(bytes: &[u8]) -> Element { + // an element is slightly smaller than a "u254". For convenience, we're just going to pretend + // it's a u128. If we need the extra perf, we can be a bit more compact here. + + let initial = Element::BYTE_HASH_IV; + + let elements_from_bytes = bytes + .chunks(core::mem::size_of::()) + .map(bytes_to_element); + + core::iter::once(initial) + .chain(elements_from_bytes) + .reduce(|left, right| hash_merge([left, right])) + .unwrap() // there's always at least 1 element +} + +/// Convert a slice of bytes with length in the range `1..=16` to an [`Element`] +/// +/// If there are fewer than 16 bytes, the lower bytes are padded with zeroes +fn bytes_to_element(bytes: &[u8]) -> Element { + let mut padded_bytes = [0; 16]; + padded_bytes[0..bytes.len()].copy_from_slice(bytes); + u128::from_be_bytes(padded_bytes).into() +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use rand::Rng; + use rand_chacha::{ChaChaRng, rand_core::SeedableRng}; + + use super::*; + + #[derive(serde::Serialize)] + struct MergeResult { + left: Element, + right: Element, + merged: Element, + } + + impl MergeResult { + pub fn new(left: Element, right: Element) -> Self { + let merged = hash_merge([left, right]); + + Self { + left, + right, + merged, + } + } + } + + #[test] + fn hash_merge_snapshot_test() { + let max = + Element::from_str("0x30644E72E131A029B85045B68181585D2833E84879B9709143E1F593F0000000") + .unwrap(); + let special_cases = [ + MergeResult::new(Element::NULL_HASH, Element::NULL_HASH), + MergeResult::new(Element::NULL_HASH, Element::ONE), + MergeResult::new(Element::ONE, Element::NULL_HASH), + MergeResult::new(Element::new(10), Element::new(20)), + MergeResult::new(max, max), + ]; + + let mut rng = ChaChaRng::from_seed([0; 32]); + let random_cases = core::iter::from_fn(|| { + let left = Element::secure_random(&mut rng); + let right = Element::secure_random(&mut rng); + Some(MergeResult::new(left, right)) + }); + + let results: Vec<_> = special_cases + .into_iter() + .chain(random_cases.take(100)) + .collect(); + + insta::assert_json_snapshot!(results); + } + + #[derive(serde::Serialize)] + struct ByteResult { + #[serde(with = "hex::serde")] + bytes: Vec, + hash: Element, + } + + impl ByteResult { + fn new(bytes: &[u8]) -> Self { + let hash = hash_bytes(bytes); + let bytes = bytes.to_vec(); + Self { bytes, hash } + } + } + + #[test] + fn hash_bytes_snapshot_test() { + let special_cases = [ + ByteResult::new(&[]), + ByteResult::new(&[0]), + ByteResult::new(&[0; 16]), + ]; + + let mut rng = ChaChaRng::from_seed([0; 32]); + + let random_cases = core::iter::from_fn(|| { + let mut bytes = [0; 64]; + rng.fill(&mut bytes); + Some(ByteResult::new(&bytes)) + }); + + let results: Vec<_> = special_cases + .into_iter() + .chain(random_cases.take(100)) + .collect(); + + insta::assert_json_snapshot!(results); + } +} diff --git a/pkg/hash/src/path.rs b/pkg/hash/src/path.rs new file mode 100644 index 0000000..c52f984 --- /dev/null +++ b/pkg/hash/src/path.rs @@ -0,0 +1,146 @@ +use crate::{Element, hash_merge}; +use core::iter::zip; + +/// Compute the root hash of a merkle tree +/// +/// `siblings` is an [`Iterator`] that yields tuples containing the sibling, and a boolean value +/// that indicates whether the sibling in question was on the left or right (`false` means that the +/// sibling is on the right, `true` means that the sibling is on the left). +/// +/// The elements of `siblings` are in "deepest-first" order. +/// Note that the root hash of the tree is not considered to be a sibling, so a tree of depth `N` +/// would have `N - 1` siblings +/// +/// For example, consider the following tree: +/// ```text +/// ┌─────┐ +/// │ C │ +/// └──┬──┘ +/// │ +/// ┌─────┴─────┐ +/// │ │ +/// ┌──▼──┐ ┌──▼──┐ +/// │ A │ │ B │ +/// └──┬──┘ └──┬──┘ +/// │ │ +/// ┌──┴──┐ ┌──┴──┐ +/// │ │ │ │ +/// ┌─▼─┐ ┌─▼─┐ ┌─▼─┐ ┌─▼─┐ +/// │ 0 │ │ 1 │ │ 2 │ │ 3 │ +/// └───┘ └───┘ └───┘ └───┘ +/// ``` +/// Here: +/// - `A` is [`hash_merge(0, 1)`][crate::hash_merge] +/// - `B` is [`hash_merge(2, 3)`][crate::hash_merge] +/// - `C` is [`hash_merge(hash_merge(0, 1), hash_merge(2, 3))`][crate::hash_merge] (i.e. the root hash of the tree) +/// +/// If you wanted to prove that `2` was in the tree with this function, you would do the +/// following: +/// ```rust +/// # use element::Element; +/// # use hash::*; +/// // create the iterator of tuples and left/right bools +/// let a = hash_merge([Element::new(0), Element::new(1)]); +/// let b = hash_merge([Element::new(2), Element::new(3)]); +/// let c = hash_merge([a, b]); +/// +/// let siblings = [ +/// Element::new(3), +/// a +/// ]; +/// +/// // we are trying to prove the existence of `2`, so we use this as the `leaf` parameter +/// let root_hash = compute_merkle_root(Element::new(2), Element::new(2), &siblings); +/// assert_eq!(root_hash, c); // the hashes match, proving that `2` is in the tree +/// +/// // It might be the case that the tree had `Element::NULL_HASH` at this location in the tree +/// let root_hash_if_null = compute_merkle_root(Element::NULL_HASH, Element::NULL_HASH, &siblings); +/// assert_ne!(root_hash_if_null, c); // these aren't equal +/// ``` +pub fn compute_merkle_root(leaf: Element, path_element: Element, siblings: &[Element]) -> Element { + let bits = least_significant_bits(path_element, siblings.len()); + compute_merkle_root_from_iter(leaf, zip(siblings, bits)) +} + +/// Compute the root hash of a merkle tree, assuming null leaf. +/// +/// This allows you to prove that an element is not in the tree +/// +pub fn compute_null_root(leaf: Element, siblings: &[Element]) -> Element { + let bits = least_significant_bits(leaf, siblings.len()); + compute_merkle_root_from_iter(Element::NULL_HASH, zip(siblings, bits)) +} + +fn compute_merkle_root_from_iter<'a, I: IntoIterator>( + mut leaf: Element, + siblings: I, +) -> Element { + for (sibling, bit) in siblings { + match bit { + // bit is 0, this element is on the left + false => leaf = hash_merge([leaf, *sibling]), + + // bit is 1, this element is on the right + true => leaf = hash_merge([*sibling, leaf]), + } + } + + leaf +} + +/// Computes a new merkle path for `leaf` (given existing siblings). +/// +/// This function is useful when you are inserting an element into a tree to calculate the new path +/// that proves the element is now in the tree. +/// +pub fn compute_merkle_path_for_leaf(leaf: Element, siblings: &[Element]) -> Vec { + let mut path = vec![leaf]; + let mut hash = leaf; + + let bits = least_significant_bits(leaf, siblings.len()); + + for (sibling, bit) in zip(siblings, bits) { + match bit { + // bit is 0, this element is on the left + false => hash = hash_merge([hash, *sibling]), + + // bit is 1, this element is on the right + true => hash = hash_merge([*sibling, hash]), + } + path.push(hash); + } + + path +} + +/// The hash of an empty tree with a given depth +/// +/// This function can be defined recursively: +/// - `empty_tree_hash(1) = Element::NULL_HASH` +/// - `empty_tree_hash(n) = hash_merge(empty_tree_hash(n - 1), empty_tree_hash(n - 1))` +/// +/// # Panics +/// +/// Panics if `depth` is 0, since there is no such thing as a tree with depth 0. +#[inline] +#[must_use] +pub fn empty_tree_root(depth: usize) -> Element { + assert_ne!(depth, 0, "the smallest possible tree has depth 1"); + + compute_merkle_root_from_iter( + Element::NULL_HASH, + (1..depth).map(|_| (&Element::NULL_HASH, false)), + ) +} + +/// Get the least significant bits of an element (upto depth) +/// +/// This function is useful for getting the bits of an element that are used to compute the merkle +/// path. +/// +#[inline] +pub fn least_significant_bits(element: Element, depth: usize) -> impl Iterator { + element.lsb(depth).into_iter().rev() +} + +// TODO: add tests for these! diff --git a/pkg/hash/src/snapshots/hash__tests__hash_bytes_snapshot_test.snap b/pkg/hash/src/snapshots/hash__tests__hash_bytes_snapshot_test.snap new file mode 100644 index 0000000..10d9dfd --- /dev/null +++ b/pkg/hash/src/snapshots/hash__tests__hash_bytes_snapshot_test.snap @@ -0,0 +1,418 @@ +--- +source: pkg/hash/src/lib.rs +expression: results +--- +[ + { + "bytes": "", + "hash": "0000000000000000000000000000000000000000000000000000000000000002" + }, + { + "bytes": "00", + "hash": "24f8c162c4a75a200f3d486f5910b1ab8fe297ce1cce94e55e2af0da0a421507" + }, + { + "bytes": "00000000000000000000000000000000", + "hash": "24f8c162c4a75a200f3d486f5910b1ab8fe297ce1cce94e55e2af0da0a421507" + }, + { + "bytes": "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586", + "hash": "0325940bd4ad5e8faa8b2e322d40e60e4cfeb7461097df6573a11a6bf2a9cf82" + }, + { + "bytes": "9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f", + "hash": "0952ac772a083254cf44b3455bd105de148137310efaefc6a2168b3c6fe29bce" + }, + { + "bytes": "2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d012737681f7b5d0f281e3afde458bc1e73d2d313c9cf94c05ff3716240a248f2", + "hash": "140ed65ac127d40c634b1fc5109d11c41fe1a4fa1d003b5c6291b8e64e00c6b7" + }, + { + "bytes": "1320a058d7b3566bd520daaa3ed2bf0ac5b8b120fb852773c3639734b45c91a42dd4cb83f8840d2eedb158131062ac3f1f2cf8ff6dcd1856e86a1e6c3167167e", + "hash": "30624ada7dbb390f7b69fa959f6f37f5bd587a75350a3b236deef9f2f8762191" + }, + { + "bytes": "e5a688742b47c5adfb59d4df76fd1db1e51ee03b1ca9f82aca173edb8b7293474ebe980f904d10c916442b4783a0e984860cb6c957b39c38ed8f51cffaa68a4d", + "hash": "0293dfc64198a3d5341b177dfc809afb7c4c172e7e654f4651166b3a3b887e68" + }, + { + "bytes": "e01025a39c504546b9dc1406a7eb28151e5150d7b204baa719d4f091021217db5cf1b5c84c4fa71a879610a1a695ac527c5b56774a6b8a21aae88685868e094c", + "hash": "0d1b59e135e83dc2de18cebc4d3620f4ab1b8fafa879ada067088d88e7a8d0e1" + }, + { + "bytes": "f29ef4090af7a90cc07e8817aa528763797d3c332b67ca4bc110642c2151ec47ee84cb8c42d85f10e2a8cb18c3b7335f26e8c39a12b1bcc1707177b76138732e", + "hash": "1b7c3ed4362d15796ed39b364423a99a19ab085f797e0403fb13ceb6998bfa8c" + }, + { + "bytes": "edaab74da1410fc055ea068c99e9260acbe337cf5d3e00e5b3230ffedb0b990787d0c70e0bfe4198ea6758dd5a61fb5fec2df981f31befe153f81d17161784db", + "hash": "0e7534766e74e68e93bfe07a480b22e8ebadacd54fc42b6b0310af0477372c00" + }, + { + "bytes": "1c8822d53cd1ee7db532364828bdf404b040a8dcc522f3d3d99aec4b8057edb8500931a2c42d2f0c570847100b5754dafc5fbdb894bbef1a2de1a07f8ba0c4b9", + "hash": "2e84e926c43ea9ba44f3e950bf9748b6a084468f7a52f6e4e67522c0885187ca" + }, + { + "bytes": "19301066edbc056b7b481e7a0c46297bbb589d9da5b675a6723e152e5e63a4ce034e9e83e58a013af0e7352fb7908514e3b3d1040d0bb963b3954b636b5fd4bf", + "hash": "1be291b293429fd40293d5c27ce3302987973c4786f0db64624d79c8076942c6" + }, + { + "bytes": "6d0aadbaf8157d062acb2418c176a475511b35c3f6218a5668ea5bc6f54b8782f8b340f00ac1beba5e62cd632a7ce7809c725608aca5efbf7c41f237643f06c0", + "hash": "12c8f2f6223807ea574d6ffbf6f90302f3d93b5ad601c264c68367729c587161" + }, + { + "bytes": "997207171de867f9d697bf5ea6011abcce6c8cdb211394d2c02dd0fb60db5a2c17ac3dc85878a90bed3809dbb96eaa5426fc8eae0d2d65c42a479f088648be2d", + "hash": "0bacfb8e9ba58e70999e46d6be1c16a4f806ce422ebb90aa6c64b1776da18243" + }, + { + "bytes": "c801d82a366fddc0ef234263c0b6417d5f9da41817b88d68e5e67195c5c1ee3095e821f22524b20be41ceb590412e41dc648843fa9bfec7a3dcf61ab05415733", + "hash": "048b66830949299d23122419a8d44f9c8786d5782883f76092e10745b83f4de8" + }, + { + "bytes": "16d3fa8151629303fe9741562ed065db4ebc0050ef558364ae81124a28f5c01313232fbc496dfd8a2568657b686d7214382a1a00903017dda969878442ba5aff", + "hash": "0e98f36e8d5df2022e7c0f388a6349eef85d415ae9c3c18cc75786ea2d1f7248" + }, + { + "bytes": "f6613f553cbb233ce46d9aee93a7876cf5e9e82912b18cadf0b34327b2e0427ecf66b7ceb7c0918dc47bdff12a062adf07133009ce7a5e5c917e0168306109b7", + "hash": "20587afd369f79d155affe9833d113b26b8ba4ce216f7c3af0e92c5fb52d7b8b" + }, + { + "bytes": "cb49653a6d2caef005de783a9a9bfe05381ed1348d94ec65886f9c0b619c52c5533800b16c836172b95182dbc5eec042b89e22f11a085b739a3611cd8d836018", + "hash": "2949c806c28c1906b8e107513692466afa47ff5b00fab95e326c2786f8fe3a62" + }, + { + "bytes": "c4fff0b86c02ed662d2d2522647a1f09a7b2f9eea56e7e20b1f06ccdd9cec37e3b2d20812df369978636c22646603675804104745d2997e28df5d8242aad19c8", + "hash": "00627c5b00f0c817b0df696a2355254804793946ce243d2484ec7f96fea3b318" + }, + { + "bytes": "120ca4142fb6019fccecf9fadb04ade03b341e3fc77201b3dc957a8097ab2f615aff142ab753811d5f32e75bc8825b456555f3d179ffabcf35f6ae61365851f3", + "hash": "1e2f8d5ac0d75f4a62df2605b404c61bd74d75ed97b5fa2e2e438221a6dc946c" + }, + { + "bytes": "f681a2e86e8078b064976646186394cb9064767750dad4e336b8f1d20fe2c13c6248d3d73d4d66d9c8587ac68a7976a3bbb8b5808320607400dbdb1918e3d3b9", + "hash": "301b42dc48be79e809fc27e2729793c94f4644cc0d424dde2e81c8e0624a8dcc" + }, + { + "bytes": "0cfc38c4ddfade990a213d208fbf7898334f4deed7e5830fd266751315435ae19bb94f4d3dc92652f243dd1f96f3595ab473d2356d8fa8f6d64cc4f64b12ca99", + "hash": "1d8c1e50d7a36c6c885c2050d3144c6093e47ce12cdcbb405ebd575c31526141" + }, + { + "bytes": "ecdd1962572e6add609d9c619aab678b3fc298bc2f0f81feb4f0d3ebad7e850a8bcb52ca467e649de2db913bfda001294c49dc369f7d14cc25c5fa65d4d5af6a", + "hash": "0053858d66e6de0195f93a4493fd188538f7bc285742e8dca4809f3b8f6c2aee" + }, + { + "bytes": "436d22bd2839be23dd3c57825033fecdce2ded6c511dbeaf4df2b4cbb7af8215bb48a550f57d02750e599298f512b1ec1829722fc10a5acf9537e392a7284559", + "hash": "26a189f3311bb97ca5dd270b6bc1aa77d8348b052ca811cdc4d6709334251d02" + }, + { + "bytes": "05d3ab4837dece4b63fdfd5dd07a2b76a8c82566df1a2167dae5e125b6aa0e76b9d99ca84664f50eeea54e449f0e587039137f57543d89205483141c933166b6", + "hash": "0655f17bba1490a078ec2e20c9d4599a02d3a11d3cb04b7f9b5c46b90e12ab4d" + }, + { + "bytes": "1990a706aca07f467d22bc34c6552f5bba91cb1fc21db51d03dfff6523a5e1b4285d54c47660eda1b290e4087b30651b542305a714e98a8233577d2afb383e40", + "hash": "1cecb8b30cc621eae80f586c541d3665679632eb851eb71cbbf82300eb80a1b9" + }, + { + "bytes": "2f6b9fd214b194c738886bd2289cc5f997951910994b0a6104092fbc9b385639343cf26c9faf845e7a98cb1f2c9306e8200185d95de059f83ad17c4b97f8c62c", + "hash": "1ad59ad57a6336b5a757d788fed324da480306503a7a8fe988612438678c3d0b" + }, + { + "bytes": "f6c347dc6eb5f2b1f4bf2dd328130d4500ca39beba2d4281a3d8ceb4cb1ecde378b20029fb6a4c543312e41013915c57016e5da681944cc277f9c7e75f4a654a", + "hash": "065760db51b58150a8a3527a3c07a28241b9e0ba19a12cd56c09d5cd8d8e0552" + }, + { + "bytes": "b2e5dc646ada242b6223aacc63674f9702146723360811adbdf2bb938b595bf4c688a8a844130d9da3f0efe3650c2283640b342f8922fb6dd10b8bbe35c7aebe", + "hash": "25f6a88061e9e70997e00bd0d60e3539e34845de764f6093da2f902c117e79df" + }, + { + "bytes": "ba416cb0180fb7d2b171149018f8d880463ac26202c2b72f9a7cf83a917ad26183f8e74cd418e3b63459f7ad59849ee43cac6df3bb63fceec1abe8e9e0b64b23", + "hash": "1f93694efb2b6d6e92941af60a00845a71df9eb11410126e6353014411e7648e" + }, + { + "bytes": "3a43aac54f9ba0998d2219b3baca111940d524b7cf94677d6c557750fa4db9e1077eedb5ba6e33c104ae25443c86bf1583353addf6fddd19a4ff491188e3d487", + "hash": "1f4e5d6c73b6f97aa772f929b3874ab96d13e3c4b9ed46f0e02e412bb404bdd6" + }, + { + "bytes": "8769611b36427c8f4c705cf42338475c3185c123919b79b3a4887243b924509c9a4e7a3fff0517021e51642d9b4526c28a0cf86fb254be7eab18701ca5919b75", + "hash": "0d38eb22ace443d740c22d7da84bf270f2f77b9614e9481c1e2872c5978198eb" + }, + { + "bytes": "4ec2506eccc087ac6141b4c3a661a3d1a89e0d4dd2df52caa5b3402d0026b3c643fa7126e8ed101a94188a048b34ab61e1182d6be76e2e9e6acf401443ed0d99", + "hash": "1c54b9b6dd43f73ca403b807cb97495c1a13605991db1199c63be09a1b86704a" + }, + { + "bytes": "7dd5ae67346cb1e189791102900225e6b955cd7c9e39fc7255021045fe7ecd40e2c68486a4c2fbcdbc53e847790dafe5b2cbdca09bf09de327076c79f2a339a9", + "hash": "16364105a77f70fc40131ffd82b27e3ddb812c5d234e710a41912b920dc744d3" + }, + { + "bytes": "f942dfa372b41a390eabbbf296383d438466ae6105b5058117b8e406dcaa62a98ac624d30bc8773de643cce7578e8d5c57c5718711421e6d04a182f8714e192e", + "hash": "0163670992b5d9ec54ddc5ed6eb452c1a16fe3ce0441687c0d40818378789355" + }, + { + "bytes": "df3935cb2e0380e10c77aa6583832deb64cb41dc401541504e0420d06379e4830f06125018db3810a684c4e888b3b88829cf97ec67fc8549703f9ea5d6b8f67c", + "hash": "0977ff81cac92d90c1bf3663e9866881ac87c244f9fbb5092ad4a4cef374d206" + }, + { + "bytes": "e9e060f765532c323db034ec700db819936fbe6f749fd37ce927663f439498c98c5104d69ae9cd8b04444a471f95390873346858625420ed783203f8db371d76", + "hash": "1e0674182b353c58543be0ae7726d6cbf75ff67983f5214abcb3ef2aeaeeab70" + }, + { + "bytes": "6586137459505525cb3ee59a7fd8ac3c1db3f5f4e0dab62b43d1c4cd813d998ed83637f922f884a7584835bcdc03e9f1802b449dfa2d249d9ed7f2f9129815cd", + "hash": "176ca194c690750a6d30312ab5bfbac753de430ce885c41b357570b672b89ed8" + }, + { + "bytes": "8d4ec4169ec51eac449ddfa5bc0f232d47323d4c48ab558576160103820d485877cc2bbab641d21d94e67b32cefb4e9ce5dac84d03ed3228ea3cdddd33f3915b", + "hash": "1866a78b4e2c133a45d0a7372f916a83451d98a5cab060b1699e77b2d8dc43f2" + }, + { + "bytes": "9e21b435bbed927a539b556ffcdd4c9822fd1ce81acca79b6f7050b0c01a3a317f066a1a89c81e4df8c7ee2e042203be8c290cf8605c193471953f8fe6055ac5", + "hash": "197f3e0502005733040b7536c3d7423b4e8c5ce3ee3de27a7b2fa8c4b01b0014" + }, + { + "bytes": "46670a4a075f70909246c3e3b92b39cf2f35ab49fe6fda67072a6e1b82364820477fd522a746eac07e0398e873790486abebb50ec59a9e4129b7cea87c5182eb", + "hash": "23ad84c10d0884f94f33f9cb8669bdc375ee6c1804ea2dcb4f7eb193d3ca43af" + }, + { + "bytes": "43bcdf096ef740ef67482e98165a4ec64ebe9d57c8d8c16ceaa81f3203dff26b3d5bf01edc0b0458b6b47846c326c75a822fc8b42774a3b201ef941484631406", + "hash": "3049c9dba3600d889f49a563cc5118ce2077cb33b6844b4fffabcdd46ac0aa84" + }, + { + "bytes": "cbbeac961ccf42860ebac578703b485844bb9e01b2d6c2df72b62b43bade982b0bdd0501230fc76b820d2f5bd259ec791b33225e06afc2d996c90e756dbd4257", + "hash": "0ebba037c0cb8d3263b438b529766bb736d405b502be1ea9a1d2fbdb6ddbd49a" + }, + { + "bytes": "d53ea6d6ff2371330035b57bf54c9dc4fa95d61536aac11cdb08a664efb55bc91a4c6f7fbe3efa8c621fd9f2cb343898979e7bcbd55b55217143493b6de415a8", + "hash": "0ab5831ea750d4547b69cabff61b5bb36210efb0cf8dcfd6348bc1fdb998c000" + }, + { + "bytes": "5d681a2405113f3ada3edaee6eb0e78572d2baf9c43e3fc39b93081cf2fb3f8879e810f417b733927525acb6d026f6ec46395620547d057a539a391de7c6f4b7", + "hash": "01eefc394d50cab9225057813cd2220c58ccdbd7b7b7ad260d1d394d6ba438d6" + }, + { + "bytes": "095911c2d3ae075ad4f2c0c96d9f70e48a42cdcdae542bae833eb4a976d4f98410b4a3d77857762d1527ec6714a040baaec3bec41bf9cff00e1cf81ce61e95d9", + "hash": "0f0677baf88d756e661d812283d2f627a364eed3538a17afd62a78b5f57053c0" + }, + { + "bytes": "7792d7c0db7a88545f10d9b0a5940457018817725da257766906ffbc6172b9c4d2d32a14d00c0d1d01e15280074a4a9fd2d21393f078ef55b16cfea532799326", + "hash": "089aba747759ad1f741f0cb6eb58c3b07c8b72907a5fdf2f29078456fedfbe15" + }, + { + "bytes": "3bffe8e99e56837b2763abd221ed85d83f9187af8b9e928f00deff423fffdadb786e6678a59af305cdc02546d0f8ab4681acc1f00069b0c47bbc9f13d12fd941", + "hash": "1568e535acea2d19fb48fcd8b7cc001f77ce0ed68770475f7d789de1494d1789" + }, + { + "bytes": "1f8df532096d53e4b7861839e602fc5dfa0d0b72232dd81d2b0e4b660a7eba353da27e66ceaf2d6c7734925247281866a12d67752a1edaadd1ea59e4e86e2e85", + "hash": "0327e02ed57b1e9c860894a0c26d92ec53fbc4b5fb67a99dcb7e6eda73e71b0c" + }, + { + "bytes": "a81a573cd68f6dfb526558d81a8f488f261f355ddac23f6caf07d27fda71d8f3968d4ceeda89a09dcfdd00c17fa6db3658cc7ab02c0e5f44b1f526a7db9269e4", + "hash": "154ddfba4ceb90becd0025a4cf8cf2739ed33a602ec5bdb09282580df5ba3367" + }, + { + "bytes": "dcd1d11b8421c204c07a5de46e48769579718c69532f1671e552b92ef1451ffbc7a2f412696c6d67ef071c988acf61f39319ca02dc853247be1f7f07b3bbd68c", + "hash": "0031293ed1c746204e78b747db584e12e2550e044e08d32f3057f22067ad1771" + }, + { + "bytes": "901ef36d46868f65d0fa1d1755eff6c2802212908250207ab65fce827f0a82f3140ddc692cb5742b3133c541e0fe17718b546ad1fc8cb8a3a5af69a825a84343", + "hash": "1ddac2644785b736323d6d1e42c78b805c637a7b2a3d31e4f2c1495fe7a020a7" + }, + { + "bytes": "c378d7b54f917057a8d026d4a59931ff9e24ab95bce2bebdb3a4286e000a4c47e74cf82925dea07686dd20de228828705d90638661173e703e712d69b043dceb", + "hash": "29c9b67a951b7652a2c915a2b7053438568dbd52268378a72a9e726f5bb35d4f" + }, + { + "bytes": "afdc53f132be3d04ce50d70b80dd118db00e45dfe953db87525880ba9f7abb0fc481a5f3acfa363aa2153391aef0dbf680512a0fa37a6c8293865ca95015dedb", + "hash": "19d51d6e9c0fdf702e37eceea33dd45aeecee4057b319a55230037d464fea90b" + }, + { + "bytes": "f6a21992ce1feb5f499359e288a3255ef3fbaea5b01440bd787251caf362326c7ffad20086aa7fcf35e95bbf398db75735e087e0863e016246703946c4e88bca", + "hash": "2172c074c8ad02cd6b213c79cc2b774293fe1f6b95d1c89a493da657c26abfd1" + }, + { + "bytes": "6fc21446146bd342aae88ad4249f9a38ca3e4ed0a88aa6fd746f578e5b414ce0f2ce5ec76f87fa3b6321102ef7110b7e6d889b2b85bb11fcfd4ab2b3bd5f92b8", + "hash": "178d34c4b8a60835e81a10f5f7034a7af78d886c7fd9d857aad7d349e5c095c3" + }, + { + "bytes": "a2f66166f0695c0b13f32f97efaa0cde4f28e1674bf120e03fa15980873a1c6ab674c085303fdd74832cc1df5ef787ae11c6e6a9302c1488f36996c170367078", + "hash": "041407acf802fb85345326bf552eb7561b9ac17e4b1856f6b9f91590a819347d" + }, + { + "bytes": "6c05324f99d9d2cda1624db95b8eab6f7e10ac5bc985d6536cf667307a577a2555888bd9302cfe704cf72e59fd28b6daea343a83531a10a732d65ce93f523a03", + "hash": "0ada31834e2418c0d30b9a2d6053e2f1d5917fb95bcecf18e2ed1fc8fa11f549" + }, + { + "bytes": "e5e791efd5ac502bb0a1f756e93208746240bc7bb1c085728ccc8150d8ea74b33aebc59567e65b7e2bd83699f607412448d202d948bb111badd456d68086ff9a", + "hash": "0de137643d3cff539dcd0ce9d1114e1ffdc9c19d207b2b58247159eded63fcae" + }, + { + "bytes": "5906ea3b2cda4111d3638391f7a7b153eea77ab47215d6fe13b350f59f884c6e31ac087239d9145b816424cba2c8bcb7b3ed7e19638089d91e5c9136d2aefc8d", + "hash": "0f629d99913be1c2478e8edae71d63d295e2bf8094ff8b26f584eea25659c073" + }, + { + "bytes": "a165284b42229a70346296a7484648daafb9b88994d8823efbce9e029ace51706fc1e6e194b7d8906bb83be681a96d50f4a66f5af24aff5007aa2052277d75e1", + "hash": "193adcb346f018aeb618bc2b054f8c8cfbcbe5fd00b336be6338be43620cbe47" + }, + { + "bytes": "c6fcb719ae789587e73bfb11029b2ae9e380cd7b4fbd78f0c5318ef61802ecbfe5d91ba28184e96963366be3d5b063b5b664002ab0682e5820e3f9d30afd461b", + "hash": "02638b8a83f6fad1c6bb9391075a7a0626d5736f1fc16531a145581461392b92" + }, + { + "bytes": "3046cfc86f29605458ae94054cc2967ca77f102f97bae3454bc190726af88cffd5f0f05e18d31159ef2a9d9800f48d1b6719617474f1b3594315795822976613", + "hash": "05eaa5c12fbbc731ac3b97b51d6792ae51342c2d6375eed411f61f9798e51da4" + }, + { + "bytes": "cb63a4d6996505f4a4c57f3454ec101f5303f5b84aa8236843fc51d63d8445ad5c9b4f4e15aa0395695cde980a6d48936146c519fb84ab775647e2cf809135d1", + "hash": "2d40d286e6bdc40b22ef4c2f2f039480cf9c9f548247d00049d5ac550a68aeb5" + }, + { + "bytes": "0b12f7e632654c679f92988b79021746c867a8e05102bb98f8fe7d3d7c005f690d9ca7c6a175ff26ed82b873d63df4cbea0218bad0cb9a8c4404526f9806e2d4", + "hash": "183a361d7eeeba42ba85fa0d937b07c47f71b2e5803be965bd519b3f71228826" + }, + { + "bytes": "fbf37e84b756561c67c3a5732966dc4f0701063eaa7d3a52a2b5e4a8c9acdb30ee8b9f5125f76bcf7b22db897de9a8a9560c54118f31dccf49e87527d188fcb8", + "hash": "065962cf8de4cdb4a39306fdac8207b61ba1453855e3b284b2880c444fd888b3" + }, + { + "bytes": "1c6f5b28a37a1dad399f8c4f2d2cedd0f71a6937c10aa78e29f82b4f5d12e74efa4fff5a8b700664959913542472af8df1acc815617dffd8e01873b1290e5b94", + "hash": "1062b8735d18f40fc2d68dd5aec3f158ab75b5857a6019c9c4a3d7509feb1768" + }, + { + "bytes": "fc2e9349517916ee0f7315369649f30a5a9feee736882f82b5e4d0ffca74cb98dab997217f7a461a34b4e7a87a933c6a2a21a63ba0437a12c1368cd74e621f47", + "hash": "16d4777c6616ad8adf93b5f331b879e9cd09166cae1bce61249f5392d397975c" + }, + { + "bytes": "4d1921742f5adbb26bb811fc0eb71fb828991bb21b8089897b83ae61d2c9d015dcabee391edaa47c8814d76ecee6b7af3979f04e1c52b4bc3d5f46cc79301fc7", + "hash": "1e0749c0f21292bcca1e5809696f5126375165eef01c39c39e1834e43c4819e4" + }, + { + "bytes": "40693a47db68c22a39fb722e32605a150fd57c56ae63ca90e40059f26b6d5a73929f48ab33f1130143850fe2383e95d214cf585971d8d14b10175ef1e06b540d", + "hash": "16e372aab30f0f88658c35c082aa9d28bb406206af3c9166d45d927dc140915a" + }, + { + "bytes": "8f9e3e29f60ed31e7a8effe89a827cd82b647739105d305188d0f1d628187dcad530fef13ffb3959016d7271d2ae5ed6750591c774c0458468357676b6e16dfc", + "hash": "245bf67fb2e9c9de0a29b42274cf553c69e0210e1606798335386e5d4c4d4e80" + }, + { + "bytes": "cfaa9aa876b986ab6334f1dd995c400ec2f54d837547a59632f8ba09f076be49be6ed506c3a8ae3482140720d9459ad6ceb67c5878a3d470e35d8cc999cf2309", + "hash": "01a31b82f16993b0764f4ac09e74e9f2285cab75543985e05c723210523dd61f" + }, + { + "bytes": "305182e87f493edcefd416f8508d45ba6d63e06068a37292c4089a44a901ca1a216199258016bfefa8de980e3a584f80a91be8e7f24f58331bf5fa241834b613", + "hash": "0dc36e8ce8617300e88db17d55160e39af144c62ef1db2d5c628f6443ca982b2" + }, + { + "bytes": "38c97b885891b18fa38998a1653518ae7d789d760f4ca8d468092e26bfae63fa73cdebcc3309068f4515b14fd2fb2362ee2ef7e29f479fd1beb55b485ffac908", + "hash": "21e6a059ffa062eacdaca2f80589ff60979cb3e12bebb9a70d93262d294a5add" + }, + { + "bytes": "42d56a92fddeb287c383761677bdb435cd93c38b37b9c09ed22c2249f991cceceb89d151340af1a2f4bb084725358747dcc981de16d44d3c146065d591e91ff9", + "hash": "1a252a029c596ed470d83752991196d4c9ae27536b06d0ea08529784a0a9d0a4" + }, + { + "bytes": "856a6fd02f673aa0330e9bd7158d55e5adbb21c367dc2259e7015c567832d0e456af9602c93ec4d1b131a3d06d42a2d9d5d4d0860ba9199ee2784f22cf98aff2", + "hash": "28eaa8c5c1c566ad40de103dfd03938deec1510e9ce73f78518a517a9e37a555" + }, + { + "bytes": "7e6da102dd36362d7bf76a6c1ea387e0cb7102f8abd40ad2e9d8fafb79270cb7c81138cbe246c0d4e7c70501f2975c155b6713511e8c2cbb7db2a83e1a486496", + "hash": "2bd7300726e0c1b4cb513dcb0143166affa4effea5b7f5aeb3b3403fdf58565c" + }, + { + "bytes": "c2d922cc229cdb7d207f6bab3a15bc83fd3322d5af189d92b91e22d5b461c0164d55cddbb1c4b2f9ade5e5509c1dc0d4d2901ef7e844905e226e7de848baf023", + "hash": "1b7a69bd4a365d1309203a0dc310bb7b24a1f01fc1d0f0e73d80d4dfde159087" + }, + { + "bytes": "0f662fba30d7f6f6085a0d3190ffea1f3f58e3d41ba50b72d4a4a49fbaecf4dd2f2cfbbc2799d45da1f4e7072aaf99928b3ec2bb70f30ca0c61201b524d042fb", + "hash": "1c25778d26bc50d2a97ef3bf04b987d17aae240eaac539d68fc2ca7236479fb8" + }, + { + "bytes": "8c87e11160769b7b004c34dcd33194276815bdedb37644dc6b3d8197d891e4a6ef9fcac6cc7504dd7c7207ecff088c332f38490584b9c7edc494a504a67cc8da", + "hash": "1c9fb3e6224fe0176d3d081c9944aeeffc9be54a5acffbeba91583e4a151195b" + }, + { + "bytes": "4cdb8b378d96420aeb69000a3bf5d56201412abb9d74fc58c48822b002a06e4a43f3bfdee8a97d7cbce9d30619bd2221ab592ac2fb2f4983a384ad500036efb4", + "hash": "1736e4180c60e363f607df7e51c0bd3f08c59dc6d909f5dbe262a58ff15d4581" + }, + { + "bytes": "f57060718c3e158acc124be4cdbac6769f4f2d31f94ef248336b6306fe8ff561083d381e53a4753e00c37215b3bda81c865a3b3d13696e0ba0d7e693acfc2604", + "hash": "29e5a895f9e63ff910abb3ee3579bfacb265d3577d3b8151807df05299d983ea" + }, + { + "bytes": "1dee4be85e40d0315f2e333b615d4ee2ba10fba1c2ad0cc752ae4858634eddf5ae30a213a2e49f4c754870f76a6ff7d99aed38765f629d3732a306a3437f9afe", + "hash": "12bf427d98c543a412597405f7001a8d72fcd0f909376197bf7e54c09759d642" + }, + { + "bytes": "de3bb535558d42c12dff44b828ad7be8cac11b42bbe6a93fe847c720f878cc952d07a62966d9e71434b0e0a8a7954434d56846d3b4a3fadc49cd0a1c9ae41d9c", + "hash": "0a8efb4bfdab43d87466ddce609095b342c7791757bff832874f6e60ebf29429" + }, + { + "bytes": "d6621e6a2f941085674640294fffd3e2fa4f42156e5479f44f1a91da28475f8ac5b2be3f6f0f2eb67f08131a44f7f55f2632e809823f5a9277d5bd1de1469830", + "hash": "10c6f49b8cb388290cf51a74c7d1ed3fae67689d4038102ba07f58b3931c9796" + }, + { + "bytes": "a9274e953f7df569235e674461bca46af7920a0b211d2ee8178f74fbf68c1724d1b3c5434167e5f0e2e921f3fb6f722c843d40f8f58b7c8018b01d102625e29b", + "hash": "15bc64b8f0d5eeee2366705821c6eae3553fb3f35b966c4270177e1667d393c2" + }, + { + "bytes": "e2af5c555bd3f739a4f3edc6da860a5d75f6a91a5d184ffd860fb9a53564e73b5d240423a653f1e809e5db896de10fbe8040b8161280deef34840351fa84ffd0", + "hash": "1a34f1bcc5dd458c0689bbf628f5e32c67ded32eade8e6cf6cab71b7f737992a" + }, + { + "bytes": "788437c9600828b8de20afb4688e27d3caf3760896c50ef81fa3cfd6074436149b85f754b4f314983667e2a37aa9328f71a63cf59b0b06065991ff6ecf22c90f", + "hash": "194b36bb91d6189687b8e9c00d07e176fbe5cb556048c6b2179386931a8618d5" + }, + { + "bytes": "a09660d21ef0e3e991e245ed30b4b04f17472270f998ad080bce5255689d064bbca3052aab260b768fbec6a56a17ee54d4c12cd96558fa469c8fca1ad972a259", + "hash": "25de9ab83f3c1f33bbdb5fc4a66971223cbfa6fb508ba05acd098ab0e816e795" + }, + { + "bytes": "f3b84a404106af36c494cb830d3e0cb01b6b44ad7826e478a34fdfa7015a91e3b3a4c08e9428a4cb102f251a7977b235ed425b7ef21f1e5595d92e5252d4436d", + "hash": "1302c38636570b7f0a200f427531e3df2968ca9424e420549b7426e5ed8fe3c0" + }, + { + "bytes": "1b9df198f83db437ee90aeeacf94af024ffd87c3d2b3e6594a75753cd2967fb4de858623a29b06feb432a72a535bd981bc6ac99710f2308e8ab17654d1e2bb12", + "hash": "2401fc64bc25eeceee9b8b5c876ae9240724af8fd7b7664e3fb536364dd34598" + }, + { + "bytes": "f0d01f6c9ff71befeb0b8a8176a3cb3989b76797134974d19af22d03f60bdb4e814de7109030e90ce8fb8d114522fe2b06792677ae3f7d235dae091ebce1e537", + "hash": "034a4ae8aebd9b176bf8c43c5625fee6d75ade1b88712d7178701aaf1e922970" + }, + { + "bytes": "0694c6a51db474c512fc285a1ef1fd474daabb93262d07490193d588f30860fb834100093fb78ffa85ed4d0aaad4194ebea9059da23885d4efa67bb268ecabda", + "hash": "035bc54685c3548bd2a1730e500d99a776018a3384aef690abc2656c50d90a48" + }, + { + "bytes": "23ea0f4618d0c4fd7b7739aa04212c276b4a9cc4c572863a2070a8e7f03b11a94535b4faffdba896fa0dd006eb5507b171cc12b2cddd381fbac78da4bf99ec1e", + "hash": "2ee536196619741e59c8fe2c5bcd8852d2cdad5dbfd3d41c641e696660717004" + }, + { + "bytes": "9c19e5aa5adc6a4725272018970f1b64932e09d8a2f073ed8a69bf983884417cdf62850ed3fefafa3287148fb864768fc61a3ef2bbba86d9b9fa3d116d00fa03", + "hash": "1693b0343712b6a8fff2f7a067d29021293753a81ef8dba6807980275da87acc" + }, + { + "bytes": "ccba91d7325350eefa4efb7741618ec791ff5be602dfacfc61bdc360a30d0ae16ea28d7b8704070593cef54b05de23ab5b3fdce377a6922919909f5208434685", + "hash": "2f4c63ebe737eefcee42a8624bf1b97c3c3b085a10c016c1defae2267a1485fd" + }, + { + "bytes": "df43a63c66f441729f04083af63ccf2ad09c6bd90e0340f7326cc07b715cfa20a02c6c653a939234ed302a4f7aafe658577fc1ef924e9b134aa59fa4b73eb0f4", + "hash": "0b2bbec84d51268b65d29314af8b6464aefbb5dbd7787cd438c15ceac6c46dcb" + }, + { + "bytes": "ebe5842666a94d53ed8b1db65e07f0c224a749aa57f1f2960845705dfa1d552c514ede74700a3e7412852399c9fd28b5ca4d6b53128ee47385108572f7e2cfe4", + "hash": "21033b23aba8cb0646c4699cbeb74545bc6aa3b063537e4e661dc5389bc244e1" + }, + { + "bytes": "8f530d653193e12de05ec8ea31e9f040b0e7f9faeb4ae6928e630eec7bb33e213c3b8d0f7b26050a7c1a3daf7c81957814165291d76ea64e9c1d2a61bf28081e", + "hash": "156e080a149c50c1de4b10a9a2ffd73738740b511b0e1664d7397cf04ce94253" + }, + { + "bytes": "af4c29ea559d2ef584f4dc5346c5468eaba16716c7040c9d39a46373ef4c622027e67cc971be8ccb6f4729fcbd341023a76b81a396f3bec9783f0a2547e66dbc", + "hash": "0e02b137be39e3ea520e96f7da3d385b51465feee80906bba3d03f89730f9fbf" + }, + { + "bytes": "6d44bebd692e60522b515035f58d51696212f509323d8fdf4f81a3c0cec5d807b15ab900a61287064846d1b0b66af50f2a730391fe3f677e5e84d10908d83e18", + "hash": "0e5232af837e527bf23a379247615d63729bccb422d332fae1186f351c9528f5" + }, + { + "bytes": "0b36b96a99cdbc6bd4421b11be569976680031f71af13af66ed3b5659764cfe24f947ff376beb30ffd1e60ebb693703366d7cec799d26c207d67d3cb54f1c123", + "hash": "099b92f642adb2c7460e74ce7f1855f05133957bc89a5a1db6362c405953fd49" + } +] diff --git a/pkg/hash/src/snapshots/hash__tests__hash_merge_snapshot_test.snap b/pkg/hash/src/snapshots/hash__tests__hash_merge_snapshot_test.snap new file mode 100644 index 0000000..1855de4 --- /dev/null +++ b/pkg/hash/src/snapshots/hash__tests__hash_merge_snapshot_test.snap @@ -0,0 +1,531 @@ +--- +source: pkg/hash/src/lib.rs +expression: results +--- +[ + { + "left": "0000000000000000000000000000000000000000000000000000000000000000", + "right": "0000000000000000000000000000000000000000000000000000000000000000", + "merged": "0b63a53787021a4a962a452c2921b3663aff1ffd8d5510540f8e659e782956f1" + }, + { + "left": "0000000000000000000000000000000000000000000000000000000000000000", + "right": "0000000000000000000000000000000000000000000000000000000000000001", + "merged": "0dd6d785caa3fe1ad139a40b6bd26fccbd6c8697573b0e34489c740533db5cc8" + }, + { + "left": "0000000000000000000000000000000000000000000000000000000000000001", + "right": "0000000000000000000000000000000000000000000000000000000000000000", + "merged": "1e05013a2f40c60dc58cfe36bfa4d7e94676c43436922368628342bc5144d103" + }, + { + "left": "000000000000000000000000000000000000000000000000000000000000000a", + "right": "0000000000000000000000000000000000000000000000000000000000000014", + "merged": "1dd8037c0559952dd9d36c95b8425887933e2a80481b93339bbca23af6a8e7b1" + }, + { + "left": "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "right": "30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "merged": "16ab2bdbff8e66f191cd6d39f6ad3af51d8a7e41f4c59942dd21713e4aebcc2d" + }, + { + "left": "76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7", + "right": "da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586", + "merged": "2a4da321d5086206824d1b7893029daefb6c468ae9f5bfb3e3aaa7827201f3e9" + }, + { + "left": "9f07e7be5551387a98ba977c732d080dcb0f29a048e3656912c6533e32ee7aed", + "right": "29b721769ce64e43d57133b074d839d531ed1f28510afb45ace10a1f4b794d6f", + "merged": "2fdf237f38fa35fef6269b67af852a022e62a5282c8f6199f206e3c89a5ecc57" + }, + { + "left": "2d09a0e663266ce1ae7ed1081968a0758e718e997bd362c6b0c34634a9a0b35d", + "right": "012737681f7b5d0f281e3afde458bc1e73d2d313c9cf94c05ff3716240a248f2", + "merged": "04d399897c516514f9f251290922111ae600174f5468a7def392f47e23727903" + }, + { + "left": "1320a058d7b3566bd520daaa3ed2bf0ac5b8b120fb852773c3639734b45c91a4", + "right": "2dd4cb83f8840d2eedb158131062ac3f1f2cf8ff6dcd1856e86a1e6c3167167e", + "merged": "2f96008a394449122f51129d1b886ecff34736ac7a396ab84528806ab75f5fe3" + }, + { + "left": "e5a688742b47c5adfb59d4df76fd1db1e51ee03b1ca9f82aca173edb8b729347", + "right": "4ebe980f904d10c916442b4783a0e984860cb6c957b39c38ed8f51cffaa68a4d", + "merged": "305a2829b623fe858dba0c0e02aa3c5a464714b7b519493a129d7ceaaf70da65" + }, + { + "left": "e01025a39c504546b9dc1406a7eb28151e5150d7b204baa719d4f091021217db", + "right": "5cf1b5c84c4fa71a879610a1a695ac527c5b56774a6b8a21aae88685868e094c", + "merged": "0773a8e6c17aeae2c77891097fbec6b0f63b5e2de331d05b399687b0d0422c4d" + }, + { + "left": "f29ef4090af7a90cc07e8817aa528763797d3c332b67ca4bc110642c2151ec47", + "right": "ee84cb8c42d85f10e2a8cb18c3b7335f26e8c39a12b1bcc1707177b76138732e", + "merged": "0cd25b85569a2d270c8bcee9bbdb05d7c632f19bbb4a66e7132678061e6cb3a2" + }, + { + "left": "edaab74da1410fc055ea068c99e9260acbe337cf5d3e00e5b3230ffedb0b9907", + "right": "87d0c70e0bfe4198ea6758dd5a61fb5fec2df981f31befe153f81d17161784db", + "merged": "0dabfaa1740905398e9f918b3a2f9743180fbe475290a68a4a1aa22e0e12071a" + }, + { + "left": "1c8822d53cd1ee7db532364828bdf404b040a8dcc522f3d3d99aec4b8057edb8", + "right": "500931a2c42d2f0c570847100b5754dafc5fbdb894bbef1a2de1a07f8ba0c4b9", + "merged": "1dd53b811d239bc4d06f18976456d5745797d19fff84b04bdf0a36dfc91781dc" + }, + { + "left": "19301066edbc056b7b481e7a0c46297bbb589d9da5b675a6723e152e5e63a4ce", + "right": "034e9e83e58a013af0e7352fb7908514e3b3d1040d0bb963b3954b636b5fd4bf", + "merged": "2221c5edbe83dcbfc08f22d8a95e22f19c6bddacc5096ee7210108bc8301a188" + }, + { + "left": "6d0aadbaf8157d062acb2418c176a475511b35c3f6218a5668ea5bc6f54b8782", + "right": "f8b340f00ac1beba5e62cd632a7ce7809c725608aca5efbf7c41f237643f06c0", + "merged": "06293ee22e22986f199cf5d235f79f28528e1442340d31443d820e1e4685068c" + }, + { + "left": "997207171de867f9d697bf5ea6011abcce6c8cdb211394d2c02dd0fb60db5a2c", + "right": "17ac3dc85878a90bed3809dbb96eaa5426fc8eae0d2d65c42a479f088648be2d", + "merged": "15c32716fc30bfb56fd7738677362860d529d57a355904cf2e1ce4217a67466c" + }, + { + "left": "c801d82a366fddc0ef234263c0b6417d5f9da41817b88d68e5e67195c5c1ee30", + "right": "95e821f22524b20be41ceb590412e41dc648843fa9bfec7a3dcf61ab05415733", + "merged": "29f544cda40fe59cd0634ebdfaab84714a3827de10ada5bae04a4360546c658a" + }, + { + "left": "16d3fa8151629303fe9741562ed065db4ebc0050ef558364ae81124a28f5c013", + "right": "13232fbc496dfd8a2568657b686d7214382a1a00903017dda969878442ba5aff", + "merged": "2cc1e96ff5b352159a028f5363971f392f1a6fad9110777d97295c79c8a7b2f6" + }, + { + "left": "f6613f553cbb233ce46d9aee93a7876cf5e9e82912b18cadf0b34327b2e0427e", + "right": "cf66b7ceb7c0918dc47bdff12a062adf07133009ce7a5e5c917e0168306109b7", + "merged": "120e1296792097aedd03d887895fdcad9a03f5f7a89066ebc5f681e325e2c249" + }, + { + "left": "cb49653a6d2caef005de783a9a9bfe05381ed1348d94ec65886f9c0b619c52c5", + "right": "533800b16c836172b95182dbc5eec042b89e22f11a085b739a3611cd8d836018", + "merged": "262c69d50552e334ba57a5554f38cceab75cbd07542d5a8d6cfc0ed9e799274e" + }, + { + "left": "c4fff0b86c02ed662d2d2522647a1f09a7b2f9eea56e7e20b1f06ccdd9cec37e", + "right": "3b2d20812df369978636c22646603675804104745d2997e28df5d8242aad19c8", + "merged": "21fac90e4f5b5dac466f1b13c3442979f1b5412f687882c561c2d516cd847ed3" + }, + { + "left": "120ca4142fb6019fccecf9fadb04ade03b341e3fc77201b3dc957a8097ab2f61", + "right": "5aff142ab753811d5f32e75bc8825b456555f3d179ffabcf35f6ae61365851f3", + "merged": "1f9aa3fbdf4548a58f62a4a6089bc5fc932bfa135ca3a99010c5576a8d5aeea3" + }, + { + "left": "f681a2e86e8078b064976646186394cb9064767750dad4e336b8f1d20fe2c13c", + "right": "6248d3d73d4d66d9c8587ac68a7976a3bbb8b5808320607400dbdb1918e3d3b9", + "merged": "1208cad946c8cd28da7a990242804d5e1b765d1bc5c918b15998acffdeb862c4" + }, + { + "left": "0cfc38c4ddfade990a213d208fbf7898334f4deed7e5830fd266751315435ae1", + "right": "9bb94f4d3dc92652f243dd1f96f3595ab473d2356d8fa8f6d64cc4f64b12ca99", + "merged": "09aa134863664a097b083ab1b86b48573a21b2277c59c7fc58f9539c9dd857f4" + }, + { + "left": "ecdd1962572e6add609d9c619aab678b3fc298bc2f0f81feb4f0d3ebad7e850a", + "right": "8bcb52ca467e649de2db913bfda001294c49dc369f7d14cc25c5fa65d4d5af6a", + "merged": "23b4fb0bb71fadad6d120363fbf114300d9c05643a08daf88584c51ae9c7979f" + }, + { + "left": "436d22bd2839be23dd3c57825033fecdce2ded6c511dbeaf4df2b4cbb7af8215", + "right": "bb48a550f57d02750e599298f512b1ec1829722fc10a5acf9537e392a7284559", + "merged": "1dc7c583a74af9633f4893a76697b3d59dd7ce78b0b45c6a6b84abc520ce166c" + }, + { + "left": "05d3ab4837dece4b63fdfd5dd07a2b76a8c82566df1a2167dae5e125b6aa0e76", + "right": "b9d99ca84664f50eeea54e449f0e587039137f57543d89205483141c933166b6", + "merged": "19ddceedb6512bc099d2ffb4eaa28bfea69e0d1890b7e09f97bec09054aec0a7" + }, + { + "left": "1990a706aca07f467d22bc34c6552f5bba91cb1fc21db51d03dfff6523a5e1b4", + "right": "285d54c47660eda1b290e4087b30651b542305a714e98a8233577d2afb383e40", + "merged": "09e25f4c0bab797e2de0a32e0b277c1985dfca410dc2e8e647d58db146040572" + }, + { + "left": "2f6b9fd214b194c738886bd2289cc5f997951910994b0a6104092fbc9b385639", + "right": "343cf26c9faf845e7a98cb1f2c9306e8200185d95de059f83ad17c4b97f8c62c", + "merged": "2885da6cde419761dc398715910d2cb180aa9fd28a62c4902b04ce92e0a98952" + }, + { + "left": "f6c347dc6eb5f2b1f4bf2dd328130d4500ca39beba2d4281a3d8ceb4cb1ecde3", + "right": "78b20029fb6a4c543312e41013915c57016e5da681944cc277f9c7e75f4a654a", + "merged": "03c1bf7240dc88602dc880523aac0f203eab173cc2c909f39f8fee32a9bed973" + }, + { + "left": "b2e5dc646ada242b6223aacc63674f9702146723360811adbdf2bb938b595bf4", + "right": "c688a8a844130d9da3f0efe3650c2283640b342f8922fb6dd10b8bbe35c7aebe", + "merged": "0ca4f0cb70cb183ae92bd4d70eb6ddcd10d8467a8d83bb6882255d1640132eea" + }, + { + "left": "ba416cb0180fb7d2b171149018f8d880463ac26202c2b72f9a7cf83a917ad261", + "right": "83f8e74cd418e3b63459f7ad59849ee43cac6df3bb63fceec1abe8e9e0b64b23", + "merged": "1d1bb7d067e9bf41ba126d97a2fc59ef9f85b38307f6742c33c08fea3fcd95ba" + }, + { + "left": "3a43aac54f9ba0998d2219b3baca111940d524b7cf94677d6c557750fa4db9e1", + "right": "077eedb5ba6e33c104ae25443c86bf1583353addf6fddd19a4ff491188e3d487", + "merged": "1a13caab44c04bfca2fcc4c5dd8bfe3a6c5526b1a078a4984ef9401fefb7e79b" + }, + { + "left": "8769611b36427c8f4c705cf42338475c3185c123919b79b3a4887243b924509c", + "right": "9a4e7a3fff0517021e51642d9b4526c28a0cf86fb254be7eab18701ca5919b75", + "merged": "176449d232b829658863adf7b09c3b32aca9bcfdb4452afdff7098e27095cf7d" + }, + { + "left": "4ec2506eccc087ac6141b4c3a661a3d1a89e0d4dd2df52caa5b3402d0026b3c6", + "right": "43fa7126e8ed101a94188a048b34ab61e1182d6be76e2e9e6acf401443ed0d99", + "merged": "09f962e879eda1be4c60165b661afd0c8e172d27d40e5000778610cfe48786b7" + }, + { + "left": "7dd5ae67346cb1e189791102900225e6b955cd7c9e39fc7255021045fe7ecd40", + "right": "e2c68486a4c2fbcdbc53e847790dafe5b2cbdca09bf09de327076c79f2a339a9", + "merged": "013daf614ae40551d9965f8e437891f4724f3b5f1bd7ae0a327b87f8500182e6" + }, + { + "left": "f942dfa372b41a390eabbbf296383d438466ae6105b5058117b8e406dcaa62a9", + "right": "8ac624d30bc8773de643cce7578e8d5c57c5718711421e6d04a182f8714e192e", + "merged": "0c852b188f098d16eed7b723d7793581bc2160e5f14395d1951b035fe7bd1dfd" + }, + { + "left": "df3935cb2e0380e10c77aa6583832deb64cb41dc401541504e0420d06379e483", + "right": "0f06125018db3810a684c4e888b3b88829cf97ec67fc8549703f9ea5d6b8f67c", + "merged": "088e6d3b3f1489b97cd763b35f6c9abf598ff71e6332e76ec42258b03f4d3980" + }, + { + "left": "e9e060f765532c323db034ec700db819936fbe6f749fd37ce927663f439498c9", + "right": "8c5104d69ae9cd8b04444a471f95390873346858625420ed783203f8db371d76", + "merged": "2945d3f232605ff8933a331e2f4f1eeea4622ab7b5a87264d5c8cbf08f011d1c" + }, + { + "left": "6586137459505525cb3ee59a7fd8ac3c1db3f5f4e0dab62b43d1c4cd813d998e", + "right": "d83637f922f884a7584835bcdc03e9f1802b449dfa2d249d9ed7f2f9129815cd", + "merged": "20c361b26bb8cf2dea12bbecb4572af890d2e5062e385d8155040d81375992f0" + }, + { + "left": "8d4ec4169ec51eac449ddfa5bc0f232d47323d4c48ab558576160103820d4858", + "right": "77cc2bbab641d21d94e67b32cefb4e9ce5dac84d03ed3228ea3cdddd33f3915b", + "merged": "0f32fe7fb10b6976c142090d67e4e63bf63003cbe7e4a795f5a89a839ae454a2" + }, + { + "left": "9e21b435bbed927a539b556ffcdd4c9822fd1ce81acca79b6f7050b0c01a3a31", + "right": "7f066a1a89c81e4df8c7ee2e042203be8c290cf8605c193471953f8fe6055ac5", + "merged": "16be55a1f0b19cddf7b922e537edac5ec1e0f00c8d59a7288a473681df1353d2" + }, + { + "left": "46670a4a075f70909246c3e3b92b39cf2f35ab49fe6fda67072a6e1b82364820", + "right": "477fd522a746eac07e0398e873790486abebb50ec59a9e4129b7cea87c5182eb", + "merged": "181c98dc776984cd65def84214356c69df9ee960c0f6887491000aab4b0116b6" + }, + { + "left": "43bcdf096ef740ef67482e98165a4ec64ebe9d57c8d8c16ceaa81f3203dff26b", + "right": "3d5bf01edc0b0458b6b47846c326c75a822fc8b42774a3b201ef941484631406", + "merged": "1fb8a01deb344d0908d34bd77f7dd805f67d852d9d67728b610fca849cecf45b" + }, + { + "left": "cbbeac961ccf42860ebac578703b485844bb9e01b2d6c2df72b62b43bade982b", + "right": "0bdd0501230fc76b820d2f5bd259ec791b33225e06afc2d996c90e756dbd4257", + "merged": "1de87e9e821f67db5adb95af69d8d883832c34f4c2b762878f252d3d7cd72301" + }, + { + "left": "d53ea6d6ff2371330035b57bf54c9dc4fa95d61536aac11cdb08a664efb55bc9", + "right": "1a4c6f7fbe3efa8c621fd9f2cb343898979e7bcbd55b55217143493b6de415a8", + "merged": "0c2a518fc45bd85881b5866e3c1ecef8c558807b5c238b074b8f2467887bf92b" + }, + { + "left": "5d681a2405113f3ada3edaee6eb0e78572d2baf9c43e3fc39b93081cf2fb3f88", + "right": "79e810f417b733927525acb6d026f6ec46395620547d057a539a391de7c6f4b7", + "merged": "0f2700cbf0c9da73bf3a45f5ea489ef2d29dc9ec2359fff4464403fa73faf241" + }, + { + "left": "095911c2d3ae075ad4f2c0c96d9f70e48a42cdcdae542bae833eb4a976d4f984", + "right": "10b4a3d77857762d1527ec6714a040baaec3bec41bf9cff00e1cf81ce61e95d9", + "merged": "2b729485c658313b926f6e051af56d5bddeed0720dc8f970de9828a72db20fcc" + }, + { + "left": "7792d7c0db7a88545f10d9b0a5940457018817725da257766906ffbc6172b9c4", + "right": "d2d32a14d00c0d1d01e15280074a4a9fd2d21393f078ef55b16cfea532799326", + "merged": "03000449b8170e6339cf7a9c482fb98417b59a79e061e1d88ba92be1b0e06230" + }, + { + "left": "3bffe8e99e56837b2763abd221ed85d83f9187af8b9e928f00deff423fffdadb", + "right": "786e6678a59af305cdc02546d0f8ab4681acc1f00069b0c47bbc9f13d12fd941", + "merged": "05f623398b844e9a95017ef7967644ac6a15d2bb81af5f5543ec8303024f6d0f" + }, + { + "left": "1f8df532096d53e4b7861839e602fc5dfa0d0b72232dd81d2b0e4b660a7eba35", + "right": "3da27e66ceaf2d6c7734925247281866a12d67752a1edaadd1ea59e4e86e2e85", + "merged": "07a240b1ba6f42b5a54373054359d97a6daa9582f3722bb9f43920b053797f03" + }, + { + "left": "a81a573cd68f6dfb526558d81a8f488f261f355ddac23f6caf07d27fda71d8f3", + "right": "968d4ceeda89a09dcfdd00c17fa6db3658cc7ab02c0e5f44b1f526a7db9269e4", + "merged": "1cc2aaa7c918f7f917a9b015fd6f625a7d373c73b8777c8f231401a5d9ab11ca" + }, + { + "left": "dcd1d11b8421c204c07a5de46e48769579718c69532f1671e552b92ef1451ffb", + "right": "c7a2f412696c6d67ef071c988acf61f39319ca02dc853247be1f7f07b3bbd68c", + "merged": "057f74710a59ac1e46aa6024784a543d3c480edaab8275b927cf357c83376e46" + }, + { + "left": "901ef36d46868f65d0fa1d1755eff6c2802212908250207ab65fce827f0a82f3", + "right": "140ddc692cb5742b3133c541e0fe17718b546ad1fc8cb8a3a5af69a825a84343", + "merged": "11a00f340c68aba7972b3a5a39e41146203c35ded0ba4ec26a701f845e47e276" + }, + { + "left": "c378d7b54f917057a8d026d4a59931ff9e24ab95bce2bebdb3a4286e000a4c47", + "right": "e74cf82925dea07686dd20de228828705d90638661173e703e712d69b043dceb", + "merged": "0494e9b610054fc05e711fbd76db8a0cb83d11e7aad64d847fb64e478d398ddd" + }, + { + "left": "afdc53f132be3d04ce50d70b80dd118db00e45dfe953db87525880ba9f7abb0f", + "right": "c481a5f3acfa363aa2153391aef0dbf680512a0fa37a6c8293865ca95015dedb", + "merged": "18aa240da9a9384709c6adc394fdecc606906a31243e4d2588766dd1719c0d37" + }, + { + "left": "f6a21992ce1feb5f499359e288a3255ef3fbaea5b01440bd787251caf362326c", + "right": "7ffad20086aa7fcf35e95bbf398db75735e087e0863e016246703946c4e88bca", + "merged": "13aee06f57b5b2ffaf188aadf1a1951d1f220f15c00fc81dcbcf069b1b27447a" + }, + { + "left": "6fc21446146bd342aae88ad4249f9a38ca3e4ed0a88aa6fd746f578e5b414ce0", + "right": "f2ce5ec76f87fa3b6321102ef7110b7e6d889b2b85bb11fcfd4ab2b3bd5f92b8", + "merged": "11c3c585bb312e327d47c7de85fe355c047349909749129a65df13d834e948b7" + }, + { + "left": "a2f66166f0695c0b13f32f97efaa0cde4f28e1674bf120e03fa15980873a1c6a", + "right": "b674c085303fdd74832cc1df5ef787ae11c6e6a9302c1488f36996c170367078", + "merged": "0b12c9ee82b22d8b60d72145422ce1ce7d1c75a5bb30f9ea1d5035fa13fbf092" + }, + { + "left": "6c05324f99d9d2cda1624db95b8eab6f7e10ac5bc985d6536cf667307a577a25", + "right": "55888bd9302cfe704cf72e59fd28b6daea343a83531a10a732d65ce93f523a03", + "merged": "1d4c9c94d9969c252a277c75efc727f348b0c60bc23e722be4026f699d6770f5" + }, + { + "left": "e5e791efd5ac502bb0a1f756e93208746240bc7bb1c085728ccc8150d8ea74b3", + "right": "3aebc59567e65b7e2bd83699f607412448d202d948bb111badd456d68086ff9a", + "merged": "29daf0e7ca9191c88a25ab81b60d67ea410eae11817fc074ede577b701b72fba" + }, + { + "left": "5906ea3b2cda4111d3638391f7a7b153eea77ab47215d6fe13b350f59f884c6e", + "right": "31ac087239d9145b816424cba2c8bcb7b3ed7e19638089d91e5c9136d2aefc8d", + "merged": "22601663e21ee7c24e17363d244cc61a91d6fc768ea9a9ae56fe9968c56a7f40" + }, + { + "left": "a165284b42229a70346296a7484648daafb9b88994d8823efbce9e029ace5170", + "right": "6fc1e6e194b7d8906bb83be681a96d50f4a66f5af24aff5007aa2052277d75e1", + "merged": "07f4f07a07b37a0787c707ed875dc892e4a57a3ca394fb69ecd6ce409830c6db" + }, + { + "left": "c6fcb719ae789587e73bfb11029b2ae9e380cd7b4fbd78f0c5318ef61802ecbf", + "right": "e5d91ba28184e96963366be3d5b063b5b664002ab0682e5820e3f9d30afd461b", + "merged": "09770a599973c9048dd4c49df90e3fa2755f25b4d6f3676db3ad7bf89888f96f" + }, + { + "left": "3046cfc86f29605458ae94054cc2967ca77f102f97bae3454bc190726af88cff", + "right": "d5f0f05e18d31159ef2a9d9800f48d1b6719617474f1b3594315795822976613", + "merged": "2d6e31b740eb4272a1d30533c82512445f35c6164298ea0644d5ca4736b0e0fc" + }, + { + "left": "cb63a4d6996505f4a4c57f3454ec101f5303f5b84aa8236843fc51d63d8445ad", + "right": "5c9b4f4e15aa0395695cde980a6d48936146c519fb84ab775647e2cf809135d1", + "merged": "0a529f50f331cc4e0a659558680cf07cf00e52625232ca8707dc135d4b82ecd0" + }, + { + "left": "0b12f7e632654c679f92988b79021746c867a8e05102bb98f8fe7d3d7c005f69", + "right": "0d9ca7c6a175ff26ed82b873d63df4cbea0218bad0cb9a8c4404526f9806e2d4", + "merged": "0ff8214b2437f7a63427732548cd0fa05acf8e490aad6291e7965c4f9b00f66a" + }, + { + "left": "fbf37e84b756561c67c3a5732966dc4f0701063eaa7d3a52a2b5e4a8c9acdb30", + "right": "ee8b9f5125f76bcf7b22db897de9a8a9560c54118f31dccf49e87527d188fcb8", + "merged": "00737793eef73c318b227f723954500d05e41000dd0d0f8ce2afe2e3902f4f6c" + }, + { + "left": "1c6f5b28a37a1dad399f8c4f2d2cedd0f71a6937c10aa78e29f82b4f5d12e74e", + "right": "fa4fff5a8b700664959913542472af8df1acc815617dffd8e01873b1290e5b94", + "merged": "25433450faee07b3a92472fc968b49ecfa32cd1f78dbb3bf32b517d0430c7ba1" + }, + { + "left": "fc2e9349517916ee0f7315369649f30a5a9feee736882f82b5e4d0ffca74cb98", + "right": "dab997217f7a461a34b4e7a87a933c6a2a21a63ba0437a12c1368cd74e621f47", + "merged": "1142a12203a590de1f0bc10d85aa2606492f69256079532a3f0e8dfec49b7893" + }, + { + "left": "4d1921742f5adbb26bb811fc0eb71fb828991bb21b8089897b83ae61d2c9d015", + "right": "dcabee391edaa47c8814d76ecee6b7af3979f04e1c52b4bc3d5f46cc79301fc7", + "merged": "0b200b318faff7e45837a2a567a2c8edde3a3bf34b5882d5740703dff587e7ec" + }, + { + "left": "40693a47db68c22a39fb722e32605a150fd57c56ae63ca90e40059f26b6d5a73", + "right": "929f48ab33f1130143850fe2383e95d214cf585971d8d14b10175ef1e06b540d", + "merged": "2dc32e48a7b6354244577d7066936a6c442be0ce5be35fcd5c8226d7168ba37c" + }, + { + "left": "8f9e3e29f60ed31e7a8effe89a827cd82b647739105d305188d0f1d628187dca", + "right": "d530fef13ffb3959016d7271d2ae5ed6750591c774c0458468357676b6e16dfc", + "merged": "00b049f5973820b011cc7aa031888c29e4061334e1dca23e3425e24c9342a1f4" + }, + { + "left": "cfaa9aa876b986ab6334f1dd995c400ec2f54d837547a59632f8ba09f076be49", + "right": "be6ed506c3a8ae3482140720d9459ad6ceb67c5878a3d470e35d8cc999cf2309", + "merged": "1e94153af5e0ead86d569d0e932368e57ed5b87b59ffb96653f533cf72b0c421" + }, + { + "left": "305182e87f493edcefd416f8508d45ba6d63e06068a37292c4089a44a901ca1a", + "right": "216199258016bfefa8de980e3a584f80a91be8e7f24f58331bf5fa241834b613", + "merged": "0577e2a91a88190b2f9117553b6c7de6972deb95760c14f3335dbc8cdcf0d13f" + }, + { + "left": "38c97b885891b18fa38998a1653518ae7d789d760f4ca8d468092e26bfae63fa", + "right": "73cdebcc3309068f4515b14fd2fb2362ee2ef7e29f479fd1beb55b485ffac908", + "merged": "0fbbc877204419e245308845bf793cd30fefde7b82c801d603fab3b0dd826e63" + }, + { + "left": "42d56a92fddeb287c383761677bdb435cd93c38b37b9c09ed22c2249f991ccec", + "right": "eb89d151340af1a2f4bb084725358747dcc981de16d44d3c146065d591e91ff9", + "merged": "12691664d7a58079ea11eb0d9c0e6b1c7fb40e74f5e177df7118ac4b9df2012a" + }, + { + "left": "856a6fd02f673aa0330e9bd7158d55e5adbb21c367dc2259e7015c567832d0e4", + "right": "56af9602c93ec4d1b131a3d06d42a2d9d5d4d0860ba9199ee2784f22cf98aff2", + "merged": "249e23ec0b6d37b756592c2a8bb4da6b994486fdad37336a35d6903d104b34f0" + }, + { + "left": "7e6da102dd36362d7bf76a6c1ea387e0cb7102f8abd40ad2e9d8fafb79270cb7", + "right": "c81138cbe246c0d4e7c70501f2975c155b6713511e8c2cbb7db2a83e1a486496", + "merged": "260b4adc9541c5913795286a7bf32a3eb69de72fe1ab241c12e76c14d720ad52" + }, + { + "left": "c2d922cc229cdb7d207f6bab3a15bc83fd3322d5af189d92b91e22d5b461c016", + "right": "4d55cddbb1c4b2f9ade5e5509c1dc0d4d2901ef7e844905e226e7de848baf023", + "merged": "236aa318b12ef0d27c8472d46d8d7b9eb70ef8a4cfa12b94ec52e3d3097d41cb" + }, + { + "left": "0f662fba30d7f6f6085a0d3190ffea1f3f58e3d41ba50b72d4a4a49fbaecf4dd", + "right": "2f2cfbbc2799d45da1f4e7072aaf99928b3ec2bb70f30ca0c61201b524d042fb", + "merged": "1f8238fb74ea7beef4583e41d5baa5bbf862cdcdbed09cc46a3d28f4fe734057" + }, + { + "left": "8c87e11160769b7b004c34dcd33194276815bdedb37644dc6b3d8197d891e4a6", + "right": "ef9fcac6cc7504dd7c7207ecff088c332f38490584b9c7edc494a504a67cc8da", + "merged": "022147d351d5ee7e51293116e608c786d4470fc0c9cf6f0cf64d0d439b62f49d" + }, + { + "left": "4cdb8b378d96420aeb69000a3bf5d56201412abb9d74fc58c48822b002a06e4a", + "right": "43f3bfdee8a97d7cbce9d30619bd2221ab592ac2fb2f4983a384ad500036efb4", + "merged": "1011c9bbcd979156f352a66761762b8ad6e7aa55dc7a9a72a639e2176b3066bc" + }, + { + "left": "f57060718c3e158acc124be4cdbac6769f4f2d31f94ef248336b6306fe8ff561", + "right": "083d381e53a4753e00c37215b3bda81c865a3b3d13696e0ba0d7e693acfc2604", + "merged": "0db2eba4c5050c4e2b64f1b810cb74c3fe36e5abc46a44fa3a68f4e914ddb2d8" + }, + { + "left": "1dee4be85e40d0315f2e333b615d4ee2ba10fba1c2ad0cc752ae4858634eddf5", + "right": "ae30a213a2e49f4c754870f76a6ff7d99aed38765f629d3732a306a3437f9afe", + "merged": "28fbdef8a20bd416d8d6f1bc1f362d07137f69b354826474612201d8522ce826" + }, + { + "left": "de3bb535558d42c12dff44b828ad7be8cac11b42bbe6a93fe847c720f878cc95", + "right": "2d07a62966d9e71434b0e0a8a7954434d56846d3b4a3fadc49cd0a1c9ae41d9c", + "merged": "21fb6ad79ba891798401e2bfaeccc54ffa60b4f1df88fff6c50396c1747eabbd" + }, + { + "left": "d6621e6a2f941085674640294fffd3e2fa4f42156e5479f44f1a91da28475f8a", + "right": "c5b2be3f6f0f2eb67f08131a44f7f55f2632e809823f5a9277d5bd1de1469830", + "merged": "12814b22c5440908351def83383baf272a88b60d946f351d62bce2b06c877fcc" + }, + { + "left": "a9274e953f7df569235e674461bca46af7920a0b211d2ee8178f74fbf68c1724", + "right": "d1b3c5434167e5f0e2e921f3fb6f722c843d40f8f58b7c8018b01d102625e29b", + "merged": "2c4349fcff76956aef6a7086805aa70b555707537b7f41db2a606a0d89a3e3a7" + }, + { + "left": "e2af5c555bd3f739a4f3edc6da860a5d75f6a91a5d184ffd860fb9a53564e73b", + "right": "5d240423a653f1e809e5db896de10fbe8040b8161280deef34840351fa84ffd0", + "merged": "0f264ec991c7411ae1bfa1bc5cd5bea3152c25921bcb8c85c270b124c75103f3" + }, + { + "left": "788437c9600828b8de20afb4688e27d3caf3760896c50ef81fa3cfd607443614", + "right": "9b85f754b4f314983667e2a37aa9328f71a63cf59b0b06065991ff6ecf22c90f", + "merged": "23b25bc7ab68d341aeda3492c683daa7af1e4d00721237edb23745e36d26765b" + }, + { + "left": "a09660d21ef0e3e991e245ed30b4b04f17472270f998ad080bce5255689d064b", + "right": "bca3052aab260b768fbec6a56a17ee54d4c12cd96558fa469c8fca1ad972a259", + "merged": "2227b859b9c46929fade804977f1a04bacd6d58032345c3f6d3c1cf95228b5e8" + }, + { + "left": "f3b84a404106af36c494cb830d3e0cb01b6b44ad7826e478a34fdfa7015a91e3", + "right": "b3a4c08e9428a4cb102f251a7977b235ed425b7ef21f1e5595d92e5252d4436d", + "merged": "25738835b4346286a6923a36c2bec67f31c94b5b736ea9e0c3975a20ae477909" + }, + { + "left": "1b9df198f83db437ee90aeeacf94af024ffd87c3d2b3e6594a75753cd2967fb4", + "right": "de858623a29b06feb432a72a535bd981bc6ac99710f2308e8ab17654d1e2bb12", + "merged": "1e1d919901149f1d3c8e960178d07e24459ed74a2a91a920e143e8174e97fe9e" + }, + { + "left": "f0d01f6c9ff71befeb0b8a8176a3cb3989b76797134974d19af22d03f60bdb4e", + "right": "814de7109030e90ce8fb8d114522fe2b06792677ae3f7d235dae091ebce1e537", + "merged": "26f764e0ba080e47dabaca7c487ed9d01ee1ff243b2bd1e662072c3b6fc3ebff" + }, + { + "left": "0694c6a51db474c512fc285a1ef1fd474daabb93262d07490193d588f30860fb", + "right": "834100093fb78ffa85ed4d0aaad4194ebea9059da23885d4efa67bb268ecabda", + "merged": "181085e822722ef5699b3abeaa628f17b10fdfe903d182d1dc806b29f02a67e8" + }, + { + "left": "23ea0f4618d0c4fd7b7739aa04212c276b4a9cc4c572863a2070a8e7f03b11a9", + "right": "4535b4faffdba896fa0dd006eb5507b171cc12b2cddd381fbac78da4bf99ec1e", + "merged": "0ac11dcb88f72daf84bd73b45542859c492c7cf44bfdbe273f3e04a7bfcdebbd" + }, + { + "left": "9c19e5aa5adc6a4725272018970f1b64932e09d8a2f073ed8a69bf983884417c", + "right": "df62850ed3fefafa3287148fb864768fc61a3ef2bbba86d9b9fa3d116d00fa03", + "merged": "2249d3966dd64a70d9492d2340aff7e0e8f439391f57b40149214edf8d49ea5f" + }, + { + "left": "ccba91d7325350eefa4efb7741618ec791ff5be602dfacfc61bdc360a30d0ae1", + "right": "6ea28d7b8704070593cef54b05de23ab5b3fdce377a6922919909f5208434685", + "merged": "0a71e6a926918b854be5bbc9bb7961fcf0f5291e7b631ee500dbe1f488f5714b" + }, + { + "left": "df43a63c66f441729f04083af63ccf2ad09c6bd90e0340f7326cc07b715cfa20", + "right": "a02c6c653a939234ed302a4f7aafe658577fc1ef924e9b134aa59fa4b73eb0f4", + "merged": "091ad4742d710cb9ae0e52be87f929e827b76d2ebec969d90586348ee7a39f15" + }, + { + "left": "ebe5842666a94d53ed8b1db65e07f0c224a749aa57f1f2960845705dfa1d552c", + "right": "514ede74700a3e7412852399c9fd28b5ca4d6b53128ee47385108572f7e2cfe4", + "merged": "1a2feffa69b0d6dff49f9cd3febfce619cc3ebc6b63cfc9ef52fd72ef43860b4" + }, + { + "left": "8f530d653193e12de05ec8ea31e9f040b0e7f9faeb4ae6928e630eec7bb33e21", + "right": "3c3b8d0f7b26050a7c1a3daf7c81957814165291d76ea64e9c1d2a61bf28081e", + "merged": "1599a1952cf42789477a3dd6a38f4825ce322624df5316c78ddbb272f8203d54" + }, + { + "left": "af4c29ea559d2ef584f4dc5346c5468eaba16716c7040c9d39a46373ef4c6220", + "right": "27e67cc971be8ccb6f4729fcbd341023a76b81a396f3bec9783f0a2547e66dbc", + "merged": "1773da5b0175884924078544fcaa72406bb762886bd3a758d12a3f2dd22d92f5" + }, + { + "left": "6d44bebd692e60522b515035f58d51696212f509323d8fdf4f81a3c0cec5d807", + "right": "b15ab900a61287064846d1b0b66af50f2a730391fe3f677e5e84d10908d83e18", + "merged": "1a7081219f0b6b5636aa38eef2089e3afe27b39c3766398dbc8630527b488613" + }, + { + "left": "0b36b96a99cdbc6bd4421b11be569976680031f71af13af66ed3b5659764cfe2", + "right": "4f947ff376beb30ffd1e60ebb693703366d7cec799d26c207d67d3cb54f1c123", + "merged": "23670d0d1bb13b179d04dc68c50a70aee20e09df62983d68c9359da6bf568420" + } +] diff --git a/pkg/http-interface/Cargo.toml b/pkg/http-interface/Cargo.toml new file mode 100644 index 0000000..d61bfba --- /dev/null +++ b/pkg/http-interface/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "http-interface" +version = "0.1.0" +edition = "2024" + +[dependencies] +async-trait = { workspace = true } +chrono = { workspace = true } +reqwest = { workspace = true } +rpc = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +unimock = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/http-interface/src/builder.rs b/pkg/http-interface/src/builder.rs new file mode 100644 index 0000000..4541342 --- /dev/null +++ b/pkg/http-interface/src/builder.rs @@ -0,0 +1,98 @@ +use crate::{ + ClientResponse, + error::{HttpRequestExecError, Result}, +}; +use async_trait::async_trait; +use reqwest::header::HeaderMap; +use rpc::error::{ErrorOutput, TryFromHTTPError}; +use serde::Serialize; +use std::{fmt::Debug, sync::Arc}; + +/// Shared function signature applied to a [`reqwest::RequestBuilder`] before dispatch. +pub type BodyApplier = + dyn Fn(reqwest::RequestBuilder) -> reqwest::RequestBuilder + Send + Sync + 'static; + +/// Owned request body that can be replayed when the request executes. +pub struct HttpBody { + applier: Arc, +} + +impl HttpBody { + /// Construct a JSON body from an owned serializable value. + pub fn json(value: T) -> Self + where + T: Serialize + Send + Sync + 'static, + { + let value = Arc::new(value); + Self { + applier: Arc::new(move |builder: reqwest::RequestBuilder| builder.json(&*value)), + } + } + + /// Access the request mutation closure used when executing the HTTP call. + #[must_use] + pub fn applier(&self) -> Arc { + Arc::clone(&self.applier) + } +} + +/// Internal adapter trait that bridges concrete request builders to the type-erased interface. +#[async_trait] +pub trait HttpRequestExecutor: Send { + /// Attach additional headers to the request being built. + fn headers(&mut self, headers: HeaderMap); + + /// Attach query parameters to the request being built. + fn query(&mut self, query: Vec<(String, String)>); + + /// Request that authentication be applied to the built request. + fn auth(&mut self); + + /// Execute the request, yielding the raw client response or execution error. + async fn exec(self: Box) -> std::result::Result; +} + +/// Type-erased HTTP request builder returned by [`crate::HttpClient`]. +pub struct HttpRequestBuilder { + executor: Box, +} + +impl HttpRequestBuilder { + /// Create a new builder from the provided executor. + #[must_use] + pub fn new(executor: Box) -> Self { + Self { executor } + } + + /// Attach additional headers to the request. + #[must_use] + pub fn headers(mut self, headers: HeaderMap) -> Self { + self.executor.headers(headers); + self + } + + /// Attach query parameters to the request. + #[must_use] + pub fn query(mut self, query: Vec<(String, String)>) -> Self { + self.executor.query(query); + self + } + + /// Request that the underlying client applies authentication before sending. + #[must_use] + pub fn auth(mut self) -> Self { + self.executor.auth(); + self + } + + /// Execute the HTTP request and return the wrapped response. + pub async fn exec(self) -> Result + where + E: TryFrom + Debug + Send, + { + self.executor + .exec() + .await + .map_err(HttpRequestExecError::into_error::) + } +} diff --git a/pkg/http-interface/src/client.rs b/pkg/http-interface/src/client.rs new file mode 100644 index 0000000..e0a2d8d --- /dev/null +++ b/pkg/http-interface/src/client.rs @@ -0,0 +1,161 @@ +use crate::{ + ClientResponse, HttpMetadata, HttpRequestBuilder, + builder::{HttpBody, HttpRequestExecutor}, + error::{AuthError, HttpRequestExecError}, +}; +use reqwest::header::HeaderMap; +use std::sync::{Arc, Mutex}; + +/// Implement auth for the HTTP client; invoked whenever `.auth()` is used on a request. +#[async_trait::async_trait] +pub trait ClientHttpAuth: Send + Sync { + /// Get auth headers (can be a cached version). + async fn get_auth(&self) -> std::result::Result; + + /// Refresh auth. Called if the auth provided by `get_auth` is invalid (usually because it + /// needs to be refreshed). + async fn refresh_auth(&self) -> std::result::Result<(), AuthError>; +} + +/// Abstraction over HTTP client implementations to support swapping, mocking, +/// and dependency injection across crates. +#[unimock::unimock(api = HttpClientMock)] +pub trait HttpClient: Send + Sync { + /// Configure a GET request for the provided path. + fn get(&self, path: &str) -> HttpRequestBuilder; + + /// Configure a POST request for the provided path. + fn post(&self, path: &str, body: Option) -> HttpRequestBuilder; + + /// Configure a DELETE request for the provided path. + fn delete(&self, path: &str, body: Option) -> HttpRequestBuilder; + + /// Configure a PUT request for the provided path. + fn put(&self, path: &str, body: Option) -> HttpRequestBuilder; + + /// Configure a PATCH request for the provided path. + fn patch(&self, path: &str, body: Option) -> HttpRequestBuilder; +} + +/// Simple recording HTTP client for integration tests that need to assert calls. +#[derive(Clone)] +pub struct RecordingHttpClient { + calls: Arc>>, +} + +impl RecordingHttpClient { + /// Create a new recording client + #[must_use] + pub fn new() -> Self { + Self { + calls: Arc::new(Mutex::new(Vec::new())), + } + } + + /// Get recorded calls + #[must_use] + pub fn calls(&self) -> Vec<(reqwest::Method, String)> { + self.calls.lock().unwrap().clone() + } + + /// Record a call + fn record_call(&self, method: reqwest::Method, path: &str) { + self.calls.lock().unwrap().push((method, path.to_owned())); + } +} + +impl Default for RecordingHttpClient { + fn default() -> Self { + Self::new() + } +} + +/// Mock request builder that implements HttpRequestBuilder for testing +#[derive(Clone)] +pub struct MockRequestBuilder { + method: reqwest::Method, + path: String, + headers: Option, + query: Option>, + auth: bool, +} + +impl MockRequestBuilder { + fn new(method: reqwest::Method, path: String) -> Self { + Self { + method, + path, + headers: None, + query: None, + auth: false, + } + } +} + +#[async_trait::async_trait] +impl HttpRequestExecutor for MockRequestBuilder { + fn headers(&mut self, headers: reqwest::header::HeaderMap) { + self.headers = Some(headers); + } + + fn query(&mut self, query: Vec<(String, String)>) { + self.query = Some(query); + } + + fn auth(&mut self) { + self.auth = true; + } + + async fn exec(self: Box) -> Result { + // Default mock behavior: return server error + Err(HttpRequestExecError::ServerError( + "mock failure".to_string(), + HttpMetadata { + method: self.method, + path: self.path, + }, + )) + } +} + +impl HttpClient for RecordingHttpClient { + fn get(&self, path: &str) -> HttpRequestBuilder { + self.record_call(reqwest::Method::GET, path); + HttpRequestBuilder::new(Box::new(MockRequestBuilder::new( + reqwest::Method::GET, + path.to_string(), + ))) + } + + fn post(&self, path: &str, _body: Option) -> HttpRequestBuilder { + self.record_call(reqwest::Method::POST, path); + HttpRequestBuilder::new(Box::new(MockRequestBuilder::new( + reqwest::Method::POST, + path.to_string(), + ))) + } + + fn delete(&self, path: &str, _body: Option) -> HttpRequestBuilder { + self.record_call(reqwest::Method::DELETE, path); + HttpRequestBuilder::new(Box::new(MockRequestBuilder::new( + reqwest::Method::DELETE, + path.to_string(), + ))) + } + + fn put(&self, path: &str, _body: Option) -> HttpRequestBuilder { + self.record_call(reqwest::Method::PUT, path); + HttpRequestBuilder::new(Box::new(MockRequestBuilder::new( + reqwest::Method::PUT, + path.to_string(), + ))) + } + + fn patch(&self, path: &str, _body: Option) -> HttpRequestBuilder { + self.record_call(reqwest::Method::PATCH, path); + HttpRequestBuilder::new(Box::new(MockRequestBuilder::new( + reqwest::Method::PATCH, + path.to_string(), + ))) + } +} diff --git a/pkg/http-interface/src/error.rs b/pkg/http-interface/src/error.rs new file mode 100644 index 0000000..8ce19fc --- /dev/null +++ b/pkg/http-interface/src/error.rs @@ -0,0 +1,229 @@ +// lint-long-file-override allow-max-lines=250 +use crate::response::HttpMetadata; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, TryFromHTTPError}, +}; +use std::{fmt::Debug, marker::PhantomData}; + +/// Result alias for HTTP client interactions. +pub type Result = std::result::Result>; + +/// Error response from HTTP clients compatible with the workspace APIs. +#[derive(Debug, Clone, thiserror::Error)] +pub enum Error +where + E: Debug, +{ + /// RPC error propagated from the destination service. + #[error("rpc response {0:?}")] + Rpc(E), + /// Internal server error. + #[error("server error {0} at {1}")] + ServerError(String, HttpMetadata), + /// Unauthenticated error requiring credential refresh. + #[error("[http-interface/error] unauthenticated ({reason}) at {metadata}")] + Unauthenticated { + /// RPC error payload returned by the destination service. + output: ErrorOutput, + /// HTTP request metadata for observability and logging. + metadata: HttpMetadata, + /// Reason string explaining why authentication failed. + reason: String, + }, + /// Response error format is invalid. + #[error("unknown response error output {0:?} {1:?} at {2}")] + UnknownErrorOutput(ErrorOutput, TryFromHTTPError, HttpMetadata), + /// Error in expected format, but reason code is unknown. Reason code provided. + #[error("unknown response {0} at {1}")] + UnknownErrorResponse(String, HttpMetadata), + /// Serde json parse error. + #[error("serde_json error {0} at {1}")] + SerdeJson(String, HttpMetadata), + /// Reqwest client error. + #[error("reqwest error {0} at {1}")] + Reqwest(String, HttpMetadata), + /// Authentication retrieval failure. + #[error("unable to get auth {0} at {1}")] + GetAuth(String, HttpMetadata), + /// Authentication refresh failure. + #[error("unable to refresh auth {0} at {1}")] + RefreshAuth(String, HttpMetadata), +} + +/// No RPC errors exist. Its not possible for this error to be constructed. +#[derive(Debug, Clone)] +pub struct NoRpcError(PhantomData); + +/// Canonical authentication error used by [`crate::client::ClientHttpAuth`] implementations. +pub type AuthError = Error; + +impl TryFrom for NoRpcError { + type Error = TryFromHTTPError; + + fn try_from(output: ErrorOutput) -> std::result::Result { + Err(TryFromHTTPError::NoRpcErrorExpected(output)) + } +} + +/// Type-erased error produced during HTTP request execution prior to RPC error conversion. +#[derive(Debug, Clone, thiserror::Error)] +pub enum HttpRequestExecError { + /// RPC error payload returned by the remote service; conversion deferred until later. + #[error("[http-interface/error] rpc response {output:?} at {metadata}")] + Rpc { + /// Raw error payload from the server. + output: ErrorOutput, + /// Request metadata for observability. + metadata: HttpMetadata, + }, + /// Internal server error. + #[error("[http-interface/error] server error {0} at {1}")] + ServerError(String, HttpMetadata), + /// Unauthenticated error requiring credential refresh. + #[error("[http-interface/error] unauthenticated ({reason}) at {metadata}")] + Unauthenticated { + /// RPC error payload returned by the destination service. + output: ErrorOutput, + /// HTTP request metadata for observability and logging. + metadata: HttpMetadata, + /// Reason string explaining why authentication failed. + reason: String, + }, + /// Response error format is invalid. + #[error("[http-interface/error] unknown response {0} at {1}")] + UnknownErrorResponse(String, HttpMetadata), + /// Serde json parse error. + #[error("[http-interface/error] serde_json error {0} at {1}")] + SerdeJson(String, HttpMetadata), + /// Reqwest client error. + #[error("[http-interface/error] reqwest error {message} at {metadata}")] + Reqwest { + /// Error message. + message: String, + /// Request metadata for observability. + metadata: HttpMetadata, + /// Whether the failure was a connection error. + is_connect: bool, + /// Whether the failure was a timeout. + is_timeout: bool, + }, + /// Authentication retrieval failure. + #[error("[http-interface/error] unable to get auth {0} at {1}")] + GetAuth(String, HttpMetadata), + /// Authentication refresh failure. + #[error("[http-interface/error] unable to refresh auth {0} at {1}")] + RefreshAuth(String, HttpMetadata), +} + +impl HttpRequestExecError { + /// Convert the execution error into the public [`Error`] type by materialising the RPC error. + #[must_use] + pub fn into_error(self) -> Error + where + E: TryFrom + Debug, + { + match self { + Self::Rpc { output, metadata } => match output.clone().try_into() { + Ok(rpc_error) => Error::Rpc(rpc_error), + Err(into_err) => Error::UnknownErrorOutput(output, into_err, metadata), + }, + Self::ServerError(message, metadata) => Error::ServerError(message, metadata), + Self::Unauthenticated { + output, + metadata, + reason, + } => Error::Unauthenticated { + output, + metadata, + reason, + }, + Self::UnknownErrorResponse(message, metadata) => { + Error::UnknownErrorResponse(message, metadata) + } + Self::SerdeJson(message, metadata) => Error::SerdeJson(message, metadata), + Self::Reqwest { + message, metadata, .. + } => Error::Reqwest(message, metadata), + Self::GetAuth(message, metadata) => Error::GetAuth(message, metadata), + Self::RefreshAuth(message, metadata) => Error::RefreshAuth(message, metadata), + } + } +} + +/// Map the error response from the server into an execution error without materialising RPC types. +pub async fn handle_error_raw( + response: reqwest::Response, + method: &reqwest::Method, + path: &str, +) -> std::result::Result { + let status = response.status(); + if status.is_success() || status.is_redirection() { + return Ok(response); + } + + let http_metadata = HttpMetadata { + method: method.clone(), + path: path.to_owned(), + }; + + let text = response + .text() + .await + .map_err(|err| HttpRequestExecError::Reqwest { + message: err.to_string(), + metadata: http_metadata.clone(), + // Connect/timeout failures happen during request send, not response read. + is_connect: false, + is_timeout: false, + })?; + + let error_output = match serde_json::from_str::(&text) { + Ok(error) => error, + Err(err) => { + if status.is_server_error() { + return Err(HttpRequestExecError::ServerError( + "server error".to_string(), + http_metadata, + )); + } + return Err(HttpRequestExecError::UnknownErrorResponse( + err.to_string(), + http_metadata, + )); + } + }; + + // Check for internal error + if error_output.error.reason == "internal" || status.is_server_error() { + return Err(HttpRequestExecError::ServerError(text, http_metadata)); + } + + // Check for invalid authentication, if so we should reauthenticate + if error_output.error.code == ErrorCode::Unauthenticated { + return Err(HttpRequestExecError::Unauthenticated { + reason: error_output.error.reason.clone(), + output: error_output, + metadata: http_metadata, + }); + } + + Err(HttpRequestExecError::Rpc { + output: error_output, + metadata: http_metadata, + }) +} + +/// Map the error response from the server into the public [`Error`] type. +pub async fn handle_error( + response: reqwest::Response, + method: &reqwest::Method, + path: &str, +) -> Result +where + E: TryFrom + Debug, +{ + handle_error_raw(response, method, path) + .await + .map_err(HttpRequestExecError::into_error::) +} diff --git a/pkg/http-interface/src/lib.rs b/pkg/http-interface/src/lib.rs new file mode 100644 index 0000000..b2c4a2f --- /dev/null +++ b/pkg/http-interface/src/lib.rs @@ -0,0 +1,26 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::doc_markdown)] +#![deny(missing_docs)] + +//! Abstractions for interacting with HTTP clients within the zk-rollup workspace. +//! The interfaces defined here enable dependency injection, mocking, and swapping +//! of HTTP client implementations. + +/// Traits associated with building HTTP requests. +pub mod builder; +/// Core HTTP client abstraction traits. +pub mod client; +/// Shared HTTP error types and helpers. +pub mod error; +/// Response wrapper utilities shared across clients. +pub mod response; + +pub use builder::HttpRequestBuilder; +pub use client::{ + ClientHttpAuth, HttpClient, HttpClientMock, MockRequestBuilder, RecordingHttpClient, +}; +pub use error::{AuthError, Error, NoRpcError, Result, handle_error}; +pub use response::{ClientResponse, HttpMetadata}; diff --git a/pkg/http-interface/src/response.rs b/pkg/http-interface/src/response.rs new file mode 100644 index 0000000..e795c04 --- /dev/null +++ b/pkg/http-interface/src/response.rs @@ -0,0 +1,146 @@ +use crate::error::{Error, Result}; +use reqwest::header::LAST_MODIFIED; +use reqwest::{Response, StatusCode}; +use rpc::{ + error::{ErrorOutput, TryFromHTTPError}, + longpoll::PollData, +}; +use serde::Serialize; +use std::fmt::{self, Debug}; + +/// Metadata describing the HTTP request associated with a response. +#[derive(Debug, Clone)] +pub struct HttpMetadata { + /// HTTP method used for the request. + pub method: reqwest::Method, + /// Path the request was sent to. + pub path: String, +} + +impl fmt::Display for HttpMetadata { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} {}", self.method, self.path) + } +} + +enum ResponseInner { + Http(Response), + Inline { + body: String, + status: StatusCode, + last_modified: Option>, + }, +} + +/// Wrapper around a response for extracting values and metadata. +pub struct ClientResponse { + response: ResponseInner, + http_metadata: HttpMetadata, +} + +impl ClientResponse { + #[must_use] + /// Create a new client response wrapper. + pub fn new(response: Response, http_metadata: HttpMetadata) -> Self { + Self { + response: ResponseInner::Http(response), + http_metadata, + } + } + + /// Create a response from a serializable value, primarily for tests. + #[must_use] + pub fn from_serializable(value: &T, http_metadata: HttpMetadata) -> Self { + let body = + serde_json::to_string(value).expect("serializing inline HTTP response should succeed"); + Self { + response: ResponseInner::Inline { + body, + status: StatusCode::OK, + last_modified: None, + }, + http_metadata, + } + } + + /// Parse client response into the target type. + pub async fn to_value< + R: serde::de::DeserializeOwned, + E: TryFrom + Debug, + >( + self, + ) -> Result { + let metadata = self.http_metadata.clone(); + match self.response { + ResponseInner::Http(response) => { + let text = response + .text() + .await + .map_err(|err| Error::Reqwest(err.to_string(), self.http_metadata.clone()))?; + Self::parse_body(&text, self.http_metadata) + } + ResponseInner::Inline { body, .. } => Self::parse_body(&body, metadata), + } + } + + /// Parse client response with long poll info. + pub async fn to_long_poll< + R: serde::de::DeserializeOwned, + E: TryFrom + Debug, + >( + self, + ) -> Result, E> { + match self.response { + ResponseInner::Http(response) => { + if response.status() == StatusCode::NOT_MODIFIED { + return Ok(PollData::NotModified); + } + + // Get header + let last_modified = response + .headers() + .get(LAST_MODIFIED) + .and_then(|v| v.to_str().ok()) + .and_then(|time| chrono::DateTime::parse_from_rfc3339(time).ok()) + .map(|dt| dt.with_timezone(&chrono::Utc)); + + let text = response + .text() + .await + .map_err(|err| Error::Reqwest(err.to_string(), self.http_metadata.clone()))?; + + let data = Self::parse_body::(&text, self.http_metadata)?; + + Ok(PollData::Modified { + data, + modified_at: last_modified, + }) + } + ResponseInner::Inline { + body, + status, + last_modified, + } => { + if status == StatusCode::NOT_MODIFIED { + return Ok(PollData::NotModified); + } + + let data = Self::parse_body::(&body, self.http_metadata)?; + + Ok(PollData::Modified { + data, + modified_at: last_modified, + }) + } + } + } + + #[allow(clippy::result_large_err)] + fn parse_body(body: &str, metadata: HttpMetadata) -> Result + where + R: serde::de::DeserializeOwned, + E: TryFrom + Debug, + { + serde_json::from_str::(body).map_err(|err| Error::SerdeJson(err.to_string(), metadata)) + } +} diff --git a/pkg/json-store/Cargo.toml b/pkg/json-store/Cargo.toml new file mode 100644 index 0000000..df12a8d --- /dev/null +++ b/pkg/json-store/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "json-store" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +tokio = { workspace = true, features = ["test-util"] } +tempdir = { workspace = true } + +[[example]] +name = "basic_usage" +path = "examples/basic_usage.rs" diff --git a/pkg/json-store/README.md b/pkg/json-store/README.md new file mode 100644 index 0000000..cf1998a --- /dev/null +++ b/pkg/json-store/README.md @@ -0,0 +1,162 @@ +# JSON Store + +A simple, thread-safe JSON store that persists data to JSON files with atomic operations. + +## Features + +- **Atomic Operations**: All writes use temporary files and atomic moves to ensure data consistency +- **Generic Storage**: Store any type that implements `Serialize`, `Deserialize`, `Default`, `Clone`, `Send`, and `Sync` +- **Async Support**: Built with `tokio` for async operations +- **Auto-loading**: Automatically loads existing state on initialization +- **Default Fallback**: Creates default state if file doesn't exist or is corrupted +- **Thread-safe**: Uses `Arc>` for safe concurrent access +- **Configurable Path**: Specify custom directory and filename + +## Usage + +Add this to your `Cargo.toml`: + +```toml +[dependencies] +json-store = { workspace = true } +``` + +## Example + +```rust +use json_store::JsonStore; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +struct AppState { + counter: u64, + user_name: String, + settings: Vec, +} + +#[tokio::main] +async fn main() -> Result<(), Box> { + // Create store with custom directory and filename + let store = JsonStore::::new("./test_fixtures", "app_state.json").await?; + + // Read current state + let current_state = store.get().await; + println!("Current state: {:?}", current_state); + + // Update specific properties + store.update(|state| { + state.counter += 1; + state.user_name = "Alice".to_string(); + state.settings.push("dark_mode".to_string()); + }).await?; + + // Replace entire state + let new_state = AppState { + counter: 100, + user_name: "Bob".to_string(), + settings: vec!["light_mode".to_string(), "notifications".to_string()], + }; + store.set(new_state).await?; + + // Clone the store (shares the same underlying data) + let store_clone = store.clone(); + let state_from_clone = store_clone.get().await; + println!("State from clone: {:?}", state_from_clone); + + Ok(()) +} +``` + +## API + +### `JsonStore::new(dir, filename)` + +Creates a new store instance. The directory will be created if it doesn't exist. + +**Parameters:** +- `dir`: Directory path where the JSON file will be stored +- `filename`: Name of the JSON file + +**Returns:** `Result, JsonStoreError>` + +### `get()` + +Returns a clone of the current state. + +**Returns:** `T` + +### `update(update_fn)` + +Updates the state using a closure and persists changes atomically. + +**Parameters:** +- `update_fn`: Closure that takes `&mut T` and modifies the state + +**Returns:** `Result<(), JsonStoreError>` + +### `set(new_state)` + +Replaces the entire state with a new value and persists it atomically. + +**Parameters:** +- `new_state`: The new state to replace the current one + +**Returns:** `Result<(), JsonStoreError>` + +### `file_path()` + +Returns the path to the JSON file. + +**Returns:** `&Path` + +## Error Handling + +The crate defines `JsonStoreError` enum with the following variants: + +- `Io(std::io::Error)`: File system operations errors +- `Serialization(serde_json::Error)`: JSON serialization/deserialization errors +- `PathError(String)`: Path-related errors + +## Atomic Operations + +The store ensures atomicity by: + +1. Writing data to a temporary file (`.tmp` extension) +2. Using `serde_json::to_string_pretty` for human-readable JSON +3. Atomically moving the temporary file to the target location using `fs::rename` + +This approach prevents data corruption even if the process is interrupted during writes. + +## Thread Safety + +The store uses `Arc>` internally, allowing: + +- Multiple concurrent readers +- Exclusive writer access +- Safe sharing across threads via `Clone` + +## Requirements + +Your data type must implement: + +- `Serialize + Deserialize`: For JSON serialization +- `Default`: For creating initial state when file doesn't exist +- `Clone`: For returning state copies +- `Send + Sync`: For thread safety +- `'static`: For async operations + +## Testing + +Run tests with: + +```bash +cargo test -p json-store +``` + +The test suite includes: + +- Basic CRUD operations +- Persistence across instances +- Atomic write verification +- Concurrent access through cloning +- Error handling scenarios \ No newline at end of file diff --git a/pkg/json-store/examples/basic_usage.rs b/pkg/json-store/examples/basic_usage.rs new file mode 100644 index 0000000..47cc04e --- /dev/null +++ b/pkg/json-store/examples/basic_usage.rs @@ -0,0 +1,129 @@ +//! Basic usage example for json-store +//! +//! This example demonstrates how to use the JsonStore for managing application state +//! with atomic JSON file persistence. +//! +//! Run with: cargo run --example basic_usage + +use json_store::{JsonStore, JsonStoreError}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +struct AppConfig { + version: String, + debug_mode: bool, + max_connections: u32, + server_settings: ServerSettings, + user_preferences: HashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +struct ServerSettings { + host: String, + port: u16, + timeout_seconds: u64, +} + +#[tokio::main] +async fn main() -> Result<(), JsonStoreError> { + println!("🚀 JSON Store Example"); + println!("================================"); + + // Create a store for our application configuration + let config_store = JsonStore::::new("./test_fixtures", "app_config.json").await?; + + // Display initial state + let initial_config = config_store.get().await; + println!("📋 Initial configuration:"); + println!("{initial_config:#?}"); + println!(); + + // Update configuration using the update method + println!("🔧 Updating configuration..."); + config_store + .update(|config| { + config.version = "1.0.0".to_string(); + config.debug_mode = true; + config.max_connections = 100; + + // Update server settings + config.server_settings.host = "localhost".to_string(); + config.server_settings.port = 8080; + config.server_settings.timeout_seconds = 30; + + // Add user preferences + config + .user_preferences + .insert("theme".to_string(), "dark".to_string()); + config + .user_preferences + .insert("language".to_string(), "en".to_string()); + }) + .await?; + + // Display updated configuration + let updated_config = config_store.get().await; + println!("✅ Updated configuration:"); + println!("{updated_config:#?}"); + println!(); + + // Demonstrate incremental updates + println!("📝 Making incremental updates..."); + for i in 1..=5 { + config_store + .update(|config| { + config + .user_preferences + .insert(format!("setting_{i}"), format!("value_{i}")); + }) + .await?; + } + + // Show final state + let final_config = config_store.get().await; + println!("🎯 Final configuration:"); + println!("{final_config:#?}"); + println!(); + + // Demonstrate complete replacement + println!("🔄 Replacing entire configuration..."); + let new_config = AppConfig { + version: "2.0.0".to_string(), + debug_mode: false, + max_connections: 200, + server_settings: ServerSettings { + host: "0.0.0.0".to_string(), + port: 9090, + timeout_seconds: 60, + }, + user_preferences: { + let mut prefs = HashMap::new(); + prefs.insert("theme".to_string(), "light".to_string()); + prefs.insert("auto_save".to_string(), "true".to_string()); + prefs + }, + }; + + config_store.set(new_config).await?; + + let replaced_config = config_store.get().await; + println!("🔄 Replaced configuration:"); + println!("{replaced_config:#?}"); + println!(); + + // Demonstrate persistence by creating a new store instance + println!("💾 Testing persistence..."); + let second_store = JsonStore::::new("./test_fixtures", "app_config.json").await?; + let loaded_config = second_store.get().await; + println!("📂 Loaded from file:"); + println!("{loaded_config:#?}"); + println!(); + + // Show file path + println!("📄 Configuration saved to: {:?}", config_store.file_path()); + + println!("✨ Example completed successfully!"); + + Ok(()) +} diff --git a/pkg/json-store/src/lib.rs b/pkg/json-store/src/lib.rs new file mode 100644 index 0000000..756c4c1 --- /dev/null +++ b/pkg/json-store/src/lib.rs @@ -0,0 +1,358 @@ +// lint-long-file-override allow-max-lines=400 +//! A simple JSON store that persists data to JSON files with atomic operations. +//! +//! This crate provides a generic JSON store that: +//! - Stores data as JSON files +//! - Ensures atomic writes using temporary files +//! - Loads existing state on initialization +//! - Creates default state if file doesn't exist +//! - Supports async operations +//! +//! # Example +//! +//! ```rust +//! use json_store::JsonStore; +//! use serde::{Deserialize, Serialize}; +//! +//! #[derive(Debug, Clone, Serialize, Deserialize, Default)] +//! struct MyState { +//! counter: u64, +//! name: String, +//! } +//! +//! #[tokio::main] +//! async fn main() -> Result<(), Box> { +//! let store = JsonStore::::new("./test_fixtures", "state.json").await?; +//! +//! // Read current state +//! let state = store.get().await; +//! println!("Current state: {:?}", state); +//! +//! // Update a single property +//! store.update(|state| { +//! state.counter += 1; +//! state.name = "Updated".to_string(); +//! }).await?; +//! +//! Ok(()) +//! } +//! ``` + +use serde::{Deserialize, Serialize}; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use tokio::fs; +use tokio::sync::RwLock; +use tracing::{debug, info, warn}; + +/// Error types for the JSON store +#[derive(thiserror::Error, Debug)] +pub enum JsonStoreError { + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + + #[error("JSON serialization error: {0}")] + Serialization(#[from] serde_json::Error), + + #[error("File path error: {0}")] + PathError(String), +} + +/// A generic JSON store that persists data to JSON files with atomic operations +pub struct JsonStore { + data: Arc>, + file_path: PathBuf, +} + +impl JsonStore +where + T: Serialize + for<'de> Deserialize<'de> + Default + Clone + Send + Sync + 'static, +{ + /// Creates a new JsonStore instance + /// + /// # Arguments + /// * `dir` - Directory path where the JSON file will be stored + /// * `filename` - Name of the JSON file + /// + /// # Returns + /// A new JsonStore instance with loaded or default state + pub async fn new>(dir: P, filename: &str) -> Result { + let dir_path = dir.as_ref(); + let file_path = dir_path.join(filename); + + // Ensure the directory exists + if !dir_path.exists() { + info!("Creating directory: {:?}", dir_path); + fs::create_dir_all(dir_path).await?; + } + + // Load existing data or create default + let data = if file_path.exists() { + debug!("Loading existing state from: {:?}", file_path); + let content = fs::read_to_string(&file_path).await?; + match serde_json::from_str::(&content) { + Ok(parsed_data) => { + info!("Successfully loaded state from: {:?}", file_path); + parsed_data + } + Err(e) => { + warn!( + "Failed to parse JSON from {:?}, using default: {}", + file_path, e + ); + T::default() + } + } + } else { + info!( + "File {:?} doesn't exist, creating with default state", + file_path + ); + T::default() + }; + + let store = Self { + data: Arc::new(RwLock::new(data)), + file_path, + }; + + // Write initial state to file if it didn't exist + if !store.file_path.exists() { + store.persist().await?; + } + + Ok(store) + } + + /// Gets a clone of the current state + pub async fn get(&self) -> T { + let data = self.data.read().await; + data.clone() + } + + /// Updates the state using a closure and persists the changes atomically + /// + /// # Arguments + /// * `update_fn` - A closure that takes a mutable reference to the state + /// + /// # Returns + /// Result indicating success or failure of the update operation + pub async fn update(&self, update_fn: F) -> Result<(), JsonStoreError> + where + F: FnOnce(&mut T) + Send, + { + { + let mut data = self.data.write().await; + update_fn(&mut *data); + } + + self.persist().await + } + + /// Replaces the entire state with a new value and persists it atomically + /// + /// # Arguments + /// * `new_state` - The new state to replace the current one + /// + /// # Returns + /// Result indicating success or failure of the set operation + pub async fn set(&self, new_state: T) -> Result<(), JsonStoreError> { + { + let mut data = self.data.write().await; + *data = new_state; + } + + self.persist().await + } + + /// Persists the current state to the JSON file atomically + /// + /// This method writes to a temporary file first, then atomically moves it + /// to the target location to ensure consistency. + async fn persist(&self) -> Result<(), JsonStoreError> { + let data = self.data.read().await; + + // Serialize the data + let json_content = serde_json::to_string_pretty(&*data)?; + + // Create a temporary file in the same directory as the target file + let temp_path = self.file_path.with_extension("tmp"); + + // Write to temporary file + fs::write(&temp_path, &json_content).await?; + + // Atomically move the temporary file to the target location + fs::rename(&temp_path, &self.file_path).await?; + + debug!("Successfully persisted state to: {:?}", self.file_path); + Ok(()) + } + + /// Gets the file path where the data is stored + pub fn file_path(&self) -> &Path { + &self.file_path + } +} + +impl Clone for JsonStore +where + T: Clone, +{ + fn clone(&self) -> Self { + Self { + data: Arc::clone(&self.data), + file_path: self.file_path.clone(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde::{Deserialize, Serialize}; + use tempdir::TempDir; + + #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] + struct TestState { + counter: u64, + name: String, + active: bool, + } + + #[tokio::test] + async fn test_new_store_creates_default_state() { + let temp_dir = TempDir::new("json_kv_store_test").unwrap(); + let store = JsonStore::::new(temp_dir.path(), "test.json") + .await + .unwrap(); + + let state = store.get().await; + assert_eq!(state, TestState::default()); + } + + #[tokio::test] + async fn test_update_and_persist() { + let temp_dir = TempDir::new("json_kv_store_test").unwrap(); + let store = JsonStore::::new(temp_dir.path(), "test.json") + .await + .unwrap(); + + // Update the state + store + .update(|state| { + state.counter = 42; + state.name = "test".to_string(); + state.active = true; + }) + .await + .unwrap(); + + // Verify the state was updated + let state = store.get().await; + assert_eq!(state.counter, 42); + assert_eq!(state.name, "test"); + assert!(state.active); + } + + #[tokio::test] + async fn test_set_and_persist() { + let temp_dir = TempDir::new("json_kv_store_test").unwrap(); + let store = JsonStore::::new(temp_dir.path(), "test.json") + .await + .unwrap(); + + let new_state = TestState { + counter: 100, + name: "new_test".to_string(), + active: false, + }; + + store.set(new_state.clone()).await.unwrap(); + + let retrieved_state = store.get().await; + assert_eq!(retrieved_state, new_state); + } + + #[tokio::test] + async fn test_persistence_across_instances() { + let temp_dir = TempDir::new("json_kv_store_test").unwrap(); + let file_path = temp_dir.path().join("persistent.json"); + + // Create first instance and update state + { + let store = JsonStore::::new(temp_dir.path(), "persistent.json") + .await + .unwrap(); + + store + .update(|state| { + state.counter = 999; + state.name = "persistent".to_string(); + }) + .await + .unwrap(); + } + + // Create second instance and verify state was loaded + { + let store = JsonStore::::new(temp_dir.path(), "persistent.json") + .await + .unwrap(); + + let state = store.get().await; + assert_eq!(state.counter, 999); + assert_eq!(state.name, "persistent"); + } + + // Verify the file actually exists + assert!(file_path.exists()); + } + + #[tokio::test] + async fn test_atomic_writes() { + let temp_dir = TempDir::new("json_kv_store_test").unwrap(); + let store = JsonStore::::new(temp_dir.path(), "atomic.json") + .await + .unwrap(); + + // Perform multiple rapid updates + for i in 0..10 { + store + .update(|state| { + state.counter = i; + }) + .await + .unwrap(); + } + + // Verify final state + let state = store.get().await; + assert_eq!(state.counter, 9); + + // Verify no temporary files are left behind + let temp_file = store.file_path.with_extension("tmp"); + assert!(!temp_file.exists()); + } + + #[tokio::test] + async fn test_clone_shares_state() { + let temp_dir = TempDir::new("json_kv_store_test").unwrap(); + let store1 = JsonStore::::new(temp_dir.path(), "shared.json") + .await + .unwrap(); + + let store2 = store1.clone(); + + // Update through first store + store1 + .update(|state| { + state.counter = 123; + }) + .await + .unwrap(); + + // Verify change is visible through second store + let state = store2.get().await; + assert_eq!(state.counter, 123); + } +} diff --git a/pkg/json-with-logging/Cargo.toml b/pkg/json-with-logging/Cargo.toml new file mode 100644 index 0000000..0dc7cf3 --- /dev/null +++ b/pkg/json-with-logging/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "json-with-logging" +version = "0.1.0" +edition = "2024" + +[dependencies] +actix-web = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tracing = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/json-with-logging/src/lib.rs b/pkg/json-with-logging/src/lib.rs new file mode 100644 index 0000000..d91d810 --- /dev/null +++ b/pkg/json-with-logging/src/lib.rs @@ -0,0 +1,244 @@ +// lint-long-file-override allow-max-lines=300 +use std::future::Future; +use std::pin::Pin; + +use actix_web::{FromRequest, HttpRequest, dev::Payload, web}; +use serde::{Serialize, de::DeserializeOwned}; + +/// A JSON extractor that logs deserialization errors with structured logging +/// and request context for debugging purposes. +#[derive(Debug)] +pub struct JsonWithLogging { + pub json: T, +} + +impl Serialize for JsonWithLogging +where + T: Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.json.serialize(serializer) + } +} + +impl FromRequest for JsonWithLogging +where + T: DeserializeOwned + 'static, +{ + type Error = actix_web::Error; + type Future = Pin>>>; + + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { + let mut payload = payload.take(); + let req = req.clone(); + + let fut = async move { + let frozen_body = web::Bytes::from_request(&req, &mut payload).await?; + + // Deserialize the body into the specified type + let deserialized_body: T = serde_json::from_slice(&frozen_body).map_err(|e| { + // Log the raw payload for debugging with structured logging + let method = req.method().as_str(); + let path = req.path(); + let content_type = req + .headers() + .get("content-type") + .and_then(|h| h.to_str().ok()) + .unwrap_or("unknown"); + + // Truncate oversized payloads (>10KB) + const MAX_PAYLOAD_LOG_SIZE: usize = 10 * 1024; // 10KB + let payload_str = String::from_utf8_lossy(&frozen_body); + let truncated_payload = if payload_str.len() > MAX_PAYLOAD_LOG_SIZE { + format!( + "{}...[TRUNCATED: {} bytes total]", + &payload_str[..MAX_PAYLOAD_LOG_SIZE], + payload_str.len() + ) + } else { + payload_str.to_string() + }; + + // Sanitize sensitive headers for logging + let mut safe_headers = std::collections::HashMap::new(); + for (name, value) in req.headers().iter() { + let name_lower = name.as_str().to_lowercase(); + if name_lower.contains("authorization") + || name_lower.contains("signature") + || name_lower.contains("secret") + || name_lower.contains("key") + { + safe_headers.insert(name.as_str(), "[REDACTED]"); + } else if let Ok(value_str) = value.to_str() { + safe_headers.insert(name.as_str(), value_str); + } + } + + tracing::error!( + method = method, + path = path, + content_type = content_type, + payload_size = frozen_body.len(), + raw_payload = %truncated_payload, + headers = ?safe_headers, + serde_error = %e, + "JSON deserialization failed - logging raw payload for debugging" + ); + + actix_web::error::ErrorBadRequest(format!("Failed to parse JSON: {e:?}")) + })?; + + Ok(JsonWithLogging { + json: deserialized_body, + }) + }; + + Box::pin(fut) + } +} + +impl std::ops::Deref for JsonWithLogging { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.json + } +} + +impl std::ops::DerefMut for JsonWithLogging { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.json + } +} + +impl JsonWithLogging { + /// Extract the inner JSON value, consuming the wrapper + pub fn into_inner(self) -> T { + self.json + } +} + +#[cfg(test)] +mod tests { + use super::*; + use actix_web::{HttpResponse, test, web}; + use serde::{Deserialize, Serialize}; + + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct TestPayload { + message: String, + count: i32, + } + + async fn test_handler(payload: JsonWithLogging) -> HttpResponse { + HttpResponse::Ok().json(&*payload) + } + + #[actix_web::test] + async fn test_valid_json_parsing() { + let app = + test::init_service(actix_web::App::new().route("/test", web::post().to(test_handler))) + .await; + + let payload = TestPayload { + message: "hello".to_string(), + count: 42, + }; + + let req = test::TestRequest::post() + .uri("/test") + .set_json(&payload) + .to_request(); + + let resp = test::call_service(&app, req).await; + assert!(resp.status().is_success()); + } + + #[actix_web::test] + async fn test_payload_limit_enforced() { + let app = test::init_service( + actix_web::App::new() + .app_data(web::PayloadConfig::default().limit(1024)) + .route("/test", web::post().to(test_handler)), + ) + .await; + + let payload = TestPayload { + message: "x".repeat(2048), + count: 1, + }; + + let req = test::TestRequest::post() + .uri("/test") + .set_json(&payload) + .to_request(); + + let resp = test::call_service(&app, req).await; + assert_eq!( + resp.status(), + actix_web::http::StatusCode::PAYLOAD_TOO_LARGE + ); + } + + #[actix_web::test] + async fn test_payload_truncation_logic() { + let long_string = "x".repeat(12000); // > 10KB + let payload = TestPayload { + message: long_string.clone(), + count: 123, + }; + + // This test verifies the truncation logic without actually calling the service + // since we can't easily test the error case without mocking + const MAX_PAYLOAD_LOG_SIZE: usize = 10 * 1024; + let payload_str = serde_json::to_string(&payload).unwrap(); + + if payload_str.len() > MAX_PAYLOAD_LOG_SIZE { + let truncated = format!( + "{}...[TRUNCATED: {} bytes total]", + &payload_str[..MAX_PAYLOAD_LOG_SIZE], + payload_str.len() + ); + assert!(truncated.contains("[TRUNCATED:")); + assert!(truncated.len() > MAX_PAYLOAD_LOG_SIZE); + } + } + + #[test] + async fn test_header_sanitization() { + let mut safe_headers = std::collections::HashMap::new(); + + // Test cases for header sanitization + let test_headers = vec![ + ("authorization", "Bearer token123", "[REDACTED]"), + ("x-signature", "sig123", "[REDACTED]"), + ("x-api-key", "key123", "[REDACTED]"), + ("x-secret", "secret123", "[REDACTED]"), + ("content-type", "application/json", "application/json"), + ("user-agent", "test-agent", "test-agent"), + ]; + + for (name, value, _expected) in test_headers { + let name_lower = name.to_lowercase(); + if name_lower.contains("authorization") + || name_lower.contains("signature") + || name_lower.contains("secret") + || name_lower.contains("key") + { + safe_headers.insert(name, "[REDACTED]"); + } else { + safe_headers.insert(name, value); + } + } + + assert_eq!(safe_headers.get("authorization"), Some(&"[REDACTED]")); + assert_eq!(safe_headers.get("x-signature"), Some(&"[REDACTED]")); + assert_eq!(safe_headers.get("x-api-key"), Some(&"[REDACTED]")); + assert_eq!(safe_headers.get("x-secret"), Some(&"[REDACTED]")); + assert_eq!(safe_headers.get("content-type"), Some(&"application/json")); + assert_eq!(safe_headers.get("user-agent"), Some(&"test-agent")); + } +} diff --git a/pkg/kyc/Cargo.toml b/pkg/kyc/Cargo.toml new file mode 100644 index 0000000..eb3c950 --- /dev/null +++ b/pkg/kyc/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "kyc" +version = "0.1.0" +edition = "2024" + +[features] +diesel = ["dep:diesel"] +ts-rs = ["dep:ts-rs"] + +[dependencies] + +currency = { workspace = true } + +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +chrono = { workspace = true } +phonenumber = { workspace = true } +strum = { workspace = true } +base64 = { workspace = true } + +diesel = { workspace = true, optional = true } +ts-rs = { workspace = true, optional = true } +workspace-hack.workspace = true + +[dev-dependencies] +tokio = { workspace = true } diff --git a/pkg/kyc/README.md b/pkg/kyc/README.md new file mode 100644 index 0000000..dacd4e8 --- /dev/null +++ b/pkg/kyc/README.md @@ -0,0 +1,199 @@ +# KYC (Know Your Customer) Crate + +A comprehensive Rust library for managing KYC (Know Your Customer) verification processes across multiple financial service providers. This crate provides a unified interface for handling identity verification, document management, and compliance requirements. + +## Overview + +The `kyc` crate abstracts the complexity of integrating with various KYC providers (Alfred, Manteca, Rain, Sumsub) by providing: + +- **Standardized data structures** for personal information and documents +- **Comprehensive error handling** for KYC-specific scenarios +- **Type-safe status management** for verification workflows +- **Document validation and storage** capabilities + +## Features + +- `diesel` - Enable PostgreSQL database integration via Diesel ORM +- `ts-rs` - Generate TypeScript type definitions for frontend integration + +## Architecture + +### Core Components + +#### 1. **Kyc Struct** (`kyc.rs`) +The central data structure that holds all personal information required for KYC verification: + +```rust +pub struct Kyc { + pub firstname: Option, + pub lastname: Option, + pub dob: Option, + pub addressstreet: Option, + pub addresscity: Option, + pub addresscountry: Option, + pub nationalities: Option, + pub documents: Option>>, + pub phone: Option, + pub email: Option, + // ... additional fields +} +``` + +#### 2. **Type System** (`types.rs`) + +##### KycStatus Enum +Represents the current state of KYC verification: + +```rust +pub enum KycStatus { + NotStarted, // Initial state + Pending, // Verification in progress + Approved, // Successfully verified + UpdateRequired, // Additional information needed + Rejected, // Verification failed +} +``` + +##### KycField Enum +Identifies specific fields in the KYC data structure: + +```rust +pub enum KycField { + Firstname, + Lastname, + Dob, + AddressStreet, + AddressCity, + Phone, + Documents, + // ... etc +} +``` + +#### 3. **Document Management** (`documents.rs`) + +Handles identity document storage and validation: + +- **IDDocument**: Structure for storing document images (front/back) +- **IDKind**: Enumeration of supported document types (Passport, DriverLicense, NationalId, etc.) +- **IDDocumentField**: Wrapper for document data (supports both base64 strings and raw bytes) + +#### 4. **Update Requirements** (`kyc_update_required.rs`) + +Represents validation errors and update requirements: + +- **KycUpdateRequired**: Detailed information about why updates are needed +- **KycUpdateRequiredInvalidFields**: Field-specific failure reasons + +#### 5. **Error Handling** (`error.rs`) + +Comprehensive error types for KYC operations: + +```rust +pub enum Error { + MissingKYCField(String), + InvalidPhoneFormat, + InvalidState { state: String }, + Json(String), +} +``` + +## Usage Examples + +### Working with KYC Data + +```rust +use kyc::{Kyc, KycStatus}; +use currency::Country; + +// Create a new KYC instance +let mut kyc = Kyc::default(); +kyc.firstname = Some("John".to_string()); +kyc.lastname = Some("Doe".to_string()); +kyc.addresscountry = Some(Country::US); + +// Use getter methods with error handling +let full_name = format!("{} {}", + kyc.get_firstname()?, + kyc.get_lastname()? +); + +// Merge KYC data from different sources +let updated_kyc = Kyc { + phone: Some("+1234567890".to_string()), + email: Some("john@example.com".to_string()), + ..Default::default() +}; + +let merged = kyc.merge(&updated_kyc); +``` + +## Integration with Ramps Providers + +This crate provides shared KYC domain types used by the ramps stack. Concrete +provider integrations live in the provider crates: + +- **Alfred**: `alfred-provider` (European-focused KYC provider) +- **Manteca**: `manteca-provider` (Latin American markets) +- **Rain**: `rain-provider` (Middle Eastern financial services) +- **Sumsub**: `sumsub-provider` (Global KYC/AML compliance) + +Shared contracts and validation live in `ramps-interface`, while this crate +defines the common KYC data types and helpers used across providers. + +## Database Integration + +When the `diesel` feature is enabled, all core types can be stored directly in PostgreSQL: + +```rust +// Kyc struct can be stored as JSONB +#[derive(AsExpression, FromSqlRow)] +#[diesel(sql_type = diesel::sql_types::Jsonb)] +pub struct Kyc { /* ... */ } + +// KycStatus can be stored as TEXT +#[derive(AsExpression, FromSqlRow)] +#[diesel(sql_type = diesel::sql_types::Text)] +pub enum KycStatus { /* ... */ } +``` + +## Testing + +The crate includes comprehensive test coverage: + +```bash +# Run all tests +cargo test -p kyc + +# Run with specific features +cargo test -p kyc --features diesel,ts-rs +``` + +Test categories include: +- Getter method validation +- Serialization/deserialization +- Document merging logic +- Phone number validation +- Status transitions +- Error handling + +## Security Considerations + +1. **Sensitive Data Handling**: Personal information should be encrypted at rest and in transit +2. **Document Storage**: Raw document bytes are sanitized during merge operations to prevent memory bloat +3. **Phone Validation**: Phone numbers are validated using the `phonenumber` crate for international formats +4. **Access Control**: Implement appropriate access controls when exposing KYC data through APIs + +## Contributing + +When extending this crate: + +1. Ensure all new fields in `Kyc` struct have corresponding getter methods with proper error handling +2. Update the `KycField` enum when adding new fields +3. Maintain backward compatibility for serialization +4. Add comprehensive tests for new functionality +5. Update provider implementations in the relevant provider crate as needed + +## License + +This crate follows the same license as the parent workspace. diff --git a/pkg/kyc/src/documents.rs b/pkg/kyc/src/documents.rs new file mode 100644 index 0000000..4f3cd26 --- /dev/null +++ b/pkg/kyc/src/documents.rs @@ -0,0 +1,165 @@ +use std::fmt; + +use base64::Engine; +use base64::engine::general_purpose::STANDARD as BASE64; +use serde::{ + Deserialize, Deserializer, Serialize, Serializer, + de::{Error as DeError, SeqAccess, Visitor}, +}; +use strum::Display; + +use super::{Error, Result}; +#[derive(Debug, Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash, Display)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum IDKind { + Passport, + NationalId, + VoterId, + ResidentCard, + ResidentCardTemp, + TemporaryProtectionPermit, + DriversLicense, + StateId, + Selfie, + SelfieLeft, + SelfieRight, +} + +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] +pub enum IDDocumentField { + // for older apps using document bytes + Bytes(Vec), + // for newer apps using document ids + Id { id: String, bytes: Vec }, +} + +impl IDDocumentField { + pub fn get_bytes(&self) -> &[u8] { + match self { + Self::Bytes(bytes) => bytes, + Self::Id { bytes, .. } => bytes, + } + } +} + +pub fn deserialize_document_field_opt<'de, D>( + deserializer: D, +) -> std::result::Result, D::Error> +where + D: Deserializer<'de>, +{ + struct FieldVisitor; + + impl<'de> Visitor<'de> for FieldVisitor { + type Value = Option; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a base64 string, a string with ';', or a byte array") + } + + fn visit_none(self) -> std::result::Result { + Ok(None) + } + + fn visit_unit(self) -> std::result::Result { + Ok(None) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: DeError, + { + if value.contains(';') { + Ok(Some(IDDocumentField::Id { + id: value.to_string(), + bytes: Vec::new(), + })) + } else { + BASE64 + .decode(value) + .map(IDDocumentField::Bytes) + .map(Some) + .map_err(DeError::custom) + } + } + + fn visit_string(self, value: String) -> std::result::Result + where + E: DeError, + { + self.visit_str(&value) + } + + fn visit_seq(self, mut seq: A) -> std::result::Result + where + A: SeqAccess<'de>, + { + let mut bytes = Vec::new(); + while let Some(byte) = seq.next_element::()? { + bytes.push(byte); + } + Ok(Some(IDDocumentField::Bytes(bytes))) + } + } + + deserializer.deserialize_any(FieldVisitor) +} + +pub fn serialize_document_field_opt( + value: &Option, + serializer: S, +) -> std::result::Result +where + S: Serializer, +{ + match value { + Some(IDDocumentField::Bytes(data)) => { + let encoded = BASE64.encode(data); + serializer.serialize_some(&encoded) + } + // serialise only the id + Some(IDDocumentField::Id { id, .. }) => serializer.serialize_some(id), + None => serializer.serialize_none(), + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct IDDocument { + #[serde( + serialize_with = "serialize_document_field_opt", + deserialize_with = "deserialize_document_field_opt" + )] + pub front: Option, + #[serde( + default, + serialize_with = "serialize_document_field_opt", + deserialize_with = "deserialize_document_field_opt" + )] + pub back: Option, +} + +impl IDDocument { + pub fn get_front(&self) -> Result> { + let front = self + .front + .clone() + .ok_or(Error::MissingKYCField("document_front".to_string()))?; + + Ok(match front { + IDDocumentField::Bytes(bytes) => bytes, + IDDocumentField::Id { bytes, .. } => bytes, + }) + } + + pub fn get_back(&self) -> Result> { + let back = self + .back + .clone() + .ok_or(Error::MissingKYCField("document_back".to_string()))?; + + Ok(match back { + IDDocumentField::Bytes(bytes) => bytes, + IDDocumentField::Id { bytes, .. } => bytes, + }) + } +} diff --git a/pkg/kyc/src/error.rs b/pkg/kyc/src/error.rs new file mode 100644 index 0000000..a96a16b --- /dev/null +++ b/pkg/kyc/src/error.rs @@ -0,0 +1,30 @@ +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Debug, Error)] +pub enum Error { + #[error("Missing KYC field: {0}")] + MissingKYCField(String), + + #[error("Invalid phone format")] + InvalidPhoneFormat, + + #[error("[kyc] `{state}` is not a valid US state name or code")] + InvalidState { state: String }, + + #[error("JSON serialization error: {0}")] + Json(String), +} + +impl From for Error { + fn from(err: serde_json::Error) -> Self { + Self::Json(err.to_string()) + } +} + +impl Error { + pub fn missing_field(field: impl Into) -> Self { + Self::MissingKYCField(field.into()) + } +} diff --git a/pkg/kyc/src/kyc.rs b/pkg/kyc/src/kyc.rs new file mode 100644 index 0000000..de271d1 --- /dev/null +++ b/pkg/kyc/src/kyc.rs @@ -0,0 +1,349 @@ +// lint-long-file-override allow-max-lines=400 +use super::{ + Error, IDDocument, IDDocumentField, IDKind, Result, deserialize_document_field_opt, ok_field, + serialize_document_field_opt, +}; +use currency::{Country, CountryList}; +#[cfg(feature = "diesel")] +use diesel::{ + AsExpression, + deserialize::{self, FromSql, FromSqlRow}, + pg::{Pg, PgValue}, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Jsonb, +}; +use phonenumber::parse; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +#[cfg(feature = "diesel")] +use std::io::Write; + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature="diesel",diesel(sql_type = diesel::sql_types::Jsonb))] +pub struct Kyc { + pub firstname: Option, + pub middlename: Option, + pub lastname: Option, + pub dob: Option, + pub occupation: Option, + pub addressstreet: Option, + pub addresscity: Option, + pub addressstate: Option, + pub addresscountry: Option, + pub addresspostalcode: Option, + pub nationalities: Option, + #[serde(default)] + pub documents: Option>>, + pub phone: Option, + pub phoneverified: Option, + pub email: Option, + pub emailverified: Option, + pub nationalid: Option, + pub pep: Option, + pub civilstate: Option, + pub fatca: Option, + pub uif: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde( + default, + serialize_with = "serialize_document_field_opt", + deserialize_with = "deserialize_document_field_opt" + )] + pub selfiefront: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde( + default, + serialize_with = "serialize_document_field_opt", + deserialize_with = "deserialize_document_field_opt" + )] + pub selfieleft: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde( + default, + serialize_with = "serialize_document_field_opt", + deserialize_with = "deserialize_document_field_opt" + )] + pub selfieright: Option, +} + +impl Kyc { + pub fn merge(&self, kyc: &Kyc) -> Self { + let mut merged_documents = self.documents.clone().unwrap_or_default(); + + if let Some(new_documents) = &kyc.documents { + for (country, ids) in new_documents { + let entry = merged_documents.entry(*country).or_default(); + for (id_kind, doc) in ids { + let sanitized_doc = match (doc.front.as_ref(), doc.back.as_ref()) { + (Some(IDDocumentField::Bytes(_)), _) + | (_, Some(IDDocumentField::Bytes(_))) => IDDocument { + front: None, + back: None, + }, + _ => doc.clone(), + }; + entry.insert(*id_kind, sanitized_doc); + } + } + } + + Kyc { + firstname: kyc.firstname.clone().or_else(|| self.firstname.clone()), + middlename: kyc.middlename.clone().or_else(|| self.middlename.clone()), + lastname: kyc.lastname.clone().or_else(|| self.lastname.clone()), + dob: kyc.dob.or(self.dob), + occupation: kyc.occupation.clone().or_else(|| self.occupation.clone()), + addressstreet: kyc + .addressstreet + .clone() + .or_else(|| self.addressstreet.clone()), + addresscity: kyc.addresscity.clone().or_else(|| self.addresscity.clone()), + addressstate: kyc + .addressstate + .clone() + .or_else(|| self.addressstate.clone()), + addresscountry: kyc.addresscountry.or(self.addresscountry), + addresspostalcode: kyc + .addresspostalcode + .clone() + .or_else(|| self.addresspostalcode.clone()), + nationalities: kyc + .nationalities + .clone() + .or_else(|| self.nationalities.clone()), + phone: kyc.phone.clone().or_else(|| self.phone.clone()), + phoneverified: kyc.phoneverified.or(self.phoneverified), + email: kyc.email.clone().or_else(|| self.email.clone()), + emailverified: kyc.emailverified.or(self.emailverified), + nationalid: kyc.nationalid.clone().or_else(|| self.nationalid.clone()), + pep: kyc.pep.or(self.pep), + civilstate: kyc.civilstate.clone().or_else(|| self.civilstate.clone()), + fatca: kyc.fatca.or(self.fatca), + uif: kyc.uif.or(self.uif), + documents: Some(merged_documents), + selfiefront: kyc.selfiefront.clone().or_else(|| self.selfiefront.clone()), + selfieleft: kyc.selfieleft.clone().or_else(|| self.selfieleft.clone()), + selfieright: kyc.selfieright.clone().or_else(|| self.selfieright.clone()), + } + } + + pub fn sanitize_for_storage(&self) -> Self { + let mut sanitized = self.clone(); + + if let Some(mut docs) = sanitized.documents.take() { + for (_country, id_map) in docs.iter_mut() { + for (_id_kind, doc) in id_map.iter_mut() { + if let Some(IDDocumentField::Bytes(_)) = doc.front { + doc.front = None; + } + if let Some(IDDocumentField::Bytes(_)) = doc.back { + doc.back = None; + } + } + } + sanitized.documents = Some(docs); + } + + sanitized + } +} + +#[cfg(feature = "diesel")] +impl ToSql for Kyc { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + out.write_all(&[1])?; + serde_json::to_writer(out, self)?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Kyc { + fn from_sql(bytes: PgValue) -> deserialize::Result { + let bytes = bytes.as_bytes(); + if bytes.is_empty() { + return Ok(Kyc::default()); + } + let json_bytes = &bytes[1..]; + serde_json::from_slice(json_bytes).map_err(Into::into) + } +} + +impl Kyc { + pub fn get_firstname(&self) -> Result { + ok_field(&self.firstname, "firstname") + } + + pub fn get_lastname(&self) -> Result { + ok_field(&self.lastname, "lastname") + } + + pub fn get_dob(&self) -> Result { + ok_field(&self.dob, "dob") + } + + pub fn get_occupation(&self) -> Result { + ok_field(&self.occupation, "occupation") + } + + pub fn get_addressstreet(&self) -> Result { + ok_field(&self.addressstreet, "addressstreet") + } + + pub fn get_addresscity(&self) -> Result { + ok_field(&self.addresscity, "addresscity") + } + + pub fn get_addressstate(&self) -> Result { + ok_field(&self.addressstate, "addressstate") + } + + pub fn get_addresscountry(&self) -> Result { + ok_field(&self.addresscountry, "addresscountry") + } + + pub fn get_addresspostalcode(&self) -> Result { + ok_field(&self.addresspostalcode, "addresspostalcode") + } + + pub fn get_nationalities(&self) -> Result { + let nationalities = ok_field(&self.nationalities, "nationalities")?; + if nationalities.0.is_empty() { + return Err(Error::MissingKYCField("nationalities".to_string())); + } + Ok(nationalities) + } + + pub fn get_nationality_one(&self) -> Result { + ok_field(&self.nationalities, "nationalities")? + .0 + .first() + .cloned() + .ok_or(Error::MissingKYCField("nationalities".to_string())) + } + + pub fn get_document_by_country(&self, country: Country) -> Result<(IDKind, IDDocument)> { + let documents = ok_field(&self.documents, "documents")?; + documents + .get(&country) + .and_then(|docs| docs.iter().next()) + .map(|(kind, doc)| (*kind, doc.clone())) + .ok_or(Error::MissingKYCField("documents".to_string())) + } + + pub fn get_all_documents(&self) -> Result> { + let documents = ok_field(&self.documents, "documents")?; + let mut all = Vec::new(); + + for doc_map in documents.values() { + for doc in doc_map.values() { + all.push(doc.clone()); + } + } + + if all.is_empty() { + return Err(Error::MissingKYCField("documents".to_string())); + } + + Ok(all) + } + + pub fn get_documents_by_country_and_kind( + &self, + country: Country, + kind: IDKind, + ) -> Result { + let documents = ok_field(&self.documents, "documents")?; + documents + .get(&country) + .and_then(|docs| docs.get(&kind)) + .cloned() + .ok_or(Error::MissingKYCField("documents".to_string())) + } + + pub fn get_one_of_document_kinds( + &self, + country: Country, + kinds: &[IDKind], + ) -> Result { + let documents = ok_field(&self.documents, "documents")?; + for kind in kinds { + if let Some(doc) = documents.get(&country).and_then(|docs| docs.get(kind)) { + return Ok(doc.clone()); + } + } + Err(Error::MissingKYCField("documents".to_string())) + } + + pub fn get_documents_countries(&self) -> Result> { + let documents = ok_field(&self.documents, "documents")?; + Ok(documents.keys().cloned().collect()) + } + + pub fn get_documents_countries_one(&self) -> Result { + let countries = self.get_documents_countries()?; + countries + .first() + .cloned() + .ok_or(Error::MissingKYCField("documents".to_string())) + } + + pub fn get_phone(&self) -> Result { + ok_field(&self.phone, "phone") + } + + pub fn get_phone_parts(&self) -> Result<(String, String)> { + let phone = self.get_phone()?; + + // Remove leading zeros and ensure phone has a + prefix + let phone_with_prefix = if !phone.starts_with('+') { + format!("+{}", phone.trim_start_matches('0')) + } else { + format!("+{}", phone.trim_start_matches(['+', '0'])) + }; + + // Try to parse without country first, then with country if that fails + let parsed = parse(None, phone_with_prefix).map_err(|_| Error::InvalidPhoneFormat)?; + + // Get the country code (as u32) and convert to string + let country_code = parsed.country().code().to_string(); + + // Get the national number (without country code) + let national_number = parsed.national().value().to_string(); + + Ok((country_code, national_number)) + } + + pub fn get_phone_verified(&self) -> Result { + ok_field(&self.phoneverified, "phoneverified") + } + + pub fn get_email(&self) -> Result { + ok_field(&self.email, "email") + } + + pub fn get_email_verified(&self) -> Result { + ok_field(&self.emailverified, "emailverified") + } + + pub fn get_nationalid(&self) -> Result { + ok_field(&self.nationalid, "nationalid") + } + + pub fn get_civil_state(&self) -> Result { + ok_field(&self.civilstate, "civilstate") + } + + pub fn get_fatca(&self) -> Result { + ok_field(&self.fatca, "fatca") + } + + pub fn get_uif(&self) -> Result { + ok_field(&self.uif, "uif") + } + + pub fn get_pep(&self) -> Result { + ok_field(&self.pep, "pep") + } +} diff --git a/pkg/kyc/src/kyc_update_required.rs b/pkg/kyc/src/kyc_update_required.rs new file mode 100644 index 0000000..fab10f0 --- /dev/null +++ b/pkg/kyc/src/kyc_update_required.rs @@ -0,0 +1,138 @@ +use std::collections::HashMap; +#[cfg(feature = "diesel")] +use std::io::Write; + +#[cfg(feature = "diesel")] +use diesel::{ + AsExpression, + deserialize::{self, FromSql, FromSqlRow}, + pg::{Pg, PgValue}, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Jsonb, +}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +use crate::KycField; + +#[derive(Default, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE", tag = "reason", content = "data")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum KycUpdateRequiredInvalidFieldsReason { + #[default] + Unspecified, + NameMismatch, + DocumentKycMismatch, + DocumentPhotoBlurry, + DocumentPhotoNotCentered, + DocumentPhotoDamaged, + DocumentPhotoNotOriginal, + DocumentExpiresSoon, + DocumentIsExpired, + DocumentKindNotAllowed, + AdverseMedia, + AgeRequirementMismatch, + Blacklist, + Blocklist, + CheckUnavailable, + CompromisedPersons, + Criminal, + DbDataMismatch, + DbDataNotFound, + DocumentTemplate, + Duplicate, + ExperienceRequirementMismatch, + Forgery, + FraudulentLiveness, + FraudulentPatterns, + InconsistentProfile, + Pep, + RegulationsViolations, + Sanctions, + SelfieMismatch, + Spam, + NotDocument, + ThirdPartyInvolved, + UnsupportedLanguage, + WrongUserRegion, + InvalidPhoneNumber, + InvalidEmail, + InvalidFormat, + InvalidPostalCode, + InvalidNationalId, + NameTooLong, + AddressStreetTooLong, + AddressCityTooLong, + AddressStateTooLong, + Compliance, + Sanctioned, + PoliticallyExposedPerson, +} + +#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct KycUpdateRequiredInvalidFields { + pub fields: HashMap, +} + +#[derive(Default, Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Jsonb))] +#[serde(rename_all = "SCREAMING_SNAKE_CASE", tag = "error", content = "data")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum KycUpdateRequired { + #[default] + None, + UnsupportedCountry, + // String should be an error message to be displayed to the user + InvalidFields(KycUpdateRequiredInvalidFields), + UserRequestedDelete, + PayyComplianceViolation, + Duplicate, + AgeRestriction, + DocumentForgery, + InvalidDocumentPhoto, + InconsistentDocuments, +} + +impl KycUpdateRequired { + pub fn merge(&self, other: &KycUpdateRequired) -> KycUpdateRequired { + match (self, other) { + (KycUpdateRequired::InvalidFields(a), KycUpdateRequired::InvalidFields(b)) => { + let mut merged_fields = a.fields.clone(); + for (field, reason) in &b.fields { + merged_fields.insert(*field, *reason); + } + KycUpdateRequired::InvalidFields(KycUpdateRequiredInvalidFields { + fields: merged_fields, + }) + } + _ => other.clone(), + } + } +} + +#[cfg(feature = "diesel")] +impl ToSql for KycUpdateRequired { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + out.write_all(&[1])?; + serde_json::to_writer(out, self)?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for KycUpdateRequired { + fn from_sql(bytes: PgValue) -> deserialize::Result { + let bytes = bytes.as_bytes(); + if bytes.is_empty() { + return Ok(KycUpdateRequired::default()); + } + let json_bytes = &bytes[1..]; + serde_json::from_slice(json_bytes).map_err(Into::into) + } +} diff --git a/pkg/kyc/src/lib.rs b/pkg/kyc/src/lib.rs new file mode 100644 index 0000000..d441308 --- /dev/null +++ b/pkg/kyc/src/lib.rs @@ -0,0 +1,13 @@ +mod documents; +pub mod error; +mod kyc; +mod kyc_update_required; +pub mod types; +mod utils; + +pub use documents::*; +pub use error::*; +pub use kyc::*; +pub use kyc_update_required::*; +pub use types::*; +pub use utils::*; diff --git a/pkg/kyc/src/types.rs b/pkg/kyc/src/types.rs new file mode 100644 index 0000000..1e45e01 --- /dev/null +++ b/pkg/kyc/src/types.rs @@ -0,0 +1,81 @@ +#[cfg(feature = "diesel")] +use std::io::Write; + +#[cfg(feature = "diesel")] +use diesel::{ + AsExpression, + deserialize::{self, FromSql, FromSqlRow}, + pg::Pg, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Text, +}; +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumString}; + +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +#[derive( + Debug, Serialize, Deserialize, Copy, Clone, Eq, Default, PartialEq, Display, EnumString, +)] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature="diesel",diesel(sql_type = diesel::sql_types::Text))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum KycStatus { + #[default] + NotStarted, + Pending, + Approved, + UpdateRequired, + Rejected, +} + +#[cfg(feature = "diesel")] +impl ToSql for KycStatus { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for KycStatus { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized kyc status".into()) + } +} + +#[derive( + Debug, Display, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, strum::EnumIter, +)] +#[strum(serialize_all = "lowercase")] +#[serde(rename_all = "lowercase")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum KycField { + Firstname, + Middlename, + Lastname, + Dob, + Occupation, + AddressStreet, + AddressCity, + AddressState, + AddressCountry, + AddressPostalCode, + Nationalities, + Documents, + Phone, + PhoneVerified, + Email, + EmailVerified, + NationalId, + CivilState, + Pep, + Fatca, + Uif, +} diff --git a/pkg/kyc/src/utils.rs b/pkg/kyc/src/utils.rs new file mode 100644 index 0000000..89f0c65 --- /dev/null +++ b/pkg/kyc/src/utils.rs @@ -0,0 +1,101 @@ +use super::{Error, Result}; + +pub fn abbreviate_state(state: &str) -> Result<&'static str> { + let normalized = state.trim().to_uppercase(); + + let abbreviation = match normalized.as_str() { + "ALABAMA" | "AL" => Some("AL"), + "ALASKA" | "AK" => Some("AK"), + "ARIZONA" | "AZ" => Some("AZ"), + "ARKANSAS" | "AR" => Some("AR"), + "CALIFORNIA" | "CA" => Some("CA"), + "COLORADO" | "CO" => Some("CO"), + "CONNECTICUT" | "CT" => Some("CT"), + "DELAWARE" | "DE" => Some("DE"), + "FLORIDA" | "FL" => Some("FL"), + "GEORGIA" | "GA" => Some("GA"), + "HAWAII" | "HI" => Some("HI"), + "IDAHO" | "ID" => Some("ID"), + "ILLINOIS" | "IL" => Some("IL"), + "INDIANA" | "IN" => Some("IN"), + "IOWA" | "IA" => Some("IA"), + "KANSAS" | "KS" => Some("KS"), + "KENTUCKY" | "KY" => Some("KY"), + "LOUISIANA" | "LA" => Some("LA"), + "MAINE" | "ME" => Some("ME"), + "MARYLAND" | "MD" => Some("MD"), + "MASSACHUSETTS" | "MA" => Some("MA"), + "MICHIGAN" | "MI" => Some("MI"), + "MINNESOTA" | "MN" => Some("MN"), + "MISSISSIPPI" | "MS" => Some("MS"), + "MISSOURI" | "MO" => Some("MO"), + "MONTANA" | "MT" => Some("MT"), + "NEBRASKA" | "NE" => Some("NE"), + "NEVADA" | "NV" => Some("NV"), + "NEW HAMPSHIRE" | "NH" => Some("NH"), + "NEW JERSEY" | "NJ" => Some("NJ"), + "NEW MEXICO" | "NM" => Some("NM"), + "NEW YORK" | "NY" => Some("NY"), + "NORTH CAROLINA" | "NC" => Some("NC"), + "NORTH DAKOTA" | "ND" => Some("ND"), + "OHIO" | "OH" => Some("OH"), + "OKLAHOMA" | "OK" => Some("OK"), + "OREGON" | "OR" => Some("OR"), + "PENNSYLVANIA" | "PA" => Some("PA"), + "RHODE ISLAND" | "RI" => Some("RI"), + "SOUTH CAROLINA" | "SC" => Some("SC"), + "SOUTH DAKOTA" | "SD" => Some("SD"), + "TENNESSEE" | "TN" => Some("TN"), + "TEXAS" | "TX" => Some("TX"), + "UTAH" | "UT" => Some("UT"), + "VERMONT" | "VT" => Some("VT"), + "VIRGINIA" | "VA" => Some("VA"), + "WASHINGTON" | "WA" => Some("WA"), + "WEST VIRGINIA" | "WV" => Some("WV"), + "WISCONSIN" | "WI" => Some("WI"), + "WYOMING" | "WY" => Some("WY"), + "DISTRICT OF COLUMBIA" | "DC" => Some("DC"), + _ => None, + }; + + if let Some(value) = abbreviation { + Ok(value) + } else { + Err(Error::InvalidState { state: normalized }) + } +} + +pub fn ok_field(field: &Option, field_name: &'static str) -> Result { + field + .clone() + .ok_or(Error::MissingKYCField(field_name.to_string())) +} + +#[cfg(test)] +mod test { + use super::{Error, abbreviate_state}; + + #[test] + fn test_abbreviate_state() { + let state = abbreviate_state("ALABAMA").unwrap(); + + assert_eq!(state, "AL") + } + + #[test] + fn test_abbreviate_state_invalid() { + let error = abbreviate_state("Atlantis").unwrap_err(); + + assert!(matches!( + error, + Error::InvalidState { state } if state == "ATLANTIS" + )); + + let trimmed = abbreviate_state(" narnia ").unwrap_err(); + + assert!(matches!( + trimmed, + Error::InvalidState { state } if state == "NARNIA" + )); + } +} diff --git a/pkg/kyc/tests/kyc_tests.rs b/pkg/kyc/tests/kyc_tests.rs new file mode 100644 index 0000000..1867928 --- /dev/null +++ b/pkg/kyc/tests/kyc_tests.rs @@ -0,0 +1,482 @@ +// lint-long-file-override allow-max-lines=500 +use base64::Engine; +use chrono::NaiveDate; +use currency::{Country, CountryList}; +use kyc::*; +use serde_json::json; +use std::collections::HashMap; + +fn make_id_doc_front_bytes() -> IDDocument { + IDDocument { + front: Some(IDDocumentField::Bytes(vec![1, 2, 3])), + back: None, + } +} + +fn make_id_doc_front_id_back_bytes() -> IDDocument { + IDDocument { + front: Some(IDDocumentField::Id { + id: "file;abc".to_string(), + bytes: vec![9, 9], + }), + back: Some(IDDocumentField::Bytes(vec![4, 5, 6])), + } +} + +fn make_id_doc_front_id_back_id() -> IDDocument { + IDDocument { + front: Some(IDDocumentField::Id { + id: "file;front".to_string(), + bytes: vec![7], + }), + back: Some(IDDocumentField::Id { + id: "file;back".to_string(), + bytes: vec![8], + }), + } +} + +fn base_kyc_all_fields() -> Kyc { + let mut docs_by_kind = HashMap::new(); + docs_by_kind.insert(IDKind::Passport, make_id_doc_front_bytes()); + let mut documents = HashMap::new(); + documents.insert(Country::US, docs_by_kind); + + Kyc { + firstname: Some("Alice".to_string()), + middlename: Some("B".to_string()), + lastname: Some("Carroll".to_string()), + dob: Some(NaiveDate::from_ymd_opt(1990, 1, 1).unwrap()), + occupation: Some("Engineer".to_string()), + addressstreet: Some("123 Main St".to_string()), + addresscity: Some("Metropolis".to_string()), + addressstate: Some("CA".to_string()), + addresscountry: Some(Country::US), + addresspostalcode: Some("94105".to_string()), + nationalities: Some(CountryList(vec![Country::US, Country::CA])), + documents: Some(documents), + phone: Some("+14155552671".to_string()), + phoneverified: Some(true), + email: Some("alice@example.com".to_string()), + emailverified: Some(true), + nationalid: Some("SSN123".to_string()), + pep: Some(false), + civilstate: Some("Single".to_string()), + fatca: Some(false), + uif: Some(false), + selfiefront: Some(IDDocumentField::Bytes(vec![42])), + selfieleft: Some(IDDocumentField::Id { + id: "file;left".to_string(), + bytes: vec![1], + }), + selfieright: Some(IDDocumentField::Id { + id: "file;right".to_string(), + bytes: vec![2], + }), + } +} + +#[test] +fn test_getters_success() { + let kyc = base_kyc_all_fields(); + assert_eq!(kyc.get_firstname().unwrap(), "Alice"); + assert_eq!(kyc.get_lastname().unwrap(), "Carroll"); + assert_eq!( + kyc.get_dob().unwrap(), + NaiveDate::from_ymd_opt(1990, 1, 1).unwrap() + ); + assert_eq!(kyc.get_occupation().unwrap(), "Engineer"); + assert_eq!(kyc.get_addressstreet().unwrap(), "123 Main St"); + assert_eq!(kyc.get_addresscity().unwrap(), "Metropolis"); + assert_eq!(kyc.get_addressstate().unwrap(), "CA"); + assert_eq!(kyc.get_addresscountry().unwrap(), Country::US); + assert_eq!(kyc.get_addresspostalcode().unwrap(), "94105"); + let nats = kyc.get_nationalities().unwrap(); + assert_eq!(nats.0, vec![Country::US, Country::CA]); + assert_eq!(kyc.get_nationality_one().unwrap(), Country::US); + let (cc, national) = kyc.get_phone_parts().unwrap(); + assert_eq!(cc, "1"); + assert_eq!(national, "4155552671"); + assert!(kyc.get_phone_verified().unwrap()); + assert_eq!(kyc.get_email().unwrap(), "alice@example.com"); + assert!(kyc.get_email_verified().unwrap()); + assert_eq!(kyc.get_nationalid().unwrap(), "SSN123"); + assert_eq!(kyc.get_civil_state().unwrap(), "Single"); + assert!(!kyc.get_fatca().unwrap()); + assert!(!kyc.get_uif().unwrap()); + assert!(!kyc.get_pep().unwrap()); +} + +#[test] +fn test_getters_errors() { + let mut kyc = Kyc { + nationalities: Some(CountryList(vec![])), + ..Default::default() + }; + // nationalities empty triggers specific error in get_nationalities + assert!(matches!( + kyc.get_nationalities(), + Err(Error::MissingKYCField(_)) + )); + // nationality one when option is None + kyc.nationalities = None; + assert!(matches!( + kyc.get_nationality_one(), + Err(Error::MissingKYCField(_)) + )); + // phone parts invalid + kyc.phone = Some("abc".to_string()); + assert!(matches!( + kyc.get_phone_parts(), + Err(Error::InvalidPhoneFormat) + )); + // documents None -> errors + assert!(matches!( + kyc.get_document_by_country(Country::US), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_documents_by_country_and_kind(Country::US, IDKind::Passport), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_documents_countries(), + Err(Error::MissingKYCField(_)) + )); +} + +#[test] +fn test_documents_queries() { + let mut kyc = base_kyc_all_fields(); + // add another kind to test preference order + if let Some(ref mut docs) = kyc.documents { + let entry = docs.entry(Country::US).or_insert_with(HashMap::new); + entry.insert(IDKind::DriversLicense, make_id_doc_front_id_back_id()); + } + // get by country returns some pair + let (kind, doc) = kyc.get_document_by_country(Country::US).unwrap(); + assert!(matches!(kind, IDKind::Passport | IDKind::DriversLicense)); + assert!(doc.front.is_some() || doc.back.is_some()); + // get by country and kind + let dl = kyc + .get_documents_by_country_and_kind(Country::US, IDKind::DriversLicense) + .unwrap(); + assert!(dl.front.is_some()); + // one of kinds prefers first present + let chosen = kyc + .get_one_of_document_kinds(Country::US, &[IDKind::ResidentCard, IDKind::Passport]) + .unwrap(); + assert!(chosen.front.is_some()); + // missing country/kind errors + assert!(matches!( + kyc.get_documents_by_country_and_kind(Country::CA, IDKind::Passport), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_one_of_document_kinds(Country::US, &[IDKind::ResidentCard, IDKind::StateId]), + Err(Error::MissingKYCField(_)) + )); + // countries list and first + let countries = kyc.get_documents_countries().unwrap(); + assert!(countries.contains(&Country::US)); + let one = kyc.get_documents_countries_one().unwrap(); + assert!(one == Country::US); + // empty map -> countries returns empty and countries_one errors + let kyc_empty = Kyc { + documents: Some(HashMap::new()), + ..Default::default() + }; + assert_eq!( + kyc_empty.get_documents_countries().unwrap(), + Vec::::new() + ); + assert!(matches!( + kyc_empty.get_documents_countries_one(), + Err(Error::MissingKYCField(_)) + )); +} + +#[test] +fn test_invalid_field_reason_name_too_long_serializes_as_expected() { + let value = serde_json::to_value(KycUpdateRequiredInvalidFieldsReason::NameTooLong).unwrap(); + assert_eq!(value, json!({ "reason": "NAME_TOO_LONG" })); +} + +#[test] +fn test_merge_prefers_new_and_sanitizes_new_documents() { + let base = base_kyc_all_fields(); + let mut new_docs_by_kind = HashMap::new(); + new_docs_by_kind.insert(IDKind::DriversLicense, make_id_doc_front_id_back_bytes()); + let mut new_documents = HashMap::new(); + new_documents.insert(Country::US, new_docs_by_kind); + // Also include a country with doc that should not be sanitized (both fields are Id) + let mut ca_docs = HashMap::new(); + ca_docs.insert(IDKind::StateId, make_id_doc_front_id_back_id()); + new_documents.insert(Country::CA, ca_docs); + let update = Kyc { + firstname: Some("Alicia".to_string()), + middlename: None, + lastname: Some("Carroll-Updated".to_string()), + dob: None, + occupation: Some("Senior Engineer".to_string()), + addressstreet: Some("456 Market St".to_string()), + addresscity: None, + addressstate: Some("California".to_string()), + addresscountry: None, + addresspostalcode: Some("94107".to_string()), + nationalities: None, + documents: Some(new_documents), + phone: Some("0014155552671".to_string()), + phoneverified: Some(false), + email: None, + emailverified: Some(false), + nationalid: None, + pep: Some(true), + civilstate: Some("Married".to_string()), + fatca: Some(true), + uif: Some(true), + selfiefront: Some(IDDocumentField::Id { + id: "file;selfie".to_string(), + bytes: vec![], + }), + selfieleft: None, + selfieright: None, + }; + + let merged = base.merge(&update); + // Fields prefer update when Some + assert_eq!(merged.firstname.as_deref(), Some("Alicia")); + assert_eq!(merged.lastname.as_deref(), Some("Carroll-Updated")); + assert_eq!(merged.occupation.as_deref(), Some("Senior Engineer")); + assert_eq!(merged.addressstreet.as_deref(), Some("456 Market St")); + assert_eq!(merged.addressstate.as_deref(), Some("California")); + assert_eq!(merged.addresspostalcode.as_deref(), Some("94107")); + assert_eq!(merged.phone.as_deref(), Some("0014155552671")); + assert_eq!(merged.phoneverified, Some(false)); + assert_eq!(merged.email.as_deref(), Some("alice@example.com")); // fell back to base + assert_eq!(merged.emailverified, Some(false)); + assert_eq!(merged.nationalid.as_deref(), Some("SSN123")); // fell back to base + assert_eq!(merged.pep, Some(true)); + assert_eq!(merged.civilstate.as_deref(), Some("Married")); + assert_eq!(merged.fatca, Some(true)); + assert_eq!(merged.uif, Some(true)); + // Fallbacks for None in update + assert_eq!(merged.middlename.as_deref(), Some("B")); + assert_eq!(merged.addresscity.as_deref(), Some("Metropolis")); + assert_eq!( + merged.dob, + Some(NaiveDate::from_ymd_opt(1990, 1, 1).unwrap()) + ); + assert_eq!(merged.addresscountry, Some(Country::US)); + assert_eq!( + merged.nationalities.as_ref().map(|n| &n.0[..]), + Some(&[Country::US, Country::CA][..]) + ); + // Selfies: prefer update when present; left/right fallback + match merged.selfiefront { + Some(IDDocumentField::Id { ref id, .. }) => assert_eq!(id, "file;selfie"), + _ => panic!("expected selfiefront from update"), + } + match merged.selfieleft { + Some(IDDocumentField::Id { ref id, .. }) => assert_eq!(id, "file;left"), + _ => panic!("expected selfieleft from base"), + } + match merged.selfieright { + Some(IDDocumentField::Id { ref id, .. }) => assert_eq!(id, "file;right"), + _ => panic!("expected selfieright from base"), + } + // Documents: base passport remains, new US DL is sanitized (no bytes retained), CA doc remains intact + let docs = merged.documents.unwrap(); + let us_docs = docs.get(&Country::US).unwrap(); + assert!(us_docs.contains_key(&IDKind::Passport)); + let dl = us_docs.get(&IDKind::DriversLicense).unwrap(); + assert!(dl.front.is_none() && dl.back.is_none()); + let ca_docs = docs.get(&Country::CA).unwrap(); + let ca_doc = ca_docs.get(&IDKind::StateId).unwrap(); + assert!(ca_doc.front.is_some() && ca_doc.back.is_some()); +} + +#[test] +fn test_merge_update_without_documents_keeps_base_documents() { + let base = base_kyc_all_fields(); + let update = Kyc { + documents: None, + ..Default::default() + }; + let merged = base.merge(&update); + let base_docs = base.documents.unwrap(); + let merged_docs = merged.documents.unwrap(); + assert_eq!( + merged_docs.keys().cloned().collect::>(), + base_docs.keys().cloned().collect::>() + ); + let us_docs_base = base_docs.get(&Country::US).unwrap(); + let us_docs_merged = merged_docs.get(&Country::US).unwrap(); + assert!(us_docs_merged.contains_key(&IDKind::Passport)); + assert_eq!(us_docs_merged.len(), us_docs_base.len()); +} + +#[test] +fn test_sanitize_for_storage_no_documents_is_noop() { + let kyc = Kyc { + firstname: Some("Alice".to_string()), + ..Default::default() + }; + let sanitized = kyc.sanitize_for_storage(); + assert_eq!(sanitized.firstname.as_deref(), Some("Alice")); + assert!(sanitized.documents.is_none()); +} + +#[test] +fn test_selfies_serde_behavior() { + let kyc = Kyc { + selfiefront: Some(IDDocumentField::Bytes(vec![1, 2])), + selfieleft: Some(IDDocumentField::Id { + id: "file;left".to_string(), + bytes: vec![9], + }), + selfieright: None, + ..Default::default() + }; + let value = serde_json::to_value(&kyc).unwrap(); + let obj = value.as_object().unwrap(); + // Bytes variant serializes as base64 string + let selfiefront_val = obj.get("selfiefront").unwrap(); + assert_eq!( + selfiefront_val.as_str().unwrap(), + base64::engine::general_purpose::STANDARD.encode([1u8, 2u8]) + ); + // Id variant serializes as the id string + let selfieleft_val = obj.get("selfieleft").unwrap(); + assert_eq!(selfieleft_val.as_str().unwrap(), "file;left"); + // None is skipped + assert!(!obj.contains_key("selfieright")); + // Roundtrip deserialize + let round: Kyc = serde_json::from_value(value).unwrap(); + match round.selfiefront.unwrap() { + IDDocumentField::Bytes(bytes) => assert_eq!(bytes, vec![1, 2]), + _ => panic!("expected selfiefront bytes after roundtrip"), + } + match round.selfieleft.unwrap() { + IDDocumentField::Id { id, .. } => assert_eq!(id, "file;left"), + _ => panic!("expected selfieleft id after roundtrip"), + } +} + +#[test] +fn test_sanitize_for_storage_removes_bytes_keeps_ids() { + let mut docs_by_kind = HashMap::new(); + docs_by_kind.insert( + IDKind::Passport, + IDDocument { + front: Some(IDDocumentField::Bytes(vec![1])), + back: Some(IDDocumentField::Id { + id: "file;keep".to_string(), + bytes: vec![2], + }), + }, + ); + docs_by_kind.insert( + IDKind::StateId, + IDDocument { + front: Some(IDDocumentField::Id { + id: "file;front".to_string(), + bytes: vec![3], + }), + back: Some(IDDocumentField::Bytes(vec![4])), + }, + ); + let mut documents = HashMap::new(); + documents.insert(Country::US, docs_by_kind); + let kyc = Kyc { + documents: Some(documents), + ..Default::default() + }; + let sanitized = kyc.sanitize_for_storage(); + let docs = sanitized.documents.unwrap(); + let us_docs = docs.get(&Country::US).unwrap(); + let passport = us_docs.get(&IDKind::Passport).unwrap(); + assert!(passport.front.is_none()); + match passport.back { + Some(IDDocumentField::Id { ref id, .. }) => assert_eq!(id, "file;keep"), + _ => panic!("expected back id to be kept"), + } + let state_id = us_docs.get(&IDKind::StateId).unwrap(); + match state_id.front { + Some(IDDocumentField::Id { ref id, .. }) => assert_eq!(id, "file;front"), + _ => panic!("expected front id to be kept"), + } + assert!(state_id.back.is_none()); +} + +#[test] +fn test_phone_parts_handles_leading_zeros_and_no_plus() { + let kyc = Kyc { + phone: Some("0014155552671".to_string()), + ..Default::default() + }; + let (cc, national) = kyc.get_phone_parts().unwrap(); + assert_eq!(cc, "1"); + assert_eq!(national, "4155552671"); +} + +#[test] +fn test_all_other_getters_missing_field_errors() { + let kyc = Kyc::default(); + assert!(matches!( + kyc.get_firstname(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!(kyc.get_lastname(), Err(Error::MissingKYCField(_)))); + assert!(matches!(kyc.get_dob(), Err(Error::MissingKYCField(_)))); + assert!(matches!( + kyc.get_occupation(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_addressstreet(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_addresscity(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_addressstate(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_addresscountry(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_addresspostalcode(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!(kyc.get_phone(), Err(Error::MissingKYCField(_)))); + assert!(matches!( + kyc.get_phone_verified(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!(kyc.get_email(), Err(Error::MissingKYCField(_)))); + assert!(matches!( + kyc.get_email_verified(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_nationalid(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!( + kyc.get_civil_state(), + Err(Error::MissingKYCField(_)) + )); + assert!(matches!(kyc.get_fatca(), Err(Error::MissingKYCField(_)))); + assert!(matches!(kyc.get_uif(), Err(Error::MissingKYCField(_)))); + assert!(matches!(kyc.get_pep(), Err(Error::MissingKYCField(_)))); + // get_phone_parts should also error when phone is missing + assert!(matches!( + kyc.get_phone_parts(), + Err(Error::MissingKYCField(_)) + )); +} diff --git a/pkg/minimal-poseidon/Cargo.toml b/pkg/minimal-poseidon/Cargo.toml new file mode 100644 index 0000000..2a3edbf --- /dev/null +++ b/pkg/minimal-poseidon/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "minimal-poseidon" +version = "0.1.0" +edition = "2024" + +[dependencies] +halo2curves = { workspace = true, features = ["derive_serde"] } +ff = { workspace = true } +lazy_static = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/minimal-poseidon/README.md b/pkg/minimal-poseidon/README.md new file mode 100644 index 0000000..fe81d2a --- /dev/null +++ b/pkg/minimal-poseidon/README.md @@ -0,0 +1,16 @@ +# Minimal Poseidon + +> **⚠️ DEPRECATION WARNING**: This package is used primarily for migration from the old Halo2 proof system and can be deprecated once the migration completes. + +Lightweight Poseidon hash implementation with BN256 constants. This hash was used as part of our Halo2 ZK proof system, which implemented a unique variant for the Poseidon hash fn. + +## Overview + +This package provides a minimal, lightweight implementation of the Poseidon hash function optimized for the BN256 curve. + +## Features + +- Lightweight Poseidon implementation +- BN256 curve constants +- Core hash logic +- Poseidon specification diff --git a/pkg/minimal-poseidon/src/bn256_constants.rs b/pkg/minimal-poseidon/src/bn256_constants.rs new file mode 100644 index 0000000..b865e57 --- /dev/null +++ b/pkg/minimal-poseidon/src/bn256_constants.rs @@ -0,0 +1,301 @@ +// Parameters generated from: +// +// https://github.com/scroll-tech/poseidon-circuit/blob/e3841d0828e577b80c9cd84aa71f79adc96756fc/src/poseidon/primitives.rs#L61 +// +// or equivalently: +// +// https://extgit.iaik.tugraz.at/krypto/hadeshash/-/blob/b5434fd2b2785926dd1dd386efbef167da57c064/code/poseidonperm_x5_254_3.sage +// + +// lint-long-file-override allow-max-lines=400 +use halo2curves::{ + bn256::Fr as Fp, + group::ff::{Field, PrimeField}, +}; +use lazy_static::lazy_static; + +use crate::{P128Pow5T3Constants, core_logic::Mds}; + +lazy_static! { + pub static ref ROUND_CONSTANTS: [[Fp; 3]; 65] = { + let c_str = round_constants(); + let ret: Vec<[Fp; 3]> = (0..65) + .map(|i| [0, 1, 2].map(|j| Fp::from_str_vartime(c_str[i * 3 + j]).unwrap())) + .collect(); + + ret.try_into().unwrap() + }; + pub static ref MDS: [[Fp; 3]; 3] = { + let m_str = mds(); + + [0, 1, 2].map(|i| [0, 1, 2].map(|j| Fp::from_str_vartime(m_str[i][j]).unwrap())) + }; + pub static ref MDS_INV: [[Fp; 3]; 3] = { + let mds = *MDS; + + let det_items = |idx: usize| { + (0..3) + .map(|i| mds[(idx + i) % 3][i]) + .reduce(|acc, fr| acc * fr) + .unwrap() + - (0..3) + .map(|i| mds[(idx + 3 - i) % 3][i]) + .reduce(|acc, fr| acc * fr) + .unwrap() + }; + + let det = (0..3) + .map(det_items) + .reduce(|acc, fr| acc + fr) + .unwrap() + .invert() + .unwrap(); + + let ci = |i: usize, j: usize| { + mds[(i + 1) % 3][(j + 1) % 3] * mds[(i + 2) % 3][(j + 2) % 3] + - mds[(i + 1) % 3][(j + 2) % 3] * mds[(i + 2) % 3][(j + 1) % 3] + }; + + [ + [ci(0, 0) * det, ci(1, 0) * det, ci(2, 0) * det], + [ci(0, 1) * det, ci(1, 1) * det, ci(2, 1) * det], + [ci(0, 2) * det, ci(1, 2) * det, ci(2, 2) * det], + ] + }; +} + +fn round_constants() -> Vec<&'static str> { + vec![ + "6745197990210204598374042828761989596302876299545964402857411729872131034734", + "426281677759936592021316809065178817848084678679510574715894138690250139748", + "4014188762916583598888942667424965430287497824629657219807941460227372577781", + "21328925083209914769191926116470334003273872494252651254811226518870906634704", + "19525217621804205041825319248827370085205895195618474548469181956339322154226", + "1402547928439424661186498190603111095981986484908825517071607587179649375482", + "18320863691943690091503704046057443633081959680694199244583676572077409194605", + "17709820605501892134371743295301255810542620360751268064484461849423726103416", + "15970119011175710804034336110979394557344217932580634635707518729185096681010", + "9818625905832534778628436765635714771300533913823445439412501514317783880744", + "6235167673500273618358172865171408902079591030551453531218774338170981503478", + "12575685815457815780909564540589853169226710664203625668068862277336357031324", + "7381963244739421891665696965695211188125933529845348367882277882370864309593", + "14214782117460029685087903971105962785460806586237411939435376993762368956406", + "13382692957873425730537487257409819532582973556007555550953772737680185788165", + "2203881792421502412097043743980777162333765109810562102330023625047867378813", + "2916799379096386059941979057020673941967403377243798575982519638429287573544", + "4341714036313630002881786446132415875360643644216758539961571543427269293497", + "2340590164268886572738332390117165591168622939528604352383836760095320678310", + "5222233506067684445011741833180208249846813936652202885155168684515636170204", + "7963328565263035669460582454204125526132426321764384712313576357234706922961", + "1394121618978136816716817287892553782094854454366447781505650417569234586889", + "20251767894547536128245030306810919879363877532719496013176573522769484883301", + "141695147295366035069589946372747683366709960920818122842195372849143476473", + "15919677773886738212551540894030218900525794162097204800782557234189587084981", + "2616624285043480955310772600732442182691089413248613225596630696960447611520", + "4740655602437503003625476760295930165628853341577914460831224100471301981787", + "19201590924623513311141753466125212569043677014481753075022686585593991810752", + "12116486795864712158501385780203500958268173542001460756053597574143933465696", + "8481222075475748672358154589993007112877289817336436741649507712124418867136", + "5181207870440376967537721398591028675236553829547043817076573656878024336014", + "1576305643467537308202593927724028147293702201461402534316403041563704263752", + "2555752030748925341265856133642532487884589978209403118872788051695546807407", + "18840924862590752659304250828416640310422888056457367520753407434927494649454", + "14593453114436356872569019099482380600010961031449147888385564231161572479535", + "20826991704411880672028799007667199259549645488279985687894219600551387252871", + "9159011389589751902277217485643457078922343616356921337993871236707687166408", + "5605846325255071220412087261490782205304876403716989785167758520729893194481", + "1148784255964739709393622058074925404369763692117037208398835319441214134867", + "20945896491956417459309978192328611958993484165135279604807006821513499894540", + "229312996389666104692157009189660162223783309871515463857687414818018508814", + "21184391300727296923488439338697060571987191396173649012875080956309403646776", + "21853424399738097885762888601689700621597911601971608617330124755808946442758", + "12776298811140222029408960445729157525018582422120161448937390282915768616621", + "7556638921712565671493830639474905252516049452878366640087648712509680826732", + "19042212131548710076857572964084011858520620377048961573689299061399932349935", + "12871359356889933725034558434803294882039795794349132643274844130484166679697", + "3313271555224009399457959221795880655466141771467177849716499564904543504032", + "15080780006046305940429266707255063673138269243146576829483541808378091931472", + "21300668809180077730195066774916591829321297484129506780637389508430384679582", + "20480395468049323836126447690964858840772494303543046543729776750771407319822", + "10034492246236387932307199011778078115444704411143703430822959320969550003883", + "19584962776865783763416938001503258436032522042569001300175637333222729790225", + "20155726818439649091211122042505326538030503429443841583127932647435472711802", + "13313554736139368941495919643765094930693458639277286513236143495391474916777", + "14606609055603079181113315307204024259649959674048912770003912154260692161833", + "5563317320536360357019805881367133322562055054443943486481491020841431450882", + "10535419877021741166931390532371024954143141727751832596925779759801808223060", + "12025323200952647772051708095132262602424463606315130667435888188024371598063", + "2906495834492762782415522961458044920178260121151056598901462871824771097354", + "19131970618309428864375891649512521128588657129006772405220584460225143887876", + "8896386073442729425831367074375892129571226824899294414632856215758860965449", + "7748212315898910829925509969895667732958278025359537472413515465768989125274", + "422974903473869924285294686399247660575841594104291551918957116218939002865", + "6398251826151191010634405259351528880538837895394722626439957170031528482771", + "18978082967849498068717608127246258727629855559346799025101476822814831852169", + "19150742296744826773994641927898928595714611370355487304294875666791554590142", + "12896891575271590393203506752066427004153880610948642373943666975402674068209", + "9546270356416926575977159110423162512143435321217584886616658624852959369669", + "2159256158967802519099187112783460402410585039950369442740637803310736339200", + "8911064487437952102278704807713767893452045491852457406400757953039127292263", + "745203718271072817124702263707270113474103371777640557877379939715613501668", + "19313999467876585876087962875809436559985619524211587308123441305315685710594", + "13254105126478921521101199309550428567648131468564858698707378705299481802310", + "1842081783060652110083740461228060164332599013503094142244413855982571335453", + "9630707582521938235113899367442877106957117302212260601089037887382200262598", + "5066637850921463603001689152130702510691309665971848984551789224031532240292", + "4222575506342961001052323857466868245596202202118237252286417317084494678062", + "2919565560395273474653456663643621058897649501626354982855207508310069954086", + "6828792324689892364977311977277548750189770865063718432946006481461319858171", + "2245543836264212411244499299744964607957732316191654500700776604707526766099", + "19602444885919216544870739287153239096493385668743835386720501338355679311704", + "8239538512351936341605373169291864076963368674911219628966947078336484944367", + "15053013456316196458870481299866861595818749671771356646798978105863499965417", + "7173615418515925804810790963571435428017065786053377450925733428353831789901", + "8239211677777829016346247446855147819062679124993100113886842075069166957042", + "15330855478780269194281285878526984092296288422420009233557393252489043181621", + "10014883178425964324400942419088813432808659204697623248101862794157084619079", + "14014440630268834826103915635277409547403899966106389064645466381170788813506", + "3580284508947993352601712737893796312152276667249521401778537893620670305946", + "2559754020964039399020874042785294258009596917335212876725104742182177996988", + "14898657953331064524657146359621913343900897440154577299309964768812788279359", + "2094037260225570753385567402013028115218264157081728958845544426054943497065", + "18051086536715129874440142649831636862614413764019212222493256578581754875930", + "21680659279808524976004872421382255670910633119979692059689680820959727969489", + "13950668739013333802529221454188102772764935019081479852094403697438884885176", + "9703845704528288130475698300068368924202959408694460208903346143576482802458", + "12064310080154762977097567536495874701200266107682637369509532768346427148165", + "16970760937630487134309762150133050221647250855182482010338640862111040175223", + "9790997389841527686594908620011261506072956332346095631818178387333642218087", + "16314772317774781682315680698375079500119933343877658265473913556101283387175", + "82044870826814863425230825851780076663078706675282523830353041968943811739", + "21696416499108261787701615667919260888528264686979598953977501999747075085778", + "327771579314982889069767086599893095509690747425186236545716715062234528958", + "4606746338794869835346679399457321301521448510419912225455957310754258695442", + "64499140292086295251085369317820027058256893294990556166497635237544139149", + "10455028514626281809317431738697215395754892241565963900707779591201786416553", + "10421411526406559029881814534127830959833724368842872558146891658647152404488", + "18848084335930758908929996602136129516563864917028006334090900573158639401697", + "13844582069112758573505569452838731733665881813247931940917033313637916625267", + "13488838454403536473492810836925746129625931018303120152441617863324950564617", + "15742141787658576773362201234656079648895020623294182888893044264221895077688", + "6756884846734501741323584200608866954194124526254904154220230538416015199997", + "7860026400080412708388991924996537435137213401947704476935669541906823414404", + "7871040688194276447149361970364037034145427598711982334898258974993423182255", + "20758972836260983284101736686981180669442461217558708348216227791678564394086", + "21723241881201839361054939276225528403036494340235482225557493179929400043949", + "19428469330241922173653014973246050805326196062205770999171646238586440011910", + "7969200143746252148180468265998213908636952110398450526104077406933642389443", + "10950417916542216146808986264475443189195561844878185034086477052349738113024", + "18149233917533571579549129116652755182249709970669448788972210488823719849654", + "3729796741814967444466779622727009306670204996071028061336690366291718751463", + "5172504399789702452458550583224415301790558941194337190035441508103183388987", + "6686473297578275808822003704722284278892335730899287687997898239052863590235", + "19426913098142877404613120616123695099909113097119499573837343516470853338513", + "5120337081764243150760446206763109494847464512045895114970710519826059751800", + "5055737465570446530938379301905385631528718027725177854815404507095601126720", + "14235578612970484492268974539959119923625505766550088220840324058885914976980", + "653592517890187950103239281291172267359747551606210609563961204572842639923", + "5507360526092411682502736946959369987101940689834541471605074817375175870579", + "7864202866011437199771472205361912625244234597659755013419363091895334445453", + "21294659996736305811805196472076519801392453844037698272479731199885739891648", + "13767183507040326119772335839274719411331242166231012705169069242737428254651", + "810181532076738148308457416289197585577119693706380535394811298325092337781", + "14232321930654703053193240133923161848171310212544136614525040874814292190478", + "16796904728299128263054838299534612533844352058851230375569421467352578781209", + "16256310366973209550759123431979563367001604350120872788217761535379268327259", + "19791658638819031543640174069980007021961272701723090073894685478509001321817", + "7046232469803978873754056165670086532908888046886780200907660308846356865119", + "16001732848952745747636754668380555263330934909183814105655567108556497219752", + "9737276123084413897604802930591512772593843242069849260396983774140735981896", + "11410895086919039954381533622971292904413121053792570364694836768885182251535", + "19098362474249267294548762387533474746422711206129028436248281690105483603471", + "11013788190750472643548844759298623898218957233582881400726340624764440203586", + "2206958256327295151076063922661677909471794458896944583339625762978736821035", + "7171889270225471948987523104033632910444398328090760036609063776968837717795", + "2510237900514902891152324520472140114359583819338640775472608119384714834368", + "8825275525296082671615660088137472022727508654813239986303576303490504107418", + "1481125575303576470988538039195271612778457110700618040436600537924912146613", + "16268684562967416784133317570130804847322980788316762518215429249893668424280", + "4681491452239189664806745521067158092729838954919425311759965958272644506354", + "3131438137839074317765338377823608627360421824842227925080193892542578675835", + "7930402370812046914611776451748034256998580373012248216998696754202474945793", + "8973151117361309058790078507956716669068786070949641445408234962176963060145", + "10223139291409280771165469989652431067575076252562753663259473331031932716923", + "2232089286698717316374057160056566551249777684520809735680538268209217819725", + "16930089744400890347392540468934821520000065594669279286854302439710657571308", + "21739597952486540111798430281275997558482064077591840966152905690279247146674", + "7508315029150148468008716674010060103310093296969466203204862163743615534994", + "11418894863682894988747041469969889669847284797234703818032750410328384432224", + "10895338268862022698088163806301557188640023613155321294365781481663489837917", + "18644184384117747990653304688839904082421784959872380449968500304556054962449", + "7414443845282852488299349772251184564170443662081877445177167932875038836497", + "5391299369598751507276083947272874512197023231529277107201098701900193273851", + "10329906873896253554985208009869159014028187242848161393978194008068001342262", + "4711719500416619550464783480084256452493890461073147512131129596065578741786", + "11943219201565014805519989716407790139241726526989183705078747065985453201504", + "4298705349772984837150885571712355513879480272326239023123910904259614053334", + "9999044003322463509208400801275356671266978396985433172455084837770460579627", + "4908416131442887573991189028182614782884545304889259793974797565686968097291", + "11963412684806827200577486696316210731159599844307091475104710684559519773777", + "20129916000261129180023520480843084814481184380399868943565043864970719708502", + "12884788430473747619080473633364244616344003003135883061507342348586143092592", + "20286808211545908191036106582330883564479538831989852602050135926112143921015", + "16282045180030846845043407450751207026423331632332114205316676731302016331498", + "4332932669439410887701725251009073017227450696965904037736403407953448682093", + "11105712698773407689561953778861118250080830258196150686012791790342360778288", + "21853934471586954540926699232107176721894655187276984175226220218852955976831", + "9807888223112768841912392164376763820266226276821186661925633831143729724792", + "13411808896854134882869416756427789378942943805153730705795307450368858622668", + "17906847067500673080192335286161014930416613104209700445088168479205894040011", + "14554387648466176616800733804942239711702169161888492380425023505790070369632", + "4264116751358967409634966292436919795665643055548061693088119780787376143967", + "2401104597023440271473786738539405349187326308074330930748109868990675625380", + "12251645483867233248963286274239998200789646392205783056343767189806123148785", + "15331181254680049984374210433775713530849624954688899814297733641575188164316", + "13108834590369183125338853868477110922788848506677889928217413952560148766472", + "6843160824078397950058285123048455551935389277899379615286104657075620692224", + "10151103286206275742153883485231683504642432930275602063393479013696349676320", + "7074320081443088514060123546121507442501369977071685257650287261047855962224", + "11413928794424774638606755585641504971720734248726394295158115188173278890938", + "7312756097842145322667451519888915975561412209738441762091369106604423801080", + "7181677521425162567568557182629489303281861794357882492140051324529826589361", + "15123155547166304758320442783720138372005699143801247333941013553002921430306", + "13409242754315411433193860530743374419854094495153957441316635981078068351329", + ] +} + +fn mds() -> Vec> { + vec![ + vec![ + "7511745149465107256748700652201246547602992235352608707588321460060273774987", + "10370080108974718697676803824769673834027675643658433702224577712625900127200", + "19705173408229649878903981084052839426532978878058043055305024233888854471533", + ], + vec![ + "18732019378264290557468133440468564866454307626475683536618613112504878618481", + "20870176810702568768751421378473869562658540583882454726129544628203806653987", + "7266061498423634438633389053804536045105766754026813321943009179476902321146", + ], + vec![ + "9131299761947733513298312097611845208338517739621853568979632113419485819303", + "10595341252162738537912664445405114076324478519622938027420701542910180337937", + "11597556804922396090267472882856054602429588299176362916247939723151043581408", + ], + ] +} + +impl P128Pow5T3Constants for Fp { + fn partial_rounds() -> usize { + 57 + } + + fn round_constants() -> Vec<[Fp; 3]> { + ROUND_CONSTANTS.to_vec() + } + fn mds() -> Mds { + *MDS + } + fn mds_inv() -> Mds { + *MDS_INV + } +} diff --git a/pkg/minimal-poseidon/src/core_logic.rs b/pkg/minimal-poseidon/src/core_logic.rs new file mode 100644 index 0000000..41d5bd4 --- /dev/null +++ b/pkg/minimal-poseidon/src/core_logic.rs @@ -0,0 +1,353 @@ +// lint-long-file-override allow-max-lines=400 +use std::convert::TryInto; +use std::fmt; +use std::iter; +use std::marker::PhantomData; + +use ff::FromUniformBytes; // Used by Spec trait bound + +// --- Paste relevant content from poseidon-base/src/primitives.rs --- +// (State, SpongeRate, Mds types; Spec, CachedSpec traits; permute fn; +// SpongeMode, Absorbing, Squeezing; Sponge struct and impls; +// Domain trait, ConstantLength; Hash struct and impls) + +/// The type used to hold permutation state. +pub type State = [F; T]; +/// The type used to hold sponge rate. +pub type SpongeRate = [Option; RATE]; +/// The type used to hold the MDS matrix and its inverse. +pub type Mds = [[F; T]; T]; + +/// A specification for a Poseidon permutation. +pub trait Spec + Ord, const T: usize, const RATE: usize>: + Copy + fmt::Debug +{ + fn full_rounds() -> usize; + fn partial_rounds() -> usize; + fn sbox(val: F) -> F; + fn secure_mds() -> usize; // May not be used if constants() is overridden + fn constants() -> (Vec<[F; T]>, Mds, Mds); + // Default impl of constants() using grain might be removed if not needed, + // as P128Pow5T3 overrides it. For now, keep it for completeness or remove if it pulls `grain`. + // If kept, `grain.rs` and `mds.rs` (generators) would be needed. + // For this minimal version, we assume P128Pow5T3's override is sufficient. +} + +pub trait CachedSpec + Ord, const T: usize, const RATE: usize>: + Spec +{ + fn cached_round_constants() -> &'static [[F; T]]; + fn cached_mds() -> &'static Mds; + fn cached_mds_inv() -> &'static Mds; +} + +pub fn permute< + F: FromUniformBytes<64> + Ord, + S: Spec, + const T: usize, + const RATE: usize, +>( + state: &mut State, + mds: &Mds, + round_constants: &[[F; T]], +) { + let r_f = S::full_rounds() / 2; + let r_p = S::partial_rounds(); + + let apply_mds = |state: &mut State| { + let mut new_state = [F::ZERO; T]; + #[allow(clippy::needless_range_loop)] + for i in 0..T { + for j in 0..T { + new_state[i] += mds[i][j] * state[j]; + } + } + *state = new_state; + }; + + let full_round = |state: &mut State, rcs: &[F; T]| { + for (word, rc) in state.iter_mut().zip(rcs.iter()) { + *word = S::sbox(*word + rc); + } + apply_mds(state); + }; + + let part_round = |state: &mut State, rcs: &[F; T]| { + for (word, rc) in state.iter_mut().zip(rcs.iter()) { + *word += rc; + } + state[0] = S::sbox(state[0]); + apply_mds(state); + }; + + iter::empty() + .chain(std::iter::repeat_n( + &full_round as &dyn Fn(&mut State, &[F; T]), + r_f, + )) + .chain(std::iter::repeat_n( + &part_round as &dyn Fn(&mut State, &[F; T]), + r_p, + )) + .chain(std::iter::repeat_n( + &full_round as &dyn Fn(&mut State, &[F; T]), + r_f, + )) + .zip(round_constants.iter()) + .fold(state, |state, (round, rcs)| { + round(state, rcs); + state + }); +} + +fn poseidon_sponge_internal< + // Renamed to avoid conflict if original poseidon_sponge is kept + F: FromUniformBytes<64> + Ord, + S: CachedSpec, // Changed Spec to CachedSpec + const T: usize, + const RATE: usize, +>( + state: &mut State, + input: Option<(&Absorbing, usize)>, + // mds_matrix and round_constants are now fetched from CachedSpec +) -> Squeezing { + if let Some((Absorbing(input_data), layout_offset)) = input { + assert!(layout_offset <= T - RATE); + for (word, value) in state.iter_mut().skip(layout_offset).zip(input_data.iter()) { + *word += value.expect("poseidon_sponge is called with a padded input"); + } + } + + permute::(state, S::cached_mds(), S::cached_round_constants()); + + let mut output = [None; RATE]; + for (word, value) in output.iter_mut().zip(state.iter()) { + *word = Some(*value); + } + Squeezing(output) +} + +mod private_sponge { + // Renamed to avoid conflict + pub trait SealedSpongeMode {} + impl SealedSpongeMode for super::Absorbing {} + impl SealedSpongeMode for super::Squeezing {} +} + +pub trait SpongeMode: private_sponge::SealedSpongeMode + Clone {} + +#[derive(Debug, Copy, Clone)] +pub struct Absorbing(pub SpongeRate); +#[derive(Debug, Copy, Clone)] +pub struct Squeezing(pub SpongeRate); + +impl SpongeMode for Absorbing {} +impl SpongeMode for Squeezing {} + +impl Absorbing { + pub fn init_with(val: F) -> Self { + Self( + iter::once(Some(val)) + .chain((1..RATE).map(|_| None)) + .collect::>() + .try_into() + .unwrap(), + ) + } +} + +#[derive(Clone)] +pub(crate) struct Sponge< + F: FromUniformBytes<64> + Ord, + S: CachedSpec, + M: SpongeMode, + const T: usize, + const RATE: usize, +> { + mode: M, + state: State, + layout: usize, + _marker: PhantomData, +} + +impl + Ord, S: CachedSpec, const T: usize, const RATE: usize> + Sponge, T, RATE> +{ + pub(crate) fn new(initial_capacity_element: F, layout: usize) -> Self { + let mode = Absorbing([None; RATE]); + let mut state = [F::ZERO; T]; + state[(RATE + layout) % T] = initial_capacity_element; + + Sponge { + mode, + state, + layout, + _marker: PhantomData, + } + } + + pub(crate) fn absorb(&mut self, value: F) { + for entry in self.mode.0.iter_mut() { + if entry.is_none() { + *entry = Some(value); + return; + } + } + let _ = poseidon_sponge_internal::( + &mut self.state, + Some((&self.mode, self.layout)), + ); + self.mode = Absorbing::init_with(value); + } + + pub(crate) fn finish_absorbing(mut self) -> Sponge, T, RATE> { + let mode = poseidon_sponge_internal::( + &mut self.state, + Some((&self.mode, self.layout)), + ); + Sponge { + mode, + state: self.state, + layout: self.layout, + _marker: PhantomData, + } + } +} + +impl + Ord, S: CachedSpec, const T: usize, const RATE: usize> + Sponge, T, RATE> +{ + pub(crate) fn squeeze(&mut self) -> F { + loop { + for entry in self.mode.0.iter_mut() { + if let Some(e) = entry.take() { + return e; + } + } + self.mode = poseidon_sponge_internal::(&mut self.state, None); + } + } +} + +pub trait Domain + Ord, const RATE: usize> { + type Padding: IntoIterator; + fn name() -> String; + fn initial_capacity_element() -> F; + fn padding(input_len: usize) -> Self::Padding; + fn layout(_width: usize) -> usize { + 0 + } +} + +#[derive(Clone, Copy, Debug)] +pub struct ConstantLength; + +impl + Ord, const RATE: usize, const L: usize> Domain + for ConstantLength +{ + type Padding = iter::RepeatN; + fn name() -> String { + format!("ConstantLength<{L}>") + } + fn initial_capacity_element() -> F { + F::from_u128((L as u128) << 64) + } + fn padding(input_len: usize) -> Self::Padding { + assert_eq!(input_len, L); + let k = L.div_ceil(RATE); + std::iter::repeat_n(F::ZERO, k * RATE - L) + } +} + +#[derive(Clone)] +pub struct Hash< + F: FromUniformBytes<64> + Ord, + S: CachedSpec, + D: Domain, + const T: usize, + const RATE: usize, +> { + sponge: Sponge, T, RATE>, + _domain: PhantomData, +} + +impl< + F: FromUniformBytes<64> + Ord, + S: CachedSpec, + D: Domain, + const T: usize, + const RATE: usize, +> fmt::Debug for Hash +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Hash") + .field("width", &T) + .field("rate", &RATE) + .field("R_F", &S::full_rounds()) + .field("R_P", &S::partial_rounds()) + .field("domain", &D::name()) + .finish() + } +} + +impl< + F: FromUniformBytes<64> + Ord, + S: CachedSpec, + D: Domain, + const T: usize, + const RATE: usize, +> Hash +{ + pub fn init() -> Self { + Hash { + sponge: Sponge::new(D::initial_capacity_element(), D::layout(T)), + _domain: PhantomData, + } + } +} + +impl< + F: FromUniformBytes<64> + Ord, + S: CachedSpec, + const T: usize, + const RATE: usize, + const L: usize, +> Hash, T, RATE> +{ + pub fn hash(mut self, message: [F; L]) -> F { + for value in message + .into_iter() + .chain( as Domain>::padding(L)) + { + self.sponge.absorb(value); + } + self.sponge.finish_absorbing().squeeze() + } +} + +#[cfg(test)] +mod tests { + use crate::{Bn256Fr as Fp, P128Pow5T3}; + + use super::{ConstantLength, Hash, Spec, permute}; + type OrchardNullifier = P128Pow5T3; + + #[test] + fn orchard_spec_equivalence() { + let message = [Fp::from(6), Fp::from(42)]; + + let (round_constants, mds, _) = OrchardNullifier::constants(); + + let hasher = Hash::<_, OrchardNullifier, ConstantLength<2>, 3, 2>::init(); + let result = hasher.hash(message); + + // The result should be equivalent to just directly applying the permutation and + // taking the first state element as the output. + let mut two_to_sixty_five = Fp::from(1 << 63); + two_to_sixty_five = two_to_sixty_five.double(); + two_to_sixty_five = two_to_sixty_five.double(); + let mut state = [message[0], message[1], two_to_sixty_five]; + permute::<_, OrchardNullifier, 3, 2>(&mut state, &mds, &round_constants); + assert_eq!(state[0], result); + } +} diff --git a/pkg/minimal-poseidon/src/lib.rs b/pkg/minimal-poseidon/src/lib.rs new file mode 100644 index 0000000..3a91af3 --- /dev/null +++ b/pkg/minimal-poseidon/src/lib.rs @@ -0,0 +1,8 @@ +pub use halo2curves::bn256::Fr as Bn256Fr; // Or your preferred alias for the base field + +pub use crate::core_logic::{ConstantLength, Hash}; +pub use crate::poseidon_spec::{P128Pow5T3, P128Pow5T3Constants}; + +mod bn256_constants; +mod core_logic; +mod poseidon_spec; diff --git a/pkg/minimal-poseidon/src/poseidon_spec.rs b/pkg/minimal-poseidon/src/poseidon_spec.rs new file mode 100644 index 0000000..f2bbeb7 --- /dev/null +++ b/pkg/minimal-poseidon/src/poseidon_spec.rs @@ -0,0 +1,63 @@ +use ff::FromUniformBytes; +use halo2curves::bn256::Fr as Bn256Fr; +use std::marker::PhantomData; + +use crate::bn256_constants::{MDS, MDS_INV, ROUND_CONSTANTS}; +use crate::core_logic::{CachedSpec, Mds, Spec}; // Actual constants + +// --- Paste from poseidon-base/src/primitives/p128pow5t3.rs --- +/// The trait required for fields can handle a pow5 sbox, 3 field, 2 rate permutation +pub trait P128Pow5T3Constants: FromUniformBytes<64> + Ord { + fn partial_rounds() -> usize { + 56 // Default, overridden by Bn256Fr impl + } + fn round_constants() -> Vec<[Self; 3]>; + fn mds() -> Mds; + fn mds_inv() -> Mds; +} + +/// Poseidon-128 using the $x^5$ S-box, with a width of 3 field elements, and the +/// standard number of rounds for 128-bit security "with margin". +#[derive(Debug, Copy, Clone)] +pub struct P128Pow5T3 { + _marker: PhantomData, +} + +impl Spec for P128Pow5T3 { + fn full_rounds() -> usize { + 8 + } + + fn partial_rounds() -> usize { + Fp::partial_rounds() + } + + fn sbox(val: Fp) -> Fp { + val.pow_vartime([5]) + } + + fn secure_mds() -> usize { + // This is not used because constants() is overridden + unimplemented!( + "secure_mds is not needed when constants are hardcoded via P128Pow5T3Constants" + ) + } + + fn constants() -> (Vec<[Fp; 3]>, Mds, Mds) { + (Fp::round_constants(), Fp::mds(), Fp::mds_inv()) + } +} +// --- End of paste --- + +// CachedSpec impl for P128Pow5T3 +impl CachedSpec for P128Pow5T3 { + fn cached_round_constants() -> &'static [[Bn256Fr; 3]] { + &*ROUND_CONSTANTS + } + fn cached_mds() -> &'static Mds { + &MDS + } + fn cached_mds_inv() -> &'static Mds { + &MDS_INV + } +} diff --git a/pkg/network/Cargo.toml b/pkg/network/Cargo.toml new file mode 100644 index 0000000..82b53fe --- /dev/null +++ b/pkg/network/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "network" +version = "0.1.0" +edition = "2024" + +[features] +diesel = ["dep:diesel"] +ts-rs = ["dep:ts-rs"] + +[dependencies] +diesel = { workspace = true, optional = true } +serde = { workspace = true } +serde_json = { workspace = true } +strum_macros = { workspace = true } +strum = { workspace = true } +thiserror = { workspace = true } +uuid = { workspace = true, features = ["serde"] } +veil = { workspace = true } +workspace-hack.workspace = true + +[dependencies.ts-rs] +workspace = true +optional = true + +[package.metadata.cargo-machete] +ignored = ["strum"] diff --git a/pkg/network/src/error.rs b/pkg/network/src/error.rs new file mode 100644 index 0000000..dac437f --- /dev/null +++ b/pkg/network/src/error.rs @@ -0,0 +1,9 @@ +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Missing required network identifier field: {0}")] + MissingRequiredNetworkIdentifierField(String), +} diff --git a/pkg/network/src/lib.rs b/pkg/network/src/lib.rs new file mode 100644 index 0000000..e9169f9 --- /dev/null +++ b/pkg/network/src/lib.rs @@ -0,0 +1,229 @@ +// lint-long-file-override allow-max-lines=300 +#[cfg(feature = "diesel")] +use std::io::Write; + +use strum_macros::{Display, EnumString}; +use uuid::Uuid; + +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + pg::{Pg, PgValue}, + serialize::{self, IsNull, Output, ToSql}, + sql_types::{Jsonb, Text}, +}; +use serde::{Deserialize, Deserializer, Serialize}; +use veil::Redact; + +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +pub mod error; + +pub use error::{Error, Result}; + +#[derive( + Debug, Serialize, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Display, EnumString, +)] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE", ascii_case_insensitive)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature="diesel",diesel(sql_type = diesel::sql_types::Text))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum Network { + Payy, + Polygon, + Ethereum, + Spei, + Pix, + Coelsa, + Card, + ExternalCard, + UsBank, + Plaid, +} + +impl<'de> Deserialize<'de> for Network { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + // Try case-insensitive parsing using strum + s.parse().map_err(serde::de::Error::custom) + } +} + +#[cfg(feature = "diesel")] +impl ToSql for Network { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Network { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized network".into()) + } +} + +/// Provides normalized options to identify an account +/// on a network. A network may support multiple ways +/// to identify an account, and each way may require multiple +/// fields. +#[derive(Default, Serialize, Deserialize, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Redact)] +#[cfg_attr(feature = "diesel", derive(AsExpression, deserialize::FromSqlRow))] +#[cfg_attr(feature="diesel",diesel(sql_type = diesel::sql_types::Jsonb))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct NetworkIdentifier { + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub accountnumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub routingnumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub cardnumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub cardexpiration: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + #[redact] + pub cardcvv: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + #[redact] + pub pin: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub phonenumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub email: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional, rename = "address"))] + pub evmaddress: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub methodid: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub reference: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub accountid: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub qrcode: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub plaid_public_token: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub plaid_account_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub plaid_institution_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub bank_name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub plaid_mask: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub plaid_account_name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub external_bank_guid: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PlaidDetails { + pub plaid_public_token: String, + pub plaid_account_id: String, + pub plaid_institution_id: String, + pub plaid_mask: String, + pub plaid_account_name: String, + pub bank_name: String, +} + +#[cfg(feature = "diesel")] +impl ToSql for NetworkIdentifier { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + out.write_all(&[1])?; + serde_json::to_writer(out, self)?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for NetworkIdentifier { + fn from_sql(bytes: PgValue) -> deserialize::Result { + let bytes = bytes.as_bytes(); + if bytes.is_empty() { + return Ok(NetworkIdentifier::default()); + } + let json_bytes = &bytes[1..]; + serde_json::from_slice(json_bytes).map_err(Into::into) + } +} + +impl NetworkIdentifier { + pub fn from_account(account_number: String) -> Self { + Self { + accountnumber: Some(account_number), + ..Default::default() + } + } + + pub fn from_account_and_reference(account_number: String, reference: Option) -> Self { + Self { + accountnumber: Some(account_number), + reference, + ..Default::default() + } + } + + pub fn from_method(method_id: Uuid) -> Self { + Self { + methodid: Some(method_id), + ..Default::default() + } + } + + pub fn get_account_number(&self) -> Result { + ok_field(&self.accountnumber, "accountnumber") + } + + pub fn get_method_id(&self) -> Result { + ok_field(&self.methodid, "methodid") + } + + pub fn get_plaid_details(&self) -> Result { + Ok(PlaidDetails { + plaid_public_token: ok_field(&self.plaid_public_token, "plaid_public_token")?, + plaid_mask: ok_field(&self.plaid_mask, "plaid_mask")?, + plaid_account_name: ok_field(&self.plaid_account_name, "plaid_account_name")?, + plaid_institution_id: ok_field(&self.plaid_institution_id, "plaid_institution_id")?, + plaid_account_id: ok_field(&self.plaid_account_id, "plaid_account_id")?, + bank_name: ok_field(&self.bank_name, "bank_name")?, + }) + } +} + +pub fn ok_field(field: &Option, field_name: &'static str) -> Result { + field + .clone() + .ok_or(Error::MissingRequiredNetworkIdentifierField( + field_name.to_string(), + )) +} diff --git a/pkg/node-client-http/Cargo.toml b/pkg/node-client-http/Cargo.toml new file mode 100644 index 0000000..5174c99 --- /dev/null +++ b/pkg/node-client-http/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "node-client-http" +version = "0.1.0" +edition = "2024" + +[dependencies] +client-http = { workspace = true } +http-interface = { workspace = true } +element = { workspace = true } +node-interface = { workspace = true } +primitives = { workspace = true } +zk-primitives = { workspace = true } + +async-trait = { workspace = true } +serde = { workspace = true } +reqwest = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } +unimock = { workspace = true } diff --git a/pkg/node-client-http/README.md b/pkg/node-client-http/README.md new file mode 100644 index 0000000..72a77f1 --- /dev/null +++ b/pkg/node-client-http/README.md @@ -0,0 +1,16 @@ +# Node Client HTTP + +HTTP client specifically for blockchain node communication. + +## Overview + +This package provides an HTTP client tailored for communicating with blockchain nodes in the network. + +## Features + +- Node-specific HTTP operations +- Element retrieval +- Transaction submission +- Height queries +- Error handling + diff --git a/pkg/node-client-http/src/block_tree.rs b/pkg/node-client-http/src/block_tree.rs new file mode 100644 index 0000000..b3fb2bc --- /dev/null +++ b/pkg/node-client-http/src/block_tree.rs @@ -0,0 +1,268 @@ +// lint-long-file-override allow-max-lines=300 +use crate::{Error, NodeClientHttp, Result}; +use http_interface::HttpMetadata; +use node_interface::{BlockTreeDiff, BlockTreeResponse, BlockTreeSnapshot}; +use primitives::block_height::BlockHeight; +use reqwest::Method; + +const BLOCKS_PATH: &str = "/blocks"; + +impl NodeClientHttp { + /// Fetch the block tree snapshot for the provided height. + pub async fn block_tree(&self, height: BlockHeight) -> Result { + let path = block_tree_path(height); + let metadata = HttpMetadata { + method: Method::GET, + path: path.clone(), + }; + self.http_client + .get(&path) + .exec() + .await? + .to_value() + .await + .and_then(|response: BlockTreeResponse| { + response.elements.map_or_else( + || { + Err(Error::ServerError( + "missing block tree snapshot elements".to_owned(), + metadata, + )) + }, + |elements| { + Ok(BlockTreeSnapshot { + height: response.height, + root_hash: response.root_hash, + elements, + }) + }, + ) + }) + } + + /// Fetch the block tree diff from `diff_from` to `height`. + pub async fn block_tree_diff( + &self, + height: BlockHeight, + diff_from: BlockHeight, + ) -> Result { + let path = block_tree_path(height); + let metadata = HttpMetadata { + method: Method::GET, + path: path.clone(), + }; + self.http_client + .get(&path) + .query(vec![("diff_from".to_owned(), diff_from.0.to_string())]) + .exec() + .await? + .to_value() + .await + .and_then(|response: BlockTreeResponse| { + response.diff.map_or_else( + || { + Err(Error::ServerError( + "missing block tree diff response".to_owned(), + metadata, + )) + }, + |diff| { + Ok(BlockTreeDiff { + height: response.height, + root_hash: response.root_hash, + diff, + }) + }, + ) + }) + } +} + +fn block_tree_path(height: BlockHeight) -> String { + format!("{BLOCKS_PATH}/{}/tree", height.0) +} + +#[cfg(test)] +mod tests { + use super::*; + use element::Element; + use http_interface::{ + ClientResponse, HttpClient, HttpClientMock, HttpMetadata, + builder::{HttpRequestBuilder, HttpRequestExecutor}, + error::HttpRequestExecError, + }; + use node_interface::BlockTreeDiffChanges; + use reqwest::Method; + use std::{ + collections::HashMap, + sync::{Arc, Mutex}, + }; + use unimock::{MockFn, Unimock, matching}; + + #[derive(Default)] + struct RequestCapture { + query: Mutex>>, + } + + impl RequestCapture { + fn record_query(&self, query: Vec<(String, String)>) { + *self.query.lock().unwrap() = Some(query); + } + + fn query_map(&self) -> HashMap { + self.query + .lock() + .unwrap() + .clone() + .unwrap_or_default() + .into_iter() + .collect() + } + } + + struct TestRequestExecutor { + state: Arc, + response: Option>, + } + + impl TestRequestExecutor { + fn new( + state: Arc, + response: std::result::Result, + ) -> Self { + Self { + state, + response: Some(response), + } + } + } + + #[async_trait::async_trait] + impl HttpRequestExecutor for TestRequestExecutor { + fn headers(&mut self, _headers: reqwest::header::HeaderMap) {} + + fn query(&mut self, query: Vec<(String, String)>) { + self.state.record_query(query); + } + + fn auth(&mut self) {} + + async fn exec( + mut self: Box, + ) -> std::result::Result { + self.response.take().expect("response already taken") + } + } + + fn builder_with_response( + capture: Arc, + response: std::result::Result, + ) -> HttpRequestBuilder { + HttpRequestBuilder::new(Box::new(TestRequestExecutor::new(capture, response))) + } + + fn leak_get_answer( + f: F, + ) -> &'static ( + dyn for<'ctx, 'path> Fn(&'ctx Unimock, &'path str) -> HttpRequestBuilder + + Send + + Sync + ) + where + F: for<'ctx, 'path> Fn(&'ctx Unimock, &'path str) -> HttpRequestBuilder + + Send + + Sync + + 'static, + { + Box::leak(Box::new(f)) + } + + #[tokio::test] + async fn block_tree_fetches_snapshot() { + let height = BlockHeight(7); + let path = block_tree_path(height); + let expected_elements = vec![Element::new(2)]; + + let http: Arc = Arc::new(Unimock::new( + HttpClientMock::get + .next_call(matching!(_)) + .answers(leak_get_answer({ + let path = path.clone(); + let expected_elements = expected_elements.clone(); + move |_, actual_path| { + assert_eq!(actual_path, path); + let response_body = BlockTreeResponse { + height, + root_hash: Element::ONE, + elements: Some(expected_elements.clone()), + diff: None, + }; + builder_with_response( + Arc::new(RequestCapture::default()), + Ok(ClientResponse::from_serializable( + &response_body, + HttpMetadata { + method: Method::GET, + path: path.clone(), + }, + )), + ) + } + })), + )); + + let client = NodeClientHttp::with_dyn_http_client(http); + let response = client.block_tree(height).await.expect("request succeeds"); + assert_eq!(response.height, height); + assert_eq!(response.root_hash, Element::ONE); + assert_eq!(response.elements, expected_elements); + } + + #[tokio::test] + async fn block_tree_diff_sets_query() { + let capture = Arc::new(RequestCapture::default()); + let height = BlockHeight(10); + let diff_from = BlockHeight(5); + let path = block_tree_path(height); + let http: Arc = Arc::new(Unimock::new( + HttpClientMock::get + .next_call(matching!(_)) + .answers(leak_get_answer({ + let capture = Arc::clone(&capture); + let path = path.clone(); + move |_, actual_path| { + assert_eq!(actual_path, path); + builder_with_response( + Arc::clone(&capture), + Ok(ClientResponse::from_serializable( + &BlockTreeResponse { + height, + root_hash: Element::new(3), + elements: None, + diff: Some(BlockTreeDiffChanges { + from_height: diff_from, + additions: vec![Element::ONE], + removals: vec![], + }), + }, + HttpMetadata { + method: Method::GET, + path: path.clone(), + }, + )), + ) + } + })), + )); + + let client = NodeClientHttp::with_dyn_http_client(http); + let diff = client + .block_tree_diff(height, diff_from) + .await + .expect("request succeeds"); + assert_eq!(diff.diff.from_height, diff_from); + + let params = capture.query_map(); + assert_eq!(params.get("diff_from"), Some(&diff_from.0.to_string())); + } +} diff --git a/pkg/node-client-http/src/blocks.rs b/pkg/node-client-http/src/blocks.rs new file mode 100644 index 0000000..0994653 --- /dev/null +++ b/pkg/node-client-http/src/blocks.rs @@ -0,0 +1,230 @@ +// lint-long-file-override allow-max-lines=300 +use crate::{Error, NodeClientHttp, Result}; +use client_http::serde_to_query_params; +use http_interface::HttpMetadata; +use node_interface::{ListBlocksOrder, ListBlocksResponse}; +use primitives::{ + block_height::BlockHeight, + pagination::{CursorChoice, CursorChoiceAfter}, +}; +use reqwest::Method; +use serde::Serialize; + +const BLOCKS_PATH: &str = "/blocks"; +const MAX_BLOCKS_LIMIT: usize = 256; + +#[derive(Serialize)] +struct BlocksQuery { + limit: usize, + #[serde(skip_serializing_if = "Option::is_none")] + cursor: Option, + order: ListBlocksOrder, + skip_empty: bool, +} + +impl NodeClientHttp { + /// Fetch blocks starting at `start_height`, optionally skipping empty blocks. + pub async fn blocks( + &self, + start_height: BlockHeight, + limit: usize, + skip_empty: bool, + ) -> Result { + let cursor = CursorChoice::After(CursorChoiceAfter::AfterInclusive(start_height)) + .opaque() + .serialize() + .map_err(|err| Error::SerdeJson(err.to_string(), blocks_metadata()))?; + + let query = BlocksQuery { + limit: limit.min(MAX_BLOCKS_LIMIT), + cursor: Some(cursor), + order: ListBlocksOrder::LowestToHighest, + skip_empty, + }; + + self.http_client + .get(BLOCKS_PATH) + .query(serde_to_query_params(&query)) + .exec() + .await? + .to_value() + .await + } +} + +fn blocks_metadata() -> HttpMetadata { + HttpMetadata { + method: Method::GET, + path: BLOCKS_PATH.to_owned(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use http_interface::{ + ClientResponse, HttpClient, HttpClientMock, + builder::{HttpRequestBuilder, HttpRequestExecutor}, + error::HttpRequestExecError, + }; + use primitives::pagination::{Cursor, CursorChoice, CursorChoiceAfter}; + use std::{ + collections::HashMap, + sync::{Arc, Mutex}, + }; + use unimock::{MockFn, Unimock, matching}; + + #[derive(Default)] + struct RequestCapture { + query: Mutex>>, + } + + impl RequestCapture { + fn record_query(&self, query: Vec<(String, String)>) { + *self.query.lock().unwrap() = Some(query); + } + + fn query_map(&self) -> HashMap { + self.query + .lock() + .unwrap() + .clone() + .unwrap_or_default() + .into_iter() + .collect() + } + } + + struct TestRequestExecutor { + state: Arc, + response: Option>, + } + + impl TestRequestExecutor { + fn new( + state: Arc, + response: std::result::Result, + ) -> Self { + Self { + state, + response: Some(response), + } + } + } + + #[async_trait::async_trait] + impl HttpRequestExecutor for TestRequestExecutor { + fn headers(&mut self, _headers: reqwest::header::HeaderMap) {} + + fn query(&mut self, query: Vec<(String, String)>) { + self.state.record_query(query); + } + + fn auth(&mut self) {} + + async fn exec( + mut self: Box, + ) -> std::result::Result { + self.response.take().expect("response already taken") + } + } + + fn builder_with_response( + capture: Arc, + response: std::result::Result, + ) -> HttpRequestBuilder { + HttpRequestBuilder::new(Box::new(TestRequestExecutor::new(capture, response))) + } + + fn leak_get_answer( + f: F, + ) -> &'static ( + dyn for<'ctx, 'path> Fn(&'ctx Unimock, &'path str) -> HttpRequestBuilder + + Send + + Sync + ) + where + F: for<'ctx, 'path> Fn(&'ctx Unimock, &'path str) -> HttpRequestBuilder + + Send + + Sync + + 'static, + { + Box::leak(Box::new(f)) + } + + #[tokio::test] + async fn blocks_sets_cursor_and_skip_flag() { + let capture = Arc::new(RequestCapture::default()); + let http: Arc = Arc::new(Unimock::new( + HttpClientMock::get + .next_call(matching!("/blocks")) + .answers(leak_get_answer({ + let capture = Arc::clone(&capture); + move |_, _path| { + builder_with_response( + Arc::clone(&capture), + Err(HttpRequestExecError::ServerError( + "server error".to_owned(), + blocks_metadata(), + )), + ) + } + })), + )); + let client = NodeClientHttp::with_dyn_http_client(http); + + let _ = client.blocks(BlockHeight(42), 5, true).await; + + let params = capture.query_map(); + assert_eq!(params.get("limit"), Some(&"5".to_owned())); + assert_eq!(params.get("skip_empty"), Some(&"true".to_owned())); + assert_eq!(params.get("order"), Some(&"LowestToHighest".to_owned())); + + let expected_cursor = + CursorChoice::After(CursorChoiceAfter::AfterInclusive(BlockHeight(42))) + .opaque() + .serialize() + .expect("cursor serialization should succeed"); + assert_eq!(params.get("cursor"), Some(&expected_cursor)); + } + + #[tokio::test] + async fn blocks_clamps_limit_and_returns_response() { + let capture = Arc::new(RequestCapture::default()); + let response_body = ListBlocksResponse { + blocks: Vec::new(), + cursor: Cursor::::default().into_opaque(), + }; + + let http: Arc = Arc::new(Unimock::new( + HttpClientMock::get + .next_call(matching!("/blocks")) + .answers(leak_get_answer({ + let capture = Arc::clone(&capture); + let response_body = response_body.clone(); + move |_, _path| { + builder_with_response( + Arc::clone(&capture), + Ok(ClientResponse::from_serializable( + &response_body, + blocks_metadata(), + )), + ) + } + })), + )); + + let client = NodeClientHttp::with_dyn_http_client(http); + let result = client + .blocks(BlockHeight(7), 300, false) + .await + .expect("request should succeed"); + assert!(result.blocks.is_empty()); + assert!(result.cursor.after.is_none()); + assert!(result.cursor.before.is_none()); + + let params = capture.query_map(); + assert_eq!(params.get("limit"), Some(&MAX_BLOCKS_LIMIT.to_string())); + assert_eq!(params.get("skip_empty"), Some(&"false".to_owned())); + } +} diff --git a/pkg/node-client-http/src/elements.rs b/pkg/node-client-http/src/elements.rs new file mode 100644 index 0000000..b7fbeae --- /dev/null +++ b/pkg/node-client-http/src/elements.rs @@ -0,0 +1,27 @@ +use crate::{NodeClientHttp, error::Result}; +use client_http::HttpBody; +use element::Element; +use node_interface::{ElementsResponse, ListElementsBody}; + +impl NodeClientHttp { + /// Returns a list of elements that are in the tree, and when they were + /// inserted into the tree. If an element is not in the tree, it will be skipped + /// from the returned elements list + pub async fn elements( + &self, + elements: &[Element], + include_spent: bool, + ) -> Result { + let body = ListElementsBody { + elements: elements.to_vec(), + include_spent, + }; + + self.http_client + .post("/elements", Some(HttpBody::json(body))) + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/node-client-http/src/error.rs b/pkg/node-client-http/src/error.rs new file mode 100644 index 0000000..700506c --- /dev/null +++ b/pkg/node-client-http/src/error.rs @@ -0,0 +1,5 @@ +/// Node client error +pub type Error = client_http::Error; + +/// Node client result +pub type Result = std::result::Result; diff --git a/pkg/node-client-http/src/height.rs b/pkg/node-client-http/src/height.rs new file mode 100644 index 0000000..179a845 --- /dev/null +++ b/pkg/node-client-http/src/height.rs @@ -0,0 +1,14 @@ +use crate::{NodeClientHttp, error::Result}; +use node_interface::HeightResponse; + +impl NodeClientHttp { + /// Returns the current height of the chain and the root hash + pub async fn height(&self) -> Result { + self.http_client + .get("/height") + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/node-client-http/src/lib.rs b/pkg/node-client-http/src/lib.rs new file mode 100644 index 0000000..965d1fa --- /dev/null +++ b/pkg/node-client-http/src/lib.rs @@ -0,0 +1,140 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::match_bool)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::doc_markdown)] +#![deny(missing_docs)] + +//! HTTPS client for Payy Network + +use std::{error::Error as StdError, sync::Arc}; + +use async_trait::async_trait; +use client_http::{ClientHttp, NoAuth}; +use element::Element; +use http_interface::HttpClient; +use node_interface::{ + BlockTreeDiff, BlockTreeSnapshot, ElementsResponse, Error as NodeInterfaceError, + HeightResponse, ListBlocksResponse, MerklePathResponse, NodeClient, + Result as NodeInterfaceResult, TransactionResponse, +}; +use primitives::block_height::BlockHeight; +use zk_primitives::UtxoProof; + +pub use reqwest::{Url, header::HeaderMap}; + +mod block_tree; +mod blocks; +mod elements; +mod error; +mod height; +mod merkle; +mod transaction; + +pub use error::{Error, Result}; + +/// Node client for interfacting with the Payy Network validator +/// over HTTPS +#[derive(Clone)] +pub struct NodeClientHttp { + pub(crate) http_client: Arc, +} + +impl NodeClientHttp { + /// Create a new client with a base URL using the default HTTP implementation. + #[must_use] + pub fn new(base_url: Url) -> Self { + Self::with_http_client(ClientHttp::new(base_url, HeaderMap::default(), NoAuth)) + } + + /// Construct a node client with a pre-configured HTTP implementation. + #[must_use] + pub fn with_http_client(http_client: C) -> Self + where + C: HttpClient + 'static, + { + Self::with_dyn_http_client(Arc::new(http_client)) + } + + /// Construct a node client backed by a trait-object HTTP client. + #[must_use] + pub fn with_dyn_http_client(http_client: Arc) -> Self { + Self { http_client } + } +} + +#[async_trait] +impl NodeClient for NodeClientHttp { + async fn height(&self) -> NodeInterfaceResult { + NodeClientHttp::height(self).await.map_err(map_client_error) + } + + async fn elements( + &self, + elements: &[Element], + include_spent: bool, + ) -> NodeInterfaceResult { + NodeClientHttp::elements(self, elements, include_spent) + .await + .map_err(map_client_error) + } + + async fn transaction(&self, proof: UtxoProof) -> NodeInterfaceResult { + NodeClientHttp::transaction(self, proof) + .await + .map_err(map_client_error) + } + + async fn list_transactions( + &self, + params: node_interface::ListTxnsParams, + ) -> NodeInterfaceResult { + NodeClientHttp::list_transactions(self, params) + .await + .map_err(map_client_error) + } + + async fn merkle_paths( + &self, + commitments: &[Element], + ) -> NodeInterfaceResult { + NodeClientHttp::merkle_paths(self, commitments) + .await + .map_err(map_client_error) + } + + async fn blocks( + &self, + start_height: BlockHeight, + limit: usize, + skip_empty: bool, + ) -> NodeInterfaceResult { + NodeClientHttp::blocks(self, start_height, limit, skip_empty) + .await + .map_err(map_client_error) + } + + async fn block_tree(&self, height: BlockHeight) -> NodeInterfaceResult { + NodeClientHttp::block_tree(self, height) + .await + .map_err(map_client_error) + } + + async fn block_tree_diff( + &self, + height: BlockHeight, + diff_from: BlockHeight, + ) -> NodeInterfaceResult { + NodeClientHttp::block_tree_diff(self, height, diff_from) + .await + .map_err(map_client_error) + } +} + +fn map_client_error(err: Error) -> NodeInterfaceError { + match err { + client_http::Error::Rpc(rpc_error) => rpc_error.into(), + other => NodeInterfaceError::from(Box::new(other) as Box), + } +} diff --git a/pkg/node-client-http/src/merkle.rs b/pkg/node-client-http/src/merkle.rs new file mode 100644 index 0000000..8699356 --- /dev/null +++ b/pkg/node-client-http/src/merkle.rs @@ -0,0 +1,33 @@ +use crate::{NodeClientHttp, error::Result}; +use client_http::serde_to_query_params; +use element::Element; +use node_interface::MerklePathResponse; +use serde::Serialize; + +const MERKLE_PATH: &str = "/merkle"; + +#[derive(Serialize)] +struct MerkleQuery { + commitments: String, +} + +impl NodeClientHttp { + /// Fetch Merkle inclusion paths for the provided commitments. + pub async fn merkle_paths(&self, commitments: &[Element]) -> Result { + let query = MerkleQuery { + commitments: commitments + .iter() + .map(|element| element.to_hex()) + .collect::>() + .join(","), + }; + + self.http_client + .get(MERKLE_PATH) + .query(serde_to_query_params(&query)) + .exec() + .await? + .to_value() + .await + } +} diff --git a/pkg/node-client-http/src/transaction.rs b/pkg/node-client-http/src/transaction.rs new file mode 100644 index 0000000..9ad37dc --- /dev/null +++ b/pkg/node-client-http/src/transaction.rs @@ -0,0 +1,65 @@ +use crate::{Error, NodeClientHttp, error::Result}; +use client_http::{HttpBody, serde_to_query_params}; +use http_interface::HttpMetadata; +use node_interface::{ListTxnsParams, ListTxnsResponse, TransactionRequest, TransactionResponse}; +use reqwest::Method; +use serde::Serialize; +use zk_primitives::UtxoProof; + +const TRANSACTION_PATH: &str = "/transaction"; +const TRANSACTIONS_PATH: &str = "/transactions"; + +#[derive(Serialize)] +struct ListTxnsQuery { + limit: usize, + #[serde(skip_serializing_if = "Option::is_none")] + cursor: Option, + order: node_interface::ListTxnsOrder, + poll: bool, +} + +impl NodeClientHttp { + /// Sends a transaction to Payy Network validator + pub async fn transaction(&self, proof: UtxoProof) -> Result { + self.http_client + .post( + TRANSACTION_PATH, + Some(HttpBody::json(TransactionRequest { proof })), + ) + .exec() + .await? + .to_value() + .await + } + + /// List transactions from Payy Network validator. + pub async fn list_transactions(&self, params: ListTxnsParams) -> Result { + let cursor = params + .cursor + .map(|cursor| cursor.serialize()) + .transpose() + .map_err(|err| Error::SerdeJson(err.to_string(), transactions_metadata()))?; + + let query = ListTxnsQuery { + limit: params.limit.min(100), + cursor, + order: params.order, + poll: params.poll, + }; + + self.http_client + .get(TRANSACTIONS_PATH) + .query(serde_to_query_params(&query)) + .exec() + .await? + .to_value() + .await + } +} + +fn transactions_metadata() -> HttpMetadata { + HttpMetadata { + method: Method::GET, + path: TRANSACTIONS_PATH.to_owned(), + } +} diff --git a/pkg/node-interface/Cargo.toml b/pkg/node-interface/Cargo.toml new file mode 100644 index 0000000..64dbf70 --- /dev/null +++ b/pkg/node-interface/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "node-interface" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } +rpc = { workspace = true } +rpc-error-convert = { workspace = true } +primitives = { workspace = true } +zk-primitives = { workspace = true } + +async-trait = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +unimock = { workspace = true } +workspace-hack.workspace = true + +[dependencies.ts-rs] +workspace = true +optional = true + +[features] +ts-rs = ["dep:ts-rs", "element/ts-rs", "primitives/ts-rs", "zk-primitives/ts-rs"] + +[package.metadata.cargo-machete] +ignored = ["serde_json"] diff --git a/pkg/node-interface/README.md b/pkg/node-interface/README.md new file mode 100644 index 0000000..02955c9 --- /dev/null +++ b/pkg/node-interface/README.md @@ -0,0 +1,16 @@ +# Node Interface + +Interface definitions for node communication protocols. + +## Overview + +This package defines the interface contracts for communication between nodes in the network. + +## Features + +- Node communication interfaces +- Element handling +- Transaction protocols +- Height management +- Error definitions + diff --git a/pkg/node-interface/src/blocks.rs b/pkg/node-interface/src/blocks.rs new file mode 100644 index 0000000..098e266 --- /dev/null +++ b/pkg/node-interface/src/blocks.rs @@ -0,0 +1,133 @@ +use element::Element; +use primitives::{ + block_height::BlockHeight, hash::CryptoHash, pagination::OpaqueCursor, sig::Signature, +}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use zk_primitives::UtxoProof; + +/// Ordering options for listing blocks. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum ListBlocksOrder { + /// Return blocks from the lowest height to the highest. + LowestToHighest, + /// Return blocks from the highest height to the lowest. + HighestToLowest, +} + +impl ListBlocksOrder { + /// Convenience helper for the lowest to highest order. + #[must_use] + pub const fn lowest_to_highest() -> Self { + Self::LowestToHighest + } + + /// Convenience helper for the highest to lowest order. + #[must_use] + pub const fn highest_to_lowest() -> Self { + Self::HighestToLowest + } +} + +/// Response structure for listing blocks. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct ListBlocksResponse { + /// Blocks returned by the node. + pub blocks: Vec, + /// Pagination cursor for fetching additional blocks. + #[cfg_attr( + feature = "ts-rs", + ts(type = "import(\"./OpaqueClientCursor\").OpaqueClientCursor") + )] + pub cursor: OpaqueCursor, +} + +/// Block bundle with metadata returned by the node. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct BlockWithInfo { + /// Block payload. + pub block: Block, + /// Hash of the block. + #[cfg_attr(feature = "ts-rs", ts(type = "string"))] + pub hash: CryptoHash, + /// Timestamp provided by the node. + pub time: u64, +} + +/// High-level block representation exposed over HTTP. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct Block { + /// Content of the block. + pub content: BlockContent, + /// Validator signature for the block. + #[cfg_attr(feature = "ts-rs", ts(type = "string"))] + pub signature: Signature, +} + +/// Block content containing the header and state. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct BlockContent { + /// Block header metadata. + pub header: BlockHeader, + /// Block state describing the transactions. + pub state: BlockState, +} + +/// Header information for a block. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct BlockHeader { + /// Height of the block. + pub height: BlockHeight, + /// Hash of the previous block. + #[cfg_attr(feature = "ts-rs", ts(type = "string"))] + pub last_block_hash: CryptoHash, + /// Epoch identifier. + pub epoch_id: u64, + /// Hash of the last finalized block. + #[cfg_attr(feature = "ts-rs", ts(type = "string"))] + pub last_final_block_hash: CryptoHash, + /// Approvals collected for the block. + #[cfg_attr(feature = "ts-rs", ts(type = "string[]"))] + pub approvals: Vec, +} + +/// State payload for the block. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct BlockState { + /// Merkle root hash after executing this block. + pub root_hash: Element, + /// Transactions included in the block. + pub txns: Vec, +} + +/// Transaction data with additional metadata. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct TxnWithInfo { + /// Transaction proof. + pub proof: UtxoProof, + /// Hash of the transaction. + pub hash: Element, + /// Index of the transaction inside the block. + pub index_in_block: u64, + /// Height of the block that included the transaction. + pub block_height: BlockHeight, + /// Timestamp assigned to the transaction. + pub time: u64, +} diff --git a/pkg/node-interface/src/client.rs b/pkg/node-interface/src/client.rs new file mode 100644 index 0000000..9ee7a28 --- /dev/null +++ b/pkg/node-interface/src/client.rs @@ -0,0 +1,50 @@ +#![allow(clippy::ignored_unit_patterns)] + +use async_trait::async_trait; +use element::Element; +use primitives::block_height::BlockHeight; +use zk_primitives::UtxoProof; + +use crate::{ + BlockTreeDiff, BlockTreeSnapshot, ElementsResponse, HeightResponse, ListBlocksResponse, + ListTxnsParams, ListTxnsResponse, MerklePathResponse, Result, TransactionResponse, +}; + +/// Node client interface that supports interacting with a validator over RPC. +#[unimock::unimock(api = NodeClientMock)] +#[async_trait] +pub trait NodeClient: Send + Sync { + /// Fetch the latest chain height and root hash. + async fn height(&self) -> Result; + + /// Lookup elements within the commitment tree. + async fn elements(&self, elements: &[Element], include_spent: bool) + -> Result; + + /// Submit a transaction to the validator. + async fn transaction(&self, proof: UtxoProof) -> Result; + + /// List transactions from the validator. + async fn list_transactions(&self, params: ListTxnsParams) -> Result; + + /// Fetch Merkle inclusion paths for the provided commitments. + async fn merkle_paths(&self, commitments: &[Element]) -> Result; + + /// Fetch blocks from a starting height. + async fn blocks( + &self, + start_height: BlockHeight, + limit: usize, + skip_empty: bool, + ) -> Result; + + /// Fetch a snapshot of the block tree for the provided height. + async fn block_tree(&self, height: BlockHeight) -> Result; + + /// Fetch a diff for the block tree from `diff_from` to the provided height. + async fn block_tree_diff( + &self, + height: BlockHeight, + diff_from: BlockHeight, + ) -> Result; +} diff --git a/pkg/node-interface/src/elements.rs b/pkg/node-interface/src/elements.rs new file mode 100644 index 0000000..2e2b9f1 --- /dev/null +++ b/pkg/node-interface/src/elements.rs @@ -0,0 +1,92 @@ +use element::Element; +use primitives::block_height::BlockHeight; +use serde::{Deserialize, Serialize}; + +/// Query for list elemenets +#[derive(Debug, Serialize, Deserialize)] +pub struct ListElementsQuery { + /// String comma seperated list of elements to lookup + pub elements: String, + /// When true, include elements that have been spent (seen historically) + #[serde(default)] + pub include_spent: bool, +} + +/// Body for listing elements via POST to avoid URL length limitations +#[derive(Debug, Serialize, Deserialize)] +pub struct ListElementsBody { + /// Elements to lookup in the tree + pub elements: Vec, + /// When true, include elements that have been spent (seen historically) + #[serde(default)] + pub include_spent: bool, +} + +/// Response from the elements endpoint +pub type ElementsResponse = Vec; + +/// Response item from the elements endpoint +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ElementsResponseSingle { + /// The element being returned + pub element: Element, + /// Block height that the element was included in + pub height: u64, + /// Root hash of the block the element was included in + pub root_hash: Element, + /// Txn hash + pub txn_hash: Element, + /// Whether the element has been spent + pub spent: bool, +} + +/// Snapshot of the tree as of a block height +#[derive(Debug, Serialize, Deserialize)] +pub struct BlockTreeResponse { + /// Block height the snapshot corresponds to + pub height: BlockHeight, + /// Root hash for the block at `height` + pub root_hash: Element, + /// Optional ordered list of elements present in the tree at `height` + /// + /// When requesting a diff, this may be omitted so clients can apply the diff to their cached + /// tree. + #[serde(skip_serializing_if = "Option::is_none")] + pub elements: Option>, + /// Optional diff from a previous height + #[serde(skip_serializing_if = "Option::is_none")] + pub diff: Option, +} + +/// Snapshot of block tree elements at a block height. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BlockTreeSnapshot { + /// Block height the snapshot corresponds to + pub height: BlockHeight, + /// Root hash for the block at `height` + pub root_hash: Element, + /// Ordered list of elements present in the tree at `height` + pub elements: Vec, +} + +/// Diff response including metadata for transforming a previous block's tree into the current tree. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BlockTreeDiff { + /// Block height the diff corresponds to + pub height: BlockHeight, + /// Root hash for the block at `height` + pub root_hash: Element, + /// Detailed diff entries + pub diff: BlockTreeDiffChanges, +} + +/// Detailed diff entries needed to transform a previous block's tree into the current tree. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BlockTreeDiffChanges { + /// Height being diffed from + pub from_height: BlockHeight, + /// Elements to insert to reach the new tree + pub additions: Vec, + /// Elements to remove to reach the new tree + pub removals: Vec, +} diff --git a/pkg/node-interface/src/error.rs b/pkg/node-interface/src/error.rs new file mode 100644 index 0000000..9859cbf --- /dev/null +++ b/pkg/node-interface/src/error.rs @@ -0,0 +1,206 @@ +// lint-long-file-override allow-max-lines=300 +use element::Element; +use primitives::block_height::BlockHeight; +use rpc::{ + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +/// Result for public errors from Payy Network +pub type Result = std::result::Result; + +/// Error data for a note already spent +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct NoteAlreadySpentData { + /// Commitment of the spent note + pub spent_note: Element, + /// Transaction hash that included the spent note + pub failing_txn_hash: Element, +} + +/// Error data detailed the element related to the error +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct ElementData { + /// Element related to error + pub element: Element, +} + +/// Error data detailed the element related to the error +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct ElementsVecData { + /// Element related to error + pub elements: Vec, +} + +/// Error data for mint in contract is different +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, thiserror::Error)] +#[error( + "[node-interface] mint in contract mismatch: contract_value={contract_value:?}, contract_note_kind={contract_note_kind:?}, proof_value={proof_value:?}, proof_note_kind={proof_note_kind:?}" +)] +pub struct MintInContractIsDifferent { + /// Value of mint in contract + pub contract_value: Element, + /// Kind of note in contract + pub contract_note_kind: Element, + /// Proof mint/burn value message + pub proof_value: Element, + /// Proof mint/burn note kind + pub proof_note_kind: Element, +} + +/// Node client interface error +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// A rpc error + #[error("rpc error")] + Rpc(#[from] RpcError), + + /// A client error + #[error("client error")] + Client(#[from] Box), +} + +/// Public errors from Payy Network node +#[derive(Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize)] +pub enum RpcError { + /// Submitted proof is not valid (i.e. verify of proof failed) + #[bad_request("invalid-proof")] + #[error("invalid proof")] + InvalidProof, + + /// Output note included in the transaction is already present in the tree, + /// the transaction could be accepted but then the user would lose their funds + #[already_exists("txn-root-not-recent-enough")] + #[error("txn root is not recent enough (must be last 120)")] + TxnRootNotRecentEnough(ElementData), + + /// Conflicting element in another transaction in the same block + #[already_exists("conflicting-elements")] + #[error("conflicting element in the same block")] + ConflictingElementsInBlock(ElementsVecData), + + /// Output commitment included in the transaction is already present in the tree, + /// this indicates that the client may be trying to re-submit an existing transaction + #[already_exists("output-commitments-exists")] + #[error("output commitments already exists")] + TxnOutputCommitmentsExist(ElementsVecData), + + /// Input commitments are not in the tree (note may never have existed or may be spent) + #[not_found("input-commitments-not-found")] + #[error("input commitments are not in the tree")] + TxnInputCommitmentsNotInTree(ElementsVecData), + + /// Output note commitment + #[already_exists("output-commitments-existed-recetly")] + #[error("output commitments existed recently")] + TxnOutputCommitmentsExistedRecently(ElementsVecData), + + /// Mint is not in the contract on the base chain, it is required that + /// all mints be registered on the base chain before being submitted to Payy + /// Network, as we need to validate the users locked funds before releasing them + /// on Payy Network + #[not_found("mint-not-in-contract")] + #[error("mint leaf is not in the contract")] + MintIsNotInTheContract(ElementData), + + /// Mint has already been spent on the Payy Network. This error occurs when attempting + /// to spend a mint that has already been rolled up. The smart contract has marked the mint as spent. + /// Each mint can only be spent once to prevent double-spending attacks. The client should check + /// their transaction history and avoid reusing spent mints. + #[already_exists("mint-is-already-spent")] + #[error("mint is already spent")] + MintIsAlreadySpent(ElementsVecData), + + /// Mint is in the contract on the base chain, but the minted amount is different + /// to the txn proof sent. A new txn should be submitted with the correct values. + #[bad_request("mint-in-contract-is-different")] + #[error("mint in contract is different to provided txn proof")] + MintInContractIsDifferent(Box), + + /// Mint references a chain that is not configured on this validator + #[bad_request("unsupported-chain")] + #[error("[node-interface] unsupported chain {chain_id}")] + UnsupportedChain { + /// Chain identifier encoded in the mint note kind. + chain_id: u64, + }, + + /// Transaction contains duplicate input commitments + #[bad_request("duplicate-input-commitments")] + #[error("transaction contains duplicate input commitments")] + TxnDuplicateInputCommitments(ElementsVecData), + + /// Transaction contains duplicate output commitments + #[bad_request("duplicate-output-commitments")] + #[error("transaction contains duplicate output commitments")] + TxnDuplicateOutputCommitments(ElementsVecData), + + /// Transaction uses a commitment that is already pending in the mempool + #[already_exists("commitment-already-pending")] + #[error("commitment already pending in another transaction")] + TxnCommitmentAlreadyPending(ElementsVecData), + + /// Prevent the user from accidentally burning to the zero address and therefore + /// losing their funds + #[bad_request("burn-to-address-cannot-be-zero")] + #[error("burn 'to' address cannot be zero")] + BurnToAddressCannotBeZero, + + /// Element was not found + #[not_found("element-not-found")] + #[error("failed to find element in tree")] + ElementNotFound(ElementData), + + /// Transaction was not found + #[not_found("txn-not-found")] + #[error("failed to find transaction")] + TxnNotFound(ElementData), + + /// Element is too large for the modulus of the zk primitive + #[bad_request("invalid-element-size")] + #[error("invalid element, size exceeds modulus")] + InvalidElementSize(ElementData), + + /// Element string provided was in invalid format + #[bad_request("failed-to-parse-element")] + #[error("invalid element")] + FailedToParseElement(ElementData), + + /// Mint hash already exists + #[already_exists("mint-hash-already-exists")] + #[error("mint hash already exists")] + MintHashAlreadyExists(ElementData), + + /// Transaction has already been included in a block + #[already_exists("txn-already-included")] + #[error("[node-interface] transaction already included in block {height}")] + TxnAlreadyIncluded { + /// Root hash of the block that included the transaction + root_hash: Element, + /// Hash of the submitted transaction + txn_hash: Element, + /// Height of the block that already contains the transaction + height: BlockHeight, + }, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_convert() { + let error = RpcError::InvalidProof; + let http_error: HTTPError = error.into(); + let http_output: ErrorOutput = http_error.into(); + let orig_error: RpcError = http_output.try_into().unwrap(); + println!("orig_error: {orig_error}"); + } +} diff --git a/pkg/node-interface/src/height.rs b/pkg/node-interface/src/height.rs new file mode 100644 index 0000000..04f6be5 --- /dev/null +++ b/pkg/node-interface/src/height.rs @@ -0,0 +1,11 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +/// Height response for the chain +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct HeightResponse { + /// Height of the chain + pub height: u64, + /// Root hash of the merkle tree + pub root_hash: Element, +} diff --git a/pkg/node-interface/src/lib.rs b/pkg/node-interface/src/lib.rs new file mode 100644 index 0000000..78cf130 --- /dev/null +++ b/pkg/node-interface/src/lib.rs @@ -0,0 +1,25 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![allow(clippy::match_bool)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::doc_markdown)] +#![deny(missing_docs)] + +//! Interface for requests to Payy Network + +mod blocks; +mod client; +mod elements; +mod error; +mod height; +mod merkle; +mod transaction; + +pub use blocks::*; +pub use client::{NodeClient, NodeClientMock}; +pub use elements::*; +pub use error::*; +pub use height::*; +pub use merkle::*; +pub use transaction::*; diff --git a/pkg/node-interface/src/merkle.rs b/pkg/node-interface/src/merkle.rs new file mode 100644 index 0000000..2a3eb18 --- /dev/null +++ b/pkg/node-interface/src/merkle.rs @@ -0,0 +1,9 @@ +use element::Element; +use serde::Deserialize; + +/// Response payload containing Merkle inclusion paths for provided commitments. +#[derive(Debug, Deserialize)] +pub struct MerklePathResponse { + /// Each entry corresponds to the requested commitment order. + pub paths: Vec>, +} diff --git a/pkg/node-interface/src/transaction.rs b/pkg/node-interface/src/transaction.rs new file mode 100644 index 0000000..99a5fcf --- /dev/null +++ b/pkg/node-interface/src/transaction.rs @@ -0,0 +1,102 @@ +use element::Element; +use primitives::{ + block_height::BlockHeight, + pagination::{OpaqueCursor, OpaqueCursorChoice}, +}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use zk_primitives::UtxoProof; + +use crate::TxnWithInfo; + +/// Request for submit transaction +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct TransactionRequest { + /// Utxo proof to be verified and applied + pub proof: UtxoProof, +} + +/// Response for submit transaction +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct TransactionResponse { + /// Height of the block the transaction was included in + pub height: BlockHeight, + /// Root hash of the merkle tree for the block + pub root_hash: Element, + /// Transaction hash of submitted transaction + pub txn_hash: Element, +} + +/// Ordering options for listing transactions. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum ListTxnsOrder { + /// Return transactions from newest to oldest. + NewestToOldest, + /// Return transactions from oldest to newest. + OldestToNewest, +} + +impl ListTxnsOrder { + /// Convenience helper for newest to oldest order. + #[must_use] + pub const fn newest_to_oldest() -> Self { + Self::NewestToOldest + } + + /// Convenience helper for oldest to newest order. + #[must_use] + pub const fn oldest_to_newest() -> Self { + Self::OldestToNewest + } +} + +/// Cursor position for listing transactions. +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct ListTxnsPosition { + /// Block height for the transaction. + pub block: BlockHeight, + /// Transaction index within the block. + pub txn: u64, +} + +/// Parameters for listing transactions. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct ListTxnsParams { + /// Maximum number of transactions to return. + pub limit: usize, + /// Pagination cursor for fetching additional transactions. + #[cfg_attr(feature = "ts-rs", ts(type = "string"))] + #[cfg_attr(feature = "ts-rs", ts(optional))] + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option>, + /// Ordering for the listed transactions. + pub order: ListTxnsOrder, + /// Whether to wait for a new transaction when none are available. + pub poll: bool, +} + +/// Response structure for listing transactions. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct ListTxnsResponse { + /// Transactions returned by the node. + pub txns: Vec, + /// Pagination cursor for fetching additional transactions. + #[cfg_attr( + feature = "ts-rs", + ts(type = "import(\"./OpaqueClientCursor\").OpaqueClientCursor") + )] + pub cursor: OpaqueCursor, +} diff --git a/pkg/node/Cargo.toml b/pkg/node/Cargo.toml index 7cfc54a..d097d4b 100644 --- a/pkg/node/Cargo.toml +++ b/pkg/node/Cargo.toml @@ -1,33 +1,37 @@ [package] name = "node" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] block-store = { workspace = true } contracts = { workspace = true } +constants = { workspace = true } doomslug = { workspace = true } +element = { workspace = true } +node-interface = { workspace = true } p2p2 = { workspace = true } primitives = { workspace = true } prover = { workspace = true } rpc = { workspace = true } smirk = { workspace = true } zk-primitives = { workspace = true } -zk-circuits = { workspace = true } testutil = { workspace = true } burn-substitutor = { workspace = true } +zk-circuits = { workspace = true } +barretenberg-cli = { workspace = true } +hash = { workspace = true } actix-cors = { workspace = true } actix-server = { workspace = true } actix-web = { workspace = true } async-trait = { workspace = true } -base64 = { workspace = true } chrono = { workspace = true } clap = { workspace = true } -color-eyre = { workspace = true } +contextful = { workspace = true } +json-with-logging = { workspace = true } dirs = { workspace = true } ethereum-types = { workspace = true } -eyre = { workspace = true } expect-test = { workspace = true } figment = { workspace = true } futures = { workspace = true } @@ -39,22 +43,19 @@ rand = { workspace = true } rustc-hex = { workspace = true } rocksdb = { workspace = true } secp256k1 = { workspace = true } -sentry = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sha3 = { workspace = true } -strum = { workspace = true } thiserror = { workspace = true } -tiny-keccak = { workspace = true } tokio = { workspace = true } tokio-stream = { workspace = true } tracing = { workspace = true } -tracing-stackdriver = { workspace = true } tracing-subscriber = { workspace = true } web3 = { workspace = true } itertools = { workspace = true } borsh = { workspace = true } wire-message = { workspace = true } +strum = { workspace = true } derivative = { workspace = true } microtype = { workspace = true } rand_derive2 = { workspace = true } @@ -63,9 +64,15 @@ tokio-postgres = { workspace = true } postgres-native-tls = { workspace = true } native-tls = { workspace = true } scopeguard = { workspace = true } +workspace-hack.workspace = true [dev-dependencies] dotenvy = { workspace = true } reqwest = { workspace = true } tempdir = { workspace = true } serial_test = { workspace = true } +tempfile = { workspace = true } +aggregator = { workspace = true } +aggregator-interface = { workspace = true } +barretenberg-interface = { workspace = true } +node-client-http = { workspace = true } diff --git a/pkg/node/README.md b/pkg/node/README.md index 00f9c61..9a9145a 100644 --- a/pkg/node/README.md +++ b/pkg/node/README.md @@ -2,7 +2,7 @@ Primary client for Solid blockchain. -Before running node, deploy contracts in the `eth` directory and set rollup-contract-addr to the address of the deployed rollup contract. +Before running the node, deploy contracts in the `eth` directory and ensure the `chains` section of your configuration includes the deployed rollup contract and RPC endpoint for that chain. Each chain can customize its confirmation depth with the `safe-eth-height-offset` field. The legacy `--eth-rpc-url` and `--rollup-contract-addr` flags still override the first configured chain for convenience. ### Single validators @@ -86,7 +86,7 @@ Query parameters: `/v0/blocks` Query parameters: -- `limit`, max 100, default 10 +- `limit`, max 256, default 10 - `cursor`, same as for transactions - `order`, either `"LowestToHighest"` or `"HighestToLowest"` - `skip_empty`, if true, skips blocks with no transactions diff --git a/pkg/node/src/bin/generate_key.rs b/pkg/node/src/bin/generate_key.rs index aa0bf5c..ee19209 100644 --- a/pkg/node/src/bin/generate_key.rs +++ b/pkg/node/src/bin/generate_key.rs @@ -1,8 +1,6 @@ use primitives::peer::PeerIdSigner; fn main() { - color_eyre::install().unwrap(); - let peer_signer = PeerIdSigner::default(); println!("Secret key:"); println!(" 0x{}", peer_signer.to_hex()); diff --git a/pkg/node/src/bin/node.rs b/pkg/node/src/bin/node.rs index 65f85bc..a884555 100644 --- a/pkg/node/src/bin/node.rs +++ b/pkg/node/src/bin/node.rs @@ -1,40 +1,109 @@ +// lint-long-file-override allow-max-lines=300 +use std::collections::HashMap; use std::sync::Arc; use std::{pin::Pin, time::Duration}; use clap::Parser; -use eyre::Result; -use futures::Future; +use contextful::{Contextful, ResultContextExt}; +use futures::{ + Future, + future::{FutureExt, pending}, + stream::{FuturesUnordered, StreamExt}, +}; +use node::{Mode, Node, TracingInitError, TxnStats}; use node::{ - config::{cli::CliArgs, Config}, + config::{Config, cli::CliArgs}, create_rpc_server, }; -use node::{Mode, Node, TxnStats}; use rpc::tracing::setup_tracing; +use zk_circuits::BbBackend; -#[tokio::main] -async fn main() -> Result<()> { - color_eyre::install().unwrap(); +/// Run the contract worker with restart attempts on failure. +async fn run_contract_worker_with_retries( + contract: contracts::RollupContract, + interval: Duration, + max_restarts: u32, + delay_on_error: Duration, +) -> contracts::Result<()> { + let mut attempts: u32 = 0; + let reset_duration = Duration::from_secs(30 * 60); // 30 minutes + + loop { + let start_time = std::time::Instant::now(); + match contract.worker(interval).await { + Ok(()) => return Ok(()), + Err(e) => { + let ran_for = start_time.elapsed(); + if ran_for >= reset_duration { + tracing::info!( + ran_for = ?ran_for, + old_attempts = attempts, + "contract worker ran long enough; resetting attempt counter", + ); + attempts = 0; + } + + attempts += 1; + + if attempts > max_restarts { + tracing::error!( + attempts, + max_restarts, + error = ?e, + "contract worker exceeded restart attempts", + ); + return Err(e); + } + + tracing::warn!( + attempts, + max_restarts, + ran_for = ?ran_for, + error = ?e, + "contract worker failed; restarting", + ); + tokio::time::sleep(delay_on_error).await; + } + } + } +} + +#[allow(clippy::result_large_err)] +#[tokio::main] +async fn main() -> node::Result<()> { let args = CliArgs::parse(); - let config = Config::from_env(args.clone()).unwrap(); + let config = Config::from_env(args.clone())?; - let _guard = setup_tracing( + let _guard = match setup_tracing( &[ "node", "solid", "smirk", - "p2p", + "p2p2", "prover", "zk_primitives", "contracts", "block_store", + "notes", ], &args.log_level, &args.log_format, config.sentry_dsn.clone(), config.env_name.clone(), - )?; + ) + .context("initialize tracing") + { + Ok(guard) => guard, + Err(err) => { + let err = err.map_source(|source| { + let boxed: Box = source.into(); + TracingInitError::from(boxed) + }); + return Err(err.into()); + } + }; // Listen address of the server let rpc_laddr = config.rpc_laddr.clone(); @@ -42,24 +111,70 @@ async fn main() -> Result<()> { // Private key let peer_signer = config.secret_key.clone(); + // web3 depends on a different version ofsecp256k1, which carries an error type that + // does not implement our `From>`; map it into + // a generic InvalidSecretKey instead of using `?`. let secret_key = web3::signing::SecretKey::from_slice(&config.secret_key.secret_key().secret_bytes()[..]) - .unwrap(); - let contracts_client = - contracts::Client::new(&config.eth_rpc_url, config.minimum_gas_price_gwei); - let contract = - contracts::RollupContract::load(contracts_client, &config.rollup_contract_addr, secret_key) - .await?; + .map_err(|_err| { + node::Error::Secp256k1(Contextful::new( + "load secret key", + secp256k1::Error::InvalidSecretKey, + )) + })?; + let mut rollup_contracts_map = HashMap::new(); + for chain in &config.chains { + let client = contracts::Client::new(&chain.eth_rpc_url, config.minimum_gas_price_gwei); + let contract = contracts::RollupContract::load( + client, + u128::from(chain.chain_id), + &chain.rollup_contract_addr, + secret_key, + ) + .await + .context(format!("load rollup contract for chain {}", chain.chain_id))?; + rollup_contracts_map.insert(chain.chain_id, contract); + } + + if rollup_contracts_map.is_empty() { + return Err(node::Error::MissingPrimaryChainConfig); + } + + let rollup_contracts = Arc::new(rollup_contracts_map); // Services - let node = Node::new(peer_signer, contract.clone(), config.clone()).unwrap(); + let bb_backend: Arc = Arc::new(barretenberg_cli::CliBackend); + let node = Node::new( + peer_signer, + Arc::clone(&rollup_contracts), + config.clone(), + Arc::clone(&bb_backend), + )?; + let mut contract_worker_tasks: Option> = { + let tasks: FuturesUnordered<_> = rollup_contracts + .values() + .cloned() + .map(|contract| { + run_contract_worker_with_retries( + contract, + Duration::from_secs(30), + 3, + Duration::from_secs(5), + ) + .boxed() + }) + .collect(); + + if tasks.is_empty() { None } else { Some(tasks) } + }; let txn_stats = Arc::new(TxnStats::new(Arc::clone(&node.shared))); let server = create_rpc_server( &rpc_laddr, config.health_check_commit_interval_sec, Arc::clone(&node.shared), Arc::clone(&txn_stats), - )?; + ) + .context("start RPC server")?; let prover_task: Pin>>> = if config.mode == Mode::Prover || config.mode == Mode::MockProver { @@ -81,12 +196,26 @@ async fn main() -> Result<()> { res = server => { tracing::info!("rpc server shutdown: {:?}", res); } - res = contract.worker(Duration::from_secs(30)) => { - tracing::info!("contract worker shutdown: {:?}", res); + Some(res) = async { + if let Some(tasks) = &mut contract_worker_tasks { + tasks.next().await + } else { + pending::>>().await + } + } => { + match res { + Ok(()) => tracing::info!("contract worker shutdown: Ok(())"), + Err(e) => { + tracing::error!(error = ?e, "contract worker shutdown after retries"); + } + } } - res = txn_stats.worker() => { + res = txn_stats.clone().worker() => { tracing::info!("txn stats worker shutdown: {:?}", res); } + res = txn_stats.today_stats_worker() => { + tracing::info!("txn stats today worker shutdown: {:?}", res); + } } Ok(()) diff --git a/pkg/node/src/block.rs b/pkg/node/src/block.rs index b78ed72..55ead6f 100644 --- a/pkg/node/src/block.rs +++ b/pkg/node/src/block.rs @@ -1,20 +1,24 @@ +// lint-long-file-override allow-max-lines=300 use block_store::BlockStore; use borsh::{BorshDeserialize, BorshSerialize}; +use contextful::ErrorContextExt as _; +use element::Element; use ethereum_types::U256; +use node_interface::{ElementsVecData, RpcError}; +use parking_lot::RwLock; use primitives::{hash::CryptoHash, peer::PeerIdSigner}; use serde::{Deserialize, Serialize}; use sha3::{Digest, Keccak256}; use std::{collections::HashMap, fmt::Debug}; use tracing::error; -use zk_primitives::Element; +use zk_circuits::BbBackend; use crate::types::BlockHeight; -use crate::{ - utxo::{validate_txn, UtxoProof}, - BlockFormat, PersistentMerkleTree, -}; +use crate::utxo::{validate_txn_state, verify_txn_proof}; +use crate::{BlockFormat, PersistentMerkleTree}; use crate::{Error, Mode}; use primitives::sig::Signature; +use zk_primitives::UtxoProof; #[derive( Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, BorshSerialize, BorshDeserialize, @@ -56,15 +60,15 @@ impl BlockState { Self { root_hash, txns } } - /// Get an iterator over all leaves in this block - pub fn leaves(&self) -> impl Iterator + '_ { - self.txns.iter().flat_map(|proof| proof.leaves()) - } + // /// Get an iterator over all leaves in this block + // pub fn leaves(&self) -> impl Iterator + '_ { + // self.txns.iter().flat_map(|proof| proof.leaves()) + // } - /// Get an iterator over all the non-null leaves in this block - pub fn leaves_non_null(&self) -> impl Iterator + '_ { - self.leaves().filter(|&e| e != Element::NULL_HASH) - } + // /// Get an iterator over all the non-null leaves in this block + // pub fn leaves_non_null(&self) -> impl Iterator + '_ { + // self.leaves().filter(|&e| e != Element::NULL_HASH) + // } } impl Block { @@ -134,42 +138,73 @@ impl BlockContent { signer.sign(&self.hash()) } - pub(crate) fn validate( + pub(crate) async fn validate( &self, + bb_backend: &dyn BbBackend, mode: Mode, block_store: &BlockStore, - notes_tree: &PersistentMerkleTree, + notes_tree: &RwLock, ) -> Result<(), Error> { - let mut txn_leaves = HashMap::new(); + let mut insert_txn_leaves = HashMap::new(); + let mut remove_txn_leaves = HashMap::new(); + + // 1. Verify all proofs first (async, without lock) + for utxo_proof in self.state.txns.iter() { + verify_txn_proof(bb_backend, utxo_proof).await?; + } - for txn in self.state.txns.iter() { + // 2. Take lock and validate all states (sync) + let notes_tree_guard = notes_tree.read(); + + for utxo_proof in self.state.txns.iter() { // Between transactions in the same block, // we check that the leaves are unique, // otherwise there could be a double spend. - for leaf in txn.leaves() { + for leaf in utxo_proof.public_inputs.output_commitments { + if leaf == Element::ZERO { + continue; + } + + let existing_leaf_txn_hash = insert_txn_leaves + .get(&leaf) + .or(remove_txn_leaves.get(&leaf)); + if existing_leaf_txn_hash.is_some() { + return Err(RpcError::ConflictingElementsInBlock(ElementsVecData { + elements: vec![leaf], + }) + .wrap_err("duplicate output commitment detected within block") + .into()); + } else { + insert_txn_leaves.insert(leaf, utxo_proof.hash()); + } + } + + for leaf in utxo_proof.public_inputs.input_commitments { if leaf == Element::ZERO { continue; } - let existing_leaf_txn_hash = txn_leaves.get(&leaf); - if let Some(existing_leaf_txn_hash) = existing_leaf_txn_hash { - return Err(Error::LeafAlreadyInsertedInTheSameBlock { - inserted_leaf: leaf, - txn_hash: *existing_leaf_txn_hash, - failing_txn_hash: txn.hash(), - }); + let existing_leaf_txn_hash = insert_txn_leaves + .get(&leaf) + .or(remove_txn_leaves.get(&leaf)); + if existing_leaf_txn_hash.is_some() { + return Err(RpcError::ConflictingElementsInBlock(ElementsVecData { + elements: vec![leaf], + }) + .wrap_err("duplicate input commitment detected within block") + .into()); } else { - txn_leaves.insert(leaf, txn.hash()); + remove_txn_leaves.insert(leaf, utxo_proof.hash()); } } - let result = validate_txn( + let result = validate_txn_state( mode, - txn, + utxo_proof, // TODO: is this valid? self.header.height, block_store, - notes_tree, + ¬es_tree_guard, ); if let Err(err) = result { @@ -183,12 +218,14 @@ impl BlockContent { } } - let new_root_hash = match txn_leaves.is_empty() { + let new_root_hash = if insert_txn_leaves.is_empty() && remove_txn_leaves.is_empty() { // If there is no leaves to insert, the root hash wouldn't change - true => notes_tree.tree().root_hash(), - false => notes_tree - .tree() - .root_hash_with(&txn_leaves.into_keys().collect::>()), + notes_tree_guard.tree().root_hash() + } else { + notes_tree_guard.tree().root_hash_with( + &insert_txn_leaves.into_keys().collect::>(), + &remove_txn_leaves.into_keys().collect::>(), + ) }; if new_root_hash != self.state.root_hash { return Err(Error::InvalidBlockRoot { diff --git a/pkg/node/src/cache.rs b/pkg/node/src/cache.rs index e24812a..6cc49bf 100644 --- a/pkg/node/src/cache.rs +++ b/pkg/node/src/cache.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=400 use std::collections::{BTreeMap, HashMap}; use primitives::hash::CryptoHash; @@ -168,8 +169,8 @@ impl BlockCache { #[cfg(test)] mod tests { + use element::Element; use primitives::sig::Signature; - use smirk::Element; use crate::block::{BlockContent, BlockHeader, BlockState}; @@ -266,19 +267,13 @@ mod tests { for i in 0..3 { assert!(block_cache.get_by_height(i.into()).is_none()); - assert!(block_cache - .block_hash_heights - .get(&BlockHeight(i)) - .is_none()); + assert!(!block_cache.block_hash_heights.contains_key(&BlockHeight(i))); } // Check blocks and hashes above or equal to the confirmed height are untouched for i in 3..6 { assert!(block_cache.get_by_height(i.into()).is_some()); - assert!(block_cache - .block_hash_heights - .get(&BlockHeight(i)) - .is_some()); + assert!(block_cache.block_hash_heights.contains_key(&BlockHeight(i))); } } diff --git a/pkg/node/src/config/cli.rs b/pkg/node/src/config/cli.rs index a5daacb..136423e 100644 --- a/pkg/node/src/config/cli.rs +++ b/pkg/node/src/config/cli.rs @@ -27,7 +27,7 @@ pub struct CliArgs { pub rpc_laddr: Option, /// P2P listen address - #[arg(long)] + #[arg(long, env = "POLY_P2P_LADDR")] pub p2p_laddr: Option, /// Peers to dial diff --git a/pkg/node/src/config/default_config.toml b/pkg/node/src/config/default_config.toml index 8de2aca..2dc8438 100644 --- a/pkg/node/src/config/default_config.toml +++ b/pkg/node/src/config/default_config.toml @@ -20,17 +20,19 @@ fast-sync-threshold = 100000 mode = "validator" run-prover = false +enable-prover-worker = true +enable-rollup-worker = true secret-key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" -rpc-laddr = "0.0.0.0:8080" +rpc-laddr = "0.0.0.0:8091" db-path = "~/.polybase/db" smirk-path = "~/.polybase/smirk" eth-rpc-url = "http://localhost:8545" -rollup-contract-addr = "0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6" +rollup-contract-addr = "0xdc64a140aa3e981100a9beca4e685f962f0cf6c9" health-check-commit-interval-sec = 60 @@ -38,12 +40,16 @@ rollup-wait-time-ms = 3000 bad-blocks = [] +[[chains]] +chain-id = 137 +eth-rpc-url = "http://localhost:8545" +rollup-contract-addr = "0xcf7ed3acca5a467e9e704c703e8d87f634fb0fc9" safe-eth-height-offset = 0 [p2p] # Addresses are "multiaddr"s - see the libp2p docs for more details: # https://docs.rs/libp2p/latest/libp2p/struct.Multiaddr.html -laddr = "/ip4/0.0.0.0/tcp/0" +laddr = "/ip4/127.0.0.1/tcp/5000" # Optionally specify other addresses to dial on startup dial = "" diff --git a/pkg/node/src/config/mod.rs b/pkg/node/src/config/mod.rs index 5113a04..140c339 100644 --- a/pkg/node/src/config/mod.rs +++ b/pkg/node/src/config/mod.rs @@ -1,20 +1,37 @@ -use std::path::PathBuf; +// lint-long-file-override allow-max-lines=400 +use std::{ + collections::BTreeMap, + fs::File, + io::Read, + path::{Path, PathBuf}, + str::FromStr, +}; use self::cli::CliArgs; -use crate::Mode; -use color_eyre::Result; +use crate::{Error, Mode, Result}; +use contextful::ResultContextExt; use dirs::home_dir; use figment::{ - providers::{Env, Format, Toml}, Figment, + providers::{Env, Format, Toml}, }; use primitives::peer::PeerIdSigner; -use serde::Deserialize; -use std::io::Read; -use std::{fs::File, str::FromStr}; +use serde::{Deserialize, Deserializer, de::Error as DeError}; pub mod cli; +#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct ChainConfig { + pub chain_id: u64, + pub eth_rpc_url: String, + pub rollup_contract_addr: String, + #[serde(default)] + pub safe_eth_height_offset: u64, + #[serde(default)] + pub max_rollup_gas_price_gwei: Option, +} + // TODO: should we use kebab-case? Currently _ is used to split into // multiple level dictionaries #[derive(Debug, Clone, PartialEq, Eq, Deserialize)] @@ -55,9 +72,15 @@ pub struct Config { /// Path to Smirk pub smirk_path: PathBuf, - pub eth_rpc_url: String, + /// Chain-specific configuration, accepting both TOML arrays and env var maps. + #[serde(default, deserialize_with = "deserialize_chain_configs")] + pub chains: Vec, - pub rollup_contract_addr: String, + #[serde(default)] + pub eth_rpc_url: Option, + + #[serde(default)] + pub rollup_contract_addr: Option, /// If the last commit is older than this, health check will fail pub health_check_commit_interval_sec: u64, @@ -73,7 +96,16 @@ pub struct Config { /// The minimum amount of gas (in gwei) to use for transactions pub minimum_gas_price_gwei: Option, - pub safe_eth_height_offset: u64, + /// Whether the prover worker should be started alongside the rollup worker + #[serde(default = "default_true")] + pub enable_prover_worker: bool, + + /// Whether the rollup worker should be started + #[serde(default = "default_true")] + pub enable_rollup_worker: bool, + + #[serde(default, rename = "safe-eth-height-offset")] + legacy_safe_eth_height_offset: Option, } impl Config { @@ -84,15 +116,18 @@ impl Config { /// /// `config_path` doesn't need to point to an actual file pub fn from_env(args: CliArgs) -> Result { - let mut config: Config = Figment::new() + let cli_eth_rpc_url = args.eth_rpc_url.clone(); + let cli_rollup_contract_addr = args.rollup_contract_addr.clone(); + + let mut config: Config = Figment::from(Toml::string(Self::DEFAULT_STR)) .merge(Toml::file(args.config_path)) .merge( Env::prefixed("POLY_") .split("__") .map(|k| k.as_str().replace('_', "-").into()), ) - .join(Toml::string(Self::DEFAULT_STR)) - .extract()?; + .extract() + .context("extract configuration")?; if let Some(mode) = args.mode { config.mode = mode; @@ -107,10 +142,17 @@ impl Config { } if let Some(secret_key_path) = args.secret_key_path { - let mut file = File::open(secret_key_path)?; + let mut file = File::open(&secret_key_path).context(format!( + "open secret key file {}", + display_path(&secret_key_path) + ))?; let mut key = String::new(); - file.read_to_string(&mut key)?; - config.secret_key = PeerIdSigner::from_str(&key)?; + file.read_to_string(&mut key).context(format!( + "read secret key file {}", + display_path(&secret_key_path) + ))?; + config.secret_key = PeerIdSigner::from_str(key.trim()) + .context("parse secret key from file contents")?; } if let Some(secret_key) = args.secret_key { @@ -125,47 +167,144 @@ impl Config { config.db_path = db_path; } - if config.db_path.starts_with("~") { - config.db_path = home_dir() - .unwrap() - .join(config.db_path.strip_prefix("~").unwrap()); - } + config.db_path = expand_home_if_needed(config.db_path)?; if let Some(smirk_path) = args.smirk_path { config.smirk_path = smirk_path; } - if config.smirk_path.starts_with("~") { - config.smirk_path = home_dir() - .unwrap() - .join(config.smirk_path.strip_prefix("~").unwrap()); - } + config.smirk_path = expand_home_if_needed(config.smirk_path)?; - if let Some(eth_rpc_url) = args.eth_rpc_url { - config.eth_rpc_url = eth_rpc_url; + if let Some(eth_rpc_url) = cli_eth_rpc_url { + config.eth_rpc_url = Some(eth_rpc_url); } - if let Some(rollup_contract_addr) = args.rollup_contract_addr { - config.rollup_contract_addr = rollup_contract_addr; + if let Some(rollup_contract_addr) = cli_rollup_contract_addr { + config.rollup_contract_addr = Some(rollup_contract_addr); } if let Some(sync_chunk_size) = args.sync_chunk_size { config.sync_chunk_size = sync_chunk_size; } + let legacy_safe_eth_height_offset = config.legacy_safe_eth_height_offset.take(); + let had_legacy_safe_eth_height_offset = legacy_safe_eth_height_offset.is_some(); + let legacy_safe_eth_height_offset_value = legacy_safe_eth_height_offset.unwrap_or_default(); + + if config.chains.is_empty() { + return Err(Error::MissingPrimaryChainConfig); + } + + let single_chain = config.chains.len() == 1; + + if let Some(chain) = config.chains.first_mut() { + if let Some(ref eth_rpc_url) = config.eth_rpc_url { + chain.eth_rpc_url = eth_rpc_url.clone(); + } else { + config.eth_rpc_url = Some(chain.eth_rpc_url.clone()); + } + + if let Some(ref rollup_contract_addr) = config.rollup_contract_addr { + chain.rollup_contract_addr = rollup_contract_addr.clone(); + } else { + config.rollup_contract_addr = Some(chain.rollup_contract_addr.clone()); + } + + if had_legacy_safe_eth_height_offset && single_chain { + chain.safe_eth_height_offset = legacy_safe_eth_height_offset_value; + } + } + Ok(config) } + + #[must_use] + pub fn primary_chain(&self) -> Option<&ChainConfig> { + self.chains.first() + } + + #[must_use] + pub fn chain_config(&self, chain_id: u64) -> Option<&ChainConfig> { + self.chains.iter().find(|chain| chain.chain_id == chain_id) + } + + #[must_use] + pub fn primary_chain_id(&self) -> Option { + self.primary_chain().map(|chain| chain.chain_id) + } + + #[must_use] + pub fn safe_eth_height_offset(&self, chain_id: u64) -> Option { + self.chain_config(chain_id) + .map(|chain| chain.safe_eth_height_offset) + } + + #[must_use] + pub fn primary_safe_eth_height_offset(&self) -> Option { + self.primary_chain() + .map(|chain| chain.safe_eth_height_offset) + } } -#[cfg(test)] -mod tests { - use clap::Parser; +/// Allow `chains` to be described as either a TOML array or an env-var map produced +/// by Figment (from keys like `POLY_CHAINS__0__CHAIN_ID`), normalizing into a Vec. +fn deserialize_chain_configs<'de, D>( + deserializer: D, +) -> std::result::Result, D::Error> +where + D: Deserializer<'de>, +{ + #[derive(Deserialize)] + #[serde(untagged)] + enum Chains { + Seq(Vec), + Map(BTreeMap), + } - use super::*; + let Some(value) = Option::::deserialize(deserializer)? else { + return Ok(Vec::new()); + }; + + match value { + Chains::Seq(seq) => Ok(seq), + Chains::Map(map) => { + let mut entries = Vec::with_capacity(map.len()); + for (idx, chain) in map { + let idx_num = idx.parse::().map_err(|_| { + DeError::custom(format!("chains index `{idx}` is not a number")) + })?; + entries.push((idx_num, chain)); + } + entries.sort_by_key(|(idx, _)| *idx); + Ok(entries.into_iter().map(|(_, chain)| chain).collect()) + } + } +} - #[test] - fn can_parse_from_empty() { - let args = CliArgs::try_parse_from(["node"]).unwrap(); - Config::from_env(args).unwrap(); +fn expand_home_if_needed(path: PathBuf) -> Result { + if !path.starts_with("~") { + return Ok(path); } + + let Some(home) = home_dir() else { + return Err(Error::ConfigMissingHomeDir { path }); + }; + + let suffix = strip_tilde(&path); + Ok(home.join(suffix)) +} + +fn strip_tilde(path: &Path) -> &Path { + path.strip_prefix("~").unwrap_or(path) } + +fn display_path(path: &Path) -> String { + path.display().to_string() +} + +const fn default_true() -> bool { + true +} + +#[cfg(test)] +mod tests; diff --git a/pkg/node/src/config/tests.rs b/pkg/node/src/config/tests.rs new file mode 100644 index 0000000..5ed85ab --- /dev/null +++ b/pkg/node/src/config/tests.rs @@ -0,0 +1,170 @@ +use std::{io::Write, sync::Mutex}; + +use clap::Parser; +use tempfile::NamedTempFile; + +use crate::Error; + +use super::*; + +static ENV_MUTEX: Mutex<()> = Mutex::new(()); + +const TEST_ENV_VARS: [&str; 6] = [ + "POLY_CHAINS__0__CHAIN_ID", + "POLY_CHAINS__0__ETH_RPC_URL", + "POLY_CHAINS__0__ROLLUP_CONTRACT_ADDR", + "POLY_CHAINS__0__SAFE_ETH_HEIGHT_OFFSET", + "POLY_ETH_RPC_URL", + "POLY_ROLLUP_CONTRACT_ADDR", +]; + +#[test] +fn can_parse_from_empty() { + let _lock = ENV_MUTEX.lock().unwrap(); + let _guard = EnvGuard::new(&TEST_ENV_VARS); + let args = CliArgs::try_parse_from(["node"]).unwrap(); + let config = Config::from_env(args).unwrap(); + assert!(!config.chains.is_empty()); + assert_eq!(config.primary_chain_id(), Some(137)); +} + +#[test] +fn legacy_single_chain_translates_to_chains_vec() { + let _lock = ENV_MUTEX.lock().unwrap(); + let _guard = EnvGuard::new(&TEST_ENV_VARS); + let mut file = NamedTempFile::new().unwrap(); + writeln!( + file, + r#" +env-name = "dev" +eth-rpc-url = "http://legacy.example" +rollup-contract-addr = "0x1234567890abcdef1234567890abcdef12345678" +"# + ) + .unwrap(); + + let args = + CliArgs::try_parse_from(["node", "--config-path", file.path().to_str().unwrap()]).unwrap(); + + let config = Config::from_env(args).unwrap(); + assert_eq!(config.chains.len(), 1); + let chain = &config.chains[0]; + assert_eq!(chain.chain_id, 137); + assert_eq!(chain.eth_rpc_url, "http://legacy.example"); + assert_eq!( + chain.rollup_contract_addr, + "0x1234567890abcdef1234567890abcdef12345678" + ); +} + +#[test] +fn error_when_chains_are_missing() { + let _lock = ENV_MUTEX.lock().unwrap(); + let _guard = EnvGuard::new(&TEST_ENV_VARS); + let mut file = NamedTempFile::new().unwrap(); + writeln!( + file, + r#" +chains = [] +eth-rpc-url = "http://legacy.example" +rollup-contract-addr = "0x1234567890abcdef1234567890abcdef12345678" +"# + ) + .unwrap(); + + let args = + CliArgs::try_parse_from(["node", "--config-path", file.path().to_str().unwrap()]).unwrap(); + + let err = Config::from_env(args).unwrap_err(); + assert!(matches!(err, Error::MissingPrimaryChainConfig)); +} + +#[test] +fn env_chain_map_translates_to_vec() { + let _lock = ENV_MUTEX.lock().unwrap(); + let _guard = EnvGuard::new(&TEST_ENV_VARS); + set_env_var("POLY_CHAINS__0__CHAIN_ID", "999"); + set_env_var("POLY_CHAINS__0__ETH_RPC_URL", "http://env-chain.example"); + set_env_var( + "POLY_CHAINS__0__ROLLUP_CONTRACT_ADDR", + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ); + set_env_var("POLY_CHAINS__0__SAFE_ETH_HEIGHT_OFFSET", "42"); + set_env_var("POLY_ETH_RPC_URL", "http://env-chain.example"); + set_env_var( + "POLY_ROLLUP_CONTRACT_ADDR", + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ); + + let args = CliArgs::try_parse_from(["node"]).unwrap(); + let config = Config::from_env(args).unwrap(); + assert_eq!(config.chains.len(), 1); + let chain = &config.chains[0]; + assert_eq!(chain.chain_id, 999); + assert_eq!(chain.eth_rpc_url, "http://env-chain.example"); + assert_eq!( + chain.rollup_contract_addr, + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + ); + assert_eq!(chain.safe_eth_height_offset, 42); +} + +#[test] +fn enable_rollup_worker_config() { + let _lock = ENV_MUTEX.lock().unwrap(); + let mut vars = TEST_ENV_VARS.to_vec(); + vars.push("POLY_ENABLE_ROLLUP_WORKER"); + let _guard = EnvGuard::new(&vars); + + // Test default + let args = CliArgs::try_parse_from(["node"]).unwrap(); + let config = Config::from_env(args).unwrap(); + assert!(config.enable_rollup_worker); + + // Test env override + set_env_var("POLY_ENABLE_ROLLUP_WORKER", "false"); + let args = CliArgs::try_parse_from(["node"]).unwrap(); + let config = Config::from_env(args).unwrap(); + assert!(!config.enable_rollup_worker); +} + +struct EnvGuard { + values: Vec<(String, Option)>, +} + +impl EnvGuard { + fn new(keys: &[&str]) -> Self { + let mut values = Vec::with_capacity(keys.len()); + for key in keys { + values.push(((*key).to_owned(), std::env::var(key).ok())); + remove_env_var(key); + } + Self { values } + } +} + +impl Drop for EnvGuard { + fn drop(&mut self) { + for (key, value) in &self.values { + if let Some(value) = value { + set_env_var(key, value); + } else { + remove_env_var(key); + } + } + } +} + +fn set_env_var(key: &str, value: &str) { + // SAFETY: tests serialize access to environment variables since they run single-threaded. + unsafe { + std::env::set_var(key, value); + } +} + +fn remove_env_var(key: &str) { + // SAFETY: tests serialize access to environment variables since they run single-threaded. + unsafe { + std::env::remove_var(key); + } +} diff --git a/pkg/node/src/constants.rs b/pkg/node/src/constants.rs index c72dc4b..25850a3 100644 --- a/pkg/node/src/constants.rs +++ b/pkg/node/src/constants.rs @@ -1,5 +1,3 @@ -pub const RECENT_ROOT_COUNT: u64 = 64; - /// Expected block production time in ms. pub const MIN_BLOCK_PRODUCTION_DELAY: u64 = 600; @@ -11,4 +9,3 @@ pub const MAX_BLOCK_WAIT_DELAY: u64 = 6_000; /// Depth of merkle tree pub const MERKLE_TREE_DEPTH: usize = 161; - diff --git a/pkg/node/src/errors.rs b/pkg/node/src/errors.rs index 250e534..ccf6677 100644 --- a/pkg/node/src/errors.rs +++ b/pkg/node/src/errors.rs @@ -1,132 +1,152 @@ -use std::num::ParseIntError; +// lint-long-file-override allow-max-lines=250 +use std::{error::Error as StdError, fmt, num::ParseIntError, path::PathBuf}; +use crate::sync; +use contextful::Contextful; +use element::Element; use libp2p::PeerId; +use node_interface::RpcError; use primitives::{block_height::BlockHeight, hash::CryptoHash}; -use tracing::error; -use zk_primitives::Element; -use crate::sync; +#[derive(Debug)] +pub struct TracingInitError(Box); + +impl fmt::Display for TracingInitError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +impl StdError for TracingInitError { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + Some(&*self.0) + } +} + +impl From> for TracingInitError { + fn from(inner: Box) -> Self { + Self(inner) + } +} pub type Result = std::result::Result; #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("invalid snapshot chunk, peer mismatch - accepted {accepted}, got {got}")] + #[error("[node] rpc error: {0}")] + Rpc(#[from] Contextful), + + #[error("[node] invalid snapshot chunk, peer mismatch - accepted {accepted}, got {got}")] SnapshotChunkPeerMismatch { accepted: Box, got: Box, }, - #[error("invalid proof")] - InvalidProof, - - #[error("note already spent: 0x{spent_note:x}")] + #[error("[node] note already spent: 0x{spent_note:x}")] NoteAlreadySpent { spent_note: Element, - failing_txn_hash: CryptoHash, + failing_txn_hash: Element, }, #[error( - "leaf 0x{inserted_leaf} was already inserted in the same block in transaction 0x{txn_hash}" + "[node] leaf 0x{inserted_leaf} was already inserted in the same block in transaction 0x{txn_hash}" )] LeafAlreadyInsertedInTheSameBlock { inserted_leaf: Element, - txn_hash: CryptoHash, - failing_txn_hash: CryptoHash, - }, - - #[error("output note already exists: 0x{output_note:x}")] - OutputNoteExists { output_note: Element }, - - #[error("invalid element, size exceeds modulus")] - InvalidElementSize { element: Element }, - - #[error( - "UTXO root is not recent enough: 0x{utxo_recent_root:x}, expected one of: {recent_roots:?}" - )] - UtxoRootIsNotRecentEnough { - utxo_recent_root: Element, - recent_roots: Vec, - txn_hash: CryptoHash, + txn_hash: Element, + failing_txn_hash: Element, }, - #[error("element is not in the tree")] - ElementNotInTree { element: Element }, - - #[error("element is not in any transaction of block {block_height}")] + #[error("[node] element is not in any transaction of block {block_height}")] ElementNotInTxn { element: Element, block_height: BlockHeight, }, - #[error("block height {block} not found")] + #[error("[node] block height {block} not found")] BlockNotFound { block: BlockHeight }, - #[error("block hash {block} not found")] + #[error("[node] block hash {block} not found")] BlockHashNotFound { block: CryptoHash }, - #[error("mint leaf is not in the contract")] - MintIsNotInTheContract { key: Element }, - - #[error("burn leaf is not in the contract")] - BurnIsNotInTheContract { key: Element }, - - #[error("burn 'to' address cannot be zero")] - BurnToAddressCannotBeZero, - - #[error("invalid mint or burn leaves")] + #[error("[node] invalid mint or burn leaves")] InvalidMintOrBurnLeaves, - #[error("invalid mint or burn leaves")] + #[error("[node] invalid mint or burn leaves")] InvalidSignature, - #[error("invalid transaction '{txn}'")] - InvalidTransaction { txn: CryptoHash }, + #[error("[node] invalid transaction '{txn}'")] + InvalidTransaction { txn: Element }, - #[error("invalid block root, got: {got}, expected: {expected}")] + #[error("[node] invalid block root, got: {got}, expected: {expected}")] InvalidBlockRoot { got: Element, expected: Element }, - #[error("failed to find transaction {txn}")] - TxnNotFound { txn: CryptoHash }, + /// A mint references a chain that is not configured on this node. + #[error("[node] unsupported chain id {chain_id}")] + UnsupportedChain { chain_id: u64 }, + + #[error("[node] transaction contains locked element {locked_element}")] + TransactionContainsLockedElement { locked_element: Element }, - #[error("invalid element: {element}")] + #[error("[node] invalid element: {element}")] FailedToParseElement { element: String, #[source] source: ParseIntError, }, - #[error("invalid hash: {hash}")] + #[error("[node] invalid hash: {hash}")] FailedToParseHash { hash: String, #[source] source: rustc_hex::FromHexError, }, - #[error("failed to get eth block number")] - FailedToGetEthBlockNumber(#[source] web3::Error), + #[error("[node] failed to get eth block number: {0}")] + FailedToGetEthBlockNumber(#[from] Contextful), + + #[error("[node] secp256k1 error: {0}")] + Secp256k1(#[from] Contextful), + + #[error("[node] web3 secp256k1 error: {0}")] + Web3Secp256k1(#[from] Contextful), + + #[error("[node] tracing setup error: {0}")] + Tracing(#[from] Contextful), + + #[error("[node] config error: {0}")] + Config(#[from] Contextful), + + #[error("[node] doomslug error: {0}")] + Doomslug(#[from] Contextful), + + #[error("[node] sync error: {0}")] + Sync(#[from] Contextful), + + #[error("[node] network error: {0}")] + Network(#[from] Contextful), - #[error("Invalid accept")] - DoomslugError(#[from] doomslug::Error), + #[error("[node] block store error: {0}")] + BlockStore(#[from] Contextful), - #[error("sync error: {0}")] - Sync(#[from] sync::Error), + #[error("[node] smirk error: {0}")] + Smirk(#[from] Contextful), - #[error("network error: {0}")] - Network(#[from] p2p2::Error), + #[error("[node] contracts error: {0}")] + Contracts(#[from] Contextful), - #[error("block store error: {0}")] - BlockStore(#[from] block_store::Error), + #[error("[node] io error: {0}")] + Io(#[from] Contextful), - #[error("smirk error: {0}")] - Smirk(#[from] smirk::storage::Error), + #[error("[node] unable to resolve home directory for path {path:?}")] + ConfigMissingHomeDir { path: PathBuf }, - #[error("contracts error: {0}")] - Contracts(#[from] contracts::Error), + #[error("[node] smirk collision error: {0}")] + Collision(#[from] Contextful), - #[error("io error: {0}")] - Io(#[from] std::io::Error), + #[error("[node] missing primary chain configuration")] + MissingPrimaryChainConfig, - #[error("smirk collision error: {0}")] - Collision(#[from] smirk::CollisionError), + #[error("[node] missing rollup contract for primary chain {chain_id}")] + MissingPrimaryRollupContract { chain_id: u64 }, } diff --git a/pkg/node/src/lib.rs b/pkg/node/src/lib.rs index 4641255..7c191ad 100644 --- a/pkg/node/src/lib.rs +++ b/pkg/node/src/lib.rs @@ -1,6 +1,5 @@ #![deny(clippy::disallowed_methods)] -#![feature(once_cell)] // this feature is fine beause it's since been stabilized -#![feature(bound_map)] // this feature is fine beause it's since been stabilized +#![allow(clippy::result_large_err)] mod block; mod cache; @@ -21,7 +20,6 @@ mod utxo; pub use crate::block::Block; pub use crate::errors::*; pub use crate::node::*; -pub use crate::rpc::routes::{configure_routes, State}; +pub use crate::rpc::routes::{State, configure_routes}; pub use crate::rpc::server::create_rpc_server; pub use crate::rpc::stats::TxnStats; -pub use crate::utxo::UtxoProof; diff --git a/pkg/node/src/mempool.rs b/pkg/node/src/mempool.rs index e17fa14..95d1836 100644 --- a/pkg/node/src/mempool.rs +++ b/pkg/node/src/mempool.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=400 use parking_lot::Mutex; use std::collections::{HashMap, HashSet, VecDeque}; use std::hash::Hash; @@ -5,9 +6,17 @@ use std::sync::Arc; use std::vec; use tokio::sync::oneshot; +use crate::Error; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum AddError { + Conflict(C), + DuplicateKey, +} + struct MempoolTxn { txn: Txn, - sender: Option>>, + sender: Option>>, changes: Vec, } @@ -54,32 +63,47 @@ where /// Add a transaction to the mempool, only adds key/txn if the key /// doesn't already exist in the mempool. This is used when other nodes /// send us a txn they have received from a client - pub fn add(&self, key: K, txn: V, changes: Vec) { - self._add(key, txn, changes, None); + pub fn add(&self, key: K, txn: V, changes: Vec) -> std::result::Result<(), AddError> { + self._add(key, txn, changes, None) } - /// Add a transaction to the mempool and wait for it to be committed. This will only - /// be called where the txn is directly submitted to this node from a client - // TODO: handle duplicate add_wait, so we properly await - pub async fn add_wait(&self, key: K, txn: V, changes: Vec) -> Result { - let (send, recv) = oneshot::channel::>(); - self._add(key, txn, changes, Some(send)); - - recv.await.expect("recv error") + /// Add a transaction to the mempool and obtain a receiver that resolves once the + /// transaction is committed. + // TODO: consider surfacing richer context for conflicts if needed + pub fn add_with_listener( + &self, + key: K, + txn: V, + changes: Vec, + ) -> std::result::Result>, AddError> { + let (send, recv) = oneshot::channel::>(); + match self._add(key, txn, changes, Some(send)) { + Ok(()) => Ok(recv), + Err(err) => Err(err), + } } - /// Internal add function, used by both add and add_wait + /// Internal add function, used by both `add` and `add_with_listener` fn _add( &self, key: K, txn: V, changes: Vec, - sender: Option>>, - ) { + sender: Option>>, + ) -> std::result::Result<(), AddError> { let mut state = self.state.lock(); + if let Some(conflict) = changes.iter().find(|change| { + state + .txns + .values() + .any(|txn| txn.changes.iter().any(|existing| existing == *change)) + }) { + return Err(AddError::Conflict(conflict.clone())); + } + if state.txns.contains_key(&key) { - return; + return Err(AddError::DuplicateKey); } state.txns.entry(key.clone()).or_insert(MempoolTxn { @@ -90,19 +114,21 @@ where // Add the key to the pool state.pool.push_back(key); + + Ok(()) } /// Commit a given transaction with key, removing it from the mempool /// and resolving any waiting futures (from add_txn_wait) #[allow(clippy::type_complexity)] - pub fn commit(&self, lease: L, keys_with_results: Vec<(&K, Result)>) { + pub fn commit(&self, lease: L, keys_with_results: Vec<(&K, Result)>) { let mut state = self.state.lock(); for (key, result) in keys_with_results { - if let Some(mem_txn) = state.txns.remove(key) { - if let Some(sender) = mem_txn.sender { - let _ = sender.send(result); - } + if let Some(mem_txn) = state.txns.remove(key) + && let Some(sender) = mem_txn.sender + { + let _ = sender.send(result); } if let Some(lease) = state.leased.get_mut(&lease) { @@ -155,11 +181,7 @@ where let key = if let Some(k) = k { k } else { key.clone() }; // Add it to the lease - state - .leased - .entry(lease.clone()) - .or_insert(HashSet::new()) - .insert(key); + state.leased.entry(lease.clone()).or_default().insert(key); } } @@ -189,7 +211,7 @@ where state .leased .entry(lease.clone()) - .or_insert(HashSet::new()) + .or_default() .insert(key.clone()); conflict_check.extend(changes); @@ -222,7 +244,7 @@ mod tests { #[test] fn test_add_txn() { let mempool = Mp::default(); - mempool.add("key1".to_string(), 42, vec![]); + mempool.add("key1".to_string(), 42, vec![]).unwrap(); { let state = mempool.state.lock(); @@ -230,7 +252,10 @@ mod tests { assert_eq!(state.txns.get("key1").unwrap().txn, 42); } - mempool.add("key1".to_string(), 24, vec![]); + assert_eq!( + mempool.add("key1".to_string(), 24, vec![]), + Err(AddError::DuplicateKey) + ); { let state = mempool.state.lock(); @@ -252,11 +277,11 @@ mod tests { let rt = Runtime::new().unwrap(); let mempool2 = mempool.clone(); - rt.spawn(async move { - mempool2 - .add_wait("key1".to_string(), 42, vec![]) - .await + let handle = rt.spawn(async move { + let receiver = mempool2 + .add_with_listener("key1".to_string(), 42, vec![]) .unwrap(); + receiver.await.unwrap().unwrap(); }); sleep(Duration::from_millis(100)); @@ -266,29 +291,32 @@ mod tests { assert_eq!(state.txns.len(), 1); assert_eq!(state.txns.get("key1").unwrap().txn, 42); } + + mempool.commit(1, vec![(&"key1".to_string(), Ok(()))]); + rt.block_on(handle).unwrap(); } #[test] fn test_commit_txn() { let mempool = Mp::default(); - mempool.add("key1".into(), 42, vec![]); - mempool.add("key2".into(), 24, vec![]); + mempool.add("key1".into(), 42, vec![]).unwrap(); + mempool.add("key2".into(), 24, vec![]).unwrap(); mempool.commit(1, vec![(&"key1".to_string(), Ok(()))]); let state = mempool.state.lock(); assert_eq!(state.txns.len(), 1); assert_eq!(state.pool.len(), 1); - assert!(state.txns.get("key1").is_none()); + assert!(!state.txns.contains_key("key1")); assert_eq!(state.txns.get("key2").unwrap().txn, 24); } #[test] fn test_lease_batch() { let mempool = Mp::default(); - mempool.add("key1".to_string(), 42, vec![]); - mempool.add("key2".to_string(), 24, vec![]); - mempool.add("key3".to_string(), 15, vec![]); + mempool.add("key1".to_string(), 42, vec![]).unwrap(); + mempool.add("key2".to_string(), 24, vec![]).unwrap(); + mempool.add("key3".to_string(), 15, vec![]).unwrap(); let batch = mempool.lease_batch(2, 2); assert_eq!(batch.len(), 2); @@ -310,25 +338,28 @@ mod tests { #[test] fn test_lease_with_duplicate_changes() { let mempool = Mp::default(); - mempool.add("key1".to_string(), 42, vec![1, 2, 3]); - mempool.add("key2".to_string(), 24, vec![3, 4, 5]); - mempool.add("key3".to_string(), 15, vec![6, 7, 8]); + mempool.add("key1".to_string(), 42, vec![1, 2, 3]).unwrap(); + assert!(matches!( + mempool.add("key2".to_string(), 24, vec![3, 4, 5]), + Err(AddError::Conflict(3)) + )); + mempool.add("key3".to_string(), 15, vec![6, 7, 8]).unwrap(); let batch = mempool.lease_batch(2, 3); assert_eq!(batch.len(), 2); { let state = mempool.state.lock(); - assert_eq!(state.pool.len(), 1); + assert_eq!(state.pool.len(), 0); } } #[test] fn test_partial_commit_followed_by_lease() { let mempool = Mp::default(); - mempool.add("key1".to_string(), 1, vec![1]); - mempool.add("key2".to_string(), 2, vec![2]); - mempool.add("key3".to_string(), 3, vec![3]); + mempool.add("key1".to_string(), 1, vec![1]).unwrap(); + mempool.add("key2".to_string(), 2, vec![2]).unwrap(); + mempool.add("key3".to_string(), 3, vec![3]).unwrap(); let batch = mempool.lease_batch(2, 3); assert_eq!(batch.len(), 3); diff --git a/pkg/node/src/network.rs b/pkg/node/src/network.rs index 93bb6de..09f99cf 100644 --- a/pkg/node/src/network.rs +++ b/pkg/node/src/network.rs @@ -1,10 +1,10 @@ use crate::types::BlockHeight; -use crate::utxo::UtxoProof; use crate::{block::Block, types::SnapshotId}; use borsh::{BorshDeserialize, BorshSerialize}; use derivative::Derivative; use doomslug::Approval; -use smirk::Element; +use element::Element; +use zk_primitives::UtxoProof; #[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] pub enum NetworkEvent { diff --git a/pkg/node/src/network_handler.rs b/pkg/node/src/network_handler.rs index 5bfd1e9..d36dc87 100644 --- a/pkg/node/src/network_handler.rs +++ b/pkg/node/src/network_handler.rs @@ -1,6 +1,5 @@ use crate::network::{NetworkEvent, SnapshotAccept, SnapshotOffer, SnapshotRequest}; -use crate::node::NodeShared; -use eyre::Context; +use crate::{NodeShared, Result}; use libp2p::PeerId; use p2p2::Network; use std::sync::Arc; @@ -12,7 +11,9 @@ pub fn network_handler( ) -> JoinHandle<()> { tokio::spawn(async move { loop { - let Some((network_peer_id, event)) = network.next().await else { continue }; + let Some((network_peer_id, event)) = network.next().await else { + continue; + }; tracing::debug!(network_peer_id = ?network_peer_id, event = ?event, "network event"); if let Err(e) = handle_event(&node, network_peer_id, event).await { @@ -22,57 +23,42 @@ pub fn network_handler( }) } -async fn handle_event( - node: &NodeShared, - peer: PeerId, - event: NetworkEvent, -) -> color_eyre::Result<()> { - use NetworkEvent as NE; - +async fn handle_event(node: &NodeShared, peer: PeerId, event: NetworkEvent) -> Result<()> { match event { - NE::Approval(approval) => node - .receive_accept(&approval) - .await - .context("Accept failed")?, + NetworkEvent::Approval(approval) => node.receive_accept(&approval).await?, - NE::Block(block) => { - node.receive_proposal(block) - .context("Failed to process block")?; + NetworkEvent::Block(block) => { + node.receive_proposal(block)?; node.ticker.tick(); } - NE::Transaction(txn) => node - .receive_transaction(txn) - .await - .context("Transaction failed")?, + NetworkEvent::Transaction(txn) => node.receive_transaction(txn).await?, - NE::SnapshotRequest(SnapshotRequest { + NetworkEvent::SnapshotRequest(SnapshotRequest { snapshot_id, from_height, to_height, kind, - }) => node - .receive_snapshot_request(peer, snapshot_id, from_height, to_height, kind) - .await - .context("Snapshot request failed")?, + }) => { + node.receive_snapshot_request(peer, snapshot_id, from_height, to_height, kind) + .await? + } - NE::SnapshotOffer(SnapshotOffer { snapshot_id }) => node - .receive_snapshot_offer(peer, snapshot_id) - .context("Snapshot offer failed")?, + NetworkEvent::SnapshotOffer(SnapshotOffer { snapshot_id }) => { + node.receive_snapshot_offer(peer, snapshot_id)?; + } - NE::SnapshotChunk(sc) => node - .receive_snapshot_chunk(peer, sc) - .context("Snapshot chunk failed")?, + NetworkEvent::SnapshotChunk(sc) => node.receive_snapshot_chunk(peer, sc)?, - NE::SnapshotAccept(SnapshotAccept { + NetworkEvent::SnapshotAccept(SnapshotAccept { snapshot_id, from_height, to_height, kind, - }) => node - .receive_snapshot_accept(peer, snapshot_id, from_height, to_height, kind) - .await - .context("Snapshot accept failed")?, + }) => { + node.receive_snapshot_accept(peer, snapshot_id, from_height, to_height, kind) + .await? + } } Ok(()) diff --git a/pkg/node/src/node.rs b/pkg/node/src/node.rs index 4260337..adffa04 100644 --- a/pkg/node/src/node.rs +++ b/pkg/node/src/node.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=700 use crate::block::Block; use crate::cache::BlockCache; use crate::config::Config; @@ -10,14 +11,17 @@ use crate::mempool::Mempool; use crate::network::NetworkEvent; use crate::network_handler::network_handler; use crate::node::load::LoadedData; +use crate::sync::SyncWorker; use crate::types::BlockHeight; -use crate::utxo::UtxoProof; use crate::{sync, util}; -use block_store::{BlockListOrder, BlockStore, StoreList}; +use block_store::{BlockListOrder, BlockStore, ElementHistoryIndexEntry, StoreList}; +use contextful::ResultContextExt as _; use contracts::RollupContract; use doomslug::{Approval, ApprovalContent, ApprovalStake, ApprovalValidated, Doomslug}; +use element::Element; use futures::Stream; use libp2p::PeerId; +use node_interface::{ElementData, RpcError}; use p2p2::Network; use parking_lot::{Mutex, RwLock}; use primitives::hash::CryptoHash; @@ -26,17 +30,18 @@ use primitives::peer::{self, Address, PeerIdSigner}; use primitives::tick_worker::TickWorker; use prover::smirk_metadata::SmirkMetadata; use serde::{Deserialize, Serialize}; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::net::IpAddr; use std::ops::RangeBounds; use std::pin::Pin; use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::sync::mpsc; -use tokio_stream::wrappers::UnboundedReceiverStream; use tokio_stream::StreamExt; +use tokio_stream::wrappers::UnboundedReceiverStream; use tracing::{debug, error, info, instrument}; -use zk_primitives::Element; +use zk_circuits::BbBackend; +use zk_primitives::UtxoProof; pub use self::block_format::BlockFormat; pub use self::txn_format::TxnFormat; @@ -86,7 +91,7 @@ pub struct NodeShared { /// Ethereum private key local_peer: PeerIdSigner, - rollup_contract: RollupContract, + rollup_contracts: Arc>, /// Config config: Config, @@ -95,7 +100,7 @@ pub struct NodeShared { doomslug: Arc>, /// Mempool for storing pending txns - mempool: Mempool>, + mempool: Mempool>, // Block cache (unconfirmed blocks) pub(crate) block_cache: Arc>, @@ -126,6 +131,8 @@ pub struct NodeShared { /// /// If empty, whitelisting is disabled (i.e. all IPs are allowed) pub whitelisted_ips: HashSet, + + pub bb_backend: Arc, } pub struct NodeSharedArc(Arc); @@ -139,11 +146,23 @@ pub struct NodeSharedState { listeners: Vec>>, } +#[derive(Debug, Clone, Copy)] +pub(crate) struct ElementSeenInfo { + #[expect(dead_code)] + pub input_height: Option, + pub output_height: BlockHeight, + #[expect(dead_code)] + pub input_block_hash: Option, + pub output_block_hash: CryptoHash, + pub spent: bool, +} + impl Node { pub fn new( local_peer: PeerIdSigner, - rollup_contract: RollupContract, + rollup_contracts: Arc>, config: Config, + bb_backend: Arc, ) -> Result { info!("Mode: {:?}", config.mode); info!( @@ -158,7 +177,9 @@ impl Node { block: initial_block, } = Self::load_db_and_smirk(&config)?; - block_store.migrate()?; + block_store + .migrate() + .context("run block store migrations during node startup")?; let block_store = Arc::new(block_store); let notes_tree = Arc::new(RwLock::new(persistent_tree)); @@ -185,13 +206,23 @@ impl Node { vec![config.p2p.laddr.clone()].into_iter(), config.p2p.dial.clone().into_iter(), config.p2p.whitelisted_ips.clone(), - )?; + ) + .context("initialize P2P network stack with configured addresses")?; let (sync_worker_sender, sync_worker_receiver) = mpsc::unbounded_channel(); + let primary_chain_id = config + .primary_chain_id() + .ok_or(Error::MissingPrimaryChainConfig)?; + let primary_rollup_contract = rollup_contracts.get(&primary_chain_id).cloned().ok_or( + Error::MissingPrimaryRollupContract { + chain_id: primary_chain_id, + }, + )?; + let node_shared = Arc::new(NodeShared { local_peer, - rollup_contract: rollup_contract.clone(), + rollup_contracts: Arc::clone(&rollup_contracts), mempool: Mempool::default(), block_store, block_cache, @@ -206,11 +237,12 @@ impl Node { }), sync_worker: sync::SyncWorkerChannel(sync_worker_sender.clone()), whitelisted_ips: config.p2p.whitelisted_ips, + bb_backend, }); - let sync_worker = crate::sync::SyncWorker::new( + let sync_worker = SyncWorker::new( Arc::clone(&node_shared), - rollup_contract, + Some(primary_rollup_contract), config.sync_chunk_size, config.fast_sync_threshold, Duration::from_millis(config.sync_timeout_ms), @@ -242,6 +274,11 @@ impl Node { } } + // Run the ticker + self.shared + .ticker + .run(NodeSharedArc(Arc::clone(&self.shared))); + // Wait for the handlers tokio::select! { res = self.sync_worker.run() => { @@ -249,14 +286,6 @@ impl Node { tracing::error!(?err, "Sync worker ended"); } } - res = self.shared.ticker.run(NodeSharedArc(Arc::clone(&self.shared))) => { - match res { - Ok(()) => {} - Err(err) => { - tracing::error!(?err, "Commit ticker ended"); - } - } - } } } } @@ -282,18 +311,38 @@ impl NodeShared { &self.notes_tree } - #[must_use] - pub(crate) fn is_validator_for_height(&self, height: BlockHeight) -> bool { + pub(crate) fn is_validator_for_height(&self, height: BlockHeight) -> Result { if self.config.mode != Mode::Validator { - return false; + return Ok(false); } - // Check if I am a validator in Ethereum for the given height - self.rollup_contract + let contract = self.primary_rollup_contract_required()?; + + Ok(contract .validators_for_height(height.0) .into_iter() .map(peer::Address::from) - .any(|p| self.local_peer.address() == p) + .any(|p| self.local_peer.address() == p)) + } + + pub(super) fn primary_rollup_contract(&self) -> Option<&RollupContract> { + let chain_id = self.config.primary_chain_id()?; + self.rollup_contracts.get(&chain_id) + } + + pub(super) fn primary_rollup_contract_required(&self) -> Result<&RollupContract> { + let chain_id = self + .config + .primary_chain_id() + .ok_or(Error::MissingPrimaryChainConfig)?; + + self.rollup_contracts + .get(&chain_id) + .ok_or(Error::MissingPrimaryRollupContract { chain_id }) + } + + pub(super) fn rollup_contract_for_chain(&self, chain_id: u64) -> Option<&RollupContract> { + self.rollup_contracts.get(&chain_id) } pub(crate) fn get_merkle_paths(&self, elements: &[Element]) -> Result>> { @@ -305,7 +354,8 @@ impl NodeShared { .map(|e| { // Check the element is in the tree if !tree.contains_element(e) { - return Err(Error::ElementNotInTree { element: *e }); + Err::, _>(RpcError::ElementNotFound(ElementData { element: *e })) + .context("merkle path requested for element not present in notes tree")?; } // Return the path @@ -369,11 +419,15 @@ impl NodeShared { // 1. Check if the accept is from a valid validator // 2. Check if the accept is for the current proposal // 3. Check if I am the leader of the accept - let approval: ApprovalValidated = approval_message.clone().try_into()?; + let approval: ApprovalValidated = approval_message + .clone() + .try_into() + .context("convert approval message into validated doomslug approval")?; // Get validator stakes - let stakes = self - .rollup_contract + let contract = self.primary_rollup_contract_required()?; + + let stakes = contract .validators_for_height(approval_message.content.target_height) .into_iter() .map(|address| { @@ -402,13 +456,22 @@ impl NodeShared { pub fn get_leader_for_block_height(&self, height: BlockHeight) -> Address { // TODO: will validators be in the same order for all nodes? - let validators = self.rollup_contract.validators_for_height(height.0); + let Some(contract) = self.primary_rollup_contract() else { + return self.self_peer(); + }; + + let validators = contract.validators_for_height(height.0); + if validators.is_empty() { + return self.self_peer(); + } let leader_index = height.0 % validators.len() as u64; Address::from(validators[leader_index as usize]) } pub(crate) async fn handle_out_of_sync(&self) -> Result<()> { - self.sync_worker.out_of_sync(self.max_height())?; + self.sync_worker + .out_of_sync(self.max_height()) + .context("check whether node is out of sync before scheduling recovery")?; Ok(()) } @@ -419,22 +482,23 @@ impl NodeShared { order: BlockListOrder, ) -> impl StoreList> + '_ { self.block_store.list(height_range, order).map(|r| { - let (_, block) = r?; + let (_, block) = r.context("materialize block entry from store list during fetch")?; Ok(block) }) } - pub fn fetch_blocks_paginated( - &self, - cursor: &Option>, + pub fn fetch_blocks_paginated<'a>( + &'a self, + cursor: &'a Option>, order: BlockListOrder, limit: usize, - ) -> Result> + '_> { + ) -> Result> + 'a> { Ok(self .block_store - .list_paginated(cursor, order, limit)? + .list_paginated(cursor, order, limit) + .context("paginate block store listing")? .map(|r| { - let (_, block) = r?; + let (_, block) = r.context("materialize paginated block entry")?; Ok(block) })) } @@ -447,38 +511,77 @@ impl NodeShared { self.block_store .list_non_empty(height_range, order) .map(|r| { - let (_, block) = r?; + let (_, block) = r.context("materialize non-empty block entry from store")?; Ok(block) }) } - pub fn fetch_blocks_non_empty_paginated( - &self, - cursor: &Option>, + pub fn fetch_blocks_non_empty_paginated<'a>( + &'a self, + cursor: &'a Option>, order: BlockListOrder, limit: usize, - ) -> Result> + '_> { + ) -> Result> + 'a> { Ok(self .block_store - .list_non_empty_paginated(cursor, order, limit)? + .list_non_empty_paginated(cursor, order, limit) + .context("paginate non-empty block listing")? .map(|r| { - let (_, block) = r?; + let (_, block) = r.context("materialize paginated non-empty block entry")?; Ok(block) })) } pub(crate) fn get_block(&self, height: BlockHeight) -> Result> { - Ok(self.block_store.get(height)?) + Ok(self + .block_store + .get(height) + .context("fetch block by height from block store")?) } pub(crate) fn get_block_by_hash(&self, hash: CryptoHash) -> Result> { - let Some(block_height) = self.block_store.get_block_height_by_hash(hash.into_inner())? else { + let Some(block_height) = self + .block_store + .get_block_height_by_hash(hash.into_inner()) + .context("resolve block height by block hash")? + else { return Ok(None); }; self.get_block(block_height) } + /// Returns info about when an element was first seen (as an output), and whether it was later + /// spent (seen as an input). If the element has never been seen, returns None. + pub(crate) fn get_element_seen_info( + &self, + element: Element, + ) -> Result> { + let (input_hist, output_hist) = self + .block_store + .get_element_history(element) + .context("fetch element history from block store")?; + if let Some(out) = output_hist { + let spent = input_hist.is_some(); + Ok(Some(ElementSeenInfo { + input_height: input_hist.as_ref().map(|h| h.block_height), + output_height: out.block_height, + input_block_hash: input_hist.map(|h| h.block_hash), + output_block_hash: out.block_hash, + spent, + })) + } else { + Ok(None) + } + } + + pub(crate) fn element_history_range( + &self, + range: impl RangeBounds, + ) -> Vec { + self.block_store.element_history_range(range) + } + pub(crate) async fn commit_stream( &self, from_height: Option, @@ -514,7 +617,10 @@ impl NodeShared { } pub(crate) fn get_txn(&self, txn_hash: [u8; 32]) -> Result> { - let txn = self.block_store.get_txn_by_hash(txn_hash)?; + let txn = self + .block_store + .get_txn_by_hash(txn_hash) + .context("fetch transaction by hash from block store")?; Ok(txn.map(|TxnFormat::V1(txn, metadata)| (txn, metadata))) } diff --git a/pkg/node/src/node/block.rs b/pkg/node/src/node/block.rs index cd0f890..7ee438c 100644 --- a/pkg/node/src/node/block.rs +++ b/pkg/node/src/node/block.rs @@ -1,17 +1,17 @@ -use either::Either; +use contextful::ResultContextExt as _; use prover::smirk_metadata::SmirkMetadata; -use smirk::{Batch, Element}; +use smirk::Batch; use tracing::instrument; use crate::{ + Error, NodeShared, PersistentMerkleTree, Result, block::{Block, BlockState}, types::BlockHeight, - Error, NodeShared, PersistentMerkleTree, Result, }; impl NodeShared { #[instrument(skip_all)] - pub(super) fn validate_block(&self, block: &Block) -> Result<()> { + pub(super) async fn validate_block(&self, block: &Block) -> Result<()> { if self .config .bad_blocks @@ -33,7 +33,13 @@ impl NodeShared { block .content - .validate(self.config.mode, &self.block_store, &self.notes_tree.read())?; + .validate( + &*self.bb_backend, + self.config.mode, + &self.block_store, + &self.notes_tree, + ) + .await?; Ok(()) } @@ -43,33 +49,27 @@ impl NodeShared { notes_tree: &mut PersistentMerkleTree, state: &BlockState, current_height: BlockHeight, - ignore_collisions: bool, ) -> Result<()> { - let leaves = state + let insert_leaves = state .txns .iter() - .flat_map(|txn| txn.leaves()) - .filter(|e| *e != Element::ZERO); + .flat_map(|txn| txn.public_inputs.output_commitments) + .filter(|e| !e.is_zero()); - for leaf in leaves.clone() { - if !ignore_collisions && notes_tree.tree().contains_element(&leaf) { - panic!("Double-spend detected. This should never happen, this should have been caught before commit"); - } - } + let remove_leaves = state + .txns + .iter() + .flat_map(|txn| txn.public_inputs.input_commitments) + .filter(|e| !e.is_zero()); let metadata = SmirkMetadata::inserted_in(current_height.0); - let leaves_with_height = leaves.map(|e| (e, metadata.clone())); - let leaves_with_height_maybe_ignoring_collisions = match ignore_collisions { - false => Either::Left(leaves_with_height), - true => Either::Right( - // If we're ignoring collisions, we need to filter out the leaves that are already in the tree, - // otherwise the insert_batch would fail. - leaves_with_height.filter(|(leaf, _)| !notes_tree.tree().contains_element(leaf)), - ), - }; - let batch = Batch::from_entries(leaves_with_height_maybe_ignoring_collisions)?; + let leaves_with_height = insert_leaves.map(|e| (e, metadata.clone())); + let batch = Batch::from_entries(leaves_with_height, remove_leaves.collect::>()) + .context("construct smirk batch for block application")?; - notes_tree.insert_batch(batch)?; + notes_tree + .insert_batch(batch) + .context("apply smirk batch to persistent notes tree")?; Ok(()) } } diff --git a/pkg/node/src/node/block_format.rs b/pkg/node/src/node/block_format.rs index 209280f..9bf2857 100644 --- a/pkg/node/src/node/block_format.rs +++ b/pkg/node/src/node/block_format.rs @@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use primitives::block_height::BlockHeight; use wire_message::WireMessage; -use crate::{block::Block, TxnFormat}; +use crate::{TxnFormat, block::Block}; use super::txn_format::TxnMetadata; diff --git a/pkg/node/src/node/load.rs b/pkg/node/src/node/load.rs index 8e7c91c..4489a67 100644 --- a/pkg/node/src/node/load.rs +++ b/pkg/node/src/node/load.rs @@ -1,12 +1,13 @@ use std::{path::Path, sync::OnceLock}; use block_store::BlockStore; -use smirk::Element; +use contextful::ResultContextExt as _; +use element::Element; use tracing::info; use crate::{ - block::Block, config::Config, constants::MERKLE_TREE_DEPTH, types::BlockHeight, BlockFormat, - Node, NodeShared, PersistentMerkleTree, Result, + BlockFormat, Node, NodeShared, PersistentMerkleTree, Result, block::Block, config::Config, + constants::MERKLE_TREE_DEPTH, types::BlockHeight, }; pub(super) struct LoadedData { @@ -21,6 +22,7 @@ fn empty_tree_hash() -> Element { } impl Node { + #[tracing::instrument(skip_all)] pub(super) fn load_db_and_smirk(config: &Config) -> Result { let db_path = &config.db_path.join("latest"); info!("Loading DB from: {}", db_path.to_str().unwrap()); @@ -28,10 +30,15 @@ impl Node { let smirk_path = config.smirk_path.join("latest"); info!("Loading Smirk from: {}", &smirk_path.to_str().unwrap()); - let block_store = BlockStore::create_or_load(db_path)?; - let mut persistent_tree = smirk::storage::Persistent::load(&smirk_path)?; + let block_store = BlockStore::create_or_load(db_path) + .context("load block store from latest database path")?; + let mut persistent_tree = smirk::storage::Persistent::load(&smirk_path) + .context("load persistent smirk tree from latest path")?; - let Some(max_height) = block_store.get_max_height()? else { + let Some(max_height) = block_store + .get_max_height() + .context("fetch max block height from block store")? + else { info!( smirk_root_hash = ?persistent_tree.tree().root_hash(), "No blocks found in the block store, resetting smirk and starting from genesis" @@ -40,8 +47,8 @@ impl Node { drop(persistent_tree); Self::reset_db_and_smirk(None, Some(&config.smirk_path))?; - let persistent_tree = - smirk::storage::Persistent::load(smirk_path)?; + let persistent_tree = smirk::storage::Persistent::load(&smirk_path) + .context("reload persistent smirk tree after reset")?; debug_assert_eq!(persistent_tree.tree().root_hash(), empty_tree_hash()); @@ -54,7 +61,11 @@ impl Node { return Ok(data); }; - let block = block_store.get(max_height)?.unwrap().into_block(); + let block = block_store + .get(max_height) + .context("fetch latest block from block store")? + .unwrap() + .into_block(); if persistent_tree.tree().root_hash() == block.content.state.root_hash { let data = LoadedData { @@ -67,7 +78,8 @@ impl Node { } let previous_block = block_store - .get(BlockHeight(max_height.0 - 1))? + .get(BlockHeight(max_height.0 - 1)) + .context("fetch previous block during crash recovery")? .unwrap() .into_block(); @@ -83,7 +95,6 @@ impl Node { &mut persistent_tree, &block.content.state, max_height, - config.bad_blocks.contains(&max_height), )?; assert!(persistent_tree.tree().root_hash() == block.content.state.root_hash); @@ -107,10 +118,15 @@ impl Node { Self::reset_db_and_smirk(Some(&config.db_path), Some(&config.smirk_path))?; - let block_store = BlockStore::create_or_load(db_path)?; - let persistent_tree = smirk::storage::Persistent::load(&smirk_path)?; + let block_store = + BlockStore::create_or_load(db_path).context("reload block store after full reset")?; + let persistent_tree = smirk::storage::Persistent::load(&smirk_path) + .context("reload persistent smirk tree after full reset")?; - debug_assert!(block_store.get_max_height()?.is_none()); + let max_height = block_store + .get_max_height() + .context("verify block store empty after reset")?; + debug_assert!(max_height.is_none()); debug_assert_eq!(persistent_tree.tree().root_hash(), empty_tree_hash(),); let data = LoadedData { @@ -123,6 +139,7 @@ impl Node { } /// Moves current db and smirk to old-{unix-timestamp-millis}-{random} + #[tracing::instrument(skip_all)] fn reset_db_and_smirk(db_path: Option<&Path>, smirk_path: Option<&Path>) -> Result<()> { let timestamp = chrono::Utc::now().timestamp_millis(); let random = rand::random::(); @@ -130,13 +147,15 @@ impl Node { if let Some(db_path) = db_path { let new_db_path = db_path.join(&new_dir_name); - std::fs::rename(db_path.join("latest"), &new_db_path)?; + std::fs::rename(db_path.join("latest"), &new_db_path) + .context("rename latest db directory into timestamped backup")?; info!("Moved db to {:?}", new_db_path); } if let Some(smirk_path) = smirk_path { let new_smirk_path = smirk_path.join(&new_dir_name); - std::fs::rename(smirk_path.join("latest"), &new_smirk_path)?; + std::fs::rename(smirk_path.join("latest"), &new_smirk_path) + .context("rename latest smirk directory into timestamped backup")?; info!("Moved smirk to {:?}", new_smirk_path); } diff --git a/pkg/node/src/node/proposal.rs b/pkg/node/src/node/proposal.rs index d4041b7..d3e48c8 100644 --- a/pkg/node/src/node/proposal.rs +++ b/pkg/node/src/node/proposal.rs @@ -1,17 +1,22 @@ +// lint-long-file-override allow-max-lines=300 use std::{sync::Arc, time::Instant}; +use contextful::ResultContextExt as _; use doomslug::ApprovalValidated; use primitives::hash::CryptoHash; -use smirk::Element; use tracing::{info, instrument, warn}; use crate::{ - block::{Block, BlockContent, BlockHeader, BlockState}, network::NetworkEvent, node::block_format::BlockMetadata, types::BlockHeight, BlockFormat, Error, Mode, NodeShared, Result + BlockFormat, Error, Mode, NodeShared, Result, + block::{Block, BlockContent, BlockHeader, BlockState}, + network::NetworkEvent, + node::block_format::BlockMetadata, + types::BlockHeight, }; impl NodeShared { #[instrument(skip(self))] - pub(crate) fn commit_proposal(&self, block: Block) -> Result<()> { + pub(crate) fn commit_proposal(&self, block: Block) -> Result<()> { let state = &block.content.state; let height = block.content.header.height; @@ -32,31 +37,37 @@ impl NodeShared { }) .collect::>>()?; - for txn in &block.content.state.txns { + for utxo_proof in &block.content.state.txns { info!( - hash = format!("0x{}", txn.hash()), - recent_root = format!("0x{:x}", txn.recent_root), - mb_hash = format!("0x{:x}", txn.mb_hash), - mb_value = format!("0x{:x}", txn.mb_value), - input_leaves = ?txn.input_leaves.iter().map(|l| format!("0x{l:x}")).collect::>(), - output_leaves = ?txn.output_leaves.iter().map(|l| format!("0x{l:x}")).collect::>(), + hash = format!("0x{}", utxo_proof.hash()), + kind = ?utxo_proof.kind(), + kind_messages = ?utxo_proof.kind_messages(), + messages = ?utxo_proof.public_inputs.messages.iter().map(|l| format!("0x{l:x}")).collect::>(), + input_leaves = ?utxo_proof.public_inputs.input_commitments.iter().map(|l| format!("0x{l:x}")).collect::>(), + output_leaves = ?utxo_proof.public_inputs.output_commitments.iter().map(|l| format!("0x{l:x}")).collect::>(), "Committing transaction" ) } - // Validate leaves before commit - let leaves = state + // Input commitments (to be removed from the tree) + let block_input_commitments = state .txns .iter() - .flat_map(|txn| txn.leaves()) - .filter(|e| *e != Element::ZERO); - - let skip_validation = self.config.bad_blocks.contains(&height); - { - for leaf in leaves { - if !skip_validation && self.notes_tree.read().tree().contains_element(&leaf) { - panic!("Double-spend detected. This should never happen, this should have been caught before commit"); - } + .flat_map(|utxo_proof| utxo_proof.public_inputs.input_commitments) + .filter(|l: &_| !l.is_zero()) + .collect::>(); + + // Input notes should be in the tree + for input_commitment in block_input_commitments { + if !self + .notes_tree + .read() + .tree() + .contains_element(&input_commitment) + { + panic!( + "Double-spend detected -> input note NOT in tree. This should never happen, this should have been caught before commit" + ); } } @@ -64,30 +75,35 @@ impl NodeShared { // If we exit after commiting to block store, // but before commiting to notes tree, we // can detect it by checking the previous block's root hash. - self.block_store.set( - &BlockFormat::V2(block.clone(), BlockMetadata { - timestamp_unix_s: Some(commit_time.timestamp() as u64) - }), - )?; + self.block_store + .set(&BlockFormat::V2( + block.clone(), + BlockMetadata { + timestamp_unix_s: Some(commit_time.timestamp() as u64), + }, + )) + .context("persist committed block metadata to block store")?; - Self::apply_block_to_tree(&mut self.notes_tree.write(), state, height, skip_validation)?; + Self::apply_block_to_tree(&mut self.notes_tree.write(), state, height)?; let block = Arc::new(block); // Commit changes in mempool (releasing unused txns and removing used ones). This will // also release all requests that were waiting for these txns to be committed. - self.mempool - .commit(height, keys.iter().map(|k| (k, Ok(Arc::clone(&block)))).collect()); + self.mempool.commit( + height, + keys.iter().map(|k| (k, Ok(Arc::clone(&block)))).collect(), + ); // Notify any commit listeners let listeners = &mut self.state.lock().listeners; listeners.retain(|tx| tx.send(Arc::clone(&block)).is_ok()); Ok(()) - } + } - #[instrument(skip(self))] - pub fn receive_proposal(&self, block: Block) -> Result<()> { + #[instrument(skip(self))] + pub fn receive_proposal(&self, block: Block) -> Result<()> { if self.config.mode == Mode::Validator { panic!("This function should not be called by the validator"); } @@ -114,8 +130,7 @@ impl NodeShared { // Notify the worker Ok(()) - } - + } #[instrument(skip_all, fields(height))] pub(crate) async fn create_proposal( @@ -148,15 +163,28 @@ impl NodeShared { utxos.into_iter().map(|(_, utxo)| utxo).collect::>() }; - let leaves = txns.iter().flat_map(|utxo| utxo.leaves()).filter(|leaf| leaf != &Element::ZERO).collect::>(); + let insert_leaves = txns + .iter() + .flat_map(|utxo| utxo.public_inputs.output_commitments) + .filter(|l| !l.is_zero()) + .collect::>(); + let remove_leaves = txns + .iter() + .flat_map(|utxo| utxo.public_inputs.input_commitments) + .filter(|l| !l.is_zero()) + .collect::>(); - let new_root_hash = match leaves.is_empty() { + let new_root_hash = match insert_leaves.is_empty() && remove_leaves.is_empty() { true => { // Root is unchanged self.notes_tree.read().tree().root_hash() - }, + } false => { - self.notes_tree.read().tree().root_hash_with(&leaves) + // TODO_NOIR: we also need to remove some elements from the tree too + self.notes_tree + .read() + .tree() + .root_hash_with(&insert_leaves, &remove_leaves) } }; @@ -174,7 +202,7 @@ impl NodeShared { // Create a signed block let block = block_content.to_block(&self.local_peer); - let validate_res = self.validate_block(&block); + let validate_res = self.validate_block(&block).await; match &validate_res { Ok(()) => {} Err(Error::LeafAlreadyInsertedInTheSameBlock { @@ -216,44 +244,31 @@ impl NodeShared { )], ); } - Err(Error::UtxoRootIsNotRecentEnough { utxo_recent_root, recent_roots, txn_hash }) => { - let utxo_recent_root = *utxo_recent_root; - let recent_roots = recent_roots.clone(); - let txn_hash = *txn_hash; - self.mempool.commit( - height, - vec![( - &txn_hash, - Err(Error::UtxoRootIsNotRecentEnough { - utxo_recent_root, - recent_roots, - txn_hash, - }), - )], - ); - } Err(_err) => { // One of the transactions failed, but we don't know which one. // Send the same error to each of them. let txn_iter = block.content.state.txns.iter(); - let txn_errors = txn_iter - .clone() - .map(|_tx| - // This is not optimal, but it's required because Error is not clone-able. - self.validate_block(&block) - ) - .collect::>(); - let txn_keys = txn_iter - .map(|tx| tx.hash()) - .collect::>(); + let mut txn_errors = Vec::new(); + for _ in txn_iter.clone() { + // This is not optimal, but it's required because Error is not clone-able. + txn_errors.push(self.validate_block(&block).await); + } + let txn_keys = txn_iter.map(|tx| tx.hash()).collect::>(); self.mempool.commit( height, txn_errors .into_iter() .enumerate() - .map(|(i, err)| (&txn_keys[i], err.map(|_| unreachable!("We know the result is Err in this match branch")))) + .map(|(i, err)| { + ( + &txn_keys[i], + err.map(|_| { + unreachable!("We know the result is Err in this match branch") + }), + ) + }) .collect::>(), ); } @@ -271,5 +286,5 @@ impl NodeShared { self.send_all(NetworkEvent::Block(block.clone())).await; Ok(block) - } + } } diff --git a/pkg/node/src/node/snapshot.rs b/pkg/node/src/node/snapshot.rs index 2fe303c..6d20fdc 100644 --- a/pkg/node/src/node/snapshot.rs +++ b/pkg/node/src/node/snapshot.rs @@ -1,12 +1,13 @@ use std::sync::Arc; +use contextful::ResultContextExt as _; use libp2p::PeerId; use tracing::{info, instrument}; use crate::{ + NodeShared, Result, network::{SnapshotChunk, SnapshotKind}, types::{BlockHeight, SnapshotId}, - NodeShared, Result, }; use super::sync; @@ -20,7 +21,9 @@ impl NodeShared { snapshot_id: SnapshotId, ) -> Result<()> { info!("Received snapshot offer"); - self.sync_worker.snapshot_offer(peer, snapshot_id)?; + self.sync_worker + .snapshot_offer(peer, snapshot_id) + .context("process incoming snapshot offer from peer")?; Ok(()) } @@ -29,7 +32,9 @@ impl NodeShared { #[instrument(skip(self))] pub(crate) fn receive_snapshot_chunk(&self, peer: PeerId, sc: SnapshotChunk) -> Result<()> { info!("Received snapshot chunk"); - self.sync_worker.snapshot_chunk(peer, sc)?; + self.sync_worker + .snapshot_chunk(peer, sc) + .context("process incoming snapshot chunk from peer")?; Ok(()) } @@ -46,7 +51,8 @@ impl NodeShared { ) -> Result<()> { info!("Received snapshot request"); sync::handle_snapshot_request(self, peer, snapshot_id, from_height, to_height, kind) - .await?; + .await + .context("handle snapshot request from peer")?; Ok(()) } @@ -71,7 +77,8 @@ impl NodeShared { to_height, kind, ) - .await?; + .await + .context("handle snapshot accept from peer")?; Ok(()) } diff --git a/pkg/node/src/node/tick_worker.rs b/pkg/node/src/node/tick_worker.rs index 27df3f5..dc21b22 100644 --- a/pkg/node/src/node/tick_worker.rs +++ b/pkg/node/src/node/tick_worker.rs @@ -5,7 +5,7 @@ use doomslug::ApprovalContent; use primitives::tick_worker::TickWorkerTick; use tracing::{error, warn}; -use crate::{types::BlockHeight, Mode, NodeSharedArc}; +use crate::{Mode, NodeSharedArc, types::BlockHeight}; #[async_trait] impl TickWorkerTick for NodeSharedArc { @@ -17,14 +17,24 @@ impl TickWorkerTick for NodeSharedArc { let target_height = height + BlockHeight(1); // Check if I am the single validator - if !node.is_validator_for_height(target_height) { + let is_validator = match node.is_validator_for_height(target_height) { + Ok(value) => value, + Err(err) => { + error!(?err, "Unable to determine validator status"); + // Retry soon to avoid busy-looping on configuration errors. + return Some(Instant::now() + Duration::from_secs(5)); + } + }; + + if !is_validator { // This block may mean we can commit some proposals loop { let next = node.block_cache.lock().get_next_commit_block(); + let Some(block) = next else { break; }; - if let Err(err) = node.validate_block(&block) { + if let Err(err) = node.validate_block(&block).await { error!(?err, ?block, "Error validating block"); node.block_cache.lock().remove(&block.hash()); continue; diff --git a/pkg/node/src/node/transaction.rs b/pkg/node/src/node/transaction.rs index cba8932..b8beee2 100644 --- a/pkg/node/src/node/transaction.rs +++ b/pkg/node/src/node/transaction.rs @@ -1,47 +1,87 @@ -use std::{sync::Arc, time::Duration}; - -use ethereum_types::U64; -use smirk::Element; -use tracing::{error, info, instrument}; - +// lint-long-file-override allow-max-lines=300 use crate::{ - network::NetworkEvent, - utxo::{validate_txn, UtxoProof}, Block, Error, NodeShared, Result, + mempool::AddError, + network::NetworkEvent, + utxo::{validate_txn_state, verify_txn_proof}, +}; +use contextful::{ErrorContextExt as _, ResultContextExt as _}; +use element::Element; +use ethereum_types::U64; +use node_interface::{ElementData, ElementsVecData, MintInContractIsDifferent, RpcError}; +use std::{sync::Arc, time::Duration}; +use tracing::{error, info, instrument}; +use zk_primitives::{ + UtxoKindMessages, UtxoProof, bridged_polygon_usdc_note_kind, extract_chain_id_from_note_kind, }; impl NodeShared { pub async fn submit_transaction_and_wait(&self, utxo: UtxoProof) -> Result> { + let mint_chain_id = match utxo.kind_messages() { + UtxoKindMessages::Mint(mint_msgs) => { + Some(self.chain_id_for_mint_check(mint_msgs.note_kind)) + } + _ => None, + }; + let mut started_waiting_at_eth_block = None; loop { match self.validate_transaction(&utxo).await { Ok(_) => break, - Err(err @ Error::MintIsNotInTheContract { key: _ }) - | Err(err @ Error::BurnIsNotInTheContract { key: _ }) => { - let current_eth_block = self - .rollup_contract - .client - .client() - .eth() - .block_number() - .await - .map_err(Error::FailedToGetEthBlockNumber)? - .as_u64(); - let started_waiting_at_eth_block = - *started_waiting_at_eth_block.get_or_insert(current_eth_block); - - let waited_too_long_for_confirmation = current_eth_block - - started_waiting_at_eth_block - > self.config.safe_eth_height_offset; - - // TODO: we could wait a little extra time and accept mints/burns - // that are not even valid at `latest` height yet, - // because they are still in eth mempool - if self.config.safe_eth_height_offset == 0 || waited_too_long_for_confirmation { + Err(err) => { + let mut should_wait_for_confirmation = false; + if let Error::Rpc(rpc_error) = &err + && matches!(rpc_error.source_ref(), RpcError::MintIsNotInTheContract(..)) + { + let Some(chain_id) = mint_chain_id else { + return Err(err); + }; + + let rollup_contract = match self.rollup_contract_for_chain(chain_id) { + Some(contract) => contract, + None => { + return Err(RpcError::UnsupportedChain { chain_id } + .wrap_err("rollup contract not configured for mint chain") + .into()); + } + }; + + let safe_eth_height_offset = match self.config.chain_config(chain_id) { + Some(chain) => chain.safe_eth_height_offset, + None => { + return Err(RpcError::UnsupportedChain { chain_id } + .wrap_err("chain configuration not found for mint chain") + .into()); + } + }; + + let current_eth_block = rollup_contract + .client + .block_number_with_fast_retries() + .await + .context("fetch pending eth block number")? + .as_u64(); + let started_waiting_at_eth_block = + *started_waiting_at_eth_block.get_or_insert(current_eth_block); + + let waited_too_long_for_confirmation = current_eth_block + .saturating_sub(started_waiting_at_eth_block) + > safe_eth_height_offset; + + // TODO: we could wait a little extra time and accept mints/burns + // that are not even valid at `latest` height yet, + // because they are still in eth mempool + if safe_eth_height_offset == 0 || waited_too_long_for_confirmation { + return Err(err); + } + + should_wait_for_confirmation = true; + } + + if !should_wait_for_confirmation { return Err(err); } } - Err(err) => return Err(err), } tokio::time::sleep(Duration::from_secs(6)).await; @@ -49,58 +89,122 @@ impl NodeShared { self.send_all(NetworkEvent::Transaction(utxo.clone())).await; - let changes = utxo.leaves(); - self.mempool.add_wait(utxo.hash(), utxo, changes).await + let mut changes = Vec::new(); + for commitment in utxo + .public_inputs + .input_commitments + .into_iter() + .chain(utxo.public_inputs.output_commitments) + { + if commitment.is_zero() { + continue; + } + if !changes.contains(&commitment) { + changes.push(commitment); + } + } + + let receiver = match self.mempool.add_with_listener(utxo.hash(), utxo, changes) { + Ok(receiver) => receiver, + Err(AddError::Conflict(conflict)) => { + return Err(RpcError::TxnCommitmentAlreadyPending(ElementsVecData { + elements: vec![conflict], + }) + .wrap_err("mempool reports conflicting transaction commitment while submitting") + .into()); + } + Err(AddError::DuplicateKey) => { + return Err(RpcError::TxnCommitmentAlreadyPending(ElementsVecData { + elements: vec![], + }) + .wrap_err("duplicate transaction commitment detected while submitting") + .into()); + } + }; + + receiver.await.expect("recv error") } pub(super) async fn validate_transaction(&self, utxo: &UtxoProof) -> Result<()> { - let is_mint_or_burn = utxo.mb_hash != Element::ZERO && utxo.mb_value != Element::ZERO; - if is_mint_or_burn { - let eth_block = self - .rollup_contract + if let UtxoKindMessages::Mint(mint_msgs) = utxo.kind_messages() { + let chain_id = self.chain_id_for_mint_check(mint_msgs.note_kind); + let rollup_contract = match self.rollup_contract_for_chain(chain_id) { + Some(contract) => contract, + None => { + return Err(RpcError::UnsupportedChain { chain_id } + .wrap_err("rollup contract not configured for mint chain") + .into()); + } + }; + let safe_eth_height_offset = match self.config.chain_config(chain_id) { + Some(chain) => chain.safe_eth_height_offset, + None => { + return Err(RpcError::UnsupportedChain { chain_id } + .wrap_err("chain configuration not found for mint chain") + .into()); + } + }; + + let eth_block = rollup_contract .client - .client() - .eth() - .block_number() + .block_number_with_fast_retries() .await - .map_err(Error::FailedToGetEthBlockNumber)?; - let safe_eth_height = - match eth_block.overflowing_sub(U64::from(self.config.safe_eth_height_offset)) { - (safe_eth_height, false) => safe_eth_height, - // This can happen if we are running with a local hardhat node - (_, true) => U64::from(0), - }; - let rollup_contract_at_safe_height = self - .rollup_contract + .context("fetch latest eth block number")?; + + let safe_eth_height = match eth_block.overflowing_sub(U64::from(safe_eth_height_offset)) + { + (safe_eth_height, false) => safe_eth_height, + // This can happen if we are running with a local hardhat node + (_, true) => U64::from(0), + }; + let rollup_contract_at_safe_height = rollup_contract .clone() .at_height(Some(safe_eth_height.as_u64())); - match (utxo.input_leaves, utxo.output_leaves) { - // mint - ([Element::ZERO, Element::ZERO], [key, Element::ZERO]) => { - if rollup_contract_at_safe_height - .get_mint(&key) - .await? - .is_none() - { - return Err(Error::MintIsNotInTheContract { key }); - } - } - // burn - ([key, Element::ZERO], [Element::ZERO, Element::ZERO]) => { - match rollup_contract_at_safe_height.has_burn(&key).await? { - false => return Err(Error::BurnIsNotInTheContract { key }), - true => {} - } + let get_mint_res = match rollup_contract_at_safe_height + .get_mint(&mint_msgs.mint_hash) + .await + .context("query rollup contract for mint details at safe height")? + { + Some(res) => res, + None => { + return Err(RpcError::MintIsNotInTheContract(ElementData { + element: mint_msgs.mint_hash, + }) + .wrap_err("mint note hash not found in rollup contract at safe height") + .into()); } + }; - _ => { - return Err(Error::InvalidMintOrBurnLeaves); - } + // Check if mint is already spent + if get_mint_res.spent { + return Err(RpcError::MintIsAlreadySpent(ElementsVecData { + elements: utxo.public_inputs.output_commitments.to_vec(), + }) + .wrap_err("mint already marked spent in rollup contract") + .into()); + } + + // Check mint amout/kind matches the submitted utxo proof + if get_mint_res.amount != mint_msgs.value + || get_mint_res.note_kind != mint_msgs.note_kind + { + return Err(RpcError::MintInContractIsDifferent(Box::new( + MintInContractIsDifferent { + contract_value: get_mint_res.amount, + contract_note_kind: get_mint_res.note_kind, + proof_value: mint_msgs.value, + proof_note_kind: mint_msgs.note_kind, + }, + )) + .wrap_err("mint data in contract differs from provided UTXO proof") + .into()); } } - validate_txn( + verify_txn_proof(&*self.bb_backend, utxo).await?; + + validate_txn_state( self.config.mode, utxo, self.height(), @@ -109,7 +213,17 @@ impl NodeShared { ) } - #[instrument(skip(self))] + fn chain_id_for_mint_check(&self, note_kind: Element) -> u64 { + if note_kind == bridged_polygon_usdc_note_kind() + && let Some(primary_chain_id) = self.config.primary_chain_id() + { + return primary_chain_id; + } + + extract_chain_id_from_note_kind(note_kind) + } + + #[instrument(skip(self, txn))] pub async fn receive_transaction(&self, txn: UtxoProof) -> Result<()> { info!("Received transaction"); @@ -121,8 +235,34 @@ impl NodeShared { return Ok(()); } - let changes = txn.leaves(); - self.mempool.add(txn.hash(), txn, changes); + let mut changes = Vec::new(); + for commitment in txn + .public_inputs + .input_commitments + .into_iter() + .chain(txn.public_inputs.output_commitments) + { + if commitment.is_zero() { + continue; + } + if !changes.contains(&commitment) { + changes.push(commitment); + } + } + + match self.mempool.add(txn.hash(), txn, changes) { + Ok(()) => {} + Err(AddError::Conflict(conflict)) => { + return Err(RpcError::TxnCommitmentAlreadyPending(ElementsVecData { + elements: vec![conflict], + }) + .wrap_err("mempool reports conflicting transaction commitment while receiving") + .into()); + } + Err(AddError::DuplicateKey) => { + return Ok(()); + } + } Ok(()) } diff --git a/pkg/node/src/node/txn_format.rs b/pkg/node/src/node/txn_format.rs index c73b861..1860ce0 100644 --- a/pkg/node/src/node/txn_format.rs +++ b/pkg/node/src/node/txn_format.rs @@ -2,8 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use primitives::block_height::BlockHeight; use serde::{Deserialize, Serialize}; use wire_message::WireMessage; - -use crate::utxo::UtxoProof; +use zk_primitives::UtxoProof; #[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] pub struct TxnMetadata { @@ -41,7 +40,43 @@ impl WireMessage for TxnFormat { impl block_store::Transaction for TxnFormat { fn txn_hash(&self) -> [u8; 32] { match self { - Self::V1(txn, _) => txn.hash().into_inner(), + Self::V1(txn, _) => txn.hash().to_be_bytes(), + } + } + + fn input_elements(&self) -> Vec { + match self { + TxnFormat::V1(utxo_proof, _) => utxo_proof + .public_inputs + .input_commitments + .iter() + .filter(|c| !c.is_zero()) + .copied() + .collect(), + } + } + + fn output_elements(&self) -> Vec { + match self { + TxnFormat::V1(utxo_proof, _) => utxo_proof + .public_inputs + .output_commitments + .iter() + .filter(|c| !c.is_zero()) + .copied() + .collect(), + } + } + + fn mint_hash(&self) -> Option { + match self { + TxnFormat::V1(utxo_proof, _) => match utxo_proof.public_inputs.kind_messages() { + zk_primitives::UtxoKindMessages::Mint(utxo_kind_mint_messages) => { + Some(utxo_kind_mint_messages.mint_hash) + } + zk_primitives::UtxoKindMessages::Burn(_) => None, + zk_primitives::UtxoKindMessages::None => None, + }, } } } diff --git a/pkg/node/src/prover/db.rs b/pkg/node/src/prover/db.rs index 0d1d176..0525956 100644 --- a/pkg/node/src/prover/db.rs +++ b/pkg/node/src/prover/db.rs @@ -1,9 +1,10 @@ +// lint-long-file-override allow-max-lines=300 use std::{ops::Range, path::Path}; use borsh::BorshDeserialize; +use element::Element; use prover::RollupInput; use wire_message::WireMessage; -use zk_primitives::Element; use crate::types::BlockHeight; @@ -85,6 +86,7 @@ pub(crate) struct LastSeenBlock { } #[derive(Debug, borsh::BorshSerialize, borsh::BorshDeserialize)] +#[allow(clippy::large_enum_variant)] enum ValueV1 { LastSeenBlock(LastSeenBlock), Rollup(RollupInput), diff --git a/pkg/node/src/prover/error.rs b/pkg/node/src/prover/error.rs index 796d66b..7a1c793 100644 --- a/pkg/node/src/prover/error.rs +++ b/pkg/node/src/prover/error.rs @@ -1,14 +1,18 @@ use super::db; +use element::Element; use primitives::block_height::BlockHeight; -use zk_primitives::Element; + +use crate::errors::Error as NodeError; #[derive(Debug, thiserror::Error)] pub enum Error { #[error("failed to peek the next commit")] FailedToPeekNextCommit, - #[error("prover tree root hash does not match block state root hash, prover tree root hash: {prover_tree}, block state root hash: {block_tree}")] + #[error( + "prover tree root hash does not match block state root hash, prover tree root hash: {prover_tree}, block state root hash: {block_tree}" + )] ProverTreeRootDoesNotMatchBlockStateRoot { prover_tree: Element, block_tree: Element, @@ -30,7 +34,7 @@ pub enum Error { Db(#[from] db::Error), #[error("node error")] - Node(#[from] crate::errors::Error), + Node(#[from] NodeError), #[error("contract error")] Contract(#[from] contracts::Error), diff --git a/pkg/node/src/prover/worker.rs b/pkg/node/src/prover/worker.rs index 75650da..f9cf0b7 100644 --- a/pkg/node/src/prover/worker.rs +++ b/pkg/node/src/prover/worker.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=800 use std::future::Future; use std::pin::Pin; use std::str::FromStr; @@ -7,20 +8,40 @@ use std::time::Duration; use super::{Error, Result}; use crate::config::Config; use crate::constants::MERKLE_TREE_DEPTH; +use crate::errors::Error as NodeError; use crate::prover::db::{LastSeenBlock, ProverDb}; use crate::types::BlockHeight; use crate::{Mode, NodeShared, PersistentMerkleTree}; -use contracts::RollupContract; +use contracts::{Error as ContractsError, RollupContract}; use either::Either; -use futures::StreamExt; -use prover::smirk_metadata::SmirkMetadata; +use element::Element; +use futures::{StreamExt, future::pending}; +use prover::{MAXIMUM_TXNS, RollupInput}; use prover::{Prover, Transaction}; -use prover::{RollupInput, MAXIMUM_TXNS}; use scopeguard::ScopeGuard; -use smirk::{empty_tree_hash, Element, Tree}; -use tokio::sync::{mpsc, Mutex, Notify}; -use tracing::{error, info}; -use zk_circuits::data::Utxo; +use smirk::empty_tree_hash; +use tokio::sync::{Mutex, Notify, mpsc}; +use tracing::{error, info, warn}; +use web3::types::U256; + +const GWEI_IN_WEI: u64 = 1_000_000_000; + +fn gas_price_exceeds_threshold(max_rollup_gas_price_gwei: u64, current_gas_price: U256) -> bool { + let max_gas_price = U256::from(max_rollup_gas_price_gwei) * U256::from(GWEI_IN_WEI); + + let exceeds_threshold = current_gas_price > max_gas_price; + + if exceeds_threshold { + info!( + ?current_gas_price, + ?max_gas_price, + "Skipping rollup due to high gas price" + ); + } + + exceeds_threshold +} +use zk_primitives::{AggFinalProof, UtxoKind}; pub async fn run_prover(config: &Config, node: Arc) -> Result<()> { let (client, postgres_future) = if let Some(url) = &config.prover_database_url { @@ -45,15 +66,23 @@ pub async fn run_prover(config: &Config, node: Arc) -> Result<()> { web3::signing::SecretKey::from_slice(&config.secret_key.secret_key().secret_bytes()[..]) .unwrap(); + let chain = config + .primary_chain() + .ok_or_else(|| Error::Node(NodeError::UnsupportedChain { chain_id: 0 }))?; + let contracts_client = - contracts::Client::new(&config.eth_rpc_url, config.minimum_gas_price_gwei); - let contract = - contracts::RollupContract::load(contracts_client, &config.rollup_contract_addr, secret_key) - .await?; + contracts::Client::new(&chain.eth_rpc_url, config.minimum_gas_price_gwei); + let contract = contracts::RollupContract::load( + contracts_client, + u128::from(chain.chain_id), + &chain.rollup_contract_addr, + secret_key, + ) + .await?; let db_path = config.db_path.join("prover"); let prover_state_db = Arc::new(ProverDb::create_or_load(&db_path)?); - let prover = Arc::new(Prover::new(contract.clone())); + let prover = Arc::new(Prover::new(contract.clone(), Arc::clone(&node.bb_backend))); let smirk_path = config.smirk_path.join("prover"); let notes_tree = Arc::new(Mutex::new(Some(PersistentMerkleTree::load(&smirk_path)?))); @@ -95,32 +124,59 @@ pub async fn run_prover(config: &Config, node: Arc) -> Result<()> { Some(n) => return Err(Error::InvalidProverVersion(n)), } - tokio::try_join!( - run_prover_worker( - config, - Arc::clone(&node), - contract.clone(), - Arc::clone(&prover_state_db), - Arc::clone(¬es_tree), - client.clone(), - prover_worker_delete_smirk, - Arc::clone(&prover), - Arc::clone(&proof_notifier), - ), - run_rollup_worker( - Duration::from_millis(config.rollup_wait_time_ms), - contract, - prover_state_db, - prover, - proof_notifier, - None, - client, - ), + let prover_worker_future = { + let node = Arc::clone(&node); + let contract_clone = contract.clone(); + let prover_state_db_clone = Arc::clone(&prover_state_db); + let notes_tree_clone = Arc::clone(¬es_tree); + let client_clone = client.clone(); + let prover_clone = Arc::clone(&prover); + let proof_notifier_clone = Arc::clone(&proof_notifier); + async move { - postgres_future.await?; - Ok(()) + if config.enable_prover_worker { + run_prover_worker( + config, + node, + contract_clone, + prover_state_db_clone, + notes_tree_clone, + client_clone, + prover_worker_delete_smirk, + prover_clone, + proof_notifier_clone, + ) + .await + } else { + info!("Prover worker disabled via configuration (enable_prover_worker = false)"); + pending::>().await + } } - )?; + }; + + let rollup_worker_future = async { + if config.enable_rollup_worker { + run_rollup_worker( + Duration::from_millis(config.rollup_wait_time_ms), + contract, + prover_state_db, + prover, + proof_notifier, + chain.max_rollup_gas_price_gwei, + None, + client, + ) + .await + } else { + info!("Rollup worker disabled via configuration (enable_rollup_worker = false)"); + pending::>().await + } + }; + + tokio::try_join!(prover_worker_future, rollup_worker_future, async move { + postgres_future.await?; + Ok(()) + })?; Ok(()) } @@ -140,48 +196,15 @@ async fn run_prover_worker( where Fut: Future>, { - let ban_tree = Tree::::new(); - let initial_contract_block_height = BlockHeight(contract.block_height().await?); - { - // Wait for node to notice it's out of sync - tokio::time::sleep(Duration::from_secs(5)).await; - // Wait for node to sync. - // Trying to sync without waiting would mean invalid prover smirk tree, - // if the node synced with fast sync. - while node.is_out_of_sync() { - tokio::time::sleep(Duration::from_secs(1)).await; - } - - let mut prover_tree = notes_tree.lock().await; - let prover_tree = prover_tree.as_mut().unwrap(); - let node_notes_tree = node.notes_tree().read(); - - let elements_rolled_up_not_in_prover = - node_notes_tree.tree().elements().filter(|(el, meta)| { - meta.inserted_in <= initial_contract_block_height.0 - && !prover_tree.tree().contains_element(el) - }); - - let mut batch = smirk::Batch::new(); - let mut highest_block_height = None; - for (el, meta) in elements_rolled_up_not_in_prover { - batch.insert(*el, SmirkMetadata::inserted_in(meta.inserted_in))?; - if highest_block_height.map_or(true, |highest_block_height: BlockHeight| { - meta.inserted_in > highest_block_height.0 - }) { - highest_block_height = Some(BlockHeight(meta.inserted_in)); - } - } - prover_tree.insert_batch(batch)?; - - if let Some(highest_block_height) = highest_block_height { - prover_state_db.set_last_seen_block(LastSeenBlock { - height: highest_block_height, - root_hash: prover_tree.tree().root_hash(), - })?; - } + // Wait for node to notice it's out of sync + tokio::time::sleep(Duration::from_secs(5)).await; + // Wait for node to sync. + // Trying to sync without waiting would mean invalid prover smirk tree, + // if the node synced with fast sync. + while node.is_out_of_sync() { + tokio::time::sleep(Duration::from_secs(1)).await; } let last_seen_block = prover_state_db @@ -206,7 +229,9 @@ where })?; delete_smirk().await?; // Exit the process and let the supervisor restart us - panic!("Our tree's root hash does not match the last seen block's root hash. Please restart the prover"); + panic!( + "Our tree's root hash does not match the last seen block's root hash. Please restart the prover" + ); } let height = last_seen_block.height + BlockHeight(1); @@ -275,7 +300,6 @@ where notes_tree.lock().await.as_mut().unwrap(), &commit.content.state, commit.content.header.height, - is_a_bad_block, )?; prover_state_db.set_last_seen_block(LastSeenBlock { height: commit_height, @@ -293,7 +317,7 @@ where .state .txns .iter() - .map(|utxo| Ok(Some(Transaction::new(utxo.to_snark_witness())))) + .map(|utxo_proof| Ok(Some(Transaction::new(utxo_proof.clone())))) .collect::>>()?; while txns.len() < MAXIMUM_TXNS { @@ -316,50 +340,40 @@ where let proof = match config.mode { Mode::MockProver => { - let utxo_hashes = txns - .into_iter() - .map(|txn| txn.map(|t| t.proof.try_as_v_1().unwrap().instances)) - .map(|maybe_instances| { - maybe_instances.unwrap_or_else(|| { - vec![Utxo::::new_padding() - .public_inputs() - .into_iter() - .map(Element::from_base) - .collect::>()] - }) - }) - .flat_map(|instances| { - let root = instances[0][0]; - let mb_hash = instances[0][1]; - let mb_value = instances[0][2]; - - [root, mb_hash, mb_value] - }) - .collect::>(); - - prover::Proof { - proof: vec![], - agg_instances: vec![Element::ZERO; 12], - old_root: notes_tree.tree().root_hash(), - new_root: commit.content.state.root_hash, - utxo_hashes, + let mut agg_final_proof = AggFinalProof::default(); + agg_final_proof.public_inputs.old_root = notes_tree.tree().root_hash(); + agg_final_proof.public_inputs.new_root = commit.content.state.root_hash; + + let mut messages = [Element::ZERO; 1000]; + let mut index = 0; + + for proof in commit.content.state.txns.iter() { + let proof_messages = match proof.kind() { + UtxoKind::Null | UtxoKind::Send => &[][..], + UtxoKind::Mint => &proof.public_inputs.messages[..4], + UtxoKind::Burn => &proof.public_inputs.messages[..], + }; + + for &message in proof_messages { + messages[index] = message; + index += 1; + } } + + agg_final_proof.public_inputs.messages = messages.to_vec(); + + agg_final_proof } _ => { prover - .prove( - notes_tree.tree(), - &ban_tree, - commit_height.0, - txns.try_into().unwrap(), - ) + .prove(notes_tree.tree(), commit_height.0, txns.try_into().unwrap()) .await? } }; - if proof.new_root() != &commit.content.state.root_hash { + if proof.public_inputs.new_root != commit.content.state.root_hash { return Err(Error::RootMismatch { - got: *proof.new_root(), + got: proof.public_inputs.new_root, expected: commit.content.state.root_hash, }); } @@ -367,12 +381,7 @@ where let rollup_input = RollupInput::new(proof, commit_height.0, other_hash, signatures); prover_state_db.set_rollup(commit_height, rollup_input.clone())?; - NodeShared::apply_block_to_tree( - notes_tree, - &commit.content.state, - commit_height, - is_a_bad_block, - )?; + NodeShared::apply_block_to_tree(notes_tree, &commit.content.state, commit_height)?; prover_state_db.set_last_seen_block(LastSeenBlock { height: commit_height, root_hash: commit.content.state.root_hash, @@ -416,6 +425,7 @@ async fn run_rollup_worker( prover_state_db: Arc, prover: Arc, proof_notifier: Arc, + max_rollup_gas_price_gwei: Option, rollup_subscription: Option>, postgres_db: Option>, ) -> Result<()> { @@ -438,7 +448,8 @@ async fn run_rollup_worker( let Some(rollup) = prover_state_db .list_rollups(contract_height.next()..max) - .next() else { + .next() + else { info!(?contract_height, "No proofs to roll up"); continue; }; @@ -448,7 +459,7 @@ async fn run_rollup_worker( let rollup_contract_root_hash = Element::from_be_bytes(rollup_contract.root_hash().await?.0); - let rollup = if rollup.old_root() != &rollup_contract_root_hash { + let rollup = if rollup.old_root() != rollup_contract_root_hash { info!( ?contract_height, ?rollup_contract_root_hash, @@ -506,6 +517,20 @@ async fn run_rollup_worker( rollup }; + if let Some(max_gas_price_gwei) = max_rollup_gas_price_gwei { + let current_gas_price = match rollup_contract.client.fast_gas_price().await { + Ok(price) => price, + Err(err) => { + let err = ContractsError::from(err); + warn!(?err, "Failed to fetch gas price; skipping rollup attempt"); + continue; + } + }; + if gas_price_exceeds_threshold(max_gas_price_gwei, current_gas_price) { + continue; + } + } + let pending_nonce = rollup_contract .client .get_nonce( @@ -558,24 +583,78 @@ async fn run_rollup_worker( #[cfg(test)] mod tests { - use std::str::FromStr; + use std::{ + io::Write, + str::FromStr, + sync::{Arc, Mutex}, + }; use crate::{ - block::{BlockContent, BlockHeader, BlockState}, Block, + block::{BlockContent, BlockHeader, BlockState}, }; use super::*; - use contracts::{util::convert_element_to_h256, SecretKey}; + use contracts::{SecretKey, util::convert_element_to_h256}; use doomslug::ApprovalContent; use primitives::peer::PeerIdSigner; - use prover::Proof; use tempdir::TempDir; use testutil::{ - eth::{EthNode, EthNodeOptions}, ACCOUNT_1_SK, + eth::{EthNode, EthNodeOptions}, }; + use zk_circuits::BbBackend; + use zk_primitives::AggFinalProof; + #[derive(Clone)] + struct BufferingWriter { + buffer: Arc>>, + } + + impl Write for BufferingWriter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.buffer.lock().unwrap().extend_from_slice(buf); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } + } + + #[test] + fn logs_and_skips_when_gas_price_exceeds_threshold() { + let buffer = Arc::new(Mutex::new(Vec::new())); + let writer = { + let buffer = Arc::clone(&buffer); + move || BufferingWriter { + buffer: Arc::clone(&buffer), + } + }; + + let subscriber = tracing_subscriber::fmt() + .with_writer(writer) + .without_time() + .finish(); + let _guard = tracing::subscriber::set_default(subscriber); + + assert!(super::gas_price_exceeds_threshold( + 1, + U256::from(2_000_000_000u64) + )); + assert!(!super::gas_price_exceeds_threshold( + 3, + U256::from(2_000_000_000u64) + )); + + let logs = String::from_utf8(buffer.lock().unwrap().clone()).unwrap(); + assert!( + logs.contains("Skipping rollup due to high gas price"), + "expected log to contain skip message, got: {logs}" + ); + } + + #[ignore] #[tokio::test] async fn test_rollup() { tracing_subscriber::fmt() @@ -600,7 +679,8 @@ mod tests { .unwrap(); let prover_db = Arc::new(ProverDb::create_or_load(tempdir.path()).unwrap()); - let prover = Prover::new(rollup_contract.clone()); + let bb_backend: Arc = Arc::new(barretenberg_cli::CliBackend); + let prover = Prover::new(rollup_contract.clone(), bb_backend); let proof_notifier = Arc::new(Notify::new()); let (rollup_height_sender, mut rollup_height_receiver) = mpsc::channel(1); @@ -611,6 +691,7 @@ mod tests { Arc::clone(&prover_db), Arc::new(prover), Arc::clone(&proof_notifier), + None, Some(rollup_height_sender), None, ); @@ -618,7 +699,7 @@ mod tests { let mut rollup_worker = Box::pin(rollup_worker); let mut last_block = Block::genesis(); - let mut last_root = empty_tree_hash(MERKLE_TREE_DEPTH); + // let mut last_root = empty_tree_hash(MERKLE_TREE_DEPTH); for height in [1, 2, 3] { let new_root = Element::new(height); let block = BlockContent { @@ -641,13 +722,7 @@ mod tests { .set_rollup( BlockHeight(height), RollupInput::new( - Proof { - proof: Vec::new(), - agg_instances: vec![Element::ZERO; 12], - old_root: last_root, - new_root, - utxo_hashes: vec![Element::ZERO; 18], - }, + AggFinalProof::default(), height, *other_hash.inner(), vec![approval.signature], @@ -673,7 +748,7 @@ mod tests { ); last_block = block; - last_root = new_root; + // last_root = new_root; } } } diff --git a/pkg/node/src/rpc/http_error.rs b/pkg/node/src/rpc/http_error.rs index 8c804ca..33c7493 100644 --- a/pkg/node/src/rpc/http_error.rs +++ b/pkg/node/src/rpc/http_error.rs @@ -1,9 +1,6 @@ use super::routes; use crate::errors; -use primitives::hash::CryptoHash; use rpc::{code::ErrorCode, error::HTTPError}; -use serde::Serialize; -use zk_primitives::Element; impl From for HTTPError { fn from(err: routes::error::Error) -> Self { @@ -36,104 +33,13 @@ impl From for HTTPError { } } -#[derive(Debug, Serialize)] -pub struct ElementData { - pub element: Element, -} - -#[derive(Debug, Serialize)] -pub struct HashData { - pub hash: CryptoHash, -} - -#[derive(Debug, Serialize)] -pub struct ElementStringData { - pub element: String, -} - impl From for HTTPError { fn from(err: errors::Error) -> Self { match err { - errors::Error::InvalidProof => HTTPError::new( - ErrorCode::BadRequest, - "invalid-proof", - Some(err.into()), - None::<()>, - ), - errors::Error::UtxoRootIsNotRecentEnough { - utxo_recent_root, .. - } => { - // let allowed_recent_roots = err..clone(); - HTTPError::new( - ErrorCode::BadRequest, - "utxo-root-not-recent-enough", - Some(err.into()), - Some(ElementData { - element: utxo_recent_root, - }), - ) + errors::Error::Rpc(rpc_error) => { + let (_, inner) = rpc_error.into_parts(); + inner.into() } - errors::Error::ElementNotInTree { element } => HTTPError::new( - ErrorCode::NotFound, - "element-not-found", - Some(err.into()), - Some(ElementData { element }), - ), - errors::Error::NoteAlreadySpent { - spent_note: nullifier, - .. - } => HTTPError::new( - ErrorCode::AlreadyExists, - "nullifier-conflict", - Some(err.into()), - Some(ElementData { element: nullifier }), - ), - errors::Error::OutputNoteExists { - output_note: commitment, - } => HTTPError::new( - ErrorCode::AlreadyExists, - "commitment-conflict", - Some(err.into()), - Some(ElementData { - element: commitment, - }), - ), - errors::Error::MintIsNotInTheContract { key } => HTTPError::new( - ErrorCode::NotFound, - "mint-not-in-contract", - Some(err.into()), - Some(ElementData { element: key }), - ), - errors::Error::BurnIsNotInTheContract { key } => HTTPError::new( - ErrorCode::NotFound, - "burn-not-in-contract", - Some(err.into()), - Some(ElementData { element: key }), - ), - errors::Error::BurnToAddressCannotBeZero => HTTPError::new( - ErrorCode::BadRequest, - "burn-to-address-cannot-be-zero", - Some(err.into()), - None::<()>, - ), - errors::Error::InvalidElementSize { element } => HTTPError::new( - ErrorCode::BadRequest, - "invalid-element-modulus", - Some(err.into()), - Some(ElementData { element }), - ), - errors::Error::TxnNotFound { txn } => HTTPError::new( - ErrorCode::NotFound, - "txn-not-found", - Some(err.into()), - Some(HashData { hash: txn }), - ), - errors::Error::FailedToParseElement { element, source } => HTTPError::new( - ErrorCode::BadRequest, - "failed-to-parse-element", - Some(source.into()), - Some(ElementStringData { element }), - ), _ => HTTPError::new( ErrorCode::Internal, "internal", diff --git a/pkg/node/src/rpc/mod.rs b/pkg/node/src/rpc/mod.rs index bbd2f56..e9abd26 100644 --- a/pkg/node/src/rpc/mod.rs +++ b/pkg/node/src/rpc/mod.rs @@ -7,3 +7,4 @@ mod http_error; pub mod routes; pub mod server; pub mod stats; +pub mod stats_today; diff --git a/pkg/node/src/rpc/routes/blocks.rs b/pkg/node/src/rpc/routes/blocks.rs index 7e080ca..12475e3 100644 --- a/pkg/node/src/rpc/routes/blocks.rs +++ b/pkg/node/src/rpc/routes/blocks.rs @@ -1,7 +1,20 @@ -use super::{txn::TxnWithInfo, State}; -use crate::node; +// lint-long-file-override allow-max-lines=300 +mod tree; + +pub use tree::get_block_tree; + +use super::{State, txn::TxnWithInfo}; +use crate::{ + Error, Result, + block::{ + Block as NodeBlock, BlockContent as NodeBlockContent, BlockHeader as NodeBlockHeader, + BlockState as NodeBlockState, + }, + node, +}; use actix_web::web; use either::Either; +use element::Element; use primitives::{ block_height::BlockHeight, hash::CryptoHash, @@ -9,10 +22,11 @@ use primitives::{ sig::Signature, }; use rpc::error::HttpResult; -use serde::{de::IntoDeserializer, Deserialize, Serialize}; -use smirk::Element; +use serde::{Deserialize, Serialize, de::IntoDeserializer}; use wire_message::WireMessage; +const MAX_BLOCKS_LIMIT: usize = 256; + pub type BlockResponse = BlockWithInfo; #[derive(Serialize)] @@ -22,17 +36,17 @@ pub struct Block { } impl Block { - fn from_node_block(block: crate::block::Block, time: u64) -> Self { - let crate::block::Block { content, signature } = block; - let crate::block::BlockContent { header, state } = content; - let crate::block::BlockHeader { + fn from_node_block(block: NodeBlock, time: u64) -> Self { + let NodeBlock { content, signature } = block; + let NodeBlockContent { header, state } = content; + let NodeBlockHeader { height, last_block_hash, epoch_id, last_final_block_hash, approvals, } = header; - let crate::block::BlockState { root_hash, txns } = state; + let NodeBlockState { root_hash, txns } = state; Self { content: BlockContent { @@ -121,11 +135,11 @@ pub async fn get_block( BlockIdentifier::Height(height) => state .node .get_block(height)? - .ok_or(crate::Error::BlockNotFound { block: height })?, + .ok_or(Error::BlockNotFound { block: height })?, BlockIdentifier::Hash(hash) => state .node .get_block_by_hash(hash)? - .ok_or(crate::Error::BlockHashNotFound { block: hash })?, + .ok_or(Error::BlockHashNotFound { block: hash })?, }; let (block, metadata) = match block.upgrade(&mut ()).unwrap() { @@ -207,7 +221,7 @@ pub async fn list_blocks( } = query; let cursor = cursor.map(|c| c.into_inner()); - let limit = limit.unwrap_or(10).min(100); + let limit = limit.unwrap_or(10).min(MAX_BLOCKS_LIMIT); let blocks = if skip_empty { Either::Left( @@ -227,7 +241,7 @@ pub async fn list_blocks( let (cursor, blocks) = Paginator::new( blocks.map(|r| { - let (block, metadata) = match r.map_err(node::Error::from)?.upgrade(&mut ()).unwrap() { + let (block, metadata) = match r?.upgrade(&mut ()).unwrap() { node::BlockFormat::V1(_) => unreachable!("already upgraded"), node::BlockFormat::V2(block, metadata) => (block, metadata), }; diff --git a/pkg/node/src/rpc/routes/blocks/tree.rs b/pkg/node/src/rpc/routes/blocks/tree.rs new file mode 100644 index 0000000..9392f2c --- /dev/null +++ b/pkg/node/src/rpc/routes/blocks/tree.rs @@ -0,0 +1,137 @@ +use crate::{Error, Result, rpc::routes::State}; +use actix_web::web; +use block_store::{ElementHistoryIndexEntry, ElementHistoryKind}; +use element::Element; +use node_interface::{BlockTreeDiffChanges, BlockTreeResponse}; +use primitives::block_height::BlockHeight; +use rpc::error::HttpResult; +use serde::Deserialize; +use std::collections::BTreeSet; + +#[derive(Debug, Deserialize)] +pub struct BlockTreeQuery { + #[serde(default)] + pub diff_from: Option, +} + +#[tracing::instrument(err, skip(state))] +pub async fn get_block_tree( + state: web::Data, + path: web::Path<(BlockHeight,)>, + query: web::Query, +) -> HttpResult> { + let (height,) = path.into_inner(); + let query = query.into_inner(); + tracing::info!( + method = "get_block_tree", + ?height, + ?query, + "Incoming request" + ); + + let block = state + .node + .get_block(height)? + .ok_or(Error::BlockNotFound { block: height })? + .into_block(); + let root_hash = block.content.state.root_hash; + + let diff = query + .diff_from + .map(|from_height| { + if from_height >= height { + Ok(BlockTreeDiffChanges { + from_height, + additions: vec![], + removals: vec![], + }) + } else { + compute_tree_diff(state.as_ref(), from_height, height) + } + }) + .transpose()?; + let elements = if diff.is_some() { + None + } else { + Some( + collect_tree_elements(state.as_ref(), height)? + .into_iter() + .collect(), + ) + }; + + Ok(web::Json(BlockTreeResponse { + height, + root_hash, + elements, + diff, + })) +} + +fn collect_tree_elements(state: &State, height: BlockHeight) -> Result> { + let mut elements = BTreeSet::new(); + for entry in state.node.element_history_range(..=height) { + apply_history_entry(&mut elements, entry); + } + + Ok(elements) +} + +fn compute_tree_diff( + state: &State, + from_height: BlockHeight, + to_height: BlockHeight, +) -> Result { + let mut additions = BTreeSet::new(); + let mut removals = BTreeSet::new(); + for entry in state + .node + .element_history_range(from_height.next()..=to_height) + { + apply_diff_entry(&mut additions, &mut removals, entry); + } + + Ok(BlockTreeDiffChanges { + from_height, + additions: additions.into_iter().collect(), + removals: removals.into_iter().collect(), + }) +} + +fn apply_history_entry(target: &mut BTreeSet, entry: ElementHistoryIndexEntry) { + if entry.element.is_zero() { + return; + } + + match entry.kind { + ElementHistoryKind::Output => { + target.insert(entry.element); + } + ElementHistoryKind::Input => { + target.remove(&entry.element); + } + } +} + +fn apply_diff_entry( + additions: &mut BTreeSet, + removals: &mut BTreeSet, + entry: ElementHistoryIndexEntry, +) { + if entry.element.is_zero() { + return; + } + + match entry.kind { + ElementHistoryKind::Output => { + if !removals.remove(&entry.element) { + additions.insert(entry.element); + } + } + ElementHistoryKind::Input => { + if !additions.remove(&entry.element) { + removals.insert(entry.element); + } + } + } +} diff --git a/pkg/node/src/rpc/routes/configure.rs b/pkg/node/src/rpc/routes/configure.rs index a782bd7..40f13ec 100644 --- a/pkg/node/src/rpc/routes/configure.rs +++ b/pkg/node/src/rpc/routes/configure.rs @@ -1,4 +1,4 @@ -use super::{blocks, element, health, height, merkle, stats, txn, State}; +use super::{State, blocks, element, health, height, merkle, smirk, stats, txn}; use actix_web::web; pub fn configure_routes(state: State) -> Box { @@ -8,7 +8,12 @@ pub fn configure_routes(state: State) -> Box Box, path: web::Path<(Element,)>, -) -> HttpResult> { +) -> HttpResult> { let (element,) = path.into_inner(); - Ok(web::Json(get_element_response(&state, element)?)) -} - -#[derive(Deserialize)] -pub struct ListElementsQuery { - elements: String, + Ok(web::Json(get_element_response(&state, element, false)?)) } #[tracing::instrument(err, skip_all)] pub async fn list_elements( state: web::Data, query: web::Query, -) -> HttpResult>> { +) -> HttpResult> { if query.elements.is_empty() { return Ok(web::Json(vec![])); } @@ -48,56 +41,144 @@ pub async fn list_elements( }) .collect::>>()?; - Ok(web::Json( - elements - .iter() - .map(|element| match get_element_response(&state, *element) { - Ok(response) => Ok(Some(response)), - Err(e) => { - if let crate::Error::ElementNotInTree { .. } = e { - Ok(None) - } else { - Err(e) - } - } - }) - .filter_map(Result::transpose) - .collect::>>()?, - )) + Ok(web::Json(list_elements_internal( + &state, + &elements, + query.include_spent, + )?)) +} + +#[tracing::instrument(err, skip_all)] +pub async fn list_elements_post( + state: web::Data, + body: JsonWithLogging, +) -> HttpResult> { + let body = body.into_inner(); + if body.elements.is_empty() { + return Ok(web::Json(vec![])); + } + + Ok(web::Json(list_elements_internal( + &state, + &body.elements, + body.include_spent, + )?)) } fn get_element_response( state: &web::Data, element: Element, -) -> crate::Result { + include_spent: bool, +) -> Result { + match get_element_response_unspent(state, element) { + Ok(resp) => Ok(resp), + Err(err) => match err { + Error::Rpc(rpc_error) + if include_spent + && matches!(rpc_error.source_ref(), RpcError::ElementNotFound { .. }) => + { + get_element_response_from_history(state, element) + } + other => Err(other), + }, + } +} + +fn get_element_response_unspent( + state: &web::Data, + element: Element, +) -> Result { let notes_tree = state.node.notes_tree().read(); let tree = notes_tree.tree(); let meta = tree .get(element) - .ok_or(crate::Error::ElementNotInTree { element })?; + .ok_or(RpcError::ElementNotFound(ElementData { element })) + .context("element not present in notes tree while building RPC response")?; let Some(block) = state.node.get_block(meta.inserted_in.into())? else { - return Err(crate::Error::BlockNotFound { block: meta.inserted_in.into() }); + return Err(Error::BlockNotFound { + block: meta.inserted_in.into(), + }); }; - let block = block.into_block(); - let root_hash = block.content.state.root_hash; + let txn = block .content .state .txns .iter() - .find(|txn| txn.leaves().contains(&element)); - let Some(txn) = txn else { - // This should never happen in practice - return Err(crate::Error::ElementNotInTxn { element, block_height: block.block_height() }); - }; - let txn_hash = txn.hash(); + .find(|txn| txn.public_inputs.commitments().contains(&element)) + .ok_or(Error::ElementNotInTxn { + element, + block_height: block.block_height(), + })?; - Ok(ElementResponse { + Ok(ElementsResponseSingle { element, height: meta.inserted_in, - root_hash, - txn_hash, + root_hash: block.content.state.root_hash, + txn_hash: txn.hash(), + spent: false, }) } + +fn get_element_response_from_history( + state: &web::Data, + element: Element, +) -> Result { + let Some(info) = state.node.get_element_seen_info(element)? else { + return Err(RpcError::ElementNotFound(ElementData { element }) + .wrap_err("element not found in current or historical state") + .into()); + }; + + let Some(block) = state.node.get_block_by_hash(info.output_block_hash)? else { + return Err(Error::BlockNotFound { + block: info.output_height, + }); + }; + let block = block.into_block(); + + let txn = block + .content + .state + .txns + .iter() + .find(|txn| txn.public_inputs.commitments().contains(&element)) + .ok_or(Error::ElementNotInTxn { + element, + block_height: info.output_height, + })?; + + Ok(ElementsResponseSingle { + element, + height: info.output_height.0, // Use the height when the element was added to tree + root_hash: block.content.state.root_hash, + txn_hash: txn.hash(), + spent: info.spent, + }) +} + +fn list_elements_internal( + state: &web::Data, + elements: &[Element], + include_spent: bool, +) -> Result { + elements + .iter() + .map( + |element| match get_element_response(state, *element, include_spent) { + Ok(response) => Ok(Some(response)), + Err(e) => match e { + Error::Rpc(rpc_error) + if matches!(rpc_error.source_ref(), RpcError::ElementNotFound { .. }) => + { + Ok(None) + } + _ => Err(e), + }, + }, + ) + .filter_map(Result::transpose) + .collect::>>() +} diff --git a/pkg/node/src/rpc/routes/health.rs b/pkg/node/src/rpc/routes/health.rs index b9ab064..86a3423 100644 --- a/pkg/node/src/rpc/routes/health.rs +++ b/pkg/node/src/rpc/routes/health.rs @@ -1,4 +1,4 @@ -use super::{error, State}; +use super::{State, error}; use actix_web::web; use rpc::error::HttpResult; use serde::Serialize; @@ -18,9 +18,11 @@ pub async fn get_health(state: web::Data) -> HttpResult state.health_check_commit_interval_sec - }) { + if state + .node + .last_commit_time() + .is_none_or(|x| x.elapsed().as_secs() > state.health_check_commit_interval_sec) + { return Err(error::Error::OutOfSync)?; } diff --git a/pkg/node/src/rpc/routes/height.rs b/pkg/node/src/rpc/routes/height.rs index ba04e94..b9943cb 100644 --- a/pkg/node/src/rpc/routes/height.rs +++ b/pkg/node/src/rpc/routes/height.rs @@ -1,19 +1,13 @@ use super::State; use actix_web::web; +use node_interface::HeightResponse; use rpc::error::HttpResult; -use serde::Serialize; -use zk_primitives::Element; - -#[derive(Serialize)] -pub struct HeightResp { - height: u64, - root_hash: Element, -} /// GET /height - returns data about the rollup (e.g. root hash, version, etc) + #[tracing::instrument(err, skip(state))] -pub async fn get_height(state: web::Data) -> HttpResult> { - Ok(web::Json(HeightResp { +pub async fn get_height(state: web::Data) -> HttpResult> { + Ok(web::Json(HeightResponse { height: state.node.height().0, root_hash: state.node.root_hash(), })) diff --git a/pkg/node/src/rpc/routes/merkle.rs b/pkg/node/src/rpc/routes/merkle.rs index 00f2b6d..e884804 100644 --- a/pkg/node/src/rpc/routes/merkle.rs +++ b/pkg/node/src/rpc/routes/merkle.rs @@ -1,9 +1,9 @@ -use super::{error, State}; +use super::{State, error}; use actix_web::web; +use element::Element; use rpc::error::HttpResult; use serde::{Deserialize, Serialize}; use std::str::FromStr; -use zk_primitives::Element; #[derive(Debug, Deserialize)] pub struct MerklePathRequestQuery { diff --git a/pkg/node/src/rpc/routes/mod.rs b/pkg/node/src/rpc/routes/mod.rs index f6f715a..ccbf0e0 100644 --- a/pkg/node/src/rpc/routes/mod.rs +++ b/pkg/node/src/rpc/routes/mod.rs @@ -5,6 +5,7 @@ pub mod error; pub mod health; pub mod height; pub mod merkle; +pub mod smirk; pub mod state; pub mod stats; pub mod txn; diff --git a/pkg/node/src/rpc/routes/smirk.rs b/pkg/node/src/rpc/routes/smirk.rs new file mode 100644 index 0000000..e7b7d64 --- /dev/null +++ b/pkg/node/src/rpc/routes/smirk.rs @@ -0,0 +1,33 @@ +use actix_web::web; +use element::Element; +use rpc::error::HttpResult; +use serde::Serialize; + +use crate::rpc::routes::State; + +#[derive(Serialize)] +pub struct SmirkElementInfo { + element: Element, + inserted_at_height: u64, +} + +pub type GetAllSmirkElementsResponse = Vec; + +#[tracing::instrument(err, skip_all)] +pub async fn get_all_smirk_elements( + state: web::Data, +) -> HttpResult> { + tracing::info!(method = "get_all_smirk_elements", "Incoming request"); + + let notes_tree = state.node.notes_tree().read(); + let elements = notes_tree + .tree() + .elements() + .map(|(element, metadata)| SmirkElementInfo { + element: *element, + inserted_at_height: metadata.inserted_in, + }) + .collect(); + + Ok(web::Json(elements)) +} diff --git a/pkg/node/src/rpc/routes/state.rs b/pkg/node/src/rpc/routes/state.rs index 0015141..4a0ea64 100644 --- a/pkg/node/src/rpc/routes/state.rs +++ b/pkg/node/src/rpc/routes/state.rs @@ -1,4 +1,4 @@ -use crate::{rpc::stats, NodeShared}; +use crate::{NodeShared, rpc::stats}; use std::sync::Arc; pub struct State { diff --git a/pkg/node/src/rpc/routes/stats.rs b/pkg/node/src/rpc/routes/stats.rs index c2c2876..c9a74c0 100644 --- a/pkg/node/src/rpc/routes/stats.rs +++ b/pkg/node/src/rpc/routes/stats.rs @@ -14,6 +14,7 @@ struct TxnDayStats { #[derive(Debug, serde::Serialize)] pub struct StatsResponse { last_7_days_txns: Vec, + today_txns: u64, } #[tracing::instrument(err, skip_all)] @@ -29,5 +30,10 @@ pub async fn get_stats(state: web::Data) -> HttpResult, - web::Json(data): web::Json, -) -> HttpResult> { - let SnarkWitness::V1(snark) = &data.snark; + body: JsonWithLogging, +) -> HttpResult> { + let data = body.into_inner(); + let utxo_proof = data.proof; tracing::info!( method = "submit_txn", - instances = ?snark.instances, - proof = base64::prelude::BASE64_STANDARD.encode(&snark.proof), + proof = serde_json::to_string(&utxo_proof).unwrap(), "Incoming request" ); - let utxo = UtxoProof::from_snark_witness(data.snark); - let utxo_hash = utxo.hash(); + let circuit_proof = Proof::from(utxo_proof.clone()); + if let Err(_err) = circuit_proof.verify(&*state.node.bb_backend).await { + return Err(RpcError::InvalidProof)?; + } + + let utxo_hash = utxo_proof.hash(); + + if let Some((_, metadata)) = state + .node + .get_txn(utxo_hash.to_be_bytes()) + .map_err(HTTPError::from)? + { + let root_hash = state + .node + .get_block(metadata.block_height) + .map_err(HTTPError::from)? + .map(|block_format| match block_format { + node::BlockFormat::V1(block) => block.content.state.root_hash, + node::BlockFormat::V2(block, _) => block.content.state.root_hash, + }) + .unwrap_or_else(|| { + tracing::warn!( + ?utxo_hash, + height = ?metadata.block_height, + "missing block for already included transaction" + ); + Element::ZERO + }); + + return Err(RpcError::TxnAlreadyIncluded { + root_hash, + txn_hash: utxo_hash, + height: metadata.block_height, + })?; + } let node = Arc::clone(&state.node); - let block = tokio::spawn(async move { node.submit_transaction_and_wait(utxo).await }) + let block = tokio::spawn(async move { node.submit_transaction_and_wait(utxo_proof).await }) .await - .context("tokio spawn join handle error")??; + .map_err(|err| HTTPError::internal(Box::new(err)))??; - Ok(web::Json(SubmitUtxoResp { + Ok(web::Json(TransactionResponse { height: block.content.header.height, root_hash: block.content.state.root_hash, txn_hash: utxo_hash, @@ -64,7 +85,7 @@ pub async fn submit_txn( pub(crate) struct TxnWithInfo { pub(crate) proof: UtxoProof, pub(crate) index_in_block: u64, - pub(crate) hash: CryptoHash, + pub(crate) hash: Element, pub(crate) block_height: BlockHeight, pub(crate) time: u64, } @@ -118,16 +139,22 @@ pub async fn list_txns( ) -> HttpResult> { tracing::info!(method = "list_txns", ?path, ?query, "Incoming request"); - let block_fetcher = - |cursor: &Option>, order: BlockListOrder, limit: usize| { - state + let make_block_fetcher = |s: web::Data| { + move |cursor: &Option>, + order: BlockListOrder, + limit: usize| + -> Result>, Error> { + let iter = s .node - .fetch_blocks_non_empty_paginated(cursor, order, limit) - }; + .fetch_blocks_non_empty_paginated(cursor, order, limit)?; + Ok(iter.collect::>().into_iter()) + } + }; let max_height = state.node.max_height(); - let (cursor, transactions) = list_txns_inner(block_fetcher, &query, max_height)?; + let (cursor, transactions) = + list_txns_inner(make_block_fetcher(state.clone()), &query, max_height)?; let (cursor, transactions) = if transactions.is_empty() && query.poll { let towards_newer_height = match (&query.order, query.cursor.as_deref()) { @@ -163,7 +190,7 @@ pub async fn list_txns( } _ = non_empty_block_stream.next() => { list_txns_inner( - block_fetcher, + make_block_fetcher(state.clone()), &query, max_height, )? @@ -284,21 +311,16 @@ pub struct GetTxnResponse { #[tracing::instrument(err, skip_all)] pub async fn get_txn( state: web::Data, - path: web::Path<(String,)>, + path: web::Path<(Element,)>, ) -> HttpResult> { tracing::info!(method = "get_txn", ?path, "Incoming request"); let (txn_hash,) = path.into_inner(); - let txn_hash = - CryptoHash::from_str(&txn_hash).map_err(|err| crate::Error::FailedToParseHash { - hash: txn_hash, - source: err, - })?; let (txn, metadata) = state .node - .get_txn(txn_hash.into_inner())? - .ok_or(crate::Error::TxnNotFound { txn: txn_hash })?; + .get_txn(txn_hash.to_be_bytes())? + .ok_or(RpcError::TxnNotFound(ElementData { element: txn_hash }))?; let time = metadata.block_time.unwrap_or_else(|| { node::NodeShared::estimate_block_time(metadata.block_height, state.node.max_height()) @@ -317,6 +339,7 @@ pub async fn get_txn( #[cfg(test)] mod tests { + use contextful::ResultContextExt; use primitives::pagination::Opaque; use crate::{Block, BlockFormat}; @@ -336,19 +359,13 @@ mod tests { block }; - let new_proof = |recent_root: Element| UtxoProof { - recent_root, - ..UtxoProof::default() - }; + let new_proof = || UtxoProof::default(); let blocks = [ new_block(1, vec![]), - new_block(2, vec![new_proof(Element::new(1))]), - new_block( - 3, - vec![new_proof(Element::new(2)), new_proof(Element::new(3))], - ), - new_block(4, vec![new_proof(Element::new(4))]), + new_block(2, vec![new_proof()]), + new_block(3, vec![new_proof(), new_proof()]), + new_block(4, vec![new_proof()]), ]; let max_height = blocks.last().unwrap().content.header.height; @@ -359,9 +376,16 @@ mod tests { let block_fetcher = |cursor: &Option>, order: BlockListOrder, limit: usize| { - Ok(store - .list_paginated(cursor, order, limit)? - .map(|r| r.map(|(_, block)| block).map_err(node::Error::from))) + let blocks = store + .list_paginated(cursor, order, limit) + .context("list paginated blocks")? + .map(|res| -> Result<_, node::Error> { + let (_, block) = res.context("load paginated block")?; + Ok(block) + }) + .collect::>(); + + Ok(blocks.into_iter()) }; let (_pagination, txns) = list_txns_inner( @@ -406,7 +430,6 @@ mod tests { .unwrap(); assert_eq!(txns.len(), 1); assert_eq!(txns[0].block_height, BlockHeight(3)); - assert_eq!(txns[0].proof.recent_root, Element::new(2)); let (cursor, txns) = list_txns_inner( block_fetcher, @@ -421,7 +444,6 @@ mod tests { .unwrap(); assert_eq!(txns.len(), 1); assert_eq!(txns[0].block_height, BlockHeight(3)); - assert_eq!(txns[0].proof.recent_root, Element::new(3)); let (cursor, txns) = list_txns_inner( block_fetcher, @@ -436,7 +458,6 @@ mod tests { .unwrap(); assert_eq!(txns.len(), 1); assert_eq!(txns[0].block_height, BlockHeight(2)); - assert_eq!(txns[0].proof.recent_root, Element::new(1)); let (cursor, txns) = list_txns_inner( block_fetcher, @@ -469,7 +490,6 @@ mod tests { .unwrap(); assert_eq!(txns.len(), 1); assert_eq!(txns[0].block_height, BlockHeight(2)); - assert_eq!(txns[0].proof.recent_root, Element::new(1)); let (cursor, txns) = list_txns_inner( block_fetcher, @@ -484,7 +504,6 @@ mod tests { .unwrap(); assert_eq!(txns.len(), 1); assert_eq!(txns[0].block_height, BlockHeight(3)); - assert_eq!(txns[0].proof.recent_root, Element::new(2)); let (cursor, txns) = list_txns_inner( block_fetcher, @@ -499,7 +518,6 @@ mod tests { .unwrap(); assert_eq!(txns.len(), 1); assert_eq!(txns[0].block_height, BlockHeight(3)); - assert_eq!(txns[0].proof.recent_root, Element::new(3)); let (cursor, txns) = list_txns_inner( block_fetcher, @@ -514,7 +532,6 @@ mod tests { .unwrap(); assert_eq!(txns.len(), 1); assert_eq!(txns[0].block_height, BlockHeight(4)); - assert_eq!(txns[0].proof.recent_root, Element::new(4)); let (cursor, txns) = list_txns_inner( block_fetcher, diff --git a/pkg/node/src/rpc/server.rs b/pkg/node/src/rpc/server.rs index 9945075..1ddd8e6 100644 --- a/pkg/node/src/rpc/server.rs +++ b/pkg/node/src/rpc/server.rs @@ -1,16 +1,17 @@ #![warn(clippy::unwrap_used, clippy::expect_used)] +use super::routes::error::Error as RoutesError; use crate::{NodeShared, TxnStats}; use actix_cors::Cors; use actix_server::Server; -use actix_web::{dev::Service, web, App, HttpResponse, HttpServer, Responder}; +use actix_web::{App, HttpResponse, HttpServer, Responder, dev::Service, web}; use rpc::{ - error::{not_found_error_handler, HTTPError}, + error::{HTTPError, not_found_error_handler}, middleware::Middleware, }; use std::sync::Arc; -use super::routes::{configure_routes, State}; +use super::routes::{State, configure_routes}; async fn root() -> impl Responder { HttpResponse::Ok() @@ -49,7 +50,7 @@ pub fn create_rpc_server( async move { if is_out_of_sync { - let err = HTTPError::from(crate::rpc::routes::error::Error::OutOfSync); + let err = HTTPError::from(RoutesError::OutOfSync); Err(err.into()) } else { fut.await diff --git a/pkg/node/src/rpc/stats.rs b/pkg/node/src/rpc/stats.rs index a3df9ac..983da2f 100644 --- a/pkg/node/src/rpc/stats.rs +++ b/pkg/node/src/rpc/stats.rs @@ -1,32 +1,30 @@ use std::{ collections::HashMap, fmt::Debug, - sync::{atomic::AtomicBool, Arc}, + sync::{Arc, atomic::AtomicBool}, }; use block_store::{BlockListOrder, StoreList}; use chrono::{NaiveDate, Utc}; use parking_lot::RwLock; -use crate::{node, NodeShared}; +use crate::{NodeShared, node}; + +use super::stats_today::TodayStats; pub struct TxnStats { node: Arc, ready: Arc, last_7_days: Arc>>, + today: Arc, } impl Debug for TxnStats { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let TxnStats { - node: _, - ready, - last_7_days, - } = self; - f.debug_struct("TxnStats") - .field("ready", &ready) - .field("last_7_days", &last_7_days) + .field("ready", &self.ready) + .field("last_7_days", &self.last_7_days) + .field("today", &self.today) .finish() } } @@ -34,8 +32,9 @@ impl Debug for TxnStats { impl TxnStats { pub fn new(node: Arc) -> Self { Self { - node, + node: Arc::clone(&node), last_7_days: Arc::new(RwLock::new(Vec::new())), + today: Arc::new(TodayStats::new(node)), ready: Arc::new(AtomicBool::new(false)), } } @@ -88,6 +87,10 @@ impl TxnStats { Ok(()) } + pub fn count_today_txns(&self) -> u64 { + self.today.count() + } + pub async fn worker(self: Arc) -> Result<(), tokio::task::JoinError> { tokio::spawn(async move { loop { @@ -123,4 +126,8 @@ impl TxnStats { }) .await } + + pub async fn today_stats_worker(self: Arc) -> Result<(), tokio::task::JoinError> { + tokio::spawn(async move { self.today.clone().run().await }).await + } } diff --git a/pkg/node/src/rpc/stats_today.rs b/pkg/node/src/rpc/stats_today.rs new file mode 100644 index 0000000..373d242 --- /dev/null +++ b/pkg/node/src/rpc/stats_today.rs @@ -0,0 +1,164 @@ +use std::fmt::Debug; +use std::sync::Arc; + +use block_store::{BlockListOrder, StoreList}; +use chrono::{NaiveDate, Utc}; +use parking_lot::RwLock; +use tokio_stream::StreamExt; + +use crate::block::Block; +use crate::types::BlockHeight; +use crate::{NodeShared, node}; + +pub struct TodayStats { + node: Arc, + stats: RwLock<(NaiveDate, u64)>, +} + +impl Debug for TodayStats { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TodayStats") + .field("stats", &self.stats) + .finish_non_exhaustive() + } +} + +impl TodayStats { + pub fn new(node: Arc) -> Self { + Self { + node, + stats: RwLock::new((Utc::now().date_naive(), 0)), + } + } + + pub fn count(&self) -> u64 { + let today = Utc::now().date_naive(); + let (date, count) = *self.stats.read(); + if date == today { count } else { 0 } + } + + pub async fn run(self: Arc) { + let start_height = self.wait_for_start_height().await; + + let last_primed_height = self.prime_stats(start_height); + let stream_start = last_primed_height + .map(|h| BlockHeight(h.0 + 1)) + .unwrap_or(start_height); + + let mut stream = self.node.commit_stream(Some(stream_start)).await; + let mut interval = tokio::time::interval(std::time::Duration::from_secs(60)); + + loop { + tokio::select! { + Some(res) = stream.next() => { + match res { + Ok(block) => self.process_new_block(block), + Err(e) => tracing::error!(?e, "Stream error"), + } + } + _ = interval.tick() => self.check_day_rollover(), + } + } + } + + fn prime_stats(&self, start_height: BlockHeight) -> Option { + let blocks = self + .node + .fetch_blocks_non_empty(start_height.., BlockListOrder::LowestToHighest) + .into_iterator(); + + let mut max_height = None; + + for block in blocks.flatten() { + let block = Arc::new(block.into_block()); + max_height = Some(block.content.header.height); + self.process_new_block(block); + } + + max_height + } + + async fn wait_for_start_height(&self) -> BlockHeight { + loop { + let today = Utc::now().date_naive(); + match self.find_first_non_empty_block_of_day(today) { + Ok(height) => { + *self.stats.write() = (today, 0); + return height; + } + Err(err) => { + tracing::error!(?err, "Failed to scan start height, retrying in 5s"); + tokio::time::sleep(std::time::Duration::from_secs(5)).await; + } + } + } + } + + fn process_new_block(&self, block: Arc) { + let height = block.content.header.height; + let block_date = self.get_block_date(height); + let txns_count = block.content.state.txns.len() as u64; + + let mut stats = self.stats.write(); + if block_date > stats.0 { + *stats = (block_date, txns_count); + } else if block_date == stats.0 { + stats.1 += txns_count; + } + } + + fn check_day_rollover(&self) { + let now = Utc::now().date_naive(); + let mut stats = self.stats.write(); + if now > stats.0 { + *stats = (now, 0); + } + } + + fn get_block_date(&self, height: BlockHeight) -> NaiveDate { + let block_format = self.node.get_block(height).ok().flatten(); + let time = block_format + .as_ref() + .and_then(|b| b.metadata().timestamp_unix_s) + .unwrap_or_else(|| NodeShared::estimate_block_time(height, self.node.max_height())); + + chrono::DateTime::::from_timestamp(time as i64, 0) + .unwrap() + .date_naive() + } + + fn find_first_non_empty_block_of_day( + &self, + today: NaiveDate, + ) -> Result { + let blocks = self + .node + .fetch_blocks_non_empty(.., BlockListOrder::HighestToLowest) + .into_iterator(); + + let max_height = self.node.max_height(); + let mut start_height = BlockHeight(max_height.0 + 1); + + let today_start_ts = chrono::DateTime::::from_naive_utc_and_offset( + today.and_hms_opt(0, 0, 0).unwrap(), + Utc, + ) + .timestamp() as u64; + + for block in blocks { + let block = block?; + let time = block.metadata().timestamp_unix_s; + let block = block.into_block(); + let block_height = block.content.header.height; + + let time = + time.unwrap_or_else(|| NodeShared::estimate_block_time(block_height, max_height)); + + if time < today_start_ts { + break; + } + start_height = block_height; + } + Ok(start_height) + } +} diff --git a/pkg/node/src/sync.rs b/pkg/node/src/sync.rs index 86d30a0..386ee0b 100644 --- a/pkg/node/src/sync.rs +++ b/pkg/node/src/sync.rs @@ -5,10 +5,15 @@ //! via the [SyncWorkerChannel]. //! The main entry point is [SyncWorker::run]. -use std::{collections::HashSet, sync::Arc}; +// lint-long-file-override allow-max-lines=700 +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, +}; use block_store::{BlockListOrder, StoreList}; use contracts::RollupContract; +use element::Element; use libp2p::PeerId; use parking_lot::Mutex; use prover::smirk_metadata::SmirkMetadata; @@ -16,13 +21,15 @@ use tokio::sync::mpsc; use tracing::{error, info, warn}; use crate::{ + Error as NodeError, NodeShared, PersistentMerkleTree, + block::Block, cache::BlockCache, network::{ NetworkEvent, SnapshotAccept, SnapshotChunk, SnapshotChunkFast, SnapshotChunkSlow, - SnapshotKind, SnapshotRequest, + SnapshotKind, SnapshotOffer as NetworkSnapshotOffer, SnapshotRequest, }, + node::Mode, types::{BlockHeight, SnapshotId}, - NodeShared, }; #[derive(Debug, thiserror::Error)] @@ -34,13 +41,13 @@ pub enum Error { Send(&'static str), #[error("node error: {0}")] - NodeError(#[from] Box), + Node(#[from] Box), #[error("smirk collision error: {0}")] - SmirkCollisionError(#[from] smirk::CollisionError), + SmirkCollision(#[from] smirk::CollisionError), #[error("smirk storage error: {0}")] - SmirkStorageError(#[from] smirk::storage::Error), + SmirkStorage(#[from] smirk::storage::Error), #[error("tokio join error: {0}")] TokioJoin(#[from] tokio::task::JoinError), @@ -48,7 +55,7 @@ pub enum Error { pub enum Message { OutOfSync(OutOfSync), - SnapshotOffer(SnapshotOffer), + SnapshotOffer(SyncSnapshotOffer), SnapshotChunk(PeerId, SnapshotChunk), } @@ -59,7 +66,7 @@ pub struct OutOfSync { } /// Same as [crate::network::NetworkEvent::SnapshotOffer] -pub struct SnapshotOffer { +pub struct SyncSnapshotOffer { pub peer: PeerId, pub snapshot_id: SnapshotId, } @@ -81,7 +88,10 @@ impl SyncWorkerChannel { /// Handled by [SyncWorker::handle_snapshot_offer]. pub fn snapshot_offer(&self, peer: PeerId, snapshot_id: SnapshotId) -> Result<(), Error> { self.0 - .send(Message::SnapshotOffer(SnapshotOffer { peer, snapshot_id })) + .send(Message::SnapshotOffer(SyncSnapshotOffer { + peer, + snapshot_id, + })) .map_err(|_| Error::ChannelWasClosed) } @@ -95,14 +105,14 @@ impl SyncWorkerChannel { pub struct SyncWorker { node: Arc, - rollup_contract: RollupContract, + rollup_contract: Option, /// The number of blocks to request in a snapshot chunk. chunk_size: u64, /// Only request fast sync if the node is this many blocks behind. fast_sync_threshold: u64, /// Duration after which we stop waiting for a snapshot offer/chunk. timeout: std::time::Duration, - node_mode: crate::node::Mode, + node_mode: Mode, /// A channel for receiving sync network messages. channel: mpsc::UnboundedReceiver, /// We need the channel sender to send messages to ourselves, @@ -116,11 +126,11 @@ impl SyncWorker { #[allow(clippy::too_many_arguments)] pub fn new( node: Arc, - rollup_contract: RollupContract, + rollup_contract: Option, chunk_size: u64, fast_sync_threshold: u64, timeout: std::time::Duration, - node_mode: crate::node::Mode, + node_mode: Mode, channel: mpsc::UnboundedReceiver, channel_sender: SyncWorkerChannel, ) -> Self { @@ -174,8 +184,11 @@ impl SyncWorker { let far_enough_to_try_fast_sync = max_seen_height.0 - self.node.height().0 > self.fast_sync_threshold; - if self.node_mode.is_prover() && far_enough_to_try_fast_sync { - match self.rollup_contract.block_height().await { + if self.node_mode.is_prover() + && far_enough_to_try_fast_sync + && let Some(rollup_contract) = &self.rollup_contract + { + match rollup_contract.block_height().await { Ok(contract_height) => { let contract_height = BlockHeight(contract_height); if contract_height > to_height { @@ -227,7 +240,7 @@ impl SyncWorker { async fn wait_for_snapshot_offer( &mut self, snapshot_id: SnapshotId, - ) -> Result { + ) -> Result { while let Some(msg) = self.channel.recv().await { match msg { Message::SnapshotOffer(so) if so.snapshot_id == snapshot_id => return Ok(so), @@ -242,7 +255,7 @@ impl SyncWorker { &mut self, kind: SnapshotKind, to_height: BlockHeight, - SnapshotOffer { peer, snapshot_id }: SnapshotOffer, + SyncSnapshotOffer { peer, snapshot_id }: SyncSnapshotOffer, ) -> Result<(), Error> { let from_height = self.node.height() + BlockHeight(1); @@ -286,7 +299,7 @@ impl SyncWorker { Message::SnapshotChunk(sc_peer, sc) if sc_peer == peer && sc.snapshot_id() == snapshot_id => { - return Ok((peer, sc)) + return Ok((peer, sc)); } _ => {} } @@ -370,53 +383,9 @@ impl SyncWorker { return Ok(()); }; - let block_elements = block - .content - .state - .txns - .iter() - .flat_map(|txn| txn.leaves()) - .filter(|l| !l.is_zero()) - .collect::>(); - { let mut tree = self.node.notes_tree().write(); - let elements = HashSet::from_iter(elements.iter()) - .difference( - &tree - .tree() - .elements() - .map(|(e, _)| e) - .collect::>(), - ) - .copied() - .copied() - .collect::>(); - if tree.tree().root_hash_with(&elements) != block.content.state.root_hash { - error!("Fast snapshot chunk root hash mismatch"); - return Ok(()); - } - - let mut batch = smirk::Batch::new(); - let mut block_elements_left_to_find = block_elements.clone(); - for element in elements { - if block_elements.contains(&element) { - block_elements_left_to_find.remove(&element); - continue; - } - - batch.insert(element, SmirkMetadata::inserted_in(0))?; - } - - if !block_elements_left_to_find.is_empty() { - error!( - ?block_elements_left_to_find, - "Fast snapshot chunk missing elements" - ); - return Ok(()); - } - - tree.insert_batch(batch)?; + Self::apply_fast_snapshot_chunk(&mut tree, &block, &elements)?; self.node .block_cache .lock() @@ -428,6 +397,98 @@ impl SyncWorker { Ok(()) } + + fn apply_fast_snapshot_chunk( + tree: &mut PersistentMerkleTree, + block: &Block, + elements: &[Element], + ) -> Result<(), Error> { + // Elements for the last block in the chunk + let mut last_block_elements = HashMap::< + Element, + // true = add + // false = remove + bool, + >::new(); + for utxo in block.content.state.txns.iter() { + for e in &utxo.public_inputs.input_commitments { + last_block_elements.insert(*e, false); + } + for e in &utxo.public_inputs.output_commitments { + last_block_elements.insert(*e, true); + } + } + + // Build sets for diffing + let elements_set: HashSet<_> = elements.iter().copied().collect(); + let tree_elements_set: HashSet<_> = tree.tree().elements().map(|(e, _)| *e).collect(); + + // New elements (present in `elements` but not in the tree) + let new_elements = elements_set + .difference(&tree_elements_set) + .copied() + .collect::>(); + + // Missing elements (present in the tree but not in `elements`) + let missing_elements = tree_elements_set + .difference(&elements_set) + .copied() + .collect::>(); + + // Validate root hash with both insertions and removals + if tree.tree().root_hash_with(&new_elements, &missing_elements) + != block.content.state.root_hash + { + error!("Fast snapshot chunk root hash mismatch"); + return Ok(()); + } + + let mut batch = smirk::Batch::new(); + let mut block_elements_left_to_find = last_block_elements.clone(); + + // Apply insertions that are not part of the last block (the last block + // will be applied separately via receive_proposal) + for element in new_elements { + if element == Element::ZERO { + continue; + } + if let Some(is_add) = last_block_elements.get(&element) + && *is_add + { + // This element is expected to be added by the last block; skip now. + block_elements_left_to_find.remove(&element); + continue; + } + batch.insert(element, SmirkMetadata::inserted_in(0))?; + } + + // Apply removals that are not part of the last block (the last block + // will remove its inputs separately via receive_proposal) + for element in missing_elements { + if element == Element::ZERO { + continue; + } + if let Some(is_add) = last_block_elements.get(&element) + && !*is_add + { + // This element is expected to be removed by the last block; skip now. + block_elements_left_to_find.remove(&element); + continue; + } + batch.remove(element)?; + } + + if !block_elements_left_to_find.is_empty() { + error!( + ?block_elements_left_to_find, + "Fast snapshot chunk missing elements" + ); + return Ok(()); + } + + tree.insert_batch(batch)?; + Ok(()) + } } /// An out of sync node sent a snapshot request, @@ -447,7 +508,7 @@ pub(crate) async fn handle_snapshot_request( info!(?snapshot_id, "Sending snapshot offer"); - let offer = crate::network::SnapshotOffer { snapshot_id }; + let offer = NetworkSnapshotOffer { snapshot_id }; node.send(peer, NetworkEvent::SnapshotOffer(offer)).await; Ok(()) @@ -497,7 +558,7 @@ async fn send_snapshot_chunk_slow( .fetch_blocks(from_height..to_height, BlockListOrder::LowestToHighest) .into_iterator() .map(|r| r.map(|bf| bf.into_block())) - .collect::, crate::Error>>() + .collect::, NodeError>>() .map_err(Box::new)?; // Get the latest current pending block @@ -512,12 +573,10 @@ async fn send_snapshot_chunk_slow( // Send snapshot chunk node.send( peer, - NetworkEvent::SnapshotChunk(crate::network::SnapshotChunk::Slow( - crate::network::SnapshotChunkSlow { - snapshot_id, - chunk: blocks, - }, - )), + NetworkEvent::SnapshotChunk(SnapshotChunk::Slow(SnapshotChunkSlow { + snapshot_id, + chunk: blocks, + })), ) .await; @@ -552,15 +611,17 @@ async fn send_snapshot_chunk_fast( // Send snapshot chunk node.send( peer, - NetworkEvent::SnapshotChunk(crate::network::SnapshotChunk::Fast( - crate::network::SnapshotChunkFast { - snapshot_id, - block: block.map(|b| Box::new(b.into_block())), - elements, - }, - )), + NetworkEvent::SnapshotChunk(SnapshotChunk::Fast(SnapshotChunkFast { + snapshot_id, + block: block.map(|b| Box::new(b.into_block())), + elements, + })), ) .await; Ok(()) } + +#[cfg(test)] +#[path = "sync_test.rs"] +mod sync_test; diff --git a/pkg/node/src/sync_test.rs b/pkg/node/src/sync_test.rs new file mode 100644 index 0000000..31ac612 --- /dev/null +++ b/pkg/node/src/sync_test.rs @@ -0,0 +1,177 @@ +use super::SyncWorker; +use crate::{PersistentMerkleTree, block::Block, constants::MERKLE_TREE_DEPTH, types::BlockHeight}; +use element::Element; +use prover::smirk_metadata::SmirkMetadata; +use zk_primitives::{UtxoProof, UtxoPublicInput}; + +fn e(n: u64) -> Element { + Element::new(n) +} + +fn make_block(height: u64, root: Element, inputs: [Element; 2], outputs: [Element; 2]) -> Block { + let mut block = Block::default(); + block.content.header.height = BlockHeight(height); + block.content.state.root_hash = root; + block.content.state.txns = vec![UtxoProof { + proof: Default::default(), + public_inputs: UtxoPublicInput { + input_commitments: inputs, + output_commitments: outputs, + messages: [Element::ZERO; 5], + }, + }]; + block +} + +fn compute_fast_snapshot_diffs( + tree: &PersistentMerkleTree, + block: &Block, + elements: &[Element], +) -> ( + Vec, + Vec, + std::collections::HashMap, +) { + // Elements for the last block in the chunk (ignoring ZERO) + let mut last_block_elements = std::collections::HashMap::::new(); + for utxo in block.content.state.txns.iter() { + for e in &utxo.public_inputs.input_commitments { + if *e != Element::ZERO { + last_block_elements.insert(*e, false); + } + } + for e in &utxo.public_inputs.output_commitments { + if *e != Element::ZERO { + last_block_elements.insert(*e, true); + } + } + } + + let elements_set: std::collections::HashSet<_> = elements.iter().copied().collect(); + let tree_elements_set: std::collections::HashSet<_> = + tree.tree().elements().map(|(e, _)| *e).collect(); + + let mut new_elements = elements_set + .difference(&tree_elements_set) + .copied() + .collect::>(); + let mut missing_elements = tree_elements_set + .difference(&elements_set) + .copied() + .collect::>(); + + // Track last block elements that are still unaccounted for in the snapshot `elements` + let mut block_elements_left_to_find = last_block_elements.clone(); + // Filter out last-block changes from the returned diffs (they are applied by the block) + new_elements.retain(|e| { + if last_block_elements.get(e) == Some(&true) { + block_elements_left_to_find.remove(e); + false + } else { + true + } + }); + + missing_elements.retain(|e| { + if last_block_elements.get(e) == Some(&false) { + block_elements_left_to_find.remove(e); + false + } else { + true + } + }); + + (new_elements, missing_elements, block_elements_left_to_find) +} + +#[test] +fn fast_snapshot_diff_computation() { + let dir = tempdir::TempDir::new("fast_snapshot").unwrap(); + let tree_path = dir.path().join("db"); + let mut tree: PersistentMerkleTree = PersistentMerkleTree::new(&tree_path).unwrap(); + + // Initial tree: {1,2,3} + for v in [1u64, 2, 3] { + tree.insert(Element::new(v), SmirkMetadata::inserted_in(0)) + .unwrap(); + } + + // Expected final state after to_height (elements vector): {2,4,5} + let elements = vec![e(2), e(4), e(5)]; + + // Last block removes 3, adds 5 + let block_root = tree.tree().root_hash_with(&[e(4), e(5)], &[e(1), e(3)]); + let block = make_block(10, block_root, [e(3), Element::ZERO], [e(5), Element::ZERO]); + + let (new_elems, missing_elems, left_to_find) = + compute_fast_snapshot_diffs(&tree, &block, &elements); + + let new_set: std::collections::HashSet<_> = new_elems.into_iter().collect(); + let missing_set: std::collections::HashSet<_> = missing_elems.into_iter().collect(); + assert_eq!(new_set, [e(4)].into_iter().collect()); + assert_eq!(missing_set, [e(1)].into_iter().collect()); + assert!(left_to_find.is_empty()); +} + +#[test] +fn fast_snapshot_root_mismatch_does_not_mutate_tree() { + let dir = tempdir::TempDir::new("fast_snapshot_mismatch").unwrap(); + let mut tree: PersistentMerkleTree = PersistentMerkleTree::new(dir.path().join("db")).unwrap(); + + // Initial tree: {1,2} + for v in [1u64, 2] { + tree.insert(Element::new(v), SmirkMetadata::inserted_in(0)) + .unwrap(); + } + + // Elements claim state {2,3} + let elements = vec![e(2), e(3)]; + + // Incorrect root (use empty tree root to ensure mismatch) + let wrong_root = smirk::empty_tree_hash(MERKLE_TREE_DEPTH); + let block = make_block(5, wrong_root, [Element::ZERO; 2], [Element::ZERO; 2]); + + // Capture before state + let before: std::collections::HashSet<_> = tree.tree().elements().map(|(e, _)| *e).collect(); + + SyncWorker::apply_fast_snapshot_chunk(&mut tree, &block, &elements).unwrap(); + + // Tree unchanged + let after: std::collections::HashSet<_> = tree.tree().elements().map(|(e, _)| *e).collect(); + assert_eq!(before, after); +} + +#[test] +fn fast_snapshot_missing_last_block_elements_diff_computation() { + let dir = tempdir::TempDir::new("fast_snapshot_missing_last").unwrap(); + let mut tree: PersistentMerkleTree = PersistentMerkleTree::new(dir.path().join("db")).unwrap(); + + // Initial tree: {1,3} + for v in [1u64, 3] { + tree.insert(Element::new(v), SmirkMetadata::inserted_in(0)) + .unwrap(); + } + + // Final intended state after block: remove 3, add 5, plus 2 + let elements_full = vec![e(1), e(2), e(5)]; + let expected_root = tree.tree().root_hash_with(&[e(2), e(5)], &[e(3)]); + + // Last block removes 3, adds 5 + let block = make_block( + 7, + expected_root, + [e(3), Element::ZERO], + [e(5), Element::ZERO], + ); + + // Provide an elements vector missing the last block's add (5) + let elements_missing = vec![e(1), e(2)]; + + let (_new_full, _missing_full, left_full) = + compute_fast_snapshot_diffs(&tree, &block, &elements_full); + assert!(left_full.is_empty()); + + let (_new_missing, _missing_missing, left_missing) = + compute_fast_snapshot_diffs(&tree, &block, &elements_missing); + assert!(left_missing.contains_key(&e(5))); // last block add is missing from snapshot elements +} diff --git a/pkg/node/src/utxo.rs b/pkg/node/src/utxo.rs index a6c9041..56407eb 100644 --- a/pkg/node/src/utxo.rs +++ b/pkg/node/src/utxo.rs @@ -1,86 +1,114 @@ -use block_store::BlockListOrder; use block_store::BlockStore; - -use block_store::StoreList; -use zk_circuits::{constants::MERKLE_TREE_DEPTH, data::SnarkWitness, CircuitKind}; -use zk_primitives::Element; +use contextful::ResultContextExt as _; +use element::Element; +use node_interface::{ElementData, ElementsVecData, RpcError}; +use zk_circuits::{BbBackend, Proof, Verify}; +use zk_primitives::UtxoProof; use crate::Mode; -use crate::{ - constants::RECENT_ROOT_COUNT, types::BlockHeight, BlockFormat, Error, PersistentMerkleTree, - Result, -}; +use crate::{BlockFormat, PersistentMerkleTree, Result, types::BlockHeight}; -pub type UtxoProof = zk_circuits::data::UTXOProof; +/// Verify the UTXO txn proof +pub async fn verify_txn_proof(bb_backend: &dyn BbBackend, utxo_proof: &UtxoProof) -> Result<()> { + let proof = Proof::from(utxo_proof.clone()); + if let Err(_err) = proof.verify(bb_backend).await { + Err(RpcError::InvalidProof).context("verify UTXO proof before validation")?; + } + Ok(()) +} -/// Validate a UTXO txn, we check the following: -/// - The proof is valid +/// Validate a UTXO txn state, we check the following: /// - The recent root is recent enough /// - The input notes are not already spent (not in tree) /// - The output notes do not already exist (not in tree) -pub fn validate_txn( - mode: Mode, - utxo: &UtxoProof, - height: BlockHeight, +pub fn validate_txn_state( + _mode: Mode, + utxo_proof: &UtxoProof, + _height: BlockHeight, block_store: &BlockStore, notes_tree: &PersistentMerkleTree, ) -> Result<()> { - let SnarkWitness::V1(witness) = utxo.to_snark_witness(); + let public_inputs = &utxo_proof.public_inputs; - if !witness.verify(CircuitKind::Utxo) { - return Err(Error::InvalidProof); + let [input_0, input_1] = public_inputs.input_commitments; + if input_0 != Element::ZERO && input_0 == input_1 { + Err(RpcError::TxnDuplicateInputCommitments(ElementsVecData { + elements: vec![input_0], + })) + .context("UTXO txn provides duplicate non-zero input commitments")?; } - // No need to check recent roots if recent_root is zero - // TODO: are we defo this is secure? - if utxo.recent_root != Element::ZERO { - let next_block = height.next(); - let range = BlockHeight(next_block.saturating_sub(RECENT_ROOT_COUNT))..next_block; - - // TODO: this should be finding the last 64 DIFFERENT hashes, not just the last 64 blocks or we should increase - // the number of recent roots - let recent_roots = block_store - .list(range, BlockListOrder::LowestToHighest) - .into_iterator() - .map(|r| { - let block = r?.1.into_block(); - Ok::<_, Error>(block) - }) - .map(|b| Ok::<_, Error>(b?.content.state.root_hash)) - .collect::>>()?; - - if !recent_roots.iter().any(|r| *r == utxo.recent_root) && !mode.is_prover() { - return Err(Error::UtxoRootIsNotRecentEnough { - utxo_recent_root: utxo.recent_root, - recent_roots, - txn_hash: utxo.hash(), - }); - } + let [output_0, output_1] = public_inputs.output_commitments; + if output_0 != Element::ZERO && output_0 == output_1 { + Err(RpcError::TxnDuplicateOutputCommitments(ElementsVecData { + elements: vec![output_0], + })) + .context("UTXO txn provides duplicate non-zero output commitments")?; } // Check if any of the txn inserts are already in the tree let tree = notes_tree.tree(); - for leaf in utxo.input_leaves { + for leaf in utxo_proof.public_inputs.output_commitments { if leaf >= Element::MODULUS { - return Err(Error::InvalidElementSize { element: leaf }); + Err(RpcError::InvalidElementSize(ElementData { element: leaf })) + .context("UTXO output commitment exceeds field modulus")?; } - if leaf != Element::ZERO && tree.contains_element(&leaf) { - return Err(Error::NoteAlreadySpent { - spent_note: leaf, - failing_txn_hash: utxo.hash(), - }); + if leaf != Element::ZERO { + if tree.contains_element(&leaf) { + Err(RpcError::TxnOutputCommitmentsExist(ElementsVecData { + elements: vec![leaf], + })) + .context("UTXO output commitment already present in notes tree")?; + } + + let (_, output_history) = block_store + .get_element_history(leaf) + .context("fetch element history for UTXO output commitment")?; + if output_history.is_some() { + // This note used to be in tree, but was removed (used as insert in txn) + Err(RpcError::TxnOutputCommitmentsExistedRecently( + ElementsVecData { + elements: vec![leaf], + }, + )) + .context("UTXO output commitment existed recently in block history")?; + } } } - for leaf in utxo.output_leaves { + for leaf in utxo_proof.public_inputs.input_commitments { if leaf >= Element::MODULUS { - return Err(Error::InvalidElementSize { element: leaf }); + Err(RpcError::InvalidElementSize(ElementData { element: leaf })) + .context("UTXO input commitment exceeds field modulus")?; + } + + if leaf != Element::ZERO && !tree.contains_element(&leaf) { + Err(RpcError::TxnInputCommitmentsNotInTree(ElementsVecData { + elements: vec![leaf], + })) + .context("UTXO input commitment not found in notes tree")?; + } + } + + let mint_hash = match utxo_proof.kind_messages() { + zk_primitives::UtxoKindMessages::Mint(utxo_kind_mint_messages) => { + Some(utxo_kind_mint_messages.mint_hash) } + zk_primitives::UtxoKindMessages::Burn(_) => None, + zk_primitives::UtxoKindMessages::None => None, + }; - if leaf != Element::ZERO && tree.contains_element(&leaf) { - return Err(Error::OutputNoteExists { output_note: leaf }); + if let Some(mint_hash) = mint_hash { + let mint_hash_in_db = block_store + .get_mint_hash(mint_hash) + .context("lookup mint hash during UTXO validation")?; + if mint_hash_in_db.is_some() { + Err(RpcError::MintHashAlreadyExists(ElementData { + element: mint_hash, + })) + .context("UTXO mint hash already recorded in block store")?; } } diff --git a/pkg/node/tests/cache/utxo-burn-4c0779baeffa81f8f5a1420587b13fbff4c23fb3cf1f39b414fefb080a7369a1.proof b/pkg/node/tests/cache/utxo-burn-4c0779baeffa81f8f5a1420587b13fbff4c23fb3cf1f39b414fefb080a7369a1.proof new file mode 100644 index 0000000..6a74a1d Binary files /dev/null and b/pkg/node/tests/cache/utxo-burn-4c0779baeffa81f8f5a1420587b13fbff4c23fb3cf1f39b414fefb080a7369a1.proof differ diff --git a/pkg/node/tests/cache/utxo-burn-50528ab561fc224280f83fe593e22f94ffd329315d3d3777e0fc17b191917542.proof b/pkg/node/tests/cache/utxo-burn-50528ab561fc224280f83fe593e22f94ffd329315d3d3777e0fc17b191917542.proof new file mode 100644 index 0000000..932a142 Binary files /dev/null and b/pkg/node/tests/cache/utxo-burn-50528ab561fc224280f83fe593e22f94ffd329315d3d3777e0fc17b191917542.proof differ diff --git a/pkg/node/tests/cache/utxo-burn-6d7c4ce62131c8ad48fb27bf91ef4933c97c4afa0d9b9ae8c34e3999708516a2.proof b/pkg/node/tests/cache/utxo-burn-6d7c4ce62131c8ad48fb27bf91ef4933c97c4afa0d9b9ae8c34e3999708516a2.proof deleted file mode 100644 index 2e63f5d..0000000 Binary files a/pkg/node/tests/cache/utxo-burn-6d7c4ce62131c8ad48fb27bf91ef4933c97c4afa0d9b9ae8c34e3999708516a2.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-double_spend-2-56f3667d60acfb1e9e771d4107bea75ab57210714a3578103412aef81ba97b88.proof b/pkg/node/tests/cache/utxo-double_spend-2-56f3667d60acfb1e9e771d4107bea75ab57210714a3578103412aef81ba97b88.proof new file mode 100644 index 0000000..e495ea0 Binary files /dev/null and b/pkg/node/tests/cache/utxo-double_spend-2-56f3667d60acfb1e9e771d4107bea75ab57210714a3578103412aef81ba97b88.proof differ diff --git a/pkg/node/tests/cache/utxo-double_spend-2-91a8c38a51d46ca90354b4beaad943c2a38b19051d7a9841c3e5220a1efac585.proof b/pkg/node/tests/cache/utxo-double_spend-2-91a8c38a51d46ca90354b4beaad943c2a38b19051d7a9841c3e5220a1efac585.proof deleted file mode 100644 index 3f03161..0000000 Binary files a/pkg/node/tests/cache/utxo-double_spend-2-91a8c38a51d46ca90354b4beaad943c2a38b19051d7a9841c3e5220a1efac585.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-double_spend-2-b6ce83439214e92ea401ca3a400d897de8f9f144a82c8cdc70785f8c89d9a9f6.proof b/pkg/node/tests/cache/utxo-double_spend-2-b6ce83439214e92ea401ca3a400d897de8f9f144a82c8cdc70785f8c89d9a9f6.proof new file mode 100644 index 0000000..92022bc Binary files /dev/null and b/pkg/node/tests/cache/utxo-double_spend-2-b6ce83439214e92ea401ca3a400d897de8f9f144a82c8cdc70785f8c89d9a9f6.proof differ diff --git a/pkg/node/tests/cache/utxo-double_spend-279ae69068ca13966478057f6437643b1c4cf8ebd9091dae59d8a98b45dc2692.proof b/pkg/node/tests/cache/utxo-double_spend-279ae69068ca13966478057f6437643b1c4cf8ebd9091dae59d8a98b45dc2692.proof new file mode 100644 index 0000000..d0a6b3d Binary files /dev/null and b/pkg/node/tests/cache/utxo-double_spend-279ae69068ca13966478057f6437643b1c4cf8ebd9091dae59d8a98b45dc2692.proof differ diff --git a/pkg/node/tests/cache/utxo-double_spend-2d96985126f05bdb55636fd359b6de65d6d968593e96edd4306c1a30f668e8ae.proof b/pkg/node/tests/cache/utxo-double_spend-2d96985126f05bdb55636fd359b6de65d6d968593e96edd4306c1a30f668e8ae.proof new file mode 100644 index 0000000..e9ac3ef Binary files /dev/null and b/pkg/node/tests/cache/utxo-double_spend-2d96985126f05bdb55636fd359b6de65d6d968593e96edd4306c1a30f668e8ae.proof differ diff --git a/pkg/node/tests/cache/utxo-double_spend-e34dd8d66326771f363769bcd8a8b75a407a27c9a6509bf9e5ee0ac33f466ac8.proof b/pkg/node/tests/cache/utxo-double_spend-e34dd8d66326771f363769bcd8a8b75a407a27c9a6509bf9e5ee0ac33f466ac8.proof deleted file mode 100644 index 38a30cf..0000000 Binary files a/pkg/node/tests/cache/utxo-double_spend-e34dd8d66326771f363769bcd8a8b75a407a27c9a6509bf9e5ee0ac33f466ac8.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-mint-00017cff8bfbf04ac40ba8d86046e5fb56409971524ea1969894244c932055ae.proof b/pkg/node/tests/cache/utxo-mint-00017cff8bfbf04ac40ba8d86046e5fb56409971524ea1969894244c932055ae.proof deleted file mode 100644 index 3b6f055..0000000 Binary files a/pkg/node/tests/cache/utxo-mint-00017cff8bfbf04ac40ba8d86046e5fb56409971524ea1969894244c932055ae.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-mint-15fc4bad1b48125c7779a68096ae832f62cb24c0b5d19e9328657606430963bd.proof b/pkg/node/tests/cache/utxo-mint-15fc4bad1b48125c7779a68096ae832f62cb24c0b5d19e9328657606430963bd.proof new file mode 100644 index 0000000..fd35476 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-15fc4bad1b48125c7779a68096ae832f62cb24c0b5d19e9328657606430963bd.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-178841698d21c586ec0d1e76ccffd2fe62d9a76d1e9d62b109a5441a1875a117.proof b/pkg/node/tests/cache/utxo-mint-178841698d21c586ec0d1e76ccffd2fe62d9a76d1e9d62b109a5441a1875a117.proof deleted file mode 100644 index d50d7a0..0000000 Binary files a/pkg/node/tests/cache/utxo-mint-178841698d21c586ec0d1e76ccffd2fe62d9a76d1e9d62b109a5441a1875a117.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-mint-1eb6b41b938763f77fb6101e82f84f845bf5d1aa2851620fc2176ca4d7a1e24c.proof b/pkg/node/tests/cache/utxo-mint-1eb6b41b938763f77fb6101e82f84f845bf5d1aa2851620fc2176ca4d7a1e24c.proof new file mode 100644 index 0000000..75212b7 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-1eb6b41b938763f77fb6101e82f84f845bf5d1aa2851620fc2176ca4d7a1e24c.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-28aac33216b29c2b49f14b90b523f3bdca62b4fdd33c36b10688eda11c23abb9.proof b/pkg/node/tests/cache/utxo-mint-28aac33216b29c2b49f14b90b523f3bdca62b4fdd33c36b10688eda11c23abb9.proof deleted file mode 100644 index 785075e..0000000 Binary files a/pkg/node/tests/cache/utxo-mint-28aac33216b29c2b49f14b90b523f3bdca62b4fdd33c36b10688eda11c23abb9.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-mint-341febc1be7883a7f913b3bd7c328b2f2c2cbacedfde756f2dfe6bb054a5df32.proof b/pkg/node/tests/cache/utxo-mint-341febc1be7883a7f913b3bd7c328b2f2c2cbacedfde756f2dfe6bb054a5df32.proof new file mode 100644 index 0000000..dda75f8 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-341febc1be7883a7f913b3bd7c328b2f2c2cbacedfde756f2dfe6bb054a5df32.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-38505006af66209f5c564eb8120cb0c8cc805fb6db3df19179cc0960efa9d0ca.proof b/pkg/node/tests/cache/utxo-mint-38505006af66209f5c564eb8120cb0c8cc805fb6db3df19179cc0960efa9d0ca.proof deleted file mode 100644 index adf40ff..0000000 Binary files a/pkg/node/tests/cache/utxo-mint-38505006af66209f5c564eb8120cb0c8cc805fb6db3df19179cc0960efa9d0ca.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-mint-51955b900327de05ac1c5f65dca083c61c6a432cc4001c1b094ede4d06883430.proof b/pkg/node/tests/cache/utxo-mint-51955b900327de05ac1c5f65dca083c61c6a432cc4001c1b094ede4d06883430.proof new file mode 100644 index 0000000..835225a Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-51955b900327de05ac1c5f65dca083c61c6a432cc4001c1b094ede4d06883430.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-64d09898e244c8c8afc33cd624a3346df2b921e1881ea0821f3df98653239c97.proof b/pkg/node/tests/cache/utxo-mint-64d09898e244c8c8afc33cd624a3346df2b921e1881ea0821f3df98653239c97.proof new file mode 100644 index 0000000..7821b5a Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-64d09898e244c8c8afc33cd624a3346df2b921e1881ea0821f3df98653239c97.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-6603bce173766f6c4125709fcc4ff688e0c9caa10700d2a2f887dce5fae69dd4.proof b/pkg/node/tests/cache/utxo-mint-6603bce173766f6c4125709fcc4ff688e0c9caa10700d2a2f887dce5fae69dd4.proof new file mode 100644 index 0000000..c906648 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-6603bce173766f6c4125709fcc4ff688e0c9caa10700d2a2f887dce5fae69dd4.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-6a0da323f905c1c55e96fcac0bbcefd74c92b09418c53b61fe146a652d13ed5f.proof b/pkg/node/tests/cache/utxo-mint-6a0da323f905c1c55e96fcac0bbcefd74c92b09418c53b61fe146a652d13ed5f.proof new file mode 100644 index 0000000..a2f4016 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-6a0da323f905c1c55e96fcac0bbcefd74c92b09418c53b61fe146a652d13ed5f.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-8cc876bd3b54eb373c234cb5b773d3dfb15c52f6731720f2ec0900ef320bb54d.proof b/pkg/node/tests/cache/utxo-mint-8cc876bd3b54eb373c234cb5b773d3dfb15c52f6731720f2ec0900ef320bb54d.proof new file mode 100644 index 0000000..e707531 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-8cc876bd3b54eb373c234cb5b773d3dfb15c52f6731720f2ec0900ef320bb54d.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-9fb6072a101faca75f8b42069a08a916b2b62e38787353148da964fd7bafaf69.proof b/pkg/node/tests/cache/utxo-mint-9fb6072a101faca75f8b42069a08a916b2b62e38787353148da964fd7bafaf69.proof new file mode 100644 index 0000000..8280337 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint-9fb6072a101faca75f8b42069a08a916b2b62e38787353148da964fd7bafaf69.proof differ diff --git a/pkg/node/tests/cache/utxo-mint-ff2271897f3ed377bf17eac34548278c6ea2d1e08230f546ba876d1b0db3afbb.proof b/pkg/node/tests/cache/utxo-mint-ff2271897f3ed377bf17eac34548278c6ea2d1e08230f546ba876d1b0db3afbb.proof deleted file mode 100644 index a74636f..0000000 Binary files a/pkg/node/tests/cache/utxo-mint-ff2271897f3ed377bf17eac34548278c6ea2d1e08230f546ba876d1b0db3afbb.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-279ae69068ca13966478057f6437643b1c4cf8ebd9091dae59d8a98b45dc2692.proof b/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-279ae69068ca13966478057f6437643b1c4cf8ebd9091dae59d8a98b45dc2692.proof new file mode 100644 index 0000000..a2abe1c Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-279ae69068ca13966478057f6437643b1c4cf8ebd9091dae59d8a98b45dc2692.proof differ diff --git a/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-e34dd8d66326771f363769bcd8a8b75a407a27c9a6509bf9e5ee0ac33f466ac8.proof b/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-e34dd8d66326771f363769bcd8a8b75a407a27c9a6509bf9e5ee0ac33f466ac8.proof deleted file mode 100644 index d5e8090..0000000 Binary files a/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-e34dd8d66326771f363769bcd8a8b75a407a27c9a6509bf9e5ee0ac33f466ac8.proof and /dev/null differ diff --git a/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-eb48617e2db352c19a2a0b42de166c856caa07754977d455fec1cb02aa76a138.proof b/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-eb48617e2db352c19a2a0b42de166c856caa07754977d455fec1cb02aa76a138.proof new file mode 100644 index 0000000..7e6c9a3 Binary files /dev/null and b/pkg/node/tests/cache/utxo-mint_and_transfer_alice_to_bob-eb48617e2db352c19a2a0b42de166c856caa07754977d455fec1cb02aa76a138.proof differ diff --git a/pkg/node/tests/rpc/aggregator_support.rs b/pkg/node/tests/rpc/aggregator_support.rs new file mode 100644 index 0000000..7d9b320 --- /dev/null +++ b/pkg/node/tests/rpc/aggregator_support.rs @@ -0,0 +1,375 @@ +// lint-long-file-override allow-max-lines=400 +use std::{ + collections::VecDeque, + sync::{Arc, Mutex}, +}; + +use aggregator::{ + AggAggCircuitInterface, AggFinalCircuitInterface, Aggregator, ContractsRollupContract, +}; +use aggregator_interface::{ + Aggregator as AggregatorTrait, BlockProver as BlockProverTrait, BlockProverError, + PreparationOutcome, PreparedBlock, PreparedChunk, RollupTree, UTXO_AGG_NUMBER, + UTXO_AGGREGATIONS, +}; +use barretenberg_interface::{BbBackend, error::Error as BbError}; +use element::Element; +use node_client_http::{Error as NodeClientHttpError, NodeClientHttp}; +use node_interface::{Error as NodeInterfaceError, NodeClient}; +use primitives::block_height::BlockHeight; +use rpc::code::ErrorCode; +use testutil::eth::EthNode; +use zk_circuits::{AggAggCircuit, AggFinalCircuit}; +use zk_primitives::{ + AggAggProof, AggAggPublicInput, AggFinalPublicInput, ProofBytes, + UtxoProofBundleWithMerkleProofs, +}; + +use super::{Server, rollup_contract}; + +const BYTES_PER_ELEMENT: usize = 32; +const AGG_AGG_PUBLIC_INPUTS_COUNT: usize = 2 + 1 + 1 + 1 + 1000; +const AGG_AGG_PROOF_ELEMENT_COUNT: usize = 508; +const AGG_FINAL_PUBLIC_INPUTS_COUNT: usize = 1 + 1 + 1 + 1000; +const AGG_FINAL_PROOF_ELEMENT_COUNT: usize = 330; +const MERKLE_TREE_DEPTH: usize = 161; +const MERKLE_TREE_PATH_DEPTH: usize = MERKLE_TREE_DEPTH - 1; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RunMockAggregatorOutcome { + NoPendingBatch, + SubmittedBatch, +} + +pub async fn run_mock_aggregator( + server: &Server, + eth_node: &Arc, +) -> RunMockAggregatorOutcome { + let rollup: Arc = + Arc::new(rollup_contract(server.rollup_contract_addr, eth_node).await); + let node_client: Arc = Arc::new(NodeClientHttp::new(server.base_url())); + let block_prover = Arc::new(MockBlockProver::new(Arc::clone(&node_client))); + let backend = Arc::new(MockBbBackend::default()); + + let (rolled_root, rolled_height) = plan_mock_rollup(rollup.as_ref(), &backend).await; + + let rollup_tree: Box = + Box::new(MockRollupTree::new(rolled_root, rolled_height)); + let contract_adapter = Arc::new(ContractsRollupContract::new( + Arc::clone(&rollup), + std::time::Duration::from_secs(60), + std::time::Duration::from_millis(100), + )); + + let node_height = server.height().await.unwrap(); + assert!( + node_height.height.0 >= rolled_height, + "mock aggregator observed node height below rollup height; node={}, rollup={rolled_height}", + node_height.height.0, + ); + if node_height.height.0 == rolled_height + || !has_pending_non_empty_blocks(node_client.as_ref(), rolled_height).await + { + return RunMockAggregatorOutcome::NoPendingBatch; + } + + let agg_agg_circuit: Arc = Arc::new(AggAggCircuit); + let agg_final_circuit: Arc = Arc::new(AggFinalCircuit); + let aggregator = Aggregator::new( + node_client, + contract_adapter, + block_prover, + rollup_tree, + 2, + 1_000_000, + agg_agg_circuit, + agg_final_circuit, + ); + + let batch = match aggregator + .prepare_next_batch() + .await + .expect("prepare next aggregator batch") + { + PreparationOutcome::Success(batch) => batch, + PreparationOutcome::InsufficientBlocks { .. } => { + return RunMockAggregatorOutcome::NoPendingBatch; + } + }; + let proven = aggregator + .prove_batch(batch, Arc::clone(&backend) as Arc) + .await + .expect("prove aggregator batch"); + aggregator + .submit_batch(proven) + .await + .expect("submit aggregator batch"); + + let contract_height = rollup.block_height().await.unwrap(); + let contract_root = Element::from_be_bytes(rollup.root_hash().await.unwrap().to_fixed_bytes()); + let node_height = server.height().await.unwrap(); + assert_eq!(contract_height, node_height.height.0); + assert_eq!(contract_root, node_height.root_hash); + RunMockAggregatorOutcome::SubmittedBatch +} + +async fn plan_mock_rollup( + rollup: &contracts::RollupContract, + backend: &MockBbBackend, +) -> (Element, u64) { + let rolled_height = rollup.block_height().await.unwrap(); + let rolled_root = Element::from_be_bytes(rollup.root_hash().await.unwrap().to_fixed_bytes()); + + let agg_inputs = AggAggPublicInput { + verification_key_hash: [Element::ZERO; 2], + old_root: rolled_root, + new_root: rolled_root, + commit_hash: Element::ZERO, + messages: [Element::ZERO; 1000], + }; + backend.push_response(agg_agg_bb_output(&agg_inputs)); + + let final_inputs = AggFinalPublicInput { + old_root: rolled_root, + new_root: rolled_root, + commit_hash: Element::ZERO, + messages: agg_inputs.messages.to_vec(), + }; + backend.push_response(agg_final_bb_output(&final_inputs)); + + (rolled_root, rolled_height) +} + +struct MockBbBackend { + responses: Mutex>>, +} + +impl Default for MockBbBackend { + fn default() -> Self { + Self { + responses: Mutex::new(VecDeque::new()), + } + } +} + +impl MockBbBackend { + fn push_response(&self, bytes: Vec) { + self.responses.lock().unwrap().push_back(bytes); + } +} + +#[async_trait::async_trait] +impl BbBackend for MockBbBackend { + async fn prove( + &self, + _program: &[u8], + _bytecode: &[u8], + _key: &[u8], + _witness: &[u8], + _oracle: bool, + ) -> Result, BbError> { + self.responses + .lock() + .unwrap() + .pop_front() + .ok_or_else(|| BbError::Backend("missing mock barretenberg response".into())) + } + + async fn verify( + &self, + _proof: &[u8], + _public_inputs: &[u8], + _key: &[u8], + _oracle: bool, + ) -> Result<(), BbError> { + Ok(()) + } +} + +struct MockBlockProver { + node_client: Arc, +} + +impl MockBlockProver { + fn new(node_client: Arc) -> Self { + Self { node_client } + } +} + +#[async_trait::async_trait] +impl BlockProverTrait for MockBlockProver { + async fn prepare( + &self, + height: u64, + tree: &mut dyn RollupTree, + ) -> Result { + let response = self + .node_client + .blocks(BlockHeight(height), 1, true) + .await + .map_err(map_node_error)?; + let block = response.blocks.first().cloned().ok_or_else(|| { + BlockProverError::ImplementationSpecific(Box::new(std::io::Error::other(format!( + "missing block {height}" + )))) + })?; + + let old_root = tree.root_hash(); + let new_root = block.block.content.state.root_hash; + tree.insert(&[(new_root, height)])?; + tree.set_height(height); + + let mut chunks: [PreparedChunk; UTXO_AGGREGATIONS] = + std::array::from_fn(|_| padding_chunk()); + chunks[0] = PreparedChunk { + old_root, + new_root, + bundles: default_bundles(), + }; + + Ok(PreparedBlock { height, chunks }) + } + + async fn prove( + &self, + prepared: PreparedBlock, + _bb_backend: Arc, + ) -> Result { + let chunk = prepared.chunks[0].clone(); + Ok(AggAggProof { + proof: ProofBytes::default(), + public_inputs: AggAggPublicInput { + verification_key_hash: [Element::ZERO; 2], + old_root: chunk.old_root, + new_root: chunk.new_root, + commit_hash: Element::ZERO, + messages: [Element::ZERO; 1000], + }, + kzg: vec![], + }) + } +} + +fn default_bundles() -> [UtxoProofBundleWithMerkleProofs; UTXO_AGG_NUMBER] { + std::array::from_fn(|_| UtxoProofBundleWithMerkleProofs::default()) +} + +fn padding_chunk() -> PreparedChunk { + PreparedChunk { + old_root: Element::ZERO, + new_root: Element::ZERO, + bundles: default_bundles(), + } +} + +struct MockRollupTree { + root: Element, + height: u64, +} + +impl MockRollupTree { + fn new(root: Element, height: u64) -> Self { + Self { root, height } + } +} + +impl RollupTree for MockRollupTree { + fn root_hash(&self) -> Element { + self.root + } + + fn height(&self) -> u64 { + self.height + } + + fn set_height(&mut self, height: u64) { + self.height = height; + } + + fn sibling_path(&self, _element: Element) -> Result, BlockProverError> { + Ok(vec![Element::ZERO; MERKLE_TREE_PATH_DEPTH]) + } + + fn remove(&mut self, _element: Element) -> Result<(), BlockProverError> { + Ok(()) + } + + fn insert(&mut self, entries: &[(Element, u64)]) -> Result<(), BlockProverError> { + if let Some((element, _)) = entries.last() { + self.root = *element; + } + Ok(()) + } +} + +fn agg_agg_bb_output(inputs: &AggAggPublicInput) -> Vec { + let mut bytes = Vec::with_capacity( + AGG_AGG_PUBLIC_INPUTS_COUNT * BYTES_PER_ELEMENT + + AGG_AGG_PROOF_ELEMENT_COUNT * BYTES_PER_ELEMENT, + ); + + for element in &inputs.verification_key_hash { + bytes.extend_from_slice(&element.to_be_bytes()); + } + bytes.extend_from_slice(&inputs.old_root.to_be_bytes()); + bytes.extend_from_slice(&inputs.new_root.to_be_bytes()); + bytes.extend_from_slice(&inputs.commit_hash.to_be_bytes()); + + for message in &inputs.messages { + bytes.extend_from_slice(&message.to_be_bytes()); + } + + bytes.extend(vec![4u8; AGG_AGG_PROOF_ELEMENT_COUNT * BYTES_PER_ELEMENT]); + bytes +} + +fn agg_final_bb_output(inputs: &AggFinalPublicInput) -> Vec { + let mut bytes = Vec::with_capacity( + AGG_FINAL_PUBLIC_INPUTS_COUNT * BYTES_PER_ELEMENT + + AGG_FINAL_PROOF_ELEMENT_COUNT * BYTES_PER_ELEMENT, + ); + + bytes.extend_from_slice(&inputs.old_root.to_be_bytes()); + bytes.extend_from_slice(&inputs.new_root.to_be_bytes()); + bytes.extend_from_slice(&inputs.commit_hash.to_be_bytes()); + + for message in &inputs.messages { + bytes.extend_from_slice(&message.to_be_bytes()); + } + + bytes.extend(vec![5u8; AGG_FINAL_PROOF_ELEMENT_COUNT * BYTES_PER_ELEMENT]); + bytes +} + +fn map_node_error(err: NodeInterfaceError) -> BlockProverError { + BlockProverError::ImplementationSpecific(Box::new(err)) +} + +async fn has_pending_non_empty_blocks(node_client: &dyn NodeClient, rolled_height: u64) -> bool { + let start_height = rolled_height + .checked_add(1) + .expect("rolled height overflow while checking pending aggregator blocks"); + match node_client.blocks(BlockHeight(start_height), 1, true).await { + Ok(response) => response + .blocks + .into_iter() + .any(|block| block.block.content.header.height.0 >= start_height), + Err(err) if is_blocks_not_found(&err) => false, + Err(err) => panic!("query pending aggregator blocks: {err}"), + } +} + +fn is_blocks_not_found(err: &NodeInterfaceError) -> bool { + let NodeInterfaceError::Client(err) = err else { + return false; + }; + let Some(err) = err.as_ref().downcast_ref::() else { + return false; + }; + + matches!( + err, + NodeClientHttpError::UnknownErrorOutput(output, _, metadata) + if output.error.code == ErrorCode::NotFound && metadata.path == "/blocks" + ) +} diff --git a/pkg/node/tests/rpc/blocks_tree.rs b/pkg/node/tests/rpc/blocks_tree.rs new file mode 100644 index 0000000..54625eb --- /dev/null +++ b/pkg/node/tests/rpc/blocks_tree.rs @@ -0,0 +1,83 @@ +use std::sync::Arc; + +use barretenberg_cli::CliBackend; +use element::Element; +use hash::hash_merge; +use zk_circuits::Prove; +use zk_primitives::{InputNote, Note, Utxo, bridged_polygon_usdc_note_kind}; + +use super::{Server, ServerConfig, mint, rollup_contract, usdc_contract}; +use testutil::eth::EthNode; + +#[tokio::test(flavor = "multi_thread")] +async fn block_tree_include_block_outputs() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + + let (alice_note, eth_tx, node_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(10u64), + Element::ZERO, + ) + .await; + eth_tx.await.unwrap(); + let tx = node_tx.await.unwrap(); + + let response = server + .block_tree(tx.height, None) + .await + .expect("fetch block elements"); + + assert_eq!(response.height, tx.height); + assert_eq!(response.root_hash, tx.root_hash); + let tree_elements = response + .elements + .as_ref() + .expect("full tree should be included when diff_from is not provided"); + assert!( + tree_elements.contains(&alice_note.commitment()), + "expected minted note commitment in block elements snapshot" + ); + + // Spend Alice's note to Bob so we exercise removals + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + let bob_note = Note::new_with_psi( + bob_address, + Element::from(10u64), + Element::ZERO, + bridged_polygon_usdc_note_kind(), + ); + let input_note = InputNote::new(alice_note.clone(), alice_pk); + let utxo = Utxo::new_send( + [input_note, InputNote::padding_note()], + [bob_note.clone(), Note::padding_note()], + ); + let backend = CliBackend; + let send_proof = utxo.prove(&backend).await.unwrap(); + let send_tx = server.transaction(&send_proof).await.unwrap(); + + let post_send = server + .block_tree(send_tx.height, Some(tx.height)) + .await + .expect("fetch block elements after send"); + assert!( + post_send.elements.is_none(), + "diff responses should omit the full tree to avoid recomputation" + ); + let diff = post_send + .diff + .expect("diff should be present when diff_from is requested"); + assert_eq!(diff.from_height, tx.height); + assert_eq!(diff.additions, vec![bob_note.commitment()]); + assert_eq!(diff.removals, vec![alice_note.commitment()]); +} diff --git a/pkg/node/tests/rpc/elements.rs b/pkg/node/tests/rpc/elements.rs new file mode 100644 index 0000000..e9656e7 --- /dev/null +++ b/pkg/node/tests/rpc/elements.rs @@ -0,0 +1,116 @@ +use std::sync::Arc; + +use barretenberg_cli::CliBackend; +use element::Element; +use hash::hash_merge; +use zk_primitives::{InputNote, Note, Utxo, bridged_polygon_usdc_note_kind}; + +use super::{Server, ServerConfig, mint, rollup_contract, usdc_contract}; +use testutil::eth::EthNode; +use zk_circuits::Prove; + +#[tokio::test(flavor = "multi_thread")] +async fn list_elements_unspent_default() { + let eth_node = EthNode::default().run_and_deploy().await; + let server_config = ServerConfig::single_node(false); + let server = Server::setup_and_wait(server_config, Arc::clone(ð_node)).await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + + let (alice_note, eth_tx, node_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(10u64), + Element::ZERO, + ) + .await; + eth_tx.await.unwrap(); + let tx = node_tx.await.unwrap(); + + let commitment = alice_note.commitment(); + let list = server + .list_elements(&[commitment], false) + .await + .expect("list_elements failed"); + assert_eq!(list.len(), 1, "expected exactly one element"); + let item = &list[0]; + assert_eq!(item.element, commitment); + assert_eq!(item.height, tx.height.0); + assert!(!item.spent, "expected unspent element to have spent=false"); +} + +#[tokio::test(flavor = "multi_thread")] +#[ignore] // Requires Ethereum node - skip in CI +async fn list_elements_include_spent() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + let (alice_note, eth_tx, node_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(5u64), + Element::ZERO, + ) + .await; + eth_tx.await.unwrap(); + let _tx = node_tx.await.unwrap(); + + // Spend Alice's note to Bob so Alice's commitment is removed from the tree + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + let bob_note = Note::new_with_psi( + bob_address, + Element::from(5u64), + Element::ZERO, + bridged_polygon_usdc_note_kind(), + ); + let input_note = InputNote::new(alice_note.clone(), alice_pk); + let utxo = Utxo::new_send( + [input_note, InputNote::padding_note()], + [bob_note, Note::padding_note()], + ); + let backend = CliBackend; + let snark = utxo.prove(&backend).await.unwrap(); + let _resp = server.transaction(&snark).await.unwrap(); + + let commitment = alice_note.commitment(); + + // Default behavior should not include spent elements + let list_default = server + .list_elements(&[commitment], false) + .await + .expect("list_elements failed"); + assert!( + list_default.is_empty(), + "expected no elements without include_spent" + ); + + // With include_spent=true we should see it and it should be marked as spent + let list_spent = server + .list_elements(&[commitment], true) + .await + .expect("list_elements failed"); + assert_eq!( + list_spent.len(), + 1, + "expected one element with include_spent" + ); + let item = &list_spent[0]; + assert_eq!(item.element, commitment); + assert!( + item.spent, + "expected spent=true for previously spent element" + ); +} diff --git a/pkg/node/tests/rpc/empty.rs b/pkg/node/tests/rpc/empty.rs index 9ae2dc4..8966af8 100644 --- a/pkg/node/tests/rpc/empty.rs +++ b/pkg/node/tests/rpc/empty.rs @@ -1,5 +1,5 @@ +use constants::MERKLE_TREE_DEPTH; use testutil::eth::EthNode; -use zk_circuits::constants::MERKLE_TREE_DEPTH; use crate::rpc::ServerConfig; diff --git a/pkg/node/tests/rpc/merkle.rs b/pkg/node/tests/rpc/merkle.rs index a6a2289..c487244 100644 --- a/pkg/node/tests/rpc/merkle.rs +++ b/pkg/node/tests/rpc/merkle.rs @@ -1,10 +1,11 @@ +// lint-long-file-override allow-max-lines=300 use std::sync::Arc; +use element::Element; use expect_test::expect; use testutil::eth::EthNode; -use zk_primitives::Element; -use crate::rpc::{mint, rollup_contract, ServerConfig}; +use crate::rpc::{ServerConfig, mint, rollup_contract}; use super::usdc_contract; @@ -23,7 +24,9 @@ async fn merkle() { &server, Element::new(1), Element::from(100u64), - ); + Element::ZERO, + ) + .await; eth_mint_tx.await.unwrap(); tx.await.unwrap(); @@ -34,165 +37,165 @@ async fn merkle() { [ [ 0x0, - 0x2ba00861b8f1581f5e17d438e323fa2809f58f1a60009dcd05edb1c9c7c833da, - 0xfa0082e09dd9cc2d8a236938f628b668d57f7b6cb72008ac03142111050864c, - 0x15894af6b6c0549fa9cd30128579a2dc0c567ed7cabfb09bff95949341a9ac81, - 0x1196ddacfe831a4c4a002c3287c5d7b7e62f393acc5dfb9a44e8d4e42852c630, - 0x2e7cc44f05afd41946244940e561ae69222c657950e6540cf9a5589ac2665887, - 0x18a8a74c4cf90a653286ff96cb8bc367eb4a45eaadf256e46f5dedcc969afde7, - 0xcf1ec907e066d0522395aba3c93e3b85aed37d1f51d9503a461a33d3d600128, - 0xda004968db5a60e1689936fa00b858b23187fc0702d07c6b439116d8ee6dec8, - 0x181312e20b6687d377125bc687e156dc8a2167502524d4e56164ceda881ed5fb, - 0x2fd86a1ceaea396f5fb3d98d667bf0e3af20e5b00328fdae766024d96fe923f3, - 0x2cd010d45400358310a2806b6e81c732615fb19396106d8cdd429a066ec4c93b, - 0x26a66bd2ee4162c99a4f0b04ff2f23b69d7bd5841f642760aa590c77528bcb79, - 0x2d0e0d42612b3497ab4033be4d8bce8324b48b1b1e7d7eedddc70a43e8a11b53, - 0x29cb3d60d1d9ea510c929bea0dc112781190aefdd8dc938b5d8478b7d04e6f82, - 0x1ef66fa5658e40fec30020d1796a417ee4b81668b49a71318973d23d3822fb0f, - 0x193b047ed90559dd7cb4e85140d7f92422e3c69f90a049e8d0be21bec59c7ad9, - 0xcfcaec39ff6cf9310f45b44abff9f1c8cfbd5428b785592d3ba8626d1c5b467, - 0x26e15d391281e8698157e32a22635c3b8f6ce159fa398ba4c4ecd8c363e358b2, - 0x25ba03a2973fbc88f7b976626e63586b9330b6ddb08a07aa9c577ce3bb1d3f39, - 0x1f98b89c9a0eafbd9dd569f3d8c5d3e0d3da62b6d358214b4b94a70ba317a5b6, - 0x2c7254b5504739b2384f40bd702c9b1d7aa5559a924b38c545206327790fe23b, - 0x1ad2b9d6ed2c042e2e815f9ea51f1417e8df49da4d5935354df37eec8105b173, - 0x8a9dc89f3b17592f0e55d4e1b818ebd876fc8dafdacb28afb54ad97a482a292, - 0x18d5107e17690548b5fc2cd3c2c532f40448ba29166611ed139261125ac95ed8, - 0x34659157a0f40421b20f7d138b79d1c22f6d5ac16b23ca0ab6791ff40de26eb, - 0x2b22abdfce9a96e2c7306ebaf45f64c7e0c2e7738119447776a6aac223565dfa, - 0x63b1ef8cfe229647b0aff38cff254f8c20e21381881a147f6cf977709a44edc, - 0x11686509090e942105341635ed4a2735c8240b491c75a158f9e8ff4f0a89d25f, - 0x93c360a8f834b92f7e5eac996f164a0a05c3ea454b334efa8b7dcfc2603a179, - 0x36724ee92610cbd02258014d4252e5dbf8e55c85f3fca802ab2d33069e560df, - 0x285013a6c0d3d6b7ee02566ebcba866ed801ddcf6eb852522c2b195c3287de7d, - 0x6334f3c5298ad916b6999c5b2404046b52cabed931e6a75008b6792afb1e5b8, - 0x1fc17d9d3b264f123d7619aa30b1bf07772c1ec90ae9ffec87814d5513e917c5, - 0xa7f2ad12d4e7b7b47e26e9ac4c50aeeef3340e9e938a0d63263f7d04dc47965, - 0x14a929f2e9a65f0ee918baa8d2165ebc566a07c704a4918fa57e9f8867e098c6, - 0x21c0e64648ca0af081e4d5aee2284a953411ba83c816b766f5b7ac3a1c5f2ea, - 0x1e60f854fccdf9186e6fdeffe35b1781d72a5e5084c1f9cdacbdf59682b2b6da, - 0x27ee017018f45efbd35d1c13becfccf19930a17ffdeada836308586f7a17652b, - 0x544f3743bc9686e28c6c1c6f7e05d9882befbf4d81c1a9c9d19e4ac04f0c772, - 0x27027b296144ff2f66b259eacc9ae658f54ec80f1e1778e08863976fc1333122, - 0xfe4d2582275a130e303b95758bebe9003985eea6db0aa7a813170f9d44e6c6b, - 0x2b2a56fc63705101358d464dd6f96f6a2f40d0d22929a82a13f38b4e1ef83c5a, - 0x21136a71eb3e0ccad128ed0c5fae4acf435935142cc4fea0cb5ca5245f964c09, - 0x109aa23474c1223413e13d176196f0b448c413df7ea091f20d5acfbe94c2adb2, - 0x24812503a9748360aca77f150d6ada11b3bca7c8eb76a7c045f4455347f569ff, - 0x24e75967390b53e4667ea7b202070f0e9ba1d6e4a24fa98403de9a6c0afd1be4, - 0x1fc5c8ba7bea28dcaea544338a6466600d8bbf3eea093c912168dc4544d33109, - 0x2ff0a633dccfaf90a76262a6c7771a4b7707ada7d11691494bab0bd44332fd78, - 0x140a69600cfe5daca43117a5915001b474e9be63f8654a745d7e993e5a24667d, - 0x19ef5205ba4137f9a5ed1d653c485f020d583f5adf5f82ffb1accbff613dedad, - 0xe99a2b688ce12dda9a54d7f46294409528b6c2465dd115e9b7edbbfbce6885e, - 0x159b0b17f684742dc49112891bb04d2ec062c68985bd3c2bfdd9b4d008f4092a, - 0x1f94545a8c4c82da4c5faef5a8bd37e5b767d5c758f3cf2c82a671cad380e80d, - 0x1ae026e0eb3eb3a299c4d6d4b93ab200dd183d951d088c6b73aae56693073e16, - 0xda75df3d02f700a29702d2d867e8152106e15a6b3248f406d90dcbce9e03418, - 0xa58a88c183eb1f7cb645758052d439d6264fd212a0e8aaa49dcec034a641c05, - 0x2984944ab07ac291118becffefd8dde8da228ddf99057060e402ee82cf68d2f7, - 0x24508e620942303909250d9c9fc529374f64963448da76cfc8475c2c425faab4, - 0x507c07e3bf4b56fcee9aa982dddfbe440e02ea3beb0cb8a9ae95ddfda5fbbde, - 0xe5592d32d17e603a77406fa21672096996fe7f54f394efef7de7702a13f6bba, - 0x2deb5197b1d60ba97dfc37ec3015411da21c4d77dd9ba013f6d43fe4ef28fd19, - 0x25b425103cbf4d26b7da0388c00f9800c1c54d4cc92155cee9326394b91834a7, - 0x2b2dbad7e25fe587c8ecb97565c4bd9e0a40c4961a56338031cd8d915f893e90, - 0x27b6938eb53bcebe08152e94567c23a2b83cf6fcebb86d046bf199d015c169db, - 0x9012b9bb4d4c0a6780f1c1e28c1a96cf89c379e11eac30bc771e79bbfcc053, - 0x252bf1ab57061be6cefaaf2aa7ddd6ec2e835388e40c7053602103e1b783c322, - 0x173dfc638518e03edd94a5b486cec75b9aa6069b45b798e4b400fe18f6979cd9, - 0x11f0842a361399af7446e5745e3fb6495883bfd2356a9139911bc444a657d0fb, - 0x1c398263a2ed1b23d33d880184f388223711b7df30f87dda37bb084f91f53698, - 0x2afdcc3a40cccedb8a98e0b1196ee9f63f181f87a551eb44d3d50189b7ffee6c, - 0x17082b729fca0c048af719f83d26767cbb44eead9619d42f44741ec81c3d8a59, - 0x5f1be7515c6d34d4598a1bb17e8e7fafe5c3a99c1425f0eefb9e0fedef63d5a, - 0x5b5765901c85a9da1c3aae8d119866701d69f2382e9c4aa304c9bbc57ecd0af, - 0x27a3b0457254c48693d271502fdea91d33a3b89cbb1d22935e73969562187efe, - 0xdcea5250a826f3f5acded4b85c74551f5b326fdf9c2ef91bf2f5ecc410f4ef8, - 0x1f379e6864a284f383987c53f943226ed9a9def9df9c2e1281f3038db8b73069, - 0xcaa4d9ddf67f8e978965105dc4c294e1558f5be96a5ab20abee26f06a86b878, - 0x1db72ce81df8fdb4aa7e66eaad248dacb30de46e3fd86bcb9dffc342b0b24617, - 0x2314cdb07373f9a1fd7ded5b9ea565de4505b41aa3d5156958a923ea2e1923ac, - 0x97d34ba4f29d89e80d542735f3bc99bfa93c5966d54c88ee2802fbe50c97c58, - 0x12533b89ca25234e4dea018caa44f300ce713b106e654cfd4ea679c5412e7959, - 0x2884459a3ffe9ab537b7f5ec5a86f1793e4f028d8bab3cdf2a400907d3ed96f9, - 0x1394f07051dddb186e9182b095121087855f242cf11334f245a704e42a4183ff, - 0x22955f8513585f0fedf06ed81b534223ac5fa5a992bc78a761c2087a5ac7baf2, - 0x2f8301832bde89a531681692b8e6f0bf136e939b9b8c03e8d24b77fa624ddfb8, - 0x118e5c94e59a2cd73d3b00c4c4483fccbdc42f070f246af0fc0a86eaa51fbf99, - 0x267b0901de64e0220079c220f161c51e244c53c3279390140774b7b5bc574e40, - 0x214b939514396f2ca90881b1f921f4ff3b31a16852308571dc8077fa1eb37656, - 0x26d48477fc326e88f1134913143fae780d71de284652660add809d39866509e0, - 0x1145c8fd39f3456b393b71e8611d5fad9125947322284f8548309be82531609b, - 0x2086513dd7eb6578f2aba16707468de7d16ad760fe528331c0e96bd2c4a4036c, - 0x13c570d595c0fde0070d159223092afa5588b01a87a75844adbf4a110514fd2b, - 0x27c8bcdc4210198f4e29c8f9a4b13dc0aa3c00a9107e30f4419a16b0cb4d5366, - 0x2629bd6dae28951476867adbd259179f48686e0cde662b59bff836c8b2d6831f, - 0x5a7c99dc95d6d4e9d46236adc2deedc67b678b67336ccf783a53b044bfcf5f1, - 0x36510786765e76b1c7fa376ceb48c82a4d1ddcf263b7dd82aa93b90ef4fa78d, - 0x1f53f9d04b27c91342057aa34f15969b2c641c95892fae689a39c1957fccb530, - 0x125ee4de8d7089d8261d33831f0e4325766de85caa77791cd39a3a908aab2c17, - 0x194c4130d3f1b4772b96a30272d79da42df1292d248374c0806ea5d199af9746, - 0xca3cb766448934cd89fe8a1631727d97d8019521f51782495dcd169968c8337, - 0x35d951b1d12f5843439a0721b580af43300b06e7de281774d4c8c9f182534c9, - 0x2bb501e9511bb182edad8dd8806a6a294586673a0c72d4a1269704d729cc3357, - 0x2aa87225c3d169c5137ec4a7fd1873961db3844aae14f9a3a2078a27c35c5038, - 0x256f32fe2edf48dfe279cb3b726351a2d4d365b577c4470ec44f88eb7c1242cc, - 0x1f6225529eb00cfd73675e721ea058be52176deab58c64795777739e0cee6cf8, - 0x2e693346afd5d191e5dbfbba4cdfb0d9bc53c797deea50d55cb5f7d13e60fdb8, - 0x2c6c7a27f0c2a0de21fa33a0e0f069be431529271bdf0da2ffce52a28ae0235a, - 0x2f90bd167db8b47ae2d0ea7cc70543e78591c007da07072e9f95a29b54a3991c, - 0x10b25567ba36f0abb42f536e9a6fb5844f9f5010cff1c8487eba4f6c540c0064, - 0x2276bc9b659de721f352a0442febbea9026aa81c1c3f115061ebbbadf37d7683, - 0xedd0555c6ecf3a7c1e0bacb1207f9daef31c1679134bf302cca22a8c1cc54, - 0x218dcea0df356a2f081351f450a7f0962369b4e648b91200972a5835e4a06503, - 0x1d69b9822fe5728269b97d7a03c999a9fbdbc98920f314e9a41252f5ef2fb5f7, - 0x152a306eb8a4dc149c0e4452dfeab442b90c7eb7a9a930ac3bd38fb0c7a1b833, - 0x15e401b95e184dc3e6c0e1f2286f49f4359b80b9b96eb8d5a9d19d5ee3092146, - 0x2cb80795764b18c4b627c9232c1b2dafbf0ae4baeee1c5c2e6eceb3b30c36555, - 0x294d52725db793d6a2dcf07ecbde9f02b056028d2ee0e11f408cbe0ef234b194, - 0x16df97d34e665d9cb326e39406aff9a0b39f17486749911bfba484770e142cd5, - 0x1eb4c97ca54d4b1adbe2fcdad6c5fdf9a38f1bad81096ef6777e4361016676ad, - 0x7a308ef1477c1e390b8b214e8ca80a7977cf2be687d67cb349fc82ebdb87b31, - 0x2527942088d4ba989eeacbd70a6acd4ed3cdee752363ac4ce3833107acd2d8c3, - 0x189a361042b61e7110848dff866a6a4a29ef815e609e3ffbc33183e1b6154fdd, - 0x2cd0bd86569a39970ad6bf2da3224582e4286180f3165a800e1fe3325960783, - 0xf34bf67ad006a684438b07434e91a3c17d9ac96ea1c71a6275e193a43f0d7, - 0x78d0d3c786f837a3d8b9efff48842213f1d219d04786e6eee2abee305cc86af, - 0x92cbb658b1ecd01d9f1ee20fe6a68a5f496f42ace98fd2121c04b378921decb, - 0x1ee266caa678ef7fea4aab420b5aa7475c7b68fe880ccc7c86e810126eb6d1cd, - 0x143b87b510452a62a2e51b9871053decf891b70061b1a79f2ae8f87f37b8acf8, - 0x1fb5320ee24d0fbcf175aa684e62696ddb6f223f871d695826a36361add1661d, - 0x1c34c61be4ced83bf40a0bee9b29d7e6e9b3d1410373a2a510270aafa007088, - 0x1aa855b00ced895b2184fb178f1cf5f44f8f88def97c8fce964df15993116183, - 0x1086a9dd3f295f3f01dcd830e3aa0b62645362426a1dda0eabc74e50372b0a52, - 0xb2109c29b79aa99ba8d442dc6474f6d84120028729b6b3d176d0dcf3a1604f6, - 0x7a88f9504ba43e4ce71340c31b5af809d1f9b6f1e9f4d0f9768248c5d7dd088, - 0x22c3e71fab692ae8783769d2ea3888d6fe1d2b023a9dc76f805c9b23bff2e05f, - 0x1dd9b20d0c4daa00a94fa36608951270bdc155bc4f8324c90146771f088ea143, - 0x15749bb855186a554c3e3622be72a779662eb930659ccf28ed248b0c86dc7055, - 0x252fd9f88628078919388aac15a0d82c782ae32c86132f3bd9b4958729b14136, - 0x17d6be2861eded7c6c96c5ffb8aacc7c4c0cc7a3a5127aaf0dbe96e2251add7f, - 0x6e7ac72836cfd43a812a953a4bea6ee4fcb727e55d43c546855aa38382f312a, - 0x27dfcd4ffd0d6973a06d34be17ba029cc8a6459d8d12be848683d2e062750495, - 0x5010920284b5fcbb77cf4cdfb7a025d1fda2419901ee2d1030fbe758cbe723, - 0x1e41a2afbbe0f7fad4bf11cee21748817a5102e57937511eac918fc6c81568db, - 0x2b2b02f42458e2c1444ad79c4c227da347dc22db00c47dc2a0336ef7ef77478a, - 0x467b1d559d17f600f8476b79bbc44c10efa14603b441d68580f8595426d9e04, - 0x1fc9e2d15bb823ca4be72512f612e6276669cb1c6b76326c32b6e9000c2eeb54, - 0x1f45dcfc01d7e8e186d9fda3c70915d548584bc9d4f2d5c8de85f90947e3ea0a, - 0xff71f6ef2c10f43103eedb6755394555afb2aab7742a66284c451a5523ed445, - 0xc2c279fba7dd01bc126ecd1ff474b41a16e98459347225606d750b1a644c849, - 0x1cd4c5ec22ccb66acf72ab5b42f9f0009e850c56f73b348f35e17011bbf6daf, - 0xe030f83a4f043ed6fd8afb9880b04ed0a12da734c814412c687c0baa9cf842d, - 0xd154640cac2aae058c07b17d7d410c2ab05a1f556e2775f345d1f6f666d864a, - 0xea35bedb3fdb789063d7b0b3eba2d0fc783e0638c15d6f54587af8221158e8f, - 0x21111d6c57bddb775be680be28720e07eca3aec542667574e2d4caf43284d759, - 0x26357c4e2253a07f6e072b1126e3ba2d2bbbf82514ef8d7a43a1da727afcca1d, - 0x77667291e6c8ad34ac18971ca6dbcffd78f9caaf74ef2cdac367b1a12bfa4c0, - 0x2a1516069c40654857ac5183d347e322fd110d06abe6c9ad9a08b9f97ce62a32, - 0x2b78671c0ad73e9c5a5a22ff38cd1b5dd6f89ee35290a77ab02081846116e17, - 0x1729f54054d00d17bb46d4afb4446f4ae32ca87f4a768d1f1ffcb0117281d0b8, + 0xb63a53787021a4a962a452c2921b3663aff1ffd8d5510540f8e659e782956f1, + 0xe34ac2c09f45a503d2908bcb12f1cbae5fa4065759c88d501c097506a8b2290, + 0x21f9172d72fdcdafc312eee05cf5092980dda821da5b760a9fb8dbdf607c8a20, + 0x2373ea368857ec7af97e7b470d705848e2bf93ed7bef142a490f2119bcf82d8e, + 0x120157cfaaa49ce3da30f8b47879114977c24b266d58b0ac18b325d878aafddf, + 0x1c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76, + 0x2d78ed82f93b61ba718b17c2dfe5b52375b4d37cbbed6f1fc98b47614b0cf21b, + 0x67243231eddf4222f3911defbba7705aff06ed45960b27f6f91319196ef97e1, + 0x1849b85f3c693693e732dfc4577217acc18295193bede09ce8b97ad910310972, + 0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686, + 0xf320b0703439a8114f81593de99cd0b8f3b9bf854601abb5b2ea0e8a3dda4a7, + 0xd07f6e7a8a0e9199d6d92801fff867002ff5b4808962f9da2ba5ce1bdd26a73, + 0x1c4954081e324939350febc2b918a293ebcdaead01be95ec02fcbe8d2c1635d1, + 0x197f2171ef99c2d053ee1fb5ff5ab288d56b9b41b4716c9214a4d97facc4c4a, + 0x2b9cdd484c5ba1e4d6efcc3f18734b5ac4c4a0b9102e2aeb48521a661d3feee9, + 0x14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3, + 0x71d7627ae3b2eabda8a810227bf04206370ac78dbf6c372380182dbd3711fe3, + 0x2fdc08d9fe075ac58cb8c00f98697861a13b3ab6f9d41a4e768f75e477475bf5, + 0x20165fe405652104dceaeeca92950aa5adc571b8cafe192878cba58ff1be49c5, + 0x1c8c3ca0b3a3d75850fcd4dc7bf1e3445cd0cfff3ca510630fd90b47e8a24755, + 0x1f0c1a8fb16b0d2ac9a146d7ae20d8d179695a92a79ed66fc45d9da4532459b3, + 0x38146ec5a2573e1c30d2fb32c66c8440f426fbd108082df41c7bebd1d521c30, + 0x17d3d12b17fe762de4b835b2180b012e808816a7f2ff69ecb9d65188235d8fd4, + 0xe1a6b7d63a6e5a9e54e8f391dd4e9d49cdfedcbc87f02cd34d4641d2eb30491, + 0x9244eec34977ff795fc41036996ce974136377f521ac8eb9e04642d204783d2, + 0x1646d6f544ec36df9dc41f778a7ef1690a53c730b501471b6acd202194a7e8e9, + 0x64769603ba3f6c41f664d266ecb9a3a0f6567cd3e48b40f34d4894ee4c361b3, + 0x1595bb3cd19f84619dc2e368175a88d8627a7439eda9397202cdb1167531fd3f, + 0x2a529be462b81ca30265b558763b1498289c9d88277ab14f0838cb1fce4b472c, + 0xc08da612363088ad0bbc78abd233e8ace4c05a56fdabdd5e5e9b05e428bdaee, + 0x14748d0241710ef47f54b931ac5a58082b1d56b0f0c30d55fb71a6e8c9a6be14, + 0xb59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d, + 0x2c45bb0c3d5bc1dc98e0baef09ff46d18c1a451e724f41c2b675549bb5c80e59, + 0x121468e6710bf1ffec6d0f26743afe6f88ef55dab40b83ca0a39bc44b196374c, + 0x2042c32c823a7440ceb6c342f9125f1fe426b02c527cd8fb28c85d02b705e759, + 0xd582c10ff8115413aa5b70564fdd2f3cefe1f33a1e43a47bc495081e91e73e5, + 0xf55a0d491a9da093eb999fa0dffaf904620cbc78d07e63c6f795c5c7512b523, + 0x21849764e1aa64b83a69e39d27eedaec2a8f97066e5ddb74634ffdb11388dd9a, + 0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6, + 0x1fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb, + 0x1a180441acbe2e25177de322888800476d75191e3c2c753300dedf84de7d2053, + 0x2ac5dda169f6bb3b9ca09bbac34e14c94d1654597db740153a1288d859a8a30a, + 0x2de9cf8ca22a0c9f7ac822564e7e90726457ffdee6107772e7461aa6dacf876d, + 0x15e4cf322bd4693b5ba17d7d77599ed6b40e943b15d4b652dcd1b206f57a4c6e, + 0x2f79c24831208eb014af76127ee58b95cf9598ad1dad9c82e19f10b7fee8f6f, + 0x19d4d18c572a9b0b503094e1de87b8594e1d37dd1da42acdb3a19bd35f005a3a, + 0x24d3e3c36e11f6dac11d08927f0a925e2c4c42248a913c18da9f5cc0da73836a, + 0x131b0345b2f2564b2338810cd8d7b90a8d5a2fcc1a9a8876a494dbe3c8135c6c, + 0xe765e363b659fafffce80bef02723bbbea3669cc9b07f327b4fc9c959c169a5, + 0xf2d774b6dc7c8c6c49e2056f9f9e77d510637ff52368027fd8326821c83445a, + 0x16599e0bb19201fa33d4c00c3f7c5189552a26038ee219b1c8b08fd1b16ecd52, + 0x22f62d7c8204be97acc7644d4b14a422c17e573506e900a4788acbfb8c8b1aba, + 0x691a1f6e7dd363914d2754f434659383019fe2a1d10a9ce92d152decccfc5f5, + 0x1250a6bd4582016e8af7d74a31a7d181864326e50cea97f643b70ec9d94e1efc, + 0x2d2011d328f63f5cb9eb68a6806f8ce624ceb84a876a390fda61d6d6bb5a530, + 0x1b593cc9332c0bb29333e5833284e18e765bb17fc0a7718f6b21d8a833a0765b, + 0x19bffd7d85c0863485890e50a717ebb21d4b888f0268d9c7258a3db25f969d9, + 0x12340d5bb49b5667c9194321fc364488d0f082a8fb1bc4f1b96359209b1bf110, + 0x2209d88df4bf41b2e002ff46f8ac45aa4ec8b222f4551c178fe50f99b505681f, + 0x4f95f7efd61e5dfab009860f0e53b7e65686c5dbb1b1a800d597ec130836f92, + 0x74b0f589c0d62b3ee0d70fd057f9d0e143a6b888d0a9f60ac1d0f1c77ddf863, + 0x5e7d0fbf97820e4f7e37899bee6f967bc67f5b396f760665eb5ce76f51cff90, + 0xee294cdea89cdfb6a3fd3f85316222c2e6e7482b9cd052cea388141037acdb5, + 0x73f3f1b95b5cafa069fe1bb5e08c8586775783cc6a11c35ab0107dbd0437dd6, + 0x12a604345e9442be58176866c68899249a7c14a777af0938a759826474ebb215, + 0xb983d964a33bdccf941858b4eed650917cc9c35265f14ec2715dc6999c0489, + 0x1a1a7fbdc860bcc40d4b3eea4c8f469f991050b9fb6ef33ca3694edc4f36a82b, + 0xdf2ad5009b0aa7b9cc62d10f9fddc978e28452ef5f3bb3d274743359383592b, + 0x16e0518517026f2c7cbf14301679bcecd00e8babaf0bda664c49b02dcda6b4dd, + 0x205e35d27e9528e137e8f93ff50b877d6f0fa3230e1215df6360ef7ca4b3680a, + 0x2b14a855c417e66c86c9e1bd864e0a5b00d45bbe84e6d93749ef109d25790d9d, + 0x2cde883b4ec6916a780528e64ab784c3c081ed2d71397c5d739a5bd4f24a8e3c, + 0x1bf2b15c37a3eb5f94bbf12c10e19a22f3c8ddde72133d9fe32db2be7387a77c, + 0x1fd2be106c935c189640b47d2ad9deb51ff348845b7e6cf0eca562435735fa67, + 0x3029a5ede685ae7e42e029a4f1b22a0575d6b5cef84f695a2f987ede9fe41280, + 0x2c16523888340ddb03fff41ab7a56b492c345a76411e5d3467360264cc5f67, + 0x2c6d19a82f4a7679d929c99dbbe056cf07e74fe0460e9d5b81226b9b2283d96d, + 0x2c5164b5c7798ae26796f2374fe1acace1a69b5772352fdd9c09e83b95847e75, + 0xd31f8f2a4e34d6731f1042d995d4ab9b3f9dc01e033446521947534ed617886, + 0x1f1a7feb56222e6eb83bf3beb69f5efcc05d10c2cff3d6c3f5b8134943ef678e, + 0x24c4aca03d4a952cc1b2879b1241b0669afde82390de9fc8edad89c2fda41014, + 0x1c0857ed41b1a306a787fd591e14f0190c7332745112e4d4aaa4f71fcdb18b1e, + 0x145e3cb92e0058bc04394485e73dd1f9ba87c2cc15a3b201c027e43109dbef81, + 0x26e0aeb64465f3ad7046be46afc13c942be769135549b36c833947b4e0da69df, + 0x21f428f358cce02f84038fd4cbd838dabd72b8ceed847cde16375f1c98ab81fd, + 0xc3e112a2286b468499a5ea53e050bcb848dc0f70c7d758c7602e327746a063b, + 0x291d939f9e3a70af5d6d2d8caffc34175cbfab587d4e9e293821806149453d9e, + 0x2e81f77acaf016b7fc5567d50a96773c72743783e7bba0e5a12a4a135485a49f, + 0x12e0e08c58426173229fb99e97a35c8f75a8c4f30ec5ed8fbe7b00c81765c2ec, + 0x25ee0b3dc3db03f85b355d34f156066cc1ad50112589092d90de8ebb4017d116, + 0xb29d0ddf485319a9bfbf6b263e865a67c6122e7f47ecc482f591f92e4effaf4, + 0x140f26545084fcd739e0abf03a75d1c889b8dd99818e9ae23ed638a63fee2191, + 0x2fb6de61ff780b7274373cb13232d4c9ad8487c6ebb1e3121a16ddec2c4b624c, + 0x854275e7235881668b5b98251a66d8c9b82af0a6451da41d0eac04d4e7811c8, + 0x822679ef57fef500de54d6cba8415ce9ac944d3afb1dd4cacce2b2ff451403f, + 0x1d0ca0d26b8051fcceaedb7a95f25c4cd5e71ffce3ae1f2942c3612c8f6e80a8, + 0x2353d576c4d9f118a4bc7b2c492f7164cf173bc2c37d17f7fa6126c7d0094927, + 0x188e9347138c524bda0413d4ad63350c88ba806491204abd61a285d192d50e14, + 0x126c2038a88263356a46f4de9a59b538df61a3c4cedee042ba66193debf0d4b7, + 0x1b34d0aba99f650468f0d3241fab6192755b6ee17d345f3c23f784c365e97e52, + 0x13f60d322ff331eeb58a3c85acc593c97f8930c1f07e92b9c19772ba6f185221, + 0x10d2b5662f6977c2cf9b23c1d7dfce6a56ccc7baf7bc7b2cbb505368828888c1, + 0x1000b1532ad15dab1910284d08588e0ed96b09a95a7b06180bd40f3e43041aa4, + 0xe4425e6397061fb0a1cb79d4861ee8e780ec260783d6462dda5109cf13e0311, + 0x13999b236cd8cb12546b95e2234e5e92f2dbe1ea227ee7ff9477896864d9c26f, + 0x16253ee85a590b7d7e450d3ef38b6d8d72e57d7985d98fdae9d3e69d280e1490, + 0x849dd12c0483e541856ebf80f3fe755a4f4cbc02a3921c2909d04890f9ce86b, + 0x2f4f55d48db9c60e9b822552c9db290c03cfa51fe52e0980f99fd882bd2e0065, + 0x26e9c4c282f2aba00a3f528e04abab1e63df8a908636c7295a4f67135c986e75, + 0x1d5717b6a1d0d20e41d35e2c7d0b4fa001924d91618550026106b4fc2b978b9e, + 0x16276c3116072ae2d3815ebef6eae3c7418641bc048667418409cb1a36a3c6bd, + 0x200ace77e0d131b2652e782f50136c4f3e7bd21b7342327715ae96796b0e4785, + 0x303f0d0ee0cfc4509ac0174c85aad3ee1aab586e90b118f8de5aa446d2aec8ca, + 0x21d023dac5b44bad38d5b4f08ecc711cc9f9a916ee3a8e9e406236cef888f7e8, + 0x1ee0da36a81b54a9eef3b4b0a1b2f8d697855a48b8db44478aa2383eb635b218, + 0x2dbabb204983acc8179b7b3242862961b174d22f4fefcd81e68c6549c9a88cea, + 0x23954e35feba58a113fa213392abd035c2b032f0b4e83c2f52a83d18e54433bc, + 0x2aed396db05f304fc6775f10e0aa0dceeefe297e511ad478414eb1ab84844957, + 0x25221fd64e70bb4c90b30a2fb1852ddaa8704ba4680584651c3c9732f501e138, + 0x4e4fe96e487b1979011964d97719275a68773ee23ba55fe2f809d69c10c3a22, + 0x2c212b4c639445a6c03ea31cc755c51433c61afbed9eea3556b36f27cdf344a6, + 0x249a023bda5b6a8d6b1e3d994693cdd3ad81f0282b95d5a15ddc36b195138e4e, + 0x156b5cd887b306896b7ca039e2afa02868ba62817d7b7e5d2896ae14e1a9a7e5, + 0x162d3e89ec9131809bc10150382a744f65af577521cc37c46bd00912f3eb4d31, + 0x22075061e5564be974e193731c06a4e22cfc8242a38180c732ad2f0d4604e3fe, + 0xb6b9c320f299ad3afd75f0d0bd81afbb0e757f8307f61978d5de7817f608327, + 0x506e0a856c856e7634ab226160b6a323261a3e0c8810f68e2743a4263b57ee2, + 0x2413c3e2b026ffff5628832762082690520fc5a22f825e3af1a86cc435901981, + 0x2cef9a3613e8172d950b3c1cb7cab1224277ad2712ac02e96dc8519794a8ad5f, + 0xf636c6a10dbda008e10895d5b588f5b5d01a5da3a09c361c1a0b548b560b220, + 0x18c09a08d500307171b4f240ce0f2c5e78866ec7e6374a0176047fa890fba0ff, + 0xa3cc6a6411731de29dc727f71370d6c9ad89980d868ed69220b8807e76c9f1a, + 0x199c7b72643a56c5dacc094c5ab51c19ea6d4e2ab5067abd873cfd728483ee3a, + 0xa9c91ec9d961021c7f3e816b9aa9a04257acde68474586c8a9d9d5c940807e8, + 0x14c5fd147f901e87ded8a14a4fc59939bfb72af7f7e67186e733fe9bb2d03eca, + 0x1acef925c3cca5dc9f0a031563d268374fdb1719c59b743c7ee6667ef6879399, + 0xea860a77c1c5de892c3659365c610d079fa8d064fc0982291d5b2313505b8a2, + 0xcf81c182313729421c7b9a627208a70acde524a61589b88630842aec4151fbe, + 0x3c1dd4555254c7c2663290bee910ae8f7359fe0cc45e306a9df149b9583fc28, + 0x2380880753bc787886c9330c047d222cc2a90ac6be2fe1bbe69c3be7c83c7b0e, + 0x1db6521a766a6d998d0502d2543209962f3352d55e72b29656bfc3d7e2a250d8, + 0x5c4aa57c046dd90cdccc970263f2dec18fa0dac5108e96d9ef1511758d3d191, + 0xc879e4b1793ca7ad312adf8d83aa14a3b7df00eff18e9e9b8d1da21dc0b3033, + 0x2f234d5aab8610df7b41caf56ed7db37efde646138f699c64da49313f944b20b, + 0x2abb52222822ff819894aa1506aceb69cdd387abb73d541f1e8ba8f971fb4375, + 0x1d9472930835607a1a5543cc38ab10b3db29aa5bd46d779548a05927fae2531c, + 0x22b45ca22855701aa0ecb8609bdc31390e8c94cd9935202ed90d90c07e5f6c67, + 0xa1f39f29473f6a16b502a67dc2683705e177ef3763ca210b36a6222f201928c, + 0x156cc79f3ce078aad6e5696dca53bd414daee13f69b6e1843927981c36505697, + 0x228e1ea054fd72054b743d4d83e8cb1fd688fcf6e988b79cd73c590befbea8c8, + 0x26b7327ab922821bd4f8140cce34ff4ccea50fbc5422ae813c2656408cce3a70, + 0x1f88cb99931d78883fc9390abb33404b4b7d45ab032cfabf43c2cba6bf04924c, + 0x2c9a9e3033be9def3f405a74334e13abda0a9bf0e2dded80e07464946626163c, + 0x1ffba91116956a6d7499ce126e4d007b26ba57aa42ca8d260b1e6cd7f38541c5, + 0x4d01766bf4af18c1c993689ba59328da95a06be98204edda80174720e47b975, + 0xa3a44d64bcf0c2b158912d887c5993e9568331b7249d98aed3e143c555bee34, + 0x1b03b3acfb879340d7ded90a8a34d6aaa567e052a02fde21942fee82e8f66410, + 0x26fa331c2375a0bb32aa7f2084a5ff100db2398c10a3415fb1d082dffd478794, + 0x27db7d141d06b30011b01150c3a4e29bb43e22eed0d8c7e73219256fad9255f8, ], ] "#]]; diff --git a/pkg/node/tests/rpc/mod.rs b/pkg/node/tests/rpc/mod.rs index e17ee2d..a7fbb6e 100644 --- a/pkg/node/tests/rpc/mod.rs +++ b/pkg/node/tests/rpc/mod.rs @@ -1,11 +1,22 @@ +// lint-long-file-override allow-max-lines=800 +mod aggregator_support; +mod blocks_tree; +mod elements; mod empty; mod merkle; +mod smirk; +mod stats; mod sync; mod transaction; mod types; +use barretenberg_cli::CliBackend; +use element::Element; +use node_interface::BlockTreeResponse; pub use types::*; -use web3::{contract::tokens::Tokenizable, ethabi::Token, signing::keccak256}; +use zk_circuits::Prove; + +use crate::rpc::types::ElementsListItem; use std::{ env::VarError, @@ -13,30 +24,18 @@ use std::{ path::PathBuf, process::Command, str::FromStr, - sync::{mpsc, Arc, Mutex}, + sync::{Arc, Mutex, mpsc}, }; -use contracts::{ - util::{convert_element_to_h256, convert_h160_to_element}, - Address, RollupContract, SecretKey, USDCContract, -}; +use contracts::{Address, RollupContract, SecretKey, USDCContract, util::convert_h160_to_element}; use futures::Future; -// use ethereum_types::H160; -// use node::util::public_to_address; use once_cell::sync::Lazy; -use primitives::hash::CryptoHash; +use primitives::{block_height::BlockHeight, hash::CryptoHash}; use reqwest::Url; use serde_json::json; -use sha3::Digest; -use testutil::{eth::EthNode, PortPool}; +use testutil::{PortPool, eth::EthNode}; use tokio::runtime::RuntimeFlavor; -use wire_message::WireMessage; -use zk_circuits::{ - constants::MERKLE_TREE_DEPTH, - data::{Burn, BurnTo, InputNote, Mint, Note, ParameterSet, SnarkWitness}, - CircuitKind, -}; -use zk_primitives::Element; +use zk_primitives::{InputNote, Note, UtxoProof, bridged_polygon_usdc_note_kind}; type Error = serde_json::Value; @@ -70,7 +69,7 @@ impl ServerConfig { keep_port_after_drop, safe_eth_height_offset: 0, rollup_contract: Address::from_slice( - &hex::decode("2279b7a0a67db372996a5fab50d91eaa73d2ebe6").unwrap(), + &hex::decode("dc64a140aa3e981100a9beca4e685f962f0cf6c9").unwrap(), ), secret_key: hex::decode( "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", @@ -88,41 +87,16 @@ impl ServerConfig { ..Self::single_node(keep_port_after_drop) } } - - // TODO: once we bring this back, we need to configure EthNode to spawn with multiple validators - // fn four_nodes(keep_port_after_drop: bool) -> [Self; 4] { - // let config = |secret_key| Self { - // keep_port_after_drop, - // rollup_contract: Address::from_slice( - // &hex::decode( - // "2279b7a0a67db372996a5fab50d91eaa73d2ebe6", - // ) - // .unwrap(), - // ), - // secret_key: hex::decode(secret_key).unwrap().try_into().unwrap(), - // mock_prover: false, - // }; - - // // First 4 default hardhat accounts - // [ - // config("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"), - // config("59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"), - // config("5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a"), - // config("7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6"), - // ] - // } } #[derive(Debug)] struct Server { process: Option, - // Keep the root dir alive so that server can use it root_dir: tempdir::TempDir, api_port: u16, p2p_port: u16, secret_key: [u8; 32], rollup_contract_addr: Address, - // address: H160, peers: Vec, keep_port_after_drop: bool, safe_eth_height_offset: u64, @@ -139,7 +113,6 @@ struct Server { #[derive(Debug, Clone)] struct Peer { p2p_port: u16, - // _address: H160, } impl Drop for Server { @@ -166,8 +139,6 @@ impl Server { match std::env::var("COPY_DATA_FROM_DIR") { Ok(copy_data_from_dir) => { - // copy both ${COPY_DATA_FROM_DIR}/db and ${COPY_DATA_FROM_DIR}/smirk to root_dir/db and root_dir/smirk - // making sure that the directories exist in COPY_DATA_FROM_DIR for dir in &["db", "smirk"] { let src = PathBuf::from(©_data_from_dir).join(dir).join("latest"); let dst = root_dir.path().join(dir).join("latest"); @@ -185,13 +156,6 @@ impl Server { Err(VarError::NotUnicode(_)) => panic!("COPY_DATA_FROM_DIR has invalid unicode"), } - // let public_key = secp256k1::SecretKey::from_slice(&config.secret_key) - // .unwrap() - // .public_key(secp256k1::SECP256K1); - // let public_key_bytes = public_key.serialize_uncompressed(); - // let public_key_bytes = TryInto::<[u8; 64]>::try_into(&public_key_bytes[1..]).unwrap(); - // let address = public_to_address(&public_key_bytes.into()); - let (stdout_sender, stdout) = mpsc::channel(); let (stderr_sender, stderr) = mpsc::channel(); @@ -203,11 +167,7 @@ impl Server { safe_eth_height_offset: config.safe_eth_height_offset, secret_key: config.secret_key, rollup_contract_addr: config.rollup_contract, - // address, - peers: vec![Peer { - p2p_port, - // _address: address, - }], + peers: vec![Peer { p2p_port }], prover: config.mock_prover, api_port, p2p_port, @@ -229,7 +189,6 @@ impl Server { fn to_peer(&self) -> Peer { Peer { p2p_port: self.p2p_port, - // _address: self.address, } } @@ -338,7 +297,6 @@ impl Server { } if std::thread::panicking() { - // If a test failed, print the last 10 lines of output so we can debug node errors let stdout = self .stdout .recv_timeout(std::time::Duration::from_secs(10)) @@ -393,14 +351,6 @@ impl Server { } } - // fn reset_db(&mut self) { - // std::fs::remove_dir_all(self.root_dir.path().join("db")).unwrap(); - // } - - // fn reset_smirk(&mut self) { - // std::fs::remove_dir_all(self.root_dir.path().join("smirk")).unwrap(); - // } - async fn setup_and_wait(config: ServerConfig, eth_node: Arc) -> Self { let mut server = Self::new(config, eth_node); server.run(None); @@ -425,7 +375,7 @@ impl Server { match self.client.execute(req).await { Ok(res) if res.status().is_success() => return Ok(()), Ok(res) if is_last_retry => { - return Err(format!("Failed to get health: {}", res.status()).into()) + return Err(format!("Failed to get health: {}", res.status()).into()); } Ok(_) => {} Err(err) if is_last_retry => return Err(err.into()), @@ -439,42 +389,23 @@ impl Server { async fn wait(&self) -> Result<(), Box> { self.wait_for_healthy().await?; - Ok(()) } #[allow(dead_code)] async fn wait_to_notice_sync(&self) -> Result<(), Box> { self.wait_for_healthy().await?; - - // When a node starts up, it doesn't know if it's out of sync yet, - // so /v0/health returns 200 OK, but practically the node is not - // ready to serve requests yet. So we wait a second to work around that. tokio::time::sleep(std::time::Duration::from_secs(10)).await; self.wait_for_healthy().await?; - Ok(()) } - // async fn wait_for_height(&self, min_height: u64) -> Result<(), Error> { - // loop { - // let height = self.height().await?; - // if height.height > min_height { - // return Ok(()); - // } - // tokio::time::sleep(std::time::Duration::from_millis(100)).await; - // } - // } - - pub async fn transaction( - &self, - snark_witness: &SnarkWitness, - ) -> Result { + pub async fn transaction(&self, proof: &UtxoProof) -> Result { let res = self .client .post(self.base_url().join("/v0/transaction").unwrap()) .json(&json!({ - "snark": snark_witness, + "proof": proof, })) .send() .await @@ -548,6 +479,64 @@ impl Server { Ok(res.json::().await.unwrap()) } + pub async fn list_elements( + &self, + elements: &[Element], + include_spent: bool, + ) -> Result, Error> { + let res = self + .client + .get(self.base_url().join("/v0/elements").unwrap()) + .query(&[ + ( + "elements", + elements + .iter() + .map(|e| e.to_hex()) + .collect::>() + .join(","), + ), + if include_spent { + ("include_spent", include_spent.to_string()) + } else { + ("", "".to_string()) + }, + ]) + .send() + .await + .unwrap(); + + if !res.status().is_success() { + let err = res.json::().await.unwrap(); + return Err(err); + } + + Ok(res.json().await.unwrap()) + } + + pub async fn block_tree( + &self, + height: BlockHeight, + diff_from: Option, + ) -> Result { + let mut request = self.client.get( + self.base_url() + .join(&format!("/v0/blocks/{}/tree", height.0)) + .unwrap(), + ); + if let Some(diff_height) = diff_from { + request = request.query(&[("diff_from", diff_height.0)]); + } + let res = request.send().await.unwrap(); + + if !res.status().is_success() { + let err = res.json::().await.unwrap(); + return Err(err); + } + + Ok(res.json().await.unwrap()) + } + pub async fn list_blocks(&self, query: &ListBlocksQuery) -> Result { let res = self .client @@ -624,9 +613,42 @@ impl Server { Ok(res.json().await.unwrap()) } + + pub async fn get_all_smirk_elements(&self) -> Result { + let res = self + .client + .get(self.base_url().join("/v0/smirk/elements/all").unwrap()) + .header("x-guild", "LC38R7uFkM&M") + .send() + .await + .unwrap(); + + if !res.status().is_success() { + let err = res.json::().await.unwrap(); + return Err(err); + } + + Ok(res.json().await.unwrap()) + } + + pub async fn stats(&self) -> Result { + let res = self + .client + .get(self.base_url().join("/v0/stats").unwrap()) + .send() + .await + .unwrap(); + + if !res.status().is_success() { + let err = res.json::().await.unwrap(); + return Err(err); + } + + Ok(res.json::().await.unwrap()) + } } -fn mint_with_note<'m, 't>( +async fn mint_with_note<'m, 't>( rollup: &'m RollupContract, _usdc: &'m USDCContract, server: &'t Server, @@ -635,16 +657,15 @@ fn mint_with_note<'m, 't>( impl Future> + 'm, impl Future> + 't, ) { - let utxo = zk_circuits::data::Utxo::::new_mint(note.clone()); - let snark = cache_utxo_proof("mint", &utxo); - - let mint = Mint::new([note.clone()]); - let proof = mint.evm_proof(ParameterSet::Eight).unwrap(); + let output_notes = [note.clone(), Note::padding_note()]; + let utxo = zk_primitives::Utxo::new_mint(output_notes.clone()); + let backend = CliBackend; + let proof = utxo.prove(&backend).await.unwrap(); ( async move { let tx = rollup - .mint(&proof, ¬e.commitment(), ¬e.value(), ¬e.source()) + .mint(&utxo.mint_hash(), ¬e.value, ¬e.contract) .await?; while rollup @@ -654,142 +675,63 @@ fn mint_with_note<'m, 't>( .transaction_receipt(tx) .await .unwrap() - .map_or(true, |r| r.block_number.is_none()) + .is_none_or(|r| r.block_number.is_none()) { tokio::time::sleep(std::time::Duration::from_millis(500)).await; } Ok(()) }, - async move { server.transaction(&snark).await }, + async move { server.transaction(&proof).await }, ) } -fn mint<'m, 't>( +async fn mint<'m, 't>( rollup: &'m RollupContract, usdc: &'m USDCContract, server: &'t Server, address: Element, value: Element, + psi: Element, ) -> ( Note, impl Future> + 'm, impl Future> + 't, ) { - let note = Note::restore(address, Element::new(0), value, Element::new(0)); - - let (eth_tx, rpc_tx) = mint_with_note(rollup, usdc, server, note.clone()); + let note = Note::new_with_psi(address, value, psi, bridged_polygon_usdc_note_kind()); + let (eth_tx, rpc_tx) = mint_with_note(rollup, usdc, server, note.clone()).await; (note, eth_tx, rpc_tx) } -fn burn<'m, 't>( - rollup: &'m RollupContract, +async fn burn<'m, 't>( server: &'t Server, - note: &'m InputNote, + note: &'m InputNote, to: &'m Address, - via_router: bool, ) -> ( impl Future> + 'm, impl Future> + 't, ) { - let utxo = - zk_circuits::data::Utxo::::new_burn(note.clone(), note.recent_root()); - let snark = cache_utxo_proof("burn", &utxo); + let input_notes = [note.clone(), InputNote::padding_note()]; + let evm_address = convert_h160_to_element(to); + let utxo = zk_primitives::Utxo::new_burn(input_notes, evm_address); + let backend = CliBackend; + let proof = utxo.prove(&backend).await.unwrap(); ( async move { - let tx = if via_router { - let router = Address::from_str("4a679253410272dd5232b3ff7cf5dbb88f295319").unwrap(); - let return_address = - Address::from_str("0000000000000000000000000000000000000001").unwrap(); - let usdc_address = rollup.usdc().await.unwrap(); - - let mut router_calldata = - keccak256(b"burnToAddress(address,address,uint256)")[0..4].to_vec(); - router_calldata.extend_from_slice(&web3::ethabi::encode(&[ - usdc_address.into_token(), - to.into_token(), - convert_element_to_h256(¬e.value()).into_token(), - ])); - - let msg = web3::ethabi::encode(&[ - Token::Address(router), - Token::Bytes(router_calldata.clone()), - Token::Address(return_address), - ]); - - let mut msg_hash = keccak256(&msg); - // Bn256 can't fit the full hash, so we remove the first 3 bits - msg_hash[0] &= 0x1f; // 0b11111 - - let burn = BurnTo { - notes: [note.note().clone()], - secret_key: note.secret_key(), - to_address: Element::from_be_bytes(msg_hash), - kind: Element::ONE, - }; - - rollup - .burn_to_router( - &Element::ONE, - &Element::from_be_bytes(msg_hash), - &burn.evm_proof(ParameterSet::Nine).unwrap(), - ¬e.nullifer(), - ¬e.value(), - ¬e.source(), - &burn.signature(note.note()), - &router, - &router_calldata, - &return_address, - ) - .await? - } else { - let burn = { - let notes = [note.note().clone()]; - let secret_key = note.secret_key(); - let to_address = convert_h160_to_element(to); - Burn { - notes, - secret_key, - to_address, - } - }; - - rollup - .burn( - to, - &burn.evm_proof(ParameterSet::Nine).unwrap(), - ¬e.nullifer(), - ¬e.value(), - ¬e.source(), - &burn.signature(note.note()), - ) - .await? - }; - - while rollup - .client - .client() - .eth() - .transaction_receipt(tx) - .await - .unwrap() - .map_or(true, |r| r.block_number.is_none()) - { - tokio::time::sleep(std::time::Duration::from_millis(500)).await; - } - + // We don't need to send an ETH transaction for burn anymore Ok(()) }, - async move { server.transaction(&snark).await }, + async move { server.transaction(&proof).await }, ) } async fn rollup_contract(addr: Address, eth_node: &EthNode) -> RollupContract { - let client = contracts::Client::new(ð_node.rpc_url(), None); + let client = contracts::Client::new(ð_node.rpc_url(), None).with_latest_nonce(); RollupContract::load( client, + 1337, &hex::encode(addr.as_bytes()), SecretKey::from_str("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") .unwrap(), @@ -804,6 +746,7 @@ async fn usdc_contract(rollup: &RollupContract, eth_node: &EthNode) -> USDCContr let client = contracts::Client::new(ð_node.rpc_url(), None); USDCContract::load( client, + 1337, &hex::encode(usdc_addr.as_bytes()), SecretKey::from_str("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80") .unwrap(), @@ -811,29 +754,3 @@ async fn usdc_contract(rollup: &RollupContract, eth_node: &EthNode) -> USDCContr .await .unwrap() } - -fn cache_proof(name: &str, f: impl FnOnce() -> SnarkWitness) -> SnarkWitness { - let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(format!("tests/cache/{name}.proof")); - - if path.exists() { - let proof = std::fs::read(&path).unwrap(); - return SnarkWitness::from_bytes(&proof).unwrap(); - } - - let proof = f(); - std::fs::write(&path, proof.to_bytes().unwrap()).unwrap(); - - proof -} - -fn hash_utxo(utxo: &zk_circuits::data::Utxo) -> [u8; 32] { - let utxo_hash = sha3::Sha3_256::digest(serde_json::to_string(&utxo).unwrap().as_bytes()); - utxo_hash.into() -} - -fn cache_utxo_proof(name: &str, utxo: &zk_circuits::data::Utxo) -> SnarkWitness { - cache_proof( - &format!("utxo-{}-{}", name, hex::encode(hash_utxo(utxo))), - || SnarkWitness::V1(utxo.snark(CircuitKind::Utxo).unwrap().to_witness()), - ) -} diff --git a/pkg/node/tests/rpc/smirk.rs b/pkg/node/tests/rpc/smirk.rs new file mode 100644 index 0000000..3473872 --- /dev/null +++ b/pkg/node/tests/rpc/smirk.rs @@ -0,0 +1,54 @@ +use std::sync::Arc; + +use element::Element; +use testutil::eth::EthNode; + +use crate::rpc::{ServerConfig, mint, rollup_contract}; + +use super::usdc_contract; + +#[tokio::test(flavor = "multi_thread")] +async fn smirk_elements_export() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + super::Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)) + .await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let (note1, eth_mint_tx1, tx1) = mint( + &rollup, + &usdc, + &server, + Element::new(1), + Element::from(100u64), + Element::ZERO, + ) + .await; + eth_mint_tx1.await.unwrap(); + let tx_resp1 = tx1.await.unwrap(); + + let smirk_elements = server.get_all_smirk_elements().await.unwrap(); + + assert_eq!(smirk_elements.len(), 1); + + assert!( + !smirk_elements.is_empty(), + "Smirk elements list should not be empty after minting." + ); + + let minted_element_info = smirk_elements + .iter() + .find(|info| info.element == note1.commitment()); + assert!( + minted_element_info.is_some(), + "Minted note commitment should be in the smirk elements list." + ); + + let info = minted_element_info.unwrap(); + assert_eq!(info.element, note1.commitment()); + assert_eq!( + info.inserted_at_height, tx_resp1.height.0, + "Inserted_at_height should match the block height of the mint transaction." + ); +} diff --git a/pkg/node/tests/rpc/stats.rs b/pkg/node/tests/rpc/stats.rs new file mode 100644 index 0000000..f9bf7f2 --- /dev/null +++ b/pkg/node/tests/rpc/stats.rs @@ -0,0 +1,48 @@ +use std::sync::Arc; + +use element::Element; +use hash::hash_merge; + +use super::{Server, ServerConfig, mint, rollup_contract, usdc_contract}; +use testutil::eth::EthNode; + +#[tokio::test(flavor = "multi_thread")] +async fn test_stats_today_counter() { + let eth_node = EthNode::default().run_and_deploy().await; + let server_config = ServerConfig::single_node(false); + let server = Server::setup_and_wait(server_config, Arc::clone(ð_node)).await; + + // Wait until stats are ready + let mut stats = loop { + match server.stats().await { + Ok(s) => break s, + Err(_) => tokio::time::sleep(std::time::Duration::from_millis(100)).await, + } + }; + + // Initial stats + assert_eq!(stats.today_txns, 0); + + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + + // Mint a transaction + let (_alice_note, eth_tx, node_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(10u64), + Element::ZERO, + ) + .await; + eth_tx.await.unwrap(); + node_tx.await.unwrap(); + + // Query stats again + stats = server.stats().await.expect("stats failed"); + assert_eq!(stats.today_txns, 1, "Expected 1 transaction today"); +} diff --git a/pkg/node/tests/rpc/sync.rs b/pkg/node/tests/rpc/sync.rs index 6bb6672..c21c97f 100644 --- a/pkg/node/tests/rpc/sync.rs +++ b/pkg/node/tests/rpc/sync.rs @@ -5,7 +5,7 @@ // use node::PersistentMerkleTree; // use prover::smirk_metadata::SmirkMetadata; // use serial_test::serial; -// use zk_primitives::Element; +// use element::Element; // use super::{Server, ServerConfig}; diff --git a/pkg/node/tests/rpc/transaction.rs b/pkg/node/tests/rpc/transaction.rs index 024e573..4bbff17 100644 --- a/pkg/node/tests/rpc/transaction.rs +++ b/pkg/node/tests/rpc/transaction.rs @@ -1,35 +1,120 @@ +// lint-long-file-override allow-max-lines=1700 +use std::rc::Rc; use std::sync::Arc; -use std::{str::FromStr, time::Duration, time::Instant}; +use std::{time::Duration, time::Instant}; +use barretenberg_cli::CliBackend; use burn_substitutor::BurnSubstitutor; -use contracts::{Address, Client, U256}; -use ethereum_types::H160; +use contracts::{ + Address, Client, ConfirmationType, RollupContract, USDCContract, util::convert_element_to_h256, +}; +use element::Element; +use ethereum_types::{H160, U256}; +use hash::hash_merge; use hex::ToHex; +use node_client_http::NodeClientHttp; use primitives::{block_height::BlockHeight, hash::CryptoHash, pagination::CursorChoice}; -use smirk::hash_merge; use testutil::eth::{EthNode, EthNodeOptions}; -use zk_circuits::{ - constants::MERKLE_TREE_DEPTH, - data::{InputNote, MerklePath, Note, Utxo}, - Base, -}; - -use zk_primitives::Element; +use web3::contract::Contract; +use zk_circuits::Prove; +use zk_primitives::generate_note_kind_bridge_evm; +use zk_primitives::{InputNote, Note, Utxo, UtxoProof, bridged_polygon_usdc_note_kind}; +use super::{Server, aggregator_support}; use crate::rpc::{ - burn, cache_utxo_proof, mint, mint_with_note, rollup_contract, usdc_contract, ElementResponse, - ListBlocksOrder, ListBlocksQuery, ListTxnOrder, ListTxnsQuery, ServerConfig, + ElementResponse, ListBlocksOrder, ListBlocksQuery, ListTxnOrder, ListTxnsQuery, ServerConfig, + burn, mint, mint_with_note, rollup_contract, usdc_contract, }; -use super::Server; +fn extract_error_code(err: &serde_json::Value) -> String { + let error_obj = err.get("error").expect("expected error object in response"); + + let primary_code = error_obj + .get("code") + .and_then(|code| code.as_str()) + .unwrap_or_default(); + + if primary_code != "bad-request" { + return primary_code.to_owned(); + } + + error_obj + .get("details") + .and_then(|details| details.get("code")) + .and_then(|code| code.as_str()) + .map(|code| code.to_owned()) + .or_else(|| { + error_obj + .get("reason") + .and_then(|reason| reason.as_str()) + .map(|reason| reason.to_owned()) + }) + .or_else(|| { + error_obj + .get("data") + .and_then(|data| data.get("code")) + .and_then(|code| code.as_str()) + .map(|code| code.to_owned()) + }) + .unwrap_or_else(|| primary_code.to_owned()) +} macro_rules! expect_root_hash { ($server:expr, $root_hash:expr) => { - let resp = $server.height().await.unwrap(); - $root_hash.assert_debug_eq(&resp.root_hash); + if option_env!("TEMP_NOIR") == Some("1") { + } else { + let resp = $server.height().await.unwrap(); + $root_hash.assert_debug_eq(&resp.root_hash); + } }; } +const ALLOWED_DUPLICATE_CODES: &[&str] = &[ + "commitment-already-pending", + "duplicate-output-commitments", + "duplicate-input-commitments", + "already-exists", +]; + +const ALLOWED_DUPLICATE_INPUT_CODES: &[&str] = &[ + "commitment-already-pending", + "duplicate-input-commitments", + "input-commitments-not-found", + "already-exists", +]; + +async fn prove_utxo(utxo: &Utxo) -> UtxoProof { + let backend = CliBackend; + utxo.prove(&backend).await.unwrap() +} + +async fn deploy_mock_erc20(rollup: &RollupContract) -> USDCContract { + let artifact = + include_str!("../../../../eth/artifacts/contracts/mocks/MockERC20.sol/MockERC20.json"); + let artifact_json = serde_json::from_str::(artifact).unwrap(); + let abi = serde_json::to_vec(artifact_json.get("abi").unwrap()).unwrap(); + let bytecode = artifact_json + .get("bytecode") + .and_then(|value| value.as_str()) + .unwrap(); + + let contract = Contract::deploy(rollup.client.client().eth(), abi.as_slice()) + .unwrap() + .confirmations(0) + .sign_with_key_and_execute(bytecode, (), &rollup.signer, Some(1337)) + .await + .unwrap(); + + USDCContract::load( + rollup.client.clone(), + 1337, + &hex::encode(contract.address().as_bytes()), + rollup.signer, + ) + .await + .unwrap() +} + #[tokio::test(flavor = "multi_thread")] async fn mint_transaction_not_in_contract() { let eth_node = EthNode::default().run_and_deploy().await; @@ -40,15 +125,18 @@ async fn mint_transaction_not_in_contract() { let usdc = usdc_contract(&rollup, ð_node).await; let root_hash_before = server.height().await.unwrap().root_hash; - let alice_pk = Base::from(0xA11CE); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); let (_note, _eth_tx, node_tx) = mint( &rollup, &usdc, &server, - alice_pk.into(), + alice_address, Element::from(100u64), - ); + Element::ZERO, + ) + .await; let time_before_sending_node_txn = Instant::now(); tokio::spawn({ let usdc = usdc.clone(); @@ -62,6 +150,7 @@ async fn mint_transaction_not_in_contract() { .wait_for_confirm( usdc.approve(H160::from_low_u64_be(1), 1).await.unwrap(), Duration::from_secs(1), + ConfirmationType::Latest, ) .await .unwrap(); @@ -69,6 +158,7 @@ async fn mint_transaction_not_in_contract() { .wait_for_confirm( usdc.approve(H160::from_low_u64_be(1), 1).await.unwrap(), Duration::from_secs(1), + ConfirmationType::Latest, ) .await .unwrap(); @@ -92,16 +182,184 @@ async fn mint_transaction_not_in_contract() { // Root hash should not change assert_eq!(root_hash_before, resp.root_hash); - expect_root_hash!( - server, - expect_test::expect![[r#" - 0x3b6dc0852dc266fa6e5d22290ce1d5a399cc316900cf683e158bd2e4590fe53 - "#]] + if option_env!("TEMP_NOIR") == Some("1") { + } else { + expect_root_hash!( + server, + expect_test::expect![[r#" + 0x577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff + "#]] + ); + } +} + +#[tokio::test(flavor = "multi_thread")] +async fn mint_transaction_with_unsupported_chain() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + let note = Note::new_with_psi( + alice_address, + Element::from(100u64), + Element::ZERO, + generate_note_kind_bridge_evm(1, H160::zero()), ); + + rollup + .call( + "addToken", + (convert_element_to_h256(¬e.contract), usdc.address()), + ) + .await + .unwrap(); + + let (eth_tx, rpc_tx) = mint_with_note(&rollup, &usdc, &server, note).await; + eth_tx.await.unwrap(); + + let err = rpc_tx.await.unwrap_err(); + let code = extract_error_code(&err); + assert_eq!(code, "unsupported-chain"); +} + +#[tokio::test(flavor = "multi_thread")] +async fn mint_usdc_then_different_token() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + + let usdc_note = { + let (usdc_note, usdc_eth_tx, usdc_node_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(100u64), + Element::ZERO, + ) + .await; + usdc_eth_tx.await.unwrap(); + let _ = usdc_node_tx.await.unwrap(); + usdc_note + }; + + let (other_token_note, other_mint_tx) = { + let other_token_note = Note::new_with_psi( + alice_address, + Element::from(50u64), + Element::from(1u64), + generate_note_kind_bridge_evm(137, H160::from_low_u64_be(2)), + ); + assert_ne!(other_token_note.contract, bridged_polygon_usdc_note_kind()); + + let other_token = deploy_mock_erc20(&rollup).await; + other_token + .mint(rollup.signer_address, 1_000_000) + .await + .unwrap(); + other_token + .approve(rollup.address(), 1_000_000) + .await + .unwrap(); + + rollup + .call( + "addToken", + ( + convert_element_to_h256(&other_token_note.contract), + other_token.address(), + ), + ) + .await + .unwrap(); + + let (other_eth_tx, other_node_tx) = + mint_with_note(&rollup, &usdc, &server, other_token_note.clone()).await; + + other_eth_tx.await.unwrap(); + let other_mint_tx = other_node_tx.await.unwrap(); + (other_token_note, other_mint_tx) + }; + + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + + { + let charlie_pk = Element::new(0xC0DE); + let charlie_address = hash_merge([charlie_pk, Element::ZERO]); + + let bob_usdc_note = Note::new_with_psi( + bob_address, + Element::from(100u64), + Element::from(3u64), + usdc_note.contract, + ); + + let charlie_other_token_note = Note::new_with_psi( + charlie_address, + Element::from(50u64), + Element::from(4u64), + other_token_note.contract, + ); + + let mixed_input_send = Utxo::new_send( + [ + InputNote::new(usdc_note.clone(), alice_pk), + InputNote::new(other_token_note.clone(), alice_pk), + ], + [bob_usdc_note, charlie_other_token_note], + ); + + match mixed_input_send.prove(&CliBackend).await { + Err(_) => {} + Ok(mixed_input_send_proof) => { + let _ = server + .transaction(&mixed_input_send_proof) + .await + .expect_err("mixed token-kind send should fail"); + } + } + } + + { + let bob_other_token_note = Note::new_with_psi( + bob_address, + Element::from(50u64), + Element::from(2u64), + other_token_note.contract, + ); + + let other_token_input_note = InputNote::new(other_token_note, alice_pk); + let other_token_transfer = Utxo::new_send( + [other_token_input_note, InputNote::padding_note()], + [bob_other_token_note.clone(), Note::padding_note()], + ); + let other_token_transfer_proof = prove_utxo(&other_token_transfer).await; + let other_token_transfer_tx = server + .transaction(&other_token_transfer_proof) + .await + .unwrap(); + assert_ne!(other_mint_tx.root_hash, other_token_transfer_tx.root_hash); + + let bob_element_info = server + .element(bob_other_token_note.commitment()) + .await + .unwrap(); + assert_eq!(bob_element_info.element, bob_other_token_note.commitment()); + } } #[tokio::test(flavor = "multi_thread")] -async fn mint_transaction() { +async fn mint_transaction_only() { let eth_node = EthNode::default().run_and_deploy().await; let mut server_config = ServerConfig::single_node(false); server_config.safe_eth_height_offset = 1; @@ -110,17 +368,18 @@ async fn mint_transaction() { let usdc = usdc_contract(&rollup, ð_node).await; let root_hash_before = server.height().await.unwrap().root_hash; - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); let (alice_note, eth_tx, node_tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(100u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); - let time_before_sending_node_txn = Instant::now(); tokio::spawn(async move { // wait for node to receive the txn tokio::time::sleep(Duration::from_secs(2)).await; @@ -128,11 +387,6 @@ async fn mint_transaction() { usdc.approve(H160::from_low_u64_be(2), 1).await.unwrap(); }); let tx = node_tx.await.unwrap(); - assert!( - time_before_sending_node_txn.elapsed() > Duration::from_secs(2), - "time_before_sending_node_txn.elapsed() was expected to be more than 2 seconds, but is: {:?}", - time_before_sending_node_txn.elapsed() - ); let resp = server.height().await.unwrap(); assert_ne!(root_hash_before, resp.root_hash); @@ -149,12 +403,15 @@ async fn mint_transaction() { } ); - expect_root_hash!( - server, - expect_test::expect![[r#" - 0x106841ef9d8e8f75d39db2106187b1f09f7b7b0d540fd6bcd7fc3181ce73cea9 - "#]] - ); + if option_env!("TEMP_NOIR") == Some("1") { + } else { + expect_root_hash!( + server, + expect_test::expect![[r#" + 0xea000ebbc4e827874e8f3743b6c68765ea7d513731625f595139bf56381827 + "#]] + ); + } } #[tokio::test(flavor = "multi_thread")] @@ -165,46 +422,46 @@ async fn mint_and_transfer_alice_to_bob() { let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; let usdc = usdc_contract(&rollup, ð_node).await; - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); let (alice_note, eth_tx, tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(100u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); let tx = tx.await.unwrap(); - let bob_pk = Base::from(0xB0B); - let bob_address = hash_merge([bob_pk.into(), Element::ZERO]); - let bob_note = Note::restore( - bob_address, - Element::new(0), - Element::from(100u64), - Element::new(0), - ); - - let path = server.merkle(&[alice_note.commitment()]).await.unwrap(); - let path = MerklePath::::new(path.paths.into_iter().next().unwrap()); + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + let bob_note = Note { + kind: Element::new(2), + contract: bridged_polygon_usdc_note_kind(), + address: bob_address, + psi: Element::new(0), + value: Element::new(100), + }; - let input_note = InputNote::new(alice_note.clone(), alice_pk.into(), path.clone()); - let utxo = Utxo::::new_transfer( + let input_note = InputNote::new(alice_note.clone(), alice_pk); + let utxo = Utxo::new_send( [input_note.clone(), InputNote::padding_note()], [bob_note, Note::padding_note()], - input_note.recent_root(), ); - let snark = cache_utxo_proof("mint_and_transfer_alice_to_bob", &utxo); + // let snark = cache_utxo_proof("mint_and_transfer_alice_to_bob", &utxo); + let snark = prove_utxo(&utxo).await; let resp = server.transaction(&snark).await.unwrap(); assert_ne!(tx.root_hash, resp.root_hash); expect_root_hash!( server, expect_test::expect![[r#" - 0xcb6a5e1ea03999766c5605fc4032d5229a37913f2d241b3b84a43fbd03b9823 - "#]] + 0xf478b616bd7df6d0443336bf26784eeefb226444106ddb5135c58cdc6927e99 + "#]] ); } @@ -216,55 +473,53 @@ async fn double_spend() { let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; let usdc = usdc_contract(&rollup, ð_node).await; - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); let (alice_note, eth_tx, tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(100u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); let _tx = tx.await.unwrap(); - let bob_pk = Base::from(0xB0B); - let bob_address = hash_merge([bob_pk.into(), Element::ZERO]); - let bob_note = Note::restore( + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + let bob_note = Note::new_with_psi( bob_address, - Element::new(0), Element::from(100u64), - Element::new(0), + Element::ZERO, + bridged_polygon_usdc_note_kind(), ); - let path = server.merkle(&[alice_note.commitment()]).await.unwrap(); - let path = MerklePath::::new(path.paths.into_iter().next().unwrap()); - - let input_note = InputNote::new(alice_note.clone(), alice_pk.into(), path.clone()); - let utxo = Utxo::::new_transfer( + let input_note = InputNote::new(alice_note.clone(), alice_pk); + let utxo = Utxo::new_send( [input_note.clone(), InputNote::padding_note()], [bob_note, Note::padding_note()], - input_note.recent_root(), ); - let snark = cache_utxo_proof("double_spend", &utxo); + // let snark = cache_utxo_proof("double_spend", &utxo); + let snark = prove_utxo(&utxo).await; let resp_1 = server.transaction(&snark); - // Attempt to double spend - let bob_note_2 = Note::restore( + let bob_note_2 = Note::new_with_psi( bob_address, - Element::new(1), Element::from(100u64), - Element::new(0), + Element::new(1), + bridged_polygon_usdc_note_kind(), ); - let utxo = Utxo::::new_transfer( + let utxo = Utxo::new_send( [input_note.clone(), InputNote::padding_note()], [bob_note_2, Note::padding_note()], - input_note.recent_root(), ); - let snark_2 = cache_utxo_proof("double_spend-2", &utxo); + // let snark_2 = cache_utxo_proof("double_spend-2", &utxo); + let snark_2 = prove_utxo(&utxo).await; let resp_2 = server.transaction(&snark_2); @@ -272,29 +527,31 @@ async fn double_spend() { match (resp_1, resp_2) { (Ok(_), Err(err)) => { - assert_eq!( - err.get("error").unwrap().get("code").unwrap(), - &serde_json::Value::String("already-exists".to_owned()) + let code = extract_error_code(&err); + assert!( + ALLOWED_DUPLICATE_INPUT_CODES.contains(&code.as_str()), + "unexpected error code {code}" ); expect_root_hash!( server, expect_test::expect![[r#" - 0xcb6a5e1ea03999766c5605fc4032d5229a37913f2d241b3b84a43fbd03b9823 - "#]] + 0xf478b616bd7df6d0443336bf26784eeefb226444106ddb5135c58cdc6927e99 + "#]] ); } (Err(err), Ok(_)) => { - assert_eq!( - err.get("error").unwrap().get("code").unwrap(), - &serde_json::Value::String("already-exists".to_owned()) + let code = extract_error_code(&err); + assert!( + ALLOWED_DUPLICATE_INPUT_CODES.contains(&code.as_str()), + "unexpected error code {code}" ); expect_root_hash!( server, expect_test::expect![[r#" - 0x14f022d43bc4804b47474131b92a2c3e563f86b143c14969655e21e9fc94c639 - "#]] + 0x27a9c15038cc9786757ea83814c73e70781f481d2504ca845cc1a5ba42ab8f11 + "#]] ); } (Ok(_), Ok(_)) => { @@ -307,78 +564,275 @@ async fn double_spend() { } #[tokio::test(flavor = "multi_thread")] -async fn burn_tx() { - let eth_node = EthNode::new(EthNodeOptions { - use_noop_verifier: true, - ..Default::default() - }) - .run_and_deploy() +async fn send_transaction_with_duplicate_inputs_is_rejected() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + let (alice_note, eth_tx, rpc_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(100u64), + Element::ZERO, + ) .await; + eth_tx.await.unwrap(); + rpc_tx.await.unwrap(); + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + let duplicate_output = Note::new_with_psi( + bob_address, + Element::from(200u64), + Element::ZERO, + bridged_polygon_usdc_note_kind(), + ); + + let input_note = InputNote::new(alice_note.clone(), alice_pk); + let utxo = Utxo::new_send( + [input_note.clone(), input_note.clone()], + [duplicate_output, Note::padding_note()], + ); + let proof = prove_utxo(&utxo).await; + + let res = server.transaction(&proof).await; + match res { + Ok(_) => panic!("duplicate inputs should be rejected"), + Err(err) => { + assert_eq!(extract_error_code(&err), "duplicate-input-commitments"); + } + } +} + +#[tokio::test(flavor = "multi_thread")] +async fn resubmitting_committed_transaction_returns_already_included() { + let eth_node = EthNode::default().run_and_deploy().await; let server = Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; - let mut prover_server = Server::new(ServerConfig::mock_prover(false), Arc::clone(ð_node)); - prover_server.set_peers(&[server.to_peer()]); - prover_server.run(None); - prover_server.wait().await.unwrap(); + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + let (alice_note, eth_tx, rpc_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(100u64), + Element::ZERO, + ) + .await; + eth_tx.await.unwrap(); + rpc_tx.await.unwrap(); + + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + + let input_note = InputNote::new(alice_note.clone(), alice_pk); + let bob_note = Note::new_with_psi( + bob_address, + Element::from(100u64), + Element::new(1), + bridged_polygon_usdc_note_kind(), + ); + let utxo = Utxo::new_send( + [input_note.clone(), InputNote::padding_note()], + [bob_note, Note::padding_note()], + ); + let proof = prove_utxo(&utxo).await; + let proof_hash = proof.hash(); + let first_tx = server.transaction(&proof).await.unwrap(); + + let err = server.transaction(&proof).await.unwrap_err(); + let error = err.get("error").expect("error object missing"); + let code = extract_error_code(&err); + assert_eq!(code, "already-exists"); + assert_eq!( + error + .get("reason") + .and_then(|reason| reason.as_str()) + .expect("reason missing"), + "txn-already-included" + ); + let data = error.get("data").expect("error data missing"); + + let err_height: BlockHeight = + serde_json::from_value(data.get("height").cloned().expect("height missing")).unwrap(); + let err_root_hash: Element = + serde_json::from_value(data.get("root_hash").cloned().expect("root_hash missing")).unwrap(); + let err_txn_hash: Element = + serde_json::from_value(data.get("txn_hash").cloned().expect("txn_hash missing")).unwrap(); + + assert_eq!(err_height, first_tx.height); + assert_eq!(err_root_hash, first_tx.root_hash); + assert_eq!(err_txn_hash, proof_hash); +} + +#[tokio::test(flavor = "multi_thread")] +async fn two_transactions_with_duplicate_output_should_conflict() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; let usdc = usdc_contract(&rollup, ð_node).await; - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); - let (alice_note, eth_tx, tx) = mint( + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + let (alice_note, alice_eth_tx, alice_rpc_tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(100u64), + Element::ZERO, + ) + .await; + + let charlie_pk = Element::new(0xC0FFEE); + let charlie_address = hash_merge([charlie_pk, Element::ZERO]); + let (charlie_note, charlie_eth_tx, charlie_rpc_tx) = mint( + &rollup, + &usdc, + &server, + charlie_address, + Element::from(100u64), + Element::from(1u64), + ) + .await; + + alice_eth_tx.await.unwrap(); + alice_rpc_tx.await.unwrap(); + charlie_eth_tx.await.unwrap(); + charlie_rpc_tx.await.unwrap(); + + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + let duplicated_output = Note::new_with_psi( + bob_address, + Element::from(100u64), + Element::ZERO, + bridged_polygon_usdc_note_kind(), ); - eth_tx.await.unwrap(); - let _tx = tx.await.unwrap(); - let path = server.merkle(&[alice_note.commitment()]).await.unwrap(); - let path = MerklePath::::new(path.paths.into_iter().next().unwrap()); + let alice_input = InputNote::new(alice_note.clone(), alice_pk); + let charlie_input = InputNote::new(charlie_note.clone(), charlie_pk); - let input_note = InputNote::new(alice_note.clone(), alice_pk.into(), path.clone()); + let utxo_1 = Utxo::new_send( + [alice_input.clone(), InputNote::padding_note()], + [duplicated_output.clone(), Note::padding_note()], + ); + let utxo_2 = Utxo::new_send( + [charlie_input.clone(), InputNote::padding_note()], + [duplicated_output.clone(), Note::padding_note()], + ); - let to = Address::from_low_u64_be(1); - let (eth_tx, tx) = burn(&rollup, &server, &input_note, &to, false); - eth_tx.await.unwrap(); + let proof_1 = prove_utxo(&utxo_1).await; + let proof_2 = prove_utxo(&utxo_2).await; - let tx_resp = tx.await.unwrap(); + let (res_1, res_2) = tokio::join!(server.transaction(&proof_1), server.transaction(&proof_2),); - for i in 0.. { - let height = rollup.block_height().await.unwrap(); - if height == tx_resp.height.0 { - break; + match (res_1, res_2) { + (Ok(_), Err(err)) | (Err(err), Ok(_)) => { + let code = extract_error_code(&err); + assert!( + ALLOWED_DUPLICATE_CODES.contains(&code.as_str()), + "unexpected error code {code}" + ); } + (Err(err1), Err(err2)) => { + let code1 = extract_error_code(&err1); + let code2 = extract_error_code(&err2); - if i == 10 { - panic!("Failed to wait for tx to be included in a block"); + assert!(ALLOWED_DUPLICATE_CODES.contains(&code1.as_str())); + assert!(ALLOWED_DUPLICATE_CODES.contains(&code2.as_str())); } - - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + (Ok(_), Ok(_)) => panic!("both transactions with duplicate outputs succeeded unexpectedly"), } +} - let balance = usdc.balance(to).await.unwrap(); - assert_eq!(balance, U256::from(100)); +#[tokio::test(flavor = "multi_thread")] +async fn two_transactions_with_duplicate_input_should_conflict() { + let eth_node = EthNode::default().run_and_deploy().await; + let server = + Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; + let usdc = usdc_contract(&rollup, ð_node).await; + + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); + let (alice_note, alice_eth_tx, alice_rpc_tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(100u64), + Element::ZERO, + ) + .await; - // TODO: run a prover (with mock proofs so its not slow) - // and wait for rollup to process the tx - // let balance = usdc.balance(to).await.unwrap(); - // assert_eq!(balance, U256::from(100)); + alice_eth_tx.await.unwrap(); + alice_rpc_tx.await.unwrap(); - expect_root_hash!( - server, - expect_test::expect![[r#" - 0x64073a527d8d8ff6986a04ceb11a9ac53b42529d15eeb00c9acdb85cd6a00b - "#]] + let bob_pk = Element::new(0xB0B); + let bob_address = hash_merge([bob_pk, Element::ZERO]); + let bob_note_1 = Note::new_with_psi( + bob_address, + Element::from(100u64), + Element::ZERO, + bridged_polygon_usdc_note_kind(), ); + let bob_note_2 = Note::new_with_psi( + bob_address, + Element::from(100u64), + Element::from(1u64), + bridged_polygon_usdc_note_kind(), + ); + + let alice_input = InputNote::new(alice_note.clone(), alice_pk); + + let utxo_1 = Utxo::new_send( + [alice_input.clone(), InputNote::padding_note()], + [bob_note_1, Note::padding_note()], + ); + let utxo_2 = Utxo::new_send( + [alice_input.clone(), InputNote::padding_note()], + [bob_note_2, Note::padding_note()], + ); + + let proof_1 = prove_utxo(&utxo_1).await; + let proof_2 = prove_utxo(&utxo_2).await; + + let (res_1, res_2) = tokio::join!(server.transaction(&proof_1), server.transaction(&proof_2),); + + match (res_1, res_2) { + (Ok(_), Err(err)) | (Err(err), Ok(_)) => { + let code = extract_error_code(&err); + assert!( + ALLOWED_DUPLICATE_INPUT_CODES.contains(&code.as_str()), + "unexpected error code {code}" + ); + } + (Err(err1), Err(err2)) => { + let code1 = extract_error_code(&err1); + let code2 = extract_error_code(&err2); + + assert!(ALLOWED_DUPLICATE_INPUT_CODES.contains(&code1.as_str())); + assert!(ALLOWED_DUPLICATE_INPUT_CODES.contains(&code2.as_str())); + } + (Ok(_), Ok(_)) => panic!("both transactions with duplicate inputs succeeded unexpectedly"), + } } #[tokio::test(flavor = "multi_thread")] -async fn burn_to_address_via_router() { +async fn burn_tx() { let eth_node = EthNode::new(EthNodeOptions { use_noop_verifier: true, ..Default::default() @@ -396,29 +850,24 @@ async fn burn_to_address_via_router() { let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; let usdc = usdc_contract(&rollup, ð_node).await; - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); let (alice_note, eth_tx, tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(100u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); let _tx = tx.await.unwrap(); - let rollup_balance = usdc.balance(rollup.address()).await.unwrap(); - assert_eq!(rollup_balance, U256::from(100)); - - let path = server.merkle(&[alice_note.commitment()]).await.unwrap(); - let path = MerklePath::::new(path.paths.into_iter().next().unwrap()); - - let input_note = InputNote::new(alice_note.clone(), alice_pk.into(), path.clone()); + let input_note = InputNote::new(alice_note.clone(), alice_pk); let to = Address::from_low_u64_be(1); - - let (eth_tx, tx) = burn(&rollup, &server, &input_note, &to, true); + let (eth_tx, tx) = burn(&server, &input_note, &to).await; eth_tx.await.unwrap(); let tx_resp = tx.await.unwrap(); @@ -429,7 +878,7 @@ async fn burn_to_address_via_router() { break; } - if i == 10 { + if i == 120 { panic!("Failed to wait for tx to be included in a block"); } @@ -439,12 +888,23 @@ async fn burn_to_address_via_router() { let balance = usdc.balance(to).await.unwrap(); assert_eq!(balance, U256::from(100)); - let rollup_balance = usdc.balance(rollup.address()).await.unwrap(); - assert_eq!(rollup_balance, U256::from(0)); + expect_root_hash!( + server, + expect_test::expect![[r#" + 0x577b5b4aa3eaba75b2a919d5d7c63b7258aa507d38e346bf2ff1d48790379ff + "#]] + ); + + assert_eq!( + aggregator_support::run_mock_aggregator(&server, ð_node).await, + aggregator_support::RunMockAggregatorOutcome::NoPendingBatch, + "mock aggregator should not find a pending batch after the burn was rolled up" + ); } #[tokio::test(flavor = "multi_thread")] -async fn substitute_burn_to_address_via_router() { +#[ignore] // Requires Ethereum node - skip in CI +async fn substitute_burn_to_address() { let eth_node = EthNode::new(EthNodeOptions { use_noop_verifier: true, ..Default::default() @@ -462,39 +922,38 @@ async fn substitute_burn_to_address_via_router() { let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; let usdc = usdc_contract(&rollup, ð_node).await; + let node_client = NodeClientHttp::new(server.base_url()); + let mut burn_substitutor = BurnSubstitutor::new( rollup.clone(), - server - .base_url() - .to_string() - .trim_end_matches('/') - .to_owned(), + usdc.clone(), + Box::new(node_client), Duration::from_millis(50), + Vec::new(), ); - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); let (alice_note, eth_tx, tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(100u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); let _tx = tx.await.unwrap(); let rollup_balance = usdc.balance(rollup.address()).await.unwrap(); assert_eq!(rollup_balance, U256::from(100)); - let path = server.merkle(&[alice_note.commitment()]).await.unwrap(); - let path = MerklePath::::new(path.paths.into_iter().next().unwrap()); - - let input_note = InputNote::new(alice_note.clone(), alice_pk.into(), path.clone()); + let input_note = InputNote::new(alice_note.clone(), alice_pk); let to = Address::from_low_u64_be(1); - let (eth_tx, tx) = burn(&rollup, &server, &input_note, &to, true); + let (eth_tx, tx) = burn(&server, &input_note, &to).await; eth_tx.await.unwrap(); let tx_resp = tx.await.unwrap(); @@ -541,118 +1000,105 @@ async fn substitute_burn_to_address_via_router() { } #[tokio::test(flavor = "multi_thread")] -async fn burn_to_address_via_router_with_failing_router_call() { - let eth_node = EthNode::new(EthNodeOptions { - use_noop_verifier: true, - ..Default::default() - }) - .run_and_deploy() - .await; - +async fn double_mint() { + let eth_node = EthNode::default().run_and_deploy().await; let server = Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; - let mut prover_server = Server::new(ServerConfig::mock_prover(false), Arc::clone(ð_node)); - prover_server.set_peers(&[server.to_peer()]); - prover_server.run(None); - prover_server.wait().await.unwrap(); - let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; let usdc = usdc_contract(&rollup, ð_node).await; - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash_merge([alice_pk, Element::ZERO]); let (alice_note, eth_tx, tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(100u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); let _tx = tx.await.unwrap(); - let path = server.merkle(&[alice_note.commitment()]).await.unwrap(); - let path = MerklePath::::new(path.paths.into_iter().next().unwrap()); + let (_eth_tx, tx) = mint_with_note(&rollup, &usdc, &server, alice_note.clone()).await; - let input_note = InputNote::new(alice_note.clone(), alice_pk.into(), path.clone()); - - // USDC transfer should revert with 'transfer to the zero address' - let to = Address::zero(); - let (eth_tx, tx) = burn(&rollup, &server, &input_note, &to, true); - eth_tx.await.unwrap(); - - let tx_resp = tx.await.unwrap(); - - for i in 0.. { - let height = rollup.block_height().await.unwrap(); - if height == tx_resp.height.0 { - break; - } - - if i == 10 { - panic!("Failed to wait for tx to be included in a block"); - } - - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; - } - - let return_address_balance = usdc - .balance(Address::from_str("0000000000000000000000000000000000000001").unwrap()) - .await - .unwrap(); - assert_eq!(return_address_balance, U256::from(100)); - - let rollup_balance = usdc.balance(rollup.address()).await.unwrap(); - assert_eq!(rollup_balance, U256::from(0)); + let err = tx.await.unwrap_err(); + let error = err.get("error").unwrap(); + assert_eq!(extract_error_code(&err), "already-exists"); + assert_eq!( + error + .get("reason") + .and_then(|reason| reason.as_str()) + .unwrap(), + "txn-already-included" + ); expect_root_hash!( server, expect_test::expect![[r#" - 0x64073a527d8d8ff6986a04ceb11a9ac53b42529d15eeb00c9acdb85cd6a00b + 0xea000ebbc4e827874e8f3743b6c68765ea7d513731625f595139bf56381827 "#]] ); } #[tokio::test(flavor = "multi_thread")] -async fn double_mint() { +async fn double_mint_same_mint_hash_different_address() { let eth_node = EthNode::default().run_and_deploy().await; + let server = - Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await; + super::Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)) + .await; + let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; - let usdc = usdc_contract(&rollup, ð_node).await; - let alice_pk = Base::from(0xA11CE); - let alice_address = hash_merge([alice_pk.into(), Element::ZERO]); - let (alice_note, eth_tx, tx) = mint( - &rollup, - &usdc, - &server, - alice_address, - Element::from(100u64), - ); - eth_tx.await.unwrap(); - let _tx = tx.await.unwrap(); + let alice_pk = Element::new(0xA11CE); + let alice_address = hash::hash_merge([alice_pk, Element::ZERO]); - let (_eth_tx, tx) = mint_with_note(&rollup, &usdc, &server, alice_note.clone()); + let bob_pk = Element::new(0xB0B); + let bob_address = hash::hash_merge([bob_pk, Element::ZERO]); - let err = tx.await.unwrap_err(); + let psi = Element::ZERO; + let value = Element::from(100u64); + let note_kind = bridged_polygon_usdc_note_kind(); + + // Compute mint_hash (same for both since same psi) + let mint_hash = hash::hash_merge([psi, Element::ZERO]); + + // Submit to EVM + rollup.mint(&mint_hash, &value, ¬e_kind).await.unwrap(); + + // Mint note A for Alice + let alice_note = Note::new_with_psi(alice_address, value, psi, note_kind); + let utxo_a = Utxo::new_mint([alice_note.clone(), Note::padding_note()]); + let proof_a = prove_utxo(&utxo_a).await; + let _tx_a = server.transaction(&proof_a).await.unwrap(); + + // Mint note B for Bob with same psi + let bob_note = Note::new_with_psi(bob_address, value, psi, note_kind); + let utxo_b = Utxo::new_mint([bob_note.clone(), Note::padding_note()]); + let proof_b = prove_utxo(&utxo_b).await; + let tx_b_err = server.transaction(&proof_b).await.unwrap_err(); assert_eq!( - err.get("error").unwrap().get("reason").unwrap(), - &serde_json::Value::String("commitment-conflict".to_owned()) + tx_b_err.get("error").unwrap().get("reason").unwrap(), + &serde_json::Value::String("mint-hash-already-exists".to_owned()) ); - expect_root_hash!( - server, - expect_test::expect![[r#" - 0x106841ef9d8e8f75d39db2106187b1f09f7b7b0d540fd6bcd7fc3181ce73cea9 - "#]] + // Check only one note was minted + let alice_element = server.element(alice_note.commitment()).await.unwrap(); + assert_eq!(alice_element.element, alice_note.commitment()); + + let bob_element_err = server.element(bob_note.commitment()).await.unwrap_err(); + assert_eq!( + bob_element_err.get("error").unwrap().get("reason").unwrap(), + &serde_json::Value::String("element-not-found".to_owned()) ); } #[tokio::test(flavor = "multi_thread")] async fn query_transactions() { let eth_node = EthNode::default().run_and_deploy().await; - let server = Arc::new( + let server = Rc::new( Server::setup_and_wait(ServerConfig::single_node(false), Arc::clone(ð_node)).await, ); let rollup = rollup_contract(server.rollup_contract_addr, ð_node).await; @@ -662,8 +1108,15 @@ async fn query_transactions() { let alice_address = hash_merge([alice_pk, Element::ZERO]); let mut notes = vec![]; for value in [50u64, 100] { - let (alice_note, eth_tx, tx) = - mint(&rollup, &usdc, &server, alice_address, Element::from(value)); + let (alice_note, eth_tx, tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(value), + Element::from(value), + ) + .await; eth_tx.await.unwrap(); let tx = tx.await.unwrap(); notes.push((alice_note, tx)); @@ -672,7 +1125,7 @@ async fn query_transactions() { for note in ¬es { let resp = server.get_transaction(note.1.txn_hash).await.unwrap(); assert!(resp.txn.time > 1); - assert!(resp.txn.proof.leaves().contains(&(note.0.commitment()))); + // assert!(resp.txn.proof.leaves().contains(&(note.0.commitment()))); let not_found = server .get_transaction(CryptoHash::new([0; 32])) @@ -688,14 +1141,14 @@ async fn query_transactions() { let resp = server.list_transactions(&Default::default()).await.unwrap(); // Latest transaction should be first assert_eq!(resp.txns.len(), 2); - assert!(resp.txns[0] - .proof - .leaves() - .contains(&(notes[1].0.commitment()))); - assert!(resp.txns[1] - .proof - .leaves() - .contains(&(notes[0].0.commitment()))); + // assert!(resp.txns[0] + // .proof + // .leaves() + // .contains(&(notes[1].0.commitment()))); + // assert!(resp.txns[1] + // .proof + // .leaves() + // .contains(&(notes[0].0.commitment()))); } { @@ -709,10 +1162,10 @@ async fn query_transactions() { .await .unwrap(); assert_eq!(resp.txns.len(), 1); - assert!(resp.txns[0] - .proof - .leaves() - .contains(&(notes[0].0.commitment()))); + // assert!(resp.txns[0] + // .proof + // .leaves() + // .contains(&(notes[0].0.commitment()))); // Next page let resp = server @@ -724,10 +1177,10 @@ async fn query_transactions() { .await .unwrap(); assert_eq!(resp.txns.len(), 1); - assert!(resp.txns[0] - .proof - .leaves() - .contains(&(notes[1].0.commitment()))); + // assert!(resp.txns[0] + // .proof + // .leaves() + // .contains(&(notes[1].0.commitment()))); // Previous page let resp = server @@ -739,10 +1192,10 @@ async fn query_transactions() { .await .unwrap(); assert_eq!(resp.txns.len(), 1); - assert!(resp.txns[0] - .proof - .leaves() - .contains(&(notes[0].0.commitment()))); + // assert!(resp.txns[0] + // .proof + // .leaves() + // .contains(&(notes[0].0.commitment()))); // Previous page again should return nothing let resp = server @@ -765,10 +1218,10 @@ async fn query_transactions() { .await .unwrap(); assert_eq!(resp.txns.len(), 1); - assert!(resp.txns[0] - .proof - .leaves() - .contains(&(notes[1].0.commitment()))); + // assert!(resp.txns[0] + // .proof + // .leaves() + // .contains(&(notes[1].0.commitment()))); // Next page let resp = server @@ -779,10 +1232,10 @@ async fn query_transactions() { .await .unwrap(); assert_eq!(resp.txns.len(), 1); - assert!(resp.txns[0] - .proof - .leaves() - .contains(&(notes[0].0.commitment()))); + // assert!(resp.txns[0] + // .proof + // .leaves() + // .contains(&(notes[0].0.commitment()))); // Previous page let resp = server @@ -793,10 +1246,10 @@ async fn query_transactions() { .await .unwrap(); assert_eq!(resp.txns.len(), 1); - assert!(resp.txns[0] - .proof - .leaves() - .contains(&(notes[1].0.commitment()))); + // assert!(resp.txns[0] + // .proof + // .leaves() + // .contains(&(notes[1].0.commitment()))); // Previous page again should return nothing let resp_with_nothing = server @@ -811,10 +1264,10 @@ async fn query_transactions() { // Start polling and mint a new note let local_set = tokio::task::LocalSet::new(); - let server = Arc::clone(&server); + let server = Rc::clone(&server); let resp = local_set.spawn_local({ - let server = Arc::clone(&server); + let server = Rc::clone(&server); async move { server @@ -834,36 +1287,37 @@ async fn query_transactions() { &server, alice_address, Element::from(150u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); let _tx = tx.await.unwrap(); new_note }); - let (resp, mint) = local_set + let (resp, _mint) = local_set .run_until(async { tokio::join!(resp, mint) }) .await; // We should get the new note in the resp let resp = resp.unwrap().unwrap(); - let mint = mint.unwrap(); assert_eq!(resp.txns.len(), 1); - assert_eq!( - resp.txns[0].proof.leaves(), - [ - Element::ZERO, - Element::ZERO, - mint.commitment(), - Element::ZERO - ] - ); + // assert_eq!( + // resp.txns[0].proof.leaves(), + // [ + // Element::ZERO, + // Element::ZERO, + // mint.commitment(), + // Element::ZERO + // ] + // ); } expect_root_hash!( server, expect_test::expect![[r#" - 0x2d52d37d95839a960b8fcc68cfb67d75853e14bc7980a1529e1fb1555818182c - "#]] + 0xdc8048c64aab47beea9e3d82c8f7ed835748fd9cd975252e6fae7a7a489fe3a + "#]] ); } @@ -879,23 +1333,30 @@ async fn query_blocks() { let alice_address = hash_merge([alice_pk, Element::ZERO]); let mut notes = vec![]; for value in [50u64, 100] { - let (alice_note, eth_tx, tx) = - mint(&rollup, &usdc, &server, alice_address, Element::from(value)); + let (alice_note, eth_tx, tx) = mint( + &rollup, + &usdc, + &server, + alice_address, + Element::from(value), + Element::from(value), + ) + .await; eth_tx.await.unwrap(); let tx = tx.await.unwrap(); notes.push((alice_note, tx)); } - for (note, txn_resp) in ¬es { + for (_note, txn_resp) in ¬es { let resp = server .get_block(&txn_resp.height.to_string()) .await .unwrap(); assert_eq!(resp.block.content.header.height, txn_resp.height); - assert!(resp.block.content.state.txns[0] - .proof - .leaves() - .contains(&(note.commitment()))); + // assert!(resp.block.content.state.txns[0] + // .proof + // .leaves() + // .contains(&(note.commitment()))); let resp_by_hash = server .get_block(&resp.hash.0.encode_hex::()) @@ -920,27 +1381,27 @@ async fn query_blocks() { .unwrap(); // Latest transaction should be first assert!(resp.blocks.len() >= notes.last().unwrap().1.height.0 as usize); - assert!(non_empty_blocks!(resp.blocks.iter()) - .next() - .unwrap() - .block - .content - .state - .txns[0] - .proof - .leaves() - .contains(¬es[1].0.commitment())); - assert!(non_empty_blocks!(resp.blocks.iter()) - .skip(1) - .next() - .unwrap() - .block - .content - .state - .txns[0] - .proof - .leaves() - .contains(¬es[0].0.commitment())); + // assert!(non_empty_blocks!(resp.blocks.iter()) + // .next() + // .unwrap() + // .block + // .content + // .state + // .txns[0] + // .proof + // .leaves() + // .contains(¬es[1].0.commitment())); + // assert!(non_empty_blocks!(resp.blocks.iter()) + // .skip(1) + // .next() + // .unwrap() + // .block + // .content + // .state + // .txns[0] + // .proof + // .leaves() + // .contains(¬es[0].0.commitment())); } { @@ -1045,13 +1506,15 @@ async fn query_blocks() { assert_eq!(resp_with_nothing.blocks.len(), 0); // If we add a transaction and try again, we should get the new transaction - let (new_note, eth_tx, tx) = mint( + let (_new_note, eth_tx, tx) = mint( &rollup, &usdc, &server, alice_address, Element::from(150u64), - ); + Element::ZERO, + ) + .await; eth_tx.await.unwrap(); let _tx = tx.await.unwrap(); @@ -1065,22 +1528,22 @@ async fn query_blocks() { .unwrap(); assert_eq!(non_empty_blocks!(resp.blocks.iter()).count(), 1); - assert!(non_empty_blocks!(resp.blocks.iter()) - .next() - .unwrap() - .block - .content - .state - .txns[0] - .proof - .leaves() - .contains(&new_note.commitment())); + // assert!(non_empty_blocks!(resp.blocks.iter()) + // .next() + // .unwrap() + // .block + // .content + // .state + // .txns[0] + // .proof + // .leaves() + // .contains(&new_note.commitment())); } expect_root_hash!( server, expect_test::expect![[r#" - 0x2d52d37d95839a960b8fcc68cfb67d75853e14bc7980a1529e1fb1555818182c - "#]] + 0xdc8048c64aab47beea9e3d82c8f7ed835748fd9cd975252e6fae7a7a489fe3a + "#]] ); } diff --git a/pkg/node/tests/rpc/types.rs b/pkg/node/tests/rpc/types.rs index 9cfc653..d88fb5f 100644 --- a/pkg/node/tests/rpc/types.rs +++ b/pkg/node/tests/rpc/types.rs @@ -1,4 +1,4 @@ -use node::UtxoProof; +use element::Element; use primitives::{ block_height::BlockHeight, hash::CryptoHash, @@ -6,7 +6,7 @@ use primitives::{ sig::Signature, }; use serde::{Deserialize, Serialize}; -use smirk::Element; +use zk_primitives::UtxoProof; #[derive(Debug, PartialEq, Deserialize)] pub struct Block { @@ -61,6 +61,17 @@ pub struct ElementResponse { pub txn_hash: CryptoHash, } +#[derive(Debug, Deserialize)] +pub struct ElementsListItem { + pub element: Element, + pub height: u64, + #[expect(dead_code)] + pub root_hash: Element, + #[expect(dead_code)] + pub txn_hash: CryptoHash, + pub spent: bool, +} + #[derive(Debug, Default, Serialize, Deserialize)] pub struct ListTxnsQuery { #[serde(skip_serializing_if = "Option::is_none")] @@ -135,3 +146,23 @@ pub struct ListBlocksResponse { pub blocks: Vec, pub cursor: OpaqueCursor, } + +#[derive(Debug, PartialEq, Deserialize)] +pub struct SmirkElementInfo { + pub element: Element, + pub inserted_at_height: u64, +} + +pub type GetAllSmirkElementsResponse = Vec; + +#[derive(Debug, Serialize, Deserialize)] +pub struct StatsResponse { + pub last_7_days_txns: Vec, + pub today_txns: u64, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct TxnDayStats { + pub date: chrono::NaiveDate, + pub count: u64, +} diff --git a/pkg/noir-abi-inputs-macro/Cargo.toml b/pkg/noir-abi-inputs-macro/Cargo.toml new file mode 100644 index 0000000..a8df1a1 --- /dev/null +++ b/pkg/noir-abi-inputs-macro/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "noir-abi-inputs-macro" +version = "0.1.0" +edition = "2024" + +[lib] +proc-macro = true + +[features] +default = [] +serde = [] + +[dependencies] +proc-macro2 = { workspace = true } +quote = { workspace = true } +syn = { workspace = true, features = ["full"] } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/noir-abi-inputs-macro/src/fixtures.rs b/pkg/noir-abi-inputs-macro/src/fixtures.rs new file mode 100644 index 0000000..784dfeb --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/fixtures.rs @@ -0,0 +1,81 @@ +use std::collections::BTreeMap; +use std::env; +use std::fs; +use std::path::{Path, PathBuf}; + +use proc_macro2::Span; +use syn::LitStr; + +use crate::{AbiField, AbiType, ProgramArtifact, StructPath}; + +pub(crate) struct FixturePaths { + pub(crate) program_path: PathBuf, + pub(crate) key_path: PathBuf, + pub(crate) key_fields_path: PathBuf, +} + +/// Resolve a path from a literal string, relative to CARGO_MANIFEST_DIR if not absolute. +pub(crate) fn resolve_path(path_literal: &LitStr) -> syn::Result { + let raw = path_literal.value(); + let path = Path::new(&raw); + if path.is_absolute() { + return Ok(path.to_path_buf()); + } + + let manifest_dir = env::var("CARGO_MANIFEST_DIR").map_err(|err| { + syn::Error::new( + path_literal.span(), + format!("CARGO_MANIFEST_DIR is not set: {}", err), + ) + })?; + + Ok(Path::new(&manifest_dir).join(path)) +} + +pub(crate) fn resolve_fixture_paths(path_literal: &LitStr) -> syn::Result { + let fixture_dir = resolve_path(path_literal)?; + + Ok(FixturePaths { + program_path: fixture_dir.join("program.json"), + key_path: fixture_dir.join("key"), + key_fields_path: fixture_dir.join("key_fields.json"), + }) +} + +pub(crate) fn parse_program(path: &Path) -> syn::Result { + let contents = fs::read_to_string(path).map_err(|err| { + syn::Error::new( + Span::call_site(), + format!("failed to read program json {}: {}", path.display(), err), + ) + })?; + serde_json::from_str(&contents).map_err(|err| { + syn::Error::new( + Span::call_site(), + format!("failed to parse program json {}: {}", path.display(), err), + ) + }) +} + +pub(crate) fn collect_structs(ty: &AbiType, out: &mut BTreeMap>) { + match ty { + AbiType::Struct { path, fields } => { + if !out.contains_key(path) { + out.insert(path.clone(), fields.clone()); + for field in fields { + collect_structs(&field.ty, out); + } + } + } + AbiType::Array { ty, .. } => collect_structs(ty, out), + AbiType::Tuple { fields } => { + for field in fields { + collect_structs(field, out); + } + } + AbiType::Field => {} + AbiType::Integer { .. } => {} + AbiType::Boolean => {} + AbiType::String { .. } => {} + } +} diff --git a/pkg/noir-abi-inputs-macro/src/input_expand.rs b/pkg/noir-abi-inputs-macro/src/input_expand.rs new file mode 100644 index 0000000..086d581 --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/input_expand.rs @@ -0,0 +1,136 @@ +use std::collections::BTreeMap; + +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use syn::{Ident, LitStr}; + +use crate::fixtures::{collect_structs, parse_program, resolve_fixture_paths}; +use crate::input_value::generate_struct_input_value_impl; +use crate::proof_inputs::{generate_proof_inputs_impl, generate_public_inputs_impl}; +use crate::structs::generate_struct_def; +use crate::to_pascal_case::to_pascal_case; +use crate::{AbiVisibility, MacroArgs}; + +pub(crate) fn expand_noir_abi_inputs(args: MacroArgs) -> syn::Result { + let module_ident = args.module; + let interface_module = &args.interface_module; + let path_literal = args.path; + let fixture_paths = resolve_fixture_paths(&path_literal)?; + let include_program_path = LitStr::new( + &fixture_paths.program_path.to_string_lossy(), + path_literal.span(), + ); + let include_key_path = LitStr::new( + &fixture_paths.key_path.to_string_lossy(), + path_literal.span(), + ); + let include_key_fields_path = LitStr::new( + &fixture_paths.key_fields_path.to_string_lossy(), + path_literal.span(), + ); + let program = parse_program(&fixture_paths.program_path)?; + + let mut structs = BTreeMap::new(); + for param in &program.abi.parameters { + collect_structs(¶m.field.ty, &mut structs); + } + + let mut struct_defs = Vec::new(); + let mut struct_impls = Vec::new(); + + for (path, fields) in &structs { + if path.is_qualified() { + continue; + } + let struct_ident = path.ident(); + struct_defs.push(generate_struct_def(&struct_ident, fields, interface_module)); + struct_impls.push(generate_struct_input_value_impl( + &struct_ident, + fields, + interface_module, + )); + } + + let input_ident = Ident::new( + &format!("{}Input", to_pascal_case(&module_ident.to_string())), + module_ident.span(), + ); + + let public_params: Vec<_> = program + .abi + .parameters + .iter() + .filter_map(|param| { + (param.visibility == AbiVisibility::Public).then_some(param.field.clone()) + }) + .collect(); + let public_inputs_ident = Ident::new( + &format!("{}PublicInputs", to_pascal_case(&module_ident.to_string())), + module_ident.span(), + ); + + let all_parameters = program + .abi + .parameters + .iter() + .map(|p| p.field.clone()) + .collect::>(); + let input_def = generate_struct_def(&input_ident, &all_parameters, interface_module); + let input_impl = generate_proof_inputs_impl( + &input_ident, + &public_inputs_ident, + &all_parameters, + interface_module, + ); + + let public_inputs_def = + generate_struct_def(&public_inputs_ident, &public_params, interface_module); + let public_inputs_impl = generate_public_inputs_impl( + &public_inputs_ident, + &public_params, + interface_module, + args.oracle_hash_keccak, + ); + + Ok(quote! { + pub mod #module_ident { + use acvm::AcirField; + use #interface_module::{Base, FromFields, ToFields}; + use lazy_static::lazy_static; + use noirc_abi::{InputMap, input_parser::InputValue}; + use std::collections::BTreeMap; + use super::submodules; + + pub const PROGRAM: &str = include_str!(#include_program_path); + pub const KEY: &[u8] = include_bytes!(#include_key_path); + pub const KEY_FIELDS: &[u8] = include_bytes!(#include_key_fields_path); + + lazy_static! { + pub static ref PROGRAM_ARTIFACT: noirc_artifacts::program::ProgramArtifact = + serde_json::from_str(PROGRAM).unwrap(); + pub static ref PROGRAM_COMPILED: noirc_driver::CompiledProgram = + noirc_driver::CompiledProgram::from(PROGRAM_ARTIFACT.clone()); + pub static ref BYTECODE: Vec = super::super::get_bytecode_from_program(PROGRAM); + pub static ref VERIFICATION_KEY: Vec = parse_key_fields(KEY_FIELDS); + pub static ref VERIFICATION_KEY_HASH: Base = + bn254_blackbox_solver::poseidon_hash(&VERIFICATION_KEY).unwrap(); + } + + fn parse_key_fields(key_fields_json: &[u8]) -> Vec { + let fields = serde_json::from_slice::>(key_fields_json).unwrap(); + + fields + .into_iter() + .map(|field| Base::from_hex(&field).unwrap()) + .collect() + } + + #(#struct_defs)* + #(#struct_impls)* + #input_def + #input_impl + #public_inputs_def + #public_inputs_impl + } + }) +} diff --git a/pkg/noir-abi-inputs-macro/src/input_value.rs b/pkg/noir-abi-inputs-macro/src/input_value.rs new file mode 100644 index 0000000..1f20b78 --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/input_value.rs @@ -0,0 +1,61 @@ +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use syn::{Ident, Type}; + +use crate::{AbiField, AbiType}; + +pub(crate) fn generate_struct_input_value_impl( + struct_ident: &Ident, + fields: &[AbiField], + interface_module: &Type, +) -> TokenStream2 { + let inserts = fields.iter().map(|field| { + let field_name = &field.name; + let ident = Ident::new(&field.name, Span::call_site()); + let expr = input_value_expr(quote!(value.#ident), &field.ty, interface_module); + quote! { + map.insert(#field_name.to_owned(), #expr); + } + }); + + quote! { + impl From<#struct_ident> for InputValue { + fn from(value: #struct_ident) -> Self { + let mut map = BTreeMap::new(); + #(#inserts)* + InputValue::Struct(map) + } + } + } +} + +pub(crate) fn input_value_expr( + expr: TokenStream2, + ty: &AbiType, + interface_module: &Type, +) -> TokenStream2 { + match ty { + AbiType::Field => { + quote! { InputValue::Field(#interface_module::Base::from(#expr)) } + } + AbiType::Integer { .. } => { + quote! { InputValue::Field(#interface_module::IntToBase::to_base(#expr)) } + } + AbiType::Boolean => { + quote! { InputValue::Field(#interface_module::Base::from(#expr as u128)) } + } + AbiType::String { .. } => quote! { InputValue::String(#expr) }, + AbiType::Array { ty, .. } => { + let inner = input_value_expr(quote!(value), ty, interface_module); + quote! { InputValue::Vec(#expr.map(|value| #inner).to_vec()) } + } + AbiType::Struct { .. } => quote! { InputValue::from(#expr) }, + AbiType::Tuple { fields } => { + let field_exprs = (0..) + .map(syn::Index::from) + .zip(fields) + .map(|(idx, ty)| input_value_expr(quote!(#expr.#idx), ty, interface_module)); + quote! { InputValue::Vec(vec![#(#field_exprs),*]) } + } + } +} diff --git a/pkg/noir-abi-inputs-macro/src/lib.rs b/pkg/noir-abi-inputs-macro/src/lib.rs new file mode 100644 index 0000000..65e03c1 --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/lib.rs @@ -0,0 +1,161 @@ +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +#[cfg(feature = "serde")] +use quote::quote; +use serde::Deserialize; +use syn::parse::{Parse, ParseStream}; +use syn::token::Comma; +use syn::{Ident, LitBool, LitStr, Result as SynResult, Type}; + +use input_expand::expand_noir_abi_inputs; +use qualified_core::expand_noir_abi_shared_structs; +use struct_path::StructPath; + +pub(crate) mod fixtures; +pub(crate) mod input_expand; +pub(crate) mod input_value; +pub(crate) mod proof_inputs; +pub(crate) mod qualified_core; +pub(crate) mod qualified_modules; +pub(crate) mod struct_path; +pub(crate) mod structs; +pub(crate) mod to_pascal_case; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "serde")] +fn serde_derives() -> TokenStream2 { + quote! { , ::serde::Serialize, ::serde::Deserialize } +} + +#[cfg(not(feature = "serde"))] +fn serde_derives() -> TokenStream2 { + TokenStream2::new() +} + +#[proc_macro] +pub fn noir_abi_inputs(input: TokenStream) -> TokenStream { + let args = syn::parse_macro_input!(input as MacroArgs); + match expand_noir_abi_inputs(args) { + Ok(tokens) => tokens.into(), + Err(err) => err.into_compile_error().into(), + } +} + +#[proc_macro] +pub fn noir_abi_shared_structs(input: TokenStream) -> TokenStream { + let args = syn::parse_macro_input!(input as SharedMacroArgs); + match expand_noir_abi_shared_structs(args) { + Ok(tokens) => tokens.into(), + Err(err) => err.into_compile_error().into(), + } +} + +struct MacroArgs { + path: LitStr, + module: Ident, + oracle_hash_keccak: LitBool, + interface_module: Type, +} + +impl Parse for MacroArgs { + fn parse(input: ParseStream) -> SynResult { + let path = input.parse()?; + let _: Comma = input.parse()?; + let module = input.parse()?; + let _: Comma = input.parse()?; + let oracle_hash_keccak = input.parse()?; + let _: Comma = input.parse()?; + let interface_module = input.parse()?; + + Ok(MacroArgs { + path, + module, + oracle_hash_keccak, + interface_module, + }) + } +} + +struct SharedMacroArgs { + path: LitStr, + interface_module: Type, +} + +impl Parse for SharedMacroArgs { + fn parse(input: ParseStream) -> SynResult { + let path = input.parse()?; + let _: Comma = input.parse()?; + let interface_module = input.parse()?; + + Ok(Self { + path, + interface_module, + }) + } +} + +#[derive(Debug, Deserialize)] +struct ProgramArtifact { + abi: Abi, +} + +#[derive(Debug, Deserialize)] +struct Abi { + parameters: Vec, +} + +#[derive(Debug, Deserialize)] +struct AbiParam { + #[serde(flatten)] + field: AbiField, + visibility: AbiVisibility, +} + +#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +enum AbiVisibility { + Public, + Private, +} + +#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] +#[serde(tag = "kind", rename_all = "lowercase")] +enum AbiType { + Field, + Array { + length: usize, + #[serde(rename = "type")] + ty: Box, + }, + Integer { + sign: Sign, + width: u32, + }, + Boolean, + Struct { + path: StructPath, + fields: Vec, + }, + Tuple { + fields: Vec, + }, + String { + length: u32, + }, +} + +#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +enum Sign { + Unsigned, + Signed, +} + +#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] +struct AbiField { + name: String, + #[serde(rename = "type")] + ty: AbiType, +} diff --git a/pkg/noir-abi-inputs-macro/src/proof_inputs.rs b/pkg/noir-abi-inputs-macro/src/proof_inputs.rs new file mode 100644 index 0000000..e00f4ff --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/proof_inputs.rs @@ -0,0 +1,58 @@ +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use syn::{Ident, LitBool, Type}; + +use crate::AbiField; +use crate::input_value::input_value_expr; +use crate::structs::generate_serialization_to_fields; + +pub(crate) fn generate_proof_inputs_impl( + input_ident: &Ident, + public_inputs_ident: &Ident, + params: &[AbiField], + interface_module: &Type, +) -> TokenStream2 { + let inserts = params.iter().map(|param| { + let field_name = ¶m.name; + let ident = Ident::new(¶m.name, Span::call_site()); + let expr = input_value_expr(quote!(me.#ident), ¶m.ty, interface_module); + quote! { + map.insert(#field_name.to_owned(), #expr); + } + }); + + quote! { + impl crate::circuits::ProofInputs for #input_ident { + const PROGRAM: &'static str = PROGRAM; + const KEY: &'static [u8] = KEY; + fn bytecode(&self) -> &[u8] { &*BYTECODE } + fn compiled_program(&self) -> &noirc_driver::CompiledProgram { &*PROGRAM_COMPILED } + type PublicInputs = #public_inputs_ident; + + fn input_map(&self) -> InputMap { + let me = self.clone(); + let mut map = InputMap::new(); + #(#inserts)* + map + } + } + } +} + +pub(crate) fn generate_public_inputs_impl( + public_ident: &Ident, + params: &[AbiField], + interface_module: &Type, + oracle_hash_keccak: LitBool, +) -> TokenStream2 { + let fields_impls = generate_serialization_to_fields(public_ident, params, interface_module); + + quote! { + #fields_impls + + impl #interface_module::PublicInputs for #public_ident { + const KEY: &'static [u8] = KEY; + const ORACLE_HASH_KECCAK: bool = #oracle_hash_keccak; + } + } +} diff --git a/pkg/noir-abi-inputs-macro/src/qualified_core.rs b/pkg/noir-abi-inputs-macro/src/qualified_core.rs new file mode 100644 index 0000000..9bc4b3e --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/qualified_core.rs @@ -0,0 +1,94 @@ +use std::collections::BTreeMap; +use std::fs; +use std::path::{Path, PathBuf}; + +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; + +use crate::fixtures::{collect_structs, parse_program, resolve_path}; +use crate::qualified_modules::generate_qualified_modules; +use crate::{AbiField, SharedMacroArgs, StructPath}; + +/// Organized qualified structs by module name. +/// Key: module name (e.g., "utxo" or "a_b" from "a::b::C") +/// Value: list of (struct name, fields) +pub(crate) type QualifiedModuleGroups = BTreeMap)>>; + +pub(crate) fn expand_noir_abi_shared_structs(args: SharedMacroArgs) -> syn::Result { + let interface_module = &args.interface_module; + let root_dir = resolve_path(&args.path)?; + let program_paths = list_program_json_paths(&root_dir)?; + + let mut qualified_structs = BTreeMap::>::new(); + for program_path in program_paths { + let program = parse_program(&program_path)?; + let mut structs = BTreeMap::new(); + for param in &program.abi.parameters { + collect_structs(¶m.field.ty, &mut structs); + } + + for (path, fields) in structs { + if !path.is_qualified() { + continue; + } + + match qualified_structs.get(&path) { + Some(existing_fields) if existing_fields != &fields => { + return Err(syn::Error::new( + Span::call_site(), + format!( + "qualified struct '{}::{}' has conflicting field definitions", + path.module, path.name + ), + )); + } + Some(_) => {} + None => { + qualified_structs.insert(path, fields); + } + } + } + } + + let mut module_groups = QualifiedModuleGroups::new(); + for (path, fields) in qualified_structs { + module_groups + .entry(path.module) + .or_default() + .push((path.name, fields)); + } + + let modules = generate_qualified_modules(&module_groups, interface_module); + Ok(quote! { + #modules + }) +} + +fn list_program_json_paths(root: &Path) -> syn::Result> { + let entries = fs::read_dir(root).map_err(|err| { + syn::Error::new( + Span::call_site(), + format!( + "failed to read fixtures directory {}: {}", + root.display(), + err + ), + ) + })?; + + let mut programs = Vec::new(); + for entry in entries.flatten() { + let path = entry.path(); + if !path.is_dir() { + continue; + } + + let program_json = path.join("program.json"); + if program_json.is_file() { + programs.push(program_json); + } + } + + programs.sort(); + Ok(programs) +} diff --git a/pkg/noir-abi-inputs-macro/src/qualified_modules.rs b/pkg/noir-abi-inputs-macro/src/qualified_modules.rs new file mode 100644 index 0000000..338b91f --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/qualified_modules.rs @@ -0,0 +1,63 @@ +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use syn::{Ident, Type}; + +use crate::AbiField; +use crate::input_value::generate_struct_input_value_impl; +use crate::qualified_core::QualifiedModuleGroups; +use crate::structs::{generate_serialization_to_fields, generate_struct_def}; +use crate::to_pascal_case::to_pascal_case; + +pub(crate) fn generate_qualified_modules( + module_groups: &QualifiedModuleGroups, + interface_module: &Type, +) -> TokenStream2 { + let module_defs = module_groups + .iter() + .map(|(module_name, structs)| { + let module_ident = Ident::new(module_name, Span::call_site()); + let struct_defs = structs + .iter() + .map(|(struct_name, fields)| { + generate_qualified_struct_def(struct_name, fields, interface_module) + }) + .collect::>(); + + quote! { + pub mod #module_ident { + use #interface_module::{Base, FromFields, ToFields}; + use noirc_abi::input_parser::InputValue; + use std::collections::BTreeMap; + use super::super::submodules; + + #(#struct_defs)* + } + } + }) + .collect::>(); + + quote! { + pub mod submodules { + #(#module_defs)* + } + } +} + +fn generate_qualified_struct_def( + struct_name: &str, + fields: &[AbiField], + interface_module: &Type, +) -> TokenStream2 { + let struct_ident = Ident::new(&to_pascal_case(struct_name), Span::call_site()); + + let definition = generate_struct_def(&struct_ident, fields, interface_module); + let input_value_impl = + generate_struct_input_value_impl(&struct_ident, fields, interface_module); + let fields_impls = generate_serialization_to_fields(&struct_ident, fields, interface_module); + + quote! { + #definition + #input_value_impl + #fields_impls + } +} diff --git a/pkg/noir-abi-inputs-macro/src/struct_path.rs b/pkg/noir-abi-inputs-macro/src/struct_path.rs new file mode 100644 index 0000000..17528b2 --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/struct_path.rs @@ -0,0 +1,60 @@ +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use serde::Deserialize; +use syn::Ident; + +use crate::to_pascal_case::to_pascal_case; + +/// Parsed struct path from Noir ABI. +/// Converts "a::b::C" to module="a_b", name="C" +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct StructPath { + /// Flattened module name (e.g., "a_b" from "a::b::C") + pub(crate) module: String, + /// Struct name (e.g., "C" from "a::b::C") + pub(crate) name: String, +} + +impl StructPath { + /// Parse a Noir path string like "a::b::C" into module and name components. + /// The module becomes a flattened identifier by joining non-last parts with "_". + pub(crate) fn from_noir_path(path: &str) -> Self { + let parts: Vec<&str> = path.split("::").collect(); + let name = parts.last().map(|s| s.to_string()).unwrap_or_default(); + let module = parts[..parts.len().saturating_sub(1)].join("_"); + Self { module, name } + } + + /// Returns true if this is a qualified struct (has a module prefix from Noir path). + pub(crate) fn is_qualified(&self) -> bool { + !self.module.is_empty() + } + + /// Generate an identifier for this struct (pascal-cased name). + pub(crate) fn ident(&self) -> Ident { + Ident::new(&to_pascal_case(&self.name), Span::call_site()) + } + + /// Generate a type path for referencing this struct. + /// Expects `submodules` to be in scope in the generated module. + pub(crate) fn type_path(&self) -> TokenStream2 { + let struct_ident = self.ident(); + + if self.module.is_empty() { + quote! { #struct_ident } + } else { + let module_ident = Ident::new(&self.module, Span::call_site()); + quote! { submodules::#module_ident::#struct_ident } + } + } +} + +impl<'de> Deserialize<'de> for StructPath { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Ok(StructPath::from_noir_path(&s)) + } +} diff --git a/pkg/noir-abi-inputs-macro/src/structs.rs b/pkg/noir-abi-inputs-macro/src/structs.rs new file mode 100644 index 0000000..b7007f1 --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/structs.rs @@ -0,0 +1,103 @@ +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use syn::{Ident, Type}; + +use crate::serde_derives; +use crate::{AbiField, AbiType, Sign}; + +pub(crate) fn generate_struct_def( + struct_ident: &Ident, + fields: &[AbiField], + interface_module: &Type, +) -> TokenStream2 { + let serde_derives = serde_derives(); + let field_defs = fields.iter().map(|field| { + let name = Ident::new(&field.name, Span::call_site()); + let ty = rust_type(&field.ty, interface_module); + quote! { pub #name: #ty, } + }); + + quote! { + #[derive(Debug, Clone #serde_derives)] + pub struct #struct_ident { + #(#field_defs)* + } + } +} + +/// Generates `FromFields` and `ToFields` trait implementations for a struct. +pub(crate) fn generate_serialization_to_fields( + struct_ident: &Ident, + fields: &[AbiField], + interface_module: &Type, +) -> TokenStream2 { + let field_count_exprs = fields.iter().map(|field| { + let ty = rust_type(&field.ty, interface_module); + quote! { <#ty as #interface_module::FromFields>::FIELD_COUNT } + }); + + let assignments = fields.iter().map(|field| { + let name = Ident::new(&field.name, Span::call_site()); + let ty = rust_type(&field.ty, interface_module); + quote! { #name: <#ty>::from_fields(iter) } + }); + + let field_serializations = fields.iter().map(|field| { + let name = Ident::new(&field.name, Span::call_site()); + quote! { self.#name.to_fields(out) } + }); + + quote! { + impl #interface_module::FromFields for #struct_ident { + const FIELD_COUNT: usize = #(#field_count_exprs)+*; + + fn from_fields(iter: &mut impl Iterator) -> Self { + Self { + #(#assignments),* + } + } + } + + impl #interface_module::ToFields for #struct_ident { + fn to_fields(&self, out: &mut Vec<#interface_module::Base>) { + #(#field_serializations);* + } + } + } +} + +pub(crate) fn rust_type(ty: &AbiType, interface_module: &Type) -> TokenStream2 { + match ty { + AbiType::Field => quote! { #interface_module::Element }, + AbiType::Integer { sign, width } => rust_type_for_integer(sign, *width), + AbiType::Boolean => quote! { bool }, + AbiType::String { .. } => quote! { String }, + + AbiType::Array { length, ty } => { + let inner = rust_type(ty, interface_module); + quote! { [#inner; #length] } + } + AbiType::Tuple { fields } => { + let types = fields.iter().map(|f| rust_type(f, interface_module)); + quote! { (#(#types),*) } + } + + AbiType::Struct { path, .. } => path.type_path(), + } +} + +fn rust_type_for_integer(sign: &Sign, width: u32) -> TokenStream2 { + match (sign, width) { + (Sign::Unsigned, 8) => quote! { u8 }, + (Sign::Signed, 8) => quote! { i8 }, + (Sign::Unsigned, 16) => quote! { u16 }, + (Sign::Signed, 16) => quote! { i16 }, + (Sign::Unsigned, 32) => quote! { u32 }, + (Sign::Signed, 32) => quote! { i32 }, + (Sign::Unsigned, 64) => quote! { u64 }, + (Sign::Signed, 64) => quote! { i64 }, + (Sign::Unsigned, 128) => quote! { u128 }, + (Sign::Signed, 128) => quote! { i128 }, + _ => panic!("Unsupported integer width {width}"), + } +} diff --git a/pkg/noir-abi-inputs-macro/src/tests.rs b/pkg/noir-abi-inputs-macro/src/tests.rs new file mode 100644 index 0000000..3485e2b --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/tests.rs @@ -0,0 +1,29 @@ +use syn::{Type, parse_quote}; + +use crate::AbiField; +use crate::qualified_core::QualifiedModuleGroups; +use crate::qualified_modules::generate_qualified_modules; +use crate::struct_path::StructPath; + +#[test] +fn qualified_type_path_for_circuit_modules_is_namespaced() { + let path = StructPath::from_noir_path("signature::Foo"); + let tokens = path.type_path(); + let normalized = tokens.to_string().replace(' ', ""); + assert_eq!(normalized, "submodules::signature::Foo"); +} + +#[test] +fn generate_qualified_modules_wraps_namespace() { + let interface_module: Type = parse_quote!(crate::circuits::proc_macro_interface); + let mut groups = QualifiedModuleGroups::new(); + groups.insert( + "signature".to_string(), + vec![("foo".to_string(), Vec::::new())], + ); + + let tokens = generate_qualified_modules(&groups, &interface_module); + let output = tokens.to_string(); + assert!(output.contains("pub mod submodules")); + assert!(output.contains("pub mod signature")); +} diff --git a/pkg/noir-abi-inputs-macro/src/to_pascal_case.rs b/pkg/noir-abi-inputs-macro/src/to_pascal_case.rs new file mode 100644 index 0000000..0e12754 --- /dev/null +++ b/pkg/noir-abi-inputs-macro/src/to_pascal_case.rs @@ -0,0 +1,39 @@ +pub(crate) fn to_pascal_case(input: &str) -> String { + let mut out = String::new(); + let mut capitalize = true; + for ch in input.chars() { + if ch == '_' || ch == '-' { + capitalize = true; + continue; + } + if capitalize { + out.push(ch.to_ascii_uppercase()); + capitalize = false; + } else { + out.push(ch.to_ascii_lowercase()); + } + } + out +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_to_pascal_case() { + assert_eq!(to_pascal_case("hello_world"), "HelloWorld"); + assert_eq!(to_pascal_case("foo-bar"), "FooBar"); + assert_eq!(to_pascal_case("simple"), "Simple"); + assert_eq!(to_pascal_case(""), ""); + assert_eq!(to_pascal_case("a_b_c"), "ABC"); + assert_eq!(to_pascal_case("snake_case_string"), "SnakeCaseString"); + assert_eq!(to_pascal_case("kebab-case-string"), "KebabCaseString"); + assert_eq!(to_pascal_case("mixed_case-string"), "MixedCaseString"); + assert_eq!(to_pascal_case("already_Pascal"), "AlreadyPascal"); + assert_eq!( + to_pascal_case("___multiple___underscores___"), + "MultipleUnderscores" + ); + } +} diff --git a/pkg/notes-interface/Cargo.toml b/pkg/notes-interface/Cargo.toml new file mode 100644 index 0000000..143f16a --- /dev/null +++ b/pkg/notes-interface/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "notes-interface" +version = "0.1.0" +edition = "2024" + +[features] +default = [] +diesel = [ + "dep:diesel", + "dep:database", + "database/diesel", + "element/diesel", +] + +[dependencies] +async-trait = { workspace = true } +chrono = { workspace = true } +contextful = { workspace = true } +database = { workspace = true, optional = true, default-features = false } +diesel = { workspace = true, optional = true, features = ["postgres"] } +element = { workspace = true } +hash = { workspace = true } +rand = { workspace = true } +rpc = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +strum = { workspace = true } +thiserror = { workspace = true } +unimock = { workspace = true } +uuid = { workspace = true } +zk-primitives = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +serde_json = { workspace = true } diff --git a/pkg/notes-interface/src/assign.rs b/pkg/notes-interface/src/assign.rs new file mode 100644 index 0000000..801aff0 --- /dev/null +++ b/pkg/notes-interface/src/assign.rs @@ -0,0 +1,85 @@ +use async_trait::async_trait; +use element::Element; +use unimock::unimock; +use uuid::Uuid; + +use crate::{Note, NoteWithPk, RefKind, Result}; + +/// Notes to be used for a transaction after assignment and database insertion. +#[derive(Debug, Clone)] +pub struct AssignedTxnNotes { + /// Primary input note, now marked as assigned in storage. + pub input_note_1: NoteWithPk, + /// Optional second input note when two notes are needed. + pub input_note_2: Option, + /// Primary output note created for the recipient. + pub output_note_1: NoteWithPk, + /// Optional change output note returned to the sender. + pub output_note_2: Option, +} + +/// Order preference for selecting notes by value. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum NoteSelectionOrder { + /// Select smallest value notes first (ascending order). + SmallestFirst, + /// Select largest value notes first (descending order). + LargestFirst, +} + +#[unimock(api = AssignInterfaceMock)] +#[async_trait] +/// Core assignment logic for selecting inputs and creating output notes for spending. +pub trait AssignInterface: Send + Sync { + #[allow(clippy::too_many_arguments)] + /// Find notes for the amount, assign inputs/outputs, and execute the transfer. + async fn assign_and_spend_note_with_amount( + &self, + from: Uuid, + to: Uuid, + amount: Element, + note_kind: Element, + ref_kind: RefKind, + ref_id: Option, + selection_order: NoteSelectionOrder, + ) -> Result; + + #[allow(clippy::too_many_arguments)] + /// Find a single note from `from` with value >= amount and assign outputs. + async fn assign_single_owner_note_with_amount( + &self, + from: Uuid, + to: Uuid, + amount: Element, + note_kind: Element, + ref_kind: RefKind, + ref_id: Option, + selection_order: NoteSelectionOrder, + ) -> Result; + + #[allow(clippy::too_many_arguments)] + /// Use up to two notes (largest first) to cover the amount, with optional strictness. + async fn assign_multi_owner_note_with_amount_value_desc( + &self, + from: Uuid, + to: Uuid, + amount: Element, + note_kind: Element, + ref_kind: RefKind, + ref_id: Option, + strict_amount: bool, + ) -> Result; + + #[allow(clippy::too_many_arguments)] + /// Assign the provided input notes and create corresponding output notes. + async fn assign_given_notes( + &self, + input_note_1: Note, + input_note_2: Option, + to: Uuid, + change_to: Uuid, + amount: Element, + ref_kind: RefKind, + ref_id: Option, + ) -> Result; +} diff --git a/pkg/notes-interface/src/clean_up.rs b/pkg/notes-interface/src/clean_up.rs new file mode 100644 index 0000000..3383535 --- /dev/null +++ b/pkg/notes-interface/src/clean_up.rs @@ -0,0 +1,76 @@ +use async_trait::async_trait; +use chrono::Duration; +use element::Element; +use unimock::unimock; + +use crate::{NoteStatus, NoteWithPk, Result}; + +#[unimock(api = CleanUpInterfaceMock)] +#[async_trait] +pub trait CleanUpInterface: Send + Sync { + /// Spawn background cleanup for timed-out notes using the default timeout. + fn spawn_clean_up_old_notes_after_timeout(&self); + + /// Spawn background cleanup for timed-out notes immediately. + fn spawn_clean_up_old_notes_now(&self); + + /// Spawn background cleanup for timed-out notes after a custom delay. + fn spawn_clean_up_old_notes_after(&self, delay: Duration); + + /// Clean up all timed-out notes (both input and output pending notes) + async fn clean_up_old_notes(&self) -> Result<()>; + + /// Clean up a note while validating it currently has one of the provided statuses. + async fn clean_up_note_with_existing_status( + &self, + commitment: Element, + existing_status: &[NoteStatus], + clear_spend_ref_claim: bool, + is_output_note: bool, + ) -> Result; + + /// Clean up a single input note, optionally clearing its spend ref claim + async fn clean_up_input_note( + &self, + commitment: Element, + clear_spend_ref_claim: bool, + ) -> Result; + + /// Clean up a single output note + async fn clean_up_output_note(&self, commitment: Element) -> Result; + + /// Clean up all notes involved in a transaction + async fn clean_up_transaction_notes( + &self, + input_note_1: &NoteWithPk, + input_note_2: Option<&NoteWithPk>, + output_note_1: &NoteWithPk, + output_note_2: Option<&NoteWithPk>, + ) -> Result<()>; + + /// Spawn cleanup for all transaction notes after the default timeout. + fn spawn_clean_up_transaction_notes_after_timeout( + &self, + input_note_1: &NoteWithPk, + input_note_2: Option<&NoteWithPk>, + output_note_1: &NoteWithPk, + output_note_2: Option<&NoteWithPk>, + ); + + /// Spawn cleanup for all transaction notes after a custom delay. + fn spawn_clean_up_transaction_notes_after( + &self, + input_note_1: &NoteWithPk, + input_note_2: Option<&NoteWithPk>, + output_note_1: &NoteWithPk, + output_note_2: Option<&NoteWithPk>, + delay: Duration, + ); + + /// Get the current status of a note by querying the node + async fn get_note_status( + &self, + commitment: Element, + is_output_note: bool, + ) -> Result; +} diff --git a/pkg/notes-interface/src/data.rs b/pkg/notes-interface/src/data.rs new file mode 100644 index 0000000..632a366 --- /dev/null +++ b/pkg/notes-interface/src/data.rs @@ -0,0 +1,269 @@ +// lint-long-file-override allow-max-lines=300 +#[cfg(feature = "diesel")] +use database::schema::notes; +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{FromSql, FromSqlRow}, + expression::AsExpression, + pg::Pg, + prelude::*, + serialize::{IsNull, ToSql}, + sql_types::Text, +}; +use element::Element; +use hash::hash_merge; +use rand::thread_rng; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "diesel")] +use std::io::Write; +use strum::{Display, EnumString}; +use uuid::Uuid; +/// Owner ID used for unassigned/orphan notes (e.g., ramp deposits before assignment). +pub const NULL_OWNER_ID: Uuid = Uuid::nil(); +/// System-owned notes pool for platform operations. +pub const PAYY_OWNER_ID: Uuid = Uuid::from_bytes([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]); +/// Migration-specific owner identifier for legacy note moves. +pub const PAYY_OWNER_MIGRATE_ID: Uuid = + Uuid::from_bytes([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]); +#[derive(Debug, Clone, Serialize, Deserialize)] +/// A note paired with its private key for signing/proving spend transactions. +pub struct NoteWithPk { + pub private_key: Element, + pub note: zk_primitives::Note, +} + +impl NoteWithPk { + #[must_use] + /// Create a note with a random private key and address derived from that key. + pub fn new_with_value(value: Element, note_kind: Element) -> Self { + let private_key = Element::secure_random(thread_rng()); + let address = hash_merge([private_key, Element::ZERO]); + let note = zk_primitives::Note::new(address, value, note_kind); + Self { private_key, note } + } + + #[must_use] + /// Create a note with a random ephemeral private key for output notes. + pub fn new_with_value_ephemeral_private_key(value: Element, note_kind: Element) -> Self { + let private_key = Element::secure_random(thread_rng()); + let note = + zk_primitives::Note::new_from_ephemeral_private_key(private_key, value, note_kind); + Self { private_key, note } + } +} +#[derive( + Debug, + Display, + Default, + Serialize, + Deserialize, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + EnumString, +)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +/// Lifecycle status for a note stored in the database. +pub enum NoteStatus { + #[default] + /// Ready for spending by the owner + Unspent, + /// Note has been allocated as an input note for a txn + TxnInputAssigned, + /// New possible note that will be the output of a txn + TxnOutputPending, + /// Note has been spent, and can no longer be used + Spent, + /// Note was the output of a txn, but the txn failed + Dropped, +} + +#[cfg(feature = "diesel")] +impl ToSql for NoteStatus { + fn to_sql(&self, out: &mut diesel::serialize::Output) -> diesel::serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for NoteStatus { + fn from_sql(bytes: diesel::pg::PgValue) -> diesel::deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized status".into()) + } +} + +#[derive( + Debug, + Display, + Serialize, + Deserialize, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + EnumString, +)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +/// Reason a note was created or spent, used to relate notes to external flows. +pub enum RefKind { + /// Notes associated with NFT-related flows. + Nft, + /// Notes created/spent as part of a ramp transaction. + RampTransaction, + /// Notes representing change output from a transaction. + TxnChange, + /// Notes created by direct user actions. + User, + /// Notes created during legacy migration flows. + MigrateV0, + /// Notes used to merge system-owned pools. + PayyOwnerMerge, + /// Notes created for deposit link flows. + DepositLink, + /// Notes created for withdraw link flows. + WithdrawLink, + /// Notes representing EVM burn operations. + BurnEvm, +} + +#[cfg(feature = "diesel")] +impl ToSql for RefKind { + fn to_sql(&self, out: &mut diesel::serialize::Output) -> diesel::serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for RefKind { + fn from_sql(bytes: diesel::pg::PgValue) -> diesel::deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized ref kind".into()) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "diesel", derive(Queryable, Selectable, Identifiable))] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = notes))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +/// Full database representation of a note and its metadata. +pub struct Note { + /// Primary identifier for the note row. + pub id: Uuid, + /// Note kind/contract identifier. + pub kind: Element, + /// Commitment hash for the note. + pub commitment: Element, + /// Address derived from the note's private key. + pub address: Element, + /// Private key stored for spend authorization. + pub private_key: Element, + /// Note randomness/secret. + pub psi: Element, + /// Note value. + pub value: Element, + /// Current lifecycle status. + pub status: NoteStatus, + /// First parent note (input) identifier when created via transfer. + pub parent_1_id: Option, + /// Optional second parent note identifier. + pub parent_2_id: Option, + /// Reference kind for the spending action. + pub spend_ref_kind: Option, + /// External reference ID for the spending action. + pub spend_ref_id: Option, + /// Reference kind for the receiving action. + pub received_ref_kind: Option, + /// External reference ID for the receiving action. + pub received_ref_id: Option, + /// Timestamp when the note was spent. + pub spent_at: Option, + /// Current owner wallet ID. + pub owner_id: Uuid, + /// Timestamp when the note was created. + pub added_at: chrono::NaiveDateTime, + /// Timestamp when the note was last updated. + pub updated_at: chrono::NaiveDateTime, + #[cfg_attr(feature = "diesel", diesel(deserialize_as = i16))] + /// Schema/version marker for rollup compatibility. + pub version: u16, +} + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "diesel", derive(Insertable))] +#[cfg_attr(feature = "diesel", diesel(table_name = notes))] +/// Insert struct for creating new note rows. +pub struct NewNote { + pub id: Option, + pub kind: Element, + pub commitment: Element, + pub address: Element, + pub private_key: Element, + pub psi: Element, + pub value: Element, + pub status: NoteStatus, + pub parent_1_id: Option, + pub parent_2_id: Option, + pub received_ref_kind: Option, + pub received_ref_id: Option, + pub owner_id: Uuid, + pub version: i16, +} + +impl NewNote { + #[must_use] + /// Build a pending output note from a `NoteWithPk` and parent metadata. + pub fn new_with_note( + note: &NoteWithPk, + parent_1_id: Uuid, + parent_2_id: Option, + owner_id: Uuid, + received_ref_kind: Option, + received_ref_id: Option, + ) -> Self { + Self { + id: Some(Uuid::new_v4()), + kind: note.note.contract, + commitment: note.note.commitment(), + address: note.note.address, + private_key: note.private_key, + psi: note.note.psi, + value: note.note.value, + status: NoteStatus::TxnOutputPending, + parent_1_id: Some(parent_1_id), + parent_2_id, + owner_id, + received_ref_kind, + received_ref_id, + // New rollup is 1 + version: 1, + } + } +} + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "diesel", derive(AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = notes))] +/// Changeset for updating note status and spend metadata. +pub struct UpdateNote { + pub status: NoteStatus, + pub spend_ref_kind: Option, + pub spend_ref_id: Option, + pub spent_at: Option, +} diff --git a/pkg/notes-interface/src/error.rs b/pkg/notes-interface/src/error.rs new file mode 100644 index 0000000..78959e3 --- /dev/null +++ b/pkg/notes-interface/src/error.rs @@ -0,0 +1,61 @@ +use contextful::{FromContextful, InternalError}; +use rpc::{ + HTTPErrorConversion, + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Debug, Error, HTTPErrorConversion, FromContextful)] +/// Errors returned by notes-interface operations, mapped to RPC-friendly codes. +pub enum Error { + #[error("[notes-interface] note was claimed by another transaction")] + #[aborted("note-was-claimed-by-another-transaction")] + NoteWasClaimedByAnotherTransaction, + + #[error("[notes-interface] no notes available to claim")] + #[failed_precondition("no-notes-available-to-claim")] + NoNotesAvailableToClaim, + + #[error("[notes-interface] note does not exist")] + #[failed_precondition("note-not-exist")] + NoteNotExist, + + #[error("[notes-interface] note is already spent")] + #[failed_precondition("note-already-spent")] + NoteAlreadySpent, + + #[error("[notes-interface] note already exists")] + #[already_exists("note-already-exists")] + NoteAlreadyExists, + + #[error("[notes-interface] input notes kind mismatch")] + #[failed_precondition("input-notes-kind-mismatch")] + InputNotesKindMismatch, + + #[error("[notes-interface] transaction exceeded deadline")] + #[internal("txn-exceeded-deadline")] + TxnExceededDeadline, + + #[error("[notes-interface] unable to generate utxo proof")] + #[internal("unable-to-generate-utxo-proof")] + UnableToGenerateUtxoProof, + + #[error("[notes-interface] note request transaction not found")] + #[not_found("note-request-transaction-not-found")] + NoteRequestTransactionNotFound, + + #[error("[notes-interface] invalid note request transaction")] + #[bad_request("note-request-invalid-transaction")] + InvalidNoteRequestTransaction, + + #[error("[notes-interface] invalid authentication")] + #[unauthenticated("invalid-auth")] + InvalidAuth, + + #[error("[notes-interface] internal error")] + #[internal("internal-error", data = "omit")] + Internal(#[from] InternalError), +} diff --git a/pkg/notes-interface/src/lib.rs b/pkg/notes-interface/src/lib.rs new file mode 100644 index 0000000..b12c11c --- /dev/null +++ b/pkg/notes-interface/src/lib.rs @@ -0,0 +1,44 @@ +#![warn(clippy::pedantic)] +#![allow(missing_docs)] +#![allow(clippy::ignored_unit_patterns)] + +pub mod assign; +pub mod clean_up; +pub mod data; +pub mod error; +mod note_conversion; +pub mod request; +pub mod transfer; +pub mod user; + +pub use assign::{AssignInterface, AssignedTxnNotes, NoteSelectionOrder}; +pub use clean_up::{CleanUpInterface, CleanUpInterfaceMock}; +pub use data::{ + NULL_OWNER_ID, NewNote, Note, NoteStatus, NoteWithPk, PAYY_OWNER_ID, PAYY_OWNER_MIGRATE_ID, + RefKind, UpdateNote, +}; +pub use error::{Error, Result}; +pub use request::{NoteRequestInput, NoteRequestKind, RequestInterface}; +pub use transfer::TransferInterface; +pub use user::{ListNotesQuery, UserNotesInterface}; + +use async_trait::async_trait; +use std::sync::Arc; +use unimock::unimock; + +#[unimock(api = NotesInterfaceMock)] +#[async_trait] +#[allow(clippy::ignored_unit_patterns)] +/// Main entry point for note operations, exposing sub-interfaces used by guild and notes services. +pub trait NotesInterface: Send + Sync { + /// User-facing note operations (create, list, and status checks). + fn user_notes(&self) -> Arc; + /// Assignment logic for selecting inputs and preparing outputs before spending. + fn assign(&self) -> Arc; + /// Transaction execution and proof submission for assigned notes. + fn transfer(&self) -> Arc; + /// Allocation of notes for external requests (e.g., ramp deposit payouts). + fn request(&self) -> Arc; + /// Cleanup routines for pending or failed note transactions. + fn clean_up(&self) -> Arc; +} diff --git a/pkg/notes-interface/src/note_conversion.rs b/pkg/notes-interface/src/note_conversion.rs new file mode 100644 index 0000000..542c688 --- /dev/null +++ b/pkg/notes-interface/src/note_conversion.rs @@ -0,0 +1,30 @@ +use element::Element; + +use crate::data::{Note, NoteWithPk}; + +impl<'a> From<&'a Note> for NoteWithPk { + fn from(note: &'a Note) -> Self { + Self { + private_key: note.private_key, + note: zk_primitives::Note { + kind: Element::new(2), + contract: note.kind, + address: note.address, + psi: note.psi, + value: note.value, + }, + } + } +} + +impl<'a> From<&'a Note> for zk_primitives::Note { + fn from(note: &'a Note) -> Self { + Self { + kind: Element::new(2), + contract: note.kind, + address: note.address, + psi: note.psi, + value: note.value, + } + } +} diff --git a/pkg/notes-interface/src/request.rs b/pkg/notes-interface/src/request.rs new file mode 100644 index 0000000..57bbabc --- /dev/null +++ b/pkg/notes-interface/src/request.rs @@ -0,0 +1,39 @@ +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +use unimock::unimock; +use uuid::Uuid; + +use crate::{Note, Result}; + +/// Kind of note request (reason for requesting a note) +#[derive(Debug, Deserialize, Serialize, Clone)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum NoteRequestKind { + /// Transaction to be paid out + RampDeposit, +} + +/// Kind of note request (reason for requesting a note) +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct NoteRequestInput { + /// ID of the note request kind + pub id: String, + /// Kind of note request + pub kind: NoteRequestKind, +} + +#[unimock(api = RequestInterfaceMock)] +#[async_trait] +/// Handles allocation of notes for external request flows (e.g., ramp deposits). +pub trait RequestInterface: Send + Sync { + /// Allocate or return an existing note for the requested purpose. + async fn request_note( + &self, + wallet_id: Uuid, + ref_id: String, + ref_kind: NoteRequestKind, + ) -> Result; +} + +#[cfg(test)] +mod tests; diff --git a/pkg/notes-interface/src/request/tests.rs b/pkg/notes-interface/src/request/tests.rs new file mode 100644 index 0000000..12fbe33 --- /dev/null +++ b/pkg/notes-interface/src/request/tests.rs @@ -0,0 +1,14 @@ +use super::{NoteRequestInput, NoteRequestKind}; + +#[test] +fn note_request_input_ignores_removed_note_kind_field() { + let input = serde_json::from_value::(serde_json::json!({ + "id": "ramp-id", + "kind": NoteRequestKind::RampDeposit, + "note_kind": element::Element::new(1), + })) + .unwrap(); + + assert_eq!(input.id, "ramp-id"); + assert!(matches!(input.kind, NoteRequestKind::RampDeposit)); +} diff --git a/pkg/notes-interface/src/transfer.rs b/pkg/notes-interface/src/transfer.rs new file mode 100644 index 0000000..75b4b6c --- /dev/null +++ b/pkg/notes-interface/src/transfer.rs @@ -0,0 +1,21 @@ +use async_trait::async_trait; +use unimock::unimock; + +use crate::{AssignedTxnNotes, NoteWithPk, Result}; + +#[unimock(api = TransferInterfaceMock)] +#[async_trait] +/// Executes ZK note transactions and submits them to the node. +pub trait TransferInterface: Send + Sync { + /// Generate a UTXO proof, submit the transaction, and clean up on failure. + async fn spend_assigned_note(&self, assigned_notes: AssignedTxnNotes) -> Result<()>; + + /// Low-level transaction submission without cleanup orchestration. + async fn transfer_notes_txn( + &self, + input_note_1: NoteWithPk, + input_note_2: Option, + output_note_1: NoteWithPk, + output_note_2: Option, + ) -> Result<()>; +} diff --git a/pkg/notes-interface/src/user.rs b/pkg/notes-interface/src/user.rs new file mode 100644 index 0000000..b92f334 --- /dev/null +++ b/pkg/notes-interface/src/user.rs @@ -0,0 +1,67 @@ +use async_trait::async_trait; +use element::Element; +use serde::{Deserialize, Serialize}; +use unimock::unimock; +use uuid::Uuid; + +use crate::{Note, NoteStatus, RefKind, Result}; + +/// Query parameters for list notes +#[derive(Debug, Default, Deserialize, Serialize, Clone)] +pub struct ListNotesQuery { + /// Long poll duration + pub wait: Option, + /// Get changes since unix timestamps (in microseconds) + pub after: Option, + /// Limit result count + pub limit: Option, + /// Filter for note status + pub status: Option, + /// Filter for note kind (token contract). + pub note_kind: Option, +} + +#[unimock(api = UserNotesInterfaceMock)] +#[async_trait] +/// User-facing note operations backed by storage and node queries. +pub trait UserNotesInterface: Send + Sync { + #[allow(clippy::too_many_arguments)] + /// Create a note for a wallet from external deposit data. + async fn create_user_notes( + &self, + wallet_id: Uuid, + private_key: Element, + psi: Element, + value: Element, + note_kind: Element, + ref_kind: RefKind, + ref_kind_id: Option, + ) -> Result; + + /// List notes owned by a wallet, filtered by query parameters. + async fn list_notes_by_wallet_id( + &self, + wallet_id: Uuid, + query: ListNotesQuery, + ) -> Result>; + + /// List notes owned by a wallet, filtered by `ref_id` (`spend_ref_id` OR `received_ref_id`). + async fn list_notes_by_wallet_id_and_ref_id( + &self, + wallet_id: Uuid, + ref_id: &str, + ) -> Result>; + + /// List notes owned by a wallet, filtered by multiple statuses. + async fn list_notes_by_wallet_id_and_status( + &self, + wallet_id: Uuid, + status: Vec, + ) -> Result>; + + /// Partition notes into (unspent, spent) by checking on-chain state. + async fn check_existing_notes_spent<'a>( + &self, + notes: Vec<&'a Note>, + ) -> Result<(Vec<&'a Note>, Vec<&'a Note>)>; +} diff --git a/pkg/p2p2/Cargo.toml b/pkg/p2p2/Cargo.toml index 18f02a3..00c2b34 100644 --- a/pkg/p2p2/Cargo.toml +++ b/pkg/p2p2/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "p2p2" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] + async-trait = { workspace = true } figment = { workspace = true } futures = { workspace = true } @@ -11,13 +12,12 @@ futures-util = { workspace = true } libp2p = { workspace = true } parking_lot = { workspace = true } serde = { workspace = true } -serde_json = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } toml = { workspace = true } tracing = { workspace = true } -tracing-subscriber = { workspace = true } borsh = { workspace = true } wire-message = { workspace = true } strum = { workspace = true } whitelist-ips = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/p2p2/README.md b/pkg/p2p2/README.md new file mode 100644 index 0000000..97ce9ea --- /dev/null +++ b/pkg/p2p2/README.md @@ -0,0 +1,16 @@ +# P2P2 + +Alternative P2P implementation with custom protocols. + +## Overview + +This package provides an alternative peer-to-peer networking implementation with custom protocols for the network. + +## Features + +- Custom P2P protocols +- Network behavior management +- Transport layer abstraction +- Command handling +- Error management + diff --git a/pkg/p2p2/src/behaviour.rs b/pkg/p2p2/src/behaviour.rs index 96e2a26..d95f2c8 100644 --- a/pkg/p2p2/src/behaviour.rs +++ b/pkg/p2p2/src/behaviour.rs @@ -2,7 +2,7 @@ use super::protocol::PolyProtocol; use borsh::{BorshDeserialize, BorshSerialize}; use libp2p::{ request_response, - swarm::{behaviour::toggle::Toggle, keep_alive, NetworkBehaviour}, + swarm::{NetworkBehaviour, behaviour::toggle::Toggle, keep_alive}, }; #[derive(NetworkBehaviour)] diff --git a/pkg/p2p2/src/config.rs b/pkg/p2p2/src/config.rs index 43b1af5..b0eb616 100644 --- a/pkg/p2p2/src/config.rs +++ b/pkg/p2p2/src/config.rs @@ -1,8 +1,8 @@ -use std::{path::Path, sync::OnceLock, collections::HashSet, net::IpAddr}; +use std::{collections::HashSet, net::IpAddr, path::Path, sync::OnceLock}; use figment::{ - providers::{Env, Format, Toml}, Figment, + providers::{Env, Format, Toml}, }; use libp2p::Multiaddr; use serde::{Deserialize, Deserializer}; @@ -52,12 +52,12 @@ impl Config { /// In particular, specific fields can be overridden by setting the `P2P_*` environment /// variable. For example: /// - to override `listen_on`, set `P2P_LISTEN-ON="..."` (notice the kebab case inside an - /// identifier) + /// identifier) /// - to override `foo.bar`, set `P2P_FOO_BAR="..."` /// /// Use underscores to separate identifiers, and hyphens to separate words within an /// identifier - pub fn from_env>(path: P) -> Result { + pub fn from_env>(path: P) -> Result> { tracing::info!("loading config from {}", path.as_ref().to_string_lossy()); Figment::new() @@ -65,6 +65,7 @@ impl Config { .merge(Env::prefixed("P2P_").split("_")) .join(Toml::string(Self::DEFAULT_STR)) .extract() + .map_err(Box::new) } } diff --git a/pkg/p2p2/src/lib.rs b/pkg/p2p2/src/lib.rs index 51fafb7..212f035 100644 --- a/pkg/p2p2/src/lib.rs +++ b/pkg/p2p2/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(once_cell)] +// #![feature(once_cell)] #![deny(clippy::disallowed_methods)] mod behaviour; diff --git a/pkg/p2p2/src/network.rs b/pkg/p2p2/src/network.rs index 53773d2..d50a8ba 100644 --- a/pkg/p2p2/src/network.rs +++ b/pkg/p2p2/src/network.rs @@ -1,18 +1,19 @@ +// lint-long-file-override allow-max-lines=300 use crate::{ + Error, behaviour::{Behaviour, BehaviourEvent}, command::Command, error::Result, protocol::{PolyProtocol, Request, Response}, transport::create_transport, - Error, }; use borsh::{BorshDeserialize, BorshSerialize}; use futures_util::StreamExt; use libp2p::{ + Multiaddr, PeerId, identity::Keypair, request_response, - swarm::{keep_alive, SwarmBuilder, SwarmEvent}, - Multiaddr, PeerId, + swarm::{SwarmBuilder, SwarmEvent, keep_alive}, }; use parking_lot::Mutex; use std::{ @@ -21,7 +22,7 @@ use std::{ marker::PhantomData, }; use std::{net::IpAddr, sync::Arc}; -use tokio::{select, sync::mpsc, sync::oneshot, sync::Mutex as AsyncMutex}; +use tokio::{select, sync::Mutex as AsyncMutex, sync::mpsc, sync::oneshot}; use tracing::{debug, error, info}; pub struct Network diff --git a/pkg/p2p2/src/protocol.rs b/pkg/p2p2/src/protocol.rs index 68b938b..174fba9 100644 --- a/pkg/p2p2/src/protocol.rs +++ b/pkg/p2p2/src/protocol.rs @@ -6,7 +6,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use futures::prelude::*; use libp2p::request_response; use tokio::io; -use wire_message::{wire_message, WireMessage}; +use wire_message::{WireMessage, wire_message}; #[derive(Clone)] pub struct PolyProtocol( diff --git a/pkg/p2p2/src/transport.rs b/pkg/p2p2/src/transport.rs index 1a28e83..5419df2 100644 --- a/pkg/p2p2/src/transport.rs +++ b/pkg/p2p2/src/transport.rs @@ -1,8 +1,9 @@ use libp2p::{ + PeerId, Transport, core::{muxing::StreamMuxerBox, transport::Boxed, upgrade}, dns::TokioDnsConfig, identity::Keypair, - noise, tcp, yamux, PeerId, Transport, + noise, tcp, yamux, }; /// Create the transports for the swarm, we use TCP/IP and quic. diff --git a/pkg/parse-link/Cargo.toml b/pkg/parse-link/Cargo.toml new file mode 100644 index 0000000..47e9834 --- /dev/null +++ b/pkg/parse-link/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "parse-link" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } +ethnum = { workspace = true } +sha3 = { workspace = true } +bs58 = { workspace = true } +hex = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +web3 = { workspace = true } +ts-rs = { workspace = true, optional = true } +hash = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +serde_json = { workspace = true } + +[features] +ts-rs = ["dep:ts-rs", "element/ts-rs"] diff --git a/pkg/parse-link/README.md b/pkg/parse-link/README.md new file mode 100644 index 0000000..e345a67 --- /dev/null +++ b/pkg/parse-link/README.md @@ -0,0 +1,30 @@ +# Parse Link + +Link parsing and validation utilities. + +## Overview + +This package provides utilities for parsing and validating various types of links used throughout the zk-rollup system. It now hosts the canonical implementations for: + +- Activity link payload encoding/decoding (moved from `zk-primitives`) +- Payment link parsing logic (migrated from the TypeScript `parseLink.ts` helper) + +## Features + +- Decode and encode `NoteURLPayload` structures used by `s#` links +- Default omitted note kinds to Polygon bridged USDC while preserving non-USDC kinds in v2 links +- Parse request, send, and invite URLs into strongly typed Rust structs +- Extract common metadata (invite codes, memos) from parsed links +- Shareable parsing API for the React Native bridge and backend services + +## Key APIs + +- `parse_link::parse_url(&str) -> Result` parses any supported Payy link with detailed errors. +- `parse_link::parse_send_url(&str) -> Option` focuses on send links. +- `parse_link::NoteURLPayload` exposes helpers to `encode_activity_url_payload`, `decode_activity_url_payload`, `address`, `psi`, and `commitment`. + +`NoteURLPayload` keeps version `2` for current send links. Old links continue to decode as Polygon +bridged USDC when `note_kind` is omitted. New non-USDC links append a note-kind trailer under the +same version, while new USDC links still encode in the legacy-compatible format. + +See `src/parse.rs` and `src/note_url.rs` for more details and unit tests covering the supported formats. diff --git a/pkg/parse-link/examples/parse_link_cli.rs b/pkg/parse-link/examples/parse_link_cli.rs new file mode 100644 index 0000000..a4f8716 --- /dev/null +++ b/pkg/parse-link/examples/parse_link_cli.rs @@ -0,0 +1,57 @@ +use parse_link::{ParseError, parse_url}; +use serde::Serialize; +use std::env; + +const INVALID_LINK_MESSAGE: &str = "Invalid Link"; + +#[derive(Serialize)] +struct Output { + link: Option, + error: Option, +} + +fn main() { + let args: Vec = env::args().collect(); + let url = args + .get(1) + .map_or(String::new(), |value| value.trim().to_owned()); + + if url.is_empty() { + emit(Output { + link: None, + error: Some(INVALID_LINK_MESSAGE.to_owned()), + }); + return; + } + + match parse_url(&url) { + Ok(link) => emit(Output { + link: Some(link), + error: None, + }), + Err(err) => emit(Output { + link: None, + error: Some(map_parse_error(&err).to_owned()), + }), + } +} + +fn emit(output: Output) { + println!( + "{}", + serde_json::to_string(&output).expect("failed to serialize parse_link_cli output") + ); +} + +fn map_parse_error(err: &ParseError) -> &'static str { + match err { + ParseError::EmptyInput + | ParseError::MissingPrefix + | ParseError::UnknownPrefix(_) + | ParseError::MissingSegment(_) + | ParseError::MissingHash(_) + | ParseError::InvalidElement { .. } + | ParseError::InvalidRequestFormat + | ParseError::InvalidSendFormat => INVALID_LINK_MESSAGE, + } +} diff --git a/pkg/parse-link/src/lib.rs b/pkg/parse-link/src/lib.rs new file mode 100644 index 0000000..d6f5206 --- /dev/null +++ b/pkg/parse-link/src/lib.rs @@ -0,0 +1,65 @@ +use element::Element; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +mod note_url; +mod parse; + +pub use note_url::{ + NoteURLPayload, NoteUrlDecodeError, NoteUrlDecodeResult, decode_activity_url_payload, + try_decode_activity_url_payload, +}; +pub use parse::{ParseError, extract_invite_code, extract_memo, parse_send_url, parse_url}; + +/// Represents any supported Payy link. +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +#[cfg_attr(feature = "ts-rs", ts(rename = "PaymentLink"))] +#[serde(tag = "kind", rename_all = "kebab-case")] +pub enum Link { + Request(RequestLink), + Send(SendLinkHash), + Invite(InviteLink), +} + +/// Convenience alias for callers expecting the previous `PaymentLink` terminology. +pub type PaymentLink = Link; + +/// Convenience enum for send-only link parsing operations. +#[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +#[serde(tag = "kind", rename_all = "kebab-case")] +pub enum SendLink { + Send(SendLinkHash), +} + +/// Request links generated by the v1 format `/r/1//#/`. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct RequestLink { + pub value: Element, + pub public_key: Element, + pub invite_code: Option, + pub memo: Option, +} + +/// `/s/#` links containing a base58-encoded payload. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct SendLinkHash { + pub secret_hash: String, + pub memo: Option, +} + +/// `/invite/` links for onboarding flows. +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct InviteLink { + pub code: String, +} diff --git a/pkg/parse-link/src/note_url.rs b/pkg/parse-link/src/note_url.rs new file mode 100644 index 0000000..8fa025f --- /dev/null +++ b/pkg/parse-link/src/note_url.rs @@ -0,0 +1,279 @@ +// lint-long-file-override allow-max-lines=400 +use element::Element; +use hash::hash_merge; +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Sha3_256}; +use std::str::FromStr; +use thiserror::Error; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use web3::{signing::keccak256, types::H160}; + +const NOTE_KIND_TRAILER_MARKER: u8 = 0xff; + +/// Errors returned when decoding activity URL payloads. +#[derive(Debug, Error, PartialEq, Eq)] +pub enum NoteUrlDecodeError { + /// The payload could not be decoded from base58. + #[error("[parse-link/note-url] failed to decode base58 payload: {0}")] + Base58(String), + /// The payload is too short to contain the required metadata. + #[error("[parse-link/note-url] payload too short")] + TooShort, + /// The note URL version embedded in the payload is not supported. + #[error("[parse-link/note-url] unsupported version {0}")] + UnsupportedVersion(u8), + /// The payload contains an invalid UTF-8 referral code. + #[error("[parse-link/note-url] invalid referral code encoding")] + InvalidReferralCode, +} + +/// Result alias for note URL decoding operations. +pub type NoteUrlDecodeResult = std::result::Result; + +/// NoteURLPayload is a struct that contains the data required to create a note URL. +/// +/// These are used to send payments to a user e.g. `https://payy.link/s#`. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +pub struct NoteURLPayload { + /// The version of the note URL payload. + /// 0 -> old rollup note + /// 1 -> old rollup note (derived psi) + /// 2 -> new rollup (derived psi) + pub version: u8, + /// The private key of the note + pub private_key: Element, + /// The psi of the note, this is only kept for older note urls + /// which included the psi + pub psi: Option, + /// The value of the note + pub value: Element, + /// The note kind of the note. + /// + /// When omitted the payload defaults to Polygon bridged USDC. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub note_kind: Option, + /// The referral code of the note + pub referral_code: String, +} + +impl NoteURLPayload { + /// Gets the explicit or derived psi for the note url. + #[must_use] + pub fn psi(&self) -> Element { + match self.version { + 0 => self + .psi + .expect("version 0 payloads must include explicit psi"), + 1 => { + let private_key_bytes = self.private_key.to_be_bytes(); + Element::from_str(&hex::encode(keccak256(&private_key_bytes))).unwrap() + } + 2 => hash_private_key_for_psi(self.private_key), + version => panic!("unsupported note url version {version}"), + } + } + + /// Get the explicit or default note kind for the payload. + #[must_use] + pub fn note_kind(&self) -> Element { + self.note_kind + .unwrap_or_else(bridged_polygon_usdc_note_kind) + } + + /// Derive the address for the payload's private key. + #[must_use] + pub fn address(&self) -> Element { + get_address_for_private_key(self.private_key) + } + + /// Compute the note commitment corresponding to this payload. + #[must_use] + pub fn commitment(&self) -> Element { + if self.value == Element::ZERO { + Element::ZERO + } else { + hash_merge([ + Element::new(2), + self.note_kind(), + self.value, + self.address(), + self.psi(), + Element::ZERO, + Element::ZERO, + ]) + } + } + + /// Encode a note URL payload to a base58-encoded string. + #[must_use] + pub fn encode_activity_url_payload(&self) -> String { + let mut bytes = Vec::new(); + + // Encode version + bytes.push(self.version); + + // Encode private_key + bytes.extend_from_slice(&self.private_key.to_be_bytes()); + + // Encode psi if version is 0 + if let (0, Some(psi)) = (self.version, &self.psi) { + bytes.extend_from_slice(&psi.to_be_bytes()); + } + + // Encode value with leading zeros + let value_bytes = self.value.to_be_bytes(); + let leading_zeros = value_bytes.iter().take_while(|&&b| b == 0).count(); + #[allow(clippy::cast_possible_truncation)] + bytes.push(leading_zeros as u8); + bytes.extend_from_slice(&value_bytes[leading_zeros..]); + + // Encode referral_code as UTF-8 + bytes.extend_from_slice(self.referral_code.as_bytes()); + + if let Some(note_kind) = self.encoded_note_kind() { + bytes.push(NOTE_KIND_TRAILER_MARKER); + bytes.extend_from_slice(¬e_kind.to_be_bytes()); + } + + bs58::encode(bytes).into_string() + } + + fn encoded_note_kind(&self) -> Option { + let note_kind = self.note_kind(); + + (note_kind != bridged_polygon_usdc_note_kind()).then_some(note_kind) + } +} + +/// Decode a note URL payload from a base58-encoded string. +#[must_use] +pub fn decode_activity_url_payload(payload: &str) -> NoteURLPayload { + try_decode_activity_url_payload(payload) + .unwrap_or_else(|err| panic!("failed to decode note url payload: {err}")) +} + +/// Attempt to decode a note URL payload from a base58-encoded string returning an error on failure. +pub fn try_decode_activity_url_payload(payload: &str) -> NoteUrlDecodeResult { + let payload_bytes = bs58::decode(payload) + .into_vec() + .map_err(|err| NoteUrlDecodeError::Base58(err.to_string()))?; + + if payload_bytes.len() < 33 { + return Err(NoteUrlDecodeError::TooShort); + } + + let mut rest = &payload_bytes[..]; + + let version = rest[0]; + rest = &rest[1..]; + + if rest.len() < 32 { + return Err(NoteUrlDecodeError::TooShort); + } + + let private_key_bytes: [u8; 32] = rest[..32] + .try_into() + .expect("length already validated above"); + let private_key = Element::from_be_bytes(private_key_bytes); + rest = &rest[32..]; + + let psi = match version { + 0 => { + if rest.len() < 32 { + return Err(NoteUrlDecodeError::TooShort); + } + let psi_bytes: [u8; 32] = rest[..32] + .try_into() + .expect("length already validated above"); + rest = &rest[32..]; + Some(Element::from_be_bytes(psi_bytes)) + } + 1 => Some(Element::from_str(&hex::encode(keccak256(&private_key_bytes))).unwrap()), + 2 => Some(hash_private_key_for_psi(private_key)), + unsupported => return Err(NoteUrlDecodeError::UnsupportedVersion(unsupported)), + }; + + if rest.is_empty() { + return Err(NoteUrlDecodeError::TooShort); + } + + let leading_zeros = rest[0] as usize; + rest = &rest[1..]; + + if leading_zeros > 32 || rest.len() < (32 - leading_zeros) { + return Err(NoteUrlDecodeError::TooShort); + } + + let value_len = 32 - leading_zeros; + let value_without_leading_zeros = &rest[..value_len]; + rest = &rest[value_len..]; + + let mut value_bytes = [0u8; 32]; + value_bytes[leading_zeros..].copy_from_slice(value_without_leading_zeros); + let value = Element::from_be_bytes(value_bytes); + + let (referral_code_bytes, note_kind) = split_note_kind_trailer(rest); + let referral_code = String::from_utf8(referral_code_bytes.to_vec()) + .map_err(|_| NoteUrlDecodeError::InvalidReferralCode)?; + + Ok(NoteURLPayload { + version, + private_key, + psi, + value, + note_kind, + referral_code, + }) +} + +fn split_note_kind_trailer(rest: &[u8]) -> (&[u8], Option) { + if rest.len() < 33 || rest[rest.len() - 33] != NOTE_KIND_TRAILER_MARKER { + return (rest, None); + } + + let note_kind = Element::from_be_bytes( + rest[rest.len() - 32..] + .try_into() + .expect("note kind trailer length already validated"), + ); + + (&rest[..rest.len() - 33], normalize_note_kind(note_kind)) +} + +fn normalize_note_kind(note_kind: Element) -> Option { + (note_kind != bridged_polygon_usdc_note_kind()).then_some(note_kind) +} + +fn hash_private_key_for_psi(private_key: Element) -> Element { + let mut hasher = Sha3_256::new(); + hasher.update(private_key.to_be_bytes()); + let result = hasher.finalize(); + + Element::from_be_bytes(result.into()) +} + +fn get_address_for_private_key(private_key: Element) -> Element { + hash_merge([private_key, Element::ZERO]) +} + +fn bridged_polygon_usdc_note_kind() -> Element { + let chain = 137u64; + let address = + H160::from_slice(&hex::decode("3c499c542cef5e3811e1192ce70d8cc03d5c3359").unwrap()); + generate_note_kind_bridge_evm(chain, address) +} + +fn generate_note_kind_bridge_evm(chain: u64, address: H160) -> Element { + let mut bytes = [0u8; 32]; + + bytes[0..2].copy_from_slice(&(2u16).to_be_bytes()); + bytes[2..10].copy_from_slice(&chain.to_be_bytes()); + bytes[10..30].copy_from_slice(address.as_bytes()); + + Element::from_be_bytes(bytes) +} + +#[cfg(test)] +mod tests; diff --git a/pkg/parse-link/src/note_url/tests.rs b/pkg/parse-link/src/note_url/tests.rs new file mode 100644 index 0000000..f27e83b --- /dev/null +++ b/pkg/parse-link/src/note_url/tests.rs @@ -0,0 +1,137 @@ +use super::*; + +const LEGACY_V2_USDC_PAYLOAD: &str = "9YcSG3egf5iEsLFFWTzHBhavV2WBka2HPYR5sx5giwYTTs8tJbDX6HwA4r"; +const NON_USDC_V2_PAYLOAD: &str = "aMf8si8A6coYZqmSTSkp7mNdGVeAWgvZic1SgEdgUkUTbZigL3sVJPwbgXUdJstTVrwVRuskgUTDRgwHZDg1AbYUoGkxR9AJmAt2"; + +#[test] +fn encode_decode_roundtrip_version_2() { + let payload = NoteURLPayload { + version: 2, + private_key: Element::new(101), + psi: None, + value: Element::new(1_000_000), + note_kind: None, + referral_code: "REF123".to_owned(), + }; + + let encoded = payload.encode_activity_url_payload(); + let decoded = decode_activity_url_payload(&encoded); + + assert_eq!(encoded, LEGACY_V2_USDC_PAYLOAD); + assert_eq!(decoded.version, payload.version); + assert_eq!(decoded.private_key, payload.private_key); + assert_eq!(decoded.value, payload.value); + assert_eq!(decoded.note_kind(), bridged_polygon_usdc_note_kind()); + assert_eq!(decoded.referral_code, payload.referral_code); + assert_eq!(decoded.psi(), payload.psi()); +} + +#[test] +fn decode_old_links_defaults_to_usdc_note_kind() { + let decoded = decode_activity_url_payload(LEGACY_V2_USDC_PAYLOAD); + + assert_eq!(decoded.note_kind, None); + assert_eq!(decoded.note_kind(), bridged_polygon_usdc_note_kind()); +} + +#[test] +fn encode_decode_roundtrip_preserves_non_usdc_note_kind() { + let note_kind = Element::new(99); + let payload = NoteURLPayload { + version: 2, + private_key: Element::new(33), + psi: None, + value: Element::new(44), + note_kind: Some(note_kind), + referral_code: "REF123".to_owned(), + }; + + let encoded = payload.encode_activity_url_payload(); + let decoded = decode_activity_url_payload(&encoded); + + assert_eq!(encoded, NON_USDC_V2_PAYLOAD); + assert_eq!(decoded.version, payload.version); + assert_eq!(decoded.note_kind, Some(note_kind)); + assert_eq!(decoded.note_kind(), note_kind); + assert_eq!(decoded.referral_code, payload.referral_code); +} + +#[test] +fn encode_with_explicit_usdc_note_kind_matches_legacy_format() { + let legacy_payload = NoteURLPayload { + version: 2, + private_key: Element::new(33), + psi: None, + value: Element::new(44), + note_kind: None, + referral_code: "REF123".to_owned(), + }; + let explicit_usdc_payload = NoteURLPayload { + note_kind: Some(bridged_polygon_usdc_note_kind()), + ..legacy_payload.clone() + }; + + assert_eq!( + explicit_usdc_payload.encode_activity_url_payload(), + legacy_payload.encode_activity_url_payload() + ); +} + +#[test] +fn try_decode_detects_invalid_payload() { + let err = try_decode_activity_url_payload("invalid").unwrap_err(); + assert!(matches!(err, NoteUrlDecodeError::Base58(_))); +} + +#[test] +fn psi_derivation_matches_versions() { + let explicit_psi = Element::new(42); + let payload_v0 = NoteURLPayload { + version: 0, + private_key: Element::new(7), + psi: Some(explicit_psi), + value: Element::new(10), + note_kind: None, + referral_code: String::new(), + }; + assert_eq!(payload_v0.psi(), explicit_psi); + + let payload_v2 = NoteURLPayload { + version: 2, + private_key: Element::new(99), + psi: None, + value: Element::new(10), + note_kind: None, + referral_code: String::new(), + }; + + let derived = hash_private_key_for_psi(payload_v2.private_key); + assert_eq!(payload_v2.psi(), derived); +} + +#[test] +fn address_and_commitment_helpers_work() { + let payload = NoteURLPayload { + version: 2, + private_key: Element::new(11), + psi: None, + value: Element::new(5), + note_kind: Some(Element::new(99)), + referral_code: String::new(), + }; + + let address = payload.address(); + assert_eq!(address, get_address_for_private_key(payload.private_key)); + + let commitment = payload.commitment(); + let expected = hash_merge([ + Element::new(2), + payload.note_kind(), + payload.value, + address, + payload.psi(), + Element::ZERO, + Element::ZERO, + ]); + assert_eq!(commitment, expected); +} diff --git a/pkg/parse-link/src/parse.rs b/pkg/parse-link/src/parse.rs new file mode 100644 index 0000000..345cd40 --- /dev/null +++ b/pkg/parse-link/src/parse.rs @@ -0,0 +1,355 @@ +// lint-long-file-override allow-max-lines=500 +use crate::{InviteLink, Link, RequestLink, SendLink, SendLinkHash}; +use element::Element; +use ethnum::U256; +use std::borrow::Cow; +use std::str::FromStr; +use thiserror::Error; + +/// Errors that can occur when parsing Payy links. +#[derive(Debug, Error, PartialEq, Eq)] +pub enum ParseError { + /// The input URL was empty or only contained whitespace. + #[error("[parse-link/parse] empty url input")] + EmptyInput, + /// The URL path did not include a leading segment (e.g. `/s`). + #[error("[parse-link/parse] missing url prefix segment")] + MissingPrefix, + /// The URL prefix is not recognised. + #[error("[parse-link/parse] unsupported prefix '{0}'")] + UnknownPrefix(String), + /// A required segment was absent for the provided prefix. + #[error("[parse-link/parse] missing required segment for '{0}' link")] + MissingSegment(String), + /// A required hash fragment was absent. + #[error("[parse-link/parse] missing hash fragment for '{0}' link")] + MissingHash(String), + /// A segment failed to parse into an `Element`. + #[error("[parse-link/parse] invalid element in segment '{segment}': {value}")] + InvalidElement { + /// The segment name being parsed. + segment: &'static str, + /// The raw value that failed to parse. + value: String, + }, + /// The link did not match any known request formats. + #[error("[parse-link/parse] invalid request link format")] + InvalidRequestFormat, + /// The link did not match any known send formats. + #[error("[parse-link/parse] invalid send link format")] + InvalidSendFormat, +} + +/// Parse a URL into a [`Link`] returning detailed errors on failure. +pub fn parse_url(url: &str) -> Result { + let components = parse_components(url)?; + + match components.prefix { + "r" => parse_request(&components.segments, components.hash), + prefix if prefix.starts_with('s') => parse_send(&components.segments, components.hash), + "invite" => parse_invite(&components.segments), + prefix => Err(ParseError::UnknownPrefix(prefix.to_owned())), + } +} + +/// Parse only send links, returning `None` when the input is not a send link. +#[must_use] +pub fn parse_send_url(url: &str) -> Option { + parse_url(url).ok().and_then(|link| match link { + Link::Send(send) => Some(SendLink::Send(send)), + _ => None, + }) +} + +/// Extract an invite code (if available) from a parsed link. +#[must_use] +pub fn extract_invite_code(link: &Link) -> Option<&str> { + match link { + Link::Request(request) => request.invite_code.as_deref(), + Link::Send(_) => None, + Link::Invite(invite) => Some(invite.code.as_str()), + } +} + +/// Extract the memo text for a parsed link (empty string when absent). +#[must_use] +pub fn extract_memo(link: &Link) -> Cow<'_, str> { + match link { + Link::Request(request) => request + .memo + .as_deref() + .map_or(Cow::Borrowed(""), Cow::Borrowed), + Link::Send(send) => send + .memo + .as_deref() + .map_or(Cow::Borrowed(""), Cow::Borrowed), + Link::Invite(_) => Cow::Borrowed(""), + } +} + +struct UrlComponents<'a> { + prefix: &'a str, + segments: Vec<&'a str>, + hash: Option<&'a str>, +} + +fn parse_components(url: &str) -> Result, ParseError> { + let mut path = url.trim(); + if path.is_empty() { + return Err(ParseError::EmptyInput); + } + + for prefix in [ + "https://payy.link/", + "http://payy.link/", + "payy.link/", + "https://www.payy.link/", + "http://www.payy.link/", + "www.payy.link/", + ] { + if let Some(stripped) = path.strip_prefix(prefix) { + path = stripped; + break; + } + } + + while path.starts_with('/') { + path = &path[1..]; + } + + let (path_no_query, hash_query) = path.split_once('?').unwrap_or((path, "")); + let (path_no_hash, hash_part) = + path_no_query + .split_once('#') + .map_or((path_no_query, None), |(p, h)| { + let (hash_without_query, _) = h.split_once('?').unwrap_or((h, "")); + (p, Some(hash_without_query)) + }); + + let mut iter = path_no_hash.split('/'); + let prefix = iter.next().unwrap_or(""); + if prefix.is_empty() { + return Err(ParseError::MissingPrefix); + } + + let mut segments: Vec<&str> = iter.collect(); + + // Preserve trailing empty segment when the path ends with `/` by inspecting the + // original hash-less path string. + if path_no_hash.ends_with('/') { + segments.push(""); + } + + Ok(UrlComponents { + prefix, + segments, + hash: hash_part.or_else(|| hash_query.split_once('#').map(|(_, h)| h)), + }) +} + +fn parse_request(segments: &[&str], hash: Option<&str>) -> Result { + let a = segments.first().copied().unwrap_or(""); + let b = segments.get(1).copied().unwrap_or(""); + + if a == "1" && !b.is_empty() { + let hash = hash.ok_or_else(|| ParseError::MissingHash("r".to_owned()))?; + if hash.is_empty() { + return Err(ParseError::MissingHash("r".to_owned())); + } + + let mut hash_parts = hash.split('/'); + let public_key_str = hash_parts + .next() + .filter(|segment| !segment.is_empty()) + .ok_or(ParseError::InvalidRequestFormat)?; + let public_key = parse_element("public_key", public_key_str)?; + + let invite_code = hash_parts + .next() + .filter(|segment| !segment.is_empty()) + .map(std::string::ToString::to_string); + + let value = parse_element("value", b)?; + let memo = segments.get(2).map(|memo| (*memo).to_owned()); + + return Ok(Link::Request(RequestLink { + value, + public_key, + invite_code, + memo, + })); + } + + Err(ParseError::InvalidRequestFormat) +} + +fn parse_send(segments: &[&str], hash: Option<&str>) -> Result { + if let Some(secret_hash) = hash { + if secret_hash.is_empty() { + return Err(ParseError::InvalidSendFormat); + } + + let memo = segments + .first() + .map(|segment| (*segment).to_owned()) + .filter(|memo| !memo.is_empty()); + + return Ok(Link::Send(SendLinkHash { + secret_hash: secret_hash.to_owned(), + memo, + })); + } + + Err(ParseError::InvalidSendFormat) +} + +fn parse_invite(segments: &[&str]) -> Result { + let code = segments + .first() + .filter(|segment| !segment.is_empty()) + .ok_or_else(|| ParseError::MissingSegment("invite".to_owned()))?; + + Ok(Link::Invite(InviteLink { + code: (*code).to_owned(), + })) +} + +fn parse_element(segment: &'static str, value: &str) -> Result { + try_parse_element(value).ok_or_else(|| ParseError::InvalidElement { + segment, + value: value.to_owned(), + }) +} + +fn try_parse_element(value: &str) -> Option { + if value.is_empty() { + return None; + } + + if value.chars().all(|c| c.is_ascii_digit()) + && let Ok(decimal) = U256::from_str_radix(value, 10) + { + return Some(Element::from(decimal)); + } + + Element::from_str(value).ok() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_invite_link() { + let link = parse_url("https://payy.link/invite/9KJLMZ").unwrap(); + match link { + Link::Invite(invite) => assert_eq!(invite.code, "9KJLMZ"), + other => panic!("unexpected link parsed: {other:?}"), + } + + let link = parse_url("https://payy.link/invite/9KJLMZ?posthog_id=abc").unwrap(); + match link { + Link::Invite(invite) => assert_eq!(invite.code, "9KJLMZ"), + other => panic!("unexpected link parsed: {other:?}"), + } + } + + #[test] + fn parse_send_link_with_memo() { + let link = parse_url("https://payy.link/s/howdy#").unwrap_err(); + assert_eq!(link, ParseError::InvalidSendFormat); + + let link = parse_url( + "https://payy.link/s/howdy#52wMdUKJXCEc7Bp4VeAf55QF9g7rC4Usez6p3RhK5a25xgEQqD", + ) + .unwrap(); + match link { + Link::Send(send) => { + assert_eq!( + send.secret_hash, + "52wMdUKJXCEc7Bp4VeAf55QF9g7rC4Usez6p3RhK5a25xgEQqD" + ); + assert_eq!(send.memo, Some("howdy".to_owned())); + } + other => panic!("unexpected link parsed: {other:?}"), + } + + let link = parse_url( + "https://payy.link/s/howdy#52wMdUKJXCEc7Bp4VeAf55QF9g7rC4Usez6p3RhK5a25xgEQqD?posthog=1", + ) + .unwrap(); + assert!(matches!(link, Link::Send(_))); + } + + #[test] + fn parse_request_links() { + let modern = parse_url("https://payy.link/r/1/1000000/send_money#0x00c6/8D9GEF").unwrap(); + match modern { + Link::Request(request) => { + assert_eq!( + request.value, + Element::from(U256::from_str_radix("1000000", 10).unwrap()) + ); + assert_eq!(request.public_key, Element::from_str("0x00c6").unwrap()); + assert_eq!(request.invite_code.as_deref(), Some("8D9GEF")); + assert_eq!(request.memo.as_deref(), Some("send_money")); + } + other => panic!("unexpected link parsed: {other:?}"), + } + } + + #[test] + fn parse_request_v1_without_memo_has_empty_string() { + let link = parse_url("https://payy.link/r/1/1000000/#0x00c6/8D9GEF").unwrap(); + + match link { + Link::Request(request) => { + assert_eq!(request.memo.as_deref(), Some("")); + assert_eq!( + extract_invite_code(&Link::Request(request.clone())), + Some("8D9GEF") + ); + } + other => panic!("unexpected link parsed: {other:?}"), + } + } + + #[test] + fn extract_memo_defaults_to_empty_string() { + let link = parse_url("https://payy.link/invite/9KJLMZ").unwrap(); + assert_eq!(extract_memo(&link), Cow::Borrowed("")); + } + + #[test] + fn extract_invite_code_variants() { + let invite = parse_url("https://payy.link/invite/9KJLMZ").unwrap(); + assert_eq!(extract_invite_code(&invite), Some("9KJLMZ")); + + let send = parse_url( + "https://payy.link/s/howdy#52wMdUKJXCEc7Bp4VeAf55QF9g7rC4Usez6p3RhK5a25xgEQqD", + ) + .unwrap(); + assert_eq!(extract_invite_code(&send), None); + } + + #[test] + fn parse_send_url_helper_matches_kinds() { + let send = parse_send_url( + "https://payy.link/s/howdy#52wMdUKJXCEc7Bp4VeAf55QF9g7rC4Usez6p3RhK5a25xgEQqD", + ) + .unwrap(); + let SendLink::Send(send) = send; + assert_eq!(send.memo.as_deref(), Some("howdy")); + } + + #[test] + fn parse_url_returns_error_for_unknown() { + assert!(parse_url("https://payy.link/unknown/abc123").is_err()); + } + + #[test] + fn parse_unknown_prefix_fails() { + let err = parse_url("https://payy.link/unknown/abc123").unwrap_err(); + assert!(matches!(err, ParseError::UnknownPrefix(prefix) if prefix == "unknown")); + } +} diff --git a/pkg/payy-note/Cargo.toml b/pkg/payy-note/Cargo.toml new file mode 100644 index 0000000..9f187e6 --- /dev/null +++ b/pkg/payy-note/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "payy-note" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } +serde = { workspace = true } +unimock = { workspace = true } +zk-primitives = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +serde_json = { workspace = true } diff --git a/pkg/payy-note/src/lib.rs b/pkg/payy-note/src/lib.rs new file mode 100644 index 0000000..a22f448 --- /dev/null +++ b/pkg/payy-note/src/lib.rs @@ -0,0 +1,132 @@ +#![warn(clippy::pedantic)] +#![allow(clippy::module_name_repetitions)] +#![deny(missing_docs)] + +//! Selector-guarded note access. + +#[cfg(test)] +mod tests; + +use element::Element; +use serde::{Deserialize, Serialize}; +use zk_primitives::Note; + +/// Runtime selector for obtaining notes. +/// +/// This currently scopes note retrieval by note kind. +/// +/// # Contract +/// The serialized shape is an object so this type can evolve with additional +/// selector fields in the future. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub struct NoteSelector { + note_kind: Element, +} + +/// A value scoped to a specific note kind. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub struct NoteValue { + /// Note kind for this value. + pub note_kind: Element, + /// Value scoped to this note kind. + pub value: Element, +} + +impl NoteSelector { + /// Creates a note selector for the provided note kind. + #[must_use] + pub fn new(note_kind: Element) -> Self { + Self { note_kind } + } + + /// Returns the note kind for this selector. + #[must_use] + pub fn note_kind(self) -> Element { + self.note_kind + } +} + +/// A note that has not yet been scoped to a specific selector. +/// +/// # Contract +/// - `NoteGuard` intentionally exposes no direct note accessors. +/// - Callers may obtain a `SelectedNote` only through `select`. +/// - `select` enforces selector matching. +/// - Matching is currently defined as `note.note_kind() == selector.note_kind()`. +#[repr(transparent)] +pub struct NoteGuard { + note: N, +} + +/// A note that has already been validated against a selector. +/// +/// # Contract +/// `SelectedNote` can only be constructed via `NoteGuard::select`. +#[repr(transparent)] +pub struct SelectedNote { + note: N, +} + +/// Abstraction for types that can expose a note kind discriminator. +pub trait HasNoteKind: std::fmt::Debug { + /// Returns the note kind discriminator. + /// + /// # Contract + /// Must return the discriminator used by selector matching. + fn note_kind(&self) -> Element; +} + +impl HasNoteKind for Note { + fn note_kind(&self) -> Element { + self.contract + } +} + +impl NoteGuard { + /// Creates a note guard wrapper. + #[must_use] + pub fn new(note: N) -> Self { + Self { note } + } +} + +impl NoteGuard +where + N: HasNoteKind, +{ + /// Returns `true` when this note satisfies the provided selector. + /// + /// # Contract + /// This is the canonical predicate used by both `get_ref` and `get`. + #[must_use] + pub fn matches(&self, selector: NoteSelector) -> bool { + self.note.note_kind() == selector.note_kind() + } + + /// Attempts to scope this note for the provided selector. + /// + /// # Errors + /// + /// Returns `Err(self)` when `matches(selector)` is `false`. + pub fn select(self, selector: NoteSelector) -> std::result::Result, Self> { + if self.matches(selector) { + return Ok(SelectedNote { note: self.note }); + } + + Err(self) + } +} + +impl SelectedNote { + /// Returns a reference to the validated note. + #[must_use] + pub fn as_note(&self) -> &N { + &self.note + } + + /// Returns the validated note. + #[must_use] + pub fn into_note(self) -> N { + self.note + } +} diff --git a/pkg/payy-note/src/tests.rs b/pkg/payy-note/src/tests.rs new file mode 100644 index 0000000..a0bc648 --- /dev/null +++ b/pkg/payy-note/src/tests.rs @@ -0,0 +1,91 @@ +use crate::{NoteGuard, NoteSelector, NoteValue}; +use element::Element; +use zk_primitives::Note; + +fn note_with_kind(kind: Element) -> Note { + Note { + kind: Element::new(2), + contract: kind, + address: Element::from(11u64), + psi: Element::from(22u64), + value: Element::from(33u64), + } +} + +#[test] +fn select_accepts_matching_kind() { + let note_kind = Element::from(777u64); + let note = note_with_kind(note_kind); + + let selected_note = NoteGuard::new(note.clone()).select(NoteSelector::new(note_kind)); + + let Ok(selected_note) = selected_note else { + panic!("expected note to match selector"); + }; + assert_eq!(selected_note.as_note(), ¬e); +} + +#[test] +fn select_rejects_mismatched_kind() { + let note_kind = Element::from(777u64); + let other_kind = Element::from(888u64); + let note = note_with_kind(note_kind); + + let selected_note = NoteGuard::new(note).select(NoteSelector::new(other_kind)); + + let Err(note_guard) = selected_note else { + panic!("expected note mismatch"); + }; + let selected_note = note_guard.select(NoteSelector::new(note_kind)); + let Ok(selected_note) = selected_note else { + panic!("expected note to remain available for matching selector"); + }; + assert_eq!(selected_note.as_note().contract, note_kind); +} + +#[test] +fn selected_note_into_note_returns_note() { + let note_kind = Element::from(777u64); + let note = note_with_kind(note_kind); + let selected_note = NoteGuard::new(note.clone()).select(NoteSelector::new(note_kind)); + let Ok(selected_note) = selected_note else { + panic!("note should match selector"); + }; + + assert_eq!(selected_note.into_note(), note); +} + +#[test] +fn matches_respects_selector_note_kind() { + let note_kind = Element::from(777u64); + let other_kind = Element::from(888u64); + let note_guard = NoteGuard::new(note_with_kind(note_kind)); + + assert!(note_guard.matches(NoteSelector::new(note_kind))); + assert!(!note_guard.matches(NoteSelector::new(other_kind))); +} + +#[test] +fn note_selector_roundtrip_preserves_kind() { + let selector = NoteSelector::new(Element::from(555u64)); + + let value = serde_json::to_value(selector).expect("serialize selector"); + let parsed: NoteSelector = serde_json::from_value(value).expect("deserialize selector"); + + assert_eq!(parsed, selector); +} + +#[test] +fn note_value_roundtrip_preserves_fields() { + let note_value = NoteValue { + value: Element::from(12u64), + note_kind: Element::from(34u64), + }; + + let value = serde_json::to_value(note_value).expect("serialize note value"); + let parsed: NoteValue = serde_json::from_value(value).expect("deserialize note value"); + + assert_eq!(parsed, note_value); + assert_eq!(parsed.value, Element::from(12u64)); + assert_eq!(parsed.note_kind, Element::from(34u64)); +} diff --git a/pkg/primitives/Cargo.toml b/pkg/primitives/Cargo.toml index 74fb33f..b2c5e31 100644 --- a/pkg/primitives/Cargo.toml +++ b/pkg/primitives/Cargo.toml @@ -1,27 +1,36 @@ [package] name = "primitives" version = "1.3.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] async-trait = { workspace = true } -chrono = { workspace = true } base64 = { workspace = true } borsh = { workspace = true } secp256k1 = { workspace = true } serde = { workspace = true } -serde_bytes = { workspace = true } serde_json = { workspace = true } rand = { workspace = true } hex = { workspace = true } sha2 = { workspace = true } sha3 = { workspace = true } tokio = { workspace = true } -tracing = { workspace = true } uint = { workspace = true } parking_lot = { workspace = true } microtype = { workspace = true } rand_derive2 = { workspace = true } web3 = { workspace = true } +futures = { workspace = true } +thiserror = { workspace = true } +diesel = { workspace = true, optional = true } +workspace-hack.workspace = true + +[dependencies.ts-rs] +workspace = true +optional = true + +[features] +ts-rs = ["dep:ts-rs"] +diesel = ["dep:diesel"] diff --git a/pkg/primitives/README.md b/pkg/primitives/README.md new file mode 100644 index 0000000..a6f16bc --- /dev/null +++ b/pkg/primitives/README.md @@ -0,0 +1,17 @@ +# Primitives + +Shared blockchain primitives including block heights, hashes, and utilities. + +## Overview + +This package provides fundamental data types and utilities. + +## Features + +- Block height management +- Hash types and operations +- Pagination utilities +- Retry mechanisms +- Serialization support +- U256 operations + diff --git a/pkg/primitives/src/batch.rs b/pkg/primitives/src/batch.rs new file mode 100644 index 0000000..82198db --- /dev/null +++ b/pkg/primitives/src/batch.rs @@ -0,0 +1,800 @@ +// lint-long-file-override allow-max-lines=800 +use async_trait::async_trait; +use futures::future::BoxFuture; +use parking_lot::Mutex; +use std::collections::VecDeque; +use std::sync::Arc; +use std::time::{Duration, Instant}; +use tokio::sync::oneshot; +use tokio::time::sleep; + +/// Errors that can occur within the batch processing system +#[derive(Debug, Clone, thiserror::Error)] +pub enum BatchError { + /// The task processing the batch was dropped + #[error("task has been dropped")] + TaskDropped, + /// Processor error + #[error("processor error: {0}")] + ProcessorError(#[from] T), +} + +/// A trait for processing batches of items asynchronously. +/// +/// The `BatchProcessor` trait defines an interface for types that can process +/// multiple items in a single batch operation. This is useful for optimizing +/// operations that are more efficient when performed in bulk, such as: +/// +/// - Database operations (bulk inserts, updates) +/// - Network requests (reducing connection overhead) +/// - API calls with rate limits (maximizing throughput) +/// - Resource-intensive computations (amortizing setup costs) +/// +/// # Type Parameters +/// +/// - `Item`: The type of individual items to be processed. Must be clonable and +/// safe to send across thread boundaries. +/// - `Result`: The type of result produced for each processed item. +/// - `Error`: The error type that can occur during batch processing. Must implement +/// the standard error trait and be clonable. +/// +/// # Implementation Requirements +/// +/// Implementors must ensure: +/// +/// 1. The number of results matches the number of input items +/// 2. Results maintain the same order as the input items +/// 3. If an error occurs, the entire batch fails (no partial processing) +/// +/// # Examples +/// +/// ## Basic numeric processor +/// +/// ```rust +/// use async_trait::async_trait; +/// use primitives::batch::BatchProcessor; +/// +/// struct NumberMultiplier { +/// factor: u32, +/// } +/// +/// // Define a proper error type +/// #[derive(Debug, Clone)] +/// struct MyError(String); +/// +/// impl std::fmt::Display for MyError { +/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +/// write!(f, "{}", self.0) +/// } +/// } +/// +/// impl std::error::Error for MyError {} +/// +/// #[async_trait] +/// impl BatchProcessor for NumberMultiplier { +/// type Item = u32; +/// type Result = u32; +/// type Error = MyError; +/// +/// async fn process_batch(&self, items: Vec) -> Result, Self::Error> { +/// // Multiply each number by the factor +/// Ok(items.into_iter().map(|item| item * self.factor).collect()) +/// } +/// } +/// +/// // Usage +/// async fn example() -> Result<(), MyError> { +/// let processor = NumberMultiplier { factor: 10 }; +/// let batch = vec![1, 2, 3, 4, 5]; +/// +/// let results = processor.process_batch(batch).await?; +/// // results will be [10, 20, 30, 40, 50] +/// +/// Ok(()) +/// } +/// ``` +#[async_trait] +pub trait BatchProcessor { + /// The type of item being batched. + /// + /// This represents individual items that will be collected into batches for processing. + /// These are the input parameters. + type Item: Clone + Send + 'static; + + /// The result type returned for each item. + /// + /// Each input item will correspond to exactly one result item in the output vector, + /// maintaining the same order as the input. + type Result: Send + 'static; + + /// The error type that can occur during processing. + /// + /// If batch processing fails, this error will be returned. The error must be clonable + /// to support error propagation across async boundaries and must implement the standard + /// error trait for compatibility with error handling libraries. + type Error: Clone + Send + Sync + std::error::Error + 'static; + + /// Process a batch of items. + /// + /// This method takes a vector of items and processes them as a batch, returning + /// a vector of results in the same order as the input items. If processing fails, + /// an error is returned and no results are produced. + /// + /// # Parameters + /// + /// * `items` - A vector of items to process in a batch + /// + /// # Returns + /// + /// * `Ok(Vec)` - A vector of results, one for each input item in the same order + /// * `Err(Self::Error)` - An error if batch processing failed + /// + /// # Implementation Notes + /// + /// Implementations should ensure: + /// - The output vector contains exactly the same number of elements as the input vector + /// - Results are in the same order as the corresponding inputs + /// - If partial processing is possible, consider whether to return partial results or an error + async fn process_batch(&self, items: Vec) + -> Result, Self::Error>; +} + +/// Configuration for the batch processor +pub struct BatchConfig { + /// Minimum time to wait before processing a batch after receiving the first item + pub batch_delay_ms: u64, + /// Minimum time between batch executions (throttling) + pub min_interval_ms: u64, +} + +impl Default for BatchConfig { + fn default() -> Self { + Self { + batch_delay_ms: 10, + min_interval_ms: 100, + } + } +} + +/// The result for a single processed item +type ProcessResult

= + Result<

::Result, BatchError<

::Error>>; + +/// A struct that batches items to be processed by a BatchProcessor +pub struct Batch { + processor: Arc

, + config: BatchConfig, + queue: Arc>>>, +} + +struct BatchQueue { + items: VecDeque<(Item, oneshot::Sender)>, + next_execution: Option, + last_execution: Option, + processing: bool, +} + +impl Batch

{ + /// Creates a new batch with the given processor and configuration + pub fn new(processor: P, config: BatchConfig) -> Self { + Self { + processor: Arc::new(processor), + config, + queue: Arc::new(Mutex::new(BatchQueue { + items: VecDeque::new(), + next_execution: None, + last_execution: None, + processing: false, + })), + } + } + + /// Creates a new batch with default configuration + pub fn with_defaults(processor: P) -> Self { + Self::new(processor, BatchConfig::default()) + } + + /// Creates a new batch with specified delay and interval + pub fn with_timing(processor: P, batch_delay_ms: u64, min_interval_ms: u64) -> Self { + Self::new( + processor, + BatchConfig { + batch_delay_ms, + min_interval_ms, + }, + ) + } + + /// Schedules an item to be processed and returns the result + pub async fn call(&self, item: P::Item) -> ProcessResult

{ + let (tx, rx) = oneshot::channel(); + let should_schedule = { + let mut queue = self.queue.lock(); + queue.items.push_back((item, tx)); + + // If no execution is scheduled and not currently processing, schedule one + if queue.next_execution.is_none() && !queue.processing { + let now = Instant::now(); + + // Calculate when the next execution should happen, respecting the throttle + let next_time = if let Some(last_exec) = queue.last_execution { + let min_next = last_exec + Duration::from_millis(self.config.min_interval_ms); + let batch_next = now + Duration::from_millis(self.config.batch_delay_ms); + std::cmp::max(min_next, batch_next) + } else { + now + Duration::from_millis(self.config.batch_delay_ms) + }; + + queue.next_execution = Some(next_time); + true + } else { + false + } + }; + + if should_schedule { + // Clone what we need for the processor + let queue_clone = Arc::clone(&self.queue); + let processor_clone = Arc::clone(&self.processor); + + // Spawn a task to manage the batch processing + tokio::spawn(async move { + Self::schedule_next_batch(queue_clone, processor_clone).await; + }); + } + + // Wait for the result + rx.await.map_err(|_| BatchError::TaskDropped)? + } + + /// Schedules and processes the next batch, respecting throttling + fn schedule_next_batch( + queue: Arc>>>, + processor: Arc

, + ) -> BoxFuture<'static, ()> { + Box::pin(async move { + let wait_duration = { + let queue_guard = queue.lock(); + if let Some(next_time) = queue_guard.next_execution { + let now = Instant::now(); + if next_time > now { + next_time - now + } else { + Duration::from_millis(0) + } + } else { + return; // No scheduled execution + } + }; + + // Wait until it's time to process the batch + sleep(wait_duration).await; + + // Mark as processing and get items + let items = { + let mut queue_guard = queue.lock(); + queue_guard.next_execution = None; + queue_guard.processing = true; + std::mem::take(&mut queue_guard.items) + }; + + if !items.is_empty() { + // Split into arguments and senders + let (args, senders): (Vec<_>, Vec<_>) = items.into_iter().unzip(); + + // Call the processor with all arguments + match processor.process_batch(args).await { + Ok(results) => { + // Send results back to callers + for (sender, result) in senders.into_iter().zip(results.into_iter()) { + let _ = sender.send(Ok(result)); // Ignore if receiver dropped + } + } + Err(err) => { + // If processing failed, notify all callers of the error + let batch_error = BatchError::ProcessorError(err); + for sender in senders { + let _ = sender.send(Err(batch_error.clone())); + } + } + } + } + + // Update state and check if we need to schedule another batch + let should_schedule = { + let mut queue_guard = queue.lock(); + queue_guard.last_execution = Some(Instant::now()); + queue_guard.processing = false; + + if !queue_guard.items.is_empty() && queue_guard.next_execution.is_none() { + // Calculate next execution time based on throttle + let now = Instant::now(); + let next_time = if let Some(last_exec) = queue_guard.last_execution { + let min_next = last_exec + + Duration::from_millis( + queue_guard + .last_execution + .map(|_| { + std::cmp::max( + 0, + queue_guard + .last_execution + .unwrap() + .elapsed() + .as_millis() + as u64, + ) + }) + .unwrap_or(0), + ); + std::cmp::max(min_next, now) + } else { + now + }; + + queue_guard.next_execution = Some(next_time); + true + } else { + false + } + }; + + // If there are more items, schedule another batch + if should_schedule { + Self::schedule_next_batch(queue, processor).await; + } + }) + } + + /// Updates the batch configuration + pub fn update_config(&mut self, config: BatchConfig) { + self.config = config; + } + + /// Updates just the batch delay + pub fn set_batch_delay(&mut self, batch_delay_ms: u64) { + self.config.batch_delay_ms = batch_delay_ms; + } + + /// Updates just the minimum interval (throttle) + pub fn set_min_interval(&mut self, min_interval_ms: u64) { + self.config.min_interval_ms = min_interval_ms; + } +} +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Arc; + use std::sync::atomic::{AtomicUsize, Ordering}; + use tokio::time::sleep; + + // Custom error type for the test processor + #[derive(Debug, Clone, thiserror::Error)] + #[error("{0}")] + struct TestError(String); + + // A simple test processor that multiplies numbers + struct TestProcessor { + process_count: Arc, + delay_ms: u64, + should_fail: bool, + } + + #[async_trait] + impl BatchProcessor for TestProcessor { + type Item = u32; + type Result = u32; + type Error = TestError; + + async fn process_batch( + &self, + items: Vec, + ) -> Result, Self::Error> { + // Increment the process count + self.process_count.fetch_add(1, Ordering::SeqCst); + + // Simulate processing delay + if self.delay_ms > 0 { + sleep(Duration::from_millis(self.delay_ms)).await; + } + + // Optionally fail the processing + if self.should_fail { + return Err(TestError("Simulated processor error".to_string())); + } + + // Process items (multiply by 2) + Ok(items.into_iter().map(|x| x * 2).collect()) + } + } + + impl TestProcessor { + fn new() -> Self { + Self { + process_count: Arc::new(AtomicUsize::new(0)), + delay_ms: 0, + should_fail: false, + } + } + + fn with_delay(delay_ms: u64) -> Self { + Self { + process_count: Arc::new(AtomicUsize::new(0)), + delay_ms, + should_fail: false, + } + } + + fn with_failure() -> Self { + Self { + process_count: Arc::new(AtomicUsize::new(0)), + delay_ms: 0, + should_fail: true, + } + } + + fn process_count(&self) -> usize { + self.process_count.load(Ordering::SeqCst) + } + } + + #[tokio::test] + async fn test_single_item_processing() { + let processor = TestProcessor::new(); + let batch = Batch::with_defaults(processor); + + let result = batch.call(5).await.unwrap(); + assert_eq!(result, 10); + } + + #[tokio::test] + async fn test_multiple_items_batched() { + let processor = TestProcessor::new(); + let batch = Arc::new(Batch::with_timing(processor, 0, 0)); + + // Submit multiple items that should be batched together + let batch_clone1 = Arc::clone(&batch); + let handle1 = tokio::spawn(async move { batch_clone1.call(1).await }); + + let batch_clone2 = Arc::clone(&batch); + let handle2 = tokio::spawn(async move { batch_clone2.call(2).await }); + + let batch_clone3 = Arc::clone(&batch); + let handle3 = tokio::spawn(async move { batch_clone3.call(3).await }); + + let result1 = handle1.await.unwrap().unwrap(); + let result2 = handle2.await.unwrap().unwrap(); + let result3 = handle3.await.unwrap().unwrap(); + + assert_eq!(result1, 2); + assert_eq!(result2, 4); + assert_eq!(result3, 6); + + // Should have been processed in a single batch + assert_eq!(batch.processor.process_count(), 1); + } + + #[tokio::test] + async fn test_batching_with_delay() { + let processor = TestProcessor::new(); + let batch_delay = 100; + let batch = Batch::with_timing(processor, batch_delay, 0); + + let start = Instant::now(); + let result = batch.call(5).await.unwrap(); + let elapsed = start.elapsed(); + + assert_eq!(result, 10); + // Should have waited at least the batch delay + assert!(elapsed.as_millis() >= batch_delay as u128); + } + + #[tokio::test] + async fn test_throttling() { + let processor = TestProcessor::new(); + let min_interval = 200; + let batch = Batch::with_timing(processor, 0, min_interval); + + // First batch should process immediately + let result1 = batch.call(1).await.unwrap(); + assert_eq!(result1, 2); + + // Second call should be throttled + let start = Instant::now(); + let result2 = batch.call(2).await.unwrap(); + let elapsed = start.elapsed(); + + assert_eq!(result2, 4); + // Should have waited at least the minimum interval + assert!(elapsed.as_millis() >= min_interval as u128); + } + + #[tokio::test] + async fn test_processor_error() { + let processor = TestProcessor::with_failure(); + let batch = Batch::with_defaults(processor); + + let result = batch.call(5).await; + assert!(result.is_err()); + + match result { + Err(BatchError::ProcessorError(err)) => { + assert_eq!(err.0, "Simulated processor error"); + } + _ => panic!("Expected ProcessorError"), + } + } + + #[tokio::test] + async fn test_multiple_batches() { + let processor = TestProcessor::new(); + let batch = Arc::new(Batch::with_timing(processor, 50, 100)); + + // First batch + let futures = vec![1, 2, 3] + .into_iter() + .map(|i| { + let batch_clone = Arc::clone(&batch); + tokio::spawn(async move { batch_clone.call(i).await }) + }) + .collect::>(); + + let results1 = futures::future::join_all(futures).await; + + for result in &results1 { + assert!(result.as_ref().unwrap().is_ok()); + } + + // Wait for the first batch to fully complete and the throttle time to be recorded + sleep(Duration::from_millis(50)).await; + + // Second batch - should be throttled + let start = Instant::now(); + + let futures = vec![4, 5] + .into_iter() + .map(|i| { + let batch_clone = Arc::clone(&batch); + tokio::spawn(async move { batch_clone.call(i).await }) + }) + .collect::>(); + + let results2 = futures::future::join_all(futures).await; + let elapsed = start.elapsed(); + + for result in &results2 { + assert!(result.as_ref().unwrap().is_ok()); + } + + // Should have processed in two separate batches + assert_eq!(batch.processor.process_count(), 2); + + // The second batch might not be throttled by the full interval if some time has already passed + // Just check that there was some delay, not the exact amount + assert!(elapsed.as_millis() > 0); + } + + #[tokio::test] + async fn test_update_config() { + let processor = TestProcessor::new(); + let mut batch = Batch::with_timing(processor, 100, 200); + + // Update config + batch.update_config(BatchConfig { + batch_delay_ms: 10, + min_interval_ms: 20, + }); + + let start = Instant::now(); + let result = batch.call(5).await.unwrap(); + let elapsed = start.elapsed(); + + assert_eq!(result, 10); + // Should use the new shorter delay + assert!(elapsed.as_millis() >= 10); + assert!(elapsed.as_millis() < 100); + } + + #[tokio::test] + async fn test_set_batch_delay() { + let processor = TestProcessor::new(); + let mut batch = Batch::with_timing(processor, 100, 200); + + // Update just the batch delay + batch.set_batch_delay(10); + + let start = Instant::now(); + let result = batch.call(5).await.unwrap(); + let elapsed = start.elapsed(); + + assert_eq!(result, 10); + // Should use the new shorter delay + assert!(elapsed.as_millis() >= 10); + assert!(elapsed.as_millis() < 100); + } + + #[tokio::test] + async fn test_set_min_interval() { + let processor = TestProcessor::new(); + let mut batch = Batch::with_timing(processor, 0, 200); + + // First call + batch.call(1).await.unwrap(); + + // Update min interval + batch.set_min_interval(50); + + // Second call should use new interval + let start = Instant::now(); + batch.call(2).await.unwrap(); + let elapsed = start.elapsed(); + + // Should use the new shorter interval + assert!(elapsed.as_millis() >= 50); + assert!(elapsed.as_millis() < 200); + } + + #[tokio::test] + async fn test_empty_batch() { + // This is an edge case that shouldn't happen in normal usage, + // but we test it for completeness + let processor = TestProcessor::new(); + let batch = Batch::with_defaults(processor); + + // Manually trigger the batch processing with no items + // (This is a bit of a hack to test internal behavior) + let queue = Arc::clone(&batch.queue); + Batch::::schedule_next_batch(queue, Arc::clone(&batch.processor)).await; + + // The processor should not have been called + assert_eq!(batch.processor.process_count(), 0); + } + + #[tokio::test] + async fn test_slow_processor() { + let processor = TestProcessor::with_delay(200); + let batch = Arc::new(Batch::with_timing(processor, 10, 0)); + + // Submit multiple items + let futures = vec![1, 2, 3] + .into_iter() + .map(|i| { + let batch_clone = Arc::clone(&batch); + tokio::spawn(async move { batch_clone.call(i).await }) + }) + .collect::>(); + + let start = Instant::now(); + let results = futures::future::join_all(futures).await; + let elapsed = start.elapsed(); + + for result in &results { + assert!(result.as_ref().unwrap().is_ok()); + } + + // Should have waited for the processor delay + assert!(elapsed.as_millis() >= 200); + } + + #[tokio::test] + async fn test_task_dropped() { + let processor = TestProcessor::with_delay(1000); // Long delay + let batch = Arc::new(Batch::with_defaults(processor)); + + // Start a task that will be cancelled + let batch_clone = Arc::clone(&batch); + let handle = tokio::spawn(async move { batch_clone.call(5).await }); + + // Cancel the task before it completes + sleep(Duration::from_millis(10)).await; + handle.abort(); + + // The batch should still process, but no one will receive the result + sleep(Duration::from_millis(1100)).await; + + // The processor should have been called once + assert_eq!(batch.processor.process_count(), 1); + } + + #[tokio::test] + async fn test_concurrent_batches_with_different_timings() { + let processor = TestProcessor::new(); + let batch = Arc::new(Batch::with_timing(processor, 50, 100)); + + // Submit first item + let batch_clone1 = Arc::clone(&batch); + let handle1 = tokio::spawn(async move { batch_clone1.call(1).await }); + + // Wait a bit but not enough to trigger the batch + sleep(Duration::from_millis(20)).await; + + // Submit more items that should be in the same batch + let batch_clone2 = Arc::clone(&batch); + let handle2 = tokio::spawn(async move { batch_clone2.call(2).await }); + + let batch_clone3 = Arc::clone(&batch); + let handle3 = tokio::spawn(async move { batch_clone3.call(3).await }); + + // Wait for the first batch to complete + let result1 = handle1.await.unwrap().unwrap(); + let result2 = handle2.await.unwrap().unwrap(); + let result3 = handle3.await.unwrap().unwrap(); + + assert_eq!(result1, 2); + assert_eq!(result2, 4); + assert_eq!(result3, 6); + + // Wait a bit but not enough to clear the throttle + sleep(Duration::from_millis(50)).await; + + // Submit more items that should be in a second batch + let start = Instant::now(); + let batch_clone4 = Arc::clone(&batch); + let handle4 = tokio::spawn(async move { batch_clone4.call(4).await }); + + let result4 = handle4.await.unwrap().unwrap(); + let elapsed = start.elapsed(); + + assert_eq!(result4, 8); + + // Should have been throttled + assert!(elapsed.as_millis() >= 50); // Remaining throttle time + + // Should have processed in two batches + assert_eq!(batch.processor.process_count(), 2); + } + + #[tokio::test] + async fn test_large_batch() { + let processor = TestProcessor::new(); + let batch = Arc::new(Batch::with_timing(processor, 10, 0)); + + // Submit a large number of items + let count = 1000; + let handles = (0..count) + .map(|i| { + let batch_clone = Arc::clone(&batch); + tokio::spawn(async move { batch_clone.call(i).await }) + }) + .collect::>(); + + // Wait for all to complete + let results = futures::future::join_all(handles).await; + + // Verify all results + for (i, result) in results.iter().enumerate() { + let value = result.as_ref().unwrap().as_ref().unwrap(); + assert_eq!(*value, (i as u32) * 2); + } + + // Should have processed in a single batch + assert_eq!(batch.processor.process_count(), 1); + } + + #[tokio::test] + async fn test_zero_timing_wait_for_active() { + let processor = TestProcessor::with_delay(100); // Processor with delay + let batch = Arc::new(Batch::with_timing(processor, 0, 0)); // Zero timing config + + // Start first batch + let batch_clone1 = Arc::clone(&batch); + let handle1 = tokio::spawn(async move { batch_clone1.call(1).await }); + + // Immediately start second batch while first is still processing + sleep(Duration::from_millis(10)).await; + let start = Instant::now(); + let batch_clone2 = Arc::clone(&batch); + let handle2 = tokio::spawn(async move { batch_clone2.call(2).await }); + + let result1 = handle1.await.unwrap().unwrap(); + let result2 = handle2.await.unwrap().unwrap(); + let elapsed = start.elapsed(); + + assert_eq!(result1, 2); + assert_eq!(result2, 4); + + // Even with zero timing, should have waited for first batch to complete + assert!(elapsed.as_millis() >= 90); // Processor delay was 100ms, we waited 10ms before starting + assert_eq!(batch.processor.process_count(), 2); // Should be two separate batches + } +} diff --git a/pkg/primitives/src/block_height.rs b/pkg/primitives/src/block_height.rs index 50b892e..dae1f2e 100644 --- a/pkg/primitives/src/block_height.rs +++ b/pkg/primitives/src/block_height.rs @@ -3,9 +3,13 @@ use std::fmt::Debug; use borsh::{BorshDeserialize, BorshSerialize}; use rand_derive2::RandGen; use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; microtype::microtype! { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, BorshSerialize, BorshDeserialize, RandGen, Serialize, Deserialize)] + #[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] pub u64 { #[derive(Default)] #[int] // add maths traits diff --git a/pkg/primitives/src/lib.rs b/pkg/primitives/src/lib.rs index 497a879..dc48ada 100644 --- a/pkg/primitives/src/lib.rs +++ b/pkg/primitives/src/lib.rs @@ -1,8 +1,11 @@ +pub mod batch; pub mod block_height; pub mod hash; pub mod pagination; pub mod peer; pub mod pool; +pub mod retry; +pub mod serde; pub mod sig; pub mod tick_worker; pub mod u256; @@ -12,3 +15,6 @@ pub use web3::{ signing::SecretKey, types::{Address, H256, U256}, }; + +#[cfg(test)] +mod tests; diff --git a/pkg/primitives/src/pagination.rs b/pkg/primitives/src/pagination.rs index 5dfc201..f1c11ad 100644 --- a/pkg/primitives/src/pagination.rs +++ b/pkg/primitives/src/pagination.rs @@ -1,6 +1,9 @@ +// lint-long-file-override allow-max-lines=400 use std::ops::Bound; use base64::Engine; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; /// A wrapper around a value that serializes it using serde_json and then encodes it using base64 #[derive(Debug, Clone, Copy)] @@ -108,6 +111,8 @@ pub struct OpaqueCursor { /// This type is meant to be used in client code, /// where the actual cursor types are not needed. #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] pub struct OpaqueClientCursor { pub after: Option, pub before: Option, diff --git a/pkg/primitives/src/peer.rs b/pkg/primitives/src/peer.rs index d535fbb..1d38741 100644 --- a/pkg/primitives/src/peer.rs +++ b/pkg/primitives/src/peer.rs @@ -1,6 +1,7 @@ -use crate::{hash::CryptoHash, sig::Signature}; +// lint-long-file-override allow-max-lines=300 +use crate::{hash::CryptoHash, sig::Signature, u256::U256}; use borsh::{BorshDeserialize, BorshSerialize}; -use secp256k1::{Message, PublicKey, SecretKey, SECP256K1}; +use secp256k1::{Message, PublicKey, SECP256K1, SecretKey}; use serde::{Deserialize, Deserializer, Serialize}; use sha3::{Digest, Keccak256}; use std::{fmt::Display, str::FromStr}; @@ -55,8 +56,8 @@ impl Address { self.0.to_vec() } - pub fn to_u256(&self) -> crate::u256::U256 { - crate::u256::U256::from_little_endian(&self.0) + pub fn to_u256(&self) -> U256 { + U256::from_little_endian(&self.0) } } @@ -137,8 +138,8 @@ impl PeerIdSigner { pub fn sign(&self, msg: &CryptoHash) -> Signature { let mut hasher = Keccak256::new(); - hasher.update(b"Polybase".len().to_be_bytes()); - hasher.update(b"Polybase"); + hasher.update(b"Payy".len().to_be_bytes()); + hasher.update(b"Payy"); hasher.update(msg.inner()); let msg = Into::<[u8; 32]>::into(hasher.finalize()); let msg = Message::from_digest(msg); diff --git a/pkg/primitives/src/pool.rs b/pkg/primitives/src/pool.rs index 2da0ccf..581293f 100644 --- a/pkg/primitives/src/pool.rs +++ b/pkg/primitives/src/pool.rs @@ -110,6 +110,17 @@ impl Drop for PoolGuard { } } +impl std::fmt::Debug for PoolGuard +where + T: std::fmt::Debug, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("PoolGuard") + .field("value", &self.value) + .finish() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/pkg/primitives/src/retry.rs b/pkg/primitives/src/retry.rs new file mode 100644 index 0000000..a44aacd --- /dev/null +++ b/pkg/primitives/src/retry.rs @@ -0,0 +1,126 @@ +use std::time::Duration; +use tokio::time::sleep; + +pub fn retry(operation: F) -> Retry +where + F: FnMut() -> Fut, + Fut: std::future::Future>, +{ + Retry { + operation, + retry_delay: Duration::from_millis(1000), + error_handler: None, + } +} + +pub async fn retry_forever(operation: F, retry_delay: Duration) -> T +where + F: FnMut() -> Fut, + Fut: std::future::Future>, +{ + retry(operation) + .retry_delay(retry_delay) + .exec_forever() + .await +} + +pub async fn retry_with_exponential_backoff( + mut operation: F, + attempts: usize, + initial_delay: Duration, + max_delay: Duration, + mut on_error: H, +) -> Result +where + F: FnMut() -> Fut, + Fut: std::future::Future>, + H: FnMut(usize, &E, Duration) + Send, +{ + let attempts = attempts.max(1); + let mut delay = initial_delay; + let max_delay = max_delay.max(initial_delay); + let mut attempt = 1; + + loop { + match operation().await { + Ok(value) => return Ok(value), + Err(err) => { + if attempt >= attempts { + return Err(err); + } + + on_error(attempt, &err, delay); + sleep(delay).await; + delay = delay.saturating_mul(2).min(max_delay); + attempt += 1; + } + } + } +} + +pub struct Retry +where + F: FnMut() -> Fut, + Fut: std::future::Future>, +{ + operation: F, + retry_delay: Duration, + error_handler: Option>, +} + +// Type alias to reduce type complexity warning +type ErrorHandler = Box; + +impl Retry +where + F: FnMut() -> Fut, + Fut: std::future::Future>, +{ + pub fn on_error(mut self, handler: H) -> Self + where + H: Fn(&E) + Send + 'static, + { + self.error_handler = Some(Box::new(handler)); + self + } + + pub fn retry_delay(mut self, delay: Duration) -> Self { + self.retry_delay = delay; + self + } + + pub async fn exec_forever(self) -> T { + let mut operation = self.operation; + loop { + match operation().await { + Ok(value) => return value, + Err(err) => { + if let Some(ref handler) = self.error_handler { + handler(&err); + } + sleep(self.retry_delay).await; + } + } + } + } + + pub async fn exec(self, attempts: usize) -> Result { + let mut operation = self.operation; + let mut last_error: Option = None; + + for _ in 0..attempts { + match operation().await { + Ok(value) => return Ok(value), + Err(err) => { + if let Some(ref handler) = self.error_handler { + handler(&err); + } + last_error = Some(err); + sleep(self.retry_delay).await; + } + } + } + + Err(last_error.unwrap()) + } +} diff --git a/pkg/primitives/src/serde.rs b/pkg/primitives/src/serde.rs new file mode 100644 index 0000000..515e144 --- /dev/null +++ b/pkg/primitives/src/serde.rs @@ -0,0 +1,152 @@ +use base64::Engine; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::ops::{Deref, DerefMut}; + +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql}, + pg::Pg, + serialize::{self, Output, ToSql}, + sql_types::Bytea, +}; + +/// Wrapper for `Vec` that (de)serializes to/from base64 strings. +/// +/// Using this type instead of raw `Vec` avoids sprinkling `#[serde(serialize_with = ...)]` +/// attributes throughout the codebase while preserving the JSON contract. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, Hash)] +#[serde(transparent)] +#[cfg_attr(feature = "diesel", derive(diesel::AsExpression, diesel::FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Bytea))] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct Base64Bytes( + #[serde( + serialize_with = "serialize_base64", + deserialize_with = "deserialize_base64" + )] + #[cfg_attr(feature = "ts-rs", ts(as = "String"))] + pub Vec, +); + +impl Base64Bytes { + pub fn new(bytes: Vec) -> Self { + Self(bytes) + } + + pub fn into_inner(self) -> Vec { + self.0 + } + + pub fn as_slice(&self) -> &[u8] { + &self.0 + } + + pub fn as_mut_slice(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +impl Deref for Base64Bytes { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Base64Bytes { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl AsRef<[u8]> for Base64Bytes { + fn as_ref(&self) -> &[u8] { + self.as_slice() + } +} + +impl AsMut<[u8]> for Base64Bytes { + fn as_mut(&mut self) -> &mut [u8] { + self.as_mut_slice() + } +} + +impl From> for Base64Bytes { + fn from(bytes: Vec) -> Self { + Self::new(bytes) + } +} + +impl From<&[u8]> for Base64Bytes { + fn from(bytes: &[u8]) -> Self { + Self::new(bytes.to_vec()) + } +} + +impl From for Vec { + fn from(bytes: Base64Bytes) -> Self { + bytes.into_inner() + } +} + +#[cfg(feature = "diesel")] +impl ToSql for Base64Bytes { + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result { + as ToSql>::to_sql(&self.0, out) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Base64Bytes { + fn from_sql( + bytes: ::RawValue<'_>, + ) -> deserialize::Result { + as FromSql>::from_sql(bytes).map(Base64Bytes::new) + } +} + +// Custom serializer for Vec to base64 string +pub fn serialize_base64(value: &Vec, serializer: S) -> Result +where + S: Serializer, +{ + let base64_string = base64::engine::general_purpose::STANDARD.encode(value); + serializer.serialize_str(&base64_string) +} + +// Custom deserializer for base64 string to Vec +pub fn deserialize_base64<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + let trimmed = s.trim(); + base64::engine::general_purpose::STANDARD + .decode(trimmed) + .map_err(serde::de::Error::custom) +} + +pub fn serialize_hex_0x_prefixed(value: &Vec, serializer: S) -> Result +where + S: Serializer, +{ + let hex_string = format!("0x{}", hex::encode(value)); + serializer.serialize_str(&hex_string) +} + +pub fn deserialize_hex_0x_prefixed<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + let s = s.trim_start_matches("0x"); + hex::decode(s).map_err(serde::de::Error::custom) +} + +#[cfg(test)] +mod tests; diff --git a/pkg/primitives/src/serde/tests.rs b/pkg/primitives/src/serde/tests.rs new file mode 100644 index 0000000..a48a2b3 --- /dev/null +++ b/pkg/primitives/src/serde/tests.rs @@ -0,0 +1,48 @@ +use super::Base64Bytes; +use serde::{Deserialize, Serialize}; + +#[test] +fn base64bytes_json_roundtrip() { + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Payload { + data: Base64Bytes, + } + + let bytes = vec![0xde, 0xad, 0xbe, 0xef]; + let payload = Payload { + data: Base64Bytes::from(bytes.clone()), + }; + + let json = serde_json::to_string(&payload).expect("serialize payload"); + assert_eq!(json, "{\"data\":\"3q2+7w==\"}"); + + let decoded: Payload = serde_json::from_str(&json).expect("deserialize payload"); + assert_eq!(decoded, payload); + assert_eq!(decoded.data.as_slice(), bytes.as_slice()); +} + +#[test] +fn base64bytes_from_impls_preserve_data() { + let bytes = vec![1, 2, 3, 4]; + let from_vec = Base64Bytes::from(bytes.clone()); + let from_slice = Base64Bytes::from(bytes.as_slice()); + + assert_eq!(from_vec.as_slice(), bytes.as_slice()); + assert_eq!(from_slice.as_slice(), bytes.as_slice()); + + let round_trip: Vec = from_vec.into(); + assert_eq!(round_trip, bytes); +} + +#[test] +fn deserialize_base64_trims_input() { + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] + struct Payload { + data: Base64Bytes, + } + + let json = "{\"data\":\" 3q2+7w==\\n\"}"; + let decoded: Payload = serde_json::from_str(json).expect("deserialize payload with whitespace"); + + assert_eq!(decoded.data.as_slice(), &[0xde, 0xad, 0xbe, 0xef]); +} diff --git a/pkg/primitives/src/sig.rs b/pkg/primitives/src/sig.rs index 9715e09..3af950a 100644 --- a/pkg/primitives/src/sig.rs +++ b/pkg/primitives/src/sig.rs @@ -1,15 +1,17 @@ use crate::{hash::CryptoHash, peer::Address}; use borsh::{BorshDeserialize, BorshSerialize}; use secp256k1::{ - ecdsa::{self, RecoveryId}, Message, SECP256K1, + ecdsa::{self, RecoveryId}, }; use serde::{Deserialize, Serialize}; use sha3::{Digest, Keccak256}; -const NETWORK: &str = "Polybase"; +const NETWORK: &str = "Payy"; -#[derive(Debug, Clone, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] +#[derive( + Debug, Clone, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize, Serialize, Deserialize, +)] #[serde(transparent)] pub struct Signature(#[serde(with = "hex::serde")] pub [u8; 65]); diff --git a/pkg/primitives/src/tests.rs b/pkg/primitives/src/tests.rs new file mode 100644 index 0000000..de2e70d --- /dev/null +++ b/pkg/primitives/src/tests.rs @@ -0,0 +1,94 @@ +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::{Arc, Mutex}; +use std::time::Duration; + +use tokio::task::yield_now; +use tokio::time::advance; + +use crate::retry::retry_with_exponential_backoff; + +#[tokio::test(start_paused = true)] +async fn retry_with_exponential_backoff_retries_until_success() { + let attempts = Arc::new(AtomicUsize::new(0)); + let attempts_clone = Arc::clone(&attempts); + let events = Arc::new(Mutex::new(Vec::new())); + let events_clone = Arc::clone(&events); + + let handle = tokio::spawn(async move { + retry_with_exponential_backoff( + || { + let attempts = Arc::clone(&attempts_clone); + async move { + let attempt = attempts.fetch_add(1, Ordering::SeqCst); + if attempt < 2 { Err("fail") } else { Ok("ok") } + } + }, + 5, + Duration::from_secs(1), + Duration::from_secs(8), + move |attempt, _err, delay| { + let mut guard = events_clone.lock().unwrap(); + guard.push((attempt, delay)); + }, + ) + .await + }); + + yield_now().await; + advance(Duration::from_secs(1)).await; + yield_now().await; + advance(Duration::from_secs(2)).await; + + let result = handle.await.unwrap(); + assert_eq!(result.unwrap(), "ok"); + assert_eq!(attempts.load(Ordering::SeqCst), 3); + + let events = events.lock().unwrap(); + assert_eq!( + events.as_slice(), + &[(1, Duration::from_secs(1)), (2, Duration::from_secs(2))] + ); +} + +#[tokio::test(start_paused = true)] +async fn retry_with_exponential_backoff_returns_last_error() { + let attempts = Arc::new(AtomicUsize::new(0)); + let attempts_clone = Arc::clone(&attempts); + let events = Arc::new(Mutex::new(Vec::new())); + let events_clone = Arc::clone(&events); + + let handle = tokio::spawn(async move { + retry_with_exponential_backoff( + || { + let attempts = Arc::clone(&attempts_clone); + async move { + attempts.fetch_add(1, Ordering::SeqCst); + Err::<(), &str>("fail") + } + }, + 3, + Duration::from_secs(1), + Duration::from_secs(4), + move |attempt, _err, delay| { + let mut guard = events_clone.lock().unwrap(); + guard.push((attempt, delay)); + }, + ) + .await + }); + + yield_now().await; + advance(Duration::from_secs(1)).await; + yield_now().await; + advance(Duration::from_secs(2)).await; + + let result = handle.await.unwrap(); + assert_eq!(result.unwrap_err(), "fail"); + assert_eq!(attempts.load(Ordering::SeqCst), 3); + + let events = events.lock().unwrap(); + assert_eq!( + events.as_slice(), + &[(1, Duration::from_secs(1)), (2, Duration::from_secs(2))] + ); +} diff --git a/pkg/primitives/src/tick_worker.rs b/pkg/primitives/src/tick_worker.rs index 5dd8954..7f3e3ee 100644 --- a/pkg/primitives/src/tick_worker.rs +++ b/pkg/primitives/src/tick_worker.rs @@ -1,8 +1,8 @@ use async_trait::async_trait; use std::marker::PhantomData; use std::sync::{ - atomic::{AtomicBool, Ordering::Relaxed}, Arc, + atomic::{AtomicBool, Ordering::Relaxed}, }; use std::time::Instant; use tokio::sync::Notify; @@ -13,6 +13,7 @@ pub struct TickWorker { } pub struct TickWorkerShared { + is_running: AtomicBool, shutdown: AtomicBool, background_worker: Notify, } @@ -32,6 +33,7 @@ impl TickWorker { pub fn new() -> Self { TickWorker { shared: Arc::new(TickWorkerShared { + is_running: AtomicBool::new(false), shutdown: AtomicBool::new(false), background_worker: Notify::new(), }), @@ -39,12 +41,23 @@ impl TickWorker { } } - /// Creates and starts the background worker - pub fn run(&self, ticker: T) -> tokio::task::JoinHandle<()> { - tokio::spawn(background_worker(Arc::clone(&self.shared), ticker)) + /// Creates and starts the background worker. You may safely call run multiple + /// times, and only one worker will be spawned. + pub fn run(&self, ticker: T) { + if self + .shared + .is_running + .compare_exchange(false, true, Relaxed, Relaxed) + .is_ok() + { + tokio::spawn(background_worker(Arc::clone(&self.shared), ticker)); + } else { + self.tick(); + } } - /// Manually forces a tick to occur + /// Manually forces a tick to occur if the tick was paused due to tick worker + /// tick returning None pub fn tick(&self) { self.shared.background_worker.notify_one(); } @@ -61,6 +74,9 @@ impl TickWorkerShared { // Mark as shutdown self.shutdown.store(true, Relaxed); + // Mark as not running + self.is_running.store(false, Relaxed); + // Notify the worker, so it wakes up and exits immediately self.background_worker.notify_one(); } @@ -73,15 +89,17 @@ impl TickWorkerShared { /// Background worker that calls `tick` whenever its scheduled to run the /// next task or worken up by the `background_worker` channel. pub async fn background_worker(worker: Arc, shared: T) { - // If the shutdown flag is set, then the task should exit. + // If the shutdown flag is set, then the task should exit while !worker.is_shutdown() { // Check timeout if let Some(when) = shared.tick().await { - let time_to_sleep = when - Instant::now(); - - tokio::select! { - _ = tokio::time::sleep(time_to_sleep) => {} - _ = worker.background_worker.notified() => {} + let now = Instant::now(); + if when > now { + let time_to_sleep = when - now; + tokio::select! { + _ = tokio::time::sleep(time_to_sleep) => {} + _ = worker.background_worker.notified() => {} + } } } else { // No expiry set, so wait to be notified diff --git a/pkg/primitives/src/u256.rs b/pkg/primitives/src/u256.rs index 9eea7b9..9b972d7 100644 --- a/pkg/primitives/src/u256.rs +++ b/pkg/primitives/src/u256.rs @@ -1,4 +1,5 @@ #![allow(clippy::assign_op_pattern)] +#![expect(clippy::manual_div_ceil)] use uint::*; diff --git a/pkg/primitives/src/util.rs b/pkg/primitives/src/util.rs index 086deb9..abb6d96 100644 --- a/pkg/primitives/src/util.rs +++ b/pkg/primitives/src/util.rs @@ -5,7 +5,7 @@ use std::borrow::Cow; /// Truncate the given string in the middle, keeping `max_len/2` characters from /// the beginning and `max_len/2` characters from the end. /// If the string is smaller than `max_len`, it is returned as is. -pub fn middle_truncate(s: &str, max_len: usize) -> Cow { +pub fn middle_truncate(s: &str, max_len: usize) -> Cow<'_, str> { if s.len() <= max_len { Cow::Borrowed(s) } else { diff --git a/pkg/prover/Cargo.toml b/pkg/prover/Cargo.toml index 1dd3761..f832d68 100644 --- a/pkg/prover/Cargo.toml +++ b/pkg/prover/Cargo.toml @@ -1,30 +1,28 @@ [package] name = "prover" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] zk-circuits = { workspace = true } primitives = { workspace = true } contracts = { workspace = true } smirk = { workspace = true } +element = { workspace = true } +zk-primitives = { workspace = true } ethereum-types = { workspace = true } -parking_lot = { workspace = true } -rand = { workspace = true, features = ["getrandom"] } secp256k1 = { workspace = true } serde_json = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } web3 = { workspace = true } -lazy_static = { workspace = true } borsh = { workspace = true } -tokio-postgres = { workspace = true } # TODO: why are we using this instead of hex lib? rustc-hex = { workspace = true } - +workspace-hack.workspace = true [dev-dependencies] expect-test = { workspace = true } diff --git a/pkg/prover/README.md b/pkg/prover/README.md index 4d4782a..f17be95 100644 --- a/pkg/prover/README.md +++ b/pkg/prover/README.md @@ -14,7 +14,7 @@ npm run deploy -- --network localhost Copy the `Rollup` contract address and set it as an environment variable `ROLLUP_CONTRACT_ADDR`: ``` -export ROLLUP_CONTRACT_ADDR=0x2279b7a0a67db372996a5fab50d91eaa73d2ebe6 +export ROLLUP_CONTRACT_ADDR=0xdc64a140aa3e981100a9beca4e685f962f0cf6c9 ``` Then run the tests: @@ -22,5 +22,3 @@ Then run the tests: ``` cargo test ``` - - diff --git a/pkg/prover/src/lib.rs b/pkg/prover/src/lib.rs index 32aa36a..773e5c9 100644 --- a/pkg/prover/src/lib.rs +++ b/pkg/prover/src/lib.rs @@ -1,29 +1,30 @@ #![warn(clippy::unwrap_used, clippy::expect_used)] #![deny(clippy::disallowed_methods)] +// lint-long-file-override allow-max-lines=600 mod constants; pub mod smirk_metadata; - -use crate::constants::{MERKLE_TREE_DEPTH, MERKLE_TREE_PATH_DEPTH, UTXO_AGGREGATIONS}; +use crate::constants::{ + MERKLE_TREE_DEPTH, MERKLE_TREE_PATH_DEPTH, UTXO_AGG_LEAVES, UTXO_AGG_NUMBER, UTXO_AGGREGATIONS, +}; use borsh::{BorshDeserialize, BorshSerialize}; pub use constants::MAXIMUM_TXNS; -use constants::{UTXO_AGG_LEAVES, UTXO_AGG_NUMBER}; use contracts::RollupContract; +use element::Element; use ethereum_types::H256; use primitives::sig::Signature; use smirk::{ + Path, Tree, hash_cache::{NoopHashCache, SimpleHashCache}, - Element, Tree, }; use smirk_metadata::SmirkMetadata; use std::sync::Arc; use tracing::info; use web3::{ethabi, types::TransactionId}; -use zk_circuits::{ - aggregate_utxo::AggregateUtxo, - chips::aggregation::snark::Snark, - data::{AggregateAgg, Batch, Insert, MerklePath, Note, ParameterSet, SnarkWitness, Utxo}, - evm_verifier, Base, CircuitKind, +use zk_circuits::{BbBackend, Prove, Verify}; +use zk_primitives::{ + AggAgg, AggFinal, AggFinalProof, AggProof, AggUtxo, AggUtxoProof, MerklePath, UtxoProof, + UtxoProofBundleWithMerkleProofs, }; type Result = std::result::Result; @@ -48,9 +49,6 @@ pub enum Error { #[error("ethabi error")] EthAbi(#[from] ethabi::Error), - #[error("zk error: {0}")] - Zk(#[from] zk_circuits::Error), - #[error("TryFromSlice error")] TryFromSlice(#[from] std::array::TryFromSliceError), @@ -74,36 +72,28 @@ pub enum Error { #[error("tokio task join error")] TokioTaskJoin(#[from] tokio::task::JoinError), + + #[error("barretenberg prove error: {0}")] + BarretenbergProve(String), + + #[error("vec to array conversion failed, expected {expected}, got {actual}")] + VecToArrayConversion { expected: usize, actual: usize }, } #[derive(Debug, Clone)] pub struct Transaction { - pub proof: SnarkWitness, + pub proof: UtxoProof, } impl Transaction { - pub fn new(proof: SnarkWitness) -> Self { + pub fn new(proof: UtxoProof) -> Self { Self { proof } } } -#[derive(Debug, Clone, Default, BorshSerialize, BorshDeserialize)] -pub struct Proof { - pub proof: Vec, - pub agg_instances: Vec, - pub old_root: Element, - pub new_root: Element, - pub utxo_hashes: Vec, -} - -impl Proof { - pub fn new_root(&self) -> &Element { - &self.new_root - } -} #[derive(Debug, Clone, Default, BorshSerialize, BorshDeserialize)] pub struct RollupInput { - proof: Proof, + proof: AggFinalProof, height: u64, other_hash: [u8; 32], signatures: Vec, @@ -111,7 +101,7 @@ pub struct RollupInput { impl RollupInput { pub fn new( - proof: Proof, + proof: AggFinalProof, height: u64, other_hash: [u8; 32], signatures: Vec, @@ -124,8 +114,12 @@ impl RollupInput { } } - pub fn old_root(&self) -> &Element { - &self.proof.old_root + pub fn old_root(&self) -> Element { + self.proof.public_inputs.old_root + } + + pub fn new_root(&self) -> Element { + self.proof.public_inputs.new_root } pub fn height(&self) -> u64 { @@ -135,51 +129,35 @@ impl RollupInput { pub struct Prover { contract: RollupContract, + bb_backend: Arc, } impl Prover { - pub fn new(contract: RollupContract) -> Self { - Self { contract } + pub fn new(contract: RollupContract, bb_backend: Arc) -> Self { + Self { + contract, + bb_backend, + } } #[tracing::instrument(err, skip_all, fields(height, txns_len = txns.len()))] pub async fn prove( self: &Arc, notes_tree: &MerkleTree, - _ban_tree: &MerkleTree, height: u64, txns: [Option; MAXIMUM_TXNS], - ) -> Result { + ) -> Result { info!( "Bundling {} UTXO proof(s) and proving new root hash", txns.len() ); - let (agg, proof) = tokio::task::spawn_blocking({ - let s = Arc::clone(self); - let mut tree = notes_tree.clone(); - - move || s.generate_aggregate_proof(&mut tree, txns, height) - }) - .await??; + let mut tree = notes_tree.clone(); + let proof = self + .generate_aggregate_proof(&mut tree, txns, height) + .await?; - Ok(Proof { - proof, - agg_instances: agg - .agg_instances() - .iter() - .copied() - .map(Element::from) - .collect(), - old_root: Element::from(*agg.old_root()), - new_root: Element::from(*agg.new_root()), - utxo_hashes: agg - .utxo_values() - .iter() - .copied() - .map(Element::from) - .collect(), - }) + Ok(proof) } #[tracing::instrument(err, skip(self), fields(height = input.height))] @@ -189,13 +167,12 @@ impl Prover { let tx = self .contract .verify_block( - &input.proof.proof, - // These should never fail. If they fail, we will catch them in testing - #[allow(clippy::unwrap_used)] - input.proof.agg_instances.clone().try_into().unwrap(), - &input.proof.old_root, - &input.proof.new_root, - &input.proof.utxo_hashes, + &input.proof.proof.0, + &input.proof.public_inputs.old_root, + &input.proof.public_inputs.new_root, + &input.proof.public_inputs.commit_hash, + &input.proof.public_inputs.messages.to_vec(), + &input.proof.kzg, input.other_hash, input.height, &input @@ -249,92 +226,130 @@ impl Prover { } #[tracing::instrument(err, skip_all)] - fn generate_aggregate_proof( + async fn generate_aggregate_proof( &self, tree: &mut MerkleTree, txns: [Option; 6], current_block: u64, - ) -> Result<(AggregateAgg<1>, Vec), Error> { - let mut txns = txns.into_iter().map(|t| match t { - Some(t) => Ok(t), - None => Ok(Transaction { - proof: SnarkWitness::V1( - Utxo::::new_padding() - .snark(CircuitKind::Utxo)? - .to_witness(), - ), - }), - }); + ) -> Result { + let txns = txns + .into_iter() + .map(|t| match t { + Some(t) => Ok(t), + None => Ok(Transaction { + proof: UtxoProof::default(), + }), + }) + .collect::>>()?; + let txns = &mut txns.iter(); let mut utxo_aggregations = Vec::new(); for _i in 0..UTXO_AGGREGATIONS { + // Take the first 3 txns (removing from the vec) // Unwrap is safe because we know we have enough txns #[allow(clippy::unwrap_used)] - let txns: [Transaction; UTXO_AGG_NUMBER] = (&mut txns) + let txns: [Transaction; UTXO_AGG_NUMBER] = txns .take(3) - .collect::>>()? + .cloned() + .collect::>() .try_into() .unwrap(); - let utxo_aggregate = self.aggregate_utxo(tree, txns.clone(), current_block)?; + let utxo_aggregate = self + .aggregate_utxo(tree, txns.clone(), current_block) + .await?; utxo_aggregations.push(utxo_aggregate); } - #[allow(clippy::unwrap_used)] - let agg = self.aggregate_aggregate_utxo(&utxo_aggregations.try_into().unwrap())?; - let agg_agg_agg = AggregateAgg::<1>::new([agg.snark(ParameterSet::TwentyOne)?]); - let agg = agg_agg_agg; - let (pk, _) = agg.keygen(ParameterSet::TwentyOne); - let proof = evm_verifier::gen_proof( - ParameterSet::TwentyOne, - &pk, - agg.clone(), - &[&agg.public_inputs()], - )?; - - Ok((agg, proof)) - } - - #[tracing::instrument(err, skip_all)] - fn aggregate_aggregate_utxo( - &self, - aggregations: &[AggregateUtxo; - UTXO_AGGREGATIONS], - ) -> Result, Error> { - Ok(AggregateAgg::new( - #[allow(clippy::unwrap_used)] - TryInto::<[Snark; UTXO_AGGREGATIONS]>::try_into( - aggregations - .iter() - .map(|a| a.snark(ParameterSet::TwentyOne)) - .collect::, _>>()?, - ) - .unwrap(), - )) + let utxo_aggregations: [AggUtxoProof; UTXO_AGGREGATIONS] = utxo_aggregations + .try_into() + .map_err(|v: Vec<_>| Error::VecToArrayConversion { + expected: UTXO_AGGREGATIONS, + actual: v.len(), + })?; + + let agg_proofs: [AggProof; UTXO_AGGREGATIONS] = + utxo_aggregations.map(|proof| AggProof::AggUtxo(Box::new(proof))); + + let agg_agg = AggAgg::new(agg_proofs); + let agg_agg_proof = agg_agg + .prove(&*self.bb_backend) + .await + .map_err(|e| Error::BarretenbergProve(e.to_string()))?; + + let agg_final = AggFinal::new(agg_agg_proof); + let proof = agg_final + .prove(&*self.bb_backend) + .await + .map_err(|e| Error::BarretenbergProve(e.to_string()))?; + + // Verify the newly generated proof + proof + .verify(&*self.bb_backend) + .await + .map_err(|e| Error::BarretenbergProve(e.to_string()))?; + + Ok(proof) } #[tracing::instrument(err, skip_all)] - fn aggregate_utxo( + async fn aggregate_utxo( &self, tree: &mut MerkleTree, utxos: [Transaction; UTXO_AGG_NUMBER], current_block: u64, - ) -> Result, Error> { - let (_, _, _, batch) = self.gen_batch(tree, &utxos, current_block)?; - // TODO: use pre-generated VK as this can be expensive - let (_, utxo_vk) = Utxo::::default().keygen(ParameterSet::Fourteen); - - Ok(AggregateUtxo::new( - utxos.map(|u| { - let SnarkWitness::V1(proof) = u.proof; - proof.to_snark(&utxo_vk, ParameterSet::Fourteen) - }), - batch, - )) + ) -> Result { + if utxos.iter().all(|utxo| utxo.proof.is_padding()) { + return Ok(AggUtxoProof::default()); + } + + let (_, old_tree, new_tree, merkle_paths) = + self.gen_merkle_paths(tree, &utxos, current_block)?; + + // Chunk the merkle paths into 3 x 4 + let merkle_paths = merkle_paths.chunks(4).collect::>(); + + let mut utxo_proof_bundles = Vec::new(); + + for (i, chunk) in merkle_paths.into_iter().enumerate() { + let utxo = &utxos[i]; + + let utxo_proof_bundle = match utxo.proof.is_padding() { + false => UtxoProofBundleWithMerkleProofs::new( + utxo.proof.clone(), + &[ + chunk[0].clone(), + chunk[1].clone(), + chunk[2].clone(), + chunk[3].clone(), + ], + ), + true => UtxoProofBundleWithMerkleProofs::default(), + }; + + utxo_proof_bundles.push(utxo_proof_bundle); + } + + let utxo_proof_bundles: [UtxoProofBundleWithMerkleProofs; UTXO_AGG_NUMBER] = + utxo_proof_bundles + .try_into() + .map_err(|v: Vec<_>| Error::VecToArrayConversion { + expected: UTXO_AGG_NUMBER, + actual: v.len(), + })?; + + let agg_utxo = AggUtxo::new(utxo_proof_bundles, old_tree, new_tree); + + let agg_utxo_proof = agg_utxo + .prove(&*self.bb_backend) + .await + .map_err(|e| Error::BarretenbergProve(e.to_string()))?; + + Ok(agg_utxo_proof) } #[tracing::instrument(err, skip_all)] - fn gen_batch( + fn gen_merkle_paths( &self, tree: &mut MerkleTree, txns: &[Transaction; UTXO_AGG_NUMBER], @@ -343,99 +358,68 @@ impl Prover { usize, Element, Element, - Batch, + [MerklePath; UTXO_AGG_LEAVES], )> { - let (inserts, old_tree, new_tree) = { + let padding_path = MerklePath::default(); + + let (merkle_paths, old_tree, new_tree) = { let old_tree = tree.root_hash(); - let padding_path = tree.path_for(Note::padding_note().commitment()); - let mut leaves = vec![]; + let mut merkle_paths = vec![]; // Extract leaves to be inserted from proof for Transaction { proof } in txns { - let instances = match &proof { - SnarkWitness::V1(proof) => &proof.instances[0], - }; - - let elements = instances - .iter() - .skip(3) - .map(|f| Element::from_base(f.to_base())) - .collect::>(); - - // Skip the first instance, as that is the root - leaves.extend(elements); - } - - let mut inserts = vec![]; - for leaf in leaves { - let path = if leaf == Element::ZERO { - padding_path.clone() - } else { + for leaf in proof.public_inputs.input_commitments { + if leaf.is_zero() { + merkle_paths.push(padding_path.clone()); + continue; + } + + merkle_paths.push(path_to_merkle_path(tree.path_for(leaf))); + tree.remove(leaf)?; + } + + for leaf in proof.public_inputs.output_commitments { + if leaf.is_zero() { + merkle_paths.push(padding_path.clone()); + continue; + } + + // Insert the leaf into the tree tree.insert( leaf, SmirkMetadata { inserted_in: current_block, }, )?; - tree.path_for(leaf) - }; - - let fpath = path - .siblings_deepest_first() - .iter() - .cloned() - .take(MERKLE_TREE_PATH_DEPTH) - .collect::>(); - - let mp = MerklePath::new(fpath); - inserts.push(Insert::new(leaf, mp)); + // Then add the path to the merkle paths + merkle_paths.push(path_to_merkle_path(tree.path_for(leaf))); + } } let new_tree = tree.root_hash(); - (inserts, old_tree, new_tree) + (merkle_paths, old_tree, new_tree) }; - let inserts_len: usize = inserts.len(); - - #[allow(clippy::unwrap_used)] - let fixed_size_inserts: [Insert; UTXO_AGG_LEAVES] = - inserts.try_into().unwrap(); - - Ok(( - inserts_len, - old_tree, - new_tree, - Batch::new(fixed_size_inserts), - )) - } - - pub fn get_proof(&self, notes_tree: &MerkleTree, note_cm: Base) -> Result, Error> { - let el = Element::from_base(note_cm); - - // Sibling path - let path = notes_tree.path_for(el); - - let path = path - .siblings_deepest_first() - .iter() - .copied() - .map(Element::to_base) - .collect(); - - Ok(path) + let inserts_len: usize = merkle_paths.len(); + let merkle_paths: [MerklePath; UTXO_AGG_LEAVES] = merkle_paths + .try_into() + .map_err(|v: Vec<_>| Error::VecToArrayConversion { + expected: UTXO_AGG_LEAVES, + actual: v.len(), + })?; + Ok((inserts_len, old_tree, new_tree, merkle_paths)) } - // TODO: We don't use this yet, when we do, make the ban tree persistent - // /// Bans a given address, adding them to the banned list - // pub async fn ban_address(&self, address: Base) -> Result, Error> { - // let mut ban_tree = self.ban_tree.lock(); - // let el = Element::from_base(address); + // pub fn get_merkle_path_for_commitment( + // &self, + // notes_tree: &MerkleTree, + // commitment: Base, + // ) -> Result, Error> { + // let el = Element::from_base(commitment); - // // Insert address into banned tree - // ban_tree.insert(el, ())?; - - // let path = ban_tree.path_for(el); + // // Sibling path + // let path = notes_tree.path_for(el); // let path = path // .siblings_deepest_first() @@ -446,27 +430,17 @@ impl Prover { // Ok(path) // } +} - /// Checks if the address is in the banned list - pub async fn compliance_check( - &self, - ban_tree: &MerkleTree, - address: Base, - ) -> Result<(bool, Vec), Error> { - let el = Element::from_base(address); - - let is_banned = ban_tree.contains_element(&el); - let path = ban_tree.path_for(el); - - let path = path - .siblings_deepest_first() - .iter() - .copied() - .map(Element::to_base) - .collect(); - - Ok((is_banned, path)) - } +fn path_to_merkle_path(path: Path) -> MerklePath { + let elements = path + .siblings_deepest_first() + .iter() + .cloned() + .take(MERKLE_TREE_PATH_DEPTH) + .collect::>(); + + MerklePath::new(elements) } // #[cfg(test)] diff --git a/pkg/prover/src/smirk_metadata.rs b/pkg/prover/src/smirk_metadata.rs index 5e5d30e..5319d0f 100644 --- a/pkg/prover/src/smirk_metadata.rs +++ b/pkg/prover/src/smirk_metadata.rs @@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; /// The block number of the block that a particular [`Element`] was inserted into a [`Tree`] /// -/// [`Element`]: smirk::Element +/// [`Element`]: element::Element /// [`Tree`]: smirk::Tree #[derive(Debug, Clone, PartialEq, BorshSerialize, BorshDeserialize)] #[non_exhaustive] diff --git a/pkg/ramps-interface/Cargo.toml b/pkg/ramps-interface/Cargo.toml new file mode 100644 index 0000000..dc5acea --- /dev/null +++ b/pkg/ramps-interface/Cargo.toml @@ -0,0 +1,53 @@ +[package] +name = "ramps-interface" +version = "0.1.0" +edition = "2024" + +[features] +diesel = [ + "dep:diesel", + "dep:diesel-util", + "diesel-util/diesel", + "dep:database", + "database/diesel", + "element/diesel", + "network/diesel", + "kyc/diesel", + "currency/diesel", +] +ts-rs = [ + "dep:ts-rs", + "currency/ts-rs", + "element/ts-rs", + "kyc/ts-rs", + "network/ts-rs", +] + +[dependencies] +async-trait = { workspace = true } +currency = { workspace = true } +database = { workspace = true, optional = true } +element = { workspace = true } +ethereum-types = { workspace = true } +kyc = { workspace = true } +network = { workspace = true } +primitives = { workspace = true } +rpc = { workspace = true } +test-spy = { workspace = true } +chrono = { workspace = true } +contextful = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +uuid = { workspace = true } +rand = { workspace = true } +strum = { workspace = true } +strum_macros = { workspace = true } +veil = { workspace = true } +zk-primitives = { workspace = true } + +# Optional dependencies for feature flags +diesel = { workspace = true, optional = true } +diesel-util = { workspace = true, optional = true } +ts-rs = { workspace = true, optional = true } +workspace-hack.workspace = true diff --git a/pkg/ramps-interface/src/account.rs b/pkg/ramps-interface/src/account.rs new file mode 100644 index 0000000..93c9d96 --- /dev/null +++ b/pkg/ramps-interface/src/account.rs @@ -0,0 +1,254 @@ +// lint-long-file-override allow-max-lines=400 +use async_trait::async_trait; +use chrono::{DateTime, Utc}; +use currency::Country; +#[cfg(feature = "diesel")] +use database::schema::ramps_accounts; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +use kyc::{Kyc, KycStatus, KycUpdateRequired}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use test_spy::spy_mock; +use uuid::Uuid; + +use crate::error::Result; +use crate::provider::Provider; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Selectable, Identifiable, Insertable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_accounts))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Account { + pub id: Uuid, + pub provider: Provider, + pub wallet_id: Uuid, + pub kyc_status: KycStatus, + pub kyc_update_required_fields: Option, + pub kyc_external_id: Option, + pub kyc_delegated_id: Option, + pub kyc_non_delegated_status: Option, + pub country: Option, + pub external_id: Option, + pub withdraw_evm_address: Option, + pub deposit_evm_address: Option, + pub metadata: Option, + pub updated_at: DateTime, + pub added_at: DateTime, +} + +impl Default for Account { + fn default() -> Self { + let now = Utc::now(); + Self { + id: Uuid::nil(), + provider: Provider::Alfred, + wallet_id: Uuid::nil(), + kyc_status: KycStatus::NotStarted, + kyc_update_required_fields: None, + kyc_external_id: None, + kyc_delegated_id: None, + kyc_non_delegated_status: None, + country: None, + external_id: None, + withdraw_evm_address: None, + deposit_evm_address: None, + metadata: None, + updated_at: now, + added_at: now, + } + } +} + +impl Account { + #[must_use] + pub fn email(&self) -> String { + format!("{}@payy.link", self.id) + } + + #[must_use] + pub fn from_request( + wallet_id: Uuid, + kyc_delegated_id: Option, + request: AccountCreateRequest, + ) -> Self { + let date = chrono::Utc::now(); + Self { + id: Uuid::new_v4(), + wallet_id, + country: request.country, + kyc_status: KycStatus::NotStarted, + kyc_update_required_fields: None, + kyc_external_id: None, + kyc_delegated_id, + kyc_non_delegated_status: None, + provider: request.provider, + withdraw_evm_address: None, + deposit_evm_address: request.evm_address, + external_id: None, + metadata: None, + updated_at: date, + added_at: date, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "diesel", derive(Queryable, AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_accounts))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct AccountUpdate { + pub external_id: Option, + pub kyc_status: Option, + pub kyc_update_required_fields: Option, + pub kyc_external_id: Option, + pub deposit_evm_address: Option, + pub withdraw_evm_address: Option, + pub metadata: Option, + pub kyc_non_delegated_status: Option, +} + +impl AccountUpdate { + #[must_use] + pub fn without_metadata(&self) -> Self { + Self { + metadata: None, + ..self.clone() + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AccountCreateRequest { + pub provider: Provider, + pub country: Option, + pub kyc: Option, + pub evm_address: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct AccountUpdateRequest { + pub kyc: Option, + pub evm_address: Option, +} + +#[derive(Debug, Clone, Default)] +pub struct AccountKyc { + pub kyc_status: KycStatus, + pub kyc_update_required: Option, +} + +impl AccountKyc { + #[must_use] + pub fn approved() -> Self { + Self { + kyc_status: KycStatus::Approved, + kyc_update_required: None, + } + } + + #[must_use] + pub fn rejected() -> Self { + Self { + kyc_status: KycStatus::Rejected, + kyc_update_required: None, + } + } + + #[must_use] + pub fn rejected_with_reason(reason: Option) -> Self { + Self { + kyc_status: KycStatus::Rejected, + kyc_update_required: reason, + } + } + + #[must_use] + pub fn rejected_country() -> Self { + Self { + kyc_status: KycStatus::Rejected, + kyc_update_required: Some(KycUpdateRequired::UnsupportedCountry), + } + } +} + +#[derive(Deserialize, Debug, Clone)] +pub struct ListAccountsQuery { + pub provider: Option, + pub country: Option, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct ShippingAddress { + pub firstname: String, + pub lastname: String, + pub addressstreet: String, + pub addresscity: String, + pub addresspostalcode: String, + pub addresscountry: String, +} + +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct CreatePhysicalCardRequest { + pub shipping_address: serde_json::Value, +} + +/// Interface for ramps account operations. +#[spy_mock] +#[async_trait] +pub trait AccountsInterface: Send + Sync { + /// Create or update an account for the authenticated wallet. + async fn create_account( + &self, + wallet_id: Uuid, + ip_address: String, + request: AccountCreateRequest, + ) -> Result; + + /// List all accounts associated with the wallet. + async fn list_accounts( + &self, + wallet_id: Uuid, + query: ListAccountsQuery, + ) -> Result>; + + /// Retrieve the Rain services card for the wallet. + async fn get_account_services_card(&self, wallet_id: Uuid) -> Result; + + /// Retrieve or create an account by provider for the wallet. + async fn get_account_by_provider(&self, wallet_id: Uuid, provider: Provider) + -> Result; + + /// Fetch account details by identifier, ensuring wallet ownership. + async fn get_account_by_id(&self, wallet_id: Uuid, account_id: Uuid) -> Result; + + /// Update account by identifier. + async fn update_account_by_id( + &self, + wallet_id: Uuid, + account_id: Uuid, + ip_address: String, + request: AccountUpdateRequest, + ) -> Result; + + /// Update account using provider/country lookup. + async fn update_account_by_provider_and_country( + &self, + wallet_id: Uuid, + provider: Provider, + country: Option, + ip_address: String, + request: AccountUpdateRequest, + ) -> Result; + + /// Create a physical card for the wallet. + async fn create_physical_card( + &self, + wallet_id: Uuid, + request: CreatePhysicalCardRequest, + ) -> Result; +} diff --git a/pkg/ramps-interface/src/admin.rs b/pkg/ramps-interface/src/admin.rs new file mode 100644 index 0000000..d8a40ad --- /dev/null +++ b/pkg/ramps-interface/src/admin.rs @@ -0,0 +1,134 @@ +use async_trait::async_trait; +use kyc::KycUpdateRequired; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use test_spy::spy_mock; +use uuid::Uuid; + +use crate::account::Account; +use crate::error::Result; +use crate::provider::Provider; +use crate::transaction::{RampTransaction, Transaction}; + +/// Authorization metadata extracted from admin HTTP requests. +#[derive(Debug, Clone, Default)] +pub struct AdminAuthContext { + /// Raw `Authorization` header value, if supplied by the client. + pub authorization: Option, +} + +/// Request payload for fulfilling unfunded transactions. +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct FulfillUnfundedRequest { + pub address: String, + pub provider: Option, +} + +/// Response payload summarising the outcome of an unfunded fulfilment run. +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct FulfillUnfundedResult { + pub total_amount: u64, + pub failed: Vec, + pub total_transactions: u32, +} + +/// Response payload containing data from an individual fulfilment. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct FulfillTransactionResult { + pub transaction: RampTransaction, + pub fulfilled_amount: u64, +} + +impl Default for FulfillTransactionResult { + fn default() -> Self { + Self { + transaction: RampTransaction::from(Transaction::default()), + fulfilled_amount: 0, + } + } +} + +/// Request payload for rejecting an account with an optional reason. +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RejectAccountRequest { + pub rejection_reason: Option, +} + +/// Request payload for updating required KYC fields on an account. +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct UpdateRequiredRequest { + pub update_required: KycUpdateRequired, +} + +/// Request payload for updating account metadata. +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct UpdateMetadataRequest { + pub metadata: Value, +} + +/// Response payload for admin-triggered settlement. +#[derive(Debug, Clone, Deserialize, Serialize, Default)] +pub struct SettleTransactionResult { + pub success: bool, + pub message: String, + pub transaction_id: Uuid, + pub wallet_id: Uuid, +} + +/// Interface describing admin-centric ramps operations. +#[spy_mock] +#[async_trait] +pub trait AdminInterface: Send + Sync { + /// Fulfil any unfunded transactions for a wallet address. + async fn fulfill_unfunded( + &self, + auth: AdminAuthContext, + request: FulfillUnfundedRequest, + ) -> Result; + + /// Fulfil a specific transaction by identifier. + async fn fulfill_transaction( + &self, + auth: AdminAuthContext, + transaction_id: Uuid, + ) -> Result; + + /// Approve an account by identifier. + async fn approve_account( + &self, + auth: AdminAuthContext, + account_id: Uuid, + ip_address: String, + ) -> Result; + + /// Reject an account by identifier with an optional reason. + async fn reject_account( + &self, + auth: AdminAuthContext, + account_id: Uuid, + rejection_reason: Option, + ) -> Result; + + /// Update required fields on an account. + async fn update_required( + &self, + auth: AdminAuthContext, + account_id: Uuid, + update_required: KycUpdateRequired, + ) -> Result; + + /// Update account metadata by identifier. + async fn update_account_metadata( + &self, + auth: AdminAuthContext, + account_id: Uuid, + metadata: Value, + ) -> Result; + + /// Trigger settlement for a transaction. + async fn settle_transaction( + &self, + auth: AdminAuthContext, + transaction_id: Uuid, + ) -> Result; +} diff --git a/pkg/ramps-interface/src/document.rs b/pkg/ramps-interface/src/document.rs new file mode 100644 index 0000000..6d3e5ef --- /dev/null +++ b/pkg/ramps-interface/src/document.rs @@ -0,0 +1,32 @@ +use async_trait::async_trait; +use primitives::serde::Base64Bytes; +use serde::{Deserialize, Serialize}; +use test_spy::spy_mock; +use uuid::Uuid; + +use crate::error::Result; + +/// Request payload for uploading an encrypted document. +#[derive(Debug, Clone, Deserialize)] +pub struct CreateDocumentRequest { + pub data: Base64Bytes, + pub key: String, +} + +/// Response payload exposing the document hash identifier. +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct CreateDocumentResponse { + pub hash: String, +} + +/// Interface for document management endpoints. +#[spy_mock] +#[async_trait] +pub trait DocumentsInterface: Send + Sync { + /// Persist a new encrypted document and return its canonical hash. + async fn create_document( + &self, + wallet_id: Uuid, + request: CreateDocumentRequest, + ) -> Result; +} diff --git a/pkg/ramps-interface/src/error.rs b/pkg/ramps-interface/src/error.rs new file mode 100644 index 0000000..e9925fd --- /dev/null +++ b/pkg/ramps-interface/src/error.rs @@ -0,0 +1,274 @@ +// lint-long-file-override allow-max-lines=300 +use std::fmt; + +use contextful::{FromContextful, InternalError}; +use element::Element; +use kyc::{KycStatus, KycUpdateRequired}; +use rpc::{ + HTTPErrorConversion, + code::ErrorCode, + error::{ErrorOutput, HTTPError, TryFromHTTPError}, +}; +use serde::{Deserialize, Serialize}; +use thiserror::Error; + +use crate::transaction::FundingStatus; + +/// Convenience result alias for ramps operations. +pub type Result = std::result::Result; + +/// Identifiers describing how an account lookup was performed. +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[allow(clippy::enum_variant_names)] +pub enum AccountKind { + AccountId, + WalletId, + CardId, + ExternalId, + KycExternalId, +} + +#[derive(Debug, Error, HTTPErrorConversion, FromContextful)] +pub enum Error { + #[error("[ramps-interface] unable to get provider client")] + UnableToGetProviderClient, + + #[error("[ramps-interface] failed to settle transaction")] + FailedToSettledTxn, + + #[error("[ramps-interface] wallet registration failed")] + WalletRegistrationFailed, + + #[error("[ramps-interface] card is frozen")] + #[permission_denied("card-is-frozen")] + CardFrozen, + + #[error("[ramps-interface] fraud block")] + #[permission_denied("fraud-block")] + FraudBlock, + + #[error("[ramps-interface] payy owner insufficient funds")] + PayyOwnerInsufficientFunds, + + #[error("[ramps-interface] invalid encryption key")] + #[bad_request("missing-encryption-key")] + InvalidEncryptionKey, + + #[error("[ramps-interface] invalid decimal string")] + #[bad_request("invalid-decimal")] + InvalidDecimalString, + + #[error("[ramps-interface] invalid phone format")] + InvalidPhoneFormat, + + #[error("[ramps-interface] invalid amount")] + #[bad_request("invalid-amount")] + InvalidAmount { + min: Option, + max: Option, + }, + + #[error("[ramps-interface] invalid provider")] + #[bad_request("invalid-provider")] + InvalidProvider, + + #[error("[ramps-interface] funding status is invalid: {0:?}")] + InvalidFundingStatus(Option), + + #[error("[ramps-interface] external record not found")] + ExternalRecordNotFound, + + #[error("[ramps-interface] exceeded provider limit")] + #[bad_request("exceeded-provider-limit")] + ExceededProviderLimit, + + #[error("[ramps-interface] kyc required")] + #[failed_precondition("kyc-required")] + KycRequired(KycStatus), + + #[error("[ramps-interface] kyc update required")] + KycUpdateRequired(KycUpdateRequired), + + #[error("[ramps-interface] missing required kyc docs")] + MissingRequiredKyCDocs, + + #[error("[ramps-interface] missing kyc data")] + #[bad_request("missing-kyc")] + MissingKyc, + + #[error("[ramps-interface] missing kyc required field")] + #[bad_request("missing-kyc-field")] + MissingKycField(String), + + #[error("[ramps-interface] invalid document id format")] + #[bad_request("invalid-document-id")] + InvalidDocumentId, + + #[error("[ramps-interface] document not found")] + #[not_found("document-not-found")] + DocumentNotFound, + + #[error("[ramps-interface] unsupported currency")] + #[bad_request("unsupported-currency")] + UnsupportedCurrency, + + #[error("[ramps-interface] unsupported network")] + UnsupportedNetwork, + + #[error("[ramps-interface] unsupported currency for provider")] + UnsupportedProviderCurrency, + + #[error("[ramps-interface] unsupported country for provider")] + #[bad_request("unsupported-provider-country")] + UnsupportedProviderCountry, + + #[error("[ramps-interface] unsupported network for provider")] + #[bad_request("unsupported-provider-network")] + UnsupportedProviderNetwork, + + #[error("[ramps-interface] missing country")] + #[bad_request("missing-country")] + MissingCountry, + + #[error("[ramps-interface] method not found")] + #[not_found("method-not-found")] + MethodNotFound, + + #[error("[ramps-interface] quote missing both to/from amount")] + QuoteMissingBothAmounts, + + #[error("[ramps-interface] invalid quote")] + #[bad_request("invalid-quote")] + InvalidQuote, + + #[error("[ramps-interface] missing quote")] + MissingQuote, + + #[error("[ramps-interface] quote not found")] + #[not_found("quote-not-found")] + QuoteNotFound, + + #[error("[ramps-interface] quote provider mismatch")] + #[bad_request("quote-provider-mismatch")] + QuoteProviderMismatch, + + #[error("[ramps-interface] payy network is required in either to or from")] + #[bad_request("payy-network-required")] + PayyNetworkRequired, + + #[error("[ramps-interface] account not found")] + #[not_found("account-not-found")] + AccountNotFound { kind: AccountKind, id: String }, + + #[error("[ramps-interface] account already exists")] + #[already_exists("account-already-exists")] + AccountAlreadyExists, + + #[error("[ramps-interface] method required")] + #[bad_request("method-required")] + MethodRequired, + + #[error("[ramps-interface] missing evm address")] + #[failed_precondition("evm-address-required")] + MissingEvmAddress, + + #[error("[ramps-interface] missing external id")] + #[internal("missing-external-id")] + MissingExternalId, + + #[error("[ramps-interface] invalid method details")] + #[bad_request("invalid-method-details")] + InvalidMethodDetails, + + #[error("[ramps-interface] account creation requires kyc")] + AccountCreationRequiresKyc, + + #[error("[ramps-interface] account provider mismatch")] + #[bad_request("account-provider-mismatch")] + AccountProviderMismatch, + + #[error("[ramps-interface] account address mismatch")] + #[bad_request("account-address-mismatch")] + AccountAddressMismatch, + + #[error("[ramps-interface] missing required network identifier field")] + #[bad_request("missing-required-network-identifier-field")] + MissingRequiredNetworkIdentifierField(String), + + #[error("[ramps-interface] insufficient funds")] + #[failed_precondition("insufficient-funds")] + InsufficientFunds, + + #[error("[ramps-interface] transaction can only be cancelled")] + #[bad_request("transaction-can-only-be-cancelled")] + TransactionCanOnlyBeCancelled, + + #[error("[ramps-interface] transaction not found")] + #[not_found("transaction-not-found")] + TransactionNotFound, + + #[error("[ramps-interface] transaction is in progress and cannot be cancelled")] + #[failed_precondition("transaction-in-progress-cannot-be-cancelled")] + TransactionCannotBeCancelled, + + #[error("[ramps-interface] transaction evm address cannot be updated")] + #[failed_precondition("transaction-evm-address-cannot-be-updated")] + TransactionEvmAddressCannotBeUpdated, + + #[error("[ramps-interface] transaction local id cannot be updated")] + #[failed_precondition("transaction-local-id-cannot-be-updated")] + TransactionLocalIdCannotBeUpdated, + + #[error("[ramps-interface] invalid currency code")] + InvalidCurrencyCode, + + #[error("[ramps-interface] declined transaction with spent notes")] + DeclinedTransactionWithSpentNotes, + + #[error( + "[ramps-interface] MCC 6012 transactions are blocked unless they are $0 Visa Provisioning Service transactions" + )] + #[bad_request("declined-mcc-6012-transaction")] + DeclinedMcc6012Transaction, + + #[error("[ramps-interface] transaction blocked due to restricted MCC: {0}")] + #[bad_request("declined-mcc-transaction")] + DeclinedMccTransaction(u16), + + #[error("[ramps-interface] daily spending limit exceeded")] + #[bad_request("daily-spending-limit-exceeded")] + DailySpendingLimitExceeded, + + #[error("[ramps-interface] PAYY transactions are blocked to prevent circular usage")] + #[bad_request("declined-payy-transaction")] + DeclinedPayyTransaction, + + #[error("[ramps-interface] invalid auth")] + #[unauthenticated("unauthorized-to-perform-action")] + InvalidAuth, + + #[error("[ramps-interface] invalid admin key")] + #[unauthenticated("invalid-admin-key")] + InvalidAdminKey, + + #[error("[ramps-interface] permission denied: admin token lacks required scope")] + #[permission_denied("permission-denied")] + AdminTokenLacksRequiredScope, + + /// Internal error. + #[error("[ramps-interface] internal error")] + Internal(#[from] InternalError), +} + +impl fmt::Display for AccountKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let name = match self { + AccountKind::AccountId => "account_id", + AccountKind::WalletId => "wallet_id", + AccountKind::CardId => "card_id", + AccountKind::ExternalId => "external_id", + AccountKind::KycExternalId => "kyc_external_id", + }; + f.write_str(name) + } +} diff --git a/pkg/ramps-interface/src/event.rs b/pkg/ramps-interface/src/event.rs new file mode 100644 index 0000000..9999c98 --- /dev/null +++ b/pkg/ramps-interface/src/event.rs @@ -0,0 +1,82 @@ +use chrono::DateTime; +use chrono::Utc; +#[cfg(feature = "diesel")] +use database::schema::ramps_events; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + pg::Pg, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Text, +}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +#[cfg(feature = "diesel")] +use std::io::Write; +use strum_macros::{Display, EnumString}; +use uuid::Uuid; + +use crate::provider::Provider; + +#[derive( + Debug, + Serialize, + Deserialize, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +pub enum EventSource { + Webhook, + Request, + Response, +} + +#[cfg(feature = "diesel")] +impl ToSql for EventSource { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for EventSource { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse() + .map_err(|_| "Unrecognized event source kind".into()) + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Insertable, Selectable, Identifiable) +)] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_events))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Event { + pub id: Uuid, + pub provider: Provider, + pub data: Value, + pub source: EventSource, + pub account_id: Option, + pub transaction_id: Option, + pub path: Option, + pub added_at: DateTime, + pub success: Option, +} diff --git a/pkg/ramps-interface/src/lib.rs b/pkg/ramps-interface/src/lib.rs new file mode 100644 index 0000000..72825a8 --- /dev/null +++ b/pkg/ramps-interface/src/lib.rs @@ -0,0 +1,66 @@ +#![warn(clippy::pedantic)] +#![allow(missing_docs)] + +//! Core interface definitions, shared data structures, and error types for +//! ramps operations. This crate owns the canonical API contract between the +//! HTTP layer (`ramps-rpc`) and business logic implementations. + +pub mod account; +pub mod admin; +pub mod document; +pub mod error; +pub mod event; +pub mod method; +pub mod provider; +pub mod quote; +pub mod transaction; +pub mod util; +pub mod webhooks; + +#[cfg(test)] +mod tests; + +pub use account::*; +pub use admin::*; +pub use document::*; +pub use error::{Error, Result}; +pub use event::*; +pub use method::*; +pub use provider::*; +pub use quote::*; +pub use transaction::*; +pub use util::*; +pub use webhooks::*; + +use async_trait::async_trait; +use std::sync::Arc; +use test_spy::spy_mock; + +#[cfg(feature = "diesel")] +pub(crate) use diesel_util::derive_pg_text_enum; + +/// Root interface that exposes accessors to all ramps sub interfaces. +#[spy_mock] +#[async_trait] +pub trait RampsInterface: Send + Sync { + /// Accounts domain API. + fn accounts(&self) -> Arc; + + /// Methods domain API. + fn methods(&self) -> Arc; + + /// Transactions domain API. + fn transactions(&self) -> Arc; + + /// Quotes domain API. + fn quotes(&self) -> Arc; + + /// Admin domain API. + fn admin(&self) -> Arc; + + /// Webhooks domain API. + fn webhooks(&self) -> Arc; + + /// Documents domain API. + fn documents(&self) -> Arc; +} diff --git a/pkg/ramps-interface/src/method.rs b/pkg/ramps-interface/src/method.rs new file mode 100644 index 0000000..3b8e0a6 --- /dev/null +++ b/pkg/ramps-interface/src/method.rs @@ -0,0 +1,148 @@ +// lint-long-file-override allow-max-lines=300 +#[cfg(feature = "diesel")] +use database::schema::ramps_methods; + +#[cfg(feature = "diesel")] +use diesel::prelude::*; + +use async_trait::async_trait; +use network::{Network, NetworkIdentifier}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use test_spy::spy_mock; +use uuid::Uuid; +use veil::Redact; + +use crate::error::Result; +use crate::provider::Provider; + +#[derive(Deserialize, Debug, Clone)] +pub struct ListMethodsQuery { + pub provider: Option, + pub network: Option, + pub account_id: Option, + pub include_deleted: Option, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct MethodCreateRequest { + pub network: Network, + pub network_identifier: Option, + pub account_id: Uuid, + pub local_id: String, + pub set_as_default: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Selectable, Identifiable, Insertable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_methods))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Method { + pub id: Uuid, + pub account_id: Uuid, + pub external_id: Option, + pub local_id: String, + pub network: Network, + pub network_identifier: NetworkIdentifier, + pub preview: Option, + pub metadata: Option, + pub is_default: bool, + pub added_at: chrono::NaiveDateTime, + pub frozen: bool, + pub deleted_at: Option, +} + +impl Default for Method { + fn default() -> Self { + Self { + id: Uuid::nil(), + account_id: Uuid::nil(), + external_id: None, + local_id: "method-default".to_string(), + network: Network::Payy, + network_identifier: NetworkIdentifier::default(), + preview: None, + metadata: None, + is_default: false, + added_at: chrono::Utc::now().naive_utc(), + frozen: false, + deleted_at: None, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "diesel", derive(Queryable, AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_methods))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct MethodUpdate { + pub local_id: Option, + pub network: Option, + pub network_identifier: Option, + pub preview: Option, + pub is_default: Option, + pub metadata: Option, +} + +impl MethodUpdate { + #[must_use] + pub fn without_metadata(mut self) -> Self { + self.metadata = None; + self + } +} + +#[derive(Clone, Deserialize, Redact)] +pub struct SetPinRequest { + #[redact] + pub pin: String, +} + +#[derive(Serialize, Deserialize, Redact, Default)] +pub struct MethodPinResponse { + #[redact] + pub pin: String, +} + +#[derive(Clone, Serialize, Deserialize, Redact, Default)] +pub struct MethodProviderSecretsResponse { + #[redact] + pub network_identifier: NetworkIdentifier, +} + +#[spy_mock] +#[async_trait] +pub trait MethodsInterface: Send + Sync { + async fn create_method(&self, wallet_id: Uuid, request: MethodCreateRequest) -> Result; + + async fn refresh_method(&self, method_id: Uuid) -> Result; + + async fn list_methods(&self, wallet_id: Uuid, query: ListMethodsQuery) -> Result>; + + async fn get_method(&self, wallet_id: Uuid, method_id: Uuid) -> Result; + + async fn delete_method(&self, wallet_id: Uuid, method_id: Uuid) -> Result<()>; + + async fn get_method_secrets( + &self, + wallet_id: Uuid, + method_id: Uuid, + ) -> Result; + + async fn get_method_pin(&self, wallet_id: Uuid, method_id: Uuid) -> Result; + + async fn set_method_pin( + &self, + wallet_id: Uuid, + method_id: Uuid, + request: SetPinRequest, + ) -> Result; + + async fn freeze_method(&self, wallet_id: Uuid, method_id: Uuid) -> Result; + + async fn unfreeze_method(&self, wallet_id: Uuid, method_id: Uuid) -> Result; +} diff --git a/pkg/ramps-interface/src/provider.rs b/pkg/ramps-interface/src/provider.rs new file mode 100644 index 0000000..f8c05e5 --- /dev/null +++ b/pkg/ramps-interface/src/provider.rs @@ -0,0 +1,77 @@ +use currency::Currency; +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + pg::Pg, + serialize::{self, IsNull, Output, ToSql}, + sql_types::Text, +}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "diesel")] +use std::io::Write; +use strum_macros::{Display, EnumString}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +use crate::error::{Error, Result}; + +#[derive( + Debug, + Serialize, + Deserialize, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum Provider { + Alfred, + Manteca, + Rain, + Sumsub, + Cybrid, + Stripe, +} + +impl Provider { + /// Derives a provider for a given currency. + /// + /// # Errors + /// + /// Returns [`Error::UnsupportedProviderCurrency`] when no provider supports the currency. + pub fn from_currency(currency: &Currency) -> Result { + match currency { + Currency::ARS => Ok(Self::Manteca), + Currency::BRL | Currency::MXN => Ok(Self::Alfred), + _ => Err(Error::UnsupportedProviderCurrency), + } + } +} + +#[cfg(feature = "diesel")] +impl ToSql for Provider { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Provider { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized provider".into()) + } +} diff --git a/pkg/ramps-interface/src/quote.rs b/pkg/ramps-interface/src/quote.rs new file mode 100644 index 0000000..afd142f --- /dev/null +++ b/pkg/ramps-interface/src/quote.rs @@ -0,0 +1,229 @@ +// lint-long-file-override allow-max-lines=300 +use async_trait::async_trait; +use chrono::{DateTime, Utc}; +use currency::Currency; +#[cfg(feature = "diesel")] +use database::schema::ramps_quotes; +#[cfg(feature = "diesel")] +use diesel::prelude::*; +use element::Element; +use network::Network; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use test_spy::spy_mock; +use uuid::Uuid; + +use crate::error::{Error, Result}; +use crate::provider::Provider; + +#[derive(Serialize, Deserialize)] +pub struct QuoteRequestAmount { + pub currency: Currency, + pub amount: Option, + pub network: Network, +} + +#[derive(Serialize, Deserialize)] +pub struct QuoteResponseAmount { + pub currency: Currency, + pub amount: Element, + pub network: Network, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum QuoteProviderResponse { + Estimated(QuoteProviderResponseEstimated), + Guaranteed(QuoteProviderResponseGuarenteed), +} + +pub enum QuoteRequestDefinedAmount { + From(Element), + To(Element), +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct QuoteRequest { + pub provider: Option, + pub from_currency: Currency, + pub from_amount: Option, + pub from_network: Network, + pub to_currency: Currency, + pub to_amount: Option, + pub to_network: Network, +} + +impl QuoteRequest { + #[must_use] + pub fn is_onramp(&self) -> bool { + self.to_network == Network::Payy + } + + #[must_use] + pub fn is_offramp(&self) -> bool { + self.from_network == Network::Payy + } + + #[must_use] + pub fn get_alt_currency(&self) -> Currency { + if self.is_onramp() { + self.from_currency + } else { + self.to_currency + } + } + + /// Determines which amount is provided in the request. + /// + /// # Errors + /// + /// Returns [`Error::QuoteMissingBothAmounts`] when neither `from_amount` nor `to_amount` is set. + pub fn get_defined_amount(&self) -> Result { + match (self.from_amount, self.to_amount) { + (Some(from), _) => Ok(QuoteRequestDefinedAmount::From(from)), + (_, Some(to)) => Ok(QuoteRequestDefinedAmount::To(to)), + (None, None) => Err(Error::QuoteMissingBothAmounts), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct QuoteProviderResponseEstimated { + pub provider: Provider, + pub from_amount: Element, + pub to_amount: Element, + pub metadata: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct QuoteProviderResponseGuarenteed { + pub id: String, + pub provider: Provider, + pub from_amount: Element, + pub to_amount: Element, + pub expires_at: DateTime, + pub metadata: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr( + feature = "diesel", + derive(Queryable, Selectable, Identifiable, Insertable, AsChangeset) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_quotes))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Quote { + pub id: Uuid, + pub provider: Provider, + pub account_id: Uuid, + pub external_id: String, + pub from_currency: Currency, + pub from_amount: Element, + pub from_network: Network, + pub to_currency: Currency, + pub to_amount: Element, + pub to_network: Network, + pub metadata: Option, + pub expires_at: DateTime, + pub added_at: DateTime, +} + +#[derive(Debug, Clone, Serialize)] +#[serde(default)] +pub struct QuoteResponse { + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + pub provider: Provider, + pub account_id: Uuid, + pub from_currency: Currency, + pub from_amount: Element, + pub from_network: Network, + pub to_currency: Currency, + pub to_amount: Element, + pub to_network: Network, + #[serde(skip_serializing_if = "Option::is_none")] + pub metadata: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub expires_at: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub added_at: Option>, +} + +impl Default for QuoteResponse { + fn default() -> Self { + Self { + id: None, + provider: Provider::Alfred, + account_id: Uuid::nil(), + from_currency: Currency::USD, + from_amount: Element::default(), + from_network: Network::Payy, + to_currency: Currency::USD, + to_amount: Element::default(), + to_network: Network::Payy, + metadata: None, + expires_at: None, + added_at: None, + } + } +} + +impl QuoteResponse { + #[must_use] + pub fn from_quote_db(quote: Quote) -> Self { + Self { + id: Some(quote.id), + provider: quote.provider, + account_id: quote.account_id, + from_currency: quote.from_currency, + from_amount: quote.from_amount, + from_network: quote.from_network, + to_currency: quote.to_currency, + to_amount: quote.to_amount, + to_network: quote.to_network, + metadata: quote.metadata, + expires_at: Some(quote.expires_at), + added_at: Some(quote.added_at), + } + } + + #[must_use] + pub fn from_estimated_response( + response: QuoteProviderResponseEstimated, + request: &QuoteRequest, + account_id: Uuid, + ) -> Self { + Self { + id: None, + account_id, + provider: response.provider, + from_currency: request.from_currency, + from_amount: response.from_amount, + from_network: request.from_network, + to_currency: request.to_currency, + to_amount: response.to_amount, + to_network: request.to_network, + metadata: response.metadata, + expires_at: None, + added_at: None, + } + } +} + +impl Quote { + #[must_use] + pub fn is_onramp(&self) -> bool { + self.to_network == Network::Payy + } + + #[must_use] + pub fn is_offramp(&self) -> bool { + self.from_network == Network::Payy + } +} + +#[spy_mock] +#[async_trait] +pub trait QuotesInterface: Send + Sync { + async fn create_quote(&self, wallet_id: Uuid, request: QuoteRequest) -> Result; +} diff --git a/pkg/ramps-interface/src/tests.rs b/pkg/ramps-interface/src/tests.rs new file mode 100644 index 0000000..7418338 --- /dev/null +++ b/pkg/ramps-interface/src/tests.rs @@ -0,0 +1,31 @@ +use rpc::{code::ErrorCode, error::HTTPError}; + +use crate::Error; + +#[test] +fn invalid_auth_keeps_legacy_unauthorized_reason() { + let http_error = HTTPError::from(Error::InvalidAuth); + + assert_eq!(http_error.code, ErrorCode::Unauthenticated); + assert_eq!(http_error.reason, "unauthorized-to-perform-action"); +} + +#[test] +fn invalid_admin_key_uses_invalid_admin_key_reason() { + let http_error = HTTPError::from(Error::InvalidAdminKey); + + assert_eq!(http_error.code, ErrorCode::Unauthenticated); + assert_eq!(http_error.reason, "invalid-admin-key"); +} + +#[test] +fn permission_denied_uses_permission_denied_reason() { + let http_error = HTTPError::from(Error::AdminTokenLacksRequiredScope); + + assert_eq!(http_error.code, ErrorCode::PermissionDenied); + assert_eq!(http_error.reason, "permission-denied"); + assert_eq!( + http_error.message(), + "[ramps-interface] permission denied: admin token lacks required scope" + ); +} diff --git a/pkg/ramps-interface/src/transaction/category.rs b/pkg/ramps-interface/src/transaction/category.rs new file mode 100644 index 0000000..eb45fd6 --- /dev/null +++ b/pkg/ramps-interface/src/transaction/category.rs @@ -0,0 +1,350 @@ +// lint-long-file-override allow-max-lines=350 +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql, FromSqlRow}, + expression::AsExpression, + pg::Pg, + serialize::{self, IsNull, Output, ToSql}, +}; +use element::Element; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "diesel")] +use std::io::Write; +use strum::{Display, EnumString}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +#[derive( + Debug, + Serialize, + Deserialize, + Copy, + Clone, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow))] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum Category { + Bills, + Charity, + EatingOut, + Entertainment, + Expenses, + Family, + Finances, + General, + Gifts, + Groceries, + Holidays, + Income, + PersonalCare, + Savings, + Shopping, + Transfer, + Transport, + PetCare, +} + +impl Category { + #[must_use] + pub fn is_safe_6012_mcc_transaction(merchant_name: &str, amount: &Element) -> bool { + amount.is_zero() && merchant_name == "Visa Provisioning Service" + } + + #[must_use] + #[allow(clippy::match_same_arms)] + #[allow(clippy::too_many_lines)] + pub fn from_mcc(mcc: u16) -> Category { + match mcc { + // Pet Care + 742 => Category::PetCare, // Veterinary Services + // Expenses + 763 => Category::Expenses, // Agricultural Co-operatives + 780 => Category::Expenses, // Horticultural Services, Landscaping Services + 1520 => Category::Expenses, // General Contractors-Residential and Commercial + 1711 => Category::Expenses, // Air Conditioning Contractors – Sales and Installation, Heating Contractors – Sales, Service, Installation + 1731 => Category::Expenses, // Electrical Contractors + 1740 => Category::Expenses, // Insulation – Contractors, Masonry, Stonework Contractors, Plastering Contractors, Stonework and Masonry Contractors, Tile Settings Contractors + 1750 => Category::Expenses, // Carpentry Contractors + 1761 => Category::Expenses, // Roofing – Contractors, Sheet Metal Work – Contractors, Siding – Contractors + 1771 => Category::Expenses, // Contractors – Concrete Work + 1799 => Category::Expenses, // Contractors – Special Trade, Not Elsewhere Classified + 2741 => Category::Expenses, // Miscellaneous Publishing and Printing + 2791 => Category::Expenses, // Typesetting, Plate Making, & Related Services + 2842 => Category::Expenses, // Specialty Cleaning, Polishing, and Sanitation Preparations + 4119 => Category::Expenses, // Ambulance Services + 4225 => Category::Expenses, // Public Warehousing + 7332 => Category::Expenses, // Blueprinting and Photocopying + 7692 => Category::Expenses, // Welding Repair + 8111 => Category::Expenses, // Legal Services and Attorneys + 8211 => Category::Expenses, // Elementary and Secondary Schools + 8220 => Category::Expenses, // Colleges, Universities, Professional Schools, and Junior Colleges + 8241 => Category::Expenses, // Correspondence Schools + 8244 => Category::Expenses, // Business and Secretarial Schools + 8249 => Category::Expenses, // Vocational and Trade Schools + 8299 => Category::Expenses, // Schools and Educational Services + 8734 => Category::Expenses, // Testing Laboratories + 8911 => Category::Expenses, // Architectural, Engineering, and Surveying Services + 8999 => Category::Expenses, // Professional Services + 9211 => Category::Expenses, // Court Costs, Including Alimony and Child Support + 9222 => Category::Expenses, // Fines + 9223 => Category::Expenses, // Bail and Bond Payments + 9311 => Category::Expenses, // Tax Payments + 9399 => Category::Expenses, // Government Services + 9402 => Category::Expenses, // Postal Services + 9405 => Category::Expenses, // Intra-Government Purchases + 9700 => Category::Expenses, // Automated Referral Service + 9701 => Category::Expenses, // Visa Credential Service + 9702 => Category::Expenses, // GCAS Emergency Services + 9950 => Category::Expenses, // Intra-Company Purchases + // Transport + 3000..=3299 => Category::Holidays, // Airlines + 3351..=3441 => Category::Transport, // Car Rentals + 3501..=3999 => Category::Transport, // Car Rentals and Railroads + 4011 => Category::Transport, // Railroads + 4111 => Category::Transport, // Local and Suburban Commuter Passenger Transportation + 4112 => Category::Transport, // Passenger Railways + 4121 => Category::Transport, // Taxicabs and Limousines + 4131 => Category::Transport, // Bus Lines + 4214 | 4215 => Category::Transport, // Motor Freight Carriers + 4457 => Category::Transport, // Boat Rentals + 4468 => Category::Transport, // Marinas + 4511 => Category::Transport, // Air Carriers, Airlines + 4582 => Category::Transport, // Airports + 4784 => Category::Transport, // Tolls and Bridge Fees + 4789 => Category::Transport, // Other Transport Services + 5172 => Category::Transport, // Petroleum Products + 5541 => Category::Transport, // Service Stations + 5542 => Category::Transport, // Automated Fuel Dispensers + 7511 => Category::Transport, // Truck Stop + 7512 => Category::Transport, // Automobile Rental Agency + 7513 => Category::Transport, // Truck and Utility Trailer Rentals + 7519 => Category::Transport, // Motor Home and Recreational Vehicle Rentals + 7523 => Category::Transport, // Parking Lots, Garages + 7531 => Category::Transport, // Automotive Body Repair Shops + 7534 => Category::Transport, // Tire Retreading and Repair Shops + 7535 => Category::Transport, // Automotive Paint Shops + 7538 => Category::Transport, // Automotive Service Shops + 7542 => Category::Transport, // Car Washes + 7549 => Category::Transport, // Towing Services + // Bills + 4812 | 4815 | 4816 | 4821 | 4899 => Category::Bills, // Telecommunications + 4814 => Category::Bills, // Telecommunication Services + 4900 => Category::Bills, // Electric, Gas, Sanitary and Water Utilities + // Transfer + 4829 => Category::Transfer, // Money Transfer + 6536 => Category::Transfer, // MoneySend Intracountry + // Savings + 6760 => Category::Savings, // Savings Bonds + // Holidays + 4411 => Category::Holidays, // Cruise Lines + 4722 => Category::Holidays, // Travel Agencies and Tour Operators + 4723 => Category::Holidays, // Package Tour Operators + 7011 => Category::Holidays, // Lodging - Hotels, Motels, Resorts + 7012 => Category::Holidays, // Timeshares + 7032 => Category::Holidays, // Sporting and Recreational Camps + 7033 => Category::Holidays, // Trailer Parks and Campgrounds + // Shopping + 5013 => Category::Shopping, // Motor Vehicle Supplies + 5021 => Category::Shopping, // Office and Commercial Furniture + 5039 => Category::Shopping, // Construction Materials + 5044 => Category::Shopping, // Office Equipment + 5045 => Category::Shopping, // Computers, Peripherals, and Software + 5047 => Category::Shopping, // Medical Equipment + 5051 => Category::Shopping, // Metal Service Centers + 5065 => Category::Shopping, // Electrical Parts + 5072 => Category::Shopping, // Hardware Supplies + 5074 => Category::Shopping, // Plumbing and Heating + 5085 => Category::Shopping, // Industrial Supplies + 5099 => Category::Shopping, // Durable Goods + 5111 => Category::Shopping, // Stationery, Office Supplies, Printing, and Writing Paper + 5131 => Category::Shopping, // Piece Goods and Notions + 5137 => Category::Shopping, // Uniforms and Commercial Clothing + 5139 => Category::Shopping, // Commercial Footwear + 5169 => Category::Shopping, // Chemicals and Allied Products + 5192 => Category::Shopping, // Books and Newspapers + 5198 => Category::Shopping, // Paints and Supplies + 5199 => Category::Shopping, // Non-durable Goods + 5200 => Category::Shopping, // Home Supply Warehouse Stores + 5211 => Category::Shopping, // Building Materials Stores + 5231 => Category::Shopping, // Glass, Paint, and Wallpaper + 5251 => Category::Shopping, // Hardware Stores + 5261 => Category::Shopping, // Lawn and Garden Supply + 5271 => Category::Shopping, // Mobile Home Dealers + 5300 => Category::Shopping, // Wholesale Clubs + 5309 => Category::Shopping, // Duty-Free Store + 5310 => Category::Shopping, // Discount Stores + 5311 => Category::Shopping, // Department Stores + 5331 => Category::Shopping, // Variety Stores + 5399 => Category::Shopping, // Miscellaneous General Merchandise Stores + 5411 => Category::Groceries, // Grocery Stores, Supermarkets + 5422 => Category::Groceries, // Meat Provisioners + 5441 => Category::Groceries, // Candy and Confectionery Stores + 5451 => Category::Groceries, // Dairy Products Stores + 5462 => Category::Groceries, // Bakeries + 5499 => Category::Groceries, // Miscellaneous Food Stores + 5511 | 5521 => Category::Shopping, // Car and Truck Dealers + 5531 => Category::Shopping, // Automobile Supply Stores + 5532 => Category::Shopping, // Automotive Tire Stores + 5533 => Category::Shopping, // Automotive Parts and Accessories Stores + 5551 => Category::Shopping, // Boat Dealers + 5561 => Category::Shopping, // Recreational Dealers + 5571 => Category::Shopping, // Motorcycle Dealers + 5592 => Category::Shopping, // Motor Home Dealers + 5598 => Category::Shopping, // Snowmobile Dealers + 5599 => Category::Shopping, // Miscellaneous Auto Dealers + 5611 => Category::Shopping, // Men's and Boy's Clothing Stores + 5621 => Category::Shopping, // Women's Ready-to-Wear Stores + 5631 => Category::Shopping, // Women's Accessory Shops + 5641 => Category::Family, // Children's and Infants' Wear Stores + 5651 => Category::Shopping, // Family Clothing Stores + 5655 => Category::Shopping, // Sports Apparel Stores + 5661 => Category::Shopping, // Shoe Stores + 5681 => Category::Shopping, // Furriers and Fur Shops + 5691 => Category::Shopping, // Men's and Women's Clothing Stores + 5699 => Category::Shopping, // Miscellaneous Apparel and Accessory Shops + 5712 => Category::Shopping, // Furniture and Home Furnishings + 5713 => Category::Shopping, // Floor Covering Stores + 5714 => Category::Shopping, // Drapery and Upholstery Stores + 5718 => Category::Shopping, // Fireplace and Accessories Stores + 5719 => Category::Shopping, // Miscellaneous Home Furnishing Stores + 5722 => Category::Shopping, // Household Appliance Stores + 5732 => Category::Shopping, // Electronics Stores + 5733 => Category::Shopping, // Music Stores + 5734 => Category::Shopping, // Computer Software Stores + 5735 => Category::Shopping, // Record Stores + 5811 => Category::EatingOut, // Caterers + 5812 => Category::EatingOut, // Eating Places and Restaurants + 5813 => Category::Entertainment, // Drinking Places (Alcoholic Beverages) + 5814 => Category::EatingOut, // Fast Food Restaurants + 5815..=5818 => Category::Entertainment, // Digital Goods + 5832 | 5932 | 5937 => Category::Shopping, // Antique Shops + 5912 => Category::Shopping, // Drug Stores and Pharmacies + 5921 => Category::Groceries, // Package Stores – Beer, Wine, and Liquor + 5931 => Category::Shopping, // Used Merchandise and Secondhand Stores + 5933 => Category::Shopping, // Pawn Shops + 5935 => Category::Shopping, // Wrecking and Salvage Yards + 5940 => Category::Shopping, // Bicycle Shops + 5941 => Category::Shopping, // Sporting Goods Stores + 5942 => Category::Shopping, // Book Stores + 5943 => Category::Shopping, // Stationery Stores + 5945 => Category::Shopping, // Hobby, Toy, and Game Shops + 5946 => Category::Shopping, // Camera and Photographic Supply Stores + 5947 => Category::Gifts, // Gift, Card, Novelty, and Souvenir Shops + 5948 => Category::Shopping, // Leather Goods Stores + 5949 => Category::Shopping, // Sewing and Fabric Stores + 5950 => Category::Shopping, // Glassware/Crystal Stores + 5960 | 5962 => Category::Shopping, // Direct Marketing + 5963 => Category::Shopping, // Door-to-Door Sales + 5970 => Category::Shopping, // Artist's Supply and Craft Shops + 5971 => Category::Shopping, // Art Dealers and Galleries + 5972 => Category::Shopping, // Stamp and Coin Stores + 5973 => Category::Shopping, // Religious Goods Stores + 5977 => Category::Shopping, // Cosmetic Stores + 5978 => Category::Shopping, // Typewriter Stores + 5993 => Category::Shopping, // Cigar Stores + 5994 => Category::Shopping, // News Dealers + 5995 => Category::PetCare, // Pet Shops, Pet Foods, and Supplies Stores + 5996 => Category::Shopping, // Swimming Pools Stores + 5997 => Category::Shopping, // Electric Razor Stores + 5998 => Category::Shopping, // Tent and Awning Shops + 5999 => Category::Shopping, // Miscellaneous and Specialty Retail Stores + // Gifts + 5094 => Category::Gifts, // Precious Stones and Jewelry + 5193 => Category::Gifts, // Florists' Supplies + 5944 => Category::Gifts, // Jewelry and Silverware Stores + 5992 => Category::Gifts, // Florists + + // Finances + 6010 => Category::Finances, // Financial Institutions + 6011 => Category::Finances, // Financial Institutions - Manual Cash Disbursements + 6012 => Category::Finances, // Financial Institutions - Merchandise and Services + 6051 => Category::Finances, // Non-Financial Institutions + 6211 => Category::Finances, // Security Brokers/Dealers + 6300 => Category::Finances, // Insurance Sales, Underwriting, and Premiums + 6381 | 6399 => Category::Finances, // Insurance + 6513 => Category::Finances, // Real Estate Agents + 7276 => Category::Finances, // Tax Preparation Service + 8931 => Category::Finances, // Accounting, Auditing, and Bookkeeping Services + + // Family + 7261 => Category::Family, // Funeral Services + 8351 => Category::Family, // Child Care Services + + // Charity + 8398 => Category::Charity, // Charitable and Social Service Organizations + 8641 => Category::Charity, // Civic, Social, and Fraternal Associations + 8651 => Category::Charity, // Political Organizations + 8661 => Category::Charity, // Religious Organizations + 8675 => Category::Charity, // Automobile Associations + 8699 => Category::Charity, // Membership Organizations + + // Personal Care + 5122 => Category::PersonalCare, // Drugs and Druggist's Sundries + 5697 => Category::PersonalCare, // Tailors and Alterations + 5698 => Category::PersonalCare, // Wig and Toupee Stores + 5975 => Category::PersonalCare, // Hearing Aids Stores + 5976 => Category::PersonalCare, // Orthopedic Goods Stores + 7210 => Category::PersonalCare, // Laundry, Cleaning, and Garment Services + 7211 => Category::PersonalCare, // Laundry Services + 7216 => Category::PersonalCare, // Dry Cleaners + 7217 => Category::PersonalCare, // Carpet and Upholstery Cleaning + 7221 => Category::PersonalCare, // Photographic Studios + 7230 => Category::PersonalCare, // Beauty and Barber Shops + 7251 => Category::PersonalCare, // Shoe Repair and Hat Cleaning + 7273 => Category::PersonalCare, // Dating and Escort Services + 7277 => Category::PersonalCare, // Counseling Service + 7297 => Category::PersonalCare, // Massage Parlors + 7298 => Category::PersonalCare, // Health and Beauty Spas + 7299 => Category::PersonalCare, // Miscellaneous Personal Services + 7333 => Category::Expenses, // Commercial Photography, Art, and Graphics + 7342 => Category::PersonalCare, // Exterminating Services + 7622 => Category::Expenses, // Electronic Repair Shops + 7623 => Category::Expenses, // Air Conditioning and Refrigeration Repair Shops + 7629 => Category::Expenses, // Electrical and Small Appliance Repair Shops + 7631 => Category::Expenses, // Watch, Clock, and Jewelry Repair Shops + 7641 => Category::Expenses, // Furniture, Upholstery Repair, and Reupholstery + 7699 => Category::Expenses, // Miscellaneous Repair Shops + 8011 => Category::PersonalCare, // Doctors and Physicians + 8021 => Category::PersonalCare, // Dentists and Orthodontists + 8031 => Category::PersonalCare, // Osteopathic Physicians + 8041 => Category::PersonalCare, // Chiropractors + 8042 => Category::PersonalCare, // Optometrists + 8043 => Category::PersonalCare, // Opticians, Optical Goods, and Eyeglasses + 8044 => Category::PersonalCare, // Opticians, Optical Goods, and Eyeglasses + 8049 => Category::PersonalCare, // Podiatrists and Chiropodists + 8050 => Category::PersonalCare, // Nursing and Personal Care Facilities + 8062 => Category::PersonalCare, // Hospitals + 8071 => Category::PersonalCare, // Medical and Dental Laboratories + 8099 => Category::PersonalCare, // Health Practitioners, Medical Services, and Health Associations + + // Default + _ => Category::General, + } + } +} + +#[cfg(feature = "diesel")] +impl ToSql for Category { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Category { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized method kind".into()) + } +} diff --git a/pkg/ramps-interface/src/transaction/db.rs b/pkg/ramps-interface/src/transaction/db.rs new file mode 100644 index 0000000..59bbe2e --- /dev/null +++ b/pkg/ramps-interface/src/transaction/db.rs @@ -0,0 +1,226 @@ +// lint-long-file-override allow-max-lines=300 + +use chrono::{DateTime, Utc}; +use currency::Currency; +#[cfg(feature = "diesel")] +use database::schema::ramps_transactions; +use element::Element; +use network::{Network, NetworkIdentifier}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use strum::{Display, EnumString}; +use uuid::Uuid; +use zk_primitives::bridged_polygon_usdc_note_kind; + +#[cfg(feature = "diesel")] +use crate::derive_pg_text_enum; +use crate::provider::Provider; + +use super::{Category, FundingStatus, Status, TransactionStatusReason}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr( + feature = "diesel", + derive( + diesel::Queryable, + diesel::Selectable, + diesel::Identifiable, + diesel::Insertable, + diesel::AsChangeset + ) +)] +#[cfg_attr(feature = "diesel", diesel(primary_key(id)))] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_transactions))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct Transaction { + pub id: Uuid, + pub wallet_id: Uuid, + pub quote_id: Option, + pub account_id: Uuid, + pub provider: Provider, + pub external_id: Option, + pub external_fund_id: Option, + pub status: Status, + pub funding_status: Option, + pub funding_kind: FundingKind, + pub status_reason: Option, + pub from_currency: Currency, + pub from_amount: Element, + pub from_network: Network, + pub from_network_identifier: Option, + pub pending_refund_amount: Option, + pub funding_due_amount: Option, + pub from_note_kind: Option, + pub to_note_kind: Option, + pub to_currency: Currency, + pub to_amount: Element, + pub to_network: Network, + pub to_network_identifier: Option, + pub evm_address: Option, + pub private_key: Option, + pub name: Option, + pub memo: Option, + pub desc: Option, + pub emoji: Option, + pub icon: Option, + pub category: Category, + pub metadata: Option, + pub transaction_at: Option>, + pub updated_at: DateTime, + pub added_at: DateTime, +} + +impl Default for Transaction { + fn default() -> Self { + let now = Utc::now(); + Self { + id: Uuid::nil(), + wallet_id: Uuid::nil(), + quote_id: None, + account_id: Uuid::nil(), + provider: Provider::Alfred, + external_id: None, + external_fund_id: None, + status: Status::Pending, + funding_status: None, + funding_kind: FundingKind::Crypto, + status_reason: None, + from_currency: Currency::USD, + from_amount: Element::default(), + from_network: Network::Payy, + from_network_identifier: None, + pending_refund_amount: None, + funding_due_amount: None, + from_note_kind: None, + to_note_kind: None, + to_currency: Currency::USD, + to_amount: Element::default(), + to_network: Network::Payy, + to_network_identifier: None, + evm_address: None, + private_key: None, + name: None, + memo: None, + desc: None, + emoji: None, + icon: None, + category: Category::Transfer, + metadata: None, + transaction_at: None, + updated_at: now, + added_at: now, + } + } +} + +pub enum TransactionKind { + Deposit, + DepositLink, + Withdraw, + Card, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TransactionAction { + Deposit, + Withdraw, +} + +#[derive( + Debug, Default, EnumString, Display, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, +)] +#[cfg_attr( + feature = "diesel", + derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow) +)] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum FundingKind { + #[default] + Crypto, + Link, + UserRemoteNotes, +} + +#[cfg(feature = "diesel")] +derive_pg_text_enum!(FundingKind, "SCREAMING_SNAKE_CASE"); + +impl Transaction { + #[must_use] + pub fn from_note_kind(&self) -> Element { + self.from_note_kind + .unwrap_or_else(bridged_polygon_usdc_note_kind) + } + + #[must_use] + pub fn to_note_kind(&self) -> Element { + self.to_note_kind + .unwrap_or_else(bridged_polygon_usdc_note_kind) + } + + #[must_use] + pub fn kind(&self) -> TransactionKind { + match (self.from_network, self.to_network) { + (Network::Card, _) | (_, Network::Card) => TransactionKind::Card, + (Network::Payy, _) => TransactionKind::Withdraw, + (_, Network::Payy) => match self.funding_kind { + FundingKind::Crypto => TransactionKind::Deposit, + FundingKind::Link => TransactionKind::DepositLink, + FundingKind::UserRemoteNotes => { + unreachable!("invalid funding kind UserRemoteNotes for deposit") + } + }, + _ => unreachable!("one of to_network, from_network must be Network::Payy"), + } + } + + #[must_use] + pub fn is_onramp(&self) -> bool { + self.to_network == Network::Payy + } + + #[must_use] + pub fn is_offramp(&self) -> bool { + self.from_network == Network::Payy + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "diesel", derive(diesel::Queryable, diesel::AsChangeset))] +#[cfg_attr(feature = "diesel", diesel(table_name = ramps_transactions))] +#[cfg_attr(feature = "diesel", diesel(check_for_backend(diesel::pg::Pg)))] +pub struct TransactionUpdate { + pub name: Option, + pub status: Option, + pub quote_id: Option, + pub external_id: Option, + pub external_fund_id: Option, + pub transaction_at: Option>, + pub metadata: Option, + pub from_amount: Option, + pub from_currency: Option, + pub from_network: Option, + pub to_amount: Option, + pub to_currency: Option, + pub to_network: Option, + pub evm_address: Option, + pub private_key: Option, + pub from_note_kind: Option, + pub to_note_kind: Option, + pub pending_refund_amount: Option, + pub funding_status: Option, + pub funding_due_amount: Option, + pub status_reason: Option, + pub memo: Option, +} + +impl TransactionUpdate { + #[must_use] + pub fn without_metadata(&self) -> Self { + Self { + metadata: None, + ..self.clone() + } + } +} diff --git a/pkg/ramps-interface/src/transaction/kinds/card.rs b/pkg/ramps-interface/src/transaction/kinds/card.rs new file mode 100644 index 0000000..c3b0ed5 --- /dev/null +++ b/pkg/ramps-interface/src/transaction/kinds/card.rs @@ -0,0 +1,37 @@ +use element::Element; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +use crate::transaction::{Category, FundingStatus}; + +use super::{CardStatus, Transaction}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct RampCardTransaction { + pub status: CardStatus, + pub name: String, + pub desc: Option, + pub icon: Option, + pub category: Category, + pub pending_refund_amount: Option, + pub funding_status: Option, + pub funding_due_amount: Option, +} + +impl From for RampCardTransaction { + fn from(txn: Transaction) -> Self { + Self { + status: txn.status.into(), + name: txn.name.unwrap_or_default(), + desc: txn.desc, + icon: txn.icon, + category: txn.category, + pending_refund_amount: txn.pending_refund_amount, + funding_status: txn.funding_status, + funding_due_amount: txn.funding_due_amount, + } + } +} diff --git a/pkg/ramps-interface/src/transaction/kinds/deposit.rs b/pkg/ramps-interface/src/transaction/kinds/deposit.rs new file mode 100644 index 0000000..b4b0629 --- /dev/null +++ b/pkg/ramps-interface/src/transaction/kinds/deposit.rs @@ -0,0 +1,52 @@ +use std::str::FromStr; + +use element::Element; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use zk_primitives::bridged_polygon_usdc_note_kind; + +use super::{RampStatus, Transaction}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct RampDepositTransaction { + pub status: RampStatus, + pub private_key: Element, + #[serde(default = "bridged_polygon_usdc_note_kind")] + pub note_kind: Element, +} + +impl From for RampDepositTransaction { + fn from(txn: Transaction) -> Self { + Self { + status: txn.status.into(), + private_key: Element::from_str( + txn.private_key + .as_ref() + .expect("deposit transactions require private key"), + ) + .expect("private key must be valid element"), + note_kind: txn.to_note_kind(), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct RampDepositLinkTransaction { + pub status: RampStatus, + #[serde(default = "bridged_polygon_usdc_note_kind")] + pub note_kind: Element, +} + +impl From for RampDepositLinkTransaction { + fn from(txn: Transaction) -> Self { + Self { + status: txn.status.into(), + note_kind: txn.to_note_kind(), + } + } +} diff --git a/pkg/ramps-interface/src/transaction/kinds/mod.rs b/pkg/ramps-interface/src/transaction/kinds/mod.rs new file mode 100644 index 0000000..ca32f5e --- /dev/null +++ b/pkg/ramps-interface/src/transaction/kinds/mod.rs @@ -0,0 +1,142 @@ +use chrono::{DateTime, Utc}; +use currency::Currency; +use element::Element; +use network::{Network, NetworkIdentifier}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use uuid::Uuid; + +use crate::provider::Provider; + +use super::{Status, Transaction, TransactionKind}; + +mod card; +mod deposit; +mod withdraw; + +pub use card::*; +pub use deposit::*; +pub use withdraw::*; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RampTransaction { + #[serde(flatten)] + pub base: RampTransactionBase, + #[serde(flatten)] + pub kind: RampTransactionKind, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE", tag = "kind")] +pub enum RampTransactionKind { + Card(RampCardTransaction), + Withdraw(RampWithdrawTransaction), + Deposit(RampDepositTransaction), + DepositLink(RampDepositLinkTransaction), +} + +impl From for RampTransaction { + fn from(txn: Transaction) -> Self { + let kind = match txn.kind() { + TransactionKind::Card => RampTransactionKind::Card(txn.clone().into()), + TransactionKind::Withdraw => RampTransactionKind::Withdraw(txn.clone().into()), + TransactionKind::Deposit => RampTransactionKind::Deposit(txn.clone().into()), + TransactionKind::DepositLink => RampTransactionKind::DepositLink(txn.clone().into()), + }; + + Self { + base: RampTransactionBase::from(txn), + kind, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct RampTransactionBase { + pub id: Uuid, + pub account_id: Uuid, + pub provider: Provider, + pub from_currency: Currency, + pub from_amount: Element, + pub from_network: Network, + pub from_network_identifier: Option, + pub to_currency: Currency, + pub to_amount: Element, + pub to_network: Network, + pub to_network_identifier: Option, + pub updated_at: DateTime, + pub added_at: DateTime, +} + +impl From for RampTransactionBase { + fn from(txn: Transaction) -> Self { + Self { + id: txn.id, + account_id: txn.account_id, + provider: txn.provider, + from_currency: txn.from_currency, + from_amount: txn.from_amount, + from_network: txn.from_network, + from_network_identifier: txn.from_network_identifier, + to_currency: txn.to_currency, + to_amount: txn.to_amount, + to_network: txn.to_network, + to_network_identifier: txn.to_network_identifier, + updated_at: txn.updated_at, + added_at: txn.added_at, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum CardStatus { + Pending, + Complete, + Declined, + Refunded, +} + +impl From for CardStatus { + fn from(status: Status) -> Self { + match status { + Status::Pending => CardStatus::Pending, + Status::Complete => CardStatus::Complete, + Status::Declined => CardStatus::Declined, + Status::Refunded => CardStatus::Refunded, + other => panic!("unexpected status {other:?} for card txn"), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum RampStatus { + Pending, + Complete, + Cancelled, + Refunded, + Funded, + Withdraw, +} + +impl From for RampStatus { + fn from(status: Status) -> Self { + match status { + Status::Pending => RampStatus::Pending, + Status::Complete => RampStatus::Complete, + Status::Cancelled => RampStatus::Cancelled, + Status::Refunded => RampStatus::Refunded, + Status::Funded => RampStatus::Funded, + Status::Withdraw => RampStatus::Withdraw, + other => panic!("unexpected status {other:?} for ramp txn"), + } + } +} diff --git a/pkg/ramps-interface/src/transaction/kinds/withdraw.rs b/pkg/ramps-interface/src/transaction/kinds/withdraw.rs new file mode 100644 index 0000000..86e25b8 --- /dev/null +++ b/pkg/ramps-interface/src/transaction/kinds/withdraw.rs @@ -0,0 +1,36 @@ +use std::str::FromStr; + +use element::Element; +use ethereum_types::Address; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use zk_primitives::bridged_polygon_usdc_note_kind; + +use super::{RampStatus, Transaction}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct RampWithdrawTransaction { + pub status: RampStatus, + #[cfg_attr(feature = "ts-rs", ts(type = "string"))] + pub evm_address: Address, + #[serde(default = "bridged_polygon_usdc_note_kind")] + pub note_kind: Element, +} + +impl From for RampWithdrawTransaction { + fn from(txn: Transaction) -> Self { + Self { + status: txn.status.into(), + evm_address: Address::from_str( + txn.evm_address + .as_ref() + .expect("withdraw transactions require evm_address"), + ) + .expect("evm_address should be valid hex"), + note_kind: txn.from_note_kind(), + } + } +} diff --git a/pkg/ramps-interface/src/transaction/mod.rs b/pkg/ramps-interface/src/transaction/mod.rs new file mode 100644 index 0000000..02848ca --- /dev/null +++ b/pkg/ramps-interface/src/transaction/mod.rs @@ -0,0 +1,13 @@ +mod category; +mod db; +mod kinds; +mod rpc; +mod status; +mod traits; + +pub use category::*; +pub use db::*; +pub use kinds::*; +pub use rpc::*; +pub use status::*; +pub use traits::*; diff --git a/pkg/ramps-interface/src/transaction/rpc.rs b/pkg/ramps-interface/src/transaction/rpc.rs new file mode 100644 index 0000000..aafe728 --- /dev/null +++ b/pkg/ramps-interface/src/transaction/rpc.rs @@ -0,0 +1,84 @@ +use currency::Currency; +use element::Element; +use network::Network; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use crate::provider::Provider; + +use super::{FundingStatus, Status, TransactionUpdate}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct CreateTransactionRequest { + pub quote_id: Uuid, + pub from_network_identifier: Option, + pub to_network_identifier: Option, + pub evm_address: Option, + pub external_id: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct UpdateTransactionRequest { + pub status: Option, + pub local_id: Option, + pub evm_address: Option, + pub memo: Option, +} + +impl From for TransactionUpdate { + fn from(req: UpdateTransactionRequest) -> Self { + Self { + status: req.status, + memo: req.memo, + ..Default::default() + } + } +} + +pub struct FundTransactionRequest { + pub external_id: String, + pub from_currency: Currency, + pub from_amount: Element, + pub from_network: Network, + pub default_to_currency: Currency, + pub default_to_network: Network, + pub default_method_id: Option, +} + +#[derive(Debug, Default, Clone, Deserialize, Serialize)] +pub struct ListRampsTransactionsQuery { + pub wait: Option, + pub after: Option, + pub provider: Option, + pub status: Option, + pub funding_status: Option, + pub network: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LimitQuery { + pub provider: Provider, + pub network: Network, + pub action: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct RemainingLimits { + #[serde(skip_serializing_if = "Option::is_none")] + pub daily: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub weekly: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub monthly: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub default_daily: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub default_weekly: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub default_monthly: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + pub min_amount: Option, +} diff --git a/pkg/ramps-interface/src/transaction/status.rs b/pkg/ramps-interface/src/transaction/status.rs new file mode 100644 index 0000000..61838ed --- /dev/null +++ b/pkg/ramps-interface/src/transaction/status.rs @@ -0,0 +1,162 @@ +#[cfg(feature = "diesel")] +use std::io::Write; + +#[cfg(feature = "diesel")] +use diesel::{ + deserialize::{self, FromSql}, + pg::Pg, + serialize::{self, IsNull, Output, ToSql}, +}; +use serde::{Deserialize, Serialize}; +use strum::{Display, EnumString}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +#[derive( + Debug, + Clone, + Serialize, + Deserialize, + Copy, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr( + feature = "diesel", + derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow) +)] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum FundingStatus { + PendingDebit, + PendingCredit, + InsufficientFunds, + Settled, +} + +#[cfg(feature = "diesel")] +impl ToSql for FundingStatus { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for FundingStatus { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized funding status".into()) + } +} + +#[derive( + Debug, + Clone, + Serialize, + Deserialize, + Copy, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr( + feature = "diesel", + derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow) +)] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum TransactionStatusReason { + DepositAmountTooLow, + DepositAmountTooHigh, +} + +#[cfg(feature = "diesel")] +impl ToSql for TransactionStatusReason { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for TransactionStatusReason { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse() + .map_err(|_| "Unrecognized Transaction cancel reason".into()) + } +} + +#[derive( + Debug, + Clone, + Serialize, + Deserialize, + Copy, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + Display, + EnumString, +)] +#[cfg_attr( + feature = "diesel", + derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow) +)] +#[cfg_attr(feature = "diesel", diesel(sql_type = diesel::sql_types::Text))] +#[strum(serialize_all = "SCREAMING_SNAKE_CASE")] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(rename = "RampsTransactionStatus"))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum Status { + /// Pending status - default initial status + Pending, + /// Transaction is complete, no further changes expected + Complete, + /// Cancelled by either the user or the provider + Cancelled, + /// Txn was refunded back to the user in full + Refunded, + /// Card only + Declined, + /// An error caused the request to fail + Failed, + // Onramp/offramps only + /// Transaction has been funded, we have received the users funds + Funded, + /// Funds have been withdrawn/sent to the user + Withdraw, +} + +#[cfg(feature = "diesel")] +impl ToSql for Status { + fn to_sql(&self, out: &mut Output) -> serialize::Result { + write!(out, "{self}")?; + Ok(IsNull::No) + } +} + +#[cfg(feature = "diesel")] +impl FromSql for Status { + fn from_sql(bytes: diesel::pg::PgValue) -> deserialize::Result { + let s = std::str::from_utf8(bytes.as_bytes())?; + s.parse().map_err(|_| "Unrecognized status".into()) + } +} diff --git a/pkg/ramps-interface/src/transaction/traits.rs b/pkg/ramps-interface/src/transaction/traits.rs new file mode 100644 index 0000000..153f0f4 --- /dev/null +++ b/pkg/ramps-interface/src/transaction/traits.rs @@ -0,0 +1,37 @@ +use async_trait::async_trait; +use test_spy::spy_mock; +use uuid::Uuid; + +use crate::error::Result; + +use super::{ + CreateTransactionRequest, LimitQuery, ListRampsTransactionsQuery, RampTransaction, + RemainingLimits, Transaction, UpdateTransactionRequest, +}; + +#[spy_mock] +#[async_trait] +pub trait TransactionsInterface: Send + Sync { + async fn create_transaction( + &self, + wallet_id: Uuid, + request: CreateTransactionRequest, + ) -> Result; + + async fn list_transactions( + &self, + wallet_id: Uuid, + query: ListRampsTransactionsQuery, + ) -> Result>; + + async fn get_transaction(&self, wallet_id: Uuid, transaction_id: Uuid) -> Result; + + async fn update_transaction( + &self, + wallet_id: Uuid, + transaction_id: Uuid, + request: UpdateTransactionRequest, + ) -> Result; + + async fn get_limits(&self, wallet_id: Uuid, query: LimitQuery) -> Result; +} diff --git a/pkg/ramps-interface/src/util.rs b/pkg/ramps-interface/src/util.rs new file mode 100644 index 0000000..bdf72d9 --- /dev/null +++ b/pkg/ramps-interface/src/util.rs @@ -0,0 +1,35 @@ +//! Miscellaneous helpers shared across ramps interface modules. + +use chrono::Utc; +use rand::Rng; + +/// Generates a unique, human-readable identifier for local method records. +/// +/// The identifier embeds a timestamp to preserve ordering while avoiding +/// collisions via a random suffix. +#[must_use] +pub fn local_uid() -> String { + let now = Utc::now().timestamp_millis(); + let random = rand::thread_rng().gen_range(0..1_000_000_000); + format!("id-{now}-{random}") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn generates_distinct_values() { + let uid1 = local_uid(); + let uid2 = local_uid(); + + assert!(uid1.starts_with("id-")); + assert!(uid2.starts_with("id-")); + assert_ne!(uid1, uid2); + + let parts: Vec<&str> = uid1.split('-').collect(); + assert_eq!(parts.len(), 3); + assert!(parts[1].parse::().is_ok()); + assert!(parts[2].parse::().is_ok()); + } +} diff --git a/pkg/ramps-interface/src/webhooks.rs b/pkg/ramps-interface/src/webhooks.rs new file mode 100644 index 0000000..0e8522a --- /dev/null +++ b/pkg/ramps-interface/src/webhooks.rs @@ -0,0 +1,32 @@ +use async_trait::async_trait; +use serde_json::Value; +use std::collections::HashMap; +use test_spy::spy_mock; + +use crate::provider::Provider; + +use crate::error::Result; + +/// High-level metadata describing the inbound webhook request. +#[derive(Debug, Clone, Default)] +pub struct WebhookContext { + pub path: String, + pub headers: HashMap, + pub peer_addr: Option, + pub provider: Option, +} + +/// Wrapper around provider webhook payloads with auxiliary request data. +#[derive(Debug, Clone)] +pub struct WebhookRequest { + pub context: WebhookContext, + pub raw_body: Vec, + pub provider: Provider, +} + +/// Interface covering provider webhook entry points. +#[spy_mock] +#[async_trait] +pub trait WebhooksInterface: Send + Sync { + async fn handle_webhook(&self, request: WebhookRequest) -> Result; +} diff --git a/pkg/rpc-error-convert/Cargo.toml b/pkg/rpc-error-convert/Cargo.toml new file mode 100644 index 0000000..234b65a --- /dev/null +++ b/pkg/rpc-error-convert/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rpc-error-convert" +version = "0.1.0" +edition = "2024" + +[lib] +proc-macro = true + +[dependencies] +serde_json = { workspace = true } +syn = { workspace = true, features = ["full"] } +quote = { workspace = true } +proc-macro2 = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/rpc-error-convert/README.md b/pkg/rpc-error-convert/README.md new file mode 100644 index 0000000..555e46e --- /dev/null +++ b/pkg/rpc-error-convert/README.md @@ -0,0 +1,133 @@ +# RPC Error Convert + +A procedural macro for automatic conversion between application errors and HTTP errors in RPC contexts. + +## Overview + +This package provides the `HTTPErrorConversion` derive macro that automatically implements conversions between your application error types and RPC HTTP errors. It supports: + +- Unit variants (no data) +- Single unnamed fields +- Multiple unnamed fields (creates tuple struct) +- Named fields (creates struct) + +## Features + +- Automatic generation of `From for HTTPError` +- Automatic generation of `TryFrom for YourError` +- Automatic generation of `TryFrom for YourError` +- Support for serializing/deserializing error data +- Type-safe error conversions +- Works seamlessly with `Contextful` wrappers via `HTTPError::from` + +## Usage + +```rust +use rpc::HTTPErrorConversion; +use rpc::code::ErrorCode; +use rpc::error::{ErrorOutput, HTTPError, Severity, TryFromHTTPError}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize)] +pub enum MyError { + // Unit variant - no data + #[bad_request("invalid-request")] + #[error("invalid request")] + InvalidRequest, + + // Single unnamed field - data passed directly + #[not_found("user-not-found")] + #[error("user not found: {0:?}")] + UserNotFound(UserData), + + // Multiple unnamed fields - generates MultipleFieldsData tuple struct + #[bad_request("multiple-fields")] + #[error("multiple fields error")] + MultipleFields(String, u32, bool), + + // Named fields - generates DuplicateEntryData struct + #[already_exists("duplicate-entry")] + #[error("duplicate entry with id {id}")] + DuplicateEntry { + id: u64, + name: String + }, + + // Unit variant with warn severity + #[bad_request("quote-too-small", severity = "warn")] + #[error("[my_error] quote output amount below minimum")] + QuoteTooSmall, +} +``` + +## Generated Structures + +For variants with multiple unnamed fields or named fields, the macro automatically generates data structures: + +### Multiple Unnamed Fields +For `MultipleFields(String, u32, bool)`, generates: +```rust +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct MultipleFieldsData(pub String, pub u32, pub bool); +``` + +### Named Fields +For `DuplicateEntry { id: u64, name: String }`, generates: +```rust +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct DuplicateEntryData { + pub id: u64, + pub name: String, +} +``` + +## Supported Attributes + +- `#[bad_request("error-code")]` - Maps to `ErrorCode::BadRequest` +- `#[not_found("error-code")]` - Maps to `ErrorCode::NotFound` +- `#[already_exists("error-code")]` - Maps to `ErrorCode::AlreadyExists` +- `#[failed_precondition("error-code")]` - Maps to `ErrorCode::FailedPrecondition` +- `#[internal("error-code")]` - Maps to `ErrorCode::FailedPrecondition` +- Optional `severity = "warn" | "error"` argument adjusts the generated `HTTPError` severity level (defaults to `"error"` when omitted) + +## Severity Overrides + +By default, generated `HTTPError` instances use `Severity::Error`. For expected validation failures where you want to downgrade the alerting noise, supply an explicit severity override: + +```rust +#[derive(Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize)] +pub enum QuoteError { + #[error("[quote] output amount below provider minimum")] + #[bad_request("output-too-low", severity = "warn")] + OutputTooLow, +} +``` + +This keeps the HTTP status and reason intact while ensuring `HTTPError::severity` is `Severity::Warn`, allowing downstream logging and alerting policies to treat the error as non-fatal. The derive emits fully-qualified severity paths, so no additional imports are required in the consuming crate. + +## Requirements + +All data types used in variants must implement: +- `Clone` +- `Serialize` +- `Deserialize` + +## Example Conversion Flow + +```rust +// Create an error +let error = MyError::DuplicateEntry { + id: 123, + name: "test".to_string() +}; + +// Convert to HTTPError (automatic serialization of data) +let http_error: HTTPError = error.into(); + +// Convert back from HTTPError (automatic deserialization of data) +let recovered = MyError::try_from(http_error).unwrap(); +``` + +## Contextful Support + +Errors wrapped in `contextful::Contextful` convert directly into `HTTPError` whenever `E` already implements `Into`. This keeps the ergonomic `.context(...)` workflow while avoiding manual calls to `into_parts()` when delegating to the derived conversions. diff --git a/pkg/rpc-error-convert/src/attrs.rs b/pkg/rpc-error-convert/src/attrs.rs new file mode 100644 index 0000000..0ab5f43 --- /dev/null +++ b/pkg/rpc-error-convert/src/attrs.rs @@ -0,0 +1,145 @@ +use quote::quote; +use syn::{Attribute, Ident, LitStr, Variant, parse::ParseStream}; + +#[derive(Clone)] +pub struct HttpErrorMapping { + pub error_code: proc_macro2::TokenStream, + pub error_code_str: String, + pub severity: Option, + pub include_data: bool, +} + +#[derive(Clone)] +pub enum HttpErrorAttr { + Mapping(HttpErrorMapping), + Delegate, +} + +pub fn find_http_error_attr(variant: &Variant) -> syn::Result> { + for attr in &variant.attrs { + let ident = match attr.path().get_ident() { + Some(ident) => ident.to_string(), + None => continue, + }; + let attr_value = match ident.as_str() { + "bad_request" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::BadRequest }, + )?), + "not_found" => Some(parse_http_error_attr(attr, quote! { ErrorCode::NotFound })?), + "already_exists" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::AlreadyExists }, + )?), + "failed_precondition" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::FailedPrecondition }, + )?), + "payload_too_large" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::PayloadTooLarge }, + )?), + "deadline_exceeded" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::DeadlineExceeded }, + )?), + "internal" => Some(parse_http_error_attr(attr, quote! { ErrorCode::Internal })?), + "invalid_argument" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::InvalidArgument }, + )?), + "permission_denied" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::PermissionDenied }, + )?), + "unauthenticated" => Some(parse_http_error_attr( + attr, + quote! { ErrorCode::Unauthenticated }, + )?), + "aborted" => Some(parse_http_error_attr(attr, quote! { ErrorCode::Aborted })?), + "delegate" => Some(HttpErrorAttr::Delegate), + _ => None, + }; + + if attr_value.is_some() { + return Ok(attr_value); + } + } + + Ok(None) +} + +fn parse_http_error_attr( + attr: &Attribute, + error_code: proc_macro2::TokenStream, +) -> syn::Result { + let (error_code_str, severity, include_data) = extract_attr_details(attr)?; + + Ok(HttpErrorAttr::Mapping(HttpErrorMapping { + error_code, + error_code_str, + severity, + include_data, + })) +} + +fn extract_attr_details( + attr: &Attribute, +) -> syn::Result<(String, Option, bool)> { + let mut reason: Option = None; + let mut severity_tokens: Option = None; + let mut include_data = true; + + attr.parse_args_with(|input: ParseStream<'_>| { + while !input.is_empty() { + if input.peek(LitStr) && reason.is_none() { + reason = Some(input.parse::()?.value()); + } else { + let name = input.parse::()?; + input.parse::()?; + let value = input.parse::()?; + + match name.to_string().as_str() { + "severity" => { + severity_tokens = match value.value().to_lowercase().as_str() { + "warn" => Some(quote! { ::rpc::error::Severity::Warn }), + "error" => None, + other => { + return Err(syn::Error::new_spanned( + &value, + format!("Unsupported severity level: {other}"), + )); + } + }; + } + "data" => { + include_data = !matches!( + value.value().to_lowercase().as_str(), + "omit" | "none" | "skip" | "false" + ); + } + _ => { + return Err(syn::Error::new_spanned( + name, + "Unsupported attribute argument", + )); + } + } + } + + if input.is_empty() { + break; + } + + input.parse::()?; + } + + Ok(()) + })?; + + let reason = reason.ok_or_else(|| { + syn::Error::new_spanned(attr, "Expected string literal reason in attribute") + })?; + + Ok((reason, severity_tokens, include_data)) +} diff --git a/pkg/rpc-error-convert/src/data_structs.rs b/pkg/rpc-error-convert/src/data_structs.rs new file mode 100644 index 0000000..e123dc4 --- /dev/null +++ b/pkg/rpc-error-convert/src/data_structs.rs @@ -0,0 +1,84 @@ +use quote::{format_ident, quote}; +use syn::{Fields, Variant, punctuated::Punctuated, token::Comma}; + +use crate::attrs::HttpErrorAttr; + +pub fn generate_data_structs( + variants: &Punctuated, + attrs: &[Option], +) -> syn::Result { + let structs = variants + .iter() + .zip(attrs.iter()) + .filter_map(|(variant, attr)| { + let include_data = match attr { + Some(HttpErrorAttr::Mapping(mapping)) => mapping.include_data, + _ => false, + }; + if !include_data { + return None; + } + + let variant_name = &variant.ident; + let data_struct_name = format_ident!("{}Data", variant_name); + + let struct_tokens = match &variant.fields { + Fields::Named(fields) => { + let field_definitions: syn::Result> = fields + .named + .iter() + .map(|f| { + let field_name = f.ident.as_ref().ok_or_else(|| { + syn::Error::new_spanned(f, "expected named field") + })?; + let field_type = &f.ty; + let doc_attrs: Vec<_> = f + .attrs + .iter() + .filter(|attr| attr.path().is_ident("doc")) + .collect(); + + Ok(quote! { + #(#doc_attrs)* + pub #field_name: #field_type + }) + }) + .collect(); + + let field_definitions = match field_definitions { + Ok(fields) => fields, + Err(err) => return Some(Err(err)), + }; + + let struct_doc = format!("Data structure for {variant_name} error variant"); + + Ok(quote! { + #[doc = #struct_doc] + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] + pub struct #data_struct_name { + #(#field_definitions),* + } + }) + } + Fields::Unnamed(fields) if fields.unnamed.len() > 1 => { + let field_types: Vec<_> = fields.unnamed.iter().map(|f| &f.ty).collect(); + let struct_doc = + format!("Data structure for {variant_name} error variant (tuple fields)"); + + Ok(quote! { + #[doc = #struct_doc] + #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] + pub struct #data_struct_name(#(pub #field_types),*); + }) + } + _ => Ok(proc_macro2::TokenStream::new()), + }; + + Some(struct_tokens) + }) + .collect::>>()?; + + Ok(quote! { + #(#structs)* + }) +} diff --git a/pkg/rpc-error-convert/src/derive.rs b/pkg/rpc-error-convert/src/derive.rs new file mode 100644 index 0000000..389b123 --- /dev/null +++ b/pkg/rpc-error-convert/src/derive.rs @@ -0,0 +1,79 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{Data, DeriveInput}; + +use crate::attrs::find_http_error_attr; +use crate::data_structs::generate_data_structs; +use crate::fallback::build_fallback_match_arm; +use crate::from_http::build_match_arms_from_http; +use crate::to_http::build_match_arms_to_http; + +pub fn derive_http_error(input: TokenStream) -> TokenStream { + let input = syn::parse_macro_input!(input as DeriveInput); + match derive_http_error_impl(&input) { + Ok(tokens) => tokens.into(), + Err(err) => err.to_compile_error().into(), + } +} + +fn derive_http_error_impl(input: &DeriveInput) -> syn::Result { + let enum_name = &input.ident; + let variants = match &input.data { + Data::Enum(data_enum) => &data_enum.variants, + _ => { + return Err(syn::Error::new_spanned( + input, + "HTTPErrorConversion can only be derived for enums", + )); + } + }; + + let http_attrs = variants + .iter() + .map(find_http_error_attr) + .collect::>>()?; + + let data_structs = generate_data_structs(variants, &http_attrs)?; + let match_arms_to_http = build_match_arms_to_http(enum_name, variants, &http_attrs)?; + let match_arms_from_http = build_match_arms_from_http(enum_name, variants, &http_attrs)?; + let fallback_match_arm = build_fallback_match_arm(enum_name, variants, &http_attrs)?; + + Ok(quote! { + #data_structs + + // Note: All data types used in tuple variants must implement Clone + impl From<#enum_name> for HTTPError { + fn from(err: #enum_name) -> Self { + match err { + #(#match_arms_to_http)* + } + } + } + + impl std::convert::TryFrom for #enum_name { + type Error = TryFromHTTPError; + + fn try_from(http_error: HTTPError) -> std::result::Result { + match http_error.reason.as_str() { + #(#match_arms_from_http)* + #fallback_match_arm + } + } + } + + impl std::convert::TryFrom for #enum_name { + type Error = TryFromHTTPError; + + fn try_from(error_output: ErrorOutput) -> std::result::Result { + let http_error = HTTPError::new( + error_output.error.code, + &error_output.error.reason, + None, + error_output.error.data, + ); + + Self::try_from(http_error) + } + } + }) +} diff --git a/pkg/rpc-error-convert/src/fallback.rs b/pkg/rpc-error-convert/src/fallback.rs new file mode 100644 index 0000000..3855881 --- /dev/null +++ b/pkg/rpc-error-convert/src/fallback.rs @@ -0,0 +1,39 @@ +use quote::quote; +use syn::{Variant, punctuated::Punctuated, token::Comma}; + +use crate::attrs::HttpErrorAttr; +use crate::util::{contextful_inner_type, delegate_variant_info}; + +pub fn build_fallback_match_arm( + enum_name: &syn::Ident, + variants: &Punctuated, + attrs: &[Option], +) -> syn::Result { + let delegate_variant = delegate_variant_info(variants, attrs)?; + let fallback = match delegate_variant { + Some((variant_name, inner_type)) => { + if let Some(contextful_inner) = contextful_inner_type(&inner_type) { + quote! { + _ => { + let inner = <#contextful_inner as std::convert::TryFrom>::try_from(http_error) + .map_err(TryFromHTTPError::from)?; + Ok(#enum_name::#variant_name(contextful::Contextful::from(inner))) + } + } + } else { + quote! { + _ => { + let inner = <#inner_type as std::convert::TryFrom>::try_from(http_error) + .map_err(TryFromHTTPError::from)?; + Ok(#enum_name::#variant_name(inner)) + } + } + } + } + None => quote! { + reason => Err(TryFromHTTPError::UnknownReason(reason.to_string())), + }, + }; + + Ok(fallback) +} diff --git a/pkg/rpc-error-convert/src/from_http.rs b/pkg/rpc-error-convert/src/from_http.rs new file mode 100644 index 0000000..999cd3a --- /dev/null +++ b/pkg/rpc-error-convert/src/from_http.rs @@ -0,0 +1,102 @@ +use quote::{format_ident, quote}; +use syn::{Fields, Variant, punctuated::Punctuated, token::Comma}; + +use crate::attrs::{HttpErrorAttr, HttpErrorMapping}; +use crate::util::named_field_idents; + +pub fn build_match_arms_from_http( + enum_name: &syn::Ident, + variants: &Punctuated, + attrs: &[Option], +) -> syn::Result> { + let mut arms = Vec::new(); + + for (variant, attr) in variants.iter().zip(attrs.iter()) { + let mapping = match attr { + Some(HttpErrorAttr::Mapping(mapping)) => mapping, + _ => continue, + }; + arms.push(build_from_http_arm(enum_name, variant, mapping)?); + } + + Ok(arms) +} + +fn build_from_http_arm( + enum_name: &syn::Ident, + variant: &Variant, + mapping: &HttpErrorMapping, +) -> syn::Result { + let variant_name = &variant.ident; + let error_code_str = &mapping.error_code_str; + let include_data = mapping.include_data; + + let arm = match &variant.fields { + Fields::Unit => quote! { + #error_code_str => Ok(#enum_name::#variant_name), + }, + Fields::Unnamed(fields) => { + let field_count = fields.unnamed.len(); + match (field_count, include_data) { + (1, true) => quote! { + #error_code_str => { + if let Some(data) = http_error.data { + let data = serde_json::from_value(data) + .map_err(|_| TryFromHTTPError::DeserializationError)?; + Ok(#enum_name::#variant_name(data)) + } else { + Err(TryFromHTTPError::MissingData) + } + }, + }, + (1, false) => quote! { + #error_code_str => Err(TryFromHTTPError::MissingData), + }, + (_, true) => { + let data_struct_name = format_ident!("{}Data", variant_name); + let field_bindings: Vec<_> = (0..field_count) + .map(|i| format_ident!("field_{}", i)) + .collect(); + + quote! { + #error_code_str => { + if let Some(data) = http_error.data { + let #data_struct_name(#(#field_bindings),*) = serde_json::from_value(data) + .map_err(|_| TryFromHTTPError::DeserializationError)?; + Ok(#enum_name::#variant_name(#(#field_bindings),*)) + } else { + Err(TryFromHTTPError::MissingData) + } + }, + } + } + (_, false) => quote! { + #error_code_str => Err(TryFromHTTPError::MissingData), + }, + } + } + Fields::Named(fields) => { + if include_data { + let data_struct_name = format_ident!("{}Data", variant_name); + let field_names = named_field_idents(fields)?; + quote! { + #error_code_str => { + if let Some(data) = http_error.data { + let #data_struct_name { #(#field_names),* } = serde_json::from_value(data) + .map_err(|_| TryFromHTTPError::DeserializationError)?; + Ok(#enum_name::#variant_name { #(#field_names),* }) + } else { + Err(TryFromHTTPError::MissingData) + } + }, + } + } else { + quote! { + #error_code_str => Err(TryFromHTTPError::MissingData), + } + } + } + }; + + Ok(arm) +} diff --git a/pkg/rpc-error-convert/src/lib.rs b/pkg/rpc-error-convert/src/lib.rs new file mode 100644 index 0000000..e8c63a8 --- /dev/null +++ b/pkg/rpc-error-convert/src/lib.rs @@ -0,0 +1,33 @@ +extern crate proc_macro; + +mod attrs; +mod data_structs; +mod derive; +mod fallback; +mod from_http; +mod to_http; +mod util; + +use proc_macro::TokenStream; + +/// Derive macro for implementing `From` for HTTPError and `TryFrom` for Error +#[proc_macro_derive( + HTTPErrorConversion, + attributes( + bad_request, + not_found, + already_exists, + failed_precondition, + payload_too_large, + deadline_exceeded, + internal, + invalid_argument, + permission_denied, + unauthenticated, + aborted, + delegate + ) +)] +pub fn derive_http_error(input: TokenStream) -> TokenStream { + derive::derive_http_error(input) +} diff --git a/pkg/rpc-error-convert/src/to_http.rs b/pkg/rpc-error-convert/src/to_http.rs new file mode 100644 index 0000000..41d5d02 --- /dev/null +++ b/pkg/rpc-error-convert/src/to_http.rs @@ -0,0 +1,183 @@ +use quote::{format_ident, quote}; +use syn::{Fields, FieldsNamed, FieldsUnnamed, Variant, punctuated::Punctuated, token::Comma}; + +use crate::attrs::{HttpErrorAttr, HttpErrorMapping}; +use crate::util::{build_http_error_call, named_field_idents}; + +pub fn build_match_arms_to_http( + enum_name: &syn::Ident, + variants: &Punctuated, + attrs: &[Option], +) -> syn::Result> { + variants + .iter() + .zip(attrs.iter()) + .map(|(variant, attr)| build_match_arm_to_http(enum_name, variant, attr)) + .collect() +} + +fn build_match_arm_to_http( + enum_name: &syn::Ident, + variant: &Variant, + attr: &Option, +) -> syn::Result { + let variant_name = &variant.ident; + + match attr { + Some(HttpErrorAttr::Mapping(mapping)) => { + build_mapping_arm_to_http(enum_name, variant_name, &variant.fields, mapping) + } + Some(HttpErrorAttr::Delegate) => build_delegate_arm_to_http(enum_name, variant), + None => Ok(build_internal_arm_to_http( + enum_name, + variant_name, + &variant.fields, + )), + } +} + +fn build_mapping_arm_to_http( + enum_name: &syn::Ident, + variant_name: &syn::Ident, + fields: &Fields, + mapping: &HttpErrorMapping, +) -> syn::Result { + match fields { + Fields::Unit => Ok(build_unit_mapping_arm(enum_name, variant_name, mapping)), + Fields::Unnamed(fields) => Ok(build_unnamed_mapping_arm( + enum_name, + variant_name, + fields, + mapping, + )), + Fields::Named(fields) => build_named_mapping_arm(enum_name, variant_name, fields, mapping), + } +} + +fn build_unit_mapping_arm( + enum_name: &syn::Ident, + variant_name: &syn::Ident, + mapping: &HttpErrorMapping, +) -> proc_macro2::TokenStream { + let http_error = build_http_error_for_mapping(mapping, quote! { None::<()> }); + quote! { + #enum_name::#variant_name => #http_error, + } +} + +fn build_unnamed_mapping_arm( + enum_name: &syn::Ident, + variant_name: &syn::Ident, + fields: &FieldsUnnamed, + mapping: &HttpErrorMapping, +) -> proc_macro2::TokenStream { + let field_count = fields.unnamed.len(); + match (field_count, mapping.include_data) { + (1, true) => { + let http_error = build_http_error_for_mapping(mapping, quote! { Some(data_clone) }); + quote! { + #enum_name::#variant_name(ref data) => { + let data_clone = data.clone(); + #http_error + }, + } + } + (1, false) => { + let http_error = build_http_error_for_mapping(mapping, quote! { None::<()> }); + quote! { + #enum_name::#variant_name(_) => #http_error, + } + } + (_, true) => { + let data_struct_name = format_ident!("{}Data", variant_name); + let field_names: Vec<_> = (0..field_count) + .map(|i| format_ident!("field_{}", i)) + .collect(); + let http_error = build_http_error_for_mapping(mapping, quote! { Some(data) }); + quote! { + #enum_name::#variant_name(#(ref #field_names),*) => { + let data = #data_struct_name(#(#field_names.clone()),*); + #http_error + }, + } + } + (_, false) => { + let http_error = build_http_error_for_mapping(mapping, quote! { None::<()> }); + quote! { + #enum_name::#variant_name(..) => #http_error, + } + } + } +} + +fn build_named_mapping_arm( + enum_name: &syn::Ident, + variant_name: &syn::Ident, + fields: &FieldsNamed, + mapping: &HttpErrorMapping, +) -> syn::Result { + if mapping.include_data { + let data_struct_name = format_ident!("{}Data", variant_name); + let field_names = named_field_idents(fields)?; + let http_error = build_http_error_for_mapping(mapping, quote! { Some(data) }); + Ok(quote! { + #enum_name::#variant_name { #(ref #field_names),* } => { + let data = #data_struct_name { + #(#field_names: #field_names.clone()),* + }; + #http_error + }, + }) + } else { + let http_error = build_http_error_for_mapping(mapping, quote! { None::<()> }); + Ok(quote! { + #enum_name::#variant_name { .. } => #http_error, + }) + } +} + +fn build_http_error_for_mapping( + mapping: &HttpErrorMapping, + data_tokens: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + build_http_error_call( + &mapping.error_code, + &mapping.error_code_str, + mapping.severity.as_ref(), + data_tokens, + ) +} + +fn build_delegate_arm_to_http( + enum_name: &syn::Ident, + variant: &Variant, +) -> syn::Result { + let variant_name = &variant.ident; + match &variant.fields { + Fields::Unnamed(fields) if fields.unnamed.len() == 1 => Ok(quote! { + #enum_name::#variant_name(inner) => inner.into(), + }), + _ => Err(syn::Error::new_spanned( + variant, + "delegate attribute requires a single unnamed field", + )), + } +} + +fn build_internal_arm_to_http( + enum_name: &syn::Ident, + variant_name: &syn::Ident, + fields: &Fields, +) -> proc_macro2::TokenStream { + match fields { + Fields::Unit => quote! { + #enum_name::#variant_name => HTTPError::internal(err.into()), + }, + Fields::Unnamed(_) => quote! { + #enum_name::#variant_name(..) => HTTPError::internal(err.into()), + }, + Fields::Named(_) => quote! { + #enum_name::#variant_name { .. } => HTTPError::internal(err.into()), + }, + } +} diff --git a/pkg/rpc-error-convert/src/util.rs b/pkg/rpc-error-convert/src/util.rs new file mode 100644 index 0000000..adc5c1c --- /dev/null +++ b/pkg/rpc-error-convert/src/util.rs @@ -0,0 +1,103 @@ +use quote::quote; +use syn::{ + Fields, FieldsNamed, GenericArgument, PathArguments, Type, Variant, punctuated::Punctuated, + token::Comma, +}; + +use crate::attrs::HttpErrorAttr; + +pub fn build_http_error_call( + error_code: &proc_macro2::TokenStream, + error_code_str: &str, + severity: Option<&proc_macro2::TokenStream>, + data_tokens: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + match severity { + Some(severity) => quote! { + HTTPError::new_with_severity( + #error_code, + #error_code_str, + Some(err.into()), + #data_tokens, + #severity, + ) + }, + None => quote! { + HTTPError::new( + #error_code, + #error_code_str, + Some(err.into()), + #data_tokens, + ) + }, + } +} + +pub fn contextful_inner_type(ty: &Type) -> Option { + let type_path = match ty { + Type::Path(type_path) => type_path, + _ => return None, + }; + + let segment = type_path.path.segments.last()?; + if segment.ident != "Contextful" { + return None; + } + + let args = match &segment.arguments { + PathArguments::AngleBracketed(args) => args, + _ => return None, + }; + + let mut inner_types = args.args.iter().filter_map(|arg| match arg { + GenericArgument::Type(inner) => Some(inner.clone()), + _ => None, + }); + let inner = inner_types.next()?; + if inner_types.next().is_some() { + return None; + } + + Some(inner) +} + +pub fn delegate_variant_info( + variants: &Punctuated, + attrs: &[Option], +) -> syn::Result> { + for (variant, attr) in variants.iter().zip(attrs.iter()) { + if !matches!(attr, Some(HttpErrorAttr::Delegate)) { + continue; + } + + match &variant.fields { + Fields::Unnamed(fields) if fields.unnamed.len() == 1 => { + let field = fields.unnamed.first().ok_or_else(|| { + syn::Error::new_spanned(variant, "delegate attribute requires a field") + })?; + return Ok(Some((variant.ident.clone(), field.ty.clone()))); + } + _ => { + return Err(syn::Error::new_spanned( + variant, + "delegate attribute requires a single unnamed field", + )); + } + } + } + + Ok(None) +} + +pub fn named_field_idents(fields: &FieldsNamed) -> syn::Result> { + fields + .named + .iter() + .map(|field| { + field + .ident + .clone() + .ok_or_else(|| syn::Error::new_spanned(field, "expected named field")) + }) + .collect() +} diff --git a/pkg/rpc/Cargo.toml b/pkg/rpc/Cargo.toml index 9b20d4a..9e3f368 100644 --- a/pkg/rpc/Cargo.toml +++ b/pkg/rpc/Cargo.toml @@ -1,22 +1,14 @@ [package] name = "rpc" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] -prover = { workspace = true } -zk-circuits = { workspace = true } - -actix-cors = { workspace = true } -actix-server = { workspace = true } actix-web = { workspace = true } chrono = { workspace = true } clap = { workspace = true } -derive_more = { workspace = true } eyre = { workspace = true } -futures = { workspace = true } futures-util = { workspace = true } -hex = { workspace = true } sentry = { workspace = true } sentry-tracing = { workspace = true } serde = { workspace = true } @@ -25,9 +17,15 @@ tokio = { workspace = true } tracing = { workspace = true } tracing-stackdriver = { workspace = true } tracing-subscriber = { workspace = true } -lazy_static = { workspace = true } opentelemetry = { workspace = true } opentelemetry_sdk = { workspace = true } opentelemetry-otlp = { workspace = true } tracing-opentelemetry = { workspace = true } -base64 = { workspace = true } +strum_macros = { workspace = true } +strum = { workspace = true } +rpc-error-convert = { workspace = true } +contextful = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +thiserror = { workspace = true } diff --git a/pkg/rpc/README.md b/pkg/rpc/README.md new file mode 100644 index 0000000..bfbd499 --- /dev/null +++ b/pkg/rpc/README.md @@ -0,0 +1,16 @@ +# RPC + +RPC framework with error handling, middleware, and long-polling support. + +## Overview + +This package provides a comprehensive RPC framework for building networked services. + +## Features + +- RPC error handling +- Middleware support +- Long-polling capabilities +- Tracing integration +- Response codes + diff --git a/pkg/rpc/src/code.rs b/pkg/rpc/src/code.rs index 933acdf..4a24953 100644 --- a/pkg/rpc/src/code.rs +++ b/pkg/rpc/src/code.rs @@ -1,52 +1,25 @@ use actix_web::http::StatusCode; -use derive_more::Display; +use serde::{Deserialize, Serialize}; +use strum_macros::{Display, EnumString}; -#[derive(Debug, Display)] +#[derive(Debug, Clone, Copy, Display, EnumString, Deserialize, Serialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +#[strum(serialize_all = "kebab-case")] pub enum ErrorCode { - #[display(fmt = "bad-request")] BadRequest, - - #[display(fmt = "invalid-argument")] InvalidArgument, - - #[display(fmt = "failed-precondition")] FailedPrecondition, - - #[display(fmt = "out-of-range")] OutOfRange, - - #[allow(unused)] - #[display(fmt = "unauthenticated")] Unauthenticated, - - #[display(fmt = "permission-denied")] PermissionDenied, - - #[display(fmt = "not-found")] NotFound, - - #[display(fmt = "aborted")] Aborted, - - #[display(fmt = "already-exists")] AlreadyExists, - - #[display(fmt = "resource-exhausted")] ResourceExhausted, - - #[display(fmt = "cancelled")] Cancelled, - - #[display(fmt = "payload-too-large")] PayloadTooLarge, - - #[display(fmt = "unavailable")] Unavailable, - - #[display(fmt = "internal")] Internal, - - #[display(fmt = "deadline-exceeded")] DeadlineExceeded, } diff --git a/pkg/rpc/src/error.rs b/pkg/rpc/src/error.rs index 675dfc3..ea510b5 100644 --- a/pkg/rpc/src/error.rs +++ b/pkg/rpc/src/error.rs @@ -1,51 +1,107 @@ -use crate::code::ErrorCode; -use actix_web::Responder; -use actix_web::ResponseError; -use actix_web::{http::header::ContentType, HttpResponse}; -use serde::Serialize; +// lint-long-file-override allow-max-lines=300 use std::fmt::Debug; use std::{error::Error, fmt::Display}; +use actix_web::{HttpResponse, Responder, ResponseError, http::header::ContentType}; +use contextful::Contextful; +use serde::{Deserialize, Serialize}; + +use crate::code::ErrorCode; + pub type HttpResult = std::result::Result; +/// Variant `Error` is the default error level. +/// `Warn` is to be used for "expected" errors that we wish +/// to avoid polluting the error logs. +#[derive(Debug, Default, Serialize, Deserialize)] +#[serde(rename_all = "UPPERCASE")] +pub enum Severity { + Warn, + #[default] + Error, +} + #[derive(Debug)] pub struct HTTPError { pub code: ErrorCode, pub reason: String, - source: Option>, + pub source: Option>, pub data: Option, + pub severity: Severity, } -#[derive(Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ErrorOutput { - error: ErrorDetail, + pub error: ErrorDetail, } -#[derive(Serialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct ErrorDetail { - code: String, - reason: String, - message: String, - data: Option, + pub code: ErrorCode, + pub reason: String, + pub message: String, + pub data: Option, +} + +// Define a custom error for TryFrom conversion failures +#[derive(Debug, Clone)] +pub enum TryFromHTTPError { + NoRpcErrorExpected(ErrorOutput), + UnknownReason(String), + DeserializationError, + MissingData, +} + +impl std::fmt::Display for TryFromHTTPError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + TryFromHTTPError::NoRpcErrorExpected(output) => { + write!(f, "No RPC error expected: {output:?}") + } + TryFromHTTPError::UnknownReason(reason) => { + write!(f, "Unknown error reason: {reason}") + } + TryFromHTTPError::DeserializationError => write!(f, "Failed to deserialize error data"), + TryFromHTTPError::MissingData => write!(f, "Error data is missing"), + } + } } + +impl std::error::Error for TryFromHTTPError {} + impl HTTPError { pub fn new( code: ErrorCode, reason: &str, source: Option>, data: Option, + ) -> HTTPError { + Self::new_with_severity(code, reason, source, data, Severity::Error) + } + + pub fn new_with_severity( + code: ErrorCode, + reason: &str, + source: Option>, + data: Option, + severity: Severity, ) -> HTTPError { HTTPError { - data: data.map(|data| { - serde_json::to_value(data).unwrap_or_else(|err| { - panic!( - "Unable to serialize error data for error {source:?}, serializing data err: {err:?}", - ) - }) + data: data.and_then(|data| match serde_json::to_value(data) { + Ok(value) => Some(value), + Err(err) => { + tracing::warn!( + ?err, + ?source, + "Unable to serialize error data for reason: {reason}" + ); + None + } }), reason: reason.to_owned(), code, source, + severity, } } @@ -53,6 +109,14 @@ impl HTTPError { Self::new(ErrorCode::Internal, "internal", Some(err), None::<()>) } + pub fn not_found( + reason: &str, + source: Option>, + data: Option, + ) -> HTTPError { + Self::new(ErrorCode::NotFound, reason, source, data) + } + pub fn bad_request( reason: &str, source: Option>, @@ -119,7 +183,7 @@ impl actix_web::error::ResponseError for HTTPError { fn error_response(&self) -> HttpResponse { let error = ErrorOutput { error: ErrorDetail { - code: self.code.to_string(), + code: self.code, reason: self.reason.clone(), message: self.message(), data: self.data.clone(), @@ -136,6 +200,19 @@ impl actix_web::error::ResponseError for HTTPError { } } +impl From for ErrorOutput { + fn from(value: HTTPError) -> Self { + ErrorOutput { + error: ErrorDetail { + code: value.code, + reason: value.reason.clone(), + message: value.message(), + data: value.data.clone(), + }, + } + } +} + impl From for HTTPError { fn from(err: eyre::Error) -> Self { HTTPError::new( @@ -147,6 +224,16 @@ impl From for HTTPError { } } +impl From> for HTTPError +where + E: Into, +{ + fn from(err: Contextful) -> Self { + let (_, source) = err.into_parts(); + source.into() + } +} + pub async fn not_found_error_handler() -> impl Responder { let error = HTTPError::new( ErrorCode::NotFound, // Assuming you have this variant defined. @@ -156,3 +243,34 @@ pub async fn not_found_error_handler() -> impl Responder { ); error.error_response() // Returns HttpResponse with JSON error. } + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug)] + struct FailsSerializationAtRuntime; + + impl Serialize for FailsSerializationAtRuntime { + fn serialize(&self, _serializer: S) -> Result + where + S: serde::Serializer, + { + Err(serde::ser::Error::custom( + "this fails serialisation at runtime", + )) + } + } + + #[test] + fn test_creating_http_error_from_unserialisable_data_should_return_none_for_data() { + let err = HTTPError::new( + ErrorCode::Internal, + "failed-to-serialize", + None, + Some(FailsSerializationAtRuntime), + ); + + assert!(err.data.is_none()); + } +} diff --git a/pkg/rpc/src/lib.rs b/pkg/rpc/src/lib.rs index 19057c6..3fa9551 100644 --- a/pkg/rpc/src/lib.rs +++ b/pkg/rpc/src/lib.rs @@ -1,7 +1,14 @@ #![warn(clippy::unwrap_used, clippy::expect_used)] #![deny(clippy::disallowed_methods)] +extern crate self as rpc; pub mod code; pub mod error; pub mod longpoll; pub mod middleware; pub mod tracing; + +#[cfg(test)] +mod tests; + +// Re-export the HTTPErrorConversion macro +pub use rpc_error_convert::HTTPErrorConversion; diff --git a/pkg/rpc/src/longpoll.rs b/pkg/rpc/src/longpoll.rs index 4e9834d..cf348f1 100644 --- a/pkg/rpc/src/longpoll.rs +++ b/pkg/rpc/src/longpoll.rs @@ -1,13 +1,13 @@ use crate::error::HTTPError; -use actix_web::http::header::LAST_MODIFIED; +pub use actix_web::http::header::LAST_MODIFIED; use actix_web::{HttpResponse, Responder}; -use chrono::{DateTime, Utc}; +use chrono::{DateTime, SecondsFormat, Utc}; use eyre::Result; use serde::Serialize; use std::future::Future; use std::time::Duration; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum PollData { Modified { data: T, @@ -45,7 +45,7 @@ where return Ok(PollData::Modified { data, modified_at: Some(modified_at), - }) + }); } Ok(None) => {} Err(e) => return Err(e), @@ -75,7 +75,10 @@ impl Responder for PollData { PollData::Modified { data, modified_at } => { let mut res = HttpResponse::Ok(); if let Some(modified_at) = modified_at { - res.insert_header((LAST_MODIFIED, modified_at.to_rfc2822())); + res.insert_header(( + LAST_MODIFIED, + modified_at.to_rfc3339_opts(SecondsFormat::Micros, true), + )); res.insert_header(( "Last-Modified-Unix", modified_at.timestamp_micros().to_string(), diff --git a/pkg/rpc/src/middleware.rs b/pkg/rpc/src/middleware.rs index 4518e35..5471932 100644 --- a/pkg/rpc/src/middleware.rs +++ b/pkg/rpc/src/middleware.rs @@ -1,12 +1,41 @@ -use std::future::{ready, Ready}; +use std::future::{Ready, ready}; -use crate::error::HTTPError; +use crate::error::{HTTPError, Severity}; use actix_web::{ - dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error, ResponseError, + dev::{Service, ServiceRequest, ServiceResponse, Transform, forward_ready}, }; use futures_util::future::LocalBoxFuture; -use tracing::error; +use tracing::{error, warn}; + +fn log_http_error(severity: &Severity, err: &HTTPError, path: &str, method: &str) { + match severity { + Severity::Warn => { + warn!( + path, + method, + ?err, + code = err.code.to_string(), + data = ?err.data, + report = err.report(), + is_request_error = true, // for filtering in sentry_layer + "HTTP Error" + ); + } + Severity::Error => { + error!( + path, + method, + ?err, + code = err.code.to_string(), + data = ?err.data, + report = err.report(), + is_request_error = true, // for filtering in sentry_layer + "HTTP Error" + ); + } + } +} pub struct Middleware; @@ -57,19 +86,16 @@ where // send 5XX errors to Sentry if status_code >= 500 { - sentry::capture_error(&err); + let mut e = sentry::event_from_error(&err); + // invert the errors for better error naming + e.exception.values.reverse(); + // inject the url path and method + e.tags.insert("path".into(), path.clone()); + e.tags.insert("method".into(), method.clone()); + sentry::capture_event(e); } - error!( - path, - method, - ?err, - code = err.code.to_string(), - data = ?err.data, - report = err.report(), - is_request_error = true, // for filtering in sentry_layer - "HTTP Error" - ); + log_http_error(&err.severity, err, &path, &method); } else { error!(path, method, ?err, "Unhandled server error"); } diff --git a/pkg/rpc/src/tests/fixtures.rs b/pkg/rpc/src/tests/fixtures.rs new file mode 100644 index 0000000..1b7c1b0 --- /dev/null +++ b/pkg/rpc/src/tests/fixtures.rs @@ -0,0 +1,88 @@ +use rpc_error_convert::HTTPErrorConversion; +use serde::{Deserialize, Serialize}; + +use crate::code::ErrorCode; +use crate::error::{ErrorOutput, HTTPError, TryFromHTTPError}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct TestUserData { + pub id: u64, + pub username: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub struct ValidationDetails { + pub field: String, + pub message: String, +} + +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize, PartialEq, +)] +pub enum SubError { + #[permission_denied("sub-permission-denied")] + #[error("[rpc/tests] sub permission denied")] + PermissionDenied, + + // Skipping Contextful because no extra context is needed in tests. + #[delegate] + #[error("[rpc/tests] delegate sub sub")] + SubDelegate(#[from] SubSubError), +} + +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize, PartialEq, +)] +pub enum SubSubError { + #[permission_denied("sub-sub-permission-denied")] + #[error("[rpc/tests] sub sub permission denied")] + PermissionIsReallyDenied, +} + +#[derive( + Debug, Clone, thiserror::Error, HTTPErrorConversion, Serialize, Deserialize, PartialEq, +)] +pub enum TestAppError { + #[bad_request("generic-error")] + #[error("[rpc/tests] generic error occurred")] + GenericError, + + #[not_found("user-not-found")] + #[error("[rpc/tests] user not found: {0:?}")] + UserNotFound(TestUserData), + + #[bad_request("validation-failed")] + #[error("[rpc/tests] validation failed")] + ValidationFailed(String, u32, bool), + + #[already_exists("duplicate-user")] + #[error("[rpc/tests] duplicate user with id {id} and email {email}")] + DuplicateUser { + /// User ID that already exists + id: u64, + /// Email address associated with the duplicate user + email: String, + }, + + #[failed_precondition("complex-error")] + #[error("[rpc/tests] complex error")] + ComplexError { + /// Error code for the complex error + code: i32, + /// Whether the system is active + active: bool, + /// Optional additional details about the error + details: Option, + /// Optional validation metadata + metadata: Option, + }, + + #[bad_request("warn-severity", severity = "warn")] + #[error("[rpc/tests] warn severity error")] + WarnSeverity, + + // Skipping Contextful because no extra context is needed in tests. + #[delegate] + #[error("[rpc/tests] delegated error: {0:?}")] + Delegated(#[from] SubError), +} diff --git a/pkg/rpc/src/tests/http_error_conversion_basic.rs b/pkg/rpc/src/tests/http_error_conversion_basic.rs new file mode 100644 index 0000000..783acf4 --- /dev/null +++ b/pkg/rpc/src/tests/http_error_conversion_basic.rs @@ -0,0 +1,180 @@ +use std::convert::TryFrom; + +use serde_json::json; + +use crate::code::ErrorCode; +use crate::error::{ErrorDetail, ErrorOutput, HTTPError, Severity, TryFromHTTPError}; + +use super::fixtures::{TestAppError, TestUserData}; + +#[test] +fn test_unit_variant_conversion() { + let error = TestAppError::GenericError; + let http_error = HTTPError::from(error); + + assert_eq!(http_error.code, ErrorCode::BadRequest); + assert_eq!(http_error.reason, "generic-error"); + assert!(http_error.data.is_none()); + assert!(matches!(http_error.severity, Severity::Error)); + + let http_error = HTTPError::new( + ErrorCode::BadRequest, + "generic-error", + None::>, + None::<()>, + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, TestAppError::GenericError); +} + +#[test] +fn test_single_unnamed_field_conversion() { + let user_data = TestUserData { + id: 42, + username: "testuser".to_string(), + }; + let error = TestAppError::UserNotFound(user_data.clone()); + let http_error = HTTPError::from(error); + + assert_eq!(http_error.code, ErrorCode::NotFound); + assert_eq!(http_error.reason, "user-not-found"); + assert!(http_error.data.is_some()); + + let data_value = http_error.data.unwrap(); + let deserialized = serde_json::from_value::(data_value.clone()).unwrap(); + assert_eq!(deserialized, user_data); + + let http_error = HTTPError::new( + ErrorCode::NotFound, + "user-not-found", + None::>, + Some(data_value), + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, TestAppError::UserNotFound(user_data)); +} + +#[test] +fn test_multiple_unnamed_fields_conversion() { + let error = TestAppError::ValidationFailed("email field".to_string(), 400, true); + let http_error = HTTPError::from(error.clone()); + + assert_eq!(http_error.code, ErrorCode::BadRequest); + assert_eq!(http_error.reason, "validation-failed"); + assert!(http_error.data.is_some()); + assert!(matches!(http_error.severity, Severity::Error)); + + let data_value = http_error.data.unwrap(); + let array = serde_json::from_value::>(data_value.clone()).unwrap(); + assert_eq!(array.len(), 3); + assert_eq!(array[0], json!("email field")); + assert_eq!(array[1], json!(400)); + assert_eq!(array[2], json!(true)); + + let http_error = HTTPError::new( + ErrorCode::BadRequest, + "validation-failed", + None::>, + Some(data_value), + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, error); +} + +#[test] +fn test_warn_severity_override() { + let error = TestAppError::WarnSeverity; + let http_error = HTTPError::from(error); + + assert_eq!(http_error.code, ErrorCode::BadRequest); + assert_eq!(http_error.reason, "warn-severity"); + assert!(http_error.data.is_none()); + assert!(matches!(http_error.severity, Severity::Warn)); + + let http_error = HTTPError::new( + ErrorCode::BadRequest, + "warn-severity", + None::>, + None::<()>, + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, TestAppError::WarnSeverity); +} + +#[test] +fn test_from_error_output() { + let error_output = ErrorOutput { + error: ErrorDetail { + code: ErrorCode::AlreadyExists, + reason: "duplicate-user".to_string(), + message: "User already exists".to_string(), + data: Some(json!({ + "id": 777, + "email": "output@example.com" + })), + }, + }; + + let result = TestAppError::try_from(error_output); + assert!(result.is_ok()); + assert_eq!( + result.unwrap(), + TestAppError::DuplicateUser { + id: 777, + email: "output@example.com".to_string(), + } + ); +} + +#[test] +fn test_missing_data_error() { + let http_error = HTTPError::new( + ErrorCode::NotFound, + "user-not-found", + None::>, + None::<()>, + ); + + let result = TestAppError::try_from(http_error); + assert!(result.is_err()); + match result.unwrap_err() { + TryFromHTTPError::MissingData => {} + _ => panic!("Expected MissingData error"), + } +} + +#[test] +fn test_unknown_reason_error() { + let http_error = HTTPError::new( + ErrorCode::BadRequest, + "unknown-error-code", + None::>, + None::<()>, + ); + + let result = TestAppError::try_from(http_error); + assert!(result.is_err()); + match result.unwrap_err() { + TryFromHTTPError::UnknownReason(reason) => { + assert_eq!(reason, "unknown-error-code"); + } + _ => panic!("Expected UnknownReason error"), + } +} + +#[test] +fn test_deserialization_error() { + let http_error = HTTPError::new( + ErrorCode::NotFound, + "user-not-found", + None::>, + Some(json!("invalid_data_type")), + ); + + let result = TestAppError::try_from(http_error); + assert!(result.is_err()); + match result.unwrap_err() { + TryFromHTTPError::DeserializationError => {} + _ => panic!("Expected DeserializationError"), + } +} diff --git a/pkg/rpc/src/tests/http_error_conversion_complex.rs b/pkg/rpc/src/tests/http_error_conversion_complex.rs new file mode 100644 index 0000000..408ca88 --- /dev/null +++ b/pkg/rpc/src/tests/http_error_conversion_complex.rs @@ -0,0 +1,146 @@ +use std::convert::TryFrom; + +use serde_json::json; + +use crate::code::ErrorCode; +use crate::error::HTTPError; + +use super::fixtures::{ + ComplexErrorData, DuplicateUserData, TestAppError, ValidationDetails, ValidationFailedData, +}; + +#[test] +fn test_named_fields_conversion() { + let error = TestAppError::DuplicateUser { + id: 999, + email: "test@example.com".to_string(), + }; + let http_error = HTTPError::from(error.clone()); + + assert_eq!(http_error.code, ErrorCode::AlreadyExists); + assert_eq!(http_error.reason, "duplicate-user"); + assert!(http_error.data.is_some()); + + let data_value = http_error.data.unwrap(); + assert_eq!( + data_value, + json!({ + "id": 999, + "email": "test@example.com" + }) + ); + + let http_error = HTTPError::new( + ErrorCode::AlreadyExists, + "duplicate-user", + None::>, + Some(data_value), + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, error); +} + +#[test] +fn test_complex_named_fields_with_optionals() { + let error = TestAppError::ComplexError { + code: -100, + active: false, + details: Some("Additional context".to_string()), + metadata: Some(ValidationDetails { + field: "username".to_string(), + message: "Too short".to_string(), + }), + }; + let http_error = HTTPError::from(error.clone()); + + assert_eq!(http_error.code, ErrorCode::FailedPrecondition); + assert_eq!(http_error.reason, "complex-error"); + assert!(http_error.data.is_some()); + + let data_value = http_error.data.unwrap(); + let expected = json!({ + "code": -100, + "active": false, + "details": "Additional context", + "metadata": { + "field": "username", + "message": "Too short" + } + }); + assert_eq!(data_value, expected); + + let http_error = HTTPError::new( + ErrorCode::FailedPrecondition, + "complex-error", + None::>, + Some(data_value), + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, error); +} + +#[test] +fn test_complex_named_fields_with_none_values() { + let error = TestAppError::ComplexError { + code: 50, + active: true, + details: None, + metadata: None, + }; + let http_error = HTTPError::from(error.clone()); + + let data_value = http_error.data.unwrap(); + assert_eq!( + data_value, + json!({ + "code": 50, + "active": true, + "details": null, + "metadata": null + }) + ); + + let http_error = HTTPError::new( + ErrorCode::FailedPrecondition, + "complex-error", + None::>, + Some(data_value), + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, error); +} + +#[test] +fn test_generated_structs() { + let validation_data = ValidationFailedData("test".to_string(), 123, false); + let json_value = serde_json::to_value(&validation_data).unwrap(); + let deserialized = serde_json::from_value::(json_value).unwrap(); + assert_eq!(deserialized.0, "test"); + assert_eq!(deserialized.1, 123); + assert!(!deserialized.2); + + let user_data = DuplicateUserData { + id: 456, + email: "struct@test.com".to_string(), + }; + let json_value = serde_json::to_value(&user_data).unwrap(); + let deserialized = serde_json::from_value::(json_value).unwrap(); + assert_eq!(deserialized.id, 456); + assert_eq!(deserialized.email, "struct@test.com"); + + let complex_data = ComplexErrorData { + code: 789, + active: true, + details: None, + metadata: Some(ValidationDetails { + field: "test".to_string(), + message: "msg".to_string(), + }), + }; + let json_value = serde_json::to_value(&complex_data).unwrap(); + let deserialized = serde_json::from_value::(json_value).unwrap(); + assert_eq!(deserialized.code, 789); + assert!(deserialized.active); + assert_eq!(deserialized.details, None); + assert!(deserialized.metadata.is_some()); +} diff --git a/pkg/rpc/src/tests/http_error_conversion_delegate.rs b/pkg/rpc/src/tests/http_error_conversion_delegate.rs new file mode 100644 index 0000000..f8d1595 --- /dev/null +++ b/pkg/rpc/src/tests/http_error_conversion_delegate.rs @@ -0,0 +1,47 @@ +use std::convert::TryFrom; + +use crate::code::ErrorCode; +use crate::error::HTTPError; + +use super::fixtures::{SubError, SubSubError, TestAppError}; + +#[test] +fn test_delegate_conversion_roundtrip() { + let sub_error = SubError::PermissionDenied; + let error = TestAppError::Delegated(sub_error.clone()); + let http_error = HTTPError::from(error.clone()); + + assert_eq!(http_error.code, ErrorCode::PermissionDenied); + assert_eq!(http_error.reason, "sub-permission-denied"); + assert!(http_error.data.is_none()); + + let http_error = HTTPError::new( + ErrorCode::PermissionDenied, + "sub-permission-denied", + None::>, + None::<()>, + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, error); +} + +#[test] +fn test_delegate_multi_depth_conversion_roundtrip() { + let sub_error = SubSubError::PermissionIsReallyDenied; + let delegated = SubError::SubDelegate(sub_error); + let error = TestAppError::Delegated(delegated); + let http_error = HTTPError::from(error.clone()); + + assert_eq!(http_error.code, ErrorCode::PermissionDenied); + assert_eq!(http_error.reason, "sub-sub-permission-denied"); + assert!(http_error.data.is_none()); + + let http_error = HTTPError::new( + ErrorCode::PermissionDenied, + "sub-sub-permission-denied", + None::>, + None::<()>, + ); + let recovered = TestAppError::try_from(http_error).unwrap(); + assert_eq!(recovered, error); +} diff --git a/pkg/rpc/src/tests/mod.rs b/pkg/rpc/src/tests/mod.rs new file mode 100644 index 0000000..58ec3c5 --- /dev/null +++ b/pkg/rpc/src/tests/mod.rs @@ -0,0 +1,4 @@ +mod fixtures; +mod http_error_conversion_basic; +mod http_error_conversion_complex; +mod http_error_conversion_delegate; diff --git a/pkg/rpc/src/tracing.rs b/pkg/rpc/src/tracing.rs index 14c1a35..6ae681d 100644 --- a/pkg/rpc/src/tracing.rs +++ b/pkg/rpc/src/tracing.rs @@ -1,14 +1,19 @@ +// lint-long-file-override allow-max-lines=300 use clap::ValueEnum; +use opentelemetry::trace::TracerProvider; use opentelemetry_otlp::{ - OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, + MetricExporter, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, + OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, SpanExporter, }; -use opentelemetry_sdk::trace::{RandomIdGenerator, Sampler}; -use sentry_tracing::{event_from_event, EventMapping}; +use opentelemetry_sdk::{ + metrics::SdkMeterProvider, + trace::{RandomIdGenerator, Sampler, SdkTracerProvider}, +}; +use sentry_tracing::{EventMapping, event_from_event}; use serde::{Deserialize, Serialize}; use std::{borrow::Cow, fmt}; use tracing::field::Visit; -use tracing_subscriber::{filter::FilterFn, layer::SubscriberExt, Layer}; +use tracing_subscriber::{Layer, filter::FilterFn, layer::SubscriberExt}; #[derive( ValueEnum, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Deserialize, Serialize, @@ -101,15 +106,14 @@ pub fn setup_tracing( let use_otel_tracing = std::env::var(OTEL_EXPORTER_OTLP_ENDPOINT).is_ok() || std::env::var(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT).is_ok(); let telemetry = if use_otel_tracing { - let trace_config = opentelemetry_sdk::trace::config() + let trace_exporter = SpanExporter::builder().with_tonic().build()?; + let tracer_provider = SdkTracerProvider::builder() .with_sampler(Sampler::AlwaysOn) - .with_id_generator(RandomIdGenerator::default()); - - let tracer = opentelemetry_otlp::new_pipeline() - .tracing() - .with_exporter(opentelemetry_otlp::new_exporter().tonic()) - .with_trace_config(trace_config) - .install_batch(opentelemetry_sdk::runtime::Tokio)?; + .with_id_generator(RandomIdGenerator::default()) + .with_batch_exporter(trace_exporter) + .build(); + opentelemetry::global::set_tracer_provider(tracer_provider.clone()); + let tracer = tracer_provider.tracer(env!("CARGO_PKG_NAME")); Some( tracing_opentelemetry::layer() @@ -125,10 +129,10 @@ pub fn setup_tracing( let use_otel_metrics = std::env::var(OTEL_EXPORTER_OTLP_ENDPOINT).is_ok() || std::env::var(OTEL_EXPORTER_OTLP_METRICS_ENDPOINT).is_ok(); let metrics = if use_otel_metrics { - let meter_provider = opentelemetry_otlp::new_pipeline() - .metrics(opentelemetry_sdk::runtime::Tokio) - .with_exporter(opentelemetry_otlp::new_exporter().tonic()) - .build()?; + let metric_exporter = MetricExporter::builder().with_tonic().build()?; + let meter_provider = SdkMeterProvider::builder() + .with_periodic_exporter(metric_exporter) + .build(); opentelemetry::global::set_meter_provider(meter_provider.clone()); Some(tracing_opentelemetry::MetricsLayer::new(meter_provider)) @@ -154,7 +158,7 @@ pub fn setup_tracing( EventMapping::Ignore } else { // send the original `sentry` event unchanged - EventMapping::Event(event_from_event(evt, ctx)) + EventMapping::Event(event_from_event(evt, &ctx)) } }); diff --git a/pkg/serde_yaml/Cargo.toml b/pkg/serde_yaml/Cargo.toml new file mode 100644 index 0000000..2f0b0c2 --- /dev/null +++ b/pkg/serde_yaml/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "serde_yaml" +version = "0.9.36" +edition = "2024" +description = "Shim crate that re-exports serde_yaml_ng for the workspace" +license = "MIT OR Apache-2.0" + +[lib] +path = "lib.rs" + +[dependencies] +serde_yaml_ng = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/serde_yaml/lib.rs b/pkg/serde_yaml/lib.rs new file mode 100644 index 0000000..45af9f1 --- /dev/null +++ b/pkg/serde_yaml/lib.rs @@ -0,0 +1,5 @@ +//! Local shim crate that re-exports `serde_yaml_ng` under the historic +//! `serde_yaml` crate name so upstream dependencies continue to compile. + +pub use serde_yaml_ng::*; +pub use serde_yaml_ng::{mapping, value, with}; diff --git a/pkg/smirk/Cargo.toml b/pkg/smirk/Cargo.toml index 7cc27d7..ab9b44a 100644 --- a/pkg/smirk/Cargo.toml +++ b/pkg/smirk/Cargo.toml @@ -1,25 +1,18 @@ [package] name = "smirk" version = "1.3.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -zk-primitives = { workspace = true } +element = { workspace = true } +hash = { workspace = true } bitvec = { workspace = true } -ethnum = { workspace = true } -ff = { workspace = true } -halo2_gadgets = { workspace = true } -halo2_proofs = { workspace = true } -halo2curves = { workspace = true } -poseidon-circuit = { workspace = true } -proptest = { workspace = true, optional = true } +proptest = { workspace = true } rand = { workspace = true } -rand_chacha = { workspace = true } -rocksdb = { workspace = true, optional = true } -serde = { workspace = true, optional = true, features = ["derive"] } +rocksdb = { workspace = true } thiserror = { workspace = true } borsh = { workspace = true } wire-message = { workspace = true } @@ -27,24 +20,34 @@ strum = { workspace = true } rayon = { workspace = true } dashmap = { workspace = true } tracing = { workspace = true } - +workspace-hack.workspace = true [dev-dependencies] -proptest = { workspace = true } serde_json = { workspace = true } test-strategy = { workspace = true } tempdir = { workspace = true } benchy = { workspace = true } -zk-primitives = { workspace = true, features = ["test-api"] } +hash = { workspace = true, features = ["test-api"] } expect-test = { workspace = true } +node-client-http = { workspace = true } +primitives = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread"] } +reqwest = { workspace = true } [features] -default = ["serde", "storage"] - -storage = ["dep:rocksdb"] -serde = ["dep:serde", "zk-primitives/serde", "zk-primitives/proptest"] slow-storage-tests = [] [[bench]] name = "storage_load" harness = false + +[[bench]] +name = "root_hash_with" +harness = false + +[[bench]] +name = "insert_batch_mainnet" +harness = false + +[package.metadata.cargo-machete] +ignored = ["strum"] diff --git a/pkg/smirk/README.md b/pkg/smirk/README.md new file mode 100644 index 0000000..98b0a46 --- /dev/null +++ b/pkg/smirk/README.md @@ -0,0 +1,23 @@ +# Smirk + +Sparse Merkle tree implementation with batch operations and storage management. + +## Overview + +This package provides a high-performance sparse Merkle tree implementation for the zk-rollup system. + +## Features + +- Sparse Merkle tree operations +- Batch processing +- Storage management +- Hash caching +- Tree iteration +- Property testing + +## Benchmarks + +- `cargo bench -p smirk --bench insert_batch_mainnet` downloads a mainnet snapshot/diff from + `validators.mainnet.payy.network` and benchmarks tree construction plus a single `insert_batch` + call (download time excluded). Update `TARGET_HEIGHT` in + `pkg/smirk/benches/insert_batch_mainnet.rs` if needed. diff --git a/pkg/smirk/benches/insert_batch_mainnet.rs b/pkg/smirk/benches/insert_batch_mainnet.rs new file mode 100644 index 0000000..3f6a8a3 --- /dev/null +++ b/pkg/smirk/benches/insert_batch_mainnet.rs @@ -0,0 +1,109 @@ +use std::hint::black_box; + +use benchy::{BenchmarkRun, benchmark}; +use smirk::{Batch, Tree, storage::Persistent}; +use tempdir::TempDir; + +const TREE_DEPTH: usize = 161; + +mod data_download { + use element::Element; + use node_client_http::NodeClientHttp; + use primitives::block_height::BlockHeight; + use reqwest::Url; + use std::sync::OnceLock; + + const TARGET_HEIGHT: u64 = 13_226_573; // non-empty diff as of 2026-02-04 + const BASE_URL: &str = "https://validators.mainnet.payy.network/v0"; + + pub fn test_data() -> &'static (Vec, Vec, Vec) { + TEST_DATA.get_or_init(download_data) + } + + static TEST_DATA: OnceLock<(Vec, Vec, Vec)> = OnceLock::new(); + + fn download_data() -> (Vec, Vec, Vec) { + let rt = tokio::runtime::Runtime::new().unwrap(); + rt.block_on(async { + let client = NodeClientHttp::new(Url::parse(BASE_URL).unwrap()); + let snapshot = client + .block_tree(BlockHeight(TARGET_HEIGHT - 1)) + .await + .unwrap(); + let diff = client + .block_tree_diff(BlockHeight(TARGET_HEIGHT), BlockHeight(TARGET_HEIGHT - 1)) + .await + .unwrap(); + (snapshot.elements, diff.diff.additions, diff.diff.removals) + }) + } +} + +#[benchmark] +pub fn build_tree_from_snapshot(b: &mut BenchmarkRun) { + let (elements, _, _) = data_download::test_data(); + + b.run(|| { + let mut tree = Tree::::new(); + let batch = Batch::::from_entries( + elements.iter().copied().map(|element| (element, ())), + [], + ) + .unwrap(); + tree.insert_batch(batch, |_| {}, |_| {}).unwrap(); + black_box(tree); + }); +} + +#[benchmark] +pub fn insert_batch_single_block(b: &mut BenchmarkRun) { + let (elements, additions, removals) = data_download::test_data(); + + let mut tree = Tree::::new(); + let batch = Batch::::from_entries( + elements.iter().copied().map(|element| (element, ())), + [], + ) + .unwrap(); + tree.insert_batch(batch, |_| {}, |_| {}).unwrap(); + + b.run(|| { + let batch = Batch::::from_entries( + black_box(additions) + .iter() + .copied() + .map(|element| (element, ())), + black_box(removals).iter().copied(), + ) + .unwrap(); + + tree.insert_batch(batch, |_| {}, |_| {}).unwrap(); + black_box(tree); + }); +} + +#[benchmark] +pub fn load_tree_from_rocksdb(b: &mut BenchmarkRun) { + let (elements, _, _) = data_download::test_data(); + let dir = TempDir::new("smirk-benchmark").unwrap(); + + let batch = Batch::::from_entries( + elements.iter().copied().map(|element| (element, ())), + [], + ) + .unwrap(); + let mut persistent = Persistent::::new(dir.path()).unwrap(); + persistent.insert_batch(batch).unwrap(); + drop(persistent); + + b.run(|| { + let loaded = Persistent::::load(dir.path()).unwrap(); + black_box(loaded); + }); +} + +benchy::main!( + build_tree_from_snapshot, + insert_batch_single_block, + load_tree_from_rocksdb +); diff --git a/pkg/smirk/benches/root_hash_with.rs b/pkg/smirk/benches/root_hash_with.rs new file mode 100644 index 0000000..8cb42eb --- /dev/null +++ b/pkg/smirk/benches/root_hash_with.rs @@ -0,0 +1,64 @@ +use std::hint::black_box; + +use benchy::{BenchmarkRun, benchmark}; +use element::Element; +use rand::thread_rng; +use smirk::{Batch, Tree}; + +const TREE_DEPTH: usize = 160; +const TREE_SIZE: usize = 50_000; + +fn populate_tree() -> Tree { + let mut tree = Tree::::new(); + let mut batch = Batch::with_capacity(TREE_SIZE); + let mut rng = thread_rng(); + + while batch.insert_elements().count() < TREE_SIZE { + let candidate = Element::secure_random(&mut rng); + if batch.insert(candidate, ()).is_ok() { + continue; + } + } + + tree.insert_batch(batch, |_| {}, |_| {}).unwrap(); + + tree +} + +fn random_insert_elements(tree: &Tree) -> [Element; 2] { + let mut inserts = Vec::with_capacity(2); + let mut rng = thread_rng(); + + while inserts.len() < 2 { + let candidate = Element::secure_random(&mut rng); + if inserts.contains(&candidate) { + continue; + } + + if tree.contains_element(&candidate) { + continue; + } + + inserts.push(candidate); + } + + [inserts[0], inserts[1]] +} + +#[benchmark] +pub fn root_hash_with_two_inserts_one_remove(b: &mut BenchmarkRun) { + let tree = populate_tree(); + let insert_elements = random_insert_elements(&tree); + let remove_element = tree + .elements() + .next() + .map(|(element, _)| *element) + .expect("tree populated"); + let remove_elements = [remove_element]; + + b.run(|| { + black_box(tree.root_hash_with(&insert_elements, &remove_elements)); + }); +} + +benchy::main!(root_hash_with_two_inserts_one_remove); diff --git a/pkg/smirk/benches/storage_load.rs b/pkg/smirk/benches/storage_load.rs index fce1a2a..b44ad10 100644 --- a/pkg/smirk/benches/storage_load.rs +++ b/pkg/smirk/benches/storage_load.rs @@ -1,8 +1,10 @@ use std::{hint::black_box, process::Command}; -use benchy::{benchmark, BenchmarkRun}; +use benchy::{BenchmarkRun, benchmark}; +use element::Element; +use hash::hash_merge; use rand::thread_rng; -use smirk::{hash_merge, storage::Persistent, Batch, Element}; +use smirk::{Batch, storage::Persistent}; use tempdir::TempDir; fn make_batch(n: usize) -> Batch<160, ()> { @@ -31,13 +33,10 @@ pub fn hash_merge_1_000_000(b: &mut BenchmarkRun) { } }); - b.metrics - .insert("hash_count".into(), zk_primitives::hash_count()); + b.metrics.insert("hash_count".into(), hash::hash_count()); - b.metrics.insert( - "hash_element_count".into(), - zk_primitives::hash_element_count(), - ); + b.metrics + .insert("hash_element_count".into(), hash::hash_element_count()); } #[benchmark] @@ -63,13 +62,10 @@ pub fn hash_merge_1_000_000_cached(b: &mut BenchmarkRun) { } }); - b.metrics - .insert("hash_count".into(), zk_primitives::hash_count()); + b.metrics.insert("hash_count".into(), hash::hash_count()); - b.metrics.insert( - "hash_element_count".into(), - zk_primitives::hash_element_count(), - ); + b.metrics + .insert("hash_element_count".into(), hash::hash_element_count()); } #[benchmark] @@ -83,13 +79,10 @@ pub fn create_tree(b: &mut BenchmarkRun) { black_box(tree); }); - b.metrics - .insert("hash_count".into(), zk_primitives::hash_count()); + b.metrics.insert("hash_count".into(), hash::hash_count()); - b.metrics.insert( - "hash_element_count".into(), - zk_primitives::hash_element_count(), - ); + b.metrics + .insert("hash_element_count".into(), hash::hash_element_count()); } #[benchmark] @@ -115,13 +108,10 @@ pub fn storage_load(b: &mut BenchmarkRun) { black_box(tree); }); - b.metrics - .insert("hash_count".into(), zk_primitives::hash_count()); + b.metrics.insert("hash_count".into(), hash::hash_count()); - b.metrics.insert( - "hash_element_count".into(), - zk_primitives::hash_element_count(), - ); + b.metrics + .insert("hash_element_count".into(), hash::hash_element_count()); } benchy::main!( diff --git a/pkg/smirk/src/batch/merge.rs b/pkg/smirk/src/batch/merge.rs index a2603cb..9233225 100644 --- a/pkg/smirk/src/batch/merge.rs +++ b/pkg/smirk/src/batch/merge.rs @@ -1,4 +1,4 @@ -use crate::{tree, Batch, Collision, CollisionError}; +use crate::{Batch, Collision, CollisionError, tree}; impl Batch { /// Merge `other` into `self` @@ -8,7 +8,7 @@ impl Batch { /// /// If there are collisions, they will be returned in a [`Vec`] /// - /// [`Element`]: crate::Element + /// [`Element`]: element::Element pub fn merge(mut self, other: Self) -> Result { let colliding_lsbs = self.lsbs.iter().filter(|lsb| other.lsbs.contains(lsb)); @@ -41,9 +41,9 @@ impl Batch { #[cfg(test)] mod tests { + use element::Element; use proptest::prop_assert_eq; use test_strategy::proptest; - use zk_primitives::Element; use crate::batch; @@ -70,8 +70,8 @@ mod tests { 4 => "bar", }; - let mut entries: Vec<_> = c.entries().collect(); - let mut expected_entries: Vec<_> = expected.entries().collect(); + let mut entries: Vec<_> = c.insert_entries().to_vec(); + let mut expected_entries: Vec<_> = expected.insert_entries().to_vec(); entries.sort_by_key(|tuple| tuple.0); expected_entries.sort_by_key(|tuple| tuple.0); @@ -81,13 +81,16 @@ mod tests { #[proptest] fn merge_batches(batch1: Batch<64, Element>, batch2: Batch<64, Element>) { - let expected_elements: Vec<_> = batch1.elements().chain(batch2.elements()).collect(); + let expected_elements: Vec<_> = batch1 + .insert_elements() + .chain(batch2.insert_elements()) + .collect(); let result = batch1.merge(batch2); proptest::prop_assume!(result.is_ok()); let merged = result.unwrap(); - let elements: Vec<_> = merged.elements().collect(); + let elements: Vec<_> = merged.insert_elements().collect(); prop_assert_eq!(elements, expected_elements); } diff --git a/pkg/smirk/src/batch/mod.rs b/pkg/smirk/src/batch/mod.rs index 30bf1d7..d987898 100644 --- a/pkg/smirk/src/batch/mod.rs +++ b/pkg/smirk/src/batch/mod.rs @@ -1,10 +1,9 @@ use std::collections::HashSet; -use zk_primitives::{Element, Lsb}; +use element::{Element, Lsb}; -use crate::{tree, Collision, CollisionError}; +use crate::{Collision, CollisionError, tree}; -#[cfg(any(test, feature = "proptest"))] mod proptest; mod merge; @@ -19,6 +18,7 @@ mod merge; #[must_use = "a `Batch` does nothing unless inserted"] pub struct Batch { pub(crate) entries: Vec<(Element, V)>, + pub(crate) remove_entries: Vec, /// The LSBs of the elements that have been inserted, for efficient checking of new entries pub(crate) lsbs: HashSet, } @@ -27,6 +27,7 @@ impl Default for Batch { fn default() -> Self { Self { entries: Vec::new(), + remove_entries: Vec::new(), lsbs: HashSet::new(), } } @@ -37,6 +38,7 @@ impl Batch { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut batch = Batch::<64, String>::new(); /// /// batch.insert(Element::new(1), String::from("hello")); @@ -46,6 +48,7 @@ impl Batch { /// Alternatively, you can use the [`batch!`] macro for a more concise syntax: /// ```rust /// # use smirk::*; + /// # use element::Element; /// let batch: Batch<64, _> = batch! { /// 1 => String::from("hello"), /// 2 => String::from("world"), @@ -61,6 +64,7 @@ impl Batch { pub fn with_capacity(capacity: usize) -> Self { Self { entries: Vec::with_capacity(capacity), + remove_entries: Vec::new(), lsbs: HashSet::with_capacity(capacity), } } @@ -68,7 +72,7 @@ impl Batch { /// Check whether this batch is empty #[must_use] pub fn is_empty(&self) -> bool { - self.entries.is_empty() + self.entries.is_empty() && self.remove_entries.is_empty() } /// Insert a key-value pair into this [`Batch`] @@ -79,7 +83,7 @@ impl Batch { /// Note that, unlike [`Tree::insert`], no hashing takes place when inserting into a [`Batch`], /// so performance is very good /// - /// [least significant bits]: zk_primitives::Lsb + /// [least significant bits]: element::Lsb /// [`Tree::insert`]: crate::Tree::insert pub fn insert(&mut self, element: Element, value: V) -> Result<(), CollisionError> { let lsb = element.lsb(DEPTH - 1); @@ -106,46 +110,67 @@ impl Batch { Ok(()) } - #[cfg(test)] - pub(crate) fn remove(&mut self, element: Element) { + /// An element to be removed from the tree that this batch will be applied to. + pub fn remove(&mut self, element: Element) -> Result<(), CollisionError> { let lsb = element.lsb(DEPTH - 1); - self.entries.retain(|(e, _)| *e != element); - self.lsbs.remove(&lsb); + if self.lsbs.contains(&lsb) { + let in_tree = self.find_element_with_lsb(element.lsb(DEPTH - 1)).unwrap(); + + let collision = Collision { + in_tree, + inserted: element, + depth: DEPTH, + struct_name: tree::StructName::Batch, + }; + + return Err(CollisionError { + collisions: vec![collision], + }); + } + + self.lsbs.insert(lsb); + self.remove_entries.push(element); + + Ok(()) } - /// Get an iterator over the elements that have been inserted into this [`Batch`] - pub fn elements(&self) -> impl Iterator + '_ { + /// Get an iterator over the elements that should be inserted into a tree + pub fn insert_elements(&self) -> impl Iterator + '_ { self.entries.iter().map(|(element, _)| element).copied() } - - /// Get an iterator over the values that have been inserted into this [`Batch`] - pub fn values(&self) -> impl Iterator + '_ { - self.entries.iter().map(|(_, v)| v) + /// Get an iterator over the elements that should be removed from a tree + pub fn remove_elements(&self) -> impl Iterator + '_ { + self.remove_entries.iter().copied() } - /// Get an iterator over the entries that have been inserted into this [`Batch`] - pub fn entries(&self) -> impl Iterator + '_ { - self.entries.iter() + /// Returns the insert entries of this batch + #[must_use] + pub fn insert_entries(&self) -> &[(Element, V)] { + &self.entries } pub(crate) fn find_element_with_lsb(&self, lsb: Lsb) -> Option { - self.elements().find(|e| e.lsb(DEPTH - 1) == lsb) + self.insert_elements() + .chain(self.remove_elements()) + .find(|e| e.lsb(DEPTH - 1) == lsb) } /// Create a [`Batch`] from an [`Iterator`] over tuples of [`Element`]s and values /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let batch = Batch::<64, _>::from_entries([ /// (Element::new(1), 123), /// (Element::new(2), 234), /// (Element::new(3), 345), - /// ]); + /// ], []); /// ``` - pub fn from_entries(entries: I) -> Result + pub fn from_entries(entries: I, remove_entries: RI) -> Result where I: IntoIterator, + RI: IntoIterator, { let mut batch = Self::new(); @@ -153,25 +178,10 @@ impl Batch { batch.insert(element, value)?; } - Ok(batch) - } + for element in remove_entries { + batch.remove(element)?; + } - /// Create a [`Batch`] from an [`Iterator`] of [`Element`]s, using the [`Default`] - /// implementation for the values - /// - /// ```rust - /// # use smirk::*; - /// let batch = Batch::<64, ()>::from_elements([ - /// Element::new(1), - /// Element::new(2), - /// Element::new(3), - /// ]); - /// ``` - pub fn from_elements(entries: I) -> Result - where - I: IntoIterator, - V: Default, - { - Self::from_entries(entries.into_iter().map(|element| (element, V::default()))) + Ok(batch) } } diff --git a/pkg/smirk/src/batch/proptest.rs b/pkg/smirk/src/batch/proptest.rs index 107b4f3..b1f895d 100644 --- a/pkg/smirk/src/batch/proptest.rs +++ b/pkg/smirk/src/batch/proptest.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; +use element::Element; use proptest::{arbitrary::StrategyFor, prelude::*, strategy::Map}; -use zk_primitives::Element; use crate::Batch; diff --git a/pkg/smirk/src/hash.rs b/pkg/smirk/src/hash.rs index 9ddebe6..2c2b107 100644 --- a/pkg/smirk/src/hash.rs +++ b/pkg/smirk/src/hash.rs @@ -1,6 +1,6 @@ use std::sync::OnceLock; -use crate::Element; +use element::Element; const COMPUTE_DEPTH: usize = 257; @@ -38,8 +38,8 @@ fn fallback(depth: usize) -> Element { other => { // if you hit this warning, consider increasing `COMPUTE_DEPTH` above eprintln!("WARNING - using slow fallback for `empty_tree_hash` for depth: {other}"); - let hash = fallback(other - 1); - crate::hash_merge([hash, hash]) + let hashed = fallback(other - 1); + hash::hash_merge([hashed, hashed]) } } } @@ -53,7 +53,7 @@ fn get_cache() -> &'static [Element] { for _ in 1..COMPUTE_DEPTH { let hash = *vec.last().unwrap(); - let new_hash = crate::hash_merge([hash, hash]); + let new_hash = hash::hash_merge([hash, hash]); vec.push(new_hash); } diff --git a/pkg/smirk/src/hash_cache/metrics/mod.rs b/pkg/smirk/src/hash_cache/metrics/mod.rs index bd1b9cd..31dbff0 100644 --- a/pkg/smirk/src/hash_cache/metrics/mod.rs +++ b/pkg/smirk/src/hash_cache/metrics/mod.rs @@ -1,6 +1,6 @@ use std::sync::{ - atomic::{AtomicUsize, Ordering}, Arc, + atomic::{AtomicUsize, Ordering}, }; /// A container for metrics relating to hashing, useful for debugging diff --git a/pkg/smirk/src/hash_cache/mod.rs b/pkg/smirk/src/hash_cache/mod.rs index 7a2086c..1a3b67c 100644 --- a/pkg/smirk/src/hash_cache/mod.rs +++ b/pkg/smirk/src/hash_cache/mod.rs @@ -1,7 +1,8 @@ use std::sync::Arc; -use dashmap::{mapref::entry::Entry, DashMap}; -use zk_primitives::{hash_merge, Element}; +use dashmap::{DashMap, mapref::entry::Entry}; +use element::Element; +use hash::hash_merge; pub use self::metrics::CacheMetrics; @@ -9,7 +10,7 @@ mod metrics; /// A known result of computation [`hash_merge([left, right])`][hash_merge] /// -/// [hash_merge]: zk_primitives::hash_merge +/// [hash_merge]: hash::hash_merge #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct KnownHash { /// The left input [`Element`] @@ -158,12 +159,16 @@ mod tests { cache.hash(Element::new(1), Element::new(2)); cache.hash(Element::new(3), Element::new(4)); - assert!(cache - .inner - .contains_key(&(Element::new(1), Element::new(2)))); - assert!(cache - .inner - .contains_key(&(Element::new(3), Element::new(4)))); + assert!( + cache + .inner + .contains_key(&(Element::new(1), Element::new(2))) + ); + assert!( + cache + .inner + .contains_key(&(Element::new(3), Element::new(4))) + ); assert_eq!(cache.metrics().hashes(), 2); assert_eq!(cache.metrics().cache_hits(), 0); diff --git a/pkg/smirk/src/lib.rs b/pkg/smirk/src/lib.rs index 9b4a5d9..834e852 100644 --- a/pkg/smirk/src/lib.rs +++ b/pkg/smirk/src/lib.rs @@ -8,7 +8,6 @@ #![allow(clippy::single_match_else)] #![allow(clippy::from_iter_instead_of_collect)] #![deny(missing_docs)] -#![feature(once_cell)] // TODO: remove this once we can get to a more recent rustc version //! # Smirk (**S**parse **M**e**RK**le tree) //! @@ -19,6 +18,7 @@ //! //! ```rust //! # use smirk::*; +//! # use element::Element; //! // the tree is generic over the depth, 64 is a good default //! let mut tree = Tree::<64, String>::new(); //! @@ -55,14 +55,16 @@ //! A Smirk tree is represented by a binary tree with a fixed depth controlled by a const generic //! parameter `DEPTH`. Each node of depth `DEPTH` have two children of depth `DEPTH - 1`, except //! for the case of a node with depth `1`, which either contains an [`Element`], or is empty, which -//! is represented by [`Element::NULL_HASH`]. +//! is represented by [`element::Element::NULL_HASH`]. //! //! However, especially if `DEPTH` is small, there may be two elements with the same `DEPTH - 1` //! least significant bits, meaning they would occupy the same slot. This is a collision, and the //! second [`Element`] will fail to insert. //! -//! Because [`Element::NULL_HASH`] is a valid value at any point in the tree, it is considered to +//! Because [`element::Element::NULL_HASH`] is a valid value at any point in the tree, it is considered to //! collide with every value, and cannot be inserted into the tree ever. +//! +//! [`Element`]: element::Element /// APIs relating to batched inserts into [`Tree`]s and [`Persistent`]s /// @@ -74,11 +76,9 @@ mod hash; pub mod hash_cache; mod macros; /// APIs relating to persistence of a [`Tree`] -#[cfg(feature = "storage")] pub mod storage; mod tree; pub use batch::Batch; pub use hash::empty_tree_hash; pub use tree::{Collision, CollisionError, Path, Tree}; -pub use zk_primitives::*; diff --git a/pkg/smirk/src/macros.rs b/pkg/smirk/src/macros.rs index 3a6d4b0..fe95895 100644 --- a/pkg/smirk/src/macros.rs +++ b/pkg/smirk/src/macros.rs @@ -2,7 +2,7 @@ /// /// ```rust /// # use smirk::*; -/// # use zk_primitives::*; +/// # use element::Element; /// let tree: Tree<64, _> = smirk! { /// // the element is converted using Element::from /// 123 => "hello", @@ -53,7 +53,7 @@ macro_rules! smirk { /// /// ```rust /// # use smirk::*; -/// # use zk_primitives::*; +/// # use element::Element; /// let batch: Batch<64, _> = batch! { /// // the element is converted using Element::from /// 123 => "hello", @@ -97,22 +97,18 @@ macro_rules! batch { /// Helper macro to create an [`Element`] /// -/// [`Element`]: zk_primitives::Element +/// [`Element`]: element::Element #[macro_export] macro_rules! element { - ($e:literal) => {{ - zk_primitives::Element::new($e) - }}; - ($e:expr) => {{ - zk_primitives::Element::from($e) - }}; + ($e:literal) => {{ element::Element::new($e) }}; + ($e:expr) => {{ element::Element::from($e) }}; } #[cfg(test)] mod tests { - use zk_primitives::Element; + use element::Element; - use crate::{smirk, Batch, Tree}; + use crate::{Batch, Tree}; type T = Tree<64, i32>; type B = Batch<64, i32>; diff --git a/pkg/smirk/src/storage/batch.rs b/pkg/smirk/src/storage/batch.rs index 2766e2b..7f6f4f2 100644 --- a/pkg/smirk/src/storage/batch.rs +++ b/pkg/smirk/src/storage/batch.rs @@ -8,13 +8,13 @@ use rocksdb::WriteBatch; use wire_message::WireMessage; use crate::{ - storage::format::{ValueFormat, ValueV2}, Batch, + storage::format::{ValueFormat, ValueV2}, }; use super::{ - format::{KeyFormat, KeyV2}, Error, Persistent, + format::{KeyFormat, KeyV2}, }; impl Persistent { @@ -22,6 +22,7 @@ impl Persistent { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// # use smirk::storage::*; /// # let dir = tempdir::TempDir::new("smirk_doctest").unwrap(); /// # let path = dir.path().join("db"); @@ -42,7 +43,8 @@ impl Persistent { return Ok(()); } - let new_kv_pairs: HashMap<_, _> = batch.entries().cloned().collect(); + let new_kv_pairs: HashMap<_, _> = batch.insert_entries().iter().cloned().collect(); + let removed_elements = batch.remove_elements().collect::>(); let hash_changes = Arc::new(Mutex::new(HashMap::new())); self.tree.insert_batch( @@ -78,6 +80,12 @@ impl Persistent { write_batch.delete(old_key.to_bytes().unwrap()); } + for key in removed_elements { + for k in [KeyFormat::V2(KeyV2::Element(key)), KeyFormat::V1(key)] { + write_batch.delete(k.to_bytes().unwrap()); + } + } + for ((left, right), _) in hashes_to_remove { let key = KeyFormat::V2(KeyV2::KnownHash { left, right }); write_batch.delete(key.to_bytes().unwrap()); diff --git a/pkg/smirk/src/storage/format.rs b/pkg/smirk/src/storage/format.rs index 4b51420..4e5b95c 100644 --- a/pkg/smirk/src/storage/format.rs +++ b/pkg/smirk/src/storage/format.rs @@ -1,8 +1,8 @@ use std::sync::Arc; use borsh::{BorshDeserialize, BorshSerialize}; -use wire_message::{wire_message, WireMessage}; -use zk_primitives::Element; +use element::Element; +use wire_message::{WireMessage, wire_message}; #[derive(Debug, Clone)] #[wire_message] diff --git a/pkg/smirk/src/storage/load.rs b/pkg/smirk/src/storage/load.rs index 3a741cd..28bb1a5 100644 --- a/pkg/smirk/src/storage/load.rs +++ b/pkg/smirk/src/storage/load.rs @@ -2,21 +2,22 @@ use core::fmt::Debug; use std::sync::Arc; use borsh::{BorshDeserialize, BorshSerialize}; -use rocksdb::{IteratorMode, DB}; +use element::Element; +use rocksdb::{DB, IteratorMode}; use wire_message::WireMessage; -use zk_primitives::Element; use crate::{ + Batch, Tree, hash_cache::{KnownHash, SimpleHashCache}, storage::format::{KeyV2, ValueFormat}, - Batch, Tree, }; use super::{ - format::{KeyFormat, ValueV2}, Error, + format::{KeyFormat, ValueV2}, }; +#[tracing::instrument(skip_all)] pub(super) fn load_tree( db: &DB, ) -> Result, Error> diff --git a/pkg/smirk/src/storage/mod.rs b/pkg/smirk/src/storage/mod.rs index 2c21f63..a862ff0 100644 --- a/pkg/smirk/src/storage/mod.rs +++ b/pkg/smirk/src/storage/mod.rs @@ -1,12 +1,10 @@ -use core::fmt::Debug; -use std::path::Path; - +use crate::{Tree, batch as batch_macro, hash_cache::SimpleHashCache}; use borsh::{BorshDeserialize, BorshSerialize}; -use rocksdb::DB; - +use core::fmt::Debug; +use element::Element; pub use error::Error; - -use crate::{hash_cache::SimpleHashCache, Element, Tree}; +use rocksdb::DB; +use std::path::Path; mod batch; mod error; @@ -21,6 +19,7 @@ mod tests; /// /// ```rust /// # use smirk::*; +/// # use element::Element; /// # use smirk::storage::*; /// # let dir = tempdir::TempDir::new("smirk_doctest").unwrap(); /// # let path = dir.path().join("db"); @@ -35,6 +34,7 @@ impl Persistent { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// # use smirk::storage::*; /// # let dir = tempdir::TempDir::new("smirk_doctest").unwrap(); /// # let path = dir.path().join("db"); @@ -54,6 +54,7 @@ impl Persistent { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// # use smirk::storage::*; /// # let dir = tempdir::TempDir::new("smirk_doctest").unwrap(); /// # let path = dir.path().join("db"); @@ -66,6 +67,7 @@ impl Persistent { /// let persistent = Persistent::<64, i32>::load(&path).unwrap(); /// assert_eq!(persistent.tree().get(Element::ONE), Some(&123)); /// ``` + #[tracing::instrument(skip_all)] pub fn load>(path: P) -> Result where V: BorshDeserialize + BorshSerialize + Debug + Clone + Send + Sync + 'static, @@ -80,6 +82,7 @@ impl Persistent { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// # use smirk::storage::*; /// # let dir = tempdir::TempDir::new("smirk_doctest").unwrap(); /// # let path = dir.path().join("db"); @@ -118,6 +121,7 @@ impl Persistent { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// # use smirk::storage::*; /// # let dir = tempdir::TempDir::new("smirk_doctest").unwrap(); /// # let path = dir.path().join("db"); @@ -139,7 +143,7 @@ impl Persistent { where V: BorshSerialize + BorshDeserialize + Send + Sync + 'static + Clone, { - self.insert_batch(crate::batch! { element => value }) + self.insert_batch(batch_macro! { element => value }) } /// Store all computed hashes from the in-memory tree into rocksdb diff --git a/pkg/smirk/src/storage/store.rs b/pkg/smirk/src/storage/store.rs index f21bac3..4adfe9e 100644 --- a/pkg/smirk/src/storage/store.rs +++ b/pkg/smirk/src/storage/store.rs @@ -1,12 +1,12 @@ use std::collections::HashSet; use borsh::{BorshDeserialize, BorshSerialize}; -use rocksdb::{IteratorMode, WriteBatch, DB}; +use rocksdb::{DB, IteratorMode, WriteBatch}; use wire_message::WireMessage; use crate::{ - hash_cache::{KnownHash, SimpleHashCache}, Tree, + hash_cache::{KnownHash, SimpleHashCache}, }; use super::format::{KeyFormat, KeyV2, ValueFormat, ValueV2}; @@ -27,11 +27,15 @@ where .filter_map(|result| { let (key, value) = result.ok()?; - let KeyFormat::V2(KeyV2::KnownHash { left, right }) = KeyFormat::from_bytes(&key).ok()? else { + let KeyFormat::V2(KeyV2::KnownHash { left, right }) = + KeyFormat::from_bytes(&key).ok()? + else { return None; }; - let ValueFormat::::V2(ValueV2::KnownHash(result)) = ValueFormat::from_bytes(&value).ok()? else { + let ValueFormat::::V2(ValueV2::KnownHash(result)) = + ValueFormat::from_bytes(&value).ok()? + else { return None; }; @@ -43,7 +47,9 @@ where }) .collect::>(); - let hashes_to_insert = in_memory_hashes.into_iter().filter(|hash| !in_db_hashes.contains(hash)); + let hashes_to_insert = in_memory_hashes + .into_iter() + .filter(|hash| !in_db_hashes.contains(hash)); let mut batch = WriteBatch::default(); diff --git a/pkg/smirk/src/storage/test-snapshots/known_hashes_1.txt b/pkg/smirk/src/storage/test-snapshots/known_hashes_1.txt index 8ff7a6f..40ba4f7 100644 --- a/pkg/smirk/src/storage/test-snapshots/known_hashes_1.txt +++ b/pkg/smirk/src/storage/test-snapshots/known_hashes_1.txt @@ -2,321 +2,321 @@ KnownHash { left: 0x0, right: 0x1, - result: 0x1f4c45f9764aa17b0b277e23e1da0cefd69affc8caa18bb01f65b5c9d9761d21, + result: 0xdd6d785caa3fe1ad139a40b6bd26fccbd6c8697573b0e34489c740533db5cc8, }, KnownHash { left: 0x2, right: 0x3, - result: 0x19014d18a3179c5731155fcb7b6da422f456bccbd6da9dbc7df0f8dc6d4938ed, + result: 0x2bc00d90b885b09d12764e764410f7f693f514f7f3ca14d916741ff3968b3079, }, KnownHash { - left: 0x3bca21dd40c31c50cd4125801ed7fa88d42988cc56d3070e5a7772438925ba, - right: 0x24508e620942303909250d9c9fc529374f64963448da76cfc8475c2c425faab4, - result: 0x29df9a1a29fab0b8b8a3f11f1054405f1692063afb365655c723c00a97ba4b3, + left: 0x1131ee49df616cdbe459bb5ff267dbd8dc17969dd83baab4f0a16fbde2f5eeb, + right: 0x2f79c24831208eb014af76127ee58b95cf9598ad1dad9c82e19f10b7fee8f6f, + result: 0xbfe239476adba9d8820d005203d7fb7edd8a5b9ef96362c9834bf5918226657, }, KnownHash { - left: 0x409ca2e35bad171a2bd19effbebc385587b7e29b7ec16c2678d41952829ce2, - right: 0x18d5107e17690548b5fc2cd3c2c532f40448ba29166611ed139261125ac95ed8, - result: 0x1e8f7325359bc7737b56425cbe1ed0ea6ea73c4f5ef4d11f5ed2a6c678e5537c, + left: 0x16b5efcb64290843015617d3b65480146091129d39717eebb33f77da04111fc, + right: 0x2c45bb0c3d5bc1dc98e0baef09ff46d18c1a451e724f41c2b675549bb5c80e59, + result: 0xbb13d7253249d180049357549d34dc9c149d7cbcca8d53c49f78da7827d3092, }, KnownHash { - left: 0x4a39d3ef8d9d79980ec73f45fb26e36094eb924972050e0c360b24c0de8993, - right: 0xcf1ec907e066d0522395aba3c93e3b85aed37d1f51d9503a461a33d3d600128, - result: 0x302d53a1adc90ffd917bb16dd1c476966fb05351047c19f75d29a4a16cdc9be8, + left: 0x1df4e9650931ec0b20032e782aee9c3921fe2c21548ee5c33cfc9cbc29f0476, + right: 0x64769603ba3f6c41f664d266ecb9a3a0f6567cd3e48b40f34d4894ee4c361b3, + result: 0x260e51c984e7d1892a9e5ddae0f765cf4c952fcf12ba33fd0de8dd2bf132a8e, }, KnownHash { - left: 0x802eca53ba64bf5dee7cce0335ee032d2dcc97cb7213b78ef11ca46d7477de, - right: 0x2ff0a633dccfaf90a76262a6c7771a4b7707ada7d11691494bab0bd44332fd78, - result: 0x17527c70f81cce42d2abc30723caf6217f133dcd70a238cb4a1d8d52c24dc043, + left: 0x1ef8ae92253fac500b7de0e37e1f906ac01e9951ea5fef44b953058c2821fdd, + right: 0x74b0f589c0d62b3ee0d70fd057f9d0e143a6b888d0a9f60ac1d0f1c77ddf863, + result: 0x54a454b1d56629583b11fe12c706c6709b3b4c939fdb3add107a33fc0612ee5, }, KnownHash { - left: 0x29df9a1a29fab0b8b8a3f11f1054405f1692063afb365655c723c00a97ba4b3, - right: 0x507c07e3bf4b56fcee9aa982dddfbe440e02ea3beb0cb8a9ae95ddfda5fbbde, - result: 0xb4253341d1df9f82f9dcac5941b319fcee090a1acafd24767f83cd82cfd41a6, + left: 0x260e51c984e7d1892a9e5ddae0f765cf4c952fcf12ba33fd0de8dd2bf132a8e, + right: 0x1595bb3cd19f84619dc2e368175a88d8627a7439eda9397202cdb1167531fd3f, + result: 0x200c7968c05e5be61c92a041a7d23b2db0095b99c6c986fec4b74214ee7fd74e, }, KnownHash { - left: 0x2a32979641d7e996ff94a434708bb7b6132bb4201025295bccf56728d89578c, - right: 0x2d0e0d42612b3497ab4033be4d8bce8324b48b1b1e7d7eedddc70a43e8a11b53, - result: 0x2008c2ccfb2a4d49ec4cb3e51d6ab04e89f41ca7e5c9e39e08b854b71572e235, + left: 0x2bc57950debfef5f68ab8ddd9161bc72a66d3ac9e567dc91ee74c6cc406a481, + right: 0x16599e0bb19201fa33d4c00c3f7c5189552a26038ee219b1c8b08fd1b16ecd52, + result: 0x2d907fd9fdcb3c22c8a3483a97b711623d92956612fa4f279f82d77e230b8a02, }, KnownHash { - left: 0x2bfcc81fc984292a3bb81275c07e50e631ec53729211ca5e97056287409ac09, - right: 0x25b425103cbf4d26b7da0388c00f9800c1c54d4cc92155cee9326394b91834a7, - result: 0x1535cd1e0f5dd34f95edf38fcadc5df8cbb7730b4a37e0a29df030c7faebffa1, + left: 0x3db8216828ef62f803f0c9908219d4b3e8a2f2a7f00c0cff9297ce251df700d, + right: 0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6, + result: 0x27c788f23a309b94aea6e0d60c37aab04e1833f8ccb2b50414a8a89af784bb44, }, KnownHash { - left: 0x3e71bb330e01311d7d98ea52ed4f1ae0abee672293bf73d0f6f31e83c78591d, - right: 0x1f98b89c9a0eafbd9dd569f3d8c5d3e0d3da62b6d358214b4b94a70ba317a5b6, - result: 0x2e388168d14bc1f8798c0bd3043cb9ab9170d40acc246795d90f8d13a4062aa6, + left: 0x4a999758e9155c921ffe46d85adb6f19c6601676be3c36da6398cf00791878b, + right: 0xd07f6e7a8a0e9199d6d92801fff867002ff5b4808962f9da2ba5ce1bdd26a73, + result: 0x99ec77e7b542398dfafa6e8870e356c433605ea113020d97d9f12134c5fd45a, }, KnownHash { - left: 0x44a1440c68b0f9ec2e7f2cbc5d118abadd24329062711165b08b0e7a14ae71b, - right: 0x6334f3c5298ad916b6999c5b2404046b52cabed931e6a75008b6792afb1e5b8, - result: 0x153a4bfa2ab11aabc7d8cccc1bef2abfbb30204cdb9bbd7aafa778343f584618, + left: 0x54a454b1d56629583b11fe12c706c6709b3b4c939fdb3add107a33fc0612ee5, + right: 0x5e7d0fbf97820e4f7e37899bee6f967bc67f5b396f760665eb5ce76f51cff90, + result: 0x20978da57e00120d6c84fecf239db3c3d271005df2a9ff875322e458dd31f8c1, }, KnownHash { - left: 0x4d2c2434969075b772bc1dca38218db428f4c08648059827a0ab6a5794fc136, - right: 0x2fd86a1ceaea396f5fb3d98d667bf0e3af20e5b00328fdae766024d96fe923f3, - result: 0x73a4f08dfddf05b22b9f6e7e95f43c78b12af12be0a2788cf8eb12aa90b770a, + left: 0x555da1d413b84e269262b883d3bdcfe5b81bf6cbf3e6ee139862b891e05c2f9, + right: 0x1f0c1a8fb16b0d2ac9a146d7ae20d8d179695a92a79ed66fc45d9da4532459b3, + result: 0x2456ba004217b5d568d87e99483bdf88338851d56625964451c206a2789c8b53, }, KnownHash { - left: 0x52e18eace4efef4bfe98e748389bceb2e2bbec79e865506a70022ee5b50453f, - right: 0x27ee017018f45efbd35d1c13becfccf19930a17ffdeada836308586f7a17652b, - result: 0x2cbb521b05bd957ec431ac89c62e54e064dd721c31333201d87901724d594965, + left: 0x58e407975455fc49d55e31fc1e0351258e35746401a3bf61b60edb7f6c1dd6a, + right: 0x12340d5bb49b5667c9194321fc364488d0f082a8fb1bc4f1b96359209b1bf110, + result: 0x2a911f5fc2c7bc1e21fe9b0dd59228498bf9a27d1fed3c1a96b9007d297ed995, }, KnownHash { - left: 0x73a4f08dfddf05b22b9f6e7e95f43c78b12af12be0a2788cf8eb12aa90b770a, - right: 0x2cd010d45400358310a2806b6e81c732615fb19396106d8cdd429a066ec4c93b, - result: 0x90799c1ba498f52e576af5ea1e5b992e862bfdfda9cabf6c7b3f4d4f9c45898, + left: 0x591aa200b02efa913213ce774b4c6db2f35c8efb8c28aa8b104f59738d13a89, + right: 0x2373ea368857ec7af97e7b470d705848e2bf93ed7bef142a490f2119bcf82d8e, + result: 0x12e4fea7e8cad09eb7a029516ab0b6a508382745d4a63b154af166acb3408a2c, }, KnownHash { - left: 0x8063f34cf2540a631c16107a4d21e7430a766e2e7bf472ead5381a98c750fea, - right: 0x27027b296144ff2f66b259eacc9ae658f54ec80f1e1778e08863976fc1333122, - result: 0x160167e6bd6e8af8e8bc4a99661d4384390d6c7feb213a94ccd0f25303a665b2, + left: 0x6268bb4d61abf5f327b7b81d0d5922ffeccb40c5f2634eaac3ab8337c9e742f, + right: 0x197f2171ef99c2d053ee1fb5ff5ab288d56b9b41b4716c9214a4d97facc4c4a, + result: 0x2d9925151c8dd812f0342f3003c66b92c2bda3c7391e62189dff13a21f292f14, }, KnownHash { - left: 0x859ec6a11dcabefe61a2f2cd245f73f1e44a30c080edea75847edbd505c6c20, - right: 0xa58a88c183eb1f7cb645758052d439d6264fd212a0e8aaa49dcec034a641c05, - result: 0x1941759f4b8df229deaf73397b6451348589aa4e6ae3a1d658ba48c3eccd7da9, + left: 0x80215d084ab2679eb58cf1962c50fc87c482747f7635085867a7bedc27df802, + right: 0xb59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d, + result: 0x16b5efcb64290843015617d3b65480146091129d39717eebb33f77da04111fc, }, KnownHash { - left: 0x8725338bbccc405923a9ebe46eca1a83466a4b374f62d8a7d15dbfcdd6d8eeb, - right: 0xe99a2b688ce12dda9a54d7f46294409528b6c2465dd115e9b7edbbfbce6885e, - result: 0x2fbbb8a35bbb27a7719c050e7c49cae00317b3cbe7f6c649307cc2cfee0a99d4, + left: 0x940ca8f605baacf7ea1216772063d4b4a82238d5cda8d87fc39bd10351ac63b, + right: 0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686, + result: 0x11e970ae816a167aef9e3fc5cbb17e0f993be15381abf546805bc628f057f91e, }, KnownHash { - left: 0x90799c1ba498f52e576af5ea1e5b992e862bfdfda9cabf6c7b3f4d4f9c45898, - right: 0x26a66bd2ee4162c99a4f0b04ff2f23b69d7bd5841f642760aa590c77528bcb79, - result: 0x2a32979641d7e996ff94a434708bb7b6132bb4201025295bccf56728d89578c, + left: 0x99ec77e7b542398dfafa6e8870e356c433605ea113020d97d9f12134c5fd45a, + right: 0x1c4954081e324939350febc2b918a293ebcdaead01be95ec02fcbe8d2c1635d1, + result: 0x6268bb4d61abf5f327b7b81d0d5922ffeccb40c5f2634eaac3ab8337c9e742f, }, KnownHash { - left: 0x93663fa44a54d58600d9d1a0ecaf802a29c37547ac029a1ff321e0fc3b21e44, - right: 0x63b1ef8cfe229647b0aff38cff254f8c20e21381881a147f6cf977709a44edc, - result: 0x1ff9d92981be0c0fbfafe5513e7fbb04647f2de6c348d2c3c19d1712a7bc84d4, + left: 0xbb13d7253249d180049357549d34dc9c149d7cbcca8d53c49f78da7827d3092, + right: 0x121468e6710bf1ffec6d0f26743afe6f88ef55dab40b83ca0a39bc44b196374c, + result: 0x2cd0863c38562760213caf208978b610038a76eef8565090a53ecef5cec85914, }, KnownHash { - left: 0xae1fddd9381dae11da0bc5ac94245ddeb190c4f336169b0d3557fdd33932100, - right: 0xa7f2ad12d4e7b7b47e26e9ac4c50aeeef3340e9e938a0d63263f7d04dc47965, - result: 0x1379c361bcedea4024d497119f6a04eaa08f77403959e55eea8e46e1c7a7db1b, + left: 0xbf0043e87e62613ceab0345624d84c3e8da57b3a1e5bbafc8cc91cd204bb295, + right: 0x24d3e3c36e11f6dac11d08927f0a925e2c4c42248a913c18da9f5cc0da73836a, + result: 0x1b37ed47184b67fe0a0d1cfdd4c964d445efcf885771d78a23468003ed80d3ac, }, KnownHash { - left: 0xb4253341d1df9f82f9dcac5941b319fcee090a1acafd24767f83cd82cfd41a6, - right: 0xe5592d32d17e603a77406fa21672096996fe7f54f394efef7de7702a13f6bba, - result: 0x2b3471094f49c33d290d657b99022100a129999a3eebd59c562dc6599a6421c3, + left: 0xbfe239476adba9d8820d005203d7fb7edd8a5b9ef96362c9834bf5918226657, + right: 0x19d4d18c572a9b0b503094e1de87b8594e1d37dd1da42acdb3a19bd35f005a3a, + result: 0xbf0043e87e62613ceab0345624d84c3e8da57b3a1e5bbafc8cc91cd204bb295, }, KnownHash { - left: 0xc0f1ff4be2b4b07ce7c04590ae9513d512301f5bf71ab57cf13f6ac7dd9b35a, - right: 0x1ae026e0eb3eb3a299c4d6d4b93ab200dd183d951d088c6b73aae56693073e16, - result: 0x22a6b0ec17454bf940d44f53d6a32aa605f14dff1d4fb49bdd563269b564f764, + left: 0xc4aaeaddb7315eabd99bc8b6fdb4c9a4dc00a68c8f00643fb6f0d26810580d1, + right: 0x1849b85f3c693693e732dfc4577217acc18295193bede09ce8b97ad910310972, + result: 0x940ca8f605baacf7ea1216772063d4b4a82238d5cda8d87fc39bd10351ac63b, }, KnownHash { - left: 0xd63a986b4f054385358a02fc72a3bdada2219fac1f79f6194f06840165ca76e, - right: 0x1196ddacfe831a4c4a002c3287c5d7b7e62f393acc5dfb9a44e8d4e42852c630, - result: 0x1efbaa4ee0fc7bd321dd7aacaa70bdf4baaa1fdb63b75b8d3b43db8e6b91dfa6, + left: 0xdd6d785caa3fe1ad139a40b6bd26fccbd6c8697573b0e34489c740533db5cc8, + right: 0x2bc00d90b885b09d12764e764410f7f693f514f7f3ca14d916741ff3968b3079, + result: 0x132756d3b036721c09b6e427f31f27974cb765d2532f441a56bbc9a2649590c1, }, KnownHash { - left: 0xefbdd13c5ce10dadd7fcd867dc95f223eb98e2295f65acc5be8d19037dceca0, - right: 0x21c0e64648ca0af081e4d5aee2284a953411ba83c816b766f5b7ac3a1c5f2ea, - result: 0x215047c2e71463d4756b83e07d3c97432ce6eecbceb1239808a9c542d20fbc7f, + left: 0xdeb06a54f6227b18e2bc191c52446a96f0f5381a750256ae27a1dc7b1349236, + right: 0x71d7627ae3b2eabda8a810227bf04206370ac78dbf6c372380182dbd3711fe3, + result: 0x1a1f1ef0437bcb710cc581f26c7947db38b362e9f95e7c9a09f704a133bb9a2d, }, KnownHash { - left: 0x116f328e5ece8997fe664ec1edc95c4ff6cb36f5fb10921fd916f4633f94db22, - right: 0x19ef5205ba4137f9a5ed1d653c485f020d583f5adf5f82ffb1accbff613dedad, - result: 0x8725338bbccc405923a9ebe46eca1a83466a4b374f62d8a7d15dbfcdd6d8eeb, + left: 0xe6e1a73aed1f5b76bbfa6f4eb29b6b5b469551184b6b012da7d568e8a9cdb15, + right: 0x20165fe405652104dceaeeca92950aa5adc571b8cafe192878cba58ff1be49c5, + result: 0x244e04fae05c8af0854c12a229fd911bd04bbd6def97f560a24aa5ced9c01497, }, KnownHash { - left: 0x131b27da2e7e94884f29dd2b150a51fcadc753f60108c3e7817284e960572d57, - right: 0x24e75967390b53e4667ea7b202070f0e9ba1d6e4a24fa98403de9a6c0afd1be4, - result: 0x2e8f923a8a794edbfc3e1077aec1732394e205fbbb204f9c7d8d0298e2f60501, + left: 0xefb4b2eebefd1d93f89e0370355e2c4492998e19062450c4f9b4f2f7b7e7eee, + right: 0x15e4cf322bd4693b5ba17d7d77599ed6b40e943b15d4b652dcd1b206f57a4c6e, + result: 0x1131ee49df616cdbe459bb5ff267dbd8dc17969dd83baab4f0a16fbde2f5eeb, }, KnownHash { - left: 0x1379c361bcedea4024d497119f6a04eaa08f77403959e55eea8e46e1c7a7db1b, - right: 0x14a929f2e9a65f0ee918baa8d2165ebc566a07c704a4918fa57e9f8867e098c6, - result: 0xefbdd13c5ce10dadd7fcd867dc95f223eb98e2295f65acc5be8d19037dceca0, + left: 0x106250fb059f6227ea16e46c1b9d514761303c0b8e248a31ee5ff685518fb5b4, + right: 0x14748d0241710ef47f54b931ac5a58082b1d56b0f0c30d55fb71a6e8c9a6be14, + result: 0x80215d084ab2679eb58cf1962c50fc87c482747f7635085867a7bedc27df802, }, KnownHash { - left: 0x13cce5de3dbc2c6a96f9205f693860f722b60e681c922307ce162c686a33c2c7, - right: 0x1ef66fa5658e40fec30020d1796a417ee4b81668b49a71318973d23d3822fb0f, - result: 0x2773910604b872f3fbc071f6035f32a926b210f22d6a9bee9759bb84d1f45afd, + left: 0x11e970ae816a167aef9e3fc5cbb17e0f993be15381abf546805bc628f057f91e, + right: 0xf320b0703439a8114f81593de99cd0b8f3b9bf854601abb5b2ea0e8a3dda4a7, + result: 0x4a999758e9155c921ffe46d85adb6f19c6601676be3c36da6398cf00791878b, }, KnownHash { - left: 0x143dc7cbad4a9c3f17795ebb48cb85f97ad0199410df57c23bbfb844f0a81add, - right: 0x93c360a8f834b92f7e5eac996f164a0a05c3ea454b334efa8b7dcfc2603a179, - result: 0x21f0ec3c3dc1b3cee8a84a5593b530b2bb79f26128077e22ea8b7c7a05b5b26b, + left: 0x12e4fea7e8cad09eb7a029516ab0b6a508382745d4a63b154af166acb3408a2c, + right: 0x120157cfaaa49ce3da30f8b47879114977c24b266d58b0ac18b325d878aafddf, + result: 0x2ccd4c482b330a0326803806f60f3efcf1daa99eca64c2c6b4b3dd7add7676c5, }, KnownHash { - left: 0x153a4bfa2ab11aabc7d8cccc1bef2abfbb30204cdb9bbd7aafa778343f584618, - right: 0x1fc17d9d3b264f123d7619aa30b1bf07772c1ec90ae9ffec87814d5513e917c5, - result: 0xae1fddd9381dae11da0bc5ac94245ddeb190c4f336169b0d3557fdd33932100, + left: 0x12f9b64a597f27748a9bdb0cb9eb336ad453cf16a68505d88b647fc5f97710f2, + right: 0x2ac5dda169f6bb3b9ca09bbac34e14c94d1654597db740153a1288d859a8a30a, + result: 0x276704a95e8147ecfdf6e4ac20177cee5bd07e0cf3c8c3f6842abfedd5054404, }, KnownHash { - left: 0x160167e6bd6e8af8e8bc4a99661d4384390d6c7feb213a94ccd0f25303a665b2, - right: 0xfe4d2582275a130e303b95758bebe9003985eea6db0aa7a813170f9d44e6c6b, - result: 0x19a8ef2b1ec3e6bd2ddfbbe95fba33ef3dda4aaf3dcbdefbb9fddfc538213037, + left: 0x132756d3b036721c09b6e427f31f27974cb765d2532f441a56bbc9a2649590c1, + right: 0xe34ac2c09f45a503d2908bcb12f1cbae5fa4065759c88d501c097506a8b2290, + result: 0x2510b44266a0a8402bd470459de3fdf0e914dd2f266e7cb2dd1fc5e2f31dc7e2, }, KnownHash { - left: 0x17527c70f81cce42d2abc30723caf6217f133dcd70a238cb4a1d8d52c24dc043, - right: 0x140a69600cfe5daca43117a5915001b474e9be63f8654a745d7e993e5a24667d, - result: 0x116f328e5ece8997fe664ec1edc95c4ff6cb36f5fb10921fd916f4633f94db22, + left: 0x14029358f687b6cc4e444e8584f41cae01925c1f621d9a9dd3054f16975e7163, + right: 0xf55a0d491a9da093eb999fa0dffaf904620cbc78d07e63c6f795c5c7512b523, + result: 0x20b333e967e6cc02ac42f82374231f58cf31e1f21e6e34eb4319f98538e285a6, }, KnownHash { - left: 0x18ced2ad9a0247ac9dfbdc163e3ddc44e9d319994da19ed500861ebf3ed66bf3, - right: 0x24812503a9748360aca77f150d6ada11b3bca7c8eb76a7c045f4455347f569ff, - result: 0x131b27da2e7e94884f29dd2b150a51fcadc753f60108c3e7817284e960572d57, + left: 0x146cdbfe513b6d08829bdb312e9a3788ebecfb1deaf91caf3f8ecdcd6b6bd449, + right: 0x19bffd7d85c0863485890e50a717ebb21d4b888f0268d9c7258a3db25f969d9, + result: 0x58e407975455fc49d55e31fc1e0351258e35746401a3bf61b60edb7f6c1dd6a, }, KnownHash { - left: 0x1941759f4b8df229deaf73397b6451348589aa4e6ae3a1d658ba48c3eccd7da9, - right: 0x2984944ab07ac291118becffefd8dde8da228ddf99057060e402ee82cf68d2f7, - result: 0x3bca21dd40c31c50cd4125801ed7fa88d42988cc56d3070e5a7772438925ba, + left: 0x149299f55d4605dffae9e475448c8d8e592193624f1e01c60f13dadec9269440, + right: 0x1b593cc9332c0bb29333e5833284e18e765bb17fc0a7718f6b21d8a833a0765b, + result: 0x146cdbfe513b6d08829bdb312e9a3788ebecfb1deaf91caf3f8ecdcd6b6bd449, }, KnownHash { - left: 0x19a8ef2b1ec3e6bd2ddfbbe95fba33ef3dda4aaf3dcbdefbb9fddfc538213037, - right: 0x2b2a56fc63705101358d464dd6f96f6a2f40d0d22929a82a13f38b4e1ef83c5a, - result: 0x30016313602ad98fd049debe33b99c0ee04c0625190fc700f0312b9f56bbcd74, + left: 0x159c56dacf03a6c0654e7132390035f0db054ddb45dbf2e95edfd0639210009d, + right: 0x691a1f6e7dd363914d2754f434659383019fe2a1d10a9ce92d152decccfc5f5, + result: 0x272fa34a3ee4a268c4e9abe0c5d0e5c0b533f7915fe1b848bf20aeb785227312, }, KnownHash { - left: 0x19afc88f312c0747352cd24f1e666c516b3fde8ffbcf442d28a31ad83f053bed, - right: 0x15894af6b6c0549fa9cd30128579a2dc0c567ed7cabfb09bff95949341a9ac81, - result: 0xd63a986b4f054385358a02fc72a3bdada2219fac1f79f6194f06840165ca76e, + left: 0x17f40dca43dbb1e5793fe9b32d554f8b18054437df95c6806d9bf50a630b2fd2, + right: 0x2d2011d328f63f5cb9eb68a6806f8ce624ceb84a876a390fda61d6d6bb5a530, + result: 0x149299f55d4605dffae9e475448c8d8e592193624f1e01c60f13dadec9269440, }, KnownHash { - left: 0x1b57a9937f5e6d1b033f421637ed72d417ca945f866967988e3f12c09297e39c, - right: 0xcfcaec39ff6cf9310f45b44abff9f1c8cfbd5428b785592d3ba8626d1c5b467, - result: 0x213b932d8a344ee57b1b0b6faaaedf03c8a01ffb25a34e341a6f1653c9a2d28d, + left: 0x1a1f1ef0437bcb710cc581f26c7947db38b362e9f95e7c9a09f704a133bb9a2d, + right: 0x2fdc08d9fe075ac58cb8c00f98697861a13b3ab6f9d41a4e768f75e477475bf5, + result: 0xe6e1a73aed1f5b76bbfa6f4eb29b6b5b469551184b6b012da7d568e8a9cdb15, }, KnownHash { - left: 0x1e2b310d668a5737fc2b32977cf506541f6b9524739d5049dc8ec1065f677cd8, - right: 0x181312e20b6687d377125bc687e156dc8a2167502524d4e56164ceda881ed5fb, - result: 0x4d2c2434969075b772bc1dca38218db428f4c08648059827a0ab6a5794fc136, + left: 0x1b37ed47184b67fe0a0d1cfdd4c964d445efcf885771d78a23468003ed80d3ac, + right: 0x131b0345b2f2564b2338810cd8d7b90a8d5a2fcc1a9a8876a494dbe3c8135c6c, + result: 0x242dc4d66867bb3c5a5c3c333687ab19db5a2425b928ac30ac5fcab9062f32d2, }, KnownHash { - left: 0x1e8f7325359bc7737b56425cbe1ed0ea6ea73c4f5ef4d11f5ed2a6c678e5537c, - right: 0x34659157a0f40421b20f7d138b79d1c22f6d5ac16b23ca0ab6791ff40de26eb, - result: 0x3051796108014c19003f6427bd954399c1a5393807a871b9c433f51409e53d39, + left: 0x1bf3d9b8f367a97d86f372cdc03d55d7dceb5bf5676d0ec7e6bee2178bf24774, + right: 0x4f95f7efd61e5dfab009860f0e53b7e65686c5dbb1b1a800d597ec130836f92, + result: 0x1ef8ae92253fac500b7de0e37e1f906ac01e9951ea5fef44b953058c2821fdd, }, KnownHash { - left: 0x1efbaa4ee0fc7bd321dd7aacaa70bdf4baaa1fdb63b75b8d3b43db8e6b91dfa6, - right: 0x2e7cc44f05afd41946244940e561ae69222c657950e6540cf9a5589ac2665887, - result: 0x28b6c53212af05cc0194c64852df3caa691b0e492e80c925834b95762d88385c, + left: 0x1dc89b333deed0192ba47e563c75c3f8d4b690bca25ac5533d91a5de4e49ff3d, + right: 0x1a180441acbe2e25177de322888800476d75191e3c2c753300dedf84de7d2053, + result: 0x12f9b64a597f27748a9bdb0cb9eb336ad453cf16a68505d88b647fc5f97710f2, }, KnownHash { - left: 0x1f4c45f9764aa17b0b277e23e1da0cefd69affc8caa18bb01f65b5c9d9761d21, - right: 0x19014d18a3179c5731155fcb7b6da422f456bccbd6da9dbc7df0f8dc6d4938ed, - result: 0x209946ef716cab484342d4fe6b7bae73700d4798cc85d16c466e7f34e1f94b0e, + left: 0x200c7968c05e5be61c92a041a7d23b2db0095b99c6c986fec4b74214ee7fd74e, + right: 0x2a529be462b81ca30265b558763b1498289c9d88277ab14f0838cb1fce4b472c, + result: 0x21f5b79d8dfd93f3f83d9c0f9734319734bbb9a8700931e992552a15a1ee2bf2, }, KnownHash { - left: 0x1ff9d92981be0c0fbfafe5513e7fbb04647f2de6c348d2c3c19d1712a7bc84d4, - right: 0x11686509090e942105341635ed4a2735c8240b491c75a158f9e8ff4f0a89d25f, - result: 0x143dc7cbad4a9c3f17795ebb48cb85f97ad0199410df57c23bbfb844f0a81add, + left: 0x20b333e967e6cc02ac42f82374231f58cf31e1f21e6e34eb4319f98538e285a6, + right: 0x21849764e1aa64b83a69e39d27eedaec2a8f97066e5ddb74634ffdb11388dd9a, + result: 0x3db8216828ef62f803f0c9908219d4b3e8a2f2a7f00c0cff9297ce251df700d, }, KnownHash { - left: 0x2008c2ccfb2a4d49ec4cb3e51d6ab04e89f41ca7e5c9e39e08b854b71572e235, - right: 0x29cb3d60d1d9ea510c929bea0dc112781190aefdd8dc938b5d8478b7d04e6f82, - result: 0x13cce5de3dbc2c6a96f9205f693860f722b60e681c922307ce162c686a33c2c7, + left: 0x20f7f0a38855a05aad7aa91cde98e8d955fb05fdfdab217dc06dc6a5cbf03bec, + right: 0x9244eec34977ff795fc41036996ce974136377f521ac8eb9e04642d204783d2, + result: 0x262d96d6f8cbecebafad1b7cf92d72b9686a59caf790af5f86027b502a22deee, }, KnownHash { - left: 0x209946ef716cab484342d4fe6b7bae73700d4798cc85d16c466e7f34e1f94b0e, - right: 0xfa0082e09dd9cc2d8a236938f628b668d57f7b6cb72008ac03142111050864c, - result: 0x19afc88f312c0747352cd24f1e666c516b3fde8ffbcf442d28a31ad83f053bed, + left: 0x21f5b79d8dfd93f3f83d9c0f9734319734bbb9a8700931e992552a15a1ee2bf2, + right: 0xc08da612363088ad0bbc78abd233e8ace4c05a56fdabdd5e5e9b05e428bdaee, + result: 0x106250fb059f6227ea16e46c1b9d514761303c0b8e248a31ee5ff685518fb5b4, }, KnownHash { - left: 0x213b932d8a344ee57b1b0b6faaaedf03c8a01ffb25a34e341a6f1653c9a2d28d, - right: 0x26e15d391281e8698157e32a22635c3b8f6ce159fa398ba4c4ecd8c363e358b2, - result: 0x29e315ccb55d523a8b36e7a3320a3405a8abbd7f479563f21219d3883b85d1c6, + left: 0x240ba238f4bd4ddd4786e4bd64fb18335c3583e299deadb2b5932d544221c846, + right: 0x14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3, + result: 0xdeb06a54f6227b18e2bc191c52446a96f0f5381a750256ae27a1dc7b1349236, }, KnownHash { - left: 0x215047c2e71463d4756b83e07d3c97432ce6eecbceb1239808a9c542d20fbc7f, - right: 0x1e60f854fccdf9186e6fdeffe35b1781d72a5e5084c1f9cdacbdf59682b2b6da, - result: 0x52e18eace4efef4bfe98e748389bceb2e2bbec79e865506a70022ee5b50453f, + left: 0x242dc4d66867bb3c5a5c3c333687ab19db5a2425b928ac30ac5fcab9062f32d2, + right: 0xe765e363b659fafffce80bef02723bbbea3669cc9b07f327b4fc9c959c169a5, + result: 0x2c5a2afdb4747dff3702c3a5ad16facad924525ce2434bb282fdcf8c56e98fc9, }, KnownHash { - left: 0x21f0ec3c3dc1b3cee8a84a5593b530b2bb79f26128077e22ea8b7c7a05b5b26b, - right: 0x36724ee92610cbd02258014d4252e5dbf8e55c85f3fca802ab2d33069e560df, - result: 0x2d7239c598ec0c2c67b9e9925c1e6a326b84de0b803cb47a3abda41c3f939c03, + left: 0x244e04fae05c8af0854c12a229fd911bd04bbd6def97f560a24aa5ced9c01497, + right: 0x1c8c3ca0b3a3d75850fcd4dc7bf1e3445cd0cfff3ca510630fd90b47e8a24755, + result: 0x555da1d413b84e269262b883d3bdcfe5b81bf6cbf3e6ee139862b891e05c2f9, }, KnownHash { - left: 0x22a6b0ec17454bf940d44f53d6a32aa605f14dff1d4fb49bdd563269b564f764, - right: 0xda75df3d02f700a29702d2d867e8152106e15a6b3248f406d90dcbce9e03418, - result: 0x859ec6a11dcabefe61a2f2cd245f73f1e44a30c080edea75847edbd505c6c20, + left: 0x2456ba004217b5d568d87e99483bdf88338851d56625964451c206a2789c8b53, + right: 0x38146ec5a2573e1c30d2fb32c66c8440f426fbd108082df41c7bebd1d521c30, + result: 0x26ebd2e69b4913dc1139db5a3af852676539c88f7eda5c9e1a1758726bfb2a57, }, KnownHash { - left: 0x23cb5a3a51829ec1823c416441b68d7dba54364b725036fa77029ae69c26ba61, - right: 0x1f94545a8c4c82da4c5faef5a8bd37e5b767d5c758f3cf2c82a671cad380e80d, - result: 0xc0f1ff4be2b4b07ce7c04590ae9513d512301f5bf71ab57cf13f6ac7dd9b35a, + left: 0x250c1bd29a38a07b9f1c30324d0acd6baec6c1062d4f24e0debe4ea7bfc734aa, + right: 0x67243231eddf4222f3911defbba7705aff06ed45960b27f6f91319196ef97e1, + result: 0xc4aaeaddb7315eabd99bc8b6fdb4c9a4dc00a68c8f00643fb6f0d26810580d1, }, KnownHash { - left: 0x2773910604b872f3fbc071f6035f32a926b210f22d6a9bee9759bb84d1f45afd, - right: 0x193b047ed90559dd7cb4e85140d7f92422e3c69f90a049e8d0be21bec59c7ad9, - result: 0x1b57a9937f5e6d1b033f421637ed72d417ca945f866967988e3f12c09297e39c, + left: 0x2510b44266a0a8402bd470459de3fdf0e914dd2f266e7cb2dd1fc5e2f31dc7e2, + right: 0x21f9172d72fdcdafc312eee05cf5092980dda821da5b760a9fb8dbdf607c8a20, + result: 0x591aa200b02efa913213ce774b4c6db2f35c8efb8c28aa8b104f59738d13a89, }, KnownHash { - left: 0x27d8c95fa0943e51e71d398d0665fe3cf534a0b178c7107ef57572cc11ce5b57, - right: 0x109aa23474c1223413e13d176196f0b448c413df7ea091f20d5acfbe94c2adb2, - result: 0x18ced2ad9a0247ac9dfbdc163e3ddc44e9d319994da19ed500861ebf3ed66bf3, + left: 0x262d96d6f8cbecebafad1b7cf92d72b9686a59caf790af5f86027b502a22deee, + right: 0x1646d6f544ec36df9dc41f778a7ef1690a53c730b501471b6acd202194a7e8e9, + result: 0x1df4e9650931ec0b20032e782aee9c3921fe2c21548ee5c33cfc9cbc29f0476, }, KnownHash { - left: 0x289905ad379a529664ee4d6d7e10b32c39439c4b4a5fd097ad261b78151dbcef, - right: 0x1ad2b9d6ed2c042e2e815f9ea51f1417e8df49da4d5935354df37eec8105b173, - result: 0x2ea0beb4f028897ce99926868ef8ed873198fc10703b977ed352eb0d6c538d6a, + left: 0x26ebd2e69b4913dc1139db5a3af852676539c88f7eda5c9e1a1758726bfb2a57, + right: 0x17d3d12b17fe762de4b835b2180b012e808816a7f2ff69ecb9d65188235d8fd4, + result: 0x2ccf2393ca1c3d7727231b47c6fde4c3a33ad2ca0f653fb7c042edfdc03f8d3c, }, KnownHash { - left: 0x28b6c53212af05cc0194c64852df3caa691b0e492e80c925834b95762d88385c, - right: 0x18a8a74c4cf90a653286ff96cb8bc367eb4a45eaadf256e46f5dedcc969afde7, - result: 0x4a39d3ef8d9d79980ec73f45fb26e36094eb924972050e0c360b24c0de8993, + left: 0x272fa34a3ee4a268c4e9abe0c5d0e5c0b533f7915fe1b848bf20aeb785227312, + right: 0x1250a6bd4582016e8af7d74a31a7d181864326e50cea97f643b70ec9d94e1efc, + result: 0x17f40dca43dbb1e5793fe9b32d554f8b18054437df95c6806d9bf50a630b2fd2, }, KnownHash { - left: 0x29e315ccb55d523a8b36e7a3320a3405a8abbd7f479563f21219d3883b85d1c6, - right: 0x25ba03a2973fbc88f7b976626e63586b9330b6ddb08a07aa9c577ce3bb1d3f39, - result: 0x3e71bb330e01311d7d98ea52ed4f1ae0abee672293bf73d0f6f31e83c78591d, + left: 0x276704a95e8147ecfdf6e4ac20177cee5bd07e0cf3c8c3f6842abfedd5054404, + right: 0x2de9cf8ca22a0c9f7ac822564e7e90726457ffdee6107772e7461aa6dacf876d, + result: 0xefb4b2eebefd1d93f89e0370355e2c4492998e19062450c4f9b4f2f7b7e7eee, }, KnownHash { - left: 0x2b3471094f49c33d290d657b99022100a129999a3eebd59c562dc6599a6421c3, - right: 0x2deb5197b1d60ba97dfc37ec3015411da21c4d77dd9ba013f6d43fe4ef28fd19, - result: 0x2bfcc81fc984292a3bb81275c07e50e631ec53729211ca5e97056287409ac09, + left: 0x27c788f23a309b94aea6e0d60c37aab04e1833f8ccb2b50414a8a89af784bb44, + right: 0x1fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb, + result: 0x1dc89b333deed0192ba47e563c75c3f8d4b690bca25ac5533d91a5de4e49ff3d, }, KnownHash { - left: 0x2cbb521b05bd957ec431ac89c62e54e064dd721c31333201d87901724d594965, - right: 0x544f3743bc9686e28c6c1c6f7e05d9882befbf4d81c1a9c9d19e4ac04f0c772, - result: 0x8063f34cf2540a631c16107a4d21e7430a766e2e7bf472ead5381a98c750fea, + left: 0x2a911f5fc2c7bc1e21fe9b0dd59228498bf9a27d1fed3c1a96b9007d297ed995, + right: 0x2209d88df4bf41b2e002ff46f8ac45aa4ec8b222f4551c178fe50f99b505681f, + result: 0x1bf3d9b8f367a97d86f372cdc03d55d7dceb5bf5676d0ec7e6bee2178bf24774, }, KnownHash { - left: 0x2d7239c598ec0c2c67b9e9925c1e6a326b84de0b803cb47a3abda41c3f939c03, - right: 0x285013a6c0d3d6b7ee02566ebcba866ed801ddcf6eb852522c2b195c3287de7d, - result: 0x44a1440c68b0f9ec2e7f2cbc5d118abadd24329062711165b08b0e7a14ae71b, + left: 0x2ac796e25fb6fd16f1c4c6a472f495a2f88389006d16323ca67751f0ee954fcb, + right: 0xd582c10ff8115413aa5b70564fdd2f3cefe1f33a1e43a47bc495081e91e73e5, + result: 0x14029358f687b6cc4e444e8584f41cae01925c1f621d9a9dd3054f16975e7163, }, KnownHash { - left: 0x2e388168d14bc1f8798c0bd3043cb9ab9170d40acc246795d90f8d13a4062aa6, - right: 0x2c7254b5504739b2384f40bd702c9b1d7aa5559a924b38c545206327790fe23b, - result: 0x289905ad379a529664ee4d6d7e10b32c39439c4b4a5fd097ad261b78151dbcef, + left: 0x2c5a2afdb4747dff3702c3a5ad16facad924525ce2434bb282fdcf8c56e98fc9, + right: 0xf2d774b6dc7c8c6c49e2056f9f9e77d510637ff52368027fd8326821c83445a, + result: 0x2bc57950debfef5f68ab8ddd9161bc72a66d3ac9e567dc91ee74c6cc406a481, }, KnownHash { - left: 0x2e8f923a8a794edbfc3e1077aec1732394e205fbbb204f9c7d8d0298e2f60501, - right: 0x1fc5c8ba7bea28dcaea544338a6466600d8bbf3eea093c912168dc4544d33109, - result: 0x802eca53ba64bf5dee7cce0335ee032d2dcc97cb7213b78ef11ca46d7477de, + left: 0x2ccd4c482b330a0326803806f60f3efcf1daa99eca64c2c6b4b3dd7add7676c5, + right: 0x1c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76, + result: 0x2e32b1ee5e294e8290dbd8d27cd0f2f577dfc28b23e4962e8593b101c2d25191, }, KnownHash { - left: 0x2ea0beb4f028897ce99926868ef8ed873198fc10703b977ed352eb0d6c538d6a, - right: 0x8a9dc89f3b17592f0e55d4e1b818ebd876fc8dafdacb28afb54ad97a482a292, - result: 0x409ca2e35bad171a2bd19effbebc385587b7e29b7ec16c2678d41952829ce2, + left: 0x2ccf2393ca1c3d7727231b47c6fde4c3a33ad2ca0f653fb7c042edfdc03f8d3c, + right: 0xe1a6b7d63a6e5a9e54e8f391dd4e9d49cdfedcbc87f02cd34d4641d2eb30491, + result: 0x20f7f0a38855a05aad7aa91cde98e8d955fb05fdfdab217dc06dc6a5cbf03bec, }, KnownHash { - left: 0x2fbbb8a35bbb27a7719c050e7c49cae00317b3cbe7f6c649307cc2cfee0a99d4, - right: 0x159b0b17f684742dc49112891bb04d2ec062c68985bd3c2bfdd9b4d008f4092a, - result: 0x23cb5a3a51829ec1823c416441b68d7dba54364b725036fa77029ae69c26ba61, + left: 0x2cd0863c38562760213caf208978b610038a76eef8565090a53ecef5cec85914, + right: 0x2042c32c823a7440ceb6c342f9125f1fe426b02c527cd8fb28c85d02b705e759, + result: 0x2ac796e25fb6fd16f1c4c6a472f495a2f88389006d16323ca67751f0ee954fcb, }, KnownHash { - left: 0x30016313602ad98fd049debe33b99c0ee04c0625190fc700f0312b9f56bbcd74, - right: 0x21136a71eb3e0ccad128ed0c5fae4acf435935142cc4fea0cb5ca5245f964c09, - result: 0x27d8c95fa0943e51e71d398d0665fe3cf534a0b178c7107ef57572cc11ce5b57, + left: 0x2d907fd9fdcb3c22c8a3483a97b711623d92956612fa4f279f82d77e230b8a02, + right: 0x22f62d7c8204be97acc7644d4b14a422c17e573506e900a4788acbfb8c8b1aba, + result: 0x159c56dacf03a6c0654e7132390035f0db054ddb45dbf2e95edfd0639210009d, }, KnownHash { - left: 0x302d53a1adc90ffd917bb16dd1c476966fb05351047c19f75d29a4a16cdc9be8, - right: 0xda004968db5a60e1689936fa00b858b23187fc0702d07c6b439116d8ee6dec8, - result: 0x1e2b310d668a5737fc2b32977cf506541f6b9524739d5049dc8ec1065f677cd8, + left: 0x2d9925151c8dd812f0342f3003c66b92c2bda3c7391e62189dff13a21f292f14, + right: 0x2b9cdd484c5ba1e4d6efcc3f18734b5ac4c4a0b9102e2aeb48521a661d3feee9, + result: 0x240ba238f4bd4ddd4786e4bd64fb18335c3583e299deadb2b5932d544221c846, }, KnownHash { - left: 0x3051796108014c19003f6427bd954399c1a5393807a871b9c433f51409e53d39, - right: 0x2b22abdfce9a96e2c7306ebaf45f64c7e0c2e7738119447776a6aac223565dfa, - result: 0x93663fa44a54d58600d9d1a0ecaf802a29c37547ac029a1ff321e0fc3b21e44, + left: 0x2e32b1ee5e294e8290dbd8d27cd0f2f577dfc28b23e4962e8593b101c2d25191, + right: 0x2d78ed82f93b61ba718b17c2dfe5b52375b4d37cbbed6f1fc98b47614b0cf21b, + result: 0x250c1bd29a38a07b9f1c30324d0acd6baec6c1062d4f24e0debe4ea7bfc734aa, }, ] diff --git a/pkg/smirk/src/storage/test-snapshots/known_hashes_2.txt b/pkg/smirk/src/storage/test-snapshots/known_hashes_2.txt index 19a12ba..384bee9 100644 --- a/pkg/smirk/src/storage/test-snapshots/known_hashes_2.txt +++ b/pkg/smirk/src/storage/test-snapshots/known_hashes_2.txt @@ -2,336 +2,336 @@ KnownHash { left: 0x0, right: 0x1, - result: 0x1f4c45f9764aa17b0b277e23e1da0cefd69affc8caa18bb01f65b5c9d9761d21, + result: 0xdd6d785caa3fe1ad139a40b6bd26fccbd6c8697573b0e34489c740533db5cc8, }, KnownHash { left: 0x2, right: 0x3, - result: 0x19014d18a3179c5731155fcb7b6da422f456bccbd6da9dbc7df0f8dc6d4938ed, + result: 0x2bc00d90b885b09d12764e764410f7f693f514f7f3ca14d916741ff3968b3079, }, KnownHash { left: 0x4, right: 0x5, - result: 0x972526c0e9d5ba84d44d55eee3ac3090da2820c18141279b798f63bb9328a36, + result: 0xcbead93d02a01ab38edbd469a154c4900b8c8b9091d6c25c978f2cf7e33e790, }, KnownHash { left: 0x6, right: 0x0, - result: 0xab71b3c956eb8ec4f639a7205c95d693586c15e474aa5b8886d90f7b9a25fe8, + result: 0xdbff02cfa93acbb844e2a588983dc5e4b72d682ddaccc2a6d8df5ffffbcb1f4, }, KnownHash { - left: 0x2dabf837ae1777f6c609af2525c9e59b989da810102b43f7c3e15379c2097a, - right: 0x24e75967390b53e4667ea7b202070f0e9ba1d6e4a24fa98403de9a6c0afd1be4, - result: 0x2505f998cb09db6b9e77343816655f82f655683c5b0702ffe24c198c4b1532e6, + left: 0x19894df714fdf8a7d0dedc2e61454ea1da351cc98b9d2a71f7d06c14f02ed8, + right: 0x1646d6f544ec36df9dc41f778a7ef1690a53c730b501471b6acd202194a7e8e9, + result: 0x1453a60409d0dba36c61cff32e156a856545e903d9cb82fce6347b8faf668955, }, KnownHash { - left: 0x3f7f0d18a3438e8f3abf9ef7ee205b0b82db68d9b24695087dc485d80d30f4, - right: 0x14a929f2e9a65f0ee918baa8d2165ebc566a07c704a4918fa57e9f8867e098c6, - result: 0x126ed49b84f78f7df6eb3f2bab7c573df204d8780b93d6206aa8efc785df0ed3, + left: 0x233750fdee4c0c4e2e81e2a564d37ba9945cc31ed1ac65b6ffa980b6c0cbf2c, + right: 0x38146ec5a2573e1c30d2fb32c66c8440f426fbd108082df41c7bebd1d521c30, + result: 0x104b1bc6e8c9fcd9869631a312a53a92080d026bff81fa3b82b024f8bf0103d4, }, KnownHash { - left: 0x14b9211682f1078581d5719b2240da23c6cac1424dbd48e8769106d71c45b1f, - right: 0x1fc17d9d3b264f123d7619aa30b1bf07772c1ec90ae9ffec87814d5513e917c5, - result: 0x2064b8acdb79ca2bc427f790164b9eae191dd4b0581cb6a33a698e84ef9416c8, + left: 0x291b1be21583775a0251fee328a85e2f74ec6096fa449f8a058bb67efedd6d5, + right: 0x2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6, + result: 0xf085dada9a0fedb9689910a112f2ffc037600d689de3022888033e9b6927f21, }, KnownHash { - left: 0x1e048647cfbefd6672fda954a168e3f841f746b654679738ff5b797aec8a64b, - right: 0x2deb5197b1d60ba97dfc37ec3015411da21c4d77dd9ba013f6d43fe4ef28fd19, - result: 0x3b1c3ab99e966f9cdc90d57f012e5b10db0e986d6f06406e34974b716a58858, + left: 0x31cada8e33482ec16c828b712dd10525bee92b0576840cc366dc191a603d8da, + right: 0x20165fe405652104dceaeeca92950aa5adc571b8cafe192878cba58ff1be49c5, + result: 0x444169d48d1ff4fbddb599570954bf1a700e21ffac20a66be46287b063e376f, }, KnownHash { - left: 0x3b1c3ab99e966f9cdc90d57f012e5b10db0e986d6f06406e34974b716a58858, - right: 0x25b425103cbf4d26b7da0388c00f9800c1c54d4cc92155cee9326394b91834a7, - result: 0x2d11c0b2e1c763f166dc8b14d592d192beabea1bbbb622921d9d2b5b7ab0a970, + left: 0x32c2ee775483c2a4ea33b550fed3d0d8da2be1d6df803fa369672f209236198, + right: 0x2209d88df4bf41b2e002ff46f8ac45aa4ec8b222f4551c178fe50f99b505681f, + result: 0x2006484cb63349b65c82c3d0a6ff0651ce628a57f10b796c90e3e07e01ac6fa2, }, KnownHash { - left: 0x53f210d76a7304baaddf90d76399dbf4059d5a07e7efc10aa04080bcd0937da, - right: 0x21136a71eb3e0ccad128ed0c5fae4acf435935142cc4fea0cb5ca5245f964c09, - result: 0x10a677e42e1deceb6cd59bc8135c0332389276b0dd985d3d3defdf410c0f1231, + left: 0x3609a7a2916db64630f6d49c0f50f88b776780f40bb4ed7c4219cc4da3ff149, + right: 0x2d2011d328f63f5cb9eb68a6806f8ce624ceb84a876a390fda61d6d6bb5a530, + result: 0x2c31b494a5f558ae26bfd601cec1dfb21eded28f43c4906b133c2aa734679046, }, KnownHash { - left: 0x6f8397381966da0113dc141da278a91e678b21fec0f3175e870d0220a9cac54, - right: 0x27027b296144ff2f66b259eacc9ae658f54ec80f1e1778e08863976fc1333122, - result: 0x2872aa6b0597d605d9e8a54571e316eec2f9fa7217a1bbc02b8eab1862b4f108, + left: 0x3ebecd701f607563e8429d2e27b2476f4f3fd427a8e9cd97028e7c381110241, + right: 0x2ac5dda169f6bb3b9ca09bbac34e14c94d1654597db740153a1288d859a8a30a, + result: 0x15aff39be21f6e3aa6c1a7f6c12d2a93e00aaf5ebb363af32418c6dee4e819f1, }, KnownHash { - left: 0x706713676571315c6e754e9a794c0d8af69d0f2987d96828af57ffd85120a49, - right: 0x25ba03a2973fbc88f7b976626e63586b9330b6ddb08a07aa9c577ce3bb1d3f39, - result: 0x186a46b6400b00a3b38c366f81cc45e8a414fdffb190726ce767dfaad8f4fcdc, + left: 0x444169d48d1ff4fbddb599570954bf1a700e21ffac20a66be46287b063e376f, + right: 0x1c8c3ca0b3a3d75850fcd4dc7bf1e3445cd0cfff3ca510630fd90b47e8a24755, + result: 0x2d095e2920660da0bf42f8d8598185f7e3e00d1d8052bab558af3b5577a3b7ee, }, KnownHash { - left: 0x7a846a889971f831edad4f09bcf22fb87edd62f9ac994e7d85e38270eb40609, - right: 0xda75df3d02f700a29702d2d867e8152106e15a6b3248f406d90dcbce9e03418, - result: 0x1fe0c6364be10b1624c95dde1add014772203e68a5c49b403975ac0fdad9ac81, + left: 0x55a8e7ba8ae99fc528616b576d59e6d19f1b5ea068c9b7c1ce8b7770d38d7e5, + right: 0x12340d5bb49b5667c9194321fc364488d0f082a8fb1bc4f1b96359209b1bf110, + result: 0x32c2ee775483c2a4ea33b550fed3d0d8da2be1d6df803fa369672f209236198, }, KnownHash { - left: 0x7c852792038c00199583bbed3fe37fb4e383b98f3c11e608ce759e9bce0d2ec, - right: 0x26e15d391281e8698157e32a22635c3b8f6ce159fa398ba4c4ecd8c363e358b2, - result: 0x706713676571315c6e754e9a794c0d8af69d0f2987d96828af57ffd85120a49, + left: 0x575f52be4a0a1f62f2a222034330b1d9972079019fbccfb1d62a690d03eb9e1, + right: 0x19bffd7d85c0863485890e50a717ebb21d4b888f0268d9c7258a3db25f969d9, + result: 0x55a8e7ba8ae99fc528616b576d59e6d19f1b5ea068c9b7c1ce8b7770d38d7e5, }, KnownHash { - left: 0x85c23bd218ed3cef00f2f7062edc726a08ccb2ca5b5886d06ab366de8409339, - right: 0x63b1ef8cfe229647b0aff38cff254f8c20e21381881a147f6cf977709a44edc, - result: 0xbd3fad51dfa1e4821aa289d3f7a1ea3629bca985ce26ace9202c9b98a61798d, + left: 0x5948c417d93fd320e210ed58792c19c22210143b623f3ce2021fc799cb85f06, + right: 0x120157cfaaa49ce3da30f8b47879114977c24b266d58b0ac18b325d878aafddf, + result: 0x261c0b8a15816ad46a77fd0c305729987dbfb934c4ee3655cbb74a39a5f6829c, }, KnownHash { - left: 0x86ff8756c40a03f52c8835b78896b5e79ff7f3cbe5099965cc3d132cce816ad, - right: 0x2ff0a633dccfaf90a76262a6c7771a4b7707ada7d11691494bab0bd44332fd78, - result: 0xa4c886307cd614d07a4e50d9cae5ecc5835bb26987e1c5377dc5aef70e7df69, + left: 0x5c8dda05fb454f9e8c32121c93afaa0caa3108b5868198cdb4c39ed4b0d41db, + right: 0x2d78ed82f93b61ba718b17c2dfe5b52375b4d37cbbed6f1fc98b47614b0cf21b, + result: 0x15a2ad0ca52ddd0c05f0eb32ad9e5a033a8e8bc2c8bf0b27c12e380ae3397802, }, KnownHash { - left: 0x91471564f3cc6a2f4cdd4b149c8f19b6b25bc860ea015bc846a25e6e70391c2, - right: 0x6334f3c5298ad916b6999c5b2404046b52cabed931e6a75008b6792afb1e5b8, - result: 0x14b9211682f1078581d5719b2240da23c6cac1424dbd48e8769106d71c45b1f, + left: 0x61fa1d36181e7c6161c89e1b1848708fd5d8526be8a87ac91a21d5a959fc03b, + right: 0x197f2171ef99c2d053ee1fb5ff5ab288d56b9b41b4716c9214a4d97facc4c4a, + result: 0x295c8d0b994cd68dbbf2ac01722ae489f81b3ee106113b0a2965018047061322, }, KnownHash { - left: 0x972526c0e9d5ba84d44d55eee3ac3090da2820c18141279b798f63bb9328a36, - right: 0xab71b3c956eb8ec4f639a7205c95d693586c15e474aa5b8886d90f7b9a25fe8, - result: 0x14265fb8f44d78dbea1f5eb8d90b0bfadbbdfce8a4af8352048d68dc44005475, + left: 0x6a75a35e4c04a68efa4edc0cee7a48e64e366b44c12cc8713caf1f4480a8fa0, + right: 0x1849b85f3c693693e732dfc4577217acc18295193bede09ce8b97ad910310972, + result: 0x2e3d1307a2ddbf78320bf6ee17a9a8cf2a3946c85e05b5bbe57e2a444e2c4913, }, KnownHash { - left: 0xa4c886307cd614d07a4e50d9cae5ecc5835bb26987e1c5377dc5aef70e7df69, - right: 0x140a69600cfe5daca43117a5915001b474e9be63f8654a745d7e993e5a24667d, - result: 0x29198057e0a158eafb1069f1f535c5c62117249f180b3e466485af2317493121, + left: 0x7b4fe1badae979a7e794b5ae22e45d4928be29008ca73dcd60bd287605a6c39, + right: 0xc08da612363088ad0bbc78abd233e8ace4c05a56fdabdd5e5e9b05e428bdaee, + result: 0x1cd19a9633a5c087c45f1836d8fe7532d7f962741483f0b7d3ffdf79fc9146ed, }, KnownHash { - left: 0xac1a7fbcd7f756c97d34491c9519cd70b2aa6ae480201a3ec19ad1be68290c4, - right: 0x2cd010d45400358310a2806b6e81c732615fb19396106d8cdd429a066ec4c93b, - result: 0x1d12c8e031dbe0b673f702629e60c493b6ab68ad4547b5d89423e07ae5143100, + left: 0x82ff964500c30a17ed4b0063b90ca61012c64db9baedaa81fdd404e004bc004, + right: 0x14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3, + result: 0x1a752bb7665ea05dae9d38101fe97af168bf4a6ea5b4c0a749e2a1ceb36f1eac, }, KnownHash { - left: 0xbbb801ecbb5fd9ec362507447351d3d820c19490521899eebd9096dfbf37630, - right: 0xe5592d32d17e603a77406fa21672096996fe7f54f394efef7de7702a13f6bba, - result: 0x1e048647cfbefd6672fda954a168e3f841f746b654679738ff5b797aec8a64b, + left: 0x9476f6aad2549a02185614273c572c7c91af82b31c7bfd29fd8750f1c6425f4, + right: 0xe765e363b659fafffce80bef02723bbbea3669cc9b07f327b4fc9c959c169a5, + result: 0x2b081f1ccee4386c0fb90191275f9e16f68050a2707ad7d2ef141841122b3ba4, }, KnownHash { - left: 0xbd3fad51dfa1e4821aa289d3f7a1ea3629bca985ce26ace9202c9b98a61798d, - right: 0x11686509090e942105341635ed4a2735c8240b491c75a158f9e8ff4f0a89d25f, - result: 0x2db89f0a1d022e30f5322d55eb614aa62def55feb925d4d4a25f16f04d50afdb, + left: 0x9697e416be1dfcb6977d86e065af3be3ec7870c78faa3e9dfd6bd783beec887, + right: 0x2fdc08d9fe075ac58cb8c00f98697861a13b3ab6f9d41a4e768f75e477475bf5, + result: 0x31cada8e33482ec16c828b712dd10525bee92b0576840cc366dc191a603d8da, }, KnownHash { - left: 0xfafece8d80b41e0c5fe356045a329f3ac29a37ac8d9d46cb48361c39da15608, - right: 0x1f94545a8c4c82da4c5faef5a8bd37e5b767d5c758f3cf2c82a671cad380e80d, - result: 0x25017b53780e2e8d1d7cff06aa6eba2c7db205c85103486ef6c1e8d15897bda8, + left: 0xcbead93d02a01ab38edbd469a154c4900b8c8b9091d6c25c978f2cf7e33e790, + right: 0xdbff02cfa93acbb844e2a588983dc5e4b72d682ddaccc2a6d8df5ffffbcb1f4, + result: 0x1047bc082675bad40abfef36b3683e776ff448c0a2cb014652237cdbf32ed17c, }, KnownHash { - left: 0xfcc07135367f80d17ff8c2a769827eabc9effea8447a397f147c415825cc673, - right: 0x159b0b17f684742dc49112891bb04d2ec062c68985bd3c2bfdd9b4d008f4092a, - result: 0xfafece8d80b41e0c5fe356045a329f3ac29a37ac8d9d46cb48361c39da15608, + left: 0xdd6d785caa3fe1ad139a40b6bd26fccbd6c8697573b0e34489c740533db5cc8, + right: 0x2bc00d90b885b09d12764e764410f7f693f514f7f3ca14d916741ff3968b3079, + result: 0x132756d3b036721c09b6e427f31f27974cb765d2532f441a56bbc9a2649590c1, }, KnownHash { - left: 0x102aa55dde4b829de07b40a8f9b81996f7b279c6ae920bd1ceea95b57f0fbe4a, - right: 0x24812503a9748360aca77f150d6ada11b3bca7c8eb76a7c045f4455347f569ff, - result: 0x2dabf837ae1777f6c609af2525c9e59b989da810102b43f7c3e15379c2097a, + left: 0xf085dada9a0fedb9689910a112f2ffc037600d689de3022888033e9b6927f21, + right: 0x1fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb, + result: 0x1afc4b08b856e546d6ba1018783f295a7e9a31986c1334dbb24a05102ae0388f, }, KnownHash { - left: 0x10627bb93eefe99746a3d5e92f64c81e59d076d651621ed2bf7b61cfd8279677, - right: 0x18a8a74c4cf90a653286ff96cb8bc367eb4a45eaadf256e46f5dedcc969afde7, - result: 0x1e251bc1c78ae03b4ec5dbdf8aee3a29d5e8e4643639e050947a9d89444f57fb, + left: 0x104b1bc6e8c9fcd9869631a312a53a92080d026bff81fa3b82b024f8bf0103d4, + right: 0x17d3d12b17fe762de4b835b2180b012e808816a7f2ff69ecb9d65188235d8fd4, + result: 0x182c8b7fffb5b666fee10cb83d218fb3527ba3ace6920eb4a89f9fc646080d0d, }, KnownHash { - left: 0x10a677e42e1deceb6cd59bc8135c0332389276b0dd985d3d3defdf410c0f1231, - right: 0x109aa23474c1223413e13d176196f0b448c413df7ea091f20d5acfbe94c2adb2, - result: 0x102aa55dde4b829de07b40a8f9b81996f7b279c6ae920bd1ceea95b57f0fbe4a, + left: 0x1100a2dbc8c2fca3c623a6f1e6f9b2e9cff4849e0cb0a3cc6f9fa1967a89753f, + right: 0x2c45bb0c3d5bc1dc98e0baef09ff46d18c1a451e724f41c2b675549bb5c80e59, + result: 0x259a407ab93714f2b3e43b5dd310c6fd38cd7adba04598b74034a63fce39248d, }, KnownHash { - left: 0x117f56a05ddb98c6b9847e490d02311c44c7a0914734b9cae446dd02b5aa0647, - right: 0xe99a2b688ce12dda9a54d7f46294409528b6c2465dd115e9b7edbbfbce6885e, - result: 0xfcc07135367f80d17ff8c2a769827eabc9effea8447a397f147c415825cc673, + left: 0x11b312d35f1106fe78aa6cd40f2b838707a500396ca2311670426adcf1b435b8, + right: 0xf55a0d491a9da093eb999fa0dffaf904620cbc78d07e63c6f795c5c7512b523, + result: 0x286f00030b9b6b2dfa00ea1c70a31ecd733c3791e8fbdef93e93ed34a7b3ae57, }, KnownHash { - left: 0x11981f8d15decdcd5c7b8b9408103576b477fae3bfac3d185c83aff74304a4da, - right: 0x2fd86a1ceaea396f5fb3d98d667bf0e3af20e5b00328fdae766024d96fe923f3, - result: 0xac1a7fbcd7f756c97d34491c9519cd70b2aa6ae480201a3ec19ad1be68290c4, + left: 0x132756d3b036721c09b6e427f31f27974cb765d2532f441a56bbc9a2649590c1, + right: 0x1047bc082675bad40abfef36b3683e776ff448c0a2cb014652237cdbf32ed17c, + result: 0x1b446dccfcf23006b4131b5191e2362da1807a8ea501da614d23fd42eea0e9ae, }, KnownHash { - left: 0x11f18cdca3030a2af55509e64a10f968cf6f6512f5382b4c11dc4f01ce91a9dc, - right: 0x2c7254b5504739b2384f40bd702c9b1d7aa5559a924b38c545206327790fe23b, - result: 0x140390f9116872e05b6617fc709cf5249287d777a94e6db661687089cefd5423, + left: 0x14220004192916845b117fdcd458257c50083c8f7fdd8e71fbaabf5547084cba, + right: 0x2f79c24831208eb014af76127ee58b95cf9598ad1dad9c82e19f10b7fee8f6f, + result: 0x2bf8dea925b1912f4dd72f0003d4298060a7eb756f603fb11b7dc6b9b1c68b86, }, KnownHash { - left: 0x126ed49b84f78f7df6eb3f2bab7c573df204d8780b93d6206aa8efc785df0ed3, - right: 0x21c0e64648ca0af081e4d5aee2284a953411ba83c816b766f5b7ac3a1c5f2ea, - result: 0x2d0f5cc297643f783b3f6a53806427fa77b7b219db632c39bbb7470829b060c3, + left: 0x1453a60409d0dba36c61cff32e156a856545e903d9cb82fce6347b8faf668955, + right: 0x64769603ba3f6c41f664d266ecb9a3a0f6567cd3e48b40f34d4894ee4c361b3, + result: 0x18a5385a2794ac535f6a7f5625146ca66b94bc69ad3866a3d5ebb21457953e7d, }, KnownHash { - left: 0x12dc8d0fe6f6c5064e4131c6f89da61903405676444c602c9bea940b02b9519c, - right: 0x29cb3d60d1d9ea510c929bea0dc112781190aefdd8dc938b5d8478b7d04e6f82, - result: 0x1f6f9eed2f50e018b3effaf4df0616e2b968df73961169d7456b44e5743af209, + left: 0x150ea420b048c2e3adc5910ae3b378a27350c98dde25544ec56c5f4a912bd559, + right: 0x15e4cf322bd4693b5ba17d7d77599ed6b40e943b15d4b652dcd1b206f57a4c6e, + result: 0x14220004192916845b117fdcd458257c50083c8f7fdd8e71fbaabf5547084cba, }, KnownHash { - left: 0x140390f9116872e05b6617fc709cf5249287d777a94e6db661687089cefd5423, - right: 0x1ad2b9d6ed2c042e2e815f9ea51f1417e8df49da4d5935354df37eec8105b173, - result: 0x18cdcf795ffdc17de3e809e5cfe74f3b158dcd7df94fedffc14fbae90d86a26a, + left: 0x15a2ad0ca52ddd0c05f0eb32ad9e5a033a8e8bc2c8bf0b27c12e380ae3397802, + right: 0x67243231eddf4222f3911defbba7705aff06ed45960b27f6f91319196ef97e1, + result: 0x6a75a35e4c04a68efa4edc0cee7a48e64e366b44c12cc8713caf1f4480a8fa0, }, KnownHash { - left: 0x15bbf5170fdaa7789d1f098aa0f7a71564b4dc5a66b3ade0018a33ecd04d6b22, - right: 0x15894af6b6c0549fa9cd30128579a2dc0c567ed7cabfb09bff95949341a9ac81, - result: 0x1fda4b1a96efc9a289327f8749cc3f54f856a3f10a27d79edd50f5090696e5e9, + left: 0x15aff39be21f6e3aa6c1a7f6c12d2a93e00aaf5ebb363af32418c6dee4e819f1, + right: 0x2de9cf8ca22a0c9f7ac822564e7e90726457ffdee6107772e7461aa6dacf876d, + result: 0x150ea420b048c2e3adc5910ae3b378a27350c98dde25544ec56c5f4a912bd559, }, KnownHash { - left: 0x178167cbbb3d6a65bf2b121c5254b8abcea407f556b55ce9ffb1f03e18f36850, - right: 0x2b2a56fc63705101358d464dd6f96f6a2f40d0d22929a82a13f38b4e1ef83c5a, - result: 0x53f210d76a7304baaddf90d76399dbf4059d5a07e7efc10aa04080bcd0937da, + left: 0x182c8b7fffb5b666fee10cb83d218fb3527ba3ace6920eb4a89f9fc646080d0d, + right: 0xe1a6b7d63a6e5a9e54e8f391dd4e9d49cdfedcbc87f02cd34d4641d2eb30491, + result: 0x1a346d41faf0708cb9f8eda3a6849a636407e1ce7bb815478af0c4a21a7379fc, }, KnownHash { - left: 0x186a46b6400b00a3b38c366f81cc45e8a414fdffb190726ce767dfaad8f4fcdc, - right: 0x1f98b89c9a0eafbd9dd569f3d8c5d3e0d3da62b6d358214b4b94a70ba317a5b6, - result: 0x11f18cdca3030a2af55509e64a10f968cf6f6512f5382b4c11dc4f01ce91a9dc, + left: 0x18a5385a2794ac535f6a7f5625146ca66b94bc69ad3866a3d5ebb21457953e7d, + right: 0x1595bb3cd19f84619dc2e368175a88d8627a7439eda9397202cdb1167531fd3f, + result: 0x2fcea1ee353ae539e49d2849d301b333f144e84e5182c4cba69ac2a501526bb9, }, KnownHash { - left: 0x188cce2b840e51b911fc1c3da0d1df5f9b5e96eef52eb26f194a3dc0bd3f4f6a, - right: 0x27ee017018f45efbd35d1c13becfccf19930a17ffdeada836308586f7a17652b, - result: 0x20c10e65b78d3e0bd5100d1a49c1c8dc241358e4bf58a6f65d18513912672142, + left: 0x1a346d41faf0708cb9f8eda3a6849a636407e1ce7bb815478af0c4a21a7379fc, + right: 0x9244eec34977ff795fc41036996ce974136377f521ac8eb9e04642d204783d2, + result: 0x19894df714fdf8a7d0dedc2e61454ea1da351cc98b9d2a71f7d06c14f02ed8, }, KnownHash { - left: 0x18cdcf795ffdc17de3e809e5cfe74f3b158dcd7df94fedffc14fbae90d86a26a, - right: 0x8a9dc89f3b17592f0e55d4e1b818ebd876fc8dafdacb28afb54ad97a482a292, - result: 0x2feee723b36f2a33b5ae9c8fc55a752a119a8d5fa97ca9d9c531a48d74680571, + left: 0x1a752bb7665ea05dae9d38101fe97af168bf4a6ea5b4c0a749e2a1ceb36f1eac, + right: 0x71d7627ae3b2eabda8a810227bf04206370ac78dbf6c372380182dbd3711fe3, + result: 0x9697e416be1dfcb6977d86e065af3be3ec7870c78faa3e9dfd6bd783beec887, }, KnownHash { - left: 0x199f3eb874fc7ecad0a8dcac9d5199a71f88a19599b7dbc679ddd233c46246ac, - right: 0x181312e20b6687d377125bc687e156dc8a2167502524d4e56164ceda881ed5fb, - result: 0x11981f8d15decdcd5c7b8b9408103576b477fae3bfac3d185c83aff74304a4da, + left: 0x1afc4b08b856e546d6ba1018783f295a7e9a31986c1334dbb24a05102ae0388f, + right: 0x1a180441acbe2e25177de322888800476d75191e3c2c753300dedf84de7d2053, + result: 0x3ebecd701f607563e8429d2e27b2476f4f3fd427a8e9cd97028e7c381110241, }, KnownHash { - left: 0x1c38163d2f0e3875a5ee7fe1ec72e1cdf85135d5e8b5512ea5fe6b8e080b8555, - right: 0x2b22abdfce9a96e2c7306ebaf45f64c7e0c2e7738119447776a6aac223565dfa, - result: 0x85c23bd218ed3cef00f2f7062edc726a08ccb2ca5b5886d06ab366de8409339, + left: 0x1b446dccfcf23006b4131b5191e2362da1807a8ea501da614d23fd42eea0e9ae, + right: 0x21f9172d72fdcdafc312eee05cf5092980dda821da5b760a9fb8dbdf607c8a20, + result: 0x2a2fa7a8d8e8b5b67a78bd310de5ce535fe0c013259874f854ca9cb8daa479bb, }, KnownHash { - left: 0x1d12c8e031dbe0b673f702629e60c493b6ab68ad4547b5d89423e07ae5143100, - right: 0x26a66bd2ee4162c99a4f0b04ff2f23b69d7bd5841f642760aa590c77528bcb79, - result: 0x2f0cc8de5f1658173d0ede3c5982116829bc8c5d70d694314b19ca72a239e1b6, + left: 0x1c9c198c9efe5c09f7b10f200de7bab0a56f911c1e61847dbb2b5704a0f8dd8c, + right: 0x1250a6bd4582016e8af7d74a31a7d181864326e50cea97f643b70ec9d94e1efc, + result: 0x3609a7a2916db64630f6d49c0f50f88b776780f40bb4ed7c4219cc4da3ff149, }, KnownHash { - left: 0x1e251bc1c78ae03b4ec5dbdf8aee3a29d5e8e4643639e050947a9d89444f57fb, - right: 0xcf1ec907e066d0522395aba3c93e3b85aed37d1f51d9503a461a33d3d600128, - result: 0x29c2415ebd49cf5f7155ae8f7893477dc1766614e52a5e4023682330bf53042d, + left: 0x1cd19a9633a5c087c45f1836d8fe7532d7f962741483f0b7d3ffdf79fc9146ed, + right: 0x14748d0241710ef47f54b931ac5a58082b1d56b0f0c30d55fb71a6e8c9a6be14, + result: 0x2327223b93cde1ebb53ee3490b761c3f87c33ef9ac156dacc2ed6ed59ea88b48, }, KnownHash { - left: 0x1f4c45f9764aa17b0b277e23e1da0cefd69affc8caa18bb01f65b5c9d9761d21, - right: 0x19014d18a3179c5731155fcb7b6da422f456bccbd6da9dbc7df0f8dc6d4938ed, - result: 0x209946ef716cab484342d4fe6b7bae73700d4798cc85d16c466e7f34e1f94b0e, + left: 0x1e9637e7fc66382c4fee121fde1a125441caea006287ad828b7f17afda749c5b, + right: 0x691a1f6e7dd363914d2754f434659383019fe2a1d10a9ce92d152decccfc5f5, + result: 0x1c9c198c9efe5c09f7b10f200de7bab0a56f911c1e61847dbb2b5704a0f8dd8c, }, KnownHash { - left: 0x1f6f9eed2f50e018b3effaf4df0616e2b968df73961169d7456b44e5743af209, - right: 0x1ef66fa5658e40fec30020d1796a417ee4b81668b49a71318973d23d3822fb0f, - result: 0x2ad3574124c5cc22660c6b0e8959d3e484c51f382f4cbbe804cf048036e8a749, + left: 0x2006484cb63349b65c82c3d0a6ff0651ce628a57f10b796c90e3e07e01ac6fa2, + right: 0x4f95f7efd61e5dfab009860f0e53b7e65686c5dbb1b1a800d597ec130836f92, + result: 0x2e0edcd5254e72e1d8e2419fb5f040126b1f222afffa1164559e7f170b8d44da, }, KnownHash { - left: 0x1fda4b1a96efc9a289327f8749cc3f54f856a3f10a27d79edd50f5090696e5e9, - right: 0x1196ddacfe831a4c4a002c3287c5d7b7e62f393acc5dfb9a44e8d4e42852c630, - result: 0x296f93d726b8e747ed1e3a35292fe899f12d65d6268b77352fe184e2c5801df3, + left: 0x20e4be3fcad2ec132c88c19c5f948dd8de4d688ca60064266eda10796bb342e7, + right: 0x1c4954081e324939350febc2b918a293ebcdaead01be95ec02fcbe8d2c1635d1, + result: 0x61fa1d36181e7c6161c89e1b1848708fd5d8526be8a87ac91a21d5a959fc03b, }, KnownHash { - left: 0x1fe0c6364be10b1624c95dde1add014772203e68a5c49b403975ac0fdad9ac81, - right: 0xa58a88c183eb1f7cb645758052d439d6264fd212a0e8aaa49dcec034a641c05, - result: 0x2132230aa4a59d79a92603c1db703a845ee53fb6181ea6ced927ac74757c7fca, + left: 0x2209049fc09602af8a3bd26f3a9f9cd66f899775494739d649f5c85075024d29, + right: 0x16599e0bb19201fa33d4c00c3f7c5189552a26038ee219b1c8b08fd1b16ecd52, + result: 0x2681dba620c115d1796b6f57482bb954ede9a1927a2d0c14fde2a4362796bdda, }, KnownHash { - left: 0x204706cb933e77eaaeecdd7485d93dfd2c0d6fb14c9eff1501f4450775d1362a, - right: 0xcfcaec39ff6cf9310f45b44abff9f1c8cfbd5428b785592d3ba8626d1c5b467, - result: 0x7c852792038c00199583bbed3fe37fb4e383b98f3c11e608ce759e9bce0d2ec, + left: 0x2327223b93cde1ebb53ee3490b761c3f87c33ef9ac156dacc2ed6ed59ea88b48, + right: 0xb59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d, + result: 0x1100a2dbc8c2fca3c623a6f1e6f9b2e9cff4849e0cb0a3cc6f9fa1967a89753f, }, KnownHash { - left: 0x2064b8acdb79ca2bc427f790164b9eae191dd4b0581cb6a33a698e84ef9416c8, - right: 0xa7f2ad12d4e7b7b47e26e9ac4c50aeeef3340e9e938a0d63263f7d04dc47965, - result: 0x3f7f0d18a3438e8f3abf9ef7ee205b0b82db68d9b24695087dc485d80d30f4, + left: 0x259a407ab93714f2b3e43b5dd310c6fd38cd7adba04598b74034a63fce39248d, + right: 0x121468e6710bf1ffec6d0f26743afe6f88ef55dab40b83ca0a39bc44b196374c, + result: 0x2880f1923f8bf3fd6041776d0b28632b5d3f7ad11729907e2aa9ebf37a3de6b7, }, KnownHash { - left: 0x209946ef716cab484342d4fe6b7bae73700d4798cc85d16c466e7f34e1f94b0e, - right: 0x14265fb8f44d78dbea1f5eb8d90b0bfadbbdfce8a4af8352048d68dc44005475, - result: 0x15bbf5170fdaa7789d1f098aa0f7a71564b4dc5a66b3ade0018a33ecd04d6b22, + left: 0x261c0b8a15816ad46a77fd0c305729987dbfb934c4ee3655cbb74a39a5f6829c, + right: 0x1c28fe1059ae0237b72334700697bdf465e03df03986fe05200cadeda66bd76, + result: 0x5c8dda05fb454f9e8c32121c93afaa0caa3108b5868198cdb4c39ed4b0d41db, }, KnownHash { - left: 0x20c10e65b78d3e0bd5100d1a49c1c8dc241358e4bf58a6f65d18513912672142, - right: 0x544f3743bc9686e28c6c1c6f7e05d9882befbf4d81c1a9c9d19e4ac04f0c772, - result: 0x6f8397381966da0113dc141da278a91e678b21fec0f3175e870d0220a9cac54, + left: 0x2681dba620c115d1796b6f57482bb954ede9a1927a2d0c14fde2a4362796bdda, + right: 0x22f62d7c8204be97acc7644d4b14a422c17e573506e900a4788acbfb8c8b1aba, + result: 0x1e9637e7fc66382c4fee121fde1a125441caea006287ad828b7f17afda749c5b, }, KnownHash { - left: 0x2132230aa4a59d79a92603c1db703a845ee53fb6181ea6ced927ac74757c7fca, - right: 0x2984944ab07ac291118becffefd8dde8da228ddf99057060e402ee82cf68d2f7, - result: 0x28630bca5176fa2b70201d03c6d8677e9f280b5552720812214531a1b8db46a2, + left: 0x286f00030b9b6b2dfa00ea1c70a31ecd733c3791e8fbdef93e93ed34a7b3ae57, + right: 0x21849764e1aa64b83a69e39d27eedaec2a8f97066e5ddb74634ffdb11388dd9a, + result: 0x291b1be21583775a0251fee328a85e2f74ec6096fa449f8a058bb67efedd6d5, }, KnownHash { - left: 0x25017b53780e2e8d1d7cff06aa6eba2c7db205c85103486ef6c1e8d15897bda8, - right: 0x1ae026e0eb3eb3a299c4d6d4b93ab200dd183d951d088c6b73aae56693073e16, - result: 0x7a846a889971f831edad4f09bcf22fb87edd62f9ac994e7d85e38270eb40609, + left: 0x2880f1923f8bf3fd6041776d0b28632b5d3f7ad11729907e2aa9ebf37a3de6b7, + right: 0x2042c32c823a7440ceb6c342f9125f1fe426b02c527cd8fb28c85d02b705e759, + result: 0x2c27a9717c07a0552f720822422670c6490fbdbeb501f911240393f6c5772b36, }, KnownHash { - left: 0x2505f998cb09db6b9e77343816655f82f655683c5b0702ffe24c198c4b1532e6, - right: 0x1fc5c8ba7bea28dcaea544338a6466600d8bbf3eea093c912168dc4544d33109, - result: 0x86ff8756c40a03f52c8835b78896b5e79ff7f3cbe5099965cc3d132cce816ad, + left: 0x295c8d0b994cd68dbbf2ac01722ae489f81b3ee106113b0a2965018047061322, + right: 0x2b9cdd484c5ba1e4d6efcc3f18734b5ac4c4a0b9102e2aeb48521a661d3feee9, + result: 0x82ff964500c30a17ed4b0063b90ca61012c64db9baedaa81fdd404e004bc004, }, KnownHash { - left: 0x2630ea38a7a01caff1272273c737d1d9d7eed7a5b3b84b4ad2b1773a978de5cd, - right: 0x34659157a0f40421b20f7d138b79d1c22f6d5ac16b23ca0ab6791ff40de26eb, - result: 0x1c38163d2f0e3875a5ee7fe1ec72e1cdf85135d5e8b5512ea5fe6b8e080b8555, + left: 0x296884bb350d25da6e170c450cb431aae9537ec713a7f496d729177ef4fbfc0d, + right: 0x131b0345b2f2564b2338810cd8d7b90a8d5a2fcc1a9a8876a494dbe3c8135c6c, + result: 0x9476f6aad2549a02185614273c572c7c91af82b31c7bfd29fd8750f1c6425f4, }, KnownHash { - left: 0x28630bca5176fa2b70201d03c6d8677e9f280b5552720812214531a1b8db46a2, - right: 0x24508e620942303909250d9c9fc529374f64963448da76cfc8475c2c425faab4, - result: 0x2d40afddeff362e563ba40e560615147a96dfe59ac298544d8056f279461d0d1, + left: 0x2a1d92d72939048a6164566e307b381b58dd3e120f4b19c5a13d28fd72bd5afb, + right: 0xd07f6e7a8a0e9199d6d92801fff867002ff5b4808962f9da2ba5ce1bdd26a73, + result: 0x20e4be3fcad2ec132c88c19c5f948dd8de4d688ca60064266eda10796bb342e7, }, KnownHash { - left: 0x2872aa6b0597d605d9e8a54571e316eec2f9fa7217a1bbc02b8eab1862b4f108, - right: 0xfe4d2582275a130e303b95758bebe9003985eea6db0aa7a813170f9d44e6c6b, - result: 0x178167cbbb3d6a65bf2b121c5254b8abcea407f556b55ce9ffb1f03e18f36850, + left: 0x2a2fa7a8d8e8b5b67a78bd310de5ce535fe0c013259874f854ca9cb8daa479bb, + right: 0x2373ea368857ec7af97e7b470d705848e2bf93ed7bef142a490f2119bcf82d8e, + result: 0x5948c417d93fd320e210ed58792c19c22210143b623f3ce2021fc799cb85f06, }, KnownHash { - left: 0x29198057e0a158eafb1069f1f535c5c62117249f180b3e466485af2317493121, - right: 0x19ef5205ba4137f9a5ed1d653c485f020d583f5adf5f82ffb1accbff613dedad, - result: 0x117f56a05ddb98c6b9847e490d02311c44c7a0914734b9cae446dd02b5aa0647, + left: 0x2b081f1ccee4386c0fb90191275f9e16f68050a2707ad7d2ef141841122b3ba4, + right: 0xf2d774b6dc7c8c6c49e2056f9f9e77d510637ff52368027fd8326821c83445a, + result: 0x2209049fc09602af8a3bd26f3a9f9cd66f899775494739d649f5c85075024d29, }, KnownHash { - left: 0x296f93d726b8e747ed1e3a35292fe899f12d65d6268b77352fe184e2c5801df3, - right: 0x2e7cc44f05afd41946244940e561ae69222c657950e6540cf9a5589ac2665887, - result: 0x10627bb93eefe99746a3d5e92f64c81e59d076d651621ed2bf7b61cfd8279677, + left: 0x2bcc14058970b082bc5729e206c3e59b670d48a78aa4ac7c7ebc35520776b0b3, + right: 0xf320b0703439a8114f81593de99cd0b8f3b9bf854601abb5b2ea0e8a3dda4a7, + result: 0x2a1d92d72939048a6164566e307b381b58dd3e120f4b19c5a13d28fd72bd5afb, }, KnownHash { - left: 0x29c2415ebd49cf5f7155ae8f7893477dc1766614e52a5e4023682330bf53042d, - right: 0xda004968db5a60e1689936fa00b858b23187fc0702d07c6b439116d8ee6dec8, - result: 0x199f3eb874fc7ecad0a8dcac9d5199a71f88a19599b7dbc679ddd233c46246ac, + left: 0x2bf8dea925b1912f4dd72f0003d4298060a7eb756f603fb11b7dc6b9b1c68b86, + right: 0x19d4d18c572a9b0b503094e1de87b8594e1d37dd1da42acdb3a19bd35f005a3a, + result: 0x30252cc46f32c5db42ecfded89831b9704641b91445219eb500efff493e34062, }, KnownHash { - left: 0x2ad3574124c5cc22660c6b0e8959d3e484c51f382f4cbbe804cf048036e8a749, - right: 0x193b047ed90559dd7cb4e85140d7f92422e3c69f90a049e8d0be21bec59c7ad9, - result: 0x204706cb933e77eaaeecdd7485d93dfd2c0d6fb14c9eff1501f4450775d1362a, + left: 0x2c27a9717c07a0552f720822422670c6490fbdbeb501f911240393f6c5772b36, + right: 0xd582c10ff8115413aa5b70564fdd2f3cefe1f33a1e43a47bc495081e91e73e5, + result: 0x11b312d35f1106fe78aa6cd40f2b838707a500396ca2311670426adcf1b435b8, }, KnownHash { - left: 0x2ce7ec2454da4cd4347c2c8bf0c49c1b7ef34582738b10345baddd9b57e664d5, - right: 0x285013a6c0d3d6b7ee02566ebcba866ed801ddcf6eb852522c2b195c3287de7d, - result: 0x91471564f3cc6a2f4cdd4b149c8f19b6b25bc860ea015bc846a25e6e70391c2, + left: 0x2c31b494a5f558ae26bfd601cec1dfb21eded28f43c4906b133c2aa734679046, + right: 0x1b593cc9332c0bb29333e5833284e18e765bb17fc0a7718f6b21d8a833a0765b, + result: 0x575f52be4a0a1f62f2a222034330b1d9972079019fbccfb1d62a690d03eb9e1, }, KnownHash { - left: 0x2d0f5cc297643f783b3f6a53806427fa77b7b219db632c39bbb7470829b060c3, - right: 0x1e60f854fccdf9186e6fdeffe35b1781d72a5e5084c1f9cdacbdf59682b2b6da, - result: 0x188cce2b840e51b911fc1c3da0d1df5f9b5e96eef52eb26f194a3dc0bd3f4f6a, + left: 0x2d095e2920660da0bf42f8d8598185f7e3e00d1d8052bab558af3b5577a3b7ee, + right: 0x1f0c1a8fb16b0d2ac9a146d7ae20d8d179695a92a79ed66fc45d9da4532459b3, + result: 0x233750fdee4c0c4e2e81e2a564d37ba9945cc31ed1ac65b6ffa980b6c0cbf2c, }, KnownHash { - left: 0x2d40afddeff362e563ba40e560615147a96dfe59ac298544d8056f279461d0d1, - right: 0x507c07e3bf4b56fcee9aa982dddfbe440e02ea3beb0cb8a9ae95ddfda5fbbde, - result: 0xbbb801ecbb5fd9ec362507447351d3d820c19490521899eebd9096dfbf37630, + left: 0x2dc5a80e7427fbd76213c2b4e598773a97706278adbe384b739432efd226a466, + right: 0x5e7d0fbf97820e4f7e37899bee6f967bc67f5b396f760665eb5ce76f51cff90, + result: 0x56f5da7a12267c0caec8cec7dca1bedd1711a43b3026c74abe55da4368e770c, }, KnownHash { - left: 0x2db89f0a1d022e30f5322d55eb614aa62def55feb925d4d4a25f16f04d50afdb, - right: 0x93c360a8f834b92f7e5eac996f164a0a05c3ea454b334efa8b7dcfc2603a179, - result: 0x3036c6d2cca0f02ed8dc1ce15be49126003ac395b6a5530be9c11fdd005b43fa, + left: 0x2e0edcd5254e72e1d8e2419fb5f040126b1f222afffa1164559e7f170b8d44da, + right: 0x74b0f589c0d62b3ee0d70fd057f9d0e143a6b888d0a9f60ac1d0f1c77ddf863, + result: 0x2dc5a80e7427fbd76213c2b4e598773a97706278adbe384b739432efd226a466, }, KnownHash { - left: 0x2f0cc8de5f1658173d0ede3c5982116829bc8c5d70d694314b19ca72a239e1b6, - right: 0x2d0e0d42612b3497ab4033be4d8bce8324b48b1b1e7d7eedddc70a43e8a11b53, - result: 0x12dc8d0fe6f6c5064e4131c6f89da61903405676444c602c9bea940b02b9519c, + left: 0x2e3d1307a2ddbf78320bf6ee17a9a8cf2a3946c85e05b5bbe57e2a444e2c4913, + right: 0x2a775ea761d20435b31fa2c33ff07663e24542ffb9e7b293dfce3042eb104686, + result: 0x2bcc14058970b082bc5729e206c3e59b670d48a78aa4ac7c7ebc35520776b0b3, }, KnownHash { - left: 0x2feee723b36f2a33b5ae9c8fc55a752a119a8d5fa97ca9d9c531a48d74680571, - right: 0x18d5107e17690548b5fc2cd3c2c532f40448ba29166611ed139261125ac95ed8, - result: 0x2630ea38a7a01caff1272273c737d1d9d7eed7a5b3b84b4ad2b1773a978de5cd, + left: 0x2fcea1ee353ae539e49d2849d301b333f144e84e5182c4cba69ac2a501526bb9, + right: 0x2a529be462b81ca30265b558763b1498289c9d88277ab14f0838cb1fce4b472c, + result: 0x7b4fe1badae979a7e794b5ae22e45d4928be29008ca73dcd60bd287605a6c39, }, KnownHash { - left: 0x3036c6d2cca0f02ed8dc1ce15be49126003ac395b6a5530be9c11fdd005b43fa, - right: 0x36724ee92610cbd02258014d4252e5dbf8e55c85f3fca802ab2d33069e560df, - result: 0x2ce7ec2454da4cd4347c2c8bf0c49c1b7ef34582738b10345baddd9b57e664d5, + left: 0x30252cc46f32c5db42ecfded89831b9704641b91445219eb500efff493e34062, + right: 0x24d3e3c36e11f6dac11d08927f0a925e2c4c42248a913c18da9f5cc0da73836a, + result: 0x296884bb350d25da6e170c450cb431aae9537ec713a7f496d729177ef4fbfc0d, }, ] diff --git a/pkg/smirk/src/storage/tests.rs b/pkg/smirk/src/storage/tests.rs index 6d80f07..3ededf3 100644 --- a/pkg/smirk/src/storage/tests.rs +++ b/pkg/smirk/src/storage/tests.rs @@ -4,7 +4,7 @@ use expect_test::expect_file; use tempdir::TempDir; use test_strategy::proptest; -use crate::{batch, Batch}; +use crate::{Batch, batch}; use super::*; @@ -75,32 +75,37 @@ fn insert_batch_works(batch_1: Batch<64, i32>, mut batch_2: Batch<64, i32>) { let (_dir1, path) = setup_path(); let mut persistent = Persistent::<64, i32>::new(&path).unwrap(); - for element in batch_1.elements() { - batch_2.remove(element); + for element in batch_1.insert_elements() { + batch_2.remove(element).unwrap(); } - let batch_1_elements: HashSet<_> = batch_1.elements().collect(); - let batch_2_elements: HashSet<_> = batch_2.elements().collect(); + let batch_1_elements: HashSet<_> = batch_1.insert_elements().collect(); + let batch_2_elements: HashSet<_> = batch_2.remove_elements().collect(); persistent.insert_batch(batch_1).unwrap(); - persistent.insert_batch(batch_2).unwrap(); drop(persistent); - let loaded = Persistent::<64, i32>::load(&path).unwrap(); + let mut loaded = Persistent::<64, i32>::load(&path).unwrap(); for element in batch_1_elements { assert!(loaded.tree().contains_element(&element)); } + loaded.insert_batch(batch_2).unwrap(); + + drop(loaded); + + let loaded = Persistent::<64, i32>::load(&path).unwrap(); + for element in batch_2_elements { - assert!(loaded.tree().contains_element(&element)); + assert!(!loaded.tree().contains_element(&element)); } } macro_rules! expect_storage_known_hashes { ($persistent:expr, hashes: $expected_hashes:expr) => {{ - use crate::storage::load::{entries, RocksbEntry}; + use crate::storage::load::{RocksbEntry, entries}; let known_hashes_in_db = entries::<()>($persistent.db()) .collect::, _>>() @@ -126,9 +131,9 @@ fn insert_batch_hash_test() { expect_storage_known_hashes!( persistent, hashes: - expect_test::expect![[r#" + expect_test::expect![[r" [] - "#]] + "]] ); let batch = batch! { 1, 2, 3 }; diff --git a/pkg/smirk/src/tree/batch.rs b/pkg/smirk/src/tree/batch.rs index 8bef03d..7341ff5 100644 --- a/pkg/smirk/src/tree/batch.rs +++ b/pkg/smirk/src/tree/batch.rs @@ -1,6 +1,8 @@ -use zk_primitives::Element; +use std::collections::HashSet; -use crate::{hash_cache::HashCache, Batch, Collision, CollisionError, Tree}; +use element::Element; + +use crate::{Batch, Collision, CollisionError, Tree, hash_cache::HashCache}; impl Tree { /// Check whether this batch contains any [`Element`]s which would collide with an [`Element`] @@ -8,6 +10,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree: Tree<64, ()> = smirk! { 1, 2, 3 }; /// /// let good_batch: Batch<64, ()> = batch! { 4, 5 }; @@ -19,32 +22,63 @@ impl Tree { /// assert_eq!(error.collisions().len(), 1); /// ``` /// - /// [`Element`]: crate::Element + /// [`Element`]: element::Element pub fn check_collisions(&self, batch: &Batch) -> Result<(), CollisionError> { let mut error = CollisionError::new(); let tree_lsbs = self .entries .keys() - .map(|element| (element, element.lsb(DEPTH - 1))); - - for (tree_element, tree_lsb) in tree_lsbs { - if batch.lsbs.contains(&tree_lsb) { + .map(|element| (element, element.lsb(DEPTH - 1))) + .collect::>(); + + let batch_insert_lsbs = batch + .insert_elements() + .map(|e| e.lsb(DEPTH - 1)) + .collect::>(); + let batch_remove_lsbs = batch + .remove_elements() + .map(|e| (e, e.lsb(DEPTH - 1))) + .collect::>(); + + for (tree_element, tree_lsb) in &tree_lsbs { + if batch_insert_lsbs.contains(tree_lsb) { // unwrap fine because there is definitely a collision here let batch_element = batch - .elements() - .find(|e| e.lsb(DEPTH - 1) == tree_lsb) + .insert_elements() + .chain(batch.remove_elements()) + .find(|e| e.lsb(DEPTH - 1) == *tree_lsb) .unwrap(); error.push(Collision { depth: DEPTH, - in_tree: *tree_element, + in_tree: **tree_element, inserted: batch_element, struct_name: super::StructName::Tree, }); } } + for (batch_remove_element, batch_remove_element_lsb) in batch_remove_lsbs { + if !tree_lsbs + .iter() + .any(|(_, lsb)| batch_remove_element_lsb == *lsb) + { + if option_env!("TEMP_NOIR") != Some("1") { + todo!( + "we should return something else than collision error here. This is an error that happens if the user wants to remove an element that's not in the tree" + ); + } + + error.push(Collision { + depth: DEPTH, + in_tree: Element::ZERO, + inserted: batch_remove_element, + struct_name: super::StructName::Tree, + }); + } + } + if !error.is_empty() { return Err(error); } @@ -59,6 +93,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree: Tree<64, ()> = smirk! { 1, 2, 3 }; /// let batch: Batch<64, ()> = batch! { 4, 5 }; /// @@ -75,9 +110,14 @@ impl Tree { ) -> Result<(), CollisionError> { self.check_collisions(&batch)?; - let Batch { entries, .. } = batch; + let Batch { + entries, + remove_entries, + lsbs: _, + } = batch; - self.insert_without_hashing(entries).unwrap(); + self.insert_without_hashing(entries, &remove_entries) + .unwrap(); tracing::info_span!("recalculate_hashes").in_scope(|| { self.tree @@ -98,7 +138,7 @@ mod tests { #[proptest] fn can_always_insert_into_empty_tree(batch: Batch<64, ()>) { - let elements: HashSet<_> = batch.elements().collect(); + let elements: HashSet<_> = batch.insert_elements().collect(); let mut tree = Tree::<64, ()>::new(); tree.insert_batch(batch, |_| {}, |_| {}).unwrap(); @@ -109,11 +149,11 @@ mod tests { #[proptest] fn fixed_batch_can_always_insert(mut batch: Batch<64, ()>, mut tree: Tree<64, ()>) { - for (element, _) in tree.elements() { - batch.remove(*element); + for (element, ()) in tree.elements() { + batch.remove(*element).unwrap(); } - let elements_in_batch: HashSet<_> = batch.elements().collect(); + let elements_in_batch: HashSet<_> = batch.insert_elements().collect(); tree.insert_batch(batch, |_| {}, |_| {}).unwrap(); diff --git a/pkg/smirk/src/tree/error.rs b/pkg/smirk/src/tree/error.rs index 4690fa2..bf35e34 100644 --- a/pkg/smirk/src/tree/error.rs +++ b/pkg/smirk/src/tree/error.rs @@ -1,9 +1,10 @@ -use zk_primitives::Element; +use element::Element; /// An error indicating at least one collision occurred when trying to insert a value into the tree /// /// ```rust /// # use smirk::*; +/// # use element::Element; /// let mut tree: Tree<64, _> = smirk! { 1 }; /// /// let colliding_element = Element::ONE + (Element::ONE << 100); @@ -83,7 +84,11 @@ impl core::fmt::Display for Collision { StructName::Tree => "tree", }; - write!(f, "collision: tried to insert {inserted}, but {in_tree} was already in the {struct_name}, which have the same least significant {} bits", depth - 1) + write!( + f, + "collision: tried to insert {inserted}, but {in_tree} was already in the {struct_name}, which have the same least significant {} bits", + depth - 1 + ) } } @@ -92,6 +97,7 @@ impl Collision { /// /// ```rust /// use smirk::*; + /// use element::Element; /// let mut tree: Tree<64, _> = smirk! { 1 }; /// let collides = Element::ONE + (Element::ONE << 100); /// let error = tree.insert(collides, ()).unwrap_err(); @@ -109,6 +115,7 @@ impl Collision { /// /// ```rust /// use smirk::*; + /// use element::Element; /// let mut tree: Tree<64, _> = smirk! { 1 }; /// let collides = Element::ONE + (Element::ONE << 100); /// let error = tree.insert(collides, ()).unwrap_err(); diff --git a/pkg/smirk/src/tree/insert.rs b/pkg/smirk/src/tree/insert.rs index 14e5f4b..49f33f4 100644 --- a/pkg/smirk/src/tree/insert.rs +++ b/pkg/smirk/src/tree/insert.rs @@ -1,4 +1,6 @@ -use crate::{batch, hash_cache::HashCache, CollisionError, Element, Path, Tree}; +// lint-long-file-override allow-max-lines=300 +use crate::{CollisionError, Path, Tree, batch, hash_cache::HashCache}; +use element::Element; impl Tree { /// Insert a non-null element and a value into the tree @@ -9,6 +11,7 @@ impl Tree { /// - If the tree already contained this an entry at this element, `false` is returned /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree = Tree::<64, i32>::new(); /// /// let res = tree.insert(Element::new(1), 123); @@ -32,6 +35,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree = Tree::<64, i32>::new(); /// tree.insert(Element::new(1), 123).unwrap(); /// @@ -60,6 +64,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree = Tree::<64, i32>::new(); /// /// let elements = (1..=10).map(|i| (Element::new(i), i as i32)); @@ -88,7 +93,7 @@ impl Tree { pub fn insert_with_paths>( &mut self, entries: I, - ) -> Result>, CollisionError> + ) -> Result, CollisionError> where C: HashCache, { @@ -112,10 +117,7 @@ impl Tree { /// was inserted /// /// This function is a convenience wrapper around [`Tree::insert_with_paths`] - pub fn insert_with_paths_default( - &mut self, - elements: I, - ) -> Result>, CollisionError> + pub fn insert_with_paths_default(&mut self, elements: I) -> Result, CollisionError> where I: IntoIterator, V: Default, @@ -139,7 +141,7 @@ mod tests { use test_strategy::proptest; - use crate::{smirk, tree::error::StructName, Collision}; + use crate::{Collision, smirk, tree::error::StructName}; use super::*; @@ -151,7 +153,7 @@ mod tests { assert!(res.is_ok()); assert_eq!( format!("0x{:x}", tree.root_hash()), - "0x26debce8a5ba1d092589121944bfc2cc55d858bcd7a697ec2fd1b832b4b20c40" + "0x5281c6856f41bb70d2d33a56206f93b20da3babd86361d692e7422d505ca654" ); let res = tree.insert(Element::new(1), 1); @@ -188,7 +190,7 @@ mod tests { for (element, value) in entries { match tree.insert(element, value) { Err(_) => assert_eq!(tree.root_hash(), last_hash), - Ok(_) => { + Ok(()) => { let new_root_hash = tree.root_hash(); assert!(!seen_hashes.contains(&new_root_hash)); @@ -209,7 +211,9 @@ mod tests { let tree_3: Tree<64, _> = smirk! { 3, 6, 8 }; let paths = tree.insert_with_paths_default(elements).unwrap(); - let [first, second, third] = &paths[..] else { panic!() }; + let [first, second, third] = &paths[..] else { + panic!() + }; assert_eq!(first.actual_root_hash(), tree_1.root_hash(),); assert_eq!(second.actual_root_hash(), tree_2.root_hash(),); diff --git a/pkg/smirk/src/tree/iter.rs b/pkg/smirk/src/tree/iter.rs index 8b244ef..550c787 100644 --- a/pkg/smirk/src/tree/iter.rs +++ b/pkg/smirk/src/tree/iter.rs @@ -1,12 +1,15 @@ +use crate::Tree; +use element::Element; use std::collections::btree_map; -use crate::{Element, Tree}; - #[derive(Debug, Clone)] pub struct Elements<'a, V> { inner: btree_map::Iter<'a, Element, V>, } +/// Backwards-compatible alias for the historical iterator type. +pub type Iter<'a, V> = Elements<'a, V>; + impl<'a, V> Iterator for Elements<'a, V> { type Item = (&'a Element, &'a V); @@ -25,6 +28,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree: Tree<64, _> = smirk! { 1, 2, 3 }; /// /// let vec: Vec<(&Element, &())> = tree.elements().collect(); @@ -38,7 +42,7 @@ impl Tree { #[inline] #[must_use] #[doc(alias = "iter")] - pub fn elements(&self) -> Elements { + pub fn elements(&self) -> Iter<'_, V> { let inner = self.entries.iter(); Elements { inner } } @@ -67,30 +71,6 @@ impl IntoIterator for Tree { } } -/// An [`Iterator`] over [`Element`]s and values -#[derive(Debug, Clone)] -pub struct Iter<'a, V> { - inner: btree_map::Iter<'a, Element, V>, -} - -impl<'a, V> Iterator for Iter<'a, V> { - type Item = (&'a Element, &'a V); - - fn next(&mut self) -> Option { - self.inner.next() - } -} - -impl Tree { - /// Get an iterator over elements and values - #[must_use] - pub fn iter(&self) -> Iter { - Iter { - inner: self.entries.iter(), - } - } -} - #[cfg(test)] mod tests { use test_strategy::proptest; diff --git a/pkg/smirk/src/tree/known_hashes.rs b/pkg/smirk/src/tree/known_hashes.rs index 951e211..53be71c 100644 --- a/pkg/smirk/src/tree/known_hashes.rs +++ b/pkg/smirk/src/tree/known_hashes.rs @@ -1,4 +1,4 @@ -use crate::{hash_cache::KnownHash, Tree}; +use crate::{Tree, hash_cache::KnownHash}; use super::tree_repr::Node; @@ -42,7 +42,8 @@ impl Node { #[cfg(test)] mod tests { - use zk_primitives::{hash_merge, Element}; + use element::Element; + use hash::hash_merge; use crate::{hash::empty_tree_hash, smirk}; diff --git a/pkg/smirk/src/tree/mod.rs b/pkg/smirk/src/tree/mod.rs index 57f4a45..30b701a 100644 --- a/pkg/smirk/src/tree/mod.rs +++ b/pkg/smirk/src/tree/mod.rs @@ -1,7 +1,6 @@ -use crate::{ - hash_cache::{HashCache, NoopHashCache}, - Element, -}; +// lint-long-file-override allow-max-lines=300 +use crate::hash_cache::{HashCache, NoopHashCache}; +use element::Element; use std::collections::BTreeMap; mod batch; @@ -11,15 +10,14 @@ mod iter; mod known_hashes; mod path; mod raw_api; +mod remove; mod tree_repr; pub use error::{Collision, CollisionError}; -pub use iter::{Elements, IntoIter, Iter}; pub use path::Path; pub(crate) use error::StructName; -#[cfg(any(test, feature = "proptest"))] pub mod proptest; /// A sparse Merkle tree @@ -29,6 +27,7 @@ pub mod proptest; /// /// ```rust /// # use smirk::*; +/// # use element::Element; /// let mut tree = Tree::<64, i32>::new(); /// /// tree.insert(Element::new(1), 123); @@ -37,13 +36,14 @@ pub mod proptest; /// /// assert!(tree.contains_element(&Element::new(1))); /// -/// for (element, value) in tree.iter() { +/// for (element, value) in tree.into_iter() { /// println!("the tree contains {value} at element {element}"); /// } /// ``` #[derive(Debug, Clone)] pub struct Tree { /// The tree-like representation + #[expect(clippy::struct_field_names)] tree: tree_repr::Node, entries: BTreeMap, cache: C, @@ -73,6 +73,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree = Tree::<64, i32>::new(); /// assert!(tree.is_empty()); /// ``` @@ -93,6 +94,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree = Tree::<64, i32>::new(); /// assert!(tree.is_empty()); /// ``` @@ -110,6 +112,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// # use smirk::hash_cache::*; /// let tree = Tree::<64, i32, NoopHashCache>::new(); /// let cache = tree.cache(); @@ -126,6 +129,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree = Tree::<64, i32>::new(); /// /// assert_eq!(tree.len(), 0); @@ -146,6 +150,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree = Tree::<64, i32>::new(); /// /// assert_eq!(tree.is_empty(), true); @@ -164,6 +169,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree: Tree<64, _> = smirk! { 1, 2, 3 }; /// /// assert_eq!(tree.contains_element(&Element::new(1)), true); @@ -184,6 +190,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree = Tree::<64, i32>::new(); /// let hash_1 = tree.root_hash(); /// @@ -213,8 +220,9 @@ where /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let mut tree = Tree::<64, ()>::new(); - /// let hash_with_1 = tree.root_hash_with(&[Element::new(1)]); + /// let hash_with_1 = tree.root_hash_with(&[Element::new(1)], &[]); /// /// tree.insert(Element::new(1), ()); /// @@ -223,8 +231,12 @@ where #[inline] #[must_use] #[tracing::instrument(skip(self))] - pub fn root_hash_with(&self, extra_elements: &[Element]) -> Element { + pub fn root_hash_with( + &self, + insert_elements: &[Element], + remove_elements: &[Element], + ) -> Element { self.tree - .hash_with::(self.cache(), extra_elements.to_vec()) + .hash_with::(self.cache(), insert_elements, remove_elements) } } diff --git a/pkg/smirk/src/tree/path.rs b/pkg/smirk/src/tree/path.rs index 1ef207b..705306a 100644 --- a/pkg/smirk/src/tree/path.rs +++ b/pkg/smirk/src/tree/path.rs @@ -1,6 +1,6 @@ -use std::iter::zip; - -use crate::{Element, Lsb, Tree}; +// lint-long-file-override allow-max-lines=400 +use crate::Tree; +use element::{Element, Lsb}; use super::tree_repr::Node; @@ -22,6 +22,7 @@ use super::tree_repr::Node; /// To get a [`Path`], generate it from a tree: /// ```rust /// # use smirk::*; +/// # use element::Element; /// let tree: Tree<64, _> = smirk! { 1, 2, 3, 4, 5 }; /// /// // generate a path for the element 1 @@ -44,23 +45,17 @@ use super::tree_repr::Node; /// assert_ne!(hash_if_collision, tree.root_hash()); /// ``` #[derive(Debug, Clone)] -pub struct Path { +pub struct Path { /// The siblings of the element with the deepest siblings first - /// - /// The first N - 1 values are the siblings, and the last value is the element that created - /// this [`Path`] - /// - /// Ideally, we would have 2 fields here: - /// - `siblings: [Element: {N - 1}]` - /// - `element: Element` - /// Unfortunately, Rust doesn't yet support this. So we just squeeze them together and deal - /// with it 🤷 - pub siblings: [Element; DEPTH], + pub siblings: Vec, + + /// The element that this path leads to + pub element: Element, pub(crate) root_hash: Element, } -impl Path { +impl Path { /// Get a slice of siblings in this path /// /// Note that a [`Tree`] will generate a `Path` (due to limitations in Rust's @@ -68,6 +63,7 @@ impl Path { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree = Tree::<64, i32>::new(); /// let path = tree.path_for(Element::ONE); /// assert_eq!(path.siblings_deepest_first().len(), 63); @@ -75,7 +71,7 @@ impl Path { #[inline] #[must_use] pub fn siblings_deepest_first(&self) -> &[Element] { - &self.siblings[0..(DEPTH - 1)] + &self.siblings } /// The [`Element`] that this path proves the (non) existance of (i.e. the argument to @@ -83,6 +79,7 @@ impl Path { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree = Tree::<64, ()>::default(); /// let element = Element::new(1234); /// @@ -92,7 +89,7 @@ impl Path { #[inline] #[must_use] pub fn element(&self) -> Element { - *self.siblings.last().unwrap() + self.element } /// The bits that are used by this path to determine left/right choices @@ -101,6 +98,7 @@ impl Path { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree = Tree::<4, i32>::default(); /// let path = tree.path_for(Element::ONE); /// let bits: Vec = path.lsb().iter().copied().collect(); @@ -114,7 +112,7 @@ impl Path { #[must_use] #[doc(alias = "least_significant_bits")] pub fn lsb(&self) -> Lsb { - self.element().lsb(DEPTH - 1) + self.element().lsb(self.siblings.len()) } /// Check whether this [`Path`] proves the existance of the given [`Element`] @@ -124,6 +122,7 @@ impl Path { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree: Tree<64, _> = smirk! { 1, 2, 3 }; /// /// let path_for_1 = tree.path_for(Element::new(1)); @@ -148,6 +147,7 @@ impl Path { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree: Tree<64, ()> = smirk! { 1, 2, 3, 4, 5 }; /// let element = Element::new(3); /// @@ -161,21 +161,19 @@ impl Path { /// assert_ne!(root_hash_if_null, tree.root_hash()); /// ``` /// - /// Internally, this function calls [`zk_primitives::compute_merkle_root`]. See the docs for + /// Internally, this function calls [`hash::compute_merkle_root`]. See the docs for /// that function for more details #[must_use] pub fn compute_root_hash(&self, element: Element) -> Element { - // `.lsb()` yields bits in *big endian* order - so we need to reverse them - let bits = self.lsb().into_iter().rev(); - let siblings = self.siblings_deepest_first().iter().copied(); - - zk_primitives::compute_merkle_root(element, zip(siblings, bits)) + let siblings = self.siblings_deepest_first(); + hash::compute_merkle_root(element, self.element(), siblings) } /// The root hash of the tree when this path was created /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree: Tree<64, _> = smirk! { 1, 2, 3, 4, 5 }; /// let path = tree.path_for(Element::ONE); /// @@ -194,6 +192,7 @@ impl Tree { /// /// ```rust /// # use smirk::*; + /// # use element::Element; /// let tree: Tree<64, _> = smirk! { /// 1 => 123, /// 2 => 234, @@ -213,10 +212,11 @@ impl Tree { /// Given that, this function cannot fail, since every location is conceptually occupied /// (either with a real value or [`Element::NULL_HASH`]) #[must_use] - pub fn path_for(&self, element: Element) -> Path { + pub fn path_for(&self, element: Element) -> Path { let bits = element.lsb(DEPTH - 1); - let mut siblings = [Element::NULL_HASH; DEPTH]; + let mut siblings = Vec::with_capacity(DEPTH - 1); + siblings.resize(DEPTH - 1, Element::NULL_HASH); let mut tree = &self.tree; for (index, bit) in bits.iter().enumerate() { @@ -251,14 +251,12 @@ impl Tree { } } - // set the last element - *siblings.last_mut().unwrap() = element; - // reverse the siblings so they are in depth-first order siblings[0..DEPTH - 1].reverse(); Path { siblings, + element, root_hash: self.root_hash(), } } diff --git a/pkg/smirk/src/tree/proptest.rs b/pkg/smirk/src/tree/proptest.rs index aa249ce..07ce956 100644 --- a/pkg/smirk/src/tree/proptest.rs +++ b/pkg/smirk/src/tree/proptest.rs @@ -1,8 +1,8 @@ use ::proptest::{arbitrary::StrategyFor, prelude::*, strategy::Map}; use crate::{ - hash_cache::{HashCache, NoopHashCache, SimpleHashCache}, Batch, Tree, + hash_cache::{HashCache, NoopHashCache, SimpleHashCache}, }; impl Arbitrary for Tree diff --git a/pkg/smirk/src/tree/raw_api.rs b/pkg/smirk/src/tree/raw_api.rs index 9c5f10d..b40f729 100644 --- a/pkg/smirk/src/tree/raw_api.rs +++ b/pkg/smirk/src/tree/raw_api.rs @@ -1,6 +1,6 @@ -use crate::{hash_cache::HashCache, Collision, Element, Tree}; - -use super::error::StructName; +use super::{error::StructName, tree_repr::Change}; +use crate::{Collision, Tree, hash_cache::HashCache}; +use element::Element; impl Tree where @@ -9,13 +9,24 @@ where /// Insert into the tree and btreemap at the same time, without updating the hash pub(crate) fn insert_without_hashing( &mut self, - entries: Vec<(Element, V)>, + insert_entries: Vec<(Element, V)>, + remove_entries: &[Element], ) -> Result<(), Collision> { - if entries.is_empty() { + let insert_elements = insert_entries + .iter() + .map(|(e, _)| e) + .copied() + .collect::>(); + + if insert_elements.is_empty() && remove_entries.is_empty() { return Ok(()); } - if entries.iter().any(|(e, _)| e == &Element::NULL_HASH) { + if insert_elements + .iter() + .chain(remove_entries.iter()) + .any(|e| e == &Element::NULL_HASH) + { return Err(Collision { inserted: Element::NULL_HASH, in_tree: Element::NULL_HASH, @@ -24,7 +35,10 @@ where }); } - if let Some((element, _)) = entries.iter().find(|(e, _)| self.entries.contains_key(e)) { + if let Some(element) = insert_elements + .iter() + .find(|e| self.entries.contains_key(e)) + { return Err(Collision { in_tree: *element, inserted: *element, @@ -33,10 +47,23 @@ where }); } - let mut elements_and_bits = Vec::with_capacity(entries.len()); - for (element, _) in &entries { + if let Some(element) = remove_entries + .iter() + .find(|e| !self.entries.contains_key(e)) + { + todo!( + "return error that we can't remove this element because it's not in tree {element:?}" + ); + } + + let mut elements_and_bits = Vec::with_capacity(insert_entries.len() + remove_entries.len()); + for (change, element) in insert_entries + .iter() + .map(|(e, _)| (Change::Insert, e)) + .chain(remove_entries.iter().map(|e| (Change::Remove, e))) + { // if the tree has depth n, we need n-1 bits, since there are n-1 left/right decisions - elements_and_bits.push((element, element.lsb(DEPTH - 1).to_bitvec())); + elements_and_bits.push(((change, *element), element.lsb(DEPTH - 1).to_bitvec())); } elements_and_bits.sort_unstable_by(|(_, a_bits), (_, b_bits)| a_bits.cmp(b_bits)); @@ -48,14 +75,18 @@ where match result { true => { - for (element, value) in entries { + for (element, value) in insert_entries { self.entries.insert(element, value); } + + for element in remove_entries { + self.entries.remove(element); + } } false => unreachable!( "we check if the tree contains the element earlier, so this should be impossible" ), - }; + } Ok(()) } diff --git a/pkg/smirk/src/tree/remove.rs b/pkg/smirk/src/tree/remove.rs new file mode 100644 index 0000000..71be318 --- /dev/null +++ b/pkg/smirk/src/tree/remove.rs @@ -0,0 +1,14 @@ +use crate::{Batch, CollisionError, Tree, hash_cache::HashCache}; +use element::Element; + +impl Tree { + /// Remove a non-null element from the tree + pub fn remove(&mut self, element: Element) -> Result<(), CollisionError> + where + C: HashCache, + { + let mut b = Batch::new(); + b.remove(element)?; + self.insert_batch(b, |_| {}, |_| {}) + } +} diff --git a/pkg/smirk/src/tree/tree_repr.rs b/pkg/smirk/src/tree/tree_repr.rs index 5cf4abe..a193904 100644 --- a/pkg/smirk/src/tree/tree_repr.rs +++ b/pkg/smirk/src/tree/tree_repr.rs @@ -1,6 +1,8 @@ +// lint-long-file-override allow-max-lines=400 use bitvec::{prelude::Msb0, vec::BitVec}; -use crate::{hash::empty_tree_hash, hash_cache::HashCache, Collision, Element}; +use crate::{Collision, hash::empty_tree_hash, hash_cache::HashCache}; +use element::Element; use super::StructName; @@ -26,85 +28,194 @@ pub(crate) enum Node { }, } +#[derive(Debug, Clone, Copy)] +pub enum Change { + Insert, + Remove, +} + impl Node { + /// Calculates the root hash as if the given insertions and removals were applied. + /// Does not modify the actual tree node. pub fn hash_with( &self, cache: &C, - extra_elements: Vec, + insert_elements: &[Element], + remove_elements: &[Element], ) -> Element { - let mut extra_elements_with_bits = extra_elements - .into_iter() - .map(|e| (e, e.lsb(DEPTH - 1).to_bitvec())) + // Combine insertions and removals into a single list with change type + let mut changes_with_bits: Vec<((Change, Element), BitVec)> = insert_elements + .iter() + .map(|&e| ((Change::Insert, e), e.lsb(DEPTH - 1).to_bitvec())) .collect::>(); - extra_elements_with_bits.sort_unstable_by(|(_, a_bits), (_, b_bits)| a_bits.cmp(b_bits)); + changes_with_bits.extend( + remove_elements + .iter() + .map(|&e| ((Change::Remove, e), e.lsb(DEPTH - 1).to_bitvec())), + ); + + // Sort based on the LSB path. This is crucial for correct processing. + changes_with_bits.sort_unstable_by(|(_, a_bits), (_, b_bits)| a_bits.cmp(b_bits)); + + // Separate back into changes and bits vectors + let (changes, bits): (Vec<_>, Vec<_>) = changes_with_bits.into_iter().unzip(); - let (elements, bits): (Vec<_>, Vec<_>) = extra_elements_with_bits.into_iter().unzip(); - self.hash_with_inner::(cache, &elements, &bits, 0) + // Start the recursive hash calculation + self.hash_with_inner::(cache, &changes, &bits, 0) } + /// Recursive helper for `hash_with`. + #[allow(clippy::too_many_lines)] fn hash_with_inner( &self, cache: &C, - extra_elements: &[Element], - extra_elements_bits: &[BitVec], + changes: &[(Change, Element)], // Sorted list of changes (insert/remove, element) + bits: &[BitVec], // Corresponding sorted LSB paths path_depth: usize, ) -> Element { + if changes.is_empty() { + // No pending updates for this subtree, so the cached hash is still valid unless this + // node was marked dirty. When dirty, we must recompute to avoid returning a stale + // cached value. + if let Self::Parent { + left, + right, + hash_dirty, + .. + } = self + && *hash_dirty + { + let left_hash = + left.hash_with_inner::(cache, changes, bits, path_depth + 1); + let right_hash = + right.hash_with_inner::(cache, changes, bits, path_depth + 1); + + return cache.hash(left_hash, right_hash); + } + + return self.hash(); + } + match self { - Self::Leaf(element) => *element, + Self::Leaf(current_element) => { + // Check if any change affects *this specific leaf path*. + // Since changes are sorted by path, only the first change (if any) + // could possibly affect this leaf. + assert!( + changes.len() <= 1, + "Logic error: Multiple changes target the same leaf path in hash_with_inner" + ); + + match changes.first() { + Some((Change::Insert, new_element)) => { + // An insert targets this leaf's path. Assume it replaces the current one. + // Collision check (LSBs must match) should ideally happen before. + debug_assert_eq!( + current_element.lsb(DEPTH - 1), + new_element.lsb(DEPTH - 1), + "LSB mismatch at leaf during hash_with insert simulation" + ); + *new_element // Hash reflects the element *after* the change + } + Some((Change::Remove, removed_element)) => { + // A remove targets this leaf's path. + // Check if it's removing the element currently here. + if current_element == removed_element { + empty_tree_hash(1) // Removed, so becomes empty + } else { + // Attempting to remove a different element than what's present. + // This indicates either an invalid removal request (should be checked before) + // or the removal targets an element that *was* here but got replaced + // by an earlier insert in the same batch (complex case). + // For hash_with, we assume the state *after* all changes. If this leaf + // wasn't the one targeted for removal, it remains. + *current_element + } + } + None => *current_element, // No change affecting this leaf path + } + } Self::Parent { left, right, .. } => { - let right_start = extra_elements_bits + // Find the split point for left/right based on the current bit in the path + let right_start = bits .iter() - .position(|b| b[path_depth]) - .unwrap_or(extra_elements_bits.len()); - let lefts = &extra_elements_bits[..right_start]; - let lefts_elements = &extra_elements[..right_start]; - let rights = &extra_elements_bits[right_start..]; - let rights_elements = &extra_elements[right_start..]; - - let left_hash = match lefts.is_empty() { - true => left.hash(), - false => left.hash_with_inner::( - cache, - lefts_elements, - lefts, - path_depth + 1, - ), - }; - let right_hash = match rights.is_empty() { - true => right.hash(), - false => right.hash_with_inner::( - cache, - rights_elements, - rights, - path_depth + 1, - ), - }; + .position(|b| b[path_depth]) // Find first path going right (bit == 1) + .unwrap_or(bits.len()); // If none go right, all go left + + // Slice the changes and bits for left and right subtrees + let left_bits = &bits[..right_start]; + let left_changes = &changes[..right_start]; + let right_bits = &bits[right_start..]; + let right_changes = &changes[right_start..]; + + // Recursively calculate hashes for left and right children + let left_hash = left.hash_with_inner::( + cache, + left_changes, + left_bits, + path_depth + 1, + ); + let right_hash = right.hash_with_inner::( + cache, + right_changes, + right_bits, + path_depth + 1, + ); + // Merge the resulting hashes cache.hash(left_hash, right_hash) } Self::Empty { depth: 1 } => { - // we need to check whether there should be an element here - assert!(extra_elements.len() <= 1, "too many elements"); - extra_elements - .first() - .copied() - .unwrap_or_else(|| empty_tree_hash(1)) + // Base case: An empty node at the leaf depth. + assert!( + changes.len() <= 1, + "Logic error: Multiple changes target the same empty leaf path: {:?}", + &changes, + ); + match changes.first() { + Some((Change::Insert, element)) => *element, // Insert creates a leaf + Some((Change::Remove, _)) | None => empty_tree_hash(1), // Removing from empty or no change -> stays empty + } } Self::Empty { depth } => { - let child = Self::Parent { - left: Box::new(Self::Empty { depth: *depth - 1 }), - right: Box::new(Self::Empty { depth: *depth - 1 }), - hash: empty_tree_hash(*depth), - hash_dirty: false, - }; + // An empty node at an intermediate depth. + // If no changes pass through this node, its hash remains the empty tree hash. + if changes.is_empty() { + return empty_tree_hash(*depth); + } - child.hash_with_inner::( + // Otherwise, we need to simulate its expansion and recurse. + // Find the split point for left/right changes. + let right_start = bits + .iter() + .position(|b| b[path_depth]) + .unwrap_or(bits.len()); + let left_bits = &bits[..right_start]; + let left_changes = &changes[..right_start]; + let right_bits = &bits[right_start..]; + let right_changes = &changes[right_start..]; + + // Simulate the two empty children it would have. + let temp_left_node = Node::Empty { depth: *depth - 1 }; + let temp_right_node = Node::Empty { depth: *depth - 1 }; + + // Recurse into the simulated children. + let left_hash = temp_left_node.hash_with_inner::( + cache, + left_changes, + left_bits, + path_depth + 1, + ); + let right_hash = temp_right_node.hash_with_inner::( cache, - extra_elements, - extra_elements_bits, - path_depth, - ) + right_changes, + right_bits, + path_depth + 1, + ); + + // Merge the results. + cache.hash(left_hash, right_hash) } } } @@ -124,12 +235,27 @@ impl Node { /// The elements and bits should be sorted by the bits before calling this function pub(crate) fn insert_without_hashing( &mut self, - elements: &[Element], + elements: &[(Change, Element)], bits: &[BitVec], path_depth: usize, ) -> Result { match self { - Self::Leaf(e) if elements.contains(e) => Ok(false), + Self::Leaf(e) if elements.iter().any(|(_, ee)| e == ee) => { + let Some((change, _)) = elements.iter().find(|(_, ee)| e == ee) else { + unreachable!() + }; + + match change { + Change::Insert => { + // It's already in tree + Ok(false) + } + Change::Remove => { + *self = Self::Empty { depth: 1 }; + Ok(true) + } + } + } Self::Leaf(e) if bits.iter().any({ let e_lsb = e.lsb(N - 1); @@ -138,10 +264,11 @@ impl Node { { Err(Collision { in_tree: *e, - inserted: *elements + inserted: elements .iter() - .find(|e| e.lsb(N - 1) == e.lsb(N - 1)) - .unwrap(), + .find(|(_, ee)| e.lsb(N - 1) == ee.lsb(N - 1)) + .unwrap() + .1, depth: N, struct_name: StructName::Tree, }) @@ -192,8 +319,13 @@ impl Node { } Self::Empty { depth: 1 } => { assert_eq!(elements.len(), 1); - *self = Self::Leaf(elements.first().copied().unwrap()); - Ok(true) + match elements.first().copied().unwrap() { + (Change::Insert, e) => { + *self = Self::Leaf(e); + Ok(true) + } + (Change::Remove, _) => Ok(false), + } } Self::Empty { depth } => { @@ -257,7 +389,7 @@ mod tests { #[proptest] fn root_hash_with_matches_insert(mut tree: Tree<16, i32>, batch: Batch<16, i32>) { - let hash_with = tree.root_hash_with(&batch.elements().collect::>()); + let hash_with = tree.root_hash_with(&batch.insert_elements().collect::>(), &[]); let result = tree.insert_batch(batch, |_| {}, |_| {}); prop_assume!(result.is_ok()); diff --git a/pkg/solid/Cargo.toml b/pkg/solid/Cargo.toml new file mode 100644 index 0000000..d45f0dc --- /dev/null +++ b/pkg/solid/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "solid" +version = "1.3.0" +edition = "2024" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bs58 = { workspace = true } +chrono = { workspace = true } +futures = { workspace = true } +hex = { workspace = true } +parking_lot = { workspace = true } +rand = { workspace = true } +sha2 = { workspace = true } +sha3 = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tokio-stream = { workspace = true } +uint = { workspace = true } +borsh = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +proptest = { workspace = true } +quickcheck = { workspace = true } +rand = { workspace = true } +test-strategy = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } + +[[example]] + +name = "basic" +path = "examples/basic.rs" + +[[example]] + +name = "multi" +path = "examples/multi.rs" diff --git a/pkg/solid/README.md b/pkg/solid/README.md new file mode 100644 index 0000000..4c9bd3c --- /dev/null +++ b/pkg/solid/README.md @@ -0,0 +1,181 @@ +# Solid Consensus Protocol + +Protocol for achieving high throughput BFT consensus for a given state machine. + +Features: + + ✅ Fast finality (finality after 2 blocks) + + ✅ High throughput (minimal communication, pipelining) + + ✅ Safety over liveness + + ✅ BYO Network/state machine + + + +## Background + +[Consensus]((https://www.youtube.com/watch?v=rN6ma561tak&list=PLeKd45zvjcDFUEv_ohr_HdUFe97RItdiB&index=18)) is a mechanism for converging to an agreement on some state in a distributed system. [BFT](https://www.youtube.com/watch?v=LoGx_ldRBU0&list=PLeKd45zvjcDFUEv_ohr_HdUFe97RItdiB&index=5) (Byzantine Fault Tolerance) consensus provides a provable mechanism of ensuring that network state is consistent so long as no more than 1/3 of nodes are faulty/malicious. + + +## Overview of Solid + +Solid prioritizes safety over liveness (similar to [Doomslug](https://near.org/blog/doomslug-comparison), [HotStuff](https://hackernoon.com/hotstuff-the-consensus-protocol-behind-safestake-and-facebooks-librabft) and [Tendermint](https://docs.tendermint.com/v0.34/introduction/what-is-tendermint.html#consensus-overview)). + + +Solid minimizes network communication. `accept` messages are sent only to the next designated leader (many to one). Once a leader accumulates `accept` messages from a majority of nodes (including itself), +it will then propose a new `proposal` to the network (one to many). + +If the network detects that no proposal has been received from the network within a given timeout period, then the node will then send an `accept` to the next designated leader, with a `skip` of 1. This process is repeated until a valid proposal is sent from a node. + +This is how a typical network using Solid might look like: + +![Consensus Protocol Overview](docs/consensus.png) + +Solid implements an async event stream interface where relevant events are omitted and it is the responsibility of the implementor to define the network and storage implementations. + +The number of nodes should always be an odd number to prevent a deadlock situation where no majority can be reached. This is the *liveness* property alluded to previously. + + + +### Terminology + + * Leader - The node which is in charge of submitting proposals. See [Leader Election](#leader-election) + + * Proposal - a request to add a block with a bunch of transactions to the network. + + * Accepts - message sent by all nodes to the leader indicating acceptance of the previous proposal. Also sent in the case where a leader is skipped since + it did not produce a proposal in time. + + * Skips - the number of changes of leaders since the last confirmed proposal. A leader is skipped if it does not produce a proposal before timeout. + + * Height - the number of committed blocks on the network. A proposal has an associated height which indicates how updated (or outdated) the node state is. + + * Validators - all the nodes of the system that vote for a proposal to be accepted (so all the available, non-malicious nodes in the system). + + +### Solid State Machine and Transitions + +```mermaid +%% Note: This content is sourced from docs/solid.mmd. See the instructions in that file. Any modifications to the code +%% must be done in that file, and the changes copied over here. +stateDiagram-v2 + state CheckStartState <> + state CheckProposalHeight <> + state CheckAcceptedByQuorum <> + state CheckHasPendingCommits <> + + [*] --> CheckStartState: Starting state + CheckStartState --> Genesis: New node startup + CheckStartState --> WithLastConfirmedProposal: Has last confirmed proposal + Genesis --> NewRound + WithLastConfirmedProposal --> NewRound + + NewRound --> Propose + + state CheckDuplicateProposal <> + Propose --> CheckDuplicateProposal + CheckDuplicateProposal --> DuplicateProposal: proposal is duplicate + DuplicateProposal --> ResetTimeouts + ResetTimeouts --> SkipAndChooseNewLeader + SkipAndChooseNewLeader --> NewRound + CheckDuplicateProposal --> CheckProposalHeight: proposal is not duplicate + CheckProposalHeight --> Accept: height < proposal height + + + Accept --> CheckAcceptedByQuorum + CheckAcceptedByQuorum --> ResetTimeouts: proposal not accepted by majority of validators + CheckAcceptedByQuorum --> Commit: proposal accepted by majority of validators + + Commit --> CheckHasPendingCommits + CheckHasPendingCommits --> OutOfSync: if has pending commits + OutOfSync --> SyncWithNetwork + SyncWithNetwork --> NewRound + CheckHasPendingCommits --> IncrementHeight: if no pending commits + IncrementHeight --> NewRound +``` + +### Solid States (and Conditions) + +Note that the actual states that a node can be in are: + + * Propose + * Accept, and + * Commit + +In addition, we consider a number of other pseudo-states (basically, events): + + * Out of Sync + * Out of Date + * Duplicate Proposal + +Also note that these states and conditions are applicable to each node of the network at different stages of operation meaning that the states are not specific to any particular node unless explicitly +noted as such, and any particular node can be in any of the states ate different points in time. + +The Solid states in the state transition diagram shown above are explained in the following sections. + +#### Propose + +Only the leader node (i.e., the single node amongst all the nodes which has been chosen for this round) can put forth a proposal. + +A proposal has the following general structure: + + * last_proposal_hash - the hash of the last proposal. + * skips - the number of changes of leader that have occurred since the last leadership change. + * height - the height of the proposal (meaning the number of blocks that have already been committed in the network). + * leader_id - the id of the proposer/leader (See also [Leader Election](#leader-election)). + * txns - the changes included in the proposal, and + * peers - the list of peers on the network + +The `txns` field is generic - any higher-level protocol (i.e., any solution built on top of Solid) can specify its own transaction format and thereby propose arbitrarily complex payloads. + +If the leader node does not have any proposals, or if the leader fails to put forth the proposal before the timeout period, the round is skipped and a new round is started with *possibly* a new leader. See [Leader Election])#Leader election). + +#### Accept + +Accepts are sent to the next designated leader in the following scenarios: + + 1. When a valid proposal is received from the previous leader (building on the last confirmed proposal) + + 2. After a given timeout (in order to move on from nodes that are not online), these are referred to as `skips` + + 3. If there are no pending proposals (usually on start up) + +Accepts are either for a proposal: + - confirmed height + 1 (when a valid proposal is received) + - confirmed height (when no valid pending proposals exist) + +#### Commit + +In the commit state, the proposal gooes through a final round of validation - if the node has pending commits in its local store/register/cache, then the node is considered to be out of sync, and as such transitions to the [Out of Sync](#out-of-sync) state. If not, +the commit is carried through and the `height` is incremented by 1 in preparation for the next round. + +#### Out of Sync + +This condition implies that the node's state is behind that of the network. As such, Solid will notify the higher-level protocol, which is then responsible for handling this conditions. For instance, `Polybase` will handle this condition +by attempting to update the state of this node by accepting snapshots from other nodes in the network. + +#### Out of Date + +This condition implies that the proposal is out-of-date or invalid, and as such, Solid again delegates the handling of the proposal to the higher-level protocol. For instance, `Polybase` will log and discard the proposal. + +#### Duplicate Proposal + +This condition implies that the proposal has already been seen by the network, and as such, Solid will delegate the appropriate follow-up to the higher-level protocol. For instance, `Polybase` will log and discard the duplicate proposal. + +### Leader Election + +Leader election is done for every proposal/accept round (accounting for timeouts) using the following simple formula: + +``` + next_leader_id = skips % number_of_peers + +``` + +So this is **not** a Round-Robin procedure (as in some consensus protocols), but rather depends on the number of current peers (which is fixed at start-up for now), and the number of skips (i.e, since the last confirmed proposal) thus far. + + +## Todo + + - Add/remove peers from the protocol validators diff --git a/pkg/solid/docs/consensus.png b/pkg/solid/docs/consensus.png new file mode 100644 index 0000000..b3d37d4 Binary files /dev/null and b/pkg/solid/docs/consensus.png differ diff --git a/pkg/solid/docs/solid.mmd b/pkg/solid/docs/solid.mmd new file mode 100644 index 0000000..3b02bdf --- /dev/null +++ b/pkg/solid/docs/solid.mmd @@ -0,0 +1,46 @@ +%% +%% This is the State Transition Diagram for the Solid Consensus Protocol generated using Mermaid (https://mermaid.js.org/). +%% +%% How to run and generate images locally: +%% +%% 1. Install `mermaid-cli` (https://github.com/mermaid-js/mermaid-cli) +%% 2. Run `$ mmdc -i sold.mmd -o .{svg|png}` +%% +%% For instance: +%% $ mmdc -i sold.mmd -o solid.png +%% +stateDiagram-v2 + state CheckStartState <> + state CheckProposalHeight <> + state CheckAcceptedByQuorum <> + state CheckHasPendingCommits <> + + + [*] --> CheckStartState: Starting state + CheckStartState --> Genesis: New node startup + CheckStartState --> WithLastConfirmedProposal: Has last confirmed proposal + Genesis --> NewRound + WithLastConfirmedProposal --> NewRound + + NewRound --> Propose + + state CheckDuplicateProposal <> + Propose --> CheckDuplicateProposal + CheckDuplicateProposal --> DuplicateProposal: proposal is duplicate + DuplicateProposal --> ResetTimeouts + ResetTimeouts --> SkipAndChooseNewLeader + SkipAndChooseNewLeader --> NewRound + CheckDuplicateProposal --> CheckProposalHeight: proposal is not duplicate + CheckProposalHeight --> Accept: height < proposal height + + + Accept --> CheckAcceptedByQuorum + CheckAcceptedByQuorum --> ResetTimeouts: proposal not accepted by majority of validators + CheckAcceptedByQuorum --> Commit: proposal accepted by majority of validators + + Commit --> CheckHasPendingCommits + CheckHasPendingCommits --> OutOfSync: if has pending commits + OutOfSync --> SyncWithNetwork + SyncWithNetwork --> NewRound + CheckHasPendingCommits --> IncrementHeight: if no pending commits + IncrementHeight --> NewRound \ No newline at end of file diff --git a/pkg/solid/examples/basic.rs b/pkg/solid/examples/basic.rs new file mode 100644 index 0000000..85ea391 --- /dev/null +++ b/pkg/solid/examples/basic.rs @@ -0,0 +1,98 @@ +use futures::StreamExt; +use solid::App; +use solid::Solid; +use solid::config::SolidConfig; +use solid::event::SolidEvent; +use solid::proposal::{Manifest, ManifestContent}; +use solid::test::app::{InsecurePeerSigner, TestApp, UncheckedPeerId as PeerId}; +use solid::{Peer, PeerSigner}; +use std::time::Duration; +use std::vec; +use tracing::info; +use tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt}; + +#[tokio::main] +async fn main() { + let local_peer_id = InsecurePeerSigner::new(PeerId::random()); + + // Logging + let stdout_tracer = tracing_subscriber::fmt::layer().compact(); + let filter = EnvFilter::try_new("warn") + .unwrap() + .add_directive("basic=info".parse().unwrap()); + let subscriber = tracing_subscriber::registry() + .with(stdout_tracer) + .with(filter); + + tracing::subscriber::set_global_default(subscriber).unwrap(); + + // Create a new solid instance + let mut solid: Solid = Solid::genesis( + local_peer_id.clone(), + vec![local_peer_id.peer()], + TestApp, + SolidConfig::default(), + ); + + // Start the service + solid.run(); + + // Start + loop { + tokio::select! { + Some(event) = solid.next() => { + match event { + // Node should send accept for an active proposal + // to another peer + SolidEvent::Accept { accept } => { + info!(height = &accept.proposal.height, skips = &accept.skips, to = &accept.leader_id.prefix(), hash = accept.proposal.hash.to_string(), "Send accept"); + } + + // Node should create and send a new proposal + SolidEvent::Propose { + last_proposal_hash, + height, + skips, + accepts, + } => { + // Simulate delay + tokio::time::sleep(Duration::from_secs(1)).await; + + // Create the proposal manifest + let manifest = Manifest::new(ManifestContent { + last_proposal_hash: last_proposal_hash.clone(), + skips, + height, + leader_id: local_peer_id.peer().clone(), + state: 0.into(), + validators: vec![local_peer_id.peer().clone()], + accepts, + }, vec![]); + let proposal_hash = TestApp::hash(&manifest); + + info!(hash = proposal_hash.to_string(), height = height, skips = skips, "Propose"); + + // Add proposal to own register, this will trigger an accept + solid.receive_proposal(manifest.clone()).unwrap(); + } + + // Commit a confirmed proposal changes + SolidEvent::Commit { manifest, .. } => { + info!(hash = TestApp::hash(&manifest).to_string(), height = manifest.height, skips = manifest.skips, "Commit"); + } + + SolidEvent::OutOfSync { + height, + max_seen_height, + } => { + info!(local_height = height, max_seen_height = max_seen_height, "Out of sync"); + } + + SolidEvent::DuplicateProposal { proposal_hash } => { + info!(hash = proposal_hash.to_string(), "Duplicate proposal"); + } + } + } + } + } +} diff --git a/pkg/solid/examples/multi.rs b/pkg/solid/examples/multi.rs new file mode 100644 index 0000000..e053b50 --- /dev/null +++ b/pkg/solid/examples/multi.rs @@ -0,0 +1,462 @@ +// lint-long-file-override allow-max-lines=500 +use borsh::{BorshDeserialize, BorshSerialize}; +use futures::StreamExt; +use futures::channel::mpsc::{self, Sender, TrySendError}; +use futures::stream::Stream; +use rand::Rng; +use solid::App; +use solid::Solid; +use solid::config::SolidConfig; +use solid::event::SolidEvent; +use solid::proposal::ManifestContent; +use solid::proposal::{Manifest, ProposalAccept}; +use solid::test::app::{InsecurePeerSigner, TestApp, TestAppTxnState, UncheckedPeerId as PeerId}; +use solid::{Peer, PeerSigner}; +use std::collections::HashMap; +// use std::mem; +use std::pin::Pin; +use std::sync::atomic::AtomicBool; +use std::sync::{Arc, Mutex}; +use std::task::{Context, Poll}; +use std::time::Duration; +use tokio::time::sleep; + +use tracing::{Instrument, error, info, info_span}; +use tracing_subscriber::{filter::EnvFilter, layer::SubscriberExt}; + +#[derive(Debug, BorshSerialize, BorshDeserialize)] +struct Store { + data: HashMap, + proposal: Option>, + pending: Vec, +} + +impl Store { + // fn propose(&mut self) -> Vec { + // mem::take(&mut self.pending) + // } + + // fn add_pending_txn(&mut self, txn: solid::txn::Txn) { + // self.pending.push(txn); + // } + + fn commit(&mut self, manifest: Manifest) -> Vec { + self.proposal = Some(manifest); + vec![] + } + + // fn restore(&mut self, snapshot: Snapshot) { + // let Snapshot { data, proposal } = snapshot; + // let data: HashMap = deserialize(&data).unwrap(); + // self.data = data; + // self.proposal = Some(proposal) + // } + + #[allow(clippy::disallowed_methods)] // it's just an example + fn snapshot(&self) -> std::result::Result> { + Ok(Snapshot { + data: borsh::to_vec(&self.data)?, + proposal: self.proposal.as_ref().unwrap().clone(), + }) + } +} + +pub type SenderMap = HashMap)>>; + +#[derive(Clone)] +pub struct MyNetworkConfig { + min_latency: u64, + max_latency: u64, + drop_probability: f64, + partition_duration: u64, + partition_frequency: u64, +} + +pub struct MyNetwork { + local_peer_id: PeerId, + event_stream: Option)> + Unpin + Sync + Send>>, + senders: Arc>, + partition: Arc, + config: MyNetworkConfig, +} + +impl MyNetwork { + pub fn new( + local_peer_id: PeerId, + senders: Arc>, + config: MyNetworkConfig, + ) -> Self { + // A small buffer, so we can simulate network partition + let (sender, receiver) = mpsc::channel(20); + + // Insert self into senders! + { + let mut senders = senders.lock().unwrap(); + senders.insert(local_peer_id.clone(), sender); + } + + let partition = Arc::new(AtomicBool::new(false)); + + let drop_probability = config.drop_probability; + let dropping_stream = DroppingStream::new(receiver, drop_probability, partition.clone()); + + let event_stream = Some(Box::new(dropping_stream) + as Box)> + Unpin + Send + Sync>); + + let prefix = local_peer_id.prefix(); + let shared_partition = partition.clone(); + tokio::spawn(async move { + loop { + if rand::thread_rng().gen_range(0..=config.partition_frequency) == 1 { + println!( + "----- START: simulating {}s network partition for {} -----", + config.partition_duration / 1000, + prefix, + ); + { + shared_partition.swap(true, std::sync::atomic::Ordering::Relaxed); + } + sleep(std::time::Duration::from_millis(config.partition_duration)).await; + println!("----- END: simulating network partition for {prefix} -----",); + { + shared_partition.swap(false, std::sync::atomic::Ordering::Relaxed); + } + } + + // Only check for partition every 1 seconds + sleep(std::time::Duration::from_millis(1000)).await; + } + }); + + Self { + local_peer_id, + event_stream, + senders, + config, + partition, + } + } + + async fn send(&self, peer_id: &PeerId, event: &NetworkEvent) { + #[allow(clippy::disallowed_methods)] // it's just an example + let data = borsh::to_vec(event).unwrap(); + + let senders = self.senders.clone(); + let local_peer_id = self.local_peer_id.clone(); + let MyNetworkConfig { + min_latency, + max_latency, + .. + } = self.config; + let sleep_duration = + rand::thread_rng().gen_range(0..=max_latency - min_latency) + min_latency; + + // If we're simulating a network partition ignore requests + { + if self.partition.load(std::sync::atomic::Ordering::Relaxed) { + return; + } + } + + // Randomly sleep for a minute (simulate network partition) + sleep(std::time::Duration::from_millis(sleep_duration)).await; + + let mut sender_opt = None; + { + let senders = senders.lock().unwrap(); + if let Some(sender) = senders.get(peer_id) { + sender_opt = Some(sender.clone()); + } + } + if let Some(mut sender) = sender_opt { + match sender.try_send((local_peer_id, data)) { + Ok(_) => { + // println!("Sending from {}", self.local_peer_id.prefix()); + } + Err(TrySendError { .. }) => { + info!( + "Failed to send message to {} from {}", + peer_id.prefix(), + self.local_peer_id.prefix(), + ) + } + } + } + } + + async fn send_all(&self, event: &NetworkEvent) { + let senders = self.senders.lock().unwrap().clone(); + let local_peer_id = self.local_peer_id.clone(); + let tasks: Vec<_> = senders + .keys() + .filter(|peer_id| **peer_id != local_peer_id) // Exclude local_peer_id from broadcasting + .map(|peer_id| self.send(peer_id, event)) + .collect(); + futures::future::join_all(tasks).await; + } +} + +impl Stream for MyNetwork { + type Item = (PeerId, Vec); + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let stream = self.event_stream.as_mut().unwrap(); + Pin::new(stream).poll_next(cx) + } +} + +#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)] +enum NetworkEvent { + OutOfSync { + peer_id: PeerId, + height: u64, + }, + Accept { + accept: ProposalAccept, + }, + Proposal { + manifest: Manifest, + }, + Snapshot { + snapshot: Snapshot, + }, +} + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct Snapshot { + pub proposal: Manifest, + pub data: Vec, +} + +#[tokio::main] +async fn main() { + let num_of_nodes = 3; + let senders = Arc::new(Mutex::new(HashMap::new())); + let peers: Vec = (0..num_of_nodes).map(|_| PeerId::random()).collect(); + + // Logging + let stdout_tracer = tracing_subscriber::fmt::layer().compact(); + + let filter = EnvFilter::try_new("warn") + .unwrap() + .add_directive("multi=info".parse().unwrap()); + + let subscriber = tracing_subscriber::registry() + .with(stdout_tracer) + .with(filter); + + tracing::subscriber::set_global_default(subscriber).unwrap(); + + let mut handles = Vec::new(); + + for i in 0..num_of_nodes { + let local_peer_id = InsecurePeerSigner::new(peers[i].clone()); + let peers = peers.clone(); + + let mut store = Store { + data: HashMap::new(), + proposal: None, + pending: vec![], + }; + + info!("Starting node {}", local_peer_id.peer().prefix()); + + let config = MyNetworkConfig { + min_latency: 200, + max_latency: 600, + drop_probability: 0.1, + partition_duration: 80_000, + partition_frequency: 600, + }; + + let mut network = MyNetwork::new(local_peer_id.peer().clone(), senders.clone(), config); + + let mut solid = Solid::genesis( + local_peer_id.clone(), + peers.clone(), + TestApp, + SolidConfig::default(), + ); + + let span = info_span!("task_span", local_peer_id = local_peer_id.peer().prefix()); + handles.push(tokio::spawn(async move { + solid.run(); + loop { + tokio::select! { + Some((_, data)) = network.next() => { + let event = NetworkEvent::deserialize(&mut data.as_slice()).unwrap(); + match event { + NetworkEvent::OutOfSync { peer_id, height } => { + info!(peer_id = peer_id.prefix(), height = height, "Peer is out of sync"); + if height + 1024 < solid.height() { + let snapshot = match store.snapshot() { + Ok(snapshot) => snapshot, + Err(err) => { + error!(r#for = peer_id.prefix(), ?err, "Error creating snapshot"); + return; + } + }; + network.send(&peer_id, &NetworkEvent::Snapshot { snapshot }).await; + } else { + for proposal in solid.confirmed_proposals_from(height) { + network.send( + &peer_id, + &NetworkEvent::Proposal { + manifest: proposal.clone(), + }, + ) + .await; + } + } + } + + NetworkEvent::Snapshot { .. } => { + info!("Received snapshot"); + // solid.receive_snapshot(snapshot); + } + + NetworkEvent::Accept { accept } => { + info!(height = &accept.proposal.height, skips = &accept.skips, from = &accept.leader_id.prefix(), hash = accept.proposal.hash.to_string(), "Received accept"); + match solid.receive_accept(&accept) { + Ok(_) => {} + Err(err) => { + error!(?err, "Error receiving accept"); + } + } + } + + NetworkEvent::Proposal { manifest } => { + info!(height = &manifest.height, skips = &manifest.skips, from = &manifest.leader_id.prefix(), hash = TestApp::hash(&manifest).to_string(), "Received proposal"); + match solid.receive_proposal(manifest) { + Ok(_) => {} + Err(err) => { + error!(?err, "Error receiving proposal"); + } + } + } + } + }, + + Some(event) = solid.next() => { + match event { + // Node should send accept for an active proposal + // to another peer + SolidEvent::Accept { accept } => { + info!(height = &accept.proposal.height, skips = &accept.skips, to = &accept.leader_id.prefix(), hash = accept.proposal.hash.to_string(), "Send accept"); + let leader = &accept.leader_id.clone(); + + network.send( + leader, + &NetworkEvent::Accept { accept }, + ) + .await; + } + + // Node should create and send a new proposal + SolidEvent::Propose { + last_proposal_hash, + height, + skips, + accepts, + } => { + // Simulate delay + tokio::time::sleep(Duration::from_secs(1)).await; + + // Create the proposl manfiest + let manifest = Manifest::new(ManifestContent:: { + last_proposal_hash, + skips, + height, + leader_id: local_peer_id.peer().clone(), + state: 0.into(), + validators: peers.clone(), + accepts, + }, vec![]); + let proposal_hash = TestApp::hash(&manifest); + + info!(hash = proposal_hash.to_string(), height = height, skips = skips, "Propose"); + + // Add proposal to own register, this will trigger an accept + match solid.receive_proposal(manifest.clone()) { + Ok(_) => {} + Err(err) => { + error!(?err, "Error receiving proposal"); + } + } + + // // Send proposal to all other nodes + network.send_all( + &NetworkEvent::Proposal { manifest: manifest.clone() } + ) + .await; + } + + // Commit a confirmed proposal changes + SolidEvent::Commit { manifest, .. } => { + info!(hash = TestApp::hash(&manifest).to_string(), height = manifest.height, skips = manifest.skips, "Commit"); + store.commit(manifest); + } + + SolidEvent::OutOfSync { + height, + max_seen_height, + } => { + info!(local_height = height, max_seen_height = max_seen_height, "Out of sync"); + network.send_all(&NetworkEvent::OutOfSync { peer_id: local_peer_id.peer().clone(), height }) + .await + } + + SolidEvent::DuplicateProposal { proposal_hash } => { + info!(hash = proposal_hash.to_string(), "Duplicate proposal"); + } + } + } + } + } + }.instrument(span))); + } + + for handle in handles { + handle.await.unwrap(); + } +} + +/// Util for simulating dropping of messages +pub struct DroppingStream { + inner: S, + drop_probability: f64, + partition: Arc, +} + +impl DroppingStream { + pub fn new(inner: S, drop_probability: f64, partition: Arc) -> Self { + Self { + inner, + drop_probability, + partition, + } + } +} + +impl Stream for DroppingStream { + type Item = S::Item; + + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + loop { + let res = self.inner.poll_next_unpin(cx); + match res { + Poll::Pending => return Poll::Pending, + Poll::Ready(Some(item)) => { + if rand::thread_rng().gen_range(0.0..=1.0) < self.drop_probability + || self.partition.load(std::sync::atomic::Ordering::Relaxed) + { + info!("Dropping message"); + continue; + } + return Poll::Ready(Some(item)); + } + Poll::Ready(None) => return Poll::Ready(None), + } + } + } +} diff --git a/pkg/solid/src/config.rs b/pkg/solid/src/config.rs new file mode 100644 index 0000000..8354c89 --- /dev/null +++ b/pkg/solid/src/config.rs @@ -0,0 +1,127 @@ +use std::time::Duration; + +#[derive(Debug, Clone)] +pub struct SolidConfig { + /// Minimum delay for each proposal + pub min_proposal_duration: Duration, + + /// Maximum number of confirmed proposals to keep in history. This helps prevent us + /// running out of memory if we receive a lot of proposals. + pub max_proposal_history: u64, + + /// Amount of time to wait before we skip a leader + pub skip_timeout: Duration, + + /// Amount of time to wait before we send another out of sync message + pub out_of_sync_timeout: Duration, + + /// Threshold for accepting a proposal as confirmed + pub accept_threshold: AcceptThreshold, + + /// Timeout to wait for missing proposal (i.e. we've received an accept for + /// a proposal we don't have. In normal cases this could just be a race condition, + /// and we will receive the proposal shortly after. However, if we don't receive + /// the proposal after this timeout, we will send an out of sync event. + pub missing_proposal_timeout: Duration, +} + +impl Default for SolidConfig { + fn default() -> Self { + SolidConfig { + min_proposal_duration: Duration::from_secs(1), + max_proposal_history: 1024, + skip_timeout: Duration::from_secs(5), + out_of_sync_timeout: Duration::from_secs(60), + accept_threshold: AcceptThreshold::MoreThanTwoThirds, + missing_proposal_timeout: Duration::from_secs(5), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum AcceptThreshold { + /// Accepts are required from more than two thirds of peers + MoreThanTwoThirds, + + /// Accepts are required from a majority of peers + Majority, +} + +impl AcceptThreshold { + /// Calculate the threshold based on the number of peers + pub fn threshold(&self, peers: usize) -> usize { + match self { + AcceptThreshold::MoreThanTwoThirds => (peers * 2 / 3) + 1, + AcceptThreshold::Majority => (peers / 2) + 1, + } + } + + /// Returns true only when threshold is exactly breached, and not at other times + /// it is exceeded. + pub fn is_exact_breach(&self, accepts: usize, peers: usize) -> bool { + self.threshold(peers) == accepts + } + + /// Inverse is the opposite of the threshold limit, so if the threshold is >2/3, + /// then the inverse is >=1/3 + pub fn inverse_exceeded(&self, accepts: usize, peers: usize) -> bool { + accepts > peers - self.threshold(peers) + } + + pub fn is_exceeded(&self, accepts: usize, peers: usize) -> bool { + accepts >= self.threshold(peers) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_exact_breach_two_thirds() { + // 3 peers + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(1, 3)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(2, 3)); + assert!(AcceptThreshold::MoreThanTwoThirds.is_exact_breach(3, 3)); + + // 4 peers + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(1, 4)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(2, 4)); + assert!(AcceptThreshold::MoreThanTwoThirds.is_exact_breach(3, 4)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(4, 4)); + + // 5 peers + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(1, 5)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(2, 5)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(3, 5)); + assert!(AcceptThreshold::MoreThanTwoThirds.is_exact_breach(4, 5)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exact_breach(5, 5)); + } + + #[test] + fn test_inverse_exceeded() { + // 3 peers + assert!(!AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(0, 3)); + assert!(AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(1, 3)); + assert!(AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(2, 3)); + assert!(AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(3, 3)); + + // 4 peers + assert!(!AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(0, 4)); + assert!(!AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(1, 4)); + assert!(AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(2, 4)); + assert!(AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(3, 4)); + assert!(AcceptThreshold::MoreThanTwoThirds.inverse_exceeded(4, 4)); + } + + #[test] + fn test_is_exceeded() { + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exceeded(0, 1)); + + // 3 peers + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exceeded(0, 3)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exceeded(1, 3)); + assert!(!AcceptThreshold::MoreThanTwoThirds.is_exceeded(2, 3)); + assert!(AcceptThreshold::MoreThanTwoThirds.is_exceeded(3, 3)); + } +} diff --git a/pkg/solid/src/errors.rs b/pkg/solid/src/errors.rs new file mode 100644 index 0000000..7489133 --- /dev/null +++ b/pkg/solid/src/errors.rs @@ -0,0 +1,49 @@ +use std::fmt::Debug; + +use crate::proposal; + +pub type Result = std::result::Result; + +// TODO: we should pass info with each of these errors + +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +pub enum Error { + #[error("invalid signature for accept")] + InvalidAcceptSignature, + + #[error("invalid accept for proposal")] + InvalidAcceptProposalHash, + + #[error("invalid validator accept in proposal")] + InvalidAcceptValidator, + + #[error("invalid proposal leader")] + InvalidProposalLeader, + + #[error("invalid accept leader, expected: {expected}, got: {got}")] + InvalidAcceptLeader { expected: String, got: String }, + + #[error("insufficient accepts for proposal")] + InsufficientAcceptsForProposal, + + #[error("invalid signature for proposal")] + InvalidProposalSignature, + + #[error("proposal already exists")] + ProposalAlreadyExists(proposal::ProposalHash), + + #[error("proposal height too low")] + ProposalHeightTooLow, + + #[error("proposal peer threshold not met")] + ProposalPeerThresholdNotMet, + + #[error("confirmed proposal is not a decendent")] + ProposalInvalidDecendent, + + #[error("proposal invalid structure")] + ProposalInvalidAppStructure, + + #[error("proposal invalid content")] + ProposalInvalidAppContent, +} diff --git a/pkg/solid/src/lib.rs b/pkg/solid/src/lib.rs new file mode 100644 index 0000000..bbd1d28 --- /dev/null +++ b/pkg/solid/src/lib.rs @@ -0,0 +1,15 @@ +#![warn(clippy::unwrap_used, clippy::expect_used)] +#![deny(clippy::disallowed_methods)] + +pub mod config; +mod errors; +pub mod proposal; +mod solid; +pub mod test; +mod traits; +mod util; + +pub use self::errors::{Error, Result}; +pub use self::solid::*; +pub use self::traits::*; +pub use self::util::u256::U256; diff --git a/pkg/solid/src/proposal/accept.rs b/pkg/solid/src/proposal/accept.rs new file mode 100644 index 0000000..fc3f3ac --- /dev/null +++ b/pkg/solid/src/proposal/accept.rs @@ -0,0 +1,45 @@ +use super::ProposalHeader; +use crate::ProposalAcceptSigData; +use crate::errors::{Error, Result}; +use crate::traits::Peer; +use borsh::{BorshDeserialize, BorshSerialize}; + +/// ProposalAccept is sent by all peers to the next leader to indicate +/// they accept a previous proposal. ProposalAccept is also used in the scenario +/// where a leader is skipped because they did not produce a proposal in time. +#[derive(Debug, Clone, Hash, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct ProposalAccept { + /// The leader being sent the accept, if the leader collects enough + /// accepts they can propose + pub leader_id: P, + + /// Header data for the proposal being accepted, allowing to more easily + /// ignore out of date accepts + pub proposal: ProposalHeader, + + /// If skips > 0, we have skipped over a previous leader because they + /// did not produce a proposal within the allocated period. This is the + /// number of skips that have occurred since the last confirmed proposal. + pub skips: u64, + + /// The peer the accept is from + pub from: P, + + /// Signature of the peer + pub signature: Vec, +} + +impl ProposalAccept

) -> Self { + Manifest { + content: ManifestContent::genesis(validators), + signature: vec![], + } + } + + pub fn verify>(&self, signer: &P) -> bool { + signer.verify(&self.signature, *A::hash(&self.content).inner()) + } +} + +impl Deref for Manifest { + type Target = ManifestContent; + + fn deref(&self) -> &Self::Target { + &self.content + } +} + +impl DerefMut for Manifest { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.content + } +} + +#[derive(Default, Debug, Clone, Hash, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct ManifestContent { + /// Hash of the last proposal, so we can confirm the last + /// proposal when we receive this message + pub last_proposal_hash: ProposalHash, + + /// Number of skips of leader that have occured since the last + /// leadership order change. This skips should match the skips + /// sent to this node in the ProposalAccept messages. + pub skips: u64, + + /// Height of the proposal, for easy checking whether we + /// are up to date with the network + pub height: u64, + + /// PeerId of the proposer/leader + pub leader_id: P, + + /// Changes included in the proposal + pub state: S, + + /// List of validators on the network + pub validators: Vec

, + + /// List of collected accepts for last proposal hash + pub accepts: Vec>, +} + +impl ManifestContent { + fn genesis(validators: Vec

) -> Self { + let leader_id = get_leader_for_skip(0, &validators); + ManifestContent { + last_proposal_hash: ProposalHash::genesis(), + skips: 0, + height: 0, + leader_id, + state: S::genesis(), + validators, + accepts: vec![], + } + } + + pub fn get_leader_for_skip(&self, skip: u64) -> P { + get_leader_for_skip(skip, &self.ordered_validators()) + } + + /// Get a list of ordered validators, this is a little expensive so it + /// can be useful to cache it + pub fn ordered_validators(&self) -> Vec

{ + let mut validators = self.validators.to_vec(); + validators.sort_by_key(|a| a.distance(&ordering_hash(self.height, self.skips))); + validators + } + + pub fn sign>(&self, signer: &A::PS) -> Vec { + signer.sign(*A::hash(self).inner()) + } +} + +fn get_leader_for_skip(skip: u64, ordered_validators: &[P]) -> P { + // We can use usize cast here, because skips reset for each proposal. Given min 1s per proposal skip, + // even with 2^32 arch it would take 136 years to overflow + let pos = (skip as usize) % ordered_validators.len(); + let peer = &ordered_validators[pos]; + peer.clone() +} + +/// Used to order peers in a safe way, its not possible for nodes to manipulate +/// the height/skips as these are what determine the previous leader +fn ordering_hash(height: u64, skips: u64) -> u256::U256 { + let mut bytes = Vec::new(); + bytes.extend_from_slice(&height.to_be_bytes()); + bytes.extend_from_slice(&skips.to_be_bytes()); + let hash = Sha256::digest(bytes); + u256::U256::from_little_endian(hash.as_slice()) +} diff --git a/pkg/solid/src/proposal/mod.rs b/pkg/solid/src/proposal/mod.rs new file mode 100644 index 0000000..56c0c67 --- /dev/null +++ b/pkg/solid/src/proposal/mod.rs @@ -0,0 +1,437 @@ +// lint-long-file-override allow-max-lines=500 +pub mod accept; +pub mod cache; +pub mod hash; +pub mod header; +pub mod manifest; +// #[cfg(test)] +// mod tests; + +pub use self::accept::*; +pub use self::hash::*; +pub use self::header::*; +pub use self::manifest::*; + +use crate::Error; +use crate::errors::Result; +use crate::{config::AcceptThreshold, traits::App}; +use std::collections::BTreeMap; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Proposal { + /// Accepts/votes for this proposal, only received by the leader node + incoming_accepts: BTreeMap>>, + + /// Hash of the proposal state + hash: ProposalHash, + + /// State of the proposal that is sent across the network + pub(crate) manifest: Manifest, + + /// Ordered Validators (in order based on height + skip) + ordered_validators: Vec, + + /// Has an initial accept been sent for this proposal, we keep track of this + /// to know later if we need to skip. + pub(crate) initial_accept_sent: bool, + + /// Skips sent for this proposal, skips are sent to the next leader + /// who should produce a proposal at the next height (this proposals height + 1). + /// E.g. if this proposal is height 54.0, and skips_sent is 2, then the last accept + /// sent is to 55.2 (for 54.0) + pub(crate) skips_sent: u64, + + pub(crate) is_validated: bool, +} + +impl Proposal { + pub fn new(manifest: Manifest) -> Self { + let hash = A::hash(&manifest); + let ordered_validators = manifest.ordered_validators(); + + Self { + incoming_accepts: BTreeMap::new(), + hash, + manifest, + ordered_validators, + initial_accept_sent: false, + skips_sent: 0, + is_validated: false, + } + } + + pub fn manifest(&self) -> &Manifest { + &self.manifest + } + + /// Generates a genesis proposal, which uses default values except for peers + pub fn genesis(existing_peers: Vec) -> Self { + Self::new(Manifest::genesis(existing_peers)) + } + + pub fn hash(&self) -> &ProposalHash { + &self.hash + } + + pub fn last_hash(&self) -> &ProposalHash { + &self.manifest.last_proposal_hash + } + + /// Height of this proposal + pub fn height(&self) -> u64 { + self.manifest.height + } + + /// Number of skips of leader that have occured since the last leadership order change. + /// Skips should match the skips sent to this node in the ProposalAccept messages. + pub fn skips(&self) -> u64 { + self.manifest.skips + } + + /// Adds an accept to a proposal, and returns whether a proposal should be generated + pub fn add_accept(&mut self, accept: ProposalAccept, threshold: AcceptThreshold) -> bool { + // Ignore accepts that are not valid + match self.validate_accept(&accept) { + Ok(_) => {} + Err(_) => { + return false; + } + } + + let skips: u64 = accept.skips; + let added = self + .incoming_accepts + .entry(skips) + .or_default() + .insert(accept.from.clone(), accept); + added.is_none() && self.accept_threshold_breached(skips, threshold) + } + + pub fn accepts_for_skip(&self, skips: &u64) -> Option>> { + self.incoming_accepts + .get(skips) + .map(|p| p.values().cloned().collect::>()) + } + + /// Checks that we have just enough accepts for meeting the majority + /// threshold, allowing us to confirm the proposal when majority threshold met, + /// but only when the threshold is first breached + pub fn accept_threshold_breached(&self, skips: u64, threshold: AcceptThreshold) -> bool { + let accepts_len = self + .incoming_accepts + .get(&skips) + .map(|p| p.len()) + .unwrap_or(0); + + threshold.is_exact_breach(accepts_len, self.ordered_validators.len()) + } + + /// Finds the highest skip, where the inverse threshold is met. + pub fn highest_skip_with_inverse(&self, threshold: AcceptThreshold) -> Option { + for (skip, accepts) in self.incoming_accepts.iter().rev() { + let accepts_len = accepts.len(); + let peers_len = std::cmp::max(self.ordered_validators.len(), 1); + + if threshold.inverse_exceeded(accepts_len, peers_len) { + return Some(*skip); + } + } + + None + } + + /// Get next accept skip + pub fn next_accept_skip(&self, threshold: AcceptThreshold, skip: bool) -> u64 { + if !self.initial_accept_sent && self.skips_sent == 0 { + return 0; + } + + let skips_sent_with_skip = if skip { + self.skips_sent + 1 + } else { + self.skips_sent + }; + + if let Some(highest_with_inverse) = self.highest_skip_with_inverse(threshold) + && highest_with_inverse > skips_sent_with_skip + { + return highest_with_inverse; + } + + skips_sent_with_skip + } + + /// Validate the proposal manifest, these checks are the minimum neccessary + /// checks and it is expected that additional checks will be performed by + /// the application impl + pub fn validate_structure(&self, app: &A, threshold: AcceptThreshold) -> Result<()> { + // Check we have enough accepts + if !threshold.is_exceeded(self.manifest.accepts.len(), self.ordered_validators.len()) { + return Err(Error::InsufficientAcceptsForProposal); + } + + if !self.manifest.verify::(&self.manifest.leader_id) { + return Err(Error::InvalidProposalSignature); + } + + // Check all accepts are valid + for accept in &self.manifest.accepts { + // Check the signature is valid + accept.verify_signature()?; + + // Check the accept leader_id matches the manifest (we cannot check the leader_id is valid + // until validate_contents) + if accept.leader_id != self.manifest.leader_id { + return Err(Error::InvalidAcceptLeader { + expected: self.manifest.leader_id.to_string(), + got: accept.leader_id.to_string(), + }); + } + + // Check the accept hash matches the last proposal hash + if accept.proposal.hash != self.manifest.last_proposal_hash { + return Err(Error::InvalidAcceptProposalHash); + } + } + + // Invalid structure based on app impl + if !app.validate_structure(self.manifest()) { + return Err(Error::ProposalInvalidAppStructure); + } + + Ok(()) + } + + pub fn validate_contents(&self, app: &A, last_confirmed: &Proposal) -> Result<()> { + // Validate the last proposal hash is last confirmed, in practice this should + // never be the triggered because next pending fn would never return + // a current proposal with an invalid decendent, but added as an extra defense + if *last_confirmed.hash() != self.manifest.last_proposal_hash { + return Err(Error::ProposalInvalidDecendent); + } + + // Check the leader is correct, we have to have the last confirmed proposal to check + // the leader as there may have been a validator set change + if last_confirmed.manifest.get_leader_for_skip(self.skips()) != self.manifest.leader_id { + return Err(Error::InvalidProposalLeader); + } + + // Validate the proposal manifest with app specific logic + if !app.validate_contents(self.manifest(), &last_confirmed.manifest) { + return Err(Error::ProposalInvalidAppContent); + } + + // Validate the accepts + for accept in &self.manifest.accepts { + // Validate the accept came from a validator + if !last_confirmed.manifest().validators.contains(&accept.from) { + return Err(Error::InvalidAcceptValidator); + } + } + + Ok(()) + } + + /// Validate an accept sent for this proposal (NOT accepts attached to the manifest) + pub fn validate_accept(&self, accept: &ProposalAccept) -> Result<()> { + // Check the signature is valid + accept.verify_signature()?; + + // Check the accept leader_id is valid + if self.manifest.get_leader_for_skip(accept.skips) != accept.leader_id { + return Err(Error::InvalidAcceptLeader { + expected: self.manifest.get_leader_for_skip(accept.skips).to_string(), + got: accept.leader_id.to_string(), + }); + } + + // Check the accept is from a validator + if !self.manifest().validators.contains(&accept.from) { + return Err(Error::InvalidAcceptValidator); + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::{ + app::{TestApp, TestAppTxnState, UncheckedPeerId}, + util::{ + accept, create_manifest, create_manifest_with_accepts, create_proposal, + genesis_manifest, hash, leader, peer, proposal, + }, + }; + + #[test] + fn test_get_next_leader() { + let proposal_0 = create_proposal(0, 0, 1, &genesis_manifest()); + let proposal_1 = create_proposal(1, 0, 1, proposal_0.manifest()); + let proposal_2 = create_proposal(2, 0, 1, proposal_1.manifest()); + let proposal_3 = create_proposal(3, 0, 1, proposal_2.manifest()); + let proposal_4 = create_proposal(4, 0, 1, proposal_3.manifest()); + let proposal_5 = create_proposal(5, 0, 1, proposal_4.manifest()); + let proposal_6 = create_proposal(6, 0, 1, proposal_5.manifest()); + let proposal_7 = create_proposal(7, 0, 1, proposal_6.manifest()); + let proposal_8 = create_proposal(8, 0, 1, proposal_7.manifest()); + + assert_eq!(proposal_0.manifest.get_leader_for_skip(0), peer(4)); + assert_eq!(proposal_1.manifest.get_leader_for_skip(0), peer(1)); + assert_eq!(proposal_2.manifest.get_leader_for_skip(0), peer(3)); + assert_eq!(proposal_3.manifest.get_leader_for_skip(0), peer(3)); + assert_eq!(proposal_4.manifest.get_leader_for_skip(0), peer(4)); + assert_eq!(proposal_5.manifest.get_leader_for_skip(0), peer(4)); + assert_eq!(proposal_6.manifest.get_leader_for_skip(0), peer(4)); + assert_eq!(proposal_7.manifest.get_leader_for_skip(0), peer(1)); + assert_eq!(proposal_8.manifest.get_leader_for_skip(0), peer(4)); + } + + #[test] + fn test_get_next_leader_with_skips() { + let manifest: Manifest = Manifest::new( + ManifestContent { + last_proposal_hash: ProposalHash::from_vec_hash(vec![0u8]), + skips: 0, + height: 0, + leader_id: peer(1), + state: 0.into(), + validators: vec![peer(1), peer(2), peer(3)], + accepts: vec![], + }, + vec![], + ); + + let proposal = Proposal::::new(manifest); + + // Deterministic sort order + assert_eq!(proposal.ordered_validators, vec![peer(3), peer(2), peer(1)]); + + // Can loop around the peers if needed + assert_eq!(proposal.manifest.get_leader_for_skip(0), peer(3)); + assert_eq!(proposal.manifest.get_leader_for_skip(1), peer(2)); + assert_eq!(proposal.manifest.get_leader_for_skip(2), peer(1)); + assert_eq!(proposal.manifest.get_leader_for_skip(3), peer(3)); + } + + #[test] + fn test_two_thirds_accept_breached_4_peers() { + let manifest = genesis_manifest(); + let mut proposal = proposal(manifest.clone()); + + assert!( + !proposal.accept_threshold_breached(0, AcceptThreshold::MoreThanTwoThirds), + "Should not be breached" + ); + + proposal.add_accept( + accept(&manifest, 0, leader(4), peer(1)), + AcceptThreshold::MoreThanTwoThirds, + ); + + assert!( + !proposal.accept_threshold_breached(0, AcceptThreshold::MoreThanTwoThirds), + "Should not be breached" + ); + + proposal.add_accept( + accept(&manifest, 0, leader(4), peer(2)), + AcceptThreshold::MoreThanTwoThirds, + ); + + assert!( + !proposal.accept_threshold_breached(0, AcceptThreshold::MoreThanTwoThirds), + "Should not be breached" + ); + + proposal.add_accept( + accept(&manifest, 0, leader(4), peer(3)), + AcceptThreshold::MoreThanTwoThirds, + ); + + assert!( + proposal.accept_threshold_breached(0, AcceptThreshold::MoreThanTwoThirds), + "Should be breached" + ); + + proposal.add_accept( + accept(&manifest, 0, leader(4), peer(4)), + AcceptThreshold::MoreThanTwoThirds, + ); + + assert!( + !proposal.accept_threshold_breached(0, AcceptThreshold::MoreThanTwoThirds), + "Should not be breached" + ); + } + + #[test] + fn valid_proposal() { + let last_proposal = create_manifest(0, 0, 1, &genesis_manifest()); + let app = TestApp; + + let manifest = create_manifest_with_accepts( + 1, + 0, + 1, + &hash(&last_proposal), + vec![ + accept(&last_proposal, 0, peer(1), peer(1)), + accept(&last_proposal, 0, peer(1), peer(2)), + accept(&last_proposal, 0, peer(1), peer(3)), + ], + ); + + assert_eq!( + Proposal::new(manifest).validate_structure(&app, AcceptThreshold::MoreThanTwoThirds), + Ok(()) + ); + } + + #[test] + fn insufficient_accepts_for_proposal() { + let app = TestApp; + let manifest = Manifest::new( + ManifestContent { + last_proposal_hash: ProposalHash::genesis(), + skips: 0, + height: 0, + leader_id: peer(1), + state: 0.into(), + validators: vec![peer(1)], + accepts: vec![], + }, + vec![], + ); + + assert_eq!( + Proposal::new(manifest).validate_structure(&app, AcceptThreshold::MoreThanTwoThirds), + Err(Error::InsufficientAcceptsForProposal) + ); + } + + #[test] + fn invalid_proposal_hash() { + let app = TestApp; + let last_proposal = create_manifest(0, 0, 1, &genesis_manifest()); + let alt_proposal = create_manifest(0, 1, 1, &genesis_manifest()); + + let manifest = create_manifest_with_accepts( + 1, + 0, + 1, + &hash(&last_proposal), + vec![ + accept(&last_proposal, 0, peer(1), peer(1)), + accept(&last_proposal, 0, peer(1), peer(2)), + accept(&alt_proposal, 0, peer(1), peer(3)), + ], + ); + + assert_eq!( + Proposal::new(manifest).validate_structure(&app, AcceptThreshold::MoreThanTwoThirds), + Err(Error::InvalidAcceptProposalHash) + ); + } +} diff --git a/pkg/solid/src/proposal/state.rs b/pkg/solid/src/proposal/state.rs new file mode 100644 index 0000000..0d22a8e --- /dev/null +++ b/pkg/solid/src/proposal/state.rs @@ -0,0 +1,44 @@ +use crate::peer::Peer; +use crate::txn::Txn; +use borsh::{BorshDeserialize, BorshSerialize}; +use sha2::{Digest, Sha256}; +use std::fmt::Debug; + +use super::ProposalManifest; + +pub trait ProposalState: Clone + Debug + Send + Sync + 'static { + type State: Debug + + Clone + + Default + + Send + + PartialEq + + Eq + + BorshSerialize + + BorshDeserialize + + 'static; + + fn genesis() -> Self::State { + Self::State::default() + } + + // Validate the proposal, called when the proposal is the "current" proposal, i.e. + // just before an accept is sent. This allows the validate fn to take into account + // the last confirmed proposal state when validating this proposal. + fn validate(&self, _: &ProposalManifest) -> bool { + true + } + + /// Hash of the proposal/block + fn hash(manifest: &ProposalManifest) -> [u8; 32]; +} + +impl ProposalState for Vec { + type State = Self; + + fn hash(manifest: &ProposalManifest) -> [u8; 32] { + #[allow(clippy::unwrap_used)] + #[allow(clippy::disallowed_methods)] // fine since we're just hashing, not deserializing + let bytes = Sha256::digest(borsh::to_vec(&manifest).unwrap()); + bytes.into() + } +} diff --git a/pkg/solid/src/solid/core.rs b/pkg/solid/src/solid/core.rs new file mode 100644 index 0000000..8f864e2 --- /dev/null +++ b/pkg/solid/src/solid/core.rs @@ -0,0 +1,1147 @@ +// lint-long-file-override allow-max-lines=1200 +use super::event::SolidEvent; +use crate::ProposalAcceptSigData; +use crate::config::SolidConfig; +use crate::errors::{Error, Result}; +use crate::proposal::cache::ProposalCache; +use crate::proposal::{Manifest, ProposalHeader}; +use crate::proposal::{Proposal, ProposalAccept, ProposalHash}; +use crate::traits::{App, PeerSigner}; +use std::collections::HashMap; +use std::time::Instant; + +/// SolidCore is responsible for processing proposals and accepts. +#[derive(Debug)] +pub struct SolidCore { + /// peer_id of the local node + local_peer_signer: A::PS, + + /// Pending proposals that may or may not end up being confirmed. + proposals: ProposalCache, + + // TODO: optimisation, we should move this to the proposal cache, and have manifest be an option if we + // haven't received the proposal yet. + /// Orphaned accepts are when we receive an accept for a proposal before we + /// receive the proposal itself. We can then add these as soon as the proposal arrives. + orphan_accepts: HashMap>, + + /// Application state + app: A, + + /// Config + config: SolidConfig, + + /// Max height + max_height: u64, +} + +#[derive(Debug)] +pub struct ProposalOrphan { + pub accepts: Vec>, + pub first_seen: Instant, +} + +impl SolidCore { + pub fn with_last_confirmed( + local_peer_signer: A::PS, + last_confirmed_proposal: Manifest, + app: A, + config: SolidConfig, + ) -> Self { + let max_height = last_confirmed_proposal.height; + + Self { + local_peer_signer, + proposals: ProposalCache::new( + Proposal::new(last_confirmed_proposal), + config.max_proposal_history, + ), + app, + max_height, + orphan_accepts: HashMap::new(), + config, + } + } + + /// Height of the proposal that was last confirmed + pub fn height(&self) -> u64 { + self.proposals.height() + } + + /// Hash of last confirmed + pub fn hash(&self) -> &ProposalHash { + self.proposals().last_confirmed_proposal().hash() + } + + /// Checks if the proposal hash exists, only checks pending proposals + /// as confirmed proposals can be checked via height. + pub fn exists(&self, hash: &ProposalHash) -> bool { + self.proposals.contains(hash) + } + + pub fn max_height(&self) -> u64 { + self.max_height + } + + pub fn proposals(&self) -> &ProposalCache { + &self.proposals + } + + /// Add a pending proposal to the storeProposalManifestContent + pub fn receive_proposal(&mut self, manifest: Manifest) -> Result<()> { + let mut proposal = Proposal::::new(manifest); + let hash = proposal.hash().clone(); + + // Check that the manifest is valid (basic accepts/sig check) + proposal.validate_structure(&self.app, self.config.accept_threshold)?; + + // Proposal already exists, don't recreate + if self.exists(&hash) { + return Err(Error::ProposalAlreadyExists(hash)); + } + + // Check that the height of this proposal > confirmed + if self.height() >= proposal.height() { + return Err(Error::ProposalHeightTooLow); + } + + // Set max height based on proposal + if proposal.height() > self.max_height { + self.max_height = proposal.height(); + } + + // Check if we have orphaned accepts + if let Some(orphan) = self.orphan_accepts.remove(proposal.hash()) { + for accept in orphan.accepts { + proposal.add_accept(accept, self.config.accept_threshold); + } + } + + // Insert the proposal to be processed later + self.proposals.insert(proposal); + + Ok(()) + } + + /// Processes the next event in the store, this will either return a commit or accept + /// event, or None if no more events are ready + pub fn next_event(&mut self) -> Option> { + // Check if there is a proposal we can commit + if let Some(proposal) = self.proposals.next_pending_proposal(0) + && let Some(confirmed_by) = self.proposals.next_pending_proposal(1) + { + let manifest = proposal.manifest().clone(); + let confirmed_by = confirmed_by.manifest().clone(); + + // Add proposal to confirmed list + self.proposals.confirm(A::hash(&manifest)); + + // Send commit + return Some(SolidEvent::Commit { + manifest, + confirmed_by, + }); + } + + // Check if we're out of sync + if self.is_out_of_sync() { + return Some(SolidEvent::OutOfSync { + height: self.height(), + max_seen_height: self.max_height, + }); + } + + let current_proposal = self.validated_current_proposal(); + + // If we have not already sent an accept for this proposal, then do so now + if !current_proposal.initial_accept_sent { + return self.get_next_accept_event(false); + } + + None + } + + /// Skip should be called when we have not received a proposal from the next leader + /// within the timeout period. Skip will send an accept to the next leader. + pub fn skip(&mut self) -> Option> { + // Just in case we try to skip when we're still catching up + if self.is_out_of_sync() { + return None; + } + + // Get the next accept/skip + self.get_next_accept_event(true) + } + + /// Gets the next accept to send, where no pending proposal is available, + /// last confirmed will be used. + fn get_next_accept_event(&mut self, skip: bool) -> Option> { + let local_peer = self.local_peer_signer.peer(); + let threshold = self.config.accept_threshold; + let current_proposal = self.validated_current_proposal(); + + let current_proposal_hash = current_proposal.hash().clone(); + + // Get the skip counter + let skips = current_proposal.next_accept_skip(threshold, skip); + + let proposal_header = ProposalHeader { + hash: current_proposal_hash, + height: current_proposal.height(), + skips: current_proposal.skips(), + }; + + let signature = ProposalAcceptSigData::new(proposal_header.clone(), skips) + .sign(&self.local_peer_signer); + + let current_proposal = self.validated_current_proposal(); + + let accept = ProposalAccept { + proposal: proposal_header, + leader_id: current_proposal.manifest.get_leader_for_skip(skips), + skips, + from: local_peer, + signature, + }; + + current_proposal.skips_sent = skips; + current_proposal.initial_accept_sent = true; + + // Add our own accept to the proposal + self.add_accept(&accept) + .or(Some(SolidEvent::Accept { accept })) + } + + pub fn receive_accept( + &mut self, + accept: &ProposalAccept, + ) -> Result>> { + // Check if accept is valid + accept.verify_signature()?; + + let current_proposal_hash = self.validated_current_proposal().hash().clone(); + + // Update max height + if accept.proposal.height > self.height() { + self.max_height = accept.proposal.height; + } + + // Check if we have the proposal, so we can exit early if we know it's invalid + if let Some(p) = self.proposals.get(&accept.proposal.hash) { + // Check if the accept is valid + p.validate_accept(accept)?; + } + + // Add accept to proposal + Ok(self.add_accept(accept).or_else(|| { + // Check if the current proposal has changed, due to adding the accept + if current_proposal_hash != *self.validated_current_proposal().hash() { + return self.get_next_accept_event(false); + } + None + })) + } + + /// Adds an accept to a proposal, we should only be receiving accepts if we are the + /// next designated leader. Returns ProposalNextState if we have hit the majority and the + /// accept is still valid, otherwise returns None. + pub fn add_accept( + &mut self, + accept: &ProposalAccept, + ) -> Option> { + let ProposalAccept { + proposal: accepted_proposal, + skips, + .. + } = accept; + + // Check if accept is out of date, accept_height must be greater than confirmed height, + // but if there are no pending proposals we may need to accept a proposal with + // accept height == confirmed height (e.g. during start up) + if self.height() > accepted_proposal.height { + return None; + } + + let is_out_of_sync = self.is_out_of_sync(); + let local_peer = &self.local_peer_signer.peer(); + let current_proposal_hash = self.validated_current_proposal().hash().clone(); + + // Add accept to proposal (or to orphaned hash map if proposal is not found/received yet). + // We always store accepts for any future proposal, as we may need them later + match self.proposals.get_mut(&accepted_proposal.hash) { + Some(p) => { + // Trigger propose if adding this accept brings us over the accept threshold AND + // we are the leader for this accept skip AND we are not out of sync + if p.add_accept(accept.clone(), self.config.accept_threshold) + && &p.manifest.get_leader_for_skip(*skips) == local_peer + && !is_out_of_sync + { + return Some(SolidEvent::Propose { + last_proposal_hash: accepted_proposal.hash.clone(), + height: p.height() + 1, + skips: *skips, + accepts: p.accepts_for_skip(skips).unwrap_or_default(), + }); + } + + // This allows us to send an accept for the higher accept we just received, or produce + // a proposal if we have >2/3 accepts for the current proposal + if current_proposal_hash == accepted_proposal.hash && skips > &p.skips_sent { + // TODO: this is UNSAFE in an untrusted network, as a validator could send a high skip + // that would make them the leader, and all other validators would then send supporing accepts/skips. + // We either need to have a VDF that ensures that the skip height is valid (or use some other + // safe method for convergence) + p.skips_sent = *skips; + return self.get_next_accept_event(false); + } + + None + } + None => { + // Get exisiting orphaned proposal list (or create it if it doesn't exist yet) + let first_seen = + if let Some(o) = self.orphan_accepts.get_mut(&accepted_proposal.hash) { + o.accepts.push(accept.clone()); + o.first_seen + } else { + let now = Instant::now(); + self.orphan_accepts.insert( + accepted_proposal.hash.clone(), + ProposalOrphan { + accepts: vec![accept.clone()], + first_seen: now, + }, + ); + now + }; + + // We're the designated leader, and we don't have the proposal being + // accepted. We may need to request it from the network. + let missing_proposal_timeout = self.config.missing_proposal_timeout; + let current_proposal = self.validated_current_proposal(); + let current_proposal_height = current_proposal.height(); + + // It's normal to receive accepts for proposals +1 height ahead of our current proposal, + // because a recently published proposal may be received by another node before me, and they + // could then send that accept. + let missing_more_than_one_proposal = + accepted_proposal.height > (current_proposal_height + 1); + + // We've been waiting a long time for a proposal and that proposal is a higher height or + // same height but higher skip + let proposal_first_seen_expired = first_seen.elapsed() > missing_proposal_timeout; + + let accept_is_greater = accepted_proposal.height > current_proposal.height() + || accepted_proposal.skips > current_proposal.skips(); + + let accept_is_greater_and_timeout = + proposal_first_seen_expired && accept_is_greater; + + if missing_more_than_one_proposal || accept_is_greater_and_timeout { + // We are behind, so we need to request proposals from the network + return Some(SolidEvent::OutOfSync { + height: self.height(), + max_seen_height: accepted_proposal.height, + }); + } + None + } + } + } + + fn highest_next_pending(&self) -> Option<&Proposal> { + let last_confirmed = self.proposals.last_confirmed_proposal(); + + let last_confirmed_highest_skip = last_confirmed + .highest_skip_with_inverse(self.config.accept_threshold) + .unwrap_or(0); + + // The proposal with the highest skip at height + 1 + self.proposals.next_pending_proposal(0).and_then(|p| { + // Check if the skips for the next proposal are high enough: + // 1. network has already skipped passed this proposal, then we should ignore it (it can never be valid) + // 2. we have skipped pass this proposal ourselves + if last_confirmed_highest_skip > p.skips() || last_confirmed.skips_sent > p.skips() { + return None; + } + Some(p) + }) + } + + /// The current proposal we are sending accepts for, this will be either: + /// - confirmed_proposal + 1 (with the heighest skip we have seen) + /// - confirmed_proposal (if we have no pending proposals) + fn validated_current_proposal_hash(&mut self) -> ProposalHash { + loop { + let last_confirmed = self.proposals.last_confirmed_proposal(); + let (highest_next_pending, is_valid) = self + .highest_next_pending() + .map(|p| { + ( + p.hash(), + p.is_validated || p.validate_contents(&self.app, last_confirmed).is_ok(), + ) + }) + .unwrap_or_else(|| (self.proposals.last_confirmed_proposal().hash(), true)); + + let hash = highest_next_pending.clone(); + + if is_valid { + return hash; + } + + // Remove the invalid proposal + self.proposals.remove(&hash); + } + } + + pub fn current_proposal(&mut self) -> &Proposal { + let hash = self.validated_current_proposal_hash(); + #[allow(clippy::expect_used)] + self.proposals + .get(&hash) + .expect("Proposal is current, but now missing from proposal cache") + } + + pub fn validated_current_proposal(&mut self) -> &mut Proposal { + let hash = self.validated_current_proposal_hash(); + #[allow(clippy::expect_used)] + let proposal = self + .proposals + .get_mut(&hash) + .expect("Proposal is current, but now missing from proposal cache"); + + // Cache the validation status, we can simply mark as true as we only get the hash if + // it's valid + proposal.is_validated = true; + proposal + } + + /// Do we have have proposals from the network that are beyond the normal operating + /// limit (i.e. confirmed height + 1) + /// TODO: should we include accepts in this too? + pub fn is_out_of_sync(&self) -> bool { + self.max_height > self.height() + 1 + } +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use crate::{ + Error, assert_none, + config::SolidConfig, + test::{ + app::TestApp, + util::{ + SolidCore, accept, accept_event, commit_event, core_genesis, + core_genesis_with_config, core_with_last_confirmed, create_manifest, hash, + last_confirmed, leader, manifest_at, out_of_sync_event, peer, propose_event, skips, + }, + }, + }; + + // Propoasl/accept numbering: + // - 1.0 = height 1, skip 0 + // - 1.1 = height 1, skip 1 + // - 2.0 = height 2, skip 0 + // etc + + // TODO: + // - test .skip() - more events are possible than are tested + // - do we detect invalid proposal chains? E.g. 1.0 -> 2.0 -> 1.1 + // - test we do not send accepts or proposals when out of sync with the network + // - out of order accepts are stored and can be used to propose later + // - ignores accepts where I am not the designated leader, we should just reject these completely + + /// Test nominal path for proposal confirmation from genesis -> 0.0 -> 1.0 -> 2.0 + #[test] + fn test_next_genesis() { + // Create store from genesis + let mut store = core_genesis(); + + // Confirmed genesis + let p_0_0 = last_confirmed(&store); + + // Send accept for 0.0 (to 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + assert_none!(store.next_event()); + + // Proposal 1.0 received (from 0.0) + let p_1_0 = create_manifest(1, 0, 4, &p_0_0); + store.receive_proposal(p_1_0.clone()).unwrap(); + + // Send accept for 1.0 (to 2.0) + assert_eq!( + store.next_event(), + accept_event(&p_1_0, skips(0), leader(1), peer(1)) + ); + assert_none!(store.next_event()); + + // Add proposal for height 2.0 (from 1.0) + let p_2_0 = create_manifest(2, 0, 1, &p_1_0); + store.receive_proposal(p_2_0.clone()).unwrap(); + + // Commit 1.0 (from 0.0) + assert_eq!(store.next_event(), commit_event(&p_1_0, &p_2_0)); + + // Send accept for 2.0 (from 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_2_0, skips(0), leader(3), peer(1)) + ); + + // Noting else to do + assert_none!(store.next_event()); + } + + // Tests nominal path for confirmation from a given starting proposal -> 10.0 -> 11.0 -> 12.0 + #[test] + fn test_next_with_last_confirmed() { + // Create a store with last confirmed 10.0 + let p_10_0 = create_manifest(10, 0, 2, &manifest_at(9)); + let mut store = core_with_last_confirmed(&p_10_0); + + // Send accept for 10.0 (to 11.0) + assert_eq!( + store.next_event(), + accept_event(&p_10_0, skips(0), leader(4), peer(1)) + ); + + // Proposal 11.0 received (from 10.0) + let p_11_0 = create_manifest(11, 0, 4, &p_10_0); + store.receive_proposal(p_11_0.clone()).unwrap(); + + // Send accept for 11.0 (to 12.0) + assert_eq!( + store.next_event(), + accept_event(&p_11_0, skips(0), leader(4), peer(1)) + ); + assert_none!(store.next_event()); + + // Proposal 12.0 received (from 11.0) + let p_12_0 = create_manifest(12, 0, 4, &p_11_0); + store.receive_proposal(p_12_0.clone()).unwrap(); + + // Commit 11.0 (from 10.0) + assert_eq!(store.next_event(), commit_event(&p_11_0, &p_12_0)); + + // Send accept for 12.0 (from 11.0) + assert_eq!( + store.next_event(), + accept_event(&p_12_0, skips(0), leader(4), peer(1)) + ); + + // Nothing else to do + assert_none!(store.next_event()); + } + + /// Node skips, network skips -> 0.0 -> 1.1 -> 2.0 + /// + /// - 0.0 is confirmed (genesis) + /// - Send accept for 0.0 (to 1.0) + /// - Timeout expires waiting for 1.0 + /// - Send accept for 0.0 (to 1.1) + /// - 1.1 proposal received + /// - Send accept for 1.1 (to 2.0) + /// - 2.0 proposal received + /// - Confirm 1.0 proposal + /// + #[test] + fn test_node_skips_network_skips() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Send accept for 0.0 (to 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + + // Send skip for 0.0 (to 1.1) after timeout + assert_eq!(store.skip(), accept_event(&p_0_0, 1, leader(3), peer(1))); + + // Proposal 1.1 received (from 0.0) + let p_1_1 = create_manifest(1, 1, 3, &p_0_0); + store.receive_proposal(p_1_1.clone()).unwrap(); + + // Send accept for 1.1 (to 2.0) + assert_eq!( + store.next_event(), + accept_event(&p_1_1, skips(0), leader(3), peer(1)) + ); + + // Proposal 2.0 received (from 1.1) + let p_2_0 = create_manifest(2, 0, 3, &p_1_1); + store.receive_proposal(p_2_0.clone()).unwrap(); + + // Commit + assert_eq!(store.next_event(), commit_event(&p_1_1, &p_2_0)); + + // Send accept for 2.0 (to 3.0) + assert_eq!( + store.next_event(), + accept_event(&p_2_0, skips(0), leader(3), peer(1)) + ); + + // Nothing else to do + assert_none!(store.next_event()); + } + + /// Node accepts, network skips -> 0.0 -> 1.1 -> 2.0 + /// + /// In this scenario, the network skips a proposal, but the node does not. + /// Node will later conform to the network decision to skip. + /// + /// - 0.0 is confirmed (genesis) + /// - Send accept for 0.0 (to 1.0) + /// - 1.0 proposal received + /// - Send accept for 1.0 (to 2.0) + /// - 1.1 proposal received + /// - Send accept for 1.1 (to 2.0) + /// - 2.0 proposal received + /// - Confirm 1.1 proposal + /// + #[test] + fn test_node_accepts_network_skips() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Send accept for 0.0 (to 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + assert_none!(store.next_event()); + + // Proposal 1.0 received (from 0.0) + let p_1_0 = create_manifest(1, 0, 4, &p_0_0); + store.receive_proposal(p_1_0.clone()).unwrap(); + + // Send accept for 1.0 (to 2.0), I can do this because I have not sent a skip for 0.0 to 1.1 + assert_eq!( + store.next_event(), + accept_event(&p_1_0, skips(0), leader(1), peer(1)) + ); + assert_none!(store.next_event()); + + // Proposal 1.1 received (from 1.0), >2/3 must have sent a skip to 1.1 + let p_1_1 = create_manifest(1, 1, 3, &p_0_0); + store.receive_proposal(p_1_1.clone()).unwrap(); + + // Send accept for 1.1 (to 2.0) + assert_eq!( + store.next_event(), + accept_event(&p_1_1, skips(0), leader(3), peer(1)) + ); + assert_none!(store.next_event()); + + // TODO: if I receive a proposal 2.0 based on 1.0 then something malicious is going on, we should test this scenario + // and impl alerting/slashing rules + + // Proposal 2.0 received (from 1.1) + let p_2_0 = create_manifest(2, 0, 3, &p_1_1); + store.receive_proposal(p_2_0.clone()).unwrap(); + + // Commit + assert_eq!(store.next_event(), commit_event(&p_1_1, &p_2_0)); + + // Send accept for 2.0 (to 3.0) + assert_eq!( + store.next_event(), + accept_event(&p_2_0, skips(0), leader(3), peer(1)) + ); + + // Nothing else to do + assert_none!(store.next_event()); + } + + /// Node skips, network accepts -> 0.0 -> 1.0 -> 2.0 + /// + /// In this scenario, the node skips a proposal, but the network does not. Although, I may + /// see the proposal I skipped (as the network has voted for it), I must not accept it. + /// + /// - 0.0 is confirmed (last confirmed proposal, genesis) + /// - Send accept for 0.0 (to 1.0) + /// - Timeout expires waiting for 1.0 + /// - Send accept for 0.0 (to 1.1) + /// - 1.0 proposal received (ignored) + /// - 1.1 proposal received + /// - 2.0 proposal received + /// - Confirm 1.0 proposal + /// + #[test] + fn test_node_skips_network_accepts() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Send accept for 0.0 (to 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + + // Send skip for 0.0 (to 1.1) after timeout + assert_eq!(store.skip(), accept_event(&p_0_0, 1, peer(3), peer(1))); + + // Proposal 1.0 received (from 0.0) + let p_1_0 = create_manifest(1, 0, 1, &p_0_0); + store.receive_proposal(p_1_0.clone()).unwrap(); + + // Ignore proposal, as we skipped it + assert_none!(store.next_event()); + + // Proposal 2.0 received (from 1.0) + let p_2_0 = create_manifest(2, 0, 1, &p_1_0); + store.receive_proposal(p_2_0.clone()).unwrap(); + + // Commit + assert_eq!(store.next_event(), commit_event(&p_1_0, &p_2_0)); + + // Send accept for 2.0 (to 3.0) + assert_eq!( + store.next_event(), + accept_event(&p_2_0, skips(0), leader(3), peer(1)) + ); + + // Nothing else to do + assert_none!(store.next_event()); + } + + /// Node accepts, network skips, node reverts -> 0.0 -> 1.1 -> 2.0 + /// + /// In this scenario, the node accepts a proposal (1.0) along with >=1/3 of the network, however >=1/3 + /// skip 1.0. As a result, those who have accepted 1.0 must now revert to skipping 1.0 and instead vote + /// for 1.1 so the network can converge. + /// + /// - 0.0 is confirmed (last confirmed proposal, genesis) + /// - Send accept for 0.0 (to 1.0) + /// - 1.0 proposal received + /// - Send accept for 1.0 (to 2.0) + /// - Receive skips from >1/3 for 0.0 (to 1.1) - 1.0 can never be confirmed now + /// - Send accept for 0.0 (to 1.1) + /// - 1.1 proposal received + /// - Send accept for 1.1 (to 2.0) + /// + #[test] + fn test_node_accepts_network_skips_with_skip_revert() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Send accept for 0.0 (to 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + assert_none!(store.next_event()); + + // Proposal 1.0 received (from 0.0) + let p_1_0 = create_manifest(1, 0, 4, &p_0_0); + store.receive_proposal(p_1_0.clone()).unwrap(); + + // Send accept for 1.0 (to 2.0), I can do this because I have not sent a skip for 0.0 to 1.1 + assert_eq!( + store.next_event(), + accept_event(&p_1_0, skips(0), leader(1), peer(1)) + ); + assert_none!(store.next_event()); + + // Notified that peer 2 has skipped to 1.1 + assert_none!( + store + .receive_accept(&accept(&p_0_0, 1, leader(3), peer(2))) + .unwrap() + ); + + // Notified that peer 3 has skipped to 1.1, now more than >=1/3 skips seen, + // we should send an accept for 1.1 too + assert_eq!( + store.receive_accept(&accept(&p_0_0, 1, peer(3), peer(3))), + Ok(accept_event(&p_0_0, 1, peer(3), peer(1))) + ); + + // Proposal 1.1 received (from 1.0), >2/3 must have sent a skip to 1.1 + let p_1_1 = create_manifest(1, 1, 3, &p_0_0); + store.receive_proposal(p_1_1.clone()).unwrap(); + + // Send accept for 1.1 (to 2.0) + assert_eq!( + store.next_event(), + accept_event(&p_1_1, skips(0), leader(3), peer(1)) + ); + assert_none!(store.next_event()); + + // Proposal 2.0 received (from 1.1) + let p_2_0 = create_manifest(2, 0, 3, &p_1_1); + store.receive_proposal(p_2_0.clone()).unwrap(); + + // Commit + assert_eq!(store.next_event(), commit_event(&p_1_1, &p_2_0)); + + // Send accept for 2.0 (to 3.0) + assert_eq!( + store.next_event(), + accept_event(&p_2_0, skips(0), leader(3), peer(1)) + ); + + // Nothing else to do + assert_none!(store.next_event()); + } + + /// Test multiple skips for a proposal, leader should rotate for each skip, + /// no further action should be taken by .next_event() + #[test] + fn test_multiple_skips() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Send accept for 0.0 (to 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + assert_none!(store.next_event()); + + // Send skip for 0.0 (to 1.1) after timeout + assert_eq!(store.skip(), accept_event(&p_0_0, 1, peer(3), peer(1))); + assert_none!(store.next_event()); + + // Send skip for 0.0 (to 1.2) after timeout + assert_eq!(store.skip(), accept_event(&p_0_0, 2, peer(2), peer(1))); + assert_none!(store.next_event()); + + // Send skip for 0.0 (to 1.3) after timeout + assert_eq!(store.skip(), accept_event(&p_0_0, 3, peer(1), peer(1))); + assert_none!(store.next_event()); + + // Send skip for 0.0 (to 1.4) after timeout + assert_eq!(store.skip(), accept_event(&p_0_0, 4, peer(4), peer(1))); + assert_none!(store.next_event()); + } + + /// Node should propose a proposal once it has received >2/3 of accepts + #[test] + fn test_propose_when_accept_threshold_met() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + + // Skip 3 times so we are the leader (so we can ensure the leader adds their own accept) + assert_eq!(store.skip(), accept_event(&p_0_0, 1, leader(3), peer(1))); + assert_eq!(store.skip(), accept_event(&p_0_0, 2, leader(2), peer(1))); + assert_eq!(store.skip(), accept_event(&p_0_0, 3, leader(1), peer(1))); + + // Receive first accept, no >2/3 + assert_none!( + store + .receive_accept(&accept(&p_0_0, 3, leader(1), peer(2))) + .unwrap() + ); + + // Receive duplicate first accept, no >2/3 + assert_none!( + store + .receive_accept(&accept(&p_0_0, 3, leader(1), peer(2))) + .unwrap() + ); + + // Receive second accept, >2/3, so we should propose + let propose = propose_event( + hash(&p_0_0), + 1, + 3, + vec![ + accept(&p_0_0, 3, leader(1), peer(1)), + accept(&p_0_0, 3, leader(1), peer(2)), + accept(&p_0_0, 3, leader(1), peer(3)), + ], + ); + assert_eq!( + store.receive_accept(&accept(&p_0_0, skips(3), leader(1), peer(3))), + Ok(propose) + ); + + // Technically, we'd expect to be passed a proposal (generated locally from the propose event + // but if we haven't been sent that, then we have nothing else to do) + assert_none!(store.next_event()); + + // Final accept received, but no further action required + assert_none!( + store + .receive_accept(&accept(&p_0_0, skips(0), leader(4), peer(4))) + .unwrap() + ); + + // Still nothing to do + assert_none!(store.next_event()); + } + + #[test] + fn test_propose_with_higher_skip_when_threshold_met() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Skip + assert_eq!( + store.next_event(), + accept_event(&p_0_0, 0, leader(4), peer(1)) + ); + assert_eq!(store.skip(), accept_event(&p_0_0, 1, leader(3), peer(1))); + + // Add accept for 0.0 (to 1.11), we generate an accept here so the network + // can converge more quickly + assert_eq!( + store.receive_accept(&accept(&p_0_0, 11, leader(1), peer(2))), + Ok(accept_event(&p_0_0, 11, leader(1), peer(1))) + ); + + // Receive second accept, >2/3, so we should propose + let propose = propose_event( + hash(&p_0_0), + 1, + 11, + vec![ + accept(&p_0_0, 11, peer(1), peer(1)), + accept(&p_0_0, 11, peer(1), peer(2)), + accept(&p_0_0, 11, peer(1), peer(3)), + ], + ); + assert_eq!( + store.receive_accept(&accept(&p_0_0, skips(11), leader(1), peer(3))), + Ok(propose) + ); + + assert_none!(store.next_event()); + } + + #[test] + fn test_higher_skip_accept_received() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Add accept for 0.0 (to 1.10) + assert_eq!( + store.receive_accept(&accept(&p_0_0, 10, leader(2), peer(2))), + Ok(accept_event(&p_0_0, 10, leader(2), peer(1))) + ); + + // Skip should now start from 11 + assert_eq!(store.skip(), accept_event(&p_0_0, 11, leader(1), peer(1))); + } + + /// Test that during start up (where we have no pending proposals), that we generate + /// an out of sync event if we are behind the network. + #[test] + fn test_out_of_sync_from_proposal_at_startup() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Send accept for 0.0 (to 1.0) + assert_eq!( + store.next_event(), + accept_event(&p_0_0, skips(0), leader(4), peer(1)) + ); + assert_none!(store.next_event()); + + // Not out of sync currently + assert!(!store.is_out_of_sync()); + + // DID NOT receive proposal 1.0 + let p_1_0 = create_manifest(1, 0, 2, &p_0_0); + + // Receive proposal 2.0 + let p_2_0 = create_manifest(2, 0, 1, &p_1_0); + store.receive_proposal(p_2_0.clone()).unwrap(); + + // We are behind, so we should send an out of sync message + assert_eq!(store.next_event(), out_of_sync_event(0, 2)); + + // Out of sync + assert!(store.is_out_of_sync()); + + // Now we receive proposal 1.0 + store.receive_proposal(p_1_0.clone()).unwrap(); + + // Commit 1.0 + assert_eq!(store.next_event(), commit_event(&p_1_0, &p_2_0)); + + // No longer out of sync + assert!(!store.is_out_of_sync()); + } + + /// Test that after start up, where we should always have a pending proposal, that we + /// generate an out of sync event if we are behind the network. + #[test] + fn test_out_of_sync_from_proposal_with_pending() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Receive proposal 1.0 + let p_1_0 = create_manifest(1, 0, 4, &p_0_0); + store.receive_proposal(p_1_0.clone()).unwrap(); + + // Send accept for 1.0 (to 2.0) + assert_eq!( + store.next_event(), + accept_event(&p_1_0, skips(0), leader(1), peer(1)) + ); + assert_none!(store.next_event()); + + // Not out of sync currently + assert!(!store.is_out_of_sync()); + + // DID NOT receive proposal 2.0 + let p_2_0 = create_manifest(2, 0, 2, &p_1_0); + + // Receive proposal 3.0 + let p_3_0 = create_manifest(3, 0, 1, &p_2_0); + store.receive_proposal(p_3_0.clone()).unwrap(); + + // We are behind, so we should send an out of sync message + assert_eq!(store.next_event(), out_of_sync_event(0, 3)); + + // Out of sync + assert!(store.is_out_of_sync()); + + // Now we receive proposal 2.0 + store.receive_proposal(p_2_0.clone()).unwrap(); + + // Commit 1.0 + assert_eq!(store.next_event(), commit_event(&p_1_0, &p_2_0)); + + // Commit 2.0 + assert_eq!(store.next_event(), commit_event(&p_2_0, &p_3_0)); + + // No longer out of sync + assert!(!store.is_out_of_sync()); + } + + /// We can also use accepts to determine if we're out of sync with the network + #[test] + fn test_out_of_sync_from_accept_at_startup() { + // Create store from genesis + let mut store = core_genesis(); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Not out of sync currently + assert!(!store.is_out_of_sync()); + + // DID NOT receive proposal 1.0 + let p_1_0 = create_manifest(1, 0, 2, &p_0_0); + + // DID NOT receive proposal 2.0 + let p_2_0 = create_manifest(2, 0, 2, &p_1_0); + + // Receive accept for 1.0 + assert_none!( + store + .receive_accept(&accept(&p_1_0, 0, leader(1), peer(1))) + .unwrap() + ); + + // Not out of sync currently + assert!(!store.is_out_of_sync()); + + // Receive accept for 2.0 + assert_eq!( + store.receive_accept(&accept(&p_2_0, 0, leader(1), peer(1))), + Ok(out_of_sync_event(0, 2)) + ); + + // Receive accept for 2.0 + assert_none!( + store + .receive_accept(&accept(&p_0_0, 0, leader(4), peer(2))) + .unwrap() + ); + } + + #[test] + fn test_out_of_sync_from_accept_at_startup_with_delay() { + // Create store from genesis + let mut store: SolidCore = core_genesis_with_config(SolidConfig { + missing_proposal_timeout: Duration::from_millis(200), + ..Default::default() + }); + + // Last confirmed proposal + let p_0_0 = last_confirmed(&store); + + // Not out of sync currently + assert!(!store.is_out_of_sync()); + + // DID NOT receive proposal 1.0 + let p_1_0 = create_manifest(1, 0, 2, &p_0_0); + + // Receive accept for 1.0 + assert_none!( + store + .receive_accept(&accept(&p_1_0, 0, leader(1), peer(1))) + .unwrap() + ); + + // Time passes and we receive another accept for 1.0 + std::thread::sleep(store.config.missing_proposal_timeout); + + // Now enough time has passed, we should send out of sync + assert_eq!( + store.receive_accept(&accept(&p_1_0, 0, leader(1), peer(1))), + Ok(out_of_sync_event(0, 1)) + ); + } + + #[test] + fn error_duplicate_proposal() { + let mut core = core_genesis(); + + let manifest = manifest_at(10); + let hash = hash(&manifest); + + // Send proposal twice + core.receive_proposal(manifest.clone()).unwrap(); + assert_eq!( + core.receive_proposal(manifest), + Err(Error::ProposalAlreadyExists(hash)) + ); + } +} diff --git a/pkg/solid/src/solid/event.rs b/pkg/solid/src/solid/event.rs new file mode 100644 index 0000000..e0f9f68 --- /dev/null +++ b/pkg/solid/src/solid/event.rs @@ -0,0 +1,39 @@ +use crate::{ + AppState, Peer, + proposal::{Manifest, ProposalAccept, ProposalHash}, +}; +use borsh::{BorshDeserialize, BorshSerialize}; + +#[derive(Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub enum SolidEvent { + /// Send a new proposal to the network, as we are the the next leader + Propose { + last_proposal_hash: ProposalHash, + height: u64, + skips: u64, + accepts: Vec>, + }, + + /// Proposal has been confirmed and should be committed + /// to the data store + Commit { + /// Proposal manifest to commit + manifest: Manifest, + /// An unconfirmed proposal that justified the proposal being committed + confirmed_by: Manifest, + }, + + /// Accept a proposal, this is a vote this node + /// to become the next leader (and create a proposal) + Accept { accept: ProposalAccept

}, + + /// Node is missing proposals + OutOfSync { + /// Height of the node + height: u64, + max_seen_height: u64, + }, + + /// Duplicate proposal received + DuplicateProposal { proposal_hash: ProposalHash }, +} diff --git a/pkg/solid/src/solid/mod.rs b/pkg/solid/src/solid/mod.rs new file mode 100644 index 0000000..a21ced3 --- /dev/null +++ b/pkg/solid/src/solid/mod.rs @@ -0,0 +1,269 @@ +#![allow(clippy::unwrap_used)] +// lint-long-file-override allow-max-lines=300 +pub mod core; +pub mod event; +mod shared; +mod stream; +use std::collections::VecDeque; +use std::sync::Arc; + +use self::core::SolidCore; +use self::event::SolidEvent; +pub use self::shared::*; + +use crate::config::SolidConfig; +use crate::errors::Result; +use crate::proposal::{Manifest, ProposalAccept, ProposalHash}; +use crate::traits::{App, PeerSigner}; +use crate::util::tick_worker::TickWorker; +use crate::util::time::AtomicTimestamp; +use chrono::Utc; +use parking_lot::Mutex; +use tokio::time::Instant; + +/** + * Solid is responsible creating an event stream of SolidEvent events, and + * triggering skip messages if interval expires. + */ + +#[derive(Clone)] +pub struct Solid { + shared: Arc>, + ticker: Arc>>>, +} + +impl Solid { + pub fn with_last_confirmed( + local_peer_signer: A::PS, + validators: Vec, + manifest: Manifest, + app: A, + config: SolidConfig, + ) -> Self { + assert!(!validators.is_empty(), "Must have at least one validator"); + + let shared = Arc::new(SolidShared { + local_peer_signer: local_peer_signer.clone(), + events: Mutex::new(VecDeque::new()), + core: Mutex::new(SolidCore::with_last_confirmed( + local_peer_signer, + manifest, + app, + config.clone(), + )), + skip_timeout: AtomicTimestamp::new(None), + out_of_sync_timeout: Mutex::new(None), + state: Mutex::new(SolidState { waker: None }), + config, + }); + + Self { + shared, + ticker: Arc::new(TickWorker::new()), + } + } + + pub fn genesis( + local_peer_signer: A::PS, + validators: Vec, + app: A, + config: SolidConfig, + ) -> Self { + Self::with_last_confirmed( + local_peer_signer, + validators.clone(), + Manifest::genesis(validators), + app, + config, + ) + } + + pub fn reset(&self, manifest: Manifest, app: A) { + let mut store = self.shared.core.lock(); + *store = SolidCore::with_last_confirmed( + self.shared.local_peer_signer.clone(), + manifest, + app, + self.shared.config.clone(), + ); + let mut events = self.shared.events.lock(); + events.clear(); + self.reset_skip_timeout(); + } + + pub fn run(&self) -> tokio::task::JoinHandle<()> { + // Create background worker, this is mostly responsible for sending skips + // when a new proposal has not been created by the next responsible leader + // *self.shared.skip_timeout.lock().unwrap() = Some(Instant::now()); + self.next_event(); + self.ticker.run(Arc::clone(&self.shared)) + } + + /// Gets the highest confirmed height for this register + pub fn height(&self) -> u64 { + self.shared.core.lock().height() + } + + pub fn hash(&self) -> ProposalHash { + self.shared.core.lock().hash().clone() + } + + pub fn max_height(&self) -> u64 { + self.shared.core.lock().max_height() + } + + pub fn is_out_of_sync(&self) -> bool { + self.shared.core.lock().is_out_of_sync() + } + + /// Whether a proposal hash exists in the data + pub fn exists(&self, hash: &ProposalHash) -> bool { + self.shared.core.lock().exists(hash) + } + + /// Get a list of confirmed proposals from a given height + pub fn confirmed_proposals_from(&self, i: u64) -> Vec> { + self.shared + .core + .lock() + .proposals() + .confirmed_proposals_from(i) + .iter() + .map(|p| p.manifest().clone()) + .collect() + } + + pub fn get_proposal(&self, hash: &ProposalHash) -> Option> { + self.shared + .core + .lock() + .proposals() + .get(hash) + .map(|p| p.manifest().clone()) + } + + pub fn current_proposal(&self) -> Manifest { + self.shared + .core + .lock() + .current_proposal() + .manifest() + .clone() + } + + /// Get a list of decendents from a given proposal hash + pub fn decendents( + &self, + decendent_hash: &ProposalHash, + parent_hash: &ProposalHash, + ) -> Vec> { + self.shared + .core + .lock() + .proposals() + .decendents(decendent_hash, parent_hash) + .into_iter() + .map(|p| p.manifest().clone()) + .collect() + } + + /// Receive a new proposal from an external source, we do some basic validation + /// to make sure this is a valid proposal that could be confirmed. + pub fn receive_proposal(&self, manifest: Manifest) -> Result<()> { + self.shared.core.lock().receive_proposal(manifest)?; + + // Process next rounds with the newly added proposal, and keep + // processing until nothing is left + self.next_event(); + + Ok(()) + } + + /// Receive a new accept from an external source, we should only really receive accepts + /// if we are to to be the next leader, store will determine if this is valid and send + pub fn receive_accept(&self, accept: &ProposalAccept) -> Result<()> { + if let Some(event) = self.shared.core.lock().receive_accept(accept)? { + self.shared.send_event(event) + } + + Ok(()) + } + + /// Reset skip timeout as we received the next proposal in time + fn reset_skip_timeout(&self) { + // should we just make the config use `chrono::Duration` instead? + let skip_timeout = chrono::Duration::from_std(self.shared.config.skip_timeout).unwrap(); + let new_timeout = Utc::now() + skip_timeout; + self.shared.skip_timeout.store(Some(new_timeout)); + self.ticker.tick(); + } + + /// Clear skip timeout when we are the one proposing a new proposal, or when we are + /// behind/out of sync with the network + fn clear_skip_timeout(&self) { + self.shared.skip_timeout.store(None); + self.ticker.tick(); + } + + // Process the next proposal in the chain, this should move the proposal + // If we don't have the next proposal in the chain, request it from the network + fn next_event(&self) { + let mut store = self.shared.core.lock(); + + // Keep telling the store to process proposals until it returns None, signalling it cannot + // make further process until another proposal or accept is received + while let Some(event) = store.next_event() { + match &event { + // We are catching up or out of sync, so there is no need for the timeout to be active, + // we will wake up the timer after we have caught up (i.e. when we see the next SendAccept) + SolidEvent::OutOfSync { .. } => { + self.clear_skip_timeout(); + + let mut timeout = self.shared.out_of_sync_timeout.lock(); + if let Some(timeout) = &mut *timeout + && *timeout > Instant::now() + { + return; + } + + // Set the out of sync timeout + *timeout = Some(Instant::now() + self.shared.config.out_of_sync_timeout); + + // Send the event, but cancel looping + self.shared.send_event(event); + return; + } + SolidEvent::Commit { .. } => { + self.reset_skip_timeout(); + } + + SolidEvent::Propose { .. } => { + // We don't want to send a skip for our own proposals, so clear the timeout + self.clear_skip_timeout(); + } + + // We received a new valid proposal, that we are willing to accept. This is the best + // indication that we think we are in sync with the network. We now want to track + // whether the proposal for this accept is also accepted by the network (in time), indicated + // by receiving a subsequent proposal at the next height (and subsequently the store tells us + // to send the next SendAccept) + SolidEvent::Accept { accept } => { + // Cancel out of sync, if we are sending an accept + *self.shared.out_of_sync_timeout.lock() = None; + // Restart the timer for the current proposal to be accepted + self.reset_skip_timeout(); + + // Skip sending accept for our own proposal + if accept.leader_id == self.shared.local_peer_signer.peer() { + return; + } + } + + _ => {} + } + + // Send the event to the event stream + self.shared.send_event(event); + } + } +} diff --git a/pkg/solid/src/solid/shared.rs b/pkg/solid/src/solid/shared.rs new file mode 100644 index 0000000..e8bf38e --- /dev/null +++ b/pkg/solid/src/solid/shared.rs @@ -0,0 +1,274 @@ +#![allow(clippy::unwrap_used)] +// lint-long-file-override allow-max-lines=300 +use super::core::SolidCore; +use super::event::SolidEvent; +use crate::config::SolidConfig; +use crate::traits::App; +use crate::util::tick_worker::TickWorkerTick; +use crate::util::time::AtomicTimestamp; +use chrono::{DateTime, Utc}; +#[allow(unused_imports)] +use futures::stream::StreamExt; +use futures::task::Waker; +use parking_lot::Mutex; +use std::collections::VecDeque; +use std::sync::Arc; +use tokio::time::Instant; + +pub struct SolidShared { + pub(crate) local_peer_signer: A::PS, + + /// Events to be streamed + pub(crate) events: Mutex>>, + + /// Timeout used for skips (aka expired accepts, no new proposal + /// received within timeout period) + pub(crate) skip_timeout: AtomicTimestamp, + + /// Timeout used when an out of sync message has been sent to the network, + /// we need to wait a configurable amount of time before sending another + pub(crate) out_of_sync_timeout: Mutex>, + + /// Shared proposal state, must be updated together + pub(crate) state: Mutex, + + /// Core for processing proposals and accepts + pub(crate) core: Mutex>, + + /// Configuration for the proposal register + pub(crate) config: SolidConfig, +} + +#[derive(Debug)] +pub struct SolidState { + pub(crate) waker: Option, +} + +impl SolidShared { + pub fn send_event(&self, event: SolidEvent) { + { + let mut events = self.events.lock(); + events.push_back(event); + } + let mut state = self.state.lock(); + if let Some(waker) = state.waker.take() { + waker.wake(); + } + } +} + +impl TickWorkerTick for Arc> { + /// Checks for either: next_proposal or a skip timeout + fn tick(&self) -> Option> { + let skip_timeout = self.skip_timeout.load(); + + if skip_timeout? > Utc::now() { + return skip_timeout; + } + + if let Some(event) = self.core.lock().skip() { + self.send_event(event); + } + + let add = chrono::Duration::from_std(self.config.skip_timeout).unwrap(); + + // TODO: is this valid, do we really want to add the time here rather than just + // set a new time from now? + self.skip_timeout.fetch_add(add); + + self.skip_timeout.load() + } +} + +#[cfg(test)] +mod test { + + use super::super::*; + use super::*; + use crate::proposal::{ProposalAccept, ProposalHeader}; + use crate::test::util::{ManifestContent, hash}; + use crate::test::{ + app::{TestApp, UncheckedPeerId}, + util::{create_peers, peer, signer}, + }; + use chrono::{TimeZone, Timelike}; + + fn solid(id: u8) -> Solid { + let app = TestApp; + + Solid::::genesis( + signer(id), + create_peers().to_vec(), + app, + SolidConfig { + ..SolidConfig::default() + }, + ) + } + + fn accept( + leader: u8, + hash: ProposalHash, + height: u64, + skips: u64, + from: u8, + ) -> ProposalAccept { + ProposalAccept { + leader_id: peer(leader), + proposal: ProposalHeader { + hash, + height, + skips: 0, + }, + skips, + from: peer(from), + signature: vec![], + } + } + + #[tokio::test] + async fn first_proposal_single_peer() { + let config = SolidConfig::default(); + let mut solid = Solid::genesis(signer(1), vec![peer(1)], TestApp, config); + + let manifest = Manifest::new( + ManifestContent { + last_proposal_hash: solid.hash(), + height: 1, + skips: 0, + leader_id: peer(1), + state: 0.into(), + validators: vec![peer(1)], + accepts: vec![accept(1, solid.hash(), 0, 0, 1)], + }, + vec![], + ); + let hash = hash(&manifest); + + solid.receive_proposal(manifest.clone()).unwrap(); + + let next = solid.next().await.unwrap(); + + assert_eq!( + next, + SolidEvent::Propose { + last_proposal_hash: hash.clone(), + height: 2, + skips: 0, + accepts: vec![accept(1, hash, 1, 0, 1)], + } + ) + } + + #[tokio::test] + async fn first_proposal_multi_peer() { + let mut solid = solid(2); + + let manifest = Manifest::new( + ManifestContent { + last_proposal_hash: solid.hash(), + height: 1, + skips: 0, + leader_id: peer(4), + state: 0.into(), + validators: vec![peer(1), peer(2), peer(3)], + accepts: vec![ + accept(4, solid.hash(), 0, 0, 1), + accept(4, solid.hash(), 0, 0, 2), + accept(4, solid.hash(), 0, 0, 3), + ], + }, + vec![], + ); + let hash = hash(&manifest); + + solid.receive_proposal(manifest.clone()).unwrap(); + + let next = solid.next().await.unwrap(); + + assert_eq!( + next, + SolidEvent::Accept { + accept: ProposalAccept { + proposal: ProposalHeader { + hash, + height: 1, + skips: 0 + }, + leader_id: peer(1), + skips: 0, + from: peer(2), + signature: vec![] + } + } + ) + } + + #[tokio::test] + async fn test_tick_no_action() { + let solid = solid(1); + + assert_eq!(solid.shared.tick(), None); + } + + /// round down to nearest millisecond + fn round_millis(time: DateTime) -> DateTime { + let nanos_and_micros = time.nanosecond() % 1_000_000; + let total_nanos = time.nanosecond() - nanos_and_micros; + time.with_nanosecond(total_nanos).unwrap() + } + + #[test] + fn round_millis_works() { + let time = Utc + .with_ymd_and_hms(2023, 1, 1, 1, 1, 1) + .unwrap() + .with_nanosecond(123_000_123) + .unwrap(); + + let expected = Utc + .with_ymd_and_hms(2023, 1, 1, 1, 1, 1) + .unwrap() + .with_nanosecond(123_000_000) + .unwrap(); + + assert_eq!(round_millis(time), expected); + } + + #[test] + fn test_tick_send_skip() { + let solid = solid(1); + + let now = Utc::now(); + + // Add an expired skip_timeout instant + solid.shared.skip_timeout.store(Some(now)); + + let next_tick = solid.shared.tick(); + + // Should return the next tick + assert!( + next_tick > Some(now + chrono::Duration::seconds(3)), + "next tick {next_tick:?} should be more than 3 seconds away from now: {now:?}", + ); + + // Should add skip event + assert_eq!(solid.shared.events.lock().len(), 1); + } + + #[test] + fn test_tick_not_ready() { + let solid = solid(1); + + let time = Utc::now() + chrono::Duration::seconds(10); + + // Add time which is not ready + solid.shared.skip_timeout.store(Some(time)); + + // Returns time to wake up tick + assert_eq!(solid.shared.tick().unwrap(), round_millis(time)); + + // No events added + assert_eq!(solid.shared.events.lock().len(), 0); + } +} diff --git a/pkg/solid/src/solid/stream.rs b/pkg/solid/src/solid/stream.rs new file mode 100644 index 0000000..83b7086 --- /dev/null +++ b/pkg/solid/src/solid/stream.rs @@ -0,0 +1,18 @@ +use crate::{App, Solid, event::SolidEvent}; +use std::pin::Pin; +use std::task::{Context, Poll}; +use tokio_stream::Stream; + +impl Stream for Solid { + type Item = SolidEvent; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let mut events = self.shared.events.lock(); + if let Some(event) = events.pop_front() { + return Poll::Ready(Some(event)); + } + let mut state = self.shared.state.lock(); + state.waker = Some(cx.waker().clone()); + Poll::Pending + } +} diff --git a/pkg/solid/src/test/app.rs b/pkg/solid/src/test/app.rs new file mode 100644 index 0000000..c3d5453 --- /dev/null +++ b/pkg/solid/src/test/app.rs @@ -0,0 +1,121 @@ +use crate::{ + AppState, + proposal::{ManifestContent, ProposalHash}, + traits::{App, Peer, PeerSigner}, + util::u256::U256, +}; +use borsh::{BorshDeserialize, BorshSerialize}; +use rand::Rng; +use sha2::{Digest, Sha256}; +use std::borrow::Borrow; +use std::fmt::Display; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TestApp; + +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize, Default)] +pub struct TestAppTxnState(u64); + +impl From for TestAppTxnState { + fn from(v: u64) -> Self { + Self(v) + } +} + +impl AppState for TestAppTxnState {} + +impl App for TestApp { + type State = TestAppTxnState; + type P = UncheckedPeerId; + type PS = InsecurePeerSigner; + + fn hash(manifest: &ManifestContent) -> ProposalHash { + #[allow(clippy::unwrap_used)] + #[allow(clippy::disallowed_methods)] + // we are only serializing, so no format requirements + let bytes = Sha256::digest(borsh::to_vec(&manifest).unwrap()); + ProposalHash::new(bytes.into()) + } +} + +#[derive( + Default, Debug, Clone, PartialEq, Ord, PartialOrd, Eq, Hash, BorshSerialize, BorshDeserialize, +)] +pub struct UncheckedPeerId(pub Vec); + +impl Peer for UncheckedPeerId { + fn verify(&self, _signature: &[u8], _msg: [u8; 32]) -> bool { + true + } + + fn prefix(&self) -> String { + let string = self.to_string(); + if string.len() > 4 { + string[string.len() - 4..].to_string() + } else { + string + } + } + + fn to_bytes(&self) -> Vec { + self.0.clone() + } + + fn genesis() -> Self { + Self(vec![0u8]) + } + + fn to_u256(&self) -> U256 { + U256::from_little_endian(&self.0) + } +} + +impl UncheckedPeerId { + pub fn new(bytes: Vec) -> Self { + Self(bytes) + } + + pub fn random() -> UncheckedPeerId { + let peer_id = rand::thread_rng().r#gen::<[u8; 32]>(); + UncheckedPeerId(peer_id.to_vec()) + } +} + +impl Display for UncheckedPeerId { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", bs58::encode(&self.0).into_string()) + } +} + +impl Borrow<[u8]> for UncheckedPeerId { + fn borrow(&self) -> &[u8] { + &self.0 + } +} + +impl From<&[u8]> for UncheckedPeerId { + fn from(bytes: &[u8]) -> Self { + Self(bytes.to_vec()) + } +} + +#[derive(Debug, Clone)] +pub struct InsecurePeerSigner { + peer: UncheckedPeerId, +} + +impl InsecurePeerSigner { + pub fn new(peer: UncheckedPeerId) -> Self { + Self { peer } + } +} + +impl PeerSigner for InsecurePeerSigner { + fn sign(&self, _proposal: [u8; 32]) -> Vec { + vec![] + } + + fn peer(&self) -> UncheckedPeerId { + self.peer.clone() + } +} diff --git a/pkg/solid/src/test/mod.rs b/pkg/solid/src/test/mod.rs new file mode 100644 index 0000000..ebc4f18 --- /dev/null +++ b/pkg/solid/src/test/mod.rs @@ -0,0 +1,3 @@ +pub mod app; +#[cfg(test)] +pub mod util; diff --git a/pkg/solid/src/test/util.rs b/pkg/solid/src/test/util.rs new file mode 100644 index 0000000..87f80c5 --- /dev/null +++ b/pkg/solid/src/test/util.rs @@ -0,0 +1,218 @@ +// lint-long-file-override allow-max-lines=300 +use super::app::{InsecurePeerSigner, TestApp, TestAppTxnState, UncheckedPeerId as PeerId}; +use crate::proposal::{Manifest, Proposal}; +pub use crate::{ + config::SolidConfig, + event::SolidEvent, + proposal::{ManifestContent, ProposalAccept, ProposalHash, ProposalHeader}, + solid::core::SolidCore, + traits::App, +}; +use std::vec; + +pub fn peer(id: u8) -> PeerId { + PeerId::new(vec![id]) +} + +pub fn leader(id: u8) -> PeerId { + peer(id) +} + +pub fn signer(id: u8) -> InsecurePeerSigner { + InsecurePeerSigner::new(peer(id)) +} + +pub fn create_peers() -> [PeerId; 4] { + [peer(1), peer(2), peer(3), peer(4)] +} + +pub fn skips(skip: u64) -> u64 { + skip +} + +pub fn hash(m: &ManifestContent) -> ProposalHash { + TestApp::hash(m) +} + +pub fn proposal(manifest: Manifest) -> Proposal { + Proposal::new(manifest) +} + +pub fn create_proposal( + height: u64, + skips: u64, + leader: u8, + last_proposal_manifest: &ManifestContent, +) -> Proposal { + Proposal::new(create_manifest( + height, + skips, + leader, + last_proposal_manifest, + )) +} + +pub fn create_manifest( + height: u64, + skips: u64, + leader: u8, + last_proposal_manifest: &ManifestContent, +) -> Manifest { + let last_proposal_hash = &TestApp::hash(last_proposal_manifest); + create_manifest_with_accepts( + height, + skips, + leader, + last_proposal_hash, + vec![ + accept(last_proposal_manifest, 0, peer(leader), peer(1)), + accept(last_proposal_manifest, 0, peer(leader), peer(2)), + accept(last_proposal_manifest, 0, peer(leader), peer(3)), + ], + ) +} + +pub fn create_manifest_with_accepts( + height: u64, + skips: u64, + leader: u8, + last_proposal_hash: &ProposalHash, + accepts: Vec>, +) -> Manifest { + Manifest::new( + ManifestContent { + last_proposal_hash: last_proposal_hash.clone(), + height, + skips, + leader_id: peer(leader), + state: 0.into(), + validators: create_peers().to_vec(), + accepts, + }, + vec![], + ) +} + +pub fn accept( + manifest: &ManifestContent, + skips: u64, + leader_id: PeerId, + from: PeerId, +) -> ProposalAccept { + ProposalAccept { + proposal: ProposalHeader { + hash: TestApp::hash(manifest), + height: manifest.height, + skips: manifest.skips, + }, + leader_id, + skips, + from, + signature: vec![], + } +} + +pub fn accept_event( + proposal: &ManifestContent, + skips: u64, + leader_id: PeerId, + from: PeerId, +) -> Option> { + Some(SolidEvent::Accept { + accept: accept(proposal, skips, leader_id, from), + }) +} + +pub fn commit_event( + manifest: &Manifest, + confirmed_by: &Manifest, +) -> Option> { + Some(SolidEvent::Commit { + manifest: manifest.clone(), + confirmed_by: confirmed_by.clone(), + }) +} + +pub fn out_of_sync_event( + height: u64, + max_seen_height: u64, +) -> Option> { + Some(SolidEvent::OutOfSync { + height, + max_seen_height, + }) +} + +pub fn propose_event( + last_proposal_hash: ProposalHash, + height: u64, + skips: u64, + accepts: Vec>, +) -> Option> { + Some(SolidEvent::Propose { + last_proposal_hash, + height, + skips, + accepts, + }) +} + +pub fn genesis_manifest() -> Manifest { + Manifest::genesis(create_peers().to_vec()) +} + +pub fn core_genesis() -> SolidCore { + core_genesis_with_config(SolidConfig::default()) +} + +pub fn core_genesis_with_config(config: SolidConfig) -> SolidCore { + SolidCore::with_last_confirmed(signer(1), genesis_manifest(), TestApp, config) +} + +pub fn core_with_last_confirmed( + proposal: &Manifest, +) -> SolidCore { + SolidCore::with_last_confirmed(signer(1), proposal.clone(), TestApp, SolidConfig::default()) +} + +pub fn gensis_hash() -> ProposalHash { + TestApp::hash(&Manifest::::genesis( + create_peers().to_vec(), + )) +} + +pub fn manifest_at(height: u64) -> Manifest { + create_manifest( + height, + 0, + 1, + &create_manifest_with_accepts(0, 0, 0, &ProposalHash::genesis(), vec![]), + ) +} + +pub fn last_confirmed(store: &SolidCore) -> Manifest { + store + .proposals() + .last_confirmed_proposal() + .manifest() + .clone() +} + +#[macro_export] +macro_rules! assert_none { + ($expr:expr $(,)?) => ({ + match $expr { + None => (), + ref got => panic!("assertion failed: `None` does not equal `{:?}`", got), + } + }); + ($expr:expr, $($arg:tt)*) => ({ + match $expr { + None => (), + ref got => { + let msg = format!($($arg)*); + panic!("{}: `None` does not equal `{}`", msg, got); + } + } + }); +} diff --git a/pkg/solid/src/traits.rs b/pkg/solid/src/traits.rs new file mode 100644 index 0000000..d58b88b --- /dev/null +++ b/pkg/solid/src/traits.rs @@ -0,0 +1,111 @@ +use crate::proposal::{ManifestContent, ProposalHash, ProposalHeader}; +use crate::util::u256::U256; +use borsh::{BorshDeserialize, BorshSerialize}; +use sha3::{Digest, Keccak256}; +use std::fmt::{Debug, Display}; +use std::hash::Hash; + +pub trait AppState: + Debug + Clone + Default + Send + PartialEq + Eq + BorshSerialize + BorshDeserialize + 'static +{ + fn genesis() -> Self { + Self::default() + } +} + +pub trait App: Clone + Debug + Send + Sync + 'static { + /// The state for a txn + type State: AppState; + + /// An external peer address, some other peer on the network + type P: Peer; + + /// PeerSigner, used by the running node to sign proposals + type PS: PeerSigner; + + /// Validate the proposal structure, this validates that the basic structure of the proposal + /// is valid. It validates whether a proposal COULD be valid. + fn validate_structure(&self, _: &ManifestContent) -> bool { + true + } + + /// Validate the proposal contents, this called when the proposal is next inline to be + /// confirmed. It validates whether a proposal IS valid based on previous state of the app. + fn validate_contents( + &self, + _manifest: &ManifestContent, + _last_confirmed: &ManifestContent, + ) -> bool { + true + } + + /// Hash of the proposal/block + fn hash(manifest: &ManifestContent) -> ProposalHash; +} + +#[derive(Debug, Clone)] +pub struct ProposalAcceptSigData { + proposal: ProposalHeader, + skips: u64, +} + +impl ProposalAcceptSigData { + pub fn new(proposal: ProposalHeader, skips: u64) -> Self { + Self { proposal, skips } + } + + fn hash(&self) -> [u8; 32] { + let mut hasher = Keccak256::new(); + hasher.update(&self.proposal.hash.inner()[..]); + hasher.update(self.skips.to_be_bytes()); + + hasher.finalize().into() + } + + pub fn sign(&self, signer: &impl PeerSigner

) -> Vec { + signer.sign(self.hash()) + } + + pub fn verify(&self, peer: &P, signature: &[u8]) -> bool { + peer.verify(signature, self.hash()) + } +} + +pub trait Peer: + Default + + Debug + + Display + + Clone + + PartialEq + + Ord + + PartialOrd + + Eq + + Hash + + BorshSerialize + + BorshDeserialize + + Send + + Sync + + 'static +{ + fn verify(&self, signature: &[u8], msg: [u8; 32]) -> bool; + + fn prefix(&self) -> String; + + fn to_bytes(&self) -> Vec; + + fn genesis() -> Self { + Self::default() + } + + fn to_u256(&self) -> U256; + + fn distance(&self, other: &U256) -> U256 { + *other ^ self.to_u256() + } +} + +pub trait PeerSigner: Clone + Debug + Send + Sync + 'static { + fn sign(&self, msg: [u8; 32]) -> Vec; + + fn peer(&self) -> P; +} diff --git a/pkg/solid/src/util/mod.rs b/pkg/solid/src/util/mod.rs new file mode 100644 index 0000000..f8b5019 --- /dev/null +++ b/pkg/solid/src/util/mod.rs @@ -0,0 +1,3 @@ +pub mod tick_worker; +pub mod time; +pub mod u256; diff --git a/pkg/solid/src/util/tick_worker.rs b/pkg/solid/src/util/tick_worker.rs new file mode 100644 index 0000000..898dec8 --- /dev/null +++ b/pkg/solid/src/util/tick_worker.rs @@ -0,0 +1,85 @@ +use chrono::{DateTime, Utc}; +use std::marker::PhantomData; +use std::sync::{ + Arc, + atomic::{AtomicBool, Ordering::Relaxed}, +}; +use tokio::sync::Notify; + +pub struct TickWorker { + shared: Arc, + _marker: PhantomData, +} + +pub struct TickWorkerShared { + shutdown: AtomicBool, + background_worker: Notify, +} + +impl Drop for TickWorker { + fn drop(&mut self) { + self.shared.shutdown(); + } +} + +pub trait TickWorkerTick: Send + Sync + 'static { + fn tick(&self) -> Option>; +} + +impl TickWorker { + pub fn new() -> Self { + TickWorker { + shared: Arc::new(TickWorkerShared { + shutdown: AtomicBool::new(false), + background_worker: Notify::new(), + }), + _marker: PhantomData, + } + } + + /// Creates and starts the background worker + pub fn run(&self, ticker: T) -> tokio::task::JoinHandle<()> { + tokio::spawn(background_worker(Arc::clone(&self.shared), ticker)) + } + + /// Manually forces a tick to occur + pub fn tick(&self) { + self.shared.background_worker.notify_one(); + } +} + +impl TickWorkerShared { + pub fn shutdown(&self) { + // Mark as shutdown + self.shutdown.store(true, Relaxed); + + // Notify the worker, so it wakes up and exits immediately + self.background_worker.notify_one(); + } + + pub fn is_shutdown(&self) -> bool { + self.shutdown.load(Relaxed) + } +} + +/// Background worker that calls `tick` whenever its scheduled to run the +/// next task or worken up by the `background_worker` channel. +pub async fn background_worker(worker: Arc, shared: T) { + // If the shutdown flag is set, then the task should exit. + while !worker.is_shutdown() { + // Check timeout + if let Some(when) = shared.tick() { + let time_to_sleep = match (when - Utc::now()).to_std() { + Ok(dur) => dur, + Err(_) => std::time::Duration::from_secs(0), + }; + tokio::select! { + _ = tokio::time::sleep(time_to_sleep) => {} + _ = worker.background_worker.notified() => {} + } + } else { + // No expiry set, so wait to be notified + worker.background_worker.notified().await; + } + } +} diff --git a/pkg/solid/src/util/time.rs b/pkg/solid/src/util/time.rs new file mode 100644 index 0000000..8ef64d5 --- /dev/null +++ b/pkg/solid/src/util/time.rs @@ -0,0 +1,117 @@ +#![allow(clippy::unwrap_used)] +use std::sync::atomic::{AtomicI64, Ordering}; + +use chrono::{DateTime, Duration, Utc}; + +/// A timestamp that can be modified via immutable reference +/// +/// Essentially, an `Atomic>>`, where all operations use sequentially +/// consistent ordering - if this causes perf issues, we can look to be more fine grained, but it's +/// probably good enough for now +#[derive(Debug)] +pub struct AtomicTimestamp { + /// Milliseconds since epoch + /// + /// `i64::MIN` is treated as `None` + inner: AtomicI64, +} + +impl AtomicTimestamp { + /// Create a new [`AtomicTimestamp`] from the given [`SystemTime`] + pub fn new(time: Option>) -> Self { + let inner = AtomicI64::new(Self::encode(time)); + Self { inner } + } + + /// Store a time in this [`AtomicTimestamp`] + pub fn store(&self, time: Option>) { + self.inner.store(Self::encode(time), Ordering::SeqCst); + } + + /// Load the stored time + pub fn load(&self) -> Option> { + let millis = self.inner.load(Ordering::SeqCst); + Self::decode(millis) + } + + /// Add a duration to this timestamp, returning the previous value + /// + /// If the current value is `None`, `None` is returned and the state isn't changed + /// + /// Note: the duration is rounded down to the nearest millisecond before it is added + pub fn fetch_add(&self, duration: Duration) -> Option> { + self.inner + .fetch_update(Ordering::SeqCst, Ordering::SeqCst, |old| match old { + i64::MIN => None, + old => Some(old + duration.num_milliseconds()), + }) + .ok() + .and_then(Self::decode) + } + + fn encode(time: Option>) -> i64 { + match time { + None => i64::MIN, + Some(x) => x.timestamp_millis(), + } + } + + fn decode(millis: i64) -> Option> { + match millis { + i64::MIN => None, + millis => Some(DateTime::from_timestamp_millis(millis).unwrap()), + } + } +} + +#[cfg(test)] +mod tests { + use chrono::{LocalResult, TimeZone}; + use proptest::{prop_assert_eq, prop_assume}; + use test_strategy::proptest; + + use super::*; + + #[proptest] + fn any_sane_time_load_store_round_trip( + #[strategy(1971..=2040)] year: i32, + #[strategy(1u32..=12)] month: u32, + #[strategy(1u32..=31)] day: u32, + #[strategy(0u32..=23)] hour: u32, + #[strategy(0u32..=60)] min: u32, + #[strategy(0u32..=60)] sec: u32, + ) { + let time = Utc.with_ymd_and_hms(year, month, day, hour, min, sec); + let time = match time { + LocalResult::Single(time) => time, + // handle months with fewer than 31 days + LocalResult::None | LocalResult::Ambiguous(..) => { + prop_assume!(false); + panic!(); + } + }; + + let atomic = AtomicTimestamp::new(Some(time)); + + let time_again = atomic.load().unwrap(); + prop_assert_eq!(time, time_again); + + // just in case store behaves differently + atomic.store(Some(time)); + let time_again = atomic.load().unwrap(); + prop_assert_eq!(time, time_again); + } + + #[test] + fn fetch_add_sub_works() { + let time = Utc.with_ymd_and_hms(2023, 1, 1, 5, 4, 3).unwrap(); + + let atomic = AtomicTimestamp::new(Some(time)); + atomic.fetch_add(Duration::seconds(5)); + + assert_eq!( + atomic.load().unwrap(), + Utc.with_ymd_and_hms(2023, 1, 1, 5, 4, 8).unwrap() + ); + } +} diff --git a/pkg/solid/src/util/u256.rs b/pkg/solid/src/util/u256.rs new file mode 100644 index 0000000..9b972d7 --- /dev/null +++ b/pkg/solid/src/util/u256.rs @@ -0,0 +1,9 @@ +#![allow(clippy::assign_op_pattern)] +#![expect(clippy::manual_div_ceil)] + +use uint::*; + +construct_uint! { + /// 256-bit unsigned integer. + pub struct U256(4); +} diff --git a/pkg/test-spy-macros/Cargo.toml b/pkg/test-spy-macros/Cargo.toml new file mode 100644 index 0000000..528b157 --- /dev/null +++ b/pkg/test-spy-macros/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "test-spy-macros" +version = "1.0.0" +edition = "2024" + +[lib] +proc-macro = true + +[dependencies] +quote = { workspace = true } +proc-macro2 = { workspace = true } +syn = { workspace = true, features = ["full", "extra-traits"] } +workspace-hack.workspace = true diff --git a/pkg/test-spy-macros/src/lib.rs b/pkg/test-spy-macros/src/lib.rs new file mode 100644 index 0000000..781b468 --- /dev/null +++ b/pkg/test-spy-macros/src/lib.rs @@ -0,0 +1,28 @@ +use proc_macro::TokenStream; +use syn::parse_macro_input; + +mod mock_generation; +mod param_extraction; +mod spy_fields; +mod trait_impl; +mod type_analysis; + +use mock_generation::{generate_mock_for_impl, generate_mock_for_trait}; + +#[proc_macro_attribute] +pub fn spy_mock(_attr: TokenStream, input: TokenStream) -> TokenStream { + let item = parse_macro_input!(input as syn::Item); + + match item { + syn::Item::Trait(trait_item) => generate_mock_for_trait(trait_item), + syn::Item::Impl(impl_item) if impl_item.trait_.is_some() => { + generate_mock_for_impl(impl_item) + } + _ => { + let error = quote::quote! { + compile_error!("#[spy_mock] can only be applied to traits or trait implementations"); + }; + TokenStream::from(error) + } + } +} diff --git a/pkg/test-spy-macros/src/mock_generation.rs b/pkg/test-spy-macros/src/mock_generation.rs new file mode 100644 index 0000000..777b1fb --- /dev/null +++ b/pkg/test-spy-macros/src/mock_generation.rs @@ -0,0 +1,129 @@ +use proc_macro::TokenStream; +use quote::{format_ident, quote}; +use syn::{ImplItem, ItemImpl, ItemTrait, TraitItem, TraitItemFn, Type}; + +use crate::spy_fields::{generate_spy_fields, generate_spy_initializers}; +use crate::trait_impl::generate_trait_impl_methods; + +pub fn generate_mock_for_trait(trait_item: ItemTrait) -> TokenStream { + let trait_name = &trait_item.ident; + let mock_struct_name = format_ident!("{}Mock", trait_name); + let trait_vis = &trait_item.vis; + + let methods: Vec<_> = trait_item + .items + .iter() + .filter_map(|item| { + if let TraitItem::Fn(method) = item { + Some(method) + } else { + None + } + }) + .collect(); + + let spy_fields = generate_spy_fields(&methods); + let spy_initializers = generate_spy_initializers(&methods); + let trait_impl_methods = generate_trait_impl_methods(&methods); + + let has_async = methods.iter().any(|m| m.sig.asyncness.is_some()); + let async_trait_attr = if has_async { + quote! { #[async_trait::async_trait] } + } else { + quote! {} + }; + + let output = quote! { + #trait_item + + #trait_vis struct #mock_struct_name { + #(#spy_fields)* + } + + impl #mock_struct_name { + pub fn new() -> Self { + Self { + #(#spy_initializers)* + } + } + } + + #async_trait_attr + impl #trait_name for #mock_struct_name { + #(#trait_impl_methods)* + } + }; + + TokenStream::from(output) +} + +pub fn generate_mock_for_impl(mut impl_item: ItemImpl) -> TokenStream { + let self_ty = &impl_item.self_ty; + let mock_struct_name = if let Type::Path(type_path) = &**self_ty { + type_path.path.segments.last().unwrap().ident.clone() + } else { + return TokenStream::from(quote! { + compile_error!("Cannot determine struct name from impl"); + }); + }; + + let trait_path = impl_item + .trait_ + .as_ref() + .map(|(_, path, _)| path) + .unwrap() + .clone(); + + let trait_methods: Vec = impl_item + .items + .iter() + .filter_map(|item| { + if let ImplItem::Fn(method) = item { + Some(TraitItemFn { + attrs: method.attrs.clone(), + sig: method.sig.clone(), + default: None, + semi_token: None, + }) + } else { + None + } + }) + .collect(); + + let methods: Vec<_> = trait_methods.iter().collect(); + let spy_fields = generate_spy_fields(&methods); + let spy_initializers = generate_spy_initializers(&methods); + let trait_impl_methods = generate_trait_impl_methods(&methods); + + // Keep the original impl with #[spy_mock] removed + let attrs_without_spy_mock: Vec<_> = impl_item + .attrs + .iter() + .filter(|attr| !attr.path().is_ident("spy_mock")) + .cloned() + .collect(); + impl_item.attrs = attrs_without_spy_mock; + + let output = quote! { + pub struct #mock_struct_name { + #(#spy_fields)* + } + + impl #mock_struct_name { + pub fn new() -> Self { + Self { + #(#spy_initializers)* + } + } + } + + #impl_item + + impl #trait_path for #mock_struct_name { + #(#trait_impl_methods)* + } + }; + + TokenStream::from(output) +} diff --git a/pkg/test-spy-macros/src/param_extraction.rs b/pkg/test-spy-macros/src/param_extraction.rs new file mode 100644 index 0000000..9ab6c23 --- /dev/null +++ b/pkg/test-spy-macros/src/param_extraction.rs @@ -0,0 +1,101 @@ +use quote::quote; +use syn::{FnArg, Pat, ReturnType, TraitItemFn, Type}; + +pub fn extract_params_type(method: &TraitItemFn) -> proc_macro2::TokenStream { + let params: Vec<_> = method + .sig + .inputs + .iter() + .filter_map(|arg| { + if let FnArg::Typed(pat_type) = arg { + let ty = &pat_type.ty; + // Handle references and mutable references + let cleaned_ty = if let Type::Reference(type_ref) = &**ty { + let elem = &type_ref.elem; + // Check if it's a slice type like &str or &[T] + if let Type::Path(path) = &**elem { + if path.path.is_ident("str") { + // Convert &str to String for storage + quote! { String } + } else { + // For other reference types, store as owned + quote! { #elem } + } + } else if let Type::Slice(slice_type) = &**elem { + // Convert &[T] to Vec + let inner = &slice_type.elem; + quote! { Vec<#inner> } + } else { + quote! { #elem } + } + } else { + quote! { #ty } + }; + Some(cleaned_ty) + } else { + None + } + }) + .collect(); + + match params.len() { + 0 => quote! { () }, + 1 => params[0].clone(), + _ => quote! { (#(#params),*) }, + } +} + +pub fn extract_params_for_call(method: &TraitItemFn) -> proc_macro2::TokenStream { + let params: Vec<_> = method + .sig + .inputs + .iter() + .filter_map(|arg| { + if let FnArg::Typed(pat_type) = arg { + if let Pat::Ident(pat_ident) = &*pat_type.pat { + let name = &pat_ident.ident; + let ty = &pat_type.ty; + // Handle references by cloning/converting to owned + let param_value = if let Type::Reference(type_ref) = &**ty { + let elem = &type_ref.elem; + // Check if it's a slice type like &str or &[T] + if let Type::Path(path) = &**elem { + if path.path.is_ident("str") { + // Convert &str to String + quote! { #name.to_string() } + } else { + // For other reference types, clone + quote! { #name.clone() } + } + } else if let Type::Slice(_) = &**elem { + // Convert &[T] to Vec + quote! { #name.to_vec() } + } else { + quote! { #name.clone() } + } + } else { + quote! { #name } + }; + Some(param_value) + } else { + None + } + } else { + None + } + }) + .collect(); + + match params.len() { + 0 => quote! { () }, + 1 => params[0].clone(), + _ => quote! { (#(#params),*) }, + } +} + +pub fn extract_return_type(output: &ReturnType) -> proc_macro2::TokenStream { + match output { + ReturnType::Default => quote! { () }, + ReturnType::Type(_, ty) => quote! { #ty }, + } +} diff --git a/pkg/test-spy-macros/src/spy_fields.rs b/pkg/test-spy-macros/src/spy_fields.rs new file mode 100644 index 0000000..9add46c --- /dev/null +++ b/pkg/test-spy-macros/src/spy_fields.rs @@ -0,0 +1,50 @@ +use quote::quote; +use syn::TraitItemFn; + +use crate::param_extraction::{extract_params_type, extract_return_type}; +use crate::type_analysis::create_default_value_from_return_type; + +pub fn generate_spy_fields(methods: &[&TraitItemFn]) -> Vec { + methods + .iter() + .map(|method| { + let method_name = &method.sig.ident; + let params_type = extract_params_type(method); + let return_type = extract_return_type(&method.sig.output); + let is_async = method.sig.asyncness.is_some(); + + let spy_type = if is_async { + quote! { test_spy::AsyncSpy<#params_type, #return_type> } + } else { + quote! { test_spy::Spy<#params_type, #return_type> } + }; + + quote! { + pub #method_name: #spy_type, + } + }) + .collect() +} + +pub fn generate_spy_initializers(methods: &[&TraitItemFn]) -> Vec { + methods + .iter() + .map(|method| { + let method_name = &method.sig.ident; + let is_async = method.sig.asyncness.is_some(); + + // Create a default value that handles Result types + let default_value = create_default_value_from_return_type(&method.sig.output); + + let spy_constructor = if is_async { + quote! { test_spy::AsyncSpy::new(|_| #default_value) } + } else { + quote! { test_spy::Spy::new(|_| #default_value) } + }; + + quote! { + #method_name: #spy_constructor, + } + }) + .collect() +} diff --git a/pkg/test-spy-macros/src/trait_impl.rs b/pkg/test-spy-macros/src/trait_impl.rs new file mode 100644 index 0000000..8878166 --- /dev/null +++ b/pkg/test-spy-macros/src/trait_impl.rs @@ -0,0 +1,28 @@ +use quote::quote; +use syn::TraitItemFn; + +use crate::param_extraction::extract_params_for_call; + +pub fn generate_trait_impl_methods(methods: &[&TraitItemFn]) -> Vec { + methods + .iter() + .map(|method| { + let sig = &method.sig; + let method_name = &sig.ident; + let is_async = sig.asyncness.is_some(); + let params = extract_params_for_call(method); + + let register_call = if is_async { + quote! { self.#method_name.register_call(#params).await } + } else { + quote! { self.#method_name.register_call(#params) } + }; + + quote! { + #sig { + #register_call + } + } + }) + .collect() +} diff --git a/pkg/test-spy-macros/src/type_analysis.rs b/pkg/test-spy-macros/src/type_analysis.rs new file mode 100644 index 0000000..73cdd9c --- /dev/null +++ b/pkg/test-spy-macros/src/type_analysis.rs @@ -0,0 +1,72 @@ +use quote::quote; +use syn::{GenericArgument, PathArguments, ReturnType, Type}; + +pub fn create_default_value_from_return_type(return_type: &ReturnType) -> proc_macro2::TokenStream { + match return_type { + ReturnType::Default => quote! { () }, + ReturnType::Type(_, ty) => create_default_value_from_type(ty), + } +} + +pub fn create_default_value_from_type(ty: &Type) -> proc_macro2::TokenStream { + if is_result_type(ty) { + // For Result types, return Ok with the inner type's default + quote! { Ok(Default::default()) } + } else if is_arc_dyn_type(ty) { + // For Arc (or similar), default can't be derived; force tests to set via return_next + quote! { panic!("test-spy: default not set for this return type; use return_next() in your test") } + } else { + // For non-Result types, use the Default trait + quote! { <#ty>::default() } + } +} + +pub fn is_result_type(ty: &Type) -> bool { + match ty { + Type::Path(type_path) => { + // Check if the last segment of the path is "Result" + if let Some(last_segment) = type_path.path.segments.last() + && last_segment.ident == "Result" + { + return true; + } + + // Check for fully qualified Result types like std::result::Result + for segment in &type_path.path.segments { + if segment.ident == "Result" { + // Check if this appears to be std::result::Result or similar + let path_str = type_path + .path + .segments + .iter() + .map(|s| s.ident.to_string()) + .collect::>() + .join("::"); + if path_str.contains("result::Result") || path_str.contains("std::Result") { + return true; + } + } + } + + false + } + // Handle other type variants if needed + _ => false, + } +} + +fn is_arc_dyn_type(ty: &Type) -> bool { + match ty { + Type::Path(type_path) => { + if let Some(last) = type_path.path.segments.last() + && last.ident == "Arc" + && let PathArguments::AngleBracketed(ref ab) = last.arguments + && let Some(GenericArgument::Type(inner_ty)) = ab.args.first() + { + return matches!(inner_ty, Type::TraitObject(_)); + } + false + } + _ => false, + } +} diff --git a/pkg/test-spy/Cargo.toml b/pkg/test-spy/Cargo.toml new file mode 100644 index 0000000..7118b29 --- /dev/null +++ b/pkg/test-spy/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "test-spy" +version = "1.0.0" +edition = "2024" + +[lib] + +[dependencies] +test-spy-macros = { workspace = true } +parking_lot = { workspace = true } +serde = { workspace = true, features = ["derive"] } +workspace-hack.workspace = true + +[dev-dependencies] +async-trait = { workspace = true } +tokio = { workspace = true, features = ["rt", "macros"] } diff --git a/pkg/test-spy/README.md b/pkg/test-spy/README.md new file mode 100644 index 0000000..e78e99c --- /dev/null +++ b/pkg/test-spy/README.md @@ -0,0 +1,128 @@ +# test-spy + +A testing utility crate that provides spy-based mock implementations for Rust traits. + +## Features + +- **Spy Types**: `Spy` and `AsyncSpy` for tracking function calls and controlling return values +- **Procedural Macro**: `#[spy_mock]` attribute macro for auto-generating mock implementations +- **Call Tracking**: Record all function calls with their parameters +- **Return Value Control**: Queue specific return values or use default functions + +## Usage + +### Manual Mock Creation + +```rust +use test_spy::{AsyncSpy, Spy}; +use uuid::Uuid; + +pub struct ServiceMock { + pub sync_method: Spy>, + pub async_method: AsyncSpy>, +} + +impl ServiceMock { + pub fn new() -> Self { + Self { + sync_method: Spy::new(|_| Ok(42)), + async_method: AsyncSpy::new(|_| Ok("default".to_string())), + } + } +} +``` + +### Using the Macro + +The `#[spy_mock]` macro can auto-generate mock implementations for traits: + +```rust +use test_spy::spy_mock; + +#[spy_mock] +trait SimpleService { + fn get_value(&self, id: u32) -> String; + fn set_value(&self, id: u32, value: String) -> bool; +} + +// Generates SimpleServiceMock with spy fields +``` + +For async traits: + +```rust +use test_spy::spy_mock; + +#[spy_mock] +#[async_trait::async_trait] +trait AsyncService { + async fn fetch(&self, url: &str) -> Result; + async fn process(&self) -> u64; +} + +// Generates AsyncServiceMock with AsyncSpy fields +``` + +## Working with Spies + +### Recording Calls + +```rust +let mock = ServiceMock::new(); +mock.sync_method.register_call("test".to_string()); + +// Check recorded calls +let calls = mock.sync_method.calls(); +assert_eq!(calls.len(), 1); +assert_eq!(calls[0].params, "test".to_string()); +``` + +### Controlling Return Values + +```rust +// Queue a specific return value +mock.sync_method.return_next(Ok(100)); + +// Next call will return the queued value +let result = mock.sync_method.register_call("input".to_string()); +assert_eq!(result, Ok(100)); + +// Subsequent calls use the default function +let result = mock.sync_method.register_call("input2".to_string()); +assert_eq!(result, Ok(42)); // default +``` + +### Resetting State + +```rust +// Clear all recorded calls and queued returns +mock.sync_method.reset(); +``` + +## Type Conversions + +The macro automatically handles common type conversions: +- `&str` parameters are stored as `String` +- `&[T]` parameters are stored as `Vec` +- References are cloned for storage + +## Return Type Defaults + +- For `Result` types, the default is `Ok(T::default())` +- For other types, `Default::default()` is used +- Custom defaults can be provided when creating spies manually + +## Migration from testutil + +If migrating from `testutil::spy`: +1. Replace `use testutil::spy::{Spy, AsyncSpy}` with `use test_spy::{Spy, AsyncSpy}` +2. For async trait methods, ensure AsyncSpy is used and `.await` is called on `register_call()` +3. The API remains otherwise identical + +## Limitations + +- The `#[spy_mock]` macro requires all parameter types to implement `Clone` +- Return types must implement `Default` for automatic mock generation +- The macro works on trait definitions, not existing trait implementations from external crates + +For existing traits you don't own, create mocks manually using the `Spy` and `AsyncSpy` types directly. \ No newline at end of file diff --git a/pkg/test-spy/src/lib.rs b/pkg/test-spy/src/lib.rs new file mode 100644 index 0000000..ecf8573 --- /dev/null +++ b/pkg/test-spy/src/lib.rs @@ -0,0 +1,4 @@ +pub mod spy; + +pub use spy::{AsyncSpy, Spy, SpyCall}; +pub use test_spy_macros::spy_mock; diff --git a/pkg/test-spy/src/spy.rs b/pkg/test-spy/src/spy.rs new file mode 100644 index 0000000..7187f81 --- /dev/null +++ b/pkg/test-spy/src/spy.rs @@ -0,0 +1,137 @@ +use parking_lot::Mutex; +use serde::{Deserialize, Serialize}; +use std::{collections::VecDeque, future::Future, marker::PhantomData, pin::Pin, sync::Arc}; + +pub struct AsyncSpy< + P: Clone + Send + Sync + 'static, + R: Send + Sync + 'static, + F = fn(&P) -> R, + AF = fn(&P) -> Pin + Send>>, +> { + calls: Arc>>>, + return_next: Arc>>, + default_return: Arc, + _phantom_data: PhantomData, +} + +impl AsyncSpy +where + P: Clone + Send + Sync + 'static, + R: Send + Sync + 'static, + F: Fn(&P) -> R + Send + Sync + 'static, + AF: Fn(&P) -> Pin + Send>> + Send + Sync + 'static, +{ + /// Creates a new spy + pub fn new(default_return: F) -> Self { + Self { + calls: Arc::new(Mutex::new(vec![])), + return_next: Arc::new(Mutex::new(VecDeque::new())), + default_return: Arc::new(default_return), + _phantom_data: PhantomData, + } + } + + pub fn return_next(&self, fn_to_call: AF) { + self.return_next.lock().push_back(fn_to_call); + } + + pub async fn register_call(&self, params: P) -> R { + let cloned_params = params.clone(); + let return_fn = self.return_next.lock().pop_front(); + + let return_value = match return_fn { + Some(v) => v(&cloned_params).await, + None => { + let default_fn = Arc::clone(&self.default_return); + default_fn(&cloned_params) + } + }; + + self.calls.lock().push(SpyCall::new(params)); + + return_value + } + + /// Resets the spy + pub fn reset(&self) { + self.calls.lock().clear(); + self.return_next.lock().clear(); + } + + /// Gets all calls to the spied fn so values can be asserted + pub fn calls(&self) -> Vec> { + self.calls.lock().clone() + } +} + +pub struct Spy R> { + calls: Arc>>>, + return_next: Arc>>, + default_return: Arc>, +} + +impl Spy +where + F: Fn(&P) -> R + Send + Sync + 'static, +{ + /// Creates a new spy + pub fn new(default_return: F) -> Self { + Self { + calls: Arc::new(Mutex::new(vec![])), + return_next: Arc::new(Mutex::new(VecDeque::new())), + default_return: Arc::new(Mutex::new(default_return)), + } + } + + /// Registers a call for the spy and returns the relevant return value + pub fn register_call(&self, params: P) -> R { + let return_value = match self.return_next.lock().pop_front() { + Some(v) => v, + None => { + let default_fn = &*self.default_return.lock(); + default_fn(¶ms) + } + }; + + self.calls.lock().push(SpyCall::new(params)); + + return_value + } + + pub fn register_call_return_next(&self, params: P) -> Option { + self.calls.lock().push(SpyCall::new(params)); + self.return_next.lock().pop_front() + } + + /// Updates the default return value for the spy + pub fn return_default(&self, new_default: F) { + *self.default_return.lock() = new_default; + } + + /// Adds a return value to be returned from the mock next + pub fn return_next(&self, value: R) { + self.return_next.lock().push_back(value); + } + + /// Resets the spy + pub fn reset(&self) { + self.calls.lock().clear(); + self.return_next.lock().clear(); + } + + /// Gets all calls to the spied fn so values can be asserted + pub fn calls(&self) -> Vec> { + self.calls.lock().clone() + } +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct SpyCall { + pub params: P, +} + +impl SpyCall

{ + pub fn new(params: P) -> Self { + Self { params } + } +} diff --git a/pkg/test-spy/tests/async_return_next_test.rs b/pkg/test-spy/tests/async_return_next_test.rs new file mode 100644 index 0000000..c29a619 --- /dev/null +++ b/pkg/test-spy/tests/async_return_next_test.rs @@ -0,0 +1,63 @@ +use test_spy::spy_mock; + +#[derive(Debug, PartialEq)] +pub struct FetchError { + message: String, +} + +impl FetchError { + pub fn new(message: &str) -> Self { + Self { + message: message.to_string(), + } + } +} + +#[spy_mock] +#[async_trait::async_trait] +trait RemoteClient { + async fn fetch(&self, url: String) -> Result; + async fn publish(&self, body: String); +} + +#[tokio::test] +async fn test_async_return_next() { + let mock = RemoteClientMock::new(); + + // Test return_next with a closure that returns a pinned future + mock.fetch.return_next(|url| { + let url = url.clone(); // Clone the parameter to avoid lifetime issues + Box::pin(async move { Ok(format!("{{\"url\":\"{url}\"}}")) }) + }); + + let response = mock.fetch("https://api".to_string()).await; + assert!(response.unwrap().contains("https://api")); + + // Verify calls were recorded + assert_eq!(mock.fetch.calls().len(), 1); + assert_eq!(mock.publish.calls().len(), 0); + + // Test multiple return_next calls + mock.fetch + .return_next(|_url| Box::pin(async move { Err(FetchError::new("network error")) })); + + let error_response = mock.fetch("https://api2".to_string()).await; + assert!(error_response.is_err()); + + assert_eq!(mock.fetch.calls().len(), 2); +} + +#[tokio::test] +async fn test_async_default_behavior() { + let mock = RemoteClientMock::new(); + + // Test default behavior (should return Ok(String::default()) for Result) + let response = mock.fetch("https://default".to_string()).await; + assert_eq!(response, Ok(String::default())); + + // Test publish default (should return ()) + mock.publish("test".to_string()).await; + + assert_eq!(mock.fetch.calls().len(), 1); + assert_eq!(mock.publish.calls().len(), 1); +} diff --git a/pkg/test-spy/tests/macro_tests.rs b/pkg/test-spy/tests/macro_tests.rs new file mode 100644 index 0000000..7aa1cc0 --- /dev/null +++ b/pkg/test-spy/tests/macro_tests.rs @@ -0,0 +1,121 @@ +#![allow(dead_code)] + +use test_spy::spy_mock; + +// Test simple sync trait +#[spy_mock] +trait SimpleService { + fn get_value(&self, id: u32) -> String; + fn set_value(&self, id: u32, value: String) -> bool; +} + +#[test] +fn test_simple_sync_trait() { + let mock = SimpleServiceMock::new(); + + // Test default return + let result = mock.get_value(42); + assert_eq!(result, String::default()); + + // Verify call was recorded + let calls = mock.get_value.calls(); + assert_eq!(calls.len(), 1); + assert_eq!(calls[0].params, 42); + + // Test return_next + mock.get_value.return_next("custom".to_string()); + let result = mock.get_value(100); + assert_eq!(result, "custom"); + + // Verify both calls recorded + let calls = mock.get_value.calls(); + assert_eq!(calls.len(), 2); + assert_eq!(calls[1].params, 100); +} + +// Test async trait +#[spy_mock] +#[async_trait::async_trait] +trait AsyncService { + async fn fetch_data(&self, url: &str) -> Result; + async fn process(&self) -> u64; +} + +#[tokio::test] +async fn test_async_trait() { + let mock = AsyncServiceMock::new(); + + // Test default return + let result = mock.fetch_data("https://example.com").await; + assert_eq!(result, Ok(String::default())); + + // Verify call was recorded + let calls = mock.fetch_data.calls(); + assert_eq!(calls.len(), 1); + assert_eq!(calls[0].params, "https://example.com".to_string()); + + // Test process method + let result = mock.process().await; + assert_eq!(result, 0); +} + +// Test trait with multiple parameters +#[spy_mock] +trait ComplexService { + fn calculate(&self, a: i32, b: i32, c: f64) -> f64; +} + +#[test] +fn test_multiple_params() { + let mock = ComplexServiceMock::new(); + + let result = mock.calculate(10, 20, 3.5); + assert_eq!(result, f64::default()); + + let calls = mock.calculate.calls(); + assert_eq!(calls.len(), 1); + assert_eq!(calls[0].params, (10, 20, 3.5)); +} + +// Test trait with no parameters +#[spy_mock] +trait NoParamsService { + fn get_constant(&self) -> i32; +} + +#[test] +fn test_no_params() { + let mock = NoParamsServiceMock::new(); + + let result = mock.get_constant(); + assert_eq!(result, i32::default()); + + let calls = mock.get_constant.calls(); + assert_eq!(calls.len(), 1); + // params is () for no-args functions +} + +// Test mixed sync and async methods +#[spy_mock] +#[async_trait::async_trait] +trait MixedService { + fn sync_method(&self, value: String) -> bool; + async fn async_method(&self, value: String) -> bool; +} + +#[tokio::test] +async fn test_mixed_methods() { + let mock = MixedServiceMock::new(); + + // Test sync method + let result = mock.sync_method("test".to_string()); + assert_eq!(result, bool::default()); + + // Test async method + let result = mock.async_method("test".to_string()).await; + assert_eq!(result, bool::default()); + + // Verify both methods tracked their calls + assert_eq!(mock.sync_method.calls().len(), 1); + assert_eq!(mock.async_method.calls().len(), 1); +} diff --git a/pkg/testutil/Cargo.toml b/pkg/testutil/Cargo.toml index 0311fad..63082cc 100644 --- a/pkg/testutil/Cargo.toml +++ b/pkg/testutil/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "testutil" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] once_cell = { workspace = true } reqwest = { workspace = true } tokio = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/testutil/README.md b/pkg/testutil/README.md new file mode 100644 index 0000000..a058848 --- /dev/null +++ b/pkg/testutil/README.md @@ -0,0 +1,15 @@ +# Test Utilities + +Testing utilities including Ethereum test helpers and waiting functions. + +## Overview + +This package provides common testing utilities and helpers used across the test suites. + +## Features + +- Ethereum testing utilities +- Spy/mock functionality +- Wait-for utilities +- Test helpers + diff --git a/pkg/testutil/src/eth.rs b/pkg/testutil/src/eth.rs index 6914906..1924e74 100644 --- a/pkg/testutil/src/eth.rs +++ b/pkg/testutil/src/eth.rs @@ -1,3 +1,4 @@ +// lint-long-file-override allow-max-lines=300 use std::{ path::PathBuf, process::Command, @@ -104,7 +105,7 @@ impl EthNode { match reqwest::Client::new().execute(req).await { Ok(res) if res.status().is_success() => return Ok(()), Ok(res) if is_last_retry => { - return Err(format!("Failed to get health: {}", res.status()).into()) + return Err(format!("Failed to get health: {}", res.status()).into()); } Ok(_) => {} Err(err) if is_last_retry => return Err(err.into()), diff --git a/pkg/testutil/src/lib.rs b/pkg/testutil/src/lib.rs index 998cf85..a24026f 100644 --- a/pkg/testutil/src/lib.rs +++ b/pkg/testutil/src/lib.rs @@ -1,6 +1,8 @@ pub mod eth; +mod wait_for; use std::collections::HashSet; +pub use wait_for::wait_for; pub const ACCOUNT_1_SK: &str = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; diff --git a/pkg/testutil/src/wait_for.rs b/pkg/testutil/src/wait_for.rs new file mode 100644 index 0000000..6715f1b --- /dev/null +++ b/pkg/testutil/src/wait_for.rs @@ -0,0 +1,45 @@ +use std::time::{Duration, Instant}; +use tokio::time::sleep; + +/// Polls the given function until it returns true or the timeout is reached. +/// +/// # Arguments +/// +/// * `f` - The function to poll. Should return true when the condition is met. +/// * `timeout` - The maximum duration to wait for the condition to be met. +pub async fn wait_for(f: F, timeout: Duration) +where + F: FnMut() -> bool, +{ + wait_for_poll_interval(f, timeout, None).await +} + +/// Polls the given future-producing function until it returns true or the timeout is reached. +/// +/// # Arguments +/// +/// * `f` - The function to poll. Should return a Future that resolves to true when the condition is met. +/// * `timeout` - The maximum duration to wait for the condition to be met. +/// * `poll_frequency` - Optional polling frequency. If None, will poll as fast as possible. +pub async fn wait_for_poll_interval( + mut f: F, + timeout: Duration, + poll_frequency: Option, +) where + F: FnMut() -> bool, +{ + let start = Instant::now(); + let poll_delay = poll_frequency.unwrap_or(Duration::from_millis(0)); + + loop { + if f() { + return; + } + + if start.elapsed() >= timeout { + panic!("Timed out after waiting for {timeout:?}"); + } + + sleep(poll_delay).await; + } +} diff --git a/pkg/wallet-data-dep/Cargo.toml b/pkg/wallet-data-dep/Cargo.toml new file mode 100644 index 0000000..17f4a91 --- /dev/null +++ b/pkg/wallet-data-dep/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "wallet-data-dep" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } +indexmap = { workspace = true } +hash-poseidon = { workspace = true } +wallet-primitives = { workspace = true } +zk-primitives = { workspace = true } + +ethereum-types = { workspace = true } +chrono = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +uuid = { workspace = true } +workspace-hack.workspace = true + +[dev-dependencies] +insta = { workspace = true, features = ["yaml", "redactions"] } + +[dependencies.ts-rs] +workspace = true +optional = true + +[features] +ts-rs = ["dep:ts-rs", "element/ts-rs", "zk-primitives/ts-rs"] diff --git a/pkg/wallet-data-dep/README.md b/pkg/wallet-data-dep/README.md new file mode 100644 index 0000000..5eba913 --- /dev/null +++ b/pkg/wallet-data-dep/README.md @@ -0,0 +1,16 @@ +# Wallet Data Dep + +Data structures for wallet activities and transaction types. + +## Overview + +This package provides data structures and types used for wallet activities and transaction processing. + +## Features + +- Activity data structures +- Transaction type definitions +- Note management +- Wallet state representation +- Test fixtures and utilities + diff --git a/pkg/wallet-data-dep/src/activity.rs b/pkg/wallet-data-dep/src/activity.rs new file mode 100644 index 0000000..61795fd --- /dev/null +++ b/pkg/wallet-data-dep/src/activity.rs @@ -0,0 +1,79 @@ +use chrono::serde::ts_milliseconds; +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +use crate::util::deserialize_null_default; +use crate::{ + WalletActivityBurnBridgeStage, WalletActivityBurnStage, WalletActivityBuyNftStage, + WalletActivityClaim, WalletActivityMergeStage, WalletActivityMintStage, + WalletActivityRampStage, WalletActivityReceiveStage, WalletActivitySendNoteStage, + WalletActivitySendStage, WalletActivitySupportStage, WalletActivitySwapStage, + WalletActivityTxnStage, +}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityBase { + #[serde(skip_serializing_if = "Option::is_none")] + pub parent_id: Option, + #[serde(default, deserialize_with = "deserialize_null_default")] + pub result: WalletActivityResultStatus, + #[serde(with = "ts_milliseconds")] + pub timestamp: DateTime, + pub user_cancel: bool, + pub error: Option, + #[serde(default)] + pub error_cycles: u32, + #[serde(default)] + pub attempts: u32, + #[serde(default, deserialize_with = "deserialize_null_default")] + pub ok_cycles: u32, +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum WalletActivityResultStatus { + #[default] + Pending, + Success, + Error, + Declined, + Cancelled, + Onhold, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct WalletActivity { + #[serde(flatten)] + pub base: WalletActivityBase, + #[serde(flatten)] + pub kind: WalletActivityKind, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "kind", rename_all = "kebab-case")] +pub enum WalletActivityKind { + Merge(WalletActivityMergeStage), + BuyNft(WalletActivityBuyNftStage), + Mint(WalletActivityMintStage), + Receive(WalletActivityReceiveStage), + Send(WalletActivitySendStage), + Claim(WalletActivityClaim), + SendNote(WalletActivitySendNoteStage), + Txn(WalletActivityTxnStage), + Swap(WalletActivitySwapStage), + Burn(WalletActivityBurnStage), + BurnBridge(WalletActivityBurnBridgeStage), + Ramp(Box), + Support(WalletActivitySupportStage), +} + +impl WalletActivityKind { + pub fn id(&self) -> Option { + match self { + WalletActivityKind::Ramp(ramp) => ramp.id(), + _ => None, + } + } +} diff --git a/pkg/wallet-data-dep/src/common.rs b/pkg/wallet-data-dep/src/common.rs new file mode 100644 index 0000000..3eb9105 --- /dev/null +++ b/pkg/wallet-data-dep/src/common.rs @@ -0,0 +1,45 @@ +use crate::util::deserialize_optional_element; +use element::Element; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct PayyData { + pub height: u64, + #[serde(default, deserialize_with = "deserialize_optional_element")] + pub root: Option, + #[serde(default, deserialize_with = "deserialize_optional_element")] + pub txn: Option, +} + +pub struct PayyDataDefault { + pub height: u64, + pub root: Element, + pub txn: Element, +} + +impl From<&PayyData> for PayyDataDefault { + fn from(data: &PayyData) -> Self { + Self { + height: data.height, + root: data.root.unwrap_or_default(), + txn: data.txn.unwrap_or_default(), + } + } +} + +impl From<&Option> for PayyDataDefault { + fn from(data: &Option) -> Self { + match data { + Some(data) => Self { + height: data.height, + root: data.root.unwrap_or_default(), + txn: data.txn.unwrap_or_default(), + }, + None => Self { + height: 0, + root: Element::default(), + txn: Element::default(), + }, + } + } +} diff --git a/pkg/wallet-data-dep/src/kinds/burn.rs b/pkg/wallet-data-dep/src/kinds/burn.rs new file mode 100644 index 0000000..5bf136d --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/burn.rs @@ -0,0 +1,184 @@ +use element::Element; +use ethereum_types::Address; +use serde::{Deserialize, Serialize}; +use std::str::FromStr; + +use crate::{PayyData, SnarkWitness, StoredNote, activity::WalletActivityBase}; + +// Burn Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct WalletActivityBurn { + #[serde(flatten)] + pub base: WalletActivityBase, + #[serde(flatten)] + pub stage: WalletActivityBurnStage, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivityBurnStage { + Init(BurnInitData), + Merge(BurnMergeCombinedData), + Proof(BurnProofCombinedData), + Ethereum(BurnEthereumCombinedData), + Rollup(BurnRollupCombinedData), + Success(BurnSuccessCombinedData), +} + +impl WalletActivityBurnStage { + pub fn value(&self) -> Element { + match &self { + WalletActivityBurnStage::Init(init) => init.value, + WalletActivityBurnStage::Merge(merge) => merge.init_data.value, + WalletActivityBurnStage::Proof(proof) => proof.init_data.value, + WalletActivityBurnStage::Ethereum(ethereum) => ethereum.init_data.value, + WalletActivityBurnStage::Rollup(rollup) => rollup.init_data.value, + WalletActivityBurnStage::Success(success) => success.init_data.value, + } + } + + pub fn eth_address(&self) -> Address { + let str = match &self { + WalletActivityBurnStage::Init(init) => &init.ethaddress, + WalletActivityBurnStage::Merge(merge) => &merge.init_data.ethaddress, + WalletActivityBurnStage::Proof(proof) => &proof.init_data.ethaddress, + WalletActivityBurnStage::Ethereum(ethereum) => ðereum.init_data.ethaddress, + WalletActivityBurnStage::Rollup(rollup) => &rollup.init_data.ethaddress, + WalletActivityBurnStage::Success(success) => &success.init_data.ethaddress, + }; + *str + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum BurnRouterType { + Router, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnRouterData { + #[serde(rename = "type")] + pub router_type: BurnRouterType, + pub router: String, + pub router_calldata: String, + pub return_address: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnInitData { + #[serde(deserialize_with = "deserialize_address")] + pub ethaddress: Address, + pub value: Element, + pub kind: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub extra_data: Option, +} + +pub fn deserialize_address<'de, D>(deserializer: D) -> Result +where + D: serde::Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + + // Trim off the 0x + // Trim off the 0x prefix if present + let s = if s.starts_with("0x") { + s.trim_start_matches("0x").to_string() + } else { + s + }; + + // Check if the string is a valid hex representation + let s = s.trim_start_matches("0x"); + + // Remove any padding (leading zeros beyond 40 characters) + let s = if s.len() > 40 { &s[s.len() - 40..] } else { s }; + + // Parse as Address + Address::from_str(&format!("0x{s}")).map_err(serde::de::Error::custom) +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnMergeCombinedData { + #[serde(flatten)] + pub init_data: BurnInitData, + #[serde(flatten)] + pub merge_data: BurnMergeData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnMergeData { + pub note: StoredNote, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnProofCombinedData { + #[serde(flatten)] + pub init_data: BurnInitData, + #[serde(flatten)] + pub merge_data: BurnMergeData, + #[serde(flatten)] + pub proof_data: BurnProofData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnProofData { + pub snark: SnarkWitness, + pub proof: String, + pub root: Option, + pub signature: Element, + pub nullifier: Element, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnEthereumCombinedData { + #[serde(flatten)] + pub init_data: BurnInitData, + #[serde(flatten)] + pub merge_data: BurnMergeData, + #[serde(flatten)] + pub proof_data: BurnProofData, + #[serde(flatten)] + pub ethereum_data: BurnEthereumData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnEthereumData { + pub txn: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnRollupCombinedData { + #[serde(flatten)] + pub init_data: BurnInitData, + #[serde(flatten)] + pub merge_data: BurnMergeData, + #[serde(flatten)] + pub proof_data: BurnProofData, + #[serde(flatten)] + pub ethereum_data: BurnEthereumData, + #[serde(flatten)] + pub rollup_data: BurnRollupData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnRollupData { + pub height: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub payy: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnSuccessCombinedData { + #[serde(flatten)] + pub init_data: BurnInitData, + #[serde(flatten)] + pub merge_data: BurnMergeData, + #[serde(flatten)] + pub ethereum_data: BurnEthereumData, + #[serde(flatten)] + pub rollup_data: BurnRollupData, + pub snark: Option<()>, + pub proof: Option<()>, +} diff --git a/pkg/wallet-data-dep/src/kinds/burn_bridge.rs b/pkg/wallet-data-dep/src/kinds/burn_bridge.rs new file mode 100644 index 0000000..9a63d23 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/burn_bridge.rs @@ -0,0 +1,84 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "kebab-case")] +pub enum WalletActivityBurnBridgeStage { + Init(BurnBridgeInitData), + BurnToAddress(BurnBridgeBurnToAddressCombinedData), + Success(BurnBridgeSuccessCombinedData), + Failed(BurnBridgeFailedCombinedData), +} + +impl WalletActivityBurnBridgeStage { + pub fn value(&self) -> Element { + match self { + WalletActivityBurnBridgeStage::Init(data) => data.value, + WalletActivityBurnBridgeStage::BurnToAddress(data) => data.init_data.value, + WalletActivityBurnBridgeStage::Success(data) => data.init_data.value, + WalletActivityBurnBridgeStage::Failed(data) => data.init_data.value, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum BurnBridgeProvider { + Across, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct BurnBridgeInitData { + pub provider: BurnBridgeProvider, + pub chain_id: u64, + pub to: String, + pub output_token: String, + pub value: Element, + pub minimum_output_value: Element, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct BurnBridgeBurnToAddressData { + pub child_burn_id: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnBridgeBurnToAddressCombinedData { + #[serde(flatten)] + pub init_data: BurnBridgeInitData, + #[serde(flatten)] + pub burn_to_address_data: BurnBridgeBurnToAddressData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnBridgeSuccessData { + pub txn: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnBridgeSuccessCombinedData { + #[serde(flatten)] + pub init_data: BurnBridgeInitData, + #[serde(flatten)] + pub success_data: BurnBridgeSuccessData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnBridgeFailedData { + #[serde(skip_serializing_if = "Option::is_none")] + pub burn_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mint_id: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct BurnBridgeFailedCombinedData { + #[serde(flatten)] + pub init_data: BurnBridgeInitData, + #[serde(flatten)] + pub burn_to_address_data: BurnBridgeBurnToAddressData, + #[serde(flatten)] + pub failed_data: BurnBridgeFailedData, +} diff --git a/pkg/wallet-data-dep/src/kinds/buy_nft.rs b/pkg/wallet-data-dep/src/kinds/buy_nft.rs new file mode 100644 index 0000000..02c62a6 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/buy_nft.rs @@ -0,0 +1,46 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +use crate::StoredNote; + +// BuyNft Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "kebab-case")] +pub enum WalletActivityBuyNftStage { + Init(BuyNftInitData), + RequestPayment(Box), +} + +impl WalletActivityBuyNftStage { + pub fn value(&self) -> Element { + match self { + WalletActivityBuyNftStage::Init(d) => d.value, + WalletActivityBuyNftStage::RequestPayment(d) => d.init_data.value, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct BuyNftInitData { + pub payment_id: Option, + pub value: Element, + pub currency: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct BuyNftRequestPaymentCombinedData { + #[serde(flatten)] + pub init_data: BuyNftInitData, + #[serde(flatten)] + pub request_payment_data: BuyNftRequestPaymentData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct BuyNftRequestPaymentData { + pub url: String, + pub private_key: String, + pub note: StoredNote, +} diff --git a/pkg/wallet-data-dep/src/kinds/claim.rs b/pkg/wallet-data-dep/src/kinds/claim.rs new file mode 100644 index 0000000..f17f160 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/claim.rs @@ -0,0 +1,54 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +use crate::StoredNote; + +// Claim Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityClaim { + #[serde(flatten)] + pub stage: WalletActivityClaimStage, + pub error_reason: Option, +} + +impl WalletActivityClaim { + pub fn value(&self) -> Element { + match &self.stage { + WalletActivityClaimStage::Init(data) => data.note.note.value, + WalletActivityClaimStage::Txn(data) => data.note.note.value, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivityClaimStage { + Init(WalletActivityClaimInitData), + Txn(WalletActivityClaimInitData), +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "kebab-case")] +pub enum WalletActivityClaimErrorReason { + NullifierConflict, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityClaimInitData { + pub private_key: Element, + pub note: StoredNote, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option, + pub source: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum WalletActivityClaimSource { + Receive, + Link, + Cancel, + Merge, +} diff --git a/pkg/wallet-data-dep/src/kinds/merge.rs b/pkg/wallet-data-dep/src/kinds/merge.rs new file mode 100644 index 0000000..4bba0e7 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/merge.rs @@ -0,0 +1,19 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +// Merge Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivityMergeStage { + Init(MergeInitData), + Claim(MergeInitData), + Success(MergeInitData), +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct MergeInitData { + pub private_key: Element, + #[serde(skip_serializing_if = "Option::is_none")] + pub value: Option, +} diff --git a/pkg/wallet-data-dep/src/kinds/mint.rs b/pkg/wallet-data-dep/src/kinds/mint.rs new file mode 100644 index 0000000..3f54496 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/mint.rs @@ -0,0 +1,140 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +use crate::{ + PayyData, PayyDataDefault, SnarkWitness, StoredNote, util::deserialize_option_or_none, +}; + +// Mint Activity Types + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivityMintStage { + Deposit(MintInitData), + Init(MintInitData), + Proof(MintProofCombinedData), + Ethereum(MintEthereumCombinedData), + Rollup(MintRollupCombinedData), + Success(MintSuccessCombinedData), +} + +impl WalletActivityMintStage { + pub fn value(&self) -> Element { + match self { + WalletActivityMintStage::Init(init) => init.value, + WalletActivityMintStage::Deposit(deposit) => deposit.value, + WalletActivityMintStage::Proof(proof) => proof.init_data.value, + WalletActivityMintStage::Ethereum(ethereum) => ethereum.init_data.value, + WalletActivityMintStage::Rollup(rollup) => rollup.init_data.value, + WalletActivityMintStage::Success(success) => success.init_data.value, + } + } + + pub fn txn_receipt(&self) -> Option { + match &self { + WalletActivityMintStage::Rollup(rollup) => { + Some(PayyDataDefault::from(&rollup.rollup_data.payy)) + } + WalletActivityMintStage::Success(success) => { + Some(PayyDataDefault::from(&success.rollup_data.payy)) + } + _ => None, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct MintInitData { + pub to: Element, + pub value: Element, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(deserialize_with = "deserialize_option_or_none", default)] + pub provider: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub private_key: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum WalletActivityMintProviderType { + Mayan, + Across, + #[serde(rename = "polygon-usdc")] + PolygonUsdc, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityMintProvider { + pub provider: WalletActivityMintProviderType, + #[serde(skip_serializing_if = "Option::is_none")] + pub txn: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub txn_success: Option, + pub estimated_value: Element, + pub from_chain: String, + pub from_token: String, + pub from_value: u64, + pub eta: i64, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MintProofCombinedData { + #[serde(flatten)] + pub init_data: MintInitData, + #[serde(flatten)] + pub proof_data: MintProofData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MintProofData { + pub note: StoredNote, + pub snark: SnarkWitness, + pub proof: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MintEthereumCombinedData { + #[serde(flatten)] + pub init_data: MintInitData, + #[serde(flatten)] + pub proof_data: MintProofData, + #[serde(flatten)] + pub ethereum_data: MintEthereumData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MintEthereumData { + #[serde(skip_serializing_if = "Option::is_none")] + pub txn: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MintRollupCombinedData { + #[serde(flatten)] + pub init_data: MintInitData, + #[serde(flatten)] + pub ethereum_data: MintEthereumData, + #[serde(flatten)] + pub rollup_data: MintRollupData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MintRollupData { + #[serde(skip_serializing_if = "Option::is_none")] + pub payy: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MintSuccessCombinedData { + #[serde(flatten)] + pub rollup_data: MintRollupData, + #[serde(flatten)] + pub init_data: MintInitData, + #[serde(flatten)] + pub ethereum_data: MintEthereumData, + pub note: StoredNote, + pub snark: Option<()>, + pub proof: Option<()>, +} diff --git a/pkg/wallet-data-dep/src/kinds/mod.rs b/pkg/wallet-data-dep/src/kinds/mod.rs new file mode 100644 index 0000000..25ceee7 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/mod.rs @@ -0,0 +1,27 @@ +mod burn; +mod burn_bridge; +mod buy_nft; +mod claim; +mod merge; +mod mint; +mod ramp; +mod receive; +mod send; +mod send_note; +mod support; +mod swap; +mod txn; + +pub use burn::*; +pub use burn_bridge::*; +pub use buy_nft::*; +pub use claim::*; +pub use merge::*; +pub use mint::*; +pub use ramp::*; +pub use receive::*; +pub use send::*; +pub use send_note::*; +pub use support::*; +pub use swap::*; +pub use txn::*; diff --git a/pkg/wallet-data-dep/src/kinds/ramp.rs b/pkg/wallet-data-dep/src/kinds/ramp.rs new file mode 100644 index 0000000..7565d42 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/ramp.rs @@ -0,0 +1,206 @@ +// lint-long-file-override allow-max-lines=300 +use element::Element; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivityRampStage { + Kyc(WalletActivityRampInitData), + Transaction(WalletActivityRampInitData), + Fund(Box), +} + +impl WalletActivityRampStage { + pub fn id(&self) -> Option { + match self { + WalletActivityRampStage::Fund(fund) => { + Uuid::parse_str(&fund.fund_data.transaction_id).ok() + } + _ => None, + } + } + + pub fn init_data(&self) -> WalletActivityRampInitData { + match self { + WalletActivityRampStage::Kyc(init_data) => init_data.clone(), + WalletActivityRampStage::Transaction(init_data) => init_data.clone(), + WalletActivityRampStage::Fund(fund) => fund.init_data.clone(), + } + } + + pub fn txn_data(&self) -> Option { + self.init_data() + .transaction + .or(self.init_data().transaction2) + } + + pub fn ramp_kind(&self) -> Option { + match self.txn_data().map(|t| (t.from_network, t.to_network))? { + (Network::Card, _) => Some(RampKind::Card), + (_, Network::Card) => Some(RampKind::Card), + (Network::Payy, _) => Some(RampKind::Withdraw), + (_, Network::Payy) => Some(RampKind::Deposit), + _ => None, + } + } + + pub fn balance_movement(&self) -> Option<(Element, bool)> { + let txn = self.txn_data()?; + let is_credit = matches!(txn.to_network, Network::Payy); + let value = match is_credit { + true => txn.from_amount, + false => txn.to_amount, + }; + Some((value, is_credit)) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum Network { + Payy, + Polygon, + Ethereum, + Coelsa, + Card, +} + +pub enum RampKind { + Deposit, + Withdraw, + Card, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum Category { + Bills, + Charity, + EatingOut, + Entertainment, + Expenses, + Family, + Finances, + General, + Gifts, + Groceries, + Holidays, + Income, + PersonalCare, + Savings, + Shopping, + Transfer, + Transport, + PetCare, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct NetworkIdentifier { + #[serde(skip_serializing_if = "Option::is_none")] + pub accountnumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub routingnumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cardnumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cardexpiration: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub cardcvv: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub phonenumber: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub email: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub address: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub methodid: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub reference: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityRampInitData { + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option, + pub account_id: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub quote_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub quote_added_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub quote_expires_at: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub method: Option, + pub category: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub confirmed: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub pending_refund_amount: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub mint_burn_complete: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub transaction: Option, + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub transaction2: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct RampMethod { + #[serde(skip_serializing_if = "Option::is_none")] + pub local_id: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub method_id: Option, + pub network: String, + pub identifier: NetworkIdentifier, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityRampFundCombinedData { + #[serde(flatten)] + pub init_data: WalletActivityRampInitData, + #[serde(flatten)] + pub fund_data: WalletActivityRampFundData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityRampFundData { + #[serde(alias = "rampTransactionId", alias = "transactionId")] + pub transaction_id: String, + pub has_remote_evm_address: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivityRampFundTransactionData { + pub kind: Option, + pub provider: String, + #[serde(alias = "to_amount")] + pub to_amount: Element, + #[serde(alias = "to_network")] + pub to_network: Network, + #[serde(alias = "from_amount")] + pub from_amount: Element, + #[serde(alias = "to_currency")] + pub to_currency: String, + #[serde(alias = "from_network")] + pub from_network: Network, + #[serde(alias = "from_currency")] + pub from_currency: String, + #[serde( + skip_serializing_if = "Option::is_none", + alias = "to_network_identifier" + )] + pub to_network_identifier: Option, + #[serde( + skip_serializing_if = "Option::is_none", + alias = "from_network_identifier" + )] + pub from_network_identifier: Option, +} diff --git a/pkg/wallet-data-dep/src/kinds/receive.rs b/pkg/wallet-data-dep/src/kinds/receive.rs new file mode 100644 index 0000000..b15e693 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/receive.rs @@ -0,0 +1,24 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +use crate::StoredNote; + +// Receive Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivityReceiveStage { + Received(WalletActivityReceiveData), +} + +impl WalletActivityReceiveStage { + pub fn value(&self) -> Element { + match self { + WalletActivityReceiveStage::Received(data) => data.note.note.value, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct WalletActivityReceiveData { + pub note: StoredNote, +} diff --git a/pkg/wallet-data-dep/src/kinds/send.rs b/pkg/wallet-data-dep/src/kinds/send.rs new file mode 100644 index 0000000..ac6aec9 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/send.rs @@ -0,0 +1,100 @@ +use element::Element; +use serde::{Deserialize, Serialize}; +use wallet_primitives::derive_private_key; + +use crate::{PayyData, StoredNote}; + +// Send Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivitySendStage { + Init(SendInitData), + Txn(SendTxnCombinedData), + Failed(SendFailedCombinedData), +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SendInitData { + #[serde(rename = "type")] + pub send_type: Option, + pub to: Element, + pub value: Element, + pub public_key: Element, + #[serde(skip_serializing_if = "Option::is_none")] + pub private_key: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub memo: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub bridge_version: Option, +} + +impl WalletActivitySendStage { + pub fn init_data(&self) -> SendInitData { + match self { + WalletActivitySendStage::Init(init) => init.clone(), + WalletActivitySendStage::Txn(txn) => txn.init_data.clone(), + WalletActivitySendStage::Failed(failed) => failed.init_data.clone(), + } + } + + pub fn note(&self) -> Option { + let private_key = self.init_data().private_key?; + let psi = match &self { + WalletActivitySendStage::Init(_) => None, + WalletActivitySendStage::Txn(txn) => txn.txn_data.note.as_ref().map(|n| n.note.psi), + WalletActivitySendStage::Failed(txn) => txn.txn_data.note.as_ref().map(|n| n.note.psi), + }; + Some(StoredNote::claimable_from_private_key_psi( + self.value(), + private_key, + psi.unwrap_or(derive_private_key(&[], private_key)), + )) + } + + pub fn value(&self) -> Element { + match self { + WalletActivitySendStage::Init(init) => init.value, + WalletActivitySendStage::Txn(txn) => txn.init_data.value, + WalletActivitySendStage::Failed(failed) => failed.init_data.value, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum WalletActivitySendType { + Claimable, + Direct, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SendTxnData { + pub height: u64, + #[serde(skip_serializing_if = "Option::is_none")] + pub note: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub is_spent: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub registry_height: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub payy: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct SendTxnCombinedData { + #[serde(flatten)] + pub init_data: SendInitData, + #[serde(flatten)] + pub txn_data: SendTxnData, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct SendFailedCombinedData { + #[serde(flatten)] + pub init_data: SendInitData, + #[serde(flatten)] + pub txn_data: SendTxnData, + pub error: String, +} diff --git a/pkg/wallet-data-dep/src/kinds/send_note.rs b/pkg/wallet-data-dep/src/kinds/send_note.rs new file mode 100644 index 0000000..f145b3e --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/send_note.rs @@ -0,0 +1,30 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +use crate::StoredNote; + +// SendNote Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivitySendNoteStage { + Init(WalletActivitySendNoteInitData), + Txn(WalletActivitySendNoteInitData), +} + +impl WalletActivitySendNoteStage { + pub fn value(&self) -> Element { + match self { + WalletActivitySendNoteStage::Init(data) => data.note.note.value, + WalletActivitySendNoteStage::Txn(data) => data.note.note.value, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletActivitySendNoteInitData { + pub to: Element, + pub public_key: Element, + pub private_key: Element, + pub note: StoredNote, +} diff --git a/pkg/wallet-data-dep/src/kinds/support.rs b/pkg/wallet-data-dep/src/kinds/support.rs new file mode 100644 index 0000000..213d1a8 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/support.rs @@ -0,0 +1,26 @@ +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +// Support Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivitySupportStage { + Init(SupportInitData), + Success(SupportInitData), +} + +impl WalletActivitySupportStage { + pub fn issue_id(&self) -> Uuid { + match self { + Self::Init(data) => data.issue_id, + Self::Success(data) => data.issue_id, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SupportInitData { + pub issue_id: Uuid, + pub message: String, +} diff --git a/pkg/wallet-data-dep/src/kinds/swap.rs b/pkg/wallet-data-dep/src/kinds/swap.rs new file mode 100644 index 0000000..a3b9e42 --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/swap.rs @@ -0,0 +1,24 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +// Swap Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivitySwapStage { + Init(SwapInitData), + Success(SwapSuccessData), +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SwapInitData { + pub new_primary_key: Element, + pub value: Element, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct SwapSuccessData { + pub new_primary_key: Option<()>, + pub value: Element, +} diff --git a/pkg/wallet-data-dep/src/kinds/txn.rs b/pkg/wallet-data-dep/src/kinds/txn.rs new file mode 100644 index 0000000..8cbf63a --- /dev/null +++ b/pkg/wallet-data-dep/src/kinds/txn.rs @@ -0,0 +1,52 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +use crate::{PayyData, SnarkWitness, StoredNote}; + +// Txn Activity Types +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(tag = "stage", content = "data", rename_all = "lowercase")] +pub enum WalletActivityTxnStage { + Init(WalletTxnInitData), + Success(WalletTxnSuccessData), + Failed(WalletTxnFailedData), +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletTxnInitData { + pub root: Element, + pub inputs: Vec, + pub outputs: Vec, + pub nullifiers: Vec, + pub snark: SnarkWitness, + pub is_self_transfer: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletTxnSuccessData { + pub root: Element, + pub inputs: Vec, + pub outputs: Vec, + pub nullifiers: Vec, + pub is_self_transfer: Option, + #[serde(default)] + pub height: u64, + pub payy: Option, + pub snark: Option<()>, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct WalletTxnFailedData { + pub root: Element, + pub inputs: Vec, + pub outputs: Vec, + pub nullifiers: Vec, + pub is_self_transfer: Option, + pub error: String, + pub snark: Option<()>, + #[serde(skip_serializing_if = "Option::is_none")] + pub invalid_notes: Option>, +} diff --git a/pkg/wallet-data-dep/src/lib.rs b/pkg/wallet-data-dep/src/lib.rs new file mode 100644 index 0000000..c53f0cc --- /dev/null +++ b/pkg/wallet-data-dep/src/lib.rs @@ -0,0 +1,21 @@ +mod activity; +mod common; +mod kinds; +mod note; +mod util; +mod wallet; + +#[cfg(test)] +mod test; + +// use chrono::serde::ts_milliseconds; +// use chrono::{DateTime, Utc}; +// use element::Element; +// use serde::{Deserialize, Serialize}; +// use std::collections::HashMap; + +pub use activity::*; +pub use common::*; +pub use kinds::*; +pub use note::*; +pub use wallet::*; diff --git a/pkg/wallet-data-dep/src/note.rs b/pkg/wallet-data-dep/src/note.rs new file mode 100644 index 0000000..72c987c --- /dev/null +++ b/pkg/wallet-data-dep/src/note.rs @@ -0,0 +1,366 @@ +// lint-long-file-override allow-max-lines=400 +use element::Element; +use hash_poseidon::hash_merge; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; +use wallet_primitives::derive_private_key; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(rename = "WalletDataNote"))] +pub struct Note { + pub address: Element, + pub psi: Element, + pub value: Element, + #[serde(default)] + pub source: Option, + #[serde(default)] + pub token: Option, +} + +impl Note { + pub fn commitment(&self) -> Element { + if self.value == Element::ZERO { + return Element::ZERO; + } + + hash_merge([ + self.value, + self.address, + self.psi, + self.address, + Element::ONE, + Element::ONE, + ]) + } +} + +impl From for zk_primitives::Note { + fn from(note: Note) -> Self { + Self { + kind: Element::new(2), + contract: Element::new(1), + value: note.value, + psi: note.psi, + address: note.address, + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct StoredNote { + pub note: Note, + pub commitment: Element, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(type = "number"), ts(optional))] + pub timestamp: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(type = "number"), ts(optional))] + pub received: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(type = "number"), ts(optional))] + pub spent: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub owner: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(type = "boolean"), ts(optional))] + pub remote: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub private_key: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[cfg_attr(feature = "ts-rs", ts(optional))] + pub invalidreason: Option, +} + +impl StoredNote { + pub fn claimable_from_private_key(value: Element, private_key: Element) -> Self { + let psi = derive_private_key(&[], private_key); + Self::claimable_from_private_key_psi(value, private_key, psi) + } + + pub fn claimable_from_private_key_psi( + value: Element, + private_key: Element, + psi: Element, + ) -> Self { + let note = Note { + value, + address: hash_merge([private_key, Element::ZERO]), + psi, + source: None, + token: None, + }; + StoredNote { + commitment: note.commitment(), + note, + private_key: Some(private_key), + owner: None, + timestamp: None, + received: None, + spent: None, + remote: None, + invalidreason: None, + } + } + + pub fn get_private_key(&self, wallet_private_key: Element) -> Option { + // We have an explicit private key, try to use that + if let Some(pk) = self.private_key { + let addr = hash_merge([pk, Element::ZERO]); + if self.note.address == addr { + return Some(pk); + } + } + + // Next try using a derived private key using the psi + let psi_pk = derive_private_key( + format!("0x{}", self.note.psi.to_hex()).as_bytes(), + wallet_private_key, + ); + let psi_addr = hash_merge([psi_pk, Element::ZERO]); + if self.note.address == psi_addr { + return Some(psi_pk); + } + + // Otherwise check if the raw wallet pk is used + let wallet_addr = hash_merge([wallet_private_key, Element::ZERO]); + if self.note.address == wallet_addr { + return Some(wallet_private_key); + } + + None + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct MerklePath { + pub siblings: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct ClaimableNote { + pub note: StoredNote, + pub secret_key: Element, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct InputNote { + pub note: Note, + pub secret_key: Element, + pub merkle_path: MerklePath, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct SnarkWitness { + #[serde(rename = "V1")] + pub v1: SnarkWitnessV1, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct SnarkWitnessV1 { + pub proof: String, + pub instances: Vec>, +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + use element::Element; + + #[test] + fn test_get_private_key() { + let wallet_private_key = + Element::from_str("0x39c8c2ca6c49019ab3f8670968008e54678d41ebf3254ab5773f2b772a31aa69") + .unwrap(); + let psi = + Element::from_str("0x0b8ffa9a1a747c202f8291bb8c1ec7aceedb010da1ca7fa788ed77d036bc2e5d") + .unwrap(); + let derived_address = + Element::from_str("1603fb25f420f4cfdc81a9962e2bdc6b2da279498f02392329bcb48b6070b8cf") + .unwrap(); + let derived_private_key = + Element::from_str("0x267537a04de9d21de3e6bdb61f0d2d0e0862891ce4e6bcc2c9fd6c7de60b9aa7") + .unwrap(); + + let note = Note { + address: derived_address, + psi, + value: Element::new(100), + source: None, + token: None, + }; + + let stored_note = StoredNote { + note, + commitment: Element::new(0), + timestamp: None, + received: None, + spent: None, + owner: None, + remote: None, + private_key: None, + invalidreason: None, + }; + + let result = stored_note.get_private_key(wallet_private_key); + assert_eq!(result, Some(derived_private_key)); + } + + #[test] + fn test_claimable_from_private_key() { + let private_key = + Element::from_str("0xade2737d8245c6e45e906cdeeb127aa066187e98822f6eed31098bac13d68936") + .unwrap(); + let expected_psi = + Element::from_str("0x82a54bb547a18cdf3036ba399f01bd8f99136d8f05417cf503b4f4e5b6ac265a") + .unwrap(); + let value = Element::new(100); + + let stored_note = StoredNote::claimable_from_private_key(value, private_key); + + assert_eq!(stored_note.note.psi, expected_psi); + assert_eq!(stored_note.note.value, value); + assert_eq!(stored_note.private_key, Some(private_key)); + assert_eq!( + stored_note.note.address, + hash_merge([private_key, Element::ZERO]) + ); + } + + #[test] + fn test_note_deserialize_missing_source_field() { + // Test JSON without source field (old format) + let json_without_source = r#"{ + "address": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "psi": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + "value": "0000000000000000000000000000000000000000000000000000000000000064" + }"#; + + let note: Result = serde_json::from_str(json_without_source); + assert!( + note.is_ok(), + "Failed to deserialize note without source field" + ); + + let note = note.unwrap(); + assert_eq!(note.source, None); + assert_eq!(note.token, None); + } + + #[test] + fn test_note_deserialize_missing_token_field() { + // Test JSON without token field (old format) + let json_without_token = r#"{ + "address": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "psi": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + "value": "0000000000000000000000000000000000000000000000000000000000000064", + "source": "1111111111111111111111111111111111111111111111111111111111111111" + }"#; + + let note: Result = serde_json::from_str(json_without_token); + assert!( + note.is_ok(), + "Failed to deserialize note without token field" + ); + + let note = note.unwrap(); + assert_eq!(note.token, None); + assert!(note.source.is_some()); + } + + #[test] + fn test_note_deserialize_missing_both_fields() { + // Test JSON without both source and token fields (very old format) + let json_without_both = r#"{ + "address": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "psi": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + "value": "0000000000000000000000000000000000000000000000000000000000000064" + }"#; + + let note: Result = serde_json::from_str(json_without_both); + assert!( + note.is_ok(), + "Failed to deserialize note without source and token fields" + ); + + let note = note.unwrap(); + assert_eq!(note.source, None); + assert_eq!(note.token, None); + } + + #[test] + fn test_note_serialize_deserialize_with_all_fields() { + // Test complete note with all fields present + let original_note = Note { + address: Element::from_str( + "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + ) + .unwrap(), + psi: Element::from_str( + "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + ) + .unwrap(), + value: Element::new(100), + source: Some( + Element::from_str( + "1111111111111111111111111111111111111111111111111111111111111111", + ) + .unwrap(), + ), + token: Some("USDC".to_string()), + }; + + // Serialize to JSON + let json = serde_json::to_string(&original_note).unwrap(); + + // Deserialize back + let deserialized_note: Note = serde_json::from_str(&json).unwrap(); + + // Verify all fields match + assert_eq!(original_note.address, deserialized_note.address); + assert_eq!(original_note.psi, deserialized_note.psi); + assert_eq!(original_note.value, deserialized_note.value); + assert_eq!(original_note.source, deserialized_note.source); + assert_eq!(original_note.token, deserialized_note.token); + } + + #[test] + fn test_stored_note_deserialize_missing_fields() { + // Test StoredNote with note missing optional fields + let json_stored_note = r#"{ + "note": { + "address": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "psi": "abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890", + "value": "0000000000000000000000000000000000000000000000000000000000000064" + }, + "commitment": "2222222222222222222222222222222222222222222222222222222222222222" + }"#; + + let stored_note: Result = serde_json::from_str(json_stored_note); + assert!( + stored_note.is_ok(), + "Failed to deserialize StoredNote with note missing optional fields" + ); + + let stored_note = stored_note.unwrap(); + assert_eq!(stored_note.note.source, None); + assert_eq!(stored_note.note.token, None); + } +} diff --git a/pkg/wallet-data-dep/src/test.rs b/pkg/wallet-data-dep/src/test.rs new file mode 100644 index 0000000..64a50e2 --- /dev/null +++ b/pkg/wallet-data-dep/src/test.rs @@ -0,0 +1,203 @@ +// lint-long-file-override allow-max-lines=300 +use element::Element; +use std::str::FromStr; + +use crate::*; + +#[test] +fn test_output() { + let activity = WalletActivity { + base: WalletActivityBase { + parent_id: Some("123".to_string()), + result: WalletActivityResultStatus::Pending, + // TODO: can we use chrono here? + timestamp: chrono::DateTime::::from_timestamp(100, 0).unwrap(), + user_cancel: false, + error: None, + error_cycles: 0, + attempts: 0, + ok_cycles: 3, + }, + kind: WalletActivityKind::Mint(WalletActivityMintStage::Init(MintInitData { + to: Element::from_str( + "17782185823259c80f8e56d8e98bdf7d955177ffbc6683d2a3339c3fc7c3a82a", + ) + .unwrap(), + value: Element::new(10), + provider: None, + private_key: None, + })), + }; + let output = serde_json::to_string(&activity).unwrap(); + assert_eq!( + output, + "{\"parentId\":\"123\",\"result\":\"pending\",\"timestamp\":100000,\"userCancel\":false,\"error\":null,\"errorCycles\":0,\"attempts\":0,\"okCycles\":3,\"kind\":\"mint\",\"stage\":\"init\",\"data\":{\"to\":\"17782185823259c80f8e56d8e98bdf7d955177ffbc6683d2a3339c3fc7c3a82a\",\"value\":\"000000000000000000000000000000000000000000000000000000000000000a\"}}" + ); +} + +#[test] +fn test_mint_success() { + let address_str = "17782185823259c80f8e56d8e98bdf7d955177ffbc6683d2a3339c3fc7c3a82a"; + let address = Element::from_str(address_str).unwrap(); + + let note = Note { + psi: Element::from_str("1d2244c6b9556a00f48b0246f958b4b4478e22443133fcaaf9646a53c923380b") + .unwrap(), + token: Some("USDC".to_string()), + value: Element::from_str( + "0000000000000000000000000000000000000000000000000000000005f5e100", + ) + .unwrap(), + source: Some(address), + address, + }; + + let stored_note = StoredNote { + note, + commitment: Element::from_str( + "09a9ae3ef3daac29e9482b78e4417007995b4aa248206dba470c803f1a0fe8d8", + ) + .unwrap(), + received: Some(1741519021433), + timestamp: None, + spent: None, + owner: None, + remote: None, + private_key: None, + invalidreason: None, + }; + + let payy_data = PayyData { + txn: Some( + Element::from_str("4916ae8486aa666e7b77a1075eff6ff7d0f49c8a366fd0eec5435c6e86f6f4d9") + .unwrap(), + ), + root: Some( + Element::from_str("2f33f620c4129ac1b39cae29ae6780c061decce4fa5fe1fe5a1c17132a1aeb79") + .unwrap(), + ), + height: 3823585, + }; + + let init_data = MintInitData { + to: address, + value: Element::from_str( + "0000000000000000000000000000000000000000000000000000000005f5e100", + ) + .unwrap(), + provider: None, + private_key: None, + }; + + let ethereum_data = MintEthereumCombinedData { + init_data: init_data.clone(), + proof_data: MintProofData { + note: stored_note.clone(), + snark: SnarkWitness { + v1: SnarkWitnessV1 { + proof: "".to_string(), + instances: vec![], + }, + }, + proof: "".to_string(), + }, + ethereum_data: MintEthereumData { + txn: Some( + "0x423f0b6923cf21723c4f19aaf6e629f1bab4a0a2a6deaa6a14c64da23187345b".to_string(), + ), + }, + }; + + let rollup_data = MintRollupCombinedData { + ethereum_data: ethereum_data.ethereum_data, + rollup_data: MintRollupData { + payy: Some(payy_data), + }, + init_data, + }; + + let success_data = MintSuccessCombinedData { + rollup_data: rollup_data.rollup_data, + ethereum_data: rollup_data.ethereum_data, + init_data: ethereum_data.init_data, + note: stored_note, + snark: None, + proof: None, + }; + + let activity = WalletActivity { + base: WalletActivityBase { + parent_id: None, + result: WalletActivityResultStatus::Success, + timestamp: chrono::DateTime::::from_timestamp_millis(1741518988123) + .unwrap(), + user_cancel: false, + error: None, + error_cycles: 0, + attempts: 0, + ok_cycles: 3, + }, + kind: WalletActivityKind::Mint(WalletActivityMintStage::Success(success_data)), + }; + + let output = serde_json::to_string(&activity).unwrap(); + + println!("{output}"); + + // Check that the serialized JSON contains the expected fields + let json_value: serde_json::Value = serde_json::from_str(&output).unwrap(); + + assert_eq!(json_value["kind"], "mint"); + assert_eq!(json_value["stage"], "success"); + assert_eq!(json_value["result"], "success"); + assert_eq!(json_value["timestamp"].as_i64().unwrap(), 1741518988123); + assert_eq!(json_value["userCancel"], false); + assert_eq!(json_value["errorCycles"], 0); + assert_eq!(json_value["attempts"], 0); + assert_eq!(json_value["okCycles"], 3); + + // Check note fields + assert_eq!( + json_value["data"]["note"]["note"]["psi"], + "1d2244c6b9556a00f48b0246f958b4b4478e22443133fcaaf9646a53c923380b" + ); + assert_eq!(json_value["data"]["note"]["note"]["token"], "USDC"); + assert_eq!( + json_value["data"]["note"]["note"]["address"], + "17782185823259c80f8e56d8e98bdf7d955177ffbc6683d2a3339c3fc7c3a82a" + ); + + // Check other important fields + assert_eq!( + json_value["data"]["txn"], + "0x423f0b6923cf21723c4f19aaf6e629f1bab4a0a2a6deaa6a14c64da23187345b" + ); + assert_eq!( + json_value["data"]["value"], + "0000000000000000000000000000000000000000000000000000000005f5e100" + ); + assert_eq!( + json_value["data"]["to"], + "17782185823259c80f8e56d8e98bdf7d955177ffbc6683d2a3339c3fc7c3a82a" + ); +} + +#[test] +fn test_provider_type_serialization() { + // Test all provider types serialize/deserialize correctly + let providers = [ + (WalletActivityMintProviderType::Mayan, "mayan"), + (WalletActivityMintProviderType::Across, "across"), + (WalletActivityMintProviderType::PolygonUsdc, "polygon-usdc"), + ]; + + for (provider_type, expected_string) in providers { + // Test serialization + let json = serde_json::to_string(&provider_type).unwrap(); + assert_eq!(json, format!("\"{expected_string}\"")); + + // Test deserialization + let deserialized: WalletActivityMintProviderType = serde_json::from_str(&json).unwrap(); + assert_eq!(deserialized, provider_type); + } +} diff --git a/pkg/wallet-data-dep/src/util.rs b/pkg/wallet-data-dep/src/util.rs new file mode 100644 index 0000000..f6885b6 --- /dev/null +++ b/pkg/wallet-data-dep/src/util.rs @@ -0,0 +1,32 @@ +use element::Element; +use serde::{Deserialize, Deserializer}; + +// Custom deserializer function that converts failures to None +pub fn deserialize_optional_element<'de, D>(deserializer: D) -> Result, D::Error> +where + D: serde::Deserializer<'de>, +{ + let result: Result = Deserialize::deserialize(deserializer); + Ok(result.ok()) +} + +pub fn deserialize_null_default<'de, D, T>(deserializer: D) -> Result +where + T: Default + Deserialize<'de>, + D: serde::Deserializer<'de>, +{ + let opt = Option::deserialize(deserializer)?; + Ok(opt.unwrap_or_default()) +} + +pub fn deserialize_option_or_none<'de, D, T>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, + T: Deserialize<'de>, +{ + let value = serde_json::Value::deserialize(deserializer)?; + match T::deserialize(value) { + Ok(t) => Ok(Some(t)), + Err(_) => Ok(None), + } +} diff --git a/pkg/wallet-data-dep/src/wallet.rs b/pkg/wallet-data-dep/src/wallet.rs new file mode 100644 index 0000000..3527999 --- /dev/null +++ b/pkg/wallet-data-dep/src/wallet.rs @@ -0,0 +1,92 @@ +use element::Element; +use indexmap::IndexMap; +use serde::{Deserialize, Serialize}; + +use crate::{ + StoredNote, WalletActivity, WalletActivityKind, WalletActivityMintStage, + WalletActivityResultStatus, WalletActivityTxnStage, +}; + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct WalletState { + pub version: String, + pub last_update: Option, + pub address: Option, + #[serde(default)] + pub invalid_notes: IndexMap, + #[serde(default)] + pub unspent_notes: IndexMap, + #[serde(default)] + pub spent_notes: IndexMap, + #[serde(default)] + pub pending_notes: IndexMap, + pub activity: IndexMap, + #[serde(default)] + pub registry_check_block: u64, +} + +impl WalletState { + /// Gets all possible notes in the wallet + pub fn get_notes(&self) -> Vec { + let mut notes = Vec::new(); + + // Collect from pending_notes + notes.extend(self.pending_notes.values().cloned()); + + // Collect from unspent_notes + notes.extend(self.unspent_notes.values().cloned()); + + // Collect from invalid_notes + notes.extend(self.invalid_notes.values().cloned()); + + // Look for txn notes + for activity in self.activity.values() { + if activity.base.result == WalletActivityResultStatus::Pending + && let WalletActivityKind::Txn(WalletActivityTxnStage::Init(init)) = &activity.kind + { + // Add input notes + notes.extend(init.inputs.clone()); + // Add output notes + notes.extend(init.outputs.clone()); + } + if let WalletActivityKind::Send(send) = &activity.kind + && let Some(note) = send.note() + { + notes.push(note); + } + } + + notes + } + + /// Gets failed Mayan and Across mint activities that may have USDC balances + /// at their derived deposit addresses. Returns activities with their original IDs. + pub fn get_failed_mints(&self) -> Vec<(String, &WalletActivity)> { + let mut failed_mints = Vec::new(); + + for (activity_id, activity) in &self.activity { + // Only look at failed activities (not success) + if activity.base.result != WalletActivityResultStatus::Success { + // Only process mints + if let WalletActivityKind::Mint(mint_stage) = &activity.kind { + // Extract the provider from the mint stage + let provider = match mint_stage { + WalletActivityMintStage::Init(init) => &init.provider, + WalletActivityMintStage::Deposit(deposit) => &deposit.provider, + WalletActivityMintStage::Proof(proof) => &proof.init_data.provider, + WalletActivityMintStage::Ethereum(ethereum) => ðereum.init_data.provider, + WalletActivityMintStage::Rollup(rollup) => &rollup.init_data.provider, + WalletActivityMintStage::Success(success) => &success.init_data.provider, + }; + + // Check if provider exists at all (as that was used to determine if derived private key should be used) + if provider.is_some() { + failed_mints.push((activity_id.clone(), activity)); + } + } + } + } + + failed_mints + } +} diff --git a/pkg/wallet-primitives/Cargo.toml b/pkg/wallet-primitives/Cargo.toml new file mode 100644 index 0000000..40f2243 --- /dev/null +++ b/pkg/wallet-primitives/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "wallet-primitives" +version = "0.1.0" +edition = "2024" + +[dependencies] +element = { workspace = true } +encrypt = { workspace = true } +zk-primitives = { workspace = true } + +serde = { workspace = true } +serde_json = { workspace = true } +sha3 = { workspace = true } +thiserror = { workspace = true } +workspace-hack.workspace = true diff --git a/pkg/wallet-primitives/README.md b/pkg/wallet-primitives/README.md new file mode 100644 index 0000000..f857c90 --- /dev/null +++ b/pkg/wallet-primitives/README.md @@ -0,0 +1,15 @@ +# Wallet Primitives + +Fundamental wallet types including public keys and registry operations. + +## Overview + +This package provides the fundamental data types and operations used by wallet implementations. + +## Features + +- Public key management +- Registry operations +- Core wallet types +- Cryptographic primitives + diff --git a/pkg/wallet-primitives/src/lib.rs b/pkg/wallet-primitives/src/lib.rs new file mode 100644 index 0000000..bb1a3e3 --- /dev/null +++ b/pkg/wallet-primitives/src/lib.rs @@ -0,0 +1,41 @@ +use element::Element; +use sha3::{Digest, Keccak256}; + +pub mod public_key; +pub mod registry; + +pub fn derive_private_key(bytes: &[u8], private_key: Element) -> Element { + // Convert the private key to big-endian bytes + let private_key_bytes = private_key.to_be_bytes(); + + // Create a combined buffer with DEPOSIT_HEX prefix + let mut combined = Vec::with_capacity(bytes.len() + private_key_bytes.len()); + combined.extend_from_slice(bytes); + combined.extend_from_slice(&private_key_bytes); + + // Compute keccak256 hash + let hash = Keccak256::digest(&combined); + + // Convert hash to Element + Element::from_be_bytes(hash.as_slice().try_into().unwrap()) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + + #[test] + fn test_derive_private_key() { + let base_pk_el = + Element::from_str("0x32e9d283c6b6e42c7b57cb7183ce8c43b493bcce17eddc3c3aca3cb003bb075f") + .unwrap(); + let derived_pk_el = + Element::from_str("0xcdeb86d2b4aa02dbff2e3bc1356f4292cc6f0327cf4b4db2003b57385d3a5ac1") + .unwrap(); + assert_eq!( + derive_private_key(&[222, 96, 81, 112], base_pk_el), + derived_pk_el + ) + } +} diff --git a/pkg/wallet-primitives/src/public_key.rs b/pkg/wallet-primitives/src/public_key.rs new file mode 100644 index 0000000..acdc60b --- /dev/null +++ b/pkg/wallet-primitives/src/public_key.rs @@ -0,0 +1,9 @@ +use element::Element; +use encrypt::{PublicKey, StaticSecret}; + +pub fn to_public_key(private_key: Element) -> Element { + let private_key_bytes = private_key.to_be_bytes(); + let static_secret = StaticSecret::from(private_key_bytes); + let public_key = PublicKey::from(&static_secret); + Element::from_be_bytes(*public_key.as_bytes()) +} diff --git a/pkg/wallet-primitives/src/registry.rs b/pkg/wallet-primitives/src/registry.rs new file mode 100644 index 0000000..28ecb25 --- /dev/null +++ b/pkg/wallet-primitives/src/registry.rs @@ -0,0 +1,118 @@ +use element::Element; +use encrypt::{ + EncryptedAsymmetricData, EncryptedSymmetricData, PublicKey, StaticSecret, asymmetric_decrypt, + asymmetric_encrypt, generate_symmetric_key, symmetric_decrypt, symmetric_encrypt, +}; +use serde::{Deserialize, Serialize}; +use zk_primitives::Note; + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("Encrypt error: {0}")] + Encrypt(#[from] encrypt::Error), + #[error("Serialization error: {0}")] + Serialization(#[from] serde_json::Error), +} + +pub type Result = std::result::Result; + +#[derive(Debug, Clone, Deserialize)] +pub struct RegistryNote { + pub note: Note, + pub private_key: Element, + pub memo: Option, +} + +#[derive(Debug, Clone, Serialize)] +struct RegistryNoteRef<'a> { + note: &'a Note, + private_key: &'a Element, + memo: Option<&'a String>, +} + +pub struct EncryptedRegistryNote { + pub encrypted_key: Vec, + pub encrypted_note: Vec, +} + +impl EncryptedRegistryNote { + pub fn to_asymmetric_data(&self) -> Result { + EncryptedAsymmetricData::from_bytes(&self.encrypted_key).map_err(Error::Encrypt) + } + + pub fn to_symmetric_data(&self) -> Result { + EncryptedSymmetricData::from_bytes(&self.encrypted_note).map_err(Error::Encrypt) + } +} + +pub fn encode_registry_note( + to_public_key: Element, + private_key: Element, + note: &zk_primitives::Note, + memo: Option, +) -> Result { + // Encrypt the note data + let registry_note = RegistryNoteRef { + note, + private_key: &private_key, + memo: memo.as_ref(), + }; + + // Convert note to JSON string + let note_json_str = serde_json::to_string(®istry_note)?; + + // Convert JSON string to bytes + let note_json_str_bytes = note_json_str.as_bytes(); + + // Symmetric key to be asymmetric encrypted + let ephemeral_pk = generate_symmetric_key(); + let asymmetric_encrypted_symmetric_key = + asymmetric_encrypt(&PublicKey::from(to_public_key.to_be_bytes()), &ephemeral_pk)? + .to_bytes(); + + // Note json bytes data to be symmetric encrypted + let encrypted_note = symmetric_encrypt(&ephemeral_pk, note_json_str_bytes)?.to_bytes(); + + // Return the encrypted key and note + Ok(EncryptedRegistryNote { + encrypted_key: asymmetric_encrypted_symmetric_key, + encrypted_note, + }) +} + +pub fn decode_registry_note( + private_key: Element, + encrypted_note: &EncryptedRegistryNote, +) -> Result { + // Convert private key to StaticSecret for asymmetric decryption + let private_key_bytes = private_key.to_be_bytes(); + let static_secret = StaticSecret::from(private_key_bytes); + + // Convert encrypted key to EncryptedAsymmetricData + let encrypted_key_data = encrypted_note.to_asymmetric_data()?; + + // Decrypt the symmetric key using the private key + let symmetric_key_bytes = asymmetric_decrypt(&static_secret, &encrypted_key_data)?; + + // Convert symmetric key bytes to Key + let symmetric_key = encrypt::Key::from_slice(&symmetric_key_bytes); + + // Convert encrypted note to EncryptedSymmetricData + let encrypted_note_data = encrypted_note.to_symmetric_data()?; + + // Decrypt the note data using the symmetric key + let decrypted_note_bytes = symmetric_decrypt(symmetric_key, &encrypted_note_data)?; + + // Convert decrypted bytes to string + let decrypted_note_str = String::from_utf8(decrypted_note_bytes).map_err(|_| { + Error::Serialization(serde_json::Error::io(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "Decrypted data is not valid UTF-8", + ))) + })?; + + // Deserialize JSON string back to RegistryNote + let registry_note = serde_json::from_str::(&decrypted_note_str)?; + + Ok(registry_note) +} diff --git a/pkg/whitelist-ips/Cargo.toml b/pkg/whitelist-ips/Cargo.toml index 9e43094..d933719 100644 --- a/pkg/whitelist-ips/Cargo.toml +++ b/pkg/whitelist-ips/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "whitelist-ips" version = "1.3.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] libp2p.workspace = true tracing.workspace = true -tokio.workspace = true +workspace-hack.workspace = true diff --git a/pkg/whitelist-ips/README.md b/pkg/whitelist-ips/README.md new file mode 100644 index 0000000..ba644e7 --- /dev/null +++ b/pkg/whitelist-ips/README.md @@ -0,0 +1,15 @@ +# Whitelist IPs + +IP address whitelisting functionality. + +## Overview + +This package provides IP address whitelisting capabilities for access control. + +## Features + +- IP address whitelisting +- Access control logic +- Network security utilities +- Configuration management + diff --git a/pkg/whitelist-ips/src/lib.rs b/pkg/whitelist-ips/src/lib.rs index 712677f..a98f2fc 100644 --- a/pkg/whitelist-ips/src/lib.rs +++ b/pkg/whitelist-ips/src/lib.rs @@ -6,12 +6,12 @@ use std::{ }; use libp2p::{ + Multiaddr, PeerId, multiaddr::Protocol, swarm::{ - dummy, CloseConnection, ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, - THandler, THandlerInEvent, ToSwarm, + CloseConnection, ConnectionDenied, ConnectionId, NetworkBehaviour, PollParameters, + THandler, THandlerInEvent, ToSwarm, dummy, }, - Multiaddr, PeerId, }; #[derive(Debug, Clone, Default)] @@ -69,7 +69,9 @@ impl NetworkBehaviour for Behaviour { #[cfg(not(debug_assertions))] { - tracing::warn!("whitelist_ips::Behaviour::on_connection_handler_event called, which should be impossible") + tracing::warn!( + "whitelist_ips::Behaviour::on_connection_handler_event called, which should be impossible" + ) } } diff --git a/pkg/wire-message-macro/Cargo.toml b/pkg/wire-message-macro/Cargo.toml index a93e7ed..8331974 100644 --- a/pkg/wire-message-macro/Cargo.toml +++ b/pkg/wire-message-macro/Cargo.toml @@ -1,12 +1,13 @@ [package] name = "wire-message-macro" version = "1.3.0" -edition = "2021" +edition = "2024" [lib] proc-macro = true [dependencies] -quote = "1" -proc-macro2 = "1" -syn = { version = "2", features = ["full"] } +quote = { workspace = true } +proc-macro2 = { workspace = true } +syn = { workspace = true, features = ["full"] } +workspace-hack.workspace = true diff --git a/pkg/wire-message-macro/README.md b/pkg/wire-message-macro/README.md new file mode 100644 index 0000000..ce40b2b --- /dev/null +++ b/pkg/wire-message-macro/README.md @@ -0,0 +1,15 @@ +# Wire Message Macro + +Procedural macros for wire message generation. + +## Overview + +This package provides procedural macros for automatically generating wire message types and serialization code. + +## Features + +- Procedural macro implementations +- Message code generation +- Serialization automation +- Type safety utilities + diff --git a/pkg/wire-message-macro/src/lib.rs b/pkg/wire-message-macro/src/lib.rs index ed36555..631c101 100644 --- a/pkg/wire-message-macro/src/lib.rs +++ b/pkg/wire-message-macro/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; -use syn::{parse_macro_input, spanned::Spanned, Data, DeriveInput}; +use syn::{Data, DeriveInput, parse_macro_input, spanned::Spanned}; #[proc_macro_attribute] pub fn wire_message( diff --git a/pkg/wire-message/Cargo.toml b/pkg/wire-message/Cargo.toml index 1aad3eb..85e60bc 100644 --- a/pkg/wire-message/Cargo.toml +++ b/pkg/wire-message/Cargo.toml @@ -1,16 +1,17 @@ [package] name = "wire-message" version = "1.3.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] borsh = { workspace = true } -wire-message-macro = { path = "../wire-message-macro" } +wire-message-macro = { workspace = true } strum = { workspace = true } strum_macros = { workspace = true } static_assertions = { workspace = true } +workspace-hack.workspace = true [features] test-api = [] diff --git a/pkg/wire-message/README.md b/pkg/wire-message/README.md new file mode 100644 index 0000000..cd73567 --- /dev/null +++ b/pkg/wire-message/README.md @@ -0,0 +1,15 @@ +# Wire Message + +Wire protocol message definitions with error handling. + +## Overview + +This package defines the wire protocol messages used for communication in the network. + +## Features + +- Message protocol definitions +- Error handling +- Serialization support +- Test API utilities + diff --git a/pkg/wire-message/src/test_api.rs b/pkg/wire-message/src/test_api.rs index 780027e..894769d 100644 --- a/pkg/wire-message/src/test_api.rs +++ b/pkg/wire-message/src/test_api.rs @@ -1,12 +1,13 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use crate::WireMessage; +use crate::strum_macros::EnumCount; +use crate::{Error, WireMessage}; /// Dummy message type for use in testing #[derive( ::borsh::BorshSerialize, ::borsh::BorshDeserialize, - crate::strum_macros::EnumCount, // we don't use the macro here because it's in the same crate + EnumCount, // we don't use the macro here because it's in the same crate Debug, Clone, PartialEq, @@ -23,7 +24,7 @@ impl WireMessage f 1 } - fn upgrade_once(self, _ctx: &mut Self::Ctx) -> Result { + fn upgrade_once(self, _ctx: &mut Self::Ctx) -> Result { Err(Self::max_version_error()) } } diff --git a/pkg/wire-message/tests/example.rs b/pkg/wire-message/tests/example.rs index 94e2f77..7ed5c7f 100644 --- a/pkg/wire-message/tests/example.rs +++ b/pkg/wire-message/tests/example.rs @@ -1,6 +1,6 @@ #![allow(clippy::disallowed_names)] use borsh::{BorshDeserialize, BorshSerialize}; -use wire_message::{wire_message, Error, WireMessage}; +use wire_message::{Error, WireMessage, wire_message}; #[wire_message] enum ExampleMessage { diff --git a/pkg/workspace-hack/Cargo.toml b/pkg/workspace-hack/Cargo.toml new file mode 100644 index 0000000..9390880 --- /dev/null +++ b/pkg/workspace-hack/Cargo.toml @@ -0,0 +1,516 @@ +[package] +name = "workspace-hack" +version = "0.1.0" +edition = "2024" +description = "Workspace hack crate maintained by cargo-hakari" +publish = false + +[features] +default = [] + +### BEGIN HAKARI SECTION +[dependencies] +actix-router = { version = "0.5", default-features = false, features = ["http", "unicode"] } +ahash = { version = "0.8", default-features = false, features = ["runtime-rng"] } +aho-corasick = { version = "1" } +allocator-api2 = { version = "0.2" } +alloy-chains = { version = "0.2", default-features = false, features = ["rlp", "serde", "std"] } +alloy-consensus = { version = "1", features = ["k256", "kzg", "serde", "serde-bincode-compat"] } +alloy-dyn-abi = { version = "1", features = ["eip712"] } +alloy-eip7702 = { version = "0.6", default-features = false, features = ["k256", "serde", "serde-bincode-compat", "std"] } +alloy-eips = { version = "1", features = ["k256", "kzg", "serde", "serde-bincode-compat", "ssz"] } +alloy-json-abi = { version = "1", features = ["serde_json"] } +alloy-primitives = { version = "1", features = ["k256", "map-indexmap", "rand", "rlp", "serde"] } +alloy-provider = { version = "1", default-features = false, features = ["debug-api", "ipc", "reqwest", "ws"] } +alloy-rlp = { version = "0.3", features = ["arrayvec", "core-error", "core-net", "derive"] } +alloy-rpc-client = { version = "1", default-features = false, features = ["ipc", "reqwest", "ws"] } +alloy-rpc-types = { version = "1", default-features = false, features = ["engine", "eth"] } +alloy-rpc-types-engine = { version = "1", features = ["kzg", "ssz"] } +alloy-rpc-types-eth = { version = "1", default-features = false, features = ["serde-bincode-compat", "std"] } +alloy-signer-local = { version = "1", default-features = false, features = ["mnemonic"] } +alloy-sol-type-parser = { version = "1", default-features = false, features = ["eip712", "serde", "std"] } +alloy-sol-types = { version = "1", features = ["eip712-serde", "json"] } +alloy-transport-http = { version = "1", default-features = false, features = ["reqwest", "reqwest-rustls-tls"] } +ark-bn254 = { version = "0.5", default-features = false, features = ["curve", "std"] } +ark-ec = { version = "0.5", default-features = false, features = ["std"] } +ark-ff = { version = "0.5", default-features = false, features = ["asm", "std"] } +ark-serialize = { version = "0.5", default-features = false, features = ["derive", "std"] } +ark-std = { version = "0.5", default-features = false, features = ["std"] } +arrayvec = { version = "0.7", features = ["serde"] } +async-compression = { version = "0.4", default-features = false, features = ["brotli", "gzip", "tokio", "zlib", "zstd"] } +base64 = { version = "0.13", features = ["alloc"] } +bitflags = { version = "2", default-features = false, features = ["serde", "std"] } +bitvec = { version = "1", features = ["serde"] } +blst = { version = "0.3", features = ["portable"] } +bs58 = { version = "0.5", features = ["check"] } +bumpalo = { version = "3", features = ["allocator-api2", "collections"] } +byteorder = { version = "1", features = ["i128"] } +bytes = { version = "1", features = ["serde"] } +c-kzg = { version = "2", features = ["serde"] } +chrono = { version = "0.4", features = ["serde"] } +cipher = { version = "0.4", default-features = false, features = ["block-padding", "zeroize"] } +clap = { version = "4", features = ["derive", "env", "string"] } +clap_builder = { version = "4", default-features = false, features = ["color", "env", "help", "std", "string", "suggestions", "usage"] } +compression-codecs = { version = "0.4", default-features = false, features = ["brotli", "gzip", "zlib", "zstd"] } +const-hex = { version = "1", features = ["core-error", "hex", "serde"] } +crossbeam-epoch = { version = "0.9" } +crossbeam-utils = { version = "0.8" } +crunchy = { version = "0.2", features = ["limit_256", "std"] } +crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } +curve25519-dalek = { version = "4", default-features = false, features = ["alloc", "digest", "precomputed-tables", "zeroize"] } +dashmap = { version = "6", default-features = false, features = ["inline"] } +data-encoding = { version = "2" } +derive_more = { version = "2", features = ["full"] } +digest = { version = "0.10", features = ["mac", "oid", "std"] } +ecdsa = { version = "0.16", default-features = false, features = ["pem", "serde", "signing", "std", "verifying"] } +ed25519 = { version = "2", default-features = false, features = ["alloc", "pkcs8", "std"] } +ed25519-dalek = { version = "2", features = ["pkcs8", "rand_core"] } +either = { version = "1", features = ["serde", "use_std"] } +elliptic-curve = { version = "0.13", default-features = false, features = ["ecdh", "hazmat", "pem", "serde", "std"] } +ethbloom = { version = "0.13", default-features = false, features = ["codec", "rlp", "serialize", "std"] } +ethereum-types = { version = "0.14", features = ["codec"] } +ff = { version = "0.13" } +figment = { version = "0.10", default-features = false, features = ["env", "test", "toml"] } +foldhash = { version = "0.1" } +form_urlencoded = { version = "1" } +futures = { version = "0.3", features = ["bilock", "thread-pool", "unstable"] } +futures-channel = { version = "0.3", features = ["sink", "unstable"] } +futures-core = { version = "0.3", features = ["unstable"] } +futures-executor = { version = "0.3", features = ["thread-pool"] } +futures-io = { version = "0.3", features = ["unstable"] } +futures-sink = { version = "0.3" } +futures-task = { version = "0.3", default-features = false, features = ["std", "unstable"] } +futures-timer = { version = "3", default-features = false, features = ["wasm-bindgen"] } +futures-util = { version = "0.3", features = ["bilock", "channel", "io", "sink", "unstable"] } +generic-array = { version = "0.14", default-features = false, features = ["more_lengths", "zeroize"] } +getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2", default-features = false, features = ["std"] } +group = { version = "0.13" } +hashbrown-3575ec1268b04181 = { package = "hashbrown", version = "0.15" } +hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14", features = ["raw"] } +hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13", features = ["raw"] } +hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16", features = ["serde"] } +hex = { version = "0.4", features = ["serde"] } +hmac = { version = "0.12", default-features = false, features = ["reset"] } +httparse = { version = "1" } +hyper = { version = "1", features = ["client", "http1", "http2", "server"] } +hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "service"] } +idna = { version = "1", default-features = false, features = ["compiled_data", "std"] } +indexmap = { version = "2", features = ["serde"] } +inout = { version = "0.1", default-features = false, features = ["block-padding"] } +insta = { version = "1", features = ["json", "redactions", "yaml"] } +itertools-582f2526e08bb6a0 = { package = "itertools", version = "0.14" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } +itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +k256 = { version = "0.13", features = ["serde"] } +keccak = { version = "0.1", default-features = false, features = ["asm"] } +lalrpop-util = { version = "0.20" } +lazy_static = { version = "1", default-features = false, features = ["spin_no_std"] } +libc = { version = "0.2" } +libz-sys = { version = "1", default-features = false, features = ["libc", "static"] } +lock_api = { version = "0.4", features = ["arc_lock", "serde"] } +log = { version = "0.4", default-features = false, features = ["std"] } +memchr = { version = "2" } +mio = { version = "1", features = ["net", "os-ext"] } +native-tls = { version = "0.2", default-features = false, features = ["alpn"] } +nom = { version = "7" } +num-bigint = { version = "0.4", features = ["serde"] } +num-integer = { version = "0.1", features = ["i128"] } +num-iter = { version = "0.1", default-features = false, features = ["i128", "std"] } +num-traits = { version = "0.2", features = ["i128", "libm"] } +num_enum = { version = "0.7" } +nybbles = { version = "0.4", default-features = false, features = ["rlp", "serde", "std"] } +once_cell = { version = "1", features = ["critical-section"] } +parity-scale-codec = { version = "3", features = ["bytes", "derive", "max-encoded-len"] } +parking_lot = { version = "0.12", features = ["arc_lock", "send_guard", "serde"] } +percent-encoding = { version = "2" } +phf_shared = { version = "0.11" } +portable-atomic = { version = "1" } +postgres-types = { version = "0.2", default-features = false, features = ["with-uuid-1"] } +ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } +primitive-types = { version = "0.12", default-features = false, features = ["byteorder", "rlp", "rustc-hex", "scale-info", "serde_no_std", "std"] } +proc-macro2 = { version = "1", features = ["span-locations"] } +prost = { version = "0.13", features = ["prost-derive"] } +rand-274715c4dabd11b0 = { package = "rand", version = "0.9", features = ["serde"] } +rand-c38e5c1d305a1b54 = { package = "rand", version = "0.8", features = ["serde", "small_rng"] } +rand_chacha-274715c4dabd11b0 = { package = "rand_chacha", version = "0.9", default-features = false, features = ["std"] } +rand_chacha-468e82937335b1c9 = { package = "rand_chacha", version = "0.3" } +rand_core-274715c4dabd11b0 = { package = "rand_core", version = "0.9", default-features = false, features = ["os_rng", "serde", "std"] } +rand_core-3b31131e45eafb45 = { package = "rand_core", version = "0.6", default-features = false, features = ["std"] } +regex = { version = "1" } +regex-automata = { version = "0.4", default-features = false, features = ["dfa-build", "dfa-onepass", "hybrid", "meta", "nfa", "perf", "std", "unicode"] } +regex-syntax = { version = "0.8" } +reqwest-5ef9efb8ec2df382 = { package = "reqwest", version = "0.12", features = ["blocking", "json", "multipart", "rustls-tls", "rustls-tls-native-roots", "stream"] } +reqwest-a6292c17cd707f01 = { package = "reqwest", version = "0.11", default-features = false, features = ["default-tls", "gzip", "json"] } +ring = { version = "0.17", features = ["std"] } +rlp = { version = "0.5", features = ["derive"] } +ruint = { version = "1", default-features = false, features = ["alloy-rlp", "rand-09", "serde", "std"] } +rustc-hash = { version = "2", features = ["rand"] } +rustc-hex = { version = "2" } +rustls = { version = "0.23", features = ["ring"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs", "ring", "std"] } +scopeguard = { version = "1" } +sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] } +semver = { version = "1", features = ["serde"] } +serde = { version = "1", features = ["alloc", "derive", "rc"] } +serde_core = { version = "1", features = ["alloc", "rc"] } +serde_json = { version = "1", features = ["alloc", "raw_value", "unbounded_depth"] } +serde_with = { version = "3", features = ["base64"] } +sha1 = { version = "0.10", features = ["oid"] } +sha2 = { version = "0.10", features = ["compress", "oid"] } +sha3 = { version = "0.10", features = ["asm"] } +signature = { version = "2", default-features = false, features = ["digest", "rand_core", "std"] } +similar = { version = "2", features = ["inline"] } +smallvec = { version = "1", default-features = false, features = ["const_new", "serde", "union"] } +socket2-3b31131e45eafb45 = { package = "socket2", version = "0.6", default-features = false, features = ["all"] } +socket2-d8f496e17d97b5cb = { package = "socket2", version = "0.5", default-features = false, features = ["all"] } +strum = { version = "0.27", features = ["derive"] } +subtle = { version = "2" } +sync_wrapper = { version = "1", default-features = false, features = ["futures"] } +thiserror = { version = "2" } +time = { version = "0.3", features = ["formatting", "local-offset", "macros", "parsing"] } +tiny-keccak = { version = "2", features = ["keccak", "sha3"] } +tokio = { version = "1", features = ["full", "test-util"] } +tokio-postgres = { version = "0.7", features = ["with-uuid-1"] } +tokio-rustls = { version = "0.26", features = ["ring"] } +tokio-stream = { version = "0.1", features = ["sync"] } +tokio-util = { version = "0.7", features = ["codec", "compat", "io", "time"] } +tower = { version = "0.5", default-features = false, features = ["full", "log"] } +tracing = { version = "0.1", features = ["log", "valuable"] } +tracing-core = { version = "0.1", features = ["valuable"] } +tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } +triomphe = { version = "0.1", features = ["arc-swap"] } +unicode-bidi = { version = "0.3" } +unicode-normalization = { version = "0.1" } +url = { version = "2", features = ["serde"] } +uuid = { version = "1", features = ["serde", "v4"] } +winnow = { version = "0.7" } +zeroize = { version = "1", features = ["zeroize_derive"] } +zstd = { version = "0.13", features = ["experimental"] } +zstd-safe = { version = "7", default-features = false, features = ["arrays", "experimental", "legacy", "std", "zdict_builder"] } +zstd-sys = { version = "2", features = ["experimental", "std"] } + +[build-dependencies] +actix-router = { version = "0.5", default-features = false, features = ["http", "unicode"] } +ahash = { version = "0.8", default-features = false, features = ["runtime-rng"] } +aho-corasick = { version = "1" } +allocator-api2 = { version = "0.2" } +alloy-chains = { version = "0.2", default-features = false, features = ["rlp", "serde", "std"] } +alloy-consensus = { version = "1", features = ["k256", "kzg", "serde", "serde-bincode-compat"] } +alloy-dyn-abi = { version = "1", features = ["eip712"] } +alloy-eip7702 = { version = "0.6", default-features = false, features = ["k256", "serde", "serde-bincode-compat", "std"] } +alloy-eips = { version = "1", features = ["k256", "kzg", "serde", "serde-bincode-compat", "ssz"] } +alloy-json-abi = { version = "1", features = ["serde_json"] } +alloy-primitives = { version = "1", features = ["k256", "map-indexmap", "rand", "rlp", "serde"] } +alloy-provider = { version = "1", default-features = false, features = ["debug-api", "ipc", "reqwest", "ws"] } +alloy-rlp = { version = "0.3", features = ["arrayvec", "core-error", "core-net", "derive"] } +alloy-rpc-client = { version = "1", default-features = false, features = ["ipc", "reqwest", "ws"] } +alloy-rpc-types = { version = "1", default-features = false, features = ["engine", "eth"] } +alloy-rpc-types-engine = { version = "1", features = ["kzg", "ssz"] } +alloy-rpc-types-eth = { version = "1", default-features = false, features = ["serde-bincode-compat", "std"] } +alloy-signer-local = { version = "1", default-features = false, features = ["mnemonic"] } +alloy-sol-macro = { version = "1", default-features = false, features = ["json"] } +alloy-sol-macro-expander = { version = "1", default-features = false, features = ["json"] } +alloy-sol-macro-input = { version = "1", default-features = false, features = ["json"] } +alloy-sol-type-parser = { version = "1", default-features = false, features = ["eip712", "serde", "std"] } +alloy-sol-types = { version = "1", features = ["eip712-serde", "json"] } +alloy-transport-http = { version = "1", default-features = false, features = ["reqwest", "reqwest-rustls-tls"] } +ark-bn254 = { version = "0.5", default-features = false, features = ["curve", "std"] } +ark-ec = { version = "0.5", default-features = false, features = ["std"] } +ark-ff = { version = "0.5", default-features = false, features = ["asm", "std"] } +ark-serialize = { version = "0.5", default-features = false, features = ["derive", "std"] } +ark-std = { version = "0.5", default-features = false, features = ["std"] } +arrayvec = { version = "0.7", features = ["serde"] } +async-compression = { version = "0.4", default-features = false, features = ["brotli", "gzip", "tokio", "zlib", "zstd"] } +base64 = { version = "0.13", features = ["alloc"] } +bindgen = { version = "0.71" } +bitflags = { version = "2", default-features = false, features = ["serde", "std"] } +bitvec = { version = "1", features = ["serde"] } +blst = { version = "0.3", features = ["portable"] } +bs58 = { version = "0.5", features = ["check"] } +bumpalo = { version = "3", features = ["allocator-api2", "collections"] } +byteorder = { version = "1", features = ["i128"] } +bytes = { version = "1", features = ["serde"] } +c-kzg = { version = "2", features = ["serde"] } +cc = { version = "1", default-features = false, features = ["parallel"] } +chrono = { version = "0.4", features = ["serde"] } +cipher = { version = "0.4", default-features = false, features = ["block-padding", "zeroize"] } +clang-sys = { version = "1", default-features = false, features = ["clang_11_0", "runtime"] } +clap = { version = "4", features = ["derive", "env", "string"] } +clap_builder = { version = "4", default-features = false, features = ["color", "env", "help", "std", "string", "suggestions", "usage"] } +compression-codecs = { version = "0.4", default-features = false, features = ["brotli", "gzip", "zlib", "zstd"] } +const-hex = { version = "1", features = ["core-error", "hex", "serde"] } +crossbeam-epoch = { version = "0.9" } +crossbeam-utils = { version = "0.8" } +crunchy = { version = "0.2", features = ["limit_256", "std"] } +crypto-common = { version = "0.1", default-features = false, features = ["getrandom", "std"] } +curve25519-dalek = { version = "4", default-features = false, features = ["alloc", "digest", "precomputed-tables", "zeroize"] } +darling = { version = "0.21", features = ["serde"] } +darling_core = { version = "0.21", default-features = false, features = ["serde", "suggestions"] } +dashmap = { version = "6", default-features = false, features = ["inline"] } +data-encoding = { version = "2" } +derive_more = { version = "2", features = ["full"] } +derive_more-impl = { version = "2", features = ["add", "add_assign", "as_ref", "constructor", "debug", "deref", "deref_mut", "display", "eq", "error", "from", "from_str", "index", "index_mut", "into", "into_iterator", "is_variant", "mul", "mul_assign", "not", "sum", "try_from", "try_into", "try_unwrap", "unwrap"] } +digest = { version = "0.10", features = ["mac", "oid", "std"] } +ecdsa = { version = "0.16", default-features = false, features = ["pem", "serde", "signing", "std", "verifying"] } +ed25519 = { version = "2", default-features = false, features = ["alloc", "pkcs8", "std"] } +ed25519-dalek = { version = "2", features = ["pkcs8", "rand_core"] } +either = { version = "1", features = ["serde", "use_std"] } +elliptic-curve = { version = "0.13", default-features = false, features = ["ecdh", "hazmat", "pem", "serde", "std"] } +ethbloom = { version = "0.13", default-features = false, features = ["codec", "rlp", "serialize", "std"] } +ethereum-types = { version = "0.14", features = ["codec"] } +ff = { version = "0.13" } +figment = { version = "0.10", default-features = false, features = ["env", "test", "toml"] } +foldhash = { version = "0.1" } +form_urlencoded = { version = "1" } +futures = { version = "0.3", features = ["bilock", "thread-pool", "unstable"] } +futures-channel = { version = "0.3", features = ["sink", "unstable"] } +futures-core = { version = "0.3", features = ["unstable"] } +futures-executor = { version = "0.3", features = ["thread-pool"] } +futures-io = { version = "0.3", features = ["unstable"] } +futures-sink = { version = "0.3" } +futures-task = { version = "0.3", default-features = false, features = ["std", "unstable"] } +futures-timer = { version = "3", default-features = false, features = ["wasm-bindgen"] } +futures-util = { version = "0.3", features = ["bilock", "channel", "io", "sink", "unstable"] } +generic-array = { version = "0.14", default-features = false, features = ["more_lengths", "zeroize"] } +getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2", default-features = false, features = ["std"] } +group = { version = "0.13" } +hashbrown-3575ec1268b04181 = { package = "hashbrown", version = "0.15" } +hashbrown-582f2526e08bb6a0 = { package = "hashbrown", version = "0.14", features = ["raw"] } +hashbrown-594e8ee84c453af0 = { package = "hashbrown", version = "0.13", features = ["raw"] } +hashbrown-986da7b5efc2b80e = { package = "hashbrown", version = "0.16", features = ["serde"] } +hex = { version = "0.4", features = ["serde"] } +hmac = { version = "0.12", default-features = false, features = ["reset"] } +httparse = { version = "1" } +hyper = { version = "1", features = ["client", "http1", "http2", "server"] } +hyper-util = { version = "0.1", features = ["client-legacy", "server-auto", "service"] } +idna = { version = "1", default-features = false, features = ["compiled_data", "std"] } +indexmap = { version = "2", features = ["serde"] } +inout = { version = "0.1", default-features = false, features = ["block-padding"] } +insta = { version = "1", features = ["json", "redactions", "yaml"] } +itertools-582f2526e08bb6a0 = { package = "itertools", version = "0.14" } +itertools-594e8ee84c453af0 = { package = "itertools", version = "0.13" } +itertools-a6292c17cd707f01 = { package = "itertools", version = "0.11" } +k256 = { version = "0.13", features = ["serde"] } +keccak = { version = "0.1", default-features = false, features = ["asm"] } +lalrpop-util = { version = "0.20" } +lazy_static = { version = "1", default-features = false, features = ["spin_no_std"] } +libc = { version = "0.2" } +libz-sys = { version = "1", default-features = false, features = ["libc", "static"] } +lock_api = { version = "0.4", features = ["arc_lock", "serde"] } +log = { version = "0.4", default-features = false, features = ["std"] } +memchr = { version = "2" } +mio = { version = "1", features = ["net", "os-ext"] } +native-tls = { version = "0.2", default-features = false, features = ["alpn"] } +nom = { version = "7" } +num-bigint = { version = "0.4", features = ["serde"] } +num-integer = { version = "0.1", features = ["i128"] } +num-iter = { version = "0.1", default-features = false, features = ["i128", "std"] } +num-traits = { version = "0.2", features = ["i128", "libm"] } +num_enum = { version = "0.7" } +num_enum_derive = { version = "0.7", default-features = false, features = ["std"] } +nybbles = { version = "0.4", default-features = false, features = ["rlp", "serde", "std"] } +once_cell = { version = "1", features = ["critical-section"] } +parity-scale-codec = { version = "3", features = ["bytes", "derive", "max-encoded-len"] } +parking_lot = { version = "0.12", features = ["arc_lock", "send_guard", "serde"] } +percent-encoding = { version = "2" } +phf_shared = { version = "0.11" } +portable-atomic = { version = "1" } +postgres-types = { version = "0.2", default-features = false, features = ["with-uuid-1"] } +ppv-lite86 = { version = "0.2", default-features = false, features = ["simd", "std"] } +prettyplease = { version = "0.2", default-features = false, features = ["verbatim"] } +primitive-types = { version = "0.12", default-features = false, features = ["byteorder", "rlp", "rustc-hex", "scale-info", "serde_no_std", "std"] } +proc-macro2 = { version = "1", features = ["span-locations"] } +prost = { version = "0.13", features = ["prost-derive"] } +quote = { version = "1" } +rand-274715c4dabd11b0 = { package = "rand", version = "0.9", features = ["serde"] } +rand-c38e5c1d305a1b54 = { package = "rand", version = "0.8", features = ["serde", "small_rng"] } +rand_chacha-274715c4dabd11b0 = { package = "rand_chacha", version = "0.9", default-features = false, features = ["std"] } +rand_chacha-468e82937335b1c9 = { package = "rand_chacha", version = "0.3" } +rand_core-274715c4dabd11b0 = { package = "rand_core", version = "0.9", default-features = false, features = ["os_rng", "serde", "std"] } +rand_core-3b31131e45eafb45 = { package = "rand_core", version = "0.6", default-features = false, features = ["std"] } +regex = { version = "1" } +regex-automata = { version = "0.4", default-features = false, features = ["dfa-build", "dfa-onepass", "hybrid", "meta", "nfa", "perf", "std", "unicode"] } +regex-syntax = { version = "0.8" } +reqwest-5ef9efb8ec2df382 = { package = "reqwest", version = "0.12", features = ["blocking", "json", "multipart", "rustls-tls", "rustls-tls-native-roots", "stream"] } +reqwest-a6292c17cd707f01 = { package = "reqwest", version = "0.11", default-features = false, features = ["default-tls", "gzip", "json"] } +ring = { version = "0.17", features = ["std"] } +rlp = { version = "0.5", features = ["derive"] } +ruint = { version = "1", default-features = false, features = ["alloy-rlp", "rand-09", "serde", "std"] } +rustc-hash = { version = "2", features = ["rand"] } +rustc-hex = { version = "2" } +rustls = { version = "0.23", features = ["ring"] } +rustls-webpki = { version = "0.103", default-features = false, features = ["aws-lc-rs", "ring", "std"] } +scopeguard = { version = "1" } +sec1 = { version = "0.7", features = ["pem", "serde", "std", "subtle"] } +semver = { version = "1", features = ["serde"] } +serde = { version = "1", features = ["alloc", "derive", "rc"] } +serde_core = { version = "1", features = ["alloc", "rc"] } +serde_json = { version = "1", features = ["alloc", "raw_value", "unbounded_depth"] } +serde_with = { version = "3", features = ["base64"] } +sha1 = { version = "0.10", features = ["oid"] } +sha2 = { version = "0.10", features = ["compress", "oid"] } +sha3 = { version = "0.10", features = ["asm"] } +signature = { version = "2", default-features = false, features = ["digest", "rand_core", "std"] } +similar = { version = "2", features = ["inline"] } +smallvec = { version = "1", default-features = false, features = ["const_new", "serde", "union"] } +socket2-3b31131e45eafb45 = { package = "socket2", version = "0.6", default-features = false, features = ["all"] } +socket2-d8f496e17d97b5cb = { package = "socket2", version = "0.5", default-features = false, features = ["all"] } +strum = { version = "0.27", features = ["derive"] } +subtle = { version = "2" } +syn-dff4ba8e3ae991db = { package = "syn", version = "1", features = ["extra-traits", "full", "visit"] } +syn-f595c2ba2a3f28df = { package = "syn", version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] } +sync_wrapper = { version = "1", default-features = false, features = ["futures"] } +thiserror = { version = "2" } +time = { version = "0.3", features = ["formatting", "local-offset", "macros", "parsing"] } +tiny-keccak = { version = "2", features = ["keccak", "sha3"] } +tokio = { version = "1", features = ["full", "test-util"] } +tokio-postgres = { version = "0.7", features = ["with-uuid-1"] } +tokio-rustls = { version = "0.26", features = ["ring"] } +tokio-stream = { version = "0.1", features = ["sync"] } +tokio-util = { version = "0.7", features = ["codec", "compat", "io", "time"] } +tower = { version = "0.5", default-features = false, features = ["full", "log"] } +tracing = { version = "0.1", features = ["log", "valuable"] } +tracing-core = { version = "0.1", features = ["valuable"] } +tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } +triomphe = { version = "0.1", features = ["arc-swap"] } +unicode-bidi = { version = "0.3" } +unicode-normalization = { version = "0.1" } +url = { version = "2", features = ["serde"] } +uuid = { version = "1", features = ["serde", "v4"] } +winnow = { version = "0.7" } +zeroize = { version = "1", features = ["zeroize_derive"] } +zstd = { version = "0.13", features = ["experimental"] } +zstd-safe = { version = "7", default-features = false, features = ["arrays", "experimental", "legacy", "std", "zdict_builder"] } +zstd-sys = { version = "2", features = ["experimental", "std"] } + +[target.x86_64-unknown-linux-gnu.dependencies] +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "ioctl", "no_std", "prctl", "system"] } +linux-raw-sys-a6292c17cd707f01 = { package = "linux-raw-sys", version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl", "system"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +openssl = { version = "0.10", features = ["vendored"] } +openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["param", "process", "system", "thread"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "param", "process", "system", "thread"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.x86_64-unknown-linux-gnu.build-dependencies] +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +linux-raw-sys-9fbad63c4bcf4a8f = { package = "linux-raw-sys", version = "0.4", default-features = false, features = ["elf", "errno", "general", "ioctl", "no_std", "prctl", "system"] } +linux-raw-sys-a6292c17cd707f01 = { package = "linux-raw-sys", version = "0.11", default-features = false, features = ["auxvec", "elf", "errno", "general", "ioctl", "no_std", "prctl", "system"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +openssl = { version = "0.10", features = ["vendored"] } +openssl-sys = { version = "0.9", default-features = false, features = ["vendored"] } +rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38", features = ["param", "process", "system", "thread"] } +rustix-dff4ba8e3ae991db = { package = "rustix", version = "1", features = ["fs", "param", "process", "system", "thread"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.aarch64-apple-darwin.dependencies] +errno = { version = "0.3" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +security-framework-7b89eefb6aaa9bf3 = { package = "security-framework", version = "3", features = ["OSX_10_14"] } +security-framework-f595c2ba2a3f28df = { package = "security-framework", version = "2", features = ["alpn"] } +security-framework-sys = { version = "2", features = ["OSX_10_14"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.aarch64-apple-darwin.build-dependencies] +errno = { version = "0.3" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +security-framework-7b89eefb6aaa9bf3 = { package = "security-framework", version = "3", features = ["OSX_10_14"] } +security-framework-f595c2ba2a3f28df = { package = "security-framework", version = "2", features = ["alpn"] } +security-framework-sys = { version = "2", features = ["OSX_10_14"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.aarch64-apple-ios.dependencies] +errno = { version = "0.3" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +security-framework-f595c2ba2a3f28df = { package = "security-framework", version = "2", features = ["alpn"] } +security-framework-sys = { version = "2", features = ["OSX_10_14"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.aarch64-apple-ios.build-dependencies] +errno = { version = "0.3" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +security-framework-f595c2ba2a3f28df = { package = "security-framework", version = "2", features = ["alpn"] } +security-framework-sys = { version = "2", features = ["OSX_10_14"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.aarch64-apple-ios-sim.dependencies] +errno = { version = "0.3" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +security-framework-f595c2ba2a3f28df = { package = "security-framework", version = "2", features = ["alpn"] } +security-framework-sys = { version = "2", features = ["OSX_10_14"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.aarch64-apple-ios-sim.build-dependencies] +errno = { version = "0.3" } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +libc = { version = "0.2", default-features = false, features = ["extra_traits"] } +miniz_oxide = { version = "0.8", default-features = false, features = ["simd", "with-alloc"] } +security-framework-f595c2ba2a3f28df = { package = "security-framework", version = "2", features = ["alpn"] } +security-framework-sys = { version = "2", features = ["OSX_10_14"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } + +[target.x86_64-pc-windows-msvc.dependencies] +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } +winapi = { version = "0.3", default-features = false, features = ["cfg", "consoleapi", "errhandlingapi", "evntrace", "fileapi", "handleapi", "in6addr", "inaddr", "knownfolders", "libloaderapi", "memoryapi", "minwinbase", "minwindef", "ntsecapi", "ntstatus", "objbase", "processenv", "processthreadsapi", "profileapi", "psapi", "shlobj", "std", "synchapi", "sysinfoapi", "winbase", "wincon", "windef", "winerror", "winioctl", "winnt", "ws2ipdef", "ws2tcpip"] } +windows-sys-4db8c43aad08e7ae = { package = "windows-sys", version = "0.60", features = ["Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_Threading", "Win32_System_WindowsProgramming"] } +windows-sys-73dcd821b1037cfd = { package = "windows-sys", version = "0.59", features = ["Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Console", "Win32_System_IO", "Win32_System_Memory", "Win32_System_Threading", "Win32_UI_Input_KeyboardAndMouse"] } +windows-sys-b21d60becc0929df = { package = "windows-sys", version = "0.52", features = ["Win32_Foundation", "Win32_Networking_WinSock", "Win32_Security_Authorization", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Pipes", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_WindowsProgramming"] } +windows-sys-c8eced492e86ede7 = { package = "windows-sys", version = "0.48", features = ["Win32_Foundation", "Win32_Globalization", "Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Diagnostics_Debug", "Win32_System_Memory", "Win32_System_Registry", "Win32_System_Time", "Win32_UI_Shell"] } +windows-sys-d4189bed749088b6 = { package = "windows-sys", version = "0.61", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Wdk_System_IO", "Win32_Networking_WinSock", "Win32_Security_Authentication_Identity", "Win32_Security_Credentials", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_WindowsProgramming", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] } + +[target.x86_64-pc-windows-msvc.build-dependencies] +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3", default-features = false, features = ["std"] } +hyper-rustls = { version = "0.27", default-features = false, features = ["http1", "http2", "logging", "native-tokio", "ring", "tls12", "webpki-tokio"] } +hyper-util = { version = "0.1", default-features = false, features = ["client-proxy", "client-proxy-system"] } +tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots", "rustls-tls-webpki-roots"] } +tower-http = { version = "0.6", features = ["full"] } +winapi = { version = "0.3", default-features = false, features = ["cfg", "consoleapi", "errhandlingapi", "evntrace", "fileapi", "handleapi", "in6addr", "inaddr", "knownfolders", "libloaderapi", "memoryapi", "minwinbase", "minwindef", "ntsecapi", "ntstatus", "objbase", "processenv", "processthreadsapi", "profileapi", "psapi", "shlobj", "std", "synchapi", "sysinfoapi", "winbase", "wincon", "windef", "winerror", "winioctl", "winnt", "ws2ipdef", "ws2tcpip"] } +windows-sys-4db8c43aad08e7ae = { package = "windows-sys", version = "0.60", features = ["Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_Threading", "Win32_System_WindowsProgramming"] } +windows-sys-73dcd821b1037cfd = { package = "windows-sys", version = "0.59", features = ["Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Console", "Win32_System_IO", "Win32_System_Memory", "Win32_System_Threading", "Win32_UI_Input_KeyboardAndMouse"] } +windows-sys-b21d60becc0929df = { package = "windows-sys", version = "0.52", features = ["Win32_Foundation", "Win32_Networking_WinSock", "Win32_Security_Authorization", "Win32_Storage_FileSystem", "Win32_System_IO", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Pipes", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_WindowsProgramming"] } +windows-sys-c8eced492e86ede7 = { package = "windows-sys", version = "0.48", features = ["Win32_Foundation", "Win32_Globalization", "Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_Security", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Diagnostics_Debug", "Win32_System_Memory", "Win32_System_Registry", "Win32_System_Time", "Win32_UI_Shell"] } +windows-sys-d4189bed749088b6 = { package = "windows-sys", version = "0.61", features = ["Wdk_Foundation", "Wdk_Storage_FileSystem", "Wdk_System_IO", "Win32_Networking_WinSock", "Win32_Security_Authentication_Identity", "Win32_Security_Credentials", "Win32_Security_Cryptography", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_System_Console", "Win32_System_Diagnostics_Debug", "Win32_System_IO", "Win32_System_LibraryLoader", "Win32_System_Memory", "Win32_System_Pipes", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_System_WindowsProgramming", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] } + +### END HAKARI SECTION diff --git a/pkg/workspace-hack/src/lib.rs b/pkg/workspace-hack/src/lib.rs new file mode 100644 index 0000000..9ac8670 --- /dev/null +++ b/pkg/workspace-hack/src/lib.rs @@ -0,0 +1 @@ +// Workspace hack crate intentionally empty. diff --git a/pkg/zk-circuits/Cargo.toml b/pkg/zk-circuits/Cargo.toml index 422740e..d0ad2ed 100644 --- a/pkg/zk-circuits/Cargo.toml +++ b/pkg/zk-circuits/Cargo.toml @@ -1,55 +1,45 @@ [package] name = "zk-circuits" -version = "1.3.0" -edition = "2021" +version = "0.1.0" +edition = "2024" [dependencies] -smirk = { workspace = true, default-features = false, features = ["serde"] } -zk-primitives = { workspace = true, default-features = false, features = [ - "serde", -] } -primitives = { workspace = true } +barretenberg-interface = { workspace = true } -base64 = { workspace = true } -bitvec = { workspace = true } -blake2b_simd = { workspace = true } -eth-types = { workspace = true } -halo2-base = { workspace = true } -halo2-ecc = { workspace = true } -halo2_gadgets = { workspace = true } -itertools = { workspace = true } -num-bigint = { workspace = true } -poseidon-circuit = { workspace = true } -rand = { workspace = true, features = ["small_rng"] } -secp256k1 = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } -snark-verifier = { workspace = true } -snark-verifier-sdk = { workspace = true } -thiserror = { workspace = true } -uint = { workspace = true } -zkevm-circuits = { workspace = true } -borsh = { workspace = true } -wire-message = { workspace = true } -strum = { workspace = true } -strum_macros = { workspace = true } -hex = { workspace = true } -once_cell = { workspace = true } -expect-test = { workspace = true } -sha3 = { workspace = true } -bs58 = { workspace = true } +element = { workspace = true } +zk-primitives = { workspace = true } +lazy_static = { workspace = true } +hash = { workspace = true } +hash-poseidon = { workspace = true } +unimock = { workspace = true } +tempfile = { workspace = true } +acvm = { workspace = true } +bn254_blackbox_solver = { workspace = true } +nargo = { workspace = true } +noirc_abi = { workspace = true } +noirc_driver = { workspace = true } +noirc_artifacts = { workspace = true } +noir-abi-inputs-macro = { workspace = true } +serde_json = { workspace = true } +bincode = { workspace = true } +base64 = { workspace = true } +flate2 = { workspace = true } +async-trait = { workspace = true } +tokio = { workspace = true } +paste = { workspace = true } +workspace-hack.workspace = true [dev-dependencies] -ethereum-types = { workspace = true } -serde_json = { workspace = true } -benchy = { workspace = true } +smirk = { workspace = true } +barretenberg-cli = { workspace = true } +barretenberg-api-client = { workspace = true } +barretenberg-rs = { workspace = true } +url = { workspace = true } sha3 = { workspace = true } +bitvec = { workspace = true } +alloy = { workspace = true } -[features] -test = [] -default = ["test"] - -[[bench]] -name = "aggregate" -harness = false +[[bin]] +name = "vk_hash" +path = "src/bin/vk_hash.rs" diff --git a/pkg/zk-circuits/README.md b/pkg/zk-circuits/README.md deleted file mode 100644 index 22f9430..0000000 --- a/pkg/zk-circuits/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# ZK Circuits - - -## Regenerating EVM verifiers - -If the aggregate_verifier is modified (i.e. as a result of the aggregation proof being modified), then we need to EVM verifiers. - -See [Scroll's ZkEvmVerifierV1.sol](https://github.com/scroll-tech/scroll/blob/4aa5d5cd37649b26d442147e9c2b79e330ba1a2f/contracts/src/libraries/verifier/ZkEvmVerifierV1.sol#L37) code for how to call this verifier from Solidity. - - -### Aggregate - -```sh -UPDATE_EXPECT=1 cargo test "aggregate_agg::tests::generate_verifier" --release -``` - -Verifier YUL code will be generated in `pkg/zk-circuits/src/aggregate_agg/aggregate_verifier.yul`. - -```sh -solc --bin --yul pkg/zk-circuits/src/aggregate_agg/aggregate_verifier.yul | grep -E '^[0-9a-fA-F]+$' >eth/contracts/AggregateVerifier.bin -``` - -### Mint - -```sh -UPDATE_EXPECT=1 cargo test "mint::tests::generate_verifier" --release -``` - -Verifier YUL code will be generated in `pkg/zk-circuits/src/mint/mint_verifier.yul`. - -```sh -solc --bin --yul pkg/zk-circuits/src/mint/mint_verifier.yul | grep -E '^[0-9a-fA-F]+$' >eth/contracts/MintVerifier.bin -``` - -### Burn - -```sh -UPDATE_EXPECT=1 cargo test "mint::burn::generate_verifier" --release -``` - -Verifier YUL code will be generated in `pkg/zk-circuits/src/burn/burn_verifier.yul`. - -```sh -solc --bin --yul pkg/zk-circuits/src/burn/burn_verifier.yul | grep -E '^[0-9a-fA-F]+$' >eth/contracts/BurnVerifier.bin -``` - diff --git a/pkg/zk-circuits/benches/aggregate.rs b/pkg/zk-circuits/benches/aggregate.rs deleted file mode 100644 index effa961..0000000 --- a/pkg/zk-circuits/benches/aggregate.rs +++ /dev/null @@ -1,163 +0,0 @@ -use benchy::{benchmark, BenchmarkRun}; -use halo2_base::halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; -use rand::thread_rng; -use smirk::{hash_merge, Element, Tree}; -use zk_circuits::{ - aggregate_utxo::AggregateUtxo, - chips::aggregation::snark::Snark, - data::{Batch, InputNote, Insert, MerklePath, Note, SnarkWitnessV1, Utxo, UtxoKind}, - test::util::{get_params, get_snark}, - util::insecure_random_element, -}; - -const MERKLE_TREE_DEPTH: usize = 161; - -fn gen_utxo() -> (Snark, Fr, Fr) { - let k = 12; - - let pk = Element::secure_random(thread_rng()); - let from_address = hash_merge([pk, Element::ZERO]); - let to_address = insecure_random_element(); - - // Input notes - let note = Note::new(from_address, Element::from(100u64)); - let path = MerklePath::::default(); - let input_note = InputNote::new(note.clone(), pk, path.clone()); - let nullifier = input_note.nullifer(); - let input_notes = [input_note, InputNote::padding_note()]; - let recent_root = path.compute_root(note.commitment()); - - // Output notes - let output_note = Note::new(to_address, Element::from(100u64)); - let output_notes = [output_note.clone(), Note::padding_note()]; - - let circuit = Utxo::new(input_notes, output_notes, recent_root, UtxoKind::Transfer); - let instances = circuit.public_inputs(); - - // Assert this proof is valid before trying to aggregate it - let prover = MockProver::::run(k, &circuit, vec![circuit.public_inputs()]).unwrap(); - prover.assert_satisfied(); - - ( - get_snark(k, circuit, instances).unwrap(), - nullifier.into(), - output_note.commitment().into(), - ) -} - -fn utxo_to_inserts( - utxos: &[SnarkWitnessV1], -) -> [Insert; N_INSERTS] { - let mut tree = Tree::::new(); - - let (mut inserts, _old_tree, _new_tree) = { - let old_tree = tree.root_hash(); - - let mut leaves = vec![]; - - // Extract leaves to be inserted from proof - for proof in utxos { - let instances = &proof.instances[0]; - let elements = instances - .iter() - .skip(1) - .map(|f| Element::from_base(f.to_base())) - .collect::>(); - - // Skip the first instance, as that is the root - leaves.extend(elements); - } - - let paths = tree - .insert_with_paths_default(leaves.iter().copied()) - .unwrap(); - - let mut inserts = vec![]; - - // Convert paths to merkle paths - for (path, leaf) in paths.iter().zip(&leaves) { - let fpath = path - .siblings - .iter() - .cloned() - .take(MERKLE_TREE_DEPTH) - .collect::>(); - let mp: MerklePath = MerklePath::new(fpath); - let insert = Insert::new(*leaf, mp); - inserts.push(insert) - } - - let new_tree = tree.root_hash(); - - (inserts, old_tree, new_tree) - }; - - while inserts.len() < N_INSERTS { - inserts.push(Insert::padding_insert()); - } - - inserts - .try_into() - .unwrap_or_else(|_| panic!("Expected slice of length {N_INSERTS}")) -} - -fn gen_aggregate_input( -) -> ([Snark; UTXOS], Batch) { - assert_eq!(UTXOS * 4, BATCH_N); - - let mut utxos = Vec::new(); - for _ in 0..UTXOS { - utxos.push(gen_utxo().0); - } - - let inserts = utxo_to_inserts::( - &utxos - .iter() - .map(|utxo| utxo.to_witness()) - .collect::>(), - ); - - // let params = halo2_base::utils::fs::gen_srs(if BATCH_N <= 8 { 15 } else { 16 }); - (utxos.try_into().unwrap(), Batch::new(inserts)) -} - -fn aggregate(b: &mut BenchmarkRun) { - let k = 21; - - let (utxos, batch) = gen_aggregate_input::(); - let circuit = AggregateUtxo::new(utxos, batch); - - let (params, vk, pk) = get_params(k, &circuit); - let public_inputs = circuit.public_inputs(); - - let proof = b - .run(|| { - zk_circuits::proof::Proof::create( - ¶ms, - &pk, - circuit, - &[&public_inputs], - rand::thread_rng(), - ) - }) - .unwrap(); - proof.verify(&vk, ¶ms, &[&public_inputs]).unwrap(); -} - -#[benchmark] -fn aggregate_1_utxo(b: &mut BenchmarkRun) { - aggregate::<1, 4>(b); -} - -#[benchmark] -fn aggregate_2_utxo(b: &mut BenchmarkRun) { - aggregate::<2, 8>(b); -} - -// This size requires num_lookup_advice: 2, bumped from 1 -#[benchmark] -fn aggregate_3_utxo(b: &mut BenchmarkRun) { - aggregate::<3, 12>(b); -} - -benchy::main!(aggregate_1_utxo, aggregate_2_utxo, aggregate_3_utxo); diff --git a/pkg/zk-circuits/src/aggregate_agg/aggregate.rs b/pkg/zk-circuits/src/aggregate_agg/aggregate.rs deleted file mode 100644 index d7ade37..0000000 --- a/pkg/zk-circuits/src/aggregate_agg/aggregate.rs +++ /dev/null @@ -1,145 +0,0 @@ -use crate::{ - chips::aggregation::{ - aggregate::{accumulator_native, AggregationChip}, - snark::Snark, - }, - data::{AggregateAgg, ParameterSet}, - params::load_params, - util::keygen_from_params, - CircuitKind, -}; -use halo2_base::halo2_proofs::{ - circuit::{Cell, Layouter, Value}, - halo2curves::bn256::{Fr, G1Affine}, - plonk::{Column, Error, Instance, ProvingKey, VerifyingKey}, -}; -use itertools::Itertools; -use smirk::Element; - -impl AggregateAgg { - pub fn new(aggregates: [Snark; AGG_N]) -> Self { - let snarks: Vec<&Snark> = Self::snarks(&aggregates); - - let (agg_instances, proof) = accumulator_native(&snarks); - let agg_instances = agg_instances.into_iter().map(Element::from).collect(); - - Self { - aggregates, - agg_instances, - proof, - } - } - - fn snarks(utxo: &[Snark; AGG_N]) -> Vec<&Snark> { - utxo.iter().collect_vec() - } - - #[allow(clippy::too_many_arguments)] - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - instance: Column, - aggregation_chip: &AggregationChip, - ) -> Result<(), Error> { - // Gather snarks - let snarks = Self::snarks(&self.aggregates); - - // Aggregate proofs - let (agg_cells, aggregates) = aggregation_chip.aggregate( - layouter.namespace(|| "aggregate"), - &snarks, - Value::known(&self.proof), - )?; - - // Constrain verify aggregation cells to public inputs - for (i, cell) in agg_cells.iter().enumerate() { - layouter.constrain_instance(*cell, instance, i)?; - } - - let old_root = aggregates[0][0][12]; - let mut last_new_root = old_root; - let mut recent_roots: Vec = vec![]; - - // Prove new root is next old root - for agg in aggregates { - let old_root = agg[0][12]; - let new_root = agg[0][13]; - recent_roots.extend(agg[0][14..].iter()); - - // Check that the old root is the same as the last new root - layouter.assign_region( - || "constrain roots", - |mut region| region.constrain_equal(last_new_root, old_root), - )?; - - last_new_root = new_root; - } - - // Constrain old root - layouter.constrain_instance(old_root, instance, 12)?; - - // Constrain new root - layouter.constrain_instance(last_new_root, instance, 13)?; - - // Constraint recent roots (pass through) - for (i, recent_root) in recent_roots.iter().enumerate() { - layouter.constrain_instance(*recent_root, instance, 14 + i)?; - } - - Ok(()) - } - - // TODO: we should use a typed system for extracting cells from the snark instances - pub fn public_inputs(&self) -> Vec { - let mut instances = vec![]; - - // Add verify instances (12) - instances.extend(self.agg_instances.iter().copied().map(Fr::from)); - - // Add old root (1) - instances.push(*self.old_root()); - - // Add new root (1) - instances.push(*self.new_root()); - - // UTXO values (recent root, mint/burn hash, mint/burn value) (= 3 per UTXO) - instances.extend(self.utxo_values()); - - instances - } - - pub fn agg_instances(&self) -> &Vec { - &self.agg_instances - } - - pub fn old_root(&self) -> &Fr { - &self.aggregates[0].instances[0][12] - } - - pub fn new_root(&self) -> &Fr { - &self.aggregates.iter().last().unwrap().instances[0][13] - } - - pub fn utxo_values(&self) -> Vec { - self.aggregates - .iter() - .flat_map(|snark| &snark.instances[0][14..]) - .copied() - .collect_vec() - } - - pub fn snark(&self, params: ParameterSet) -> Result { - let pk = CircuitKind::AggAgg.pk(); - Snark::create( - self.clone(), - vec![self.public_inputs()], - load_params(params), - pk, - ) - .map_err(crate::Error::err) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} diff --git a/pkg/zk-circuits/src/aggregate_agg/aggregate_verifier.yul b/pkg/zk-circuits/src/aggregate_agg/aggregate_verifier.yul deleted file mode 100644 index bb2c3d2..0000000 --- a/pkg/zk-circuits/src/aggregate_agg/aggregate_verifier.yul +++ /dev/null @@ -1,2022 +0,0 @@ - - object "plonk_verifier" { - code { - function allocate(size) -> ptr { - ptr := mload(0x40) - if eq(ptr, 0) { ptr := 0x60 } - mstore(0x40, add(ptr, size)) - } - let size := datasize("Runtime") - let offset := allocate(size) - datacopy(offset, dataoffset("Runtime"), size) - return(offset, size) - } - object "Runtime" { - code { - let success:bool := true - let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - function validate_ec_point(x, y) -> valid:bool { - { - let x_lt_p:bool := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_lt_p:bool := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - valid := and(x_lt_p, y_lt_p) - } - { - let x_is_zero:bool := eq(x, 0) - let y_is_zero:bool := eq(y, 0) - let x_or_y_is_zero:bool := or(x_is_zero, y_is_zero) - let x_and_y_is_not_zero:bool := not(x_or_y_is_zero) - valid := and(x_and_y_is_not_zero, valid) - } - { - let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube := mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube_plus_3 := addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_square_eq_x_cube_plus_3:bool := eq(x_cube_plus_3, y_square) - valid := and(y_square_eq_x_cube_plus_3, valid) - } - } - mstore(0x20, mod(calldataload(0x0), f_q)) -mstore(0x40, mod(calldataload(0x20), f_q)) -mstore(0x60, mod(calldataload(0x40), f_q)) -mstore(0x80, mod(calldataload(0x60), f_q)) -mstore(0xa0, mod(calldataload(0x80), f_q)) -mstore(0xc0, mod(calldataload(0xa0), f_q)) -mstore(0xe0, mod(calldataload(0xc0), f_q)) -mstore(0x100, mod(calldataload(0xe0), f_q)) -mstore(0x120, mod(calldataload(0x100), f_q)) -mstore(0x140, mod(calldataload(0x120), f_q)) -mstore(0x160, mod(calldataload(0x140), f_q)) -mstore(0x180, mod(calldataload(0x160), f_q)) -mstore(0x1a0, mod(calldataload(0x180), f_q)) -mstore(0x1c0, mod(calldataload(0x1a0), f_q)) -mstore(0x1e0, mod(calldataload(0x1c0), f_q)) -mstore(0x200, mod(calldataload(0x1e0), f_q)) -mstore(0x220, mod(calldataload(0x200), f_q)) -mstore(0x240, mod(calldataload(0x220), f_q)) -mstore(0x260, mod(calldataload(0x240), f_q)) -mstore(0x280, mod(calldataload(0x260), f_q)) -mstore(0x2a0, mod(calldataload(0x280), f_q)) -mstore(0x2c0, mod(calldataload(0x2a0), f_q)) -mstore(0x2e0, mod(calldataload(0x2c0), f_q)) -mstore(0x300, mod(calldataload(0x2e0), f_q)) -mstore(0x320, mod(calldataload(0x300), f_q)) -mstore(0x340, mod(calldataload(0x320), f_q)) -mstore(0x360, mod(calldataload(0x340), f_q)) -mstore(0x380, mod(calldataload(0x360), f_q)) -mstore(0x3a0, mod(calldataload(0x380), f_q)) -mstore(0x3c0, mod(calldataload(0x3a0), f_q)) -mstore(0x3e0, mod(calldataload(0x3c0), f_q)) -mstore(0x400, mod(calldataload(0x3e0), f_q)) -mstore(0x0, 8860187075162106536466745194526099750237620018716400003177853599183775300133) - - { - let x := calldataload(0x400) - mstore(0x420, x) - let y := calldataload(0x420) - mstore(0x440, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x440) - mstore(0x460, x) - let y := calldataload(0x460) - mstore(0x480, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x480) - mstore(0x4a0, x) - let y := calldataload(0x4a0) - mstore(0x4c0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x4c0) - mstore(0x4e0, x) - let y := calldataload(0x4e0) - mstore(0x500, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x500) - mstore(0x520, x) - let y := calldataload(0x520) - mstore(0x540, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x540) - mstore(0x560, x) - let y := calldataload(0x560) - mstore(0x580, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x580) - mstore(0x5a0, x) - let y := calldataload(0x5a0) - mstore(0x5c0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x5e0, keccak256(0x0, 1504)) -{ - let hash := mload(0x5e0) - mstore(0x600, mod(hash, f_q)) - mstore(0x620, hash) - } - - { - let x := calldataload(0x5c0) - mstore(0x640, x) - let y := calldataload(0x5e0) - mstore(0x660, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x600) - mstore(0x680, x) - let y := calldataload(0x620) - mstore(0x6a0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x6c0, keccak256(0x620, 160)) -{ - let hash := mload(0x6c0) - mstore(0x6e0, mod(hash, f_q)) - mstore(0x700, hash) - } -mstore8(1824, 1) -mstore(0x720, keccak256(0x700, 33)) -{ - let hash := mload(0x720) - mstore(0x740, mod(hash, f_q)) - mstore(0x760, hash) - } - - { - let x := calldataload(0x640) - mstore(0x780, x) - let y := calldataload(0x660) - mstore(0x7a0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x680) - mstore(0x7c0, x) - let y := calldataload(0x6a0) - mstore(0x7e0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x6c0) - mstore(0x800, x) - let y := calldataload(0x6e0) - mstore(0x820, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x700) - mstore(0x840, x) - let y := calldataload(0x720) - mstore(0x860, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x740) - mstore(0x880, x) - let y := calldataload(0x760) - mstore(0x8a0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x780) - mstore(0x8c0, x) - let y := calldataload(0x7a0) - mstore(0x8e0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x7c0) - mstore(0x900, x) - let y := calldataload(0x7e0) - mstore(0x920, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x940, keccak256(0x760, 480)) -{ - let hash := mload(0x940) - mstore(0x960, mod(hash, f_q)) - mstore(0x980, hash) - } - - { - let x := calldataload(0x800) - mstore(0x9a0, x) - let y := calldataload(0x820) - mstore(0x9c0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x840) - mstore(0x9e0, x) - let y := calldataload(0x860) - mstore(0xa00, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x880) - mstore(0xa20, x) - let y := calldataload(0x8a0) - mstore(0xa40, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0xa60, keccak256(0x980, 224)) -{ - let hash := mload(0xa60) - mstore(0xa80, mod(hash, f_q)) - mstore(0xaa0, hash) - } -mstore(0xac0, mod(calldataload(0x8c0), f_q)) -mstore(0xae0, mod(calldataload(0x8e0), f_q)) -mstore(0xb00, mod(calldataload(0x900), f_q)) -mstore(0xb20, mod(calldataload(0x920), f_q)) -mstore(0xb40, mod(calldataload(0x940), f_q)) -mstore(0xb60, mod(calldataload(0x960), f_q)) -mstore(0xb80, mod(calldataload(0x980), f_q)) -mstore(0xba0, mod(calldataload(0x9a0), f_q)) -mstore(0xbc0, mod(calldataload(0x9c0), f_q)) -mstore(0xbe0, mod(calldataload(0x9e0), f_q)) -mstore(0xc00, mod(calldataload(0xa00), f_q)) -mstore(0xc20, mod(calldataload(0xa20), f_q)) -mstore(0xc40, mod(calldataload(0xa40), f_q)) -mstore(0xc60, mod(calldataload(0xa60), f_q)) -mstore(0xc80, mod(calldataload(0xa80), f_q)) -mstore(0xca0, mod(calldataload(0xaa0), f_q)) -mstore(0xcc0, mod(calldataload(0xac0), f_q)) -mstore(0xce0, mod(calldataload(0xae0), f_q)) -mstore(0xd00, mod(calldataload(0xb00), f_q)) -mstore(0xd20, mod(calldataload(0xb20), f_q)) -mstore(0xd40, mod(calldataload(0xb40), f_q)) -mstore(0xd60, mod(calldataload(0xb60), f_q)) -mstore(0xd80, mod(calldataload(0xb80), f_q)) -mstore(0xda0, mod(calldataload(0xba0), f_q)) -mstore(0xdc0, mod(calldataload(0xbc0), f_q)) -mstore(0xde0, mod(calldataload(0xbe0), f_q)) -mstore(0xe00, mod(calldataload(0xc00), f_q)) -mstore(0xe20, mod(calldataload(0xc20), f_q)) -mstore(0xe40, mod(calldataload(0xc40), f_q)) -mstore(0xe60, mod(calldataload(0xc60), f_q)) -mstore(0xe80, mod(calldataload(0xc80), f_q)) -mstore(0xea0, mod(calldataload(0xca0), f_q)) -mstore(0xec0, mod(calldataload(0xcc0), f_q)) -mstore(0xee0, mod(calldataload(0xce0), f_q)) -mstore(0xf00, mod(calldataload(0xd00), f_q)) -mstore(0xf20, mod(calldataload(0xd20), f_q)) -mstore(0xf40, mod(calldataload(0xd40), f_q)) -mstore(0xf60, mod(calldataload(0xd60), f_q)) -mstore(0xf80, mod(calldataload(0xd80), f_q)) -mstore(0xfa0, mod(calldataload(0xda0), f_q)) -mstore(0xfc0, mod(calldataload(0xdc0), f_q)) -mstore(0xfe0, mod(calldataload(0xde0), f_q)) -mstore(0x1000, mod(calldataload(0xe00), f_q)) -mstore(0x1020, mod(calldataload(0xe20), f_q)) -mstore(0x1040, mod(calldataload(0xe40), f_q)) -mstore(0x1060, mod(calldataload(0xe60), f_q)) -mstore(0x1080, mod(calldataload(0xe80), f_q)) -mstore(0x10a0, mod(calldataload(0xea0), f_q)) -mstore(0x10c0, mod(calldataload(0xec0), f_q)) -mstore(0x10e0, mod(calldataload(0xee0), f_q)) -mstore(0x1100, mod(calldataload(0xf00), f_q)) -mstore(0x1120, mod(calldataload(0xf20), f_q)) -mstore(0x1140, mod(calldataload(0xf40), f_q)) -mstore(0x1160, mod(calldataload(0xf60), f_q)) -mstore(0x1180, mod(calldataload(0xf80), f_q)) -mstore(0x11a0, mod(calldataload(0xfa0), f_q)) -mstore(0x11c0, mod(calldataload(0xfc0), f_q)) -mstore(0x11e0, mod(calldataload(0xfe0), f_q)) -mstore(0x1200, mod(calldataload(0x1000), f_q)) -mstore(0x1220, mod(calldataload(0x1020), f_q)) -mstore(0x1240, mod(calldataload(0x1040), f_q)) -mstore(0x1260, mod(calldataload(0x1060), f_q)) -mstore(0x1280, keccak256(0xaa0, 2016)) -{ - let hash := mload(0x1280) - mstore(0x12a0, mod(hash, f_q)) - mstore(0x12c0, hash) - } -mstore8(4832, 1) -mstore(0x12e0, keccak256(0x12c0, 33)) -{ - let hash := mload(0x12e0) - mstore(0x1300, mod(hash, f_q)) - mstore(0x1320, hash) - } - - { - let x := calldataload(0x1080) - mstore(0x1340, x) - let y := calldataload(0x10a0) - mstore(0x1360, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x1380, keccak256(0x1320, 96)) -{ - let hash := mload(0x1380) - mstore(0x13a0, mod(hash, f_q)) - mstore(0x13c0, hash) - } - - { - let x := calldataload(0x10c0) - mstore(0x13e0, x) - let y := calldataload(0x10e0) - mstore(0x1400, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x1420, mulmod(mload(0xa80), mload(0xa80), f_q)) -mstore(0x1440, mulmod(mload(0x1420), mload(0x1420), f_q)) -mstore(0x1460, mulmod(mload(0x1440), mload(0x1440), f_q)) -mstore(0x1480, mulmod(mload(0x1460), mload(0x1460), f_q)) -mstore(0x14a0, mulmod(mload(0x1480), mload(0x1480), f_q)) -mstore(0x14c0, mulmod(mload(0x14a0), mload(0x14a0), f_q)) -mstore(0x14e0, mulmod(mload(0x14c0), mload(0x14c0), f_q)) -mstore(0x1500, mulmod(mload(0x14e0), mload(0x14e0), f_q)) -mstore(0x1520, mulmod(mload(0x1500), mload(0x1500), f_q)) -mstore(0x1540, mulmod(mload(0x1520), mload(0x1520), f_q)) -mstore(0x1560, mulmod(mload(0x1540), mload(0x1540), f_q)) -mstore(0x1580, mulmod(mload(0x1560), mload(0x1560), f_q)) -mstore(0x15a0, mulmod(mload(0x1580), mload(0x1580), f_q)) -mstore(0x15c0, mulmod(mload(0x15a0), mload(0x15a0), f_q)) -mstore(0x15e0, mulmod(mload(0x15c0), mload(0x15c0), f_q)) -mstore(0x1600, mulmod(mload(0x15e0), mload(0x15e0), f_q)) -mstore(0x1620, mulmod(mload(0x1600), mload(0x1600), f_q)) -mstore(0x1640, mulmod(mload(0x1620), mload(0x1620), f_q)) -mstore(0x1660, mulmod(mload(0x1640), mload(0x1640), f_q)) -mstore(0x1680, mulmod(mload(0x1660), mload(0x1660), f_q)) -mstore(0x16a0, mulmod(mload(0x1680), mload(0x1680), f_q)) -mstore(0x16c0, addmod(mload(0x16a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0x16e0, mulmod(mload(0x16c0), 21888232434711746154598842647110004286396165347431605739555851272621938401409, f_q)) -mstore(0x1700, mulmod(mload(0x16e0), 20975929243409798062839949658616274858986091382510192949221301676705706354487, f_q)) -mstore(0x1720, addmod(mload(0xa80), 912313628429477159406456086641000229562273017905841394476902509870102141130, f_q)) -mstore(0x1740, mulmod(mload(0x16e0), 495188420091111145957709789221178673495499187437761988132837836548330853701, f_q)) -mstore(0x1760, addmod(mload(0xa80), 21393054451748164076288695956036096415052865212978272355565366350027477641916, f_q)) -mstore(0x1780, mulmod(mload(0x16e0), 16064522944768515290584536219762686197737451920702130080538975732575755569557, f_q)) -mstore(0x17a0, addmod(mload(0xa80), 5823719927070759931661869525494588890810912479713904263159228454000052926060, f_q)) -mstore(0x17c0, mulmod(mload(0x16e0), 14686510910986211321976396297238126901237973400949744736326777596334651355305, f_q)) -mstore(0x17e0, addmod(mload(0xa80), 7201731960853063900270009448019148187310390999466289607371426590241157140312, f_q)) -mstore(0x1800, mulmod(mload(0x16e0), 10939663269433627367777756708678102241564365262857670666700619874077960926249, f_q)) -mstore(0x1820, addmod(mload(0xa80), 10948579602405647854468649036579172846983999137558363676997584312497847569368, f_q)) -mstore(0x1840, mulmod(mload(0x16e0), 15402826414547299628414612080036060696555554914079673875872749760617770134879, f_q)) -mstore(0x1860, addmod(mload(0xa80), 6485416457291975593831793665221214391992809486336360467825454425958038360738, f_q)) -mstore(0x1880, mulmod(mload(0x16e0), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q)) -mstore(0x18a0, addmod(mload(0xa80), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q)) -mstore(0x18c0, mulmod(mload(0x16e0), 1, f_q)) -mstore(0x18e0, addmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0x1900, mulmod(mload(0x16e0), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) -mstore(0x1920, addmod(mload(0xa80), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q)) -mstore(0x1940, mulmod(mload(0x16e0), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q)) -mstore(0x1960, addmod(mload(0xa80), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q)) -mstore(0x1980, mulmod(mload(0x16e0), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q)) -mstore(0x19a0, addmod(mload(0xa80), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q)) -mstore(0x19c0, mulmod(mload(0x16e0), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q)) -mstore(0x19e0, addmod(mload(0xa80), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q)) -mstore(0x1a00, mulmod(mload(0x16e0), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q)) -mstore(0x1a20, addmod(mload(0xa80), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q)) -mstore(0x1a40, mulmod(mload(0x16e0), 9697063347556872083384215826199993067635178715531258559890418744774301211662, f_q)) -mstore(0x1a60, addmod(mload(0xa80), 12191179524282403138862189919057282020913185684884775783807785441801507283955, f_q)) -mstore(0x1a80, mulmod(mload(0x16e0), 12459868075641381822485233712013080087763946065665469821362892189399541605692, f_q)) -mstore(0x1aa0, addmod(mload(0xa80), 9428374796197893399761172033244195000784418334750564522335311997176266889925, f_q)) -mstore(0x1ac0, mulmod(mload(0x16e0), 6955697244493336113861667751840378876927906302623587437721024018233754910398, f_q)) -mstore(0x1ae0, addmod(mload(0xa80), 14932545627345939108384737993416896211620458097792446905977180168342053585219, f_q)) -mstore(0x1b00, mulmod(mload(0x16e0), 20345677989844117909528750049476969581182118546166966482506114734614108237981, f_q)) -mstore(0x1b20, addmod(mload(0xa80), 1542564881995157312717655695780305507366245854249067861192089451961700257636, f_q)) -mstore(0x1b40, mulmod(mload(0x16e0), 5289443209903185443361862148540090689648485914368835830972895623576469023722, f_q)) -mstore(0x1b60, addmod(mload(0xa80), 16598799661936089778884543596717184398899878486047198512725308562999339471895, f_q)) -mstore(0x1b80, mulmod(mload(0x16e0), 557567375339945239933617516585967620814823575807691402619711360028043331811, f_q)) -mstore(0x1ba0, addmod(mload(0xa80), 21330675496499329982312788228671307467733540824608342941078492826547765163806, f_q)) -mstore(0x1bc0, mulmod(mload(0x16e0), 4509404676247677387317362072810231899718070082381452255950861037254608304934, f_q)) -mstore(0x1be0, addmod(mload(0xa80), 17378838195591597834929043672447043188830294318034582087747343149321200190683, f_q)) -mstore(0x1c00, mulmod(mload(0x16e0), 20169013865622130318472103510465966222180994822334426398191891983290742724178, f_q)) -mstore(0x1c20, addmod(mload(0xa80), 1719229006217144903774302234791308866367369578081607945506312203285065771439, f_q)) -mstore(0x1c40, mulmod(mload(0x16e0), 2579947959091681244170407980400327834520881737801886423874592072501514087543, f_q)) -mstore(0x1c60, addmod(mload(0xa80), 19308294912747593978075997764856947254027482662614147919823612114074294408074, f_q)) -mstore(0x1c80, mulmod(mload(0x16e0), 1881761935718519990121799628252273658786792458106649887437395059872945867717, f_q)) -mstore(0x1ca0, addmod(mload(0xa80), 20006480936120755232124606117005001429761571942309384456260809126702862627900, f_q)) -mstore(0x1cc0, mulmod(mload(0x16e0), 21846745818185811051373434299876022191132089169516983080959277716660228899818, f_q)) -mstore(0x1ce0, addmod(mload(0xa80), 41497053653464170872971445381252897416275230899051262738926469915579595799, f_q)) -mstore(0x1d00, mulmod(mload(0x16e0), 13018529307372270489258244406856841315962482733096074798317807775255504614069, f_q)) -mstore(0x1d20, addmod(mload(0xa80), 8869713564467004732988161338400433772585881667319959545380396411320303881548, f_q)) -mstore(0x1d40, mulmod(mload(0x16e0), 1459528961030896569807206253631725410868595642414057264270714861278164633285, f_q)) -mstore(0x1d60, addmod(mload(0xa80), 20428713910808378652439199491625549677679768758001977079427489325297643862332, f_q)) -mstore(0x1d80, mulmod(mload(0x16e0), 3090451643741879200285099477849831179472024364989630500355756836624424014697, f_q)) -mstore(0x1da0, addmod(mload(0xa80), 18797791228097396021961306267407443909076340035426403843342447349951384480920, f_q)) -mstore(0x1dc0, mulmod(mload(0x16e0), 21594472933355353940227302948201802990541640451776958309590170926766063614527, f_q)) -mstore(0x1de0, addmod(mload(0xa80), 293769938483921282019102797055472098006723948639076034108033259809744881090, f_q)) -mstore(0x1e00, mulmod(mload(0x16e0), 15233875724801927436678555222002139405060841628305391430751578735629430475003, f_q)) -mstore(0x1e20, addmod(mload(0xa80), 6654367147037347785567850523255135683487522772110642912946625450946378020614, f_q)) -mstore(0x1e40, mulmod(mload(0x16e0), 9228489335593836417731216695316971397516686186585289059470421738439643366942, f_q)) -mstore(0x1e60, addmod(mload(0xa80), 12659753536245438804515189049940303691031678213830745284227782448136165128675, f_q)) -mstore(0x1e80, mulmod(mload(0x16e0), 3995919348991837205145968657202036478264857555951392348803092712948091309793, f_q)) -mstore(0x1ea0, addmod(mload(0xa80), 17892323522847438017100437088055238610283506844464641994895111473627717185824, f_q)) -mstore(0x1ec0, mulmod(mload(0x16e0), 13526759757306252939732186602630155490343117803221487512984160143178057306805, f_q)) -mstore(0x1ee0, addmod(mload(0xa80), 8361483114533022282514219142627119598205246597194546830714044043397751188812, f_q)) -mstore(0x1f00, mulmod(mload(0x16e0), 16872061813506464818966731303749201041171378844856965745877263150794549664761, f_q)) -mstore(0x1f20, addmod(mload(0xa80), 5016181058332810403279674441508074047376985555559068597820941035781258830856, f_q)) -mstore(0x1f40, mulmod(mload(0x16e0), 16722112256235738599640138637711059524347378135686596767512885208913020182609, f_q)) -mstore(0x1f60, addmod(mload(0xa80), 5166130615603536622606267107546215564200986264729437576185318977662788313008, f_q)) -mstore(0x1f80, mulmod(mload(0x16e0), 1090429695315567589994397636958424176325357300588701546801508770738211219865, f_q)) -mstore(0x1fa0, addmod(mload(0xa80), 20797813176523707632252008108298850912223007099827332796896695415837597275752, f_q)) -mstore(0x1fc0, mulmod(mload(0x16e0), 13098481875020205420942233016824212164786287930169045450599302794675261377069, f_q)) -mstore(0x1fe0, addmod(mload(0xa80), 8789760996819069801304172728433062923762076470246988893098901391900547118548, f_q)) -mstore(0x2000, mulmod(mload(0x16e0), 14888729180837150747383544491700106534035081718079253803389148494695024292715, f_q)) -mstore(0x2020, addmod(mload(0xa80), 6999513691002124474862861253557168554513282682336780540309055691880784202902, f_q)) -mstore(0x2040, mulmod(mload(0x16e0), 11377070488770263259987342577173204149358055510182982082489928583535951905289, f_q)) -mstore(0x2060, addmod(mload(0xa80), 10511172383069011962259063168084070939190308890233052261208275603039856590328, f_q)) -mstore(0x2080, mulmod(mload(0x16e0), 11748242721932305273763667649430430511617294288466722020869673941162436296085, f_q)) -mstore(0x20a0, addmod(mload(0xa80), 10140000149906969948482738095826844576931070111949312322828530245413372199532, f_q)) -{ - let prod := mload(0x1720) - - prod := mulmod(mload(0x1760), prod, f_q) - mstore(0x20c0, prod) - - prod := mulmod(mload(0x17a0), prod, f_q) - mstore(0x20e0, prod) - - prod := mulmod(mload(0x17e0), prod, f_q) - mstore(0x2100, prod) - - prod := mulmod(mload(0x1820), prod, f_q) - mstore(0x2120, prod) - - prod := mulmod(mload(0x1860), prod, f_q) - mstore(0x2140, prod) - - prod := mulmod(mload(0x18a0), prod, f_q) - mstore(0x2160, prod) - - prod := mulmod(mload(0x18e0), prod, f_q) - mstore(0x2180, prod) - - prod := mulmod(mload(0x1920), prod, f_q) - mstore(0x21a0, prod) - - prod := mulmod(mload(0x1960), prod, f_q) - mstore(0x21c0, prod) - - prod := mulmod(mload(0x19a0), prod, f_q) - mstore(0x21e0, prod) - - prod := mulmod(mload(0x19e0), prod, f_q) - mstore(0x2200, prod) - - prod := mulmod(mload(0x1a20), prod, f_q) - mstore(0x2220, prod) - - prod := mulmod(mload(0x1a60), prod, f_q) - mstore(0x2240, prod) - - prod := mulmod(mload(0x1aa0), prod, f_q) - mstore(0x2260, prod) - - prod := mulmod(mload(0x1ae0), prod, f_q) - mstore(0x2280, prod) - - prod := mulmod(mload(0x1b20), prod, f_q) - mstore(0x22a0, prod) - - prod := mulmod(mload(0x1b60), prod, f_q) - mstore(0x22c0, prod) - - prod := mulmod(mload(0x1ba0), prod, f_q) - mstore(0x22e0, prod) - - prod := mulmod(mload(0x1be0), prod, f_q) - mstore(0x2300, prod) - - prod := mulmod(mload(0x1c20), prod, f_q) - mstore(0x2320, prod) - - prod := mulmod(mload(0x1c60), prod, f_q) - mstore(0x2340, prod) - - prod := mulmod(mload(0x1ca0), prod, f_q) - mstore(0x2360, prod) - - prod := mulmod(mload(0x1ce0), prod, f_q) - mstore(0x2380, prod) - - prod := mulmod(mload(0x1d20), prod, f_q) - mstore(0x23a0, prod) - - prod := mulmod(mload(0x1d60), prod, f_q) - mstore(0x23c0, prod) - - prod := mulmod(mload(0x1da0), prod, f_q) - mstore(0x23e0, prod) - - prod := mulmod(mload(0x1de0), prod, f_q) - mstore(0x2400, prod) - - prod := mulmod(mload(0x1e20), prod, f_q) - mstore(0x2420, prod) - - prod := mulmod(mload(0x1e60), prod, f_q) - mstore(0x2440, prod) - - prod := mulmod(mload(0x1ea0), prod, f_q) - mstore(0x2460, prod) - - prod := mulmod(mload(0x1ee0), prod, f_q) - mstore(0x2480, prod) - - prod := mulmod(mload(0x1f20), prod, f_q) - mstore(0x24a0, prod) - - prod := mulmod(mload(0x1f60), prod, f_q) - mstore(0x24c0, prod) - - prod := mulmod(mload(0x1fa0), prod, f_q) - mstore(0x24e0, prod) - - prod := mulmod(mload(0x1fe0), prod, f_q) - mstore(0x2500, prod) - - prod := mulmod(mload(0x2020), prod, f_q) - mstore(0x2520, prod) - - prod := mulmod(mload(0x2060), prod, f_q) - mstore(0x2540, prod) - - prod := mulmod(mload(0x20a0), prod, f_q) - mstore(0x2560, prod) - - prod := mulmod(mload(0x16c0), prod, f_q) - mstore(0x2580, prod) - - } -mstore(0x25c0, 32) -mstore(0x25e0, 32) -mstore(0x2600, 32) -mstore(0x2620, mload(0x2580)) -mstore(0x2640, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x2660, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x25c0, 0xc0, 0x25a0, 0x20), 1), success) -{ - - let inv := mload(0x25a0) - let v - - v := mload(0x16c0) - mstore(5824, mulmod(mload(0x2560), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x20a0) - mstore(8352, mulmod(mload(0x2540), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2060) - mstore(8288, mulmod(mload(0x2520), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x2020) - mstore(8224, mulmod(mload(0x2500), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1fe0) - mstore(8160, mulmod(mload(0x24e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1fa0) - mstore(8096, mulmod(mload(0x24c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1f60) - mstore(8032, mulmod(mload(0x24a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1f20) - mstore(7968, mulmod(mload(0x2480), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ee0) - mstore(7904, mulmod(mload(0x2460), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ea0) - mstore(7840, mulmod(mload(0x2440), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1e60) - mstore(7776, mulmod(mload(0x2420), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1e20) - mstore(7712, mulmod(mload(0x2400), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1de0) - mstore(7648, mulmod(mload(0x23e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1da0) - mstore(7584, mulmod(mload(0x23c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1d60) - mstore(7520, mulmod(mload(0x23a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1d20) - mstore(7456, mulmod(mload(0x2380), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ce0) - mstore(7392, mulmod(mload(0x2360), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ca0) - mstore(7328, mulmod(mload(0x2340), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1c60) - mstore(7264, mulmod(mload(0x2320), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1c20) - mstore(7200, mulmod(mload(0x2300), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1be0) - mstore(7136, mulmod(mload(0x22e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ba0) - mstore(7072, mulmod(mload(0x22c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1b60) - mstore(7008, mulmod(mload(0x22a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1b20) - mstore(6944, mulmod(mload(0x2280), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1ae0) - mstore(6880, mulmod(mload(0x2260), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1aa0) - mstore(6816, mulmod(mload(0x2240), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1a60) - mstore(6752, mulmod(mload(0x2220), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1a20) - mstore(6688, mulmod(mload(0x2200), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x19e0) - mstore(6624, mulmod(mload(0x21e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x19a0) - mstore(6560, mulmod(mload(0x21c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1960) - mstore(6496, mulmod(mload(0x21a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1920) - mstore(6432, mulmod(mload(0x2180), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x18e0) - mstore(6368, mulmod(mload(0x2160), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x18a0) - mstore(6304, mulmod(mload(0x2140), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1860) - mstore(6240, mulmod(mload(0x2120), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1820) - mstore(6176, mulmod(mload(0x2100), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x17e0) - mstore(6112, mulmod(mload(0x20e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x17a0) - mstore(6048, mulmod(mload(0x20c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1760) - mstore(5984, mulmod(mload(0x1720), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x1720, inv) - - } -mstore(0x2680, mulmod(mload(0x1700), mload(0x1720), f_q)) -mstore(0x26a0, mulmod(mload(0x1740), mload(0x1760), f_q)) -mstore(0x26c0, mulmod(mload(0x1780), mload(0x17a0), f_q)) -mstore(0x26e0, mulmod(mload(0x17c0), mload(0x17e0), f_q)) -mstore(0x2700, mulmod(mload(0x1800), mload(0x1820), f_q)) -mstore(0x2720, mulmod(mload(0x1840), mload(0x1860), f_q)) -mstore(0x2740, mulmod(mload(0x1880), mload(0x18a0), f_q)) -mstore(0x2760, mulmod(mload(0x18c0), mload(0x18e0), f_q)) -mstore(0x2780, mulmod(mload(0x1900), mload(0x1920), f_q)) -mstore(0x27a0, mulmod(mload(0x1940), mload(0x1960), f_q)) -mstore(0x27c0, mulmod(mload(0x1980), mload(0x19a0), f_q)) -mstore(0x27e0, mulmod(mload(0x19c0), mload(0x19e0), f_q)) -mstore(0x2800, mulmod(mload(0x1a00), mload(0x1a20), f_q)) -mstore(0x2820, mulmod(mload(0x1a40), mload(0x1a60), f_q)) -mstore(0x2840, mulmod(mload(0x1a80), mload(0x1aa0), f_q)) -mstore(0x2860, mulmod(mload(0x1ac0), mload(0x1ae0), f_q)) -mstore(0x2880, mulmod(mload(0x1b00), mload(0x1b20), f_q)) -mstore(0x28a0, mulmod(mload(0x1b40), mload(0x1b60), f_q)) -mstore(0x28c0, mulmod(mload(0x1b80), mload(0x1ba0), f_q)) -mstore(0x28e0, mulmod(mload(0x1bc0), mload(0x1be0), f_q)) -mstore(0x2900, mulmod(mload(0x1c00), mload(0x1c20), f_q)) -mstore(0x2920, mulmod(mload(0x1c40), mload(0x1c60), f_q)) -mstore(0x2940, mulmod(mload(0x1c80), mload(0x1ca0), f_q)) -mstore(0x2960, mulmod(mload(0x1cc0), mload(0x1ce0), f_q)) -mstore(0x2980, mulmod(mload(0x1d00), mload(0x1d20), f_q)) -mstore(0x29a0, mulmod(mload(0x1d40), mload(0x1d60), f_q)) -mstore(0x29c0, mulmod(mload(0x1d80), mload(0x1da0), f_q)) -mstore(0x29e0, mulmod(mload(0x1dc0), mload(0x1de0), f_q)) -mstore(0x2a00, mulmod(mload(0x1e00), mload(0x1e20), f_q)) -mstore(0x2a20, mulmod(mload(0x1e40), mload(0x1e60), f_q)) -mstore(0x2a40, mulmod(mload(0x1e80), mload(0x1ea0), f_q)) -mstore(0x2a60, mulmod(mload(0x1ec0), mload(0x1ee0), f_q)) -mstore(0x2a80, mulmod(mload(0x1f00), mload(0x1f20), f_q)) -mstore(0x2aa0, mulmod(mload(0x1f40), mload(0x1f60), f_q)) -mstore(0x2ac0, mulmod(mload(0x1f80), mload(0x1fa0), f_q)) -mstore(0x2ae0, mulmod(mload(0x1fc0), mload(0x1fe0), f_q)) -mstore(0x2b00, mulmod(mload(0x2000), mload(0x2020), f_q)) -mstore(0x2b20, mulmod(mload(0x2040), mload(0x2060), f_q)) -mstore(0x2b40, mulmod(mload(0x2080), mload(0x20a0), f_q)) -{ - let result := mulmod(mload(0x2760), mload(0x20), f_q) -result := addmod(mulmod(mload(0x2780), mload(0x40), f_q), result, f_q) -result := addmod(mulmod(mload(0x27a0), mload(0x60), f_q), result, f_q) -result := addmod(mulmod(mload(0x27c0), mload(0x80), f_q), result, f_q) -result := addmod(mulmod(mload(0x27e0), mload(0xa0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2800), mload(0xc0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2820), mload(0xe0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2840), mload(0x100), f_q), result, f_q) -result := addmod(mulmod(mload(0x2860), mload(0x120), f_q), result, f_q) -result := addmod(mulmod(mload(0x2880), mload(0x140), f_q), result, f_q) -result := addmod(mulmod(mload(0x28a0), mload(0x160), f_q), result, f_q) -result := addmod(mulmod(mload(0x28c0), mload(0x180), f_q), result, f_q) -result := addmod(mulmod(mload(0x28e0), mload(0x1a0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2900), mload(0x1c0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2920), mload(0x1e0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2940), mload(0x200), f_q), result, f_q) -result := addmod(mulmod(mload(0x2960), mload(0x220), f_q), result, f_q) -result := addmod(mulmod(mload(0x2980), mload(0x240), f_q), result, f_q) -result := addmod(mulmod(mload(0x29a0), mload(0x260), f_q), result, f_q) -result := addmod(mulmod(mload(0x29c0), mload(0x280), f_q), result, f_q) -result := addmod(mulmod(mload(0x29e0), mload(0x2a0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2a00), mload(0x2c0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2a20), mload(0x2e0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2a40), mload(0x300), f_q), result, f_q) -result := addmod(mulmod(mload(0x2a60), mload(0x320), f_q), result, f_q) -result := addmod(mulmod(mload(0x2a80), mload(0x340), f_q), result, f_q) -result := addmod(mulmod(mload(0x2aa0), mload(0x360), f_q), result, f_q) -result := addmod(mulmod(mload(0x2ac0), mload(0x380), f_q), result, f_q) -result := addmod(mulmod(mload(0x2ae0), mload(0x3a0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2b00), mload(0x3c0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2b20), mload(0x3e0), f_q), result, f_q) -result := addmod(mulmod(mload(0x2b40), mload(0x400), f_q), result, f_q) -mstore(11104, result) - } -mstore(0x2b80, mulmod(mload(0xb00), mload(0xae0), f_q)) -mstore(0x2ba0, addmod(mload(0xac0), mload(0x2b80), f_q)) -mstore(0x2bc0, addmod(mload(0x2ba0), sub(f_q, mload(0xb20)), f_q)) -mstore(0x2be0, mulmod(mload(0x2bc0), mload(0xe20), f_q)) -mstore(0x2c00, mulmod(mload(0x960), mload(0x2be0), f_q)) -mstore(0x2c20, mulmod(mload(0xb80), mload(0xb60), f_q)) -mstore(0x2c40, addmod(mload(0xb40), mload(0x2c20), f_q)) -mstore(0x2c60, addmod(mload(0x2c40), sub(f_q, mload(0xba0)), f_q)) -mstore(0x2c80, mulmod(mload(0x2c60), mload(0xe40), f_q)) -mstore(0x2ca0, addmod(mload(0x2c00), mload(0x2c80), f_q)) -mstore(0x2cc0, mulmod(mload(0x960), mload(0x2ca0), f_q)) -mstore(0x2ce0, mulmod(mload(0xc00), mload(0xbe0), f_q)) -mstore(0x2d00, addmod(mload(0xbc0), mload(0x2ce0), f_q)) -mstore(0x2d20, addmod(mload(0x2d00), sub(f_q, mload(0xc20)), f_q)) -mstore(0x2d40, mulmod(mload(0x2d20), mload(0xe60), f_q)) -mstore(0x2d60, addmod(mload(0x2cc0), mload(0x2d40), f_q)) -mstore(0x2d80, mulmod(mload(0x960), mload(0x2d60), f_q)) -mstore(0x2da0, mulmod(mload(0xc80), mload(0xc60), f_q)) -mstore(0x2dc0, addmod(mload(0xc40), mload(0x2da0), f_q)) -mstore(0x2de0, addmod(mload(0x2dc0), sub(f_q, mload(0xca0)), f_q)) -mstore(0x2e00, mulmod(mload(0x2de0), mload(0xe80), f_q)) -mstore(0x2e20, addmod(mload(0x2d80), mload(0x2e00), f_q)) -mstore(0x2e40, mulmod(mload(0x960), mload(0x2e20), f_q)) -mstore(0x2e60, mulmod(mload(0xd00), mload(0xce0), f_q)) -mstore(0x2e80, addmod(mload(0xcc0), mload(0x2e60), f_q)) -mstore(0x2ea0, addmod(mload(0x2e80), sub(f_q, mload(0xd20)), f_q)) -mstore(0x2ec0, mulmod(mload(0x2ea0), mload(0xea0), f_q)) -mstore(0x2ee0, addmod(mload(0x2e40), mload(0x2ec0), f_q)) -mstore(0x2f00, mulmod(mload(0x960), mload(0x2ee0), f_q)) -mstore(0x2f20, mulmod(mload(0xd80), mload(0xd60), f_q)) -mstore(0x2f40, addmod(mload(0xd40), mload(0x2f20), f_q)) -mstore(0x2f60, addmod(mload(0x2f40), sub(f_q, mload(0xda0)), f_q)) -mstore(0x2f80, mulmod(mload(0x2f60), mload(0xec0), f_q)) -mstore(0x2fa0, addmod(mload(0x2f00), mload(0x2f80), f_q)) -mstore(0x2fc0, mulmod(mload(0x960), mload(0x2fa0), f_q)) -mstore(0x2fe0, addmod(1, sub(f_q, mload(0x1020)), f_q)) -mstore(0x3000, mulmod(mload(0x2fe0), mload(0x2760), f_q)) -mstore(0x3020, addmod(mload(0x2fc0), mload(0x3000), f_q)) -mstore(0x3040, mulmod(mload(0x960), mload(0x3020), f_q)) -mstore(0x3060, mulmod(mload(0x11a0), mload(0x11a0), f_q)) -mstore(0x3080, addmod(mload(0x3060), sub(f_q, mload(0x11a0)), f_q)) -mstore(0x30a0, mulmod(mload(0x3080), mload(0x2680), f_q)) -mstore(0x30c0, addmod(mload(0x3040), mload(0x30a0), f_q)) -mstore(0x30e0, mulmod(mload(0x960), mload(0x30c0), f_q)) -mstore(0x3100, addmod(mload(0x1080), sub(f_q, mload(0x1060)), f_q)) -mstore(0x3120, mulmod(mload(0x3100), mload(0x2760), f_q)) -mstore(0x3140, addmod(mload(0x30e0), mload(0x3120), f_q)) -mstore(0x3160, mulmod(mload(0x960), mload(0x3140), f_q)) -mstore(0x3180, addmod(mload(0x10e0), sub(f_q, mload(0x10c0)), f_q)) -mstore(0x31a0, mulmod(mload(0x3180), mload(0x2760), f_q)) -mstore(0x31c0, addmod(mload(0x3160), mload(0x31a0), f_q)) -mstore(0x31e0, mulmod(mload(0x960), mload(0x31c0), f_q)) -mstore(0x3200, addmod(mload(0x1140), sub(f_q, mload(0x1120)), f_q)) -mstore(0x3220, mulmod(mload(0x3200), mload(0x2760), f_q)) -mstore(0x3240, addmod(mload(0x31e0), mload(0x3220), f_q)) -mstore(0x3260, mulmod(mload(0x960), mload(0x3240), f_q)) -mstore(0x3280, addmod(mload(0x11a0), sub(f_q, mload(0x1180)), f_q)) -mstore(0x32a0, mulmod(mload(0x3280), mload(0x2760), f_q)) -mstore(0x32c0, addmod(mload(0x3260), mload(0x32a0), f_q)) -mstore(0x32e0, mulmod(mload(0x960), mload(0x32c0), f_q)) -mstore(0x3300, addmod(1, sub(f_q, mload(0x2680)), f_q)) -mstore(0x3320, addmod(mload(0x26a0), mload(0x26c0), f_q)) -mstore(0x3340, addmod(mload(0x3320), mload(0x26e0), f_q)) -mstore(0x3360, addmod(mload(0x3340), mload(0x2700), f_q)) -mstore(0x3380, addmod(mload(0x3360), mload(0x2720), f_q)) -mstore(0x33a0, addmod(mload(0x3380), mload(0x2740), f_q)) -mstore(0x33c0, addmod(mload(0x3300), sub(f_q, mload(0x33a0)), f_q)) -mstore(0x33e0, mulmod(mload(0xf00), mload(0x6e0), f_q)) -mstore(0x3400, addmod(mload(0x2b60), mload(0x33e0), f_q)) -mstore(0x3420, addmod(mload(0x3400), mload(0x740), f_q)) -mstore(0x3440, mulmod(mload(0xf20), mload(0x6e0), f_q)) -mstore(0x3460, addmod(mload(0xde0), mload(0x3440), f_q)) -mstore(0x3480, addmod(mload(0x3460), mload(0x740), f_q)) -mstore(0x34a0, mulmod(mload(0x3480), mload(0x3420), f_q)) -mstore(0x34c0, mulmod(mload(0x34a0), mload(0x1040), f_q)) -mstore(0x34e0, mulmod(1, mload(0x6e0), f_q)) -mstore(0x3500, mulmod(mload(0xa80), mload(0x34e0), f_q)) -mstore(0x3520, addmod(mload(0x2b60), mload(0x3500), f_q)) -mstore(0x3540, addmod(mload(0x3520), mload(0x740), f_q)) -mstore(0x3560, mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x6e0), f_q)) -mstore(0x3580, mulmod(mload(0xa80), mload(0x3560), f_q)) -mstore(0x35a0, addmod(mload(0xde0), mload(0x3580), f_q)) -mstore(0x35c0, addmod(mload(0x35a0), mload(0x740), f_q)) -mstore(0x35e0, mulmod(mload(0x35c0), mload(0x3540), f_q)) -mstore(0x3600, mulmod(mload(0x35e0), mload(0x1020), f_q)) -mstore(0x3620, addmod(mload(0x34c0), sub(f_q, mload(0x3600)), f_q)) -mstore(0x3640, mulmod(mload(0x3620), mload(0x33c0), f_q)) -mstore(0x3660, addmod(mload(0x32e0), mload(0x3640), f_q)) -mstore(0x3680, mulmod(mload(0x960), mload(0x3660), f_q)) -mstore(0x36a0, mulmod(mload(0xf40), mload(0x6e0), f_q)) -mstore(0x36c0, addmod(mload(0xac0), mload(0x36a0), f_q)) -mstore(0x36e0, addmod(mload(0x36c0), mload(0x740), f_q)) -mstore(0x3700, mulmod(mload(0xf60), mload(0x6e0), f_q)) -mstore(0x3720, addmod(mload(0xb40), mload(0x3700), f_q)) -mstore(0x3740, addmod(mload(0x3720), mload(0x740), f_q)) -mstore(0x3760, mulmod(mload(0x3740), mload(0x36e0), f_q)) -mstore(0x3780, mulmod(mload(0x3760), mload(0x10a0), f_q)) -mstore(0x37a0, mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x6e0), f_q)) -mstore(0x37c0, mulmod(mload(0xa80), mload(0x37a0), f_q)) -mstore(0x37e0, addmod(mload(0xac0), mload(0x37c0), f_q)) -mstore(0x3800, addmod(mload(0x37e0), mload(0x740), f_q)) -mstore(0x3820, mulmod(11166246659983828508719468090013646171463329086121580628794302409516816350802, mload(0x6e0), f_q)) -mstore(0x3840, mulmod(mload(0xa80), mload(0x3820), f_q)) -mstore(0x3860, addmod(mload(0xb40), mload(0x3840), f_q)) -mstore(0x3880, addmod(mload(0x3860), mload(0x740), f_q)) -mstore(0x38a0, mulmod(mload(0x3880), mload(0x3800), f_q)) -mstore(0x38c0, mulmod(mload(0x38a0), mload(0x1080), f_q)) -mstore(0x38e0, addmod(mload(0x3780), sub(f_q, mload(0x38c0)), f_q)) -mstore(0x3900, mulmod(mload(0x38e0), mload(0x33c0), f_q)) -mstore(0x3920, addmod(mload(0x3680), mload(0x3900), f_q)) -mstore(0x3940, mulmod(mload(0x960), mload(0x3920), f_q)) -mstore(0x3960, mulmod(mload(0xf80), mload(0x6e0), f_q)) -mstore(0x3980, addmod(mload(0xbc0), mload(0x3960), f_q)) -mstore(0x39a0, addmod(mload(0x3980), mload(0x740), f_q)) -mstore(0x39c0, mulmod(mload(0xfa0), mload(0x6e0), f_q)) -mstore(0x39e0, addmod(mload(0xc40), mload(0x39c0), f_q)) -mstore(0x3a00, addmod(mload(0x39e0), mload(0x740), f_q)) -mstore(0x3a20, mulmod(mload(0x3a00), mload(0x39a0), f_q)) -mstore(0x3a40, mulmod(mload(0x3a20), mload(0x1100), f_q)) -mstore(0x3a60, mulmod(284840088355319032285349970403338060113257071685626700086398481893096618818, mload(0x6e0), f_q)) -mstore(0x3a80, mulmod(mload(0xa80), mload(0x3a60), f_q)) -mstore(0x3aa0, addmod(mload(0xbc0), mload(0x3a80), f_q)) -mstore(0x3ac0, addmod(mload(0x3aa0), mload(0x740), f_q)) -mstore(0x3ae0, mulmod(21134065618345176623193549882539580312263652408302468683943992798037078993309, mload(0x6e0), f_q)) -mstore(0x3b00, mulmod(mload(0xa80), mload(0x3ae0), f_q)) -mstore(0x3b20, addmod(mload(0xc40), mload(0x3b00), f_q)) -mstore(0x3b40, addmod(mload(0x3b20), mload(0x740), f_q)) -mstore(0x3b60, mulmod(mload(0x3b40), mload(0x3ac0), f_q)) -mstore(0x3b80, mulmod(mload(0x3b60), mload(0x10e0), f_q)) -mstore(0x3ba0, addmod(mload(0x3a40), sub(f_q, mload(0x3b80)), f_q)) -mstore(0x3bc0, mulmod(mload(0x3ba0), mload(0x33c0), f_q)) -mstore(0x3be0, addmod(mload(0x3940), mload(0x3bc0), f_q)) -mstore(0x3c00, mulmod(mload(0x960), mload(0x3be0), f_q)) -mstore(0x3c20, mulmod(mload(0xfc0), mload(0x6e0), f_q)) -mstore(0x3c40, addmod(mload(0xcc0), mload(0x3c20), f_q)) -mstore(0x3c60, addmod(mload(0x3c40), mload(0x740), f_q)) -mstore(0x3c80, mulmod(mload(0xfe0), mload(0x6e0), f_q)) -mstore(0x3ca0, addmod(mload(0xd40), mload(0x3c80), f_q)) -mstore(0x3cc0, addmod(mload(0x3ca0), mload(0x740), f_q)) -mstore(0x3ce0, mulmod(mload(0x3cc0), mload(0x3c60), f_q)) -mstore(0x3d00, mulmod(mload(0x3ce0), mload(0x1160), f_q)) -mstore(0x3d20, mulmod(5625741653535312224677218588085279924365897425605943700675464992185016992283, mload(0x6e0), f_q)) -mstore(0x3d40, mulmod(mload(0xa80), mload(0x3d20), f_q)) -mstore(0x3d60, addmod(mload(0xcc0), mload(0x3d40), f_q)) -mstore(0x3d80, addmod(mload(0x3d60), mload(0x740), f_q)) -mstore(0x3da0, mulmod(14704729814417906439424896605881467874595262020190401576785074330126828718155, mload(0x6e0), f_q)) -mstore(0x3dc0, mulmod(mload(0xa80), mload(0x3da0), f_q)) -mstore(0x3de0, addmod(mload(0xd40), mload(0x3dc0), f_q)) -mstore(0x3e00, addmod(mload(0x3de0), mload(0x740), f_q)) -mstore(0x3e20, mulmod(mload(0x3e00), mload(0x3d80), f_q)) -mstore(0x3e40, mulmod(mload(0x3e20), mload(0x1140), f_q)) -mstore(0x3e60, addmod(mload(0x3d00), sub(f_q, mload(0x3e40)), f_q)) -mstore(0x3e80, mulmod(mload(0x3e60), mload(0x33c0), f_q)) -mstore(0x3ea0, addmod(mload(0x3c00), mload(0x3e80), f_q)) -mstore(0x3ec0, mulmod(mload(0x960), mload(0x3ea0), f_q)) -mstore(0x3ee0, mulmod(mload(0x1000), mload(0x6e0), f_q)) -mstore(0x3f00, addmod(mload(0xdc0), mload(0x3ee0), f_q)) -mstore(0x3f20, addmod(mload(0x3f00), mload(0x740), f_q)) -mstore(0x3f40, mulmod(mload(0x3f20), mload(0x11c0), f_q)) -mstore(0x3f60, mulmod(8343274462013750416000956870576256937330525306073862550863787263304548803879, mload(0x6e0), f_q)) -mstore(0x3f80, mulmod(mload(0xa80), mload(0x3f60), f_q)) -mstore(0x3fa0, addmod(mload(0xdc0), mload(0x3f80), f_q)) -mstore(0x3fc0, addmod(mload(0x3fa0), mload(0x740), f_q)) -mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0x11a0), f_q)) -mstore(0x4000, addmod(mload(0x3f40), sub(f_q, mload(0x3fe0)), f_q)) -mstore(0x4020, mulmod(mload(0x4000), mload(0x33c0), f_q)) -mstore(0x4040, addmod(mload(0x3ec0), mload(0x4020), f_q)) -mstore(0x4060, mulmod(mload(0x960), mload(0x4040), f_q)) -mstore(0x4080, addmod(1, sub(f_q, mload(0x11e0)), f_q)) -mstore(0x40a0, mulmod(mload(0x4080), mload(0x2760), f_q)) -mstore(0x40c0, addmod(mload(0x4060), mload(0x40a0), f_q)) -mstore(0x40e0, mulmod(mload(0x960), mload(0x40c0), f_q)) -mstore(0x4100, mulmod(mload(0x11e0), mload(0x11e0), f_q)) -mstore(0x4120, addmod(mload(0x4100), sub(f_q, mload(0x11e0)), f_q)) -mstore(0x4140, mulmod(mload(0x4120), mload(0x2680), f_q)) -mstore(0x4160, addmod(mload(0x40e0), mload(0x4140), f_q)) -mstore(0x4180, mulmod(mload(0x960), mload(0x4160), f_q)) -mstore(0x41a0, addmod(mload(0x1220), mload(0x6e0), f_q)) -mstore(0x41c0, mulmod(mload(0x41a0), mload(0x1200), f_q)) -mstore(0x41e0, addmod(mload(0x1260), mload(0x740), f_q)) -mstore(0x4200, mulmod(mload(0x41e0), mload(0x41c0), f_q)) -mstore(0x4220, addmod(mload(0xdc0), mload(0x6e0), f_q)) -mstore(0x4240, mulmod(mload(0x4220), mload(0x11e0), f_q)) -mstore(0x4260, addmod(mload(0xe00), mload(0x740), f_q)) -mstore(0x4280, mulmod(mload(0x4260), mload(0x4240), f_q)) -mstore(0x42a0, addmod(mload(0x4200), sub(f_q, mload(0x4280)), f_q)) -mstore(0x42c0, mulmod(mload(0x42a0), mload(0x33c0), f_q)) -mstore(0x42e0, addmod(mload(0x4180), mload(0x42c0), f_q)) -mstore(0x4300, mulmod(mload(0x960), mload(0x42e0), f_q)) -mstore(0x4320, addmod(mload(0x1220), sub(f_q, mload(0x1260)), f_q)) -mstore(0x4340, mulmod(mload(0x4320), mload(0x2760), f_q)) -mstore(0x4360, addmod(mload(0x4300), mload(0x4340), f_q)) -mstore(0x4380, mulmod(mload(0x960), mload(0x4360), f_q)) -mstore(0x43a0, mulmod(mload(0x4320), mload(0x33c0), f_q)) -mstore(0x43c0, addmod(mload(0x1220), sub(f_q, mload(0x1240)), f_q)) -mstore(0x43e0, mulmod(mload(0x43c0), mload(0x43a0), f_q)) -mstore(0x4400, addmod(mload(0x4380), mload(0x43e0), f_q)) -mstore(0x4420, mulmod(mload(0x16a0), mload(0x16a0), f_q)) -mstore(0x4440, mulmod(mload(0x4420), mload(0x16a0), f_q)) -mstore(0x4460, mulmod(1, mload(0x16a0), f_q)) -mstore(0x4480, mulmod(1, mload(0x4420), f_q)) -mstore(0x44a0, mulmod(mload(0x4400), mload(0x16c0), f_q)) -mstore(0x44c0, mulmod(mload(0x1420), mload(0xa80), f_q)) -mstore(0x44e0, mulmod(mload(0xa80), 1, f_q)) -mstore(0x4500, addmod(mload(0x13a0), sub(f_q, mload(0x44e0)), f_q)) -mstore(0x4520, mulmod(mload(0xa80), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) -mstore(0x4540, addmod(mload(0x13a0), sub(f_q, mload(0x4520)), f_q)) -mstore(0x4560, mulmod(mload(0xa80), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q)) -mstore(0x4580, addmod(mload(0x13a0), sub(f_q, mload(0x4560)), f_q)) -mstore(0x45a0, mulmod(mload(0xa80), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q)) -mstore(0x45c0, addmod(mload(0x13a0), sub(f_q, mload(0x45a0)), f_q)) -mstore(0x45e0, mulmod(mload(0xa80), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q)) -mstore(0x4600, addmod(mload(0x13a0), sub(f_q, mload(0x45e0)), f_q)) -mstore(0x4620, mulmod(mload(0xa80), 20975929243409798062839949658616274858986091382510192949221301676705706354487, f_q)) -mstore(0x4640, addmod(mload(0x13a0), sub(f_q, mload(0x4620)), f_q)) -{ - let result := mulmod(mload(0x13a0), 12142985201493934370659158242092015678465417407805993602870272259656026591649, f_q) -result := addmod(mulmod(mload(0xa80), 9745257670345340851587247503165259410082946992610040740827931926919781903968, f_q), result, f_q) -mstore(18016, result) - } -{ - let result := mulmod(mload(0x13a0), 12858672892267984631233883117647866851148059157064290846881981435700301865966, f_q) -result := addmod(mulmod(mload(0xa80), 20880316823902385764034220950270964645276820671488089374347912013802613180902, f_q), result, f_q) -mstore(18048, result) - } -{ - let result := mulmod(mload(0x13a0), 20880316823902385764034220950270964645276820671488089374347912013802613180902, f_q) -result := addmod(mulmod(mload(0xa80), 11271371393372049418391749801370907147092722420906347516206630933275258056927, f_q), result, f_q) -mstore(18080, result) - } -{ - let result := mulmod(mload(0x13a0), 17575202995145968412995467587554373308969396527144859871466654432792864477050, f_q) -result := addmod(mulmod(mload(0xa80), 13507346808256882665261837699919635602236930155453310622146452670066717241788, f_q), result, f_q) -mstore(18112, result) - } -mstore(0x46e0, mulmod(1, mload(0x4500), f_q)) -mstore(0x4700, mulmod(mload(0x46e0), mload(0x4540), f_q)) -mstore(0x4720, mulmod(mload(0x4700), mload(0x4600), f_q)) -mstore(0x4740, mulmod(mload(0x4720), mload(0x45c0), f_q)) -{ - let result := mulmod(mload(0x13a0), 1, f_q) -result := addmod(mulmod(mload(0xa80), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q), result, f_q) -mstore(18272, result) - } -{ - let result := mulmod(mload(0x13a0), 21869340487638379139105209872801492456082780734504032269410146788560475001942, f_q) -result := addmod(mulmod(mload(0xa80), 18902384200896083141195872455782632465583665912002074288057398015333493675, f_q), result, f_q) -mstore(18304, result) - } -{ - let result := mulmod(mload(0x13a0), 16199055355995875908874098831560099797649990976433931925532505422809603664814, f_q) -result := addmod(mulmod(mload(0xa80), 8947971868341681741891709615862399935097131087938461120792105052975383179198, f_q), result, f_q) -mstore(18336, result) - } -{ - let result := mulmod(mload(0x13a0), 4865187280763976036134135047793386535665014353502380106898040096680231678680, f_q) -result := addmod(mulmod(mload(0xa80), 11630478684739875729628806875878858148067322406415298287941825707875102831079, f_q), result, f_q) -mstore(18368, result) - } -mstore(0x47e0, mulmod(mload(0x4700), mload(0x4640), f_q)) -{ - let result := mulmod(mload(0x13a0), 20461838439117790833741043996939313553025008529160428886800406442142042007111, f_q) -result := addmod(mulmod(mload(0xa80), 1426404432721484388505361748317961535523355871255605456897797744433766488506, f_q), result, f_q) -mstore(18432, result) - } -{ - let result := mulmod(mload(0x13a0), 1426404432721484388505361748317961535523355871255605456897797744433766488506, f_q) -result := addmod(mulmod(mload(0xa80), 4281685467322811008008141037834996387840601218638499035555958417347771835972, f_q), result, f_q) -mstore(18464, result) - } -{ - let result := mulmod(mload(0x13a0), 19102728315457599142069468034376470979900453007937332237837518576196438670602, f_q) -result := addmod(mulmod(mload(0xa80), 2785514556381676080176937710880804108647911392478702105860685610379369825015, f_q), result, f_q) -mstore(18496, result) - } -{ - let result := mulmod(mload(0x13a0), 2785514556381676080176937710880804108647911392478702105860685610379369825015, f_q) -result := addmod(mulmod(mload(0xa80), 9270931013673651674008731376102018500640720878815062573686140036337408185754, f_q), result, f_q) -mstore(18528, result) - } -mstore(0x4880, mulmod(mload(0x46e0), mload(0x4580), f_q)) -{ - let prod := mload(0x4660) - - prod := mulmod(mload(0x4680), prod, f_q) - mstore(0x48a0, prod) - - prod := mulmod(mload(0x46a0), prod, f_q) - mstore(0x48c0, prod) - - prod := mulmod(mload(0x46c0), prod, f_q) - mstore(0x48e0, prod) - - prod := mulmod(mload(0x4760), prod, f_q) - mstore(0x4900, prod) - - prod := mulmod(mload(0x46e0), prod, f_q) - mstore(0x4920, prod) - - prod := mulmod(mload(0x4780), prod, f_q) - mstore(0x4940, prod) - - prod := mulmod(mload(0x47a0), prod, f_q) - mstore(0x4960, prod) - - prod := mulmod(mload(0x47c0), prod, f_q) - mstore(0x4980, prod) - - prod := mulmod(mload(0x47e0), prod, f_q) - mstore(0x49a0, prod) - - prod := mulmod(mload(0x4800), prod, f_q) - mstore(0x49c0, prod) - - prod := mulmod(mload(0x4820), prod, f_q) - mstore(0x49e0, prod) - - prod := mulmod(mload(0x4700), prod, f_q) - mstore(0x4a00, prod) - - prod := mulmod(mload(0x4840), prod, f_q) - mstore(0x4a20, prod) - - prod := mulmod(mload(0x4860), prod, f_q) - mstore(0x4a40, prod) - - prod := mulmod(mload(0x4880), prod, f_q) - mstore(0x4a60, prod) - - } -mstore(0x4aa0, 32) -mstore(0x4ac0, 32) -mstore(0x4ae0, 32) -mstore(0x4b00, mload(0x4a60)) -mstore(0x4b20, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x4b40, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x4aa0, 0xc0, 0x4a80, 0x20), 1), success) -{ - - let inv := mload(0x4a80) - let v - - v := mload(0x4880) - mstore(18560, mulmod(mload(0x4a40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4860) - mstore(18528, mulmod(mload(0x4a20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4840) - mstore(18496, mulmod(mload(0x4a00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4700) - mstore(18176, mulmod(mload(0x49e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4820) - mstore(18464, mulmod(mload(0x49c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4800) - mstore(18432, mulmod(mload(0x49a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x47e0) - mstore(18400, mulmod(mload(0x4980), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x47c0) - mstore(18368, mulmod(mload(0x4960), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x47a0) - mstore(18336, mulmod(mload(0x4940), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4780) - mstore(18304, mulmod(mload(0x4920), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x46e0) - mstore(18144, mulmod(mload(0x4900), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4760) - mstore(18272, mulmod(mload(0x48e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x46c0) - mstore(18112, mulmod(mload(0x48c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x46a0) - mstore(18080, mulmod(mload(0x48a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4680) - mstore(18048, mulmod(mload(0x4660), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x4660, inv) - - } -{ - let result := mload(0x4660) -result := addmod(mload(0x4680), result, f_q) -result := addmod(mload(0x46a0), result, f_q) -result := addmod(mload(0x46c0), result, f_q) -mstore(19296, result) - } -mstore(0x4b80, mulmod(mload(0x4740), mload(0x46e0), f_q)) -{ - let result := mload(0x4760) -mstore(19360, result) - } -mstore(0x4bc0, mulmod(mload(0x4740), mload(0x47e0), f_q)) -{ - let result := mload(0x4780) -result := addmod(mload(0x47a0), result, f_q) -result := addmod(mload(0x47c0), result, f_q) -mstore(19424, result) - } -mstore(0x4c00, mulmod(mload(0x4740), mload(0x4700), f_q)) -{ - let result := mload(0x4800) -result := addmod(mload(0x4820), result, f_q) -mstore(19488, result) - } -mstore(0x4c40, mulmod(mload(0x4740), mload(0x4880), f_q)) -{ - let result := mload(0x4840) -result := addmod(mload(0x4860), result, f_q) -mstore(19552, result) - } -{ - let prod := mload(0x4b60) - - prod := mulmod(mload(0x4ba0), prod, f_q) - mstore(0x4c80, prod) - - prod := mulmod(mload(0x4be0), prod, f_q) - mstore(0x4ca0, prod) - - prod := mulmod(mload(0x4c20), prod, f_q) - mstore(0x4cc0, prod) - - prod := mulmod(mload(0x4c60), prod, f_q) - mstore(0x4ce0, prod) - - } -mstore(0x4d20, 32) -mstore(0x4d40, 32) -mstore(0x4d60, 32) -mstore(0x4d80, mload(0x4ce0)) -mstore(0x4da0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x4dc0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x4d20, 0xc0, 0x4d00, 0x20), 1), success) -{ - - let inv := mload(0x4d00) - let v - - v := mload(0x4c60) - mstore(19552, mulmod(mload(0x4cc0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4c20) - mstore(19488, mulmod(mload(0x4ca0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4be0) - mstore(19424, mulmod(mload(0x4c80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x4ba0) - mstore(19360, mulmod(mload(0x4b60), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x4b60, inv) - - } -mstore(0x4de0, mulmod(mload(0x4b80), mload(0x4ba0), f_q)) -mstore(0x4e00, mulmod(mload(0x4bc0), mload(0x4be0), f_q)) -mstore(0x4e20, mulmod(mload(0x4c00), mload(0x4c20), f_q)) -mstore(0x4e40, mulmod(mload(0x4c40), mload(0x4c60), f_q)) -mstore(0x4e60, mulmod(mload(0x12a0), mload(0x12a0), f_q)) -mstore(0x4e80, mulmod(mload(0x4e60), mload(0x12a0), f_q)) -mstore(0x4ea0, mulmod(mload(0x4e80), mload(0x12a0), f_q)) -mstore(0x4ec0, mulmod(mload(0x4ea0), mload(0x12a0), f_q)) -mstore(0x4ee0, mulmod(mload(0x4ec0), mload(0x12a0), f_q)) -mstore(0x4f00, mulmod(mload(0x4ee0), mload(0x12a0), f_q)) -mstore(0x4f20, mulmod(mload(0x4f00), mload(0x12a0), f_q)) -mstore(0x4f40, mulmod(mload(0x4f20), mload(0x12a0), f_q)) -mstore(0x4f60, mulmod(mload(0x4f40), mload(0x12a0), f_q)) -mstore(0x4f80, mulmod(mload(0x4f60), mload(0x12a0), f_q)) -mstore(0x4fa0, mulmod(mload(0x4f80), mload(0x12a0), f_q)) -mstore(0x4fc0, mulmod(mload(0x4fa0), mload(0x12a0), f_q)) -mstore(0x4fe0, mulmod(mload(0x4fc0), mload(0x12a0), f_q)) -mstore(0x5000, mulmod(mload(0x4fe0), mload(0x12a0), f_q)) -mstore(0x5020, mulmod(mload(0x5000), mload(0x12a0), f_q)) -mstore(0x5040, mulmod(mload(0x5020), mload(0x12a0), f_q)) -mstore(0x5060, mulmod(mload(0x5040), mload(0x12a0), f_q)) -mstore(0x5080, mulmod(mload(0x5060), mload(0x12a0), f_q)) -mstore(0x50a0, mulmod(mload(0x5080), mload(0x12a0), f_q)) -mstore(0x50c0, mulmod(mload(0x50a0), mload(0x12a0), f_q)) -mstore(0x50e0, mulmod(mload(0x1300), mload(0x1300), f_q)) -mstore(0x5100, mulmod(mload(0x50e0), mload(0x1300), f_q)) -mstore(0x5120, mulmod(mload(0x5100), mload(0x1300), f_q)) -mstore(0x5140, mulmod(mload(0x5120), mload(0x1300), f_q)) -{ - let result := mulmod(mload(0xac0), mload(0x4660), f_q) -result := addmod(mulmod(mload(0xae0), mload(0x4680), f_q), result, f_q) -result := addmod(mulmod(mload(0xb00), mload(0x46a0), f_q), result, f_q) -result := addmod(mulmod(mload(0xb20), mload(0x46c0), f_q), result, f_q) -mstore(20832, result) - } -mstore(0x5180, mulmod(mload(0x5160), mload(0x4b60), f_q)) -mstore(0x51a0, mulmod(sub(f_q, mload(0x5180)), 1, f_q)) -{ - let result := mulmod(mload(0xb40), mload(0x4660), f_q) -result := addmod(mulmod(mload(0xb60), mload(0x4680), f_q), result, f_q) -result := addmod(mulmod(mload(0xb80), mload(0x46a0), f_q), result, f_q) -result := addmod(mulmod(mload(0xba0), mload(0x46c0), f_q), result, f_q) -mstore(20928, result) - } -mstore(0x51e0, mulmod(mload(0x51c0), mload(0x4b60), f_q)) -mstore(0x5200, mulmod(sub(f_q, mload(0x51e0)), mload(0x12a0), f_q)) -mstore(0x5220, mulmod(1, mload(0x12a0), f_q)) -mstore(0x5240, addmod(mload(0x51a0), mload(0x5200), f_q)) -{ - let result := mulmod(mload(0xbc0), mload(0x4660), f_q) -result := addmod(mulmod(mload(0xbe0), mload(0x4680), f_q), result, f_q) -result := addmod(mulmod(mload(0xc00), mload(0x46a0), f_q), result, f_q) -result := addmod(mulmod(mload(0xc20), mload(0x46c0), f_q), result, f_q) -mstore(21088, result) - } -mstore(0x5280, mulmod(mload(0x5260), mload(0x4b60), f_q)) -mstore(0x52a0, mulmod(sub(f_q, mload(0x5280)), mload(0x4e60), f_q)) -mstore(0x52c0, mulmod(1, mload(0x4e60), f_q)) -mstore(0x52e0, addmod(mload(0x5240), mload(0x52a0), f_q)) -{ - let result := mulmod(mload(0xc40), mload(0x4660), f_q) -result := addmod(mulmod(mload(0xc60), mload(0x4680), f_q), result, f_q) -result := addmod(mulmod(mload(0xc80), mload(0x46a0), f_q), result, f_q) -result := addmod(mulmod(mload(0xca0), mload(0x46c0), f_q), result, f_q) -mstore(21248, result) - } -mstore(0x5320, mulmod(mload(0x5300), mload(0x4b60), f_q)) -mstore(0x5340, mulmod(sub(f_q, mload(0x5320)), mload(0x4e80), f_q)) -mstore(0x5360, mulmod(1, mload(0x4e80), f_q)) -mstore(0x5380, addmod(mload(0x52e0), mload(0x5340), f_q)) -{ - let result := mulmod(mload(0xcc0), mload(0x4660), f_q) -result := addmod(mulmod(mload(0xce0), mload(0x4680), f_q), result, f_q) -result := addmod(mulmod(mload(0xd00), mload(0x46a0), f_q), result, f_q) -result := addmod(mulmod(mload(0xd20), mload(0x46c0), f_q), result, f_q) -mstore(21408, result) - } -mstore(0x53c0, mulmod(mload(0x53a0), mload(0x4b60), f_q)) -mstore(0x53e0, mulmod(sub(f_q, mload(0x53c0)), mload(0x4ea0), f_q)) -mstore(0x5400, mulmod(1, mload(0x4ea0), f_q)) -mstore(0x5420, addmod(mload(0x5380), mload(0x53e0), f_q)) -{ - let result := mulmod(mload(0xd40), mload(0x4660), f_q) -result := addmod(mulmod(mload(0xd60), mload(0x4680), f_q), result, f_q) -result := addmod(mulmod(mload(0xd80), mload(0x46a0), f_q), result, f_q) -result := addmod(mulmod(mload(0xda0), mload(0x46c0), f_q), result, f_q) -mstore(21568, result) - } -mstore(0x5460, mulmod(mload(0x5440), mload(0x4b60), f_q)) -mstore(0x5480, mulmod(sub(f_q, mload(0x5460)), mload(0x4ec0), f_q)) -mstore(0x54a0, mulmod(1, mload(0x4ec0), f_q)) -mstore(0x54c0, addmod(mload(0x5420), mload(0x5480), f_q)) -mstore(0x54e0, mulmod(mload(0x54c0), 1, f_q)) -mstore(0x5500, mulmod(mload(0x5220), 1, f_q)) -mstore(0x5520, mulmod(mload(0x52c0), 1, f_q)) -mstore(0x5540, mulmod(mload(0x5360), 1, f_q)) -mstore(0x5560, mulmod(mload(0x5400), 1, f_q)) -mstore(0x5580, mulmod(mload(0x54a0), 1, f_q)) -mstore(0x55a0, mulmod(1, mload(0x4b80), f_q)) -{ - let result := mulmod(mload(0xdc0), mload(0x4760), f_q) -mstore(21952, result) - } -mstore(0x55e0, mulmod(mload(0x55c0), mload(0x4de0), f_q)) -mstore(0x5600, mulmod(sub(f_q, mload(0x55e0)), 1, f_q)) -mstore(0x5620, mulmod(mload(0x55a0), 1, f_q)) -{ - let result := mulmod(mload(0x1260), mload(0x4760), f_q) -mstore(22080, result) - } -mstore(0x5660, mulmod(mload(0x5640), mload(0x4de0), f_q)) -mstore(0x5680, mulmod(sub(f_q, mload(0x5660)), mload(0x12a0), f_q)) -mstore(0x56a0, mulmod(mload(0x55a0), mload(0x12a0), f_q)) -mstore(0x56c0, addmod(mload(0x5600), mload(0x5680), f_q)) -{ - let result := mulmod(mload(0xde0), mload(0x4760), f_q) -mstore(22240, result) - } -mstore(0x5700, mulmod(mload(0x56e0), mload(0x4de0), f_q)) -mstore(0x5720, mulmod(sub(f_q, mload(0x5700)), mload(0x4e60), f_q)) -mstore(0x5740, mulmod(mload(0x55a0), mload(0x4e60), f_q)) -mstore(0x5760, addmod(mload(0x56c0), mload(0x5720), f_q)) -{ - let result := mulmod(mload(0xe00), mload(0x4760), f_q) -mstore(22400, result) - } -mstore(0x57a0, mulmod(mload(0x5780), mload(0x4de0), f_q)) -mstore(0x57c0, mulmod(sub(f_q, mload(0x57a0)), mload(0x4e80), f_q)) -mstore(0x57e0, mulmod(mload(0x55a0), mload(0x4e80), f_q)) -mstore(0x5800, addmod(mload(0x5760), mload(0x57c0), f_q)) -{ - let result := mulmod(mload(0xe20), mload(0x4760), f_q) -mstore(22560, result) - } -mstore(0x5840, mulmod(mload(0x5820), mload(0x4de0), f_q)) -mstore(0x5860, mulmod(sub(f_q, mload(0x5840)), mload(0x4ea0), f_q)) -mstore(0x5880, mulmod(mload(0x55a0), mload(0x4ea0), f_q)) -mstore(0x58a0, addmod(mload(0x5800), mload(0x5860), f_q)) -{ - let result := mulmod(mload(0xe40), mload(0x4760), f_q) -mstore(22720, result) - } -mstore(0x58e0, mulmod(mload(0x58c0), mload(0x4de0), f_q)) -mstore(0x5900, mulmod(sub(f_q, mload(0x58e0)), mload(0x4ec0), f_q)) -mstore(0x5920, mulmod(mload(0x55a0), mload(0x4ec0), f_q)) -mstore(0x5940, addmod(mload(0x58a0), mload(0x5900), f_q)) -{ - let result := mulmod(mload(0xe60), mload(0x4760), f_q) -mstore(22880, result) - } -mstore(0x5980, mulmod(mload(0x5960), mload(0x4de0), f_q)) -mstore(0x59a0, mulmod(sub(f_q, mload(0x5980)), mload(0x4ee0), f_q)) -mstore(0x59c0, mulmod(mload(0x55a0), mload(0x4ee0), f_q)) -mstore(0x59e0, addmod(mload(0x5940), mload(0x59a0), f_q)) -{ - let result := mulmod(mload(0xe80), mload(0x4760), f_q) -mstore(23040, result) - } -mstore(0x5a20, mulmod(mload(0x5a00), mload(0x4de0), f_q)) -mstore(0x5a40, mulmod(sub(f_q, mload(0x5a20)), mload(0x4f00), f_q)) -mstore(0x5a60, mulmod(mload(0x55a0), mload(0x4f00), f_q)) -mstore(0x5a80, addmod(mload(0x59e0), mload(0x5a40), f_q)) -{ - let result := mulmod(mload(0xea0), mload(0x4760), f_q) -mstore(23200, result) - } -mstore(0x5ac0, mulmod(mload(0x5aa0), mload(0x4de0), f_q)) -mstore(0x5ae0, mulmod(sub(f_q, mload(0x5ac0)), mload(0x4f20), f_q)) -mstore(0x5b00, mulmod(mload(0x55a0), mload(0x4f20), f_q)) -mstore(0x5b20, addmod(mload(0x5a80), mload(0x5ae0), f_q)) -mstore(0x5b40, addmod(mload(0x5a60), mload(0x5b00), f_q)) -{ - let result := mulmod(mload(0xec0), mload(0x4760), f_q) -mstore(23392, result) - } -mstore(0x5b80, mulmod(mload(0x5b60), mload(0x4de0), f_q)) -mstore(0x5ba0, mulmod(sub(f_q, mload(0x5b80)), mload(0x4f40), f_q)) -mstore(0x5bc0, mulmod(mload(0x55a0), mload(0x4f40), f_q)) -mstore(0x5be0, addmod(mload(0x5b20), mload(0x5ba0), f_q)) -mstore(0x5c00, addmod(mload(0x5b40), mload(0x5bc0), f_q)) -{ - let result := mulmod(mload(0xf00), mload(0x4760), f_q) -mstore(23584, result) - } -mstore(0x5c40, mulmod(mload(0x5c20), mload(0x4de0), f_q)) -mstore(0x5c60, mulmod(sub(f_q, mload(0x5c40)), mload(0x4f60), f_q)) -mstore(0x5c80, mulmod(mload(0x55a0), mload(0x4f60), f_q)) -mstore(0x5ca0, addmod(mload(0x5be0), mload(0x5c60), f_q)) -{ - let result := mulmod(mload(0xf20), mload(0x4760), f_q) -mstore(23744, result) - } -mstore(0x5ce0, mulmod(mload(0x5cc0), mload(0x4de0), f_q)) -mstore(0x5d00, mulmod(sub(f_q, mload(0x5ce0)), mload(0x4f80), f_q)) -mstore(0x5d20, mulmod(mload(0x55a0), mload(0x4f80), f_q)) -mstore(0x5d40, addmod(mload(0x5ca0), mload(0x5d00), f_q)) -{ - let result := mulmod(mload(0xf40), mload(0x4760), f_q) -mstore(23904, result) - } -mstore(0x5d80, mulmod(mload(0x5d60), mload(0x4de0), f_q)) -mstore(0x5da0, mulmod(sub(f_q, mload(0x5d80)), mload(0x4fa0), f_q)) -mstore(0x5dc0, mulmod(mload(0x55a0), mload(0x4fa0), f_q)) -mstore(0x5de0, addmod(mload(0x5d40), mload(0x5da0), f_q)) -{ - let result := mulmod(mload(0xf60), mload(0x4760), f_q) -mstore(24064, result) - } -mstore(0x5e20, mulmod(mload(0x5e00), mload(0x4de0), f_q)) -mstore(0x5e40, mulmod(sub(f_q, mload(0x5e20)), mload(0x4fc0), f_q)) -mstore(0x5e60, mulmod(mload(0x55a0), mload(0x4fc0), f_q)) -mstore(0x5e80, addmod(mload(0x5de0), mload(0x5e40), f_q)) -{ - let result := mulmod(mload(0xf80), mload(0x4760), f_q) -mstore(24224, result) - } -mstore(0x5ec0, mulmod(mload(0x5ea0), mload(0x4de0), f_q)) -mstore(0x5ee0, mulmod(sub(f_q, mload(0x5ec0)), mload(0x4fe0), f_q)) -mstore(0x5f00, mulmod(mload(0x55a0), mload(0x4fe0), f_q)) -mstore(0x5f20, addmod(mload(0x5e80), mload(0x5ee0), f_q)) -{ - let result := mulmod(mload(0xfa0), mload(0x4760), f_q) -mstore(24384, result) - } -mstore(0x5f60, mulmod(mload(0x5f40), mload(0x4de0), f_q)) -mstore(0x5f80, mulmod(sub(f_q, mload(0x5f60)), mload(0x5000), f_q)) -mstore(0x5fa0, mulmod(mload(0x55a0), mload(0x5000), f_q)) -mstore(0x5fc0, addmod(mload(0x5f20), mload(0x5f80), f_q)) -{ - let result := mulmod(mload(0xfc0), mload(0x4760), f_q) -mstore(24544, result) - } -mstore(0x6000, mulmod(mload(0x5fe0), mload(0x4de0), f_q)) -mstore(0x6020, mulmod(sub(f_q, mload(0x6000)), mload(0x5020), f_q)) -mstore(0x6040, mulmod(mload(0x55a0), mload(0x5020), f_q)) -mstore(0x6060, addmod(mload(0x5fc0), mload(0x6020), f_q)) -{ - let result := mulmod(mload(0xfe0), mload(0x4760), f_q) -mstore(24704, result) - } -mstore(0x60a0, mulmod(mload(0x6080), mload(0x4de0), f_q)) -mstore(0x60c0, mulmod(sub(f_q, mload(0x60a0)), mload(0x5040), f_q)) -mstore(0x60e0, mulmod(mload(0x55a0), mload(0x5040), f_q)) -mstore(0x6100, addmod(mload(0x6060), mload(0x60c0), f_q)) -{ - let result := mulmod(mload(0x1000), mload(0x4760), f_q) -mstore(24864, result) - } -mstore(0x6140, mulmod(mload(0x6120), mload(0x4de0), f_q)) -mstore(0x6160, mulmod(sub(f_q, mload(0x6140)), mload(0x5060), f_q)) -mstore(0x6180, mulmod(mload(0x55a0), mload(0x5060), f_q)) -mstore(0x61a0, addmod(mload(0x6100), mload(0x6160), f_q)) -mstore(0x61c0, mulmod(mload(0x4460), mload(0x4b80), f_q)) -mstore(0x61e0, mulmod(mload(0x4480), mload(0x4b80), f_q)) -{ - let result := mulmod(mload(0x44a0), mload(0x4760), f_q) -mstore(25088, result) - } -mstore(0x6220, mulmod(mload(0x6200), mload(0x4de0), f_q)) -mstore(0x6240, mulmod(sub(f_q, mload(0x6220)), mload(0x5080), f_q)) -mstore(0x6260, mulmod(mload(0x55a0), mload(0x5080), f_q)) -mstore(0x6280, mulmod(mload(0x61c0), mload(0x5080), f_q)) -mstore(0x62a0, mulmod(mload(0x61e0), mload(0x5080), f_q)) -mstore(0x62c0, addmod(mload(0x61a0), mload(0x6240), f_q)) -{ - let result := mulmod(mload(0xee0), mload(0x4760), f_q) -mstore(25312, result) - } -mstore(0x6300, mulmod(mload(0x62e0), mload(0x4de0), f_q)) -mstore(0x6320, mulmod(sub(f_q, mload(0x6300)), mload(0x50a0), f_q)) -mstore(0x6340, mulmod(mload(0x55a0), mload(0x50a0), f_q)) -mstore(0x6360, addmod(mload(0x62c0), mload(0x6320), f_q)) -mstore(0x6380, mulmod(mload(0x6360), mload(0x1300), f_q)) -mstore(0x63a0, mulmod(mload(0x5620), mload(0x1300), f_q)) -mstore(0x63c0, mulmod(mload(0x56a0), mload(0x1300), f_q)) -mstore(0x63e0, mulmod(mload(0x5740), mload(0x1300), f_q)) -mstore(0x6400, mulmod(mload(0x57e0), mload(0x1300), f_q)) -mstore(0x6420, mulmod(mload(0x5880), mload(0x1300), f_q)) -mstore(0x6440, mulmod(mload(0x5920), mload(0x1300), f_q)) -mstore(0x6460, mulmod(mload(0x59c0), mload(0x1300), f_q)) -mstore(0x6480, mulmod(mload(0x5c00), mload(0x1300), f_q)) -mstore(0x64a0, mulmod(mload(0x5c80), mload(0x1300), f_q)) -mstore(0x64c0, mulmod(mload(0x5d20), mload(0x1300), f_q)) -mstore(0x64e0, mulmod(mload(0x5dc0), mload(0x1300), f_q)) -mstore(0x6500, mulmod(mload(0x5e60), mload(0x1300), f_q)) -mstore(0x6520, mulmod(mload(0x5f00), mload(0x1300), f_q)) -mstore(0x6540, mulmod(mload(0x5fa0), mload(0x1300), f_q)) -mstore(0x6560, mulmod(mload(0x6040), mload(0x1300), f_q)) -mstore(0x6580, mulmod(mload(0x60e0), mload(0x1300), f_q)) -mstore(0x65a0, mulmod(mload(0x6180), mload(0x1300), f_q)) -mstore(0x65c0, mulmod(mload(0x6260), mload(0x1300), f_q)) -mstore(0x65e0, mulmod(mload(0x6280), mload(0x1300), f_q)) -mstore(0x6600, mulmod(mload(0x62a0), mload(0x1300), f_q)) -mstore(0x6620, mulmod(mload(0x6340), mload(0x1300), f_q)) -mstore(0x6640, addmod(mload(0x54e0), mload(0x6380), f_q)) -mstore(0x6660, mulmod(1, mload(0x4bc0), f_q)) -{ - let result := mulmod(mload(0x1020), mload(0x4780), f_q) -result := addmod(mulmod(mload(0x1040), mload(0x47a0), f_q), result, f_q) -result := addmod(mulmod(mload(0x1060), mload(0x47c0), f_q), result, f_q) -mstore(26240, result) - } -mstore(0x66a0, mulmod(mload(0x6680), mload(0x4e00), f_q)) -mstore(0x66c0, mulmod(sub(f_q, mload(0x66a0)), 1, f_q)) -mstore(0x66e0, mulmod(mload(0x6660), 1, f_q)) -{ - let result := mulmod(mload(0x1080), mload(0x4780), f_q) -result := addmod(mulmod(mload(0x10a0), mload(0x47a0), f_q), result, f_q) -result := addmod(mulmod(mload(0x10c0), mload(0x47c0), f_q), result, f_q) -mstore(26368, result) - } -mstore(0x6720, mulmod(mload(0x6700), mload(0x4e00), f_q)) -mstore(0x6740, mulmod(sub(f_q, mload(0x6720)), mload(0x12a0), f_q)) -mstore(0x6760, mulmod(mload(0x6660), mload(0x12a0), f_q)) -mstore(0x6780, addmod(mload(0x66c0), mload(0x6740), f_q)) -{ - let result := mulmod(mload(0x10e0), mload(0x4780), f_q) -result := addmod(mulmod(mload(0x1100), mload(0x47a0), f_q), result, f_q) -result := addmod(mulmod(mload(0x1120), mload(0x47c0), f_q), result, f_q) -mstore(26528, result) - } -mstore(0x67c0, mulmod(mload(0x67a0), mload(0x4e00), f_q)) -mstore(0x67e0, mulmod(sub(f_q, mload(0x67c0)), mload(0x4e60), f_q)) -mstore(0x6800, mulmod(mload(0x6660), mload(0x4e60), f_q)) -mstore(0x6820, addmod(mload(0x6780), mload(0x67e0), f_q)) -{ - let result := mulmod(mload(0x1140), mload(0x4780), f_q) -result := addmod(mulmod(mload(0x1160), mload(0x47a0), f_q), result, f_q) -result := addmod(mulmod(mload(0x1180), mload(0x47c0), f_q), result, f_q) -mstore(26688, result) - } -mstore(0x6860, mulmod(mload(0x6840), mload(0x4e00), f_q)) -mstore(0x6880, mulmod(sub(f_q, mload(0x6860)), mload(0x4e80), f_q)) -mstore(0x68a0, mulmod(mload(0x6660), mload(0x4e80), f_q)) -mstore(0x68c0, addmod(mload(0x6820), mload(0x6880), f_q)) -mstore(0x68e0, mulmod(mload(0x68c0), mload(0x50e0), f_q)) -mstore(0x6900, mulmod(mload(0x66e0), mload(0x50e0), f_q)) -mstore(0x6920, mulmod(mload(0x6760), mload(0x50e0), f_q)) -mstore(0x6940, mulmod(mload(0x6800), mload(0x50e0), f_q)) -mstore(0x6960, mulmod(mload(0x68a0), mload(0x50e0), f_q)) -mstore(0x6980, addmod(mload(0x6640), mload(0x68e0), f_q)) -mstore(0x69a0, mulmod(1, mload(0x4c00), f_q)) -{ - let result := mulmod(mload(0x11a0), mload(0x4800), f_q) -result := addmod(mulmod(mload(0x11c0), mload(0x4820), f_q), result, f_q) -mstore(27072, result) - } -mstore(0x69e0, mulmod(mload(0x69c0), mload(0x4e20), f_q)) -mstore(0x6a00, mulmod(sub(f_q, mload(0x69e0)), 1, f_q)) -mstore(0x6a20, mulmod(mload(0x69a0), 1, f_q)) -{ - let result := mulmod(mload(0x11e0), mload(0x4800), f_q) -result := addmod(mulmod(mload(0x1200), mload(0x4820), f_q), result, f_q) -mstore(27200, result) - } -mstore(0x6a60, mulmod(mload(0x6a40), mload(0x4e20), f_q)) -mstore(0x6a80, mulmod(sub(f_q, mload(0x6a60)), mload(0x12a0), f_q)) -mstore(0x6aa0, mulmod(mload(0x69a0), mload(0x12a0), f_q)) -mstore(0x6ac0, addmod(mload(0x6a00), mload(0x6a80), f_q)) -mstore(0x6ae0, mulmod(mload(0x6ac0), mload(0x5100), f_q)) -mstore(0x6b00, mulmod(mload(0x6a20), mload(0x5100), f_q)) -mstore(0x6b20, mulmod(mload(0x6aa0), mload(0x5100), f_q)) -mstore(0x6b40, addmod(mload(0x6980), mload(0x6ae0), f_q)) -mstore(0x6b60, mulmod(1, mload(0x4c40), f_q)) -{ - let result := mulmod(mload(0x1220), mload(0x4840), f_q) -result := addmod(mulmod(mload(0x1240), mload(0x4860), f_q), result, f_q) -mstore(27520, result) - } -mstore(0x6ba0, mulmod(mload(0x6b80), mload(0x4e40), f_q)) -mstore(0x6bc0, mulmod(sub(f_q, mload(0x6ba0)), 1, f_q)) -mstore(0x6be0, mulmod(mload(0x6b60), 1, f_q)) -mstore(0x6c00, mulmod(mload(0x6bc0), mload(0x5120), f_q)) -mstore(0x6c20, mulmod(mload(0x6be0), mload(0x5120), f_q)) -mstore(0x6c40, addmod(mload(0x6b40), mload(0x6c00), f_q)) -mstore(0x6c60, mulmod(1, mload(0x4740), f_q)) -mstore(0x6c80, mulmod(1, mload(0x13a0), f_q)) -mstore(0x6ca0, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x6cc0, 0x0000000000000000000000000000000000000000000000000000000000000002) -mstore(0x6ce0, mload(0x6c40)) -success := and(eq(staticcall(gas(), 0x7, 0x6ca0, 0x60, 0x6ca0, 0x40), 1), success) -mstore(0x6d00, mload(0x6ca0)) - mstore(0x6d20, mload(0x6cc0)) -mstore(0x6d40, mload(0x420)) - mstore(0x6d60, mload(0x440)) -success := and(eq(staticcall(gas(), 0x6, 0x6d00, 0x80, 0x6d00, 0x40), 1), success) -mstore(0x6d80, mload(0x460)) - mstore(0x6da0, mload(0x480)) -mstore(0x6dc0, mload(0x5500)) -success := and(eq(staticcall(gas(), 0x7, 0x6d80, 0x60, 0x6d80, 0x40), 1), success) -mstore(0x6de0, mload(0x6d00)) - mstore(0x6e00, mload(0x6d20)) -mstore(0x6e20, mload(0x6d80)) - mstore(0x6e40, mload(0x6da0)) -success := and(eq(staticcall(gas(), 0x6, 0x6de0, 0x80, 0x6de0, 0x40), 1), success) -mstore(0x6e60, mload(0x4a0)) - mstore(0x6e80, mload(0x4c0)) -mstore(0x6ea0, mload(0x5520)) -success := and(eq(staticcall(gas(), 0x7, 0x6e60, 0x60, 0x6e60, 0x40), 1), success) -mstore(0x6ec0, mload(0x6de0)) - mstore(0x6ee0, mload(0x6e00)) -mstore(0x6f00, mload(0x6e60)) - mstore(0x6f20, mload(0x6e80)) -success := and(eq(staticcall(gas(), 0x6, 0x6ec0, 0x80, 0x6ec0, 0x40), 1), success) -mstore(0x6f40, mload(0x4e0)) - mstore(0x6f60, mload(0x500)) -mstore(0x6f80, mload(0x5540)) -success := and(eq(staticcall(gas(), 0x7, 0x6f40, 0x60, 0x6f40, 0x40), 1), success) -mstore(0x6fa0, mload(0x6ec0)) - mstore(0x6fc0, mload(0x6ee0)) -mstore(0x6fe0, mload(0x6f40)) - mstore(0x7000, mload(0x6f60)) -success := and(eq(staticcall(gas(), 0x6, 0x6fa0, 0x80, 0x6fa0, 0x40), 1), success) -mstore(0x7020, mload(0x520)) - mstore(0x7040, mload(0x540)) -mstore(0x7060, mload(0x5560)) -success := and(eq(staticcall(gas(), 0x7, 0x7020, 0x60, 0x7020, 0x40), 1), success) -mstore(0x7080, mload(0x6fa0)) - mstore(0x70a0, mload(0x6fc0)) -mstore(0x70c0, mload(0x7020)) - mstore(0x70e0, mload(0x7040)) -success := and(eq(staticcall(gas(), 0x6, 0x7080, 0x80, 0x7080, 0x40), 1), success) -mstore(0x7100, mload(0x560)) - mstore(0x7120, mload(0x580)) -mstore(0x7140, mload(0x5580)) -success := and(eq(staticcall(gas(), 0x7, 0x7100, 0x60, 0x7100, 0x40), 1), success) -mstore(0x7160, mload(0x7080)) - mstore(0x7180, mload(0x70a0)) -mstore(0x71a0, mload(0x7100)) - mstore(0x71c0, mload(0x7120)) -success := and(eq(staticcall(gas(), 0x6, 0x7160, 0x80, 0x7160, 0x40), 1), success) -mstore(0x71e0, mload(0x5a0)) - mstore(0x7200, mload(0x5c0)) -mstore(0x7220, mload(0x63a0)) -success := and(eq(staticcall(gas(), 0x7, 0x71e0, 0x60, 0x71e0, 0x40), 1), success) -mstore(0x7240, mload(0x7160)) - mstore(0x7260, mload(0x7180)) -mstore(0x7280, mload(0x71e0)) - mstore(0x72a0, mload(0x7200)) -success := and(eq(staticcall(gas(), 0x6, 0x7240, 0x80, 0x7240, 0x40), 1), success) -mstore(0x72c0, mload(0x680)) - mstore(0x72e0, mload(0x6a0)) -mstore(0x7300, mload(0x63c0)) -success := and(eq(staticcall(gas(), 0x7, 0x72c0, 0x60, 0x72c0, 0x40), 1), success) -mstore(0x7320, mload(0x7240)) - mstore(0x7340, mload(0x7260)) -mstore(0x7360, mload(0x72c0)) - mstore(0x7380, mload(0x72e0)) -success := and(eq(staticcall(gas(), 0x6, 0x7320, 0x80, 0x7320, 0x40), 1), success) -mstore(0x73a0, 0x2e698414127a0e86525b8ab580509c87a9aa2652ee073ae00a670c5b041f3aba) - mstore(0x73c0, 0x05c8831a3f2150eb05c8cfffbe7a247b9db780b200d2dc2eac2a8b95f7e1bd8e) -mstore(0x73e0, mload(0x63e0)) -success := and(eq(staticcall(gas(), 0x7, 0x73a0, 0x60, 0x73a0, 0x40), 1), success) -mstore(0x7400, mload(0x7320)) - mstore(0x7420, mload(0x7340)) -mstore(0x7440, mload(0x73a0)) - mstore(0x7460, mload(0x73c0)) -success := and(eq(staticcall(gas(), 0x6, 0x7400, 0x80, 0x7400, 0x40), 1), success) -mstore(0x7480, 0x287ee5534d4c16ef78de7646cc481ed44aa9377c9f27a39779833f7ddb4bdf7c) - mstore(0x74a0, 0x126ab83eede4df118f9cd4216d70c70da40820443112c18ddc36e2dabb355323) -mstore(0x74c0, mload(0x6400)) -success := and(eq(staticcall(gas(), 0x7, 0x7480, 0x60, 0x7480, 0x40), 1), success) -mstore(0x74e0, mload(0x7400)) - mstore(0x7500, mload(0x7420)) -mstore(0x7520, mload(0x7480)) - mstore(0x7540, mload(0x74a0)) -success := and(eq(staticcall(gas(), 0x6, 0x74e0, 0x80, 0x74e0, 0x40), 1), success) -mstore(0x7560, 0x1ba9808a009a471bfe68acdd646958a0dcd0d1bbc2765661c65ee3c923ac4cfa) - mstore(0x7580, 0x12249d6743178d65c9932c27bf41455847035c2564eb6986f7523412af000fe9) -mstore(0x75a0, mload(0x6420)) -success := and(eq(staticcall(gas(), 0x7, 0x7560, 0x60, 0x7560, 0x40), 1), success) -mstore(0x75c0, mload(0x74e0)) - mstore(0x75e0, mload(0x7500)) -mstore(0x7600, mload(0x7560)) - mstore(0x7620, mload(0x7580)) -success := and(eq(staticcall(gas(), 0x6, 0x75c0, 0x80, 0x75c0, 0x40), 1), success) -mstore(0x7640, 0x29a79cf4eb491b6cd63763398cc283a9ceccc2a065983e7caf615ab73dc826cb) - mstore(0x7660, 0x226745e7bec29993785ef2676b2188b1b0dc01b101262a0cbcad4ce61a66d4fa) -mstore(0x7680, mload(0x6440)) -success := and(eq(staticcall(gas(), 0x7, 0x7640, 0x60, 0x7640, 0x40), 1), success) -mstore(0x76a0, mload(0x75c0)) - mstore(0x76c0, mload(0x75e0)) -mstore(0x76e0, mload(0x7640)) - mstore(0x7700, mload(0x7660)) -success := and(eq(staticcall(gas(), 0x6, 0x76a0, 0x80, 0x76a0, 0x40), 1), success) -mstore(0x7720, 0x090b8182b879c2d24027ae1912570b524f6b042ae01632783b779404c2026e53) - mstore(0x7740, 0x009946eed5a8b45fad680bba5f59d27f91c97ec53425eff954b5638da8173b32) -mstore(0x7760, mload(0x6460)) -success := and(eq(staticcall(gas(), 0x7, 0x7720, 0x60, 0x7720, 0x40), 1), success) -mstore(0x7780, mload(0x76a0)) - mstore(0x77a0, mload(0x76c0)) -mstore(0x77c0, mload(0x7720)) - mstore(0x77e0, mload(0x7740)) -success := and(eq(staticcall(gas(), 0x6, 0x7780, 0x80, 0x7780, 0x40), 1), success) -mstore(0x7800, 0x0000000000000000000000000000000000000000000000000000000000000000) - mstore(0x7820, 0x0000000000000000000000000000000000000000000000000000000000000000) -mstore(0x7840, mload(0x6480)) -success := and(eq(staticcall(gas(), 0x7, 0x7800, 0x60, 0x7800, 0x40), 1), success) -mstore(0x7860, mload(0x7780)) - mstore(0x7880, mload(0x77a0)) -mstore(0x78a0, mload(0x7800)) - mstore(0x78c0, mload(0x7820)) -success := and(eq(staticcall(gas(), 0x6, 0x7860, 0x80, 0x7860, 0x40), 1), success) -mstore(0x78e0, 0x014aeb1a1ae039d92258d444cf80423dfe4f10b994ad21ec17d354cf1e267f92) - mstore(0x7900, 0x0885c5dd19b94a4dfd9e7f827c991ac2d534c9f36d76c4ed6c0f5d9d08054ec1) -mstore(0x7920, mload(0x64a0)) -success := and(eq(staticcall(gas(), 0x7, 0x78e0, 0x60, 0x78e0, 0x40), 1), success) -mstore(0x7940, mload(0x7860)) - mstore(0x7960, mload(0x7880)) -mstore(0x7980, mload(0x78e0)) - mstore(0x79a0, mload(0x7900)) -success := and(eq(staticcall(gas(), 0x6, 0x7940, 0x80, 0x7940, 0x40), 1), success) -mstore(0x79c0, 0x2e1118d7237f003e76c91c75f0b8f0b53a3dabb62e9ae1b789169e464c268d52) - mstore(0x79e0, 0x2958a4a2355c5b846e841e61c893ff64aa327b04347cc4ca6ae136d6fedd027a) -mstore(0x7a00, mload(0x64c0)) -success := and(eq(staticcall(gas(), 0x7, 0x79c0, 0x60, 0x79c0, 0x40), 1), success) -mstore(0x7a20, mload(0x7940)) - mstore(0x7a40, mload(0x7960)) -mstore(0x7a60, mload(0x79c0)) - mstore(0x7a80, mload(0x79e0)) -success := and(eq(staticcall(gas(), 0x6, 0x7a20, 0x80, 0x7a20, 0x40), 1), success) -mstore(0x7aa0, 0x0c7ce3344d5535f0b42216a00b8efd355ec8ed96d3d094b446cc4a181d482869) - mstore(0x7ac0, 0x0d51489b13bc4119a51d8f2776bbe74af095d7ccf992c15efcc0c9d8dbd37be6) -mstore(0x7ae0, mload(0x64e0)) -success := and(eq(staticcall(gas(), 0x7, 0x7aa0, 0x60, 0x7aa0, 0x40), 1), success) -mstore(0x7b00, mload(0x7a20)) - mstore(0x7b20, mload(0x7a40)) -mstore(0x7b40, mload(0x7aa0)) - mstore(0x7b60, mload(0x7ac0)) -success := and(eq(staticcall(gas(), 0x6, 0x7b00, 0x80, 0x7b00, 0x40), 1), success) -mstore(0x7b80, 0x2cbbb80dd4de5ec0996b34af58b7ead5bbf87187bc458df1beb21657cdad4779) - mstore(0x7ba0, 0x15b362af6039cf173040a6a3c87549db94855d385df662d28b845e3bc871efc4) -mstore(0x7bc0, mload(0x6500)) -success := and(eq(staticcall(gas(), 0x7, 0x7b80, 0x60, 0x7b80, 0x40), 1), success) -mstore(0x7be0, mload(0x7b00)) - mstore(0x7c00, mload(0x7b20)) -mstore(0x7c20, mload(0x7b80)) - mstore(0x7c40, mload(0x7ba0)) -success := and(eq(staticcall(gas(), 0x6, 0x7be0, 0x80, 0x7be0, 0x40), 1), success) -mstore(0x7c60, 0x17737df752edc8afc5eb9237db5a33e66ee84edc97e46c77f801792f7bfe616c) - mstore(0x7c80, 0x2bb7610e5398d0456c63d26ec2f4a10c7051e13e9f1f186e49cd270fdd3fc367) -mstore(0x7ca0, mload(0x6520)) -success := and(eq(staticcall(gas(), 0x7, 0x7c60, 0x60, 0x7c60, 0x40), 1), success) -mstore(0x7cc0, mload(0x7be0)) - mstore(0x7ce0, mload(0x7c00)) -mstore(0x7d00, mload(0x7c60)) - mstore(0x7d20, mload(0x7c80)) -success := and(eq(staticcall(gas(), 0x6, 0x7cc0, 0x80, 0x7cc0, 0x40), 1), success) -mstore(0x7d40, 0x21447dfd8b5238a9f84377a51ddff98bfb71ee0dbd96fa83c8df41ad3229bb97) - mstore(0x7d60, 0x1cab5f7182d947bfdb45214d6417041268f06208edfbda8e26754b9d504c4b3b) -mstore(0x7d80, mload(0x6540)) -success := and(eq(staticcall(gas(), 0x7, 0x7d40, 0x60, 0x7d40, 0x40), 1), success) -mstore(0x7da0, mload(0x7cc0)) - mstore(0x7dc0, mload(0x7ce0)) -mstore(0x7de0, mload(0x7d40)) - mstore(0x7e00, mload(0x7d60)) -success := and(eq(staticcall(gas(), 0x6, 0x7da0, 0x80, 0x7da0, 0x40), 1), success) -mstore(0x7e20, 0x0eb97ab030395b28aaa371bc741e959cfdeb6060fafc1962ad9a54ce791312d5) - mstore(0x7e40, 0x155aee4198fc22dcc374268c99bb0d6c7e3d35a5f4ad1a6564f37bf9abf45095) -mstore(0x7e60, mload(0x6560)) -success := and(eq(staticcall(gas(), 0x7, 0x7e20, 0x60, 0x7e20, 0x40), 1), success) -mstore(0x7e80, mload(0x7da0)) - mstore(0x7ea0, mload(0x7dc0)) -mstore(0x7ec0, mload(0x7e20)) - mstore(0x7ee0, mload(0x7e40)) -success := and(eq(staticcall(gas(), 0x6, 0x7e80, 0x80, 0x7e80, 0x40), 1), success) -mstore(0x7f00, 0x0c1824efd938f810b1ec9b455b6fce7dedf96e18bad57241de1b35d820285f32) - mstore(0x7f20, 0x23b2fdeaeeebb400d3f1dcee64d7296403672cf36ee453e82c3d5d90acdc739a) -mstore(0x7f40, mload(0x6580)) -success := and(eq(staticcall(gas(), 0x7, 0x7f00, 0x60, 0x7f00, 0x40), 1), success) -mstore(0x7f60, mload(0x7e80)) - mstore(0x7f80, mload(0x7ea0)) -mstore(0x7fa0, mload(0x7f00)) - mstore(0x7fc0, mload(0x7f20)) -success := and(eq(staticcall(gas(), 0x6, 0x7f60, 0x80, 0x7f60, 0x40), 1), success) -mstore(0x7fe0, 0x1fce9d9af75dca515792c3dd77525fb8a66cfdd94ba23457d1e35f9d5f94bf2b) - mstore(0x8000, 0x0b87b7a7c54c75c401332977b6002fdbcaf40d42ce73c3e0c8c7bfbf8e9f7564) -mstore(0x8020, mload(0x65a0)) -success := and(eq(staticcall(gas(), 0x7, 0x7fe0, 0x60, 0x7fe0, 0x40), 1), success) -mstore(0x8040, mload(0x7f60)) - mstore(0x8060, mload(0x7f80)) -mstore(0x8080, mload(0x7fe0)) - mstore(0x80a0, mload(0x8000)) -success := and(eq(staticcall(gas(), 0x6, 0x8040, 0x80, 0x8040, 0x40), 1), success) -mstore(0x80c0, mload(0x9a0)) - mstore(0x80e0, mload(0x9c0)) -mstore(0x8100, mload(0x65c0)) -success := and(eq(staticcall(gas(), 0x7, 0x80c0, 0x60, 0x80c0, 0x40), 1), success) -mstore(0x8120, mload(0x8040)) - mstore(0x8140, mload(0x8060)) -mstore(0x8160, mload(0x80c0)) - mstore(0x8180, mload(0x80e0)) -success := and(eq(staticcall(gas(), 0x6, 0x8120, 0x80, 0x8120, 0x40), 1), success) -mstore(0x81a0, mload(0x9e0)) - mstore(0x81c0, mload(0xa00)) -mstore(0x81e0, mload(0x65e0)) -success := and(eq(staticcall(gas(), 0x7, 0x81a0, 0x60, 0x81a0, 0x40), 1), success) -mstore(0x8200, mload(0x8120)) - mstore(0x8220, mload(0x8140)) -mstore(0x8240, mload(0x81a0)) - mstore(0x8260, mload(0x81c0)) -success := and(eq(staticcall(gas(), 0x6, 0x8200, 0x80, 0x8200, 0x40), 1), success) -mstore(0x8280, mload(0xa20)) - mstore(0x82a0, mload(0xa40)) -mstore(0x82c0, mload(0x6600)) -success := and(eq(staticcall(gas(), 0x7, 0x8280, 0x60, 0x8280, 0x40), 1), success) -mstore(0x82e0, mload(0x8200)) - mstore(0x8300, mload(0x8220)) -mstore(0x8320, mload(0x8280)) - mstore(0x8340, mload(0x82a0)) -success := and(eq(staticcall(gas(), 0x6, 0x82e0, 0x80, 0x82e0, 0x40), 1), success) -mstore(0x8360, mload(0x900)) - mstore(0x8380, mload(0x920)) -mstore(0x83a0, mload(0x6620)) -success := and(eq(staticcall(gas(), 0x7, 0x8360, 0x60, 0x8360, 0x40), 1), success) -mstore(0x83c0, mload(0x82e0)) - mstore(0x83e0, mload(0x8300)) -mstore(0x8400, mload(0x8360)) - mstore(0x8420, mload(0x8380)) -success := and(eq(staticcall(gas(), 0x6, 0x83c0, 0x80, 0x83c0, 0x40), 1), success) -mstore(0x8440, mload(0x780)) - mstore(0x8460, mload(0x7a0)) -mstore(0x8480, mload(0x6900)) -success := and(eq(staticcall(gas(), 0x7, 0x8440, 0x60, 0x8440, 0x40), 1), success) -mstore(0x84a0, mload(0x83c0)) - mstore(0x84c0, mload(0x83e0)) -mstore(0x84e0, mload(0x8440)) - mstore(0x8500, mload(0x8460)) -success := and(eq(staticcall(gas(), 0x6, 0x84a0, 0x80, 0x84a0, 0x40), 1), success) -mstore(0x8520, mload(0x7c0)) - mstore(0x8540, mload(0x7e0)) -mstore(0x8560, mload(0x6920)) -success := and(eq(staticcall(gas(), 0x7, 0x8520, 0x60, 0x8520, 0x40), 1), success) -mstore(0x8580, mload(0x84a0)) - mstore(0x85a0, mload(0x84c0)) -mstore(0x85c0, mload(0x8520)) - mstore(0x85e0, mload(0x8540)) -success := and(eq(staticcall(gas(), 0x6, 0x8580, 0x80, 0x8580, 0x40), 1), success) -mstore(0x8600, mload(0x800)) - mstore(0x8620, mload(0x820)) -mstore(0x8640, mload(0x6940)) -success := and(eq(staticcall(gas(), 0x7, 0x8600, 0x60, 0x8600, 0x40), 1), success) -mstore(0x8660, mload(0x8580)) - mstore(0x8680, mload(0x85a0)) -mstore(0x86a0, mload(0x8600)) - mstore(0x86c0, mload(0x8620)) -success := and(eq(staticcall(gas(), 0x6, 0x8660, 0x80, 0x8660, 0x40), 1), success) -mstore(0x86e0, mload(0x840)) - mstore(0x8700, mload(0x860)) -mstore(0x8720, mload(0x6960)) -success := and(eq(staticcall(gas(), 0x7, 0x86e0, 0x60, 0x86e0, 0x40), 1), success) -mstore(0x8740, mload(0x8660)) - mstore(0x8760, mload(0x8680)) -mstore(0x8780, mload(0x86e0)) - mstore(0x87a0, mload(0x8700)) -success := and(eq(staticcall(gas(), 0x6, 0x8740, 0x80, 0x8740, 0x40), 1), success) -mstore(0x87c0, mload(0x880)) - mstore(0x87e0, mload(0x8a0)) -mstore(0x8800, mload(0x6b00)) -success := and(eq(staticcall(gas(), 0x7, 0x87c0, 0x60, 0x87c0, 0x40), 1), success) -mstore(0x8820, mload(0x8740)) - mstore(0x8840, mload(0x8760)) -mstore(0x8860, mload(0x87c0)) - mstore(0x8880, mload(0x87e0)) -success := and(eq(staticcall(gas(), 0x6, 0x8820, 0x80, 0x8820, 0x40), 1), success) -mstore(0x88a0, mload(0x8c0)) - mstore(0x88c0, mload(0x8e0)) -mstore(0x88e0, mload(0x6b20)) -success := and(eq(staticcall(gas(), 0x7, 0x88a0, 0x60, 0x88a0, 0x40), 1), success) -mstore(0x8900, mload(0x8820)) - mstore(0x8920, mload(0x8840)) -mstore(0x8940, mload(0x88a0)) - mstore(0x8960, mload(0x88c0)) -success := and(eq(staticcall(gas(), 0x6, 0x8900, 0x80, 0x8900, 0x40), 1), success) -mstore(0x8980, mload(0x640)) - mstore(0x89a0, mload(0x660)) -mstore(0x89c0, mload(0x6c20)) -success := and(eq(staticcall(gas(), 0x7, 0x8980, 0x60, 0x8980, 0x40), 1), success) -mstore(0x89e0, mload(0x8900)) - mstore(0x8a00, mload(0x8920)) -mstore(0x8a20, mload(0x8980)) - mstore(0x8a40, mload(0x89a0)) -success := and(eq(staticcall(gas(), 0x6, 0x89e0, 0x80, 0x89e0, 0x40), 1), success) -mstore(0x8a60, mload(0x1340)) - mstore(0x8a80, mload(0x1360)) -mstore(0x8aa0, sub(f_q, mload(0x6c60))) -success := and(eq(staticcall(gas(), 0x7, 0x8a60, 0x60, 0x8a60, 0x40), 1), success) -mstore(0x8ac0, mload(0x89e0)) - mstore(0x8ae0, mload(0x8a00)) -mstore(0x8b00, mload(0x8a60)) - mstore(0x8b20, mload(0x8a80)) -success := and(eq(staticcall(gas(), 0x6, 0x8ac0, 0x80, 0x8ac0, 0x40), 1), success) -mstore(0x8b40, mload(0x13e0)) - mstore(0x8b60, mload(0x1400)) -mstore(0x8b80, mload(0x6c80)) -success := and(eq(staticcall(gas(), 0x7, 0x8b40, 0x60, 0x8b40, 0x40), 1), success) -mstore(0x8ba0, mload(0x8ac0)) - mstore(0x8bc0, mload(0x8ae0)) -mstore(0x8be0, mload(0x8b40)) - mstore(0x8c00, mload(0x8b60)) -success := and(eq(staticcall(gas(), 0x6, 0x8ba0, 0x80, 0x8ba0, 0x40), 1), success) -mstore(0x8c20, mload(0x8ba0)) - mstore(0x8c40, mload(0x8bc0)) -mstore(0x8c60, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) - mstore(0x8c80, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x8ca0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0x8cc0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) -mstore(0x8ce0, mload(0x13e0)) - mstore(0x8d00, mload(0x1400)) -mstore(0x8d20, 0x0181624e80f3d6ae28df7e01eaeab1c0e919877a3b8a6b7fbc69a6817d596ea2) - mstore(0x8d40, 0x1783d30dcb12d259bb89098addf6280fa4b653be7a152542a28f7b926e27e648) - mstore(0x8d60, 0x00ae44489d41a0d179e2dfdc03bddd883b7109f8b6ae316a59e815c1a6b35304) - mstore(0x8d80, 0x0b2147ab62a386bd63e6de1522109b8c9588ab466f5aadfde8c41ca3749423ee) -success := and(eq(staticcall(gas(), 0x8, 0x8c20, 0x180, 0x8c20, 0x20), 1), success) -success := and(eq(mload(0x8c20), 1), success) - - if not(success) { revert(0, 0) } - return(0, 0) - - } - } - } \ No newline at end of file diff --git a/pkg/zk-circuits/src/aggregate_agg/circuit.rs b/pkg/zk-circuits/src/aggregate_agg/circuit.rs deleted file mode 100644 index b3e8aee..0000000 --- a/pkg/zk-circuits/src/aggregate_agg/circuit.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::{chips::aggregation::aggregate::{ - AggregationChip, AggregationChipConfig, AggregationChipConfigParams, -}, data::AggregateAgg}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct AggregateAggCircuitConfig { - instance: Column, - aggregation_config: AggregationChipConfig, -} - -impl Circuit for AggregateAgg { - type Config = AggregateAggCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - self.clone() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let num_advice = 3 + AGG_N * 3; - let num_lookup_advice = 1 + num_advice / 12; - let params = AggregationChipConfigParams { - strategy: halo2_ecc::fields::fp::FpStrategy::Simple, - degree: 21, - num_advice, - num_lookup_advice, - num_fixed: 1, - lookup_bits: 20, - limb_bits: 88, - num_limbs: 3, - }; - - AggregateAggCircuitConfig { - instance, - aggregation_config: AggregationChip::configure(meta, params), - } - } - - fn synthesize(&self, config: Self::Config, layouter: impl Layouter) -> Result<(), Error> { - // Build aggregation chip - let aggregation_chip = AggregationChip::construct(config.aggregation_config); - - self.enforce_constraints(layouter, config.instance, &aggregation_chip)?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/aggregate_agg/mod.rs b/pkg/zk-circuits/src/aggregate_agg/mod.rs deleted file mode 100644 index dd619a9..0000000 --- a/pkg/zk-circuits/src/aggregate_agg/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod aggregate; -mod circuit; - -#[cfg(test)] -mod tests; - -// Main circuit -pub use aggregate::*; diff --git a/pkg/zk-circuits/src/aggregate_agg/tests.rs b/pkg/zk-circuits/src/aggregate_agg/tests.rs deleted file mode 100644 index 338fe36..0000000 --- a/pkg/zk-circuits/src/aggregate_agg/tests.rs +++ /dev/null @@ -1,43 +0,0 @@ -use crate::{ - data::{AggregateAgg, ParameterSet}, - evm_verifier, - test::{agg_agg::create_or_load_agg_agg_utxo_snark, agg_utxo::create_or_load_agg_utxo_snarks}, -}; -use halo2_base::halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; - -#[test] -fn test_aggregate_agg() { - let k = 21; - - let utxo_aggs = create_or_load_agg_utxo_snarks(ParameterSet::TwentyOne); - - let aggregate_agg = AggregateAgg::<2>::new(utxo_aggs); - - let prover = - MockProver::::run(k, &aggregate_agg, vec![aggregate_agg.public_inputs()]).unwrap(); - - prover.assert_satisfied(); -} - -#[test] -fn generate_verifier() { - let params_21 = ParameterSet::TwentyOne; - - let utxo_aggs = create_or_load_agg_utxo_snarks(params_21); - let aggregate_agg = create_or_load_agg_agg_utxo_snark(params_21, utxo_aggs); - - // Currently we can only do 1 for the Ethereum verifier as 2 creates a "too large" verifier (25,137 bytes) where - // the max limit is 24,576 bytes (we are so close, we might be able to get this to fit!) - let aggregate_agg_agg = AggregateAgg::<1>::new([aggregate_agg]); - - let pk = aggregate_agg_agg.keygen(params_21).0; - - let yul_code = evm_verifier::generate_verifier( - params_21, - &pk, - vec![aggregate_agg_agg.public_inputs().len()], - ); - - let expected_yul_code = expect_test::expect_file!["./aggregate_verifier.yul"]; - expected_yul_code.assert_eq(&yul_code); -} diff --git a/pkg/zk-circuits/src/aggregate_utxo/aggregate.rs b/pkg/zk-circuits/src/aggregate_utxo/aggregate.rs deleted file mode 100644 index c4743ac..0000000 --- a/pkg/zk-circuits/src/aggregate_utxo/aggregate.rs +++ /dev/null @@ -1,234 +0,0 @@ -use crate::{ - chips::{ - aggregation::{ - aggregate::{accumulator_native, AggregationChip}, - snark::Snark, - }, - binary_decomposition::BinaryDecompositionConfig, - is_constant::IsConstantChip, - is_less_than::IsLessThanChip, - poseidon::PoseidonConfig, - swap::CondSwapChip, - }, - data::{Batch as BatchInsert, ParameterSet, Utxo}, - params::load_params, - util::keygen_from_params, - CircuitKind, -}; -use halo2_base::halo2_proofs::{ - circuit::{Cell, Layouter, Value}, - halo2curves::bn256::{Fr, G1Affine}, - plonk::{Advice, Column, Error, Instance, ProvingKey, VerifyingKey}, -}; -use itertools::Itertools; - -#[derive(Clone, Debug)] -pub struct AggregateUtxo { - /// UTXO to aggregate - utxo: [Snark; UTXO_N], - - /// Insert for the UTXO - insert: BatchInsert, - - /// Instances used to verify the proof - pub agg_instances: Vec, - - /// Private witness to proof - proof: Vec, -} - -impl - AggregateUtxo -{ - pub fn new(utxo: [Snark; UTXO_N], insert: BatchInsert) -> Self { - let snarks = Self::snarks(&utxo); - - let (agg_instances, proof) = accumulator_native(&snarks); - - Self { - // previous_agg, - utxo, - insert, - agg_instances, - proof, - } - } - - fn snarks(utxo: &[Snark; UTXO_N]) -> Vec<&Snark> { - utxo.iter().collect_vec() - } - - #[allow(clippy::too_many_arguments)] - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - instance: Column, - advice: Column, - poseidon_config: PoseidonConfig, - decompose: BinaryDecompositionConfig, - swap_chip: CondSwapChip, - padding_constant_chip: IsConstantChip, - aggregation_chip: &AggregationChip, - is_less_than_chip: &IsLessThanChip, - ) -> Result<(), Error> { - // Gather snarks - let snarks = Self::snarks(&self.utxo); - - // Aggregate proofs - let (agg_cells, utxo_snarks) = aggregation_chip.aggregate( - layouter.namespace(|| "aggregate"), - &snarks, - Value::known(&self.proof), - )?; - - // // Prove merkle insert logic - let insert = self.insert.enforce_constraints( - layouter.namespace(|| "insert"), - advice, - poseidon_config, - decompose, - swap_chip, - padding_constant_chip, - is_less_than_chip, - )?; - - // Constrain verify aggregation cells to public inputs - for (i, cell) in agg_cells.iter().enumerate() { - layouter.constrain_instance(*cell, instance, i)?; - } - let mut instance_counter = agg_cells.len(); - - // Constrain old root - layouter.constrain_instance(insert.old_root.cell(), instance, instance_counter)?; - instance_counter += 1; - - // Constrain new root - layouter.constrain_instance(insert.new_root.cell(), instance, instance_counter)?; - instance_counter += 1; - - // Constrain recent roots & get leafs - let mut utxo_leafs: Vec<&Cell> = vec![]; - for (i, snark_instances) in utxo_snarks.iter().enumerate() { - let instance_counter_base = instance_counter + (i * 3); - - // We only use one instance column per snark, so no need to use the others - let snark_instances = snark_instances.first().unwrap(); - - // First instance is the root (pass through from input proof to agg proof) - let utxo_root = snark_instances.first().expect("Missing utxo root instance"); - layouter.constrain_instance(*utxo_root, instance, instance_counter_base)?; - - // Second instance is kind (mint, burn, transfer) - let hash: &Cell = snark_instances - .get(1) - .expect("Missing mint/burn hash instance"); - layouter.constrain_instance(*hash, instance, instance_counter_base + 1)?; - - // Third instance is value (constrain to output instance) - let value = snark_instances - .get(2) - .expect("Missing mint/burn value instance"); - layouter.constrain_instance(*value, instance, instance_counter_base + 2)?; - - // Remaining instances are leaves - utxo_leafs.extend(snark_instances.iter().skip(3)); - } - - // Constrain utxo and insert leafs to be equal, only for the amount of utxo leafs that should exist. Remaining - // insert leafs are for mints. - for (utxo_leaf, insert_leaf) in utxo_leafs.iter().zip(insert.leafs.iter()).take(LEAVES) { - layouter.assign_region( - || "leaf equality", - |mut region| { - region.constrain_equal(**utxo_leaf, insert_leaf.cell())?; - Ok(()) - }, - )?; - } - - Ok(()) - } - - // TODO: we should use a typed system for extracting cells from the snark instances - pub fn public_inputs(&self) -> Vec { - let mut instances = vec![]; - - // Add verify instances (12) - instances.extend(self.agg_instances.clone()); - - // Add old root (1) - instances.push(self.old_root()); - - // Add new root (1) - instances.push(self.new_root()); - - // Recent root (1), mint/burn hash (1), mint/burn value (1) (= 3 per UTXO) - instances.extend(self.utxo_public_inputs()); - - instances - } - - pub fn utxo_public_inputs(&self) -> Vec<&Fr> { - self.utxo - .iter() - .flat_map(|snark| { - let recent_root = &snark.instances[0][0]; - let mb_hash = &snark.instances[0][1]; - let value = &snark.instances[0][2]; - - vec![recent_root, mb_hash, value] - }) - .collect_vec() - } - - pub fn recent_roots(&self) -> Vec<&Fr> { - self.utxo - .iter() - .map(|snark| &snark.instances[0][0]) - .collect_vec() - } - - pub fn leafs(&self) -> Vec { - self.insert.leafs() - } - - pub fn old_root(&self) -> Fr { - self.insert.old_root() - } - - pub fn new_root(&self) -> Fr { - self.insert.new_root() - } - - pub fn snark(&self, params: ParameterSet) -> Result { - let pk = CircuitKind::AggUtxo.pk(); - Snark::create( - Self::default(), - vec![self.public_inputs()], - load_params(params), - pk, - ) - .map_err(crate::Error::err) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} - -impl Default - for AggregateUtxo -{ - fn default() -> Self { - let utxo = (0..UTXO_N) - .map(|_| Utxo::::default().snark(CircuitKind::Utxo)) - .collect::, _>>() - .unwrap() - .try_into() - .unwrap(); - - let insert = BatchInsert::default(); - - Self::new(utxo, insert) - } -} diff --git a/pkg/zk-circuits/src/aggregate_utxo/circuit.rs b/pkg/zk-circuits/src/aggregate_utxo/circuit.rs deleted file mode 100644 index 6e7b6f7..0000000 --- a/pkg/zk-circuits/src/aggregate_utxo/circuit.rs +++ /dev/null @@ -1,189 +0,0 @@ -use super::aggregate::AggregateUtxo; -use crate::{ - chips::{ - aggregation::aggregate::{ - AggregationChip, AggregationChipConfig, AggregationChipConfigParams, - }, - binary_decomposition::BinaryDecompositionConfig, - is_constant::{IsConstantChip, IsConstantConfig}, - is_less_than::{IsLessThanChip, IsLessThanChipConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, - }, - data::Note, -}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct AggregateUtxoCircuitConfig { - instance: Column, - advice: Column, - poseidon_config: PoseidonConfig, - binary_decomposition_config: BinaryDecompositionConfig, - swap_config: CondSwapConfig, - is_padding_config: IsConstantConfig, - aggregation_config: AggregationChipConfig, - is_less_than: IsLessThanChipConfig, -} - -impl Circuit - for AggregateUtxo -{ - type Config = AggregateUtxoCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - self.clone() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let num_advice = 2 + UTXO_N * 2; - let num_lookup_advice = 1 + num_advice / 12; - let params = AggregationChipConfigParams { - strategy: halo2_ecc::fields::fp::FpStrategy::Simple, - degree: 21, - num_advice, - num_lookup_advice, - num_fixed: 1, - lookup_bits: 20, - limb_bits: 88, - num_limbs: 3, - }; - - let aggregation_config = AggregationChip::configure(meta, params); - - // let advices = aggregation_config - // .base_field_config - // .range - // .gate - // .basic_gates - // .iter() - // .flat_map(|gate| gate.iter().map(|gate| gate.value)) - // .collect::>(); - - // println!("advices: {:?}", advices.len()); - - // 2 advices - // let advices = aggregation_config - // .base_field_config - // .range - // .lookup_advice - // .iter() - // .flatten() - // .cloned() - // .collect::>(); - - // println!("advices: {:?}", advices.len()); - - // // 1 fixed - // let fixed_1 = aggregation_config - // .base_field_config - // .range - // .gate - // .constants - // .iter() - // .collect::>(); - - // println!("fixed: {:?}", fixed_1.len()); - - // // x fixed - // let fixed_2 = aggregation_config - // .base_field_config - // .range - // .gate - // .basic_gates - // .iter() - // .flat_map(|gate| gate.iter().flat_map(|gate| gate.q_enable_plus.clone())) - // .collect::>(); - - // println!("fixed: {:?}", fixed_2.len()); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - // *fixed_1[0], - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - let q_range_check = meta.selector(); - - // TODO: q_range_check doesn't seem corrrect - let binary_decomposition_config = - BinaryDecompositionConfig::configure(meta, q_range_check, advices[0], advices[1]); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Padding chip - let is_padding_config = IsConstantChip::configure( - meta, - advices[0], - advices[1], - advices[2], - Note::padding_note().commitment().into(), - ); - - let is_less_than = - IsLessThanChip::configure(meta, [advices[0], advices[1], advices[2], advices[3]]); - - AggregateUtxoCircuitConfig { - instance, - advice: advices[0], - poseidon_config, - binary_decomposition_config, - swap_config, - is_padding_config, - aggregation_config, - is_less_than, - } - } - - fn synthesize(&self, config: Self::Config, layouter: impl Layouter) -> Result<(), Error> { - // Build aggregation chip - let aggregation_chip = AggregationChip::construct(config.aggregation_config); - - self.enforce_constraints( - layouter, - config.instance, - config.advice, - config.poseidon_config, - config.binary_decomposition_config, - CondSwapChip::construct(config.swap_config), - IsConstantChip::construct(config.is_padding_config), - &aggregation_chip, - &IsLessThanChip::construct(config.is_less_than), - )?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/aggregate_utxo/constants.rs b/pkg/zk-circuits/src/aggregate_utxo/constants.rs deleted file mode 100644 index 0b793c1..0000000 --- a/pkg/zk-circuits/src/aggregate_utxo/constants.rs +++ /dev/null @@ -1,45 +0,0 @@ -use expect_test::Expect; -use halo2_base::halo2_proofs::{halo2curves::bn256::G1Affine, plonk::VerifyingKey}; -use once_cell::sync::Lazy; - -use super::AggregateUtxo; - -const GENERATED_UTXO_AGGREGATE_3_161_12_VK: Expect = expect_test::expect![[r#" - "00000015000000187cdf4bdb7d3f837997a3279f7c37a94ad41e48cc4676de78ef164c4d53e57ea8741d9d613f77c292e8d1db3612d4deda12f5cd4c9bc5baaefd28fe16474c1e92107d17ed4de445c1a6cce6cdead4855348027b7822bb7ae2822ab4e0d8c3ed87f9d64c47561a18a1428d2f3d3822561fb281c06accb9a6a8b1320f7ced0932a7c5df5cc2b49149b5460af5a170d5023c0dbc85d2c28f39ff377ad66199305a8bf0a0a56085773d2f49a8b76ede5311934352de22833a3f2f8a6f069cd58dff1d02ae920386c882283c466ead3a9e8ba724f6e409b36e9bd0aa6b49497ffdbf9efba688991c9272fd1f76109e34311b4b2094987a32bf45217fd0f4a63ceea7980967a769f962ef9ba9d3a7afbe7ced5bd7668271b72250e97f0a6dc7babf40174cfeaccd7269609a8fd1b1a68ed1796d239d4a2c9654a8fc5db7e1ffc5b46416fb8db527ada9ddeb42cebaa9a0183440e4123bf7cb04892fa678f4d43e5aad88736b8906cf0d2624c97ef62fe1c63b803bf9ddf2840aced1f8f6f2fde3be1e9af0b6daf1e493f5d2fd047078dc5315b5520fcdc4b85272eb0d24e69d9c127f87b6837fd192a049e365c0d8accda539e2b3feaeafda65f28fb22a0efefd74b306bc6bb2a9979c85cf9855a9410778606b1af0d9c0d33578ca32994f6692883c873be96da8d37aa1a690fc8add9670be302d546943c0c269895dca0ff7d9411c0c8546fd9db1bb06d05449e991edf31461eda065e2ddcefac6c3393665966daf839e3dd52f78458fa11e5f7c93b52b2ee755b425d142b6ebed0695146c5c62c5afe4bbef572e329be8f9fb617665034b3ffb91db659a55fb2da5fff3e07410aa95a2b85ac92820fa779ea806647fc6ed975140082a42c8c921f285d842396f3d2be165069dc095be52f5f97e2939b2f5bf63b39684b0262d6dd0ec754d67a4459bc9a07a5f4e9cd11bcfe74d2d9f744b7ea615cf474e13b8e610706b597645f02830f715bdb63d53388d8d52d387a5a7c1157ba89e422c71772faa28f4ca2c4c1ac745fb9a91da64307bd5c6480233c5e388889bc0419f0108981b187f8ac27616fb2e8b794aa4df3bc42db788f16f926c1640768d1c613add04a0782e3b38c72fa7cdda8fd4d45cdbfc990f2cb7bf914eb12f434e6d6d083708ae24fbe49f15891443a300d21049096ed632e8608cff3845f2d859d2489dfa7d094717239d7b29ff832e069eda678eaebb5d878d30d29d2f9359d727cf8f9d1b2bf9664d552d08743930a6ca3a5ed164d71edb32d34b200957db585751ef5a30561ea5ced19a8952d27dc648a4cca22909629b762deb4b03078e0b5290e6fe9c80ec28f803432c8a130728a45ce437e1d65a9742efa9f6790cccbe16471cf24412837432545225e73f62dc877860fd8edd565dfcb813316bdad1997263eadd560a0da674d07ea46fe0715ac561158b29680682c00e3dbfe61070a0afc3d9ce81e8cd61bb635c2cafbbd577c119bc1b37987d81c69236084cbee68140feed04e112c07073c4819eaa98594eef61408009a95f1b86164eda3cf4b7c8196d4986046d648b5fc9d805a8aadab654623de3380cf550c3e6128eb95cca9060d3cb784a83d342bbe0981dda7328db8c1c5328fe5c39b507e9e98e20c4148a339bad639aa69629afe36d99faa494b87f778e5ec93b9fc9468f900765ee5e60da6e43141d1809fb4d7761814efa88675b4b8875894ed9d1bbd315970ca3e45d6686bbadc3d5c91424e44104fa04fe1fa61d5ebd353931eb7fe4e1ff714eb7f4c425c83ef4ac50a353580e9b602852bbbe700c4c2414081b80cf2614b6133f22f52ebd29ec1ac3ddd2ff5f98e3a319d6aa24343861fec09f10a1bfcdc0507241db47a95202d583c490100088d7f3d4d088e09c765a93fdbfcf7872fc6df899565fe887c4781a6a322b353020624067df92e16ec47c14863662fb2a059232a14a8bba63b1d6fc9fcea9a3ada1" -"#]]; - -pub static UTXO_AGGREGATE_3_161_12_VK: Lazy> = Lazy::new(|| { - #[allow(clippy::unwrap_used)] - let vk_bytes = hex::decode( - GENERATED_UTXO_AGGREGATE_3_161_12_VK - .data() - .replace(['\n', '"', ' '], ""), - ) - .unwrap(); - #[allow(clippy::unwrap_used)] - VerifyingKey::::from_bytes::>( - &vk_bytes, - halo2_base::halo2_proofs::SerdeFormat::Processed, - ) - .unwrap() -}); - -#[cfg(test)] -mod tests { - use crate::{aggregate_utxo::AggregateUtxo, data::ParameterSet}; - - use super::*; - - #[test] - #[ignore] - fn generate_utxo_aggregate_vk() { - let aggregate_utxo = AggregateUtxo::<3, 161, 12>::default(); - - let params = ParameterSet::TwentyOne; - let (_, vk) = aggregate_utxo.keygen(params); - - let generated_vk = - hex::encode(vk.to_bytes(halo2_base::halo2_proofs::SerdeFormat::Processed)); - GENERATED_UTXO_AGGREGATE_3_161_12_VK.assert_debug_eq(&generated_vk); - } -} diff --git a/pkg/zk-circuits/src/aggregate_utxo/mod.rs b/pkg/zk-circuits/src/aggregate_utxo/mod.rs deleted file mode 100644 index d82074b..0000000 --- a/pkg/zk-circuits/src/aggregate_utxo/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod aggregate; -mod circuit; -pub mod constants; - -#[cfg(test)] -pub(crate) mod tests; - -// Main circuit -pub use aggregate::*; diff --git a/pkg/zk-circuits/src/aggregate_utxo/tests.rs b/pkg/zk-circuits/src/aggregate_utxo/tests.rs deleted file mode 100644 index 56cdd8f..0000000 --- a/pkg/zk-circuits/src/aggregate_utxo/tests.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::test::rollup::Rollup; -use halo2_base::halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; - -#[test] -fn test_aggregate_utxo() { - let k = 21; - - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - let alice = rollup.new_wallet(); - let sally = rollup.new_wallet(); - - // Add existing notes to the tree - let bob_n1 = rollup.unverified_add_unspent_note(&bob, 100); - let bob_n2 = rollup.unverified_add_unspent_note(&bob, 100); - let alice_n3 = rollup.unverified_add_unspent_note(&alice, 100); - - // Send 100 from bob to sally - let utxo1 = rollup.transfer(bob_n1, sally.new_note(100)); - - // Send 100 from bob to alice - let utxo2 = rollup.transfer(bob_n2, alice.new_note(100)); - - // Send 100 from alice to sally - let utxo3 = rollup.transfer(alice_n3, sally.new_note(100)); - - // Aggregate UTXOs - let utxos = [utxo1, utxo2, utxo3]; - let aggregate_utxo = rollup.aggregate_utxo(&utxos); - - let prover = - MockProver::::run(k, &aggregate_utxo, vec![aggregate_utxo.public_inputs()]).unwrap(); - - prover.assert_satisfied(); -} diff --git a/pkg/zk-circuits/src/bin/vk_hash.rs b/pkg/zk-circuits/src/bin/vk_hash.rs new file mode 100644 index 0000000..b844626 --- /dev/null +++ b/pkg/zk-circuits/src/bin/vk_hash.rs @@ -0,0 +1,64 @@ +use acvm::AcirField; +use bn254_blackbox_solver::poseidon_hash; +use element::{Base, Element}; +use std::env; +use std::fs; +use std::path::Path; +use zk_circuits::verify::VerificationKey; + +fn main() { + let args: Vec = env::args().collect(); + if args.len() != 2 { + eprintln!("Usage: {} ", args[0]); + std::process::exit(1); + } + + let vk_fields_path = &args[1]; + + if !Path::new(vk_fields_path).exists() { + eprintln!("Error: File {vk_fields_path} does not exist"); + std::process::exit(1); + } + + let vk_fields_data = match fs::read(vk_fields_path) { + Ok(data) => data, + Err(e) => { + eprintln!("Error reading file {vk_fields_path}: {e}"); + std::process::exit(1); + } + }; + + let vk_fields: Vec = match serde_json::from_slice(&vk_fields_data) { + Ok(fields) => fields, + Err(e) => { + eprintln!("Error parsing JSON from {vk_fields_path}: {e}"); + std::process::exit(1); + } + }; + + let vk_fields = vk_fields + .into_iter() + .map(|field| { + Base::from_hex(&field).unwrap_or_else(|| { + eprintln!("Error parsing hex field {field}"); + std::process::exit(1); + }) + }) + .collect::>(); + + let verification_key = VerificationKey(vk_fields); + + let hash = match poseidon_hash(&verification_key.0) { + Ok(hash) => hash, + Err(e) => { + eprintln!("Error computing Poseidon hash: {e}"); + std::process::exit(1); + } + }; + + let hash_u256 = Element::from_base(hash).to_u256(); + let hash_hex = format!("0x{hash_u256:064x}"); + + println!("u256: {hash_u256}"); + println!("hex: {hash_hex}"); +} diff --git a/pkg/zk-circuits/src/burn/burn.rs b/pkg/zk-circuits/src/burn/burn.rs deleted file mode 100644 index 05a1fad..0000000 --- a/pkg/zk-circuits/src/burn/burn.rs +++ /dev/null @@ -1,156 +0,0 @@ -use crate::chips::poseidon::poseidon_hash_gadget; -use crate::chips::swap::CondSwapChip; -use crate::chips::{is_constant::IsConstantChip, poseidon::PoseidonConfig}; -use crate::data::{Burn, Note, ParameterSet}; -use crate::evm_verifier; -use crate::util::{assign_constant, assign_private_input, keygen_from_params}; -use halo2_base::halo2_proofs::circuit::Value; -use halo2_base::halo2_proofs::halo2curves::bn256::G1Affine; -use halo2_base::halo2_proofs::plonk::VerifyingKey; -use halo2_base::halo2_proofs::{ - circuit::Layouter, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error, Instance, ProvingKey}, -}; -use smirk::{hash_merge, Element}; - -#[cfg(test)] -use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; -#[cfg(test)] -use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; - -#[cfg(test)] -use crate::proof::Proof; -#[cfg(test)] -use rand::RngCore; - -impl Burn { - pub(crate) fn enforce_constraints( - &self, - mut layouter: impl Layouter, - instance: Column, - advice: Column, - poseidon_config: PoseidonConfig, - is_zero_chip: IsConstantChip, - swap_chip: CondSwapChip, - ) -> Result<(), Error> { - // Witness to address - let to_address = assign_private_input( - || "to address witness", - layouter.namespace(|| "to_address witness"), - advice, - Value::known(self.to_address.to_base()), - )?; - - let zero = assign_constant( - || "zero witness", - layouter.namespace(|| "zero witness"), - advice, - Fr::zero(), - )?; - - layouter.constrain_instance(to_address.cell(), instance, 0)?; - - // Witness secret_key - let secret_key: halo2_base::halo2_proofs::circuit::AssignedCell = - assign_private_input( - || "secret key witness", - layouter.namespace(|| "secret key witness"), - advice, - Value::known(self.secret_key.to_base()), - )?; - - for (i, note) in self.notes.iter().enumerate() { - // Ensure note is of valid construction - let note_cells = note.enforce_constraints( - layouter.namespace(|| format!("input_note {i}")), - advice, - poseidon_config.clone(), - is_zero_chip.clone(), - swap_chip.clone(), - )?; - - // Generate the nullifier - let nullifier = poseidon_hash_gadget( - poseidon_config.clone(), - layouter.namespace(|| "nullifer hash"), - [ - note_cells.cm.clone(), - secret_key.clone(), - note_cells.psi.clone(), - zero.clone(), - ], - )?; - - // Constrain note details to public instances - layouter.constrain_instance(nullifier.cell(), instance, i * 4 + 1)?; - layouter.constrain_instance(note_cells.value.cell(), instance, (i * 4) + 2)?; - layouter.constrain_instance(note_cells.source.cell(), instance, (i * 4) + 3)?; - - let sig = poseidon_hash_gadget( - poseidon_config.clone(), - layouter.namespace(|| "sig hash"), - [ - nullifier.clone(), - secret_key.clone(), - to_address.clone(), - zero.clone(), - ], - )?; - - layouter.constrain_instance(sig.cell(), instance, (i * 4) + 4)?; - } - - Ok(()) - } - - pub fn signature(&self, note: &Note) -> Element { - hash_merge([ - note.nullifier(self.secret_key), - self.secret_key, - self.to_address, - // Padding - Element::ZERO, - ]) - } - - pub(crate) fn public_inputs(&self) -> Vec { - let mut inputs = vec![]; - - // Address of request - inputs.push(self.to_address.to_base()); - - for note in self.notes.iter() { - // Expose the note details we need to verify in Ethereum - inputs.push(note.nullifier(self.secret_key).into()); - inputs.push(note.value().into()); - inputs.push(note.source().into()); - inputs.push(self.signature(note).into()); - } - - inputs - } - - #[cfg(test)] - pub(crate) fn prove( - &self, - params: &ParamsKZG, - pk: &ProvingKey, - rng: impl RngCore, - ) -> Result { - let circuit = Self::default(); - let instance = self.public_inputs(); - let instances = &[instance.as_slice()]; - Proof::create(params, pk, circuit, instances, rng) - } - - pub fn evm_proof(&self, params: ParameterSet) -> Result, crate::Error> { - let (pk, _) = self.keygen(params); - - evm_verifier::gen_proof(params, &pk, self.clone(), &[&self.public_inputs()]) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} diff --git a/pkg/zk-circuits/src/burn/burn_verifier.yul b/pkg/zk-circuits/src/burn/burn_verifier.yul deleted file mode 100644 index 15503c6..0000000 --- a/pkg/zk-circuits/src/burn/burn_verifier.yul +++ /dev/null @@ -1,1621 +0,0 @@ - - object "plonk_verifier" { - code { - function allocate(size) -> ptr { - ptr := mload(0x40) - if eq(ptr, 0) { ptr := 0x60 } - mstore(0x40, add(ptr, size)) - } - let size := datasize("Runtime") - let offset := allocate(size) - datacopy(offset, dataoffset("Runtime"), size) - return(offset, size) - } - object "Runtime" { - code { - let success:bool := true - let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - function validate_ec_point(x, y) -> valid:bool { - { - let x_lt_p:bool := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_lt_p:bool := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - valid := and(x_lt_p, y_lt_p) - } - { - let x_is_zero:bool := eq(x, 0) - let y_is_zero:bool := eq(y, 0) - let x_or_y_is_zero:bool := or(x_is_zero, y_is_zero) - let x_and_y_is_not_zero:bool := not(x_or_y_is_zero) - valid := and(x_and_y_is_not_zero, valid) - } - { - let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube := mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube_plus_3 := addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_square_eq_x_cube_plus_3:bool := eq(x_cube_plus_3, y_square) - valid := and(y_square_eq_x_cube_plus_3, valid) - } - } - mstore(0x20, mod(calldataload(0x0), f_q)) -mstore(0x40, mod(calldataload(0x20), f_q)) -mstore(0x60, mod(calldataload(0x40), f_q)) -mstore(0x80, mod(calldataload(0x60), f_q)) -mstore(0xa0, mod(calldataload(0x80), f_q)) -mstore(0x0, 10322602023388315580025713573786230810385694011781111745724901402505239809551) - - { - let x := calldataload(0xa0) - mstore(0xc0, x) - let y := calldataload(0xc0) - mstore(0xe0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0xe0) - mstore(0x100, x) - let y := calldataload(0x100) - mstore(0x120, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x120) - mstore(0x140, x) - let y := calldataload(0x140) - mstore(0x160, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x160) - mstore(0x180, x) - let y := calldataload(0x180) - mstore(0x1a0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x1a0) - mstore(0x1c0, x) - let y := calldataload(0x1c0) - mstore(0x1e0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x200, keccak256(0x0, 512)) -{ - let hash := mload(0x200) - mstore(0x220, mod(hash, f_q)) - mstore(0x240, hash) - } -mstore8(608, 1) -mstore(0x260, keccak256(0x240, 33)) -{ - let hash := mload(0x260) - mstore(0x280, mod(hash, f_q)) - mstore(0x2a0, hash) - } -mstore8(704, 1) -mstore(0x2c0, keccak256(0x2a0, 33)) -{ - let hash := mload(0x2c0) - mstore(0x2e0, mod(hash, f_q)) - mstore(0x300, hash) - } - - { - let x := calldataload(0x1e0) - mstore(0x320, x) - let y := calldataload(0x200) - mstore(0x340, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x220) - mstore(0x360, x) - let y := calldataload(0x240) - mstore(0x380, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x260) - mstore(0x3a0, x) - let y := calldataload(0x280) - mstore(0x3c0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x2a0) - mstore(0x3e0, x) - let y := calldataload(0x2c0) - mstore(0x400, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x420, keccak256(0x300, 288)) -{ - let hash := mload(0x420) - mstore(0x440, mod(hash, f_q)) - mstore(0x460, hash) - } - - { - let x := calldataload(0x2e0) - mstore(0x480, x) - let y := calldataload(0x300) - mstore(0x4a0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x320) - mstore(0x4c0, x) - let y := calldataload(0x340) - mstore(0x4e0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x360) - mstore(0x500, x) - let y := calldataload(0x380) - mstore(0x520, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x3a0) - mstore(0x540, x) - let y := calldataload(0x3c0) - mstore(0x560, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x3e0) - mstore(0x580, x) - let y := calldataload(0x400) - mstore(0x5a0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x5c0, keccak256(0x460, 352)) -{ - let hash := mload(0x5c0) - mstore(0x5e0, mod(hash, f_q)) - mstore(0x600, hash) - } -mstore(0x620, mod(calldataload(0x420), f_q)) -mstore(0x640, mod(calldataload(0x440), f_q)) -mstore(0x660, mod(calldataload(0x460), f_q)) -mstore(0x680, mod(calldataload(0x480), f_q)) -mstore(0x6a0, mod(calldataload(0x4a0), f_q)) -mstore(0x6c0, mod(calldataload(0x4c0), f_q)) -mstore(0x6e0, mod(calldataload(0x4e0), f_q)) -mstore(0x700, mod(calldataload(0x500), f_q)) -mstore(0x720, mod(calldataload(0x520), f_q)) -mstore(0x740, mod(calldataload(0x540), f_q)) -mstore(0x760, mod(calldataload(0x560), f_q)) -mstore(0x780, mod(calldataload(0x580), f_q)) -mstore(0x7a0, mod(calldataload(0x5a0), f_q)) -mstore(0x7c0, mod(calldataload(0x5c0), f_q)) -mstore(0x7e0, mod(calldataload(0x5e0), f_q)) -mstore(0x800, mod(calldataload(0x600), f_q)) -mstore(0x820, mod(calldataload(0x620), f_q)) -mstore(0x840, mod(calldataload(0x640), f_q)) -mstore(0x860, mod(calldataload(0x660), f_q)) -mstore(0x880, mod(calldataload(0x680), f_q)) -mstore(0x8a0, mod(calldataload(0x6a0), f_q)) -mstore(0x8c0, mod(calldataload(0x6c0), f_q)) -mstore(0x8e0, mod(calldataload(0x6e0), f_q)) -mstore(0x900, mod(calldataload(0x700), f_q)) -mstore(0x920, mod(calldataload(0x720), f_q)) -mstore(0x940, mod(calldataload(0x740), f_q)) -mstore(0x960, mod(calldataload(0x760), f_q)) -mstore(0x980, mod(calldataload(0x780), f_q)) -mstore(0x9a0, mod(calldataload(0x7a0), f_q)) -mstore(0x9c0, mod(calldataload(0x7c0), f_q)) -mstore(0x9e0, mod(calldataload(0x7e0), f_q)) -mstore(0xa00, mod(calldataload(0x800), f_q)) -mstore(0xa20, mod(calldataload(0x820), f_q)) -mstore(0xa40, mod(calldataload(0x840), f_q)) -mstore(0xa60, mod(calldataload(0x860), f_q)) -mstore(0xa80, mod(calldataload(0x880), f_q)) -mstore(0xaa0, mod(calldataload(0x8a0), f_q)) -mstore(0xac0, mod(calldataload(0x8c0), f_q)) -mstore(0xae0, mod(calldataload(0x8e0), f_q)) -mstore(0xb00, mod(calldataload(0x900), f_q)) -mstore(0xb20, mod(calldataload(0x920), f_q)) -mstore(0xb40, mod(calldataload(0x940), f_q)) -mstore(0xb60, keccak256(0x600, 1376)) -{ - let hash := mload(0xb60) - mstore(0xb80, mod(hash, f_q)) - mstore(0xba0, hash) - } -mstore8(3008, 1) -mstore(0xbc0, keccak256(0xba0, 33)) -{ - let hash := mload(0xbc0) - mstore(0xbe0, mod(hash, f_q)) - mstore(0xc00, hash) - } - - { - let x := calldataload(0x960) - mstore(0xc20, x) - let y := calldataload(0x980) - mstore(0xc40, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0xc60, keccak256(0xc00, 96)) -{ - let hash := mload(0xc60) - mstore(0xc80, mod(hash, f_q)) - mstore(0xca0, hash) - } - - { - let x := calldataload(0x9a0) - mstore(0xcc0, x) - let y := calldataload(0x9c0) - mstore(0xce0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0xd00, mulmod(mload(0x5e0), mload(0x5e0), f_q)) -mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) -mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) -mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) -mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) -mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) -mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) -mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) -mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) -mstore(0xe20, addmod(mload(0xe00), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0xe40, mulmod(mload(0xe20), 21845492397480214137827955734036069473141043376196471776620668631523902619649, f_q)) -mstore(0xe60, mulmod(mload(0xe40), 11423757818648818765461327411617109120243501240676889555478397529313037714234, f_q)) -mstore(0xe80, addmod(mload(0x5e0), 10464485053190456456785078333640165968304863159739144788219806657262770781383, f_q)) -mstore(0xea0, mulmod(mload(0xe40), 18658909205715493985327367002986689246357274798059125448824250603171843521466, f_q)) -mstore(0xec0, addmod(mload(0x5e0), 3229333666123781236919038742270585842191089602356908894873953583403964974151, f_q)) -mstore(0xee0, mulmod(mload(0xe40), 13677048343952077794467995888380402608453928821079198134318291065290235358859, f_q)) -mstore(0xf00, addmod(mload(0x5e0), 8211194527887197427778409856876872480094435579336836209379913121285573136758, f_q)) -mstore(0xf20, mulmod(mload(0xe40), 9936069627611189518829255670237324269287146421271524553312532036927871056678, f_q)) -mstore(0xf40, addmod(mload(0x5e0), 11952173244228085703417150075019950819261217979144509790385672149647937438939, f_q)) -mstore(0xf60, mulmod(mload(0xe40), 14158528901797138466244491986759313854666262535363044392173788062030301470987, f_q)) -mstore(0xf80, addmod(mload(0x5e0), 7729713970042136756001913758497961233882101865052989951524416124545507024630, f_q)) -mstore(0xfa0, mulmod(mload(0xe40), 4260969412351770314333984243767775737437927068151180798236715529158398853173, f_q)) -mstore(0xfc0, addmod(mload(0x5e0), 17627273459487504907912421501489499351110437332264853545461488657417409642444, f_q)) -mstore(0xfe0, mulmod(mload(0xe40), 1, f_q)) -mstore(0x1000, addmod(mload(0x5e0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0x1020, mulmod(mload(0xe40), 6252951856119339508807713076978770803512896272623217303779254502899773638908, f_q)) -mstore(0x1040, addmod(mload(0x5e0), 15635291015719935713438692668278504285035468127792817039918949683676034856709, f_q)) -mstore(0x1060, mulmod(mload(0xe40), 7393649265675507591155086225434297871937368251641985215568891852805958167681, f_q)) -mstore(0x1080, addmod(mload(0x5e0), 14494593606163767631091319519822977216610996148774049128129312333769850327936, f_q)) -mstore(0x10a0, mulmod(mload(0xe40), 7274544076708594923658723438209548371461798187263202684844743708658536398896, f_q)) -mstore(0x10c0, addmod(mload(0x5e0), 14613698795130680298587682307047726717086566213152831658853460477917272096721, f_q)) -mstore(0x10e0, mulmod(mload(0xe40), 18154240498369470423574571952998640420834620155273666494480695920805672807787, f_q)) -mstore(0x1100, addmod(mload(0x5e0), 3734002373469804798671833792258634667713744245142367849217508265770135687830, f_q)) -{ - let prod := mload(0xe80) - - prod := mulmod(mload(0xec0), prod, f_q) - mstore(0x1120, prod) - - prod := mulmod(mload(0xf00), prod, f_q) - mstore(0x1140, prod) - - prod := mulmod(mload(0xf40), prod, f_q) - mstore(0x1160, prod) - - prod := mulmod(mload(0xf80), prod, f_q) - mstore(0x1180, prod) - - prod := mulmod(mload(0xfc0), prod, f_q) - mstore(0x11a0, prod) - - prod := mulmod(mload(0x1000), prod, f_q) - mstore(0x11c0, prod) - - prod := mulmod(mload(0x1040), prod, f_q) - mstore(0x11e0, prod) - - prod := mulmod(mload(0x1080), prod, f_q) - mstore(0x1200, prod) - - prod := mulmod(mload(0x10c0), prod, f_q) - mstore(0x1220, prod) - - prod := mulmod(mload(0x1100), prod, f_q) - mstore(0x1240, prod) - - prod := mulmod(mload(0xe20), prod, f_q) - mstore(0x1260, prod) - - } -mstore(0x12a0, 32) -mstore(0x12c0, 32) -mstore(0x12e0, 32) -mstore(0x1300, mload(0x1260)) -mstore(0x1320, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x1340, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x12a0, 0xc0, 0x1280, 0x20), 1), success) -{ - - let inv := mload(0x1280) - let v - - v := mload(0xe20) - mstore(3616, mulmod(mload(0x1240), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1100) - mstore(4352, mulmod(mload(0x1220), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x10c0) - mstore(4288, mulmod(mload(0x1200), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1080) - mstore(4224, mulmod(mload(0x11e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1040) - mstore(4160, mulmod(mload(0x11c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1000) - mstore(4096, mulmod(mload(0x11a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xfc0) - mstore(4032, mulmod(mload(0x1180), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xf80) - mstore(3968, mulmod(mload(0x1160), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xf40) - mstore(3904, mulmod(mload(0x1140), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xf00) - mstore(3840, mulmod(mload(0x1120), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xec0) - mstore(3776, mulmod(mload(0xe80), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0xe80, inv) - - } -mstore(0x1360, mulmod(mload(0xe60), mload(0xe80), f_q)) -mstore(0x1380, mulmod(mload(0xea0), mload(0xec0), f_q)) -mstore(0x13a0, mulmod(mload(0xee0), mload(0xf00), f_q)) -mstore(0x13c0, mulmod(mload(0xf20), mload(0xf40), f_q)) -mstore(0x13e0, mulmod(mload(0xf60), mload(0xf80), f_q)) -mstore(0x1400, mulmod(mload(0xfa0), mload(0xfc0), f_q)) -mstore(0x1420, mulmod(mload(0xfe0), mload(0x1000), f_q)) -mstore(0x1440, mulmod(mload(0x1020), mload(0x1040), f_q)) -mstore(0x1460, mulmod(mload(0x1060), mload(0x1080), f_q)) -mstore(0x1480, mulmod(mload(0x10a0), mload(0x10c0), f_q)) -mstore(0x14a0, mulmod(mload(0x10e0), mload(0x1100), f_q)) -{ - let result := mulmod(mload(0x1420), mload(0x20), f_q) -result := addmod(mulmod(mload(0x1440), mload(0x40), f_q), result, f_q) -result := addmod(mulmod(mload(0x1460), mload(0x60), f_q), result, f_q) -result := addmod(mulmod(mload(0x1480), mload(0x80), f_q), result, f_q) -result := addmod(mulmod(mload(0x14a0), mload(0xa0), f_q), result, f_q) -mstore(5312, result) - } -mstore(0x14e0, addmod(mload(0x640), mload(0x780), f_q)) -mstore(0x1500, mulmod(mload(0x14e0), mload(0x14e0), f_q)) -mstore(0x1520, mulmod(mload(0x1500), mload(0x1500), f_q)) -mstore(0x1540, mulmod(mload(0x14e0), mload(0x1520), f_q)) -mstore(0x1560, mulmod(mload(0x1540), 7511745149465107256748700652201246547602992235352608707588321460060273774987, f_q)) -mstore(0x1580, addmod(mload(0x660), mload(0x800), f_q)) -mstore(0x15a0, mulmod(mload(0x1580), mload(0x1580), f_q)) -mstore(0x15c0, mulmod(mload(0x15a0), mload(0x15a0), f_q)) -mstore(0x15e0, mulmod(mload(0x1580), mload(0x15c0), f_q)) -mstore(0x1600, mulmod(mload(0x15e0), 10370080108974718697676803824769673834027675643658433702224577712625900127200, f_q)) -mstore(0x1620, addmod(mload(0x1560), mload(0x1600), f_q)) -mstore(0x1640, addmod(mload(0x680), mload(0x820), f_q)) -mstore(0x1660, mulmod(mload(0x1640), mload(0x1640), f_q)) -mstore(0x1680, mulmod(mload(0x1660), mload(0x1660), f_q)) -mstore(0x16a0, mulmod(mload(0x1640), mload(0x1680), f_q)) -mstore(0x16c0, mulmod(mload(0x16a0), 19705173408229649878903981084052839426532978878058043055305024233888854471533, f_q)) -mstore(0x16e0, addmod(mload(0x1620), mload(0x16c0), f_q)) -mstore(0x1700, addmod(mload(0x16e0), sub(f_q, mload(0x6c0)), f_q)) -mstore(0x1720, mulmod(mload(0x1700), mload(0x840), f_q)) -mstore(0x1740, mulmod(mload(0x440), mload(0x1720), f_q)) -mstore(0x1760, mulmod(mload(0x1540), 18732019378264290557468133440468564866454307626475683536618613112504878618481, f_q)) -mstore(0x1780, mulmod(mload(0x15e0), 20870176810702568768751421378473869562658540583882454726129544628203806653987, f_q)) -mstore(0x17a0, addmod(mload(0x1760), mload(0x1780), f_q)) -mstore(0x17c0, mulmod(mload(0x16a0), 7266061498423634438633389053804536045105766754026813321943009179476902321146, f_q)) -mstore(0x17e0, addmod(mload(0x17a0), mload(0x17c0), f_q)) -mstore(0x1800, addmod(mload(0x17e0), sub(f_q, mload(0x6e0)), f_q)) -mstore(0x1820, mulmod(mload(0x1800), mload(0x840), f_q)) -mstore(0x1840, addmod(mload(0x1740), mload(0x1820), f_q)) -mstore(0x1860, mulmod(mload(0x440), mload(0x1840), f_q)) -mstore(0x1880, mulmod(mload(0x1540), 9131299761947733513298312097611845208338517739621853568979632113419485819303, f_q)) -mstore(0x18a0, mulmod(mload(0x15e0), 10595341252162738537912664445405114076324478519622938027420701542910180337937, f_q)) -mstore(0x18c0, addmod(mload(0x1880), mload(0x18a0), f_q)) -mstore(0x18e0, mulmod(mload(0x16a0), 11597556804922396090267472882856054602429588299176362916247939723151043581408, f_q)) -mstore(0x1900, addmod(mload(0x18c0), mload(0x18e0), f_q)) -mstore(0x1920, addmod(mload(0x1900), sub(f_q, mload(0x700)), f_q)) -mstore(0x1940, mulmod(mload(0x1920), mload(0x840), f_q)) -mstore(0x1960, addmod(mload(0x1860), mload(0x1940), f_q)) -mstore(0x1980, mulmod(mload(0x440), mload(0x1960), f_q)) -mstore(0x19a0, addmod(mload(0x1540), sub(f_q, mload(0x620)), f_q)) -mstore(0x19c0, mulmod(mload(0x19a0), mload(0x860), f_q)) -mstore(0x19e0, addmod(mload(0x1980), mload(0x19c0), f_q)) -mstore(0x1a00, mulmod(mload(0x440), mload(0x19e0), f_q)) -mstore(0x1a20, mulmod(mload(0x620), 7511745149465107256748700652201246547602992235352608707588321460060273774987, f_q)) -mstore(0x1a40, mulmod(mload(0x1580), 10370080108974718697676803824769673834027675643658433702224577712625900127200, f_q)) -mstore(0x1a60, addmod(mload(0x1a20), mload(0x1a40), f_q)) -mstore(0x1a80, mulmod(mload(0x1640), 19705173408229649878903981084052839426532978878058043055305024233888854471533, f_q)) -mstore(0x1aa0, addmod(mload(0x1a60), mload(0x1a80), f_q)) -mstore(0x1ac0, addmod(mload(0x1aa0), mload(0x7a0), f_q)) -mstore(0x1ae0, mulmod(mload(0x1ac0), mload(0x1ac0), f_q)) -mstore(0x1b00, mulmod(mload(0x1ae0), mload(0x1ae0), f_q)) -mstore(0x1b20, mulmod(mload(0x1ac0), mload(0x1b00), f_q)) -mstore(0x1b40, mulmod(mload(0x6c0), 14581990407185373640425896461718924180109794780799188900903678642755512839974, f_q)) -mstore(0x1b60, mulmod(mload(0x6e0), 18866968878651837536281064213261914109651535895144158735451177080294903852066, f_q)) -mstore(0x1b80, addmod(mload(0x1b40), mload(0x1b60), f_q)) -mstore(0x1ba0, mulmod(mload(0x700), 7839627026775837327267018712780335784833794955194428770232963186824469625450, f_q)) -mstore(0x1bc0, addmod(mload(0x1b80), mload(0x1ba0), f_q)) -mstore(0x1be0, addmod(mload(0x1b20), sub(f_q, mload(0x1bc0)), f_q)) -mstore(0x1c00, mulmod(mload(0x1be0), mload(0x860), f_q)) -mstore(0x1c20, addmod(mload(0x1a00), mload(0x1c00), f_q)) -mstore(0x1c40, mulmod(mload(0x440), mload(0x1c20), f_q)) -mstore(0x1c60, mulmod(mload(0x620), 18732019378264290557468133440468564866454307626475683536618613112504878618481, f_q)) -mstore(0x1c80, mulmod(mload(0x1580), 20870176810702568768751421378473869562658540583882454726129544628203806653987, f_q)) -mstore(0x1ca0, addmod(mload(0x1c60), mload(0x1c80), f_q)) -mstore(0x1cc0, mulmod(mload(0x1640), 7266061498423634438633389053804536045105766754026813321943009179476902321146, f_q)) -mstore(0x1ce0, addmod(mload(0x1ca0), mload(0x1cc0), f_q)) -mstore(0x1d00, addmod(mload(0x1ce0), mload(0x7c0), f_q)) -mstore(0x1d20, mulmod(mload(0x6c0), 18938579070830856475783700955955783311402730090941909099413093949983854639956, f_q)) -mstore(0x1d40, mulmod(mload(0x6e0), 8613994242085266665256493323589366394657716111166474713216639394202078033993, f_q)) -mstore(0x1d60, addmod(mload(0x1d20), mload(0x1d40), f_q)) -mstore(0x1d80, mulmod(mload(0x700), 5498488707276883206944027953979269171532592088279065622083714982398440150521, f_q)) -mstore(0x1da0, addmod(mload(0x1d60), mload(0x1d80), f_q)) -mstore(0x1dc0, addmod(mload(0x1d00), sub(f_q, mload(0x1da0)), f_q)) -mstore(0x1de0, mulmod(mload(0x1dc0), mload(0x860), f_q)) -mstore(0x1e00, addmod(mload(0x1c40), mload(0x1de0), f_q)) -mstore(0x1e20, mulmod(mload(0x440), mload(0x1e00), f_q)) -mstore(0x1e40, mulmod(mload(0x620), 9131299761947733513298312097611845208338517739621853568979632113419485819303, f_q)) -mstore(0x1e60, mulmod(mload(0x1580), 10595341252162738537912664445405114076324478519622938027420701542910180337937, f_q)) -mstore(0x1e80, addmod(mload(0x1e40), mload(0x1e60), f_q)) -mstore(0x1ea0, mulmod(mload(0x1640), 11597556804922396090267472882856054602429588299176362916247939723151043581408, f_q)) -mstore(0x1ec0, addmod(mload(0x1e80), mload(0x1ea0), f_q)) -mstore(0x1ee0, addmod(mload(0x1ec0), mload(0x7e0), f_q)) -mstore(0x1f00, mulmod(mload(0x6c0), 655752878747070013666604006434797489161341466456915955415098407670323222025, f_q)) -mstore(0x1f20, mulmod(mload(0x6e0), 4856172836225950379592127603074379105027349156448153533703883389233432728400, f_q)) -mstore(0x1f40, addmod(mload(0x1f00), mload(0x1f20), f_q)) -mstore(0x1f60, mulmod(mload(0x700), 10503264605839191981081969978629584646259107387222177725485772749763096823552, f_q)) -mstore(0x1f80, addmod(mload(0x1f40), mload(0x1f60), f_q)) -mstore(0x1fa0, addmod(mload(0x1ee0), sub(f_q, mload(0x1f80)), f_q)) -mstore(0x1fc0, mulmod(mload(0x1fa0), mload(0x860), f_q)) -mstore(0x1fe0, addmod(mload(0x1e20), mload(0x1fc0), f_q)) -mstore(0x2000, mulmod(mload(0x440), mload(0x1fe0), f_q)) -mstore(0x2020, addmod(mload(0x1a40), mload(0x1a80), f_q)) -mstore(0x2040, addmod(mload(0x1560), mload(0x2020), f_q)) -mstore(0x2060, addmod(mload(0x2040), sub(f_q, mload(0x6c0)), f_q)) -mstore(0x2080, mulmod(mload(0x2060), mload(0x880), f_q)) -mstore(0x20a0, addmod(mload(0x2000), mload(0x2080), f_q)) -mstore(0x20c0, mulmod(mload(0x440), mload(0x20a0), f_q)) -mstore(0x20e0, addmod(mload(0x1c80), mload(0x1cc0), f_q)) -mstore(0x2100, addmod(mload(0x1760), mload(0x20e0), f_q)) -mstore(0x2120, addmod(mload(0x2100), sub(f_q, mload(0x6e0)), f_q)) -mstore(0x2140, mulmod(mload(0x2120), mload(0x880), f_q)) -mstore(0x2160, addmod(mload(0x20c0), mload(0x2140), f_q)) -mstore(0x2180, mulmod(mload(0x440), mload(0x2160), f_q)) -mstore(0x21a0, addmod(mload(0x1e60), mload(0x1ea0), f_q)) -mstore(0x21c0, addmod(mload(0x1880), mload(0x21a0), f_q)) -mstore(0x21e0, addmod(mload(0x21c0), sub(f_q, mload(0x700)), f_q)) -mstore(0x2200, mulmod(mload(0x21e0), mload(0x880), f_q)) -mstore(0x2220, addmod(mload(0x2180), mload(0x2200), f_q)) -mstore(0x2240, mulmod(mload(0x440), mload(0x2220), f_q)) -mstore(0x2260, addmod(mload(0x740), mload(0x640), f_q)) -mstore(0x2280, addmod(mload(0x2260), sub(f_q, mload(0x6c0)), f_q)) -mstore(0x22a0, mulmod(mload(0x2280), mload(0x8a0), f_q)) -mstore(0x22c0, addmod(mload(0x2240), mload(0x22a0), f_q)) -mstore(0x22e0, mulmod(mload(0x440), mload(0x22c0), f_q)) -mstore(0x2300, addmod(mload(0x760), mload(0x660), f_q)) -mstore(0x2320, addmod(mload(0x2300), sub(f_q, mload(0x6e0)), f_q)) -mstore(0x2340, mulmod(mload(0x2320), mload(0x8a0), f_q)) -mstore(0x2360, addmod(mload(0x22e0), mload(0x2340), f_q)) -mstore(0x2380, mulmod(mload(0x440), mload(0x2360), f_q)) -mstore(0x23a0, addmod(mload(0x720), sub(f_q, mload(0x700)), f_q)) -mstore(0x23c0, mulmod(mload(0x23a0), mload(0x8a0), f_q)) -mstore(0x23e0, addmod(mload(0x2380), mload(0x23c0), f_q)) -mstore(0x2400, mulmod(mload(0x440), mload(0x23e0), f_q)) -mstore(0x2420, mulmod(mload(0x640), mload(0x6a0), f_q)) -mstore(0x2440, addmod(1, sub(f_q, mload(0x6a0)), f_q)) -mstore(0x2460, mulmod(mload(0x620), mload(0x2440), f_q)) -mstore(0x2480, addmod(mload(0x2420), mload(0x2460), f_q)) -mstore(0x24a0, addmod(mload(0x660), sub(f_q, mload(0x2480)), f_q)) -mstore(0x24c0, mulmod(mload(0x24a0), mload(0x8c0), f_q)) -mstore(0x24e0, addmod(mload(0x2400), mload(0x24c0), f_q)) -mstore(0x2500, mulmod(mload(0x440), mload(0x24e0), f_q)) -mstore(0x2520, mulmod(mload(0x620), mload(0x6a0), f_q)) -mstore(0x2540, mulmod(mload(0x640), mload(0x2440), f_q)) -mstore(0x2560, addmod(mload(0x2520), mload(0x2540), f_q)) -mstore(0x2580, addmod(mload(0x680), sub(f_q, mload(0x2560)), f_q)) -mstore(0x25a0, mulmod(mload(0x2580), mload(0x8c0), f_q)) -mstore(0x25c0, addmod(mload(0x2500), mload(0x25a0), f_q)) -mstore(0x25e0, mulmod(mload(0x440), mload(0x25c0), f_q)) -mstore(0x2600, mulmod(mload(0x2440), mload(0x6a0), f_q)) -mstore(0x2620, mulmod(mload(0x2600), mload(0x8c0), f_q)) -mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) -mstore(0x2660, mulmod(mload(0x440), mload(0x2640), f_q)) -mstore(0x2680, addmod(mload(0x620), 21888242871839275222246405745257275088548364400416034343698204186575808495617, f_q)) -mstore(0x26a0, mulmod(mload(0x2680), mload(0x8e0), f_q)) -mstore(0x26c0, mulmod(mload(0x640), mload(0x2680), f_q)) -mstore(0x26e0, addmod(1, sub(f_q, mload(0x26c0)), f_q)) -mstore(0x2700, mulmod(mload(0x26e0), mload(0x26a0), f_q)) -mstore(0x2720, addmod(mload(0x2660), mload(0x2700), f_q)) -mstore(0x2740, mulmod(mload(0x440), mload(0x2720), f_q)) -mstore(0x2760, addmod(mload(0x660), sub(f_q, mload(0x26e0)), f_q)) -mstore(0x2780, mulmod(mload(0x2760), mload(0x8e0), f_q)) -mstore(0x27a0, addmod(mload(0x2740), mload(0x2780), f_q)) -mstore(0x27c0, mulmod(mload(0x440), mload(0x27a0), f_q)) -mstore(0x27e0, addmod(1, sub(f_q, mload(0xa60)), f_q)) -mstore(0x2800, mulmod(mload(0x27e0), mload(0x1420), f_q)) -mstore(0x2820, addmod(mload(0x27c0), mload(0x2800), f_q)) -mstore(0x2840, mulmod(mload(0x440), mload(0x2820), f_q)) -mstore(0x2860, mulmod(mload(0xb20), mload(0xb20), f_q)) -mstore(0x2880, addmod(mload(0x2860), sub(f_q, mload(0xb20)), f_q)) -mstore(0x28a0, mulmod(mload(0x2880), mload(0x1360), f_q)) -mstore(0x28c0, addmod(mload(0x2840), mload(0x28a0), f_q)) -mstore(0x28e0, mulmod(mload(0x440), mload(0x28c0), f_q)) -mstore(0x2900, addmod(mload(0xac0), sub(f_q, mload(0xaa0)), f_q)) -mstore(0x2920, mulmod(mload(0x2900), mload(0x1420), f_q)) -mstore(0x2940, addmod(mload(0x28e0), mload(0x2920), f_q)) -mstore(0x2960, mulmod(mload(0x440), mload(0x2940), f_q)) -mstore(0x2980, addmod(mload(0xb20), sub(f_q, mload(0xb00)), f_q)) -mstore(0x29a0, mulmod(mload(0x2980), mload(0x1420), f_q)) -mstore(0x29c0, addmod(mload(0x2960), mload(0x29a0), f_q)) -mstore(0x29e0, mulmod(mload(0x440), mload(0x29c0), f_q)) -mstore(0x2a00, addmod(1, sub(f_q, mload(0x1360)), f_q)) -mstore(0x2a20, addmod(mload(0x1380), mload(0x13a0), f_q)) -mstore(0x2a40, addmod(mload(0x2a20), mload(0x13c0), f_q)) -mstore(0x2a60, addmod(mload(0x2a40), mload(0x13e0), f_q)) -mstore(0x2a80, addmod(mload(0x2a60), mload(0x1400), f_q)) -mstore(0x2aa0, addmod(mload(0x2a00), sub(f_q, mload(0x2a80)), f_q)) -mstore(0x2ac0, mulmod(mload(0x920), mload(0x280), f_q)) -mstore(0x2ae0, addmod(mload(0x14c0), mload(0x2ac0), f_q)) -mstore(0x2b00, addmod(mload(0x2ae0), mload(0x2e0), f_q)) -mstore(0x2b20, mulmod(mload(0x940), mload(0x280), f_q)) -mstore(0x2b40, addmod(mload(0x620), mload(0x2b20), f_q)) -mstore(0x2b60, addmod(mload(0x2b40), mload(0x2e0), f_q)) -mstore(0x2b80, mulmod(mload(0x2b60), mload(0x2b00), f_q)) -mstore(0x2ba0, mulmod(mload(0x960), mload(0x280), f_q)) -mstore(0x2bc0, addmod(mload(0x640), mload(0x2ba0), f_q)) -mstore(0x2be0, addmod(mload(0x2bc0), mload(0x2e0), f_q)) -mstore(0x2c00, mulmod(mload(0x2be0), mload(0x2b80), f_q)) -mstore(0x2c20, mulmod(mload(0x980), mload(0x280), f_q)) -mstore(0x2c40, addmod(mload(0x660), mload(0x2c20), f_q)) -mstore(0x2c60, addmod(mload(0x2c40), mload(0x2e0), f_q)) -mstore(0x2c80, mulmod(mload(0x2c60), mload(0x2c00), f_q)) -mstore(0x2ca0, mulmod(mload(0x2c80), mload(0xa80), f_q)) -mstore(0x2cc0, mulmod(1, mload(0x280), f_q)) -mstore(0x2ce0, mulmod(mload(0x5e0), mload(0x2cc0), f_q)) -mstore(0x2d00, addmod(mload(0x14c0), mload(0x2ce0), f_q)) -mstore(0x2d20, addmod(mload(0x2d00), mload(0x2e0), f_q)) -mstore(0x2d40, mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x280), f_q)) -mstore(0x2d60, mulmod(mload(0x5e0), mload(0x2d40), f_q)) -mstore(0x2d80, addmod(mload(0x620), mload(0x2d60), f_q)) -mstore(0x2da0, addmod(mload(0x2d80), mload(0x2e0), f_q)) -mstore(0x2dc0, mulmod(mload(0x2da0), mload(0x2d20), f_q)) -mstore(0x2de0, mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x280), f_q)) -mstore(0x2e00, mulmod(mload(0x5e0), mload(0x2de0), f_q)) -mstore(0x2e20, addmod(mload(0x640), mload(0x2e00), f_q)) -mstore(0x2e40, addmod(mload(0x2e20), mload(0x2e0), f_q)) -mstore(0x2e60, mulmod(mload(0x2e40), mload(0x2dc0), f_q)) -mstore(0x2e80, mulmod(11166246659983828508719468090013646171463329086121580628794302409516816350802, mload(0x280), f_q)) -mstore(0x2ea0, mulmod(mload(0x5e0), mload(0x2e80), f_q)) -mstore(0x2ec0, addmod(mload(0x660), mload(0x2ea0), f_q)) -mstore(0x2ee0, addmod(mload(0x2ec0), mload(0x2e0), f_q)) -mstore(0x2f00, mulmod(mload(0x2ee0), mload(0x2e60), f_q)) -mstore(0x2f20, mulmod(mload(0x2f00), mload(0xa60), f_q)) -mstore(0x2f40, addmod(mload(0x2ca0), sub(f_q, mload(0x2f20)), f_q)) -mstore(0x2f60, mulmod(mload(0x2f40), mload(0x2aa0), f_q)) -mstore(0x2f80, addmod(mload(0x29e0), mload(0x2f60), f_q)) -mstore(0x2fa0, mulmod(mload(0x440), mload(0x2f80), f_q)) -mstore(0x2fc0, mulmod(mload(0x9a0), mload(0x280), f_q)) -mstore(0x2fe0, addmod(mload(0x680), mload(0x2fc0), f_q)) -mstore(0x3000, addmod(mload(0x2fe0), mload(0x2e0), f_q)) -mstore(0x3020, mulmod(mload(0x9c0), mload(0x280), f_q)) -mstore(0x3040, addmod(mload(0x6a0), mload(0x3020), f_q)) -mstore(0x3060, addmod(mload(0x3040), mload(0x2e0), f_q)) -mstore(0x3080, mulmod(mload(0x3060), mload(0x3000), f_q)) -mstore(0x30a0, mulmod(mload(0x9e0), mload(0x280), f_q)) -mstore(0x30c0, addmod(mload(0x780), mload(0x30a0), f_q)) -mstore(0x30e0, addmod(mload(0x30c0), mload(0x2e0), f_q)) -mstore(0x3100, mulmod(mload(0x30e0), mload(0x3080), f_q)) -mstore(0x3120, mulmod(mload(0xa00), mload(0x280), f_q)) -mstore(0x3140, addmod(mload(0x7a0), mload(0x3120), f_q)) -mstore(0x3160, addmod(mload(0x3140), mload(0x2e0), f_q)) -mstore(0x3180, mulmod(mload(0x3160), mload(0x3100), f_q)) -mstore(0x31a0, mulmod(mload(0x3180), mload(0xae0), f_q)) -mstore(0x31c0, mulmod(284840088355319032285349970403338060113257071685626700086398481893096618818, mload(0x280), f_q)) -mstore(0x31e0, mulmod(mload(0x5e0), mload(0x31c0), f_q)) -mstore(0x3200, addmod(mload(0x680), mload(0x31e0), f_q)) -mstore(0x3220, addmod(mload(0x3200), mload(0x2e0), f_q)) -mstore(0x3240, mulmod(21134065618345176623193549882539580312263652408302468683943992798037078993309, mload(0x280), f_q)) -mstore(0x3260, mulmod(mload(0x5e0), mload(0x3240), f_q)) -mstore(0x3280, addmod(mload(0x6a0), mload(0x3260), f_q)) -mstore(0x32a0, addmod(mload(0x3280), mload(0x2e0), f_q)) -mstore(0x32c0, mulmod(mload(0x32a0), mload(0x3220), f_q)) -mstore(0x32e0, mulmod(5625741653535312224677218588085279924365897425605943700675464992185016992283, mload(0x280), f_q)) -mstore(0x3300, mulmod(mload(0x5e0), mload(0x32e0), f_q)) -mstore(0x3320, addmod(mload(0x780), mload(0x3300), f_q)) -mstore(0x3340, addmod(mload(0x3320), mload(0x2e0), f_q)) -mstore(0x3360, mulmod(mload(0x3340), mload(0x32c0), f_q)) -mstore(0x3380, mulmod(14704729814417906439424896605881467874595262020190401576785074330126828718155, mload(0x280), f_q)) -mstore(0x33a0, mulmod(mload(0x5e0), mload(0x3380), f_q)) -mstore(0x33c0, addmod(mload(0x7a0), mload(0x33a0), f_q)) -mstore(0x33e0, addmod(mload(0x33c0), mload(0x2e0), f_q)) -mstore(0x3400, mulmod(mload(0x33e0), mload(0x3360), f_q)) -mstore(0x3420, mulmod(mload(0x3400), mload(0xac0), f_q)) -mstore(0x3440, addmod(mload(0x31a0), sub(f_q, mload(0x3420)), f_q)) -mstore(0x3460, mulmod(mload(0x3440), mload(0x2aa0), f_q)) -mstore(0x3480, addmod(mload(0x2fa0), mload(0x3460), f_q)) -mstore(0x34a0, mulmod(mload(0x440), mload(0x3480), f_q)) -mstore(0x34c0, mulmod(mload(0xa20), mload(0x280), f_q)) -mstore(0x34e0, addmod(mload(0x7c0), mload(0x34c0), f_q)) -mstore(0x3500, addmod(mload(0x34e0), mload(0x2e0), f_q)) -mstore(0x3520, mulmod(mload(0xa40), mload(0x280), f_q)) -mstore(0x3540, addmod(mload(0x7e0), mload(0x3520), f_q)) -mstore(0x3560, addmod(mload(0x3540), mload(0x2e0), f_q)) -mstore(0x3580, mulmod(mload(0x3560), mload(0x3500), f_q)) -mstore(0x35a0, mulmod(mload(0x3580), mload(0xb40), f_q)) -mstore(0x35c0, mulmod(8343274462013750416000956870576256937330525306073862550863787263304548803879, mload(0x280), f_q)) -mstore(0x35e0, mulmod(mload(0x5e0), mload(0x35c0), f_q)) -mstore(0x3600, addmod(mload(0x7c0), mload(0x35e0), f_q)) -mstore(0x3620, addmod(mload(0x3600), mload(0x2e0), f_q)) -mstore(0x3640, mulmod(20928372310071051017340352686640453451620397549739756658327314209761852842004, mload(0x280), f_q)) -mstore(0x3660, mulmod(mload(0x5e0), mload(0x3640), f_q)) -mstore(0x3680, addmod(mload(0x7e0), mload(0x3660), f_q)) -mstore(0x36a0, addmod(mload(0x3680), mload(0x2e0), f_q)) -mstore(0x36c0, mulmod(mload(0x36a0), mload(0x3620), f_q)) -mstore(0x36e0, mulmod(mload(0x36c0), mload(0xb20), f_q)) -mstore(0x3700, addmod(mload(0x35a0), sub(f_q, mload(0x36e0)), f_q)) -mstore(0x3720, mulmod(mload(0x3700), mload(0x2aa0), f_q)) -mstore(0x3740, addmod(mload(0x34a0), mload(0x3720), f_q)) -mstore(0x3760, mulmod(mload(0xe00), mload(0xe00), f_q)) -mstore(0x3780, mulmod(mload(0x3760), mload(0xe00), f_q)) -mstore(0x37a0, mulmod(mload(0x3780), mload(0xe00), f_q)) -mstore(0x37c0, mulmod(mload(0x37a0), mload(0xe00), f_q)) -mstore(0x37e0, mulmod(1, mload(0xe00), f_q)) -mstore(0x3800, mulmod(1, mload(0x3760), f_q)) -mstore(0x3820, mulmod(1, mload(0x3780), f_q)) -mstore(0x3840, mulmod(1, mload(0x37a0), f_q)) -mstore(0x3860, mulmod(mload(0x3740), mload(0xe20), f_q)) -mstore(0x3880, mulmod(mload(0x5e0), 1, f_q)) -mstore(0x38a0, addmod(mload(0xc80), sub(f_q, mload(0x3880)), f_q)) -mstore(0x38c0, mulmod(mload(0x5e0), 4260969412351770314333984243767775737437927068151180798236715529158398853173, f_q)) -mstore(0x38e0, addmod(mload(0xc80), sub(f_q, mload(0x38c0)), f_q)) -mstore(0x3900, mulmod(mload(0x5e0), 6252951856119339508807713076978770803512896272623217303779254502899773638908, f_q)) -mstore(0x3920, addmod(mload(0xc80), sub(f_q, mload(0x3900)), f_q)) -mstore(0x3940, mulmod(mload(0x5e0), 11423757818648818765461327411617109120243501240676889555478397529313037714234, f_q)) -mstore(0x3960, addmod(mload(0xc80), sub(f_q, mload(0x3940)), f_q)) -{ - let result := mulmod(mload(0xc80), 1, f_q) -result := addmod(mulmod(mload(0x5e0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q), result, f_q) -mstore(14720, result) - } -mstore(0x39a0, mulmod(1, mload(0x38a0), f_q)) -{ - let result := mulmod(mload(0xc80), 11374321603368165399104708424510728547597541059641636241682234154517636003538, f_q) -result := addmod(mulmod(mload(0x5e0), 10513921268471109823141697320746546540950823340774398102015970032058172492079, f_q), result, f_q) -mstore(14784, result) - } -{ - let result := mulmod(mload(0xc80), 5401666821907938396681357392223302805862399047169948710026352879064583381945, f_q) -result := addmod(mulmod(mload(0x5e0), 6372057045086252176304075864203520303988466337001999834503402647047195407692, f_q), result, f_q) -mstore(14816, result) - } -{ - let result := mulmod(mload(0xc80), 16150511345564707660718220819970308920741231739835080897716327035771676256721, f_q) -result := addmod(mulmod(mload(0x5e0), 8483428686537719261749220560289765322817043182242700637097971554260829267481, f_q), result, f_q) -mstore(14848, result) - } -mstore(0x3a20, mulmod(mload(0x39a0), mload(0x3920), f_q)) -mstore(0x3a40, mulmod(mload(0x3a20), mload(0x38e0), f_q)) -{ - let result := mulmod(mload(0xc80), 982199530947335711058326514390809322600877284759018589566598570959032168325, f_q) -result := addmod(mulmod(mload(0x5e0), 20906043340891939511188079230866465765947487115657015754131605615616776327292, f_q), result, f_q) -mstore(14944, result) - } -{ - let result := mulmod(mload(0xc80), 15793788894328768084727739302343222030859062822052566362141988462623187217158, f_q) -result := addmod(mulmod(mload(0x5e0), 17025487199042771698883397417875737951120588487814889559916392792841622101795, f_q), result, f_q) -mstore(14976, result) - } -{ - let result := mulmod(mload(0xc80), 8225778414108386131857824234780332238746220130309253143140026671792101940293, f_q) -result := addmod(mulmod(mload(0x5e0), 12089860469981555972352979896169738621752335090266596234307820947387409624317, f_q), result, f_q) -mstore(15008, result) - } -mstore(0x3ac0, mulmod(mload(0x3a20), mload(0x3960), f_q)) -{ - let result := mulmod(mload(0xc80), 15635291015719935713438692668278504285035468127792817039918949683676034856710, f_q) -result := addmod(mulmod(mload(0x5e0), 6252951856119339508807713076978770803512896272623217303779254502899773638907, f_q), result, f_q) -mstore(15072, result) - } -{ - let result := mulmod(mload(0xc80), 6252951856119339508807713076978770803512896272623217303779254502899773638907, f_q) -result := addmod(mulmod(mload(0x5e0), 20747545462283107139899032596801748020123892421397266431908566836669623966844, f_q), result, f_q) -mstore(15104, result) - } -{ - let prod := mload(0x3980) - - prod := mulmod(mload(0x39c0), prod, f_q) - mstore(0x3b20, prod) - - prod := mulmod(mload(0x39e0), prod, f_q) - mstore(0x3b40, prod) - - prod := mulmod(mload(0x3a00), prod, f_q) - mstore(0x3b60, prod) - - prod := mulmod(mload(0x3a40), prod, f_q) - mstore(0x3b80, prod) - - prod := mulmod(mload(0x3a60), prod, f_q) - mstore(0x3ba0, prod) - - prod := mulmod(mload(0x3a80), prod, f_q) - mstore(0x3bc0, prod) - - prod := mulmod(mload(0x3aa0), prod, f_q) - mstore(0x3be0, prod) - - prod := mulmod(mload(0x3ac0), prod, f_q) - mstore(0x3c00, prod) - - prod := mulmod(mload(0x3ae0), prod, f_q) - mstore(0x3c20, prod) - - prod := mulmod(mload(0x3b00), prod, f_q) - mstore(0x3c40, prod) - - prod := mulmod(mload(0x3a20), prod, f_q) - mstore(0x3c60, prod) - - } -mstore(0x3ca0, 32) -mstore(0x3cc0, 32) -mstore(0x3ce0, 32) -mstore(0x3d00, mload(0x3c60)) -mstore(0x3d20, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x3d40, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x3ca0, 0xc0, 0x3c80, 0x20), 1), success) -{ - - let inv := mload(0x3c80) - let v - - v := mload(0x3a20) - mstore(14880, mulmod(mload(0x3c40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b00) - mstore(15104, mulmod(mload(0x3c20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3ae0) - mstore(15072, mulmod(mload(0x3c00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3ac0) - mstore(15040, mulmod(mload(0x3be0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3aa0) - mstore(15008, mulmod(mload(0x3bc0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3a80) - mstore(14976, mulmod(mload(0x3ba0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3a60) - mstore(14944, mulmod(mload(0x3b80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3a40) - mstore(14912, mulmod(mload(0x3b60), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3a00) - mstore(14848, mulmod(mload(0x3b40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x39e0) - mstore(14816, mulmod(mload(0x3b20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x39c0) - mstore(14784, mulmod(mload(0x3980), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x3980, inv) - - } -{ - let result := mload(0x3980) -mstore(15712, result) - } -mstore(0x3d80, mulmod(mload(0x39a0), mload(0x3a40), f_q)) -{ - let result := mload(0x39c0) -result := addmod(mload(0x39e0), result, f_q) -result := addmod(mload(0x3a00), result, f_q) -mstore(15776, result) - } -mstore(0x3dc0, mulmod(mload(0x39a0), mload(0x3ac0), f_q)) -{ - let result := mload(0x3a60) -result := addmod(mload(0x3a80), result, f_q) -result := addmod(mload(0x3aa0), result, f_q) -mstore(15840, result) - } -mstore(0x3e00, mulmod(mload(0x39a0), mload(0x3a20), f_q)) -{ - let result := mload(0x3ae0) -result := addmod(mload(0x3b00), result, f_q) -mstore(15904, result) - } -{ - let prod := mload(0x3d60) - - prod := mulmod(mload(0x3da0), prod, f_q) - mstore(0x3e40, prod) - - prod := mulmod(mload(0x3de0), prod, f_q) - mstore(0x3e60, prod) - - prod := mulmod(mload(0x3e20), prod, f_q) - mstore(0x3e80, prod) - - } -mstore(0x3ec0, 32) -mstore(0x3ee0, 32) -mstore(0x3f00, 32) -mstore(0x3f20, mload(0x3e80)) -mstore(0x3f40, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x3f60, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x3ec0, 0xc0, 0x3ea0, 0x20), 1), success) -{ - - let inv := mload(0x3ea0) - let v - - v := mload(0x3e20) - mstore(15904, mulmod(mload(0x3e60), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3de0) - mstore(15840, mulmod(mload(0x3e40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3da0) - mstore(15776, mulmod(mload(0x3d60), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x3d60, inv) - - } -mstore(0x3f80, mulmod(mload(0x3d80), mload(0x3da0), f_q)) -mstore(0x3fa0, mulmod(mload(0x3dc0), mload(0x3de0), f_q)) -mstore(0x3fc0, mulmod(mload(0x3e00), mload(0x3e20), f_q)) -mstore(0x3fe0, mulmod(mload(0xb80), mload(0xb80), f_q)) -mstore(0x4000, mulmod(mload(0x3fe0), mload(0xb80), f_q)) -mstore(0x4020, mulmod(mload(0x4000), mload(0xb80), f_q)) -mstore(0x4040, mulmod(mload(0x4020), mload(0xb80), f_q)) -mstore(0x4060, mulmod(mload(0x4040), mload(0xb80), f_q)) -mstore(0x4080, mulmod(mload(0x4060), mload(0xb80), f_q)) -mstore(0x40a0, mulmod(mload(0x4080), mload(0xb80), f_q)) -mstore(0x40c0, mulmod(mload(0x40a0), mload(0xb80), f_q)) -mstore(0x40e0, mulmod(mload(0x40c0), mload(0xb80), f_q)) -mstore(0x4100, mulmod(mload(0x40e0), mload(0xb80), f_q)) -mstore(0x4120, mulmod(mload(0x4100), mload(0xb80), f_q)) -mstore(0x4140, mulmod(mload(0x4120), mload(0xb80), f_q)) -mstore(0x4160, mulmod(mload(0x4140), mload(0xb80), f_q)) -mstore(0x4180, mulmod(mload(0x4160), mload(0xb80), f_q)) -mstore(0x41a0, mulmod(mload(0x4180), mload(0xb80), f_q)) -mstore(0x41c0, mulmod(mload(0x41a0), mload(0xb80), f_q)) -mstore(0x41e0, mulmod(mload(0x41c0), mload(0xb80), f_q)) -mstore(0x4200, mulmod(mload(0x41e0), mload(0xb80), f_q)) -mstore(0x4220, mulmod(mload(0x4200), mload(0xb80), f_q)) -mstore(0x4240, mulmod(mload(0x4220), mload(0xb80), f_q)) -mstore(0x4260, mulmod(mload(0x4240), mload(0xb80), f_q)) -mstore(0x4280, mulmod(mload(0x4260), mload(0xb80), f_q)) -mstore(0x42a0, mulmod(mload(0x4280), mload(0xb80), f_q)) -mstore(0x42c0, mulmod(mload(0x42a0), mload(0xb80), f_q)) -mstore(0x42e0, mulmod(mload(0x42c0), mload(0xb80), f_q)) -mstore(0x4300, mulmod(mload(0xbe0), mload(0xbe0), f_q)) -mstore(0x4320, mulmod(mload(0x4300), mload(0xbe0), f_q)) -mstore(0x4340, mulmod(mload(0x4320), mload(0xbe0), f_q)) -{ - let result := mulmod(mload(0x620), mload(0x3980), f_q) -mstore(17248, result) - } -mstore(0x4380, mulmod(mload(0x4360), mload(0x3d60), f_q)) -mstore(0x43a0, mulmod(sub(f_q, mload(0x4380)), 1, f_q)) -{ - let result := mulmod(mload(0x6a0), mload(0x3980), f_q) -mstore(17344, result) - } -mstore(0x43e0, mulmod(mload(0x43c0), mload(0x3d60), f_q)) -mstore(0x4400, mulmod(sub(f_q, mload(0x43e0)), mload(0xb80), f_q)) -mstore(0x4420, mulmod(1, mload(0xb80), f_q)) -mstore(0x4440, addmod(mload(0x43a0), mload(0x4400), f_q)) -{ - let result := mulmod(mload(0x780), mload(0x3980), f_q) -mstore(17504, result) - } -mstore(0x4480, mulmod(mload(0x4460), mload(0x3d60), f_q)) -mstore(0x44a0, mulmod(sub(f_q, mload(0x4480)), mload(0x3fe0), f_q)) -mstore(0x44c0, mulmod(1, mload(0x3fe0), f_q)) -mstore(0x44e0, addmod(mload(0x4440), mload(0x44a0), f_q)) -{ - let result := mulmod(mload(0x7a0), mload(0x3980), f_q) -mstore(17664, result) - } -mstore(0x4520, mulmod(mload(0x4500), mload(0x3d60), f_q)) -mstore(0x4540, mulmod(sub(f_q, mload(0x4520)), mload(0x4000), f_q)) -mstore(0x4560, mulmod(1, mload(0x4000), f_q)) -mstore(0x4580, addmod(mload(0x44e0), mload(0x4540), f_q)) -{ - let result := mulmod(mload(0x7c0), mload(0x3980), f_q) -mstore(17824, result) - } -mstore(0x45c0, mulmod(mload(0x45a0), mload(0x3d60), f_q)) -mstore(0x45e0, mulmod(sub(f_q, mload(0x45c0)), mload(0x4020), f_q)) -mstore(0x4600, mulmod(1, mload(0x4020), f_q)) -mstore(0x4620, addmod(mload(0x4580), mload(0x45e0), f_q)) -{ - let result := mulmod(mload(0x7e0), mload(0x3980), f_q) -mstore(17984, result) - } -mstore(0x4660, mulmod(mload(0x4640), mload(0x3d60), f_q)) -mstore(0x4680, mulmod(sub(f_q, mload(0x4660)), mload(0x4040), f_q)) -mstore(0x46a0, mulmod(1, mload(0x4040), f_q)) -mstore(0x46c0, addmod(mload(0x4620), mload(0x4680), f_q)) -{ - let result := mulmod(mload(0x800), mload(0x3980), f_q) -mstore(18144, result) - } -mstore(0x4700, mulmod(mload(0x46e0), mload(0x3d60), f_q)) -mstore(0x4720, mulmod(sub(f_q, mload(0x4700)), mload(0x4060), f_q)) -mstore(0x4740, mulmod(1, mload(0x4060), f_q)) -mstore(0x4760, addmod(mload(0x46c0), mload(0x4720), f_q)) -{ - let result := mulmod(mload(0x820), mload(0x3980), f_q) -mstore(18304, result) - } -mstore(0x47a0, mulmod(mload(0x4780), mload(0x3d60), f_q)) -mstore(0x47c0, mulmod(sub(f_q, mload(0x47a0)), mload(0x4080), f_q)) -mstore(0x47e0, mulmod(1, mload(0x4080), f_q)) -mstore(0x4800, addmod(mload(0x4760), mload(0x47c0), f_q)) -{ - let result := mulmod(mload(0x840), mload(0x3980), f_q) -mstore(18464, result) - } -mstore(0x4840, mulmod(mload(0x4820), mload(0x3d60), f_q)) -mstore(0x4860, mulmod(sub(f_q, mload(0x4840)), mload(0x40a0), f_q)) -mstore(0x4880, mulmod(1, mload(0x40a0), f_q)) -mstore(0x48a0, addmod(mload(0x4800), mload(0x4860), f_q)) -{ - let result := mulmod(mload(0x860), mload(0x3980), f_q) -mstore(18624, result) - } -mstore(0x48e0, mulmod(mload(0x48c0), mload(0x3d60), f_q)) -mstore(0x4900, mulmod(sub(f_q, mload(0x48e0)), mload(0x40c0), f_q)) -mstore(0x4920, mulmod(1, mload(0x40c0), f_q)) -mstore(0x4940, addmod(mload(0x48a0), mload(0x4900), f_q)) -{ - let result := mulmod(mload(0x880), mload(0x3980), f_q) -mstore(18784, result) - } -mstore(0x4980, mulmod(mload(0x4960), mload(0x3d60), f_q)) -mstore(0x49a0, mulmod(sub(f_q, mload(0x4980)), mload(0x40e0), f_q)) -mstore(0x49c0, mulmod(1, mload(0x40e0), f_q)) -mstore(0x49e0, addmod(mload(0x4940), mload(0x49a0), f_q)) -{ - let result := mulmod(mload(0x8a0), mload(0x3980), f_q) -mstore(18944, result) - } -mstore(0x4a20, mulmod(mload(0x4a00), mload(0x3d60), f_q)) -mstore(0x4a40, mulmod(sub(f_q, mload(0x4a20)), mload(0x4100), f_q)) -mstore(0x4a60, mulmod(1, mload(0x4100), f_q)) -mstore(0x4a80, addmod(mload(0x49e0), mload(0x4a40), f_q)) -{ - let result := mulmod(mload(0x8c0), mload(0x3980), f_q) -mstore(19104, result) - } -mstore(0x4ac0, mulmod(mload(0x4aa0), mload(0x3d60), f_q)) -mstore(0x4ae0, mulmod(sub(f_q, mload(0x4ac0)), mload(0x4120), f_q)) -mstore(0x4b00, mulmod(1, mload(0x4120), f_q)) -mstore(0x4b20, addmod(mload(0x4a80), mload(0x4ae0), f_q)) -{ - let result := mulmod(mload(0x8e0), mload(0x3980), f_q) -mstore(19264, result) - } -mstore(0x4b60, mulmod(mload(0x4b40), mload(0x3d60), f_q)) -mstore(0x4b80, mulmod(sub(f_q, mload(0x4b60)), mload(0x4140), f_q)) -mstore(0x4ba0, mulmod(1, mload(0x4140), f_q)) -mstore(0x4bc0, addmod(mload(0x4b20), mload(0x4b80), f_q)) -{ - let result := mulmod(mload(0x920), mload(0x3980), f_q) -mstore(19424, result) - } -mstore(0x4c00, mulmod(mload(0x4be0), mload(0x3d60), f_q)) -mstore(0x4c20, mulmod(sub(f_q, mload(0x4c00)), mload(0x4160), f_q)) -mstore(0x4c40, mulmod(1, mload(0x4160), f_q)) -mstore(0x4c60, addmod(mload(0x4bc0), mload(0x4c20), f_q)) -{ - let result := mulmod(mload(0x940), mload(0x3980), f_q) -mstore(19584, result) - } -mstore(0x4ca0, mulmod(mload(0x4c80), mload(0x3d60), f_q)) -mstore(0x4cc0, mulmod(sub(f_q, mload(0x4ca0)), mload(0x4180), f_q)) -mstore(0x4ce0, mulmod(1, mload(0x4180), f_q)) -mstore(0x4d00, addmod(mload(0x4c60), mload(0x4cc0), f_q)) -{ - let result := mulmod(mload(0x960), mload(0x3980), f_q) -mstore(19744, result) - } -mstore(0x4d40, mulmod(mload(0x4d20), mload(0x3d60), f_q)) -mstore(0x4d60, mulmod(sub(f_q, mload(0x4d40)), mload(0x41a0), f_q)) -mstore(0x4d80, mulmod(1, mload(0x41a0), f_q)) -mstore(0x4da0, addmod(mload(0x4d00), mload(0x4d60), f_q)) -{ - let result := mulmod(mload(0x980), mload(0x3980), f_q) -mstore(19904, result) - } -mstore(0x4de0, mulmod(mload(0x4dc0), mload(0x3d60), f_q)) -mstore(0x4e00, mulmod(sub(f_q, mload(0x4de0)), mload(0x41c0), f_q)) -mstore(0x4e20, mulmod(1, mload(0x41c0), f_q)) -mstore(0x4e40, addmod(mload(0x4da0), mload(0x4e00), f_q)) -{ - let result := mulmod(mload(0x9a0), mload(0x3980), f_q) -mstore(20064, result) - } -mstore(0x4e80, mulmod(mload(0x4e60), mload(0x3d60), f_q)) -mstore(0x4ea0, mulmod(sub(f_q, mload(0x4e80)), mload(0x41e0), f_q)) -mstore(0x4ec0, mulmod(1, mload(0x41e0), f_q)) -mstore(0x4ee0, addmod(mload(0x4e40), mload(0x4ea0), f_q)) -{ - let result := mulmod(mload(0x9c0), mload(0x3980), f_q) -mstore(20224, result) - } -mstore(0x4f20, mulmod(mload(0x4f00), mload(0x3d60), f_q)) -mstore(0x4f40, mulmod(sub(f_q, mload(0x4f20)), mload(0x4200), f_q)) -mstore(0x4f60, mulmod(1, mload(0x4200), f_q)) -mstore(0x4f80, addmod(mload(0x4ee0), mload(0x4f40), f_q)) -{ - let result := mulmod(mload(0x9e0), mload(0x3980), f_q) -mstore(20384, result) - } -mstore(0x4fc0, mulmod(mload(0x4fa0), mload(0x3d60), f_q)) -mstore(0x4fe0, mulmod(sub(f_q, mload(0x4fc0)), mload(0x4220), f_q)) -mstore(0x5000, mulmod(1, mload(0x4220), f_q)) -mstore(0x5020, addmod(mload(0x4f80), mload(0x4fe0), f_q)) -{ - let result := mulmod(mload(0xa00), mload(0x3980), f_q) -mstore(20544, result) - } -mstore(0x5060, mulmod(mload(0x5040), mload(0x3d60), f_q)) -mstore(0x5080, mulmod(sub(f_q, mload(0x5060)), mload(0x4240), f_q)) -mstore(0x50a0, mulmod(1, mload(0x4240), f_q)) -mstore(0x50c0, addmod(mload(0x5020), mload(0x5080), f_q)) -{ - let result := mulmod(mload(0xa20), mload(0x3980), f_q) -mstore(20704, result) - } -mstore(0x5100, mulmod(mload(0x50e0), mload(0x3d60), f_q)) -mstore(0x5120, mulmod(sub(f_q, mload(0x5100)), mload(0x4260), f_q)) -mstore(0x5140, mulmod(1, mload(0x4260), f_q)) -mstore(0x5160, addmod(mload(0x50c0), mload(0x5120), f_q)) -{ - let result := mulmod(mload(0xa40), mload(0x3980), f_q) -mstore(20864, result) - } -mstore(0x51a0, mulmod(mload(0x5180), mload(0x3d60), f_q)) -mstore(0x51c0, mulmod(sub(f_q, mload(0x51a0)), mload(0x4280), f_q)) -mstore(0x51e0, mulmod(1, mload(0x4280), f_q)) -mstore(0x5200, addmod(mload(0x5160), mload(0x51c0), f_q)) -{ - let result := mulmod(mload(0x3860), mload(0x3980), f_q) -mstore(21024, result) - } -mstore(0x5240, mulmod(mload(0x5220), mload(0x3d60), f_q)) -mstore(0x5260, mulmod(sub(f_q, mload(0x5240)), mload(0x42a0), f_q)) -mstore(0x5280, mulmod(1, mload(0x42a0), f_q)) -mstore(0x52a0, mulmod(mload(0x37e0), mload(0x42a0), f_q)) -mstore(0x52c0, mulmod(mload(0x3800), mload(0x42a0), f_q)) -mstore(0x52e0, mulmod(mload(0x3820), mload(0x42a0), f_q)) -mstore(0x5300, mulmod(mload(0x3840), mload(0x42a0), f_q)) -mstore(0x5320, addmod(mload(0x5200), mload(0x5260), f_q)) -{ - let result := mulmod(mload(0x900), mload(0x3980), f_q) -mstore(21312, result) - } -mstore(0x5360, mulmod(mload(0x5340), mload(0x3d60), f_q)) -mstore(0x5380, mulmod(sub(f_q, mload(0x5360)), mload(0x42c0), f_q)) -mstore(0x53a0, mulmod(1, mload(0x42c0), f_q)) -mstore(0x53c0, addmod(mload(0x5320), mload(0x5380), f_q)) -mstore(0x53e0, mulmod(mload(0x53c0), 1, f_q)) -mstore(0x5400, mulmod(mload(0x4420), 1, f_q)) -mstore(0x5420, mulmod(mload(0x44c0), 1, f_q)) -mstore(0x5440, mulmod(mload(0x4560), 1, f_q)) -mstore(0x5460, mulmod(mload(0x4600), 1, f_q)) -mstore(0x5480, mulmod(mload(0x46a0), 1, f_q)) -mstore(0x54a0, mulmod(mload(0x4740), 1, f_q)) -mstore(0x54c0, mulmod(mload(0x47e0), 1, f_q)) -mstore(0x54e0, mulmod(mload(0x4880), 1, f_q)) -mstore(0x5500, mulmod(mload(0x4920), 1, f_q)) -mstore(0x5520, mulmod(mload(0x49c0), 1, f_q)) -mstore(0x5540, mulmod(mload(0x4a60), 1, f_q)) -mstore(0x5560, mulmod(mload(0x4b00), 1, f_q)) -mstore(0x5580, mulmod(mload(0x4ba0), 1, f_q)) -mstore(0x55a0, mulmod(mload(0x4c40), 1, f_q)) -mstore(0x55c0, mulmod(mload(0x4ce0), 1, f_q)) -mstore(0x55e0, mulmod(mload(0x4d80), 1, f_q)) -mstore(0x5600, mulmod(mload(0x4e20), 1, f_q)) -mstore(0x5620, mulmod(mload(0x4ec0), 1, f_q)) -mstore(0x5640, mulmod(mload(0x4f60), 1, f_q)) -mstore(0x5660, mulmod(mload(0x5000), 1, f_q)) -mstore(0x5680, mulmod(mload(0x50a0), 1, f_q)) -mstore(0x56a0, mulmod(mload(0x5140), 1, f_q)) -mstore(0x56c0, mulmod(mload(0x51e0), 1, f_q)) -mstore(0x56e0, mulmod(mload(0x5280), 1, f_q)) -mstore(0x5700, mulmod(mload(0x52a0), 1, f_q)) -mstore(0x5720, mulmod(mload(0x52c0), 1, f_q)) -mstore(0x5740, mulmod(mload(0x52e0), 1, f_q)) -mstore(0x5760, mulmod(mload(0x5300), 1, f_q)) -mstore(0x5780, mulmod(mload(0x53a0), 1, f_q)) -mstore(0x57a0, mulmod(1, mload(0x3d80), f_q)) -{ - let result := mulmod(mload(0x640), mload(0x39c0), f_q) -result := addmod(mulmod(mload(0x6c0), mload(0x39e0), f_q), result, f_q) -result := addmod(mulmod(mload(0x740), mload(0x3a00), f_q), result, f_q) -mstore(22464, result) - } -mstore(0x57e0, mulmod(mload(0x57c0), mload(0x3f80), f_q)) -mstore(0x5800, mulmod(sub(f_q, mload(0x57e0)), 1, f_q)) -mstore(0x5820, mulmod(mload(0x57a0), 1, f_q)) -{ - let result := mulmod(mload(0x660), mload(0x39c0), f_q) -result := addmod(mulmod(mload(0x6e0), mload(0x39e0), f_q), result, f_q) -result := addmod(mulmod(mload(0x760), mload(0x3a00), f_q), result, f_q) -mstore(22592, result) - } -mstore(0x5860, mulmod(mload(0x5840), mload(0x3f80), f_q)) -mstore(0x5880, mulmod(sub(f_q, mload(0x5860)), mload(0xb80), f_q)) -mstore(0x58a0, mulmod(mload(0x57a0), mload(0xb80), f_q)) -mstore(0x58c0, addmod(mload(0x5800), mload(0x5880), f_q)) -{ - let result := mulmod(mload(0x680), mload(0x39c0), f_q) -result := addmod(mulmod(mload(0x700), mload(0x39e0), f_q), result, f_q) -result := addmod(mulmod(mload(0x720), mload(0x3a00), f_q), result, f_q) -mstore(22752, result) - } -mstore(0x5900, mulmod(mload(0x58e0), mload(0x3f80), f_q)) -mstore(0x5920, mulmod(sub(f_q, mload(0x5900)), mload(0x3fe0), f_q)) -mstore(0x5940, mulmod(mload(0x57a0), mload(0x3fe0), f_q)) -mstore(0x5960, addmod(mload(0x58c0), mload(0x5920), f_q)) -mstore(0x5980, mulmod(mload(0x5960), mload(0xbe0), f_q)) -mstore(0x59a0, mulmod(mload(0x5820), mload(0xbe0), f_q)) -mstore(0x59c0, mulmod(mload(0x58a0), mload(0xbe0), f_q)) -mstore(0x59e0, mulmod(mload(0x5940), mload(0xbe0), f_q)) -mstore(0x5a00, addmod(mload(0x53e0), mload(0x5980), f_q)) -mstore(0x5a20, mulmod(1, mload(0x3dc0), f_q)) -{ - let result := mulmod(mload(0xa60), mload(0x3a60), f_q) -result := addmod(mulmod(mload(0xa80), mload(0x3a80), f_q), result, f_q) -result := addmod(mulmod(mload(0xaa0), mload(0x3aa0), f_q), result, f_q) -mstore(23104, result) - } -mstore(0x5a60, mulmod(mload(0x5a40), mload(0x3fa0), f_q)) -mstore(0x5a80, mulmod(sub(f_q, mload(0x5a60)), 1, f_q)) -mstore(0x5aa0, mulmod(mload(0x5a20), 1, f_q)) -{ - let result := mulmod(mload(0xac0), mload(0x3a60), f_q) -result := addmod(mulmod(mload(0xae0), mload(0x3a80), f_q), result, f_q) -result := addmod(mulmod(mload(0xb00), mload(0x3aa0), f_q), result, f_q) -mstore(23232, result) - } -mstore(0x5ae0, mulmod(mload(0x5ac0), mload(0x3fa0), f_q)) -mstore(0x5b00, mulmod(sub(f_q, mload(0x5ae0)), mload(0xb80), f_q)) -mstore(0x5b20, mulmod(mload(0x5a20), mload(0xb80), f_q)) -mstore(0x5b40, addmod(mload(0x5a80), mload(0x5b00), f_q)) -mstore(0x5b60, mulmod(mload(0x5b40), mload(0x4300), f_q)) -mstore(0x5b80, mulmod(mload(0x5aa0), mload(0x4300), f_q)) -mstore(0x5ba0, mulmod(mload(0x5b20), mload(0x4300), f_q)) -mstore(0x5bc0, addmod(mload(0x5a00), mload(0x5b60), f_q)) -mstore(0x5be0, mulmod(1, mload(0x3e00), f_q)) -{ - let result := mulmod(mload(0xb20), mload(0x3ae0), f_q) -result := addmod(mulmod(mload(0xb40), mload(0x3b00), f_q), result, f_q) -mstore(23552, result) - } -mstore(0x5c20, mulmod(mload(0x5c00), mload(0x3fc0), f_q)) -mstore(0x5c40, mulmod(sub(f_q, mload(0x5c20)), 1, f_q)) -mstore(0x5c60, mulmod(mload(0x5be0), 1, f_q)) -mstore(0x5c80, mulmod(mload(0x5c40), mload(0x4320), f_q)) -mstore(0x5ca0, mulmod(mload(0x5c60), mload(0x4320), f_q)) -mstore(0x5cc0, addmod(mload(0x5bc0), mload(0x5c80), f_q)) -mstore(0x5ce0, mulmod(1, mload(0x39a0), f_q)) -mstore(0x5d00, mulmod(1, mload(0xc80), f_q)) -mstore(0x5d20, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x5d40, 0x0000000000000000000000000000000000000000000000000000000000000002) -mstore(0x5d60, mload(0x5cc0)) -success := and(eq(staticcall(gas(), 0x7, 0x5d20, 0x60, 0x5d20, 0x40), 1), success) -mstore(0x5d80, mload(0x5d20)) - mstore(0x5da0, mload(0x5d40)) -mstore(0x5dc0, mload(0xc0)) - mstore(0x5de0, mload(0xe0)) -success := and(eq(staticcall(gas(), 0x6, 0x5d80, 0x80, 0x5d80, 0x40), 1), success) -mstore(0x5e00, mload(0x1c0)) - mstore(0x5e20, mload(0x1e0)) -mstore(0x5e40, mload(0x5400)) -success := and(eq(staticcall(gas(), 0x7, 0x5e00, 0x60, 0x5e00, 0x40), 1), success) -mstore(0x5e60, mload(0x5d80)) - mstore(0x5e80, mload(0x5da0)) -mstore(0x5ea0, mload(0x5e00)) - mstore(0x5ec0, mload(0x5e20)) -success := and(eq(staticcall(gas(), 0x6, 0x5e60, 0x80, 0x5e60, 0x40), 1), success) -mstore(0x5ee0, 0x0341e02d0a90fa7aac7a65889eba530d75368442ca0307a0a5f6f85b163893e9) - mstore(0x5f00, 0x1c393a8d9755fe659443beb65861563ea97e3a128b8c35dc506d69090b6870ac) -mstore(0x5f20, mload(0x5420)) -success := and(eq(staticcall(gas(), 0x7, 0x5ee0, 0x60, 0x5ee0, 0x40), 1), success) -mstore(0x5f40, mload(0x5e60)) - mstore(0x5f60, mload(0x5e80)) -mstore(0x5f80, mload(0x5ee0)) - mstore(0x5fa0, mload(0x5f00)) -success := and(eq(staticcall(gas(), 0x6, 0x5f40, 0x80, 0x5f40, 0x40), 1), success) -mstore(0x5fc0, 0x128b5ee87f8c6cb09882888619d13076e820bcc692eeaeff3bee44ecc821f4d4) - mstore(0x5fe0, 0x2b7f30ecf3bef2f2704831295fa61426b21edfa0fbfabe41b9299b596f11e0b4) -mstore(0x6000, mload(0x5440)) -success := and(eq(staticcall(gas(), 0x7, 0x5fc0, 0x60, 0x5fc0, 0x40), 1), success) -mstore(0x6020, mload(0x5f40)) - mstore(0x6040, mload(0x5f60)) -mstore(0x6060, mload(0x5fc0)) - mstore(0x6080, mload(0x5fe0)) -success := and(eq(staticcall(gas(), 0x6, 0x6020, 0x80, 0x6020, 0x40), 1), success) -mstore(0x60a0, 0x1b5e298bf4afb17fea85af012dfb9c8445e103c651e5ed61a67e0a854bfe420f) - mstore(0x60c0, 0x2038846df4afa8405699bc5d237e7d9860e311d1bccbf985acd05fc9916f1b8f) -mstore(0x60e0, mload(0x5460)) -success := and(eq(staticcall(gas(), 0x7, 0x60a0, 0x60, 0x60a0, 0x40), 1), success) -mstore(0x6100, mload(0x6020)) - mstore(0x6120, mload(0x6040)) -mstore(0x6140, mload(0x60a0)) - mstore(0x6160, mload(0x60c0)) -success := and(eq(staticcall(gas(), 0x6, 0x6100, 0x80, 0x6100, 0x40), 1), success) -mstore(0x6180, 0x1c074e4e97cf9132bb816d51dfccfeb6e01d78c3c2774bc2a3d299e800efdf93) - mstore(0x61a0, 0x1e88102db7fe50b830f08fdb80e4b7565486e6ebbac3502bd07b447139cf2afe) -mstore(0x61c0, mload(0x5480)) -success := and(eq(staticcall(gas(), 0x7, 0x6180, 0x60, 0x6180, 0x40), 1), success) -mstore(0x61e0, mload(0x6100)) - mstore(0x6200, mload(0x6120)) -mstore(0x6220, mload(0x6180)) - mstore(0x6240, mload(0x61a0)) -success := and(eq(staticcall(gas(), 0x6, 0x61e0, 0x80, 0x61e0, 0x40), 1), success) -mstore(0x6260, 0x15cef6494971fe8fa15cab3a50844f72affb41027c2b894d76f7d26da3a1598b) - mstore(0x6280, 0x26a6367840031bf2396c6c84a9830f9b0b004da830ef705b52c7da7e2642fb76) -mstore(0x62a0, mload(0x54a0)) -success := and(eq(staticcall(gas(), 0x7, 0x6260, 0x60, 0x6260, 0x40), 1), success) -mstore(0x62c0, mload(0x61e0)) - mstore(0x62e0, mload(0x6200)) -mstore(0x6300, mload(0x6260)) - mstore(0x6320, mload(0x6280)) -success := and(eq(staticcall(gas(), 0x6, 0x62c0, 0x80, 0x62c0, 0x40), 1), success) -mstore(0x6340, 0x08154ecc74f8ceed4d8fc56bd808e4a88aaaddb45869084f020703acf5159060) - mstore(0x6360, 0x1f7a554d5efed6cdeb112f1f88f8424f08a94bfa80e36778151fe73e87aeb203) -mstore(0x6380, mload(0x54c0)) -success := and(eq(staticcall(gas(), 0x7, 0x6340, 0x60, 0x6340, 0x40), 1), success) -mstore(0x63a0, mload(0x62c0)) - mstore(0x63c0, mload(0x62e0)) -mstore(0x63e0, mload(0x6340)) - mstore(0x6400, mload(0x6360)) -success := and(eq(staticcall(gas(), 0x6, 0x63a0, 0x80, 0x63a0, 0x40), 1), success) -mstore(0x6420, 0x1bc5a9858e2798d1add49f5360657dcfe9cc323a2409ac93911bff1a11ffc8ba) - mstore(0x6440, 0x2c03580c416eed8be0098bb755e7970276b362b683da9fb5df60959213656932) -mstore(0x6460, mload(0x54e0)) -success := and(eq(staticcall(gas(), 0x7, 0x6420, 0x60, 0x6420, 0x40), 1), success) -mstore(0x6480, mload(0x63a0)) - mstore(0x64a0, mload(0x63c0)) -mstore(0x64c0, mload(0x6420)) - mstore(0x64e0, mload(0x6440)) -success := and(eq(staticcall(gas(), 0x6, 0x6480, 0x80, 0x6480, 0x40), 1), success) -mstore(0x6500, 0x10f44aa8aab225b24160b866f6bfbd299646c64396807f9bdc9658ff85f9b755) - mstore(0x6520, 0x070214e425a29c414f516f0add3f4ef79e7ff9dac8e2f6d03a9f0ffe115e0672) -mstore(0x6540, mload(0x5500)) -success := and(eq(staticcall(gas(), 0x7, 0x6500, 0x60, 0x6500, 0x40), 1), success) -mstore(0x6560, mload(0x6480)) - mstore(0x6580, mload(0x64a0)) -mstore(0x65a0, mload(0x6500)) - mstore(0x65c0, mload(0x6520)) -success := and(eq(staticcall(gas(), 0x6, 0x6560, 0x80, 0x6560, 0x40), 1), success) -mstore(0x65e0, 0x0f9f565a8961cfdc8af95c0265102c68c43c7cdff118b0d31bb614f06095a7a1) - mstore(0x6600, 0x00bfaf19774d21515d5fca9a90fb2cee4ff28b7608f4e464225ee4a441c82d4d) -mstore(0x6620, mload(0x5520)) -success := and(eq(staticcall(gas(), 0x7, 0x65e0, 0x60, 0x65e0, 0x40), 1), success) -mstore(0x6640, mload(0x6560)) - mstore(0x6660, mload(0x6580)) -mstore(0x6680, mload(0x65e0)) - mstore(0x66a0, mload(0x6600)) -success := and(eq(staticcall(gas(), 0x6, 0x6640, 0x80, 0x6640, 0x40), 1), success) -mstore(0x66c0, 0x08368cbb7e88e6e5fd6a6edcc853b4a00f9ad8ab652972610271e501092d5b43) - mstore(0x66e0, 0x206a25d68953a65fbe6a3f4cb216e8617fe62cb2883704cd29f6fd3ee5d0c4cf) -mstore(0x6700, mload(0x5540)) -success := and(eq(staticcall(gas(), 0x7, 0x66c0, 0x60, 0x66c0, 0x40), 1), success) -mstore(0x6720, mload(0x6640)) - mstore(0x6740, mload(0x6660)) -mstore(0x6760, mload(0x66c0)) - mstore(0x6780, mload(0x66e0)) -success := and(eq(staticcall(gas(), 0x6, 0x6720, 0x80, 0x6720, 0x40), 1), success) -mstore(0x67a0, 0x199df78c2d44e9ba230348c70643c500bd81ea0eca68d98a31b95f12feab26de) - mstore(0x67c0, 0x0ae906a97fd1ccc673ced029ee3e17912704473bfb71187c0a64dd7015097c4a) -mstore(0x67e0, mload(0x5560)) -success := and(eq(staticcall(gas(), 0x7, 0x67a0, 0x60, 0x67a0, 0x40), 1), success) -mstore(0x6800, mload(0x6720)) - mstore(0x6820, mload(0x6740)) -mstore(0x6840, mload(0x67a0)) - mstore(0x6860, mload(0x67c0)) -success := and(eq(staticcall(gas(), 0x6, 0x6800, 0x80, 0x6800, 0x40), 1), success) -mstore(0x6880, 0x280d51932ed030fa971f74762a498584ee710b511e77a68df955c827e23fee7f) - mstore(0x68a0, 0x0713847193005b47edcf7d3617f544293988d8c0fc86d3f0d7ace2ccdbc5b8ab) -mstore(0x68c0, mload(0x5580)) -success := and(eq(staticcall(gas(), 0x7, 0x6880, 0x60, 0x6880, 0x40), 1), success) -mstore(0x68e0, mload(0x6800)) - mstore(0x6900, mload(0x6820)) -mstore(0x6920, mload(0x6880)) - mstore(0x6940, mload(0x68a0)) -success := and(eq(staticcall(gas(), 0x6, 0x68e0, 0x80, 0x68e0, 0x40), 1), success) -mstore(0x6960, 0x007b75c4483a065c1e997c956f3b22de2b320d7c12046450bcd77e386241dd5a) - mstore(0x6980, 0x28fa79fbe83057f880997b1563defc79fa528802ff5fee7cf98f3d4871e9aaf9) -mstore(0x69a0, mload(0x55a0)) -success := and(eq(staticcall(gas(), 0x7, 0x6960, 0x60, 0x6960, 0x40), 1), success) -mstore(0x69c0, mload(0x68e0)) - mstore(0x69e0, mload(0x6900)) -mstore(0x6a00, mload(0x6960)) - mstore(0x6a20, mload(0x6980)) -success := and(eq(staticcall(gas(), 0x6, 0x69c0, 0x80, 0x69c0, 0x40), 1), success) -mstore(0x6a40, 0x2a4b2d5546eb85dd541205664d052c12b53d1e10a623febeb5132d81a7fd9d05) - mstore(0x6a60, 0x111dd772c7c4982944d56565c85ac62f3a94ce449ad712af683c03364d0bd90e) -mstore(0x6a80, mload(0x55c0)) -success := and(eq(staticcall(gas(), 0x7, 0x6a40, 0x60, 0x6a40, 0x40), 1), success) -mstore(0x6aa0, mload(0x69c0)) - mstore(0x6ac0, mload(0x69e0)) -mstore(0x6ae0, mload(0x6a40)) - mstore(0x6b00, mload(0x6a60)) -success := and(eq(staticcall(gas(), 0x6, 0x6aa0, 0x80, 0x6aa0, 0x40), 1), success) -mstore(0x6b20, 0x207af788789398bcfbd1b5f8bac1c35e8437fbbcc076dbc885ab07aef8e3e0aa) - mstore(0x6b40, 0x160f16359135fde44fd6f79d9cec35a7be71c3d69b05e54d812ec4e685a4ee8f) -mstore(0x6b60, mload(0x55e0)) -success := and(eq(staticcall(gas(), 0x7, 0x6b20, 0x60, 0x6b20, 0x40), 1), success) -mstore(0x6b80, mload(0x6aa0)) - mstore(0x6ba0, mload(0x6ac0)) -mstore(0x6bc0, mload(0x6b20)) - mstore(0x6be0, mload(0x6b40)) -success := and(eq(staticcall(gas(), 0x6, 0x6b80, 0x80, 0x6b80, 0x40), 1), success) -mstore(0x6c00, 0x0a2d04fe10ac2291738a1799f225bdf76f4a3cb8b3c3bc45d4f919b8675c0d10) - mstore(0x6c20, 0x2f7963f08f423eb1ab69266ef1cf294e1b228246b7ff62cd2e47cbd16d9b784f) -mstore(0x6c40, mload(0x5600)) -success := and(eq(staticcall(gas(), 0x7, 0x6c00, 0x60, 0x6c00, 0x40), 1), success) -mstore(0x6c60, mload(0x6b80)) - mstore(0x6c80, mload(0x6ba0)) -mstore(0x6ca0, mload(0x6c00)) - mstore(0x6cc0, mload(0x6c20)) -success := and(eq(staticcall(gas(), 0x6, 0x6c60, 0x80, 0x6c60, 0x40), 1), success) -mstore(0x6ce0, 0x2515be01a26f7a57850c32df641653ca7ecd922b2168c1f6772df8e2214afaba) - mstore(0x6d00, 0x1c23af0b659338972255982b31aabad3ee2d5aa8fbc58b97eb8b165c90df8a61) -mstore(0x6d20, mload(0x5620)) -success := and(eq(staticcall(gas(), 0x7, 0x6ce0, 0x60, 0x6ce0, 0x40), 1), success) -mstore(0x6d40, mload(0x6c60)) - mstore(0x6d60, mload(0x6c80)) -mstore(0x6d80, mload(0x6ce0)) - mstore(0x6da0, mload(0x6d00)) -success := and(eq(staticcall(gas(), 0x6, 0x6d40, 0x80, 0x6d40, 0x40), 1), success) -mstore(0x6dc0, 0x060e259d46f6c7b86667c2d7e7df0cbedf7e6b17fe6aa405277904fc674df675) - mstore(0x6de0, 0x0dbea8744958aef49fab6d4e98da9497889ad0d4c90cbe4a97f96d50b7bb8511) -mstore(0x6e00, mload(0x5640)) -success := and(eq(staticcall(gas(), 0x7, 0x6dc0, 0x60, 0x6dc0, 0x40), 1), success) -mstore(0x6e20, mload(0x6d40)) - mstore(0x6e40, mload(0x6d60)) -mstore(0x6e60, mload(0x6dc0)) - mstore(0x6e80, mload(0x6de0)) -success := and(eq(staticcall(gas(), 0x6, 0x6e20, 0x80, 0x6e20, 0x40), 1), success) -mstore(0x6ea0, 0x1c80642ec68afea53a4f370f010e199950f02208fb862ec6f60ff57c636cd10c) - mstore(0x6ec0, 0x13a904e861a54452bf28ce9093f928fc41a446891642010a194034d75b2eac95) -mstore(0x6ee0, mload(0x5660)) -success := and(eq(staticcall(gas(), 0x7, 0x6ea0, 0x60, 0x6ea0, 0x40), 1), success) -mstore(0x6f00, mload(0x6e20)) - mstore(0x6f20, mload(0x6e40)) -mstore(0x6f40, mload(0x6ea0)) - mstore(0x6f60, mload(0x6ec0)) -success := and(eq(staticcall(gas(), 0x6, 0x6f00, 0x80, 0x6f00, 0x40), 1), success) -mstore(0x6f80, 0x0c1824efd938f810b1ec9b455b6fce7dedf96e18bad57241de1b35d820285f32) - mstore(0x6fa0, 0x23b2fdeaeeebb400d3f1dcee64d7296403672cf36ee453e82c3d5d90acdc739a) -mstore(0x6fc0, mload(0x5680)) -success := and(eq(staticcall(gas(), 0x7, 0x6f80, 0x60, 0x6f80, 0x40), 1), success) -mstore(0x6fe0, mload(0x6f00)) - mstore(0x7000, mload(0x6f20)) -mstore(0x7020, mload(0x6f80)) - mstore(0x7040, mload(0x6fa0)) -success := and(eq(staticcall(gas(), 0x6, 0x6fe0, 0x80, 0x6fe0, 0x40), 1), success) -mstore(0x7060, 0x0ec6d72e2ce7c233ca8af2fc2bd4223a6d81d545e8785579de4cb241740f36a2) - mstore(0x7080, 0x028a4450999577e25fc7d191fecf7f1a8a0526f7e042f316767c7ff43299fdd9) -mstore(0x70a0, mload(0x56a0)) -success := and(eq(staticcall(gas(), 0x7, 0x7060, 0x60, 0x7060, 0x40), 1), success) -mstore(0x70c0, mload(0x6fe0)) - mstore(0x70e0, mload(0x7000)) -mstore(0x7100, mload(0x7060)) - mstore(0x7120, mload(0x7080)) -success := and(eq(staticcall(gas(), 0x6, 0x70c0, 0x80, 0x70c0, 0x40), 1), success) -mstore(0x7140, 0x26d8b7b13f52340b2e122f12d279deccb9cec2319ec4371d28ef1455e8acce48) - mstore(0x7160, 0x0b69e5f1edd7a5ebb8b3d29122b6b2ae59dc5cc3fcc18a672cd2bad60357db4f) -mstore(0x7180, mload(0x56c0)) -success := and(eq(staticcall(gas(), 0x7, 0x7140, 0x60, 0x7140, 0x40), 1), success) -mstore(0x71a0, mload(0x70c0)) - mstore(0x71c0, mload(0x70e0)) -mstore(0x71e0, mload(0x7140)) - mstore(0x7200, mload(0x7160)) -success := and(eq(staticcall(gas(), 0x6, 0x71a0, 0x80, 0x71a0, 0x40), 1), success) -mstore(0x7220, mload(0x480)) - mstore(0x7240, mload(0x4a0)) -mstore(0x7260, mload(0x56e0)) -success := and(eq(staticcall(gas(), 0x7, 0x7220, 0x60, 0x7220, 0x40), 1), success) -mstore(0x7280, mload(0x71a0)) - mstore(0x72a0, mload(0x71c0)) -mstore(0x72c0, mload(0x7220)) - mstore(0x72e0, mload(0x7240)) -success := and(eq(staticcall(gas(), 0x6, 0x7280, 0x80, 0x7280, 0x40), 1), success) -mstore(0x7300, mload(0x4c0)) - mstore(0x7320, mload(0x4e0)) -mstore(0x7340, mload(0x5700)) -success := and(eq(staticcall(gas(), 0x7, 0x7300, 0x60, 0x7300, 0x40), 1), success) -mstore(0x7360, mload(0x7280)) - mstore(0x7380, mload(0x72a0)) -mstore(0x73a0, mload(0x7300)) - mstore(0x73c0, mload(0x7320)) -success := and(eq(staticcall(gas(), 0x6, 0x7360, 0x80, 0x7360, 0x40), 1), success) -mstore(0x73e0, mload(0x500)) - mstore(0x7400, mload(0x520)) -mstore(0x7420, mload(0x5720)) -success := and(eq(staticcall(gas(), 0x7, 0x73e0, 0x60, 0x73e0, 0x40), 1), success) -mstore(0x7440, mload(0x7360)) - mstore(0x7460, mload(0x7380)) -mstore(0x7480, mload(0x73e0)) - mstore(0x74a0, mload(0x7400)) -success := and(eq(staticcall(gas(), 0x6, 0x7440, 0x80, 0x7440, 0x40), 1), success) -mstore(0x74c0, mload(0x540)) - mstore(0x74e0, mload(0x560)) -mstore(0x7500, mload(0x5740)) -success := and(eq(staticcall(gas(), 0x7, 0x74c0, 0x60, 0x74c0, 0x40), 1), success) -mstore(0x7520, mload(0x7440)) - mstore(0x7540, mload(0x7460)) -mstore(0x7560, mload(0x74c0)) - mstore(0x7580, mload(0x74e0)) -success := and(eq(staticcall(gas(), 0x6, 0x7520, 0x80, 0x7520, 0x40), 1), success) -mstore(0x75a0, mload(0x580)) - mstore(0x75c0, mload(0x5a0)) -mstore(0x75e0, mload(0x5760)) -success := and(eq(staticcall(gas(), 0x7, 0x75a0, 0x60, 0x75a0, 0x40), 1), success) -mstore(0x7600, mload(0x7520)) - mstore(0x7620, mload(0x7540)) -mstore(0x7640, mload(0x75a0)) - mstore(0x7660, mload(0x75c0)) -success := and(eq(staticcall(gas(), 0x6, 0x7600, 0x80, 0x7600, 0x40), 1), success) -mstore(0x7680, mload(0x3e0)) - mstore(0x76a0, mload(0x400)) -mstore(0x76c0, mload(0x5780)) -success := and(eq(staticcall(gas(), 0x7, 0x7680, 0x60, 0x7680, 0x40), 1), success) -mstore(0x76e0, mload(0x7600)) - mstore(0x7700, mload(0x7620)) -mstore(0x7720, mload(0x7680)) - mstore(0x7740, mload(0x76a0)) -success := and(eq(staticcall(gas(), 0x6, 0x76e0, 0x80, 0x76e0, 0x40), 1), success) -mstore(0x7760, mload(0x100)) - mstore(0x7780, mload(0x120)) -mstore(0x77a0, mload(0x59a0)) -success := and(eq(staticcall(gas(), 0x7, 0x7760, 0x60, 0x7760, 0x40), 1), success) -mstore(0x77c0, mload(0x76e0)) - mstore(0x77e0, mload(0x7700)) -mstore(0x7800, mload(0x7760)) - mstore(0x7820, mload(0x7780)) -success := and(eq(staticcall(gas(), 0x6, 0x77c0, 0x80, 0x77c0, 0x40), 1), success) -mstore(0x7840, mload(0x140)) - mstore(0x7860, mload(0x160)) -mstore(0x7880, mload(0x59c0)) -success := and(eq(staticcall(gas(), 0x7, 0x7840, 0x60, 0x7840, 0x40), 1), success) -mstore(0x78a0, mload(0x77c0)) - mstore(0x78c0, mload(0x77e0)) -mstore(0x78e0, mload(0x7840)) - mstore(0x7900, mload(0x7860)) -success := and(eq(staticcall(gas(), 0x6, 0x78a0, 0x80, 0x78a0, 0x40), 1), success) -mstore(0x7920, mload(0x180)) - mstore(0x7940, mload(0x1a0)) -mstore(0x7960, mload(0x59e0)) -success := and(eq(staticcall(gas(), 0x7, 0x7920, 0x60, 0x7920, 0x40), 1), success) -mstore(0x7980, mload(0x78a0)) - mstore(0x79a0, mload(0x78c0)) -mstore(0x79c0, mload(0x7920)) - mstore(0x79e0, mload(0x7940)) -success := and(eq(staticcall(gas(), 0x6, 0x7980, 0x80, 0x7980, 0x40), 1), success) -mstore(0x7a00, mload(0x320)) - mstore(0x7a20, mload(0x340)) -mstore(0x7a40, mload(0x5b80)) -success := and(eq(staticcall(gas(), 0x7, 0x7a00, 0x60, 0x7a00, 0x40), 1), success) -mstore(0x7a60, mload(0x7980)) - mstore(0x7a80, mload(0x79a0)) -mstore(0x7aa0, mload(0x7a00)) - mstore(0x7ac0, mload(0x7a20)) -success := and(eq(staticcall(gas(), 0x6, 0x7a60, 0x80, 0x7a60, 0x40), 1), success) -mstore(0x7ae0, mload(0x360)) - mstore(0x7b00, mload(0x380)) -mstore(0x7b20, mload(0x5ba0)) -success := and(eq(staticcall(gas(), 0x7, 0x7ae0, 0x60, 0x7ae0, 0x40), 1), success) -mstore(0x7b40, mload(0x7a60)) - mstore(0x7b60, mload(0x7a80)) -mstore(0x7b80, mload(0x7ae0)) - mstore(0x7ba0, mload(0x7b00)) -success := and(eq(staticcall(gas(), 0x6, 0x7b40, 0x80, 0x7b40, 0x40), 1), success) -mstore(0x7bc0, mload(0x3a0)) - mstore(0x7be0, mload(0x3c0)) -mstore(0x7c00, mload(0x5ca0)) -success := and(eq(staticcall(gas(), 0x7, 0x7bc0, 0x60, 0x7bc0, 0x40), 1), success) -mstore(0x7c20, mload(0x7b40)) - mstore(0x7c40, mload(0x7b60)) -mstore(0x7c60, mload(0x7bc0)) - mstore(0x7c80, mload(0x7be0)) -success := and(eq(staticcall(gas(), 0x6, 0x7c20, 0x80, 0x7c20, 0x40), 1), success) -mstore(0x7ca0, mload(0xc20)) - mstore(0x7cc0, mload(0xc40)) -mstore(0x7ce0, sub(f_q, mload(0x5ce0))) -success := and(eq(staticcall(gas(), 0x7, 0x7ca0, 0x60, 0x7ca0, 0x40), 1), success) -mstore(0x7d00, mload(0x7c20)) - mstore(0x7d20, mload(0x7c40)) -mstore(0x7d40, mload(0x7ca0)) - mstore(0x7d60, mload(0x7cc0)) -success := and(eq(staticcall(gas(), 0x6, 0x7d00, 0x80, 0x7d00, 0x40), 1), success) -mstore(0x7d80, mload(0xcc0)) - mstore(0x7da0, mload(0xce0)) -mstore(0x7dc0, mload(0x5d00)) -success := and(eq(staticcall(gas(), 0x7, 0x7d80, 0x60, 0x7d80, 0x40), 1), success) -mstore(0x7de0, mload(0x7d00)) - mstore(0x7e00, mload(0x7d20)) -mstore(0x7e20, mload(0x7d80)) - mstore(0x7e40, mload(0x7da0)) -success := and(eq(staticcall(gas(), 0x6, 0x7de0, 0x80, 0x7de0, 0x40), 1), success) -mstore(0x7e60, mload(0x7de0)) - mstore(0x7e80, mload(0x7e00)) -mstore(0x7ea0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) - mstore(0x7ec0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x7ee0, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0x7f00, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) -mstore(0x7f20, mload(0xcc0)) - mstore(0x7f40, mload(0xce0)) -mstore(0x7f60, 0x0181624e80f3d6ae28df7e01eaeab1c0e919877a3b8a6b7fbc69a6817d596ea2) - mstore(0x7f80, 0x1783d30dcb12d259bb89098addf6280fa4b653be7a152542a28f7b926e27e648) - mstore(0x7fa0, 0x00ae44489d41a0d179e2dfdc03bddd883b7109f8b6ae316a59e815c1a6b35304) - mstore(0x7fc0, 0x0b2147ab62a386bd63e6de1522109b8c9588ab466f5aadfde8c41ca3749423ee) -success := and(eq(staticcall(gas(), 0x8, 0x7e60, 0x180, 0x7e60, 0x20), 1), success) -success := and(eq(mload(0x7e60), 1), success) - - if not(success) { revert(0, 0) } - return(0, 0) - - } - } - } \ No newline at end of file diff --git a/pkg/zk-circuits/src/burn/circuit.rs b/pkg/zk-circuits/src/burn/circuit.rs deleted file mode 100644 index d0be875..0000000 --- a/pkg/zk-circuits/src/burn/circuit.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crate::{chips::{ - is_constant::{IsConstantChip, IsConstantConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, -}, data::Burn}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct BurnCircuitConfig { - advices: [Column; 5], - instance: Column, - poseidon_config: PoseidonConfig, - is_zero_config: IsConstantConfig, - swap_config: CondSwapConfig, -} - -impl Circuit for Burn { - type FloorPlanner = SimpleFloorPlanner; - type Config = BurnCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Is zero chip - let is_zero_config = - IsConstantChip::configure(meta, advices[0], advices[1], advices[2], Fr::zero()); - - BurnCircuitConfig { - advices, - instance, - poseidon_config, - is_zero_config, - swap_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - self.enforce_constraints( - layouter.namespace(|| "mint"), - config.instance, - config.advices[0], - config.poseidon_config, - IsConstantChip::construct(config.is_zero_config), - CondSwapChip::construct(config.swap_config), - )?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/burn/mod.rs b/pkg/zk-circuits/src/burn/mod.rs deleted file mode 100644 index ca1b221..0000000 --- a/pkg/zk-circuits/src/burn/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[allow(clippy::module_inception)] -mod burn; -mod circuit; -#[cfg(test)] -mod tests; - diff --git a/pkg/zk-circuits/src/burn/tests.rs b/pkg/zk-circuits/src/burn/tests.rs deleted file mode 100644 index bd4301e..0000000 --- a/pkg/zk-circuits/src/burn/tests.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::data::{Burn, ParameterSet}; -use crate::evm_verifier; -use crate::test::{rollup::Rollup, util::get_params}; -use crate::util::keygen_from_params; -use halo2_base::halo2_proofs::dev::MockProver; -use halo2_base::halo2_proofs::halo2curves::bn256::Fr; -use smirk::Element; - -#[test] -fn test_burn_proof() { - let k = 9; - - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - - let bob_note = rollup.unverified_add_unspent_note(&bob, 100); - - let circuit = { - let notes = [bob_note.note()]; - let secret_key = Element::ONE; - let to_address = Element::ONE; - Burn { - notes, - secret_key, - to_address, - } - }; - let instance_columns = vec![circuit.public_inputs()]; - - // Prove mockw - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - - // Prove for real circuit - let (params, _, pk) = get_params(k, &circuit); - circuit - .prove(¶ms, &pk, &mut rand::thread_rng()) - .unwrap(); -} - -#[test] -fn generate_verifier() { - let params_9 = ParameterSet::Nine; - - let circuit = Burn::<1>::default(); - - let (pk, _) = keygen_from_params(params_9, &circuit); - let yul_code = - evm_verifier::generate_verifier(params_9, &pk, vec![circuit.public_inputs().len()]); - - let expected_yul_code = expect_test::expect_file!["./burn_verifier.yul"]; - expected_yul_code.assert_eq(&yul_code); -} diff --git a/pkg/zk-circuits/src/burn_to/burn.rs b/pkg/zk-circuits/src/burn_to/burn.rs deleted file mode 100644 index e8a87fb..0000000 --- a/pkg/zk-circuits/src/burn_to/burn.rs +++ /dev/null @@ -1,167 +0,0 @@ -use crate::chips::poseidon::poseidon_hash_gadget; -use crate::chips::swap::CondSwapChip; -use crate::chips::{is_constant::IsConstantChip, poseidon::PoseidonConfig}; -use crate::data::{BurnTo, Note, ParameterSet}; -use crate::evm_verifier; -use crate::util::{assign_constant, assign_private_input, keygen_from_params}; -use halo2_base::halo2_proofs::circuit::Value; -use halo2_base::halo2_proofs::halo2curves::bn256::G1Affine; -use halo2_base::halo2_proofs::plonk::VerifyingKey; -use halo2_base::halo2_proofs::{ - circuit::Layouter, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error, Instance, ProvingKey}, -}; -use smirk::{hash_merge, Element}; - -#[cfg(test)] -use halo2_base::halo2_proofs::halo2curves::bn256::Bn256; -#[cfg(test)] -use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; - -#[cfg(test)] -use crate::proof::Proof; -#[cfg(test)] -use rand::RngCore; - -impl BurnTo { - pub(crate) fn enforce_constraints( - &self, - mut layouter: impl Layouter, - instance: Column, - advice: Column, - poseidon_config: PoseidonConfig, - is_zero_chip: IsConstantChip, - swap_chip: CondSwapChip, - ) -> Result<(), Error> { - // Witness to kind - let kind = assign_private_input( - || "kind witness", - layouter.namespace(|| "kind witness"), - advice, - Value::known(self.kind.to_base()), - )?; - - // Witness to address - let to_address = assign_private_input( - || "to address witness", - layouter.namespace(|| "to_address witness"), - advice, - Value::known(self.to_address.to_base()), - )?; - - let zero = assign_constant( - || "zero witness", - layouter.namespace(|| "zero witness"), - advice, - Fr::zero(), - )?; - - layouter.constrain_instance(kind.cell(), instance, 0)?; - layouter.constrain_instance(to_address.cell(), instance, 1)?; - - // Witness secret_key - let secret_key: halo2_base::halo2_proofs::circuit::AssignedCell = - assign_private_input( - || "secret key witness", - layouter.namespace(|| "secret key witness"), - advice, - Value::known(self.secret_key.to_base()), - )?; - - for (i, note) in self.notes.iter().enumerate() { - // Ensure note is of valid construction - let note_cells = note.enforce_constraints( - layouter.namespace(|| format!("input_note {i}")), - advice, - poseidon_config.clone(), - is_zero_chip.clone(), - swap_chip.clone(), - )?; - - // Generate the nullifier - let nullifier = poseidon_hash_gadget( - poseidon_config.clone(), - layouter.namespace(|| "nullifer hash"), - [ - note_cells.cm.clone(), - secret_key.clone(), - note_cells.psi.clone(), - zero.clone(), - ], - )?; - - // Constrain note details to public instances - layouter.constrain_instance(nullifier.cell(), instance, i * 4 + 2)?; - layouter.constrain_instance(note_cells.value.cell(), instance, (i * 4) + 2 + 1)?; - layouter.constrain_instance(note_cells.source.cell(), instance, (i * 4) + 2 + 2)?; - - let sig = poseidon_hash_gadget( - poseidon_config.clone(), - layouter.namespace(|| "sig hash"), - [ - nullifier.clone(), - secret_key.clone(), - to_address.clone(), - kind.clone(), - ], - )?; - - layouter.constrain_instance(sig.cell(), instance, (i * 4) + 5)?; - } - - Ok(()) - } - - pub fn signature(&self, note: &Note) -> Element { - hash_merge([ - note.nullifier(self.secret_key), - self.secret_key, - self.to_address, - self.kind, - ]) - } - - pub(crate) fn public_inputs(&self) -> Vec { - let mut inputs = vec![]; - - // Kind of request - inputs.push(self.kind.to_base()); - - // Address of request - inputs.push(self.to_address.to_base()); - - for note in self.notes.iter() { - // Expose the note details we need to verify in Ethereum - inputs.push(note.nullifier(self.secret_key).into()); - inputs.push(note.value().into()); - inputs.push(note.source().into()); - inputs.push(self.signature(note).into()); - } - - inputs - } - - #[cfg(test)] - pub(crate) fn prove( - &self, - params: &ParamsKZG, - pk: &ProvingKey, - rng: impl RngCore, - ) -> Result { - let circuit = Self::default(); - let instance = self.public_inputs(); - let instances = &[instance.as_slice()]; - Proof::create(params, pk, circuit, instances, rng) - } - - pub fn evm_proof(&self, params: ParameterSet) -> Result, crate::Error> { - let (pk, _) = self.keygen(params); - - evm_verifier::gen_proof(params, &pk, self.clone(), &[&self.public_inputs()]) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} diff --git a/pkg/zk-circuits/src/burn_to/burn_to_verifier.yul b/pkg/zk-circuits/src/burn_to/burn_to_verifier.yul deleted file mode 100644 index ec838fb..0000000 --- a/pkg/zk-circuits/src/burn_to/burn_to_verifier.yul +++ /dev/null @@ -1,1633 +0,0 @@ - - object "plonk_verifier" { - code { - function allocate(size) -> ptr { - ptr := mload(0x40) - if eq(ptr, 0) { ptr := 0x60 } - mstore(0x40, add(ptr, size)) - } - let size := datasize("Runtime") - let offset := allocate(size) - datacopy(offset, dataoffset("Runtime"), size) - return(offset, size) - } - object "Runtime" { - code { - let success:bool := true - let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - function validate_ec_point(x, y) -> valid:bool { - { - let x_lt_p:bool := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_lt_p:bool := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - valid := and(x_lt_p, y_lt_p) - } - { - let x_is_zero:bool := eq(x, 0) - let y_is_zero:bool := eq(y, 0) - let x_or_y_is_zero:bool := or(x_is_zero, y_is_zero) - let x_and_y_is_not_zero:bool := not(x_or_y_is_zero) - valid := and(x_and_y_is_not_zero, valid) - } - { - let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube := mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube_plus_3 := addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_square_eq_x_cube_plus_3:bool := eq(x_cube_plus_3, y_square) - valid := and(y_square_eq_x_cube_plus_3, valid) - } - } - mstore(0x20, mod(calldataload(0x0), f_q)) -mstore(0x40, mod(calldataload(0x20), f_q)) -mstore(0x60, mod(calldataload(0x40), f_q)) -mstore(0x80, mod(calldataload(0x60), f_q)) -mstore(0xa0, mod(calldataload(0x80), f_q)) -mstore(0xc0, mod(calldataload(0xa0), f_q)) -mstore(0x0, 11639820181909433010075151564098621295864840124267478171514800439227488252023) - - { - let x := calldataload(0xc0) - mstore(0xe0, x) - let y := calldataload(0xe0) - mstore(0x100, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x100) - mstore(0x120, x) - let y := calldataload(0x120) - mstore(0x140, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x140) - mstore(0x160, x) - let y := calldataload(0x160) - mstore(0x180, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x180) - mstore(0x1a0, x) - let y := calldataload(0x1a0) - mstore(0x1c0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x1c0) - mstore(0x1e0, x) - let y := calldataload(0x1e0) - mstore(0x200, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x220, keccak256(0x0, 544)) -{ - let hash := mload(0x220) - mstore(0x240, mod(hash, f_q)) - mstore(0x260, hash) - } -mstore8(640, 1) -mstore(0x280, keccak256(0x260, 33)) -{ - let hash := mload(0x280) - mstore(0x2a0, mod(hash, f_q)) - mstore(0x2c0, hash) - } -mstore8(736, 1) -mstore(0x2e0, keccak256(0x2c0, 33)) -{ - let hash := mload(0x2e0) - mstore(0x300, mod(hash, f_q)) - mstore(0x320, hash) - } - - { - let x := calldataload(0x200) - mstore(0x340, x) - let y := calldataload(0x220) - mstore(0x360, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x240) - mstore(0x380, x) - let y := calldataload(0x260) - mstore(0x3a0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x280) - mstore(0x3c0, x) - let y := calldataload(0x2a0) - mstore(0x3e0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x2c0) - mstore(0x400, x) - let y := calldataload(0x2e0) - mstore(0x420, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x440, keccak256(0x320, 288)) -{ - let hash := mload(0x440) - mstore(0x460, mod(hash, f_q)) - mstore(0x480, hash) - } - - { - let x := calldataload(0x300) - mstore(0x4a0, x) - let y := calldataload(0x320) - mstore(0x4c0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x340) - mstore(0x4e0, x) - let y := calldataload(0x360) - mstore(0x500, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x380) - mstore(0x520, x) - let y := calldataload(0x3a0) - mstore(0x540, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x3c0) - mstore(0x560, x) - let y := calldataload(0x3e0) - mstore(0x580, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x400) - mstore(0x5a0, x) - let y := calldataload(0x420) - mstore(0x5c0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x5e0, keccak256(0x480, 352)) -{ - let hash := mload(0x5e0) - mstore(0x600, mod(hash, f_q)) - mstore(0x620, hash) - } -mstore(0x640, mod(calldataload(0x440), f_q)) -mstore(0x660, mod(calldataload(0x460), f_q)) -mstore(0x680, mod(calldataload(0x480), f_q)) -mstore(0x6a0, mod(calldataload(0x4a0), f_q)) -mstore(0x6c0, mod(calldataload(0x4c0), f_q)) -mstore(0x6e0, mod(calldataload(0x4e0), f_q)) -mstore(0x700, mod(calldataload(0x500), f_q)) -mstore(0x720, mod(calldataload(0x520), f_q)) -mstore(0x740, mod(calldataload(0x540), f_q)) -mstore(0x760, mod(calldataload(0x560), f_q)) -mstore(0x780, mod(calldataload(0x580), f_q)) -mstore(0x7a0, mod(calldataload(0x5a0), f_q)) -mstore(0x7c0, mod(calldataload(0x5c0), f_q)) -mstore(0x7e0, mod(calldataload(0x5e0), f_q)) -mstore(0x800, mod(calldataload(0x600), f_q)) -mstore(0x820, mod(calldataload(0x620), f_q)) -mstore(0x840, mod(calldataload(0x640), f_q)) -mstore(0x860, mod(calldataload(0x660), f_q)) -mstore(0x880, mod(calldataload(0x680), f_q)) -mstore(0x8a0, mod(calldataload(0x6a0), f_q)) -mstore(0x8c0, mod(calldataload(0x6c0), f_q)) -mstore(0x8e0, mod(calldataload(0x6e0), f_q)) -mstore(0x900, mod(calldataload(0x700), f_q)) -mstore(0x920, mod(calldataload(0x720), f_q)) -mstore(0x940, mod(calldataload(0x740), f_q)) -mstore(0x960, mod(calldataload(0x760), f_q)) -mstore(0x980, mod(calldataload(0x780), f_q)) -mstore(0x9a0, mod(calldataload(0x7a0), f_q)) -mstore(0x9c0, mod(calldataload(0x7c0), f_q)) -mstore(0x9e0, mod(calldataload(0x7e0), f_q)) -mstore(0xa00, mod(calldataload(0x800), f_q)) -mstore(0xa20, mod(calldataload(0x820), f_q)) -mstore(0xa40, mod(calldataload(0x840), f_q)) -mstore(0xa60, mod(calldataload(0x860), f_q)) -mstore(0xa80, mod(calldataload(0x880), f_q)) -mstore(0xaa0, mod(calldataload(0x8a0), f_q)) -mstore(0xac0, mod(calldataload(0x8c0), f_q)) -mstore(0xae0, mod(calldataload(0x8e0), f_q)) -mstore(0xb00, mod(calldataload(0x900), f_q)) -mstore(0xb20, mod(calldataload(0x920), f_q)) -mstore(0xb40, mod(calldataload(0x940), f_q)) -mstore(0xb60, mod(calldataload(0x960), f_q)) -mstore(0xb80, keccak256(0x620, 1376)) -{ - let hash := mload(0xb80) - mstore(0xba0, mod(hash, f_q)) - mstore(0xbc0, hash) - } -mstore8(3040, 1) -mstore(0xbe0, keccak256(0xbc0, 33)) -{ - let hash := mload(0xbe0) - mstore(0xc00, mod(hash, f_q)) - mstore(0xc20, hash) - } - - { - let x := calldataload(0x980) - mstore(0xc40, x) - let y := calldataload(0x9a0) - mstore(0xc60, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0xc80, keccak256(0xc20, 96)) -{ - let hash := mload(0xc80) - mstore(0xca0, mod(hash, f_q)) - mstore(0xcc0, hash) - } - - { - let x := calldataload(0x9c0) - mstore(0xce0, x) - let y := calldataload(0x9e0) - mstore(0xd00, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0xd20, mulmod(mload(0x600), mload(0x600), f_q)) -mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) -mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) -mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) -mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) -mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) -mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) -mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) -mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) -mstore(0xe40, addmod(mload(0xe20), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0xe60, mulmod(mload(0xe40), 21845492397480214137827955734036069473141043376196471776620668631523902619649, f_q)) -mstore(0xe80, mulmod(mload(0xe60), 11423757818648818765461327411617109120243501240676889555478397529313037714234, f_q)) -mstore(0xea0, addmod(mload(0x600), 10464485053190456456785078333640165968304863159739144788219806657262770781383, f_q)) -mstore(0xec0, mulmod(mload(0xe60), 18658909205715493985327367002986689246357274798059125448824250603171843521466, f_q)) -mstore(0xee0, addmod(mload(0x600), 3229333666123781236919038742270585842191089602356908894873953583403964974151, f_q)) -mstore(0xf00, mulmod(mload(0xe60), 13677048343952077794467995888380402608453928821079198134318291065290235358859, f_q)) -mstore(0xf20, addmod(mload(0x600), 8211194527887197427778409856876872480094435579336836209379913121285573136758, f_q)) -mstore(0xf40, mulmod(mload(0xe60), 9936069627611189518829255670237324269287146421271524553312532036927871056678, f_q)) -mstore(0xf60, addmod(mload(0x600), 11952173244228085703417150075019950819261217979144509790385672149647937438939, f_q)) -mstore(0xf80, mulmod(mload(0xe60), 14158528901797138466244491986759313854666262535363044392173788062030301470987, f_q)) -mstore(0xfa0, addmod(mload(0x600), 7729713970042136756001913758497961233882101865052989951524416124545507024630, f_q)) -mstore(0xfc0, mulmod(mload(0xe60), 4260969412351770314333984243767775737437927068151180798236715529158398853173, f_q)) -mstore(0xfe0, addmod(mload(0x600), 17627273459487504907912421501489499351110437332264853545461488657417409642444, f_q)) -mstore(0x1000, mulmod(mload(0xe60), 1, f_q)) -mstore(0x1020, addmod(mload(0x600), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0x1040, mulmod(mload(0xe60), 6252951856119339508807713076978770803512896272623217303779254502899773638908, f_q)) -mstore(0x1060, addmod(mload(0x600), 15635291015719935713438692668278504285035468127792817039918949683676034856709, f_q)) -mstore(0x1080, mulmod(mload(0xe60), 7393649265675507591155086225434297871937368251641985215568891852805958167681, f_q)) -mstore(0x10a0, addmod(mload(0x600), 14494593606163767631091319519822977216610996148774049128129312333769850327936, f_q)) -mstore(0x10c0, mulmod(mload(0xe60), 7274544076708594923658723438209548371461798187263202684844743708658536398896, f_q)) -mstore(0x10e0, addmod(mload(0x600), 14613698795130680298587682307047726717086566213152831658853460477917272096721, f_q)) -mstore(0x1100, mulmod(mload(0xe60), 18154240498369470423574571952998640420834620155273666494480695920805672807787, f_q)) -mstore(0x1120, addmod(mload(0x600), 3734002373469804798671833792258634667713744245142367849217508265770135687830, f_q)) -mstore(0x1140, mulmod(mload(0xe60), 15586570050748673699465420638072599785655843846638594232047124335074855808474, f_q)) -mstore(0x1160, addmod(mload(0x600), 6301672821090601522780985107184675302892520553777440111651079851500952687143, f_q)) -{ - let prod := mload(0xea0) - - prod := mulmod(mload(0xee0), prod, f_q) - mstore(0x1180, prod) - - prod := mulmod(mload(0xf20), prod, f_q) - mstore(0x11a0, prod) - - prod := mulmod(mload(0xf60), prod, f_q) - mstore(0x11c0, prod) - - prod := mulmod(mload(0xfa0), prod, f_q) - mstore(0x11e0, prod) - - prod := mulmod(mload(0xfe0), prod, f_q) - mstore(0x1200, prod) - - prod := mulmod(mload(0x1020), prod, f_q) - mstore(0x1220, prod) - - prod := mulmod(mload(0x1060), prod, f_q) - mstore(0x1240, prod) - - prod := mulmod(mload(0x10a0), prod, f_q) - mstore(0x1260, prod) - - prod := mulmod(mload(0x10e0), prod, f_q) - mstore(0x1280, prod) - - prod := mulmod(mload(0x1120), prod, f_q) - mstore(0x12a0, prod) - - prod := mulmod(mload(0x1160), prod, f_q) - mstore(0x12c0, prod) - - prod := mulmod(mload(0xe40), prod, f_q) - mstore(0x12e0, prod) - - } -mstore(0x1320, 32) -mstore(0x1340, 32) -mstore(0x1360, 32) -mstore(0x1380, mload(0x12e0)) -mstore(0x13a0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x13c0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x1320, 0xc0, 0x1300, 0x20), 1), success) -{ - - let inv := mload(0x1300) - let v - - v := mload(0xe40) - mstore(3648, mulmod(mload(0x12c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1160) - mstore(4448, mulmod(mload(0x12a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1120) - mstore(4384, mulmod(mload(0x1280), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x10e0) - mstore(4320, mulmod(mload(0x1260), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x10a0) - mstore(4256, mulmod(mload(0x1240), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1060) - mstore(4192, mulmod(mload(0x1220), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1020) - mstore(4128, mulmod(mload(0x1200), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xfe0) - mstore(4064, mulmod(mload(0x11e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xfa0) - mstore(4000, mulmod(mload(0x11c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xf60) - mstore(3936, mulmod(mload(0x11a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xf20) - mstore(3872, mulmod(mload(0x1180), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xee0) - mstore(3808, mulmod(mload(0xea0), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0xea0, inv) - - } -mstore(0x13e0, mulmod(mload(0xe80), mload(0xea0), f_q)) -mstore(0x1400, mulmod(mload(0xec0), mload(0xee0), f_q)) -mstore(0x1420, mulmod(mload(0xf00), mload(0xf20), f_q)) -mstore(0x1440, mulmod(mload(0xf40), mload(0xf60), f_q)) -mstore(0x1460, mulmod(mload(0xf80), mload(0xfa0), f_q)) -mstore(0x1480, mulmod(mload(0xfc0), mload(0xfe0), f_q)) -mstore(0x14a0, mulmod(mload(0x1000), mload(0x1020), f_q)) -mstore(0x14c0, mulmod(mload(0x1040), mload(0x1060), f_q)) -mstore(0x14e0, mulmod(mload(0x1080), mload(0x10a0), f_q)) -mstore(0x1500, mulmod(mload(0x10c0), mload(0x10e0), f_q)) -mstore(0x1520, mulmod(mload(0x1100), mload(0x1120), f_q)) -mstore(0x1540, mulmod(mload(0x1140), mload(0x1160), f_q)) -{ - let result := mulmod(mload(0x14a0), mload(0x20), f_q) -result := addmod(mulmod(mload(0x14c0), mload(0x40), f_q), result, f_q) -result := addmod(mulmod(mload(0x14e0), mload(0x60), f_q), result, f_q) -result := addmod(mulmod(mload(0x1500), mload(0x80), f_q), result, f_q) -result := addmod(mulmod(mload(0x1520), mload(0xa0), f_q), result, f_q) -result := addmod(mulmod(mload(0x1540), mload(0xc0), f_q), result, f_q) -mstore(5472, result) - } -mstore(0x1580, addmod(mload(0x660), mload(0x7a0), f_q)) -mstore(0x15a0, mulmod(mload(0x1580), mload(0x1580), f_q)) -mstore(0x15c0, mulmod(mload(0x15a0), mload(0x15a0), f_q)) -mstore(0x15e0, mulmod(mload(0x1580), mload(0x15c0), f_q)) -mstore(0x1600, mulmod(mload(0x15e0), 7511745149465107256748700652201246547602992235352608707588321460060273774987, f_q)) -mstore(0x1620, addmod(mload(0x680), mload(0x820), f_q)) -mstore(0x1640, mulmod(mload(0x1620), mload(0x1620), f_q)) -mstore(0x1660, mulmod(mload(0x1640), mload(0x1640), f_q)) -mstore(0x1680, mulmod(mload(0x1620), mload(0x1660), f_q)) -mstore(0x16a0, mulmod(mload(0x1680), 10370080108974718697676803824769673834027675643658433702224577712625900127200, f_q)) -mstore(0x16c0, addmod(mload(0x1600), mload(0x16a0), f_q)) -mstore(0x16e0, addmod(mload(0x6a0), mload(0x840), f_q)) -mstore(0x1700, mulmod(mload(0x16e0), mload(0x16e0), f_q)) -mstore(0x1720, mulmod(mload(0x1700), mload(0x1700), f_q)) -mstore(0x1740, mulmod(mload(0x16e0), mload(0x1720), f_q)) -mstore(0x1760, mulmod(mload(0x1740), 19705173408229649878903981084052839426532978878058043055305024233888854471533, f_q)) -mstore(0x1780, addmod(mload(0x16c0), mload(0x1760), f_q)) -mstore(0x17a0, addmod(mload(0x1780), sub(f_q, mload(0x6e0)), f_q)) -mstore(0x17c0, mulmod(mload(0x17a0), mload(0x860), f_q)) -mstore(0x17e0, mulmod(mload(0x460), mload(0x17c0), f_q)) -mstore(0x1800, mulmod(mload(0x15e0), 18732019378264290557468133440468564866454307626475683536618613112504878618481, f_q)) -mstore(0x1820, mulmod(mload(0x1680), 20870176810702568768751421378473869562658540583882454726129544628203806653987, f_q)) -mstore(0x1840, addmod(mload(0x1800), mload(0x1820), f_q)) -mstore(0x1860, mulmod(mload(0x1740), 7266061498423634438633389053804536045105766754026813321943009179476902321146, f_q)) -mstore(0x1880, addmod(mload(0x1840), mload(0x1860), f_q)) -mstore(0x18a0, addmod(mload(0x1880), sub(f_q, mload(0x700)), f_q)) -mstore(0x18c0, mulmod(mload(0x18a0), mload(0x860), f_q)) -mstore(0x18e0, addmod(mload(0x17e0), mload(0x18c0), f_q)) -mstore(0x1900, mulmod(mload(0x460), mload(0x18e0), f_q)) -mstore(0x1920, mulmod(mload(0x15e0), 9131299761947733513298312097611845208338517739621853568979632113419485819303, f_q)) -mstore(0x1940, mulmod(mload(0x1680), 10595341252162738537912664445405114076324478519622938027420701542910180337937, f_q)) -mstore(0x1960, addmod(mload(0x1920), mload(0x1940), f_q)) -mstore(0x1980, mulmod(mload(0x1740), 11597556804922396090267472882856054602429588299176362916247939723151043581408, f_q)) -mstore(0x19a0, addmod(mload(0x1960), mload(0x1980), f_q)) -mstore(0x19c0, addmod(mload(0x19a0), sub(f_q, mload(0x720)), f_q)) -mstore(0x19e0, mulmod(mload(0x19c0), mload(0x860), f_q)) -mstore(0x1a00, addmod(mload(0x1900), mload(0x19e0), f_q)) -mstore(0x1a20, mulmod(mload(0x460), mload(0x1a00), f_q)) -mstore(0x1a40, addmod(mload(0x15e0), sub(f_q, mload(0x640)), f_q)) -mstore(0x1a60, mulmod(mload(0x1a40), mload(0x880), f_q)) -mstore(0x1a80, addmod(mload(0x1a20), mload(0x1a60), f_q)) -mstore(0x1aa0, mulmod(mload(0x460), mload(0x1a80), f_q)) -mstore(0x1ac0, mulmod(mload(0x640), 7511745149465107256748700652201246547602992235352608707588321460060273774987, f_q)) -mstore(0x1ae0, mulmod(mload(0x1620), 10370080108974718697676803824769673834027675643658433702224577712625900127200, f_q)) -mstore(0x1b00, addmod(mload(0x1ac0), mload(0x1ae0), f_q)) -mstore(0x1b20, mulmod(mload(0x16e0), 19705173408229649878903981084052839426532978878058043055305024233888854471533, f_q)) -mstore(0x1b40, addmod(mload(0x1b00), mload(0x1b20), f_q)) -mstore(0x1b60, addmod(mload(0x1b40), mload(0x7c0), f_q)) -mstore(0x1b80, mulmod(mload(0x1b60), mload(0x1b60), f_q)) -mstore(0x1ba0, mulmod(mload(0x1b80), mload(0x1b80), f_q)) -mstore(0x1bc0, mulmod(mload(0x1b60), mload(0x1ba0), f_q)) -mstore(0x1be0, mulmod(mload(0x6e0), 14581990407185373640425896461718924180109794780799188900903678642755512839974, f_q)) -mstore(0x1c00, mulmod(mload(0x700), 18866968878651837536281064213261914109651535895144158735451177080294903852066, f_q)) -mstore(0x1c20, addmod(mload(0x1be0), mload(0x1c00), f_q)) -mstore(0x1c40, mulmod(mload(0x720), 7839627026775837327267018712780335784833794955194428770232963186824469625450, f_q)) -mstore(0x1c60, addmod(mload(0x1c20), mload(0x1c40), f_q)) -mstore(0x1c80, addmod(mload(0x1bc0), sub(f_q, mload(0x1c60)), f_q)) -mstore(0x1ca0, mulmod(mload(0x1c80), mload(0x880), f_q)) -mstore(0x1cc0, addmod(mload(0x1aa0), mload(0x1ca0), f_q)) -mstore(0x1ce0, mulmod(mload(0x460), mload(0x1cc0), f_q)) -mstore(0x1d00, mulmod(mload(0x640), 18732019378264290557468133440468564866454307626475683536618613112504878618481, f_q)) -mstore(0x1d20, mulmod(mload(0x1620), 20870176810702568768751421378473869562658540583882454726129544628203806653987, f_q)) -mstore(0x1d40, addmod(mload(0x1d00), mload(0x1d20), f_q)) -mstore(0x1d60, mulmod(mload(0x16e0), 7266061498423634438633389053804536045105766754026813321943009179476902321146, f_q)) -mstore(0x1d80, addmod(mload(0x1d40), mload(0x1d60), f_q)) -mstore(0x1da0, addmod(mload(0x1d80), mload(0x7e0), f_q)) -mstore(0x1dc0, mulmod(mload(0x6e0), 18938579070830856475783700955955783311402730090941909099413093949983854639956, f_q)) -mstore(0x1de0, mulmod(mload(0x700), 8613994242085266665256493323589366394657716111166474713216639394202078033993, f_q)) -mstore(0x1e00, addmod(mload(0x1dc0), mload(0x1de0), f_q)) -mstore(0x1e20, mulmod(mload(0x720), 5498488707276883206944027953979269171532592088279065622083714982398440150521, f_q)) -mstore(0x1e40, addmod(mload(0x1e00), mload(0x1e20), f_q)) -mstore(0x1e60, addmod(mload(0x1da0), sub(f_q, mload(0x1e40)), f_q)) -mstore(0x1e80, mulmod(mload(0x1e60), mload(0x880), f_q)) -mstore(0x1ea0, addmod(mload(0x1ce0), mload(0x1e80), f_q)) -mstore(0x1ec0, mulmod(mload(0x460), mload(0x1ea0), f_q)) -mstore(0x1ee0, mulmod(mload(0x640), 9131299761947733513298312097611845208338517739621853568979632113419485819303, f_q)) -mstore(0x1f00, mulmod(mload(0x1620), 10595341252162738537912664445405114076324478519622938027420701542910180337937, f_q)) -mstore(0x1f20, addmod(mload(0x1ee0), mload(0x1f00), f_q)) -mstore(0x1f40, mulmod(mload(0x16e0), 11597556804922396090267472882856054602429588299176362916247939723151043581408, f_q)) -mstore(0x1f60, addmod(mload(0x1f20), mload(0x1f40), f_q)) -mstore(0x1f80, addmod(mload(0x1f60), mload(0x800), f_q)) -mstore(0x1fa0, mulmod(mload(0x6e0), 655752878747070013666604006434797489161341466456915955415098407670323222025, f_q)) -mstore(0x1fc0, mulmod(mload(0x700), 4856172836225950379592127603074379105027349156448153533703883389233432728400, f_q)) -mstore(0x1fe0, addmod(mload(0x1fa0), mload(0x1fc0), f_q)) -mstore(0x2000, mulmod(mload(0x720), 10503264605839191981081969978629584646259107387222177725485772749763096823552, f_q)) -mstore(0x2020, addmod(mload(0x1fe0), mload(0x2000), f_q)) -mstore(0x2040, addmod(mload(0x1f80), sub(f_q, mload(0x2020)), f_q)) -mstore(0x2060, mulmod(mload(0x2040), mload(0x880), f_q)) -mstore(0x2080, addmod(mload(0x1ec0), mload(0x2060), f_q)) -mstore(0x20a0, mulmod(mload(0x460), mload(0x2080), f_q)) -mstore(0x20c0, addmod(mload(0x1ae0), mload(0x1b20), f_q)) -mstore(0x20e0, addmod(mload(0x1600), mload(0x20c0), f_q)) -mstore(0x2100, addmod(mload(0x20e0), sub(f_q, mload(0x6e0)), f_q)) -mstore(0x2120, mulmod(mload(0x2100), mload(0x8a0), f_q)) -mstore(0x2140, addmod(mload(0x20a0), mload(0x2120), f_q)) -mstore(0x2160, mulmod(mload(0x460), mload(0x2140), f_q)) -mstore(0x2180, addmod(mload(0x1d20), mload(0x1d60), f_q)) -mstore(0x21a0, addmod(mload(0x1800), mload(0x2180), f_q)) -mstore(0x21c0, addmod(mload(0x21a0), sub(f_q, mload(0x700)), f_q)) -mstore(0x21e0, mulmod(mload(0x21c0), mload(0x8a0), f_q)) -mstore(0x2200, addmod(mload(0x2160), mload(0x21e0), f_q)) -mstore(0x2220, mulmod(mload(0x460), mload(0x2200), f_q)) -mstore(0x2240, addmod(mload(0x1f00), mload(0x1f40), f_q)) -mstore(0x2260, addmod(mload(0x1920), mload(0x2240), f_q)) -mstore(0x2280, addmod(mload(0x2260), sub(f_q, mload(0x720)), f_q)) -mstore(0x22a0, mulmod(mload(0x2280), mload(0x8a0), f_q)) -mstore(0x22c0, addmod(mload(0x2220), mload(0x22a0), f_q)) -mstore(0x22e0, mulmod(mload(0x460), mload(0x22c0), f_q)) -mstore(0x2300, addmod(mload(0x760), mload(0x660), f_q)) -mstore(0x2320, addmod(mload(0x2300), sub(f_q, mload(0x6e0)), f_q)) -mstore(0x2340, mulmod(mload(0x2320), mload(0x8c0), f_q)) -mstore(0x2360, addmod(mload(0x22e0), mload(0x2340), f_q)) -mstore(0x2380, mulmod(mload(0x460), mload(0x2360), f_q)) -mstore(0x23a0, addmod(mload(0x780), mload(0x680), f_q)) -mstore(0x23c0, addmod(mload(0x23a0), sub(f_q, mload(0x700)), f_q)) -mstore(0x23e0, mulmod(mload(0x23c0), mload(0x8c0), f_q)) -mstore(0x2400, addmod(mload(0x2380), mload(0x23e0), f_q)) -mstore(0x2420, mulmod(mload(0x460), mload(0x2400), f_q)) -mstore(0x2440, addmod(mload(0x740), sub(f_q, mload(0x720)), f_q)) -mstore(0x2460, mulmod(mload(0x2440), mload(0x8c0), f_q)) -mstore(0x2480, addmod(mload(0x2420), mload(0x2460), f_q)) -mstore(0x24a0, mulmod(mload(0x460), mload(0x2480), f_q)) -mstore(0x24c0, mulmod(mload(0x660), mload(0x6c0), f_q)) -mstore(0x24e0, addmod(1, sub(f_q, mload(0x6c0)), f_q)) -mstore(0x2500, mulmod(mload(0x640), mload(0x24e0), f_q)) -mstore(0x2520, addmod(mload(0x24c0), mload(0x2500), f_q)) -mstore(0x2540, addmod(mload(0x680), sub(f_q, mload(0x2520)), f_q)) -mstore(0x2560, mulmod(mload(0x2540), mload(0x8e0), f_q)) -mstore(0x2580, addmod(mload(0x24a0), mload(0x2560), f_q)) -mstore(0x25a0, mulmod(mload(0x460), mload(0x2580), f_q)) -mstore(0x25c0, mulmod(mload(0x640), mload(0x6c0), f_q)) -mstore(0x25e0, mulmod(mload(0x660), mload(0x24e0), f_q)) -mstore(0x2600, addmod(mload(0x25c0), mload(0x25e0), f_q)) -mstore(0x2620, addmod(mload(0x6a0), sub(f_q, mload(0x2600)), f_q)) -mstore(0x2640, mulmod(mload(0x2620), mload(0x8e0), f_q)) -mstore(0x2660, addmod(mload(0x25a0), mload(0x2640), f_q)) -mstore(0x2680, mulmod(mload(0x460), mload(0x2660), f_q)) -mstore(0x26a0, mulmod(mload(0x24e0), mload(0x6c0), f_q)) -mstore(0x26c0, mulmod(mload(0x26a0), mload(0x8e0), f_q)) -mstore(0x26e0, addmod(mload(0x2680), mload(0x26c0), f_q)) -mstore(0x2700, mulmod(mload(0x460), mload(0x26e0), f_q)) -mstore(0x2720, addmod(mload(0x640), 21888242871839275222246405745257275088548364400416034343698204186575808495617, f_q)) -mstore(0x2740, mulmod(mload(0x2720), mload(0x900), f_q)) -mstore(0x2760, mulmod(mload(0x660), mload(0x2720), f_q)) -mstore(0x2780, addmod(1, sub(f_q, mload(0x2760)), f_q)) -mstore(0x27a0, mulmod(mload(0x2780), mload(0x2740), f_q)) -mstore(0x27c0, addmod(mload(0x2700), mload(0x27a0), f_q)) -mstore(0x27e0, mulmod(mload(0x460), mload(0x27c0), f_q)) -mstore(0x2800, addmod(mload(0x680), sub(f_q, mload(0x2780)), f_q)) -mstore(0x2820, mulmod(mload(0x2800), mload(0x900), f_q)) -mstore(0x2840, addmod(mload(0x27e0), mload(0x2820), f_q)) -mstore(0x2860, mulmod(mload(0x460), mload(0x2840), f_q)) -mstore(0x2880, addmod(1, sub(f_q, mload(0xa80)), f_q)) -mstore(0x28a0, mulmod(mload(0x2880), mload(0x14a0), f_q)) -mstore(0x28c0, addmod(mload(0x2860), mload(0x28a0), f_q)) -mstore(0x28e0, mulmod(mload(0x460), mload(0x28c0), f_q)) -mstore(0x2900, mulmod(mload(0xb40), mload(0xb40), f_q)) -mstore(0x2920, addmod(mload(0x2900), sub(f_q, mload(0xb40)), f_q)) -mstore(0x2940, mulmod(mload(0x2920), mload(0x13e0), f_q)) -mstore(0x2960, addmod(mload(0x28e0), mload(0x2940), f_q)) -mstore(0x2980, mulmod(mload(0x460), mload(0x2960), f_q)) -mstore(0x29a0, addmod(mload(0xae0), sub(f_q, mload(0xac0)), f_q)) -mstore(0x29c0, mulmod(mload(0x29a0), mload(0x14a0), f_q)) -mstore(0x29e0, addmod(mload(0x2980), mload(0x29c0), f_q)) -mstore(0x2a00, mulmod(mload(0x460), mload(0x29e0), f_q)) -mstore(0x2a20, addmod(mload(0xb40), sub(f_q, mload(0xb20)), f_q)) -mstore(0x2a40, mulmod(mload(0x2a20), mload(0x14a0), f_q)) -mstore(0x2a60, addmod(mload(0x2a00), mload(0x2a40), f_q)) -mstore(0x2a80, mulmod(mload(0x460), mload(0x2a60), f_q)) -mstore(0x2aa0, addmod(1, sub(f_q, mload(0x13e0)), f_q)) -mstore(0x2ac0, addmod(mload(0x1400), mload(0x1420), f_q)) -mstore(0x2ae0, addmod(mload(0x2ac0), mload(0x1440), f_q)) -mstore(0x2b00, addmod(mload(0x2ae0), mload(0x1460), f_q)) -mstore(0x2b20, addmod(mload(0x2b00), mload(0x1480), f_q)) -mstore(0x2b40, addmod(mload(0x2aa0), sub(f_q, mload(0x2b20)), f_q)) -mstore(0x2b60, mulmod(mload(0x940), mload(0x2a0), f_q)) -mstore(0x2b80, addmod(mload(0x1560), mload(0x2b60), f_q)) -mstore(0x2ba0, addmod(mload(0x2b80), mload(0x300), f_q)) -mstore(0x2bc0, mulmod(mload(0x960), mload(0x2a0), f_q)) -mstore(0x2be0, addmod(mload(0x640), mload(0x2bc0), f_q)) -mstore(0x2c00, addmod(mload(0x2be0), mload(0x300), f_q)) -mstore(0x2c20, mulmod(mload(0x2c00), mload(0x2ba0), f_q)) -mstore(0x2c40, mulmod(mload(0x980), mload(0x2a0), f_q)) -mstore(0x2c60, addmod(mload(0x660), mload(0x2c40), f_q)) -mstore(0x2c80, addmod(mload(0x2c60), mload(0x300), f_q)) -mstore(0x2ca0, mulmod(mload(0x2c80), mload(0x2c20), f_q)) -mstore(0x2cc0, mulmod(mload(0x9a0), mload(0x2a0), f_q)) -mstore(0x2ce0, addmod(mload(0x680), mload(0x2cc0), f_q)) -mstore(0x2d00, addmod(mload(0x2ce0), mload(0x300), f_q)) -mstore(0x2d20, mulmod(mload(0x2d00), mload(0x2ca0), f_q)) -mstore(0x2d40, mulmod(mload(0x2d20), mload(0xaa0), f_q)) -mstore(0x2d60, mulmod(1, mload(0x2a0), f_q)) -mstore(0x2d80, mulmod(mload(0x600), mload(0x2d60), f_q)) -mstore(0x2da0, addmod(mload(0x1560), mload(0x2d80), f_q)) -mstore(0x2dc0, addmod(mload(0x2da0), mload(0x300), f_q)) -mstore(0x2de0, mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x2a0), f_q)) -mstore(0x2e00, mulmod(mload(0x600), mload(0x2de0), f_q)) -mstore(0x2e20, addmod(mload(0x640), mload(0x2e00), f_q)) -mstore(0x2e40, addmod(mload(0x2e20), mload(0x300), f_q)) -mstore(0x2e60, mulmod(mload(0x2e40), mload(0x2dc0), f_q)) -mstore(0x2e80, mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x2a0), f_q)) -mstore(0x2ea0, mulmod(mload(0x600), mload(0x2e80), f_q)) -mstore(0x2ec0, addmod(mload(0x660), mload(0x2ea0), f_q)) -mstore(0x2ee0, addmod(mload(0x2ec0), mload(0x300), f_q)) -mstore(0x2f00, mulmod(mload(0x2ee0), mload(0x2e60), f_q)) -mstore(0x2f20, mulmod(11166246659983828508719468090013646171463329086121580628794302409516816350802, mload(0x2a0), f_q)) -mstore(0x2f40, mulmod(mload(0x600), mload(0x2f20), f_q)) -mstore(0x2f60, addmod(mload(0x680), mload(0x2f40), f_q)) -mstore(0x2f80, addmod(mload(0x2f60), mload(0x300), f_q)) -mstore(0x2fa0, mulmod(mload(0x2f80), mload(0x2f00), f_q)) -mstore(0x2fc0, mulmod(mload(0x2fa0), mload(0xa80), f_q)) -mstore(0x2fe0, addmod(mload(0x2d40), sub(f_q, mload(0x2fc0)), f_q)) -mstore(0x3000, mulmod(mload(0x2fe0), mload(0x2b40), f_q)) -mstore(0x3020, addmod(mload(0x2a80), mload(0x3000), f_q)) -mstore(0x3040, mulmod(mload(0x460), mload(0x3020), f_q)) -mstore(0x3060, mulmod(mload(0x9c0), mload(0x2a0), f_q)) -mstore(0x3080, addmod(mload(0x6a0), mload(0x3060), f_q)) -mstore(0x30a0, addmod(mload(0x3080), mload(0x300), f_q)) -mstore(0x30c0, mulmod(mload(0x9e0), mload(0x2a0), f_q)) -mstore(0x30e0, addmod(mload(0x6c0), mload(0x30c0), f_q)) -mstore(0x3100, addmod(mload(0x30e0), mload(0x300), f_q)) -mstore(0x3120, mulmod(mload(0x3100), mload(0x30a0), f_q)) -mstore(0x3140, mulmod(mload(0xa00), mload(0x2a0), f_q)) -mstore(0x3160, addmod(mload(0x7a0), mload(0x3140), f_q)) -mstore(0x3180, addmod(mload(0x3160), mload(0x300), f_q)) -mstore(0x31a0, mulmod(mload(0x3180), mload(0x3120), f_q)) -mstore(0x31c0, mulmod(mload(0xa20), mload(0x2a0), f_q)) -mstore(0x31e0, addmod(mload(0x7c0), mload(0x31c0), f_q)) -mstore(0x3200, addmod(mload(0x31e0), mload(0x300), f_q)) -mstore(0x3220, mulmod(mload(0x3200), mload(0x31a0), f_q)) -mstore(0x3240, mulmod(mload(0x3220), mload(0xb00), f_q)) -mstore(0x3260, mulmod(284840088355319032285349970403338060113257071685626700086398481893096618818, mload(0x2a0), f_q)) -mstore(0x3280, mulmod(mload(0x600), mload(0x3260), f_q)) -mstore(0x32a0, addmod(mload(0x6a0), mload(0x3280), f_q)) -mstore(0x32c0, addmod(mload(0x32a0), mload(0x300), f_q)) -mstore(0x32e0, mulmod(21134065618345176623193549882539580312263652408302468683943992798037078993309, mload(0x2a0), f_q)) -mstore(0x3300, mulmod(mload(0x600), mload(0x32e0), f_q)) -mstore(0x3320, addmod(mload(0x6c0), mload(0x3300), f_q)) -mstore(0x3340, addmod(mload(0x3320), mload(0x300), f_q)) -mstore(0x3360, mulmod(mload(0x3340), mload(0x32c0), f_q)) -mstore(0x3380, mulmod(5625741653535312224677218588085279924365897425605943700675464992185016992283, mload(0x2a0), f_q)) -mstore(0x33a0, mulmod(mload(0x600), mload(0x3380), f_q)) -mstore(0x33c0, addmod(mload(0x7a0), mload(0x33a0), f_q)) -mstore(0x33e0, addmod(mload(0x33c0), mload(0x300), f_q)) -mstore(0x3400, mulmod(mload(0x33e0), mload(0x3360), f_q)) -mstore(0x3420, mulmod(14704729814417906439424896605881467874595262020190401576785074330126828718155, mload(0x2a0), f_q)) -mstore(0x3440, mulmod(mload(0x600), mload(0x3420), f_q)) -mstore(0x3460, addmod(mload(0x7c0), mload(0x3440), f_q)) -mstore(0x3480, addmod(mload(0x3460), mload(0x300), f_q)) -mstore(0x34a0, mulmod(mload(0x3480), mload(0x3400), f_q)) -mstore(0x34c0, mulmod(mload(0x34a0), mload(0xae0), f_q)) -mstore(0x34e0, addmod(mload(0x3240), sub(f_q, mload(0x34c0)), f_q)) -mstore(0x3500, mulmod(mload(0x34e0), mload(0x2b40), f_q)) -mstore(0x3520, addmod(mload(0x3040), mload(0x3500), f_q)) -mstore(0x3540, mulmod(mload(0x460), mload(0x3520), f_q)) -mstore(0x3560, mulmod(mload(0xa40), mload(0x2a0), f_q)) -mstore(0x3580, addmod(mload(0x7e0), mload(0x3560), f_q)) -mstore(0x35a0, addmod(mload(0x3580), mload(0x300), f_q)) -mstore(0x35c0, mulmod(mload(0xa60), mload(0x2a0), f_q)) -mstore(0x35e0, addmod(mload(0x800), mload(0x35c0), f_q)) -mstore(0x3600, addmod(mload(0x35e0), mload(0x300), f_q)) -mstore(0x3620, mulmod(mload(0x3600), mload(0x35a0), f_q)) -mstore(0x3640, mulmod(mload(0x3620), mload(0xb60), f_q)) -mstore(0x3660, mulmod(8343274462013750416000956870576256937330525306073862550863787263304548803879, mload(0x2a0), f_q)) -mstore(0x3680, mulmod(mload(0x600), mload(0x3660), f_q)) -mstore(0x36a0, addmod(mload(0x7e0), mload(0x3680), f_q)) -mstore(0x36c0, addmod(mload(0x36a0), mload(0x300), f_q)) -mstore(0x36e0, mulmod(20928372310071051017340352686640453451620397549739756658327314209761852842004, mload(0x2a0), f_q)) -mstore(0x3700, mulmod(mload(0x600), mload(0x36e0), f_q)) -mstore(0x3720, addmod(mload(0x800), mload(0x3700), f_q)) -mstore(0x3740, addmod(mload(0x3720), mload(0x300), f_q)) -mstore(0x3760, mulmod(mload(0x3740), mload(0x36c0), f_q)) -mstore(0x3780, mulmod(mload(0x3760), mload(0xb40), f_q)) -mstore(0x37a0, addmod(mload(0x3640), sub(f_q, mload(0x3780)), f_q)) -mstore(0x37c0, mulmod(mload(0x37a0), mload(0x2b40), f_q)) -mstore(0x37e0, addmod(mload(0x3540), mload(0x37c0), f_q)) -mstore(0x3800, mulmod(mload(0xe20), mload(0xe20), f_q)) -mstore(0x3820, mulmod(mload(0x3800), mload(0xe20), f_q)) -mstore(0x3840, mulmod(mload(0x3820), mload(0xe20), f_q)) -mstore(0x3860, mulmod(mload(0x3840), mload(0xe20), f_q)) -mstore(0x3880, mulmod(1, mload(0xe20), f_q)) -mstore(0x38a0, mulmod(1, mload(0x3800), f_q)) -mstore(0x38c0, mulmod(1, mload(0x3820), f_q)) -mstore(0x38e0, mulmod(1, mload(0x3840), f_q)) -mstore(0x3900, mulmod(mload(0x37e0), mload(0xe40), f_q)) -mstore(0x3920, mulmod(mload(0x600), 1, f_q)) -mstore(0x3940, addmod(mload(0xca0), sub(f_q, mload(0x3920)), f_q)) -mstore(0x3960, mulmod(mload(0x600), 4260969412351770314333984243767775737437927068151180798236715529158398853173, f_q)) -mstore(0x3980, addmod(mload(0xca0), sub(f_q, mload(0x3960)), f_q)) -mstore(0x39a0, mulmod(mload(0x600), 6252951856119339508807713076978770803512896272623217303779254502899773638908, f_q)) -mstore(0x39c0, addmod(mload(0xca0), sub(f_q, mload(0x39a0)), f_q)) -mstore(0x39e0, mulmod(mload(0x600), 11423757818648818765461327411617109120243501240676889555478397529313037714234, f_q)) -mstore(0x3a00, addmod(mload(0xca0), sub(f_q, mload(0x39e0)), f_q)) -{ - let result := mulmod(mload(0xca0), 1, f_q) -result := addmod(mulmod(mload(0x600), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q), result, f_q) -mstore(14880, result) - } -mstore(0x3a40, mulmod(1, mload(0x3940), f_q)) -{ - let result := mulmod(mload(0xca0), 11374321603368165399104708424510728547597541059641636241682234154517636003538, f_q) -result := addmod(mulmod(mload(0x600), 10513921268471109823141697320746546540950823340774398102015970032058172492079, f_q), result, f_q) -mstore(14944, result) - } -{ - let result := mulmod(mload(0xca0), 5401666821907938396681357392223302805862399047169948710026352879064583381945, f_q) -result := addmod(mulmod(mload(0x600), 6372057045086252176304075864203520303988466337001999834503402647047195407692, f_q), result, f_q) -mstore(14976, result) - } -{ - let result := mulmod(mload(0xca0), 16150511345564707660718220819970308920741231739835080897716327035771676256721, f_q) -result := addmod(mulmod(mload(0x600), 8483428686537719261749220560289765322817043182242700637097971554260829267481, f_q), result, f_q) -mstore(15008, result) - } -mstore(0x3ac0, mulmod(mload(0x3a40), mload(0x39c0), f_q)) -mstore(0x3ae0, mulmod(mload(0x3ac0), mload(0x3980), f_q)) -{ - let result := mulmod(mload(0xca0), 982199530947335711058326514390809322600877284759018589566598570959032168325, f_q) -result := addmod(mulmod(mload(0x600), 20906043340891939511188079230866465765947487115657015754131605615616776327292, f_q), result, f_q) -mstore(15104, result) - } -{ - let result := mulmod(mload(0xca0), 15793788894328768084727739302343222030859062822052566362141988462623187217158, f_q) -result := addmod(mulmod(mload(0x600), 17025487199042771698883397417875737951120588487814889559916392792841622101795, f_q), result, f_q) -mstore(15136, result) - } -{ - let result := mulmod(mload(0xca0), 8225778414108386131857824234780332238746220130309253143140026671792101940293, f_q) -result := addmod(mulmod(mload(0x600), 12089860469981555972352979896169738621752335090266596234307820947387409624317, f_q), result, f_q) -mstore(15168, result) - } -mstore(0x3b60, mulmod(mload(0x3ac0), mload(0x3a00), f_q)) -{ - let result := mulmod(mload(0xca0), 15635291015719935713438692668278504285035468127792817039918949683676034856710, f_q) -result := addmod(mulmod(mload(0x600), 6252951856119339508807713076978770803512896272623217303779254502899773638907, f_q), result, f_q) -mstore(15232, result) - } -{ - let result := mulmod(mload(0xca0), 6252951856119339508807713076978770803512896272623217303779254502899773638907, f_q) -result := addmod(mulmod(mload(0x600), 20747545462283107139899032596801748020123892421397266431908566836669623966844, f_q), result, f_q) -mstore(15264, result) - } -{ - let prod := mload(0x3a20) - - prod := mulmod(mload(0x3a60), prod, f_q) - mstore(0x3bc0, prod) - - prod := mulmod(mload(0x3a80), prod, f_q) - mstore(0x3be0, prod) - - prod := mulmod(mload(0x3aa0), prod, f_q) - mstore(0x3c00, prod) - - prod := mulmod(mload(0x3ae0), prod, f_q) - mstore(0x3c20, prod) - - prod := mulmod(mload(0x3b00), prod, f_q) - mstore(0x3c40, prod) - - prod := mulmod(mload(0x3b20), prod, f_q) - mstore(0x3c60, prod) - - prod := mulmod(mload(0x3b40), prod, f_q) - mstore(0x3c80, prod) - - prod := mulmod(mload(0x3b60), prod, f_q) - mstore(0x3ca0, prod) - - prod := mulmod(mload(0x3b80), prod, f_q) - mstore(0x3cc0, prod) - - prod := mulmod(mload(0x3ba0), prod, f_q) - mstore(0x3ce0, prod) - - prod := mulmod(mload(0x3ac0), prod, f_q) - mstore(0x3d00, prod) - - } -mstore(0x3d40, 32) -mstore(0x3d60, 32) -mstore(0x3d80, 32) -mstore(0x3da0, mload(0x3d00)) -mstore(0x3dc0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x3de0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x3d40, 0xc0, 0x3d20, 0x20), 1), success) -{ - - let inv := mload(0x3d20) - let v - - v := mload(0x3ac0) - mstore(15040, mulmod(mload(0x3ce0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3ba0) - mstore(15264, mulmod(mload(0x3cc0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b80) - mstore(15232, mulmod(mload(0x3ca0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b60) - mstore(15200, mulmod(mload(0x3c80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b40) - mstore(15168, mulmod(mload(0x3c60), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b20) - mstore(15136, mulmod(mload(0x3c40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3b00) - mstore(15104, mulmod(mload(0x3c20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3ae0) - mstore(15072, mulmod(mload(0x3c00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3aa0) - mstore(15008, mulmod(mload(0x3be0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3a80) - mstore(14976, mulmod(mload(0x3bc0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3a60) - mstore(14944, mulmod(mload(0x3a20), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x3a20, inv) - - } -{ - let result := mload(0x3a20) -mstore(15872, result) - } -mstore(0x3e20, mulmod(mload(0x3a40), mload(0x3ae0), f_q)) -{ - let result := mload(0x3a60) -result := addmod(mload(0x3a80), result, f_q) -result := addmod(mload(0x3aa0), result, f_q) -mstore(15936, result) - } -mstore(0x3e60, mulmod(mload(0x3a40), mload(0x3b60), f_q)) -{ - let result := mload(0x3b00) -result := addmod(mload(0x3b20), result, f_q) -result := addmod(mload(0x3b40), result, f_q) -mstore(16000, result) - } -mstore(0x3ea0, mulmod(mload(0x3a40), mload(0x3ac0), f_q)) -{ - let result := mload(0x3b80) -result := addmod(mload(0x3ba0), result, f_q) -mstore(16064, result) - } -{ - let prod := mload(0x3e00) - - prod := mulmod(mload(0x3e40), prod, f_q) - mstore(0x3ee0, prod) - - prod := mulmod(mload(0x3e80), prod, f_q) - mstore(0x3f00, prod) - - prod := mulmod(mload(0x3ec0), prod, f_q) - mstore(0x3f20, prod) - - } -mstore(0x3f60, 32) -mstore(0x3f80, 32) -mstore(0x3fa0, 32) -mstore(0x3fc0, mload(0x3f20)) -mstore(0x3fe0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x4000, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x3f60, 0xc0, 0x3f40, 0x20), 1), success) -{ - - let inv := mload(0x3f40) - let v - - v := mload(0x3ec0) - mstore(16064, mulmod(mload(0x3f00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3e80) - mstore(16000, mulmod(mload(0x3ee0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3e40) - mstore(15936, mulmod(mload(0x3e00), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x3e00, inv) - - } -mstore(0x4020, mulmod(mload(0x3e20), mload(0x3e40), f_q)) -mstore(0x4040, mulmod(mload(0x3e60), mload(0x3e80), f_q)) -mstore(0x4060, mulmod(mload(0x3ea0), mload(0x3ec0), f_q)) -mstore(0x4080, mulmod(mload(0xba0), mload(0xba0), f_q)) -mstore(0x40a0, mulmod(mload(0x4080), mload(0xba0), f_q)) -mstore(0x40c0, mulmod(mload(0x40a0), mload(0xba0), f_q)) -mstore(0x40e0, mulmod(mload(0x40c0), mload(0xba0), f_q)) -mstore(0x4100, mulmod(mload(0x40e0), mload(0xba0), f_q)) -mstore(0x4120, mulmod(mload(0x4100), mload(0xba0), f_q)) -mstore(0x4140, mulmod(mload(0x4120), mload(0xba0), f_q)) -mstore(0x4160, mulmod(mload(0x4140), mload(0xba0), f_q)) -mstore(0x4180, mulmod(mload(0x4160), mload(0xba0), f_q)) -mstore(0x41a0, mulmod(mload(0x4180), mload(0xba0), f_q)) -mstore(0x41c0, mulmod(mload(0x41a0), mload(0xba0), f_q)) -mstore(0x41e0, mulmod(mload(0x41c0), mload(0xba0), f_q)) -mstore(0x4200, mulmod(mload(0x41e0), mload(0xba0), f_q)) -mstore(0x4220, mulmod(mload(0x4200), mload(0xba0), f_q)) -mstore(0x4240, mulmod(mload(0x4220), mload(0xba0), f_q)) -mstore(0x4260, mulmod(mload(0x4240), mload(0xba0), f_q)) -mstore(0x4280, mulmod(mload(0x4260), mload(0xba0), f_q)) -mstore(0x42a0, mulmod(mload(0x4280), mload(0xba0), f_q)) -mstore(0x42c0, mulmod(mload(0x42a0), mload(0xba0), f_q)) -mstore(0x42e0, mulmod(mload(0x42c0), mload(0xba0), f_q)) -mstore(0x4300, mulmod(mload(0x42e0), mload(0xba0), f_q)) -mstore(0x4320, mulmod(mload(0x4300), mload(0xba0), f_q)) -mstore(0x4340, mulmod(mload(0x4320), mload(0xba0), f_q)) -mstore(0x4360, mulmod(mload(0x4340), mload(0xba0), f_q)) -mstore(0x4380, mulmod(mload(0x4360), mload(0xba0), f_q)) -mstore(0x43a0, mulmod(mload(0xc00), mload(0xc00), f_q)) -mstore(0x43c0, mulmod(mload(0x43a0), mload(0xc00), f_q)) -mstore(0x43e0, mulmod(mload(0x43c0), mload(0xc00), f_q)) -{ - let result := mulmod(mload(0x640), mload(0x3a20), f_q) -mstore(17408, result) - } -mstore(0x4420, mulmod(mload(0x4400), mload(0x3e00), f_q)) -mstore(0x4440, mulmod(sub(f_q, mload(0x4420)), 1, f_q)) -{ - let result := mulmod(mload(0x6c0), mload(0x3a20), f_q) -mstore(17504, result) - } -mstore(0x4480, mulmod(mload(0x4460), mload(0x3e00), f_q)) -mstore(0x44a0, mulmod(sub(f_q, mload(0x4480)), mload(0xba0), f_q)) -mstore(0x44c0, mulmod(1, mload(0xba0), f_q)) -mstore(0x44e0, addmod(mload(0x4440), mload(0x44a0), f_q)) -{ - let result := mulmod(mload(0x7a0), mload(0x3a20), f_q) -mstore(17664, result) - } -mstore(0x4520, mulmod(mload(0x4500), mload(0x3e00), f_q)) -mstore(0x4540, mulmod(sub(f_q, mload(0x4520)), mload(0x4080), f_q)) -mstore(0x4560, mulmod(1, mload(0x4080), f_q)) -mstore(0x4580, addmod(mload(0x44e0), mload(0x4540), f_q)) -{ - let result := mulmod(mload(0x7c0), mload(0x3a20), f_q) -mstore(17824, result) - } -mstore(0x45c0, mulmod(mload(0x45a0), mload(0x3e00), f_q)) -mstore(0x45e0, mulmod(sub(f_q, mload(0x45c0)), mload(0x40a0), f_q)) -mstore(0x4600, mulmod(1, mload(0x40a0), f_q)) -mstore(0x4620, addmod(mload(0x4580), mload(0x45e0), f_q)) -{ - let result := mulmod(mload(0x7e0), mload(0x3a20), f_q) -mstore(17984, result) - } -mstore(0x4660, mulmod(mload(0x4640), mload(0x3e00), f_q)) -mstore(0x4680, mulmod(sub(f_q, mload(0x4660)), mload(0x40c0), f_q)) -mstore(0x46a0, mulmod(1, mload(0x40c0), f_q)) -mstore(0x46c0, addmod(mload(0x4620), mload(0x4680), f_q)) -{ - let result := mulmod(mload(0x800), mload(0x3a20), f_q) -mstore(18144, result) - } -mstore(0x4700, mulmod(mload(0x46e0), mload(0x3e00), f_q)) -mstore(0x4720, mulmod(sub(f_q, mload(0x4700)), mload(0x40e0), f_q)) -mstore(0x4740, mulmod(1, mload(0x40e0), f_q)) -mstore(0x4760, addmod(mload(0x46c0), mload(0x4720), f_q)) -{ - let result := mulmod(mload(0x820), mload(0x3a20), f_q) -mstore(18304, result) - } -mstore(0x47a0, mulmod(mload(0x4780), mload(0x3e00), f_q)) -mstore(0x47c0, mulmod(sub(f_q, mload(0x47a0)), mload(0x4100), f_q)) -mstore(0x47e0, mulmod(1, mload(0x4100), f_q)) -mstore(0x4800, addmod(mload(0x4760), mload(0x47c0), f_q)) -{ - let result := mulmod(mload(0x840), mload(0x3a20), f_q) -mstore(18464, result) - } -mstore(0x4840, mulmod(mload(0x4820), mload(0x3e00), f_q)) -mstore(0x4860, mulmod(sub(f_q, mload(0x4840)), mload(0x4120), f_q)) -mstore(0x4880, mulmod(1, mload(0x4120), f_q)) -mstore(0x48a0, addmod(mload(0x4800), mload(0x4860), f_q)) -{ - let result := mulmod(mload(0x860), mload(0x3a20), f_q) -mstore(18624, result) - } -mstore(0x48e0, mulmod(mload(0x48c0), mload(0x3e00), f_q)) -mstore(0x4900, mulmod(sub(f_q, mload(0x48e0)), mload(0x4140), f_q)) -mstore(0x4920, mulmod(1, mload(0x4140), f_q)) -mstore(0x4940, addmod(mload(0x48a0), mload(0x4900), f_q)) -{ - let result := mulmod(mload(0x880), mload(0x3a20), f_q) -mstore(18784, result) - } -mstore(0x4980, mulmod(mload(0x4960), mload(0x3e00), f_q)) -mstore(0x49a0, mulmod(sub(f_q, mload(0x4980)), mload(0x4160), f_q)) -mstore(0x49c0, mulmod(1, mload(0x4160), f_q)) -mstore(0x49e0, addmod(mload(0x4940), mload(0x49a0), f_q)) -{ - let result := mulmod(mload(0x8a0), mload(0x3a20), f_q) -mstore(18944, result) - } -mstore(0x4a20, mulmod(mload(0x4a00), mload(0x3e00), f_q)) -mstore(0x4a40, mulmod(sub(f_q, mload(0x4a20)), mload(0x4180), f_q)) -mstore(0x4a60, mulmod(1, mload(0x4180), f_q)) -mstore(0x4a80, addmod(mload(0x49e0), mload(0x4a40), f_q)) -{ - let result := mulmod(mload(0x8c0), mload(0x3a20), f_q) -mstore(19104, result) - } -mstore(0x4ac0, mulmod(mload(0x4aa0), mload(0x3e00), f_q)) -mstore(0x4ae0, mulmod(sub(f_q, mload(0x4ac0)), mload(0x41a0), f_q)) -mstore(0x4b00, mulmod(1, mload(0x41a0), f_q)) -mstore(0x4b20, addmod(mload(0x4a80), mload(0x4ae0), f_q)) -{ - let result := mulmod(mload(0x8e0), mload(0x3a20), f_q) -mstore(19264, result) - } -mstore(0x4b60, mulmod(mload(0x4b40), mload(0x3e00), f_q)) -mstore(0x4b80, mulmod(sub(f_q, mload(0x4b60)), mload(0x41c0), f_q)) -mstore(0x4ba0, mulmod(1, mload(0x41c0), f_q)) -mstore(0x4bc0, addmod(mload(0x4b20), mload(0x4b80), f_q)) -{ - let result := mulmod(mload(0x900), mload(0x3a20), f_q) -mstore(19424, result) - } -mstore(0x4c00, mulmod(mload(0x4be0), mload(0x3e00), f_q)) -mstore(0x4c20, mulmod(sub(f_q, mload(0x4c00)), mload(0x41e0), f_q)) -mstore(0x4c40, mulmod(1, mload(0x41e0), f_q)) -mstore(0x4c60, addmod(mload(0x4bc0), mload(0x4c20), f_q)) -{ - let result := mulmod(mload(0x940), mload(0x3a20), f_q) -mstore(19584, result) - } -mstore(0x4ca0, mulmod(mload(0x4c80), mload(0x3e00), f_q)) -mstore(0x4cc0, mulmod(sub(f_q, mload(0x4ca0)), mload(0x4200), f_q)) -mstore(0x4ce0, mulmod(1, mload(0x4200), f_q)) -mstore(0x4d00, addmod(mload(0x4c60), mload(0x4cc0), f_q)) -{ - let result := mulmod(mload(0x960), mload(0x3a20), f_q) -mstore(19744, result) - } -mstore(0x4d40, mulmod(mload(0x4d20), mload(0x3e00), f_q)) -mstore(0x4d60, mulmod(sub(f_q, mload(0x4d40)), mload(0x4220), f_q)) -mstore(0x4d80, mulmod(1, mload(0x4220), f_q)) -mstore(0x4da0, addmod(mload(0x4d00), mload(0x4d60), f_q)) -{ - let result := mulmod(mload(0x980), mload(0x3a20), f_q) -mstore(19904, result) - } -mstore(0x4de0, mulmod(mload(0x4dc0), mload(0x3e00), f_q)) -mstore(0x4e00, mulmod(sub(f_q, mload(0x4de0)), mload(0x4240), f_q)) -mstore(0x4e20, mulmod(1, mload(0x4240), f_q)) -mstore(0x4e40, addmod(mload(0x4da0), mload(0x4e00), f_q)) -{ - let result := mulmod(mload(0x9a0), mload(0x3a20), f_q) -mstore(20064, result) - } -mstore(0x4e80, mulmod(mload(0x4e60), mload(0x3e00), f_q)) -mstore(0x4ea0, mulmod(sub(f_q, mload(0x4e80)), mload(0x4260), f_q)) -mstore(0x4ec0, mulmod(1, mload(0x4260), f_q)) -mstore(0x4ee0, addmod(mload(0x4e40), mload(0x4ea0), f_q)) -{ - let result := mulmod(mload(0x9c0), mload(0x3a20), f_q) -mstore(20224, result) - } -mstore(0x4f20, mulmod(mload(0x4f00), mload(0x3e00), f_q)) -mstore(0x4f40, mulmod(sub(f_q, mload(0x4f20)), mload(0x4280), f_q)) -mstore(0x4f60, mulmod(1, mload(0x4280), f_q)) -mstore(0x4f80, addmod(mload(0x4ee0), mload(0x4f40), f_q)) -{ - let result := mulmod(mload(0x9e0), mload(0x3a20), f_q) -mstore(20384, result) - } -mstore(0x4fc0, mulmod(mload(0x4fa0), mload(0x3e00), f_q)) -mstore(0x4fe0, mulmod(sub(f_q, mload(0x4fc0)), mload(0x42a0), f_q)) -mstore(0x5000, mulmod(1, mload(0x42a0), f_q)) -mstore(0x5020, addmod(mload(0x4f80), mload(0x4fe0), f_q)) -{ - let result := mulmod(mload(0xa00), mload(0x3a20), f_q) -mstore(20544, result) - } -mstore(0x5060, mulmod(mload(0x5040), mload(0x3e00), f_q)) -mstore(0x5080, mulmod(sub(f_q, mload(0x5060)), mload(0x42c0), f_q)) -mstore(0x50a0, mulmod(1, mload(0x42c0), f_q)) -mstore(0x50c0, addmod(mload(0x5020), mload(0x5080), f_q)) -{ - let result := mulmod(mload(0xa20), mload(0x3a20), f_q) -mstore(20704, result) - } -mstore(0x5100, mulmod(mload(0x50e0), mload(0x3e00), f_q)) -mstore(0x5120, mulmod(sub(f_q, mload(0x5100)), mload(0x42e0), f_q)) -mstore(0x5140, mulmod(1, mload(0x42e0), f_q)) -mstore(0x5160, addmod(mload(0x50c0), mload(0x5120), f_q)) -{ - let result := mulmod(mload(0xa40), mload(0x3a20), f_q) -mstore(20864, result) - } -mstore(0x51a0, mulmod(mload(0x5180), mload(0x3e00), f_q)) -mstore(0x51c0, mulmod(sub(f_q, mload(0x51a0)), mload(0x4300), f_q)) -mstore(0x51e0, mulmod(1, mload(0x4300), f_q)) -mstore(0x5200, addmod(mload(0x5160), mload(0x51c0), f_q)) -{ - let result := mulmod(mload(0xa60), mload(0x3a20), f_q) -mstore(21024, result) - } -mstore(0x5240, mulmod(mload(0x5220), mload(0x3e00), f_q)) -mstore(0x5260, mulmod(sub(f_q, mload(0x5240)), mload(0x4320), f_q)) -mstore(0x5280, mulmod(1, mload(0x4320), f_q)) -mstore(0x52a0, addmod(mload(0x5200), mload(0x5260), f_q)) -{ - let result := mulmod(mload(0x3900), mload(0x3a20), f_q) -mstore(21184, result) - } -mstore(0x52e0, mulmod(mload(0x52c0), mload(0x3e00), f_q)) -mstore(0x5300, mulmod(sub(f_q, mload(0x52e0)), mload(0x4340), f_q)) -mstore(0x5320, mulmod(1, mload(0x4340), f_q)) -mstore(0x5340, mulmod(mload(0x3880), mload(0x4340), f_q)) -mstore(0x5360, mulmod(mload(0x38a0), mload(0x4340), f_q)) -mstore(0x5380, mulmod(mload(0x38c0), mload(0x4340), f_q)) -mstore(0x53a0, mulmod(mload(0x38e0), mload(0x4340), f_q)) -mstore(0x53c0, addmod(mload(0x52a0), mload(0x5300), f_q)) -{ - let result := mulmod(mload(0x920), mload(0x3a20), f_q) -mstore(21472, result) - } -mstore(0x5400, mulmod(mload(0x53e0), mload(0x3e00), f_q)) -mstore(0x5420, mulmod(sub(f_q, mload(0x5400)), mload(0x4360), f_q)) -mstore(0x5440, mulmod(1, mload(0x4360), f_q)) -mstore(0x5460, addmod(mload(0x53c0), mload(0x5420), f_q)) -mstore(0x5480, mulmod(mload(0x5460), 1, f_q)) -mstore(0x54a0, mulmod(mload(0x44c0), 1, f_q)) -mstore(0x54c0, mulmod(mload(0x4560), 1, f_q)) -mstore(0x54e0, mulmod(mload(0x4600), 1, f_q)) -mstore(0x5500, mulmod(mload(0x46a0), 1, f_q)) -mstore(0x5520, mulmod(mload(0x4740), 1, f_q)) -mstore(0x5540, mulmod(mload(0x47e0), 1, f_q)) -mstore(0x5560, mulmod(mload(0x4880), 1, f_q)) -mstore(0x5580, mulmod(mload(0x4920), 1, f_q)) -mstore(0x55a0, mulmod(mload(0x49c0), 1, f_q)) -mstore(0x55c0, mulmod(mload(0x4a60), 1, f_q)) -mstore(0x55e0, mulmod(mload(0x4b00), 1, f_q)) -mstore(0x5600, mulmod(mload(0x4ba0), 1, f_q)) -mstore(0x5620, mulmod(mload(0x4c40), 1, f_q)) -mstore(0x5640, mulmod(mload(0x4ce0), 1, f_q)) -mstore(0x5660, mulmod(mload(0x4d80), 1, f_q)) -mstore(0x5680, mulmod(mload(0x4e20), 1, f_q)) -mstore(0x56a0, mulmod(mload(0x4ec0), 1, f_q)) -mstore(0x56c0, mulmod(mload(0x4f60), 1, f_q)) -mstore(0x56e0, mulmod(mload(0x5000), 1, f_q)) -mstore(0x5700, mulmod(mload(0x50a0), 1, f_q)) -mstore(0x5720, mulmod(mload(0x5140), 1, f_q)) -mstore(0x5740, mulmod(mload(0x51e0), 1, f_q)) -mstore(0x5760, mulmod(mload(0x5280), 1, f_q)) -mstore(0x5780, mulmod(mload(0x5320), 1, f_q)) -mstore(0x57a0, mulmod(mload(0x5340), 1, f_q)) -mstore(0x57c0, mulmod(mload(0x5360), 1, f_q)) -mstore(0x57e0, mulmod(mload(0x5380), 1, f_q)) -mstore(0x5800, mulmod(mload(0x53a0), 1, f_q)) -mstore(0x5820, mulmod(mload(0x5440), 1, f_q)) -mstore(0x5840, mulmod(1, mload(0x3e20), f_q)) -{ - let result := mulmod(mload(0x660), mload(0x3a60), f_q) -result := addmod(mulmod(mload(0x6e0), mload(0x3a80), f_q), result, f_q) -result := addmod(mulmod(mload(0x760), mload(0x3aa0), f_q), result, f_q) -mstore(22624, result) - } -mstore(0x5880, mulmod(mload(0x5860), mload(0x4020), f_q)) -mstore(0x58a0, mulmod(sub(f_q, mload(0x5880)), 1, f_q)) -mstore(0x58c0, mulmod(mload(0x5840), 1, f_q)) -{ - let result := mulmod(mload(0x680), mload(0x3a60), f_q) -result := addmod(mulmod(mload(0x700), mload(0x3a80), f_q), result, f_q) -result := addmod(mulmod(mload(0x780), mload(0x3aa0), f_q), result, f_q) -mstore(22752, result) - } -mstore(0x5900, mulmod(mload(0x58e0), mload(0x4020), f_q)) -mstore(0x5920, mulmod(sub(f_q, mload(0x5900)), mload(0xba0), f_q)) -mstore(0x5940, mulmod(mload(0x5840), mload(0xba0), f_q)) -mstore(0x5960, addmod(mload(0x58a0), mload(0x5920), f_q)) -{ - let result := mulmod(mload(0x6a0), mload(0x3a60), f_q) -result := addmod(mulmod(mload(0x720), mload(0x3a80), f_q), result, f_q) -result := addmod(mulmod(mload(0x740), mload(0x3aa0), f_q), result, f_q) -mstore(22912, result) - } -mstore(0x59a0, mulmod(mload(0x5980), mload(0x4020), f_q)) -mstore(0x59c0, mulmod(sub(f_q, mload(0x59a0)), mload(0x4080), f_q)) -mstore(0x59e0, mulmod(mload(0x5840), mload(0x4080), f_q)) -mstore(0x5a00, addmod(mload(0x5960), mload(0x59c0), f_q)) -mstore(0x5a20, mulmod(mload(0x5a00), mload(0xc00), f_q)) -mstore(0x5a40, mulmod(mload(0x58c0), mload(0xc00), f_q)) -mstore(0x5a60, mulmod(mload(0x5940), mload(0xc00), f_q)) -mstore(0x5a80, mulmod(mload(0x59e0), mload(0xc00), f_q)) -mstore(0x5aa0, addmod(mload(0x5480), mload(0x5a20), f_q)) -mstore(0x5ac0, mulmod(1, mload(0x3e60), f_q)) -{ - let result := mulmod(mload(0xa80), mload(0x3b00), f_q) -result := addmod(mulmod(mload(0xaa0), mload(0x3b20), f_q), result, f_q) -result := addmod(mulmod(mload(0xac0), mload(0x3b40), f_q), result, f_q) -mstore(23264, result) - } -mstore(0x5b00, mulmod(mload(0x5ae0), mload(0x4040), f_q)) -mstore(0x5b20, mulmod(sub(f_q, mload(0x5b00)), 1, f_q)) -mstore(0x5b40, mulmod(mload(0x5ac0), 1, f_q)) -{ - let result := mulmod(mload(0xae0), mload(0x3b00), f_q) -result := addmod(mulmod(mload(0xb00), mload(0x3b20), f_q), result, f_q) -result := addmod(mulmod(mload(0xb20), mload(0x3b40), f_q), result, f_q) -mstore(23392, result) - } -mstore(0x5b80, mulmod(mload(0x5b60), mload(0x4040), f_q)) -mstore(0x5ba0, mulmod(sub(f_q, mload(0x5b80)), mload(0xba0), f_q)) -mstore(0x5bc0, mulmod(mload(0x5ac0), mload(0xba0), f_q)) -mstore(0x5be0, addmod(mload(0x5b20), mload(0x5ba0), f_q)) -mstore(0x5c00, mulmod(mload(0x5be0), mload(0x43a0), f_q)) -mstore(0x5c20, mulmod(mload(0x5b40), mload(0x43a0), f_q)) -mstore(0x5c40, mulmod(mload(0x5bc0), mload(0x43a0), f_q)) -mstore(0x5c60, addmod(mload(0x5aa0), mload(0x5c00), f_q)) -mstore(0x5c80, mulmod(1, mload(0x3ea0), f_q)) -{ - let result := mulmod(mload(0xb40), mload(0x3b80), f_q) -result := addmod(mulmod(mload(0xb60), mload(0x3ba0), f_q), result, f_q) -mstore(23712, result) - } -mstore(0x5cc0, mulmod(mload(0x5ca0), mload(0x4060), f_q)) -mstore(0x5ce0, mulmod(sub(f_q, mload(0x5cc0)), 1, f_q)) -mstore(0x5d00, mulmod(mload(0x5c80), 1, f_q)) -mstore(0x5d20, mulmod(mload(0x5ce0), mload(0x43c0), f_q)) -mstore(0x5d40, mulmod(mload(0x5d00), mload(0x43c0), f_q)) -mstore(0x5d60, addmod(mload(0x5c60), mload(0x5d20), f_q)) -mstore(0x5d80, mulmod(1, mload(0x3a40), f_q)) -mstore(0x5da0, mulmod(1, mload(0xca0), f_q)) -mstore(0x5dc0, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x5de0, 0x0000000000000000000000000000000000000000000000000000000000000002) -mstore(0x5e00, mload(0x5d60)) -success := and(eq(staticcall(gas(), 0x7, 0x5dc0, 0x60, 0x5dc0, 0x40), 1), success) -mstore(0x5e20, mload(0x5dc0)) - mstore(0x5e40, mload(0x5de0)) -mstore(0x5e60, mload(0xe0)) - mstore(0x5e80, mload(0x100)) -success := and(eq(staticcall(gas(), 0x6, 0x5e20, 0x80, 0x5e20, 0x40), 1), success) -mstore(0x5ea0, mload(0x1e0)) - mstore(0x5ec0, mload(0x200)) -mstore(0x5ee0, mload(0x54a0)) -success := and(eq(staticcall(gas(), 0x7, 0x5ea0, 0x60, 0x5ea0, 0x40), 1), success) -mstore(0x5f00, mload(0x5e20)) - mstore(0x5f20, mload(0x5e40)) -mstore(0x5f40, mload(0x5ea0)) - mstore(0x5f60, mload(0x5ec0)) -success := and(eq(staticcall(gas(), 0x6, 0x5f00, 0x80, 0x5f00, 0x40), 1), success) -mstore(0x5f80, 0x1ba48a6fef916a20d399bbfadbf9ccbb2932899f6f8b18279099a1ca149cc34e) - mstore(0x5fa0, 0x0eabb2d19e057cfc46d6920a45f37aab2516e74af3704650233f17ce888ecd07) -mstore(0x5fc0, mload(0x54c0)) -success := and(eq(staticcall(gas(), 0x7, 0x5f80, 0x60, 0x5f80, 0x40), 1), success) -mstore(0x5fe0, mload(0x5f00)) - mstore(0x6000, mload(0x5f20)) -mstore(0x6020, mload(0x5f80)) - mstore(0x6040, mload(0x5fa0)) -success := and(eq(staticcall(gas(), 0x6, 0x5fe0, 0x80, 0x5fe0, 0x40), 1), success) -mstore(0x6060, 0x088fe5ff0415f316b067e6982f2edec66829c3e608c4158dd3e9d0d8185d86eb) - mstore(0x6080, 0x067d99198137fe9eff93c6dae0c9883ef80895fb17a510ca75ce80f1691ee1a4) -mstore(0x60a0, mload(0x54e0)) -success := and(eq(staticcall(gas(), 0x7, 0x6060, 0x60, 0x6060, 0x40), 1), success) -mstore(0x60c0, mload(0x5fe0)) - mstore(0x60e0, mload(0x6000)) -mstore(0x6100, mload(0x6060)) - mstore(0x6120, mload(0x6080)) -success := and(eq(staticcall(gas(), 0x6, 0x60c0, 0x80, 0x60c0, 0x40), 1), success) -mstore(0x6140, 0x119ba9ef28301d5d0adb7a66026643253adcd4df7f72a1cbb08bb1c3e12b65a3) - mstore(0x6160, 0x20e5530ea585d269979502b1507aacde9197cd3bb17f83082e3ad2d267c0edaa) -mstore(0x6180, mload(0x5500)) -success := and(eq(staticcall(gas(), 0x7, 0x6140, 0x60, 0x6140, 0x40), 1), success) -mstore(0x61a0, mload(0x60c0)) - mstore(0x61c0, mload(0x60e0)) -mstore(0x61e0, mload(0x6140)) - mstore(0x6200, mload(0x6160)) -success := and(eq(staticcall(gas(), 0x6, 0x61a0, 0x80, 0x61a0, 0x40), 1), success) -mstore(0x6220, 0x0570e8e102786dc2d699bc91c4328e1c30cd3e44ea92c447bd5f1aba0e857584) - mstore(0x6240, 0x0dba8fcae8f82e505add438241991e1ccb9e0356448329e2b08ca14cb4f041be) -mstore(0x6260, mload(0x5520)) -success := and(eq(staticcall(gas(), 0x7, 0x6220, 0x60, 0x6220, 0x40), 1), success) -mstore(0x6280, mload(0x61a0)) - mstore(0x62a0, mload(0x61c0)) -mstore(0x62c0, mload(0x6220)) - mstore(0x62e0, mload(0x6240)) -success := and(eq(staticcall(gas(), 0x6, 0x6280, 0x80, 0x6280, 0x40), 1), success) -mstore(0x6300, 0x05f6ef57df75900751a0b8585f49515b5ea5e5e129cac385c7a9519dc8d7dcf1) - mstore(0x6320, 0x16c3d325bc0e50eb7f119628b0d15b387a1db49d0a7e6c5689a167ea54105072) -mstore(0x6340, mload(0x5540)) -success := and(eq(staticcall(gas(), 0x7, 0x6300, 0x60, 0x6300, 0x40), 1), success) -mstore(0x6360, mload(0x6280)) - mstore(0x6380, mload(0x62a0)) -mstore(0x63a0, mload(0x6300)) - mstore(0x63c0, mload(0x6320)) -success := and(eq(staticcall(gas(), 0x6, 0x6360, 0x80, 0x6360, 0x40), 1), success) -mstore(0x63e0, 0x1725fadbd5c5a1527f313b0975a5b21a390f474197ae7411099db096ed540562) - mstore(0x6400, 0x1a7d9ef8207090b3ab3b3dbb683922c79f1c65f623c9449532dea7d56019d711) -mstore(0x6420, mload(0x5560)) -success := and(eq(staticcall(gas(), 0x7, 0x63e0, 0x60, 0x63e0, 0x40), 1), success) -mstore(0x6440, mload(0x6360)) - mstore(0x6460, mload(0x6380)) -mstore(0x6480, mload(0x63e0)) - mstore(0x64a0, mload(0x6400)) -success := and(eq(staticcall(gas(), 0x6, 0x6440, 0x80, 0x6440, 0x40), 1), success) -mstore(0x64c0, 0x2aefc3ed0030b8f1349065a636377e51dd0ab87c2f62afb414dd43abf8254b12) - mstore(0x64e0, 0x177b723ea72fdbc9267318b6cd9a9aef2b0b69341c938700134ac71c983bd72f) -mstore(0x6500, mload(0x5580)) -success := and(eq(staticcall(gas(), 0x7, 0x64c0, 0x60, 0x64c0, 0x40), 1), success) -mstore(0x6520, mload(0x6440)) - mstore(0x6540, mload(0x6460)) -mstore(0x6560, mload(0x64c0)) - mstore(0x6580, mload(0x64e0)) -success := and(eq(staticcall(gas(), 0x6, 0x6520, 0x80, 0x6520, 0x40), 1), success) -mstore(0x65a0, 0x17673d964bba991cd9f7123a60974ae516d735782681f1bcf85525118169af09) - mstore(0x65c0, 0x14712178638d0d8c6dc8ecbd161248d5bc0d71170a07c898016ca406490b6b71) -mstore(0x65e0, mload(0x55a0)) -success := and(eq(staticcall(gas(), 0x7, 0x65a0, 0x60, 0x65a0, 0x40), 1), success) -mstore(0x6600, mload(0x6520)) - mstore(0x6620, mload(0x6540)) -mstore(0x6640, mload(0x65a0)) - mstore(0x6660, mload(0x65c0)) -success := and(eq(staticcall(gas(), 0x6, 0x6600, 0x80, 0x6600, 0x40), 1), success) -mstore(0x6680, 0x1b7009f9bfcc229095c008736391bfbdd7f55e2b498d80bfd86de439dc96b2d1) - mstore(0x66a0, 0x261f3c8b993a70207145375e60440f4d3f12d97ac71f7c7a4450f6b63400078e) -mstore(0x66c0, mload(0x55c0)) -success := and(eq(staticcall(gas(), 0x7, 0x6680, 0x60, 0x6680, 0x40), 1), success) -mstore(0x66e0, mload(0x6600)) - mstore(0x6700, mload(0x6620)) -mstore(0x6720, mload(0x6680)) - mstore(0x6740, mload(0x66a0)) -success := and(eq(staticcall(gas(), 0x6, 0x66e0, 0x80, 0x66e0, 0x40), 1), success) -mstore(0x6760, 0x170c45ec706e6d8fda4c2a57babee9641e9cf06a8af3b5962b63ed8c247875e8) - mstore(0x6780, 0x25ed6f00d2f19fcdcf6c24a1893e9e28d7b6609e5aa83a942e6ef7a890c9ee3b) -mstore(0x67a0, mload(0x55e0)) -success := and(eq(staticcall(gas(), 0x7, 0x6760, 0x60, 0x6760, 0x40), 1), success) -mstore(0x67c0, mload(0x66e0)) - mstore(0x67e0, mload(0x6700)) -mstore(0x6800, mload(0x6760)) - mstore(0x6820, mload(0x6780)) -success := and(eq(staticcall(gas(), 0x6, 0x67c0, 0x80, 0x67c0, 0x40), 1), success) -mstore(0x6840, 0x1b5204f04e4952483afb2a2f3d1d3297b1ca3ca70a417634a77f912fcf933a2b) - mstore(0x6860, 0x290c7867a14ba34b08dc1a4028311e9eec1efafd25489dd058d4407cd9f40fec) -mstore(0x6880, mload(0x5600)) -success := and(eq(staticcall(gas(), 0x7, 0x6840, 0x60, 0x6840, 0x40), 1), success) -mstore(0x68a0, mload(0x67c0)) - mstore(0x68c0, mload(0x67e0)) -mstore(0x68e0, mload(0x6840)) - mstore(0x6900, mload(0x6860)) -success := and(eq(staticcall(gas(), 0x6, 0x68a0, 0x80, 0x68a0, 0x40), 1), success) -mstore(0x6920, 0x199df78c2d44e9ba230348c70643c500bd81ea0eca68d98a31b95f12feab26de) - mstore(0x6940, 0x0ae906a97fd1ccc673ced029ee3e17912704473bfb71187c0a64dd7015097c4a) -mstore(0x6960, mload(0x5620)) -success := and(eq(staticcall(gas(), 0x7, 0x6920, 0x60, 0x6920, 0x40), 1), success) -mstore(0x6980, mload(0x68a0)) - mstore(0x69a0, mload(0x68c0)) -mstore(0x69c0, mload(0x6920)) - mstore(0x69e0, mload(0x6940)) -success := and(eq(staticcall(gas(), 0x6, 0x6980, 0x80, 0x6980, 0x40), 1), success) -mstore(0x6a00, 0x2924fd6012cfbf12e7a769122b598ed14236b543e1352db08f02e58c1c8751dc) - mstore(0x6a20, 0x01e10dc4803e0ef9b013cb75916337c9571d162fd554d4a624a129325df75a20) -mstore(0x6a40, mload(0x5640)) -success := and(eq(staticcall(gas(), 0x7, 0x6a00, 0x60, 0x6a00, 0x40), 1), success) -mstore(0x6a60, mload(0x6980)) - mstore(0x6a80, mload(0x69a0)) -mstore(0x6aa0, mload(0x6a00)) - mstore(0x6ac0, mload(0x6a20)) -success := and(eq(staticcall(gas(), 0x6, 0x6a60, 0x80, 0x6a60, 0x40), 1), success) -mstore(0x6ae0, 0x289e679960ac748a0d0162edc9cf29a2197ba3228f7eeae2607f2cee1292ef6e) - mstore(0x6b00, 0x0579c30989e2837fae47810cb481148f43fc62d199c9ca11c45cc8faf224e0bb) -mstore(0x6b20, mload(0x5660)) -success := and(eq(staticcall(gas(), 0x7, 0x6ae0, 0x60, 0x6ae0, 0x40), 1), success) -mstore(0x6b40, mload(0x6a60)) - mstore(0x6b60, mload(0x6a80)) -mstore(0x6b80, mload(0x6ae0)) - mstore(0x6ba0, mload(0x6b00)) -success := and(eq(staticcall(gas(), 0x6, 0x6b40, 0x80, 0x6b40, 0x40), 1), success) -mstore(0x6bc0, 0x2ef01c47be895ace6beda088564385a5e22c4d3fd4a023503d26522484a4293f) - mstore(0x6be0, 0x033861e1de5c24e8b56a26837fcc2a263634f98a403e495076ce5b8be4ccdaec) -mstore(0x6c00, mload(0x5680)) -success := and(eq(staticcall(gas(), 0x7, 0x6bc0, 0x60, 0x6bc0, 0x40), 1), success) -mstore(0x6c20, mload(0x6b40)) - mstore(0x6c40, mload(0x6b60)) -mstore(0x6c60, mload(0x6bc0)) - mstore(0x6c80, mload(0x6be0)) -success := and(eq(staticcall(gas(), 0x6, 0x6c20, 0x80, 0x6c20, 0x40), 1), success) -mstore(0x6ca0, 0x15947a382b2701ac4136c492df8aeff8900344ab18a944ae3167f73cee9ea03d) - mstore(0x6cc0, 0x0767f0ea068278158a8f78401911df09259a0b487ec1f5a7a149778826f6e1ca) -mstore(0x6ce0, mload(0x56a0)) -success := and(eq(staticcall(gas(), 0x7, 0x6ca0, 0x60, 0x6ca0, 0x40), 1), success) -mstore(0x6d00, mload(0x6c20)) - mstore(0x6d20, mload(0x6c40)) -mstore(0x6d40, mload(0x6ca0)) - mstore(0x6d60, mload(0x6cc0)) -success := and(eq(staticcall(gas(), 0x6, 0x6d00, 0x80, 0x6d00, 0x40), 1), success) -mstore(0x6d80, 0x03ff9449e27d073bebd5c97daf8a77154716775a680c4d4f1543ebbab2bc755c) - mstore(0x6da0, 0x12b22c46b8bf8dd4d9b6ae892fc5898aab4ec95c79eaf819e46a0a76ad68f110) -mstore(0x6dc0, mload(0x56c0)) -success := and(eq(staticcall(gas(), 0x7, 0x6d80, 0x60, 0x6d80, 0x40), 1), success) -mstore(0x6de0, mload(0x6d00)) - mstore(0x6e00, mload(0x6d20)) -mstore(0x6e20, mload(0x6d80)) - mstore(0x6e40, mload(0x6da0)) -success := and(eq(staticcall(gas(), 0x6, 0x6de0, 0x80, 0x6de0, 0x40), 1), success) -mstore(0x6e60, 0x01b7bf732e433a000c73ed1e93ace24bab29943a036f4be73011bd8c658f961c) - mstore(0x6e80, 0x2a36fc7e0044a80add8a5d2b75138bd9ae6fca74caf310fbf3dcf538819e8b43) -mstore(0x6ea0, mload(0x56e0)) -success := and(eq(staticcall(gas(), 0x7, 0x6e60, 0x60, 0x6e60, 0x40), 1), success) -mstore(0x6ec0, mload(0x6de0)) - mstore(0x6ee0, mload(0x6e00)) -mstore(0x6f00, mload(0x6e60)) - mstore(0x6f20, mload(0x6e80)) -success := and(eq(staticcall(gas(), 0x6, 0x6ec0, 0x80, 0x6ec0, 0x40), 1), success) -mstore(0x6f40, 0x16b4687b4ad49ecbb4973fda24d4c201854ca101aaca9b69b60a96bb25fc4f87) - mstore(0x6f60, 0x0e56bffce506ddd260c0dc7c40a9e96343328d7c606ec103b28c5017efbae720) -mstore(0x6f80, mload(0x5700)) -success := and(eq(staticcall(gas(), 0x7, 0x6f40, 0x60, 0x6f40, 0x40), 1), success) -mstore(0x6fa0, mload(0x6ec0)) - mstore(0x6fc0, mload(0x6ee0)) -mstore(0x6fe0, mload(0x6f40)) - mstore(0x7000, mload(0x6f60)) -success := and(eq(staticcall(gas(), 0x6, 0x6fa0, 0x80, 0x6fa0, 0x40), 1), success) -mstore(0x7020, 0x0c1824efd938f810b1ec9b455b6fce7dedf96e18bad57241de1b35d820285f32) - mstore(0x7040, 0x23b2fdeaeeebb400d3f1dcee64d7296403672cf36ee453e82c3d5d90acdc739a) -mstore(0x7060, mload(0x5720)) -success := and(eq(staticcall(gas(), 0x7, 0x7020, 0x60, 0x7020, 0x40), 1), success) -mstore(0x7080, mload(0x6fa0)) - mstore(0x70a0, mload(0x6fc0)) -mstore(0x70c0, mload(0x7020)) - mstore(0x70e0, mload(0x7040)) -success := and(eq(staticcall(gas(), 0x6, 0x7080, 0x80, 0x7080, 0x40), 1), success) -mstore(0x7100, 0x0ec6d72e2ce7c233ca8af2fc2bd4223a6d81d545e8785579de4cb241740f36a2) - mstore(0x7120, 0x028a4450999577e25fc7d191fecf7f1a8a0526f7e042f316767c7ff43299fdd9) -mstore(0x7140, mload(0x5740)) -success := and(eq(staticcall(gas(), 0x7, 0x7100, 0x60, 0x7100, 0x40), 1), success) -mstore(0x7160, mload(0x7080)) - mstore(0x7180, mload(0x70a0)) -mstore(0x71a0, mload(0x7100)) - mstore(0x71c0, mload(0x7120)) -success := and(eq(staticcall(gas(), 0x6, 0x7160, 0x80, 0x7160, 0x40), 1), success) -mstore(0x71e0, 0x26d8b7b13f52340b2e122f12d279deccb9cec2319ec4371d28ef1455e8acce48) - mstore(0x7200, 0x0b69e5f1edd7a5ebb8b3d29122b6b2ae59dc5cc3fcc18a672cd2bad60357db4f) -mstore(0x7220, mload(0x5760)) -success := and(eq(staticcall(gas(), 0x7, 0x71e0, 0x60, 0x71e0, 0x40), 1), success) -mstore(0x7240, mload(0x7160)) - mstore(0x7260, mload(0x7180)) -mstore(0x7280, mload(0x71e0)) - mstore(0x72a0, mload(0x7200)) -success := and(eq(staticcall(gas(), 0x6, 0x7240, 0x80, 0x7240, 0x40), 1), success) -mstore(0x72c0, mload(0x4a0)) - mstore(0x72e0, mload(0x4c0)) -mstore(0x7300, mload(0x5780)) -success := and(eq(staticcall(gas(), 0x7, 0x72c0, 0x60, 0x72c0, 0x40), 1), success) -mstore(0x7320, mload(0x7240)) - mstore(0x7340, mload(0x7260)) -mstore(0x7360, mload(0x72c0)) - mstore(0x7380, mload(0x72e0)) -success := and(eq(staticcall(gas(), 0x6, 0x7320, 0x80, 0x7320, 0x40), 1), success) -mstore(0x73a0, mload(0x4e0)) - mstore(0x73c0, mload(0x500)) -mstore(0x73e0, mload(0x57a0)) -success := and(eq(staticcall(gas(), 0x7, 0x73a0, 0x60, 0x73a0, 0x40), 1), success) -mstore(0x7400, mload(0x7320)) - mstore(0x7420, mload(0x7340)) -mstore(0x7440, mload(0x73a0)) - mstore(0x7460, mload(0x73c0)) -success := and(eq(staticcall(gas(), 0x6, 0x7400, 0x80, 0x7400, 0x40), 1), success) -mstore(0x7480, mload(0x520)) - mstore(0x74a0, mload(0x540)) -mstore(0x74c0, mload(0x57c0)) -success := and(eq(staticcall(gas(), 0x7, 0x7480, 0x60, 0x7480, 0x40), 1), success) -mstore(0x74e0, mload(0x7400)) - mstore(0x7500, mload(0x7420)) -mstore(0x7520, mload(0x7480)) - mstore(0x7540, mload(0x74a0)) -success := and(eq(staticcall(gas(), 0x6, 0x74e0, 0x80, 0x74e0, 0x40), 1), success) -mstore(0x7560, mload(0x560)) - mstore(0x7580, mload(0x580)) -mstore(0x75a0, mload(0x57e0)) -success := and(eq(staticcall(gas(), 0x7, 0x7560, 0x60, 0x7560, 0x40), 1), success) -mstore(0x75c0, mload(0x74e0)) - mstore(0x75e0, mload(0x7500)) -mstore(0x7600, mload(0x7560)) - mstore(0x7620, mload(0x7580)) -success := and(eq(staticcall(gas(), 0x6, 0x75c0, 0x80, 0x75c0, 0x40), 1), success) -mstore(0x7640, mload(0x5a0)) - mstore(0x7660, mload(0x5c0)) -mstore(0x7680, mload(0x5800)) -success := and(eq(staticcall(gas(), 0x7, 0x7640, 0x60, 0x7640, 0x40), 1), success) -mstore(0x76a0, mload(0x75c0)) - mstore(0x76c0, mload(0x75e0)) -mstore(0x76e0, mload(0x7640)) - mstore(0x7700, mload(0x7660)) -success := and(eq(staticcall(gas(), 0x6, 0x76a0, 0x80, 0x76a0, 0x40), 1), success) -mstore(0x7720, mload(0x400)) - mstore(0x7740, mload(0x420)) -mstore(0x7760, mload(0x5820)) -success := and(eq(staticcall(gas(), 0x7, 0x7720, 0x60, 0x7720, 0x40), 1), success) -mstore(0x7780, mload(0x76a0)) - mstore(0x77a0, mload(0x76c0)) -mstore(0x77c0, mload(0x7720)) - mstore(0x77e0, mload(0x7740)) -success := and(eq(staticcall(gas(), 0x6, 0x7780, 0x80, 0x7780, 0x40), 1), success) -mstore(0x7800, mload(0x120)) - mstore(0x7820, mload(0x140)) -mstore(0x7840, mload(0x5a40)) -success := and(eq(staticcall(gas(), 0x7, 0x7800, 0x60, 0x7800, 0x40), 1), success) -mstore(0x7860, mload(0x7780)) - mstore(0x7880, mload(0x77a0)) -mstore(0x78a0, mload(0x7800)) - mstore(0x78c0, mload(0x7820)) -success := and(eq(staticcall(gas(), 0x6, 0x7860, 0x80, 0x7860, 0x40), 1), success) -mstore(0x78e0, mload(0x160)) - mstore(0x7900, mload(0x180)) -mstore(0x7920, mload(0x5a60)) -success := and(eq(staticcall(gas(), 0x7, 0x78e0, 0x60, 0x78e0, 0x40), 1), success) -mstore(0x7940, mload(0x7860)) - mstore(0x7960, mload(0x7880)) -mstore(0x7980, mload(0x78e0)) - mstore(0x79a0, mload(0x7900)) -success := and(eq(staticcall(gas(), 0x6, 0x7940, 0x80, 0x7940, 0x40), 1), success) -mstore(0x79c0, mload(0x1a0)) - mstore(0x79e0, mload(0x1c0)) -mstore(0x7a00, mload(0x5a80)) -success := and(eq(staticcall(gas(), 0x7, 0x79c0, 0x60, 0x79c0, 0x40), 1), success) -mstore(0x7a20, mload(0x7940)) - mstore(0x7a40, mload(0x7960)) -mstore(0x7a60, mload(0x79c0)) - mstore(0x7a80, mload(0x79e0)) -success := and(eq(staticcall(gas(), 0x6, 0x7a20, 0x80, 0x7a20, 0x40), 1), success) -mstore(0x7aa0, mload(0x340)) - mstore(0x7ac0, mload(0x360)) -mstore(0x7ae0, mload(0x5c20)) -success := and(eq(staticcall(gas(), 0x7, 0x7aa0, 0x60, 0x7aa0, 0x40), 1), success) -mstore(0x7b00, mload(0x7a20)) - mstore(0x7b20, mload(0x7a40)) -mstore(0x7b40, mload(0x7aa0)) - mstore(0x7b60, mload(0x7ac0)) -success := and(eq(staticcall(gas(), 0x6, 0x7b00, 0x80, 0x7b00, 0x40), 1), success) -mstore(0x7b80, mload(0x380)) - mstore(0x7ba0, mload(0x3a0)) -mstore(0x7bc0, mload(0x5c40)) -success := and(eq(staticcall(gas(), 0x7, 0x7b80, 0x60, 0x7b80, 0x40), 1), success) -mstore(0x7be0, mload(0x7b00)) - mstore(0x7c00, mload(0x7b20)) -mstore(0x7c20, mload(0x7b80)) - mstore(0x7c40, mload(0x7ba0)) -success := and(eq(staticcall(gas(), 0x6, 0x7be0, 0x80, 0x7be0, 0x40), 1), success) -mstore(0x7c60, mload(0x3c0)) - mstore(0x7c80, mload(0x3e0)) -mstore(0x7ca0, mload(0x5d40)) -success := and(eq(staticcall(gas(), 0x7, 0x7c60, 0x60, 0x7c60, 0x40), 1), success) -mstore(0x7cc0, mload(0x7be0)) - mstore(0x7ce0, mload(0x7c00)) -mstore(0x7d00, mload(0x7c60)) - mstore(0x7d20, mload(0x7c80)) -success := and(eq(staticcall(gas(), 0x6, 0x7cc0, 0x80, 0x7cc0, 0x40), 1), success) -mstore(0x7d40, mload(0xc40)) - mstore(0x7d60, mload(0xc60)) -mstore(0x7d80, sub(f_q, mload(0x5d80))) -success := and(eq(staticcall(gas(), 0x7, 0x7d40, 0x60, 0x7d40, 0x40), 1), success) -mstore(0x7da0, mload(0x7cc0)) - mstore(0x7dc0, mload(0x7ce0)) -mstore(0x7de0, mload(0x7d40)) - mstore(0x7e00, mload(0x7d60)) -success := and(eq(staticcall(gas(), 0x6, 0x7da0, 0x80, 0x7da0, 0x40), 1), success) -mstore(0x7e20, mload(0xce0)) - mstore(0x7e40, mload(0xd00)) -mstore(0x7e60, mload(0x5da0)) -success := and(eq(staticcall(gas(), 0x7, 0x7e20, 0x60, 0x7e20, 0x40), 1), success) -mstore(0x7e80, mload(0x7da0)) - mstore(0x7ea0, mload(0x7dc0)) -mstore(0x7ec0, mload(0x7e20)) - mstore(0x7ee0, mload(0x7e40)) -success := and(eq(staticcall(gas(), 0x6, 0x7e80, 0x80, 0x7e80, 0x40), 1), success) -mstore(0x7f00, mload(0x7e80)) - mstore(0x7f20, mload(0x7ea0)) -mstore(0x7f40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) - mstore(0x7f60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x7f80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0x7fa0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) -mstore(0x7fc0, mload(0xce0)) - mstore(0x7fe0, mload(0xd00)) -mstore(0x8000, 0x0181624e80f3d6ae28df7e01eaeab1c0e919877a3b8a6b7fbc69a6817d596ea2) - mstore(0x8020, 0x1783d30dcb12d259bb89098addf6280fa4b653be7a152542a28f7b926e27e648) - mstore(0x8040, 0x00ae44489d41a0d179e2dfdc03bddd883b7109f8b6ae316a59e815c1a6b35304) - mstore(0x8060, 0x0b2147ab62a386bd63e6de1522109b8c9588ab466f5aadfde8c41ca3749423ee) -success := and(eq(staticcall(gas(), 0x8, 0x7f00, 0x180, 0x7f00, 0x20), 1), success) -success := and(eq(mload(0x7f00), 1), success) - - if not(success) { revert(0, 0) } - return(0, 0) - - } - } - } \ No newline at end of file diff --git a/pkg/zk-circuits/src/burn_to/circuit.rs b/pkg/zk-circuits/src/burn_to/circuit.rs deleted file mode 100644 index 950b6cc..0000000 --- a/pkg/zk-circuits/src/burn_to/circuit.rs +++ /dev/null @@ -1,97 +0,0 @@ -use crate::{ - chips::{ - is_constant::{IsConstantChip, IsConstantConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, - }, - data::BurnTo, -}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct BurnCircuitConfig { - advices: [Column; 5], - instance: Column, - poseidon_config: PoseidonConfig, - is_zero_config: IsConstantConfig, - swap_config: CondSwapConfig, -} - -impl Circuit for BurnTo { - type FloorPlanner = SimpleFloorPlanner; - type Config = BurnCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Is zero chip - let is_zero_config = - IsConstantChip::configure(meta, advices[0], advices[1], advices[2], Fr::zero()); - - BurnCircuitConfig { - advices, - instance, - poseidon_config, - is_zero_config, - swap_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - self.enforce_constraints( - layouter.namespace(|| "mint"), - config.instance, - config.advices[0], - config.poseidon_config, - IsConstantChip::construct(config.is_zero_config), - CondSwapChip::construct(config.swap_config), - )?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/burn_to/mod.rs b/pkg/zk-circuits/src/burn_to/mod.rs deleted file mode 100644 index ca1b221..0000000 --- a/pkg/zk-circuits/src/burn_to/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[allow(clippy::module_inception)] -mod burn; -mod circuit; -#[cfg(test)] -mod tests; - diff --git a/pkg/zk-circuits/src/burn_to/tests.rs b/pkg/zk-circuits/src/burn_to/tests.rs deleted file mode 100644 index 70a9f28..0000000 --- a/pkg/zk-circuits/src/burn_to/tests.rs +++ /dev/null @@ -1,54 +0,0 @@ -use crate::data::{BurnTo, ParameterSet}; -use crate::evm_verifier; -use crate::test::{rollup::Rollup, util::get_params}; -use crate::util::keygen_from_params; -use halo2_base::halo2_proofs::dev::MockProver; -use halo2_base::halo2_proofs::halo2curves::bn256::Fr; -use smirk::Element; - -#[test] -fn test_burn_proof() { - let k = 9; - - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - - let bob_note = rollup.unverified_add_unspent_note(&bob, 100); - - let circuit = { - let notes = [bob_note.note()]; - let secret_key = Element::ONE; - let to_address = Element::ONE; - BurnTo { - notes, - secret_key, - to_address, - kind: Element::default(), - } - }; - let instance_columns = vec![circuit.public_inputs()]; - - // Prove mockw - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - - // Prove for real circuit - let (params, _, pk) = get_params(k, &circuit); - circuit - .prove(¶ms, &pk, &mut rand::thread_rng()) - .unwrap(); -} - -#[test] -fn generate_verifier() { - let params_9 = ParameterSet::Nine; - - let circuit = BurnTo::<1>::default(); - - let (pk, _) = keygen_from_params(params_9, &circuit); - let yul_code = - evm_verifier::generate_verifier(params_9, &pk, vec![circuit.public_inputs().len()]); - - let expected_yul_code = expect_test::expect_file!["./burn_to_verifier.yul"]; - expected_yul_code.assert_eq(&yul_code); -} diff --git a/pkg/zk-circuits/src/chips/add.rs b/pkg/zk-circuits/src/chips/add.rs deleted file mode 100644 index 86c629e..0000000 --- a/pkg/zk-circuits/src/chips/add.rs +++ /dev/null @@ -1,97 +0,0 @@ -use halo2_base::halo2_proofs::{ - arithmetic::Field, - circuit::{AssignedCell, Layouter, Value}, - plonk::{Advice, Column, ConstraintSystem, Error, Selector}, - poly::Rotation, -}; -use std::marker::PhantomData; - -#[derive(Debug, Clone)] -pub struct AddCulmChipConfig { - selector: Selector, - culm: Column, - add: Column, -} - -#[derive(Debug, Clone)] -pub struct AddCulmChip { - config: AddCulmChipConfig, - _marker: PhantomData, -} - -impl AddCulmChip { - pub fn configure( - meta: &mut ConstraintSystem, - add: Column, - culm: Column, - ) -> AddCulmChipConfig { - let selector = meta.selector(); - - meta.create_gate("Sum", |meta| { - let s = meta.query_selector(selector); - let a = meta.query_advice(culm, Rotation::prev()); - let b = meta.query_advice(add, Rotation::cur()); - let c = meta.query_advice(culm, Rotation::cur()); - - // add | culm | selector - // | a | - // b | c | 1 - - vec![s * (a + b - c)] - }); - - AddCulmChipConfig { - selector, - culm, - add, - } - } - - pub fn construct(config: AddCulmChipConfig) -> Self { - Self { - _marker: PhantomData, - config, - } - } - - pub fn assign( - &self, - mut layouter: impl Layouter, - cells: &[AssignedCell], - ) -> Result, Error> { - layouter.assign_region( - || "add chip", - |mut region| { - let first = &cells[0]; - - let mut culm = - first.copy_advice(|| "first culm", &mut region, self.config.culm, 0)?; - - for (i, cell) in cells[1..].iter().enumerate() { - let offset = i + 1; - - // Enable the selector, so we constrain the new culm value - self.config.selector.enable(&mut region, offset)?; - - // Copy in the value to be added - let b = cell.copy_advice(|| "add", &mut region, self.config.add, offset)?; - - // Add the expected value - culm = region.assign_advice( - || "new culm", - self.config.culm, - offset, - || { - culm.value().and_then(|culm_val| { - b.value().and_then(|b_val| Value::known(*culm_val + *b_val)) - }) - }, - )? - } - - // Return the final calculated value - Ok(culm) - }, - ) - } -} diff --git a/pkg/zk-circuits/src/chips/aggregation/aggregate.rs b/pkg/zk-circuits/src/chips/aggregation/aggregate.rs deleted file mode 100644 index 5df7dd4..0000000 --- a/pkg/zk-circuits/src/chips/aggregation/aggregate.rs +++ /dev/null @@ -1,463 +0,0 @@ -use super::snark::Snark; -use halo2_base::halo2_proofs::halo2curves::bn256::{Fq, Fr, G1Affine}; -use halo2_base::halo2_proofs::plonk::Error; -use halo2_base::halo2_proofs::{ - circuit::{Cell, Layouter, Value}, - plonk::ConstraintSystem, -}; - -use super::constants::{BITS, LIMBS}; -use super::types::{As, Halo2Loader, Plonk, PoseidonTranscript, SnarkInstanceColumnCells}; - -use halo2_base::{Context, ContextParams}; -use halo2_ecc::ecc::EccChip; -use itertools::Itertools; -use rand::rngs::OsRng; -use snark_verifier::{ - loader::native::NativeLoader, - pcs::{kzg::KzgAccumulator, AccumulationScheme, AccumulationSchemeProver}, - util::arithmetic::fe_to_limbs, - verifier::PlonkVerifier, -}; -use std::rc::Rc; - -#[derive(Clone)] -pub struct AggregationChipConfigParams { - pub strategy: halo2_ecc::fields::fp::FpStrategy, - pub degree: u32, - pub num_advice: usize, - pub num_lookup_advice: usize, - pub num_fixed: usize, - pub lookup_bits: usize, - pub limb_bits: usize, - pub num_limbs: usize, -} - -#[derive(Clone, Debug)] -pub struct AggregationChipConfig { - pub base_field_config: halo2_ecc::fields::fp::FpConfig, -} - -impl AggregationChipConfig { - pub fn configure(meta: &mut ConstraintSystem, params: AggregationChipConfigParams) -> Self { - assert!( - params.limb_bits == BITS && params.num_limbs == LIMBS, - "For now we fix limb_bits = {BITS}, otherwise change code" - ); - - let base_field_config = halo2_ecc::fields::fp::FpConfig::configure( - meta, - params.strategy, - &[params.num_advice], - &[params.num_lookup_advice], - params.num_fixed, - params.lookup_bits, - params.limb_bits, - params.num_limbs, - halo2_base::utils::modulus::(), - 0, - params.degree as usize, - ); - - Self { base_field_config } - } - - pub fn range(&self) -> &halo2_base::gates::range::RangeConfig { - &self.base_field_config.range - } - - pub fn ecc_chip(&self) -> halo2_ecc::ecc::BaseFieldEccChip { - EccChip::construct(self.base_field_config.clone()) - } -} - -#[derive(Clone)] -pub struct AggregationChip { - config: AggregationChipConfig, -} - -impl AggregationChip { - pub fn construct(config: AggregationChipConfig) -> Self { - Self { config } - } - - pub fn configure( - meta: &mut ConstraintSystem, - params: AggregationChipConfigParams, - ) -> AggregationChipConfig { - AggregationChipConfig::configure(meta, params) - } - - pub fn aggregate( - &self, - mut layouter: impl Layouter, - snarks: &[&Snark], - as_proof: Value<&[u8]>, - ) -> Result<(Vec, Vec>), Error> { - self.config.range().load_lookup_table(&mut layouter)?; - let max_rows = self.config.range().gate.max_rows; - - layouter.assign_region( - || "", - |region| { - let ctx = Context::new( - region, - ContextParams { - max_rows, - num_context_ids: 1, - fixed_columns: self.config.base_field_config.range.gate.constants.clone(), - }, - ); - - let ecc_chip = self.config.ecc_chip(); - let loader = Halo2Loader::new(ecc_chip, ctx); - let (KzgAccumulator { lhs, rhs }, instances) = - accumulator_ecc(&loader, snarks, as_proof); - - let lhs = lhs.assigned(); - let rhs = rhs.assigned(); - - self.config - .base_field_config - .finalize(&mut loader.ctx_mut()); - - let agg_instances: Vec<_> = lhs - .x - .truncation - .limbs - .iter() - .chain(lhs.y.truncation.limbs.iter()) - .chain(rhs.x.truncation.limbs.iter()) - .chain(rhs.y.truncation.limbs.iter()) - .map(|assigned| assigned.cell()) - .collect(); - - Ok((agg_instances, instances)) - }, - ) - } - - pub fn num_instance() -> Vec { - // [..lhs, ..rhs] - vec![4 * LIMBS] - } - - pub fn accumulator_indices() -> Vec<(usize, usize)> { - (0..4 * LIMBS).map(|idx| (0, idx)).collect() - } -} - -pub fn accumulator_native(snarks: &[&Snark]) -> (Vec, Vec) { - let accumulators = snarks - .iter() - .flat_map(|snark| { - let mut transcript = PoseidonTranscript::::new(snark.proof.as_slice()); - let proof = Plonk::read_proof( - &snark.svk, - &snark.protocol, - &snark.instances, - &mut transcript, - ); - Plonk::succinct_verify(&snark.svk, &snark.protocol, &snark.instances, &proof) - }) - .collect_vec(); - - let (accumulator, as_proof) = { - let mut transcript = PoseidonTranscript::::new(Vec::new()); - let accumulator = - As::create_proof(&Default::default(), &accumulators, &mut transcript, OsRng).unwrap(); - (accumulator, transcript.finalize()) - }; - let KzgAccumulator { lhs, rhs } = accumulator; - let instances = [lhs.x, lhs.y, rhs.x, rhs.y] - .map(fe_to_limbs::<_, _, LIMBS, BITS>) - .concat(); - - (instances, as_proof) -} - -pub fn accumulator_ecc<'a>( - loader: &Rc>, - snarks: &[&Snark], - as_proof: Value<&'_ [u8]>, -) -> ( - KzgAccumulator>>, - Vec>, -) { - let assign_instances = |instances: &[Vec]| { - instances - .iter() - .map(|instances| { - instances - .iter() - .map(|instance| loader.assign_scalar(Value::known(*instance))) - .collect_vec() - }) - .collect_vec() - }; - - let mut all_instances = vec![]; - - let accumulators = snarks - .iter() - .flat_map(|snark| { - let protocol = snark.protocol.loaded(loader); - let instances = assign_instances(&snark.instances); - - all_instances.push( - instances - .iter() - .map(|f| f.iter().map(|f| f.clone().assigned().cell()).collect_vec()) - .collect_vec(), - ); - - let mut transcript = - PoseidonTranscript::, _>::new(loader, snark.proof_value()); - let proof = Plonk::read_proof(&snark.svk, &protocol, &instances, &mut transcript); - Plonk::succinct_verify(&snark.svk, &protocol, &instances, &proof) - }) - .collect_vec(); - - let acccumulator = { - let mut transcript = PoseidonTranscript::, _>::new(loader, as_proof); - let proof = As::read_proof(&Default::default(), &accumulators, &mut transcript).unwrap(); - As::verify(&Default::default(), &accumulators, &proof).unwrap() - }; - - (acccumulator, all_instances) -} - -#[cfg(test)] -mod tests { - use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, - }; - - use crate::{ - chips::aggregation::snark::Snark, - test::util::{advice_column_equality, get_snark, instance_column_equality}, - util::assign_private_input, - }; - - use super::*; - - #[derive(Clone, Debug)] - pub struct BasicCircuitConfig { - instance: Column, - advice: Column, - } - - #[derive(Clone, Default, Debug)] - pub struct BasicCircuit { - input: Fr, - } - - impl Circuit for BasicCircuit { - type Config = BasicCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - BasicCircuitConfig { - instance: instance_column_equality(meta), - advice: advice_column_equality(meta), - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let input = assign_private_input( - || "assign input", - layouter.namespace(|| "assign input"), - config.advice, - Value::known(self.input), - )?; - - layouter.constrain_instance(input.cell(), config.instance, 0) - } - } - - #[derive(Clone, Default, Debug)] - pub struct BasicCircuit2 { - input1: Fr, - input2: Fr, - } - - impl Circuit for BasicCircuit2 { - type Config = BasicCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - BasicCircuitConfig { - instance: instance_column_equality(meta), - advice: advice_column_equality(meta), - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let input1 = assign_private_input( - || "assign input1", - layouter.namespace(|| "assign input1"), - config.advice, - Value::known(self.input1), - )?; - - let input2 = assign_private_input( - || "assign input2", - layouter.namespace(|| "assign input2"), - config.advice, - Value::known(self.input2), - )?; - - layouter.constrain_instance(input1.cell(), config.instance, 0)?; - layouter.constrain_instance(input2.cell(), config.instance, 1) - } - } - - #[derive(Clone)] - pub struct AggregationCircuitConfig { - aggregation_config: AggregationChipConfig, - instance: Column, - } - - #[derive(Clone)] - pub struct AggregationCircuit { - snarks: Vec, - agg_instances: Vec, - as_proof: Vec, - } - - impl AggregationCircuit { - pub fn new(snarks: Vec) -> Self { - let snarks_ref: Vec<&Snark> = snarks.iter().collect(); - let (instances, as_proof) = accumulator_native(&snarks_ref); - - AggregationCircuit { - snarks, - agg_instances: instances, - as_proof, - } - } - - pub fn instances(&self) -> Vec> { - // Instances to verify aggregation/recurssion part of the proof - let mut instances = self.agg_instances.clone(); - - // Verify original elements - let snark_instances = self - .snarks - .iter() - .flat_map(|s| s.instances.clone().into_iter().flatten().collect_vec()) - .collect_vec(); - - instances.extend(snark_instances); - - vec![instances] - } - } - - impl Circuit for AggregationCircuit { - type Config = AggregationCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - self.clone() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let params = AggregationChipConfigParams { - strategy: halo2_ecc::fields::fp::FpStrategy::Simple, - degree: 21, - num_advice: 6, - num_lookup_advice: 1, - num_fixed: 1, - lookup_bits: 20, - limb_bits: 88, - num_limbs: 3, - }; - - let instance = meta.instance_column(); - meta.enable_equality(instance); - - AggregationCircuitConfig { - aggregation_config: AggregationChipConfig::configure(meta, params), - instance, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let agg_chip = AggregationChip::construct(config.aggregation_config); - let snarks_ref: Vec<&Snark> = self.snarks.iter().collect(); - - // Expose instances - let (agg_instances, snark_instances) = agg_chip.aggregate( - layouter.namespace(|| "aggregate"), - &snarks_ref, - Value::known(&self.as_proof), - )?; - - // TODO: use less instances by following Scroll's strategy of keeping only last bit of y coordinate - let mut layouter = layouter.namespace(|| "expose"); - for (i, cell) in agg_instances - .into_iter() - .chain(snark_instances.into_iter().flatten().flatten()) - .enumerate() - { - layouter.constrain_instance(cell, config.instance, i)?; - } - - Ok(()) - } - } - - pub fn gen_application_snark(i: usize) -> Snark { - let circuit = BasicCircuit { - input: Fr::from(i as u64), - }; - get_snark(8, circuit, vec![Fr::from(i as u64)]).unwrap() - } - - #[test] - fn test_aggregation() { - let mut snarks = [(); 3] - .iter() - .enumerate() - .map(|(i, _)| gen_application_snark(i)) - .collect_vec(); - - // Test with two different circuits with different inputs/instances - let circuit = BasicCircuit2 { - input1: Fr::from(10), - input2: Fr::from(11), - }; - let alt_snark = get_snark(8, circuit, vec![Fr::from(10), Fr::from(11)]).unwrap(); - snarks.push(alt_snark); - - let agg_circuit = AggregationCircuit::new(snarks); - - let prover = MockProver::::run(21, &agg_circuit, agg_circuit.instances()).unwrap(); - prover.assert_satisfied(); - - println!("Success!"); - } -} diff --git a/pkg/zk-circuits/src/chips/aggregation/constants.rs b/pkg/zk-circuits/src/chips/aggregation/constants.rs deleted file mode 100644 index 7ac6895..0000000 --- a/pkg/zk-circuits/src/chips/aggregation/constants.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub const T: usize = 5; -pub const RATE: usize = 4; -pub const R_F: usize = 8; -pub const R_P: usize = 60; - -pub const LIMBS: usize = 3; -pub const BITS: usize = 88; diff --git a/pkg/zk-circuits/src/chips/aggregation/mod.rs b/pkg/zk-circuits/src/chips/aggregation/mod.rs deleted file mode 100644 index 795340e..0000000 --- a/pkg/zk-circuits/src/chips/aggregation/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod aggregate; -pub(crate) mod constants; -pub mod snark; -pub(crate) mod types; diff --git a/pkg/zk-circuits/src/chips/aggregation/snark.rs b/pkg/zk-circuits/src/chips/aggregation/snark.rs deleted file mode 100644 index 9643b86..0000000 --- a/pkg/zk-circuits/src/chips/aggregation/snark.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::{ - data::{ParameterSet, SnarkWitnessV1}, - params::load_params, -}; - -use super::types::{PoseidonTranscript, Svk}; -use halo2_base::halo2_proofs::{ - circuit::Value, - halo2curves::bn256::{Bn256, Fr, G1Affine}, - plonk::{create_proof, Circuit, Error, ProvingKey, VerifyingKey}, - poly::{ - commitment::ParamsProver, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::ProverSHPLONK, - }, - }, - transcript::TranscriptWriterBuffer, -}; -use itertools::Itertools; -use rand::rngs::OsRng; -use snark_verifier::{ - loader::native::NativeLoader, - pcs::kzg::KzgDecidingKey, - system::halo2::{compile, Config}, - Protocol, -}; - -#[derive(Clone, Debug)] -pub struct Snark { - pub protocol: Protocol, - // TODO: make instances fixed size/typed - pub instances: Vec>, - pub proof: Vec, - pub svk: Svk, - pub dk: KzgDecidingKey, -} - -impl Snark { - pub fn new( - protocol: Protocol, - instances: Vec>, - proof: Vec, - params: &ParamsKZG, - ) -> Self { - Self { - protocol, - instances, - proof, - svk: params.get_g()[0].into(), - dk: (params.g2(), params.s_g2()).into(), - } - } - - pub fn create>( - circuit: C, - instances: Vec>, - params: &ParamsKZG, - pk: &ProvingKey, - ) -> Result { - let num_instance = instances.iter().map(|v| v.len()).collect_vec(); - - let protocol = compile( - params, - pk.get_vk(), - Config::kzg().with_num_instance(num_instance), - ); - let slice = &instances - .iter() - .map(|instances| instances.as_slice()) - .collect_vec(); - - let proof = { - let mut transcript = PoseidonTranscript::::init(Vec::new()); - create_proof::, ProverSHPLONK<_>, _, _, _, _>( - params, - pk, - &[circuit], - &[slice.as_slice()], - OsRng, - &mut transcript, - ) - .unwrap(); - transcript.finalize() - }; - - Ok(Self::new(protocol, instances.clone(), proof, params)) - } - - pub fn from_witness( - witness: SnarkWitnessV1, - vk: &VerifyingKey, - params: ParameterSet, - ) -> Self { - let params = load_params(params); - - let num_instance = witness.instances.iter().map(|v| v.len()).collect_vec(); - // let vk = keygen_vk(params, circuit).expect("keygen_vk should not fail"); - let protocol = compile(params, vk, Config::kzg().with_num_instance(num_instance)); - - Self { - protocol, - instances: witness.fr_instances(), - proof: witness.proof, - svk: params.get_g()[0].into(), - dk: (params.g2(), params.s_g2()).into(), - } - } - - pub fn to_witness(&self) -> SnarkWitnessV1 { - SnarkWitnessV1::new( - self.instances - .iter() - .map(|v| v.iter().map(|v| (*v).into()).collect_vec()) - .collect_vec(), - self.proof.clone(), - ) - } - - pub fn proof(&self) -> &[u8] { - &self.proof - } - - pub fn proof_value(&self) -> Value<&[u8]> { - Value::known(&self.proof) - } -} diff --git a/pkg/zk-circuits/src/chips/aggregation/types.rs b/pkg/zk-circuits/src/chips/aggregation/types.rs deleted file mode 100644 index 916f999..0000000 --- a/pkg/zk-circuits/src/chips/aggregation/types.rs +++ /dev/null @@ -1,22 +0,0 @@ -use halo2_base::halo2_proofs::{ - circuit::Cell, - halo2curves::bn256::{Bn256, G1Affine}, -}; -use snark_verifier::{ - loader, - pcs::kzg::{Bdfg21, Kzg, KzgAs, KzgSuccinctVerifyingKey, LimbsEncoding}, - system, verifier, -}; - -use super::constants::{BITS, LIMBS, RATE, R_F, R_P, T}; - -pub type Svk = KzgSuccinctVerifyingKey; -pub type PoseidonTranscript = - system::halo2::transcript::halo2::PoseidonTranscript; - -pub type Pcs = Kzg; -pub type As = KzgAs; -pub type Plonk = verifier::Plonk>; -pub type BaseFieldEccChip = halo2_ecc::ecc::BaseFieldEccChip; -pub type Halo2Loader<'a> = loader::halo2::Halo2Loader<'a, G1Affine, BaseFieldEccChip>; -pub type SnarkInstanceColumnCells = Vec; diff --git a/pkg/zk-circuits/src/chips/binary_decomposition.rs b/pkg/zk-circuits/src/chips/binary_decomposition.rs deleted file mode 100644 index 6ff64dd..0000000 --- a/pkg/zk-circuits/src/chips/binary_decomposition.rs +++ /dev/null @@ -1,383 +0,0 @@ -//! Decomposes an $n$-bit field element $\alpha$ into $W$ windows, each window -//! being a $K$-bit word, using a running sum $z$. -//! We constrain $K \leq 3$ for this helper. -//! $$\alpha = k_0 + (2^K) k_1 + (2^{2K}) k_2 + ... + (2^{(W-1)K}) k_{W-1}$$ -//! -//! $z_0$ is initialized as $\alpha$. Each successive $z_{i+1}$ is computed as -//! $$z_{i+1} = (z_{i} - k_i) / (2^K).$$ -//! $z_W$ is constrained to be zero. -//! The difference between each interstitial running sum output is constrained -//! to be $K$ bits, i.e. -//! `range_check`($k_i$, $2^K$), -//! where -//! ```text -//! range_check(word, range) -//! = word * (1 - word) * (2 - word) * ... * ((range - 1) - word) -//! ``` -//! -//! Given that the `range_check` constraint will be toggled by a selector, in -//! practice we will have a `selector * range_check(word, range)` expression -//! of degree `range + 1`. -//! -//! This means that $2^K$ has to be at most `degree_bound - 1` in order for -//! the range check constraint to stay within the degree bound. - -// use ff::PrimeFieldBits; -use halo2_base::halo2_proofs::{ - circuit::{AssignedCell, Region, Value}, - halo2curves::FieldExt, - plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, - poly::Rotation, -}; -use std::marker::PhantomData; - -use crate::fr::PrimeFieldBits; - -/// Check that an expression is in the small range [0..range), -/// i.e. 0 ≤ word < range. -pub fn range_check(word: Expression, range: usize) -> Expression { - (1..range).fold(word.clone(), |acc, i| { - acc * (Expression::Constant(F::from(i as u64)) - word.clone()) - }) -} - -pub fn decompose_word( - word: &F, - word_num_bits: usize, - window_num_bits: usize, -) -> Vec { - assert!(window_num_bits <= 8); - - // Pad bits to multiple of window_num_bits - let padding = (window_num_bits - (word_num_bits % window_num_bits)) % window_num_bits; - let bits: Vec = word - .to_le_bits() - .into_iter() - .take(word_num_bits) - .chain(std::iter::repeat(false).take(padding)) - .collect(); - assert_eq!(bits.len(), word_num_bits + padding); - - bits.chunks_exact(window_num_bits) - .map(|chunk| chunk.iter().rev().fold(0, |acc, b| (acc << 1) + (*b as u8))) - .collect() -} - -/// The running sum $[z_0, ..., z_W]$. If created in strict mode, $z_W = 0$. -#[derive(Debug)] -pub struct BinaryDecomposition(pub(crate) Vec>); -impl std::ops::Deref for BinaryDecomposition { - type Target = Vec>; - - fn deref(&self) -> &Vec> { - &self.0 - } -} - -/// Configuration that provides methods for running sum decomposition. -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub struct BinaryDecompositionConfig { - q_range_check: Selector, - z: Column, - b: Column, - _marker: PhantomData, -} - -impl - BinaryDecompositionConfig -{ - /// `perm` MUST include the advice column `z`. - /// - /// # Panics - /// - /// Panics if WINDOW_NUM_BITS > 3. - /// - /// # Side-effects - /// - /// `z` will be equality-enabled. - pub fn configure( - meta: &mut ConstraintSystem, - q_range_check: Selector, - z: Column, - b: Column, - ) -> Self { - assert!(WINDOW_NUM_BITS <= 3); - - meta.enable_equality(z); - - let config = Self { - q_range_check, - z, - b, - _marker: PhantomData, - }; - - // https://p.z.cash/halo2-0.1:decompose-short-range - meta.create_gate("range check", |meta| { - let q_range_check = meta.query_selector(config.q_range_check); - let z_cur = meta.query_advice(config.z, Rotation::cur()); - let z_next = meta.query_advice(config.z, Rotation::next()); - let b = meta.query_advice(b, Rotation::cur()); - // z_i = 2^{K}⋅z_{i + 1} + k_i - // => k_i = z_i - 2^{K}⋅z_{i + 1} - let word = z_cur - z_next * F::from(1 << WINDOW_NUM_BITS); - - Constraints::with_selector( - q_range_check, - [range_check(word.clone(), 1 << WINDOW_NUM_BITS), b - word], - ) - }); - - config - } - - /// Decompose a field element alpha that is witnessed in this helper. - /// - /// `strict` = true constrains the final running sum to be zero, i.e. - /// constrains alpha to be within WINDOW_NUM_BITS * num_windows bits. - pub fn witness_decompose( - &self, - region: &mut Region<'_, F>, - offset: usize, - alpha: Value, - word_num_bits: usize, - num_windows: usize, - ) -> Result, Error> { - let z_0 = region.assign_advice(|| "z_0 = alpha", self.z, offset, || alpha)?; - self.decompose(region, offset, z_0, word_num_bits, num_windows) - } - - /// Decompose an existing variable alpha that is copied into this helper. - /// - /// `strict` = true constrains the final running sum to be zero, i.e. - /// constrains alpha to be within WINDOW_NUM_BITS * num_windows bits. - pub fn copy_decompose( - &self, - region: &mut Region<'_, F>, - offset: usize, - alpha: AssignedCell, - word_num_bits: usize, - num_windows: usize, - ) -> Result, Error> { - let z_0 = alpha.copy_advice(|| "copy z_0 = alpha", region, self.z, offset)?; - self.decompose(region, offset, z_0, word_num_bits, num_windows) - } - - /// `z_0` must be the cell at `(self.z, offset)` in `region`. - /// - /// # Panics - /// - /// Panics if there are too many windows for the given word size. - fn decompose( - &self, - region: &mut Region<'_, F>, - offset: usize, - z_0: AssignedCell, - word_num_bits: usize, - num_windows: usize, - ) -> Result, Error> { - // Make sure that we do not have more windows than required for the number - // of bits in the word. In other words, every window must contain at least - // one bit of the word (no empty windows). - // - // For example, let: - // - word_num_bits = 64 - // - WINDOW_NUM_BITS = 3 - // In this case, the maximum allowed num_windows is 22: - // 3 * 22 < 64 + 3 - // - assert!(WINDOW_NUM_BITS * num_windows < word_num_bits + WINDOW_NUM_BITS); - - // Enable selectors - for idx in 0..num_windows { - self.q_range_check.enable(region, offset + idx)?; - } - - // Decompose base field element into K-bit words. - let words = z_0 - .value() - .map(|word| decompose_word::(word, word_num_bits, WINDOW_NUM_BITS)) - .transpose_vec(num_windows); - - // Initialize empty vector to store running sum values [z_0, ..., z_W]. - let mut zs: Vec> = vec![]; - let mut z = z_0; - - // Assign padding to the first element? - // region.assign_advice( - // || format!("b_{:?}", 0), - // self.b, - // offset, - // || Value::known(F::zero()), - // )?; - - // Assign running sum `z_{i+1}` = (z_i - k_i) / (2^K) for i = 0..=n-1. - // Outside of this helper, z_0 = alpha must have already been loaded into the - // `z` column at `offset`. - let two_pow_k_inv = Value::known(F::from(1 << WINDOW_NUM_BITS as u64).invert().unwrap()); - for (i, word) in words.iter().enumerate() { - // z_next = (z_cur - word) / (2^K) - - let word = word.map(|word| F::from(word as u64)); - - let z_next = { - let z_cur_val = z.value().copied(); - let z_next_val = (z_cur_val - word) * two_pow_k_inv; - region.assign_advice( - || format!("z_{:?}", i + 1), - self.z, - offset + i + 1, - || z_next_val, - )? - }; - - let b_assigned = - region.assign_advice(|| format!("b_{i:?}"), self.b, offset + i, || word)?; - - // Update `z`. - z = z_next; - zs.push(b_assigned); - } - assert_eq!(zs.len(), num_windows); - - // Constrain the final running sum output to be zero. - region.constrain_constant(z.cell(), F::zero())?; - - Ok(BinaryDecomposition(zs)) - } -} - -#[cfg(test)] -mod tests { - use crate::test::util::{advice_column_equality, instance_column_equality}; - - use super::*; - use halo2_base::halo2_proofs::plonk::Instance; - use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::MockProver, - halo2curves::{bn256::Fr, FieldExt}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - - struct BinaryDecompCircuit { - alpha: Value, - word_num_bits: usize, - num_windows: usize, - } - - impl Circuit - for BinaryDecompCircuit - { - type Config = ( - Column, - BinaryDecompositionConfig, - ); - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self { - alpha: Value::unknown(), - word_num_bits: self.word_num_bits, - num_windows: self.num_windows, - } - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let z = advice_column_equality(meta); - let b = advice_column_equality(meta); - let i = instance_column_equality(meta); - let q_range_check = meta.selector(); - let constants = meta.fixed_column(); - meta.enable_constant(constants); - - ( - i, - BinaryDecompositionConfig::::configure( - meta, - q_range_check, - z, - b, - ), - ) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let (instance, config) = config; - let bits = layouter.assign_region( - || "decompose", - |mut region| { - let offset = 0; - config.witness_decompose( - &mut region, - offset, - self.alpha, - self.word_num_bits, - self.num_windows, - ) - }, - )?; - - for (i, b) in bits.iter().enumerate() { - layouter.constrain_instance(b.cell(), instance, i)?; - } - - Ok(()) - } - } - - #[test] - fn test_binary_decomp() { - let k = 14; - - let circuit = BinaryDecompCircuit:: { - alpha: Value::known(Fr::from(3)), - num_windows: 3, - word_num_bits: 3, - }; - - // 011 -> 1,1,0 - let bits = vec![Fr::one(), Fr::one(), Fr::zero()]; - - let prover = MockProver::::run(k, &circuit, vec![bits]).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_binary_decomp_2() { - let k = 14; - - let circuit = BinaryDecompCircuit:: { - alpha: Value::known(Fr::from(7)), - num_windows: 3, - word_num_bits: 3, - }; - - // 111 -> 1,1,1 - let bits = vec![Fr::one(), Fr::one(), Fr::one()]; - - let prover = MockProver::::run(k, &circuit, vec![bits]).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_binary_decomp_fail() { - let k = 14; - - let circuit = BinaryDecompCircuit:: { - alpha: Value::known(Fr::from(7)), - num_windows: 3, - word_num_bits: 3, - }; - - // 111 -> 1,1,1 - let bits = vec![Fr::one(), Fr::one(), Fr::zero()]; - - let prover = MockProver::::run(k, &circuit, vec![bits]).unwrap(); - prover.verify().unwrap_err(); - } -} diff --git a/pkg/zk-circuits/src/chips/is_constant.rs b/pkg/zk-circuits/src/chips/is_constant.rs deleted file mode 100644 index af53a2f..0000000 --- a/pkg/zk-circuits/src/chips/is_constant.rs +++ /dev/null @@ -1,229 +0,0 @@ -use super::is_zero::{IsZeroChip, IsZeroConfig}; -use halo2_base::halo2_proofs::{ - arithmetic::FieldExt, - circuit::{AssignedCell, Layouter, Value}, - plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Expression, Selector}, - poly::Rotation, -}; - -#[derive(Clone, Debug)] -pub struct IsConstantConfig { - is_zero_config: IsZeroConfig, - selector: Selector, - zero_advice: Column, - output_advice: Column, - constant: F, -} - -#[derive(Clone, Debug)] -pub struct IsConstantChip { - config: IsConstantConfig, -} - -impl IsConstantChip { - pub fn configure( - meta: &mut ConstraintSystem, - zero_advice: Column, - inverse_advice: Column, - output_advice: Column, - constant: F, - ) -> IsConstantConfig { - let selector: halo2_base::halo2_proofs::plonk::Selector = meta.selector(); - - let is_zero_config = IsZeroChip::::configure( - meta, - |meta| meta.query_selector(selector), - |meta| meta.query_advice(zero_advice, Rotation::cur()) - Expression::Constant(constant), - inverse_advice, - ); - - meta.create_gate("is_constant", |meta| { - let s = meta.query_selector(selector); - let o = meta.query_advice(output_advice, Rotation::cur()); - - Constraints::with_selector(s, [o - is_zero_config.is_zero_expr.clone()]) - }); - - IsConstantConfig { - is_zero_config, - selector, - zero_advice, - output_advice, - constant, - } - } - - pub fn construct(config: IsConstantConfig) -> Self { - IsConstantChip { config } - } - - pub fn assign( - &self, - mut layouter: impl Layouter, - comparison: AssignedCell, - ) -> Result, Error> { - let zero_chip = IsZeroChip::construct(self.config.is_zero_config.clone()); - - layouter.assign_region( - || "check is constant", - |mut region| { - // Enable the selector - self.config.selector.enable(&mut region, 0)?; - - // Copy the assigned cell into the region - let comparison_cell: AssignedCell = comparison.copy_advice( - || "comparison value", - &mut region, - self.config.zero_advice, - 0, - )?; - - // Subtract the constant from the provided cell value - let value = comparison_cell.value().cloned() - Value::known(self.config.constant); - - // Assign the inverse value - zero_chip.assign(&mut region, 0, value)?; - - // Assign the bool value - let output_cell = region.assign_advice( - || "is constant", - self.config.output_advice, - 0, - || { - value.and_then(|v| { - if v == F::zero() { - Value::known(F::one()) - } else { - Value::known(F::zero()) - } - }) - }, - )?; - - Ok(output_cell) - }, - ) - } -} - -#[cfg(test)] -mod tests { - use halo2_base::halo2_proofs::{ - circuit::SimpleFloorPlanner, - dev::MockProver, - halo2curves::bn256::Fr, - plonk::{Circuit, Instance}, - }; - - use crate::{ - test::util::{advice_column_equality, instance_column_equality}, - util::assign_private_input, - }; - - use super::*; - - #[derive(Clone, Debug)] - struct IsConstantCircuitConfig { - is_constant_config: IsConstantConfig, - instance: Column, - comparison: Column, - } - - #[derive(Default, Clone, Debug)] - struct IsConstantCircuit { - compare: Fr, - } - - impl Circuit for IsConstantCircuit { - type Config = IsConstantCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let zero_advice = advice_column_equality(meta); - let inverse_advice = advice_column_equality(meta); - let output_advice = advice_column_equality(meta); - - IsConstantCircuitConfig { - is_constant_config: IsConstantChip::configure( - meta, - zero_advice, - inverse_advice, - output_advice, - Fr::from_u128(10u128), - ), - comparison: advice_column_equality(meta), - instance: instance_column_equality(meta), - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let is_constant_chip = IsConstantChip::construct(config.is_constant_config); - - let comparison_witness = assign_private_input( - || "witness compare", - layouter.namespace(|| "witness compare"), - config.comparison, - Value::known(self.compare), - )?; - - let output = is_constant_chip.assign( - layouter.namespace(|| "compare to constant"), - comparison_witness, - )?; - - layouter.constrain_instance(output.cell(), config.instance, 0)?; - - Ok(()) - } - } - - #[test] - fn test_equal_constant() { - let k = 3; - - let public_input = vec![Fr::from_u128(1u128)]; - let instance_columns = vec![public_input]; - let circuit = IsConstantCircuit { - compare: Fr::from_u128(10u128), - }; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_not_equal_constant() { - let k = 3; - - let public_input = vec![Fr::from_u128(0u128)]; - let instance_columns = vec![public_input]; - let circuit = IsConstantCircuit { - compare: Fr::from_u128(11u128), - }; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_zero() { - let k = 3; - - let public_input = vec![Fr::from_u128(0u128)]; - let instance_columns = vec![public_input]; - let circuit = IsConstantCircuit { - compare: Fr::from_u128(0u128), - }; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } -} diff --git a/pkg/zk-circuits/src/chips/is_less_than.rs b/pkg/zk-circuits/src/chips/is_less_than.rs deleted file mode 100644 index ca53ad8..0000000 --- a/pkg/zk-circuits/src/chips/is_less_than.rs +++ /dev/null @@ -1,336 +0,0 @@ -use halo2_base::halo2_proofs::{ - arithmetic::Field, - circuit::{AssignedCell, Layouter, Value}, - plonk::{Advice, Column, ConstraintSystem, Error, Expression, Selector}, - poly::Rotation, -}; -use std::marker::PhantomData; - -#[derive(Debug, Clone)] -pub struct IsLessThanChipConfig { - selector: Selector, - advices: [Column; 4], -} - -/// This chip should be used to compare two binary values (with each bit being represented by an assigned cell). -/// It is assumed that the bit values have been range checked, and are in big-endian order. -#[derive(Debug, Clone)] -pub struct IsLessThanChip { - config: IsLessThanChipConfig, - _marker: PhantomData, -} - -impl IsLessThanChip { - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 4], - ) -> IsLessThanChipConfig { - let selector = meta.selector(); - - let max = advices[0]; - let alpha = advices[1]; - let is_less = advices[2]; - let can_set = advices[3]; - - meta.create_gate("Is Less", |meta| { - let s = meta.query_selector(selector); - - let last_is_less = meta.query_advice(is_less, Rotation::prev()); - let last_can_set = meta.query_advice(can_set, Rotation::prev()); - - let max = meta.query_advice(max, Rotation::cur()); - let alpha = meta.query_advice(alpha, Rotation::cur()); - let is_less = meta.query_advice(is_less, Rotation::cur()); - let can_set = meta.query_advice(can_set, Rotation::cur()); - - let one = Expression::Constant(F::one()); - - // max | alpha | is_less | can_set | selector - // | last_is_less | last_can_set | - // max | alpha | is_less | can_set | 1 - - vec![ - // Constraint is_less - s.clone() - * ((last_is_less - - (max.clone() * (one.clone() - alpha.clone())) * last_can_set.clone()) - - is_less), - // Constrain can_set - s * ((max.clone() * alpha.clone() + (one.clone() - max) * (one - alpha)) - * last_can_set - - can_set), - ] - }); - - IsLessThanChipConfig { selector, advices } - } - - pub fn construct(config: IsLessThanChipConfig) -> Self { - Self { - _marker: PhantomData, - config, - } - } - - pub fn assign( - &self, - mut layouter: impl Layouter, - max_bits: &[AssignedCell], - alpha_bits: &[AssignedCell], - ) -> Result<(), Error> { - assert_eq!( - max_bits.len(), - alpha_bits.len(), - "max and alpha bits must have the same length" - ); - - layouter.assign_region( - || "is less than chip", - |mut region| { - let advices = self.config.advices; - - let max_advice = advices[0]; - let alpha_advice = advices[1]; - let is_less_advice = advices[2]; - let can_set_advice = advices[3]; - - // Copy the first region values - let mut is_less = region.assign_advice_from_constant( - || "init is_less", - is_less_advice, - 0, - F::one(), - )?; - let mut can_set = region.assign_advice_from_constant( - || "init can_set", - can_set_advice, - 0, - F::one(), - )?; - - for (i, (m_bit, a_bit)) in max_bits.iter().zip(alpha_bits.iter()).enumerate() { - let offset = i + 1; - - // Enable the selector, so we constrain all rows (except the first) - self.config.selector.enable(&mut region, offset)?; - - // Copy in the values to be compared - let m_bit = m_bit.copy_advice(|| "m_bit", &mut region, max_advice, offset)?; - let a_bit = a_bit.copy_advice(|| "a_bit", &mut region, alpha_advice, offset)?; - - // is_less expected value - is_less = region.assign_advice( - || "is less", - is_less_advice, - offset, - || { - is_less.value().and_then(|last_is_less| { - can_set.value().and_then(|last_can_set| { - m_bit.value().and_then(|m_val| { - a_bit.value().and_then(|a_val| { - Value::known( - *last_is_less - - (*m_val - * (F::one() - *a_val) - * *last_can_set), - ) - }) - }) - }) - }) - }, - )?; - - // can_set expected value - can_set = region.assign_advice( - || "can_set", - can_set_advice, - offset, - || { - can_set.value().and_then(|last_can_set| { - m_bit.value().and_then(|m_val| { - a_bit.value().and_then(|a_val| { - Value::known( - (*m_val * *a_val - + (F::one() - *m_val) * (F::one() - *a_val)) - * *last_can_set, - ) - }) - }) - }) - }, - )?; - } - - // Assert the final value is zero - region.constrain_constant(is_less.cell(), F::zero())?; - - Ok(()) - }, - ) - } -} - -#[cfg(test)] -mod tests { - // use halo2_base::halo2_proofs::arithmetic::FieldExt; - use halo2_base::halo2_proofs::{ - circuit::SimpleFloorPlanner, - dev::MockProver, - halo2curves::bn256::Fr, - plonk::{Circuit, Error}, - }; - - use crate::{test::util::advice_column_equality, util::assign_private_input}; - - use super::*; - - #[derive(Default, Clone, Debug)] - struct IsLessThanCircuit { - max: Vec, - alpha: Vec, - } - - impl Circuit for IsLessThanCircuit { - type Config = IsLessThanChipConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - advice_column_equality(meta), - advice_column_equality(meta), - advice_column_equality(meta), - advice_column_equality(meta), - ]; - let fixed = meta.fixed_column(); - meta.enable_constant(fixed); - IsLessThanChip::configure(meta, advices) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let is_less_than_chip = IsLessThanChip::construct(config.clone()); - - let max_bits = self - .max - .iter() - .map(|v| { - assign_private_input( - || "max", - layouter.namespace(|| "max"), - config.advices[0], - Value::known(*v), - ) - }) - .collect::, Error>>()?; - - let alpha_bits = self - .alpha - .iter() - .map(|v| { - assign_private_input( - || "max", - layouter.namespace(|| "alpha"), - config.advices[1], - Value::known(*v), - ) - }) - .collect::, Error>>()?; - - is_less_than_chip.assign( - layouter.namespace(|| "is less than"), - max_bits.as_slice(), - alpha_bits.as_slice(), - )?; - - Ok(()) - } - } - - #[test] - fn test_less_than_1_bit() { - let k = 8; - - let circuit = IsLessThanCircuit { - max: vec![Fr::from(1u64)], - alpha: vec![Fr::from(0u64)], - }; - - let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_not_less_than_1_bit_error() { - let k = 8; - - let circuit = IsLessThanCircuit { - max: vec![Fr::from(1u64)], - alpha: vec![Fr::from(1u64)], - }; - - let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); - prover.verify().expect_err("proof should not be satisfied"); - } - - #[test] - fn test_less_than_6_bits() { - let k = 8; - - let circuit = IsLessThanCircuit { - max: vec![ - Fr::from(0u64), - Fr::from(1u64), - Fr::from(0u64), - Fr::from(1u64), - Fr::from(1u64), - Fr::from(0u64), - ], - alpha: vec![ - Fr::from(0u64), - Fr::from(0u64), - Fr::from(1u64), - Fr::from(1u64), - Fr::from(1u64), - Fr::from(1u64), - ], - }; - - let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_less_than_6_bits_error() { - let k = 8; - - let circuit = IsLessThanCircuit { - max: vec![ - Fr::from(0u64), - Fr::from(1u64), - Fr::from(0u64), - Fr::from(1u64), - Fr::from(1u64), - Fr::from(0u64), - ], - alpha: vec![ - Fr::from(0u64), - Fr::from(1u64), - Fr::from(1u64), - Fr::from(0u64), - Fr::from(0u64), - Fr::from(0u64), - ], - }; - - let prover = MockProver::::run(k, &circuit, vec![]).unwrap(); - prover.verify().expect_err("proof should not be satisfied"); - } -} diff --git a/pkg/zk-circuits/src/chips/is_zero.rs b/pkg/zk-circuits/src/chips/is_zero.rs deleted file mode 100644 index f0226db..0000000 --- a/pkg/zk-circuits/src/chips/is_zero.rs +++ /dev/null @@ -1,330 +0,0 @@ -use halo2_base::halo2_proofs::{ - arithmetic::FieldExt, - circuit::{Region, Value}, - plonk::{Advice, Column, ConstraintSystem, Error, Expression, VirtualCells}, - poly::Rotation, -}; - -#[derive(Clone, Debug)] -pub struct IsZeroConfig { - pub value_inv: Column, - pub is_zero_expr: Expression, -} - -/// IsZeroChip -/// -/// Cannot be used standalone, you MUST use the configured isZeroChip with another custom gate -/// to actually use the isZeroExpr value which will be 1 if the value is zero, and 0 otherwise. -/// -#[derive(Clone, Debug)] -pub struct IsZeroChip { - config: IsZeroConfig, -} - -impl IsZeroChip { - pub fn construct(config: IsZeroConfig) -> Self { - IsZeroChip { config } - } - - // Here we deal with expressions that must evaluate to 0, these constrain the assignment values of a circuit - // (in the next step) - pub fn configure( - meta: &mut ConstraintSystem, - // Selector - q_enable: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression, - // Value expression to check for zero (can including multiple columns) - value: impl FnOnce(&mut VirtualCells<'_, F>) -> Expression, - value_inv: Column, - ) -> IsZeroConfig { - let mut is_zero_expr = Expression::Constant(F::zero()); - - // GATE WILL EVALUATE TO 1 if ZERO, 0 otherwise! - meta.create_gate("is_zero", |meta| { - // - // valid | value | value_inv | 1 - value * value_inv | value * (1 - value* value_inv) - // ------+-------+------------+------------------------+------------------------------- - // yes | x | 1/x | 0 | 0 - // no | x | 0 | 1 | x - // yes | 0 | 0 | 1 | 0 - // yes | 0 | y | 1 | 0 - // - let value = value(meta); - let q_enable = q_enable(meta); - let value_inv = meta.query_advice(value_inv, Rotation::cur()); - - // This will be used inside another constrait gate! - is_zero_expr = Expression::Constant(F::one()) - value.clone() * value_inv; - - // This is an additional constraint check to prevent the value_inv being populated incorrectly! This is populated - // by the prover, in assign below, so we must ensure they have used a valid value! - vec![q_enable * value * is_zero_expr.clone()] - }); - - IsZeroConfig { - value_inv, - - // is_zero_expr will evalautate to 1 if the value is 0, and 1 otherwise. That means we can basically - // think of is_zero_expr as a selector. - - // If we want to check if an expr evaluates to 0, we can use is_zero_expr * expr, because if expr is != 0 - // then selector will cause the value to not be 0. - - // If we want to check if an expr evaluates to 1 (i.e. not zero), we can use (1 - is_zero_expr) * expr - is_zero_expr, - } - } - - pub fn assign( - &self, - region: &mut Region<'_, F>, - offset: usize, - value: Value, - ) -> Result<(), Error> { - let value_inv = value.map(|value| value.invert().unwrap_or(F::zero())); - region.assign_advice(|| "value inv", self.config.value_inv, offset, || value_inv)?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use crate::test::util::{advice_column_equality, instance_column_equality}; - - use super::*; - use halo2_base::halo2_proofs::{ - arithmetic::FieldExt, - circuit::SimpleFloorPlanner, - dev::{FailureLocation, MockProver, VerifyFailure}, - halo2curves::pasta::Fp, - plonk::{Advice, Any, Circuit, Column, ConstraintSystem, Constraints, Instance, Selector}, - poly::Rotation, - }; - - ///////// - /// - /// Impl chip in circuit - /// - //////// - - #[derive(Debug, Clone)] - struct TestCircuitConfig { - zero_chip_config: IsZeroConfig, - value_to_check_advice: Column, - bool_is_zero_advice: Column, - instance: Column, - selector: Selector, - } - - #[derive(Debug, Default)] - struct TestCircuit { - is_zero: F, - } - - impl Circuit for TestCircuit { - type Config = TestCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - // Constrain the circuit - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let value_to_check_advice: Column = advice_column_equality(meta); - let bool_is_zero_advice = advice_column_equality(meta); - let zero_col = advice_column_equality(meta); - let instance_col = instance_column_equality(meta); - let selector: Selector = meta.selector(); - - // Configure the isZero chip so we can get access to the - let is_zero_configure = IsZeroChip::::configure( - meta, - |meta| meta.query_selector(selector), - // This is the value being checked - |meta| meta.query_advice(value_to_check_advice, Rotation::cur()), - // This is the inverse of value bieng checked (required for safety) - zero_col, - ); - - meta.create_gate("is_zero", |meta| { - let s = meta.query_selector(selector); - let bool_is_zero = meta.query_advice(bool_is_zero_advice, Rotation::cur()); - - Constraints::with_selector( - s, - [bool_is_zero - is_zero_configure.is_zero_expr.clone()], - ) - }); - - TestCircuitConfig { - zero_chip_config: is_zero_configure, - value_to_check_advice, - bool_is_zero_advice, - instance: instance_col, - selector, - } - } - - // Populate the circuit - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl halo2_base::halo2_proofs::circuit::Layouter, - ) -> Result<(), halo2_base::halo2_proofs::plonk::Error> { - let zero_chip = IsZeroChip::construct(config.zero_chip_config); - - layouter.assign_region( - || "check_num", - |mut region| { - // Enables the enforcement of the gate on the pre-configured instance column - config.selector.enable(&mut region, 0)?; - - let cell = region.assign_advice_from_instance( - || "value to check is 0", - config.instance, - 0, - config.value_to_check_advice, - 0, - )?; - - // Assign the value to check - zero_chip.assign(&mut region, 0, cell.value().copied())?; - - // Bool is zero - region.assign_advice( - || "bool is zero", - config.bool_is_zero_advice, - 0, - || Value::known(self.is_zero), - )?; - - Ok(()) - }, - ) - } - } - - #[test] - fn test_zero() { - let k = 4; - - let val = Fp::zero(); - - let circuit = TestCircuit { is_zero: Fp::one() }; - - // Vector for the public input column (if we had more, we'd need to add additional) - let public_input = vec![val]; - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_zero_invalid() { - let k = 4; - - let val = Fp::zero(); - - let circuit = TestCircuit { - is_zero: Fp::zero(), - }; - - // Vector for the public input column (if we had more, we'd need to add additional) - let public_input = vec![val]; - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::ConstraintNotSatisfied { - constraint: ((1, "is_zero").into(), 0, "").into(), - location: FailureLocation::InRegion { - region: (0, "check_num").into(), - offset: 0 - }, - cell_values: vec![( - ((Any::Advice(Advice::default()), 1).into(), 0).into(), - "0".to_string() - )] - }]) - ); - } - - #[test] - fn test_non_zero() { - let k = 4; - - let val = Fp::from_u128(10u128); - - let circuit = TestCircuit { - is_zero: Fp::zero(), - }; - - let public_input = vec![val]; - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_non_zero_invalid() { - let k = 4; - - let val = Fp::from_u128(10u128); - - let circuit = TestCircuit { is_zero: Fp::one() }; - - // Vector for the public input column (if we had more, we'd need to add additional) - let public_input = vec![val]; - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::ConstraintNotSatisfied { - constraint: ((1, "is_zero").into(), 0, "").into(), - location: FailureLocation::InRegion { - region: (0, "check_num").into(), - offset: 0 - }, - cell_values: vec![( - ((Any::Advice(Advice::default()), 1).into(), 0).into(), - "1".to_string() - )] - }]) - ); - } - - #[test] - fn test_non_zero_invalid_non_bool() { - let k = 4; - - let val = Fp::from_u128(10u128); - - let circuit = TestCircuit { - is_zero: Fp::from_u128(10u128), - }; - - // Vector for the public input column (if we had more, we'd need to add additional) - let public_input = vec![val]; - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - assert_eq!( - prover.verify(), - Err(vec![VerifyFailure::ConstraintNotSatisfied { - constraint: ((1, "is_zero").into(), 0, "").into(), - location: FailureLocation::InRegion { - region: (0, "check_num").into(), - offset: 0 - }, - cell_values: vec![( - ((Any::Advice(Advice::default()), 1).into(), 0).into(), - "0xa".to_string() - )] - }]) - ); - } -} diff --git a/pkg/zk-circuits/src/chips/merkle_path.rs b/pkg/zk-circuits/src/chips/merkle_path.rs deleted file mode 100644 index 9d254d5..0000000 --- a/pkg/zk-circuits/src/chips/merkle_path.rs +++ /dev/null @@ -1,271 +0,0 @@ -use crate::{ - chips::{ - poseidon::{poseidon_hash, poseidon_hash_gadget, PoseidonConfig}, - swap::CondSwapChip, - }, - data::MerklePath, -}; -use halo2_base::halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - halo2curves::bn256::Fr, - plonk::Error, -}; -use smirk::Element; -use std::iter::zip; - -impl MerklePath { - pub fn new(siblings: Vec) -> Self { - assert_eq!(DEPTH - 1, siblings.len(), "Merkle path invalid size"); - - MerklePath { siblings } - } - - // Calcualte a MerklePath based on the current leaf - pub fn apply_leaf(&self, leaf: Element) -> MerklePath { - MerklePath { - siblings: self.compute_path_from_leaf(leaf)[0..DEPTH - 1].to_vec(), - } - } - - /// Compute the root hash of a tree with the given hash at this path - pub fn compute_root(&self, hash: Element) -> Element { - self.compute_root_from_leaf(&hash, hash) - } - - pub fn compute_null_root(&self, hash: Element) -> Element { - self.compute_root_from_leaf(&hash, Element::ZERO) - } - - /// Compute the root hash of a tree with the given hash at this path - fn compute_root_from_leaf(&self, hash_path: &Element, leaf: Element) -> Element { - let bits = Self::least_significant_bits(*hash_path); - - let mut hash = leaf.to_base(); - - for (is_right, &sibling) in zip(bits, &self.siblings) { - match is_right { - true => hash = poseidon_hash([sibling.to_base(), hash]), - false => hash = poseidon_hash([hash, sibling.to_base()]), - } - } - - hash.into() - } - - pub fn compute_path_from_leaf(&self, leaf: Element) -> Vec { - let bits = Self::least_significant_bits(leaf); - - let mut path = vec![leaf]; - let mut hash = leaf.to_base(); - - for (is_right, &sibling) in zip(bits, &self.siblings) { - // TODO: make Element hashable - match is_right { - true => hash = poseidon_hash([sibling.to_base(), hash]), - false => hash = poseidon_hash([hash, sibling.to_base()]), - }; - path.push(hash.into()) - } - - path - } - - /// `bits` takes the first N least significant bits from the field element and returns the bits in - /// reverse order. - /// - /// For example assuming N is 2 (max 2 bis): - /// - /// Int | Bit | Returns - /// ----|----------|---------------- - /// `2` | `010` | `[0, 1]` - /// `3` | `011` | `[1, 1]` - /// `4` | `100` | `[0, 0]` - /// `5` | `101` | `[1, 0]` - /// - // pub fn bits(hash_path: &Fr) -> BitVec { - // let bits: BitArray<[u64; 4]> = hash_path.to_le_bits(); - // let bits = Self::last_n_bits(&bits); - // BitVec::from_bitslice(bits) - // } - // - // fn last_n_bits(bits: &BitArray<[u64; 4]>) -> &BitSlice { - // let slice = &bits[0..N]; - // assert_eq!(slice.len(), N); - // slice - // } - - pub fn least_significant_bits(element: Element) -> impl Iterator { - element.lsb(DEPTH - 1).into_iter().rev() - } - - pub fn enforce_inclusion_constraints( - &self, - mut layouter: impl Layouter, - leaf_value: Fr, - leaf_assigned: AssignedCell, - poseidon_config: PoseidonConfig, - swap_chip: CondSwapChip, - ) -> Result { - let decomposed_bits = - MerklePath::::least_significant_bits(Element::from(leaf_value)); - - let siblings = self - .siblings - .iter() - .map(|e| e.to_base()) - .map(Value::known) - .zip(decomposed_bits.map(|b| Value::known(if b { Fr::one() } else { Fr::zero() }))) - .collect::>(); - - let root = merkle_root_value( - layouter.namespace(|| "new root"), - swap_chip, - poseidon_config, - leaf_assigned, - siblings.as_slice(), - )?; - - Ok(MerklePathInclusionConstrainCells { root }) - } -} - -pub struct MerklePathInclusionConstrainCells { - pub root: AssignedCell, -} - -// TODO: refactor these! - -/// Get the merkle root based on leaf + (siblings + LR directions) -#[allow(clippy::type_complexity)] -pub fn merkle_root( - mut layouter: impl Layouter, - swap_chip: CondSwapChip, - poseidon_config: PoseidonConfig, - leaf: AssignedCell, - // Turple is (node, LR) - siblings: &[(&AssignedCell, &AssignedCell)], -) -> Result, Error> { - let mut cur = leaf; - - for (sibling, swap) in siblings.iter() { - // Pair, in the correct order (left=0, right=1) - // TODO: is this the correct way around?! - let pair = swap_chip.swap_assigned( - layouter.namespace(|| "merkle path swap"), - (&cur, sibling), - swap, - )?; - - cur = poseidon_hash_gadget( - poseidon_config.clone(), - layouter.namespace(|| "merkle poseidon hash"), - [pair.0, pair.1], - )?; - } - - Ok(cur) -} - -/// Get the merkle root based on leaf + (siblings + LR directions) -#[allow(clippy::type_complexity)] -pub fn merkle_root_value( - mut layouter: impl Layouter, - swap_chip: CondSwapChip, - poseidon_config: PoseidonConfig, - leaf: AssignedCell, - // Turple is (node, LR) - siblings: &[(Value, Value)], -) -> Result, Error> { - let mut cur = leaf; - - for (sibling, swap) in siblings.iter() { - // Pair, in the correct order (left=0, right=1) - // TODO: is this the correct way around?! - let pair = swap_chip.swap( - layouter.namespace(|| "merkle path swap"), - (&cur, *sibling), - *swap, - )?; - - cur = poseidon_hash_gadget( - poseidon_config.clone(), - layouter.namespace(|| "merkle poseidon hash"), - [pair.0, pair.1], - )?; - } - - Ok(cur) -} - -#[cfg(test)] -mod tests { - use bitvec::prelude::*; - use itertools::Itertools; - - use super::*; - - fn hmerge(a: Element, b: Element) -> Element { - poseidon_hash([a.to_base(), b.to_base()]).into() - } - - #[test] - fn first_insert() { - let empty_tree = MerklePath::<64>::default(); - - let root = empty_tree.compute_root(Element::from(3u64)).to_base(); - - assert_eq!( - format!("{root:?}"), - "0x26debce8a5ba1d092589121944bfc2cc55d858bcd7a697ec2fd1b832b4b20c40" - ); - } - - #[test] - fn last_n_bits_no_cutoff_test() { - // Binary: [1, 0] - let hash_last_bits = 2u64; - let hash = Fr::from(hash_last_bits); - let bits = MerklePath::<3>::least_significant_bits(Element::from(hash)); - - // let slice = - let mut bv: BitVec = BitVec::new(); - - // [0, 1] - bv.push(false); - bv.push(true); - - assert_eq!(bits.collect_vec(), bv.into_iter().collect_vec()); - } - - #[test] - fn last_n_bits_cutoff_test() { - // Binary: [1, 0, 1] - let hash_last_bits = 5u64; - let hash = Fr::from(hash_last_bits); - let bits = MerklePath::<3>::least_significant_bits(Element::from(hash)); - - // let slice = - let mut bv: BitVec = BitVec::new(); - - // [1, 0] - bv.push(true); - bv.push(false); - - assert_eq!(bits.collect_vec(), bv.into_iter().collect_vec()); - } - - #[test] - fn simple_root() { - let siblings = (0..5u64).map(Element::from).collect::>(); - let path = MerklePath::<6> { - siblings: siblings.clone(), - }; - - let root = path.compute_root(Element::from(0u64)); - - // because 0 is the lowest (left-most) possible value, every merge is this way round - let expected_root = siblings.into_iter().fold(Element::from(0u64), hmerge); - - assert_eq!(root, expected_root); - } -} diff --git a/pkg/zk-circuits/src/chips/mod.rs b/pkg/zk-circuits/src/chips/mod.rs deleted file mode 100644 index 2b22bfc..0000000 --- a/pkg/zk-circuits/src/chips/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub(crate) mod add; -pub mod aggregation; -pub(crate) mod binary_decomposition; -pub(crate) mod is_constant; -pub(crate) mod is_less_than; -pub(crate) mod is_zero; -pub mod merkle_path; -pub(crate) mod poseidon; -#[allow(dead_code)] -pub(crate) mod sig; -pub(crate) mod swap; - -pub use poseidon::poseidon_hash; diff --git a/pkg/zk-circuits/src/chips/poseidon.rs b/pkg/zk-circuits/src/chips/poseidon.rs deleted file mode 100644 index ed9bc2d..0000000 --- a/pkg/zk-circuits/src/chips/poseidon.rs +++ /dev/null @@ -1,179 +0,0 @@ -use halo2_base::halo2_proofs::{ - circuit::{AssignedCell, Layouter}, - halo2curves::bn256::Fr, - plonk::Error, -}; -use poseidon_circuit::{ - poseidon::{ - primitives::{ConstantLength, Hash as PoseidonHash, P128Pow5T3}, - Hash, - }, - Hashable, -}; - -pub use poseidon_circuit::poseidon::{Pow5Chip as PoseidonChip, Pow5Config as PoseidonConfig}; - -pub type P128Pow5T3Fr = P128Pow5T3; - -/// Hashes AssignedCells -/// -/// **BUG** must be equal number of elements due to bug in posiedon impl -/// Fixed in Halo2 poseidon (https://github.com/zcash/halo2/pull/646), but not in Scroll poseidon. -/// -pub fn poseidon_hash_gadget( - config: PoseidonConfig, - mut layouter: impl Layouter, - messages: [AssignedCell; L], -) -> Result, Error> { - let chip = PoseidonChip::construct(config); - let hasher = Hash::<_, _, P128Pow5T3, ConstantLength, 3, 2>::init( - chip, - layouter.namespace(|| "init poseidon hasher"), - )?; - - hasher.hash(layouter.namespace(|| "hash"), messages) -} - -// TODO: make Element Hashable -pub fn poseidon_hash(message: [F; L]) -> F { - PoseidonHash::, ConstantLength, 3, 2>::init().hash(message) -} - -#[cfg(test)] -mod tests { - use crate::util::{assign_private_input, random_fr}; - - use super::*; - use halo2_base::halo2_proofs::{ - circuit::{SimpleFloorPlanner, Value}, - dev::MockProver, - plonk::{Advice, Circuit, Column, ConstraintSystem, Instance}, - }; - use smirk::hash_merge; - use snark_verifier::util::arithmetic::FieldExt; - - #[test] - fn poseidon_hash_snapshot() { - let result = poseidon_hash([Fr::from_u128(2), Fr::from_u128(3)]); - - // make sure the debug representation doesn't change so we can change the hash impl - assert_eq!( - format!("{result:?}"), - "0x19014d18a3179c5731155fcb7b6da422f456bccbd6da9dbc7df0f8dc6d4938ed" - ); - - assert_eq!( - result, - Fr::from(hash_merge([2, 3].map(zk_primitives::Element::new))), - ) - } - - #[derive(Debug, Clone)] - struct PoseidonCircuitConfig { - advices: [Column; 4], - instance: Column, - poseidon_config: PoseidonConfig, - } - - #[derive(Debug, Default, Clone)] - struct PoseidonCircuit { - left: Fr, - right: Fr, - } - - impl Circuit for PoseidonCircuit { - type Config = PoseidonCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> PoseidonCircuitConfig { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::>( - meta, - advices[0..3].try_into().unwrap(), - advices[3], - lagrange_coeffs[2..5].try_into().unwrap(), - lagrange_coeffs[5..8].try_into().unwrap(), - ); - - PoseidonCircuitConfig { - advices, - instance, - poseidon_config, - } - } - - fn synthesize( - &self, - config: PoseidonCircuitConfig, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Witness left - let left = assign_private_input( - || "assign left", - layouter.namespace(|| "assign left"), - config.advices[0], - Value::known(self.left), - )?; - - // Witness right - let right = assign_private_input( - || "assign right", - layouter.namespace(|| "assign right"), - config.advices[0], - Value::known(self.right), - )?; - - let combined = poseidon_hash_gadget( - config.poseidon_config, - layouter.namespace(|| "combine"), - [left, right], - )?; - - layouter.constrain_instance(combined.cell(), config.instance, 0)?; - - Ok(()) - } - } - - #[test] - fn test_poseidon() { - let k = 7; - let left = random_fr(); - let right = random_fr(); - let combined = poseidon_hash([left, right]); - - let circuit = PoseidonCircuit { left, right }; - - let prover = MockProver::::run(k, &circuit, vec![vec![combined]]).unwrap(); - prover.assert_satisfied(); - } -} diff --git a/pkg/zk-circuits/src/chips/sig.rs b/pkg/zk-circuits/src/chips/sig.rs deleted file mode 100644 index 4d53699..0000000 --- a/pkg/zk-circuits/src/chips/sig.rs +++ /dev/null @@ -1,324 +0,0 @@ -use std::marker::PhantomData; - -use ::secp256k1::{ecdsa::RecoverableSignature, PublicKey}; -use eth_types::{ - sign_types::{pk_bytes_le, pk_bytes_swap_endianness, SignData}, - Field, -}; -use halo2_base::halo2_proofs::{ - circuit::Layouter, - halo2curves::secp256k1, - plonk::{self, ConstraintSystem}, -}; -use zkevm_circuits::{ - sig_circuit::{utils::AssignedSignatureVerify, SigCircuitConfig, SigCircuitConfigArgs}, - table::{KeccakTable, SigTable}, - util::{Challenges, SubCircuitConfig}, -}; - -#[derive(Debug, thiserror::Error)] -pub enum Error { - #[error("Failed to convert bytes to secp256k1::Fp")] - FailedToConvertBytesToSecp256k1Fp, - #[error("Failed to convert bytes to secp256k1::Fq")] - FailedToConvertBytesToSecp256k1Fq, -} - -pub fn convert_sig_to_sign_data( - signature: RecoverableSignature, - message: &str, - public_key: PublicKey, - msg_hash: [u8; 32], -) -> Result { - let message_bytes = message.as_bytes().to_vec(); - - let (recovery_id, compact_signature) = signature.serialize_compact(); - - let r = &compact_signature[..32]; - let s = &compact_signature[32..64]; - - let mut r_arr = [0u8; 32]; - let mut s_arr = [0u8; 32]; - r_arr.copy_from_slice(r); - s_arr.copy_from_slice(s); - - let v = recovery_id.to_i32() as u8; - - sig_to_sign_data(public_key, message_bytes, msg_hash, r_arr, s_arr, v) -} - -fn sig_to_sign_data( - pk: PublicKey, - msg: Vec, - mut msg_hash: [u8; 32], - mut r: [u8; 32], - mut s: [u8; 32], - v: u8, -) -> Result { - let mut pk_x_bytes: [u8; 32] = pk.serialize_uncompressed()[1..33].try_into().unwrap(); - let mut pk_y_bytes: [u8; 32] = pk.serialize_uncompressed()[33..65].try_into().unwrap(); - - // Change endianness - pk_x_bytes.reverse(); - pk_y_bytes.reverse(); - r.reverse(); - s.reverse(); - msg_hash.reverse(); - - let pk = secp256k1::Secp256k1Affine { - x: match secp256k1::Fp::from_bytes(&pk_x_bytes) { - opt if bool::from(opt.is_some()) => opt.unwrap(), - _ => return Err(Error::FailedToConvertBytesToSecp256k1Fp), - }, - y: match secp256k1::Fp::from_bytes(&pk_y_bytes) { - opt if bool::from(opt.is_some()) => opt.unwrap(), - _ => return Err(Error::FailedToConvertBytesToSecp256k1Fp), - }, - }; - - let r = match secp256k1::Fq::from_bytes(&r) { - opt if bool::from(opt.is_some()) => opt.unwrap(), - _ => return Err(Error::FailedToConvertBytesToSecp256k1Fq), - }; - let s = match secp256k1::Fq::from_bytes(&s) { - opt if bool::from(opt.is_some()) => opt.unwrap(), - _ => return Err(Error::FailedToConvertBytesToSecp256k1Fq), - }; - - let msg_hash = match secp256k1::Fq::from_bytes(&msg_hash) { - opt if bool::from(opt.is_some()) => opt.unwrap(), - _ => return Err(Error::FailedToConvertBytesToSecp256k1Fq), - }; - - Ok(SignData { - signature: (r, s, v), - pk, - msg: msg.into(), - msg_hash, - }) -} - -#[derive(Clone)] -pub struct SignatureChipConfig { - challenges: Challenges, - sig_circuit_config: SigCircuitConfig, -} - -impl SignatureChipConfig { - pub fn configure(meta: &mut ConstraintSystem) -> Self { - let keccak_table = KeccakTable::construct(meta); - let sig_table = SigTable::construct(meta); - let challenges = Challenges::construct(meta); - let challenges_exprs = challenges.exprs(meta); - - let sig_circuit_config = SigCircuitConfig::new( - meta, - SigCircuitConfigArgs { - keccak_table, - sig_table, - challenges: challenges_exprs, - }, - ); - - Self { - challenges, - sig_circuit_config, - } - } -} - -pub struct SignatureChip { - config: SignatureChipConfig, -} - -impl SignatureChip { - pub fn construct(config: SignatureChipConfig) -> Self { - Self { config } - } - - fn keccak_inputs_sign_verify(&self, sigs: &[SignData]) -> Vec> { - let mut inputs = Vec::new(); - let dummy_sign_data = SignData::default(); - - for sig in sigs.iter().chain(std::iter::once(&dummy_sign_data)) { - let pk_le = pk_bytes_le(&sig.pk); - let pk_be = pk_bytes_swap_endianness(&pk_le); - inputs.push(pk_be.to_vec()); - inputs.push(sig.msg.to_vec()); - } - - inputs - } - - pub fn verify( - &self, - layouter: &mut impl Layouter, - signatures: &[SignData], - ) -> Result>, plonk::Error> { - let sig_circuit = zkevm_circuits::sig_circuit::SigCircuit:: { - max_verif: signatures.len(), - signatures: signatures.to_vec(), - _marker: PhantomData, - }; - - let challenges_values = self.config.challenges.values(layouter); - - self.config - .sig_circuit_config - .ecdsa_config - .load_lookup_table(layouter)?; - - let assigned = sig_circuit.assign( - &self.config.sig_circuit_config, - layouter, - &sig_circuit.signatures, - &challenges_values, - )?; - - self.config.sig_circuit_config.keccak_table.dev_load( - layouter, - &self.keccak_inputs_sign_verify(signatures), - &challenges_values, - )?; - - Ok(assigned) - } -} - -#[cfg(test)] -mod tests { - use std::marker::PhantomData; - - use ::secp256k1::{ - ecdsa::RecoverableSignature, rand::SeedableRng, Message, PublicKey, Secp256k1, SecretKey, - }; - use eth_types::{ - sign_types::{biguint_to_32bytes_le, SignData}, - Field, - }; - use halo2_base::halo2_proofs::{ - circuit::SimpleFloorPlanner, - dev::MockProver, - halo2curves::bn256, - plonk::{Circuit, Column, Instance}, - }; - use halo2_ecc::fields::PrimeField; - use num_bigint::BigUint; - use sha3::{Digest, Keccak256}; - - use crate::util::decompose_to_limbs; - - use super::*; - - #[derive(Default)] - struct SignatureCircuit { - signatures: Vec, - _marker: PhantomData, - } - - impl SignatureCircuit { - pub fn new(signatures: Vec) -> Self { - Self { - signatures, - _marker: PhantomData, - } - } - } - - impl SignatureCircuit { - pub fn public_inputs(&self) -> Vec { - let mut public_inputs = Vec::new(); - - for sign_data in &self.signatures { - let msg_hash_big = BigUint::from_bytes_le(&sign_data.msg_hash.to_bytes()); - for limb in decompose_to_limbs(msg_hash_big, 3, 88) - .into_iter() - .map(|b| bn256::Fr::from_bytes(&biguint_to_32bytes_le(b))) - { - public_inputs.push(limb.unwrap()); - } - } - - public_inputs - } - } - - impl Circuit for SignatureCircuit { - type Config = (Column, SignatureChipConfig); - - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { - let fixed_column = meta.fixed_column(); - meta.enable_constant(fixed_column); - - let msg_hash_instance = meta.instance_column(); - meta.enable_equality(msg_hash_instance); - - (msg_hash_instance, SignatureChipConfig::configure(meta)) - } - - fn synthesize( - &self, - (msg_hash_instance, config): Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), plonk::Error> { - let sig_chip = SignatureChip::construct(config); - - let verified_sigs = sig_chip.verify(&mut layouter, &self.signatures)?; - - let msg_hash = verified_sigs[0].assigned_ecdsa.msg_hash.limbs(); - for (i, limb) in msg_hash.iter().enumerate() { - layouter.constrain_instance(limb.cell, msg_hash_instance, i)?; - } - - layouter.assign_region( - || "check sig_is_valid = 1", - |mut region| { - region.constrain_constant(verified_sigs[0].sig_is_valid.cell(), F::one())?; - - Ok(()) - }, - )?; - - Ok(()) - } - } - - fn generate_signature( - message_str: &str, - ) -> (PublicKey, SecretKey, RecoverableSignature, [u8; 32]) { - let secp = Secp256k1::new(); - let (secret_key, public_key) = secp.generate_keypair( - &mut ::secp256k1::rand::prelude::SmallRng::from_seed([0u8; 32]), - ); - - let message_bytes = message_str.as_bytes(); - - let mut hasher = Keccak256::new(); - hasher.update(message_bytes); - let hash = hasher.finalize(); - - let message = Message::from_digest_slice(&hash).expect("32 bytes"); - let signature = secp.sign_ecdsa_recoverable(&message, &secret_key); - - (public_key, secret_key, signature, hash.into()) - } - - #[test] - fn verify_sig_in_circuit() { - let msg = "hello world"; - let (pk, _sk, sig, msg_hash) = generate_signature(msg); - let sign_data = convert_sig_to_sign_data(sig, msg, pk, msg_hash).unwrap(); - let signatures = vec![sign_data]; - - let circuit = SignatureCircuit::::new(signatures); - let prover = - MockProver::::run(20, &circuit, vec![circuit.public_inputs()]).unwrap(); - prover.assert_satisfied(); - } -} diff --git a/pkg/zk-circuits/src/chips/swap.rs b/pkg/zk-circuits/src/chips/swap.rs deleted file mode 100644 index 4bbd645..0000000 --- a/pkg/zk-circuits/src/chips/swap.rs +++ /dev/null @@ -1,304 +0,0 @@ -//! Gadget and chip for a conditional swap utility. -use halo2_base::halo2_proofs::{ - arithmetic::FieldExt, - circuit::{AssignedCell, Layouter, Region, Value}, - plonk::{Advice, Column, ConstraintSystem, Constraints, Error, Selector}, - poly::Rotation, -}; -use halo2_gadgets::utilities::{bool_check, ternary}; -use std::marker::PhantomData; - -/// A chip implementing a conditional swap. -#[derive(Clone, Debug)] -pub struct CondSwapChip { - config: CondSwapConfig, - _marker: PhantomData, -} - -impl CondSwapChip { - #[allow(clippy::type_complexity)] - pub fn swap( - &self, - mut layouter: impl Layouter, - pair: (&AssignedCell, Value), - swap: Value, - ) -> Result<(AssignedCell, AssignedCell), Error> { - let config = &self.config; - layouter.assign_region( - || "swap", - |mut region| { - // Copy in `a` value - let a = pair.0.copy_advice(|| "copy a", &mut region, config.a, 0)?; - - // Witness `b` value - let b = region.assign_advice(|| "witness b", config.b, 0, || pair.1)?; - - // Witness `swap` value - let swap = region.assign_advice(|| "swap", config.swap, 0, || swap)?; - - self.swap_in_region(region, a, b, swap) - }, - ) - } - - #[allow(clippy::type_complexity)] - pub fn swap_assigned( - &self, - mut layouter: impl Layouter, - pair: (&AssignedCell, &AssignedCell), - swap: &AssignedCell, - ) -> Result<(AssignedCell, AssignedCell), Error> { - let config = &self.config; - layouter.assign_region( - || "swap assigned", - |mut region| { - // Copy in `a` value - let a = pair.0.copy_advice(|| "copy a", &mut region, config.a, 0)?; - - // Copy in `b` value - let b = pair.1.copy_advice(|| "copy b", &mut region, config.b, 0)?; - - // Witness `swap` value - let swap = swap.copy_advice(|| "swap value", &mut region, config.swap, 0)?; - - self.swap_in_region(region, a, b, swap) - }, - ) - } - - #[allow(clippy::type_complexity)] - pub fn swap_in_region( - &self, - mut region: Region, - a: AssignedCell, - b: AssignedCell, - swap: AssignedCell, - ) -> Result<(AssignedCell, AssignedCell), Error> { - let config = &self.config; - // Enable `q_swap` selector - config.q_swap.enable(&mut region, 0)?; - - // Conditionally swap a - let a_swapped = { - let a_swapped = a - .value() - .zip(b.value()) - .zip(swap.value()) - .map(|((a, b), swap)| if *swap == F::one() { b } else { a }) - .cloned(); - region.assign_advice(|| "a_swapped", config.a_swapped, 0, || a_swapped)? - }; - - // Conditionally swap b - let b_swapped = { - let b_swapped = a - .value() - .zip(b.value()) - .zip(swap.value()) - .map(|((a, b), swap)| if *swap == F::one() { a } else { b }) - .cloned(); - region.assign_advice(|| "b_swapped", config.b_swapped, 0, || b_swapped)? - }; - - // Return swapped pair - Ok((a_swapped, b_swapped)) - } -} - -/// Configuration for the [`CondSwapChip`]. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct CondSwapConfig { - q_swap: Selector, - a: Column, - b: Column, - a_swapped: Column, - b_swapped: Column, - swap: Column, -} - -impl CondSwapChip { - /// Configures this chip for use in a circuit. - /// - /// # Side-effects - /// - /// `advices[0]` will be equality-enabled. - pub fn configure( - meta: &mut ConstraintSystem, - advices: [Column; 5], - ) -> CondSwapConfig { - let q_swap = meta.selector(); - - let config = CondSwapConfig { - q_swap, - a: advices[0], - b: advices[1], - a_swapped: advices[2], - b_swapped: advices[3], - swap: advices[4], - }; - - meta.enable_equality(config.a); - meta.enable_equality(config.b); - meta.enable_equality(config.swap); - - // TODO: optimise shape of gate for Merkle path validation - - meta.create_gate("a' = b ⋅ swap + a ⋅ (1-swap)", |meta| { - let q_swap = meta.query_selector(q_swap); - - let a = meta.query_advice(config.a, Rotation::cur()); - let b = meta.query_advice(config.b, Rotation::cur()); - let a_swapped = meta.query_advice(config.a_swapped, Rotation::cur()); - let b_swapped = meta.query_advice(config.b_swapped, Rotation::cur()); - let swap = meta.query_advice(config.swap, Rotation::cur()); - - // This checks that `a_swapped` is equal to `b` when `swap` is set, - // but remains as `a` when `swap` is not set. - let a_check = a_swapped - ternary(swap.clone(), b.clone(), a.clone()); - - // This checks that `b_swapped` is equal to `a` when `swap` is set, - // but remains as `b` when `swap` is not set. - let b_check = b_swapped - ternary(swap.clone(), a, b); - - // Check `swap` is boolean. - let bool_check = bool_check(swap); - - Constraints::with_selector( - q_swap, - [ - ("a check", a_check), - ("b check", b_check), - ("swap is bool", bool_check), - ], - ) - }); - - config - } - - /// Constructs a [`CondSwapChip`] given a [`CondSwapConfig`]. - pub fn construct(config: CondSwapConfig) -> Self { - CondSwapChip { - config, - _marker: PhantomData, - } - } -} - -#[cfg(test)] -mod tests { - use crate::util::assign_private_input; - - use super::{CondSwapChip, CondSwapConfig}; - use halo2_base::halo2_proofs::{ - arithmetic::Field, - circuit::{Layouter, SimpleFloorPlanner, Value}, - dev::MockProver, - halo2curves::{bn256::Fr, FieldExt}, - plonk::{Circuit, ConstraintSystem, Error}, - }; - use rand::rngs::OsRng; - - #[test] - fn cond_swap() { - #[derive(Default)] - struct MyCircuit { - a: Value, - b: Value, - swap: Value, - } - - impl Circuit for MyCircuit { - type Config = CondSwapConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - CondSwapChip::::configure(meta, advices) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let chip = CondSwapChip::::construct(config.clone()); - - // Load the pair and the swap flag into the circuit. - // let a = chip.load_private(layouter.namespace(|| "a"), config.a, self.a)?; - let a = assign_private_input( - || "assign a", - layouter.namespace(|| "assign a"), - config.a, - self.a, - )?; - let b = assign_private_input( - || "assign b", - layouter.namespace(|| "assign b"), - config.b, - self.b, - )?; - let swap = assign_private_input( - || "assign swap", - layouter.namespace(|| "assign swap"), - config.a, - self.swap, - )?; - - // Return the swapped pair. - let swapped_pair = - chip.swap_assigned(layouter.namespace(|| "swap"), (&a, &b), &swap)?; - - self.swap - .zip(a.value().zip(self.b.as_ref())) - .zip(swapped_pair.0.value().zip(swapped_pair.1.value())) - .assert_if_known(|((swap, (a, b)), (a_swapped, b_swapped))| { - if *swap == F::one() { - // Check that `a` and `b` have been swapped - (a_swapped == b) && (b_swapped == a) - } else { - // Check that `a` and `b` have not been swapped - (a_swapped == a) && (b_swapped == b) - } - }); - - Ok(()) - } - } - - let rng = OsRng; - - // Test swap case - { - let circuit: MyCircuit = MyCircuit { - a: Value::known(Fr::random(rng)), - b: Value::known(Fr::random(rng)), - swap: Value::known(Fr::one()), - }; - let prover = MockProver::::run(4, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - - // Test non-swap case - { - let circuit: MyCircuit = MyCircuit { - a: Value::known(Fr::random(rng)), - b: Value::known(Fr::random(rng)), - swap: Value::known(Fr::zero()), - }; - let prover = MockProver::::run(4, &circuit, vec![]).unwrap(); - assert_eq!(prover.verify(), Ok(())); - } - } -} diff --git a/pkg/zk-circuits/src/circuits/agg_agg.rs b/pkg/zk-circuits/src/circuits/agg_agg.rs new file mode 100644 index 0000000..6246a8b --- /dev/null +++ b/pkg/zk-circuits/src/circuits/agg_agg.rs @@ -0,0 +1,108 @@ +use super::conversions::impl_circuit_proof_conversions; +use super::generated::agg_agg::{ + AggAggInput, AggAggPublicInputs as CircuitAggAggPublicInputs, Aggproof as CircuitAggProofInput, +}; +use crate::circuits::Proof; +use crate::{Prove, Result, Verify}; +use element::Element; +use zk_primitives::{AggAgg, AggAggProof, AggAggPublicInput, AggProof}; + +impl From for CircuitAggProofInput { + fn from(value: AggProof) -> Self { + match value { + AggProof::AggUtxo(proof) => { + let proof_fields = proof.proof.to_fields(); + + Self { + proof: std::array::from_fn(|idx| proof_fields[idx]), + old_root: proof.public_inputs.old_root, + new_root: proof.public_inputs.new_root, + commit_hash: proof.public_inputs.commit_hash, + messages: proof.public_inputs.messages, + verification_key: std::array::from_fn(|idx| { + Element::from(super::generated::agg_utxo::VERIFICATION_KEY[idx]) + }), + verification_key_hash: Element::from( + *super::generated::agg_utxo::VERIFICATION_KEY_HASH, + ), + } + } + AggProof::AggAgg(proof) => { + let proof_fields = proof.proof.to_fields(); + + Self { + proof: std::array::from_fn(|idx| proof_fields[idx]), + old_root: proof.public_inputs.old_root, + new_root: proof.public_inputs.new_root, + commit_hash: proof.public_inputs.commit_hash, + messages: proof.public_inputs.messages, + verification_key: std::array::from_fn(|idx| { + Element::from(super::generated::agg_agg::VERIFICATION_KEY[idx]) + }), + verification_key_hash: Element::from( + *super::generated::agg_agg::VERIFICATION_KEY_HASH, + ), + } + } + } + } +} + +impl From for AggAggInput { + fn from(agg_agg: AggAgg) -> Self { + let old_root = agg_agg.old_root(); + let new_root = agg_agg.new_root(); + let commit_hash = agg_agg.commit_hash(); + let messages = agg_agg.messages(); + let AggAgg { proofs } = agg_agg; + + Self { + proofs: proofs.map(CircuitAggProofInput::from), + verification_key_hash: [ + Element::from(*super::generated::agg_utxo::VERIFICATION_KEY_HASH), + Element::from(*super::generated::agg_agg::VERIFICATION_KEY_HASH), + ], + old_root, + new_root, + commit_hash, + messages, + } + } +} + +impl_circuit_proof_conversions!( + AggAggPublicInput, + CircuitAggAggPublicInputs, + AggAggProof, + Proof, + [ + verification_key_hash, + old_root, + new_root, + commit_hash, + messages + ], + [kzg: vec![]] +); + +#[async_trait::async_trait] +impl Prove for AggAgg { + type Proof = AggAggProof; + + async fn prove( + &self, + bb_backend: &dyn barretenberg_interface::BbBackend, + ) -> Result { + let input = AggAggInput::from(self.clone()); + let proof = input.prove(bb_backend).await?; + Ok(proof.into()) + } +} + +#[async_trait::async_trait] +impl Verify for AggAggProof { + async fn verify(&self, bb_backend: &dyn barretenberg_interface::BbBackend) -> Result<()> { + let proof = Proof::from(self.clone()); + proof.verify(bb_backend).await + } +} diff --git a/pkg/zk-circuits/src/circuits/agg_final.rs b/pkg/zk-circuits/src/circuits/agg_final.rs new file mode 100644 index 0000000..80f6934 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/agg_final.rs @@ -0,0 +1,97 @@ +use element::Element; +use zk_primitives::{AggFinal, AggFinalProof, AggFinalPublicInput, OracleProofBytes}; + +use super::generated::agg_final::{ + AggFinalInput, AggFinalPublicInputs as CircuitAggFinalPublicInputs, +}; +use crate::circuits::Proof; +use crate::{Prove, Result, Verify}; + +fn messages_vec_to_array(messages: Vec) -> [Element; 1000] { + let mut array = [Element::ZERO; 1000]; + let len = messages.len().min(array.len()); + array[..len].copy_from_slice(&messages[..len]); + array +} + +impl From for AggFinalInput { + fn from(agg_final: AggFinal) -> Self { + let AggFinal { proof } = agg_final; + let proof_fields = proof.proof.to_fields(); + + Self { + verification_key: std::array::from_fn(|idx| { + Element::from(super::generated::agg_agg::VERIFICATION_KEY[idx]) + }), + verification_key_hash: Element::from(*super::generated::agg_agg::VERIFICATION_KEY_HASH), + proof: std::array::from_fn(|idx| proof_fields[idx]), + commit_hash: proof.public_inputs.commit_hash, + old_root: proof.public_inputs.old_root, + new_root: proof.public_inputs.new_root, + messages: proof.public_inputs.messages, + } + } +} + +impl From for AggFinalPublicInput { + fn from(value: CircuitAggFinalPublicInputs) -> Self { + Self { + old_root: value.old_root, + new_root: value.new_root, + commit_hash: value.commit_hash, + messages: value.messages.to_vec(), + } + } +} + +impl From for CircuitAggFinalPublicInputs { + fn from(value: AggFinalPublicInput) -> Self { + Self { + old_root: value.old_root, + new_root: value.new_root, + commit_hash: value.commit_hash, + messages: messages_vec_to_array(value.messages), + } + } +} + +impl From> for AggFinalProof { + fn from(value: Proof) -> Self { + Self { + proof: OracleProofBytes(value.proof), + public_inputs: value.public_inputs.into(), + kzg: vec![], + } + } +} + +impl From for Proof { + fn from(value: AggFinalProof) -> Self { + Self { + proof: value.proof.0, + public_inputs: value.public_inputs.into(), + } + } +} + +#[async_trait::async_trait] +impl Prove for AggFinal { + type Proof = AggFinalProof; + + async fn prove( + &self, + bb_backend: &dyn barretenberg_interface::BbBackend, + ) -> Result { + let input = AggFinalInput::from(self.clone()); + let proof = input.prove(bb_backend).await?; + Ok(proof.into()) + } +} + +#[async_trait::async_trait] +impl Verify for AggFinalProof { + async fn verify(&self, bb_backend: &dyn barretenberg_interface::BbBackend) -> Result<()> { + let proof = Proof::from(self.clone()); + proof.verify(bb_backend).await + } +} diff --git a/pkg/zk-circuits/src/circuits/agg_utxo.rs b/pkg/zk-circuits/src/circuits/agg_utxo.rs new file mode 100644 index 0000000..1208009 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/agg_utxo.rs @@ -0,0 +1,108 @@ +use element::Element; +use zk_primitives::{AggUtxo, AggUtxoProof, AggUtxoPublicInput, UtxoProofBundleWithMerkleProofs}; + +use crate::circuits::Proof; +use crate::{Prove, Result, Verify}; + +use super::UTXO_VERIFICATION_KEY; +use super::conversions::impl_circuit_proof_conversions; +use super::generated::agg_utxo::{ + AggUtxoInput, AggUtxoPublicInputs as CircuitAggUtxoPublicInputs, + Aggutxoproofinput as CircuitAggUtxoProofInput, +}; + +impl From for CircuitAggUtxoProofInput { + fn from(value: UtxoProofBundleWithMerkleProofs) -> Self { + let UtxoProofBundleWithMerkleProofs { + utxo_proof, + input_merkle_paths, + output_merkle_paths, + } = value; + + let proof_fields = utxo_proof.proof.to_fields(); + + let input_merkle_paths = input_merkle_paths.map(|path| { + let siblings = path.siblings; + std::array::from_fn(|idx| siblings[idx]) + }); + + let output_merkle_paths = output_merkle_paths.map(|path| { + let siblings = path.siblings; + std::array::from_fn(|idx| siblings[idx]) + }); + + Self { + proof: std::array::from_fn(|idx| proof_fields[idx]), + utxo_kind: utxo_proof.kind().to_element(), + input_merkle_paths, + output_merkle_paths, + input_commitments: utxo_proof.public_inputs.input_commitments, + output_commitments: utxo_proof.public_inputs.output_commitments, + } + } +} + +impl From for AggUtxoInput { + fn from(agg_utxo: AggUtxo) -> Self { + let commit_hash = agg_utxo.commit_hash(); + let messages = agg_utxo.messages(); + + let AggUtxo { + proofs, + old_root, + new_root, + } = agg_utxo; + + let verification_key = + std::array::from_fn(|idx| Element::from(UTXO_VERIFICATION_KEY.0[idx])); + + Self { + verification_key, + proofs: proofs.map(CircuitAggUtxoProofInput::from), + verification_key_hash: [ + Element::from(*super::generated::agg_utxo::VERIFICATION_KEY_HASH), + Element::from(*super::generated::agg_agg::VERIFICATION_KEY_HASH), + ], + old_root, + new_root, + commit_hash, + messages, + } + } +} + +impl_circuit_proof_conversions!( + AggUtxoPublicInput, + CircuitAggUtxoPublicInputs, + AggUtxoProof, + Proof, + [ + verification_key_hash, + old_root, + new_root, + commit_hash, + messages + ] +); + +#[async_trait::async_trait] +impl Prove for AggUtxo { + type Proof = AggUtxoProof; + + async fn prove( + &self, + bb_backend: &dyn barretenberg_interface::BbBackend, + ) -> Result { + let input = AggUtxoInput::from(self.clone()); + let proof = ::prove(&input, bb_backend).await?; + Ok(proof.into()) + } +} + +#[async_trait::async_trait] +impl Verify for AggUtxoProof { + async fn verify(&self, bb_backend: &dyn barretenberg_interface::BbBackend) -> Result<()> { + let proof = Proof::from(self.clone()); + proof.verify(bb_backend).await + } +} diff --git a/pkg/zk-circuits/src/circuits/conversions.rs b/pkg/zk-circuits/src/circuits/conversions.rs new file mode 100644 index 0000000..673e849 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/conversions.rs @@ -0,0 +1,70 @@ +macro_rules! impl_circuit_proof_conversions { + ( + $primitive_public_inputs:ty, + $circuit_public_inputs:ty, + $primitive_proof:ty, + $circuit_proof:ty, + [$($field:ident),+ $(,)?] + ) => { + impl_circuit_proof_conversions!( + $primitive_public_inputs, + $circuit_public_inputs, + $primitive_proof, + $circuit_proof, + [$($field),+], + [] + ); + }; + + ( + $primitive_public_inputs:ty, + $circuit_public_inputs:ty, + $primitive_proof:ty, + $circuit_proof:ty, + [$($field:ident),+ $(,)?], + [$($proof_extra_field:ident : $proof_extra_value:expr),* $(,)?] + ) => { + impl From<$circuit_public_inputs> for $primitive_public_inputs { + fn from(value: $circuit_public_inputs) -> Self { + Self { + $( + $field: value.$field, + )+ + } + } + } + + impl From<$primitive_public_inputs> for $circuit_public_inputs { + fn from(value: $primitive_public_inputs) -> Self { + Self { + $( + $field: value.$field, + )+ + } + } + } + + impl From<$circuit_proof> for $primitive_proof { + fn from(value: $circuit_proof) -> Self { + Self { + proof: zk_primitives::ProofBytes(value.proof), + public_inputs: value.public_inputs.into(), + $( + $proof_extra_field: $proof_extra_value, + )* + } + } + } + + impl From<$primitive_proof> for $circuit_proof { + fn from(value: $primitive_proof) -> Self { + Self { + proof: value.proof.0, + public_inputs: value.public_inputs.into(), + } + } + } + }; +} + +pub(crate) use impl_circuit_proof_conversions; diff --git a/pkg/zk-circuits/src/circuits/migrate.rs b/pkg/zk-circuits/src/circuits/migrate.rs new file mode 100644 index 0000000..eeb96cb --- /dev/null +++ b/pkg/zk-circuits/src/circuits/migrate.rs @@ -0,0 +1,30 @@ +use zk_primitives::{Migrate, MigrateProof, MigratePublicInput}; + +use crate::circuits::Proof; + +use super::conversions::impl_circuit_proof_conversions; +use super::generated::migrate::{MigrateInput, MigratePublicInputs as CircuitMigratePublicInputs}; + +impl From for MigrateInput { + fn from(migrate: Migrate) -> Self { + let Migrate { + owner_pk, + old_address, + new_address, + } = migrate; + + MigrateInput { + owner_pk, + old_address, + new_address, + } + } +} + +impl_circuit_proof_conversions!( + MigratePublicInput, + CircuitMigratePublicInputs, + MigrateProof, + Proof, + [old_address, new_address] +); diff --git a/pkg/zk-circuits/src/circuits/mod.rs b/pkg/zk-circuits/src/circuits/mod.rs new file mode 100644 index 0000000..a8a7896 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/mod.rs @@ -0,0 +1,131 @@ +use std::io::Read; + +use acvm::AcirField; +use async_trait::async_trait; +use base64::Engine; +use element::Base; +use flate2::read::GzDecoder; + +mod agg_agg; +mod agg_final; +mod agg_utxo; +mod conversions; +mod migrate; +pub mod note_v2; +mod notes; +mod points; +mod proc_macro_interface; +mod proof; +mod signature; +#[cfg(test)] +mod tests; +mod utxo; + +pub use proof::Proof; +pub use utxo::*; + +use crate::{ + Prove, Result, + circuits::proc_macro_interface::{ProofInputs, PublicInputs}, + prove::prove, +}; + +#[async_trait] +impl Prove for T +where + T::PublicInputs: Send + Sync, + T: Send + Sync, +{ + type Proof = Proof; + async fn prove( + &self, + bb_backend: &dyn barretenberg_interface::BbBackend, + ) -> Result { + let inputs = self.input_map(); + let proof_bytes = prove( + bb_backend, + self.compiled_program(), + Self::PROGRAM.as_bytes(), + self.bytecode(), + Self::KEY, + &inputs, + T::PublicInputs::ORACLE_HASH_KECCAK, + ) + .await?; + Ok(Proof::from_raw_proof_bytes(proof_bytes)) + } +} + +macro_rules! generate_inputs { + ($fixture_path:literal, $mod:ident) => { + generate_inputs!($fixture_path, $mod, false); + }; + ($fixture_path:literal, $mod:ident, $oracle_keccak:literal) => { + noir_abi_inputs_macro::noir_abi_inputs!($fixture_path, $mod, $oracle_keccak, crate::circuits::proc_macro_interface); + + paste::paste!( + pub struct [<$mod:camel Circuit>]; + + #[async_trait::async_trait] + impl $crate::Circuit<$mod::[<$mod:camel Input>], super::Proof<$mod::[<$mod:camel PublicInputs>]>> for [<$mod:camel Circuit>] { + async fn prove( + &self, + input: &$mod::[<$mod:camel Input>], + bb_backend: std::sync::Arc, + ) -> $crate::Result]>> { + let _ = self; + <$mod::[<$mod:camel Input>] as $crate::Prove>::prove(input, bb_backend.as_ref()).await + } + } + + pub trait [<$mod:camel CircuitInterface>]: $crate::Circuit<$mod::[<$mod:camel Input>], super::Proof<$mod::[<$mod:camel PublicInputs>]>> {} + + impl [<$mod:camel CircuitInterface>] for T + where + T: $crate::Circuit<$mod::[<$mod:camel Input>], super::Proof<$mod::[<$mod:camel PublicInputs>]>> + {} + ); + }; +} + +// CI treats warnings as errors; remove to surface duplicate-struct warnings. +#[allow(deprecated)] +pub mod generated { + noir_abi_inputs_macro::noir_abi_shared_structs!( + "../../fixtures/circuits", + crate::circuits::proc_macro_interface + ); + generate_inputs!("../../fixtures/circuits/agg_agg", agg_agg); + generate_inputs!("../../fixtures/circuits/agg_final", agg_final, true); + generate_inputs!("../../fixtures/circuits/agg_utxo", agg_utxo); + generate_inputs!("../../fixtures/circuits/migrate", migrate); + generate_inputs!("../../fixtures/circuits/points", points); + generate_inputs!("../../fixtures/circuits/signature", signature); + generate_inputs!("../../fixtures/circuits/utxo", utxo); + generate_inputs!("../../fixtures/circuits/erc20_transfer", erc20_transfer); + generate_inputs!("../../fixtures/circuits/transfer", transfer); + generate_inputs!("../../fixtures/circuits/mint", mint); + generate_inputs!("../../fixtures/circuits/burn", burn); +} + +pub fn get_bytecode_from_program(program_json: &str) -> Vec { + let mut program = serde_json::from_str::(program_json).unwrap(); + let bytecode_base64 = program.get_mut("bytecode").unwrap().as_str().unwrap(); + let bytecode_gzipped = base64::engine::general_purpose::STANDARD + .decode(bytecode_base64) + .unwrap(); + let mut decoder = GzDecoder::new(&bytecode_gzipped[..]); + let mut bytecode = Vec::new(); + decoder.read_to_end(&mut bytecode).unwrap(); + + bytecode +} + +pub fn parse_key_fields(key_fields_json: &[u8]) -> Vec { + let fields = serde_json::from_slice::>(key_fields_json).unwrap(); + + fields + .into_iter() + .map(|field| Base::from_hex(&field).unwrap()) + .collect() +} diff --git a/pkg/zk-circuits/src/circuits/note.rs b/pkg/zk-circuits/src/circuits/note.rs new file mode 100644 index 0000000..509ac8d --- /dev/null +++ b/pkg/zk-circuits/src/circuits/note.rs @@ -0,0 +1,59 @@ +use element::Base; +use noirc_abi::input_parser::InputValue; +use std::collections::BTreeMap; +use zk_primitives::{InputNote, Note}; + +#[derive(Debug, Clone)] +pub struct BInputNote { + pub note: BNote, + pub secret_key: Base, +} + +impl From<&InputNote> for BInputNote { + fn from(note: &InputNote) -> Self { + BInputNote { + note: BNote::from(¬e.note), + secret_key: note.secret_key.to_base(), + } + } +} + +impl From for InputValue { + fn from(note: BInputNote) -> Self { + InputValue::Struct(BTreeMap::from([ + ("note".to_owned(), note.note.into()), + ("secret_key".to_owned(), InputValue::Field(note.secret_key)), + ])) + } +} +#[derive(Debug, Clone)] +pub struct BNote { + pub kind: Base, + pub value: Base, + pub address: Base, + pub psi: Base, +} + +impl From<&Note> for BNote { + fn from(note: &Note) -> Self { + BNote { + kind: note.contract.to_base(), + value: note.value.to_base(), + address: note.address.to_base(), + psi: note.psi.to_base(), + } + } +} + +impl From for InputValue { + fn from(note: BNote) -> Self { + let mut struct_ = BTreeMap::new(); + + struct_.insert("kind".to_owned(), InputValue::Field(note.kind)); + struct_.insert("value".to_owned(), InputValue::Field(note.value)); + struct_.insert("address".to_owned(), InputValue::Field(note.address)); + struct_.insert("psi".to_owned(), InputValue::Field(note.psi)); + + InputValue::Struct(struct_) + } +} diff --git a/pkg/zk-circuits/src/circuits/note_v2.rs b/pkg/zk-circuits/src/circuits/note_v2.rs new file mode 100644 index 0000000..c32f42f --- /dev/null +++ b/pkg/zk-circuits/src/circuits/note_v2.rs @@ -0,0 +1,29 @@ +//! Utilities for handling Payy V2 Notes + +use element::Element; + +use crate::circuits::generated::erc20_transfer::Note; + +pub fn hash_note(note: &Note) -> Element { + let &Note { + kind, + address, + token, + value, + psi, + } = note; + hash::hash_merge([ + kind, + address_to_element(address), + address_to_element(token), + value, + psi, + ]) +} + +/// Helper to convert 20-byte address to Element +fn address_to_element(addr: [u8; 20]) -> Element { + let mut bytes = [0u8; 32]; + bytes[12..32].copy_from_slice(&addr); + Element::from_be_bytes(bytes) +} diff --git a/pkg/zk-circuits/src/circuits/notes.rs b/pkg/zk-circuits/src/circuits/notes.rs new file mode 100644 index 0000000..2491f6b --- /dev/null +++ b/pkg/zk-circuits/src/circuits/notes.rs @@ -0,0 +1,42 @@ +use super::generated::submodules::common::Inputnote as CommonInputNote; +use super::generated::submodules::common::Note as CommonNote; + +impl From for CommonNote { + fn from(note: zk_primitives::Note) -> Self { + CommonNote { + kind: note.contract, + value: note.value, + address: note.address, + psi: note.psi, + } + } +} + +impl From for CommonInputNote { + fn from(note: zk_primitives::InputNote) -> Self { + CommonInputNote { + note: note.note.into(), + secret_key: note.secret_key, + } + } +} + +impl From<&zk_primitives::InputNote> for CommonInputNote { + fn from(note: &zk_primitives::InputNote) -> Self { + CommonInputNote { + note: (¬e.note).into(), + secret_key: note.secret_key, + } + } +} + +impl From<&zk_primitives::Note> for CommonNote { + fn from(note: &zk_primitives::Note) -> Self { + CommonNote { + kind: note.contract, + value: note.value, + address: note.address, + psi: note.psi, + } + } +} diff --git a/pkg/zk-circuits/src/circuits/points.rs b/pkg/zk-circuits/src/circuits/points.rs new file mode 100644 index 0000000..2e49bf1 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/points.rs @@ -0,0 +1,39 @@ +// lint-long-file-override allow-max-lines=300 +use zk_primitives::{Points, PointsProof, PointsPublicInput}; + +use crate::circuits::Proof; + +use super::conversions::impl_circuit_proof_conversions; +use super::generated::points::{PointsInput, PointsPublicInputs as CircuitPointsPublicInputs}; +use super::generated::submodules::common::Note as CommonNote; + +impl From for PointsInput { + fn from(points: Points) -> Self { + let Points { + secret_keys, + notes, + timestamp, + address, + } = points; + let value = notes.each_ref().map(|note| note.value).into_iter().sum(); + let commitments = notes.each_ref().map(zk_primitives::Note::commitment); + + PointsInput { + secret_keys, + notes: notes.map(CommonNote::from), + timestamp, + address, + value, + hash: hash::hash_merge([timestamp, address]), + commitments, + } + } +} + +impl_circuit_proof_conversions!( + PointsPublicInput, + CircuitPointsPublicInputs, + PointsProof, + Proof, + [value, timestamp, hash, commitments] +); diff --git a/pkg/zk-circuits/src/circuits/proc_macro_interface.rs b/pkg/zk-circuits/src/circuits/proc_macro_interface.rs new file mode 100644 index 0000000..bf602e2 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/proc_macro_interface.rs @@ -0,0 +1,171 @@ +//! Types and traits exposed to the `noir-abi-inputs-macro` proc-macro crate. +//! +//! The traits defined in this module are implemented by structs that +//! are generated from proof JSONs. + +use acvm::AcirField; +use std::fmt::Debug; + +pub use element::{Base, Element}; +use noirc_abi::InputMap; +use noirc_driver::CompiledProgram; + +pub trait ProofInputs { + const PROGRAM: &'static str; + const KEY: &'static [u8]; + fn bytecode(&self) -> &[u8]; + fn compiled_program(&self) -> &CompiledProgram; + + fn input_map(&self) -> InputMap; + + type PublicInputs: PublicInputs; +} + +pub trait PublicInputs: ToFields + FromFields { + const KEY: &'static [u8]; + const ORACLE_HASH_KECCAK: bool; +} + +pub trait ToFields { + fn to_fields(&self, out: &mut Vec); +} + +impl ToFields for Element { + fn to_fields(&self, out: &mut Vec) { + out.push(self.to_base()) + } +} + +impl ToFields for [T; N] { + fn to_fields(&self, out: &mut Vec) { + for x in self { + x.to_fields(out); + } + } +} + +pub trait FromFields { + const FIELD_COUNT: usize; + fn from_fields(iter: &mut impl Iterator) -> Self; +} + +impl FromFields for Element { + const FIELD_COUNT: usize = 1; + fn from_fields(iter: &mut impl Iterator) -> Self { + let base = iter.next().expect("not enough fields to unpack"); + Element::from_base(base) + } +} + +impl FromFields for [T; N] { + const FIELD_COUNT: usize = N * T::FIELD_COUNT; + + fn from_fields(iter: &mut impl Iterator) -> Self { + (0..N) + .map(|_| T::from_fields(iter)) + .collect::>() + .try_into() + .unwrap() + } +} + +// Boolean implementations +impl ToFields for bool { + fn to_fields(&self, out: &mut Vec) { + out.push(Base::from(*self as u64)); + } +} + +impl FromFields for bool { + const FIELD_COUNT: usize = 1; + + fn from_fields(iter: &mut impl Iterator) -> Self { + let base = iter.next().expect("not enough fields to unpack"); + !base.is_zero() + } +} + +// Integer implementations +pub trait IntToBase: Sized { + fn to_base(self) -> Base; + fn from_base(base: Base) -> Self; +} + +macro_rules! impl_int_to_base { + ($($ty:ty => $unsigned:ty),* $(,)?) => { + $( + impl IntToBase for $ty { + fn to_base(self) -> Base { + Base::from(self as $unsigned as u128) + } + + fn from_base(base: Base) -> Self { + (base.to_u128() as $unsigned) as $ty + } + } + )* + }; +} + +impl_int_to_base!( + u8 => u8, + i8 => u8, + u16 => u16, + i16 => u16, + u32 => u32, + i32 => u32, + u64 => u64, + i64 => u64, + u128 => u128, + i128 => u128, +); + +macro_rules! impl_to_from_fields_for_int { + ($($ty:ty),*) => { + $( + impl ToFields for $ty { + fn to_fields(&self, out: &mut Vec) { + out.push(IntToBase::to_base(*self)); + } + } + + impl FromFields for $ty { + const FIELD_COUNT: usize = 1; + + fn from_fields(iter: &mut impl Iterator) -> Self { + let base = iter.next().expect("not enough fields to unpack"); + IntToBase::from_base(base) + } + } + )* + }; +} + +impl_to_from_fields_for_int!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128); + +// Tuple implementations +macro_rules! impl_to_from_fields_for_tuple { + ($($idx:tt: $name:ident),*) => { + impl<$($name: ToFields),*> ToFields for ($($name,)*) { + fn to_fields(&self, out: &mut Vec) { + $(self.$idx.to_fields(out);)* + } + } + + impl<$($name: FromFields),*> FromFields for ($($name,)*) { + const FIELD_COUNT: usize = 0 $( + $name::FIELD_COUNT )*; + + fn from_fields(iter: &mut impl Iterator) -> Self { + ($($name::from_fields(iter),)*) + } + } + }; +} + +impl_to_from_fields_for_tuple!(0: A, 1: B); +impl_to_from_fields_for_tuple!(0: A, 1: B, 2: C); +impl_to_from_fields_for_tuple!(0: A, 1: B, 2: C, 3: D); +impl_to_from_fields_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E); +impl_to_from_fields_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F); +impl_to_from_fields_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G); +impl_to_from_fields_for_tuple!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H); diff --git a/pkg/zk-circuits/src/circuits/proof.rs b/pkg/zk-circuits/src/circuits/proof.rs new file mode 100644 index 0000000..f6e15cd --- /dev/null +++ b/pkg/zk-circuits/src/circuits/proof.rs @@ -0,0 +1,73 @@ +use acvm::AcirField; +use async_trait::async_trait; +use element::Base; + +use crate::{Result, Verify, circuits::proc_macro_interface::PublicInputs, verify::verify}; + +pub struct Proof { + pub proof: Vec, + pub public_inputs: PublicInputs, +} + +impl Proof

{ + pub fn from_raw_proof_bytes(raw_proof: Vec) -> Self { + assert!( + raw_proof.len() >= P::FIELD_COUNT * 32, + "proof bytes too short for public inputs" + ); + assert!( + raw_proof.len().is_multiple_of(32), + "proof bytes length must be a multiple of 32" + ); + + let public_inputs_bytes = &raw_proof[..P::FIELD_COUNT * 32]; + let proof = raw_proof[P::FIELD_COUNT * 32..].to_vec(); + let fields = bytes_to_bases(public_inputs_bytes); + let mut iter = fields.into_iter(); + let public_inputs = P::from_fields(&mut iter); + debug_assert!(iter.next().is_none(), "iterator should be exhausted"); + + Self { + proof, + public_inputs, + } + } +} + +fn bytes_to_bases(bytes: &[u8]) -> Vec { + assert!( + bytes.len().is_multiple_of(32), + "public input bytes length must be a multiple of 32" + ); + bytes + .chunks_exact(32) + .map(|chunk| { + let mut arr = [0u8; 32]; + arr.copy_from_slice(chunk); + Base::from_be_bytes_reduce(&arr) + }) + .collect() +} + +#[async_trait] +impl Verify for Proof

+where + Proof

: Send + Sync, +{ + async fn verify(&self, bb_backend: &dyn barretenberg_interface::BbBackend) -> Result<()> { + let mut fields = vec![]; + self.public_inputs.to_fields(&mut fields); + let public_inputs = fields + .into_iter() + .flat_map(|f| f.to_be_bytes()) + .collect::>(); + verify( + bb_backend, + P::KEY, + &self.proof, + &public_inputs, + P::ORACLE_HASH_KECCAK, + ) + .await + } +} diff --git a/pkg/zk-circuits/src/circuits/signature.rs b/pkg/zk-circuits/src/circuits/signature.rs new file mode 100644 index 0000000..7aa50f8 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/signature.rs @@ -0,0 +1,32 @@ +use zk_primitives::{Signature, SignatureProof, SignaturePublicInput, get_address_for_private_key}; + +use crate::circuits::Proof; + +use super::conversions::impl_circuit_proof_conversions; +use super::generated::signature::{ + SignatureInput, SignaturePublicInputs as CircuitSignaturePublicInputs, +}; + +impl From for SignatureInput { + fn from(signature: Signature) -> Self { + let Signature { + secret_key, + message, + } = signature; + + SignatureInput { + owner_pk: secret_key, + message_hash: hash::hash_merge([secret_key, message]), + address: get_address_for_private_key(secret_key), + message, + } + } +} + +impl_circuit_proof_conversions!( + SignaturePublicInput, + CircuitSignaturePublicInputs, + SignatureProof, + Proof, + [address, message] +); diff --git a/pkg/zk-circuits/src/circuits/tests.rs b/pkg/zk-circuits/src/circuits/tests.rs new file mode 100644 index 0000000..583a701 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/tests.rs @@ -0,0 +1,646 @@ +// lint-long-file-override allow-max-lines=700 +use barretenberg_api_client::ClientBackend; +use barretenberg_cli::CliBackend; +use barretenberg_rs::BindingBackend; +use element::Element; +use std::sync::OnceLock; +use tokio::sync::{Mutex, MutexGuard}; +use zk_primitives::{ + AggAgg, AggFinal, AggProof, AggUtxo, InputNote, MerklePath, Note, Utxo, UtxoKind, UtxoProof, + UtxoProofBundleWithMerkleProofs, bridged_polygon_usdc_note_kind, get_address_for_private_key, +}; + +use crate::{BbBackend, Prove, Result, Verify, circuits::Proof}; +use url::Url; + +mod erc_20; +mod migrate; +mod points; +mod signature; + +const API_BACKEND_ENV: &str = "BARRETENBERG_API_BASE_URL"; +const RS_BACKEND_ENV: &str = "BARRETENBERG_RS"; + +/// Used to ensure that only one BbBackend exists at once +/// in order to limit memory usage of the tests. +static TEST_BACKEND_LOCK: OnceLock>> = OnceLock::new(); + +async fn test_backend() -> MutexGuard<'static, Box> { + TEST_BACKEND_LOCK + .get_or_init(|| Mutex::new(test_backend_inner())) + .lock() + .await +} + +fn test_backend_inner() -> Box { + if std::env::var(RS_BACKEND_ENV).is_ok() { + return Box::new(BindingBackend); + } + + match std::env::var(API_BACKEND_ENV) { + Ok(value) => { + let trimmed = value.trim(); + if trimmed.is_empty() { + Box::new(CliBackend) + } else { + match Url::parse(trimmed) { + Ok(url) => match ClientBackend::new(url) { + Ok(client) => Box::new(client), + Err(err) => { + eprintln!( + "Failed to initialize API backend ({err}), falling back to CLI backend" + ); + Box::new(CliBackend) + } + }, + Err(err) => { + eprintln!( + "Invalid {API_BACKEND_ENV} value `{trimmed}` ({err}), falling back to CLI backend" + ); + Box::new(CliBackend) + } + } + } + } + Err(_) => Box::new(CliBackend), + } +} + +pub fn get_keypair(key: u64) -> (Element, Element) { + let secret_key = Element::new(key); + let address = get_address_for_private_key(secret_key); + (secret_key, address) +} + +pub fn send_note(value: u64, address: Element, psi: u64) -> Note { + note(value, address, psi, bridged_polygon_usdc_note_kind()) +} + +pub fn note(value: u64, address: Element, psi: u64, contract: Element) -> Note { + Note { + kind: Element::new(2), + value: Element::new(value), + address, + contract, + psi: Element::new(psi), + } +} + +pub async fn prove_proof(proof_input: &P) -> Result { + let backend = test_backend().await; + let start = std::time::Instant::now(); + let proof = proof_input.prove(backend.as_ref()).await.unwrap(); + let end = std::time::Instant::now() - start; + println!("Proving completed in {end:?}"); + Ok(proof) +} + +pub async fn verify_proof(proof: &impl Verify) { + let backend = test_backend().await; + let start = std::time::Instant::now(); + let result = proof.verify(backend.as_ref()).await; + let duration = start.elapsed(); + + assert!( + result.is_ok(), + "Proof verification failed: {:?}", + result.err() + ); + + println!("Proof verification completed in {duration:?}"); +} + +pub async fn verify_utxo_proof(proof: &UtxoProof) { + let circuit_proof = Proof::from(proof.clone()); + verify_proof(&circuit_proof).await; +} + +pub async fn prove_and_verify(proof_input: &P) -> Result { + let proof = prove_proof(proof_input).await?; + verify_proof(&proof).await; + Ok(proof) +} + +async fn process_utxo_for_agg( + tree: &mut smirk::Tree<161, ()>, + utxo: &Utxo, +) -> Result<( + UtxoProof, + MerklePath<161>, + MerklePath<161>, + MerklePath<161>, + MerklePath<161>, + Element, +)> { + let backend = test_backend().await; + let utxo_proof = utxo.prove(backend.as_ref()).await?; + + let input_commitment_1 = utxo.input_notes[0].note.commitment(); + let p1: MerklePath<161> = MerklePath::new(tree.path_for(input_commitment_1).siblings.to_vec()); + if input_commitment_1 != Element::ZERO { + tree.remove(input_commitment_1).unwrap(); + } + + let input_commitment_2 = utxo.input_notes[1].note.commitment(); + let p2: MerklePath<161> = MerklePath::new(tree.path_for(input_commitment_2).siblings.to_vec()); + if input_commitment_2 != Element::ZERO { + tree.remove(input_commitment_2).unwrap(); + } + + let output_commitment_1 = utxo.output_notes[0].commitment(); + if output_commitment_1 != Element::ZERO { + tree.insert(output_commitment_1, ()).unwrap(); + } + let p3: MerklePath<161> = MerklePath::new(tree.path_for(output_commitment_1).siblings.to_vec()); + + let output_commitment_2 = utxo.output_notes[1].commitment(); + if output_commitment_2 != Element::ZERO { + tree.insert(output_commitment_2, ()).unwrap(); + } + let p4: MerklePath<161> = MerklePath::new(tree.path_for(output_commitment_2).siblings.to_vec()); + + let new_root = tree.root_hash(); + + Ok((utxo_proof, p1, p2, p3, p4, new_root)) +} + +pub fn add_note_to_tree(tree: &mut smirk::Tree<161, ()>, note: &InputNote) { + tree.insert(note.note.commitment(), ()).unwrap(); +} + +#[tokio::test] +async fn test_utxo() { + let (secret_key, address) = get_keypair(101); + + let input_note1 = InputNote { + note: send_note(50, address, 1), + secret_key, + }; + + let input_note2 = InputNote { + note: send_note(30, address, 2), + secret_key, + }; + + let output_note1 = send_note(40, address, 3); + let output_note2 = send_note(40, address, 4); + + let utxo = Utxo { + input_notes: [input_note1, input_note2], + output_notes: [output_note1, output_note2], + kind: UtxoKind::Send, + burn_address: None, + }; + + prove_and_verify(&utxo).await.unwrap(); +} + +#[tokio::test] +async fn test_agg_utxo() { + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); + + let utxo1_input_note1 = InputNote { + note: send_note(50, address, 1), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note1); + + let utxo1_input_note2 = InputNote { + note: send_note(30, address, 2), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note2); + + let utxo1_old_root = tree.root_hash(); + + let utxo1_output_note1 = send_note(40, address, 3); + let utxo1_output_note2 = send_note(40, address, 4); + + let utxo1 = Utxo { + input_notes: [utxo1_input_note1.clone(), utxo1_input_note2.clone()], + output_notes: [utxo1_output_note1.clone(), utxo1_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo1_proof, p1, p2, p3, p4, utxo1_new_root) = + process_utxo_for_agg(&mut tree, &utxo1).await.unwrap(); + verify_utxo_proof(&utxo1_proof).await; + + let agg_utxo1 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo1_proof, &[p1, p2, p3, p4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo1_old_root, + utxo1_new_root, + ); + + prove_and_verify(&agg_utxo1).await.unwrap(); +} + +#[tokio::test] +async fn test_agg_agg() { + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); + + let utxo1_input_note1 = InputNote { + note: send_note(60, address, 1), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note1); + + let utxo1_input_note2 = InputNote { + note: send_note(40, address, 2), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note2); + + let utxo1_old_root = tree.root_hash(); + + let utxo1_output_note1 = send_note(70, address, 3); + let utxo1_output_note2 = send_note(30, address, 4); + + let utxo1 = Utxo { + input_notes: [utxo1_input_note1.clone(), utxo1_input_note2.clone()], + output_notes: [utxo1_output_note1.clone(), utxo1_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo1_proof, p1_1, p1_2, p1_3, p1_4, utxo1_new_root) = + process_utxo_for_agg(&mut tree, &utxo1).await.unwrap(); + verify_utxo_proof(&utxo1_proof).await; + + let agg_utxo1 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo1_proof, &[p1_1, p1_2, p1_3, p1_4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo1_old_root, + utxo1_new_root, + ); + let agg_utxo1_proof = prove_and_verify(&agg_utxo1).await.unwrap(); + + let utxo2_input_note1 = InputNote { + note: utxo1_output_note1.clone(), + secret_key, + }; + + let utxo2_input_note2 = InputNote { + note: utxo1_output_note2.clone(), + secret_key, + }; + + let utxo2_old_root = tree.root_hash(); + + let utxo2_output_note1 = send_note(55, address, 5); + let utxo2_output_note2 = send_note(45, address, 6); + + let utxo2 = Utxo { + input_notes: [utxo2_input_note1.clone(), utxo2_input_note2.clone()], + output_notes: [utxo2_output_note1.clone(), utxo2_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo2_proof, p2_1, p2_2, p2_3, p2_4, utxo2_new_root) = + process_utxo_for_agg(&mut tree, &utxo2).await.unwrap(); + verify_utxo_proof(&utxo2_proof).await; + + let agg_utxo2 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo2_proof, &[p2_1, p2_2, p2_3, p2_4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo2_old_root, + utxo2_new_root, + ); + let agg_utxo2_proof = prove_and_verify(&agg_utxo2).await.unwrap(); + + let agg_agg = AggAgg::new([ + AggProof::AggUtxo(Box::new(agg_utxo1_proof)), + AggProof::AggUtxo(Box::new(agg_utxo2_proof)), + ]); + + prove_and_verify(&agg_agg).await.unwrap(); +} + +#[tokio::test] +async fn test_agg_final() { + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); + + let utxo1_input_note1 = InputNote { + note: send_note(60, address, 1), + secret_key, + }; + tree.insert(utxo1_input_note1.note.commitment(), ()) + .unwrap(); + + let utxo1_input_note2 = InputNote { + note: send_note(40, address, 2), + secret_key, + }; + tree.insert(utxo1_input_note2.note.commitment(), ()) + .unwrap(); + + let utxo1_old_root = tree.root_hash(); + + let utxo1_output_note1 = send_note(70, address, 3); + let utxo1_output_note2 = send_note(30, address, 4); + + let utxo1 = Utxo { + input_notes: [utxo1_input_note1.clone(), utxo1_input_note2.clone()], + output_notes: [utxo1_output_note1.clone(), utxo1_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo1_proof, p1_1, p1_2, p1_3, p1_4, utxo1_new_root) = + process_utxo_for_agg(&mut tree, &utxo1).await.unwrap(); + verify_utxo_proof(&utxo1_proof).await; + + let agg_utxo1 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo1_proof, &[p1_1, p1_2, p1_3, p1_4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo1_old_root, + utxo1_new_root, + ); + let agg_utxo1_proof = prove_and_verify(&agg_utxo1).await.unwrap(); + + let utxo2_input_note1 = InputNote { + note: utxo1_output_note1.clone(), + secret_key, + }; + + let utxo2_input_note2 = InputNote { + note: utxo1_output_note2.clone(), + secret_key, + }; + + let utxo2_old_root = tree.root_hash(); + + let utxo2_output_note1 = send_note(55, address, 5); + let utxo2_output_note2 = send_note(45, address, 6); + + let utxo2 = Utxo { + input_notes: [utxo2_input_note1.clone(), utxo2_input_note2.clone()], + output_notes: [utxo2_output_note1.clone(), utxo2_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo2_proof, p2_1, p2_2, p2_3, p2_4, utxo2_new_root) = + process_utxo_for_agg(&mut tree, &utxo2).await.unwrap(); + verify_utxo_proof(&utxo2_proof).await; + + let agg_utxo2 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo2_proof, &[p2_1, p2_2, p2_3, p2_4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo2_old_root, + utxo2_new_root, + ); + let agg_utxo2_proof = prove_and_verify(&agg_utxo2).await.unwrap(); + + let agg_agg = AggAgg::new([ + AggProof::AggUtxo(Box::new(agg_utxo1_proof)), + AggProof::AggUtxo(Box::new(agg_utxo2_proof)), + ]); + let agg_agg_proof = prove_and_verify(&agg_agg).await.unwrap(); + + let agg_final = AggFinal::new(agg_agg_proof); + + prove_and_verify(&agg_final).await.unwrap(); +} + +#[tokio::test] +async fn test_utxo_mint() { + let (_secret_key, address) = get_keypair(101); + + let input_note1 = InputNote::padding_note(); + let input_note2 = InputNote::padding_note(); + + let output_note1 = send_note(100, address, 1); + let output_note2 = send_note(50, address, 2); + + let utxo = Utxo { + input_notes: [input_note1, input_note2], + output_notes: [output_note1, output_note2], + kind: UtxoKind::Mint, + burn_address: None, + }; + + prove_and_verify(&utxo).await.unwrap(); +} + +#[tokio::test] +async fn test_utxo_burn() { + let (secret_key, address) = get_keypair(101); + let burn_address = Element::new(999); + + let input_note1 = InputNote { + note: send_note(80, address, 1), + secret_key, + }; + + let input_note2 = InputNote { + note: send_note(70, address, 2), + secret_key, + }; + + let output_note1 = send_note(20, address, 3); + let output_note2 = send_note(30, address, 4); + + let utxo = Utxo { + input_notes: [input_note1, input_note2], + output_notes: [output_note1, output_note2], + kind: UtxoKind::Burn, + burn_address: Some(burn_address), + }; + + prove_and_verify(&utxo).await.unwrap(); +} + +#[tokio::test] +async fn test_agg_utxo_mint_burn() { + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); + + let utxo1_input_note1 = InputNote { + note: send_note(50, address, 1), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note1); + + let utxo1_input_note2 = InputNote { + note: send_note(30, address, 2), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note2); + + let utxo1_old_root = tree.root_hash(); + + let utxo1_output_note1 = send_note(40, address, 3); + let utxo1_output_note2 = send_note(40, address, 4); + + let utxo1 = Utxo { + input_notes: [utxo1_input_note1.clone(), utxo1_input_note2.clone()], + output_notes: [utxo1_output_note1.clone(), utxo1_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo1_proof, p1, p2, p3, p4, _) = process_utxo_for_agg(&mut tree, &utxo1).await.unwrap(); + verify_utxo_proof(&utxo1_proof).await; + + // Second UTXO: Burn + let utxo2_input_note1 = InputNote { + note: utxo1_output_note1.clone(), + secret_key, + }; + + let utxo2 = Utxo { + input_notes: [utxo2_input_note1.clone(), InputNote::padding_note()], + output_notes: [Note::padding_note(), Note::padding_note()], + kind: UtxoKind::Burn, + burn_address: Some(Element::new(999)), + }; + + let (utxo2_proof, p2_1, p2_2, p2_3, p2_4, _) = + process_utxo_for_agg(&mut tree, &utxo2).await.unwrap(); + verify_utxo_proof(&utxo2_proof).await; + + // Third UTXO: Mint + let utxo3_output_note1 = send_note(100, address, 1); + + let utxo3 = Utxo { + input_notes: [InputNote::padding_note(), InputNote::padding_note()], + output_notes: [utxo3_output_note1.clone(), Note::padding_note()], + kind: UtxoKind::Mint, + burn_address: None, + }; + + let (utxo3_proof, p3_1, p3_2, p3_3, p3_4, utxo3_new_root) = + process_utxo_for_agg(&mut tree, &utxo3).await.unwrap(); + verify_utxo_proof(&utxo3_proof).await; + + let agg_utxo1 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo1_proof, &[p1, p2, p3, p4]), + UtxoProofBundleWithMerkleProofs::new(utxo2_proof, &[p2_1, p2_2, p2_3, p2_4]), + UtxoProofBundleWithMerkleProofs::new(utxo3_proof, &[p3_1, p3_2, p3_3, p3_4]), + ], + utxo1_old_root, + utxo3_new_root, + ); + + prove_and_verify(&agg_utxo1).await.unwrap(); +} + +#[tokio::test] +async fn test_agg_final_with_mint_and_burn() { + let (secret_key, address) = get_keypair(101); + let mut tree = smirk::Tree::<161, ()>::new(); + + let utxo1_input_note1 = InputNote { + note: send_note(50, address, 1), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note1); + + let utxo1_input_note2 = InputNote { + note: send_note(30, address, 2), + secret_key, + }; + add_note_to_tree(&mut tree, &utxo1_input_note2); + + let utxo1_old_root = tree.root_hash(); + + let utxo1_output_note1 = send_note(40, address, 3); + let utxo1_output_note2 = send_note(40, address, 4); + + let utxo1 = Utxo { + input_notes: [utxo1_input_note1.clone(), utxo1_input_note2.clone()], + output_notes: [utxo1_output_note1.clone(), utxo1_output_note2.clone()], + kind: UtxoKind::Send, + burn_address: None, + }; + + let (utxo1_proof, p1, p2, p3, p4, _) = process_utxo_for_agg(&mut tree, &utxo1).await.unwrap(); + verify_utxo_proof(&utxo1_proof).await; + + // Second UTXO: Burn + let utxo2_input_note1 = InputNote { + note: utxo1_output_note1.clone(), + secret_key, + }; + + let utxo2 = Utxo { + input_notes: [utxo2_input_note1.clone(), InputNote::padding_note()], + output_notes: [Note::padding_note(), Note::padding_note()], + kind: UtxoKind::Burn, + burn_address: Some(Element::new(999)), + }; + + let (utxo2_proof, p2_1, p2_2, p2_3, p2_4, utxo2_new_root) = + process_utxo_for_agg(&mut tree, &utxo2).await.unwrap(); + verify_utxo_proof(&utxo2_proof).await; + + let agg_utxo1 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo1_proof, &[p1, p2, p3, p4]), + UtxoProofBundleWithMerkleProofs::new(utxo2_proof, &[p2_1, p2_2, p2_3, p2_4]), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo1_old_root, + utxo2_new_root, + ); + let agg_utxo1_proof = prove_and_verify(&agg_utxo1).await.unwrap(); + + // Third UTXO: Mint + let utxo3_output_note1 = send_note(100, address, 1); + + let utxo3 = Utxo { + input_notes: [InputNote::padding_note(), InputNote::padding_note()], + output_notes: [utxo3_output_note1.clone(), Note::padding_note()], + kind: UtxoKind::Mint, + burn_address: None, + }; + + let (utxo3_proof, p3_1, p3_2, p3_3, p3_4, utxo3_new_root) = + process_utxo_for_agg(&mut tree, &utxo3).await.unwrap(); + verify_utxo_proof(&utxo3_proof).await; + + let agg_utxo2 = AggUtxo::new( + [ + UtxoProofBundleWithMerkleProofs::new(utxo3_proof, &[p3_1, p3_2, p3_3, p3_4]), + UtxoProofBundleWithMerkleProofs::default(), + UtxoProofBundleWithMerkleProofs::default(), + ], + utxo2_new_root, + utxo3_new_root, + ); + let agg_utxo2_proof = prove_and_verify(&agg_utxo2).await.unwrap(); + + // Create AggAgg with both mint and burn proofs + let agg_agg = AggAgg::new([ + AggProof::AggUtxo(Box::new(agg_utxo1_proof)), + AggProof::AggUtxo(Box::new(agg_utxo2_proof)), + ]); + let agg_agg_proof = prove_and_verify(&agg_agg).await.unwrap(); + + // Create AggFinal + let agg_final = AggFinal::new(agg_agg_proof); + prove_and_verify(&agg_final).await.unwrap(); +} diff --git a/pkg/zk-circuits/src/circuits/tests/erc_20.rs b/pkg/zk-circuits/src/circuits/tests/erc_20.rs new file mode 100644 index 0000000..36214d1 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/tests/erc_20.rs @@ -0,0 +1,257 @@ +// lint-long-file-override allow-max-lines=300 +use crate::circuits::generated::erc20_transfer::{Erc20TransferInput, Erc20transfer, Note}; +use crate::circuits::generated::submodules::common::Merklepath; +use crate::circuits::generated::submodules::signature::Signature as SignatureStruct; +use crate::circuits::{note_v2::hash_note, tests::prove_and_verify}; + +use alloy::consensus::{SignableTransaction, TxEip1559}; +use alloy::primitives::{Address, Bytes, U256}; +use alloy::signers::Signer; +use alloy::signers::local::PrivateKeySigner; +use bitvec::{array::BitArray, order::Lsb0}; +use element::Element; +use sha3::{Digest, Keccak256}; +use std::str::FromStr; + +fn build_erc20_transfer_calldata(receiver: [u8; 20], amount: u64) -> Bytes { + let mut data = Vec::with_capacity(68); + // transfer(address,uint256) selector + data.extend_from_slice(&[0xa9, 0x05, 0x9c, 0xbb]); + // receiver address (padded to 32 bytes) + data.extend_from_slice(&[0u8; 12]); + data.extend_from_slice(&receiver); + data.extend_from_slice(&U256::from(amount).to_be_bytes::<32>()); + Bytes::from(data) +} + +/// Helper function to build Merkle proofs for two commitments +/// Returns (root, [path_for_commitment_1, path_for_commitment_2]) +fn build_merkle_inputs( + commitment_one: Element, + commitment_two: Element, +) -> (Element, [[Element; 160]; 2]) { + let le_bits_one: BitArray<_, Lsb0> = BitArray::new(commitment_one.to_le_bytes()); + let le_bits_two: BitArray<_, Lsb0> = BitArray::new(commitment_two.to_le_bytes()); + + // Find the divergence point + let mut divergence = 0; + for i in 0..160 { + if le_bits_one[i] != le_bits_two[i] { + divergence = i; + } + } + + let mut hash_one = commitment_one; + let mut hash_two = commitment_two; + let mut path_one = [Element::ZERO; 160]; + let mut path_two = [Element::ZERO; 160]; + + for i in 0..160 { + if i == divergence { + path_one[i] = hash_two; + path_two[i] = hash_one; + let next_hash = if !le_bits_one[i] { + hash::hash_merge([hash_one, hash_two]) + } else { + hash::hash_merge([hash_two, hash_one]) + }; + hash_one = next_hash; + hash_two = next_hash; + } else { + let sibling = Element::new((i + 1000) as u64); + path_one[i] = sibling; + path_two[i] = sibling; + hash_one = if !le_bits_one[i] { + hash::hash_merge([hash_one, sibling]) + } else { + hash::hash_merge([sibling, hash_one]) + }; + hash_two = if !le_bits_two[i] { + hash::hash_merge([hash_two, sibling]) + } else { + hash::hash_merge([sibling, hash_two]) + }; + } + } + + (hash_one, [path_one, path_two]) +} + +async fn build_valid_inputs() -> Erc20TransferInput { + let chain_id: u64 = 1; + let bridge_address = Element::new(56789u64); + let token_address: [u8; 20] = [ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, + 0xfe, 0x11, 0x22, 0x33, 0x44, + ]; + let receiver: [u8; 20] = [ + 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x99, 0xab, 0xcd, 0xef, 0x01, + ]; + + let transfer_amount = 123456789; + let nonce = 0; + let max_priority_fee_per_gas = 2000000000; + let max_fee_per_gas = 100000000000; + let gas_limit = 21000; + + let original_transfer = Erc20transfer { + chain_id, + nonce, + max_priority_fee_per_gas, + max_fee_per_gas, + gas_limit, + token_address, + receiver, + amount: Element::new(transfer_amount), + }; + + let tx = TxEip1559 { + chain_id, + nonce, + max_priority_fee_per_gas, + max_fee_per_gas, + gas_limit, + to: Address::from(token_address).into(), + value: U256::ZERO, + input: build_erc20_transfer_calldata(receiver, transfer_amount), + access_list: Default::default(), + }; + + let tx_hash = tx.signature_hash(); + + let signer = PrivateKeySigner::from_str( + "0x0000000000000000000000000000000000000000000000000000000000000001", + ) + .expect("invalid private key"); + + let pubkey = signer.public_key(); + let sender_pubkey_x: [u8; 32] = pubkey[..32].try_into().unwrap(); + let sender_pubkey_y: [u8; 32] = pubkey[32..].try_into().unwrap(); + + let signature = signer.sign_hash(&tx_hash).await.expect("signing failed"); + let r: [u8; 32] = signature.r().to_be_bytes(); + let s: [u8; 32] = signature.s().to_be_bytes(); + + let mut pubkey_concat = [0u8; 64]; + pubkey_concat[..32].copy_from_slice(&sender_pubkey_x); + pubkey_concat[32..].copy_from_slice(&sender_pubkey_y); + let sender_address: [u8; 20] = Keccak256::digest(pubkey_concat)[12..32].try_into().unwrap(); + + let input_note_value_one = 70000000; + let input_note_value_two = 80000000; + + let input_note_one = Note { + kind: Element::ONE, + address: sender_address, + token: token_address, + value: Element::new(input_note_value_one), + psi: Element::new(42u64), + }; + let input_note_two = Note { + kind: Element::ONE, + address: sender_address, + token: token_address, + value: Element::new(input_note_value_two), + psi: Element::new(1000u64), + }; + + let commitment_one = hash_note(&input_note_one); + let commitment_two = hash_note(&input_note_two); + let (merkle_root, merkle_paths) = build_merkle_inputs(commitment_one, commitment_two); + + let new_nullifier_one = hash::hash_merge([commitment_one, input_note_one.psi]); + let new_nullifier_two = hash::hash_merge([commitment_two, input_note_two.psi]); + let new_nullifier_three = hash::hash_merge([ + Element::from_be_bytes(r), + Element::new(chain_id), + bridge_address, + ]); + + let output_change = input_note_value_one + input_note_value_two - transfer_amount; + let output_note_one = Note { + kind: Element::ONE, + address: sender_address, + token: token_address, + value: Element::new(output_change), + psi: Element::new(99u64), + }; + let output_note_two = Note { + kind: Element::ONE, + address: receiver, + token: token_address, + value: Element::new(transfer_amount), + psi: Element::new(1234u64), + }; + let new_commitments = [hash_note(&output_note_one), hash_note(&output_note_two)]; + + Erc20TransferInput { + chain_id, + bridge_address, + original_transfer, + signature: SignatureStruct { + r, + s, + sender_pubkey_x, + sender_pubkey_y, + }, + input_notes: [input_note_one, input_note_two], + input_note_merkle_proofs: [ + Merklepath { + path: merkle_paths[0], + }, + Merklepath { + path: merkle_paths[1], + }, + ], + input_note_merkle_root: merkle_root, + new_nullifiers: [new_nullifier_one, new_nullifier_two, new_nullifier_three], + output_notes: [output_note_one, output_note_two], + new_commitments, + } +} + +#[tokio::test] +async fn test_erc20_transfer_accepts_inputs() { + let input = build_valid_inputs().await; + prove_and_verify(&input).await.unwrap(); +} + +#[tokio::test] +#[should_panic(expected = "UnsatisfiedConstrain")] +async fn test_erc20_transfer_rejects_bad_root() { + let mut input = build_valid_inputs().await; + input.input_note_merkle_root = input.input_note_merkle_root + Element::ONE; + prove_and_verify(&input).await.unwrap(); +} + +#[tokio::test] +#[should_panic(expected = "UnsatisfiedConstrain")] +async fn test_erc20_transfer_rejects_bad_nullifier() { + let mut input = build_valid_inputs().await; + input.new_nullifiers[0] = input.new_nullifiers[0] + Element::ONE; + prove_and_verify(&input).await.unwrap(); +} + +#[tokio::test] +#[should_panic(expected = "UnsatisfiedConstrain")] +async fn test_erc20_transfer_rejects_bad_commitment() { + let mut input = build_valid_inputs().await; + input.new_commitments[0] = input.new_commitments[0] + Element::ONE; + prove_and_verify(&input).await.unwrap(); +} + +#[tokio::test] +#[should_panic(expected = "UnsatisfiedConstrain")] +async fn test_erc20_transfer_rejects_wrong_money_source() { + let mut input = build_valid_inputs().await; + // Change the first input note to belong to the receiver instead of the sender + input.input_notes[0].address = input.original_transfer.receiver; + // Rebuild merkle proofs for the modified notes + let commitment_one = hash_note(&input.input_notes[0]); + let commitment_two = hash_note(&input.input_notes[1]); + let (root, paths) = build_merkle_inputs(commitment_one, commitment_two); + input.input_note_merkle_root = root; + input.input_note_merkle_proofs = [Merklepath { path: paths[0] }, Merklepath { path: paths[1] }]; + prove_and_verify(&input).await.unwrap(); +} diff --git a/pkg/zk-circuits/src/circuits/tests/migrate.rs b/pkg/zk-circuits/src/circuits/tests/migrate.rs new file mode 100644 index 0000000..15e1584 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/tests/migrate.rs @@ -0,0 +1,22 @@ +use crate::circuits::generated::migrate::MigrateInput; +use crate::{Prove, Result, Verify}; +use barretenberg_cli::CliBackend; +use element::Element; + +#[tokio::test] +async fn test_migrate_proof_generation_and_verification() -> Result<()> { + let owner_pk = Element::from(101u64); + let old_address = hash_poseidon::hash_merge([owner_pk, Element::ZERO]); + let new_address = hash::hash_merge([owner_pk, Element::ZERO]); + let input = MigrateInput { + owner_pk, + old_address, + new_address, + }; + let backend = CliBackend; + + let proof = input.prove(&backend).await?; + proof.verify(&backend).await?; + + Ok(()) +} diff --git a/pkg/zk-circuits/src/circuits/tests/points.rs b/pkg/zk-circuits/src/circuits/tests/points.rs new file mode 100644 index 0000000..0c80802 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/tests/points.rs @@ -0,0 +1,59 @@ +use crate::circuits::generated::points::PointsInput; +use crate::circuits::generated::submodules::common::Note as CommonNote; +use crate::{Prove, Result, Verify}; +use barretenberg_cli::CliBackend; +use element::Element; +use zk_primitives::{bridged_polygon_usdc_note_kind, get_address_for_private_key}; + +#[tokio::test] +async fn test_points_prove_and_verify() -> Result<()> { + // Match the Noir `points` test pattern with one padding note and nine owned notes. + let secret_key = Element::new(101); + let address = get_address_for_private_key(secret_key); + + let primitive_notes = std::array::from_fn(|i| { + if i == 0 { + zk_primitives::Note::padding_note() + } else { + zk_primitives::Note::new_with_psi( + address, + Element::new((i * 10) as u64), + Element::new((i + 1) as u64), + bridged_polygon_usdc_note_kind(), + ) + } + }); + + let secret_keys = std::array::from_fn(|i| if i == 0 { Element::ZERO } else { secret_key }); + let commitments = primitive_notes + .each_ref() + .map(zk_primitives::Note::commitment); + + let timestamp = Element::new(1234567890u64); + let value = primitive_notes + .each_ref() + .map(|note| note.value) + .into_iter() + .sum(); + let hash = hash::hash_merge([timestamp, address]); + let notes = primitive_notes.map(CommonNote::from); + + let input = PointsInput { + notes, + secret_keys, + address, + timestamp, + value, + hash, + commitments, + }; + + let backend = CliBackend; + let proof = input.prove(&backend).await?; + assert!( + proof.verify(&backend).await.is_ok(), + "Proof verification failed" + ); + + Ok(()) +} diff --git a/pkg/zk-circuits/src/circuits/tests/signature.rs b/pkg/zk-circuits/src/circuits/tests/signature.rs new file mode 100644 index 0000000..1cda296 --- /dev/null +++ b/pkg/zk-circuits/src/circuits/tests/signature.rs @@ -0,0 +1,22 @@ +use crate::circuits::generated::signature::SignatureInput; +use crate::{Prove, Result, Verify}; +use barretenberg_cli::CliBackend; +use element::Element; + +#[tokio::test] +async fn test_signature_proof_generation_and_verification() -> Result<()> { + let owner_pk = Element::from(101u64); + let message = Element::from(100u64); + let input = SignatureInput { + owner_pk, + message_hash: hash::hash_merge([owner_pk, message]), + address: hash::hash_merge([owner_pk, Element::ZERO]), + message, + }; + let backend = CliBackend; + + let proof = input.prove(&backend).await?; + proof.verify(&backend).await?; + + Ok(()) +} diff --git a/pkg/zk-circuits/src/circuits/utxo.rs b/pkg/zk-circuits/src/circuits/utxo.rs new file mode 100644 index 0000000..5b4576c --- /dev/null +++ b/pkg/zk-circuits/src/circuits/utxo.rs @@ -0,0 +1,100 @@ +use lazy_static::lazy_static; +use zk_primitives::{Utxo, UtxoProof, UtxoPublicInput}; + +use crate::circuits::Proof; +use crate::verify::{VerificationKey, VerificationKeyHash}; +use crate::{Prove, Result, Verify}; + +use super::generated::submodules::common::{Inputnote as CommonInputNote, Note as CommonNote}; +use super::generated::utxo::{UtxoInput, UtxoPublicInputs as CircuitUtxoPublicInputs}; + +lazy_static! { + pub static ref UTXO_VERIFICATION_KEY: VerificationKey = + VerificationKey(super::generated::utxo::VERIFICATION_KEY.clone()); + pub static ref UTXO_VERIFICATION_KEY_HASH: VerificationKeyHash = + VerificationKeyHash(*super::generated::utxo::VERIFICATION_KEY_HASH); +} + +impl From for UtxoInput { + fn from(utxo: Utxo) -> Self { + let messages = utxo.messages(); + let commitments = utxo.leaf_elements(); + let Utxo { + input_notes, + output_notes, + .. + } = utxo; + + UtxoInput { + input_notes: input_notes.map(CommonInputNote::from), + output_notes: output_notes.map(CommonNote::from), + pmessage4: messages[4], + commitments, + messages, + } + } +} + +#[async_trait::async_trait] +impl Prove for Utxo { + type Proof = UtxoProof; + + async fn prove( + &self, + bb_backend: &dyn barretenberg_interface::BbBackend, + ) -> Result { + let input = UtxoInput::from(self.clone()); + let proof = input.prove(bb_backend).await?; + Ok(UtxoProof::from(proof)) + } +} + +impl From for UtxoPublicInput { + fn from(value: CircuitUtxoPublicInputs) -> Self { + Self { + input_commitments: [value.commitments[0], value.commitments[1]], + output_commitments: [value.commitments[2], value.commitments[3]], + messages: value.messages, + } + } +} + +impl From for CircuitUtxoPublicInputs { + fn from(value: UtxoPublicInput) -> Self { + Self { + commitments: [ + value.input_commitments[0], + value.input_commitments[1], + value.output_commitments[0], + value.output_commitments[1], + ], + messages: value.messages, + } + } +} + +impl From> for UtxoProof { + fn from(value: Proof) -> Self { + Self { + proof: zk_primitives::ProofBytes(value.proof), + public_inputs: value.public_inputs.into(), + } + } +} + +impl From for Proof { + fn from(value: UtxoProof) -> Self { + Self { + proof: value.proof.0, + public_inputs: value.public_inputs.into(), + } + } +} + +#[async_trait::async_trait] +impl Verify for UtxoProof { + async fn verify(&self, bb_backend: &dyn barretenberg_interface::BbBackend) -> Result<()> { + let proof = Proof::from(self.clone()); + proof.verify(bb_backend).await + } +} diff --git a/pkg/zk-circuits/src/compliance/circuit.rs b/pkg/zk-circuits/src/compliance/circuit.rs deleted file mode 100644 index 17d2328..0000000 --- a/pkg/zk-circuits/src/compliance/circuit.rs +++ /dev/null @@ -1,98 +0,0 @@ -use super::Compliance; -use crate::chips::{ - is_constant::{IsConstantChip, IsConstantConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, -}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct ComplianceCircuitConfig { - advices: [Column; 5], - instance: Column, - poseidon_config: PoseidonConfig, - swap_config: CondSwapConfig, - is_zero_config: IsConstantConfig, -} - -impl Circuit for Compliance { - type FloorPlanner = SimpleFloorPlanner; - type Config = ComplianceCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[0..3].try_into().unwrap(), - advices[4], - lagrange_coeffs[2..5].try_into().unwrap(), - lagrange_coeffs[5..8].try_into().unwrap(), - ); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Zero chip - let is_zero_config = - IsConstantChip::configure(meta, advices[0], advices[1], advices[2], Fr::zero()); - - ComplianceCircuitConfig { - advices, - instance, - poseidon_config, - swap_config, - is_zero_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Get the public instances - self.enforce_constraints( - layouter.namespace(|| "compliance"), - config.advices[0], - config.instance, - config.poseidon_config, - CondSwapChip::construct(config.swap_config), - IsConstantChip::construct(config.is_zero_config), - )?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/compliance/compliance.rs b/pkg/zk-circuits/src/compliance/compliance.rs deleted file mode 100644 index 5ca9509..0000000 --- a/pkg/zk-circuits/src/compliance/compliance.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crate::{ - chips::{ - is_constant::IsConstantChip, merkle_path::MerklePathInclusionConstrainCells, - poseidon::PoseidonConfig, swap::CondSwapChip, - }, - data::{MerklePath, Note, ParameterSet}, - util::{assign_constant, keygen_from_params}, -}; -use halo2_base::halo2_proofs::{ - circuit::Layouter, - halo2curves::bn256::{Fr, G1Affine}, - plonk::{Advice, Column, Error, Instance, ProvingKey, VerifyingKey}, -}; - -/// Compliance proves that the source of a note was not from a known bad actor -#[derive(Clone, Debug, Default)] -pub struct Compliance { - /// Note that we want to prove compliance for - note: Note, - - /// Expected recent root of the compliance merkle tree - #[allow(unused)] - recent_root: Fr, - - /// Merkle tree path for compliance merkle tree, so we can prove that the source does not exist in the - /// merkle tree - merkle_path: MerklePath, -} - -impl Compliance { - pub fn new(note: Note, recent_root: Fr, merkle_path: MerklePath) -> Self { - Self { - note, - recent_root, - merkle_path, - } - } - - /// Enforces constraints for the input note (includes default note constraints, plus additional - /// constraints to prove spending of note is allowable) - #[allow(clippy::too_many_arguments)] - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - advice: Column, - instance: Column, - poseidon_config: PoseidonConfig, - swap_chip: CondSwapChip, - is_zero_chip: IsConstantChip, - ) -> Result<(), Error> { - // First we need to check the std note constraints - // TODO(sec): update note to include SOURCE - let note_commitment_cells = self.note.enforce_constraints( - layouter.namespace(|| "input note enforce commitment"), - advice, - poseidon_config.clone(), - is_zero_chip, - swap_chip.clone(), - )?; - - // Witness null leaf - let null_leaf = assign_constant( - || "null leaf witness", - layouter.namespace(|| "null leaf witness"), - advice, - Fr::zero(), - )?; - - // Check input note commitment is in an existing merkle root - let MerklePathInclusionConstrainCells { root } = - self.merkle_path.enforce_inclusion_constraints( - layouter.namespace(|| "leaf in tree"), - // TODO(sec): this should come from note_commitment_cells - self.note.source().into(), - null_leaf, - poseidon_config, - swap_chip, - )?; - - // Constrain calculated root from null merkle path to be equal to the recent root - // provided. Recent root must be checked against the compliance merkle tre. - layouter.constrain_instance(root.cell(), instance, 0)?; - - // Constrain the note commitment, so we know which note to allow - layouter.constrain_instance(note_commitment_cells.cm.cell(), instance, 1)?; - - Ok(()) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} diff --git a/pkg/zk-circuits/src/compliance/mod.rs b/pkg/zk-circuits/src/compliance/mod.rs deleted file mode 100644 index dec0907..0000000 --- a/pkg/zk-circuits/src/compliance/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod circuit; -#[allow(clippy::module_inception)] -mod compliance; - -// Main circuit -pub use compliance::*; diff --git a/pkg/zk-circuits/src/constants.rs b/pkg/zk-circuits/src/constants.rs deleted file mode 100644 index 3605dd2..0000000 --- a/pkg/zk-circuits/src/constants.rs +++ /dev/null @@ -1,15 +0,0 @@ -/// Depth of the sparse merkle tree, a smaller tree increases the -/// likihood of collisions -pub const MERKLE_TREE_DEPTH: usize = 161; - -pub const UTXO_INPUTS: usize = 2; -pub const UTXO_OUTPUTS: usize = 2; - -pub const UTXO_AGG_NUMBER: usize = 3; -pub const UTXO_AGG_LEAVES: usize = UTXO_AGG_NUMBER * (UTXO_INPUTS + UTXO_OUTPUTS); - -/// Personalisation to blake to increase entropy -pub const BLAKE_PERSONALISATION: &[u8; 13] = b"Polybase_Seed"; - -/// Extends PSI entropy -pub const NOTE_RCM_EXT: u8 = 0; diff --git a/pkg/zk-circuits/src/data.rs b/pkg/zk-circuits/src/data.rs deleted file mode 100644 index b464b6d..0000000 --- a/pkg/zk-circuits/src/data.rs +++ /dev/null @@ -1,348 +0,0 @@ -use borsh::{BorshDeserialize, BorshSerialize}; -use serde::{Deserialize, Serialize}; -use smirk::Element; - -use crate::{aggregate_utxo::AggregateUtxo, Snark, UTXO_INPUTS, UTXO_OUTPUTS}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ParameterSet { - Six, - Eight, - Nine, - Fourteen, - TwentyOne, -} - -#[derive(Clone, Debug)] -pub struct Burn { - pub secret_key: Element, - pub notes: [Note; L], - pub to_address: Element, -} - -// https://github.com/rust-lang/rust/issues/61415 -impl Default for Burn { - fn default() -> Self { - Self { - secret_key: Element::default(), - notes: core::array::from_fn(|_| Note::default()), - to_address: Element::default(), - } - } -} - -#[derive(Clone, Debug)] -pub struct BurnTo { - pub secret_key: Element, - pub notes: [Note; L], - pub kind: Element, - pub to_address: Element, -} - -// https://github.com/rust-lang/rust/issues/61415 -impl Default for BurnTo { - fn default() -> Self { - Self { - secret_key: Element::default(), - notes: core::array::from_fn(|_| Note::default()), - to_address: Element::default(), - kind: Element::default(), - } - } -} - -// TODO: change Fr to Element -#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Note { - /// Address of owner of the note (AKA nullifer key or nk, a commitment to the secret key) - pub address: Element, - /// Blake2 hash with salts for increased entropy - pub psi: Element, - /// Value of the note - pub value: Element, - /// Kind of note - pub token: String, - /// Source of note (should be ethereum address) - pub source: Element, -} - -#[derive(Clone, Debug)] -pub struct Mint { - pub notes: [Note; L], -} - -// https://github.com/rust-lang/rust/issues/61415 -impl Default for Mint { - fn default() -> Self { - Self { - notes: [(); L].map(|_| Note::default()), - } - } -} - -#[derive(Debug, Clone, Default)] -pub struct Insert { - /// Leaf node - pub leaf: Element, - /// Sibling path (does not include leaf or root) - pub path: MerklePath, -} - -/// The siblings of a merkle path, for a [`smirk::Tree`] of depth `DEPTH` -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct MerklePath { - /// The siblings that form the merkle path - pub siblings: Vec, -} - -impl Default for MerklePath { - fn default() -> Self { - let siblings = (1..DEPTH).map(smirk::empty_tree_hash).collect::>(); - - assert_eq!(siblings.len(), DEPTH - 1); - - Self { siblings } - } -} - -#[derive(Clone, Debug)] -pub struct Batch { - /// Inserts must link to each other, in other words the new root of the first element must match - /// the old root of the second element, and so on. - pub inserts: [Insert; INSERTS], -} - -impl Default for Batch { - fn default() -> Self { - Self { - inserts: core::array::from_fn(|_| Insert::default()), - } - } -} - -/// InputNote is a Note that belongs to the current user, i.e. they have the -/// spending sercret key and can therefore use it as an input, "spending" the note. Extra -/// constraints need to be applied to input notes to ensure they are valid. -#[derive(Clone, Debug, Default, Serialize, Deserialize)] -pub struct InputNote { - pub note: Note, - /// Secret key for the address, required to spend a note - pub secret_key: Element, - /// Input notes merkle tree path, so we can verify that the note exists - /// in the tree, without revealing which hash it is - /// Path for tree that matches recent root - pub merkle_path: MerklePath, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Utxo { - pub inputs: [InputNote; UTXO_INPUTS], - pub outputs: [Note; UTXO_OUTPUTS], - - /// Merkle root of the input notes (required to prove that input notes already - /// exist in the tree and can therefore be spent) - pub root: Element, - - // Kind of transaction - pub kind: UtxoKind, -} - -impl Default for Utxo { - fn default() -> Self { - Self { - inputs: core::array::from_fn(|_| InputNote::default()), - outputs: core::array::from_fn(|_| Note::default()), - root: Element::ZERO, - kind: UtxoKind::default(), - } - } -} - -#[derive(Debug, Clone, Default, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum UtxoKind { - Null, - #[default] - Transfer, - Mint, - Burn, -} - -#[derive( - Debug, - Default, - Clone, - Hash, - PartialEq, - Eq, - Serialize, - Deserialize, - BorshSerialize, - BorshDeserialize, -)] -pub struct UTXOProof { - /// Root hash - pub recent_root: Element, - /// Mint/Burn hash (null for transfer) - pub mb_hash: Element, - /// Mint/Burn value (null for transfer) - pub mb_value: Element, - /// Leaves - pub input_leaves: [Element; UTXO_INPUTS], - pub output_leaves: [Element; UTXO_OUTPUTS], - /// Proof - pub proof: Vec, -} - -/// The serialized form of a proof -#[derive(Debug, Clone, Serialize, Deserialize)] -#[wire_message::wire_message] -pub enum SnarkWitness { - V1(SnarkWitnessV1), -} - -#[derive(Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize)] -pub struct SnarkWitnessV1 { - pub instances: Vec>, - #[serde( - serialize_with = "crate::util::serialize_base64", - deserialize_with = "crate::util::deserialize_base64" - )] - pub proof: Vec, -} - -impl wire_message::WireMessage for SnarkWitness { - type Ctx = (); - type Err = core::convert::Infallible; - - fn version(&self) -> u64 { - match self { - Self::V1(_) => 1, - } - } - - fn upgrade_once(self, _ctx: &mut Self::Ctx) -> Result { - Err(Self::max_version_error()) - } -} - -#[derive(Clone, Default, Debug)] -pub struct Signature { - /// Secret key for the address, required to spend a note - pub secret_key: Element, - /// Message to be signed - pub message: Element, -} - -#[derive(Clone, Debug)] -pub struct Points { - /// Secret key - pub secret_key: Element, - /// Message to be signed - pub notes: Vec, -} - -#[derive(Clone, Debug)] -pub struct AggregateAgg { - /// UTXO to aggregate - pub aggregates: [Snark; AGG_N], - - /// Instances used to verify the proof - pub agg_instances: Vec, - - /// Private witness to proof - pub proof: Vec, -} - -impl Default for AggregateAgg { - fn default() -> Self { - let aggregate_utxo = AggregateUtxo::<3, 161, 12>::default() - .snark(ParameterSet::TwentyOne) - .unwrap(); - - Self::new(core::array::from_fn(|_| aggregate_utxo.clone())) - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct NoteURLPayload { - pub version: u8, - pub private_key: Element, - pub psi: Option, - pub value: Element, - pub referral_code: String, -} - -pub fn decode_activity_url_payload(payload: &str) -> NoteURLPayload { - let payload_bytes = bs58::decode(payload) - .into_vec() - .expect("Failed to decode base58 payload"); - - let mut rest = &payload_bytes[..]; - - let version = rest[0]; - rest = &rest[1..]; - - let private_key_bytes: [u8; 32] = rest[..32] - .try_into() - .expect("Not enough bytes for private_key"); - let private_key = Element::from_be_bytes(private_key_bytes); - rest = &rest[32..]; - - let psi = if version == 0 { - let psi_bytes: [u8; 32] = rest[..32].try_into().expect("Not enough bytes for psi"); - rest = &rest[32..]; - Some(Element::from_be_bytes(psi_bytes)) - } else { - None - }; - - let leading_zeros = rest[0] as usize; - rest = &rest[1..]; - - let value_len = 32 - leading_zeros; - let value_without_leading_zeros = &rest[..value_len]; - rest = &rest[value_len..]; - - let mut value_bytes = [0u8; 32]; - value_bytes[leading_zeros..].copy_from_slice(value_without_leading_zeros); - let value = Element::from_be_bytes(value_bytes); - - let referral_code = String::from_utf8(rest.to_vec()).expect("Invalid UTF-8 in referral code"); - - NoteURLPayload { - version, - private_key, - psi, - value, - referral_code, - } -} - -pub fn encode_activity_url_payload(payload: &NoteURLPayload) -> String { - let mut bytes = Vec::new(); - - // Encode version - bytes.push(payload.version); - - // Encode private_key - bytes.extend_from_slice(&payload.private_key.to_be_bytes()); - - // Encode psi if version is 0 - if let Some(psi) = &payload.psi { - if payload.version == 0 { - bytes.extend_from_slice(&psi.to_be_bytes()); - } - } - - // Encode value with leading zeros - let value_bytes = payload.value.to_be_bytes(); - let leading_zeros = value_bytes.iter().take_while(|&&b| b == 0).count(); - bytes.push(leading_zeros as u8); - bytes.extend_from_slice(&value_bytes[leading_zeros..]); - - // Encode referral_code as UTF-8 - bytes.extend_from_slice(payload.referral_code.as_bytes()); - - // Return Base58-encoded string - bs58::encode(bytes).into_string() -} diff --git a/pkg/zk-circuits/src/data/delegates.rs b/pkg/zk-circuits/src/data/delegates.rs deleted file mode 100644 index 07e3ac2..0000000 --- a/pkg/zk-circuits/src/data/delegates.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::{aggregate_utxo::AggregateUtxoPrivate, CircuitKind}; - -use super::{AggregateUtxo, SnarkWitnessV1}; - -impl - AggregateUtxo -{ - pub fn snark(&self) -> SnarkWitnessV1 { - let private = AggregateUtxoPrivate::new(self.clone()); - private.snark().unwrap().to_witness() - } -} diff --git a/pkg/zk-circuits/src/error.rs b/pkg/zk-circuits/src/error.rs deleted file mode 100644 index 51e23ad..0000000 --- a/pkg/zk-circuits/src/error.rs +++ /dev/null @@ -1,69 +0,0 @@ -use std::fmt::Debug; - -/// An error produced by zk-circuits -/// -/// It is designed to be FFI-safe -#[derive(Debug)] -pub struct Error { - /// The debug representation of the underlying error - debug: String, - /// The type name of the error that caused this error - /// - /// Note that the exact representation of this field are unspecified, since they come from - /// [`core::any::type_name`], so should only be used for debugging (i.e. don't try to parse - /// this) - type_name: String, - - /// Was this error caused by a panic (if false, it was caused by a `Result::Err`) - was_panic: bool, -} - -pub type Result = core::result::Result; - -impl Error { - pub(crate) fn err(inner: T) -> Self { - Self { - debug: format!("{inner:?}"), - type_name: core::any::type_name::().to_string(), - was_panic: false, - } - } - - #[allow(unused)] - pub(crate) fn panic(inner: T) -> Self { - Self { - debug: format!("{inner:?}"), - type_name: core::any::type_name::().to_string(), - was_panic: true, - } - } - - /// Was this error caused by a panic (if false, it was caused by a `Result::Err`) - #[inline] - pub fn was_panic(&self) -> bool { - self.was_panic - } - - /// The debug representation of the underlying error - #[inline] - pub fn debug_repr(&self) -> &str { - &self.debug - } - - /// The type name of the error that caused this error - /// - /// Note that the exact representation of this field are unspecified, since they come from - /// [`core::any::type_name`], so should only be used for debugging (i.e. don't try to parse - /// this) - #[inline] - pub fn type_name(&self) -> &str { - &self.type_name - } -} - -impl std::error::Error for Error {} -impl core::fmt::Display for Error { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "Error(type = {})", self.type_name) - } -} diff --git a/pkg/zk-circuits/src/evm_verifier.rs b/pkg/zk-circuits/src/evm_verifier.rs deleted file mode 100644 index e0121fa..0000000 --- a/pkg/zk-circuits/src/evm_verifier.rs +++ /dev/null @@ -1,107 +0,0 @@ -use std::rc::Rc; - -use halo2_base::halo2_proofs::{ - halo2curves::bn256::{self, Bn256, G1Affine}, - plonk::{create_proof, Circuit, ProvingKey}, - poly::{ - commitment::ParamsProver, - kzg::{ - commitment::KZGCommitmentScheme, - multiopen::{ProverSHPLONK, VerifierSHPLONK}, - strategy::AccumulatorStrategy, - }, - VerificationStrategy, - }, - transcript::TranscriptReadBuffer, -}; -use rand::rngs::OsRng; -use snark_verifier::{ - loader::evm::EvmLoader, - pcs::kzg::{Bdfg21, Kzg}, - system::halo2::transcript::evm::EvmTranscript, - verifier::{Plonk, PlonkVerifier}, -}; - -use crate::{data::ParameterSet, params::load_params, CircuitKind}; - -pub type Error = halo2_base::halo2_proofs::plonk::Error; - -pub fn gen_proof>( - params: ParameterSet, - pk: &ProvingKey, - circuit: C, - instances: &[&[bn256::Fr]], -) -> Result, crate::Error> { - let params = load_params(params); - - let mut transcript: EvmTranscript<_, _, _, _> = - halo2_base::halo2_proofs::transcript::TranscriptWriterBuffer::<_, G1Affine, _>::init( - Vec::new(), - ); - create_proof::, ProverSHPLONK, _, _, _, _>( - params, - pk, - &[circuit], - &[instances], - OsRng, - &mut transcript, - ) - .map_err(crate::Error::err)?; - - Ok(transcript.finalize()) -} - -pub fn verify_proof( - kind: CircuitKind, - proof: &[u8], - instances: &[Vec], -) -> Result { - let params = load_params(kind.params()); - let vk = kind.vk(); - - let mut transcript: EvmTranscript<_, _, _, _> = - TranscriptReadBuffer::<_, G1Affine, _>::init(proof); - - Ok(VerificationStrategy::<_, VerifierSHPLONK<_>>::finalize( - halo2_base::halo2_proofs::plonk::verify_proof::< - _, - VerifierSHPLONK<_>, - _, - EvmTranscript<_, _, _, _>, - _, - >( - params.verifier_params(), - vk, - AccumulatorStrategy::new(params.verifier_params()), - &[&instances.iter().map(|a| a.as_slice()).collect::>()], - &mut transcript, - )?, - )) -} - -pub fn generate_verifier( - params: ParameterSet, - pk: &ProvingKey, - num_instance: Vec, -) -> String { - let params = load_params(params); - let vk = pk.get_vk(); - - let svk: snark_verifier::pcs::kzg::KzgSuccinctVerifyingKey = params.get_g()[0].into(); - let dk: snark_verifier::pcs::kzg::KzgDecidingKey = (params.g2(), params.s_g2()).into(); - let protocol = snark_verifier::system::halo2::compile( - params, - vk, - snark_verifier::system::halo2::Config::kzg().with_num_instance(num_instance.clone()), - ); - let loader: Rc = EvmLoader::new::(); - let protocol = protocol.loaded(&loader); - - let mut transcript = EvmTranscript::, _, _>::new(&loader); - let instances = transcript.load_instances(num_instance); - let proof = - Plonk::>::read_proof(&svk, &protocol, &instances, &mut transcript); - Plonk::>::verify(&svk, &dk, &protocol, &instances, &proof); - - loader.yul_code() -} diff --git a/pkg/zk-circuits/src/execute.rs b/pkg/zk-circuits/src/execute.rs new file mode 100644 index 0000000..79e2097 --- /dev/null +++ b/pkg/zk-circuits/src/execute.rs @@ -0,0 +1,75 @@ +use acvm::FieldElement; +use acvm::acir::native_types::WitnessStack; +use bn254_blackbox_solver::Bn254BlackBoxSolver; +use nargo::errors::try_to_diagnose_runtime_error; +use nargo::foreign_calls::DefaultForeignCallBuilder; +use noirc_abi::InputMap; +use noirc_abi::input_parser::InputValue; +use noirc_artifacts::debug::DebugArtifact; +use noirc_driver::CompiledProgram; + +#[derive(Debug)] +pub struct ExecutionResults { + #[allow(dead_code)] + pub actual_return: Option, + pub witness_stack: WitnessStack, +} + +pub fn execute_program_and_decode( + program: &CompiledProgram, + inputs_map: &InputMap, + pedantic_solving: bool, +) -> Result> { + let witness_stack = execute_program(program, inputs_map, pedantic_solving)?; + + // Get the entry point witness for the ABI + let main_witness = &witness_stack + .peek() + .expect("Should have at least one witness on the stack") + .witness; + let (_, actual_return) = program.abi.decode(main_witness)?; + + Ok(ExecutionResults { + actual_return, + witness_stack, + }) +} + +pub fn execute_program( + compiled_program: &CompiledProgram, + inputs_map: &InputMap, + pedantic_solving: bool, +) -> Result, Box> { + let initial_witness = compiled_program.abi.encode(inputs_map, None)?; + + let solved_witness_stack_err = nargo::ops::execute_program( + &compiled_program.program, + initial_witness, + &Bn254BlackBoxSolver(pedantic_solving), + &mut DefaultForeignCallBuilder { + output: std::io::stdout(), + enable_mocks: false, + // resolver_url: foreign_call_resolver_url.map(|s| s.to_string()), + // root_path, + // package_name, + } + .build(), + ); + match solved_witness_stack_err { + Ok(solved_witness_stack) => Ok(solved_witness_stack), + Err(err) => { + let debug_artifact = DebugArtifact { + debug_symbols: compiled_program.debug.clone(), + file_map: compiled_program.file_map.clone(), + }; + + if let Some(diagnostic) = + try_to_diagnose_runtime_error(&err, &compiled_program.abi, &compiled_program.debug) + { + diagnostic.report(&debug_artifact, false); + } + + Err(Box::new(err)) + } + } +} diff --git a/pkg/zk-circuits/src/fr.rs b/pkg/zk-circuits/src/fr.rs deleted file mode 100644 index 68de835..0000000 --- a/pkg/zk-circuits/src/fr.rs +++ /dev/null @@ -1,44 +0,0 @@ -use bitvec::prelude::*; -pub use bitvec::view::BitViewSized; -use halo2_base::halo2_proofs::halo2curves::bn256::Fr; -use halo2_base::halo2_proofs::halo2curves::group::ff::PrimeField; - -pub type FieldBits = BitArray; - -pub const MODULUS: [u64; 4] = [ - 0x43e1f593f0000001, - 0x2833e84879b97091, - 0xb85045b68181585d, - 0x30644e72e131a029, -]; - -pub trait PrimeFieldBits: PrimeField { - /// The backing store for a bit representation of a prime field element. - type ReprBits: BitViewSized + Send + Sync; - - /// Converts an element of the prime field into a little-endian sequence of bits. - fn to_le_bits(&self) -> FieldBits; - - /// Returns the bits of the field characteristic (the modulus) in little-endian order. - fn char_le_bits() -> FieldBits; -} - -impl PrimeFieldBits for Fr { - type ReprBits = [u64; 4]; - - fn to_le_bits(&self) -> FieldBits { - let bytes = self.to_repr(); - let limbs = [ - u64::from_le_bytes(bytes[0..8].try_into().unwrap()), - u64::from_le_bytes(bytes[8..16].try_into().unwrap()), - u64::from_le_bytes(bytes[16..24].try_into().unwrap()), - u64::from_le_bytes(bytes[24..32].try_into().unwrap()), - ]; - - FieldBits::new(limbs) - } - - fn char_le_bits() -> FieldBits { - FieldBits::new(MODULUS) - } -} diff --git a/pkg/zk-circuits/src/insert/batch.rs b/pkg/zk-circuits/src/insert/batch.rs deleted file mode 100644 index 0a741f7..0000000 --- a/pkg/zk-circuits/src/insert/batch.rs +++ /dev/null @@ -1,198 +0,0 @@ -use crate::{ - chips::{ - aggregation::snark::Snark, binary_decomposition::BinaryDecompositionConfig, - is_constant::IsConstantChip, is_less_than::IsLessThanChip, poseidon::PoseidonConfig, - swap::CondSwapChip, - }, - data::{Batch, Insert, ParameterSet}, - params::load_params, - proof::Proof, - util::{assign_private_input, keygen_from_params}, -}; -use halo2_base::halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - halo2curves::bn256::{Bn256, Fr, G1Affine}, - plonk::{Advice, Column, Error, Instance, ProvingKey, VerifyingKey}, - poly::kzg::commitment::ParamsKZG, -}; -use rand::RngCore; - -use super::InsertConstraintCells; - -impl Batch { - pub fn new(inserts: [Insert; INSERTS]) -> Self { - Self { inserts } - } - - #[allow(clippy::too_many_arguments)] - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - advice: Column, - poseidon_config: PoseidonConfig, - decompose: BinaryDecompositionConfig, - swap_chip: CondSwapChip, - padding_constant_chip: IsConstantChip, - is_less_than_chip: &IsLessThanChip, - ) -> Result { - let mut leafs = vec![]; - - // Witness old root - let old_root: AssignedCell = assign_private_input( - || "old root witness", - layouter.namespace(|| "old root witness"), - advice, - Value::known(self.old_root()), - )?; - - // Old root - let mut last_new_root = old_root.clone(); - - for insert in self.inserts.iter() { - let InsertConstraintCells { - old_root, - new_root, - new_leaf, - is_padding, - } = insert.enforce_constraints( - layouter.namespace(|| "insert"), - advice, - poseidon_config.clone(), - decompose, - swap_chip.clone(), - padding_constant_chip.clone(), - is_less_than_chip.clone(), - )?; - - // Store leafs for instance constraint - leafs.push(new_leaf); - - // TODO(perf) should we remove this, as this adds extra ZK work and we could calculate - // this in the merkle tree - let (old_root, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap padding"), - (&old_root, &last_new_root), - &is_padding, - )?; - - let (new_root, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap padding"), - (&new_root, &old_root), - &is_padding, - )?; - - // Check that the old root is the same as the last new root - layouter.assign_region( - || "constrain roots", - |mut region| region.constrain_equal(last_new_root.cell(), old_root.cell()), - )?; - - last_new_root = new_root; - } - - Ok(BatchConstraintCells { - old_root, - new_root: last_new_root, - leafs, - }) - } - - pub fn enforce_instances( - &self, - mut layouter: impl Layouter, - instance: Column, - cells: BatchConstraintCells, - ) -> Result<(), Error> { - let BatchConstraintCells { - old_root, - new_root, - leafs, - } = cells; - - // Old root - layouter.constrain_instance(old_root.cell(), instance, 0)?; - - // New root - layouter.constrain_instance(new_root.cell(), instance, 1)?; - - // Check constraints leafs - for (i, leaf) in leafs.iter().enumerate() { - // Constrain leaf to be the same as the leaf in the instance, +2 as the first - // two contraints are old_root and new_root - layouter.constrain_instance(leaf.cell(), instance, i + 2)?; - } - - Ok(()) - } - - pub fn old_root(&self) -> Fr { - // Calculate the old root from first entry - self.inserts - .first() - .expect("at least one insert") - .compute_null_root() - } - - pub fn new_root(&self) -> Fr { - self.inserts - .iter() - .rev() - .find(|i| !i.is_padding()) - .map(|i| i.compute_leaf_root()) - .unwrap_or(self.old_root()) - } - - pub fn leafs(&self) -> Vec { - self.inserts - .iter() - .map(|insert| insert.leaf.to_base()) - .collect::>() - } - - /// Public instances needed to construct proof - pub fn public_inputs(&self) -> Vec { - // Calculate the old root from first entry - let old_root = self.old_root(); - - // Calculate new root from last entry - let new_root = self.new_root(); - - // Collect all leafs - let leafs = self.leafs(); - - vec![old_root, new_root].into_iter().chain(leafs).collect() - } - - pub fn snark(&self, params: ParameterSet) -> Result { - let (pk, _) = self.keygen(params); - - Snark::create( - Self::default(), - vec![self.public_inputs()], - load_params(params), - &pk, - ) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } - - pub fn prove( - &self, - params: &ParamsKZG, - pk: &ProvingKey, - rng: impl RngCore, - ) -> Result { - let circuit = Self::default(); - let instance = self.public_inputs(); - let instances = &[instance.as_slice()]; - Proof::create(params, pk, circuit, instances, rng) - } -} - -pub struct BatchConstraintCells { - pub old_root: AssignedCell, - pub new_root: AssignedCell, - pub leafs: Vec>, -} diff --git a/pkg/zk-circuits/src/insert/circuit.rs b/pkg/zk-circuits/src/insert/circuit.rs deleted file mode 100644 index 28e209f..0000000 --- a/pkg/zk-circuits/src/insert/circuit.rs +++ /dev/null @@ -1,231 +0,0 @@ -use crate::{ - chips::{ - binary_decomposition::BinaryDecompositionConfig, - is_constant::{IsConstantChip, IsConstantConfig}, - is_less_than::{IsLessThanChip, IsLessThanChipConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, - }, - data::{Batch, Note}, -}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct BatchCircuitConfig { - instance: Column, - advices: [Column; 5], - poseidon_config: PoseidonConfig, - binary_decomposition_config: BinaryDecompositionConfig, - swap_config: CondSwapConfig, - is_padding_config: IsConstantConfig, - is_less_than: IsLessThanChipConfig, -} - -impl Circuit for Batch { - type FloorPlanner = SimpleFloorPlanner; - type Config = BatchCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - let q_range_check = meta.selector(); - - // TODO: q_range_check doesn't seem corrrect - let binary_decomposition_config = - BinaryDecompositionConfig::configure(meta, q_range_check, advices[0], advices[1]); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Padding chip - let is_padding_config = IsConstantChip::configure( - meta, - advices[0], - advices[1], - advices[2], - Note::padding_note().commitment().into(), - ); - - let is_less_than = - IsLessThanChip::configure(meta, [advices[0], advices[1], advices[2], advices[3]]); - - BatchCircuitConfig { - advices, - instance, - poseidon_config, - binary_decomposition_config, - swap_config, - is_padding_config, - is_less_than, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Get the public instances - let cells = self.enforce_constraints( - layouter.namespace(|| "enforce insert constraints"), - config.advices[0], - config.poseidon_config, - config.binary_decomposition_config, - CondSwapChip::construct(config.swap_config), - IsConstantChip::construct(config.is_padding_config), - &IsLessThanChip::construct(config.is_less_than), - )?; - - // Constrain verify aggregation cells to public inputs - self.enforce_instances( - layouter.namespace(|| "enforce insert instances"), - config.instance, - cells, - )?; - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use crate::{ - constants::MERKLE_TREE_DEPTH, - data::{Insert, MerklePath}, - test::rollup::Rollup, - }; - use halo2_base::halo2_proofs::dev::MockProver; - use zk_primitives::Element; - - use super::*; - - #[test] - fn test_batch_insert_pad_insert_pad() { - let k = 16; - - let mut rollup = Rollup::new(); - let old_root = rollup.root_hash(); - - let padding_leaf = Note::padding_note().commitment(); - let padding_path = MerklePath::default(); - let padding_insert = Insert::new(padding_leaf, padding_path); - - let leaf_1 = Element::from(3u64); - let leaf_1_path = rollup.merkle_path(leaf_1); - let insert_1 = Insert::new(leaf_1, leaf_1_path); - - // Update the tree with the new insert, so leaf_2 path is valid - rollup.tree.insert(leaf_1, ()).unwrap(); - - let leaf_2 = Element::from(2u64); - let leaf_2_path = rollup.merkle_path(leaf_2); - let insert_2 = Insert::new(leaf_2, leaf_2_path); - - rollup.tree.insert(leaf_2, ()).unwrap(); - - let circuit = Batch::<4, MERKLE_TREE_DEPTH>::new([ - insert_1, - padding_insert.clone(), - insert_2, - padding_insert, - ]); - - let instances = circuit.public_inputs(); - let new_root = rollup.root_hash(); - - assert_eq!(instances.len(), 6); - assert_eq!(instances[0], old_root.to_base()); - assert_eq!(instances[1], new_root.to_base()); - assert_eq!(instances[2], leaf_1.to_base()); - assert_eq!(instances[3], padding_leaf.to_base()); - assert_eq!(instances[4], leaf_2.to_base()); - assert_eq!(instances[5], padding_leaf.to_base()); - - let prover = MockProver::::run(k, &circuit, vec![instances]).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_batch_pad_insert_pad_insert() { - let k = 16; - - let mut rollup = Rollup::new(); - let old_root = rollup.root_hash(); - - let padding_leaf = Note::padding_note().commitment(); - let padding_path = MerklePath::default(); - let padding_insert = Insert::new(padding_leaf, padding_path); - - let leaf_1 = Element::from(3u64); - let leaf_1_path = rollup.merkle_path(leaf_1); - let insert_1 = Insert::new(leaf_1, leaf_1_path); - - // Update the tree with the new insert, so leaf_2 path is valid - rollup.tree.insert(leaf_1, ()).unwrap(); - - let leaf_2 = Element::from(2u64); - let leaf_2_path = rollup.merkle_path(leaf_2); - let insert_2 = Insert::new(leaf_2, leaf_2_path); - - rollup.tree.insert(leaf_2, ()).unwrap(); - - let circuit = Batch::<4, MERKLE_TREE_DEPTH>::new([ - padding_insert.clone(), - insert_1, - padding_insert, - insert_2, - ]); - - let instances = circuit.public_inputs(); - let new_root = rollup.root_hash(); - - assert_eq!(instances.len(), 6); - assert_eq!(instances[0], old_root.to_base()); - assert_eq!(instances[1], new_root.to_base()); - assert_eq!(instances[2], padding_leaf.to_base()); - assert_eq!(instances[3], leaf_1.to_base()); - assert_eq!(instances[4], padding_leaf.to_base()); - assert_eq!(instances[5], leaf_2.to_base()); - - let prover = MockProver::::run(k, &circuit, vec![circuit.public_inputs()]).unwrap(); - prover.assert_satisfied(); - } -} diff --git a/pkg/zk-circuits/src/insert/insert.rs b/pkg/zk-circuits/src/insert/insert.rs deleted file mode 100644 index 3c0c050..0000000 --- a/pkg/zk-circuits/src/insert/insert.rs +++ /dev/null @@ -1,299 +0,0 @@ -use crate::chips::is_less_than::IsLessThanChip; -use crate::chips::{ - binary_decomposition::BinaryDecompositionConfig, is_constant::IsConstantChip, - merkle_path::merkle_root, poseidon::PoseidonConfig, swap::CondSwapChip, -}; -use crate::data::{Insert, MerklePath, Note}; -use crate::util::{assign_constant, assign_private_input}; -use halo2_base::halo2_proofs::circuit::AssignedCell; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, Value}, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error}, -}; -use zk_primitives::Element; - -impl Insert { - pub fn new(leaf: Element, path: MerklePath) -> Self { - Self { leaf, path } - } - - pub fn padding_insert() -> Self { - Insert::new(Note::padding_note().commitment(), MerklePath::default()) - } - - #[allow(clippy::too_many_arguments)] - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - advice: Column, - poseidon_config: PoseidonConfig, - decompose: BinaryDecompositionConfig, - swap_chip: CondSwapChip, - padding_constant_chip: IsConstantChip, - less_than_chip: IsLessThanChip, - ) -> Result { - // Witness new leaf - let new_leaf = assign_private_input( - || "new leaf witness", - layouter.namespace(|| "new leaf witness"), - advice, - Value::known(self.leaf()), - )?; - - // Witness null leaf - let null_leaf = assign_constant( - || "null leaf witness", - layouter.namespace(|| "null leaf witness"), - advice, - Fr::zero(), - )?; - - // Binary decomposition using RunningSum is a vec of AssignedCells containing the bits - let decomposed_bits = layouter.assign_region( - || "decompose", - |mut region| { - // We use non-struct because the merkle tree is not as big as the hash (i.e. we're only - // interested in the last n bits) - decompose.copy_decompose(&mut region, 0, new_leaf.clone(), 256, 256) - }, - )?; - - // Zero - let zero = assign_constant( - || "assign zero bit", - layouter.namespace(|| "zero bit"), - advice, - Fr::from(0), - )?; - - // One - let one: AssignedCell = assign_constant( - || "assign one bit", - layouter.namespace(|| "one bit"), - advice, - Fr::from(1), - )?; - - // Ensure insert hash is within modulus - less_than_chip.assign( - layouter.namespace(|| "less than modulus"), - &Element::MODULUS - .to_be_bits() - .iter() - .map(|b| if *b { one.clone() } else { zero.clone() }) - .collect::>(), - &decomposed_bits - .clone() - .into_iter() - .rev() - .collect::>(), - )?; - - // Witness all siblings - let sibling_witnesses = self - .path - .siblings - .iter() - .map(|w| { - assign_private_input( - || "leaf witness", - layouter.namespace(|| "leaf witness"), - advice, - Value::known(w.to_base()), - ) - }) - .collect::, Error>>()?; - - // Merge siblings with decomposed bits - let siblings = sibling_witnesses - .iter() - .zip(decomposed_bits.iter().take(MERKLE_D - 1)) - .collect::>(); - - // Prove old root based on merkle path and null leaf - let old_root = merkle_root( - layouter.namespace(|| "old root"), - swap_chip.clone(), - poseidon_config.clone(), - null_leaf, - &siblings, - )?; - - let new_root = merkle_root( - layouter.namespace(|| "new root"), - swap_chip, - poseidon_config, - new_leaf.clone(), - &siblings, - )?; - - // Padding check - let is_padding = - padding_constant_chip.assign(layouter.namespace(|| "is padding"), new_leaf.clone())?; - - Ok(InsertConstraintCells { - new_leaf, - old_root, - new_root, - is_padding, - }) - } - - pub fn leaf(&self) -> Fr { - self.leaf.into() - } - - pub fn compute_null_root(&self) -> Fr { - self.path.compute_null_root(self.leaf).into() - } - - pub fn compute_leaf_root(&self) -> Fr { - self.path.compute_root(self.leaf).into() - } - - pub fn is_padding(&self) -> bool { - self.leaf == Note::padding_note().commitment() - } - - /// Public inputs to be used in proof - /// [new_leaf, old_root, new_root] - pub fn public_inputs(&self) -> Vec { - let old_root = self.path.compute_null_root(self.leaf).into(); - let new_root = self.path.compute_root(self.leaf).into(); - - vec![self.leaf(), old_root, new_root] - } -} - -#[derive(Debug)] -pub struct InsertConstraintCells { - /// New leaf node witness - pub new_leaf: AssignedCell, - /// Old root node witness - pub old_root: AssignedCell, - /// New root node calculated from path and new leaf - pub new_root: AssignedCell, - /// Is this padding? - pub is_padding: AssignedCell, -} - -#[cfg(test)] -mod tests { - use halo2_base::halo2_proofs::{ - circuit::SimpleFloorPlanner, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Error, Instance}, - }; - use zk_primitives::Element; - - use crate::{ - chips::{ - is_constant::IsConstantConfig, is_less_than::IsLessThanChipConfig, swap::CondSwapConfig, - }, - constants::MERKLE_TREE_DEPTH, - test::util::{advice_column_equality, instance_column_equality, poseidon_config}, - }; - - use super::*; - - #[derive(Debug, Clone)] - struct InsertCircuitConfig { - poseidon_config: PoseidonConfig, - swap_config: CondSwapConfig, - is_padding_config: IsConstantConfig, - binary_decomposition_config: BinaryDecompositionConfig, - advice: Column, - instance: Column, - is_less_than: IsLessThanChipConfig, - } - - #[derive(Default, Clone, Debug)] - struct InsertCircuit { - insert: Insert, - } - - impl Circuit for InsertCircuit { - type Config = InsertCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let advices: [Column; 5] = (0..5) - .map(|_| advice_column_equality(meta)) - .collect::>() - .try_into() - .unwrap(); - - let q_range_check = meta.selector(); - - InsertCircuitConfig { - poseidon_config: poseidon_config(meta), - swap_config: CondSwapChip::configure(meta, advices), - // Padding chip - is_padding_config: IsConstantChip::configure( - meta, - advices[0], - advices[1], - advices[2], - Note::padding_note().commitment().into(), - ), - binary_decomposition_config: BinaryDecompositionConfig::configure( - meta, - q_range_check, - advices[0], - advices[1], - ), - advice: advice_column_equality(meta), - instance: instance_column_equality(meta), - is_less_than: IsLessThanChip::configure( - meta, - [advices[0], advices[1], advices[2], advices[3]], - ), - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let swap_chip = CondSwapChip::construct(config.swap_config); - - let insert_cells = self.insert.enforce_constraints( - layouter.namespace(|| "insert"), - config.advice, - config.poseidon_config, - config.binary_decomposition_config, - swap_chip, - IsConstantChip::construct(config.is_padding_config), - IsLessThanChip::construct(config.is_less_than), - )?; - - layouter.constrain_instance(insert_cells.new_leaf.cell(), config.instance, 0)?; - layouter.constrain_instance(insert_cells.old_root.cell(), config.instance, 1)?; - layouter.constrain_instance(insert_cells.new_root.cell(), config.instance, 2)?; - - Ok(()) - } - } - - #[test] - fn test_insert() { - let k = 14; - - let leaf = Element::from(7u64); // random_fr(); - let path = MerklePath::default(); - let insert = Insert::new(leaf, path); - - let public_input = insert.public_inputs(); - let instance_columns = vec![public_input]; - let circuit = InsertCircuit { insert }; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } -} diff --git a/pkg/zk-circuits/src/insert/mod.rs b/pkg/zk-circuits/src/insert/mod.rs deleted file mode 100644 index 3f483f9..0000000 --- a/pkg/zk-circuits/src/insert/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub mod batch; -mod circuit; -#[allow(clippy::module_inception)] -mod insert; - -// Main circuit, batches multiple inserts -pub use batch::*; - -// Individual insert -pub use insert::*; diff --git a/pkg/zk-circuits/src/keys/mod.rs b/pkg/zk-circuits/src/keys/mod.rs deleted file mode 100644 index dd1dcf6..0000000 --- a/pkg/zk-circuits/src/keys/mod.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::sync::OnceLock; - -use halo2_base::halo2_proofs::{ - halo2curves::bn256::G1Affine, - plonk::{ProvingKey, VerifyingKey}, -}; - -use crate::{ - aggregate_utxo::AggregateUtxo, - data::{AggregateAgg, Burn, BurnTo, Mint, ParameterSet, Points, Signature, Utxo}, -}; - -type VK = VerifyingKey; -type PK = ProvingKey; - -// macro because we don't have a trait for this, just a convention -macro_rules! create { - ($self:expr, $circuit:ty) => {{ - let circ = <$circuit>::default(); - circ.keygen($self.params()) - }}; -} - -macro_rules! vk_function { - ($name:ident, $t:ty) => { - fn $name() -> &'static VerifyingKey { - static CACHE: OnceLock> = OnceLock::new(); - const VK_HEX: &str = include_str!(concat!("vk/", stringify!($name))); - - CACHE.get_or_init(|| { - let vk_bytes = hex::decode(VK_HEX.replace(['\n', '"', ' '], "")).unwrap(); - VerifyingKey::::from_bytes::<$t>( - &vk_bytes, - halo2_base::halo2_proofs::SerdeFormat::Processed, - ) - .unwrap() - }) - } - }; -} - -vk_function!(agg_agg_2, AggregateAgg::<2>); -vk_function!(points, Points); -vk_function!(utxo, Utxo::<161>); -vk_function!(utxo_agg_3_161_12, AggregateUtxo::<3, 161, 12>); - -pub enum CircuitKind { - Signature, - Points, - Utxo, - AggUtxo, - AggAgg, - Burn, - BurnTo, - Mint, -} - -impl CircuitKind { - #[inline] - pub fn params(&self) -> ParameterSet { - match self { - Self::Points => ParameterSet::Fourteen, - Self::Utxo => ParameterSet::Fourteen, - Self::AggUtxo => ParameterSet::TwentyOne, - Self::AggAgg => ParameterSet::TwentyOne, - Self::Signature => ParameterSet::Six, - Self::Burn => ParameterSet::Nine, - Self::BurnTo => ParameterSet::Nine, - Self::Mint => ParameterSet::Eight, - } - } - - pub(crate) fn vk(&self) -> &'static VK { - match self { - Self::Points => points(), - Self::AggUtxo => utxo_agg_3_161_12(), - Self::AggAgg => agg_agg_2(), - Self::Utxo => utxo(), - - _ => { - let (_, vk) = self.keys(); - vk - } - } - } - - pub(crate) fn pk(&self) -> &'static PK { - let (pk, _) = self.keys(); - pk - } - - fn keys(&self) -> &'static (PK, VK) { - static SIGNATURE: OnceLock<(PK, VK)> = OnceLock::new(); - static POINTS: OnceLock<(PK, VK)> = OnceLock::new(); - static UTXO_KEYS: OnceLock<(PK, VK)> = OnceLock::new(); - static AGG_UTXO: OnceLock<(PK, VK)> = OnceLock::new(); - static AGG_AGG: OnceLock<(PK, VK)> = OnceLock::new(); - static BURN_KEYS: OnceLock<(PK, VK)> = OnceLock::new(); - static BURN_TO_KEYS: OnceLock<(PK, VK)> = OnceLock::new(); - static MINT: OnceLock<(PK, VK)> = OnceLock::new(); - - match self { - Self::Signature => SIGNATURE.get_or_init(|| create!(self, Signature)), - Self::Points => POINTS.get_or_init(|| create!(self, Points)), - Self::Utxo => UTXO_KEYS.get_or_init(|| create!(self, Utxo::<161>)), - Self::AggUtxo => AGG_UTXO.get_or_init(|| create!(self, AggregateUtxo::<3, 161, 12>)), - Self::AggAgg => AGG_AGG.get_or_init(|| create!(self, AggregateAgg::<2>)), - Self::Burn => BURN_KEYS.get_or_init(|| create!(self, Burn::<1>)), - Self::BurnTo => BURN_TO_KEYS.get_or_init(|| create!(self, BurnTo::<1>)), - Self::Mint => MINT.get_or_init(|| create!(self, Mint::<1>)), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn keys() { - let kinds = [ - CircuitKind::Signature, - CircuitKind::Points, - CircuitKind::Utxo, - CircuitKind::AggUtxo, - CircuitKind::Burn, - CircuitKind::Mint, - ]; - - for kind in kinds { - let _ = kind.vk(); - let _ = kind.keys(); - } - } -} diff --git a/pkg/zk-circuits/src/keys/vk/agg_agg_2 b/pkg/zk-circuits/src/keys/vk/agg_agg_2 deleted file mode 100644 index 84fdd45..0000000 --- a/pkg/zk-circuits/src/keys/vk/agg_agg_2 +++ /dev/null @@ -1 +0,0 @@ -000000150000000b7cdf4bdb7d3f837997a3279f7c37a94ad41e48cc4676de78ef164c4d53e57ea87b3c2efffe7798d60442c227eb0cc69b381f14dc45b931a30c65f902e5049b909410653eac6e0b57d02a0bf602798204810a0ea3d9bb8d667aec08c99920349714b14bfe9d7c31a44f0b8eeea06056a95658ab26f579ee1bc8d6f462c9f0840385f17cd94e033d6c491cf90d4d2b60afc7038db5e112e79082bac8f9e64e4d00963e1ca6c91fa38c210f8a87d8b88837ff0bd503ddd3d90d6ca65db9aa5ddc192672155d7bcc7e0eb9100dab59887456cddf6faf4719c628a1b746f4c8cb7f12144fb351ba687c0c8fb5c5a38e6ebc45c83377da05a244db95a87608b5d157ae6fedbe9a4763693d57572b9225431d3a0f8da63fb678208ec4734f5272050204e86f44247ecb26f669c1538b57a40c430bb6e1889134ce267e02d3d74e10df19159e17ac8341eb09985f9c44b92ffa7cd1864f1f1dec57b4ae2a8b59d1d32ca633637620c3169a7f3b53ed7c951f4daaeceefc6944b03e23b8245bac8048b822a1046700607d8e05ad956e4405236b4312a4b0488e33afc9d2e09cb46b52f6af52f552ed8ac8293a1b9738947cca0b25bcf299bc3d667f0dcc6af9baf5b8331651279693b4821a4c5d4667b08d31ae562391678a6672cb7abcfb3282a922cd1d68d20055a1006993a700038df3bb52c222e4acae9847dba0be9407e3ae7b778a2593d8a00a35f79e947ecae2561a08d7e8726d3293477484159215d51f2863224d6679854d54f52d2e93025a0284825b8fc084fa03afac39cd393f221df2bda44466378def32c481b16760df0e609fa81ec4e7794da0ac7b472e5c1c7db3ca8db115dfec16c79e217277c95866210be740ed3cc34e740dd267a6572a7c1c760ca25b34e2cb0e4bc85dd3952ae1105b21c0822daf12bd211ced014ac27dca161da9bebd3e5682ab4487b13c883f19508255e18673259c800961b030577574bf9f6ec560eaa085025e27d8d0b2ca0a1e7bea047a26c3d5728c037d8150df5e4f8b diff --git a/pkg/zk-circuits/src/keys/vk/points b/pkg/zk-circuits/src/keys/vk/points deleted file mode 100644 index d7f662c..0000000 --- a/pkg/zk-circuits/src/keys/vk/points +++ /dev/null @@ -1 +0,0 @@ -0000000e0000000d1b3ddc26be404a1d4951f1f0e754339569698a17c5bcaded32e9c9e956e68d81c071090430a6de117c38ebf5a5ed8c70dca091c81a8d0aea47a5cdb73f99e691859c412fc265d172326041ae687c6ae90d52a299ac267f2cf697881f1e62b71fa5b82c1fee2bd6c0be61ea81ae3974cb9a7c4d48791addd7fa79572f6815810f025d69c8e7056c344a24421becd3047e238ffd1f3e809f7b5d11f4e9b99b00931538cb533d40ca360684f947ce1dfc61eea2f4bcb7494c9e9c3678326dd7bf048544574311b1c6df7939d5c2a6deca85325c2bf4fca556dfd4e89712e5e6ad0f509ffecdae0535d8032b8d1c15b9b793a3c53c6f4127f74021011f9506695f2aaef0d48a1838bd74ed6a324d66fa021f1fd111e3a8aa796e1504de3311038b1ccff56ac3d6c1c02a235cf0131e22dfbe4feed0778d864a0851785374d61646862167982ee892bda0aa2272e762cb2f5e3ba5ec61769534733b915e96ed819b2709d15df5a82b2eb511a3aac6d34961add562757503e1b7d674ea005006a0499afb1094a959f7ee59d59322e12ded3e9aea08f240604071b5f070efd153fec5a006d22840c1586886f3072b5e2f5c77bd9102abf782ad6ba251f4d7362920458b4a06bec431379e69cfa7e66b8ecf3f8c6844d0b2fd876d8ce836fdad0ce93683a9541ec0e5f96de314fcc26c367e058c602274cf638c7d82c42966a08dd337155b5f3f2b6e91cc3f2af86297da62f77b75f7ad62b5f6e9db5e1c38875f01be83c974f4b1ba9fbdd1d0ec768e8dbed76547e00a79f84a87e2b35281a386435627f11fb749270e27217a35728e8b1cec97993138445014d1b8e7df2a477431da1db80956497c17f98dcf13d981ed6ded93c7ba2d26d1f826b5f16d9906c2345601325f2820d8351bde4172d5ba186ef9ed7dce6f5b459becb110f838d9ef24180ca2360f7441b24cde795578e845d5816d3a22d42bfcf28aca33c2e72c2ed7c68e48ceace85514ef281d37c49e31c2ceb9ccde79d2122f122e0b34523fb1b7d8a6 diff --git a/pkg/zk-circuits/src/keys/vk/utxo b/pkg/zk-circuits/src/keys/vk/utxo deleted file mode 100644 index e1b940d..0000000 --- a/pkg/zk-circuits/src/keys/vk/utxo +++ /dev/null @@ -1 +0,0 @@ -0000000e00000010e0cd63656622deeb344fb34cb7ceb9e829728615916a2de1daa2f0a7d01ca52e5930b469b28ec5ecd929c2bf24565bbcca43d2d5381ce11b65296cd60413d31a88e175b33fff0cce183fa3e2180cd65d4791dbd17bf5c5131fe38f915b2affafc7cc10f1fdebec930caa1d114061a21e6013c73ea1df25bda67352c72f36f29fed455806af5e49c0e76ada88d1caaa4471200e68d14bccafee4e21ced4f89e9e2f06786aa8ae2cd17a18536fa9ba3ff64f165f27678ab3af5f04502badcf061b1fd48afa9a78b9fa618a60f2634d529180826782c7a7bfe57b508ef54af36207f7587f6a3dae1ed1cbc3e85211e2f2825f2b9b61be47b4fc93ba1a15df0e1791b5a701ac590a5ba66de326eadcba9ae6e5a83eb6655bf92af141ab46ba44d71d3146d20227873f7e6397257af2637554a8a61ab9048961a59a385ea67202de87d10f28d0516b52790b06759bb9b4523cbad7469ca893c50b472cd87f7c76bc227a11629fb15bbc7ef64cbafd37f8c8cb809809f43d2082e4b6d654f7966ff5908f74015da44c51cabd9a9d905f0e12d0f6aba5340d10491be4093478ce8edf8eeb277b1776f1e1c00418960ea692de6689e52bc5d9c2c5998f4f2102b35528a0f386123a90bcbe629368ec46e19c8fe5faf1c7eddc570d804e465f2c3ad2f404d4a0c9554024d054b4daeccbc70f19b5cf068888a38fb79258bb34638021a91fd5b18110f0fd52bfc5116f93963415a41d69dccf5171233480f957e4c85274a814ca9799dece9fb91985205098b509518061fbda1b105a56b019de09fc68d78508be1c56b567cba207d5744d68fce91d4ee4cda6cc1631b9d9e65b6164ffd500c999fc7e9831926dd9e140242f7c30de252ac449da068829d13c73bbb5cb2c177387ad7ecb1539dea1c0179094f521f629f2c8246e5edb99b2bfd4e489335c2d9aaab7f16e944364f91722ccc7dc3ede1861e770ec3090207abd0cda098e6409a6cab5a182f0f383537fe71841e5d7f5cbbef4188ad92e5854c1727078cda92c325f2820d8351bde4172d5ba186ef9ed7dce6f5b459becb110f838d9ef24180ca2360f7441b24cde795578e845d5816d3a22d42bfcf28aca33c2e72c2ed7c68e48ceace85514ef281d37c49e31c2ceb9ccde79d2122f122e0b34523fb1b7d8a6 diff --git a/pkg/zk-circuits/src/keys/vk/utxo_agg_3_161_12 b/pkg/zk-circuits/src/keys/vk/utxo_agg_3_161_12 deleted file mode 100644 index 30ccacd..0000000 --- a/pkg/zk-circuits/src/keys/vk/utxo_agg_3_161_12 +++ /dev/null @@ -1 +0,0 @@ -00000015000000187cdf4bdb7d3f837997a3279f7c37a94ad41e48cc4676de78ef164c4d53e57ea8741d9d613f77c292e8d1db3612d4deda12f5cd4c9bc5baaefd28fe16474c1e92107d17ed4de445c1a6cce6cdead4855348027b7822bb7ae2822ab4e0d8c3ed87f9d64c47561a18a1428d2f3d3822561fb281c06accb9a6a8b1320f7ced0932a7c5df5cc2b49149b5460af5a170d5023c0dbc85d2c28f39ff377ad66199305a8bf0a0a56085773d2f49a8b76ede5311934352de22833a3f2f8a6f069cd58dff1d02ae920386c882283c466ead3a9e8ba724f6e409b36e9bd0aa6b49497ffdbf9efba688991c9272fd1f76109e34311b4b2094987a32bf45217fd0f4a63ceea7980967a769f962ef9ba9d3a7afbe7ced5bd7668271b72250e97f0a6dc7babf40174cfeaccd7269609a8fd1b1a68ed1796d239d4a2c9654a8fc5db7e1ffc5b46416fb8db527ada9ddeb42cebaa9a0183440e4123bf7cb04892fa678f4d43e5aad88736b8906cf0d2624c97ef62fe1c63b803bf9ddf2840aced1f8f6f2fde3be1e9af0b6daf1e493f5d2fd047078dc5315b5520fcdc4b85272eb0d24e69d9c127f87b6837fd192a049e365c0d8accda539e2b3feaeafda65f28fb22a0efefd74b306bc6bb2a9979c85cf9855a9410778606b1af0d9c0d33578ca32994f6692883c873be96da8d37aa1a690fc8add9670be302d546943c0c269895dca0ff7d9411c0c8546fd9db1bb06d05449e991edf31461eda065e2ddcefac6c3393665966daf839e3dd52f78458fa11e5f7c93b52b2ee755b425d142b6ebed0695146c5c62c5afe4bbef572e329be8f9fb617665034b3ffb91db659a55fb2da5fff3e07410aa95a2b85ac92820fa779ea806647fc6ed975140082a42c8c921f285d842396f3d2be165069dc095be52f5f97e2939b2f5bf63b39684b0262d6dd0ec754d67a4459bc9a07a5f4e9cd11bcfe74d2d9f744b7ea615cf474e13b8e610706b597645f02830f715bdb63d53388d8d52d387a5a7c1157ba89e422c71772faa28f4ca2c4c1ac745fb9a91da64307bd5c6480233c5e388889bc0419f0108981b187f8ac27616fb2e8b794aa4df3bc42db788f16f926c1640768d1c613add04a0782e3b38c72fa7cdda8fd4d45cdbfc990f2cb7bf914eb12f434e6d6d083708ae24fbe49f15891443a300d21049096ed632e8608cff3845f2d859d2489dfa7d094717239d7b29ff832e069eda678eaebb5d878d30d29d2f9359d727cf8f9d1b2bf9664d552d08743930a6ca3a5ed164d71edb32d34b200957db585751ef5a30561ea5ced19a8952d27dc648a4cca22909629b762deb4b03078e0b5290e6fe9c80ec28f803432c8a130728a45ce437e1d65a9742efa9f6790cccbe16471cf24412837432545225e73f62dc877860fd8edd565dfcb813316bdad1997263eadd560a0da674d07ea46fe0715ac561158b29680682c00e3dbfe61070a0afc3d9ce81e8cd61bb635c2cafbbd577c119bc1b37987d81c69236084cbee68140feed04e112c07073c4819eaa98594eef61408009a95f1b86164eda3cf4b7c8196d4986046d648b5fc9d805a8aadab654623de3380cf550c3e6128eb95cca9060d3cb784a83d342bbe0981dda7328db8c1c5328fe5c39b507e9e98e20c4148a339bad639aa69629afe36d99faa494b87f778e5ec93b9fc9468f900765ee5e60da6e43141d1809fb4d7761814efa88675b4b8875894ed9d1bbd315970ca3e45d6686bbadc3d5c91424e44104fa04fe1fa61d5ebd353931eb7fe4e1ff714eb7f4c425c83ef4ac50a353580e9b602852bbbe700c4c2414081b80cf2614b6133f22f52ebd29ec1ac3ddd2ff5f98e3a319d6aa24343861fec09f10a1bfcdc0507241db47a95202d583c490100088d7f3d4d088e09c765a93fdbfcf7872fc6df899565fe887c4781a6a322b353020624067df92e16ec47c14863662fb2a059232a14a8bba63b1d6fc9fcea9a3ada1 diff --git a/pkg/zk-circuits/src/lib.rs b/pkg/zk-circuits/src/lib.rs index 4f6f9ac..aa6360a 100644 --- a/pkg/zk-circuits/src/lib.rs +++ b/pkg/zk-circuits/src/lib.rs @@ -1,39 +1,14 @@ -#![allow(clippy::assign_op_pattern)] -#![deny(clippy::disallowed_methods)] -#![feature(once_cell)] - -pub mod aggregate_agg; -pub mod aggregate_utxo; -mod burn; -mod burn_to; -pub mod chips; -pub mod compliance; -pub mod constants; -pub mod evm_verifier; -pub(crate) mod fr; -pub mod insert; -pub mod mint; -pub mod points; -pub mod proof; -pub mod proof_format; -pub(crate) mod signature; +pub mod circuits; +pub mod execute; +pub mod prove; +pub mod traits; pub mod util; -mod utxo; - -mod error; - -#[cfg(feature = "test")] -pub mod test; - -/// Simple data types used as inputs to the proofs -pub mod data; - -mod keys; -mod params; +pub mod verify; -pub(crate) use crate::chips::aggregation::snark::Snark; -pub use constants::{UTXO_INPUTS, UTXO_OUTPUTS}; -pub use keys::CircuitKind; +pub use barretenberg_interface::BbBackend; +pub use barretenberg_interface::error::{Error, Result}; +pub use circuits::Proof; +pub use circuits::generated::{AggAggCircuit, AggFinalCircuit, AggUtxoCircuit}; +pub use traits::{Circuit, Prove, Verify}; -pub use error::{Error, Result}; -pub use zk_primitives::Base; +pub use circuits::generated::agg_utxo::VERIFICATION_KEY_HASH as AGG_UTXO_VERIFICATION_KEY_HASH; diff --git a/pkg/zk-circuits/src/mint/circuit.rs b/pkg/zk-circuits/src/mint/circuit.rs deleted file mode 100644 index 4f041c1..0000000 --- a/pkg/zk-circuits/src/mint/circuit.rs +++ /dev/null @@ -1,96 +0,0 @@ -use crate::{chips::{ - is_constant::{IsConstantChip, IsConstantConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, -}, data::Mint}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct MintCircuitConfig { - advices: [Column; 5], - instance: Column, - poseidon_config: PoseidonConfig, - is_zero_config: IsConstantConfig, - swap_config: CondSwapConfig, -} - -impl Circuit for Mint { - type FloorPlanner = SimpleFloorPlanner; - type Config = MintCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Is zero chip - let is_zero_config = - IsConstantChip::configure(meta, advices[0], advices[1], advices[2], Fr::zero()); - - // - - MintCircuitConfig { - advices, - instance, - poseidon_config, - is_zero_config, - swap_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - self.enforce_constraints( - layouter.namespace(|| "mint"), - config.instance, - config.advices[0], - config.poseidon_config, - IsConstantChip::construct(config.is_zero_config), - CondSwapChip::construct(config.swap_config), - )?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/mint/mint.rs b/pkg/zk-circuits/src/mint/mint.rs deleted file mode 100644 index ed8dcda..0000000 --- a/pkg/zk-circuits/src/mint/mint.rs +++ /dev/null @@ -1,96 +0,0 @@ -use crate::chips::swap::CondSwapChip; -use crate::chips::{is_constant::IsConstantChip, poseidon::PoseidonConfig}; -use crate::data::{Mint, Note, ParameterSet}; -use crate::params::load_params; -use crate::proof::Proof; -use crate::util::keygen_from_params; -use crate::{evm_verifier, Snark}; -use halo2_base::halo2_proofs::halo2curves::bn256::{Bn256, G1Affine}; -use halo2_base::halo2_proofs::plonk::VerifyingKey; -use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; -use halo2_base::halo2_proofs::{ - circuit::Layouter, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error, Instance, ProvingKey}, -}; -use rand::RngCore; - -impl Mint { - pub fn new(notes: [Note; L]) -> Self { - Mint { notes } - } - - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - instance: Column, - advice: Column, - poseidon_config: PoseidonConfig, - is_zero_chip: IsConstantChip, - swap_chip: CondSwapChip, - ) -> Result<(), Error> { - for (i, note) in self.notes.iter().enumerate() { - // Ensure note is of valid construction - let note_cells = note.enforce_constraints( - layouter.namespace(|| format!("note {i}")), - advice, - poseidon_config.clone(), - is_zero_chip.clone(), - swap_chip.clone(), - )?; - - // Constrain note details to public instances - layouter.constrain_instance(note_cells.cm.cell(), instance, i * 3)?; - layouter.constrain_instance(note_cells.value.cell(), instance, (i * 3) + 1)?; - layouter.constrain_instance(note_cells.source.cell(), instance, (i * 3) + 2)?; - } - - Ok(()) - } - - pub fn public_inputs(&self) -> Vec { - let mut inputs = vec![]; - - for note in self.notes.iter() { - // Expose the note details we need to verify in Ethereum - inputs.push(note.commitment().into()); - inputs.push(note.value().into()); - inputs.push(note.source().into()); - } - - inputs - } - - pub fn prove( - &self, - params: &ParamsKZG, - pk: &ProvingKey, - rng: impl RngCore, - ) -> Result { - let circuit = Self::default(); - let instance = self.public_inputs(); - let instances = &[instance.as_slice()]; - Proof::create(params, pk, circuit, instances, rng) - } - - pub fn snark(&self, params: ParameterSet) -> Result { - let (pk, _) = self.keygen(params); - - Snark::create( - self.clone(), - vec![self.public_inputs()], - load_params(params), - &pk, - ) - } - - pub fn evm_proof(&self, params: ParameterSet) -> Result, crate::Error> { - let (pk, _) = self.keygen(params); - - evm_verifier::gen_proof(params, &pk, self.clone(), &[&self.public_inputs()]) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} diff --git a/pkg/zk-circuits/src/mint/mint_verifier.yul b/pkg/zk-circuits/src/mint/mint_verifier.yul deleted file mode 100644 index fe1c077..0000000 --- a/pkg/zk-circuits/src/mint/mint_verifier.yul +++ /dev/null @@ -1,1596 +0,0 @@ - - object "plonk_verifier" { - code { - function allocate(size) -> ptr { - ptr := mload(0x40) - if eq(ptr, 0) { ptr := 0x60 } - mstore(0x40, add(ptr, size)) - } - let size := datasize("Runtime") - let offset := allocate(size) - datacopy(offset, dataoffset("Runtime"), size) - return(offset, size) - } - object "Runtime" { - code { - let success:bool := true - let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 - let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 - function validate_ec_point(x, y) -> valid:bool { - { - let x_lt_p:bool := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_lt_p:bool := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - valid := and(x_lt_p, y_lt_p) - } - { - let x_is_zero:bool := eq(x, 0) - let y_is_zero:bool := eq(y, 0) - let x_or_y_is_zero:bool := or(x_is_zero, y_is_zero) - let x_and_y_is_not_zero:bool := not(x_or_y_is_zero) - valid := and(x_and_y_is_not_zero, valid) - } - { - let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube := mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let x_cube_plus_3 := addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) - let y_square_eq_x_cube_plus_3:bool := eq(x_cube_plus_3, y_square) - valid := and(y_square_eq_x_cube_plus_3, valid) - } - } - mstore(0x20, mod(calldataload(0x0), f_q)) -mstore(0x40, mod(calldataload(0x20), f_q)) -mstore(0x60, mod(calldataload(0x40), f_q)) -mstore(0x0, 11051604434568129905274603767071032769468944362511933681002967722565578872981) - - { - let x := calldataload(0x60) - mstore(0x80, x) - let y := calldataload(0x80) - mstore(0xa0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0xa0) - mstore(0xc0, x) - let y := calldataload(0xc0) - mstore(0xe0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0xe0) - mstore(0x100, x) - let y := calldataload(0x100) - mstore(0x120, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x120) - mstore(0x140, x) - let y := calldataload(0x140) - mstore(0x160, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x160) - mstore(0x180, x) - let y := calldataload(0x180) - mstore(0x1a0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x1c0, keccak256(0x0, 448)) -{ - let hash := mload(0x1c0) - mstore(0x1e0, mod(hash, f_q)) - mstore(0x200, hash) - } -mstore8(544, 1) -mstore(0x220, keccak256(0x200, 33)) -{ - let hash := mload(0x220) - mstore(0x240, mod(hash, f_q)) - mstore(0x260, hash) - } -mstore8(640, 1) -mstore(0x280, keccak256(0x260, 33)) -{ - let hash := mload(0x280) - mstore(0x2a0, mod(hash, f_q)) - mstore(0x2c0, hash) - } - - { - let x := calldataload(0x1a0) - mstore(0x2e0, x) - let y := calldataload(0x1c0) - mstore(0x300, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x1e0) - mstore(0x320, x) - let y := calldataload(0x200) - mstore(0x340, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x220) - mstore(0x360, x) - let y := calldataload(0x240) - mstore(0x380, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x260) - mstore(0x3a0, x) - let y := calldataload(0x280) - mstore(0x3c0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x3e0, keccak256(0x2c0, 288)) -{ - let hash := mload(0x3e0) - mstore(0x400, mod(hash, f_q)) - mstore(0x420, hash) - } - - { - let x := calldataload(0x2a0) - mstore(0x440, x) - let y := calldataload(0x2c0) - mstore(0x460, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x2e0) - mstore(0x480, x) - let y := calldataload(0x300) - mstore(0x4a0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x320) - mstore(0x4c0, x) - let y := calldataload(0x340) - mstore(0x4e0, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x360) - mstore(0x500, x) - let y := calldataload(0x380) - mstore(0x520, y) - success := and(validate_ec_point(x, y), success) - } - - { - let x := calldataload(0x3a0) - mstore(0x540, x) - let y := calldataload(0x3c0) - mstore(0x560, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0x580, keccak256(0x420, 352)) -{ - let hash := mload(0x580) - mstore(0x5a0, mod(hash, f_q)) - mstore(0x5c0, hash) - } -mstore(0x5e0, mod(calldataload(0x3e0), f_q)) -mstore(0x600, mod(calldataload(0x400), f_q)) -mstore(0x620, mod(calldataload(0x420), f_q)) -mstore(0x640, mod(calldataload(0x440), f_q)) -mstore(0x660, mod(calldataload(0x460), f_q)) -mstore(0x680, mod(calldataload(0x480), f_q)) -mstore(0x6a0, mod(calldataload(0x4a0), f_q)) -mstore(0x6c0, mod(calldataload(0x4c0), f_q)) -mstore(0x6e0, mod(calldataload(0x4e0), f_q)) -mstore(0x700, mod(calldataload(0x500), f_q)) -mstore(0x720, mod(calldataload(0x520), f_q)) -mstore(0x740, mod(calldataload(0x540), f_q)) -mstore(0x760, mod(calldataload(0x560), f_q)) -mstore(0x780, mod(calldataload(0x580), f_q)) -mstore(0x7a0, mod(calldataload(0x5a0), f_q)) -mstore(0x7c0, mod(calldataload(0x5c0), f_q)) -mstore(0x7e0, mod(calldataload(0x5e0), f_q)) -mstore(0x800, mod(calldataload(0x600), f_q)) -mstore(0x820, mod(calldataload(0x620), f_q)) -mstore(0x840, mod(calldataload(0x640), f_q)) -mstore(0x860, mod(calldataload(0x660), f_q)) -mstore(0x880, mod(calldataload(0x680), f_q)) -mstore(0x8a0, mod(calldataload(0x6a0), f_q)) -mstore(0x8c0, mod(calldataload(0x6c0), f_q)) -mstore(0x8e0, mod(calldataload(0x6e0), f_q)) -mstore(0x900, mod(calldataload(0x700), f_q)) -mstore(0x920, mod(calldataload(0x720), f_q)) -mstore(0x940, mod(calldataload(0x740), f_q)) -mstore(0x960, mod(calldataload(0x760), f_q)) -mstore(0x980, mod(calldataload(0x780), f_q)) -mstore(0x9a0, mod(calldataload(0x7a0), f_q)) -mstore(0x9c0, mod(calldataload(0x7c0), f_q)) -mstore(0x9e0, mod(calldataload(0x7e0), f_q)) -mstore(0xa00, mod(calldataload(0x800), f_q)) -mstore(0xa20, mod(calldataload(0x820), f_q)) -mstore(0xa40, mod(calldataload(0x840), f_q)) -mstore(0xa60, mod(calldataload(0x860), f_q)) -mstore(0xa80, mod(calldataload(0x880), f_q)) -mstore(0xaa0, mod(calldataload(0x8a0), f_q)) -mstore(0xac0, mod(calldataload(0x8c0), f_q)) -mstore(0xae0, mod(calldataload(0x8e0), f_q)) -mstore(0xb00, mod(calldataload(0x900), f_q)) -mstore(0xb20, keccak256(0x5c0, 1376)) -{ - let hash := mload(0xb20) - mstore(0xb40, mod(hash, f_q)) - mstore(0xb60, hash) - } -mstore8(2944, 1) -mstore(0xb80, keccak256(0xb60, 33)) -{ - let hash := mload(0xb80) - mstore(0xba0, mod(hash, f_q)) - mstore(0xbc0, hash) - } - - { - let x := calldataload(0x920) - mstore(0xbe0, x) - let y := calldataload(0x940) - mstore(0xc00, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0xc20, keccak256(0xbc0, 96)) -{ - let hash := mload(0xc20) - mstore(0xc40, mod(hash, f_q)) - mstore(0xc60, hash) - } - - { - let x := calldataload(0x960) - mstore(0xc80, x) - let y := calldataload(0x980) - mstore(0xca0, y) - success := and(validate_ec_point(x, y), success) - } -mstore(0xcc0, mulmod(mload(0x5a0), mload(0x5a0), f_q)) -mstore(0xce0, mulmod(mload(0xcc0), mload(0xcc0), f_q)) -mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) -mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) -mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) -mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) -mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) -mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) -mstore(0xdc0, addmod(mload(0xda0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0xde0, mulmod(mload(0xdc0), 21802741923121153053409505722814863857733722351976909209543133076471996743681, f_q)) -mstore(0xe00, mulmod(mload(0xde0), 10167250710514084151592399827148084713285735496006016499965216114801401041468, f_q)) -mstore(0xe20, addmod(mload(0x5a0), 11720992161325191070654005918109190375262628904410017843732988071774407454149, f_q)) -mstore(0xe40, mulmod(mload(0xde0), 15620430616972136973029697708057142747056669543503469918700292712864029815878, f_q)) -mstore(0xe60, addmod(mload(0x5a0), 6267812254867138249216708037200132341491694856912564424997911473711778679739, f_q)) -mstore(0xe80, mulmod(mload(0xde0), 4658854783519236281304787251426829785380272013053939496434657852755686889074, f_q)) -mstore(0xea0, addmod(mload(0x5a0), 17229388088320038940941618493830445303168092387362094847263546333820121606543, f_q)) -mstore(0xec0, mulmod(mload(0xde0), 11423757818648818765461327411617109120243501240676889555478397529313037714234, f_q)) -mstore(0xee0, addmod(mload(0x5a0), 10464485053190456456785078333640165968304863159739144788219806657262770781383, f_q)) -mstore(0xf00, mulmod(mload(0xde0), 13677048343952077794467995888380402608453928821079198134318291065290235358859, f_q)) -mstore(0xf20, addmod(mload(0x5a0), 8211194527887197427778409856876872480094435579336836209379913121285573136758, f_q)) -mstore(0xf40, mulmod(mload(0xde0), 14158528901797138466244491986759313854666262535363044392173788062030301470987, f_q)) -mstore(0xf60, addmod(mload(0x5a0), 7729713970042136756001913758497961233882101865052989951524416124545507024630, f_q)) -mstore(0xf80, mulmod(mload(0xde0), 1, f_q)) -mstore(0xfa0, addmod(mload(0x5a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) -mstore(0xfc0, mulmod(mload(0xde0), 7393649265675507591155086225434297871937368251641985215568891852805958167681, f_q)) -mstore(0xfe0, addmod(mload(0x5a0), 14494593606163767631091319519822977216610996148774049128129312333769850327936, f_q)) -mstore(0x1000, mulmod(mload(0xde0), 18154240498369470423574571952998640420834620155273666494480695920805672807787, f_q)) -mstore(0x1020, addmod(mload(0x5a0), 3734002373469804798671833792258634667713744245142367849217508265770135687830, f_q)) -{ - let prod := mload(0xe20) - - prod := mulmod(mload(0xe60), prod, f_q) - mstore(0x1040, prod) - - prod := mulmod(mload(0xea0), prod, f_q) - mstore(0x1060, prod) - - prod := mulmod(mload(0xee0), prod, f_q) - mstore(0x1080, prod) - - prod := mulmod(mload(0xf20), prod, f_q) - mstore(0x10a0, prod) - - prod := mulmod(mload(0xf60), prod, f_q) - mstore(0x10c0, prod) - - prod := mulmod(mload(0xfa0), prod, f_q) - mstore(0x10e0, prod) - - prod := mulmod(mload(0xfe0), prod, f_q) - mstore(0x1100, prod) - - prod := mulmod(mload(0x1020), prod, f_q) - mstore(0x1120, prod) - - prod := mulmod(mload(0xdc0), prod, f_q) - mstore(0x1140, prod) - - } -mstore(0x1180, 32) -mstore(0x11a0, 32) -mstore(0x11c0, 32) -mstore(0x11e0, mload(0x1140)) -mstore(0x1200, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x1220, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x1180, 0xc0, 0x1160, 0x20), 1), success) -{ - - let inv := mload(0x1160) - let v - - v := mload(0xdc0) - mstore(3520, mulmod(mload(0x1120), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x1020) - mstore(4128, mulmod(mload(0x1100), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xfe0) - mstore(4064, mulmod(mload(0x10e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xfa0) - mstore(4000, mulmod(mload(0x10c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xf60) - mstore(3936, mulmod(mload(0x10a0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xf20) - mstore(3872, mulmod(mload(0x1080), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xee0) - mstore(3808, mulmod(mload(0x1060), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xea0) - mstore(3744, mulmod(mload(0x1040), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0xe60) - mstore(3680, mulmod(mload(0xe20), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0xe20, inv) - - } -mstore(0x1240, mulmod(mload(0xe00), mload(0xe20), f_q)) -mstore(0x1260, mulmod(mload(0xe40), mload(0xe60), f_q)) -mstore(0x1280, mulmod(mload(0xe80), mload(0xea0), f_q)) -mstore(0x12a0, mulmod(mload(0xec0), mload(0xee0), f_q)) -mstore(0x12c0, mulmod(mload(0xf00), mload(0xf20), f_q)) -mstore(0x12e0, mulmod(mload(0xf40), mload(0xf60), f_q)) -mstore(0x1300, mulmod(mload(0xf80), mload(0xfa0), f_q)) -mstore(0x1320, mulmod(mload(0xfc0), mload(0xfe0), f_q)) -mstore(0x1340, mulmod(mload(0x1000), mload(0x1020), f_q)) -{ - let result := mulmod(mload(0x1300), mload(0x20), f_q) -result := addmod(mulmod(mload(0x1320), mload(0x40), f_q), result, f_q) -result := addmod(mulmod(mload(0x1340), mload(0x60), f_q), result, f_q) -mstore(4960, result) - } -mstore(0x1380, addmod(mload(0x600), mload(0x740), f_q)) -mstore(0x13a0, mulmod(mload(0x1380), mload(0x1380), f_q)) -mstore(0x13c0, mulmod(mload(0x13a0), mload(0x13a0), f_q)) -mstore(0x13e0, mulmod(mload(0x1380), mload(0x13c0), f_q)) -mstore(0x1400, mulmod(mload(0x13e0), 7511745149465107256748700652201246547602992235352608707588321460060273774987, f_q)) -mstore(0x1420, addmod(mload(0x620), mload(0x7c0), f_q)) -mstore(0x1440, mulmod(mload(0x1420), mload(0x1420), f_q)) -mstore(0x1460, mulmod(mload(0x1440), mload(0x1440), f_q)) -mstore(0x1480, mulmod(mload(0x1420), mload(0x1460), f_q)) -mstore(0x14a0, mulmod(mload(0x1480), 10370080108974718697676803824769673834027675643658433702224577712625900127200, f_q)) -mstore(0x14c0, addmod(mload(0x1400), mload(0x14a0), f_q)) -mstore(0x14e0, addmod(mload(0x640), mload(0x7e0), f_q)) -mstore(0x1500, mulmod(mload(0x14e0), mload(0x14e0), f_q)) -mstore(0x1520, mulmod(mload(0x1500), mload(0x1500), f_q)) -mstore(0x1540, mulmod(mload(0x14e0), mload(0x1520), f_q)) -mstore(0x1560, mulmod(mload(0x1540), 19705173408229649878903981084052839426532978878058043055305024233888854471533, f_q)) -mstore(0x1580, addmod(mload(0x14c0), mload(0x1560), f_q)) -mstore(0x15a0, addmod(mload(0x1580), sub(f_q, mload(0x680)), f_q)) -mstore(0x15c0, mulmod(mload(0x15a0), mload(0x800), f_q)) -mstore(0x15e0, mulmod(mload(0x400), mload(0x15c0), f_q)) -mstore(0x1600, mulmod(mload(0x13e0), 18732019378264290557468133440468564866454307626475683536618613112504878618481, f_q)) -mstore(0x1620, mulmod(mload(0x1480), 20870176810702568768751421378473869562658540583882454726129544628203806653987, f_q)) -mstore(0x1640, addmod(mload(0x1600), mload(0x1620), f_q)) -mstore(0x1660, mulmod(mload(0x1540), 7266061498423634438633389053804536045105766754026813321943009179476902321146, f_q)) -mstore(0x1680, addmod(mload(0x1640), mload(0x1660), f_q)) -mstore(0x16a0, addmod(mload(0x1680), sub(f_q, mload(0x6a0)), f_q)) -mstore(0x16c0, mulmod(mload(0x16a0), mload(0x800), f_q)) -mstore(0x16e0, addmod(mload(0x15e0), mload(0x16c0), f_q)) -mstore(0x1700, mulmod(mload(0x400), mload(0x16e0), f_q)) -mstore(0x1720, mulmod(mload(0x13e0), 9131299761947733513298312097611845208338517739621853568979632113419485819303, f_q)) -mstore(0x1740, mulmod(mload(0x1480), 10595341252162738537912664445405114076324478519622938027420701542910180337937, f_q)) -mstore(0x1760, addmod(mload(0x1720), mload(0x1740), f_q)) -mstore(0x1780, mulmod(mload(0x1540), 11597556804922396090267472882856054602429588299176362916247939723151043581408, f_q)) -mstore(0x17a0, addmod(mload(0x1760), mload(0x1780), f_q)) -mstore(0x17c0, addmod(mload(0x17a0), sub(f_q, mload(0x6c0)), f_q)) -mstore(0x17e0, mulmod(mload(0x17c0), mload(0x800), f_q)) -mstore(0x1800, addmod(mload(0x1700), mload(0x17e0), f_q)) -mstore(0x1820, mulmod(mload(0x400), mload(0x1800), f_q)) -mstore(0x1840, addmod(mload(0x13e0), sub(f_q, mload(0x5e0)), f_q)) -mstore(0x1860, mulmod(mload(0x1840), mload(0x820), f_q)) -mstore(0x1880, addmod(mload(0x1820), mload(0x1860), f_q)) -mstore(0x18a0, mulmod(mload(0x400), mload(0x1880), f_q)) -mstore(0x18c0, mulmod(mload(0x5e0), 7511745149465107256748700652201246547602992235352608707588321460060273774987, f_q)) -mstore(0x18e0, mulmod(mload(0x1420), 10370080108974718697676803824769673834027675643658433702224577712625900127200, f_q)) -mstore(0x1900, addmod(mload(0x18c0), mload(0x18e0), f_q)) -mstore(0x1920, mulmod(mload(0x14e0), 19705173408229649878903981084052839426532978878058043055305024233888854471533, f_q)) -mstore(0x1940, addmod(mload(0x1900), mload(0x1920), f_q)) -mstore(0x1960, addmod(mload(0x1940), mload(0x760), f_q)) -mstore(0x1980, mulmod(mload(0x1960), mload(0x1960), f_q)) -mstore(0x19a0, mulmod(mload(0x1980), mload(0x1980), f_q)) -mstore(0x19c0, mulmod(mload(0x1960), mload(0x19a0), f_q)) -mstore(0x19e0, mulmod(mload(0x680), 14581990407185373640425896461718924180109794780799188900903678642755512839974, f_q)) -mstore(0x1a00, mulmod(mload(0x6a0), 18866968878651837536281064213261914109651535895144158735451177080294903852066, f_q)) -mstore(0x1a20, addmod(mload(0x19e0), mload(0x1a00), f_q)) -mstore(0x1a40, mulmod(mload(0x6c0), 7839627026775837327267018712780335784833794955194428770232963186824469625450, f_q)) -mstore(0x1a60, addmod(mload(0x1a20), mload(0x1a40), f_q)) -mstore(0x1a80, addmod(mload(0x19c0), sub(f_q, mload(0x1a60)), f_q)) -mstore(0x1aa0, mulmod(mload(0x1a80), mload(0x820), f_q)) -mstore(0x1ac0, addmod(mload(0x18a0), mload(0x1aa0), f_q)) -mstore(0x1ae0, mulmod(mload(0x400), mload(0x1ac0), f_q)) -mstore(0x1b00, mulmod(mload(0x5e0), 18732019378264290557468133440468564866454307626475683536618613112504878618481, f_q)) -mstore(0x1b20, mulmod(mload(0x1420), 20870176810702568768751421378473869562658540583882454726129544628203806653987, f_q)) -mstore(0x1b40, addmod(mload(0x1b00), mload(0x1b20), f_q)) -mstore(0x1b60, mulmod(mload(0x14e0), 7266061498423634438633389053804536045105766754026813321943009179476902321146, f_q)) -mstore(0x1b80, addmod(mload(0x1b40), mload(0x1b60), f_q)) -mstore(0x1ba0, addmod(mload(0x1b80), mload(0x780), f_q)) -mstore(0x1bc0, mulmod(mload(0x680), 18938579070830856475783700955955783311402730090941909099413093949983854639956, f_q)) -mstore(0x1be0, mulmod(mload(0x6a0), 8613994242085266665256493323589366394657716111166474713216639394202078033993, f_q)) -mstore(0x1c00, addmod(mload(0x1bc0), mload(0x1be0), f_q)) -mstore(0x1c20, mulmod(mload(0x6c0), 5498488707276883206944027953979269171532592088279065622083714982398440150521, f_q)) -mstore(0x1c40, addmod(mload(0x1c00), mload(0x1c20), f_q)) -mstore(0x1c60, addmod(mload(0x1ba0), sub(f_q, mload(0x1c40)), f_q)) -mstore(0x1c80, mulmod(mload(0x1c60), mload(0x820), f_q)) -mstore(0x1ca0, addmod(mload(0x1ae0), mload(0x1c80), f_q)) -mstore(0x1cc0, mulmod(mload(0x400), mload(0x1ca0), f_q)) -mstore(0x1ce0, mulmod(mload(0x5e0), 9131299761947733513298312097611845208338517739621853568979632113419485819303, f_q)) -mstore(0x1d00, mulmod(mload(0x1420), 10595341252162738537912664445405114076324478519622938027420701542910180337937, f_q)) -mstore(0x1d20, addmod(mload(0x1ce0), mload(0x1d00), f_q)) -mstore(0x1d40, mulmod(mload(0x14e0), 11597556804922396090267472882856054602429588299176362916247939723151043581408, f_q)) -mstore(0x1d60, addmod(mload(0x1d20), mload(0x1d40), f_q)) -mstore(0x1d80, addmod(mload(0x1d60), mload(0x7a0), f_q)) -mstore(0x1da0, mulmod(mload(0x680), 655752878747070013666604006434797489161341466456915955415098407670323222025, f_q)) -mstore(0x1dc0, mulmod(mload(0x6a0), 4856172836225950379592127603074379105027349156448153533703883389233432728400, f_q)) -mstore(0x1de0, addmod(mload(0x1da0), mload(0x1dc0), f_q)) -mstore(0x1e00, mulmod(mload(0x6c0), 10503264605839191981081969978629584646259107387222177725485772749763096823552, f_q)) -mstore(0x1e20, addmod(mload(0x1de0), mload(0x1e00), f_q)) -mstore(0x1e40, addmod(mload(0x1d80), sub(f_q, mload(0x1e20)), f_q)) -mstore(0x1e60, mulmod(mload(0x1e40), mload(0x820), f_q)) -mstore(0x1e80, addmod(mload(0x1cc0), mload(0x1e60), f_q)) -mstore(0x1ea0, mulmod(mload(0x400), mload(0x1e80), f_q)) -mstore(0x1ec0, addmod(mload(0x18e0), mload(0x1920), f_q)) -mstore(0x1ee0, addmod(mload(0x1400), mload(0x1ec0), f_q)) -mstore(0x1f00, addmod(mload(0x1ee0), sub(f_q, mload(0x680)), f_q)) -mstore(0x1f20, mulmod(mload(0x1f00), mload(0x840), f_q)) -mstore(0x1f40, addmod(mload(0x1ea0), mload(0x1f20), f_q)) -mstore(0x1f60, mulmod(mload(0x400), mload(0x1f40), f_q)) -mstore(0x1f80, addmod(mload(0x1b20), mload(0x1b60), f_q)) -mstore(0x1fa0, addmod(mload(0x1600), mload(0x1f80), f_q)) -mstore(0x1fc0, addmod(mload(0x1fa0), sub(f_q, mload(0x6a0)), f_q)) -mstore(0x1fe0, mulmod(mload(0x1fc0), mload(0x840), f_q)) -mstore(0x2000, addmod(mload(0x1f60), mload(0x1fe0), f_q)) -mstore(0x2020, mulmod(mload(0x400), mload(0x2000), f_q)) -mstore(0x2040, addmod(mload(0x1d00), mload(0x1d40), f_q)) -mstore(0x2060, addmod(mload(0x1720), mload(0x2040), f_q)) -mstore(0x2080, addmod(mload(0x2060), sub(f_q, mload(0x6c0)), f_q)) -mstore(0x20a0, mulmod(mload(0x2080), mload(0x840), f_q)) -mstore(0x20c0, addmod(mload(0x2020), mload(0x20a0), f_q)) -mstore(0x20e0, mulmod(mload(0x400), mload(0x20c0), f_q)) -mstore(0x2100, addmod(mload(0x700), mload(0x600), f_q)) -mstore(0x2120, addmod(mload(0x2100), sub(f_q, mload(0x680)), f_q)) -mstore(0x2140, mulmod(mload(0x2120), mload(0x860), f_q)) -mstore(0x2160, addmod(mload(0x20e0), mload(0x2140), f_q)) -mstore(0x2180, mulmod(mload(0x400), mload(0x2160), f_q)) -mstore(0x21a0, addmod(mload(0x720), mload(0x620), f_q)) -mstore(0x21c0, addmod(mload(0x21a0), sub(f_q, mload(0x6a0)), f_q)) -mstore(0x21e0, mulmod(mload(0x21c0), mload(0x860), f_q)) -mstore(0x2200, addmod(mload(0x2180), mload(0x21e0), f_q)) -mstore(0x2220, mulmod(mload(0x400), mload(0x2200), f_q)) -mstore(0x2240, addmod(mload(0x6e0), sub(f_q, mload(0x6c0)), f_q)) -mstore(0x2260, mulmod(mload(0x2240), mload(0x860), f_q)) -mstore(0x2280, addmod(mload(0x2220), mload(0x2260), f_q)) -mstore(0x22a0, mulmod(mload(0x400), mload(0x2280), f_q)) -mstore(0x22c0, mulmod(mload(0x600), mload(0x660), f_q)) -mstore(0x22e0, addmod(1, sub(f_q, mload(0x660)), f_q)) -mstore(0x2300, mulmod(mload(0x5e0), mload(0x22e0), f_q)) -mstore(0x2320, addmod(mload(0x22c0), mload(0x2300), f_q)) -mstore(0x2340, addmod(mload(0x620), sub(f_q, mload(0x2320)), f_q)) -mstore(0x2360, mulmod(mload(0x2340), mload(0x880), f_q)) -mstore(0x2380, addmod(mload(0x22a0), mload(0x2360), f_q)) -mstore(0x23a0, mulmod(mload(0x400), mload(0x2380), f_q)) -mstore(0x23c0, mulmod(mload(0x5e0), mload(0x660), f_q)) -mstore(0x23e0, mulmod(mload(0x600), mload(0x22e0), f_q)) -mstore(0x2400, addmod(mload(0x23c0), mload(0x23e0), f_q)) -mstore(0x2420, addmod(mload(0x640), sub(f_q, mload(0x2400)), f_q)) -mstore(0x2440, mulmod(mload(0x2420), mload(0x880), f_q)) -mstore(0x2460, addmod(mload(0x23a0), mload(0x2440), f_q)) -mstore(0x2480, mulmod(mload(0x400), mload(0x2460), f_q)) -mstore(0x24a0, mulmod(mload(0x22e0), mload(0x660), f_q)) -mstore(0x24c0, mulmod(mload(0x24a0), mload(0x880), f_q)) -mstore(0x24e0, addmod(mload(0x2480), mload(0x24c0), f_q)) -mstore(0x2500, mulmod(mload(0x400), mload(0x24e0), f_q)) -mstore(0x2520, addmod(mload(0x5e0), 21888242871839275222246405745257275088548364400416034343698204186575808495617, f_q)) -mstore(0x2540, mulmod(mload(0x2520), mload(0x8a0), f_q)) -mstore(0x2560, mulmod(mload(0x600), mload(0x2520), f_q)) -mstore(0x2580, addmod(1, sub(f_q, mload(0x2560)), f_q)) -mstore(0x25a0, mulmod(mload(0x2580), mload(0x2540), f_q)) -mstore(0x25c0, addmod(mload(0x2500), mload(0x25a0), f_q)) -mstore(0x25e0, mulmod(mload(0x400), mload(0x25c0), f_q)) -mstore(0x2600, addmod(mload(0x620), sub(f_q, mload(0x2580)), f_q)) -mstore(0x2620, mulmod(mload(0x2600), mload(0x8a0), f_q)) -mstore(0x2640, addmod(mload(0x25e0), mload(0x2620), f_q)) -mstore(0x2660, mulmod(mload(0x400), mload(0x2640), f_q)) -mstore(0x2680, addmod(1, sub(f_q, mload(0xa20)), f_q)) -mstore(0x26a0, mulmod(mload(0x2680), mload(0x1300), f_q)) -mstore(0x26c0, addmod(mload(0x2660), mload(0x26a0), f_q)) -mstore(0x26e0, mulmod(mload(0x400), mload(0x26c0), f_q)) -mstore(0x2700, mulmod(mload(0xae0), mload(0xae0), f_q)) -mstore(0x2720, addmod(mload(0x2700), sub(f_q, mload(0xae0)), f_q)) -mstore(0x2740, mulmod(mload(0x2720), mload(0x1240), f_q)) -mstore(0x2760, addmod(mload(0x26e0), mload(0x2740), f_q)) -mstore(0x2780, mulmod(mload(0x400), mload(0x2760), f_q)) -mstore(0x27a0, addmod(mload(0xa80), sub(f_q, mload(0xa60)), f_q)) -mstore(0x27c0, mulmod(mload(0x27a0), mload(0x1300), f_q)) -mstore(0x27e0, addmod(mload(0x2780), mload(0x27c0), f_q)) -mstore(0x2800, mulmod(mload(0x400), mload(0x27e0), f_q)) -mstore(0x2820, addmod(mload(0xae0), sub(f_q, mload(0xac0)), f_q)) -mstore(0x2840, mulmod(mload(0x2820), mload(0x1300), f_q)) -mstore(0x2860, addmod(mload(0x2800), mload(0x2840), f_q)) -mstore(0x2880, mulmod(mload(0x400), mload(0x2860), f_q)) -mstore(0x28a0, addmod(1, sub(f_q, mload(0x1240)), f_q)) -mstore(0x28c0, addmod(mload(0x1260), mload(0x1280), f_q)) -mstore(0x28e0, addmod(mload(0x28c0), mload(0x12a0), f_q)) -mstore(0x2900, addmod(mload(0x28e0), mload(0x12c0), f_q)) -mstore(0x2920, addmod(mload(0x2900), mload(0x12e0), f_q)) -mstore(0x2940, addmod(mload(0x28a0), sub(f_q, mload(0x2920)), f_q)) -mstore(0x2960, mulmod(mload(0x8e0), mload(0x240), f_q)) -mstore(0x2980, addmod(mload(0x1360), mload(0x2960), f_q)) -mstore(0x29a0, addmod(mload(0x2980), mload(0x2a0), f_q)) -mstore(0x29c0, mulmod(mload(0x900), mload(0x240), f_q)) -mstore(0x29e0, addmod(mload(0x5e0), mload(0x29c0), f_q)) -mstore(0x2a00, addmod(mload(0x29e0), mload(0x2a0), f_q)) -mstore(0x2a20, mulmod(mload(0x2a00), mload(0x29a0), f_q)) -mstore(0x2a40, mulmod(mload(0x920), mload(0x240), f_q)) -mstore(0x2a60, addmod(mload(0x600), mload(0x2a40), f_q)) -mstore(0x2a80, addmod(mload(0x2a60), mload(0x2a0), f_q)) -mstore(0x2aa0, mulmod(mload(0x2a80), mload(0x2a20), f_q)) -mstore(0x2ac0, mulmod(mload(0x940), mload(0x240), f_q)) -mstore(0x2ae0, addmod(mload(0x620), mload(0x2ac0), f_q)) -mstore(0x2b00, addmod(mload(0x2ae0), mload(0x2a0), f_q)) -mstore(0x2b20, mulmod(mload(0x2b00), mload(0x2aa0), f_q)) -mstore(0x2b40, mulmod(mload(0x2b20), mload(0xa40), f_q)) -mstore(0x2b60, mulmod(1, mload(0x240), f_q)) -mstore(0x2b80, mulmod(mload(0x5a0), mload(0x2b60), f_q)) -mstore(0x2ba0, addmod(mload(0x1360), mload(0x2b80), f_q)) -mstore(0x2bc0, addmod(mload(0x2ba0), mload(0x2a0), f_q)) -mstore(0x2be0, mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x240), f_q)) -mstore(0x2c00, mulmod(mload(0x5a0), mload(0x2be0), f_q)) -mstore(0x2c20, addmod(mload(0x5e0), mload(0x2c00), f_q)) -mstore(0x2c40, addmod(mload(0x2c20), mload(0x2a0), f_q)) -mstore(0x2c60, mulmod(mload(0x2c40), mload(0x2bc0), f_q)) -mstore(0x2c80, mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x240), f_q)) -mstore(0x2ca0, mulmod(mload(0x5a0), mload(0x2c80), f_q)) -mstore(0x2cc0, addmod(mload(0x600), mload(0x2ca0), f_q)) -mstore(0x2ce0, addmod(mload(0x2cc0), mload(0x2a0), f_q)) -mstore(0x2d00, mulmod(mload(0x2ce0), mload(0x2c60), f_q)) -mstore(0x2d20, mulmod(11166246659983828508719468090013646171463329086121580628794302409516816350802, mload(0x240), f_q)) -mstore(0x2d40, mulmod(mload(0x5a0), mload(0x2d20), f_q)) -mstore(0x2d60, addmod(mload(0x620), mload(0x2d40), f_q)) -mstore(0x2d80, addmod(mload(0x2d60), mload(0x2a0), f_q)) -mstore(0x2da0, mulmod(mload(0x2d80), mload(0x2d00), f_q)) -mstore(0x2dc0, mulmod(mload(0x2da0), mload(0xa20), f_q)) -mstore(0x2de0, addmod(mload(0x2b40), sub(f_q, mload(0x2dc0)), f_q)) -mstore(0x2e00, mulmod(mload(0x2de0), mload(0x2940), f_q)) -mstore(0x2e20, addmod(mload(0x2880), mload(0x2e00), f_q)) -mstore(0x2e40, mulmod(mload(0x400), mload(0x2e20), f_q)) -mstore(0x2e60, mulmod(mload(0x960), mload(0x240), f_q)) -mstore(0x2e80, addmod(mload(0x640), mload(0x2e60), f_q)) -mstore(0x2ea0, addmod(mload(0x2e80), mload(0x2a0), f_q)) -mstore(0x2ec0, mulmod(mload(0x980), mload(0x240), f_q)) -mstore(0x2ee0, addmod(mload(0x660), mload(0x2ec0), f_q)) -mstore(0x2f00, addmod(mload(0x2ee0), mload(0x2a0), f_q)) -mstore(0x2f20, mulmod(mload(0x2f00), mload(0x2ea0), f_q)) -mstore(0x2f40, mulmod(mload(0x9a0), mload(0x240), f_q)) -mstore(0x2f60, addmod(mload(0x740), mload(0x2f40), f_q)) -mstore(0x2f80, addmod(mload(0x2f60), mload(0x2a0), f_q)) -mstore(0x2fa0, mulmod(mload(0x2f80), mload(0x2f20), f_q)) -mstore(0x2fc0, mulmod(mload(0x9c0), mload(0x240), f_q)) -mstore(0x2fe0, addmod(mload(0x760), mload(0x2fc0), f_q)) -mstore(0x3000, addmod(mload(0x2fe0), mload(0x2a0), f_q)) -mstore(0x3020, mulmod(mload(0x3000), mload(0x2fa0), f_q)) -mstore(0x3040, mulmod(mload(0x3020), mload(0xaa0), f_q)) -mstore(0x3060, mulmod(284840088355319032285349970403338060113257071685626700086398481893096618818, mload(0x240), f_q)) -mstore(0x3080, mulmod(mload(0x5a0), mload(0x3060), f_q)) -mstore(0x30a0, addmod(mload(0x640), mload(0x3080), f_q)) -mstore(0x30c0, addmod(mload(0x30a0), mload(0x2a0), f_q)) -mstore(0x30e0, mulmod(21134065618345176623193549882539580312263652408302468683943992798037078993309, mload(0x240), f_q)) -mstore(0x3100, mulmod(mload(0x5a0), mload(0x30e0), f_q)) -mstore(0x3120, addmod(mload(0x660), mload(0x3100), f_q)) -mstore(0x3140, addmod(mload(0x3120), mload(0x2a0), f_q)) -mstore(0x3160, mulmod(mload(0x3140), mload(0x30c0), f_q)) -mstore(0x3180, mulmod(5625741653535312224677218588085279924365897425605943700675464992185016992283, mload(0x240), f_q)) -mstore(0x31a0, mulmod(mload(0x5a0), mload(0x3180), f_q)) -mstore(0x31c0, addmod(mload(0x740), mload(0x31a0), f_q)) -mstore(0x31e0, addmod(mload(0x31c0), mload(0x2a0), f_q)) -mstore(0x3200, mulmod(mload(0x31e0), mload(0x3160), f_q)) -mstore(0x3220, mulmod(14704729814417906439424896605881467874595262020190401576785074330126828718155, mload(0x240), f_q)) -mstore(0x3240, mulmod(mload(0x5a0), mload(0x3220), f_q)) -mstore(0x3260, addmod(mload(0x760), mload(0x3240), f_q)) -mstore(0x3280, addmod(mload(0x3260), mload(0x2a0), f_q)) -mstore(0x32a0, mulmod(mload(0x3280), mload(0x3200), f_q)) -mstore(0x32c0, mulmod(mload(0x32a0), mload(0xa80), f_q)) -mstore(0x32e0, addmod(mload(0x3040), sub(f_q, mload(0x32c0)), f_q)) -mstore(0x3300, mulmod(mload(0x32e0), mload(0x2940), f_q)) -mstore(0x3320, addmod(mload(0x2e40), mload(0x3300), f_q)) -mstore(0x3340, mulmod(mload(0x400), mload(0x3320), f_q)) -mstore(0x3360, mulmod(mload(0x9e0), mload(0x240), f_q)) -mstore(0x3380, addmod(mload(0x780), mload(0x3360), f_q)) -mstore(0x33a0, addmod(mload(0x3380), mload(0x2a0), f_q)) -mstore(0x33c0, mulmod(mload(0xa00), mload(0x240), f_q)) -mstore(0x33e0, addmod(mload(0x7a0), mload(0x33c0), f_q)) -mstore(0x3400, addmod(mload(0x33e0), mload(0x2a0), f_q)) -mstore(0x3420, mulmod(mload(0x3400), mload(0x33a0), f_q)) -mstore(0x3440, mulmod(mload(0x3420), mload(0xb00), f_q)) -mstore(0x3460, mulmod(8343274462013750416000956870576256937330525306073862550863787263304548803879, mload(0x240), f_q)) -mstore(0x3480, mulmod(mload(0x5a0), mload(0x3460), f_q)) -mstore(0x34a0, addmod(mload(0x780), mload(0x3480), f_q)) -mstore(0x34c0, addmod(mload(0x34a0), mload(0x2a0), f_q)) -mstore(0x34e0, mulmod(20928372310071051017340352686640453451620397549739756658327314209761852842004, mload(0x240), f_q)) -mstore(0x3500, mulmod(mload(0x5a0), mload(0x34e0), f_q)) -mstore(0x3520, addmod(mload(0x7a0), mload(0x3500), f_q)) -mstore(0x3540, addmod(mload(0x3520), mload(0x2a0), f_q)) -mstore(0x3560, mulmod(mload(0x3540), mload(0x34c0), f_q)) -mstore(0x3580, mulmod(mload(0x3560), mload(0xae0), f_q)) -mstore(0x35a0, addmod(mload(0x3440), sub(f_q, mload(0x3580)), f_q)) -mstore(0x35c0, mulmod(mload(0x35a0), mload(0x2940), f_q)) -mstore(0x35e0, addmod(mload(0x3340), mload(0x35c0), f_q)) -mstore(0x3600, mulmod(mload(0xda0), mload(0xda0), f_q)) -mstore(0x3620, mulmod(mload(0x3600), mload(0xda0), f_q)) -mstore(0x3640, mulmod(mload(0x3620), mload(0xda0), f_q)) -mstore(0x3660, mulmod(mload(0x3640), mload(0xda0), f_q)) -mstore(0x3680, mulmod(1, mload(0xda0), f_q)) -mstore(0x36a0, mulmod(1, mload(0x3600), f_q)) -mstore(0x36c0, mulmod(1, mload(0x3620), f_q)) -mstore(0x36e0, mulmod(1, mload(0x3640), f_q)) -mstore(0x3700, mulmod(mload(0x35e0), mload(0xdc0), f_q)) -mstore(0x3720, mulmod(mload(0x5a0), 1, f_q)) -mstore(0x3740, addmod(mload(0xc40), sub(f_q, mload(0x3720)), f_q)) -mstore(0x3760, mulmod(mload(0x5a0), 7393649265675507591155086225434297871937368251641985215568891852805958167681, f_q)) -mstore(0x3780, addmod(mload(0xc40), sub(f_q, mload(0x3760)), f_q)) -mstore(0x37a0, mulmod(mload(0x5a0), 10167250710514084151592399827148084713285735496006016499965216114801401041468, f_q)) -mstore(0x37c0, addmod(mload(0xc40), sub(f_q, mload(0x37a0)), f_q)) -mstore(0x37e0, mulmod(mload(0x5a0), 14158528901797138466244491986759313854666262535363044392173788062030301470987, f_q)) -mstore(0x3800, addmod(mload(0xc40), sub(f_q, mload(0x37e0)), f_q)) -{ - let result := mulmod(mload(0xc40), 1, f_q) -result := addmod(mulmod(mload(0x5a0), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q), result, f_q) -mstore(14368, result) - } -mstore(0x3840, mulmod(1, mload(0x3740), f_q)) -{ - let result := mulmod(mload(0xc40), 336064704366629164846827533063663361944733613411004735955524271739548856951, f_q) -result := addmod(mulmod(mload(0x5a0), 21552178167472646057399578212193611726603630787005029607742679914836259638666, f_q), result, f_q) -mstore(14432, result) - } -{ - let result := mulmod(mload(0xc40), 3030877262651826076417571969066381315015150038578691327387387943454207615475, f_q) -result := addmod(mulmod(mload(0x5a0), 14391901014454789459162553807845746888032227144654257069993329772708615854226, f_q), result, f_q) -mstore(14464, result) - } -{ - let result := mulmod(mload(0xc40), 6912168707830446919378590127055386625725034537358138957713394856065892055552, f_q) -result := addmod(mulmod(mload(0x5a0), 16411819427100397495251160463522607342876690115765352971013681598007499115611, f_q), result, f_q) -mstore(14496, result) - } -mstore(0x38c0, mulmod(mload(0x3840), mload(0x3780), f_q)) -mstore(0x38e0, mulmod(mload(0x38c0), mload(0x3800), f_q)) -{ - let result := mulmod(mload(0xc40), 19947773512621820452528617400732035250381930196271502546864388931832479102347, f_q) -result := addmod(mulmod(mload(0x5a0), 1940469359217454769717788344525239838166434204144531796833815254743329393270, f_q), result, f_q) -mstore(14592, result) - } -{ - let result := mulmod(mload(0xc40), 5307411326235910010982187846655284515126317856134227860176727469937085865696, f_q) -result := addmod(mulmod(mload(0x5a0), 17924918787165656398528962871038411142966825762978775775857007246370123255359, f_q), result, f_q) -mstore(14624, result) - } -{ - let result := mulmod(mload(0xc40), 2868352760655725740670530120331463788036206322158892420596360852137805089611, f_q) -result := addmod(mulmod(mload(0x5a0), 10564729777571317642127391059634284919194202867615836652533661042770582751185, f_q), result, f_q) -mstore(14656, result) - } -mstore(0x3960, mulmod(mload(0x38c0), mload(0x37c0), f_q)) -{ - let result := mulmod(mload(0xc40), 14494593606163767631091319519822977216610996148774049128129312333769850327937, f_q) -result := addmod(mulmod(mload(0x5a0), 7393649265675507591155086225434297871937368251641985215568891852805958167680, f_q), result, f_q) -mstore(14720, result) - } -{ - let result := mulmod(mload(0xc40), 7393649265675507591155086225434297871937368251641985215568891852805958167680, f_q) -result := addmod(mulmod(mload(0x5a0), 11127651639145312389826920017692932539651112496784353064786400118576093855511, f_q), result, f_q) -mstore(14752, result) - } -{ - let prod := mload(0x3820) - - prod := mulmod(mload(0x3860), prod, f_q) - mstore(0x39c0, prod) - - prod := mulmod(mload(0x3880), prod, f_q) - mstore(0x39e0, prod) - - prod := mulmod(mload(0x38a0), prod, f_q) - mstore(0x3a00, prod) - - prod := mulmod(mload(0x38e0), prod, f_q) - mstore(0x3a20, prod) - - prod := mulmod(mload(0x3900), prod, f_q) - mstore(0x3a40, prod) - - prod := mulmod(mload(0x3920), prod, f_q) - mstore(0x3a60, prod) - - prod := mulmod(mload(0x3940), prod, f_q) - mstore(0x3a80, prod) - - prod := mulmod(mload(0x3960), prod, f_q) - mstore(0x3aa0, prod) - - prod := mulmod(mload(0x3980), prod, f_q) - mstore(0x3ac0, prod) - - prod := mulmod(mload(0x39a0), prod, f_q) - mstore(0x3ae0, prod) - - prod := mulmod(mload(0x38c0), prod, f_q) - mstore(0x3b00, prod) - - } -mstore(0x3b40, 32) -mstore(0x3b60, 32) -mstore(0x3b80, 32) -mstore(0x3ba0, mload(0x3b00)) -mstore(0x3bc0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x3be0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x3b40, 0xc0, 0x3b20, 0x20), 1), success) -{ - - let inv := mload(0x3b20) - let v - - v := mload(0x38c0) - mstore(14528, mulmod(mload(0x3ae0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x39a0) - mstore(14752, mulmod(mload(0x3ac0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3980) - mstore(14720, mulmod(mload(0x3aa0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3960) - mstore(14688, mulmod(mload(0x3a80), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3940) - mstore(14656, mulmod(mload(0x3a60), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3920) - mstore(14624, mulmod(mload(0x3a40), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3900) - mstore(14592, mulmod(mload(0x3a20), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x38e0) - mstore(14560, mulmod(mload(0x3a00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x38a0) - mstore(14496, mulmod(mload(0x39e0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3880) - mstore(14464, mulmod(mload(0x39c0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3860) - mstore(14432, mulmod(mload(0x3820), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x3820, inv) - - } -{ - let result := mload(0x3820) -mstore(15360, result) - } -mstore(0x3c20, mulmod(mload(0x3840), mload(0x38e0), f_q)) -{ - let result := mload(0x3860) -result := addmod(mload(0x3880), result, f_q) -result := addmod(mload(0x38a0), result, f_q) -mstore(15424, result) - } -mstore(0x3c60, mulmod(mload(0x3840), mload(0x3960), f_q)) -{ - let result := mload(0x3900) -result := addmod(mload(0x3920), result, f_q) -result := addmod(mload(0x3940), result, f_q) -mstore(15488, result) - } -mstore(0x3ca0, mulmod(mload(0x3840), mload(0x38c0), f_q)) -{ - let result := mload(0x3980) -result := addmod(mload(0x39a0), result, f_q) -mstore(15552, result) - } -{ - let prod := mload(0x3c00) - - prod := mulmod(mload(0x3c40), prod, f_q) - mstore(0x3ce0, prod) - - prod := mulmod(mload(0x3c80), prod, f_q) - mstore(0x3d00, prod) - - prod := mulmod(mload(0x3cc0), prod, f_q) - mstore(0x3d20, prod) - - } -mstore(0x3d60, 32) -mstore(0x3d80, 32) -mstore(0x3da0, 32) -mstore(0x3dc0, mload(0x3d20)) -mstore(0x3de0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) -mstore(0x3e00, 21888242871839275222246405745257275088548364400416034343698204186575808495617) -success := and(eq(staticcall(gas(), 0x5, 0x3d60, 0xc0, 0x3d40, 0x20), 1), success) -{ - - let inv := mload(0x3d40) - let v - - v := mload(0x3cc0) - mstore(15552, mulmod(mload(0x3d00), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3c80) - mstore(15488, mulmod(mload(0x3ce0), inv, f_q)) - inv := mulmod(v, inv, f_q) - - v := mload(0x3c40) - mstore(15424, mulmod(mload(0x3c00), inv, f_q)) - inv := mulmod(v, inv, f_q) - mstore(0x3c00, inv) - - } -mstore(0x3e20, mulmod(mload(0x3c20), mload(0x3c40), f_q)) -mstore(0x3e40, mulmod(mload(0x3c60), mload(0x3c80), f_q)) -mstore(0x3e60, mulmod(mload(0x3ca0), mload(0x3cc0), f_q)) -mstore(0x3e80, mulmod(mload(0xb40), mload(0xb40), f_q)) -mstore(0x3ea0, mulmod(mload(0x3e80), mload(0xb40), f_q)) -mstore(0x3ec0, mulmod(mload(0x3ea0), mload(0xb40), f_q)) -mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0xb40), f_q)) -mstore(0x3f00, mulmod(mload(0x3ee0), mload(0xb40), f_q)) -mstore(0x3f20, mulmod(mload(0x3f00), mload(0xb40), f_q)) -mstore(0x3f40, mulmod(mload(0x3f20), mload(0xb40), f_q)) -mstore(0x3f60, mulmod(mload(0x3f40), mload(0xb40), f_q)) -mstore(0x3f80, mulmod(mload(0x3f60), mload(0xb40), f_q)) -mstore(0x3fa0, mulmod(mload(0x3f80), mload(0xb40), f_q)) -mstore(0x3fc0, mulmod(mload(0x3fa0), mload(0xb40), f_q)) -mstore(0x3fe0, mulmod(mload(0x3fc0), mload(0xb40), f_q)) -mstore(0x4000, mulmod(mload(0x3fe0), mload(0xb40), f_q)) -mstore(0x4020, mulmod(mload(0x4000), mload(0xb40), f_q)) -mstore(0x4040, mulmod(mload(0x4020), mload(0xb40), f_q)) -mstore(0x4060, mulmod(mload(0x4040), mload(0xb40), f_q)) -mstore(0x4080, mulmod(mload(0x4060), mload(0xb40), f_q)) -mstore(0x40a0, mulmod(mload(0x4080), mload(0xb40), f_q)) -mstore(0x40c0, mulmod(mload(0x40a0), mload(0xb40), f_q)) -mstore(0x40e0, mulmod(mload(0x40c0), mload(0xb40), f_q)) -mstore(0x4100, mulmod(mload(0x40e0), mload(0xb40), f_q)) -mstore(0x4120, mulmod(mload(0x4100), mload(0xb40), f_q)) -mstore(0x4140, mulmod(mload(0x4120), mload(0xb40), f_q)) -mstore(0x4160, mulmod(mload(0x4140), mload(0xb40), f_q)) -mstore(0x4180, mulmod(mload(0x4160), mload(0xb40), f_q)) -mstore(0x41a0, mulmod(mload(0xba0), mload(0xba0), f_q)) -mstore(0x41c0, mulmod(mload(0x41a0), mload(0xba0), f_q)) -mstore(0x41e0, mulmod(mload(0x41c0), mload(0xba0), f_q)) -{ - let result := mulmod(mload(0x5e0), mload(0x3820), f_q) -mstore(16896, result) - } -mstore(0x4220, mulmod(mload(0x4200), mload(0x3c00), f_q)) -mstore(0x4240, mulmod(sub(f_q, mload(0x4220)), 1, f_q)) -{ - let result := mulmod(mload(0x660), mload(0x3820), f_q) -mstore(16992, result) - } -mstore(0x4280, mulmod(mload(0x4260), mload(0x3c00), f_q)) -mstore(0x42a0, mulmod(sub(f_q, mload(0x4280)), mload(0xb40), f_q)) -mstore(0x42c0, mulmod(1, mload(0xb40), f_q)) -mstore(0x42e0, addmod(mload(0x4240), mload(0x42a0), f_q)) -{ - let result := mulmod(mload(0x740), mload(0x3820), f_q) -mstore(17152, result) - } -mstore(0x4320, mulmod(mload(0x4300), mload(0x3c00), f_q)) -mstore(0x4340, mulmod(sub(f_q, mload(0x4320)), mload(0x3e80), f_q)) -mstore(0x4360, mulmod(1, mload(0x3e80), f_q)) -mstore(0x4380, addmod(mload(0x42e0), mload(0x4340), f_q)) -{ - let result := mulmod(mload(0x760), mload(0x3820), f_q) -mstore(17312, result) - } -mstore(0x43c0, mulmod(mload(0x43a0), mload(0x3c00), f_q)) -mstore(0x43e0, mulmod(sub(f_q, mload(0x43c0)), mload(0x3ea0), f_q)) -mstore(0x4400, mulmod(1, mload(0x3ea0), f_q)) -mstore(0x4420, addmod(mload(0x4380), mload(0x43e0), f_q)) -{ - let result := mulmod(mload(0x780), mload(0x3820), f_q) -mstore(17472, result) - } -mstore(0x4460, mulmod(mload(0x4440), mload(0x3c00), f_q)) -mstore(0x4480, mulmod(sub(f_q, mload(0x4460)), mload(0x3ec0), f_q)) -mstore(0x44a0, mulmod(1, mload(0x3ec0), f_q)) -mstore(0x44c0, addmod(mload(0x4420), mload(0x4480), f_q)) -{ - let result := mulmod(mload(0x7a0), mload(0x3820), f_q) -mstore(17632, result) - } -mstore(0x4500, mulmod(mload(0x44e0), mload(0x3c00), f_q)) -mstore(0x4520, mulmod(sub(f_q, mload(0x4500)), mload(0x3ee0), f_q)) -mstore(0x4540, mulmod(1, mload(0x3ee0), f_q)) -mstore(0x4560, addmod(mload(0x44c0), mload(0x4520), f_q)) -{ - let result := mulmod(mload(0x7c0), mload(0x3820), f_q) -mstore(17792, result) - } -mstore(0x45a0, mulmod(mload(0x4580), mload(0x3c00), f_q)) -mstore(0x45c0, mulmod(sub(f_q, mload(0x45a0)), mload(0x3f00), f_q)) -mstore(0x45e0, mulmod(1, mload(0x3f00), f_q)) -mstore(0x4600, addmod(mload(0x4560), mload(0x45c0), f_q)) -{ - let result := mulmod(mload(0x7e0), mload(0x3820), f_q) -mstore(17952, result) - } -mstore(0x4640, mulmod(mload(0x4620), mload(0x3c00), f_q)) -mstore(0x4660, mulmod(sub(f_q, mload(0x4640)), mload(0x3f20), f_q)) -mstore(0x4680, mulmod(1, mload(0x3f20), f_q)) -mstore(0x46a0, addmod(mload(0x4600), mload(0x4660), f_q)) -{ - let result := mulmod(mload(0x800), mload(0x3820), f_q) -mstore(18112, result) - } -mstore(0x46e0, mulmod(mload(0x46c0), mload(0x3c00), f_q)) -mstore(0x4700, mulmod(sub(f_q, mload(0x46e0)), mload(0x3f40), f_q)) -mstore(0x4720, mulmod(1, mload(0x3f40), f_q)) -mstore(0x4740, addmod(mload(0x46a0), mload(0x4700), f_q)) -{ - let result := mulmod(mload(0x820), mload(0x3820), f_q) -mstore(18272, result) - } -mstore(0x4780, mulmod(mload(0x4760), mload(0x3c00), f_q)) -mstore(0x47a0, mulmod(sub(f_q, mload(0x4780)), mload(0x3f60), f_q)) -mstore(0x47c0, mulmod(1, mload(0x3f60), f_q)) -mstore(0x47e0, addmod(mload(0x4740), mload(0x47a0), f_q)) -{ - let result := mulmod(mload(0x840), mload(0x3820), f_q) -mstore(18432, result) - } -mstore(0x4820, mulmod(mload(0x4800), mload(0x3c00), f_q)) -mstore(0x4840, mulmod(sub(f_q, mload(0x4820)), mload(0x3f80), f_q)) -mstore(0x4860, mulmod(1, mload(0x3f80), f_q)) -mstore(0x4880, addmod(mload(0x47e0), mload(0x4840), f_q)) -{ - let result := mulmod(mload(0x860), mload(0x3820), f_q) -mstore(18592, result) - } -mstore(0x48c0, mulmod(mload(0x48a0), mload(0x3c00), f_q)) -mstore(0x48e0, mulmod(sub(f_q, mload(0x48c0)), mload(0x3fa0), f_q)) -mstore(0x4900, mulmod(1, mload(0x3fa0), f_q)) -mstore(0x4920, addmod(mload(0x4880), mload(0x48e0), f_q)) -{ - let result := mulmod(mload(0x880), mload(0x3820), f_q) -mstore(18752, result) - } -mstore(0x4960, mulmod(mload(0x4940), mload(0x3c00), f_q)) -mstore(0x4980, mulmod(sub(f_q, mload(0x4960)), mload(0x3fc0), f_q)) -mstore(0x49a0, mulmod(1, mload(0x3fc0), f_q)) -mstore(0x49c0, addmod(mload(0x4920), mload(0x4980), f_q)) -{ - let result := mulmod(mload(0x8a0), mload(0x3820), f_q) -mstore(18912, result) - } -mstore(0x4a00, mulmod(mload(0x49e0), mload(0x3c00), f_q)) -mstore(0x4a20, mulmod(sub(f_q, mload(0x4a00)), mload(0x3fe0), f_q)) -mstore(0x4a40, mulmod(1, mload(0x3fe0), f_q)) -mstore(0x4a60, addmod(mload(0x49c0), mload(0x4a20), f_q)) -{ - let result := mulmod(mload(0x8e0), mload(0x3820), f_q) -mstore(19072, result) - } -mstore(0x4aa0, mulmod(mload(0x4a80), mload(0x3c00), f_q)) -mstore(0x4ac0, mulmod(sub(f_q, mload(0x4aa0)), mload(0x4000), f_q)) -mstore(0x4ae0, mulmod(1, mload(0x4000), f_q)) -mstore(0x4b00, addmod(mload(0x4a60), mload(0x4ac0), f_q)) -{ - let result := mulmod(mload(0x900), mload(0x3820), f_q) -mstore(19232, result) - } -mstore(0x4b40, mulmod(mload(0x4b20), mload(0x3c00), f_q)) -mstore(0x4b60, mulmod(sub(f_q, mload(0x4b40)), mload(0x4020), f_q)) -mstore(0x4b80, mulmod(1, mload(0x4020), f_q)) -mstore(0x4ba0, addmod(mload(0x4b00), mload(0x4b60), f_q)) -{ - let result := mulmod(mload(0x920), mload(0x3820), f_q) -mstore(19392, result) - } -mstore(0x4be0, mulmod(mload(0x4bc0), mload(0x3c00), f_q)) -mstore(0x4c00, mulmod(sub(f_q, mload(0x4be0)), mload(0x4040), f_q)) -mstore(0x4c20, mulmod(1, mload(0x4040), f_q)) -mstore(0x4c40, addmod(mload(0x4ba0), mload(0x4c00), f_q)) -{ - let result := mulmod(mload(0x940), mload(0x3820), f_q) -mstore(19552, result) - } -mstore(0x4c80, mulmod(mload(0x4c60), mload(0x3c00), f_q)) -mstore(0x4ca0, mulmod(sub(f_q, mload(0x4c80)), mload(0x4060), f_q)) -mstore(0x4cc0, mulmod(1, mload(0x4060), f_q)) -mstore(0x4ce0, addmod(mload(0x4c40), mload(0x4ca0), f_q)) -{ - let result := mulmod(mload(0x960), mload(0x3820), f_q) -mstore(19712, result) - } -mstore(0x4d20, mulmod(mload(0x4d00), mload(0x3c00), f_q)) -mstore(0x4d40, mulmod(sub(f_q, mload(0x4d20)), mload(0x4080), f_q)) -mstore(0x4d60, mulmod(1, mload(0x4080), f_q)) -mstore(0x4d80, addmod(mload(0x4ce0), mload(0x4d40), f_q)) -{ - let result := mulmod(mload(0x980), mload(0x3820), f_q) -mstore(19872, result) - } -mstore(0x4dc0, mulmod(mload(0x4da0), mload(0x3c00), f_q)) -mstore(0x4de0, mulmod(sub(f_q, mload(0x4dc0)), mload(0x40a0), f_q)) -mstore(0x4e00, mulmod(1, mload(0x40a0), f_q)) -mstore(0x4e20, addmod(mload(0x4d80), mload(0x4de0), f_q)) -{ - let result := mulmod(mload(0x9a0), mload(0x3820), f_q) -mstore(20032, result) - } -mstore(0x4e60, mulmod(mload(0x4e40), mload(0x3c00), f_q)) -mstore(0x4e80, mulmod(sub(f_q, mload(0x4e60)), mload(0x40c0), f_q)) -mstore(0x4ea0, mulmod(1, mload(0x40c0), f_q)) -mstore(0x4ec0, addmod(mload(0x4e20), mload(0x4e80), f_q)) -{ - let result := mulmod(mload(0x9c0), mload(0x3820), f_q) -mstore(20192, result) - } -mstore(0x4f00, mulmod(mload(0x4ee0), mload(0x3c00), f_q)) -mstore(0x4f20, mulmod(sub(f_q, mload(0x4f00)), mload(0x40e0), f_q)) -mstore(0x4f40, mulmod(1, mload(0x40e0), f_q)) -mstore(0x4f60, addmod(mload(0x4ec0), mload(0x4f20), f_q)) -{ - let result := mulmod(mload(0x9e0), mload(0x3820), f_q) -mstore(20352, result) - } -mstore(0x4fa0, mulmod(mload(0x4f80), mload(0x3c00), f_q)) -mstore(0x4fc0, mulmod(sub(f_q, mload(0x4fa0)), mload(0x4100), f_q)) -mstore(0x4fe0, mulmod(1, mload(0x4100), f_q)) -mstore(0x5000, addmod(mload(0x4f60), mload(0x4fc0), f_q)) -{ - let result := mulmod(mload(0xa00), mload(0x3820), f_q) -mstore(20512, result) - } -mstore(0x5040, mulmod(mload(0x5020), mload(0x3c00), f_q)) -mstore(0x5060, mulmod(sub(f_q, mload(0x5040)), mload(0x4120), f_q)) -mstore(0x5080, mulmod(1, mload(0x4120), f_q)) -mstore(0x50a0, addmod(mload(0x5000), mload(0x5060), f_q)) -{ - let result := mulmod(mload(0x3700), mload(0x3820), f_q) -mstore(20672, result) - } -mstore(0x50e0, mulmod(mload(0x50c0), mload(0x3c00), f_q)) -mstore(0x5100, mulmod(sub(f_q, mload(0x50e0)), mload(0x4140), f_q)) -mstore(0x5120, mulmod(1, mload(0x4140), f_q)) -mstore(0x5140, mulmod(mload(0x3680), mload(0x4140), f_q)) -mstore(0x5160, mulmod(mload(0x36a0), mload(0x4140), f_q)) -mstore(0x5180, mulmod(mload(0x36c0), mload(0x4140), f_q)) -mstore(0x51a0, mulmod(mload(0x36e0), mload(0x4140), f_q)) -mstore(0x51c0, addmod(mload(0x50a0), mload(0x5100), f_q)) -{ - let result := mulmod(mload(0x8c0), mload(0x3820), f_q) -mstore(20960, result) - } -mstore(0x5200, mulmod(mload(0x51e0), mload(0x3c00), f_q)) -mstore(0x5220, mulmod(sub(f_q, mload(0x5200)), mload(0x4160), f_q)) -mstore(0x5240, mulmod(1, mload(0x4160), f_q)) -mstore(0x5260, addmod(mload(0x51c0), mload(0x5220), f_q)) -mstore(0x5280, mulmod(mload(0x5260), 1, f_q)) -mstore(0x52a0, mulmod(mload(0x42c0), 1, f_q)) -mstore(0x52c0, mulmod(mload(0x4360), 1, f_q)) -mstore(0x52e0, mulmod(mload(0x4400), 1, f_q)) -mstore(0x5300, mulmod(mload(0x44a0), 1, f_q)) -mstore(0x5320, mulmod(mload(0x4540), 1, f_q)) -mstore(0x5340, mulmod(mload(0x45e0), 1, f_q)) -mstore(0x5360, mulmod(mload(0x4680), 1, f_q)) -mstore(0x5380, mulmod(mload(0x4720), 1, f_q)) -mstore(0x53a0, mulmod(mload(0x47c0), 1, f_q)) -mstore(0x53c0, mulmod(mload(0x4860), 1, f_q)) -mstore(0x53e0, mulmod(mload(0x4900), 1, f_q)) -mstore(0x5400, mulmod(mload(0x49a0), 1, f_q)) -mstore(0x5420, mulmod(mload(0x4a40), 1, f_q)) -mstore(0x5440, mulmod(mload(0x4ae0), 1, f_q)) -mstore(0x5460, mulmod(mload(0x4b80), 1, f_q)) -mstore(0x5480, mulmod(mload(0x4c20), 1, f_q)) -mstore(0x54a0, mulmod(mload(0x4cc0), 1, f_q)) -mstore(0x54c0, mulmod(mload(0x4d60), 1, f_q)) -mstore(0x54e0, mulmod(mload(0x4e00), 1, f_q)) -mstore(0x5500, mulmod(mload(0x4ea0), 1, f_q)) -mstore(0x5520, mulmod(mload(0x4f40), 1, f_q)) -mstore(0x5540, mulmod(mload(0x4fe0), 1, f_q)) -mstore(0x5560, mulmod(mload(0x5080), 1, f_q)) -mstore(0x5580, mulmod(mload(0x5120), 1, f_q)) -mstore(0x55a0, mulmod(mload(0x5140), 1, f_q)) -mstore(0x55c0, mulmod(mload(0x5160), 1, f_q)) -mstore(0x55e0, mulmod(mload(0x5180), 1, f_q)) -mstore(0x5600, mulmod(mload(0x51a0), 1, f_q)) -mstore(0x5620, mulmod(mload(0x5240), 1, f_q)) -mstore(0x5640, mulmod(1, mload(0x3c20), f_q)) -{ - let result := mulmod(mload(0x600), mload(0x3860), f_q) -result := addmod(mulmod(mload(0x680), mload(0x3880), f_q), result, f_q) -result := addmod(mulmod(mload(0x700), mload(0x38a0), f_q), result, f_q) -mstore(22112, result) - } -mstore(0x5680, mulmod(mload(0x5660), mload(0x3e20), f_q)) -mstore(0x56a0, mulmod(sub(f_q, mload(0x5680)), 1, f_q)) -mstore(0x56c0, mulmod(mload(0x5640), 1, f_q)) -{ - let result := mulmod(mload(0x620), mload(0x3860), f_q) -result := addmod(mulmod(mload(0x6a0), mload(0x3880), f_q), result, f_q) -result := addmod(mulmod(mload(0x720), mload(0x38a0), f_q), result, f_q) -mstore(22240, result) - } -mstore(0x5700, mulmod(mload(0x56e0), mload(0x3e20), f_q)) -mstore(0x5720, mulmod(sub(f_q, mload(0x5700)), mload(0xb40), f_q)) -mstore(0x5740, mulmod(mload(0x5640), mload(0xb40), f_q)) -mstore(0x5760, addmod(mload(0x56a0), mload(0x5720), f_q)) -{ - let result := mulmod(mload(0x640), mload(0x3860), f_q) -result := addmod(mulmod(mload(0x6c0), mload(0x3880), f_q), result, f_q) -result := addmod(mulmod(mload(0x6e0), mload(0x38a0), f_q), result, f_q) -mstore(22400, result) - } -mstore(0x57a0, mulmod(mload(0x5780), mload(0x3e20), f_q)) -mstore(0x57c0, mulmod(sub(f_q, mload(0x57a0)), mload(0x3e80), f_q)) -mstore(0x57e0, mulmod(mload(0x5640), mload(0x3e80), f_q)) -mstore(0x5800, addmod(mload(0x5760), mload(0x57c0), f_q)) -mstore(0x5820, mulmod(mload(0x5800), mload(0xba0), f_q)) -mstore(0x5840, mulmod(mload(0x56c0), mload(0xba0), f_q)) -mstore(0x5860, mulmod(mload(0x5740), mload(0xba0), f_q)) -mstore(0x5880, mulmod(mload(0x57e0), mload(0xba0), f_q)) -mstore(0x58a0, addmod(mload(0x5280), mload(0x5820), f_q)) -mstore(0x58c0, mulmod(1, mload(0x3c60), f_q)) -{ - let result := mulmod(mload(0xa20), mload(0x3900), f_q) -result := addmod(mulmod(mload(0xa40), mload(0x3920), f_q), result, f_q) -result := addmod(mulmod(mload(0xa60), mload(0x3940), f_q), result, f_q) -mstore(22752, result) - } -mstore(0x5900, mulmod(mload(0x58e0), mload(0x3e40), f_q)) -mstore(0x5920, mulmod(sub(f_q, mload(0x5900)), 1, f_q)) -mstore(0x5940, mulmod(mload(0x58c0), 1, f_q)) -{ - let result := mulmod(mload(0xa80), mload(0x3900), f_q) -result := addmod(mulmod(mload(0xaa0), mload(0x3920), f_q), result, f_q) -result := addmod(mulmod(mload(0xac0), mload(0x3940), f_q), result, f_q) -mstore(22880, result) - } -mstore(0x5980, mulmod(mload(0x5960), mload(0x3e40), f_q)) -mstore(0x59a0, mulmod(sub(f_q, mload(0x5980)), mload(0xb40), f_q)) -mstore(0x59c0, mulmod(mload(0x58c0), mload(0xb40), f_q)) -mstore(0x59e0, addmod(mload(0x5920), mload(0x59a0), f_q)) -mstore(0x5a00, mulmod(mload(0x59e0), mload(0x41a0), f_q)) -mstore(0x5a20, mulmod(mload(0x5940), mload(0x41a0), f_q)) -mstore(0x5a40, mulmod(mload(0x59c0), mload(0x41a0), f_q)) -mstore(0x5a60, addmod(mload(0x58a0), mload(0x5a00), f_q)) -mstore(0x5a80, mulmod(1, mload(0x3ca0), f_q)) -{ - let result := mulmod(mload(0xae0), mload(0x3980), f_q) -result := addmod(mulmod(mload(0xb00), mload(0x39a0), f_q), result, f_q) -mstore(23200, result) - } -mstore(0x5ac0, mulmod(mload(0x5aa0), mload(0x3e60), f_q)) -mstore(0x5ae0, mulmod(sub(f_q, mload(0x5ac0)), 1, f_q)) -mstore(0x5b00, mulmod(mload(0x5a80), 1, f_q)) -mstore(0x5b20, mulmod(mload(0x5ae0), mload(0x41c0), f_q)) -mstore(0x5b40, mulmod(mload(0x5b00), mload(0x41c0), f_q)) -mstore(0x5b60, addmod(mload(0x5a60), mload(0x5b20), f_q)) -mstore(0x5b80, mulmod(1, mload(0x3840), f_q)) -mstore(0x5ba0, mulmod(1, mload(0xc40), f_q)) -mstore(0x5bc0, 0x0000000000000000000000000000000000000000000000000000000000000001) - mstore(0x5be0, 0x0000000000000000000000000000000000000000000000000000000000000002) -mstore(0x5c00, mload(0x5b60)) -success := and(eq(staticcall(gas(), 0x7, 0x5bc0, 0x60, 0x5bc0, 0x40), 1), success) -mstore(0x5c20, mload(0x5bc0)) - mstore(0x5c40, mload(0x5be0)) -mstore(0x5c60, mload(0x80)) - mstore(0x5c80, mload(0xa0)) -success := and(eq(staticcall(gas(), 0x6, 0x5c20, 0x80, 0x5c20, 0x40), 1), success) -mstore(0x5ca0, mload(0x180)) - mstore(0x5cc0, mload(0x1a0)) -mstore(0x5ce0, mload(0x52a0)) -success := and(eq(staticcall(gas(), 0x7, 0x5ca0, 0x60, 0x5ca0, 0x40), 1), success) -mstore(0x5d00, mload(0x5c20)) - mstore(0x5d20, mload(0x5c40)) -mstore(0x5d40, mload(0x5ca0)) - mstore(0x5d60, mload(0x5cc0)) -success := and(eq(staticcall(gas(), 0x6, 0x5d00, 0x80, 0x5d00, 0x40), 1), success) -mstore(0x5d80, 0x1070b546d316337679a8fd8ba9e5bdd338767065129affddfe2e393b541bbc21) - mstore(0x5da0, 0x26889fa8606a87db71ce7a7afd15b2fe97d9d156d7277c59eed4506757e4e794) -mstore(0x5dc0, mload(0x52c0)) -success := and(eq(staticcall(gas(), 0x7, 0x5d80, 0x60, 0x5d80, 0x40), 1), success) -mstore(0x5de0, mload(0x5d00)) - mstore(0x5e00, mload(0x5d20)) -mstore(0x5e20, mload(0x5d80)) - mstore(0x5e40, mload(0x5da0)) -success := and(eq(staticcall(gas(), 0x6, 0x5de0, 0x80, 0x5de0, 0x40), 1), success) -mstore(0x5e60, 0x2cfba73d2e95e73892f2c0947d54b6593bd163e513d5240241b0acaed9f01809) - mstore(0x5e80, 0x0d3e5674dd78d3d3bd44c762e97ce18e9b3d4f9a38fe5e42956bd04acadf2497) -mstore(0x5ea0, mload(0x52e0)) -success := and(eq(staticcall(gas(), 0x7, 0x5e60, 0x60, 0x5e60, 0x40), 1), success) -mstore(0x5ec0, mload(0x5de0)) - mstore(0x5ee0, mload(0x5e00)) -mstore(0x5f00, mload(0x5e60)) - mstore(0x5f20, mload(0x5e80)) -success := and(eq(staticcall(gas(), 0x6, 0x5ec0, 0x80, 0x5ec0, 0x40), 1), success) -mstore(0x5f40, 0x1059195a5280f87af576d612a90595a4b67513cab3db74e9703bef9f758ede90) - mstore(0x5f60, 0x24e851acda2841abbc85ea90c7e7904aded17886317495e212691d27fcf91d30) -mstore(0x5f80, mload(0x5300)) -success := and(eq(staticcall(gas(), 0x7, 0x5f40, 0x60, 0x5f40, 0x40), 1), success) -mstore(0x5fa0, mload(0x5ec0)) - mstore(0x5fc0, mload(0x5ee0)) -mstore(0x5fe0, mload(0x5f40)) - mstore(0x6000, mload(0x5f60)) -success := and(eq(staticcall(gas(), 0x6, 0x5fa0, 0x80, 0x5fa0, 0x40), 1), success) -mstore(0x6020, 0x16365714138c5bee75fbb5d98bfb0fb454e878292969c1856d2149ccea18b332) - mstore(0x6040, 0x304d9d4199ce679308ac6bb22b517c7fa108a1f2ee2b3d3ae65387bb9591be24) -mstore(0x6060, mload(0x5320)) -success := and(eq(staticcall(gas(), 0x7, 0x6020, 0x60, 0x6020, 0x40), 1), success) -mstore(0x6080, mload(0x5fa0)) - mstore(0x60a0, mload(0x5fc0)) -mstore(0x60c0, mload(0x6020)) - mstore(0x60e0, mload(0x6040)) -success := and(eq(staticcall(gas(), 0x6, 0x6080, 0x80, 0x6080, 0x40), 1), success) -mstore(0x6100, 0x084f4c4995b081528df74f3dc14437a101f24ebe22969f721fab48b5029c9b9f) - mstore(0x6120, 0x07dd2bcd881bda96175f3225beb06e65dba867b186e0aedb2dcc8fa19875af2a) -mstore(0x6140, mload(0x5340)) -success := and(eq(staticcall(gas(), 0x7, 0x6100, 0x60, 0x6100, 0x40), 1), success) -mstore(0x6160, mload(0x6080)) - mstore(0x6180, mload(0x60a0)) -mstore(0x61a0, mload(0x6100)) - mstore(0x61c0, mload(0x6120)) -success := and(eq(staticcall(gas(), 0x6, 0x6160, 0x80, 0x6160, 0x40), 1), success) -mstore(0x61e0, 0x1867552ae096d25c07d68fa7e937093f52e780ae9685755d2f9c7422f5768a89) - mstore(0x6200, 0x1441985c483b7c6a60629a92dcc6ebd7bb8e595091a50181ec7e74aea2086903) -mstore(0x6220, mload(0x5360)) -success := and(eq(staticcall(gas(), 0x7, 0x61e0, 0x60, 0x61e0, 0x40), 1), success) -mstore(0x6240, mload(0x6160)) - mstore(0x6260, mload(0x6180)) -mstore(0x6280, mload(0x61e0)) - mstore(0x62a0, mload(0x6200)) -success := and(eq(staticcall(gas(), 0x6, 0x6240, 0x80, 0x6240, 0x40), 1), success) -mstore(0x62c0, 0x2aaeeba7bd1fb7f3a78e52a7670fc69b436daf943dbcdc6af2b4a4704eadea25) - mstore(0x62e0, 0x1ae77ac2926486fb66efe8c5c5943d20d6fa4ab99c776b7aae6c03f62e428e3d) -mstore(0x6300, mload(0x5380)) -success := and(eq(staticcall(gas(), 0x7, 0x62c0, 0x60, 0x62c0, 0x40), 1), success) -mstore(0x6320, mload(0x6240)) - mstore(0x6340, mload(0x6260)) -mstore(0x6360, mload(0x62c0)) - mstore(0x6380, mload(0x62e0)) -success := and(eq(staticcall(gas(), 0x6, 0x6320, 0x80, 0x6320, 0x40), 1), success) -mstore(0x63a0, 0x0f8c966c4e9ea940bda98927b2a9a8a425e245149e99e399ad0e72757202725c) - mstore(0x63c0, 0x0dc141e24bbdbe08045937a7a8e968766381cd16635c77e18cdf7dc9948dac08) -mstore(0x63e0, mload(0x53a0)) -success := and(eq(staticcall(gas(), 0x7, 0x63a0, 0x60, 0x63a0, 0x40), 1), success) -mstore(0x6400, mload(0x6320)) - mstore(0x6420, mload(0x6340)) -mstore(0x6440, mload(0x63a0)) - mstore(0x6460, mload(0x63c0)) -success := and(eq(staticcall(gas(), 0x6, 0x6400, 0x80, 0x6400, 0x40), 1), success) -mstore(0x6480, 0x1a7f4b70992dce6a230b929368c4f3256d02274d76322154ec047c9d045c8fba) - mstore(0x64a0, 0x15db14ddabf429124e4a6bdbd21790313d090e9978d4f347b9a94f2f296c029e) -mstore(0x64c0, mload(0x53c0)) -success := and(eq(staticcall(gas(), 0x7, 0x6480, 0x60, 0x6480, 0x40), 1), success) -mstore(0x64e0, mload(0x6400)) - mstore(0x6500, mload(0x6420)) -mstore(0x6520, mload(0x6480)) - mstore(0x6540, mload(0x64a0)) -success := and(eq(staticcall(gas(), 0x6, 0x64e0, 0x80, 0x64e0, 0x40), 1), success) -mstore(0x6560, 0x204eff0d1866846e6e9ac83b980aa24f2201ce8d7aac9053b170a661467ea351) - mstore(0x6580, 0x0062db454f807816648558dbe08d87dd0a4598d77de991332f687cc95d854216) -mstore(0x65a0, mload(0x53e0)) -success := and(eq(staticcall(gas(), 0x7, 0x6560, 0x60, 0x6560, 0x40), 1), success) -mstore(0x65c0, mload(0x64e0)) - mstore(0x65e0, mload(0x6500)) -mstore(0x6600, mload(0x6560)) - mstore(0x6620, mload(0x6580)) -success := and(eq(staticcall(gas(), 0x6, 0x65c0, 0x80, 0x65c0, 0x40), 1), success) -mstore(0x6640, 0x2164ce3a5c1533a274129539555cb7ab913ff0aefd38b3bbad42dda0e89fd34b) - mstore(0x6660, 0x1e8506870b8a92cd54a5436e29258bcf75ff5b01238b99df1fc1cd34558269b8) -mstore(0x6680, mload(0x5400)) -success := and(eq(staticcall(gas(), 0x7, 0x6640, 0x60, 0x6640, 0x40), 1), success) -mstore(0x66a0, mload(0x65c0)) - mstore(0x66c0, mload(0x65e0)) -mstore(0x66e0, mload(0x6640)) - mstore(0x6700, mload(0x6660)) -success := and(eq(staticcall(gas(), 0x6, 0x66a0, 0x80, 0x66a0, 0x40), 1), success) -mstore(0x6720, 0x2efc557a8dbde14355847f2dc7655d5fdb6a3834ccc0715a694ff78761358fc6) - mstore(0x6740, 0x11e395f1be7a58d6b4668377aa71d2012768b5a35e853b6c514055245653fcc6) -mstore(0x6760, mload(0x5420)) -success := and(eq(staticcall(gas(), 0x7, 0x6720, 0x60, 0x6720, 0x40), 1), success) -mstore(0x6780, mload(0x66a0)) - mstore(0x67a0, mload(0x66c0)) -mstore(0x67c0, mload(0x6720)) - mstore(0x67e0, mload(0x6740)) -success := and(eq(staticcall(gas(), 0x6, 0x6780, 0x80, 0x6780, 0x40), 1), success) -mstore(0x6800, 0x10ad1b5f2c5e3d96ca86f094259f03bf03c4e6634246a1db231614879b10cacd) - mstore(0x6820, 0x12762e1eda998052570002d04467159d3013f5f958fc66466b13f60362124fd5) -mstore(0x6840, mload(0x5440)) -success := and(eq(staticcall(gas(), 0x7, 0x6800, 0x60, 0x6800, 0x40), 1), success) -mstore(0x6860, mload(0x6780)) - mstore(0x6880, mload(0x67a0)) -mstore(0x68a0, mload(0x6800)) - mstore(0x68c0, mload(0x6820)) -success := and(eq(staticcall(gas(), 0x6, 0x6860, 0x80, 0x6860, 0x40), 1), success) -mstore(0x68e0, 0x251aa1c8c0d3b91c851bd0d6d4984ee6165f11dc52a32f0504f34d1d4e297847) - mstore(0x6900, 0x0b761c3e05536f3da20ed7755be08a51edde74023e4ca77a26d1a29c5d162641) -mstore(0x6920, mload(0x5460)) -success := and(eq(staticcall(gas(), 0x7, 0x68e0, 0x60, 0x68e0, 0x40), 1), success) -mstore(0x6940, mload(0x6860)) - mstore(0x6960, mload(0x6880)) -mstore(0x6980, mload(0x68e0)) - mstore(0x69a0, mload(0x6900)) -success := and(eq(staticcall(gas(), 0x6, 0x6940, 0x80, 0x6940, 0x40), 1), success) -mstore(0x69c0, 0x10500c835287ade1b2b36fec4b0f5a119e5219635d2209134359075188b584cd) - mstore(0x69e0, 0x2f9b4981b897224adf1030c1529ecc2b9c436bf05fd7c229644c401d2a6c3a8a) -mstore(0x6a00, mload(0x5480)) -success := and(eq(staticcall(gas(), 0x7, 0x69c0, 0x60, 0x69c0, 0x40), 1), success) -mstore(0x6a20, mload(0x6940)) - mstore(0x6a40, mload(0x6960)) -mstore(0x6a60, mload(0x69c0)) - mstore(0x6a80, mload(0x69e0)) -success := and(eq(staticcall(gas(), 0x6, 0x6a20, 0x80, 0x6a20, 0x40), 1), success) -mstore(0x6aa0, 0x09a8af5221bfb29bfce5db3013de2aeee98b85aced568cc9ec0cff80f26ee59a) - mstore(0x6ac0, 0x04c580f285af8e69880072693d91e55a8c49da269b24de12bcd51481b6a7321c) -mstore(0x6ae0, mload(0x54a0)) -success := and(eq(staticcall(gas(), 0x7, 0x6aa0, 0x60, 0x6aa0, 0x40), 1), success) -mstore(0x6b00, mload(0x6a20)) - mstore(0x6b20, mload(0x6a40)) -mstore(0x6b40, mload(0x6aa0)) - mstore(0x6b60, mload(0x6ac0)) -success := and(eq(staticcall(gas(), 0x6, 0x6b00, 0x80, 0x6b00, 0x40), 1), success) -mstore(0x6b80, 0x02ba7ee32506bd134e3847a1b3e70e16f703a71b53c5c21b263272824148e46d) - mstore(0x6ba0, 0x11b8a259bc8677a5b5fd3dc5dda9c334de9e226a70e5965dc43c430dd2e9f14c) -mstore(0x6bc0, mload(0x54c0)) -success := and(eq(staticcall(gas(), 0x7, 0x6b80, 0x60, 0x6b80, 0x40), 1), success) -mstore(0x6be0, mload(0x6b00)) - mstore(0x6c00, mload(0x6b20)) -mstore(0x6c20, mload(0x6b80)) - mstore(0x6c40, mload(0x6ba0)) -success := and(eq(staticcall(gas(), 0x6, 0x6be0, 0x80, 0x6be0, 0x40), 1), success) -mstore(0x6c60, 0x1b70d412eafd2575a0fabc1a34e8f800307a2a974cefa11d3f215afb654c3cd5) - mstore(0x6c80, 0x1f3a531ad9ccb2e56a0805231431a7a24e4c2d032d598acb9342fb41c2967853) -mstore(0x6ca0, mload(0x54e0)) -success := and(eq(staticcall(gas(), 0x7, 0x6c60, 0x60, 0x6c60, 0x40), 1), success) -mstore(0x6cc0, mload(0x6be0)) - mstore(0x6ce0, mload(0x6c00)) -mstore(0x6d00, mload(0x6c60)) - mstore(0x6d20, mload(0x6c80)) -success := and(eq(staticcall(gas(), 0x6, 0x6cc0, 0x80, 0x6cc0, 0x40), 1), success) -mstore(0x6d40, 0x10d66e374767c959313078647eb901309c907572efaf9887d049e4a5ef17c505) - mstore(0x6d60, 0x0eed57d443694c7641328dd5a31a224f414f00c3b0a81e4a7286b68d8b335e38) -mstore(0x6d80, mload(0x5500)) -success := and(eq(staticcall(gas(), 0x7, 0x6d40, 0x60, 0x6d40, 0x40), 1), success) -mstore(0x6da0, mload(0x6cc0)) - mstore(0x6dc0, mload(0x6ce0)) -mstore(0x6de0, mload(0x6d40)) - mstore(0x6e00, mload(0x6d60)) -success := and(eq(staticcall(gas(), 0x6, 0x6da0, 0x80, 0x6da0, 0x40), 1), success) -mstore(0x6e20, 0x0c1824efd938f810b1ec9b455b6fce7dedf96e18bad57241de1b35d820285f32) - mstore(0x6e40, 0x23b2fdeaeeebb400d3f1dcee64d7296403672cf36ee453e82c3d5d90acdc739a) -mstore(0x6e60, mload(0x5520)) -success := and(eq(staticcall(gas(), 0x7, 0x6e20, 0x60, 0x6e20, 0x40), 1), success) -mstore(0x6e80, mload(0x6da0)) - mstore(0x6ea0, mload(0x6dc0)) -mstore(0x6ec0, mload(0x6e20)) - mstore(0x6ee0, mload(0x6e40)) -success := and(eq(staticcall(gas(), 0x6, 0x6e80, 0x80, 0x6e80, 0x40), 1), success) -mstore(0x6f00, 0x0ec6d72e2ce7c233ca8af2fc2bd4223a6d81d545e8785579de4cb241740f36a2) - mstore(0x6f20, 0x028a4450999577e25fc7d191fecf7f1a8a0526f7e042f316767c7ff43299fdd9) -mstore(0x6f40, mload(0x5540)) -success := and(eq(staticcall(gas(), 0x7, 0x6f00, 0x60, 0x6f00, 0x40), 1), success) -mstore(0x6f60, mload(0x6e80)) - mstore(0x6f80, mload(0x6ea0)) -mstore(0x6fa0, mload(0x6f00)) - mstore(0x6fc0, mload(0x6f20)) -success := and(eq(staticcall(gas(), 0x6, 0x6f60, 0x80, 0x6f60, 0x40), 1), success) -mstore(0x6fe0, 0x26d8b7b13f52340b2e122f12d279deccb9cec2319ec4371d28ef1455e8acce48) - mstore(0x7000, 0x0b69e5f1edd7a5ebb8b3d29122b6b2ae59dc5cc3fcc18a672cd2bad60357db4f) -mstore(0x7020, mload(0x5560)) -success := and(eq(staticcall(gas(), 0x7, 0x6fe0, 0x60, 0x6fe0, 0x40), 1), success) -mstore(0x7040, mload(0x6f60)) - mstore(0x7060, mload(0x6f80)) -mstore(0x7080, mload(0x6fe0)) - mstore(0x70a0, mload(0x7000)) -success := and(eq(staticcall(gas(), 0x6, 0x7040, 0x80, 0x7040, 0x40), 1), success) -mstore(0x70c0, mload(0x440)) - mstore(0x70e0, mload(0x460)) -mstore(0x7100, mload(0x5580)) -success := and(eq(staticcall(gas(), 0x7, 0x70c0, 0x60, 0x70c0, 0x40), 1), success) -mstore(0x7120, mload(0x7040)) - mstore(0x7140, mload(0x7060)) -mstore(0x7160, mload(0x70c0)) - mstore(0x7180, mload(0x70e0)) -success := and(eq(staticcall(gas(), 0x6, 0x7120, 0x80, 0x7120, 0x40), 1), success) -mstore(0x71a0, mload(0x480)) - mstore(0x71c0, mload(0x4a0)) -mstore(0x71e0, mload(0x55a0)) -success := and(eq(staticcall(gas(), 0x7, 0x71a0, 0x60, 0x71a0, 0x40), 1), success) -mstore(0x7200, mload(0x7120)) - mstore(0x7220, mload(0x7140)) -mstore(0x7240, mload(0x71a0)) - mstore(0x7260, mload(0x71c0)) -success := and(eq(staticcall(gas(), 0x6, 0x7200, 0x80, 0x7200, 0x40), 1), success) -mstore(0x7280, mload(0x4c0)) - mstore(0x72a0, mload(0x4e0)) -mstore(0x72c0, mload(0x55c0)) -success := and(eq(staticcall(gas(), 0x7, 0x7280, 0x60, 0x7280, 0x40), 1), success) -mstore(0x72e0, mload(0x7200)) - mstore(0x7300, mload(0x7220)) -mstore(0x7320, mload(0x7280)) - mstore(0x7340, mload(0x72a0)) -success := and(eq(staticcall(gas(), 0x6, 0x72e0, 0x80, 0x72e0, 0x40), 1), success) -mstore(0x7360, mload(0x500)) - mstore(0x7380, mload(0x520)) -mstore(0x73a0, mload(0x55e0)) -success := and(eq(staticcall(gas(), 0x7, 0x7360, 0x60, 0x7360, 0x40), 1), success) -mstore(0x73c0, mload(0x72e0)) - mstore(0x73e0, mload(0x7300)) -mstore(0x7400, mload(0x7360)) - mstore(0x7420, mload(0x7380)) -success := and(eq(staticcall(gas(), 0x6, 0x73c0, 0x80, 0x73c0, 0x40), 1), success) -mstore(0x7440, mload(0x540)) - mstore(0x7460, mload(0x560)) -mstore(0x7480, mload(0x5600)) -success := and(eq(staticcall(gas(), 0x7, 0x7440, 0x60, 0x7440, 0x40), 1), success) -mstore(0x74a0, mload(0x73c0)) - mstore(0x74c0, mload(0x73e0)) -mstore(0x74e0, mload(0x7440)) - mstore(0x7500, mload(0x7460)) -success := and(eq(staticcall(gas(), 0x6, 0x74a0, 0x80, 0x74a0, 0x40), 1), success) -mstore(0x7520, mload(0x3a0)) - mstore(0x7540, mload(0x3c0)) -mstore(0x7560, mload(0x5620)) -success := and(eq(staticcall(gas(), 0x7, 0x7520, 0x60, 0x7520, 0x40), 1), success) -mstore(0x7580, mload(0x74a0)) - mstore(0x75a0, mload(0x74c0)) -mstore(0x75c0, mload(0x7520)) - mstore(0x75e0, mload(0x7540)) -success := and(eq(staticcall(gas(), 0x6, 0x7580, 0x80, 0x7580, 0x40), 1), success) -mstore(0x7600, mload(0xc0)) - mstore(0x7620, mload(0xe0)) -mstore(0x7640, mload(0x5840)) -success := and(eq(staticcall(gas(), 0x7, 0x7600, 0x60, 0x7600, 0x40), 1), success) -mstore(0x7660, mload(0x7580)) - mstore(0x7680, mload(0x75a0)) -mstore(0x76a0, mload(0x7600)) - mstore(0x76c0, mload(0x7620)) -success := and(eq(staticcall(gas(), 0x6, 0x7660, 0x80, 0x7660, 0x40), 1), success) -mstore(0x76e0, mload(0x100)) - mstore(0x7700, mload(0x120)) -mstore(0x7720, mload(0x5860)) -success := and(eq(staticcall(gas(), 0x7, 0x76e0, 0x60, 0x76e0, 0x40), 1), success) -mstore(0x7740, mload(0x7660)) - mstore(0x7760, mload(0x7680)) -mstore(0x7780, mload(0x76e0)) - mstore(0x77a0, mload(0x7700)) -success := and(eq(staticcall(gas(), 0x6, 0x7740, 0x80, 0x7740, 0x40), 1), success) -mstore(0x77c0, mload(0x140)) - mstore(0x77e0, mload(0x160)) -mstore(0x7800, mload(0x5880)) -success := and(eq(staticcall(gas(), 0x7, 0x77c0, 0x60, 0x77c0, 0x40), 1), success) -mstore(0x7820, mload(0x7740)) - mstore(0x7840, mload(0x7760)) -mstore(0x7860, mload(0x77c0)) - mstore(0x7880, mload(0x77e0)) -success := and(eq(staticcall(gas(), 0x6, 0x7820, 0x80, 0x7820, 0x40), 1), success) -mstore(0x78a0, mload(0x2e0)) - mstore(0x78c0, mload(0x300)) -mstore(0x78e0, mload(0x5a20)) -success := and(eq(staticcall(gas(), 0x7, 0x78a0, 0x60, 0x78a0, 0x40), 1), success) -mstore(0x7900, mload(0x7820)) - mstore(0x7920, mload(0x7840)) -mstore(0x7940, mload(0x78a0)) - mstore(0x7960, mload(0x78c0)) -success := and(eq(staticcall(gas(), 0x6, 0x7900, 0x80, 0x7900, 0x40), 1), success) -mstore(0x7980, mload(0x320)) - mstore(0x79a0, mload(0x340)) -mstore(0x79c0, mload(0x5a40)) -success := and(eq(staticcall(gas(), 0x7, 0x7980, 0x60, 0x7980, 0x40), 1), success) -mstore(0x79e0, mload(0x7900)) - mstore(0x7a00, mload(0x7920)) -mstore(0x7a20, mload(0x7980)) - mstore(0x7a40, mload(0x79a0)) -success := and(eq(staticcall(gas(), 0x6, 0x79e0, 0x80, 0x79e0, 0x40), 1), success) -mstore(0x7a60, mload(0x360)) - mstore(0x7a80, mload(0x380)) -mstore(0x7aa0, mload(0x5b40)) -success := and(eq(staticcall(gas(), 0x7, 0x7a60, 0x60, 0x7a60, 0x40), 1), success) -mstore(0x7ac0, mload(0x79e0)) - mstore(0x7ae0, mload(0x7a00)) -mstore(0x7b00, mload(0x7a60)) - mstore(0x7b20, mload(0x7a80)) -success := and(eq(staticcall(gas(), 0x6, 0x7ac0, 0x80, 0x7ac0, 0x40), 1), success) -mstore(0x7b40, mload(0xbe0)) - mstore(0x7b60, mload(0xc00)) -mstore(0x7b80, sub(f_q, mload(0x5b80))) -success := and(eq(staticcall(gas(), 0x7, 0x7b40, 0x60, 0x7b40, 0x40), 1), success) -mstore(0x7ba0, mload(0x7ac0)) - mstore(0x7bc0, mload(0x7ae0)) -mstore(0x7be0, mload(0x7b40)) - mstore(0x7c00, mload(0x7b60)) -success := and(eq(staticcall(gas(), 0x6, 0x7ba0, 0x80, 0x7ba0, 0x40), 1), success) -mstore(0x7c20, mload(0xc80)) - mstore(0x7c40, mload(0xca0)) -mstore(0x7c60, mload(0x5ba0)) -success := and(eq(staticcall(gas(), 0x7, 0x7c20, 0x60, 0x7c20, 0x40), 1), success) -mstore(0x7c80, mload(0x7ba0)) - mstore(0x7ca0, mload(0x7bc0)) -mstore(0x7cc0, mload(0x7c20)) - mstore(0x7ce0, mload(0x7c40)) -success := and(eq(staticcall(gas(), 0x6, 0x7c80, 0x80, 0x7c80, 0x40), 1), success) -mstore(0x7d00, mload(0x7c80)) - mstore(0x7d20, mload(0x7ca0)) -mstore(0x7d40, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) - mstore(0x7d60, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) - mstore(0x7d80, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) - mstore(0x7da0, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) -mstore(0x7dc0, mload(0xc80)) - mstore(0x7de0, mload(0xca0)) -mstore(0x7e00, 0x0181624e80f3d6ae28df7e01eaeab1c0e919877a3b8a6b7fbc69a6817d596ea2) - mstore(0x7e20, 0x1783d30dcb12d259bb89098addf6280fa4b653be7a152542a28f7b926e27e648) - mstore(0x7e40, 0x00ae44489d41a0d179e2dfdc03bddd883b7109f8b6ae316a59e815c1a6b35304) - mstore(0x7e60, 0x0b2147ab62a386bd63e6de1522109b8c9588ab466f5aadfde8c41ca3749423ee) -success := and(eq(staticcall(gas(), 0x8, 0x7d00, 0x180, 0x7d00, 0x20), 1), success) -success := and(eq(mload(0x7d00), 1), success) - - if not(success) { revert(0, 0) } - return(0, 0) - - } - } - } \ No newline at end of file diff --git a/pkg/zk-circuits/src/mint/mod.rs b/pkg/zk-circuits/src/mint/mod.rs deleted file mode 100644 index 6c72848..0000000 --- a/pkg/zk-circuits/src/mint/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -mod circuit; -#[allow(clippy::module_inception)] -mod mint; -#[cfg(test)] -mod tests; - diff --git a/pkg/zk-circuits/src/mint/tests.rs b/pkg/zk-circuits/src/mint/tests.rs deleted file mode 100644 index 9bf91dc..0000000 --- a/pkg/zk-circuits/src/mint/tests.rs +++ /dev/null @@ -1,42 +0,0 @@ -use crate::data::{Mint, Note, ParameterSet}; -use crate::evm_verifier; -use crate::test::util::get_params; -use crate::util::{insecure_random_element, keygen_from_params}; -use halo2_base::halo2_proofs::dev::MockProver; -use halo2_base::halo2_proofs::halo2curves::bn256::Fr; -use zk_primitives::Element; - -#[test] -fn test_mint_proof() { - let k = 8; - - let address = insecure_random_element(); - let note = Note::new(address, Element::from(100u64)); - - let circuit = Mint::new([note]); - let instance_columns = vec![circuit.public_inputs()]; - - // Prove mock - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - - // Prove for real circuit - let (params, _, pk) = get_params(k, &circuit); - circuit - .prove(¶ms, &pk, &mut rand::thread_rng()) - .unwrap(); -} - -#[test] -fn generate_verifier() { - let params_8 = ParameterSet::Eight; - - let circuit = Mint::<1>::default(); - - let (pk, _) = keygen_from_params(params_8, &circuit); - let yul_code = - evm_verifier::generate_verifier(params_8, &pk, vec![circuit.public_inputs().len()]); - - let expected_yul_code = expect_test::expect_file!["./mint_verifier.yul"]; - expected_yul_code.assert_eq(&yul_code); -} diff --git a/pkg/zk-circuits/src/params.rs b/pkg/zk-circuits/src/params.rs deleted file mode 100644 index f958da1..0000000 --- a/pkg/zk-circuits/src/params.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::{fs, io::Cursor, path::PathBuf, sync::OnceLock}; - -use halo2_base::halo2_proofs::{ - halo2curves::bn256::Bn256, - poly::{commitment::Params, kzg::commitment::ParamsKZG}, -}; - -use crate::data::ParameterSet; - -#[cfg(not(debug_assertions))] -mod embedded { - pub(super) const BYTES_6: &[u8] = include_bytes!("../../../fixtures/params/kzg_bn254_6.srs"); - pub(super) const BYTES_8: &[u8] = include_bytes!("../../../fixtures/params/kzg_bn254_8.srs"); - pub(super) const BYTES_9: &[u8] = include_bytes!("../../../fixtures/params/kzg_bn254_9.srs"); - pub(super) const BYTES_14: &[u8] = include_bytes!("../../../fixtures/params/kzg_bn254_14.srs"); - pub(super) const BYTES_21: &[u8] = include_bytes!("../../../fixtures/params/kzg_bn254_21.srs"); -} - -static PARAMS_6: OnceLock> = OnceLock::new(); -static PARAMS_8: OnceLock> = OnceLock::new(); -static PARAMS_9: OnceLock> = OnceLock::new(); -static PARAMS_14: OnceLock> = OnceLock::new(); -static PARAMS_21: OnceLock> = OnceLock::new(); - -#[cfg(debug_assertions)] -fn get_params_path(k: u32) -> PathBuf { - let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - manifest_dir - .join("../../fixtures/params") - .join(format!("kzg_bn254_{k}.srs")) -} - -fn load_from_bytes(bytes: &[u8]) -> ParamsKZG { - ParamsKZG::read(&mut Cursor::new(bytes)).unwrap() -} - -#[cfg(debug_assertions)] -fn load_from_fs(k: u32) -> ParamsKZG { - let path = get_params_path(k); - let bytes = fs::read(&path) - .unwrap_or_else(|_| panic!("Failed to read params file: {}", path.display())); - load_from_bytes(&bytes) -} - -pub(crate) fn load_params(params: ParameterSet) -> &'static ParamsKZG { - #[cfg(debug_assertions)] - return match params { - ParameterSet::Six => PARAMS_6.get_or_init(|| load_from_fs(6)), - ParameterSet::Eight => PARAMS_8.get_or_init(|| load_from_fs(8)), - ParameterSet::Nine => PARAMS_9.get_or_init(|| load_from_fs(9)), - ParameterSet::Fourteen => PARAMS_14.get_or_init(|| load_from_fs(14)), - ParameterSet::TwentyOne => PARAMS_21.get_or_init(|| load_from_fs(21)), - }; - - #[cfg(not(debug_assertions))] - return match params { - ParameterSet::Six => PARAMS_6.get_or_init(|| load_from_bytes(embedded::BYTES_6)), - ParameterSet::Eight => PARAMS_8.get_or_init(|| load_from_bytes(embedded::BYTES_8)), - ParameterSet::Nine => PARAMS_9.get_or_init(|| load_from_bytes(embedded::BYTES_9)), - ParameterSet::Fourteen => PARAMS_14.get_or_init(|| load_from_bytes(embedded::BYTES_14)), - ParameterSet::TwentyOne => PARAMS_21.get_or_init(|| load_from_bytes(embedded::BYTES_21)), - }; -} diff --git a/pkg/zk-circuits/src/points/circuit.rs b/pkg/zk-circuits/src/points/circuit.rs deleted file mode 100644 index e2c434b..0000000 --- a/pkg/zk-circuits/src/points/circuit.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::{ - chips::{ - add::{AddCulmChip, AddCulmChipConfig}, - is_constant::{IsConstantChip, IsConstantConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, - }, - data::{Note, Points}, -}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct PointsCircuitConfig { - advices: [Column; 5], - instance: Column, - poseidon_config: PoseidonConfig, - culm_add_config: AddCulmChipConfig, - swap_config: CondSwapConfig, - is_padding_config: IsConstantConfig, -} - -impl Circuit for Points { - type FloorPlanner = SimpleFloorPlanner; - type Config = PointsCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - let culm_add_config = AddCulmChip::configure(meta, advices[0], advices[1]); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Padding chip - let is_padding_config = IsConstantChip::configure( - meta, - advices[0], - advices[1], - advices[2], - Note::padding_note().commitment().into(), - ); - - PointsCircuitConfig { - advices, - instance, - poseidon_config, - culm_add_config, - swap_config, - is_padding_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Get the public instances - self.enforce_constraints( - layouter.namespace(|| "txn"), - config.advices[0], - config.instance, - AddCulmChip::construct(config.culm_add_config), - config.poseidon_config, - CondSwapChip::construct(config.swap_config), - IsConstantChip::construct(config.is_padding_config), - )?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/points/mod.rs b/pkg/zk-circuits/src/points/mod.rs deleted file mode 100644 index 05534db..0000000 --- a/pkg/zk-circuits/src/points/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub mod circuit; -#[allow(clippy::module_inception)] -mod points; -#[cfg(test)] -mod tests; - -pub use crate::points::points::*; diff --git a/pkg/zk-circuits/src/points/points.rs b/pkg/zk-circuits/src/points/points.rs deleted file mode 100644 index 47c25e6..0000000 --- a/pkg/zk-circuits/src/points/points.rs +++ /dev/null @@ -1,121 +0,0 @@ -use crate::chips::add::AddCulmChip; -use crate::chips::is_constant::IsConstantChip; -use crate::chips::swap::CondSwapChip; -use crate::data::{Note, ParameterSet, Points}; -use crate::params::load_params; -use crate::util::keygen_from_params; -use crate::Snark; -use crate::{chips::poseidon::PoseidonConfig, util::assign_private_input}; -use halo2_base::halo2_proofs::circuit::Value; -use halo2_base::halo2_proofs::halo2curves::bn256::G1Affine; -use halo2_base::halo2_proofs::plonk::{ProvingKey, VerifyingKey}; -use halo2_base::halo2_proofs::{ - circuit::Layouter, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error, Instance}, -}; -use smirk::hash_merge; -use zk_primitives::Element; - -const NUM_NOTES: usize = 112; - -impl Points { - pub fn new(secret_key: Element, notes: Vec) -> Self { - assert!(notes.len() == NUM_NOTES, "notes must be 112"); - Self { secret_key, notes } - } - - #[allow(clippy::too_many_arguments)] - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - advice: Column, - instance: Column, - add_chip: AddCulmChip, - poseidon_config: PoseidonConfig, - swap_chip: CondSwapChip, - is_zero_chip: IsConstantChip, - ) -> Result<(), Error> { - let unverified_address = assign_private_input( - || "unverified address", - layouter.namespace(|| "unverified address witness"), - advice, - Value::known(self.address()), - )?; - - let mut values = vec![]; - - for note in &self.notes { - let note_cells = note.enforce_constraints( - layouter.namespace(|| "input note enforce commitment"), - advice, - poseidon_config.clone(), - is_zero_chip.clone(), - swap_chip.clone(), - )?; - - // Swap address if the note is padding - let (address, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap address?"), - (¬e_cells.address, &unverified_address), - ¬e_cells.is_padding, - )?; - - // Contrain address - layouter.constrain_instance(address.cell(), instance, 0)?; - - // Add values so we can get total - values.push(note_cells.value); - } - - // Total sum of all notes - let total = add_chip.assign(layouter.namespace(|| "totals"), values.as_slice())?; - - // Constrain total - layouter.constrain_instance(total.cell(), instance, 1)?; - - Ok(()) - } - - pub fn address(&self) -> Fr { - hash_merge([self.secret_key, Element::ZERO]).into() - } - - pub fn total_value(&self) -> Element { - self.notes.iter().map(|n| n.value).sum() - } - - pub(crate) fn public_inputs(&self) -> Vec { - let mut inputs = vec![self.address(), self.total_value().to_base()]; - - for note in &self.notes { - inputs.push(note.commitment().into()); - inputs.push(note.nullifier(self.secret_key).into()) - } - - inputs - } - - pub fn snark(&self, params: ParameterSet) -> Result { - let (pk, _) = self.keygen(params); - Snark::create( - self.clone(), - vec![self.public_inputs()], - load_params(params), - &pk, - ) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} - -impl Default for Points { - fn default() -> Self { - Self { - secret_key: Element::default(), - notes: (0..112).map(|_| Note::padding_note()).collect(), - } - } -} diff --git a/pkg/zk-circuits/src/points/tests.rs b/pkg/zk-circuits/src/points/tests.rs deleted file mode 100644 index 0427d64..0000000 --- a/pkg/zk-circuits/src/points/tests.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::data::{Note, Points}; -use halo2_base::halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; -use rand::thread_rng; -use smirk::{hash_merge, Element}; -use snark_verifier::util::arithmetic::FieldExt; - -#[test] -fn test_one_note() { - let k = 14; - - let pk = Element::secure_random(thread_rng()); - let address = hash_merge([pk, Element::ZERO]); - - let mut notes = vec![ - Note::new(address, Element::from(10u32)), - Note::new(address, Element::from(5u32)), - Note::new(address, Element::from(6u32)), - Note::new(address, Element::from(10u32)), - ]; - - for _ in 0..112 - 4 { - notes.push(Note::padding_note()) - } - - let circuit = Points::new(pk, notes); - let public_input = circuit.public_inputs(); - - assert_eq!(public_input.len(), 2 + (112 * 2)); - assert_eq!(public_input[0], address.to_base()); - assert_eq!(public_input[1], Fr::from_u128(31)); - - let instance_columns = vec![public_input]; - - // Prove mock - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); -} diff --git a/pkg/zk-circuits/src/proof.rs b/pkg/zk-circuits/src/proof.rs deleted file mode 100644 index 463b001..0000000 --- a/pkg/zk-circuits/src/proof.rs +++ /dev/null @@ -1,85 +0,0 @@ -use std::io::Cursor; - -use halo2_base::halo2_proofs::{ - circuit::Value, - halo2curves::{ - bn256::{Bn256, Fr, G1Affine}, - pairing::Engine, - }, - plonk::{self, Circuit, ProvingKey, VerifyingKey}, - poly::{ - commitment::ParamsProver, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::VerifierSHPLONK, - }, - kzg::{multiopen::ProverSHPLONK, strategy::SingleStrategy}, - }, - transcript::{Blake2bRead, Blake2bWrite, TranscriptReadBuffer, TranscriptWriterBuffer}, -}; -use rand::RngCore; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub struct Proof(Vec); - -impl Proof { - /// Creates a proof for the given circuits and instances. - #[allow(dead_code)] - pub fn create>( - params: &ParamsKZG, - pk: &ProvingKey, - circuit: C, - instances: &[&[Fr]], - rng: impl RngCore, - ) -> Result { - let mut transcript = Blake2bWrite::<_, ::G1Affine, _>::init(Vec::new()); - plonk::create_proof::, ProverSHPLONK, _, _, _, _>( - params, - pk, - &[circuit], - &[instances], - rng, - &mut transcript, - )?; - Ok(Self(transcript.finalize())) - } - - // TODO: this should be generic, as `create` above - /// Verifies this proof with the given instances. - #[allow(dead_code)] - pub fn verify( - &self, - vk: &VerifyingKey, - params: &ParamsKZG, - instances: &[&[Fr]], - ) -> Result<(), plonk::Error> { - let strategy = SingleStrategy::new(params); - let mut transcript = - Blake2bRead::<_, ::G1Affine, _>::init(Cursor::new(self.0.clone())); - plonk::verify_proof::<_, VerifierSHPLONK<_>, _, _, _>( - params.verifier_params(), - vk, - strategy, - &[instances], - &mut transcript, - ) - } - - /// Constructs a new Proof value. - pub fn new(bytes: Vec) -> Self { - Proof(bytes) - } - - pub fn as_bytes(&self) -> &[u8] { - &self.0 - } - - pub fn inner(&self) -> Vec { - self.0.clone() - } - - pub fn value(&self) -> Value<&[u8]> { - Value::known(self.as_bytes()) - } -} diff --git a/pkg/zk-circuits/src/proof_format.rs b/pkg/zk-circuits/src/proof_format.rs deleted file mode 100644 index b729705..0000000 --- a/pkg/zk-circuits/src/proof_format.rs +++ /dev/null @@ -1,62 +0,0 @@ -use halo2_base::halo2_proofs::{ - halo2curves::bn256::{Fr, G1Affine}, - plonk::{verify_proof, VerifyingKey}, - poly::{ - commitment::ParamsProver, - kzg::{multiopen::VerifierSHPLONK, strategy::AccumulatorStrategy}, - VerificationStrategy, - }, - transcript::TranscriptWriterBuffer, -}; -use std::io::Cursor; - -use smirk::Element; -use snark_verifier::loader::native::NativeLoader; - -use crate::{ - chips::aggregation::types::PoseidonTranscript, - data::{ParameterSet, SnarkWitnessV1}, - keys::CircuitKind, - params::load_params, - Snark, -}; - -impl SnarkWitnessV1 { - pub(crate) fn new(instances: Vec>, proof: Vec) -> Self { - Self { instances, proof } - } - - pub fn to_snark(&self, vk: &VerifyingKey, params: ParameterSet) -> Snark { - Snark::from_witness(self.clone(), vk, params) - } - - pub(crate) fn fr_instances(&self) -> Vec> { - self.instances - .iter() - .map(|v| v.iter().map(|v| v.to_base()).collect()) - .collect() - } - - pub fn verify(&self, kind: CircuitKind) -> bool { - let params = load_params(kind.params()); - let vk = kind.vk(); - - let mut transcript = - PoseidonTranscript::::init(Cursor::new(self.proof.clone())); - - VerificationStrategy::<_, VerifierSHPLONK<_>>::finalize( - verify_proof::<_, VerifierSHPLONK<_>, _, PoseidonTranscript, _>( - params.verifier_params(), - vk, - AccumulatorStrategy::new(params.verifier_params()), - &[&self - .fr_instances() - .iter() - .map(|v| v.as_slice()) - .collect::>()], - &mut transcript, - ) - .unwrap(), - ) - } -} diff --git a/pkg/zk-circuits/src/prove.rs b/pkg/zk-circuits/src/prove.rs new file mode 100644 index 0000000..285cdfd --- /dev/null +++ b/pkg/zk-circuits/src/prove.rs @@ -0,0 +1,23 @@ +use crate::{BbBackend, Error, Result, execute::execute_program_and_decode}; +use noirc_abi::InputMap; +use noirc_driver::CompiledProgram; + +pub async fn prove( + bb_backend: &dyn BbBackend, + compiled_program: &CompiledProgram, + program: &[u8], + bytecode: &[u8], + key: &[u8], + inputs_map: &InputMap, + oracle_hash_keccak: bool, +) -> Result> { + let results = execute_program_and_decode(compiled_program, inputs_map, false) + .map_err(Error::ImplementationSpecific)?; + + let witness = bincode::serde::encode_to_vec(&results.witness_stack, bincode::config::legacy()) + .map_err(|e| Error::ImplementationSpecific(e.into()))?; + + bb_backend + .prove(program, bytecode, key, &witness, oracle_hash_keccak) + .await +} diff --git a/pkg/zk-circuits/src/signature/circuit.rs b/pkg/zk-circuits/src/signature/circuit.rs deleted file mode 100644 index 70dcdb2..0000000 --- a/pkg/zk-circuits/src/signature/circuit.rs +++ /dev/null @@ -1,109 +0,0 @@ -use crate::{chips::poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, data::Signature}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct SignatureCircuitConfig { - advices: [Column; 5], - instance: Column, - poseidon_config: PoseidonConfig, -} - -impl Circuit for Signature { - type FloorPlanner = SimpleFloorPlanner; - type Config = SignatureCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - SignatureCircuitConfig { - advices, - instance, - poseidon_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - self.enforce_constraints( - layouter.namespace(|| "signature"), - config.advices[0], - config.instance, - config.poseidon_config, - )?; - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use halo2_base::halo2_proofs::dev::MockProver; - use rand::thread_rng; - use smirk::Element; - - use crate::{test::util::get_params, Snark}; - - use super::*; - - #[test] - fn test_address_proof() { - let k = 6; - - let pk = Element::secure_random(thread_rng()); - let message = Element::secure_random(thread_rng()); - - let circuit = Signature::new(pk, message); - let instance_columns = vec![circuit.public_inputs()]; - - // Prove mock - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - - // Prove for real circuit - let (params, _vk, pk) = get_params(k, &circuit); - let _snark = - Snark::create(circuit.clone(), vec![circuit.public_inputs()], ¶ms, &pk).unwrap(); - } -} diff --git a/pkg/zk-circuits/src/signature/mod.rs b/pkg/zk-circuits/src/signature/mod.rs deleted file mode 100644 index 4eb282c..0000000 --- a/pkg/zk-circuits/src/signature/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod circuit; -#[allow(clippy::module_inception)] -mod signature; - -pub use crate::signature::signature::*; diff --git a/pkg/zk-circuits/src/signature/signature.rs b/pkg/zk-circuits/src/signature/signature.rs deleted file mode 100644 index 53c9c57..0000000 --- a/pkg/zk-circuits/src/signature/signature.rs +++ /dev/null @@ -1,110 +0,0 @@ -use crate::data::{ParameterSet, Signature}; -use crate::params::load_params; -use crate::proof::Proof; -use crate::util::{assign_constant, keygen_from_params}; -use crate::Snark; -use crate::{ - chips::{ - poseidon::{poseidon_hash_gadget, PoseidonConfig}, - poseidon_hash, - }, - util::assign_private_input, -}; -use halo2_base::halo2_proofs::halo2curves::bn256::{Bn256, G1Affine}; -use halo2_base::halo2_proofs::plonk::VerifyingKey; -use halo2_base::halo2_proofs::poly::kzg::commitment::ParamsKZG; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, Value}, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error, Instance, ProvingKey}, -}; -use rand::RngCore; -use smirk::Element; - -impl Signature { - pub fn new(secret_key: Element, message: Element) -> Self { - Self { - secret_key, - message, - } - } - - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - advice: Column, - instance: Column, - poseidon_config: PoseidonConfig, - ) -> Result<(), Error> { - // Witness the message - let message = assign_private_input( - || "message", - layouter.namespace(|| "message witness"), - advice, - Value::known(self.message.to_base()), - )?; - - // Witness the message - let secret_key = assign_private_input( - || "secret_key", - layouter.namespace(|| "secret key witness"), - advice, - Value::known(self.secret_key.to_base()), - )?; - - let padding = assign_constant( - || "padding witness", - layouter.namespace(|| "padding witness"), - advice, - Fr::zero(), - )?; - - let address_from_private_key = poseidon_hash_gadget( - poseidon_config, - layouter.namespace(|| "address from pk"), - [secret_key, padding], - )?; - - // Constrain address to be the same as verified address - layouter.constrain_instance(address_from_private_key.cell(), instance, 0)?; - - // Constrain message witness - layouter.constrain_instance(message.cell(), instance, 1)?; - - Ok(()) - } - - pub(crate) fn address(&self) -> Fr { - poseidon_hash([self.secret_key.into(), Fr::zero()]) - } - - pub(crate) fn public_inputs(&self) -> Vec { - vec![self.address(), self.message.into()] - } - - pub fn prove( - &self, - params: &ParamsKZG, - pk: &ProvingKey, - rng: impl RngCore, - ) -> Result { - let circuit = Self::default(); - let instance = self.public_inputs(); - let instances = &[instance.as_slice()]; - Proof::create(params, pk, circuit, instances, rng) - } - - pub fn snark(&self, params: ParameterSet) -> Result { - let (pk, _) = self.keygen(params); - Snark::create( - self.clone(), - vec![self.public_inputs()], - load_params(params), - &pk, - ) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} diff --git a/pkg/zk-circuits/src/test/agg_agg.rs b/pkg/zk-circuits/src/test/agg_agg.rs deleted file mode 100644 index f404edb..0000000 --- a/pkg/zk-circuits/src/test/agg_agg.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::{ - chips::aggregation::snark::Snark, - data::{AggregateAgg, ParameterSet, SnarkWitness}, - evm_verifier, CircuitKind, -}; -use borsh::{BorshDeserialize, BorshSerialize}; -use smirk::Element; -use wire_message::{wire_message, WireMessage}; - -use super::fs::{load_file, load_witness, save_file, save_witness}; - -pub fn create_or_load_agg_agg_utxo_snark(params: ParameterSet, snarks: [Snark; 2]) -> Snark { - load_witness("agg_utxo_agg") - .map(|sw| match sw { - SnarkWitness::V1(sw) => sw, - }) - .map(|sw| sw.to_snark(CircuitKind::AggAgg.vk(), params)) - .unwrap_or_else(|| { - // Currently we can only do 1 for the Ethereum verifier as 2 creates a "too large" verifier (25,137 bytes) where - // the max limit is 24,576 bytes (we are so close, we might be able to get this to fit!) - let aggregate_agg_agg = AggregateAgg::new(snarks); - let snark = aggregate_agg_agg.snark(params).unwrap(); - - save_witness("agg_utxo_agg", &SnarkWitness::V1(snark.to_witness())); - snark - }) -} - -pub fn create_or_load_agg_agg_final_snark(params: ParameterSet, snark: Snark) -> Snark { - load_witness("agg_agg_final") - .map(|sw| match sw { - SnarkWitness::V1(sw) => sw, - }) - .map(|sw| { - sw.to_snark( - &AggregateAgg::<1>::new([snark.clone()]).keygen(params).1, - params, - ) - }) - .unwrap_or_else(|| { - // Currently we can only do 1 for the Ethereum verifier as 2 creates a "too large" verifier (25,137 bytes) where - // the max limit is 24,576 bytes (we are so close, we might be able to get this to fit!) - let aggregate_agg_agg = AggregateAgg::<1>::new([snark]); - let snark = aggregate_agg_agg.snark(params).unwrap(); - - save_witness("agg_agg_final", &SnarkWitness::V1(snark.to_witness())); - snark - }) -} - -#[derive(Clone, Debug)] -#[wire_message] -pub enum EvmProof { - V1(EvmProofV1), -} - -#[derive(Clone, Debug, BorshSerialize, BorshDeserialize)] -pub struct EvmProofV1 { - pub proof: Vec, - pub agg_instances: Vec, - pub old_root: Element, - pub new_root: Element, - pub utxo_inputs: Vec, -} - -impl WireMessage for EvmProof { - type Ctx = (); - type Err = core::convert::Infallible; - - fn upgrade_once(self, _ctx: &mut Self::Ctx) -> Result { - match self { - Self::V1(_) => Err(Self::max_version_error()), - } - } - - fn version(&self) -> u64 { - match self { - Self::V1(_) => 1, - } - } -} - -pub fn create_or_load_agg_agg_final_evm_proof( - params: ParameterSet, - agg_agg_utxo: Snark, -) -> EvmProof { - load_file("agg_agg_final_evm_proof").unwrap_or_else(|| { - let aggregate_agg_agg = AggregateAgg::<1>::new([agg_agg_utxo]); - let inputs = aggregate_agg_agg.public_inputs(); - let (pk, _) = aggregate_agg_agg.keygen(params); - - let proof = - evm_verifier::gen_proof(params, &pk, aggregate_agg_agg.clone(), &[&inputs]).unwrap(); - - let evm_proof = EvmProofV1 { - proof, - agg_instances: aggregate_agg_agg - .agg_instances() - .iter() - .cloned() - .map(From::from) - .collect(), - old_root: (*aggregate_agg_agg.old_root()).into(), - new_root: (*aggregate_agg_agg.new_root()).into(), - utxo_inputs: aggregate_agg_agg - .utxo_values() - .into_iter() - .map(From::from) - .collect::>(), - }; - let evm_proof = EvmProof::V1(evm_proof); - - save_file("agg_agg_final_evm_proof", &evm_proof); - - evm_proof - }) -} diff --git a/pkg/zk-circuits/src/test/agg_utxo.rs b/pkg/zk-circuits/src/test/agg_utxo.rs deleted file mode 100644 index 20f1674..0000000 --- a/pkg/zk-circuits/src/test/agg_utxo.rs +++ /dev/null @@ -1,82 +0,0 @@ -use super::{ - fs::{load_witness, save_witness}, - rollup::Rollup, -}; -use crate::{ - aggregate_utxo::{constants::UTXO_AGGREGATE_3_161_12_VK, AggregateUtxo}, - chips::aggregation::snark::Snark, - constants::{MERKLE_TREE_DEPTH, UTXO_AGG_LEAVES, UTXO_AGG_NUMBER}, - data::{Batch, ParameterSet, SnarkWitness, Utxo}, - CircuitKind, -}; - -pub fn create_or_load_agg_utxo_snarks(params: ParameterSet) -> [Snark; N] { - if let Some(utxo_aggs) = load_agg_utxo_snarks(params) { - utxo_aggs - } else { - let snarks = create_agg_utxo_snarks::(params); - for (i, snark) in snarks.iter().enumerate() { - save_witness( - &format!("agg_utxo_{i}"), - &SnarkWitness::V1(snark.to_witness()), - ); - } - snarks - } -} - -pub fn load_agg_utxo_snarks(params: ParameterSet) -> Option<[Snark; N]> { - let mut snarks = vec![]; - for i in 0..N { - let sw = load_witness(&format!("agg_utxo_{i}"))?; - let SnarkWitness::V1(sw) = sw; - let snark = sw.to_snark(&UTXO_AGGREGATE_3_161_12_VK, params); - snarks.push(snark); - } - Some(snarks.try_into().unwrap()) -} - -pub fn default_aggregate_utxo() -> AggregateUtxo -{ - let mut snarks = vec![]; - for _ in 0..UTXO_AGG_NUMBER { - snarks.push( - Utxo::::new_padding() - .snark(CircuitKind::Utxo) - .unwrap(), - ); - } - AggregateUtxo::::new( - snarks.try_into().unwrap(), - Batch::default(), - ) -} - -pub fn create_agg_utxo_snarks( - params: ParameterSet, -) -> [Snark; N] { - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - let sally = rollup.new_wallet(); - - // Add existing notes to the tree - let bob_notes = (0..UTXO_N * N) - .map(|_| rollup.unverified_add_unspent_note(&bob, 100)) - .collect::>(); - - let utxos = bob_notes - .iter() - .map(|note| rollup.transfer(note.clone(), sally.new_note(100))) - .collect::>(); - - utxos - .chunks(UTXO_N) - .map(|utxos| { - let utxo_agg = rollup.aggregate_utxo(utxos.try_into().unwrap()); - utxo_agg.snark(params) - }) - .collect::, _>>() - .unwrap() - .try_into() - .unwrap() -} diff --git a/pkg/zk-circuits/src/test/fs.rs b/pkg/zk-circuits/src/test/fs.rs deleted file mode 100644 index 18b22b9..0000000 --- a/pkg/zk-circuits/src/test/fs.rs +++ /dev/null @@ -1,57 +0,0 @@ -use std::env::var; -use std::fs; -use std::path::{Path, PathBuf}; - -use wire_message::WireMessage; - -use crate::data::SnarkWitness; - -pub fn save_witness(name: &str, snark_witness: &SnarkWitness) { - save_file(name, snark_witness); -} - -pub fn load_witness(name: &str) -> Option { - load_file(name) -} - -pub fn save_file(name: &str, data: &impl WireMessage) { - let dir = get_dir(); - fs::create_dir_all(&dir).unwrap(); - let path = dir.join(format!("{name}.proof")); - fs::write(path, data.to_bytes().unwrap()).unwrap(); -} - -pub fn load_file(name: &str) -> Option { - let dir = get_dir(); - let path = dir.join(format!("{name}.proof")); - println!("Loading proof from: {path:?}"); - let bytes = fs::read(path).ok()?; - M::from_bytes(&bytes).ok() -} - -pub fn get_dir() -> PathBuf { - var("PROOF_DIR") - .map(PathBuf::from) - .ok() - .or(find_workspace_root()) - .map(|dir| dir.join("fixtures/proofs")) - .unwrap_or_else(|| PathBuf::from("./proofs")) -} - -fn find_workspace_root() -> Option { - if let Ok(package_dir) = var("CARGO_MANIFEST_DIR") { - let mut path = Path::new(&package_dir).to_path_buf(); - - while let Some(parent_path) = path.parent() { - let possible_root = parent_path.join("Cargo.toml"); - - if possible_root.exists() && fs::metadata(&possible_root).unwrap().is_file() { - return Some(parent_path.to_path_buf()); - } else { - path = parent_path.to_path_buf() - } - } - } - - None -} diff --git a/pkg/zk-circuits/src/test/mod.rs b/pkg/zk-circuits/src/test/mod.rs deleted file mode 100644 index 92dffb9..0000000 --- a/pkg/zk-circuits/src/test/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod agg_agg; -pub mod agg_utxo; -pub mod fs; -pub mod rollup; -pub mod util; diff --git a/pkg/zk-circuits/src/test/rollup.rs b/pkg/zk-circuits/src/test/rollup.rs deleted file mode 100644 index 793561f..0000000 --- a/pkg/zk-circuits/src/test/rollup.rs +++ /dev/null @@ -1,166 +0,0 @@ -use crate::constants::{MERKLE_TREE_DEPTH, UTXO_AGG_LEAVES, UTXO_AGG_NUMBER}; -use crate::data::{Batch, InputNote, Insert, MerklePath, Note, Utxo, UtxoKind}; -use crate::CircuitKind; -use crate::{ - aggregate_utxo::AggregateUtxo, chips::poseidon::poseidon_hash, util::insecure_random_element, -}; -use halo2_base::halo2_proofs::halo2curves::bn256::Fr; -use smirk::{Path, Tree}; -use zk_primitives::Element; - -#[derive(Debug, Clone, Default)] -pub struct Rollup { - pub tree: Tree, -} - -impl Rollup { - pub fn new() -> Self { - let tree = smirk::Tree::new(); - Self { tree } - } - - pub fn new_wallet(&self) -> Wallet { - Wallet::new() - } - - /// Adds an unspent note to the tree without verifying any proofs (test only to simulate - /// existing notes in a tree) - pub fn unverified_add_unspent_note(&mut self, wallet: &Wallet, amount: u64) -> WalletNote { - let note = wallet.new_wallet_note(amount); - self.tree.insert(note.commitment(), ()).unwrap(); - note - } - - /// Convert WalletNote into an InputNote to be used in a UTXO txn - pub fn to_input_note(&self, note: &WalletNote) -> InputNote { - note.to_input_note(self.tree.path_for(note.commitment())) - } - - pub fn merkle_path(&self, el: Element) -> MerklePath { - merkle_path(&self.tree, el) - } - - pub fn root_hash(&self) -> Element { - self.tree.root_hash() - } - - pub fn transfer(&self, input_note: WalletNote, output_note: Note) -> Utxo { - let input_notes = [self.to_input_note(&input_note), InputNote::padding_note()]; - let output_notes = [output_note, Note::padding_note()]; - - Utxo::new( - input_notes, - output_notes, - self.root_hash(), - UtxoKind::Transfer, - ) - } - - // pub fn mint(&self, output_note: Note) -> Utxo { - // Utxo::new_mint(output_note, self.root_hash()) - // } - - // pub fn burn(&self, input_note: WalletNote) -> Utxo { - // Utxo::new_burn(self.to_input_note(input_note), self.root_hash()) - // } - - pub fn batch_inserts_for_utxos( - &mut self, - utxos: &[Utxo; UTXO_AGG_NUMBER], - ) -> Batch { - let mut inserts = vec![]; - for utxo in utxos.iter() { - for leaf in utxo.leafs() { - inserts.push(Insert::new( - leaf.into(), - merkle_path(&self.tree, leaf.into()), - )); - if Element::from(leaf) != Note::padding_note().commitment() { - self.tree.insert(leaf.into(), ()).unwrap(); - } - } - } - - Batch::new(inserts.try_into().unwrap()) - } - - pub fn aggregate_utxo( - &mut self, - utxos: &[Utxo; UTXO_AGG_NUMBER], - ) -> AggregateUtxo { - // Convert UTXO to Snarks - let snarks = utxos - .iter() - .map(|utxo| utxo.snark(CircuitKind::Utxo)) - .collect::, _>>() - .unwrap(); - - let batch_inserts = self.batch_inserts_for_utxos(utxos); - - AggregateUtxo::new(snarks.try_into().unwrap(), batch_inserts) - } -} - -#[derive(Clone, Copy, Debug, Default)] -pub struct Wallet { - pub pk: Element, -} - -impl Wallet { - pub fn new() -> Self { - Self { - pk: insecure_random_element(), - } - } - - pub fn address(&self) -> Fr { - poseidon_hash([self.pk.to_base(), Fr::zero()]) - } - - pub fn new_note(&self, amount: u64) -> Note { - Note::new(self.address().into(), Element::from(amount)) - } - - pub fn new_wallet_note(&self, amount: u64) -> WalletNote { - WalletNote::new( - *self, - Note::new(self.address().into(), Element::from(amount)), - ) - } -} - -#[derive(Clone, Debug)] -pub struct WalletNote { - note: Note, - wallet: Wallet, -} - -impl WalletNote { - pub fn new(wallet: Wallet, note: Note) -> Self { - Self { note, wallet } - } - - pub fn commitment(&self) -> Element { - self.note.commitment() - } - - pub fn nullifier(&self) -> Element { - self.note.nullifier(self.wallet.pk) - } - - pub fn note(&self) -> Note { - self.note.clone() - } - - pub fn to_input_note(&self, path: Path) -> InputNote { - let merkle_path = MerklePath::new(path.siblings_deepest_first().to_vec()); - InputNote::new(self.note.clone(), self.wallet.pk, merkle_path) - } -} - -pub fn merkle_path( - tree: &Tree, - el: Element, -) -> MerklePath { - MerklePath::new(tree.path_for(el).siblings_deepest_first().to_vec()) -} diff --git a/pkg/zk-circuits/src/test/util.rs b/pkg/zk-circuits/src/test/util.rs deleted file mode 100644 index 84357d1..0000000 --- a/pkg/zk-circuits/src/test/util.rs +++ /dev/null @@ -1,187 +0,0 @@ -use halo2_base::halo2_proofs::{ - halo2curves::{ - bn256::{Bn256, Fr, G1Affine}, - FieldExt, - }, - plonk::{ - keygen_pk, keygen_vk, Advice, Circuit, Column, ConstraintSystem, Error, Instance, - ProvingKey, VerifyingKey, - }, - poly::kzg::commitment::ParamsKZG, -}; -use itertools::Itertools; -use smirk::Element; - -use crate::{ - chips::{ - aggregation::snark::Snark, - is_constant::{IsConstantChip, IsConstantConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, - }, - data::MerklePath, -}; - -pub fn poseidon_config(meta: &mut ConstraintSystem) -> PoseidonConfig { - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[1..4].try_into().unwrap(), - lagrange_coeffs[4..7].try_into().unwrap(), - ) -} - -pub fn is_padding_config( - meta: &mut ConstraintSystem, - constant_val: F, -) -> IsConstantConfig { - let a = advice_column_equality(meta); - let b = advice_column_equality(meta); - let c = advice_column_equality(meta); - IsConstantChip::configure(meta, a, b, c, constant_val) -} - -pub fn swap_config(meta: &mut ConstraintSystem) -> CondSwapConfig { - let advices = [ - advice_column_equality(meta), - advice_column_equality(meta), - advice_column_equality(meta), - advice_column_equality(meta), - advice_column_equality(meta), - ]; - CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()) -} - -pub fn advice_column_equality(meta: &mut ConstraintSystem) -> Column { - let advice = meta.advice_column(); - meta.enable_equality(advice); - advice -} - -pub fn instance_column_equality(meta: &mut ConstraintSystem) -> Column { - let instance = meta.instance_column(); - meta.enable_equality(instance); - instance -} - -pub fn get_params>( - k: u32, - circuit: &C, -) -> ( - ParamsKZG, - VerifyingKey, - ProvingKey, -) { - let params = halo2_base::utils::fs::gen_srs(k); - let vk = keygen_vk(¶ms, circuit).expect("keygen_vk should not fail"); - let pk = keygen_pk(¶ms, vk.clone(), circuit).expect("keygen_pk should not fail"); - - (params, vk, pk) -} - -pub fn get_snark>(k: u32, circuit: C, instances: Vec) -> Result { - let (params, _, pk) = get_params(k, &circuit); - Snark::create(circuit, vec![instances], ¶ms, &pk) -} - -pub fn apply_two_merkle_leaves( - leaf_1: Element, - leaf_2: Element, -) -> MerklePath { - let default_path = MerklePath::::default(); - let applied_path = default_path.apply_leaf(leaf_1); - - // Calculate the computed leaves based on leaf_1 on default tree, from high to low - let computed_siblings = applied_path.siblings.iter().rev().collect_vec(); - - let leaf_1_bits = leaf_1.lsb(DEPTH - 1).into_iter().collect_vec(); - - let leaf_2_bits = leaf_2.lsb(DEPTH - 1).into_iter().collect_vec(); - - // let leaf_1_bits = MerklePath::::bits(&leaf_1); - // let leaf_1_bits = leaf_1_bits.iter().map(|b| *b).rev().collect_vec(); - // let leaf_2_bits = MerklePath::::bits(&leaf_2); - // let leaf_2_bits = leaf_2_bits.iter().map(|b| *b).rev().collect_vec(); - - let mut second_path_siblings = MerklePath::::default() - .siblings - .into_iter() - .rev() - .collect_vec(); - - for (i, _) in computed_siblings.iter().enumerate() { - if leaf_1_bits[i] != leaf_2_bits[i] { - second_path_siblings[i] = *computed_siblings[i]; - break; - } - } - - second_path_siblings.reverse(); - - let new_sibs_path = MerklePath { - siblings: second_path_siblings, - }; - - assert_eq!( - default_path.compute_root(leaf_1), - new_sibs_path.compute_null_root(leaf_2), - "leaf_1 new root, must match leaf_2 old root" - ); - - new_sibs_path -} - -#[cfg(test)] -mod tests { - use crate::util::insecure_random_element; - - use super::*; - - #[test] - fn test_apply_two_merkle_leaves() { - let leaf_1 = Element::from(4u64); - let leaf_2 = Element::from(6u64); - - apply_two_merkle_leaves::<3>(leaf_1, leaf_2); - } - - #[test] - fn test_apply_two_merkle_leaves_0_6() { - let leaf_1 = Element::from(1u64); - let leaf_2 = Element::from(6u64); - - apply_two_merkle_leaves::<3>(leaf_1, leaf_2); - } - - #[test] - fn test_apply_two_merkle_leaves_big_tree() { - let leaf_1 = insecure_random_element(); - let leaf_2 = insecure_random_element(); - - apply_two_merkle_leaves::<32>(leaf_1, leaf_2); - } -} diff --git a/pkg/zk-circuits/src/traits.rs b/pkg/zk-circuits/src/traits.rs new file mode 100644 index 0000000..da5081f --- /dev/null +++ b/pkg/zk-circuits/src/traits.rs @@ -0,0 +1,28 @@ +use std::sync::Arc; + +use crate::Result; +use async_trait::async_trait; +use barretenberg_interface::BbBackend; + +#[async_trait] +pub trait Prove { + type Proof: Verify + Send + Sync; + + async fn prove(&self, bb_backend: &dyn BbBackend) -> Result; +} + +#[async_trait] +pub trait Verify: Send + Sync { + #[must_use = "verification result must be explicitly handled"] + async fn verify(&self, bb_backend: &dyn BbBackend) -> Result<()>; +} + +#[unimock::unimock(api = CircuitMock)] +#[async_trait] +pub trait Circuit: Send + Sync { + async fn prove(&self, input: &Input, bb_backend: Arc) -> Result; +} + +pub use crate::circuits::generated::AggAggCircuitInterface; +pub use crate::circuits::generated::AggFinalCircuitInterface; +pub use crate::circuits::generated::AggUtxoCircuitInterface; diff --git a/pkg/zk-circuits/src/util.rs b/pkg/zk-circuits/src/util.rs index 4515111..7bf78d2 100644 --- a/pkg/zk-circuits/src/util.rs +++ b/pkg/zk-circuits/src/util.rs @@ -1,144 +1,12 @@ -use crate::constants::BLAKE_PERSONALISATION; -use crate::data::ParameterSet; -use crate::params::load_params; -use base64::Engine; -use blake2b_simd::Params as Blake2bParams; -use halo2_base::halo2_proofs::{ - arithmetic::{Field, FieldExt}, - circuit::{AssignedCell, Layouter, Value}, - halo2curves::bn256::{Fr, G1Affine}, - plonk::{ - keygen_pk, keygen_vk, Advice, Assigned, Circuit, Column, Error, ProvingKey, VerifyingKey, - }, -}; -use num_bigint::{BigUint, ToBigUint}; -use serde::{Deserialize, Deserializer, Serializer}; -use zk_primitives::Element; - -pub(crate) fn assign_private_input NR, NR: Into>( - name: N, - mut layouter: impl Layouter, - column: Column, - value: Value, -) -> Result, Error> -where - for<'v> Assigned: From<&'v V>, -{ - layouter.assign_region(name, |mut region| { - region.assign_advice(|| "load advice", column, 0, || value) - }) -} - -pub(crate) fn assign_constant NR, NR: Into>( - name: N, - mut layouter: impl Layouter, - column: Column, - value: V, -) -> Result, Error> -where - for<'v> Assigned: From<&'v V>, -{ - layouter.assign_region(name, |mut region| { - region.assign_advice_from_constant(|| "load constant advice", column, 0, value) - }) -} - -pub fn blake_hash(message: [&[u8]; L]) -> Element { - let mut h = Blake2bParams::new() - .hash_length(64) - .personal(BLAKE_PERSONALISATION) - .to_state(); - - for i in message { - h.update(i); - } - - let psi_bytes = *h.finalize().as_array(); - Fr::from_bytes_wide(&psi_bytes).into() -} - -// fn random_bytes_32() { -// let mut rng = rand::thread_rng(); -// let mut bytes = [0u8; 32]; -// rng.fill(&mut bytes[..]) -// } - -pub(crate) fn random_fr() -> Fr { - let mut rng = rand::thread_rng(); - Fr::random(&mut rng) -} - -pub fn insecure_random_element() -> Element { - let mut rng: rand::rngs::ThreadRng = rand::thread_rng(); - Element::random(&mut rng).get_insecure() -} -pub(crate) fn keygen_from_params>( - params: ParameterSet, - circuit: &C, -) -> (ProvingKey, VerifyingKey) { - let params = load_params(params); - - let vk = keygen_vk(params, circuit).expect("keygen_vk should not fail"); - let pk = keygen_pk(params, vk.clone(), circuit).expect("keygen_pk should not fail"); - - (pk, vk) -} - -pub fn decompose_to_limbs(mut num: BigUint, num_limbs: u32, num_bits: u32) -> Vec { - let mut parts = Vec::new(); - for _ in 0..num_limbs { - let limb_mask = (BigUint::from(1u128) << num_bits) - 1u32.to_biguint().unwrap(); - let part = &num & &limb_mask; - parts.push(part); - num >>= num_bits; - } - - parts -} - -// Custom serializer for Vec to base64 string -pub fn serialize_base64(value: &Vec, serializer: S) -> Result -where - S: Serializer, -{ - let base64_string = base64::engine::general_purpose::STANDARD.encode(value); - serializer.serialize_str(&base64_string) -} - -pub fn serialize_base64_opt(value: &Option>, serializer: S) -> Result -where - S: Serializer, -{ - match value { - Some(v) => serialize_base64(v, serializer), - None => serializer.serialize_none(), - } -} - -// Custom deserializer for base64 string to Vec -pub fn deserialize_base64<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - base64::engine::general_purpose::STANDARD - .decode(s) - .map_err(serde::de::Error::custom) -} - -pub fn serialize_hex_0x_prefixed(value: &Vec, serializer: S) -> Result -where - S: Serializer, -{ - let hex_string = format!("0x{}", hex::encode(value)); - serializer.serialize_str(&hex_string) -} - -pub fn deserialize_hex_0x_prefixed<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - let s = s.trim_start_matches("0x"); - hex::decode(s).map_err(serde::de::Error::custom) +use std::io::Write; +use std::path::PathBuf; + +pub fn write_to_temp_file(data: &[u8], suffix: &str) -> PathBuf { + let mut file = tempfile::NamedTempFile::with_suffix(suffix).unwrap(); + file.write_all(data).unwrap(); + file.flush().unwrap(); + let path = file.path().to_path_buf(); + // Deliberately leak the tempfile to prevent deletion + std::mem::forget(file); + path } diff --git a/pkg/zk-circuits/src/utxo/circuit.rs b/pkg/zk-circuits/src/utxo/circuit.rs deleted file mode 100644 index eeac438..0000000 --- a/pkg/zk-circuits/src/utxo/circuit.rs +++ /dev/null @@ -1,141 +0,0 @@ -use crate::{ - chips::{ - add::{AddCulmChip, AddCulmChipConfig}, - binary_decomposition::BinaryDecompositionConfig, - is_constant::{IsConstantChip, IsConstantConfig}, - poseidon::{P128Pow5T3Fr, PoseidonChip, PoseidonConfig}, - swap::{CondSwapChip, CondSwapConfig}, - }, - data::{Note, Utxo, UtxoKind}, -}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - halo2curves::bn256::Fr, - plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Instance}, -}; - -#[derive(Clone, Debug)] -pub struct UtxoCircuitConfig { - advices: [Column; 5], - instance: Column, - poseidon_config: PoseidonConfig, - culm_add_config: AddCulmChipConfig, - swap_config: CondSwapConfig, - is_padding_config: IsConstantConfig, - is_mint_config: IsConstantConfig, - is_burn_config: IsConstantConfig, - binary_decomposition_config: BinaryDecompositionConfig, -} - -impl Circuit for Utxo { - type FloorPlanner = SimpleFloorPlanner; - type Config = UtxoCircuitConfig; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - let instance = meta.instance_column(); - meta.enable_equality(instance); - - let advices = [ - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - meta.advice_column(), - ]; - - for advice in advices.iter() { - meta.enable_equality(*advice); - } - - let lagrange_coeffs = [ - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - meta.fixed_column(), - ]; - meta.enable_constant(lagrange_coeffs[0]); - - let poseidon_config = PoseidonChip::configure::( - meta, - advices[1..4].try_into().unwrap(), - advices[0], - lagrange_coeffs[0..3].try_into().unwrap(), - lagrange_coeffs[3..6].try_into().unwrap(), - ); - - let culm_add_config = AddCulmChip::configure(meta, advices[0], advices[1]); - - let swap_config = CondSwapChip::configure(meta, advices[0..5].try_into().unwrap()); - - // Padding chip - let is_padding_config = IsConstantChip::configure( - meta, - advices[0], - advices[1], - advices[2], - Note::padding_note().commitment().into(), - ); - - // Is mint chip - let is_mint_config = IsConstantChip::configure( - meta, - advices[0], - advices[1], - advices[2], - UtxoKind::Mint.as_element(), - ); - - // Is burn chip - let is_burn_config = IsConstantChip::configure( - meta, - advices[0], - advices[1], - advices[2], - UtxoKind::Burn.as_element(), - ); - - let q_range_check = meta.selector(); - let binary_decomposition_config = - BinaryDecompositionConfig::configure(meta, q_range_check, advices[0], advices[1]); - - UtxoCircuitConfig { - advices, - instance, - poseidon_config, - culm_add_config, - swap_config, - is_padding_config, - is_mint_config, - is_burn_config, - binary_decomposition_config, - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Get the public instances - self.enforce_constraints( - layouter.namespace(|| "txn"), - config.instance, - config.advices[0], - config.poseidon_config, - AddCulmChip::construct(config.culm_add_config), - CondSwapChip::construct(config.swap_config), - IsConstantChip::construct(config.is_padding_config), - IsConstantChip::construct(config.is_mint_config), - IsConstantChip::construct(config.is_burn_config), - config.binary_decomposition_config, - )?; - - Ok(()) - } -} diff --git a/pkg/zk-circuits/src/utxo/input_note.rs b/pkg/zk-circuits/src/utxo/input_note.rs deleted file mode 100644 index 2e3306a..0000000 --- a/pkg/zk-circuits/src/utxo/input_note.rs +++ /dev/null @@ -1,275 +0,0 @@ -use super::note::NoteConstraintCells; -use crate::{ - chips::{ - is_constant::IsConstantChip, - merkle_path::MerklePathInclusionConstrainCells, - poseidon::{poseidon_hash_gadget, PoseidonConfig}, - swap::CondSwapChip, - }, - data::{InputNote, MerklePath, Note}, - util::{assign_constant, assign_private_input}, -}; -use halo2_base::halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error}, -}; -use zk_primitives::Element; - -impl InputNote { - pub fn new(note: Note, secret_key: Element, merkle_path: MerklePath) -> Self { - InputNote { - note, - secret_key, - merkle_path, - } - } - - /// Deterministic padding note - pub fn padding_note() -> Self { - InputNote { - note: Note::padding_note(), - secret_key: Element::ZERO, - merkle_path: MerklePath::default(), - } - } - - pub fn output_note(&self, address: Element, value: Element) -> Note { - Note::new_with_source(address, value, self.note.address) - } - - pub fn is_padding(&self) -> bool { - self.note.commitment() == Note::padding_note().commitment() - } - - /// Get the nullifier for an input note - pub fn nullifer(&self) -> Element { - self.note.nullifier(self.secret_key) - } - - /// Enforces constraints for the input note (includes default note constraints, plus additional - /// constraints to prove spending of note is allowable) - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - advice: Column, - poseidon_config: PoseidonConfig, - swap_chip: CondSwapChip, - is_zero_chip: IsConstantChip, - ) -> Result { - // First we need to check the std note constraints - let note_commitment_cells = self.note.enforce_constraints( - layouter.namespace(|| "input note enforce commitment"), - advice, - poseidon_config.clone(), - is_zero_chip, - swap_chip.clone(), - )?; - - // Check input note commitment is in an existing merkle root - let MerklePathInclusionConstrainCells { root } = - self.merkle_path.enforce_inclusion_constraints( - layouter.namespace(|| "leaf in tree"), - self.note.commitment().into(), - note_commitment_cells.cm.clone(), - poseidon_config.clone(), - swap_chip, - )?; - - // Witness secret_key - let secret_key = assign_private_input( - || "secret key witness", - layouter.namespace(|| "secret key witness"), - advice, - Value::known(self.secret_key().into()), - )?; - - let padding = assign_constant( - || "padding witness", - layouter.namespace(|| "padding witness"), - advice, - Fr::zero(), - )?; - - // Verify that the address matches the secret key - let verified_address = poseidon_hash_gadget( - poseidon_config.clone(), - layouter.namespace(|| "verify address"), - [secret_key.clone(), padding.clone()], - )?; - - // Constrain address to be the same as verified address - // TODO: are we allowed to constrain_equal between two different regions cells? - layouter.assign_region( - || "constrain address", - |mut region| { - region.constrain_equal( - verified_address.cell(), - note_commitment_cells.address.cell(), - ) - }, - )?; - - // Generate the nullifier - let nullifier = poseidon_hash_gadget( - poseidon_config, - layouter.namespace(|| "nullifer hash"), - [ - note_commitment_cells.cm.clone(), - secret_key.clone(), - note_commitment_cells.psi.clone(), - padding.clone(), - ], - )?; - - Ok(InputNoteConstraintCells { - commitment: note_commitment_cells, - nullifier, - root, - secret_key, - zero: padding, - }) - } - - pub fn secret_key(&self) -> Element { - self.secret_key - } - - pub fn recent_root(&self) -> Element { - self.merkle_path.compute_root(self.note.commitment()) - } - - pub fn note(&self) -> &Note { - &self.note - } - - pub fn value(&self) -> Element { - self.note.value() - } - - pub fn source(&self) -> Element { - self.note.source() - } - - pub fn commitment(&self) -> Element { - self.note.commitment() - } -} - -pub struct InputNoteConstraintCells { - /// Note commitment constaint cells - pub commitment: NoteConstraintCells, - /// Nullifier to be inserted into hte tree - pub nullifier: AssignedCell, - /// recent root commitment that merkle tree path was verified against - pub root: AssignedCell, - /// Secret key for the address, required to spend a note - pub secret_key: AssignedCell, - /// Padding - pub zero: AssignedCell, -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - chips::{is_constant::IsConstantConfig, swap::CondSwapConfig}, - constants::MERKLE_TREE_DEPTH, - test::util::{ - advice_column_equality, instance_column_equality, is_padding_config, poseidon_config, - }, - }; - use halo2_base::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - dev::MockProver, - plonk::{Advice, Circuit, Column, Error, Instance}, - }; - use rand::thread_rng; - use smirk::hash_merge; - - #[derive(Clone, Debug)] - struct InputNoteCircuitConfig { - poseidon_config: PoseidonConfig, - swap_config: CondSwapConfig, - advice: Column, - instance: Column, - is_zero_config: IsConstantConfig, - } - - #[derive(Default, Debug, Clone)] - struct InputNoteCircuit { - input_note: InputNote, - } - - impl Circuit for InputNoteCircuit { - type Config = InputNoteCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure( - meta: &mut halo2_base::halo2_proofs::plonk::ConstraintSystem, - ) -> Self::Config { - let advices: [Column; 5] = (0..5) - .map(|_| advice_column_equality(meta)) - .collect::>() - .try_into() - .unwrap(); - - InputNoteCircuitConfig { - poseidon_config: poseidon_config(meta), - swap_config: CondSwapChip::configure(meta, advices), - is_zero_config: is_padding_config(meta, Fr::zero()), - advice: advice_column_equality(meta), - instance: instance_column_equality(meta), - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let input_note_cells = self.input_note.enforce_constraints( - layouter.namespace(|| "input note"), - config.advice, - config.poseidon_config, - CondSwapChip::construct(config.swap_config), - IsConstantChip::construct(config.is_zero_config), - )?; - - layouter.constrain_instance( - input_note_cells.commitment.cm.cell(), - config.instance, - 0, - )?; - layouter.constrain_instance(input_note_cells.nullifier.cell(), config.instance, 1)?; - layouter.constrain_instance(input_note_cells.root.cell(), config.instance, 2)?; - - Ok(()) - } - } - - #[test] - fn test_input_note() { - let k = 14; - let pk = Element::secure_random(thread_rng()); - let address = hash_merge([pk, Element::ZERO]); - - let note = Note::new(address, Element::from(100u64)); - let path = MerklePath::default(); - let input_note = InputNote::new(note.clone(), pk, path.clone()); - - let nullifier = input_note.nullifer(); - let root = path.compute_root(note.commitment()); - - let public_input = vec![note.commitment().into(), nullifier.into(), root.into()]; - let instance_columns = vec![public_input]; - let circuit = InputNoteCircuit { input_note }; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } -} diff --git a/pkg/zk-circuits/src/utxo/mod.rs b/pkg/zk-circuits/src/utxo/mod.rs deleted file mode 100644 index 941440d..0000000 --- a/pkg/zk-circuits/src/utxo/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -mod circuit; -mod input_note; -mod note; -pub mod proof; -#[cfg(test)] -mod tests; -#[allow(clippy::module_inception)] -mod utxo; - -/// UTXO circuit runs on the client, it takes a set of input notes, validates a given merkle path -/// (which will later be used to prove they are in the tree), and outputs a set of output notes -/// -/// (Private) (Public) -/// ┌────────┐ -/// InputNote │ │ Nullifer (for InputNote) -/// InputNote ───► │ UTXO │ ───► Nullifer (for InputNote) -/// Note (output) │ │ Note (output) commitment -/// Note (output) │ │ Note (output) commitment -/// │ │ Recent Merkle Root (used to verify Input Notes) -/// └────────┘ -/// -// Main circuit -pub use utxo::*; - -// Input/output notes to utxo txn -pub use input_note::*; -pub use note::*; diff --git a/pkg/zk-circuits/src/utxo/note.rs b/pkg/zk-circuits/src/utxo/note.rs deleted file mode 100644 index 9a38bc1..0000000 --- a/pkg/zk-circuits/src/utxo/note.rs +++ /dev/null @@ -1,342 +0,0 @@ -#![allow(clippy::assign_op_pattern)] - -use crate::{ - chips::{ - is_constant::IsConstantChip, - poseidon::{poseidon_hash, poseidon_hash_gadget, PoseidonConfig}, - swap::CondSwapChip, - }, - constants::NOTE_RCM_EXT, - data::Note, - util::{assign_constant, assign_private_input, random_fr}, -}; -use halo2_base::halo2_proofs::{ - circuit::{AssignedCell, Layouter, Value}, - halo2curves::bn256::Fr, - plonk::{Advice, Column, Error}, -}; -use smirk::hash_merge; -use zk_primitives::Element; - -impl Note { - pub fn new(address: Element, value: Element) -> Self { - Self::new_with_source(address, value, address) - } - - pub(crate) fn new_with_source(address: Element, value: Element, source: Element) -> Self { - let rseed = random_fr(); - let psi = poseidon_hash([rseed, Fr::from(NOTE_RCM_EXT as u64)]); - - Self::restore(address, psi.into(), value, source) - } - - pub fn restore(address: Element, psi: Element, value: Element, source: Element) -> Self { - Note { - address, - psi, - value, - source, - token: "USDC".to_string(), - } - } - - /// Deterministic padding note - pub fn padding_note() -> Self { - let zero_hash: Element = poseidon_hash([Fr::zero(), Fr::zero()]).into(); - Note { - address: zero_hash, - psi: Element::ZERO, - value: Element::ZERO, - source: zero_hash, - token: "USDC".to_string(), - } - } - - /// Hash/commitment for the note - pub fn commitment(&self) -> Element { - if self.value() == Element::ZERO { - return Element::ZERO; - } - - hash_merge([ - self.value(), - self.address, - self.psi, - self.source, - // TODO: should these be zero? - Element::ONE, - Element::ONE, - ]) - } - - pub fn is_padding(&self) -> bool { - self.commitment() == Note::padding_note().commitment() || self.commitment() == Element::ZERO - } - - pub fn nullifier(&self, secret_key: Element) -> Element { - if self.is_padding() { - Note::padding_note().commitment() - } else { - hash_merge([self.commitment(), secret_key, self.psi(), Element::ZERO]) - } - } - - /// Enforces constraints for the note - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - advice: Column, - poseidon_config: PoseidonConfig, - is_zero_chip: IsConstantChip, - swap_chip: CondSwapChip, - ) -> Result { - // Reconstruct the commitment using its parts by witnessing each of the parts/values - // and then generating the commitment using those witnessed values. Those witnessed values - // can later be used knowing they came from the commitment - // [value, address, psi] - - // Witness zero - let zero = assign_constant( - || "zero witness", - layouter.namespace(|| "zero witness"), - advice, - Fr::zero(), - )?; - - // Witness value - let value = assign_private_input( - || "value witness", - layouter.namespace(|| "value witness"), - advice, - Value::known(self.value().into()), - )?; - - // Witness address - let address = assign_private_input( - || "address witness", - layouter.namespace(|| "address witness"), - advice, - Value::known(self.address().into()), - )?; - - // Witness psi - let psi = assign_private_input( - || "psi witness", - layouter.namespace(|| "psi witness"), - advice, - Value::known(self.psi().into()), - )?; - - // Witness Source - let source: AssignedCell = assign_private_input( - || "source witness", - layouter.namespace(|| "source witness"), - advice, - Value::known(self.source().into()), - )?; - - // Witness Version - let version: AssignedCell = assign_private_input( - || "version witness", - layouter.namespace(|| "version witness"), - advice, - Value::known(Fr::one()), - )?; - - // Calculate the incoming commitment, must be equal number of elements! - let cm = poseidon_hash_gadget( - poseidon_config, - layouter.namespace(|| "note commitment hash"), - [ - value.clone(), - address.clone(), - psi.clone(), - source.clone(), - version.clone(), - version, - ], - )?; - - // Padding check - let is_value_zero = - is_zero_chip.assign(layouter.namespace(|| "is zero/padding"), value.clone())?; - - // Swap cm to zero if padding - let (cm, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap cm if padding note"), - (&cm, &zero), - &is_value_zero, - )?; - - Ok(NoteConstraintCells { - value, - address, - cm, - is_padding: is_value_zero, - source, - psi, - }) - } - - pub fn value(&self) -> Element { - self.value - } - - pub fn address(&self) -> Element { - self.address - } - - pub fn psi(&self) -> Element { - self.psi - } - - pub fn source(&self) -> Element { - self.source - } -} - -pub struct NoteConstraintCells { - /// AssignedCell holding the notes value - pub value: AssignedCell, - /// AssignedCell holding the notes address - pub address: AssignedCell, - /// AssignedCell holding the notes commitment hash - pub cm: AssignedCell, - // AssignedCell identifying if this note is for padding only - pub is_padding: AssignedCell, - /// AssignedCell for the source of note - pub source: AssignedCell, - /// PSI for the source of note - pub psi: AssignedCell, -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - chips::{ - is_constant::{IsConstantChip, IsConstantConfig}, - swap::CondSwapConfig, - }, - test::util::{ - advice_column_equality, instance_column_equality, is_padding_config, poseidon_config, - swap_config, - }, - }; - use halo2_base::halo2_proofs::{ - arithmetic::Field, - circuit::SimpleFloorPlanner, - dev::MockProver, - plonk::{Circuit, ConstraintSystem, Instance}, - }; - use rand::rngs::OsRng as rng; - - #[test] - fn test_serde_note() { - let note = Note { - address: Element::random(rng).get_insecure(), - psi: Element::random(rng).get_insecure(), - value: Element::from(100u64), - source: Element::random(rng).get_insecure(), - token: "USDC".to_string(), - }; - - // Serialize note - let note_json = serde_json::to_string(¬e).unwrap(); - - // Deserialize note - let deserialized_note: Note = serde_json::from_str(¬e_json).unwrap(); - - assert_eq!(note, deserialized_note); - } - - #[derive(Clone, Debug, Default)] - struct NoteCircuit { - note: Note, - } - - #[derive(Clone, Debug)] - struct NoteCircuitConfig { - poseidon_config: PoseidonConfig, - advice: Column, - instance: Column, - swap_config: CondSwapConfig, - is_zero_config: IsConstantConfig, - } - - impl NoteCircuit { - pub fn new(note: Note) -> Self { - NoteCircuit { note } - } - } - - impl Circuit for NoteCircuit { - type Config = NoteCircuitConfig; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::default() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - NoteCircuitConfig { - poseidon_config: poseidon_config(meta), - is_zero_config: is_padding_config(meta, Fr::zero()), - swap_config: swap_config(meta), - advice: advice_column_equality(meta), - instance: instance_column_equality(meta), - } - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - let is_zero_chip = IsConstantChip::construct(config.is_zero_config); - - let note_cells = self.note.enforce_constraints( - layouter.namespace(|| "note constraints"), - config.advice, - config.poseidon_config, - is_zero_chip, - CondSwapChip::construct(config.swap_config), - )?; - - layouter.constrain_instance(note_cells.cm.cell(), config.instance, 0)?; - layouter.constrain_instance(note_cells.is_padding.cell(), config.instance, 1)?; - - Ok(()) - } - } - - #[test] - fn test_note() { - let k = 8; - let address = Fr::random(rng); - - let note = Note::new(address.into(), Element::from(100u64)); - let cm = note.commitment(); - - let public_input = vec![cm.into(), Fr::zero()]; - let instance_columns = vec![public_input]; - let circuit = NoteCircuit::new(note); - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } - - #[test] - fn test_padding() { - let k = 8; - let note = Note::padding_note(); - let cm = note.commitment(); - - let public_input = vec![cm.into(), Fr::one()]; - let instance_columns = vec![public_input]; - let circuit = NoteCircuit::new(note); - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - } -} diff --git a/pkg/zk-circuits/src/utxo/proof.rs b/pkg/zk-circuits/src/utxo/proof.rs deleted file mode 100644 index 0b02f07..0000000 --- a/pkg/zk-circuits/src/utxo/proof.rs +++ /dev/null @@ -1,164 +0,0 @@ -use crate::{ - constants::{UTXO_INPUTS, UTXO_OUTPUTS}, - data::{ParameterSet, SnarkWitness, SnarkWitnessV1, UTXOProof, Utxo}, - CircuitKind, Snark, -}; -use primitives::hash::CryptoHash; -use sha3::{Digest, Keccak256}; -use zk_primitives::Element; - -impl UTXOProof { - pub fn new( - recent_root: Element, - mb_hash: Element, - mb_value: Element, - input_leaves: [Element; UTXO_INPUTS], - output_leaves: [Element; UTXO_OUTPUTS], - proof: Vec, - ) -> Self { - Self { - recent_root, - mb_hash, - mb_value, - input_leaves, - output_leaves, - proof, - } - } - - pub fn hash(&self) -> CryptoHash { - let mut sorted_input_leaves = self.input_leaves; - sorted_input_leaves.sort(); - let mut sorted_output_leaves = self.output_leaves; - sorted_output_leaves.sort(); - - let mut hasher = Keccak256::new(); - hasher.update(self.recent_root.to_be_bytes()); - hasher.update(self.mb_hash.to_be_bytes()); - hasher.update(self.mb_value.to_be_bytes()); - for leaf in sorted_input_leaves.iter() { - hasher.update(leaf.to_be_bytes()); - } - for leaf in sorted_output_leaves.iter() { - hasher.update(leaf.to_be_bytes()); - } - - CryptoHash::new(hasher.finalize().into()) - } - - /// Whether this UTXO is a mint or burn. - /// - /// If `true`, this is a mint or burn, otherwise it is a transfer - pub fn is_mint_or_burn(&self) -> bool { - self.mb_hash != Element::NULL_HASH || self.mb_value != Element::NULL_HASH - } - - pub fn is_mint(&self) -> bool { - self.is_mint_or_burn() && self.input_leaves.iter().all(|l| *l == Element::NULL_HASH) - } - - pub fn is_burn(&self) -> bool { - self.is_mint_or_burn() && self.output_leaves.iter().all(|l| *l == Element::NULL_HASH) - } - - pub fn from_snark_witness(snark: SnarkWitness) -> Self { - let SnarkWitness::V1(snark) = snark; - let instances = &snark.instances[0]; - let recent_root = instances[0]; - let mb_hash = instances[1]; - let mb_value = instances[2]; - let input_leaves = [instances[3], instances[4]]; - let output_leaves = [instances[5], instances[6]]; - Self { - recent_root, - mb_hash, - mb_value, - input_leaves, - output_leaves, - proof: snark.proof, - } - } - - pub fn to_snark(&self, params: ParameterSet) -> Snark { - let utxo = Utxo::::default(); - let (_, vk) = utxo.keygen(params); - - match self.to_snark_witness() { - SnarkWitness::V1(witness) => witness.to_snark(&vk, params), - } - } - - pub fn to_snark_witness(&self) -> SnarkWitness { - let sw = SnarkWitnessV1::new(vec![self.instances()], self.proof.clone()); - SnarkWitness::V1(sw) - } - - pub fn leaves(&self) -> Vec { - self.input_leaves - .into_iter() - .chain(self.output_leaves.into_iter()) - .collect() - } - - pub fn instances(&self) -> Vec { - vec![self.recent_root, self.mb_hash, self.mb_value] - .into_iter() - .chain(self.leaves()) - .collect() - } - - pub fn verify(&self) -> bool { - match self.to_snark_witness() { - SnarkWitness::V1(sw) => sw.verify(CircuitKind::Utxo), - } - } -} - -#[cfg(test)] -mod tests { - use crate::{ - constants::MERKLE_TREE_DEPTH, - data::{InputNote, Note, UtxoKind}, - }; - - use super::*; - - #[test] - fn gen_utxo() { - let u = Utxo::<161>::new( - [InputNote::padding_note(), InputNote::padding_note()], - [Note::padding_note(), Note::padding_note()], - smirk::Tree::<161, ()>::new().root_hash(), - UtxoKind::Transfer, - ); - - let snark = u.snark(CircuitKind::Utxo).unwrap(); - - assert!(snark.to_witness().verify(CircuitKind::Utxo)); - - let utxo_proof = UTXOProof::<161>::from_snark_witness(SnarkWitness::V1(snark.to_witness())); - assert!(utxo_proof.verify()); - - let snark_witness = utxo_proof.to_snark_witness(); - println!("{}", serde_json::to_string(&snark_witness).unwrap()); - } - - #[test] - fn bench_txn_hashing() { - let txn = UTXOProof::::new( - Element::new(1), - Element::new(2), - Element::new(3), - [Element::new(5), Element::new(6)], - [Element::new(7), Element::new(8)], - vec![], - ); - - let start = std::time::Instant::now(); - for _ in 0..1000 { - let _ = txn.hash(); - } - - eprintln!("1000 hashes took {:?}", start.elapsed()); - } -} diff --git a/pkg/zk-circuits/src/utxo/tests.rs b/pkg/zk-circuits/src/utxo/tests.rs deleted file mode 100644 index 0ac7386..0000000 --- a/pkg/zk-circuits/src/utxo/tests.rs +++ /dev/null @@ -1,147 +0,0 @@ -use crate::{ - constants::MERKLE_TREE_DEPTH, - data::{InputNote, Note, Utxo, UtxoKind}, - test::rollup::Rollup, - CircuitKind, -}; -use halo2_base::halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; - -#[test] -fn test_utxo_one_input_one_output() { - let k = 14; - - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - let alice = rollup.new_wallet(); - - // Add existing note to the tree for bob - let bob_note = rollup.unverified_add_unspent_note(&bob, 10); - let recent_root = rollup.root_hash(); - - let input_note = rollup.to_input_note(&bob_note); - let input_notes = [input_note.clone(), InputNote::padding_note()]; - - let output_note = alice.new_note(10); - let output_notes = [output_note.clone(), Note::padding_note()]; - - let circuit = Utxo::new(input_notes, output_notes, recent_root, UtxoKind::Transfer); - let public_input = circuit.public_inputs(); - - assert_eq!(public_input.len(), 7); - assert_eq!(public_input[0], recent_root.to_base()); - assert_eq!(public_input[1], Fr::zero()); - assert_eq!(public_input[2], Fr::zero()); - assert_eq!(public_input[3], input_note.nullifer().into()); - assert_eq!(public_input[4], Fr::zero()); - assert_eq!(public_input[5], output_note.commitment().into()); - assert_eq!(public_input[6], Fr::zero()); - - let instance_columns = vec![public_input]; - - // Prove mock - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); - - // Prove for real circuit - let snark = circuit.snark(CircuitKind::Utxo).unwrap(); - assert!(snark.to_witness().verify(CircuitKind::Utxo)); -} - -#[test] -fn test_utxo_one_input_two_output() { - let k = 14; - - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - let alice = rollup.new_wallet(); - let sally = rollup.new_wallet(); - - // Add existing note to the tree for bob - let bob_note = rollup.unverified_add_unspent_note(&bob, 100); - let recent_root = rollup.root_hash(); - - let input_note = rollup.to_input_note(&bob_note); - let input_notes = [input_note.clone(), InputNote::padding_note()]; - - let output_notes = [alice.new_note(30), sally.new_note(70)]; - - let circuit = Utxo::new( - input_notes, - output_notes.clone(), - recent_root, - UtxoKind::Transfer, - ); - let public_input = circuit.public_inputs(); - - assert_eq!(public_input.len(), 7); - assert_eq!(public_input[0], recent_root.to_base()); - assert_eq!(public_input[1], Fr::zero()); - assert_eq!(public_input[2], Fr::zero()); - assert_eq!(public_input[3], input_note.nullifer().into()); - assert_eq!(public_input[4], Fr::zero()); - assert_eq!(public_input[5], output_notes[0].commitment().into()); - assert_eq!(public_input[6], output_notes[1].commitment().into()); - - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); -} - -#[test] -fn test_utxo_mint() { - let k = 14; - - let rollup = Rollup::new(); - let bob = rollup.new_wallet(); - - let output_note = bob.new_note(100); - - let circuit = Utxo::::new_mint(output_note.clone()); - let public_input = circuit.public_inputs(); - - assert_eq!(public_input.len(), 7); - assert_eq!(public_input[0], Fr::zero()); - assert_eq!(public_input[1], output_note.commitment().into()); - assert_eq!(public_input[2], Fr::from(100u64)); - assert_eq!(public_input[3], Fr::zero()); - assert_eq!(public_input[4], Fr::zero()); - assert_eq!(public_input[5], output_note.commitment().into()); - assert_eq!(public_input[6], Fr::zero()); - - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); -} - -#[test] -fn test_utxo_burn() { - let k = 14; - - let mut rollup = Rollup::new(); - let bob = rollup.new_wallet(); - - // Add existing note to the tree for bob - let bob_note = rollup.unverified_add_unspent_note(&bob, 100); - let recent_root = rollup.root_hash(); - - let input_note = rollup.to_input_note(&bob_note); - - let circuit = Utxo::new_burn(input_note.clone(), recent_root); - let public_input = circuit.public_inputs(); - - assert_eq!(public_input.len(), 7); - assert_eq!(public_input[0], recent_root.to_base()); - assert_eq!(public_input[3], input_note.nullifer().into()); - assert_eq!(public_input[2], Fr::from(100u64)); - assert_eq!(public_input[3], input_note.nullifer().into()); - assert_eq!(public_input[4], Fr::zero()); - assert_eq!(public_input[5], Fr::zero()); - assert_eq!(public_input[6], Fr::zero()); - - let instance_columns = vec![public_input]; - - let prover = MockProver::::run(k, &circuit, instance_columns).unwrap(); - prover.assert_satisfied(); -} diff --git a/pkg/zk-circuits/src/utxo/utxo.rs b/pkg/zk-circuits/src/utxo/utxo.rs deleted file mode 100644 index f2ec554..0000000 --- a/pkg/zk-circuits/src/utxo/utxo.rs +++ /dev/null @@ -1,361 +0,0 @@ -use std::array; - -use crate::{ - chips::{ - add::AddCulmChip, aggregation::snark::Snark, - binary_decomposition::BinaryDecompositionConfig, is_constant::IsConstantChip, - poseidon::PoseidonConfig, swap::CondSwapChip, - }, - constants::{UTXO_INPUTS, UTXO_OUTPUTS}, - data::{InputNote, Note, ParameterSet, Utxo, UtxoKind}, - params::load_params, - proof::Proof, - util::{assign_constant, assign_private_input, keygen_from_params}, - CircuitKind, -}; -use halo2_base::halo2_proofs::{ - circuit::{Layouter, Value}, - halo2curves::bn256::{Bn256, Fr, G1Affine}, - plonk::{Advice, Column, Error, Instance, ProvingKey, VerifyingKey}, - poly::kzg::commitment::ParamsKZG, -}; -use rand::RngCore; -use zk_primitives::Element; - -impl UtxoKind { - pub(crate) fn as_element(&self) -> Fr { - match self { - UtxoKind::Null => Fr::from(0u64), - UtxoKind::Transfer => Fr::from(1u64), - UtxoKind::Mint => Fr::from(2u64), - UtxoKind::Burn => Fr::from(3u64), - } - } -} - -impl Utxo { - pub fn new( - inputs: [InputNote; UTXO_INPUTS], - outputs: [Note; UTXO_OUTPUTS], - root: Element, - kind: UtxoKind, - ) -> Self { - Utxo { - inputs, - outputs, - root, - kind, - } - } - - pub fn new_transfer( - inputs: [InputNote; UTXO_INPUTS], - outputs: [Note; UTXO_OUTPUTS], - root: Element, - ) -> Self { - Utxo::new(inputs, outputs, root, UtxoKind::Transfer) - } - - // TODO: do we need root here? Surely its just a padding element - pub fn new_mint(output_note: Note) -> Self { - let inputs = array::from_fn(|_| InputNote::padding_note()); - let outputs = [output_note, Note::padding_note()]; - Utxo::new(inputs, outputs, Element::ZERO, UtxoKind::Mint) - } - - pub fn new_burn(input_note: InputNote, root: Element) -> Self { - let inputs = [input_note, InputNote::padding_note()]; - let outputs = array::from_fn(|_| Note::padding_note()); - Utxo::new(inputs, outputs, root, UtxoKind::Burn) - } - - pub fn new_padding() -> Self { - let inputs: [InputNote; 2] = array::from_fn(|_| InputNote::padding_note()); - let outputs = array::from_fn(|_| Note::padding_note()); - Utxo::new(inputs, outputs, Element::ZERO, UtxoKind::Transfer) - } - - #[allow(clippy::too_many_arguments)] - pub fn enforce_constraints( - &self, - mut layouter: impl Layouter, - instance: Column, - advice: Column, - poseidon_config: PoseidonConfig, - add_chip: AddCulmChip, - swap_chip: CondSwapChip, - padding_constant_chip: IsConstantChip, - is_mint_chip: IsConstantChip, - is_burn_chip: IsConstantChip, - decompose: BinaryDecompositionConfig, - ) -> Result<(), Error> { - // Total value - let mut in_value = vec![]; - let mut out_value = vec![]; - - // A set of hashes that we need to verify against public inputs - let mut input_hashes = vec![]; - let mut output_hashes = vec![]; - - // Root of the merkle tree for each input, should all be the same root - let mut roots = vec![]; - - // Witness the root of the merkle tree (in case we need to ignore the merkle tree check) - let unverified_root = assign_private_input( - || "unverified root witness", - layouter.namespace(|| "unverified root witness"), - advice, - Value::known(self.root()), - )?; - - let zero = assign_constant( - || "unverified padding witness", - layouter.namespace(|| "unverified root witness"), - advice, - Fr::zero(), - )?; - - // Witness the kind of utxo txn - let utxo_kind = assign_private_input( - || "utxo kind witness", - layouter.namespace(|| "utxo kind witness"), - advice, - Value::known(self.kind.as_element()), - )?; - - // Is mint - let is_mint = is_mint_chip.assign(layouter.namespace(|| "is mint"), utxo_kind.clone())?; - - // Is burn - let is_burn = is_burn_chip.assign(layouter.namespace(|| "is burn"), utxo_kind)?; - - for input_note in &self.inputs { - let cells = input_note.enforce_constraints( - layouter.namespace(|| "input note"), - advice, - poseidon_config.clone(), - swap_chip.clone(), - padding_constant_chip.clone(), - )?; - - // Swap the merkle tree root if the note is padding, we're essentially using Swap - // as a ternary operator here, so the merkle tree root will be the same if the note - // is not padding, and if it is padding, the merkle tree root will be the unverified - // in this case we don't care as this is just padding record with 0 value - let (root, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap padded root?"), - (&cells.root, &unverified_root), - &cells.commitment.is_padding, - )?; - - // Change the nullifier to the default padding nullifier if input note is padding, we - // want to use the same padding commitment value for easier detection upstream of padding - // notes - let (nullifier, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap padded root?"), - (&cells.nullifier, &zero), - &cells.commitment.is_padding, - )?; - - roots.push(root); - input_hashes.push(nullifier); - in_value.push(cells.commitment.value); - } - - for output_note in &self.outputs { - let cells = output_note.enforce_constraints( - layouter.namespace(|| "output_note"), - advice, - poseidon_config.clone(), - padding_constant_chip.clone(), - swap_chip.clone(), - )?; - let value = cells.value; - - output_hashes.push(cells.cm); - out_value.push(value.clone()); - - // Verify that out_value is MAX 2^240 - // Binary decomposition using RunningSum is a vec of AssignedCells containing the bits - let decomposed_bits = layouter.assign_region( - || "decompose", - |mut region| { - // We use non-struct because the merkle tree is not as big as the hash (i.e. we're only - // interested in the last n bits) - decompose.copy_decompose(&mut region, 0, value.clone(), 256, 256) - }, - )?; - - layouter.assign_region( - || "2^240 value range check", - |mut region| { - // Constrain the value to be less than 2^240 - for bit in decomposed_bits.iter().rev().take(256 - 240) { - region.constrain_constant(bit.cell(), Fr::zero())?; - } - Ok(()) - }, - )?; - } - - let hashes = input_hashes - .iter() - .chain(output_hashes.iter()) - .collect::>(); - - let total_in = add_chip.assign(layouter.namespace(|| "total in"), in_value.as_slice())?; - - let total_out = - add_chip.assign(layouter.namespace(|| "total out"), out_value.as_slice())?; - - // Set mint/burn hash if minting - let (mb_hash, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap hash to mint hash?"), - (&zero, &output_hashes[0]), - &is_mint, - )?; - - // Set mint/burn hash if burning - let (mb_hash, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap value to burn value?"), - (&mb_hash, &input_hashes[0]), - &is_burn, - )?; - - // Set mint/burn value if minting - let (value, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap value to mint value?"), - (&zero, &total_out), - &is_mint, - )?; - - // Set mint/burn value if burning - let (value, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap value to burn value?"), - (&value, &total_in), - &is_burn, - )?; - - // Swap total_out if minting - let (total_out, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap total_in to mint value?"), - (&total_out, &zero), - &is_mint, - )?; - - // Swap total_in if burning - let (total_in, _) = swap_chip.swap_assigned( - layouter.namespace(|| "swap total_in to burn value?"), - (&total_in, &zero), - &is_burn, - )?; - - // Check value total_in == total_out! - layouter.assign_region( - || "constrain total_in == total_out", - |mut region| region.constrain_equal(total_in.cell(), total_out.cell()), - )?; - - // Check roots are valid - for hash in roots.iter() { - layouter.constrain_instance(hash.cell(), instance, 0)?; - } - - // Constrain kind to public input, so we know what rules have been applied - // TODO: do we need this, can we just check if value has an output, meaning it is a mint/burn - layouter.constrain_instance(mb_hash.cell(), instance, 1)?; - - // Constrain value to public input (value will be non-zero if minting or burning) - layouter.constrain_instance(value.cell(), instance, 2)?; - - // Verify hashes aginst inputs - for (i, hash) in hashes.iter().enumerate() { - layouter.constrain_instance(hash.cell(), instance, i + 3)?; - } - - Ok(()) - } - - /// Public inputs to be used in proof, public inputs need to have a determinsitc ordering - /// so we can constrain them correctly - ordering is: - /// - input.merkle_root x inputs - /// - input.nullifier x inputs - /// - output.commitment x outputs - pub fn public_inputs(&self) -> Vec { - let mut hashes = vec![]; - - // Push the root of the merkle tree as a witness - hashes.push(self.root()); - - // Push the input/output hash, used for mint/burn only - hashes.push(match self.kind { - UtxoKind::Mint => self.outputs[0].commitment().into(), - UtxoKind::Burn => self.inputs[0].nullifer().into(), - _ => Fr::zero(), - }); - - // Output value (only when minting/burning) - hashes.push(match self.kind { - UtxoKind::Mint => self.outputs[0].value().into(), - UtxoKind::Burn => self.inputs[0].value().into(), - _ => Fr::zero(), - }); - - // input notes use the same merkle root - for input_note in &self.inputs { - hashes.push(input_note.nullifer().into()) - } - - for output_note in &self.outputs { - hashes.push(output_note.commitment().into()) - } - - hashes - } - - pub fn root(&self) -> Fr { - self.root.into() - } - - pub fn leafs(&self) -> Vec { - let mut hashes = vec![]; - - for input_note in &self.inputs { - hashes.push(input_note.nullifer().into()) - } - - for output_note in &self.outputs { - hashes.push(output_note.commitment().into()) - } - - hashes - } - - pub fn prove( - &self, - params: &ParamsKZG, - pk: &ProvingKey, - rng: impl RngCore, - ) -> Result { - let circuit = Self::default(); - let instance = self.public_inputs(); - let instances = &[instance.as_slice()]; - Proof::create(params, pk, circuit, instances, rng) - } - - pub fn snark(&self, kind: CircuitKind) -> Result { - let (pk, _) = self.keygen(kind.params()); - - Snark::create( - self.clone(), - vec![self.public_inputs()], - load_params(kind.params()), - &pk, - ) - .map_err(crate::Error::err) - } - - pub fn keygen(&self, params: ParameterSet) -> (ProvingKey, VerifyingKey) { - keygen_from_params(params, self) - } -} diff --git a/pkg/zk-circuits/src/verify.rs b/pkg/zk-circuits/src/verify.rs new file mode 100644 index 0000000..b065f44 --- /dev/null +++ b/pkg/zk-circuits/src/verify.rs @@ -0,0 +1,20 @@ +use crate::{BbBackend, Result}; +use element::Base; + +pub async fn verify( + bb_backend: &dyn BbBackend, + key: &[u8], + proof: &[u8], + public_inputs: &[u8], + oracle_hash_keccak: bool, +) -> Result<()> { + bb_backend + .verify(proof, public_inputs, key, oracle_hash_keccak) + .await +} + +#[derive(Debug, Clone)] +pub struct VerificationKeyHash(pub Base); + +#[derive(Debug, Clone)] +pub struct VerificationKey(pub Vec); diff --git a/pkg/zk-primitives/Cargo.toml b/pkg/zk-primitives/Cargo.toml index 64cb3b6..be0797f 100644 --- a/pkg/zk-primitives/Cargo.toml +++ b/pkg/zk-primitives/Cargo.toml @@ -1,28 +1,27 @@ [package] name = "zk-primitives" version = "1.3.0" -edition = "2021" +edition = "2024" [dependencies] -bitvec = { workspace = true } -diesel = { workspace = true, optional = true, features = ["postgres", "r2d2"] } +primitives = { workspace = true } +element = { workspace = true } +hash = { workspace = true } +parse-link = { workspace = true } + +borsh = { workspace = true } ethnum = { workspace = true } -ff = { workspace = true } hex = { workspace = true } -poseidon-circuit = { workspace = true } -proptest = { workspace = true, optional = true } -rand = { workspace = true, optional = true } -serde = { workspace = true, optional = true, features = ["derive"] } -borsh = { workspace = true, optional = true } +noirc_abi = { workspace = true } +rand = { workspace = true } +serde = { workspace = true, features = ["derive"] } +sha3 = { workspace = true } +web3 = { workspace = true } +workspace-hack.workspace = true -[dev-dependencies] -proptest = { workspace = true } -test-strategy = { workspace = true } -serde_json = { workspace = true } -insta = { workspace = true } -rand_chacha = { workspace = true } -rand_xorshift = { workspace = true } +[dependencies.ts-rs] +workspace = true +optional = true [features] -default = ["serde", "rand", "borsh"] -test-api = [] +ts-rs = ["dep:ts-rs", "element/ts-rs", "primitives/ts-rs"] diff --git a/pkg/zk-primitives/README.md b/pkg/zk-primitives/README.md new file mode 100644 index 0000000..bb982ad --- /dev/null +++ b/pkg/zk-primitives/README.md @@ -0,0 +1,16 @@ +# ZK Primitives + +Core zero-knowledge primitives - these provide a common interface for the ZK circuits inputs/outputs, so the circuit backend is abstracted. + +## Overview + +This package provides the fundamental zero-knowledge cryptographic primitives. + +## Features + +- UTXO proof circuits +- Digital signature verification +- Merkle path operations +- Note management +- Address utilities +- Aggregation circuits diff --git a/pkg/zk-primitives/src/address.rs b/pkg/zk-primitives/src/address.rs new file mode 100644 index 0000000..2737412 --- /dev/null +++ b/pkg/zk-primitives/src/address.rs @@ -0,0 +1,16 @@ +use element::Element; + +/// Get the address from a private key +/// +/// # Arguments +/// +/// * `private_key` - The private key to get the address from. +/// +/// # Returns +/// +/// The address derived from the private key. +#[must_use] +#[inline] +pub fn get_address_for_private_key(private_key: Element) -> Element { + hash::hash_merge([private_key, Element::ZERO]) +} diff --git a/pkg/zk-primitives/src/agg_agg.rs b/pkg/zk-primitives/src/agg_agg.rs new file mode 100644 index 0000000..1c6d973 --- /dev/null +++ b/pkg/zk-primitives/src/agg_agg.rs @@ -0,0 +1,336 @@ +// lint-long-file-override allow-max-lines=400 +use crate::{AggUtxoProof, ProofBytes, ToBytes}; +use borsh::{BorshDeserialize, BorshSerialize}; +use element::Element; +use hash::hash_merge; +use serde::{Deserialize, Serialize}; + +/// Enum representing a proof that can be either an AggUtxo or AggAgg proof +/// This enables composable aggregation where AggAgg can aggregate AggAgg proofs +#[derive(Debug, Clone)] +pub enum AggProof { + /// An aggregated UTXO proof + AggUtxo(Box), + /// An aggregated AggAgg proof (recursive aggregation) + AggAgg(Box), +} + +impl AggProof { + /// Get the old root of the proof + #[must_use] + pub fn old_root(&self) -> Element { + match self { + AggProof::AggUtxo(proof) => proof.public_inputs.old_root, + AggProof::AggAgg(proof) => proof.public_inputs.old_root, + } + } + + /// Get the new root of the proof + #[must_use] + pub fn new_root(&self) -> Element { + match self { + AggProof::AggUtxo(proof) => proof.public_inputs.new_root, + AggProof::AggAgg(proof) => proof.public_inputs.new_root, + } + } + + /// Get the commit hash of the proof + #[must_use] + pub fn commit_hash(&self) -> Element { + match self { + AggProof::AggUtxo(proof) => proof.public_inputs.commit_hash, + AggProof::AggAgg(proof) => proof.public_inputs.commit_hash, + } + } + + /// Get the messages from the proof + #[must_use] + pub fn messages(&self) -> &[Element; 1000] { + match self { + AggProof::AggUtxo(proof) => &proof.public_inputs.messages, + AggProof::AggAgg(proof) => &proof.public_inputs.messages, + } + } + + /// Check if this is a padding proof + #[must_use] + pub fn is_padding(&self) -> bool { + match self { + AggProof::AggUtxo(proof) => proof.public_inputs.is_padding(), + AggProof::AggAgg(proof) => proof.public_inputs.old_root == Element::ZERO, + } + } + + /// Get the proof bytes + #[must_use] + pub fn proof_bytes(&self) -> &[u8] { + match self { + AggProof::AggUtxo(proof) => &proof.proof.0, + AggProof::AggAgg(proof) => &proof.proof.0, + } + } + + /// Get the verification key hash + #[must_use] + pub fn verification_key_hash(&self) -> &[Element; 2] { + match self { + AggProof::AggUtxo(proof) => &proof.public_inputs.verification_key_hash, + AggProof::AggAgg(proof) => &proof.public_inputs.verification_key_hash, + } + } +} + +/// The data required to prove an AggAgg transaction, this aggregates multiple AggUtxo or AggAgg +/// proofs into a single proof. Expects each new_root from the previous proof to be the same as the +/// old_root of the next proof. This enables composable/recursive aggregation. +#[derive(Debug, Clone)] +pub struct AggAgg { + /// The proofs for the AggAgg transaction (can be AggUtxo or AggAgg proofs) + pub proofs: [AggProof; 2], +} + +impl AggAgg { + /// Create a new AggAgg + #[must_use] + pub fn new(proofs: [AggProof; 2]) -> Self { + Self { proofs } + } + + /// Get the old root of the AggAgg transaction + #[must_use] + pub fn old_root(&self) -> Element { + self.proofs[0].old_root() + } + + /// Get the new root of the AggAgg transaction + #[must_use] + pub fn new_root(&self) -> Element { + if self.proofs[1].is_padding() { + self.proofs[0].new_root() + } else { + self.proofs[1].new_root() + } + } + + /// Helper function to iterate through messages from proofs + fn iterate_messages(&self, mut callback: F) + where + F: FnMut(Element), + { + for proof in &self.proofs { + // Exportable message kinds (2, 3 and 4) consume the next x messages, so when checking + // for the end we skip the consumed messages, so we can find the first non-exportable kind. + // Assumes that agg_utxo proof also compacts exportable kinds from index 0 (without gaps). + let mut next_check = 0; + + for (j, &proof_message) in proof.messages().iter().enumerate() { + // Update next checkpoint (or end) + if next_check == j { + match proof_message { + element if element == Element::from(2u64) => { + // Mint + next_check += 4; + } + element + if element == Element::from(3u64) || element == Element::from(4u64) => + { + // Burn, Swap + next_check += 5; + } + _ => break, + } + } + + callback(proof_message); + } + } + } + + /// Get the count of messages from the proofs + #[must_use] + pub fn messages_count(&self) -> usize { + let mut messages_count = 0; + + self.iterate_messages(|_| { + messages_count += 1; + }); + + messages_count + } + + /// Get the messages from the proofs with compaction (trailing zeros) + #[must_use] + #[allow(clippy::large_stack_arrays)] + pub fn messages(&self) -> [Element; 1000] { + let mut messages = [Element::ZERO; 1000]; + let mut messages_index = 0; + + self.iterate_messages(|proof_message| { + messages[messages_index] = proof_message; + messages_index += 1; + }); + + messages + } + + /// Get the public inputs for the AggAgg circuit + #[must_use] + pub fn public_inputs(&self) -> AggAggPublicInput { + AggAggPublicInput { + verification_key_hash: *self.proofs[0].verification_key_hash(), + old_root: self.old_root(), + new_root: self.new_root(), + commit_hash: self.commit_hash(), + messages: self.messages(), + } + } + + /// Commit hash of the agg_agg (will be posted onchain and verified by Celestia) + #[must_use] + pub fn commit_hash(&self) -> Element { + hash_merge([self.proofs[0].commit_hash(), self.proofs[1].commit_hash()]) + } +} + +/// The public input for a AggAgg transaction +#[derive(Debug, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +pub struct AggAggPublicInput { + /// Verification key hashes for allowed proof types (AggUtxo and AggAgg) + pub verification_key_hash: [Element; 2], + /// The old root of the tree + pub old_root: Element, + /// The new root of the tree + pub new_root: Element, + /// Commit hash + pub commit_hash: Element, + /// The messages of the transactions (compacted with trailing zeros) + #[serde(with = "serde_message_array")] + #[borsh( + serialize_with = "serialize_message_array_borsh", + deserialize_with = "deserialize_message_array_borsh" + )] + pub messages: [Element; 1000], +} + +impl Default for AggAggPublicInput { + #[allow(clippy::large_stack_arrays)] + fn default() -> Self { + Self { + verification_key_hash: [Element::ZERO; 2], + old_root: Element::ZERO, + new_root: Element::ZERO, + commit_hash: Element::ZERO, + messages: [Element::ZERO; 1000], + } + } +} + +mod serde_message_array { + use element::Element; + use serde::ser::SerializeSeq; + use serde::{Deserialize, Deserializer, Serializer}; + + pub fn serialize(messages: &[Element; 1000], serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(1000))?; + for element in messages { + seq.serialize_element(element)?; + } + seq.end() + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result<[Element; 1000], D::Error> + where + D: Deserializer<'de>, + { + let vec: Vec = Vec::deserialize(deserializer)?; + vec.try_into() + .map_err(|_| serde::de::Error::custom("expected 1000 elements")) + } +} + +fn serialize_message_array_borsh( + messages: &[Element; 1000], + writer: &mut impl std::io::Write, +) -> std::io::Result<()> { + // Write length prefix for Vec compatibility + (1000u32) + .to_le_bytes() + .iter() + .try_for_each(|b| writer.write_all(&[*b]))?; + // Write each element + for msg in messages { + borsh::BorshSerialize::serialize(msg, writer)?; + } + Ok(()) +} + +#[allow(clippy::large_stack_arrays)] +fn deserialize_message_array_borsh( + reader: &mut impl std::io::Read, +) -> std::io::Result<[Element; 1000]> { + // Read length prefix + let mut len_bytes = [0u8; 4]; + reader.read_exact(&mut len_bytes)?; + let len = u32::from_le_bytes(len_bytes); + if len != 1000 { + return Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "expected 1000 elements", + )); + } + // Read elements + let mut messages = [Element::ZERO; 1000]; + for msg in &mut messages { + *msg = borsh::BorshDeserialize::deserialize_reader(reader)?; + } + Ok(messages) +} + +impl AggAggPublicInput { + /// Convert the AggAggPublicInput to a AggAggPublicInputBytes + #[must_use] + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::with_capacity(32 * (2 + 1 + 1 + 1 + 1000)); + + bytes.extend(self.verification_key_hash[0].to_be_bytes()); + bytes.extend(self.verification_key_hash[1].to_be_bytes()); + bytes.extend(self.old_root.to_be_bytes()); + bytes.extend(self.new_root.to_be_bytes()); + bytes.extend(self.commit_hash.to_be_bytes()); + + for message in &self.messages { + bytes.extend(message.to_be_bytes()); + } + + bytes + } +} + +/// The output proof for a AggAgg transaction +#[derive(Debug, Default, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +pub struct AggAggProof { + /// The proof for the AggAgg transaction + pub proof: ProofBytes, + /// The public input for the AggAgg transaction + pub public_inputs: AggAggPublicInput, + /// KZG accumulator inputs + pub kzg: Vec, +} + +impl ToBytes for AggAggProof { + /// Convert the AggAggProof to a ProofBytes + fn to_bytes(&self) -> Vec { + // TODO: move to impl detail of proving backend + let pi = self.public_inputs.to_bytes(); + let kzg = self + .kzg + .iter() + .flat_map(|e| e.to_be_bytes()) + .collect::>(); + let proof = &self.proof.0; + [pi.as_slice(), kzg.as_slice(), proof.as_slice()].concat() + } +} diff --git a/pkg/zk-primitives/src/agg_final.rs b/pkg/zk-primitives/src/agg_final.rs new file mode 100644 index 0000000..6123527 --- /dev/null +++ b/pkg/zk-primitives/src/agg_final.rs @@ -0,0 +1,112 @@ +use crate::{AggAggProof, OracleProofBytes, ToBytes}; +use borsh::{BorshDeserialize, BorshSerialize}; +use element::Element; +use serde::{Deserialize, Serialize}; + +/// The data required to prove an AggFinal transaction, this takes a single AggAgg proof +/// and produces a final proof suitable for submission to the smart contract. +#[derive(Debug, Clone)] +pub struct AggFinal { + /// The proof for the AggFinal transaction + pub proof: AggAggProof, +} + +impl AggFinal { + /// Create a new AggFinal + #[must_use] + pub fn new(proof: AggAggProof) -> Self { + Self { proof } + } + + /// Get the old root of the AggFinal transaction + #[must_use] + pub fn old_root(&self) -> Element { + self.proof.public_inputs.old_root + } + + /// Get the new root of the AggFinal transaction + #[must_use] + pub fn new_root(&self) -> Element { + self.proof.public_inputs.new_root + } + + /// Get the messages from the proof + #[must_use] + pub fn messages(&self) -> Vec { + self.proof.public_inputs.messages.to_vec() + } + + /// Get the commit hash from the proof + #[must_use] + pub fn commit_hash(&self) -> Element { + self.proof.public_inputs.commit_hash + } + + /// Get the public inputs for the AggFinal circuit + #[must_use] + pub fn public_inputs(&self) -> AggFinalPublicInput { + AggFinalPublicInput { + old_root: self.old_root(), + new_root: self.new_root(), + commit_hash: self.commit_hash(), + messages: self.messages(), + } + } +} + +/// The public input for a AggFinal transaction +#[derive(Default, Debug, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +pub struct AggFinalPublicInput { + /// The old root of the tree + pub old_root: Element, + /// The new root of the tree + pub new_root: Element, + /// Commit hash + pub commit_hash: Element, + /// The messages of the transactions + pub messages: Vec, +} + +impl AggFinalPublicInput { + /// Convert the AggFinalPublicInput to bytes + #[must_use] + pub fn to_bytes(&self) -> Vec { + let mut bytes = Vec::with_capacity(32 * (1 + 1 + 1 + self.messages.len())); + + bytes.extend(self.old_root.to_be_bytes()); + bytes.extend(self.new_root.to_be_bytes()); + bytes.extend(self.commit_hash.to_be_bytes()); + + for message in &self.messages { + bytes.extend(message.to_be_bytes()); + } + + bytes + } +} + +/// The output proof for a AggFinal transaction +#[derive(Debug, Default, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +pub struct AggFinalProof { + /// The proof for the AggFinal transaction + pub proof: OracleProofBytes, + /// The public input for the AggFinal transaction + pub public_inputs: AggFinalPublicInput, + /// KZG accumulator inputs + pub kzg: Vec, +} + +impl ToBytes for AggFinalProof { + /// Convert the AggFinalProof to bytes + fn to_bytes(&self) -> Vec { + // TODO: move to impl detail of proving backend + let pi = self.public_inputs.to_bytes(); + let kzg = self + .kzg + .iter() + .flat_map(|e| e.to_be_bytes()) + .collect::>(); + let proof = &self.proof.0; + [pi.as_slice(), kzg.as_slice(), proof.as_slice()].concat() + } +} diff --git a/pkg/zk-primitives/src/agg_utxo.rs b/pkg/zk-primitives/src/agg_utxo.rs new file mode 100644 index 0000000..b2916f3 --- /dev/null +++ b/pkg/zk-primitives/src/agg_utxo.rs @@ -0,0 +1,165 @@ +// lint-long-file-override allow-max-lines=300 +use crate::{MerklePath, UtxoProof}; +use crate::{ProofBytes, UtxoKind, impl_serde_for_element_array}; +use element::{Base, Element}; +use hash::hash_merge; + +/// The data required to prove an AggUtxo transaction, this aggregates multiple Utxo proofs into +/// a single proof. It also validates that the input notes are removed from the tree and the output +/// notes are added to the tree. +#[derive(Debug, Clone)] +pub struct AggUtxo { + /// The proofs for the AggUtxo transaction + pub proofs: [UtxoProofBundleWithMerkleProofs; 3], + /// The old root of the tree (must match the first merkle proof) + pub old_root: Element, + /// The new root of the tree (must match the last merkle proof) + pub new_root: Element, +} + +impl AggUtxo { + /// Create a new AggUtxo + #[must_use] + pub fn new( + proofs: [UtxoProofBundleWithMerkleProofs; 3], + old_root: Element, + new_root: Element, + ) -> Self { + Self { + proofs, + old_root, + new_root, + } + } + + /// Commit hash for utxo_agg + #[must_use] + pub fn commit_hash(&self) -> Element { + hash_merge([ + self.proofs[0].utxo_proof.public_inputs.commit_hash(), + self.proofs[1].utxo_proof.public_inputs.commit_hash(), + self.proofs[2].utxo_proof.public_inputs.commit_hash(), + ]) + } + + /// Get messages with compaction (trailing zeros after last exportable message) + #[must_use] + #[allow(clippy::large_stack_arrays)] + pub fn messages(&self) -> [Element; 1000] { + let mut messages = [Element::ZERO; 1000]; + let mut index = 0; + + for proof in &self.proofs { + let proof_messages = match proof.utxo_proof.kind() { + UtxoKind::Null | UtxoKind::Send => &[][..], + UtxoKind::Mint => &proof.utxo_proof.public_inputs.messages[..4], + UtxoKind::Burn => &proof.utxo_proof.public_inputs.messages[..], + }; + + for &message in proof_messages { + messages[index] = message; + index += 1; + } + } + + // Remaining elements are already zero (trailing zeros after compaction) + messages + } +} + +/// A Utxo proof bundle with merkle proofs +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct UtxoProofBundleWithMerkleProofs { + /// The proof for the Utxo + pub utxo_proof: UtxoProof, + /// The merkle path proofs for removing input notes + pub input_merkle_paths: [MerklePath<161>; 2], + /// The merkle path proofs for adding output notes + pub output_merkle_paths: [MerklePath<161>; 2], +} + +impl UtxoProofBundleWithMerkleProofs { + /// Create a new UtxoProofBundleWithMerkleProofs + #[must_use] + pub fn new(utxo_proof: UtxoProof, merkle_paths: &[MerklePath<161>; 4]) -> Self { + Self { + utxo_proof, + input_merkle_paths: [merkle_paths[0].clone(), merkle_paths[1].clone()], + output_merkle_paths: [merkle_paths[2].clone(), merkle_paths[3].clone()], + } + } +} + +impl Default for UtxoProofBundleWithMerkleProofs { + /// Create a padding UtxoProofBundleWithMerkleProofs + fn default() -> UtxoProofBundleWithMerkleProofs { + let merkle_path = MerklePath::default(); + Self { + utxo_proof: UtxoProof::default(), + input_merkle_paths: [merkle_path.clone(), merkle_path.clone()], + output_merkle_paths: [merkle_path.clone(), merkle_path.clone()], + } + } +} + +/// The proof for a Utxo transaction +#[derive(Debug, Clone)] +pub struct AggUtxoProofFields(pub [Element; 93]); +impl_serde_for_element_array!(AggUtxoProofFields, 93); + +impl From<[Base; 93]> for AggUtxoProofFields { + fn from(elements: [Base; 93]) -> Self { + AggUtxoProofFields(elements.map(Element::from_base)) + } +} + +impl From<&AggUtxoProofFields> for [Base; 93] { + fn from(value: &AggUtxoProofFields) -> Self { + value.0.map(|e| e.to_base()) + } +} + +/// The public input for a AggUtxo transaction +#[derive(Debug, Clone)] +pub struct AggUtxoPublicInput { + /// Verification key hashes for allowed proof types + pub verification_key_hash: [Element; 2], + /// The old root of the tree + pub old_root: Element, + /// The new root of the tree + pub new_root: Element, + /// Commit hash + pub commit_hash: Element, + /// The messages of the transactions (compacted with trailing zeros) + pub messages: [Element; 1000], +} + +impl Default for AggUtxoPublicInput { + #[allow(clippy::large_stack_arrays)] + fn default() -> Self { + Self { + verification_key_hash: [Element::ZERO; 2], + old_root: Element::ZERO, + new_root: Element::ZERO, + commit_hash: Element::ZERO, + messages: [Element::ZERO; 1000], + } + } +} + +impl AggUtxoPublicInput { + /// Check if this is a padding proof (if old_root is zero element) + #[must_use] + pub fn is_padding(&self) -> bool { + self.old_root == Element::ZERO + } +} + +/// The output proof for a AggUtxo transaction +#[derive(Default, Debug, Clone)] +pub struct AggUtxoProof { + /// The proof for the AggUtxo transaction + pub proof: ProofBytes, + /// The public input for the AggUtxo transaction + pub public_inputs: AggUtxoPublicInput, +} diff --git a/pkg/zk-primitives/src/burn.rs b/pkg/zk-primitives/src/burn.rs new file mode 100644 index 0000000..8ae8041 --- /dev/null +++ b/pkg/zk-primitives/src/burn.rs @@ -0,0 +1,30 @@ +use crate::Note; +use element::Element; + +/// Burn is a struct that contains the data required to burn a note +/// +/// This is used to burn notes in the zk-rollup +#[derive(Clone, Debug)] +pub struct Burn { + /// Secret key for the address, required to spend a note + pub secret_key: Element, + /// The notes to burn + pub notes: [Note; L], + /// The EVM address to send the burnt notes to + pub to_address: Element, +} + +// https://github.com/rust-lang/rust/issues/61415 +impl Default for Burn { + fn default() -> Self { + Self { + secret_key: Element::default(), + notes: core::array::from_fn(|_| Note::default()), + to_address: Element::default(), + } + } +} + +// 2025-05-06T12:10:29.022792Z INFO node::node::proposal: Committing transaction hash="0x1d527d5fe86464963c5b9439a49e21f5acfd082993df856d9ef898e7919c2b0b" kind=Burn mint_burn_hash=Some(b35547856eecc13f73cb61acc76836b991b91e10372c8dc6e3733bcba92e359) value=1 messages=["0x3", "0x1", "0x989680", "0xb35547856eecc13f73cb61acc76836b991b91e10372c8dc6e3733bcba92e359", "0x8a147ec8b96015e30f732d41f6366b2d72bcff534aae9cb5785b54f5d9f4dc5", "0x0"] input_leaves=["0x239977083fe42eea41ca1dd9831ce022d35ae848a797de1be48a0ef325abb877", "0x0"] output_leaves=["0x0", "0x0"] + +// 2025-05-06T12:31:30.465683Z INFO node::node::proposal: Committing transaction hash="0x2eaaab98a5725b4fe40de234e32eaf079f2206fabedbe54cdae30be74c65c885" kind=Burn mint_burn_hash=Some(2358b58d7d1ed86d3dcb0a409040f20a6daebdca831a4d23c5986e3ae327d07f) value=1 messages=["0x3", "0x1", "0x989680", "0x2358b58d7d1ed86d3dcb0a409040f20a6daebdca831a4d23c5986e3ae327d07f", "0xfbe2f48855f751c01087e52eb4717d1d195bc48c", "0x0"] input_leaves=["0x149f0e7c916ab6863416a1549aa587c7500b3cf3ca220e56e21d96ff64901a63", "0x0"] output_leaves=["0x0", "0x0"] diff --git a/pkg/zk-primitives/src/element/convert.rs b/pkg/zk-primitives/src/element/convert.rs deleted file mode 100644 index ec6a3f3..0000000 --- a/pkg/zk-primitives/src/element/convert.rs +++ /dev/null @@ -1,189 +0,0 @@ -use crate::Element; -use bitvec::{array::BitArray, order::Msb0}; -use core::num::TryFromIntError; -use ethnum::U256; -use std::str::FromStr; - -macro_rules! from_int_impls { - ($t:ty) => { - impl From<$t> for Element { - #[inline] - fn from(value: $t) -> Self { - Element(U256::from(value)) - } - } - - impl TryFrom for $t { - type Error = TryFromIntError; - - #[inline] - fn try_from(value: Element) -> Result { - <$t>::try_from(value.0) - } - } - }; -} - -from_int_impls!(u8); -from_int_impls!(u16); -from_int_impls!(u32); -from_int_impls!(u64); -from_int_impls!(u128); - -impl From for Element { - #[inline] - fn from(value: bool) -> Self { - match value { - false => Self::ZERO, - true => Self::ONE, - } - } -} - -impl FromStr for Element { - type Err = ::Err; - - #[inline] - fn from_str(s: &str) -> Result { - let s = s.strip_prefix("0x").unwrap_or(s); - Ok(Self(U256::from_str_radix(s, 16)?)) - } -} - -impl From for Element { - fn from(value: U256) -> Self { - Self(value) - } -} - -impl From for U256 { - fn from(value: Element) -> Self { - value.0 - } -} - -impl Element { - /// Convert the [`Element`] to its bytes in big-endian format - /// - /// ```rust - /// # use zk_primitives::*; - /// let element = Element::ZERO; - /// assert_eq!(element.to_be_bytes(), [0; 32]); - /// - /// let element = Element::ONE; - /// assert_eq!(element.to_be_bytes(), { - /// let mut temp = [0; 32]; - /// temp[31] = 1; - /// temp - /// }); - /// ``` - #[inline] - #[must_use] - pub fn to_be_bytes(self) -> [u8; 32] { - self.0.to_be_bytes() - } - - /// Convert the [`Element`] to its bits in big-endian format - /// - /// ```rust - /// # use zk_primitives::*; - /// let element = Element::ZERO; - /// let bits = element.to_be_bits(); - /// - /// ``` - #[inline] - #[must_use] - pub fn to_be_bits(self) -> BitArray<[u8; 32], Msb0> { - let bits = self.0.to_be_bytes(); - BitArray::new(bits) - } - - /// Convert the [`Element`] to its bytes in little-endian format - /// - /// ```rust - /// # use zk_primitives::*; - /// let element = Element::ZERO; - /// assert_eq!(element.to_le_bytes(), [0; 32]); - /// - /// let element = Element::ONE; - /// assert_eq!(element.to_le_bytes(), { - /// let mut temp = [0; 32]; - /// temp[0] = 1; - /// temp - /// }); - /// ``` - #[inline] - #[must_use] - pub fn to_le_bytes(self) -> [u8; 32] { - self.0.to_le_bytes() - } - - /// Convert big-endian bytes into an [`Element`] - /// ```rust - /// # use zk_primitives::*; - /// let element = Element::from_be_bytes([0; 32]); - /// assert_eq!(element, Element::ZERO); - /// - /// let element = Element::from_be_bytes({ - /// let mut temp = [0; 32]; - /// temp[31] = 1; - /// temp - /// }); - /// assert_eq!(element, Element::ONE); - /// ``` - #[inline] - #[must_use] - pub fn from_be_bytes(bytes: [u8; 32]) -> Self { - Self(U256::from_be_bytes(bytes)) - } - - /// Convert little-endian bytes into an [`Element`] - /// ```rust - /// # use zk_primitives::*; - /// let element = Element::from_le_bytes([0; 32]); - /// assert_eq!(element, Element::ZERO); - /// - /// let element = Element::from_le_bytes({ - /// let mut temp = [0; 32]; - /// temp[0] = 1; - /// temp - /// }); - /// assert_eq!(element, Element::ONE); - /// ``` - #[inline] - #[must_use] - pub fn from_le_bytes(bytes: [u8; 32]) -> Self { - Self(U256::from_le_bytes(bytes)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_to_be_bits() { - let element = Element::ZERO; - let bits = BitArray::<[u8; 32], Msb0>::new([0u8; 32]); - assert_eq!(element.to_be_bits(), bits); - - let element = Element::ONE; - assert_eq!( - element - .to_be_bits() - .iter() - .rev() - .take(1) - .collect::>(), - vec![true] - ); - } - - #[test] - fn test_from_str() { - assert_eq!(Element::from_str("0").unwrap(), Element::ZERO); - assert_eq!(Element::from_str("0x0").unwrap(), Element::ZERO); - assert_eq!(Element::from_str("0x1").unwrap(), Element::ONE); - assert_eq!(Element::from_str("0xB").unwrap(), Element::from(11u64)); - } -} diff --git a/pkg/zk-primitives/src/element/halo2.rs b/pkg/zk-primitives/src/element/halo2.rs deleted file mode 100644 index 3c7dedd..0000000 --- a/pkg/zk-primitives/src/element/halo2.rs +++ /dev/null @@ -1,124 +0,0 @@ -use ethnum::{uint, U256}; -use ff::PrimeField; - -use crate::{hash_merge, Base, Element}; - -impl Element { - /// The modulus of the underlying prime field - pub const MODULUS: Element = Element(uint!( - "0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001" - )); - - /// Return the result of hash-merging this value with `other` - /// - /// This element is considered to be on the left: - /// ```rust - /// # use zk_primitives::*; - /// let a = Element::new(1); - /// let b = Element::new(2); - /// - /// let ab = a.hashed_with(b); - /// - /// assert_eq!(ab, hash_merge([a, b])); - /// ``` - #[inline] - #[must_use = "this function doesn't modify self"] - pub fn hashed_with(self, other: Element) -> Self { - hash_merge([self, other]) - } - - /// Convert this [`Element`] to its equivalent [`Base`] representation - #[inline] - #[must_use] - pub fn to_base(self) -> Base { - let u8s = self.0.to_le_bytes(); - Base::from_raw(u8s_to_u64(u8s)) - } - - /// Create an [`Element`] from a [`Base`] - #[inline] - #[must_use] - pub fn from_base(base: Base) -> Element { - let u8s = base.to_repr(); - Self(U256::from_le_bytes(u8s)) - } - - /// Reduce this element to its canonical form - /// - /// [`Base`]s are integers modulo "some prime number", and as such have a smaller set of - /// possible values than [`Element`], which is just a 256-bit unsigned integer. - /// - /// This function reduces an element to its canonical form by applying this modulus. - /// - /// Elements in canonical form are guaranteed to be unchanged when converting to/from a [`Base`] - #[inline] - pub fn canonicalize(&mut self) { - self.0 %= Self::MODULUS.0; - } - - /// Whether this [`Element`] is in its canonical form - /// - /// See the docs for [`Element::canonicalize`] for more details on what the canonical form of - /// an [`Element`] is - #[inline] - #[must_use] - pub fn is_canonical(&self) -> bool { - let mut canonical = *self; - canonical.canonicalize(); - self == &canonical - } -} - -impl From for Element { - fn from(value: Base) -> Self { - Element::from_base(value) - } -} - -impl From for Base { - fn from(value: Element) -> Self { - value.to_base() - } -} - -fn u8s_to_u64(u8s: [u8; 32]) -> [u64; 4] { - [ - u64::from_le_bytes((&u8s[0..8]).try_into().unwrap()), - u64::from_le_bytes((&u8s[8..16]).try_into().unwrap()), - u64::from_le_bytes((&u8s[16..24]).try_into().unwrap()), - u64::from_le_bytes((&u8s[24..32]).try_into().unwrap()), - ] -} - -#[cfg(test)] -fn u64s_to_u8s(u64s: [u64; 4]) -> [u8; 32] { - core::array::from_fn(|i| { - let u64 = u64s[i / 8]; - u64.to_le_bytes()[i % 8] - }) -} - -#[cfg(test)] -mod tests { - use test_strategy::proptest; - - use super::*; - - #[proptest] - fn u64_u8_conversion(u64s: [u64; 4]) { - let u8s = u64s_to_u8s(u64s); - let u64s_again = u8s_to_u64(u8s); - - assert_eq!(u64s, u64s_again); - } - - #[proptest] - fn to_from_base_biject(mut element: Element) { - element.canonicalize(); - - let base = element.to_base(); - let element_again = Element::from_base(base); - - assert_eq!(element, element_again); - } -} diff --git a/pkg/zk-primitives/src/element/mod.rs b/pkg/zk-primitives/src/element/mod.rs deleted file mode 100644 index 3578f77..0000000 --- a/pkg/zk-primitives/src/element/mod.rs +++ /dev/null @@ -1,171 +0,0 @@ -use ethnum::U256; - -mod arith; -mod collision; -mod convert; -mod fmt; -mod halo2; -mod lsb; - -#[cfg(feature = "borsh")] -mod borsh_impls; - -#[cfg(feature = "rand")] -mod rand_impls; -#[cfg(feature = "rand")] -pub use rand_impls::Insecure; - -pub use lsb::Lsb; - -#[cfg(feature = "serde")] -mod serde; - -#[cfg(feature = "diesel")] -mod diesel_pg; - -// #[cfg(feature = "diesel")] -// use diesel::sql_types::*; - -/// A 256-bit unsigned integer -/// -/// This type is a wrapper around a [`U256`], so can represent any value in the range `0..=(2^256 - -/// 1)`. -/// However, in a ZK context, it is usually converted to a [`Base`], which is an integer modulo -/// "some large prime". This restricts the set of usable values to something approximating a `u254` -/// -/// [`Base`]: crate::Base -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] -#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(transparent))] -#[cfg_attr( - feature = "diesel", - derive(::diesel::expression::AsExpression, ::diesel::deserialize::FromSqlRow) -)] -#[cfg_attr(feature = "diesel", diesel(sql_type = ::diesel::sql_types::Numeric))] -pub struct Element(#[cfg_attr(feature = "serde", serde(with = "serde"))] pub(crate) U256); - -impl Element { - /// The zero element of the group (the additive identity) - pub const ZERO: Self = Self(U256::ZERO); - - /// The one element of the group (the multiplicative identity) - pub const ONE: Self = Self(U256::ONE); - - /// The largest possible element (note that this is not canonical) - pub const MAX: Self = Self(U256::MAX); - - /// A null hash value (this is identical to [`Element::ZERO`]) - /// - /// Note that this value is chosen arbitrarily - pub const NULL_HASH: Self = Self::ZERO; - - /// The [`Element`] used as the initialization vector when hashing bytes - pub(crate) const BYTE_HASH_IV: Self = Self(U256::new(2)); - - /// Create a new [`Element`] from a u64 - /// - /// This is largely provided to help type inference in simple cases - #[inline] - #[must_use] - pub fn new(i: u64) -> Self { - Self(U256::from(i)) - } - - /// Attempt to convert this [`Element`] to a bool - /// - /// If this value is not 0 or 1, `None` is returned - #[inline] - #[must_use] - pub fn as_bool(self) -> Option { - match self { - Self::ZERO => Some(false), - Self::ONE => Some(true), - _else => None, - } - } - - /// Convert this [`Element`] to a U256 string - #[inline] - #[must_use] - pub fn to_u256(self) -> U256 { - self.0 - } - - /// Convert this [`Element`] to a hex string - #[inline] - #[must_use] - pub fn to_hex(self) -> String { - hex::encode(self.to_be_bytes()) - } - - /// If this element is zero, returns true - #[inline] - #[must_use] - pub fn is_zero(self) -> bool { - self == Self::ZERO - } -} - -macro_rules! partial_eq_impl { - ($int:ty) => { - impl PartialEq<$int> for Element { - fn eq(&self, other: &$int) -> bool { - *self == Element::from(*other) - } - } - }; -} - -partial_eq_impl!(bool); -partial_eq_impl!(u8); -partial_eq_impl!(u16); -partial_eq_impl!(u32); -partial_eq_impl!(u64); -partial_eq_impl!(u128); - -#[cfg(any(test, feature = "proptest"))] -pub mod proptest { - use super::Element; - use ::proptest::{arbitrary::StrategyFor, prelude::*, strategy::Map}; - use ethnum::U256; - - impl Arbitrary for Element { - type Strategy = Map, fn([u8; 32]) -> Self>; - type Parameters = (); - - fn arbitrary_with((): Self::Parameters) -> Self::Strategy { - any::<[u8; 32]>().prop_map(|array| Self(U256::from_be_bytes(array))) - } - } -} - -#[cfg(test)] -mod test { - use super::Element; - - #[test] - fn syntax_test() { - let element = Element::new(123); - - assert_eq!(element + 1u64, Element::new(124)); - assert_eq!(element * 2u64, Element::new(246)); - assert_eq!(element - 2u64, Element::new(121)); - assert_eq!(element + Element::ONE, Element::new(124)); - assert_eq!(element * Element::new(2), Element::new(246)); - assert_eq!(element - Element::new(2), Element::new(121)); - - assert_eq!(Element::new(1).to_string(), "1"); - assert_eq!(Element::new(100).to_string(), "64"); - assert_eq!(Element::new(123).to_string(), "7b"); - - assert_eq!( - (1..=10).map(Element::new).sum::(), - Element::new(55) - ); - - assert_eq!( - (1..=5).map(Element::new).product::(), - Element::new(120) - ); - } -} diff --git a/pkg/zk-primitives/src/element/serde.rs b/pkg/zk-primitives/src/element/serde.rs deleted file mode 100644 index a88fa9d..0000000 --- a/pkg/zk-primitives/src/element/serde.rs +++ /dev/null @@ -1,55 +0,0 @@ -use ethnum::U256; -use serde::{Deserialize, Deserializer, Serializer}; - -pub(super) fn serialize(u: &U256, serializer: S) -> Result -where - S: Serializer, -{ - hex::serde::serialize(u.to_be_bytes(), serializer) -} - -pub(super) fn deserialize<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let s = String::deserialize(deserializer)?; - let vec = hex::decode(s.trim_start_matches("0x")).map_err(serde::de::Error::custom)?; - let bytes = - <[u8; 32]>::try_from(vec).map_err(|_| serde::de::Error::custom("Invalid length"))?; - Ok(U256::from_be_bytes(bytes)) -} - -#[cfg(test)] -mod tests { - use serde::{Deserialize, Serialize}; - use test_strategy::proptest; - - use crate::Element; - - #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] - struct Example { - element: Element, - } - - #[proptest] - fn canonical_element_serialize_bijection(mut element: Element) { - element.canonicalize(); - - let value = serde_json::to_value(element).unwrap(); - let element_again: Element = serde_json::from_value(value).unwrap(); - - assert_eq!(element, element_again); - } - - #[proptest] - fn elements_produce_identical_base_before_after_serialize(element: Element) { - let base = element.to_base(); - - let value = serde_json::to_value(element).unwrap(); - let element_again: Element = serde_json::from_value(value).unwrap(); - - let base_again = element_again.to_base(); - - assert_eq!(base, base_again); - } -} diff --git a/pkg/zk-primitives/src/hash.rs b/pkg/zk-primitives/src/hash.rs deleted file mode 100644 index 7c70e52..0000000 --- a/pkg/zk-primitives/src/hash.rs +++ /dev/null @@ -1,200 +0,0 @@ -use poseidon_circuit::poseidon::primitives::{ConstantLength, Hash, P128Pow5T3}; - -use crate::{Base, Element}; - -#[cfg(feature = "test-api")] -static HASH_COUNTER: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0); - -/// The number of times [`hash_merge`] has been called -#[cfg(feature = "test-api")] -pub fn hash_count() -> usize { - HASH_COUNTER.load(core::sync::atomic::Ordering::Relaxed) -} - -/// Reset the count returned by [`hash_count`] to 0 -#[cfg(feature = "test-api")] -pub fn reset_hash_count() { - HASH_COUNTER.store(0, core::sync::atomic::Ordering::Relaxed); -} - -#[cfg(feature = "test-api")] -static HASH_ELEMENT_COUNTER: core::sync::atomic::AtomicUsize = - core::sync::atomic::AtomicUsize::new(0); - -/// The number of elements that have been hashed together -#[cfg(feature = "test-api")] -pub fn hash_element_count() -> usize { - HASH_ELEMENT_COUNTER.load(core::sync::atomic::Ordering::Relaxed) -} - -/// Reset the count returned by [`hash_element_count`] to 0 -#[cfg(feature = "test-api")] -pub fn reset_hash_element_count() { - HASH_ELEMENT_COUNTER.store(0, core::sync::atomic::Ordering::Relaxed); -} - -/// Hash two elements together -/// -/// This function is used to calculate the hash of a parent node from the hash of its children, -/// i.e.: `parent_hash = hash_merge(left_hash, right_hash)` -/// -/// ```rust -/// # use zk_primitives::*; -/// let a = hash_merge([Element::new(1), Element::new(2)]); -/// let b = hash_merge([Element::new(1), Element::new(3)]); -/// let c = hash_merge([Element::new(2), Element::new(3)]); -/// -/// assert_ne!(a, b); -/// assert_ne!(a, c); -/// assert_ne!(b, c); -/// ``` -/// This operation is not symmetric: -/// ```rust -/// # use zk_primitives::*; -/// let a = Element::new(1); -/// let b = Element::new(2); -/// -/// let ab = hash_merge([a, b]); -/// let ba = hash_merge([b, a]); -/// -/// assert_ne!(ab, ba); -/// ``` -#[inline] -#[must_use] -pub fn hash_merge(elements: [Element; N]) -> Element { - type H = Hash, ConstantLength, 3, 2>; - - #[cfg(feature = "test-api")] - { - HASH_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed); - HASH_ELEMENT_COUNTER.fetch_add(N, core::sync::atomic::Ordering::Relaxed); - } - - let hash = H::::init().hash(elements.map(Element::to_base)); - Element::from_base(hash) -} - -/// Hash a slice of bytes -/// -/// ```rust -/// # use zk_primitives::*; -/// let hash_1 = hash_bytes(&[1, 2, 3, 4]); -/// let hash_2 = hash_bytes(&[1, 2, 3, 5]); -/// -/// assert_ne!(hash_1, hash_2); -/// ``` -#[inline] -#[must_use] -pub fn hash_bytes(bytes: &[u8]) -> Element { - // an element is slightly smaller than a "u254". For convenience, we're just going to pretend - // it's a u128. If we need the extra perf, we can be a bit more compact here. - - let initial = Element::BYTE_HASH_IV; - - let elements_from_bytes = bytes - .chunks(core::mem::size_of::()) - .map(bytes_to_element); - - core::iter::once(initial) - .chain(elements_from_bytes) - .reduce(|left, right| hash_merge([left, right])) - .unwrap() // there's always at least 1 element -} - -/// Convert a slice of bytes with length in the range `1..=16` to an [`Element`] -/// -/// If there are fewer than 16 bytes, the lower bytes are padded with zeroes -fn bytes_to_element(bytes: &[u8]) -> Element { - let mut padded_bytes = [0; 16]; - padded_bytes[0..bytes.len()].copy_from_slice(bytes); - u128::from_be_bytes(padded_bytes).into() -} - -#[cfg(test)] -mod tests { - use rand::Rng; - use rand_chacha::{rand_core::SeedableRng, ChaChaRng}; - - use super::*; - - #[derive(serde::Serialize)] - struct MergeResult { - left: Element, - right: Element, - merged: Element, - } - - impl MergeResult { - pub fn new(left: Element, right: Element) -> Self { - let merged = hash_merge([left, right]); - - Self { - left, - right, - merged, - } - } - } - - #[test] - fn hash_merge_snapshot_test() { - let special_cases = [ - MergeResult::new(Element::NULL_HASH, Element::NULL_HASH), - MergeResult::new(Element::NULL_HASH, Element::ONE), - MergeResult::new(Element::ONE, Element::NULL_HASH), - ]; - - let mut rng = ChaChaRng::from_seed([0; 32]); - let random_cases = core::iter::from_fn(|| { - let left = Element::secure_random(&mut rng); - let right = Element::secure_random(&mut rng); - Some(MergeResult::new(left, right)) - }); - - let results: Vec<_> = special_cases - .into_iter() - .chain(random_cases.take(100)) - .collect(); - - insta::assert_json_snapshot!(results); - } - - #[derive(serde::Serialize)] - struct ByteResult { - #[serde(with = "hex::serde")] - bytes: Vec, - hash: Element, - } - - impl ByteResult { - fn new(bytes: &[u8]) -> Self { - let hash = hash_bytes(bytes); - let bytes = bytes.to_vec(); - Self { bytes, hash } - } - } - - #[test] - fn hash_bytes_snapshot_test() { - let special_cases = [ - ByteResult::new(&[]), - ByteResult::new(&[0]), - ByteResult::new(&[0; 16]), - ]; - - let mut rng = ChaChaRng::from_seed([0; 32]); - - let random_cases = core::iter::from_fn(|| { - let mut bytes = [0; 64]; - rng.fill(&mut bytes); - Some(ByteResult::new(&bytes)) - }); - - let results: Vec<_> = special_cases - .into_iter() - .chain(random_cases.take(100)) - .collect(); - - insta::assert_json_snapshot!(results); - } -} diff --git a/pkg/zk-primitives/src/input_note.rs b/pkg/zk-primitives/src/input_note.rs new file mode 100644 index 0000000..374bdd1 --- /dev/null +++ b/pkg/zk-primitives/src/input_note.rs @@ -0,0 +1,93 @@ +use crate::note::Note; +use crate::{bridged_polygon_usdc_note_kind, get_address_for_private_key}; +use element::Element; +use parse_link::{NoteURLPayload, decode_activity_url_payload}; +use serde::{Deserialize, Serialize}; + +/// InputNote is a Note that belongs to the current user, i.e. they have the +/// spending sercret key and can therefore use it as an input, "spending" the note. Extra +/// constraints need to be applied to input notes to ensure they are valid. +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct InputNote { + /// The note to spend + pub note: Note, + /// Secret key for the address, required to spend a note + pub secret_key: Element, +} + +impl InputNote { + /// Create a new input note + #[must_use] + pub fn new(note: Note, secret_key: Element) -> Self { + Self { note, secret_key } + } + + /// Create a new padding note + #[must_use] + pub fn padding_note() -> Self { + Self { + secret_key: Element::ZERO, + note: Note::padding_note(), + } + } + + /// Generates a new note with given value, for an ephemeral private key, the private key + /// must only be used once + #[must_use] + pub fn new_from_ephemeral_private_key( + private_key: Element, + value: Element, + note_kind: Element, + ) -> Self { + Self { + note: Note::new_from_ephemeral_private_key(private_key, value, note_kind), + secret_key: private_key, + } + } + + /// Generates an InputNote from a link string e.g. /s#A0F3... + #[must_use] + pub fn new_from_link(link: &str) -> Self { + InputNote::from(&decode_activity_url_payload(link)) + } + + /// Generates a Payy link from the Note + Private Key + #[must_use] + pub fn generate_link(&self) -> String { + self.to_note_url_payload().encode_activity_url_payload() + } + + /// Construct the canonical [`NoteURLPayload`] representing this note. + #[must_use] + pub fn to_note_url_payload(&self) -> NoteURLPayload { + NoteURLPayload { + version: 2, + private_key: self.secret_key, + psi: None, + value: self.note.value, + note_kind: (self.note.contract != bridged_polygon_usdc_note_kind()) + .then_some(self.note.contract), + referral_code: String::new(), + } + } +} + +impl From<&NoteURLPayload> for InputNote { + fn from(value: &NoteURLPayload) -> Self { + let psi = value.psi(); + + Self { + secret_key: value.private_key, + note: Note { + kind: Element::new(2), + contract: value.note_kind(), + address: get_address_for_private_key(value.private_key), + psi, + value: value.value, + }, + } + } +} + +#[cfg(test)] +mod tests; diff --git a/pkg/zk-primitives/src/input_note/tests.rs b/pkg/zk-primitives/src/input_note/tests.rs new file mode 100644 index 0000000..252d00d --- /dev/null +++ b/pkg/zk-primitives/src/input_note/tests.rs @@ -0,0 +1,69 @@ +use super::InputNote; +use crate::note::Note; +use crate::{bridged_polygon_usdc_note_kind, get_address_for_private_key}; +use element::Element; + +#[test] +fn to_note_url_payload_omits_default_usdc_note_kind() { + let note_kind = bridged_polygon_usdc_note_kind(); + let input_note = InputNote::new( + Note::new_from_ephemeral_private_key(Element::new(10), Element::new(20), note_kind), + Element::new(10), + ); + + let payload = input_note.to_note_url_payload(); + + assert_eq!(payload.note_kind, None); + assert_eq!(payload.note_kind(), note_kind); +} + +#[test] +fn to_note_url_payload_preserves_non_usdc_note_kind() { + let note_kind = Element::new(99); + let secret_key = Element::new(10); + let input_note = InputNote::new( + Note::new_with_psi( + get_address_for_private_key(secret_key), + Element::new(20), + Element::new(30), + note_kind, + ), + secret_key, + ); + + let payload = input_note.to_note_url_payload(); + + assert_eq!(payload.note_kind, Some(note_kind)); + assert_eq!(payload.note_kind(), note_kind); +} + +#[test] +fn input_note_from_payload_uses_payload_note_kind() { + let note_kind = Element::new(99); + let payload = parse_link::NoteURLPayload { + version: 2, + private_key: Element::new(10), + psi: None, + value: Element::new(20), + note_kind: Some(note_kind), + referral_code: String::new(), + }; + + let input_note = InputNote::from(&payload); + + assert_eq!(input_note.note.contract, note_kind); +} + +#[test] +fn generate_link_roundtrips_non_usdc_note_kind() { + let note_kind = Element::new(99); + let input_note = InputNote::new( + Note::new_from_ephemeral_private_key(Element::new(10), Element::new(20), note_kind), + Element::new(10), + ); + + let link = input_note.generate_link(); + let decoded = InputNote::new_from_link(&link); + + assert_eq!(decoded.note.contract, note_kind); +} diff --git a/pkg/zk-primitives/src/lib.rs b/pkg/zk-primitives/src/lib.rs index b996cd0..2797c21 100644 --- a/pkg/zk-primitives/src/lib.rs +++ b/pkg/zk-primitives/src/lib.rs @@ -9,20 +9,38 @@ //! A set of core primitives for use with polybase's zk circuits -mod element; -mod hash; -mod path; +mod address; +mod agg_agg; +mod agg_final; +mod agg_utxo; +mod burn; +mod input_note; +mod merkle_path; +mod migrate; +mod note; +mod points; +mod proof_bytes; +mod signature; +mod traits; +mod util; +mod utxo; -#[cfg(feature = "test-api")] -pub use hash::{hash_count, hash_element_count, reset_hash_count, reset_hash_element_count}; - -#[cfg(feature = "rand")] -pub use element::Insecure; -pub use element::{Element, Lsb}; -pub use hash::{hash_bytes, hash_merge}; -pub use path::compute_merkle_root; - -/// The base element used by cryptographic operations on this tree -/// -/// This is (roughly) an integer modulo `p` where `p` is [`Element::MODULUS`] -pub type Base = poseidon_circuit::Bn256Fr; +pub use address::*; +pub use agg_agg::*; +pub use agg_final::*; +pub use agg_utxo::*; +pub use burn::*; +pub use input_note::*; +pub use merkle_path::*; +pub use migrate::*; +pub use note::*; +pub use parse_link::{ + NoteURLPayload, NoteUrlDecodeError, NoteUrlDecodeResult, decode_activity_url_payload, + try_decode_activity_url_payload, +}; +pub use points::*; +pub use proof_bytes::*; +pub use signature::*; +pub use traits::*; +pub use util::*; +pub use utxo::*; diff --git a/pkg/zk-primitives/src/merkle_path.rs b/pkg/zk-primitives/src/merkle_path.rs new file mode 100644 index 0000000..5ad0bcc --- /dev/null +++ b/pkg/zk-primitives/src/merkle_path.rs @@ -0,0 +1,82 @@ +use element::Base; +use element::Element; +use serde::{Deserialize, Serialize}; + +/// The siblings of a merkle path, for a `smirk::Tree` of depth `DEPTH` +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct MerklePath { + /// The siblings that form the merkle path + pub siblings: Vec, +} + +impl Default for MerklePath { + fn default() -> Self { + let siblings = (1..DEPTH).map(|_| Element::ZERO).collect::>(); + + assert_eq!(siblings.len(), DEPTH - 1); + + Self { siblings } + } +} + +impl MerklePath { + /// Create a new merkle path from a list of siblings + /// + /// # Panics + /// + /// If the number of siblings is not equal to `DEPTH - 1` + #[must_use] + pub fn new(siblings: Vec) -> Self { + assert_eq!(DEPTH - 1, siblings.len(), "Merkle path invalid size"); + MerklePath { siblings } + } + + /// Compute the root hash of a tree with the given hash at this path (i.e. the state + /// after the leaf is inserted) + #[must_use] + pub fn compute_before_root(&self, hash: Element) -> Element { + hash::compute_merkle_root(hash, hash, &self.siblings) + } + + /// Compute the root hash of a tree given siblings, assuming leaf is null (i.e. the state + /// before the leaf is inserted) + #[must_use] + pub fn compute_after_root(&self, hash: Element) -> Element { + hash::compute_null_root(hash, &self.siblings) + } + + /// Create a new merkle path, after the insertion of the leaf, leaf must match + /// the siblings + #[must_use] + pub fn apply_leaf(&self, leaf: Element) -> MerklePath { + MerklePath { + siblings: hash::compute_merkle_path_for_leaf(leaf, &self.siblings), + } + } +} + +impl From<[Base; DEPTH]> for MerklePath { + fn from(elements: [Base; DEPTH]) -> Self { + MerklePath::new( + elements[..DEPTH - 1] + .iter() + .copied() + .map(Element::from_base) + .collect(), + ) + } +} + +// TODO: this probably won't work! Maybe we should just use a complete path incl root, +// then take off root if needed +// TODO_NOIR +impl From> for [Base; DEPTH] { + fn from(path: MerklePath) -> Self { + path.siblings + .iter() + .map(Element::to_base) + .collect::>() + .try_into() + .unwrap() + } +} diff --git a/pkg/zk-primitives/src/migrate.rs b/pkg/zk-primitives/src/migrate.rs new file mode 100644 index 0000000..b6bb13d --- /dev/null +++ b/pkg/zk-primitives/src/migrate.rs @@ -0,0 +1,61 @@ +use element::{Base, Element}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +use crate::ProofBytes; + +/// Migration input for proving ownership during address migration +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Migrate { + /// The private key of the owner + pub owner_pk: Element, + /// The old address (public input) + pub old_address: Element, + /// The new address (public input) + pub new_address: Element, +} + +impl Migrate { + /// Create a new migration input + #[must_use] + pub fn new(owner_pk: Element, old_address: Element, new_address: Element) -> Self { + Self { + owner_pk, + old_address, + new_address, + } + } +} + +/// Migration public inputs +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct MigratePublicInput { + /// The old address being migrated from + #[cfg_attr(feature = "ts-rs", ts(as = "String"))] + pub old_address: Element, + /// The new address being migrated to + #[cfg_attr(feature = "ts-rs", ts(as = "String"))] + pub new_address: Element, +} + +impl MigratePublicInput { + /// Convert the public inputs to field elements + #[must_use] + pub fn to_fields(&self) -> Vec { + vec![self.old_address.to_base(), self.new_address.to_base()] + } +} + +/// Migration proof output +#[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct MigrateProof { + /// The proof bytes (without public inputs) + pub proof: ProofBytes, + /// The public inputs + pub public_inputs: MigratePublicInput, +} diff --git a/pkg/zk-primitives/src/note.rs b/pkg/zk-primitives/src/note.rs new file mode 100644 index 0000000..4d527af --- /dev/null +++ b/pkg/zk-primitives/src/note.rs @@ -0,0 +1,139 @@ +use crate::{get_address_for_private_key, hash_private_key_for_psi}; +use element::Element; +use noirc_abi::input_parser::InputValue; +use rand::thread_rng; +use serde::{Deserialize, Serialize}; +use std::collections::BTreeMap; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +/// A note is used in zk circuits to represent some kind of token (e.g. USDC) on +/// the Payy Network. +/// +/// This is used to create notes in the zk-rollup +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Note { + /// The kind of note + pub kind: Element, + /// The contract of note + pub contract: Element, + /// The address of the note + pub address: Element, + /// The psi adds additional entropy to the note, to ensure uniqueness + pub psi: Element, + /// The value of the note (dependent on the token) + pub value: Element, +} + +impl Note { + /// Create a new note + #[must_use] + pub fn new(address: Element, value: Element, note_kind: Element) -> Self { + Self { + kind: Element::new(2), + contract: note_kind, + address, + psi: Element::secure_random(thread_rng()), + value, + } + } + + /// Create a new note with custom PSI + #[must_use] + pub fn new_with_psi( + address: Element, + value: Element, + psi: Element, + note_kind: Element, + ) -> Self { + Self { + kind: Element::new(2), + contract: note_kind, + address, + psi, + value, + } + } + + /// New note from ephemeral private key (only use private key once) + #[must_use] + pub fn new_from_ephemeral_private_key( + private_key: Element, + value: Element, + note_kind: Element, + ) -> Self { + let address = get_address_for_private_key(private_key); + let psi = hash_private_key_for_psi(private_key); + Self { + kind: Element::new(2), + contract: note_kind, + address, + psi, + value, + } + } + + /// Deterministic padding note, because circuits have a fixed note input size, + /// and so we pad extra notes with zeros + #[must_use] + pub fn padding_note() -> Self { + Note { + kind: Element::new(2), + contract: Element::ZERO, + address: Element::ZERO, + psi: Element::ZERO, + value: Element::ZERO, + } + } + + /// Check if the note is a padding note + #[must_use] + pub fn is_padding_note(&self) -> bool { + self.contract == Element::ZERO && self.value == Element::ZERO + } + + /// Commitment of the note, this is stored in the merkle tree and proves the note exists + // TODO: should we leave some space in here? + #[must_use] + pub fn commitment(&self) -> Element { + if self.value == Element::ZERO { + Element::ZERO + } else { + hash::hash_merge([ + self.kind, + self.contract, + self.value, + self.address, + self.psi, + Element::ZERO, + Element::ZERO, + ]) + } + } +} + +impl Default for Note { + fn default() -> Self { + Self::padding_note() + } +} + +impl From<&Note> for InputValue { + fn from(note: &Note) -> Self { + let mut struct_ = BTreeMap::new(); + + struct_.insert( + "address".to_owned(), + InputValue::Field(note.address.to_base()), + ); + struct_.insert( + "kind".to_owned(), + InputValue::Field(note.contract.to_base()), + ); + struct_.insert("psi".to_owned(), InputValue::Field(note.psi.to_base())); + struct_.insert("value".to_owned(), InputValue::Field(note.value.to_base())); + + InputValue::Struct(struct_) + } +} diff --git a/pkg/zk-primitives/src/path.rs b/pkg/zk-primitives/src/path.rs deleted file mode 100644 index 6ebc533..0000000 --- a/pkg/zk-primitives/src/path.rs +++ /dev/null @@ -1,80 +0,0 @@ -use crate::{hash_merge, Element}; - -/// Compute the root hash of a merkle tree -/// -/// `siblings` is an [`Iterator`] that yields tuples containing the sibling, and a boolean value -/// that indicates whether the sibling in question was on the left or right (`false` means that the -/// sibling is on the right, `true` means that the sibling is on the left). -/// -/// The elements of `siblings` are in "deepest-first" order. -/// Note that the root hash of the tree is not considered to be a sibling, so a tree of depth `N` -/// would have `N - 1` siblings -/// -/// For example, consider the following tree: -/// ```text -/// ┌─────┐ -/// │ C │ -/// └──┬──┘ -/// │ -/// ┌─────┴─────┐ -/// │ │ -/// ┌──▼──┐ ┌──▼──┐ -/// │ A │ │ B │ -/// └──┬──┘ └──┬──┘ -/// │ │ -/// ┌──┴──┐ ┌──┴──┐ -/// │ │ │ │ -/// ┌─▼─┐ ┌─▼─┐ ┌─▼─┐ ┌─▼─┐ -/// │ 0 │ │ 1 │ │ 2 │ │ 3 │ -/// └───┘ └───┘ └───┘ └───┘ -/// ``` -/// Here: -/// - `A` is [`hash_merge(0, 1)`][crate::hash_merge] -/// - `B` is [`hash_merge(2, 3)`][crate::hash_merge] -/// - `C` is [`hash_merge(hash_merge(0, 1), hash_merge(2, 3))`][crate::hash_merge] (i.e. the root -/// hash of the tree) -/// -/// If you wanted to prove that `2` was in the tree with this function, you would do the -/// following: -/// ```rust -/// # use zk_primitives::*; -/// // create the iterator of tuples and left/right bools -/// let a = hash_merge([Element::new(0), Element::new(1)]); -/// let b = hash_merge([Element::new(2), Element::new(3)]); -/// let c = hash_merge([a, b]); -/// -/// let siblings = [ -/// ( -/// Element::new(3), -/// false, // the sibling right, so this value is false -/// ), -/// ( -/// a, -/// true, // the sibling left, so this value is true -/// ), -/// ]; -/// -/// // we are trying to prove the existence of `2`, so we use this as the `leaf` parameter -/// let root_hash = compute_merkle_root(Element::new(2), siblings); -/// assert_eq!(root_hash, c); // the hashes match, proving that `2` is in the tree -/// -/// // It might be the case that the tree had `Element::NULL_HASH` at this location in the tree -/// let root_hash_if_null = compute_merkle_root(Element::NULL_HASH, siblings); -/// assert_ne!(root_hash_if_null, c); // these aren't equal -/// ``` -pub fn compute_merkle_root>( - mut leaf: Element, - siblings: I, -) -> Element { - for (sibling, bit) in siblings { - match bit { - // bit is 0, this element is on the left - false => leaf = hash_merge([leaf, sibling]), - - // bit is 1, this element is on the right - true => leaf = hash_merge([sibling, leaf]), - } - } - - leaf -} diff --git a/pkg/zk-primitives/src/points.rs b/pkg/zk-primitives/src/points.rs new file mode 100644 index 0000000..cde43fc --- /dev/null +++ b/pkg/zk-primitives/src/points.rs @@ -0,0 +1,78 @@ +use crate::{Note, ProofBytes}; +use element::Element; +use serde::{Deserialize, Serialize}; +use std::time::{SystemTime, UNIX_EPOCH}; + +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +/// Points represents the data for a circuit that proves the number of points to give +/// to a user based on the notes they own. +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Points { + /// Secret key + pub secret_keys: [Element; 10], + /// Note values to be proven + pub notes: [Note; 10], + /// Timestamp + pub timestamp: Element, + /// Address to award points to + pub address: Element, +} + +impl Points { + /// Create a new points proof + #[must_use] + pub fn new(address: Element, secret_keys: [Element; 10], notes: [Note; 10]) -> Self { + Self { + address, + secret_keys, + notes, + timestamp: Element::new( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(), + ), + } + } + + /// Get the value of the points + #[must_use] + pub fn value(&self) -> Element { + self.notes.iter().map(|note| note.value).sum() + } + + /// Get the hash of the address and timestamp + #[must_use] + pub fn hash(&self) -> Element { + hash::hash_merge([self.timestamp, self.address]) + } +} + +/// Public input for the points circuit +#[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct PointsPublicInput { + /// Value of the points + pub value: Element, + /// Timestamp (points proofs are valid for 1 day) + pub timestamp: Element, + /// Hash of address and timestamp + pub hash: Element, + /// Commitments to check that are in the tree and so points can be claimed + pub commitments: [Element; 10], +} + +/// Bundle of a proof and its public inputs for points. This can be used +/// verify the proof. +#[derive(Clone, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct PointsProof { + /// Proof + pub proof: ProofBytes, + /// Public inputs + pub public_inputs: PointsPublicInput, +} diff --git a/pkg/zk-primitives/src/proof_bytes.rs b/pkg/zk-primitives/src/proof_bytes.rs new file mode 100644 index 0000000..57ff912 --- /dev/null +++ b/pkg/zk-primitives/src/proof_bytes.rs @@ -0,0 +1,65 @@ +use borsh::{BorshDeserialize, BorshSerialize}; +use element::Element; +use primitives::serde::{deserialize_base64, serialize_base64}; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +use crate::bytes_to_elements; + +/// Default proof byte length for agg_agg and related proofs. +pub const PROOF_BYTES_LEN: usize = 508 * 32; + +/// Default proof byte length for oracle/agg_final proofs. +pub const ORACLE_PROOF_BYTES_LEN: usize = 330 * 32; + +/// Raw proof bytes for zk circuit proofs (without public inputs). +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct ProofBytes( + #[serde( + serialize_with = "serialize_base64", + deserialize_with = "deserialize_base64" + )] + #[cfg_attr(feature = "ts-rs", ts(as = "String"))] + pub Vec, +); + +impl Default for ProofBytes { + fn default() -> Self { + Self(vec![0u8; PROOF_BYTES_LEN]) + } +} + +impl ProofBytes { + /// Convert proof bytes into field elements. + #[must_use] + pub fn to_fields(&self) -> Vec { + bytes_to_elements(&self.0) + } +} + +/// Raw oracle proof bytes for zk circuit proofs (without public inputs). +#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +pub struct OracleProofBytes( + #[serde( + serialize_with = "serialize_base64", + deserialize_with = "deserialize_base64" + )] + pub Vec, +); + +impl Default for OracleProofBytes { + fn default() -> Self { + Self(vec![0u8; ORACLE_PROOF_BYTES_LEN]) + } +} + +impl OracleProofBytes { + /// Convert proof bytes into field elements. + #[must_use] + pub fn to_fields(&self) -> Vec { + bytes_to_elements(&self.0) + } +} diff --git a/pkg/zk-primitives/src/signature.rs b/pkg/zk-primitives/src/signature.rs new file mode 100644 index 0000000..5d16023 --- /dev/null +++ b/pkg/zk-primitives/src/signature.rs @@ -0,0 +1,49 @@ +use element::Element; +use serde::{Deserialize, Serialize}; + +use crate::ProofBytes; + +/// A signature is a message signed by a secret key, often used to authenticate a user's +/// posession of a address +#[derive(Clone, Default, Debug, Serialize, Deserialize)] +pub struct Signature { + /// Secret key for the address, required to spend a note + pub secret_key: Element, + /// Message to be signed + pub message: Element, +} + +impl Signature { + /// Create a new signature + #[must_use] + pub fn new(secret_key: Element, message: Element) -> Self { + Self { + secret_key, + message, + } + } + + /// Get the message hash + #[must_use] + pub fn message_hash(&self) -> Element { + hash::hash_merge([self.secret_key, self.message]) + } +} + +/// The public inputs for a signature proof +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct SignaturePublicInput { + /// The address of the sender + pub address: Element, + /// The message to be signed + pub message: Element, +} + +/// The output proof for a signature proof +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct SignatureProof { + /// The proof for the signature proof + pub proof: ProofBytes, + /// The public inputs for the signature proof + pub public_inputs: SignaturePublicInput, +} diff --git a/pkg/zk-primitives/src/signed_element.rs b/pkg/zk-primitives/src/signed_element.rs new file mode 100644 index 0000000..25693b2 --- /dev/null +++ b/pkg/zk-primitives/src/signed_element.rs @@ -0,0 +1,867 @@ +// lint-long-file-override allow-max-lines=900 +use crate::Element; +use ethnum::U256; +use std::cmp::{Ord, Ordering, PartialOrd}; +use std::ops::{Add, Div, Mul, Neg, Sub}; + +/// A signed 256-bit integer that wraps an `Element` with a sign bit +/// +/// This type allows performing arithmetic operations with signed numbers, +/// while the underlying `Element` remains unsigned. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] +pub struct SignedElement { + /// The absolute value stored as an Element + pub value: Element, + /// The sign: true for negative, false for positive or zero + pub negative: bool, +} + +impl SignedElement { + /// Creates a new SignedElement with the given value and sign + #[inline] + #[must_use] + pub fn new(value: Element, negative: bool) -> Self { + // Normalize: if value is zero, sign should be positive + if value.is_zero() { + Self { + value, + negative: false, + } + } else { + Self { value, negative } + } + } + + /// The zero element (the additive identity) + pub const ZERO: Self = Self { + value: Element::ZERO, + negative: false, + }; + + /// The one element (the multiplicative identity) + pub const ONE: Self = Self { + value: Element::ONE, + negative: false, + }; + + /// The negative one element + pub const NEG_ONE: Self = Self { + value: Element::ONE, + negative: true, + }; + + /// Get the absolute value of this element + #[inline] + #[must_use] + pub fn abs(self) -> Element { + self.value + } + + /// Check if this element is negative + #[inline] + #[must_use] + pub fn is_negative(self) -> bool { + self.negative + } + + /// Check if this element is positive (greater than zero) + #[inline] + #[must_use] + pub fn is_positive(self) -> bool { + !self.negative && !self.value.is_zero() + } + + /// Check if this element is zero + #[inline] + #[must_use] + pub fn is_zero(self) -> bool { + self.value.is_zero() + } + + /// Get the sign of this element: -1, 0, or 1 + #[inline] + #[must_use] + pub fn signum(self) -> Self { + if self.is_zero() { + Self::ZERO + } else if self.negative { + Self::NEG_ONE + } else { + Self::ONE + } + } + + /// Convert to the underlying U256 value with sign information + /// Returns the U256 absolute value and a boolean indicating if negative + #[inline] + #[must_use] + pub fn to_u256_with_sign(self) -> (U256, bool) { + (self.value.to_u256(), self.negative) + } +} + +// Conversions from various types to SignedElement + +impl From for SignedElement { + fn from(value: Element) -> Self { + Self::new(value, false) + } +} + +impl From for SignedElement { + fn from(value: u64) -> Self { + Self::new(Element::new(value), false) + } +} + +impl From for SignedElement { + fn from(value: i64) -> Self { + if value < 0 { + Self::new(Element::new(value.unsigned_abs()), true) + } else { + Self::new(Element::new(value.unsigned_abs()), false) + } + } +} + +// Arithmetic operations + +impl Neg for SignedElement { + type Output = Self; + + fn neg(self) -> Self::Output { + if self.is_zero() { + self + } else { + Self::new(self.value, !self.negative) + } + } +} + +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + if self.negative == rhs.negative { + // Same sign, add values and keep the sign + Self::new(self.value + rhs.value, self.negative) + } else { + // Different signs, subtract the smaller from the larger + match self.value.cmp(&rhs.value) { + std::cmp::Ordering::Equal => Self::ZERO, + std::cmp::Ordering::Greater => Self::new(self.value - rhs.value, self.negative), + std::cmp::Ordering::Less => Self::new(rhs.value - self.value, rhs.negative), + } + } + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + self + (-rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: Self) -> Self::Output { + // Multiply absolute values, XOR the signs + Self::new(self.value * rhs.value, self.negative != rhs.negative) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + // Divide absolute values, XOR the signs + assert!(!rhs.is_zero(), "Division by zero"); + Self::new(self.value / rhs.value, self.negative != rhs.negative) + } +} + +// Implement operations with Element operands + +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: Element) -> Self::Output { + self + Self::from(rhs) + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: Element) -> Self::Output { + self - Self::from(rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: Element) -> Self::Output { + self * Self::from(rhs) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: Element) -> Self::Output { + self / Self::from(rhs) + } +} + +// Implement operations with primitive types +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: u64) -> Self::Output { + self + Self::from(rhs) + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: u64) -> Self::Output { + self - Self::from(rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: u64) -> Self::Output { + self * Self::from(rhs) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: u64) -> Self::Output { + self / Self::from(rhs) + } +} + +// Implement operations with i64 +impl Add for SignedElement { + type Output = Self; + + fn add(self, rhs: i64) -> Self::Output { + self + Self::from(rhs) + } +} + +impl Sub for SignedElement { + type Output = Self; + + fn sub(self, rhs: i64) -> Self::Output { + self - Self::from(rhs) + } +} + +impl Mul for SignedElement { + type Output = Self; + + fn mul(self, rhs: i64) -> Self::Output { + self * Self::from(rhs) + } +} + +impl Div for SignedElement { + type Output = Self; + + fn div(self, rhs: i64) -> Self::Output { + self / Self::from(rhs) + } +} + +// Display implementation +impl std::fmt::Display for SignedElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.negative { + write!(f, "-{}", self.value) + } else { + write!(f, "{}", self.value) + } + } +} + +// Implement PartialEq for primitive types +impl PartialEq for SignedElement { + fn eq(&self, other: &Element) -> bool { + !self.negative && self.value == *other + } +} + +impl PartialEq for SignedElement { + fn eq(&self, other: &u64) -> bool { + !self.negative && self.value == *other + } +} + +impl PartialEq for SignedElement { + fn eq(&self, other: &i64) -> bool { + if *other < 0 { + // Convert negative i64 to positive u64 safely using unsigned_abs() instead of casting + self.negative && self.value == Element::new(other.unsigned_abs()) + } else { + // For non-negative values, explicitly create from non-negative i64 + // This should never fail since we've verified other >= 0 + let Ok(u64_value) = u64::try_from(*other) else { + // This branch should be unreachable - i64::MAX is well within u64 range + panic!("Failed to convert non-negative i64 {other} to u64"); + }; + !self.negative && self.value == Element::new(u64_value) + } + } +} + +// Implement a few more utility methods +impl SignedElement { + /// Tries to convert this SignedElement to an i64 + /// + /// Returns None if the value doesn't fit in an i64 + #[must_use] + pub fn to_i64(&self) -> Option { + if self.value > Element::new(i64::MAX as u64) { + None + } else { + // First convert to u64 + let unsigned_val = self.value.to_u256().as_u64(); + + // Check if it can fit in i64 before conversion + if !self.negative && unsigned_val > i64::MAX as u64 { + None + } else { + // We've verified the value fits in i64, so conversion should never fail + let Ok(signed_value) = i64::try_from(unsigned_val) else { + // This should be unreachable given our checks + panic!("Failed to convert u64 {unsigned_val} to i64 despite being in range"); + }; + + Some(if self.negative { + -signed_value + } else { + signed_value + }) + } + } + } + + /// Checks if this SignedElement represents a value that fits in an i64 + #[must_use] + pub fn fits_in_i64(&self) -> bool { + self.to_i64().is_some() + } +} + +// Implement PartialOrd for SignedElement +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// Implement Ord for SignedElement +impl Ord for SignedElement { + fn cmp(&self, other: &Self) -> Ordering { + match (self.negative, other.negative) { + // Both positive (or zero): compare normally + (false, false) => self.value.cmp(&other.value), + + // Both negative: larger absolute value is smaller + (true, true) => other.value.cmp(&self.value), + + // Self negative, other positive (or zero): self is less + (true, false) => Ordering::Less, + + // Self positive (or zero), other negative: self is greater + (false, true) => Ordering::Greater, + } + } +} + +// Implement PartialOrd with Element +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &Element) -> Option { + if self.negative { + // Any negative number is less than any Element (which is unsigned) + Some(Ordering::Less) + } else { + // Positive SignedElement: compare values normally + Some(self.value.cmp(other)) + } + } +} + +// Implement PartialOrd with u64 +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &u64) -> Option { + if self.negative { + // Any negative number is less than any u64 + Some(Ordering::Less) + } else { + // Positive SignedElement: compare values normally + let other_element = Element::from(*other); + Some(self.value.cmp(&other_element)) + } + } +} + +// Implement PartialOrd with i64 +impl PartialOrd for SignedElement { + fn partial_cmp(&self, other: &i64) -> Option { + if *other < 0 { + // Compare with negative i64 + if self.negative { + // Both negative, compare absolute values (reversed) + // For negative numbers, the one with the larger absolute value is smaller + // -15 > -25 because 15 < 25 + let other_abs = other.unsigned_abs(); + let self_abs = self.value.to_u256().as_u64(); + + // Here we compare self_abs with other_abs, and then reverse the result + // because larger absolute value means smaller negative number + Some(self_abs.cmp(&other_abs).reverse()) + } else { + // Self positive, other negative: self is greater + Some(Ordering::Greater) + } + } else { + // Compare with non-negative i64 + if self.negative { + // Self negative, other non-negative: self is less + Some(Ordering::Less) + } else { + // Both non-negative: normal comparison + // This conversion should never fail since we've checked other >= 0 + let Ok(u64_other) = u64::try_from(*other) else { + // This branch should be unreachable - i64::MAX is well within u64 range + panic!("Failed to convert non-negative i64 {other} to u64"); + }; + let other_element = Element::from(u64_other); + Some(self.value.cmp(&other_element)) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_basic_operations() { + // Test addition with same signs + let a = SignedElement::from(5i64); + let b = SignedElement::from(3i64); + assert_eq!(a + b, SignedElement::from(8i64)); + assert!((a + b).is_positive()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a + b, SignedElement::from(-8i64)); + assert!((a + b).is_negative()); + + // Test addition with different signs + let a = SignedElement::from(5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a + b, SignedElement::from(2i64)); + assert!((a + b).is_positive()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(3i64); + assert_eq!(a + b, SignedElement::from(-2i64)); + assert!((a + b).is_negative()); + + // Test subtraction + let a = SignedElement::from(5i64); + let b = SignedElement::from(3i64); + assert_eq!(a - b, SignedElement::from(2i64)); + assert!((a - b).is_positive()); + + let a = SignedElement::from(3i64); + let b = SignedElement::from(5i64); + assert_eq!(a - b, SignedElement::from(-2i64)); + assert!((a - b).is_negative()); + + // Test multiplication + let a = SignedElement::from(5i64); + let b = SignedElement::from(3i64); + assert_eq!(a * b, SignedElement::from(15i64)); + assert!((a * b).is_positive()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(3i64); + assert_eq!(a * b, SignedElement::from(-15i64)); + assert!((a * b).is_negative()); + + let a = SignedElement::from(5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a * b, SignedElement::from(-15i64)); + assert!((a * b).is_negative()); + + let a = SignedElement::from(-5i64); + let b = SignedElement::from(-3i64); + assert_eq!(a * b, SignedElement::from(15i64)); + assert!((a * b).is_positive()); + + // Test division + let a = SignedElement::from(15i64); + let b = SignedElement::from(3i64); + assert_eq!(a / b, SignedElement::from(5i64)); + assert!((a / b).is_positive()); + + let a = SignedElement::from(-15i64); + let b = SignedElement::from(3i64); + assert_eq!(a / b, SignedElement::from(-5i64)); + assert!((a / b).is_negative()); + + let a = SignedElement::from(15i64); + let b = SignedElement::from(-3i64); + assert_eq!(a / b, SignedElement::from(-5i64)); + assert!((a / b).is_negative()); + + let a = SignedElement::from(-15i64); + let b = SignedElement::from(-3i64); + assert_eq!(a / b, SignedElement::from(5i64)); + assert!((a / b).is_positive()); + } + + #[test] + fn test_sign_operations() { + let a = SignedElement::from(5i64); + assert!(!a.is_negative()); + assert!(a.is_positive()); + assert!(!a.is_zero()); + + let a = SignedElement::from(-5i64); + assert!(a.is_negative()); + assert!(!a.is_positive()); + assert!(!a.is_zero()); + + let a = SignedElement::ZERO; + assert!(!a.is_negative()); + assert!(!a.is_positive()); + assert!(a.is_zero()); + + // Test negation + let a = SignedElement::from(5i64); + assert_eq!(-a, SignedElement::from(-5i64)); + + let a = SignedElement::from(-5i64); + assert_eq!(-a, SignedElement::from(5i64)); + + let a = SignedElement::ZERO; + assert_eq!(-a, SignedElement::ZERO); + } + + #[test] + fn test_signum() { + let a = SignedElement::from(5i64); + assert_eq!(a.signum(), SignedElement::ONE); + + let a = SignedElement::from(-5i64); + assert_eq!(a.signum(), SignedElement::NEG_ONE); + + let a = SignedElement::ZERO; + assert_eq!(a.signum(), SignedElement::ZERO); + } + + #[test] + fn test_large_numbers() { + // Create elements with large values near U256 limits + let max_element = Element::MAX; + + // Create large elements using U256 values + let large_u256 = U256::from_str_radix( + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0", + 16, + ) + .unwrap(); + let large_element = Element::from(large_u256); + + // Create signed elements with these large values + let pos_max = SignedElement::new(max_element, false); + let neg_max = SignedElement::new(max_element, true); + let pos_large = SignedElement::new(large_element, false); + let neg_large = SignedElement::new(large_element, true); + + // Test signs are preserved + assert!(!pos_max.is_negative()); + assert!(neg_max.is_negative()); + assert!(!pos_large.is_negative()); + assert!(neg_large.is_negative()); + + // Test negation of large values + assert_eq!(-pos_max, neg_max); + assert_eq!(-neg_max, pos_max); + + // Test addition with large numbers + let small = SignedElement::from(1u64); + + // Addition with small numbers + let result = pos_large + small; + assert!(!result.is_negative()); + + // Addition with opposite signs + let result = pos_large + neg_small(); + assert!(!result.is_negative()); + + let result = neg_large + small; + assert!(result.is_negative()); + + // Test multiplication with sign changes + let result = pos_large * SignedElement::NEG_ONE; + assert!(result.is_negative()); + assert_eq!(result.value, large_element); + + let result = neg_large * SignedElement::NEG_ONE; + assert!(!result.is_negative()); + assert_eq!(result.value, large_element); + } + + // Helper function for a small negative number + fn neg_small() -> SignedElement { + SignedElement::new(Element::ONE, true) + } + + #[test] + fn test_large_number_sign_preservation() { + // Create a more moderate large value that won't overflow + let large_value = Element::from( + U256::from_str_radix( + "8000000000000000000000000000000000000000000000000000000000000000", + 16, + ) + .unwrap(), + ); + + // Test positive large value + let pos_large = SignedElement::new(large_value, false); + assert!(!pos_large.is_negative()); + assert!(pos_large.is_positive()); + + // Test negative large value + let neg_large = SignedElement::new(large_value, true); + assert!(neg_large.is_negative()); + assert!(!neg_large.is_positive()); + + // Test negation preserves absolute value + assert_eq!(-pos_large, neg_large); + assert_eq!(-neg_large, pos_large); + + // Test addition with small number + let small = SignedElement::from(10u64); + + // Adding small to positive large + let result = pos_large + small; + assert!(!result.is_negative()); + + // Adding small to negative large + let result = neg_large + small; + // Should still be negative since |large| > |small| + assert!(result.is_negative()); + + // Test subtraction with small number + let result = pos_large - small; + // Still positive + assert!(!result.is_negative()); + + let result = neg_large - small; + // Still negative and absolute value increased + assert!(result.is_negative()); + + // Test with reasonable multiplication + let small_multiplier = SignedElement::from(2u64); + + let result = pos_large / small_multiplier; + assert!(!result.is_negative()); + + let result = neg_large / small_multiplier; + assert!(result.is_negative()); + + // Test with sign-changing multiplication + let neg_one = SignedElement::from(-1i64); + + let result = pos_large * neg_one; + assert!(result.is_negative()); + + let result = neg_large * neg_one; + assert!(!result.is_negative()); + } + + #[test] + fn test_safe_arithmetic() { + // Test with values that won't overflow + let a = SignedElement::from(i64::MAX); + let b = SignedElement::from(i64::MIN); + + // Test negation + assert_eq!(-a, SignedElement::from(-i64::MAX)); + // Note: -i64::MIN would overflow in i64, but works in our bigger type + assert!(!(-b).is_negative()); + + // Test addition + let result = a + a; + assert!(!result.is_negative()); + + let result = b + b; + assert!(result.is_negative()); + + // Test subtraction + let result = a - b; + assert!(!result.is_negative()); + + // Test multiplication + let result = a * SignedElement::from(2i64); + assert!(!result.is_negative()); + + let result = b * SignedElement::from(2i64); + assert!(result.is_negative()); + + let result = a * SignedElement::from(-1i64); + assert!(result.is_negative()); + + let result = b * SignedElement::from(-1i64); + assert!(!result.is_negative()); + + // Test with values that could overflow i64 but are fine for Element + let big_positive = SignedElement::from(u64::MAX); + let big_negative = SignedElement::new(Element::from(u64::MAX), true); + + assert!(!big_positive.is_negative()); + assert!(big_negative.is_negative()); + + // Test sign preservation with division + let result = big_positive / SignedElement::from(2u64); + assert!(!result.is_negative()); + + let result = big_negative / SignedElement::from(2u64); + assert!(result.is_negative()); + + // Test sign flipping with division + let result = big_positive / SignedElement::from(-2i64); + assert!(result.is_negative()); + + let result = big_negative / SignedElement::from(-2i64); + assert!(!result.is_negative()); + } + + #[test] + fn test_comparison_operators() { + // Test comparisons between SignedElements with different signs + let pos = SignedElement::from(5i64); + let neg = SignedElement::from(-5i64); + let zero = SignedElement::ZERO; + + // Positive vs Negative + assert!(pos > neg); + assert!(neg < pos); + assert!(pos >= neg); + assert!(neg <= pos); + assert!(pos != neg); + + // Zero vs Positive/Negative + assert!(zero > neg); + assert!(zero < pos); + assert!(zero >= neg); + assert!(zero <= pos); + assert!(zero != pos); + assert!(zero != neg); + + // Test comparisons between SignedElements with the same sign + let pos_small = SignedElement::from(3i64); + let pos_large = SignedElement::from(10i64); + let neg_small = SignedElement::from(-3i64); + let neg_large = SignedElement::from(-10i64); + + // Positive comparisons + assert!(pos_large > pos_small); + assert!(pos_small < pos_large); + assert!(pos_large >= pos_small); + assert!(pos_small <= pos_large); + assert!(pos_large != pos_small); + + // Negative comparisons (larger absolute value is smaller) + assert!(neg_large < neg_small); + assert!(neg_small > neg_large); + assert!(neg_large <= neg_small); + assert!(neg_small >= neg_large); + assert!(neg_large != neg_small); + + // Equal values + let pos_equal1 = SignedElement::from(7i64); + let pos_equal2 = SignedElement::from(7i64); + let neg_equal1 = SignedElement::from(-7i64); + let neg_equal2 = SignedElement::from(-7i64); + + assert_eq!(pos_equal1, pos_equal2); + assert!(pos_equal1 >= pos_equal2); + assert!(pos_equal1 <= pos_equal2); + assert!(pos_equal1 <= pos_equal2); + assert!(pos_equal1 >= pos_equal2); + + assert_eq!(neg_equal1, neg_equal2); + assert!(neg_equal1 >= neg_equal2); + assert!(neg_equal1 <= neg_equal2); + assert!(neg_equal1 <= neg_equal2); + assert!(neg_equal1 >= neg_equal2); + + // Test comparisons with Element + let pos_elem = SignedElement::from(15i64); + let neg_elem = SignedElement::from(-15i64); + let elem = Element::new(15); + + assert!(pos_elem == elem); + assert!(neg_elem < elem); + assert!(neg_elem <= elem); + assert!(pos_elem >= elem); + assert!(pos_elem >= elem); + assert!(pos_elem <= elem); + + // Test comparisons with u64 + let u64_val = 20u64; + let pos_u64 = SignedElement::from(20i64); + let equal_u64 = SignedElement::from(20i64); + let neg_u64 = SignedElement::from(-20i64); + let smaller_u64 = SignedElement::from(10i64); + let larger_u64 = SignedElement::from(30i64); + + assert!(pos_u64 == u64_val); + assert!(equal_u64 == u64_val); + assert!(neg_u64 < u64_val); + assert!(smaller_u64 < u64_val); + assert!(larger_u64 > u64_val); + + // Test comparisons with i64 + let i64_pos = 25i64; + let i64_neg = -25i64; + let equal_pos = SignedElement::from(25i64); + let equal_neg = SignedElement::from(-25i64); + let smaller_pos = SignedElement::from(15i64); + let smaller_neg = SignedElement::from(-15i64); + let larger_pos = SignedElement::from(35i64); + let larger_neg = SignedElement::from(-35i64); + + // Compare with positive i64 + assert!(equal_pos == i64_pos); + assert!(equal_neg < i64_pos); + assert!(smaller_pos < i64_pos); + assert!(larger_pos > i64_pos); + + // Compare with negative i64 + assert!(equal_neg == i64_neg); + assert!(equal_pos > i64_neg); + assert!(smaller_neg > i64_neg); // -15 > -25 + assert!(larger_neg < i64_neg); // -35 < -25 + } +} diff --git a/pkg/zk-primitives/src/traits.rs b/pkg/zk-primitives/src/traits.rs new file mode 100644 index 0000000..5180ed0 --- /dev/null +++ b/pkg/zk-primitives/src/traits.rs @@ -0,0 +1,5 @@ +/// Trait for types that can be converted to a byte representation. +pub trait ToBytes { + /// Convert to bytes + fn to_bytes(&self) -> Vec; +} diff --git a/pkg/zk-primitives/src/util.rs b/pkg/zk-primitives/src/util.rs new file mode 100644 index 0000000..aff9230 --- /dev/null +++ b/pkg/zk-primitives/src/util.rs @@ -0,0 +1,369 @@ +// lint-long-file-override allow-max-lines=400 +use element::Element; +use sha3::{Digest, Sha3_256}; +use web3::types::H160; + +/// Implement Serialize and Deserialize for an array of elements of a given size +#[macro_export] +macro_rules! impl_serde_for_element_array { + ($name:ident, $size:expr) => { + use ::serde::ser::SerializeSeq; + + impl ::serde::Serialize for $name { + fn serialize(&self, serializer: S) -> Result + where + S: ::serde::Serializer, + { + let mut seq = serializer.serialize_seq(Some($size))?; + for element in &self.0 { + seq.serialize_element(element)?; + } + seq.end() + } + } + + impl<'de> ::serde::Deserialize<'de> for $name { + fn deserialize(deserializer: D) -> Result + where + D: ::serde::de::Deserializer<'de>, + { + struct ArrayVisitor; + + impl<'de> ::serde::de::Visitor<'de> for ArrayVisitor { + type Value = $name; + + fn expecting( + &self, + formatter: &mut ::std::fmt::Formatter, + ) -> ::std::fmt::Result { + write!(formatter, "a sequence of {} elements", $size) + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: ::serde::de::SeqAccess<'de>, + { + let mut elements = [element::Element::default(); $size]; + for i in 0..$size { + elements[i] = seq + .next_element()? + .ok_or_else(|| ::serde::de::Error::invalid_length(i, &self))?; + } + Ok($name(elements)) + } + } + + deserializer.deserialize_seq(ArrayVisitor) + } + } + }; +} + +/// Converts a slice of bytes into a vector of Elements by splitting the bytes into 32-byte chunks. +/// Each chunk is converted to an Element using Element::from_be_bytes. +/// +/// # Arguments +/// +/// * `bytes` - A slice of bytes to be converted into Elements. +/// +/// # Returns +/// +/// A vector of Elements, where each Element is created from a 32-byte chunk of the input. +/// +/// # Panics +/// +/// Panics if the length of `bytes` is not a multiple of 32. +#[must_use] +#[inline] +pub fn bytes_to_elements(bytes: &[u8]) -> Vec { + assert!( + bytes.len().is_multiple_of(32), + "Input bytes length must be a multiple of 32" + ); + + bytes + .chunks_exact(32) + .map(|chunk| { + let chunk_array: [u8; 32] = chunk.try_into().unwrap(); + Element::from_be_bytes(chunk_array) + }) + .collect() +} + +/// Hashes a private key using SHA3-256 and returns the resulting Element. +/// +/// # Arguments +/// +/// * `private_key` - The private key to be hashed. +/// +/// # Returns +/// +/// The hashed private key as an Element. +#[must_use] +pub fn hash_private_key_for_psi(private_key: Element) -> Element { + let mut hasher = Sha3_256::new(); + hasher.update(private_key.to_be_bytes()); + let result = hasher.finalize(); + + Element::from_be_bytes(result.into()) +} + +/// Generates a note kind element from address, chain ID, and note kind format. +/// The format is big endian: +/// Returns an Element where bytes 31-32 contain the note kind format, bytes 29-30 contain the chain, and bytes 9-28 contain the address. +/// +/// # Arguments +/// +/// * `note_kind_format` - The note kind format as u8 (will be stored in 2 bytes) +/// * `chain` - The chain ID as u64 (8 bytes) +/// * `address` - The H160 address (20 bytes) +/// +/// # Returns +/// +/// An Element constructed from the big-endian byte representation. +#[must_use] +pub fn generate_note_kind_bridge_evm(chain: u64, address: H160) -> Element { + let mut bytes = [0u8; 32]; + + // Big endian format: note_kind_format in bytes 0-2, chain in bytes 2-10, address in bytes 10-30 + bytes[0..2].copy_from_slice(&(2u16).to_be_bytes()); + bytes[2..10].copy_from_slice(&chain.to_be_bytes()); + bytes[10..30].copy_from_slice(address.as_bytes()); + + Element::from_be_bytes(bytes) +} + +/// Extracts the chain identifier from a note kind element. +/// +/// The bridge note kind uses the format ``. +/// This helper copies the chain bytes (index 2 through 9) and converts them to a `u64`. +#[must_use] +pub fn extract_chain_id_from_note_kind(note_kind: Element) -> u64 { + let note_bytes = note_kind.to_be_bytes(); + let mut chain_bytes = [0u8; 8]; + chain_bytes.copy_from_slice(¬e_bytes[2..10]); + u64::from_be_bytes(chain_bytes) +} + +/// Generates a note kind element for USDC on Polygon network. +/// Uses the standard bridged asset format for USDC token on Polygon chain. +/// +/// # Returns +/// +/// An Element representing the note kind for USDC on Polygon with: +/// - note_kind_format: 2 (ETH based bridged asset) +/// - chain: 137 (Polygon) +/// - address: 0x3c499c542cef5e3811e1192ce70d8cc03d5c3359 (USDC contract address) +#[must_use] +pub fn bridged_polygon_usdc_note_kind() -> Element { + let chain = 137u64; // Polygon chain + let address = + H160::from_slice(&hex::decode("3c499c542cef5e3811e1192ce70d8cc03d5c3359").unwrap()); + + generate_note_kind_bridge_evm(chain, address) +} + +/// Generates a note kind element for USTB on Ethereum mainnet. +/// Uses the standard bridged asset format for the USTB token on Ethereum. +/// +/// # Returns +/// +/// An Element representing the note kind for USTB on Ethereum with: +/// - note_kind_format: 2 (ETH based bridged asset) +/// - chain: 1 (Ethereum Mainnet) +/// - address: 0x43415eB6ff9DB7E26A15b704e7A3eDCe97d31C4e (USTB contract address) +#[must_use] +pub fn bridged_ethereum_ustb_note_kind() -> Element { + let chain = 1u64; // Ethereum mainnet + let address = + H160::from_slice(&hex::decode("43415eb6ff9db7e26a15b704e7a3edce97d31c4e").unwrap()); + + generate_note_kind_bridge_evm(chain, address) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_generate_note_kind() { + // Test with known values + let chain = 0x1234u64; + let address = H160::from([ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + ]); + + let result = generate_note_kind_bridge_evm(chain, address); + + // Verify the structure by extracting bytes + let result_bytes = result.to_be_bytes(); + + // Check note_kind_format is in bytes 0-2 + assert_eq!(&result_bytes[0..2], &(2u16).to_be_bytes()); + + // Check chain is in bytes 2-10 + assert_eq!(&result_bytes[2..10], &chain.to_be_bytes()); + + // Check address is in bytes 10-30 + assert_eq!(&result_bytes[10..30], address.as_bytes()); + + // Check last 2 bytes are zero (padding) + assert_eq!(&result_bytes[30..32], &[0u8; 2]); + } + + #[test] + fn test_generate_note_kind_zero_values() { + let chain = 0x0000u64; + let address = H160::zero(); + + let result = generate_note_kind_bridge_evm(chain, address); + let result_bytes = result.to_be_bytes(); + + // Check note_kind_format is in bytes 0-2 + assert_eq!(&result_bytes[0..2], &(2u16).to_be_bytes()); + + // Check chain is in bytes 2-10 (all zeros) + assert_eq!(&result_bytes[2..10], &[0u8; 8]); + + // Check address is in bytes 10-30 (all zeros) + assert_eq!(&result_bytes[10..30], &[0u8; 20]); + + // Check last 2 bytes are zero (padding) + assert_eq!(&result_bytes[30..32], &[0u8; 2]); + } + + #[test] + fn test_generate_note_kind_one_values() { + let chain = 0x0001u64; + let address = H160::from([ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + ]); + + let result = generate_note_kind_bridge_evm(chain, address); + let result_bytes = result.to_be_bytes(); + + // Check note_kind_format is in bytes 0-2 + assert_eq!(&result_bytes[0..2], &(2u16).to_be_bytes()); + + // Check chain is in bytes 2-10 + assert_eq!(&result_bytes[2..10], &chain.to_be_bytes()); + + // Check address is in bytes 10-30 + assert_eq!(&result_bytes[10..30], address.as_bytes()); + + // Check last 2 bytes are zero (padding) + assert_eq!(&result_bytes[30..32], &[0u8; 2]); + } + + #[test] + fn test_generate_note_kind_max_values() { + let chain = 0xFFFF_FFFF_FFFF_FFFF_u64; + let address = H160::from([0xFF; 20]); + + let result = generate_note_kind_bridge_evm(chain, address); + let result_bytes = result.to_be_bytes(); + + // Check note_kind_format is in bytes 0-2 + assert_eq!(&result_bytes[0..2], &(2u16).to_be_bytes()); + + // Check chain bytes are 0xFF + assert_eq!(&result_bytes[2..10], &[0xFF; 8]); + + // Check address bytes are 0xFF + assert_eq!(&result_bytes[10..30], &[0xFF; 20]); + + // Check last 2 bytes are zero (padding) + assert_eq!(&result_bytes[30..32], &[0u8; 2]); + } + + #[test] + fn test_generate_note_kind_byte_order() { + // Test that chain bytes are stored in big endian + let chain = 0x0123_4567_89AB_CDEF_u64; + let address = H160::zero(); + + let result = generate_note_kind_bridge_evm(chain, address); + let result_bytes = result.to_be_bytes(); + + // In big endian, chain should match the to_be_bytes output + let expected_chain_bytes = chain.to_be_bytes(); + assert_eq!(&result_bytes[2..10], &expected_chain_bytes); + } + + #[test] + fn test_bridged_polygon_usdc_note_kind() { + let result = bridged_polygon_usdc_note_kind(); + let result_bytes = result.to_be_bytes(); + + println!("{:?}", result.to_hex()); + + // Check note_kind_format is in bytes 0-2 + assert_eq!(&result_bytes[0..2], &(2u16).to_be_bytes()); + + // Check chain is in bytes 2-10 (big endian) + // 137 (Polygon) = 0x89, so as u64 big endian = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89] + let expected_chain_bytes = 137u64.to_be_bytes(); + assert_eq!(&result_bytes[2..10], &expected_chain_bytes); + + // Check address is in bytes 10-30 + let expected_address_bytes = + hex::decode("3c499c542cef5e3811e1192ce70d8cc03d5c3359").unwrap(); + assert_eq!(&result_bytes[10..30], &expected_address_bytes[..]); + + // Check last 2 bytes are zero (padding) + assert_eq!(&result_bytes[30..32], &[0u8; 2]); + } + + #[test] + fn test_bridged_ethereum_ustb_note_kind() { + let result = bridged_ethereum_ustb_note_kind(); + + // Snapshot of expected hex encoding for USTB on Ethereum. + let hex_value = format!("0x{}", result.to_hex()); + assert_eq!( + hex_value, + "0x0002000000000000000143415eb6ff9db7e26a15b704e7a3edce97d31c4e0000" + ); + + let result_bytes = result.to_be_bytes(); + + // Check chain is Ethereum mainnet (1) + let expected_chain_bytes = 1u64.to_be_bytes(); + assert_eq!(&result_bytes[2..10], &expected_chain_bytes); + + // Check address is encoded correctly + let expected_address_bytes = + hex::decode("43415eb6ff9db7e26a15b704e7a3edce97d31c4e").unwrap(); + assert_eq!(&result_bytes[10..30], &expected_address_bytes[..]); + + // Check padding + assert_eq!(&result_bytes[30..32], &[0u8; 2]); + } + + #[test] + fn test_extract_chain_id_from_note_kind() { + let chain = 137u64; + let address = + H160::from_slice(&hex::decode("3c499c542cef5e3811e1192ce70d8cc03d5c3359").unwrap()); + let note_kind = generate_note_kind_bridge_evm(chain, address); + + assert_eq!(extract_chain_id_from_note_kind(note_kind), chain); + } + + #[test] + fn test_extract_chain_id_from_note_kind_zero_chain() { + let note_kind = generate_note_kind_bridge_evm(0, H160::zero()); + + assert_eq!(extract_chain_id_from_note_kind(note_kind), 0); + } + + #[test] + fn test_extract_chain_id_from_note_kind_max_chain() { + let chain = u64::MAX; + let note_kind = generate_note_kind_bridge_evm(chain, H160::zero()); + + assert_eq!(extract_chain_id_from_note_kind(note_kind), chain); + } +} diff --git a/pkg/zk-primitives/src/utxo.rs b/pkg/zk-primitives/src/utxo.rs new file mode 100644 index 0000000..cd6cf6a --- /dev/null +++ b/pkg/zk-primitives/src/utxo.rs @@ -0,0 +1,437 @@ +// lint-long-file-override allow-max-lines=600 +use std::fmt::Debug; + +use crate::impl_serde_for_element_array; +use crate::{InputNote, Note, ProofBytes}; +use borsh::{BorshDeserialize, BorshSerialize}; +use element::{Base, Element}; +use hash::hash_merge; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "ts-rs")] +use ts_rs::TS; + +/// Number of public input fields for utxo proof +pub const UTXO_PUBLIC_INPUTS_COUNT: usize = 9; +/// Number of fields in the proof +pub const UTXO_PROOF_SIZE: usize = 508; + +/// Utxo is the data required to prove a utxo transaction +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Utxo { + /// The kind of transaction + pub kind: UtxoKind, + /// The input notes (being spent) + pub input_notes: [InputNote; 2], + /// The output notes (being created) + pub output_notes: [Note; 2], + /// The burn address + pub burn_address: Option, +} + +impl Utxo { + /// Creates a new utxo txn + #[must_use] + pub fn new( + kind: UtxoKind, + input_notes: [InputNote; 2], + output_notes: [Note; 2], + burn_address: Option, + ) -> Self { + Self { + kind, + input_notes, + output_notes, + burn_address, + } + } + + /// Create a new send transaction + #[must_use] + pub fn new_send(input_notes: [InputNote; 2], output_notes: [Note; 2]) -> Self { + Self { + kind: UtxoKind::Send, + input_notes, + output_notes, + burn_address: None, + } + } + + /// Create a new burn transaction + #[must_use] + pub fn new_burn(input_notes: [InputNote; 2], evm_address: Element) -> Self { + Self { + kind: UtxoKind::Burn, + input_notes, + output_notes: [Note::padding_note(), Note::padding_note()], + burn_address: Some(evm_address), + } + } + + /// Create a new mint transaction + #[must_use] + pub fn new_mint(output_notes: [Note; 2]) -> Self { + Self { + kind: UtxoKind::Mint, + burn_address: None, + input_notes: [InputNote::padding_note(), InputNote::padding_note()], + output_notes, + } + } + + /// Get the leaf elements for the Utxo transaction, these will be inserted + /// or removed from the tree + #[must_use] + pub fn leaf_elements(&self) -> [Element; 4] { + [ + self.input_notes[0].note.commitment(), + self.input_notes[1].note.commitment(), + self.output_notes[0].commitment(), + self.output_notes[1].commitment(), + ] + } + + /// Get the messages for the Utxo transaction + #[must_use] + pub fn messages(&self) -> [Element; 5] { + match self.kind { + UtxoKind::Send => [ + Element::new(1), + Element::ZERO, + Element::ZERO, + Element::ZERO, + Element::ZERO, + ], + UtxoKind::Mint => [ + Element::new(2), + self.output_notes[0].contract, + self.output_value() - self.input_value(), + self.mint_hash(), + Element::ZERO, + ], + UtxoKind::Burn => [ + Element::new(3), + self.input_notes[0].note.contract, + self.input_value() - self.output_value(), + self.burn_hash(), + self.burn_address.unwrap(), + ], + UtxoKind::Null => [ + Element::ZERO, + Element::ZERO, + Element::ZERO, + Element::ZERO, + Element::ZERO, + ], + } + } + + /// Get the mint hash + #[must_use] + pub fn mint_hash(&self) -> Element { + hash_merge([self.output_notes[0].psi, self.output_notes[1].psi]) + } + + /// Get the burn hash + #[must_use] + pub fn burn_hash(&self) -> Element { + self.input_notes[0].note.commitment() + } + + /// Get the input value for the Utxo transaction + #[must_use] + pub fn input_value(&self) -> Element { + self.input_notes[0].note.value + self.input_notes[1].note.value + } + + /// Get the output value for the Utxo transaction + #[must_use] + pub fn output_value(&self) -> Element { + self.output_notes[0].value + self.output_notes[1].value + } + + /// Get the public inputs for the Utxo transaction + #[must_use] + pub fn public_inputs(&self) -> UtxoPublicInput { + UtxoPublicInput { + input_commitments: [ + self.input_notes[0].note.commitment(), + self.input_notes[1].note.commitment(), + ], + output_commitments: [ + self.output_notes[0].commitment(), + self.output_notes[1].commitment(), + ], + messages: self.messages(), + } + } + + /// Create a new padding Utxo + #[must_use] + pub fn new_padding() -> Self { + Self { + kind: UtxoKind::Null, + input_notes: [InputNote::padding_note(), InputNote::padding_note()], + output_notes: [Note::padding_note(), Note::padding_note()], + burn_address: None, + } + } + + /// Returns true if the Utxo is a padding Utxo + #[must_use] + pub fn is_padding(&self) -> bool { + self.kind == UtxoKind::Null + } +} + +/// The kind of Utxo transaction +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub enum UtxoKind { + /// A null transaction (padding UTXO) + Null, + /// Send a note (of the same token) to another address + Send, + /// A mint transaction (minting on Payy Network) + Mint, + /// A burn transaction (burning on Payy Network) + Burn, +} + +impl UtxoKind { + /// Convert the UtxoKind to an Element + #[must_use] + pub fn to_element(&self) -> Element { + Element::from(u8::from(*self)) + } +} + +impl From for UtxoKind { + fn from(value: u8) -> Self { + match value { + 1 => UtxoKind::Send, + 2 => UtxoKind::Mint, + 3 => UtxoKind::Burn, + _ => UtxoKind::Null, + } + } +} + +impl From for u8 { + fn from(value: UtxoKind) -> Self { + match value { + UtxoKind::Send => 1, + UtxoKind::Mint => 2, + UtxoKind::Burn => 3, + UtxoKind::Null => 0, + } + } +} + +impl From for UtxoKind { + fn from(value: Element) -> Self { + value.to_u256().as_u8().into() + } +} + +/// The public input for a Utxo transaction +#[derive( + Default, Debug, Clone, Eq, PartialEq, Serialize, Deserialize, BorshSerialize, BorshDeserialize, +)] +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +pub struct UtxoPublicInput { + /// The input commitments + #[cfg_attr(feature = "ts-rs", ts(as = "[String; 2]"))] + pub input_commitments: [Element; 2], + /// The output commitments + #[cfg_attr(feature = "ts-rs", ts(as = "[String; 2]"))] + pub output_commitments: [Element; 2], + /// The message of the transaction + #[cfg_attr(feature = "ts-rs", ts(as = "[String; 5]"))] + pub messages: [Element; 5], +} + +impl UtxoPublicInput { + /// Fields + #[must_use] + pub fn fields(&self) -> [Element; 9] { + [ + self.input_commitments[0], + self.input_commitments[1], + self.output_commitments[0], + self.output_commitments[1], + self.messages[0], + self.messages[1], + self.messages[2], + self.messages[3], + self.messages[4], + ] + } + + /// Get the commitments for the UtxoPublicInput + #[must_use] + pub fn commitments(&self) -> [Element; 4] { + [ + self.input_commitments[0], + self.input_commitments[1], + self.output_commitments[0], + self.output_commitments[1], + ] + } + + /// Get the commit hash for the Utxo proof + #[must_use] + pub fn commit_hash(&self) -> Element { + hash_merge(self.commitments()) + } + + /// Hash the UtxoProof + #[must_use] + pub fn hash(&self) -> Element { + hash::hash_merge(self.fields()) + } + + /// Get the kind of the UtxoProof + #[must_use] + pub fn kind(&self) -> UtxoKind { + // Get the kind from the first byte of the first message + let msg_bytes = self.messages[0].to_be_bytes(); + let kind = msg_bytes[31]; + UtxoKind::from(kind) + } + + /// Get the kind messages associated with the kind + #[must_use] + pub fn kind_messages(&self) -> UtxoKindMessages { + match self.kind() { + UtxoKind::Null | UtxoKind::Send => UtxoKindMessages::None, + UtxoKind::Mint => UtxoKindMessages::Mint(UtxoKindMintMessages { + note_kind: self.messages[1], + value: self.messages[2], + mint_hash: self.messages[3], + }), + UtxoKind::Burn => UtxoKindMessages::Burn(UtxoKindBurnMessages { + note_kind: self.messages[1], + value: self.messages[2], + burn_hash: self.messages[3], + burn_address: self.messages[4], + }), + } + } + + /// Gets the hash of the mint/burn, otherwise None + #[must_use] + pub fn mint_burn_hash(&self) -> Option { + match self.kind_messages() { + UtxoKindMessages::Mint(mint) => Some(mint.mint_hash), + UtxoKindMessages::Burn(burn) => Some(burn.burn_hash), + UtxoKindMessages::None => None, + } + } +} + +/// Kind messages for each Utxo kind +#[derive(Debug, Clone)] +pub enum UtxoKindMessages { + /// No relevant messages + None, + /// Burn messages + Burn(UtxoKindBurnMessages), + /// Mint messages + Mint(UtxoKindMintMessages), +} + +/// Structured messages for burn +#[derive(Debug, Clone)] +pub struct UtxoKindBurnMessages { + /// Kind of note (USDC, etc) + pub note_kind: Element, + /// Value of the note + pub value: Element, + /// Hash of the burn + pub burn_hash: Element, + /// EVM Address to send funds to + pub burn_address: Element, +} + +/// Structured messages for mint +#[derive(Debug, Clone)] +pub struct UtxoKindMintMessages { + /// Kind of note (USDC, etc) + pub note_kind: Element, + /// Value of the note + pub value: Element, + /// Hash of the mint + pub mint_hash: Element, +} + +/// Proof as field elements (instead of bytes) +#[derive(Debug, Clone)] +pub struct UtxoProofFields(pub [Element; 93]); +impl_serde_for_element_array!(UtxoProofFields, 93); + +impl From for [Base; 93] { + fn from(value: UtxoProofFields) -> Self { + value.0.map(|e| e.to_base()) + } +} + +impl From<[Base; 93]> for UtxoProofFields { + fn from(elements: [Base; 93]) -> Self { + UtxoProofFields(elements.map(Element::from_base)) + } +} + +/// The output proof for a Utxo transaction +#[cfg_attr(feature = "ts-rs", derive(TS))] +#[cfg_attr(feature = "ts-rs", ts(export))] +#[derive(Default, Debug, Clone, Serialize, Deserialize, BorshSerialize, BorshDeserialize)] +pub struct UtxoProof { + /// The proof for the Utxo transaction + #[cfg_attr(feature = "ts-rs", ts(type = "string"))] + pub proof: ProofBytes, + /// The public input for the Utxo transaction + pub public_inputs: UtxoPublicInput, +} + +impl PartialEq for UtxoProof { + fn eq(&self, other: &Self) -> bool { + self.public_inputs == other.public_inputs + } +} + +impl Eq for UtxoProof {} + +impl UtxoProof { + /// Hash the UtxoProof, can be used to uniquely identify the UtxoProof + #[must_use] + pub fn hash(&self) -> Element { + self.public_inputs.hash() + } + + /// Get the mint/burn hash of the Utxo transaction + #[must_use] + pub fn kind_messages(&self) -> UtxoKindMessages { + self.public_inputs.kind_messages() + } + + /// Get the kind of the Utxo transaction + #[must_use] + pub fn kind(&self) -> UtxoKind { + self.public_inputs.kind() + } + + /// Gets the hash of the mint/burn, otherwise None + #[must_use] + pub fn mint_burn_hash(&self) -> Option { + self.public_inputs.mint_burn_hash() + } + + /// Returns true if the Utxo is a padding Utxo + #[must_use] + pub fn is_padding(&self) -> bool { + self.public_inputs.kind() == UtxoKind::Null + } +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fb56cda..fdfacc4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-01-04" -components = ["clippy"] +channel = "1.91.0" +components = ["clippy", "rustfmt"] diff --git a/scripts/check-file-length.sh b/scripts/check-file-length.sh new file mode 100755 index 0000000..c7bf057 --- /dev/null +++ b/scripts/check-file-length.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +set -euo pipefail + +ROOT_DIR="$(git rev-parse --show-toplevel)" +TARGET_DIR="$ROOT_DIR/pkg" +DEFAULT_LIMIT=200 +OVERRIDE_PATTERN='^[[:space:]]*//[[:space:]]*lint-long-file-override[[:space:]]+allow-max-lines[[:space:]]*=[[:space:]]*([0-9]+)' + +if [[ ! -d "$TARGET_DIR" ]]; then + echo "pkg directory not found at $TARGET_DIR" >&2 + exit 1 +fi + +violations=() + +# Track whether we discovered any Rust files without relying on mapfile (which +# is unavailable on macOS's default bash 3.2). +found_files=0 + +while IFS= read -r file; do + found_files=1 + + limit=$DEFAULT_LIMIT + + if head -n 1 "$file" | grep -Eq '^//[[:space:]]*@generated'; then + continue + fi + + override_line="$(head -n 20 "$file" | grep -E "$OVERRIDE_PATTERN" || true)" + if [[ -n "$override_line" ]]; then + if [[ $override_line =~ $OVERRIDE_PATTERN ]]; then + limit="${BASH_REMATCH[1]}" + fi + fi + + line_count=$(wc -l < "$file") + # Trim whitespace that wc emits + line_count="${line_count//[[:space:]]/}" + + if [[ "$line_count" =~ ^[0-9]+$ ]] && [[ "$limit" =~ ^[0-9]+$ ]]; then + if (( line_count > limit )); then + relative_path="${file#$ROOT_DIR/}" + violations+=("$relative_path has $line_count lines (limit $limit)") + fi + else + echo "Unable to determine line limit or count for $file" >&2 + exit 1 + fi + +done < <(find "$TARGET_DIR" -type f -name '*.rs' -print | sort) + +if [[ $found_files -eq 0 ]]; then + echo "No Rust files found under pkg/." + exit 0 +fi + +if [[ ${#violations[@]} -ne 0 ]]; then + echo "❌ File length check failed. The following files exceed their configured limits:" + echo "" + for violation in "${violations[@]}"; do + echo "- $violation" + done + echo "" + echo "Primary hint: Refactor large files to reduce their length." + echo "Secondary hint: If the additional length is justified, add an override comment at the top of the file." + echo " Example override comment: '// lint-long-file-override allow-max-lines=300' to bump the limit to 300 lines" + echo " Bump the limits in increments of 100." + echo "" + exit 1 +fi + +echo "✅ All Rust files in pkg/ comply with the file length limits." diff --git a/scripts/conductor-setup.sh b/scripts/conductor-setup.sh new file mode 100755 index 0000000..f0f9ae2 --- /dev/null +++ b/scripts/conductor-setup.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -euo pipefail + +cd "$(dirname "$0")/.." + +if ! command -v cargo >/dev/null 2>&1; then + echo "cargo is required to run workspace setup" >&2 + exit 1 +fi + +echo "Running cargo xtask setup..." +eval "$(cargo xtask setup)" diff --git a/scripts/download-fixtures-params.sh b/scripts/download-fixtures-params.sh new file mode 100755 index 0000000..e80795c --- /dev/null +++ b/scripts/download-fixtures-params.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +set -euo pipefail + +PARAMS_URL="https://storage.googleapis.com/payy-public-fixtures/g1.max.dat" +PARAMS_SHA256="3ef417367184adaf0dcdebfccc440b5bb72f9a228b278f17d1411b1340f2daa5" +PARAMS_CACHE_DIR="${POLYBASE_PARAMS_DIR:-$HOME/.polybase/fixtures/params}" +CACHE_TARGET="$PARAMS_CACHE_DIR/g1.max.dat" +BB_CRS_DIR="${BB_CRS_DIR:-$HOME/.bb-crs}" +BB_CRS_TARGET="$BB_CRS_DIR/bn254_g1.dat" + +mkdir -p "$PARAMS_CACHE_DIR" +mkdir -p "$BB_CRS_DIR" + +sha256_file() { + local target="$1" + + if command -v sha256sum >/dev/null 2>&1; then + sha256sum "$target" | cut -d' ' -f1 + return + fi + + shasum -a 256 "$target" | cut -d' ' -f1 +} + +verify_sha256() { + local target="$1" + local actual + + actual=$(sha256_file "$target") + + if [[ "$actual" != "$PARAMS_SHA256" ]]; then + echo "Checksum mismatch for $target (expected $PARAMS_SHA256, got $actual)" >&2 + return 1 + fi +} + +if [[ -f "$CACHE_TARGET" ]] && ! verify_sha256 "$CACHE_TARGET"; then + rm -f "$CACHE_TARGET" + rm -f "$BB_CRS_TARGET" +fi + +if [[ ! -f "$CACHE_TARGET" ]]; then + TMP_FILE=$(mktemp) + trap 'rm -f "$TMP_FILE"' EXIT + + echo "Downloading params from $PARAMS_URL" >&2 + curl -fsSL "$PARAMS_URL" -o "$TMP_FILE" + + if ! verify_sha256 "$TMP_FILE"; then + exit 1 + fi + + mv "$TMP_FILE" "$CACHE_TARGET" +fi + +echo "Params available at $CACHE_TARGET" + +if [[ -L "$BB_CRS_TARGET" ]]; then + rm -f "$BB_CRS_TARGET" +fi + +if [[ ! -e "$BB_CRS_TARGET" ]]; then + ln -s "$CACHE_TARGET" "$BB_CRS_TARGET" + echo "Linked $CACHE_TARGET to $BB_CRS_TARGET" +fi

{ + pub fn verify_signature(&self) -> Result<()> { + // Check the signature is valid + // TODO: the signature should verify the entire accept, not just the proposal hash + + if !ProposalAcceptSigData::new(self.proposal.clone(), self.skips) + .verify(&self.from, &self.signature) + { + return Err(Error::InvalidAcceptSignature); + } + + Ok(()) + } +} diff --git a/pkg/solid/src/proposal/cache.rs b/pkg/solid/src/proposal/cache.rs new file mode 100644 index 0000000..de5f8e9 --- /dev/null +++ b/pkg/solid/src/proposal/cache.rs @@ -0,0 +1,469 @@ +// lint-long-file-override allow-max-lines=500 +use crate::{ + proposal::{Proposal, ProposalHash}, + traits::App, +}; +use std::cmp::Ordering; +use std::collections::HashMap; + +/// Responsible for storing proposals temporarily in the cache. +/// Provides untility methods for easily traversing proposals. +#[derive(Debug)] +pub struct ProposalCache { + /// Hash of last confirmed proposal, we can work backwards from here to get + /// all other confirmed proposals in the cache. + pub(crate) last_confirmed_proposal_hash: ProposalHash, + + /// List of proposals cached in memory + proposals: HashMap>, + + /// Config for the proposal cache + cache_size: u64, +} + +impl ProposalCache { + pub fn new(last_confirmed_proposal: Proposal, cache_size: u64) -> Self { + let proposal_hash = last_confirmed_proposal.hash().clone(); + let mut proposals = HashMap::new(); + + // Add last confirmed proposal to pending proposals + proposals.insert(proposal_hash.clone(), last_confirmed_proposal); + + ProposalCache { + last_confirmed_proposal_hash: proposal_hash, + proposals, + cache_size, + } + } + + /// Confirmed height + pub fn height(&self) -> u64 { + // We can use unwrap because last_confirmed_proposal_hash must always be set + #[allow(clippy::unwrap_used)] + self.proposals + .get(&self.last_confirmed_proposal_hash) + .unwrap() + .height() + } + + #[cfg(test)] + fn len(&self) -> u64 { + self.proposals.len() as u64 + } + + /// Check if a proposal exists in the cache + pub fn contains(&self, hash: &ProposalHash) -> bool { + self.proposals.contains_key(hash) + } + + /// Insert a proposal into the cache + pub fn insert(&mut self, proposal: Proposal) { + self.proposals.insert(proposal.hash().clone(), proposal); + } + + /// Get a proposal by hash (mutable) + pub fn get_mut(&mut self, proposal_hash: &ProposalHash) -> Option<&mut Proposal> { + self.proposals.get_mut(proposal_hash) + } + + /// Get a proposal + pub fn get(&self, proposal_hash: &ProposalHash) -> Option<&Proposal> { + self.proposals.get(proposal_hash) + } + + // Remove a proposal + pub fn remove(&mut self, proposal_hash: &ProposalHash) -> Option> { + self.proposals.remove(proposal_hash) + } + + /// Get the last confirmed proposal + pub fn last_confirmed_proposal(&self) -> &Proposal { + // We can use unwrap because last_confirmed_proposal_hash must always be set + #[allow(clippy::unwrap_used)] + self.proposals + .get(&self.last_confirmed_proposal_hash) + .unwrap() + } + + /// Returns all confirmed proposals from height to confirmed proposal + pub fn proposals_from(&self, from_height: u64) -> Vec<&Proposal> { + self.proposals + .values() + .filter(|p| p.height() >= from_height) + .collect() + } + + /// Returns all confirmed proposals from height to confirmed proposal + pub fn confirmed_proposals_from(&self, from_height: u64) -> Vec<&Proposal> { + // Start with the last confirmed proposal and work backwards + // We can use unwrap because last_confirmed_proposal_hash must always be set + #[allow(clippy::unwrap_used)] + let mut proposal = self + .proposals + .get(&self.last_confirmed_proposal_hash) + .unwrap(); + + let mut proposals = vec![proposal]; + + // Loop through to get the next proposal by looking at the chain of proposals + while proposal.height() >= from_height { + if let Some(p) = self.proposals.get(proposal.last_hash()) { + proposals.push(p); + proposal = p + } else { + return proposals; + } + } + + proposals + } + + /// Next pending proposal to be processed (`confirmed height + 1 + offset`). + /// If there are a no pending commits for a given offset + /// then None is returned. Offset can be used to get + /// proposals higher up the chain. This is usually only used with a value of `0` or `1`. + /// - `0`: next proposal (used to send accept) + /// - `1`: proposal after next proposal (used to confirm the next proposal) + pub fn next_pending_proposal(&self, offset: u64) -> Option<&Proposal> { + // Get the first next proposal, by looking for an unconfirmed proposal with the highest height + // and skip + let mut proposal = self.max_continuous_proposal()?; + + // Max proposal is not higher than requested (minimum is always height + 1, as we + // are looking for the next proposal) + if proposal.height() < self.height() + 1 + offset { + return None; + } + + // Loop through to get the next proposal by looking at the chain of proposals + while proposal.height() > self.height() + 1 + offset { + proposal = self.proposals.get(proposal.last_hash())?; + } + + Some(proposal) + } + + /// Max proposal that decends to the last confirmed proposal + fn max_continuous_proposal(&self) -> Option<&Proposal> { + // Get the last confirmed, so we can check if an unconfirmed proposal is a parent of the + // last confirmed proposal + let last_confirmed = &self.last_confirmed_proposal_hash; + let from_height = self.height(); + + self.proposals + .values() + .filter(|proposal| { + proposal.height() > from_height + && self.is_decendent(last_confirmed, proposal.hash()) + }) + .max_by(|a, b| { + (a.height(), a.skips()) + .partial_cmp(&(b.height(), b.skips())) + .unwrap_or(std::cmp::Ordering::Equal) + }) + } + + /// Confirm a proposal, all subsequent proposals must now + /// include this proposal in the tree. + pub fn confirm(&mut self, proposal_hash: ProposalHash) { + self.last_confirmed_proposal_hash = proposal_hash; + self.purge(); + } + + /// Check if a hash is a decendent of another hash + fn is_decendent(&self, decendent_hash: &ProposalHash, parent_hash: &ProposalHash) -> bool { + let mut proposal = match self.proposals.get(parent_hash) { + Some(p) => p, + None => return false, + }; + + loop { + if proposal.hash() == decendent_hash { + return true; + } + + let next_decendent = match self.proposals.get(proposal.last_hash()) { + Some(p) => p, + None => return false, + }; + + // Check the decendent is one level higher than the parent + if next_decendent.height() + 1 != proposal.height() { + return false; + } + + proposal = next_decendent + } + } + + /// Get decendents from a parent to a specified decendent (not including the specified decendent). + /// Ordered from parent to decendent + pub fn decendents( + &self, + decendent_hash: &ProposalHash, + parent_hash: &ProposalHash, + ) -> Vec<&Proposal> { + // Get the first proposal + let mut proposal = match self.proposals.get(parent_hash) { + Some(p) => p, + None => return vec![], + }; + + let mut proposals = vec![]; + + // Loop through to get the next proposal by looking at the chain of proposals + // until we reach the decendent + loop { + if proposal.hash() == decendent_hash { + return proposals; + } + + proposals.push(proposal); + + proposal = match self.proposals.get(proposal.last_hash()) { + Some(p) => p, + None => return vec![], + }; + } + } + + /// Remove redundant proposals from the cache + fn purge(&mut self) { + let confirmed_height = self.height(); + let confirmed_hash = self.last_confirmed_proposal_hash.clone(); + + let keys_to_remove = self + .proposals + .iter() + .filter(|(_, p)| match confirmed_height.partial_cmp(&p.height()) { + Some(Ordering::Greater) => { + if p.height() + (self.cache_size) < confirmed_height { + return true; + } + false + } + Some(Ordering::Less) => !self.is_decendent(&confirmed_hash, p.hash()), + Some(Ordering::Equal) => p.hash() != &self.last_confirmed_proposal_hash, + None => true, + }) + .map(|(k, _)| k.clone()) + .collect::>(); + + for key in keys_to_remove { + self.proposals.remove(&key); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::proposal::{Manifest, ManifestContent, ProposalHash}; + use crate::test::app::{TestApp, UncheckedPeerId as PeerId}; + + fn create_peers() -> [PeerId; 3] { + let p1 = PeerId::new(vec![1u8]); + let p2 = PeerId::new(vec![2u8]); + let p3 = PeerId::new(vec![3u8]); + [p1, p2, p3] + } + + fn create_proposal( + height: u64, + skips: u64, + last_proposal_hash: ProposalHash, + ) -> (Proposal, ProposalHash) { + let m = Manifest::new( + ManifestContent { + last_proposal_hash, + height, + skips, + leader_id: PeerId::new(vec![1u8]), + state: 0.into(), + validators: create_peers().to_vec(), + accepts: vec![], + }, + vec![], + ); + let m_hash = TestApp::hash(&m); + (Proposal::new(m), m_hash) + } + + #[test] + fn test_new_cache() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let cache = ProposalCache::new(genesis.clone(), 1000); + + assert_eq!(cache.len(), 1); + assert_eq!(cache.height(), 0); + assert_eq!(cache.last_confirmed_proposal(), &genesis); + assert!(cache.contains(&genesis_hash), "contains genesis hash"); + } + + #[test] + fn test_insert() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let mut cache = ProposalCache::new(genesis, 1000); + + let (p1, _) = create_proposal(1, 0, genesis_hash); + cache.insert(p1); + + assert_eq!(cache.len(), 2); + assert_eq!(cache.height(), 0); + } + + #[test] + fn test_confirm_proposal() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let mut cache = ProposalCache::new(genesis, 1000); + + let (p1, p1_hash) = create_proposal(1, 0, genesis_hash); + cache.insert(p1.clone()); + cache.confirm(p1_hash); + + assert_eq!(cache.len(), 2); + assert_eq!(cache.height(), 1); + assert_eq!(cache.last_confirmed_proposal(), &p1); + } + + #[test] + fn test_is_decendent() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let mut cache = ProposalCache::new(genesis, 1000); + + let (p1, p1_hash) = create_proposal(1, 0, genesis_hash.clone()); + let (p2, p2_hash) = create_proposal(2, 0, p1_hash.clone()); + let (p3, p3_hash) = create_proposal(3, 0, genesis_hash.clone()); + cache.insert(p1); + cache.insert(p2); + cache.insert(p3); + + assert!( + cache.is_decendent(&genesis_hash, &p2_hash), + "genesis is decendent of p2" + ); + + assert!( + !cache.is_decendent(&genesis_hash, &p3_hash), + "genesis is decendent of p3" + ); + + assert!( + !cache.is_decendent(&p2_hash, &genesis_hash), + "p2 is not decendent of genesis" + ); + + assert!( + !cache.is_decendent(&p1_hash, &p3_hash), + "p1 not is decendent of p3" + ); + } + + #[test] + fn test_purge_proposals() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let mut cache = ProposalCache::new(genesis, 1000); + + let (p1a, p1a_hash) = create_proposal(1, 0, genesis_hash); + let (p1b, p1b_hash) = create_proposal(1, 1, ProposalHash::from_vec_hash(vec![1u8])); + // let (p2a, p2a_hash) = create_proposal(2, 0, p1_hash.clone()); + // let (p2b, p2b_hash) = create_proposal(2, 1, p1_hash); + + cache.insert(p1a); + cache.insert(p1b); + + assert_eq!(cache.len(), 3); + + cache.purge(); + + assert_eq!(cache.len(), 2); + assert!(cache.contains(&p1a_hash), "p1a should not be purged"); + assert!(!cache.contains(&p1b_hash), "p1b should be purged"); + + let mut last_hash = p1a_hash; + for i in 2..1010 { + let (p, h) = create_proposal(i, 0, last_hash); + last_hash = h.clone(); + cache.insert(p); + } + + cache.confirm(last_hash); + + assert_eq!(cache.len(), 1001); + } + + #[test] + fn test_next_pending_proposal() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let mut cache = ProposalCache::new(genesis, 1000); + + let (p1, p1_hash) = create_proposal(1, 0, genesis_hash); + let (p2a, p2a_hash) = create_proposal(2, 0, p1_hash.clone()); + let (p2b, p2b_hash) = create_proposal(2, 1, p1_hash); + let (p3a, _) = create_proposal(3, 0, p2a_hash.clone()); + let (p3b, _) = create_proposal(3, 1, p2b_hash); + + cache.insert(p1.clone()); + cache.insert(p2a); + cache.insert(p2b); + cache.insert(p3a.clone()); + cache.insert(p3b); + + assert_eq!(cache.len(), 6); + assert_eq!(cache.height(), 0); + assert_eq!(cache.next_pending_proposal(0), Some(&p1)); + + cache.confirm(p2a_hash); + + assert_eq!(cache.next_pending_proposal(0), Some(&p3a)); + } + + #[test] + fn test_next_pending_proposal_invalid_decendent() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let mut cache = ProposalCache::new(genesis, 1000); + + let (p1_0, p1_0_hash) = create_proposal(1, 0, genesis_hash); + + // Incorrect decendent, so should be ignored + let (p1_1, _) = create_proposal(1, 1, p1_0_hash); + + cache.insert(p1_0.clone()); + cache.insert(p1_1); + + assert_eq!(cache.len(), 3); + assert_eq!(cache.height(), 0); + assert_eq!(cache.next_pending_proposal(0), Some(&p1_0)); + } + + #[test] + fn test_next_pending_proposal_no_pending() { + let (genesis, _) = create_proposal(0, 0, ProposalHash::genesis()); + let cache = ProposalCache::new(genesis, 1000); + + assert_eq!(cache.len(), 1); + assert_eq!(cache.height(), 0); + assert_eq!(cache.next_pending_proposal(0), None); + } + + #[test] + fn test_next_pending_proposal_with_offset() { + let (genesis, genesis_hash) = create_proposal(0, 0, ProposalHash::genesis()); + let mut cache = ProposalCache::new(genesis, 1000); + + let (p1, p1_hash) = create_proposal(1, 0, genesis_hash); + let (p2, p2_hash) = create_proposal(2, 0, p1_hash); + let (p3, _) = create_proposal(3, 0, p2_hash); + + cache.insert(p1.clone()); + cache.insert(p2.clone()); + cache.insert(p3.clone()); + + assert_eq!(cache.len(), 4); + assert_eq!(cache.height(), 0); + assert_eq!(cache.next_pending_proposal(0), Some(&p1)); + assert_eq!(cache.next_pending_proposal(1), Some(&p2)); + assert_eq!(cache.next_pending_proposal(2), Some(&p3)); + assert_eq!(cache.next_pending_proposal(3), None); + } +} diff --git a/pkg/solid/src/proposal/hash.rs b/pkg/solid/src/proposal/hash.rs new file mode 100644 index 0000000..2e411d5 --- /dev/null +++ b/pkg/solid/src/proposal/hash.rs @@ -0,0 +1,53 @@ +use crate::util::u256; +use borsh::{BorshDeserialize, BorshSerialize}; +use sha2::{Digest, Sha256}; +use std::borrow::Borrow; +use std::fmt::{Debug, Display}; + +#[derive(Clone, Default, PartialEq, Eq, Hash, BorshSerialize, BorshDeserialize)] +pub struct ProposalHash([u8; 32]); + +impl ProposalHash { + pub fn new(v: [u8; 32]) -> Self { + ProposalHash(v) + } + + pub fn as_u256(&self) -> u256::U256 { + u256::U256::from_little_endian(&self.0) + } + + pub fn inner(&self) -> &[u8; 32] { + &self.0 + } + + pub fn from_vec_hash(v: Vec) -> Self { + let bytes: [u8; 32] = Sha256::digest(v).into(); + ProposalHash(bytes) + } + + pub fn genesis() -> Self { + ProposalHash([0u8; 32]) + } + + pub fn to_vec(&self) -> Vec { + self.0.to_vec() + } +} + +impl Display for ProposalHash { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", hex::encode(self.0)) + } +} + +impl Debug for ProposalHash { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", hex::encode(self.0)) + } +} + +impl Borrow<[u8]> for ProposalHash { + fn borrow(&self) -> &[u8] { + &self.0 + } +} diff --git a/pkg/solid/src/proposal/header.rs b/pkg/solid/src/proposal/header.rs new file mode 100644 index 0000000..41374a7 --- /dev/null +++ b/pkg/solid/src/proposal/header.rs @@ -0,0 +1,12 @@ +use borsh::{BorshDeserialize, BorshSerialize}; + +use super::ProposalHash; + +/// ProposalHeader provides the position of the proposal in the block +/// sequence and the hash of the proposal at that sequence. +#[derive(Debug, Clone, Hash, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct ProposalHeader { + pub hash: ProposalHash, + pub height: u64, + pub skips: u64, +} diff --git a/pkg/solid/src/proposal/manifest.rs b/pkg/solid/src/proposal/manifest.rs new file mode 100644 index 0000000..80e804a --- /dev/null +++ b/pkg/solid/src/proposal/manifest.rs @@ -0,0 +1,122 @@ +use std::ops::{Deref, DerefMut}; + +use super::{ProposalAccept, ProposalHash}; +use crate::traits::{AppState, Peer}; +use crate::util::u256; +use crate::{App, PeerSigner}; +use borsh::{BorshDeserialize, BorshSerialize}; +use sha2::{Digest, Sha256}; + +#[derive(Default, Debug, Clone, Hash, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct Manifest { + pub content: ManifestContent, + pub signature: Vec, +} + +impl Manifest { + pub fn new(content: ManifestContent, signature: Vec) -> Self { + Manifest { content, signature } + } + + pub fn genesis(validators: Vec